Xuyi Wang / wolfSSL

Dependents:   OS

Files at this revision

API Documentation at this revision

Comitter:
sPymbed
Date:
Wed Nov 20 13:27:48 2019 +0000
Parent:
16:048e5e270a58
Commit message:
removed: wolfcrypt

Changed in this revision

src/crl.c Show annotated file Show diff for this revision Revisions of this file
src/internal.c Show annotated file Show diff for this revision Revisions of this file
src/keys.c Show annotated file Show diff for this revision Revisions of this file
src/ocsp.c Show annotated file Show diff for this revision Revisions of this file
src/sniffer.c Show annotated file Show diff for this revision Revisions of this file
src/ssl.c Show annotated file Show diff for this revision Revisions of this file
src/tls.c Show annotated file Show diff for this revision Revisions of this file
src/tls13.c Show annotated file Show diff for this revision Revisions of this file
src/wolfio.c Show annotated file Show diff for this revision Revisions of this file
wolfcrypt/src/aes.c Show diff for this revision Revisions of this file
wolfcrypt/src/arc4.c Show diff for this revision Revisions of this file
wolfcrypt/src/asm.c Show diff for this revision Revisions of this file
wolfcrypt/src/asn.c Show diff for this revision Revisions of this file
wolfcrypt/src/async.c Show diff for this revision Revisions of this file
wolfcrypt/src/blake2b.c Show diff for this revision Revisions of this file
wolfcrypt/src/camellia.c Show diff for this revision Revisions of this file
wolfcrypt/src/chacha.c Show diff for this revision Revisions of this file
wolfcrypt/src/chacha20_poly1305.c Show diff for this revision Revisions of this file
wolfcrypt/src/cmac.c Show diff for this revision Revisions of this file
wolfcrypt/src/coding.c Show diff for this revision Revisions of this file
wolfcrypt/src/compress.c Show diff for this revision Revisions of this file
wolfcrypt/src/cpuid.c Show diff for this revision Revisions of this file
wolfcrypt/src/cryptodev.c Show diff for this revision Revisions of this file
wolfcrypt/src/curve25519.c Show diff for this revision Revisions of this file
wolfcrypt/src/des3.c Show diff for this revision Revisions of this file
wolfcrypt/src/dh.c Show diff for this revision Revisions of this file
wolfcrypt/src/dsa.c Show diff for this revision Revisions of this file
wolfcrypt/src/ecc.c Show diff for this revision Revisions of this file
wolfcrypt/src/ecc_fp.c Show diff for this revision Revisions of this file
wolfcrypt/src/ed25519.c Show diff for this revision Revisions of this file
wolfcrypt/src/error.c Show diff for this revision Revisions of this file
wolfcrypt/src/evp.c Show diff for this revision Revisions of this file
wolfcrypt/src/fe_low_mem.c Show diff for this revision Revisions of this file
wolfcrypt/src/fe_operations.c Show diff for this revision Revisions of this file
wolfcrypt/src/ge_low_mem.c Show diff for this revision Revisions of this file
wolfcrypt/src/ge_operations.c Show diff for this revision Revisions of this file
wolfcrypt/src/hash.c Show diff for this revision Revisions of this file
wolfcrypt/src/hc128.c Show diff for this revision Revisions of this file
wolfcrypt/src/hmac.c Show diff for this revision Revisions of this file
wolfcrypt/src/idea.c Show diff for this revision Revisions of this file
wolfcrypt/src/integer.c Show diff for this revision Revisions of this file
wolfcrypt/src/logging.c Show diff for this revision Revisions of this file
wolfcrypt/src/md2.c Show diff for this revision Revisions of this file
wolfcrypt/src/md4.c Show diff for this revision Revisions of this file
wolfcrypt/src/md5.c Show diff for this revision Revisions of this file
wolfcrypt/src/memory.c Show diff for this revision Revisions of this file
wolfcrypt/src/misc.c Show diff for this revision Revisions of this file
wolfcrypt/src/pkcs12.c Show diff for this revision Revisions of this file
wolfcrypt/src/pkcs7.c Show diff for this revision Revisions of this file
wolfcrypt/src/poly1305.c Show diff for this revision Revisions of this file
wolfcrypt/src/pwdbased.c Show diff for this revision Revisions of this file
wolfcrypt/src/rabbit.c Show diff for this revision Revisions of this file
wolfcrypt/src/random.c Show diff for this revision Revisions of this file
wolfcrypt/src/ripemd.c Show diff for this revision Revisions of this file
wolfcrypt/src/rsa.c Show diff for this revision Revisions of this file
wolfcrypt/src/selftest.c Show diff for this revision Revisions of this file
wolfcrypt/src/sha.c Show diff for this revision Revisions of this file
wolfcrypt/src/sha256.c Show diff for this revision Revisions of this file
wolfcrypt/src/sha3.c Show diff for this revision Revisions of this file
wolfcrypt/src/sha512.c Show diff for this revision Revisions of this file
wolfcrypt/src/signature.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_arm32.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_arm64.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_c32.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_c64.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_int.c Show diff for this revision Revisions of this file
wolfcrypt/src/sp_x86_64.c Show diff for this revision Revisions of this file
wolfcrypt/src/srp.c Show diff for this revision Revisions of this file
wolfcrypt/src/tfm.c Show diff for this revision Revisions of this file
wolfcrypt/src/wc_encrypt.c Show diff for this revision Revisions of this file
wolfcrypt/src/wc_port.c Show diff for this revision Revisions of this file
wolfcrypt/src/wolfcrypt_first.c Show diff for this revision Revisions of this file
wolfcrypt/src/wolfcrypt_last.c Show diff for this revision Revisions of this file
wolfcrypt/src/wolfevent.c Show diff for this revision Revisions of this file
wolfcrypt/src/wolfmath.c Show diff for this revision Revisions of this file
wolfssl/error-ssl.h Show annotated file Show diff for this revision Revisions of this file
wolfssl/internal.h Show annotated file Show diff for this revision Revisions of this file
wolfssl/ssl.h Show annotated file Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/aes.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/arc4.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/asn.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/asn_public.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/async.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/blake2-impl.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/blake2-int.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/blake2.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/camellia.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/chacha.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/chacha20_poly1305.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/cmac.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/coding.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/compress.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/cpuid.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/cryptodev.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/curve25519.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/des3.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/dh.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/dsa.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/ecc.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/ed25519.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/error-crypt.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/fe_operations.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/fips.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/fips_test.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/ge_operations.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/hash.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/hc128.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/hmac.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/idea.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/integer.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/logging.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/md2.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/md4.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/md5.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/mem_track.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/memory.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/misc.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/mpi_class.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/mpi_superclass.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/pkcs12.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/pkcs7.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/poly1305.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/pwdbased.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/rabbit.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/random.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/ripemd.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/rsa.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/selftest.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/settings.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sha.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sha256.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sha3.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sha512.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/signature.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sp.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/sp_int.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/srp.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/tfm.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/types.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/visibility.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/wc_encrypt.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/wc_port.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/wolfevent.h Show diff for this revision Revisions of this file
wolfssl/wolfcrypt/wolfmath.h Show diff for this revision Revisions of this file
--- a/src/crl.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/crl.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,1098 +1,1098 @@
-/* crl.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-  /* Name change compatibility layer no longer needs included here */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-#ifdef HAVE_CRL
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-
-#include <string.h>
-
-#ifdef HAVE_CRL_MONITOR
-    #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
-        static int StopMonitor(int mfd);
-    #else
-        #error "CRL monitor only currently supported on linux or mach"
-    #endif
-#endif /* HAVE_CRL_MONITOR */
-
-
-/* Initialize CRL members */
-int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("InitCRL");
-    if(cm != NULL)
-        crl->heap = cm->heap;
-    else
-        crl->heap = NULL;
-    crl->cm = cm;
-    crl->crlList = NULL;
-    crl->monitors[0].path = NULL;
-    crl->monitors[1].path = NULL;
-#ifdef HAVE_CRL_MONITOR
-    crl->tid   =  0;
-    crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
-    crl->setup = 0;     /* thread setup done predicate */
-    if (pthread_cond_init(&crl->cond, 0) != 0) {
-        WOLFSSL_MSG("Pthread condition init failed");
-        return BAD_COND_E;
-    }
-#endif
-    if (wc_InitMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("Init Mutex failed");
-        return BAD_MUTEX_E;
-    }
-
-    return 0;
-}
-
-
-/* Initialize CRL Entry */
-static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
-                         int verified, void* heap)
-{
-    WOLFSSL_ENTER("InitCRL_Entry");
-
-    XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
-    /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
-     *   copy the hash here if needed for optimized comparisons */
-    XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
-    XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
-    crle->lastDateFormat = dcrl->lastDateFormat;
-    crle->nextDateFormat = dcrl->nextDateFormat;
-
-    crle->certs = dcrl->certs;   /* take ownsership */
-    dcrl->certs = NULL;
-    crle->totalCerts = dcrl->totalCerts;
-    crle->verified = verified;
-    if (!verified) {
-        crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
-        crle->signatureSz = dcrl->sigLength;
-        crle->signatureOID = dcrl->signatureOID;
-        crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
-                                          DYNAMIC_TYPE_CRL_ENTRY);
-        if (crle->toBeSigned == NULL)
-            return -1;
-        crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
-                                         DYNAMIC_TYPE_CRL_ENTRY);
-        if (crle->signature == NULL) {
-            XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
-            return -1;
-        }
-        XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
-        XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
-    #if !defined(NO_SKID) && defined(CRL_SKID_READY)
-        crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
-        if (crle->extAuthKeyIdSet)
-            XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
-    #endif
-    }
-    else {
-        crle->toBeSigned = NULL;
-        crle->signature = NULL;
-    }
-
-    (void)verified;
-
-    return 0;
-}
-
-
-/* Free all CRL Entry resources */
-static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
-{
-    RevokedCert* tmp = crle->certs;
-    RevokedCert* next;
-
-    WOLFSSL_ENTER("FreeCRL_Entry");
-
-    while (tmp) {
-        next = tmp->next;
-        XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
-        tmp = next;
-    }
-    if (crle->signature != NULL)
-        XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
-    if (crle->toBeSigned != NULL)
-        XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
-
-    (void)heap;
-}
-
-
-
-/* Free all CRL resources */
-void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
-{
-    CRL_Entry* tmp = crl->crlList;
-
-    WOLFSSL_ENTER("FreeCRL");
-    if (crl->monitors[0].path)
-        XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
-
-    if (crl->monitors[1].path)
-        XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
-
-    while(tmp) {
-        CRL_Entry* next = tmp->next;
-        FreeCRL_Entry(tmp, crl->heap);
-        XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-        tmp = next;
-    }
-
-#ifdef HAVE_CRL_MONITOR
-    if (crl->tid != 0) {
-        WOLFSSL_MSG("stopping monitor thread");
-        if (StopMonitor(crl->mfd) == 0)
-            pthread_join(crl->tid, NULL);
-        else {
-            WOLFSSL_MSG("stop monitor failed");
-        }
-    }
-    pthread_cond_destroy(&crl->cond);
-#endif
-    wc_FreeMutex(&crl->crlLock);
-    if (dynamic)   /* free self */
-        XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
-}
-
-
-static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
-{
-    CRL_Entry* crle;
-    int        foundEntry = 0;
-    int        ret = 0;
-
-    if (wc_LockMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex failed");
-        return BAD_MUTEX_E;
-    }
-
-    crle = crl->crlList;
-
-    while (crle) {
-        if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
-            int doNextDate = 1;
-
-            WOLFSSL_MSG("Found CRL Entry on list");
-
-            if (crle->verified == 0) {
-                Signer* ca;
-            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
-                byte extAuthKeyId[KEYID_SIZE]
-            #endif
-                byte issuerHash[CRL_DIGEST_SIZE];
-                byte* tbs = NULL;
-                word32 tbsSz = crle->tbsSz;
-                byte* sig = NULL;
-                word32 sigSz = crle->signatureSz;
-                word32 sigOID = crle->signatureOID;
-                SignatureCtx sigCtx;
-
-                tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                if (tbs == NULL) {
-                    wc_UnLockMutex(&crl->crlLock);
-                    return MEMORY_E;
-                }
-                sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                if (sig == NULL) {
-                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                    wc_UnLockMutex(&crl->crlLock);
-                    return MEMORY_E;
-                }
-
-                XMEMCPY(tbs, crle->toBeSigned, tbsSz);
-                XMEMCPY(sig, crle->signature, sigSz);
-            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
-                XMEMCMPY(extAuthKeyId, crle->extAuthKeyId,
-                                                          sizeof(extAuthKeyId));
-            #endif
-                XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
-
-                wc_UnLockMutex(&crl->crlLock);
-
-            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
-                if (crle->extAuthKeyIdSet)
-                    ca = GetCA(crl->cm, extAuthKeyId);
-                if (ca == NULL)
-                    ca = GetCAByName(crl->cm, issuerHash);
-            #else /* NO_SKID */
-                ca = GetCA(crl->cm, issuerHash);
-            #endif /* NO_SKID */
-                if (ca == NULL) {
-                    XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                    WOLFSSL_MSG("Did NOT find CRL issuer CA");
-                    return ASN_CRL_NO_SIGNER_E;
-                }
-
-                ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
-                                          sigOID, ca, crl->heap);
-
-                XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-                XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-
-                if (wc_LockMutex(&crl->crlLock) != 0) {
-                    WOLFSSL_MSG("wc_LockMutex failed");
-                    return BAD_MUTEX_E;
-                }
-
-                crle = crl->crlList;
-                while (crle) {
-                    if (XMEMCMP(crle->issuerHash, cert->issuerHash,
-                        CRL_DIGEST_SIZE) == 0) {
-
-                        if (ret == 0)
-                            crle->verified = 1;
-                        else
-                            crle->verified = ret;
-
-                        XFREE(crle->toBeSigned, crl->heap,
-                                                        DYNAMIC_TYPE_CRL_ENTRY);
-                        crle->toBeSigned = NULL;
-                        XFREE(crle->signature, crl->heap,
-                                                        DYNAMIC_TYPE_CRL_ENTRY);
-                        crle->signature = NULL;
-                        break;
-                    }
-                    crle = crle->next;
-                }
-                if (crle == NULL || crle->verified < 0)
-                    break;
-            }
-            else if (crle->verified < 0) {
-                WOLFSSL_MSG("Cannot use CRL as it didn't verify");
-                ret = crle->verified;
-                break;
-            }
-
-            WOLFSSL_MSG("Checking next date validity");
-
-            #ifdef WOLFSSL_NO_CRL_NEXT_DATE
-                if (crle->nextDateFormat == ASN_OTHER_TYPE)
-                    doNextDate = 0;  /* skip */
-            #endif
-
-            if (doNextDate) {
-            #ifndef NO_ASN_TIME
-                if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) {
-                    WOLFSSL_MSG("CRL next date is no longer valid");
-                    ret = ASN_AFTER_DATE_E;
-                }
-            #endif
-            }
-            if (ret == 0) {
-                foundEntry = 1;
-            }
-            break;
-        }
-        crle = crle->next;
-    }
-
-    if (foundEntry) {
-        RevokedCert* rc = crle->certs;
-
-        while (rc) {
-            if (rc->serialSz == cert->serialSz &&
-                   XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
-                WOLFSSL_MSG("Cert revoked");
-                ret = CRL_CERT_REVOKED;
-                break;
-            }
-            rc = rc->next;
-        }
-    }
-
-    wc_UnLockMutex(&crl->crlLock);
-
-    *pFoundEntry = foundEntry;
-
-    return ret;
-}
-
-/* Is the cert ok with CRL, return 0 on success */
-int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
-{
-    int        foundEntry = 0;
-    int        ret = 0;
-
-    WOLFSSL_ENTER("CheckCertCRL");
-
-    ret = CheckCertCRLList(crl, cert, &foundEntry);
-
-#ifdef HAVE_CRL_IO
-    if (foundEntry == 0) {
-        /* perform embedded lookup */
-        if (crl->crlIOCb) {
-            ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
-                                                        cert->extCrlInfoSz);
-            if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
-                ret = WANT_READ;
-            }
-            else if (ret >= 0) {
-                /* try again */
-                ret = CheckCertCRLList(crl, cert, &foundEntry);
-            }
-        }
-    }
-#endif
-
-    if (foundEntry == 0) {
-        WOLFSSL_MSG("Couldn't find CRL for status check");
-        ret = CRL_MISSING;
-
-        if (crl->cm->cbMissingCRL) {
-            char url[256];
-
-            WOLFSSL_MSG("Issuing missing CRL callback");
-            url[0] = '\0';
-            if (cert->extCrlInfo) {
-                if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
-                    XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
-                    url[cert->extCrlInfoSz] = '\0';
-                }
-                else  {
-                    WOLFSSL_MSG("CRL url too long");
-                }
-            }
-
-            crl->cm->cbMissingCRL(url);
-        }
-    }
-
-    return ret;
-}
-
-
-/* Add Decoded CRL, 0 on success */
-static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
-                  int verified)
-{
-    CRL_Entry* crle;
-
-    WOLFSSL_ENTER("AddCRL");
-
-    crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-    if (crle == NULL) {
-        WOLFSSL_MSG("alloc CRL Entry failed");
-        return -1;
-    }
-
-    if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
-        WOLFSSL_MSG("Init CRL Entry failed");
-        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-        return -1;
-    }
-
-    if (wc_LockMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex failed");
-        FreeCRL_Entry(crle, crl->heap);
-        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-        return BAD_MUTEX_E;
-    }
-    crle->next = crl->crlList;
-    crl->crlList = crle;
-    wc_UnLockMutex(&crl->crlLock);
-
-    return 0;
-}
-
-
-/* Load CRL File of type, WOLFSSL_SUCCESS on ok */
-int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
-                  int noVerify)
-{
-    int          ret = WOLFSSL_SUCCESS;
-    const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
-    DerBuffer*   der = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCRL*  dcrl;
-#else
-    DecodedCRL   dcrl[1];
-#endif
-
-    WOLFSSL_ENTER("BufferLoadCRL");
-
-    if (crl == NULL || buff == NULL || sz == 0)
-        return BAD_FUNC_ARG;
-
-    if (type == WOLFSSL_FILETYPE_PEM) {
-    #ifdef WOLFSSL_PEM_TO_DER
-        ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
-        if (ret == 0) {
-            myBuffer = der->buffer;
-            sz = der->length;
-        }
-        else {
-            WOLFSSL_MSG("Pem to Der failed");
-            FreeDer(&der);
-            return -1;
-        }
-    #else
-        ret = NOT_COMPILED_IN;
-    #endif
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (dcrl == NULL) {
-        FreeDer(&der);
-        return MEMORY_E;
-    }
-#endif
-
-    InitDecodedCRL(dcrl, crl->heap);
-    ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
-    if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) {
-        WOLFSSL_MSG("ParseCRL error");
-    }
-    else {
-        ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
-        if (ret != 0) {
-            WOLFSSL_MSG("AddCRL error");
-        }
-    }
-
-    FreeDecodedCRL(dcrl);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    FreeDer(&der);
-
-    return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
-}
-
-#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
-int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
-{
-    CRL_Entry   *crle;
-    WOLFSSL_CRL *crl;
-
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
-    if (store == NULL || newcrl == NULL)
-        return BAD_FUNC_ARG;
-
-    crl = store->crl;
-    crle = newcrl->crlList;
-
-    if (wc_LockMutex(&crl->crlLock) != 0)
-    {
-        WOLFSSL_MSG("wc_LockMutex failed");
-        return BAD_MUTEX_E;
-    }
-    crle->next = crl->crlList;
-    crl->crlList = crle;
-    newcrl->crlList = NULL;
-    wc_UnLockMutex(&crl->crlLock);
-
-    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
-    
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-#ifdef HAVE_CRL_MONITOR
-
-
-/* Signal Monitor thread is setup, save status to setup flag, 0 on success */
-static int SignalSetup(WOLFSSL_CRL* crl, int status)
-{
-    int ret;
-
-    /* signal to calling thread we're setup */
-    if (wc_LockMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex crlLock failed");
-        return BAD_MUTEX_E;
-    }
-
-        crl->setup = status;
-        ret = pthread_cond_signal(&crl->cond);
-
-    wc_UnLockMutex(&crl->crlLock);
-
-    if (ret != 0)
-        return BAD_COND_E;
-
-    return 0;
-}
-
-
-/* read in new CRL entries and save new list */
-static int SwapLists(WOLFSSL_CRL* crl)
-{
-    int        ret;
-    CRL_Entry* newList;
-#ifdef WOLFSSL_SMALL_STACK
-    WOLFSSL_CRL* tmp;
-#else
-    WOLFSSL_CRL tmp[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (tmp == NULL)
-        return MEMORY_E;
-#endif
-
-    if (InitCRL(tmp, crl->cm) < 0) {
-        WOLFSSL_MSG("Init tmp CRL failed");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return -1;
-    }
-
-    if (crl->monitors[0].path) {
-        ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("PEM LoadCRL on dir change failed");
-            FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return -1;
-        }
-    }
-
-    if (crl->monitors[1].path) {
-        ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("DER LoadCRL on dir change failed");
-            FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return -1;
-        }
-    }
-
-    if (wc_LockMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex failed");
-        FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return -1;
-    }
-
-    newList = tmp->crlList;
-
-    /* swap lists */
-    tmp->crlList  = crl->crlList;
-    crl->crlList = newList;
-
-    wc_UnLockMutex(&crl->crlLock);
-
-    FreeCRL(tmp, 0);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-
-#if (defined(__MACH__) || defined(__FreeBSD__))
-
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#ifdef __MACH__
-    #define XEVENT_MODE O_EVTONLY
-#elif defined(__FreeBSD__)
-    #define XEVENT_MODE EVFILT_VNODE
-#endif
-
-
-/* we need a unique kqueue user filter fd for crl in case user is doing custom
- * events too */
-#ifndef CRL_CUSTOM_FD
-    #define CRL_CUSTOM_FD 123456
-#endif
-
-
-/* shutdown monitor thread, 0 on success */
-static int StopMonitor(int mfd)
-{
-    struct kevent change;
-
-    /* trigger custom shutdown */
-    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
-    if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
-        WOLFSSL_MSG("kevent trigger customer event failed");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/* OS X  monitoring */
-static void* DoMonitor(void* arg)
-{
-    int fPEM, fDER;
-    struct kevent change;
-
-    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
-
-    WOLFSSL_ENTER("DoMonitor");
-
-    crl->mfd = kqueue();
-    if (crl->mfd == -1) {
-        WOLFSSL_MSG("kqueue failed");
-        SignalSetup(crl, MONITOR_SETUP_E);
-        return NULL;
-    }
-
-    /* listen for custom shutdown event */
-    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
-    if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
-        WOLFSSL_MSG("kevent monitor customer event failed");
-        SignalSetup(crl, MONITOR_SETUP_E);
-        close(crl->mfd);
-        return NULL;
-    }
-
-    fPEM = -1;
-    fDER = -1;
-
-    if (crl->monitors[0].path) {
-        fPEM = open(crl->monitors[0].path, XEVENT_MODE);
-        if (fPEM == -1) {
-            WOLFSSL_MSG("PEM event dir open failed");
-            SignalSetup(crl, MONITOR_SETUP_E);
-            close(crl->mfd);
-            return NULL;
-        }
-    }
-
-    if (crl->monitors[1].path) {
-        fDER = open(crl->monitors[1].path, XEVENT_MODE);
-        if (fDER == -1) {
-            WOLFSSL_MSG("DER event dir open failed");
-            if (fPEM != -1)
-                close(fPEM);
-            close(crl->mfd);
-            SignalSetup(crl, MONITOR_SETUP_E);
-            return NULL;
-        }
-    }
-
-    if (fPEM != -1)
-        EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
-                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
-
-    if (fDER != -1)
-        EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
-                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
-
-    /* signal to calling thread we're setup */
-    if (SignalSetup(crl, 1) != 0) {
-        if (fPEM != -1)
-            close(fPEM);
-        if (fDER != -1)
-            close(fDER);
-        close(crl->mfd);
-        return NULL;
-    }
-
-    for (;;) {
-        struct kevent event;
-        int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
-
-        WOLFSSL_MSG("Got kevent");
-
-        if (numEvents == -1) {
-            WOLFSSL_MSG("kevent problem, continue");
-            continue;
-        }
-
-        if (event.filter == EVFILT_USER) {
-            WOLFSSL_MSG("Got user shutdown event, breaking out");
-            break;
-        }
-
-        if (SwapLists(crl) < 0) {
-            WOLFSSL_MSG("SwapLists problem, continue");
-        }
-    }
-
-    if (fPEM != -1)
-        close(fPEM);
-    if (fDER != -1)
-        close(fDER);
-
-    close(crl->mfd);
-
-    return NULL;
-}
-
-
-#elif defined(__linux__)
-
-#include <sys/types.h>
-#include <sys/inotify.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-
-#ifndef max
-    static WC_INLINE int max(int a, int b)
-    {
-        return a > b ? a : b;
-    }
-#endif /* max */
-
-
-/* shutdown monitor thread, 0 on success */
-static int StopMonitor(int mfd)
-{
-    word64 w64 = 1;
-
-    /* write to our custom event */
-    if (write(mfd, &w64, sizeof(w64)) < 0) {
-        WOLFSSL_MSG("StopMonitor write failed");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/* linux monitoring */
-static void* DoMonitor(void* arg)
-{
-    int         notifyFd;
-    int         wd  = -1;
-    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
-#ifdef WOLFSSL_SMALL_STACK
-    char*       buff;
-#else
-    char        buff[8192];
-#endif
-
-    WOLFSSL_ENTER("DoMonitor");
-
-    crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
-    if (crl->mfd < 0) {
-        WOLFSSL_MSG("eventfd failed");
-        SignalSetup(crl, MONITOR_SETUP_E);
-        return NULL;
-    }
-
-    notifyFd = inotify_init();
-    if (notifyFd < 0) {
-        WOLFSSL_MSG("inotify failed");
-        close(crl->mfd);
-        SignalSetup(crl, MONITOR_SETUP_E);
-        return NULL;
-    }
-
-    if (crl->monitors[0].path) {
-        wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
-                                                                IN_DELETE);
-        if (wd < 0) {
-            WOLFSSL_MSG("PEM notify add watch failed");
-            close(crl->mfd);
-            close(notifyFd);
-            SignalSetup(crl, MONITOR_SETUP_E);
-            return NULL;
-        }
-    }
-
-    if (crl->monitors[1].path) {
-        wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
-                                                                IN_DELETE);
-        if (wd < 0) {
-            WOLFSSL_MSG("DER notify add watch failed");
-            close(crl->mfd);
-            close(notifyFd);
-            SignalSetup(crl, MONITOR_SETUP_E);
-            return NULL;
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buff == NULL)
-        return NULL;
-#endif
-
-    /* signal to calling thread we're setup */
-    if (SignalSetup(crl, 1) != 0) {
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-
-        if (wd > 0)
-            inotify_rm_watch(notifyFd, wd);
-        close(crl->mfd);
-        close(notifyFd);
-        return NULL;
-    }
-
-    for (;;) {
-        fd_set readfds;
-        int    result;
-        int    length;
-
-        FD_ZERO(&readfds);
-        FD_SET(notifyFd, &readfds);
-        FD_SET(crl->mfd, &readfds);
-
-        result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
-
-        WOLFSSL_MSG("Got notify event");
-
-        if (result < 0) {
-            WOLFSSL_MSG("select problem, continue");
-            continue;
-        }
-
-        if (FD_ISSET(crl->mfd, &readfds)) {
-            WOLFSSL_MSG("got custom shutdown event, breaking out");
-            break;
-        }
-
-        length = (int) read(notifyFd, buff, 8192);
-        if (length < 0) {
-            WOLFSSL_MSG("notify read problem, continue");
-            continue;
-        }
-
-        if (SwapLists(crl) < 0) {
-            WOLFSSL_MSG("SwapLists problem, continue");
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (wd > 0)
-        inotify_rm_watch(notifyFd, wd);
-    close(crl->mfd);
-    close(notifyFd);
-
-    return NULL;
-}
-
-#endif /* MACH or linux */
-
-
-/* Start Monitoring the CRL path(s) in a thread */
-static int StartMonitorCRL(WOLFSSL_CRL* crl)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("StartMonitorCRL");
-
-    if (crl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (crl->tid != 0) {
-        WOLFSSL_MSG("Monitor thread already running");
-        return ret;  /* that's ok, someone already started */
-    }
-
-    if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
-        WOLFSSL_MSG("Thread creation error");
-        return THREAD_CREATE_E;
-    }
-
-    /* wait for setup to complete */
-    if (wc_LockMutex(&crl->crlLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex crlLock error");
-        return BAD_MUTEX_E;
-    }
-
-        while (crl->setup == 0) {
-            if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
-                ret = BAD_COND_E;
-                break;
-            }
-        }
-
-        if (crl->setup < 0)
-            ret = crl->setup;  /* store setup error */
-
-    wc_UnLockMutex(&crl->crlLock);
-
-    if (ret < 0) {
-        WOLFSSL_MSG("DoMonitor setup failure");
-        crl->tid = 0;  /* thread already done */
-    }
-
-    return ret;
-}
-
-
-#else /* HAVE_CRL_MONITOR */
-
-#ifndef NO_FILESYSTEM
-
-static int StartMonitorCRL(WOLFSSL_CRL* crl)
-{
-    (void)crl;
-
-    WOLFSSL_ENTER("StartMonitorCRL");
-    WOLFSSL_MSG("Not compiled in");
-
-    return NOT_COMPILED_IN;
-}
-
-#endif /* NO_FILESYSTEM */
-
-#endif  /* HAVE_CRL_MONITOR */
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
-
-/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
-int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
-{
-    int         ret = WOLFSSL_SUCCESS;
-    char*       name = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    ReadDirCtx* readCtx = NULL;
-#else
-    ReadDirCtx  readCtx[1];
-#endif
-
-    WOLFSSL_ENTER("LoadCRL");
-    if (crl == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (readCtx == NULL)
-        return MEMORY_E;
-#endif
-
-    /* try to load each regular file in path */
-    ret = wc_ReadDirFirst(readCtx, path, &name);
-    while (ret == 0 && name) {
-        int skip = 0;
-        if (type == WOLFSSL_FILETYPE_PEM) {
-            if (XSTRSTR(name, ".pem") == NULL) {
-                WOLFSSL_MSG("not .pem file, skipping");
-                skip = 1;
-            }
-        }
-        else {
-            if (XSTRSTR(name, ".der") == NULL &&
-                XSTRSTR(name, ".crl") == NULL)
-            {
-                WOLFSSL_MSG("not .der or .crl file, skipping");
-                skip = 1;
-            }
-        }
-
-        if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
-                                                           != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("CRL file load failed, continuing");
-        }
-
-        ret = wc_ReadDirNext(readCtx, path, &name);
-    }
-    wc_ReadDirClose(readCtx);
-    ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (monitor & WOLFSSL_CRL_MONITOR) {
-        word32 pathLen;
-        char* pathBuf;
-
-        WOLFSSL_MSG("monitor path requested");
-
-        pathLen = (word32)XSTRLEN(path);
-        pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
-        if (pathBuf) {
-            XSTRNCPY(pathBuf, path, pathLen);
-            pathBuf[pathLen] = '\0'; /* Null Terminate */
-
-            if (type == WOLFSSL_FILETYPE_PEM) {
-                /* free old path before setting a new one */
-                if (crl->monitors[0].path) {
-                    XFREE(crl->monitors[0].path, crl->heap,
-                            DYNAMIC_TYPE_CRL_MONITOR);
-                }
-                crl->monitors[0].path = pathBuf;
-                crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
-            } else {
-                /* free old path before setting a new one */
-                if (crl->monitors[1].path) {
-                    XFREE(crl->monitors[1].path, crl->heap,
-                            DYNAMIC_TYPE_CRL_MONITOR);
-                }
-                crl->monitors[1].path = pathBuf;
-                crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
-            }
-
-            if (monitor & WOLFSSL_CRL_START_MON) {
-                WOLFSSL_MSG("start monitoring requested");
-
-                ret = StartMonitorCRL(crl);
-            }
-        }
-        else {
-            ret = MEMORY_E;
-        }
-    }
-
-    return ret;
-}
-
-#else
-int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
-{
-	(void)crl;
-	(void)path;
-	(void)type;
-	(void)monitor;
-
-    /* stub for scenario where file system is not supported */
-    return NOT_COMPILED_IN;
-}
-#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
-
-#endif /* HAVE_CRL */
-#endif /* !WOLFCRYPT_ONLY */
+/* crl.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+  /* Name change compatibility layer no longer needs included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef HAVE_CRL
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+
+#include <string.h>
+
+#ifdef HAVE_CRL_MONITOR
+    #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
+        static int StopMonitor(int mfd);
+    #else
+        #error "CRL monitor only currently supported on linux or mach"
+    #endif
+#endif /* HAVE_CRL_MONITOR */
+
+
+/* Initialize CRL members */
+int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("InitCRL");
+    if(cm != NULL)
+        crl->heap = cm->heap;
+    else
+        crl->heap = NULL;
+    crl->cm = cm;
+    crl->crlList = NULL;
+    crl->monitors[0].path = NULL;
+    crl->monitors[1].path = NULL;
+#ifdef HAVE_CRL_MONITOR
+    crl->tid   =  0;
+    crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
+    crl->setup = 0;     /* thread setup done predicate */
+    if (pthread_cond_init(&crl->cond, 0) != 0) {
+        WOLFSSL_MSG("Pthread condition init failed");
+        return BAD_COND_E;
+    }
+#endif
+    if (wc_InitMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("Init Mutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    return 0;
+}
+
+
+/* Initialize CRL Entry */
+static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
+                         int verified, void* heap)
+{
+    WOLFSSL_ENTER("InitCRL_Entry");
+
+    XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
+    /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
+     *   copy the hash here if needed for optimized comparisons */
+    XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
+    XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
+    crle->lastDateFormat = dcrl->lastDateFormat;
+    crle->nextDateFormat = dcrl->nextDateFormat;
+
+    crle->certs = dcrl->certs;   /* take ownsership */
+    dcrl->certs = NULL;
+    crle->totalCerts = dcrl->totalCerts;
+    crle->verified = verified;
+    if (!verified) {
+        crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
+        crle->signatureSz = dcrl->sigLength;
+        crle->signatureOID = dcrl->signatureOID;
+        crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
+                                          DYNAMIC_TYPE_CRL_ENTRY);
+        if (crle->toBeSigned == NULL)
+            return -1;
+        crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
+                                         DYNAMIC_TYPE_CRL_ENTRY);
+        if (crle->signature == NULL) {
+            XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
+            return -1;
+        }
+        XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
+        XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
+    #if !defined(NO_SKID) && defined(CRL_SKID_READY)
+        crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
+        if (crle->extAuthKeyIdSet)
+            XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
+    #endif
+    }
+    else {
+        crle->toBeSigned = NULL;
+        crle->signature = NULL;
+    }
+
+    (void)verified;
+
+    return 0;
+}
+
+
+/* Free all CRL Entry resources */
+static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
+{
+    RevokedCert* tmp = crle->certs;
+    RevokedCert* next;
+
+    WOLFSSL_ENTER("FreeCRL_Entry");
+
+    while (tmp) {
+        next = tmp->next;
+        XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
+        tmp = next;
+    }
+    if (crle->signature != NULL)
+        XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
+    if (crle->toBeSigned != NULL)
+        XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
+
+    (void)heap;
+}
+
+
+
+/* Free all CRL resources */
+void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
+{
+    CRL_Entry* tmp = crl->crlList;
+
+    WOLFSSL_ENTER("FreeCRL");
+    if (crl->monitors[0].path)
+        XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
+
+    if (crl->monitors[1].path)
+        XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
+
+    while(tmp) {
+        CRL_Entry* next = tmp->next;
+        FreeCRL_Entry(tmp, crl->heap);
+        XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        tmp = next;
+    }
+
+#ifdef HAVE_CRL_MONITOR
+    if (crl->tid != 0) {
+        WOLFSSL_MSG("stopping monitor thread");
+        if (StopMonitor(crl->mfd) == 0)
+            pthread_join(crl->tid, NULL);
+        else {
+            WOLFSSL_MSG("stop monitor failed");
+        }
+    }
+    pthread_cond_destroy(&crl->cond);
+#endif
+    wc_FreeMutex(&crl->crlLock);
+    if (dynamic)   /* free self */
+        XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
+}
+
+
+static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
+{
+    CRL_Entry* crle;
+    int        foundEntry = 0;
+    int        ret = 0;
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        return BAD_MUTEX_E;
+    }
+
+    crle = crl->crlList;
+
+    while (crle) {
+        if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
+            int doNextDate = 1;
+
+            WOLFSSL_MSG("Found CRL Entry on list");
+
+            if (crle->verified == 0) {
+                Signer* ca;
+            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
+                byte extAuthKeyId[KEYID_SIZE]
+            #endif
+                byte issuerHash[CRL_DIGEST_SIZE];
+                byte* tbs = NULL;
+                word32 tbsSz = crle->tbsSz;
+                byte* sig = NULL;
+                word32 sigSz = crle->signatureSz;
+                word32 sigOID = crle->signatureOID;
+                SignatureCtx sigCtx;
+
+                tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                if (tbs == NULL) {
+                    wc_UnLockMutex(&crl->crlLock);
+                    return MEMORY_E;
+                }
+                sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                if (sig == NULL) {
+                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    wc_UnLockMutex(&crl->crlLock);
+                    return MEMORY_E;
+                }
+
+                XMEMCPY(tbs, crle->toBeSigned, tbsSz);
+                XMEMCPY(sig, crle->signature, sigSz);
+            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
+                XMEMCMPY(extAuthKeyId, crle->extAuthKeyId,
+                                                          sizeof(extAuthKeyId));
+            #endif
+                XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
+
+                wc_UnLockMutex(&crl->crlLock);
+
+            #if !defined(NO_SKID) && defined(CRL_SKID_READY)
+                if (crle->extAuthKeyIdSet)
+                    ca = GetCA(crl->cm, extAuthKeyId);
+                if (ca == NULL)
+                    ca = GetCAByName(crl->cm, issuerHash);
+            #else /* NO_SKID */
+                ca = GetCA(crl->cm, issuerHash);
+            #endif /* NO_SKID */
+                if (ca == NULL) {
+                    XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                    WOLFSSL_MSG("Did NOT find CRL issuer CA");
+                    return ASN_CRL_NO_SIGNER_E;
+                }
+
+                ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
+                                          sigOID, ca, crl->heap);
+
+                XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+                XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+
+                if (wc_LockMutex(&crl->crlLock) != 0) {
+                    WOLFSSL_MSG("wc_LockMutex failed");
+                    return BAD_MUTEX_E;
+                }
+
+                crle = crl->crlList;
+                while (crle) {
+                    if (XMEMCMP(crle->issuerHash, cert->issuerHash,
+                        CRL_DIGEST_SIZE) == 0) {
+
+                        if (ret == 0)
+                            crle->verified = 1;
+                        else
+                            crle->verified = ret;
+
+                        XFREE(crle->toBeSigned, crl->heap,
+                                                        DYNAMIC_TYPE_CRL_ENTRY);
+                        crle->toBeSigned = NULL;
+                        XFREE(crle->signature, crl->heap,
+                                                        DYNAMIC_TYPE_CRL_ENTRY);
+                        crle->signature = NULL;
+                        break;
+                    }
+                    crle = crle->next;
+                }
+                if (crle == NULL || crle->verified < 0)
+                    break;
+            }
+            else if (crle->verified < 0) {
+                WOLFSSL_MSG("Cannot use CRL as it didn't verify");
+                ret = crle->verified;
+                break;
+            }
+
+            WOLFSSL_MSG("Checking next date validity");
+
+            #ifdef WOLFSSL_NO_CRL_NEXT_DATE
+                if (crle->nextDateFormat == ASN_OTHER_TYPE)
+                    doNextDate = 0;  /* skip */
+            #endif
+
+            if (doNextDate) {
+            #ifndef NO_ASN_TIME
+                if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) {
+                    WOLFSSL_MSG("CRL next date is no longer valid");
+                    ret = ASN_AFTER_DATE_E;
+                }
+            #endif
+            }
+            if (ret == 0) {
+                foundEntry = 1;
+            }
+            break;
+        }
+        crle = crle->next;
+    }
+
+    if (foundEntry) {
+        RevokedCert* rc = crle->certs;
+
+        while (rc) {
+            if (rc->serialSz == cert->serialSz &&
+                   XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
+                WOLFSSL_MSG("Cert revoked");
+                ret = CRL_CERT_REVOKED;
+                break;
+            }
+            rc = rc->next;
+        }
+    }
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    *pFoundEntry = foundEntry;
+
+    return ret;
+}
+
+/* Is the cert ok with CRL, return 0 on success */
+int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
+{
+    int        foundEntry = 0;
+    int        ret = 0;
+
+    WOLFSSL_ENTER("CheckCertCRL");
+
+    ret = CheckCertCRLList(crl, cert, &foundEntry);
+
+#ifdef HAVE_CRL_IO
+    if (foundEntry == 0) {
+        /* perform embedded lookup */
+        if (crl->crlIOCb) {
+            ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
+                                                        cert->extCrlInfoSz);
+            if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
+                ret = WANT_READ;
+            }
+            else if (ret >= 0) {
+                /* try again */
+                ret = CheckCertCRLList(crl, cert, &foundEntry);
+            }
+        }
+    }
+#endif
+
+    if (foundEntry == 0) {
+        WOLFSSL_MSG("Couldn't find CRL for status check");
+        ret = CRL_MISSING;
+
+        if (crl->cm->cbMissingCRL) {
+            char url[256];
+
+            WOLFSSL_MSG("Issuing missing CRL callback");
+            url[0] = '\0';
+            if (cert->extCrlInfo) {
+                if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
+                    XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
+                    url[cert->extCrlInfoSz] = '\0';
+                }
+                else  {
+                    WOLFSSL_MSG("CRL url too long");
+                }
+            }
+
+            crl->cm->cbMissingCRL(url);
+        }
+    }
+
+    return ret;
+}
+
+
+/* Add Decoded CRL, 0 on success */
+static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
+                  int verified)
+{
+    CRL_Entry* crle;
+
+    WOLFSSL_ENTER("AddCRL");
+
+    crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+    if (crle == NULL) {
+        WOLFSSL_MSG("alloc CRL Entry failed");
+        return -1;
+    }
+
+    if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
+        WOLFSSL_MSG("Init CRL Entry failed");
+        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        return -1;
+    }
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        FreeCRL_Entry(crle, crl->heap);
+        XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        return BAD_MUTEX_E;
+    }
+    crle->next = crl->crlList;
+    crl->crlList = crle;
+    wc_UnLockMutex(&crl->crlLock);
+
+    return 0;
+}
+
+
+/* Load CRL File of type, WOLFSSL_SUCCESS on ok */
+int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
+                  int noVerify)
+{
+    int          ret = WOLFSSL_SUCCESS;
+    const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
+    DerBuffer*   der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCRL*  dcrl;
+#else
+    DecodedCRL   dcrl[1];
+#endif
+
+    WOLFSSL_ENTER("BufferLoadCRL");
+
+    if (crl == NULL || buff == NULL || sz == 0)
+        return BAD_FUNC_ARG;
+
+    if (type == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
+        if (ret == 0) {
+            myBuffer = der->buffer;
+            sz = der->length;
+        }
+        else {
+            WOLFSSL_MSG("Pem to Der failed");
+            FreeDer(&der);
+            return -1;
+        }
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (dcrl == NULL) {
+        FreeDer(&der);
+        return MEMORY_E;
+    }
+#endif
+
+    InitDecodedCRL(dcrl, crl->heap);
+    ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
+    if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) {
+        WOLFSSL_MSG("ParseCRL error");
+    }
+    else {
+        ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
+        if (ret != 0) {
+            WOLFSSL_MSG("AddCRL error");
+        }
+    }
+
+    FreeDecodedCRL(dcrl);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    FreeDer(&der);
+
+    return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
+}
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
+int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
+{
+    CRL_Entry   *crle;
+    WOLFSSL_CRL *crl;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
+    if (store == NULL || newcrl == NULL)
+        return BAD_FUNC_ARG;
+
+    crl = store->crl;
+    crle = newcrl->crlList;
+
+    if (wc_LockMutex(&crl->crlLock) != 0)
+    {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        return BAD_MUTEX_E;
+    }
+    crle->next = crl->crlList;
+    crl->crlList = crle;
+    newcrl->crlList = NULL;
+    wc_UnLockMutex(&crl->crlLock);
+
+    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
+    
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef HAVE_CRL_MONITOR
+
+
+/* Signal Monitor thread is setup, save status to setup flag, 0 on success */
+static int SignalSetup(WOLFSSL_CRL* crl, int status)
+{
+    int ret;
+
+    /* signal to calling thread we're setup */
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex crlLock failed");
+        return BAD_MUTEX_E;
+    }
+
+        crl->setup = status;
+        ret = pthread_cond_signal(&crl->cond);
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    if (ret != 0)
+        return BAD_COND_E;
+
+    return 0;
+}
+
 
+/* read in new CRL entries and save new list */
+static int SwapLists(WOLFSSL_CRL* crl)
+{
+    int        ret;
+    CRL_Entry* newList;
+#ifdef WOLFSSL_SMALL_STACK
+    WOLFSSL_CRL* tmp;
+#else
+    WOLFSSL_CRL tmp[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmp == NULL)
+        return MEMORY_E;
+#endif
+
+    if (InitCRL(tmp, crl->cm) < 0) {
+        WOLFSSL_MSG("Init tmp CRL failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return -1;
+    }
+
+    if (crl->monitors[0].path) {
+        ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("PEM LoadCRL on dir change failed");
+            FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return -1;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("DER LoadCRL on dir change failed");
+            FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+            XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+            return -1;
+        }
+    }
+
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex failed");
+        FreeCRL(tmp, 0);
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        return -1;
+    }
+
+    newList = tmp->crlList;
+
+    /* swap lists */
+    tmp->crlList  = crl->crlList;
+    crl->crlList = newList;
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    FreeCRL(tmp, 0);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return 0;
+}
+
+
+#if (defined(__MACH__) || defined(__FreeBSD__))
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef __MACH__
+    #define XEVENT_MODE O_EVTONLY
+#elif defined(__FreeBSD__)
+    #define XEVENT_MODE EVFILT_VNODE
+#endif
+
+
+/* we need a unique kqueue user filter fd for crl in case user is doing custom
+ * events too */
+#ifndef CRL_CUSTOM_FD
+    #define CRL_CUSTOM_FD 123456
+#endif
+
+
+/* shutdown monitor thread, 0 on success */
+static int StopMonitor(int mfd)
+{
+    struct kevent change;
+
+    /* trigger custom shutdown */
+    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
+    if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
+        WOLFSSL_MSG("kevent trigger customer event failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* OS X  monitoring */
+static void* DoMonitor(void* arg)
+{
+    int fPEM, fDER;
+    struct kevent change;
+
+    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
+
+    WOLFSSL_ENTER("DoMonitor");
+
+    crl->mfd = kqueue();
+    if (crl->mfd == -1) {
+        WOLFSSL_MSG("kqueue failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    /* listen for custom shutdown event */
+    EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
+    if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
+        WOLFSSL_MSG("kevent monitor customer event failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        close(crl->mfd);
+        return NULL;
+    }
+
+    fPEM = -1;
+    fDER = -1;
+
+    if (crl->monitors[0].path) {
+        fPEM = open(crl->monitors[0].path, XEVENT_MODE);
+        if (fPEM == -1) {
+            WOLFSSL_MSG("PEM event dir open failed");
+            SignalSetup(crl, MONITOR_SETUP_E);
+            close(crl->mfd);
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        fDER = open(crl->monitors[1].path, XEVENT_MODE);
+        if (fDER == -1) {
+            WOLFSSL_MSG("DER event dir open failed");
+            if (fPEM != -1)
+                close(fPEM);
+            close(crl->mfd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+    if (fPEM != -1)
+        EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    if (fDER != -1)
+        EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    /* signal to calling thread we're setup */
+    if (SignalSetup(crl, 1) != 0) {
+        if (fPEM != -1)
+            close(fPEM);
+        if (fDER != -1)
+            close(fDER);
+        close(crl->mfd);
+        return NULL;
+    }
+
+    for (;;) {
+        struct kevent event;
+        int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
+
+        WOLFSSL_MSG("Got kevent");
+
+        if (numEvents == -1) {
+            WOLFSSL_MSG("kevent problem, continue");
+            continue;
+        }
+
+        if (event.filter == EVFILT_USER) {
+            WOLFSSL_MSG("Got user shutdown event, breaking out");
+            break;
+        }
+
+        if (SwapLists(crl) < 0) {
+            WOLFSSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+    if (fPEM != -1)
+        close(fPEM);
+    if (fDER != -1)
+        close(fDER);
+
+    close(crl->mfd);
+
+    return NULL;
+}
+
+
+#elif defined(__linux__)
+
+#include <sys/types.h>
+#include <sys/inotify.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+
+
+#ifndef max
+    static WC_INLINE int max(int a, int b)
+    {
+        return a > b ? a : b;
+    }
+#endif /* max */
+
+
+/* shutdown monitor thread, 0 on success */
+static int StopMonitor(int mfd)
+{
+    word64 w64 = 1;
+
+    /* write to our custom event */
+    if (write(mfd, &w64, sizeof(w64)) < 0) {
+        WOLFSSL_MSG("StopMonitor write failed");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* linux monitoring */
+static void* DoMonitor(void* arg)
+{
+    int         notifyFd;
+    int         wd  = -1;
+    WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
+#ifdef WOLFSSL_SMALL_STACK
+    char*       buff;
+#else
+    char        buff[8192];
+#endif
+
+    WOLFSSL_ENTER("DoMonitor");
+
+    crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
+    if (crl->mfd < 0) {
+        WOLFSSL_MSG("eventfd failed");
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    notifyFd = inotify_init();
+    if (notifyFd < 0) {
+        WOLFSSL_MSG("inotify failed");
+        close(crl->mfd);
+        SignalSetup(crl, MONITOR_SETUP_E);
+        return NULL;
+    }
+
+    if (crl->monitors[0].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            WOLFSSL_MSG("PEM notify add watch failed");
+            close(crl->mfd);
+            close(notifyFd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            WOLFSSL_MSG("DER notify add watch failed");
+            close(crl->mfd);
+            close(notifyFd);
+            SignalSetup(crl, MONITOR_SETUP_E);
+            return NULL;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buff == NULL)
+        return NULL;
+#endif
+
+    /* signal to calling thread we're setup */
+    if (SignalSetup(crl, 1) != 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+
+        if (wd > 0)
+            inotify_rm_watch(notifyFd, wd);
+        close(crl->mfd);
+        close(notifyFd);
+        return NULL;
+    }
+
+    for (;;) {
+        fd_set readfds;
+        int    result;
+        int    length;
+
+        FD_ZERO(&readfds);
+        FD_SET(notifyFd, &readfds);
+        FD_SET(crl->mfd, &readfds);
+
+        result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
+
+        WOLFSSL_MSG("Got notify event");
+
+        if (result < 0) {
+            WOLFSSL_MSG("select problem, continue");
+            continue;
+        }
+
+        if (FD_ISSET(crl->mfd, &readfds)) {
+            WOLFSSL_MSG("got custom shutdown event, breaking out");
+            break;
+        }
+
+        length = (int) read(notifyFd, buff, 8192);
+        if (length < 0) {
+            WOLFSSL_MSG("notify read problem, continue");
+            continue;
+        }
+
+        if (SwapLists(crl) < 0) {
+            WOLFSSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (wd > 0)
+        inotify_rm_watch(notifyFd, wd);
+    close(crl->mfd);
+    close(notifyFd);
+
+    return NULL;
+}
+
+#endif /* MACH or linux */
+
+
+/* Start Monitoring the CRL path(s) in a thread */
+static int StartMonitorCRL(WOLFSSL_CRL* crl)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("StartMonitorCRL");
+
+    if (crl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (crl->tid != 0) {
+        WOLFSSL_MSG("Monitor thread already running");
+        return ret;  /* that's ok, someone already started */
+    }
+
+    if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
+        WOLFSSL_MSG("Thread creation error");
+        return THREAD_CREATE_E;
+    }
+
+    /* wait for setup to complete */
+    if (wc_LockMutex(&crl->crlLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex crlLock error");
+        return BAD_MUTEX_E;
+    }
+
+        while (crl->setup == 0) {
+            if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
+                ret = BAD_COND_E;
+                break;
+            }
+        }
+
+        if (crl->setup < 0)
+            ret = crl->setup;  /* store setup error */
+
+    wc_UnLockMutex(&crl->crlLock);
+
+    if (ret < 0) {
+        WOLFSSL_MSG("DoMonitor setup failure");
+        crl->tid = 0;  /* thread already done */
+    }
+
+    return ret;
+}
+
+
+#else /* HAVE_CRL_MONITOR */
+
+#ifndef NO_FILESYSTEM
+
+static int StartMonitorCRL(WOLFSSL_CRL* crl)
+{
+    (void)crl;
+
+    WOLFSSL_ENTER("StartMonitorCRL");
+    WOLFSSL_MSG("Not compiled in");
+
+    return NOT_COMPILED_IN;
+}
+
+#endif /* NO_FILESYSTEM */
+
+#endif  /* HAVE_CRL_MONITOR */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+
+/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
+int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
+{
+    int         ret = WOLFSSL_SUCCESS;
+    char*       name = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    ReadDirCtx* readCtx = NULL;
+#else
+    ReadDirCtx  readCtx[1];
+#endif
+
+    WOLFSSL_ENTER("LoadCRL");
+    if (crl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (readCtx == NULL)
+        return MEMORY_E;
+#endif
+
+    /* try to load each regular file in path */
+    ret = wc_ReadDirFirst(readCtx, path, &name);
+    while (ret == 0 && name) {
+        int skip = 0;
+        if (type == WOLFSSL_FILETYPE_PEM) {
+            if (XSTRSTR(name, ".pem") == NULL) {
+                WOLFSSL_MSG("not .pem file, skipping");
+                skip = 1;
+            }
+        }
+        else {
+            if (XSTRSTR(name, ".der") == NULL &&
+                XSTRSTR(name, ".crl") == NULL)
+            {
+                WOLFSSL_MSG("not .der or .crl file, skipping");
+                skip = 1;
+            }
+        }
+
+        if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
+                                                           != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("CRL file load failed, continuing");
+        }
+
+        ret = wc_ReadDirNext(readCtx, path, &name);
+    }
+    wc_ReadDirClose(readCtx);
+    ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (monitor & WOLFSSL_CRL_MONITOR) {
+        word32 pathLen;
+        char* pathBuf;
+
+        WOLFSSL_MSG("monitor path requested");
+
+        pathLen = (word32)XSTRLEN(path);
+        pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
+        if (pathBuf) {
+            XSTRNCPY(pathBuf, path, pathLen);
+            pathBuf[pathLen] = '\0'; /* Null Terminate */
+
+            if (type == WOLFSSL_FILETYPE_PEM) {
+                /* free old path before setting a new one */
+                if (crl->monitors[0].path) {
+                    XFREE(crl->monitors[0].path, crl->heap,
+                            DYNAMIC_TYPE_CRL_MONITOR);
+                }
+                crl->monitors[0].path = pathBuf;
+                crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
+            } else {
+                /* free old path before setting a new one */
+                if (crl->monitors[1].path) {
+                    XFREE(crl->monitors[1].path, crl->heap,
+                            DYNAMIC_TYPE_CRL_MONITOR);
+                }
+                crl->monitors[1].path = pathBuf;
+                crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
+            }
+
+            if (monitor & WOLFSSL_CRL_START_MON) {
+                WOLFSSL_MSG("start monitoring requested");
+
+                ret = StartMonitorCRL(crl);
+            }
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+
+    return ret;
+}
+
+#else
+int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
+{
+	(void)crl;
+	(void)path;
+	(void)type;
+	(void)monitor;
+
+    /* stub for scenario where file system is not supported */
+    return NOT_COMPILED_IN;
+}
+#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
+
+#endif /* HAVE_CRL */
+#endif /* !WOLFCRYPT_ONLY */
+
--- a/src/internal.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/internal.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,25281 +1,25281 @@
-/* internal.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/dh.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA)
-    #include <wolfssl/wolfcrypt/srp.h>
-#endif
-
-#ifdef HAVE_LIBZ
-    #include "zlib.h"
-#endif
-
-#ifdef HAVE_NTRU
-    #include "libntruencrypt/ntru_crypto.h"
-#endif
-
-#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \
-    defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #else
-        #include <stdio.h>
-    #endif
-#endif
-
-#ifdef __sun
-    #include <sys/filio.h>
-#endif
-
-
-#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
-
-#ifdef _MSC_VER
-    /* disable for while(0) cases at the .c level for now */
-    #pragma warning(disable:4127)
-#endif
-
-#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS)
-    #error \
-WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
-#endif
-
-#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION)
-    #error Cannot use both secure-renegotiation and renegotiation-indication
-#endif
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifndef NO_WOLFSSL_CLIENT
-    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
-                                                                        word32);
-    static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
-                                                                        word32);
-    #ifndef NO_CERTS
-        static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*,
-                                                                        word32);
-    #endif
-    #ifdef HAVE_SESSION_TICKET
-        static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*,
-                                                                        word32);
-    #endif
-#endif
-
-
-#ifndef NO_WOLFSSL_SERVER
-    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
-    #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
-                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
-        static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
-    #endif
-    #ifdef WOLFSSL_DTLS
-        static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
-    #endif /* WOLFSSL_DTLS */
-#endif
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef WOLFSSL_DTLS
-    static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl);
-    static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
-#endif
-
-
-enum processReply {
-    doProcessInit = 0,
-#ifndef NO_WOLFSSL_SERVER
-    runProcessOldClientHello,
-#endif
-    getRecordLayerHeader,
-    getData,
-    decryptMessage,
-    verifyMessage,
-    runProcessingOneMessage
-};
-
-
-#ifndef WOLFSSL_NO_TLS12
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-
-/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
-static const byte tls13Downgrade[7] = {
-    0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44
-};
-#define TLS13_DOWNGRADE_SZ  sizeof(tls13Downgrade)
-
-#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
-
-#ifndef NO_OLD_TLS
-static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
-                    int padSz, int content, int verify);
-
-#endif
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef HAVE_QSH
-    int QSH_Init(WOLFSSL* ssl);
-#endif
-
-
-int IsTLS(const WOLFSSL* ssl)
-{
-    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
-        return 1;
-
-    return 0;
-}
-
-
-int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
-{
-    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
-        return 1;
-#ifdef WOLFSSL_DTLS
-    if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
-        return 1;
-#endif
-
-    return 0;
-}
-
-int IsAtLeastTLSv1_3(const ProtocolVersion pv)
-{
-    return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR);
-}
-
-static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
-{
-    (void)isSend;
-
-    #ifdef WOLFSSL_DTLS
-    /* For DTLS, epoch 0 is always not encrypted. */
-    if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
-        return 0;
-    #endif /* WOLFSSL_DTLS */
-
-    return ssl->keys.encryptionOn;
-}
-
-
-/* If SCTP is not enabled returns the state of the dtls option.
- * If SCTP is enabled returns dtls && !sctp. */
-static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
-{
-    int result = ssl->options.dtls;
-
-    if (result) {
-#ifdef WOLFSSL_SCTP
-        result = !ssl->options.dtlsSctp;
-#endif
-    }
-
-    return result;
-}
-
-
-#ifdef HAVE_QSH
-/* free all structs that where used with QSH */
-static int QSH_FreeAll(WOLFSSL* ssl)
-{
-    QSHKey* key        = ssl->QSH_Key;
-    QSHKey* preKey     = NULL;
-    QSHSecret* secret  = ssl->QSH_secret;
-    QSHScheme* list    = NULL;
-    QSHScheme* preList = NULL;
-
-    /* free elements in struct */
-    while (key) {
-        preKey = key;
-        if (key->pri.buffer) {
-            ForceZero(key->pri.buffer, key->pri.length);
-            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
-        }
-        if (key->pub.buffer)
-            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        key = (QSHKey*)key->next;
-
-        /* free struct */
-        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
-    }
-    key = NULL;
-
-
-    /* free all of peers QSH keys */
-    key = ssl->peerQSHKey;
-    while (key) {
-        preKey = key;
-        if (key->pri.buffer) {
-            ForceZero(key->pri.buffer, key->pri.length);
-            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
-        }
-        if (key->pub.buffer)
-            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        key = (QSHKey*)key->next;
-
-        /* free struct */
-        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
-    }
-    key = NULL;
-
-    /* free secret information */
-    if (secret) {
-        /* free up the QSHScheme list in QSHSecret */
-        if (secret->list)
-            list = secret->list;
-        while (list) {
-            preList = list;
-            if (list->PK)
-                XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET);
-            list = (QSHScheme*)list->next;
-            XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH);
-        }
-
-        /* free secret buffers */
-        if (secret->SerSi) {
-            if (secret->SerSi->buffer) {
-                /* clear extra secret material that supplemented Master Secret*/
-                ForceZero(secret->SerSi->buffer, secret->SerSi->length);
-                XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
-            }
-            XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET);
-        }
-        if (secret->CliSi) {
-            if (secret->CliSi->buffer) {
-                /* clear extra secret material that supplemented Master Secret*/
-                ForceZero(secret->CliSi->buffer, secret->CliSi->length);
-                XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
-            }
-            XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET);
-        }
-    }
-    XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH);
-    secret = NULL;
-
-    return 0;
-}
-#endif
-
-
-#ifdef HAVE_NTRU
-static WC_RNG* rng;
-static wolfSSL_Mutex* rngMutex;
-
-static word32 GetEntropy(unsigned char* out, word32 num_bytes)
-{
-    int ret = 0;
-
-    if (rng == NULL) {
-        if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0,
-                                                    DYNAMIC_TYPE_RNG)) == NULL)
-            return DRBG_OUT_OF_MEMORY;
-        wc_InitRng(rng);
-    }
-
-    if (rngMutex == NULL) {
-        if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0,
-                        DYNAMIC_TYPE_MUTEX)) == NULL)
-            return DRBG_OUT_OF_MEMORY;
-        wc_InitMutex(rngMutex);
-    }
-
-    ret |= wc_LockMutex(rngMutex);
-    ret |= wc_RNG_GenerateBlock(rng, out, num_bytes);
-    ret |= wc_UnLockMutex(rngMutex);
-
-    if (ret != 0)
-        return DRBG_ENTROPY_FAIL;
-
-    return DRBG_OK;
-}
-#endif /* HAVE_NTRU */
-
-#ifdef HAVE_LIBZ
-
-    /* alloc user allocs to work with zlib */
-    static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
-    {
-        (void)opaque;
-        return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
-    }
-
-
-    static void myFree(void* opaque, void* memory)
-    {
-        (void)opaque;
-        XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
-    }
-
-
-    /* init zlib comp/decomp streams, 0 on success */
-    static int InitStreams(WOLFSSL* ssl)
-    {
-        ssl->c_stream.zalloc = (alloc_func)myAlloc;
-        ssl->c_stream.zfree  = (free_func)myFree;
-        ssl->c_stream.opaque = (voidpf)ssl->heap;
-
-        if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
-            return ZLIB_INIT_ERROR;
-
-        ssl->didStreamInit = 1;
-
-        ssl->d_stream.zalloc = (alloc_func)myAlloc;
-        ssl->d_stream.zfree  = (free_func)myFree;
-        ssl->d_stream.opaque = (voidpf)ssl->heap;
-
-        if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
-
-        return 0;
-    }
-
-
-    static void FreeStreams(WOLFSSL* ssl)
-    {
-        if (ssl->didStreamInit) {
-            deflateEnd(&ssl->c_stream);
-            inflateEnd(&ssl->d_stream);
-        }
-    }
-
-
-    /* compress in to out, return out size or error */
-    static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz)
-    {
-        int    err;
-        int    currTotal = (int)ssl->c_stream.total_out;
-
-        ssl->c_stream.next_in   = in;
-        ssl->c_stream.avail_in  = inSz;
-        ssl->c_stream.next_out  = out;
-        ssl->c_stream.avail_out = outSz;
-
-        err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
-        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
-
-        return (int)ssl->c_stream.total_out - currTotal;
-    }
-
-
-    /* decompress in to out, return out size or error */
-    static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
-    {
-        int    err;
-        int    currTotal = (int)ssl->d_stream.total_out;
-
-        ssl->d_stream.next_in   = in;
-        ssl->d_stream.avail_in  = inSz;
-        ssl->d_stream.next_out  = out;
-        ssl->d_stream.avail_out = outSz;
-
-        err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
-        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
-
-        return (int)ssl->d_stream.total_out - currTotal;
-    }
-
-#endif /* HAVE_LIBZ */
-
-
-#ifdef WOLFSSL_SESSION_EXPORT
-#ifdef WOLFSSL_DTLS
-/* serializes the cipher specs struct for exporting */
-static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    word32 idx = 0;
-    CipherSpecs* specs;
-
-    WOLFSSL_ENTER("ExportCipherSpecState");
-
-    if (exp == NULL || ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    specs= &(ssl->specs);
-
-    if (DTLS_EXPORT_SPC_SZ > len) {
-        return BUFFER_E;
-    }
-
-    XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ);
-
-    c16toa(specs->key_size, exp + idx);      idx += OPAQUE16_LEN;
-    c16toa(specs->iv_size, exp + idx);       idx += OPAQUE16_LEN;
-    c16toa(specs->block_size, exp + idx);    idx += OPAQUE16_LEN;
-    c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN;
-    exp[idx++] = specs->bulk_cipher_algorithm;
-    exp[idx++] = specs->cipher_type;
-    exp[idx++] = specs->mac_algorithm;
-    exp[idx++] = specs->kea;
-    exp[idx++] = specs->sig_algo;
-    exp[idx++] = specs->hash_size;
-    exp[idx++] = specs->pad_size;
-    exp[idx++] = specs->static_ecdh;
-
-    if (idx != DTLS_EXPORT_SPC_SZ) {
-        WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version");
-        return DTLS_EXPORT_VER_E;
-    }
-
-    WOLFSSL_LEAVE("ExportCipherSpecState", idx);
-    (void)ver;
-    return idx;
-}
-
-
-/* serializes the key struct for exporting */
-static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    word32 idx = 0;
-    byte   sz;
-    Keys* keys;
-
-    WOLFSSL_ENTER("ExportKeyState");
-
-    if (exp == NULL || ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    keys = &(ssl->keys);
-
-    if (DTLS_EXPORT_KEY_SZ > len) {
-        WOLFSSL_MSG("Buffer not large enough for max key struct size");
-        return BUFFER_E;
-    }
-
-    XMEMSET(exp, 0, DTLS_EXPORT_KEY_SZ);
-
-    c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
-    c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
-    c32toa(keys->sequence_number_hi, exp + idx);      idx += OPAQUE32_LEN;
-    c32toa(keys->sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
-
-    c16toa(keys->peerSeq[0].nextEpoch, exp + idx);  idx += OPAQUE16_LEN;
-    c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
-    c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
-    c16toa(keys->curEpoch, exp + idx);   idx += OPAQUE16_LEN;
-    c16toa(keys->curSeq_hi, exp + idx);  idx += OPAQUE16_LEN;
-    c32toa(keys->curSeq_lo, exp + idx);  idx += OPAQUE32_LEN;
-    c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
-    c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN;
-
-    c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN;
-    c16toa(keys->dtls_expected_peer_handshake_number, exp + idx);
-    idx += OPAQUE16_LEN;
-
-    c16toa(keys->dtls_sequence_number_hi, exp + idx);      idx += OPAQUE16_LEN;
-    c32toa(keys->dtls_sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
-    c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN;
-    c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
-    c16toa(keys->dtls_epoch, exp + idx);                   idx += OPAQUE16_LEN;
-    c16toa(keys->dtls_handshake_number, exp + idx);        idx += OPAQUE16_LEN;
-    c32toa(keys->encryptSz, exp + idx);                    idx += OPAQUE32_LEN;
-    c32toa(keys->padSz, exp + idx);                        idx += OPAQUE32_LEN;
-    exp[idx++] = keys->encryptionOn;
-    exp[idx++] = keys->decryptedCur;
-
-    {
-        word32 i;
-
-        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
-        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
-            c32toa(keys->peerSeq[0].window[i], exp + idx);
-            idx += OPAQUE32_LEN;
-        }
-        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
-        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
-            c32toa(keys->peerSeq[0].prevWindow[i], exp + idx);
-            idx += OPAQUE32_LEN;
-        }
-    }
-
-#ifdef HAVE_TRUNCATED_HMAC
-    sz         = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size;
-    exp[idx++] = ssl->truncated_hmac;
-#else
-    sz         = ssl->specs.hash_size;
-    exp[idx++] = 0; /* no truncated hmac */
-#endif
-    exp[idx++] = sz;
-    XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz;
-    XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz;
-
-    sz         = ssl->specs.key_size;
-    exp[idx++] = sz;
-    XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz;
-    XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz;
-
-    sz         = ssl->specs.iv_size;
-    exp[idx++] = sz;
-    XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz;
-    XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz;
-    XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
-    idx += AEAD_MAX_EXP_SZ;
-
-    sz         = AEAD_MAX_IMP_SZ;
-    exp[idx++] = sz;
-    XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz;
-    XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz;
-
-    /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */
-    if (idx > DTLS_EXPORT_KEY_SZ) {
-        WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version");
-        return DTLS_EXPORT_VER_E;
-    }
-
-    WOLFSSL_LEAVE("ExportKeyState", idx);
-    (void)ver;
-    return idx;
-}
-
-static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    word32 idx = 0;
-    CipherSpecs* specs;
-
-    WOLFSSL_ENTER("ImportCipherSpecState");
-
-    if (exp == NULL || ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    specs= &(ssl->specs);
-
-    if (DTLS_EXPORT_SPC_SZ > len) {
-        WOLFSSL_MSG("Buffer not large enough for max spec struct size");
-        return BUFFER_E;
-    }
-
-    ato16(exp + idx, &specs->key_size);      idx += OPAQUE16_LEN;
-    ato16(exp + idx, &specs->iv_size);       idx += OPAQUE16_LEN;
-    ato16(exp + idx, &specs->block_size);    idx += OPAQUE16_LEN;
-    ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN;
-    specs->bulk_cipher_algorithm = exp[idx++];
-    specs->cipher_type           = exp[idx++];
-    specs->mac_algorithm         = exp[idx++];
-    specs->kea                   = exp[idx++];
-    specs->sig_algo              = exp[idx++];
-    specs->hash_size             = exp[idx++];
-    specs->pad_size              = exp[idx++];
-    specs->static_ecdh           = exp[idx++];
-
-    WOLFSSL_LEAVE("ImportCipherSpecState", idx);
-    (void)ver;
-    return idx;
-}
-
-
-static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    word32 idx = 0;
-    byte  sz;
-    Keys* keys;
-
-    WOLFSSL_ENTER("ImportKeyState");
-
-    if (exp == NULL || ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    keys = &(ssl->keys);
-
-    /* check minimum length -- includes byte used for size indicators */
-    if (len < DTLS_EXPORT_MIN_KEY_SZ) {
-        return BUFFER_E;
-    }
-    ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN;
-    ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN;
-    ato32(exp + idx, &keys->sequence_number_hi);      idx += OPAQUE32_LEN;
-    ato32(exp + idx, &keys->sequence_number_lo);      idx += OPAQUE32_LEN;
-
-    ato16(exp + idx, &keys->peerSeq[0].nextEpoch);  idx += OPAQUE16_LEN;
-    ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN;
-    ato16(exp + idx, &keys->curEpoch);   idx += OPAQUE16_LEN;
-    ato16(exp + idx, &keys->curSeq_hi);  idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->curSeq_lo);  idx += OPAQUE32_LEN;
-    ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN;
-
-    ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
-    ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
-    idx += OPAQUE16_LEN;
-
-    ato16(exp + idx, &keys->dtls_sequence_number_hi);      idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->dtls_sequence_number_lo);      idx += OPAQUE32_LEN;
-    ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN;
-    ato16(exp + idx, &keys->dtls_epoch);                   idx += OPAQUE16_LEN;
-    ato16(exp + idx, &keys->dtls_handshake_number);        idx += OPAQUE16_LEN;
-    ato32(exp + idx, &keys->encryptSz);                    idx += OPAQUE32_LEN;
-    ato32(exp + idx, &keys->padSz);                        idx += OPAQUE32_LEN;
-    keys->encryptionOn = exp[idx++];
-    keys->decryptedCur = exp[idx++];
-
-    {
-        word16 i, wordCount, wordAdj = 0;
-
-        /* do window */
-        ato16(exp + idx, &wordCount);
-        idx += OPAQUE16_LEN;
-
-        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
-            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
-            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
-        }
-
-        XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
-        for (i = 0; i < wordCount; i++) {
-            ato32(exp + idx, &keys->peerSeq[0].window[i]);
-            idx += OPAQUE32_LEN;
-        }
-        idx += wordAdj;
-
-        /* do prevWindow */
-        ato16(exp + idx, &wordCount);
-        idx += OPAQUE16_LEN;
-
-        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
-            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
-            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
-        }
-
-        XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
-        for (i = 0; i < wordCount; i++) {
-            ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]);
-            idx += OPAQUE32_LEN;
-        }
-        idx += wordAdj;
-
-    }
-
-#ifdef HAVE_TRUNCATED_HMAC
-    ssl->truncated_hmac = exp[idx++];
-#else
-    idx++; /* no truncated hmac */
-#endif
-    sz = exp[idx++];
-    if (sz > sizeof(keys->client_write_MAC_secret) || sz + idx > len) {
-        return BUFFER_E;
-    }
-    XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz;
-    XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz;
-
-    sz = exp[idx++];
-    if (sz > sizeof(keys->client_write_key) || sz + idx > len) {
-        return BUFFER_E;
-    }
-    XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz;
-    XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz;
-
-    sz = exp[idx++];
-    if (sz > sizeof(keys->client_write_IV) || sz + idx > len) {
-        return BUFFER_E;
-    }
-    XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz;
-    XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz;
-    XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ);
-    idx += AEAD_MAX_EXP_SZ;
-
-    sz = exp[idx++];
-    if (sz > sizeof(keys->aead_enc_imp_IV) || sz + idx > len) {
-        return BUFFER_E;
-    }
-    XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz;
-    XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz;
-
-    WOLFSSL_LEAVE("ImportKeyState", idx);
-    (void)ver;
-    return idx;
-}
-
-
-/* copy over necessary information from Options struct to buffer
- * On success returns size of buffer used on failure returns a negative value */
-static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    int idx = 0;
-    word16 zero = 0;
-    Options* options = &ssl->options;
-
-    WOLFSSL_ENTER("dtls_export_new");
-
-    if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ);
-
-    /* these options are kept and sent to indicate verify status and strength
-     * of handshake */
-    exp[idx++] = options->sendVerify;
-    exp[idx++] = options->verifyPeer;
-    exp[idx++] = options->verifyNone;
-    exp[idx++] = options->downgrade;
-#ifndef NO_DH
-    c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN;
-    c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN;
-    c16toa(options->dhKeySz, exp + idx);    idx += OPAQUE16_LEN;
-#else
-    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
-    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
-    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
-#endif
-#ifndef NO_RSA
-    c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN;
-#else
-    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
-#endif
-#ifdef HAVE_ECC
-    c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN;
-#else
-    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
-#endif
-
-    /* these options are kept to indicate state and behavior */
-#ifndef NO_PSK
-    exp[idx++] = options->havePSK;
-#else
-    exp[idx++] = 0;
-#endif
-    exp[idx++] = options->sessionCacheOff;
-    exp[idx++] = options->sessionCacheFlushOff;
-    exp[idx++] = options->side;
-    exp[idx++] = options->resuming;
-    exp[idx++] = options->haveSessionId;
-    exp[idx++] = options->tls;
-    exp[idx++] = options->tls1_1;
-    exp[idx++] = options->dtls;
-    exp[idx++] = options->connReset;
-    exp[idx++] = options->isClosed;
-    exp[idx++] = options->closeNotify;
-    exp[idx++] = options->sentNotify;
-    exp[idx++] = options->usingCompression;
-    exp[idx++] = options->haveRSA;
-    exp[idx++] = options->haveECC;
-    exp[idx++] = options->haveDH;
-    exp[idx++] = options->haveNTRU;
-    exp[idx++] = options->haveQSH;
-    exp[idx++] = options->haveECDSAsig;
-    exp[idx++] = options->haveStaticECC;
-    exp[idx++] = options->havePeerVerify;
-    exp[idx++] = options->usingPSK_cipher;
-    exp[idx++] = options->usingAnon_cipher;
-    exp[idx++] = options->sendAlertState;
-    exp[idx++] = options->partialWrite;
-    exp[idx++] = options->quietShutdown;
-    exp[idx++] = options->groupMessages;
-#ifdef HAVE_POLY1305
-    exp[idx++] = options->oldPoly;
-#else
-    exp[idx++] = 0;
-#endif
-#ifdef HAVE_ANON
-    exp[idx++] = options->haveAnon;
-#else
-    exp[idx++] = 0;
-#endif
-#ifdef HAVE_SESSION_TICKET
-    exp[idx++] = options->createTicket;
-    exp[idx++] = options->useTicket;
-#ifdef WOLFSSL_TLS13
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        exp[idx++] = options->noTicketTls13;
-    }
-#else
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        exp[idx++] = 0;
-    }
-#endif
-#else
-    exp[idx++] = 0;
-    exp[idx++] = 0;
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        exp[idx++] = 0;
-    }
-#endif
-    exp[idx++] = options->processReply;
-    exp[idx++] = options->cipherSuite0;
-    exp[idx++] = options->cipherSuite;
-    exp[idx++] = options->serverState;
-    exp[idx++] = options->clientState;
-    exp[idx++] = options->handShakeState;
-    exp[idx++] = options->handShakeDone;
-    exp[idx++] = options->minDowngrade;
-    exp[idx++] = options->connectState;
-    exp[idx++] = options->acceptState;
-    exp[idx++] = options->asyncState;
-
-    /* version of connection */
-    exp[idx++] = ssl->version.major;
-    exp[idx++] = ssl->version.minor;
-
-    (void)zero;
-
-    /* check if changes were made and notify of need to update export version */
-    switch (ver) {
-        case DTLS_EXPORT_VERSION_3:
-            if (idx != DTLS_EXPORT_OPT_SZ_3) {
-                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
-                return DTLS_EXPORT_VER_E;
-            }
-            break;
-
-        case DTLS_EXPORT_VERSION:
-            if (idx != DTLS_EXPORT_OPT_SZ) {
-                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
-                return DTLS_EXPORT_VER_E;
-            }
-            break;
-
-       default:
-            WOLFSSL_MSG("New version case needs added to wolfSSL export");
-            return DTLS_EXPORT_VER_E;
-    }
-
-    WOLFSSL_LEAVE("dtls_export_new", idx);
-
-    return idx;
-}
-
-
-/* copy items from Export struct to Options struct
- * On success returns size of buffer used on failure returns a negative value */
-static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    int idx = 0;
-    Options* options = &ssl->options;
-
-    switch (ver) {
-        case DTLS_EXPORT_VERSION:
-            if (len < DTLS_EXPORT_OPT_SZ) {
-                WOLFSSL_MSG("Sanity check on buffer size failed");
-                return BAD_FUNC_ARG;
-            }
-            break;
-
-        case DTLS_EXPORT_VERSION_3:
-            if (len < DTLS_EXPORT_OPT_SZ_3) {
-                WOLFSSL_MSG("Sanity check on buffer size failed");
-                return BAD_FUNC_ARG;
-            }
-            break;
-
-        default:
-            WOLFSSL_MSG("Export version not supported");
-            return BAD_FUNC_ARG;
-    }
-
-    if (exp == NULL || options == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-
-    /* these options are kept and sent to indicate verify status and strength
-     * of handshake */
-    options->sendVerify = exp[idx++];
-    options->verifyPeer = exp[idx++];
-    options->verifyNone = exp[idx++];
-    options->downgrade  = exp[idx++];
-#ifndef NO_DH
-    ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN;
-    ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN;
-    ato16(exp + idx, &(options->dhKeySz));    idx += OPAQUE16_LEN;
-#else
-    idx += OPAQUE16_LEN;
-    idx += OPAQUE16_LEN;
-    idx += OPAQUE16_LEN;
-#endif
-#ifndef NO_RSA
-    ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN;
-#else
-    idx += OPAQUE16_LEN;
-#endif
-#ifdef HAVE_ECC
-    ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN;
-#else
-    idx += OPAQUE16_LEN;
-#endif
-
-    /* these options are kept to indicate state and behavior */
-#ifndef NO_PSK
-    options->havePSK = exp[idx++];
-#else
-    idx++;
-#endif
-    options->sessionCacheOff      = exp[idx++];
-    options->sessionCacheFlushOff = exp[idx++];
-    options->side                 = exp[idx++];
-    options->resuming             = exp[idx++];
-    options->haveSessionId    = exp[idx++];
-    options->tls              = exp[idx++];
-    options->tls1_1           = exp[idx++];
-    options->dtls             = exp[idx++];
-    options->connReset        = exp[idx++];
-    options->isClosed         = exp[idx++];
-    options->closeNotify      = exp[idx++];
-    options->sentNotify       = exp[idx++];
-    options->usingCompression = exp[idx++];
-    options->haveRSA          = exp[idx++];
-    options->haveECC          = exp[idx++];
-    options->haveDH           = exp[idx++];
-    options->haveNTRU         = exp[idx++];
-    options->haveQSH          = exp[idx++];
-    options->haveECDSAsig     = exp[idx++];
-    options->haveStaticECC    = exp[idx++];
-    options->havePeerVerify   = exp[idx++];
-    options->usingPSK_cipher  = exp[idx++];
-    options->usingAnon_cipher = exp[idx++];
-    options->sendAlertState   = exp[idx++];
-    options->partialWrite     = exp[idx++];
-    options->quietShutdown    = exp[idx++];
-    options->groupMessages    = exp[idx++];
-#ifdef HAVE_POLY1305
-    options->oldPoly = exp[idx++];      /* set when to use old rfc way of poly*/
-#else
-    idx++;
-#endif
-#ifdef HAVE_ANON
-    options->haveAnon = exp[idx++];     /* User wants to allow Anon suites */
-#else
-    idx++;
-#endif
-#ifdef HAVE_SESSION_TICKET
-    options->createTicket  = exp[idx++]; /* Server to create new Ticket */
-    options->useTicket     = exp[idx++]; /* Use Ticket not session cache */
-#ifdef WOLFSSL_TLS13
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */
-    }
-#else
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        exp[idx++] = 0;
-    }
-#endif
-#else
-    idx++;
-    idx++;
-    if (ver > DTLS_EXPORT_VERSION_3) {
-        idx++;
-    }
-#endif
-    options->processReply   = exp[idx++];
-    options->cipherSuite0   = exp[idx++];
-    options->cipherSuite    = exp[idx++];
-    options->serverState    = exp[idx++];
-    options->clientState    = exp[idx++];
-    options->handShakeState = exp[idx++];
-    options->handShakeDone  = exp[idx++];
-    options->minDowngrade   = exp[idx++];
-    options->connectState   = exp[idx++];
-    options->acceptState    = exp[idx++];
-    options->asyncState     = exp[idx++];
-
-    /* version of connection */
-    if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) {
-        WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2");
-        return VERSION_ERROR;
-    }
-
-    return idx;
-}
-
-static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
-{
-    int    idx  = 0;
-    int    ipSz = DTLS_EXPORT_IP; /* start as max size */
-    int    fam  = 0;
-    word16 port = 0;
-    char   ip[DTLS_EXPORT_IP];
-
-    if (ver != DTLS_EXPORT_VERSION) {
-        WOLFSSL_MSG("Export version not supported");
-        return BAD_FUNC_ARG;
-    }
-
-    if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (ssl->ctx->CBGetPeer == NULL) {
-        WOLFSSL_MSG("No get peer call back set");
-        return BAD_FUNC_ARG;
-    }
-    if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("Get peer callback error");
-        return SOCKET_ERROR_E;
-    }
-
-    /* check that ipSz/fam is not negative or too large since user can set cb */
-    if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) {
-        WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback");
-        return SOCKET_ERROR_E;
-    }
-
-    c16toa((word16)fam, exp + idx);  idx += DTLS_EXPORT_LEN;
-    c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
-    XMEMCPY(exp + idx, ip, ipSz);    idx += ipSz;
-    c16toa(port, exp + idx);         idx += DTLS_EXPORT_LEN;
-
-    return idx;
-}
-
-
-static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
-{
-    word16 idx = 0;
-    word16 ipSz;
-    word16 fam;
-    word16 port;
-    char   ip[DTLS_EXPORT_IP];
-
-    if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) {
-        WOLFSSL_MSG("Export version not supported");
-        return BAD_FUNC_ARG;
-    }
-
-    if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* import sin family */
-    ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN;
-
-    /* import ip address idx, and ipSz are unsigned but cast for enum */
-    ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN;
-    if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) {
-        return BUFFER_E;
-    }
-    XMEMSET(ip, 0, sizeof(ip));
-    XMEMCPY(ip, buf + idx, ipSz); idx += ipSz;
-    ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */
-    ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN;
-
-    /* sanity check for a function to call, then use it to import peer info */
-    if (ssl->ctx->CBSetPeer == NULL) {
-        WOLFSSL_MSG("No set peer function");
-        return BAD_FUNC_ARG;
-    }
-    if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("Error setting peer info");
-        return SOCKET_ERROR_E;
-    }
-
-    return idx;
-}
-
-
-/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
- * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
- * passed in.
- * On success returns the size of serialized session.*/
-int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
-{
-    int ret;
-    word32 idx      = 0;
-    word32 totalLen = 0;
-
-    WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
-
-    if (buf == NULL || ssl == NULL) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG);
-        return BAD_FUNC_ARG;
-    }
-
-    totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
-    /* each of the following have a 2 byte length before data */
-    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ;
-    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ;
-    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ;
-    totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
-
-    if (totalLen > sz) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
-        return BUFFER_E;
-    }
-
-    buf[idx++] =  (byte)DTLS_EXPORT_PRO;
-    buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
-                 ((byte)DTLS_EXPORT_VERSION & 0X0F);
-
-    idx += DTLS_EXPORT_LEN; /* leave spot for length */
-
-    c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
-    if ((ret = dtls_export_new(ssl, buf + idx, sz - idx,
-                                                    DTLS_EXPORT_VERSION)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
-        return ret;
-    }
-    idx += ret;
-
-    /* export keys struct and dtls state -- variable length stored in ret */
-    idx += DTLS_EXPORT_LEN; /* leave room for length */
-    if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
-                                                    DTLS_EXPORT_VERSION)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
-        return ret;
-    }
-    c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
-
-    /* export of cipher specs struct */
-    c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
-    if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx,
-                                                    DTLS_EXPORT_VERSION)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
-        return ret;
-    }
-    idx += ret;
-
-    /* export of dtls peer information */
-    idx += DTLS_EXPORT_LEN;
-    if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx,
-                                                    DTLS_EXPORT_VERSION)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
-        return ret;
-    }
-    c16toa(ret, buf + idx - DTLS_EXPORT_LEN);
-    idx += ret;
-
-    /* place total length of exported buffer minus 2 bytes protocol/version */
-    c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
-
-    /* if compiled with debug options then print the version, protocol, size */
-#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
-    {
-        char debug[256];
-        XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n"
-                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
-               , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
-        WOLFSSL_MSG(debug);
-    }
-#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
-
-    WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
-    return idx;
-}
-
-
-/* On success return amount of buffer consumed */
-int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
-{
-    word32 idx    = 0;
-    word16 length = 0;
-    int version;
-    int ret;
-    int optSz;
-
-    WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
-    /* check at least enough room for protocol and length */
-    if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* sanity check on protocol ID and size of buffer */
-    if (buf[idx++]       !=  (byte)DTLS_EXPORT_PRO ||
-       (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
-        /* don't increment on second idx to next get version */
-        WOLFSSL_MSG("Incorrect protocol");
-        return BAD_FUNC_ARG;
-    }
-    version = buf[idx++] & 0x0F;
-
-    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
-    if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
-        return BUFFER_E;
-    }
-
-    /* if compiled with debug options then print the version, protocol, size */
-#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
-    {
-        char debug[256];
-        XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n"
-                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
-               , (int)version, buf[0], (buf[1] >> 4), length);
-        WOLFSSL_MSG(debug);
-    }
-#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
-
-    /* perform sanity checks and extract Options information used */
-    switch (version) {
-        case DTLS_EXPORT_VERSION:
-            optSz = DTLS_EXPORT_OPT_SZ;
-            break;
-
-        case DTLS_EXPORT_VERSION_3:
-            WOLFSSL_MSG("Importing older version 3");
-            optSz = DTLS_EXPORT_OPT_SZ_3;
-            break;
-
-        default:
-            WOLFSSL_MSG("Bad export version");
-            return BAD_FUNC_ARG;
-
-    }
-
-    if (DTLS_EXPORT_LEN + optSz + idx > sz) {
-        WOLFSSL_MSG("Import Options struct error");
-        return BUFFER_E;
-    }
-    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
-    if (length != optSz) {
-        WOLFSSL_MSG("Import Options struct error");
-        return BUFFER_E;
-    }
-    if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) {
-        WOLFSSL_MSG("Import Options struct error");
-        return ret;
-    }
-    idx += length;
-
-    /* perform sanity checks and extract Keys struct */
-    if (DTLS_EXPORT_LEN + idx > sz) {
-        WOLFSSL_MSG("Import Key struct error");
-        return BUFFER_E;
-    }
-    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
-    if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
-        WOLFSSL_MSG("Import Key struct error");
-        return BUFFER_E;
-    }
-    if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
-        WOLFSSL_MSG("Import Key struct error");
-        return ret;
-    }
-    idx += ret;
-
-    /* perform sanity checks and extract CipherSpecs struct */
-    if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) {
-        WOLFSSL_MSG("Import CipherSpecs struct error");
-        return BUFFER_E;
-    }
-    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
-    if ( length != DTLS_EXPORT_SPC_SZ) {
-        WOLFSSL_MSG("Import CipherSpecs struct error");
-        return BUFFER_E;
-    }
-    if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) {
-        WOLFSSL_MSG("Import CipherSpecs struct error");
-        return ret;
-    }
-    idx += ret;
-
-    /* perform sanity checks and extract DTLS peer info */
-    if (DTLS_EXPORT_LEN + idx > sz) {
-        WOLFSSL_MSG("Import DTLS peer info error");
-        return BUFFER_E;
-    }
-    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
-    if (idx + length > sz) {
-        WOLFSSL_MSG("Import DTLS peer info error");
-        return BUFFER_E;
-    }
-    if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) {
-        WOLFSSL_MSG("Import Peer Addr error");
-        return ret;
-    }
-    idx += ret;
-
-    SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
-
-    /* set hmac function to use when verifying */
-    if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 ||
-            ssl->options.dtls == 1) {
-        ssl->hmac = TLS_hmac;
-    }
-
-    /* make sure is a valid suite used */
-    if (wolfSSL_get_cipher(ssl) == NULL) {
-        WOLFSSL_MSG("Can not match cipher suite imported");
-        return MATCH_SUITE_ERROR;
-    }
-
-    /* do not allow stream ciphers with DTLS, except for NULL cipher */
-    if (ssl->specs.cipher_type == stream &&
-        ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) {
-        WOLFSSL_MSG("Can not import stream ciphers for DTLS");
-        return SANITY_CIPHER_E;
-    }
-
-    return idx;
-}
-#endif /* WOLFSSL_DTLS */
-#endif /* WOLFSSL_SESSION_EXPORT */
-
-
-void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
-{
-    method->version    = pv;
-    method->side       = WOLFSSL_CLIENT_END;
-    method->downgrade  = 0;
-}
-
-
-/* Initialize SSL context, return 0 on success */
-int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
-{
-    int ret = 0;
-
-    XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
-
-    ctx->method   = method;
-    ctx->refCount = 1;          /* so either CTX_free or SSL_free can release */
-    ctx->heap     = ctx;        /* defaults to self */
-    ctx->timeout  = WOLFSSL_SESSION_TIMEOUT;
-    ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */
-
-    if (wc_InitMutex(&ctx->countMutex) < 0) {
-        WOLFSSL_MSG("Mutex error on CTX init");
-        ctx->err = CTX_INIT_MUTEX_E;
-        return BAD_MUTEX_E;
-    }
-
-#ifndef NO_DH
-    ctx->minDhKeySz  = MIN_DHKEY_SZ;
-    ctx->maxDhKeySz  = MAX_DHKEY_SZ;
-#endif
-#ifndef NO_RSA
-    ctx->minRsaKeySz = MIN_RSAKEY_SZ;
-#endif
-#ifdef HAVE_ECC
-    ctx->minEccKeySz  = MIN_ECCKEY_SZ;
-    ctx->eccTempKeySz = ECDHE_SIZE;
-#endif
-#ifdef OPENSSL_EXTRA
-    ctx->verifyDepth = MAX_CHAIN_DEPTH;
-    ctx->cbioFlag = WOLFSSL_CBIO_NONE;
-#endif
-
-#ifndef WOLFSSL_USER_IO
-    #ifdef MICRIUM
-        ctx->CBIORecv = MicriumReceive;
-        ctx->CBIOSend = MicriumSend;
-        #ifdef WOLFSSL_DTLS
-            if (method->version.major == DTLS_MAJOR) {
-                ctx->CBIORecv   = MicriumReceiveFrom;
-                ctx->CBIOSend   = MicriumSendTo;
-            }
-            #ifdef WOLFSSL_SESSION_EXPORT
-                #error Micrium port does not support DTLS session export yet
-            #endif
-        #endif
-    #else
-        ctx->CBIORecv = EmbedReceive;
-        ctx->CBIOSend = EmbedSend;
-        #ifdef WOLFSSL_DTLS
-            if (method->version.major == DTLS_MAJOR) {
-                ctx->CBIORecv   = EmbedReceiveFrom;
-                ctx->CBIOSend   = EmbedSendTo;
-            }
-            #ifdef WOLFSSL_SESSION_EXPORT
-            ctx->CBGetPeer = EmbedGetPeer;
-            ctx->CBSetPeer = EmbedSetPeer;
-            #endif
-        #endif
-    #endif /* MICRIUM */
-#endif /* WOLFSSL_USER_IO */
-
-#ifdef HAVE_NETX
-    ctx->CBIORecv = NetX_Receive;
-    ctx->CBIOSend = NetX_Send;
-#endif
-
-#ifdef HAVE_NTRU
-    if (method->side == WOLFSSL_CLIENT_END)
-        ctx->haveNTRU = 1;           /* always on client side */
-                                     /* server can turn on by loading key */
-#endif
-#ifdef HAVE_ECC
-    if (method->side == WOLFSSL_CLIENT_END) {
-        ctx->haveECDSAsig  = 1;        /* always on client side */
-        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
-        ctx->haveStaticECC = 1;        /* server can turn on by loading key */
-    }
-#elif defined(HAVE_ED25519)
-    if (method->side == WOLFSSL_CLIENT_END) {
-        ctx->haveECDSAsig  = 1;        /* always on client side */
-        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
-    }
-#endif
-
-    ctx->devId = INVALID_DEVID;
-
-#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP)
-    ctx->dtlsMtuSz = MAX_RECORD_SIZE;
-#endif
-
-#ifndef NO_CERTS
-    ctx->cm = wolfSSL_CertManagerNew_ex(heap);
-    if (ctx->cm == NULL) {
-        WOLFSSL_MSG("Bad Cert Manager New");
-        return BAD_CERT_MANAGER_ERROR;
-    }
-    #ifdef OPENSSL_EXTRA
-    /* setup WOLFSSL_X509_STORE */
-    ctx->x509_store.cm = ctx->cm;
-    #endif
-#endif
-
-#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
-    if (method->side == WOLFSSL_CLIENT_END) {
-        if ((method->version.major == SSLv3_MAJOR) &&
-             (method->version.minor >= TLSv1_MINOR)) {
-
-            ctx->haveEMS = 1;
-        }
-#ifdef WOLFSSL_DTLS
-        if (method->version.major == DTLS_MAJOR)
-            ctx->haveEMS = 1;
-#endif /* WOLFSSL_DTLS */
-    }
-#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
-
-#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
-    ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
-#endif
-
-#ifdef HAVE_WOLF_EVENT
-    ret = wolfEventQueue_Init(&ctx->event_queue);
-#endif /* HAVE_WOLF_EVENT */
-
-#ifdef WOLFSSL_EARLY_DATA
-    ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ;
-#endif
-
-    ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */
-    ctx->verifyDepth = MAX_CHAIN_DEPTH;
-
-    return ret;
-}
-
-
-/* In case contexts are held in array and don't want to free actual ctx */
-void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
-{
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-    int i;
-#endif
-
-#ifdef HAVE_WOLF_EVENT
-    wolfEventQueue_Free(&ctx->event_queue);
-#endif /* HAVE_WOLF_EVENT */
-
-    XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
-    if (ctx->suites)
-        XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
-
-#ifndef NO_DH
-    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-#endif /* !NO_DH */
-
-#ifdef SINGLE_THREADED
-    if (ctx->rng) {
-        wc_FreeRng(ctx->rng);
-        XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG);
-    }
-#endif /* SINGLE_THREADED */
-
-#ifndef NO_CERTS
-    FreeDer(&ctx->privateKey);
-    FreeDer(&ctx->certificate);
-    #ifdef KEEP_OUR_CERT
-        if (ctx->ourCert && ctx->ownOurCert) {
-            FreeX509(ctx->ourCert);
-            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
-        }
-    #endif /* KEEP_OUR_CERT */
-    FreeDer(&ctx->certChain);
-    wolfSSL_CertManagerFree(ctx->cm);
-    #ifdef OPENSSL_EXTRA
-	/* ctx->cm was free'd so cm of x509 store should now be NULL */
-        if (ctx->x509_store_pt != NULL) {
-            ctx->x509_store_pt->cm = NULL;
-        }
-        wolfSSL_X509_STORE_free(ctx->x509_store_pt);
-        while (ctx->ca_names != NULL) {
-            WOLFSSL_STACK *next = ctx->ca_names->next;
-            wolfSSL_X509_NAME_free(ctx->ca_names->data.name);
-            XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL);
-            ctx->ca_names = next;
-        }
-    #endif
-    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-        while (ctx->x509Chain != NULL) {
-            WOLFSSL_STACK *next = ctx->x509Chain->next;
-            wolfSSL_X509_free(ctx->x509Chain->data.x509);
-            XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL);
-            ctx->x509Chain = next;
-        }
-    #endif
-#endif /* !NO_CERTS */
-
-#ifdef HAVE_TLS_EXTENSIONS
-    TLSX_FreeAll(ctx->extensions, ctx->heap);
-
-#ifndef NO_WOLFSSL_SERVER
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-    if (ctx->certOcspRequest) {
-        FreeOcspRequest(ctx->certOcspRequest);
-        XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-    }
-#endif
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-    for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
-        if (ctx->chainOcspRequest[i]) {
-            FreeOcspRequest(ctx->chainOcspRequest[i]);
-            XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-        }
-    }
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-#endif /* !NO_WOLFSSL_SERVER */
-
-#endif /* HAVE_TLS_EXTENSIONS */
-#ifdef OPENSSL_EXTRA
-    if(ctx->alpn_cli_protos)
-        XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL);
-#endif
-#ifdef WOLFSSL_STATIC_MEMORY
-    if (ctx->heap != NULL) {
-#ifdef WOLFSSL_HEAP_TEST
-        /* avoid derefrencing a test value */
-        if (ctx->heap != (void*)WOLFSSL_HEAP_TEST)
-#endif
-        {
-            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap);
-            wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex);
-        }
-    }
-#endif /* WOLFSSL_STATIC_MEMORY */
-}
-
-
-void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
-{
-    int doFree = 0;
-
-    if (wc_LockMutex(&ctx->countMutex) != 0) {
-        WOLFSSL_MSG("Couldn't lock count mutex");
-
-        /* check error state, if mutex error code then mutex init failed but
-         * CTX was still malloc'd */
-        if (ctx->err == CTX_INIT_MUTEX_E) {
-            SSL_CtxResourceFree(ctx);
-            XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
-        }
-        return;
-    }
-    ctx->refCount--;
-    if (ctx->refCount == 0)
-        doFree = 1;
-    wc_UnLockMutex(&ctx->countMutex);
-
-    if (doFree) {
-        WOLFSSL_MSG("CTX ref count down to 0, doing full free");
-        SSL_CtxResourceFree(ctx);
-        wc_FreeMutex(&ctx->countMutex);
-        XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
-    }
-    else {
-        (void)ctx;
-        WOLFSSL_MSG("CTX ref count not 0 yet, no free");
-    }
-}
-
-
-/* Set cipher pointers to null */
-void InitCiphers(WOLFSSL* ssl)
-{
-#ifdef BUILD_ARC4
-    ssl->encrypt.arc4 = NULL;
-    ssl->decrypt.arc4 = NULL;
-#endif
-#ifdef BUILD_DES3
-    ssl->encrypt.des3 = NULL;
-    ssl->decrypt.des3 = NULL;
-#endif
-#ifdef BUILD_AES
-    ssl->encrypt.aes = NULL;
-    ssl->decrypt.aes = NULL;
-#endif
-#ifdef HAVE_CAMELLIA
-    ssl->encrypt.cam = NULL;
-    ssl->decrypt.cam = NULL;
-#endif
-#ifdef HAVE_HC128
-    ssl->encrypt.hc128 = NULL;
-    ssl->decrypt.hc128 = NULL;
-#endif
-#ifdef BUILD_RABBIT
-    ssl->encrypt.rabbit = NULL;
-    ssl->decrypt.rabbit = NULL;
-#endif
-#ifdef HAVE_CHACHA
-    ssl->encrypt.chacha = NULL;
-    ssl->decrypt.chacha = NULL;
-#endif
-#ifdef HAVE_POLY1305
-    ssl->auth.poly1305 = NULL;
-#endif
-    ssl->encrypt.setup = 0;
-    ssl->decrypt.setup = 0;
-#ifdef HAVE_ONE_TIME_AUTH
-    ssl->auth.setup    = 0;
-#endif
-#ifdef HAVE_IDEA
-    ssl->encrypt.idea = NULL;
-    ssl->decrypt.idea = NULL;
-#endif
-}
-
-
-/* Free ciphers */
-void FreeCiphers(WOLFSSL* ssl)
-{
-    (void)ssl;
-#ifdef BUILD_ARC4
-    wc_Arc4Free(ssl->encrypt.arc4);
-    wc_Arc4Free(ssl->decrypt.arc4);
-    XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef BUILD_DES3
-    wc_Des3Free(ssl->encrypt.des3);
-    wc_Des3Free(ssl->decrypt.des3);
-    XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef BUILD_AES
-    wc_AesFree(ssl->encrypt.aes);
-    wc_AesFree(ssl->decrypt.aes);
-    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-        XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-        XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-        XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-        XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-    #endif
-    XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef HAVE_CAMELLIA
-    XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef HAVE_HC128
-    XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef BUILD_RABBIT
-    XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef HAVE_CHACHA
-    XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef HAVE_POLY1305
-    XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#ifdef HAVE_IDEA
-    XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
-    XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-}
-
-
-void InitCipherSpecs(CipherSpecs* cs)
-{
-    XMEMSET(cs, 0, sizeof(CipherSpecs));
-
-    cs->bulk_cipher_algorithm = INVALID_BYTE;
-    cs->cipher_type           = INVALID_BYTE;
-    cs->mac_algorithm         = INVALID_BYTE;
-    cs->kea                   = INVALID_BYTE;
-    cs->sig_algo              = INVALID_BYTE;
-}
-
-void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig,
-                           int haveAnon, int tls1_2, int keySz)
-{
-    int idx = 0;
-
-    (void)tls1_2;
-    (void)keySz;
-
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    if (haveECDSAsig) {
-    #ifdef HAVE_ECC
-        #ifdef WOLFSSL_SHA512
-            suites->hashSigAlgo[idx++] = sha512_mac;
-            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            suites->hashSigAlgo[idx++] = sha384_mac;
-            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
-        #endif
-        #ifndef NO_SHA256
-            suites->hashSigAlgo[idx++] = sha256_mac;
-            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
-        #endif
-        #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
-                                                defined(WOLFSSL_ALLOW_TLS_SHA1))
-            suites->hashSigAlgo[idx++] = sha_mac;
-            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
-        #endif
-    #endif
-        #ifdef HAVE_ED25519
-            suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR;
-            suites->hashSigAlgo[idx++] = ED25519_SA_MINOR;
-        #endif
-    }
-#endif /* HAVE_ECC || HAVE_ED25519 */
-
-    if (haveRSAsig) {
-        #ifdef WC_RSA_PSS
-            if (tls1_2) {
-            #ifdef WOLFSSL_SHA512
-                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
-                suites->hashSigAlgo[idx++] = sha512_mac;
-            #endif
-            #ifdef WOLFSSL_SHA384
-                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
-                suites->hashSigAlgo[idx++] = sha384_mac;
-            #endif
-            #ifndef NO_SHA256
-                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
-                suites->hashSigAlgo[idx++] = sha256_mac;
-            #endif
-            }
-        #endif
-        #ifdef WOLFSSL_SHA512
-            suites->hashSigAlgo[idx++] = sha512_mac;
-            suites->hashSigAlgo[idx++] = rsa_sa_algo;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            suites->hashSigAlgo[idx++] = sha384_mac;
-            suites->hashSigAlgo[idx++] = rsa_sa_algo;
-        #endif
-        #ifndef NO_SHA256
-            suites->hashSigAlgo[idx++] = sha256_mac;
-            suites->hashSigAlgo[idx++] = rsa_sa_algo;
-        #endif
-        #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
-                                                defined(WOLFSSL_ALLOW_TLS_SHA1))
-            suites->hashSigAlgo[idx++] = sha_mac;
-            suites->hashSigAlgo[idx++] = rsa_sa_algo;
-        #endif
-    }
-
-#ifdef HAVE_ANON
-    if (haveAnon) {
-            suites->hashSigAlgo[idx++] = sha_mac;
-            suites->hashSigAlgo[idx++] = anonymous_sa_algo;
-    }
-#endif
-
-    (void)haveAnon;
-    (void)haveECDSAsig;
-    suites->hashSigAlgoSz = (word16)idx;
-}
-
-void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
-                word16 havePSK, word16 haveDH, word16 haveNTRU,
-                word16 haveECDSAsig, word16 haveECC,
-                word16 haveStaticECC, int side)
-{
-    word16 idx = 0;
-    int    tls    = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
-    int    tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
-#ifdef WOLFSSL_TLS13
-    int    tls1_3 = IsAtLeastTLSv1_3(pv);
-#endif
-    int    dtls   = 0;
-    int    haveRSAsig = 1;
-
-    (void)tls;  /* shut up compiler */
-    (void)tls1_2;
-    (void)dtls;
-    (void)haveDH;
-    (void)havePSK;
-    (void)haveNTRU;
-    (void)haveStaticECC;
-    (void)haveECC;
-    (void)side;
-    (void)haveRSA;    /* some builds won't read */
-    (void)haveRSAsig; /* non ecc builds won't read */
-
-    if (suites == NULL) {
-        WOLFSSL_MSG("InitSuites pointer error");
-        return;
-    }
-
-    if (suites->setSuites)
-        return;      /* trust user settings, don't override */
-
-#ifdef WOLFSSL_TLS13
-#ifdef BUILD_TLS_AES_128_GCM_SHA256
-    if (tls1_3) {
-        suites->suites[idx++] = TLS13_BYTE;
-        suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_AES_256_GCM_SHA384
-    if (tls1_3) {
-        suites->suites[idx++] = TLS13_BYTE;
-        suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
-    if (tls1_3) {
-        suites->suites[idx++] = TLS13_BYTE;
-        suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_SHA256
-    if (tls1_3) {
-        suites->suites[idx++] = TLS13_BYTE;
-        suites->suites[idx++] = TLS_AES_128_CCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
-    if (tls1_3) {
-        suites->suites[idx++] = TLS13_BYTE;
-        suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256;
-    }
-#endif
-#endif /* WOLFSSL_TLS13 */
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifndef NO_WOLFSSL_SERVER
-    if (side == WOLFSSL_SERVER_END && haveStaticECC) {
-        haveRSA = 0;   /* can't do RSA with ECDSA key */
-    }
-
-    if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
-        haveRSAsig = 0;     /* can't have RSA sig if signed by ECDSA */
-    }
-#endif /* !NO_WOLFSSL_SERVER */
-
-#ifdef WOLFSSL_DTLS
-    if (pv.major == DTLS_MAJOR) {
-        dtls   = 1;
-        tls    = 1;
-        /* May be dead assignments dependant upon configuration */
-        (void) dtls;
-        (void) tls;
-        tls1_2 = pv.minor <= DTLSv1_2_MINOR;
-    }
-#endif
-
-#ifdef HAVE_RENEGOTIATION_INDICATION
-    if (side == WOLFSSL_CLIENT_END) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
-    }
-#endif
-
-#ifdef BUILD_TLS_QSH
-    if (tls) {
-        suites->suites[idx++] = QSH_BYTE;
-        suites->suites[idx++] = TLS_QSH;
-    }
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-   if (tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
-   }
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-    if (tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-    if (!dtls && tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveNTRU && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-    if (tls1_2 && haveDH) {
-      suites->suites[idx++] = CIPHER_BYTE;
-      suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && haveDH) {
-      suites->suites[idx++] = CIPHER_BYTE;
-      suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-    if (tls1_2 && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-    if (tls1_2 && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-/* Place as higher priority for MYSQL */
-#if defined(WOLFSSL_MYSQL_COMPATIBLE)
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-    if (tls1_2 && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-    if (tls1_2 && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-    if (tls1_2 && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-    if (tls1_2 && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-    if (tls && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-    if (tls && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-    if (tls && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-    if (tls && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-    if (!dtls && tls && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-    if (!dtls && tls && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveECC && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-    if (tls && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-    if (tls && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-    if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-    if (!dtls && tls && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveRSAsig && haveStaticECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-/* Place as higher priority for MYSQL testing */
-#if !defined(WOLFSSL_MYSQL_COMPATIBLE)
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    if (tls1_2 && haveECC) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] =
-                              TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    if (tls1_2 && haveRSA) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-    if (tls && haveECC) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CCM;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = CHACHA_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM_8;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
-    }
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = ECC_BYTE;
-        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-    if (tls && haveDH && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
-    if (tls && havePSK) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
-    }
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
-    if (!dtls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
-    if (!dtls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
-    }
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-    if (haveRSA ) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
-    if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
-    if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
-    if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
-    if (!dtls && tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    if (tls && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    if (tls && haveDH && haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
-    }
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-    if (haveRSA) {
-        suites->suites[idx++] = CIPHER_BYTE;
-        suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
-    }
-#endif
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-    suites->suiteSz = idx;
-
-    InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0, tls1_2, keySz);
-}
-
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \
-    (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC)))
-
-/* Decode the signature algorithm.
- *
- * input     The encoded signature algorithm.
- * hashalgo  The hash algorithm.
- * hsType    The signature type.
- */
-static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
-{
-    switch (input[0]) {
-        case NEW_SA_MAJOR:
-    #ifdef WC_RSA_PSS
-            /* PSS signatures: 0x080[4-6] */
-            if (input[1] <= sha512_mac) {
-                *hsType   = input[0];
-                *hashAlgo = input[1];
-            }
-    #endif
-    #ifdef HAVE_ED25519
-            /* ED25519: 0x0807 */
-            if (input[1] == ED25519_SA_MINOR) {
-                *hsType = ed25519_sa_algo;
-                /* Hash performed as part of sign/verify operation. */
-                *hashAlgo = sha512_mac;
-            }
-    #endif
-            /* ED448: 0x0808 */
-            break;
-        default:
-            *hashAlgo = input[0];
-            *hsType   = input[1];
-            break;
-    }
-}
-#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
-
-#ifndef WOLFSSL_NO_TLS12
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
-                                       (!defined(NO_RSA) && defined(WC_RSA_PSS))
-
-static enum wc_HashType HashAlgoToType(int hashAlgo)
-{
-    switch (hashAlgo) {
-    #ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            return WC_HASH_TYPE_SHA512;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            return WC_HASH_TYPE_SHA384;
-    #endif
-    #ifndef NO_SHA256
-        case sha256_mac:
-            return WC_HASH_TYPE_SHA256;
-    #endif
-    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
-                             defined(WOLFSSL_ALLOW_TLS_SHA1))
-        case sha_mac:
-            return WC_HASH_TYPE_SHA;
-    #endif
-        default:
-            WOLFSSL_MSG("Bad hash sig algo");
-            break;
-    }
-
-    return WC_HASH_TYPE_NONE;
-}
-#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */
-#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifndef NO_CERTS
-
-void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
-{
-    (void)dynamicFlag;
-
-    if (name != NULL) {
-        name->name        = name->staticName;
-        name->dynamicName = 0;
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        XMEMSET(&name->fullName, 0, sizeof(DecodedName));
-        XMEMSET(&name->cnEntry,  0, sizeof(WOLFSSL_X509_NAME_ENTRY));
-        XMEMSET(&name->extra,    0, sizeof(name->extra));
-        name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/
-        name->cnEntry.nid = ASN_COMMON_NAME;
-        name->x509 = NULL;
-#endif /* OPENSSL_EXTRA */
-    }
-}
-
-
-void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap)
-{
-    if (name != NULL) {
-        if (name->dynamicName)
-            XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        {
-            int i;
-            if (name->fullName.fullName != NULL) {
-                XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509);
-                name->fullName.fullName = NULL;
-            }
-            for (i = 0; i < MAX_NAME_ENTRIES; i++) {
-                /* free ASN1 string data */
-                if (name->extra[i].set && name->extra[i].data.data != NULL) {
-                    XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL);
-                }
-            }
-        }
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-    }
-    (void)heap;
-}
-
-
-/* Initialize wolfSSL X509 type */
-void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
-{
-    if (x509 == NULL) {
-        WOLFSSL_MSG("Null parameter passed in!");
-        return;
-    }
-
-    XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
-
-    x509->heap = heap;
-    InitX509Name(&x509->issuer, 0);
-    InitX509Name(&x509->subject, 0);
-    x509->dynamicMemory  = (byte)dynamicFlag;
-}
-
-
-/* Free wolfSSL X509 type */
-void FreeX509(WOLFSSL_X509* x509)
-{
-    if (x509 == NULL)
-        return;
-
-    FreeX509Name(&x509->issuer, x509->heap);
-    FreeX509Name(&x509->subject, x509->heap);
-    if (x509->pubKey.buffer)
-        XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    FreeDer(&x509->derCert);
-    XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
-        XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
-        if (x509->authInfo != NULL) {
-            XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
-        }
-        if (x509->extKeyUsageSrc != NULL) {
-            XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
-        }
-    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-    if (x509->altNames)
-        FreeAltNames(x509->altNames, x509->heap);
-}
-
-
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-/* Encode the signature algorithm into buffer.
- *
- * hashalgo  The hash algorithm.
- * hsType   The signature type.
- * output    The buffer to encode into.
- */
-static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
-{
-    switch (hsType) {
-#ifdef HAVE_ECC
-        case ecc_dsa_sa_algo:
-            output[0] = hashAlgo;
-            output[1] = ecc_dsa_sa_algo;
-            break;
-#endif
-#ifdef HAVE_ED25519
-        case ed25519_sa_algo:
-            output[0] = ED25519_SA_MAJOR;
-            output[1] = ED25519_SA_MINOR;
-            (void)hashAlgo;
-            break;
-#endif
-#ifndef NO_RSA
-        case rsa_sa_algo:
-            output[0] = hashAlgo;
-            output[1] = rsa_sa_algo;
-            break;
-    #ifdef WC_RSA_PSS
-        /* PSS signatures: 0x080[4-6] */
-        case rsa_pss_sa_algo:
-            output[0] = rsa_pss_sa_algo;
-            output[1] = hashAlgo;
-            break;
-    #endif
-#endif
-        /* ED448: 0x0808 */
-    }
-    (void)hashAlgo;
-    (void)output;
-}
-
-#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
-static void SetDigest(WOLFSSL* ssl, int hashAlgo)
-{
-    switch (hashAlgo) {
-    #ifndef NO_SHA
-        case sha_mac:
-            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha;
-            ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA */
-    #ifndef NO_SHA256
-        case sha256_mac:
-            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256;
-            ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA256 */
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384;
-            ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512;
-            ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA512 */
-    } /* switch */
-}
-#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */
-#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
-#endif /* !NO_CERTS */
-
-#ifndef NO_RSA
-#ifndef WOLFSSL_NO_TLS12
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-static int TypeHash(int hashAlgo)
-{
-    switch (hashAlgo) {
-    #ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            return SHA512h;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            return SHA384h;
-    #endif
-    #ifndef NO_SHA256
-        case sha256_mac:
-            return SHA256h;
-    #endif
-    #ifndef NO_SHA
-        case sha_mac:
-            return SHAh;
-    #endif
-    }
-
-    return 0;
-}
-#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#if defined(WC_RSA_PSS)
-int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
-{
-    switch (hashAlgo) {
-        #ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            *hashType = WC_HASH_TYPE_SHA512;
-            if (mgf != NULL)
-                *mgf = WC_MGF1SHA512;
-            break;
-        #endif
-        #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            *hashType = WC_HASH_TYPE_SHA384;
-            if (mgf != NULL)
-                *mgf = WC_MGF1SHA384;
-            break;
-        #endif
-        #ifndef NO_SHA256
-        case sha256_mac:
-            *hashType = WC_HASH_TYPE_SHA256;
-            if (mgf != NULL)
-                *mgf = WC_MGF1SHA256;
-            break;
-        #endif
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    return 0;
-}
-#endif
-
-int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
-            word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
-            DerBuffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-    (void)sigAlgo;
-    (void)hashAlgo;
-
-    WOLFSSL_ENTER("RsaSign");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#if defined(WC_RSA_PSS)
-    if (sigAlgo == rsa_pss_sa_algo) {
-        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
-        int mgf = 0;
-
-        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
-        if (ret != 0)
-            return ret;
-
-    #if defined(HAVE_PK_CALLBACKS)
-        if (ssl->ctx->RsaPssSignCb) {
-            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
-            ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz,
-                                         TypeHash(hashAlgo), mgf,
-                                         keyBuf, keySz, ctx);
-        }
-        else
-    #endif
-        {
-            ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key,
-                                                                      ssl->rng);
-        }
-    }
-    else
-#endif
-#if defined(HAVE_PK_CALLBACKS)
-    if (ssl->ctx->RsaSignCb) {
-        void* ctx = wolfSSL_GetRsaSignCtx(ssl);
-        ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
-                                                                          ctx);
-    }
-    else
-#endif /*HAVE_PK_CALLBACKS */
-        ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng);
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* For positive response return in outSz */
-    if (ret > 0) {
-        *outSz = ret;
-        ret = 0;
-    }
-
-    WOLFSSL_LEAVE("RsaSign", ret);
-
-    return ret;
-}
-
-int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
-              int hashAlgo, RsaKey* key, buffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-    (void)sigAlgo;
-    (void)hashAlgo;
-
-    WOLFSSL_ENTER("RsaVerify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#if defined(WC_RSA_PSS)
-    if (sigAlgo == rsa_pss_sa_algo) {
-        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
-        int mgf = 0;
-
-        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
-        if (ret != 0)
-            return ret;
-#ifdef HAVE_PK_CALLBACKS
-        if (ssl->ctx->RsaPssVerifyCb) {
-            void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl);
-            ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out,
-                                           TypeHash(hashAlgo), mgf,
-                                           keyBuf, keySz, ctx);
-        }
-        else
-#endif /*HAVE_PK_CALLBACKS */
-            ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key);
-    }
-    else
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->RsaVerifyCb) {
-        void* ctx = wolfSSL_GetRsaVerifyCtx(ssl);
-        ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
-    }
-    else
-#endif /*HAVE_PK_CALLBACKS */
-    {
-        ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("RsaVerify", ret);
-
-    return ret;
-}
-
-/* Verify RSA signature, 0 on success */
-/* This function is used to check the sign result */
-int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
-    const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key,
-    DerBuffer* keyBufInfo)
-{
-    byte* out = NULL;  /* inline result */
-    int   ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-    (void)sigAlgo;
-    (void)hashAlgo;
-
-    WOLFSSL_ENTER("VerifyRsaSign");
-
-    if (verifySig == NULL || plain == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (sigSz > ENCRYPT_LEN) {
-        WOLFSSL_MSG("Signature buffer too big");
-        return BUFFER_E;
-    }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    if (key) {
-        ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-        if (ret != 0)
-            return ret;
-    }
-#endif
-
-#if defined(WC_RSA_PSS)
-    if (sigAlgo == rsa_pss_sa_algo) {
-        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
-        int mgf = 0;
-
-        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
-        if (ret != 0)
-            return ret;
-    #ifdef HAVE_PK_CALLBACKS
-        if (ssl->ctx->RsaPssSignCheckCb) {
-            /* The key buffer includes private/public portion,
-                but only public is used */
-            /* If HSM hardware is checking the signature result you can
-                optionally skip the sign check and return 0 */
-            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
-            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
-            ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out,
-                                           TypeHash(hashAlgo), mgf,
-                                           keyBuf, keySz, ctx);
-        }
-        else
-    #endif /* HAVE_PK_CALLBACKS */
-        {
-            ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
-                                         key);
-        }
-
-        if (ret > 0) {
-            ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType);
-            if (ret != 0)
-                ret = VERIFY_CERT_ERROR;
-        }
-    }
-    else
-#endif /* WC_RSA_PSS */
-    {
-    #ifdef HAVE_PK_CALLBACKS
-        if (ssl->ctx->RsaSignCheckCb) {
-            /* The key buffer includes private/public portion,
-                but only public is used */
-            /* If HSM hardware is checking the signature result you can
-                optionally skip the sign check and return 0 */
-            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
-            void* ctx = wolfSSL_GetRsaSignCtx(ssl);
-            ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out,
-                keyBuf, keySz, ctx);
-        }
-        else
-    #endif /* HAVE_PK_CALLBACKS */
-        {
-            ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key);
-        }
-
-        if (ret > 0) {
-            if (ret != (int)plainSz || !out ||
-                                            XMEMCMP(plain, out, plainSz) != 0) {
-                WOLFSSL_MSG("RSA Signature verification failed");
-                ret = RSA_SIGN_FAULT;
-            } else {
-                ret = 0;  /* RSA reset */
-            }
-        }
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (key && ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("VerifyRsaSign", ret);
-
-    return ret;
-}
-
-#ifndef WOLFSSL_NO_TLS12
-
-int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
-    RsaKey* key, DerBuffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("RsaDec");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->RsaDecCb) {
-        void* ctx = wolfSSL_GetRsaDecCtx(ssl);
-        ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS */
-    {
-        #ifdef WC_RSA_BLINDING
-            ret = wc_RsaSetRNG(key, ssl->rng);
-            if (ret != 0)
-                return ret;
-        #endif
-        ret = wc_RsaPrivateDecryptInline(in, inSz, out, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* For positive response return in outSz */
-    if (ret > 0) {
-        *outSz = ret;
-        ret = 0;
-    }
-
-    WOLFSSL_LEAVE("RsaDec", ret);
-
-    return ret;
-}
-
-int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
-    RsaKey* key, buffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("RsaEnc");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->RsaEncCb) {
-        void* ctx = wolfSSL_GetRsaEncCtx(ssl);
-        ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS */
-    {
-        ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* For positive response return in outSz */
-    if (ret > 0) {
-        *outSz = ret;
-        ret = 0;
-    }
-
-    WOLFSSL_LEAVE("RsaEnc", ret);
-
-    return ret;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#endif /* NO_RSA */
-
-#ifdef HAVE_ECC
-
-int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
-    word32* outSz, ecc_key* key, DerBuffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("EccSign");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#if defined(HAVE_PK_CALLBACKS)
-    if (ssl->ctx->EccSignCb) {
-        void* ctx = wolfSSL_GetEccSignCtx(ssl);
-        ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf,
-            keySz, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS */
-    {
-        ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("EccSign", ret);
-
-    return ret;
-}
-
-int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
-    word32 outSz, ecc_key* key, buffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("EccVerify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->EccVerifyCb) {
-        void* ctx = wolfSSL_GetEccVerifyCtx(ssl);
-        ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
-            &ssl->eccVerifyRes, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS  */
-    {
-        ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-    else
-#endif /* WOLFSSL_ASYNC_CRYPT */
-    {
-        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
-    }
-
-    WOLFSSL_LEAVE("EccVerify", ret);
-
-    return ret;
-}
-
-#ifdef HAVE_PK_CALLBACKS
-    /* Gets ECC key for shared secret callback testing
-     * Client side: returns peer key
-     * Server side: returns private key
-     */
-    static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey)
-    {
-        int ret = NO_PEER_KEY;
-        ecc_key* tmpKey = NULL;
-
-        if (ssl == NULL || otherKey == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (ssl->options.side == WOLFSSL_CLIENT_END) {
-            if (ssl->specs.static_ecdh) {
-                if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
-                                           !ssl->peerEccDsaKey->dp) {
-                    return NO_PEER_KEY;
-                }
-                tmpKey = (struct ecc_key*)ssl->peerEccDsaKey;
-            }
-            else {
-                if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
-                                        !ssl->peerEccKey->dp) {
-                    return NO_PEER_KEY;
-                }
-                tmpKey = (struct ecc_key*)ssl->peerEccKey;
-            }
-        }
-        else if (ssl->options.side == WOLFSSL_SERVER_END) {
-            if (ssl->specs.static_ecdh) {
-                if (ssl->hsKey == NULL) {
-                    return NO_PRIVATE_KEY;
-                }
-                tmpKey = (struct ecc_key*)ssl->hsKey;
-            }
-            else {
-                if (!ssl->eccTempKeyPresent) {
-                    return NO_PRIVATE_KEY;
-                }
-                tmpKey = (struct ecc_key*)ssl->eccTempKey;
-            }
-        }
-
-        if (tmpKey) {
-            *otherKey = tmpKey;
-            ret = 0;
-        }
-
-        return ret;
-    }
-#endif /* HAVE_PK_CALLBACKS */
-
-int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
-        byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
-        int side)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    ecc_key* otherKey = NULL;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev;
-#endif
-
-    (void)ssl;
-    (void)pubKeyDer;
-    (void)pubKeySz;
-    (void)side;
-
-    WOLFSSL_ENTER("EccSharedSecret");
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->EccSharedSecretCb) {
-        ret = EccGetKey(ssl, &otherKey);
-        if (ret != 0)
-            return ret;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        asyncDev = &otherKey->asyncDev;
-    #endif
-    }
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->EccSharedSecretCb) {
-        void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl);
-        ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
-            pubKeySz, out, outlen, side, ctx);
-    }
-    else
-#endif
-    {
-        ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("EccSharedSecret", ret);
-
-    return ret;
-}
-
-int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
-{
-    int ret = 0;
-    int keySz = 0;
-    int ecc_curve = ECC_CURVE_DEF;
-
-    WOLFSSL_ENTER("EccMakeKey");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
-    if (ret != 0)
-        return ret;
-#endif
-
-    /* get key size */
-    if (peer == NULL) {
-        keySz = ssl->eccTempKeySz;
-    }
-    else {
-        keySz = peer->dp->size;
-    }
-
-    /* get curve type */
-    if (ssl->ecdhCurveOID > 0) {
-        ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
-    }
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->EccKeyGenCb) {
-        void* ctx = wolfSSL_GetEccKeyGenCtx(ssl);
-        ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx);
-    }
-    else
-#endif
-    {
-        ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
-    }
-
-    /* make sure the curve is set for TLS */
-    if (ret == 0 && key->dp) {
-        ssl->ecdhCurveOID = key->dp->oidSum;
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("EccMakeKey", ret);
-
-    return ret;
-}
-#endif /* HAVE_ECC */
-
-#ifdef HAVE_ED25519
-/* Check whether the key contains a public key.
- * If not then pull it out of the leaf certificate.
- *
- * ssl  SSL/TLS object.
- * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
- * 0 on success.
- */
-int Ed25519CheckPubKey(WOLFSSL* ssl)
-{
-    ed25519_key* key = (ed25519_key*)ssl->hsKey;
-    int ret = 0;
-
-    /* Public key required for signing. */
-    if (!key->pubKeySet) {
-        DerBuffer* leaf = ssl->buffers.certificate;
-        DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert),
-                                     ssl->heap, DYNAMIC_TYPE_DCERT);
-        if (cert == NULL)
-            ret = MEMORY_E;
-
-        if (ret == 0) {
-            InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
-            ret = DecodeToKey(cert, 0);
-        }
-        if (ret == 0) {
-            ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize,
-                                                                           key);
-        }
-        if (cert != NULL) {
-            FreeDecodedCert(cert);
-            XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
-        }
-    }
-
-    return ret;
-}
-
-/* Sign the data using EdDSA and key using X25519.
- *
- * ssl    SSL object.
- * in     Data or message to sign.
- * inSz   Length of the data.
- * out    Buffer to hold signature.
- * outSz  On entry, size of the buffer. On exit, the size of the signature.
- * key    The private X25519 key data.
- * keySz  The length of the private key data in bytes.
- * ctx    The callback context.
- * returns 0 on success, otherwise the value is an error.
- */
-int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
-                word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("Ed25519Sign");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#if defined(HAVE_PK_CALLBACKS)
-    if (ssl->ctx->Ed25519SignCb) {
-        void* ctx = wolfSSL_GetEd25519SignCtx(ssl);
-        ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf,
-            keySz, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS */
-    {
-        ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("Ed25519Sign", ret);
-
-    return ret;
-}
-
-/* Verify the data using EdDSA and key using X25519.
- *
- * ssl    SSL object.
- * in     Signature data.
- * inSz   Length of the signature data in bytes.
- * msg    Message to verify.
- * outSz  Length of message in bytes.
- * key    The public X25519 key data.
- * keySz  The length of the private key data in bytes.
- * ctx    The callback context.
- * returns 0 on success, otherwise the value is an error.
- */
-int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
-                  word32 msgSz, ed25519_key* key, buffer* keyBufInfo)
-{
-    int ret;
-#ifdef HAVE_PK_CALLBACKS
-    const byte* keyBuf = NULL;
-    word32 keySz = 0;
-
-    if (keyBufInfo) {
-        keyBuf = keyBufInfo->buffer;
-        keySz = keyBufInfo->length;
-    }
-#endif
-
-    (void)ssl;
-    (void)keyBufInfo;
-
-    WOLFSSL_ENTER("Ed25519Verify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->Ed25519VerifyCb) {
-        void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl);
-        ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf,
-                                        keySz, &ssl->eccVerifyRes, ctx);
-    }
-    else
-#endif /* HAVE_PK_CALLBACKS  */
-    {
-        ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz,
-                                    &ssl->eccVerifyRes, key);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-    else
-#endif /* WOLFSSL_ASYNC_CRYPT */
-    {
-        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
-    }
-
-    WOLFSSL_LEAVE("Ed25519Verify", ret);
-
-    return ret;
-}
-#endif /* HAVE_ED25519 */
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef HAVE_CURVE25519
-#ifdef HAVE_PK_CALLBACKS
-    /* Gets X25519 key for shared secret callback testing
-     * Client side: returns peer key
-     * Server side: returns private key
-     */
-    static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey)
-    {
-        int ret = NO_PEER_KEY;
-        struct curve25519_key* tmpKey = NULL;
-
-        if (ssl == NULL || otherKey == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (ssl->options.side == WOLFSSL_CLIENT_END) {
-            if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent ||
-                                       !ssl->peerX25519Key->dp) {
-                return NO_PEER_KEY;
-            }
-            tmpKey = (struct curve25519_key*)ssl->peerX25519Key;
-        }
-        else if (ssl->options.side == WOLFSSL_SERVER_END) {
-            if (!ssl->eccTempKeyPresent) {
-                return NO_PRIVATE_KEY;
-            }
-            tmpKey = (struct curve25519_key*)ssl->eccTempKey;
-        }
-
-        if (tmpKey) {
-            *otherKey = (curve25519_key *)tmpKey;
-            ret = 0;
-        }
-
-        return ret;
-    }
-#endif /* HAVE_PK_CALLBACKS */
-
-static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
-        curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz,
-        byte* out, word32* outlen, int side)
-{
-    int ret;
-
-    (void)ssl;
-    (void)pubKeyDer;
-    (void)pubKeySz;
-    (void)side;
-
-    WOLFSSL_ENTER("X25519SharedSecret");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->X25519SharedSecretCb) {
-        curve25519_key* otherKey = NULL;
-
-        ret = X25519GetKey(ssl, &otherKey);
-        if (ret == 0) {
-            void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl);
-            ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer,
-                pubKeySz, out, outlen, side, ctx);
-        }
-    }
-    else
-#endif
-    {
-        ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
-                                             EC25519_LITTLE_ENDIAN);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("X25519SharedSecret", ret);
-
-    return ret;
-}
-
-static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
-        curve25519_key* peer)
-{
-    int ret = 0;
-
-    (void)peer;
-
-    WOLFSSL_ENTER("X25519MakeKey");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->X25519KeyGenCb) {
-        void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl);
-        ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx);
-    }
-    else
-#endif
-    {
-        ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
-    }
-
-    if (ret == 0) {
-        ssl->ecdhCurveOID = ECC_X25519_OID;
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("X25519MakeKey", ret);
-
-    return ret;
-}
-#endif /* HAVE_CURVE25519 */
-
-#if !defined(NO_CERTS) || !defined(NO_PSK)
-#if !defined(NO_DH)
-
-int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
-    byte* priv, word32* privSz,
-    byte* pub, word32* pubSz)
-{
-    int ret;
-
-    WOLFSSL_ENTER("DhGenKeyPair");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
-    if (ret != 0)
-        return ret;
-#endif
-
-    ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz);
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("DhGenKeyPair", ret);
-
-    return ret;
-}
-
-int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
-    const byte* priv, word32 privSz,
-    const byte* otherPub, word32 otherPubSz,
-    byte* agree, word32* agreeSz)
-{
-    int ret;
-
-    (void)ssl;
-
-    WOLFSSL_ENTER("DhAgree");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* initialize event */
-    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-    if (ssl->ctx->DhAgreeCb) {
-        void* ctx = wolfSSL_GetDhAgreeCtx(ssl);
-
-        WOLFSSL_MSG("Calling DhAgree Callback Function");
-        ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz,
-                    otherPub, otherPubSz, agree, agreeSz, ctx);
-    }
-    else
-#endif
-    {
-        ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub,
-                otherPubSz);
-    }
-
-    /* Handle async pending response */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    WOLFSSL_LEAVE("DhAgree", ret);
-
-    return ret;
-}
-#endif /* !NO_DH */
-#endif /* !NO_CERTS || !NO_PSK */
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-
-#ifdef HAVE_PK_CALLBACKS
-int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
-{
-    int pkcbset = 0;
-    (void)ctx;
-#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_RSA)
-    if (0
-    #ifdef HAVE_ECC
-        || ctx->EccSignCb != NULL
-    #endif
-    #ifdef HAVE_ED25519
-        || ctx->Ed25519SignCb != NULL
-    #endif
-    #ifndef NO_RSA
-        || ctx->RsaSignCb != NULL
-        || ctx->RsaDecCb != NULL
-        #ifdef WC_RSA_PSS
-        || ctx->RsaPssSignCb != NULL
-        #endif
-    #endif
-    ) {
-        pkcbset = 1;
-    }
-#endif
-    return pkcbset;
-}
-#endif /* HAVE_PK_CALLBACKS */
-
-/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
-   It is used during initialization and to switch an ssl's CTX with
-   wolfSSL_Set_SSL_CTX.  Requires ssl->suites alloc and ssl-arrays with PSK
-   unless writeDup is on.
-
-   ssl      object to initialize
-   ctx      parent factory
-   writeDup flag indicating this is a write dup only
-
-   WOLFSSL_SUCCESS return value on success */
-int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
-{
-    byte havePSK = 0;
-    byte haveAnon = 0;
-    byte newSSL;
-    byte haveRSA = 0;
-    byte haveMcast = 0;
-
-    (void)haveAnon; /* Squash unused var warnings */
-    (void)haveMcast;
-
-    if (!ssl || !ctx)
-        return BAD_FUNC_ARG;
-
-    if (ssl->suites == NULL && !writeDup)
-        return BAD_FUNC_ARG;
-
-    newSSL = ssl->ctx == NULL; /* Assign after null check */
-
-#ifndef NO_PSK
-    if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
-        return BAD_FUNC_ARG;  /* needed for copy below */
-    }
-#endif
-
-
-#ifndef NO_RSA
-    haveRSA = 1;
-#endif
-#ifndef NO_PSK
-    havePSK = ctx->havePSK;
-#endif /* NO_PSK */
-#ifdef HAVE_ANON
-    haveAnon = ctx->haveAnon;
-#endif /* HAVE_ANON*/
-#ifdef WOLFSSL_MULTICAST
-    haveMcast = ctx->haveMcast;
-#endif /* WOLFSSL_MULTICAST */
-
-    /* decrement previous CTX reference count if exists.
-     * This should only happen if switching ctxs!*/
-    if (!newSSL) {
-        WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx.");
-        wolfSSL_CTX_free(ssl->ctx);
-    }
-
-    /* increment CTX reference count */
-    if (wc_LockMutex(&ctx->countMutex) != 0) {
-        WOLFSSL_MSG("Couldn't lock CTX count mutex");
-        return BAD_MUTEX_E;
-    }
-    ctx->refCount++;
-    wc_UnLockMutex(&ctx->countMutex);
-    ssl->ctx     = ctx; /* only for passing to calls, options could change */
-    ssl->version = ctx->method->version;
-
-#ifdef HAVE_ECC
-    ssl->eccTempKeySz = ctx->eccTempKeySz;
-    ssl->ecdhCurveOID = ctx->ecdhCurveOID;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    ssl->pkCurveOID = ctx->pkCurveOID;
-#endif
-
-#ifdef OPENSSL_EXTRA
-    ssl->options.mask = ctx->mask;
-    ssl->CBIS         = ctx->CBIS;
-#endif
-    ssl->timeout = ctx->timeout;
-    ssl->verifyCallback    = ctx->verifyCallback;
-    ssl->options.side      = ctx->method->side;
-    ssl->options.downgrade    = ctx->method->downgrade;
-    ssl->options.minDowngrade = ctx->minDowngrade;
-
-    ssl->options.haveDH        = ctx->haveDH;
-    ssl->options.haveNTRU      = ctx->haveNTRU;
-    ssl->options.haveECDSAsig  = ctx->haveECDSAsig;
-    ssl->options.haveECC       = ctx->haveECC;
-    ssl->options.haveStaticECC = ctx->haveStaticECC;
-
-#ifndef NO_PSK
-    ssl->options.havePSK   = ctx->havePSK;
-    ssl->options.client_psk_cb = ctx->client_psk_cb;
-    ssl->options.server_psk_cb = ctx->server_psk_cb;
-#endif /* NO_PSK */
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz;
-#endif
-
-#ifdef HAVE_ANON
-    ssl->options.haveAnon = ctx->haveAnon;
-#endif
-#ifndef NO_DH
-    ssl->options.minDhKeySz = ctx->minDhKeySz;
-    ssl->options.maxDhKeySz = ctx->maxDhKeySz;
-#endif
-#ifndef NO_RSA
-    ssl->options.minRsaKeySz = ctx->minRsaKeySz;
-#endif
-#ifdef HAVE_ECC
-    ssl->options.minEccKeySz = ctx->minEccKeySz;
-#endif
-#ifdef OPENSSL_EXTRA
-    ssl->options.verifyDepth = ctx->verifyDepth;
-#endif
-
-    ssl->options.sessionCacheOff      = ctx->sessionCacheOff;
-    ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
-#ifdef HAVE_EXT_CACHE
-    ssl->options.internalCacheOff     = ctx->internalCacheOff;
-#endif
-
-    ssl->options.verifyPeer     = ctx->verifyPeer;
-    ssl->options.verifyNone     = ctx->verifyNone;
-    ssl->options.failNoCert     = ctx->failNoCert;
-    ssl->options.failNoCertxPSK = ctx->failNoCertxPSK;
-    ssl->options.sendVerify     = ctx->sendVerify;
-
-    ssl->options.partialWrite  = ctx->partialWrite;
-    ssl->options.quietShutdown = ctx->quietShutdown;
-    ssl->options.groupMessages = ctx->groupMessages;
-
-#ifndef NO_DH
-    ssl->buffers.serverDH_P = ctx->serverDH_P;
-    ssl->buffers.serverDH_G = ctx->serverDH_G;
-#endif
-
-#ifndef NO_CERTS
-    /* ctx still owns certificate, certChain, key, dh, and cm */
-    ssl->buffers.certificate = ctx->certificate;
-    ssl->buffers.certChain = ctx->certChain;
-#ifdef WOLFSSL_TLS13
-    ssl->buffers.certChainCnt = ctx->certChainCnt;
-#endif
-    ssl->buffers.key     = ctx->privateKey;
-    ssl->buffers.keyType = ctx->privateKeyType;
-    ssl->buffers.keySz   = ctx->privateKeySz;
-#endif
-#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                        !defined(NO_ED25519_CLIENT_AUTH)
-    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
-                                        ssl->buffers.keyType == ed25519_sa_algo;
-#endif
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ssl->devId = ctx->devId;
-#endif
-
-    if (writeDup == 0) {
-        int keySz = 0;
-#ifndef NO_CERTS
-        keySz = ssl->buffers.keySz;
-#endif
-
-#ifndef NO_PSK
-        if (ctx->server_hint[0]) {   /* set in CTX */
-            XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,
-                                    sizeof(ssl->arrays->server_hint));
-            ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
-        }
-#endif /* NO_PSK */
-
-        if (ctx->suites)
-            *ssl->suites = *ctx->suites;
-        else
-            XMEMSET(ssl->suites, 0, sizeof(Suites));
-
-        /* make sure server has DH parms, and add PSK if there, add NTRU too */
-        if (ssl->options.side == WOLFSSL_SERVER_END)
-            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       ssl->options.haveDH, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-        else
-            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       TRUE, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-
-#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
-        /* make sure server has cert and key unless using PSK, Anon, or
-         * Multicast. This should be true even if just switching ssl ctx */
-        if (ssl->options.side == WOLFSSL_SERVER_END &&
-                !havePSK && !haveAnon && !haveMcast) {
-
-            /* server certificate must be loaded */
-            if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) {
-                WOLFSSL_MSG("Server missing certificate");
-                return NO_PRIVATE_KEY;
-            }
-
-            /* allow no private key if using PK callbacks and CB is set */
-        #ifdef HAVE_PK_CALLBACKS
-            if (wolfSSL_CTX_IsPrivatePkSet(ctx)) {
-                WOLFSSL_MSG("Using PK for server private key");
-            }
-            else
-        #endif
-            if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
-                WOLFSSL_MSG("Server missing private key");
-                return NO_PRIVATE_KEY;
-            }
-        }
-#endif
-
-    }  /* writeDup check */
-
-#ifdef WOLFSSL_SESSION_EXPORT
-    #ifdef WOLFSSL_DTLS
-    ssl->dtls_export = ctx->dtls_export; /* export function for session */
-    #endif
-#endif
-
-    ssl->CBIORecv = ctx->CBIORecv;
-    ssl->CBIOSend = ctx->CBIOSend;
-#ifdef OPENSSL_EXTRA
-    ssl->readAhead = ctx->readAhead;
-#endif
-    ssl->verifyDepth = ctx->verifyDepth;
-
-    return WOLFSSL_SUCCESS;
-}
-
-int InitHandshakeHashes(WOLFSSL* ssl)
-{
-    int ret;
-
-    /* make sure existing handshake hashes are free'd */
-    if (ssl->hsHashes != NULL) {
-        FreeHandshakeHashes(ssl);
-    }
-
-    /* allocate handshake hashes */
-    ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
-                                                           DYNAMIC_TYPE_HASHES);
-    if (ssl->hsHashes == NULL) {
-        WOLFSSL_MSG("HS_Hashes Memory error");
-        return MEMORY_E;
-    }
-    XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes));
-
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
-    ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId);
-    if (ret != 0)
-        return ret;
-#endif
-#ifndef NO_SHA
-    ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId);
-    if (ret != 0)
-        return ret;
-#endif
-#endif /* !NO_OLD_TLS */
-#ifndef NO_SHA256
-    ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_SHA384
-    ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_SHA512
-    ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId);
-    if (ret != 0)
-        return ret;
-#endif
-
-    return ret;
-}
-
-void FreeHandshakeHashes(WOLFSSL* ssl)
-{
-    if (ssl->hsHashes) {
-#ifndef NO_OLD_TLS
-    #ifndef NO_MD5
-        wc_Md5Free(&ssl->hsHashes->hashMd5);
-    #endif
-    #ifndef NO_SHA
-        wc_ShaFree(&ssl->hsHashes->hashSha);
-    #endif
-#endif /* !NO_OLD_TLS */
-    #ifndef NO_SHA256
-        wc_Sha256Free(&ssl->hsHashes->hashSha256);
-    #endif
-    #ifdef WOLFSSL_SHA384
-        wc_Sha384Free(&ssl->hsHashes->hashSha384);
-    #endif
-    #ifdef WOLFSSL_SHA512
-        wc_Sha512Free(&ssl->hsHashes->hashSha512);
-    #endif
-    #if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
-        if (ssl->hsHashes->messages != NULL) {
-            XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
-            ssl->hsHashes->messages = NULL;
-         }
-    #endif
-
-        XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
-        ssl->hsHashes = NULL;
-    }
-}
-
-
-/* init everything to 0, NULL, default values before calling anything that may
-   fail so that destructor has a "good" state to cleanup
-
-   ssl      object to initialize
-   ctx      parent factory
-   writeDup flag indicating this is a write dup only
-
-   0 on success */
-int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
-{
-    int  ret;
-
-    XMEMSET(ssl, 0, sizeof(WOLFSSL));
-
-#if defined(WOLFSSL_STATIC_MEMORY)
-    if (ctx->heap != NULL) {
-        WOLFSSL_HEAP_HINT* ssl_hint;
-        WOLFSSL_HEAP_HINT* ctx_hint;
-
-        /* avoid derefrencing a test value */
-    #ifdef WOLFSSL_HEAP_TEST
-        if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) {
-            ssl->heap = ctx->heap;
-        }
-        else {
-    #endif
-        ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT),
-                                               ctx->heap, DYNAMIC_TYPE_SSL);
-        if (ssl->heap == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT));
-        ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
-        ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap));
-
-        /* lock and check IO count / handshake count */
-        if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
-            WOLFSSL_MSG("Bad memory_mutex lock");
-            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
-            ssl->heap = NULL; /* free and set to NULL for IO counter */
-            return BAD_MUTEX_E;
-        }
-        if (ctx_hint->memory->maxHa > 0 &&
-                           ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) {
-            WOLFSSL_MSG("At max number of handshakes for static memory");
-            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
-            ssl->heap = NULL; /* free and set to NULL for IO counter */
-            return MEMORY_E;
-        }
-
-        if (ctx_hint->memory->maxIO > 0 &&
-                           ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) {
-            WOLFSSL_MSG("At max number of IO allowed for static memory");
-            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
-            ssl->heap = NULL; /* free and set to NULL for IO counter */
-            return MEMORY_E;
-        }
-        ctx_hint->memory->curIO++;
-        ctx_hint->memory->curHa++;
-        ssl_hint->memory = ctx_hint->memory;
-        ssl_hint->haFlag = 1;
-        wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-
-        /* check if tracking stats */
-        if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) {
-            ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC(
-               sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL);
-            if (ssl_hint->stats == NULL) {
-                return MEMORY_E;
-            }
-            XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS));
-        }
-
-        /* check if using fixed IO buffers */
-        if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) {
-            if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
-                WOLFSSL_MSG("Bad memory_mutex lock");
-                return BAD_MUTEX_E;
-            }
-            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) {
-                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-                return MEMORY_E;
-            }
-            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) {
-                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-                return MEMORY_E;
-            }
-            if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) {
-                WOLFSSL_MSG("Not enough memory to create fixed IO buffers");
-                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-                return MEMORY_E;
-            }
-            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
-        }
-    #ifdef WOLFSSL_HEAP_TEST
-        }
-    #endif
-    }
-    else {
-        ssl->heap = ctx->heap;
-    }
-#else
-    ssl->heap = ctx->heap; /* carry over user heap without static memory */
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
-    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
-
-    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
-    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
-
-#ifdef KEEP_PEER_CERT
-    InitX509(&ssl->peerCert, 0, ssl->heap);
-#endif
-
-    ssl->rfd = -1;   /* set to invalid descriptor */
-    ssl->wfd = -1;
-    ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */
-
-    ssl->IOCB_ReadCtx  = &ssl->rfd;  /* prevent invalid pointer access if not */
-    ssl->IOCB_WriteCtx = &ssl->wfd;  /* correctly set */
-
-#ifdef HAVE_NETX
-    ssl->IOCB_ReadCtx  = &ssl->nxCtx;  /* default NetX IO ctx, same for read */
-    ssl->IOCB_WriteCtx = &ssl->nxCtx;  /* and write */
-#endif
-
-    /* initialize states */
-    ssl->options.serverState = NULL_STATE;
-    ssl->options.clientState = NULL_STATE;
-    ssl->options.connectState = CONNECT_BEGIN;
-    ssl->options.acceptState  = ACCEPT_BEGIN;
-    ssl->options.handShakeState  = NULL_STATE;
-    ssl->options.processReply = doProcessInit;
-    ssl->options.asyncState = TLS_ASYNC_BEGIN;
-    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
-    ssl->encrypt.state = CIPHER_STATE_BEGIN;
-    ssl->decrypt.state = CIPHER_STATE_BEGIN;
-
-#ifdef WOLFSSL_DTLS
-    #ifdef WOLFSSL_SCTP
-        ssl->options.dtlsSctp           = ctx->dtlsSctp;
-        ssl->dtlsMtuSz                  = ctx->dtlsMtuSz;
-        ssl->dtls_expected_rx           = ssl->dtlsMtuSz;
-    #else
-        ssl->dtls_expected_rx = MAX_MTU;
-    #endif
-    ssl->dtls_timeout_init              = DTLS_TIMEOUT_INIT;
-    ssl->dtls_timeout_max               = DTLS_TIMEOUT_MAX;
-    ssl->dtls_timeout                   = ssl->dtls_timeout_init;
-    ssl->buffers.dtlsCtx.rfd            = -1;
-    ssl->buffers.dtlsCtx.wfd            = -1;
-#endif
-
-    #ifndef NO_OLD_TLS
-        ssl->hmac = SSL_hmac; /* default to SSLv3 */
-    #elif !defined(WOLFSSL_NO_TLS12)
-        ssl->hmac = TLS_hmac;
-    #endif
-
-
-    ssl->cipher.ssl = ssl;
-
-#ifdef HAVE_EXTENDED_MASTER
-    ssl->options.haveEMS = ctx->haveEMS;
-#endif
-    ssl->options.useClientOrder = ctx->useClientOrder;
-
-#ifdef WOLFSSL_TLS13
-    #ifdef HAVE_SESSION_TICKET
-        ssl->options.noTicketTls13 = ctx->noTicketTls13;
-    #endif
-    ssl->options.noPskDheKe = ctx->noPskDheKe;
-    #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-        ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
-    #endif
-
-    if (ctx->numGroups > 0) {
-        XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups);
-        ssl->numGroups = ctx->numGroups;
-    }
-#endif
-
-#ifdef HAVE_TLS_EXTENSIONS
-#ifdef HAVE_MAX_FRAGMENT
-    ssl->max_fragment = MAX_RECORD_SIZE;
-#endif
-#ifdef HAVE_ALPN
-    ssl->alpn_client_list = NULL;
-    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-        ssl->alpnSelect    = ctx->alpnSelect;
-        ssl->alpnSelectArg = ctx->alpnSelectArg;
-    #endif
-#endif
-#ifdef HAVE_SUPPORTED_CURVES
-    ssl->options.userCurves = ctx->userCurves;
-#endif
-#endif /* HAVE_TLS_EXTENSIONS */
-
-    /* default alert state (none) */
-    ssl->alert_history.last_rx.code  = -1;
-    ssl->alert_history.last_rx.level = -1;
-    ssl->alert_history.last_tx.code  = -1;
-    ssl->alert_history.last_tx.level = -1;
-
-#ifdef OPENSSL_EXTRA
-    /* copy over application session context ID */
-    ssl->sessionCtxSz = ctx->sessionCtxSz;
-    XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
-    ssl->cbioFlag = ctx->cbioFlag;
-#endif
-
-    InitCiphers(ssl);
-    InitCipherSpecs(&ssl->specs);
-
-    /* all done with init, now can return errors, call other stuff */
-
-    if (!writeDup) {
-        /* arrays */
-        ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
-                                                           DYNAMIC_TYPE_ARRAYS);
-        if (ssl->arrays == NULL) {
-            WOLFSSL_MSG("Arrays Memory error");
-            return MEMORY_E;
-        }
-        XMEMSET(ssl->arrays, 0, sizeof(Arrays));
-        ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
-            DYNAMIC_TYPE_SECRET);
-        if (ssl->arrays->preMasterSecret == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
-
-        /* suites */
-        ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
-                                   DYNAMIC_TYPE_SUITES);
-        if (ssl->suites == NULL) {
-            WOLFSSL_MSG("Suites Memory error");
-            return MEMORY_E;
-        }
-    }
-
-    /* Initialize SSL with the appropriate fields from it's ctx */
-    /* requires valid arrays and suites unless writeDup ing */
-    if ((ret =  SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS)
-        return ret;
-
-    ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
-
-#ifdef SINGLE_THREADED
-    ssl->rng = ctx->rng;   /* CTX may have one, if so use it */
-#endif
-
-    if (ssl->rng == NULL) {
-        /* RNG */
-        ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
-        if (ssl->rng == NULL) {
-            WOLFSSL_MSG("RNG Memory error");
-            return MEMORY_E;
-        }
-        XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
-        ssl->options.weOwnRng = 1;
-
-        /* FIPS RNG API does not accept a heap hint */
-#ifndef HAVE_FIPS
-        if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) {
-            WOLFSSL_MSG("RNG Init error");
-            return ret;
-        }
-#else
-        if ( (ret = wc_InitRng(ssl->rng)) != 0) {
-            WOLFSSL_MSG("RNG Init error");
-            return ret;
-        }
-#endif
-    }
-
-#ifdef HAVE_WRITE_DUP
-    if (writeDup) {
-        /* all done */
-        return 0;
-    }
-#endif
-
-    /* hsHashes */
-    ret = InitHandshakeHashes(ssl);
-    if (ret != 0)
-        return ret;
-
-#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
-    if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
-        ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
-        if (ret != 0) {
-            WOLFSSL_MSG("DTLS Cookie Secret error");
-            return ret;
-        }
-    }
-#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
-
-#ifdef HAVE_SECRET_CALLBACK
-    ssl->sessionSecretCb  = NULL;
-    ssl->sessionSecretCtx = NULL;
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-    ssl->session.ticket = ssl->session.staticTicket;
-#endif
-
-#ifdef WOLFSSL_MULTICAST
-    if (ctx->haveMcast) {
-        int i;
-
-        ssl->options.haveMcast = 1;
-        ssl->options.mcastID = ctx->mcastID;
-
-        /* Force the state to look like handshake has completed. */
-        /* Keying material is supplied externally. */
-        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-        ssl->options.connectState = SECOND_REPLY_DONE;
-        ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
-        ssl->options.handShakeState = HANDSHAKE_DONE;
-        ssl->options.handShakeDone = 1;
-
-        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++)
-            ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID;
-    }
-#endif
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    /* use secure renegotiation by default (not recommend) */
-    #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
-        ret = wolfSSL_UseSecureRenegotiation(ssl);
-        if (ret != WOLFSSL_SUCCESS)
-            return ret;
-    #endif
-#endif
-
-    return 0;
-}
-
-
-/* free use of temporary arrays */
-void FreeArrays(WOLFSSL* ssl, int keep)
-{
-    if (ssl->arrays) {
-        if (keep) {
-            /* keeps session id for user retrieval */
-            XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
-            ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
-        }
-        if (ssl->arrays->preMasterSecret) {
-            XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
-            ssl->arrays->preMasterSecret = NULL;
-        }
-        XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
-        ssl->arrays->pendingMsg = NULL;
-        ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */
-    }
-    XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
-    ssl->arrays = NULL;
-}
-
-void FreeKey(WOLFSSL* ssl, int type, void** pKey)
-{
-    if (ssl && pKey && *pKey) {
-        switch (type) {
-        #ifndef NO_RSA
-            case DYNAMIC_TYPE_RSA:
-                wc_FreeRsaKey((RsaKey*)*pKey);
-                break;
-        #endif /* ! NO_RSA */
-        #ifdef HAVE_ECC
-            case DYNAMIC_TYPE_ECC:
-                wc_ecc_free((ecc_key*)*pKey);
-                break;
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            case DYNAMIC_TYPE_ED25519:
-                wc_ed25519_free((ed25519_key*)*pKey);
-                break;
-        #endif /* HAVE_CURVE25519 */
-        #ifdef HAVE_CURVE25519
-            case DYNAMIC_TYPE_CURVE25519:
-                wc_curve25519_free((curve25519_key*)*pKey);
-                break;
-        #endif /* HAVE_CURVE25519 */
-        #ifndef NO_DH
-            case DYNAMIC_TYPE_DH:
-                wc_FreeDhKey((DhKey*)*pKey);
-                break;
-        #endif /* !NO_DH */
-            default:
-                break;
-        }
-        XFREE(*pKey, ssl->heap, type);
-
-        /* Reset pointer */
-        *pKey = NULL;
-    }
-}
-
-int AllocKey(WOLFSSL* ssl, int type, void** pKey)
-{
-    int ret = BAD_FUNC_ARG;
-    int sz = 0;
-
-    if (ssl == NULL || pKey == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* Sanity check key destination */
-    if (*pKey != NULL) {
-        WOLFSSL_MSG("Key already present!");
-        return BAD_STATE_E;
-    }
-
-    /* Determine size */
-    switch (type) {
-    #ifndef NO_RSA
-        case DYNAMIC_TYPE_RSA:
-            sz = sizeof(RsaKey);
-            break;
-    #endif /* ! NO_RSA */
-    #ifdef HAVE_ECC
-        case DYNAMIC_TYPE_ECC:
-            sz = sizeof(ecc_key);
-            break;
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        case DYNAMIC_TYPE_ED25519:
-            sz = sizeof(ed25519_key);
-            break;
-    #endif /* HAVE_ED25519 */
-    #ifdef HAVE_CURVE25519
-        case DYNAMIC_TYPE_CURVE25519:
-            sz = sizeof(curve25519_key);
-            break;
-    #endif /* HAVE_CURVE25519 */
-    #ifndef NO_DH
-        case DYNAMIC_TYPE_DH:
-            sz = sizeof(DhKey);
-            break;
-    #endif /* !NO_DH */
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    if (sz == 0) {
-        return NOT_COMPILED_IN;
-    }
-
-    /* Allocate memeory for key */
-    *pKey = XMALLOC(sz, ssl->heap, type);
-    if (*pKey == NULL) {
-        return MEMORY_E;
-    }
-
-    /* Initialize key */
-    switch (type) {
-    #ifndef NO_RSA
-        case DYNAMIC_TYPE_RSA:
-            ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* ! NO_RSA */
-    #ifdef HAVE_ECC
-        case DYNAMIC_TYPE_ECC:
-            ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        case DYNAMIC_TYPE_ED25519:
-            wc_ed25519_init((ed25519_key*)*pKey);
-            ret = 0;
-            break;
-    #endif /* HAVE_CURVE25519 */
-    #ifdef HAVE_CURVE25519
-        case DYNAMIC_TYPE_CURVE25519:
-            wc_curve25519_init((curve25519_key*)*pKey);
-            ret = 0;
-            break;
-    #endif /* HAVE_CURVE25519 */
-    #ifndef NO_DH
-        case DYNAMIC_TYPE_DH:
-            ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* !NO_DH */
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    /* On error free handshake key */
-    if (ret != 0) {
-        FreeKey(ssl, type, pKey);
-    }
-
-    return ret;
-}
-
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
-    defined(HAVE_CURVE25519)
-static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
-{
-    int ret = 0;
-
-    (void)ssl;
-
-    switch (type) {
-    #ifndef NO_RSA
-        case DYNAMIC_TYPE_RSA:
-            wc_FreeRsaKey((RsaKey*)pKey);
-            ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* ! NO_RSA */
-    #ifdef HAVE_ECC
-        case DYNAMIC_TYPE_ECC:
-            wc_ecc_free((ecc_key*)pKey);
-            ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        case DYNAMIC_TYPE_ED25519:
-            wc_ed25519_free((ed25519_key*)pKey);
-            ret = wc_ed25519_init((ed25519_key*)pKey);
-            break;
-    #endif /* HAVE_CURVE25519 */
-    #ifdef HAVE_CURVE25519
-        case DYNAMIC_TYPE_CURVE25519:
-            wc_curve25519_free((curve25519_key*)pKey);
-            ret = wc_curve25519_init((curve25519_key*)pKey);
-            break;
-    #endif /* HAVE_CURVE25519 */
-    #ifndef NO_DH
-        case DYNAMIC_TYPE_DH:
-            wc_FreeDhKey((DhKey*)pKey);
-            ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId);
-            break;
-    #endif /* !NO_DH */
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    return ret;
-}
-#endif
-
-void FreeKeyExchange(WOLFSSL* ssl)
-{
-    /* Cleanup signature buffer */
-    if (ssl->buffers.sig.buffer) {
-        XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        ssl->buffers.sig.buffer = NULL;
-        ssl->buffers.sig.length = 0;
-    }
-
-    /* Cleanup digest buffer */
-    if (ssl->buffers.digest.buffer) {
-        XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST);
-        ssl->buffers.digest.buffer = NULL;
-        ssl->buffers.digest.length = 0;
-    }
-
-    /* Free handshake key */
-    FreeKey(ssl, ssl->hsType, &ssl->hsKey);
-
-#ifndef NO_DH
-    /* Free temp DH key */
-    FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key);
-#endif
-
-    /* Cleanup async */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ssl->async.freeArgs) {
-        ssl->async.freeArgs(ssl, ssl->async.args);
-        ssl->async.freeArgs = NULL;
-    }
-#endif
-}
-
-/* In case holding SSL object in array and don't want to free actual ssl */
-void SSL_ResourceFree(WOLFSSL* ssl)
-{
-    /* Note: any resources used during the handshake should be released in the
-     * function FreeHandshakeResources(). Be careful with the special cases
-     * like the RNG which may optionally be kept for the whole session. (For
-     * example with the RNG, it isn't used beyond the handshake except when
-     * using stream ciphers where it is retained. */
-
-    FreeCiphers(ssl);
-    FreeArrays(ssl, 0);
-    FreeKeyExchange(ssl);
-    if (ssl->options.weOwnRng) {
-        wc_FreeRng(ssl->rng);
-        XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
-    }
-    XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
-    FreeHandshakeHashes(ssl);
-    XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
-
-    /* clear keys struct after session */
-    ForceZero(&ssl->keys, sizeof(Keys));
-
-#ifndef NO_DH
-    if (ssl->buffers.serverDH_Priv.buffer) {
-        ForceZero(ssl->buffers.serverDH_Priv.buffer,
-                                             ssl->buffers.serverDH_Priv.length);
-    }
-    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
-    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    /* parameters (p,g) may be owned by ctx */
-    if (ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    }
-#endif /* !NO_DH */
-#ifndef NO_CERTS
-    ssl->keepCert = 0; /* make sure certificate is free'd */
-    wolfSSL_UnloadCertsKeys(ssl);
-#endif
-#ifndef NO_RSA
-    FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
-    ssl->peerRsaKeyPresent = 0;
-#endif
-    if (ssl->buffers.inputBuffer.dynamicFlag)
-        ShrinkInputBuffer(ssl, FORCED_FREE);
-    if (ssl->buffers.outputBuffer.dynamicFlag)
-        ShrinkOutputBuffer(ssl);
-#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
-    XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
-          DYNAMIC_TYPE_COOKIE_PWD);
-#endif
-#ifdef WOLFSSL_DTLS
-    DtlsMsgPoolReset(ssl);
-    if (ssl->dtls_rx_msg_list != NULL) {
-        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
-        ssl->dtls_rx_msg_list = NULL;
-        ssl->dtls_rx_msg_list_sz = 0;
-    }
-    XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
-    ssl->buffers.dtlsCtx.peer.sa = NULL;
-#ifndef NO_WOLFSSL_SERVER
-    XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
-          DYNAMIC_TYPE_COOKIE_PWD);
-#endif
-#endif /* WOLFSSL_DTLS */
-#ifdef OPENSSL_EXTRA
-    if (ssl->biord != ssl->biowr)        /* only free write if different */
-        wolfSSL_BIO_free(ssl->biowr);
-    wolfSSL_BIO_free(ssl->biord);        /* always free read bio */
-#endif
-#ifdef HAVE_LIBZ
-    FreeStreams(ssl);
-#endif
-#ifdef HAVE_ECC
-    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
-    ssl->peerEccKeyPresent = 0;
-    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
-    ssl->peerEccDsaKeyPresent = 0;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-    {
-        int dtype;
-    #ifdef HAVE_ECC
-        dtype = DYNAMIC_TYPE_ECC;
-    #endif
-    #ifdef HAVE_CURVE25519
-    #ifdef HAVE_ECC
-        if (ssl->peerX25519KeyPresent ||
-                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
-    #endif /* HAVE_ECC */
-         {
-            dtype = DYNAMIC_TYPE_CURVE25519;
-         }
-    #endif /* HAVE_CURVE25519 */
-        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
-        ssl->eccTempKeyPresent = 0;
-    }
-#endif /* HAVE_ECC || HAVE_CURVE25519 */
-#ifdef HAVE_CURVE25519
-    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
-    ssl->peerX25519KeyPresent = 0;
-#endif
-#ifdef HAVE_ED25519
-    FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
-    ssl->peerEd25519KeyPresent = 0;
-    #ifdef HAVE_PK_CALLBACKS
-        if (ssl->buffers.peerEd25519Key.buffer != NULL) {
-            XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
-                                                          DYNAMIC_TYPE_ED25519);
-            ssl->buffers.peerEd25519Key.buffer = NULL;
-        }
-    #endif
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    #ifdef HAVE_ECC
-        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
-    #endif /* HAVE_ECC */
-    #ifndef NO_RSA
-        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
-    #endif /* NO_RSA */
-#endif /* HAVE_PK_CALLBACKS */
-#ifdef HAVE_TLS_EXTENSIONS
-    TLSX_FreeAll(ssl->extensions, ssl->heap);
-
-#ifdef HAVE_ALPN
-    if (ssl->alpn_client_list != NULL) {
-        XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
-        ssl->alpn_client_list = NULL;
-    }
-#endif
-#endif /* HAVE_TLS_EXTENSIONS */
-#ifdef HAVE_NETX
-    if (ssl->nxCtx.nxPacket)
-        nx_packet_release(ssl->nxCtx.nxPacket);
-#endif
-#ifdef KEEP_PEER_CERT
-    FreeX509(&ssl->peerCert);
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->session.isDynamic) {
-        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        ssl->session.ticket = ssl->session.staticTicket;
-        ssl->session.isDynamic = 0;
-        ssl->session.ticketLen = 0;
-    }
-#endif
-#ifdef HAVE_EXT_CACHE
-    wolfSSL_SESSION_free(ssl->extSession);
-#endif
-#ifdef HAVE_WRITE_DUP
-    if (ssl->dupWrite) {
-        FreeWriteDup(ssl);
-    }
-#endif
-
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-    while (ssl->certReqCtx != NULL) {
-        CertReqCtx* curr = ssl->certReqCtx;
-        ssl->certReqCtx = curr->next;
-        XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#endif
-
-#ifdef WOLFSSL_STATIC_MEMORY
-    /* check if using fixed io buffers and free them */
-    if (ssl->heap != NULL) {
-    #ifdef WOLFSSL_HEAP_TEST
-    /* avoid dereferencing a test value */
-    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
-    #endif
-        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
-        WOLFSSL_HEAP*      ctx_heap;
-        void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
-
-        ctx_heap = ssl_hint->memory;
-        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
-            WOLFSSL_MSG("Bad memory_mutex lock");
-        }
-        ctx_heap->curIO--;
-        if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) {
-            WOLFSSL_MSG("Error freeing fixed output buffer");
-        }
-        if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) {
-            WOLFSSL_MSG("Error freeing fixed output buffer");
-        }
-        if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/
-            ctx_heap->curHa--;
-        }
-        wc_UnLockMutex(&(ctx_heap->memory_mutex));
-
-        /* check if tracking stats */
-        if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
-            XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
-        }
-        XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
-    #ifdef WOLFSSL_HEAP_TEST
-    }
-    #endif
-    }
-#endif /* WOLFSSL_STATIC_MEMORY */
-}
-
-/* Free any handshake resources no longer needed */
-void FreeHandshakeResources(WOLFSSL* ssl)
-{
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
-        WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
-        return;
-    }
-#endif
-
-    /* input buffer */
-    if (ssl->buffers.inputBuffer.dynamicFlag)
-        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
-
-    /* suites */
-    XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
-    ssl->suites = NULL;
-
-    /* hsHashes */
-    FreeHandshakeHashes(ssl);
-
-    /* RNG */
-    if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) {
-        if (ssl->options.weOwnRng) {
-            wc_FreeRng(ssl->rng);
-            XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
-            ssl->rng = NULL;
-            ssl->options.weOwnRng = 0;
-        }
-    }
-
-#ifdef WOLFSSL_DTLS
-    /* DTLS_POOL */
-    if (ssl->options.dtls) {
-        DtlsMsgPoolReset(ssl);
-        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
-        ssl->dtls_rx_msg_list = NULL;
-        ssl->dtls_rx_msg_list_sz = 0;
-    }
-#endif
-
-    /* arrays */
-    if (ssl->options.saveArrays == 0)
-        FreeArrays(ssl, 1);
-
-#ifndef NO_RSA
-    /* peerRsaKey */
-    FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
-    ssl->peerRsaKeyPresent = 0;
-#endif
-
-#ifdef HAVE_ECC
-    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
-    ssl->peerEccKeyPresent = 0;
-    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
-    ssl->peerEccDsaKeyPresent = 0;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-    {
-        int dtype;
-    #ifdef HAVE_ECC
-        dtype = DYNAMIC_TYPE_ECC;
-    #endif
-    #ifdef HAVE_CURVE25519
-    #ifdef HAVE_ECC
-        if (ssl->peerX25519KeyPresent ||
-                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
-    #endif /* HAVE_ECC */
-         {
-            dtype = DYNAMIC_TYPE_CURVE25519;
-         }
-    #endif /* HAVE_CURVE25519 */
-        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
-        ssl->eccTempKeyPresent = 0;
-    }
-#endif /* HAVE_ECC || HAVE_CURVE25519 */
-#ifdef HAVE_CURVE25519
-    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
-    ssl->peerX25519KeyPresent = 0;
-#endif
-#ifndef NO_DH
-    if (ssl->buffers.serverDH_Priv.buffer) {
-        ForceZero(ssl->buffers.serverDH_Priv.buffer,
-                                             ssl->buffers.serverDH_Priv.length);
-    }
-    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
-    ssl->buffers.serverDH_Priv.buffer = NULL;
-    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    ssl->buffers.serverDH_Pub.buffer = NULL;
-    /* parameters (p,g) may be owned by ctx */
-    if (ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        ssl->buffers.serverDH_G.buffer = NULL;
-        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        ssl->buffers.serverDH_P.buffer = NULL;
-    }
-#endif /* !NO_DH */
-#ifndef NO_CERTS
-    wolfSSL_UnloadCertsKeys(ssl);
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    #ifdef HAVE_ECC
-        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
-        ssl->buffers.peerEccDsaKey.buffer = NULL;
-    #endif /* HAVE_ECC */
-    #ifndef NO_RSA
-        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
-        ssl->buffers.peerRsaKey.buffer = NULL;
-    #endif /* NO_RSA */
-    #ifdef HAVE_ED25519
-        XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
-                                                          DYNAMIC_TYPE_ED25519);
-        ssl->buffers.peerEd25519Key.buffer = NULL;
-    #endif
-#endif /* HAVE_PK_CALLBACKS */
-
-#ifdef HAVE_QSH
-    QSH_FreeAll(ssl);
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->session.isDynamic) {
-        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        ssl->session.ticket = ssl->session.staticTicket;
-        ssl->session.isDynamic = 0;
-        ssl->session.ticketLen = 0;
-    }
-#endif
-
-#ifdef WOLFSSL_STATIC_MEMORY
-    /* when done with handshake decrement current handshake count */
-    if (ssl->heap != NULL) {
-    #ifdef WOLFSSL_HEAP_TEST
-    /* avoid dereferencing a test value */
-    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
-    #endif
-        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
-        WOLFSSL_HEAP*      ctx_heap;
-
-        ctx_heap = ssl_hint->memory;
-        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
-            WOLFSSL_MSG("Bad memory_mutex lock");
-        }
-        ctx_heap->curHa--;
-        ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */
-        wc_UnLockMutex(&(ctx_heap->memory_mutex));
-    #ifdef WOLFSSL_HEAP_TEST
-    }
-    #endif
-    }
-#endif /* WOLFSSL_STATIC_MEMORY */
-}
-
-
-/* heap argument is the heap hint used when creating SSL */
-void FreeSSL(WOLFSSL* ssl, void* heap)
-{
-    if (ssl->ctx) {
-        FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
-    }
-    SSL_ResourceFree(ssl);
-    XFREE(ssl, heap, DYNAMIC_TYPE_SSL);
-    (void)heap;
-}
-
-#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \
-    ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \
-     && defined(HAVE_AEAD))
-static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
-{
-    if (verify) {
-        seq[0] = ssl->keys.peer_sequence_number_hi;
-        seq[1] = ssl->keys.peer_sequence_number_lo++;
-        if (seq[1] > ssl->keys.peer_sequence_number_lo) {
-            /* handle rollover */
-            ssl->keys.peer_sequence_number_hi++;
-        }
-    }
-    else {
-        seq[0] = ssl->keys.sequence_number_hi;
-        seq[1] = ssl->keys.sequence_number_lo++;
-        if (seq[1] > ssl->keys.sequence_number_lo) {
-            /* handle rollover */
-            ssl->keys.sequence_number_hi++;
-        }
-    }
-}
-
-
-#ifdef WOLFSSL_DTLS
-static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
-{
-    if (order == PREV_ORDER) {
-        /* Previous epoch case */
-        if (ssl->options.haveMcast) {
-        #ifdef WOLFSSL_MULTICAST
-            seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
-                     (ssl->options.mcastID << 8) |
-                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFF);
-        #endif
-        }
-        else
-            seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
-                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
-        seq[1] = ssl->keys.dtls_prev_sequence_number_lo;
-    }
-    else if (order == PEER_ORDER) {
-        if (ssl->options.haveMcast) {
-        #ifdef WOLFSSL_MULTICAST
-            seq[0] = (ssl->keys.curEpoch << 16) |
-                     (ssl->keys.curPeerId << 8) |
-                     (ssl->keys.curSeq_hi & 0xFF);
-        #endif
-        }
-        else
-            seq[0] = (ssl->keys.curEpoch << 16) |
-                     (ssl->keys.curSeq_hi & 0xFFFF);
-        seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
-    }
-    else {
-        if (ssl->options.haveMcast) {
-        #ifdef WOLFSSL_MULTICAST
-            seq[0] = (ssl->keys.dtls_epoch << 16) |
-                     (ssl->options.mcastID << 8) |
-                     (ssl->keys.dtls_sequence_number_hi & 0xFF);
-        #endif
-        }
-        else
-            seq[0] = (ssl->keys.dtls_epoch << 16) |
-                     (ssl->keys.dtls_sequence_number_hi & 0xFFFF);
-        seq[1] = ssl->keys.dtls_sequence_number_lo;
-    }
-}
-
-static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
-{
-    word32 seq;
-
-    if (order == PREV_ORDER) {
-        seq = ssl->keys.dtls_prev_sequence_number_lo++;
-        if (seq > ssl->keys.dtls_prev_sequence_number_lo) {
-            /* handle rollover */
-            ssl->keys.dtls_prev_sequence_number_hi++;
-        }
-    }
-    else if (order == PEER_ORDER) {
-        seq = ssl->keys.peer_sequence_number_lo++;
-        if (seq > ssl->keys.peer_sequence_number_lo) {
-            /* handle rollover */
-            ssl->keys.peer_sequence_number_hi++;
-        }
-    }
-    else {
-        seq = ssl->keys.dtls_sequence_number_lo++;
-        if (seq > ssl->keys.dtls_sequence_number_lo) {
-            /* handle rollover */
-            ssl->keys.dtls_sequence_number_hi++;
-        }
-    }
-}
-#endif /* WOLFSSL_DTLS */
-
-
-static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
-{
-    word32 seq[2] = {0, 0};
-
-    if (!ssl->options.dtls) {
-        GetSEQIncrement(ssl, verifyOrder, seq);
-    }
-    else {
-#ifdef WOLFSSL_DTLS
-        DtlsGetSEQ(ssl, verifyOrder, seq);
-#endif
-    }
-
-    c32toa(seq[0], out);
-    c32toa(seq[1], out + OPAQUE32_LEN);
-}
-#endif
-
-#ifdef WOLFSSL_DTLS
-
-/* functions for managing DTLS datagram reordering */
-
-/* Need to allocate space for the handshake message header. The hashing
- * routines assume the message pointer is still within the buffer that
- * has the headers, and will include those headers in the hash. The store
- * routines need to take that into account as well. New will allocate
- * extra space for the headers. */
-DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
-{
-    DtlsMsg* msg = NULL;
-
-    (void)heap;
-    msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
-
-    if (msg != NULL) {
-        XMEMSET(msg, 0, sizeof(DtlsMsg));
-        msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
-                                                heap, DYNAMIC_TYPE_DTLS_BUFFER);
-        if (msg->buf != NULL) {
-            msg->sz = sz;
-            msg->type = no_shake;
-            msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
-        }
-        else {
-            XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG);
-            msg = NULL;
-        }
-    }
-
-    return msg;
-}
-
-void DtlsMsgDelete(DtlsMsg* item, void* heap)
-{
-    (void)heap;
-
-    if (item != NULL) {
-        DtlsFrag* cur = item->fragList;
-        while (cur != NULL) {
-            DtlsFrag* next = cur->next;
-            XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
-            cur = next;
-        }
-        if (item->buf != NULL)
-            XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
-        XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
-    }
-}
-
-
-void DtlsMsgListDelete(DtlsMsg* head, void* heap)
-{
-    DtlsMsg* next;
-    while (head) {
-        next = head->next;
-        DtlsMsgDelete(head, heap);
-        head = next;
-    }
-}
-
-
-/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
-static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
-                                byte* buf, word32* bytesLeft, void* heap)
-{
-    DtlsFrag* newFrag;
-    word32 added = end - *begin + 1;
-
-    (void)heap;
-    newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
-                                 DYNAMIC_TYPE_DTLS_FRAG);
-    if (newFrag != NULL) {
-        newFrag->next = NULL;
-        newFrag->begin = *begin;
-        newFrag->end = end;
-
-        XMEMCPY(buf + *begin, data, added);
-        *bytesLeft -= added;
-        *begin = newFrag->end + 1;
-    }
-
-    return newFrag;
-}
-
-
-int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
-                                   word32 fragOffset, word32 fragSz, void* heap)
-{
-    if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
-                                             (fragOffset + fragSz) <= msg->sz) {
-        DtlsFrag* cur = msg->fragList;
-        DtlsFrag* prev = cur;
-        DtlsFrag* newFrag;
-        word32 bytesLeft = fragSz; /* could be overlapping fragment */
-        word32 startOffset = fragOffset;
-        word32 added;
-
-        msg->seq = seq;
-        msg->type = type;
-
-        if (fragOffset == 0) {
-            XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
-                    DTLS_HANDSHAKE_HEADER_SZ);
-            c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
-        }
-
-        /* if no mesage data, just return */
-        if (fragSz == 0)
-            return 0;
-
-        /* if list is empty add full fragment to front */
-        if (cur == NULL) {
-            newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
-                                     msg->msg, &bytesLeft, heap);
-            if (newFrag == NULL)
-                return MEMORY_E;
-
-            msg->fragSz = fragSz;
-            msg->fragList = newFrag;
-
-            return 0;
-        }
-
-        /* add to front if before current front, up to next->begin */
-        if (fragOffset < cur->begin) {
-            word32 end = fragOffset + fragSz - 1;
-
-            if (end >= cur->begin)
-                end = cur->begin - 1;
-
-            added = end - fragOffset + 1;
-            newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
-                                     &bytesLeft, heap);
-            if (newFrag == NULL)
-                return MEMORY_E;
-
-            msg->fragSz += added;
-
-            newFrag->next = cur;
-            msg->fragList = newFrag;
-        }
-
-        /* while we have bytes left, try to find a gap to fill */
-        while (bytesLeft > 0) {
-            /* get previous packet in list */
-            while (cur && (fragOffset >= cur->begin)) {
-                prev = cur;
-                cur = cur->next;
-            }
-
-            /* don't add duplicate data */
-            if (prev->end >= fragOffset) {
-                if ( (fragOffset + bytesLeft - 1) <= prev->end)
-                    return 0;
-                fragOffset = prev->end + 1;
-                bytesLeft = startOffset + fragSz - fragOffset;
-            }
-
-            if (cur == NULL)
-                /* we're at the end */
-                added = bytesLeft;
-            else
-                /* we're in between two frames */
-                added = min(bytesLeft, cur->begin - fragOffset);
-
-            /* data already there */
-            if (added == 0)
-                continue;
-
-            newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
-                                     data + fragOffset - startOffset,
-                                     msg->msg, &bytesLeft, heap);
-            if (newFrag == NULL)
-                return MEMORY_E;
-
-            msg->fragSz += added;
-
-            newFrag->next = prev->next;
-            prev->next = newFrag;
-        }
-    }
-
-    return 0;
-}
-
-
-DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
-{
-    while (head != NULL && head->seq != seq) {
-        head = head->next;
-    }
-    return head;
-}
-
-
-void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data,
-        word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap)
-{
-    /* See if seq exists in the list. If it isn't in the list, make
-     * a new item of size dataSz, copy fragSz bytes from data to msg->msg
-     * starting at offset fragOffset, and add fragSz to msg->fragSz. If
-     * the seq is in the list and it isn't full, copy fragSz bytes from
-     * data to msg->msg starting at offset fragOffset, and add fragSz to
-     * msg->fragSz. Insertions take into account data already in the list
-     * in case there are overlaps in the handshake message due to retransmit
-     * messages. The new item should be inserted into the list in its
-     * proper position.
-     *
-     * 1. Find seq in list, or where seq should go in list. If seq not in
-     *    list, create new item and insert into list. Either case, keep
-     *    pointer to item.
-     * 2. Copy the data from the message to the stored message where it
-     *    belongs without overlaps.
-     */
-
-    DtlsMsg* head = ssl->dtls_rx_msg_list;
-
-    if (head != NULL) {
-        DtlsMsg* cur = DtlsMsgFind(head, seq);
-        if (cur == NULL) {
-            cur = DtlsMsgNew(dataSz, heap);
-            if (cur != NULL) {
-                if (DtlsMsgSet(cur, seq, data, type,
-                                                fragOffset, fragSz, heap) < 0) {
-                    DtlsMsgDelete(cur, heap);
-                }
-                else {
-                    ssl->dtls_rx_msg_list_sz++;
-                    head = DtlsMsgInsert(head, cur);
-                }
-            }
-        }
-        else {
-            /* If this fails, the data is just dropped. */
-            DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap);
-        }
-    }
-    else {
-        head = DtlsMsgNew(dataSz, heap);
-        if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) {
-            DtlsMsgDelete(head, heap);
-            head = NULL;
-        }
-        else {
-            ssl->dtls_rx_msg_list_sz++;
-        }
-    }
-
-    ssl->dtls_rx_msg_list = head;
-}
-
-
-/* DtlsMsgInsert() is an in-order insert. */
-DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
-{
-    if (head == NULL || item->seq < head->seq) {
-        item->next = head;
-        head = item;
-    }
-    else if (head->next == NULL) {
-        head->next = item;
-    }
-    else {
-        DtlsMsg* cur = head->next;
-        DtlsMsg* prev = head;
-        while (cur) {
-            if (item->seq < cur->seq) {
-                item->next = cur;
-                prev->next = item;
-                break;
-            }
-            prev = cur;
-            cur = cur->next;
-        }
-        if (cur == NULL) {
-            prev->next = item;
-        }
-    }
-
-    return head;
-}
-
-
-/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */
-int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz)
-{
-    DtlsMsg* item;
-    int ret = 0;
-
-    if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ)
-        return DTLS_POOL_SZ_E;
-
-    item = DtlsMsgNew(dataSz, ssl->heap);
-
-    if (item != NULL) {
-        DtlsMsg* cur = ssl->dtls_tx_msg_list;
-
-        XMEMCPY(item->buf, data, dataSz);
-        item->sz = dataSz;
-        item->seq = ssl->keys.dtls_epoch;
-
-        if (cur == NULL)
-            ssl->dtls_tx_msg_list = item;
-        else {
-            while (cur->next)
-                cur = cur->next;
-            cur->next = item;
-        }
-        ssl->dtls_tx_msg_list_sz++;
-    }
-    else
-        ret = MEMORY_E;
-
-    return ret;
-}
-
-
-/* DtlsMsgPoolTimeout() updates the timeout time. */
-int DtlsMsgPoolTimeout(WOLFSSL* ssl)
-{
-    int result = -1;
-    if (ssl->dtls_timeout <  ssl->dtls_timeout_max) {
-        ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
-        result = 0;
-    }
-    return result;
-}
-
-
-/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout
- * value. */
-void DtlsMsgPoolReset(WOLFSSL* ssl)
-{
-    if (ssl->dtls_tx_msg_list) {
-        DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap);
-        ssl->dtls_tx_msg_list = NULL;
-        ssl->dtls_tx_msg_list_sz = 0;
-        ssl->dtls_timeout = ssl->dtls_timeout_init;
-    }
-}
-
-
-int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset)
-{
-    /**
-     * only the first message from previous flight should be valid
-     * to be used for triggering retransmission of whole DtlsMsgPool.
-     * change cipher suite type is not verified here
-     */
-    return ((fragOffset == 0) &&
-           (((ssl->options.side == WOLFSSL_SERVER_END) &&
-             ((type == client_hello) ||
-             ((ssl->options.verifyPeer) && (type == certificate)) ||
-             ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) ||
-            ((ssl->options.side == WOLFSSL_CLIENT_END) &&
-             (type == server_hello))));
-}
-
-
-/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is
- * updated with new sequence numbers, and will be re-encrypted if needed. */
-int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
-{
-    int ret = 0;
-    DtlsMsg* pool = ssl->dtls_tx_msg_list;
-
-    if (pool != NULL) {
-
-        while (pool != NULL) {
-            if (pool->seq == 0) {
-                DtlsRecordLayerHeader* dtls;
-                int epochOrder;
-
-                dtls = (DtlsRecordLayerHeader*)pool->buf;
-                /* If the stored record's epoch is 0, and the currently set
-                 * epoch is 0, use the "current order" sequence number.
-                 * If the stored record's epoch is 0 and the currently set
-                 * epoch is not 0, the stored record is considered a "previous
-                 * order" sequence number. */
-                epochOrder = (ssl->keys.dtls_epoch == 0) ?
-                             CUR_ORDER : PREV_ORDER;
-
-                WriteSEQ(ssl, epochOrder, dtls->sequence_number);
-                DtlsSEQIncrement(ssl, epochOrder);
-                if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0)
-                    return ret;
-
-                XMEMCPY(ssl->buffers.outputBuffer.buffer,
-                        pool->buf, pool->sz);
-                ssl->buffers.outputBuffer.idx = 0;
-                ssl->buffers.outputBuffer.length = pool->sz;
-            }
-            else if (pool->seq == ssl->keys.dtls_epoch) {
-                byte*  input;
-                byte*  output;
-                int    inputSz, sendSz;
-
-                input = pool->buf;
-                inputSz = pool->sz;
-                sendSz = inputSz + MAX_MSG_EXTRA;
-
-                if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-                    return ret;
-
-                output = ssl->buffers.outputBuffer.buffer +
-                         ssl->buffers.outputBuffer.length;
-                sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
-                                      handshake, 0, 0, 0);
-                if (sendSz < 0)
-                    return BUILD_MSG_ERROR;
-
-                ssl->buffers.outputBuffer.length += sendSz;
-            }
-
-            ret = SendBuffered(ssl);
-            if (ret < 0) {
-                return ret;
-            }
-
-            /**
-             * on server side, retranmission is being triggered only by sending
-             * first message of given flight, in order to trigger client
-             * to retransmit its whole flight. Sending the whole previous flight
-             * could lead to retranmission of previous client flight for each
-             * server message from previous flight. Therefore one message should
-             * be enough to do the trick.
-             */
-            if (sendOnlyFirstPacket &&
-                ssl->options.side == WOLFSSL_SERVER_END) {
-
-                pool = NULL;
-            }
-            else
-                pool = pool->next;
-        }
-    }
-
-    return ret;
-}
-
-#endif /* WOLFSSL_DTLS */
-
-#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-
-ProtocolVersion MakeSSLv3(void)
-{
-    ProtocolVersion pv;
-    pv.major = SSLv3_MAJOR;
-    pv.minor = SSLv3_MINOR;
-
-    return pv;
-}
-
-#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
-
-
-#ifdef WOLFSSL_DTLS
-
-ProtocolVersion MakeDTLSv1(void)
-{
-    ProtocolVersion pv;
-    pv.major = DTLS_MAJOR;
-    pv.minor = DTLS_MINOR;
-
-    return pv;
-}
-
-#ifndef WOLFSSL_NO_TLS12
-
-ProtocolVersion MakeDTLSv1_2(void)
-{
-    ProtocolVersion pv;
-    pv.major = DTLS_MAJOR;
-    pv.minor = DTLSv1_2_MINOR;
-
-    return pv;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#endif /* WOLFSSL_DTLS */
-
-
-
-
-#if defined(USER_TICKS)
-#if 0
-    word32 LowResTimer(void)
-    {
-        /*
-        write your own clock tick function if don't want time(0)
-        needs second accuracy but doesn't have to correlated to EPOCH
-        */
-    }
-#endif
-
-#elif defined(TIME_OVERRIDES)
-
-    /* use same asn time overrides unless user wants tick override above */
-
-    #ifndef HAVE_TIME_T_TYPE
-        typedef long time_t;
-    #endif
-    extern time_t XTIME(time_t * timer);
-
-    word32 LowResTimer(void)
-    {
-        return (word32) XTIME(0);
-    }
-
-#elif defined(USE_WINDOWS_API)
-
-    word32 LowResTimer(void)
-    {
-        static int           init = 0;
-        static LARGE_INTEGER freq;
-        LARGE_INTEGER        count;
-
-        if (!init) {
-            QueryPerformanceFrequency(&freq);
-            init = 1;
-        }
-
-        QueryPerformanceCounter(&count);
-
-        return (word32)(count.QuadPart / freq.QuadPart);
-    }
-
-#elif defined(HAVE_RTP_SYS)
-
-    #include "rtptime.h"
-
-    word32 LowResTimer(void)
-    {
-        return (word32)rtp_get_system_sec();
-    }
-
-
-#elif defined(MICRIUM)
-
-    word32 LowResTimer(void)
-    {
-        OS_TICK ticks = 0;
-        OS_ERR  err;
-
-        ticks = OSTimeGet(&err);
-
-        return (word32) (ticks / OSCfg_TickRate_Hz);
-    }
-
-
-#elif defined(MICROCHIP_TCPIP_V5)
-
-    word32 LowResTimer(void)
-    {
-        return (word32) (TickGet() / TICKS_PER_SECOND);
-    }
-
-
-#elif defined(MICROCHIP_TCPIP)
-
-    #if defined(MICROCHIP_MPLAB_HARMONY)
-
-        #include <system/tmr/sys_tmr.h>
-
-        word32 LowResTimer(void)
-        {
-            return (word32) (SYS_TMR_TickCountGet() /
-                             SYS_TMR_TickCounterFrequencyGet());
-        }
-
-    #else
-
-        word32 LowResTimer(void)
-        {
-            return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet());
-        }
-
-    #endif
-
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-
-    word32 LowResTimer(void)
-    {
-        TIME_STRUCT mqxTime;
-
-        _time_get_elapsed(&mqxTime);
-
-        return (word32) mqxTime.SECONDS;
-    }
-#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
-
-    #include "include/task.h"
-
-    unsigned int LowResTimer(void)
-    {
-        return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
-    }
-
-#elif defined(FREESCALE_KSDK_BM)
-
-    #include "lwip/sys.h" /* lwIP */
-    word32 LowResTimer(void)
-    {
-        return sys_now()/1000;
-    }
-
-#elif defined(WOLFSSL_TIRTOS)
-
-    word32 LowResTimer(void)
-    {
-        return (word32) Seconds_get();
-    }
-#elif defined(WOLFSSL_XILINX)
-    #include "xrtcpsu.h"
-
-    word32 LowResTimer(void)
-    {
-        XRtcPsu_Config* con;
-        XRtcPsu         rtc;
-
-        con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
-        if (con != NULL) {
-            if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr)
-                    == XST_SUCCESS) {
-                return (word32)XRtcPsu_GetCurrentTime(&rtc);
-            }
-            else {
-                WOLFSSL_MSG("Unable to initialize RTC");
-            }
-        }
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_UTASKER)
-
-    word32 LowResTimer(void)
-    {
-        return (word32)(uTaskerSystemTick / TICK_RESOLUTION);
-    }
-
-#elif defined(WOLFSSL_NUCLEUS_1_2)
-
-    #define NU_TICKS_PER_SECOND 100
-
-    word32 LowResTimer(void)
-    {
-        /* returns number of 10ms ticks, so 100 ticks/sec */
-        return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND;
-    }
-
-#else
-    /* Posix style time */
-    #ifndef USER_TIME
-    #include <time.h>
-    #endif
-
-    word32 LowResTimer(void)
-    {
-        return (word32)XTIME(0);
-    }
-#endif
-#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-/* Store the message for use with CertificateVerify using Ed25519.
- *
- * ssl   SSL/TLS object.
- * data  Message to store.
- * sz    Size of message to store.
- * returns MEMORY_E if not able to reallocate, otherwise 0.
- */
-static int Ed25519Update(WOLFSSL* ssl, const byte* data, int sz)
-{
-    int   ret = 0;
-    byte* msgs;
-
-    if (ssl->options.cacheMessages) {
-        msgs = (byte*)XREALLOC(ssl->hsHashes->messages,
-                                                ssl->hsHashes->length + sz,
-                                                ssl->heap, DYNAMIC_TYPE_HASHES);
-        if (msgs == NULL)
-            ret = MEMORY_E;
-        if (ret == 0) {
-            ssl->hsHashes->messages = msgs;
-            XMEMCPY(msgs + ssl->hsHashes->length, data, sz);
-            ssl->hsHashes->prevLen = ssl->hsHashes->length;
-            ssl->hsHashes->length += sz;
-        }
-    }
-
-    return ret;
-}
-#endif /* HAVE_ED25519 && !WOLFSSL_NO_CLIENT_AUTH */
-
-#ifndef NO_CERTS
-int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
-{
-    int ret = 0;
-
-    (void)output;
-    (void)sz;
-
-    if (ssl->hsHashes == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef HAVE_FUZZER
-    if (ssl->fuzzerCb)
-        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
-#endif
-#ifndef NO_OLD_TLS
-    #ifndef NO_SHA
-        wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
-    #endif
-    #ifndef NO_MD5
-        wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
-    #endif
-#endif /* NO_OLD_TLS */
-
-    if (IsAtLeastTLSv1_2(ssl)) {
-    #ifndef NO_SHA256
-        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-        ret = Ed25519Update(ssl, output, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    }
-
-    return ret;
-}
-#endif /* NO_CERTS */
-
-
-/* add output to md5 and sha handshake hashes, exclude record header */
-int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
-{
-    int ret = 0;
-    const byte* adj;
-
-    adj = output + RECORD_HEADER_SZ + ivSz;
-    sz -= RECORD_HEADER_SZ;
-
-#ifdef HAVE_FUZZER
-    if (ssl->fuzzerCb)
-        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
-#endif
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        adj += DTLS_RECORD_EXTRA;
-        sz  -= DTLS_RECORD_EXTRA;
-    }
-#endif
-#ifndef NO_OLD_TLS
-    #ifndef NO_SHA
-        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
-    #endif
-    #ifndef NO_MD5
-        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
-    #endif
-#endif
-
-    if (IsAtLeastTLSv1_2(ssl)) {
-    #ifndef NO_SHA256
-        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-        ret = Ed25519Update(ssl, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    }
-
-    return ret;
-}
-
-
-/* add input to md5 and sha handshake hashes, include handshake header */
-int HashInput(WOLFSSL* ssl, const byte* input, int sz)
-{
-    int ret = 0;
-    const byte* adj;
-
-    adj = input - HANDSHAKE_HEADER_SZ;
-    sz += HANDSHAKE_HEADER_SZ;
-
-    (void)adj;
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        adj -= DTLS_HANDSHAKE_EXTRA;
-        sz  += DTLS_HANDSHAKE_EXTRA;
-    }
-#endif
-
-    if (ssl->hsHashes == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef NO_OLD_TLS
-    #ifndef NO_SHA
-        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
-    #endif
-    #ifndef NO_MD5
-        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
-    #endif
-#endif
-
-    if (IsAtLeastTLSv1_2(ssl)) {
-    #ifndef NO_SHA256
-        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-        ret = Ed25519Update(ssl, adj, sz);
-        if (ret != 0)
-            return ret;
-    #endif
-    }
-
-    return ret;
-}
-
-
-/* add record layer header for message */
-static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl)
-{
-    RecordLayerHeader* rl;
-
-    /* record layer header */
-    rl = (RecordLayerHeader*)output;
-    if (rl == NULL) {
-        return;
-    }
-    rl->type    = type;
-    rl->pvMajor = ssl->version.major;       /* type and version same in each */
-#ifdef WOLFSSL_TLS13
-    if (IsAtLeastTLSv1_3(ssl->version)) {
-#ifdef WOLFSSL_TLS13_DRAFT_18
-        rl->pvMinor = TLSv1_MINOR;
-#else
-        rl->pvMinor = TLSv1_2_MINOR;
-#endif
-    }
-    else
-#endif
-        rl->pvMinor = ssl->version.minor;
-
-#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE
-    if (ssl->options.side == WOLFSSL_CLIENT_END
-    &&  ssl->options.connectState == CONNECT_BEGIN
-    && !ssl->options.resuming) {
-        rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade
-                                             : ssl->version.minor;
-    }
-#endif
-
-    if (!ssl->options.dtls) {
-        c16toa((word16)length, rl->length);
-    }
-    else {
-#ifdef WOLFSSL_DTLS
-        DtlsRecordLayerHeader* dtls;
-
-        /* dtls record layer header extensions */
-        dtls = (DtlsRecordLayerHeader*)output;
-        WriteSEQ(ssl, 0, dtls->sequence_number);
-        c16toa((word16)length, dtls->length);
-#endif
-    }
-}
-
-
-#if !defined(WOLFSSL_NO_TLS12) || defined(HAVE_SESSION_TICKET)
-/* add handshake header for message */
-static void AddHandShakeHeader(byte* output, word32 length,
-                               word32 fragOffset, word32 fragLength,
-                               byte type, WOLFSSL* ssl)
-{
-    HandShakeHeader* hs;
-    (void)fragOffset;
-    (void)fragLength;
-    (void)ssl;
-
-    /* handshake header */
-    hs = (HandShakeHeader*)output;
-    if (hs == NULL)
-        return;
-
-    hs->type = type;
-    c32to24(length, hs->length);         /* type and length same for each */
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        DtlsHandShakeHeader* dtls;
-
-        /* dtls handshake header extensions */
-        dtls = (DtlsHandShakeHeader*)output;
-        c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
-        c32to24(fragOffset, dtls->fragment_offset);
-        c32to24(fragLength, dtls->fragment_length);
-    }
-#endif
-}
-
-/* add both headers for handshake message */
-static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
-{
-    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
-    word32 outputAdj = RECORD_HEADER_SZ;
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        lengthAdj += DTLS_HANDSHAKE_EXTRA;
-        outputAdj += DTLS_RECORD_EXTRA;
-    }
-#endif
-
-    AddRecordHeader(output, length + lengthAdj, handshake, ssl);
-    AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
-}
-#endif /* !WOLFSSL_NO_TLS12 || HAVE_SESSION_TICKET */
-
-
-#ifndef WOLFSSL_NO_TLS12
-#ifndef NO_CERTS
-static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
-                           word32 length, byte type, WOLFSSL* ssl)
-{
-    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
-    word32 outputAdj = RECORD_HEADER_SZ;
-    (void)fragSz;
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        lengthAdj += DTLS_HANDSHAKE_EXTRA;
-        outputAdj += DTLS_RECORD_EXTRA;
-    }
-#endif
-
-    AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl);
-    AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
-}
-#endif /* NO_CERTS */
-#endif /* !WOLFSSL_NO_TLS12 */
-
-
-/* return bytes received, -1 on error */
-static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
-{
-    int recvd;
-
-    if (ssl->CBIORecv == NULL) {
-        WOLFSSL_MSG("Your IO Recv callback is null, please set");
-        return -1;
-    }
-
-retry:
-    recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
-    if (recvd < 0)
-        switch (recvd) {
-            case WOLFSSL_CBIO_ERR_GENERAL:        /* general/unknown error */
-                return -1;
-
-            case WOLFSSL_CBIO_ERR_WANT_READ:      /* want read, would block */
-                return WANT_READ;
-
-            case WOLFSSL_CBIO_ERR_CONN_RST:       /* connection reset */
-                #ifdef USE_WINDOWS_API
-                if (ssl->options.dtls) {
-                    goto retry;
-                }
-                #endif
-                ssl->options.connReset = 1;
-                return -1;
-
-            case WOLFSSL_CBIO_ERR_ISR:            /* interrupt */
-                /* see if we got our timeout */
-                #ifdef WOLFSSL_CALLBACKS
-                    if (ssl->toInfoOn) {
-                        struct itimerval timeout;
-                        getitimer(ITIMER_REAL, &timeout);
-                        if (timeout.it_value.tv_sec == 0 &&
-                                                timeout.it_value.tv_usec == 0) {
-                            XSTRNCPY(ssl->timeoutInfo.timeoutName,
-                                    "recv() timeout", MAX_TIMEOUT_NAME_SZ);
-                            ssl->timeoutInfo.timeoutName[
-                                MAX_TIMEOUT_NAME_SZ] = '\0';
-
-                            WOLFSSL_MSG("Got our timeout");
-                            return WANT_READ;
-                        }
-                    }
-                #endif
-                goto retry;
-
-            case WOLFSSL_CBIO_ERR_CONN_CLOSE:     /* peer closed connection */
-                ssl->options.isClosed = 1;
-                return -1;
-
-            #ifdef WOLFSSL_DTLS
-            case WOLFSSL_CBIO_ERR_TIMEOUT:
-                if (IsDtlsNotSctpMode(ssl) &&
-                    !ssl->options.handShakeDone &&
-                    DtlsMsgPoolTimeout(ssl) == 0 &&
-                    DtlsMsgPoolSend(ssl, 0) == 0) {
-
-                    goto retry;
-                }
-                return -1;
-            #endif
-
-            default:
-                return recvd;
-        }
-
-    return recvd;
-}
-
-
-/* Switch dynamic output buffer back to static, buffer is assumed clear */
-void ShrinkOutputBuffer(WOLFSSL* ssl)
-{
-    WOLFSSL_MSG("Shrinking output buffer\n");
-    XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset,
-          ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
-    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
-    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
-    ssl->buffers.outputBuffer.dynamicFlag = 0;
-    ssl->buffers.outputBuffer.offset      = 0;
-}
-
-
-/* Switch dynamic input buffer back to static, keep any remaining input */
-/* forced free means cleaning up */
-void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
-{
-    int usedLength = ssl->buffers.inputBuffer.length -
-                     ssl->buffers.inputBuffer.idx;
-    if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
-        return;
-
-    WOLFSSL_MSG("Shrinking input buffer\n");
-
-    if (!forcedFree && usedLength > 0)
-        XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
-               ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
-               usedLength);
-
-    XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
-          ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
-    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
-    ssl->buffers.inputBuffer.dynamicFlag = 0;
-    ssl->buffers.inputBuffer.offset      = 0;
-    ssl->buffers.inputBuffer.idx = 0;
-    ssl->buffers.inputBuffer.length = usedLength;
-}
-
-int SendBuffered(WOLFSSL* ssl)
-{
-    if (ssl->CBIOSend == NULL) {
-        WOLFSSL_MSG("Your IO Send callback is null, please set");
-        return SOCKET_ERROR_E;
-    }
-
-#ifdef WOLFSSL_DEBUG_TLS
-    if (ssl->buffers.outputBuffer.idx == 0) {
-        WOLFSSL_MSG("Data to send");
-        WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer,
-                       ssl->buffers.outputBuffer.length);
-    }
-#endif
-
-    while (ssl->buffers.outputBuffer.length > 0) {
-        int sent = ssl->CBIOSend(ssl,
-                                      (char*)ssl->buffers.outputBuffer.buffer +
-                                      ssl->buffers.outputBuffer.idx,
-                                      (int)ssl->buffers.outputBuffer.length,
-                                      ssl->IOCB_WriteCtx);
-        if (sent < 0) {
-            switch (sent) {
-
-                case WOLFSSL_CBIO_ERR_WANT_WRITE:        /* would block */
-                    return WANT_WRITE;
-
-                case WOLFSSL_CBIO_ERR_CONN_RST:          /* connection reset */
-                    ssl->options.connReset = 1;
-                    break;
-
-                case WOLFSSL_CBIO_ERR_ISR:               /* interrupt */
-                    /* see if we got our timeout */
-                    #ifdef WOLFSSL_CALLBACKS
-                        if (ssl->toInfoOn) {
-                            struct itimerval timeout;
-                            getitimer(ITIMER_REAL, &timeout);
-                            if (timeout.it_value.tv_sec == 0 &&
-                                                timeout.it_value.tv_usec == 0) {
-                                XSTRNCPY(ssl->timeoutInfo.timeoutName,
-                                        "send() timeout", MAX_TIMEOUT_NAME_SZ);
-                                ssl->timeoutInfo.timeoutName[
-                                    MAX_TIMEOUT_NAME_SZ] = '\0';
-
-                                WOLFSSL_MSG("Got our timeout");
-                                return WANT_WRITE;
-                            }
-                        }
-                    #endif
-                    continue;
-
-                case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
-                    ssl->options.connReset = 1;  /* treat same as reset */
-                    break;
-
-                default:
-                    return SOCKET_ERROR_E;
-            }
-
-            return SOCKET_ERROR_E;
-        }
-
-        if (sent > (int)ssl->buffers.outputBuffer.length) {
-            WOLFSSL_MSG("SendBuffered() out of bounds read");
-            return SEND_OOB_READ_E;
-        }
-
-        ssl->buffers.outputBuffer.idx += sent;
-        ssl->buffers.outputBuffer.length -= sent;
-    }
-
-    ssl->buffers.outputBuffer.idx = 0;
-
-    if (ssl->buffers.outputBuffer.dynamicFlag)
-        ShrinkOutputBuffer(ssl);
-
-    return 0;
-}
-
-
-/* Grow the output buffer */
-static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
-{
-    byte* tmp;
-#if WOLFSSL_GENERAL_ALIGNMENT > 0
-    byte  hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
-                                      RECORD_HEADER_SZ;
-    byte align = WOLFSSL_GENERAL_ALIGNMENT;
-#else
-    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
-#endif
-
-#if WOLFSSL_GENERAL_ALIGNMENT > 0
-    /* the encrypted data will be offset from the front of the buffer by
-       the header, if the user wants encrypted alignment they need
-       to define their alignment requirement */
-
-    if (align) {
-       while (align < hdrSz)
-           align *= 2;
-    }
-#endif
-
-    tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align,
-                             ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
-    WOLFSSL_MSG("growing output buffer\n");
-
-    if (tmp == NULL)
-        return MEMORY_E;
-
-#if WOLFSSL_GENERAL_ALIGNMENT > 0
-    if (align)
-        tmp += align - hdrSz;
-#endif
-
-    if (ssl->buffers.outputBuffer.length)
-        XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
-               ssl->buffers.outputBuffer.length);
-
-    if (ssl->buffers.outputBuffer.dynamicFlag)
-        XFREE(ssl->buffers.outputBuffer.buffer -
-              ssl->buffers.outputBuffer.offset, ssl->heap,
-              DYNAMIC_TYPE_OUT_BUFFER);
-    ssl->buffers.outputBuffer.dynamicFlag = 1;
-
-#if WOLFSSL_GENERAL_ALIGNMENT > 0
-    if (align)
-        ssl->buffers.outputBuffer.offset = align - hdrSz;
-    else
-#endif
-        ssl->buffers.outputBuffer.offset = 0;
-
-    ssl->buffers.outputBuffer.buffer = tmp;
-    ssl->buffers.outputBuffer.bufferSize = size +
-                                           ssl->buffers.outputBuffer.length;
-    return 0;
-}
-
-
-/* Grow the input buffer, should only be to read cert or big app data */
-int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
-{
-    byte* tmp;
-#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
-    byte  align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
-    byte  hdrSz = DTLS_RECORD_HEADER_SZ;
-#else
-    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
-#endif
-
-#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
-    /* the encrypted data will be offset from the front of the buffer by
-       the dtls record header, if the user wants encrypted alignment they need
-       to define their alignment requirement. in tls we read record header
-       to get size of record and put actual data back at front, so don't need */
-
-    if (align) {
-       while (align < hdrSz)
-           align *= 2;
-    }
-#endif
-
-    if (usedLength < 0 || size < 0) {
-        WOLFSSL_MSG("GrowInputBuffer() called with negative number");
-        return BAD_FUNC_ARG;
-    }
-
-    tmp = (byte*)XMALLOC(size + usedLength + align,
-                             ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-    WOLFSSL_MSG("growing input buffer\n");
-
-    if (tmp == NULL)
-        return MEMORY_E;
-
-#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
-    if (align)
-        tmp += align - hdrSz;
-#endif
-
-    if (usedLength)
-        XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
-                    ssl->buffers.inputBuffer.idx, usedLength);
-
-    if (ssl->buffers.inputBuffer.dynamicFlag)
-        XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
-              ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
-
-    ssl->buffers.inputBuffer.dynamicFlag = 1;
-#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
-    if (align)
-        ssl->buffers.inputBuffer.offset = align - hdrSz;
-    else
-#endif
-        ssl->buffers.inputBuffer.offset = 0;
-
-    ssl->buffers.inputBuffer.buffer = tmp;
-    ssl->buffers.inputBuffer.bufferSize = size + usedLength;
-    ssl->buffers.inputBuffer.idx    = 0;
-    ssl->buffers.inputBuffer.length = usedLength;
-
-    return 0;
-}
-
-
-/* check available size into output buffer, make room if needed */
-int CheckAvailableSize(WOLFSSL *ssl, int size)
-{
-    if (size < 0) {
-        WOLFSSL_MSG("CheckAvailableSize() called with negative number");
-        return BAD_FUNC_ARG;
-    }
-
-    if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
-                                             < (word32)size) {
-        if (GrowOutputBuffer(ssl, size) < 0)
-            return MEMORY_E;
-    }
-
-    return 0;
-}
-
-
-/* do all verify and sanity checks on record header */
-static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                           RecordLayerHeader* rh, word16 *size)
-{
-    if (!ssl->options.dtls) {
-#ifdef HAVE_FUZZER
-        if (ssl->fuzzerCb)
-            ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD,
-                    ssl->fuzzerCtx);
-#endif
-        XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
-        *inOutIdx += RECORD_HEADER_SZ;
-        ato16(rh->length, size);
-    }
-    else {
-#ifdef WOLFSSL_DTLS
-#ifdef HAVE_FUZZER
-        if (ssl->fuzzerCb)
-            ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
-                           FUZZ_HEAD, ssl->fuzzerCtx);
-#endif
-        /* type and version in same sport */
-        XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
-        *inOutIdx += ENUM_LEN + VERSION_SZ;
-        ato16(input + *inOutIdx, &ssl->keys.curEpoch);
-        *inOutIdx += OPAQUE16_LEN;
-        if (ssl->options.haveMcast) {
-        #ifdef WOLFSSL_MULTICAST
-            ssl->keys.curPeerId = input[*inOutIdx];
-            ssl->keys.curSeq_hi = input[*inOutIdx+1];
-        #endif
-        }
-        else
-            ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
-        *inOutIdx += OPAQUE16_LEN;
-        ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
-        *inOutIdx += OPAQUE32_LEN;  /* advance past rest of seq */
-        ato16(input + *inOutIdx, size);
-        *inOutIdx += LENGTH_SZ;
-#endif
-    }
-
-#ifdef WOLFSSL_DTLS
-    if (IsDtlsNotSctpMode(ssl) &&
-        (!DtlsCheckWindow(ssl) ||
-         (ssl->options.handShakeDone && ssl->keys.curEpoch == 0))) {
-            return SEQUENCE_ERROR;
-    }
-#endif
-
-    /* catch version mismatch */
-#ifndef WOLFSSL_TLS13
-    if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor)
-#else
-    if (rh->pvMajor != ssl->version.major ||
-        (rh->pvMinor != ssl->version.minor &&
-#ifdef WOLFSSL_TLS13_DRAFT_18
-         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR)
-#else
-         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR)
-#endif
-        ))
-#endif
-    {
-        if (ssl->options.side == WOLFSSL_SERVER_END &&
-            ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE)
-
-            WOLFSSL_MSG("Client attempting to connect with different version");
-        else if (ssl->options.side == WOLFSSL_CLIENT_END &&
-                                 ssl->options.downgrade &&
-                                 ssl->options.connectState < FIRST_REPLY_DONE)
-            WOLFSSL_MSG("Server attempting to accept with different version");
-        else if (ssl->options.dtls && rh->type == handshake)
-            /* Check the DTLS handshake message RH version later. */
-            WOLFSSL_MSG("DTLS handshake, skip RH version number check");
-        else {
-            WOLFSSL_MSG("SSL version error");
-            return VERSION_ERROR;              /* only use requested version */
-        }
-    }
-
-    /* record layer length check */
-#ifdef HAVE_MAX_FRAGMENT
-    if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
-        SendAlert(ssl, alert_fatal, record_overflow);
-        return LENGTH_ERROR;
-    }
-#else
-    if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
-        return LENGTH_ERROR;
-#endif
-
-    /* verify record type here as well */
-    switch (rh->type) {
-        case handshake:
-        case change_cipher_spec:
-        case application_data:
-        case alert:
-            break;
-        case no_type:
-        default:
-            WOLFSSL_MSG("Unknown Record Type");
-            return UNKNOWN_RECORD_TYPE;
-    }
-
-    /* haven't decrypted this record yet */
-    ssl->keys.decryptedCur = 0;
-
-    return 0;
-}
-
-#ifndef WOLFSSL_NO_TLS12
-static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                              byte *type, word32 *size, word32 totalSz)
-{
-    const byte *ptr = input + *inOutIdx;
-    (void)ssl;
-
-    *inOutIdx += HANDSHAKE_HEADER_SZ;
-    if (*inOutIdx > totalSz)
-        return BUFFER_E;
-
-    *type = ptr[0];
-    c24to32(&ptr[1], size);
-
-    return 0;
-}
-#endif
-
-#ifdef WOLFSSL_DTLS
-static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
-                                  word32* inOutIdx, byte *type, word32 *size,
-                                  word32 *fragOffset, word32 *fragSz,
-                                  word32 totalSz)
-{
-    word32 idx = *inOutIdx;
-
-    *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
-    if (*inOutIdx > totalSz)
-        return BUFFER_E;
-
-    *type = input[idx++];
-    c24to32(input + idx, size);
-    idx += OPAQUE24_LEN;
-
-    ato16(input + idx, &ssl->keys.dtls_peer_handshake_number);
-    idx += DTLS_HANDSHAKE_SEQ_SZ;
-
-    c24to32(input + idx, fragOffset);
-    idx += DTLS_HANDSHAKE_FRAG_SZ;
-    c24to32(input + idx, fragSz);
-
-    if (ssl->curRL.pvMajor != ssl->version.major ||
-        ssl->curRL.pvMinor != ssl->version.minor) {
-
-        if (*type != client_hello && *type != hello_verify_request)
-            return VERSION_ERROR;
-        else {
-            WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version");
-        }
-    }
-    return 0;
-}
-#endif
-
-
-#if !defined(NO_OLD_TLS) || \
-    (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1))
-/* fill with MD5 pad size since biggest required */
-static const byte PAD1[PAD_MD5] =
-                              { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
-                              };
-static const byte PAD2[PAD_MD5] =
-                              { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
-                              };
-#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */
-
-#ifndef NO_OLD_TLS
-
-/* calculate MD5 hash for finished */
-#ifdef WOLFSSL_TI_HASH
-#include <wolfssl/wolfcrypt/hash.h>
-#endif
-
-static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
-{
-    int ret;
-    byte md5_result[WC_MD5_DIGEST_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
-    if (md5 == NULL)
-        return MEMORY_E;
-#else
-    wc_Md5  md5[1];
-#endif
-
-    /* make md5 inner */
-    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5);
-    if (ret == 0)
-        ret = wc_Md5Update(md5, sender, SIZEOF_SENDER);
-    if (ret == 0)
-        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
-    if (ret == 0)
-        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
-    if (ret == 0)
-        ret = wc_Md5Final(md5, md5_result);
-
-    /* make md5 outer */
-    if (ret == 0) {
-        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
-        if (ret == 0) {
-            ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
-            if (ret == 0)
-                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
-            if (ret == 0)
-                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
-            if (ret == 0)
-                ret = wc_Md5Final(md5, hashes->md5);
-            wc_Md5Free(md5);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    return ret;
-}
-
-
-/* calculate SHA hash for finished */
-static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
-{
-    int ret;
-    byte sha_result[WC_SHA_DIGEST_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
-    if (sha == NULL)
-        return MEMORY_E;
-#else
-    wc_Sha  sha[1];
-#endif
-    /* make sha inner */
-    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
-    if (ret == 0)
-        ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER);
-    if (ret == 0)
-        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
-    if (ret == 0)
-        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
-    if (ret == 0)
-        ret = wc_ShaFinal(sha, sha_result);
-
-    /* make sha outer */
-    if (ret == 0) {
-        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
-        if (ret == 0) {
-            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
-            if (ret == 0)
-                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
-            if (ret == 0)
-                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
-            if (ret == 0)
-                ret = wc_ShaFinal(sha, hashes->sha);
-            wc_ShaFree(sha);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    return ret;
-}
-#endif
-
-#ifndef WOLFSSL_NO_TLS12
-
-/* Finished doesn't support SHA512, not SHA512 cipher suites yet */
-static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
-{
-    int ret = 0;
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-#ifndef NO_TLS
-    if (ssl->options.tls) {
-        ret = BuildTlsFinished(ssl, hashes, sender);
-    }
-#endif
-#ifndef NO_OLD_TLS
-    if (!ssl->options.tls) {
-        ret = BuildMD5(ssl, hashes, sender);
-        if (ret == 0) {
-            ret = BuildSHA(ssl, hashes, sender);
-        }
-    }
-#endif
-
-    return ret;
-}
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
-    /* cipher requirements */
-    enum {
-        REQUIRES_RSA,
-        REQUIRES_DHE,
-        REQUIRES_ECC,
-        REQUIRES_ECC_STATIC,
-        REQUIRES_PSK,
-        REQUIRES_NTRU,
-        REQUIRES_RSA_SIG
-    };
-
-
-
-    /* Does this cipher suite (first, second) have the requirement
-       an ephemeral key exchange will still require the key for signing
-       the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */
-    static int CipherRequires(byte first, byte second, int requirement)
-    {
-
-        (void)requirement;
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef HAVE_CHACHA
-        if (first == CHACHA_BYTE) {
-
-        switch (second) {
-        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-        case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-
-        case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-
-        case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-
-        case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-            }
-        }
-#endif /* HAVE_CHACHA */
-
-        /* ECC extensions */
-        if (first == ECC_BYTE) {
-
-        switch (second) {
-#ifdef HAVE_ECC
-    #ifndef NO_RSA
-        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-
-    #ifndef NO_DES3
-        case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-    #endif /* !NO_DES3 */
-
-    #ifndef NO_RC4
-        case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-    #endif /* !NO_RC4 */
-    #endif /* NO_RSA */
-
-    #ifndef NO_DES3
-        case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-    #endif /* !NO_DES3  */
-    #ifndef NO_RC4
-        case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-    #endif /* !NO_RC4 */
-    #ifndef NO_RSA
-        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-    #endif /* !NO_RSA */
-
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-#endif /* HAVE_ECC */
-
-#ifndef NO_RSA
-    #ifdef HAVE_ECC
-        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_AESCCM
-        case TLS_RSA_WITH_AES_128_CCM_8 :
-        case TLS_RSA_WITH_AES_256_CCM_8 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            break;
-    #endif /* HAVE_AESCCM */
-    #ifdef HAVE_ECC
-
-        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
-        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
-        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-    #endif /* HAVE_ECC */
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
-        case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
-        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
-        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            if (requirement == REQUIRES_ECC_STATIC)
-                return 1;
-            break;
-#endif /* HAVE_ECC */
-
-#ifndef NO_PSK
-        case TLS_PSK_WITH_AES_128_CCM:
-        case TLS_PSK_WITH_AES_256_CCM:
-        case TLS_PSK_WITH_AES_128_CCM_8:
-        case TLS_PSK_WITH_AES_256_CCM_8:
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-
-        case TLS_DHE_PSK_WITH_AES_128_CCM:
-        case TLS_DHE_PSK_WITH_AES_256_CCM:
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-#endif /* !NO_PSK */
-#ifdef HAVE_ECC
-        case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
-            if (requirement == REQUIRES_ECC)
-                return 1;
-            break;
-
-        case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-
-        case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-#endif /* HAVE_ECC */
-        default:
-            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
-            return 0;
-        }   /* switch */
-        }   /* if     */
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-        /* Distinct TLS v1.3 cipher suites with cipher and digest only. */
-        if (first == TLS13_BYTE) {
-
-            switch (second) {
-#ifdef WOLFSSL_TLS13
-            case TLS_AES_128_GCM_SHA256:
-            case TLS_AES_256_GCM_SHA384:
-            case TLS_CHACHA20_POLY1305_SHA256:
-            case TLS_AES_128_CCM_SHA256:
-            case TLS_AES_128_CCM_8_SHA256:
-                break;
-#endif
-
-            default:
-                WOLFSSL_MSG("Unsupported cipher suite, CipherRequires "
-                            "TLS v1.3");
-                return 0;
-            }
-        }
-
-#ifndef WOLFSSL_NO_TLS12
-
-        if (first != ECC_BYTE && first != CHACHA_BYTE &&
-            first != TLS13_BYTE) {   /* normal suites */
-        switch (second) {
-
-#ifndef NO_RSA
-    #ifndef NO_RC4
-        case SSL_RSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case SSL_RSA_WITH_RC4_128_MD5 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-    #endif /* NO_RC4 */
-
-        case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-    #ifdef HAVE_NTRU
-        case TLS_NTRU_RSA_WITH_RC4_128_SHA :
-            if (requirement == REQUIRES_NTRU)
-                return 1;
-            break;
-    #endif /* HAVE_NTRU */
-
-        case TLS_RSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_RSA_WITH_AES_128_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-    #ifdef HAVE_NTRU
-        case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
-            if (requirement == REQUIRES_NTRU)
-                return 1;
-            break;
-    #endif /* HAVE_NTRU */
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-    #ifdef HAVE_NTRU
-        case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_NTRU)
-                return 1;
-            break;
-    #endif /* HAVE_NTRU */
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_RSA_WITH_NULL_SHA :
-        case TLS_RSA_WITH_NULL_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-    #ifdef HAVE_NTRU
-        case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_NTRU)
-                return 1;
-            break;
-    #endif /* HAVE_NTRU */
-
-    #ifdef HAVE_IDEA
-        case SSL_RSA_WITH_IDEA_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-    #endif /* HAVE_IDEA */
-#endif /* !NO_RSA */
-
-#ifndef NO_PSK
-        case TLS_PSK_WITH_AES_128_GCM_SHA256 :
-        case TLS_PSK_WITH_AES_256_GCM_SHA384 :
-        case TLS_PSK_WITH_AES_128_CBC_SHA256 :
-        case TLS_PSK_WITH_AES_256_CBC_SHA384 :
-        case TLS_PSK_WITH_AES_128_CBC_SHA :
-        case TLS_PSK_WITH_AES_256_CBC_SHA :
-        case TLS_PSK_WITH_NULL_SHA384 :
-        case TLS_PSK_WITH_NULL_SHA256 :
-        case TLS_PSK_WITH_NULL_SHA :
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-
-        case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
-        case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
-        case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
-        case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
-        case TLS_DHE_PSK_WITH_NULL_SHA384 :
-        case TLS_DHE_PSK_WITH_NULL_SHA256 :
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            if (requirement == REQUIRES_PSK)
-                return 1;
-            break;
-#endif /* NO_PSK */
-
-#ifndef NO_RSA
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-#ifndef NO_HC128
-        case TLS_RSA_WITH_HC_128_MD5 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_RSA_WITH_HC_128_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_RSA_WITH_HC_128_B2B256:
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-#endif /* NO_HC128 */
-
-#ifdef HAVE_BLAKE2
-        case TLS_RSA_WITH_AES_128_CBC_B2B256:
-        case TLS_RSA_WITH_AES_256_CBC_B2B256:
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-#endif /* HAVE_BLAKE2 */
-
-#ifndef NO_RABBIT
-        case TLS_RSA_WITH_RABBIT_SHA :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-#endif /* !NO_RABBIT */
-
-        case TLS_RSA_WITH_AES_128_GCM_SHA256 :
-        case TLS_RSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
-        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-
-#ifdef HAVE_CAMELLIA
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            break;
-
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-#endif /* HAVE_CAMELLIA */
-
-        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            if (requirement == REQUIRES_RSA)
-                return 1;
-            if (requirement == REQUIRES_RSA_SIG)
-                return 1;
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-#endif
-#ifdef HAVE_ANON
-        case TLS_DH_anon_WITH_AES_128_CBC_SHA :
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-        case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
-            if (requirement == REQUIRES_DHE)
-                return 1;
-            break;
-#endif
-#ifdef WOLFSSL_MULTICAST
-        case WDM_WITH_NULL_SHA256 :
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires");
-            return 0;
-        }  /* switch */
-        }  /* if ECC / Normal suites else */
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-        return 0;
-    }
-
-#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
-
-
-#ifndef NO_CERTS
-
-
-/* Match names with wildcards, each wildcard can represent a single name
-   component or fragment but not mulitple names, i.e.,
-   *.z.com matches y.z.com but not x.y.z.com
-
-   return 1 on success */
-int MatchDomainName(const char* pattern, int len, const char* str)
-{
-    int ret = 0;
-    char p, s;
-
-    if (pattern == NULL || str == NULL || len <= 0)
-        return 0;
-
-    while (len > 0) {
-
-        p = (char)XTOLOWER((unsigned char)*pattern++);
-        if (p == '\0')
-            break;
-
-        if (p == '*') {
-            while (--len > 0 &&
-                (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') {
-            }
-
-            if (len == 0)
-                p = '\0';
-
-            while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') {
-                if (s == p)
-                    break;
-                if (s == '.')
-                    return 0;
-                str++;
-            }
-        }
-        else {
-            if (p != (char)XTOLOWER((unsigned char) *str))
-                return 0;
-        }
-
-
-        if (len > 0) {
-            str++;
-            len--;
-        }
-    }
-
-    if (*str == '\0' && len == 0) {
-        ret = 1; /* success */
-    }
-
-    return ret;
-}
-
-
-/* try to find an altName match to domain, return 1 on success */
-int CheckAltNames(DecodedCert* dCert, char* domain)
-{
-    int        match = 0;
-    DNS_entry* altName = NULL;
-
-    WOLFSSL_MSG("Checking AltNames");
-
-    if (dCert)
-        altName = dCert->altNames;
-
-    while (altName) {
-        WOLFSSL_MSG("\tindividual AltName check");
-
-        if (MatchDomainName(altName->name, altName->len, domain)){
-            match = 1;
-            break;
-        }
-
-        altName = altName->next;
-    }
-
-    return match;
-}
-
-
-#ifdef OPENSSL_EXTRA
-/* Check that alternative names, if they exists, match the domain.
- * Fail if there are wild patterns and they didn't match.
- * Check the common name if no alternative names matched.
- *
- * dCert    Decoded cert to get the alternative names from.
- * domain   Domain name to compare against.
- * checkCN  Whether to check the common name.
- * returns whether there was a problem in matching.
- */
-static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN)
-{
-    int        match;
-    DNS_entry* altName = NULL;
-
-    WOLFSSL_MSG("Checking AltNames");
-
-    if (dCert)
-        altName = dCert->altNames;
-
-    *checkCN = altName == NULL;
-    match = 0;
-    while (altName) {
-        WOLFSSL_MSG("\tindividual AltName check");
-
-        if (MatchDomainName(altName->name, altName->len, domain)) {
-            match = 1;
-            *checkCN = 0;
-            break;
-        }
-        /* No matches and wild pattern match failed. */
-        else if (altName->name[0] == '*' && match == 0)
-            match = -1;
-
-        altName = altName->next;
-    }
-
-    return match != -1;
-}
-
-/* Check the domain name matches the subject alternative name or the subject
- * name.
- *
- * dcert          Decoded certificate.
- * domainName     The domain name.
- * domainNameLen  The length of the domain name.
- * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success.
- */
-int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen)
-{
-    int checkCN;
-
-    /* Assume name is NUL terminated. */
-    (void)domainNameLen;
-
-    if (CheckForAltNames(dCert, domainName, &checkCN) == 0) {
-        WOLFSSL_MSG("DomainName match on alt names failed too");
-        return DOMAIN_NAME_MISMATCH;
-    }
-    if (checkCN == 1) {
-        if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
-                            domainName) == 0) {
-            WOLFSSL_MSG("DomainName match on common name failed");
-            return DOMAIN_NAME_MISMATCH;
-        }
-    }
-
-    return 0;
-}
-#endif
-
-#ifdef SESSION_CERTS
-static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
-    byte* certBuf, word32 certSz)
-{
-   if (chain->count < MAX_CHAIN_DEPTH &&
-                               certSz < MAX_X509_SIZE) {
-        chain->certs[chain->count].length = certSz;
-        XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz);
-        chain->count++;
-    }
-    else {
-        WOLFSSL_MSG("Couldn't store chain cert for session");
-    }
-}
-#endif
-
-#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
-    defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Copy parts X509 needs from Decoded cert, 0 on success */
-int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
-{
-    int ret = 0;
-
-    if (x509 == NULL || dCert == NULL ||
-        dCert->subjectCNLen < 0)
-        return BAD_FUNC_ARG;
-
-    x509->version = dCert->version + 1;
-
-    XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX);
-    x509->issuer.name[ASN_NAME_MAX - 1] = '\0';
-    x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1;
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    if (dCert->issuerName.fullName != NULL) {
-        XMEMCPY(&x509->issuer.fullName,
-                                       &dCert->issuerName, sizeof(DecodedName));
-        x509->issuer.fullName.fullName = (char*)XMALLOC(
-                        dCert->issuerName.fullNameLen, x509->heap,
-                        DYNAMIC_TYPE_X509);
-        if (x509->issuer.fullName.fullName != NULL)
-            XMEMCPY(x509->issuer.fullName.fullName,
-                     dCert->issuerName.fullName, dCert->issuerName.fullNameLen);
-    }
-    x509->issuer.x509 = x509;
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-    XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX);
-    x509->subject.name[ASN_NAME_MAX - 1] = '\0';
-    x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1;
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    if (dCert->subjectName.fullName != NULL) {
-        XMEMCPY(&x509->subject.fullName,
-                                      &dCert->subjectName, sizeof(DecodedName));
-        x509->subject.fullName.fullName = (char*)XMALLOC(
-                 dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509);
-        if (x509->subject.fullName.fullName != NULL)
-            XMEMCPY(x509->subject.fullName.fullName,
-                   dCert->subjectName.fullName, dCert->subjectName.fullNameLen);
-    }
-    x509->subject.x509 = x509;
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    XMEMCPY(x509->subject.raw, dCert->subjectRaw, dCert->subjectRawLen);
-    x509->subject.rawLen = dCert->subjectRawLen;
-#endif
-
-    XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE);
-    x509->serialSz = dCert->serialSz;
-    if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) {
-        XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen);
-        x509->subjectCN[dCert->subjectCNLen] = '\0';
-    }
-    else
-        x509->subjectCN[0] = '\0';
-
-#ifdef WOLFSSL_SEP
-    {
-        int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
-        if (minSz > 0) {
-            x509->deviceTypeSz = minSz;
-            XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
-        }
-        else
-            x509->deviceTypeSz = 0;
-        minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
-        if (minSz > 0) {
-            x509->hwTypeSz = minSz;
-            XMEMCPY(x509->hwType, dCert->hwType, minSz);
-        }
-        else
-            x509->hwTypeSz = 0;
-        minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
-        if (minSz > 0) {
-            x509->hwSerialNumSz = minSz;
-            XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
-        }
-        else
-            x509->hwSerialNumSz = 0;
-    }
-#endif /* WOLFSSL_SEP */
-    {
-        int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ);
-        if (minSz > 0) {
-            x509->notBeforeSz = minSz;
-            XMEMCPY(x509->notBefore, dCert->beforeDate, minSz);
-        }
-        else
-            x509->notBeforeSz = 0;
-        minSz = min(dCert->afterDateLen, MAX_DATE_SZ);
-        if (minSz > 0) {
-            x509->notAfterSz = minSz;
-            XMEMCPY(x509->notAfter, dCert->afterDate, minSz);
-        }
-        else
-            x509->notAfterSz = 0;
-    }
-
-    if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
-        x509->pubKey.buffer = (byte*)XMALLOC(
-                        dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        if (x509->pubKey.buffer != NULL) {
-            x509->pubKeyOID = dCert->keyOID;
-            x509->pubKey.length = dCert->pubKeySize;
-            XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize);
-        }
-        else
-            ret = MEMORY_E;
-    }
-
-    if (dCert->signature != NULL && dCert->sigLength != 0 &&
-            dCert->sigLength <= MAX_ENCODED_SIG_SZ) {
-        x509->sig.buffer = (byte*)XMALLOC(
-                          dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE);
-        if (x509->sig.buffer == NULL) {
-            ret = MEMORY_E;
-        }
-        else {
-            XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength);
-            x509->sig.length = dCert->sigLength;
-            x509->sigOID = dCert->signatureOID;
-        }
-    }
-
-    /* store cert for potential retrieval */
-    if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) {
-        XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx);
-    }
-    else {
-        ret = MEMORY_E;
-    }
-
-    x509->altNames       = dCert->altNames;
-    dCert->weOwnAltNames = 0;
-    x509->altNamesNext   = x509->altNames;  /* index hint */
-
-#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
-    !defined(IGNORE_NAME_CONSTRAINTS)
-    /* add copies of alternate emails from dCert to X509 */
-    if (dCert->altEmailNames != NULL) {
-        DNS_entry* cur = dCert->altEmailNames;
-
-        while (cur != NULL) {
-            if (cur->type == ASN_RFC822_TYPE) {
-                DNS_entry* dnsEntry;
-                int strLen = cur->len;
-
-                dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap,
-                                        DYNAMIC_TYPE_ALTNAME);
-                if (dnsEntry == NULL) {
-                    WOLFSSL_MSG("\tOut of Memory");
-                    return MEMORY_E;
-                }
-
-                dnsEntry->type = ASN_RFC822_TYPE;
-                dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap,
-                                         DYNAMIC_TYPE_ALTNAME);
-                if (dnsEntry->name == NULL) {
-                    WOLFSSL_MSG("\tOut of Memory");
-                    XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME);
-                    return MEMORY_E;
-                }
-                dnsEntry->len = strLen;
-                XMEMCPY(dnsEntry->name, cur->name, strLen);
-                dnsEntry->name[strLen] = '\0';
-
-                dnsEntry->next = x509->altNames;
-                x509->altNames = dnsEntry;
-            }
-            cur = cur->next;
-        }
-    }
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-    x509->isCa = dCert->isCA;
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    x509->pathLength = dCert->pathLength;
-    x509->keyUsage = dCert->extKeyUsage;
-
-    x509->CRLdistSet = dCert->extCRLdistSet;
-    x509->CRLdistCrit = dCert->extCRLdistCrit;
-    x509->CRLInfo = dCert->extCrlInfo;
-    x509->CRLInfoSz = dCert->extCrlInfoSz;
-    x509->authInfoSet = dCert->extAuthInfoSet;
-    x509->authInfoCrit = dCert->extAuthInfoCrit;
-    if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) {
-        x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap,
-                DYNAMIC_TYPE_X509_EXT);
-        if (x509->authInfo != NULL) {
-            XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz);
-            x509->authInfoSz = dCert->extAuthInfoSz;
-        }
-        else {
-            ret = MEMORY_E;
-        }
-    }
-    x509->basicConstSet = dCert->extBasicConstSet;
-    x509->basicConstCrit = dCert->extBasicConstCrit;
-    x509->basicConstPlSet = dCert->pathLengthSet;
-    x509->subjAltNameSet = dCert->extSubjAltNameSet;
-    x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
-    x509->authKeyIdSet = dCert->extAuthKeyIdSet;
-    x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
-    if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) {
-        x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap,
-                                         DYNAMIC_TYPE_X509_EXT);
-        if (x509->authKeyId != NULL) {
-            XMEMCPY(x509->authKeyId,
-                                 dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz);
-            x509->authKeyIdSz = dCert->extAuthKeyIdSz;
-        }
-        else
-            ret = MEMORY_E;
-    }
-    x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
-    x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
-    if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) {
-        x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap,
-                                         DYNAMIC_TYPE_X509_EXT);
-        if (x509->subjKeyId != NULL) {
-            XMEMCPY(x509->subjKeyId,
-                                 dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz);
-            x509->subjKeyIdSz = dCert->extSubjKeyIdSz;
-        }
-        else
-            ret = MEMORY_E;
-    }
-    x509->keyUsageSet = dCert->extKeyUsageSet;
-    x509->keyUsageCrit = dCert->extKeyUsageCrit;
-    if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) {
-        x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz,
-                x509->heap, DYNAMIC_TYPE_X509_EXT);
-        if (x509->extKeyUsageSrc != NULL) {
-            XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc,
-                                                       dCert->extExtKeyUsageSz);
-            x509->extKeyUsageSz    = dCert->extExtKeyUsageSz;
-            x509->extKeyUsageCrit  = dCert->extExtKeyUsageCrit;
-            x509->extKeyUsageCount = dCert->extExtKeyUsageCount;
-        }
-        else {
-            ret = MEMORY_E;
-        }
-    }
-    #ifdef WOLFSSL_SEP
-        x509->certPolicySet = dCert->extCertPolicySet;
-        x509->certPolicyCrit = dCert->extCertPolicyCrit;
-    #endif /* WOLFSSL_SEP */
-    #ifdef WOLFSSL_CERT_EXT
-        {
-            int i;
-            for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++)
-                XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i],
-                                                                MAX_CERTPOL_SZ);
-            x509->certPoliciesNb = dCert->extCertPoliciesNb;
-        }
-    #endif /* WOLFSSL_CERT_EXT */
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    x509->pkCurveOID = dCert->pkCurveOID;
-#endif /* HAVE_ECC */
-
-    return ret;
-}
-
-#endif /* KEEP_PEER_CERT || SESSION_CERTS */
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
-     (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
-static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                      word32 status_length)
-{
-    int ret = 0;
-    OcspRequest* request;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        CertStatus* status;
-        OcspResponse* response;
-    #else
-        CertStatus status[1];
-        OcspResponse response[1];
-    #endif
-
-    do {
-        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-            if (ssl->status_request) {
-                request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
-                ssl->status_request = 0;
-                break;
-            }
-        #endif
-
-        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-            if (ssl->status_request_v2) {
-                request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
-                                                          WOLFSSL_CSR2_OCSP, 0);
-                ssl->status_request_v2 = 0;
-                break;
-            }
-        #endif
-
-        return BUFFER_ERROR;
-    } while(0);
-
-    if (request == NULL)
-        return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
-
-    #ifdef WOLFSSL_SMALL_STACK
-        status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
-                                                      DYNAMIC_TYPE_OCSP_STATUS);
-        response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-
-        if (status == NULL || response == NULL) {
-            if (status)
-                XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
-            if (response)
-                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
-
-            return MEMORY_ERROR;
-        }
-    #endif
-
-    InitOcspResponse(response, status, input +*inOutIdx, status_length);
-
-    if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
-        ret = BAD_CERTIFICATE_STATUS_ERROR;
-    else if (CompareOcspReqResp(request, response) != 0)
-        ret = BAD_CERTIFICATE_STATUS_ERROR;
-    else if (response->responseStatus != OCSP_SUCCESSFUL)
-        ret = BAD_CERTIFICATE_STATUS_ERROR;
-    else if (response->status->status == CERT_REVOKED)
-        ret = OCSP_CERT_REVOKED;
-    else if (response->status->status != CERT_GOOD)
-        ret = BAD_CERTIFICATE_STATUS_ERROR;
-
-    *inOutIdx += status_length;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(status,   ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
-        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-    #endif
-
-    return ret;
-}
-#endif
-
-
-
-#ifdef HAVE_PK_CALLBACKS
-
-#ifdef HAVE_ECC
-    static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz,
-       const unsigned char* hash, unsigned int hashSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       int* result, void* ctx)
-    {
-        int ret = NOT_COMPILED_IN;
-        WOLFSSL* ssl = (WOLFSSL*)ctx;
-
-        if (ssl && ssl->ctx->EccVerifyCb) {
-            ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz,
-                keyDer, keySz, result, ssl->EccVerifyCtx);
-        }
-        return ret;
-    }
-#endif
-#ifndef NO_RSA
-    static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz,
-       unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
-       void* ctx)
-    {
-        int ret = NOT_COMPILED_IN;
-        WOLFSSL* ssl = (WOLFSSL*)ctx;
-
-        if (ssl && ssl->ctx->RsaVerifyCb) {
-            ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz,
-                ssl->RsaVerifyCtx);
-        }
-        return ret;
-    }
-#endif
-
-int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
-{
-    if (ssl == NULL || sigCtx == NULL)
-        return BAD_FUNC_ARG;
-
-    /* only setup the verify callback if a PK is set */
-#ifdef HAVE_ECC
-    if (ssl->ctx->EccVerifyCb) {
-        sigCtx->pkCbEcc = SigPkCbEccVerify;
-        sigCtx->pkCtxEcc = ssl;
-    }
-#endif
-#ifndef NO_RSA
-    /* only setup the verify callback if a PK is set */
-    if (ssl->ctx->RsaVerifyCb) {
-        sigCtx->pkCbRsa = SigPkCbRsaVerify;
-        sigCtx->pkCtxRsa = ssl;
-    }
-#endif
-
-    return 0;
-}
-
-#endif /* HAVE_PK_CALLBACKS */
-
-
-typedef struct ProcPeerCertArgs {
-    buffer*      certs;
-#ifdef WOLFSSL_TLS13
-    buffer*      exts; /* extentions */
-#endif
-    DecodedCert* dCert;
-    char*  domain;
-    word32 idx;
-    word32 begin;
-    int    totalCerts; /* number of certs in certs buffer */
-    int    count;
-    int    dCertInit;
-    int    certIdx;
-    int    fatal;
-    int    lastErr;
-#ifdef WOLFSSL_ALT_CERT_CHAINS
-    int    lastCaErr;
-#endif
-#ifdef WOLFSSL_TLS13
-    byte   ctxSz;
-#endif
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */
-#endif
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    char   untrustedDepth;
-#endif
-} ProcPeerCertArgs;
-
-static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
-{
-    ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs;
-
-    (void)ssl;
-
-    if (args->domain) {
-        XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_STRING);
-        args->domain = NULL;
-    }
-    if (args->certs) {
-        XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
-        args->certs = NULL;
-    }
-#ifdef WOLFSSL_TLS13
-    if (args->exts) {
-        XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
-        args->exts = NULL;
-    }
-#endif
-    if (args->dCert) {
-        if (args->dCertInit) {
-            FreeDecodedCert(args->dCert);
-            args->dCertInit = 0;
-        }
-        XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
-        args->dCert = NULL;
-    }
-}
-
-int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                     word32 totalSz)
-{
-    int ret = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#elif defined(WOLFSSL_NONBLOCK_OCSP)
-    ProcPeerCertArgs* args = ssl->nonblockarg;
-#else
-    ProcPeerCertArgs  args[1];
-#endif
-
-    buffer* cert;
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */
-#endif
-
-    WOLFSSL_ENTER("ProcessPeerCerts");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_ppc;
-    }
-    else
-#elif defined(WOLFSSL_NONBLOCK_OCSP)
-    if (args == NULL) {
-        args = (ProcPeerCertArgs*)XMALLOC(
-            sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (args == NULL) {
-            ERROR_OUT(MEMORY_E, exit_ppc);
-        }
-    }
-    if (ssl->nonblockarg == NULL) /* new args */
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
-        args->idx = *inOutIdx;
-        args->begin = *inOutIdx;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeProcPeerCertArgs;
-    #elif defined(WOLFSSL_NONBLOCK_OCSP)
-        ssl->nonblockarg = args;
-    #endif
-    }
-
-    switch (ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-            word32 listSz;
-
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "Certificate");
-            if (ssl->toInfoOn)
-                AddLateName("Certificate", &ssl->timeoutInfo);
-        #endif
-
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3) {
-                byte ctxSz;
-
-                /* Certificate Request Context */
-                if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz)
-                    return BUFFER_ERROR;
-                ctxSz = *(input + args->idx);
-                args->idx++;
-                if ((args->idx - args->begin) + ctxSz > totalSz)
-                    return BUFFER_ERROR;
-            #ifndef NO_WOLFSSL_CLIENT
-                /* Must be empty when received from server. */
-                if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                    if (ctxSz != 0) {
-                        return INVALID_CERT_CTX_E;
-                    }
-                }
-            #endif
-            #ifndef NO_WOLFSSL_SERVER
-                /* Must contain value sent in request. */
-                if (ssl->options.side == WOLFSSL_SERVER_END) {
-                    if (ssl->options.handShakeState != HANDSHAKE_DONE &&
-                                                                   ctxSz != 0) {
-                        return INVALID_CERT_CTX_E;
-                    }
-                    else if (ssl->options.handShakeState == HANDSHAKE_DONE) {
-                #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-                         CertReqCtx* curr = ssl->certReqCtx;
-                         CertReqCtx* prev = NULL;
-                         while (curr != NULL) {
-                             if ((ctxSz == curr->len) &&
-                                 XMEMCMP(&curr->ctx, input + args->idx, ctxSz)
-                                                                         == 0) {
-                                     if (prev != NULL)
-                                         prev->next = curr->next;
-                                     else
-                                         ssl->certReqCtx = curr->next;
-                                     XFREE(curr, ssl->heap,
-                                           DYNAMIC_TYPE_TMP_BUFFER);
-                                     break;
-                             }
-                             prev = curr;
-                             curr = curr->next;
-                        }
-                        if (curr == NULL)
-                #endif
-                            return INVALID_CERT_CTX_E;
-                    }
-                }
-            #endif
-                args->idx += ctxSz;
-
-                /* allocate buffer for cert extensions */
-                args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
-                                            ssl->heap, DYNAMIC_TYPE_CERT_EXT);
-                if (args->exts == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_ppc);
-                }
-            }
-        #endif
-
-            /* allocate buffer for certs */
-        #ifdef OPENSSL_EXTRA
-            args->certs = (buffer*)XMALLOC(sizeof(buffer) *
-                    (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER);
-            if (args->certs == NULL) {
-                ERROR_OUT(MEMORY_E, exit_ppc);
-            }
-            XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1));
-        #else
-            args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
-                                            ssl->heap, DYNAMIC_TYPE_DER);
-            if (args->certs == NULL) {
-                ERROR_OUT(MEMORY_E, exit_ppc);
-            }
-            XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
-        #endif /* OPENSSL_EXTRA */
-            /* Certificate List */
-            if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
-                ERROR_OUT(BUFFER_ERROR, exit_ppc);
-            }
-            c24to32(input + args->idx, &listSz);
-            args->idx += OPAQUE24_LEN;
-            if (listSz > MAX_CERTIFICATE_SZ) {
-                ERROR_OUT(BUFFER_ERROR, exit_ppc);
-            }
-            if ((args->idx - args->begin) + listSz != totalSz) {
-                ERROR_OUT(BUFFER_ERROR, exit_ppc);
-            }
-
-            WOLFSSL_MSG("Loading peer's cert chain");
-            /* first put cert chain into buffer so can verify top down
-               we're sent bottom up */
-            while (listSz) {
-                word32 certSz;
-
-            #ifdef OPENSSL_EXTRA
-                if (args->totalCerts > ssl->verifyDepth) {
-                    ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
-                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
-                }
-            #else
-                if (args->totalCerts >= ssl->verifyDepth ||
-                        args->totalCerts >= MAX_CHAIN_DEPTH) {
-                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
-                }
-            #endif
-
-                if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
-                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
-                }
-
-                c24to32(input + args->idx, &certSz);
-                args->idx += OPAQUE24_LEN;
-
-                if ((args->idx - args->begin) + certSz > totalSz) {
-                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
-                }
-
-                args->certs[args->totalCerts].length = certSz;
-                args->certs[args->totalCerts].buffer = input + args->idx;
-
-            #ifdef SESSION_CERTS
-                AddSessionCertToChain(&ssl->session.chain,
-                    input + args->idx, certSz);
-            #endif /* SESSION_CERTS */
-
-                args->idx += certSz;
-                listSz -= certSz + CERT_HEADER_SZ;
-
-            #ifdef WOLFSSL_TLS13
-                /* Extensions */
-                if (ssl->options.tls1_3) {
-                    word16 extSz;
-
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz)
-                        return BUFFER_ERROR;
-                    ato16(input + args->idx, &extSz);
-                    args->idx += OPAQUE16_LEN;
-                    if ((args->idx - args->begin) + extSz > totalSz)
-                        return BUFFER_ERROR;
-                    /* Store extension data info for later processing. */
-                    args->exts[args->totalCerts].length = extSz;
-                    args->exts[args->totalCerts].buffer = input + args->idx;
-                    args->idx += extSz;
-                    listSz -= extSz + OPAQUE16_LEN;
-                    ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
-                        args->exts[args->totalCerts].length, certificate, NULL);
-                    if (ret < 0)
-                        return ret;
-                }
-            #endif
-
-                args->totalCerts++;
-                WOLFSSL_MSG("\tPut another cert into chain");
-            } /* while (listSz) */
-
-            args->count = args->totalCerts;
-            args->certIdx = 0;
-
-            args->dCertInit = 0;
-            args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
-                                                       DYNAMIC_TYPE_DCERT);
-            if (args->dCert == NULL) {
-                ERROR_OUT(MEMORY_E, exit_ppc);
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            if (args->count > 0) {
-            #ifdef WOLFSSL_TRUST_PEER_CERT
-                if (args->certIdx == 0) {
-                    /* if using trusted peer certs check before verify chain
-                       and CA test */
-                    TrustedPeerCert* tp;
-
-                    cert = &args->certs[args->certIdx];
-
-                    if (!args->dCertInit) {
-                        InitDecodedCert(args->dCert,
-                            cert->buffer, cert->length, ssl->heap);
-                        args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
-                    #ifdef WOLFSSL_ASYNC_CRYPT
-                        args->dCert->sigCtx.asyncCtx = ssl;
-                    #endif
-                        args->dCertInit = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
-                        if (ret != 0)
-                            goto exit_ppc;
-                    #endif
-                    }
-
-                    ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
-                                                            ssl->ctx->cm);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                            args->dCert->sigCtx.asyncDev);
-                        goto exit_ppc;
-                    }
-                #endif
-                    if (ret != 0)
-                        goto exit_ppc;
-
-                #ifndef NO_SKID
-                    if (args->dCert->extAuthKeyIdSet) {
-                        tp = GetTrustedPeer(ssl->ctx->cm,
-                                    args->dCert->extSubjKeyId, WC_MATCH_SKID);
-                    }
-                    else { /* if the cert has no SKID try to match by name */
-                        tp = GetTrustedPeer(ssl->ctx->cm,
-                                    args->dCert->subjectHash, WC_MATCH_NAME);
-                    }
-                #else /* NO_SKID */
-                    tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash,
-                                                                 WC_MATCH_NAME);
-                #endif /* NO SKID */
-                    WOLFSSL_MSG("Checking for trusted peer cert");
-
-                    if (tp == NULL) {
-                        /* no trusted peer cert */
-                        WOLFSSL_MSG("No matching trusted peer cert. "
-                            "Checking CAs");
-                        FreeDecodedCert(args->dCert);
-                        args->dCertInit = 0;
-                    #ifdef OPENSSL_EXTRA
-                        args->untrustedDepth = 1;
-                    #endif
-                    } else if (MatchTrustedPeer(tp, args->dCert)){
-                        WOLFSSL_MSG("Found matching trusted peer cert");
-                        haveTrustPeer = 1;
-                    } else {
-                        WOLFSSL_MSG("Trusted peer cert did not match!");
-                        FreeDecodedCert(args->dCert);
-                        args->dCertInit = 0;
-                    #ifdef OPENSSL_EXTRA
-                        args->untrustedDepth = 1;
-                    #endif
-                    }
-                }
-            #endif /* WOLFSSL_TRUST_PEER_CERT */
-            #ifdef OPENSSL_EXTRA
-                #ifdef WOLFSSL_TRUST_PEER_CERT
-                else
-                #endif
-                if (args->certIdx == 0) {
-                    byte* subjectHash;
-                    cert = &args->certs[args->certIdx];
-
-                    if (!args->dCertInit) {
-                        InitDecodedCert(args->dCert,
-                            cert->buffer, cert->length, ssl->heap);
-                        args->dCert->sigCtx.devId = ssl->devId;
-                    #ifdef WOLFSSL_ASYNC_CRYPT
-                        args->dCert->sigCtx.asyncCtx = ssl;
-                    #endif
-                        args->dCertInit = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
-                        if (ret != 0)
-                            goto exit_ppc;
-                    #endif
-                    }
-
-                    ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
-                                                                  ssl->ctx->cm);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                            args->dCert->sigCtx.asyncDev);
-                        goto exit_ppc;
-                    }
-                #endif
-                    if (ret != 0) {
-                        goto exit_ppc;
-                    }
-
-                #ifndef NO_SKID
-                    subjectHash = args->dCert->extSubjKeyId;
-                #else
-                    subjectHash = args->dCert->subjectHash;
-                #endif
-                    if (!AlreadySigner(ssl->ctx->cm, subjectHash))
-                        args->untrustedDepth = 1;
-                    FreeDecodedCert(args->dCert);
-                    args->dCertInit = 0;
-                }
-            #endif
-
-                /* verify up to peer's first */
-                /* do not verify chain if trusted peer cert found */
-                while (args->count > 1
-                #ifdef WOLFSSL_TRUST_PEER_CERT
-                    && !haveTrustPeer
-                #endif /* WOLFSSL_TRUST_PEER_CERT */
-                ) {
-                    byte *subjectHash;
-
-                    args->certIdx = args->count - 1;
-                    cert = &args->certs[args->certIdx];
-
-                    if (!args->dCertInit) {
-                        InitDecodedCert(args->dCert,
-                            cert->buffer, cert->length, ssl->heap);
-                        args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
-                    #ifdef WOLFSSL_ASYNC_CRYPT
-                        args->dCert->sigCtx.asyncCtx = ssl;
-                    #endif
-                        args->dCertInit = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
-                        if (ret != 0)
-                            goto exit_ppc;
-                    #endif
-                    }
-
-                    /* check if returning from non-blocking OCSP */
-                #ifdef WOLFSSL_NONBLOCK_OCSP
-                    if (args->lastErr != OCSP_WANT_READ)
-                    {
-                #endif
-
-                    ret = ParseCertRelative(args->dCert, CERT_TYPE,
-                                    !ssl->options.verifyNone, ssl->ctx->cm);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                            args->dCert->sigCtx.asyncDev);
-                        goto exit_ppc;
-                    }
-                #endif
-
-                #ifndef NO_SKID
-                    subjectHash = args->dCert->extSubjKeyId;
-                #else
-                    subjectHash = args->dCert->subjectHash;
-                #endif
-
-                    /* Check key sizes for certs. Is redundent check since
-                       ProcessBuffer also performs this check. */
-                    if (!ssl->options.verifyNone) {
-                        switch (args->dCert->keyOID) {
-                        #ifndef NO_RSA
-                            case RSAk:
-                                if (ssl->options.minRsaKeySz < 0 ||
-                                        args->dCert->pubKeySize <
-                                         (word16)ssl->options.minRsaKeySz) {
-                                    WOLFSSL_MSG(
-                                        "RSA key size in cert chain error");
-                                    ret = RSA_KEY_SIZE_E;
-                                }
-                                break;
-                        #endif /* !NO_RSA */
-                        #ifdef HAVE_ECC
-                            case ECDSAk:
-                                if (ssl->options.minEccKeySz < 0 ||
-                                        args->dCert->pubKeySize <
-                                         (word16)ssl->options.minEccKeySz) {
-                                    WOLFSSL_MSG(
-                                        "ECC key size in cert chain error");
-                                    ret = ECC_KEY_SIZE_E;
-                                }
-                                break;
-                        #endif /* HAVE_ECC */
-                        #ifdef HAVE_ED25519
-                            case ED25519k:
-                                if (ssl->options.minEccKeySz < 0 ||
-                                        ED25519_KEY_SIZE <
-                                         (word16)ssl->options.minEccKeySz) {
-                                    WOLFSSL_MSG(
-                                        "ECC key size in cert chain error");
-                                    ret = ECC_KEY_SIZE_E;
-                                }
-                                break;
-                        #endif /* HAVE_ED25519 */
-                            default:
-                                WOLFSSL_MSG("Key size not checked");
-                                /* key not being checked for size if not in
-                                   switch */
-                                break;
-                        } /* switch (dCert->keyOID) */
-                    } /* if (!ssl->options.verifyNone) */
-
-                    if (ret == 0 && args->dCert->isCA == 0) {
-                        WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
-                    }
-                    else if (ret == 0 && ssl->options.verifyNone) {
-                        WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
-                    }
-                    else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
-                        DerBuffer* add = NULL;
-                        ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
-                        if (ret < 0)
-                            goto exit_ppc;
-
-                        WOLFSSL_MSG("Adding CA from chain");
-
-                        XMEMCPY(add->buffer, cert->buffer, cert->length);
-
-                    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-                        if (args->certIdx > args->untrustedDepth)
-                            args->untrustedDepth = (char) args->certIdx + 1;
-                    #endif
-
-                        /* already verified above */
-                        ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0);
-                        if (ret == 1) {
-                            ret = 0;   /* WOLFSSL_SUCCESS for external */
-                        }
-
-                    #ifdef WOLFSSL_ALT_CERT_CHAINS
-                        /* if the previous CA cert failed, clear last error */
-                        if (args->lastCaErr != 0) {
-                            WOLFSSL_MSG("Using alternate cert chain");
-                            ssl->options.usingAltCertChain = 1;
-
-                            /* clear last CA fail since CA cert was validated */
-                            args->lastCaErr = 0;
-
-                        #ifdef SESSION_CERTS
-                            AddSessionCertToChain(&ssl->session.altChain,
-                                cert->buffer, cert->length);
-                        #endif /* SESSION_CERTS */
-                        }
-                    #endif
-                    }
-                    else if (ret != 0) {
-                        WOLFSSL_MSG("Failed to verify CA from chain");
-                    #ifdef WOLFSSL_ALT_CERT_CHAINS
-                        if (args->lastCaErr == 0) {
-                            /* store CA error and proceed to next cert */
-                            args->lastCaErr = ret;
-                            ret = 0;
-                        }
-                        else {
-                            args->lastErr = args->lastCaErr;
-                        }
-                    #endif
-                    #ifdef OPENSSL_EXTRA
-                        ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
-                    #endif
-                    }
-                    else {
-                        WOLFSSL_MSG("Verified CA from chain and already had it");
-                    }
-
-                #ifdef WOLFSSL_NONBLOCK_OCSP
-                    }
-                    else {
-                        args->lastErr = 0; /* clear last error */
-                    }
-                #endif
-
-            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
-                    if (ret == 0) {
-                        int doCrlLookup = 1;
-                #ifdef HAVE_OCSP
-                    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-                        if (ssl->status_request_v2) {
-                            ret = TLSX_CSR2_InitRequests(ssl->extensions,
-                                                    args->dCert, 0, ssl->heap);
-                        }
-                        else /* skips OCSP and force CRL check */
-                    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-                        if (ssl->ctx->cm->ocspEnabled &&
-                                            ssl->ctx->cm->ocspCheckAll) {
-                            WOLFSSL_MSG("Doing Non Leaf OCSP check");
-                            ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
-                                                    args->dCert, NULL, ssl);
-                        #ifdef WOLFSSL_NONBLOCK_OCSP
-                            if (ret == OCSP_WANT_READ) {
-                                args->lastErr = ret;
-                                goto exit_ppc;
-                            }
-                        #endif
-                            doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
-                            if (ret != 0) {
-                                doCrlLookup = 0;
-                                WOLFSSL_MSG("\tOCSP Lookup not ok");
-                            }
-                        }
-                #endif /* HAVE_OCSP */
-
-                #ifdef HAVE_CRL
-                        if (ret == 0 && doCrlLookup &&
-                                    ssl->ctx->cm->crlEnabled &&
-                                                ssl->ctx->cm->crlCheckAll) {
-                            WOLFSSL_MSG("Doing Non Leaf CRL check");
-                            ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
-                        #ifdef WOLFSSL_NONBLOCK_OCSP
-                            if (ret == OCSP_WANT_READ) {
-                                args->lastErr = ret;
-                                goto exit_ppc;
-                            }
-                        #endif
-                            if (ret != 0) {
-                                WOLFSSL_MSG("\tCRL check not ok");
-                            }
-                        }
-                #endif /* HAVE_CRL */
-                        (void)doCrlLookup;
-                    }
-            #endif /* HAVE_OCSP || HAVE_CRL */
-
-            #if defined(WOLFSSL_VERIFY_CB_ALL_CERTS)
-                    if (ret != 0) {
-                        if (!ssl->options.verifyNone) {
-                            int why = bad_certificate;
-
-                        if (ret == ASN_AFTER_DATE_E || ret ==
-                                ASN_BEFORE_DATE_E) {
-                            why = certificate_expired;
-                        }
-                        if (ssl->verifyCallback) {
-                            int ok;
-
-                        #ifdef WOLFSSL_SMALL_STACK
-                            WOLFSSL_X509_STORE_CTX* store;
-                            WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(
-                                sizeof(WOLFSSL_X509), ssl->heap,
-                                DYNAMIC_TYPE_X509);
-                            if (x509 == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_ppc);
-                            }
-                            store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
-                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
-                                                    DYNAMIC_TYPE_X509_STORE);
-                            if (store == NULL) {
-                                wolfSSL_X509_free(x509);
-                                ERROR_OUT(MEMORY_E, exit_ppc);
-                            }
-                        #else
-                            WOLFSSL_X509_STORE_CTX  store[1];
-                            WOLFSSL_X509 x509[1];
-                        #endif
-
-                            XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
-
-                            store->error = ret;
-                            store->error_depth = args->certIdx;
-                            store->discardSessionCerts = 0;
-                            store->domain = args->domain;
-                            store->userCtx = ssl->verifyCbCtx;
-                            store->certs = args->certs;
-                            store->totalCerts = args->totalCerts;
-
-                        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-                            if (ssl->ctx->x509_store_pt != NULL) {
-                                store->store = ssl->ctx->x509_store_pt;
-                            }
-                            else {
-                                store->store = &ssl->ctx->x509_store;
-                            }
-                        #endif
-                        #if !defined(NO_CERTS)
-                            InitX509(x509, 1, ssl->heap);
-                            #if defined(KEEP_PEER_CERT) || \
-                                defined(SESSION_CERTS)
-                            if (CopyDecodedToX509(x509, args->dCert) == 0) {
-                                store->current_cert = x509;
-                            }
-                            #endif
-                        #endif
-                        #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS)
-                            store->ex_data = ssl;
-                        #endif
-                        #ifdef SESSION_CERTS
-                            store->sesChain = &(ssl->session.chain);
-                        #endif
-                            ok = ssl->verifyCallback(0, store);
-                            if (ok) {
-                                WOLFSSL_MSG("Verify callback overriding error!");
-                                ret = 0;
-                            }
-                        #ifndef NO_CERTS
-                            FreeX509(x509);
-                        #endif
-                        #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
-                            wolfSSL_sk_X509_free(store->chain);
-                            store->chain = NULL;
-                        #endif
-                        #ifdef SESSION_CERTS
-                            if (store->discardSessionCerts) {
-                                WOLFSSL_MSG("Verify callback requested discard sess certs");
-                                ssl->session.chain.count = 0;
-                            #ifdef WOLFSSL_ALT_CERT_CHAINS
-                                ssl->session.altChain.count = 0;
-                            #endif
-                            }
-                        #endif /* SESSION_CERTS */
-                        #ifdef WOLFSSL_SMALL_STACK
-                            XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
-                            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
-                        #endif
-                        }
-                        if (ret != 0) {
-                            SendAlert(ssl, alert_fatal, why);   /* try to send */
-                            ssl->options.isClosed = 1;
-                        }
-                    }
-
-                    ssl->error = ret;
-                }
-            #ifdef WOLFSSL_ALWAYS_VERIFY_CB
-                else {
-                    if (ssl->verifyCallback) {
-                        int ok;
-
-                    #ifdef WOLFSSL_SMALL_STACK
-                        WOLFSSL_X509_STORE_CTX* store;
-                        WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(
-                                sizeof(WOLFSSL_X509), ssl->heap,
-                                DYNAMIC_TYPE_X509);
-                        if (x509 == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_ppc);
-                        }
-                        store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
-                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
-                                                    DYNAMIC_TYPE_X509_STORE);
-                        if (store == NULL) {
-                            wolfSSL_X509_free(x509);
-                            ERROR_OUT(MEMORY_E, exit_ppc);
-                        }
-                    #else
-                        WOLFSSL_X509_STORE_CTX  store[1];
-                        WOLFSSL_X509            x509[1];
-                    #endif
-
-                        XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
-
-                        store->error = ret;
-                        store->error_depth = args->certIdx;
-                        store->discardSessionCerts = 0;
-                        store->domain = args->domain;
-                        store->userCtx = ssl->verifyCbCtx;
-                        store->certs = args->certs;
-                        store->totalCerts = args->totalCerts;
-
-                    #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-                        if (ssl->ctx->x509_store_pt != NULL) {
-                            store->store = ssl->ctx->x509_store_pt;
-                        }
-                        else {
-                            store->store = &ssl->ctx->x509_store;
-                        }
-                    #endif
-                    #if !defined(NO_CERTS)
-                        InitX509(x509, 1, ssl->heap);
-                        #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
-                        if (CopyDecodedToX509(x509, args->dCert) == 0) {
-                            store->current_cert = x509;
-                        }
-                        #endif
-                    #endif
-                    #ifdef SESSION_CERTS
-                        store->sesChain = &(ssl->session.chain);
-                    #endif
-                        store->ex_data = ssl;
-
-                        ok = ssl->verifyCallback(1, store);
-                        if (!ok) {
-                            WOLFSSL_MSG("Verify callback overriding valid certificate!");
-                            ret = -1;
-                            ssl->options.isClosed = 1;
-                        }
-                    #ifndef NO_CERTS
-                        FreeX509(x509);
-                    #endif
-                    #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
-                        wolfSSL_sk_X509_free(store->chain);
-                        store->chain = NULL;
-                    #endif
-                    #ifdef SESSION_CERTS
-                        if (store->discardSessionCerts) {
-                            WOLFSSL_MSG("Verify callback requested discard sess certs");
-                            ssl->session.chain.count = 0;
-                        #ifdef WOLFSSL_ALT_CERT_CHAINS
-                            ssl->session.altChain.count = 0;
-                        #endif
-                        }
-                    #endif /* SESSION_CERTS */
-                    #ifdef WOLFSSL_SMALL_STACK
-                        XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
-                        XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
-                    #endif
-                    }
-                }
-            #endif /* WOLFSSL_ALWAYS_VERIFY_CB */
-        #endif /* WOLFSSL_VERIFY_CB_ALL_CERTS */
-
-                    if (ret != 0 && args->lastErr == 0) {
-                        args->lastErr = ret;   /* save error from last time */
-                        ret = 0; /* reset error */
-                    }
-
-                    FreeDecodedCert(args->dCert);
-                    args->dCertInit = 0;
-                    args->count--;
-                } /* while (count > 0 && !haveTrustPeer) */
-            } /* if (count > 0) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_ppc;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-            /* peer's, may not have one if blank client cert sent by TLSv1.2 */
-            if (args->count > 0) {
-                WOLFSSL_MSG("Verifying Peer's cert");
-
-                args->certIdx = 0;
-                cert = &args->certs[args->certIdx];
-
-                if (!args->dCertInit) {
-                    InitDecodedCert(args->dCert,
-                        cert->buffer, cert->length, ssl->heap);
-                    args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    args->dCert->sigCtx.asyncCtx = ssl;
-                #endif
-                    args->dCertInit = 1;
-                #ifdef HAVE_PK_CALLBACKS
-                    ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
-                    if (ret != 0)
-                        goto exit_ppc;
-                #endif
-                }
-
-            #ifdef WOLFSSL_TRUST_PEER_CERT
-                if (!haveTrustPeer)
-            #endif
-                {
-                    /* only parse if not already present in dCert from above */
-                    ret = ParseCertRelative(args->dCert, CERT_TYPE,
-                                    !ssl->options.verifyNone, ssl->ctx->cm);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                            args->dCert->sigCtx.asyncDev);
-                        goto exit_ppc;
-                    }
-                #endif
-                }
-
-                if (ret == 0) {
-                    WOLFSSL_MSG("Verified Peer's cert");
-                #ifdef OPENSSL_EXTRA
-                    ssl->peerVerifyRet = X509_V_OK;
-                #endif
-                #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
-                    if (ssl->options.usingAltCertChain) {
-                        AddSessionCertToChain(&ssl->session.altChain,
-                            cert->buffer, cert->length);
-                    }
-                #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
-                    args->fatal = 0;
-                }
-                else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
-                    WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
-                #ifdef OPENSSL_EXTRA
-                    SendAlert(ssl, alert_fatal, bad_certificate);
-                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
-                #endif
-                    args->fatal = 1;
-                }
-                else {
-                    WOLFSSL_MSG("Failed to verify Peer's cert");
-                #ifdef OPENSSL_EXTRA
-                    ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
-                #endif
-                    if (ssl->verifyCallback) {
-                        WOLFSSL_MSG(
-                            "\tCallback override available, will continue");
-                        args->fatal = 0;
-                    }
-                    else {
-                        WOLFSSL_MSG("\tNo callback override available, fatal");
-                        args->fatal = 1;
-                    #ifdef OPENSSL_EXTRA
-                        SendAlert(ssl, alert_fatal, bad_certificate);
-                    #endif
-                    }
-                }
-
-            #ifdef HAVE_SECURE_RENEGOTIATION
-                if (args->fatal == 0 && ssl->secure_renegotiation
-                               && ssl->secure_renegotiation->enabled) {
-
-                    if (IsEncryptionOn(ssl, 0)) {
-                        /* compare against previous time */
-                        if (XMEMCMP(args->dCert->subjectHash,
-                                    ssl->secure_renegotiation->subject_hash,
-                                    WC_SHA_DIGEST_SIZE) != 0) {
-                            WOLFSSL_MSG(
-                                "Peer sent different cert during scr, fatal");
-                            args->fatal = 1;
-                            ret   = SCR_DIFFERENT_CERT_E;
-                        }
-                    }
-
-                    /* cache peer's hash */
-                    if (args->fatal == 0) {
-                        XMEMCPY(ssl->secure_renegotiation->subject_hash,
-                                args->dCert->subjectHash, WC_SHA_DIGEST_SIZE);
-                    }
-                }
-            #endif /* HAVE_SECURE_RENEGOTIATION */
-            } /* if (count > 0) */
-
-            /* Check for error */
-            if (args->fatal && ret != 0) {
-                goto exit_ppc;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-            if (args->count > 0) {
-            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
-                if (args->fatal == 0) {
-                    int doLookup = 1;
-
-                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-                        if (ssl->status_request) {
-                            args->fatal = TLSX_CSR_InitRequest(ssl->extensions,
-                                                    args->dCert, ssl->heap);
-                            doLookup = 0;
-                        #ifdef WOLFSSL_TLS13
-                            if (ssl->options.tls1_3) {
-                                TLSX* ext = TLSX_Find(ssl->extensions,
-                                                           TLSX_STATUS_REQUEST);
-                                if (ext != NULL) {
-                                    word32 idx = 0;
-                                    CertificateStatusRequest* csr =
-                                           (CertificateStatusRequest*)ext->data;
-                                    ret = ProcessCSR(ssl, csr->response.buffer,
-                                                    &idx, csr->response.length);
-                                    if (ret < 0)
-                                        goto exit_ppc;
-                                }
-                            }
-                        #endif
-                        }
-                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-                        if (ssl->status_request_v2) {
-                            args->fatal = TLSX_CSR2_InitRequests(ssl->extensions,
-                                                    args->dCert, 1, ssl->heap);
-                            doLookup = 0;
-                        }
-                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-                    }
-
-                #ifdef HAVE_OCSP
-                    if (doLookup && ssl->ctx->cm->ocspEnabled) {
-                        WOLFSSL_MSG("Doing Leaf OCSP check");
-                        ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
-                                                    args->dCert, NULL, ssl);
-                    #ifdef WOLFSSL_NONBLOCK_OCSP
-                        if (ret == OCSP_WANT_READ) {
-                            goto exit_ppc;
-                        }
-                    #endif
-                        doLookup = (ret == OCSP_CERT_UNKNOWN);
-                        if (ret != 0) {
-                            WOLFSSL_MSG("\tOCSP Lookup not ok");
-                            args->fatal = 0;
-                        #ifdef OPENSSL_EXTRA
-                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
-                        #endif
-                        }
-                    }
-                #endif /* HAVE_OCSP */
-
-                #ifdef HAVE_CRL
-                    if (doLookup && ssl->ctx->cm->crlEnabled) {
-                        WOLFSSL_MSG("Doing Leaf CRL check");
-                        ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
-                    #ifdef WOLFSSL_NONBLOCK_OCSP
-                        if (ret == OCSP_WANT_READ) {
-                            goto exit_ppc;
-                        }
-                    #endif
-                        if (ret != 0) {
-                            WOLFSSL_MSG("\tCRL check not ok");
-                            args->fatal = 0;
-                        #ifdef OPENSSL_EXTRA
-                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
-                        #endif
-                        }
-                    }
-                #endif /* HAVE_CRL */
-                    (void)doLookup;
-                }
-            #endif /* HAVE_OCSP || HAVE_CRL */
-
-            #ifdef KEEP_PEER_CERT
-                if (args->fatal == 0) {
-                    /* set X509 format for peer cert */
-                    int copyRet = CopyDecodedToX509(&ssl->peerCert,
-                                                                args->dCert);
-                    if (copyRet == MEMORY_E) {
-                        args->fatal = 1;
-                    }
-                }
-            #endif /* KEEP_PEER_CERT */
-
-            #ifndef IGNORE_KEY_EXTENSIONS
-                #if defined(OPENSSL_EXTRA)
-                  /* when compatibility layer is turned on and no verify is
-                   * set then ignore the certificate key extension */
-                    if (args->dCert->extKeyUsageSet &&
-                          args->dCert->extKeyUsageCrit == 0 &&
-                          ssl->options.verifyNone) {
-                        WOLFSSL_MSG("Not verifying certificate key usage");
-                    }
-                    else
-                #endif
-                if (args->dCert->extKeyUsageSet) {
-                    if ((ssl->specs.kea == rsa_kea) &&
-                        (ssl->options.side == WOLFSSL_CLIENT_END) &&
-                        (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
-                        ret = KEYUSE_ENCIPHER_E;
-                    }
-                    if ((ssl->specs.sig_algo == rsa_sa_algo ||
-                            (ssl->specs.sig_algo == ecc_dsa_sa_algo &&
-                                 !ssl->specs.static_ecdh)) &&
-                        (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
-                        WOLFSSL_MSG("KeyUse Digital Sig not set");
-                        ret = KEYUSE_SIGNATURE_E;
-                    }
-                }
-
-                #if defined(OPENSSL_EXTRA)
-                    /* when compatibility layer is turned on and no verify is
-                     * set then ignore the certificate key extension */
-                    if (args->dCert->extExtKeyUsageSet &&
-                            args->dCert->extExtKeyUsageCrit == 0 &&
-                          ssl->options.verifyNone) {
-                                WOLFSSL_MSG("Not verifying certificate ext key usage");
-                    }
-                    else
-                #endif
-                if (args->dCert->extExtKeyUsageSet) {
-                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                        if ((args->dCert->extExtKeyUsage &
-                                (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
-                            WOLFSSL_MSG("ExtKeyUse Server Auth not set");
-                            ret = EXTKEYUSE_AUTH_E;
-                        }
-                    }
-                    else {
-                        if ((args->dCert->extExtKeyUsage &
-                                (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
-                            WOLFSSL_MSG("ExtKeyUse Client Auth not set");
-                            ret = EXTKEYUSE_AUTH_E;
-                        }
-                    }
-                }
-            #endif /* IGNORE_KEY_EXTENSIONS */
-
-                if (args->fatal) {
-                    ssl->error = ret;
-                #ifdef OPENSSL_EXTRA
-                    SendAlert(ssl, alert_fatal, bad_certificate);
-                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
-                #endif
-                    goto exit_ppc;
-                }
-
-                ssl->options.havePeerCert = 1;
-
-                args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap,
-                                                    DYNAMIC_TYPE_STRING);
-                if (args->domain == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_ppc);
-                }
-
-                /* store for callback use */
-                if (args->dCert->subjectCN &&
-                                    args->dCert->subjectCNLen < ASN_NAME_MAX) {
-                    XMEMCPY(args->domain, args->dCert->subjectCN,
-                        args->dCert->subjectCNLen);
-                    args->domain[args->dCert->subjectCNLen] = '\0';
-                }
-                else {
-                    args->domain[0] = '\0';
-                }
-
-                if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
-                #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
-                    /* Per RFC 5280 section 4.2.1.6, "Whenever such identities
-                     * are to be bound into a certificate, the subject
-                     * alternative name extension MUST be used." */
-                    if (args->dCert->altNames) {
-                        if (CheckAltNames(args->dCert,
-                                (char*)ssl->buffers.domainName.buffer) == 0 ) {
-                            WOLFSSL_MSG("DomainName match on alt names failed");
-                            /* try to get peer key still */
-                            ret = DOMAIN_NAME_MISMATCH;
-                        }
-                    }
-                    else {
-                        if (MatchDomainName(
-                                 args->dCert->subjectCN,
-                                 args->dCert->subjectCNLen,
-                                 (char*)ssl->buffers.domainName.buffer) == 0) {
-                            WOLFSSL_MSG("DomainName match on common name failed");
-                            ret = DOMAIN_NAME_MISMATCH;
-                        }
-                    }
-                #else /* WOLFSSL_ALL_NO_CN_IN_SAN */
-                    /* Old behavior. */
-                    if (MatchDomainName(args->dCert->subjectCN,
-                                args->dCert->subjectCNLen,
-                                (char*)ssl->buffers.domainName.buffer) == 0) {
-                        WOLFSSL_MSG("DomainName match on common name failed");
-                        if (CheckAltNames(args->dCert,
-                                 (char*)ssl->buffers.domainName.buffer) == 0 ) {
-                            WOLFSSL_MSG(
-                                "DomainName match on alt names failed too");
-                            /* try to get peer key still */
-                            ret = DOMAIN_NAME_MISMATCH;
-                        }
-                    }
-                #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
-                }
-
-                /* decode peer key */
-                switch (args->dCert->keyOID) {
-                #ifndef NO_RSA
-                    case RSAk:
-                    {
-                        word32 keyIdx = 0;
-                        int keyRet = 0;
-
-                        if (ssl->peerRsaKey == NULL) {
-                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA,
-                                                (void**)&ssl->peerRsaKey);
-                        } else if (ssl->peerRsaKeyPresent) {
-                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA,
-                                              ssl->peerRsaKey);
-                            ssl->peerRsaKeyPresent = 0;
-                        }
-
-                        if (keyRet != 0 || wc_RsaPublicKeyDecode(
-                                args->dCert->publicKey, &keyIdx, ssl->peerRsaKey,
-                                                args->dCert->pubKeySize) != 0) {
-                            ret = PEER_KEY_ERROR;
-                        }
-                        else {
-                            ssl->peerRsaKeyPresent = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                        #ifndef NO_RSA
-                            ssl->buffers.peerRsaKey.buffer =
-                                   (byte*)XMALLOC(args->dCert->pubKeySize,
-                                                ssl->heap, DYNAMIC_TYPE_RSA);
-                            if (ssl->buffers.peerRsaKey.buffer == NULL) {
-                                ret = MEMORY_ERROR;
-                            }
-                            else {
-                                XMEMCPY(ssl->buffers.peerRsaKey.buffer,
-                                        args->dCert->publicKey,
-                                        args->dCert->pubKeySize);
-                                ssl->buffers.peerRsaKey.length =
-                                    args->dCert->pubKeySize;
-                            }
-                        #endif /* NO_RSA */
-                    #endif /* HAVE_PK_CALLBACKS */
-                        }
-
-                        /* check size of peer RSA key */
-                        if (ret == 0 && ssl->peerRsaKeyPresent &&
-                                          !ssl->options.verifyNone &&
-                                          wc_RsaEncryptSize(ssl->peerRsaKey)
-                                              < ssl->options.minRsaKeySz) {
-                            ret = RSA_KEY_SIZE_E;
-                            WOLFSSL_MSG("Peer RSA key is too small");
-                        }
-                        break;
-                    }
-                #endif /* NO_RSA */
-                #ifdef HAVE_NTRU
-                    case NTRUk:
-                    {
-                        if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
-                            ret = PEER_KEY_ERROR;
-                        }
-                        else {
-                            XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey,
-                                                      args->dCert->pubKeySize);
-                            ssl->peerNtruKeyLen =
-                                (word16)args->dCert->pubKeySize;
-                            ssl->peerNtruKeyPresent = 1;
-                        }
-                        break;
-                    }
-                #endif /* HAVE_NTRU */
-                #ifdef HAVE_ECC
-                    case ECDSAk:
-                    {
-                        int keyRet = 0;
-                        word32 idx = 0;
-
-                        if (ssl->peerEccDsaKey == NULL) {
-                            /* alloc/init on demand */
-                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                    (void**)&ssl->peerEccDsaKey);
-                        } else if (ssl->peerEccDsaKeyPresent) {
-                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
-                                              ssl->peerEccDsaKey);
-                            ssl->peerEccDsaKeyPresent = 0;
-                        }
-
-                        if (keyRet != 0 ||
-                            wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
-                                                ssl->peerEccDsaKey,
-                                                args->dCert->pubKeySize) != 0) {
-                            ret = PEER_KEY_ERROR;
-                        }
-                        else {
-                            ssl->peerEccDsaKeyPresent = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                            ssl->buffers.peerEccDsaKey.buffer =
-                                   (byte*)XMALLOC(args->dCert->pubKeySize,
-                                           ssl->heap, DYNAMIC_TYPE_ECC);
-                            if (ssl->buffers.peerEccDsaKey.buffer == NULL) {
-                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
-                            }
-                            else {
-                                XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
-                                        args->dCert->publicKey,
-                                        args->dCert->pubKeySize);
-                                ssl->buffers.peerEccDsaKey.length =
-                                        args->dCert->pubKeySize;
-                            }
-                    #endif /* HAVE_PK_CALLBACKS */
-                        }
-
-                        /* check size of peer ECC key */
-                        if (ret == 0 && ssl->peerEccDsaKeyPresent &&
-                                              !ssl->options.verifyNone &&
-                                              wc_ecc_size(ssl->peerEccDsaKey)
-                                              < ssl->options.minEccKeySz) {
-                            ret = ECC_KEY_SIZE_E;
-                            WOLFSSL_MSG("Peer ECC key is too small");
-                        }
-                        break;
-                    }
-                #endif /* HAVE_ECC */
-                #ifdef HAVE_ED25519
-                    case ED25519k:
-                    {
-                        int keyRet = 0;
-                        if (ssl->peerEd25519Key == NULL) {
-                            /* alloc/init on demand */
-                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519,
-                                    (void**)&ssl->peerEd25519Key);
-                        } else if (ssl->peerEd25519KeyPresent) {
-                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519,
-                                              ssl->peerEd25519Key);
-                            ssl->peerEd25519KeyPresent = 0;
-                        }
-
-                        if (keyRet != 0 ||
-                            wc_ed25519_import_public(args->dCert->publicKey,
-                                                     args->dCert->pubKeySize,
-                                                     ssl->peerEd25519Key)
-                                                                         != 0) {
-                            ret = PEER_KEY_ERROR;
-                        }
-                        else {
-                            ssl->peerEd25519KeyPresent = 1;
-                    #ifdef HAVE_PK_CALLBACKS
-                            ssl->buffers.peerEd25519Key.buffer =
-                                   (byte*)XMALLOC(args->dCert->pubKeySize,
-                                           ssl->heap, DYNAMIC_TYPE_ED25519);
-                            if (ssl->buffers.peerEd25519Key.buffer == NULL) {
-                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
-                            }
-                            else {
-                                XMEMCPY(ssl->buffers.peerEd25519Key.buffer,
-                                        args->dCert->publicKey,
-                                        args->dCert->pubKeySize);
-                                ssl->buffers.peerEd25519Key.length =
-                                        args->dCert->pubKeySize;
-                            }
-                    #endif /*HAVE_PK_CALLBACKS */
-                        }
-
-                        /* check size of peer ECC key */
-                        if (ret == 0 && ssl->peerEd25519KeyPresent &&
-                                  !ssl->options.verifyNone &&
-                                  ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
-                            ret = ECC_KEY_SIZE_E;
-                            WOLFSSL_MSG("Peer ECC key is too small");
-                        }
-                        break;
-                    }
-                #endif /* HAVE_ED25519 */
-                    default:
-                        break;
-                }
-
-                FreeDecodedCert(args->dCert);
-                args->dCertInit = 0;
-
-                /* release since we don't need it anymore */
-                if (args->dCert) {
-                    XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
-                    args->dCert = NULL;
-                }
-            } /* if (count > 0) */
-
-            /* Check for error */
-            if (args->fatal && ret != 0) {
-                goto exit_ppc;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-        #ifdef WOLFSSL_SMALL_STACK
-            WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
-                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
-                                                    DYNAMIC_TYPE_X509_STORE);
-            if (store == NULL) {
-                ERROR_OUT(MEMORY_E, exit_ppc);
-            }
-        #else
-            WOLFSSL_X509_STORE_CTX  store[1];
-        #endif
-
-            XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
-
-            /* load last error */
-            if (args->lastErr != 0 && ret == 0) {
-                ret = args->lastErr;
-            }
-
-        #ifdef OPENSSL_EXTRA
-            if (args->untrustedDepth > ssl->options.verifyDepth) {
-                ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
-                ret = MAX_CHAIN_ERROR;
-            }
-        #endif
-            if (ret != 0) {
-                if (!ssl->options.verifyNone) {
-                    int why = bad_certificate;
-
-                    if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
-                        why = certificate_expired;
-                    }
-                    if (ssl->verifyCallback) {
-                        int ok;
-
-                        store->error = ret;
-                        store->error_depth = args->certIdx;
-                        store->discardSessionCerts = 0;
-                        store->domain = args->domain;
-                        store->userCtx = ssl->verifyCbCtx;
-                        store->certs = args->certs;
-                        store->totalCerts = args->totalCerts;
-
-                    #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-                        if (ssl->ctx->x509_store_pt != NULL) {
-                            store->store = ssl->ctx->x509_store_pt;
-                        }
-                        else {
-                            store->store = &ssl->ctx->x509_store;
-                        }
-                    #endif
-                    #ifdef KEEP_PEER_CERT
-                        if (ssl->peerCert.subject.sz > 0)
-                            store->current_cert = &ssl->peerCert;
-                        else
-                            store->current_cert = NULL;
-                    #else
-                        store->current_cert = NULL;
-                    #endif /* KEEP_PEER_CERT */
-                    #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS)
-                        store->ex_data = ssl;
-                    #endif
-                    #ifdef SESSION_CERTS
-                        store->sesChain = &(ssl->session.chain);
-                    #endif
-                        ok = ssl->verifyCallback(0, store);
-                        if (ok) {
-                            WOLFSSL_MSG("Verify callback overriding error!");
-                            ret = 0;
-                        }
-                    #ifdef SESSION_CERTS
-                        if (store->discardSessionCerts) {
-                            WOLFSSL_MSG("Verify callback requested discard sess certs");
-                            ssl->session.chain.count = 0;
-                        #ifdef WOLFSSL_ALT_CERT_CHAINS
-                            ssl->session.altChain.count = 0;
-                        #endif
-                        }
-                    #endif /* SESSION_CERTS */
-                    }
-                    if (ret != 0) {
-                        SendAlert(ssl, alert_fatal, why);   /* try to send */
-                        ssl->options.isClosed = 1;
-                    }
-                }
-
-                ssl->error = ret;
-            }
-        #ifdef WOLFSSL_ALWAYS_VERIFY_CB
-            else {
-                if (ssl->verifyCallback) {
-                    int ok;
-
-                    store->error = ret;
-                #ifdef WOLFSSL_WPAS
-                    store->error_depth = 0;
-                #else
-                    store->error_depth = args->certIdx;
-                #endif
-                    store->discardSessionCerts = 0;
-                    store->domain = args->domain;
-                    store->userCtx = ssl->verifyCbCtx;
-                    store->certs = args->certs;
-                    store->totalCerts = args->totalCerts;
-
-                #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-                    if (ssl->ctx->x509_store_pt != NULL) {
-                        store->store = ssl->ctx->x509_store_pt;
-                    }
-                    else {
-                        store->store = &ssl->ctx->x509_store;
-                    }
-                #endif
-                #ifdef KEEP_PEER_CERT
-                    if (ssl->peerCert.subject.sz > 0)
-                        store->current_cert = &ssl->peerCert;
-                    else
-                        store->current_cert = NULL;
-                #endif
-                    store->ex_data = ssl;
-                #ifdef SESSION_CERTS
-                    store->sesChain = &(ssl->session.chain);
-                #endif
-
-                    ok = ssl->verifyCallback(1, store);
-                    if (!ok) {
-                        WOLFSSL_MSG("Verify callback overriding valid certificate!");
-                        ret = -1;
-                        SendAlert(ssl, alert_fatal, bad_certificate);
-                        ssl->options.isClosed = 1;
-                    }
-                #ifdef SESSION_CERTS
-                    if (store->discardSessionCerts) {
-                        WOLFSSL_MSG("Verify callback requested discard sess certs");
-                        ssl->session.chain.count = 0;
-                    #ifdef WOLFSSL_ALT_CERT_CHAINS
-                        ssl->session.altChain.count = 0;
-                    #endif
-                    }
-                #endif /* SESSION_CERTS */
-                }
-            }
-        #endif /* WOLFSSL_ALWAYS_VERIFY_CB */
-
-            if (ssl->options.verifyNone &&
-                                      (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
-                WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
-                ret = ssl->error = 0;
-            }
-
-            if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
-                ssl->options.serverState = SERVER_CERT_COMPLETE;
-            }
-
-            if (IsEncryptionOn(ssl, 0)) {
-                args->idx += ssl->keys.padSz;
-            }
-
-        #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
-            wolfSSL_sk_X509_free(store->chain);
-            store->chain = NULL;
-        #endif
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
-        #endif
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_END:
-        {
-            /* Set final index */
-            *inOutIdx = args->idx;
-
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-            break;
-    } /* switch(ssl->options.asyncState) */
-
-exit_ppc:
-
-    WOLFSSL_LEAVE("ProcessPeerCerts", ret);
-
-
-#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
-    if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) {
-        /* Mark message as not recevied so it can process again */
-        ssl->msgsReceived.got_certificate = 0;
-
-        return ret;
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
-
-    FreeProcPeerCertArgs(ssl, args);
-
-#if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_NONBLOCK_OCSP)
-    XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    ssl->nonblockarg = NULL;
-#endif
-
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-
-#ifndef WOLFSSL_NO_TLS12
-
-/* handle processing of certificate (11) */
-static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                                                                word32 size)
-{
-    int ret;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
-    WOLFSSL_ENTER("DoCertificate");
-
-    ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
-
-#ifdef OPENSSL_EXTRA
-    ssl->options.serverState = SERVER_CERT_COMPLETE;
-#endif
-
-    WOLFSSL_LEAVE("DoCertificate", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
-
-    return ret;
-}
-
-/* handle processing of certificate_status (22) */
-static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                                                                    word32 size)
-{
-    int    ret = 0;
-    byte   status_type;
-    word32 status_length;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
-    WOLFSSL_ENTER("DoCertificateStatus");
-
-    if (size < ENUM_LEN + OPAQUE24_LEN)
-        return BUFFER_ERROR;
-
-    status_type = input[(*inOutIdx)++];
-
-    c24to32(input + *inOutIdx, &status_length);
-    *inOutIdx += OPAQUE24_LEN;
-
-    if (size != ENUM_LEN + OPAQUE24_LEN + status_length)
-        return BUFFER_ERROR;
-
-    switch (status_type) {
-
-    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
-     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-
-        /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
-        case WOLFSSL_CSR2_OCSP:
-            ret = ProcessCSR(ssl, input, inOutIdx, status_length);
-            break;
-
-    #endif
-
-    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-
-        case WOLFSSL_CSR2_OCSP_MULTI: {
-            OcspRequest* request;
-            word32 list_length = status_length;
-            byte   idx = 0;
-
-            #ifdef WOLFSSL_SMALL_STACK
-                CertStatus* status;
-                OcspResponse* response;
-            #else
-                CertStatus status[1];
-                OcspResponse response[1];
-            #endif
-
-            do {
-                if (ssl->status_request_v2) {
-                    ssl->status_request_v2 = 0;
-                    break;
-                }
-
-                return BUFFER_ERROR;
-            } while(0);
-
-            #ifdef WOLFSSL_SMALL_STACK
-                status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
-                                                       DYNAMIC_TYPE_OCSP_STATUS);
-                response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
-                                                       DYNAMIC_TYPE_OCSP_REQUEST);
-
-                if (status == NULL || response == NULL) {
-                    if (status)
-                        XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
-                    if (response)
-                        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-
-                    return MEMORY_ERROR;
-                }
-            #endif
-
-            while (list_length && ret == 0) {
-                if (OPAQUE24_LEN > list_length) {
-                    ret = BUFFER_ERROR;
-                    break;
-                }
-
-                c24to32(input + *inOutIdx, &status_length);
-                *inOutIdx   += OPAQUE24_LEN;
-                list_length -= OPAQUE24_LEN;
-
-                if (status_length > list_length) {
-                    ret = BUFFER_ERROR;
-                    break;
-                }
-
-                if (status_length) {
-                    InitOcspResponse(response, status, input +*inOutIdx,
-                                                                 status_length);
-
-                    if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
-                                                                        0) != 0)
-                    ||  (response->responseStatus != OCSP_SUCCESSFUL)
-                    ||  (response->status->status != CERT_GOOD))
-                        ret = BAD_CERTIFICATE_STATUS_ERROR;
-
-                    while (ret == 0) {
-                        request = (OcspRequest*)TLSX_CSR2_GetRequest(
-                                ssl->extensions, status_type, idx++);
-
-                        if (request == NULL)
-                            ret = BAD_CERTIFICATE_STATUS_ERROR;
-                        else if (CompareOcspReqResp(request, response) == 0)
-                            break;
-                        else if (idx == 1) /* server cert must be OK */
-                            ret = BAD_CERTIFICATE_STATUS_ERROR;
-                    }
-
-                    *inOutIdx   += status_length;
-                    list_length -= status_length;
-                }
-            }
-
-            #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-                ssl->status_request_v2 = 0;
-            #endif
-
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(status,   NULL, DYNAMIC_TYPE_OCSP_STATUS);
-                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
-            #endif
-
-        }
-        break;
-
-    #endif
-
-        default:
-            ret = BUFFER_ERROR;
-    }
-
-    if (ret != 0)
-        SendAlert(ssl, alert_fatal, bad_certificate_status_response);
-
-    WOLFSSL_LEAVE("DoCertificateStatus", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO);
-
-    return ret;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#endif /* !NO_CERTS */
-
-#ifndef WOLFSSL_NO_TLS12
-
-static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                                                    word32 size, word32 totalSz)
-{
-    (void)input;
-
-    if (size) /* must be 0 */
-        return BUFFER_ERROR;
-
-    if (IsEncryptionOn(ssl, 0)) {
-        /* access beyond input + size should be checked against totalSz */
-        if (*inOutIdx + ssl->keys.padSz > totalSz)
-            return BUFFER_E;
-
-        *inOutIdx += ssl->keys.padSz;
-    }
-
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-        SendAlert(ssl, alert_fatal, unexpected_message); /* try */
-        return FATAL_ERROR;
-    }
-#ifdef HAVE_SECURE_RENEGOTIATION
-    else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
-        ssl->secure_renegotiation->startScr = 1;
-        return 0;
-    }
-#endif
-    else {
-        return SendAlert(ssl, alert_warning, no_renegotiation);
-    }
-}
-
-
-int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
-                                                      word32 totalSz, int sniff)
-{
-    word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ);
-
-    WOLFSSL_START(WC_FUNC_FINISHED_DO);
-    WOLFSSL_ENTER("DoFinished");
-
-    if (finishedSz != size)
-        return BUFFER_ERROR;
-
-    /* check against totalSz */
-    if (*inOutIdx + size + ssl->keys.padSz > totalSz)
-        return BUFFER_E;
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
-        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
-    #endif
-
-    if (sniff == NO_SNIFF) {
-        if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){
-            WOLFSSL_MSG("Verify finished error on hashes");
-            return VERIFY_FINISHED_ERROR;
-        }
-    }
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (ssl->secure_renegotiation) {
-        /* save peer's state */
-        if (ssl->options.side == WOLFSSL_CLIENT_END)
-            XMEMCPY(ssl->secure_renegotiation->server_verify_data,
-                    input + *inOutIdx, TLS_FINISHED_SZ);
-        else
-            XMEMCPY(ssl->secure_renegotiation->client_verify_data,
-                    input + *inOutIdx, TLS_FINISHED_SZ);
-    }
-#endif
-
-    /* force input exhaustion at ProcessReply consuming padSz */
-    *inOutIdx += size + ssl->keys.padSz;
-
-    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-#ifdef OPENSSL_EXTRA
-		ssl->cbmode = SSL_CB_MODE_WRITE;
-		ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-#endif
-        if (!ssl->options.resuming) {
-#ifdef OPENSSL_EXTRA
-			if (ssl->CBIS != NULL) {
-				ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
-			}
-#endif
-			ssl->options.handShakeState = HANDSHAKE_DONE;
-			ssl->options.handShakeDone  = 1;
-		}
-    }
-    else {
-        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-#ifdef OPENSSL_EXTRA
-        ssl->cbmode = SSL_CB_MODE_READ;
-        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-#endif
-        if (ssl->options.resuming) {
-#ifdef OPENSSL_EXTRA
-			if (ssl->CBIS != NULL) {
-				ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
-			}
-#endif
-			ssl->options.handShakeState = HANDSHAKE_DONE;
-			ssl->options.handShakeDone  = 1;
-        }
-    }
-
-    WOLFSSL_LEAVE("DoFinished", 0);
-    WOLFSSL_END(WC_FUNC_FINISHED_DO);
-
-    return 0;
-}
-
-
-/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
-static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
-{
-    /* verify not a duplicate, mark received, check state */
-    switch (type) {
-
-#ifndef NO_WOLFSSL_CLIENT
-        case hello_request:
-            if (ssl->msgsReceived.got_hello_request) {
-                WOLFSSL_MSG("Duplicate HelloRequest received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_hello_request = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-        case client_hello:
-            if (ssl->msgsReceived.got_client_hello) {
-                WOLFSSL_MSG("Duplicate ClientHello received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_client_hello = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case server_hello:
-            if (ssl->msgsReceived.got_server_hello) {
-                WOLFSSL_MSG("Duplicate ServerHello received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_server_hello = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case hello_verify_request:
-            if (ssl->msgsReceived.got_hello_verify_request) {
-                WOLFSSL_MSG("Duplicate HelloVerifyRequest received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_hello_verify_request = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case session_ticket:
-            if (ssl->msgsReceived.got_session_ticket) {
-                WOLFSSL_MSG("Duplicate SessionTicket received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_session_ticket = 1;
-
-            break;
-#endif
-
-        case certificate:
-            if (ssl->msgsReceived.got_certificate) {
-                WOLFSSL_MSG("Duplicate Certificate received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate = 1;
-
-#ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                if ( ssl->msgsReceived.got_server_hello == 0) {
-                    WOLFSSL_MSG("No ServerHello before Cert");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-#endif
-#ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                if ( ssl->msgsReceived.got_client_hello == 0) {
-                    WOLFSSL_MSG("No ClientHello before Cert");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-#endif
-            break;
-
-#ifndef NO_WOLFSSL_CLIENT
-        case certificate_status:
-            if (ssl->msgsReceived.got_certificate_status) {
-                WOLFSSL_MSG("Duplicate CertificateSatatus received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate_status = 1;
-
-            if (ssl->msgsReceived.got_certificate == 0) {
-                WOLFSSL_MSG("No Certificate before CertificateStatus");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_server_key_exchange != 0) {
-                WOLFSSL_MSG("CertificateStatus after ServerKeyExchange");
-                return OUT_OF_ORDER_E;
-            }
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case server_key_exchange:
-            if (ssl->msgsReceived.got_server_key_exchange) {
-                WOLFSSL_MSG("Duplicate ServerKeyExchange received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_server_key_exchange = 1;
-
-            if (ssl->msgsReceived.got_server_hello == 0) {
-                WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_certificate_status == 0) {
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-                if (ssl->status_request) {
-                    int ret;
-
-                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
-                    if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
-                        return ret;
-                }
-#endif
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-                if (ssl->status_request_v2) {
-                    int ret;
-
-                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
-                    if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
-                        return ret;
-                }
-#endif
-            }
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case certificate_request:
-            if (ssl->msgsReceived.got_certificate_request) {
-                WOLFSSL_MSG("Duplicate CertificateRequest received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate_request = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case server_hello_done:
-            if (ssl->msgsReceived.got_server_hello_done) {
-                WOLFSSL_MSG("Duplicate ServerHelloDone received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_server_hello_done = 1;
-
-            if (ssl->msgsReceived.got_certificate == 0) {
-                if (ssl->specs.kea == psk_kea ||
-                    ssl->specs.kea == dhe_psk_kea ||
-                    ssl->specs.kea == ecdhe_psk_kea ||
-                    ssl->options.usingAnon_cipher) {
-                    WOLFSSL_MSG("No Cert required");
-                } else {
-                    WOLFSSL_MSG("No Certificate before ServerHelloDone");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-            if (ssl->msgsReceived.got_server_key_exchange == 0) {
-                int pskNoServerHint = 0;  /* not required in this case */
-
-                #ifndef NO_PSK
-                    if (ssl->specs.kea == psk_kea &&
-                                               ssl->arrays->server_hint[0] == 0)
-                        pskNoServerHint = 1;
-                #endif
-                if (ssl->specs.static_ecdh == 1 ||
-                    ssl->specs.kea == rsa_kea ||
-                    ssl->specs.kea == ntru_kea ||
-                    pskNoServerHint) {
-                    WOLFSSL_MSG("No KeyExchange required");
-                } else {
-                    WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-        case certificate_verify:
-            if (ssl->msgsReceived.got_certificate_verify) {
-                WOLFSSL_MSG("Duplicate CertificateVerify received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate_verify = 1;
-
-            if ( ssl->msgsReceived.got_certificate == 0) {
-                WOLFSSL_MSG("No Cert before CertVerify");
-                return OUT_OF_ORDER_E;
-            }
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-        case client_key_exchange:
-            if (ssl->msgsReceived.got_client_key_exchange) {
-                WOLFSSL_MSG("Duplicate ClientKeyExchange received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_client_key_exchange = 1;
-
-            if (ssl->msgsReceived.got_client_hello == 0) {
-                WOLFSSL_MSG("No ClientHello before ClientKeyExchange");
-                return OUT_OF_ORDER_E;
-            }
-            break;
-#endif
-
-        case finished:
-            if (ssl->msgsReceived.got_finished) {
-                WOLFSSL_MSG("Duplicate Finished received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_finished = 1;
-
-            if (ssl->msgsReceived.got_change_cipher == 0) {
-                WOLFSSL_MSG("Finished received before ChangeCipher");
-                return NO_CHANGE_CIPHER_E;
-            }
-            break;
-
-        case change_cipher_hs:
-            if (ssl->msgsReceived.got_change_cipher) {
-                WOLFSSL_MSG("Duplicate ChangeCipher received");
-                return DUPLICATE_MSG_E;
-            }
-            /* DTLS is going to ignore the CCS message if the client key
-             * exchange message wasn't received yet. */
-            if (!ssl->options.dtls)
-                ssl->msgsReceived.got_change_cipher = 1;
-
-#ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                if (!ssl->options.resuming &&
-                                 ssl->msgsReceived.got_server_hello_done == 0) {
-                    WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
-                    return OUT_OF_ORDER_E;
-                }
-                #ifdef HAVE_SESSION_TICKET
-                    if (ssl->expect_session_ticket) {
-                        WOLFSSL_MSG("Expected session ticket missing");
-                        #ifdef WOLFSSL_DTLS
-                            if (ssl->options.dtls)
-                                return OUT_OF_ORDER_E;
-                        #endif
-                        return SESSION_TICKET_EXPECT_E;
-                    }
-                #endif
-            }
-#endif
-#ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                if (!ssl->options.resuming &&
-                               ssl->msgsReceived.got_client_key_exchange == 0) {
-                    WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher");
-                    return OUT_OF_ORDER_E;
-                }
-                #ifndef NO_CERTS
-                    if (ssl->options.verifyPeer &&
-                        ssl->options.havePeerCert) {
-
-                        if (!ssl->options.havePeerVerify) {
-                            WOLFSSL_MSG("client didn't send cert verify");
-                            #ifdef WOLFSSL_DTLS
-                                if (ssl->options.dtls)
-                                    return OUT_OF_ORDER_E;
-                            #endif
-                            return NO_PEER_VERIFY;
-                        }
-                    }
-                #endif
-            }
-#endif
-            if (ssl->options.dtls)
-                ssl->msgsReceived.got_change_cipher = 1;
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown message type");
-            return SANITY_MSG_E;
-    }
-
-    return 0;
-}
-
-
-static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                          byte type, word32 size, word32 totalSz)
-{
-    int ret = 0;
-    word32 expectedIdx;
-
-    WOLFSSL_ENTER("DoHandShakeMsgType");
-
-#ifdef WOLFSSL_TLS13
-    if (type == hello_retry_request) {
-        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
-                                       totalSz);
-    }
-#endif
-
-    /* make sure can read the message */
-    if (*inOutIdx + size > totalSz)
-        return INCOMPLETE_DATA;
-
-    expectedIdx = *inOutIdx + size +
-                  (ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
-
-    /* sanity check msg received */
-    if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) {
-        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
-        return ret;
-    }
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-    /* add name later, add on record and handshake header part back on */
-    if (ssl->toInfoOn) {
-        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
-                      size + add, READ_PROTO, ssl->heap);
-        #ifdef WOLFSSL_CALLBACKS
-        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
-        #endif
-    }
-#endif
-
-    if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
-        WOLFSSL_MSG("HandShake message after handshake complete");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 &&
-               ssl->options.serverState == NULL_STATE && type != server_hello) {
-        WOLFSSL_MSG("First server message not server hello");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls &&
-            type == server_hello_done &&
-            ssl->options.serverState < SERVER_HELLO_COMPLETE) {
-        WOLFSSL_MSG("Server hello done received before server hello in DTLS");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->options.side == WOLFSSL_SERVER_END &&
-               ssl->options.clientState == NULL_STATE && type != client_hello) {
-        WOLFSSL_MSG("First client message not client hello");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    /* above checks handshake state */
-    /* hello_request not hashed */
-    /* Also, skip hashing the client_hello message here for DTLS. It will be
-     * hashed later if the DTLS cookie is correct. */
-    if (type != hello_request &&
-            !(IsDtlsNotSctpMode(ssl) && type == client_hello)
-    #ifdef WOLFSSL_ASYNC_CRYPT
-            && ssl->error != WC_PENDING_E
-    #endif
-    #ifdef WOLFSSL_NONBLOCK_OCSP
-            && ssl->error != OCSP_WANT_READ
-    #endif
-    ) {
-        ret = HashInput(ssl, input + *inOutIdx, size);
-        if (ret != 0) return ret;
-    }
-
-#ifdef OPENSSL_EXTRA
-    if (ssl->CBIS != NULL){
-		ssl->cbmode = SSL_CB_MODE_READ;
-		ssl->cbtype = type;
-		ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
-    }
-#endif
-
-    switch (type) {
-
-    case hello_request:
-        WOLFSSL_MSG("processing hello request");
-        ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz);
-        break;
-
-#ifndef NO_WOLFSSL_CLIENT
-    case hello_verify_request:
-        WOLFSSL_MSG("processing hello verify request");
-        ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size);
-        break;
-
-    case server_hello:
-        WOLFSSL_MSG("processing server hello");
-        ret = DoServerHello(ssl, input, inOutIdx, size);
-    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-        if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) ||
-                                               IsAtLeastTLSv1_3(ssl->version)) {
-            ssl->options.cacheMessages = 0;
-        }
-    #endif
-        break;
-
-#ifndef NO_CERTS
-    case certificate_request:
-        WOLFSSL_MSG("processing certificate request");
-        ret = DoCertificateRequest(ssl, input, inOutIdx, size);
-        break;
-#endif
-
-    case server_key_exchange:
-        WOLFSSL_MSG("processing server key exchange");
-        ret = DoServerKeyExchange(ssl, input, inOutIdx, size);
-        break;
-
-#ifdef HAVE_SESSION_TICKET
-    case session_ticket:
-        WOLFSSL_MSG("processing session ticket");
-        ret = DoSessionTicket(ssl, input, inOutIdx, size);
-        break;
-#endif /* HAVE_SESSION_TICKET */
-#endif
-
-#ifndef NO_CERTS
-    case certificate:
-        WOLFSSL_MSG("processing certificate");
-        ret = DoCertificate(ssl, input, inOutIdx, size);
-        break;
-
-    case certificate_status:
-        WOLFSSL_MSG("processing certificate status");
-        ret = DoCertificateStatus(ssl, input, inOutIdx, size);
-        break;
-#endif
-
-    case server_hello_done:
-        WOLFSSL_MSG("processing server hello done");
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "ServerHelloDone");
-        if (ssl->toInfoOn)
-            AddLateName("ServerHelloDone", &ssl->timeoutInfo);
-    #endif
-        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
-        if (IsEncryptionOn(ssl, 0)) {
-            *inOutIdx += ssl->keys.padSz;
-        }
-        if (ssl->options.resuming) {
-            WOLFSSL_MSG("Not resuming as thought");
-            ssl->options.resuming = 0;
-        }
-        break;
-
-    case finished:
-        WOLFSSL_MSG("processing finished");
-        ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
-        break;
-
-#ifndef NO_WOLFSSL_SERVER
-    case client_hello:
-        WOLFSSL_MSG("processing client hello");
-        ret = DoClientHello(ssl, input, inOutIdx, size);
-    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-        if (ssl->options.resuming || !ssl->options.verifyPeer || \
-                     !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) {
-            ssl->options.cacheMessages = 0;
-        }
-    #endif
-        break;
-
-    case client_key_exchange:
-        WOLFSSL_MSG("processing client key exchange");
-        ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
-        break;
-
-#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
-                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
-    case certificate_verify:
-        WOLFSSL_MSG("processing certificate verify");
-        ret = DoCertificateVerify(ssl, input, inOutIdx, size);
-        break;
-#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
-
-#endif /* !NO_WOLFSSL_SERVER */
-
-    default:
-        WOLFSSL_MSG("Unknown handshake message type");
-        ret = UNKNOWN_HANDSHAKE_TYPE;
-        break;
-    }
-    if (ret == 0 && expectedIdx != *inOutIdx) {
-        WOLFSSL_MSG("Extra data in handshake message");
-        if (!ssl->options.dtls)
-            SendAlert(ssl, alert_fatal, decode_error);
-        ret = DECODE_E;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
-    /* if async, offset index so this msg will be processed again */
-    if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
-        *inOutIdx -= HANDSHAKE_HEADER_SZ;
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            *inOutIdx -= DTLS_HANDSHAKE_EXTRA;
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
-
-    WOLFSSL_LEAVE("DoHandShakeMsgType()", ret);
-    return ret;
-}
-
-
-static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                          word32 totalSz)
-{
-    int    ret = 0;
-    word32 inputLength;
-
-    WOLFSSL_ENTER("DoHandShakeMsg()");
-
-    if (ssl->arrays == NULL) {
-        byte   type;
-        word32 size;
-
-        if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
-            return PARSE_ERROR;
-
-        ssl->options.handShakeState = type;
-
-        return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
-    }
-
-    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx;
-
-    /* If there is a pending fragmented handshake message,
-     * pending message size will be non-zero. */
-    if (ssl->arrays->pendingMsgSz == 0) {
-        byte   type;
-        word32 size;
-
-        if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
-            return PARSE_ERROR;
-
-        /* Cap the maximum size of a handshake message to something reasonable.
-         * By default is the maximum size of a certificate message assuming
-         * nine 2048-bit RSA certificates in the chain. */
-        if (size > MAX_HANDSHAKE_SZ) {
-            WOLFSSL_MSG("Handshake message too large");
-            return HANDSHAKE_SIZE_ERROR;
-        }
-
-        /* size is the size of the certificate message payload */
-        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
-            ssl->arrays->pendingMsgType = type;
-            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
-            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
-                                                     ssl->heap,
-                                                     DYNAMIC_TYPE_ARRAYS);
-            if (ssl->arrays->pendingMsg == NULL)
-                return MEMORY_E;
-            XMEMCPY(ssl->arrays->pendingMsg,
-                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
-                    inputLength);
-            ssl->arrays->pendingMsgOffset = inputLength;
-            *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
-            return 0;
-        }
-
-        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
-    }
-    else {
-        if (inputLength + ssl->arrays->pendingMsgOffset
-                                                  > ssl->arrays->pendingMsgSz) {
-
-            return BUFFER_ERROR;
-        }
-
-        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
-                input + *inOutIdx, inputLength);
-        ssl->arrays->pendingMsgOffset += inputLength;
-        *inOutIdx += inputLength;
-
-        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
-        {
-            word32 idx = 0;
-            ret = DoHandShakeMsgType(ssl,
-                                     ssl->arrays->pendingMsg
-                                                          + HANDSHAKE_HEADER_SZ,
-                                     &idx, ssl->arrays->pendingMsgType,
-                                     ssl->arrays->pendingMsgSz
-                                                          - HANDSHAKE_HEADER_SZ,
-                                     ssl->arrays->pendingMsgSz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E) {
-                /* setup to process fragment again */
-                ssl->arrays->pendingMsgOffset -= inputLength;
-                *inOutIdx -= inputLength;
-            }
-            else
-        #endif
-            {
-                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
-                ssl->arrays->pendingMsg = NULL;
-                ssl->arrays->pendingMsgSz = 0;
-            }
-        }
-    }
-
-    WOLFSSL_LEAVE("DoHandShakeMsg()", ret);
-    return ret;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef WOLFSSL_DTLS
-
-static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
-{
-    word32* window;
-    word16 cur_hi, next_hi;
-    word32 cur_lo, next_lo, diff;
-    int curLT;
-    WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL;
-
-    if (!ssl->options.haveMcast)
-        peerSeq = ssl->keys.peerSeq;
-    else {
-#ifdef WOLFSSL_MULTICAST
-        WOLFSSL_DTLS_PEERSEQ* p;
-        int i;
-
-        for (i = 0, p = ssl->keys.peerSeq;
-             i < WOLFSSL_DTLS_PEERSEQ_SZ;
-             i++, p++) {
-
-            if (p->peerId == ssl->keys.curPeerId) {
-                peerSeq = p;
-                break;
-            }
-        }
-#endif
-    }
-
-    if (peerSeq == NULL) {
-        WOLFSSL_MSG("Could not find peer sequence");
-        return 0;
-    }
-
-    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
-        next_hi = peerSeq->nextSeq_hi;
-        next_lo = peerSeq->nextSeq_lo;
-        window = peerSeq->window;
-    }
-    else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) {
-        next_hi = peerSeq->prevSeq_hi;
-        next_lo = peerSeq->prevSeq_lo;
-        window = peerSeq->prevWindow;
-    }
-    else {
-        return 0;
-    }
-
-    cur_hi = ssl->keys.curSeq_hi;
-    cur_lo = ssl->keys.curSeq_lo;
-
-    /* If the difference between next and cur is > 2^32, way outside window. */
-    if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) {
-        WOLFSSL_MSG("Current record from way too far in the future.");
-        return 0;
-    }
-
-    if (cur_hi == next_hi) {
-        curLT = cur_lo < next_lo;
-        diff = curLT ? next_lo - cur_lo : cur_lo - next_lo;
-    }
-    else {
-        curLT = cur_hi < next_hi;
-        diff = curLT ? cur_lo - next_lo : next_lo - cur_lo;
-    }
-
-    /* Check to see that the next value is greater than the number of messages
-     * trackable in the window, and that the difference between the next
-     * expected sequence number and the received sequence number is inside the
-     * window. */
-    if ((next_hi || next_lo > DTLS_SEQ_BITS) &&
-        curLT && (diff > DTLS_SEQ_BITS)) {
-
-        WOLFSSL_MSG("Current record sequence number from the past.");
-        return 0;
-    }
-#ifndef WOLFSSL_DTLS_ALLOW_FUTURE
-    else if (!curLT && (diff > DTLS_SEQ_BITS)) {
-        WOLFSSL_MSG("Rejecting message too far into the future.");
-        return 0;
-    }
-#endif
-    else if (curLT) {
-        word32 idx = diff / DTLS_WORD_BITS;
-        word32 newDiff = diff % DTLS_WORD_BITS;
-
-        /* verify idx is valid for window array */
-        if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) {
-            WOLFSSL_MSG("Invalid DTLS windows index");
-            return 0;
-        }
-
-        if (window[idx] & (1 << (newDiff - 1))) {
-            WOLFSSL_MSG("Current record sequence number already received.");
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-
-#ifdef WOLFSSL_MULTICAST
-static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
-                                         word32 second, word32 max)
-{
-    word32 newCur = 0;
-
-    if (cur < first)
-        newCur = first;
-    else if (cur < second)
-        newCur = second;
-    else if (cur < max)
-        newCur = max;
-
-    return newCur;
-}
-#endif /* WOLFSSL_MULTICAST */
-
-
-static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
-{
-    word32* window;
-    word32* next_lo;
-    word16* next_hi;
-    int curLT;
-    word32 cur_lo, diff;
-    word16 cur_hi;
-    WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
-
-    cur_hi = ssl->keys.curSeq_hi;
-    cur_lo = ssl->keys.curSeq_lo;
-
-#ifdef WOLFSSL_MULTICAST
-    if (ssl->options.haveMcast) {
-        WOLFSSL_DTLS_PEERSEQ* p;
-        int i;
-
-        peerSeq = NULL;
-        for (i = 0, p = ssl->keys.peerSeq;
-             i < WOLFSSL_DTLS_PEERSEQ_SZ;
-             i++, p++) {
-
-            if (p->peerId == ssl->keys.curPeerId) {
-                peerSeq = p;
-                break;
-            }
-        }
-
-        if (peerSeq == NULL) {
-            WOLFSSL_MSG("Couldn't find that peer ID to update window.");
-            return 0;
-        }
-
-        if (p->highwaterMark && cur_lo >= p->highwaterMark) {
-            int cbError = 0;
-
-            if (ssl->ctx->mcastHwCb)
-                cbError = ssl->ctx->mcastHwCb(p->peerId,
-                                              ssl->ctx->mcastMaxSeq,
-                                              cur_lo, ssl->mcastHwCbCtx);
-            if (cbError) {
-                WOLFSSL_MSG("Multicast highwater callback returned an error.");
-                return MCAST_HIGHWATER_CB_E;
-            }
-
-            p->highwaterMark = UpdateHighwaterMark(cur_lo,
-                                                   ssl->ctx->mcastFirstSeq,
-                                                   ssl->ctx->mcastSecondSeq,
-                                                   ssl->ctx->mcastMaxSeq);
-        }
-    }
-#endif
-
-    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
-        next_hi = &peerSeq->nextSeq_hi;
-        next_lo = &peerSeq->nextSeq_lo;
-        window = peerSeq->window;
-    }
-    else {
-        next_hi = &peerSeq->prevSeq_hi;
-        next_lo = &peerSeq->prevSeq_lo;
-        window = peerSeq->prevWindow;
-    }
-
-    if (cur_hi == *next_hi) {
-        curLT = cur_lo < *next_lo;
-        diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo;
-    }
-    else {
-        curLT = cur_hi < *next_hi;
-        diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo;
-    }
-
-    if (curLT) {
-        word32 idx = diff / DTLS_WORD_BITS;
-        word32 newDiff = diff % DTLS_WORD_BITS;
-
-        if (idx < WOLFSSL_DTLS_WINDOW_WORDS)
-            window[idx] |= (1 << (newDiff - 1));
-    }
-    else {
-        if (diff >= DTLS_SEQ_BITS)
-            XMEMSET(window, 0, DTLS_SEQ_SZ);
-        else {
-            word32 idx, newDiff, temp, i;
-            word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS];
-
-            temp = 0;
-            diff++;
-            idx = diff / DTLS_WORD_BITS;
-            newDiff = diff % DTLS_WORD_BITS;
-
-            XMEMCPY(oldWindow, window, sizeof(oldWindow));
-
-            for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
-                if (i < idx)
-                    window[i] = 0;
-                else {
-                    temp |= (oldWindow[i-idx] << newDiff);
-                    window[i] = temp;
-                    temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff);
-                }
-            }
-        }
-        window[0] |= 1;
-        *next_lo = cur_lo + 1;
-        if (*next_lo < cur_lo)
-            (*next_hi)++;
-    }
-
-    return 1;
-}
-
-
-static int DtlsMsgDrain(WOLFSSL* ssl)
-{
-    DtlsMsg* item = ssl->dtls_rx_msg_list;
-    int ret = 0;
-
-    /* While there is an item in the store list, and it is the expected
-     * message, and it is complete, and there hasn't been an error in the
-     * last messge... */
-    while (item != NULL &&
-            ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
-            item->fragSz == item->sz &&
-            ret == 0) {
-        word32 idx = 0;
-        ssl->keys.dtls_expected_peer_handshake_number++;
-        ret = DoHandShakeMsgType(ssl, item->msg,
-                                 &idx, item->type, item->sz, item->sz);
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        if (ret == WC_PENDING_E) {
-            ssl->keys.dtls_expected_peer_handshake_number--;
-            break;
-        }
-    #endif
-        ssl->dtls_rx_msg_list = item->next;
-        DtlsMsgDelete(item, ssl->heap);
-        item = ssl->dtls_rx_msg_list;
-        ssl->dtls_rx_msg_list_sz--;
-    }
-
-    return ret;
-}
-
-
-static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                          word32 totalSz)
-{
-    byte type;
-    word32 size;
-    word32 fragOffset, fragSz;
-    int ret = 0;
-
-    WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
-
-    /* process any pending DTLS messages - this flow can happen with async */
-    if (ssl->dtls_rx_msg_list != NULL) {
-        ret = DtlsMsgDrain(ssl);
-        if (ret != 0)
-            return ret;
-
-        /* if done processing fragment exit with success */
-        if (totalSz == *inOutIdx)
-            return ret;
-    }
-
-    /* parse header */
-    if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
-                               &size, &fragOffset, &fragSz, totalSz) != 0)
-        return PARSE_ERROR;
-
-    /* check that we have complete fragment */
-    if (*inOutIdx + fragSz > totalSz)
-        return INCOMPLETE_DATA;
-
-    /* Check the handshake sequence number first. If out of order,
-     * add the current message to the list. If the message is in order,
-     * but it is a fragment, add the current message to the list, then
-     * check the head of the list to see if it is complete, if so, pop
-     * it out as the current message. If the message is complete and in
-     * order, process it. Check the head of the list to see if it is in
-     * order, if so, process it. (Repeat until list exhausted.) If the
-     * head is out of order, return for more processing.
-     */
-    if (ssl->keys.dtls_peer_handshake_number >
-                                ssl->keys.dtls_expected_peer_handshake_number) {
-        /* Current message is out of order. It will get stored in the list.
-         * Storing also takes care of defragmentation. If the messages is a
-         * client hello, we need to process this out of order; the server
-         * is not supposed to keep state, but the second client hello will
-         * have a different handshake sequence number than is expected, and
-         * the server shouldn't be expecting any particular handshake sequence
-         * number. (If the cookie changes multiple times in quick succession,
-         * the client could be sending multiple new client hello messages
-         * with newer and newer cookies.) */
-        if (type != client_hello) {
-            if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
-                DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
-                             input + *inOutIdx, size, type,
-                             fragOffset, fragSz, ssl->heap);
-            }
-            *inOutIdx += fragSz;
-            ret = 0;
-        }
-        else {
-            ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
-            if (ret == 0) {
-                ssl->keys.dtls_expected_peer_handshake_number =
-                    ssl->keys.dtls_peer_handshake_number + 1;
-            }
-        }
-    }
-    else if (ssl->keys.dtls_peer_handshake_number <
-                                ssl->keys.dtls_expected_peer_handshake_number) {
-        /* Already saw this message and processed it. It can be ignored. */
-        *inOutIdx += fragSz;
-        if(type == finished ) {
-            if (*inOutIdx + ssl->keys.padSz > totalSz) {
-                return BUFFER_E;
-            }
-            *inOutIdx += ssl->keys.padSz;
-        }
-        if (IsDtlsNotSctpMode(ssl) &&
-            VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) {
-
-            ret = DtlsMsgPoolSend(ssl, 0);
-        }
-    }
-    else if (fragSz < size) {
-        /* Since this branch is in order, but fragmented, dtls_rx_msg_list will
-         * be pointing to the message with this fragment in it. Check it to see
-         * if it is completed. */
-        if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
-            DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
-                         input + *inOutIdx, size, type,
-                         fragOffset, fragSz, ssl->heap);
-        }
-        *inOutIdx += fragSz;
-        ret = 0;
-        if (ssl->dtls_rx_msg_list != NULL &&
-            ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz)
-            ret = DtlsMsgDrain(ssl);
-    }
-    else {
-        /* This branch is in order next, and a complete message. */
-        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
-        if (ret == 0) {
-            if (type != client_hello || !IsDtlsNotSctpMode(ssl))
-                ssl->keys.dtls_expected_peer_handshake_number++;
-            if (ssl->dtls_rx_msg_list != NULL) {
-                ret = DtlsMsgDrain(ssl);
-            }
-        }
-    }
-
-    WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
-    return ret;
-}
-#endif
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef HAVE_AEAD
-static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
-{
-    int i;
-    for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) {
-        if (++ssl->keys.aead_exp_IV[i]) return;
-    }
-}
-
-
-#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
-/* Used for the older version of creating AEAD tags with Poly1305 */
-static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
-                       byte* cipher, word16 sz, byte* tag)
-{
-    int ret       = 0;
-    int msglen    = (sz - ssl->specs.aead_mac_size);
-    word32 keySz  = 32;
-    byte padding[8]; /* used to temporarily store lengths */
-
-#ifdef CHACHA_AEAD_TEST
-      printf("Using old version of poly1305 input.\n");
-#endif
-
-    if (msglen < 0)
-        return INPUT_CASE_ERROR;
-
-    if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
-        return ret;
-
-    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
-                   AEAD_AUTH_DATA_SZ)) != 0)
-        return ret;
-
-    /* length of additional input plus padding */
-    XMEMSET(padding, 0, sizeof(padding));
-    padding[0] = AEAD_AUTH_DATA_SZ;
-    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding,
-                    sizeof(padding))) != 0)
-        return ret;
-
-
-    /* add cipher info and then its length */
-    XMEMSET(padding, 0, sizeof(padding));
-    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
-        return ret;
-
-    /* 32 bit size of cipher to 64 bit endian */
-    padding[0] =  msglen        & 0xff;
-    padding[1] = (msglen >>  8) & 0xff;
-    padding[2] = (msglen >> 16) & 0xff;
-    padding[3] = (msglen >> 24) & 0xff;
-    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
-        != 0)
-        return ret;
-
-    /* generate tag */
-    if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
-        return ret;
-
-    return ret;
-}
-
-
-/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
- * the implmentation follows an older draft for creating the nonce and MAC.
- * The flag oldPoly gets set automaticlly depending on what cipher suite was
- * negotiated in the handshake. This is able to be done because the IDs for the
- * cipher suites was updated in RFC7905 giving unique values for the older
- * draft in comparision to the more recent RFC.
- *
- * ssl   WOLFSSL structure to get cipher and TLS state from
- * out   output buffer to hold encrypted data
- * input data to encrypt
- * sz    size of input
- *
- * Return 0 on success negative values in error case
- */
-static int  ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
-                              word16 sz)
-{
-    const byte* additionalSrc = input - RECORD_HEADER_SZ;
-    int ret       = 0;
-    word32 msgLen = (sz - ssl->specs.aead_mac_size);
-    byte tag[POLY1305_AUTH_SZ];
-    byte add[AEAD_AUTH_DATA_SZ];
-    byte nonce[CHACHA20_NONCE_SZ];
-    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
-    #ifdef CHACHA_AEAD_TEST
-        int i;
-    #endif
-
-    XMEMSET(tag,   0, sizeof(tag));
-    XMEMSET(nonce, 0, sizeof(nonce));
-    XMEMSET(poly,  0, sizeof(poly));
-    XMEMSET(add,   0, sizeof(add));
-
-    /* opaque SEQ number stored for AD */
-    WriteSEQ(ssl, CUR_ORDER, add);
-
-    if (ssl->options.oldPoly != 0) {
-        /* get nonce. SEQ should not be incremented again here */
-        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
-    }
-
-    /* Store the type, version. Unfortunately, they are in
-     * the input buffer ahead of the plaintext. */
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            additionalSrc -= DTLS_HANDSHAKE_EXTRA;
-            DtlsSEQIncrement(ssl, CUR_ORDER);
-        }
-    #endif
-
-    /* add TLS message size to additional data */
-    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
-    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
-
-    XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
-
-    #ifdef CHACHA_AEAD_TEST
-        printf("Encrypt Additional : ");
-        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
-            printf("%02x", add[i]);
-        }
-        printf("\n\n");
-        printf("input before encryption :\n");
-        for (i = 0; i < sz; i++) {
-            printf("%02x", input[i]);
-            if ((i + 1) % 16 == 0)
-                printf("\n");
-        }
-        printf("\n");
-    #endif
-
-    if (ssl->options.oldPoly == 0) {
-        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
-         * record sequence number XORed with client_write_IV/server_write_IV */
-        XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
-        nonce[4]  ^= add[0];
-        nonce[5]  ^= add[1];
-        nonce[6]  ^= add[2];
-        nonce[7]  ^= add[3];
-        nonce[8]  ^= add[4];
-        nonce[9]  ^= add[5];
-        nonce[10] ^= add[6];
-        nonce[11] ^= add[7];
-    }
-
-    /* set the nonce for chacha and get poly1305 key */
-    if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) {
-        ForceZero(nonce, CHACHA20_NONCE_SZ);
-        return ret;
-    }
-
-    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
-    /* create Poly1305 key using chacha20 keystream */
-    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly,
-                                                      poly, sizeof(poly))) != 0)
-        return ret;
-
-    /* encrypt the plain text */
-    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out,
-                                                         input, msgLen)) != 0) {
-        ForceZero(poly, sizeof(poly));
-        return ret;
-    }
-
-    /* get the poly1305 tag using either old padding scheme or more recent */
-    if (ssl->options.oldPoly != 0) {
-        if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
-                                                         poly, sz, tag)) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-    }
-    else {
-        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
-                                                          sizeof(poly))) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
-                            sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-    }
-    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
-
-    /* append tag to ciphertext */
-    XMEMCPY(out + msgLen, tag, sizeof(tag));
-
-    AeadIncrementExpIV(ssl);
-
-    #ifdef CHACHA_AEAD_TEST
-       printf("mac tag :\n");
-        for (i = 0; i < 16; i++) {
-           printf("%02x", tag[i]);
-           if ((i + 1) % 16 == 0)
-               printf("\n");
-        }
-       printf("\n\noutput after encrypt :\n");
-        for (i = 0; i < sz; i++) {
-           printf("%02x", out[i]);
-           if ((i + 1) % 16 == 0)
-               printf("\n");
-        }
-        printf("\n");
-    #endif
-
-    return ret;
-}
-
-
-/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
- * the implmentation follows an older draft for creating the nonce and MAC.
- * The flag oldPoly gets set automaticlly depending on what cipher suite was
- * negotiated in the handshake. This is able to be done because the IDs for the
- * cipher suites was updated in RFC7905 giving unique values for the older
- * draft in comparision to the more recent RFC.
- *
- * ssl   WOLFSSL structure to get cipher and TLS state from
- * plain output buffer to hold decrypted data
- * input data to decrypt
- * sz    size of input
- *
- * Return 0 on success negative values in error case
- */
-static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
-                           word16 sz)
-{
-    byte add[AEAD_AUTH_DATA_SZ];
-    byte nonce[CHACHA20_NONCE_SZ];
-    byte tag[POLY1305_AUTH_SZ];
-    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
-    int ret    = 0;
-    int msgLen = (sz - ssl->specs.aead_mac_size);
-
-    #ifdef CHACHA_AEAD_TEST
-       int i;
-       printf("input before decrypt :\n");
-        for (i = 0; i < sz; i++) {
-           printf("%02x", input[i]);
-           if ((i + 1) % 16 == 0)
-               printf("\n");
-        }
-        printf("\n");
-    #endif
-
-    XMEMSET(tag,   0, sizeof(tag));
-    XMEMSET(poly,  0, sizeof(poly));
-    XMEMSET(nonce, 0, sizeof(nonce));
-    XMEMSET(add,   0, sizeof(add));
-
-    /* sequence number field is 64-bits */
-    WriteSEQ(ssl, PEER_ORDER, add);
-
-    if (ssl->options.oldPoly != 0) {
-        /* get nonce, SEQ should not be incremented again here */
-        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
-    }
-
-    /* get AD info */
-    /* Store the type, version. */
-    add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
-    add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
-    add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
-    /* add TLS message size to additional data */
-    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
-    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
-
-    #ifdef CHACHA_AEAD_TEST
-        printf("Decrypt Additional : ");
-        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
-            printf("%02x", add[i]);
-        }
-        printf("\n\n");
-    #endif
-
-    if (ssl->options.oldPoly == 0) {
-        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
-         * record sequence number XORed with client_write_IV/server_write_IV */
-        XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
-        nonce[4]  ^= add[0];
-        nonce[5]  ^= add[1];
-        nonce[6]  ^= add[2];
-        nonce[7]  ^= add[3];
-        nonce[8]  ^= add[4];
-        nonce[9]  ^= add[5];
-        nonce[10] ^= add[6];
-        nonce[11] ^= add[7];
-    }
-
-    /* set nonce and get poly1305 key */
-    if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) {
-        ForceZero(nonce, CHACHA20_NONCE_SZ);
-        return ret;
-    }
-
-    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
-    /* use chacha20 keystream to get poly1305 key for tag */
-    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly,
-                                                      poly, sizeof(poly))) != 0)
-        return ret;
-
-    /* get the tag using Poly1305 */
-    if (ssl->options.oldPoly != 0) {
-        if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-    }
-    else {
-        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
-                                                          sizeof(poly))) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
-                   sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) {
-            ForceZero(poly, sizeof(poly));
-            return ret;
-        }
-    }
-    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
-
-    /* check tag sent along with packet */
-    if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) {
-        WOLFSSL_MSG("MAC did not match");
-        if (!ssl->options.dtls)
-            SendAlert(ssl, alert_fatal, bad_record_mac);
-        return VERIFY_MAC_ERROR;
-    }
-
-    /* if the tag was good decrypt message */
-    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
-                                                           input, msgLen)) != 0)
-        return ret;
-
-    #ifdef CHACHA_AEAD_TEST
-       printf("plain after decrypt :\n");
-        for (i = 0; i < sz; i++) {
-           printf("%02x", plain[i]);
-           if ((i + 1) % 16 == 0)
-               printf("\n");
-        }
-        printf("\n");
-    #endif
-
-    return ret;
-}
-#endif /* HAVE_CHACHA && HAVE_POLY1305 */
-#endif /* HAVE_AEAD */
-
-
-static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
-    word16 sz, int asyncOkay)
-{
-    int ret = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV* asyncDev = NULL;
-    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
-#else
-    (void)asyncOkay;
-#endif
-
-    (void)out;
-    (void)input;
-    (void)sz;
-
-    switch (ssl->specs.bulk_cipher_algorithm) {
-    #ifdef BUILD_ARC4
-        case wolfssl_rc4:
-            wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
-            break;
-    #endif
-
-    #ifdef BUILD_DES3
-        case wolfssl_triple_des:
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            asyncDev = &ssl->encrypt.des3->asyncDev;
-            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
-            if (ret != 0)
-                break;
-        #endif
-
-            ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E && asyncOkay) {
-                ret = wolfSSL_AsyncPush(ssl, asyncDev);
-            }
-        #endif
-            break;
-    #endif
-
-    #ifdef BUILD_AES
-        case wolfssl_aes:
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            asyncDev = &ssl->encrypt.aes->asyncDev;
-            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
-            if (ret != 0)
-                break;
-        #endif
-
-            ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E && asyncOkay) {
-                ret = wolfSSL_AsyncPush(ssl, asyncDev);
-            }
-        #endif
-            break;
-    #endif
-
-    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-        case wolfssl_aes_gcm:
-        case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */
-        {
-            wc_AesAuthEncryptFunc aes_auth_fn;
-            const byte* additionalSrc;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            asyncDev = &ssl->encrypt.aes->asyncDev;
-            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
-            if (ret != 0)
-                break;
-        #endif
-
-        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
-            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
-                            ? wc_AesGcmEncrypt : wc_AesCcmEncrypt;
-        #elif defined(BUILD_AESGCM)
-            aes_auth_fn = wc_AesGcmEncrypt;
-        #else
-            aes_auth_fn = wc_AesCcmEncrypt;
-        #endif
-            additionalSrc = input - 5;
-
-            XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
-            /* sequence number field is 64-bits */
-            WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
-
-            /* Store the type, version. Unfortunately, they are in
-             * the input buffer ahead of the plaintext. */
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls) {
-                additionalSrc -= DTLS_HANDSHAKE_EXTRA;
-            }
-        #endif
-            XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
-                                                        additionalSrc, 3);
-
-            /* Store the length of the plain text minus the explicit
-             * IV length minus the authentication tag size. */
-            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
-                                ssl->encrypt.additional + AEAD_LEN_OFFSET);
-            XMEMCPY(ssl->encrypt.nonce,
-                                ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ);
-            XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ,
-                                ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
-            ret = aes_auth_fn(ssl->encrypt.aes,
-                    out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
-                    sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
-                    ssl->encrypt.nonce, AESGCM_NONCE_SZ,
-                    out + sz - ssl->specs.aead_mac_size,
-                    ssl->specs.aead_mac_size,
-                    ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E && asyncOkay) {
-                ret = wolfSSL_AsyncPush(ssl, asyncDev);
-            }
-        #endif
-        }
-        break;
-    #endif /* BUILD_AESGCM || HAVE_AESCCM */
-
-    #ifdef HAVE_CAMELLIA
-        case wolfssl_camellia:
-            ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
-            break;
-    #endif
-
-    #ifdef HAVE_HC128
-        case wolfssl_hc128:
-            ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
-            break;
-    #endif
-
-    #ifdef BUILD_RABBIT
-        case wolfssl_rabbit:
-            ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
-            break;
-    #endif
-
-    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-        case wolfssl_chacha:
-            ret = ChachaAEADEncrypt(ssl, out, input, sz);
-            break;
-    #endif
-
-    #ifdef HAVE_NULL_CIPHER
-        case wolfssl_cipher_null:
-            if (input != out) {
-                XMEMMOVE(out, input, sz);
-            }
-            break;
-    #endif
-
-    #ifdef HAVE_IDEA
-        case wolfssl_idea:
-            ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz);
-            break;
-    #endif
-
-        default:
-            WOLFSSL_MSG("wolfSSL Encrypt programming error");
-            ret = ENCRYPT_ERROR;
-    }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* if async is not okay, then block */
-    if (ret == WC_PENDING_E && !asyncOkay) {
-        ret = wc_AsyncWait(ret, asyncDev, event_flags);
-    }
-#endif
-
-    return ret;
-}
-
-static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
-    int asyncOkay)
-{
-    int ret = 0;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ssl->error == WC_PENDING_E) {
-        ssl->error = 0; /* clear async */
-    }
-#endif
-
-    switch (ssl->encrypt.state) {
-        case CIPHER_STATE_BEGIN:
-        {
-            if (ssl->encrypt.setup == 0) {
-                WOLFSSL_MSG("Encrypt ciphers not setup");
-                return ENCRYPT_ERROR;
-            }
-
-        #ifdef HAVE_FUZZER
-            if (ssl->fuzzerCb)
-                ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
-        #endif
-
-        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-            /* make sure AES GCM/CCM memory is allocated */
-            /* free for these happens in FreeCiphers */
-            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
-                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
-                /* make sure auth iv and auth are allocated */
-                if (ssl->encrypt.additional == NULL)
-                    ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
-                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-                if (ssl->encrypt.nonce == NULL)
-                    ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
-                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-                if (ssl->encrypt.additional == NULL ||
-                         ssl->encrypt.nonce == NULL) {
-                    return MEMORY_E;
-                }
-            }
-        #endif /* BUILD_AESGCM || HAVE_AESCCM */
-
-            /* Advance state and proceed */
-            ssl->encrypt.state = CIPHER_STATE_DO;
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_DO:
-        {
-            ret = EncryptDo(ssl, out, input, sz, asyncOkay);
-
-            /* Advance state */
-            ssl->encrypt.state = CIPHER_STATE_END;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* If pending, then leave and return will resume below */
-            if (ret == WC_PENDING_E) {
-                return ret;
-            }
-        #endif
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_END:
-        {
-        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
-                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
-            {
-                /* finalize authentication cipher */
-                AeadIncrementExpIV(ssl);
-
-                if (ssl->encrypt.nonce)
-                    ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ);
-
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-            }
-        #endif /* BUILD_AESGCM || HAVE_AESCCM */
-            break;
-        }
-    }
-
-    /* Reset state */
-    ssl->encrypt.state = CIPHER_STATE_BEGIN;
-
-    return ret;
-}
-
-static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
-                           word16 sz)
-{
-    int ret = 0;
-
-    (void)plain;
-    (void)input;
-    (void)sz;
-
-    switch (ssl->specs.bulk_cipher_algorithm)
-    {
-    #ifdef BUILD_ARC4
-        case wolfssl_rc4:
-            wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
-            break;
-    #endif
-
-    #ifdef BUILD_DES3
-        case wolfssl_triple_des:
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
-                WC_ASYNC_FLAG_CALL_AGAIN);
-            if (ret != 0)
-                break;
-        #endif
-
-            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E) {
-                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
-            }
-        #endif
-            break;
-    #endif
-
-    #ifdef BUILD_AES
-        case wolfssl_aes:
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
-                WC_ASYNC_FLAG_CALL_AGAIN);
-            if (ret != 0)
-                break;
-        #endif
-
-            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E) {
-                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
-            }
-        #endif
-            break;
-    #endif
-
-    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-        case wolfssl_aes_gcm:
-        case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
-        {
-            wc_AesAuthDecryptFunc aes_auth_fn;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* initialize event */
-            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
-                WC_ASYNC_FLAG_CALL_AGAIN);
-            if (ret != 0)
-                break;
-        #endif
-
-        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
-            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
-                            ? wc_AesGcmDecrypt : wc_AesCcmDecrypt;
-        #elif defined(BUILD_AESGCM)
-            aes_auth_fn = wc_AesGcmDecrypt;
-        #else
-            aes_auth_fn = wc_AesCcmDecrypt;
-        #endif
-
-            XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
-            /* sequence number field is 64-bits */
-            WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
-
-            ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
-            ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
-            ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
-            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
-                                    ssl->decrypt.additional + AEAD_LEN_OFFSET);
-            XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
-                                                            AESGCM_IMP_IV_SZ);
-            XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input,
-                                                            AESGCM_EXP_IV_SZ);
-            if ((ret = aes_auth_fn(ssl->decrypt.aes,
-                        plain + AESGCM_EXP_IV_SZ,
-                        input + AESGCM_EXP_IV_SZ,
-                           sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
-                        ssl->decrypt.nonce, AESGCM_NONCE_SZ,
-                        input + sz - ssl->specs.aead_mac_size,
-                        ssl->specs.aead_mac_size,
-                        ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                if (ret == WC_PENDING_E) {
-                    ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
-                }
-            #endif
-            }
-        }
-        break;
-    #endif /* BUILD_AESGCM || HAVE_AESCCM */
-
-    #ifdef HAVE_CAMELLIA
-        case wolfssl_camellia:
-            ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
-            break;
-    #endif
-
-    #ifdef HAVE_HC128
-        case wolfssl_hc128:
-            ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
-            break;
-    #endif
-
-    #ifdef BUILD_RABBIT
-        case wolfssl_rabbit:
-            ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
-            break;
-    #endif
-
-    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-        case wolfssl_chacha:
-            ret = ChachaAEADDecrypt(ssl, plain, input, sz);
-            break;
-    #endif
-
-    #ifdef HAVE_NULL_CIPHER
-        case wolfssl_cipher_null:
-            if (input != plain) {
-                XMEMMOVE(plain, input, sz);
-            }
-            break;
-    #endif
-
-    #ifdef HAVE_IDEA
-        case wolfssl_idea:
-            ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz);
-            break;
-    #endif
-
-        default:
-            WOLFSSL_MSG("wolfSSL Decrypt programming error");
-            ret = DECRYPT_ERROR;
-    }
-
-    return ret;
-}
-
-static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
-                           word16 sz)
-{
-    int ret = 0;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
-    if (ret != WC_NOT_PENDING_E) {
-        /* check for still pending */
-        if (ret == WC_PENDING_E)
-            return ret;
-
-        ssl->error = 0; /* clear async */
-
-        /* let failures through so CIPHER_STATE_END logic is run */
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->decrypt.state = CIPHER_STATE_BEGIN;
-    }
-
-    switch (ssl->decrypt.state) {
-        case CIPHER_STATE_BEGIN:
-        {
-            if (ssl->decrypt.setup == 0) {
-                WOLFSSL_MSG("Decrypt ciphers not setup");
-                return DECRYPT_ERROR;
-            }
-
-        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-            /* make sure AES GCM/CCM memory is allocated */
-            /* free for these happens in FreeCiphers */
-            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
-                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
-                /* make sure auth iv and auth are allocated */
-                if (ssl->decrypt.additional == NULL)
-                    ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
-                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-                if (ssl->decrypt.nonce == NULL)
-                    ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
-                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-                if (ssl->decrypt.additional == NULL ||
-                         ssl->decrypt.nonce == NULL) {
-                    return MEMORY_E;
-                }
-            }
-        #endif /* BUILD_AESGCM || HAVE_AESCCM */
-
-            /* Advance state and proceed */
-            ssl->decrypt.state = CIPHER_STATE_DO;
-        }
-        FALL_THROUGH;
-        case CIPHER_STATE_DO:
-        {
-            ret = DecryptDo(ssl, plain, input, sz);
-
-            /* Advance state */
-            ssl->decrypt.state = CIPHER_STATE_END;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* If pending, leave and return below */
-            if (ret == WC_PENDING_E) {
-                return ret;
-            }
-        #endif
-        }
-        FALL_THROUGH;
-        case CIPHER_STATE_END:
-        {
-        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
-            /* make sure AES GCM/CCM nonce is cleared */
-            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
-                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
-                if (ssl->decrypt.nonce)
-                    ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ);
-
-                if (ret < 0)
-                    ret = VERIFY_MAC_ERROR;
-            }
-        #endif /* BUILD_AESGCM || HAVE_AESCCM */
-            break;
-        }
-    }
-
-    /* Reset state */
-    ssl->decrypt.state = CIPHER_STATE_BEGIN;
-
-    /* handle mac error case */
-    if (ret == VERIFY_MAC_ERROR) {
-        if (!ssl->options.dtls)
-            SendAlert(ssl, alert_fatal, bad_record_mac);
-
-        #ifdef WOLFSSL_DTLS_DROP_STATS
-            ssl->macDropCount++;
-        #endif /* WOLFSSL_DTLS_DROP_STATS */
-    }
-
-    return ret;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-/* Check conditions for a cipher to have an explicit IV.
- *
- * ssl  The SSL/TLS object.
- * returns 1 if the cipher in use has an explicit IV and 0 otherwise.
- */
-static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl)
-{
-#ifdef WOLFSSL_TLS13
-    if (ssl->options.tls1_3)
-        return 0;
-#endif
-    return (ssl->specs.cipher_type == aead) &&
-            (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha);
-}
-
-/* check cipher text size for sanity */
-static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
-{
-#ifdef HAVE_TRUNCATED_HMAC
-    word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
-                                           : ssl->specs.hash_size;
-#else
-    word32 minLength = ssl->specs.hash_size; /* covers stream */
-#endif
-
-    if (ssl->specs.cipher_type == block) {
-        if (encryptSz % ssl->specs.block_size) {
-            WOLFSSL_MSG("Block ciphertext not block size");
-            return SANITY_CIPHER_E;
-        }
-
-        minLength++;  /* pad byte */
-
-        if (ssl->specs.block_size > minLength)
-            minLength = ssl->specs.block_size;
-
-        if (ssl->options.tls1_1)
-            minLength += ssl->specs.block_size;  /* explicit IV */
-    }
-    else if (ssl->specs.cipher_type == aead) {
-        minLength = ssl->specs.aead_mac_size;    /* authTag size */
-        if (CipherHasExpIV(ssl))
-            minLength += AESGCM_EXP_IV_SZ;       /* explicit IV  */
-    }
-
-    if (encryptSz < minLength) {
-        WOLFSSL_MSG("Ciphertext not minimum size");
-        return SANITY_CIPHER_E;
-    }
-
-    return 0;
-}
-
-
-/* check all length bytes for the pad value, return 0 on success */
-static int PadCheck(const byte* a, byte pad, int length)
-{
-    int i;
-    int compareSum = 0;
-
-    for (i = 0; i < length; i++) {
-        compareSum |= a[i] ^ pad;
-    }
-
-    return compareSum;
-}
-
-
-/* Mask the padding bytes with the expected values.
- * Constant time implementation - does maximum pad size possible.
- *
- * data   Message data.
- * sz     Size of the message including MAC and padding and padding length.
- * macSz  Size of the MAC.
- * returns 0 on success, otherwise failure.
- */
-static byte MaskPadding(const byte* data, int sz, int macSz)
-{
-    int i;
-    int checkSz = sz - 1;
-    byte paddingSz = data[sz - 1];
-    byte mask;
-    byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
-
-    if (checkSz > TLS_MAX_PAD_SZ)
-        checkSz = TLS_MAX_PAD_SZ;
-
-    for (i = 0; i < checkSz; i++) {
-        mask = ctMaskLTE(i, paddingSz);
-        good |= mask & (data[sz - 1 - i] ^ paddingSz);
-    }
-
-    return good;
-}
-
-/* Mask the MAC in the message with the MAC calculated.
- * Constant time implementation - starts looking for MAC where maximum padding
- * size has it.
- *
- * data    Message data.
- * sz      Size of the message including MAC and padding and padding length.
- * macSz   Size of the MAC data.
- * expMac  Expected MAC value.
- * returns 0 on success, otherwise failure.
- */
-static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
-{
-    int i, j;
-    unsigned char mac[WC_MAX_DIGEST_SIZE];
-    int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
-    int macEnd = sz - 1 - data[sz - 1];
-    int macStart = macEnd - macSz;
-    int r = 0;
-    unsigned char started, notEnded;
-    unsigned char good = 0;
-
-    if (scanStart < 0)
-        scanStart = 0;
-
-    /* Div on Intel has different speeds depending on value.
-     * Use a bitwise AND or mod a specific value (converted to mul). */
-    if ((macSz & (macSz - 1)) == 0)
-        r = (macSz - (scanStart - macStart)) & (macSz - 1);
-#ifndef NO_SHA
-    else if (macSz == WC_SHA_DIGEST_SIZE)
-        r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
-#endif
-#ifdef WOLFSSL_SHA384
-    else if (macSz == WC_SHA384_DIGEST_SIZE)
-        r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
-#endif
-
-    XMEMSET(mac, 0, macSz);
-    for (i = scanStart; i < sz; i += macSz) {
-        for (j = 0; j < macSz && j + i < sz; j++) {
-            started = ctMaskGTE(i + j, macStart);
-            notEnded = ctMaskLT(i + j, macEnd);
-            mac[j] |= started & notEnded & data[i + j];
-        }
-    }
-
-    if ((macSz & (macSz - 1)) == 0) {
-        for (i = 0; i < macSz; i++)
-            good |= expMac[i] ^ mac[(i + r) & (macSz - 1)];
-    }
-#ifndef NO_SHA
-    else if (macSz == WC_SHA_DIGEST_SIZE) {
-        for (i = 0; i < macSz; i++)
-            good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE];
-    }
-#endif
-#ifdef WOLFSSL_SHA384
-    else if (macSz == WC_SHA384_DIGEST_SIZE) {
-        for (i = 0; i < macSz; i++)
-            good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE];
-    }
-#endif
-
-    return good;
-}
-
-/* timing resistant pad/verify check, return 0 on success */
-int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
-                    int pLen, int content)
-{
-    byte verify[WC_MAX_DIGEST_SIZE];
-    byte good;
-    int  ret = 0;
-
-    good = MaskPadding(input, pLen, macSz);
-    /* 4th argument has potential to underflow, ssl->hmac function should
-     * either increment the size by (macSz + padLen + 1) before use or check on
-     * the size to make sure is valid. */
-    ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
-                                                                    content, 1);
-    good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
-
-    /* Non-zero on failure. */
-    good = (byte)~(word32)good;
-    good &= good >> 4;
-    good &= good >> 2;
-    good &= good >> 1;
-    /* Make ret negative on masking failure. */
-    ret -= 1 - good;
-
-    /* Treat any faulure as verify MAC error. */
-    if (ret != 0)
-        ret = VERIFY_MAC_ERROR;
-
-    return ret;
-}
-
-
-int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
-{
-    word32 msgSz   = ssl->keys.encryptSz;
-    word32 idx     = *inOutIdx;
-    int    dataSz;
-    int    ivExtra = 0;
-    byte*  rawData = input + idx;  /* keep current  for hmac */
-#ifdef HAVE_LIBZ
-    byte   decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
-#endif
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-    }
-    else
-#endif
-    if (ssl->options.handShakeDone == 0) {
-        WOLFSSL_MSG("Received App data before a handshake completed");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->specs.cipher_type == block) {
-        if (ssl->options.tls1_1)
-            ivExtra = ssl->specs.block_size;
-    }
-    else if (ssl->specs.cipher_type == aead) {
-        if (CipherHasExpIV(ssl))
-            ivExtra = AESGCM_EXP_IV_SZ;
-    }
-
-    dataSz = msgSz - ivExtra - ssl->keys.padSz;
-    if (dataSz < 0) {
-        WOLFSSL_MSG("App data buffer error, malicious input?");
-        return BUFFER_ERROR;
-    }
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-        if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
-            SendAlert(ssl, alert_fatal, unexpected_message);
-            return WOLFSSL_FATAL_ERROR;
-        }
-        ssl->earlyDataSz += dataSz;
-    }
-#endif
-
-    /* read data */
-    if (dataSz) {
-        int rawSz = dataSz;       /* keep raw size for idx adjustment */
-
-#ifdef HAVE_LIBZ
-        if (ssl->options.usingCompression) {
-            dataSz = myDeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
-            if (dataSz < 0) return dataSz;
-        }
-#endif
-        idx += rawSz;
-
-        ssl->buffers.clearOutputBuffer.buffer = rawData;
-        ssl->buffers.clearOutputBuffer.length = dataSz;
-    }
-
-    idx += ssl->keys.padSz;
-
-#ifdef HAVE_LIBZ
-    /* decompress could be bigger, overwrite after verify */
-    if (ssl->options.usingCompression)
-        XMEMMOVE(rawData, decomp, dataSz);
-#endif
-
-    *inOutIdx = idx;
-    return 0;
-}
-
-
-/* process alert, return level */
-static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
-                   word32 totalSz)
-{
-    byte level;
-    byte code;
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "Alert");
-        if (ssl->toInfoOn)
-            /* add record header back on to info + alert bytes level/code */
-            AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx -
-                          RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE,
-                          READ_PROTO, ssl->heap);
-    #endif
-
-    if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) {
-        WOLFSSL_MSG("Alert count exceeded");
-        return ALERT_COUNT_E;
-    }
-
-    /* make sure can read the message */
-    if (*inOutIdx + ALERT_SIZE > totalSz)
-        return BUFFER_E;
-
-    level = input[(*inOutIdx)++];
-    code  = input[(*inOutIdx)++];
-    ssl->alert_history.last_rx.code = code;
-    ssl->alert_history.last_rx.level = level;
-    *type = code;
-    if (level == alert_fatal) {
-        ssl->options.isClosed = 1;  /* Don't send close_notify */
-    }
-
-    WOLFSSL_MSG("Got alert");
-    if (*type == close_notify) {
-        WOLFSSL_MSG("\tclose notify");
-        ssl->options.closeNotify = 1;
-    }
-#ifdef WOLFSSL_TLS13
-    if (*type == decode_error) {
-        WOLFSSL_MSG("    decode error");
-    }
-    if (*type == illegal_parameter) {
-        WOLFSSL_MSG("    illegal parameter");
-    }
-#endif
-    WOLFSSL_ERROR(*type);
-    if (IsEncryptionOn(ssl, 0)) {
-        if (*inOutIdx + ssl->keys.padSz > totalSz)
-            return BUFFER_E;
-        *inOutIdx += ssl->keys.padSz;
-    }
-
-    return level;
-}
-
-static int GetInputData(WOLFSSL *ssl, word32 size)
-{
-    int in;
-    int inSz;
-    int maxLength;
-    int usedLength;
-    int dtlsExtra = 0;
-
-
-    /* check max input length */
-    usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
-    maxLength  = ssl->buffers.inputBuffer.bufferSize - usedLength;
-    inSz       = (int)(size - usedLength);      /* from last partial read */
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        if (size < ssl->dtls_expected_rx)
-            dtlsExtra = (int)(ssl->dtls_expected_rx - size);
-        inSz = ssl->dtls_expected_rx;
-    }
-#endif
-
-    /* check that no lengths or size values are negative */
-    if (usedLength < 0 || maxLength < 0 || inSz <= 0) {
-        return BUFFER_ERROR;
-    }
-
-    if (inSz > maxLength) {
-        if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0)
-            return MEMORY_E;
-    }
-
-    /* Put buffer data at start if not there */
-    if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
-        XMEMMOVE(ssl->buffers.inputBuffer.buffer,
-                ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
-                usedLength);
-
-    /* remove processed data */
-    ssl->buffers.inputBuffer.idx    = 0;
-    ssl->buffers.inputBuffer.length = usedLength;
-
-    /* read data from network */
-    do {
-        in = wolfSSLReceive(ssl,
-                     ssl->buffers.inputBuffer.buffer +
-                     ssl->buffers.inputBuffer.length,
-                     inSz);
-        if (in == -1)
-            return SOCKET_ERROR_E;
-
-        if (in == WANT_READ)
-            return WANT_READ;
-
-        if (in > inSz)
-            return RECV_OVERFLOW_E;
-
-        ssl->buffers.inputBuffer.length += in;
-        inSz -= in;
-
-    } while (ssl->buffers.inputBuffer.length < size);
-
-#ifdef WOLFSSL_DEBUG_TLS
-    if (ssl->buffers.inputBuffer.idx == 0) {
-        WOLFSSL_MSG("Data received");
-        WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer,
-                       ssl->buffers.inputBuffer.length);
-    }
-#endif
-
-    return 0;
-}
-
-
-static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
-                            int content, word32* padSz)
-{
-#ifndef WOLFSSL_NO_TLS12
-    int    ivExtra = 0;
-    int    ret;
-    word32 pad     = 0;
-    word32 padByte = 0;
-#ifdef HAVE_TRUNCATED_HMAC
-    word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
-                                          : ssl->specs.hash_size;
-#else
-    word32 digestSz = ssl->specs.hash_size;
-#endif
-    byte   verify[WC_MAX_DIGEST_SIZE];
-
-
-    if (ssl->specs.cipher_type == block) {
-        if (ssl->options.tls1_1)
-            ivExtra = ssl->specs.block_size;
-        pad = *(input + msgSz - ivExtra - 1);
-        padByte = 1;
-
-        if (ssl->options.tls) {
-            ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
-                                  content);
-            if (ret != 0)
-                return ret;
-        }
-        else {  /* sslv3, some implementations have bad padding, but don't
-                 * allow bad read */
-            int  badPadLen = 0;
-            byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
-            byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
-
-            (void)dmy;
-
-            if (pad > (msgSz - digestSz - 1)) {
-                WOLFSSL_MSG("Plain Len not long enough for pad/mac");
-                pad       = 0;  /* no bad read */
-                badPadLen = 1;
-            }
-            PadCheck(dummy, (byte)pad, MAX_PAD_SIZE);  /* timing only */
-            ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
-                                                                    content, 1);
-            if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
-                                digestSz) != 0)
-                return VERIFY_MAC_ERROR;
-            if (ret != 0 || badPadLen)
-                return VERIFY_MAC_ERROR;
-        }
-    }
-    else if (ssl->specs.cipher_type == stream) {
-        ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
-        if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
-            return VERIFY_MAC_ERROR;
-        }
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-    }
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-    if (ssl->specs.cipher_type == aead) {
-        *padSz = ssl->specs.aead_mac_size;
-    }
-#ifndef WOLFSSL_NO_TLS12
-    else {
-        *padSz = digestSz + pad + padByte;
-    }
-#endif /* WOLFSSL_NO_TLS12 */
-
-    (void)input;
-    (void)msgSz;
-    (void)content;
-
-    return 0;
-}
-
-
-/* process input requests, return 0 is done, 1 is call again to complete, and
-   negative number is error */
-int ProcessReply(WOLFSSL* ssl)
-{
-    int    ret = 0, type, readSz;
-    int    atomicUser = 0;
-    word32 startIdx = 0;
-#if defined(WOLFSSL_DTLS)
-    int    used;
-#endif
-
-#ifdef ATOMIC_USER
-    if (ssl->ctx->DecryptVerifyCb)
-        atomicUser = 1;
-#endif
-
-    if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        && ssl->error != WC_PENDING_E
-    #endif
-    #ifdef WOLFSSL_NONBLOCK_OCSP
-        && ssl->error != OCSP_WANT_READ
-    #endif
-    ) {
-        WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
-        return ssl->error;
-    }
-
-    for (;;) {
-        switch (ssl->options.processReply) {
-
-        /* in the WOLFSSL_SERVER case, get the first byte for detecting
-         * old client hello */
-        case doProcessInit:
-
-            readSz = RECORD_HEADER_SZ;
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls)
-                readSz = DTLS_RECORD_HEADER_SZ;
-        #endif
-
-            /* get header or return error */
-            if (!ssl->options.dtls) {
-                if ((ret = GetInputData(ssl, readSz)) < 0)
-                    return ret;
-            } else {
-            #ifdef WOLFSSL_DTLS
-                /* read ahead may already have header */
-                used = ssl->buffers.inputBuffer.length -
-                       ssl->buffers.inputBuffer.idx;
-                if (used < readSz) {
-                    if ((ret = GetInputData(ssl, readSz)) < 0)
-                        return ret;
-                }
-            #endif
-            }
-
-#ifdef OLD_HELLO_ALLOWED
-
-            /* see if sending SSLv2 client hello */
-            if ( ssl->options.side == WOLFSSL_SERVER_END &&
-                 ssl->options.clientState == NULL_STATE &&
-                 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
-                         != handshake) {
-                byte b0, b1;
-
-                ssl->options.processReply = runProcessOldClientHello;
-
-                /* sanity checks before getting size at front */
-                if (ssl->buffers.inputBuffer.buffer[
-                          ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) {
-                    WOLFSSL_MSG("Not a valid old client hello");
-                    return PARSE_ERROR;
-                }
-
-                if (ssl->buffers.inputBuffer.buffer[
-                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR &&
-                    ssl->buffers.inputBuffer.buffer[
-                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) {
-                    WOLFSSL_MSG("Not a valid version in old client hello");
-                    return PARSE_ERROR;
-                }
-
-                /* how many bytes need ProcessOldClientHello */
-                b0 =
-                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
-                b1 =
-                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
-                ssl->curSize = (word16)(((b0 & 0x7f) << 8) | b1);
-            }
-            else {
-                ssl->options.processReply = getRecordLayerHeader;
-                continue;
-            }
-            FALL_THROUGH;
-
-        /* in the WOLFSSL_SERVER case, run the old client hello */
-        case runProcessOldClientHello:
-
-            /* get sz bytes or return error */
-            if (!ssl->options.dtls) {
-                if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
-                    return ret;
-            } else {
-            #ifdef WOLFSSL_DTLS
-                /* read ahead may already have */
-                used = ssl->buffers.inputBuffer.length -
-                       ssl->buffers.inputBuffer.idx;
-                if (used < ssl->curSize)
-                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
-                        return ret;
-            #endif  /* WOLFSSL_DTLS */
-            }
-
-            ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
-                                        &ssl->buffers.inputBuffer.idx,
-                                        ssl->buffers.inputBuffer.length -
-                                        ssl->buffers.inputBuffer.idx,
-                                        ssl->curSize);
-            if (ret < 0)
-                return ret;
-
-            else if (ssl->buffers.inputBuffer.idx ==
-                     ssl->buffers.inputBuffer.length) {
-                ssl->options.processReply = doProcessInit;
-                return 0;
-            }
-
-#endif  /* OLD_HELLO_ALLOWED */
-            FALL_THROUGH;
-
-        /* get the record layer header */
-        case getRecordLayerHeader:
-
-            ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
-                                       &ssl->buffers.inputBuffer.idx,
-                                       &ssl->curRL, &ssl->curSize);
-#ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls && ret == SEQUENCE_ERROR) {
-                WOLFSSL_MSG("Silently dropping out of order DTLS message");
-                ssl->options.processReply = doProcessInit;
-                ssl->buffers.inputBuffer.length = 0;
-                ssl->buffers.inputBuffer.idx = 0;
-#ifdef WOLFSSL_DTLS_DROP_STATS
-                ssl->replayDropCount++;
-#endif /* WOLFSSL_DTLS_DROP_STATS */
-
-                if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) {
-                    ret = DtlsMsgPoolSend(ssl, 0);
-                    if (ret != 0)
-                        return ret;
-                }
-
-                continue;
-            }
-#endif
-            if (ret != 0)
-                return ret;
-
-            ssl->options.processReply = getData;
-            FALL_THROUGH;
-
-        /* retrieve record layer data */
-        case getData:
-
-            /* get sz bytes or return error */
-            if (!ssl->options.dtls) {
-                if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
-                    return ret;
-            } else {
-#ifdef WOLFSSL_DTLS
-                /* read ahead may already have */
-                used = ssl->buffers.inputBuffer.length -
-                       ssl->buffers.inputBuffer.idx;
-                if (used < ssl->curSize)
-                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
-                        return ret;
-#endif
-            }
-
-            ssl->options.processReply = decryptMessage;
-            startIdx = ssl->buffers.inputBuffer.idx;  /* in case > 1 msg per */
-            FALL_THROUGH;
-
-        /* decrypt message */
-        case decryptMessage:
-
-#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
-            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
-#else
-            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
-                                        (!IsAtLeastTLSv1_3(ssl->version) ||
-                                         ssl->curRL.type != change_cipher_spec))
-#endif
-            {
-                bufferStatic* in = &ssl->buffers.inputBuffer;
-
-                ret = SanityCheckCipherText(ssl, ssl->curSize);
-                if (ret < 0)
-                    return ret;
-
-                if (atomicUser) {
-                #ifdef ATOMIC_USER
-                    ret = ssl->ctx->DecryptVerifyCb(ssl,
-                                  in->buffer + in->idx,
-                                  in->buffer + in->idx,
-                                  ssl->curSize, ssl->curRL.type, 1,
-                                  &ssl->keys.padSz, ssl->DecryptVerifyCtx);
-                #endif /* ATOMIC_USER */
-                }
-                else {
-                    if (!ssl->options.tls1_3) {
-                #ifndef WOLFSSL_NO_TLS12
-                        ret = Decrypt(ssl,
-                                      in->buffer + in->idx,
-                                      in->buffer + in->idx,
-                                      ssl->curSize);
-                #else
-                        ret = DECRYPT_ERROR;
-                #endif
-                    }
-                    else
-                    {
-                #ifdef WOLFSSL_TLS13
-                    #if defined(WOLFSSL_TLS13_DRAFT_18) || \
-                        defined(WOLFSSL_TLS13_DRAFT_22) || \
-                        defined(WOLFSSL_TLS13_DRAFT_23)
-                        ret = DecryptTls13(ssl,
-                                           in->buffer + in->idx,
-                                           in->buffer + in->idx,
-                                           ssl->curSize, NULL, 0);
-                    #else
-                        ret = DecryptTls13(ssl,
-                                        in->buffer + in->idx,
-                                        in->buffer + in->idx,
-                                        ssl->curSize,
-                                        (byte*)&ssl->curRL, RECORD_HEADER_SZ);
-                    #endif
-                #else
-                        ret = DECRYPT_ERROR;
-                #endif /* WOLFSSL_TLS13 */
-                    }
-                }
-
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                if (ret == WC_PENDING_E)
-                    return ret;
-            #endif
-
-                if (ret >= 0) {
-                #ifndef WOLFSSL_NO_TLS12
-                    /* handle success */
-                    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
-                        ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
-                        /* go past TLSv1.1 IV */
-                    if (CipherHasExpIV(ssl))
-                        ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
-                #endif
-                }
-                else {
-                    WOLFSSL_MSG("Decrypt failed");
-                    WOLFSSL_ERROR(ret);
-                #ifdef WOLFSSL_EARLY_DATA
-                    if (ssl->options.tls1_3) {
-                        ssl->earlyDataSz += ssl->curSize;
-                        if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) {
-                            if (ssl->keys.peer_sequence_number_lo-- == 0)
-                                ssl->keys.peer_sequence_number_hi--;
-                            ssl->options.processReply = doProcessInit;
-                            ssl->buffers.inputBuffer.idx =
-                                            ssl->buffers.inputBuffer.length;
-                            return 0;
-                        }
-                    }
-                #endif
-                #ifdef WOLFSSL_DTLS
-                    /* If in DTLS mode, if the decrypt fails for any
-                     * reason, pretend the datagram never happened. */
-                    if (ssl->options.dtls) {
-                        ssl->options.processReply = doProcessInit;
-                        ssl->buffers.inputBuffer.idx =
-                                        ssl->buffers.inputBuffer.length;
-                        #ifdef WOLFSSL_DTLS_DROP_STATS
-                            ssl->macDropCount++;
-                        #endif /* WOLFSSL_DTLS_DROP_STATS */
-                    }
-                #endif /* WOLFSSL_DTLS */
-
-                    return DECRYPT_ERROR;
-                }
-            }
-
-            ssl->options.processReply = verifyMessage;
-            FALL_THROUGH;
-
-        /* verify digest of message */
-        case verifyMessage:
-
-#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
-            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
-#else
-            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
-                                        (!IsAtLeastTLSv1_3(ssl->version) ||
-                                         ssl->curRL.type != change_cipher_spec))
-#endif
-            {
-                if (!atomicUser) {
-                    ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
-                                    ssl->buffers.inputBuffer.idx,
-                                    ssl->curSize, ssl->curRL.type,
-                                    &ssl->keys.padSz);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E)
-                        return ret;
-                #endif
-                    if (ret < 0) {
-                        WOLFSSL_MSG("VerifyMac failed");
-                        WOLFSSL_ERROR(ret);
-                        #ifdef WOLFSSL_DTLS
-                        /* If in DTLS mode, if the decrypt fails for any
-                         * reason, pretend the datagram never happened. */
-                        if (ssl->options.dtls) {
-                            ssl->options.processReply = doProcessInit;
-                            ssl->buffers.inputBuffer.idx =
-                                            ssl->buffers.inputBuffer.length;
-                            #ifdef WOLFSSL_DTLS_DROP_STATS
-                                ssl->macDropCount++;
-                            #endif /* WOLFSSL_DTLS_DROP_STATS */
-                        }
-                        #endif /* WOLFSSL_DTLS */
-                        return DECRYPT_ERROR;
-                    }
-                }
-
-                ssl->keys.encryptSz    = ssl->curSize;
-                ssl->keys.decryptedCur = 1;
-#ifdef WOLFSSL_TLS13
-                if (ssl->options.tls1_3) {
-                    word16 i = (word16)(ssl->buffers.inputBuffer.length -
-                                        ssl->keys.padSz);
-                    /* Remove padding from end of plain text. */
-                    for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
-                        if (ssl->buffers.inputBuffer.buffer[i] != 0)
-                            break;
-                    }
-                    /* Get the real content type from the end of the data. */
-                    ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
-                    ssl->keys.padSz = ssl->buffers.inputBuffer.length - i;
-                }
-#endif
-            }
-
-            ssl->options.processReply = runProcessingOneMessage;
-            FALL_THROUGH;
-
-        /* the record layer is here */
-        case runProcessingOneMessage:
-
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                DtlsUpdateWindow(ssl);
-            }
-        #endif /* WOLFSSL_DTLS */
-
-            WOLFSSL_MSG("received record layer msg");
-
-            switch (ssl->curRL.type) {
-                case handshake :
-                    /* debugging in DoHandShakeMsg */
-                    if (ssl->options.dtls) {
-#ifdef WOLFSSL_DTLS
-                        ret = DoDtlsHandShakeMsg(ssl,
-                                            ssl->buffers.inputBuffer.buffer,
-                                            &ssl->buffers.inputBuffer.idx,
-                                            ssl->buffers.inputBuffer.length);
-#endif
-                    }
-                    else if (!IsAtLeastTLSv1_3(ssl->version)) {
-#ifndef WOLFSSL_NO_TLS12
-                        ret = DoHandShakeMsg(ssl,
-                                            ssl->buffers.inputBuffer.buffer,
-                                            &ssl->buffers.inputBuffer.idx,
-                                            ssl->buffers.inputBuffer.length);
-#else
-                        ret = BUFFER_ERROR;
-#endif
-                    }
-                    else {
-#ifdef WOLFSSL_TLS13
-                        ret = DoTls13HandShakeMsg(ssl,
-                                            ssl->buffers.inputBuffer.buffer,
-                                            &ssl->buffers.inputBuffer.idx,
-                                            ssl->buffers.inputBuffer.length);
-    #ifdef WOLFSSL_EARLY_DATA
-                        if (ret != 0)
-                            return ret;
-                        if (ssl->options.side == WOLFSSL_SERVER_END &&
-                                ssl->earlyData &&
-                                ssl->options.handShakeState == HANDSHAKE_DONE) {
-                            ssl->earlyData = no_early_data;
-                            ssl->options.processReply = doProcessInit;
-                            return ZERO_RETURN;
-                        }
-    #endif
-#else
-                        ret = BUFFER_ERROR;
-#endif
-                    }
-                    if (ret != 0)
-                        return ret;
-                    break;
-
-                case change_cipher_spec:
-                    WOLFSSL_MSG("got CHANGE CIPHER SPEC");
-                    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-                        if (ssl->hsInfoOn)
-                            AddPacketName(ssl, "ChangeCipher");
-                        /* add record header back on info */
-                        if (ssl->toInfoOn) {
-                            AddPacketInfo(ssl, "ChangeCipher",
-                                change_cipher_spec,
-                                ssl->buffers.inputBuffer.buffer +
-                                ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
-                                1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap);
-                            #ifdef WOLFSSL_CALLBACKS
-                            AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
-                            #endif
-                        }
-                    #endif
-
-#ifdef WOLFSSL_TLS13
-    #ifdef WOLFSSL_TLS13_DRAFT_18
-                    if (IsAtLeastTLSv1_3(ssl->version)) {
-                        SendAlert(ssl, alert_fatal, illegal_parameter);
-                        return UNKNOWN_RECORD_TYPE;
-                    }
-    #else
-                    if (IsAtLeastTLSv1_3(ssl->version)) {
-                        word32 i = ssl->buffers.inputBuffer.idx;
-                        if (ssl->curSize != 1 ||
-                                      ssl->buffers.inputBuffer.buffer[i] != 1) {
-                            SendAlert(ssl, alert_fatal, illegal_parameter);
-                            return UNKNOWN_RECORD_TYPE;
-                        }
-                        ssl->buffers.inputBuffer.idx++;
-                        break;
-                    }
-    #endif
-#endif
-
-#ifndef WOLFSSL_NO_TLS12
-                    ret = SanityCheckMsgReceived(ssl, change_cipher_hs);
-                    if (ret != 0) {
-                        if (!ssl->options.dtls) {
-                            return ret;
-                        }
-                        else {
-                        #ifdef WOLFSSL_DTLS
-                        /* Check for duplicate CCS message in DTLS mode.
-                         * DTLS allows for duplicate messages, and it should be
-                         * skipped. Also skip if out of order. */
-                            if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E)
-                                return ret;
-
-                            if (IsDtlsNotSctpMode(ssl)) {
-                                ret = DtlsMsgPoolSend(ssl, 1);
-                                if (ret != 0)
-                                    return ret;
-                            }
-
-                            if (ssl->curSize != 1) {
-                                WOLFSSL_MSG("Malicious or corrupted"
-                                            " duplicate ChangeCipher msg");
-                                return LENGTH_ERROR;
-                            }
-                            ssl->buffers.inputBuffer.idx++;
-                            break;
-                        #endif /* WOLFSSL_DTLS */
-                        }
-                    }
-
-                    if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
-                        ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
-                        ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
-                    }
-
-                    if (ssl->curSize != 1) {
-                        WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg");
-                        return LENGTH_ERROR;
-                    }
-
-                    ssl->buffers.inputBuffer.idx++;
-                    ssl->keys.encryptionOn = 1;
-
-                    /* setup decrypt keys for following messages */
-                    /* XXX This might not be what we want to do when
-                     * receiving a CCS with multicast. We update the
-                     * key when the application updates them. */
-                    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-                        return ret;
-
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
-#ifdef WOLFSSL_MULTICAST
-                            if (ssl->options.haveMcast) {
-                                peerSeq += ssl->keys.curPeerId;
-                                peerSeq->highwaterMark = UpdateHighwaterMark(0,
-                                        ssl->ctx->mcastFirstSeq,
-                                        ssl->ctx->mcastSecondSeq,
-                                        ssl->ctx->mcastMaxSeq);
-                            }
-#endif
-                            DtlsMsgPoolReset(ssl);
-                            peerSeq->nextEpoch++;
-                            peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
-                            peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
-                            peerSeq->nextSeq_lo = 0;
-                            peerSeq->nextSeq_hi = 0;
-                            XMEMCPY(peerSeq->prevWindow, peerSeq->window,
-                                    DTLS_SEQ_SZ);
-                            XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
-                        }
-                    #endif
-
-                    #ifdef HAVE_LIBZ
-                        if (ssl->options.usingCompression)
-                            if ( (ret = InitStreams(ssl)) != 0)
-                                return ret;
-                    #endif
-                    ret = BuildFinished(ssl, &ssl->hsHashes->verifyHashes,
-                                       ssl->options.side == WOLFSSL_CLIENT_END ?
-                                       server : client);
-                    if (ret != 0)
-                        return ret;
-#endif /* !WOLFSSL_NO_TLS12 */
-                    break;
-
-                case application_data:
-                    WOLFSSL_MSG("got app DATA");
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls && ssl->options.dtlsHsRetain) {
-                            FreeHandshakeResources(ssl);
-                            ssl->options.dtlsHsRetain = 0;
-                        }
-                    #endif
-                    #ifdef WOLFSSL_TLS13
-                        if (ssl->keys.keyUpdateRespond) {
-                            WOLFSSL_MSG("No KeyUpdate from peer seen");
-                            return SANITY_MSG_E;
-                        }
-                    #endif
-                    if ((ret = DoApplicationData(ssl,
-                                                ssl->buffers.inputBuffer.buffer,
-                                               &ssl->buffers.inputBuffer.idx))
-                                                                         != 0) {
-                        WOLFSSL_ERROR(ret);
-                        return ret;
-                    }
-                    break;
-
-                case alert:
-                    WOLFSSL_MSG("got ALERT!");
-                    ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
-                                  &ssl->buffers.inputBuffer.idx, &type,
-                                   ssl->buffers.inputBuffer.length);
-                    if (ret == alert_fatal)
-                        return FATAL_ERROR;
-                    else if (ret < 0)
-                        return ret;
-
-                    /* catch warnings that are handled as errors */
-                    if (type == close_notify)
-                        return ssl->error = ZERO_RETURN;
-
-                    if (type == decrypt_error)
-                        return FATAL_ERROR;
-                    break;
-
-                default:
-                    WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE);
-                    return UNKNOWN_RECORD_TYPE;
-            }
-
-            ssl->options.processReply = doProcessInit;
-
-            /* input exhausted? */
-            if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length)
-                return 0;
-
-            /* more messages per record */
-            else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
-                WOLFSSL_MSG("More messages in record");
-
-                ssl->options.processReply = runProcessingOneMessage;
-
-                if (IsEncryptionOn(ssl, 0)) {
-                    WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
-                    if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
-                        ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
-                    }
-                    else {
-                        WOLFSSL_MSG("\tmiddle padding error");
-                        return FATAL_ERROR;
-                    }
-                }
-
-                continue;
-            }
-            /* more records */
-            else {
-                WOLFSSL_MSG("More records in input");
-                ssl->options.processReply = doProcessInit;
-                continue;
-            }
-
-        default:
-            WOLFSSL_MSG("Bad process input state, programming error");
-            return INPUT_CASE_ERROR;
-        }
-    }
-}
-
-
-int SendChangeCipher(WOLFSSL* ssl)
-{
-    byte              *output;
-    int                sendSz = RECORD_HEADER_SZ + ENUM_LEN;
-    int                idx    = RECORD_HEADER_SZ;
-    int                ret;
-
-    #ifdef OPENSSL_EXTRA
-	ssl->cbmode = SSL_CB_MODE_WRITE;
-	if (ssl->options.side == WOLFSSL_SERVER_END){
-		ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE;
-		if (ssl->CBIS != NULL)
-			ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
-	}
-	else{
-		ssl->options.clientState =
-			CLIENT_CHANGECIPHERSPEC_COMPLETE;
-		if (ssl->CBIS != NULL)
-			ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
-	}
-    #endif
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            sendSz += DTLS_RECORD_EXTRA;
-            idx    += DTLS_RECORD_EXTRA;
-        }
-    #endif
-
-    /* are we in scr */
-    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
-        sendSz += MAX_MSG_EXTRA;
-    }
-
-    /* check for avalaible size */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    AddRecordHeader(output, 1, change_cipher_spec, ssl);
-
-    output[idx] = 1;             /* turn it on */
-
-    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
-        byte input[ENUM_LEN];
-        int  inputSz = ENUM_LEN;
-
-        input[0] = 1;  /* turn it on */
-        sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
-                              change_cipher_spec, 0, 0, 0);
-        if (sendSz < 0) {
-            return sendSz;
-        }
-    }
-
-    #ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                return ret;
-        }
-    #endif
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output,
-                    sendSz, WRITE_PROTO, ssl->heap);
-    #endif
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if (ssl->options.groupMessages)
-        return 0;
-    #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS)
-    else if (ssl->options.dtls) {
-        /* If using DTLS, force the ChangeCipherSpec message to be in the
-         * same datagram as the finished message. */
-        return 0;
-    }
-    #endif
-    else
-        return SendBuffered(ssl);
-}
-
-
-#ifndef NO_OLD_TLS
-static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
-                    int padLen, int content, int verify)
-{
-    byte   result[WC_MAX_DIGEST_SIZE];
-    word32 digestSz = ssl->specs.hash_size;            /* actual sizes */
-    word32 padSz    = ssl->specs.pad_size;
-    int    ret      = 0;
-
-    wc_Md5 md5;
-    wc_Sha sha;
-
-    /* data */
-    byte seq[SEQ_SZ];
-    byte conLen[ENUM_LEN + LENGTH_SZ];     /* content & length */
-    const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
-
-    (void)padLen;
-
-#ifdef HAVE_FUZZER
-    if (ssl->fuzzerCb)
-        ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
-#endif
-
-    XMEMSET(seq, 0, SEQ_SZ);
-    conLen[0] = (byte)content;
-    c16toa((word16)sz, &conLen[ENUM_LEN]);
-    WriteSEQ(ssl, verify, seq);
-
-    if (ssl->specs.mac_algorithm == md5_mac) {
-        ret =  wc_InitMd5_ex(&md5, ssl->heap, ssl->devId);
-        if (ret != 0)
-            return ret;
-
-        /* inner */
-        ret =  wc_Md5Update(&md5, macSecret, digestSz);
-        ret |= wc_Md5Update(&md5, PAD1, padSz);
-        ret |= wc_Md5Update(&md5, seq, SEQ_SZ);
-        ret |= wc_Md5Update(&md5, conLen, sizeof(conLen));
-        /* in buffer */
-        ret |= wc_Md5Update(&md5, in, sz);
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-        ret = wc_Md5Final(&md5, result);
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* TODO: Make non-blocking */
-        if (ret == WC_PENDING_E) {
-            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
-        }
-    #endif
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-
-        /* outer */
-        ret =  wc_Md5Update(&md5, macSecret, digestSz);
-        ret |= wc_Md5Update(&md5, PAD2, padSz);
-        ret |= wc_Md5Update(&md5, result, digestSz);
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-        ret =  wc_Md5Final(&md5, digest);
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* TODO: Make non-blocking */
-        if (ret == WC_PENDING_E) {
-            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
-        }
-    #endif
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-
-        wc_Md5Free(&md5);
-    }
-    else {
-        ret =  wc_InitSha_ex(&sha, ssl->heap, ssl->devId);
-        if (ret != 0)
-            return ret;
-
-        /* inner */
-        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
-        ret |= wc_ShaUpdate(&sha, PAD1, padSz);
-        ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ);
-        ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen));
-        /* in buffer */
-        ret |= wc_ShaUpdate(&sha, in, sz);
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-        ret = wc_ShaFinal(&sha, result);
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* TODO: Make non-blocking */
-        if (ret == WC_PENDING_E) {
-            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
-        }
-    #endif
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-
-        /* outer */
-        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
-        ret |= wc_ShaUpdate(&sha, PAD2, padSz);
-        ret |= wc_ShaUpdate(&sha, result, digestSz);
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-        ret =  wc_ShaFinal(&sha, digest);
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* TODO: Make non-blocking */
-        if (ret == WC_PENDING_E) {
-            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
-        }
-    #endif
-        if (ret != 0)
-            return VERIFY_MAC_ERROR;
-
-        wc_ShaFree(&sha);
-    }
-    return 0;
-}
-#endif /* NO_OLD_TLS */
-
-
-#ifndef NO_CERTS
-
-#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
-static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
-{
-    int ret;
-    byte md5_result[WC_MD5_DIGEST_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#else
-    wc_Md5  md5[1];
-#endif
-
-    /* make md5 inner */
-    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */
-    if (ret == 0)
-        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
-    if (ret == 0)
-        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
-    if (ret == 0)
-        ret = wc_Md5Final(md5, md5_result);
-
-    /* make md5 outer */
-    if (ret == 0) {
-        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
-        if (ret == 0) {
-            ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN);
-            if (ret == 0)
-                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
-            if (ret == 0)
-                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
-            if (ret == 0)
-                ret = wc_Md5Final(md5, digest);
-            wc_Md5Free(md5);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    return ret;
-}
-#endif /* !NO_MD5 && !NO_OLD_TLS */
-
-#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
-                              defined(WOLFSSL_ALLOW_TLS_SHA1))
-static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
-{
-    int ret;
-    byte sha_result[WC_SHA_DIGEST_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#else
-    wc_Sha  sha[1];
-#endif
-
-    /* make sha inner */
-    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
-    if (ret == 0)
-        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
-    if (ret == 0)
-        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
-    if (ret == 0)
-        ret = wc_ShaFinal(sha, sha_result);
-
-    /* make sha outer */
-    if (ret == 0) {
-        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
-        if (ret == 0) {
-            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
-            if (ret == 0)
-                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
-            if (ret == 0)
-                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
-            if (ret == 0)
-                ret = wc_ShaFinal(sha, digest);
-            wc_ShaFree(sha);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    return ret;
-}
-#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */
-
-int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
-{
-    int ret = 0;
-
-    (void)hashes;
-
-    if (ssl->options.tls) {
-    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
-        ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
-        if (ret != 0)
-            return ret;
-    #endif
-    #if !defined(NO_SHA)
-        ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
-        if (ret != 0)
-            return ret;
-    #endif
-        if (IsAtLeastTLSv1_2(ssl)) {
-            #ifndef NO_SHA256
-                ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,
-                                       hashes->sha256);
-                if (ret != 0)
-                    return ret;
-            #endif
-            #ifdef WOLFSSL_SHA384
-                ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384,
-                                       hashes->sha384);
-                if (ret != 0)
-                    return ret;
-            #endif
-            #ifdef WOLFSSL_SHA512
-                ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512,
-                                       hashes->sha512);
-                if (ret != 0)
-                    return ret;
-            #endif
-        }
-    }
-    else {
-    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
-        ret = BuildMD5_CertVerify(ssl, hashes->md5);
-        if (ret != 0)
-            return ret;
-    #endif
-    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
-                              defined(WOLFSSL_ALLOW_TLS_SHA1))
-        ret = BuildSHA_CertVerify(ssl, hashes->sha);
-        if (ret != 0)
-            return ret;
-    #endif
-    }
-
-    return ret;
-}
-
-#endif /* !NO_CERTS */
-
-#ifndef WOLFSSL_NO_TLS12
-/* Persistable BuildMessage arguments */
-typedef struct BuildMsgArgs {
-    word32 digestSz;
-    word32 sz;
-    word32 pad;
-    word32 idx;
-    word32 headerSz;
-    word16 size;
-    word32 ivSz;      /* TLSv1.1  IV */
-    byte*  iv;
-} BuildMsgArgs;
-
-static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs)
-{
-    BuildMsgArgs* args = (BuildMsgArgs*)pArgs;
-
-    (void)ssl;
-    (void)args;
-
-    if (args->iv) {
-        XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT);
-        args->iv = NULL;
-    }
-}
-#endif
-
-/* Build SSL Message, encrypted */
-int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
-             int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
-{
-#ifndef WOLFSSL_NO_TLS12
-    int ret = 0;
-    BuildMsgArgs* args;
-    BuildMsgArgs  lcl_args;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    args = (BuildMsgArgs*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#endif
-#endif
-
-    WOLFSSL_ENTER("BuildMessage");
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_NO_TLS12
-    return BuildTls13Message(ssl, output, outSz, input, inSz, type,
-                                               hashOutput, sizeOnly, asyncOkay);
-#else
-#ifdef WOLFSSL_TLS13
-    if (ssl->options.tls1_3) {
-        return BuildTls13Message(ssl, output, outSz, input, inSz, type,
-                                 hashOutput, sizeOnly, asyncOkay);
-    }
-#endif
-
-    ret = WC_NOT_PENDING_E;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (asyncOkay) {
-        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
-        if (ret != WC_NOT_PENDING_E) {
-            /* Check for error */
-            if (ret < 0)
-                goto exit_buildmsg;
-        }
-    }
-    else
-#endif
-    {
-        args = &lcl_args;
-    }
-
-    /* Reset state */
-    if (ret == WC_NOT_PENDING_E) {
-        ret = 0;
-        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
-        XMEMSET(args, 0, sizeof(BuildMsgArgs));
-
-        args->sz = RECORD_HEADER_SZ + inSz;
-        args->idx  = RECORD_HEADER_SZ;
-        args->headerSz = RECORD_HEADER_SZ;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeBuildMsgArgs;
-    #endif
-    }
-
-    switch (ssl->options.buildMsgState) {
-        case BUILD_MSG_BEGIN:
-        {
-            /* catch mistaken sizeOnly parameter */
-            if (!sizeOnly && (output == NULL || input == NULL) ) {
-                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
-            }
-            if (sizeOnly && (output || input) ) {
-                WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output");
-                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
-            }
-
-            ssl->options.buildMsgState = BUILD_MSG_SIZE;
-        }
-        FALL_THROUGH;
-        case BUILD_MSG_SIZE:
-        {
-            args->digestSz = ssl->specs.hash_size;
-        #ifdef HAVE_TRUNCATED_HMAC
-            if (ssl->truncated_hmac)
-                args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz);
-        #endif
-            args->sz += args->digestSz;
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls) {
-                args->sz       += DTLS_RECORD_EXTRA;
-                args->idx      += DTLS_RECORD_EXTRA;
-                args->headerSz += DTLS_RECORD_EXTRA;
-            }
-        #endif
-
-            if (ssl->specs.cipher_type == block) {
-                word32 blockSz = ssl->specs.block_size;
-                if (ssl->options.tls1_1) {
-                    args->ivSz = blockSz;
-                    args->sz  += args->ivSz;
-
-                    if (args->ivSz > MAX_IV_SZ)
-                        ERROR_OUT(BUFFER_E, exit_buildmsg);
-                }
-                args->sz += 1;       /* pad byte */
-                args->pad = (args->sz - args->headerSz) % blockSz;
-                #ifdef OPENSSL_EXTRA
-                if(args->pad != 0)
-                #endif
-                    args->pad = blockSz - args->pad;
-                args->sz += args->pad;
-            }
-
-        #ifdef HAVE_AEAD
-            if (ssl->specs.cipher_type == aead) {
-                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
-                    args->ivSz = AESGCM_EXP_IV_SZ;
-
-                args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz);
-            }
-        #endif
-
-            /* done with size calculations */
-            if (sizeOnly)
-                goto exit_buildmsg;
-
-            if (args->sz > (word32)outSz) {
-                WOLFSSL_MSG("Oops, want to write past output buffer size");
-                ERROR_OUT(BUFFER_E, exit_buildmsg);
-            }
-
-            if (args->ivSz > 0) {
-                args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT);
-                if (args->iv == NULL)
-                    ERROR_OUT(MEMORY_E, exit_buildmsg);
-
-                ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz);
-                if (ret != 0)
-                    goto exit_buildmsg;
-
-            }
-
-        #ifdef HAVE_AEAD
-            if (ssl->specs.cipher_type == aead) {
-                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
-                    XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
-            }
-        #endif
-
-            args->size = (word16)(args->sz - args->headerSz);    /* include mac and digest */
-            AddRecordHeader(output, args->size, (byte)type, ssl);
-
-            /* write to output */
-            if (args->ivSz > 0) {
-                XMEMCPY(output + args->idx, args->iv,
-                                        min(args->ivSz, MAX_IV_SZ));
-                args->idx += args->ivSz;
-            }
-            XMEMCPY(output + args->idx, input, inSz);
-            args->idx += inSz;
-
-            ssl->options.buildMsgState = BUILD_MSG_HASH;
-        }
-        FALL_THROUGH;
-        case BUILD_MSG_HASH:
-        {
-            word32 i;
-
-            if (type == handshake && hashOutput) {
-                ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
-                if (ret != 0)
-                    goto exit_buildmsg;
-            }
-            if (ssl->specs.cipher_type == block) {
-                word32 tmpIdx = args->idx + args->digestSz;
-
-                for (i = 0; i <= args->pad; i++)
-                    output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */
-            }
-
-            ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC;
-        }
-        FALL_THROUGH;
-        case BUILD_MSG_VERIFY_MAC:
-        {
-            /* User Record Layer Callback handling */
-        #ifdef ATOMIC_USER
-            if (ssl->ctx->MacEncryptCb) {
-                ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
-                                output + args->headerSz + args->ivSz, inSz, type, 0,
-                                output + args->headerSz, output + args->headerSz, args->size,
-                                ssl->MacEncryptCtx);
-                goto exit_buildmsg;
-            }
-        #endif
-
-            if (ssl->specs.cipher_type != aead) {
-        #ifdef HAVE_TRUNCATED_HMAC
-            if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) {
-            #ifdef WOLFSSL_SMALL_STACK
-                byte* hmac = NULL;
-            #else
-                byte  hmac[WC_MAX_DIGEST_SIZE];
-            #endif
-
-            #ifdef WOLFSSL_SMALL_STACK
-                hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
-                                                       DYNAMIC_TYPE_DIGEST);
-                if (hmac == NULL)
-                    ERROR_OUT(MEMORY_E, exit_buildmsg);
-            #endif
-
-                ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz,
-                                                             inSz, -1, type, 0);
-                XMEMCPY(output + args->idx, hmac, args->digestSz);
-
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
-            #endif
-            }
-            else
-        #endif
-                ret = ssl->hmac(ssl, output + args->idx, output +
-                                args->headerSz + args->ivSz, inSz, -1, type, 0);
-            }
-            if (ret != 0)
-                goto exit_buildmsg;
-
-            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
-        }
-        FALL_THROUGH;
-        case BUILD_MSG_ENCRYPT:
-        {
-            ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size,
-                asyncOkay);
-            break;
-        }
-    }
-
-exit_buildmsg:
-
-    WOLFSSL_LEAVE("BuildMessage", ret);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-#endif
-
-    /* make sure build message state is reset */
-    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
-
-    #ifdef WOLFSSL_DTLS
-        if (ret == 0 && ssl->options.dtls)
-            DtlsSEQIncrement(ssl, CUR_ORDER);
-    #endif
-
-    /* return sz on success */
-    if (ret == 0)
-        ret = args->sz;
-
-    /* Final cleanup */
-    FreeBuildMsgArgs(ssl, args);
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ssl->async.freeArgs = NULL;
-#endif
-
-    return ret;
-#endif /* !WOLFSSL_NO_TLS12 */
-}
-
-#ifndef WOLFSSL_NO_TLS12
-
-int SendFinished(WOLFSSL* ssl)
-{
-    int              sendSz,
-                     finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
-                                                     FINISHED_SZ;
-    byte             input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ];  /* max */
-    byte            *output;
-    Hashes*          hashes;
-    int              ret;
-    int              headerSz = HANDSHAKE_HEADER_SZ;
-    int              outputSz;
-
-    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
-    WOLFSSL_ENTER("SendFinished");
-
-    /* setup encrypt keys */
-    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-        return ret;
-
-    /* check for available size */
-    outputSz = sizeof(input) + MAX_MSG_EXTRA;
-    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
-        return ret;
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            headerSz += DTLS_HANDSHAKE_EXTRA;
-            ssl->keys.dtls_epoch++;
-            ssl->keys.dtls_prev_sequence_number_hi =
-                    ssl->keys.dtls_sequence_number_hi;
-            ssl->keys.dtls_prev_sequence_number_lo =
-                    ssl->keys.dtls_sequence_number_lo;
-            ssl->keys.dtls_sequence_number_hi = 0;
-            ssl->keys.dtls_sequence_number_lo = 0;
-        }
-    #endif
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
-
-    /* make finished hashes */
-    hashes = (Hashes*)&input[headerSz];
-    ret = BuildFinished(ssl, hashes,
-                     ssl->options.side == WOLFSSL_CLIENT_END ? client : server);
-    if (ret != 0) return ret;
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (ssl->secure_renegotiation) {
-        if (ssl->options.side == WOLFSSL_CLIENT_END)
-            XMEMCPY(ssl->secure_renegotiation->client_verify_data, hashes,
-                    TLS_FINISHED_SZ);
-        else
-            XMEMCPY(ssl->secure_renegotiation->server_verify_data, hashes,
-                    TLS_FINISHED_SZ);
-    }
-#endif
-
-    #ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0)
-                return ret;
-        }
-    #endif
-
-    sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
-                                                          handshake, 1, 0, 0);
-    if (sendSz < 0)
-        return BUILD_MSG_ERROR;
-
-    if (!ssl->options.resuming) {
-#ifndef NO_SESSION_CACHE
-        AddSession(ssl);    /* just try */
-#endif
-        if (ssl->options.side == WOLFSSL_SERVER_END) {
-        #ifdef OPENSSL_EXTRA
-            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-            ssl->cbmode = SSL_CB_MODE_WRITE;
-            if (ssl->CBIS != NULL)
-                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
-        #endif
-            ssl->options.handShakeState = HANDSHAKE_DONE;
-            ssl->options.handShakeDone  = 1;
-        }
-    }
-    else {
-        if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        #ifdef OPENSSL_EXTRA
-            ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-            ssl->cbmode = SSL_CB_MODE_WRITE;
-            if (ssl->CBIS != NULL)
-                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
-        #endif
-            ssl->options.handShakeState = HANDSHAKE_DONE;
-            ssl->options.handShakeDone  = 1;
-        }
-    }
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
-                          WRITE_PROTO, ssl->heap);
-    #endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendFinished", ret);
-    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
-
-    return ret;
-}
-#endif /* WOLFSSL_NO_TLS12 */
-
-#ifndef NO_WOLFSSL_SERVER
-#if (!defined(WOLFSSL_NO_TLS12) && \
-        (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
-         defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \
-    (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST))
-static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
-                             DecodedCert* cert, byte* certData, word32 length)
-{
-    int ret;
-
-    InitDecodedCert(cert, certData, length, ssl->heap);
-    /* TODO: Setup async support here */
-    ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm);
-    if (ret != 0) {
-        WOLFSSL_MSG("ParseCert failed");
-    }
-    if (ret == 0)
-        ret = InitOcspRequest(request, cert, 0, ssl->heap);
-    if (ret == 0) {
-        /* make sure ctx OCSP request is updated */
-        if (!ssl->buffers.weOwnCert) {
-            wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock;
-            if (wc_LockMutex(ocspLock) == 0) {
-                if (ssl->ctx->certOcspRequest == NULL)
-                    ssl->ctx->certOcspRequest = request;
-                wc_UnLockMutex(ocspLock);
-            }
-        }
-    }
-
-    FreeDecodedCert(cert);
-
-    return ret;
-}
-
-
-int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
-                       buffer* response)
-{
-    int          ret = 0;
-    OcspRequest* request;
-
-    if (ssl == NULL || ocspRequest == NULL || response == NULL)
-        return BAD_FUNC_ARG;
-
-    request = *ocspRequest;
-
-    XMEMSET(response, 0, sizeof(*response));
-
-    /* unable to fetch status. skip. */
-    if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
-        return 0;
-
-    if (request == NULL || ssl->buffers.weOwnCert) {
-        DerBuffer* der = ssl->buffers.certificate;
-        #ifdef WOLFSSL_SMALL_STACK
-            DecodedCert* cert = NULL;
-        #else
-            DecodedCert  cert[1];
-        #endif
-
-        /* unable to fetch status. skip. */
-        if (der->buffer == NULL || der->length == 0)
-            return 0;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
-                                        DYNAMIC_TYPE_DCERT);
-        if (cert == NULL)
-            return MEMORY_E;
-    #endif
-        request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-        if (request == NULL)
-            ret = MEMORY_E;
-
-        if (ret == 0) {
-            ret = CreateOcspRequest(ssl, request, cert, der->buffer,
-                                                                   der->length);
-        }
-
-        if (request != NULL)
-            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
-    #endif
-    }
-
-    if (ret == 0) {
-        request->ssl = ssl;
-        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response);
-
-        /* Suppressing, not critical */
-        if (ret == OCSP_CERT_REVOKED ||
-            ret == OCSP_CERT_UNKNOWN ||
-            ret == OCSP_LOOKUP_FAIL) {
-            ret = 0;
-        }
-    }
-
-    *ocspRequest = request;
-
-    return ret;
-}
-#endif
-#endif /* !NO_WOLFSSL_SERVER */
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifndef NO_CERTS
-#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
-/* handle generation of certificate (11) */
-int SendCertificate(WOLFSSL* ssl)
-{
-    int    ret = 0;
-    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
-    word32 length, maxFragment;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
-    WOLFSSL_ENTER("SendCertificate");
-
-    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
-        return 0;  /* not needed */
-
-    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
-    #ifdef OPENSSL_EXTRA
-        if (ssl->version.major == SSLv3_MAJOR
-            && ssl->version.minor == SSLv3_MINOR){
-            SendAlert(ssl, alert_warning, no_certificate);
-            return 0;
-        } else {
-    #endif
-            certSz = 0;
-            certChainSz = 0;
-            headerSz = CERT_HEADER_SZ;
-            length = CERT_HEADER_SZ;
-            listSz = 0;
-    #ifdef OPENSSL_EXTRA
-        }
-    #endif
-    }
-    else {
-        if (!ssl->buffers.certificate) {
-            WOLFSSL_MSG("Send Cert missing certificate buffer");
-            return BUFFER_ERROR;
-        }
-        certSz = ssl->buffers.certificate->length;
-        headerSz = 2 * CERT_HEADER_SZ;
-        /* list + cert size */
-        length = certSz + headerSz;
-        listSz = certSz + CERT_HEADER_SZ;
-
-        /* may need to send rest of chain, already has leading size(s) */
-        if (certSz && ssl->buffers.certChain) {
-            certChainSz = ssl->buffers.certChain->length;
-            length += certChainSz;
-            listSz += certChainSz;
-        }
-        else
-            certChainSz = 0;
-    }
-
-    payloadSz = length;
-
-    if (ssl->fragOffset != 0)
-        length -= (ssl->fragOffset + headerSz);
-
-    maxFragment = MAX_RECORD_SIZE;
-
-    if (ssl->options.dtls) {
-    #ifdef WOLFSSL_DTLS
-        /* The 100 bytes is used to account for the UDP and IP headers.
-           It can also include the record padding and MAC if the
-           SendCertificate is called for a secure renegotiation. */
-        maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ
-                      - DTLS_HANDSHAKE_HEADER_SZ - 100;
-    #endif /* WOLFSSL_DTLS */
-    }
-
-    maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment);
-
-    while (length > 0 && ret == 0) {
-        byte*  output = NULL;
-        word32 fragSz = 0;
-        word32 i = RECORD_HEADER_SZ;
-        int    sendSz = RECORD_HEADER_SZ;
-
-        if (!ssl->options.dtls) {
-            if (ssl->fragOffset == 0)  {
-                if (headerSz + certSz + certChainSz <=
-                    maxFragment - HANDSHAKE_HEADER_SZ) {
-
-                    fragSz = headerSz + certSz + certChainSz;
-                }
-                else {
-                    fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
-                }
-                sendSz += fragSz + HANDSHAKE_HEADER_SZ;
-                i += HANDSHAKE_HEADER_SZ;
-            }
-            else {
-                fragSz = min(length, maxFragment);
-                sendSz += fragSz;
-            }
-
-            if (IsEncryptionOn(ssl, 1))
-                sendSz += MAX_MSG_EXTRA;
-        }
-        else {
-        #ifdef WOLFSSL_DTLS
-            fragSz = min(length, maxFragment);
-            sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
-                      + HANDSHAKE_HEADER_SZ;
-            i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
-                      + HANDSHAKE_HEADER_SZ;
-        #endif
-        }
-
-        /* check for available size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        if (ssl->fragOffset == 0) {
-            if (!ssl->options.dtls) {
-                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
-                if (!IsEncryptionOn(ssl, 1))
-                    HashOutputRaw(ssl, output + RECORD_HEADER_SZ,
-                                  HANDSHAKE_HEADER_SZ);
-            }
-            else {
-            #ifdef WOLFSSL_DTLS
-                AddHeaders(output, payloadSz, certificate, ssl);
-                if (!IsEncryptionOn(ssl, 1))
-                    HashOutputRaw(ssl,
-                                  output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA,
-                                  HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
-                /* Adding the headers increments these, decrement them for
-                 * actual message header. */
-                ssl->keys.dtls_handshake_number--;
-                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
-                ssl->keys.dtls_handshake_number--;
-            #endif /* WOLFSSL_DTLS */
-            }
-
-            /* list total */
-            c32to24(listSz, output + i);
-            if (!IsEncryptionOn(ssl, 1))
-                HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
-            i += CERT_HEADER_SZ;
-            length -= CERT_HEADER_SZ;
-            fragSz -= CERT_HEADER_SZ;
-            if (certSz) {
-                c32to24(certSz, output + i);
-                if (!IsEncryptionOn(ssl, 1))
-                    HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
-                i += CERT_HEADER_SZ;
-                length -= CERT_HEADER_SZ;
-                fragSz -= CERT_HEADER_SZ;
-
-                if (!IsEncryptionOn(ssl, 1)) {
-                    HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz);
-                    if (certChainSz)
-                        HashOutputRaw(ssl, ssl->buffers.certChain->buffer,
-                                      certChainSz);
-                }
-            }
-        }
-        else {
-            if (!ssl->options.dtls) {
-                AddRecordHeader(output, fragSz, handshake, ssl);
-            }
-            else {
-            #ifdef WOLFSSL_DTLS
-                AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz,
-                               payloadSz, certificate, ssl);
-                ssl->keys.dtls_handshake_number--;
-            #endif /* WOLFSSL_DTLS */
-            }
-        }
-
-        /* member */
-        if (certSz && ssl->fragOffset < certSz) {
-            word32 copySz = min(certSz - ssl->fragOffset, fragSz);
-            XMEMCPY(output + i,
-                    ssl->buffers.certificate->buffer + ssl->fragOffset, copySz);
-            i += copySz;
-            ssl->fragOffset += copySz;
-            length -= copySz;
-            fragSz -= copySz;
-        }
-        if (certChainSz && fragSz) {
-            word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz);
-            XMEMCPY(output + i,
-                    ssl->buffers.certChain->buffer + ssl->fragOffset - certSz,
-                    copySz);
-            i += copySz;
-            ssl->fragOffset += copySz;
-            length -= copySz;
-        }
-
-        if (IsEncryptionOn(ssl, 1)) {
-            byte* input = NULL;
-            int   inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
-
-            if (inputSz < 0) {
-                WOLFSSL_MSG("Send Cert bad inputSz");
-                return BUFFER_E;
-            }
-
-            if (inputSz > 0) {  /* clang thinks could be zero, let's help */
-                input = (byte*)XMALLOC(inputSz, ssl->heap,
-                                       DYNAMIC_TYPE_IN_BUFFER);
-                if (input == NULL)
-                    return MEMORY_E;
-                XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
-            }
-
-            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
-                                                          handshake, 1, 0, 0);
-
-            if (inputSz > 0)
-                XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
-            if (sendSz < 0)
-                return sendSz;
-        }
-        else {
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls)
-                DtlsSEQIncrement(ssl, CUR_ORDER);
-        #endif
-        }
-
-    #ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                return ret;
-        }
-    #endif
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "Certificate");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "Certificate", handshake, output, sendSz,
-                           WRITE_PROTO, ssl->heap);
-    #endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-        if (!ssl->options.groupMessages)
-            ret = SendBuffered(ssl);
-    }
-
-    if (ret != WANT_WRITE) {
-        /* Clean up the fragment offset. */
-        ssl->fragOffset = 0;
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls)
-                ssl->keys.dtls_handshake_number++;
-        #endif
-        if (ssl->options.side == WOLFSSL_SERVER_END){
-            ssl->options.serverState = SERVER_CERT_COMPLETE;
-        }
-    }
-
-    WOLFSSL_LEAVE("SendCertificate", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
-
-    return ret;
-}
-#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
-
-/* handle generation of certificate_request (13) */
-int SendCertificateRequest(WOLFSSL* ssl)
-{
-    byte   *output;
-    int    ret;
-    int    sendSz;
-    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    word32 dnLen = 0;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
-#endif
-
-    int  typeTotal = 1;  /* only 1 for now */
-    int  reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ;  /* add auth later */
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
-    WOLFSSL_ENTER("SendCertificateRequest");
-
-    if (IsAtLeastTLSv1_2(ssl))
-        reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    /* Certificate Authorities */
-    names = ssl->ctx->ca_names;
-    while (names != NULL) {
-        byte seq[MAX_SEQ_SZ];
-
-        /* 16-bit length | SEQ | Len | DER of name */
-        dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) +
-                 names->data.name->rawLen;
-        names = names->next;
-    }
-    reqSz += dnLen;
-#endif
-
-    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
-        return 0;  /* not needed */
-
-    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-            i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-        }
-    #endif
-    /* check for available size */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    AddHeaders(output, reqSz, certificate_request, ssl);
-
-    /* write to output */
-    output[i++] = (byte)typeTotal;  /* # of types */
-#ifdef HAVE_ECC
-    if ((ssl->options.cipherSuite0 == ECC_BYTE ||
-         ssl->options.cipherSuite0 == CHACHA_BYTE) &&
-                     ssl->specs.sig_algo == ecc_dsa_sa_algo) {
-        output[i++] = ecdsa_sign;
-    } else
-#endif /* HAVE_ECC */
-    {
-        output[i++] = rsa_sign;
-    }
-
-    /* supported hash/sig */
-    if (IsAtLeastTLSv1_2(ssl)) {
-        c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
-        i += OPAQUE16_LEN;
-
-        XMEMCPY(&output[i],
-                         ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
-        i += ssl->suites->hashSigAlgoSz;
-    }
-
-    /* Certificate Authorities */
-    c16toa((word16)dnLen, &output[i]);  /* auth's */
-    i += REQ_HEADER_SZ;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    names = ssl->ctx->ca_names;
-    while (names != NULL) {
-        byte seq[MAX_SEQ_SZ];
-
-        c16toa((word16)names->data.name->rawLen +
-               SetSequence(names->data.name->rawLen, seq), &output[i]);
-        i += OPAQUE16_LEN;
-        i += SetSequence(names->data.name->rawLen, output + i);
-        XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen);
-        i += names->data.name->rawLen;
-        names = names->next;
-    }
-#endif
-    (void)i;
-
-    #ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                return ret;
-        }
-        if (ssl->options.dtls)
-            DtlsSEQIncrement(ssl, CUR_ORDER);
-    #endif
-
-    ret = HashOutput(ssl, output, sendSz, 0);
-    if (ret != 0)
-        return ret;
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "CertificateRequest");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz,
-                    WRITE_PROTO, ssl->heap);
-    #endif
-    ssl->buffers.outputBuffer.length += sendSz;
-    if (ssl->options.groupMessages)
-        ret = 0;
-    else
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendCertificateRequest", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
-
-    return ret;
-}
-
-#ifndef NO_WOLFSSL_SERVER
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
-                                                                     byte count)
-{
-    byte*  output  = NULL;
-    word32 idx     = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    word32 length  = ENUM_LEN;
-    int    sendSz  = 0;
-    int    ret     = 0;
-    int    i       = 0;
-
-    WOLFSSL_ENTER("BuildCertificateStatus");
-
-    switch (type) {
-        case WOLFSSL_CSR2_OCSP_MULTI:
-            length += OPAQUE24_LEN;
-            FALL_THROUGH; /* followed by */
-
-        case WOLFSSL_CSR2_OCSP:
-            for (i = 0; i < count; i++)
-                length += OPAQUE24_LEN + status[i].length;
-        break;
-
-        default:
-            return 0;
-    }
-
-    sendSz = idx + length;
-
-    if (ssl->keys.encryptionOn)
-        sendSz += MAX_MSG_EXTRA;
-
-    if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        AddHeaders(output, length, certificate_status, ssl);
-
-        output[idx++] = type;
-
-        if (type == WOLFSSL_CSR2_OCSP_MULTI) {
-            c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
-            idx += OPAQUE24_LEN;
-        }
-
-        for (i = 0; i < count; i++) {
-            c32to24(status[i].length, output + idx);
-            idx += OPAQUE24_LEN;
-
-            XMEMCPY(output + idx, status[i].buffer, status[i].length);
-            idx += status[i].length;
-        }
-
-        if (IsEncryptionOn(ssl, 1)) {
-            byte* input;
-            int   inputSz = idx - RECORD_HEADER_SZ;
-
-            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-            if (input == NULL)
-                return MEMORY_E;
-
-            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
-            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
-                                                           handshake, 1, 0, 0);
-            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
-            if (sendSz < 0)
-                ret = sendSz;
-        }
-        else {
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-            ret = HashOutput(ssl, output, sendSz, 0);
-        }
-
-    #ifdef WOLFSSL_DTLS
-        if (ret == 0 && IsDtlsNotSctpMode(ssl))
-            ret = DtlsMsgPoolSave(ssl, output, sendSz);
-    #endif
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ret == 0 && ssl->hsInfoOn)
-            AddPacketName(ssl, "CertificateStatus");
-        if (ret == 0 && ssl->toInfoOn)
-            AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz,
-                    WRITE_PROTO, ssl->heap);
-    #endif
-
-        if (ret == 0) {
-            ssl->buffers.outputBuffer.length += sendSz;
-            if (!ssl->options.groupMessages)
-                ret = SendBuffered(ssl);
-        }
-    }
-
-    WOLFSSL_LEAVE("BuildCertificateStatus", ret);
-    return ret;
-}
-#endif
-#endif /* NO_WOLFSSL_SERVER */
-
-/* handle generation of certificate_status (22) */
-int SendCertificateStatus(WOLFSSL* ssl)
-{
-    int ret = 0;
-    byte status_type = 0;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
-    WOLFSSL_ENTER("SendCertificateStatus");
-
-    (void) ssl;
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-    status_type = ssl->status_request;
-#endif
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-    status_type = status_type ? status_type : ssl->status_request_v2;
-#endif
-
-    switch (status_type) {
-
-    #ifndef NO_WOLFSSL_SERVER
-    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
-     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-        /* case WOLFSSL_CSR_OCSP: */
-        case WOLFSSL_CSR2_OCSP:
-        {
-            OcspRequest* request = ssl->ctx->certOcspRequest;
-            buffer response;
-
-            ret = CreateOcspResponse(ssl, &request, &response);
-            if (ret == 0 && response.buffer) {
-                ret = BuildCertificateStatus(ssl, status_type, &response, 1);
-
-                XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-                response.buffer = NULL;
-            }
-
-            break;
-        }
-
-    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST    */
-           /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-
-    #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
-        case WOLFSSL_CSR2_OCSP_MULTI:
-        {
-            OcspRequest* request = ssl->ctx->certOcspRequest;
-            buffer responses[1 + MAX_CHAIN_DEPTH];
-            int i = 0;
-
-            XMEMSET(responses, 0, sizeof(responses));
-
-            ret = CreateOcspResponse(ssl, &request, &responses[0]);
-            if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
-                                              || ssl->buffers.weOwnCertChain)) {
-                buffer der;
-                word32 idx = 0;
-            #ifdef WOLFSSL_SMALL_STACK
-                DecodedCert* cert = NULL;
-            #else
-                DecodedCert  cert[1];
-            #endif
-
-            #ifdef WOLFSSL_SMALL_STACK
-                cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
-                                                            DYNAMIC_TYPE_DCERT);
-                if (cert == NULL)
-                    return MEMORY_E;
-            #endif
-                request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-                if (request == NULL) {
-            #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
-            #endif
-                    return MEMORY_E;
-                }
-
-                while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) {
-                    c24to32(ssl->buffers.certChain->buffer + idx, &der.length);
-                    idx += OPAQUE24_LEN;
-
-                    der.buffer = ssl->buffers.certChain->buffer + idx;
-                    idx += der.length;
-
-                    if (idx > ssl->buffers.certChain->length)
-                        break;
-
-                    ret = CreateOcspRequest(ssl, request, cert, der.buffer,
-                                                                    der.length);
-                    if (ret == 0) {
-                        request->ssl = ssl;
-                        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
-                                                    request, &responses[i + 1]);
-
-                        /* Suppressing, not critical */
-                        if (ret == OCSP_CERT_REVOKED ||
-                            ret == OCSP_CERT_UNKNOWN ||
-                            ret == OCSP_LOOKUP_FAIL) {
-                            ret = 0;
-                        }
-
-
-                        i++;
-                    }
-                }
-
-                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
-            #endif
-            }
-            else {
-                while (ret == 0 &&
-                            NULL != (request = ssl->ctx->chainOcspRequest[i])) {
-                    request->ssl = ssl;
-                    ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
-                                                request, &responses[++i]);
-
-                    /* Suppressing, not critical */
-                    if (ret == OCSP_CERT_REVOKED ||
-                        ret == OCSP_CERT_UNKNOWN ||
-                        ret == OCSP_LOOKUP_FAIL) {
-                        ret = 0;
-                    }
-                }
-            }
-
-            if (responses[0].buffer) {
-                if (ret == 0) {
-                    ret = BuildCertificateStatus(ssl, status_type, responses,
-                                                                   (byte)i + 1);
-                }
-
-                for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) {
-                    if (responses[i].buffer) {
-                        XFREE(responses[i].buffer, ssl->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-                    }
-                }
-            }
-
-            break;
-        }
-    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-    #endif /* NO_WOLFSSL_SERVER */
-
-        default:
-            break;
-    }
-
-    WOLFSSL_LEAVE("SendCertificateStatus", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND);
-
-    return ret;
-}
-
-#endif /* !NO_CERTS */
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-int SendData(WOLFSSL* ssl, const void* data, int sz)
-{
-    int sent = 0,  /* plainText size */
-        sendSz,
-        ret,
-        dtlsExtra = 0;
-
-    if (ssl->error == WANT_WRITE
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        || ssl->error == WC_PENDING_E
-    #endif
-    ) {
-        ssl->error = 0;
-    }
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        /* In DTLS mode, we forgive some errors and allow the session
-         * to continue despite them. */
-        if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
-            ssl->error = 0;
-    }
-#endif /* WOLFSSL_DTLS */
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-        if (ssl->options.handShakeState == HANDSHAKE_DONE) {
-            WOLFSSL_MSG("handshake complete, trying to send early data");
-            return BUILD_MSG_ERROR;
-        }
-    }
-    else
-#endif
-    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
-        int err;
-        WOLFSSL_MSG("handshake not complete, trying to finish");
-        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* if async would block return WANT_WRITE */
-            if (ssl->error == WC_PENDING_E) {
-                return WOLFSSL_CBIO_ERR_WANT_WRITE;
-            }
-        #endif
-            return  err;
-        }
-    }
-
-    /* last time system socket output buffer was full, try again to send */
-    if (ssl->buffers.outputBuffer.length > 0) {
-        WOLFSSL_MSG("output buffer was full, trying to send again");
-        if ( (ssl->error = SendBuffered(ssl)) < 0) {
-            WOLFSSL_ERROR(ssl->error);
-            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
-                                                 ssl->options.isClosed)) {
-                ssl->error = SOCKET_PEER_CLOSED_E;
-                WOLFSSL_ERROR(ssl->error);
-                return 0;  /* peer reset or closed */
-            }
-            return ssl->error;
-        }
-        else {
-            /* advance sent to previous sent + plain size just sent */
-            sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
-            WOLFSSL_MSG("sent write buffered data");
-
-            if (sent > sz) {
-                WOLFSSL_MSG("error: write() after WANT_WRITE with short size");
-                return ssl->error = BAD_FUNC_ARG;
-            }
-        }
-    }
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        dtlsExtra = DTLS_RECORD_EXTRA;
-    }
-#endif
-
-    for (;;) {
-        int   len;
-        byte* out;
-        byte* sendBuffer = (byte*)data + sent;  /* may switch on comp */
-        int   buffSz;                           /* may switch on comp */
-        int   outputSz;
-#ifdef HAVE_LIBZ
-        byte  comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
-#endif
-
-        if (sent == sz) break;
-
-        len = wolfSSL_GetMaxRecordSize(ssl, sz - sent);
-
-#ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            len = min(len, MAX_UDP_SIZE);
-        }
-#endif
-        buffSz = len;
-
-        /* check for available size */
-        outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA;
-        if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
-            return ssl->error = ret;
-
-        /* get output buffer */
-        out = ssl->buffers.outputBuffer.buffer +
-              ssl->buffers.outputBuffer.length;
-
-#ifdef HAVE_LIBZ
-        if (ssl->options.usingCompression) {
-            buffSz = myCompress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
-            if (buffSz < 0) {
-                return buffSz;
-            }
-            sendBuffer = comp;
-        }
-#endif
-        if (!ssl->options.tls1_3) {
-            sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
-                                  application_data, 0, 0, 1);
-        }
-        else {
-#ifdef WOLFSSL_TLS13
-            sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz,
-                                       application_data, 0, 0, 1);
-#else
-            sendSz = BUFFER_ERROR;
-#endif
-        }
-        if (sendSz < 0) {
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (sendSz == WC_PENDING_E)
-                ssl->error = sendSz;
-        #endif
-            return BUILD_MSG_ERROR;
-        }
-
-        ssl->buffers.outputBuffer.length += sendSz;
-
-        if ( (ssl->error = SendBuffered(ssl)) < 0) {
-            WOLFSSL_ERROR(ssl->error);
-            /* store for next call if WANT_WRITE or user embedSend() that
-               doesn't present like WANT_WRITE */
-            ssl->buffers.plainSz  = len;
-            ssl->buffers.prevSent = sent;
-            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
-                                                 ssl->options.isClosed)) {
-                ssl->error = SOCKET_PEER_CLOSED_E;
-                WOLFSSL_ERROR(ssl->error);
-                return 0;  /* peer reset or closed */
-            }
-            return ssl->error;
-        }
-
-        sent += len;
-
-        /* only one message per attempt */
-        if (ssl->options.partialWrite == 1) {
-            WOLFSSL_MSG("Paritial Write on, only sending one record");
-            break;
-        }
-    }
-
-    return sent;
-}
-
-/* process input data */
-int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
-{
-    int size;
-
-    WOLFSSL_ENTER("ReceiveData()");
-
-    /* reset error state */
-    if (ssl->error == WANT_READ
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        || ssl->error == WC_PENDING_E
-    #endif
-    ) {
-        ssl->error = 0;
-    }
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        /* In DTLS mode, we forgive some errors and allow the session
-         * to continue despite them. */
-        if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
-            ssl->error = 0;
-    }
-#endif /* WOLFSSL_DTLS */
-
-    if (ssl->error != 0 && ssl->error != WANT_WRITE) {
-        WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
-        return ssl->error;
-    }
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-    }
-    else
-#endif
-    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
-        int err;
-        WOLFSSL_MSG("Handshake not complete, trying to finish");
-        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* if async would block return WANT_WRITE */
-            if (ssl->error == WC_PENDING_E) {
-                return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-        #endif
-            return  err;
-        }
-    }
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-startScr:
-    if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
-        int err;
-        ssl->secure_renegotiation->startScr = 0;  /* only start once */
-        WOLFSSL_MSG("Need to start scr, server requested");
-        if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS)
-            return  err;
-    }
-#endif
-
-    while (ssl->buffers.clearOutputBuffer.length == 0) {
-        if ( (ssl->error = ProcessReply(ssl)) < 0) {
-            WOLFSSL_ERROR(ssl->error);
-            if (ssl->error == ZERO_RETURN) {
-                WOLFSSL_MSG("Zero return, no more data coming");
-                return 0;         /* no more data coming */
-            }
-            if (ssl->error == SOCKET_ERROR_E) {
-                if (ssl->options.connReset || ssl->options.isClosed) {
-                    WOLFSSL_MSG("Peer reset or closed, connection done");
-                    ssl->error = SOCKET_PEER_CLOSED_E;
-                    WOLFSSL_ERROR(ssl->error);
-                    return 0;     /* peer reset or closed */
-                }
-            }
-            return ssl->error;
-        }
-        #ifdef HAVE_SECURE_RENEGOTIATION
-            if (ssl->secure_renegotiation &&
-                ssl->secure_renegotiation->startScr) {
-                goto startScr;
-            }
-        #endif
-    }
-
-    if (sz < (int)ssl->buffers.clearOutputBuffer.length)
-        size = sz;
-    else
-        size = ssl->buffers.clearOutputBuffer.length;
-
-    XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
-
-    if (peek == 0) {
-        ssl->buffers.clearOutputBuffer.length -= size;
-        ssl->buffers.clearOutputBuffer.buffer += size;
-    }
-
-    if (ssl->buffers.clearOutputBuffer.length == 0 &&
-                                           ssl->buffers.inputBuffer.dynamicFlag)
-       ShrinkInputBuffer(ssl, NO_FORCED_FREE);
-
-    WOLFSSL_LEAVE("ReceiveData()", size);
-    return size;
-}
-
-
-/* send alert message */
-int SendAlert(WOLFSSL* ssl, int severity, int type)
-{
-    byte input[ALERT_SIZE];
-    byte *output;
-    int  sendSz;
-    int  ret;
-    int  outputSz;
-    int  dtlsExtra = 0;
-
-#ifdef HAVE_WRITE_DUP
-    if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
-        int notifyErr = 0;
-
-        WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
-
-        if (type == close_notify) {
-            notifyErr = ZERO_RETURN;
-        } else if (severity == alert_fatal) {
-            notifyErr = FATAL_ERROR;
-        }
-
-        if (notifyErr != 0) {
-            return NotifyWriteSide(ssl, notifyErr);
-        }
-
-        return 0;
-    }
-#endif
-
-    /* if sendalert is called again for nonblocking */
-    if (ssl->options.sendAlertState != 0) {
-        ret = SendBuffered(ssl);
-        if (ret == 0)
-            ssl->options.sendAlertState = 0;
-        return ret;
-    }
-
-   #ifdef OPENSSL_EXTRA
-        if (ssl->CBIS != NULL) {
-            ssl->CBIS(ssl, SSL_CB_ALERT, type);
-        }
-   #endif
-   #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls)
-           dtlsExtra = DTLS_RECORD_EXTRA;
-   #endif
-
-    /* check for available size */
-    outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra;
-    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
-        return ret;
-
-    /* Check output buffer */
-    if (ssl->buffers.outputBuffer.buffer == NULL)
-        return BUFFER_E;
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    input[0] = (byte)severity;
-    input[1] = (byte)type;
-    ssl->alert_history.last_tx.code = type;
-    ssl->alert_history.last_tx.level = severity;
-    if (severity == alert_fatal) {
-        ssl->options.isClosed = 1;  /* Don't send close_notify */
-    }
-
-    /* only send encrypted alert if handshake actually complete, otherwise
-       other side may not be able to handle it */
-    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
-        sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE,
-                                                          alert, 0, 0, 0);
-    else {
-
-        AddRecordHeader(output, ALERT_SIZE, alert, ssl);
-        output += RECORD_HEADER_SZ;
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls)
-                output += DTLS_RECORD_EXTRA;
-        #endif
-        XMEMCPY(output, input, ALERT_SIZE);
-
-        sendSz = RECORD_HEADER_SZ + ALERT_SIZE;
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls)
-                sendSz += DTLS_RECORD_EXTRA;
-        #endif
-    }
-    if (sendSz < 0)
-        return BUILD_MSG_ERROR;
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "Alert");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO,
-                    ssl->heap);
-    #endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-    ssl->options.sendAlertState = 1;
-
-    return SendBuffered(ssl);
-}
-
-const char* wolfSSL_ERR_reason_error_string(unsigned long e)
-{
-#ifdef NO_ERROR_STRINGS
-
-    (void)e;
-    return "no support for error strings built in";
-
-#else
-
-    int error = (int)e;
-
-    /* pass to wolfCrypt */
-    if (error < MAX_CODE_E && error > MIN_CODE_E) {
-        return wc_GetErrorString(error);
-    }
-
-    switch (error) {
-
-#ifdef WOLFSSL_WPAS
-    case 0 :
-        return "ok";
-#endif
-
-    case UNSUPPORTED_SUITE :
-        return "unsupported cipher suite";
-
-    case INPUT_CASE_ERROR :
-        return "input state error";
-
-    case PREFIX_ERROR :
-        return "bad index to key rounds";
-
-    case MEMORY_ERROR :
-        return "out of memory";
-
-    case VERIFY_FINISHED_ERROR :
-        return "verify problem on finished";
-
-    case VERIFY_MAC_ERROR :
-        return "verify mac problem";
-
-    case PARSE_ERROR :
-        return "parse error on header";
-
-    case SIDE_ERROR :
-        return "wrong client/server type";
-
-    case NO_PEER_CERT :
-        return "peer didn't send cert";
-
-    case UNKNOWN_HANDSHAKE_TYPE :
-        return "weird handshake type";
-
-    case SOCKET_ERROR_E :
-        return "error state on socket";
-
-    case SOCKET_NODATA :
-        return "expected data, not there";
-
-    case INCOMPLETE_DATA :
-        return "don't have enough data to complete task";
-
-    case UNKNOWN_RECORD_TYPE :
-        return "unknown type in record hdr";
-
-    case DECRYPT_ERROR :
-        return "error during decryption";
-
-    case FATAL_ERROR :
-        return "revcd alert fatal error";
-
-    case ENCRYPT_ERROR :
-        return "error during encryption";
-
-    case FREAD_ERROR :
-        return "fread problem";
-
-    case NO_PEER_KEY :
-        return "need peer's key";
-
-    case NO_PRIVATE_KEY :
-        return "need the private key";
-
-    case NO_DH_PARAMS :
-        return "server missing DH params";
-
-    case RSA_PRIVATE_ERROR :
-        return "error during rsa priv op";
-
-    case MATCH_SUITE_ERROR :
-        return "can't match cipher suite";
-
-    case COMPRESSION_ERROR :
-        return "compression mismatch error";
-
-    case BUILD_MSG_ERROR :
-        return "build message failure";
-
-    case BAD_HELLO :
-        return "client hello malformed";
-
-    case DOMAIN_NAME_MISMATCH :
-        return "peer subject name mismatch";
-
-    case WANT_READ :
-    case WOLFSSL_ERROR_WANT_READ :
-        return "non-blocking socket wants data to be read";
-
-    case NOT_READY_ERROR :
-        return "handshake layer not ready yet, complete first";
-
-    case VERSION_ERROR :
-        return "record layer version error";
-
-    case WANT_WRITE :
-    case WOLFSSL_ERROR_WANT_WRITE :
-        return "non-blocking socket write buffer full";
-
-    case BUFFER_ERROR :
-        return "malformed buffer input error";
-
-    case VERIFY_CERT_ERROR :
-        return "verify problem on certificate";
-
-    case VERIFY_SIGN_ERROR :
-        return "verify problem based on signature";
-
-    case CLIENT_ID_ERROR :
-        return "psk client identity error";
-
-    case SERVER_HINT_ERROR:
-        return "psk server hint error";
-
-    case PSK_KEY_ERROR:
-        return "psk key callback error";
-
-    case NTRU_KEY_ERROR:
-        return "NTRU key error";
-
-    case NTRU_DRBG_ERROR:
-        return "NTRU drbg error";
-
-    case NTRU_ENCRYPT_ERROR:
-        return "NTRU encrypt error";
-
-    case NTRU_DECRYPT_ERROR:
-        return "NTRU decrypt error";
-
-    case ZLIB_INIT_ERROR:
-        return "zlib init error";
-
-    case ZLIB_COMPRESS_ERROR:
-        return "zlib compress error";
-
-    case ZLIB_DECOMPRESS_ERROR:
-        return "zlib decompress error";
-
-    case GETTIME_ERROR:
-        return "gettimeofday() error";
-
-    case GETITIMER_ERROR:
-        return "getitimer() error";
-
-    case SIGACT_ERROR:
-        return "sigaction() error";
-
-    case SETITIMER_ERROR:
-        return "setitimer() error";
-
-    case LENGTH_ERROR:
-        return "record layer length error";
-
-    case PEER_KEY_ERROR:
-        return "cant decode peer key";
-
-    case ZERO_RETURN:
-    case WOLFSSL_ERROR_ZERO_RETURN:
-        return "peer sent close notify alert";
-
-    case ECC_CURVETYPE_ERROR:
-        return "Bad ECC Curve Type or unsupported";
-
-    case ECC_CURVE_ERROR:
-        return "Bad ECC Curve or unsupported";
-
-    case ECC_PEERKEY_ERROR:
-        return "Bad ECC Peer Key";
-
-    case ECC_MAKEKEY_ERROR:
-        return "ECC Make Key failure";
-
-    case ECC_EXPORT_ERROR:
-        return "ECC Export Key failure";
-
-    case ECC_SHARED_ERROR:
-        return "ECC DHE shared failure";
-
-    case NOT_CA_ERROR:
-        return "Not a CA by basic constraint error";
-
-    case HTTP_TIMEOUT:
-        return "HTTP timeout for OCSP or CRL req";
-
-    case BAD_CERT_MANAGER_ERROR:
-        return "Bad Cert Manager error";
-
-    case OCSP_CERT_REVOKED:
-        return "OCSP Cert revoked";
-
-    case CRL_CERT_REVOKED:
-        return "CRL Cert revoked";
-
-    case CRL_MISSING:
-        return "CRL missing, not loaded";
-
-    case MONITOR_SETUP_E:
-        return "CRL monitor setup error";
-
-    case THREAD_CREATE_E:
-        return "Thread creation problem";
-
-    case OCSP_NEED_URL:
-        return "OCSP need URL";
-
-    case OCSP_CERT_UNKNOWN:
-        return "OCSP Cert unknown";
-
-    case OCSP_LOOKUP_FAIL:
-        return "OCSP Responder lookup fail";
-
-    case MAX_CHAIN_ERROR:
-        return "Maximum Chain Depth Exceeded";
-
-    case COOKIE_ERROR:
-        return "DTLS Cookie Error";
-
-    case SEQUENCE_ERROR:
-        return "DTLS Sequence Error";
-
-    case SUITES_ERROR:
-        return "Suites Pointer Error";
-
-    case OUT_OF_ORDER_E:
-        return "Out of order message, fatal";
-
-    case BAD_KEA_TYPE_E:
-        return "Bad KEA type found";
-
-    case SANITY_CIPHER_E:
-        return "Sanity check on ciphertext failed";
-
-    case RECV_OVERFLOW_E:
-        return "Receive callback returned more than requested";
-
-    case GEN_COOKIE_E:
-        return "Generate Cookie Error";
-
-    case NO_PEER_VERIFY:
-        return "Need peer certificate verify Error";
-
-    case FWRITE_ERROR:
-        return "fwrite Error";
-
-    case CACHE_MATCH_ERROR:
-        return "Cache restore header match Error";
-
-    case UNKNOWN_SNI_HOST_NAME_E:
-        return "Unrecognized host name Error";
-
-    case UNKNOWN_MAX_FRAG_LEN_E:
-        return "Unrecognized max frag len Error";
-
-    case KEYUSE_SIGNATURE_E:
-        return "Key Use digitalSignature not set Error";
-
-    case KEYUSE_ENCIPHER_E:
-        return "Key Use keyEncipherment not set Error";
-
-    case EXTKEYUSE_AUTH_E:
-        return "Ext Key Use server/client auth not set Error";
-
-    case SEND_OOB_READ_E:
-        return "Send Callback Out of Bounds Read Error";
-
-    case SECURE_RENEGOTIATION_E:
-        return "Invalid Renegotiation Error";
-
-    case SESSION_TICKET_LEN_E:
-        return "Session Ticket Too Long Error";
-
-    case SESSION_TICKET_EXPECT_E:
-        return "Session Ticket Error";
-
-    case SCR_DIFFERENT_CERT_E:
-        return "Peer sent different cert during SCR";
-
-    case SESSION_SECRET_CB_E:
-        return "Session Secret Callback Error";
-
-    case NO_CHANGE_CIPHER_E:
-        return "Finished received from peer before Change Cipher Error";
-
-    case SANITY_MSG_E:
-        return "Sanity Check on message order Error";
-
-    case DUPLICATE_MSG_E:
-        return "Duplicate HandShake message Error";
-
-    case SNI_UNSUPPORTED:
-        return "Protocol version does not support SNI Error";
-
-    case SOCKET_PEER_CLOSED_E:
-        return "Peer closed underlying transport Error";
-
-    case BAD_TICKET_KEY_CB_SZ:
-        return "Bad user session ticket key callback Size Error";
-
-    case BAD_TICKET_MSG_SZ:
-        return "Bad session ticket message Size Error";
-
-    case BAD_TICKET_ENCRYPT:
-        return "Bad user ticket callback encrypt Error";
-
-    case DH_KEY_SIZE_E:
-        return "DH key too small Error";
-
-    case SNI_ABSENT_ERROR:
-        return "No Server Name Indication extension Error";
-
-    case RSA_SIGN_FAULT:
-        return "RSA Signature Fault Error";
-
-    case HANDSHAKE_SIZE_ERROR:
-        return "Handshake message too large Error";
-
-    case UNKNOWN_ALPN_PROTOCOL_NAME_E:
-        return "Unrecognized protocol name Error";
-
-    case BAD_CERTIFICATE_STATUS_ERROR:
-        return "Bad Certificate Status Message Error";
-
-    case OCSP_INVALID_STATUS:
-        return "Invalid OCSP Status Error";
-
-    case OCSP_WANT_READ:
-        return "OCSP nonblock wants read";
-
-    case RSA_KEY_SIZE_E:
-        return "RSA key too small";
-
-    case ECC_KEY_SIZE_E:
-        return "ECC key too small";
-
-    case DTLS_EXPORT_VER_E:
-        return "Version needs updated after code change or version mismatch";
-
-    case INPUT_SIZE_E:
-        return "Input size too large Error";
-
-    case CTX_INIT_MUTEX_E:
-        return "Initialize ctx mutex error";
-
-    case EXT_MASTER_SECRET_NEEDED_E:
-        return "Extended Master Secret must be enabled to resume EMS session";
-
-    case DTLS_POOL_SZ_E:
-        return "Maximum DTLS pool size exceeded";
-
-    case DECODE_E:
-        return "Decode handshake message error";
-
-    case WRITE_DUP_READ_E:
-        return "Write dup write side can't read error";
-
-    case WRITE_DUP_WRITE_E:
-        return "Write dup read side can't write error";
-
-    case INVALID_CERT_CTX_E:
-        return "Certificate context does not match request or not empty";
-
-    case BAD_KEY_SHARE_DATA:
-        return "The Key Share data contains group that was in Client Hello";
-
-    case MISSING_HANDSHAKE_DATA:
-        return "The handshake message is missing required data";
-
-    case BAD_BINDER:
-        return "Binder value does not match value server calculated";
-
-    case EXT_NOT_ALLOWED:
-        return "Extension type not allowed in handshake message type";
-
-    case INVALID_PARAMETER:
-        return "The security parameter is invalid";
-
-    case UNSUPPORTED_EXTENSION:
-        return "TLS Extension not requested by the client";
-
-    case KEY_SHARE_ERROR:
-        return "Key share extension did not contain a valid named group";
-
-    case POST_HAND_AUTH_ERROR:
-        return "Client will not do post handshake authentication";
-
-    case HRR_COOKIE_ERROR:
-        return "Cookie does not match one sent in HelloRetryRequest";
-
-    case MCAST_HIGHWATER_CB_E:
-        return "Multicast highwater callback returned error";
-
-    case ALERT_COUNT_E:
-        return "Alert Count exceeded error";
-
-    case EXT_MISSING:
-        return "Required TLS extension missing";
-
-    default :
-        return "unknown error number";
-    }
-
-#endif /* NO_ERROR_STRINGS */
-}
-
-void SetErrorString(int error, char* str)
-{
-    XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
-}
-
-#ifndef NO_ERROR_STRINGS
-    #define SUITE_INFO(x,y,z,w) {(x),(y),(z),(w)}
-#else
-    #define SUITE_INFO(x,y,z,w) {(x),(z),(w)}
-#endif
-
-static const CipherSuiteInfo cipher_names[] =
-{
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
-    SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
-    SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5),
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
-    SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
-    SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-    SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-    SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-    SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-    SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
-    SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
-    SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
-    SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
-    SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-    SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-    SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
-    SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
-    SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
-    SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
-    SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
-    SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
-    SUITE_INFO("HC128-B2B256","TLS_RSA_WITH_HC_128_B2B256",CIPHER_BYTE,TLS_RSA_WITH_HC_128_B2B256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
-    SUITE_INFO("AES128-B2B256","TLS_RSA_WITH_AES_128_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_B2B256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
-    SUITE_INFO("AES256-B2B256","TLS_RSA_WITH_AES_256_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_B2B256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
-    SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA),
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-    SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
-    SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
-    SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-	SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-    SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-    SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-    SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-    SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-    SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-    SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-    SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-    SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-    SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-    SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-    SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-    SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-    SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-    SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-    SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
-    SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_QSH
-    SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH),
-#endif
-
-#ifdef HAVE_RENEGOTIATION_INDICATION
-    SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV),
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-    SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-    SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-    SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-    SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256),
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-    SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA),
-#endif
-
-#ifdef BUILD_WDM_WITH_NULL_SHA256
-    SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256),
-#endif
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-#ifdef BUILD_TLS_AES_128_GCM_SHA256
-    SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_AES_256_GCM_SHA384
-    SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384),
-#endif
-
-#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
-    SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256),
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_SHA256
-    SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256),
-#endif
-
-#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
-    SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256),
-#endif
-};
-
-
-/* returns the cipher_names array */
-const CipherSuiteInfo* GetCipherNames(void)
-{
-    return cipher_names;
-}
-
-
-/* returns the number of elements in the cipher_names array */
-int GetCipherNamesSize(void)
-{
-    return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo));
-}
-
-
-const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite)
-{
-    int i;
-    const char* nameInternal = NULL;
-
-    for (i = 0; i < GetCipherNamesSize(); i++) {
-        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
-            (cipher_names[i].cipherSuite  == cipherSuite)) {
-            nameInternal = cipher_names[i].name;
-            break;
-        }
-    }
-    return nameInternal;
-}
-
-const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite)
-{
-#ifndef NO_ERROR_STRINGS
-    int i;
-    const char* nameIana = "NONE";
-
-    for (i = 0; i < GetCipherNamesSize(); i++) {
-        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
-            (cipher_names[i].cipherSuite  == cipherSuite)) {
-            nameIana = cipher_names[i].name_iana;
-            break;
-        }
-    }
-    return nameIana;
-#else
-    (void)cipherSuite0;
-    (void)cipherSuite;
-    return NULL;
-#endif
-}
-
-const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl)
-{
-    if (ssl == NULL) {
-        return NULL;
-    }
-
-    return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite);
-}
-
-const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
-{
-    if (ssl == NULL) {
-        return NULL;
-    }
-
-    return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite);
-}
-
-
-/**
-Set the enabled cipher suites.
-
-@param [out] suites Suites structure.
-@param [in]  list   List of cipher suites, only supports full name from
-                    cipher_names[] delimited by ':'.
-
-@return true on success, else false.
-*/
-int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list)
-{
-    int       ret          = 0;
-    int       idx          = 0;
-    int       haveRSAsig   = 0;
-    int       haveECDSAsig = 0;
-    int       haveAnon     = 0;
-    const int suiteSz      = GetCipherNamesSize();
-    char*     next         = (char*)list;
-
-    if (suites == NULL || list == NULL) {
-        WOLFSSL_MSG("SetCipherList parameter error");
-        return 0;
-    }
-
-    if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 ||
-                        XSTRNCMP(next, "DEFAULT", 7) == 0)
-        return 1; /* wolfSSL defualt */
-
-    do {
-        char*  current = next;
-        char   name[MAX_SUITE_NAME + 1];
-        int    i;
-        word32 length;
-
-        next   = XSTRSTR(next, ":");
-        length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
-                                         : (word32)(next - current));
-
-        XSTRNCPY(name, current, length);
-        name[(length == sizeof(name)) ? length - 1 : length] = 0;
-
-        for (i = 0; i < suiteSz; i++) {
-            if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0) {
-            #ifdef WOLFSSL_DTLS
-                /* don't allow stream ciphers with DTLS */
-                if (ctx->method->version.major == DTLS_MAJOR) {
-                    if (XSTRSTR(name, "RC4") ||
-                        XSTRSTR(name, "HC128") ||
-                        XSTRSTR(name, "RABBIT"))
-                    {
-                        WOLFSSL_MSG("Stream ciphers not supported with DTLS");
-                        continue;
-                    }
-
-                }
-            #endif /* WOLFSSL_DTLS */
-
-                if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) {
-                    WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low");
-                    return 0; /* suites buffer not large enough, error out */
-                }
-
-                suites->suites[idx++] =
-            #ifdef WOLFSSL_TLS13
-                    (XSTRSTR(name, "TLS13"))  ? TLS13_BYTE :
-            #endif
-            #ifdef HAVE_CHACHA
-                    (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE :
-            #endif
-            #ifdef HAVE_QSH
-                    (XSTRSTR(name, "QSH"))    ? QSH_BYTE :
-            #endif
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    (XSTRSTR(name, "EC"))     ? ECC_BYTE :
-            #endif
-            #ifdef HAVE_AESCCM
-                    (XSTRSTR(name, "CCM"))    ? ECC_BYTE :
-            #endif
-                    CIPHER_BYTE; /* normal */
-
-                suites->suites[idx++] = cipher_names[i].cipherSuite;
-                /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA
-                 * suites don't necessarily have RSA in the name. */
-            #ifdef WOLFSSL_TLS13
-                if (XSTRSTR(name, "TLS13")) {
-                    haveRSAsig = 1;
-                    haveECDSAsig = 1;
-                }
-                else
-            #endif
-            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
-                if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
-                    haveECDSAsig = 1;
-                else
-            #endif
-            #ifdef HAVE_ANON
-                if (XSTRSTR(name, "ADH"))
-                    haveAnon = 1;
-                else
-            #endif
-                if (haveRSAsig == 0
-                    #ifndef NO_PSK
-                        && (XSTRSTR(name, "PSK") == NULL)
-                    #endif
-                   ) {
-                    haveRSAsig = 1;
-                }
-
-                ret = 1; /* found at least one */
-                break;
-            }
-        }
-    }
-    while (next++); /* ++ needed to skip ':' */
-
-    if (ret) {
-        int keySz = 0;
-    #ifndef NO_CERTS
-        keySz = ctx->privateKeySz;
-    #endif
-        suites->setSuites = 1;
-        suites->suiteSz   = (word16)idx;
-        InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1,
-                              keySz);
-    }
-
-    (void)ctx;
-
-    return ret;
-}
-
-
-#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
-void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
-                     word32 hashSigAlgoSz)
-{
-    word32 i;
-
-    ssl->suites->sigAlgo = ssl->specs.sig_algo;
-
-    /* set defaults */
-    if (IsAtLeastTLSv1_3(ssl->version)) {
-        ssl->suites->hashAlgo = sha256_mac;
-    #ifndef NO_CERTS
-        ssl->suites->sigAlgo = ssl->buffers.keyType;
-    #endif
-    }
-#ifndef WOLFSSL_NO_TLS12
-    else if (IsAtLeastTLSv1_2(ssl)) {
-    #ifdef WOLFSSL_ALLOW_TLS_SHA1
-        ssl->suites->hashAlgo = sha_mac;
-    #else
-        ssl->suites->hashAlgo = sha256_mac;
-    #endif
-    }
-    else {
-        ssl->suites->hashAlgo = sha_mac;
-    }
-#endif
-
-    /* i+1 since peek a byte ahead for type */
-    for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) {
-        byte hashAlgo = 0, sigAlgo = 0;
-
-        DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo);
-    #ifdef HAVE_ED25519
-        if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo)
-            continue;
-
-        if (sigAlgo == ed25519_sa_algo &&
-                                      ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
-            ssl->suites->sigAlgo = sigAlgo;
-            ssl->suites->hashAlgo = sha512_mac;
-            break;
-        }
-    #endif
-        if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo &&
-                                         ssl->suites->sigAlgo == rsa_sa_algo)) {
-            switch (hashAlgo) {
-                case sha_mac:
-            #ifndef NO_SHA256
-                case sha256_mac:
-            #endif
-            #ifdef WOLFSSL_SHA384
-                case sha384_mac:
-            #endif
-            #ifdef WOLFSSL_SHA512
-                case sha512_mac:
-            #endif
-                    if (hashAlgo < ssl->suites->hashAlgo)
-                        continue;
-                    ssl->suites->hashAlgo = hashAlgo;
-                    ssl->suites->sigAlgo = sigAlgo;
-                    break;
-                default:
-                    continue;
-            }
-            break;
-        }
-        else if (ssl->specs.sig_algo == 0) {
-            ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
-        }
-    }
-
-}
-#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-
-    /* Initialisze HandShakeInfo */
-    void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl)
-    {
-        int i;
-
-        info->ssl = ssl;
-        info->cipherName[0] = 0;
-        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
-            info->packetNames[i][0] = 0;
-        info->numberPackets = 0;
-        info->negotiationError = 0;
-    }
-
-    /* Set Final HandShakeInfo parameters */
-    void FinishHandShakeInfo(HandShakeInfo* info)
-    {
-        int i;
-        int sz = GetCipherNamesSize();
-
-        for (i = 0; i < sz; i++)
-            if (info->ssl->options.cipherSuite ==
-                                            (byte)cipher_names[i].cipherSuite) {
-                if (info->ssl->options.cipherSuite0 == ECC_BYTE)
-                    continue;   /* ECC suites at end */
-                XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ);
-                info->cipherName[MAX_CIPHERNAME_SZ] = '\0';
-                break;
-            }
-
-        /* error max and min are negative numbers */
-        if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR)
-            info->negotiationError = info->ssl->error;
-    }
-
-
-    /* Add name to info packet names, increase packet name count */
-    void AddPacketName(WOLFSSL* ssl, const char* name)
-    {
-    #ifdef WOLFSSL_CALLBACKS
-        HandShakeInfo* info = &ssl->handShakeInfo;
-        if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
-            char* packetName = info->packetNames[info->numberPackets];
-            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
-            packetName[MAX_PACKETNAME_SZ] = '\0';
-            info->numberPackets++
-        }
-    #endif
-        (void)ssl;
-        (void)name;
-    }
-
-
-    #ifdef WOLFSSL_CALLBACKS
-    /* Initialisze TimeoutInfo */
-    void InitTimeoutInfo(TimeoutInfo* info)
-    {
-        int i;
-
-        info->timeoutName[0] = 0;
-        info->flags          = 0;
-
-        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
-            info->packets[i].packetName[0]     = 0;
-            info->packets[i].timestamp.tv_sec  = 0;
-            info->packets[i].timestamp.tv_usec = 0;
-            info->packets[i].bufferValue       = 0;
-            info->packets[i].valueSz           = 0;
-        }
-        info->numberPackets        = 0;
-        info->timeoutValue.tv_sec  = 0;
-        info->timeoutValue.tv_usec = 0;
-    }
-
-
-    /* Free TimeoutInfo */
-    void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
-    {
-        int i;
-        (void)heap;
-        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
-            if (info->packets[i].bufferValue) {
-                XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
-                info->packets[i].bufferValue = 0;
-            }
-
-    }
-
-    /* Add packet name to previsouly added packet info */
-    void AddLateName(const char* name, TimeoutInfo* info)
-    {
-        /* make sure we have a valid previous one */
-        if (info->numberPackets > 0 && info->numberPackets <
-                                                        MAX_PACKETS_HANDSHAKE) {
-            char* packetName = info->packets[info->numberPackets-1].packetName;
-            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
-            packetName[MAX_PACKETNAME_SZ] = '\0';
-        }
-    }
-
-    /* Add record header to previsouly added packet info */
-    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
-    {
-        /* make sure we have a valid previous one */
-        if (info->numberPackets > 0 && info->numberPackets <
-                                                        MAX_PACKETS_HANDSHAKE) {
-            if (info->packets[info->numberPackets - 1].bufferValue)
-                XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
-                       RECORD_HEADER_SZ);
-            else
-                XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
-                       RECORD_HEADER_SZ);
-        }
-    }
-
-    #endif /* WOLFSSL_CALLBACKS */
-
-
-    /* Add PacketInfo to TimeoutInfo
-     *
-     * ssl   WOLFSSL structure sending or receiving packet
-     * name  name of packet being sent
-     * type  type of packet being sent
-     * data  data bing sent with packet
-     * sz    size of data buffer
-     * written 1 if this packet is being written to wire, 0 if being read
-     * heap  custom heap to use for mallocs/frees
-     */
-    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
-            const byte* data, int sz, int written, void* heap)
-    {
-    #ifdef WOLFSSL_CALLBACKS
-        TimeoutInfo* info = &ssl->timeoutInfo;
-
-        if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
-            Timeval currTime;
-
-            /* may add name after */
-            if (name) {
-                char* packetName = info->packets[info->numberPackets].packetName;
-                XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
-                packetName[MAX_PACKETNAME_SZ] = '\0';
-            }
-
-            /* add data, put in buffer if bigger than static buffer */
-            info->packets[info->numberPackets].valueSz = sz;
-            if (sz < MAX_VALUE_SZ)
-                XMEMCPY(info->packets[info->numberPackets].value, data, sz);
-            else {
-                info->packets[info->numberPackets].bufferValue =
-                                    (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
-                if (!info->packets[info->numberPackets].bufferValue)
-                    /* let next alloc catch, just don't fill, not fatal here  */
-                    info->packets[info->numberPackets].valueSz = 0;
-                else
-                    XMEMCPY(info->packets[info->numberPackets].bufferValue,
-                           data, sz);
-            }
-            gettimeofday(&currTime, 0);
-            info->packets[info->numberPackets].timestamp.tv_sec  =
-                                                             currTime.tv_sec;
-            info->packets[info->numberPackets].timestamp.tv_usec =
-                                                             currTime.tv_usec;
-            info->numberPackets++;
-        }
-    #endif /* WOLFSSL_CALLBACKS */
-    #ifdef OPENSSL_EXTRA
-        if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) {
-            /* version from hex to dec  16 is 16^1, 256 from 16^2 and
-               4096 from 16^3 */
-            int version = (ssl->version.minor & 0X0F) +
-                          (ssl->version.minor & 0xF0) * 16  +
-                          (ssl->version.major & 0X0F) * 256 +
-                          (ssl->version.major & 0xF0) * 4096;
-
-            ssl->protoMsgCb(written, version, type,
-                         (const void *)(data + RECORD_HEADER_SZ),
-                         (size_t)(sz - RECORD_HEADER_SZ),
-                         ssl, ssl->protoMsgCtx);
-        }
-    #endif /* OPENSSL_EXTRA */
-        (void)written;
-        (void)name;
-        (void)heap;
-        (void)type;
-        (void)ssl;
-    }
-
-#endif /* WOLFSSL_CALLBACKS */
-
-#if !defined(NO_CERTS) && (defined(WOLFSSL_TLS13) || \
-                                                    !defined(NO_WOLFSSL_CLIENT))
-
-/* Decode the private key - RSA, ECC, or Ed25519 - and creates a key object.
- * The signature type is set as well.
- * The maximum length of a signature is returned.
- *
- * ssl     The SSL/TLS object.
- * length  The length of a signature.
- * returns 0 on success, otherwise failure.
- */
-int DecodePrivateKey(WOLFSSL *ssl, word16* length)
-{
-    int      ret = BAD_FUNC_ARG;
-    int      keySz;
-    word32   idx;
-
-    /* make sure private key exists */
-    if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) {
-        WOLFSSL_MSG("Private key missing!");
-        ERROR_OUT(NO_PRIVATE_KEY, exit_dpk);
-    }
-
-#ifndef NO_RSA
-    ssl->hsType = DYNAMIC_TYPE_RSA;
-    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-    if (ret != 0) {
-        goto exit_dpk;
-    }
-
-    WOLFSSL_MSG("Trying RSA private key");
-
-    /* Set start of data to beginning of buffer. */
-    idx = 0;
-    /* Decode the key assuming it is an RSA private key. */
-    ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
-                (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
-    if (ret == 0) {
-        WOLFSSL_MSG("Using RSA private key");
-
-        /* It worked so check it meets minimum key size requirements. */
-        keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
-        if (keySz < 0) { /* check if keySz has error case */
-            ERROR_OUT(keySz, exit_dpk);
-        }
-
-        if (keySz < ssl->options.minRsaKeySz) {
-            WOLFSSL_MSG("RSA key size too small");
-            ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
-        }
-
-        /* Return the maximum signature length. */
-        *length = (word16)keySz;
-
-        goto exit_dpk;
-    }
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-#ifndef NO_RSA
-    FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
-#endif /* !NO_RSA */
-
-    ssl->hsType = DYNAMIC_TYPE_ECC;
-    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-    if (ret != 0) {
-        goto exit_dpk;
-    }
-
-#ifndef NO_RSA
-    WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
-#else
-    WOLFSSL_MSG("Trying ECC private key");
-#endif
-
-    /* Set start of data to beginning of buffer. */
-    idx = 0;
-    /* Decode the key assuming it is an ECC private key. */
-    ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
-                                 (ecc_key*)ssl->hsKey,
-                                 ssl->buffers.key->length);
-    if (ret == 0) {
-        WOLFSSL_MSG("Using ECC private key");
-
-        /* Check it meets the minimum ECC key size requirements. */
-        keySz = wc_ecc_size((ecc_key*)ssl->hsKey);
-        if (keySz < ssl->options.minEccKeySz) {
-            WOLFSSL_MSG("ECC key size too small");
-            ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
-        }
-
-        /* Return the maximum signature length. */
-        *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
-
-        goto exit_dpk;
-    }
-#endif
-#ifdef HAVE_ED25519
-    #if !defined(NO_RSA) || defined(HAVE_ECC)
-        FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
-    #endif
-
-    ssl->hsType = DYNAMIC_TYPE_ED25519;
-    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-    if (ret != 0) {
-        goto exit_dpk;
-    }
-
-    #ifdef HAVE_ECC
-        WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work");
-    #elif !defined(NO_RSA)
-        WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work");
-    #else
-        WOLFSSL_MSG("Trying ED25519 private key");
-    #endif
-
-    /* Set start of data to beginning of buffer. */
-    idx = 0;
-    /* Decode the key assuming it is an ED25519 private key. */
-    ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
-                                     (ed25519_key*)ssl->hsKey,
-                                     ssl->buffers.key->length);
-    if (ret == 0) {
-        WOLFSSL_MSG("Using ED25519 private key");
-
-        /* Check it meets the minimum ECC key size requirements. */
-        if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
-            WOLFSSL_MSG("ED25519 key size too small");
-            ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
-        }
-
-        /* Return the maximum signature length. */
-        *length = ED25519_SIG_SIZE;
-
-        goto exit_dpk;
-    }
-#endif /* HAVE_ED25519 */
-
-    (void)idx;
-    (void)keySz;
-    (void)length;
-exit_dpk:
-    return ret;
-}
-
-#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
-
-/* client only parts */
-#ifndef NO_WOLFSSL_CLIENT
-
-#ifndef WOLFSSL_NO_TLS12
-
-    /* handle generation of client_hello (1) */
-    int SendClientHello(WOLFSSL* ssl)
-    {
-        byte              *output;
-        word32             length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-        int                sendSz;
-        int                idSz = ssl->options.resuming
-                                ? ssl->session.sessionIDSz
-                                : 0;
-        int                ret;
-        word16             extSz = 0;
-
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(ssl->version))
-            return SendTls13ClientHello(ssl);
-#endif
-
-        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
-        WOLFSSL_ENTER("SendClientHello");
-
-        if (ssl->suites == NULL) {
-            WOLFSSL_MSG("Bad suites pointer in SendClientHello");
-            return SUITES_ERROR;
-        }
-
-#ifdef HAVE_SESSION_TICKET
-        if (ssl->options.resuming && ssl->session.ticketLen > 0) {
-            SessionTicket* ticket;
-
-            ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket,
-                                             ssl->session.ticketLen, ssl->heap);
-            if (ticket == NULL) return MEMORY_E;
-
-            ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap);
-            if (ret != WOLFSSL_SUCCESS) return ret;
-
-            idSz = 0;
-        }
-#endif
-        length = VERSION_SZ + RAN_LEN
-               + idSz + ENUM_LEN
-               + ssl->suites->suiteSz + SUITE_LEN
-               + COMP_LEN + ENUM_LEN;
-
-#ifdef HAVE_TLS_EXTENSIONS
-        /* auto populate extensions supported unless user defined */
-        if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
-            return ret;
-    #ifdef HAVE_QSH
-        if (QSH_Init(ssl) != 0)
-            return MEMORY_E;
-    #endif
-        extSz = 0;
-        ret = TLSX_GetRequestSize(ssl, client_hello, &extSz);
-        if (ret != 0)
-            return ret;
-        length += extSz;
-#else
-        if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
-            extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
-                   + ssl->suites->hashSigAlgoSz;
-#ifdef HAVE_EXTENDED_MASTER
-        if (ssl->options.haveEMS)
-            extSz += HELLO_EXT_SZ;
-#endif
-        if (extSz != 0)
-            length += extSz + HELLO_EXT_SZ_SZ;
-#endif
-        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
-#ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            length += ENUM_LEN;   /* cookie */
-            if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz;
-            sendSz  = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
-            idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
-        }
-#endif
-
-        if (IsEncryptionOn(ssl, 1))
-            sendSz += MAX_MSG_EXTRA;
-
-        /* check for available size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        AddHeaders(output, length, client_hello, ssl);
-
-        /* client hello, first version */
-        output[idx++] = ssl->version.major;
-        output[idx++] = ssl->version.minor;
-        ssl->chVersion = ssl->version;  /* store in case changed */
-
-        /* then random */
-        if (ssl->options.connectState == CONNECT_BEGIN) {
-            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
-            if (ret != 0)
-                return ret;
-
-            /* store random */
-            XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
-        } else {
-#ifdef WOLFSSL_DTLS
-            /* send same random on hello again */
-            XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
-#endif
-        }
-        idx += RAN_LEN;
-
-        /* then session id */
-        output[idx++] = (byte)idSz;
-        if (idSz) {
-            XMEMCPY(output + idx, ssl->session.sessionID,
-                                                      ssl->session.sessionIDSz);
-            idx += ssl->session.sessionIDSz;
-        }
-
-        /* then DTLS cookie */
-#ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            byte cookieSz = ssl->arrays->cookieSz;
-
-            output[idx++] = cookieSz;
-            if (cookieSz) {
-                XMEMCPY(&output[idx], ssl->arrays->cookie, cookieSz);
-                idx += cookieSz;
-            }
-        }
-#endif
-        /* then cipher suites */
-        c16toa(ssl->suites->suiteSz, output + idx);
-        idx += OPAQUE16_LEN;
-        XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
-        idx += ssl->suites->suiteSz;
-
-        /* last, compression */
-        output[idx++] = COMP_LEN;
-        if (ssl->options.usingCompression)
-            output[idx++] = ZLIB_COMPRESSION;
-        else
-            output[idx++] = NO_COMPRESSION;
-
-#ifdef HAVE_TLS_EXTENSIONS
-        extSz = 0;
-        ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz);
-        if (ret != 0)
-            return ret;
-        idx += extSz;
-
-        (void)idx; /* suppress analyzer warning, keep idx current */
-#else
-        if (extSz != 0) {
-            c16toa(extSz, output + idx);
-            idx += HELLO_EXT_SZ_SZ;
-
-            if (IsAtLeastTLSv1_2(ssl)) {
-                if (ssl->suites->hashSigAlgoSz) {
-                    int i;
-                    /* extension type */
-                    c16toa(HELLO_EXT_SIG_ALGO, output + idx);
-                    idx += HELLO_EXT_TYPE_SZ;
-                    /* extension data length */
-                    c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz,
-                           output + idx);
-                    idx += HELLO_EXT_SZ_SZ;
-                    /* sig algos length */
-                    c16toa(ssl->suites->hashSigAlgoSz, output + idx);
-                    idx += HELLO_EXT_SIGALGO_SZ;
-                    for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
-                        output[idx] = ssl->suites->hashSigAlgo[i];
-                    }
-                }
-            }
-#ifdef HAVE_EXTENDED_MASTER
-            if (ssl->options.haveEMS) {
-                c16toa(HELLO_EXT_EXTMS, output + idx);
-                idx += HELLO_EXT_TYPE_SZ;
-                c16toa(0, output + idx);
-                idx += HELLO_EXT_SZ_SZ;
-            }
-#endif
-        }
-#endif
-
-        if (IsEncryptionOn(ssl, 1)) {
-            byte* input;
-            int   inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
-
-            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-            if (input == NULL)
-                return MEMORY_E;
-
-            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
-            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
-                                  handshake, 1, 0, 0);
-            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
-            if (sendSz < 0)
-                return sendSz;
-        } else {
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-            ret = HashOutput(ssl, output, sendSz, 0);
-            if (ret != 0)
-                return ret;
-        }
-
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                    return ret;
-            }
-        #endif
-
-        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-#ifdef OPENSSL_EXTRA
-        ssl->cbmode = SSL_CB_MODE_WRITE;
-		if (ssl->CBIS != NULL)
-			ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
-#endif
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
-                          WRITE_PROTO, ssl->heap);
-#endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-
-        ret = SendBuffered(ssl);
-
-        WOLFSSL_LEAVE("SendClientHello", ret);
-        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
-
-        return ret;
-    }
-
-
-    /* handle processing of DTLS hello_verify_request (3) */
-    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
-                                    word32* inOutIdx, word32 size)
-    {
-        ProtocolVersion pv;
-        byte            cookieSz;
-        word32          begin = *inOutIdx;
-
-#ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest");
-        if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
-#endif
-
-#ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            DtlsMsgPoolReset(ssl);
-        }
-#endif
-
-        if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size)
-            return BUFFER_ERROR;
-
-        XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN);
-        *inOutIdx += OPAQUE16_LEN;
-
-        if (pv.major != DTLS_MAJOR ||
-                         (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR))
-            return VERSION_ERROR;
-
-        cookieSz = input[(*inOutIdx)++];
-
-        if (cookieSz) {
-            if ((*inOutIdx - begin) + cookieSz > size)
-                return BUFFER_ERROR;
-
-#ifdef WOLFSSL_DTLS
-            if (cookieSz <= MAX_COOKIE_LEN) {
-                XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz);
-                ssl->arrays->cookieSz = cookieSz;
-            }
-#endif
-            *inOutIdx += cookieSz;
-        }
-
-        ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
-        return 0;
-    }
-
-
-    static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
-    {
-        int ret = 0;
-
-#ifdef HAVE_SECRET_CALLBACK
-        /* If a session secret callback exists, we are using that
-         * key instead of the saved session key. */
-        ret = ret || (ssl->sessionSecretCb != NULL);
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-        /* server may send blank ticket which may not be expected to indicate
-         * existing one ok but will also be sending a new one */
-        ret = ret || (ssl->session.ticketLen > 0);
-#endif
-
-        ret = ret ||
-              (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
-                                          ssl->session.sessionID, ID_LEN) == 0);
-
-        return ret;
-    }
-
-    /* Check the version in the received message is valid and set protocol
-     * version to use.
-     *
-     * ssl  The SSL/TLS object.
-     * pv   The protocol version from the packet.
-     * returns 0 on success, otherwise failure.
-     */
-    int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
-    {
-#ifdef WOLFSSL_TLS13
-    #ifndef WOLFSSL_TLS13_FINAL
-        /* TODO: [TLS13] Remove this.
-         * Translate the draft TLS v1.3 version to final version.
-         */
-        if (pv.major == TLS_DRAFT_MAJOR) {
-            pv.major = SSLv3_MAJOR;
-            pv.minor = TLSv1_3_MINOR;
-        }
-    #endif
-#endif
-
-        #ifdef OPENSSL_EXTRA
-        if (ssl->CBIS != NULL) {
-            ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS);
-        }
-        #endif
-
-        if (pv.minor > ssl->version.minor) {
-            WOLFSSL_MSG("Server using higher version, fatal error");
-            return VERSION_ERROR;
-        }
-        if (pv.minor < ssl->version.minor) {
-            WOLFSSL_MSG("server using lower version");
-
-            /* Check for downgrade attack. */
-            if (!ssl->options.downgrade) {
-                WOLFSSL_MSG("\tno downgrade allowed, fatal error");
-                return VERSION_ERROR;
-            }
-            if (pv.minor < ssl->options.minDowngrade) {
-                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
-                return VERSION_ERROR;
-            }
-
-            #ifdef HAVE_SECURE_RENEGOTIATION
-                if (ssl->secure_renegotiation &&
-                                         ssl->secure_renegotiation->enabled &&
-                                         ssl->options.handShakeDone) {
-                    WOLFSSL_MSG("Server changed version during scr");
-                    return VERSION_ERROR;
-                }
-            #endif
-
-            /* Checks made - OK to downgrade. */
-            if (pv.minor == SSLv3_MINOR) {
-                /* turn off tls */
-                WOLFSSL_MSG("\tdowngrading to SSLv3");
-                ssl->options.tls    = 0;
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = SSLv3_MINOR;
-            }
-            else if (pv.minor == TLSv1_MINOR) {
-                /* turn off tls 1.1+ */
-                WOLFSSL_MSG("\tdowngrading to TLSv1");
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = TLSv1_MINOR;
-            }
-            else if (pv.minor == TLSv1_1_MINOR) {
-                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
-                ssl->version.minor  = TLSv1_1_MINOR;
-            }
-            else if (pv.minor == TLSv1_2_MINOR) {
-                WOLFSSL_MSG("    downgrading to TLSv1.2");
-                ssl->version.minor  = TLSv1_2_MINOR;
-            }
-        }
-
-#ifdef OPENSSL_EXTRA
-        /* check if option is set to not allow the current version
-         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
-        if (!ssl->options.dtls && ssl->options.downgrade &&
-                ssl->options.mask > 0) {
-            if (ssl->version.minor == TLSv1_2_MINOR &&
-             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
-                ssl->version.minor = TLSv1_1_MINOR;
-            }
-            if (ssl->version.minor == TLSv1_1_MINOR &&
-             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor = TLSv1_MINOR;
-            }
-            if (ssl->version.minor == TLSv1_MINOR &&
-                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
-                ssl->options.tls    = 0;
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor = SSLv3_MINOR;
-            }
-            if (ssl->version.minor == SSLv3_MINOR &&
-                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
-                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
-                return VERSION_ERROR;
-            }
-
-            if (ssl->version.minor < ssl->options.minDowngrade) {
-                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
-                return VERSION_ERROR;
-            }
-        }
-#endif
-
-        return 0;
-    }
-
-    /* handle processing of server_hello (2) */
-    int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                      word32 helloSz)
-    {
-        byte            cs0;   /* cipher suite bytes 0, 1 */
-        byte            cs1;
-        ProtocolVersion pv;
-        byte            compression;
-        word32          i = *inOutIdx;
-        word32          begin = i;
-        int             ret;
-
-        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
-        WOLFSSL_ENTER("DoServerHello");
-
-#ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
-        if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
-#endif
-
-        /* protocol version, random and session id length check */
-        if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
-            return BUFFER_ERROR;
-
-        /* protocol version */
-        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-        i += OPAQUE16_LEN;
-
-        ret = CheckVersion(ssl, pv);
-        if (ret != 0)
-            return ret;
-
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(pv)) {
-            byte type = server_hello;
-            return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
-        }
-#endif
-
-        /* random */
-        XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
-        i += RAN_LEN;
-
-        /* session id */
-        ssl->arrays->sessionIDSz = input[i++];
-
-        if (ssl->arrays->sessionIDSz > ID_LEN) {
-            WOLFSSL_MSG("Invalid session ID size");
-            ssl->arrays->sessionIDSz = 0;
-            return BUFFER_ERROR;
-        }
-        else if (ssl->arrays->sessionIDSz) {
-            if ((i - begin) + ssl->arrays->sessionIDSz > helloSz)
-                return BUFFER_ERROR;
-
-            XMEMCPY(ssl->arrays->sessionID, input + i,
-                                                      ssl->arrays->sessionIDSz);
-            i += ssl->arrays->sessionIDSz;
-            ssl->options.haveSessionId = 1;
-        }
-
-
-        /* suite and compression */
-        if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
-            return BUFFER_ERROR;
-
-        cs0 = input[i++];
-        cs1 = input[i++];
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-        if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
-                                         ssl->options.handShakeDone) {
-            if (ssl->options.cipherSuite0 != cs0 ||
-                ssl->options.cipherSuite  != cs1) {
-                WOLFSSL_MSG("Server changed cipher suite during scr");
-                return MATCH_SUITE_ERROR;
-            }
-        }
-#endif
-
-        ssl->options.cipherSuite0 = cs0;
-        ssl->options.cipherSuite  = cs1;
-        compression = input[i++];
-
-        if (compression != NO_COMPRESSION && !ssl->options.usingCompression) {
-            WOLFSSL_MSG("Server forcing compression w/o support");
-            return COMPRESSION_ERROR;
-        }
-
-        if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
-            WOLFSSL_MSG("Server refused compression, turning off");
-            ssl->options.usingCompression = 0;  /* turn off if server refused */
-        }
-
-        *inOutIdx = i;
-
-#ifdef HAVE_TLS_EXTENSIONS
-        if ( (i - begin) < helloSz) {
-            if (TLSX_SupportExtensions(ssl)) {
-                word16 totalExtSz;
-
-                if ((i - begin) + OPAQUE16_LEN > helloSz)
-                    return BUFFER_ERROR;
-
-                ato16(&input[i], &totalExtSz);
-                i += OPAQUE16_LEN;
-
-                if ((i - begin) + totalExtSz > helloSz)
-                    return BUFFER_ERROR;
-
-                if ((ret = TLSX_Parse(ssl, (byte *) input + i,
-                                                          totalExtSz, 0, NULL)))
-                    return ret;
-
-                i += totalExtSz;
-                *inOutIdx = i;
-            }
-            else
-                *inOutIdx = begin + helloSz; /* skip extensions */
-        }
-        else
-            ssl->options.haveEMS = 0; /* If no extensions, no EMS */
-#else
-        {
-            int allowExt = 0;
-            byte pendingEMS = 0;
-
-            if ( (i - begin) < helloSz) {
-                if (ssl->version.major == SSLv3_MAJOR &&
-                    ssl->version.minor >= TLSv1_MINOR) {
-
-                    allowExt = 1;
-                }
-#ifdef WOLFSSL_DTLS
-                if (ssl->version.major == DTLS_MAJOR)
-                    allowExt = 1;
-#endif
-
-                if (allowExt) {
-                    word16 totalExtSz;
-
-                    if ((i - begin) + OPAQUE16_LEN > helloSz)
-                        return BUFFER_ERROR;
-
-                    ato16(&input[i], &totalExtSz);
-                    i += OPAQUE16_LEN;
-
-                    if ((i - begin) + totalExtSz > helloSz)
-                        return BUFFER_ERROR;
-
-                    while (totalExtSz) {
-                        word16 extId, extSz;
-
-                        if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
-                            return BUFFER_ERROR;
-
-                        ato16(&input[i], &extId);
-                        i += OPAQUE16_LEN;
-                        ato16(&input[i], &extSz);
-                        i += OPAQUE16_LEN;
-
-                        if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
-                            return BUFFER_ERROR;
-
-                        if (extId == HELLO_EXT_EXTMS)
-                            pendingEMS = 1;
-                        else
-                            i += extSz;
-
-                        totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
-                    }
-
-                    *inOutIdx = i;
-                }
-                else
-                    *inOutIdx = begin + helloSz; /* skip extensions */
-            }
-
-            if (!pendingEMS && ssl->options.haveEMS)
-                ssl->options.haveEMS = 0;
-        }
-#endif
-
-        ssl->options.serverState = SERVER_HELLO_COMPLETE;
-
-        if (IsEncryptionOn(ssl, 0)) {
-            *inOutIdx += ssl->keys.padSz;
-        }
-
-#ifdef HAVE_SECRET_CALLBACK
-        if (ssl->sessionSecretCb != NULL) {
-            int secretSz = SECRET_LEN;
-            ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
-                                              &secretSz, ssl->sessionSecretCtx);
-            if (ret != 0 || secretSz != SECRET_LEN)
-                return SESSION_SECRET_CB_E;
-        }
-#endif /* HAVE_SECRET_CALLBACK */
-
-        ret = CompleteServerHello(ssl);
-
-        WOLFSSL_LEAVE("DoServerHello", ret);
-        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
-
-        return ret;
-    }
-
-    int CompleteServerHello(WOLFSSL* ssl)
-    {
-        int ret;
-
-        if (!ssl->options.resuming) {
-            byte* down = ssl->arrays->serverRandom + RAN_LEN -
-                                                         TLS13_DOWNGRADE_SZ - 1;
-            byte  vers = ssl->arrays->serverRandom[RAN_LEN - 1];
-    #ifdef WOLFSSL_TLS13
-            if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
-                /* TLS v1.3 capable client not allowed to downgrade when
-                 * connecting to TLS v1.3 capable server unless cipher suite
-                 * demands it.
-                 */
-                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
-                                                     (vers == 0 || vers == 1)) {
-                    SendAlert(ssl, alert_fatal, illegal_parameter);
-                    return VERSION_ERROR;
-                }
-            }
-            else
-    #endif
-            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
-                             ssl->ctx->method->version.minor == TLSv1_2_MINOR) {
-                /* TLS v1.2 capable client not allowed to downgrade when
-                 * connecting to TLS v1.2 capable server.
-                 */
-                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
-                                                                    vers == 0) {
-                    SendAlert(ssl, alert_fatal, illegal_parameter);
-                    return VERSION_ERROR;
-                }
-            }
-        }
-        else {
-            if (DSH_CheckSessionId(ssl)) {
-                if (SetCipherSpecs(ssl) == 0) {
-
-                    XMEMCPY(ssl->arrays->masterSecret,
-                            ssl->session.masterSecret, SECRET_LEN);
-            #ifdef NO_OLD_TLS
-                    ret = DeriveTlsKeys(ssl);
-            #else
-                    ret = -1; /* default value */
-                #ifndef NO_TLS
-                    if (ssl->options.tls)
-                        ret = DeriveTlsKeys(ssl);
-                #endif
-                    if (!ssl->options.tls)
-                        ret = DeriveKeys(ssl);
-            #endif /* NO_OLD_TLS */
-                    ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
-
-                    return ret;
-                }
-                else {
-                    WOLFSSL_MSG("Unsupported cipher suite, DoServerHello");
-                    return UNSUPPORTED_SUITE;
-                }
-            }
-            else {
-                WOLFSSL_MSG("Server denied resumption attempt");
-                ssl->options.resuming = 0; /* server denied resumption try */
-            }
-        }
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            DtlsMsgPoolReset(ssl);
-        }
-    #endif
-
-        return SetCipherSpecs(ssl);
-    }
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-
-    /* Make sure client setup is valid for this suite, true on success */
-    int VerifyClientSuite(WOLFSSL* ssl)
-    {
-        int  havePSK = 0;
-        byte first   = ssl->options.cipherSuite0;
-        byte second  = ssl->options.cipherSuite;
-
-        WOLFSSL_ENTER("VerifyClientSuite");
-
-        #ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-        #endif
-
-        if (CipherRequires(first, second, REQUIRES_PSK)) {
-            WOLFSSL_MSG("Requires PSK");
-            if (havePSK == 0) {
-                WOLFSSL_MSG("Don't have PSK");
-                return 0;
-            }
-        }
-
-        return 1;  /* success */
-    }
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifndef NO_CERTS
-    /* handle processing of certificate_request (13) */
-    static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*
-                                    inOutIdx, word32 size)
-    {
-        word16 len;
-        word32 begin = *inOutIdx;
-
-        WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
-        WOLFSSL_ENTER("DoCertificateRequest");
-
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "CertificateRequest");
-            if (ssl->toInfoOn)
-                AddLateName("CertificateRequest", &ssl->timeoutInfo);
-        #endif
-
-        if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
-            return BUFFER_ERROR;
-
-        len = input[(*inOutIdx)++];
-
-        if ((*inOutIdx - begin) + len > size)
-            return BUFFER_ERROR;
-
-        /* types, read in here */
-        *inOutIdx += len;
-
-        /* signature and hash signature algorithm */
-        if (IsAtLeastTLSv1_2(ssl)) {
-            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-                return BUFFER_ERROR;
-
-            ato16(input + *inOutIdx, &len);
-            *inOutIdx += OPAQUE16_LEN;
-
-            if ((*inOutIdx - begin) + len > size)
-                return BUFFER_ERROR;
-
-            PickHashSigAlgo(ssl, input + *inOutIdx, len);
-            *inOutIdx += len;
-    #ifdef WC_RSA_PSS
-            ssl->pssAlgo = 0;
-            if (ssl->suites->sigAlgo == rsa_pss_sa_algo)
-                ssl->pssAlgo |= 1 << ssl->suites->hashAlgo;
-    #endif
-        }
-
-        /* authorities */
-        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-            return BUFFER_ERROR;
-
-        ato16(input + *inOutIdx, &len);
-        *inOutIdx += OPAQUE16_LEN;
-
-        if ((*inOutIdx - begin) + len > size)
-            return BUFFER_ERROR;
-
-        while (len) {
-            word16 dnSz;
-
-            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-                return BUFFER_ERROR;
-
-            ato16(input + *inOutIdx, &dnSz);
-            *inOutIdx += OPAQUE16_LEN;
-
-            if ((*inOutIdx - begin) + dnSz > size)
-                return BUFFER_ERROR;
-
-            *inOutIdx += dnSz;
-            len -= OPAQUE16_LEN + dnSz;
-        }
-
-        /* don't send client cert or cert verify if user hasn't provided
-           cert and private key */
-        if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) {
-        #ifdef HAVE_PK_CALLBACKS
-            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
-                WOLFSSL_MSG("Using PK for client private key");
-                ssl->options.sendVerify = SEND_CERT;
-            }
-        #endif
-            if (ssl->buffers.key && ssl->buffers.key->buffer) {
-                ssl->options.sendVerify = SEND_CERT;
-            }
-        }
-	#ifdef OPENSSL_EXTRA
-		else
-	#else
-        else if (IsTLS(ssl))
-	#endif
-        {
-            ssl->options.sendVerify = SEND_BLANK_CERT;
-        }
-
-        if (IsEncryptionOn(ssl, 0))
-            *inOutIdx += ssl->keys.padSz;
-
-        WOLFSSL_LEAVE("DoCertificateRequest", 0);
-        WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
-
-        return 0;
-    }
-#endif /* !NO_CERTS */
-
-
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-
-    static int CheckCurveId(int tlsCurveId)
-    {
-        int ret = ECC_CURVE_ERROR;
-
-        switch (tlsCurveId) {
-    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_SECPR2
-            case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID;
-        #endif /* HAVE_ECC_SECPR2 */
-        #ifdef HAVE_ECC_KOBLITZ
-            case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
-        #ifdef HAVE_CURVE25519
-            case WOLFSSL_ECC_X25519: return ECC_X25519_OID;
-        #endif
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID;
-        #endif /* HAVE_ECC_KOBLITZ */
-        #ifdef HAVE_ECC_BRAINPOOL
-            case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_BRAINPOOL
-            case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
-        #ifdef HAVE_ECC_BRAINPOOL
-            case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID;
-        #endif /* !NO_ECC_SECP */
-    #endif
-        }
-
-        return ret;
-    }
-
-#endif /* HAVE_ECC */
-
-
-/* Persistable DoServerKeyExchange arguments */
-typedef struct DskeArgs {
-    byte*  output; /* not allocated */
-#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-    byte*  verifySig;
-#endif
-    word32 idx;
-    word32 begin;
-#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-    word16 verifySigSz;
-#endif
-    word16 sigSz;
-    byte   sigAlgo;
-    byte   hashAlgo;
-} DskeArgs;
-
-static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs)
-{
-    DskeArgs* args = (DskeArgs*)pArgs;
-
-    (void)ssl;
-    (void)args;
-
-#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-    if (args->verifySig) {
-        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        args->verifySig = NULL;
-    }
-#endif
-}
-
-/* handle processing of server_key_exchange (12) */
-static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
-                               word32* inOutIdx, word32 size)
-{
-    int ret = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    DskeArgs* args = (DskeArgs*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#else
-    DskeArgs  args[1];
-#endif
-
-    (void)input;
-    (void)size;
-
-    WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
-    WOLFSSL_ENTER("DoServerKeyExchange");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_dske;
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(DskeArgs));
-        args->idx = *inOutIdx;
-        args->begin = *inOutIdx;
-        args->sigAlgo = ssl->specs.sig_algo;
-        args->hashAlgo = sha_mac;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeDskeArgs;
-    #endif
-    }
-
-    switch(ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "ServerKeyExchange");
-            if (ssl->toInfoOn)
-                AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
-        #endif
-
-            switch(ssl->specs.kea)
-            {
-            #ifndef NO_PSK
-                case psk_kea:
-                {
-                    int srvHintLen;
-                    word16 length;
-
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    /* get PSK server hint from the wire */
-                    srvHintLen = min(length, MAX_PSK_ID_LEN);
-                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
-                                                                    srvHintLen);
-                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
-                    args->idx += length;
-                    break;
-                }
-            #endif /* !NO_PSK */
-            #ifndef NO_DH
-                case diffie_hellman_kea:
-                {
-                    word16 length;
-
-                    /* p */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    if (length < ssl->options.minDhKeySz) {
-                        WOLFSSL_MSG("Server using a DH key that is too small");
-                        SendAlert(ssl, alert_fatal, handshake_failure);
-                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
-                    }
-                    if (length > ssl->options.maxDhKeySz) {
-                        WOLFSSL_MSG("Server using a DH key that is too big");
-                        SendAlert(ssl, alert_fatal, handshake_failure);
-                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_P.buffer =
-                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_P.buffer) {
-                        ssl->buffers.serverDH_P.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-
-                    ssl->options.dhKeySz = length;
-
-                    /* g */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_G.buffer =
-                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_G.buffer) {
-                        ssl->buffers.serverDH_G.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-
-                    ssl->buffers.weOwnDH = 1;
-
-                    /* pub */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_Pub.buffer =
-                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_Pub.buffer) {
-                        ssl->buffers.serverDH_Pub.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-                    break;
-                }
-            #endif /* !NO_DH */
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                case ecc_diffie_hellman_kea:
-                {
-                    byte b;
-                #ifdef HAVE_ECC
-                    int curveId;
-                #endif
-                    int curveOid;
-                    word16 length;
-
-                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
-                                                        OPAQUE8_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    b = input[args->idx++];
-                    if (b != named_curve) {
-                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
-                    }
-
-                    args->idx += 1;   /* curve type, eat leading 0 */
-                    b = input[args->idx++];
-                    if ((curveOid = CheckCurveId(b)) < 0) {
-                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
-                    }
-                    ssl->ecdhCurveOID = curveOid;
-
-                    length = input[args->idx++];
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                        if (ssl->peerX25519Key == NULL) {
-                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                           (void**)&ssl->peerX25519Key);
-                            if (ret != 0) {
-                                goto exit_dske;
-                            }
-                        } else if (ssl->peerX25519KeyPresent) {
-                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                           ssl->peerX25519Key);
-                            ssl->peerX25519KeyPresent = 0;
-                            if (ret != 0) {
-                                goto exit_dske;
-                            }
-                        }
-
-                        if (wc_curve25519_import_public_ex(input + args->idx,
-                                length, ssl->peerX25519Key,
-                                EC25519_LITTLE_ENDIAN) != 0) {
-                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
-                        }
-
-                        args->idx += length;
-                        ssl->peerX25519KeyPresent = 1;
-                        break;
-                    }
-                #endif
-                #ifdef HAVE_ECC
-                    if (ssl->peerEccKey == NULL) {
-                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                       (void**)&ssl->peerEccKey);
-                        if (ret != 0) {
-                            goto exit_dske;
-                        }
-                    } else if (ssl->peerEccKeyPresent) {
-                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
-                        ssl->peerEccKeyPresent = 0;
-                        if (ret != 0) {
-                            goto exit_dske;
-                        }
-                    }
-
-                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
-                    if (wc_ecc_import_x963_ex(input + args->idx, length,
-                                        ssl->peerEccKey, curveId) != 0) {
-                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
-                    }
-
-                    args->idx += length;
-                    ssl->peerEccKeyPresent = 1;
-                    break;
-                #endif
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-            #if !defined(NO_DH) && !defined(NO_PSK)
-                case dhe_psk_kea:
-                {
-                    int srvHintLen;
-                    word16 length;
-
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    /* get PSK server hint from the wire */
-                    srvHintLen = min(length, MAX_PSK_ID_LEN);
-                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
-                                                                srvHintLen);
-                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
-                    args->idx += length;
-
-                    /* p */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    if (length < ssl->options.minDhKeySz) {
-                        WOLFSSL_MSG("Server using a DH key that is too small");
-                        SendAlert(ssl, alert_fatal, handshake_failure);
-                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
-                    }
-                    if (length > ssl->options.maxDhKeySz) {
-                        WOLFSSL_MSG("Server using a DH key that is too big");
-                        SendAlert(ssl, alert_fatal, handshake_failure);
-                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length,
-                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_P.buffer) {
-                        ssl->buffers.serverDH_P.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-
-                    ssl->options.dhKeySz = length;
-
-                    /* g */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length,
-                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_G.buffer) {
-                        ssl->buffers.serverDH_G.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-
-                    ssl->buffers.weOwnDH = 1;
-
-                    /* pub */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length,
-                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    if (ssl->buffers.serverDH_Pub.buffer) {
-                        ssl->buffers.serverDH_Pub.length = length;
-                    }
-                    else {
-                        ERROR_OUT(MEMORY_ERROR, exit_dske);
-                    }
-
-                    XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
-                                                                        length);
-                    args->idx += length;
-                    break;
-                }
-            #endif /* !NO_DH || !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                case ecdhe_psk_kea:
-                {
-                    byte b;
-                    int curveOid, curveId;
-                    int srvHintLen;
-                    word16 length;
-
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &length);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    /* get PSK server hint from the wire */
-                    srvHintLen = min(length, MAX_PSK_ID_LEN);
-                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
-                                                                    srvHintLen);
-                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
-
-                    args->idx += length;
-
-                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
-                        OPAQUE8_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    /* Check curve name and ID */
-                    b = input[args->idx++];
-                    if (b != named_curve) {
-                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
-                    }
-
-                    args->idx += 1;   /* curve type, eat leading 0 */
-                    b = input[args->idx++];
-                    if ((curveOid = CheckCurveId(b)) < 0) {
-                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
-                    }
-
-                    length = input[args->idx++];
-                    if ((args->idx - args->begin) + length > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                        if (ssl->peerX25519Key == NULL) {
-                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                           (void**)&ssl->peerX25519Key);
-                            if (ret != 0) {
-                                goto exit_dske;
-                            }
-                        } else if (ssl->peerEccKeyPresent) {
-                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                           ssl->peerX25519Key);
-                            ssl->peerX25519KeyPresent = 0;
-                            if (ret != 0) {
-                                goto exit_dske;
-                            }
-                        }
-
-                        if (wc_curve25519_import_public_ex(input + args->idx,
-                                length, ssl->peerX25519Key,
-                                EC25519_LITTLE_ENDIAN) != 0) {
-                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
-                        }
-
-                        args->idx += length;
-                        ssl->peerX25519KeyPresent = 1;
-                        break;
-                    }
-                #endif
-
-                    if (ssl->peerEccKey == NULL) {
-                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                 (void**)&ssl->peerEccKey);
-                        if (ret != 0) {
-                            goto exit_dske;
-                        }
-                    } else if (ssl->peerEccKeyPresent) {
-                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
-                        ssl->peerEccKeyPresent = 0;
-                        if (ret != 0) {
-                            goto exit_dske;
-                        }
-                    }
-
-                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
-                    if (wc_ecc_import_x963_ex(input + args->idx, length,
-                        ssl->peerEccKey, curveId) != 0) {
-                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
-                    }
-
-                    args->idx += length;
-                    ssl->peerEccKeyPresent = 1;
-                    break;
-                }
-            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_dske;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            switch(ssl->specs.kea)
-            {
-                case psk_kea:
-                case dhe_psk_kea:
-                case ecdhe_psk_kea:
-                {
-                    /* Nothing to do in this sub-state */
-                    break;
-                }
-
-                case diffie_hellman_kea:
-                case ecc_diffie_hellman_kea:
-                {
-            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
-                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
-            #else
-                    enum wc_HashType hashType;
-                    word16  verifySz;
-
-                    if (ssl->options.usingAnon_cipher) {
-                        break;
-                    }
-
-                    verifySz = (word16)(args->idx - args->begin);
-                    if (verifySz > MAX_DH_SZ) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    if (IsAtLeastTLSv1_2(ssl)) {
-                        if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN >
-                                                                        size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dske);
-                        }
-
-                        DecodeSigAlg(&input[args->idx], &args->hashAlgo,
-                                     &args->sigAlgo);
-                        args->idx += 2;
-                        hashType = HashAlgoToType(args->hashAlgo);
-                        if (hashType == WC_HASH_TYPE_NONE) {
-                            ERROR_OUT(ALGO_ID_E, exit_dske);
-                        }
-                    } else {
-                        /* only using sha and md5 for rsa */
-                        #ifndef NO_OLD_TLS
-                            hashType = WC_HASH_TYPE_SHA;
-                            if (args->sigAlgo == rsa_sa_algo) {
-                                hashType = WC_HASH_TYPE_MD5_SHA;
-                            }
-                        #else
-                            ERROR_OUT(ALGO_ID_E, exit_dske);
-                        #endif
-                    }
-
-                    /* signature */
-                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    ato16(input + args->idx, &args->verifySigSz);
-                    args->idx += OPAQUE16_LEN;
-
-                    if ((args->idx - args->begin) + args->verifySigSz > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dske);
-                    }
-
-                    /* buffer for signature */
-                    ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                    if (ssl->buffers.sig.buffer == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_dske);
-                    }
-                    ssl->buffers.sig.length = SEED_LEN + verifySz;
-
-                    /* build message to hash */
-                    XMEMCPY(ssl->buffers.sig.buffer,
-                        ssl->arrays->clientRandom, RAN_LEN);
-                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN],
-                        ssl->arrays->serverRandom, RAN_LEN);
-                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2],
-                        input + args->begin, verifySz); /* message */
-
-                    if (args->sigAlgo != ed25519_sa_algo) {
-                        int digest_sz = wc_HashGetDigestSize(hashType);
-                        if (digest_sz <= 0) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dske);
-                        }
-                        ssl->buffers.digest.length = (unsigned int)digest_sz;
-
-                        /* buffer for hash */
-                        ssl->buffers.digest.buffer = (byte*)XMALLOC(
-                            ssl->buffers.digest.length, ssl->heap,
-                            DYNAMIC_TYPE_DIGEST);
-                        if (ssl->buffers.digest.buffer == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_dske);
-                        }
-
-                        /* Perform hash */
-                        ret = wc_Hash(hashType, ssl->buffers.sig.buffer,
-                                                    ssl->buffers.sig.length,
-                                                    ssl->buffers.digest.buffer,
-                                                    ssl->buffers.digest.length);
-                        if (ret != 0) {
-                            goto exit_dske;
-                        }
-                    }
-
-                    switch (args->sigAlgo)
-                    {
-                    #ifndef NO_RSA
-                    #ifdef WC_RSA_PSS
-                        case rsa_pss_sa_algo:
-                    #endif
-                        case rsa_sa_algo:
-                        {
-                            if (ssl->peerRsaKey == NULL ||
-                                                    !ssl->peerRsaKeyPresent) {
-                                ERROR_OUT(NO_PEER_KEY, exit_dske);
-                            }
-                            break;
-                        }
-                    #endif /* !NO_RSA */
-                    #ifdef HAVE_ECC
-                        case ecc_dsa_sa_algo:
-                        {
-                            if (!ssl->peerEccDsaKeyPresent) {
-                                ERROR_OUT(NO_PEER_KEY, exit_dske);
-                            }
-                            break;
-                        }
-                    #endif /* HAVE_ECC */
-                    #if defined(HAVE_ED25519)
-                        case ed25519_sa_algo:
-                        {
-                            if (!ssl->peerEd25519KeyPresent) {
-                                ERROR_OUT(NO_PEER_KEY, exit_dske);
-                            }
-                            break;
-                        }
-                    #endif /* HAVE_ED25519 */
-
-                    default:
-                        ret = ALGO_ID_E;
-                    } /* switch (args->sigAlgo) */
-
-            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
-                    break;
-                }
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_dske;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-            switch(ssl->specs.kea)
-            {
-                case psk_kea:
-                case dhe_psk_kea:
-                case ecdhe_psk_kea:
-                {
-                    /* Nothing to do in this sub-state */
-                    break;
-                }
-
-                case diffie_hellman_kea:
-                case ecc_diffie_hellman_kea:
-                {
-            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
-                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
-            #else
-                    if (ssl->options.usingAnon_cipher) {
-                        break;
-                    }
-
-                    if (args->verifySig == NULL) {
-                        args->verifySig = (byte*)XMALLOC(args->verifySigSz,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                        if (args->verifySig == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_dske);
-                        }
-                        XMEMCPY(args->verifySig, input + args->idx,
-                                                            args->verifySigSz);
-                    }
-
-                    switch (args->sigAlgo)
-                    {
-                    #ifndef NO_RSA
-                    #ifdef WC_RSA_PSS
-                        case rsa_pss_sa_algo:
-                    #endif
-                        case rsa_sa_algo:
-                        {
-                            ret = RsaVerify(ssl,
-                                args->verifySig, args->verifySigSz,
-                                &args->output,
-                                args->sigAlgo, args->hashAlgo,
-                                ssl->peerRsaKey,
-                            #ifdef HAVE_PK_CALLBACKS
-                                &ssl->buffers.peerRsaKey
-                            #else
-                                NULL
-                            #endif
-                            );
-
-                            if (ret >= 0) {
-                                args->sigSz = (word16)ret;
-                                ret = 0;
-                            }
-                            break;
-                        }
-                    #endif /* !NO_RSA */
-                    #ifdef HAVE_ECC
-                        case ecc_dsa_sa_algo:
-                        {
-                            ret = EccVerify(ssl,
-                                args->verifySig, args->verifySigSz,
-                                ssl->buffers.digest.buffer,
-                                ssl->buffers.digest.length,
-                                ssl->peerEccDsaKey,
-                            #ifdef HAVE_PK_CALLBACKS
-                                &ssl->buffers.peerEccDsaKey
-                            #else
-                                NULL
-                            #endif
-                            );
-
-                            /* peerEccDsaKey */
-                            FreeKey(ssl, DYNAMIC_TYPE_ECC,
-                                                   (void**)&ssl->peerEccDsaKey);
-                            ssl->peerEccDsaKeyPresent = 0;
-                            break;
-                        }
-                    #endif /* HAVE_ECC */
-                    #if defined(HAVE_ED25519)
-                        case ed25519_sa_algo:
-                        {
-                            ret = Ed25519Verify(ssl,
-                                args->verifySig, args->verifySigSz,
-                                ssl->buffers.sig.buffer,
-                                ssl->buffers.sig.length,
-                                ssl->peerEd25519Key,
-                            #ifdef HAVE_PK_CALLBACKS
-                                &ssl->buffers.peerEd25519Key
-                            #else
-                                NULL
-                            #endif
-                            );
-
-                            /* peerEccDsaKey */
-                            FreeKey(ssl, DYNAMIC_TYPE_ED25519,
-                                                  (void**)&ssl->peerEd25519Key);
-                            ssl->peerEd25519KeyPresent = 0;
-                            break;
-                        }
-                    #endif /* HAVE_ED25519 */
-
-                    default:
-                        ret = ALGO_ID_E;
-                    } /* switch (sigAlgo) */
-            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
-                    break;
-                }
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_dske;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-            switch(ssl->specs.kea)
-            {
-                case psk_kea:
-                case dhe_psk_kea:
-                case ecdhe_psk_kea:
-                {
-                    /* Nothing to do in this sub-state */
-                    break;
-                }
-
-                case diffie_hellman_kea:
-                case ecc_diffie_hellman_kea:
-                {
-            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
-                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
-            #else
-                    if (ssl->options.usingAnon_cipher) {
-                        break;
-                    }
-
-                    /* increment index after verify is done */
-                    args->idx += args->verifySigSz;
-
-                    switch(args->sigAlgo)
-                    {
-                    #ifndef NO_RSA
-                    #ifdef WC_RSA_PSS
-                        case rsa_pss_sa_algo:
-                            ret = wc_RsaPSS_CheckPadding(
-                                             ssl->buffers.digest.buffer,
-                                             ssl->buffers.digest.length,
-                                             args->output, args->sigSz,
-                                             HashAlgoToType(args->hashAlgo));
-                            if (ret != 0)
-                                return ret;
-                            break;
-                    #endif
-                        case rsa_sa_algo:
-                        {
-                            if (IsAtLeastTLSv1_2(ssl)) {
-                            #ifdef WOLFSSL_SMALL_STACK
-                                byte*  encodedSig = NULL;
-                            #else
-                                byte   encodedSig[MAX_ENCODED_SIG_SZ];
-                            #endif
-                                word32 encSigSz;
-
-                            #ifdef WOLFSSL_SMALL_STACK
-                                encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
-                                                ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                                if (encodedSig == NULL) {
-                                    ERROR_OUT(MEMORY_E, exit_dske);
-                                }
-                            #endif
-
-                                encSigSz = wc_EncodeSignature(encodedSig,
-                                    ssl->buffers.digest.buffer,
-                                    ssl->buffers.digest.length,
-                                    TypeHash(args->hashAlgo));
-                                if (encSigSz != args->sigSz || !args->output ||
-                                    XMEMCMP(args->output, encodedSig,
-                                            min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
-                                    ret = VERIFY_SIGN_ERROR;
-                                }
-                            #ifdef WOLFSSL_SMALL_STACK
-                                XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                            #endif
-                                if (ret != 0) {
-                                    goto exit_dske;
-                                }
-                            }
-                            else if (args->sigSz != FINISHED_SZ ||
-                                    !args->output ||
-                                    XMEMCMP(args->output,
-                                            ssl->buffers.digest.buffer,
-                                            FINISHED_SZ) != 0) {
-                                ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske);
-                            }
-                            break;
-                        }
-                    #endif /* !NO_RSA */
-                    #ifdef HAVE_ECC
-                        case ecc_dsa_sa_algo:
-                            /* Nothing to do in this algo */
-                            break;
-                    #endif /* HAVE_ECC */
-                    #if defined(HAVE_ED25519)
-                        case ed25519_sa_algo:
-                            /* Nothing to do in this algo */
-                            break;
-                    #endif /* HAVE_ED25519 */
-                        default:
-                            ret = ALGO_ID_E;
-                    } /* switch (sigAlgo) */
-            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
-                    break;
-                }
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_dske;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-            if (IsEncryptionOn(ssl, 0)) {
-                args->idx += ssl->keys.padSz;
-            }
-
-            /* QSH extensions */
-        #ifdef HAVE_QSH
-            if (ssl->peerQSHKeyPresent) {
-                word16 name;
-                int    qshSz;
-
-                /* extension name */
-                ato16(input + args->idx, &name);
-                args->idx += OPAQUE16_LEN;
-
-                if (name == TLSX_QUANTUM_SAFE_HYBRID) {
-                    /* if qshSz is larger than 0 it is the length of
-                       buffer used */
-                    if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx,
-                                                       size, 0)) < 0) {
-                        ERROR_OUT(qshSz, exit_dske);
-                    }
-                    args->idx += qshSz;
-                }
-                else {
-                    /* unknown extension sent server ignored handshake */
-                    ERROR_OUT(BUFFER_ERROR, exit_dske);
-                }
-            }
-        #endif
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_END:
-        {
-            /* return index */
-            *inOutIdx = args->idx;
-
-            ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-    } /* switch(ssl->options.asyncState) */
-
-exit_dske:
-
-    WOLFSSL_LEAVE("DoServerKeyExchange", ret);
-    WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Handle async operation */
-    if (ret == WC_PENDING_E) {
-        /* Mark message as not recevied so it can process again */
-        ssl->msgsReceived.got_server_key_exchange = 0;
-
-        return ret;
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* Final cleanup */
-    FreeDskeArgs(ssl, args);
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-
-
-#ifdef HAVE_QSH
-
-#ifdef HAVE_NTRU
-/* Encrypt a byte array using ntru
-   key    a struct containing the public key to use
-   bufIn  array to be encrypted
-   inSz   size of bufIn array
-   bufOut cipher text out
-   outSz  will be set to the new size of cipher text
- */
-static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz,
-        byte* bufOut, word16* outSz)
-{
-    int    ret;
-    DRBG_HANDLE drbg;
-
-    /* sanity checks on input arguments */
-    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
-        return BAD_FUNC_ARG;
-
-    if (key->pub.buffer == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (key->name) {
-        case WOLFSSL_NTRU_EESS439:
-        case WOLFSSL_NTRU_EESS593:
-        case WOLFSSL_NTRU_EESS743:
-            break;
-        default:
-            WOLFSSL_MSG("Unknown QSH encryption key!");
-            return -1;
-    }
-
-    /* set up ntru drbg */
-    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
-    if (ret != DRBG_OK)
-        return NTRU_DRBG_ERROR;
-
-    /* encrypt the byte array */
-    ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer,
-        inSz, bufIn, outSz, bufOut);
-    ntru_crypto_drbg_uninstantiate(drbg);
-    if (ret != NTRU_OK)
-        return NTRU_ENCRYPT_ERROR;
-
-    return ret;
-}
-
-/* Decrypt a byte array using ntru
-   key    a struct containing the private key to use
-   bufIn  array to be decrypted
-   inSz   size of bufIn array
-   bufOut plain text out
-   outSz  will be set to the new size of plain text
- */
-
-static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz,
-        byte* bufOut, word16* outSz)
-{
-    int    ret;
-    DRBG_HANDLE drbg;
-
-    /* sanity checks on input arguments */
-    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
-        return BAD_FUNC_ARG;
-
-    if (key->pri.buffer == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (key->name) {
-        case WOLFSSL_NTRU_EESS439:
-        case WOLFSSL_NTRU_EESS593:
-        case WOLFSSL_NTRU_EESS743:
-            break;
-        default:
-            WOLFSSL_MSG("Unknown QSH decryption key!");
-            return -1;
-    }
-
-
-    /* set up drbg */
-    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
-    if (ret != DRBG_OK)
-        return NTRU_DRBG_ERROR;
-
-    /* decrypt cipher text */
-    ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer,
-        inSz, bufIn, outSz, bufOut);
-    ntru_crypto_drbg_uninstantiate(drbg);
-    if (ret != NTRU_OK)
-        return NTRU_ENCRYPT_ERROR;
-
-    return ret;
-}
-#endif /* HAVE_NTRU */
-
-int QSH_Init(WOLFSSL* ssl)
-{
-    /* check so not initialising twice when running DTLS */
-    if (ssl->QSH_secret != NULL)
-        return 0;
-
-    /* malloc memory for holding generated secret information */
-    if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap,
-                    DYNAMIC_TYPE_QSH)) == NULL)
-        return MEMORY_E;
-
-    ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
-            DYNAMIC_TYPE_SECRET);
-    if (ssl->QSH_secret->CliSi == NULL)
-        return MEMORY_E;
-
-    ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
-            DYNAMIC_TYPE_SECRET);
-    if (ssl->QSH_secret->SerSi == NULL)
-        return MEMORY_E;
-
-    /* initialize variables */
-    ssl->QSH_secret->list = NULL;
-    ssl->QSH_secret->CliSi->length = 0;
-    ssl->QSH_secret->CliSi->buffer = NULL;
-    ssl->QSH_secret->SerSi->length = 0;
-    ssl->QSH_secret->SerSi->buffer = NULL;
-
-    return 0;
-}
-
-
-static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn,
-                                                       byte* out, word32* szOut)
-{
-    int ret = 0;
-    word16 size = *szOut;
-
-    (void)in;
-    (void)szIn;
-    (void)out;
-    (void)szOut;
-
-    WOLFSSL_MSG("Encrypting QSH key material");
-
-    switch (key->name) {
-    #ifdef HAVE_NTRU
-        case WOLFSSL_NTRU_EESS439:
-        case WOLFSSL_NTRU_EESS593:
-        case WOLFSSL_NTRU_EESS743:
-            ret = NtruSecretEncrypt(key, in, szIn, out, &size);
-            break;
-    #endif
-        default:
-            WOLFSSL_MSG("Unknown QSH encryption key!");
-            return -1;
-    }
-
-    *szOut = size;
-
-    return ret;
-}
-
-
-/* Decrypt using Quantum Safe Handshake algorithms */
-int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut)
-{
-    int ret = 0;
-    word16 size = *szOut;
-
-    (void)in;
-    (void)szIn;
-    (void)out;
-    (void)szOut;
-
-    WOLFSSL_MSG("Decrypting QSH key material");
-
-    switch (key->name) {
-    #ifdef HAVE_NTRU
-        case WOLFSSL_NTRU_EESS439:
-        case WOLFSSL_NTRU_EESS593:
-        case WOLFSSL_NTRU_EESS743:
-            ret = NtruSecretDecrypt(key, in, szIn, out, &size);
-            break;
-    #endif
-        default:
-            WOLFSSL_MSG("Unknown QSH decryption key!");
-            return -1;
-    }
-
-    *szOut = size;
-
-    return ret;
-}
-
-
-/* Get the max cipher text for corresponding encryption scheme
-   (encrypting  48 or max plain text whichever is smaller)
- */
-static word32 QSH_MaxSecret(QSHKey* key)
-{
-    int ret = 0;
-#ifdef HAVE_NTRU
-    byte isNtru = 0;
-    word16 inSz = 48;
-    word16 outSz;
-    DRBG_HANDLE drbg = 0;
-    byte bufIn[48];
-#endif
-
-    if (key == NULL || key->pub.length == 0)
-        return 0;
-
-    switch(key->name) {
-#ifdef HAVE_NTRU
-            case WOLFSSL_NTRU_EESS439:
-                isNtru   = 1;
-                break;
-            case WOLFSSL_NTRU_EESS593:
-                isNtru   = 1;
-                break;
-            case WOLFSSL_NTRU_EESS743:
-                isNtru   = 1;
-                break;
-#endif
-        default:
-            WOLFSSL_MSG("Unknown QSH encryption scheme size!");
-            return 0;
-    }
-
-#ifdef HAVE_NTRU
-    if (isNtru) {
-        ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
-        if (ret != DRBG_OK)
-            return NTRU_DRBG_ERROR;
-        ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length,
-                            key->pub.buffer, inSz, bufIn, &outSz, NULL);
-        if (ret != NTRU_OK) {
-            return NTRU_ENCRYPT_ERROR;
-        }
-        ntru_crypto_drbg_uninstantiate(drbg);
-        ret = outSz;
-    }
-#endif
-
-    return ret;
-}
-
-/* Generate the secret byte material for pms
-   returns length on success and -1 on fail
- */
-static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer)
-{
-    int sz       = 0;
-    int plainSz  = 48; /* lesser of 48 and max plain text able to encrypt */
-    int offset   = 0;
-    word32 tmpSz = 0;
-    buffer* buf;
-    QSHKey* current = ssl->peerQSHKey;
-    QSHScheme* schmPre = NULL;
-    QSHScheme* schm    = NULL;
-
-    if (ssl == NULL)
-        return -1;
-
-    WOLFSSL_MSG("Generating QSH secret key material");
-
-    /* get size of buffer needed */
-    while (current) {
-        if (current->pub.length != 0) {
-            sz += plainSz;
-        }
-        current = (QSHKey*)current->next;
-    }
-
-    /* allocate memory for buffer */
-    if (isServer) {
-        buf = ssl->QSH_secret->SerSi;
-    }
-    else {
-        buf = ssl->QSH_secret->CliSi;
-    }
-    buf->length = sz;
-    buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET);
-    if (buf->buffer == NULL) {
-        WOLFSSL_ERROR(MEMORY_E);
-    }
-
-    /* create secret information */
-    sz = 0;
-    current = ssl->peerQSHKey;
-    while (current) {
-        schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap,
-                                                       DYNAMIC_TYPE_QSH);
-        if (schm == NULL)
-            return MEMORY_E;
-
-        /* initialize variables */
-        schm->name  = 0;
-        schm->PK    = NULL;
-        schm->PKLen = 0;
-        schm->next  = NULL;
-        if (ssl->QSH_secret->list == NULL) {
-            ssl->QSH_secret->list = schm;
-        }
-        else {
-            if (schmPre)
-                schmPre->next = schm;
-        }
-
-        tmpSz = QSH_MaxSecret(current);
-
-        if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap,
-                                              DYNAMIC_TYPE_SECRET)) == NULL)
-            return -1;
-
-        /* store info for writing extension */
-        schm->name = current->name;
-
-        /* no key to use for encryption */
-        if (tmpSz == 0) {
-            current = (QSHKey*)current->next;
-            continue;
-        }
-
-        if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz)
-                                                                         != 0) {
-            return -1;
-        }
-        if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK,
-                                                                 &tmpSz) != 0) {
-            return -1;
-        }
-        schm->PKLen = tmpSz;
-
-        sz += tmpSz;
-        offset += plainSz;
-        schmPre = schm;
-        current = (QSHKey*)current->next;
-    }
-
-    return sz;
-}
-
-
-static word32 QSH_KeyGetSize(WOLFSSL* ssl)
-{
-    word32 sz = 0;
-    QSHKey* current = ssl->peerQSHKey;
-
-    if (ssl == NULL)
-        return -1;
-
-    sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */
-    sz += OPAQUE24_LEN;
-    /* get size of buffer needed */
-    while (current) {
-        sz += OPAQUE16_LEN; /* scheme id */
-        sz += OPAQUE16_LEN; /* encrypted key len*/
-        sz += QSH_MaxSecret(current);
-        current = (QSHKey*)current->next;
-    }
-
-    return sz;
-}
-
-
-/* handle QSH key Exchange
-   return 0 on success
- */
-static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("QSH KeyExchange");
-
-    ret = QSH_GenerateSerCliSecret(ssl, isServer);
-    if (ret < 0)
-        return MEMORY_E;
-
-    return 0;
-}
-
-#endif /* HAVE_QSH */
-
-
-typedef struct SckeArgs {
-    byte*  output; /* not allocated */
-    byte*  encSecret;
-    byte*  input;
-    word32 encSz;
-    word32 length;
-    int    sendSz;
-    int    inputSz;
-} SckeArgs;
-
-static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
-{
-    SckeArgs* args = (SckeArgs*)pArgs;
-
-    (void)ssl;
-
-    if (args->encSecret) {
-        XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
-        args->encSecret = NULL;
-    }
-    if (args->input) {
-        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-        args->input = NULL;
-    }
-}
-
-/* handle generation client_key_exchange (16) */
-int SendClientKeyExchange(WOLFSSL* ssl)
-{
-    int ret = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    SckeArgs* args = (SckeArgs*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#else
-    SckeArgs  args[1];
-#endif
-
-    WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
-    WOLFSSL_ENTER("SendClientKeyExchange");
-
-#ifdef OPENSSL_EXTRA
-	ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
-	ssl->cbmode = SSL_CB_MODE_WRITE;
-	if (ssl->CBIS != NULL)
-		ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_scke;
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(SckeArgs));
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeSckeArgs;
-    #endif
-    }
-
-    switch(ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-            switch (ssl->specs.kea) {
-            #ifndef NO_RSA
-                case rsa_kea:
-                    if (ssl->peerRsaKey == NULL ||
-                        ssl->peerRsaKeyPresent == 0) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-                    break;
-            #endif
-            #ifndef NO_DH
-                case diffie_hellman_kea:
-                    if (ssl->buffers.serverDH_P.buffer == NULL ||
-                        ssl->buffers.serverDH_G.buffer == NULL ||
-                        ssl->buffers.serverDH_Pub.buffer == NULL) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-                    break;
-            #endif /* NO_DH */
-            #ifndef NO_PSK
-                case psk_kea:
-                    /* sanity check that PSK client callback has been set */
-                    if (ssl->options.client_psk_cb == NULL) {
-                        WOLFSSL_MSG("No client PSK callback set");
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-                    break;
-            #endif /* NO_PSK */
-            #if !defined(NO_DH) && !defined(NO_PSK)
-                case dhe_psk_kea:
-                    if (ssl->buffers.serverDH_P.buffer == NULL ||
-                        ssl->buffers.serverDH_G.buffer == NULL ||
-                        ssl->buffers.serverDH_Pub.buffer == NULL) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-
-                    /* sanity check that PSK client callback has been set */
-                    if (ssl->options.client_psk_cb == NULL) {
-                        WOLFSSL_MSG("No client PSK callback set");
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-                    break;
-            #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                case ecdhe_psk_kea:
-                    /* sanity check that PSK client callback has been set */
-                    if (ssl->options.client_psk_cb == NULL) {
-                        WOLFSSL_MSG("No client PSK callback set");
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->peerX25519KeyPresent) {
-                        /* Check client ECC public key */
-                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
-                            ERROR_OUT(NO_PEER_KEY, exit_scke);
-                        }
-
-                    #ifdef HAVE_PK_CALLBACKS
-                        /* if callback then use it for shared secret */
-                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
-                            break;
-                        }
-                    #endif
-
-                        /* create private key */
-                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
-                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                        if (ret != 0) {
-                            goto exit_scke;
-                        }
-
-                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
-                                            ssl->peerX25519Key);
-                        break;
-                    }
-                #endif
-                    /* Check client ECC public key */
-                    if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
-                                            !ssl->peerEccKey->dp) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-
-                #ifdef HAVE_PK_CALLBACKS
-                    /* if callback then use it for shared secret */
-                    if (ssl->ctx->EccSharedSecretCb != NULL) {
-                        break;
-                    }
-                #endif
-
-                    /* create ephemeral private key */
-                    ssl->hsType = DYNAMIC_TYPE_ECC;
-                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
-
-                    break;
-            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-            #ifdef HAVE_NTRU
-                case ntru_kea:
-                    if (ssl->peerNtruKeyPresent == 0) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-                    break;
-            #endif /* HAVE_NTRU */
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                case ecc_diffie_hellman_kea:
-                {
-                #ifdef HAVE_ECC
-                    ecc_key* peerKey;
-                #endif
-
-            #ifdef HAVE_PK_CALLBACKS
-                    /* if callback then use it for shared secret */
-                #ifdef HAVE_CURVE25519
-                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                        if (ssl->ctx->X25519SharedSecretCb != NULL)
-                            break;
-                    }
-                    else
-                #endif
-                    if (ssl->ctx->EccSharedSecretCb != NULL) {
-                        break;
-                    }
-            #endif /* HAVE_PK_CALLBACKS */
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->peerX25519KeyPresent) {
-                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
-                            ERROR_OUT(NO_PEER_KEY, exit_scke);
-                        }
-
-                        /* create private key */
-                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
-                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                        if (ret != 0) {
-                            goto exit_scke;
-                        }
-
-                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
-                                            ssl->peerX25519Key);
-                        break;
-                    }
-                #endif
-                #ifdef HAVE_ECC
-                    if (ssl->specs.static_ecdh) {
-                        /* Note: EccDsa is really fixed Ecc key here */
-                        if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
-                                                   !ssl->peerEccDsaKey->dp) {
-                            ERROR_OUT(NO_PEER_KEY, exit_scke);
-                        }
-                        peerKey = ssl->peerEccDsaKey;
-                    }
-                    else {
-                        if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
-                                                !ssl->peerEccKey->dp) {
-                            ERROR_OUT(NO_PEER_KEY, exit_scke);
-                        }
-                        peerKey = ssl->peerEccKey;
-                    }
-                    if (peerKey == NULL) {
-                        ERROR_OUT(NO_PEER_KEY, exit_scke);
-                    }
-
-                    /* create ephemeral private key */
-                    ssl->hsType = DYNAMIC_TYPE_ECC;
-                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey);
-                #endif
-
-                    break;
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scke;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            args->encSz = MAX_ENCRYPT_SZ;
-            args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap,
-                                                    DYNAMIC_TYPE_SECRET);
-            if (args->encSecret == NULL) {
-                ERROR_OUT(MEMORY_E, exit_scke);
-            }
-
-            switch(ssl->specs.kea)
-            {
-            #ifndef NO_RSA
-                case rsa_kea:
-                {
-                    /* build PreMasterSecret with RNG data */
-                    ret = wc_RNG_GenerateBlock(ssl->rng,
-                        &ssl->arrays->preMasterSecret[VERSION_SZ],
-                        SECRET_LEN - VERSION_SZ);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
-                    ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
-                    ssl->arrays->preMasterSz = SECRET_LEN;
-                    break;
-                }
-            #endif /* !NO_RSA */
-            #ifndef NO_DH
-                case diffie_hellman_kea:
-                {
-                    ssl->buffers.sig.length = ENCRYPT_LEN;
-                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                    if (ssl->buffers.sig.buffer == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_scke);
-                    }
-
-                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
-                                            (void**)&ssl->buffers.serverDH_Key);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
-                        ssl->buffers.serverDH_P.buffer,
-                        ssl->buffers.serverDH_P.length,
-                        ssl->buffers.serverDH_G.buffer,
-                        ssl->buffers.serverDH_G.length);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    /* for DH, encSecret is Yc, agree is pre-master */
-                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
-                        ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
-                        args->encSecret, &args->encSz);
-
-                    /* set the max agree result size */
-                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
-                    break;
-                }
-            #endif /* !NO_DH */
-            #ifndef NO_PSK
-                case psk_kea:
-                {
-                    byte* pms = ssl->arrays->preMasterSecret;
-                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
-                        ssl->arrays->server_hint, ssl->arrays->client_identity,
-                        MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
-                    if (ssl->arrays->psk_keySz == 0 ||
-                        ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
-                    args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
-                    if (args->encSz > MAX_PSK_ID_LEN) {
-                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
-                    }
-                    XMEMCPY(args->encSecret, ssl->arrays->client_identity,
-                                                                args->encSz);
-
-                    /* make psk pre master secret */
-                    /* length of key + length 0s + length of key + key */
-                    c16toa((word16)ssl->arrays->psk_keySz, pms);
-                    pms += OPAQUE16_LEN;
-                    XMEMSET(pms, 0, ssl->arrays->psk_keySz);
-                    pms += ssl->arrays->psk_keySz;
-                    c16toa((word16)ssl->arrays->psk_keySz, pms);
-                    pms += OPAQUE16_LEN;
-                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) +
-                        (2 * OPAQUE16_LEN);
-                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->psk_keySz = 0; /* No further need */
-                    break;
-                }
-            #endif /* !NO_PSK */
-            #if !defined(NO_DH) && !defined(NO_PSK)
-                case dhe_psk_kea:
-                {
-                    word32 esSz = 0;
-                    args->output = args->encSecret;
-
-                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
-                         ssl->arrays->server_hint, ssl->arrays->client_identity,
-                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
-                    if (ssl->arrays->psk_keySz == 0 ||
-                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
-                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
-
-                    if (esSz > MAX_PSK_ID_LEN) {
-                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
-                    }
-
-                    ssl->buffers.sig.length = ENCRYPT_LEN;
-                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                    if (ssl->buffers.sig.buffer == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_scke);
-                    }
-
-                    c16toa((word16)esSz, args->output);
-                    args->output += OPAQUE16_LEN;
-                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
-                    args->output += esSz;
-                    args->encSz = esSz + OPAQUE16_LEN;
-
-                    args->length = 0;
-
-                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
-                                            (void**)&ssl->buffers.serverDH_Key);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
-                        ssl->buffers.serverDH_P.buffer,
-                        ssl->buffers.serverDH_P.length,
-                        ssl->buffers.serverDH_G.buffer,
-                        ssl->buffers.serverDH_G.length);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    /* for DH, encSecret is Yc, agree is pre-master */
-                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
-                        ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
-                        args->output + OPAQUE16_LEN, &args->length);
-                    break;
-                }
-            #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                case ecdhe_psk_kea:
-                {
-                    word32 esSz = 0;
-                    args->output = args->encSecret;
-
-                    /* Send PSK client identity */
-                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
-                         ssl->arrays->server_hint, ssl->arrays->client_identity,
-                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
-                    if (ssl->arrays->psk_keySz == 0 ||
-                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
-                    }
-                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
-                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
-                    if (esSz > MAX_PSK_ID_LEN) {
-                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
-                    }
-
-                    /* place size and identity in output buffer sz:identity */
-                    c16toa((word16)esSz, args->output);
-                    args->output += OPAQUE16_LEN;
-                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
-                    args->output += esSz;
-                    args->encSz = esSz + OPAQUE16_LEN;
-
-                    /* length is used for public key size */
-                    args->length = MAX_ENCRYPT_SZ;
-
-                    /* Create shared ECC key leaving room at the begining
-                       of buffer for size of shared key. */
-                    ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN;
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                    #ifdef HAVE_PK_CALLBACKS
-                        /* if callback then use it for shared secret */
-                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
-                            break;
-                        }
-                    #endif
-
-                        ret = wc_curve25519_export_public_ex(
-                                (curve25519_key*)ssl->hsKey,
-                                args->output + OPAQUE8_LEN, &args->length,
-                                EC25519_LITTLE_ENDIAN);
-                        if (ret != 0) {
-                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
-                        }
-
-                        break;
-                    }
-                #endif
-                #ifdef HAVE_PK_CALLBACKS
-                    /* if callback then use it for shared secret */
-                    if (ssl->ctx->EccSharedSecretCb != NULL) {
-                        break;
-                    }
-                #endif
-
-                    /* Place ECC key in output buffer, leaving room for size */
-                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
-                                    args->output + OPAQUE8_LEN, &args->length);
-                    if (ret != 0) {
-                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
-                    }
-
-                    break;
-                }
-            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-            #ifdef HAVE_NTRU
-                case ntru_kea:
-                {
-                    ret = wc_RNG_GenerateBlock(ssl->rng,
-                                  ssl->arrays->preMasterSecret, SECRET_LEN);
-                    if (ret != 0) {
-                        goto exit_scke;
-                    }
-
-                    ssl->arrays->preMasterSz = SECRET_LEN;
-                    args->encSz = MAX_ENCRYPT_SZ;
-                    break;
-                }
-            #endif /* HAVE_NTRU */
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                case ecc_diffie_hellman_kea:
-                {
-                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) {
-                    #ifdef HAVE_PK_CALLBACKS
-                        /* if callback then use it for shared secret */
-                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
-                            break;
-                        }
-                    #endif
-
-                        ret = wc_curve25519_export_public_ex(
-                                (curve25519_key*)ssl->hsKey,
-                                args->encSecret + OPAQUE8_LEN, &args->encSz,
-                                EC25519_LITTLE_ENDIAN);
-                        if (ret != 0) {
-                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
-                        }
-
-                        break;
-                    }
-                #endif
-                #ifdef HAVE_ECC
-                #ifdef HAVE_PK_CALLBACKS
-                    /* if callback then use it for shared secret */
-                    if (ssl->ctx->EccSharedSecretCb != NULL) {
-                        break;
-                    }
-                #endif
-
-                    /* Place ECC key in buffer, leaving room for size */
-                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
-                                args->encSecret + OPAQUE8_LEN, &args->encSz);
-                    if (ret != 0) {
-                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
-                    }
-                #endif /* HAVE_ECC */
-                    break;
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scke;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-            switch(ssl->specs.kea)
-            {
-            #ifndef NO_RSA
-                case rsa_kea:
-                {
-                    ret = RsaEnc(ssl,
-                        ssl->arrays->preMasterSecret, SECRET_LEN,
-                        args->encSecret, &args->encSz,
-                        ssl->peerRsaKey,
-                    #if defined(HAVE_PK_CALLBACKS)
-                        &ssl->buffers.peerRsaKey
-                    #else
-                        NULL
-                    #endif
-                    );
-
-                    break;
-                }
-            #endif /* !NO_RSA */
-            #ifndef NO_DH
-                case diffie_hellman_kea:
-                {
-                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
-                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
-                        ssl->buffers.serverDH_Pub.buffer,
-                        ssl->buffers.serverDH_Pub.length,
-                        ssl->arrays->preMasterSecret,
-                        &ssl->arrays->preMasterSz);
-                    break;
-                }
-            #endif /* !NO_DH */
-            #ifndef NO_PSK
-                case psk_kea:
-                {
-                    break;
-                }
-            #endif /* !NO_PSK */
-            #if !defined(NO_DH) && !defined(NO_PSK)
-                case dhe_psk_kea:
-                {
-                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
-                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
-                        ssl->buffers.serverDH_Pub.buffer,
-                        ssl->buffers.serverDH_Pub.length,
-                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                        &ssl->arrays->preMasterSz);
-                    break;
-                }
-            #endif /* !NO_DH && !NO_PSK */
-            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                case ecdhe_psk_kea:
-                {
-                #ifdef HAVE_CURVE25519
-                    if (ssl->peerX25519KeyPresent) {
-                        ret = X25519SharedSecret(ssl,
-                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
-                            args->output + OPAQUE8_LEN, &args->length,
-                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                            &ssl->arrays->preMasterSz,
-                            WOLFSSL_CLIENT_END
-                        );
-                        if (ret == 0 && !ssl->specs.static_ecdh) {
-                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                                   (void**)&ssl->peerX25519Key);
-                            ssl->peerX25519KeyPresent = 0;
-                        }
-                        break;
-                    }
-                #endif
-                    ret = EccSharedSecret(ssl,
-                        (ecc_key*)ssl->hsKey, ssl->peerEccKey,
-                        args->output + OPAQUE8_LEN, &args->length,
-                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                        &ssl->arrays->preMasterSz,
-                        WOLFSSL_CLIENT_END
-                    );
-                    break;
-                }
-            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-            #ifdef HAVE_NTRU
-                case ntru_kea:
-                {
-                    word32 rc;
-                    word16 tmpEncSz = (word16)args->encSz;
-                    DRBG_HANDLE drbg;
-
-                    rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
-                    if (rc != DRBG_OK) {
-                        ERROR_OUT(NTRU_DRBG_ERROR, exit_scke);
-                    }
-                    rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,
-                                                  ssl->peerNtruKey,
-                                                  ssl->arrays->preMasterSz,
-                                                  ssl->arrays->preMasterSecret,
-                                                  &tmpEncSz,
-                                                  args->encSecret);
-                    args->encSz = tmpEncSz;
-                    ntru_crypto_drbg_uninstantiate(drbg);
-                    if (rc != NTRU_OK) {
-                        ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke);
-                    }
-                    ret = 0;
-                    break;
-                }
-            #endif /* HAVE_NTRU */
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                case ecc_diffie_hellman_kea:
-                {
-                #ifdef HAVE_ECC
-                    ecc_key* peerKey;
-                #endif
-
-                #ifdef HAVE_CURVE25519
-                    if (ssl->peerX25519KeyPresent) {
-                        ret = X25519SharedSecret(ssl,
-                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
-                            args->encSecret + OPAQUE8_LEN, &args->encSz,
-                            ssl->arrays->preMasterSecret,
-                            &ssl->arrays->preMasterSz,
-                            WOLFSSL_CLIENT_END
-                        );
-                        if (ret == 0) {
-                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                                   (void**)&ssl->peerX25519Key);
-                            ssl->peerX25519KeyPresent = 0;
-                        }
-                        break;
-                    }
-                #endif
-                #ifdef HAVE_ECC
-                    peerKey = (ssl->specs.static_ecdh) ?
-                              ssl->peerEccDsaKey : ssl->peerEccKey;
-
-                    ret = EccSharedSecret(ssl,
-                        (ecc_key*)ssl->hsKey, peerKey,
-                        args->encSecret + OPAQUE8_LEN, &args->encSz,
-                        ssl->arrays->preMasterSecret,
-                        &ssl->arrays->preMasterSz,
-                        WOLFSSL_CLIENT_END
-                    );
-                #endif
-
-                    break;
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scke;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-            switch(ssl->specs.kea)
-            {
-            #ifndef NO_RSA
-                case rsa_kea:
-                {
-                    break;
-                }
-            #endif /* !NO_RSA */
-            #ifndef NO_DH
-                case diffie_hellman_kea:
-                {
-                    break;
-                }
-            #endif /* !NO_DH */
-            #ifndef NO_PSK
-                case psk_kea:
-                {
-                    break;
-                }
-            #endif /* !NO_PSK */
-            #if !defined(NO_DH) && !defined(NO_PSK)
-                case dhe_psk_kea:
-                {
-                    byte* pms = ssl->arrays->preMasterSecret;
-
-                    /* validate args */
-                    if (args->output == NULL || args->length == 0) {
-                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
-                    }
-
-                    c16toa((word16)args->length, args->output);
-                    args->encSz += args->length + OPAQUE16_LEN;
-                    c16toa((word16)ssl->arrays->preMasterSz, pms);
-                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
-                    pms += ssl->arrays->preMasterSz;
-
-                    /* make psk pre master secret */
-                    /* length of key + length 0s + length of key + key */
-                    c16toa((word16)ssl->arrays->psk_keySz, pms);
-                    pms += OPAQUE16_LEN;
-                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->preMasterSz +=
-                                         ssl->arrays->psk_keySz + OPAQUE16_LEN;
-                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->psk_keySz = 0; /* No further need */
-                    break;
-                }
-            #endif /* !NO_DH && !NO_PSK */
-            #if defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
-                                                                !defined(NO_PSK)
-                case ecdhe_psk_kea:
-                {
-                    byte* pms = ssl->arrays->preMasterSecret;
-
-                    /* validate args */
-                    if (args->output == NULL || args->length > ENCRYPT_LEN) {
-                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
-                    }
-
-                    /* place size of public key in output buffer */
-                    *args->output = (byte)args->length;
-                    args->encSz += args->length + OPAQUE8_LEN;
-
-                    /* Create pre master secret is the concatination of
-                       eccSize + eccSharedKey + pskSize + pskKey */
-                    c16toa((word16)ssl->arrays->preMasterSz, pms);
-                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
-                    pms += ssl->arrays->preMasterSz;
-
-                    c16toa((word16)ssl->arrays->psk_keySz, pms);
-                    pms += OPAQUE16_LEN;
-                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->preMasterSz +=
-                                          ssl->arrays->psk_keySz + OPAQUE16_LEN;
-
-                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                    ssl->arrays->psk_keySz = 0; /* No further need */
-                    break;
-                }
-            #endif /* (HAVE_ECC && !HAVE_CURVE25519) && !NO_PSK */
-            #ifdef HAVE_NTRU
-                case ntru_kea:
-                {
-                    break;
-                }
-            #endif /* HAVE_NTRU */
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                case ecc_diffie_hellman_kea:
-                {
-                    /* place size of public key in buffer */
-                    *args->encSecret = (byte)args->encSz;
-                    args->encSz += OPAQUE8_LEN;
-                    break;
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-                default:
-                    ret = BAD_KEA_TYPE_E;
-            } /* switch(ssl->specs.kea) */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scke;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-            word32 tlsSz = 0;
-            word32 idx = 0;
-
-        #ifdef HAVE_QSH
-            word32 qshSz = 0;
-            if (ssl->peerQSHKeyPresent) {
-                qshSz = QSH_KeyGetSize(ssl);
-            }
-        #endif
-
-            if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) {
-                tlsSz = 2;
-            }
-
-            if (ssl->specs.kea == ecc_diffie_hellman_kea ||
-                ssl->specs.kea == dhe_psk_kea ||
-                ssl->specs.kea == ecdhe_psk_kea) { /* always off */
-                tlsSz = 0;
-            }
-
-            idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-            args->sendSz = args->encSz + tlsSz + idx;
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls) {
-                idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
-                args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
-            }
-        #endif
-
-            if (IsEncryptionOn(ssl, 1)) {
-                args->sendSz += MAX_MSG_EXTRA;
-            }
-
-        #ifdef HAVE_QSH
-            args->encSz += qshSz;
-            args->sendSz += qshSz;
-        #endif
-
-            /* check for available size */
-            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                goto exit_scke;
-            }
-
-            /* get output buffer */
-            args->output = ssl->buffers.outputBuffer.buffer +
-                           ssl->buffers.outputBuffer.length;
-
-        #ifdef HAVE_QSH
-            if (ssl->peerQSHKeyPresent) {
-                byte idxSave = idx;
-                idx = args->sendSz - qshSz;
-
-                if (QSH_KeyExchangeWrite(ssl, 0) != 0) {
-                    ERROR_OUT(MEMORY_E, exit_scke);
-                }
-
-                /* extension type */
-                c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx);
-                idx += OPAQUE16_LEN;
-
-                /* write to output and check amount written */
-                if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
-                            args->output + idx) > qshSz - OPAQUE16_LEN) {
-                    ERROR_OUT(MEMORY_E, exit_scke);
-                }
-
-                idx = idxSave;
-            }
-        #endif
-
-            AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl);
-
-        #ifdef HAVE_QSH
-            if (ssl->peerQSHKeyPresent) {
-                args->encSz -= qshSz;
-            }
-        #endif
-            if (tlsSz) {
-                c16toa((word16)args->encSz, &args->output[idx]);
-                idx += OPAQUE16_LEN;
-            }
-            XMEMCPY(args->output + idx, args->encSecret, args->encSz);
-            idx += args->encSz;
-
-            if (IsEncryptionOn(ssl, 1)) {
-                args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */
-                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
-                                                       DYNAMIC_TYPE_IN_BUFFER);
-                if (args->input == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_scke);
-                }
-
-                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
-                                                                args->inputSz);
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_END:
-        {
-            if (IsEncryptionOn(ssl, 1)) {
-                ret = BuildMessage(ssl, args->output, args->sendSz,
-                            args->input, args->inputSz, handshake, 1, 0, 0);
-                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-                args->input = NULL; /* make sure its not double free'd on cleanup */
-
-                if (ret >= 0) {
-                    args->sendSz = ret;
-                    ret = 0;
-                }
-            }
-            else {
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-                ret = HashOutput(ssl, args->output, args->sendSz, 0);
-            }
-
-            if (ret != 0) {
-                goto exit_scke;
-            }
-
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
-                    goto exit_scke;
-                }
-            }
-        #endif
-
-        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "ClientKeyExchange");
-            if (ssl->toInfoOn)
-                AddPacketInfo(ssl, "ClientKeyExchange", handshake,
-                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
-        #endif
-
-            ssl->buffers.outputBuffer.length += args->sendSz;
-
-            if (!ssl->options.groupMessages) {
-                ret = SendBuffered(ssl);
-            }
-            if (ret == 0 || ret == WANT_WRITE) {
-                int tmpRet = MakeMasterSecret(ssl);
-                if (tmpRet != 0) {
-                    ret = tmpRet;   /* save WANT_WRITE unless more serious */
-                }
-                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
-            }
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-    } /* switch(ssl->options.asyncState) */
-
-exit_scke:
-
-    WOLFSSL_LEAVE("SendClientKeyExchange", ret);
-    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Handle async operation */
-    if (ret == WC_PENDING_E)
-        return ret;
-#endif
-
-    /* No further need for PMS */
-    ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
-    ssl->arrays->preMasterSz = 0;
-
-    /* Final cleanup */
-    FreeSckeArgs(ssl, args);
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifndef NO_CERTS
-
-#ifdef HAVE_PK_CALLBACKS
-    int GetPrivateKeySigSize(WOLFSSL* ssl)
-    {
-        int sigSz = 0;
-
-        if (ssl == NULL)
-            return 0;
-
-        switch (ssl->buffers.keyType) {
-        #ifndef NO_RSA
-        #ifdef WC_RSA_PSS
-            case rsa_pss_sa_algo:
-        #endif
-            case rsa_sa_algo:
-                sigSz = ssl->buffers.keySz;
-                ssl->hsType = DYNAMIC_TYPE_RSA;
-                break;
-        #endif
-        #ifdef HAVE_ECC
-            case ecc_dsa_sa_algo:
-                sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz);
-                ssl->hsType = DYNAMIC_TYPE_ECC;
-                break;
-        #endif
-        #ifdef HAVE_ED25519
-            case ed25519_sa_algo:
-                sigSz = ED25519_SIG_SIZE; /* fixed known value */
-                ssl->hsType = DYNAMIC_TYPE_ED25519;
-                break;
-        #endif
-            default:
-                break;
-        }
-        return sigSz;
-    }
-#endif /* HAVE_PK_CALLBACKS */
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifndef WOLFSSL_NO_CLIENT_AUTH
-typedef struct ScvArgs {
-    byte*  output; /* not allocated */
-#ifndef NO_RSA
-    byte*  verifySig;
-#endif
-    byte*  verify; /* not allocated */
-    byte*  input;
-    word32 idx;
-    word32 extraSz;
-    word32 sigSz;
-    int    sendSz;
-    int    inputSz;
-    word16 length;
-    byte   sigAlgo;
-} ScvArgs;
-
-static void FreeScvArgs(WOLFSSL* ssl, void* pArgs)
-{
-    ScvArgs* args = (ScvArgs*)pArgs;
-
-    (void)ssl;
-
-#ifndef NO_RSA
-    if (args->verifySig) {
-        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        args->verifySig = NULL;
-    }
-#endif
-    if (args->input) {
-        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-        args->input = NULL;
-    }
-}
-
-/* handle generation of certificate_verify (15) */
-int SendCertificateVerify(WOLFSSL* ssl)
-{
-    int ret = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ScvArgs* args = (ScvArgs*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#else
-    ScvArgs  args[1];
-#endif
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
-    WOLFSSL_ENTER("SendCertificateVerify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_scv;
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(ScvArgs));
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeScvArgs;
-    #endif
-    }
-
-    switch(ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
-                return 0;  /* sent blank cert, can't verify */
-            }
-
-            args->sendSz = MAX_CERT_VERIFY_SZ;
-            if (IsEncryptionOn(ssl, 1)) {
-                args->sendSz += MAX_MSG_EXTRA;
-            }
-
-            /* check for available size */
-            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                goto exit_scv;
-            }
-
-            /* get output buffer */
-            args->output = ssl->buffers.outputBuffer.buffer +
-                           ssl->buffers.outputBuffer.length;
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-            if (ssl->buffers.key == NULL) {
-            #ifdef HAVE_PK_CALLBACKS
-                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
-                    args->length = GetPrivateKeySigSize(ssl);
-                else
-            #endif
-                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
-            }
-            else {
-                /* Decode private key. */
-                ret = DecodePrivateKey(ssl, &args->length);
-                if (ret != 0) {
-                    goto exit_scv;
-                }
-            }
-
-            if (args->length <= 0) {
-                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
-            }
-
-            /* idx is used to track verify pointer offset to output */
-            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-            args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
-            args->extraSz = 0;  /* tls 1.2 hash/sig */
-
-            /* build encoded signature buffer */
-            ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ;
-            ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length,
-                                        ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-            if (ssl->buffers.sig.buffer == NULL) {
-                ERROR_OUT(MEMORY_E, exit_scv);
-            }
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls) {
-                args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-            }
-        #endif
-
-    #ifndef NO_OLD_TLS
-        #ifndef NO_SHA
-            /* old tls default */
-            SetDigest(ssl, sha_mac);
-        #endif
-    #else
-        #ifndef NO_SHA256
-            /* new tls default */
-            SetDigest(ssl, sha256_mac);
-        #endif
-    #endif /* !NO_OLD_TLS */
-
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-        #ifdef WC_RSA_PSS
-                if (IsAtLeastTLSv1_2(ssl) &&
-                                (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) {
-                    args->sigAlgo = rsa_pss_sa_algo;
-                }
-                else
-        #endif
-                    args->sigAlgo = rsa_sa_algo;
-            }
-            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
-                args->sigAlgo = ecc_dsa_sa_algo;
-            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
-                args->sigAlgo = ed25519_sa_algo;
-
-            if (IsAtLeastTLSv1_2(ssl)) {
-                EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo,
-                             args->verify);
-                args->extraSz = HASH_SIG_SIZE;
-                SetDigest(ssl, ssl->suites->hashAlgo);
-            }
-        #ifndef NO_OLD_TLS
-            else {
-                /* if old TLS load MD5 and SHA hash as value to sign */
-                XMEMCPY(ssl->buffers.sig.buffer,
-                    (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ);
-            }
-        #endif
-
-        #ifndef NO_RSA
-            if (args->sigAlgo == rsa_sa_algo) {
-                ssl->buffers.sig.length = FINISHED_SZ;
-                args->sigSz = ENCRYPT_LEN;
-
-                if (IsAtLeastTLSv1_2(ssl)) {
-                    ssl->buffers.sig.length = wc_EncodeSignature(
-                            ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
-                            ssl->buffers.digest.length,
-                            TypeHash(ssl->suites->hashAlgo));
-                }
-
-                /* prepend hdr */
-                c16toa(args->length, args->verify + args->extraSz);
-            }
-            else if (args->sigAlgo == rsa_pss_sa_algo) {
-                XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
-                        ssl->buffers.digest.length);
-                ssl->buffers.sig.length = ssl->buffers.digest.length;
-                args->sigSz = ENCRYPT_LEN;
-
-                /* prepend hdr */
-                c16toa(args->length, args->verify + args->extraSz);
-            }
-        #endif /* !NO_RSA */
-        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
-            if (args->sigAlgo == ed25519_sa_algo) {
-                ret = Ed25519CheckPubKey(ssl);
-                if (ret != 0)
-                    goto exit_scv;
-            }
-        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-        #ifdef HAVE_ECC
-           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                ecc_key* key = (ecc_key*)ssl->hsKey;
-
-                ret = EccSign(ssl,
-                    ssl->buffers.digest.buffer, ssl->buffers.digest.length,
-                    ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
-                    key,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
-            #endif
-                );
-            }
-        #endif /* HAVE_ECC */
-        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
-           if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
-                ed25519_key* key = (ed25519_key*)ssl->hsKey;
-
-                ret = Ed25519Sign(ssl,
-                    ssl->hsHashes->messages, ssl->hsHashes->length,
-                    ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
-                    key,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
-            #endif
-                );
-            }
-        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
-        #ifndef NO_RSA
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                /* restore verify pointer */
-                args->verify = &args->output[args->idx];
-
-                ret = RsaSign(ssl,
-                    ssl->buffers.sig.buffer, ssl->buffers.sig.length,
-                    args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz,
-                    args->sigAlgo, ssl->suites->hashAlgo, key,
-                    ssl->buffers.key
-                );
-            }
-        #endif /* !NO_RSA */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-            /* restore verify pointer */
-            args->verify = &args->output[args->idx];
-
-        #ifdef HAVE_ECC
-            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                args->length = (word16)ssl->buffers.sig.length;
-                /* prepend hdr */
-                c16toa(args->length, args->verify + args->extraSz);
-                XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
-                        ssl->buffers.sig.buffer, ssl->buffers.sig.length);
-            }
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
-                args->length = (word16)ssl->buffers.sig.length;
-                /* prepend hdr */
-                c16toa(args->length, args->verify + args->extraSz);
-                XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
-                        ssl->buffers.sig.buffer, ssl->buffers.sig.length);
-            }
-        #endif /* HAVE_ED25519 */
-        #ifndef NO_RSA
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                if (args->verifySig == NULL) {
-                    args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap,
-                                      DYNAMIC_TYPE_SIGNATURE);
-                    if (args->verifySig == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_scv);
-                    }
-                    XMEMCPY(args->verifySig, args->verify + args->extraSz +
-                                                    VERIFY_HEADER, args->sigSz);
-                }
-
-                /* check for signature faults */
-                ret = VerifyRsaSign(ssl,
-                    args->verifySig, args->sigSz,
-                    ssl->buffers.sig.buffer, ssl->buffers.sig.length,
-                    args->sigAlgo, ssl->suites->hashAlgo, key,
-                    ssl->buffers.key
-                );
-            }
-        #endif /* !NO_RSA */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-            if (args->output == NULL) {
-                ERROR_OUT(BUFFER_ERROR, exit_scv);
-            }
-            AddHeaders(args->output, (word32)args->length + args->extraSz +
-                                        VERIFY_HEADER, certificate_verify, ssl);
-
-            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
-                           (word32)args->length + args->extraSz + VERIFY_HEADER;
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->options.dtls) {
-                args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-            }
-        #endif
-
-            if (IsEncryptionOn(ssl, 1)) {
-                args->inputSz = args->sendSz - RECORD_HEADER_SZ;
-                                /* build msg adds rec hdr */
-                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
-                                                       DYNAMIC_TYPE_IN_BUFFER);
-                if (args->input == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_scv);
-                }
-
-                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
-                                                                args->inputSz);
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_END:
-        {
-            if (IsEncryptionOn(ssl, 1)) {
-                ret = BuildMessage(ssl, args->output,
-                                      MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
-                                      args->input, args->inputSz, handshake,
-                                      1, 0, 1);
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                if (ret == WC_PENDING_E)
-                    goto exit_scv;
-            #endif
-
-                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-                args->input = NULL;  /* make sure its not double free'd on cleanup */
-
-                if (ret >= 0) {
-                    args->sendSz = ret;
-                    ret = 0;
-                }
-            }
-            else {
-            #ifdef WOLFSSL_DTLS
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-                ret = HashOutput(ssl, args->output, args->sendSz, 0);
-            }
-
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz);
-            }
-        #endif
-
-
-        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "CertificateVerify");
-            if (ssl->toInfoOn)
-                AddPacketInfo(ssl, "CertificateVerify", handshake,
-                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
-        #endif
-
-            ssl->buffers.outputBuffer.length += args->sendSz;
-
-            if (!ssl->options.groupMessages) {
-                ret = SendBuffered(ssl);
-            }
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-    } /* switch(ssl->options.asyncState) */
-
-exit_scv:
-
-    WOLFSSL_LEAVE("SendCertificateVerify", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Handle async operation */
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* Digest is not allocated, so do this to prevent free */
-    ssl->buffers.digest.buffer = NULL;
-    ssl->buffers.digest.length = 0;
-
-    /* Final cleanup */
-    FreeScvArgs(ssl, args);
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-#endif /* WOLFSSL_NO_CLIENT_AUTH */
-
-#endif /* WOLFSSL_NO_TLS12 */
-
-#endif /* NO_CERTS */
-
-
-#ifdef HAVE_SESSION_TICKET
-int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length)
-{
-    /* Free old dynamic ticket if we already had one */
-    if (ssl->session.isDynamic) {
-        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        ssl->session.ticket = ssl->session.staticTicket;
-        ssl->session.isDynamic = 0;
-    }
-
-    if (length > sizeof(ssl->session.staticTicket)) {
-        byte* sessionTicket =
-                   (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        if (sessionTicket == NULL)
-            return MEMORY_E;
-        ssl->session.ticket = sessionTicket;
-        ssl->session.isDynamic = 1;
-    }
-    ssl->session.ticketLen = (word16)length;
-
-    if (length > 0) {
-        XMEMCPY(ssl->session.ticket, ticket, length);
-        if (ssl->session_ticket_cb != NULL) {
-            ssl->session_ticket_cb(ssl,
-                                   ssl->session.ticket, ssl->session.ticketLen,
-                                   ssl->session_ticket_ctx);
-        }
-        /* Create a fake sessionID based on the ticket, this will
-         * supercede the existing session cache info. */
-        ssl->options.haveSessionId = 1;
-        XMEMCPY(ssl->arrays->sessionID,
-                                 ssl->session.ticket + length - ID_LEN, ID_LEN);
-    }
-
-    return 0;
-}
-
-#ifndef WOLFSSL_NO_TLS12
-
-/* handle processing of session_ticket (4) */
-static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-    word32 size)
-{
-    word32 begin = *inOutIdx;
-    word32 lifetime;
-    word16 length;
-    int    ret;
-
-    if (ssl->expect_session_ticket == 0) {
-        WOLFSSL_MSG("Unexpected session ticket");
-        return SESSION_TICKET_EXPECT_E;
-    }
-
-    if ((*inOutIdx - begin) + OPAQUE32_LEN > size)
-        return BUFFER_ERROR;
-
-    ato32(input + *inOutIdx, &lifetime);
-    *inOutIdx += OPAQUE32_LEN;
-
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-
-    ato16(input + *inOutIdx, &length);
-    *inOutIdx += OPAQUE16_LEN;
-
-    if ((*inOutIdx - begin) + length > size)
-        return BUFFER_ERROR;
-
-    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
-        return ret;
-    *inOutIdx += length;
-    if (length > 0) {
-        ssl->timeout = lifetime;
-#ifndef NO_SESSION_CACHE
-        AddSession(ssl);
-#endif
-    }
-
-    if (IsEncryptionOn(ssl, 0)) {
-        *inOutIdx += ssl->keys.padSz;
-    }
-
-    ssl->expect_session_ticket = 0;
-
-    return 0;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#endif /* HAVE_SESSION_TICKET */
-
-#endif /* NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-
-#ifndef WOLFSSL_NO_TLS12
-
-    /* handle generation of server_hello (2) */
-    int SendServerHello(WOLFSSL* ssl)
-    {
-        int    ret;
-        byte   *output;
-        word16 length;
-        word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-        int    sendSz;
-        byte   sessIdSz = ID_LEN;
-        byte   echoId   = 0;  /* ticket echo id flag */
-        byte   cacheOff = 0;  /* session cache off flag */
-
-        WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
-        WOLFSSL_ENTER("SendServerHello");
-
-        length = VERSION_SZ + RAN_LEN
-               + ID_LEN + ENUM_LEN
-               + SUITE_LEN
-               + ENUM_LEN;
-
-#ifdef HAVE_TLS_EXTENSIONS
-        ret = TLSX_GetResponseSize(ssl, server_hello, &length);
-        if (ret != 0)
-            return ret;
-    #ifdef HAVE_SESSION_TICKET
-        if (ssl->options.useTicket) {
-            /* echo session id sz can be 0,32 or bogus len inbetween */
-            sessIdSz = ssl->arrays->sessionIDSz;
-            if (sessIdSz > ID_LEN) {
-                WOLFSSL_MSG("Bad bogus session id len");
-                return BUFFER_ERROR;
-            }
-            if (!IsAtLeastTLSv1_3(ssl->version))
-                length -= (ID_LEN - sessIdSz);  /* adjust ID_LEN assumption */
-            echoId = 1;
-        }
-    #endif /* HAVE_SESSION_TICKET */
-#else
-        if (ssl->options.haveEMS) {
-            length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
-        }
-#endif
-
-        /* is the session cahce off at build or runtime */
-#ifdef NO_SESSION_CACHE
-        cacheOff = 1;
-#else
-        if (ssl->options.sessionCacheOff == 1) {
-            cacheOff = 1;
-        }
-#endif
-
-        /* if no session cache don't send a session ID unless we're echoing
-         * an ID as part of session tickets */
-        if (echoId == 0 && cacheOff == 1) {
-            length -= ID_LEN;    /* adjust ID_LEN assumption */
-            sessIdSz = 0;
-        }
-
-        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-        #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            /* Server Hello should use the same sequence number as the
-             * Client Hello. */
-            ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
-            ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
-            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-        }
-        #endif /* WOLFSSL_DTLS */
-
-        /* check for avalaible size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        AddHeaders(output, length, server_hello, ssl);
-
-        /* now write to output */
-        /* first version */
-        output[idx++] = (byte)ssl->version.major;
-        output[idx++] = (byte)ssl->version.minor;
-
-        /* then random and session id */
-        if (!ssl->options.resuming) {
-            /* generate random part and session id */
-            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
-                RAN_LEN + sizeof(sessIdSz) + sessIdSz);
-            if (ret != 0)
-                return ret;
-
-#ifdef WOLFSSL_TLS13
-            if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
-                /* TLS v1.3 capable server downgraded. */
-                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
-                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
-                output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
-            }
-            else
-#endif
-            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
-                          ssl->ctx->method->version.minor == TLSv1_2_MINOR &&
-                                                       !IsAtLeastTLSv1_2(ssl)) {
-                /* TLS v1.2 capable server downgraded. */
-                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
-                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
-                output[idx + RAN_LEN - 1] = 0;
-            }
-
-            /* store info in SSL for later */
-            XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
-            idx += RAN_LEN;
-            output[idx++] = sessIdSz;
-            XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
-            ssl->arrays->sessionIDSz = sessIdSz;
-        }
-        else {
-            /* If resuming, use info from SSL */
-            XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
-            idx += RAN_LEN;
-            output[idx++] = sessIdSz;
-            XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
-        }
-        idx += sessIdSz;
-
-#ifdef SHOW_SECRETS
-        {
-            int j;
-            printf("server random: ");
-            for (j = 0; j < RAN_LEN; j++)
-                printf("%02x", ssl->arrays->serverRandom[j]);
-            printf("\n");
-        }
-#endif
-
-        /* then cipher suite */
-        output[idx++] = ssl->options.cipherSuite0;
-        output[idx++] = ssl->options.cipherSuite;
-
-        /* then compression */
-        if (ssl->options.usingCompression)
-            output[idx++] = ZLIB_COMPRESSION;
-        else
-            output[idx++] = NO_COMPRESSION;
-
-        /* last, extensions */
-#ifdef HAVE_TLS_EXTENSIONS
-        ret = TLSX_WriteResponse(ssl, output + idx, server_hello, NULL);
-        if (ret != 0)
-            return ret;
-#else
-#ifdef HAVE_EXTENDED_MASTER
-        if (ssl->options.haveEMS) {
-            c16toa(HELLO_EXT_SZ, output + idx);
-            idx += HELLO_EXT_SZ_SZ;
-
-            c16toa(HELLO_EXT_EXTMS, output + idx);
-            idx += HELLO_EXT_TYPE_SZ;
-            c16toa(0, output + idx);
-            /*idx += HELLO_EXT_SZ_SZ;*/
-            /* idx is not used after this point. uncomment the line above
-             * if adding any more extentions in the future. */
-        }
-#endif
-#endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-        #ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                    return ret;
-            }
-
-            if (ssl->options.dtls) {
-                DtlsSEQIncrement(ssl, CUR_ORDER);
-            }
-        #endif
-
-        ret = HashOutput(ssl, output, sendSz, 0);
-        if (ret != 0)
-            return ret;
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "ServerHello");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
-                          WRITE_PROTO, ssl->heap);
-    #endif
-
-        ssl->options.serverState = SERVER_HELLO_COMPLETE;
-
-        if (ssl->options.groupMessages)
-            ret = 0;
-        else
-            ret = SendBuffered(ssl);
-
-        WOLFSSL_LEAVE("SendServerHello", ret);
-        WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
-
-        return ret;
-    }
-
-
-#if defined(HAVE_ECC)
-
-    static byte SetCurveId(ecc_key* key)
-    {
-        if (key == NULL || key->dp == NULL) {
-            WOLFSSL_MSG("SetCurveId: Invalid key!");
-            return 0;
-        }
-
-        switch(key->dp->oidSum) {
-    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP160R1_OID:
-                return WOLFSSL_ECC_SECP160R1;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_SECPR2
-            case ECC_SECP160R2_OID:
-                return WOLFSSL_ECC_SECP160R2;
-        #endif /* HAVE_ECC_SECPR2 */
-        #ifdef HAVE_ECC_KOBLITZ
-            case ECC_SECP160K1_OID:
-                return WOLFSSL_ECC_SECP160K1;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP192R1_OID:
-                return WOLFSSL_ECC_SECP192R1;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case ECC_SECP192K1_OID:
-                return WOLFSSL_ECC_SECP192K1;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP224R1_OID:
-                return WOLFSSL_ECC_SECP224R1;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case ECC_SECP224K1_OID:
-                return WOLFSSL_ECC_SECP224K1;
-        #endif /* HAVE_ECC_KOBLITZ */
-    #endif
-    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP256R1_OID:
-                return WOLFSSL_ECC_SECP256R1;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_KOBLITZ
-            case ECC_SECP256K1_OID:
-                return WOLFSSL_ECC_SECP256K1;
-        #endif /* HAVE_ECC_KOBLITZ */
-        #ifdef HAVE_ECC_BRAINPOOL
-            case ECC_BRAINPOOLP256R1_OID:
-                return WOLFSSL_ECC_BRAINPOOLP256R1;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP384R1_OID:
-                return WOLFSSL_ECC_SECP384R1;
-        #endif /* !NO_ECC_SECP */
-        #ifdef HAVE_ECC_BRAINPOOL
-            case ECC_BRAINPOOLP384R1_OID:
-                return WOLFSSL_ECC_BRAINPOOLP384R1;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
-        #ifdef HAVE_ECC_BRAINPOOL
-            case ECC_BRAINPOOLP512R1_OID:
-                return WOLFSSL_ECC_BRAINPOOLP512R1;
-        #endif /* HAVE_ECC_BRAINPOOL */
-    #endif
-    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
-        #ifndef NO_ECC_SECP
-            case ECC_SECP521R1_OID:
-                return WOLFSSL_ECC_SECP521R1;
-        #endif /* !NO_ECC_SECP */
-    #endif
-            default:
-                return 0;
-        }
-    }
-
-#endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-    typedef struct SskeArgs {
-        byte*  output; /* not allocated */
-    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
-                                           (!defined(NO_DH) && !defined(NO_RSA))
-        byte*  sigDataBuf;
-    #endif
-    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-        byte*  exportBuf;
-    #endif
-    #ifndef NO_RSA
-        byte*  verifySig;
-    #endif
-        word32 idx;
-        word32 tmpSigSz;
-        word32 length;
-        word32 sigSz;
-    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
-                                           (!defined(NO_DH) && !defined(NO_RSA))
-        word32 sigDataSz;
-    #endif
-    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-        word32 exportSz;
-    #endif
-    #ifdef HAVE_QSH
-        word32 qshSz;
-    #endif
-        int    sendSz;
-    } SskeArgs;
-
-    static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs)
-    {
-        SskeArgs* args = (SskeArgs*)pArgs;
-
-        (void)ssl;
-
-    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-        if (args->exportBuf) {
-            XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
-            args->exportBuf = NULL;
-        }
-    #endif
-    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
-                                           (!defined(NO_DH) && !defined(NO_RSA))
-        if (args->sigDataBuf) {
-            XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-            args->sigDataBuf = NULL;
-        }
-    #endif
-    #ifndef NO_RSA
-        if (args->verifySig) {
-            XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-            args->verifySig = NULL;
-        }
-    #endif
-        (void)args;
-    }
-
-    /* handle generation of server_key_exchange (12) */
-    int SendServerKeyExchange(WOLFSSL* ssl)
-    {
-        int ret;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        SskeArgs* args = (SskeArgs*)ssl->async.args;
-        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-        (void)sizeof(args_test);
-    #else
-        SskeArgs  args[1];
-    #endif
-
-        WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
-        WOLFSSL_ENTER("SendServerKeyExchange");
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-        if (ret != WC_NOT_PENDING_E) {
-            /* Check for error */
-            if (ret < 0)
-                goto exit_sske;
-        }
-        else
-    #endif
-        {
-            /* Reset state */
-            ret = 0;
-            ssl->options.asyncState = TLS_ASYNC_BEGIN;
-            XMEMSET(args, 0, sizeof(SskeArgs));
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            ssl->async.freeArgs = FreeSskeArgs;
-        #endif
-        }
-
-        switch(ssl->options.asyncState)
-        {
-            case TLS_ASYNC_BEGIN:
-            {
-            #ifdef HAVE_QSH
-                if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) {
-                    args->qshSz = QSH_KeyGetSize(ssl);
-                }
-            #endif
-
-                /* Do some checks / debug msgs */
-                switch(ssl->specs.kea)
-                {
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        WOLFSSL_MSG("Using ephemeral ECDH PSK");
-                        break;
-                    }
-                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
-                #if defined(HAVE_ECC)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        if (ssl->specs.static_ecdh) {
-                            WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange");
-                            ERROR_OUT(0, exit_sske);
-                        }
-
-                        WOLFSSL_MSG("Using ephemeral ECDH");
-                        break;
-                    }
-                #endif /* HAVE_ECC */
-                }
-
-                /* Preparing keys */
-                switch(ssl->specs.kea)
-                {
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        /* Nothing to do in this sub-state */
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA))
-                #if !defined(NO_PSK)
-                    case dhe_psk_kea:
-                #endif
-                #if !defined(NO_RSA)
-                    case diffie_hellman_kea:
-                #endif
-                    {
-                        /* Allocate DH key buffers and generate key */
-                        if (ssl->buffers.serverDH_P.buffer == NULL ||
-                            ssl->buffers.serverDH_G.buffer == NULL) {
-                            ERROR_OUT(NO_DH_PARAMS, exit_sske);
-                        }
-
-                        if (ssl->buffers.serverDH_Pub.buffer == NULL) {
-                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
-                            ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
-                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
-                                    ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                            if (ssl->buffers.serverDH_Pub.buffer == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_sske);
-                            }
-                        }
-
-                        if (ssl->buffers.serverDH_Priv.buffer == NULL) {
-                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
-                            ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
-                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
-                                    ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
-                            if (ssl->buffers.serverDH_Priv.buffer == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_sske);
-                            }
-                        }
-
-                        ssl->options.dhKeySz =
-                                (word16)ssl->buffers.serverDH_P.length;
-
-                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
-                                            (void**)&ssl->buffers.serverDH_Key);
-                        if (ret != 0) {
-                            goto exit_sske;
-                        }
-
-                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_P.buffer,
-                            ssl->buffers.serverDH_P.length,
-                            ssl->buffers.serverDH_G.buffer,
-                            ssl->buffers.serverDH_G.length);
-                        if (ret != 0) {
-                            goto exit_sske;
-                        }
-
-                        ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_Priv.buffer,
-                            &ssl->buffers.serverDH_Priv.length,
-                            ssl->buffers.serverDH_Pub.buffer,
-                            &ssl->buffers.serverDH_Pub.length);
-                        break;
-                    }
-                #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                        /* Fall through to create temp ECC key */
-                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                            /* need ephemeral key now, create it if missing */
-                            if (ssl->eccTempKey == NULL) {
-                                /* alloc/init on demand */
-                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                    (void**)&ssl->eccTempKey);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-                            }
-
-                            if (ssl->eccTempKeyPresent == 0) {
-                                ret = X25519MakeKey(ssl,
-                                        (curve25519_key*)ssl->eccTempKey, NULL);
-                                if (ret == 0 || ret == WC_PENDING_E) {
-                                    ssl->eccTempKeyPresent =
-                                        DYNAMIC_TYPE_CURVE25519;
-                                }
-                            }
-                            break;
-                        }
-                    #endif
-                    #ifdef HAVE_ECC
-                        /* need ephemeral key now, create it if missing */
-                        if (ssl->eccTempKey == NULL) {
-                            /* alloc/init on demand */
-                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                (void**)&ssl->eccTempKey);
-                            if (ret != 0) {
-                                goto exit_sske;
-                            }
-                        }
-
-                        if (ssl->eccTempKeyPresent == 0) {
-                            ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
-                            if (ret == 0 || ret == WC_PENDING_E) {
-                                ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC;
-                            }
-                        }
-                    #endif
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                    default:
-                        /* Skip ServerKeyExchange */
-                        goto exit_sske;
-                } /* switch(ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_sske;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_BUILD;
-            } /* case TLS_ASYNC_BEGIN */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_BUILD:
-            {
-            #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
-                                                       defined(HAVE_CURVE25519))
-                word32 preSigSz, preSigIdx;
-            #endif
-
-                switch(ssl->specs.kea)
-                {
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
-                        if (ssl->arrays->server_hint[0] == 0) {
-                            ERROR_OUT(0, exit_sske); /* don't send */
-                        }
-
-                        /* include size part */
-                        args->length = (word32)XSTRLEN(ssl->arrays->server_hint);
-                        if (args->length > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
-                        }
-
-                        args->length += HINT_LEN_SZ;
-                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
-                                                            RECORD_HEADER_SZ;
-
-                    #ifdef HAVE_QSH
-                        args->length += args->qshSz;
-                        args->sendSz += args->qshSz;
-                    #endif
-
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                        }
-                    #endif
-                        /* check for available size */
-                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                            goto exit_sske;
-                        }
-
-                        /* get ouput buffer */
-                        args->output = ssl->buffers.outputBuffer.buffer +
-                                       ssl->buffers.outputBuffer.length;
-
-                        AddHeaders(args->output, args->length,
-                                                    server_key_exchange, ssl);
-
-                        /* key data */
-                    #ifdef HAVE_QSH
-                        c16toa((word16)(args->length - args->qshSz -
-                                        HINT_LEN_SZ), args->output + args->idx);
-                    #else
-                        c16toa((word16)(args->length - HINT_LEN_SZ),
-                                                      args->output + args->idx);
-                    #endif
-
-                        args->idx += HINT_LEN_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                ssl->arrays->server_hint,
-                                args->length - HINT_LEN_SZ);
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        word32 hintLen;
-
-                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-                        args->length = LENGTH_SZ * 3 + /* p, g, pub */
-                                 ssl->buffers.serverDH_P.length +
-                                 ssl->buffers.serverDH_G.length +
-                                 ssl->buffers.serverDH_Pub.length;
-
-                        /* include size part */
-                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
-                        if (hintLen > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
-                        }
-                        args->length += hintLen + HINT_LEN_SZ;
-                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
-                                                            RECORD_HEADER_SZ;
-
-                    #ifdef HAVE_QSH
-                        args->length += args->qshSz;
-                        args->sendSz += args->qshSz;
-                    #endif
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                        }
-                    #endif
-
-                        /* check for available size */
-                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                            goto exit_sske;
-                        }
-
-                        /* get ouput buffer */
-                        args->output = ssl->buffers.outputBuffer.buffer +
-                                       ssl->buffers.outputBuffer.length;
-
-                        AddHeaders(args->output, args->length,
-                                                    server_key_exchange, ssl);
-
-                        /* key data */
-                        c16toa((word16)hintLen, args->output + args->idx);
-                        args->idx += HINT_LEN_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                            ssl->arrays->server_hint, hintLen);
-                        args->idx += hintLen;
-
-                        /* add p, g, pub */
-                        c16toa((word16)ssl->buffers.serverDH_P.length,
-                            args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                ssl->buffers.serverDH_P.buffer,
-                                ssl->buffers.serverDH_P.length);
-                        args->idx += ssl->buffers.serverDH_P.length;
-
-                        /*  g */
-                        c16toa((word16)ssl->buffers.serverDH_G.length,
-                            args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                ssl->buffers.serverDH_G.buffer,
-                                ssl->buffers.serverDH_G.length);
-                        args->idx += ssl->buffers.serverDH_G.length;
-
-                        /*  pub */
-                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
-                            args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                ssl->buffers.serverDH_Pub.buffer,
-                                ssl->buffers.serverDH_Pub.length);
-                        /* No need to update idx, since sizes are already set */
-                        /* args->idx += ssl->buffers.serverDH_Pub.length; */
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        word32 hintLen;
-
-                        /* curve type, named curve, length(1) */
-                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
-
-                        args->exportSz = MAX_EXPORT_ECC_SZ;
-                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
-                                            ssl->heap, DYNAMIC_TYPE_DER);
-                        if (args->exportBuf == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                            if (wc_curve25519_export_public_ex(
-                                    (curve25519_key*)ssl->eccTempKey,
-                                    args->exportBuf, &args->exportSz,
-                                    EC25519_LITTLE_ENDIAN) != 0) {
-                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
-                            }
-                        }
-                        else
-                    #endif
-                        {
-                            if (wc_ecc_export_x963(ssl->eccTempKey,
-                                       args->exportBuf, &args->exportSz) != 0) {
-                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
-                            }
-                        }
-                        args->length += args->exportSz;
-
-                        /* include size part */
-                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
-                        if (hintLen > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
-                        }
-                        args->length += hintLen + HINT_LEN_SZ;
-                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
-                    #ifdef HAVE_QSH
-                        args->length += args->qshSz;
-                        args->sendSz += args->qshSz;
-                    #endif
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                        }
-                    #endif
-                        /* check for available size */
-                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                            goto exit_sske;
-                        }
-
-                        /* get output buffer */
-                        args->output = ssl->buffers.outputBuffer.buffer +
-                                       ssl->buffers.outputBuffer.length;
-
-                        /* key data */
-                        c16toa((word16)hintLen, args->output + args->idx);
-                        args->idx += HINT_LEN_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                            ssl->arrays->server_hint, hintLen);
-                        args->idx += hintLen;
-
-                        /* ECC key exchange data */
-                        args->output[args->idx++] = named_curve;
-                        args->output[args->idx++] = 0x00;          /* leading zero */
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
-                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
-                        else
-                    #endif
-                        {
-                    #ifdef HAVE_ECC
-                            args->output[args->idx++] =
-                                                    SetCurveId(ssl->eccTempKey);
-                    #endif
-                        }
-                        args->output[args->idx++] = (byte)args->exportSz;
-                        XMEMCPY(args->output + args->idx, args->exportBuf,
-                                                                args->exportSz);
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        enum wc_HashType hashType;
-
-                        /* curve type, named curve, length(1) */
-                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
-
-                        /* Export temp ECC key and add to length */
-                        args->exportSz = MAX_EXPORT_ECC_SZ;
-                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
-                                            ssl->heap, DYNAMIC_TYPE_DER);
-                        if (args->exportBuf == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                            if (wc_curve25519_export_public_ex(
-                                        (curve25519_key*)ssl->eccTempKey,
-                                        args->exportBuf, &args->exportSz,
-                                        EC25519_LITTLE_ENDIAN) != 0) {
-                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
-                            }
-                        }
-                        else
-                    #endif
-                        {
-                    #ifdef HAVE_ECC
-                            if (wc_ecc_export_x963(ssl->eccTempKey,
-                                       args->exportBuf, &args->exportSz) != 0) {
-                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
-                            }
-                     #endif
-                        }
-                        args->length += args->exportSz;
-
-                        preSigSz  = args->length;
-                        preSigIdx = args->idx;
-
-                        if (ssl->buffers.key == NULL) {
-                        #ifdef HAVE_PK_CALLBACKS
-                            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
-                                args->tmpSigSz = GetPrivateKeySigSize(ssl);
-                                if (args->tmpSigSz <= 0) {
-                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
-                                }
-                            }
-                            else
-                        #endif
-                                ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
-                        }
-                        else {
-                            switch(ssl->suites->sigAlgo) {
-                        #ifndef NO_RSA
-                        #ifdef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                        #endif
-                            case rsa_sa_algo:
-                            {
-                                word32 i = 0;
-                                int keySz;
-
-                                ssl->hsType = DYNAMIC_TYPE_RSA;
-                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-
-                                ret = wc_RsaPrivateKeyDecode(
-                                    ssl->buffers.key->buffer,
-                                    &i,
-                                    (RsaKey*)ssl->hsKey,
-                                    ssl->buffers.key->length);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-                                keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
-                                if (keySz < 0) { /* test if keySz has error */
-                                    ERROR_OUT(keySz, exit_sske);
-                                }
-
-                                args->tmpSigSz = (word32)keySz;
-                                if (keySz < ssl->options.minRsaKeySz) {
-                                    WOLFSSL_MSG("RSA signature key size too small");
-                                    ERROR_OUT(RSA_KEY_SIZE_E, exit_sske);
-                                }
-                                break;
-                            }
-                        #endif /* !NO_RSA */
-                        #ifdef HAVE_ECC
-                            case ecc_dsa_sa_algo:
-                            {
-                                word32 i = 0;
-
-                                ssl->hsType = DYNAMIC_TYPE_ECC;
-                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-
-                                ret = wc_EccPrivateKeyDecode(
-                                    ssl->buffers.key->buffer,
-                                    &i,
-                                    (ecc_key*)ssl->hsKey,
-                                    ssl->buffers.key->length);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-                                /* worst case estimate */
-                                args->tmpSigSz = wc_ecc_sig_size(
-                                    (ecc_key*)ssl->hsKey);
-
-                                /* check the minimum ECC key size */
-                                if (wc_ecc_size((ecc_key*)ssl->hsKey) <
-                                        ssl->options.minEccKeySz) {
-                                    WOLFSSL_MSG("ECC key size too small");
-                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
-                                }
-                                break;
-                            }
-                        #endif
-                        #ifdef HAVE_ED25519
-                            case ed25519_sa_algo:
-                            {
-                                word32 i = 0;
-
-                                ssl->hsType = DYNAMIC_TYPE_ED25519;
-                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-
-                                ret = wc_Ed25519PrivateKeyDecode(
-                                    ssl->buffers.key->buffer,
-                                    &i,
-                                    (ed25519_key*)ssl->hsKey,
-                                    ssl->buffers.key->length);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-
-                                /* worst case estimate */
-                                args->tmpSigSz = ED25519_SIG_SIZE;
-
-                                /* check the minimum ECC key size */
-                                if (ED25519_KEY_SIZE <
-                                        ssl->options.minEccKeySz) {
-                                    WOLFSSL_MSG("Ed25519 key size too small");
-                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
-                                }
-                                break;
-                            }
-                        #endif /* HAVE_ED25519 */
-                            default:
-                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
-                            } /* switch(ssl->specs.sig_algo) */
-                        }
-
-                        /* sig length */
-                        args->length += LENGTH_SZ;
-                        args->length += args->tmpSigSz;
-
-                        if (IsAtLeastTLSv1_2(ssl)) {
-                            args->length += HASH_SIG_SIZE;
-                        }
-
-                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
-                    #ifdef HAVE_QSH
-                        args->length += args->qshSz;
-                        args->sendSz += args->qshSz;
-                    #endif
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            preSigIdx = args->idx;
-                        }
-                    #endif
-                        /* check for available size */
-                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                            goto exit_sske;
-                        }
-
-                        /* get ouput buffer */
-                        args->output = ssl->buffers.outputBuffer.buffer +
-                                       ssl->buffers.outputBuffer.length;
-
-                        /* record and message headers will be added below, when we're sure
-                           of the sig length */
-
-                        /* key exchange data */
-                        args->output[args->idx++] = named_curve;
-                        args->output[args->idx++] = 0x00;          /* leading zero */
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
-                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
-                        else
-                    #endif
-                        {
-                    #ifdef HAVE_ECC
-                            args->output[args->idx++] =
-                                                    SetCurveId(ssl->eccTempKey);
-                    #endif
-                        }
-                        args->output[args->idx++] = (byte)args->exportSz;
-                        XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz);
-                        args->idx += args->exportSz;
-
-                        /* Determine hash type */
-                        if (IsAtLeastTLSv1_2(ssl)) {
-                            EncodeSigAlg(ssl->suites->hashAlgo,
-                                         ssl->suites->sigAlgo,
-                                         &args->output[args->idx]);
-                            args->idx += 2;
-
-                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
-                            if (hashType == WC_HASH_TYPE_NONE) {
-                                ERROR_OUT(ALGO_ID_E, exit_sske);
-                            }
-
-                        } else {
-                            /* only using sha and md5 for rsa */
-                        #ifndef NO_OLD_TLS
-                            hashType = WC_HASH_TYPE_SHA;
-                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
-                                hashType = WC_HASH_TYPE_MD5_SHA;
-                            }
-                        #else
-                            ERROR_OUT(ALGO_ID_E, exit_sske);
-                        #endif
-                        }
-
-                        /* Signtaure length will be written later, when we're sure what it is */
-
-                    #ifdef HAVE_FUZZER
-                        if (ssl->fuzzerCb) {
-                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
-                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
-                        }
-                    #endif
-
-                        /* Assemble buffer to hash for signature */
-                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
-                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                        if (args->sigDataBuf == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
-                                                                       RAN_LEN);
-                        XMEMCPY(args->sigDataBuf+RAN_LEN,
-                                            ssl->arrays->serverRandom, RAN_LEN);
-                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
-                                args->output + preSigIdx, preSigSz);
-
-                        if (ssl->suites->sigAlgo != ed25519_sa_algo) {
-                            ssl->buffers.sig.length =
-                                                 wc_HashGetDigestSize(hashType);
-                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
-                                            ssl->buffers.sig.length,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                            if (ssl->buffers.sig.buffer == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_sske);
-                            }
-
-                            /* Perform hash */
-                            ret = wc_Hash(hashType, args->sigDataBuf,
-                                                       args->sigDataSz,
-                                                       ssl->buffers.sig.buffer,
-                                                       ssl->buffers.sig.length);
-                            if (ret != 0) {
-                                goto exit_sske;
-                            }
-                        }
-
-                        args->sigSz = args->tmpSigSz;
-
-                        /* Sign hash to create signature */
-                        switch (ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                            case rsa_sa_algo:
-                            {
-                                /* For TLS 1.2 re-encode signature */
-                                if (IsAtLeastTLSv1_2(ssl)) {
-                                    byte* encodedSig = (byte*)XMALLOC(
-                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
-                                                       DYNAMIC_TYPE_SIGNATURE);
-                                    if (encodedSig == NULL) {
-                                        ERROR_OUT(MEMORY_E, exit_sske);
-                                    }
-
-                                    ssl->buffers.sig.length =
-                                        wc_EncodeSignature(encodedSig,
-                                            ssl->buffers.sig.buffer,
-                                            ssl->buffers.sig.length,
-                                            TypeHash(ssl->suites->hashAlgo));
-
-                                    /* Replace sig buffer with new one */
-                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
-                                                       DYNAMIC_TYPE_SIGNATURE);
-                                    ssl->buffers.sig.buffer = encodedSig;
-                                }
-
-                                /* write sig size here */
-                                c16toa((word16)args->sigSz,
-                                    args->output + args->idx);
-                                args->idx += LENGTH_SZ;
-                                break;
-                            }
-                        #ifdef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                                /* write sig size here */
-                                c16toa((word16)args->sigSz,
-                                    args->output + args->idx);
-                                args->idx += LENGTH_SZ;
-                                break;
-                        #endif
-                        #endif /* !NO_RSA */
-                            case ecc_dsa_sa_algo:
-                            {
-                                break;
-                            }
-                        #ifdef  HAVE_ED25519
-                            case ed25519_sa_algo:
-                                ret = Ed25519CheckPubKey(ssl);
-                                if (ret != 0)
-                                    goto exit_sske;
-                                break;
-                        #endif /* HAVE_ED25519 */
-                        } /* switch(ssl->specs.sig_algo) */
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #if !defined(NO_DH) && !defined(NO_RSA)
-                    case diffie_hellman_kea:
-                    {
-                        enum wc_HashType hashType;
-
-                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-                        args->length = LENGTH_SZ * 3;  /* p, g, pub */
-                        args->length += ssl->buffers.serverDH_P.length +
-                                        ssl->buffers.serverDH_G.length +
-                                        ssl->buffers.serverDH_Pub.length;
-
-                        preSigIdx = args->idx;
-                        preSigSz  = args->length;
-
-                        if (!ssl->options.usingAnon_cipher) {
-                            int keySz;
-
-                            /* sig length */
-                            args->length += LENGTH_SZ;
-
-                            if (ssl->buffers.key == NULL) {
-                            #ifdef HAVE_PK_CALLBACKS
-                                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
-                                    keySz = (word32)GetPrivateKeySigSize(ssl);
-                                else
-                            #endif
-                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
-                            }
-                            else
-                            {
-                                word32 i = 0;
-
-                                ssl->hsType = DYNAMIC_TYPE_RSA;
-                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-
-                                ret = wc_RsaPrivateKeyDecode(
-                                    ssl->buffers.key->buffer, &i,
-                                    (RsaKey*)ssl->hsKey,
-                                    ssl->buffers.key->length);
-                                if (ret != 0) {
-                                    goto exit_sske;
-                                }
-                                keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
-                            }
-
-                            if (keySz <= 0) { /* test if keySz has error */
-                                ERROR_OUT(keySz, exit_sske);
-                            }
-
-                            args->tmpSigSz = (word32)keySz;
-                            args->length += args->tmpSigSz;
-
-                            if (keySz < ssl->options.minRsaKeySz) {
-                                WOLFSSL_MSG("RSA key size too small");
-                                ERROR_OUT(RSA_KEY_SIZE_E, exit_sske);
-                            }
-
-                            if (IsAtLeastTLSv1_2(ssl)) {
-                                args->length += HASH_SIG_SIZE;
-                            }
-                        }
-
-                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
-                                                            RECORD_HEADER_SZ;
-
-                    #ifdef HAVE_QSH
-                        args->length += args->qshSz;
-                        args->sendSz += args->qshSz;
-                    #endif
-                    #ifdef WOLFSSL_DTLS
-                        if (ssl->options.dtls) {
-                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-                            preSigIdx = args->idx;
-                        }
-                    #endif
-
-                        /* check for available size */
-                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                            goto exit_sske;
-                        }
-
-                        /* get ouput buffer */
-                        args->output = ssl->buffers.outputBuffer.buffer +
-                                       ssl->buffers.outputBuffer.length;
-
-                        AddHeaders(args->output, args->length,
-                                                    server_key_exchange, ssl);
-
-                        /* add p, g, pub */
-                        c16toa((word16)ssl->buffers.serverDH_P.length,
-                                                    args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                              ssl->buffers.serverDH_P.buffer,
-                                              ssl->buffers.serverDH_P.length);
-                        args->idx += ssl->buffers.serverDH_P.length;
-
-                        /*  g */
-                        c16toa((word16)ssl->buffers.serverDH_G.length,
-                                                    args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                              ssl->buffers.serverDH_G.buffer,
-                                              ssl->buffers.serverDH_G.length);
-                        args->idx += ssl->buffers.serverDH_G.length;
-
-                        /*  pub */
-                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
-                                                    args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-                        XMEMCPY(args->output + args->idx,
-                                              ssl->buffers.serverDH_Pub.buffer,
-                                              ssl->buffers.serverDH_Pub.length);
-                        args->idx += ssl->buffers.serverDH_Pub.length;
-
-                    #ifdef HAVE_FUZZER
-                        if (ssl->fuzzerCb) {
-                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
-                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
-                        }
-                    #endif
-
-                        if (ssl->options.usingAnon_cipher) {
-                            break;
-                        }
-
-                        /* Determine hash type */
-                        if (IsAtLeastTLSv1_2(ssl)) {
-                            EncodeSigAlg(ssl->suites->hashAlgo,
-                                         ssl->suites->sigAlgo,
-                                         &args->output[args->idx]);
-                            args->idx += 2;
-
-                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
-                            if (hashType == WC_HASH_TYPE_NONE) {
-                                ERROR_OUT(ALGO_ID_E, exit_sske);
-                            }
-                        } else {
-                            /* only using sha and md5 for rsa */
-                        #ifndef NO_OLD_TLS
-                            hashType = WC_HASH_TYPE_SHA;
-                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
-                                hashType = WC_HASH_TYPE_MD5_SHA;
-                            }
-                        #else
-                            ERROR_OUT(ALGO_ID_E, exit_sske);
-                        #endif
-                        }
-
-                        /* signature size */
-                        c16toa((word16)args->tmpSigSz, args->output + args->idx);
-                        args->idx += LENGTH_SZ;
-
-                        /* Assemble buffer to hash for signature */
-                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
-                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
-                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                        if (args->sigDataBuf == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
-                                                                    RAN_LEN);
-                        XMEMCPY(args->sigDataBuf+RAN_LEN,
-                                        ssl->arrays->serverRandom, RAN_LEN);
-                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
-                            args->output + preSigIdx, preSigSz);
-
-                        if (ssl->suites->sigAlgo != ed25519_sa_algo) {
-                            ssl->buffers.sig.length =
-                                                 wc_HashGetDigestSize(hashType);
-                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
-                                             ssl->buffers.sig.length, ssl->heap,
-                                                       DYNAMIC_TYPE_SIGNATURE);
-                            if (ssl->buffers.sig.buffer == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_sske);
-                            }
-
-                            /* Perform hash */
-                            ret = wc_Hash(hashType, args->sigDataBuf,
-                                                       args->sigDataSz,
-                                                       ssl->buffers.sig.buffer,
-                                                       ssl->buffers.sig.length);
-                            if (ret != 0) {
-                                goto exit_sske;
-                            }
-                        }
-
-                        args->sigSz = args->tmpSigSz;
-
-                        /* Sign hash to create signature */
-                        switch (ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                            case rsa_sa_algo:
-                            {
-                                /* For TLS 1.2 re-encode signature */
-                                if (IsAtLeastTLSv1_2(ssl)) {
-                                    byte* encodedSig = (byte*)XMALLOC(
-                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
-                                                       DYNAMIC_TYPE_SIGNATURE);
-                                    if (encodedSig == NULL) {
-                                        ERROR_OUT(MEMORY_E, exit_sske);
-                                    }
-
-                                    ssl->buffers.sig.length =
-                                        wc_EncodeSignature(encodedSig,
-                                            ssl->buffers.sig.buffer,
-                                            ssl->buffers.sig.length,
-                                            TypeHash(ssl->suites->hashAlgo));
-
-                                    /* Replace sig buffer with new one */
-                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
-                                                       DYNAMIC_TYPE_SIGNATURE);
-                                    ssl->buffers.sig.buffer = encodedSig;
-                                }
-                                break;
-                            }
-                        #endif /* NO_RSA */
-                        } /* switch (ssl->suites->sigAlgo) */
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
-                } /* switch(ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_sske;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_DO;
-            } /* case TLS_ASYNC_BUILD */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_DO:
-            {
-                switch(ssl->specs.kea)
-                {
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        /* Sign hash to create signature */
-                        switch (ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                        #ifdef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                        #endif
-                            case rsa_sa_algo:
-                            {
-                                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                                ret = RsaSign(ssl,
-                                    ssl->buffers.sig.buffer,
-                                    ssl->buffers.sig.length,
-                                    args->output + args->idx,
-                                    &args->sigSz,
-                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key,
-                                    ssl->buffers.key
-                                );
-                                break;
-                            }
-                        #endif /* !NO_RSA */
-                        #ifdef HAVE_ECC
-                            case ecc_dsa_sa_algo:
-                            {
-                                ecc_key* key = (ecc_key*)ssl->hsKey;
-
-                                ret = EccSign(ssl,
-                                    ssl->buffers.sig.buffer,
-                                    ssl->buffers.sig.length,
-                                    args->output + LENGTH_SZ + args->idx,
-                                    &args->sigSz,
-                                    key,
-                            #ifdef HAVE_PK_CALLBACKS
-                                    ssl->buffers.key
-                            #else
-                                    NULL
-                            #endif
-                                );
-                                break;
-                            }
-                        #endif /* HAVE_ECC */
-                        #ifdef HAVE_ED25519
-                            case ed25519_sa_algo:
-                            {
-                                ed25519_key* key = (ed25519_key*)ssl->hsKey;
-
-                                ret = Ed25519Sign(ssl,
-                                    args->sigDataBuf, args->sigDataSz,
-                                    args->output + LENGTH_SZ + args->idx,
-                                    &args->sigSz,
-                                    key,
-                            #ifdef HAVE_PK_CALLBACKS
-                                    ssl->buffers.key
-                            #else
-                                    NULL
-                            #endif
-                                );
-                                break;
-                            }
-                        #endif
-                        } /* switch(ssl->specs.sig_algo) */
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #if !defined(NO_DH) && !defined(NO_RSA)
-                    case diffie_hellman_kea:
-                    {
-                        /* Sign hash to create signature */
-                        switch (ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                        #ifdef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                        #endif
-                            case rsa_sa_algo:
-                            {
-                                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                                if (ssl->options.usingAnon_cipher) {
-                                    break;
-                                }
-
-                                ret = RsaSign(ssl,
-                                    ssl->buffers.sig.buffer,
-                                    ssl->buffers.sig.length,
-                                    args->output + args->idx,
-                                    &args->sigSz,
-                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key,
-                                    ssl->buffers.key
-                                );
-                                break;
-                            }
-                        #endif /* NO_RSA */
-                        } /* switch (ssl->suites->sigAlgo) */
-
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
-                } /* switch(ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_sske;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_VERIFY;
-            } /* case TLS_ASYNC_DO */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_VERIFY:
-            {
-                switch(ssl->specs.kea)
-                {
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        /* Nothing to do in this sub-state */
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        /* Nothing to do in this sub-state */
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        /* Nothing to do in this sub-state */
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        switch(ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                        #ifdef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                        #endif
-                            case rsa_sa_algo:
-                            {
-                                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                                if (args->verifySig == NULL) {
-                                    if (args->sigSz == 0) {
-                                        ERROR_OUT(BAD_COND_E, exit_sske);
-                                    }
-                                    args->verifySig = (byte*)XMALLOC(
-                                                    args->sigSz, ssl->heap,
-                                                    DYNAMIC_TYPE_SIGNATURE);
-                                    if (!args->verifySig) {
-                                        ERROR_OUT(MEMORY_E, exit_sske);
-                                    }
-                                    XMEMCPY(args->verifySig,
-                                        args->output + args->idx, args->sigSz);
-                                }
-
-                                /* check for signature faults */
-                                ret = VerifyRsaSign(ssl,
-                                    args->verifySig, args->sigSz,
-                                    ssl->buffers.sig.buffer,
-                                    ssl->buffers.sig.length,
-                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key, ssl->buffers.key
-                                );
-                                break;
-                            }
-                        #endif
-                            case ecc_dsa_sa_algo:
-                        #ifdef HAVE_ED25519
-                            case ed25519_sa_algo:
-                        #endif
-                            {
-                                /* Now that we know the real sig size, write it. */
-                                c16toa((word16)args->sigSz,
-                                                    args->output + args->idx);
-
-                                /* And adjust length and sendSz from estimates */
-                                args->length += args->sigSz - args->tmpSigSz;
-                                args->sendSz += args->sigSz - args->tmpSigSz;
-                                break;
-                            }
-                            default:
-                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
-                        } /* switch(ssl->specs.sig_algo) */
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #if !defined(NO_DH) && !defined(NO_RSA)
-                    case diffie_hellman_kea:
-                    {
-                        switch (ssl->suites->sigAlgo)
-                        {
-                        #ifndef NO_RSA
-                        #ifndef WC_RSA_PSS
-                            case rsa_pss_sa_algo:
-                        #endif
-                            case rsa_sa_algo:
-                            {
-                                RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                                if (ssl->options.usingAnon_cipher) {
-                                    break;
-                                }
-
-                                if (args->verifySig == NULL) {
-                                    if (args->sigSz == 0) {
-                                        ERROR_OUT(BAD_COND_E, exit_sske);
-                                    }
-                                    args->verifySig = (byte*)XMALLOC(
-                                                      args->sigSz, ssl->heap,
-                                                      DYNAMIC_TYPE_SIGNATURE);
-                                    if (!args->verifySig) {
-                                        ERROR_OUT(MEMORY_E, exit_sske);
-                                    }
-                                    XMEMCPY(args->verifySig,
-                                        args->output + args->idx, args->sigSz);
-                                }
-
-                                /* check for signature faults */
-                                ret = VerifyRsaSign(ssl,
-                                    args->verifySig, args->sigSz,
-                                    ssl->buffers.sig.buffer,
-                                    ssl->buffers.sig.length,
-                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
-                                    key, ssl->buffers.key
-                                );
-                                break;
-                            }
-                        #endif
-                        } /* switch (ssl->suites->sigAlgo) */
-                        break;
-                    }
-                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
-                } /* switch(ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_sske;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-            } /* case TLS_ASYNC_VERIFY */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_FINALIZE:
-            {
-            #ifdef HAVE_QSH
-                if (ssl->peerQSHKeyPresent) {
-                    if (args->qshSz > 0) {
-                        args->idx = args->sendSz - args->qshSz;
-                        if (QSH_KeyExchangeWrite(ssl, 1) != 0) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-
-                        /* extension type */
-                        c16toa(TLSX_QUANTUM_SAFE_HYBRID,
-                                                    args->output + args->idx);
-                        args->idx += OPAQUE16_LEN;
-
-                        /* write to output and check amount written */
-                        if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
-                            args->output + args->idx) >
-                                                args->qshSz - OPAQUE16_LEN) {
-                            ERROR_OUT(MEMORY_E, exit_sske);
-                        }
-                    }
-                }
-            #endif
-
-            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                if (ssl->specs.kea == ecdhe_psk_kea ||
-                    ssl->specs.kea == ecc_diffie_hellman_kea) {
-                    /* Check output to make sure it was set */
-                    if (args->output) {
-                        AddHeaders(args->output, args->length,
-                                                    server_key_exchange, ssl);
-                    }
-                    else {
-                        ERROR_OUT(BUFFER_ERROR, exit_sske);
-                    }
-                }
-            #endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-            #ifdef WOLFSSL_DTLS
-                if (IsDtlsNotSctpMode(ssl)) {
-                    if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
-                        goto exit_sske;
-                    }
-                }
-
-                if (ssl->options.dtls)
-                    DtlsSEQIncrement(ssl, CUR_ORDER);
-            #endif
-
-                ret = HashOutput(ssl, args->output, args->sendSz, 0);
-                if (ret != 0) {
-                    goto exit_sske;
-                }
-
-            #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-                if (ssl->hsInfoOn) {
-                    AddPacketName(ssl, "ServerKeyExchange");
-                }
-                if (ssl->toInfoOn) {
-                    AddPacketInfo(ssl, "ServerKeyExchange", handshake,
-                        args->output, args->sendSz, WRITE_PROTO, ssl->heap);
-                }
-            #endif
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_END;
-            } /* case TLS_ASYNC_FINALIZE */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_END:
-            {
-                ssl->buffers.outputBuffer.length += args->sendSz;
-                if (!ssl->options.groupMessages) {
-                    ret = SendBuffered(ssl);
-                }
-
-                ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
-                break;
-            }
-            default:
-                ret = INPUT_CASE_ERROR;
-        } /* switch(ssl->options.asyncState) */
-
-    exit_sske:
-
-        WOLFSSL_LEAVE("SendServerKeyExchange", ret);
-        WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* Handle async operation */
-        if (ret == WC_PENDING_E)
-            return ret;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        /* Final cleanup */
-        FreeSskeArgs(ssl, args);
-        FreeKeyExchange(ssl);
-
-        return ret;
-    }
-
-#ifdef HAVE_SERVER_RENEGOTIATION_INFO
-
-    /* search suites for specific one, idx on success, negative on error */
-    static int FindSuite(Suites* suites, byte first, byte second)
-    {
-        int i;
-
-        if (suites == NULL || suites->suiteSz == 0) {
-            WOLFSSL_MSG("Suites pointer error or suiteSz 0");
-            return SUITES_ERROR;
-        }
-
-        for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
-            if (suites->suites[i]   == first &&
-                suites->suites[i+1] == second )
-                return i;
-        }
-
-        return MATCH_SUITE_ERROR;
-    }
-
-#endif
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-    /* Make sure server cert/key are valid for this suite, true on success */
-    static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
-    {
-        int  haveRSA = !ssl->options.haveStaticECC;
-        int  havePSK = 0;
-        byte first;
-        byte second;
-
-        WOLFSSL_ENTER("VerifyServerSuite");
-
-        if (ssl->suites == NULL) {
-            WOLFSSL_MSG("Suites pointer error");
-            return 0;
-        }
-
-        first   = ssl->suites->suites[idx];
-        second  = ssl->suites->suites[idx+1];
-
-        #ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-        #endif
-
-        if (ssl->options.haveNTRU)
-            haveRSA = 0;
-
-        if (CipherRequires(first, second, REQUIRES_RSA)) {
-            WOLFSSL_MSG("Requires RSA");
-            if (haveRSA == 0) {
-                WOLFSSL_MSG("Don't have RSA");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_DHE)) {
-            WOLFSSL_MSG("Requires DHE");
-            if (ssl->options.haveDH == 0) {
-                WOLFSSL_MSG("Don't have DHE");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_ECC)) {
-            WOLFSSL_MSG("Requires ECC");
-            if (ssl->options.haveECC == 0) {
-                WOLFSSL_MSG("Don't have ECC");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_ECC_STATIC)) {
-            WOLFSSL_MSG("Requires static ECC");
-            if (ssl->options.haveStaticECC == 0) {
-                WOLFSSL_MSG("Don't have static ECC");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_PSK)) {
-            WOLFSSL_MSG("Requires PSK");
-            if (havePSK == 0) {
-                WOLFSSL_MSG("Don't have PSK");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_NTRU)) {
-            WOLFSSL_MSG("Requires NTRU");
-            if (ssl->options.haveNTRU == 0) {
-                WOLFSSL_MSG("Don't have NTRU");
-                return 0;
-            }
-        }
-
-        if (CipherRequires(first, second, REQUIRES_RSA_SIG)) {
-            WOLFSSL_MSG("Requires RSA Signature");
-            if (ssl->options.side == WOLFSSL_SERVER_END &&
-                                           ssl->options.haveECDSAsig == 1) {
-                WOLFSSL_MSG("Don't have RSA Signature");
-                return 0;
-            }
-        }
-
-#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                  defined(HAVE_SUPPORTED_CURVES)
-        if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
-            WOLFSSL_MSG("Don't have matching curves");
-            return 0;
-        }
-#endif
-
-        /* ECCDHE is always supported if ECC on */
-
-#ifdef HAVE_QSH
-        /* need to negotiate a classic suite in addition to TLS_QSH */
-        if (first == QSH_BYTE && second == TLS_QSH) {
-            if (TLSX_SupportExtensions(ssl)) {
-                ssl->options.haveQSH = 1; /* matched TLS_QSH */
-            }
-            else {
-                WOLFSSL_MSG("Version of SSL connection does not support "
-                            "TLS_QSH");
-            }
-            return 0;
-        }
-#endif
-
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(ssl->version) &&
-            ssl->options.side == WOLFSSL_SERVER_END) {
-            /* Try to establish a key share. */
-            int ret = TLSX_KeyShare_Establish(ssl);
-            if (ret == KEY_SHARE_ERROR)
-                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
-            else if (ret != 0)
-                return 0;
-        }
-        else if (first == TLS13_BYTE) {
-            /* Can't negotiate TLS 1.3 ciphersuites with lower protocol
-             * version. */
-            return 0;
-        }
-#endif
-
-        return 1;
-    }
-
-#ifndef NO_WOLFSSL_SERVER
-    static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i,
-                             word16 j)
-    {
-        if (ssl->suites->suites[i]   == peerSuites->suites[j] &&
-            ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
-
-            if (VerifyServerSuite(ssl, i)) {
-                int result;
-                WOLFSSL_MSG("Verified suite validity");
-                ssl->options.cipherSuite0 = ssl->suites->suites[i];
-                ssl->options.cipherSuite  = ssl->suites->suites[i+1];
-                result = SetCipherSpecs(ssl);
-                if (result == 0)
-                    PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
-                                    peerSuites->hashSigAlgoSz);
-                return result;
-            }
-            else {
-                WOLFSSL_MSG("Could not verify suite validity, continue");
-            }
-        }
-
-        return MATCH_SUITE_ERROR;
-    }
-
-    int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
-    {
-        int ret;
-        word16 i, j;
-
-        WOLFSSL_ENTER("MatchSuite");
-
-        /* & 0x1 equivalent % 2 */
-        if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
-            return MATCH_SUITE_ERROR;
-
-        if (ssl->suites == NULL)
-            return SUITES_ERROR;
-
-        if (!ssl->options.useClientOrder) {
-            /* Server order */
-            for (i = 0; i < ssl->suites->suiteSz; i += 2) {
-                for (j = 0; j < peerSuites->suiteSz; j += 2) {
-                    ret = CompareSuites(ssl, peerSuites, i, j);
-                    if (ret != MATCH_SUITE_ERROR)
-                        return ret;
-                }
-            }
-        }
-        else {
-            /* Client order */
-            for (j = 0; j < peerSuites->suiteSz; j += 2) {
-                for (i = 0; i < ssl->suites->suiteSz; i += 2) {
-                    ret = CompareSuites(ssl, peerSuites, i, j);
-                    if (ret != MATCH_SUITE_ERROR)
-                        return ret;
-                }
-            }
-        }
-
-        return MATCH_SUITE_ERROR;
-    }
-#endif
-
-#ifdef OLD_HELLO_ALLOWED
-
-    /* process old style client hello, deprecate? */
-    int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                              word32 inSz, word16 sz)
-    {
-        word32          idx = *inOutIdx;
-        word16          sessionSz;
-        word16          randomSz;
-        word16          i, j;
-        ProtocolVersion pv;
-        Suites          clSuites;
-        int ret = -1;
-
-        (void)inSz;
-        WOLFSSL_MSG("Got old format client hello");
-#ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "ClientHello");
-        if (ssl->toInfoOn)
-            AddLateName("ClientHello", &ssl->timeoutInfo);
-#endif
-
-        /* manually hash input since different format */
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
-        wc_Md5Update(&ssl->hsHashes->hashMd5, input + idx, sz);
-#endif
-#ifndef NO_SHA
-        wc_ShaUpdate(&ssl->hsHashes->hashSha, input + idx, sz);
-#endif
-#endif
-#ifndef NO_SHA256
-        if (IsAtLeastTLSv1_2(ssl)) {
-            int shaRet = wc_Sha256Update(&ssl->hsHashes->hashSha256,
-                                         input + idx, sz);
-            if (shaRet != 0)
-                return shaRet;
-        }
-#endif
-
-        /* does this value mean client_hello? */
-        idx++;
-
-        /* version */
-        pv.major = input[idx++];
-        pv.minor = input[idx++];
-        ssl->chVersion = pv;  /* store */
-
-        if (ssl->version.minor > pv.minor) {
-            byte haveRSA = 0;
-            byte havePSK = 0;
-            int  keySz   = 0;
-
-            if (!ssl->options.downgrade) {
-                WOLFSSL_MSG("Client trying to connect with lesser version");
-                return VERSION_ERROR;
-            }
-            if (pv.minor < ssl->options.minDowngrade) {
-                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
-                return VERSION_ERROR;
-            }
-            if (pv.minor == SSLv3_MINOR) {
-                /* turn off tls */
-                WOLFSSL_MSG("\tdowngrading to SSLv3");
-                ssl->options.tls    = 0;
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = SSLv3_MINOR;
-            }
-            else if (pv.minor == TLSv1_MINOR) {
-                WOLFSSL_MSG("\tdowngrading to TLSv1");
-                /* turn off tls 1.1+ */
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = TLSv1_MINOR;
-            }
-            else if (pv.minor == TLSv1_1_MINOR) {
-                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
-                ssl->version.minor  = TLSv1_1_MINOR;
-            }
-            else if (pv.minor == TLSv1_2_MINOR) {
-                WOLFSSL_MSG("    downgrading to TLSv1.2");
-                ssl->version.minor  = TLSv1_2_MINOR;
-            }
-#ifndef NO_RSA
-            haveRSA = 1;
-#endif
-#ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-#endif
-#ifndef NO_CERTS
-            keySz = ssl->buffers.keySz;
-#endif
-
-            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       ssl->options.haveDH, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-        }
-
-        /* suite size */
-        ato16(&input[idx], &clSuites.suiteSz);
-        idx += OPAQUE16_LEN;
-
-        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
-            return BUFFER_ERROR;
-        clSuites.hashSigAlgoSz = 0;
-
-        /* session size */
-        ato16(&input[idx], &sessionSz);
-        idx += OPAQUE16_LEN;
-
-        if (sessionSz > ID_LEN)
-            return BUFFER_ERROR;
-
-        /* random size */
-        ato16(&input[idx], &randomSz);
-        idx += OPAQUE16_LEN;
-
-        if (randomSz > RAN_LEN)
-            return BUFFER_ERROR;
-
-        /* suites */
-        for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
-            byte first = input[idx++];
-            if (!first) { /* implicit: skip sslv2 type */
-                XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN);
-                j += SUITE_LEN;
-            }
-            idx += SUITE_LEN;
-        }
-        clSuites.suiteSz = j;
-
-        /* session id */
-        if (sessionSz) {
-            XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
-            ssl->arrays->sessionIDSz = (byte)sessionSz;
-            idx += sessionSz;
-            ssl->options.resuming = 1;
-        }
-
-        /* random */
-        if (randomSz < RAN_LEN)
-            XMEMSET(ssl->arrays->clientRandom, 0, RAN_LEN - randomSz);
-        XMEMCPY(&ssl->arrays->clientRandom[RAN_LEN - randomSz], input + idx,
-               randomSz);
-        idx += randomSz;
-
-        if (ssl->options.usingCompression)
-            ssl->options.usingCompression = 0;  /* turn off */
-
-        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-        ssl->cbmode = SSL_CB_MODE_WRITE;
-        *inOutIdx = idx;
-
-        ssl->options.haveSessionId = 1;
-        /* DoClientHello uses same resume code */
-        if (ssl->options.resuming) {  /* let's try */
-            WOLFSSL_SESSION* session = GetSession(ssl,
-                                                  ssl->arrays->masterSecret, 1);
-            #ifdef HAVE_SESSION_TICKET
-                if (ssl->options.useTicket == 1) {
-                    session = &ssl->session;
-                }
-            #endif
-
-            if (!session) {
-                WOLFSSL_MSG("Session lookup for resume failed");
-                ssl->options.resuming = 0;
-            } else {
-            #ifdef HAVE_EXT_CACHE
-                wolfSSL_SESSION_free(session);
-            #endif
-                if (MatchSuite(ssl, &clSuites) < 0) {
-                    WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
-                    return UNSUPPORTED_SUITE;
-                }
-
-                ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
-                                                                       RAN_LEN);
-                if (ret != 0)
-                    return ret;
-
-                #ifdef NO_OLD_TLS
-                    ret = DeriveTlsKeys(ssl);
-                #else
-                    #ifndef NO_TLS
-                        if (ssl->options.tls)
-                            ret = DeriveTlsKeys(ssl);
-                    #endif
-                        if (!ssl->options.tls)
-                            ret = DeriveKeys(ssl);
-                #endif
-                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
-
-                return ret;
-            }
-        }
-
-        ret = MatchSuite(ssl, &clSuites);
-        if (ret != 0)return ret;
-        return SanityCheckMsgReceived(ssl, client_hello);
-    }
-
-#endif /* OLD_HELLO_ALLOWED */
-
-#ifndef WOLFSSL_NO_TLS12
-
-    int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites)
-    {
-        int ret = 0;
-        WOLFSSL_SESSION* session = GetSession(ssl,
-                                                  ssl->arrays->masterSecret, 1);
-
-        (void)bogusID;
-
-        #ifdef HAVE_SESSION_TICKET
-            if (ssl->options.useTicket == 1) {
-                session = &ssl->session;
-            } else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
-                WOLFSSL_MSG("Bogus session ID without session ticket");
-                return BUFFER_ERROR;
-            }
-        #endif
-
-        if (!session) {
-            WOLFSSL_MSG("Session lookup for resume failed");
-            ssl->options.resuming = 0;
-        }
-        else if (session->haveEMS != ssl->options.haveEMS) {
-            /* RFC 7627, 5.3, server-side */
-            /* if old sess didn't have EMS, but new does, full handshake */
-            if (!session->haveEMS && ssl->options.haveEMS) {
-                WOLFSSL_MSG("Attempting to resume a session that didn't "
-                            "use EMS with a new session with EMS. Do full "
-                            "handshake.");
-                ssl->options.resuming = 0;
-            }
-            /* if old sess used EMS, but new doesn't, MUST abort */
-            else if (session->haveEMS && !ssl->options.haveEMS) {
-                WOLFSSL_MSG("Trying to resume a session with EMS without "
-                            "using EMS");
-                return EXT_MASTER_SECRET_NEEDED_E;
-            }
-        #ifdef HAVE_EXT_CACHE
-            wolfSSL_SESSION_free(session);
-        #endif
-        }
-        else {
-        #ifdef HAVE_EXT_CACHE
-            wolfSSL_SESSION_free(session);
-        #endif
-            if (MatchSuite(ssl, clSuites) < 0) {
-                WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
-                return UNSUPPORTED_SUITE;
-            }
-
-            ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
-                                                                       RAN_LEN);
-            if (ret != 0)
-                return ret;
-
-            #ifdef NO_OLD_TLS
-                ret = DeriveTlsKeys(ssl);
-            #else
-                #ifndef NO_TLS
-                    if (ssl->options.tls)
-                        ret = DeriveTlsKeys(ssl);
-                #endif
-                    if (!ssl->options.tls)
-                        ret = DeriveKeys(ssl);
-            #endif
-            ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
-        }
-
-        return ret;
-    }
-
-
-    /* handle processing of client_hello (1) */
-    int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                             word32 helloSz)
-    {
-        byte            b;
-        byte            bogusID = 0;   /* flag for a bogus session id */
-        ProtocolVersion pv;
-        Suites          clSuites;
-        word32          i = *inOutIdx;
-        word32          begin = i;
-        int             ret = 0;
-#ifdef WOLFSSL_DTLS
-        Hmac            cookieHmac;
-        byte            peerCookie[MAX_COOKIE_LEN];
-        byte            peerCookieSz = 0;
-        byte            cookieType;
-        byte            cookieSz = 0;
-
-        XMEMSET(&cookieHmac, 0, sizeof(Hmac));
-#endif /* WOLFSSL_DTLS */
-
-        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
-        WOLFSSL_ENTER("DoClientHello");
-
-#ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
-        if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
-#endif
-        /* protocol version, random and session id length check */
-        if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
-            return BUFFER_ERROR;
-
-        /* protocol version */
-        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-        ssl->chVersion = pv;   /* store */
-#ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            #if defined(NO_SHA) && defined(NO_SHA256)
-                #error "DTLS needs either SHA or SHA-256"
-            #endif /* NO_SHA && NO_SHA256 */
-
-            #if !defined(NO_SHA) && defined(NO_SHA256)
-                cookieType = WC_SHA;
-                cookieSz = WC_SHA_DIGEST_SIZE;
-            #endif /* NO_SHA */
-            #ifndef NO_SHA256
-                cookieType = WC_SHA256;
-                cookieSz = WC_SHA256_DIGEST_SIZE;
-            #endif /* NO_SHA256 */
-            ret = wc_HmacSetKey(&cookieHmac, cookieType,
-                                ssl->buffers.dtlsCookieSecret.buffer,
-                                ssl->buffers.dtlsCookieSecret.length);
-            if (ret != 0) return ret;
-            ret = wc_HmacUpdate(&cookieHmac,
-                                (const byte*)ssl->buffers.dtlsCtx.peer.sa,
-                                ssl->buffers.dtlsCtx.peer.sz);
-            if (ret != 0) return ret;
-            ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
-            if (ret != 0) return ret;
-        }
-#endif /* WOLFSSL_DTLS */
-        i += OPAQUE16_LEN;
-
-        /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
-        if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
-            pv.minor = TLSv1_2_MINOR;
-
-        if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
-            (ssl->options.dtls && ssl->version.minor != DTLS_MINOR
-             && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
-             && pv.minor != DTLSv1_2_MINOR)) {
-
-            word16 haveRSA = 0;
-            word16 havePSK = 0;
-            int    keySz   = 0;
-
-            if (!ssl->options.downgrade) {
-                WOLFSSL_MSG("Client trying to connect with lesser version");
-                return VERSION_ERROR;
-            }
-            if (pv.minor < ssl->options.minDowngrade) {
-                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
-                return VERSION_ERROR;
-            }
-
-            if (pv.minor == SSLv3_MINOR) {
-                /* turn off tls */
-                WOLFSSL_MSG("\tdowngrading to SSLv3");
-                ssl->options.tls    = 0;
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = SSLv3_MINOR;
-            }
-            else if (pv.minor == TLSv1_MINOR) {
-                /* turn off tls 1.1+ */
-                WOLFSSL_MSG("\tdowngrading to TLSv1");
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor  = TLSv1_MINOR;
-            }
-            else if (pv.minor == TLSv1_1_MINOR) {
-                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
-                ssl->version.minor  = TLSv1_1_MINOR;
-            }
-            else if (pv.minor == TLSv1_2_MINOR) {
-                WOLFSSL_MSG("    downgrading to TLSv1.2");
-                ssl->version.minor  = TLSv1_2_MINOR;
-            }
-#ifndef NO_RSA
-            haveRSA = 1;
-#endif
-#ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-#endif
-#ifndef NO_CERTS
-            keySz = ssl->buffers.keySz;
-#endif
-            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       ssl->options.haveDH, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-        }
-
-#ifdef OPENSSL_EXTRA
-        /* check if option is set to not allow the current version
-         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
-        if (!ssl->options.dtls && ssl->options.downgrade &&
-                ssl->options.mask > 0) {
-            int reset = 0;
-            if (ssl->version.minor == TLSv1_2_MINOR &&
-             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
-                ssl->version.minor = TLSv1_1_MINOR;
-                reset = 1;
-            }
-            if (ssl->version.minor == TLSv1_1_MINOR &&
-             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor = TLSv1_MINOR;
-                reset = 1;
-            }
-            if (ssl->version.minor == TLSv1_MINOR &&
-                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
-                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
-                ssl->options.tls    = 0;
-                ssl->options.tls1_1 = 0;
-                ssl->version.minor = SSLv3_MINOR;
-                reset = 1;
-            }
-            if (ssl->version.minor == SSLv3_MINOR &&
-                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
-                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
-                return VERSION_ERROR;
-            }
-
-            if (ssl->version.minor < ssl->options.minDowngrade) {
-                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
-                return VERSION_ERROR;
-            }
-
-            if (reset) {
-                word16 haveRSA = 0;
-                word16 havePSK = 0;
-                int    keySz   = 0;
-
-            #ifndef NO_RSA
-                haveRSA = 1;
-            #endif
-            #ifndef NO_PSK
-                havePSK = ssl->options.havePSK;
-            #endif
-            #ifndef NO_CERTS
-                keySz = ssl->buffers.keySz;
-            #endif
-
-                /* reset cipher suites to account for TLS version change */
-                InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       ssl->options.haveDH, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-            }
-        }
-#endif
-
-        /* random */
-        XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
-#ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
-            if (ret != 0) return ret;
-        }
-#endif /* WOLFSSL_DTLS */
-        i += RAN_LEN;
-
-#ifdef SHOW_SECRETS
-        {
-            int j;
-            printf("client random: ");
-            for (j = 0; j < RAN_LEN; j++)
-                printf("%02x", ssl->arrays->clientRandom[j]);
-            printf("\n");
-        }
-#endif
-
-        /* session id */
-        b = input[i++];
-
-#ifdef HAVE_SESSION_TICKET
-        if (b > 0 && b < ID_LEN) {
-            bogusID = 1;
-            WOLFSSL_MSG("Client sent bogus session id, let's allow for echo");
-        }
-#endif
-
-        if (b == ID_LEN || bogusID) {
-            if ((i - begin) + b > helloSz)
-                return BUFFER_ERROR;
-
-            XMEMCPY(ssl->arrays->sessionID, input + i, b);
-#ifdef WOLFSSL_DTLS
-            if (IsDtlsNotSctpMode(ssl)) {
-                ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
-                if (ret != 0) return ret;
-            }
-#endif /* WOLFSSL_DTLS */
-            ssl->arrays->sessionIDSz = b;
-            i += b;
-            ssl->options.resuming = 1; /* client wants to resume */
-            WOLFSSL_MSG("Client wants to resume session");
-        }
-        else if (b) {
-            WOLFSSL_MSG("Invalid session ID size");
-            return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
-        }
-
-        #ifdef WOLFSSL_DTLS
-            /* cookie */
-            if (ssl->options.dtls) {
-
-                if ((i - begin) + OPAQUE8_LEN > helloSz)
-                    return BUFFER_ERROR;
-
-                peerCookieSz = input[i++];
-
-                if (peerCookieSz) {
-                    if (peerCookieSz > MAX_COOKIE_LEN)
-                        return BUFFER_ERROR;
-
-                    if ((i - begin) + peerCookieSz > helloSz)
-                        return BUFFER_ERROR;
-
-                    XMEMCPY(peerCookie, input + i, peerCookieSz);
-
-                    i += peerCookieSz;
-                }
-            }
-        #endif
-
-        /* suites */
-        if ((i - begin) + OPAQUE16_LEN > helloSz)
-            return BUFFER_ERROR;
-
-        ato16(&input[i], &clSuites.suiteSz);
-        i += OPAQUE16_LEN;
-
-        /* suites and compression length check */
-        if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
-            return BUFFER_ERROR;
-
-        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
-            return BUFFER_ERROR;
-
-        XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
-
-#ifdef HAVE_SERVER_RENEGOTIATION_INFO
-        /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
-        if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
-            ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
-            if (ret != WOLFSSL_SUCCESS)
-                return ret;
-        }
-#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
-
-#ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            ret = wc_HmacUpdate(&cookieHmac,
-                                    input + i - OPAQUE16_LEN,
-                                    clSuites.suiteSz + OPAQUE16_LEN);
-            if (ret != 0) return ret;
-        }
-#endif /* WOLFSSL_DTLS */
-        i += clSuites.suiteSz;
-        clSuites.hashSigAlgoSz = 0;
-
-        /* compression length */
-        b = input[i++];
-
-        if ((i - begin) + b > helloSz)
-            return BUFFER_ERROR;
-
-        if (b == 0) {
-            WOLFSSL_MSG("No compression types in list");
-            return COMPRESSION_ERROR;
-        }
-
-#ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            byte newCookie[MAX_COOKIE_LEN];
-
-            ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
-            if (ret != 0) return ret;
-            ret = wc_HmacFinal(&cookieHmac, newCookie);
-            if (ret != 0) return ret;
-
-            /* If a cookie callback is set, call it to overwrite the cookie.
-             * This should be deprecated. The code now calculates the cookie
-             * using an HMAC as expected. */
-            if (ssl->ctx->CBIOCookie != NULL &&
-                ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
-                                             ssl->IOCB_CookieCtx) != cookieSz) {
-                return COOKIE_ERROR;
-            }
-
-            /* Check the cookie, see if we progress the state machine. */
-            if (peerCookieSz != cookieSz ||
-                XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
-
-                /* Send newCookie to client in a HelloVerifyRequest message
-                 * and let the state machine alone. */
-                ssl->msgsReceived.got_client_hello = 0;
-                ssl->keys.dtls_handshake_number = 0;
-                ssl->keys.dtls_expected_peer_handshake_number = 0;
-                *inOutIdx += helloSz;
-                return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
-            }
-
-            /* This was skipped in the DTLS case so we could handle the hello
-             * verify request. */
-            ret = HashInput(ssl, input + *inOutIdx, helloSz);
-            if (ret != 0) return ret;
-        }
-#endif /* WOLFSSL_DTLS */
-
-        {
-            /* copmression match types */
-            int matchNo = 0;
-            int matchZlib = 0;
-
-            while (b--) {
-                byte comp = input[i++];
-
-                if (comp == NO_COMPRESSION) {
-                    matchNo = 1;
-                }
-                if (comp == ZLIB_COMPRESSION) {
-                    matchZlib = 1;
-                }
-            }
-
-            if (ssl->options.usingCompression == 0 && matchNo) {
-                WOLFSSL_MSG("Matched No Compression");
-            } else if (ssl->options.usingCompression && matchZlib) {
-                WOLFSSL_MSG("Matched zlib Compression");
-            } else if (ssl->options.usingCompression && matchNo) {
-                WOLFSSL_MSG("Could only match no compression, turning off");
-                ssl->options.usingCompression = 0;  /* turn off */
-            } else {
-                WOLFSSL_MSG("Could not match compression");
-                return COMPRESSION_ERROR;
-            }
-        }
-
-        *inOutIdx = i;
-
-        /* tls extensions */
-        if ((i - begin) < helloSz) {
-#ifdef HAVE_TLS_EXTENSIONS
-        #ifdef HAVE_QSH
-            QSH_Init(ssl);
-        #endif
-            if (TLSX_SupportExtensions(ssl))
-#else
-            if (IsAtLeastTLSv1_2(ssl))
-#endif
-            {
-                /* Process the hello extension. Skip unsupported. */
-                word16 totalExtSz;
-
-#ifdef HAVE_TLS_EXTENSIONS
-                /* auto populate extensions supported unless user defined */
-                if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
-                    return ret;
-#endif
-
-                if ((i - begin) + OPAQUE16_LEN > helloSz)
-                    return BUFFER_ERROR;
-
-                ato16(&input[i], &totalExtSz);
-                i += OPAQUE16_LEN;
-
-                if ((i - begin) + totalExtSz > helloSz)
-                    return BUFFER_ERROR;
-
-#ifdef HAVE_TLS_EXTENSIONS
-                /* tls extensions */
-                if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
-                                      client_hello, &clSuites)))
-                    return ret;
-    #ifdef WOLFSSL_TLS13
-                if (TLSX_Find(ssl->extensions,
-                                             TLSX_SUPPORTED_VERSIONS) != NULL) {
-                    WOLFSSL_MSG(
-                            "Client attempting to connect with higher version");
-                    return VERSION_ERROR;
-                }
-    #endif
-    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-                if((ret=SNI_Callback(ssl)))
-                    return ret;
-                ssl->options.side = WOLFSSL_SERVER_END;
-    #endif
-
-                i += totalExtSz;
-#else
-                while (totalExtSz) {
-                    word16 extId, extSz;
-
-                    if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
-                        return BUFFER_ERROR;
-
-                    ato16(&input[i], &extId);
-                    i += OPAQUE16_LEN;
-                    ato16(&input[i], &extSz);
-                    i += OPAQUE16_LEN;
-
-                    if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
-                        return BUFFER_ERROR;
-
-                    if (extId == HELLO_EXT_SIG_ALGO) {
-                        word16 hashSigAlgoSz;
-
-                        ato16(&input[i], &hashSigAlgoSz);
-                        i += OPAQUE16_LEN;
-
-                        if (OPAQUE16_LEN + hashSigAlgoSz > extSz)
-                            return BUFFER_ERROR;
-
-                        clSuites.hashSigAlgoSz = hashSigAlgoSz;
-                        if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
-                            WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
-                                                                  "truncating");
-                            clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
-                        }
-
-                        XMEMCPY(clSuites.hashSigAlgo, &input[i],
-                                                      clSuites.hashSigAlgoSz);
-
-                        i += hashSigAlgoSz;
-                    }
-#ifdef HAVE_EXTENDED_MASTER
-                    else if (extId == HELLO_EXT_EXTMS)
-                        ssl->options.haveEMS = 1;
-#endif
-                    else
-                        i += extSz;
-
-                    totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
-                }
-#endif
-                *inOutIdx = i;
-            }
-            else
-                *inOutIdx = begin + helloSz; /* skip extensions */
-        }
-
-        ssl->options.clientState   = CLIENT_HELLO_COMPLETE;
-        ssl->options.haveSessionId = 1;
-
-        /* ProcessOld uses same resume code */
-        if (ssl->options.resuming) {
-            ret = HandleTlsResumption(ssl, bogusID, &clSuites);
-            if (ret != 0)
-                return ret;
-            if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
-                WOLFSSL_LEAVE("DoClientHello", ret);
-                WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
-
-                return ret;
-            }
-        }
-        ret = MatchSuite(ssl, &clSuites);
-
-        WOLFSSL_LEAVE("DoClientHello", ret);
-        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
-
-        return ret;
-    }
-
-
-#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
-                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
-
-    typedef struct DcvArgs {
-        byte*  output; /* not allocated */
-        word32 sendSz;
-        word16 sz;
-        word32 sigSz;
-        word32 idx;
-        word32 begin;
-        byte   hashAlgo;
-        byte   sigAlgo;
-    } DcvArgs;
-
-    static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs)
-    {
-        DcvArgs* args = (DcvArgs*)pArgs;
-
-        (void)ssl;
-        (void)args;
-    }
-
-    /* handle processing of certificate_verify (15) */
-    static int DoCertificateVerify(WOLFSSL* ssl, byte* input,
-                                word32* inOutIdx, word32 size)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        DcvArgs* args = (DcvArgs*)ssl->async.args;
-        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-        (void)sizeof(args_test);
-    #else
-        DcvArgs  args[1];
-    #endif
-
-        WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
-        WOLFSSL_ENTER("DoCertificateVerify");
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-        if (ret != WC_NOT_PENDING_E) {
-            /* Check for error */
-            if (ret < 0)
-                goto exit_dcv;
-        }
-        else
-    #endif
-        {
-            /* Reset state */
-            ret = 0;
-            ssl->options.asyncState = TLS_ASYNC_BEGIN;
-            XMEMSET(args, 0, sizeof(DcvArgs));
-            args->hashAlgo = sha_mac;
-            args->sigAlgo = anonymous_sa_algo;
-            args->idx = *inOutIdx;
-            args->begin = *inOutIdx;
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            ssl->async.freeArgs = FreeDcvArgs;
-        #endif
-        }
-
-        switch(ssl->options.asyncState)
-        {
-            case TLS_ASYNC_BEGIN:
-            {
-            #ifdef WOLFSSL_CALLBACKS
-                if (ssl->hsInfoOn)
-                    AddPacketName(ssl, "CertificateVerify");
-                if (ssl->toInfoOn)
-                    AddLateName("CertificateVerify", &ssl->timeoutInfo);
-            #endif
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_BUILD;
-            } /* case TLS_ASYNC_BEGIN */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_BUILD:
-            {
-                if (IsAtLeastTLSv1_2(ssl)) {
-                    if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) {
-                        ERROR_OUT(BUFFER_ERROR, exit_dcv);
-                    }
-
-                    DecodeSigAlg(&input[args->idx], &args->hashAlgo,
-                                 &args->sigAlgo);
-                    args->idx += 2;
-                }
-            #ifndef NO_RSA
-                else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0)
-                    args->sigAlgo = rsa_sa_algo;
-            #endif
-            #ifdef HAVE_ECC
-                else if (ssl->peerEccDsaKeyPresent)
-                    args->sigAlgo = ecc_dsa_sa_algo;
-            #endif
-            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
-                else if (ssl->peerEd25519KeyPresent)
-                    args->sigAlgo = ed25519_sa_algo;
-            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
-
-                if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
-                }
-
-                ato16(input + args->idx, &args->sz);
-                args->idx += OPAQUE16_LEN;
-
-                if ((args->idx - args->begin) + args->sz > size ||
-                                                    args->sz > ENCRYPT_LEN) {
-                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
-                }
-
-            #ifdef HAVE_ECC
-                if (ssl->peerEccDsaKeyPresent) {
-
-                    WOLFSSL_MSG("Doing ECC peer cert verify");
-
-                /* make sure a default is defined */
-                #if !defined(NO_SHA)
-                    SetDigest(ssl, sha_mac);
-                #elif !defined(NO_SHA256)
-                    SetDigest(ssl, sha256_mac);
-                #elif defined(WOLFSSL_SHA384)
-                    SetDigest(ssl, sha384_mac);
-                #elif defined(WOLFSSL_SHA512)
-                    SetDigest(ssl, sha512_mac);
-                #else
-                    #error No digest enabled for ECC sig verify
-                #endif
-
-                    if (IsAtLeastTLSv1_2(ssl)) {
-                        if (args->sigAlgo != ecc_dsa_sa_algo) {
-                            WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
-                        }
-
-                        SetDigest(ssl, args->hashAlgo);
-                    }
-                }
-            #endif /* HAVE_ECC */
-            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
-                if (ssl->peerEd25519KeyPresent) {
-                    WOLFSSL_MSG("Doing ED25519 peer cert verify");
-                    if (IsAtLeastTLSv1_2(ssl) &&
-                                             args->sigAlgo != ed25519_sa_algo) {
-                        WOLFSSL_MSG(
-                               "Oops, peer sent ED25519 key but not in verify");
-                    }
-                }
-            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_DO;
-            } /* case TLS_ASYNC_BUILD */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_DO:
-            {
-            #ifndef NO_RSA
-                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
-                    WOLFSSL_MSG("Doing RSA peer cert verify");
-
-                    ret = RsaVerify(ssl,
-                        input + args->idx,
-                        args->sz,
-                        &args->output,
-                        args->sigAlgo, args->hashAlgo,
-                        ssl->peerRsaKey,
-                    #ifdef HAVE_PK_CALLBACKS
-                        &ssl->buffers.peerRsaKey
-                    #else
-                        NULL
-                    #endif
-                    );
-                    if (ret >= 0) {
-                        if (args->sigAlgo == rsa_sa_algo)
-                            args->sendSz = ret;
-                        else {
-                            args->sigSz = ret;
-                            args->sendSz = ssl->buffers.digest.length;
-                        }
-                        ret = 0;
-                    }
-                }
-            #endif /* !NO_RSA */
-            #ifdef HAVE_ECC
-                if (ssl->peerEccDsaKeyPresent) {
-                    WOLFSSL_MSG("Doing ECC peer cert verify");
-
-                    ret = EccVerify(ssl,
-                        input + args->idx, args->sz,
-                        ssl->buffers.digest.buffer, ssl->buffers.digest.length,
-                        ssl->peerEccDsaKey,
-                    #ifdef HAVE_PK_CALLBACKS
-                        &ssl->buffers.peerEccDsaKey
-                    #else
-                        NULL
-                    #endif
-                    );
-                }
-            #endif /* HAVE_ECC */
-            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
-                if (ssl->peerEd25519KeyPresent) {
-                    WOLFSSL_MSG("Doing Ed25519 peer cert verify");
-
-                    ret = Ed25519Verify(ssl,
-                        input + args->idx, args->sz,
-                        ssl->hsHashes->messages, ssl->hsHashes->prevLen,
-                        ssl->peerEd25519Key,
-                    #ifdef HAVE_PK_CALLBACKS
-                        &ssl->buffers.peerEd25519Key
-                    #else
-                        NULL
-                    #endif
-                    );
-                }
-            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcv;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_VERIFY;
-            } /* case TLS_ASYNC_DO */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_VERIFY:
-            {
-            #ifndef NO_RSA
-                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
-                    if (IsAtLeastTLSv1_2(ssl)) {
-                    #ifdef WC_RSA_PSS
-                        if (args->sigAlgo == rsa_pss_sa_algo) {
-                            SetDigest(ssl, args->hashAlgo);
-
-                            ret = wc_RsaPSS_CheckPadding(
-                                             ssl->buffers.digest.buffer,
-                                             ssl->buffers.digest.length,
-                                             args->output, args->sigSz,
-                                             HashAlgoToType(args->hashAlgo));
-                            if (ret != 0)
-                                goto exit_dcv;
-                        }
-                        else
-                    #endif
-                        {
-                        #ifdef WOLFSSL_SMALL_STACK
-                            byte* encodedSig = NULL;
-                        #else
-                            byte  encodedSig[MAX_ENCODED_SIG_SZ];
-                        #endif
-
-                        #ifdef WOLFSSL_SMALL_STACK
-                            encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
-                                                ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                            if (encodedSig == NULL) {
-                                ERROR_OUT(MEMORY_E, exit_dcv);
-                            }
-                        #endif
-
-                            if (args->sigAlgo != rsa_sa_algo) {
-                                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
-                            }
-
-                            SetDigest(ssl, args->hashAlgo);
-
-                            args->sigSz = wc_EncodeSignature(encodedSig,
-                                ssl->buffers.digest.buffer,
-                                ssl->buffers.digest.length,
-                                TypeHash(args->hashAlgo));
-
-                            if (args->sendSz != args->sigSz || !args->output ||
-                                XMEMCMP(args->output, encodedSig,
-                                    min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) {
-                                ret = VERIFY_CERT_ERROR;
-                            }
-
-                        #ifdef WOLFSSL_SMALL_STACK
-                            XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-                        #endif
-                        }
-                    }
-                    else {
-                        if (args->sendSz != FINISHED_SZ || !args->output ||
-                            XMEMCMP(args->output,
-                                &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) {
-                            ret = VERIFY_CERT_ERROR;
-                        }
-                    }
-                }
-            #endif /* !NO_RSA */
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-            } /* case TLS_ASYNC_VERIFY */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_FINALIZE:
-            {
-                ssl->options.havePeerVerify = 1;
-
-                /* Set final index */
-                args->idx += args->sz;
-                *inOutIdx = args->idx;
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_END;
-            } /* case TLS_ASYNC_FINALIZE */
-
-            case TLS_ASYNC_END:
-            {
-                break;
-            }
-            default:
-                ret = INPUT_CASE_ERROR;
-        } /* switch(ssl->options.asyncState) */
-
-    exit_dcv:
-
-        WOLFSSL_LEAVE("DoCertificateVerify", ret);
-        WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* Handle async operation */
-        if (ret == WC_PENDING_E) {
-            /* Mark message as not recevied so it can process again */
-            ssl->msgsReceived.got_certificate_verify = 0;
-
-            return ret;
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-    #ifdef OPENSSL_EXTRA
-        if (ret != 0){
-             SendAlert(ssl, alert_fatal, bad_certificate);
-        }
-    #endif
-        /* Digest is not allocated, so do this to prevent free */
-        ssl->buffers.digest.buffer = NULL;
-        ssl->buffers.digest.length = 0;
-
-        /* Final cleanup */
-        FreeDcvArgs(ssl, args);
-        FreeKeyExchange(ssl);
-
-        return ret;
-    }
-
-#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
-
-    /* handle generation of server_hello_done (14) */
-    int SendServerHelloDone(WOLFSSL* ssl)
-    {
-        byte* output;
-        int   sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-        int   ret;
-
-        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND);
-        WOLFSSL_ENTER("SendServerHelloDone");
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls)
-            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-    #endif
-
-        /* check for available size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        AddHeaders(output, 0, server_hello_done, ssl);
-
-    #ifdef WOLFSSL_DTLS
-        if (IsDtlsNotSctpMode(ssl)) {
-            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                return 0;
-        }
-
-        if (ssl->options.dtls)
-            DtlsSEQIncrement(ssl, CUR_ORDER);
-    #endif
-
-        ret = HashOutput(ssl, output, sendSz, 0);
-            if (ret != 0)
-                return ret;
-
-    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "ServerHelloDone");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz,
-                    WRITE_PROTO, ssl->heap);
-    #endif
-        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
-
-        ssl->buffers.outputBuffer.length += sendSz;
-
-        ret = SendBuffered(ssl);
-
-        WOLFSSL_LEAVE("SendServerHelloDone", ret);
-        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND);
-
-        return ret;
-    }
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef HAVE_SESSION_TICKET
-
-#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \
-                WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ)
-#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ)
-
-    /* our ticket format */
-    typedef struct InternalTicket {
-        ProtocolVersion pv;                    /* version when ticket created */
-        byte            suite[SUITE_LEN];      /* cipher suite when created */
-        byte            msecret[SECRET_LEN];   /* master secret */
-        word32          timestamp;             /* born on */
-        word16          haveEMS;               /* have extended master secret */
-#ifdef WOLFSSL_TLS13
-        word32          ageAdd;                /* Obfuscation of age */
-        word16          namedGroup;            /* Named group used */
-    #ifndef WOLFSSL_TLS13_DRAFT_18
-        TicketNonce     ticketNonce;           /* Ticket nonce */
-    #endif
-    #ifdef WOLFSSL_EARLY_DATA
-        word32          maxEarlyDataSz;        /* Max size of early data */
-    #endif
-#endif
-    } InternalTicket;
-
-    /* fit within SESSION_TICKET_LEN */
-    typedef struct ExternalTicket {
-        byte key_name[WOLFSSL_TICKET_NAME_SZ];  /* key context name */
-        byte iv[WOLFSSL_TICKET_IV_SZ];          /* this ticket's iv */
-        byte enc_len[LENGTH_SZ];                /* encrypted length */
-        byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */
-        byte mac[WOLFSSL_TICKET_MAC_SZ];        /* total mac */
-        /* !! if add to structure, add to TICKET_FIXED_SZ !! */
-    } ExternalTicket;
-
-    /* create a new session ticket, 0 on success */
-    int CreateTicket(WOLFSSL* ssl)
-    {
-        InternalTicket  it;
-        ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
-        int encLen;
-        int ret;
-        byte zeros[WOLFSSL_TICKET_MAC_SZ];   /* biggest cmp size */
-
-        XMEMSET(&it, 0, sizeof(it));
-
-        /* build internal */
-        it.pv.major = ssl->version.major;
-        it.pv.minor = ssl->version.minor;
-
-        it.suite[0] = ssl->options.cipherSuite0;
-        it.suite[1] = ssl->options.cipherSuite;
-
-    #ifdef WOLFSSL_EARLY_DATA
-        it.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
-    #endif
-
-        if (!ssl->options.tls1_3) {
-            XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
-            c32toa(LowResTimer(), (byte*)&it.timestamp);
-            it.haveEMS = ssl->options.haveEMS;
-        }
-        else {
-#ifdef WOLFSSL_TLS13
-            /* Client adds to ticket age to obfuscate. */
-            ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd,
-                                                             sizeof(it.ageAdd));
-            if (ret != 0)
-                return BAD_TICKET_ENCRYPT;
-            ssl->session.ticketAdd = it.ageAdd;
-            it.namedGroup = ssl->session.namedGroup;
-            it.timestamp = TimeNowInMilliseconds();
-            /* Resumption master secret. */
-            XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN);
-    #ifndef WOLFSSL_TLS13_DRAFT_18
-            XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce,
-                                                           sizeof(TicketNonce));
-    #endif
-#endif
-        }
-
-        /* build external */
-        XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
-
-        /* encrypt */
-        encLen = WOLFSSL_TICKET_ENC_SZ;  /* max size user can use */
-        ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
-                                    et->enc_ticket, sizeof(InternalTicket),
-                                    &encLen, ssl->ctx->ticketEncCtx);
-        if (ret == WOLFSSL_TICKET_RET_OK) {
-            if (encLen < (int)sizeof(InternalTicket) ||
-                encLen > WOLFSSL_TICKET_ENC_SZ) {
-                WOLFSSL_MSG("Bad user ticket encrypt size");
-                return BAD_TICKET_KEY_CB_SZ;
-            }
-
-            /* sanity checks on encrypt callback */
-
-            /* internal ticket can't be the same if encrypted */
-            if (XMEMCMP(et->enc_ticket, &it, sizeof(InternalTicket)) == 0) {
-                WOLFSSL_MSG("User ticket encrypt didn't encrypt");
-                return BAD_TICKET_ENCRYPT;
-            }
-
-            XMEMSET(zeros, 0, sizeof(zeros));
-
-            /* name */
-            if (XMEMCMP(et->key_name, zeros, WOLFSSL_TICKET_NAME_SZ) == 0) {
-                WOLFSSL_MSG("User ticket encrypt didn't set name");
-                return BAD_TICKET_ENCRYPT;
-            }
-
-            /* iv */
-            if (XMEMCMP(et->iv, zeros, WOLFSSL_TICKET_IV_SZ) == 0) {
-                WOLFSSL_MSG("User ticket encrypt didn't set iv");
-                return BAD_TICKET_ENCRYPT;
-            }
-
-            /* mac */
-            if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
-                WOLFSSL_MSG("User ticket encrypt didn't set mac");
-                return BAD_TICKET_ENCRYPT;
-            }
-
-            /* set size */
-            c16toa((word16)encLen, et->enc_len);
-            ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ);
-            if (encLen < WOLFSSL_TICKET_ENC_SZ) {
-                /* move mac up since whole enc buffer not used */
-                XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ);
-            }
-        }
-
-        return ret;
-    }
-
-
-    /* Parse ticket sent by client, returns callback return value */
-    int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
-    {
-        ExternalTicket* et;
-        InternalTicket* it;
-        int             ret;
-        int             outLen;
-        word16          inLen;
-
-        WOLFSSL_START(WC_FUNC_TICKET_DO);
-        WOLFSSL_ENTER("DoClientTicket");
-
-        if (len > SESSION_TICKET_LEN ||
-             len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
-            return BAD_TICKET_MSG_SZ;
-        }
-
-        et = (ExternalTicket*)input;
-        it = (InternalTicket*)et->enc_ticket;
-
-        /* decrypt */
-        ato16(et->enc_len, &inLen);
-        if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) {
-            return BAD_TICKET_MSG_SZ;
-        }
-        outLen = inLen;   /* may be reduced by user padding */
-        ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
-                                    et->enc_ticket + inLen, 0,
-                                    et->enc_ticket, inLen, &outLen,
-                                    ssl->ctx->ticketEncCtx);
-        if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
-        if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) {
-            WOLFSSL_MSG("Bad user ticket decrypt len");
-            return BAD_TICKET_KEY_CB_SZ;
-        }
-
-        /* get master secret */
-        if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
-            if (ssl->version.minor < it->pv.minor) {
-                WOLFSSL_MSG("Ticket has greater version");
-                return VERSION_ERROR;
-            }
-            else if (ssl->version.minor > it->pv.minor) {
-                if (!ssl->options.downgrade) {
-                    WOLFSSL_MSG("Ticket has lesser version");
-                    return VERSION_ERROR;
-                }
-
-                WOLFSSL_MSG("Downgrading protocol due to ticket");
-
-                if (it->pv.minor < ssl->options.minDowngrade)
-                    return VERSION_ERROR;
-                ssl->version.minor = it->pv.minor;
-            }
-
-            if (!IsAtLeastTLSv1_3(ssl->version)) {
-                XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
-                /* Copy the haveExtendedMasterSecret property from the ticket to
-                 * the saved session, so the property may be checked later. */
-                ssl->session.haveEMS = it->haveEMS;
-            }
-            else {
-#ifdef WOLFSSL_TLS13
-                /* Restore information to renegotiate. */
-                ssl->session.ticketSeen = it->timestamp;
-                ssl->session.ticketAdd = it->ageAdd;
-                ssl->session.cipherSuite0 = it->suite[0];
-                ssl->session.cipherSuite = it->suite[1];
-    #ifdef WOLFSSL_EARLY_DATA
-                ssl->session.maxEarlyDataSz = it->maxEarlyDataSz;
-    #endif
-                /* Resumption master secret. */
-                XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN);
-    #ifndef WOLFSSL_TLS13_DRAFT_18
-                XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce,
-                                                           sizeof(TicketNonce));
-    #endif
-                ssl->session.namedGroup = it->namedGroup;
-#endif
-            }
-        }
-
-        WOLFSSL_LEAVE("DoClientTicket", ret);
-        WOLFSSL_END(WC_FUNC_TICKET_DO);
-
-        return ret;
-    }
-
-
-    /* send Session Ticket */
-    int SendTicket(WOLFSSL* ssl)
-    {
-        byte*              output;
-        int                ret;
-        int                sendSz;
-        word32             length = SESSION_HINT_SZ + LENGTH_SZ;
-        word32             idx    = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
-        WOLFSSL_START(WC_FUNC_TICKET_SEND);
-        WOLFSSL_ENTER("SendTicket");
-
-        if (ssl->options.createTicket) {
-            ret = CreateTicket(ssl);
-            if (ret != 0) return ret;
-        }
-
-        length += ssl->session.ticketLen;
-        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
-        #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
-        }
-        #endif
-        /* check for available size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        AddHeaders(output, length, session_ticket, ssl);
-
-        /* hint */
-        c32toa(ssl->ctx->ticketHint, output + idx);
-        idx += SESSION_HINT_SZ;
-
-        /* length */
-        c16toa(ssl->session.ticketLen, output + idx);
-        idx += LENGTH_SZ;
-
-        /* ticket */
-        XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
-        /* idx += ssl->session.ticketLen; */
-
-        #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
-                return ret;
-
-            DtlsSEQIncrement(ssl, CUR_ORDER);
-        }
-        #endif
-
-        ret = HashOutput(ssl, output, sendSz, 0);
-        if (ret != 0) return ret;
-        ssl->buffers.outputBuffer.length += sendSz;
-
-        ret = SendBuffered(ssl);
-
-        WOLFSSL_LEAVE("SendTicket", ret);
-        WOLFSSL_END(WC_FUNC_TICKET_SEND);
-
-        return ret;
-    }
-
-#endif /* HAVE_SESSION_TICKET */
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef WOLFSSL_DTLS
-    /* handle generation of DTLS hello_verify_request (3) */
-    static int SendHelloVerifyRequest(WOLFSSL* ssl,
-                                      const byte* cookie, byte cookieSz)
-    {
-        byte* output;
-        int   length = VERSION_SZ + ENUM_LEN + cookieSz;
-        int   idx    = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
-        int   sendSz = length + idx;
-        int   ret;
-
-        /* check for available size */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* get output buffer */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        /* Hello Verify Request should use the same sequence number as the
-         * Client Hello. */
-        ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
-        ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
-        AddHeaders(output, length, hello_verify_request, ssl);
-
-#ifdef OPENSSL_EXTRA
-        output[idx++] = DTLS_MAJOR;
-        output[idx++] = DTLS_MINOR;
-#else
-        output[idx++] = ssl->version.major;
-        output[idx++] = ssl->version.minor;
-#endif
-
-        output[idx++] = cookieSz;
-        if (cookie == NULL || cookieSz == 0)
-            return COOKIE_ERROR;
-
-        XMEMCPY(output + idx, cookie, cookieSz);
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "HelloVerifyRequest");
-        if (ssl->toInfoOn)
-            AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output,
-                          sendSz, WRITE_PROTO, ssl->heap);
-#endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-
-        return SendBuffered(ssl);
-    }
-#endif /* WOLFSSL_DTLS */
-
-    typedef struct DckeArgs {
-        byte*  output; /* not allocated */
-        word32 length;
-        word32 idx;
-        word32 begin;
-        word32 sigSz;
-    #ifndef NO_RSA
-        int    lastErr;
-    #endif
-    } DckeArgs;
-
-    static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs)
-    {
-        DckeArgs* args = (DckeArgs*)pArgs;
-
-        (void)ssl;
-        (void)args;
-    }
-
-    /* handle processing client_key_exchange (16) */
-    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                                                                    word32 size)
-    {
-        int ret;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        DckeArgs* args = (DckeArgs*)ssl->async.args;
-        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-        (void)sizeof(args_test);
-    #else
-        DckeArgs  args[1];
-    #endif
-
-        (void)size;
-        (void)input;
-
-        WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
-        WOLFSSL_ENTER("DoClientKeyExchange");
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-        if (ret != WC_NOT_PENDING_E) {
-            /* Check for error */
-            if (ret < 0)
-                goto exit_dcke;
-        }
-        else
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-        {
-            /* Reset state */
-            ret = 0;
-            ssl->options.asyncState = TLS_ASYNC_BEGIN;
-            XMEMSET(args, 0, sizeof(DckeArgs));
-            args->idx = *inOutIdx;
-            args->begin = *inOutIdx;
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            ssl->async.freeArgs = FreeDckeArgs;
-        #endif
-        }
-
-        /* Do Client Key Exchange State Machine */
-        switch(ssl->options.asyncState)
-        {
-            case TLS_ASYNC_BEGIN:
-            {
-                /* Sanity checks */
-                if (ssl->options.side != WOLFSSL_SERVER_END) {
-                    WOLFSSL_MSG("Client received client keyexchange, attack?");
-                    WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
-                    ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke);
-                }
-
-                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                    WOLFSSL_MSG("Client sending keyexchange at wrong time");
-                    SendAlert(ssl, alert_fatal, unexpected_message);
-                    ERROR_OUT(OUT_OF_ORDER_E, exit_dcke);
-                }
-
-            #ifndef NO_CERTS
-                if (ssl->options.verifyPeer && ssl->options.failNoCert) {
-                    if (!ssl->options.havePeerCert) {
-                        WOLFSSL_MSG("client didn't present peer cert");
-                        ERROR_OUT(NO_PEER_CERT, exit_dcke);
-                    }
-                }
-
-                if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) {
-                    if (!ssl->options.havePeerCert &&
-                                             !ssl->options.usingPSK_cipher) {
-                        WOLFSSL_MSG("client didn't present peer cert");
-                        return NO_PEER_CERT;
-                    }
-                }
-            #endif /* !NO_CERTS */
-
-            #if defined(WOLFSSL_CALLBACKS)
-                if (ssl->hsInfoOn) {
-                    AddPacketName(ssl, "ClientKeyExchange");
-                }
-                if (ssl->toInfoOn) {
-                    AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
-                }
-            #endif
-
-                switch (ssl->specs.kea) {
-                #ifndef NO_RSA
-                    case rsa_kea:
-                    {
-                        break;
-                    } /* rsa_kea */
-                #endif /* !NO_RSA */
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        /* sanity check that PSK server callback has been set */
-                        if (ssl->options.server_psk_cb == NULL) {
-                           WOLFSSL_MSG("No server PSK callback set");
-                           ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #ifdef HAVE_NTRU
-                    case ntru_kea:
-                    {
-                        /* make sure private key exists */
-                        if (ssl->buffers.key == NULL ||
-                                            ssl->buffers.key->buffer == NULL) {
-                            ERROR_OUT(NO_PRIVATE_KEY, exit_dcke);
-                        }
-                        break;
-                    }
-                #endif /* HAVE_NTRU */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #ifndef NO_DH
-                    case diffie_hellman_kea:
-                    {
-                        break;
-                    }
-                #endif /* !NO_DH */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        /* sanity check that PSK server callback has been set */
-                        if (ssl->options.server_psk_cb == NULL) {
-                            WOLFSSL_MSG("No server PSK callback set");
-                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-                        break;
-                    }
-                #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        /* sanity check that PSK server callback has been set */
-                        if (ssl->options.server_psk_cb == NULL) {
-                            WOLFSSL_MSG("No server PSK callback set");
-                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                    default:
-                        WOLFSSL_MSG("Bad kea type");
-                        ret = BAD_KEA_TYPE_E;
-                } /* switch (ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcke;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_BUILD;
-            } /* TLS_ASYNC_BEGIN */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_BUILD:
-            {
-                switch (ssl->specs.kea) {
-                #ifndef NO_RSA
-                    case rsa_kea:
-                    {
-                        word32 i = 0;
-                        int    keySz;
-
-                        ssl->hsType = DYNAMIC_TYPE_RSA;
-                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-
-                        ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer,
-                            &i, (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-                        keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
-                        if (keySz < 0) { /* test if keySz has error */
-                            ERROR_OUT(keySz, exit_dcke);
-                        }
-                        args->length = (word32)keySz;
-
-                        if (keySz < ssl->options.minRsaKeySz) {
-                            WOLFSSL_MSG("Peer RSA key is too small");
-                            ERROR_OUT(RSA_KEY_SIZE_E, exit_dcke);
-                        }
-                        ssl->arrays->preMasterSz = SECRET_LEN;
-
-                        if (ssl->options.tls) {
-                            word16 check;
-
-                            if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                                ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                            }
-
-                            ato16(input + args->idx, &check);
-                            args->idx += OPAQUE16_LEN;
-
-                            if ((word32)check != args->length) {
-                                WOLFSSL_MSG("RSA explicit size doesn't match");
-                                ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke);
-                            }
-                        }
-
-                        if ((args->idx - args->begin) + args->length > size) {
-                            WOLFSSL_MSG("RSA message too big");
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        /* pre-load PreMasterSecret with RNG data */
-                        ret = wc_RNG_GenerateBlock(ssl->rng,
-                            &ssl->arrays->preMasterSecret[VERSION_SZ],
-                            SECRET_LEN - VERSION_SZ);
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-
-                        args->output = NULL;
-                        break;
-                    } /* rsa_kea */
-                #endif /* !NO_RSA */
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        byte* pms = ssl->arrays->preMasterSecret;
-                        word16 ci_sz;
-
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &ci_sz);
-                        args->idx += OPAQUE16_LEN;
-
-                        if (ci_sz > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
-                        }
-
-                        if ((args->idx - args->begin) + ci_sz > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        XMEMCPY(ssl->arrays->client_identity,
-                                                    input + args->idx, ci_sz);
-                        args->idx += ci_sz;
-
-                        ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */
-                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
-                            ssl->arrays->client_identity, ssl->arrays->psk_key,
-                            MAX_PSK_KEY_LEN);
-
-                        if (ssl->arrays->psk_keySz == 0 ||
-                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-
-                        /* make psk pre master secret */
-                        /* length of key + length 0s + length of key + key */
-                        c16toa((word16) ssl->arrays->psk_keySz, pms);
-                        pms += OPAQUE16_LEN;
-
-                        XMEMSET(pms, 0, ssl->arrays->psk_keySz);
-                        pms += ssl->arrays->psk_keySz;
-
-                        c16toa((word16) ssl->arrays->psk_keySz, pms);
-                        pms += OPAQUE16_LEN;
-
-                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                        ssl->arrays->preMasterSz =
-                            (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2);
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #ifdef HAVE_NTRU
-                    case ntru_kea:
-                    {
-                        word16 cipherLen;
-                        word16 plainLen = ENCRYPT_LEN;
-
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &cipherLen);
-                        args->idx += OPAQUE16_LEN;
-
-                        if (cipherLen > MAX_NTRU_ENCRYPT_SZ) {
-                            ERROR_OUT(NTRU_KEY_ERROR, exit_dcke);
-                        }
-
-                        if ((args->idx - args->begin) + cipherLen > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        if (NTRU_OK != ntru_crypto_ntru_decrypt(
-                                    (word16) ssl->buffers.key->length,
-                                    ssl->buffers.key->buffer, cipherLen,
-                                    input + args->idx, &plainLen,
-                                    ssl->arrays->preMasterSecret)) {
-                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
-                        }
-
-                        if (plainLen != SECRET_LEN) {
-                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
-                        }
-
-                        args->idx += cipherLen;
-                        ssl->arrays->preMasterSz = plainLen;
-                        break;
-                    }
-                #endif /* HAVE_NTRU */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                    #ifdef HAVE_ECC
-                        ecc_key* private_key = ssl->eccTempKey;
-
-                        /* handle static private key */
-                        if (ssl->specs.static_ecdh &&
-                                          ssl->ecdhCurveOID != ECC_X25519_OID) {
-                            word32 i = 0;
-
-                            ssl->hsType = DYNAMIC_TYPE_ECC;
-                            ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-
-                            ret = wc_EccPrivateKeyDecode(
-                                ssl->buffers.key->buffer,
-                                &i,
-                                (ecc_key*)ssl->hsKey,
-                                ssl->buffers.key->length);
-                            if (ret == 0) {
-                                private_key = (ecc_key*)ssl->hsKey;
-                                if (wc_ecc_size(private_key) <
-                                                ssl->options.minEccKeySz) {
-                                    WOLFSSL_MSG("ECC key too small");
-                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_dcke);
-                                }
-                            }
-                        }
-                    #endif
-
-                        /* import peer ECC key */
-                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        args->length = input[args->idx++];
-
-                        if ((args->idx - args->begin) + args->length > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ssl->arrays->preMasterSz = ENCRYPT_LEN;
-
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                        #ifdef HAVE_PK_CALLBACKS
-                            /* if callback then use it for shared secret */
-                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
-                                break;
-                            }
-                        #endif
-                            if (ssl->peerX25519Key == NULL) {
-                                /* alloc/init on demand */
-                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                    (void**)&ssl->peerX25519Key);
-                                if (ret != 0) {
-                                    goto exit_dcke;
-                                }
-                            } else if (ssl->peerX25519KeyPresent) {
-                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                               ssl->peerX25519Key);
-                                ssl->peerX25519KeyPresent = 0;
-                                if (ret != 0) {
-                                    goto exit_dcke;
-                                }
-                            }
-
-                            if (wc_curve25519_import_public_ex(
-                                    input + args->idx, args->length,
-                                    ssl->peerX25519Key,
-                                    EC25519_LITTLE_ENDIAN)) {
-                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
-                            }
-
-                            ssl->peerX25519KeyPresent = 1;
-
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-                            break;
-                        }
-                    #endif
-                #ifdef HAVE_ECC
-                    #ifdef HAVE_PK_CALLBACKS
-                        /* if callback then use it for shared secret */
-                        if (ssl->ctx->EccSharedSecretCb != NULL) {
-                            break;
-                        }
-                    #endif
-
-                        if (!ssl->specs.static_ecdh &&
-                            ssl->eccTempKeyPresent == 0) {
-                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
-                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
-                        }
-
-                        if (ssl->peerEccKey == NULL) {
-                            /* alloc/init on demand */
-                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                (void**)&ssl->peerEccKey);
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-                        } else if (ssl->peerEccKeyPresent) {
-                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
-                                           ssl->peerEccKey);
-                            ssl->peerEccKeyPresent = 0;
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-                        }
-
-                        if (wc_ecc_import_x963_ex(input + args->idx, args->length,
-                                        ssl->peerEccKey, private_key->dp->id)) {
-                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
-                        }
-
-                        ssl->peerEccKeyPresent = 1;
-                #endif /* HAVE_ECC */
-
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #ifndef NO_DH
-                    case diffie_hellman_kea:
-                    {
-                        word16 clientPubSz;
-
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &clientPubSz);
-                        args->idx += OPAQUE16_LEN;
-
-                        if ((args->idx - args->begin) + clientPubSz > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        args->sigSz = clientPubSz;
-
-                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
-                                            (void**)&ssl->buffers.serverDH_Key);
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-
-                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_P.buffer,
-                            ssl->buffers.serverDH_P.length,
-                            ssl->buffers.serverDH_G.buffer,
-                            ssl->buffers.serverDH_G.length);
-
-                        /* set the max agree result size */
-                        ssl->arrays->preMasterSz = ENCRYPT_LEN;
-                        break;
-                    }
-                #endif /* !NO_DH */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        word16 clientSz;
-
-                        /* Read in the PSK hint */
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &clientSz);
-                        args->idx += OPAQUE16_LEN;
-                        if (clientSz > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
-                        }
-
-                        if ((args->idx - args->begin) + clientSz > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        XMEMCPY(ssl->arrays->client_identity, input + args->idx,
-                                                                    clientSz);
-                        args->idx += clientSz;
-                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
-
-                        /* Read in the DHE business */
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &clientSz);
-                        args->idx += OPAQUE16_LEN;
-
-                        if ((args->idx - args->begin) + clientSz > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        args->sigSz = clientSz;
-
-                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
-                                            (void**)&ssl->buffers.serverDH_Key);
-                        if (ret != 0) {
-                            goto exit_dcke;
-                        }
-
-                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_P.buffer,
-                            ssl->buffers.serverDH_P.length,
-                            ssl->buffers.serverDH_G.buffer,
-                            ssl->buffers.serverDH_G.length);
-
-                        break;
-                    }
-                #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        word16 clientSz;
-
-                        /* Read in the PSK hint */
-                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        ato16(input + args->idx, &clientSz);
-                        args->idx += OPAQUE16_LEN;
-                        if (clientSz > MAX_PSK_ID_LEN) {
-                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
-                        }
-                        if ((args->idx - args->begin) + clientSz > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        XMEMCPY(ssl->arrays->client_identity,
-                                                   input + args->idx, clientSz);
-                        args->idx += clientSz;
-                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
-
-                        /* import peer ECC key */
-                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        args->length = input[args->idx++];
-
-                        if ((args->idx - args->begin) + args->length > size) {
-                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                        }
-
-                        args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
-
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                        #ifdef HAVE_PK_CALLBACKS
-                            /* if callback then use it for shared secret */
-                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
-                                break;
-                            }
-                        #endif
-
-                            if (ssl->eccTempKeyPresent == 0) {
-                                WOLFSSL_MSG(
-                                     "X25519 ephemeral key not made correctly");
-                                ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
-                            }
-
-                            if (ssl->peerX25519Key == NULL) {
-                                /* alloc/init on demand */
-                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                    (void**)&ssl->peerX25519Key);
-                                if (ret != 0) {
-                                    goto exit_dcke;
-                                }
-                            } else if (ssl->peerX25519KeyPresent) {
-                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                               ssl->peerX25519Key);
-                                ssl->peerX25519KeyPresent = 0;
-                                if (ret != 0) {
-                                    goto exit_dcke;
-                                }
-                            }
-
-                            if (wc_curve25519_import_public_ex(
-                                    input + args->idx, args->length,
-                                    ssl->peerX25519Key,
-                                    EC25519_LITTLE_ENDIAN)) {
-                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
-                            }
-
-                            ssl->peerX25519KeyPresent = 1;
-
-                            break;
-                        }
-                    #endif
-                    #ifdef HAVE_PK_CALLBACKS
-                        /* if callback then use it for shared secret */
-                        if (ssl->ctx->EccSharedSecretCb != NULL) {
-                            break;
-                        }
-                    #endif
-
-                        if (ssl->eccTempKeyPresent == 0) {
-                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
-                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
-                        }
-
-                        if (ssl->peerEccKey == NULL) {
-                            /* alloc/init on demand */
-                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
-                                (void**)&ssl->peerEccKey);
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-                        }
-                        else if (ssl->peerEccKeyPresent) {
-                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
-                                           ssl->peerEccKey);
-                            ssl->peerEccKeyPresent = 0;
-                            if (ret != 0) {
-                                goto exit_dcke;
-                            }
-                        }
-                        if (wc_ecc_import_x963_ex(input + args->idx, args->length,
-                                 ssl->peerEccKey, ssl->eccTempKey->dp->id)) {
-                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
-                        }
-
-                        ssl->peerEccKeyPresent = 1;
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                    default:
-                        ret = BAD_KEA_TYPE_E;
-                } /* switch (ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcke;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_DO;
-            } /* TLS_ASYNC_BUILD */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_DO:
-            {
-                switch (ssl->specs.kea) {
-                #ifndef NO_RSA
-                    case rsa_kea:
-                    {
-                        RsaKey* key = (RsaKey*)ssl->hsKey;
-
-                        ret = RsaDec(ssl,
-                            input + args->idx,
-                            args->length,
-                            &args->output,
-                            &args->sigSz,
-                            key,
-                        #ifdef HAVE_PK_CALLBACKS
-                            ssl->buffers.key
-                        #else
-                            NULL
-                        #endif
-                        );
-
-                        /*  Errors that can occur here that should be
-                         *  indistinguishable:
-                         *       RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
-                         */
-                        if (ret < 0 && ret != BAD_FUNC_ARG) {
-                        #ifdef WOLFSSL_ASYNC_CRYPT
-                            if (ret == WC_PENDING_E)
-                                goto exit_dcke;
-                        #endif
-                            /* store error code for handling below */
-                            args->lastErr = ret;
-                            ret = 0;
-                        }
-                        break;
-                    } /* rsa_kea */
-                #endif /* !NO_RSA */
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #ifdef HAVE_NTRU
-                    case ntru_kea:
-                    {
-                        break;
-                    }
-                #endif /* HAVE_NTRU */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        void* private_key = ssl->eccTempKey;
-                        (void)private_key;
-
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                            ret = X25519SharedSecret(ssl,
-                                (curve25519_key*)private_key,
-                                ssl->peerX25519Key,
-                                input + args->idx, &args->length,
-                                ssl->arrays->preMasterSecret,
-                                &ssl->arrays->preMasterSz,
-                                WOLFSSL_SERVER_END
-                            );
-                            break;
-                        }
-                    #endif
-                    #ifdef HAVE_ECC
-                        if (ssl->specs.static_ecdh) {
-                            private_key = ssl->hsKey;
-                        }
-
-                        /* Generate shared secret */
-                        ret = EccSharedSecret(ssl,
-                            (ecc_key*)private_key, ssl->peerEccKey,
-                            input + args->idx, &args->length,
-                            ssl->arrays->preMasterSecret,
-                            &ssl->arrays->preMasterSz,
-                            WOLFSSL_SERVER_END
-                        );
-                    #endif
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #ifndef NO_DH
-                    case diffie_hellman_kea:
-                    {
-                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_Priv.buffer,
-                            ssl->buffers.serverDH_Priv.length,
-                            input + args->idx,
-                            (word16)args->sigSz,
-                            ssl->arrays->preMasterSecret,
-                            &ssl->arrays->preMasterSz);
-                        break;
-                    }
-                #endif /* !NO_DH */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
-                            ssl->buffers.serverDH_Priv.buffer,
-                            ssl->buffers.serverDH_Priv.length,
-                            input + args->idx,
-                            (word16)args->sigSz,
-                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                            &ssl->arrays->preMasterSz);
-                        break;
-                    }
-                #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                    #ifdef HAVE_CURVE25519
-                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
-                            ret = X25519SharedSecret(ssl,
-                                (curve25519_key*)ssl->eccTempKey,
-                                ssl->peerX25519Key,
-                                input + args->idx, &args->length,
-                                ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                                &args->sigSz,
-                                WOLFSSL_SERVER_END
-                            );
-                            if (ret == 0) {
-                                FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
-                                                   (void**)&ssl->peerX25519Key);
-                                ssl->peerX25519KeyPresent = 0;
-                            }
-                            break;
-                        }
-                    #endif
-                        /* Generate shared secret */
-                        ret = EccSharedSecret(ssl,
-                            ssl->eccTempKey, ssl->peerEccKey,
-                            input + args->idx, &args->length,
-                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
-                            &args->sigSz,
-                            WOLFSSL_SERVER_END
-                        );
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                    default:
-                        ret = BAD_KEA_TYPE_E;
-                } /* switch (ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcke;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_VERIFY;
-            } /* TLS_ASYNC_DO */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_VERIFY:
-            {
-                switch (ssl->specs.kea) {
-                #ifndef NO_RSA
-                    case rsa_kea:
-                    {
-                        /* Add the signature length to idx */
-                        args->idx += args->length;
-
-                    #ifdef DEBUG_WOLFSSL
-                        /* check version (debug warning message only) */
-                        if (args->output != NULL) {
-                            if (args->output[0] != ssl->chVersion.major ||
-                                args->output[1] != ssl->chVersion.minor) {
-                                WOLFSSL_MSG("preMasterSecret version mismatch");
-                            }
-                        }
-                    #endif
-
-                        /* RFC5246 7.4.7.1:
-                         * Treat incorrectly formatted message blocks and/or
-                         * mismatched version numbers in a manner
-                         * indistinguishable from correctly formatted RSA blocks
-                         */
-
-                        ret = args->lastErr;
-                        args->lastErr = 0; /* reset */
-
-                        /* build PreMasterSecret */
-                        ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
-                        ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
-                        if (ret == 0 && args->sigSz == SECRET_LEN &&
-                                                         args->output != NULL) {
-                            XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ],
-                                &args->output[VERSION_SZ],
-                                SECRET_LEN - VERSION_SZ);
-                        }
-                        else {
-                            /* preMasterSecret has RNG and version set */
-                            /* return proper length and ignore error */
-                            /* error will be caught as decryption error */
-                            args->sigSz = SECRET_LEN;
-                            ret = 0;
-                        }
-
-                        break;
-                    } /* rsa_kea */
-                #endif /* !NO_RSA */
-                #ifndef NO_PSK
-                    case psk_kea:
-                    {
-                        break;
-                    }
-                #endif /* !NO_PSK */
-                #ifdef HAVE_NTRU
-                    case ntru_kea:
-                    {
-                        break;
-                    }
-                #endif /* HAVE_NTRU */
-                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-                    case ecc_diffie_hellman_kea:
-                    {
-                        /* skip past the imported peer key */
-                        args->idx += args->length;
-                        break;
-                    }
-                #endif /* HAVE_ECC || HAVE_CURVE25519 */
-                #ifndef NO_DH
-                    case diffie_hellman_kea:
-                    {
-                        args->idx += (word16)args->sigSz;
-                        break;
-                    }
-                #endif /* !NO_DH */
-                #if !defined(NO_DH) && !defined(NO_PSK)
-                    case dhe_psk_kea:
-                    {
-                        byte* pms = ssl->arrays->preMasterSecret;
-                        word16 clientSz = (word16)args->sigSz;
-
-                        args->idx += clientSz;
-                        c16toa((word16)ssl->arrays->preMasterSz, pms);
-                        ssl->arrays->preMasterSz += OPAQUE16_LEN;
-                        pms += ssl->arrays->preMasterSz;
-
-                        /* Use the PSK hint to look up the PSK and add it to the
-                         * preMasterSecret here. */
-                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
-                            ssl->arrays->client_identity, ssl->arrays->psk_key,
-                            MAX_PSK_KEY_LEN);
-
-                        if (ssl->arrays->psk_keySz == 0 ||
-                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-
-                        c16toa((word16) ssl->arrays->psk_keySz, pms);
-                        pms += OPAQUE16_LEN;
-
-                        XMEMCPY(pms, ssl->arrays->psk_key,
-                                                    ssl->arrays->psk_keySz);
-                        ssl->arrays->preMasterSz += ssl->arrays->psk_keySz +
-                                                                OPAQUE16_LEN;
-                        break;
-                    }
-                #endif /* !NO_DH && !NO_PSK */
-                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
-                                                                !defined(NO_PSK)
-                    case ecdhe_psk_kea:
-                    {
-                        byte* pms = ssl->arrays->preMasterSecret;
-                        word16 clientSz = (word16)args->sigSz;
-
-                        /* skip past the imported peer key */
-                        args->idx += args->length;
-
-                        /* Add preMasterSecret */
-                        c16toa(clientSz, pms);
-                        ssl->arrays->preMasterSz += OPAQUE16_LEN + clientSz;
-                        pms += ssl->arrays->preMasterSz;
-
-                        /* Use the PSK hint to look up the PSK and add it to the
-                         * preMasterSecret here. */
-                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
-                            ssl->arrays->client_identity, ssl->arrays->psk_key,
-                            MAX_PSK_KEY_LEN);
-
-                        if (ssl->arrays->psk_keySz == 0 ||
-                                   ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
-                        }
-
-                        c16toa((word16) ssl->arrays->psk_keySz, pms);
-                        pms += OPAQUE16_LEN;
-
-                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
-                        ssl->arrays->preMasterSz +=
-                                      ssl->arrays->psk_keySz + OPAQUE16_LEN;
-                        break;
-                    }
-                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
-                    default:
-                        ret = BAD_KEA_TYPE_E;
-                } /* switch (ssl->specs.kea) */
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcke;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-            } /* TLS_ASYNC_VERIFY */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_FINALIZE:
-            {
-            #ifdef HAVE_QSH
-                word16 name;
-
-                if (ssl->options.haveQSH) {
-                    /* extension name */
-                    ato16(input + args->idx, &name);
-                    args->idx += OPAQUE16_LEN;
-
-                    if (name == TLSX_QUANTUM_SAFE_HYBRID) {
-                        int    qshSz;
-                        /* if qshSz is larger than 0 it is the
-                           length of buffer used */
-                        if ((qshSz = TLSX_QSHCipher_Parse(ssl,
-                                input + args->idx,
-                                size - args->idx + args->begin, 1)) < 0) {
-                            ERROR_OUT(qshSz, exit_dcke);
-                        }
-                        args->idx += qshSz;
-                    }
-                    else {
-                        /* unknown extension sent client ignored handshake */
-                        ERROR_OUT(BUFFER_ERROR, exit_dcke);
-                    }
-                }
-            #endif /* HAVE_QSH */
-                ret = MakeMasterSecret(ssl);
-
-                /* Check for error */
-                if (ret != 0) {
-                    goto exit_dcke;
-                }
-
-                /* Advance state and proceed */
-                ssl->options.asyncState = TLS_ASYNC_END;
-            } /* TLS_ASYNC_FINALIZE */
-            FALL_THROUGH;
-
-            case TLS_ASYNC_END:
-            {
-                /* Set final index */
-                *inOutIdx = args->idx;
-
-                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
-            #ifndef NO_CERTS
-                if (ssl->options.verifyPeer) {
-                    ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
-                }
-            #endif
-                break;
-            } /* TLS_ASYNC_END */
-            default:
-                ret = INPUT_CASE_ERROR;
-        } /* switch(ssl->options.asyncState) */
-
-    exit_dcke:
-
-        WOLFSSL_LEAVE("DoClientKeyExchange", ret);
-        WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* Handle async operation */
-        if (ret == WC_PENDING_E) {
-            /* Mark message as not recevied so it can process again */
-            ssl->msgsReceived.got_client_key_exchange = 0;
-
-            return ret;
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        /* Cleanup PMS */
-        ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
-        ssl->arrays->preMasterSz = 0;
-
-        /* Final cleanup */
-        FreeDckeArgs(ssl, args);
-        FreeKeyExchange(ssl);
-
-        return ret;
-    }
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY)
-    int SNI_Callback(WOLFSSL* ssl)
-    {
-        /* Stunnel supports a custom sni callback to switch an SSL's ctx
-        * when SNI is received. Call it now if exists */
-        if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) {
-            WOLFSSL_MSG("Calling custom sni callback");
-            if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg)
-                    == alert_fatal) {
-                WOLFSSL_MSG("Error in custom sni callback. Fatal alert");
-                SendAlert(ssl, alert_fatal, unrecognized_name);
-                return FATAL_ERROR;
-            }
-        }
-        return 0;
-    }
-#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-
-#endif /* NO_WOLFSSL_SERVER */
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
-{
-    int ret = 0;
-    WC_ASYNC_DEV* asyncDev;
-    WOLF_EVENT* event;
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* check for pending async */
-    asyncDev = ssl->async.dev;
-    if (asyncDev) {
-        /* grab event pointer */
-        event = &asyncDev->event;
-
-        ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL);
-        if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) {
-
-            /* advance key share state if doesn't need called again */
-            if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) {
-                (*state)++;
-            }
-
-            /* clear event */
-            XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT));
-
-            /* clear async dev */
-            ssl->async.dev = NULL;
-        }
-    }
-    else {
-        ret = WC_NOT_PENDING_E;
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret);
-
-    return ret;
-}
-
-int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags)
-{
-    int ret;
-    WOLF_EVENT* event;
-
-    if (ssl == NULL || asyncDev == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* grab event pointer */
-    event = &asyncDev->event;
-
-    /* init event */
-    ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags);
-
-    WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret);
-
-    return ret;
-}
-
-int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev)
-{
-    int ret;
-    WOLF_EVENT* event;
-
-    if (ssl == NULL || asyncDev == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* grab event pointer */
-    event = &asyncDev->event;
-
-    /* store reference to active async operation */
-    ssl->async.dev = asyncDev;
-
-    /* place event into queue */
-    ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event);
-
-    /* success means return WC_PENDING_E */
-    if (ret == 0) {
-        ret = WC_PENDING_E;
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret);
-
-    return ret;
-}
-
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-
-/* return the max record size */
-int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment)
-{
-    (void) ssl; /* Avoid compiler warnings */
-
-    if (maxFragment > MAX_RECORD_SIZE) {
-        maxFragment = MAX_RECORD_SIZE;
-    }
-
-#ifdef HAVE_MAX_FRAGMENT
-    if ((ssl->max_fragment != 0) && (maxFragment > ssl->max_fragment)) {
-        maxFragment = ssl->max_fragment;
-    }
-#endif /* HAVE_MAX_FRAGMENT */
-#ifdef WOLFSSL_DTLS
-    if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) {
-        maxFragment = MAX_UDP_SIZE;
-    }
-#endif
-
-    return maxFragment;
-}
-
-
-#undef ERROR_OUT
-
-#endif /* WOLFCRYPT_ONLY */
-
+/* internal.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfcrypt/asn.h>
+#include <wolfcrypt/dh.h>
+#ifdef NO_INLINE
+    #include <wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA)
+    #include <wolfcrypt/srp.h>
+#endif
+
+#ifdef HAVE_LIBZ
+    #include "zlib.h"
+#endif
+
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+#endif
+
+#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \
+    defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
+    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+        #if MQX_USE_IO_OLD
+            #include <fio.h>
+        #else
+            #include <nio.h>
+        #endif
+    #else
+        #include <stdio.h>
+    #endif
+#endif
+
+#ifdef __sun
+    #include <sys/filio.h>
+#endif
+
+
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+#ifdef _MSC_VER
+    /* disable for while(0) cases at the .c level for now */
+    #pragma warning(disable:4127)
+#endif
+
+#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS)
+    #error \
+WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
+#endif
+
+#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION)
+    #error Cannot use both secure-renegotiation and renegotiation-indication
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_WOLFSSL_CLIENT
+    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #ifndef NO_CERTS
+        static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #endif
+    #ifdef HAVE_SESSION_TICKET
+        static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*,
+                                                                        word32);
+    #endif
+#endif
+
+
+#ifndef NO_WOLFSSL_SERVER
+    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32);
+    #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+        static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32);
+    #endif
+    #ifdef WOLFSSL_DTLS
+        static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
+    #endif /* WOLFSSL_DTLS */
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_DTLS
+    static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl);
+    static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl);
+#endif
+
+
+enum processReply {
+    doProcessInit = 0,
+#ifndef NO_WOLFSSL_SERVER
+    runProcessOldClientHello,
+#endif
+    getRecordLayerHeader,
+    getData,
+    decryptMessage,
+    verifyMessage,
+    runProcessingOneMessage
+};
+
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+
+/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
+static const byte tls13Downgrade[7] = {
+    0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44
+};
+#define TLS13_DOWNGRADE_SZ  sizeof(tls13Downgrade)
+
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_OLD_TLS
+static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
+                    int padSz, int content, int verify);
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef HAVE_QSH
+    int QSH_Init(WOLFSSL* ssl);
+#endif
+
+
+int IsTLS(const WOLFSSL* ssl)
+{
+    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
+        return 1;
+
+    return 0;
+}
+
+
+int IsAtLeastTLSv1_2(const WOLFSSL* ssl)
+{
+    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
+        return 1;
+#ifdef WOLFSSL_DTLS
+    if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR)
+        return 1;
+#endif
+
+    return 0;
+}
+
+int IsAtLeastTLSv1_3(const ProtocolVersion pv)
+{
+    return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR);
+}
+
+static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend)
+{
+    (void)isSend;
+
+    #ifdef WOLFSSL_DTLS
+    /* For DTLS, epoch 0 is always not encrypted. */
+    if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0)
+        return 0;
+    #endif /* WOLFSSL_DTLS */
+
+    return ssl->keys.encryptionOn;
+}
+
+
+/* If SCTP is not enabled returns the state of the dtls option.
+ * If SCTP is enabled returns dtls && !sctp. */
+static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+{
+    int result = ssl->options.dtls;
+
+    if (result) {
+#ifdef WOLFSSL_SCTP
+        result = !ssl->options.dtlsSctp;
+#endif
+    }
+
+    return result;
+}
+
+
+#ifdef HAVE_QSH
+/* free all structs that where used with QSH */
+static int QSH_FreeAll(WOLFSSL* ssl)
+{
+    QSHKey* key        = ssl->QSH_Key;
+    QSHKey* preKey     = NULL;
+    QSHSecret* secret  = ssl->QSH_secret;
+    QSHScheme* list    = NULL;
+    QSHScheme* preList = NULL;
+
+    /* free elements in struct */
+    while (key) {
+        preKey = key;
+        if (key->pri.buffer) {
+            ForceZero(key->pri.buffer, key->pri.length);
+            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        }
+        if (key->pub.buffer)
+            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        key = (QSHKey*)key->next;
+
+        /* free struct */
+        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+    }
+    key = NULL;
+
+
+    /* free all of peers QSH keys */
+    key = ssl->peerQSHKey;
+    while (key) {
+        preKey = key;
+        if (key->pri.buffer) {
+            ForceZero(key->pri.buffer, key->pri.length);
+            XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+        }
+        if (key->pub.buffer)
+            XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        key = (QSHKey*)key->next;
+
+        /* free struct */
+        XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH);
+    }
+    key = NULL;
+
+    /* free secret information */
+    if (secret) {
+        /* free up the QSHScheme list in QSHSecret */
+        if (secret->list)
+            list = secret->list;
+        while (list) {
+            preList = list;
+            if (list->PK)
+                XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET);
+            list = (QSHScheme*)list->next;
+            XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH);
+        }
+
+        /* free secret buffers */
+        if (secret->SerSi) {
+            if (secret->SerSi->buffer) {
+                /* clear extra secret material that supplemented Master Secret*/
+                ForceZero(secret->SerSi->buffer, secret->SerSi->length);
+                XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+            }
+            XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+        }
+        if (secret->CliSi) {
+            if (secret->CliSi->buffer) {
+                /* clear extra secret material that supplemented Master Secret*/
+                ForceZero(secret->CliSi->buffer, secret->CliSi->length);
+                XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET);
+            }
+            XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET);
+        }
+    }
+    XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH);
+    secret = NULL;
+
+    return 0;
+}
+#endif
+
+
+#ifdef HAVE_NTRU
+static WC_RNG* rng;
+static wolfSSL_Mutex* rngMutex;
+
+static word32 GetEntropy(unsigned char* out, word32 num_bytes)
+{
+    int ret = 0;
+
+    if (rng == NULL) {
+        if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0,
+                                                    DYNAMIC_TYPE_RNG)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitRng(rng);
+    }
+
+    if (rngMutex == NULL) {
+        if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0,
+                        DYNAMIC_TYPE_MUTEX)) == NULL)
+            return DRBG_OUT_OF_MEMORY;
+        wc_InitMutex(rngMutex);
+    }
+
+    ret |= wc_LockMutex(rngMutex);
+    ret |= wc_RNG_GenerateBlock(rng, out, num_bytes);
+    ret |= wc_UnLockMutex(rngMutex);
+
+    if (ret != 0)
+        return DRBG_ENTROPY_FAIL;
+
+    return DRBG_OK;
+}
+#endif /* HAVE_NTRU */
+
+#ifdef HAVE_LIBZ
+
+    /* alloc user allocs to work with zlib */
+    static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
+    {
+        (void)opaque;
+        return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
+    }
+
+
+    static void myFree(void* opaque, void* memory)
+    {
+        (void)opaque;
+        XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
+    }
+
+
+    /* init zlib comp/decomp streams, 0 on success */
+    static int InitStreams(WOLFSSL* ssl)
+    {
+        ssl->c_stream.zalloc = (alloc_func)myAlloc;
+        ssl->c_stream.zfree  = (free_func)myFree;
+        ssl->c_stream.opaque = (voidpf)ssl->heap;
+
+        if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
+            return ZLIB_INIT_ERROR;
+
+        ssl->didStreamInit = 1;
+
+        ssl->d_stream.zalloc = (alloc_func)myAlloc;
+        ssl->d_stream.zfree  = (free_func)myFree;
+        ssl->d_stream.opaque = (voidpf)ssl->heap;
+
+        if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
+
+        return 0;
+    }
+
+
+    static void FreeStreams(WOLFSSL* ssl)
+    {
+        if (ssl->didStreamInit) {
+            deflateEnd(&ssl->c_stream);
+            inflateEnd(&ssl->d_stream);
+        }
+    }
+
+
+    /* compress in to out, return out size or error */
+    static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz)
+    {
+        int    err;
+        int    currTotal = (int)ssl->c_stream.total_out;
+
+        ssl->c_stream.next_in   = in;
+        ssl->c_stream.avail_in  = inSz;
+        ssl->c_stream.next_out  = out;
+        ssl->c_stream.avail_out = outSz;
+
+        err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
+        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
+
+        return (int)ssl->c_stream.total_out - currTotal;
+    }
+
+
+    /* decompress in to out, return out size or error */
+    static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz)
+    {
+        int    err;
+        int    currTotal = (int)ssl->d_stream.total_out;
+
+        ssl->d_stream.next_in   = in;
+        ssl->d_stream.avail_in  = inSz;
+        ssl->d_stream.next_out  = out;
+        ssl->d_stream.avail_out = outSz;
+
+        err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
+        if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
+
+        return (int)ssl->d_stream.total_out - currTotal;
+    }
+
+#endif /* HAVE_LIBZ */
+
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+/* serializes the cipher specs struct for exporting */
+static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    CipherSpecs* specs;
+
+    WOLFSSL_ENTER("ExportCipherSpecState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    specs= &(ssl->specs);
+
+    if (DTLS_EXPORT_SPC_SZ > len) {
+        return BUFFER_E;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ);
+
+    c16toa(specs->key_size, exp + idx);      idx += OPAQUE16_LEN;
+    c16toa(specs->iv_size, exp + idx);       idx += OPAQUE16_LEN;
+    c16toa(specs->block_size, exp + idx);    idx += OPAQUE16_LEN;
+    c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN;
+    exp[idx++] = specs->bulk_cipher_algorithm;
+    exp[idx++] = specs->cipher_type;
+    exp[idx++] = specs->mac_algorithm;
+    exp[idx++] = specs->kea;
+    exp[idx++] = specs->sig_algo;
+    exp[idx++] = specs->hash_size;
+    exp[idx++] = specs->pad_size;
+    exp[idx++] = specs->static_ecdh;
+
+    if (idx != DTLS_EXPORT_SPC_SZ) {
+        WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version");
+        return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("ExportCipherSpecState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+/* serializes the key struct for exporting */
+static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    byte   sz;
+    Keys* keys;
+
+    WOLFSSL_ENTER("ExportKeyState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    keys = &(ssl->keys);
+
+    if (DTLS_EXPORT_KEY_SZ > len) {
+        WOLFSSL_MSG("Buffer not large enough for max key struct size");
+        return BUFFER_E;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_KEY_SZ);
+
+    c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN;
+    c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+    c32toa(keys->sequence_number_hi, exp + idx);      idx += OPAQUE32_LEN;
+    c32toa(keys->sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
+
+    c16toa(keys->peerSeq[0].nextEpoch, exp + idx);  idx += OPAQUE16_LEN;
+    c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+    c16toa(keys->curEpoch, exp + idx);   idx += OPAQUE16_LEN;
+    c16toa(keys->curSeq_hi, exp + idx);  idx += OPAQUE16_LEN;
+    c32toa(keys->curSeq_lo, exp + idx);  idx += OPAQUE32_LEN;
+    c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN;
+
+    c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(keys->dtls_expected_peer_handshake_number, exp + idx);
+    idx += OPAQUE16_LEN;
+
+    c16toa(keys->dtls_sequence_number_hi, exp + idx);      idx += OPAQUE16_LEN;
+    c32toa(keys->dtls_sequence_number_lo, exp + idx);      idx += OPAQUE32_LEN;
+    c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN;
+    c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN;
+    c16toa(keys->dtls_epoch, exp + idx);                   idx += OPAQUE16_LEN;
+    c16toa(keys->dtls_handshake_number, exp + idx);        idx += OPAQUE16_LEN;
+    c32toa(keys->encryptSz, exp + idx);                    idx += OPAQUE32_LEN;
+    c32toa(keys->padSz, exp + idx);                        idx += OPAQUE32_LEN;
+    exp[idx++] = keys->encryptionOn;
+    exp[idx++] = keys->decryptedCur;
+
+    {
+        word32 i;
+
+        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+            c32toa(keys->peerSeq[0].window[i], exp + idx);
+            idx += OPAQUE32_LEN;
+        }
+        c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN;
+        for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+            c32toa(keys->peerSeq[0].prevWindow[i], exp + idx);
+            idx += OPAQUE32_LEN;
+        }
+    }
+
+#ifdef HAVE_TRUNCATED_HMAC
+    sz         = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size;
+    exp[idx++] = ssl->truncated_hmac;
+#else
+    sz         = ssl->specs.hash_size;
+    exp[idx++] = 0; /* no truncated hmac */
+#endif
+    exp[idx++] = sz;
+    XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz;
+    XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz;
+
+    sz         = ssl->specs.key_size;
+    exp[idx++] = sz;
+    XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz;
+    XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz;
+
+    sz         = ssl->specs.iv_size;
+    exp[idx++] = sz;
+    XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz;
+    XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz;
+    XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
+    idx += AEAD_MAX_EXP_SZ;
+
+    sz         = AEAD_MAX_IMP_SZ;
+    exp[idx++] = sz;
+    XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz;
+    XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz;
+
+    /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */
+    if (idx > DTLS_EXPORT_KEY_SZ) {
+        WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version");
+        return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("ExportKeyState", idx);
+    (void)ver;
+    return idx;
+}
+
+static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    CipherSpecs* specs;
+
+    WOLFSSL_ENTER("ImportCipherSpecState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    specs= &(ssl->specs);
+
+    if (DTLS_EXPORT_SPC_SZ > len) {
+        WOLFSSL_MSG("Buffer not large enough for max spec struct size");
+        return BUFFER_E;
+    }
+
+    ato16(exp + idx, &specs->key_size);      idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->iv_size);       idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->block_size);    idx += OPAQUE16_LEN;
+    ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN;
+    specs->bulk_cipher_algorithm = exp[idx++];
+    specs->cipher_type           = exp[idx++];
+    specs->mac_algorithm         = exp[idx++];
+    specs->kea                   = exp[idx++];
+    specs->sig_algo              = exp[idx++];
+    specs->hash_size             = exp[idx++];
+    specs->pad_size              = exp[idx++];
+    specs->static_ecdh           = exp[idx++];
+
+    WOLFSSL_LEAVE("ImportCipherSpecState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    word32 idx = 0;
+    byte  sz;
+    Keys* keys;
+
+    WOLFSSL_ENTER("ImportKeyState");
+
+    if (exp == NULL || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    keys = &(ssl->keys);
+
+    /* check minimum length -- includes byte used for size indicators */
+    if (len < DTLS_EXPORT_MIN_KEY_SZ) {
+        return BUFFER_E;
+    }
+    ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->sequence_number_hi);      idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->sequence_number_lo);      idx += OPAQUE32_LEN;
+
+    ato16(exp + idx, &keys->peerSeq[0].nextEpoch);  idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->curEpoch);   idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->curSeq_hi);  idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->curSeq_lo);  idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN;
+
+    ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->dtls_expected_peer_handshake_number);
+    idx += OPAQUE16_LEN;
+
+    ato16(exp + idx, &keys->dtls_sequence_number_hi);      idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->dtls_sequence_number_lo);      idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN;
+    ato16(exp + idx, &keys->dtls_epoch);                   idx += OPAQUE16_LEN;
+    ato16(exp + idx, &keys->dtls_handshake_number);        idx += OPAQUE16_LEN;
+    ato32(exp + idx, &keys->encryptSz);                    idx += OPAQUE32_LEN;
+    ato32(exp + idx, &keys->padSz);                        idx += OPAQUE32_LEN;
+    keys->encryptionOn = exp[idx++];
+    keys->decryptedCur = exp[idx++];
+
+    {
+        word16 i, wordCount, wordAdj = 0;
+
+        /* do window */
+        ato16(exp + idx, &wordCount);
+        idx += OPAQUE16_LEN;
+
+        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+        }
+
+        XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
+        for (i = 0; i < wordCount; i++) {
+            ato32(exp + idx, &keys->peerSeq[0].window[i]);
+            idx += OPAQUE32_LEN;
+        }
+        idx += wordAdj;
+
+        /* do prevWindow */
+        ato16(exp + idx, &wordCount);
+        idx += OPAQUE16_LEN;
+
+        if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
+            wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
+            wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
+        }
+
+        XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
+        for (i = 0; i < wordCount; i++) {
+            ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]);
+            idx += OPAQUE32_LEN;
+        }
+        idx += wordAdj;
+
+    }
+
+#ifdef HAVE_TRUNCATED_HMAC
+    ssl->truncated_hmac = exp[idx++];
+#else
+    idx++; /* no truncated hmac */
+#endif
+    sz = exp[idx++];
+    if (sz > sizeof(keys->client_write_MAC_secret) || sz + idx > len) {
+        return BUFFER_E;
+    }
+    XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz;
+    XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz;
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->client_write_key) || sz + idx > len) {
+        return BUFFER_E;
+    }
+    XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz;
+    XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz;
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->client_write_IV) || sz + idx > len) {
+        return BUFFER_E;
+    }
+    XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz;
+    XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz;
+    XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ);
+    idx += AEAD_MAX_EXP_SZ;
+
+    sz = exp[idx++];
+    if (sz > sizeof(keys->aead_enc_imp_IV) || sz + idx > len) {
+        return BUFFER_E;
+    }
+    XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz;
+    XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz;
+
+    WOLFSSL_LEAVE("ImportKeyState", idx);
+    (void)ver;
+    return idx;
+}
+
+
+/* copy over necessary information from Options struct to buffer
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int idx = 0;
+    word16 zero = 0;
+    Options* options = &ssl->options;
+
+    WOLFSSL_ENTER("dtls_export_new");
+
+    if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) {
+        return BAD_FUNC_ARG;
+    }
+
+    XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ);
+
+    /* these options are kept and sent to indicate verify status and strength
+     * of handshake */
+    exp[idx++] = options->sendVerify;
+    exp[idx++] = options->verifyPeer;
+    exp[idx++] = options->verifyNone;
+    exp[idx++] = options->downgrade;
+#ifndef NO_DH
+    c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(options->dhKeySz, exp + idx);    idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+    c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+    c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN;
+#else
+    c16toa(zero, exp + idx); idx += OPAQUE16_LEN;
+#endif
+
+    /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+    exp[idx++] = options->havePSK;
+#else
+    exp[idx++] = 0;
+#endif
+    exp[idx++] = options->sessionCacheOff;
+    exp[idx++] = options->sessionCacheFlushOff;
+    exp[idx++] = options->side;
+    exp[idx++] = options->resuming;
+    exp[idx++] = options->haveSessionId;
+    exp[idx++] = options->tls;
+    exp[idx++] = options->tls1_1;
+    exp[idx++] = options->dtls;
+    exp[idx++] = options->connReset;
+    exp[idx++] = options->isClosed;
+    exp[idx++] = options->closeNotify;
+    exp[idx++] = options->sentNotify;
+    exp[idx++] = options->usingCompression;
+    exp[idx++] = options->haveRSA;
+    exp[idx++] = options->haveECC;
+    exp[idx++] = options->haveDH;
+    exp[idx++] = options->haveNTRU;
+    exp[idx++] = options->haveQSH;
+    exp[idx++] = options->haveECDSAsig;
+    exp[idx++] = options->haveStaticECC;
+    exp[idx++] = options->havePeerVerify;
+    exp[idx++] = options->usingPSK_cipher;
+    exp[idx++] = options->usingAnon_cipher;
+    exp[idx++] = options->sendAlertState;
+    exp[idx++] = options->partialWrite;
+    exp[idx++] = options->quietShutdown;
+    exp[idx++] = options->groupMessages;
+#ifdef HAVE_POLY1305
+    exp[idx++] = options->oldPoly;
+#else
+    exp[idx++] = 0;
+#endif
+#ifdef HAVE_ANON
+    exp[idx++] = options->haveAnon;
+#else
+    exp[idx++] = 0;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    exp[idx++] = options->createTicket;
+    exp[idx++] = options->useTicket;
+#ifdef WOLFSSL_TLS13
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = options->noTicketTls13;
+    }
+#else
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+#else
+    exp[idx++] = 0;
+    exp[idx++] = 0;
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+    exp[idx++] = options->processReply;
+    exp[idx++] = options->cipherSuite0;
+    exp[idx++] = options->cipherSuite;
+    exp[idx++] = options->serverState;
+    exp[idx++] = options->clientState;
+    exp[idx++] = options->handShakeState;
+    exp[idx++] = options->handShakeDone;
+    exp[idx++] = options->minDowngrade;
+    exp[idx++] = options->connectState;
+    exp[idx++] = options->acceptState;
+    exp[idx++] = options->asyncState;
+
+    /* version of connection */
+    exp[idx++] = ssl->version.major;
+    exp[idx++] = ssl->version.minor;
+
+    (void)zero;
+
+    /* check if changes were made and notify of need to update export version */
+    switch (ver) {
+        case DTLS_EXPORT_VERSION_3:
+            if (idx != DTLS_EXPORT_OPT_SZ_3) {
+                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+                return DTLS_EXPORT_VER_E;
+            }
+            break;
+
+        case DTLS_EXPORT_VERSION:
+            if (idx != DTLS_EXPORT_OPT_SZ) {
+                WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export");
+                return DTLS_EXPORT_VER_E;
+            }
+            break;
+
+       default:
+            WOLFSSL_MSG("New version case needs added to wolfSSL export");
+            return DTLS_EXPORT_VER_E;
+    }
+
+    WOLFSSL_LEAVE("dtls_export_new", idx);
+
+    return idx;
+}
+
+
+/* copy items from Export struct to Options struct
+ * On success returns size of buffer used on failure returns a negative value */
+static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int idx = 0;
+    Options* options = &ssl->options;
+
+    switch (ver) {
+        case DTLS_EXPORT_VERSION:
+            if (len < DTLS_EXPORT_OPT_SZ) {
+                WOLFSSL_MSG("Sanity check on buffer size failed");
+                return BAD_FUNC_ARG;
+            }
+            break;
+
+        case DTLS_EXPORT_VERSION_3:
+            if (len < DTLS_EXPORT_OPT_SZ_3) {
+                WOLFSSL_MSG("Sanity check on buffer size failed");
+                return BAD_FUNC_ARG;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("Export version not supported");
+            return BAD_FUNC_ARG;
+    }
+
+    if (exp == NULL || options == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+
+    /* these options are kept and sent to indicate verify status and strength
+     * of handshake */
+    options->sendVerify = exp[idx++];
+    options->verifyPeer = exp[idx++];
+    options->verifyNone = exp[idx++];
+    options->downgrade  = exp[idx++];
+#ifndef NO_DH
+    ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN;
+    ato16(exp + idx, &(options->dhKeySz));    idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+    idx += OPAQUE16_LEN;
+    idx += OPAQUE16_LEN;
+#endif
+#ifndef NO_RSA
+    ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+#endif
+#ifdef HAVE_ECC
+    ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN;
+#else
+    idx += OPAQUE16_LEN;
+#endif
+
+    /* these options are kept to indicate state and behavior */
+#ifndef NO_PSK
+    options->havePSK = exp[idx++];
+#else
+    idx++;
+#endif
+    options->sessionCacheOff      = exp[idx++];
+    options->sessionCacheFlushOff = exp[idx++];
+    options->side                 = exp[idx++];
+    options->resuming             = exp[idx++];
+    options->haveSessionId    = exp[idx++];
+    options->tls              = exp[idx++];
+    options->tls1_1           = exp[idx++];
+    options->dtls             = exp[idx++];
+    options->connReset        = exp[idx++];
+    options->isClosed         = exp[idx++];
+    options->closeNotify      = exp[idx++];
+    options->sentNotify       = exp[idx++];
+    options->usingCompression = exp[idx++];
+    options->haveRSA          = exp[idx++];
+    options->haveECC          = exp[idx++];
+    options->haveDH           = exp[idx++];
+    options->haveNTRU         = exp[idx++];
+    options->haveQSH          = exp[idx++];
+    options->haveECDSAsig     = exp[idx++];
+    options->haveStaticECC    = exp[idx++];
+    options->havePeerVerify   = exp[idx++];
+    options->usingPSK_cipher  = exp[idx++];
+    options->usingAnon_cipher = exp[idx++];
+    options->sendAlertState   = exp[idx++];
+    options->partialWrite     = exp[idx++];
+    options->quietShutdown    = exp[idx++];
+    options->groupMessages    = exp[idx++];
+#ifdef HAVE_POLY1305
+    options->oldPoly = exp[idx++];      /* set when to use old rfc way of poly*/
+#else
+    idx++;
+#endif
+#ifdef HAVE_ANON
+    options->haveAnon = exp[idx++];     /* User wants to allow Anon suites */
+#else
+    idx++;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    options->createTicket  = exp[idx++]; /* Server to create new Ticket */
+    options->useTicket     = exp[idx++]; /* Use Ticket not session cache */
+#ifdef WOLFSSL_TLS13
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */
+    }
+#else
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        exp[idx++] = 0;
+    }
+#endif
+#else
+    idx++;
+    idx++;
+    if (ver > DTLS_EXPORT_VERSION_3) {
+        idx++;
+    }
+#endif
+    options->processReply   = exp[idx++];
+    options->cipherSuite0   = exp[idx++];
+    options->cipherSuite    = exp[idx++];
+    options->serverState    = exp[idx++];
+    options->clientState    = exp[idx++];
+    options->handShakeState = exp[idx++];
+    options->handShakeDone  = exp[idx++];
+    options->minDowngrade   = exp[idx++];
+    options->connectState   = exp[idx++];
+    options->acceptState    = exp[idx++];
+    options->asyncState     = exp[idx++];
+
+    /* version of connection */
+    if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) {
+        WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2");
+        return VERSION_ERROR;
+    }
+
+    return idx;
+}
+
+static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
+{
+    int    idx  = 0;
+    int    ipSz = DTLS_EXPORT_IP; /* start as max size */
+    int    fam  = 0;
+    word16 port = 0;
+    char   ip[DTLS_EXPORT_IP];
+
+    if (ver != DTLS_EXPORT_VERSION) {
+        WOLFSSL_MSG("Export version not supported");
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl->ctx->CBGetPeer == NULL) {
+        WOLFSSL_MSG("No get peer call back set");
+        return BAD_FUNC_ARG;
+    }
+    if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Get peer callback error");
+        return SOCKET_ERROR_E;
+    }
+
+    /* check that ipSz/fam is not negative or too large since user can set cb */
+    if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) {
+        WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback");
+        return SOCKET_ERROR_E;
+    }
+
+    c16toa((word16)fam, exp + idx);  idx += DTLS_EXPORT_LEN;
+    c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
+    XMEMCPY(exp + idx, ip, ipSz);    idx += ipSz;
+    c16toa(port, exp + idx);         idx += DTLS_EXPORT_LEN;
+
+    return idx;
+}
+
+
+static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
+{
+    word16 idx = 0;
+    word16 ipSz;
+    word16 fam;
+    word16 port;
+    char   ip[DTLS_EXPORT_IP];
+
+    if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) {
+        WOLFSSL_MSG("Export version not supported");
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* import sin family */
+    ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN;
+
+    /* import ip address idx, and ipSz are unsigned but cast for enum */
+    ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN;
+    if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) {
+        return BUFFER_E;
+    }
+    XMEMSET(ip, 0, sizeof(ip));
+    XMEMCPY(ip, buf + idx, ipSz); idx += ipSz;
+    ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */
+    ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN;
+
+    /* sanity check for a function to call, then use it to import peer info */
+    if (ssl->ctx->CBSetPeer == NULL) {
+        WOLFSSL_MSG("No set peer function");
+        return BAD_FUNC_ARG;
+    }
+    if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Error setting peer info");
+        return SOCKET_ERROR_E;
+    }
+
+    return idx;
+}
+
+
+/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
+ * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
+ * passed in.
+ * On success returns the size of serialized session.*/
+int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    int ret;
+    word32 idx      = 0;
+    word32 totalLen = 0;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
+
+    if (buf == NULL || ssl == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG);
+        return BAD_FUNC_ARG;
+    }
+
+    totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
+    /* each of the following have a 2 byte length before data */
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ;
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ;
+    totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ;
+    totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
+
+    if (totalLen > sz) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
+        return BUFFER_E;
+    }
+
+    buf[idx++] =  (byte)DTLS_EXPORT_PRO;
+    buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) |
+                 ((byte)DTLS_EXPORT_VERSION & 0X0F);
+
+    idx += DTLS_EXPORT_LEN; /* leave spot for length */
+
+    c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+    if ((ret = dtls_export_new(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    idx += ret;
+
+    /* export keys struct and dtls state -- variable length stored in ret */
+    idx += DTLS_EXPORT_LEN; /* leave room for length */
+    if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
+
+    /* export of cipher specs struct */
+    c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
+    if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    idx += ret;
+
+    /* export of dtls peer information */
+    idx += DTLS_EXPORT_LEN;
+    if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx,
+                                                    DTLS_EXPORT_VERSION)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
+        return ret;
+    }
+    c16toa(ret, buf + idx - DTLS_EXPORT_LEN);
+    idx += ret;
+
+    /* place total length of exported buffer minus 2 bytes protocol/version */
+    c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
+
+    /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
+    return idx;
+}
+
+
+/* On success return amount of buffer consumed */
+int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    word32 idx    = 0;
+    word16 length = 0;
+    int version;
+    int ret;
+    int optSz;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
+    /* check at least enough room for protocol and length */
+    if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* sanity check on protocol ID and size of buffer */
+    if (buf[idx++]       !=  (byte)DTLS_EXPORT_PRO ||
+       (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
+        /* don't increment on second idx to next get version */
+        WOLFSSL_MSG("Incorrect protocol");
+        return BAD_FUNC_ARG;
+    }
+    version = buf[idx++] & 0x0F;
+
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
+        return BUFFER_E;
+    }
+
+    /* if compiled with debug options then print the version, protocol, size */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    {
+        char debug[256];
+        XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n"
+                   "\tVersion  : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
+               , (int)version, buf[0], (buf[1] >> 4), length);
+        WOLFSSL_MSG(debug);
+    }
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+    /* perform sanity checks and extract Options information used */
+    switch (version) {
+        case DTLS_EXPORT_VERSION:
+            optSz = DTLS_EXPORT_OPT_SZ;
+            break;
+
+        case DTLS_EXPORT_VERSION_3:
+            WOLFSSL_MSG("Importing older version 3");
+            optSz = DTLS_EXPORT_OPT_SZ_3;
+            break;
+
+        default:
+            WOLFSSL_MSG("Bad export version");
+            return BAD_FUNC_ARG;
+
+    }
+
+    if (DTLS_EXPORT_LEN + optSz + idx > sz) {
+        WOLFSSL_MSG("Import Options struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length != optSz) {
+        WOLFSSL_MSG("Import Options struct error");
+        return BUFFER_E;
+    }
+    if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Options struct error");
+        return ret;
+    }
+    idx += length;
+
+    /* perform sanity checks and extract Keys struct */
+    if (DTLS_EXPORT_LEN + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
+        WOLFSSL_MSG("Import Key struct error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Key struct error");
+        return ret;
+    }
+    idx += ret;
+
+    /* perform sanity checks and extract CipherSpecs struct */
+    if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if ( length != DTLS_EXPORT_SPC_SZ) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import CipherSpecs struct error");
+        return ret;
+    }
+    idx += ret;
+
+    /* perform sanity checks and extract DTLS peer info */
+    if (DTLS_EXPORT_LEN + idx > sz) {
+        WOLFSSL_MSG("Import DTLS peer info error");
+        return BUFFER_E;
+    }
+    ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
+    if (idx + length > sz) {
+        WOLFSSL_MSG("Import DTLS peer info error");
+        return BUFFER_E;
+    }
+    if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) {
+        WOLFSSL_MSG("Import Peer Addr error");
+        return ret;
+    }
+    idx += ret;
+
+    SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+
+    /* set hmac function to use when verifying */
+    if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 ||
+            ssl->options.dtls == 1) {
+        ssl->hmac = TLS_hmac;
+    }
+
+    /* make sure is a valid suite used */
+    if (wolfSSL_get_cipher(ssl) == NULL) {
+        WOLFSSL_MSG("Can not match cipher suite imported");
+        return MATCH_SUITE_ERROR;
+    }
+
+    /* do not allow stream ciphers with DTLS, except for NULL cipher */
+    if (ssl->specs.cipher_type == stream &&
+        ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) {
+        WOLFSSL_MSG("Can not import stream ciphers for DTLS");
+        return SANITY_CIPHER_E;
+    }
+
+    return idx;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+
+void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv)
+{
+    method->version    = pv;
+    method->side       = WOLFSSL_CLIENT_END;
+    method->downgrade  = 0;
+}
+
+
+/* Initialize SSL context, return 0 on success */
+int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
+{
+    int ret = 0;
+
+    XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
+
+    ctx->method   = method;
+    ctx->refCount = 1;          /* so either CTX_free or SSL_free can release */
+    ctx->heap     = ctx;        /* defaults to self */
+    ctx->timeout  = WOLFSSL_SESSION_TIMEOUT;
+    ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */
+
+    if (wc_InitMutex(&ctx->countMutex) < 0) {
+        WOLFSSL_MSG("Mutex error on CTX init");
+        ctx->err = CTX_INIT_MUTEX_E;
+        return BAD_MUTEX_E;
+    }
+
+#ifndef NO_DH
+    ctx->minDhKeySz  = MIN_DHKEY_SZ;
+    ctx->maxDhKeySz  = MAX_DHKEY_SZ;
+#endif
+#ifndef NO_RSA
+    ctx->minRsaKeySz = MIN_RSAKEY_SZ;
+#endif
+#ifdef HAVE_ECC
+    ctx->minEccKeySz  = MIN_ECCKEY_SZ;
+    ctx->eccTempKeySz = ECDHE_SIZE;
+#endif
+#ifdef OPENSSL_EXTRA
+    ctx->verifyDepth = MAX_CHAIN_DEPTH;
+    ctx->cbioFlag = WOLFSSL_CBIO_NONE;
+#endif
+
+#ifndef WOLFSSL_USER_IO
+    #ifdef MICRIUM
+        ctx->CBIORecv = MicriumReceive;
+        ctx->CBIOSend = MicriumSend;
+        #ifdef WOLFSSL_DTLS
+            if (method->version.major == DTLS_MAJOR) {
+                ctx->CBIORecv   = MicriumReceiveFrom;
+                ctx->CBIOSend   = MicriumSendTo;
+            }
+            #ifdef WOLFSSL_SESSION_EXPORT
+                #error Micrium port does not support DTLS session export yet
+            #endif
+        #endif
+    #else
+        ctx->CBIORecv = EmbedReceive;
+        ctx->CBIOSend = EmbedSend;
+        #ifdef WOLFSSL_DTLS
+            if (method->version.major == DTLS_MAJOR) {
+                ctx->CBIORecv   = EmbedReceiveFrom;
+                ctx->CBIOSend   = EmbedSendTo;
+            }
+            #ifdef WOLFSSL_SESSION_EXPORT
+            ctx->CBGetPeer = EmbedGetPeer;
+            ctx->CBSetPeer = EmbedSetPeer;
+            #endif
+        #endif
+    #endif /* MICRIUM */
+#endif /* WOLFSSL_USER_IO */
+
+#ifdef HAVE_NETX
+    ctx->CBIORecv = NetX_Receive;
+    ctx->CBIOSend = NetX_Send;
+#endif
+
+#ifdef HAVE_NTRU
+    if (method->side == WOLFSSL_CLIENT_END)
+        ctx->haveNTRU = 1;           /* always on client side */
+                                     /* server can turn on by loading key */
+#endif
+#ifdef HAVE_ECC
+    if (method->side == WOLFSSL_CLIENT_END) {
+        ctx->haveECDSAsig  = 1;        /* always on client side */
+        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
+        ctx->haveStaticECC = 1;        /* server can turn on by loading key */
+    }
+#elif defined(HAVE_ED25519)
+    if (method->side == WOLFSSL_CLIENT_END) {
+        ctx->haveECDSAsig  = 1;        /* always on client side */
+        ctx->haveECC  = 1;             /* server turns on with ECC key cert */
+    }
+#endif
+
+    ctx->devId = INVALID_DEVID;
+
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP)
+    ctx->dtlsMtuSz = MAX_RECORD_SIZE;
+#endif
+
+#ifndef NO_CERTS
+    ctx->cm = wolfSSL_CertManagerNew_ex(heap);
+    if (ctx->cm == NULL) {
+        WOLFSSL_MSG("Bad Cert Manager New");
+        return BAD_CERT_MANAGER_ERROR;
+    }
+    #ifdef OPENSSL_EXTRA
+    /* setup WOLFSSL_X509_STORE */
+    ctx->x509_store.cm = ctx->cm;
+    #endif
+#endif
+
+#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
+    if (method->side == WOLFSSL_CLIENT_END) {
+        if ((method->version.major == SSLv3_MAJOR) &&
+             (method->version.minor >= TLSv1_MINOR)) {
+
+            ctx->haveEMS = 1;
+        }
+#ifdef WOLFSSL_DTLS
+        if (method->version.major == DTLS_MAJOR)
+            ctx->haveEMS = 1;
+#endif /* WOLFSSL_DTLS */
+    }
+#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
+
+#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+    ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
+#endif
+
+#ifdef HAVE_WOLF_EVENT
+    ret = wolfEventQueue_Init(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+#ifdef WOLFSSL_EARLY_DATA
+    ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ;
+#endif
+
+    ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */
+    ctx->verifyDepth = MAX_CHAIN_DEPTH;
+
+    return ret;
+}
+
+
+/* In case contexts are held in array and don't want to free actual ctx */
+void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
+{
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+    int i;
+#endif
+
+#ifdef HAVE_WOLF_EVENT
+    wolfEventQueue_Free(&ctx->event_queue);
+#endif /* HAVE_WOLF_EVENT */
+
+    XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+    if (ctx->suites)
+        XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
+
+#ifndef NO_DH
+    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#endif /* !NO_DH */
+
+#ifdef SINGLE_THREADED
+    if (ctx->rng) {
+        wc_FreeRng(ctx->rng);
+        XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG);
+    }
+#endif /* SINGLE_THREADED */
+
+#ifndef NO_CERTS
+    FreeDer(&ctx->privateKey);
+    FreeDer(&ctx->certificate);
+    #ifdef KEEP_OUR_CERT
+        if (ctx->ourCert && ctx->ownOurCert) {
+            FreeX509(ctx->ourCert);
+            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+        }
+    #endif /* KEEP_OUR_CERT */
+    FreeDer(&ctx->certChain);
+    wolfSSL_CertManagerFree(ctx->cm);
+    #ifdef OPENSSL_EXTRA
+	/* ctx->cm was free'd so cm of x509 store should now be NULL */
+        if (ctx->x509_store_pt != NULL) {
+            ctx->x509_store_pt->cm = NULL;
+        }
+        wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+        while (ctx->ca_names != NULL) {
+            WOLFSSL_STACK *next = ctx->ca_names->next;
+            wolfSSL_X509_NAME_free(ctx->ca_names->data.name);
+            XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->ca_names = next;
+        }
+    #endif
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        while (ctx->x509Chain != NULL) {
+            WOLFSSL_STACK *next = ctx->x509Chain->next;
+            wolfSSL_X509_free(ctx->x509Chain->data.x509);
+            XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->x509Chain = next;
+        }
+    #endif
+#endif /* !NO_CERTS */
+
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX_FreeAll(ctx->extensions, ctx->heap);
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    if (ctx->certOcspRequest) {
+        FreeOcspRequest(ctx->certOcspRequest);
+        XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    }
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+    for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
+        if (ctx->chainOcspRequest[i]) {
+            FreeOcspRequest(ctx->chainOcspRequest[i]);
+            XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+        }
+    }
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+#endif /* !NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef OPENSSL_EXTRA
+    if(ctx->alpn_cli_protos)
+        XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL);
+#endif
+#ifdef WOLFSSL_STATIC_MEMORY
+    if (ctx->heap != NULL) {
+#ifdef WOLFSSL_HEAP_TEST
+        /* avoid derefrencing a test value */
+        if (ctx->heap != (void*)WOLFSSL_HEAP_TEST)
+#endif
+        {
+            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap);
+            wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex);
+        }
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+}
+
+
+void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
+{
+    int doFree = 0;
+
+    if (wc_LockMutex(&ctx->countMutex) != 0) {
+        WOLFSSL_MSG("Couldn't lock count mutex");
+
+        /* check error state, if mutex error code then mutex init failed but
+         * CTX was still malloc'd */
+        if (ctx->err == CTX_INIT_MUTEX_E) {
+            SSL_CtxResourceFree(ctx);
+            XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+        }
+        return;
+    }
+    ctx->refCount--;
+    if (ctx->refCount == 0)
+        doFree = 1;
+    wc_UnLockMutex(&ctx->countMutex);
+
+    if (doFree) {
+        WOLFSSL_MSG("CTX ref count down to 0, doing full free");
+        SSL_CtxResourceFree(ctx);
+        wc_FreeMutex(&ctx->countMutex);
+        XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+    }
+    else {
+        (void)ctx;
+        WOLFSSL_MSG("CTX ref count not 0 yet, no free");
+    }
+}
+
+
+/* Set cipher pointers to null */
+void InitCiphers(WOLFSSL* ssl)
+{
+#ifdef BUILD_ARC4
+    ssl->encrypt.arc4 = NULL;
+    ssl->decrypt.arc4 = NULL;
+#endif
+#ifdef BUILD_DES3
+    ssl->encrypt.des3 = NULL;
+    ssl->decrypt.des3 = NULL;
+#endif
+#ifdef BUILD_AES
+    ssl->encrypt.aes = NULL;
+    ssl->decrypt.aes = NULL;
+#endif
+#ifdef HAVE_CAMELLIA
+    ssl->encrypt.cam = NULL;
+    ssl->decrypt.cam = NULL;
+#endif
+#ifdef HAVE_HC128
+    ssl->encrypt.hc128 = NULL;
+    ssl->decrypt.hc128 = NULL;
+#endif
+#ifdef BUILD_RABBIT
+    ssl->encrypt.rabbit = NULL;
+    ssl->decrypt.rabbit = NULL;
+#endif
+#ifdef HAVE_CHACHA
+    ssl->encrypt.chacha = NULL;
+    ssl->decrypt.chacha = NULL;
+#endif
+#ifdef HAVE_POLY1305
+    ssl->auth.poly1305 = NULL;
+#endif
+    ssl->encrypt.setup = 0;
+    ssl->decrypt.setup = 0;
+#ifdef HAVE_ONE_TIME_AUTH
+    ssl->auth.setup    = 0;
+#endif
+#ifdef HAVE_IDEA
+    ssl->encrypt.idea = NULL;
+    ssl->decrypt.idea = NULL;
+#endif
+}
+
+
+/* Free ciphers */
+void FreeCiphers(WOLFSSL* ssl)
+{
+    (void)ssl;
+#ifdef BUILD_ARC4
+    wc_Arc4Free(ssl->encrypt.arc4);
+    wc_Arc4Free(ssl->decrypt.arc4);
+    XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef BUILD_DES3
+    wc_Des3Free(ssl->encrypt.des3);
+    wc_Des3Free(ssl->decrypt.des3);
+    XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef BUILD_AES
+    wc_AesFree(ssl->encrypt.aes);
+    wc_AesFree(ssl->decrypt.aes);
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+        XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+        XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+        XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+        XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+    #endif
+    XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_CAMELLIA
+    XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_HC128
+    XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef BUILD_RABBIT
+    XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_CHACHA
+    XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_POLY1305
+    XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+#ifdef HAVE_IDEA
+    XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+    XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER);
+#endif
+}
+
+
+void InitCipherSpecs(CipherSpecs* cs)
+{
+    XMEMSET(cs, 0, sizeof(CipherSpecs));
+
+    cs->bulk_cipher_algorithm = INVALID_BYTE;
+    cs->cipher_type           = INVALID_BYTE;
+    cs->mac_algorithm         = INVALID_BYTE;
+    cs->kea                   = INVALID_BYTE;
+    cs->sig_algo              = INVALID_BYTE;
+}
+
+void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig,
+                           int haveAnon, int tls1_2, int keySz)
+{
+    int idx = 0;
+
+    (void)tls1_2;
+    (void)keySz;
+
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    if (haveECDSAsig) {
+    #ifdef HAVE_ECC
+        #ifdef WOLFSSL_SHA512
+            suites->hashSigAlgo[idx++] = sha512_mac;
+            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
+        #endif
+        #ifdef WOLFSSL_SHA384
+            suites->hashSigAlgo[idx++] = sha384_mac;
+            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
+        #endif
+        #ifndef NO_SHA256
+            suites->hashSigAlgo[idx++] = sha256_mac;
+            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
+        #endif
+        #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                                                defined(WOLFSSL_ALLOW_TLS_SHA1))
+            suites->hashSigAlgo[idx++] = sha_mac;
+            suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo;
+        #endif
+    #endif
+        #ifdef HAVE_ED25519
+            suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR;
+            suites->hashSigAlgo[idx++] = ED25519_SA_MINOR;
+        #endif
+    }
+#endif /* HAVE_ECC || HAVE_ED25519 */
+
+    if (haveRSAsig) {
+        #ifdef WC_RSA_PSS
+            if (tls1_2) {
+            #ifdef WOLFSSL_SHA512
+                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
+                suites->hashSigAlgo[idx++] = sha512_mac;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
+                suites->hashSigAlgo[idx++] = sha384_mac;
+            #endif
+            #ifndef NO_SHA256
+                suites->hashSigAlgo[idx++] = rsa_pss_sa_algo;
+                suites->hashSigAlgo[idx++] = sha256_mac;
+            #endif
+            }
+        #endif
+        #ifdef WOLFSSL_SHA512
+            suites->hashSigAlgo[idx++] = sha512_mac;
+            suites->hashSigAlgo[idx++] = rsa_sa_algo;
+        #endif
+        #ifdef WOLFSSL_SHA384
+            suites->hashSigAlgo[idx++] = sha384_mac;
+            suites->hashSigAlgo[idx++] = rsa_sa_algo;
+        #endif
+        #ifndef NO_SHA256
+            suites->hashSigAlgo[idx++] = sha256_mac;
+            suites->hashSigAlgo[idx++] = rsa_sa_algo;
+        #endif
+        #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                                                defined(WOLFSSL_ALLOW_TLS_SHA1))
+            suites->hashSigAlgo[idx++] = sha_mac;
+            suites->hashSigAlgo[idx++] = rsa_sa_algo;
+        #endif
+    }
+
+#ifdef HAVE_ANON
+    if (haveAnon) {
+            suites->hashSigAlgo[idx++] = sha_mac;
+            suites->hashSigAlgo[idx++] = anonymous_sa_algo;
+    }
+#endif
+
+    (void)haveAnon;
+    (void)haveECDSAsig;
+    suites->hashSigAlgoSz = (word16)idx;
+}
+
+void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
+                word16 havePSK, word16 haveDH, word16 haveNTRU,
+                word16 haveECDSAsig, word16 haveECC,
+                word16 haveStaticECC, int side)
+{
+    word16 idx = 0;
+    int    tls    = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
+    int    tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR;
+#ifdef WOLFSSL_TLS13
+    int    tls1_3 = IsAtLeastTLSv1_3(pv);
+#endif
+    int    dtls   = 0;
+    int    haveRSAsig = 1;
+
+    (void)tls;  /* shut up compiler */
+    (void)tls1_2;
+    (void)dtls;
+    (void)haveDH;
+    (void)havePSK;
+    (void)haveNTRU;
+    (void)haveStaticECC;
+    (void)haveECC;
+    (void)side;
+    (void)haveRSA;    /* some builds won't read */
+    (void)haveRSAsig; /* non ecc builds won't read */
+
+    if (suites == NULL) {
+        WOLFSSL_MSG("InitSuites pointer error");
+        return;
+    }
+
+    if (suites->setSuites)
+        return;      /* trust user settings, don't override */
+
+#ifdef WOLFSSL_TLS13
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_CCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+    if (tls1_3) {
+        suites->suites[idx++] = TLS13_BYTE;
+        suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256;
+    }
+#endif
+#endif /* WOLFSSL_TLS13 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_WOLFSSL_SERVER
+    if (side == WOLFSSL_SERVER_END && haveStaticECC) {
+        haveRSA = 0;   /* can't do RSA with ECDSA key */
+    }
+
+    if (side == WOLFSSL_SERVER_END && haveECDSAsig) {
+        haveRSAsig = 0;     /* can't have RSA sig if signed by ECDSA */
+    }
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifdef WOLFSSL_DTLS
+    if (pv.major == DTLS_MAJOR) {
+        dtls   = 1;
+        tls    = 1;
+        /* May be dead assignments dependant upon configuration */
+        (void) dtls;
+        (void) tls;
+        tls1_2 = pv.minor <= DTLSv1_2_MINOR;
+    }
+#endif
+
+#ifdef HAVE_RENEGOTIATION_INDICATION
+    if (side == WOLFSSL_CLIENT_END) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
+    }
+#endif
+
+#ifdef BUILD_TLS_QSH
+    if (tls) {
+        suites->suites[idx++] = QSH_BYTE;
+        suites->suites[idx++] = TLS_QSH;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+   if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
+   }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveNTRU && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    if (tls1_2 && haveDH) {
+      suites->suites[idx++] = CIPHER_BYTE;
+      suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && haveDH) {
+      suites->suites[idx++] = CIPHER_BYTE;
+      suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    if (tls1_2 && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    if (tls1_2 && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+/* Place as higher priority for MYSQL */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE)
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    if (tls1_2 && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveECC && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    if (!dtls && tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveRSAsig && haveStaticECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+/* Place as higher priority for MYSQL testing */
+#if !defined(WOLFSSL_MYSQL_COMPATIBLE)
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveECC) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] =
+                              TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    if (tls1_2 && haveRSA) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    if (tls && haveECC) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = CHACHA_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM_8;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
+    }
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = ECC_BYTE;
+        suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+    if (tls && haveDH && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    if (tls && havePSK) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    if (!dtls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    if (!dtls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    if (haveRSA ) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    if (!dtls && tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    if (tls && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    if (tls && haveDH && haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
+    }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+    if (haveRSA) {
+        suites->suites[idx++] = CIPHER_BYTE;
+        suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA;
+    }
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+    suites->suiteSz = idx;
+
+    InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0, tls1_2, keySz);
+}
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \
+    (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC)))
+
+/* Decode the signature algorithm.
+ *
+ * input     The encoded signature algorithm.
+ * hashalgo  The hash algorithm.
+ * hsType    The signature type.
+ */
+static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
+{
+    switch (input[0]) {
+        case NEW_SA_MAJOR:
+    #ifdef WC_RSA_PSS
+            /* PSS signatures: 0x080[4-6] */
+            if (input[1] <= sha512_mac) {
+                *hsType   = input[0];
+                *hashAlgo = input[1];
+            }
+    #endif
+    #ifdef HAVE_ED25519
+            /* ED25519: 0x0807 */
+            if (input[1] == ED25519_SA_MINOR) {
+                *hsType = ed25519_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+    #endif
+            /* ED448: 0x0808 */
+            break;
+        default:
+            *hashAlgo = input[0];
+            *hsType   = input[1];
+            break;
+    }
+}
+#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+                                       (!defined(NO_RSA) && defined(WC_RSA_PSS))
+
+static enum wc_HashType HashAlgoToType(int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return WC_HASH_TYPE_SHA512;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return WC_HASH_TYPE_SHA384;
+    #endif
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return WC_HASH_TYPE_SHA256;
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                             defined(WOLFSSL_ALLOW_TLS_SHA1))
+        case sha_mac:
+            return WC_HASH_TYPE_SHA;
+    #endif
+        default:
+            WOLFSSL_MSG("Bad hash sig algo");
+            break;
+    }
+
+    return WC_HASH_TYPE_NONE;
+}
+#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_CERTS
+
+void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
+{
+    (void)dynamicFlag;
+
+    if (name != NULL) {
+        name->name        = name->staticName;
+        name->dynamicName = 0;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XMEMSET(&name->fullName, 0, sizeof(DecodedName));
+        XMEMSET(&name->cnEntry,  0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+        XMEMSET(&name->extra,    0, sizeof(name->extra));
+        name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/
+        name->cnEntry.nid = ASN_COMMON_NAME;
+        name->x509 = NULL;
+#endif /* OPENSSL_EXTRA */
+    }
+}
+
+
+void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap)
+{
+    if (name != NULL) {
+        if (name->dynamicName)
+            XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        {
+            int i;
+            if (name->fullName.fullName != NULL) {
+                XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509);
+                name->fullName.fullName = NULL;
+            }
+            for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+                /* free ASN1 string data */
+                if (name->extra[i].set && name->extra[i].data.data != NULL) {
+                    XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL);
+                }
+            }
+        }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    }
+    (void)heap;
+}
+
+
+/* Initialize wolfSSL X509 type */
+void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
+{
+    if (x509 == NULL) {
+        WOLFSSL_MSG("Null parameter passed in!");
+        return;
+    }
+
+    XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
+
+    x509->heap = heap;
+    InitX509Name(&x509->issuer, 0);
+    InitX509Name(&x509->subject, 0);
+    x509->dynamicMemory  = (byte)dynamicFlag;
+}
+
+
+/* Free wolfSSL X509 type */
+void FreeX509(WOLFSSL_X509* x509)
+{
+    if (x509 == NULL)
+        return;
+
+    FreeX509Name(&x509->issuer, x509->heap);
+    FreeX509Name(&x509->subject, x509->heap);
+    if (x509->pubKey.buffer)
+        XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    FreeDer(&x509->derCert);
+    XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        if (x509->authInfo != NULL) {
+            XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        }
+        if (x509->extKeyUsageSrc != NULL) {
+            XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
+        }
+    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    if (x509->altNames)
+        FreeAltNames(x509->altNames, x509->heap);
+}
+
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+/* Encode the signature algorithm into buffer.
+ *
+ * hashalgo  The hash algorithm.
+ * hsType   The signature type.
+ * output    The buffer to encode into.
+ */
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+{
+    switch (hsType) {
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = ecc_dsa_sa_algo;
+            break;
+#endif
+#ifdef HAVE_ED25519
+        case ed25519_sa_algo:
+            output[0] = ED25519_SA_MAJOR;
+            output[1] = ED25519_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifndef NO_RSA
+        case rsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = rsa_sa_algo;
+            break;
+    #ifdef WC_RSA_PSS
+        /* PSS signatures: 0x080[4-6] */
+        case rsa_pss_sa_algo:
+            output[0] = rsa_pss_sa_algo;
+            output[1] = hashAlgo;
+            break;
+    #endif
+#endif
+        /* ED448: 0x0808 */
+    }
+    (void)hashAlgo;
+    (void)output;
+}
+
+#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+static void SetDigest(WOLFSSL* ssl, int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifndef NO_SHA
+        case sha_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha;
+            ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA */
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256;
+            ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384;
+            ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512;
+            ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA512 */
+    } /* switch */
+}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */
+#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
+#endif /* !NO_CERTS */
+
+#ifndef NO_RSA
+#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+static int TypeHash(int hashAlgo)
+{
+    switch (hashAlgo) {
+    #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            return SHA512h;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            return SHA384h;
+    #endif
+    #ifndef NO_SHA256
+        case sha256_mac:
+            return SHA256h;
+    #endif
+    #ifndef NO_SHA
+        case sha_mac:
+            return SHAh;
+    #endif
+    }
+
+    return 0;
+}
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(WC_RSA_PSS)
+int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
+{
+    switch (hashAlgo) {
+        #ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            *hashType = WC_HASH_TYPE_SHA512;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA512;
+            break;
+        #endif
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            *hashType = WC_HASH_TYPE_SHA384;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA384;
+            break;
+        #endif
+        #ifndef NO_SHA256
+        case sha256_mac:
+            *hashType = WC_HASH_TYPE_SHA256;
+            if (mgf != NULL)
+                *mgf = WC_MGF1SHA256;
+            break;
+        #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return 0;
+}
+#endif
+
+int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+            word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
+            DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("RsaSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+
+    #if defined(HAVE_PK_CALLBACKS)
+        if (ssl->ctx->RsaPssSignCb) {
+            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+            ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz,
+                                         TypeHash(hashAlgo), mgf,
+                                         keyBuf, keySz, ctx);
+        }
+        else
+    #endif
+        {
+            ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key,
+                                                                      ssl->rng);
+        }
+    }
+    else
+#endif
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->RsaSignCb) {
+        void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+        ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+                                                                          ctx);
+    }
+    else
+#endif /*HAVE_PK_CALLBACKS */
+        ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng);
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaSign", ret);
+
+    return ret;
+}
+
+int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
+              int hashAlgo, RsaKey* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("RsaVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+#ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaPssVerifyCb) {
+            void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl);
+            ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out,
+                                           TypeHash(hashAlgo), mgf,
+                                           keyBuf, keySz, ctx);
+        }
+        else
+#endif /*HAVE_PK_CALLBACKS */
+            ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key);
+    }
+    else
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaVerifyCb) {
+        void* ctx = wolfSSL_GetRsaVerifyCtx(ssl);
+        ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+    }
+    else
+#endif /*HAVE_PK_CALLBACKS */
+    {
+        ret = wc_RsaSSL_VerifyInline(in, inSz, out, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("RsaVerify", ret);
+
+    return ret;
+}
+
+/* Verify RSA signature, 0 on success */
+/* This function is used to check the sign result */
+int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
+    const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key,
+    DerBuffer* keyBufInfo)
+{
+    byte* out = NULL;  /* inline result */
+    int   ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+    (void)sigAlgo;
+    (void)hashAlgo;
+
+    WOLFSSL_ENTER("VerifyRsaSign");
+
+    if (verifySig == NULL || plain == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (sigSz > ENCRYPT_LEN) {
+        WOLFSSL_MSG("Signature buffer too big");
+        return BUFFER_E;
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    if (key) {
+        ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+#if defined(WC_RSA_PSS)
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+        int mgf = 0;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, &mgf);
+        if (ret != 0)
+            return ret;
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaPssSignCheckCb) {
+            /* The key buffer includes private/public portion,
+                but only public is used */
+            /* If HSM hardware is checking the signature result you can
+                optionally skip the sign check and return 0 */
+            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+            void* ctx = wolfSSL_GetRsaPssSignCtx(ssl);
+            ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out,
+                                           TypeHash(hashAlgo), mgf,
+                                           keyBuf, keySz, ctx);
+        }
+        else
+    #endif /* HAVE_PK_CALLBACKS */
+        {
+            ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
+                                         key);
+        }
+
+        if (ret > 0) {
+            ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType);
+            if (ret != 0)
+                ret = VERIFY_CERT_ERROR;
+        }
+    }
+    else
+#endif /* WC_RSA_PSS */
+    {
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->ctx->RsaSignCheckCb) {
+            /* The key buffer includes private/public portion,
+                but only public is used */
+            /* If HSM hardware is checking the signature result you can
+                optionally skip the sign check and return 0 */
+            /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */
+            void* ctx = wolfSSL_GetRsaSignCtx(ssl);
+            ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out,
+                keyBuf, keySz, ctx);
+        }
+        else
+    #endif /* HAVE_PK_CALLBACKS */
+        {
+            ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key);
+        }
+
+        if (ret > 0) {
+            if (ret != (int)plainSz || !out ||
+                                            XMEMCMP(plain, out, plainSz) != 0) {
+                WOLFSSL_MSG("RSA Signature verification failed");
+                ret = RSA_SIGN_FAULT;
+            } else {
+                ret = 0;  /* RSA reset */
+            }
+        }
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (key && ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("VerifyRsaSign", ret);
+
+    return ret;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
+    RsaKey* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("RsaDec");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaDecCb) {
+        void* ctx = wolfSSL_GetRsaDecCtx(ssl);
+        ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        #ifdef WC_RSA_BLINDING
+            ret = wc_RsaSetRNG(key, ssl->rng);
+            if (ret != 0)
+                return ret;
+        #endif
+        ret = wc_RsaPrivateDecryptInline(in, inSz, out, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaDec", ret);
+
+    return ret;
+}
+
+int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
+    RsaKey* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("RsaEnc");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->RsaEncCb) {
+        void* ctx = wolfSSL_GetRsaEncCtx(ssl);
+        ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* For positive response return in outSz */
+    if (ret > 0) {
+        *outSz = ret;
+        ret = 0;
+    }
+
+    WOLFSSL_LEAVE("RsaEnc", ret);
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* NO_RSA */
+
+#ifdef HAVE_ECC
+
+int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+    word32* outSz, ecc_key* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("EccSign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->EccSignCb) {
+        void* ctx = wolfSSL_GetEccSignCtx(ssl);
+        ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf,
+            keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccSign", ret);
+
+    return ret;
+}
+
+int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
+    word32 outSz, ecc_key* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("EccVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccVerifyCb) {
+        void* ctx = wolfSSL_GetEccVerifyCtx(ssl);
+        ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz,
+            &ssl->eccVerifyRes, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS  */
+    {
+        ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    {
+        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+    }
+
+    WOLFSSL_LEAVE("EccVerify", ret);
+
+    return ret;
+}
+
+#ifdef HAVE_PK_CALLBACKS
+    /* Gets ECC key for shared secret callback testing
+     * Client side: returns peer key
+     * Server side: returns private key
+     */
+    static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey)
+    {
+        int ret = NO_PEER_KEY;
+        ecc_key* tmpKey = NULL;
+
+        if (ssl == NULL || otherKey == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (ssl->specs.static_ecdh) {
+                if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
+                                           !ssl->peerEccDsaKey->dp) {
+                    return NO_PEER_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->peerEccDsaKey;
+            }
+            else {
+                if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+                                        !ssl->peerEccKey->dp) {
+                    return NO_PEER_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->peerEccKey;
+            }
+        }
+        else if (ssl->options.side == WOLFSSL_SERVER_END) {
+            if (ssl->specs.static_ecdh) {
+                if (ssl->hsKey == NULL) {
+                    return NO_PRIVATE_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->hsKey;
+            }
+            else {
+                if (!ssl->eccTempKeyPresent) {
+                    return NO_PRIVATE_KEY;
+                }
+                tmpKey = (struct ecc_key*)ssl->eccTempKey;
+            }
+        }
+
+        if (tmpKey) {
+            *otherKey = tmpKey;
+            ret = 0;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
+        byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
+        int side)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    ecc_key* otherKey = NULL;
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev;
+#endif
+
+    (void)ssl;
+    (void)pubKeyDer;
+    (void)pubKeySz;
+    (void)side;
+
+    WOLFSSL_ENTER("EccSharedSecret");
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccSharedSecretCb) {
+        ret = EccGetKey(ssl, &otherKey);
+        if (ret != 0)
+            return ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        asyncDev = &otherKey->asyncDev;
+    #endif
+    }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccSharedSecretCb) {
+        void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl);
+        ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
+            pubKeySz, out, outlen, side, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccSharedSecret", ret);
+
+    return ret;
+}
+
+int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
+{
+    int ret = 0;
+    int keySz = 0;
+    int ecc_curve = ECC_CURVE_DEF;
+
+    WOLFSSL_ENTER("EccMakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+    /* get key size */
+    if (peer == NULL) {
+        keySz = ssl->eccTempKeySz;
+    }
+    else {
+        keySz = peer->dp->size;
+    }
+
+    /* get curve type */
+    if (ssl->ecdhCurveOID > 0) {
+        ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
+    }
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->EccKeyGenCb) {
+        void* ctx = wolfSSL_GetEccKeyGenCtx(ssl);
+        ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
+    }
+
+    /* make sure the curve is set for TLS */
+    if (ret == 0 && key->dp) {
+        ssl->ecdhCurveOID = key->dp->oidSum;
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("EccMakeKey", ret);
+
+    return ret;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+/* Check whether the key contains a public key.
+ * If not then pull it out of the leaf certificate.
+ *
+ * ssl  SSL/TLS object.
+ * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise
+ * 0 on success.
+ */
+int Ed25519CheckPubKey(WOLFSSL* ssl)
+{
+    ed25519_key* key = (ed25519_key*)ssl->hsKey;
+    int ret = 0;
+
+    /* Public key required for signing. */
+    if (!key->pubKeySet) {
+        DerBuffer* leaf = ssl->buffers.certificate;
+        DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert),
+                                     ssl->heap, DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            ret = MEMORY_E;
+
+        if (ret == 0) {
+            InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap);
+            ret = DecodeToKey(cert, 0);
+        }
+        if (ret == 0) {
+            ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize,
+                                                                           key);
+        }
+        if (cert != NULL) {
+            FreeDecodedCert(cert);
+            XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+        }
+    }
+
+    return ret;
+}
+
+/* Sign the data using EdDSA and key using X25519.
+ *
+ * ssl    SSL object.
+ * in     Data or message to sign.
+ * inSz   Length of the data.
+ * out    Buffer to hold signature.
+ * outSz  On entry, size of the buffer. On exit, the size of the signature.
+ * key    The private X25519 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+                word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed25519Sign");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#if defined(HAVE_PK_CALLBACKS)
+    if (ssl->ctx->Ed25519SignCb) {
+        void* ctx = wolfSSL_GetEd25519SignCtx(ssl);
+        ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf,
+            keySz, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS */
+    {
+        ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("Ed25519Sign", ret);
+
+    return ret;
+}
+
+/* Verify the data using EdDSA and key using X25519.
+ *
+ * ssl    SSL object.
+ * in     Signature data.
+ * inSz   Length of the signature data in bytes.
+ * msg    Message to verify.
+ * outSz  Length of message in bytes.
+ * key    The public X25519 key data.
+ * keySz  The length of the private key data in bytes.
+ * ctx    The callback context.
+ * returns 0 on success, otherwise the value is an error.
+ */
+int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
+                  word32 msgSz, ed25519_key* key, buffer* keyBufInfo)
+{
+    int ret;
+#ifdef HAVE_PK_CALLBACKS
+    const byte* keyBuf = NULL;
+    word32 keySz = 0;
+
+    if (keyBufInfo) {
+        keyBuf = keyBufInfo->buffer;
+        keySz = keyBufInfo->length;
+    }
+#endif
+
+    (void)ssl;
+    (void)keyBufInfo;
+
+    WOLFSSL_ENTER("Ed25519Verify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->Ed25519VerifyCb) {
+        void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl);
+        ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf,
+                                        keySz, &ssl->eccVerifyRes, ctx);
+    }
+    else
+#endif /* HAVE_PK_CALLBACKS  */
+    {
+        ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz,
+                                    &ssl->eccVerifyRes, key);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    {
+        ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0;
+    }
+
+    WOLFSSL_LEAVE("Ed25519Verify", ret);
+
+    return ret;
+}
+#endif /* HAVE_ED25519 */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CURVE25519
+#ifdef HAVE_PK_CALLBACKS
+    /* Gets X25519 key for shared secret callback testing
+     * Client side: returns peer key
+     * Server side: returns private key
+     */
+    static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey)
+    {
+        int ret = NO_PEER_KEY;
+        struct curve25519_key* tmpKey = NULL;
+
+        if (ssl == NULL || otherKey == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent ||
+                                       !ssl->peerX25519Key->dp) {
+                return NO_PEER_KEY;
+            }
+            tmpKey = (struct curve25519_key*)ssl->peerX25519Key;
+        }
+        else if (ssl->options.side == WOLFSSL_SERVER_END) {
+            if (!ssl->eccTempKeyPresent) {
+                return NO_PRIVATE_KEY;
+            }
+            tmpKey = (struct curve25519_key*)ssl->eccTempKey;
+        }
+
+        if (tmpKey) {
+            *otherKey = (curve25519_key *)tmpKey;
+            ret = 0;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
+        curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz,
+        byte* out, word32* outlen, int side)
+{
+    int ret;
+
+    (void)ssl;
+    (void)pubKeyDer;
+    (void)pubKeySz;
+    (void)side;
+
+    WOLFSSL_ENTER("X25519SharedSecret");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X25519SharedSecretCb) {
+        curve25519_key* otherKey = NULL;
+
+        ret = X25519GetKey(ssl, &otherKey);
+        if (ret == 0) {
+            void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl);
+            ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer,
+                pubKeySz, out, outlen, side, ctx);
+        }
+    }
+    else
+#endif
+    {
+        ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
+                                             EC25519_LITTLE_ENDIAN);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X25519SharedSecret", ret);
+
+    return ret;
+}
+
+static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
+        curve25519_key* peer)
+{
+    int ret = 0;
+
+    (void)peer;
+
+    WOLFSSL_ENTER("X25519MakeKey");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->X25519KeyGenCb) {
+        void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl);
+        ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+    }
+
+    if (ret == 0) {
+        ssl->ecdhCurveOID = ECC_X25519_OID;
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("X25519MakeKey", ret);
+
+    return ret;
+}
+#endif /* HAVE_CURVE25519 */
+
+#if !defined(NO_CERTS) || !defined(NO_PSK)
+#if !defined(NO_DH)
+
+int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
+    byte* priv, word32* privSz,
+    byte* pub, word32* pubSz)
+{
+    int ret;
+
+    WOLFSSL_ENTER("DhGenKeyPair");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+    ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz);
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("DhGenKeyPair", ret);
+
+    return ret;
+}
+
+int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
+    const byte* priv, word32 privSz,
+    const byte* otherPub, word32 otherPubSz,
+    byte* agree, word32* agreeSz)
+{
+    int ret;
+
+    (void)ssl;
+
+    WOLFSSL_ENTER("DhAgree");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* initialize event */
+    ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
+    if (ret != 0)
+        return ret;
+#endif
+
+#ifdef HAVE_PK_CALLBACKS
+    if (ssl->ctx->DhAgreeCb) {
+        void* ctx = wolfSSL_GetDhAgreeCtx(ssl);
+
+        WOLFSSL_MSG("Calling DhAgree Callback Function");
+        ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz,
+                    otherPub, otherPubSz, agree, agreeSz, ctx);
+    }
+    else
+#endif
+    {
+        ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub,
+                otherPubSz);
+    }
+
+    /* Handle async pending response */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    WOLFSSL_LEAVE("DhAgree", ret);
+
+    return ret;
+}
+#endif /* !NO_DH */
+#endif /* !NO_CERTS || !NO_PSK */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+
+#ifdef HAVE_PK_CALLBACKS
+int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
+{
+    int pkcbset = 0;
+    (void)ctx;
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_RSA)
+    if (0
+    #ifdef HAVE_ECC
+        || ctx->EccSignCb != NULL
+    #endif
+    #ifdef HAVE_ED25519
+        || ctx->Ed25519SignCb != NULL
+    #endif
+    #ifndef NO_RSA
+        || ctx->RsaSignCb != NULL
+        || ctx->RsaDecCb != NULL
+        #ifdef WC_RSA_PSS
+        || ctx->RsaPssSignCb != NULL
+        #endif
+    #endif
+    ) {
+        pkcbset = 1;
+    }
+#endif
+    return pkcbset;
+}
+#endif /* HAVE_PK_CALLBACKS */
+
+/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
+   It is used during initialization and to switch an ssl's CTX with
+   wolfSSL_Set_SSL_CTX.  Requires ssl->suites alloc and ssl-arrays with PSK
+   unless writeDup is on.
+
+   ssl      object to initialize
+   ctx      parent factory
+   writeDup flag indicating this is a write dup only
+
+   WOLFSSL_SUCCESS return value on success */
+int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+    byte havePSK = 0;
+    byte haveAnon = 0;
+    byte newSSL;
+    byte haveRSA = 0;
+    byte haveMcast = 0;
+
+    (void)haveAnon; /* Squash unused var warnings */
+    (void)haveMcast;
+
+    if (!ssl || !ctx)
+        return BAD_FUNC_ARG;
+
+    if (ssl->suites == NULL && !writeDup)
+        return BAD_FUNC_ARG;
+
+    newSSL = ssl->ctx == NULL; /* Assign after null check */
+
+#ifndef NO_PSK
+    if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
+        return BAD_FUNC_ARG;  /* needed for copy below */
+    }
+#endif
+
+
+#ifndef NO_RSA
+    haveRSA = 1;
+#endif
+#ifndef NO_PSK
+    havePSK = ctx->havePSK;
+#endif /* NO_PSK */
+#ifdef HAVE_ANON
+    haveAnon = ctx->haveAnon;
+#endif /* HAVE_ANON*/
+#ifdef WOLFSSL_MULTICAST
+    haveMcast = ctx->haveMcast;
+#endif /* WOLFSSL_MULTICAST */
+
+    /* decrement previous CTX reference count if exists.
+     * This should only happen if switching ctxs!*/
+    if (!newSSL) {
+        WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx.");
+        wolfSSL_CTX_free(ssl->ctx);
+    }
+
+    /* increment CTX reference count */
+    if (wc_LockMutex(&ctx->countMutex) != 0) {
+        WOLFSSL_MSG("Couldn't lock CTX count mutex");
+        return BAD_MUTEX_E;
+    }
+    ctx->refCount++;
+    wc_UnLockMutex(&ctx->countMutex);
+    ssl->ctx     = ctx; /* only for passing to calls, options could change */
+    ssl->version = ctx->method->version;
+
+#ifdef HAVE_ECC
+    ssl->eccTempKeySz = ctx->eccTempKeySz;
+    ssl->ecdhCurveOID = ctx->ecdhCurveOID;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    ssl->pkCurveOID = ctx->pkCurveOID;
+#endif
+
+#ifdef OPENSSL_EXTRA
+    ssl->options.mask = ctx->mask;
+    ssl->CBIS         = ctx->CBIS;
+#endif
+    ssl->timeout = ctx->timeout;
+    ssl->verifyCallback    = ctx->verifyCallback;
+    ssl->options.side      = ctx->method->side;
+    ssl->options.downgrade    = ctx->method->downgrade;
+    ssl->options.minDowngrade = ctx->minDowngrade;
+
+    ssl->options.haveDH        = ctx->haveDH;
+    ssl->options.haveNTRU      = ctx->haveNTRU;
+    ssl->options.haveECDSAsig  = ctx->haveECDSAsig;
+    ssl->options.haveECC       = ctx->haveECC;
+    ssl->options.haveStaticECC = ctx->haveStaticECC;
+
+#ifndef NO_PSK
+    ssl->options.havePSK   = ctx->havePSK;
+    ssl->options.client_psk_cb = ctx->client_psk_cb;
+    ssl->options.server_psk_cb = ctx->server_psk_cb;
+#endif /* NO_PSK */
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz;
+#endif
+
+#ifdef HAVE_ANON
+    ssl->options.haveAnon = ctx->haveAnon;
+#endif
+#ifndef NO_DH
+    ssl->options.minDhKeySz = ctx->minDhKeySz;
+    ssl->options.maxDhKeySz = ctx->maxDhKeySz;
+#endif
+#ifndef NO_RSA
+    ssl->options.minRsaKeySz = ctx->minRsaKeySz;
+#endif
+#ifdef HAVE_ECC
+    ssl->options.minEccKeySz = ctx->minEccKeySz;
+#endif
+#ifdef OPENSSL_EXTRA
+    ssl->options.verifyDepth = ctx->verifyDepth;
+#endif
+
+    ssl->options.sessionCacheOff      = ctx->sessionCacheOff;
+    ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
+#ifdef HAVE_EXT_CACHE
+    ssl->options.internalCacheOff     = ctx->internalCacheOff;
+#endif
+
+    ssl->options.verifyPeer     = ctx->verifyPeer;
+    ssl->options.verifyNone     = ctx->verifyNone;
+    ssl->options.failNoCert     = ctx->failNoCert;
+    ssl->options.failNoCertxPSK = ctx->failNoCertxPSK;
+    ssl->options.sendVerify     = ctx->sendVerify;
+
+    ssl->options.partialWrite  = ctx->partialWrite;
+    ssl->options.quietShutdown = ctx->quietShutdown;
+    ssl->options.groupMessages = ctx->groupMessages;
+
+#ifndef NO_DH
+    ssl->buffers.serverDH_P = ctx->serverDH_P;
+    ssl->buffers.serverDH_G = ctx->serverDH_G;
+#endif
+
+#ifndef NO_CERTS
+    /* ctx still owns certificate, certChain, key, dh, and cm */
+    ssl->buffers.certificate = ctx->certificate;
+    ssl->buffers.certChain = ctx->certChain;
+#ifdef WOLFSSL_TLS13
+    ssl->buffers.certChainCnt = ctx->certChainCnt;
+#endif
+    ssl->buffers.key     = ctx->privateKey;
+    ssl->buffers.keyType = ctx->privateKeyType;
+    ssl->buffers.keySz   = ctx->privateKeySz;
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                        !defined(NO_ED25519_CLIENT_AUTH)
+    ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END ||
+                                        ssl->buffers.keyType == ed25519_sa_algo;
+#endif
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ssl->devId = ctx->devId;
+#endif
+
+    if (writeDup == 0) {
+        int keySz = 0;
+#ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+#endif
+
+#ifndef NO_PSK
+        if (ctx->server_hint[0]) {   /* set in CTX */
+            XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,
+                                    sizeof(ssl->arrays->server_hint));
+            ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+        }
+#endif /* NO_PSK */
+
+        if (ctx->suites)
+            *ssl->suites = *ctx->suites;
+        else
+            XMEMSET(ssl->suites, 0, sizeof(Suites));
+
+        /* make sure server has DH parms, and add PSK if there, add NTRU too */
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+        else
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       TRUE, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+
+#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
+        /* make sure server has cert and key unless using PSK, Anon, or
+         * Multicast. This should be true even if just switching ssl ctx */
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                !havePSK && !haveAnon && !haveMcast) {
+
+            /* server certificate must be loaded */
+            if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) {
+                WOLFSSL_MSG("Server missing certificate");
+                return NO_PRIVATE_KEY;
+            }
+
+            /* allow no private key if using PK callbacks and CB is set */
+        #ifdef HAVE_PK_CALLBACKS
+            if (wolfSSL_CTX_IsPrivatePkSet(ctx)) {
+                WOLFSSL_MSG("Using PK for server private key");
+            }
+            else
+        #endif
+            if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+                WOLFSSL_MSG("Server missing private key");
+                return NO_PRIVATE_KEY;
+            }
+        }
+#endif
+
+    }  /* writeDup check */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+    #ifdef WOLFSSL_DTLS
+    ssl->dtls_export = ctx->dtls_export; /* export function for session */
+    #endif
+#endif
+
+    ssl->CBIORecv = ctx->CBIORecv;
+    ssl->CBIOSend = ctx->CBIOSend;
+#ifdef OPENSSL_EXTRA
+    ssl->readAhead = ctx->readAhead;
+#endif
+    ssl->verifyDepth = ctx->verifyDepth;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int InitHandshakeHashes(WOLFSSL* ssl)
+{
+    int ret;
+
+    /* make sure existing handshake hashes are free'd */
+    if (ssl->hsHashes != NULL) {
+        FreeHandshakeHashes(ssl);
+    }
+
+    /* allocate handshake hashes */
+    ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
+                                                           DYNAMIC_TYPE_HASHES);
+    if (ssl->hsHashes == NULL) {
+        WOLFSSL_MSG("HS_Hashes Memory error");
+        return MEMORY_E;
+    }
+    XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes));
+
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+    ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+#endif
+#ifndef NO_SHA
+    ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+#endif
+#endif /* !NO_OLD_TLS */
+#ifndef NO_SHA256
+    ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_SHA384
+    ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_SHA512
+    ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId);
+    if (ret != 0)
+        return ret;
+#endif
+
+    return ret;
+}
+
+void FreeHandshakeHashes(WOLFSSL* ssl)
+{
+    if (ssl->hsHashes) {
+#ifndef NO_OLD_TLS
+    #ifndef NO_MD5
+        wc_Md5Free(&ssl->hsHashes->hashMd5);
+    #endif
+    #ifndef NO_SHA
+        wc_ShaFree(&ssl->hsHashes->hashSha);
+    #endif
+#endif /* !NO_OLD_TLS */
+    #ifndef NO_SHA256
+        wc_Sha256Free(&ssl->hsHashes->hashSha256);
+    #endif
+    #ifdef WOLFSSL_SHA384
+        wc_Sha384Free(&ssl->hsHashes->hashSha384);
+    #endif
+    #ifdef WOLFSSL_SHA512
+        wc_Sha512Free(&ssl->hsHashes->hashSha512);
+    #endif
+    #if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+        if (ssl->hsHashes->messages != NULL) {
+            XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
+            ssl->hsHashes->messages = NULL;
+         }
+    #endif
+
+        XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES);
+        ssl->hsHashes = NULL;
+    }
+}
+
+
+/* init everything to 0, NULL, default values before calling anything that may
+   fail so that destructor has a "good" state to cleanup
+
+   ssl      object to initialize
+   ctx      parent factory
+   writeDup flag indicating this is a write dup only
+
+   0 on success */
+int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
+{
+    int  ret;
+
+    XMEMSET(ssl, 0, sizeof(WOLFSSL));
+
+#if defined(WOLFSSL_STATIC_MEMORY)
+    if (ctx->heap != NULL) {
+        WOLFSSL_HEAP_HINT* ssl_hint;
+        WOLFSSL_HEAP_HINT* ctx_hint;
+
+        /* avoid derefrencing a test value */
+    #ifdef WOLFSSL_HEAP_TEST
+        if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) {
+            ssl->heap = ctx->heap;
+        }
+        else {
+    #endif
+        ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT),
+                                               ctx->heap, DYNAMIC_TYPE_SSL);
+        if (ssl->heap == NULL) {
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT));
+        ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+        ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap));
+
+        /* lock and check IO count / handshake count */
+        if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return BAD_MUTEX_E;
+        }
+        if (ctx_hint->memory->maxHa > 0 &&
+                           ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) {
+            WOLFSSL_MSG("At max number of handshakes for static memory");
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return MEMORY_E;
+        }
+
+        if (ctx_hint->memory->maxIO > 0 &&
+                           ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) {
+            WOLFSSL_MSG("At max number of IO allowed for static memory");
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+            XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
+            ssl->heap = NULL; /* free and set to NULL for IO counter */
+            return MEMORY_E;
+        }
+        ctx_hint->memory->curIO++;
+        ctx_hint->memory->curHa++;
+        ssl_hint->memory = ctx_hint->memory;
+        ssl_hint->haFlag = 1;
+        wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+
+        /* check if tracking stats */
+        if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) {
+            ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC(
+               sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL);
+            if (ssl_hint->stats == NULL) {
+                return MEMORY_E;
+            }
+            XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS));
+        }
+
+        /* check if using fixed IO buffers */
+        if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) {
+            if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
+                WOLFSSL_MSG("Bad memory_mutex lock");
+                return BAD_MUTEX_E;
+            }
+            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) {
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) {
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) {
+                WOLFSSL_MSG("Not enough memory to create fixed IO buffers");
+                wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+                return MEMORY_E;
+            }
+            wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+        }
+    #ifdef WOLFSSL_HEAP_TEST
+        }
+    #endif
+    }
+    else {
+        ssl->heap = ctx->heap;
+    }
+#else
+    ssl->heap = ctx->heap; /* carry over user heap without static memory */
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+
+    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+
+#ifdef KEEP_PEER_CERT
+    InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+
+    ssl->rfd = -1;   /* set to invalid descriptor */
+    ssl->wfd = -1;
+    ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */
+
+    ssl->IOCB_ReadCtx  = &ssl->rfd;  /* prevent invalid pointer access if not */
+    ssl->IOCB_WriteCtx = &ssl->wfd;  /* correctly set */
+
+#ifdef HAVE_NETX
+    ssl->IOCB_ReadCtx  = &ssl->nxCtx;  /* default NetX IO ctx, same for read */
+    ssl->IOCB_WriteCtx = &ssl->nxCtx;  /* and write */
+#endif
+
+    /* initialize states */
+    ssl->options.serverState = NULL_STATE;
+    ssl->options.clientState = NULL_STATE;
+    ssl->options.connectState = CONNECT_BEGIN;
+    ssl->options.acceptState  = ACCEPT_BEGIN;
+    ssl->options.handShakeState  = NULL_STATE;
+    ssl->options.processReply = doProcessInit;
+    ssl->options.asyncState = TLS_ASYNC_BEGIN;
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+    ssl->decrypt.state = CIPHER_STATE_BEGIN;
+
+#ifdef WOLFSSL_DTLS
+    #ifdef WOLFSSL_SCTP
+        ssl->options.dtlsSctp           = ctx->dtlsSctp;
+        ssl->dtlsMtuSz                  = ctx->dtlsMtuSz;
+        ssl->dtls_expected_rx           = ssl->dtlsMtuSz;
+    #else
+        ssl->dtls_expected_rx = MAX_MTU;
+    #endif
+    ssl->dtls_timeout_init              = DTLS_TIMEOUT_INIT;
+    ssl->dtls_timeout_max               = DTLS_TIMEOUT_MAX;
+    ssl->dtls_timeout                   = ssl->dtls_timeout_init;
+    ssl->buffers.dtlsCtx.rfd            = -1;
+    ssl->buffers.dtlsCtx.wfd            = -1;
+#endif
+
+    #ifndef NO_OLD_TLS
+        ssl->hmac = SSL_hmac; /* default to SSLv3 */
+    #elif !defined(WOLFSSL_NO_TLS12)
+        ssl->hmac = TLS_hmac;
+    #endif
+
+
+    ssl->cipher.ssl = ssl;
+
+#ifdef HAVE_EXTENDED_MASTER
+    ssl->options.haveEMS = ctx->haveEMS;
+#endif
+    ssl->options.useClientOrder = ctx->useClientOrder;
+
+#ifdef WOLFSSL_TLS13
+    #ifdef HAVE_SESSION_TICKET
+        ssl->options.noTicketTls13 = ctx->noTicketTls13;
+    #endif
+    ssl->options.noPskDheKe = ctx->noPskDheKe;
+    #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
+    #endif
+
+    if (ctx->numGroups > 0) {
+        XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups);
+        ssl->numGroups = ctx->numGroups;
+    }
+#endif
+
+#ifdef HAVE_TLS_EXTENSIONS
+#ifdef HAVE_MAX_FRAGMENT
+    ssl->max_fragment = MAX_RECORD_SIZE;
+#endif
+#ifdef HAVE_ALPN
+    ssl->alpn_client_list = NULL;
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        ssl->alpnSelect    = ctx->alpnSelect;
+        ssl->alpnSelectArg = ctx->alpnSelectArg;
+    #endif
+#endif
+#ifdef HAVE_SUPPORTED_CURVES
+    ssl->options.userCurves = ctx->userCurves;
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+
+    /* default alert state (none) */
+    ssl->alert_history.last_rx.code  = -1;
+    ssl->alert_history.last_rx.level = -1;
+    ssl->alert_history.last_tx.code  = -1;
+    ssl->alert_history.last_tx.level = -1;
+
+#ifdef OPENSSL_EXTRA
+    /* copy over application session context ID */
+    ssl->sessionCtxSz = ctx->sessionCtxSz;
+    XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
+    ssl->cbioFlag = ctx->cbioFlag;
+#endif
+
+    InitCiphers(ssl);
+    InitCipherSpecs(&ssl->specs);
+
+    /* all done with init, now can return errors, call other stuff */
+
+    if (!writeDup) {
+        /* arrays */
+        ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
+                                                           DYNAMIC_TYPE_ARRAYS);
+        if (ssl->arrays == NULL) {
+            WOLFSSL_MSG("Arrays Memory error");
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->arrays, 0, sizeof(Arrays));
+        ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+        if (ssl->arrays->preMasterSecret == NULL) {
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN);
+
+        /* suites */
+        ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+                                   DYNAMIC_TYPE_SUITES);
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Suites Memory error");
+            return MEMORY_E;
+        }
+    }
+
+    /* Initialize SSL with the appropriate fields from it's ctx */
+    /* requires valid arrays and suites unless writeDup ing */
+    if ((ret =  SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS)
+        return ret;
+
+    ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
+
+#ifdef SINGLE_THREADED
+    ssl->rng = ctx->rng;   /* CTX may have one, if so use it */
+#endif
+
+    if (ssl->rng == NULL) {
+        /* RNG */
+        ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
+        if (ssl->rng == NULL) {
+            WOLFSSL_MSG("RNG Memory error");
+            return MEMORY_E;
+        }
+        XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
+        ssl->options.weOwnRng = 1;
+
+        /* FIPS RNG API does not accept a heap hint */
+#ifndef HAVE_FIPS
+        if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) {
+            WOLFSSL_MSG("RNG Init error");
+            return ret;
+        }
+#else
+        if ( (ret = wc_InitRng(ssl->rng)) != 0) {
+            WOLFSSL_MSG("RNG Init error");
+            return ret;
+        }
+#endif
+    }
+
+#ifdef HAVE_WRITE_DUP
+    if (writeDup) {
+        /* all done */
+        return 0;
+    }
+#endif
+
+    /* hsHashes */
+    ret = InitHandshakeHashes(ssl);
+    if (ret != 0)
+        return ret;
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
+        ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
+        if (ret != 0) {
+            WOLFSSL_MSG("DTLS Cookie Secret error");
+            return ret;
+        }
+    }
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+#ifdef HAVE_SECRET_CALLBACK
+    ssl->sessionSecretCb  = NULL;
+    ssl->sessionSecretCtx = NULL;
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    ssl->session.ticket = ssl->session.staticTicket;
+#endif
+
+#ifdef WOLFSSL_MULTICAST
+    if (ctx->haveMcast) {
+        int i;
+
+        ssl->options.haveMcast = 1;
+        ssl->options.mcastID = ctx->mcastID;
+
+        /* Force the state to look like handshake has completed. */
+        /* Keying material is supplied externally. */
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.connectState = SECOND_REPLY_DONE;
+        ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone = 1;
+
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++)
+            ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID;
+    }
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    /* use secure renegotiation by default (not recommend) */
+    #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
+        ret = wolfSSL_UseSecureRenegotiation(ssl);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+    #endif
+#endif
+
+    return 0;
+}
+
+
+/* free use of temporary arrays */
+void FreeArrays(WOLFSSL* ssl, int keep)
+{
+    if (ssl->arrays) {
+        if (keep) {
+            /* keeps session id for user retrieval */
+            XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN);
+            ssl->session.sessionIDSz = ssl->arrays->sessionIDSz;
+        }
+        if (ssl->arrays->preMasterSecret) {
+            XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+            ssl->arrays->preMasterSecret = NULL;
+        }
+        XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+        ssl->arrays->pendingMsg = NULL;
+        ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */
+    }
+    XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+    ssl->arrays = NULL;
+}
+
+void FreeKey(WOLFSSL* ssl, int type, void** pKey)
+{
+    if (ssl && pKey && *pKey) {
+        switch (type) {
+        #ifndef NO_RSA
+            case DYNAMIC_TYPE_RSA:
+                wc_FreeRsaKey((RsaKey*)*pKey);
+                break;
+        #endif /* ! NO_RSA */
+        #ifdef HAVE_ECC
+            case DYNAMIC_TYPE_ECC:
+                wc_ecc_free((ecc_key*)*pKey);
+                break;
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            case DYNAMIC_TYPE_ED25519:
+                wc_ed25519_free((ed25519_key*)*pKey);
+                break;
+        #endif /* HAVE_CURVE25519 */
+        #ifdef HAVE_CURVE25519
+            case DYNAMIC_TYPE_CURVE25519:
+                wc_curve25519_free((curve25519_key*)*pKey);
+                break;
+        #endif /* HAVE_CURVE25519 */
+        #ifndef NO_DH
+            case DYNAMIC_TYPE_DH:
+                wc_FreeDhKey((DhKey*)*pKey);
+                break;
+        #endif /* !NO_DH */
+            default:
+                break;
+        }
+        XFREE(*pKey, ssl->heap, type);
+
+        /* Reset pointer */
+        *pKey = NULL;
+    }
+}
+
+int AllocKey(WOLFSSL* ssl, int type, void** pKey)
+{
+    int ret = BAD_FUNC_ARG;
+    int sz = 0;
+
+    if (ssl == NULL || pKey == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* Sanity check key destination */
+    if (*pKey != NULL) {
+        WOLFSSL_MSG("Key already present!");
+        return BAD_STATE_E;
+    }
+
+    /* Determine size */
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            sz = sizeof(RsaKey);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            sz = sizeof(ecc_key);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            sz = sizeof(ed25519_key);
+            break;
+    #endif /* HAVE_ED25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            sz = sizeof(curve25519_key);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            sz = sizeof(DhKey);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    if (sz == 0) {
+        return NOT_COMPILED_IN;
+    }
+
+    /* Allocate memeory for key */
+    *pKey = XMALLOC(sz, ssl->heap, type);
+    if (*pKey == NULL) {
+        return MEMORY_E;
+    }
+
+    /* Initialize key */
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            wc_ed25519_init((ed25519_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            wc_curve25519_init((curve25519_key*)*pKey);
+            ret = 0;
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    /* On error free handshake key */
+    if (ret != 0) {
+        FreeKey(ssl, type, pKey);
+    }
+
+    return ret;
+}
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+    defined(HAVE_CURVE25519)
+static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
+{
+    int ret = 0;
+
+    (void)ssl;
+
+    switch (type) {
+    #ifndef NO_RSA
+        case DYNAMIC_TYPE_RSA:
+            wc_FreeRsaKey((RsaKey*)pKey);
+            ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* ! NO_RSA */
+    #ifdef HAVE_ECC
+        case DYNAMIC_TYPE_ECC:
+            wc_ecc_free((ecc_key*)pKey);
+            ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        case DYNAMIC_TYPE_ED25519:
+            wc_ed25519_free((ed25519_key*)pKey);
+            ret = wc_ed25519_init((ed25519_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifdef HAVE_CURVE25519
+        case DYNAMIC_TYPE_CURVE25519:
+            wc_curve25519_free((curve25519_key*)pKey);
+            ret = wc_curve25519_init((curve25519_key*)pKey);
+            break;
+    #endif /* HAVE_CURVE25519 */
+    #ifndef NO_DH
+        case DYNAMIC_TYPE_DH:
+            wc_FreeDhKey((DhKey*)pKey);
+            ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId);
+            break;
+    #endif /* !NO_DH */
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return ret;
+}
+#endif
+
+void FreeKeyExchange(WOLFSSL* ssl)
+{
+    /* Cleanup signature buffer */
+    if (ssl->buffers.sig.buffer) {
+        XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        ssl->buffers.sig.buffer = NULL;
+        ssl->buffers.sig.length = 0;
+    }
+
+    /* Cleanup digest buffer */
+    if (ssl->buffers.digest.buffer) {
+        XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST);
+        ssl->buffers.digest.buffer = NULL;
+        ssl->buffers.digest.length = 0;
+    }
+
+    /* Free handshake key */
+    FreeKey(ssl, ssl->hsType, &ssl->hsKey);
+
+#ifndef NO_DH
+    /* Free temp DH key */
+    FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key);
+#endif
+
+    /* Cleanup async */
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->async.freeArgs) {
+        ssl->async.freeArgs(ssl, ssl->async.args);
+        ssl->async.freeArgs = NULL;
+    }
+#endif
+}
+
+/* In case holding SSL object in array and don't want to free actual ssl */
+void SSL_ResourceFree(WOLFSSL* ssl)
+{
+    /* Note: any resources used during the handshake should be released in the
+     * function FreeHandshakeResources(). Be careful with the special cases
+     * like the RNG which may optionally be kept for the whole session. (For
+     * example with the RNG, it isn't used beyond the handshake except when
+     * using stream ciphers where it is retained. */
+
+    FreeCiphers(ssl);
+    FreeArrays(ssl, 0);
+    FreeKeyExchange(ssl);
+    if (ssl->options.weOwnRng) {
+        wc_FreeRng(ssl->rng);
+        XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+    }
+    XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
+    FreeHandshakeHashes(ssl);
+    XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    /* clear keys struct after session */
+    ForceZero(&ssl->keys, sizeof(Keys));
+
+#ifndef NO_DH
+    if (ssl->buffers.serverDH_Priv.buffer) {
+        ForceZero(ssl->buffers.serverDH_Priv.buffer,
+                                             ssl->buffers.serverDH_Priv.length);
+    }
+    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    /* parameters (p,g) may be owned by ctx */
+    if (ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+#endif /* !NO_DH */
+#ifndef NO_CERTS
+    ssl->keepCert = 0; /* make sure certificate is free'd */
+    wolfSSL_UnloadCertsKeys(ssl);
+#endif
+#ifndef NO_RSA
+    FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+    ssl->peerRsaKeyPresent = 0;
+#endif
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, FORCED_FREE);
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        ShrinkOutputBuffer(ssl);
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+    XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
+          DYNAMIC_TYPE_COOKIE_PWD);
+#endif
+#ifdef WOLFSSL_DTLS
+    DtlsMsgPoolReset(ssl);
+    if (ssl->dtls_rx_msg_list != NULL) {
+        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+        ssl->dtls_rx_msg_list = NULL;
+        ssl->dtls_rx_msg_list_sz = 0;
+    }
+    XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
+    ssl->buffers.dtlsCtx.peer.sa = NULL;
+#ifndef NO_WOLFSSL_SERVER
+    XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
+          DYNAMIC_TYPE_COOKIE_PWD);
+#endif
+#endif /* WOLFSSL_DTLS */
+#ifdef OPENSSL_EXTRA
+    if (ssl->biord != ssl->biowr)        /* only free write if different */
+        wolfSSL_BIO_free(ssl->biowr);
+    wolfSSL_BIO_free(ssl->biord);        /* always free read bio */
+#endif
+#ifdef HAVE_LIBZ
+    FreeStreams(ssl);
+#endif
+#ifdef HAVE_ECC
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+    ssl->peerEccKeyPresent = 0;
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+    ssl->peerEccDsaKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    {
+        int dtype;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
+    #ifdef HAVE_CURVE25519
+    #ifdef HAVE_ECC
+        if (ssl->peerX25519KeyPresent ||
+                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+    #endif /* HAVE_ECC */
+         {
+            dtype = DYNAMIC_TYPE_CURVE25519;
+         }
+    #endif /* HAVE_CURVE25519 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+        ssl->eccTempKeyPresent = 0;
+    }
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
+#ifdef HAVE_CURVE25519
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+    ssl->peerX25519KeyPresent = 0;
+#endif
+#ifdef HAVE_ED25519
+    FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key);
+    ssl->peerEd25519KeyPresent = 0;
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl->buffers.peerEd25519Key.buffer != NULL) {
+            XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+                                                          DYNAMIC_TYPE_ED25519);
+            ssl->buffers.peerEd25519Key.buffer = NULL;
+        }
+    #endif
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
+    #endif /* HAVE_ECC */
+    #ifndef NO_RSA
+        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX_FreeAll(ssl->extensions, ssl->heap);
+
+#ifdef HAVE_ALPN
+    if (ssl->alpn_client_list != NULL) {
+        XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
+        ssl->alpn_client_list = NULL;
+    }
+#endif
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef HAVE_NETX
+    if (ssl->nxCtx.nxPacket)
+        nx_packet_release(ssl->nxCtx.nxPacket);
+#endif
+#ifdef KEEP_PEER_CERT
+    FreeX509(&ssl->peerCert);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+        ssl->session.ticketLen = 0;
+    }
+#endif
+#ifdef HAVE_EXT_CACHE
+    wolfSSL_SESSION_free(ssl->extSession);
+#endif
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite) {
+        FreeWriteDup(ssl);
+    }
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    while (ssl->certReqCtx != NULL) {
+        CertReqCtx* curr = ssl->certReqCtx;
+        ssl->certReqCtx = curr->next;
+        XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* check if using fixed io buffers and free them */
+    if (ssl->heap != NULL) {
+    #ifdef WOLFSSL_HEAP_TEST
+    /* avoid dereferencing a test value */
+    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
+    #endif
+        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
+        WOLFSSL_HEAP*      ctx_heap;
+        void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
+
+        ctx_heap = ssl_hint->memory;
+        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+        }
+        ctx_heap->curIO--;
+        if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) {
+            WOLFSSL_MSG("Error freeing fixed output buffer");
+        }
+        if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) {
+            WOLFSSL_MSG("Error freeing fixed output buffer");
+        }
+        if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/
+            ctx_heap->curHa--;
+        }
+        wc_UnLockMutex(&(ctx_heap->memory_mutex));
+
+        /* check if tracking stats */
+        if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
+            XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
+        }
+        XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
+    #ifdef WOLFSSL_HEAP_TEST
+    }
+    #endif
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+}
+
+/* Free any handshake resources no longer needed */
+void FreeHandshakeResources(WOLFSSL* ssl)
+{
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
+        WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
+        return;
+    }
+#endif
+
+    /* input buffer */
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+    /* suites */
+    XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
+    ssl->suites = NULL;
+
+    /* hsHashes */
+    FreeHandshakeHashes(ssl);
+
+    /* RNG */
+    if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) {
+        if (ssl->options.weOwnRng) {
+            wc_FreeRng(ssl->rng);
+            XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG);
+            ssl->rng = NULL;
+            ssl->options.weOwnRng = 0;
+        }
+    }
+
+#ifdef WOLFSSL_DTLS
+    /* DTLS_POOL */
+    if (ssl->options.dtls) {
+        DtlsMsgPoolReset(ssl);
+        DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
+        ssl->dtls_rx_msg_list = NULL;
+        ssl->dtls_rx_msg_list_sz = 0;
+    }
+#endif
+
+    /* arrays */
+    if (ssl->options.saveArrays == 0)
+        FreeArrays(ssl, 1);
+
+#ifndef NO_RSA
+    /* peerRsaKey */
+    FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey);
+    ssl->peerRsaKeyPresent = 0;
+#endif
+
+#ifdef HAVE_ECC
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+    ssl->peerEccKeyPresent = 0;
+    FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey);
+    ssl->peerEccDsaKeyPresent = 0;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    {
+        int dtype;
+    #ifdef HAVE_ECC
+        dtype = DYNAMIC_TYPE_ECC;
+    #endif
+    #ifdef HAVE_CURVE25519
+    #ifdef HAVE_ECC
+        if (ssl->peerX25519KeyPresent ||
+                              ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519)
+    #endif /* HAVE_ECC */
+         {
+            dtype = DYNAMIC_TYPE_CURVE25519;
+         }
+    #endif /* HAVE_CURVE25519 */
+        FreeKey(ssl, dtype, (void**)&ssl->eccTempKey);
+        ssl->eccTempKeyPresent = 0;
+    }
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
+#ifdef HAVE_CURVE25519
+    FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key);
+    ssl->peerX25519KeyPresent = 0;
+#endif
+#ifndef NO_DH
+    if (ssl->buffers.serverDH_Priv.buffer) {
+        ForceZero(ssl->buffers.serverDH_Priv.buffer,
+                                             ssl->buffers.serverDH_Priv.length);
+    }
+    XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+    ssl->buffers.serverDH_Priv.buffer = NULL;
+    XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    ssl->buffers.serverDH_Pub.buffer = NULL;
+    /* parameters (p,g) may be owned by ctx */
+    if (ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_G.buffer = NULL;
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+    }
+#endif /* !NO_DH */
+#ifndef NO_CERTS
+    wolfSSL_UnloadCertsKeys(ssl);
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
+        ssl->buffers.peerEccDsaKey.buffer = NULL;
+    #endif /* HAVE_ECC */
+    #ifndef NO_RSA
+        XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA);
+        ssl->buffers.peerRsaKey.buffer = NULL;
+    #endif /* NO_RSA */
+    #ifdef HAVE_ED25519
+        XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap,
+                                                          DYNAMIC_TYPE_ED25519);
+        ssl->buffers.peerEd25519Key.buffer = NULL;
+    #endif
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifdef HAVE_QSH
+    QSH_FreeAll(ssl);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+        ssl->session.ticketLen = 0;
+    }
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    /* when done with handshake decrement current handshake count */
+    if (ssl->heap != NULL) {
+    #ifdef WOLFSSL_HEAP_TEST
+    /* avoid dereferencing a test value */
+    if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
+    #endif
+        WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
+        WOLFSSL_HEAP*      ctx_heap;
+
+        ctx_heap = ssl_hint->memory;
+        if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
+            WOLFSSL_MSG("Bad memory_mutex lock");
+        }
+        ctx_heap->curHa--;
+        ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */
+        wc_UnLockMutex(&(ctx_heap->memory_mutex));
+    #ifdef WOLFSSL_HEAP_TEST
+    }
+    #endif
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+}
+
+
+/* heap argument is the heap hint used when creating SSL */
+void FreeSSL(WOLFSSL* ssl, void* heap)
+{
+    if (ssl->ctx) {
+        FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */
+    }
+    SSL_ResourceFree(ssl);
+    XFREE(ssl, heap, DYNAMIC_TYPE_SSL);
+    (void)heap;
+}
+
+#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \
+    ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \
+     && defined(HAVE_AEAD))
+static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
+{
+    if (verify) {
+        seq[0] = ssl->keys.peer_sequence_number_hi;
+        seq[1] = ssl->keys.peer_sequence_number_lo++;
+        if (seq[1] > ssl->keys.peer_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.peer_sequence_number_hi++;
+        }
+    }
+    else {
+        seq[0] = ssl->keys.sequence_number_hi;
+        seq[1] = ssl->keys.sequence_number_lo++;
+        if (seq[1] > ssl->keys.sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.sequence_number_hi++;
+        }
+    }
+}
+
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
+{
+    if (order == PREV_ORDER) {
+        /* Previous epoch case */
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
+                     (ssl->options.mcastID << 8) |
+                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) |
+                     (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_prev_sequence_number_lo;
+    }
+    else if (order == PEER_ORDER) {
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = (ssl->keys.curEpoch << 16) |
+                     (ssl->keys.curPeerId << 8) |
+                     (ssl->keys.curSeq_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = (ssl->keys.curEpoch << 16) |
+                     (ssl->keys.curSeq_hi & 0xFFFF);
+        seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
+    }
+    else {
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            seq[0] = (ssl->keys.dtls_epoch << 16) |
+                     (ssl->options.mcastID << 8) |
+                     (ssl->keys.dtls_sequence_number_hi & 0xFF);
+        #endif
+        }
+        else
+            seq[0] = (ssl->keys.dtls_epoch << 16) |
+                     (ssl->keys.dtls_sequence_number_hi & 0xFFFF);
+        seq[1] = ssl->keys.dtls_sequence_number_lo;
+    }
+}
+
+static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order)
+{
+    word32 seq;
+
+    if (order == PREV_ORDER) {
+        seq = ssl->keys.dtls_prev_sequence_number_lo++;
+        if (seq > ssl->keys.dtls_prev_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.dtls_prev_sequence_number_hi++;
+        }
+    }
+    else if (order == PEER_ORDER) {
+        seq = ssl->keys.peer_sequence_number_lo++;
+        if (seq > ssl->keys.peer_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.peer_sequence_number_hi++;
+        }
+    }
+    else {
+        seq = ssl->keys.dtls_sequence_number_lo++;
+        if (seq > ssl->keys.dtls_sequence_number_lo) {
+            /* handle rollover */
+            ssl->keys.dtls_sequence_number_hi++;
+        }
+    }
+}
+#endif /* WOLFSSL_DTLS */
+
+
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+    word32 seq[2] = {0, 0};
+
+    if (!ssl->options.dtls) {
+        GetSEQIncrement(ssl, verifyOrder, seq);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+        DtlsGetSEQ(ssl, verifyOrder, seq);
+#endif
+    }
+
+    c32toa(seq[0], out);
+    c32toa(seq[1], out + OPAQUE32_LEN);
+}
+#endif
+
+#ifdef WOLFSSL_DTLS
+
+/* functions for managing DTLS datagram reordering */
+
+/* Need to allocate space for the handshake message header. The hashing
+ * routines assume the message pointer is still within the buffer that
+ * has the headers, and will include those headers in the hash. The store
+ * routines need to take that into account as well. New will allocate
+ * extra space for the headers. */
+DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
+{
+    DtlsMsg* msg = NULL;
+
+    (void)heap;
+    msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG);
+
+    if (msg != NULL) {
+        XMEMSET(msg, 0, sizeof(DtlsMsg));
+        msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
+                                                heap, DYNAMIC_TYPE_DTLS_BUFFER);
+        if (msg->buf != NULL) {
+            msg->sz = sz;
+            msg->type = no_shake;
+            msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
+        }
+        else {
+            XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG);
+            msg = NULL;
+        }
+    }
+
+    return msg;
+}
+
+void DtlsMsgDelete(DtlsMsg* item, void* heap)
+{
+    (void)heap;
+
+    if (item != NULL) {
+        DtlsFrag* cur = item->fragList;
+        while (cur != NULL) {
+            DtlsFrag* next = cur->next;
+            XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
+            cur = next;
+        }
+        if (item->buf != NULL)
+            XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
+        XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
+    }
+}
+
+
+void DtlsMsgListDelete(DtlsMsg* head, void* heap)
+{
+    DtlsMsg* next;
+    while (head) {
+        next = head->next;
+        DtlsMsgDelete(head, heap);
+        head = next;
+    }
+}
+
+
+/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
+static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
+                                byte* buf, word32* bytesLeft, void* heap)
+{
+    DtlsFrag* newFrag;
+    word32 added = end - *begin + 1;
+
+    (void)heap;
+    newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
+                                 DYNAMIC_TYPE_DTLS_FRAG);
+    if (newFrag != NULL) {
+        newFrag->next = NULL;
+        newFrag->begin = *begin;
+        newFrag->end = end;
+
+        XMEMCPY(buf + *begin, data, added);
+        *bytesLeft -= added;
+        *begin = newFrag->end + 1;
+    }
+
+    return newFrag;
+}
+
+
+int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type,
+                                   word32 fragOffset, word32 fragSz, void* heap)
+{
+    if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
+                                             (fragOffset + fragSz) <= msg->sz) {
+        DtlsFrag* cur = msg->fragList;
+        DtlsFrag* prev = cur;
+        DtlsFrag* newFrag;
+        word32 bytesLeft = fragSz; /* could be overlapping fragment */
+        word32 startOffset = fragOffset;
+        word32 added;
+
+        msg->seq = seq;
+        msg->type = type;
+
+        if (fragOffset == 0) {
+            XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
+                    DTLS_HANDSHAKE_HEADER_SZ);
+            c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
+        }
+
+        /* if no mesage data, just return */
+        if (fragSz == 0)
+            return 0;
+
+        /* if list is empty add full fragment to front */
+        if (cur == NULL) {
+            newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
+                                     msg->msg, &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz = fragSz;
+            msg->fragList = newFrag;
+
+            return 0;
+        }
+
+        /* add to front if before current front, up to next->begin */
+        if (fragOffset < cur->begin) {
+            word32 end = fragOffset + fragSz - 1;
+
+            if (end >= cur->begin)
+                end = cur->begin - 1;
+
+            added = end - fragOffset + 1;
+            newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
+                                     &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz += added;
+
+            newFrag->next = cur;
+            msg->fragList = newFrag;
+        }
+
+        /* while we have bytes left, try to find a gap to fill */
+        while (bytesLeft > 0) {
+            /* get previous packet in list */
+            while (cur && (fragOffset >= cur->begin)) {
+                prev = cur;
+                cur = cur->next;
+            }
+
+            /* don't add duplicate data */
+            if (prev->end >= fragOffset) {
+                if ( (fragOffset + bytesLeft - 1) <= prev->end)
+                    return 0;
+                fragOffset = prev->end + 1;
+                bytesLeft = startOffset + fragSz - fragOffset;
+            }
+
+            if (cur == NULL)
+                /* we're at the end */
+                added = bytesLeft;
+            else
+                /* we're in between two frames */
+                added = min(bytesLeft, cur->begin - fragOffset);
+
+            /* data already there */
+            if (added == 0)
+                continue;
+
+            newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
+                                     data + fragOffset - startOffset,
+                                     msg->msg, &bytesLeft, heap);
+            if (newFrag == NULL)
+                return MEMORY_E;
+
+            msg->fragSz += added;
+
+            newFrag->next = prev->next;
+            prev->next = newFrag;
+        }
+    }
+
+    return 0;
+}
+
+
+DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq)
+{
+    while (head != NULL && head->seq != seq) {
+        head = head->next;
+    }
+    return head;
+}
+
+
+void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data,
+        word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap)
+{
+    /* See if seq exists in the list. If it isn't in the list, make
+     * a new item of size dataSz, copy fragSz bytes from data to msg->msg
+     * starting at offset fragOffset, and add fragSz to msg->fragSz. If
+     * the seq is in the list and it isn't full, copy fragSz bytes from
+     * data to msg->msg starting at offset fragOffset, and add fragSz to
+     * msg->fragSz. Insertions take into account data already in the list
+     * in case there are overlaps in the handshake message due to retransmit
+     * messages. The new item should be inserted into the list in its
+     * proper position.
+     *
+     * 1. Find seq in list, or where seq should go in list. If seq not in
+     *    list, create new item and insert into list. Either case, keep
+     *    pointer to item.
+     * 2. Copy the data from the message to the stored message where it
+     *    belongs without overlaps.
+     */
+
+    DtlsMsg* head = ssl->dtls_rx_msg_list;
+
+    if (head != NULL) {
+        DtlsMsg* cur = DtlsMsgFind(head, seq);
+        if (cur == NULL) {
+            cur = DtlsMsgNew(dataSz, heap);
+            if (cur != NULL) {
+                if (DtlsMsgSet(cur, seq, data, type,
+                                                fragOffset, fragSz, heap) < 0) {
+                    DtlsMsgDelete(cur, heap);
+                }
+                else {
+                    ssl->dtls_rx_msg_list_sz++;
+                    head = DtlsMsgInsert(head, cur);
+                }
+            }
+        }
+        else {
+            /* If this fails, the data is just dropped. */
+            DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap);
+        }
+    }
+    else {
+        head = DtlsMsgNew(dataSz, heap);
+        if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) {
+            DtlsMsgDelete(head, heap);
+            head = NULL;
+        }
+        else {
+            ssl->dtls_rx_msg_list_sz++;
+        }
+    }
+
+    ssl->dtls_rx_msg_list = head;
+}
+
+
+/* DtlsMsgInsert() is an in-order insert. */
+DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
+{
+    if (head == NULL || item->seq < head->seq) {
+        item->next = head;
+        head = item;
+    }
+    else if (head->next == NULL) {
+        head->next = item;
+    }
+    else {
+        DtlsMsg* cur = head->next;
+        DtlsMsg* prev = head;
+        while (cur) {
+            if (item->seq < cur->seq) {
+                item->next = cur;
+                prev->next = item;
+                break;
+            }
+            prev = cur;
+            cur = cur->next;
+        }
+        if (cur == NULL) {
+            prev->next = item;
+        }
+    }
+
+    return head;
+}
+
+
+/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */
+int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz)
+{
+    DtlsMsg* item;
+    int ret = 0;
+
+    if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ)
+        return DTLS_POOL_SZ_E;
+
+    item = DtlsMsgNew(dataSz, ssl->heap);
+
+    if (item != NULL) {
+        DtlsMsg* cur = ssl->dtls_tx_msg_list;
+
+        XMEMCPY(item->buf, data, dataSz);
+        item->sz = dataSz;
+        item->seq = ssl->keys.dtls_epoch;
+
+        if (cur == NULL)
+            ssl->dtls_tx_msg_list = item;
+        else {
+            while (cur->next)
+                cur = cur->next;
+            cur->next = item;
+        }
+        ssl->dtls_tx_msg_list_sz++;
+    }
+    else
+        ret = MEMORY_E;
+
+    return ret;
+}
+
+
+/* DtlsMsgPoolTimeout() updates the timeout time. */
+int DtlsMsgPoolTimeout(WOLFSSL* ssl)
+{
+    int result = -1;
+    if (ssl->dtls_timeout <  ssl->dtls_timeout_max) {
+        ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER;
+        result = 0;
+    }
+    return result;
+}
+
+
+/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout
+ * value. */
+void DtlsMsgPoolReset(WOLFSSL* ssl)
+{
+    if (ssl->dtls_tx_msg_list) {
+        DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap);
+        ssl->dtls_tx_msg_list = NULL;
+        ssl->dtls_tx_msg_list_sz = 0;
+        ssl->dtls_timeout = ssl->dtls_timeout_init;
+    }
+}
+
+
+int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset)
+{
+    /**
+     * only the first message from previous flight should be valid
+     * to be used for triggering retransmission of whole DtlsMsgPool.
+     * change cipher suite type is not verified here
+     */
+    return ((fragOffset == 0) &&
+           (((ssl->options.side == WOLFSSL_SERVER_END) &&
+             ((type == client_hello) ||
+             ((ssl->options.verifyPeer) && (type == certificate)) ||
+             ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) ||
+            ((ssl->options.side == WOLFSSL_CLIENT_END) &&
+             (type == server_hello))));
+}
+
+
+/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is
+ * updated with new sequence numbers, and will be re-encrypted if needed. */
+int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
+{
+    int ret = 0;
+    DtlsMsg* pool = ssl->dtls_tx_msg_list;
+
+    if (pool != NULL) {
+
+        while (pool != NULL) {
+            if (pool->seq == 0) {
+                DtlsRecordLayerHeader* dtls;
+                int epochOrder;
+
+                dtls = (DtlsRecordLayerHeader*)pool->buf;
+                /* If the stored record's epoch is 0, and the currently set
+                 * epoch is 0, use the "current order" sequence number.
+                 * If the stored record's epoch is 0 and the currently set
+                 * epoch is not 0, the stored record is considered a "previous
+                 * order" sequence number. */
+                epochOrder = (ssl->keys.dtls_epoch == 0) ?
+                             CUR_ORDER : PREV_ORDER;
+
+                WriteSEQ(ssl, epochOrder, dtls->sequence_number);
+                DtlsSEQIncrement(ssl, epochOrder);
+                if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0)
+                    return ret;
+
+                XMEMCPY(ssl->buffers.outputBuffer.buffer,
+                        pool->buf, pool->sz);
+                ssl->buffers.outputBuffer.idx = 0;
+                ssl->buffers.outputBuffer.length = pool->sz;
+            }
+            else if (pool->seq == ssl->keys.dtls_epoch) {
+                byte*  input;
+                byte*  output;
+                int    inputSz, sendSz;
+
+                input = pool->buf;
+                inputSz = pool->sz;
+                sendSz = inputSz + MAX_MSG_EXTRA;
+
+                if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+                    return ret;
+
+                output = ssl->buffers.outputBuffer.buffer +
+                         ssl->buffers.outputBuffer.length;
+                sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                      handshake, 0, 0, 0);
+                if (sendSz < 0)
+                    return BUILD_MSG_ERROR;
+
+                ssl->buffers.outputBuffer.length += sendSz;
+            }
+
+            ret = SendBuffered(ssl);
+            if (ret < 0) {
+                return ret;
+            }
+
+            /**
+             * on server side, retranmission is being triggered only by sending
+             * first message of given flight, in order to trigger client
+             * to retransmit its whole flight. Sending the whole previous flight
+             * could lead to retranmission of previous client flight for each
+             * server message from previous flight. Therefore one message should
+             * be enough to do the trick.
+             */
+            if (sendOnlyFirstPacket &&
+                ssl->options.side == WOLFSSL_SERVER_END) {
+
+                pool = NULL;
+            }
+            else
+                pool = pool->next;
+        }
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS */
+
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+
+ProtocolVersion MakeSSLv3(void)
+{
+    ProtocolVersion pv;
+    pv.major = SSLv3_MAJOR;
+    pv.minor = SSLv3_MINOR;
+
+    return pv;
+}
+
+#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
+
+
+#ifdef WOLFSSL_DTLS
+
+ProtocolVersion MakeDTLSv1(void)
+{
+    ProtocolVersion pv;
+    pv.major = DTLS_MAJOR;
+    pv.minor = DTLS_MINOR;
+
+    return pv;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+ProtocolVersion MakeDTLSv1_2(void)
+{
+    ProtocolVersion pv;
+    pv.major = DTLS_MAJOR;
+    pv.minor = DTLSv1_2_MINOR;
+
+    return pv;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* WOLFSSL_DTLS */
+
+
+
+
+#if defined(USER_TICKS)
+#if 0
+    word32 LowResTimer(void)
+    {
+        /*
+        write your own clock tick function if don't want time(0)
+        needs second accuracy but doesn't have to correlated to EPOCH
+        */
+    }
+#endif
+
+#elif defined(TIME_OVERRIDES)
+
+    /* use same asn time overrides unless user wants tick override above */
+
+    #ifndef HAVE_TIME_T_TYPE
+        typedef long time_t;
+    #endif
+    extern time_t XTIME(time_t * timer);
+
+    word32 LowResTimer(void)
+    {
+        return (word32) XTIME(0);
+    }
+
+#elif defined(USE_WINDOWS_API)
+
+    word32 LowResTimer(void)
+    {
+        static int           init = 0;
+        static LARGE_INTEGER freq;
+        LARGE_INTEGER        count;
+
+        if (!init) {
+            QueryPerformanceFrequency(&freq);
+            init = 1;
+        }
+
+        QueryPerformanceCounter(&count);
+
+        return (word32)(count.QuadPart / freq.QuadPart);
+    }
+
+#elif defined(HAVE_RTP_SYS)
+
+    #include "rtptime.h"
+
+    word32 LowResTimer(void)
+    {
+        return (word32)rtp_get_system_sec();
+    }
+
+
+#elif defined(MICRIUM)
+
+    word32 LowResTimer(void)
+    {
+        OS_TICK ticks = 0;
+        OS_ERR  err;
+
+        ticks = OSTimeGet(&err);
+
+        return (word32) (ticks / OSCfg_TickRate_Hz);
+    }
+
+
+#elif defined(MICROCHIP_TCPIP_V5)
+
+    word32 LowResTimer(void)
+    {
+        return (word32) (TickGet() / TICKS_PER_SECOND);
+    }
+
+
+#elif defined(MICROCHIP_TCPIP)
+
+    #if defined(MICROCHIP_MPLAB_HARMONY)
+
+        #include <system/tmr/sys_tmr.h>
+
+        word32 LowResTimer(void)
+        {
+            return (word32) (SYS_TMR_TickCountGet() /
+                             SYS_TMR_TickCounterFrequencyGet());
+        }
+
+    #else
+
+        word32 LowResTimer(void)
+        {
+            return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet());
+        }
+
+    #endif
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+
+    word32 LowResTimer(void)
+    {
+        TIME_STRUCT mqxTime;
+
+        _time_get_elapsed(&mqxTime);
+
+        return (word32) mqxTime.SECONDS;
+    }
+#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+
+    #include "include/task.h"
+
+    unsigned int LowResTimer(void)
+    {
+        return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ);
+    }
+
+#elif defined(FREESCALE_KSDK_BM)
+
+    #include "lwip/sys.h" /* lwIP */
+    word32 LowResTimer(void)
+    {
+        return sys_now()/1000;
+    }
+
+#elif defined(WOLFSSL_TIRTOS)
+
+    word32 LowResTimer(void)
+    {
+        return (word32) Seconds_get();
+    }
+#elif defined(WOLFSSL_XILINX)
+    #include "xrtcpsu.h"
+
+    word32 LowResTimer(void)
+    {
+        XRtcPsu_Config* con;
+        XRtcPsu         rtc;
+
+        con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
+        if (con != NULL) {
+            if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr)
+                    == XST_SUCCESS) {
+                return (word32)XRtcPsu_GetCurrentTime(&rtc);
+            }
+            else {
+                WOLFSSL_MSG("Unable to initialize RTC");
+            }
+        }
+
+        return 0;
+    }
+
+#elif defined(WOLFSSL_UTASKER)
+
+    word32 LowResTimer(void)
+    {
+        return (word32)(uTaskerSystemTick / TICK_RESOLUTION);
+    }
+
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+
+    #define NU_TICKS_PER_SECOND 100
+
+    word32 LowResTimer(void)
+    {
+        /* returns number of 10ms ticks, so 100 ticks/sec */
+        return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND;
+    }
+
+#else
+    /* Posix style time */
+    #ifndef USER_TIME
+    #include <time.h>
+    #endif
+
+    word32 LowResTimer(void)
+    {
+        return (word32)XTIME(0);
+    }
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+/* Store the message for use with CertificateVerify using Ed25519.
+ *
+ * ssl   SSL/TLS object.
+ * data  Message to store.
+ * sz    Size of message to store.
+ * returns MEMORY_E if not able to reallocate, otherwise 0.
+ */
+static int Ed25519Update(WOLFSSL* ssl, const byte* data, int sz)
+{
+    int   ret = 0;
+    byte* msgs;
+
+    if (ssl->options.cacheMessages) {
+        msgs = (byte*)XREALLOC(ssl->hsHashes->messages,
+                                                ssl->hsHashes->length + sz,
+                                                ssl->heap, DYNAMIC_TYPE_HASHES);
+        if (msgs == NULL)
+            ret = MEMORY_E;
+        if (ret == 0) {
+            ssl->hsHashes->messages = msgs;
+            XMEMCPY(msgs + ssl->hsHashes->length, data, sz);
+            ssl->hsHashes->prevLen = ssl->hsHashes->length;
+            ssl->hsHashes->length += sz;
+        }
+    }
+
+    return ret;
+}
+#endif /* HAVE_ED25519 && !WOLFSSL_NO_CLIENT_AUTH */
+
+#ifndef NO_CERTS
+int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
+{
+    int ret = 0;
+
+    (void)output;
+    (void)sz;
+
+    if (ssl->hsHashes == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
+#endif
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz);
+    #endif
+#endif /* NO_OLD_TLS */
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, output, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+#endif /* NO_CERTS */
+
+
+/* add output to md5 and sha handshake hashes, exclude record header */
+int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
+{
+    int ret = 0;
+    const byte* adj;
+
+    adj = output + RECORD_HEADER_SZ + ivSz;
+    sz -= RECORD_HEADER_SZ;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
+#endif
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        adj += DTLS_RECORD_EXTRA;
+        sz  -= DTLS_RECORD_EXTRA;
+    }
+#endif
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+    #endif
+#endif
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+
+/* add input to md5 and sha handshake hashes, include handshake header */
+int HashInput(WOLFSSL* ssl, const byte* input, int sz)
+{
+    int ret = 0;
+    const byte* adj;
+
+    adj = input - HANDSHAKE_HEADER_SZ;
+    sz += HANDSHAKE_HEADER_SZ;
+
+    (void)adj;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        adj -= DTLS_HANDSHAKE_EXTRA;
+        sz  += DTLS_HANDSHAKE_EXTRA;
+    }
+#endif
+
+    if (ssl->hsHashes == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifndef NO_OLD_TLS
+    #ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz);
+    #endif
+    #ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz);
+    #endif
+#endif
+
+    if (IsAtLeastTLSv1_2(ssl)) {
+    #ifndef NO_SHA256
+        ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        ret = Ed25519Update(ssl, adj, sz);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+
+/* add record layer header for message */
+static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl)
+{
+    RecordLayerHeader* rl;
+
+    /* record layer header */
+    rl = (RecordLayerHeader*)output;
+    if (rl == NULL) {
+        return;
+    }
+    rl->type    = type;
+    rl->pvMajor = ssl->version.major;       /* type and version same in each */
+#ifdef WOLFSSL_TLS13
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+#ifdef WOLFSSL_TLS13_DRAFT_18
+        rl->pvMinor = TLSv1_MINOR;
+#else
+        rl->pvMinor = TLSv1_2_MINOR;
+#endif
+    }
+    else
+#endif
+        rl->pvMinor = ssl->version.minor;
+
+#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE
+    if (ssl->options.side == WOLFSSL_CLIENT_END
+    &&  ssl->options.connectState == CONNECT_BEGIN
+    && !ssl->options.resuming) {
+        rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade
+                                             : ssl->version.minor;
+    }
+#endif
+
+    if (!ssl->options.dtls) {
+        c16toa((word16)length, rl->length);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+        DtlsRecordLayerHeader* dtls;
+
+        /* dtls record layer header extensions */
+        dtls = (DtlsRecordLayerHeader*)output;
+        WriteSEQ(ssl, 0, dtls->sequence_number);
+        c16toa((word16)length, dtls->length);
+#endif
+    }
+}
+
+
+#if !defined(WOLFSSL_NO_TLS12) || defined(HAVE_SESSION_TICKET)
+/* add handshake header for message */
+static void AddHandShakeHeader(byte* output, word32 length,
+                               word32 fragOffset, word32 fragLength,
+                               byte type, WOLFSSL* ssl)
+{
+    HandShakeHeader* hs;
+    (void)fragOffset;
+    (void)fragLength;
+    (void)ssl;
+
+    /* handshake header */
+    hs = (HandShakeHeader*)output;
+    if (hs == NULL)
+        return;
+
+    hs->type = type;
+    c32to24(length, hs->length);         /* type and length same for each */
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        DtlsHandShakeHeader* dtls;
+
+        /* dtls handshake header extensions */
+        dtls = (DtlsHandShakeHeader*)output;
+        c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
+        c32to24(fragOffset, dtls->fragment_offset);
+        c32to24(fragLength, dtls->fragment_length);
+    }
+#endif
+}
+
+/* add both headers for handshake message */
+static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        lengthAdj += DTLS_HANDSHAKE_EXTRA;
+        outputAdj += DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    AddRecordHeader(output, length + lengthAdj, handshake, ssl);
+    AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
+}
+#endif /* !WOLFSSL_NO_TLS12 || HAVE_SESSION_TICKET */
+
+
+#ifndef WOLFSSL_NO_TLS12
+#ifndef NO_CERTS
+static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
+                           word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+    (void)fragSz;
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        lengthAdj += DTLS_HANDSHAKE_EXTRA;
+        outputAdj += DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl);
+    AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
+}
+#endif /* NO_CERTS */
+#endif /* !WOLFSSL_NO_TLS12 */
+
+
+/* return bytes received, -1 on error */
+static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
+{
+    int recvd;
+
+    if (ssl->CBIORecv == NULL) {
+        WOLFSSL_MSG("Your IO Recv callback is null, please set");
+        return -1;
+    }
+
+retry:
+    recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+    if (recvd < 0)
+        switch (recvd) {
+            case WOLFSSL_CBIO_ERR_GENERAL:        /* general/unknown error */
+                return -1;
+
+            case WOLFSSL_CBIO_ERR_WANT_READ:      /* want read, would block */
+                return WANT_READ;
+
+            case WOLFSSL_CBIO_ERR_CONN_RST:       /* connection reset */
+                #ifdef USE_WINDOWS_API
+                if (ssl->options.dtls) {
+                    goto retry;
+                }
+                #endif
+                ssl->options.connReset = 1;
+                return -1;
+
+            case WOLFSSL_CBIO_ERR_ISR:            /* interrupt */
+                /* see if we got our timeout */
+                #ifdef WOLFSSL_CALLBACKS
+                    if (ssl->toInfoOn) {
+                        struct itimerval timeout;
+                        getitimer(ITIMER_REAL, &timeout);
+                        if (timeout.it_value.tv_sec == 0 &&
+                                                timeout.it_value.tv_usec == 0) {
+                            XSTRNCPY(ssl->timeoutInfo.timeoutName,
+                                    "recv() timeout", MAX_TIMEOUT_NAME_SZ);
+                            ssl->timeoutInfo.timeoutName[
+                                MAX_TIMEOUT_NAME_SZ] = '\0';
+
+                            WOLFSSL_MSG("Got our timeout");
+                            return WANT_READ;
+                        }
+                    }
+                #endif
+                goto retry;
+
+            case WOLFSSL_CBIO_ERR_CONN_CLOSE:     /* peer closed connection */
+                ssl->options.isClosed = 1;
+                return -1;
+
+            #ifdef WOLFSSL_DTLS
+            case WOLFSSL_CBIO_ERR_TIMEOUT:
+                if (IsDtlsNotSctpMode(ssl) &&
+                    !ssl->options.handShakeDone &&
+                    DtlsMsgPoolTimeout(ssl) == 0 &&
+                    DtlsMsgPoolSend(ssl, 0) == 0) {
+
+                    goto retry;
+                }
+                return -1;
+            #endif
+
+            default:
+                return recvd;
+        }
+
+    return recvd;
+}
+
+
+/* Switch dynamic output buffer back to static, buffer is assumed clear */
+void ShrinkOutputBuffer(WOLFSSL* ssl)
+{
+    WOLFSSL_MSG("Shrinking output buffer\n");
+    XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset,
+          ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+    ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+    ssl->buffers.outputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+    ssl->buffers.outputBuffer.dynamicFlag = 0;
+    ssl->buffers.outputBuffer.offset      = 0;
+}
+
+
+/* Switch dynamic input buffer back to static, keep any remaining input */
+/* forced free means cleaning up */
+void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
+{
+    int usedLength = ssl->buffers.inputBuffer.length -
+                     ssl->buffers.inputBuffer.idx;
+    if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
+        return;
+
+    WOLFSSL_MSG("Shrinking input buffer\n");
+
+    if (!forcedFree && usedLength > 0)
+        XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
+               ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+               usedLength);
+
+    XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
+          ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+    ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+    ssl->buffers.inputBuffer.bufferSize  = STATIC_BUFFER_LEN;
+    ssl->buffers.inputBuffer.dynamicFlag = 0;
+    ssl->buffers.inputBuffer.offset      = 0;
+    ssl->buffers.inputBuffer.idx = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+}
+
+int SendBuffered(WOLFSSL* ssl)
+{
+    if (ssl->CBIOSend == NULL) {
+        WOLFSSL_MSG("Your IO Send callback is null, please set");
+        return SOCKET_ERROR_E;
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    if (ssl->buffers.outputBuffer.idx == 0) {
+        WOLFSSL_MSG("Data to send");
+        WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer,
+                       ssl->buffers.outputBuffer.length);
+    }
+#endif
+
+    while (ssl->buffers.outputBuffer.length > 0) {
+        int sent = ssl->CBIOSend(ssl,
+                                      (char*)ssl->buffers.outputBuffer.buffer +
+                                      ssl->buffers.outputBuffer.idx,
+                                      (int)ssl->buffers.outputBuffer.length,
+                                      ssl->IOCB_WriteCtx);
+        if (sent < 0) {
+            switch (sent) {
+
+                case WOLFSSL_CBIO_ERR_WANT_WRITE:        /* would block */
+                    return WANT_WRITE;
+
+                case WOLFSSL_CBIO_ERR_CONN_RST:          /* connection reset */
+                    ssl->options.connReset = 1;
+                    break;
+
+                case WOLFSSL_CBIO_ERR_ISR:               /* interrupt */
+                    /* see if we got our timeout */
+                    #ifdef WOLFSSL_CALLBACKS
+                        if (ssl->toInfoOn) {
+                            struct itimerval timeout;
+                            getitimer(ITIMER_REAL, &timeout);
+                            if (timeout.it_value.tv_sec == 0 &&
+                                                timeout.it_value.tv_usec == 0) {
+                                XSTRNCPY(ssl->timeoutInfo.timeoutName,
+                                        "send() timeout", MAX_TIMEOUT_NAME_SZ);
+                                ssl->timeoutInfo.timeoutName[
+                                    MAX_TIMEOUT_NAME_SZ] = '\0';
+
+                                WOLFSSL_MSG("Got our timeout");
+                                return WANT_WRITE;
+                            }
+                        }
+                    #endif
+                    continue;
+
+                case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
+                    ssl->options.connReset = 1;  /* treat same as reset */
+                    break;
+
+                default:
+                    return SOCKET_ERROR_E;
+            }
+
+            return SOCKET_ERROR_E;
+        }
+
+        if (sent > (int)ssl->buffers.outputBuffer.length) {
+            WOLFSSL_MSG("SendBuffered() out of bounds read");
+            return SEND_OOB_READ_E;
+        }
+
+        ssl->buffers.outputBuffer.idx += sent;
+        ssl->buffers.outputBuffer.length -= sent;
+    }
+
+    ssl->buffers.outputBuffer.idx = 0;
+
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        ShrinkOutputBuffer(ssl);
+
+    return 0;
+}
+
+
+/* Grow the output buffer */
+static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
+{
+    byte* tmp;
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    byte  hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
+                                      RECORD_HEADER_SZ;
+    byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#else
+    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    /* the encrypted data will be offset from the front of the buffer by
+       the header, if the user wants encrypted alignment they need
+       to define their alignment requirement */
+
+    if (align) {
+       while (align < hdrSz)
+           align *= 2;
+    }
+#endif
+
+    tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align,
+                             ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+    WOLFSSL_MSG("growing output buffer\n");
+
+    if (tmp == NULL)
+        return MEMORY_E;
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        tmp += align - hdrSz;
+#endif
+
+    if (ssl->buffers.outputBuffer.length)
+        XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
+               ssl->buffers.outputBuffer.length);
+
+    if (ssl->buffers.outputBuffer.dynamicFlag)
+        XFREE(ssl->buffers.outputBuffer.buffer -
+              ssl->buffers.outputBuffer.offset, ssl->heap,
+              DYNAMIC_TYPE_OUT_BUFFER);
+    ssl->buffers.outputBuffer.dynamicFlag = 1;
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        ssl->buffers.outputBuffer.offset = align - hdrSz;
+    else
+#endif
+        ssl->buffers.outputBuffer.offset = 0;
+
+    ssl->buffers.outputBuffer.buffer = tmp;
+    ssl->buffers.outputBuffer.bufferSize = size +
+                                           ssl->buffers.outputBuffer.length;
+    return 0;
+}
+
+
+/* Grow the input buffer, should only be to read cert or big app data */
+int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
+{
+    byte* tmp;
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    byte  align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0;
+    byte  hdrSz = DTLS_RECORD_HEADER_SZ;
+#else
+    const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    /* the encrypted data will be offset from the front of the buffer by
+       the dtls record header, if the user wants encrypted alignment they need
+       to define their alignment requirement. in tls we read record header
+       to get size of record and put actual data back at front, so don't need */
+
+    if (align) {
+       while (align < hdrSz)
+           align *= 2;
+    }
+#endif
+
+    if (usedLength < 0 || size < 0) {
+        WOLFSSL_MSG("GrowInputBuffer() called with negative number");
+        return BAD_FUNC_ARG;
+    }
+
+    tmp = (byte*)XMALLOC(size + usedLength + align,
+                             ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+    WOLFSSL_MSG("growing input buffer\n");
+
+    if (tmp == NULL)
+        return MEMORY_E;
+
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        tmp += align - hdrSz;
+#endif
+
+    if (usedLength)
+        XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
+                    ssl->buffers.inputBuffer.idx, usedLength);
+
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
+              ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
+
+    ssl->buffers.inputBuffer.dynamicFlag = 1;
+#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0
+    if (align)
+        ssl->buffers.inputBuffer.offset = align - hdrSz;
+    else
+#endif
+        ssl->buffers.inputBuffer.offset = 0;
+
+    ssl->buffers.inputBuffer.buffer = tmp;
+    ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+    ssl->buffers.inputBuffer.idx    = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+
+    return 0;
+}
+
+
+/* check available size into output buffer, make room if needed */
+int CheckAvailableSize(WOLFSSL *ssl, int size)
+{
+    if (size < 0) {
+        WOLFSSL_MSG("CheckAvailableSize() called with negative number");
+        return BAD_FUNC_ARG;
+    }
+
+    if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
+                                             < (word32)size) {
+        if (GrowOutputBuffer(ssl, size) < 0)
+            return MEMORY_E;
+    }
+
+    return 0;
+}
+
+
+/* do all verify and sanity checks on record header */
+static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                           RecordLayerHeader* rh, word16 *size)
+{
+    if (!ssl->options.dtls) {
+#ifdef HAVE_FUZZER
+        if (ssl->fuzzerCb)
+            ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD,
+                    ssl->fuzzerCtx);
+#endif
+        XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
+        *inOutIdx += RECORD_HEADER_SZ;
+        ato16(rh->length, size);
+    }
+    else {
+#ifdef WOLFSSL_DTLS
+#ifdef HAVE_FUZZER
+        if (ssl->fuzzerCb)
+            ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ,
+                           FUZZ_HEAD, ssl->fuzzerCtx);
+#endif
+        /* type and version in same sport */
+        XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
+        *inOutIdx += ENUM_LEN + VERSION_SZ;
+        ato16(input + *inOutIdx, &ssl->keys.curEpoch);
+        *inOutIdx += OPAQUE16_LEN;
+        if (ssl->options.haveMcast) {
+        #ifdef WOLFSSL_MULTICAST
+            ssl->keys.curPeerId = input[*inOutIdx];
+            ssl->keys.curSeq_hi = input[*inOutIdx+1];
+        #endif
+        }
+        else
+            ato16(input + *inOutIdx, &ssl->keys.curSeq_hi);
+        *inOutIdx += OPAQUE16_LEN;
+        ato32(input + *inOutIdx, &ssl->keys.curSeq_lo);
+        *inOutIdx += OPAQUE32_LEN;  /* advance past rest of seq */
+        ato16(input + *inOutIdx, size);
+        *inOutIdx += LENGTH_SZ;
+#endif
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (IsDtlsNotSctpMode(ssl) &&
+        (!DtlsCheckWindow(ssl) ||
+         (ssl->options.handShakeDone && ssl->keys.curEpoch == 0))) {
+            return SEQUENCE_ERROR;
+    }
+#endif
+
+    /* catch version mismatch */
+#ifndef WOLFSSL_TLS13
+    if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor)
+#else
+    if (rh->pvMajor != ssl->version.major ||
+        (rh->pvMinor != ssl->version.minor &&
+#ifdef WOLFSSL_TLS13_DRAFT_18
+         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR)
+#else
+         (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR)
+#endif
+        ))
+#endif
+    {
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+            ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE)
+
+            WOLFSSL_MSG("Client attempting to connect with different version");
+        else if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                                 ssl->options.downgrade &&
+                                 ssl->options.connectState < FIRST_REPLY_DONE)
+            WOLFSSL_MSG("Server attempting to accept with different version");
+        else if (ssl->options.dtls && rh->type == handshake)
+            /* Check the DTLS handshake message RH version later. */
+            WOLFSSL_MSG("DTLS handshake, skip RH version number check");
+        else {
+            WOLFSSL_MSG("SSL version error");
+            return VERSION_ERROR;              /* only use requested version */
+        }
+    }
+
+    /* record layer length check */
+#ifdef HAVE_MAX_FRAGMENT
+    if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
+        SendAlert(ssl, alert_fatal, record_overflow);
+        return LENGTH_ERROR;
+    }
+#else
+    if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
+        return LENGTH_ERROR;
+#endif
+
+    /* verify record type here as well */
+    switch (rh->type) {
+        case handshake:
+        case change_cipher_spec:
+        case application_data:
+        case alert:
+            break;
+        case no_type:
+        default:
+            WOLFSSL_MSG("Unknown Record Type");
+            return UNKNOWN_RECORD_TYPE;
+    }
+
+    /* haven't decrypted this record yet */
+    ssl->keys.decryptedCur = 0;
+
+    return 0;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              byte *type, word32 *size, word32 totalSz)
+{
+    const byte *ptr = input + *inOutIdx;
+    (void)ssl;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ;
+    if (*inOutIdx > totalSz)
+        return BUFFER_E;
+
+    *type = ptr[0];
+    c24to32(&ptr[1], size);
+
+    return 0;
+}
+#endif
+
+#ifdef WOLFSSL_DTLS
+static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
+                                  word32* inOutIdx, byte *type, word32 *size,
+                                  word32 *fragOffset, word32 *fragSz,
+                                  word32 totalSz)
+{
+    word32 idx = *inOutIdx;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
+    if (*inOutIdx > totalSz)
+        return BUFFER_E;
+
+    *type = input[idx++];
+    c24to32(input + idx, size);
+    idx += OPAQUE24_LEN;
+
+    ato16(input + idx, &ssl->keys.dtls_peer_handshake_number);
+    idx += DTLS_HANDSHAKE_SEQ_SZ;
+
+    c24to32(input + idx, fragOffset);
+    idx += DTLS_HANDSHAKE_FRAG_SZ;
+    c24to32(input + idx, fragSz);
+
+    if (ssl->curRL.pvMajor != ssl->version.major ||
+        ssl->curRL.pvMinor != ssl->version.minor) {
+
+        if (*type != client_hello && *type != hello_verify_request)
+            return VERSION_ERROR;
+        else {
+            WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version");
+        }
+    }
+    return 0;
+}
+#endif
+
+
+#if !defined(NO_OLD_TLS) || \
+    (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1))
+/* fill with MD5 pad size since biggest required */
+static const byte PAD1[PAD_MD5] =
+                              { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+                                0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+                              };
+static const byte PAD2[PAD_MD5] =
+                              { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+                                0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+                              };
+#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */
+
+#ifndef NO_OLD_TLS
+
+/* calculate MD5 hash for finished */
+#ifdef WOLFSSL_TI_HASH
+#include <wolfssl/wolfcrypt/hash.h>
+#endif
+
+static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret;
+    byte md5_result[WC_MD5_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+    if (md5 == NULL)
+        return MEMORY_E;
+#else
+    wc_Md5  md5[1];
+#endif
+
+    /* make md5 inner */
+    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, sender, SIZEOF_SENDER);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+    if (ret == 0)
+        ret = wc_Md5Final(md5, md5_result);
+
+    /* make md5 outer */
+    if (ret == 0) {
+        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_Md5Final(md5, hashes->md5);
+            wc_Md5Free(md5);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+
+
+/* calculate SHA hash for finished */
+static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret;
+    byte sha_result[WC_SHA_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+    if (sha == NULL)
+        return MEMORY_E;
+#else
+    wc_Sha  sha[1];
+#endif
+    /* make sha inner */
+    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+    if (ret == 0)
+        ret = wc_ShaFinal(sha, sha_result);
+
+    /* make sha outer */
+    if (ret == 0) {
+        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_ShaFinal(sha, hashes->sha);
+            wc_ShaFree(sha);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* Finished doesn't support SHA512, not SHA512 cipher suites yet */
+static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
+{
+    int ret = 0;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifndef NO_TLS
+    if (ssl->options.tls) {
+        ret = BuildTlsFinished(ssl, hashes, sender);
+    }
+#endif
+#ifndef NO_OLD_TLS
+    if (!ssl->options.tls) {
+        ret = BuildMD5(ssl, hashes, sender);
+        if (ret == 0) {
+            ret = BuildSHA(ssl, hashes, sender);
+        }
+    }
+#endif
+
+    return ret;
+}
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
+    /* cipher requirements */
+    enum {
+        REQUIRES_RSA,
+        REQUIRES_DHE,
+        REQUIRES_ECC,
+        REQUIRES_ECC_STATIC,
+        REQUIRES_PSK,
+        REQUIRES_NTRU,
+        REQUIRES_RSA_SIG
+    };
+
+
+
+    /* Does this cipher suite (first, second) have the requirement
+       an ephemeral key exchange will still require the key for signing
+       the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */
+    static int CipherRequires(byte first, byte second, int requirement)
+    {
+
+        (void)requirement;
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_CHACHA
+        if (first == CHACHA_BYTE) {
+
+        switch (second) {
+        case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+
+        case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+            }
+        }
+#endif /* HAVE_CHACHA */
+
+        /* ECC extensions */
+        if (first == ECC_BYTE) {
+
+        switch (second) {
+#ifdef HAVE_ECC
+    #ifndef NO_RSA
+        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+
+    #ifndef NO_DES3
+        case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_DES3 */
+
+    #ifndef NO_RC4
+        case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_RC4 */
+    #endif /* NO_RSA */
+
+    #ifndef NO_DES3
+        case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* !NO_DES3  */
+    #ifndef NO_RC4
+        case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* !NO_RC4 */
+    #ifndef NO_RSA
+        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* !NO_RSA */
+
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+#endif /* HAVE_ECC */
+
+#ifndef NO_RSA
+    #ifdef HAVE_ECC
+        case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_AESCCM
+        case TLS_RSA_WITH_AES_128_CCM_8 :
+        case TLS_RSA_WITH_AES_256_CCM_8 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            break;
+    #endif /* HAVE_AESCCM */
+    #ifdef HAVE_ECC
+
+        case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+    #endif /* HAVE_ECC */
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
+        case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
+        case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            if (requirement == REQUIRES_ECC_STATIC)
+                return 1;
+            break;
+#endif /* HAVE_ECC */
+
+#ifndef NO_PSK
+        case TLS_PSK_WITH_AES_128_CCM:
+        case TLS_PSK_WITH_AES_256_CCM:
+        case TLS_PSK_WITH_AES_128_CCM_8:
+        case TLS_PSK_WITH_AES_256_CCM_8:
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_AES_128_CCM:
+        case TLS_DHE_PSK_WITH_AES_256_CCM:
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif /* !NO_PSK */
+#ifdef HAVE_ECC
+        case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
+            if (requirement == REQUIRES_ECC)
+                return 1;
+            break;
+
+        case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+#endif /* HAVE_ECC */
+        default:
+            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC");
+            return 0;
+        }   /* switch */
+        }   /* if     */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+        /* Distinct TLS v1.3 cipher suites with cipher and digest only. */
+        if (first == TLS13_BYTE) {
+
+            switch (second) {
+#ifdef WOLFSSL_TLS13
+            case TLS_AES_128_GCM_SHA256:
+            case TLS_AES_256_GCM_SHA384:
+            case TLS_CHACHA20_POLY1305_SHA256:
+            case TLS_AES_128_CCM_SHA256:
+            case TLS_AES_128_CCM_8_SHA256:
+                break;
+#endif
+
+            default:
+                WOLFSSL_MSG("Unsupported cipher suite, CipherRequires "
+                            "TLS v1.3");
+                return 0;
+            }
+        }
+
+#ifndef WOLFSSL_NO_TLS12
+
+        if (first != ECC_BYTE && first != CHACHA_BYTE &&
+            first != TLS13_BYTE) {   /* normal suites */
+        switch (second) {
+
+#ifndef NO_RSA
+    #ifndef NO_RC4
+        case SSL_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case SSL_RSA_WITH_RC4_128_MD5 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+    #endif /* NO_RC4 */
+
+        case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+        case TLS_RSA_WITH_AES_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_NULL_SHA :
+        case TLS_RSA_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+    #ifdef HAVE_NTRU
+        case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_NTRU)
+                return 1;
+            break;
+    #endif /* HAVE_NTRU */
+
+    #ifdef HAVE_IDEA
+        case SSL_RSA_WITH_IDEA_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+    #endif /* HAVE_IDEA */
+#endif /* !NO_RSA */
+
+#ifndef NO_PSK
+        case TLS_PSK_WITH_AES_128_GCM_SHA256 :
+        case TLS_PSK_WITH_AES_256_GCM_SHA384 :
+        case TLS_PSK_WITH_AES_128_CBC_SHA256 :
+        case TLS_PSK_WITH_AES_256_CBC_SHA384 :
+        case TLS_PSK_WITH_AES_128_CBC_SHA :
+        case TLS_PSK_WITH_AES_256_CBC_SHA :
+        case TLS_PSK_WITH_NULL_SHA384 :
+        case TLS_PSK_WITH_NULL_SHA256 :
+        case TLS_PSK_WITH_NULL_SHA :
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+
+        case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
+        case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
+        case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
+        case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
+        case TLS_DHE_PSK_WITH_NULL_SHA384 :
+        case TLS_DHE_PSK_WITH_NULL_SHA256 :
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            if (requirement == REQUIRES_PSK)
+                return 1;
+            break;
+#endif /* NO_PSK */
+
+#ifndef NO_RSA
+        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+#ifndef NO_HC128
+        case TLS_RSA_WITH_HC_128_MD5 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_HC_128_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_RSA_WITH_HC_128_B2B256:
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+#endif /* NO_HC128 */
+
+#ifdef HAVE_BLAKE2
+        case TLS_RSA_WITH_AES_128_CBC_B2B256:
+        case TLS_RSA_WITH_AES_256_CBC_B2B256:
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+#endif /* HAVE_BLAKE2 */
+
+#ifndef NO_RABBIT
+        case TLS_RSA_WITH_RABBIT_SHA :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+#endif /* !NO_RABBIT */
+
+        case TLS_RSA_WITH_AES_128_GCM_SHA256 :
+        case TLS_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
+        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+
+#ifdef HAVE_CAMELLIA
+        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            break;
+
+        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif /* HAVE_CAMELLIA */
+
+        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            if (requirement == REQUIRES_RSA)
+                return 1;
+            if (requirement == REQUIRES_RSA_SIG)
+                return 1;
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif
+#ifdef HAVE_ANON
+        case TLS_DH_anon_WITH_AES_128_CBC_SHA :
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+        case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+            if (requirement == REQUIRES_DHE)
+                return 1;
+            break;
+#endif
+#ifdef WOLFSSL_MULTICAST
+        case WDM_WITH_NULL_SHA256 :
+            break;
+#endif
+
+        default:
+            WOLFSSL_MSG("Unsupported cipher suite, CipherRequires");
+            return 0;
+        }  /* switch */
+        }  /* if ECC / Normal suites else */
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+        return 0;
+    }
+
+#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
+
+
+#ifndef NO_CERTS
+
+
+/* Match names with wildcards, each wildcard can represent a single name
+   component or fragment but not mulitple names, i.e.,
+   *.z.com matches y.z.com but not x.y.z.com
+
+   return 1 on success */
+int MatchDomainName(const char* pattern, int len, const char* str)
+{
+    int ret = 0;
+    char p, s;
+
+    if (pattern == NULL || str == NULL || len <= 0)
+        return 0;
+
+    while (len > 0) {
+
+        p = (char)XTOLOWER((unsigned char)*pattern++);
+        if (p == '\0')
+            break;
+
+        if (p == '*') {
+            while (--len > 0 &&
+                (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') {
+            }
+
+            if (len == 0)
+                p = '\0';
+
+            while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') {
+                if (s == p)
+                    break;
+                if (s == '.')
+                    return 0;
+                str++;
+            }
+        }
+        else {
+            if (p != (char)XTOLOWER((unsigned char) *str))
+                return 0;
+        }
+
+
+        if (len > 0) {
+            str++;
+            len--;
+        }
+    }
+
+    if (*str == '\0' && len == 0) {
+        ret = 1; /* success */
+    }
+
+    return ret;
+}
+
+
+/* try to find an altName match to domain, return 1 on success */
+int CheckAltNames(DecodedCert* dCert, char* domain)
+{
+    int        match = 0;
+    DNS_entry* altName = NULL;
+
+    WOLFSSL_MSG("Checking AltNames");
+
+    if (dCert)
+        altName = dCert->altNames;
+
+    while (altName) {
+        WOLFSSL_MSG("\tindividual AltName check");
+
+        if (MatchDomainName(altName->name, altName->len, domain)){
+            match = 1;
+            break;
+        }
+
+        altName = altName->next;
+    }
+
+    return match;
+}
+
+
+#ifdef OPENSSL_EXTRA
+/* Check that alternative names, if they exists, match the domain.
+ * Fail if there are wild patterns and they didn't match.
+ * Check the common name if no alternative names matched.
+ *
+ * dCert    Decoded cert to get the alternative names from.
+ * domain   Domain name to compare against.
+ * checkCN  Whether to check the common name.
+ * returns whether there was a problem in matching.
+ */
+static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN)
+{
+    int        match;
+    DNS_entry* altName = NULL;
+
+    WOLFSSL_MSG("Checking AltNames");
+
+    if (dCert)
+        altName = dCert->altNames;
+
+    *checkCN = altName == NULL;
+    match = 0;
+    while (altName) {
+        WOLFSSL_MSG("\tindividual AltName check");
+
+        if (MatchDomainName(altName->name, altName->len, domain)) {
+            match = 1;
+            *checkCN = 0;
+            break;
+        }
+        /* No matches and wild pattern match failed. */
+        else if (altName->name[0] == '*' && match == 0)
+            match = -1;
+
+        altName = altName->next;
+    }
+
+    return match != -1;
+}
+
+/* Check the domain name matches the subject alternative name or the subject
+ * name.
+ *
+ * dcert          Decoded certificate.
+ * domainName     The domain name.
+ * domainNameLen  The length of the domain name.
+ * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success.
+ */
+int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen)
+{
+    int checkCN;
+
+    /* Assume name is NUL terminated. */
+    (void)domainNameLen;
+
+    if (CheckForAltNames(dCert, domainName, &checkCN) == 0) {
+        WOLFSSL_MSG("DomainName match on alt names failed too");
+        return DOMAIN_NAME_MISMATCH;
+    }
+    if (checkCN == 1) {
+        if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
+                            domainName) == 0) {
+            WOLFSSL_MSG("DomainName match on common name failed");
+            return DOMAIN_NAME_MISMATCH;
+        }
+    }
+
+    return 0;
+}
+#endif
+
+#ifdef SESSION_CERTS
+static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
+    byte* certBuf, word32 certSz)
+{
+   if (chain->count < MAX_CHAIN_DEPTH &&
+                               certSz < MAX_X509_SIZE) {
+        chain->certs[chain->count].length = certSz;
+        XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz);
+        chain->count++;
+    }
+    else {
+        WOLFSSL_MSG("Couldn't store chain cert for session");
+    }
+}
+#endif
+
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+    defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Copy parts X509 needs from Decoded cert, 0 on success */
+int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
+{
+    int ret = 0;
+
+    if (x509 == NULL || dCert == NULL ||
+        dCert->subjectCNLen < 0)
+        return BAD_FUNC_ARG;
+
+    x509->version = dCert->version + 1;
+
+    XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX);
+    x509->issuer.name[ASN_NAME_MAX - 1] = '\0';
+    x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    if (dCert->issuerName.fullName != NULL) {
+        XMEMCPY(&x509->issuer.fullName,
+                                       &dCert->issuerName, sizeof(DecodedName));
+        x509->issuer.fullName.fullName = (char*)XMALLOC(
+                        dCert->issuerName.fullNameLen, x509->heap,
+                        DYNAMIC_TYPE_X509);
+        if (x509->issuer.fullName.fullName != NULL)
+            XMEMCPY(x509->issuer.fullName.fullName,
+                     dCert->issuerName.fullName, dCert->issuerName.fullNameLen);
+    }
+    x509->issuer.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+    XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX);
+    x509->subject.name[ASN_NAME_MAX - 1] = '\0';
+    x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    if (dCert->subjectName.fullName != NULL) {
+        XMEMCPY(&x509->subject.fullName,
+                                      &dCert->subjectName, sizeof(DecodedName));
+        x509->subject.fullName.fullName = (char*)XMALLOC(
+                 dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509);
+        if (x509->subject.fullName.fullName != NULL)
+            XMEMCPY(x509->subject.fullName.fullName,
+                   dCert->subjectName.fullName, dCert->subjectName.fullNameLen);
+    }
+    x509->subject.x509 = x509;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    XMEMCPY(x509->subject.raw, dCert->subjectRaw, dCert->subjectRawLen);
+    x509->subject.rawLen = dCert->subjectRawLen;
+#endif
+
+    XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE);
+    x509->serialSz = dCert->serialSz;
+    if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) {
+        XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen);
+        x509->subjectCN[dCert->subjectCNLen] = '\0';
+    }
+    else
+        x509->subjectCN[0] = '\0';
+
+#ifdef WOLFSSL_SEP
+    {
+        int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->deviceTypeSz = minSz;
+            XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
+        }
+        else
+            x509->deviceTypeSz = 0;
+        minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->hwTypeSz = minSz;
+            XMEMCPY(x509->hwType, dCert->hwType, minSz);
+        }
+        else
+            x509->hwTypeSz = 0;
+        minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
+        if (minSz > 0) {
+            x509->hwSerialNumSz = minSz;
+            XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
+        }
+        else
+            x509->hwSerialNumSz = 0;
+    }
+#endif /* WOLFSSL_SEP */
+    {
+        int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ);
+        if (minSz > 0) {
+            x509->notBeforeSz = minSz;
+            XMEMCPY(x509->notBefore, dCert->beforeDate, minSz);
+        }
+        else
+            x509->notBeforeSz = 0;
+        minSz = min(dCert->afterDateLen, MAX_DATE_SZ);
+        if (minSz > 0) {
+            x509->notAfterSz = minSz;
+            XMEMCPY(x509->notAfter, dCert->afterDate, minSz);
+        }
+        else
+            x509->notAfterSz = 0;
+    }
+
+    if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
+        x509->pubKey.buffer = (byte*)XMALLOC(
+                        dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        if (x509->pubKey.buffer != NULL) {
+            x509->pubKeyOID = dCert->keyOID;
+            x509->pubKey.length = dCert->pubKeySize;
+            XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize);
+        }
+        else
+            ret = MEMORY_E;
+    }
+
+    if (dCert->signature != NULL && dCert->sigLength != 0 &&
+            dCert->sigLength <= MAX_ENCODED_SIG_SZ) {
+        x509->sig.buffer = (byte*)XMALLOC(
+                          dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+        if (x509->sig.buffer == NULL) {
+            ret = MEMORY_E;
+        }
+        else {
+            XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength);
+            x509->sig.length = dCert->sigLength;
+            x509->sigOID = dCert->signatureOID;
+        }
+    }
+
+    /* store cert for potential retrieval */
+    if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) {
+        XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx);
+    }
+    else {
+        ret = MEMORY_E;
+    }
+
+    x509->altNames       = dCert->altNames;
+    dCert->weOwnAltNames = 0;
+    x509->altNamesNext   = x509->altNames;  /* index hint */
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(IGNORE_NAME_CONSTRAINTS)
+    /* add copies of alternate emails from dCert to X509 */
+    if (dCert->altEmailNames != NULL) {
+        DNS_entry* cur = dCert->altEmailNames;
+
+        while (cur != NULL) {
+            if (cur->type == ASN_RFC822_TYPE) {
+                DNS_entry* dnsEntry;
+                int strLen = cur->len;
+
+                dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+                if (dnsEntry == NULL) {
+                    WOLFSSL_MSG("\tOut of Memory");
+                    return MEMORY_E;
+                }
+
+                dnsEntry->type = ASN_RFC822_TYPE;
+                dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+                if (dnsEntry->name == NULL) {
+                    WOLFSSL_MSG("\tOut of Memory");
+                    XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME);
+                    return MEMORY_E;
+                }
+                dnsEntry->len = strLen;
+                XMEMCPY(dnsEntry->name, cur->name, strLen);
+                dnsEntry->name[strLen] = '\0';
+
+                dnsEntry->next = x509->altNames;
+                x509->altNames = dnsEntry;
+            }
+            cur = cur->next;
+        }
+    }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+    x509->isCa = dCert->isCA;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    x509->pathLength = dCert->pathLength;
+    x509->keyUsage = dCert->extKeyUsage;
+
+    x509->CRLdistSet = dCert->extCRLdistSet;
+    x509->CRLdistCrit = dCert->extCRLdistCrit;
+    x509->CRLInfo = dCert->extCrlInfo;
+    x509->CRLInfoSz = dCert->extCrlInfoSz;
+    x509->authInfoSet = dCert->extAuthInfoSet;
+    x509->authInfoCrit = dCert->extAuthInfoCrit;
+    if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) {
+        x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap,
+                DYNAMIC_TYPE_X509_EXT);
+        if (x509->authInfo != NULL) {
+            XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz);
+            x509->authInfoSz = dCert->extAuthInfoSz;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    x509->basicConstSet = dCert->extBasicConstSet;
+    x509->basicConstCrit = dCert->extBasicConstCrit;
+    x509->basicConstPlSet = dCert->pathLengthSet;
+    x509->subjAltNameSet = dCert->extSubjAltNameSet;
+    x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
+    x509->authKeyIdSet = dCert->extAuthKeyIdSet;
+    x509->authKeyIdCrit = dCert->extAuthKeyIdCrit;
+    if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) {
+        x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap,
+                                         DYNAMIC_TYPE_X509_EXT);
+        if (x509->authKeyId != NULL) {
+            XMEMCPY(x509->authKeyId,
+                                 dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz);
+            x509->authKeyIdSz = dCert->extAuthKeyIdSz;
+        }
+        else
+            ret = MEMORY_E;
+    }
+    x509->subjKeyIdSet = dCert->extSubjKeyIdSet;
+    x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit;
+    if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) {
+        x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap,
+                                         DYNAMIC_TYPE_X509_EXT);
+        if (x509->subjKeyId != NULL) {
+            XMEMCPY(x509->subjKeyId,
+                                 dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz);
+            x509->subjKeyIdSz = dCert->extSubjKeyIdSz;
+        }
+        else
+            ret = MEMORY_E;
+    }
+    x509->keyUsageSet = dCert->extKeyUsageSet;
+    x509->keyUsageCrit = dCert->extKeyUsageCrit;
+    if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) {
+        x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz,
+                x509->heap, DYNAMIC_TYPE_X509_EXT);
+        if (x509->extKeyUsageSrc != NULL) {
+            XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc,
+                                                       dCert->extExtKeyUsageSz);
+            x509->extKeyUsageSz    = dCert->extExtKeyUsageSz;
+            x509->extKeyUsageCrit  = dCert->extExtKeyUsageCrit;
+            x509->extKeyUsageCount = dCert->extExtKeyUsageCount;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    #ifdef WOLFSSL_SEP
+        x509->certPolicySet = dCert->extCertPolicySet;
+        x509->certPolicyCrit = dCert->extCertPolicyCrit;
+    #endif /* WOLFSSL_SEP */
+    #ifdef WOLFSSL_CERT_EXT
+        {
+            int i;
+            for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++)
+                XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i],
+                                                                MAX_CERTPOL_SZ);
+            x509->certPoliciesNb = dCert->extCertPoliciesNb;
+        }
+    #endif /* WOLFSSL_CERT_EXT */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    x509->pkCurveOID = dCert->pkCurveOID;
+#endif /* HAVE_ECC */
+
+    return ret;
+}
+
+#endif /* KEEP_PEER_CERT || SESSION_CERTS */
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+     (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
+static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                      word32 status_length)
+{
+    int ret = 0;
+    OcspRequest* request;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        CertStatus* status;
+        OcspResponse* response;
+    #else
+        CertStatus status[1];
+        OcspResponse response[1];
+    #endif
+
+    do {
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+            if (ssl->status_request) {
+                request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
+                ssl->status_request = 0;
+                break;
+            }
+        #endif
+
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+            if (ssl->status_request_v2) {
+                request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
+                                                          WOLFSSL_CSR2_OCSP, 0);
+                ssl->status_request_v2 = 0;
+                break;
+            }
+        #endif
+
+        return BUFFER_ERROR;
+    } while(0);
+
+    if (request == NULL)
+        return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
+
+    #ifdef WOLFSSL_SMALL_STACK
+        status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+                                                      DYNAMIC_TYPE_OCSP_STATUS);
+        response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+
+        if (status == NULL || response == NULL) {
+            if (status)
+                XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+            if (response)
+                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+
+            return MEMORY_ERROR;
+        }
+    #endif
+
+    InitOcspResponse(response, status, input +*inOutIdx, status_length);
+
+    if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (CompareOcspReqResp(request, response) != 0)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (response->responseStatus != OCSP_SUCCESSFUL)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+    else if (response->status->status == CERT_REVOKED)
+        ret = OCSP_CERT_REVOKED;
+    else if (response->status->status != CERT_GOOD)
+        ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+    *inOutIdx += status_length;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(status,   ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    #endif
+
+    return ret;
+}
+#endif
+
+
+
+#ifdef HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+    static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* hash, unsigned int hashSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx)
+    {
+        int ret = NOT_COMPILED_IN;
+        WOLFSSL* ssl = (WOLFSSL*)ctx;
+
+        if (ssl && ssl->ctx->EccVerifyCb) {
+            ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz,
+                keyDer, keySz, result, ssl->EccVerifyCtx);
+        }
+        return ret;
+    }
+#endif
+#ifndef NO_RSA
+    static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz,
+       unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
+       void* ctx)
+    {
+        int ret = NOT_COMPILED_IN;
+        WOLFSSL* ssl = (WOLFSSL*)ctx;
+
+        if (ssl && ssl->ctx->RsaVerifyCb) {
+            ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz,
+                ssl->RsaVerifyCtx);
+        }
+        return ret;
+    }
+#endif
+
+int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
+{
+    if (ssl == NULL || sigCtx == NULL)
+        return BAD_FUNC_ARG;
+
+    /* only setup the verify callback if a PK is set */
+#ifdef HAVE_ECC
+    if (ssl->ctx->EccVerifyCb) {
+        sigCtx->pkCbEcc = SigPkCbEccVerify;
+        sigCtx->pkCtxEcc = ssl;
+    }
+#endif
+#ifndef NO_RSA
+    /* only setup the verify callback if a PK is set */
+    if (ssl->ctx->RsaVerifyCb) {
+        sigCtx->pkCbRsa = SigPkCbRsaVerify;
+        sigCtx->pkCtxRsa = ssl;
+    }
+#endif
+
+    return 0;
+}
+
+#endif /* HAVE_PK_CALLBACKS */
+
+
+typedef struct ProcPeerCertArgs {
+    buffer*      certs;
+#ifdef WOLFSSL_TLS13
+    buffer*      exts; /* extentions */
+#endif
+    DecodedCert* dCert;
+    char*  domain;
+    word32 idx;
+    word32 begin;
+    int    totalCerts; /* number of certs in certs buffer */
+    int    count;
+    int    dCertInit;
+    int    certIdx;
+    int    fatal;
+    int    lastErr;
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+    int    lastCaErr;
+#endif
+#ifdef WOLFSSL_TLS13
+    byte   ctxSz;
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+    char   untrustedDepth;
+#endif
+} ProcPeerCertArgs;
+
+static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
+{
+    ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs;
+
+    (void)ssl;
+
+    if (args->domain) {
+        XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_STRING);
+        args->domain = NULL;
+    }
+    if (args->certs) {
+        XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
+        args->certs = NULL;
+    }
+#ifdef WOLFSSL_TLS13
+    if (args->exts) {
+        XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+        args->exts = NULL;
+    }
+#endif
+    if (args->dCert) {
+        if (args->dCertInit) {
+            FreeDecodedCert(args->dCert);
+            args->dCertInit = 0;
+        }
+        XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+        args->dCert = NULL;
+    }
+}
+
+int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                     word32 totalSz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    ProcPeerCertArgs* args = ssl->nonblockarg;
+#else
+    ProcPeerCertArgs  args[1];
+#endif
+
+    buffer* cert;
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */
+#endif
+
+    WOLFSSL_ENTER("ProcessPeerCerts");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_ppc;
+    }
+    else
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    if (args == NULL) {
+        args = (ProcPeerCertArgs*)XMALLOC(
+            sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (args == NULL) {
+            ERROR_OUT(MEMORY_E, exit_ppc);
+        }
+    }
+    if (ssl->nonblockarg == NULL) /* new args */
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeProcPeerCertArgs;
+    #elif defined(WOLFSSL_NONBLOCK_OCSP)
+        ssl->nonblockarg = args;
+    #endif
+    }
+
+    switch (ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            word32 listSz;
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "Certificate");
+            if (ssl->toInfoOn)
+                AddLateName("Certificate", &ssl->timeoutInfo);
+        #endif
+
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                byte ctxSz;
+
+                /* Certificate Request Context */
+                if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz)
+                    return BUFFER_ERROR;
+                ctxSz = *(input + args->idx);
+                args->idx++;
+                if ((args->idx - args->begin) + ctxSz > totalSz)
+                    return BUFFER_ERROR;
+            #ifndef NO_WOLFSSL_CLIENT
+                /* Must be empty when received from server. */
+                if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                    if (ctxSz != 0) {
+                        return INVALID_CERT_CTX_E;
+                    }
+                }
+            #endif
+            #ifndef NO_WOLFSSL_SERVER
+                /* Must contain value sent in request. */
+                if (ssl->options.side == WOLFSSL_SERVER_END) {
+                    if (ssl->options.handShakeState != HANDSHAKE_DONE &&
+                                                                   ctxSz != 0) {
+                        return INVALID_CERT_CTX_E;
+                    }
+                    else if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+                #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+                         CertReqCtx* curr = ssl->certReqCtx;
+                         CertReqCtx* prev = NULL;
+                         while (curr != NULL) {
+                             if ((ctxSz == curr->len) &&
+                                 XMEMCMP(&curr->ctx, input + args->idx, ctxSz)
+                                                                         == 0) {
+                                     if (prev != NULL)
+                                         prev->next = curr->next;
+                                     else
+                                         ssl->certReqCtx = curr->next;
+                                     XFREE(curr, ssl->heap,
+                                           DYNAMIC_TYPE_TMP_BUFFER);
+                                     break;
+                             }
+                             prev = curr;
+                             curr = curr->next;
+                        }
+                        if (curr == NULL)
+                #endif
+                            return INVALID_CERT_CTX_E;
+                    }
+                }
+            #endif
+                args->idx += ctxSz;
+
+                /* allocate buffer for cert extensions */
+                args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+                                            ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+                if (args->exts == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_ppc);
+                }
+            }
+        #endif
+
+            /* allocate buffer for certs */
+        #ifdef OPENSSL_EXTRA
+            args->certs = (buffer*)XMALLOC(sizeof(buffer) *
+                    (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER);
+            if (args->certs == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+            XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1));
+        #else
+            args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+            if (args->certs == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+            XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
+        #endif /* OPENSSL_EXTRA */
+            /* Certificate List */
+            if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+            c24to32(input + args->idx, &listSz);
+            args->idx += OPAQUE24_LEN;
+            if (listSz > MAX_CERTIFICATE_SZ) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+            if ((args->idx - args->begin) + listSz != totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_ppc);
+            }
+
+            WOLFSSL_MSG("Loading peer's cert chain");
+            /* first put cert chain into buffer so can verify top down
+               we're sent bottom up */
+            while (listSz) {
+                word32 certSz;
+
+            #ifdef OPENSSL_EXTRA
+                if (args->totalCerts > ssl->verifyDepth) {
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+                }
+            #else
+                if (args->totalCerts >= ssl->verifyDepth ||
+                        args->totalCerts >= MAX_CHAIN_DEPTH) {
+                    ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc);
+                }
+            #endif
+
+                if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                }
+
+                c24to32(input + args->idx, &certSz);
+                args->idx += OPAQUE24_LEN;
+
+                if ((args->idx - args->begin) + certSz > totalSz) {
+                    ERROR_OUT(BUFFER_ERROR, exit_ppc);
+                }
+
+                args->certs[args->totalCerts].length = certSz;
+                args->certs[args->totalCerts].buffer = input + args->idx;
+
+            #ifdef SESSION_CERTS
+                AddSessionCertToChain(&ssl->session.chain,
+                    input + args->idx, certSz);
+            #endif /* SESSION_CERTS */
+
+                args->idx += certSz;
+                listSz -= certSz + CERT_HEADER_SZ;
+
+            #ifdef WOLFSSL_TLS13
+                /* Extensions */
+                if (ssl->options.tls1_3) {
+                    word16 extSz;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz)
+                        return BUFFER_ERROR;
+                    ato16(input + args->idx, &extSz);
+                    args->idx += OPAQUE16_LEN;
+                    if ((args->idx - args->begin) + extSz > totalSz)
+                        return BUFFER_ERROR;
+                    /* Store extension data info for later processing. */
+                    args->exts[args->totalCerts].length = extSz;
+                    args->exts[args->totalCerts].buffer = input + args->idx;
+                    args->idx += extSz;
+                    listSz -= extSz + OPAQUE16_LEN;
+                    ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
+                        args->exts[args->totalCerts].length, certificate, NULL);
+                    if (ret < 0)
+                        return ret;
+                }
+            #endif
+
+                args->totalCerts++;
+                WOLFSSL_MSG("\tPut another cert into chain");
+            } /* while (listSz) */
+
+            args->count = args->totalCerts;
+            args->certIdx = 0;
+
+            args->dCertInit = 0;
+            args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                                       DYNAMIC_TYPE_DCERT);
+            if (args->dCert == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            if (args->count > 0) {
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+                if (args->certIdx == 0) {
+                    /* if using trusted peer certs check before verify chain
+                       and CA test */
+                    TrustedPeerCert* tp;
+
+                    cert = &args->certs[args->certIdx];
+
+                    if (!args->dCertInit) {
+                        InitDecodedCert(args->dCert,
+                            cert->buffer, cert->length, ssl->heap);
+                        args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        args->dCert->sigCtx.asyncCtx = ssl;
+                    #endif
+                        args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
+                    }
+
+                    ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
+                                                            ssl->ctx->cm);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                            args->dCert->sigCtx.asyncDev);
+                        goto exit_ppc;
+                    }
+                #endif
+                    if (ret != 0)
+                        goto exit_ppc;
+
+                #ifndef NO_SKID
+                    if (args->dCert->extAuthKeyIdSet) {
+                        tp = GetTrustedPeer(ssl->ctx->cm,
+                                    args->dCert->extSubjKeyId, WC_MATCH_SKID);
+                    }
+                    else { /* if the cert has no SKID try to match by name */
+                        tp = GetTrustedPeer(ssl->ctx->cm,
+                                    args->dCert->subjectHash, WC_MATCH_NAME);
+                    }
+                #else /* NO_SKID */
+                    tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash,
+                                                                 WC_MATCH_NAME);
+                #endif /* NO SKID */
+                    WOLFSSL_MSG("Checking for trusted peer cert");
+
+                    if (tp == NULL) {
+                        /* no trusted peer cert */
+                        WOLFSSL_MSG("No matching trusted peer cert. "
+                            "Checking CAs");
+                        FreeDecodedCert(args->dCert);
+                        args->dCertInit = 0;
+                    #ifdef OPENSSL_EXTRA
+                        args->untrustedDepth = 1;
+                    #endif
+                    } else if (MatchTrustedPeer(tp, args->dCert)){
+                        WOLFSSL_MSG("Found matching trusted peer cert");
+                        haveTrustPeer = 1;
+                    } else {
+                        WOLFSSL_MSG("Trusted peer cert did not match!");
+                        FreeDecodedCert(args->dCert);
+                        args->dCertInit = 0;
+                    #ifdef OPENSSL_EXTRA
+                        args->untrustedDepth = 1;
+                    #endif
+                    }
+                }
+            #endif /* WOLFSSL_TRUST_PEER_CERT */
+            #ifdef OPENSSL_EXTRA
+                #ifdef WOLFSSL_TRUST_PEER_CERT
+                else
+                #endif
+                if (args->certIdx == 0) {
+                    byte* subjectHash;
+                    cert = &args->certs[args->certIdx];
+
+                    if (!args->dCertInit) {
+                        InitDecodedCert(args->dCert,
+                            cert->buffer, cert->length, ssl->heap);
+                        args->dCert->sigCtx.devId = ssl->devId;
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        args->dCert->sigCtx.asyncCtx = ssl;
+                    #endif
+                        args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
+                    }
+
+                    ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
+                                                                  ssl->ctx->cm);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                            args->dCert->sigCtx.asyncDev);
+                        goto exit_ppc;
+                    }
+                #endif
+                    if (ret != 0) {
+                        goto exit_ppc;
+                    }
+
+                #ifndef NO_SKID
+                    subjectHash = args->dCert->extSubjKeyId;
+                #else
+                    subjectHash = args->dCert->subjectHash;
+                #endif
+                    if (!AlreadySigner(ssl->ctx->cm, subjectHash))
+                        args->untrustedDepth = 1;
+                    FreeDecodedCert(args->dCert);
+                    args->dCertInit = 0;
+                }
+            #endif
+
+                /* verify up to peer's first */
+                /* do not verify chain if trusted peer cert found */
+                while (args->count > 1
+                #ifdef WOLFSSL_TRUST_PEER_CERT
+                    && !haveTrustPeer
+                #endif /* WOLFSSL_TRUST_PEER_CERT */
+                ) {
+                    byte *subjectHash;
+
+                    args->certIdx = args->count - 1;
+                    cert = &args->certs[args->certIdx];
+
+                    if (!args->dCertInit) {
+                        InitDecodedCert(args->dCert,
+                            cert->buffer, cert->length, ssl->heap);
+                        args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        args->dCert->sigCtx.asyncCtx = ssl;
+                    #endif
+                        args->dCertInit = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                        if (ret != 0)
+                            goto exit_ppc;
+                    #endif
+                    }
+
+                    /* check if returning from non-blocking OCSP */
+                #ifdef WOLFSSL_NONBLOCK_OCSP
+                    if (args->lastErr != OCSP_WANT_READ)
+                    {
+                #endif
+
+                    ret = ParseCertRelative(args->dCert, CERT_TYPE,
+                                    !ssl->options.verifyNone, ssl->ctx->cm);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                            args->dCert->sigCtx.asyncDev);
+                        goto exit_ppc;
+                    }
+                #endif
+
+                #ifndef NO_SKID
+                    subjectHash = args->dCert->extSubjKeyId;
+                #else
+                    subjectHash = args->dCert->subjectHash;
+                #endif
+
+                    /* Check key sizes for certs. Is redundent check since
+                       ProcessBuffer also performs this check. */
+                    if (!ssl->options.verifyNone) {
+                        switch (args->dCert->keyOID) {
+                        #ifndef NO_RSA
+                            case RSAk:
+                                if (ssl->options.minRsaKeySz < 0 ||
+                                        args->dCert->pubKeySize <
+                                         (word16)ssl->options.minRsaKeySz) {
+                                    WOLFSSL_MSG(
+                                        "RSA key size in cert chain error");
+                                    ret = RSA_KEY_SIZE_E;
+                                }
+                                break;
+                        #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
+                            case ECDSAk:
+                                if (ssl->options.minEccKeySz < 0 ||
+                                        args->dCert->pubKeySize <
+                                         (word16)ssl->options.minEccKeySz) {
+                                    WOLFSSL_MSG(
+                                        "ECC key size in cert chain error");
+                                    ret = ECC_KEY_SIZE_E;
+                                }
+                                break;
+                        #endif /* HAVE_ECC */
+                        #ifdef HAVE_ED25519
+                            case ED25519k:
+                                if (ssl->options.minEccKeySz < 0 ||
+                                        ED25519_KEY_SIZE <
+                                         (word16)ssl->options.minEccKeySz) {
+                                    WOLFSSL_MSG(
+                                        "ECC key size in cert chain error");
+                                    ret = ECC_KEY_SIZE_E;
+                                }
+                                break;
+                        #endif /* HAVE_ED25519 */
+                            default:
+                                WOLFSSL_MSG("Key size not checked");
+                                /* key not being checked for size if not in
+                                   switch */
+                                break;
+                        } /* switch (dCert->keyOID) */
+                    } /* if (!ssl->options.verifyNone) */
+
+                    if (ret == 0 && args->dCert->isCA == 0) {
+                        WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
+                    }
+                    else if (ret == 0 && ssl->options.verifyNone) {
+                        WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
+                    }
+                    else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
+                        DerBuffer* add = NULL;
+                        ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
+                        if (ret < 0)
+                            goto exit_ppc;
+
+                        WOLFSSL_MSG("Adding CA from chain");
+
+                        XMEMCPY(add->buffer, cert->buffer, cert->length);
+
+                    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+                        if (args->certIdx > args->untrustedDepth)
+                            args->untrustedDepth = (char) args->certIdx + 1;
+                    #endif
+
+                        /* already verified above */
+                        ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0);
+                        if (ret == 1) {
+                            ret = 0;   /* WOLFSSL_SUCCESS for external */
+                        }
+
+                    #ifdef WOLFSSL_ALT_CERT_CHAINS
+                        /* if the previous CA cert failed, clear last error */
+                        if (args->lastCaErr != 0) {
+                            WOLFSSL_MSG("Using alternate cert chain");
+                            ssl->options.usingAltCertChain = 1;
+
+                            /* clear last CA fail since CA cert was validated */
+                            args->lastCaErr = 0;
+
+                        #ifdef SESSION_CERTS
+                            AddSessionCertToChain(&ssl->session.altChain,
+                                cert->buffer, cert->length);
+                        #endif /* SESSION_CERTS */
+                        }
+                    #endif
+                    }
+                    else if (ret != 0) {
+                        WOLFSSL_MSG("Failed to verify CA from chain");
+                    #ifdef WOLFSSL_ALT_CERT_CHAINS
+                        if (args->lastCaErr == 0) {
+                            /* store CA error and proceed to next cert */
+                            args->lastCaErr = ret;
+                            ret = 0;
+                        }
+                        else {
+                            args->lastErr = args->lastCaErr;
+                        }
+                    #endif
+                    #ifdef OPENSSL_EXTRA
+                        ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
+                    #endif
+                    }
+                    else {
+                        WOLFSSL_MSG("Verified CA from chain and already had it");
+                    }
+
+                #ifdef WOLFSSL_NONBLOCK_OCSP
+                    }
+                    else {
+                        args->lastErr = 0; /* clear last error */
+                    }
+                #endif
+
+            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+                    if (ret == 0) {
+                        int doCrlLookup = 1;
+                #ifdef HAVE_OCSP
+                    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                        if (ssl->status_request_v2) {
+                            ret = TLSX_CSR2_InitRequests(ssl->extensions,
+                                                    args->dCert, 0, ssl->heap);
+                        }
+                        else /* skips OCSP and force CRL check */
+                    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+                        if (ssl->ctx->cm->ocspEnabled &&
+                                            ssl->ctx->cm->ocspCheckAll) {
+                            WOLFSSL_MSG("Doing Non Leaf OCSP check");
+                            ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+                                                    args->dCert, NULL, ssl);
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
+                                goto exit_ppc;
+                            }
+                        #endif
+                            doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
+                            if (ret != 0) {
+                                doCrlLookup = 0;
+                                WOLFSSL_MSG("\tOCSP Lookup not ok");
+                            }
+                        }
+                #endif /* HAVE_OCSP */
+
+                #ifdef HAVE_CRL
+                        if (ret == 0 && doCrlLookup &&
+                                    ssl->ctx->cm->crlEnabled &&
+                                                ssl->ctx->cm->crlCheckAll) {
+                            WOLFSSL_MSG("Doing Non Leaf CRL check");
+                            ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+                        #ifdef WOLFSSL_NONBLOCK_OCSP
+                            if (ret == OCSP_WANT_READ) {
+                                args->lastErr = ret;
+                                goto exit_ppc;
+                            }
+                        #endif
+                            if (ret != 0) {
+                                WOLFSSL_MSG("\tCRL check not ok");
+                            }
+                        }
+                #endif /* HAVE_CRL */
+                        (void)doCrlLookup;
+                    }
+            #endif /* HAVE_OCSP || HAVE_CRL */
+
+            #if defined(WOLFSSL_VERIFY_CB_ALL_CERTS)
+                    if (ret != 0) {
+                        if (!ssl->options.verifyNone) {
+                            int why = bad_certificate;
+
+                        if (ret == ASN_AFTER_DATE_E || ret ==
+                                ASN_BEFORE_DATE_E) {
+                            why = certificate_expired;
+                        }
+                        if (ssl->verifyCallback) {
+                            int ok;
+
+                        #ifdef WOLFSSL_SMALL_STACK
+                            WOLFSSL_X509_STORE_CTX* store;
+                            WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(
+                                sizeof(WOLFSSL_X509), ssl->heap,
+                                DYNAMIC_TYPE_X509);
+                            if (x509 == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_ppc);
+                            }
+                            store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
+                                                    DYNAMIC_TYPE_X509_STORE);
+                            if (store == NULL) {
+                                wolfSSL_X509_free(x509);
+                                ERROR_OUT(MEMORY_E, exit_ppc);
+                            }
+                        #else
+                            WOLFSSL_X509_STORE_CTX  store[1];
+                            WOLFSSL_X509 x509[1];
+                        #endif
+
+                            XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
+
+                            store->error = ret;
+                            store->error_depth = args->certIdx;
+                            store->discardSessionCerts = 0;
+                            store->domain = args->domain;
+                            store->userCtx = ssl->verifyCbCtx;
+                            store->certs = args->certs;
+                            store->totalCerts = args->totalCerts;
+
+                        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+                            if (ssl->ctx->x509_store_pt != NULL) {
+                                store->store = ssl->ctx->x509_store_pt;
+                            }
+                            else {
+                                store->store = &ssl->ctx->x509_store;
+                            }
+                        #endif
+                        #if !defined(NO_CERTS)
+                            InitX509(x509, 1, ssl->heap);
+                            #if defined(KEEP_PEER_CERT) || \
+                                defined(SESSION_CERTS)
+                            if (CopyDecodedToX509(x509, args->dCert) == 0) {
+                                store->current_cert = x509;
+                            }
+                            #endif
+                        #endif
+                        #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS)
+                            store->ex_data = ssl;
+                        #endif
+                        #ifdef SESSION_CERTS
+                            store->sesChain = &(ssl->session.chain);
+                        #endif
+                            ok = ssl->verifyCallback(0, store);
+                            if (ok) {
+                                WOLFSSL_MSG("Verify callback overriding error!");
+                                ret = 0;
+                            }
+                        #ifndef NO_CERTS
+                            FreeX509(x509);
+                        #endif
+                        #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+                            wolfSSL_sk_X509_free(store->chain);
+                            store->chain = NULL;
+                        #endif
+                        #ifdef SESSION_CERTS
+                            if (store->discardSessionCerts) {
+                                WOLFSSL_MSG("Verify callback requested discard sess certs");
+                                ssl->session.chain.count = 0;
+                            #ifdef WOLFSSL_ALT_CERT_CHAINS
+                                ssl->session.altChain.count = 0;
+                            #endif
+                            }
+                        #endif /* SESSION_CERTS */
+                        #ifdef WOLFSSL_SMALL_STACK
+                            XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
+                            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
+                        #endif
+                        }
+                        if (ret != 0) {
+                            SendAlert(ssl, alert_fatal, why);   /* try to send */
+                            ssl->options.isClosed = 1;
+                        }
+                    }
+
+                    ssl->error = ret;
+                }
+            #ifdef WOLFSSL_ALWAYS_VERIFY_CB
+                else {
+                    if (ssl->verifyCallback) {
+                        int ok;
+
+                    #ifdef WOLFSSL_SMALL_STACK
+                        WOLFSSL_X509_STORE_CTX* store;
+                        WOLFSSL_X509* x509 = (WOLFSSL_X509*)XMALLOC(
+                                sizeof(WOLFSSL_X509), ssl->heap,
+                                DYNAMIC_TYPE_X509);
+                        if (x509 == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_ppc);
+                        }
+                        store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
+                                                    DYNAMIC_TYPE_X509_STORE);
+                        if (store == NULL) {
+                            wolfSSL_X509_free(x509);
+                            ERROR_OUT(MEMORY_E, exit_ppc);
+                        }
+                    #else
+                        WOLFSSL_X509_STORE_CTX  store[1];
+                        WOLFSSL_X509            x509[1];
+                    #endif
+
+                        XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
+
+                        store->error = ret;
+                        store->error_depth = args->certIdx;
+                        store->discardSessionCerts = 0;
+                        store->domain = args->domain;
+                        store->userCtx = ssl->verifyCbCtx;
+                        store->certs = args->certs;
+                        store->totalCerts = args->totalCerts;
+
+                    #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+                        if (ssl->ctx->x509_store_pt != NULL) {
+                            store->store = ssl->ctx->x509_store_pt;
+                        }
+                        else {
+                            store->store = &ssl->ctx->x509_store;
+                        }
+                    #endif
+                    #if !defined(NO_CERTS)
+                        InitX509(x509, 1, ssl->heap);
+                        #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
+                        if (CopyDecodedToX509(x509, args->dCert) == 0) {
+                            store->current_cert = x509;
+                        }
+                        #endif
+                    #endif
+                    #ifdef SESSION_CERTS
+                        store->sesChain = &(ssl->session.chain);
+                    #endif
+                        store->ex_data = ssl;
+
+                        ok = ssl->verifyCallback(1, store);
+                        if (!ok) {
+                            WOLFSSL_MSG("Verify callback overriding valid certificate!");
+                            ret = -1;
+                            ssl->options.isClosed = 1;
+                        }
+                    #ifndef NO_CERTS
+                        FreeX509(x509);
+                    #endif
+                    #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+                        wolfSSL_sk_X509_free(store->chain);
+                        store->chain = NULL;
+                    #endif
+                    #ifdef SESSION_CERTS
+                        if (store->discardSessionCerts) {
+                            WOLFSSL_MSG("Verify callback requested discard sess certs");
+                            ssl->session.chain.count = 0;
+                        #ifdef WOLFSSL_ALT_CERT_CHAINS
+                            ssl->session.altChain.count = 0;
+                        #endif
+                        }
+                    #endif /* SESSION_CERTS */
+                    #ifdef WOLFSSL_SMALL_STACK
+                        XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
+                        XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509);
+                    #endif
+                    }
+                }
+            #endif /* WOLFSSL_ALWAYS_VERIFY_CB */
+        #endif /* WOLFSSL_VERIFY_CB_ALL_CERTS */
+
+                    if (ret != 0 && args->lastErr == 0) {
+                        args->lastErr = ret;   /* save error from last time */
+                        ret = 0; /* reset error */
+                    }
+
+                    FreeDecodedCert(args->dCert);
+                    args->dCertInit = 0;
+                    args->count--;
+                } /* while (count > 0 && !haveTrustPeer) */
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            /* peer's, may not have one if blank client cert sent by TLSv1.2 */
+            if (args->count > 0) {
+                WOLFSSL_MSG("Verifying Peer's cert");
+
+                args->certIdx = 0;
+                cert = &args->certs[args->certIdx];
+
+                if (!args->dCertInit) {
+                    InitDecodedCert(args->dCert,
+                        cert->buffer, cert->length, ssl->heap);
+                    args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    args->dCert->sigCtx.asyncCtx = ssl;
+                #endif
+                    args->dCertInit = 1;
+                #ifdef HAVE_PK_CALLBACKS
+                    ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
+                    if (ret != 0)
+                        goto exit_ppc;
+                #endif
+                }
+
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+                if (!haveTrustPeer)
+            #endif
+                {
+                    /* only parse if not already present in dCert from above */
+                    ret = ParseCertRelative(args->dCert, CERT_TYPE,
+                                    !ssl->options.verifyNone, ssl->ctx->cm);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                            args->dCert->sigCtx.asyncDev);
+                        goto exit_ppc;
+                    }
+                #endif
+                }
+
+                if (ret == 0) {
+                    WOLFSSL_MSG("Verified Peer's cert");
+                #ifdef OPENSSL_EXTRA
+                    ssl->peerVerifyRet = X509_V_OK;
+                #endif
+                #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
+                    if (ssl->options.usingAltCertChain) {
+                        AddSessionCertToChain(&ssl->session.altChain,
+                            cert->buffer, cert->length);
+                    }
+                #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
+                    args->fatal = 0;
+                }
+                else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
+                    WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
+                #ifdef OPENSSL_EXTRA
+                    SendAlert(ssl, alert_fatal, bad_certificate);
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                #endif
+                    args->fatal = 1;
+                }
+                else {
+                    WOLFSSL_MSG("Failed to verify Peer's cert");
+                #ifdef OPENSSL_EXTRA
+                    ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+                #endif
+                    if (ssl->verifyCallback) {
+                        WOLFSSL_MSG(
+                            "\tCallback override available, will continue");
+                        args->fatal = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("\tNo callback override available, fatal");
+                        args->fatal = 1;
+                    #ifdef OPENSSL_EXTRA
+                        SendAlert(ssl, alert_fatal, bad_certificate);
+                    #endif
+                    }
+                }
+
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                if (args->fatal == 0 && ssl->secure_renegotiation
+                               && ssl->secure_renegotiation->enabled) {
+
+                    if (IsEncryptionOn(ssl, 0)) {
+                        /* compare against previous time */
+                        if (XMEMCMP(args->dCert->subjectHash,
+                                    ssl->secure_renegotiation->subject_hash,
+                                    WC_SHA_DIGEST_SIZE) != 0) {
+                            WOLFSSL_MSG(
+                                "Peer sent different cert during scr, fatal");
+                            args->fatal = 1;
+                            ret   = SCR_DIFFERENT_CERT_E;
+                        }
+                    }
+
+                    /* cache peer's hash */
+                    if (args->fatal == 0) {
+                        XMEMCPY(ssl->secure_renegotiation->subject_hash,
+                                args->dCert->subjectHash, WC_SHA_DIGEST_SIZE);
+                    }
+                }
+            #endif /* HAVE_SECURE_RENEGOTIATION */
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (args->fatal && ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            if (args->count > 0) {
+            #if defined(HAVE_OCSP) || defined(HAVE_CRL)
+                if (args->fatal == 0) {
+                    int doLookup = 1;
+
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+                        if (ssl->status_request) {
+                            args->fatal = TLSX_CSR_InitRequest(ssl->extensions,
+                                                    args->dCert, ssl->heap);
+                            doLookup = 0;
+                        #ifdef WOLFSSL_TLS13
+                            if (ssl->options.tls1_3) {
+                                TLSX* ext = TLSX_Find(ssl->extensions,
+                                                           TLSX_STATUS_REQUEST);
+                                if (ext != NULL) {
+                                    word32 idx = 0;
+                                    CertificateStatusRequest* csr =
+                                           (CertificateStatusRequest*)ext->data;
+                                    ret = ProcessCSR(ssl, csr->response.buffer,
+                                                    &idx, csr->response.length);
+                                    if (ret < 0)
+                                        goto exit_ppc;
+                                }
+                            }
+                        #endif
+                        }
+                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+                #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                        if (ssl->status_request_v2) {
+                            args->fatal = TLSX_CSR2_InitRequests(ssl->extensions,
+                                                    args->dCert, 1, ssl->heap);
+                            doLookup = 0;
+                        }
+                #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+                    }
+
+                #ifdef HAVE_OCSP
+                    if (doLookup && ssl->ctx->cm->ocspEnabled) {
+                        WOLFSSL_MSG("Doing Leaf OCSP check");
+                        ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp,
+                                                    args->dCert, NULL, ssl);
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
+                            goto exit_ppc;
+                        }
+                    #endif
+                        doLookup = (ret == OCSP_CERT_UNKNOWN);
+                        if (ret != 0) {
+                            WOLFSSL_MSG("\tOCSP Lookup not ok");
+                            args->fatal = 0;
+                        #ifdef OPENSSL_EXTRA
+                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                        #endif
+                        }
+                    }
+                #endif /* HAVE_OCSP */
+
+                #ifdef HAVE_CRL
+                    if (doLookup && ssl->ctx->cm->crlEnabled) {
+                        WOLFSSL_MSG("Doing Leaf CRL check");
+                        ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert);
+                    #ifdef WOLFSSL_NONBLOCK_OCSP
+                        if (ret == OCSP_WANT_READ) {
+                            goto exit_ppc;
+                        }
+                    #endif
+                        if (ret != 0) {
+                            WOLFSSL_MSG("\tCRL check not ok");
+                            args->fatal = 0;
+                        #ifdef OPENSSL_EXTRA
+                            ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                        #endif
+                        }
+                    }
+                #endif /* HAVE_CRL */
+                    (void)doLookup;
+                }
+            #endif /* HAVE_OCSP || HAVE_CRL */
+
+            #ifdef KEEP_PEER_CERT
+                if (args->fatal == 0) {
+                    /* set X509 format for peer cert */
+                    int copyRet = CopyDecodedToX509(&ssl->peerCert,
+                                                                args->dCert);
+                    if (copyRet == MEMORY_E) {
+                        args->fatal = 1;
+                    }
+                }
+            #endif /* KEEP_PEER_CERT */
+
+            #ifndef IGNORE_KEY_EXTENSIONS
+                #if defined(OPENSSL_EXTRA)
+                  /* when compatibility layer is turned on and no verify is
+                   * set then ignore the certificate key extension */
+                    if (args->dCert->extKeyUsageSet &&
+                          args->dCert->extKeyUsageCrit == 0 &&
+                          ssl->options.verifyNone) {
+                        WOLFSSL_MSG("Not verifying certificate key usage");
+                    }
+                    else
+                #endif
+                if (args->dCert->extKeyUsageSet) {
+                    if ((ssl->specs.kea == rsa_kea) &&
+                        (ssl->options.side == WOLFSSL_CLIENT_END) &&
+                        (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) {
+                        ret = KEYUSE_ENCIPHER_E;
+                    }
+                    if ((ssl->specs.sig_algo == rsa_sa_algo ||
+                            (ssl->specs.sig_algo == ecc_dsa_sa_algo &&
+                                 !ssl->specs.static_ecdh)) &&
+                        (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) {
+                        WOLFSSL_MSG("KeyUse Digital Sig not set");
+                        ret = KEYUSE_SIGNATURE_E;
+                    }
+                }
+
+                #if defined(OPENSSL_EXTRA)
+                    /* when compatibility layer is turned on and no verify is
+                     * set then ignore the certificate key extension */
+                    if (args->dCert->extExtKeyUsageSet &&
+                            args->dCert->extExtKeyUsageCrit == 0 &&
+                          ssl->options.verifyNone) {
+                                WOLFSSL_MSG("Not verifying certificate ext key usage");
+                    }
+                    else
+                #endif
+                if (args->dCert->extExtKeyUsageSet) {
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                        if ((args->dCert->extExtKeyUsage &
+                                (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) {
+                            WOLFSSL_MSG("ExtKeyUse Server Auth not set");
+                            ret = EXTKEYUSE_AUTH_E;
+                        }
+                    }
+                    else {
+                        if ((args->dCert->extExtKeyUsage &
+                                (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) {
+                            WOLFSSL_MSG("ExtKeyUse Client Auth not set");
+                            ret = EXTKEYUSE_AUTH_E;
+                        }
+                    }
+                }
+            #endif /* IGNORE_KEY_EXTENSIONS */
+
+                if (args->fatal) {
+                    ssl->error = ret;
+                #ifdef OPENSSL_EXTRA
+                    SendAlert(ssl, alert_fatal, bad_certificate);
+                    ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED;
+                #endif
+                    goto exit_ppc;
+                }
+
+                ssl->options.havePeerCert = 1;
+
+                args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap,
+                                                    DYNAMIC_TYPE_STRING);
+                if (args->domain == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_ppc);
+                }
+
+                /* store for callback use */
+                if (args->dCert->subjectCN &&
+                                    args->dCert->subjectCNLen < ASN_NAME_MAX) {
+                    XMEMCPY(args->domain, args->dCert->subjectCN,
+                        args->dCert->subjectCNLen);
+                    args->domain[args->dCert->subjectCNLen] = '\0';
+                }
+                else {
+                    args->domain[0] = '\0';
+                }
+
+                if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
+                #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
+                    /* Per RFC 5280 section 4.2.1.6, "Whenever such identities
+                     * are to be bound into a certificate, the subject
+                     * alternative name extension MUST be used." */
+                    if (args->dCert->altNames) {
+                        if (CheckAltNames(args->dCert,
+                                (char*)ssl->buffers.domainName.buffer) == 0 ) {
+                            WOLFSSL_MSG("DomainName match on alt names failed");
+                            /* try to get peer key still */
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                    else {
+                        if (MatchDomainName(
+                                 args->dCert->subjectCN,
+                                 args->dCert->subjectCNLen,
+                                 (char*)ssl->buffers.domainName.buffer) == 0) {
+                            WOLFSSL_MSG("DomainName match on common name failed");
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                #else /* WOLFSSL_ALL_NO_CN_IN_SAN */
+                    /* Old behavior. */
+                    if (MatchDomainName(args->dCert->subjectCN,
+                                args->dCert->subjectCNLen,
+                                (char*)ssl->buffers.domainName.buffer) == 0) {
+                        WOLFSSL_MSG("DomainName match on common name failed");
+                        if (CheckAltNames(args->dCert,
+                                 (char*)ssl->buffers.domainName.buffer) == 0 ) {
+                            WOLFSSL_MSG(
+                                "DomainName match on alt names failed too");
+                            /* try to get peer key still */
+                            ret = DOMAIN_NAME_MISMATCH;
+                        }
+                    }
+                #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
+                }
+
+                /* decode peer key */
+                switch (args->dCert->keyOID) {
+                #ifndef NO_RSA
+                    case RSAk:
+                    {
+                        word32 keyIdx = 0;
+                        int keyRet = 0;
+
+                        if (ssl->peerRsaKey == NULL) {
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA,
+                                                (void**)&ssl->peerRsaKey);
+                        } else if (ssl->peerRsaKeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA,
+                                              ssl->peerRsaKey);
+                            ssl->peerRsaKeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 || wc_RsaPublicKeyDecode(
+                                args->dCert->publicKey, &keyIdx, ssl->peerRsaKey,
+                                                args->dCert->pubKeySize) != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerRsaKeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                        #ifndef NO_RSA
+                            ssl->buffers.peerRsaKey.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                                ssl->heap, DYNAMIC_TYPE_RSA);
+                            if (ssl->buffers.peerRsaKey.buffer == NULL) {
+                                ret = MEMORY_ERROR;
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerRsaKey.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerRsaKey.length =
+                                    args->dCert->pubKeySize;
+                            }
+                        #endif /* NO_RSA */
+                    #endif /* HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer RSA key */
+                        if (ret == 0 && ssl->peerRsaKeyPresent &&
+                                          !ssl->options.verifyNone &&
+                                          wc_RsaEncryptSize(ssl->peerRsaKey)
+                                              < ssl->options.minRsaKeySz) {
+                            ret = RSA_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer RSA key is too small");
+                        }
+                        break;
+                    }
+                #endif /* NO_RSA */
+                #ifdef HAVE_NTRU
+                    case NTRUk:
+                    {
+                        if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey,
+                                                      args->dCert->pubKeySize);
+                            ssl->peerNtruKeyLen =
+                                (word16)args->dCert->pubKeySize;
+                            ssl->peerNtruKeyPresent = 1;
+                        }
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #ifdef HAVE_ECC
+                    case ECDSAk:
+                    {
+                        int keyRet = 0;
+                        word32 idx = 0;
+
+                        if (ssl->peerEccDsaKey == NULL) {
+                            /* alloc/init on demand */
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                    (void**)&ssl->peerEccDsaKey);
+                        } else if (ssl->peerEccDsaKeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                              ssl->peerEccDsaKey);
+                            ssl->peerEccDsaKeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 ||
+                            wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
+                                                ssl->peerEccDsaKey,
+                                                args->dCert->pubKeySize) != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerEccDsaKeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.peerEccDsaKey.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                           ssl->heap, DYNAMIC_TYPE_ECC);
+                            if (ssl->buffers.peerEccDsaKey.buffer == NULL) {
+                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerEccDsaKey.length =
+                                        args->dCert->pubKeySize;
+                            }
+                    #endif /* HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer ECC key */
+                        if (ret == 0 && ssl->peerEccDsaKeyPresent &&
+                                              !ssl->options.verifyNone &&
+                                              wc_ecc_size(ssl->peerEccDsaKey)
+                                              < ssl->options.minEccKeySz) {
+                            ret = ECC_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer ECC key is too small");
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ECC */
+                #ifdef HAVE_ED25519
+                    case ED25519k:
+                    {
+                        int keyRet = 0;
+                        if (ssl->peerEd25519Key == NULL) {
+                            /* alloc/init on demand */
+                            keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519,
+                                    (void**)&ssl->peerEd25519Key);
+                        } else if (ssl->peerEd25519KeyPresent) {
+                            keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519,
+                                              ssl->peerEd25519Key);
+                            ssl->peerEd25519KeyPresent = 0;
+                        }
+
+                        if (keyRet != 0 ||
+                            wc_ed25519_import_public(args->dCert->publicKey,
+                                                     args->dCert->pubKeySize,
+                                                     ssl->peerEd25519Key)
+                                                                         != 0) {
+                            ret = PEER_KEY_ERROR;
+                        }
+                        else {
+                            ssl->peerEd25519KeyPresent = 1;
+                    #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.peerEd25519Key.buffer =
+                                   (byte*)XMALLOC(args->dCert->pubKeySize,
+                                           ssl->heap, DYNAMIC_TYPE_ED25519);
+                            if (ssl->buffers.peerEd25519Key.buffer == NULL) {
+                                ERROR_OUT(MEMORY_ERROR, exit_ppc);
+                            }
+                            else {
+                                XMEMCPY(ssl->buffers.peerEd25519Key.buffer,
+                                        args->dCert->publicKey,
+                                        args->dCert->pubKeySize);
+                                ssl->buffers.peerEd25519Key.length =
+                                        args->dCert->pubKeySize;
+                            }
+                    #endif /*HAVE_PK_CALLBACKS */
+                        }
+
+                        /* check size of peer ECC key */
+                        if (ret == 0 && ssl->peerEd25519KeyPresent &&
+                                  !ssl->options.verifyNone &&
+                                  ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+                            ret = ECC_KEY_SIZE_E;
+                            WOLFSSL_MSG("Peer ECC key is too small");
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ED25519 */
+                    default:
+                        break;
+                }
+
+                FreeDecodedCert(args->dCert);
+                args->dCertInit = 0;
+
+                /* release since we don't need it anymore */
+                if (args->dCert) {
+                    XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
+                    args->dCert = NULL;
+                }
+            } /* if (count > 0) */
+
+            /* Check for error */
+            if (args->fatal && ret != 0) {
+                goto exit_ppc;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+        #ifdef WOLFSSL_SMALL_STACK
+            WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+                                    sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap,
+                                                    DYNAMIC_TYPE_X509_STORE);
+            if (store == NULL) {
+                ERROR_OUT(MEMORY_E, exit_ppc);
+            }
+        #else
+            WOLFSSL_X509_STORE_CTX  store[1];
+        #endif
+
+            XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
+
+            /* load last error */
+            if (args->lastErr != 0 && ret == 0) {
+                ret = args->lastErr;
+            }
+
+        #ifdef OPENSSL_EXTRA
+            if (args->untrustedDepth > ssl->options.verifyDepth) {
+                ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+                ret = MAX_CHAIN_ERROR;
+            }
+        #endif
+            if (ret != 0) {
+                if (!ssl->options.verifyNone) {
+                    int why = bad_certificate;
+
+                    if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
+                        why = certificate_expired;
+                    }
+                    if (ssl->verifyCallback) {
+                        int ok;
+
+                        store->error = ret;
+                        store->error_depth = args->certIdx;
+                        store->discardSessionCerts = 0;
+                        store->domain = args->domain;
+                        store->userCtx = ssl->verifyCbCtx;
+                        store->certs = args->certs;
+                        store->totalCerts = args->totalCerts;
+
+                    #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+                        if (ssl->ctx->x509_store_pt != NULL) {
+                            store->store = ssl->ctx->x509_store_pt;
+                        }
+                        else {
+                            store->store = &ssl->ctx->x509_store;
+                        }
+                    #endif
+                    #ifdef KEEP_PEER_CERT
+                        if (ssl->peerCert.subject.sz > 0)
+                            store->current_cert = &ssl->peerCert;
+                        else
+                            store->current_cert = NULL;
+                    #else
+                        store->current_cert = NULL;
+                    #endif /* KEEP_PEER_CERT */
+                    #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS)
+                        store->ex_data = ssl;
+                    #endif
+                    #ifdef SESSION_CERTS
+                        store->sesChain = &(ssl->session.chain);
+                    #endif
+                        ok = ssl->verifyCallback(0, store);
+                        if (ok) {
+                            WOLFSSL_MSG("Verify callback overriding error!");
+                            ret = 0;
+                        }
+                    #ifdef SESSION_CERTS
+                        if (store->discardSessionCerts) {
+                            WOLFSSL_MSG("Verify callback requested discard sess certs");
+                            ssl->session.chain.count = 0;
+                        #ifdef WOLFSSL_ALT_CERT_CHAINS
+                            ssl->session.altChain.count = 0;
+                        #endif
+                        }
+                    #endif /* SESSION_CERTS */
+                    }
+                    if (ret != 0) {
+                        SendAlert(ssl, alert_fatal, why);   /* try to send */
+                        ssl->options.isClosed = 1;
+                    }
+                }
+
+                ssl->error = ret;
+            }
+        #ifdef WOLFSSL_ALWAYS_VERIFY_CB
+            else {
+                if (ssl->verifyCallback) {
+                    int ok;
+
+                    store->error = ret;
+                #ifdef WOLFSSL_WPAS
+                    store->error_depth = 0;
+                #else
+                    store->error_depth = args->certIdx;
+                #endif
+                    store->discardSessionCerts = 0;
+                    store->domain = args->domain;
+                    store->userCtx = ssl->verifyCbCtx;
+                    store->certs = args->certs;
+                    store->totalCerts = args->totalCerts;
+
+                #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+                    if (ssl->ctx->x509_store_pt != NULL) {
+                        store->store = ssl->ctx->x509_store_pt;
+                    }
+                    else {
+                        store->store = &ssl->ctx->x509_store;
+                    }
+                #endif
+                #ifdef KEEP_PEER_CERT
+                    if (ssl->peerCert.subject.sz > 0)
+                        store->current_cert = &ssl->peerCert;
+                    else
+                        store->current_cert = NULL;
+                #endif
+                    store->ex_data = ssl;
+                #ifdef SESSION_CERTS
+                    store->sesChain = &(ssl->session.chain);
+                #endif
+
+                    ok = ssl->verifyCallback(1, store);
+                    if (!ok) {
+                        WOLFSSL_MSG("Verify callback overriding valid certificate!");
+                        ret = -1;
+                        SendAlert(ssl, alert_fatal, bad_certificate);
+                        ssl->options.isClosed = 1;
+                    }
+                #ifdef SESSION_CERTS
+                    if (store->discardSessionCerts) {
+                        WOLFSSL_MSG("Verify callback requested discard sess certs");
+                        ssl->session.chain.count = 0;
+                    #ifdef WOLFSSL_ALT_CERT_CHAINS
+                        ssl->session.altChain.count = 0;
+                    #endif
+                    }
+                #endif /* SESSION_CERTS */
+                }
+            }
+        #endif /* WOLFSSL_ALWAYS_VERIFY_CB */
+
+            if (ssl->options.verifyNone &&
+                                      (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) {
+                WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
+                ret = ssl->error = 0;
+            }
+
+            if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
+                ssl->options.serverState = SERVER_CERT_COMPLETE;
+            }
+
+            if (IsEncryptionOn(ssl, 0)) {
+                args->idx += ssl->keys.padSz;
+            }
+
+        #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+            wolfSSL_sk_X509_free(store->chain);
+            store->chain = NULL;
+        #endif
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE);
+        #endif
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* Set final index */
+            *inOutIdx = args->idx;
+
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+            break;
+    } /* switch(ssl->options.asyncState) */
+
+exit_ppc:
+
+    WOLFSSL_LEAVE("ProcessPeerCerts", ret);
+
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+    if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) {
+        /* Mark message as not recevied so it can process again */
+        ssl->msgsReceived.got_certificate = 0;
+
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
+
+    FreeProcPeerCertArgs(ssl, args);
+
+#if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_NONBLOCK_OCSP)
+    XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    ssl->nonblockarg = NULL;
+#endif
+
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of certificate (11) */
+static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                word32 size)
+{
+    int ret;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
+    WOLFSSL_ENTER("DoCertificate");
+
+    ret = ProcessPeerCerts(ssl, input, inOutIdx, size);
+
+#ifdef OPENSSL_EXTRA
+    ssl->options.serverState = SERVER_CERT_COMPLETE;
+#endif
+
+    WOLFSSL_LEAVE("DoCertificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
+
+    return ret;
+}
+
+/* handle processing of certificate_status (22) */
+static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                    word32 size)
+{
+    int    ret = 0;
+    byte   status_type;
+    word32 status_length;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
+    WOLFSSL_ENTER("DoCertificateStatus");
+
+    if (size < ENUM_LEN + OPAQUE24_LEN)
+        return BUFFER_ERROR;
+
+    status_type = input[(*inOutIdx)++];
+
+    c24to32(input + *inOutIdx, &status_length);
+    *inOutIdx += OPAQUE24_LEN;
+
+    if (size != ENUM_LEN + OPAQUE24_LEN + status_length)
+        return BUFFER_ERROR;
+
+    switch (status_type) {
+
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+        /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
+        case WOLFSSL_CSR2_OCSP:
+            ret = ProcessCSR(ssl, input, inOutIdx, status_length);
+            break;
+
+    #endif
+
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+
+        case WOLFSSL_CSR2_OCSP_MULTI: {
+            OcspRequest* request;
+            word32 list_length = status_length;
+            byte   idx = 0;
+
+            #ifdef WOLFSSL_SMALL_STACK
+                CertStatus* status;
+                OcspResponse* response;
+            #else
+                CertStatus status[1];
+                OcspResponse response[1];
+            #endif
+
+            do {
+                if (ssl->status_request_v2) {
+                    ssl->status_request_v2 = 0;
+                    break;
+                }
+
+                return BUFFER_ERROR;
+            } while(0);
+
+            #ifdef WOLFSSL_SMALL_STACK
+                status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
+                                                       DYNAMIC_TYPE_OCSP_STATUS);
+                response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
+                                                       DYNAMIC_TYPE_OCSP_REQUEST);
+
+                if (status == NULL || response == NULL) {
+                    if (status)
+                        XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+                    if (response)
+                        XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+
+                    return MEMORY_ERROR;
+                }
+            #endif
+
+            while (list_length && ret == 0) {
+                if (OPAQUE24_LEN > list_length) {
+                    ret = BUFFER_ERROR;
+                    break;
+                }
+
+                c24to32(input + *inOutIdx, &status_length);
+                *inOutIdx   += OPAQUE24_LEN;
+                list_length -= OPAQUE24_LEN;
+
+                if (status_length > list_length) {
+                    ret = BUFFER_ERROR;
+                    break;
+                }
+
+                if (status_length) {
+                    InitOcspResponse(response, status, input +*inOutIdx,
+                                                                 status_length);
+
+                    if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
+                                                                        0) != 0)
+                    ||  (response->responseStatus != OCSP_SUCCESSFUL)
+                    ||  (response->status->status != CERT_GOOD))
+                        ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+                    while (ret == 0) {
+                        request = (OcspRequest*)TLSX_CSR2_GetRequest(
+                                ssl->extensions, status_type, idx++);
+
+                        if (request == NULL)
+                            ret = BAD_CERTIFICATE_STATUS_ERROR;
+                        else if (CompareOcspReqResp(request, response) == 0)
+                            break;
+                        else if (idx == 1) /* server cert must be OK */
+                            ret = BAD_CERTIFICATE_STATUS_ERROR;
+                    }
+
+                    *inOutIdx   += status_length;
+                    list_length -= status_length;
+                }
+            }
+
+            #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+                ssl->status_request_v2 = 0;
+            #endif
+
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(status,   NULL, DYNAMIC_TYPE_OCSP_STATUS);
+                XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+            #endif
+
+        }
+        break;
+
+    #endif
+
+        default:
+            ret = BUFFER_ERROR;
+    }
+
+    if (ret != 0)
+        SendAlert(ssl, alert_fatal, bad_certificate_status_response);
+
+    WOLFSSL_LEAVE("DoCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO);
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+
+static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                                                    word32 size, word32 totalSz)
+{
+    (void)input;
+
+    if (size) /* must be 0 */
+        return BUFFER_ERROR;
+
+    if (IsEncryptionOn(ssl, 0)) {
+        /* access beyond input + size should be checked against totalSz */
+        if (*inOutIdx + ssl->keys.padSz > totalSz)
+            return BUFFER_E;
+
+        *inOutIdx += ssl->keys.padSz;
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        SendAlert(ssl, alert_fatal, unexpected_message); /* try */
+        return FATAL_ERROR;
+    }
+#ifdef HAVE_SECURE_RENEGOTIATION
+    else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
+        ssl->secure_renegotiation->startScr = 1;
+        return 0;
+    }
+#endif
+    else {
+        return SendAlert(ssl, alert_warning, no_renegotiation);
+    }
+}
+
+
+int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
+                                                      word32 totalSz, int sniff)
+{
+    word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ);
+
+    WOLFSSL_START(WC_FUNC_FINISHED_DO);
+    WOLFSSL_ENTER("DoFinished");
+
+    if (finishedSz != size)
+        return BUFFER_ERROR;
+
+    /* check against totalSz */
+    if (*inOutIdx + size + ssl->keys.padSz > totalSz)
+        return BUFFER_E;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+    #endif
+
+    if (sniff == NO_SNIFF) {
+        if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){
+            WOLFSSL_MSG("Verify finished error on hashes");
+            return VERIFY_FINISHED_ERROR;
+        }
+    }
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation) {
+        /* save peer's state */
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            XMEMCPY(ssl->secure_renegotiation->server_verify_data,
+                    input + *inOutIdx, TLS_FINISHED_SZ);
+        else
+            XMEMCPY(ssl->secure_renegotiation->client_verify_data,
+                    input + *inOutIdx, TLS_FINISHED_SZ);
+    }
+#endif
+
+    /* force input exhaustion at ProcessReply consuming padSz */
+    *inOutIdx += size + ssl->keys.padSz;
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+		ssl->cbmode = SSL_CB_MODE_WRITE;
+		ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#endif
+        if (!ssl->options.resuming) {
+#ifdef OPENSSL_EXTRA
+			if (ssl->CBIS != NULL) {
+				ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+			}
+#endif
+			ssl->options.handShakeState = HANDSHAKE_DONE;
+			ssl->options.handShakeDone  = 1;
+		}
+    }
+    else {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_READ;
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#endif
+        if (ssl->options.resuming) {
+#ifdef OPENSSL_EXTRA
+			if (ssl->CBIS != NULL) {
+				ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+			}
+#endif
+			ssl->options.handShakeState = HANDSHAKE_DONE;
+			ssl->options.handShakeDone  = 1;
+        }
+    }
+
+    WOLFSSL_LEAVE("DoFinished", 0);
+    WOLFSSL_END(WC_FUNC_FINISHED_DO);
+
+    return 0;
+}
+
+
+/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
+static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
+{
+    /* verify not a duplicate, mark received, check state */
+    switch (type) {
+
+#ifndef NO_WOLFSSL_CLIENT
+        case hello_request:
+            if (ssl->msgsReceived.got_hello_request) {
+                WOLFSSL_MSG("Duplicate HelloRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_hello:
+            if (ssl->msgsReceived.got_client_hello) {
+                WOLFSSL_MSG("Duplicate ClientHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_hello = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello:
+            if (ssl->msgsReceived.got_server_hello) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case hello_verify_request:
+            if (ssl->msgsReceived.got_hello_verify_request) {
+                WOLFSSL_MSG("Duplicate HelloVerifyRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_verify_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case session_ticket:
+            if (ssl->msgsReceived.got_session_ticket) {
+                WOLFSSL_MSG("Duplicate SessionTicket received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_session_ticket = 1;
+
+            break;
+#endif
+
+        case certificate:
+            if (ssl->msgsReceived.got_certificate) {
+                WOLFSSL_MSG("Duplicate Certificate received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate = 1;
+
+#ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if ( ssl->msgsReceived.got_server_hello == 0) {
+                    WOLFSSL_MSG("No ServerHello before Cert");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if ( ssl->msgsReceived.got_client_hello == 0) {
+                    WOLFSSL_MSG("No ClientHello before Cert");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+#endif
+            break;
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_status:
+            if (ssl->msgsReceived.got_certificate_status) {
+                WOLFSSL_MSG("Duplicate CertificateSatatus received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_status = 1;
+
+            if (ssl->msgsReceived.got_certificate == 0) {
+                WOLFSSL_MSG("No Certificate before CertificateStatus");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_server_key_exchange != 0) {
+                WOLFSSL_MSG("CertificateStatus after ServerKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_key_exchange:
+            if (ssl->msgsReceived.got_server_key_exchange) {
+                WOLFSSL_MSG("Duplicate ServerKeyExchange received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_key_exchange = 1;
+
+            if (ssl->msgsReceived.got_server_hello == 0) {
+                WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_certificate_status == 0) {
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+                if (ssl->status_request) {
+                    int ret;
+
+                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+                    if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0)
+                        return ret;
+                }
+#endif
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+                if (ssl->status_request_v2) {
+                    int ret;
+
+                    WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+                    if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0)
+                        return ret;
+                }
+#endif
+            }
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_request:
+            if (ssl->msgsReceived.got_certificate_request) {
+                WOLFSSL_MSG("Duplicate CertificateRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_request = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello_done:
+            if (ssl->msgsReceived.got_server_hello_done) {
+                WOLFSSL_MSG("Duplicate ServerHelloDone received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello_done = 1;
+
+            if (ssl->msgsReceived.got_certificate == 0) {
+                if (ssl->specs.kea == psk_kea ||
+                    ssl->specs.kea == dhe_psk_kea ||
+                    ssl->specs.kea == ecdhe_psk_kea ||
+                    ssl->options.usingAnon_cipher) {
+                    WOLFSSL_MSG("No Cert required");
+                } else {
+                    WOLFSSL_MSG("No Certificate before ServerHelloDone");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+            if (ssl->msgsReceived.got_server_key_exchange == 0) {
+                int pskNoServerHint = 0;  /* not required in this case */
+
+                #ifndef NO_PSK
+                    if (ssl->specs.kea == psk_kea &&
+                                               ssl->arrays->server_hint[0] == 0)
+                        pskNoServerHint = 1;
+                #endif
+                if (ssl->specs.static_ecdh == 1 ||
+                    ssl->specs.kea == rsa_kea ||
+                    ssl->specs.kea == ntru_kea ||
+                    pskNoServerHint) {
+                    WOLFSSL_MSG("No KeyExchange required");
+                } else {
+                    WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case certificate_verify:
+            if (ssl->msgsReceived.got_certificate_verify) {
+                WOLFSSL_MSG("Duplicate CertificateVerify received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_verify = 1;
+
+            if ( ssl->msgsReceived.got_certificate == 0) {
+                WOLFSSL_MSG("No Cert before CertVerify");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_key_exchange:
+            if (ssl->msgsReceived.got_client_key_exchange) {
+                WOLFSSL_MSG("Duplicate ClientKeyExchange received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_key_exchange = 1;
+
+            if (ssl->msgsReceived.got_client_hello == 0) {
+                WOLFSSL_MSG("No ClientHello before ClientKeyExchange");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+#endif
+
+        case finished:
+            if (ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("Duplicate Finished received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_finished = 1;
+
+            if (ssl->msgsReceived.got_change_cipher == 0) {
+                WOLFSSL_MSG("Finished received before ChangeCipher");
+                return NO_CHANGE_CIPHER_E;
+            }
+            break;
+
+        case change_cipher_hs:
+            if (ssl->msgsReceived.got_change_cipher) {
+                WOLFSSL_MSG("Duplicate ChangeCipher received");
+                return DUPLICATE_MSG_E;
+            }
+            /* DTLS is going to ignore the CCS message if the client key
+             * exchange message wasn't received yet. */
+            if (!ssl->options.dtls)
+                ssl->msgsReceived.got_change_cipher = 1;
+
+#ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (!ssl->options.resuming &&
+                                 ssl->msgsReceived.got_server_hello_done == 0) {
+                    WOLFSSL_MSG("No ServerHelloDone before ChangeCipher");
+                    return OUT_OF_ORDER_E;
+                }
+                #ifdef HAVE_SESSION_TICKET
+                    if (ssl->expect_session_ticket) {
+                        WOLFSSL_MSG("Expected session ticket missing");
+                        #ifdef WOLFSSL_DTLS
+                            if (ssl->options.dtls)
+                                return OUT_OF_ORDER_E;
+                        #endif
+                        return SESSION_TICKET_EXPECT_E;
+                    }
+                #endif
+            }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (!ssl->options.resuming &&
+                               ssl->msgsReceived.got_client_key_exchange == 0) {
+                    WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher");
+                    return OUT_OF_ORDER_E;
+                }
+                #ifndef NO_CERTS
+                    if (ssl->options.verifyPeer &&
+                        ssl->options.havePeerCert) {
+
+                        if (!ssl->options.havePeerVerify) {
+                            WOLFSSL_MSG("client didn't send cert verify");
+                            #ifdef WOLFSSL_DTLS
+                                if (ssl->options.dtls)
+                                    return OUT_OF_ORDER_E;
+                            #endif
+                            return NO_PEER_VERIFY;
+                        }
+                    }
+                #endif
+            }
+#endif
+            if (ssl->options.dtls)
+                ssl->msgsReceived.got_change_cipher = 1;
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown message type");
+            return SANITY_MSG_E;
+    }
+
+    return 0;
+}
+
+
+static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          byte type, word32 size, word32 totalSz)
+{
+    int ret = 0;
+    word32 expectedIdx;
+
+    WOLFSSL_ENTER("DoHandShakeMsgType");
+
+#ifdef WOLFSSL_TLS13
+    if (type == hello_retry_request) {
+        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                       totalSz);
+    }
+#endif
+
+    /* make sure can read the message */
+    if (*inOutIdx + size > totalSz)
+        return INCOMPLETE_DATA;
+
+    expectedIdx = *inOutIdx + size +
+                  (ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
+
+    /* sanity check msg received */
+    if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) {
+        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
+        return ret;
+    }
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    /* add name later, add on record and handshake header part back on */
+    if (ssl->toInfoOn) {
+        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
+                      size + add, READ_PROTO, ssl->heap);
+        #ifdef WOLFSSL_CALLBACKS
+        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+        #endif
+    }
+#endif
+
+    if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
+        WOLFSSL_MSG("HandShake message after handshake complete");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 &&
+               ssl->options.serverState == NULL_STATE && type != server_hello) {
+        WOLFSSL_MSG("First server message not server hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls &&
+            type == server_hello_done &&
+            ssl->options.serverState < SERVER_HELLO_COMPLETE) {
+        WOLFSSL_MSG("Server hello done received before server hello in DTLS");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+               ssl->options.clientState == NULL_STATE && type != client_hello) {
+        WOLFSSL_MSG("First client message not client hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    /* above checks handshake state */
+    /* hello_request not hashed */
+    /* Also, skip hashing the client_hello message here for DTLS. It will be
+     * hashed later if the DTLS cookie is correct. */
+    if (type != hello_request &&
+            !(IsDtlsNotSctpMode(ssl) && type == client_hello)
+    #ifdef WOLFSSL_ASYNC_CRYPT
+            && ssl->error != WC_PENDING_E
+    #endif
+    #ifdef WOLFSSL_NONBLOCK_OCSP
+            && ssl->error != OCSP_WANT_READ
+    #endif
+    ) {
+        ret = HashInput(ssl, input + *inOutIdx, size);
+        if (ret != 0) return ret;
+    }
+
+#ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL){
+		ssl->cbmode = SSL_CB_MODE_READ;
+		ssl->cbtype = type;
+		ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+    }
+#endif
+
+    switch (type) {
+
+    case hello_request:
+        WOLFSSL_MSG("processing hello request");
+        ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz);
+        break;
+
+#ifndef NO_WOLFSSL_CLIENT
+    case hello_verify_request:
+        WOLFSSL_MSG("processing hello verify request");
+        ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size);
+        break;
+
+    case server_hello:
+        WOLFSSL_MSG("processing server hello");
+        ret = DoServerHello(ssl, input, inOutIdx, size);
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) ||
+                                               IsAtLeastTLSv1_3(ssl->version)) {
+            ssl->options.cacheMessages = 0;
+        }
+    #endif
+        break;
+
+#ifndef NO_CERTS
+    case certificate_request:
+        WOLFSSL_MSG("processing certificate request");
+        ret = DoCertificateRequest(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+    case server_key_exchange:
+        WOLFSSL_MSG("processing server key exchange");
+        ret = DoServerKeyExchange(ssl, input, inOutIdx, size);
+        break;
+
+#ifdef HAVE_SESSION_TICKET
+    case session_ticket:
+        WOLFSSL_MSG("processing session ticket");
+        ret = DoSessionTicket(ssl, input, inOutIdx, size);
+        break;
+#endif /* HAVE_SESSION_TICKET */
+#endif
+
+#ifndef NO_CERTS
+    case certificate:
+        WOLFSSL_MSG("processing certificate");
+        ret = DoCertificate(ssl, input, inOutIdx, size);
+        break;
+
+    case certificate_status:
+        WOLFSSL_MSG("processing certificate status");
+        ret = DoCertificateStatus(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+    case server_hello_done:
+        WOLFSSL_MSG("processing server hello done");
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHelloDone");
+        if (ssl->toInfoOn)
+            AddLateName("ServerHelloDone", &ssl->timeoutInfo);
+    #endif
+        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+        if (IsEncryptionOn(ssl, 0)) {
+            *inOutIdx += ssl->keys.padSz;
+        }
+        if (ssl->options.resuming) {
+            WOLFSSL_MSG("Not resuming as thought");
+            ssl->options.resuming = 0;
+        }
+        break;
+
+    case finished:
+        WOLFSSL_MSG("processing finished");
+        ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
+        break;
+
+#ifndef NO_WOLFSSL_SERVER
+    case client_hello:
+        WOLFSSL_MSG("processing client hello");
+        ret = DoClientHello(ssl, input, inOutIdx, size);
+    #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+        if (ssl->options.resuming || !ssl->options.verifyPeer || \
+                     !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) {
+            ssl->options.cacheMessages = 0;
+        }
+    #endif
+        break;
+
+    case client_key_exchange:
+        WOLFSSL_MSG("processing client key exchange");
+        ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
+        break;
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+    case certificate_verify:
+        WOLFSSL_MSG("processing certificate verify");
+        ret = DoCertificateVerify(ssl, input, inOutIdx, size);
+        break;
+#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+    default:
+        WOLFSSL_MSG("Unknown handshake message type");
+        ret = UNKNOWN_HANDSHAKE_TYPE;
+        break;
+    }
+    if (ret == 0 && expectedIdx != *inOutIdx) {
+        WOLFSSL_MSG("Extra data in handshake message");
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, decode_error);
+        ret = DECODE_E;
+    }
+
+#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
+    /* if async, offset index so this msg will be processed again */
+    if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
+        *inOutIdx -= HANDSHAKE_HEADER_SZ;
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            *inOutIdx -= DTLS_HANDSHAKE_EXTRA;
+        }
+    #endif
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
+
+    WOLFSSL_LEAVE("DoHandShakeMsgType()", ret);
+    return ret;
+}
+
+
+static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          word32 totalSz)
+{
+    int    ret = 0;
+    word32 inputLength;
+
+    WOLFSSL_ENTER("DoHandShakeMsg()");
+
+    if (ssl->arrays == NULL) {
+        byte   type;
+        word32 size;
+
+        if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        ssl->options.handShakeState = type;
+
+        return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+    }
+
+    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx;
+
+    /* If there is a pending fragmented handshake message,
+     * pending message size will be non-zero. */
+    if (ssl->arrays->pendingMsgSz == 0) {
+        byte   type;
+        word32 size;
+
+        if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        /* Cap the maximum size of a handshake message to something reasonable.
+         * By default is the maximum size of a certificate message assuming
+         * nine 2048-bit RSA certificates in the chain. */
+        if (size > MAX_HANDSHAKE_SZ) {
+            WOLFSSL_MSG("Handshake message too large");
+            return HANDSHAKE_SIZE_ERROR;
+        }
+
+        /* size is the size of the certificate message payload */
+        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
+            ssl->arrays->pendingMsgType = type;
+            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
+            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
+                                                     ssl->heap,
+                                                     DYNAMIC_TYPE_ARRAYS);
+            if (ssl->arrays->pendingMsg == NULL)
+                return MEMORY_E;
+            XMEMCPY(ssl->arrays->pendingMsg,
+                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
+                    inputLength);
+            ssl->arrays->pendingMsgOffset = inputLength;
+            *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
+            return 0;
+        }
+
+        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+    }
+    else {
+        if (inputLength + ssl->arrays->pendingMsgOffset
+                                                  > ssl->arrays->pendingMsgSz) {
+
+            return BUFFER_ERROR;
+        }
+
+        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
+                input + *inOutIdx, inputLength);
+        ssl->arrays->pendingMsgOffset += inputLength;
+        *inOutIdx += inputLength;
+
+        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
+        {
+            word32 idx = 0;
+            ret = DoHandShakeMsgType(ssl,
+                                     ssl->arrays->pendingMsg
+                                                          + HANDSHAKE_HEADER_SZ,
+                                     &idx, ssl->arrays->pendingMsgType,
+                                     ssl->arrays->pendingMsgSz
+                                                          - HANDSHAKE_HEADER_SZ,
+                                     ssl->arrays->pendingMsgSz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* setup to process fragment again */
+                ssl->arrays->pendingMsgOffset -= inputLength;
+                *inOutIdx -= inputLength;
+            }
+            else
+        #endif
+            {
+                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+                ssl->arrays->pendingMsg = NULL;
+                ssl->arrays->pendingMsgSz = 0;
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoHandShakeMsg()", ret);
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef WOLFSSL_DTLS
+
+static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl)
+{
+    word32* window;
+    word16 cur_hi, next_hi;
+    word32 cur_lo, next_lo, diff;
+    int curLT;
+    WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL;
+
+    if (!ssl->options.haveMcast)
+        peerSeq = ssl->keys.peerSeq;
+    else {
+#ifdef WOLFSSL_MULTICAST
+        WOLFSSL_DTLS_PEERSEQ* p;
+        int i;
+
+        for (i = 0, p = ssl->keys.peerSeq;
+             i < WOLFSSL_DTLS_PEERSEQ_SZ;
+             i++, p++) {
+
+            if (p->peerId == ssl->keys.curPeerId) {
+                peerSeq = p;
+                break;
+            }
+        }
+#endif
+    }
+
+    if (peerSeq == NULL) {
+        WOLFSSL_MSG("Could not find peer sequence");
+        return 0;
+    }
+
+    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
+        next_hi = peerSeq->nextSeq_hi;
+        next_lo = peerSeq->nextSeq_lo;
+        window = peerSeq->window;
+    }
+    else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) {
+        next_hi = peerSeq->prevSeq_hi;
+        next_lo = peerSeq->prevSeq_lo;
+        window = peerSeq->prevWindow;
+    }
+    else {
+        return 0;
+    }
+
+    cur_hi = ssl->keys.curSeq_hi;
+    cur_lo = ssl->keys.curSeq_lo;
+
+    /* If the difference between next and cur is > 2^32, way outside window. */
+    if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) {
+        WOLFSSL_MSG("Current record from way too far in the future.");
+        return 0;
+    }
+
+    if (cur_hi == next_hi) {
+        curLT = cur_lo < next_lo;
+        diff = curLT ? next_lo - cur_lo : cur_lo - next_lo;
+    }
+    else {
+        curLT = cur_hi < next_hi;
+        diff = curLT ? cur_lo - next_lo : next_lo - cur_lo;
+    }
+
+    /* Check to see that the next value is greater than the number of messages
+     * trackable in the window, and that the difference between the next
+     * expected sequence number and the received sequence number is inside the
+     * window. */
+    if ((next_hi || next_lo > DTLS_SEQ_BITS) &&
+        curLT && (diff > DTLS_SEQ_BITS)) {
+
+        WOLFSSL_MSG("Current record sequence number from the past.");
+        return 0;
+    }
+#ifndef WOLFSSL_DTLS_ALLOW_FUTURE
+    else if (!curLT && (diff > DTLS_SEQ_BITS)) {
+        WOLFSSL_MSG("Rejecting message too far into the future.");
+        return 0;
+    }
+#endif
+    else if (curLT) {
+        word32 idx = diff / DTLS_WORD_BITS;
+        word32 newDiff = diff % DTLS_WORD_BITS;
+
+        /* verify idx is valid for window array */
+        if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) {
+            WOLFSSL_MSG("Invalid DTLS windows index");
+            return 0;
+        }
+
+        if (window[idx] & (1 << (newDiff - 1))) {
+            WOLFSSL_MSG("Current record sequence number already received.");
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+                                         word32 second, word32 max)
+{
+    word32 newCur = 0;
+
+    if (cur < first)
+        newCur = first;
+    else if (cur < second)
+        newCur = second;
+    else if (cur < max)
+        newCur = max;
+
+    return newCur;
+}
+#endif /* WOLFSSL_MULTICAST */
+
+
+static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl)
+{
+    word32* window;
+    word32* next_lo;
+    word16* next_hi;
+    int curLT;
+    word32 cur_lo, diff;
+    word16 cur_hi;
+    WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
+
+    cur_hi = ssl->keys.curSeq_hi;
+    cur_lo = ssl->keys.curSeq_lo;
+
+#ifdef WOLFSSL_MULTICAST
+    if (ssl->options.haveMcast) {
+        WOLFSSL_DTLS_PEERSEQ* p;
+        int i;
+
+        peerSeq = NULL;
+        for (i = 0, p = ssl->keys.peerSeq;
+             i < WOLFSSL_DTLS_PEERSEQ_SZ;
+             i++, p++) {
+
+            if (p->peerId == ssl->keys.curPeerId) {
+                peerSeq = p;
+                break;
+            }
+        }
+
+        if (peerSeq == NULL) {
+            WOLFSSL_MSG("Couldn't find that peer ID to update window.");
+            return 0;
+        }
+
+        if (p->highwaterMark && cur_lo >= p->highwaterMark) {
+            int cbError = 0;
+
+            if (ssl->ctx->mcastHwCb)
+                cbError = ssl->ctx->mcastHwCb(p->peerId,
+                                              ssl->ctx->mcastMaxSeq,
+                                              cur_lo, ssl->mcastHwCbCtx);
+            if (cbError) {
+                WOLFSSL_MSG("Multicast highwater callback returned an error.");
+                return MCAST_HIGHWATER_CB_E;
+            }
+
+            p->highwaterMark = UpdateHighwaterMark(cur_lo,
+                                                   ssl->ctx->mcastFirstSeq,
+                                                   ssl->ctx->mcastSecondSeq,
+                                                   ssl->ctx->mcastMaxSeq);
+        }
+    }
+#endif
+
+    if (ssl->keys.curEpoch == peerSeq->nextEpoch) {
+        next_hi = &peerSeq->nextSeq_hi;
+        next_lo = &peerSeq->nextSeq_lo;
+        window = peerSeq->window;
+    }
+    else {
+        next_hi = &peerSeq->prevSeq_hi;
+        next_lo = &peerSeq->prevSeq_lo;
+        window = peerSeq->prevWindow;
+    }
+
+    if (cur_hi == *next_hi) {
+        curLT = cur_lo < *next_lo;
+        diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo;
+    }
+    else {
+        curLT = cur_hi < *next_hi;
+        diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo;
+    }
+
+    if (curLT) {
+        word32 idx = diff / DTLS_WORD_BITS;
+        word32 newDiff = diff % DTLS_WORD_BITS;
+
+        if (idx < WOLFSSL_DTLS_WINDOW_WORDS)
+            window[idx] |= (1 << (newDiff - 1));
+    }
+    else {
+        if (diff >= DTLS_SEQ_BITS)
+            XMEMSET(window, 0, DTLS_SEQ_SZ);
+        else {
+            word32 idx, newDiff, temp, i;
+            word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS];
+
+            temp = 0;
+            diff++;
+            idx = diff / DTLS_WORD_BITS;
+            newDiff = diff % DTLS_WORD_BITS;
+
+            XMEMCPY(oldWindow, window, sizeof(oldWindow));
+
+            for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) {
+                if (i < idx)
+                    window[i] = 0;
+                else {
+                    temp |= (oldWindow[i-idx] << newDiff);
+                    window[i] = temp;
+                    temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff);
+                }
+            }
+        }
+        window[0] |= 1;
+        *next_lo = cur_lo + 1;
+        if (*next_lo < cur_lo)
+            (*next_hi)++;
+    }
+
+    return 1;
+}
+
+
+static int DtlsMsgDrain(WOLFSSL* ssl)
+{
+    DtlsMsg* item = ssl->dtls_rx_msg_list;
+    int ret = 0;
+
+    /* While there is an item in the store list, and it is the expected
+     * message, and it is complete, and there hasn't been an error in the
+     * last messge... */
+    while (item != NULL &&
+            ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
+            item->fragSz == item->sz &&
+            ret == 0) {
+        word32 idx = 0;
+        ssl->keys.dtls_expected_peer_handshake_number++;
+        ret = DoHandShakeMsgType(ssl, item->msg,
+                                 &idx, item->type, item->sz, item->sz);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        if (ret == WC_PENDING_E) {
+            ssl->keys.dtls_expected_peer_handshake_number--;
+            break;
+        }
+    #endif
+        ssl->dtls_rx_msg_list = item->next;
+        DtlsMsgDelete(item, ssl->heap);
+        item = ssl->dtls_rx_msg_list;
+        ssl->dtls_rx_msg_list_sz--;
+    }
+
+    return ret;
+}
+
+
+static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                          word32 totalSz)
+{
+    byte type;
+    word32 size;
+    word32 fragOffset, fragSz;
+    int ret = 0;
+
+    WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
+
+    /* process any pending DTLS messages - this flow can happen with async */
+    if (ssl->dtls_rx_msg_list != NULL) {
+        ret = DtlsMsgDrain(ssl);
+        if (ret != 0)
+            return ret;
+
+        /* if done processing fragment exit with success */
+        if (totalSz == *inOutIdx)
+            return ret;
+    }
+
+    /* parse header */
+    if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
+                               &size, &fragOffset, &fragSz, totalSz) != 0)
+        return PARSE_ERROR;
+
+    /* check that we have complete fragment */
+    if (*inOutIdx + fragSz > totalSz)
+        return INCOMPLETE_DATA;
+
+    /* Check the handshake sequence number first. If out of order,
+     * add the current message to the list. If the message is in order,
+     * but it is a fragment, add the current message to the list, then
+     * check the head of the list to see if it is complete, if so, pop
+     * it out as the current message. If the message is complete and in
+     * order, process it. Check the head of the list to see if it is in
+     * order, if so, process it. (Repeat until list exhausted.) If the
+     * head is out of order, return for more processing.
+     */
+    if (ssl->keys.dtls_peer_handshake_number >
+                                ssl->keys.dtls_expected_peer_handshake_number) {
+        /* Current message is out of order. It will get stored in the list.
+         * Storing also takes care of defragmentation. If the messages is a
+         * client hello, we need to process this out of order; the server
+         * is not supposed to keep state, but the second client hello will
+         * have a different handshake sequence number than is expected, and
+         * the server shouldn't be expecting any particular handshake sequence
+         * number. (If the cookie changes multiple times in quick succession,
+         * the client could be sending multiple new client hello messages
+         * with newer and newer cookies.) */
+        if (type != client_hello) {
+            if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+                DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+                             input + *inOutIdx, size, type,
+                             fragOffset, fragSz, ssl->heap);
+            }
+            *inOutIdx += fragSz;
+            ret = 0;
+        }
+        else {
+            ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+            if (ret == 0) {
+                ssl->keys.dtls_expected_peer_handshake_number =
+                    ssl->keys.dtls_peer_handshake_number + 1;
+            }
+        }
+    }
+    else if (ssl->keys.dtls_peer_handshake_number <
+                                ssl->keys.dtls_expected_peer_handshake_number) {
+        /* Already saw this message and processed it. It can be ignored. */
+        *inOutIdx += fragSz;
+        if(type == finished ) {
+            if (*inOutIdx + ssl->keys.padSz > totalSz) {
+                return BUFFER_E;
+            }
+            *inOutIdx += ssl->keys.padSz;
+        }
+        if (IsDtlsNotSctpMode(ssl) &&
+            VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) {
+
+            ret = DtlsMsgPoolSend(ssl, 0);
+        }
+    }
+    else if (fragSz < size) {
+        /* Since this branch is in order, but fragmented, dtls_rx_msg_list will
+         * be pointing to the message with this fragment in it. Check it to see
+         * if it is completed. */
+        if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
+            DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number,
+                         input + *inOutIdx, size, type,
+                         fragOffset, fragSz, ssl->heap);
+        }
+        *inOutIdx += fragSz;
+        ret = 0;
+        if (ssl->dtls_rx_msg_list != NULL &&
+            ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz)
+            ret = DtlsMsgDrain(ssl);
+    }
+    else {
+        /* This branch is in order next, and a complete message. */
+        ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
+        if (ret == 0) {
+            if (type != client_hello || !IsDtlsNotSctpMode(ssl))
+                ssl->keys.dtls_expected_peer_handshake_number++;
+            if (ssl->dtls_rx_msg_list != NULL) {
+                ret = DtlsMsgDrain(ssl);
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
+    return ret;
+}
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef HAVE_AEAD
+static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
+{
+    int i;
+    for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) {
+        if (++ssl->keys.aead_exp_IV[i]) return;
+    }
+}
+
+
+#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
+/* Used for the older version of creating AEAD tags with Poly1305 */
+static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
+                       byte* cipher, word16 sz, byte* tag)
+{
+    int ret       = 0;
+    int msglen    = (sz - ssl->specs.aead_mac_size);
+    word32 keySz  = 32;
+    byte padding[8]; /* used to temporarily store lengths */
+
+#ifdef CHACHA_AEAD_TEST
+      printf("Using old version of poly1305 input.\n");
+#endif
+
+    if (msglen < 0)
+        return INPUT_CASE_ERROR;
+
+    if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
+        return ret;
+
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
+                   AEAD_AUTH_DATA_SZ)) != 0)
+        return ret;
+
+    /* length of additional input plus padding */
+    XMEMSET(padding, 0, sizeof(padding));
+    padding[0] = AEAD_AUTH_DATA_SZ;
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding,
+                    sizeof(padding))) != 0)
+        return ret;
+
+
+    /* add cipher info and then its length */
+    XMEMSET(padding, 0, sizeof(padding));
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
+        return ret;
+
+    /* 32 bit size of cipher to 64 bit endian */
+    padding[0] =  msglen        & 0xff;
+    padding[1] = (msglen >>  8) & 0xff;
+    padding[2] = (msglen >> 16) & 0xff;
+    padding[3] = (msglen >> 24) & 0xff;
+    if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
+        != 0)
+        return ret;
+
+    /* generate tag */
+    if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
+        return ret;
+
+    return ret;
+}
+
+
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implmentation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automaticlly depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparision to the more recent RFC.
+ *
+ * ssl   WOLFSSL structure to get cipher and TLS state from
+ * out   output buffer to hold encrypted data
+ * input data to encrypt
+ * sz    size of input
+ *
+ * Return 0 on success negative values in error case
+ */
+static int  ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
+                              word16 sz)
+{
+    const byte* additionalSrc = input - RECORD_HEADER_SZ;
+    int ret       = 0;
+    word32 msgLen = (sz - ssl->specs.aead_mac_size);
+    byte tag[POLY1305_AUTH_SZ];
+    byte add[AEAD_AUTH_DATA_SZ];
+    byte nonce[CHACHA20_NONCE_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
+    #ifdef CHACHA_AEAD_TEST
+        int i;
+    #endif
+
+    XMEMSET(tag,   0, sizeof(tag));
+    XMEMSET(nonce, 0, sizeof(nonce));
+    XMEMSET(poly,  0, sizeof(poly));
+    XMEMSET(add,   0, sizeof(add));
+
+    /* opaque SEQ number stored for AD */
+    WriteSEQ(ssl, CUR_ORDER, add);
+
+    if (ssl->options.oldPoly != 0) {
+        /* get nonce. SEQ should not be incremented again here */
+        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+    }
+
+    /* Store the type, version. Unfortunately, they are in
+     * the input buffer ahead of the plaintext. */
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+        }
+    #endif
+
+    /* add TLS message size to additional data */
+    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
+
+    XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
+
+    #ifdef CHACHA_AEAD_TEST
+        printf("Encrypt Additional : ");
+        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+            printf("%02x", add[i]);
+        }
+        printf("\n\n");
+        printf("input before encryption :\n");
+        for (i = 0; i < sz; i++) {
+            printf("%02x", input[i]);
+            if ((i + 1) % 16 == 0)
+                printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    if (ssl->options.oldPoly == 0) {
+        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+         * record sequence number XORed with client_write_IV/server_write_IV */
+        XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
+        nonce[4]  ^= add[0];
+        nonce[5]  ^= add[1];
+        nonce[6]  ^= add[2];
+        nonce[7]  ^= add[3];
+        nonce[8]  ^= add[4];
+        nonce[9]  ^= add[5];
+        nonce[10] ^= add[6];
+        nonce[11] ^= add[7];
+    }
+
+    /* set the nonce for chacha and get poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
+    /* create Poly1305 key using chacha20 keystream */
+    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly,
+                                                      poly, sizeof(poly))) != 0)
+        return ret;
+
+    /* encrypt the plain text */
+    if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out,
+                                                         input, msgLen)) != 0) {
+        ForceZero(poly, sizeof(poly));
+        return ret;
+    }
+
+    /* get the poly1305 tag using either old padding scheme or more recent */
+    if (ssl->options.oldPoly != 0) {
+        if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
+                                                         poly, sz, tag)) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    else {
+        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+                                                          sizeof(poly))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+                            sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+
+    /* append tag to ciphertext */
+    XMEMCPY(out + msgLen, tag, sizeof(tag));
+
+    AeadIncrementExpIV(ssl);
+
+    #ifdef CHACHA_AEAD_TEST
+       printf("mac tag :\n");
+        for (i = 0; i < 16; i++) {
+           printf("%02x", tag[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+       printf("\n\noutput after encrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", out[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    return ret;
+}
+
+
+/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set
+ * the implmentation follows an older draft for creating the nonce and MAC.
+ * The flag oldPoly gets set automaticlly depending on what cipher suite was
+ * negotiated in the handshake. This is able to be done because the IDs for the
+ * cipher suites was updated in RFC7905 giving unique values for the older
+ * draft in comparision to the more recent RFC.
+ *
+ * ssl   WOLFSSL structure to get cipher and TLS state from
+ * plain output buffer to hold decrypted data
+ * input data to decrypt
+ * sz    size of input
+ *
+ * Return 0 on success negative values in error case
+ */
+static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    byte add[AEAD_AUTH_DATA_SZ];
+    byte nonce[CHACHA20_NONCE_SZ];
+    byte tag[POLY1305_AUTH_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
+    int ret    = 0;
+    int msgLen = (sz - ssl->specs.aead_mac_size);
+
+    #ifdef CHACHA_AEAD_TEST
+       int i;
+       printf("input before decrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", input[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    XMEMSET(tag,   0, sizeof(tag));
+    XMEMSET(poly,  0, sizeof(poly));
+    XMEMSET(nonce, 0, sizeof(nonce));
+    XMEMSET(add,   0, sizeof(add));
+
+    /* sequence number field is 64-bits */
+    WriteSEQ(ssl, PEER_ORDER, add);
+
+    if (ssl->options.oldPoly != 0) {
+        /* get nonce, SEQ should not be incremented again here */
+        XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+    }
+
+    /* get AD info */
+    /* Store the type, version. */
+    add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+    add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+    add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+    /* add TLS message size to additional data */
+    add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
+    add[AEAD_AUTH_DATA_SZ - 1] =  msgLen       & 0xff;
+
+    #ifdef CHACHA_AEAD_TEST
+        printf("Decrypt Additional : ");
+        for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
+            printf("%02x", add[i]);
+        }
+        printf("\n\n");
+    #endif
+
+    if (ssl->options.oldPoly == 0) {
+        /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
+         * record sequence number XORed with client_write_IV/server_write_IV */
+        XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
+        nonce[4]  ^= add[0];
+        nonce[5]  ^= add[1];
+        nonce[6]  ^= add[2];
+        nonce[7]  ^= add[3];
+        nonce[8]  ^= add[4];
+        nonce[9]  ^= add[5];
+        nonce[10] ^= add[6];
+        nonce[11] ^= add[7];
+    }
+
+    /* set nonce and get poly1305 key */
+    if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) {
+        ForceZero(nonce, CHACHA20_NONCE_SZ);
+        return ret;
+    }
+
+    ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */
+    /* use chacha20 keystream to get poly1305 key for tag */
+    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly,
+                                                      poly, sizeof(poly))) != 0)
+        return ret;
+
+    /* get the tag using Poly1305 */
+    if (ssl->options.oldPoly != 0) {
+        if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    else {
+        if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
+                                                          sizeof(poly))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+        if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
+                   sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) {
+            ForceZero(poly, sizeof(poly));
+            return ret;
+        }
+    }
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+
+    /* check tag sent along with packet */
+    if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) {
+        WOLFSSL_MSG("MAC did not match");
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, bad_record_mac);
+        return VERIFY_MAC_ERROR;
+    }
+
+    /* if the tag was good decrypt message */
+    if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
+                                                           input, msgLen)) != 0)
+        return ret;
+
+    #ifdef CHACHA_AEAD_TEST
+       printf("plain after decrypt :\n");
+        for (i = 0; i < sz; i++) {
+           printf("%02x", plain[i]);
+           if ((i + 1) % 16 == 0)
+               printf("\n");
+        }
+        printf("\n");
+    #endif
+
+    return ret;
+}
+#endif /* HAVE_CHACHA && HAVE_POLY1305 */
+#endif /* HAVE_AEAD */
+
+
+static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
+    word16 sz, int asyncOkay)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = NULL;
+    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
+#else
+    (void)asyncOkay;
+#endif
+
+    (void)out;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm) {
+    #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->encrypt.arc4, out, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.des3->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #ifdef BUILD_AES
+        case wolfssl_aes:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.aes->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+        case wolfssl_aes_gcm:
+        case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */
+        {
+            wc_AesAuthEncryptFunc aes_auth_fn;
+            const byte* additionalSrc;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            asyncDev = &ssl->encrypt.aes->asyncDev;
+            ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+            if (ret != 0)
+                break;
+        #endif
+
+        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+                            ? wc_AesGcmEncrypt : wc_AesCcmEncrypt;
+        #elif defined(BUILD_AESGCM)
+            aes_auth_fn = wc_AesGcmEncrypt;
+        #else
+            aes_auth_fn = wc_AesCcmEncrypt;
+        #endif
+            additionalSrc = input - 5;
+
+            XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
+
+            /* sequence number field is 64-bits */
+            WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
+
+            /* Store the type, version. Unfortunately, they are in
+             * the input buffer ahead of the plaintext. */
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+            XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
+                                                        additionalSrc, 3);
+
+            /* Store the length of the plain text minus the explicit
+             * IV length minus the authentication tag size. */
+            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                                ssl->encrypt.additional + AEAD_LEN_OFFSET);
+            XMEMCPY(ssl->encrypt.nonce,
+                                ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ);
+            XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ,
+                                ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
+            ret = aes_auth_fn(ssl->encrypt.aes,
+                    out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
+                    sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                    ssl->encrypt.nonce, AESGCM_NONCE_SZ,
+                    out + sz - ssl->specs.aead_mac_size,
+                    ssl->specs.aead_mac_size,
+                    ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E && asyncOkay) {
+                ret = wolfSSL_AsyncPush(ssl, asyncDev);
+            }
+        #endif
+        }
+        break;
+    #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+    #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
+            break;
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        case wolfssl_chacha:
+            ret = ChachaAEADEncrypt(ssl, out, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_NULL_CIPHER
+        case wolfssl_cipher_null:
+            if (input != out) {
+                XMEMMOVE(out, input, sz);
+            }
+            break;
+    #endif
+
+    #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz);
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("wolfSSL Encrypt programming error");
+            ret = ENCRYPT_ERROR;
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* if async is not okay, then block */
+    if (ret == WC_PENDING_E && !asyncOkay) {
+        ret = wc_AsyncWait(ret, asyncDev, event_flags);
+    }
+#endif
+
+    return ret;
+}
+
+static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
+    int asyncOkay)
+{
+    int ret = 0;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->error == WC_PENDING_E) {
+        ssl->error = 0; /* clear async */
+    }
+#endif
+
+    switch (ssl->encrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+            if (ssl->encrypt.setup == 0) {
+                WOLFSSL_MSG("Encrypt ciphers not setup");
+                return ENCRYPT_ERROR;
+            }
+
+        #ifdef HAVE_FUZZER
+            if (ssl->fuzzerCb)
+                ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx);
+        #endif
+
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM memory is allocated */
+            /* free for these happens in FreeCiphers */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                /* make sure auth iv and auth are allocated */
+                if (ssl->encrypt.additional == NULL)
+                    ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->encrypt.nonce == NULL)
+                    ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->encrypt.additional == NULL ||
+                         ssl->encrypt.nonce == NULL) {
+                    return MEMORY_E;
+                }
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+            /* Advance state and proceed */
+            ssl->encrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            ret = EncryptDo(ssl, out, input, sz, asyncOkay);
+
+            /* Advance state */
+            ssl->encrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, then leave and return will resume below */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+            {
+                /* finalize authentication cipher */
+                AeadIncrementExpIV(ssl);
+
+                if (ssl->encrypt.nonce)
+                    ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ);
+
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+
+    return ret;
+}
+
+static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    int ret = 0;
+
+    (void)plain;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm)
+    {
+    #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #ifdef BUILD_AES
+        case wolfssl_aes:
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+
+            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+            }
+        #endif
+            break;
+    #endif
+
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+        case wolfssl_aes_gcm:
+        case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
+        {
+            wc_AesAuthDecryptFunc aes_auth_fn;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* initialize event */
+            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                WC_ASYNC_FLAG_CALL_AGAIN);
+            if (ret != 0)
+                break;
+        #endif
+
+        #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
+            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
+                            ? wc_AesGcmDecrypt : wc_AesCcmDecrypt;
+        #elif defined(BUILD_AESGCM)
+            aes_auth_fn = wc_AesGcmDecrypt;
+        #else
+            aes_auth_fn = wc_AesCcmDecrypt;
+        #endif
+
+            XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
+
+            /* sequence number field is 64-bits */
+            WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
+
+            ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
+            ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
+            ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
+
+            c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                                    ssl->decrypt.additional + AEAD_LEN_OFFSET);
+            XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
+                                                            AESGCM_IMP_IV_SZ);
+            XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input,
+                                                            AESGCM_EXP_IV_SZ);
+            if ((ret = aes_auth_fn(ssl->decrypt.aes,
+                        plain + AESGCM_EXP_IV_SZ,
+                        input + AESGCM_EXP_IV_SZ,
+                           sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                        ssl->decrypt.nonce, AESGCM_NONCE_SZ,
+                        input + sz - ssl->specs.aead_mac_size,
+                        ssl->specs.aead_mac_size,
+                        ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E) {
+                    ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
+                }
+            #endif
+            }
+        }
+        break;
+    #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+    #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
+            break;
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        case wolfssl_chacha:
+            ret = ChachaAEADDecrypt(ssl, plain, input, sz);
+            break;
+    #endif
+
+    #ifdef HAVE_NULL_CIPHER
+        case wolfssl_cipher_null:
+            if (input != plain) {
+                XMEMMOVE(plain, input, sz);
+            }
+            break;
+    #endif
+
+    #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz);
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("wolfSSL Decrypt programming error");
+            ret = DECRYPT_ERROR;
+    }
+
+    return ret;
+}
+
+static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input,
+                           word16 sz)
+{
+    int ret = 0;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
+    if (ret != WC_NOT_PENDING_E) {
+        /* check for still pending */
+        if (ret == WC_PENDING_E)
+            return ret;
+
+        ssl->error = 0; /* clear async */
+
+        /* let failures through so CIPHER_STATE_END logic is run */
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->decrypt.state = CIPHER_STATE_BEGIN;
+    }
+
+    switch (ssl->decrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+            if (ssl->decrypt.setup == 0) {
+                WOLFSSL_MSG("Decrypt ciphers not setup");
+                return DECRYPT_ERROR;
+            }
+
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM memory is allocated */
+            /* free for these happens in FreeCiphers */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                /* make sure auth iv and auth are allocated */
+                if (ssl->decrypt.additional == NULL)
+                    ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->decrypt.nonce == NULL)
+                    ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
+                                                   ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+                if (ssl->decrypt.additional == NULL ||
+                         ssl->decrypt.nonce == NULL) {
+                    return MEMORY_E;
+                }
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+
+            /* Advance state and proceed */
+            ssl->decrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+        case CIPHER_STATE_DO:
+        {
+            ret = DecryptDo(ssl, plain, input, sz);
+
+            /* Advance state */
+            ssl->decrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, leave and return below */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+        case CIPHER_STATE_END:
+        {
+        #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
+            /* make sure AES GCM/CCM nonce is cleared */
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
+                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
+                if (ssl->decrypt.nonce)
+                    ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ);
+
+                if (ret < 0)
+                    ret = VERIFY_MAC_ERROR;
+            }
+        #endif /* BUILD_AESGCM || HAVE_AESCCM */
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->decrypt.state = CIPHER_STATE_BEGIN;
+
+    /* handle mac error case */
+    if (ret == VERIFY_MAC_ERROR) {
+        if (!ssl->options.dtls)
+            SendAlert(ssl, alert_fatal, bad_record_mac);
+
+        #ifdef WOLFSSL_DTLS_DROP_STATS
+            ssl->macDropCount++;
+        #endif /* WOLFSSL_DTLS_DROP_STATS */
+    }
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+/* Check conditions for a cipher to have an explicit IV.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 1 if the cipher in use has an explicit IV and 0 otherwise.
+ */
+static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl)
+{
+#ifdef WOLFSSL_TLS13
+    if (ssl->options.tls1_3)
+        return 0;
+#endif
+    return (ssl->specs.cipher_type == aead) &&
+            (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha);
+}
+
+/* check cipher text size for sanity */
+static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
+{
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                           : ssl->specs.hash_size;
+#else
+    word32 minLength = ssl->specs.hash_size; /* covers stream */
+#endif
+
+    if (ssl->specs.cipher_type == block) {
+        if (encryptSz % ssl->specs.block_size) {
+            WOLFSSL_MSG("Block ciphertext not block size");
+            return SANITY_CIPHER_E;
+        }
+
+        minLength++;  /* pad byte */
+
+        if (ssl->specs.block_size > minLength)
+            minLength = ssl->specs.block_size;
+
+        if (ssl->options.tls1_1)
+            minLength += ssl->specs.block_size;  /* explicit IV */
+    }
+    else if (ssl->specs.cipher_type == aead) {
+        minLength = ssl->specs.aead_mac_size;    /* authTag size */
+        if (CipherHasExpIV(ssl))
+            minLength += AESGCM_EXP_IV_SZ;       /* explicit IV  */
+    }
+
+    if (encryptSz < minLength) {
+        WOLFSSL_MSG("Ciphertext not minimum size");
+        return SANITY_CIPHER_E;
+    }
+
+    return 0;
+}
+
+
+/* check all length bytes for the pad value, return 0 on success */
+static int PadCheck(const byte* a, byte pad, int length)
+{
+    int i;
+    int compareSum = 0;
+
+    for (i = 0; i < length; i++) {
+        compareSum |= a[i] ^ pad;
+    }
+
+    return compareSum;
+}
+
+
+/* Mask the padding bytes with the expected values.
+ * Constant time implementation - does maximum pad size possible.
+ *
+ * data   Message data.
+ * sz     Size of the message including MAC and padding and padding length.
+ * macSz  Size of the MAC.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskPadding(const byte* data, int sz, int macSz)
+{
+    int i;
+    int checkSz = sz - 1;
+    byte paddingSz = data[sz - 1];
+    byte mask;
+    byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
+
+    if (checkSz > TLS_MAX_PAD_SZ)
+        checkSz = TLS_MAX_PAD_SZ;
+
+    for (i = 0; i < checkSz; i++) {
+        mask = ctMaskLTE(i, paddingSz);
+        good |= mask & (data[sz - 1 - i] ^ paddingSz);
+    }
+
+    return good;
+}
+
+/* Mask the MAC in the message with the MAC calculated.
+ * Constant time implementation - starts looking for MAC where maximum padding
+ * size has it.
+ *
+ * data    Message data.
+ * sz      Size of the message including MAC and padding and padding length.
+ * macSz   Size of the MAC data.
+ * expMac  Expected MAC value.
+ * returns 0 on success, otherwise failure.
+ */
+static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
+{
+    int i, j;
+    unsigned char mac[WC_MAX_DIGEST_SIZE];
+    int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
+    int macEnd = sz - 1 - data[sz - 1];
+    int macStart = macEnd - macSz;
+    int r = 0;
+    unsigned char started, notEnded;
+    unsigned char good = 0;
+
+    if (scanStart < 0)
+        scanStart = 0;
+
+    /* Div on Intel has different speeds depending on value.
+     * Use a bitwise AND or mod a specific value (converted to mul). */
+    if ((macSz & (macSz - 1)) == 0)
+        r = (macSz - (scanStart - macStart)) & (macSz - 1);
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE)
+        r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
+#endif
+
+    XMEMSET(mac, 0, macSz);
+    for (i = scanStart; i < sz; i += macSz) {
+        for (j = 0; j < macSz && j + i < sz; j++) {
+            started = ctMaskGTE(i + j, macStart);
+            notEnded = ctMaskLT(i + j, macEnd);
+            mac[j] |= started & notEnded & data[i + j];
+        }
+    }
+
+    if ((macSz & (macSz - 1)) == 0) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) & (macSz - 1)];
+    }
+#ifndef NO_SHA
+    else if (macSz == WC_SHA_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE];
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (macSz == WC_SHA384_DIGEST_SIZE) {
+        for (i = 0; i < macSz; i++)
+            good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE];
+    }
+#endif
+
+    return good;
+}
+
+/* timing resistant pad/verify check, return 0 on success */
+int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
+                    int pLen, int content)
+{
+    byte verify[WC_MAX_DIGEST_SIZE];
+    byte good;
+    int  ret = 0;
+
+    good = MaskPadding(input, pLen, macSz);
+    /* 4th argument has potential to underflow, ssl->hmac function should
+     * either increment the size by (macSz + padLen + 1) before use or check on
+     * the size to make sure is valid. */
+    ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
+                                                                    content, 1);
+    good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
+
+    /* Non-zero on failure. */
+    good = (byte)~(word32)good;
+    good &= good >> 4;
+    good &= good >> 2;
+    good &= good >> 1;
+    /* Make ret negative on masking failure. */
+    ret -= 1 - good;
+
+    /* Treat any faulure as verify MAC error. */
+    if (ret != 0)
+        ret = VERIFY_MAC_ERROR;
+
+    return ret;
+}
+
+
+int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
+{
+    word32 msgSz   = ssl->keys.encryptSz;
+    word32 idx     = *inOutIdx;
+    int    dataSz;
+    int    ivExtra = 0;
+    byte*  rawData = input + idx;  /* keep current  for hmac */
+#ifdef HAVE_LIBZ
+    byte   decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+    }
+    else
+#endif
+    if (ssl->options.handShakeDone == 0) {
+        WOLFSSL_MSG("Received App data before a handshake completed");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->specs.cipher_type == block) {
+        if (ssl->options.tls1_1)
+            ivExtra = ssl->specs.block_size;
+    }
+    else if (ssl->specs.cipher_type == aead) {
+        if (CipherHasExpIV(ssl))
+            ivExtra = AESGCM_EXP_IV_SZ;
+    }
+
+    dataSz = msgSz - ivExtra - ssl->keys.padSz;
+    if (dataSz < 0) {
+        WOLFSSL_MSG("App data buffer error, malicious input?");
+        return BUFFER_ERROR;
+    }
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) {
+            SendAlert(ssl, alert_fatal, unexpected_message);
+            return WOLFSSL_FATAL_ERROR;
+        }
+        ssl->earlyDataSz += dataSz;
+    }
+#endif
+
+    /* read data */
+    if (dataSz) {
+        int rawSz = dataSz;       /* keep raw size for idx adjustment */
+
+#ifdef HAVE_LIBZ
+        if (ssl->options.usingCompression) {
+            dataSz = myDeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
+            if (dataSz < 0) return dataSz;
+        }
+#endif
+        idx += rawSz;
+
+        ssl->buffers.clearOutputBuffer.buffer = rawData;
+        ssl->buffers.clearOutputBuffer.length = dataSz;
+    }
+
+    idx += ssl->keys.padSz;
+
+#ifdef HAVE_LIBZ
+    /* decompress could be bigger, overwrite after verify */
+    if (ssl->options.usingCompression)
+        XMEMMOVE(rawData, decomp, dataSz);
+#endif
+
+    *inOutIdx = idx;
+    return 0;
+}
+
+
+/* process alert, return level */
+static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
+                   word32 totalSz)
+{
+    byte level;
+    byte code;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Alert");
+        if (ssl->toInfoOn)
+            /* add record header back on to info + alert bytes level/code */
+            AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx -
+                          RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE,
+                          READ_PROTO, ssl->heap);
+    #endif
+
+    if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) {
+        WOLFSSL_MSG("Alert count exceeded");
+        return ALERT_COUNT_E;
+    }
+
+    /* make sure can read the message */
+    if (*inOutIdx + ALERT_SIZE > totalSz)
+        return BUFFER_E;
+
+    level = input[(*inOutIdx)++];
+    code  = input[(*inOutIdx)++];
+    ssl->alert_history.last_rx.code = code;
+    ssl->alert_history.last_rx.level = level;
+    *type = code;
+    if (level == alert_fatal) {
+        ssl->options.isClosed = 1;  /* Don't send close_notify */
+    }
+
+    WOLFSSL_MSG("Got alert");
+    if (*type == close_notify) {
+        WOLFSSL_MSG("\tclose notify");
+        ssl->options.closeNotify = 1;
+    }
+#ifdef WOLFSSL_TLS13
+    if (*type == decode_error) {
+        WOLFSSL_MSG("    decode error");
+    }
+    if (*type == illegal_parameter) {
+        WOLFSSL_MSG("    illegal parameter");
+    }
+#endif
+    WOLFSSL_ERROR(*type);
+    if (IsEncryptionOn(ssl, 0)) {
+        if (*inOutIdx + ssl->keys.padSz > totalSz)
+            return BUFFER_E;
+        *inOutIdx += ssl->keys.padSz;
+    }
+
+    return level;
+}
+
+static int GetInputData(WOLFSSL *ssl, word32 size)
+{
+    int in;
+    int inSz;
+    int maxLength;
+    int usedLength;
+    int dtlsExtra = 0;
+
+
+    /* check max input length */
+    usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
+    maxLength  = ssl->buffers.inputBuffer.bufferSize - usedLength;
+    inSz       = (int)(size - usedLength);      /* from last partial read */
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        if (size < ssl->dtls_expected_rx)
+            dtlsExtra = (int)(ssl->dtls_expected_rx - size);
+        inSz = ssl->dtls_expected_rx;
+    }
+#endif
+
+    /* check that no lengths or size values are negative */
+    if (usedLength < 0 || maxLength < 0 || inSz <= 0) {
+        return BUFFER_ERROR;
+    }
+
+    if (inSz > maxLength) {
+        if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0)
+            return MEMORY_E;
+    }
+
+    /* Put buffer data at start if not there */
+    if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
+        XMEMMOVE(ssl->buffers.inputBuffer.buffer,
+                ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+                usedLength);
+
+    /* remove processed data */
+    ssl->buffers.inputBuffer.idx    = 0;
+    ssl->buffers.inputBuffer.length = usedLength;
+
+    /* read data from network */
+    do {
+        in = wolfSSLReceive(ssl,
+                     ssl->buffers.inputBuffer.buffer +
+                     ssl->buffers.inputBuffer.length,
+                     inSz);
+        if (in == -1)
+            return SOCKET_ERROR_E;
+
+        if (in == WANT_READ)
+            return WANT_READ;
+
+        if (in > inSz)
+            return RECV_OVERFLOW_E;
+
+        ssl->buffers.inputBuffer.length += in;
+        inSz -= in;
+
+    } while (ssl->buffers.inputBuffer.length < size);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    if (ssl->buffers.inputBuffer.idx == 0) {
+        WOLFSSL_MSG("Data received");
+        WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer,
+                       ssl->buffers.inputBuffer.length);
+    }
+#endif
+
+    return 0;
+}
+
+
+static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
+                            int content, word32* padSz)
+{
+#ifndef WOLFSSL_NO_TLS12
+    int    ivExtra = 0;
+    int    ret;
+    word32 pad     = 0;
+    word32 padByte = 0;
+#ifdef HAVE_TRUNCATED_HMAC
+    word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
+                                          : ssl->specs.hash_size;
+#else
+    word32 digestSz = ssl->specs.hash_size;
+#endif
+    byte   verify[WC_MAX_DIGEST_SIZE];
+
+
+    if (ssl->specs.cipher_type == block) {
+        if (ssl->options.tls1_1)
+            ivExtra = ssl->specs.block_size;
+        pad = *(input + msgSz - ivExtra - 1);
+        padByte = 1;
+
+        if (ssl->options.tls) {
+            ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
+                                  content);
+            if (ret != 0)
+                return ret;
+        }
+        else {  /* sslv3, some implementations have bad padding, but don't
+                 * allow bad read */
+            int  badPadLen = 0;
+            byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
+            byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
+
+            (void)dmy;
+
+            if (pad > (msgSz - digestSz - 1)) {
+                WOLFSSL_MSG("Plain Len not long enough for pad/mac");
+                pad       = 0;  /* no bad read */
+                badPadLen = 1;
+            }
+            PadCheck(dummy, (byte)pad, MAX_PAD_SIZE);  /* timing only */
+            ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
+                                                                    content, 1);
+            if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
+                                digestSz) != 0)
+                return VERIFY_MAC_ERROR;
+            if (ret != 0 || badPadLen)
+                return VERIFY_MAC_ERROR;
+        }
+    }
+    else if (ssl->specs.cipher_type == stream) {
+        ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
+        if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
+            return VERIFY_MAC_ERROR;
+        }
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+    }
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+    if (ssl->specs.cipher_type == aead) {
+        *padSz = ssl->specs.aead_mac_size;
+    }
+#ifndef WOLFSSL_NO_TLS12
+    else {
+        *padSz = digestSz + pad + padByte;
+    }
+#endif /* WOLFSSL_NO_TLS12 */
+
+    (void)input;
+    (void)msgSz;
+    (void)content;
+
+    return 0;
+}
+
+
+/* process input requests, return 0 is done, 1 is call again to complete, and
+   negative number is error */
+int ProcessReply(WOLFSSL* ssl)
+{
+    int    ret = 0, type, readSz;
+    int    atomicUser = 0;
+    word32 startIdx = 0;
+#if defined(WOLFSSL_DTLS)
+    int    used;
+#endif
+
+#ifdef ATOMIC_USER
+    if (ssl->ctx->DecryptVerifyCb)
+        atomicUser = 1;
+#endif
+
+    if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        && ssl->error != WC_PENDING_E
+    #endif
+    #ifdef WOLFSSL_NONBLOCK_OCSP
+        && ssl->error != OCSP_WANT_READ
+    #endif
+    ) {
+        WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
+        return ssl->error;
+    }
+
+    for (;;) {
+        switch (ssl->options.processReply) {
+
+        /* in the WOLFSSL_SERVER case, get the first byte for detecting
+         * old client hello */
+        case doProcessInit:
+
+            readSz = RECORD_HEADER_SZ;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                readSz = DTLS_RECORD_HEADER_SZ;
+        #endif
+
+            /* get header or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, readSz)) < 0)
+                    return ret;
+            } else {
+            #ifdef WOLFSSL_DTLS
+                /* read ahead may already have header */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < readSz) {
+                    if ((ret = GetInputData(ssl, readSz)) < 0)
+                        return ret;
+                }
+            #endif
+            }
+
+#ifdef OLD_HELLO_ALLOWED
+
+            /* see if sending SSLv2 client hello */
+            if ( ssl->options.side == WOLFSSL_SERVER_END &&
+                 ssl->options.clientState == NULL_STATE &&
+                 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
+                         != handshake) {
+                byte b0, b1;
+
+                ssl->options.processReply = runProcessOldClientHello;
+
+                /* sanity checks before getting size at front */
+                if (ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) {
+                    WOLFSSL_MSG("Not a valid old client hello");
+                    return PARSE_ERROR;
+                }
+
+                if (ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR &&
+                    ssl->buffers.inputBuffer.buffer[
+                          ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) {
+                    WOLFSSL_MSG("Not a valid version in old client hello");
+                    return PARSE_ERROR;
+                }
+
+                /* how many bytes need ProcessOldClientHello */
+                b0 =
+                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+                b1 =
+                ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+                ssl->curSize = (word16)(((b0 & 0x7f) << 8) | b1);
+            }
+            else {
+                ssl->options.processReply = getRecordLayerHeader;
+                continue;
+            }
+            FALL_THROUGH;
+
+        /* in the WOLFSSL_SERVER case, run the old client hello */
+        case runProcessOldClientHello:
+
+            /* get sz bytes or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                    return ret;
+            } else {
+            #ifdef WOLFSSL_DTLS
+                /* read ahead may already have */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < ssl->curSize)
+                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                        return ret;
+            #endif  /* WOLFSSL_DTLS */
+            }
+
+            ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
+                                        &ssl->buffers.inputBuffer.idx,
+                                        ssl->buffers.inputBuffer.length -
+                                        ssl->buffers.inputBuffer.idx,
+                                        ssl->curSize);
+            if (ret < 0)
+                return ret;
+
+            else if (ssl->buffers.inputBuffer.idx ==
+                     ssl->buffers.inputBuffer.length) {
+                ssl->options.processReply = doProcessInit;
+                return 0;
+            }
+
+#endif  /* OLD_HELLO_ALLOWED */
+            FALL_THROUGH;
+
+        /* get the record layer header */
+        case getRecordLayerHeader:
+
+            ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
+                                       &ssl->buffers.inputBuffer.idx,
+                                       &ssl->curRL, &ssl->curSize);
+#ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls && ret == SEQUENCE_ERROR) {
+                WOLFSSL_MSG("Silently dropping out of order DTLS message");
+                ssl->options.processReply = doProcessInit;
+                ssl->buffers.inputBuffer.length = 0;
+                ssl->buffers.inputBuffer.idx = 0;
+#ifdef WOLFSSL_DTLS_DROP_STATS
+                ssl->replayDropCount++;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+                if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) {
+                    ret = DtlsMsgPoolSend(ssl, 0);
+                    if (ret != 0)
+                        return ret;
+                }
+
+                continue;
+            }
+#endif
+            if (ret != 0)
+                return ret;
+
+            ssl->options.processReply = getData;
+            FALL_THROUGH;
+
+        /* retrieve record layer data */
+        case getData:
+
+            /* get sz bytes or return error */
+            if (!ssl->options.dtls) {
+                if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                    return ret;
+            } else {
+#ifdef WOLFSSL_DTLS
+                /* read ahead may already have */
+                used = ssl->buffers.inputBuffer.length -
+                       ssl->buffers.inputBuffer.idx;
+                if (used < ssl->curSize)
+                    if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+                        return ret;
+#endif
+            }
+
+            ssl->options.processReply = decryptMessage;
+            startIdx = ssl->buffers.inputBuffer.idx;  /* in case > 1 msg per */
+            FALL_THROUGH;
+
+        /* decrypt message */
+        case decryptMessage:
+
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+                                        (!IsAtLeastTLSv1_3(ssl->version) ||
+                                         ssl->curRL.type != change_cipher_spec))
+#endif
+            {
+                bufferStatic* in = &ssl->buffers.inputBuffer;
+
+                ret = SanityCheckCipherText(ssl, ssl->curSize);
+                if (ret < 0)
+                    return ret;
+
+                if (atomicUser) {
+                #ifdef ATOMIC_USER
+                    ret = ssl->ctx->DecryptVerifyCb(ssl,
+                                  in->buffer + in->idx,
+                                  in->buffer + in->idx,
+                                  ssl->curSize, ssl->curRL.type, 1,
+                                  &ssl->keys.padSz, ssl->DecryptVerifyCtx);
+                #endif /* ATOMIC_USER */
+                }
+                else {
+                    if (!ssl->options.tls1_3) {
+                #ifndef WOLFSSL_NO_TLS12
+                        ret = Decrypt(ssl,
+                                      in->buffer + in->idx,
+                                      in->buffer + in->idx,
+                                      ssl->curSize);
+                #else
+                        ret = DECRYPT_ERROR;
+                #endif
+                    }
+                    else
+                    {
+                #ifdef WOLFSSL_TLS13
+                    #if defined(WOLFSSL_TLS13_DRAFT_18) || \
+                        defined(WOLFSSL_TLS13_DRAFT_22) || \
+                        defined(WOLFSSL_TLS13_DRAFT_23)
+                        ret = DecryptTls13(ssl,
+                                           in->buffer + in->idx,
+                                           in->buffer + in->idx,
+                                           ssl->curSize, NULL, 0);
+                    #else
+                        ret = DecryptTls13(ssl,
+                                        in->buffer + in->idx,
+                                        in->buffer + in->idx,
+                                        ssl->curSize,
+                                        (byte*)&ssl->curRL, RECORD_HEADER_SZ);
+                    #endif
+                #else
+                        ret = DECRYPT_ERROR;
+                #endif /* WOLFSSL_TLS13 */
+                    }
+                }
+
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    return ret;
+            #endif
+
+                if (ret >= 0) {
+                #ifndef WOLFSSL_NO_TLS12
+                    /* handle success */
+                    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+                        ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
+                        /* go past TLSv1.1 IV */
+                    if (CipherHasExpIV(ssl))
+                        ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
+                #endif
+                }
+                else {
+                    WOLFSSL_MSG("Decrypt failed");
+                    WOLFSSL_ERROR(ret);
+                #ifdef WOLFSSL_EARLY_DATA
+                    if (ssl->options.tls1_3) {
+                        ssl->earlyDataSz += ssl->curSize;
+                        if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) {
+                            if (ssl->keys.peer_sequence_number_lo-- == 0)
+                                ssl->keys.peer_sequence_number_hi--;
+                            ssl->options.processReply = doProcessInit;
+                            ssl->buffers.inputBuffer.idx =
+                                            ssl->buffers.inputBuffer.length;
+                            return 0;
+                        }
+                    }
+                #endif
+                #ifdef WOLFSSL_DTLS
+                    /* If in DTLS mode, if the decrypt fails for any
+                     * reason, pretend the datagram never happened. */
+                    if (ssl->options.dtls) {
+                        ssl->options.processReply = doProcessInit;
+                        ssl->buffers.inputBuffer.idx =
+                                        ssl->buffers.inputBuffer.length;
+                        #ifdef WOLFSSL_DTLS_DROP_STATS
+                            ssl->macDropCount++;
+                        #endif /* WOLFSSL_DTLS_DROP_STATS */
+                    }
+                #endif /* WOLFSSL_DTLS */
+
+                    return DECRYPT_ERROR;
+                }
+            }
+
+            ssl->options.processReply = verifyMessage;
+            FALL_THROUGH;
+
+        /* verify digest of message */
+        case verifyMessage:
+
+#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18)
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0)
+#else
+            if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
+                                        (!IsAtLeastTLSv1_3(ssl->version) ||
+                                         ssl->curRL.type != change_cipher_spec))
+#endif
+            {
+                if (!atomicUser) {
+                    ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
+                                    ssl->buffers.inputBuffer.idx,
+                                    ssl->curSize, ssl->curRL.type,
+                                    &ssl->keys.padSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E)
+                        return ret;
+                #endif
+                    if (ret < 0) {
+                        WOLFSSL_MSG("VerifyMac failed");
+                        WOLFSSL_ERROR(ret);
+                        #ifdef WOLFSSL_DTLS
+                        /* If in DTLS mode, if the decrypt fails for any
+                         * reason, pretend the datagram never happened. */
+                        if (ssl->options.dtls) {
+                            ssl->options.processReply = doProcessInit;
+                            ssl->buffers.inputBuffer.idx =
+                                            ssl->buffers.inputBuffer.length;
+                            #ifdef WOLFSSL_DTLS_DROP_STATS
+                                ssl->macDropCount++;
+                            #endif /* WOLFSSL_DTLS_DROP_STATS */
+                        }
+                        #endif /* WOLFSSL_DTLS */
+                        return DECRYPT_ERROR;
+                    }
+                }
+
+                ssl->keys.encryptSz    = ssl->curSize;
+                ssl->keys.decryptedCur = 1;
+#ifdef WOLFSSL_TLS13
+                if (ssl->options.tls1_3) {
+                    word16 i = (word16)(ssl->buffers.inputBuffer.length -
+                                        ssl->keys.padSz);
+                    /* Remove padding from end of plain text. */
+                    for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
+                        if (ssl->buffers.inputBuffer.buffer[i] != 0)
+                            break;
+                    }
+                    /* Get the real content type from the end of the data. */
+                    ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
+                    ssl->keys.padSz = ssl->buffers.inputBuffer.length - i;
+                }
+#endif
+            }
+
+            ssl->options.processReply = runProcessingOneMessage;
+            FALL_THROUGH;
+
+        /* the record layer is here */
+        case runProcessingOneMessage:
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                DtlsUpdateWindow(ssl);
+            }
+        #endif /* WOLFSSL_DTLS */
+
+            WOLFSSL_MSG("received record layer msg");
+
+            switch (ssl->curRL.type) {
+                case handshake :
+                    /* debugging in DoHandShakeMsg */
+                    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+                        ret = DoDtlsHandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+#endif
+                    }
+                    else if (!IsAtLeastTLSv1_3(ssl->version)) {
+#ifndef WOLFSSL_NO_TLS12
+                        ret = DoHandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+#else
+                        ret = BUFFER_ERROR;
+#endif
+                    }
+                    else {
+#ifdef WOLFSSL_TLS13
+                        ret = DoTls13HandShakeMsg(ssl,
+                                            ssl->buffers.inputBuffer.buffer,
+                                            &ssl->buffers.inputBuffer.idx,
+                                            ssl->buffers.inputBuffer.length);
+    #ifdef WOLFSSL_EARLY_DATA
+                        if (ret != 0)
+                            return ret;
+                        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                ssl->earlyData &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+                            ssl->earlyData = no_early_data;
+                            ssl->options.processReply = doProcessInit;
+                            return ZERO_RETURN;
+                        }
+    #endif
+#else
+                        ret = BUFFER_ERROR;
+#endif
+                    }
+                    if (ret != 0)
+                        return ret;
+                    break;
+
+                case change_cipher_spec:
+                    WOLFSSL_MSG("got CHANGE CIPHER SPEC");
+                    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+                        if (ssl->hsInfoOn)
+                            AddPacketName(ssl, "ChangeCipher");
+                        /* add record header back on info */
+                        if (ssl->toInfoOn) {
+                            AddPacketInfo(ssl, "ChangeCipher",
+                                change_cipher_spec,
+                                ssl->buffers.inputBuffer.buffer +
+                                ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
+                                1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap);
+                            #ifdef WOLFSSL_CALLBACKS
+                            AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+                            #endif
+                        }
+                    #endif
+
+#ifdef WOLFSSL_TLS13
+    #ifdef WOLFSSL_TLS13_DRAFT_18
+                    if (IsAtLeastTLSv1_3(ssl->version)) {
+                        SendAlert(ssl, alert_fatal, illegal_parameter);
+                        return UNKNOWN_RECORD_TYPE;
+                    }
+    #else
+                    if (IsAtLeastTLSv1_3(ssl->version)) {
+                        word32 i = ssl->buffers.inputBuffer.idx;
+                        if (ssl->curSize != 1 ||
+                                      ssl->buffers.inputBuffer.buffer[i] != 1) {
+                            SendAlert(ssl, alert_fatal, illegal_parameter);
+                            return UNKNOWN_RECORD_TYPE;
+                        }
+                        ssl->buffers.inputBuffer.idx++;
+                        break;
+                    }
+    #endif
+#endif
+
+#ifndef WOLFSSL_NO_TLS12
+                    ret = SanityCheckMsgReceived(ssl, change_cipher_hs);
+                    if (ret != 0) {
+                        if (!ssl->options.dtls) {
+                            return ret;
+                        }
+                        else {
+                        #ifdef WOLFSSL_DTLS
+                        /* Check for duplicate CCS message in DTLS mode.
+                         * DTLS allows for duplicate messages, and it should be
+                         * skipped. Also skip if out of order. */
+                            if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E)
+                                return ret;
+
+                            if (IsDtlsNotSctpMode(ssl)) {
+                                ret = DtlsMsgPoolSend(ssl, 1);
+                                if (ret != 0)
+                                    return ret;
+                            }
+
+                            if (ssl->curSize != 1) {
+                                WOLFSSL_MSG("Malicious or corrupted"
+                                            " duplicate ChangeCipher msg");
+                                return LENGTH_ERROR;
+                            }
+                            ssl->buffers.inputBuffer.idx++;
+                            break;
+                        #endif /* WOLFSSL_DTLS */
+                        }
+                    }
+
+                    if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
+                        ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
+                        ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
+                    }
+
+                    if (ssl->curSize != 1) {
+                        WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg");
+                        return LENGTH_ERROR;
+                    }
+
+                    ssl->buffers.inputBuffer.idx++;
+                    ssl->keys.encryptionOn = 1;
+
+                    /* setup decrypt keys for following messages */
+                    /* XXX This might not be what we want to do when
+                     * receiving a CCS with multicast. We update the
+                     * key when the application updates them. */
+                    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                        return ret;
+
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq;
+#ifdef WOLFSSL_MULTICAST
+                            if (ssl->options.haveMcast) {
+                                peerSeq += ssl->keys.curPeerId;
+                                peerSeq->highwaterMark = UpdateHighwaterMark(0,
+                                        ssl->ctx->mcastFirstSeq,
+                                        ssl->ctx->mcastSecondSeq,
+                                        ssl->ctx->mcastMaxSeq);
+                            }
+#endif
+                            DtlsMsgPoolReset(ssl);
+                            peerSeq->nextEpoch++;
+                            peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
+                            peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
+                            peerSeq->nextSeq_lo = 0;
+                            peerSeq->nextSeq_hi = 0;
+                            XMEMCPY(peerSeq->prevWindow, peerSeq->window,
+                                    DTLS_SEQ_SZ);
+                            XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
+                        }
+                    #endif
+
+                    #ifdef HAVE_LIBZ
+                        if (ssl->options.usingCompression)
+                            if ( (ret = InitStreams(ssl)) != 0)
+                                return ret;
+                    #endif
+                    ret = BuildFinished(ssl, &ssl->hsHashes->verifyHashes,
+                                       ssl->options.side == WOLFSSL_CLIENT_END ?
+                                       server : client);
+                    if (ret != 0)
+                        return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
+                    break;
+
+                case application_data:
+                    WOLFSSL_MSG("got app DATA");
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls && ssl->options.dtlsHsRetain) {
+                            FreeHandshakeResources(ssl);
+                            ssl->options.dtlsHsRetain = 0;
+                        }
+                    #endif
+                    #ifdef WOLFSSL_TLS13
+                        if (ssl->keys.keyUpdateRespond) {
+                            WOLFSSL_MSG("No KeyUpdate from peer seen");
+                            return SANITY_MSG_E;
+                        }
+                    #endif
+                    if ((ret = DoApplicationData(ssl,
+                                                ssl->buffers.inputBuffer.buffer,
+                                               &ssl->buffers.inputBuffer.idx))
+                                                                         != 0) {
+                        WOLFSSL_ERROR(ret);
+                        return ret;
+                    }
+                    break;
+
+                case alert:
+                    WOLFSSL_MSG("got ALERT!");
+                    ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
+                                  &ssl->buffers.inputBuffer.idx, &type,
+                                   ssl->buffers.inputBuffer.length);
+                    if (ret == alert_fatal)
+                        return FATAL_ERROR;
+                    else if (ret < 0)
+                        return ret;
+
+                    /* catch warnings that are handled as errors */
+                    if (type == close_notify)
+                        return ssl->error = ZERO_RETURN;
+
+                    if (type == decrypt_error)
+                        return FATAL_ERROR;
+                    break;
+
+                default:
+                    WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE);
+                    return UNKNOWN_RECORD_TYPE;
+            }
+
+            ssl->options.processReply = doProcessInit;
+
+            /* input exhausted? */
+            if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length)
+                return 0;
+
+            /* more messages per record */
+            else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
+                WOLFSSL_MSG("More messages in record");
+
+                ssl->options.processReply = runProcessingOneMessage;
+
+                if (IsEncryptionOn(ssl, 0)) {
+                    WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
+                    if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
+                        ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
+                    }
+                    else {
+                        WOLFSSL_MSG("\tmiddle padding error");
+                        return FATAL_ERROR;
+                    }
+                }
+
+                continue;
+            }
+            /* more records */
+            else {
+                WOLFSSL_MSG("More records in input");
+                ssl->options.processReply = doProcessInit;
+                continue;
+            }
+
+        default:
+            WOLFSSL_MSG("Bad process input state, programming error");
+            return INPUT_CASE_ERROR;
+        }
+    }
+}
+
+
+int SendChangeCipher(WOLFSSL* ssl)
+{
+    byte              *output;
+    int                sendSz = RECORD_HEADER_SZ + ENUM_LEN;
+    int                idx    = RECORD_HEADER_SZ;
+    int                ret;
+
+    #ifdef OPENSSL_EXTRA
+	ssl->cbmode = SSL_CB_MODE_WRITE;
+	if (ssl->options.side == WOLFSSL_SERVER_END){
+		ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE;
+		if (ssl->CBIS != NULL)
+			ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS);
+	}
+	else{
+		ssl->options.clientState =
+			CLIENT_CHANGECIPHERSPEC_COMPLETE;
+		if (ssl->CBIS != NULL)
+			ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+	}
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            sendSz += DTLS_RECORD_EXTRA;
+            idx    += DTLS_RECORD_EXTRA;
+        }
+    #endif
+
+    /* are we in scr */
+    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+        sendSz += MAX_MSG_EXTRA;
+    }
+
+    /* check for avalaible size */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddRecordHeader(output, 1, change_cipher_spec, ssl);
+
+    output[idx] = 1;             /* turn it on */
+
+    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
+        byte input[ENUM_LEN];
+        int  inputSz = ENUM_LEN;
+
+        input[0] = 1;  /* turn it on */
+        sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                              change_cipher_spec, 0, 0, 0);
+        if (sendSz < 0) {
+            return sendSz;
+        }
+    }
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+    #endif
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output,
+                    sendSz, WRITE_PROTO, ssl->heap);
+    #endif
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (ssl->options.groupMessages)
+        return 0;
+    #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS)
+    else if (ssl->options.dtls) {
+        /* If using DTLS, force the ChangeCipherSpec message to be in the
+         * same datagram as the finished message. */
+        return 0;
+    }
+    #endif
+    else
+        return SendBuffered(ssl);
+}
+
+
+#ifndef NO_OLD_TLS
+static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
+                    int padLen, int content, int verify)
+{
+    byte   result[WC_MAX_DIGEST_SIZE];
+    word32 digestSz = ssl->specs.hash_size;            /* actual sizes */
+    word32 padSz    = ssl->specs.pad_size;
+    int    ret      = 0;
+
+    wc_Md5 md5;
+    wc_Sha sha;
+
+    /* data */
+    byte seq[SEQ_SZ];
+    byte conLen[ENUM_LEN + LENGTH_SZ];     /* content & length */
+    const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
+
+    (void)padLen;
+
+#ifdef HAVE_FUZZER
+    if (ssl->fuzzerCb)
+        ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
+#endif
+
+    XMEMSET(seq, 0, SEQ_SZ);
+    conLen[0] = (byte)content;
+    c16toa((word16)sz, &conLen[ENUM_LEN]);
+    WriteSEQ(ssl, verify, seq);
+
+    if (ssl->specs.mac_algorithm == md5_mac) {
+        ret =  wc_InitMd5_ex(&md5, ssl->heap, ssl->devId);
+        if (ret != 0)
+            return ret;
+
+        /* inner */
+        ret =  wc_Md5Update(&md5, macSecret, digestSz);
+        ret |= wc_Md5Update(&md5, PAD1, padSz);
+        ret |= wc_Md5Update(&md5, seq, SEQ_SZ);
+        ret |= wc_Md5Update(&md5, conLen, sizeof(conLen));
+        /* in buffer */
+        ret |= wc_Md5Update(&md5, in, sz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret = wc_Md5Final(&md5, result);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        /* outer */
+        ret =  wc_Md5Update(&md5, macSecret, digestSz);
+        ret |= wc_Md5Update(&md5, PAD2, padSz);
+        ret |= wc_Md5Update(&md5, result, digestSz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret =  wc_Md5Final(&md5, digest);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        wc_Md5Free(&md5);
+    }
+    else {
+        ret =  wc_InitSha_ex(&sha, ssl->heap, ssl->devId);
+        if (ret != 0)
+            return ret;
+
+        /* inner */
+        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
+        ret |= wc_ShaUpdate(&sha, PAD1, padSz);
+        ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ);
+        ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen));
+        /* in buffer */
+        ret |= wc_ShaUpdate(&sha, in, sz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret = wc_ShaFinal(&sha, result);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        /* outer */
+        ret =  wc_ShaUpdate(&sha, macSecret, digestSz);
+        ret |= wc_ShaUpdate(&sha, PAD2, padSz);
+        ret |= wc_ShaUpdate(&sha, result, digestSz);
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+        ret =  wc_ShaFinal(&sha, digest);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* TODO: Make non-blocking */
+        if (ret == WC_PENDING_E) {
+            ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
+        }
+    #endif
+        if (ret != 0)
+            return VERIFY_MAC_ERROR;
+
+        wc_ShaFree(&sha);
+    }
+    return 0;
+}
+#endif /* NO_OLD_TLS */
+
+
+#ifndef NO_CERTS
+
+#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest)
+{
+    int ret;
+    byte md5_result[WC_MD5_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#else
+    wc_Md5  md5[1];
+#endif
+
+    /* make md5 inner */
+    ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */
+    if (ret == 0)
+        ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_Md5Update(md5, PAD1, PAD_MD5);
+    if (ret == 0)
+        ret = wc_Md5Final(md5, md5_result);
+
+    /* make md5 outer */
+    if (ret == 0) {
+        ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, PAD2, PAD_MD5);
+            if (ret == 0)
+                ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_Md5Final(md5, digest);
+            wc_Md5Free(md5);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif /* !NO_MD5 && !NO_OLD_TLS */
+
+#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                              defined(WOLFSSL_ALLOW_TLS_SHA1))
+static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest)
+{
+    int ret;
+    byte sha_result[WC_SHA_DIGEST_SIZE];
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#else
+    wc_Sha  sha[1];
+#endif
+
+    /* make sha inner */
+    ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+    if (ret == 0)
+        ret = wc_ShaUpdate(sha, PAD1, PAD_SHA);
+    if (ret == 0)
+        ret = wc_ShaFinal(sha, sha_result);
+
+    /* make sha outer */
+    if (ret == 0) {
+        ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId);
+        if (ret == 0) {
+            ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, PAD2, PAD_SHA);
+            if (ret == 0)
+                ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE);
+            if (ret == 0)
+                ret = wc_ShaFinal(sha, digest);
+            wc_ShaFree(sha);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
+#endif
+
+    return ret;
+}
+#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */
+
+int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes)
+{
+    int ret = 0;
+
+    (void)hashes;
+
+    if (ssl->options.tls) {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(NO_SHA)
+        ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha);
+        if (ret != 0)
+            return ret;
+    #endif
+        if (IsAtLeastTLSv1_2(ssl)) {
+            #ifndef NO_SHA256
+                ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,
+                                       hashes->sha256);
+                if (ret != 0)
+                    return ret;
+            #endif
+            #ifdef WOLFSSL_SHA384
+                ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384,
+                                       hashes->sha384);
+                if (ret != 0)
+                    return ret;
+            #endif
+            #ifdef WOLFSSL_SHA512
+                ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512,
+                                       hashes->sha512);
+                if (ret != 0)
+                    return ret;
+            #endif
+        }
+    }
+    else {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        ret = BuildMD5_CertVerify(ssl, hashes->md5);
+        if (ret != 0)
+            return ret;
+    #endif
+    #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
+                              defined(WOLFSSL_ALLOW_TLS_SHA1))
+        ret = BuildSHA_CertVerify(ssl, hashes->sha);
+        if (ret != 0)
+            return ret;
+    #endif
+    }
+
+    return ret;
+}
+
+#endif /* !NO_CERTS */
+
+#ifndef WOLFSSL_NO_TLS12
+/* Persistable BuildMessage arguments */
+typedef struct BuildMsgArgs {
+    word32 digestSz;
+    word32 sz;
+    word32 pad;
+    word32 idx;
+    word32 headerSz;
+    word16 size;
+    word32 ivSz;      /* TLSv1.1  IV */
+    byte*  iv;
+} BuildMsgArgs;
+
+static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs)
+{
+    BuildMsgArgs* args = (BuildMsgArgs*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+    if (args->iv) {
+        XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT);
+        args->iv = NULL;
+    }
+}
+#endif
+
+/* Build SSL Message, encrypted */
+int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+             int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
+{
+#ifndef WOLFSSL_NO_TLS12
+    int ret = 0;
+    BuildMsgArgs* args;
+    BuildMsgArgs  lcl_args;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    args = (BuildMsgArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#endif
+#endif
+
+    WOLFSSL_ENTER("BuildMessage");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+#ifdef WOLFSSL_NO_TLS12
+    return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+                                               hashOutput, sizeOnly, asyncOkay);
+#else
+#ifdef WOLFSSL_TLS13
+    if (ssl->options.tls1_3) {
+        return BuildTls13Message(ssl, output, outSz, input, inSz, type,
+                                 hashOutput, sizeOnly, asyncOkay);
+    }
+#endif
+
+    ret = WC_NOT_PENDING_E;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (asyncOkay) {
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_buildmsg;
+        }
+    }
+    else
+#endif
+    {
+        args = &lcl_args;
+    }
+
+    /* Reset state */
+    if (ret == WC_NOT_PENDING_E) {
+        ret = 0;
+        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+        XMEMSET(args, 0, sizeof(BuildMsgArgs));
+
+        args->sz = RECORD_HEADER_SZ + inSz;
+        args->idx  = RECORD_HEADER_SZ;
+        args->headerSz = RECORD_HEADER_SZ;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeBuildMsgArgs;
+    #endif
+    }
+
+    switch (ssl->options.buildMsgState) {
+        case BUILD_MSG_BEGIN:
+        {
+            /* catch mistaken sizeOnly parameter */
+            if (!sizeOnly && (output == NULL || input == NULL) ) {
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+            }
+            if (sizeOnly && (output || input) ) {
+                WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output");
+                ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg);
+            }
+
+            ssl->options.buildMsgState = BUILD_MSG_SIZE;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_SIZE:
+        {
+            args->digestSz = ssl->specs.hash_size;
+        #ifdef HAVE_TRUNCATED_HMAC
+            if (ssl->truncated_hmac)
+                args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz);
+        #endif
+            args->sz += args->digestSz;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->sz       += DTLS_RECORD_EXTRA;
+                args->idx      += DTLS_RECORD_EXTRA;
+                args->headerSz += DTLS_RECORD_EXTRA;
+            }
+        #endif
+
+            if (ssl->specs.cipher_type == block) {
+                word32 blockSz = ssl->specs.block_size;
+                if (ssl->options.tls1_1) {
+                    args->ivSz = blockSz;
+                    args->sz  += args->ivSz;
+
+                    if (args->ivSz > MAX_IV_SZ)
+                        ERROR_OUT(BUFFER_E, exit_buildmsg);
+                }
+                args->sz += 1;       /* pad byte */
+                args->pad = (args->sz - args->headerSz) % blockSz;
+                #ifdef OPENSSL_EXTRA
+                if(args->pad != 0)
+                #endif
+                    args->pad = blockSz - args->pad;
+                args->sz += args->pad;
+            }
+
+        #ifdef HAVE_AEAD
+            if (ssl->specs.cipher_type == aead) {
+                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
+                    args->ivSz = AESGCM_EXP_IV_SZ;
+
+                args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz);
+            }
+        #endif
+
+            /* done with size calculations */
+            if (sizeOnly)
+                goto exit_buildmsg;
+
+            if (args->sz > (word32)outSz) {
+                WOLFSSL_MSG("Oops, want to write past output buffer size");
+                ERROR_OUT(BUFFER_E, exit_buildmsg);
+            }
+
+            if (args->ivSz > 0) {
+                args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT);
+                if (args->iv == NULL)
+                    ERROR_OUT(MEMORY_E, exit_buildmsg);
+
+                ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz);
+                if (ret != 0)
+                    goto exit_buildmsg;
+
+            }
+
+        #ifdef HAVE_AEAD
+            if (ssl->specs.cipher_type == aead) {
+                if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
+                    XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ);
+            }
+        #endif
+
+            args->size = (word16)(args->sz - args->headerSz);    /* include mac and digest */
+            AddRecordHeader(output, args->size, (byte)type, ssl);
+
+            /* write to output */
+            if (args->ivSz > 0) {
+                XMEMCPY(output + args->idx, args->iv,
+                                        min(args->ivSz, MAX_IV_SZ));
+                args->idx += args->ivSz;
+            }
+            XMEMCPY(output + args->idx, input, inSz);
+            args->idx += inSz;
+
+            ssl->options.buildMsgState = BUILD_MSG_HASH;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_HASH:
+        {
+            word32 i;
+
+            if (type == handshake && hashOutput) {
+                ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
+                if (ret != 0)
+                    goto exit_buildmsg;
+            }
+            if (ssl->specs.cipher_type == block) {
+                word32 tmpIdx = args->idx + args->digestSz;
+
+                for (i = 0; i <= args->pad; i++)
+                    output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */
+            }
+
+            ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_VERIFY_MAC:
+        {
+            /* User Record Layer Callback handling */
+        #ifdef ATOMIC_USER
+            if (ssl->ctx->MacEncryptCb) {
+                ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
+                                output + args->headerSz + args->ivSz, inSz, type, 0,
+                                output + args->headerSz, output + args->headerSz, args->size,
+                                ssl->MacEncryptCtx);
+                goto exit_buildmsg;
+            }
+        #endif
+
+            if (ssl->specs.cipher_type != aead) {
+        #ifdef HAVE_TRUNCATED_HMAC
+            if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) {
+            #ifdef WOLFSSL_SMALL_STACK
+                byte* hmac = NULL;
+            #else
+                byte  hmac[WC_MAX_DIGEST_SIZE];
+            #endif
+
+            #ifdef WOLFSSL_SMALL_STACK
+                hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
+                                                       DYNAMIC_TYPE_DIGEST);
+                if (hmac == NULL)
+                    ERROR_OUT(MEMORY_E, exit_buildmsg);
+            #endif
+
+                ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz,
+                                                             inSz, -1, type, 0);
+                XMEMCPY(output + args->idx, hmac, args->digestSz);
+
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
+            #endif
+            }
+            else
+        #endif
+                ret = ssl->hmac(ssl, output + args->idx, output +
+                                args->headerSz + args->ivSz, inSz, -1, type, 0);
+            }
+            if (ret != 0)
+                goto exit_buildmsg;
+
+            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
+        }
+        FALL_THROUGH;
+        case BUILD_MSG_ENCRYPT:
+        {
+            ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size,
+                asyncOkay);
+            break;
+        }
+    }
+
+exit_buildmsg:
+
+    WOLFSSL_LEAVE("BuildMessage", ret);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif
+
+    /* make sure build message state is reset */
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+
+    #ifdef WOLFSSL_DTLS
+        if (ret == 0 && ssl->options.dtls)
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+    #endif
+
+    /* return sz on success */
+    if (ret == 0)
+        ret = args->sz;
+
+    /* Final cleanup */
+    FreeBuildMsgArgs(ssl, args);
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ssl->async.freeArgs = NULL;
+#endif
+
+    return ret;
+#endif /* !WOLFSSL_NO_TLS12 */
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+int SendFinished(WOLFSSL* ssl)
+{
+    int              sendSz,
+                     finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
+                                                     FINISHED_SZ;
+    byte             input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ];  /* max */
+    byte            *output;
+    Hashes*          hashes;
+    int              ret;
+    int              headerSz = HANDSHAKE_HEADER_SZ;
+    int              outputSz;
+
+    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+    WOLFSSL_ENTER("SendFinished");
+
+    /* setup encrypt keys */
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    /* check for available size */
+    outputSz = sizeof(input) + MAX_MSG_EXTRA;
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            headerSz += DTLS_HANDSHAKE_EXTRA;
+            ssl->keys.dtls_epoch++;
+            ssl->keys.dtls_prev_sequence_number_hi =
+                    ssl->keys.dtls_sequence_number_hi;
+            ssl->keys.dtls_prev_sequence_number_lo =
+                    ssl->keys.dtls_sequence_number_lo;
+            ssl->keys.dtls_sequence_number_hi = 0;
+            ssl->keys.dtls_sequence_number_lo = 0;
+        }
+    #endif
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
+
+    /* make finished hashes */
+    hashes = (Hashes*)&input[headerSz];
+    ret = BuildFinished(ssl, hashes,
+                     ssl->options.side == WOLFSSL_CLIENT_END ? client : server);
+    if (ret != 0) return ret;
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation) {
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            XMEMCPY(ssl->secure_renegotiation->client_verify_data, hashes,
+                    TLS_FINISHED_SZ);
+        else
+            XMEMCPY(ssl->secure_renegotiation->server_verify_data, hashes,
+                    TLS_FINISHED_SZ);
+    }
+#endif
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0)
+                return ret;
+        }
+    #endif
+
+    sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
+                                                          handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    if (!ssl->options.resuming) {
+#ifndef NO_SESSION_CACHE
+        AddSession(ssl);    /* just try */
+#endif
+        if (ssl->options.side == WOLFSSL_SERVER_END) {
+        #ifdef OPENSSL_EXTRA
+            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+            ssl->cbmode = SSL_CB_MODE_WRITE;
+            if (ssl->CBIS != NULL)
+                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+        #endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+    else {
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        #ifdef OPENSSL_EXTRA
+            ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+            ssl->cbmode = SSL_CB_MODE_WRITE;
+            if (ssl->CBIS != NULL)
+                ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS);
+        #endif
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+        }
+    }
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendFinished", ret);
+    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
+
+    return ret;
+}
+#endif /* WOLFSSL_NO_TLS12 */
+
+#ifndef NO_WOLFSSL_SERVER
+#if (!defined(WOLFSSL_NO_TLS12) && \
+        (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+         defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \
+    (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST))
+static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
+                             DecodedCert* cert, byte* certData, word32 length)
+{
+    int ret;
+
+    InitDecodedCert(cert, certData, length, ssl->heap);
+    /* TODO: Setup async support here */
+    ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm);
+    if (ret != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    if (ret == 0)
+        ret = InitOcspRequest(request, cert, 0, ssl->heap);
+    if (ret == 0) {
+        /* make sure ctx OCSP request is updated */
+        if (!ssl->buffers.weOwnCert) {
+            wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock;
+            if (wc_LockMutex(ocspLock) == 0) {
+                if (ssl->ctx->certOcspRequest == NULL)
+                    ssl->ctx->certOcspRequest = request;
+                wc_UnLockMutex(ocspLock);
+            }
+        }
+    }
+
+    FreeDecodedCert(cert);
+
+    return ret;
+}
+
+
+int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
+                       buffer* response)
+{
+    int          ret = 0;
+    OcspRequest* request;
+
+    if (ssl == NULL || ocspRequest == NULL || response == NULL)
+        return BAD_FUNC_ARG;
+
+    request = *ocspRequest;
+
+    XMEMSET(response, 0, sizeof(*response));
+
+    /* unable to fetch status. skip. */
+    if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
+        return 0;
+
+    if (request == NULL || ssl->buffers.weOwnCert) {
+        DerBuffer* der = ssl->buffers.certificate;
+        #ifdef WOLFSSL_SMALL_STACK
+            DecodedCert* cert = NULL;
+        #else
+            DecodedCert  cert[1];
+        #endif
+
+        /* unable to fetch status. skip. */
+        if (der->buffer == NULL || der->length == 0)
+            return 0;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                        DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+        request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+        if (request == NULL)
+            ret = MEMORY_E;
+
+        if (ret == 0) {
+            ret = CreateOcspRequest(ssl, request, cert, der->buffer,
+                                                                   der->length);
+        }
+
+        if (request != NULL)
+            XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+    #endif
+    }
+
+    if (ret == 0) {
+        request->ssl = ssl;
+        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response);
+
+        /* Suppressing, not critical */
+        if (ret == OCSP_CERT_REVOKED ||
+            ret == OCSP_CERT_UNKNOWN ||
+            ret == OCSP_LOOKUP_FAIL) {
+            ret = 0;
+        }
+    }
+
+    *ocspRequest = request;
+
+    return ret;
+}
+#endif
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_CERTS
+#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+/* handle generation of certificate (11) */
+int SendCertificate(WOLFSSL* ssl)
+{
+    int    ret = 0;
+    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
+    word32 length, maxFragment;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
+    WOLFSSL_ENTER("SendCertificate");
+
+    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
+        return 0;  /* not needed */
+
+    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+    #ifdef OPENSSL_EXTRA
+        if (ssl->version.major == SSLv3_MAJOR
+            && ssl->version.minor == SSLv3_MINOR){
+            SendAlert(ssl, alert_warning, no_certificate);
+            return 0;
+        } else {
+    #endif
+            certSz = 0;
+            certChainSz = 0;
+            headerSz = CERT_HEADER_SZ;
+            length = CERT_HEADER_SZ;
+            listSz = 0;
+    #ifdef OPENSSL_EXTRA
+        }
+    #endif
+    }
+    else {
+        if (!ssl->buffers.certificate) {
+            WOLFSSL_MSG("Send Cert missing certificate buffer");
+            return BUFFER_ERROR;
+        }
+        certSz = ssl->buffers.certificate->length;
+        headerSz = 2 * CERT_HEADER_SZ;
+        /* list + cert size */
+        length = certSz + headerSz;
+        listSz = certSz + CERT_HEADER_SZ;
+
+        /* may need to send rest of chain, already has leading size(s) */
+        if (certSz && ssl->buffers.certChain) {
+            certChainSz = ssl->buffers.certChain->length;
+            length += certChainSz;
+            listSz += certChainSz;
+        }
+        else
+            certChainSz = 0;
+    }
+
+    payloadSz = length;
+
+    if (ssl->fragOffset != 0)
+        length -= (ssl->fragOffset + headerSz);
+
+    maxFragment = MAX_RECORD_SIZE;
+
+    if (ssl->options.dtls) {
+    #ifdef WOLFSSL_DTLS
+        /* The 100 bytes is used to account for the UDP and IP headers.
+           It can also include the record padding and MAC if the
+           SendCertificate is called for a secure renegotiation. */
+        maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ
+                      - DTLS_HANDSHAKE_HEADER_SZ - 100;
+    #endif /* WOLFSSL_DTLS */
+    }
+
+    maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment);
+
+    while (length > 0 && ret == 0) {
+        byte*  output = NULL;
+        word32 fragSz = 0;
+        word32 i = RECORD_HEADER_SZ;
+        int    sendSz = RECORD_HEADER_SZ;
+
+        if (!ssl->options.dtls) {
+            if (ssl->fragOffset == 0)  {
+                if (headerSz + certSz + certChainSz <=
+                    maxFragment - HANDSHAKE_HEADER_SZ) {
+
+                    fragSz = headerSz + certSz + certChainSz;
+                }
+                else {
+                    fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
+                }
+                sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+                i += HANDSHAKE_HEADER_SZ;
+            }
+            else {
+                fragSz = min(length, maxFragment);
+                sendSz += fragSz;
+            }
+
+            if (IsEncryptionOn(ssl, 1))
+                sendSz += MAX_MSG_EXTRA;
+        }
+        else {
+        #ifdef WOLFSSL_DTLS
+            fragSz = min(length, maxFragment);
+            sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+                      + HANDSHAKE_HEADER_SZ;
+            i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA
+                      + HANDSHAKE_HEADER_SZ;
+        #endif
+        }
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        if (ssl->fragOffset == 0) {
+            if (!ssl->options.dtls) {
+                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl, output + RECORD_HEADER_SZ,
+                                  HANDSHAKE_HEADER_SZ);
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                AddHeaders(output, payloadSz, certificate, ssl);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl,
+                                  output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA,
+                                  HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA);
+                /* Adding the headers increments these, decrement them for
+                 * actual message header. */
+                ssl->keys.dtls_handshake_number--;
+                AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+                ssl->keys.dtls_handshake_number--;
+            #endif /* WOLFSSL_DTLS */
+            }
+
+            /* list total */
+            c32to24(listSz, output + i);
+            if (!IsEncryptionOn(ssl, 1))
+                HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+            i += CERT_HEADER_SZ;
+            length -= CERT_HEADER_SZ;
+            fragSz -= CERT_HEADER_SZ;
+            if (certSz) {
+                c32to24(certSz, output + i);
+                if (!IsEncryptionOn(ssl, 1))
+                    HashOutputRaw(ssl, output + i, CERT_HEADER_SZ);
+                i += CERT_HEADER_SZ;
+                length -= CERT_HEADER_SZ;
+                fragSz -= CERT_HEADER_SZ;
+
+                if (!IsEncryptionOn(ssl, 1)) {
+                    HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz);
+                    if (certChainSz)
+                        HashOutputRaw(ssl, ssl->buffers.certChain->buffer,
+                                      certChainSz);
+                }
+            }
+        }
+        else {
+            if (!ssl->options.dtls) {
+                AddRecordHeader(output, fragSz, handshake, ssl);
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz,
+                               payloadSz, certificate, ssl);
+                ssl->keys.dtls_handshake_number--;
+            #endif /* WOLFSSL_DTLS */
+            }
+        }
+
+        /* member */
+        if (certSz && ssl->fragOffset < certSz) {
+            word32 copySz = min(certSz - ssl->fragOffset, fragSz);
+            XMEMCPY(output + i,
+                    ssl->buffers.certificate->buffer + ssl->fragOffset, copySz);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+            fragSz -= copySz;
+        }
+        if (certChainSz && fragSz) {
+            word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz);
+            XMEMCPY(output + i,
+                    ssl->buffers.certChain->buffer + ssl->fragOffset - certSz,
+                    copySz);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+        }
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input = NULL;
+            int   inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            if (inputSz < 0) {
+                WOLFSSL_MSG("Send Cert bad inputSz");
+                return BUFFER_E;
+            }
+
+            if (inputSz > 0) {  /* clang thinks could be zero, let's help */
+                input = (byte*)XMALLOC(inputSz, ssl->heap,
+                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (input == NULL)
+                    return MEMORY_E;
+                XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            }
+
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                                          handshake, 1, 0, 0);
+
+            if (inputSz > 0)
+                XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        }
+        else {
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                DtlsSEQIncrement(ssl, CUR_ORDER);
+        #endif
+        }
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+    #endif
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Certificate");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Certificate", handshake, output, sendSz,
+                           WRITE_PROTO, ssl->heap);
+    #endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+        if (!ssl->options.groupMessages)
+            ret = SendBuffered(ssl);
+    }
+
+    if (ret != WANT_WRITE) {
+        /* Clean up the fragment offset. */
+        ssl->fragOffset = 0;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                ssl->keys.dtls_handshake_number++;
+        #endif
+        if (ssl->options.side == WOLFSSL_SERVER_END){
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+        }
+    }
+
+    WOLFSSL_LEAVE("SendCertificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
+
+/* handle generation of certificate_request (13) */
+int SendCertificateRequest(WOLFSSL* ssl)
+{
+    byte   *output;
+    int    ret;
+    int    sendSz;
+    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    word32 dnLen = 0;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
+#endif
+
+    int  typeTotal = 1;  /* only 1 for now */
+    int  reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ;  /* add auth later */
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+    WOLFSSL_ENTER("SendCertificateRequest");
+
+    if (IsAtLeastTLSv1_2(ssl))
+        reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    /* Certificate Authorities */
+    names = ssl->ctx->ca_names;
+    while (names != NULL) {
+        byte seq[MAX_SEQ_SZ];
+
+        /* 16-bit length | SEQ | Len | DER of name */
+        dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) +
+                 names->data.name->rawLen;
+        names = names->next;
+    }
+    reqSz += dnLen;
+#endif
+
+    if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher)
+        return 0;  /* not needed */
+
+    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            i      += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        }
+    #endif
+    /* check for available size */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    AddHeaders(output, reqSz, certificate_request, ssl);
+
+    /* write to output */
+    output[i++] = (byte)typeTotal;  /* # of types */
+#ifdef HAVE_ECC
+    if ((ssl->options.cipherSuite0 == ECC_BYTE ||
+         ssl->options.cipherSuite0 == CHACHA_BYTE) &&
+                     ssl->specs.sig_algo == ecc_dsa_sa_algo) {
+        output[i++] = ecdsa_sign;
+    } else
+#endif /* HAVE_ECC */
+    {
+        output[i++] = rsa_sign;
+    }
+
+    /* supported hash/sig */
+    if (IsAtLeastTLSv1_2(ssl)) {
+        c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
+        i += OPAQUE16_LEN;
+
+        XMEMCPY(&output[i],
+                         ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
+        i += ssl->suites->hashSigAlgoSz;
+    }
+
+    /* Certificate Authorities */
+    c16toa((word16)dnLen, &output[i]);  /* auth's */
+    i += REQ_HEADER_SZ;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    names = ssl->ctx->ca_names;
+    while (names != NULL) {
+        byte seq[MAX_SEQ_SZ];
+
+        c16toa((word16)names->data.name->rawLen +
+               SetSequence(names->data.name->rawLen, seq), &output[i]);
+        i += OPAQUE16_LEN;
+        i += SetSequence(names->data.name->rawLen, output + i);
+        XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen);
+        i += names->data.name->rawLen;
+        names = names->next;
+    }
+#endif
+    (void)i;
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+        }
+        if (ssl->options.dtls)
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+    #endif
+
+    ret = HashOutput(ssl, output, sendSz, 0);
+    if (ret != 0)
+        return ret;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateRequest");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+    ssl->buffers.outputBuffer.length += sendSz;
+    if (ssl->options.groupMessages)
+        ret = 0;
+    else
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendCertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
+                                                                     byte count)
+{
+    byte*  output  = NULL;
+    word32 idx     = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    word32 length  = ENUM_LEN;
+    int    sendSz  = 0;
+    int    ret     = 0;
+    int    i       = 0;
+
+    WOLFSSL_ENTER("BuildCertificateStatus");
+
+    switch (type) {
+        case WOLFSSL_CSR2_OCSP_MULTI:
+            length += OPAQUE24_LEN;
+            FALL_THROUGH; /* followed by */
+
+        case WOLFSSL_CSR2_OCSP:
+            for (i = 0; i < count; i++)
+                length += OPAQUE24_LEN + status[i].length;
+        break;
+
+        default:
+            return 0;
+    }
+
+    sendSz = idx + length;
+
+    if (ssl->keys.encryptionOn)
+        sendSz += MAX_MSG_EXTRA;
+
+    if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, certificate_status, ssl);
+
+        output[idx++] = type;
+
+        if (type == WOLFSSL_CSR2_OCSP_MULTI) {
+            c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
+            idx += OPAQUE24_LEN;
+        }
+
+        for (i = 0; i < count; i++) {
+            c32to24(status[i].length, output + idx);
+            idx += OPAQUE24_LEN;
+
+            XMEMCPY(output + idx, status[i].buffer, status[i].length);
+            idx += status[i].length;
+        }
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ;
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                                           handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                ret = sendSz;
+        }
+        else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+        }
+
+    #ifdef WOLFSSL_DTLS
+        if (ret == 0 && IsDtlsNotSctpMode(ssl))
+            ret = DtlsMsgPoolSave(ssl, output, sendSz);
+    #endif
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ret == 0 && ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateStatus");
+        if (ret == 0 && ssl->toInfoOn)
+            AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+
+        if (ret == 0) {
+            ssl->buffers.outputBuffer.length += sendSz;
+            if (!ssl->options.groupMessages)
+                ret = SendBuffered(ssl);
+        }
+    }
+
+    WOLFSSL_LEAVE("BuildCertificateStatus", ret);
+    return ret;
+}
+#endif
+#endif /* NO_WOLFSSL_SERVER */
+
+/* handle generation of certificate_status (22) */
+int SendCertificateStatus(WOLFSSL* ssl)
+{
+    int ret = 0;
+    byte status_type = 0;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
+    WOLFSSL_ENTER("SendCertificateStatus");
+
+    (void) ssl;
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+    status_type = ssl->status_request;
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+    status_type = status_type ? status_type : ssl->status_request_v2;
+#endif
+
+    switch (status_type) {
+
+    #ifndef NO_WOLFSSL_SERVER
+    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        /* case WOLFSSL_CSR_OCSP: */
+        case WOLFSSL_CSR2_OCSP:
+        {
+            OcspRequest* request = ssl->ctx->certOcspRequest;
+            buffer response;
+
+            ret = CreateOcspResponse(ssl, &request, &response);
+            if (ret == 0 && response.buffer) {
+                ret = BuildCertificateStatus(ssl, status_type, &response, 1);
+
+                XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+                response.buffer = NULL;
+            }
+
+            break;
+        }
+
+    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST    */
+           /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+    #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        case WOLFSSL_CSR2_OCSP_MULTI:
+        {
+            OcspRequest* request = ssl->ctx->certOcspRequest;
+            buffer responses[1 + MAX_CHAIN_DEPTH];
+            int i = 0;
+
+            XMEMSET(responses, 0, sizeof(responses));
+
+            ret = CreateOcspResponse(ssl, &request, &responses[0]);
+            if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
+                                              || ssl->buffers.weOwnCertChain)) {
+                buffer der;
+                word32 idx = 0;
+            #ifdef WOLFSSL_SMALL_STACK
+                DecodedCert* cert = NULL;
+            #else
+                DecodedCert  cert[1];
+            #endif
+
+            #ifdef WOLFSSL_SMALL_STACK
+                cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
+                                                            DYNAMIC_TYPE_DCERT);
+                if (cert == NULL)
+                    return MEMORY_E;
+            #endif
+                request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+                if (request == NULL) {
+            #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+            #endif
+                    return MEMORY_E;
+                }
+
+                while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) {
+                    c24to32(ssl->buffers.certChain->buffer + idx, &der.length);
+                    idx += OPAQUE24_LEN;
+
+                    der.buffer = ssl->buffers.certChain->buffer + idx;
+                    idx += der.length;
+
+                    if (idx > ssl->buffers.certChain->length)
+                        break;
+
+                    ret = CreateOcspRequest(ssl, request, cert, der.buffer,
+                                                                    der.length);
+                    if (ret == 0) {
+                        request->ssl = ssl;
+                        ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+                                                    request, &responses[i + 1]);
+
+                        /* Suppressing, not critical */
+                        if (ret == OCSP_CERT_REVOKED ||
+                            ret == OCSP_CERT_UNKNOWN ||
+                            ret == OCSP_LOOKUP_FAIL) {
+                            ret = 0;
+                        }
+
+
+                        i++;
+                    }
+                }
+
+                XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
+            #endif
+            }
+            else {
+                while (ret == 0 &&
+                            NULL != (request = ssl->ctx->chainOcspRequest[i])) {
+                    request->ssl = ssl;
+                    ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
+                                                request, &responses[++i]);
+
+                    /* Suppressing, not critical */
+                    if (ret == OCSP_CERT_REVOKED ||
+                        ret == OCSP_CERT_UNKNOWN ||
+                        ret == OCSP_LOOKUP_FAIL) {
+                        ret = 0;
+                    }
+                }
+            }
+
+            if (responses[0].buffer) {
+                if (ret == 0) {
+                    ret = BuildCertificateStatus(ssl, status_type, responses,
+                                                                   (byte)i + 1);
+                }
+
+                for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) {
+                    if (responses[i].buffer) {
+                        XFREE(responses[i].buffer, ssl->heap,
+                                                     DYNAMIC_TYPE_OCSP_REQUEST);
+                    }
+                }
+            }
+
+            break;
+        }
+    #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+    #endif /* NO_WOLFSSL_SERVER */
+
+        default:
+            break;
+    }
+
+    WOLFSSL_LEAVE("SendCertificateStatus", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND);
+
+    return ret;
+}
+
+#endif /* !NO_CERTS */
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+int SendData(WOLFSSL* ssl, const void* data, int sz)
+{
+    int sent = 0,  /* plainText size */
+        sendSz,
+        ret,
+        dtlsExtra = 0;
+
+    if (ssl->error == WANT_WRITE
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
+        ssl->error = 0;
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        /* In DTLS mode, we forgive some errors and allow the session
+         * to continue despite them. */
+        if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
+            ssl->error = 0;
+    }
+#endif /* WOLFSSL_DTLS */
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        if (ssl->options.handShakeState == HANDSHAKE_DONE) {
+            WOLFSSL_MSG("handshake complete, trying to send early data");
+            return BUILD_MSG_ERROR;
+        }
+    }
+    else
+#endif
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        int err;
+        WOLFSSL_MSG("handshake not complete, trying to finish");
+        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* if async would block return WANT_WRITE */
+            if (ssl->error == WC_PENDING_E) {
+                return WOLFSSL_CBIO_ERR_WANT_WRITE;
+            }
+        #endif
+            return  err;
+        }
+    }
+
+    /* last time system socket output buffer was full, try again to send */
+    if (ssl->buffers.outputBuffer.length > 0) {
+        WOLFSSL_MSG("output buffer was full, trying to send again");
+        if ( (ssl->error = SendBuffered(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
+                                                 ssl->options.isClosed)) {
+                ssl->error = SOCKET_PEER_CLOSED_E;
+                WOLFSSL_ERROR(ssl->error);
+                return 0;  /* peer reset or closed */
+            }
+            return ssl->error;
+        }
+        else {
+            /* advance sent to previous sent + plain size just sent */
+            sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
+            WOLFSSL_MSG("sent write buffered data");
+
+            if (sent > sz) {
+                WOLFSSL_MSG("error: write() after WANT_WRITE with short size");
+                return ssl->error = BAD_FUNC_ARG;
+            }
+        }
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        dtlsExtra = DTLS_RECORD_EXTRA;
+    }
+#endif
+
+    for (;;) {
+        int   len;
+        byte* out;
+        byte* sendBuffer = (byte*)data + sent;  /* may switch on comp */
+        int   buffSz;                           /* may switch on comp */
+        int   outputSz;
+#ifdef HAVE_LIBZ
+        byte  comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+        if (sent == sz) break;
+
+        len = wolfSSL_GetMaxRecordSize(ssl, sz - sent);
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            len = min(len, MAX_UDP_SIZE);
+        }
+#endif
+        buffSz = len;
+
+        /* check for available size */
+        outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA;
+        if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+            return ssl->error = ret;
+
+        /* get output buffer */
+        out = ssl->buffers.outputBuffer.buffer +
+              ssl->buffers.outputBuffer.length;
+
+#ifdef HAVE_LIBZ
+        if (ssl->options.usingCompression) {
+            buffSz = myCompress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
+            if (buffSz < 0) {
+                return buffSz;
+            }
+            sendBuffer = comp;
+        }
+#endif
+        if (!ssl->options.tls1_3) {
+            sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz,
+                                  application_data, 0, 0, 1);
+        }
+        else {
+#ifdef WOLFSSL_TLS13
+            sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz,
+                                       application_data, 0, 0, 1);
+#else
+            sendSz = BUFFER_ERROR;
+#endif
+        }
+        if (sendSz < 0) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (sendSz == WC_PENDING_E)
+                ssl->error = sendSz;
+        #endif
+            return BUILD_MSG_ERROR;
+        }
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        if ( (ssl->error = SendBuffered(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            /* store for next call if WANT_WRITE or user embedSend() that
+               doesn't present like WANT_WRITE */
+            ssl->buffers.plainSz  = len;
+            ssl->buffers.prevSent = sent;
+            if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
+                                                 ssl->options.isClosed)) {
+                ssl->error = SOCKET_PEER_CLOSED_E;
+                WOLFSSL_ERROR(ssl->error);
+                return 0;  /* peer reset or closed */
+            }
+            return ssl->error;
+        }
+
+        sent += len;
+
+        /* only one message per attempt */
+        if (ssl->options.partialWrite == 1) {
+            WOLFSSL_MSG("Paritial Write on, only sending one record");
+            break;
+        }
+    }
+
+    return sent;
+}
+
+/* process input data */
+int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
+{
+    int size;
+
+    WOLFSSL_ENTER("ReceiveData()");
+
+    /* reset error state */
+    if (ssl->error == WANT_READ
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || ssl->error == WC_PENDING_E
+    #endif
+    ) {
+        ssl->error = 0;
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        /* In DTLS mode, we forgive some errors and allow the session
+         * to continue despite them. */
+        if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR)
+            ssl->error = 0;
+    }
+#endif /* WOLFSSL_DTLS */
+
+    if (ssl->error != 0 && ssl->error != WANT_WRITE) {
+        WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
+        return ssl->error;
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+    }
+    else
+#endif
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        int err;
+        WOLFSSL_MSG("Handshake not complete, trying to finish");
+        if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* if async would block return WANT_WRITE */
+            if (ssl->error == WC_PENDING_E) {
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+        #endif
+            return  err;
+        }
+    }
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+startScr:
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
+        int err;
+        ssl->secure_renegotiation->startScr = 0;  /* only start once */
+        WOLFSSL_MSG("Need to start scr, server requested");
+        if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS)
+            return  err;
+    }
+#endif
+
+    while (ssl->buffers.clearOutputBuffer.length == 0) {
+        if ( (ssl->error = ProcessReply(ssl)) < 0) {
+            WOLFSSL_ERROR(ssl->error);
+            if (ssl->error == ZERO_RETURN) {
+                WOLFSSL_MSG("Zero return, no more data coming");
+                return 0;         /* no more data coming */
+            }
+            if (ssl->error == SOCKET_ERROR_E) {
+                if (ssl->options.connReset || ssl->options.isClosed) {
+                    WOLFSSL_MSG("Peer reset or closed, connection done");
+                    ssl->error = SOCKET_PEER_CLOSED_E;
+                    WOLFSSL_ERROR(ssl->error);
+                    return 0;     /* peer reset or closed */
+                }
+            }
+            return ssl->error;
+        }
+        #ifdef HAVE_SECURE_RENEGOTIATION
+            if (ssl->secure_renegotiation &&
+                ssl->secure_renegotiation->startScr) {
+                goto startScr;
+            }
+        #endif
+    }
+
+    if (sz < (int)ssl->buffers.clearOutputBuffer.length)
+        size = sz;
+    else
+        size = ssl->buffers.clearOutputBuffer.length;
+
+    XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
+
+    if (peek == 0) {
+        ssl->buffers.clearOutputBuffer.length -= size;
+        ssl->buffers.clearOutputBuffer.buffer += size;
+    }
+
+    if (ssl->buffers.clearOutputBuffer.length == 0 &&
+                                           ssl->buffers.inputBuffer.dynamicFlag)
+       ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+    WOLFSSL_LEAVE("ReceiveData()", size);
+    return size;
+}
+
+
+/* send alert message */
+int SendAlert(WOLFSSL* ssl, int severity, int type)
+{
+    byte input[ALERT_SIZE];
+    byte *output;
+    int  sendSz;
+    int  ret;
+    int  outputSz;
+    int  dtlsExtra = 0;
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+        int notifyErr = 0;
+
+        WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
+
+        if (type == close_notify) {
+            notifyErr = ZERO_RETURN;
+        } else if (severity == alert_fatal) {
+            notifyErr = FATAL_ERROR;
+        }
+
+        if (notifyErr != 0) {
+            return NotifyWriteSide(ssl, notifyErr);
+        }
+
+        return 0;
+    }
+#endif
+
+    /* if sendalert is called again for nonblocking */
+    if (ssl->options.sendAlertState != 0) {
+        ret = SendBuffered(ssl);
+        if (ret == 0)
+            ssl->options.sendAlertState = 0;
+        return ret;
+    }
+
+   #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_CB_ALERT, type);
+        }
+   #endif
+   #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls)
+           dtlsExtra = DTLS_RECORD_EXTRA;
+   #endif
+
+    /* check for available size */
+    outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra;
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* Check output buffer */
+    if (ssl->buffers.outputBuffer.buffer == NULL)
+        return BUFFER_E;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    input[0] = (byte)severity;
+    input[1] = (byte)type;
+    ssl->alert_history.last_tx.code = type;
+    ssl->alert_history.last_tx.level = severity;
+    if (severity == alert_fatal) {
+        ssl->options.isClosed = 1;  /* Don't send close_notify */
+    }
+
+    /* only send encrypted alert if handshake actually complete, otherwise
+       other side may not be able to handle it */
+    if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
+        sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE,
+                                                          alert, 0, 0, 0);
+    else {
+
+        AddRecordHeader(output, ALERT_SIZE, alert, ssl);
+        output += RECORD_HEADER_SZ;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                output += DTLS_RECORD_EXTRA;
+        #endif
+        XMEMCPY(output, input, ALERT_SIZE);
+
+        sendSz = RECORD_HEADER_SZ + ALERT_SIZE;
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls)
+                sendSz += DTLS_RECORD_EXTRA;
+        #endif
+    }
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "Alert");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO,
+                    ssl->heap);
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+    ssl->options.sendAlertState = 1;
+
+    return SendBuffered(ssl);
+}
+
+const char* wolfSSL_ERR_reason_error_string(unsigned long e)
+{
+#ifdef NO_ERROR_STRINGS
+
+    (void)e;
+    return "no support for error strings built in";
+
+#else
+
+    int error = (int)e;
+
+    /* pass to wolfCrypt */
+    if (error < MAX_CODE_E && error > MIN_CODE_E) {
+        return wc_GetErrorString(error);
+    }
+
+    switch (error) {
+
+#ifdef WOLFSSL_WPAS
+    case 0 :
+        return "ok";
+#endif
+
+    case UNSUPPORTED_SUITE :
+        return "unsupported cipher suite";
+
+    case INPUT_CASE_ERROR :
+        return "input state error";
+
+    case PREFIX_ERROR :
+        return "bad index to key rounds";
+
+    case MEMORY_ERROR :
+        return "out of memory";
+
+    case VERIFY_FINISHED_ERROR :
+        return "verify problem on finished";
+
+    case VERIFY_MAC_ERROR :
+        return "verify mac problem";
+
+    case PARSE_ERROR :
+        return "parse error on header";
+
+    case SIDE_ERROR :
+        return "wrong client/server type";
+
+    case NO_PEER_CERT :
+        return "peer didn't send cert";
+
+    case UNKNOWN_HANDSHAKE_TYPE :
+        return "weird handshake type";
+
+    case SOCKET_ERROR_E :
+        return "error state on socket";
+
+    case SOCKET_NODATA :
+        return "expected data, not there";
+
+    case INCOMPLETE_DATA :
+        return "don't have enough data to complete task";
+
+    case UNKNOWN_RECORD_TYPE :
+        return "unknown type in record hdr";
+
+    case DECRYPT_ERROR :
+        return "error during decryption";
+
+    case FATAL_ERROR :
+        return "revcd alert fatal error";
+
+    case ENCRYPT_ERROR :
+        return "error during encryption";
+
+    case FREAD_ERROR :
+        return "fread problem";
+
+    case NO_PEER_KEY :
+        return "need peer's key";
+
+    case NO_PRIVATE_KEY :
+        return "need the private key";
+
+    case NO_DH_PARAMS :
+        return "server missing DH params";
+
+    case RSA_PRIVATE_ERROR :
+        return "error during rsa priv op";
+
+    case MATCH_SUITE_ERROR :
+        return "can't match cipher suite";
+
+    case COMPRESSION_ERROR :
+        return "compression mismatch error";
+
+    case BUILD_MSG_ERROR :
+        return "build message failure";
+
+    case BAD_HELLO :
+        return "client hello malformed";
+
+    case DOMAIN_NAME_MISMATCH :
+        return "peer subject name mismatch";
+
+    case WANT_READ :
+    case WOLFSSL_ERROR_WANT_READ :
+        return "non-blocking socket wants data to be read";
+
+    case NOT_READY_ERROR :
+        return "handshake layer not ready yet, complete first";
+
+    case VERSION_ERROR :
+        return "record layer version error";
+
+    case WANT_WRITE :
+    case WOLFSSL_ERROR_WANT_WRITE :
+        return "non-blocking socket write buffer full";
+
+    case BUFFER_ERROR :
+        return "malformed buffer input error";
+
+    case VERIFY_CERT_ERROR :
+        return "verify problem on certificate";
+
+    case VERIFY_SIGN_ERROR :
+        return "verify problem based on signature";
+
+    case CLIENT_ID_ERROR :
+        return "psk client identity error";
+
+    case SERVER_HINT_ERROR:
+        return "psk server hint error";
+
+    case PSK_KEY_ERROR:
+        return "psk key callback error";
+
+    case NTRU_KEY_ERROR:
+        return "NTRU key error";
+
+    case NTRU_DRBG_ERROR:
+        return "NTRU drbg error";
+
+    case NTRU_ENCRYPT_ERROR:
+        return "NTRU encrypt error";
+
+    case NTRU_DECRYPT_ERROR:
+        return "NTRU decrypt error";
+
+    case ZLIB_INIT_ERROR:
+        return "zlib init error";
+
+    case ZLIB_COMPRESS_ERROR:
+        return "zlib compress error";
+
+    case ZLIB_DECOMPRESS_ERROR:
+        return "zlib decompress error";
+
+    case GETTIME_ERROR:
+        return "gettimeofday() error";
+
+    case GETITIMER_ERROR:
+        return "getitimer() error";
+
+    case SIGACT_ERROR:
+        return "sigaction() error";
+
+    case SETITIMER_ERROR:
+        return "setitimer() error";
+
+    case LENGTH_ERROR:
+        return "record layer length error";
+
+    case PEER_KEY_ERROR:
+        return "cant decode peer key";
+
+    case ZERO_RETURN:
+    case WOLFSSL_ERROR_ZERO_RETURN:
+        return "peer sent close notify alert";
+
+    case ECC_CURVETYPE_ERROR:
+        return "Bad ECC Curve Type or unsupported";
+
+    case ECC_CURVE_ERROR:
+        return "Bad ECC Curve or unsupported";
+
+    case ECC_PEERKEY_ERROR:
+        return "Bad ECC Peer Key";
+
+    case ECC_MAKEKEY_ERROR:
+        return "ECC Make Key failure";
+
+    case ECC_EXPORT_ERROR:
+        return "ECC Export Key failure";
+
+    case ECC_SHARED_ERROR:
+        return "ECC DHE shared failure";
+
+    case NOT_CA_ERROR:
+        return "Not a CA by basic constraint error";
+
+    case HTTP_TIMEOUT:
+        return "HTTP timeout for OCSP or CRL req";
+
+    case BAD_CERT_MANAGER_ERROR:
+        return "Bad Cert Manager error";
+
+    case OCSP_CERT_REVOKED:
+        return "OCSP Cert revoked";
+
+    case CRL_CERT_REVOKED:
+        return "CRL Cert revoked";
+
+    case CRL_MISSING:
+        return "CRL missing, not loaded";
+
+    case MONITOR_SETUP_E:
+        return "CRL monitor setup error";
+
+    case THREAD_CREATE_E:
+        return "Thread creation problem";
+
+    case OCSP_NEED_URL:
+        return "OCSP need URL";
+
+    case OCSP_CERT_UNKNOWN:
+        return "OCSP Cert unknown";
+
+    case OCSP_LOOKUP_FAIL:
+        return "OCSP Responder lookup fail";
+
+    case MAX_CHAIN_ERROR:
+        return "Maximum Chain Depth Exceeded";
+
+    case COOKIE_ERROR:
+        return "DTLS Cookie Error";
+
+    case SEQUENCE_ERROR:
+        return "DTLS Sequence Error";
+
+    case SUITES_ERROR:
+        return "Suites Pointer Error";
+
+    case OUT_OF_ORDER_E:
+        return "Out of order message, fatal";
+
+    case BAD_KEA_TYPE_E:
+        return "Bad KEA type found";
+
+    case SANITY_CIPHER_E:
+        return "Sanity check on ciphertext failed";
+
+    case RECV_OVERFLOW_E:
+        return "Receive callback returned more than requested";
+
+    case GEN_COOKIE_E:
+        return "Generate Cookie Error";
+
+    case NO_PEER_VERIFY:
+        return "Need peer certificate verify Error";
+
+    case FWRITE_ERROR:
+        return "fwrite Error";
+
+    case CACHE_MATCH_ERROR:
+        return "Cache restore header match Error";
+
+    case UNKNOWN_SNI_HOST_NAME_E:
+        return "Unrecognized host name Error";
+
+    case UNKNOWN_MAX_FRAG_LEN_E:
+        return "Unrecognized max frag len Error";
+
+    case KEYUSE_SIGNATURE_E:
+        return "Key Use digitalSignature not set Error";
+
+    case KEYUSE_ENCIPHER_E:
+        return "Key Use keyEncipherment not set Error";
+
+    case EXTKEYUSE_AUTH_E:
+        return "Ext Key Use server/client auth not set Error";
+
+    case SEND_OOB_READ_E:
+        return "Send Callback Out of Bounds Read Error";
+
+    case SECURE_RENEGOTIATION_E:
+        return "Invalid Renegotiation Error";
+
+    case SESSION_TICKET_LEN_E:
+        return "Session Ticket Too Long Error";
+
+    case SESSION_TICKET_EXPECT_E:
+        return "Session Ticket Error";
+
+    case SCR_DIFFERENT_CERT_E:
+        return "Peer sent different cert during SCR";
+
+    case SESSION_SECRET_CB_E:
+        return "Session Secret Callback Error";
+
+    case NO_CHANGE_CIPHER_E:
+        return "Finished received from peer before Change Cipher Error";
+
+    case SANITY_MSG_E:
+        return "Sanity Check on message order Error";
+
+    case DUPLICATE_MSG_E:
+        return "Duplicate HandShake message Error";
+
+    case SNI_UNSUPPORTED:
+        return "Protocol version does not support SNI Error";
+
+    case SOCKET_PEER_CLOSED_E:
+        return "Peer closed underlying transport Error";
+
+    case BAD_TICKET_KEY_CB_SZ:
+        return "Bad user session ticket key callback Size Error";
+
+    case BAD_TICKET_MSG_SZ:
+        return "Bad session ticket message Size Error";
+
+    case BAD_TICKET_ENCRYPT:
+        return "Bad user ticket callback encrypt Error";
+
+    case DH_KEY_SIZE_E:
+        return "DH key too small Error";
+
+    case SNI_ABSENT_ERROR:
+        return "No Server Name Indication extension Error";
+
+    case RSA_SIGN_FAULT:
+        return "RSA Signature Fault Error";
+
+    case HANDSHAKE_SIZE_ERROR:
+        return "Handshake message too large Error";
+
+    case UNKNOWN_ALPN_PROTOCOL_NAME_E:
+        return "Unrecognized protocol name Error";
+
+    case BAD_CERTIFICATE_STATUS_ERROR:
+        return "Bad Certificate Status Message Error";
+
+    case OCSP_INVALID_STATUS:
+        return "Invalid OCSP Status Error";
+
+    case OCSP_WANT_READ:
+        return "OCSP nonblock wants read";
+
+    case RSA_KEY_SIZE_E:
+        return "RSA key too small";
+
+    case ECC_KEY_SIZE_E:
+        return "ECC key too small";
+
+    case DTLS_EXPORT_VER_E:
+        return "Version needs updated after code change or version mismatch";
+
+    case INPUT_SIZE_E:
+        return "Input size too large Error";
+
+    case CTX_INIT_MUTEX_E:
+        return "Initialize ctx mutex error";
+
+    case EXT_MASTER_SECRET_NEEDED_E:
+        return "Extended Master Secret must be enabled to resume EMS session";
+
+    case DTLS_POOL_SZ_E:
+        return "Maximum DTLS pool size exceeded";
+
+    case DECODE_E:
+        return "Decode handshake message error";
+
+    case WRITE_DUP_READ_E:
+        return "Write dup write side can't read error";
+
+    case WRITE_DUP_WRITE_E:
+        return "Write dup read side can't write error";
+
+    case INVALID_CERT_CTX_E:
+        return "Certificate context does not match request or not empty";
+
+    case BAD_KEY_SHARE_DATA:
+        return "The Key Share data contains group that was in Client Hello";
+
+    case MISSING_HANDSHAKE_DATA:
+        return "The handshake message is missing required data";
+
+    case BAD_BINDER:
+        return "Binder value does not match value server calculated";
+
+    case EXT_NOT_ALLOWED:
+        return "Extension type not allowed in handshake message type";
+
+    case INVALID_PARAMETER:
+        return "The security parameter is invalid";
+
+    case UNSUPPORTED_EXTENSION:
+        return "TLS Extension not requested by the client";
+
+    case KEY_SHARE_ERROR:
+        return "Key share extension did not contain a valid named group";
+
+    case POST_HAND_AUTH_ERROR:
+        return "Client will not do post handshake authentication";
+
+    case HRR_COOKIE_ERROR:
+        return "Cookie does not match one sent in HelloRetryRequest";
+
+    case MCAST_HIGHWATER_CB_E:
+        return "Multicast highwater callback returned error";
+
+    case ALERT_COUNT_E:
+        return "Alert Count exceeded error";
+
+    case EXT_MISSING:
+        return "Required TLS extension missing";
+
+    default :
+        return "unknown error number";
+    }
+
+#endif /* NO_ERROR_STRINGS */
+}
+
+void SetErrorString(int error, char* str)
+{
+    XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
+}
+
+#ifndef NO_ERROR_STRINGS
+    #define SUITE_INFO(x,y,z,w) {(x),(y),(z),(w)}
+#else
+    #define SUITE_INFO(x,y,z,w) {(x),(z),(w)}
+#endif
+
+static const CipherSuiteInfo cipher_names[] =
+{
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+    SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+    SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+    SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+    SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+    SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+    SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
+    SUITE_INFO("HC128-B2B256","TLS_RSA_WITH_HC_128_B2B256",CIPHER_BYTE,TLS_RSA_WITH_HC_128_B2B256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
+    SUITE_INFO("AES128-B2B256","TLS_RSA_WITH_AES_128_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_B2B256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
+    SUITE_INFO("AES256-B2B256","TLS_RSA_WITH_AES_256_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_B2B256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+	SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+    SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+    SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_QSH
+    SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH),
+#endif
+
+#ifdef HAVE_RENEGOTIATION_INDICATION
+    SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV),
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+    SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+    SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+    SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256),
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA),
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+    SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256),
+#endif
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+    SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
+    SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384),
+#endif
+
+#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+    SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256),
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_SHA256
+    SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256),
+#endif
+
+#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+    SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256),
+#endif
+};
+
+
+/* returns the cipher_names array */
+const CipherSuiteInfo* GetCipherNames(void)
+{
+    return cipher_names;
+}
+
+
+/* returns the number of elements in the cipher_names array */
+int GetCipherNamesSize(void)
+{
+    return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo));
+}
+
+
+const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite)
+{
+    int i;
+    const char* nameInternal = NULL;
+
+    for (i = 0; i < GetCipherNamesSize(); i++) {
+        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+            (cipher_names[i].cipherSuite  == cipherSuite)) {
+            nameInternal = cipher_names[i].name;
+            break;
+        }
+    }
+    return nameInternal;
+}
+
+const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite)
+{
+#ifndef NO_ERROR_STRINGS
+    int i;
+    const char* nameIana = "NONE";
+
+    for (i = 0; i < GetCipherNamesSize(); i++) {
+        if ((cipher_names[i].cipherSuite0 == cipherSuite0) &&
+            (cipher_names[i].cipherSuite  == cipherSuite)) {
+            nameIana = cipher_names[i].name_iana;
+            break;
+        }
+    }
+    return nameIana;
+#else
+    (void)cipherSuite0;
+    (void)cipherSuite;
+    return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite);
+}
+
+const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite);
+}
+
+
+/**
+Set the enabled cipher suites.
+
+@param [out] suites Suites structure.
+@param [in]  list   List of cipher suites, only supports full name from
+                    cipher_names[] delimited by ':'.
+
+@return true on success, else false.
+*/
+int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list)
+{
+    int       ret          = 0;
+    int       idx          = 0;
+    int       haveRSAsig   = 0;
+    int       haveECDSAsig = 0;
+    int       haveAnon     = 0;
+    const int suiteSz      = GetCipherNamesSize();
+    char*     next         = (char*)list;
+
+    if (suites == NULL || list == NULL) {
+        WOLFSSL_MSG("SetCipherList parameter error");
+        return 0;
+    }
+
+    if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 ||
+                        XSTRNCMP(next, "DEFAULT", 7) == 0)
+        return 1; /* wolfSSL defualt */
+
+    do {
+        char*  current = next;
+        char   name[MAX_SUITE_NAME + 1];
+        int    i;
+        word32 length;
+
+        next   = XSTRSTR(next, ":");
+        length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */
+                                         : (word32)(next - current));
+
+        XSTRNCPY(name, current, length);
+        name[(length == sizeof(name)) ? length - 1 : length] = 0;
+
+        for (i = 0; i < suiteSz; i++) {
+            if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0) {
+            #ifdef WOLFSSL_DTLS
+                /* don't allow stream ciphers with DTLS */
+                if (ctx->method->version.major == DTLS_MAJOR) {
+                    if (XSTRSTR(name, "RC4") ||
+                        XSTRSTR(name, "HC128") ||
+                        XSTRSTR(name, "RABBIT"))
+                    {
+                        WOLFSSL_MSG("Stream ciphers not supported with DTLS");
+                        continue;
+                    }
+
+                }
+            #endif /* WOLFSSL_DTLS */
+
+                if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) {
+                    WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low");
+                    return 0; /* suites buffer not large enough, error out */
+                }
+
+                suites->suites[idx++] =
+            #ifdef WOLFSSL_TLS13
+                    (XSTRSTR(name, "TLS13"))  ? TLS13_BYTE :
+            #endif
+            #ifdef HAVE_CHACHA
+                    (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE :
+            #endif
+            #ifdef HAVE_QSH
+                    (XSTRSTR(name, "QSH"))    ? QSH_BYTE :
+            #endif
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    (XSTRSTR(name, "EC"))     ? ECC_BYTE :
+            #endif
+            #ifdef HAVE_AESCCM
+                    (XSTRSTR(name, "CCM"))    ? ECC_BYTE :
+            #endif
+                    CIPHER_BYTE; /* normal */
+
+                suites->suites[idx++] = cipher_names[i].cipherSuite;
+                /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA
+                 * suites don't necessarily have RSA in the name. */
+            #ifdef WOLFSSL_TLS13
+                if (XSTRSTR(name, "TLS13")) {
+                    haveRSAsig = 1;
+                    haveECDSAsig = 1;
+                }
+                else
+            #endif
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+                if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA"))
+                    haveECDSAsig = 1;
+                else
+            #endif
+            #ifdef HAVE_ANON
+                if (XSTRSTR(name, "ADH"))
+                    haveAnon = 1;
+                else
+            #endif
+                if (haveRSAsig == 0
+                    #ifndef NO_PSK
+                        && (XSTRSTR(name, "PSK") == NULL)
+                    #endif
+                   ) {
+                    haveRSAsig = 1;
+                }
+
+                ret = 1; /* found at least one */
+                break;
+            }
+        }
+    }
+    while (next++); /* ++ needed to skip ':' */
+
+    if (ret) {
+        int keySz = 0;
+    #ifndef NO_CERTS
+        keySz = ctx->privateKeySz;
+    #endif
+        suites->setSuites = 1;
+        suites->suiteSz   = (word16)idx;
+        InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1,
+                              keySz);
+    }
+
+    (void)ctx;
+
+    return ret;
+}
+
+
+#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS)
+void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
+                     word32 hashSigAlgoSz)
+{
+    word32 i;
+
+    ssl->suites->sigAlgo = ssl->specs.sig_algo;
+
+    /* set defaults */
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+        ssl->suites->hashAlgo = sha256_mac;
+    #ifndef NO_CERTS
+        ssl->suites->sigAlgo = ssl->buffers.keyType;
+    #endif
+    }
+#ifndef WOLFSSL_NO_TLS12
+    else if (IsAtLeastTLSv1_2(ssl)) {
+    #ifdef WOLFSSL_ALLOW_TLS_SHA1
+        ssl->suites->hashAlgo = sha_mac;
+    #else
+        ssl->suites->hashAlgo = sha256_mac;
+    #endif
+    }
+    else {
+        ssl->suites->hashAlgo = sha_mac;
+    }
+#endif
+
+    /* i+1 since peek a byte ahead for type */
+    for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) {
+        byte hashAlgo = 0, sigAlgo = 0;
+
+        DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo);
+    #ifdef HAVE_ED25519
+        if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo)
+            continue;
+
+        if (sigAlgo == ed25519_sa_algo &&
+                                      ssl->suites->sigAlgo == ecc_dsa_sa_algo) {
+            ssl->suites->sigAlgo = sigAlgo;
+            ssl->suites->hashAlgo = sha512_mac;
+            break;
+        }
+    #endif
+        if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo &&
+                                         ssl->suites->sigAlgo == rsa_sa_algo)) {
+            switch (hashAlgo) {
+                case sha_mac:
+            #ifndef NO_SHA256
+                case sha256_mac:
+            #endif
+            #ifdef WOLFSSL_SHA384
+                case sha384_mac:
+            #endif
+            #ifdef WOLFSSL_SHA512
+                case sha512_mac:
+            #endif
+                    if (hashAlgo < ssl->suites->hashAlgo)
+                        continue;
+                    ssl->suites->hashAlgo = hashAlgo;
+                    ssl->suites->sigAlgo = sigAlgo;
+                    break;
+                default:
+                    continue;
+            }
+            break;
+        }
+        else if (ssl->specs.sig_algo == 0) {
+            ssl->suites->hashAlgo = ssl->specs.mac_algorithm;
+        }
+    }
+
+}
+#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+
+    /* Initialisze HandShakeInfo */
+    void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl)
+    {
+        int i;
+
+        info->ssl = ssl;
+        info->cipherName[0] = 0;
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+            info->packetNames[i][0] = 0;
+        info->numberPackets = 0;
+        info->negotiationError = 0;
+    }
+
+    /* Set Final HandShakeInfo parameters */
+    void FinishHandShakeInfo(HandShakeInfo* info)
+    {
+        int i;
+        int sz = GetCipherNamesSize();
+
+        for (i = 0; i < sz; i++)
+            if (info->ssl->options.cipherSuite ==
+                                            (byte)cipher_names[i].cipherSuite) {
+                if (info->ssl->options.cipherSuite0 == ECC_BYTE)
+                    continue;   /* ECC suites at end */
+                XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ);
+                info->cipherName[MAX_CIPHERNAME_SZ] = '\0';
+                break;
+            }
+
+        /* error max and min are negative numbers */
+        if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR)
+            info->negotiationError = info->ssl->error;
+    }
+
+
+    /* Add name to info packet names, increase packet name count */
+    void AddPacketName(WOLFSSL* ssl, const char* name)
+    {
+    #ifdef WOLFSSL_CALLBACKS
+        HandShakeInfo* info = &ssl->handShakeInfo;
+        if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
+            char* packetName = info->packetNames[info->numberPackets];
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+            info->numberPackets++
+        }
+    #endif
+        (void)ssl;
+        (void)name;
+    }
+
+
+    #ifdef WOLFSSL_CALLBACKS
+    /* Initialisze TimeoutInfo */
+    void InitTimeoutInfo(TimeoutInfo* info)
+    {
+        int i;
+
+        info->timeoutName[0] = 0;
+        info->flags          = 0;
+
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
+            info->packets[i].packetName[0]     = 0;
+            info->packets[i].timestamp.tv_sec  = 0;
+            info->packets[i].timestamp.tv_usec = 0;
+            info->packets[i].bufferValue       = 0;
+            info->packets[i].valueSz           = 0;
+        }
+        info->numberPackets        = 0;
+        info->timeoutValue.tv_sec  = 0;
+        info->timeoutValue.tv_usec = 0;
+    }
+
+
+    /* Free TimeoutInfo */
+    void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
+    {
+        int i;
+        (void)heap;
+        for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+            if (info->packets[i].bufferValue) {
+                XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
+                info->packets[i].bufferValue = 0;
+            }
+
+    }
+
+    /* Add packet name to previsouly added packet info */
+    void AddLateName(const char* name, TimeoutInfo* info)
+    {
+        /* make sure we have a valid previous one */
+        if (info->numberPackets > 0 && info->numberPackets <
+                                                        MAX_PACKETS_HANDSHAKE) {
+            char* packetName = info->packets[info->numberPackets-1].packetName;
+            XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+            packetName[MAX_PACKETNAME_SZ] = '\0';
+        }
+    }
+
+    /* Add record header to previsouly added packet info */
+    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
+    {
+        /* make sure we have a valid previous one */
+        if (info->numberPackets > 0 && info->numberPackets <
+                                                        MAX_PACKETS_HANDSHAKE) {
+            if (info->packets[info->numberPackets - 1].bufferValue)
+                XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
+                       RECORD_HEADER_SZ);
+            else
+                XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
+                       RECORD_HEADER_SZ);
+        }
+    }
+
+    #endif /* WOLFSSL_CALLBACKS */
+
+
+    /* Add PacketInfo to TimeoutInfo
+     *
+     * ssl   WOLFSSL structure sending or receiving packet
+     * name  name of packet being sent
+     * type  type of packet being sent
+     * data  data bing sent with packet
+     * sz    size of data buffer
+     * written 1 if this packet is being written to wire, 0 if being read
+     * heap  custom heap to use for mallocs/frees
+     */
+    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
+            const byte* data, int sz, int written, void* heap)
+    {
+    #ifdef WOLFSSL_CALLBACKS
+        TimeoutInfo* info = &ssl->timeoutInfo;
+
+        if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
+            Timeval currTime;
+
+            /* may add name after */
+            if (name) {
+                char* packetName = info->packets[info->numberPackets].packetName;
+                XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ);
+                packetName[MAX_PACKETNAME_SZ] = '\0';
+            }
+
+            /* add data, put in buffer if bigger than static buffer */
+            info->packets[info->numberPackets].valueSz = sz;
+            if (sz < MAX_VALUE_SZ)
+                XMEMCPY(info->packets[info->numberPackets].value, data, sz);
+            else {
+                info->packets[info->numberPackets].bufferValue =
+                                    (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
+                if (!info->packets[info->numberPackets].bufferValue)
+                    /* let next alloc catch, just don't fill, not fatal here  */
+                    info->packets[info->numberPackets].valueSz = 0;
+                else
+                    XMEMCPY(info->packets[info->numberPackets].bufferValue,
+                           data, sz);
+            }
+            gettimeofday(&currTime, 0);
+            info->packets[info->numberPackets].timestamp.tv_sec  =
+                                                             currTime.tv_sec;
+            info->packets[info->numberPackets].timestamp.tv_usec =
+                                                             currTime.tv_usec;
+            info->numberPackets++;
+        }
+    #endif /* WOLFSSL_CALLBACKS */
+    #ifdef OPENSSL_EXTRA
+        if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) {
+            /* version from hex to dec  16 is 16^1, 256 from 16^2 and
+               4096 from 16^3 */
+            int version = (ssl->version.minor & 0X0F) +
+                          (ssl->version.minor & 0xF0) * 16  +
+                          (ssl->version.major & 0X0F) * 256 +
+                          (ssl->version.major & 0xF0) * 4096;
+
+            ssl->protoMsgCb(written, version, type,
+                         (const void *)(data + RECORD_HEADER_SZ),
+                         (size_t)(sz - RECORD_HEADER_SZ),
+                         ssl, ssl->protoMsgCtx);
+        }
+    #endif /* OPENSSL_EXTRA */
+        (void)written;
+        (void)name;
+        (void)heap;
+        (void)type;
+        (void)ssl;
+    }
+
+#endif /* WOLFSSL_CALLBACKS */
+
+#if !defined(NO_CERTS) && (defined(WOLFSSL_TLS13) || \
+                                                    !defined(NO_WOLFSSL_CLIENT))
+
+/* Decode the private key - RSA, ECC, or Ed25519 - and creates a key object.
+ * The signature type is set as well.
+ * The maximum length of a signature is returned.
+ *
+ * ssl     The SSL/TLS object.
+ * length  The length of a signature.
+ * returns 0 on success, otherwise failure.
+ */
+int DecodePrivateKey(WOLFSSL *ssl, word16* length)
+{
+    int      ret = BAD_FUNC_ARG;
+    int      keySz;
+    word32   idx;
+
+    /* make sure private key exists */
+    if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) {
+        WOLFSSL_MSG("Private key missing!");
+        ERROR_OUT(NO_PRIVATE_KEY, exit_dpk);
+    }
+
+#ifndef NO_RSA
+    ssl->hsType = DYNAMIC_TYPE_RSA;
+    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+    if (ret != 0) {
+        goto exit_dpk;
+    }
+
+    WOLFSSL_MSG("Trying RSA private key");
+
+    /* Set start of data to beginning of buffer. */
+    idx = 0;
+    /* Decode the key assuming it is an RSA private key. */
+    ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+    if (ret == 0) {
+        WOLFSSL_MSG("Using RSA private key");
+
+        /* It worked so check it meets minimum key size requirements. */
+        keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+        if (keySz < 0) { /* check if keySz has error case */
+            ERROR_OUT(keySz, exit_dpk);
+        }
+
+        if (keySz < ssl->options.minRsaKeySz) {
+            WOLFSSL_MSG("RSA key size too small");
+            ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk);
+        }
+
+        /* Return the maximum signature length. */
+        *length = (word16)keySz;
+
+        goto exit_dpk;
+    }
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+#ifndef NO_RSA
+    FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+#endif /* !NO_RSA */
+
+    ssl->hsType = DYNAMIC_TYPE_ECC;
+    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+    if (ret != 0) {
+        goto exit_dpk;
+    }
+
+#ifndef NO_RSA
+    WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
+#else
+    WOLFSSL_MSG("Trying ECC private key");
+#endif
+
+    /* Set start of data to beginning of buffer. */
+    idx = 0;
+    /* Decode the key assuming it is an ECC private key. */
+    ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                                 (ecc_key*)ssl->hsKey,
+                                 ssl->buffers.key->length);
+    if (ret == 0) {
+        WOLFSSL_MSG("Using ECC private key");
+
+        /* Check it meets the minimum ECC key size requirements. */
+        keySz = wc_ecc_size((ecc_key*)ssl->hsKey);
+        if (keySz < ssl->options.minEccKeySz) {
+            WOLFSSL_MSG("ECC key size too small");
+            ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+        }
+
+        /* Return the maximum signature length. */
+        *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
+
+        goto exit_dpk;
+    }
+#endif
+#ifdef HAVE_ED25519
+    #if !defined(NO_RSA) || defined(HAVE_ECC)
+        FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+    #endif
+
+    ssl->hsType = DYNAMIC_TYPE_ED25519;
+    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+    if (ret != 0) {
+        goto exit_dpk;
+    }
+
+    #ifdef HAVE_ECC
+        WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work");
+    #elif !defined(NO_RSA)
+        WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work");
+    #else
+        WOLFSSL_MSG("Trying ED25519 private key");
+    #endif
+
+    /* Set start of data to beginning of buffer. */
+    idx = 0;
+    /* Decode the key assuming it is an ED25519 private key. */
+    ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
+                                     (ed25519_key*)ssl->hsKey,
+                                     ssl->buffers.key->length);
+    if (ret == 0) {
+        WOLFSSL_MSG("Using ED25519 private key");
+
+        /* Check it meets the minimum ECC key size requirements. */
+        if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) {
+            WOLFSSL_MSG("ED25519 key size too small");
+            ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk);
+        }
+
+        /* Return the maximum signature length. */
+        *length = ED25519_SIG_SIZE;
+
+        goto exit_dpk;
+    }
+#endif /* HAVE_ED25519 */
+
+    (void)idx;
+    (void)keySz;
+    (void)length;
+exit_dpk:
+    return ret;
+}
+
+#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
+
+/* client only parts */
+#ifndef NO_WOLFSSL_CLIENT
+
+#ifndef WOLFSSL_NO_TLS12
+
+    /* handle generation of client_hello (1) */
+    int SendClientHello(WOLFSSL* ssl)
+    {
+        byte              *output;
+        word32             length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int                sendSz;
+        int                idSz = ssl->options.resuming
+                                ? ssl->session.sessionIDSz
+                                : 0;
+        int                ret;
+        word16             extSz = 0;
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            return SendTls13ClientHello(ssl);
+#endif
+
+        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+        WOLFSSL_ENTER("SendClientHello");
+
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Bad suites pointer in SendClientHello");
+            return SUITES_ERROR;
+        }
+
+#ifdef HAVE_SESSION_TICKET
+        if (ssl->options.resuming && ssl->session.ticketLen > 0) {
+            SessionTicket* ticket;
+
+            ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket,
+                                             ssl->session.ticketLen, ssl->heap);
+            if (ticket == NULL) return MEMORY_E;
+
+            ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap);
+            if (ret != WOLFSSL_SUCCESS) return ret;
+
+            idSz = 0;
+        }
+#endif
+        length = VERSION_SZ + RAN_LEN
+               + idSz + ENUM_LEN
+               + ssl->suites->suiteSz + SUITE_LEN
+               + COMP_LEN + ENUM_LEN;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        /* auto populate extensions supported unless user defined */
+        if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
+            return ret;
+    #ifdef HAVE_QSH
+        if (QSH_Init(ssl) != 0)
+            return MEMORY_E;
+    #endif
+        extSz = 0;
+        ret = TLSX_GetRequestSize(ssl, client_hello, &extSz);
+        if (ret != 0)
+            return ret;
+        length += extSz;
+#else
+        if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
+            extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
+                   + ssl->suites->hashSigAlgoSz;
+#ifdef HAVE_EXTENDED_MASTER
+        if (ssl->options.haveEMS)
+            extSz += HELLO_EXT_SZ;
+#endif
+        if (extSz != 0)
+            length += extSz + HELLO_EXT_SZ_SZ;
+#endif
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            length += ENUM_LEN;   /* cookie */
+            if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz;
+            sendSz  = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
+            idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+        }
+#endif
+
+        if (IsEncryptionOn(ssl, 1))
+            sendSz += MAX_MSG_EXTRA;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, client_hello, ssl);
+
+        /* client hello, first version */
+        output[idx++] = ssl->version.major;
+        output[idx++] = ssl->version.minor;
+        ssl->chVersion = ssl->version;  /* store in case changed */
+
+        /* then random */
+        if (ssl->options.connectState == CONNECT_BEGIN) {
+            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
+            if (ret != 0)
+                return ret;
+
+            /* store random */
+            XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
+        } else {
+#ifdef WOLFSSL_DTLS
+            /* send same random on hello again */
+            XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
+#endif
+        }
+        idx += RAN_LEN;
+
+        /* then session id */
+        output[idx++] = (byte)idSz;
+        if (idSz) {
+            XMEMCPY(output + idx, ssl->session.sessionID,
+                                                      ssl->session.sessionIDSz);
+            idx += ssl->session.sessionIDSz;
+        }
+
+        /* then DTLS cookie */
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            byte cookieSz = ssl->arrays->cookieSz;
+
+            output[idx++] = cookieSz;
+            if (cookieSz) {
+                XMEMCPY(&output[idx], ssl->arrays->cookie, cookieSz);
+                idx += cookieSz;
+            }
+        }
+#endif
+        /* then cipher suites */
+        c16toa(ssl->suites->suiteSz, output + idx);
+        idx += OPAQUE16_LEN;
+        XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
+        idx += ssl->suites->suiteSz;
+
+        /* last, compression */
+        output[idx++] = COMP_LEN;
+        if (ssl->options.usingCompression)
+            output[idx++] = ZLIB_COMPRESSION;
+        else
+            output[idx++] = NO_COMPRESSION;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        extSz = 0;
+        ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz);
+        if (ret != 0)
+            return ret;
+        idx += extSz;
+
+        (void)idx; /* suppress analyzer warning, keep idx current */
+#else
+        if (extSz != 0) {
+            c16toa(extSz, output + idx);
+            idx += HELLO_EXT_SZ_SZ;
+
+            if (IsAtLeastTLSv1_2(ssl)) {
+                if (ssl->suites->hashSigAlgoSz) {
+                    int i;
+                    /* extension type */
+                    c16toa(HELLO_EXT_SIG_ALGO, output + idx);
+                    idx += HELLO_EXT_TYPE_SZ;
+                    /* extension data length */
+                    c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz,
+                           output + idx);
+                    idx += HELLO_EXT_SZ_SZ;
+                    /* sig algos length */
+                    c16toa(ssl->suites->hashSigAlgoSz, output + idx);
+                    idx += HELLO_EXT_SIGALGO_SZ;
+                    for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
+                        output[idx] = ssl->suites->hashSigAlgo[i];
+                    }
+                }
+            }
+#ifdef HAVE_EXTENDED_MASTER
+            if (ssl->options.haveEMS) {
+                c16toa(HELLO_EXT_EXTMS, output + idx);
+                idx += HELLO_EXT_TYPE_SZ;
+                c16toa(0, output + idx);
+                idx += HELLO_EXT_SZ_SZ;
+            }
+#endif
+        }
+#endif
+
+        if (IsEncryptionOn(ssl, 1)) {
+            byte* input;
+            int   inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */
+
+            input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+            if (input == NULL)
+                return MEMORY_E;
+
+            XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz);
+            sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
+                                  handshake, 1, 0, 0);
+            XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+            if (sendSz < 0)
+                return sendSz;
+        } else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+            ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+        }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                    return ret;
+            }
+        #endif
+
+        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+#ifdef OPENSSL_EXTRA
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+		if (ssl->CBIS != NULL)
+			ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+#endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendClientHello", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
+
+        return ret;
+    }
+
+
+    /* handle processing of DTLS hello_verify_request (3) */
+    static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input,
+                                    word32* inOutIdx, word32 size)
+    {
+        ProtocolVersion pv;
+        byte            cookieSz;
+        word32          begin = *inOutIdx;
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest");
+        if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
+#endif
+
+#ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            DtlsMsgPoolReset(ssl);
+        }
+#endif
+
+        if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size)
+            return BUFFER_ERROR;
+
+        XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if (pv.major != DTLS_MAJOR ||
+                         (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR))
+            return VERSION_ERROR;
+
+        cookieSz = input[(*inOutIdx)++];
+
+        if (cookieSz) {
+            if ((*inOutIdx - begin) + cookieSz > size)
+                return BUFFER_ERROR;
+
+#ifdef WOLFSSL_DTLS
+            if (cookieSz <= MAX_COOKIE_LEN) {
+                XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz);
+                ssl->arrays->cookieSz = cookieSz;
+            }
+#endif
+            *inOutIdx += cookieSz;
+        }
+
+        ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+        return 0;
+    }
+
+
+    static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl)
+    {
+        int ret = 0;
+
+#ifdef HAVE_SECRET_CALLBACK
+        /* If a session secret callback exists, we are using that
+         * key instead of the saved session key. */
+        ret = ret || (ssl->sessionSecretCb != NULL);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+        /* server may send blank ticket which may not be expected to indicate
+         * existing one ok but will also be sending a new one */
+        ret = ret || (ssl->session.ticketLen > 0);
+#endif
+
+        ret = ret ||
+              (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
+                                          ssl->session.sessionID, ID_LEN) == 0);
+
+        return ret;
+    }
+
+    /* Check the version in the received message is valid and set protocol
+     * version to use.
+     *
+     * ssl  The SSL/TLS object.
+     * pv   The protocol version from the packet.
+     * returns 0 on success, otherwise failure.
+     */
+    int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv)
+    {
+#ifdef WOLFSSL_TLS13
+    #ifndef WOLFSSL_TLS13_FINAL
+        /* TODO: [TLS13] Remove this.
+         * Translate the draft TLS v1.3 version to final version.
+         */
+        if (pv.major == TLS_DRAFT_MAJOR) {
+            pv.major = SSLv3_MAJOR;
+            pv.minor = TLSv1_3_MINOR;
+        }
+    #endif
+#endif
+
+        #ifdef OPENSSL_EXTRA
+        if (ssl->CBIS != NULL) {
+            ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS);
+        }
+        #endif
+
+        if (pv.minor > ssl->version.minor) {
+            WOLFSSL_MSG("Server using higher version, fatal error");
+            return VERSION_ERROR;
+        }
+        if (pv.minor < ssl->version.minor) {
+            WOLFSSL_MSG("server using lower version");
+
+            /* Check for downgrade attack. */
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("\tno downgrade allowed, fatal error");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                if (ssl->secure_renegotiation &&
+                                         ssl->secure_renegotiation->enabled &&
+                                         ssl->options.handShakeDone) {
+                    WOLFSSL_MSG("Server changed version during scr");
+                    return VERSION_ERROR;
+                }
+            #endif
+
+            /* Checks made - OK to downgrade. */
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                /* turn off tls 1.1+ */
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+        }
+
+#ifdef OPENSSL_EXTRA
+        /* check if option is set to not allow the current version
+         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
+        if (!ssl->options.dtls && ssl->options.downgrade &&
+                ssl->options.mask > 0) {
+            if (ssl->version.minor == TLSv1_2_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+                ssl->version.minor = TLSv1_1_MINOR;
+            }
+            if (ssl->version.minor == TLSv1_1_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = TLSv1_MINOR;
+            }
+            if (ssl->version.minor == TLSv1_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = SSLv3_MINOR;
+            }
+            if (ssl->version.minor == SSLv3_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->version.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+        }
+#endif
+
+        return 0;
+    }
+
+    /* handle processing of server_hello (2) */
+    int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                      word32 helloSz)
+    {
+        byte            cs0;   /* cipher suite bytes 0, 1 */
+        byte            cs1;
+        ProtocolVersion pv;
+        byte            compression;
+        word32          i = *inOutIdx;
+        word32          begin = i;
+        int             ret;
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
+        WOLFSSL_ENTER("DoServerHello");
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
+        if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+
+        /* protocol version, random and session id length check */
+        if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        /* protocol version */
+        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+        i += OPAQUE16_LEN;
+
+        ret = CheckVersion(ssl, pv);
+        if (ret != 0)
+            return ret;
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(pv)) {
+            byte type = server_hello;
+            return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type);
+        }
+#endif
+
+        /* random */
+        XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
+        i += RAN_LEN;
+
+        /* session id */
+        ssl->arrays->sessionIDSz = input[i++];
+
+        if (ssl->arrays->sessionIDSz > ID_LEN) {
+            WOLFSSL_MSG("Invalid session ID size");
+            ssl->arrays->sessionIDSz = 0;
+            return BUFFER_ERROR;
+        }
+        else if (ssl->arrays->sessionIDSz) {
+            if ((i - begin) + ssl->arrays->sessionIDSz > helloSz)
+                return BUFFER_ERROR;
+
+            XMEMCPY(ssl->arrays->sessionID, input + i,
+                                                      ssl->arrays->sessionIDSz);
+            i += ssl->arrays->sessionIDSz;
+            ssl->options.haveSessionId = 1;
+        }
+
+
+        /* suite and compression */
+        if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        cs0 = input[i++];
+        cs1 = input[i++];
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+        if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
+                                         ssl->options.handShakeDone) {
+            if (ssl->options.cipherSuite0 != cs0 ||
+                ssl->options.cipherSuite  != cs1) {
+                WOLFSSL_MSG("Server changed cipher suite during scr");
+                return MATCH_SUITE_ERROR;
+            }
+        }
+#endif
+
+        ssl->options.cipherSuite0 = cs0;
+        ssl->options.cipherSuite  = cs1;
+        compression = input[i++];
+
+        if (compression != NO_COMPRESSION && !ssl->options.usingCompression) {
+            WOLFSSL_MSG("Server forcing compression w/o support");
+            return COMPRESSION_ERROR;
+        }
+
+        if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) {
+            WOLFSSL_MSG("Server refused compression, turning off");
+            ssl->options.usingCompression = 0;  /* turn off if server refused */
+        }
+
+        *inOutIdx = i;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        if ( (i - begin) < helloSz) {
+            if (TLSX_SupportExtensions(ssl)) {
+                word16 totalExtSz;
+
+                if ((i - begin) + OPAQUE16_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                ato16(&input[i], &totalExtSz);
+                i += OPAQUE16_LEN;
+
+                if ((i - begin) + totalExtSz > helloSz)
+                    return BUFFER_ERROR;
+
+                if ((ret = TLSX_Parse(ssl, (byte *) input + i,
+                                                          totalExtSz, 0, NULL)))
+                    return ret;
+
+                i += totalExtSz;
+                *inOutIdx = i;
+            }
+            else
+                *inOutIdx = begin + helloSz; /* skip extensions */
+        }
+        else
+            ssl->options.haveEMS = 0; /* If no extensions, no EMS */
+#else
+        {
+            int allowExt = 0;
+            byte pendingEMS = 0;
+
+            if ( (i - begin) < helloSz) {
+                if (ssl->version.major == SSLv3_MAJOR &&
+                    ssl->version.minor >= TLSv1_MINOR) {
+
+                    allowExt = 1;
+                }
+#ifdef WOLFSSL_DTLS
+                if (ssl->version.major == DTLS_MAJOR)
+                    allowExt = 1;
+#endif
+
+                if (allowExt) {
+                    word16 totalExtSz;
+
+                    if ((i - begin) + OPAQUE16_LEN > helloSz)
+                        return BUFFER_ERROR;
+
+                    ato16(&input[i], &totalExtSz);
+                    i += OPAQUE16_LEN;
+
+                    if ((i - begin) + totalExtSz > helloSz)
+                        return BUFFER_ERROR;
+
+                    while (totalExtSz) {
+                        word16 extId, extSz;
+
+                        if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
+                            return BUFFER_ERROR;
+
+                        ato16(&input[i], &extId);
+                        i += OPAQUE16_LEN;
+                        ato16(&input[i], &extSz);
+                        i += OPAQUE16_LEN;
+
+                        if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
+                            return BUFFER_ERROR;
+
+                        if (extId == HELLO_EXT_EXTMS)
+                            pendingEMS = 1;
+                        else
+                            i += extSz;
+
+                        totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+                    }
+
+                    *inOutIdx = i;
+                }
+                else
+                    *inOutIdx = begin + helloSz; /* skip extensions */
+            }
+
+            if (!pendingEMS && ssl->options.haveEMS)
+                ssl->options.haveEMS = 0;
+        }
+#endif
+
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+        if (IsEncryptionOn(ssl, 0)) {
+            *inOutIdx += ssl->keys.padSz;
+        }
+
+#ifdef HAVE_SECRET_CALLBACK
+        if (ssl->sessionSecretCb != NULL) {
+            int secretSz = SECRET_LEN;
+            ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
+                                              &secretSz, ssl->sessionSecretCtx);
+            if (ret != 0 || secretSz != SECRET_LEN)
+                return SESSION_SECRET_CB_E;
+        }
+#endif /* HAVE_SECRET_CALLBACK */
+
+        ret = CompleteServerHello(ssl);
+
+        WOLFSSL_LEAVE("DoServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+        return ret;
+    }
+
+    int CompleteServerHello(WOLFSSL* ssl)
+    {
+        int ret;
+
+        if (!ssl->options.resuming) {
+            byte* down = ssl->arrays->serverRandom + RAN_LEN -
+                                                         TLS13_DOWNGRADE_SZ - 1;
+            byte  vers = ssl->arrays->serverRandom[RAN_LEN - 1];
+    #ifdef WOLFSSL_TLS13
+            if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
+                /* TLS v1.3 capable client not allowed to downgrade when
+                 * connecting to TLS v1.3 capable server unless cipher suite
+                 * demands it.
+                 */
+                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+                                                     (vers == 0 || vers == 1)) {
+                    SendAlert(ssl, alert_fatal, illegal_parameter);
+                    return VERSION_ERROR;
+                }
+            }
+            else
+    #endif
+            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+                             ssl->ctx->method->version.minor == TLSv1_2_MINOR) {
+                /* TLS v1.2 capable client not allowed to downgrade when
+                 * connecting to TLS v1.2 capable server.
+                 */
+                if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 &&
+                                                                    vers == 0) {
+                    SendAlert(ssl, alert_fatal, illegal_parameter);
+                    return VERSION_ERROR;
+                }
+            }
+        }
+        else {
+            if (DSH_CheckSessionId(ssl)) {
+                if (SetCipherSpecs(ssl) == 0) {
+
+                    XMEMCPY(ssl->arrays->masterSecret,
+                            ssl->session.masterSecret, SECRET_LEN);
+            #ifdef NO_OLD_TLS
+                    ret = DeriveTlsKeys(ssl);
+            #else
+                    ret = -1; /* default value */
+                #ifndef NO_TLS
+                    if (ssl->options.tls)
+                        ret = DeriveTlsKeys(ssl);
+                #endif
+                    if (!ssl->options.tls)
+                        ret = DeriveKeys(ssl);
+            #endif /* NO_OLD_TLS */
+                    ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+                    return ret;
+                }
+                else {
+                    WOLFSSL_MSG("Unsupported cipher suite, DoServerHello");
+                    return UNSUPPORTED_SUITE;
+                }
+            }
+            else {
+                WOLFSSL_MSG("Server denied resumption attempt");
+                ssl->options.resuming = 0; /* server denied resumption try */
+            }
+        }
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            DtlsMsgPoolReset(ssl);
+        }
+    #endif
+
+        return SetCipherSpecs(ssl);
+    }
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+
+    /* Make sure client setup is valid for this suite, true on success */
+    int VerifyClientSuite(WOLFSSL* ssl)
+    {
+        int  havePSK = 0;
+        byte first   = ssl->options.cipherSuite0;
+        byte second  = ssl->options.cipherSuite;
+
+        WOLFSSL_ENTER("VerifyClientSuite");
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+
+        if (CipherRequires(first, second, REQUIRES_PSK)) {
+            WOLFSSL_MSG("Requires PSK");
+            if (havePSK == 0) {
+                WOLFSSL_MSG("Don't have PSK");
+                return 0;
+            }
+        }
+
+        return 1;  /* success */
+    }
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef NO_CERTS
+    /* handle processing of certificate_request (13) */
+    static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*
+                                    inOutIdx, word32 size)
+    {
+        word16 len;
+        word32 begin = *inOutIdx;
+
+        WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
+        WOLFSSL_ENTER("DoCertificateRequest");
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateRequest");
+            if (ssl->toInfoOn)
+                AddLateName("CertificateRequest", &ssl->timeoutInfo);
+        #endif
+
+        if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
+            return BUFFER_ERROR;
+
+        len = input[(*inOutIdx)++];
+
+        if ((*inOutIdx - begin) + len > size)
+            return BUFFER_ERROR;
+
+        /* types, read in here */
+        *inOutIdx += len;
+
+        /* signature and hash signature algorithm */
+        if (IsAtLeastTLSv1_2(ssl)) {
+            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+                return BUFFER_ERROR;
+
+            ato16(input + *inOutIdx, &len);
+            *inOutIdx += OPAQUE16_LEN;
+
+            if ((*inOutIdx - begin) + len > size)
+                return BUFFER_ERROR;
+
+            PickHashSigAlgo(ssl, input + *inOutIdx, len);
+            *inOutIdx += len;
+    #ifdef WC_RSA_PSS
+            ssl->pssAlgo = 0;
+            if (ssl->suites->sigAlgo == rsa_pss_sa_algo)
+                ssl->pssAlgo |= 1 << ssl->suites->hashAlgo;
+    #endif
+        }
+
+        /* authorities */
+        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+            return BUFFER_ERROR;
+
+        ato16(input + *inOutIdx, &len);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if ((*inOutIdx - begin) + len > size)
+            return BUFFER_ERROR;
+
+        while (len) {
+            word16 dnSz;
+
+            if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+                return BUFFER_ERROR;
+
+            ato16(input + *inOutIdx, &dnSz);
+            *inOutIdx += OPAQUE16_LEN;
+
+            if ((*inOutIdx - begin) + dnSz > size)
+                return BUFFER_ERROR;
+
+            *inOutIdx += dnSz;
+            len -= OPAQUE16_LEN + dnSz;
+        }
+
+        /* don't send client cert or cert verify if user hasn't provided
+           cert and private key */
+        if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) {
+        #ifdef HAVE_PK_CALLBACKS
+            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                WOLFSSL_MSG("Using PK for client private key");
+                ssl->options.sendVerify = SEND_CERT;
+            }
+        #endif
+            if (ssl->buffers.key && ssl->buffers.key->buffer) {
+                ssl->options.sendVerify = SEND_CERT;
+            }
+        }
+	#ifdef OPENSSL_EXTRA
+		else
+	#else
+        else if (IsTLS(ssl))
+	#endif
+        {
+            ssl->options.sendVerify = SEND_BLANK_CERT;
+        }
+
+        if (IsEncryptionOn(ssl, 0))
+            *inOutIdx += ssl->keys.padSz;
+
+        WOLFSSL_LEAVE("DoCertificateRequest", 0);
+        WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
+
+        return 0;
+    }
+#endif /* !NO_CERTS */
+
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+
+    static int CheckCurveId(int tlsCurveId)
+    {
+        int ret = ECC_CURVE_ERROR;
+
+        switch (tlsCurveId) {
+    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_SECPR2
+            case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID;
+        #endif /* HAVE_ECC_SECPR2 */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_CURVE25519
+            case WOLFSSL_ECC_X25519: return ECC_X25519_OID;
+        #endif
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID;
+        #endif /* HAVE_ECC_KOBLITZ */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_BRAINPOOL
+            case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID;
+        #endif /* !NO_ECC_SECP */
+    #endif
+        }
+
+        return ret;
+    }
+
+#endif /* HAVE_ECC */
+
+
+/* Persistable DoServerKeyExchange arguments */
+typedef struct DskeArgs {
+    byte*  output; /* not allocated */
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+    byte*  verifySig;
+#endif
+    word32 idx;
+    word32 begin;
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+    word16 verifySigSz;
+#endif
+    word16 sigSz;
+    byte   sigAlgo;
+    byte   hashAlgo;
+} DskeArgs;
+
+static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs)
+{
+    DskeArgs* args = (DskeArgs*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+    if (args->verifySig) {
+        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->verifySig = NULL;
+    }
+#endif
+}
+
+/* handle processing of server_key_exchange (12) */
+static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
+                               word32* inOutIdx, word32 size)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    DskeArgs* args = (DskeArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    DskeArgs  args[1];
+#endif
+
+    (void)input;
+    (void)size;
+
+    WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
+    WOLFSSL_ENTER("DoServerKeyExchange");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_dske;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(DskeArgs));
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+        args->sigAlgo = ssl->specs.sig_algo;
+        args->hashAlgo = sha_mac;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeDskeArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "ServerKeyExchange");
+            if (ssl->toInfoOn)
+                AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
+        #endif
+
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                    srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+                    args->idx += length;
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    word16 length;
+
+                    /* p */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    if (length < ssl->options.minDhKeySz) {
+                        WOLFSSL_MSG("Server using a DH key that is too small");
+                        SendAlert(ssl, alert_fatal, handshake_failure);
+                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
+                    }
+                    if (length > ssl->options.maxDhKeySz) {
+                        WOLFSSL_MSG("Server using a DH key that is too big");
+                        SendAlert(ssl, alert_fatal, handshake_failure);
+                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_P.buffer =
+                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_P.buffer) {
+                        ssl->buffers.serverDH_P.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+
+                    ssl->options.dhKeySz = length;
+
+                    /* g */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_G.buffer =
+                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_G.buffer) {
+                        ssl->buffers.serverDH_G.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+
+                    ssl->buffers.weOwnDH = 1;
+
+                    /* pub */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_Pub.buffer =
+                        (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_Pub.buffer) {
+                        ssl->buffers.serverDH_Pub.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+                    break;
+                }
+            #endif /* !NO_DH */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                case ecc_diffie_hellman_kea:
+                {
+                    byte b;
+                #ifdef HAVE_ECC
+                    int curveId;
+                #endif
+                    int curveOid;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+                                                        OPAQUE8_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    b = input[args->idx++];
+                    if (b != named_curve) {
+                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+                    }
+
+                    args->idx += 1;   /* curve type, eat leading 0 */
+                    b = input[args->idx++];
+                    if ((curveOid = CheckCurveId(b)) < 0) {
+                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+                    }
+                    ssl->ecdhCurveOID = curveOid;
+
+                    length = input[args->idx++];
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->peerX25519Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           (void**)&ssl->peerX25519Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerX25519KeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if (wc_curve25519_import_public_ex(input + args->idx,
+                                length, ssl->peerX25519Key,
+                                EC25519_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX25519KeyPresent = 1;
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    if (ssl->peerEccKey == NULL) {
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                       (void**)&ssl->peerEccKey);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    } else if (ssl->peerEccKeyPresent) {
+                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+                    if (wc_ecc_import_x963_ex(input + args->idx, length,
+                                        ssl->peerEccKey, curveId) != 0) {
+                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                    }
+
+                    args->idx += length;
+                    ssl->peerEccKeyPresent = 1;
+                    break;
+                #endif
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+                    args->idx += length;
+
+                    /* p */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    if (length < ssl->options.minDhKeySz) {
+                        WOLFSSL_MSG("Server using a DH key that is too small");
+                        SendAlert(ssl, alert_fatal, handshake_failure);
+                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
+                    }
+                    if (length > ssl->options.maxDhKeySz) {
+                        WOLFSSL_MSG("Server using a DH key that is too big");
+                        SendAlert(ssl, alert_fatal, handshake_failure);
+                        ERROR_OUT(DH_KEY_SIZE_E, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length,
+                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_P.buffer) {
+                        ssl->buffers.serverDH_P.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+
+                    ssl->options.dhKeySz = length;
+
+                    /* g */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length,
+                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_G.buffer) {
+                        ssl->buffers.serverDH_G.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+
+                    ssl->buffers.weOwnDH = 1;
+
+                    /* pub */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length,
+                                                ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    if (ssl->buffers.serverDH_Pub.buffer) {
+                        ssl->buffers.serverDH_Pub.length = length;
+                    }
+                    else {
+                        ERROR_OUT(MEMORY_ERROR, exit_dske);
+                    }
+
+                    XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx,
+                                                                        length);
+                    args->idx += length;
+                    break;
+                }
+            #endif /* !NO_DH || !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    byte b;
+                    int curveOid, curveId;
+                    int srvHintLen;
+                    word16 length;
+
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &length);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* get PSK server hint from the wire */
+                    srvHintLen = min(length, MAX_PSK_ID_LEN);
+                    XMEMCPY(ssl->arrays->server_hint, input + args->idx,
+                                                                    srvHintLen);
+                    ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+
+                    args->idx += length;
+
+                    if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+                        OPAQUE8_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* Check curve name and ID */
+                    b = input[args->idx++];
+                    if (b != named_curve) {
+                        ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
+                    }
+
+                    args->idx += 1;   /* curve type, eat leading 0 */
+                    b = input[args->idx++];
+                    if ((curveOid = CheckCurveId(b)) < 0) {
+                        ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
+                    }
+
+                    length = input[args->idx++];
+                    if ((args->idx - args->begin) + length > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->peerX25519Key == NULL) {
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           (void**)&ssl->peerX25519Key);
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        } else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                           ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dske;
+                            }
+                        }
+
+                        if (wc_curve25519_import_public_ex(input + args->idx,
+                                length, ssl->peerX25519Key,
+                                EC25519_LITTLE_ENDIAN) != 0) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                        }
+
+                        args->idx += length;
+                        ssl->peerX25519KeyPresent = 1;
+                        break;
+                    }
+                #endif
+
+                    if (ssl->peerEccKey == NULL) {
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                 (void**)&ssl->peerEccKey);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    } else if (ssl->peerEccKeyPresent) {
+                        ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+                        ssl->peerEccKeyPresent = 0;
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
+                    if (wc_ecc_import_x963_ex(input + args->idx, length,
+                        ssl->peerEccKey, curveId) != 0) {
+                        ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
+                    }
+
+                    args->idx += length;
+                    ssl->peerEccKeyPresent = 1;
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    enum wc_HashType hashType;
+                    word16  verifySz;
+
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    verifySz = (word16)(args->idx - args->begin);
+                    if (verifySz > MAX_DH_SZ) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                        if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN >
+                                                                        size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dske);
+                        }
+
+                        DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+                                     &args->sigAlgo);
+                        args->idx += 2;
+                        hashType = HashAlgoToType(args->hashAlgo);
+                        if (hashType == WC_HASH_TYPE_NONE) {
+                            ERROR_OUT(ALGO_ID_E, exit_dske);
+                        }
+                    } else {
+                        /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (args->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_dske);
+                        #endif
+                    }
+
+                    /* signature */
+                    if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    ato16(input + args->idx, &args->verifySigSz);
+                    args->idx += OPAQUE16_LEN;
+
+                    if ((args->idx - args->begin) + args->verifySigSz > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dske);
+                    }
+
+                    /* buffer for signature */
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_dske);
+                    }
+                    ssl->buffers.sig.length = SEED_LEN + verifySz;
+
+                    /* build message to hash */
+                    XMEMCPY(ssl->buffers.sig.buffer,
+                        ssl->arrays->clientRandom, RAN_LEN);
+                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN],
+                        ssl->arrays->serverRandom, RAN_LEN);
+                    XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2],
+                        input + args->begin, verifySz); /* message */
+
+                    if (args->sigAlgo != ed25519_sa_algo) {
+                        int digest_sz = wc_HashGetDigestSize(hashType);
+                        if (digest_sz <= 0) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dske);
+                        }
+                        ssl->buffers.digest.length = (unsigned int)digest_sz;
+
+                        /* buffer for hash */
+                        ssl->buffers.digest.buffer = (byte*)XMALLOC(
+                            ssl->buffers.digest.length, ssl->heap,
+                            DYNAMIC_TYPE_DIGEST);
+                        if (ssl->buffers.digest.buffer == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_dske);
+                        }
+
+                        /* Perform hash */
+                        ret = wc_Hash(hashType, ssl->buffers.sig.buffer,
+                                                    ssl->buffers.sig.length,
+                                                    ssl->buffers.digest.buffer,
+                                                    ssl->buffers.digest.length);
+                        if (ret != 0) {
+                            goto exit_dske;
+                        }
+                    }
+
+                    switch (args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            if (ssl->peerRsaKey == NULL ||
+                                                    !ssl->peerRsaKeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                        {
+                            if (!ssl->peerEccDsaKeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                        {
+                            if (!ssl->peerEd25519KeyPresent) {
+                                ERROR_OUT(NO_PEER_KEY, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* HAVE_ED25519 */
+
+                    default:
+                        ret = ALGO_ID_E;
+                    } /* switch (args->sigAlgo) */
+
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    if (args->verifySig == NULL) {
+                        args->verifySig = (byte*)XMALLOC(args->verifySigSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->verifySig == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_dske);
+                        }
+                        XMEMCPY(args->verifySig, input + args->idx,
+                                                            args->verifySigSz);
+                    }
+
+                    switch (args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            ret = RsaVerify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                &args->output,
+                                args->sigAlgo, args->hashAlgo,
+                                ssl->peerRsaKey,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerRsaKey
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                            if (ret >= 0) {
+                                args->sigSz = (word16)ret;
+                                ret = 0;
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                        {
+                            ret = EccVerify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                ssl->buffers.digest.buffer,
+                                ssl->buffers.digest.length,
+                                ssl->peerEccDsaKey,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerEccDsaKey
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                            /* peerEccDsaKey */
+                            FreeKey(ssl, DYNAMIC_TYPE_ECC,
+                                                   (void**)&ssl->peerEccDsaKey);
+                            ssl->peerEccDsaKeyPresent = 0;
+                            break;
+                        }
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                        {
+                            ret = Ed25519Verify(ssl,
+                                args->verifySig, args->verifySigSz,
+                                ssl->buffers.sig.buffer,
+                                ssl->buffers.sig.length,
+                                ssl->peerEd25519Key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                &ssl->buffers.peerEd25519Key
+                            #else
+                                NULL
+                            #endif
+                            );
+
+                            /* peerEccDsaKey */
+                            FreeKey(ssl, DYNAMIC_TYPE_ED25519,
+                                                  (void**)&ssl->peerEd25519Key);
+                            ssl->peerEd25519KeyPresent = 0;
+                            break;
+                        }
+                    #endif /* HAVE_ED25519 */
+
+                    default:
+                        ret = ALGO_ID_E;
+                    } /* switch (sigAlgo) */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            switch(ssl->specs.kea)
+            {
+                case psk_kea:
+                case dhe_psk_kea:
+                case ecdhe_psk_kea:
+                {
+                    /* Nothing to do in this sub-state */
+                    break;
+                }
+
+                case diffie_hellman_kea:
+                case ecc_diffie_hellman_kea:
+                {
+            #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519)
+                    ERROR_OUT(NOT_COMPILED_IN, exit_dske);
+            #else
+                    if (ssl->options.usingAnon_cipher) {
+                        break;
+                    }
+
+                    /* increment index after verify is done */
+                    args->idx += args->verifySigSz;
+
+                    switch(args->sigAlgo)
+                    {
+                    #ifndef NO_RSA
+                    #ifdef WC_RSA_PSS
+                        case rsa_pss_sa_algo:
+                            ret = wc_RsaPSS_CheckPadding(
+                                             ssl->buffers.digest.buffer,
+                                             ssl->buffers.digest.length,
+                                             args->output, args->sigSz,
+                                             HashAlgoToType(args->hashAlgo));
+                            if (ret != 0)
+                                return ret;
+                            break;
+                    #endif
+                        case rsa_sa_algo:
+                        {
+                            if (IsAtLeastTLSv1_2(ssl)) {
+                            #ifdef WOLFSSL_SMALL_STACK
+                                byte*  encodedSig = NULL;
+                            #else
+                                byte   encodedSig[MAX_ENCODED_SIG_SZ];
+                            #endif
+                                word32 encSigSz;
+
+                            #ifdef WOLFSSL_SMALL_STACK
+                                encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                                ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                                if (encodedSig == NULL) {
+                                    ERROR_OUT(MEMORY_E, exit_dske);
+                                }
+                            #endif
+
+                                encSigSz = wc_EncodeSignature(encodedSig,
+                                    ssl->buffers.digest.buffer,
+                                    ssl->buffers.digest.length,
+                                    TypeHash(args->hashAlgo));
+                                if (encSigSz != args->sigSz || !args->output ||
+                                    XMEMCMP(args->output, encodedSig,
+                                            min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+                                    ret = VERIFY_SIGN_ERROR;
+                                }
+                            #ifdef WOLFSSL_SMALL_STACK
+                                XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            #endif
+                                if (ret != 0) {
+                                    goto exit_dske;
+                                }
+                            }
+                            else if (args->sigSz != FINISHED_SZ ||
+                                    !args->output ||
+                                    XMEMCMP(args->output,
+                                            ssl->buffers.digest.buffer,
+                                            FINISHED_SZ) != 0) {
+                                ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske);
+                            }
+                            break;
+                        }
+                    #endif /* !NO_RSA */
+                    #ifdef HAVE_ECC
+                        case ecc_dsa_sa_algo:
+                            /* Nothing to do in this algo */
+                            break;
+                    #endif /* HAVE_ECC */
+                    #if defined(HAVE_ED25519)
+                        case ed25519_sa_algo:
+                            /* Nothing to do in this algo */
+                            break;
+                    #endif /* HAVE_ED25519 */
+                        default:
+                            ret = ALGO_ID_E;
+                    } /* switch (sigAlgo) */
+            #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */
+                    break;
+                }
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dske;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            if (IsEncryptionOn(ssl, 0)) {
+                args->idx += ssl->keys.padSz;
+            }
+
+            /* QSH extensions */
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                word16 name;
+                int    qshSz;
+
+                /* extension name */
+                ato16(input + args->idx, &name);
+                args->idx += OPAQUE16_LEN;
+
+                if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+                    /* if qshSz is larger than 0 it is the length of
+                       buffer used */
+                    if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx,
+                                                       size, 0)) < 0) {
+                        ERROR_OUT(qshSz, exit_dske);
+                    }
+                    args->idx += qshSz;
+                }
+                else {
+                    /* unknown extension sent server ignored handshake */
+                    ERROR_OUT(BUFFER_ERROR, exit_dske);
+                }
+            }
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* return index */
+            *inOutIdx = args->idx;
+
+            ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_dske:
+
+    WOLFSSL_LEAVE("DoServerKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        /* Mark message as not recevied so it can process again */
+        ssl->msgsReceived.got_server_key_exchange = 0;
+
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Final cleanup */
+    FreeDskeArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+
+#ifdef HAVE_QSH
+
+#ifdef HAVE_NTRU
+/* Encrypt a byte array using ntru
+   key    a struct containing the public key to use
+   bufIn  array to be encrypted
+   inSz   size of bufIn array
+   bufOut cipher text out
+   outSz  will be set to the new size of cipher text
+ */
+static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz,
+        byte* bufOut, word16* outSz)
+{
+    int    ret;
+    DRBG_HANDLE drbg;
+
+    /* sanity checks on input arguments */
+    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (key->pub.buffer == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (key->name) {
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption key!");
+            return -1;
+    }
+
+    /* set up ntru drbg */
+    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+    if (ret != DRBG_OK)
+        return NTRU_DRBG_ERROR;
+
+    /* encrypt the byte array */
+    ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer,
+        inSz, bufIn, outSz, bufOut);
+    ntru_crypto_drbg_uninstantiate(drbg);
+    if (ret != NTRU_OK)
+        return NTRU_ENCRYPT_ERROR;
+
+    return ret;
+}
+
+/* Decrypt a byte array using ntru
+   key    a struct containing the private key to use
+   bufIn  array to be decrypted
+   inSz   size of bufIn array
+   bufOut plain text out
+   outSz  will be set to the new size of plain text
+ */
+
+static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz,
+        byte* bufOut, word16* outSz)
+{
+    int    ret;
+    DRBG_HANDLE drbg;
+
+    /* sanity checks on input arguments */
+    if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (key->pri.buffer == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (key->name) {
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+        default:
+            WOLFSSL_MSG("Unknown QSH decryption key!");
+            return -1;
+    }
+
+
+    /* set up drbg */
+    ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+    if (ret != DRBG_OK)
+        return NTRU_DRBG_ERROR;
+
+    /* decrypt cipher text */
+    ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer,
+        inSz, bufIn, outSz, bufOut);
+    ntru_crypto_drbg_uninstantiate(drbg);
+    if (ret != NTRU_OK)
+        return NTRU_ENCRYPT_ERROR;
+
+    return ret;
+}
+#endif /* HAVE_NTRU */
+
+int QSH_Init(WOLFSSL* ssl)
+{
+    /* check so not initialising twice when running DTLS */
+    if (ssl->QSH_secret != NULL)
+        return 0;
+
+    /* malloc memory for holding generated secret information */
+    if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap,
+                    DYNAMIC_TYPE_QSH)) == NULL)
+        return MEMORY_E;
+
+    ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+    if (ssl->QSH_secret->CliSi == NULL)
+        return MEMORY_E;
+
+    ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap,
+            DYNAMIC_TYPE_SECRET);
+    if (ssl->QSH_secret->SerSi == NULL)
+        return MEMORY_E;
+
+    /* initialize variables */
+    ssl->QSH_secret->list = NULL;
+    ssl->QSH_secret->CliSi->length = 0;
+    ssl->QSH_secret->CliSi->buffer = NULL;
+    ssl->QSH_secret->SerSi->length = 0;
+    ssl->QSH_secret->SerSi->buffer = NULL;
+
+    return 0;
+}
+
+
+static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn,
+                                                       byte* out, word32* szOut)
+{
+    int ret = 0;
+    word16 size = *szOut;
+
+    (void)in;
+    (void)szIn;
+    (void)out;
+    (void)szOut;
+
+    WOLFSSL_MSG("Encrypting QSH key material");
+
+    switch (key->name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            ret = NtruSecretEncrypt(key, in, szIn, out, &size);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption key!");
+            return -1;
+    }
+
+    *szOut = size;
+
+    return ret;
+}
+
+
+/* Decrypt using Quantum Safe Handshake algorithms */
+int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut)
+{
+    int ret = 0;
+    word16 size = *szOut;
+
+    (void)in;
+    (void)szIn;
+    (void)out;
+    (void)szOut;
+
+    WOLFSSL_MSG("Decrypting QSH key material");
+
+    switch (key->name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            ret = NtruSecretDecrypt(key, in, szIn, out, &size);
+            break;
+    #endif
+        default:
+            WOLFSSL_MSG("Unknown QSH decryption key!");
+            return -1;
+    }
+
+    *szOut = size;
+
+    return ret;
+}
+
+
+/* Get the max cipher text for corresponding encryption scheme
+   (encrypting  48 or max plain text whichever is smaller)
+ */
+static word32 QSH_MaxSecret(QSHKey* key)
+{
+    int ret = 0;
+#ifdef HAVE_NTRU
+    byte isNtru = 0;
+    word16 inSz = 48;
+    word16 outSz;
+    DRBG_HANDLE drbg = 0;
+    byte bufIn[48];
+#endif
+
+    if (key == NULL || key->pub.length == 0)
+        return 0;
+
+    switch(key->name) {
+#ifdef HAVE_NTRU
+            case WOLFSSL_NTRU_EESS439:
+                isNtru   = 1;
+                break;
+            case WOLFSSL_NTRU_EESS593:
+                isNtru   = 1;
+                break;
+            case WOLFSSL_NTRU_EESS743:
+                isNtru   = 1;
+                break;
+#endif
+        default:
+            WOLFSSL_MSG("Unknown QSH encryption scheme size!");
+            return 0;
+    }
+
+#ifdef HAVE_NTRU
+    if (isNtru) {
+        ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+        if (ret != DRBG_OK)
+            return NTRU_DRBG_ERROR;
+        ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length,
+                            key->pub.buffer, inSz, bufIn, &outSz, NULL);
+        if (ret != NTRU_OK) {
+            return NTRU_ENCRYPT_ERROR;
+        }
+        ntru_crypto_drbg_uninstantiate(drbg);
+        ret = outSz;
+    }
+#endif
+
+    return ret;
+}
+
+/* Generate the secret byte material for pms
+   returns length on success and -1 on fail
+ */
+static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer)
+{
+    int sz       = 0;
+    int plainSz  = 48; /* lesser of 48 and max plain text able to encrypt */
+    int offset   = 0;
+    word32 tmpSz = 0;
+    buffer* buf;
+    QSHKey* current = ssl->peerQSHKey;
+    QSHScheme* schmPre = NULL;
+    QSHScheme* schm    = NULL;
+
+    if (ssl == NULL)
+        return -1;
+
+    WOLFSSL_MSG("Generating QSH secret key material");
+
+    /* get size of buffer needed */
+    while (current) {
+        if (current->pub.length != 0) {
+            sz += plainSz;
+        }
+        current = (QSHKey*)current->next;
+    }
+
+    /* allocate memory for buffer */
+    if (isServer) {
+        buf = ssl->QSH_secret->SerSi;
+    }
+    else {
+        buf = ssl->QSH_secret->CliSi;
+    }
+    buf->length = sz;
+    buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET);
+    if (buf->buffer == NULL) {
+        WOLFSSL_ERROR(MEMORY_E);
+    }
+
+    /* create secret information */
+    sz = 0;
+    current = ssl->peerQSHKey;
+    while (current) {
+        schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap,
+                                                       DYNAMIC_TYPE_QSH);
+        if (schm == NULL)
+            return MEMORY_E;
+
+        /* initialize variables */
+        schm->name  = 0;
+        schm->PK    = NULL;
+        schm->PKLen = 0;
+        schm->next  = NULL;
+        if (ssl->QSH_secret->list == NULL) {
+            ssl->QSH_secret->list = schm;
+        }
+        else {
+            if (schmPre)
+                schmPre->next = schm;
+        }
+
+        tmpSz = QSH_MaxSecret(current);
+
+        if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap,
+                                              DYNAMIC_TYPE_SECRET)) == NULL)
+            return -1;
+
+        /* store info for writing extension */
+        schm->name = current->name;
+
+        /* no key to use for encryption */
+        if (tmpSz == 0) {
+            current = (QSHKey*)current->next;
+            continue;
+        }
+
+        if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz)
+                                                                         != 0) {
+            return -1;
+        }
+        if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK,
+                                                                 &tmpSz) != 0) {
+            return -1;
+        }
+        schm->PKLen = tmpSz;
+
+        sz += tmpSz;
+        offset += plainSz;
+        schmPre = schm;
+        current = (QSHKey*)current->next;
+    }
+
+    return sz;
+}
+
+
+static word32 QSH_KeyGetSize(WOLFSSL* ssl)
+{
+    word32 sz = 0;
+    QSHKey* current = ssl->peerQSHKey;
+
+    if (ssl == NULL)
+        return -1;
+
+    sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */
+    sz += OPAQUE24_LEN;
+    /* get size of buffer needed */
+    while (current) {
+        sz += OPAQUE16_LEN; /* scheme id */
+        sz += OPAQUE16_LEN; /* encrypted key len*/
+        sz += QSH_MaxSecret(current);
+        current = (QSHKey*)current->next;
+    }
+
+    return sz;
+}
+
+
+/* handle QSH key Exchange
+   return 0 on success
+ */
+static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("QSH KeyExchange");
+
+    ret = QSH_GenerateSerCliSecret(ssl, isServer);
+    if (ret < 0)
+        return MEMORY_E;
+
+    return 0;
+}
+
+#endif /* HAVE_QSH */
+
+
+typedef struct SckeArgs {
+    byte*  output; /* not allocated */
+    byte*  encSecret;
+    byte*  input;
+    word32 encSz;
+    word32 length;
+    int    sendSz;
+    int    inputSz;
+} SckeArgs;
+
+static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
+{
+    SckeArgs* args = (SckeArgs*)pArgs;
+
+    (void)ssl;
+
+    if (args->encSecret) {
+        XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+        args->encSecret = NULL;
+    }
+    if (args->input) {
+        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+        args->input = NULL;
+    }
+}
+
+/* handle generation client_key_exchange (16) */
+int SendClientKeyExchange(WOLFSSL* ssl)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    SckeArgs* args = (SckeArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    SckeArgs  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+    WOLFSSL_ENTER("SendClientKeyExchange");
+
+#ifdef OPENSSL_EXTRA
+	ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+	ssl->cbmode = SSL_CB_MODE_WRITE;
+	if (ssl->CBIS != NULL)
+		ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scke;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(SckeArgs));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeSckeArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            switch (ssl->specs.kea) {
+            #ifndef NO_RSA
+                case rsa_kea:
+                    if (ssl->peerRsaKey == NULL ||
+                        ssl->peerRsaKeyPresent == 0) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                    if (ssl->buffers.serverDH_P.buffer == NULL ||
+                        ssl->buffers.serverDH_G.buffer == NULL ||
+                        ssl->buffers.serverDH_Pub.buffer == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif /* NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    break;
+            #endif /* NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                    if (ssl->buffers.serverDH_P.buffer == NULL ||
+                        ssl->buffers.serverDH_G.buffer == NULL ||
+                        ssl->buffers.serverDH_Pub.buffer == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    break;
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                    /* sanity check that PSK client callback has been set */
+                    if (ssl->options.client_psk_cb == NULL) {
+                        WOLFSSL_MSG("No client PSK callback set");
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        /* Check client ECC public key */
+                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+                                            ssl->peerX25519Key);
+                        break;
+                    }
+                #endif
+                    /* Check client ECC public key */
+                    if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+                                            !ssl->peerEccKey->dp) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* create ephemeral private key */
+                    ssl->hsType = DYNAMIC_TYPE_ECC;
+                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
+
+                    break;
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                    if (ssl->peerNtruKeyPresent == 0) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+                    break;
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                case ecc_diffie_hellman_kea:
+                {
+                #ifdef HAVE_ECC
+                    ecc_key* peerKey;
+                #endif
+
+            #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        if (ssl->ctx->X25519SharedSecretCb != NULL)
+                            break;
+                    }
+                    else
+                #endif
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+            #endif /* HAVE_PK_CALLBACKS */
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+
+                        /* create private key */
+                        ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_scke;
+                        }
+
+                        ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+                                            ssl->peerX25519Key);
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    if (ssl->specs.static_ecdh) {
+                        /* Note: EccDsa is really fixed Ecc key here */
+                        if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
+                                                   !ssl->peerEccDsaKey->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+                        peerKey = ssl->peerEccDsaKey;
+                    }
+                    else {
+                        if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+                                                !ssl->peerEccKey->dp) {
+                            ERROR_OUT(NO_PEER_KEY, exit_scke);
+                        }
+                        peerKey = ssl->peerEccKey;
+                    }
+                    if (peerKey == NULL) {
+                        ERROR_OUT(NO_PEER_KEY, exit_scke);
+                    }
+
+                    /* create ephemeral private key */
+                    ssl->hsType = DYNAMIC_TYPE_ECC;
+                    ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey);
+                #endif
+
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            args->encSz = MAX_ENCRYPT_SZ;
+            args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap,
+                                                    DYNAMIC_TYPE_SECRET);
+            if (args->encSecret == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scke);
+            }
+
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    /* build PreMasterSecret with RNG data */
+                    ret = wc_RNG_GenerateBlock(ssl->rng,
+                        &ssl->arrays->preMasterSecret[VERSION_SZ],
+                        SECRET_LEN - VERSION_SZ);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                    ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+                    ssl->arrays->preMasterSz = SECRET_LEN;
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    ssl->buffers.sig.length = ENCRYPT_LEN;
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scke);
+                    }
+
+                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                        ssl->buffers.serverDH_P.buffer,
+                        ssl->buffers.serverDH_P.length,
+                        ssl->buffers.serverDH_G.buffer,
+                        ssl->buffers.serverDH_G.length);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    /* for DH, encSecret is Yc, agree is pre-master */
+                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
+                        args->encSecret, &args->encSz);
+
+                    /* set the max agree result size */
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                        ssl->arrays->server_hint, ssl->arrays->client_identity,
+                        MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                        ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+                    if (args->encSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+                    XMEMCPY(args->encSecret, ssl->arrays->client_identity,
+                                                                args->encSz);
+
+                    /* make psk pre master secret */
+                    /* length of key + length 0s + length of key + key */
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMSET(pms, 0, ssl->arrays->psk_keySz);
+                    pms += ssl->arrays->psk_keySz;
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) +
+                        (2 * OPAQUE16_LEN);
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    word32 esSz = 0;
+                    args->output = args->encSecret;
+
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                         ssl->arrays->server_hint, ssl->arrays->client_identity,
+                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+
+                    if (esSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+
+                    ssl->buffers.sig.length = ENCRYPT_LEN;
+                    ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (ssl->buffers.sig.buffer == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scke);
+                    }
+
+                    c16toa((word16)esSz, args->output);
+                    args->output += OPAQUE16_LEN;
+                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+                    args->output += esSz;
+                    args->encSz = esSz + OPAQUE16_LEN;
+
+                    args->length = 0;
+
+                    ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                        ssl->buffers.serverDH_P.buffer,
+                        ssl->buffers.serverDH_P.length,
+                        ssl->buffers.serverDH_G.buffer,
+                        ssl->buffers.serverDH_G.length);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    /* for DH, encSecret is Yc, agree is pre-master */
+                    ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
+                        args->output + OPAQUE16_LEN, &args->length);
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    word32 esSz = 0;
+                    args->output = args->encSecret;
+
+                    /* Send PSK client identity */
+                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                         ssl->arrays->server_hint, ssl->arrays->client_identity,
+                         MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+                    if (ssl->arrays->psk_keySz == 0 ||
+                                     ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                        ERROR_OUT(PSK_KEY_ERROR, exit_scke);
+                    }
+                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
+                    esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
+                    if (esSz > MAX_PSK_ID_LEN) {
+                        ERROR_OUT(CLIENT_ID_ERROR, exit_scke);
+                    }
+
+                    /* place size and identity in output buffer sz:identity */
+                    c16toa((word16)esSz, args->output);
+                    args->output += OPAQUE16_LEN;
+                    XMEMCPY(args->output, ssl->arrays->client_identity, esSz);
+                    args->output += esSz;
+                    args->encSz = esSz + OPAQUE16_LEN;
+
+                    /* length is used for public key size */
+                    args->length = MAX_ENCRYPT_SZ;
+
+                    /* Create shared ECC key leaving room at the begining
+                       of buffer for size of shared key. */
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve25519_export_public_ex(
+                                (curve25519_key*)ssl->hsKey,
+                                args->output + OPAQUE8_LEN, &args->length,
+                                EC25519_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* Place ECC key in output buffer, leaving room for size */
+                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+                                    args->output + OPAQUE8_LEN, &args->length);
+                    if (ret != 0) {
+                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                    }
+
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    ret = wc_RNG_GenerateBlock(ssl->rng,
+                                  ssl->arrays->preMasterSecret, SECRET_LEN);
+                    if (ret != 0) {
+                        goto exit_scke;
+                    }
+
+                    ssl->arrays->preMasterSz = SECRET_LEN;
+                    args->encSz = MAX_ENCRYPT_SZ;
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                case ecc_diffie_hellman_kea:
+                {
+                    ssl->arrays->preMasterSz = ENCRYPT_LEN;
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) {
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        ret = wc_curve25519_export_public_ex(
+                                (curve25519_key*)ssl->hsKey,
+                                args->encSecret + OPAQUE8_LEN, &args->encSz,
+                                EC25519_LITTLE_ENDIAN);
+                        if (ret != 0) {
+                            ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                        }
+
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                #ifdef HAVE_PK_CALLBACKS
+                    /* if callback then use it for shared secret */
+                    if (ssl->ctx->EccSharedSecretCb != NULL) {
+                        break;
+                    }
+                #endif
+
+                    /* Place ECC key in buffer, leaving room for size */
+                    ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
+                                args->encSecret + OPAQUE8_LEN, &args->encSz);
+                    if (ret != 0) {
+                        ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
+                    }
+                #endif /* HAVE_ECC */
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    ret = RsaEnc(ssl,
+                        ssl->arrays->preMasterSecret, SECRET_LEN,
+                        args->encSecret, &args->encSz,
+                        ssl->peerRsaKey,
+                    #if defined(HAVE_PK_CALLBACKS)
+                        &ssl->buffers.peerRsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                        ssl->buffers.serverDH_Pub.buffer,
+                        ssl->buffers.serverDH_Pub.length,
+                        ssl->arrays->preMasterSecret,
+                        &ssl->arrays->preMasterSz);
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                        ssl->buffers.serverDH_Pub.buffer,
+                        ssl->buffers.serverDH_Pub.length,
+                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                        &ssl->arrays->preMasterSz);
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        ret = X25519SharedSecret(ssl,
+                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+                            args->output + OPAQUE8_LEN, &args->length,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (ret == 0 && !ssl->specs.static_ecdh) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                    ret = EccSharedSecret(ssl,
+                        (ecc_key*)ssl->hsKey, ssl->peerEccKey,
+                        args->output + OPAQUE8_LEN, &args->length,
+                        ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                        &ssl->arrays->preMasterSz,
+                        WOLFSSL_CLIENT_END
+                    );
+                    break;
+                }
+            #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    word32 rc;
+                    word16 tmpEncSz = (word16)args->encSz;
+                    DRBG_HANDLE drbg;
+
+                    rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
+                    if (rc != DRBG_OK) {
+                        ERROR_OUT(NTRU_DRBG_ERROR, exit_scke);
+                    }
+                    rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,
+                                                  ssl->peerNtruKey,
+                                                  ssl->arrays->preMasterSz,
+                                                  ssl->arrays->preMasterSecret,
+                                                  &tmpEncSz,
+                                                  args->encSecret);
+                    args->encSz = tmpEncSz;
+                    ntru_crypto_drbg_uninstantiate(drbg);
+                    if (rc != NTRU_OK) {
+                        ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke);
+                    }
+                    ret = 0;
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                case ecc_diffie_hellman_kea:
+                {
+                #ifdef HAVE_ECC
+                    ecc_key* peerKey;
+                #endif
+
+                #ifdef HAVE_CURVE25519
+                    if (ssl->peerX25519KeyPresent) {
+                        ret = X25519SharedSecret(ssl,
+                            (curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
+                            args->encSecret + OPAQUE8_LEN, &args->encSz,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_CLIENT_END
+                        );
+                        if (ret == 0) {
+                            FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                            ssl->peerX25519KeyPresent = 0;
+                        }
+                        break;
+                    }
+                #endif
+                #ifdef HAVE_ECC
+                    peerKey = (ssl->specs.static_ecdh) ?
+                              ssl->peerEccDsaKey : ssl->peerEccKey;
+
+                    ret = EccSharedSecret(ssl,
+                        (ecc_key*)ssl->hsKey, peerKey,
+                        args->encSecret + OPAQUE8_LEN, &args->encSz,
+                        ssl->arrays->preMasterSecret,
+                        &ssl->arrays->preMasterSz,
+                        WOLFSSL_CLIENT_END
+                    );
+                #endif
+
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            switch(ssl->specs.kea)
+            {
+            #ifndef NO_RSA
+                case rsa_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_RSA */
+            #ifndef NO_DH
+                case diffie_hellman_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_DH */
+            #ifndef NO_PSK
+                case psk_kea:
+                {
+                    break;
+                }
+            #endif /* !NO_PSK */
+            #if !defined(NO_DH) && !defined(NO_PSK)
+                case dhe_psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+
+                    /* validate args */
+                    if (args->output == NULL || args->length == 0) {
+                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
+                    }
+
+                    c16toa((word16)args->length, args->output);
+                    args->encSz += args->length + OPAQUE16_LEN;
+                    c16toa((word16)ssl->arrays->preMasterSz, pms);
+                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                    pms += ssl->arrays->preMasterSz;
+
+                    /* make psk pre master secret */
+                    /* length of key + length 0s + length of key + key */
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz +=
+                                         ssl->arrays->psk_keySz + OPAQUE16_LEN;
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* !NO_DH && !NO_PSK */
+            #if defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
+                                                                !defined(NO_PSK)
+                case ecdhe_psk_kea:
+                {
+                    byte* pms = ssl->arrays->preMasterSecret;
+
+                    /* validate args */
+                    if (args->output == NULL || args->length > ENCRYPT_LEN) {
+                        ERROR_OUT(BAD_FUNC_ARG, exit_scke);
+                    }
+
+                    /* place size of public key in output buffer */
+                    *args->output = (byte)args->length;
+                    args->encSz += args->length + OPAQUE8_LEN;
+
+                    /* Create pre master secret is the concatination of
+                       eccSize + eccSharedKey + pskSize + pskKey */
+                    c16toa((word16)ssl->arrays->preMasterSz, pms);
+                    ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                    pms += ssl->arrays->preMasterSz;
+
+                    c16toa((word16)ssl->arrays->psk_keySz, pms);
+                    pms += OPAQUE16_LEN;
+                    XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->preMasterSz +=
+                                          ssl->arrays->psk_keySz + OPAQUE16_LEN;
+
+                    ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                    ssl->arrays->psk_keySz = 0; /* No further need */
+                    break;
+                }
+            #endif /* (HAVE_ECC && !HAVE_CURVE25519) && !NO_PSK */
+            #ifdef HAVE_NTRU
+                case ntru_kea:
+                {
+                    break;
+                }
+            #endif /* HAVE_NTRU */
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                case ecc_diffie_hellman_kea:
+                {
+                    /* place size of public key in buffer */
+                    *args->encSecret = (byte)args->encSz;
+                    args->encSz += OPAQUE8_LEN;
+                    break;
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+                default:
+                    ret = BAD_KEA_TYPE_E;
+            } /* switch(ssl->specs.kea) */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            word32 tlsSz = 0;
+            word32 idx = 0;
+
+        #ifdef HAVE_QSH
+            word32 qshSz = 0;
+            if (ssl->peerQSHKeyPresent) {
+                qshSz = QSH_KeyGetSize(ssl);
+            }
+        #endif
+
+            if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) {
+                tlsSz = 2;
+            }
+
+            if (ssl->specs.kea == ecc_diffie_hellman_kea ||
+                ssl->specs.kea == dhe_psk_kea ||
+                ssl->specs.kea == ecdhe_psk_kea) { /* always off */
+                tlsSz = 0;
+            }
+
+            idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+            args->sendSz = args->encSz + tlsSz + idx;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                idx    += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+                args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+            }
+        #endif
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->sendSz += MAX_MSG_EXTRA;
+            }
+
+        #ifdef HAVE_QSH
+            args->encSz += qshSz;
+            args->sendSz += qshSz;
+        #endif
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scke;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                byte idxSave = idx;
+                idx = args->sendSz - qshSz;
+
+                if (QSH_KeyExchangeWrite(ssl, 0) != 0) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                /* extension type */
+                c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx);
+                idx += OPAQUE16_LEN;
+
+                /* write to output and check amount written */
+                if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+                            args->output + idx) > qshSz - OPAQUE16_LEN) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                idx = idxSave;
+            }
+        #endif
+
+            AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl);
+
+        #ifdef HAVE_QSH
+            if (ssl->peerQSHKeyPresent) {
+                args->encSz -= qshSz;
+            }
+        #endif
+            if (tlsSz) {
+                c16toa((word16)args->encSz, &args->output[idx]);
+                idx += OPAQUE16_LEN;
+            }
+            XMEMCPY(args->output + idx, args->encSecret, args->encSz);
+            idx += args->encSz;
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */
+                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+                                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (args->input == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scke);
+                }
+
+                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+                                                                args->inputSz);
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            if (IsEncryptionOn(ssl, 1)) {
+                ret = BuildMessage(ssl, args->output, args->sendSz,
+                            args->input, args->inputSz, handshake, 1, 0, 0);
+                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+                args->input = NULL; /* make sure its not double free'd on cleanup */
+
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+                ret = HashOutput(ssl, args->output, args->sendSz, 0);
+            }
+
+            if (ret != 0) {
+                goto exit_scke;
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
+                    goto exit_scke;
+                }
+            }
+        #endif
+
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "ClientKeyExchange");
+            if (ssl->toInfoOn)
+                AddPacketInfo(ssl, "ClientKeyExchange", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages) {
+                ret = SendBuffered(ssl);
+            }
+            if (ret == 0 || ret == WANT_WRITE) {
+                int tmpRet = MakeMasterSecret(ssl);
+                if (tmpRet != 0) {
+                    ret = tmpRet;   /* save WANT_WRITE unless more serious */
+                }
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+            }
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scke:
+
+    WOLFSSL_LEAVE("SendClientKeyExchange", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E)
+        return ret;
+#endif
+
+    /* No further need for PMS */
+    ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+    ssl->arrays->preMasterSz = 0;
+
+    /* Final cleanup */
+    FreeSckeArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifndef NO_CERTS
+
+#ifdef HAVE_PK_CALLBACKS
+    int GetPrivateKeySigSize(WOLFSSL* ssl)
+    {
+        int sigSz = 0;
+
+        if (ssl == NULL)
+            return 0;
+
+        switch (ssl->buffers.keyType) {
+        #ifndef NO_RSA
+        #ifdef WC_RSA_PSS
+            case rsa_pss_sa_algo:
+        #endif
+            case rsa_sa_algo:
+                sigSz = ssl->buffers.keySz;
+                ssl->hsType = DYNAMIC_TYPE_RSA;
+                break;
+        #endif
+        #ifdef HAVE_ECC
+            case ecc_dsa_sa_algo:
+                sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz);
+                ssl->hsType = DYNAMIC_TYPE_ECC;
+                break;
+        #endif
+        #ifdef HAVE_ED25519
+            case ed25519_sa_algo:
+                sigSz = ED25519_SIG_SIZE; /* fixed known value */
+                ssl->hsType = DYNAMIC_TYPE_ED25519;
+                break;
+        #endif
+            default:
+                break;
+        }
+        return sigSz;
+    }
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifndef WOLFSSL_NO_CLIENT_AUTH
+typedef struct ScvArgs {
+    byte*  output; /* not allocated */
+#ifndef NO_RSA
+    byte*  verifySig;
+#endif
+    byte*  verify; /* not allocated */
+    byte*  input;
+    word32 idx;
+    word32 extraSz;
+    word32 sigSz;
+    int    sendSz;
+    int    inputSz;
+    word16 length;
+    byte   sigAlgo;
+} ScvArgs;
+
+static void FreeScvArgs(WOLFSSL* ssl, void* pArgs)
+{
+    ScvArgs* args = (ScvArgs*)pArgs;
+
+    (void)ssl;
+
+#ifndef NO_RSA
+    if (args->verifySig) {
+        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->verifySig = NULL;
+    }
+#endif
+    if (args->input) {
+        XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+        args->input = NULL;
+    }
+}
+
+/* handle generation of certificate_verify (15) */
+int SendCertificateVerify(WOLFSSL* ssl)
+{
+    int ret = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ScvArgs* args = (ScvArgs*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    ScvArgs  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+    WOLFSSL_ENTER("SendCertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(ScvArgs));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeScvArgs;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+                return 0;  /* sent blank cert, can't verify */
+            }
+
+            args->sendSz = MAX_CERT_VERIFY_SZ;
+            if (IsEncryptionOn(ssl, 1)) {
+                args->sendSz += MAX_MSG_EXTRA;
+            }
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scv;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            if (ssl->buffers.key == NULL) {
+            #ifdef HAVE_PK_CALLBACKS
+                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                    args->length = GetPrivateKeySigSize(ssl);
+                else
+            #endif
+                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+            else {
+                /* Decode private key. */
+                ret = DecodePrivateKey(ssl, &args->length);
+                if (ret != 0) {
+                    goto exit_scv;
+                }
+            }
+
+            if (args->length <= 0) {
+                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+
+            /* idx is used to track verify pointer offset to output */
+            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+            args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
+            args->extraSz = 0;  /* tls 1.2 hash/sig */
+
+            /* build encoded signature buffer */
+            ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ;
+            ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length,
+                                        ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            if (ssl->buffers.sig.buffer == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scv);
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+
+    #ifndef NO_OLD_TLS
+        #ifndef NO_SHA
+            /* old tls default */
+            SetDigest(ssl, sha_mac);
+        #endif
+    #else
+        #ifndef NO_SHA256
+            /* new tls default */
+            SetDigest(ssl, sha256_mac);
+        #endif
+    #endif /* !NO_OLD_TLS */
+
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+        #ifdef WC_RSA_PSS
+                if (IsAtLeastTLSv1_2(ssl) &&
+                                (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) {
+                    args->sigAlgo = rsa_pss_sa_algo;
+                }
+                else
+        #endif
+                    args->sigAlgo = rsa_sa_algo;
+            }
+            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
+                args->sigAlgo = ecc_dsa_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
+                args->sigAlgo = ed25519_sa_algo;
+
+            if (IsAtLeastTLSv1_2(ssl)) {
+                EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo,
+                             args->verify);
+                args->extraSz = HASH_SIG_SIZE;
+                SetDigest(ssl, ssl->suites->hashAlgo);
+            }
+        #ifndef NO_OLD_TLS
+            else {
+                /* if old TLS load MD5 and SHA hash as value to sign */
+                XMEMCPY(ssl->buffers.sig.buffer,
+                    (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ);
+            }
+        #endif
+
+        #ifndef NO_RSA
+            if (args->sigAlgo == rsa_sa_algo) {
+                ssl->buffers.sig.length = FINISHED_SZ;
+                args->sigSz = ENCRYPT_LEN;
+
+                if (IsAtLeastTLSv1_2(ssl)) {
+                    ssl->buffers.sig.length = wc_EncodeSignature(
+                            ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+                            ssl->buffers.digest.length,
+                            TypeHash(ssl->suites->hashAlgo));
+                }
+
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+            }
+            else if (args->sigAlgo == rsa_pss_sa_algo) {
+                XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer,
+                        ssl->buffers.digest.length);
+                ssl->buffers.sig.length = ssl->buffers.digest.length;
+                args->sigSz = ENCRYPT_LEN;
+
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+            }
+        #endif /* !NO_RSA */
+        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+            if (args->sigAlgo == ed25519_sa_algo) {
+                ret = Ed25519CheckPubKey(ssl);
+                if (ret != 0)
+                    goto exit_scv;
+            }
+        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifdef HAVE_ECC
+           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                ecc_key* key = (ecc_key*)ssl->hsKey;
+
+                ret = EccSign(ssl,
+                    ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+                    ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
+                    key,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+            }
+        #endif /* HAVE_ECC */
+        #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+           if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+                ret = Ed25519Sign(ssl,
+                    ssl->hsHashes->messages, ssl->hsHashes->length,
+                    ssl->buffers.sig.buffer, &ssl->buffers.sig.length,
+                    key,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+            }
+        #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                /* restore verify pointer */
+                args->verify = &args->output[args->idx];
+
+                ret = RsaSign(ssl,
+                    ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                    args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz,
+                    args->sigAlgo, ssl->suites->hashAlgo, key,
+                    ssl->buffers.key
+                );
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+            /* restore verify pointer */
+            args->verify = &args->output[args->idx];
+
+        #ifdef HAVE_ECC
+            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                args->length = (word16)ssl->buffers.sig.length;
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+                XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length);
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                args->length = (word16)ssl->buffers.sig.length;
+                /* prepend hdr */
+                c16toa(args->length, args->verify + args->extraSz);
+                XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER,
+                        ssl->buffers.sig.buffer, ssl->buffers.sig.length);
+            }
+        #endif /* HAVE_ED25519 */
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                if (args->verifySig == NULL) {
+                    args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap,
+                                      DYNAMIC_TYPE_SIGNATURE);
+                    if (args->verifySig == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scv);
+                    }
+                    XMEMCPY(args->verifySig, args->verify + args->extraSz +
+                                                    VERIFY_HEADER, args->sigSz);
+                }
+
+                /* check for signature faults */
+                ret = VerifyRsaSign(ssl,
+                    args->verifySig, args->sigSz,
+                    ssl->buffers.sig.buffer, ssl->buffers.sig.length,
+                    args->sigAlgo, ssl->suites->hashAlgo, key,
+                    ssl->buffers.key
+                );
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            if (args->output == NULL) {
+                ERROR_OUT(BUFFER_ERROR, exit_scv);
+            }
+            AddHeaders(args->output, (word32)args->length + args->extraSz +
+                                        VERIFY_HEADER, certificate_verify, ssl);
+
+            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
+                           (word32)args->length + args->extraSz + VERIFY_HEADER;
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->options.dtls) {
+                args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            }
+        #endif
+
+            if (IsEncryptionOn(ssl, 1)) {
+                args->inputSz = args->sendSz - RECORD_HEADER_SZ;
+                                /* build msg adds rec hdr */
+                args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+                                                       DYNAMIC_TYPE_IN_BUFFER);
+                if (args->input == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scv);
+                }
+
+                XMEMCPY(args->input, args->output + RECORD_HEADER_SZ,
+                                                                args->inputSz);
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            if (IsEncryptionOn(ssl, 1)) {
+                ret = BuildMessage(ssl, args->output,
+                                      MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
+                                      args->input, args->inputSz, handshake,
+                                      1, 0, 1);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (ret == WC_PENDING_E)
+                    goto exit_scv;
+            #endif
+
+                XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+                args->input = NULL;  /* make sure its not double free'd on cleanup */
+
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+                ret = HashOutput(ssl, args->output, args->sendSz, 0);
+            }
+
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz);
+            }
+        #endif
+
+
+        #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn)
+                AddPacketInfo(ssl, "CertificateVerify", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages) {
+                ret = SendBuffered(ssl);
+            }
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scv:
+
+    WOLFSSL_LEAVE("SendCertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Digest is not allocated, so do this to prevent free */
+    ssl->buffers.digest.buffer = NULL;
+    ssl->buffers.digest.length = 0;
+
+    /* Final cleanup */
+    FreeScvArgs(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+#endif /* WOLFSSL_NO_CLIENT_AUTH */
+
+#endif /* WOLFSSL_NO_TLS12 */
+
+#endif /* NO_CERTS */
+
+
+#ifdef HAVE_SESSION_TICKET
+int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length)
+{
+    /* Free old dynamic ticket if we already had one */
+    if (ssl->session.isDynamic) {
+        XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        ssl->session.ticket = ssl->session.staticTicket;
+        ssl->session.isDynamic = 0;
+    }
+
+    if (length > sizeof(ssl->session.staticTicket)) {
+        byte* sessionTicket =
+                   (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        if (sessionTicket == NULL)
+            return MEMORY_E;
+        ssl->session.ticket = sessionTicket;
+        ssl->session.isDynamic = 1;
+    }
+    ssl->session.ticketLen = (word16)length;
+
+    if (length > 0) {
+        XMEMCPY(ssl->session.ticket, ticket, length);
+        if (ssl->session_ticket_cb != NULL) {
+            ssl->session_ticket_cb(ssl,
+                                   ssl->session.ticket, ssl->session.ticketLen,
+                                   ssl->session_ticket_ctx);
+        }
+        /* Create a fake sessionID based on the ticket, this will
+         * supercede the existing session cache info. */
+        ssl->options.haveSessionId = 1;
+        XMEMCPY(ssl->arrays->sessionID,
+                                 ssl->session.ticket + length - ID_LEN, ID_LEN);
+    }
+
+    return 0;
+}
+
+#ifndef WOLFSSL_NO_TLS12
+
+/* handle processing of session_ticket (4) */
+static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+    word32 size)
+{
+    word32 begin = *inOutIdx;
+    word32 lifetime;
+    word16 length;
+    int    ret;
+
+    if (ssl->expect_session_ticket == 0) {
+        WOLFSSL_MSG("Unexpected session ticket");
+        return SESSION_TICKET_EXPECT_E;
+    }
+
+    if ((*inOutIdx - begin) + OPAQUE32_LEN > size)
+        return BUFFER_ERROR;
+
+    ato32(input + *inOutIdx, &lifetime);
+    *inOutIdx += OPAQUE32_LEN;
+
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += OPAQUE16_LEN;
+
+    if ((*inOutIdx - begin) + length > size)
+        return BUFFER_ERROR;
+
+    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
+        return ret;
+    *inOutIdx += length;
+    if (length > 0) {
+        ssl->timeout = lifetime;
+#ifndef NO_SESSION_CACHE
+        AddSession(ssl);
+#endif
+    }
+
+    if (IsEncryptionOn(ssl, 0)) {
+        *inOutIdx += ssl->keys.padSz;
+    }
+
+    ssl->expect_session_ticket = 0;
+
+    return 0;
+}
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#endif /* HAVE_SESSION_TICKET */
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+
+#ifndef WOLFSSL_NO_TLS12
+
+    /* handle generation of server_hello (2) */
+    int SendServerHello(WOLFSSL* ssl)
+    {
+        int    ret;
+        byte   *output;
+        word16 length;
+        word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int    sendSz;
+        byte   sessIdSz = ID_LEN;
+        byte   echoId   = 0;  /* ticket echo id flag */
+        byte   cacheOff = 0;  /* session cache off flag */
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
+        WOLFSSL_ENTER("SendServerHello");
+
+        length = VERSION_SZ + RAN_LEN
+               + ID_LEN + ENUM_LEN
+               + SUITE_LEN
+               + ENUM_LEN;
+
+#ifdef HAVE_TLS_EXTENSIONS
+        ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+        if (ret != 0)
+            return ret;
+    #ifdef HAVE_SESSION_TICKET
+        if (ssl->options.useTicket) {
+            /* echo session id sz can be 0,32 or bogus len inbetween */
+            sessIdSz = ssl->arrays->sessionIDSz;
+            if (sessIdSz > ID_LEN) {
+                WOLFSSL_MSG("Bad bogus session id len");
+                return BUFFER_ERROR;
+            }
+            if (!IsAtLeastTLSv1_3(ssl->version))
+                length -= (ID_LEN - sessIdSz);  /* adjust ID_LEN assumption */
+            echoId = 1;
+        }
+    #endif /* HAVE_SESSION_TICKET */
+#else
+        if (ssl->options.haveEMS) {
+            length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
+        }
+#endif
+
+        /* is the session cahce off at build or runtime */
+#ifdef NO_SESSION_CACHE
+        cacheOff = 1;
+#else
+        if (ssl->options.sessionCacheOff == 1) {
+            cacheOff = 1;
+        }
+#endif
+
+        /* if no session cache don't send a session ID unless we're echoing
+         * an ID as part of session tickets */
+        if (echoId == 0 && cacheOff == 1) {
+            length -= ID_LEN;    /* adjust ID_LEN assumption */
+            sessIdSz = 0;
+        }
+
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+        #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            /* Server Hello should use the same sequence number as the
+             * Client Hello. */
+            ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
+            ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
+            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        }
+        #endif /* WOLFSSL_DTLS */
+
+        /* check for avalaible size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, server_hello, ssl);
+
+        /* now write to output */
+        /* first version */
+        output[idx++] = (byte)ssl->version.major;
+        output[idx++] = (byte)ssl->version.minor;
+
+        /* then random and session id */
+        if (!ssl->options.resuming) {
+            /* generate random part and session id */
+            ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
+                RAN_LEN + sizeof(sessIdSz) + sessIdSz);
+            if (ret != 0)
+                return ret;
+
+#ifdef WOLFSSL_TLS13
+            if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) {
+                /* TLS v1.3 capable server downgraded. */
+                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
+                output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
+            }
+            else
+#endif
+            if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
+                          ssl->ctx->method->version.minor == TLSv1_2_MINOR &&
+                                                       !IsAtLeastTLSv1_2(ssl)) {
+                /* TLS v1.2 capable server downgraded. */
+                XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
+                        tls13Downgrade, TLS13_DOWNGRADE_SZ);
+                output[idx + RAN_LEN - 1] = 0;
+            }
+
+            /* store info in SSL for later */
+            XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
+            idx += RAN_LEN;
+            output[idx++] = sessIdSz;
+            XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
+            ssl->arrays->sessionIDSz = sessIdSz;
+        }
+        else {
+            /* If resuming, use info from SSL */
+            XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            output[idx++] = sessIdSz;
+            XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
+        }
+        idx += sessIdSz;
+
+#ifdef SHOW_SECRETS
+        {
+            int j;
+            printf("server random: ");
+            for (j = 0; j < RAN_LEN; j++)
+                printf("%02x", ssl->arrays->serverRandom[j]);
+            printf("\n");
+        }
+#endif
+
+        /* then cipher suite */
+        output[idx++] = ssl->options.cipherSuite0;
+        output[idx++] = ssl->options.cipherSuite;
+
+        /* then compression */
+        if (ssl->options.usingCompression)
+            output[idx++] = ZLIB_COMPRESSION;
+        else
+            output[idx++] = NO_COMPRESSION;
+
+        /* last, extensions */
+#ifdef HAVE_TLS_EXTENSIONS
+        ret = TLSX_WriteResponse(ssl, output + idx, server_hello, NULL);
+        if (ret != 0)
+            return ret;
+#else
+#ifdef HAVE_EXTENDED_MASTER
+        if (ssl->options.haveEMS) {
+            c16toa(HELLO_EXT_SZ, output + idx);
+            idx += HELLO_EXT_SZ_SZ;
+
+            c16toa(HELLO_EXT_EXTMS, output + idx);
+            idx += HELLO_EXT_TYPE_SZ;
+            c16toa(0, output + idx);
+            /*idx += HELLO_EXT_SZ_SZ;*/
+            /* idx is not used after this point. uncomment the line above
+             * if adding any more extentions in the future. */
+        }
+#endif
+#endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+        #ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                    return ret;
+            }
+
+            if (ssl->options.dtls) {
+                DtlsSEQIncrement(ssl, CUR_ORDER);
+            }
+        #endif
+
+        ret = HashOutput(ssl, output, sendSz, 0);
+        if (ret != 0)
+            return ret;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHello");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+    #endif
+
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+        if (ssl->options.groupMessages)
+            ret = 0;
+        else
+            ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendServerHello", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+        return ret;
+    }
+
+
+#if defined(HAVE_ECC)
+
+    static byte SetCurveId(ecc_key* key)
+    {
+        if (key == NULL || key->dp == NULL) {
+            WOLFSSL_MSG("SetCurveId: Invalid key!");
+            return 0;
+        }
+
+        switch(key->dp->oidSum) {
+    #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP160R1_OID:
+                return WOLFSSL_ECC_SECP160R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_SECPR2
+            case ECC_SECP160R2_OID:
+                return WOLFSSL_ECC_SECP160R2;
+        #endif /* HAVE_ECC_SECPR2 */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP160K1_OID:
+                return WOLFSSL_ECC_SECP160K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP192R1_OID:
+                return WOLFSSL_ECC_SECP192R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP192K1_OID:
+                return WOLFSSL_ECC_SECP192K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP224R1_OID:
+                return WOLFSSL_ECC_SECP224R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP224K1_OID:
+                return WOLFSSL_ECC_SECP224K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+    #endif
+    #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP256R1_OID:
+                return WOLFSSL_ECC_SECP256R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_KOBLITZ
+            case ECC_SECP256K1_OID:
+                return WOLFSSL_ECC_SECP256K1;
+        #endif /* HAVE_ECC_KOBLITZ */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP256R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP256R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP384R1_OID:
+                return WOLFSSL_ECC_SECP384R1;
+        #endif /* !NO_ECC_SECP */
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP384R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP384R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
+        #ifdef HAVE_ECC_BRAINPOOL
+            case ECC_BRAINPOOLP512R1_OID:
+                return WOLFSSL_ECC_BRAINPOOLP512R1;
+        #endif /* HAVE_ECC_BRAINPOOL */
+    #endif
+    #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
+        #ifndef NO_ECC_SECP
+            case ECC_SECP521R1_OID:
+                return WOLFSSL_ECC_SECP521R1;
+        #endif /* !NO_ECC_SECP */
+    #endif
+            default:
+                return 0;
+        }
+    }
+
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+    typedef struct SskeArgs {
+        byte*  output; /* not allocated */
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        byte*  sigDataBuf;
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+        byte*  exportBuf;
+    #endif
+    #ifndef NO_RSA
+        byte*  verifySig;
+    #endif
+        word32 idx;
+        word32 tmpSigSz;
+        word32 length;
+        word32 sigSz;
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        word32 sigDataSz;
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+        word32 exportSz;
+    #endif
+    #ifdef HAVE_QSH
+        word32 qshSz;
+    #endif
+        int    sendSz;
+    } SskeArgs;
+
+    static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        SskeArgs* args = (SskeArgs*)pArgs;
+
+        (void)ssl;
+
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+        if (args->exportBuf) {
+            XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
+            args->exportBuf = NULL;
+        }
+    #endif
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \
+                                           (!defined(NO_DH) && !defined(NO_RSA))
+        if (args->sigDataBuf) {
+            XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            args->sigDataBuf = NULL;
+        }
+    #endif
+    #ifndef NO_RSA
+        if (args->verifySig) {
+            XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+            args->verifySig = NULL;
+        }
+    #endif
+        (void)args;
+    }
+
+    /* handle generation of server_key_exchange (12) */
+    int SendServerKeyExchange(WOLFSSL* ssl)
+    {
+        int ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        SskeArgs* args = (SskeArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        SskeArgs  args[1];
+    #endif
+
+        WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
+        WOLFSSL_ENTER("SendServerKeyExchange");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_sske;
+        }
+        else
+    #endif
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(SskeArgs));
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeSskeArgs;
+        #endif
+        }
+
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+            #ifdef HAVE_QSH
+                if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) {
+                    args->qshSz = QSH_KeyGetSize(ssl);
+                }
+            #endif
+
+                /* Do some checks / debug msgs */
+                switch(ssl->specs.kea)
+                {
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        WOLFSSL_MSG("Using ephemeral ECDH PSK");
+                        break;
+                    }
+                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        if (ssl->specs.static_ecdh) {
+                            WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange");
+                            ERROR_OUT(0, exit_sske);
+                        }
+
+                        WOLFSSL_MSG("Using ephemeral ECDH");
+                        break;
+                    }
+                #endif /* HAVE_ECC */
+                }
+
+                /* Preparing keys */
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA))
+                #if !defined(NO_PSK)
+                    case dhe_psk_kea:
+                #endif
+                #if !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                #endif
+                    {
+                        /* Allocate DH key buffers and generate key */
+                        if (ssl->buffers.serverDH_P.buffer == NULL ||
+                            ssl->buffers.serverDH_G.buffer == NULL) {
+                            ERROR_OUT(NO_DH_PARAMS, exit_sske);
+                        }
+
+                        if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+                            ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
+                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+                                    ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                            if (ssl->buffers.serverDH_Pub.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+                        }
+
+                        if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+                            /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+                            ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
+                                    ssl->buffers.serverDH_P.length + OPAQUE16_LEN,
+                                    ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
+                            if (ssl->buffers.serverDH_Priv.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+                        }
+
+                        ssl->options.dhKeySz =
+                                (word16)ssl->buffers.serverDH_P.length;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_sske;
+                        }
+
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+                        if (ret != 0) {
+                            goto exit_sske;
+                        }
+
+                        ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            &ssl->buffers.serverDH_Priv.length,
+                            ssl->buffers.serverDH_Pub.buffer,
+                            &ssl->buffers.serverDH_Pub.length);
+                        break;
+                    }
+                #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                        /* Fall through to create temp ECC key */
+                #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            /* need ephemeral key now, create it if missing */
+                            if (ssl->eccTempKey == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->eccTempKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                            }
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                ret = X25519MakeKey(ssl,
+                                        (curve25519_key*)ssl->eccTempKey, NULL);
+                                if (ret == 0 || ret == WC_PENDING_E) {
+                                    ssl->eccTempKeyPresent =
+                                        DYNAMIC_TYPE_CURVE25519;
+                                }
+                            }
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_ECC
+                        /* need ephemeral key now, create it if missing */
+                        if (ssl->eccTempKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->eccTempKey);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        if (ssl->eccTempKeyPresent == 0) {
+                            ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
+                            if (ret == 0 || ret == WC_PENDING_E) {
+                                ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC;
+                            }
+                        }
+                    #endif
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                    default:
+                        /* Skip ServerKeyExchange */
+                        goto exit_sske;
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* case TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+            #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
+                                                       defined(HAVE_CURVE25519))
+                word32 preSigSz, preSigIdx;
+            #endif
+
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+                        if (ssl->arrays->server_hint[0] == 0) {
+                            ERROR_OUT(0, exit_sske); /* don't send */
+                        }
+
+                        /* include size part */
+                        args->length = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (args->length > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+
+                        args->length += HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get ouput buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* key data */
+                    #ifdef HAVE_QSH
+                        c16toa((word16)(args->length - args->qshSz -
+                                        HINT_LEN_SZ), args->output + args->idx);
+                    #else
+                        c16toa((word16)(args->length - HINT_LEN_SZ),
+                                                      args->output + args->idx);
+                    #endif
+
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->arrays->server_hint,
+                                args->length - HINT_LEN_SZ);
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        word32 hintLen;
+
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = LENGTH_SZ * 3 + /* p, g, pub */
+                                 ssl->buffers.serverDH_P.length +
+                                 ssl->buffers.serverDH_G.length +
+                                 ssl->buffers.serverDH_Pub.length;
+
+                        /* include size part */
+                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (hintLen > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+                        args->length += hintLen + HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get ouput buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* key data */
+                        c16toa((word16)hintLen, args->output + args->idx);
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                            ssl->arrays->server_hint, hintLen);
+                        args->idx += hintLen;
+
+                        /* add p, g, pub */
+                        c16toa((word16)ssl->buffers.serverDH_P.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_P.buffer,
+                                ssl->buffers.serverDH_P.length);
+                        args->idx += ssl->buffers.serverDH_P.length;
+
+                        /*  g */
+                        c16toa((word16)ssl->buffers.serverDH_G.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_G.buffer,
+                                ssl->buffers.serverDH_G.length);
+                        args->idx += ssl->buffers.serverDH_G.length;
+
+                        /*  pub */
+                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
+                            args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                ssl->buffers.serverDH_Pub.buffer,
+                                ssl->buffers.serverDH_Pub.length);
+                        /* No need to update idx, since sizes are already set */
+                        /* args->idx += ssl->buffers.serverDH_Pub.length; */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        word32 hintLen;
+
+                        /* curve type, named curve, length(1) */
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+                        args->exportSz = MAX_EXPORT_ECC_SZ;
+                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+                        if (args->exportBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            if (wc_curve25519_export_public_ex(
+                                    (curve25519_key*)ssl->eccTempKey,
+                                    args->exportBuf, &args->exportSz,
+                                    EC25519_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                        {
+                            if (wc_ecc_export_x963(ssl->eccTempKey,
+                                       args->exportBuf, &args->exportSz) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        args->length += args->exportSz;
+
+                        /* include size part */
+                        hintLen = (word32)XSTRLEN(ssl->arrays->server_hint);
+                        if (hintLen > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(SERVER_HINT_ERROR, exit_sske);
+                        }
+                        args->length += hintLen + HINT_LEN_SZ;
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                        }
+                    #endif
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get output buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        /* key data */
+                        c16toa((word16)hintLen, args->output + args->idx);
+                        args->idx += HINT_LEN_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                            ssl->arrays->server_hint, hintLen);
+                        args->idx += hintLen;
+
+                        /* ECC key exchange data */
+                        args->output[args->idx++] = named_curve;
+                        args->output[args->idx++] = 0x00;          /* leading zero */
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
+                        else
+                    #endif
+                        {
+                    #ifdef HAVE_ECC
+                            args->output[args->idx++] =
+                                                    SetCurveId(ssl->eccTempKey);
+                    #endif
+                        }
+                        args->output[args->idx++] = (byte)args->exportSz;
+                        XMEMCPY(args->output + args->idx, args->exportBuf,
+                                                                args->exportSz);
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        enum wc_HashType hashType;
+
+                        /* curve type, named curve, length(1) */
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN;
+
+                        /* Export temp ECC key and add to length */
+                        args->exportSz = MAX_EXPORT_ECC_SZ;
+                        args->exportBuf = (byte*)XMALLOC(args->exportSz,
+                                            ssl->heap, DYNAMIC_TYPE_DER);
+                        if (args->exportBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            if (wc_curve25519_export_public_ex(
+                                        (curve25519_key*)ssl->eccTempKey,
+                                        args->exportBuf, &args->exportSz,
+                                        EC25519_LITTLE_ENDIAN) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                        }
+                        else
+                    #endif
+                        {
+                    #ifdef HAVE_ECC
+                            if (wc_ecc_export_x963(ssl->eccTempKey,
+                                       args->exportBuf, &args->exportSz) != 0) {
+                                ERROR_OUT(ECC_EXPORT_ERROR, exit_sske);
+                            }
+                     #endif
+                        }
+                        args->length += args->exportSz;
+
+                        preSigSz  = args->length;
+                        preSigIdx = args->idx;
+
+                        if (ssl->buffers.key == NULL) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                                args->tmpSigSz = GetPrivateKeySigSize(ssl);
+                                if (args->tmpSigSz <= 0) {
+                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                                }
+                            }
+                            else
+                        #endif
+                                ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                        }
+                        else {
+                            switch(ssl->suites->sigAlgo) {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                word32 i = 0;
+                                int keySz;
+
+                                ssl->hsType = DYNAMIC_TYPE_RSA;
+                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                ret = wc_RsaPrivateKeyDecode(
+                                    ssl->buffers.key->buffer,
+                                    &i,
+                                    (RsaKey*)ssl->hsKey,
+                                    ssl->buffers.key->length);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                                keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+                                if (keySz < 0) { /* test if keySz has error */
+                                    ERROR_OUT(keySz, exit_sske);
+                                }
+
+                                args->tmpSigSz = (word32)keySz;
+                                if (keySz < ssl->options.minRsaKeySz) {
+                                    WOLFSSL_MSG("RSA signature key size too small");
+                                    ERROR_OUT(RSA_KEY_SIZE_E, exit_sske);
+                                }
+                                break;
+                            }
+                        #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
+                            case ecc_dsa_sa_algo:
+                            {
+                                word32 i = 0;
+
+                                ssl->hsType = DYNAMIC_TYPE_ECC;
+                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                ret = wc_EccPrivateKeyDecode(
+                                    ssl->buffers.key->buffer,
+                                    &i,
+                                    (ecc_key*)ssl->hsKey,
+                                    ssl->buffers.key->length);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                                /* worst case estimate */
+                                args->tmpSigSz = wc_ecc_sig_size(
+                                    (ecc_key*)ssl->hsKey);
+
+                                /* check the minimum ECC key size */
+                                if (wc_ecc_size((ecc_key*)ssl->hsKey) <
+                                        ssl->options.minEccKeySz) {
+                                    WOLFSSL_MSG("ECC key size too small");
+                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
+                                }
+                                break;
+                            }
+                        #endif
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                            {
+                                word32 i = 0;
+
+                                ssl->hsType = DYNAMIC_TYPE_ED25519;
+                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                ret = wc_Ed25519PrivateKeyDecode(
+                                    ssl->buffers.key->buffer,
+                                    &i,
+                                    (ed25519_key*)ssl->hsKey,
+                                    ssl->buffers.key->length);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                /* worst case estimate */
+                                args->tmpSigSz = ED25519_SIG_SIZE;
+
+                                /* check the minimum ECC key size */
+                                if (ED25519_KEY_SIZE <
+                                        ssl->options.minEccKeySz) {
+                                    WOLFSSL_MSG("Ed25519 key size too small");
+                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_sske);
+                                }
+                                break;
+                            }
+                        #endif /* HAVE_ED25519 */
+                            default:
+                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
+                            } /* switch(ssl->specs.sig_algo) */
+                        }
+
+                        /* sig length */
+                        args->length += LENGTH_SZ;
+                        args->length += args->tmpSigSz;
+
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            args->length += HASH_SIG_SIZE;
+                        }
+
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            preSigIdx = args->idx;
+                        }
+                    #endif
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get ouput buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        /* record and message headers will be added below, when we're sure
+                           of the sig length */
+
+                        /* key exchange data */
+                        args->output[args->idx++] = named_curve;
+                        args->output[args->idx++] = 0x00;          /* leading zero */
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID)
+                            args->output[args->idx++] = WOLFSSL_ECC_X25519;
+                        else
+                    #endif
+                        {
+                    #ifdef HAVE_ECC
+                            args->output[args->idx++] =
+                                                    SetCurveId(ssl->eccTempKey);
+                    #endif
+                        }
+                        args->output[args->idx++] = (byte)args->exportSz;
+                        XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz);
+                        args->idx += args->exportSz;
+
+                        /* Determine hash type */
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            EncodeSigAlg(ssl->suites->hashAlgo,
+                                         ssl->suites->sigAlgo,
+                                         &args->output[args->idx]);
+                            args->idx += 2;
+
+                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
+                            if (hashType == WC_HASH_TYPE_NONE) {
+                                ERROR_OUT(ALGO_ID_E, exit_sske);
+                            }
+
+                        } else {
+                            /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_sske);
+                        #endif
+                        }
+
+                        /* Signtaure length will be written later, when we're sure what it is */
+
+                    #ifdef HAVE_FUZZER
+                        if (ssl->fuzzerCb) {
+                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
+                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+                        }
+                    #endif
+
+                        /* Assemble buffer to hash for signature */
+                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->sigDataBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+                                                                       RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN,
+                                            ssl->arrays->serverRandom, RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+                                args->output + preSigIdx, preSigSz);
+
+                        if (ssl->suites->sigAlgo != ed25519_sa_algo) {
+                            ssl->buffers.sig.length =
+                                                 wc_HashGetDigestSize(hashType);
+                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
+                                            ssl->buffers.sig.length,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            if (ssl->buffers.sig.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+
+                            /* Perform hash */
+                            ret = wc_Hash(hashType, args->sigDataBuf,
+                                                       args->sigDataSz,
+                                                       ssl->buffers.sig.buffer,
+                                                       ssl->buffers.sig.length);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        args->sigSz = args->tmpSigSz;
+
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                            case rsa_sa_algo:
+                            {
+                                /* For TLS 1.2 re-encode signature */
+                                if (IsAtLeastTLSv1_2(ssl)) {
+                                    byte* encodedSig = (byte*)XMALLOC(
+                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    if (encodedSig == NULL) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+
+                                    ssl->buffers.sig.length =
+                                        wc_EncodeSignature(encodedSig,
+                                            ssl->buffers.sig.buffer,
+                                            ssl->buffers.sig.length,
+                                            TypeHash(ssl->suites->hashAlgo));
+
+                                    /* Replace sig buffer with new one */
+                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    ssl->buffers.sig.buffer = encodedSig;
+                                }
+
+                                /* write sig size here */
+                                c16toa((word16)args->sigSz,
+                                    args->output + args->idx);
+                                args->idx += LENGTH_SZ;
+                                break;
+                            }
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                                /* write sig size here */
+                                c16toa((word16)args->sigSz,
+                                    args->output + args->idx);
+                                args->idx += LENGTH_SZ;
+                                break;
+                        #endif
+                        #endif /* !NO_RSA */
+                            case ecc_dsa_sa_algo:
+                            {
+                                break;
+                            }
+                        #ifdef  HAVE_ED25519
+                            case ed25519_sa_algo:
+                                ret = Ed25519CheckPubKey(ssl);
+                                if (ret != 0)
+                                    goto exit_sske;
+                                break;
+                        #endif /* HAVE_ED25519 */
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        enum wc_HashType hashType;
+
+                        args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+                        args->length = LENGTH_SZ * 3;  /* p, g, pub */
+                        args->length += ssl->buffers.serverDH_P.length +
+                                        ssl->buffers.serverDH_G.length +
+                                        ssl->buffers.serverDH_Pub.length;
+
+                        preSigIdx = args->idx;
+                        preSigSz  = args->length;
+
+                        if (!ssl->options.usingAnon_cipher) {
+                            int keySz;
+
+                            /* sig length */
+                            args->length += LENGTH_SZ;
+
+                            if (ssl->buffers.key == NULL) {
+                            #ifdef HAVE_PK_CALLBACKS
+                                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                                    keySz = (word32)GetPrivateKeySigSize(ssl);
+                                else
+                            #endif
+                                    ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
+                            }
+                            else
+                            {
+                                word32 i = 0;
+
+                                ssl->hsType = DYNAMIC_TYPE_RSA;
+                                ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+
+                                ret = wc_RsaPrivateKeyDecode(
+                                    ssl->buffers.key->buffer, &i,
+                                    (RsaKey*)ssl->hsKey,
+                                    ssl->buffers.key->length);
+                                if (ret != 0) {
+                                    goto exit_sske;
+                                }
+                                keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+                            }
+
+                            if (keySz <= 0) { /* test if keySz has error */
+                                ERROR_OUT(keySz, exit_sske);
+                            }
+
+                            args->tmpSigSz = (word32)keySz;
+                            args->length += args->tmpSigSz;
+
+                            if (keySz < ssl->options.minRsaKeySz) {
+                                WOLFSSL_MSG("RSA key size too small");
+                                ERROR_OUT(RSA_KEY_SIZE_E, exit_sske);
+                            }
+
+                            if (IsAtLeastTLSv1_2(ssl)) {
+                                args->length += HASH_SIG_SIZE;
+                            }
+                        }
+
+                        args->sendSz = args->length + HANDSHAKE_HEADER_SZ +
+                                                            RECORD_HEADER_SZ;
+
+                    #ifdef HAVE_QSH
+                        args->length += args->qshSz;
+                        args->sendSz += args->qshSz;
+                    #endif
+                    #ifdef WOLFSSL_DTLS
+                        if (ssl->options.dtls) {
+                            args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            args->idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+                            preSigIdx = args->idx;
+                        }
+                    #endif
+
+                        /* check for available size */
+                        if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                            goto exit_sske;
+                        }
+
+                        /* get ouput buffer */
+                        args->output = ssl->buffers.outputBuffer.buffer +
+                                       ssl->buffers.outputBuffer.length;
+
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+
+                        /* add p, g, pub */
+                        c16toa((word16)ssl->buffers.serverDH_P.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_P.buffer,
+                                              ssl->buffers.serverDH_P.length);
+                        args->idx += ssl->buffers.serverDH_P.length;
+
+                        /*  g */
+                        c16toa((word16)ssl->buffers.serverDH_G.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_G.buffer,
+                                              ssl->buffers.serverDH_G.length);
+                        args->idx += ssl->buffers.serverDH_G.length;
+
+                        /*  pub */
+                        c16toa((word16)ssl->buffers.serverDH_Pub.length,
+                                                    args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+                        XMEMCPY(args->output + args->idx,
+                                              ssl->buffers.serverDH_Pub.buffer,
+                                              ssl->buffers.serverDH_Pub.length);
+                        args->idx += ssl->buffers.serverDH_Pub.length;
+
+                    #ifdef HAVE_FUZZER
+                        if (ssl->fuzzerCb) {
+                            ssl->fuzzerCb(ssl, args->output + preSigIdx,
+                                preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx);
+                        }
+                    #endif
+
+                        if (ssl->options.usingAnon_cipher) {
+                            break;
+                        }
+
+                        /* Determine hash type */
+                        if (IsAtLeastTLSv1_2(ssl)) {
+                            EncodeSigAlg(ssl->suites->hashAlgo,
+                                         ssl->suites->sigAlgo,
+                                         &args->output[args->idx]);
+                            args->idx += 2;
+
+                            hashType = HashAlgoToType(ssl->suites->hashAlgo);
+                            if (hashType == WC_HASH_TYPE_NONE) {
+                                ERROR_OUT(ALGO_ID_E, exit_sske);
+                            }
+                        } else {
+                            /* only using sha and md5 for rsa */
+                        #ifndef NO_OLD_TLS
+                            hashType = WC_HASH_TYPE_SHA;
+                            if (ssl->suites->sigAlgo == rsa_sa_algo) {
+                                hashType = WC_HASH_TYPE_MD5_SHA;
+                            }
+                        #else
+                            ERROR_OUT(ALGO_ID_E, exit_sske);
+                        #endif
+                        }
+
+                        /* signature size */
+                        c16toa((word16)args->tmpSigSz, args->output + args->idx);
+                        args->idx += LENGTH_SZ;
+
+                        /* Assemble buffer to hash for signature */
+                        args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz;
+                        args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz,
+                                            ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        if (args->sigDataBuf == NULL) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                        XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom,
+                                                                    RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN,
+                                        ssl->arrays->serverRandom, RAN_LEN);
+                        XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN,
+                            args->output + preSigIdx, preSigSz);
+
+                        if (ssl->suites->sigAlgo != ed25519_sa_algo) {
+                            ssl->buffers.sig.length =
+                                                 wc_HashGetDigestSize(hashType);
+                            ssl->buffers.sig.buffer = (byte*)XMALLOC(
+                                             ssl->buffers.sig.length, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                            if (ssl->buffers.sig.buffer == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_sske);
+                            }
+
+                            /* Perform hash */
+                            ret = wc_Hash(hashType, args->sigDataBuf,
+                                                       args->sigDataSz,
+                                                       ssl->buffers.sig.buffer,
+                                                       ssl->buffers.sig.length);
+                            if (ret != 0) {
+                                goto exit_sske;
+                            }
+                        }
+
+                        args->sigSz = args->tmpSigSz;
+
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                            case rsa_sa_algo:
+                            {
+                                /* For TLS 1.2 re-encode signature */
+                                if (IsAtLeastTLSv1_2(ssl)) {
+                                    byte* encodedSig = (byte*)XMALLOC(
+                                                  MAX_ENCODED_SIG_SZ, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    if (encodedSig == NULL) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+
+                                    ssl->buffers.sig.length =
+                                        wc_EncodeSignature(encodedSig,
+                                            ssl->buffers.sig.buffer,
+                                            ssl->buffers.sig.length,
+                                            TypeHash(ssl->suites->hashAlgo));
+
+                                    /* Replace sig buffer with new one */
+                                    XFREE(ssl->buffers.sig.buffer, ssl->heap,
+                                                       DYNAMIC_TYPE_SIGNATURE);
+                                    ssl->buffers.sig.buffer = encodedSig;
+                                }
+                                break;
+                            }
+                        #endif /* NO_RSA */
+                        } /* switch (ssl->suites->sigAlgo) */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* case TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                ret = RsaSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + args->idx,
+                                    &args->sigSz,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key,
+                                    ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif /* !NO_RSA */
+                        #ifdef HAVE_ECC
+                            case ecc_dsa_sa_algo:
+                            {
+                                ecc_key* key = (ecc_key*)ssl->hsKey;
+
+                                ret = EccSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + LENGTH_SZ + args->idx,
+                                    &args->sigSz,
+                                    key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
+                            #else
+                                    NULL
+                            #endif
+                                );
+                                break;
+                            }
+                        #endif /* HAVE_ECC */
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                            {
+                                ed25519_key* key = (ed25519_key*)ssl->hsKey;
+
+                                ret = Ed25519Sign(ssl,
+                                    args->sigDataBuf, args->sigDataSz,
+                                    args->output + LENGTH_SZ + args->idx,
+                                    &args->sigSz,
+                                    key,
+                            #ifdef HAVE_PK_CALLBACKS
+                                    ssl->buffers.key
+                            #else
+                                    NULL
+                            #endif
+                                );
+                                break;
+                            }
+                        #endif
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        /* Sign hash to create signature */
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (ssl->options.usingAnon_cipher) {
+                                    break;
+                                }
+
+                                ret = RsaSign(ssl,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    args->output + args->idx,
+                                    &args->sigSz,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key,
+                                    ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif /* NO_RSA */
+                        } /* switch (ssl->suites->sigAlgo) */
+
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* case TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+                switch(ssl->specs.kea)
+                {
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_PSK) */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        /* Nothing to do in this sub-state */
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        switch(ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifdef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (args->verifySig == NULL) {
+                                    if (args->sigSz == 0) {
+                                        ERROR_OUT(BAD_COND_E, exit_sske);
+                                    }
+                                    args->verifySig = (byte*)XMALLOC(
+                                                    args->sigSz, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+                                    if (!args->verifySig) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+                                    XMEMCPY(args->verifySig,
+                                        args->output + args->idx, args->sigSz);
+                                }
+
+                                /* check for signature faults */
+                                ret = VerifyRsaSign(ssl,
+                                    args->verifySig, args->sigSz,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key, ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif
+                            case ecc_dsa_sa_algo:
+                        #ifdef HAVE_ED25519
+                            case ed25519_sa_algo:
+                        #endif
+                            {
+                                /* Now that we know the real sig size, write it. */
+                                c16toa((word16)args->sigSz,
+                                                    args->output + args->idx);
+
+                                /* And adjust length and sendSz from estimates */
+                                args->length += args->sigSz - args->tmpSigSz;
+                                args->sendSz += args->sigSz - args->tmpSigSz;
+                                break;
+                            }
+                            default:
+                                ERROR_OUT(ALGO_ID_E, exit_sske);  /* unsupported type */
+                        } /* switch(ssl->specs.sig_algo) */
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #if !defined(NO_DH) && !defined(NO_RSA)
+                    case diffie_hellman_kea:
+                    {
+                        switch (ssl->suites->sigAlgo)
+                        {
+                        #ifndef NO_RSA
+                        #ifndef WC_RSA_PSS
+                            case rsa_pss_sa_algo:
+                        #endif
+                            case rsa_sa_algo:
+                            {
+                                RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                                if (ssl->options.usingAnon_cipher) {
+                                    break;
+                                }
+
+                                if (args->verifySig == NULL) {
+                                    if (args->sigSz == 0) {
+                                        ERROR_OUT(BAD_COND_E, exit_sske);
+                                    }
+                                    args->verifySig = (byte*)XMALLOC(
+                                                      args->sigSz, ssl->heap,
+                                                      DYNAMIC_TYPE_SIGNATURE);
+                                    if (!args->verifySig) {
+                                        ERROR_OUT(MEMORY_E, exit_sske);
+                                    }
+                                    XMEMCPY(args->verifySig,
+                                        args->output + args->idx, args->sigSz);
+                                }
+
+                                /* check for signature faults */
+                                ret = VerifyRsaSign(ssl,
+                                    args->verifySig, args->sigSz,
+                                    ssl->buffers.sig.buffer,
+                                    ssl->buffers.sig.length,
+                                    ssl->suites->sigAlgo, ssl->suites->hashAlgo,
+                                    key, ssl->buffers.key
+                                );
+                                break;
+                            }
+                        #endif
+                        } /* switch (ssl->suites->sigAlgo) */
+                        break;
+                    }
+                #endif /* !defined(NO_DH) && !defined(NO_RSA) */
+                } /* switch(ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* case TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+            #ifdef HAVE_QSH
+                if (ssl->peerQSHKeyPresent) {
+                    if (args->qshSz > 0) {
+                        args->idx = args->sendSz - args->qshSz;
+                        if (QSH_KeyExchangeWrite(ssl, 1) != 0) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+
+                        /* extension type */
+                        c16toa(TLSX_QUANTUM_SAFE_HYBRID,
+                                                    args->output + args->idx);
+                        args->idx += OPAQUE16_LEN;
+
+                        /* write to output and check amount written */
+                        if (TLSX_QSHPK_Write(ssl->QSH_secret->list,
+                            args->output + args->idx) >
+                                                args->qshSz - OPAQUE16_LEN) {
+                            ERROR_OUT(MEMORY_E, exit_sske);
+                        }
+                    }
+                }
+            #endif
+
+            #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                if (ssl->specs.kea == ecdhe_psk_kea ||
+                    ssl->specs.kea == ecc_diffie_hellman_kea) {
+                    /* Check output to make sure it was set */
+                    if (args->output) {
+                        AddHeaders(args->output, args->length,
+                                                    server_key_exchange, ssl);
+                    }
+                    else {
+                        ERROR_OUT(BUFFER_ERROR, exit_sske);
+                    }
+                }
+            #endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) {
+                        goto exit_sske;
+                    }
+                }
+
+                if (ssl->options.dtls)
+                    DtlsSEQIncrement(ssl, CUR_ORDER);
+            #endif
+
+                ret = HashOutput(ssl, args->output, args->sendSz, 0);
+                if (ret != 0) {
+                    goto exit_sske;
+                }
+
+            #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+                if (ssl->hsInfoOn) {
+                    AddPacketName(ssl, "ServerKeyExchange");
+                }
+                if (ssl->toInfoOn) {
+                    AddPacketInfo(ssl, "ServerKeyExchange", handshake,
+                        args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+                }
+            #endif
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* case TLS_ASYNC_FINALIZE */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_END:
+            {
+                ssl->buffers.outputBuffer.length += args->sendSz;
+                if (!ssl->options.groupMessages) {
+                    ret = SendBuffered(ssl);
+                }
+
+                ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+                break;
+            }
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_sske:
+
+        WOLFSSL_LEAVE("SendServerKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E)
+            return ret;
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        /* Final cleanup */
+        FreeSskeArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+
+    /* search suites for specific one, idx on success, negative on error */
+    static int FindSuite(Suites* suites, byte first, byte second)
+    {
+        int i;
+
+        if (suites == NULL || suites->suiteSz == 0) {
+            WOLFSSL_MSG("Suites pointer error or suiteSz 0");
+            return SUITES_ERROR;
+        }
+
+        for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
+            if (suites->suites[i]   == first &&
+                suites->suites[i+1] == second )
+                return i;
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+
+#endif
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+    /* Make sure server cert/key are valid for this suite, true on success */
+    static int VerifyServerSuite(WOLFSSL* ssl, word16 idx)
+    {
+        int  haveRSA = !ssl->options.haveStaticECC;
+        int  havePSK = 0;
+        byte first;
+        byte second;
+
+        WOLFSSL_ENTER("VerifyServerSuite");
+
+        if (ssl->suites == NULL) {
+            WOLFSSL_MSG("Suites pointer error");
+            return 0;
+        }
+
+        first   = ssl->suites->suites[idx];
+        second  = ssl->suites->suites[idx+1];
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+
+        if (ssl->options.haveNTRU)
+            haveRSA = 0;
+
+        if (CipherRequires(first, second, REQUIRES_RSA)) {
+            WOLFSSL_MSG("Requires RSA");
+            if (haveRSA == 0) {
+                WOLFSSL_MSG("Don't have RSA");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_DHE)) {
+            WOLFSSL_MSG("Requires DHE");
+            if (ssl->options.haveDH == 0) {
+                WOLFSSL_MSG("Don't have DHE");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_ECC)) {
+            WOLFSSL_MSG("Requires ECC");
+            if (ssl->options.haveECC == 0) {
+                WOLFSSL_MSG("Don't have ECC");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_ECC_STATIC)) {
+            WOLFSSL_MSG("Requires static ECC");
+            if (ssl->options.haveStaticECC == 0) {
+                WOLFSSL_MSG("Don't have static ECC");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_PSK)) {
+            WOLFSSL_MSG("Requires PSK");
+            if (havePSK == 0) {
+                WOLFSSL_MSG("Don't have PSK");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_NTRU)) {
+            WOLFSSL_MSG("Requires NTRU");
+            if (ssl->options.haveNTRU == 0) {
+                WOLFSSL_MSG("Don't have NTRU");
+                return 0;
+            }
+        }
+
+        if (CipherRequires(first, second, REQUIRES_RSA_SIG)) {
+            WOLFSSL_MSG("Requires RSA Signature");
+            if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                           ssl->options.haveECDSAsig == 1) {
+                WOLFSSL_MSG("Don't have RSA Signature");
+                return 0;
+            }
+        }
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                  defined(HAVE_SUPPORTED_CURVES)
+        if (!TLSX_ValidateSupportedCurves(ssl, first, second)) {
+            WOLFSSL_MSG("Don't have matching curves");
+            return 0;
+        }
+#endif
+
+        /* ECCDHE is always supported if ECC on */
+
+#ifdef HAVE_QSH
+        /* need to negotiate a classic suite in addition to TLS_QSH */
+        if (first == QSH_BYTE && second == TLS_QSH) {
+            if (TLSX_SupportExtensions(ssl)) {
+                ssl->options.haveQSH = 1; /* matched TLS_QSH */
+            }
+            else {
+                WOLFSSL_MSG("Version of SSL connection does not support "
+                            "TLS_QSH");
+            }
+            return 0;
+        }
+#endif
+
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version) &&
+            ssl->options.side == WOLFSSL_SERVER_END) {
+            /* Try to establish a key share. */
+            int ret = TLSX_KeyShare_Establish(ssl);
+            if (ret == KEY_SHARE_ERROR)
+                ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+            else if (ret != 0)
+                return 0;
+        }
+        else if (first == TLS13_BYTE) {
+            /* Can't negotiate TLS 1.3 ciphersuites with lower protocol
+             * version. */
+            return 0;
+        }
+#endif
+
+        return 1;
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i,
+                             word16 j)
+    {
+        if (ssl->suites->suites[i]   == peerSuites->suites[j] &&
+            ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
+
+            if (VerifyServerSuite(ssl, i)) {
+                int result;
+                WOLFSSL_MSG("Verified suite validity");
+                ssl->options.cipherSuite0 = ssl->suites->suites[i];
+                ssl->options.cipherSuite  = ssl->suites->suites[i+1];
+                result = SetCipherSpecs(ssl);
+                if (result == 0)
+                    PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
+                                    peerSuites->hashSigAlgoSz);
+                return result;
+            }
+            else {
+                WOLFSSL_MSG("Could not verify suite validity, continue");
+            }
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+
+    int MatchSuite(WOLFSSL* ssl, Suites* peerSuites)
+    {
+        int ret;
+        word16 i, j;
+
+        WOLFSSL_ENTER("MatchSuite");
+
+        /* & 0x1 equivalent % 2 */
+        if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
+            return MATCH_SUITE_ERROR;
+
+        if (ssl->suites == NULL)
+            return SUITES_ERROR;
+
+        if (!ssl->options.useClientOrder) {
+            /* Server order */
+            for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+                for (j = 0; j < peerSuites->suiteSz; j += 2) {
+                    ret = CompareSuites(ssl, peerSuites, i, j);
+                    if (ret != MATCH_SUITE_ERROR)
+                        return ret;
+                }
+            }
+        }
+        else {
+            /* Client order */
+            for (j = 0; j < peerSuites->suiteSz; j += 2) {
+                for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+                    ret = CompareSuites(ssl, peerSuites, i, j);
+                    if (ret != MATCH_SUITE_ERROR)
+                        return ret;
+                }
+            }
+        }
+
+        return MATCH_SUITE_ERROR;
+    }
+#endif
+
+#ifdef OLD_HELLO_ALLOWED
+
+    /* process old style client hello, deprecate? */
+    int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              word32 inSz, word16 sz)
+    {
+        word32          idx = *inOutIdx;
+        word16          sessionSz;
+        word16          randomSz;
+        word16          i, j;
+        ProtocolVersion pv;
+        Suites          clSuites;
+        int ret = -1;
+
+        (void)inSz;
+        WOLFSSL_MSG("Got old format client hello");
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn)
+            AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+        /* manually hash input since different format */
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+        wc_Md5Update(&ssl->hsHashes->hashMd5, input + idx, sz);
+#endif
+#ifndef NO_SHA
+        wc_ShaUpdate(&ssl->hsHashes->hashSha, input + idx, sz);
+#endif
+#endif
+#ifndef NO_SHA256
+        if (IsAtLeastTLSv1_2(ssl)) {
+            int shaRet = wc_Sha256Update(&ssl->hsHashes->hashSha256,
+                                         input + idx, sz);
+            if (shaRet != 0)
+                return shaRet;
+        }
+#endif
+
+        /* does this value mean client_hello? */
+        idx++;
+
+        /* version */
+        pv.major = input[idx++];
+        pv.minor = input[idx++];
+        ssl->chVersion = pv;  /* store */
+
+        if (ssl->version.minor > pv.minor) {
+            byte haveRSA = 0;
+            byte havePSK = 0;
+            int  keySz   = 0;
+
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("Client trying to connect with lesser version");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                /* turn off tls 1.1+ */
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+#ifndef NO_RSA
+            haveRSA = 1;
+#endif
+#ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+#endif
+#ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+#endif
+
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+        }
+
+        /* suite size */
+        ato16(&input[idx], &clSuites.suiteSz);
+        idx += OPAQUE16_LEN;
+
+        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+            return BUFFER_ERROR;
+        clSuites.hashSigAlgoSz = 0;
+
+        /* session size */
+        ato16(&input[idx], &sessionSz);
+        idx += OPAQUE16_LEN;
+
+        if (sessionSz > ID_LEN)
+            return BUFFER_ERROR;
+
+        /* random size */
+        ato16(&input[idx], &randomSz);
+        idx += OPAQUE16_LEN;
+
+        if (randomSz > RAN_LEN)
+            return BUFFER_ERROR;
+
+        /* suites */
+        for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
+            byte first = input[idx++];
+            if (!first) { /* implicit: skip sslv2 type */
+                XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN);
+                j += SUITE_LEN;
+            }
+            idx += SUITE_LEN;
+        }
+        clSuites.suiteSz = j;
+
+        /* session id */
+        if (sessionSz) {
+            XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
+            ssl->arrays->sessionIDSz = (byte)sessionSz;
+            idx += sessionSz;
+            ssl->options.resuming = 1;
+        }
+
+        /* random */
+        if (randomSz < RAN_LEN)
+            XMEMSET(ssl->arrays->clientRandom, 0, RAN_LEN - randomSz);
+        XMEMCPY(&ssl->arrays->clientRandom[RAN_LEN - randomSz], input + idx,
+               randomSz);
+        idx += randomSz;
+
+        if (ssl->options.usingCompression)
+            ssl->options.usingCompression = 0;  /* turn off */
+
+        ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+        ssl->cbmode = SSL_CB_MODE_WRITE;
+        *inOutIdx = idx;
+
+        ssl->options.haveSessionId = 1;
+        /* DoClientHello uses same resume code */
+        if (ssl->options.resuming) {  /* let's try */
+            WOLFSSL_SESSION* session = GetSession(ssl,
+                                                  ssl->arrays->masterSecret, 1);
+            #ifdef HAVE_SESSION_TICKET
+                if (ssl->options.useTicket == 1) {
+                    session = &ssl->session;
+                }
+            #endif
+
+            if (!session) {
+                WOLFSSL_MSG("Session lookup for resume failed");
+                ssl->options.resuming = 0;
+            } else {
+            #ifdef HAVE_EXT_CACHE
+                wolfSSL_SESSION_free(session);
+            #endif
+                if (MatchSuite(ssl, &clSuites) < 0) {
+                    WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
+                    return UNSUPPORTED_SUITE;
+                }
+
+                ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+                                                                       RAN_LEN);
+                if (ret != 0)
+                    return ret;
+
+                #ifdef NO_OLD_TLS
+                    ret = DeriveTlsKeys(ssl);
+                #else
+                    #ifndef NO_TLS
+                        if (ssl->options.tls)
+                            ret = DeriveTlsKeys(ssl);
+                    #endif
+                        if (!ssl->options.tls)
+                            ret = DeriveKeys(ssl);
+                #endif
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+                return ret;
+            }
+        }
+
+        ret = MatchSuite(ssl, &clSuites);
+        if (ret != 0)return ret;
+        return SanityCheckMsgReceived(ssl, client_hello);
+    }
+
+#endif /* OLD_HELLO_ALLOWED */
+
+#ifndef WOLFSSL_NO_TLS12
+
+    int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites)
+    {
+        int ret = 0;
+        WOLFSSL_SESSION* session = GetSession(ssl,
+                                                  ssl->arrays->masterSecret, 1);
+
+        (void)bogusID;
+
+        #ifdef HAVE_SESSION_TICKET
+            if (ssl->options.useTicket == 1) {
+                session = &ssl->session;
+            } else if (bogusID == 1 && ssl->options.rejectTicket == 0) {
+                WOLFSSL_MSG("Bogus session ID without session ticket");
+                return BUFFER_ERROR;
+            }
+        #endif
+
+        if (!session) {
+            WOLFSSL_MSG("Session lookup for resume failed");
+            ssl->options.resuming = 0;
+        }
+        else if (session->haveEMS != ssl->options.haveEMS) {
+            /* RFC 7627, 5.3, server-side */
+            /* if old sess didn't have EMS, but new does, full handshake */
+            if (!session->haveEMS && ssl->options.haveEMS) {
+                WOLFSSL_MSG("Attempting to resume a session that didn't "
+                            "use EMS with a new session with EMS. Do full "
+                            "handshake.");
+                ssl->options.resuming = 0;
+            }
+            /* if old sess used EMS, but new doesn't, MUST abort */
+            else if (session->haveEMS && !ssl->options.haveEMS) {
+                WOLFSSL_MSG("Trying to resume a session with EMS without "
+                            "using EMS");
+                return EXT_MASTER_SECRET_NEEDED_E;
+            }
+        #ifdef HAVE_EXT_CACHE
+            wolfSSL_SESSION_free(session);
+        #endif
+        }
+        else {
+        #ifdef HAVE_EXT_CACHE
+            wolfSSL_SESSION_free(session);
+        #endif
+            if (MatchSuite(ssl, clSuites) < 0) {
+                WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
+                return UNSUPPORTED_SUITE;
+            }
+
+            ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+                                                                       RAN_LEN);
+            if (ret != 0)
+                return ret;
+
+            #ifdef NO_OLD_TLS
+                ret = DeriveTlsKeys(ssl);
+            #else
+                #ifndef NO_TLS
+                    if (ssl->options.tls)
+                        ret = DeriveTlsKeys(ssl);
+                #endif
+                    if (!ssl->options.tls)
+                        ret = DeriveKeys(ssl);
+            #endif
+            ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+        }
+
+        return ret;
+    }
+
+
+    /* handle processing of client_hello (1) */
+    int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                             word32 helloSz)
+    {
+        byte            b;
+        byte            bogusID = 0;   /* flag for a bogus session id */
+        ProtocolVersion pv;
+        Suites          clSuites;
+        word32          i = *inOutIdx;
+        word32          begin = i;
+        int             ret = 0;
+#ifdef WOLFSSL_DTLS
+        Hmac            cookieHmac;
+        byte            peerCookie[MAX_COOKIE_LEN];
+        byte            peerCookieSz = 0;
+        byte            cookieType;
+        byte            cookieSz = 0;
+
+        XMEMSET(&cookieHmac, 0, sizeof(Hmac));
+#endif /* WOLFSSL_DTLS */
+
+        WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
+        WOLFSSL_ENTER("DoClientHello");
+
+#ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+        if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+        /* protocol version, random and session id length check */
+        if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        /* protocol version */
+        XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+        ssl->chVersion = pv;   /* store */
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            #if defined(NO_SHA) && defined(NO_SHA256)
+                #error "DTLS needs either SHA or SHA-256"
+            #endif /* NO_SHA && NO_SHA256 */
+
+            #if !defined(NO_SHA) && defined(NO_SHA256)
+                cookieType = WC_SHA;
+                cookieSz = WC_SHA_DIGEST_SIZE;
+            #endif /* NO_SHA */
+            #ifndef NO_SHA256
+                cookieType = WC_SHA256;
+                cookieSz = WC_SHA256_DIGEST_SIZE;
+            #endif /* NO_SHA256 */
+            ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                                ssl->buffers.dtlsCookieSecret.buffer,
+                                ssl->buffers.dtlsCookieSecret.length);
+            if (ret != 0) return ret;
+            ret = wc_HmacUpdate(&cookieHmac,
+                                (const byte*)ssl->buffers.dtlsCtx.peer.sa,
+                                ssl->buffers.dtlsCtx.peer.sz);
+            if (ret != 0) return ret;
+            ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += OPAQUE16_LEN;
+
+        /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
+        if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
+            pv.minor = TLSv1_2_MINOR;
+
+        if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
+            (ssl->options.dtls && ssl->version.minor != DTLS_MINOR
+             && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR
+             && pv.minor != DTLSv1_2_MINOR)) {
+
+            word16 haveRSA = 0;
+            word16 havePSK = 0;
+            int    keySz   = 0;
+
+            if (!ssl->options.downgrade) {
+                WOLFSSL_MSG("Client trying to connect with lesser version");
+                return VERSION_ERROR;
+            }
+            if (pv.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (pv.minor == SSLv3_MINOR) {
+                /* turn off tls */
+                WOLFSSL_MSG("\tdowngrading to SSLv3");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = SSLv3_MINOR;
+            }
+            else if (pv.minor == TLSv1_MINOR) {
+                /* turn off tls 1.1+ */
+                WOLFSSL_MSG("\tdowngrading to TLSv1");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor  = TLSv1_MINOR;
+            }
+            else if (pv.minor == TLSv1_1_MINOR) {
+                WOLFSSL_MSG("\tdowngrading to TLSv1.1");
+                ssl->version.minor  = TLSv1_1_MINOR;
+            }
+            else if (pv.minor == TLSv1_2_MINOR) {
+                WOLFSSL_MSG("    downgrading to TLSv1.2");
+                ssl->version.minor  = TLSv1_2_MINOR;
+            }
+#ifndef NO_RSA
+            haveRSA = 1;
+#endif
+#ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+#endif
+#ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+#endif
+            InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+        }
+
+#ifdef OPENSSL_EXTRA
+        /* check if option is set to not allow the current version
+         * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */
+        if (!ssl->options.dtls && ssl->options.downgrade &&
+                ssl->options.mask > 0) {
+            int reset = 0;
+            if (ssl->version.minor == TLSv1_2_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading");
+                ssl->version.minor = TLSv1_1_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == TLSv1_1_MINOR &&
+             (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading");
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = TLSv1_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == TLSv1_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+                WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading");
+                ssl->options.tls    = 0;
+                ssl->options.tls1_1 = 0;
+                ssl->version.minor = SSLv3_MINOR;
+                reset = 1;
+            }
+            if (ssl->version.minor == SSLv3_MINOR &&
+                (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+                WOLFSSL_MSG("\tError, option set to not allow SSLv3");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->version.minor < ssl->options.minDowngrade) {
+                WOLFSSL_MSG("\tversion below minimum allowed, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (reset) {
+                word16 haveRSA = 0;
+                word16 havePSK = 0;
+                int    keySz   = 0;
+
+            #ifndef NO_RSA
+                haveRSA = 1;
+            #endif
+            #ifndef NO_PSK
+                havePSK = ssl->options.havePSK;
+            #endif
+            #ifndef NO_CERTS
+                keySz = ssl->buffers.keySz;
+            #endif
+
+                /* reset cipher suites to account for TLS version change */
+                InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+            }
+        }
+#endif
+
+        /* random */
+        XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+        {
+            int j;
+            printf("client random: ");
+            for (j = 0; j < RAN_LEN; j++)
+                printf("%02x", ssl->arrays->clientRandom[j]);
+            printf("\n");
+        }
+#endif
+
+        /* session id */
+        b = input[i++];
+
+#ifdef HAVE_SESSION_TICKET
+        if (b > 0 && b < ID_LEN) {
+            bogusID = 1;
+            WOLFSSL_MSG("Client sent bogus session id, let's allow for echo");
+        }
+#endif
+
+        if (b == ID_LEN || bogusID) {
+            if ((i - begin) + b > helloSz)
+                return BUFFER_ERROR;
+
+            XMEMCPY(ssl->arrays->sessionID, input + i, b);
+#ifdef WOLFSSL_DTLS
+            if (IsDtlsNotSctpMode(ssl)) {
+                ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+                if (ret != 0) return ret;
+            }
+#endif /* WOLFSSL_DTLS */
+            ssl->arrays->sessionIDSz = b;
+            i += b;
+            ssl->options.resuming = 1; /* client wants to resume */
+            WOLFSSL_MSG("Client wants to resume session");
+        }
+        else if (b) {
+            WOLFSSL_MSG("Invalid session ID size");
+            return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
+        }
+
+        #ifdef WOLFSSL_DTLS
+            /* cookie */
+            if (ssl->options.dtls) {
+
+                if ((i - begin) + OPAQUE8_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                peerCookieSz = input[i++];
+
+                if (peerCookieSz) {
+                    if (peerCookieSz > MAX_COOKIE_LEN)
+                        return BUFFER_ERROR;
+
+                    if ((i - begin) + peerCookieSz > helloSz)
+                        return BUFFER_ERROR;
+
+                    XMEMCPY(peerCookie, input + i, peerCookieSz);
+
+                    i += peerCookieSz;
+                }
+            }
+        #endif
+
+        /* suites */
+        if ((i - begin) + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        ato16(&input[i], &clSuites.suiteSz);
+        i += OPAQUE16_LEN;
+
+        /* suites and compression length check */
+        if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
+            return BUFFER_ERROR;
+
+        if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+            return BUFFER_ERROR;
+
+        XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+        /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
+        if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
+            ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
+            if (ret != WOLFSSL_SUCCESS)
+                return ret;
+        }
+#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            ret = wc_HmacUpdate(&cookieHmac,
+                                    input + i - OPAQUE16_LEN,
+                                    clSuites.suiteSz + OPAQUE16_LEN);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+        i += clSuites.suiteSz;
+        clSuites.hashSigAlgoSz = 0;
+
+        /* compression length */
+        b = input[i++];
+
+        if ((i - begin) + b > helloSz)
+            return BUFFER_ERROR;
+
+        if (b == 0) {
+            WOLFSSL_MSG("No compression types in list");
+            return COMPRESSION_ERROR;
+        }
+
+#ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            byte newCookie[MAX_COOKIE_LEN];
+
+            ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
+            if (ret != 0) return ret;
+            ret = wc_HmacFinal(&cookieHmac, newCookie);
+            if (ret != 0) return ret;
+
+            /* If a cookie callback is set, call it to overwrite the cookie.
+             * This should be deprecated. The code now calculates the cookie
+             * using an HMAC as expected. */
+            if (ssl->ctx->CBIOCookie != NULL &&
+                ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
+                                             ssl->IOCB_CookieCtx) != cookieSz) {
+                return COOKIE_ERROR;
+            }
+
+            /* Check the cookie, see if we progress the state machine. */
+            if (peerCookieSz != cookieSz ||
+                XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
+
+                /* Send newCookie to client in a HelloVerifyRequest message
+                 * and let the state machine alone. */
+                ssl->msgsReceived.got_client_hello = 0;
+                ssl->keys.dtls_handshake_number = 0;
+                ssl->keys.dtls_expected_peer_handshake_number = 0;
+                *inOutIdx += helloSz;
+                return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
+            }
+
+            /* This was skipped in the DTLS case so we could handle the hello
+             * verify request. */
+            ret = HashInput(ssl, input + *inOutIdx, helloSz);
+            if (ret != 0) return ret;
+        }
+#endif /* WOLFSSL_DTLS */
+
+        {
+            /* copmression match types */
+            int matchNo = 0;
+            int matchZlib = 0;
+
+            while (b--) {
+                byte comp = input[i++];
+
+                if (comp == NO_COMPRESSION) {
+                    matchNo = 1;
+                }
+                if (comp == ZLIB_COMPRESSION) {
+                    matchZlib = 1;
+                }
+            }
+
+            if (ssl->options.usingCompression == 0 && matchNo) {
+                WOLFSSL_MSG("Matched No Compression");
+            } else if (ssl->options.usingCompression && matchZlib) {
+                WOLFSSL_MSG("Matched zlib Compression");
+            } else if (ssl->options.usingCompression && matchNo) {
+                WOLFSSL_MSG("Could only match no compression, turning off");
+                ssl->options.usingCompression = 0;  /* turn off */
+            } else {
+                WOLFSSL_MSG("Could not match compression");
+                return COMPRESSION_ERROR;
+            }
+        }
+
+        *inOutIdx = i;
+
+        /* tls extensions */
+        if ((i - begin) < helloSz) {
+#ifdef HAVE_TLS_EXTENSIONS
+        #ifdef HAVE_QSH
+            QSH_Init(ssl);
+        #endif
+            if (TLSX_SupportExtensions(ssl))
+#else
+            if (IsAtLeastTLSv1_2(ssl))
+#endif
+            {
+                /* Process the hello extension. Skip unsupported. */
+                word16 totalExtSz;
+
+#ifdef HAVE_TLS_EXTENSIONS
+                /* auto populate extensions supported unless user defined */
+                if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
+                    return ret;
+#endif
+
+                if ((i - begin) + OPAQUE16_LEN > helloSz)
+                    return BUFFER_ERROR;
+
+                ato16(&input[i], &totalExtSz);
+                i += OPAQUE16_LEN;
+
+                if ((i - begin) + totalExtSz > helloSz)
+                    return BUFFER_ERROR;
+
+#ifdef HAVE_TLS_EXTENSIONS
+                /* tls extensions */
+                if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz,
+                                      client_hello, &clSuites)))
+                    return ret;
+    #ifdef WOLFSSL_TLS13
+                if (TLSX_Find(ssl->extensions,
+                                             TLSX_SUPPORTED_VERSIONS) != NULL) {
+                    WOLFSSL_MSG(
+                            "Client attempting to connect with higher version");
+                    return VERSION_ERROR;
+                }
+    #endif
+    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+                if((ret=SNI_Callback(ssl)))
+                    return ret;
+                ssl->options.side = WOLFSSL_SERVER_END;
+    #endif
+
+                i += totalExtSz;
+#else
+                while (totalExtSz) {
+                    word16 extId, extSz;
+
+                    if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
+                        return BUFFER_ERROR;
+
+                    ato16(&input[i], &extId);
+                    i += OPAQUE16_LEN;
+                    ato16(&input[i], &extSz);
+                    i += OPAQUE16_LEN;
+
+                    if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
+                        return BUFFER_ERROR;
+
+                    if (extId == HELLO_EXT_SIG_ALGO) {
+                        word16 hashSigAlgoSz;
+
+                        ato16(&input[i], &hashSigAlgoSz);
+                        i += OPAQUE16_LEN;
+
+                        if (OPAQUE16_LEN + hashSigAlgoSz > extSz)
+                            return BUFFER_ERROR;
+
+                        clSuites.hashSigAlgoSz = hashSigAlgoSz;
+                        if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+                            WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
+                                                                  "truncating");
+                            clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+                        }
+
+                        XMEMCPY(clSuites.hashSigAlgo, &input[i],
+                                                      clSuites.hashSigAlgoSz);
+
+                        i += hashSigAlgoSz;
+                    }
+#ifdef HAVE_EXTENDED_MASTER
+                    else if (extId == HELLO_EXT_EXTMS)
+                        ssl->options.haveEMS = 1;
+#endif
+                    else
+                        i += extSz;
+
+                    totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+                }
+#endif
+                *inOutIdx = i;
+            }
+            else
+                *inOutIdx = begin + helloSz; /* skip extensions */
+        }
+
+        ssl->options.clientState   = CLIENT_HELLO_COMPLETE;
+        ssl->options.haveSessionId = 1;
+
+        /* ProcessOld uses same resume code */
+        if (ssl->options.resuming) {
+            ret = HandleTlsResumption(ssl, bogusID, &clSuites);
+            if (ret != 0)
+                return ret;
+            if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
+                WOLFSSL_LEAVE("DoClientHello", ret);
+                WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+                return ret;
+            }
+        }
+        ret = MatchSuite(ssl, &clSuites);
+
+        WOLFSSL_LEAVE("DoClientHello", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+        return ret;
+    }
+
+
+#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \
+                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+
+    typedef struct DcvArgs {
+        byte*  output; /* not allocated */
+        word32 sendSz;
+        word16 sz;
+        word32 sigSz;
+        word32 idx;
+        word32 begin;
+        byte   hashAlgo;
+        byte   sigAlgo;
+    } DcvArgs;
+
+    static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        DcvArgs* args = (DcvArgs*)pArgs;
+
+        (void)ssl;
+        (void)args;
+    }
+
+    /* handle processing of certificate_verify (15) */
+    static int DoCertificateVerify(WOLFSSL* ssl, byte* input,
+                                word32* inOutIdx, word32 size)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        DcvArgs* args = (DcvArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        DcvArgs  args[1];
+    #endif
+
+        WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
+        WOLFSSL_ENTER("DoCertificateVerify");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_dcv;
+        }
+        else
+    #endif
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(DcvArgs));
+            args->hashAlgo = sha_mac;
+            args->sigAlgo = anonymous_sa_algo;
+            args->idx = *inOutIdx;
+            args->begin = *inOutIdx;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeDcvArgs;
+        #endif
+        }
+
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+            #ifdef WOLFSSL_CALLBACKS
+                if (ssl->hsInfoOn)
+                    AddPacketName(ssl, "CertificateVerify");
+                if (ssl->toInfoOn)
+                    AddLateName("CertificateVerify", &ssl->timeoutInfo);
+            #endif
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* case TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+                if (IsAtLeastTLSv1_2(ssl)) {
+                    if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) {
+                        ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                    }
+
+                    DecodeSigAlg(&input[args->idx], &args->hashAlgo,
+                                 &args->sigAlgo);
+                    args->idx += 2;
+                }
+            #ifndef NO_RSA
+                else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0)
+                    args->sigAlgo = rsa_sa_algo;
+            #endif
+            #ifdef HAVE_ECC
+                else if (ssl->peerEccDsaKeyPresent)
+                    args->sigAlgo = ecc_dsa_sa_algo;
+            #endif
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                else if (ssl->peerEd25519KeyPresent)
+                    args->sigAlgo = ed25519_sa_algo;
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+
+                if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                }
+
+                ato16(input + args->idx, &args->sz);
+                args->idx += OPAQUE16_LEN;
+
+                if ((args->idx - args->begin) + args->sz > size ||
+                                                    args->sz > ENCRYPT_LEN) {
+                    ERROR_OUT(BUFFER_ERROR, exit_dcv);
+                }
+
+            #ifdef HAVE_ECC
+                if (ssl->peerEccDsaKeyPresent) {
+
+                    WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                /* make sure a default is defined */
+                #if !defined(NO_SHA)
+                    SetDigest(ssl, sha_mac);
+                #elif !defined(NO_SHA256)
+                    SetDigest(ssl, sha256_mac);
+                #elif defined(WOLFSSL_SHA384)
+                    SetDigest(ssl, sha384_mac);
+                #elif defined(WOLFSSL_SHA512)
+                    SetDigest(ssl, sha512_mac);
+                #else
+                    #error No digest enabled for ECC sig verify
+                #endif
+
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                        if (args->sigAlgo != ecc_dsa_sa_algo) {
+                            WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+                        }
+
+                        SetDigest(ssl, args->hashAlgo);
+                    }
+                }
+            #endif /* HAVE_ECC */
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                if (ssl->peerEd25519KeyPresent) {
+                    WOLFSSL_MSG("Doing ED25519 peer cert verify");
+                    if (IsAtLeastTLSv1_2(ssl) &&
+                                             args->sigAlgo != ed25519_sa_algo) {
+                        WOLFSSL_MSG(
+                               "Oops, peer sent ED25519 key but not in verify");
+                    }
+                }
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* case TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+            #ifndef NO_RSA
+                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                    WOLFSSL_MSG("Doing RSA peer cert verify");
+
+                    ret = RsaVerify(ssl,
+                        input + args->idx,
+                        args->sz,
+                        &args->output,
+                        args->sigAlgo, args->hashAlgo,
+                        ssl->peerRsaKey,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerRsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+                    if (ret >= 0) {
+                        if (args->sigAlgo == rsa_sa_algo)
+                            args->sendSz = ret;
+                        else {
+                            args->sigSz = ret;
+                            args->sendSz = ssl->buffers.digest.length;
+                        }
+                        ret = 0;
+                    }
+                }
+            #endif /* !NO_RSA */
+            #ifdef HAVE_ECC
+                if (ssl->peerEccDsaKeyPresent) {
+                    WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                    ret = EccVerify(ssl,
+                        input + args->idx, args->sz,
+                        ssl->buffers.digest.buffer, ssl->buffers.digest.length,
+                        ssl->peerEccDsaKey,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEccDsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
+            #endif /* HAVE_ECC */
+            #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+                if (ssl->peerEd25519KeyPresent) {
+                    WOLFSSL_MSG("Doing Ed25519 peer cert verify");
+
+                    ret = Ed25519Verify(ssl,
+                        input + args->idx, args->sz,
+                        ssl->hsHashes->messages, ssl->hsHashes->prevLen,
+                        ssl->peerEd25519Key,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEd25519Key
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
+            #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcv;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* case TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+            #ifndef NO_RSA
+                if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                    if (IsAtLeastTLSv1_2(ssl)) {
+                    #ifdef WC_RSA_PSS
+                        if (args->sigAlgo == rsa_pss_sa_algo) {
+                            SetDigest(ssl, args->hashAlgo);
+
+                            ret = wc_RsaPSS_CheckPadding(
+                                             ssl->buffers.digest.buffer,
+                                             ssl->buffers.digest.length,
+                                             args->output, args->sigSz,
+                                             HashAlgoToType(args->hashAlgo));
+                            if (ret != 0)
+                                goto exit_dcv;
+                        }
+                        else
+                    #endif
+                        {
+                        #ifdef WOLFSSL_SMALL_STACK
+                            byte* encodedSig = NULL;
+                        #else
+                            byte  encodedSig[MAX_ENCODED_SIG_SZ];
+                        #endif
+
+                        #ifdef WOLFSSL_SMALL_STACK
+                            encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                                                ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                            if (encodedSig == NULL) {
+                                ERROR_OUT(MEMORY_E, exit_dcv);
+                            }
+                        #endif
+
+                            if (args->sigAlgo != rsa_sa_algo) {
+                                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
+                            }
+
+                            SetDigest(ssl, args->hashAlgo);
+
+                            args->sigSz = wc_EncodeSignature(encodedSig,
+                                ssl->buffers.digest.buffer,
+                                ssl->buffers.digest.length,
+                                TypeHash(args->hashAlgo));
+
+                            if (args->sendSz != args->sigSz || !args->output ||
+                                XMEMCMP(args->output, encodedSig,
+                                    min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) {
+                                ret = VERIFY_CERT_ERROR;
+                            }
+
+                        #ifdef WOLFSSL_SMALL_STACK
+                            XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+                        #endif
+                        }
+                    }
+                    else {
+                        if (args->sendSz != FINISHED_SZ || !args->output ||
+                            XMEMCMP(args->output,
+                                &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) {
+                            ret = VERIFY_CERT_ERROR;
+                        }
+                    }
+                }
+            #endif /* !NO_RSA */
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* case TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+                ssl->options.havePeerVerify = 1;
+
+                /* Set final index */
+                args->idx += args->sz;
+                *inOutIdx = args->idx;
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* case TLS_ASYNC_FINALIZE */
+
+            case TLS_ASYNC_END:
+            {
+                break;
+            }
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_dcv:
+
+        WOLFSSL_LEAVE("DoCertificateVerify", ret);
+        WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E) {
+            /* Mark message as not recevied so it can process again */
+            ssl->msgsReceived.got_certificate_verify = 0;
+
+            return ret;
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+    #ifdef OPENSSL_EXTRA
+        if (ret != 0){
+             SendAlert(ssl, alert_fatal, bad_certificate);
+        }
+    #endif
+        /* Digest is not allocated, so do this to prevent free */
+        ssl->buffers.digest.buffer = NULL;
+        ssl->buffers.digest.length = 0;
+
+        /* Final cleanup */
+        FreeDcvArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */
+
+    /* handle generation of server_hello_done (14) */
+    int SendServerHelloDone(WOLFSSL* ssl)
+    {
+        byte* output;
+        int   sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        int   ret;
+
+        WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND);
+        WOLFSSL_ENTER("SendServerHelloDone");
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls)
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+    #endif
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, 0, server_hello_done, ssl);
+
+    #ifdef WOLFSSL_DTLS
+        if (IsDtlsNotSctpMode(ssl)) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return 0;
+        }
+
+        if (ssl->options.dtls)
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+    #endif
+
+        ret = HashOutput(ssl, output, sendSz, 0);
+            if (ret != 0)
+                return ret;
+
+    #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "ServerHelloDone");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz,
+                    WRITE_PROTO, ssl->heap);
+    #endif
+        ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendServerHelloDone", ret);
+        WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND);
+
+        return ret;
+    }
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#ifdef HAVE_SESSION_TICKET
+
+#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \
+                WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ)
+#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ)
+
+    /* our ticket format */
+    typedef struct InternalTicket {
+        ProtocolVersion pv;                    /* version when ticket created */
+        byte            suite[SUITE_LEN];      /* cipher suite when created */
+        byte            msecret[SECRET_LEN];   /* master secret */
+        word32          timestamp;             /* born on */
+        word16          haveEMS;               /* have extended master secret */
+#ifdef WOLFSSL_TLS13
+        word32          ageAdd;                /* Obfuscation of age */
+        word16          namedGroup;            /* Named group used */
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+        TicketNonce     ticketNonce;           /* Ticket nonce */
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+        word32          maxEarlyDataSz;        /* Max size of early data */
+    #endif
+#endif
+    } InternalTicket;
+
+    /* fit within SESSION_TICKET_LEN */
+    typedef struct ExternalTicket {
+        byte key_name[WOLFSSL_TICKET_NAME_SZ];  /* key context name */
+        byte iv[WOLFSSL_TICKET_IV_SZ];          /* this ticket's iv */
+        byte enc_len[LENGTH_SZ];                /* encrypted length */
+        byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */
+        byte mac[WOLFSSL_TICKET_MAC_SZ];        /* total mac */
+        /* !! if add to structure, add to TICKET_FIXED_SZ !! */
+    } ExternalTicket;
+
+    /* create a new session ticket, 0 on success */
+    int CreateTicket(WOLFSSL* ssl)
+    {
+        InternalTicket  it;
+        ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
+        int encLen;
+        int ret;
+        byte zeros[WOLFSSL_TICKET_MAC_SZ];   /* biggest cmp size */
+
+        XMEMSET(&it, 0, sizeof(it));
+
+        /* build internal */
+        it.pv.major = ssl->version.major;
+        it.pv.minor = ssl->version.minor;
+
+        it.suite[0] = ssl->options.cipherSuite0;
+        it.suite[1] = ssl->options.cipherSuite;
+
+    #ifdef WOLFSSL_EARLY_DATA
+        it.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    #endif
+
+        if (!ssl->options.tls1_3) {
+            XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
+            c32toa(LowResTimer(), (byte*)&it.timestamp);
+            it.haveEMS = ssl->options.haveEMS;
+        }
+        else {
+#ifdef WOLFSSL_TLS13
+            /* Client adds to ticket age to obfuscate. */
+            ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd,
+                                                             sizeof(it.ageAdd));
+            if (ret != 0)
+                return BAD_TICKET_ENCRYPT;
+            ssl->session.ticketAdd = it.ageAdd;
+            it.namedGroup = ssl->session.namedGroup;
+            it.timestamp = TimeNowInMilliseconds();
+            /* Resumption master secret. */
+            XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN);
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+            XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce,
+                                                           sizeof(TicketNonce));
+    #endif
+#endif
+        }
+
+        /* build external */
+        XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
+
+        /* encrypt */
+        encLen = WOLFSSL_TICKET_ENC_SZ;  /* max size user can use */
+        ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
+                                    et->enc_ticket, sizeof(InternalTicket),
+                                    &encLen, ssl->ctx->ticketEncCtx);
+        if (ret == WOLFSSL_TICKET_RET_OK) {
+            if (encLen < (int)sizeof(InternalTicket) ||
+                encLen > WOLFSSL_TICKET_ENC_SZ) {
+                WOLFSSL_MSG("Bad user ticket encrypt size");
+                return BAD_TICKET_KEY_CB_SZ;
+            }
+
+            /* sanity checks on encrypt callback */
+
+            /* internal ticket can't be the same if encrypted */
+            if (XMEMCMP(et->enc_ticket, &it, sizeof(InternalTicket)) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't encrypt");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            XMEMSET(zeros, 0, sizeof(zeros));
+
+            /* name */
+            if (XMEMCMP(et->key_name, zeros, WOLFSSL_TICKET_NAME_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set name");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* iv */
+            if (XMEMCMP(et->iv, zeros, WOLFSSL_TICKET_IV_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set iv");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* mac */
+            if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
+                WOLFSSL_MSG("User ticket encrypt didn't set mac");
+                return BAD_TICKET_ENCRYPT;
+            }
+
+            /* set size */
+            c16toa((word16)encLen, et->enc_len);
+            ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ);
+            if (encLen < WOLFSSL_TICKET_ENC_SZ) {
+                /* move mac up since whole enc buffer not used */
+                XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ);
+            }
+        }
+
+        return ret;
+    }
+
+
+    /* Parse ticket sent by client, returns callback return value */
+    int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
+    {
+        ExternalTicket* et;
+        InternalTicket* it;
+        int             ret;
+        int             outLen;
+        word16          inLen;
+
+        WOLFSSL_START(WC_FUNC_TICKET_DO);
+        WOLFSSL_ENTER("DoClientTicket");
+
+        if (len > SESSION_TICKET_LEN ||
+             len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
+            return BAD_TICKET_MSG_SZ;
+        }
+
+        et = (ExternalTicket*)input;
+        it = (InternalTicket*)et->enc_ticket;
+
+        /* decrypt */
+        ato16(et->enc_len, &inLen);
+        if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) {
+            return BAD_TICKET_MSG_SZ;
+        }
+        outLen = inLen;   /* may be reduced by user padding */
+        ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
+                                    et->enc_ticket + inLen, 0,
+                                    et->enc_ticket, inLen, &outLen,
+                                    ssl->ctx->ticketEncCtx);
+        if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
+        if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) {
+            WOLFSSL_MSG("Bad user ticket decrypt len");
+            return BAD_TICKET_KEY_CB_SZ;
+        }
+
+        /* get master secret */
+        if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
+            if (ssl->version.minor < it->pv.minor) {
+                WOLFSSL_MSG("Ticket has greater version");
+                return VERSION_ERROR;
+            }
+            else if (ssl->version.minor > it->pv.minor) {
+                if (!ssl->options.downgrade) {
+                    WOLFSSL_MSG("Ticket has lesser version");
+                    return VERSION_ERROR;
+                }
+
+                WOLFSSL_MSG("Downgrading protocol due to ticket");
+
+                if (it->pv.minor < ssl->options.minDowngrade)
+                    return VERSION_ERROR;
+                ssl->version.minor = it->pv.minor;
+            }
+
+            if (!IsAtLeastTLSv1_3(ssl->version)) {
+                XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
+                /* Copy the haveExtendedMasterSecret property from the ticket to
+                 * the saved session, so the property may be checked later. */
+                ssl->session.haveEMS = it->haveEMS;
+            }
+            else {
+#ifdef WOLFSSL_TLS13
+                /* Restore information to renegotiate. */
+                ssl->session.ticketSeen = it->timestamp;
+                ssl->session.ticketAdd = it->ageAdd;
+                ssl->session.cipherSuite0 = it->suite[0];
+                ssl->session.cipherSuite = it->suite[1];
+    #ifdef WOLFSSL_EARLY_DATA
+                ssl->session.maxEarlyDataSz = it->maxEarlyDataSz;
+    #endif
+                /* Resumption master secret. */
+                XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN);
+    #ifndef WOLFSSL_TLS13_DRAFT_18
+                XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce,
+                                                           sizeof(TicketNonce));
+    #endif
+                ssl->session.namedGroup = it->namedGroup;
+#endif
+            }
+        }
+
+        WOLFSSL_LEAVE("DoClientTicket", ret);
+        WOLFSSL_END(WC_FUNC_TICKET_DO);
+
+        return ret;
+    }
+
+
+    /* send Session Ticket */
+    int SendTicket(WOLFSSL* ssl)
+    {
+        byte*              output;
+        int                ret;
+        int                sendSz;
+        word32             length = SESSION_HINT_SZ + LENGTH_SZ;
+        word32             idx    = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+        WOLFSSL_START(WC_FUNC_TICKET_SEND);
+        WOLFSSL_ENTER("SendTicket");
+
+        if (ssl->options.createTicket) {
+            ret = CreateTicket(ssl);
+            if (ret != 0) return ret;
+        }
+
+        length += ssl->session.ticketLen;
+        sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+        #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+            idx    += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+        }
+        #endif
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        AddHeaders(output, length, session_ticket, ssl);
+
+        /* hint */
+        c32toa(ssl->ctx->ticketHint, output + idx);
+        idx += SESSION_HINT_SZ;
+
+        /* length */
+        c16toa(ssl->session.ticketLen, output + idx);
+        idx += LENGTH_SZ;
+
+        /* ticket */
+        XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
+        /* idx += ssl->session.ticketLen; */
+
+        #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0)
+                return ret;
+
+            DtlsSEQIncrement(ssl, CUR_ORDER);
+        }
+        #endif
+
+        ret = HashOutput(ssl, output, sendSz, 0);
+        if (ret != 0) return ret;
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        ret = SendBuffered(ssl);
+
+        WOLFSSL_LEAVE("SendTicket", ret);
+        WOLFSSL_END(WC_FUNC_TICKET_SEND);
+
+        return ret;
+    }
+
+#endif /* HAVE_SESSION_TICKET */
+
+#ifndef WOLFSSL_NO_TLS12
+
+#ifdef WOLFSSL_DTLS
+    /* handle generation of DTLS hello_verify_request (3) */
+    static int SendHelloVerifyRequest(WOLFSSL* ssl,
+                                      const byte* cookie, byte cookieSz)
+    {
+        byte* output;
+        int   length = VERSION_SZ + ENUM_LEN + cookieSz;
+        int   idx    = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+        int   sendSz = length + idx;
+        int   ret;
+
+        /* check for available size */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* get output buffer */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        /* Hello Verify Request should use the same sequence number as the
+         * Client Hello. */
+        ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
+        ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
+        AddHeaders(output, length, hello_verify_request, ssl);
+
+#ifdef OPENSSL_EXTRA
+        output[idx++] = DTLS_MAJOR;
+        output[idx++] = DTLS_MINOR;
+#else
+        output[idx++] = ssl->version.major;
+        output[idx++] = ssl->version.minor;
+#endif
+
+        output[idx++] = cookieSz;
+        if (cookie == NULL || cookieSz == 0)
+            return COOKIE_ERROR;
+
+        XMEMCPY(output + idx, cookie, cookieSz);
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "HelloVerifyRequest");
+        if (ssl->toInfoOn)
+            AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output,
+                          sendSz, WRITE_PROTO, ssl->heap);
+#endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+
+        return SendBuffered(ssl);
+    }
+#endif /* WOLFSSL_DTLS */
+
+    typedef struct DckeArgs {
+        byte*  output; /* not allocated */
+        word32 length;
+        word32 idx;
+        word32 begin;
+        word32 sigSz;
+    #ifndef NO_RSA
+        int    lastErr;
+    #endif
+    } DckeArgs;
+
+    static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs)
+    {
+        DckeArgs* args = (DckeArgs*)pArgs;
+
+        (void)ssl;
+        (void)args;
+    }
+
+    /* handle processing client_key_exchange (16) */
+    static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                                                                    word32 size)
+    {
+        int ret;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        DckeArgs* args = (DckeArgs*)ssl->async.args;
+        typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+        (void)sizeof(args_test);
+    #else
+        DckeArgs  args[1];
+    #endif
+
+        (void)size;
+        (void)input;
+
+        WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
+        WOLFSSL_ENTER("DoClientKeyExchange");
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_dcke;
+        }
+        else
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+        {
+            /* Reset state */
+            ret = 0;
+            ssl->options.asyncState = TLS_ASYNC_BEGIN;
+            XMEMSET(args, 0, sizeof(DckeArgs));
+            args->idx = *inOutIdx;
+            args->begin = *inOutIdx;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            ssl->async.freeArgs = FreeDckeArgs;
+        #endif
+        }
+
+        /* Do Client Key Exchange State Machine */
+        switch(ssl->options.asyncState)
+        {
+            case TLS_ASYNC_BEGIN:
+            {
+                /* Sanity checks */
+                if (ssl->options.side != WOLFSSL_SERVER_END) {
+                    WOLFSSL_MSG("Client received client keyexchange, attack?");
+                    WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+                    ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke);
+                }
+
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Client sending keyexchange at wrong time");
+                    SendAlert(ssl, alert_fatal, unexpected_message);
+                    ERROR_OUT(OUT_OF_ORDER_E, exit_dcke);
+                }
+
+            #ifndef NO_CERTS
+                if (ssl->options.verifyPeer && ssl->options.failNoCert) {
+                    if (!ssl->options.havePeerCert) {
+                        WOLFSSL_MSG("client didn't present peer cert");
+                        ERROR_OUT(NO_PEER_CERT, exit_dcke);
+                    }
+                }
+
+                if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) {
+                    if (!ssl->options.havePeerCert &&
+                                             !ssl->options.usingPSK_cipher) {
+                        WOLFSSL_MSG("client didn't present peer cert");
+                        return NO_PEER_CERT;
+                    }
+                }
+            #endif /* !NO_CERTS */
+
+            #if defined(WOLFSSL_CALLBACKS)
+                if (ssl->hsInfoOn) {
+                    AddPacketName(ssl, "ClientKeyExchange");
+                }
+                if (ssl->toInfoOn) {
+                    AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
+                }
+            #endif
+
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                           WOLFSSL_MSG("No server PSK callback set");
+                           ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        /* make sure private key exists */
+                        if (ssl->buffers.key == NULL ||
+                                            ssl->buffers.key->buffer == NULL) {
+                            ERROR_OUT(NO_PRIVATE_KEY, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                            WOLFSSL_MSG("No server PSK callback set");
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        /* sanity check that PSK server callback has been set */
+                        if (ssl->options.server_psk_cb == NULL) {
+                            WOLFSSL_MSG("No server PSK callback set");
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                    default:
+                        WOLFSSL_MSG("Bad kea type");
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_BUILD;
+            } /* TLS_ASYNC_BEGIN */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_BUILD:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        word32 i = 0;
+                        int    keySz;
+
+                        ssl->hsType = DYNAMIC_TYPE_RSA;
+                        ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer,
+                            &i, (RsaKey*)ssl->hsKey, ssl->buffers.key->length);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+                        keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey);
+                        if (keySz < 0) { /* test if keySz has error */
+                            ERROR_OUT(keySz, exit_dcke);
+                        }
+                        args->length = (word32)keySz;
+
+                        if (keySz < ssl->options.minRsaKeySz) {
+                            WOLFSSL_MSG("Peer RSA key is too small");
+                            ERROR_OUT(RSA_KEY_SIZE_E, exit_dcke);
+                        }
+                        ssl->arrays->preMasterSz = SECRET_LEN;
+
+                        if (ssl->options.tls) {
+                            word16 check;
+
+                            if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                                ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                            }
+
+                            ato16(input + args->idx, &check);
+                            args->idx += OPAQUE16_LEN;
+
+                            if ((word32)check != args->length) {
+                                WOLFSSL_MSG("RSA explicit size doesn't match");
+                                ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke);
+                            }
+                        }
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                            WOLFSSL_MSG("RSA message too big");
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        /* pre-load PreMasterSecret with RNG data */
+                        ret = wc_RNG_GenerateBlock(ssl->rng,
+                            &ssl->arrays->preMasterSecret[VERSION_SZ],
+                            SECRET_LEN - VERSION_SZ);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        args->output = NULL;
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 ci_sz;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &ci_sz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if (ci_sz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + ci_sz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity,
+                                                    input + args->idx, ci_sz);
+                        args->idx += ci_sz;
+
+                        ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        /* make psk pre master secret */
+                        /* length of key + length 0s + length of key + key */
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMSET(pms, 0, ssl->arrays->psk_keySz);
+                        pms += ssl->arrays->psk_keySz;
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz =
+                            (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2);
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        word16 cipherLen;
+                        word16 plainLen = ENCRYPT_LEN;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &cipherLen);
+                        args->idx += OPAQUE16_LEN;
+
+                        if (cipherLen > MAX_NTRU_ENCRYPT_SZ) {
+                            ERROR_OUT(NTRU_KEY_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + cipherLen > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        if (NTRU_OK != ntru_crypto_ntru_decrypt(
+                                    (word16) ssl->buffers.key->length,
+                                    ssl->buffers.key->buffer, cipherLen,
+                                    input + args->idx, &plainLen,
+                                    ssl->arrays->preMasterSecret)) {
+                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+                        }
+
+                        if (plainLen != SECRET_LEN) {
+                            ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke);
+                        }
+
+                        args->idx += cipherLen;
+                        ssl->arrays->preMasterSz = plainLen;
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                    #ifdef HAVE_ECC
+                        ecc_key* private_key = ssl->eccTempKey;
+
+                        /* handle static private key */
+                        if (ssl->specs.static_ecdh &&
+                                          ssl->ecdhCurveOID != ECC_X25519_OID) {
+                            word32 i = 0;
+
+                            ssl->hsType = DYNAMIC_TYPE_ECC;
+                            ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+
+                            ret = wc_EccPrivateKeyDecode(
+                                ssl->buffers.key->buffer,
+                                &i,
+                                (ecc_key*)ssl->hsKey,
+                                ssl->buffers.key->length);
+                            if (ret == 0) {
+                                private_key = (ecc_key*)ssl->hsKey;
+                                if (wc_ecc_size(private_key) <
+                                                ssl->options.minEccKeySz) {
+                                    WOLFSSL_MSG("ECC key too small");
+                                    ERROR_OUT(ECC_KEY_SIZE_E, exit_dcke);
+                                }
+                            }
+                        }
+                    #endif
+
+                        /* import peer ECC key */
+                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->length = input[args->idx++];
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ssl->arrays->preMasterSz = ENCRYPT_LEN;
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+                            if (ssl->peerX25519Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->peerX25519Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX25519KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                               ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if (wc_curve25519_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX25519Key,
+                                    EC25519_LITTLE_ENDIAN)) {
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->peerX25519KeyPresent = 1;
+
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                            break;
+                        }
+                    #endif
+                #ifdef HAVE_ECC
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->EccSharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        if (!ssl->specs.static_ecdh &&
+                            ssl->eccTempKeyPresent == 0) {
+                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                        }
+
+                        if (ssl->peerEccKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->peerEccKey);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        } else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                           ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+
+                        if (wc_ecc_import_x963_ex(input + args->idx, args->length,
+                                        ssl->peerEccKey, private_key->dp->id)) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                        }
+
+                        ssl->peerEccKeyPresent = 1;
+                #endif /* HAVE_ECC */
+
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        word16 clientPubSz;
+
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientPubSz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if ((args->idx - args->begin) + clientPubSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = clientPubSz;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+
+                        /* set the max agree result size */
+                        ssl->arrays->preMasterSz = ENCRYPT_LEN;
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        word16 clientSz;
+
+                        /* Read in the PSK hint */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+                        if (clientSz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity, input + args->idx,
+                                                                    clientSz);
+                        args->idx += clientSz;
+                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
+
+                        /* Read in the DHE business */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = clientSz;
+
+                        ret = AllocKey(ssl, DYNAMIC_TYPE_DH,
+                                            (void**)&ssl->buffers.serverDH_Key);
+                        if (ret != 0) {
+                            goto exit_dcke;
+                        }
+
+                        ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_P.buffer,
+                            ssl->buffers.serverDH_P.length,
+                            ssl->buffers.serverDH_G.buffer,
+                            ssl->buffers.serverDH_G.length);
+
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        word16 clientSz;
+
+                        /* Read in the PSK hint */
+                        if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        ato16(input + args->idx, &clientSz);
+                        args->idx += OPAQUE16_LEN;
+                        if (clientSz > MAX_PSK_ID_LEN) {
+                            ERROR_OUT(CLIENT_ID_ERROR, exit_dcke);
+                        }
+                        if ((args->idx - args->begin) + clientSz > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        XMEMCPY(ssl->arrays->client_identity,
+                                                   input + args->idx, clientSz);
+                        args->idx += clientSz;
+                        ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
+
+                        /* import peer ECC key */
+                        if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->length = input[args->idx++];
+
+                        if ((args->idx - args->begin) + args->length > size) {
+                            ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                        }
+
+                        args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                        #ifdef HAVE_PK_CALLBACKS
+                            /* if callback then use it for shared secret */
+                            if (ssl->ctx->X25519SharedSecretCb != NULL) {
+                                break;
+                            }
+                        #endif
+
+                            if (ssl->eccTempKeyPresent == 0) {
+                                WOLFSSL_MSG(
+                                     "X25519 ephemeral key not made correctly");
+                                ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                            }
+
+                            if (ssl->peerX25519Key == NULL) {
+                                /* alloc/init on demand */
+                                ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                    (void**)&ssl->peerX25519Key);
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            } else if (ssl->peerX25519KeyPresent) {
+                                ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                               ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                                if (ret != 0) {
+                                    goto exit_dcke;
+                                }
+                            }
+
+                            if (wc_curve25519_import_public_ex(
+                                    input + args->idx, args->length,
+                                    ssl->peerX25519Key,
+                                    EC25519_LITTLE_ENDIAN)) {
+                                ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                            }
+
+                            ssl->peerX25519KeyPresent = 1;
+
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_PK_CALLBACKS
+                        /* if callback then use it for shared secret */
+                        if (ssl->ctx->EccSharedSecretCb != NULL) {
+                            break;
+                        }
+                    #endif
+
+                        if (ssl->eccTempKeyPresent == 0) {
+                            WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+                            ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
+                        }
+
+                        if (ssl->peerEccKey == NULL) {
+                            /* alloc/init on demand */
+                            ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
+                                (void**)&ssl->peerEccKey);
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+                        else if (ssl->peerEccKeyPresent) {
+                            ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
+                                           ssl->peerEccKey);
+                            ssl->peerEccKeyPresent = 0;
+                            if (ret != 0) {
+                                goto exit_dcke;
+                            }
+                        }
+                        if (wc_ecc_import_x963_ex(input + args->idx, args->length,
+                                 ssl->peerEccKey, ssl->eccTempKey->dp->id)) {
+                            ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
+                        }
+
+                        ssl->peerEccKeyPresent = 1;
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_DO;
+            } /* TLS_ASYNC_BUILD */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_DO:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        RsaKey* key = (RsaKey*)ssl->hsKey;
+
+                        ret = RsaDec(ssl,
+                            input + args->idx,
+                            args->length,
+                            &args->output,
+                            &args->sigSz,
+                            key,
+                        #ifdef HAVE_PK_CALLBACKS
+                            ssl->buffers.key
+                        #else
+                            NULL
+                        #endif
+                        );
+
+                        /*  Errors that can occur here that should be
+                         *  indistinguishable:
+                         *       RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
+                         */
+                        if (ret < 0 && ret != BAD_FUNC_ARG) {
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (ret == WC_PENDING_E)
+                                goto exit_dcke;
+                        #endif
+                            /* store error code for handling below */
+                            args->lastErr = ret;
+                            ret = 0;
+                        }
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        void* private_key = ssl->eccTempKey;
+                        (void)private_key;
+
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            ret = X25519SharedSecret(ssl,
+                                (curve25519_key*)private_key,
+                                ssl->peerX25519Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret,
+                                &ssl->arrays->preMasterSz,
+                                WOLFSSL_SERVER_END
+                            );
+                            break;
+                        }
+                    #endif
+                    #ifdef HAVE_ECC
+                        if (ssl->specs.static_ecdh) {
+                            private_key = ssl->hsKey;
+                        }
+
+                        /* Generate shared secret */
+                        ret = EccSharedSecret(ssl,
+                            (ecc_key*)private_key, ssl->peerEccKey,
+                            input + args->idx, &args->length,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz,
+                            WOLFSSL_SERVER_END
+                        );
+                    #endif
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            ssl->buffers.serverDH_Priv.length,
+                            input + args->idx,
+                            (word16)args->sigSz,
+                            ssl->arrays->preMasterSecret,
+                            &ssl->arrays->preMasterSz);
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        ret = DhAgree(ssl, ssl->buffers.serverDH_Key,
+                            ssl->buffers.serverDH_Priv.buffer,
+                            ssl->buffers.serverDH_Priv.length,
+                            input + args->idx,
+                            (word16)args->sigSz,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &ssl->arrays->preMasterSz);
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                    #ifdef HAVE_CURVE25519
+                        if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+                            ret = X25519SharedSecret(ssl,
+                                (curve25519_key*)ssl->eccTempKey,
+                                ssl->peerX25519Key,
+                                input + args->idx, &args->length,
+                                ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                                &args->sigSz,
+                                WOLFSSL_SERVER_END
+                            );
+                            if (ret == 0) {
+                                FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
+                                                   (void**)&ssl->peerX25519Key);
+                                ssl->peerX25519KeyPresent = 0;
+                            }
+                            break;
+                        }
+                    #endif
+                        /* Generate shared secret */
+                        ret = EccSharedSecret(ssl,
+                            ssl->eccTempKey, ssl->peerEccKey,
+                            input + args->idx, &args->length,
+                            ssl->arrays->preMasterSecret + OPAQUE16_LEN,
+                            &args->sigSz,
+                            WOLFSSL_SERVER_END
+                        );
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_VERIFY;
+            } /* TLS_ASYNC_DO */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_VERIFY:
+            {
+                switch (ssl->specs.kea) {
+                #ifndef NO_RSA
+                    case rsa_kea:
+                    {
+                        /* Add the signature length to idx */
+                        args->idx += args->length;
+
+                    #ifdef DEBUG_WOLFSSL
+                        /* check version (debug warning message only) */
+                        if (args->output != NULL) {
+                            if (args->output[0] != ssl->chVersion.major ||
+                                args->output[1] != ssl->chVersion.minor) {
+                                WOLFSSL_MSG("preMasterSecret version mismatch");
+                            }
+                        }
+                    #endif
+
+                        /* RFC5246 7.4.7.1:
+                         * Treat incorrectly formatted message blocks and/or
+                         * mismatched version numbers in a manner
+                         * indistinguishable from correctly formatted RSA blocks
+                         */
+
+                        ret = args->lastErr;
+                        args->lastErr = 0; /* reset */
+
+                        /* build PreMasterSecret */
+                        ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
+                        ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor;
+                        if (ret == 0 && args->sigSz == SECRET_LEN &&
+                                                         args->output != NULL) {
+                            XMEMCPY(&ssl->arrays->preMasterSecret[VERSION_SZ],
+                                &args->output[VERSION_SZ],
+                                SECRET_LEN - VERSION_SZ);
+                        }
+                        else {
+                            /* preMasterSecret has RNG and version set */
+                            /* return proper length and ignore error */
+                            /* error will be caught as decryption error */
+                            args->sigSz = SECRET_LEN;
+                            ret = 0;
+                        }
+
+                        break;
+                    } /* rsa_kea */
+                #endif /* !NO_RSA */
+                #ifndef NO_PSK
+                    case psk_kea:
+                    {
+                        break;
+                    }
+                #endif /* !NO_PSK */
+                #ifdef HAVE_NTRU
+                    case ntru_kea:
+                    {
+                        break;
+                    }
+                #endif /* HAVE_NTRU */
+                #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+                    case ecc_diffie_hellman_kea:
+                    {
+                        /* skip past the imported peer key */
+                        args->idx += args->length;
+                        break;
+                    }
+                #endif /* HAVE_ECC || HAVE_CURVE25519 */
+                #ifndef NO_DH
+                    case diffie_hellman_kea:
+                    {
+                        args->idx += (word16)args->sigSz;
+                        break;
+                    }
+                #endif /* !NO_DH */
+                #if !defined(NO_DH) && !defined(NO_PSK)
+                    case dhe_psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 clientSz = (word16)args->sigSz;
+
+                        args->idx += clientSz;
+                        c16toa((word16)ssl->arrays->preMasterSz, pms);
+                        ssl->arrays->preMasterSz += OPAQUE16_LEN;
+                        pms += ssl->arrays->preMasterSz;
+
+                        /* Use the PSK hint to look up the PSK and add it to the
+                         * preMasterSecret here. */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key,
+                                                    ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz += ssl->arrays->psk_keySz +
+                                                                OPAQUE16_LEN;
+                        break;
+                    }
+                #endif /* !NO_DH && !NO_PSK */
+                #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
+                                                                !defined(NO_PSK)
+                    case ecdhe_psk_kea:
+                    {
+                        byte* pms = ssl->arrays->preMasterSecret;
+                        word16 clientSz = (word16)args->sigSz;
+
+                        /* skip past the imported peer key */
+                        args->idx += args->length;
+
+                        /* Add preMasterSecret */
+                        c16toa(clientSz, pms);
+                        ssl->arrays->preMasterSz += OPAQUE16_LEN + clientSz;
+                        pms += ssl->arrays->preMasterSz;
+
+                        /* Use the PSK hint to look up the PSK and add it to the
+                         * preMasterSecret here. */
+                        ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                            ssl->arrays->client_identity, ssl->arrays->psk_key,
+                            MAX_PSK_KEY_LEN);
+
+                        if (ssl->arrays->psk_keySz == 0 ||
+                                   ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+                            ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
+                        }
+
+                        c16toa((word16) ssl->arrays->psk_keySz, pms);
+                        pms += OPAQUE16_LEN;
+
+                        XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
+                        ssl->arrays->preMasterSz +=
+                                      ssl->arrays->psk_keySz + OPAQUE16_LEN;
+                        break;
+                    }
+                #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */
+                    default:
+                        ret = BAD_KEA_TYPE_E;
+                } /* switch (ssl->specs.kea) */
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+            } /* TLS_ASYNC_VERIFY */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_FINALIZE:
+            {
+            #ifdef HAVE_QSH
+                word16 name;
+
+                if (ssl->options.haveQSH) {
+                    /* extension name */
+                    ato16(input + args->idx, &name);
+                    args->idx += OPAQUE16_LEN;
+
+                    if (name == TLSX_QUANTUM_SAFE_HYBRID) {
+                        int    qshSz;
+                        /* if qshSz is larger than 0 it is the
+                           length of buffer used */
+                        if ((qshSz = TLSX_QSHCipher_Parse(ssl,
+                                input + args->idx,
+                                size - args->idx + args->begin, 1)) < 0) {
+                            ERROR_OUT(qshSz, exit_dcke);
+                        }
+                        args->idx += qshSz;
+                    }
+                    else {
+                        /* unknown extension sent client ignored handshake */
+                        ERROR_OUT(BUFFER_ERROR, exit_dcke);
+                    }
+                }
+            #endif /* HAVE_QSH */
+                ret = MakeMasterSecret(ssl);
+
+                /* Check for error */
+                if (ret != 0) {
+                    goto exit_dcke;
+                }
+
+                /* Advance state and proceed */
+                ssl->options.asyncState = TLS_ASYNC_END;
+            } /* TLS_ASYNC_FINALIZE */
+            FALL_THROUGH;
+
+            case TLS_ASYNC_END:
+            {
+                /* Set final index */
+                *inOutIdx = args->idx;
+
+                ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+            #ifndef NO_CERTS
+                if (ssl->options.verifyPeer) {
+                    ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes);
+                }
+            #endif
+                break;
+            } /* TLS_ASYNC_END */
+            default:
+                ret = INPUT_CASE_ERROR;
+        } /* switch(ssl->options.asyncState) */
+
+    exit_dcke:
+
+        WOLFSSL_LEAVE("DoClientKeyExchange", ret);
+        WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* Handle async operation */
+        if (ret == WC_PENDING_E) {
+            /* Mark message as not recevied so it can process again */
+            ssl->msgsReceived.got_client_key_exchange = 0;
+
+            return ret;
+        }
+    #endif /* WOLFSSL_ASYNC_CRYPT */
+
+        /* Cleanup PMS */
+        ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
+        ssl->arrays->preMasterSz = 0;
+
+        /* Final cleanup */
+        FreeDckeArgs(ssl, args);
+        FreeKeyExchange(ssl);
+
+        return ret;
+    }
+
+#endif /* !WOLFSSL_NO_TLS12 */
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY)
+    int SNI_Callback(WOLFSSL* ssl)
+    {
+        /* Stunnel supports a custom sni callback to switch an SSL's ctx
+        * when SNI is received. Call it now if exists */
+        if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) {
+            WOLFSSL_MSG("Calling custom sni callback");
+            if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg)
+                    == alert_fatal) {
+                WOLFSSL_MSG("Error in custom sni callback. Fatal alert");
+                SendAlert(ssl, alert_fatal, unrecognized_name);
+                return FATAL_ERROR;
+            }
+        }
+        return 0;
+    }
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* NO_WOLFSSL_SERVER */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
+{
+    int ret = 0;
+    WC_ASYNC_DEV* asyncDev;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* check for pending async */
+    asyncDev = ssl->async.dev;
+    if (asyncDev) {
+        /* grab event pointer */
+        event = &asyncDev->event;
+
+        ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL);
+        if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) {
+
+            /* advance key share state if doesn't need called again */
+            if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) {
+                (*state)++;
+            }
+
+            /* clear event */
+            XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT));
+
+            /* clear async dev */
+            ssl->async.dev = NULL;
+        }
+    }
+    else {
+        ret = WC_NOT_PENDING_E;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret);
+
+    return ret;
+}
+
+int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags)
+{
+    int ret;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL || asyncDev == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* grab event pointer */
+    event = &asyncDev->event;
+
+    /* init event */
+    ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags);
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret);
+
+    return ret;
+}
+
+int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev)
+{
+    int ret;
+    WOLF_EVENT* event;
+
+    if (ssl == NULL || asyncDev == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* grab event pointer */
+    event = &asyncDev->event;
+
+    /* store reference to active async operation */
+    ssl->async.dev = asyncDev;
+
+    /* place event into queue */
+    ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event);
+
+    /* success means return WC_PENDING_E */
+    if (ret == 0) {
+        ret = WC_PENDING_E;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret);
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+
+/* return the max record size */
+int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment)
+{
+    (void) ssl; /* Avoid compiler warnings */
+
+    if (maxFragment > MAX_RECORD_SIZE) {
+        maxFragment = MAX_RECORD_SIZE;
+    }
+
+#ifdef HAVE_MAX_FRAGMENT
+    if ((ssl->max_fragment != 0) && (maxFragment > ssl->max_fragment)) {
+        maxFragment = ssl->max_fragment;
+    }
+#endif /* HAVE_MAX_FRAGMENT */
+#ifdef WOLFSSL_DTLS
+    if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) {
+        maxFragment = MAX_UDP_SIZE;
+    }
+#endif
+
+    return maxFragment;
+}
+
+
+#undef ERROR_OUT
+
+#endif /* WOLFCRYPT_ONLY */
+
--- a/src/keys.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/keys.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,3475 +1,3475 @@
-/* keys.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* Name change compatibility layer no longer needs to be included here */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #else
-        #include <stdio.h>
-    #endif
-#endif
-
-
-int SetCipherSpecs(WOLFSSL* ssl)
-{
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        /* server side verified before SetCipherSpecs call */
-        if (VerifyClientSuite(ssl) != 1) {
-            WOLFSSL_MSG("SetCipherSpecs() client has an unusuable suite");
-            return UNSUPPORTED_SUITE;
-        }
-    }
-#endif /* NO_WOLFSSL_CLIENT */
-
-    /* Chacha extensions, 0xcc */
-    if (ssl->options.cipherSuite0 == CHACHA_BYTE) {
-
-    switch (ssl->options.cipherSuite) {
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-    case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
-
-        break;
-#endif
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecdhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-    case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-
-        ssl->options.oldPoly             = 0; /* use recent padding RFC */
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-    default:
-        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ChaCha");
-        return UNSUPPORTED_SUITE;
-    }
-    }
-
-    /* ECC extensions, or AES-CCM */
-    if (ssl->options.cipherSuite0 == ECC_BYTE) {
-
-    switch (ssl->options.cipherSuite) {
-
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-    case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-    case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-    case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecdhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-    case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecdhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#endif /* HAVE_ECC || HAVE_CURVE25519 */
-
-#if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && defined(HAVE_ED25519))
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-    case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-    case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-    case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-    case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-    case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-    break;
-#endif
-
-#endif /* HAVE_ECC || (HAVE_CURVE25519 && HAVE_ED25519) */
-
-#if defined(HAVE_ECC)
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-    case TLS_ECDH_RSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-    case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-    case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-    case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-    case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-    case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = ecc_diffie_hellman_kea;
-        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 1;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#endif /* HAVE_ECC */
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
-    case TLS_RSA_WITH_AES_128_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
-    case TLS_RSA_WITH_AES_256_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
-    case TLS_PSK_WITH_AES_128_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
-    case TLS_PSK_WITH_AES_256_CCM_8 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
-    case TLS_PSK_WITH_AES_128_CCM :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
-    case TLS_PSK_WITH_AES_256_CCM :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-    case TLS_DHE_PSK_WITH_AES_128_CCM :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-    case TLS_DHE_PSK_WITH_AES_256_CCM :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-    default:
-        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
-        return UNSUPPORTED_SUITE;
-    }   /* switch */
-    }   /* if     */
-
-    /* TLSi v1.3 cipher suites, 0x13 */
-    if (ssl->options.cipherSuite0 == TLS13_BYTE) {
-        switch (ssl->options.cipherSuite) {
-
-#ifdef WOLFSSL_TLS13
-    #ifdef BUILD_TLS_AES_128_GCM_SHA256
-        case TLS_AES_128_GCM_SHA256 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-            ssl->specs.cipher_type           = aead;
-            ssl->specs.mac_algorithm         = sha256_mac;
-            ssl->specs.kea                   = 0;
-            ssl->specs.sig_algo              = 0;
-            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_128_KEY_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
-            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-            break;
-    #endif
-
-    #ifdef BUILD_TLS_AES_256_GCM_SHA384
-        case TLS_AES_256_GCM_SHA384 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-            ssl->specs.cipher_type           = aead;
-            ssl->specs.mac_algorithm         = sha384_mac;
-            ssl->specs.kea                   = 0;
-            ssl->specs.sig_algo              = 0;
-            ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_256_KEY_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
-            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-            break;
-    #endif
-
-    #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
-        case TLS_CHACHA20_POLY1305_SHA256 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
-            ssl->specs.cipher_type           = aead;
-            ssl->specs.mac_algorithm         = sha256_mac;
-            ssl->specs.kea                   = 0;
-            ssl->specs.sig_algo              = 0;
-            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
-            ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
-            ssl->specs.iv_size               = CHACHA20_IV_SIZE;
-            ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
-            ssl->options.oldPoly             = 0; /* use recent padding RFC */
-
-            break;
-    #endif
-
-    #ifdef BUILD_TLS_AES_128_CCM_SHA256
-        case TLS_AES_128_CCM_SHA256 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-            ssl->specs.cipher_type           = aead;
-            ssl->specs.mac_algorithm         = sha256_mac;
-            ssl->specs.kea                   = 0;
-            ssl->specs.sig_algo              = 0;
-            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_128_KEY_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
-            ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
-
-            break;
-    #endif
-
-    #ifdef BUILD_TLS_AES_128_CCM_8_SHA256
-        case TLS_AES_128_CCM_8_SHA256 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
-            ssl->specs.cipher_type           = aead;
-            ssl->specs.mac_algorithm         = sha256_mac;
-            ssl->specs.kea                   = 0;
-            ssl->specs.sig_algo              = 0;
-            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_128_KEY_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
-            ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
-
-            break;
-    #endif
-#endif /* WOLFSSL_TLS13 */
-        }
-    }
-
-    if (ssl->options.cipherSuite0 != ECC_BYTE &&
-            ssl->options.cipherSuite0 != CHACHA_BYTE &&
-            ssl->options.cipherSuite0 != TLS13_BYTE) {   /* normal suites */
-    switch (ssl->options.cipherSuite) {
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
-    case SSL_RSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-    case TLS_NTRU_RSA_WITH_RC4_128_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ntru_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
-    case SSL_RSA_WITH_RC4_128_MD5 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = md5_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_MD5;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RC4_KEY_SIZE;
-        ssl->specs.iv_size               = 0;
-        ssl->specs.block_size            = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-    case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ntru_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-    case TLS_RSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-    case TLS_RSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
-    case TLS_RSA_WITH_NULL_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
-    case TLS_RSA_WITH_NULL_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-    case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ntru_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-    case TLS_RSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-    case TLS_RSA_WITH_AES_256_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-    case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = ntru_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-    case TLS_PSK_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-    case TLS_PSK_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-        
-#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
-    case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-         ssl->options.usingAnon_cipher    = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-    case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-    case TLS_PSK_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-    case TLS_PSK_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-    case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-    case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-    case TLS_PSK_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-    case TLS_PSK_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
-    case TLS_PSK_WITH_NULL_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
-    case TLS_PSK_WITH_NULL_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
-    case TLS_PSK_WITH_NULL_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-    case TLS_DHE_PSK_WITH_NULL_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-    case TLS_DHE_PSK_WITH_NULL_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = dhe_psk_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = 0;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = 0;
-
-        ssl->options.usingPSK_cipher     = 1;
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-    case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = DES3_KEY_SIZE;
-        ssl->specs.block_size            = DES_BLOCK_SIZE;
-        ssl->specs.iv_size               = DES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
-    case TLS_RSA_WITH_HC_128_MD5 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = md5_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_MD5;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = HC_128_KEY_SIZE;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = HC_128_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
-        case TLS_RSA_WITH_HC_128_SHA :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
-            ssl->specs.cipher_type           = stream;
-            ssl->specs.mac_algorithm         = sha_mac;
-            ssl->specs.kea                   = rsa_kea;
-            ssl->specs.sig_algo              = rsa_sa_algo;
-            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = HC_128_KEY_SIZE;
-            ssl->specs.block_size            = 0;
-            ssl->specs.iv_size               = HC_128_IV_SIZE;
-
-            break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
-        case TLS_RSA_WITH_HC_128_B2B256:
-            ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
-            ssl->specs.cipher_type           = stream;
-            ssl->specs.mac_algorithm         = blake2b_mac;
-            ssl->specs.kea                   = rsa_kea;
-            ssl->specs.sig_algo              = rsa_sa_algo;
-            ssl->specs.hash_size             = BLAKE2B_256;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = HC_128_KEY_SIZE;
-            ssl->specs.block_size            = 0;
-            ssl->specs.iv_size               = HC_128_IV_SIZE;
-
-            break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
-        case TLS_RSA_WITH_AES_128_CBC_B2B256:
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-            ssl->specs.cipher_type           = block;
-            ssl->specs.mac_algorithm         = blake2b_mac;
-            ssl->specs.kea                   = rsa_kea;
-            ssl->specs.sig_algo              = rsa_sa_algo;
-            ssl->specs.hash_size             = BLAKE2B_256;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_128_KEY_SIZE;
-            ssl->specs.iv_size               = AES_IV_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-            break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
-        case TLS_RSA_WITH_AES_256_CBC_B2B256:
-            ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-            ssl->specs.cipher_type           = block;
-            ssl->specs.mac_algorithm         = blake2b_mac;
-            ssl->specs.kea                   = rsa_kea;
-            ssl->specs.sig_algo              = rsa_sa_algo;
-            ssl->specs.hash_size             = BLAKE2B_256;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = AES_256_KEY_SIZE;
-            ssl->specs.iv_size               = AES_IV_SIZE;
-            ssl->specs.block_size            = AES_BLOCK_SIZE;
-
-            break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
-    case TLS_RSA_WITH_RABBIT_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_rabbit;
-        ssl->specs.cipher_type           = stream;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = RABBIT_KEY_SIZE;
-        ssl->specs.block_size            = 0;
-        ssl->specs.iv_size               = RABBIT_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-    case TLS_RSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-    case TLS_RSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
-        ssl->specs.cipher_type           = aead;
-        ssl->specs.mac_algorithm         = sha384_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_256_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
-        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = rsa_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha256_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = rsa_sa_algo;
-        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
-        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
-        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
-
-        break;
-#endif
-
-#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-    case TLS_DH_anon_WITH_AES_128_CBC_SHA :
-        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
-        ssl->specs.cipher_type           = block;
-        ssl->specs.mac_algorithm         = sha_mac;
-        ssl->specs.kea                   = diffie_hellman_kea;
-        ssl->specs.sig_algo              = anonymous_sa_algo;
-        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-        ssl->specs.pad_size              = PAD_SHA;
-        ssl->specs.static_ecdh           = 0;
-        ssl->specs.key_size              = AES_128_KEY_SIZE;
-        ssl->specs.block_size            = AES_BLOCK_SIZE;
-        ssl->specs.iv_size               = AES_IV_SIZE;
-
-        ssl->options.usingAnon_cipher    = 1;
-        break;
-#endif
-
-#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-        case SSL_RSA_WITH_IDEA_CBC_SHA :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_idea;
-            ssl->specs.cipher_type           = block;
-            ssl->specs.mac_algorithm         = sha_mac;
-            ssl->specs.kea                   = rsa_kea;
-            ssl->specs.sig_algo              = rsa_sa_algo;
-            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-            ssl->specs.static_ecdh           = 0;
-            ssl->specs.key_size              = IDEA_KEY_SIZE;
-            ssl->specs.block_size            = IDEA_BLOCK_SIZE;
-            ssl->specs.iv_size               = IDEA_IV_SIZE;
-
-            break;
-#endif
-
-#ifdef BUILD_WDM_WITH_NULL_SHA256
-        case WDM_WITH_NULL_SHA256 :
-            ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
-            ssl->specs.cipher_type           = stream;
-            ssl->specs.mac_algorithm         = sha256_mac;
-            ssl->specs.kea                   = no_kea;
-            ssl->specs.sig_algo              = anonymous_sa_algo;
-            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
-            ssl->specs.pad_size              = PAD_SHA;
-
-            break;
-#endif
-
-    default:
-        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs");
-        return UNSUPPORTED_SUITE;
-    }  /* switch */
-    }  /* if ECC / Normal suites else */
-
-    /* set TLS if it hasn't been turned off */
-    if (ssl->version.major == 3 && ssl->version.minor >= 1) {
-#ifndef NO_TLS
-        ssl->options.tls = 1;
-    #ifndef WOLFSSL_NO_TLS12
-        ssl->hmac = TLS_hmac;
-    #endif
-        if (ssl->version.minor >= 2) {
-            ssl->options.tls1_1 = 1;
-            if (ssl->version.minor >= 4)
-                ssl->options.tls1_3 = 1;
-        }
-#endif
-    }
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls)
-        ssl->hmac = TLS_hmac;
-#endif
-
-    return 0;
-}
-
-
-enum KeyStuff {
-    MASTER_ROUNDS = 3,
-    PREFIX        = 3,     /* up to three letters for master prefix */
-    KEY_PREFIX    = 9      /* up to 9 prefix letters for key rounds */
-
-
-};
-
-#ifndef NO_OLD_TLS
-/* true or false, zero for error */
-static int SetPrefix(byte* sha_input, int idx)
-{
-    switch (idx) {
-    case 0:
-        XMEMCPY(sha_input, "A", 1);
-        break;
-    case 1:
-        XMEMCPY(sha_input, "BB", 2);
-        break;
-    case 2:
-        XMEMCPY(sha_input, "CCC", 3);
-        break;
-    case 3:
-        XMEMCPY(sha_input, "DDDD", 4);
-        break;
-    case 4:
-        XMEMCPY(sha_input, "EEEEE", 5);
-        break;
-    case 5:
-        XMEMCPY(sha_input, "FFFFFF", 6);
-        break;
-    case 6:
-        XMEMCPY(sha_input, "GGGGGGG", 7);
-        break;
-    case 7:
-        XMEMCPY(sha_input, "HHHHHHHH", 8);
-        break;
-    case 8:
-        XMEMCPY(sha_input, "IIIIIIIII", 9);
-        break;
-    default:
-        WOLFSSL_MSG("Set Prefix error, bad input");
-        return 0;
-    }
-    return 1;
-}
-#endif
-
-
-static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
-                   int side, void* heap, int devId)
-{
-#ifdef BUILD_ARC4
-    word32 sz = specs->key_size;
-    if (specs->bulk_cipher_algorithm == wolfssl_rc4) {
-        if (enc && enc->arc4 == NULL)
-            enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->arc4 == NULL)
-            return MEMORY_E;
-        if (dec && dec->arc4 == NULL)
-            dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->arc4 == NULL)
-            return MEMORY_E;
-
-        if (enc) {
-            if (wc_Arc4Init(enc->arc4, heap, devId) != 0) {
-                WOLFSSL_MSG("Arc4Init failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-        if (dec) {
-            if (wc_Arc4Init(dec->arc4, heap, devId) != 0) {
-                WOLFSSL_MSG("Arc4Init failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc)
-                wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz);
-            if (dec)
-                wc_Arc4SetKey(dec->arc4, keys->server_write_key, sz);
-        }
-        else {
-            if (enc)
-                wc_Arc4SetKey(enc->arc4, keys->server_write_key, sz);
-            if (dec)
-                wc_Arc4SetKey(dec->arc4, keys->client_write_key, sz);
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* BUILD_ARC4 */
-
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-    /* Check that the max implicit iv size is suffecient */
-    #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */
-        #error AEAD_MAX_IMP_SZ is too small for ChaCha20
-    #endif
-    #if (MAX_WRITE_IV_SZ < 12) /* CHACHA20_IMP_IV_SZ */
-        #error MAX_WRITE_IV_SZ is too small for ChaCha20
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_chacha) {
-        int chachaRet;
-        if (enc && enc->chacha == NULL)
-            enc->chacha =
-                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->chacha == NULL)
-            return MEMORY_E;
-        if (dec && dec->chacha == NULL)
-            dec->chacha =
-                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->chacha == NULL)
-            return MEMORY_E;
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key,
-                                          specs->key_size);
-                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
-                        CHACHA20_IMP_IV_SZ);
-                if (chachaRet != 0) return chachaRet;
-            }
-            if (dec) {
-                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key,
-                                          specs->key_size);
-                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
-                        CHACHA20_IMP_IV_SZ);
-                if (chachaRet != 0) return chachaRet;
-            }
-        }
-        else {
-            if (enc) {
-                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key,
-                                          specs->key_size);
-                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
-                        CHACHA20_IMP_IV_SZ);
-                if (chachaRet != 0) return chachaRet;
-            }
-            if (dec) {
-                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key,
-                                          specs->key_size);
-                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
-                        CHACHA20_IMP_IV_SZ);
-                if (chachaRet != 0) return chachaRet;
-            }
-        }
-
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* HAVE_CHACHA && HAVE_POLY1305 */
-
-
-#ifdef HAVE_HC128
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 16) /* HC_128_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for HC128
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_hc128) {
-        int hcRet;
-        if (enc && enc->hc128 == NULL)
-            enc->hc128 =
-                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->hc128 == NULL)
-            return MEMORY_E;
-        if (dec && dec->hc128 == NULL)
-            dec->hc128 =
-                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->hc128 == NULL)
-            return MEMORY_E;
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                hcRet = wc_Hc128_SetKey(enc->hc128, keys->client_write_key,
-                                     keys->client_write_IV);
-                if (hcRet != 0) return hcRet;
-            }
-            if (dec) {
-                hcRet = wc_Hc128_SetKey(dec->hc128, keys->server_write_key,
-                                     keys->server_write_IV);
-                if (hcRet != 0) return hcRet;
-            }
-        }
-        else {
-            if (enc) {
-                hcRet = wc_Hc128_SetKey(enc->hc128, keys->server_write_key,
-                                     keys->server_write_IV);
-                if (hcRet != 0) return hcRet;
-            }
-            if (dec) {
-                hcRet = wc_Hc128_SetKey(dec->hc128, keys->client_write_key,
-                                     keys->client_write_IV);
-                if (hcRet != 0) return hcRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* HAVE_HC128 */
-
-#ifdef BUILD_RABBIT
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for RABBIT
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_rabbit) {
-        int rabRet;
-        if (enc && enc->rabbit == NULL)
-            enc->rabbit =
-                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->rabbit == NULL)
-            return MEMORY_E;
-        if (dec && dec->rabbit == NULL)
-            dec->rabbit =
-                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->rabbit == NULL)
-            return MEMORY_E;
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                rabRet = wc_RabbitSetKey(enc->rabbit, keys->client_write_key,
-                                      keys->client_write_IV);
-                if (rabRet != 0) return rabRet;
-            }
-            if (dec) {
-                rabRet = wc_RabbitSetKey(dec->rabbit, keys->server_write_key,
-                                      keys->server_write_IV);
-                if (rabRet != 0) return rabRet;
-            }
-        }
-        else {
-            if (enc) {
-                rabRet = wc_RabbitSetKey(enc->rabbit, keys->server_write_key,
-                                      keys->server_write_IV);
-                if (rabRet != 0) return rabRet;
-            }
-            if (dec) {
-                rabRet = wc_RabbitSetKey(dec->rabbit, keys->client_write_key,
-                                      keys->client_write_IV);
-                if (rabRet != 0) return rabRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* BUILD_RABBIT */
-
-#ifdef BUILD_DES3
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for 3DES
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_triple_des) {
-        int desRet = 0;
-
-        if (enc) {
-            if (enc->des3 == NULL)
-                enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
-            if (enc->des3 == NULL)
-                return MEMORY_E;
-            XMEMSET(enc->des3, 0, sizeof(Des3));
-        }
-        if (dec) {
-            if (dec->des3 == NULL)
-                dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
-            if (dec->des3 == NULL)
-                return MEMORY_E;
-            XMEMSET(dec->des3, 0, sizeof(Des3));
-        }
-
-        if (enc) {
-            if (wc_Des3Init(enc->des3, heap, devId) != 0) {
-                WOLFSSL_MSG("Des3Init failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-        if (dec) {
-            if (wc_Des3Init(dec->des3, heap, devId) != 0) {
-                WOLFSSL_MSG("Des3Init failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key,
-                                     keys->client_write_IV, DES_ENCRYPTION);
-                if (desRet != 0) return desRet;
-            }
-            if (dec) {
-                desRet = wc_Des3_SetKey(dec->des3, keys->server_write_key,
-                                     keys->server_write_IV, DES_DECRYPTION);
-                if (desRet != 0) return desRet;
-            }
-        }
-        else {
-            if (enc) {
-                desRet = wc_Des3_SetKey(enc->des3, keys->server_write_key,
-                                     keys->server_write_IV, DES_ENCRYPTION);
-                if (desRet != 0) return desRet;
-            }
-            if (dec) {
-                desRet = wc_Des3_SetKey(dec->des3, keys->client_write_key,
-                                     keys->client_write_IV, DES_DECRYPTION);
-                if (desRet != 0) return desRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* BUILD_DES3 */
-
-#ifdef BUILD_AES
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for AES
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_aes) {
-        int aesRet = 0;
-
-        if (enc) {
-            if (enc->aes == NULL)
-                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (enc->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(enc->aes, 0, sizeof(Aes));
-        }
-        if (dec) {
-            if (dec->aes == NULL)
-                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (dec->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(dec->aes, 0, sizeof(Aes));
-        }
-        if (enc) {
-            if (wc_AesInit(enc->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-        if (dec) {
-            if (wc_AesInit(dec->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                aesRet = wc_AesSetKey(enc->aes, keys->client_write_key,
-                                   specs->key_size, keys->client_write_IV,
-                                   AES_ENCRYPTION);
-                if (aesRet != 0) return aesRet;
-            }
-            if (dec) {
-                aesRet = wc_AesSetKey(dec->aes, keys->server_write_key,
-                                   specs->key_size, keys->server_write_IV,
-                                   AES_DECRYPTION);
-                if (aesRet != 0) return aesRet;
-            }
-        }
-        else {
-            if (enc) {
-                aesRet = wc_AesSetKey(enc->aes, keys->server_write_key,
-                                   specs->key_size, keys->server_write_IV,
-                                   AES_ENCRYPTION);
-                if (aesRet != 0) return aesRet;
-            }
-            if (dec) {
-                aesRet = wc_AesSetKey(dec->aes, keys->client_write_key,
-                                   specs->key_size, keys->client_write_IV,
-                                   AES_DECRYPTION);
-                if (aesRet != 0) return aesRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* BUILD_AES */
-
-#ifdef BUILD_AESGCM
-    /* check that buffer sizes are sufficient */
-    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
-        #error AEAD_MAX_IMP_SZ too small for AESGCM
-    #endif
-    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
-        #error AEAD_MAX_EXP_SZ too small for AESGCM
-    #endif
-    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
-        #error MAX_WRITE_IV_SZ too small for AESGCM
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) {
-        int gcmRet;
-
-        if (enc) {
-            if (enc->aes == NULL)
-                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (enc->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(enc->aes, 0, sizeof(Aes));
-        }
-        if (dec) {
-            if (dec->aes == NULL)
-                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (dec->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(dec->aes, 0, sizeof(Aes));
-        }
-
-        if (enc) {
-            if (wc_AesInit(enc->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-        if (dec) {
-            if (wc_AesInit(dec->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                gcmRet = wc_AesGcmSetKey(enc->aes, keys->client_write_key,
-                                      specs->key_size);
-                if (gcmRet != 0) return gcmRet;
-                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-            if (dec) {
-                gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key,
-                                      specs->key_size);
-                if (gcmRet != 0) return gcmRet;
-                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-        }
-        else {
-            if (enc) {
-                gcmRet = wc_AesGcmSetKey(enc->aes, keys->server_write_key,
-                                      specs->key_size);
-                if (gcmRet != 0) return gcmRet;
-                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-            if (dec) {
-                gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key,
-                                      specs->key_size);
-                if (gcmRet != 0) return gcmRet;
-                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* BUILD_AESGCM */
-
-#ifdef HAVE_AESCCM
-    /* check that buffer sizes are sufficient (CCM is same size as GCM) */
-    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
-        #error AEAD_MAX_IMP_SZ too small for AESCCM
-    #endif
-    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
-        #error AEAD_MAX_EXP_SZ too small for AESCCM
-    #endif
-    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
-        #error MAX_WRITE_IV_SZ too small for AESCCM
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) {
-        int CcmRet;
-
-        if (enc) {
-            if (enc->aes == NULL)
-                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (enc->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(enc->aes, 0, sizeof(Aes));
-        }
-        if (dec) {
-            if (dec->aes == NULL)
-                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
-            if (dec->aes == NULL)
-                return MEMORY_E;
-            XMEMSET(dec->aes, 0, sizeof(Aes));
-        }
-
-        if (enc) {
-            if (wc_AesInit(enc->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-        if (dec) {
-            if (wc_AesInit(dec->aes, heap, devId) != 0) {
-                WOLFSSL_MSG("AesInit failed in SetKeys");
-                return ASYNC_INIT_E;
-            }
-        }
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                CcmRet = wc_AesCcmSetKey(enc->aes, keys->client_write_key,
-                                         specs->key_size);
-                if (CcmRet != 0) {
-                    return CcmRet;
-                }
-                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-            if (dec) {
-                CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key,
-                                         specs->key_size);
-                if (CcmRet != 0) {
-                    return CcmRet;
-                }
-                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-        }
-        else {
-            if (enc) {
-                CcmRet = wc_AesCcmSetKey(enc->aes, keys->server_write_key,
-                                         specs->key_size);
-                if (CcmRet != 0) {
-                    return CcmRet;
-                }
-                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-            if (dec) {
-                CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key,
-                                         specs->key_size);
-                if (CcmRet != 0) {
-                    return CcmRet;
-                }
-                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
-                        AEAD_MAX_IMP_SZ);
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* HAVE_AESCCM */
-
-#ifdef HAVE_CAMELLIA
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 16) /* CAMELLIA_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for CAMELLIA
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_camellia) {
-        int camRet;
-
-        if (enc && enc->cam == NULL)
-            enc->cam =
-                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->cam == NULL)
-            return MEMORY_E;
-
-        if (dec && dec->cam == NULL)
-            dec->cam =
-                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->cam == NULL)
-            return MEMORY_E;
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                camRet = wc_CamelliaSetKey(enc->cam, keys->client_write_key,
-                                        specs->key_size, keys->client_write_IV);
-                if (camRet != 0) return camRet;
-            }
-            if (dec) {
-                camRet = wc_CamelliaSetKey(dec->cam, keys->server_write_key,
-                                        specs->key_size, keys->server_write_IV);
-                if (camRet != 0) return camRet;
-            }
-        }
-        else {
-            if (enc) {
-                camRet = wc_CamelliaSetKey(enc->cam, keys->server_write_key,
-                                        specs->key_size, keys->server_write_IV);
-                if (camRet != 0) return camRet;
-            }
-            if (dec) {
-                camRet = wc_CamelliaSetKey(dec->cam, keys->client_write_key,
-                                        specs->key_size, keys->client_write_IV);
-                if (camRet != 0) return camRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* HAVE_CAMELLIA */
-
-#ifdef HAVE_IDEA
-    /* check that buffer sizes are sufficient */
-    #if (MAX_WRITE_IV_SZ < 8) /* IDEA_IV_SIZE */
-        #error MAX_WRITE_IV_SZ too small for IDEA
-    #endif
-
-    if (specs->bulk_cipher_algorithm == wolfssl_idea) {
-        int ideaRet;
-
-        if (enc && enc->idea == NULL)
-            enc->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
-        if (enc && enc->idea == NULL)
-            return MEMORY_E;
-
-        if (dec && dec->idea == NULL)
-            dec->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
-        if (dec && dec->idea == NULL)
-            return MEMORY_E;
-
-        if (side == WOLFSSL_CLIENT_END) {
-            if (enc) {
-                ideaRet = wc_IdeaSetKey(enc->idea, keys->client_write_key,
-                                        specs->key_size, keys->client_write_IV,
-                                        IDEA_ENCRYPTION);
-                if (ideaRet != 0) return ideaRet;
-            }
-            if (dec) {
-                ideaRet = wc_IdeaSetKey(dec->idea, keys->server_write_key,
-                                        specs->key_size, keys->server_write_IV,
-                                        IDEA_DECRYPTION);
-                if (ideaRet != 0) return ideaRet;
-            }
-        }
-        else {
-            if (enc) {
-                ideaRet = wc_IdeaSetKey(enc->idea, keys->server_write_key,
-                                        specs->key_size, keys->server_write_IV,
-                                        IDEA_ENCRYPTION);
-                if (ideaRet != 0) return ideaRet;
-            }
-            if (dec) {
-                ideaRet = wc_IdeaSetKey(dec->idea, keys->client_write_key,
-                                        specs->key_size, keys->client_write_IV,
-                                        IDEA_DECRYPTION);
-                if (ideaRet != 0) return ideaRet;
-            }
-        }
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif /* HAVE_IDEA */
-
-#ifdef HAVE_NULL_CIPHER
-    if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) {
-        if (enc)
-            enc->setup = 1;
-        if (dec)
-            dec->setup = 1;
-    }
-#endif
-
-    if (enc) {
-        keys->sequence_number_hi      = 0;
-        keys->sequence_number_lo      = 0;
-    }
-    if (dec) {
-        keys->peer_sequence_number_hi = 0;
-        keys->peer_sequence_number_lo = 0;
-    }
-    (void)side;
-    (void)heap;
-    (void)enc;
-    (void)dec;
-    (void)specs;
-    (void)devId;
-
-    return 0;
-}
-
-
-#ifdef HAVE_ONE_TIME_AUTH
-/* set one time authentication keys */
-static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys,
-                       CipherSpecs* specs, void* heap, int devId)
-{
-
-#ifdef HAVE_POLY1305
-        /* set up memory space for poly1305 */
-        if (authentication && authentication->poly1305 == NULL)
-            authentication->poly1305 =
-                (Poly1305*)XMALLOC(sizeof(Poly1305), heap, DYNAMIC_TYPE_CIPHER);
-        if (authentication && authentication->poly1305 == NULL)
-            return MEMORY_E;
-        if (authentication)
-            authentication->setup = 1;
-#endif
-        (void)authentication;
-        (void)heap;
-        (void)keys;
-        (void)specs;
-        (void)devId;
-
-        return 0;
-}
-#endif /* HAVE_ONE_TIME_AUTH */
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-/* function name is for cache_status++
- * This function was added because of error incrementing enum type when
- * compiling with a C++ compiler.
- */
-static void CacheStatusPP(SecureRenegotiation* cache)
-{
-    switch (cache->cache_status) {
-        case SCR_CACHE_NULL:
-            cache->cache_status = SCR_CACHE_NEEDED;
-            break;
-
-        case SCR_CACHE_NEEDED:
-            cache->cache_status = SCR_CACHE_COPY;
-            break;
-
-        case SCR_CACHE_COPY:
-            cache->cache_status = SCR_CACHE_PARTIAL;
-            break;
-
-        case SCR_CACHE_PARTIAL:
-            cache->cache_status = SCR_CACHE_COMPLETE;
-            break;
-
-        case SCR_CACHE_COMPLETE:
-            WOLFSSL_MSG("SCR Cache state Complete");
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown cache state!!");
-    }
-}
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-
-/* Set wc_encrypt/wc_decrypt or both sides of key setup
- * note: use wc_encrypt to avoid shadowing global encrypt
- * declared in unistd.h
- */
-int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
-{
-    int devId = INVALID_DEVID, ret, copy = 0;
-    Ciphers* wc_encrypt = NULL;
-    Ciphers* wc_decrypt = NULL;
-    Keys*    keys    = &ssl->keys;
-
-    (void)copy;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    devId = ssl->devId;
-#endif
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) {
-        keys = &ssl->secure_renegotiation->tmp_keys;
-        copy = 1;
-    }
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-    switch (side) {
-        case ENCRYPT_SIDE_ONLY:
-#ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Provisioning ENCRYPT key");
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
-            }
-            else {
-                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
-            }
-#endif
-            wc_encrypt = &ssl->encrypt;
-            break;
-
-        case DECRYPT_SIDE_ONLY:
-#ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Provisioning DECRYPT key");
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
-            }
-            else {
-                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
-            }
-#endif
-            wc_decrypt = &ssl->decrypt;
-            break;
-
-        case ENCRYPT_AND_DECRYPT_SIDE:
-#ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Provisioning ENCRYPT key");
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
-            }
-            else {
-                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
-            }
-            WOLFSSL_MSG("Provisioning DECRYPT key");
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
-            }
-            else {
-                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
-            }
-#endif
-            wc_encrypt = &ssl->encrypt;
-            wc_decrypt = &ssl->decrypt;
-            break;
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-#ifdef HAVE_ONE_TIME_AUTH
-    if (!ssl->auth.setup && ssl->specs.bulk_cipher_algorithm == wolfssl_chacha){
-        ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, devId);
-        if (ret != 0)
-           return ret;
-    }
-#endif
-
-    ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side,
-                  ssl->heap, devId);
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (copy) {
-        int clientCopy = 0;
-
-        if (ssl->options.side == WOLFSSL_CLIENT_END && wc_encrypt)
-            clientCopy = 1;
-        else if (ssl->options.side == WOLFSSL_SERVER_END && wc_decrypt)
-            clientCopy = 1;
-
-        if (clientCopy) {
-            XMEMCPY(ssl->keys.client_write_MAC_secret,
-                    keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE);
-            XMEMCPY(ssl->keys.client_write_key,
-                    keys->client_write_key, AES_256_KEY_SIZE);
-            XMEMCPY(ssl->keys.client_write_IV,
-                    keys->client_write_IV, MAX_WRITE_IV_SZ);
-        } else {
-            XMEMCPY(ssl->keys.server_write_MAC_secret,
-                    keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE);
-            XMEMCPY(ssl->keys.server_write_key,
-                    keys->server_write_key, AES_256_KEY_SIZE);
-            XMEMCPY(ssl->keys.server_write_IV,
-                    keys->server_write_IV, MAX_WRITE_IV_SZ);
-        }
-        if (wc_encrypt) {
-            ssl->keys.sequence_number_hi = keys->sequence_number_hi;
-            ssl->keys.sequence_number_lo = keys->sequence_number_lo;
-            #ifdef HAVE_AEAD
-                if (ssl->specs.cipher_type == aead) {
-                    /* Initialize the AES-GCM/CCM explicit IV to a zero. */
-                    XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV,
-                            AEAD_MAX_EXP_SZ);
-
-                    /* Initialize encrypt implicit IV by encrypt side */
-                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
-                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
-                    } else {
-                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
-                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
-                    }
-                }
-            #endif
-        }
-        if (wc_decrypt) {
-            ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi;
-            ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo;
-            #ifdef HAVE_AEAD
-                if (ssl->specs.cipher_type == aead) {
-                    /* Initialize decrypt implicit IV by decrypt side */
-                    if (ssl->options.side == WOLFSSL_SERVER_END) {
-                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
-                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
-                    } else {
-                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
-                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
-                    }
-                }
-            #endif
-        }
-        CacheStatusPP(ssl->secure_renegotiation);
-    }
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-    return ret;
-}
-
-
-/* TLS can call too */
-int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
-{
-    int sz, i = 0;
-    Keys* keys = &ssl->keys;
-
-#ifdef HAVE_SECURE_RENEGOTIATION
-    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status ==
-                                                            SCR_CACHE_NEEDED) {
-        keys = &ssl->secure_renegotiation->tmp_keys;
-        CacheStatusPP(ssl->secure_renegotiation);
-    }
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-#ifdef WOLFSSL_MULTICAST
-    if (ssl->options.haveMcast) {
-        /* Use the same keys for encrypt and decrypt. */
-        if (ssl->specs.cipher_type != aead) {
-            sz = ssl->specs.hash_size;
-            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
-            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
-            i += sz;
-        }
-        sz = ssl->specs.key_size;
-        XMEMCPY(keys->client_write_key, &keyData[i], sz);
-        XMEMCPY(keys->server_write_key, &keyData[i], sz);
-        i += sz;
-
-        sz = ssl->specs.iv_size;
-        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
-        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
-
-#ifdef HAVE_AEAD
-        if (ssl->specs.cipher_type == aead) {
-            /* Initialize the AES-GCM/CCM explicit IV to a zero. */
-            XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
-        }
-#endif /* HAVE_AEAD */
-
-        return 0;
-    }
-#endif /* WOLFSSL_MULTICAST */
-
-    if (ssl->specs.cipher_type != aead) {
-        sz = ssl->specs.hash_size;
-        if (side & PROVISION_CLIENT) {
-            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
-            i += sz;
-        }
-        if (side & PROVISION_SERVER) {
-            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
-            i += sz;
-        }
-    }
-    sz = ssl->specs.key_size;
-    if (side & PROVISION_CLIENT) {
-        XMEMCPY(keys->client_write_key, &keyData[i], sz);
-        i += sz;
-    }
-    if (side & PROVISION_SERVER) {
-        XMEMCPY(keys->server_write_key, &keyData[i], sz);
-        i += sz;
-    }
-
-    sz = ssl->specs.iv_size;
-    if (side & PROVISION_CLIENT) {
-        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
-        i += sz;
-    }
-    if (side & PROVISION_SERVER)
-        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
-
-#ifdef HAVE_AEAD
-    if (ssl->specs.cipher_type == aead) {
-        /* Initialize the AES-GCM/CCM explicit IV to a zero. */
-        XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
-    }
-#endif
-
-    return 0;
-}
-
-#ifndef NO_OLD_TLS
-int DeriveKeys(WOLFSSL* ssl)
-{
-    int    length = 2 * ssl->specs.hash_size +
-                    2 * ssl->specs.key_size  +
-                    2 * ssl->specs.iv_size;
-    int    rounds = (length + WC_MD5_DIGEST_SIZE - 1 ) / WC_MD5_DIGEST_SIZE, i;
-    int    ret = 0;
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  shaOutput;
-    byte*  md5Input;
-    byte*  shaInput;
-    byte*  keyData;
-    wc_Md5* md5;
-    wc_Sha* sha;
-#else
-    byte   shaOutput[WC_SHA_DIGEST_SIZE];
-    byte   md5Input[SECRET_LEN + WC_SHA_DIGEST_SIZE];
-    byte   shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
-    byte   keyData[KEY_PREFIX * WC_MD5_DIGEST_SIZE];
-    wc_Md5 md5[1];
-    wc_Sha sha[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    md5Input  = (byte*)XMALLOC(SECRET_LEN + WC_SHA_DIGEST_SIZE,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    shaInput  = (byte*)XMALLOC(KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    keyData   = (byte*)XMALLOC(KEY_PREFIX * WC_MD5_DIGEST_SIZE,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
-        keyData   == NULL || md5      == NULL || sha      == NULL) {
-        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (keyData)   XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-        return MEMORY_E;
-    }
-#endif
-
-    ret = wc_InitMd5(md5);
-    if (ret == 0) {
-        ret = wc_InitSha(sha);
-    }
-    if (ret == 0) {
-        XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN);
-
-        for (i = 0; i < rounds; ++i) {
-            int j   = i + 1;
-            int idx = j;
-
-            if (!SetPrefix(shaInput, i)) {
-                ret = PREFIX_ERROR;
-                break;
-            }
-
-            XMEMCPY(shaInput + idx, ssl->arrays->masterSecret, SECRET_LEN);
-            idx += SECRET_LEN;
-            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
-            idx += RAN_LEN;
-            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
-            if (ret == 0) {
-                ret = wc_ShaUpdate(sha, shaInput,
-                    (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j);
-            }
-            if (ret == 0) {
-                ret = wc_ShaFinal(sha, shaOutput);
-            }
-
-            XMEMCPY(md5Input + SECRET_LEN, shaOutput, WC_SHA_DIGEST_SIZE);
-            if (ret == 0) {
-                ret = wc_Md5Update(md5, md5Input, SECRET_LEN + WC_SHA_DIGEST_SIZE);
-            }
-            if (ret == 0) {
-                ret = wc_Md5Final(md5, keyData + i * WC_MD5_DIGEST_SIZE);
-            }
-        }
-
-        if (ret == 0)
-            ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-static int CleanPreMaster(WOLFSSL* ssl)
-{
-    int i, ret, sz = ssl->arrays->preMasterSz;
-
-    for (i = 0; i < sz; i++)
-        ssl->arrays->preMasterSecret[i] = 0;
-
-    ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, sz);
-    if (ret != 0)
-        return ret;
-
-    for (i = 0; i < sz; i++)
-        ssl->arrays->preMasterSecret[i] = 0;
-
-    return 0;
-}
-
-
-/* Create and store the master secret see page 32, 6.1 */
-static int MakeSslMasterSecret(WOLFSSL* ssl)
-{
-    int    i, ret;
-    word32 idx;
-    word32 pmsSz = ssl->arrays->preMasterSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  shaOutput;
-    byte*  md5Input;
-    byte*  shaInput;
-    wc_Md5* md5;
-    wc_Sha* sha;
-#else
-    byte   shaOutput[WC_SHA_DIGEST_SIZE];
-    byte   md5Input[ENCRYPT_LEN + WC_SHA_DIGEST_SIZE];
-    byte   shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
-    wc_Md5 md5[1];
-    wc_Sha sha[1];
-#endif
-
-#ifdef SHOW_SECRETS
-    {
-        word32 j;
-        printf("pre master secret: ");
-        for (j = 0; j < pmsSz; j++)
-            printf("%02x", ssl->arrays->preMasterSecret[j]);
-        printf("\n");
-    }
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    md5Input  = (byte*)XMALLOC(ENCRYPT_LEN + WC_SHA_DIGEST_SIZE,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    shaInput  = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN,
-                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
-                             md5      == NULL || sha      == NULL) {
-        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-        return MEMORY_E;
-    }
-#endif
-
-    ret = wc_InitMd5(md5);
-    if (ret == 0) {
-        ret = wc_InitSha(sha);
-    }
-    if (ret == 0) {
-        XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz);
-
-        for (i = 0; i < MASTER_ROUNDS; ++i) {
-            byte prefix[KEY_PREFIX];      /* only need PREFIX bytes but static */
-            if (!SetPrefix(prefix, i)) {  /* analysis thinks will overrun      */
-                ret = PREFIX_ERROR;
-                break;
-            }
-
-            idx = 0;
-            XMEMCPY(shaInput, prefix, i + 1);
-            idx += i + 1;
-
-            XMEMCPY(shaInput + idx, ssl->arrays->preMasterSecret, pmsSz);
-            idx += pmsSz;
-            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
-            idx += RAN_LEN;
-            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
-            idx += RAN_LEN;
-            if (ret == 0) {
-                ret = wc_ShaUpdate(sha, shaInput, idx);
-            }
-            if (ret == 0) {
-                ret = wc_ShaFinal(sha, shaOutput);
-            }
-            idx = pmsSz;  /* preSz */
-            XMEMCPY(md5Input + idx, shaOutput, WC_SHA_DIGEST_SIZE);
-            idx += WC_SHA_DIGEST_SIZE;
-            if (ret == 0) {
-                ret = wc_Md5Update(md5, md5Input, idx);
-            }
-            if (ret == 0) {
-                ret = wc_Md5Final(md5,
-                            &ssl->arrays->masterSecret[i * WC_MD5_DIGEST_SIZE]);
-            }
-        }
-
-#ifdef SHOW_SECRETS
-        {
-            word32 j;
-            printf("master secret: ");
-            for (j = 0; j < SECRET_LEN; j++)
-                printf("%02x", ssl->arrays->masterSecret[j]);
-            printf("\n");
-        }
-#endif
-
-        if (ret == 0)
-            ret = DeriveKeys(ssl);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (ret == 0)
-        ret = CleanPreMaster(ssl);
-    else
-        CleanPreMaster(ssl);
-
-    return ret;
-}
-#endif
-
-
-/* Master wrapper, doesn't use SSL stack space in TLS mode */
-int MakeMasterSecret(WOLFSSL* ssl)
-{
-    /* append secret to premaster : premaster | SerSi | CliSi */
-#ifdef HAVE_QSH
-    word32 offset = 0;
-
-    if (ssl->peerQSHKeyPresent) {
-        offset += ssl->arrays->preMasterSz;
-        ssl->arrays->preMasterSz += ssl->QSH_secret->CliSi->length +
-                                                 ssl->QSH_secret->SerSi->length;
-        /* test and set flag if QSH has been used */
-        if (ssl->QSH_secret->CliSi->length > 0 ||
-                ssl->QSH_secret->SerSi->length > 0)
-            ssl->isQSH = 1;
-
-        /* append secrets to the premaster */
-        if (ssl->QSH_secret->SerSi != NULL) {
-            XMEMCPY(ssl->arrays->preMasterSecret + offset,
-                ssl->QSH_secret->SerSi->buffer, ssl->QSH_secret->SerSi->length);
-        }
-        offset += ssl->QSH_secret->SerSi->length;
-        if (ssl->QSH_secret->CliSi != NULL) {
-            XMEMCPY(ssl->arrays->preMasterSecret + offset,
-                ssl->QSH_secret->CliSi->buffer, ssl->QSH_secret->CliSi->length);
-        }
-
-        /* show secret SerSi and CliSi */
-        #ifdef SHOW_SECRETS
-        {
-            word32 j;
-            printf("QSH generated secret material\n");
-            printf("SerSi        : ");
-            for (j = 0; j < ssl->QSH_secret->SerSi->length; j++) {
-                printf("%02x", ssl->QSH_secret->SerSi->buffer[j]);
-            }
-            printf("\n");
-            printf("CliSi        : ");
-            for (j = 0; j < ssl->QSH_secret->CliSi->length; j++) {
-                printf("%02x", ssl->QSH_secret->CliSi->buffer[j]);
-            }
-            printf("\n");
-        }
-        #endif
-    }
-#endif
-
-#ifndef NO_OLD_TLS
-    if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
-    return MakeSslMasterSecret(ssl);
-#elif !defined(WOLFSSL_NO_TLS12)
-    return MakeTlsMasterSecret(ssl);
-#else
-    (void)ssl;
-    return 0;
-#endif
-}
-
-#endif /* WOLFCRYPT_ONLY */
-
-
+/* keys.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* Name change compatibility layer no longer needs to be included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
+    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+        #if MQX_USE_IO_OLD
+            #include <fio.h>
+        #else
+            #include <nio.h>
+        #endif
+    #else
+        #include <stdio.h>
+    #endif
+#endif
+
+
+int SetCipherSpecs(WOLFSSL* ssl)
+{
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* server side verified before SetCipherSpecs call */
+        if (VerifyClientSuite(ssl) != 1) {
+            WOLFSSL_MSG("SetCipherSpecs() client has an unusuable suite");
+            return UNSUPPORTED_SUITE;
+        }
+    }
+#endif /* NO_WOLFSSL_CLIENT */
+
+    /* Chacha extensions, 0xcc */
+    if (ssl->options.cipherSuite0 == CHACHA_BYTE) {
+
+    switch (ssl->options.cipherSuite) {
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+    case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 1; /* use old poly1305 padding */
+
+        break;
+#endif
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+    case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+        ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+        ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+        ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+
+        ssl->options.oldPoly             = 0; /* use recent padding RFC */
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ChaCha");
+        return UNSUPPORTED_SUITE;
+    }
+    }
+
+    /* ECC extensions, or AES-CCM */
+    if (ssl->options.cipherSuite0 == ECC_BYTE) {
+
+    switch (ssl->options.cipherSuite) {
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+    case TLS_ECDHE_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+    case TLS_ECDHE_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecdhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#endif /* HAVE_ECC || HAVE_CURVE25519 */
+
+#if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && defined(HAVE_ED25519))
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+    case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+    case TLS_ECDHE_ECDSA_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+    break;
+#endif
+
+#endif /* HAVE_ECC || (HAVE_CURVE25519 && HAVE_ED25519) */
+
+#if defined(HAVE_ECC)
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+    case TLS_ECDH_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+    case TLS_ECDH_ECDSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+    case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+    case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = ecc_diffie_hellman_kea;
+        ssl->specs.sig_algo              = ecc_dsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 1;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#endif /* HAVE_ECC */
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
+    case TLS_RSA_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8
+    case TLS_RSA_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
+    case TLS_PSK_WITH_AES_128_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8
+    case TLS_PSK_WITH_AES_256_CCM_8 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
+    case TLS_PSK_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM
+    case TLS_PSK_WITH_AES_256_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+    case TLS_DHE_PSK_WITH_AES_128_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+    case TLS_DHE_PSK_WITH_AES_256_CCM :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC");
+        return UNSUPPORTED_SUITE;
+    }   /* switch */
+    }   /* if     */
+
+    /* TLSi v1.3 cipher suites, 0x13 */
+    if (ssl->options.cipherSuite0 == TLS13_BYTE) {
+        switch (ssl->options.cipherSuite) {
+
+#ifdef WOLFSSL_TLS13
+    #ifdef BUILD_TLS_AES_128_GCM_SHA256
+        case TLS_AES_128_GCM_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_256_GCM_SHA384
+        case TLS_AES_256_GCM_SHA384 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha384_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_256_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256
+        case TLS_CHACHA20_POLY1305_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = CHACHA20_256_KEY_SIZE;
+            ssl->specs.block_size            = CHACHA20_BLOCK_SIZE;
+            ssl->specs.iv_size               = CHACHA20_IV_SIZE;
+            ssl->specs.aead_mac_size         = POLY1305_AUTH_SZ;
+            ssl->options.oldPoly             = 0; /* use recent padding RFC */
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_128_CCM_SHA256
+        case TLS_AES_128_CCM_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_CCM_16_AUTH_SZ;
+
+            break;
+    #endif
+
+    #ifdef BUILD_TLS_AES_128_CCM_8_SHA256
+        case TLS_AES_128_CCM_8_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm;
+            ssl->specs.cipher_type           = aead;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = 0;
+            ssl->specs.sig_algo              = 0;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+            ssl->specs.iv_size               = AESGCM_NONCE_SZ;
+            ssl->specs.aead_mac_size         = AES_CCM_8_AUTH_SZ;
+
+            break;
+    #endif
+#endif /* WOLFSSL_TLS13 */
+        }
+    }
+
+    if (ssl->options.cipherSuite0 != ECC_BYTE &&
+            ssl->options.cipherSuite0 != CHACHA_BYTE &&
+            ssl->options.cipherSuite0 != TLS13_BYTE) {   /* normal suites */
+    switch (ssl->options.cipherSuite) {
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+    case SSL_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+    case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+    case SSL_RSA_WITH_RC4_128_MD5 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rc4;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = md5_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_MD5;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RC4_KEY_SIZE;
+        ssl->specs.iv_size               = 0;
+        ssl->specs.block_size            = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+    case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+    case TLS_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
+    case TLS_RSA_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256
+    case TLS_RSA_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+    case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+    case TLS_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+    case TLS_RSA_WITH_AES_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+    case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = ntru_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+    case TLS_PSK_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+    case TLS_PSK_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+        
+#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+    case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+         ssl->options.usingAnon_cipher    = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+    case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+    case TLS_PSK_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+    case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+    case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+    case TLS_PSK_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+    case TLS_PSK_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
+    case TLS_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
+    case TLS_PSK_WITH_NULL_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
+    case TLS_PSK_WITH_NULL_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+    case TLS_DHE_PSK_WITH_NULL_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+    case TLS_DHE_PSK_WITH_NULL_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = dhe_psk_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = 0;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = 0;
+
+        ssl->options.usingPSK_cipher     = 1;
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+    case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = DES3_KEY_SIZE;
+        ssl->specs.block_size            = DES_BLOCK_SIZE;
+        ssl->specs.iv_size               = DES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5
+    case TLS_RSA_WITH_HC_128_MD5 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = md5_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_MD5_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_MD5;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = HC_128_KEY_SIZE;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = HC_128_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA
+        case TLS_RSA_WITH_HC_128_SHA :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
+            ssl->specs.cipher_type           = stream;
+            ssl->specs.mac_algorithm         = sha_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = HC_128_KEY_SIZE;
+            ssl->specs.block_size            = 0;
+            ssl->specs.iv_size               = HC_128_IV_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256
+        case TLS_RSA_WITH_HC_128_B2B256:
+            ssl->specs.bulk_cipher_algorithm = wolfssl_hc128;
+            ssl->specs.cipher_type           = stream;
+            ssl->specs.mac_algorithm         = blake2b_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = BLAKE2B_256;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = HC_128_KEY_SIZE;
+            ssl->specs.block_size            = 0;
+            ssl->specs.iv_size               = HC_128_IV_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
+        case TLS_RSA_WITH_AES_128_CBC_B2B256:
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+            ssl->specs.cipher_type           = block;
+            ssl->specs.mac_algorithm         = blake2b_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = BLAKE2B_256;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_128_KEY_SIZE;
+            ssl->specs.iv_size               = AES_IV_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
+        case TLS_RSA_WITH_AES_256_CBC_B2B256:
+            ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+            ssl->specs.cipher_type           = block;
+            ssl->specs.mac_algorithm         = blake2b_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = BLAKE2B_256;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = AES_256_KEY_SIZE;
+            ssl->specs.iv_size               = AES_IV_SIZE;
+            ssl->specs.block_size            = AES_BLOCK_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA
+    case TLS_RSA_WITH_RABBIT_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_rabbit;
+        ssl->specs.cipher_type           = stream;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = RABBIT_KEY_SIZE;
+        ssl->specs.block_size            = 0;
+        ssl->specs.iv_size               = RABBIT_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm;
+        ssl->specs.cipher_type           = aead;
+        ssl->specs.mac_algorithm         = sha384_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA384_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_256_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AESGCM_IMP_IV_SZ;
+        ssl->specs.aead_mac_size         = AES_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = rsa_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+    case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_128_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+    case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_camellia;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha256_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = rsa_sa_algo;
+        ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = CAMELLIA_256_KEY_SIZE;
+        ssl->specs.block_size            = CAMELLIA_BLOCK_SIZE;
+        ssl->specs.iv_size               = CAMELLIA_IV_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+    case TLS_DH_anon_WITH_AES_128_CBC_SHA :
+        ssl->specs.bulk_cipher_algorithm = wolfssl_aes;
+        ssl->specs.cipher_type           = block;
+        ssl->specs.mac_algorithm         = sha_mac;
+        ssl->specs.kea                   = diffie_hellman_kea;
+        ssl->specs.sig_algo              = anonymous_sa_algo;
+        ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+        ssl->specs.pad_size              = PAD_SHA;
+        ssl->specs.static_ecdh           = 0;
+        ssl->specs.key_size              = AES_128_KEY_SIZE;
+        ssl->specs.block_size            = AES_BLOCK_SIZE;
+        ssl->specs.iv_size               = AES_IV_SIZE;
+
+        ssl->options.usingAnon_cipher    = 1;
+        break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+        case SSL_RSA_WITH_IDEA_CBC_SHA :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_idea;
+            ssl->specs.cipher_type           = block;
+            ssl->specs.mac_algorithm         = sha_mac;
+            ssl->specs.kea                   = rsa_kea;
+            ssl->specs.sig_algo              = rsa_sa_algo;
+            ssl->specs.hash_size             = WC_SHA_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+            ssl->specs.static_ecdh           = 0;
+            ssl->specs.key_size              = IDEA_KEY_SIZE;
+            ssl->specs.block_size            = IDEA_BLOCK_SIZE;
+            ssl->specs.iv_size               = IDEA_IV_SIZE;
+
+            break;
+#endif
+
+#ifdef BUILD_WDM_WITH_NULL_SHA256
+        case WDM_WITH_NULL_SHA256 :
+            ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null;
+            ssl->specs.cipher_type           = stream;
+            ssl->specs.mac_algorithm         = sha256_mac;
+            ssl->specs.kea                   = no_kea;
+            ssl->specs.sig_algo              = anonymous_sa_algo;
+            ssl->specs.hash_size             = WC_SHA256_DIGEST_SIZE;
+            ssl->specs.pad_size              = PAD_SHA;
+
+            break;
+#endif
+
+    default:
+        WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs");
+        return UNSUPPORTED_SUITE;
+    }  /* switch */
+    }  /* if ECC / Normal suites else */
+
+    /* set TLS if it hasn't been turned off */
+    if (ssl->version.major == 3 && ssl->version.minor >= 1) {
+#ifndef NO_TLS
+        ssl->options.tls = 1;
+    #ifndef WOLFSSL_NO_TLS12
+        ssl->hmac = TLS_hmac;
+    #endif
+        if (ssl->version.minor >= 2) {
+            ssl->options.tls1_1 = 1;
+            if (ssl->version.minor >= 4)
+                ssl->options.tls1_3 = 1;
+        }
+#endif
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls)
+        ssl->hmac = TLS_hmac;
+#endif
+
+    return 0;
+}
+
+
+enum KeyStuff {
+    MASTER_ROUNDS = 3,
+    PREFIX        = 3,     /* up to three letters for master prefix */
+    KEY_PREFIX    = 9      /* up to 9 prefix letters for key rounds */
+
+
+};
+
+#ifndef NO_OLD_TLS
+/* true or false, zero for error */
+static int SetPrefix(byte* sha_input, int idx)
+{
+    switch (idx) {
+    case 0:
+        XMEMCPY(sha_input, "A", 1);
+        break;
+    case 1:
+        XMEMCPY(sha_input, "BB", 2);
+        break;
+    case 2:
+        XMEMCPY(sha_input, "CCC", 3);
+        break;
+    case 3:
+        XMEMCPY(sha_input, "DDDD", 4);
+        break;
+    case 4:
+        XMEMCPY(sha_input, "EEEEE", 5);
+        break;
+    case 5:
+        XMEMCPY(sha_input, "FFFFFF", 6);
+        break;
+    case 6:
+        XMEMCPY(sha_input, "GGGGGGG", 7);
+        break;
+    case 7:
+        XMEMCPY(sha_input, "HHHHHHHH", 8);
+        break;
+    case 8:
+        XMEMCPY(sha_input, "IIIIIIIII", 9);
+        break;
+    default:
+        WOLFSSL_MSG("Set Prefix error, bad input");
+        return 0;
+    }
+    return 1;
+}
+#endif
+
+
+static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
+                   int side, void* heap, int devId)
+{
+#ifdef BUILD_ARC4
+    word32 sz = specs->key_size;
+    if (specs->bulk_cipher_algorithm == wolfssl_rc4) {
+        if (enc && enc->arc4 == NULL)
+            enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->arc4 == NULL)
+            return MEMORY_E;
+        if (dec && dec->arc4 == NULL)
+            dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->arc4 == NULL)
+            return MEMORY_E;
+
+        if (enc) {
+            if (wc_Arc4Init(enc->arc4, heap, devId) != 0) {
+                WOLFSSL_MSG("Arc4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Arc4Init(dec->arc4, heap, devId) != 0) {
+                WOLFSSL_MSG("Arc4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc)
+                wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz);
+            if (dec)
+                wc_Arc4SetKey(dec->arc4, keys->server_write_key, sz);
+        }
+        else {
+            if (enc)
+                wc_Arc4SetKey(enc->arc4, keys->server_write_key, sz);
+            if (dec)
+                wc_Arc4SetKey(dec->arc4, keys->client_write_key, sz);
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_ARC4 */
+
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+    /* Check that the max implicit iv size is suffecient */
+    #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ is too small for ChaCha20
+    #endif
+    #if (MAX_WRITE_IV_SZ < 12) /* CHACHA20_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ is too small for ChaCha20
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_chacha) {
+        int chachaRet;
+        if (enc && enc->chacha == NULL)
+            enc->chacha =
+                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->chacha == NULL)
+            return MEMORY_E;
+        if (dec && dec->chacha == NULL)
+            dec->chacha =
+                    (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->chacha == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+            if (dec) {
+                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+        }
+        else {
+            if (enc) {
+                chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+            if (dec) {
+                chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key,
+                                          specs->key_size);
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        CHACHA20_IMP_IV_SZ);
+                if (chachaRet != 0) return chachaRet;
+            }
+        }
+
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_CHACHA && HAVE_POLY1305 */
+
+
+#ifdef HAVE_HC128
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* HC_128_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for HC128
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_hc128) {
+        int hcRet;
+        if (enc && enc->hc128 == NULL)
+            enc->hc128 =
+                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->hc128 == NULL)
+            return MEMORY_E;
+        if (dec && dec->hc128 == NULL)
+            dec->hc128 =
+                      (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->hc128 == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                hcRet = wc_Hc128_SetKey(enc->hc128, keys->client_write_key,
+                                     keys->client_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+            if (dec) {
+                hcRet = wc_Hc128_SetKey(dec->hc128, keys->server_write_key,
+                                     keys->server_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+        }
+        else {
+            if (enc) {
+                hcRet = wc_Hc128_SetKey(enc->hc128, keys->server_write_key,
+                                     keys->server_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+            if (dec) {
+                hcRet = wc_Hc128_SetKey(dec->hc128, keys->client_write_key,
+                                     keys->client_write_IV);
+                if (hcRet != 0) return hcRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_HC128 */
+
+#ifdef BUILD_RABBIT
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for RABBIT
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_rabbit) {
+        int rabRet;
+        if (enc && enc->rabbit == NULL)
+            enc->rabbit =
+                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->rabbit == NULL)
+            return MEMORY_E;
+        if (dec && dec->rabbit == NULL)
+            dec->rabbit =
+                    (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->rabbit == NULL)
+            return MEMORY_E;
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                rabRet = wc_RabbitSetKey(enc->rabbit, keys->client_write_key,
+                                      keys->client_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+            if (dec) {
+                rabRet = wc_RabbitSetKey(dec->rabbit, keys->server_write_key,
+                                      keys->server_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+        }
+        else {
+            if (enc) {
+                rabRet = wc_RabbitSetKey(enc->rabbit, keys->server_write_key,
+                                      keys->server_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+            if (dec) {
+                rabRet = wc_RabbitSetKey(dec->rabbit, keys->client_write_key,
+                                      keys->client_write_IV);
+                if (rabRet != 0) return rabRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_RABBIT */
+
+#ifdef BUILD_DES3
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for 3DES
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_triple_des) {
+        int desRet = 0;
+
+        if (enc) {
+            if (enc->des3 == NULL)
+                enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->des3 == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->des3, 0, sizeof(Des3));
+        }
+        if (dec) {
+            if (dec->des3 == NULL)
+                dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->des3 == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->des3, 0, sizeof(Des3));
+        }
+
+        if (enc) {
+            if (wc_Des3Init(enc->des3, heap, devId) != 0) {
+                WOLFSSL_MSG("Des3Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Des3Init(dec->des3, heap, devId) != 0) {
+                WOLFSSL_MSG("Des3Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key,
+                                     keys->client_write_IV, DES_ENCRYPTION);
+                if (desRet != 0) return desRet;
+            }
+            if (dec) {
+                desRet = wc_Des3_SetKey(dec->des3, keys->server_write_key,
+                                     keys->server_write_IV, DES_DECRYPTION);
+                if (desRet != 0) return desRet;
+            }
+        }
+        else {
+            if (enc) {
+                desRet = wc_Des3_SetKey(enc->des3, keys->server_write_key,
+                                     keys->server_write_IV, DES_ENCRYPTION);
+                if (desRet != 0) return desRet;
+            }
+            if (dec) {
+                desRet = wc_Des3_SetKey(dec->des3, keys->client_write_key,
+                                     keys->client_write_IV, DES_DECRYPTION);
+                if (desRet != 0) return desRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_DES3 */
+
+#ifdef BUILD_AES
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for AES
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes) {
+        int aesRet = 0;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                aesRet = wc_AesSetKey(enc->aes, keys->client_write_key,
+                                   specs->key_size, keys->client_write_IV,
+                                   AES_ENCRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+            if (dec) {
+                aesRet = wc_AesSetKey(dec->aes, keys->server_write_key,
+                                   specs->key_size, keys->server_write_IV,
+                                   AES_DECRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+        }
+        else {
+            if (enc) {
+                aesRet = wc_AesSetKey(enc->aes, keys->server_write_key,
+                                   specs->key_size, keys->server_write_IV,
+                                   AES_ENCRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+            if (dec) {
+                aesRet = wc_AesSetKey(dec->aes, keys->client_write_key,
+                                   specs->key_size, keys->client_write_IV,
+                                   AES_DECRYPTION);
+                if (aesRet != 0) return aesRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_AES */
+
+#ifdef BUILD_AESGCM
+    /* check that buffer sizes are sufficient */
+    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for AESGCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for AESGCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for AESGCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) {
+        int gcmRet;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                gcmRet = wc_AesGcmSetKey(enc->aes, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                gcmRet = wc_AesGcmSetKey(enc->aes, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* BUILD_AESGCM */
+
+#ifdef HAVE_AESCCM
+    /* check that buffer sizes are sufficient (CCM is same size as GCM) */
+    #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for AESCCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for AESCCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for AESCCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) {
+        int CcmRet;
+
+        if (enc) {
+            if (enc->aes == NULL)
+                enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (enc->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(enc->aes, 0, sizeof(Aes));
+        }
+        if (dec) {
+            if (dec->aes == NULL)
+                dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
+            if (dec->aes == NULL)
+                return MEMORY_E;
+            XMEMSET(dec->aes, 0, sizeof(Aes));
+        }
+
+        if (enc) {
+            if (wc_AesInit(enc->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_AesInit(dec->aes, heap, devId) != 0) {
+                WOLFSSL_MSG("AesInit failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                CcmRet = wc_AesCcmSetKey(enc->aes, keys->client_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                CcmRet = wc_AesCcmSetKey(enc->aes, keys->server_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key,
+                                         specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_AESCCM */
+
+#ifdef HAVE_CAMELLIA
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* CAMELLIA_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for CAMELLIA
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_camellia) {
+        int camRet;
+
+        if (enc && enc->cam == NULL)
+            enc->cam =
+                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->cam == NULL)
+            return MEMORY_E;
+
+        if (dec && dec->cam == NULL)
+            dec->cam =
+                (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->cam == NULL)
+            return MEMORY_E;
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                camRet = wc_CamelliaSetKey(enc->cam, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV);
+                if (camRet != 0) return camRet;
+            }
+            if (dec) {
+                camRet = wc_CamelliaSetKey(dec->cam, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV);
+                if (camRet != 0) return camRet;
+            }
+        }
+        else {
+            if (enc) {
+                camRet = wc_CamelliaSetKey(enc->cam, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV);
+                if (camRet != 0) return camRet;
+            }
+            if (dec) {
+                camRet = wc_CamelliaSetKey(dec->cam, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV);
+                if (camRet != 0) return camRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_CAMELLIA */
+
+#ifdef HAVE_IDEA
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 8) /* IDEA_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for IDEA
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_idea) {
+        int ideaRet;
+
+        if (enc && enc->idea == NULL)
+            enc->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
+        if (enc && enc->idea == NULL)
+            return MEMORY_E;
+
+        if (dec && dec->idea == NULL)
+            dec->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER);
+        if (dec && dec->idea == NULL)
+            return MEMORY_E;
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                ideaRet = wc_IdeaSetKey(enc->idea, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV,
+                                        IDEA_ENCRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+            if (dec) {
+                ideaRet = wc_IdeaSetKey(dec->idea, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV,
+                                        IDEA_DECRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+        }
+        else {
+            if (enc) {
+                ideaRet = wc_IdeaSetKey(enc->idea, keys->server_write_key,
+                                        specs->key_size, keys->server_write_IV,
+                                        IDEA_ENCRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+            if (dec) {
+                ideaRet = wc_IdeaSetKey(dec->idea, keys->client_write_key,
+                                        specs->key_size, keys->client_write_IV,
+                                        IDEA_DECRYPTION);
+                if (ideaRet != 0) return ideaRet;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* HAVE_IDEA */
+
+#ifdef HAVE_NULL_CIPHER
+    if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) {
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif
+
+    if (enc) {
+        keys->sequence_number_hi      = 0;
+        keys->sequence_number_lo      = 0;
+    }
+    if (dec) {
+        keys->peer_sequence_number_hi = 0;
+        keys->peer_sequence_number_lo = 0;
+    }
+    (void)side;
+    (void)heap;
+    (void)enc;
+    (void)dec;
+    (void)specs;
+    (void)devId;
+
+    return 0;
+}
+
+
+#ifdef HAVE_ONE_TIME_AUTH
+/* set one time authentication keys */
+static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys,
+                       CipherSpecs* specs, void* heap, int devId)
+{
+
+#ifdef HAVE_POLY1305
+        /* set up memory space for poly1305 */
+        if (authentication && authentication->poly1305 == NULL)
+            authentication->poly1305 =
+                (Poly1305*)XMALLOC(sizeof(Poly1305), heap, DYNAMIC_TYPE_CIPHER);
+        if (authentication && authentication->poly1305 == NULL)
+            return MEMORY_E;
+        if (authentication)
+            authentication->setup = 1;
+#endif
+        (void)authentication;
+        (void)heap;
+        (void)keys;
+        (void)specs;
+        (void)devId;
+
+        return 0;
+}
+#endif /* HAVE_ONE_TIME_AUTH */
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+/* function name is for cache_status++
+ * This function was added because of error incrementing enum type when
+ * compiling with a C++ compiler.
+ */
+static void CacheStatusPP(SecureRenegotiation* cache)
+{
+    switch (cache->cache_status) {
+        case SCR_CACHE_NULL:
+            cache->cache_status = SCR_CACHE_NEEDED;
+            break;
+
+        case SCR_CACHE_NEEDED:
+            cache->cache_status = SCR_CACHE_COPY;
+            break;
+
+        case SCR_CACHE_COPY:
+            cache->cache_status = SCR_CACHE_PARTIAL;
+            break;
+
+        case SCR_CACHE_PARTIAL:
+            cache->cache_status = SCR_CACHE_COMPLETE;
+            break;
+
+        case SCR_CACHE_COMPLETE:
+            WOLFSSL_MSG("SCR Cache state Complete");
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown cache state!!");
+    }
+}
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+
+/* Set wc_encrypt/wc_decrypt or both sides of key setup
+ * note: use wc_encrypt to avoid shadowing global encrypt
+ * declared in unistd.h
+ */
+int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
+{
+    int devId = INVALID_DEVID, ret, copy = 0;
+    Ciphers* wc_encrypt = NULL;
+    Ciphers* wc_decrypt = NULL;
+    Keys*    keys    = &ssl->keys;
+
+    (void)copy;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    devId = ssl->devId;
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) {
+        keys = &ssl->secure_renegotiation->tmp_keys;
+        copy = 1;
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    switch (side) {
+        case ENCRYPT_SIDE_ONLY:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning ENCRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
+            }
+#endif
+            wc_encrypt = &ssl->encrypt;
+            break;
+
+        case DECRYPT_SIDE_ONLY:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning DECRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
+            }
+#endif
+            wc_decrypt = &ssl->decrypt;
+            break;
+
+        case ENCRYPT_AND_DECRYPT_SIDE:
+#ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Provisioning ENCRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
+            }
+            WOLFSSL_MSG("Provisioning DECRYPT key");
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE);
+            }
+            else {
+                WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE);
+            }
+#endif
+            wc_encrypt = &ssl->encrypt;
+            wc_decrypt = &ssl->decrypt;
+            break;
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+#ifdef HAVE_ONE_TIME_AUTH
+    if (!ssl->auth.setup && ssl->specs.bulk_cipher_algorithm == wolfssl_chacha){
+        ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, devId);
+        if (ret != 0)
+           return ret;
+    }
+#endif
+
+    ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side,
+                  ssl->heap, devId);
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (copy) {
+        int clientCopy = 0;
+
+        if (ssl->options.side == WOLFSSL_CLIENT_END && wc_encrypt)
+            clientCopy = 1;
+        else if (ssl->options.side == WOLFSSL_SERVER_END && wc_decrypt)
+            clientCopy = 1;
+
+        if (clientCopy) {
+            XMEMCPY(ssl->keys.client_write_MAC_secret,
+                    keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE);
+            XMEMCPY(ssl->keys.client_write_key,
+                    keys->client_write_key, AES_256_KEY_SIZE);
+            XMEMCPY(ssl->keys.client_write_IV,
+                    keys->client_write_IV, MAX_WRITE_IV_SZ);
+        } else {
+            XMEMCPY(ssl->keys.server_write_MAC_secret,
+                    keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE);
+            XMEMCPY(ssl->keys.server_write_key,
+                    keys->server_write_key, AES_256_KEY_SIZE);
+            XMEMCPY(ssl->keys.server_write_IV,
+                    keys->server_write_IV, MAX_WRITE_IV_SZ);
+        }
+        if (wc_encrypt) {
+            ssl->keys.sequence_number_hi = keys->sequence_number_hi;
+            ssl->keys.sequence_number_lo = keys->sequence_number_lo;
+            #ifdef HAVE_AEAD
+                if (ssl->specs.cipher_type == aead) {
+                    /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+                    XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV,
+                            AEAD_MAX_EXP_SZ);
+
+                    /* Initialize encrypt implicit IV by encrypt side */
+                    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
+                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
+                    } else {
+                        XMEMCPY(ssl->keys.aead_enc_imp_IV,
+                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
+                    }
+                }
+            #endif
+        }
+        if (wc_decrypt) {
+            ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi;
+            ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo;
+            #ifdef HAVE_AEAD
+                if (ssl->specs.cipher_type == aead) {
+                    /* Initialize decrypt implicit IV by decrypt side */
+                    if (ssl->options.side == WOLFSSL_SERVER_END) {
+                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
+                                keys->client_write_IV, AEAD_MAX_IMP_SZ);
+                    } else {
+                        XMEMCPY(ssl->keys.aead_dec_imp_IV,
+                                keys->server_write_IV, AEAD_MAX_IMP_SZ);
+                    }
+                }
+            #endif
+        }
+        CacheStatusPP(ssl->secure_renegotiation);
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    return ret;
+}
+
+
+/* TLS can call too */
+int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
+{
+    int sz, i = 0;
+    Keys* keys = &ssl->keys;
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status ==
+                                                            SCR_CACHE_NEEDED) {
+        keys = &ssl->secure_renegotiation->tmp_keys;
+        CacheStatusPP(ssl->secure_renegotiation);
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+#ifdef WOLFSSL_MULTICAST
+    if (ssl->options.haveMcast) {
+        /* Use the same keys for encrypt and decrypt. */
+        if (ssl->specs.cipher_type != aead) {
+            sz = ssl->specs.hash_size;
+            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
+            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
+            i += sz;
+        }
+        sz = ssl->specs.key_size;
+        XMEMCPY(keys->client_write_key, &keyData[i], sz);
+        XMEMCPY(keys->server_write_key, &keyData[i], sz);
+        i += sz;
+
+        sz = ssl->specs.iv_size;
+        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
+        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
+
+#ifdef HAVE_AEAD
+        if (ssl->specs.cipher_type == aead) {
+            /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+            XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
+        }
+#endif /* HAVE_AEAD */
+
+        return 0;
+    }
+#endif /* WOLFSSL_MULTICAST */
+
+    if (ssl->specs.cipher_type != aead) {
+        sz = ssl->specs.hash_size;
+        if (side & PROVISION_CLIENT) {
+            XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
+            i += sz;
+        }
+        if (side & PROVISION_SERVER) {
+            XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
+            i += sz;
+        }
+    }
+    sz = ssl->specs.key_size;
+    if (side & PROVISION_CLIENT) {
+        XMEMCPY(keys->client_write_key, &keyData[i], sz);
+        i += sz;
+    }
+    if (side & PROVISION_SERVER) {
+        XMEMCPY(keys->server_write_key, &keyData[i], sz);
+        i += sz;
+    }
+
+    sz = ssl->specs.iv_size;
+    if (side & PROVISION_CLIENT) {
+        XMEMCPY(keys->client_write_IV, &keyData[i], sz);
+        i += sz;
+    }
+    if (side & PROVISION_SERVER)
+        XMEMCPY(keys->server_write_IV, &keyData[i], sz);
+
+#ifdef HAVE_AEAD
+    if (ssl->specs.cipher_type == aead) {
+        /* Initialize the AES-GCM/CCM explicit IV to a zero. */
+        XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ);
+    }
+#endif
+
+    return 0;
+}
+
+#ifndef NO_OLD_TLS
+int DeriveKeys(WOLFSSL* ssl)
+{
+    int    length = 2 * ssl->specs.hash_size +
+                    2 * ssl->specs.key_size  +
+                    2 * ssl->specs.iv_size;
+    int    rounds = (length + WC_MD5_DIGEST_SIZE - 1 ) / WC_MD5_DIGEST_SIZE, i;
+    int    ret = 0;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  shaOutput;
+    byte*  md5Input;
+    byte*  shaInput;
+    byte*  keyData;
+    wc_Md5* md5;
+    wc_Sha* sha;
+#else
+    byte   shaOutput[WC_SHA_DIGEST_SIZE];
+    byte   md5Input[SECRET_LEN + WC_SHA_DIGEST_SIZE];
+    byte   shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+    byte   keyData[KEY_PREFIX * WC_MD5_DIGEST_SIZE];
+    wc_Md5 md5[1];
+    wc_Sha sha[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5Input  = (byte*)XMALLOC(SECRET_LEN + WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    shaInput  = (byte*)XMALLOC(KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    keyData   = (byte*)XMALLOC(KEY_PREFIX * WC_MD5_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
+        keyData   == NULL || md5      == NULL || sha      == NULL) {
+        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (keyData)   XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return MEMORY_E;
+    }
+#endif
+
+    ret = wc_InitMd5(md5);
+    if (ret == 0) {
+        ret = wc_InitSha(sha);
+    }
+    if (ret == 0) {
+        XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN);
+
+        for (i = 0; i < rounds; ++i) {
+            int j   = i + 1;
+            int idx = j;
+
+            if (!SetPrefix(shaInput, i)) {
+                ret = PREFIX_ERROR;
+                break;
+            }
+
+            XMEMCPY(shaInput + idx, ssl->arrays->masterSecret, SECRET_LEN);
+            idx += SECRET_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
+            if (ret == 0) {
+                ret = wc_ShaUpdate(sha, shaInput,
+                    (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j);
+            }
+            if (ret == 0) {
+                ret = wc_ShaFinal(sha, shaOutput);
+            }
+
+            XMEMCPY(md5Input + SECRET_LEN, shaOutput, WC_SHA_DIGEST_SIZE);
+            if (ret == 0) {
+                ret = wc_Md5Update(md5, md5Input, SECRET_LEN + WC_SHA_DIGEST_SIZE);
+            }
+            if (ret == 0) {
+                ret = wc_Md5Final(md5, keyData + i * WC_MD5_DIGEST_SIZE);
+            }
+        }
+
+        if (ret == 0)
+            ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(keyData,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+
+static int CleanPreMaster(WOLFSSL* ssl)
+{
+    int i, ret, sz = ssl->arrays->preMasterSz;
+
+    for (i = 0; i < sz; i++)
+        ssl->arrays->preMasterSecret[i] = 0;
+
+    ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, sz);
+    if (ret != 0)
+        return ret;
+
+    for (i = 0; i < sz; i++)
+        ssl->arrays->preMasterSecret[i] = 0;
+
+    return 0;
+}
+
+
+/* Create and store the master secret see page 32, 6.1 */
+static int MakeSslMasterSecret(WOLFSSL* ssl)
+{
+    int    i, ret;
+    word32 idx;
+    word32 pmsSz = ssl->arrays->preMasterSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+    byte*  shaOutput;
+    byte*  md5Input;
+    byte*  shaInput;
+    wc_Md5* md5;
+    wc_Sha* sha;
+#else
+    byte   shaOutput[WC_SHA_DIGEST_SIZE];
+    byte   md5Input[ENCRYPT_LEN + WC_SHA_DIGEST_SIZE];
+    byte   shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
+    wc_Md5 md5[1];
+    wc_Sha sha[1];
+#endif
+
+#ifdef SHOW_SECRETS
+    {
+        word32 j;
+        printf("pre master secret: ");
+        for (j = 0; j < pmsSz; j++)
+            printf("%02x", ssl->arrays->preMasterSecret[j]);
+        printf("\n");
+    }
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5Input  = (byte*)XMALLOC(ENCRYPT_LEN + WC_SHA_DIGEST_SIZE,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    shaInput  = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN,
+                                            NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    md5       =  (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    sha       =  (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
+                             md5      == NULL || sha      == NULL) {
+        if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5Input)  XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (shaInput)  XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (md5)       XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sha)       XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return MEMORY_E;
+    }
+#endif
+
+    ret = wc_InitMd5(md5);
+    if (ret == 0) {
+        ret = wc_InitSha(sha);
+    }
+    if (ret == 0) {
+        XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz);
+
+        for (i = 0; i < MASTER_ROUNDS; ++i) {
+            byte prefix[KEY_PREFIX];      /* only need PREFIX bytes but static */
+            if (!SetPrefix(prefix, i)) {  /* analysis thinks will overrun      */
+                ret = PREFIX_ERROR;
+                break;
+            }
+
+            idx = 0;
+            XMEMCPY(shaInput, prefix, i + 1);
+            idx += i + 1;
+
+            XMEMCPY(shaInput + idx, ssl->arrays->preMasterSecret, pmsSz);
+            idx += pmsSz;
+            XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
+            idx += RAN_LEN;
+            XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN);
+            idx += RAN_LEN;
+            if (ret == 0) {
+                ret = wc_ShaUpdate(sha, shaInput, idx);
+            }
+            if (ret == 0) {
+                ret = wc_ShaFinal(sha, shaOutput);
+            }
+            idx = pmsSz;  /* preSz */
+            XMEMCPY(md5Input + idx, shaOutput, WC_SHA_DIGEST_SIZE);
+            idx += WC_SHA_DIGEST_SIZE;
+            if (ret == 0) {
+                ret = wc_Md5Update(md5, md5Input, idx);
+            }
+            if (ret == 0) {
+                ret = wc_Md5Final(md5,
+                            &ssl->arrays->masterSecret[i * WC_MD5_DIGEST_SIZE]);
+            }
+        }
+
+#ifdef SHOW_SECRETS
+        {
+            word32 j;
+            printf("master secret: ");
+            for (j = 0; j < SECRET_LEN; j++)
+                printf("%02x", ssl->arrays->masterSecret[j]);
+            printf("\n");
+        }
+#endif
+
+        if (ret == 0)
+            ret = DeriveKeys(ssl);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5Input,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(shaInput,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(md5,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(sha,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (ret == 0)
+        ret = CleanPreMaster(ssl);
+    else
+        CleanPreMaster(ssl);
+
+    return ret;
+}
+#endif
+
+
+/* Master wrapper, doesn't use SSL stack space in TLS mode */
+int MakeMasterSecret(WOLFSSL* ssl)
+{
+    /* append secret to premaster : premaster | SerSi | CliSi */
+#ifdef HAVE_QSH
+    word32 offset = 0;
+
+    if (ssl->peerQSHKeyPresent) {
+        offset += ssl->arrays->preMasterSz;
+        ssl->arrays->preMasterSz += ssl->QSH_secret->CliSi->length +
+                                                 ssl->QSH_secret->SerSi->length;
+        /* test and set flag if QSH has been used */
+        if (ssl->QSH_secret->CliSi->length > 0 ||
+                ssl->QSH_secret->SerSi->length > 0)
+            ssl->isQSH = 1;
+
+        /* append secrets to the premaster */
+        if (ssl->QSH_secret->SerSi != NULL) {
+            XMEMCPY(ssl->arrays->preMasterSecret + offset,
+                ssl->QSH_secret->SerSi->buffer, ssl->QSH_secret->SerSi->length);
+        }
+        offset += ssl->QSH_secret->SerSi->length;
+        if (ssl->QSH_secret->CliSi != NULL) {
+            XMEMCPY(ssl->arrays->preMasterSecret + offset,
+                ssl->QSH_secret->CliSi->buffer, ssl->QSH_secret->CliSi->length);
+        }
+
+        /* show secret SerSi and CliSi */
+        #ifdef SHOW_SECRETS
+        {
+            word32 j;
+            printf("QSH generated secret material\n");
+            printf("SerSi        : ");
+            for (j = 0; j < ssl->QSH_secret->SerSi->length; j++) {
+                printf("%02x", ssl->QSH_secret->SerSi->buffer[j]);
+            }
+            printf("\n");
+            printf("CliSi        : ");
+            for (j = 0; j < ssl->QSH_secret->CliSi->length; j++) {
+                printf("%02x", ssl->QSH_secret->CliSi->buffer[j]);
+            }
+            printf("\n");
+        }
+        #endif
+    }
+#endif
+
+#ifndef NO_OLD_TLS
+    if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
+    return MakeSslMasterSecret(ssl);
+#elif !defined(WOLFSSL_NO_TLS12)
+    return MakeTlsMasterSecret(ssl);
+#else
+    (void)ssl;
+    return 0;
+#endif
+}
+
+#endif /* WOLFCRYPT_ONLY */
+
+
--- a/src/ocsp.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/ocsp.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,866 +1,866 @@
-/* ocsp.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-  /* Name change compatibility layer no longer needs to be included here */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-#ifdef HAVE_OCSP
-
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/ocsp.h>
-#include <wolfssl/internal.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("InitOCSP");
-
-    ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
-
-    if (wc_InitMutex(&ocsp->ocspLock) != 0)
-        return BAD_MUTEX_E;
-
-    ocsp->cm = cm;
-
-    return 0;
-}
-
-
-static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
-{
-    WOLFSSL_ENTER("InitOcspEntry");
-
-    ForceZero(entry, sizeof(OcspEntry));
-
-    XMEMCPY(entry->issuerHash,    request->issuerHash,    OCSP_DIGEST_SIZE);
-    XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
-
-    return 0;
-}
-
-
-static void FreeOcspEntry(OcspEntry* entry, void* heap)
-{
-    CertStatus *status, *next;
-
-    WOLFSSL_ENTER("FreeOcspEntry");
-
-    for (status = entry->status; status; status = next) {
-        next = status->next;
-
-        if (status->rawOcspResponse)
-            XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
-
-        XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
-    }
-
-    (void)heap;
-}
-
-
-void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
-{
-    OcspEntry *entry, *next;
-
-    WOLFSSL_ENTER("FreeOCSP");
-
-    for (entry = ocsp->ocspList; entry; entry = next) {
-        next = entry->next;
-        FreeOcspEntry(entry, ocsp->cm->heap);
-        XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
-    }
-
-    wc_FreeMutex(&ocsp->ocspLock);
-
-    if (dynamic)
-        XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
-
-}
-
-
-static int xstat2err(int st)
-{
-    switch (st) {
-        case CERT_GOOD:
-            return 0;
-        case CERT_REVOKED:
-            return OCSP_CERT_REVOKED;
-        default:
-            return OCSP_CERT_UNKNOWN;
-    }
-}
-
-int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
-{
-    int ret = OCSP_LOOKUP_FAIL;
-
-#ifdef WOLFSSL_SMALL_STACK
-    OcspRequest* ocspRequest;
-#else
-    OcspRequest ocspRequest[1];
-#endif
-
-    WOLFSSL_ENTER("CheckCertOCSP");
-
-
-#ifdef WOLFSSL_SMALL_STACK
-    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (ocspRequest == NULL) {
-        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
-        return MEMORY_E;
-    }
-#endif
-
-    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
-                                                         ocsp->cm->heap) == 0) {
-        ocspRequest->ssl = ssl;
-        ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
-
-        FreeOcspRequest(ocspRequest);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    WOLFSSL_LEAVE("CheckCertOCSP", ret);
-    return ret;
-}
-int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
-{
-    return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
-}
-
-static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
-                                                              OcspEntry** entry)
-{
-    WOLFSSL_ENTER("GetOcspEntry");
-
-    *entry = NULL;
-
-    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
-        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
-        return BAD_MUTEX_E;
-    }
-
-    for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
-        if (XMEMCMP((*entry)->issuerHash,    request->issuerHash,
-                                                         OCSP_DIGEST_SIZE) == 0
-        &&  XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
-                                                         OCSP_DIGEST_SIZE) == 0)
-            break;
-
-    if (*entry == NULL) {
-        *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
-                                       ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
-        if (*entry) {
-            InitOcspEntry(*entry, request);
-            (*entry)->next = ocsp->ocspList;
-            ocsp->ocspList = *entry;
-        }
-    }
-
-    wc_UnLockMutex(&ocsp->ocspLock);
-
-    return *entry ? 0 : MEMORY_ERROR;
-}
-
-
-static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
-                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
-{
-    int ret = OCSP_INVALID_STATUS;
-
-    WOLFSSL_ENTER("GetOcspStatus");
-
-    *status = NULL;
-
-    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
-        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
-        return BAD_MUTEX_E;
-    }
-
-    for (*status = entry->status; *status; *status = (*status)->next)
-        if ((*status)->serialSz == request->serialSz
-        &&  !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
-            break;
-
-    if (responseBuffer && *status && !(*status)->rawOcspResponse) {
-        /* force fetching again */
-        ret = OCSP_INVALID_STATUS;
-    }
-    else if (*status) {
-#ifndef NO_ASN_TIME
-        if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
-        &&  ((*status)->nextDate[0] != 0)
-        &&  ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
-#endif
-        {
-            ret = xstat2err((*status)->status);
-
-            if (responseBuffer) {
-                responseBuffer->buffer = (byte*)XMALLOC(
-                   (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-                if (responseBuffer->buffer) {
-                    responseBuffer->length = (*status)->rawOcspResponseSz;
-                    XMEMCPY(responseBuffer->buffer,
-                            (*status)->rawOcspResponse,
-                            (*status)->rawOcspResponseSz);
-                }
-            }
-        }
-    }
-
-    wc_UnLockMutex(&ocsp->ocspLock);
-
-    return ret;
-}
-
-/* Check that the response for validity. Store result in status.
- *
- * ocsp           Context object for OCSP status.
- * response       OCSP response message data.
- * responseSz     Length of OCSP response message data.
- * reponseBuffer  Buffer object to return the response with.
- * status         The certificate status object.
- * entry          The OCSP entry for this certificate.
- * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
- */
-static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz,
-                         buffer* responseBuffer, CertStatus* status,
-                         OcspEntry* entry, OcspRequest* ocspRequest)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    CertStatus*   newStatus;
-    OcspResponse* ocspResponse;
-#else
-    CertStatus    newStatus[1];
-    OcspResponse  ocspResponse[1];
-#endif
-    int           ret;
-    int           validated      = 0;    /* ocsp validation flag */
-
-#ifdef WOLFSSL_SMALL_STACK
-    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    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);
-
-        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
-        return MEMORY_E;
-    }
-#endif
-    XMEMSET(newStatus, 0, sizeof(CertStatus));
-
-    InitOcspResponse(ocspResponse, newStatus, response, responseSz);
-    ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
-    if (ret != 0) {
-        WOLFSSL_MSG("OcspResponseDecode failed");
-        goto end;
-    }
-
-    if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
-        WOLFSSL_MSG("OcspResponse status bad");
-        goto end;
-    }
-    if (ocspRequest != NULL) {
-        ret = CompareOcspReqResp(ocspRequest, ocspResponse);
-        if (ret != 0) {
-            goto end;
-        }
-    }
-
-    if (responseBuffer) {
-        responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
-                                                DYNAMIC_TYPE_TMP_BUFFER);
-
-        if (responseBuffer->buffer) {
-            responseBuffer->length = responseSz;
-            XMEMCPY(responseBuffer->buffer, response, responseSz);
-        }
-    }
-
-    ret = xstat2err(ocspResponse->status->status);
-    if (ret == 0) {
-        validated = 1;
-    }
-
-    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
-        ret = BAD_MUTEX_E;
-        goto end;
-    }
-
-    if (status != NULL) {
-        if (status->rawOcspResponse) {
-            XFREE(status->rawOcspResponse, ocsp->cm->heap,
-                  DYNAMIC_TYPE_OCSP_STATUS);
-        }
-
-        /* Replace existing certificate entry with updated */
-        XMEMCPY(status, newStatus, sizeof(CertStatus));
-    }
-    else {
-        /* Save new certificate entry */
-        status = (CertStatus*)XMALLOC(sizeof(CertStatus),
-                                      ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
-        if (status != NULL) {
-            XMEMCPY(status, newStatus, sizeof(CertStatus));
-            status->next  = entry->status;
-            entry->status = status;
-            entry->totalStatus++;
-        }
-    }
-
-    if (status && responseBuffer && responseBuffer->buffer) {
-        status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
-                                                 ocsp->cm->heap,
-                                                 DYNAMIC_TYPE_OCSP_STATUS);
-
-        if (status->rawOcspResponse) {
-            status->rawOcspResponseSz = responseBuffer->length;
-            XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
-                    responseBuffer->length);
-        }
-    }
-
-    wc_UnLockMutex(&ocsp->ocspLock);
-
-end:
-    if (ret == 0 && validated == 1) {
-        WOLFSSL_MSG("New OcspResponse validated");
-    } else if (ret != OCSP_CERT_REVOKED) {
-        ret = OCSP_LOOKUP_FAIL;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-    return ret;
-}
-
-/* 0 on success */
-int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
-                                                      buffer* responseBuffer)
-{
-    OcspEntry*  entry          = NULL;
-    CertStatus* status         = NULL;
-    byte*       request        = NULL;
-    int         requestSz      = 2048;
-    int         responseSz     = 0;
-    byte*       response       = NULL;
-    const char* url            = NULL;
-    int         urlSz          = 0;
-    int         ret            = -1;
-    WOLFSSL*    ssl;
-    void*       ioCtx;
-
-    WOLFSSL_ENTER("CheckOcspRequest");
-
-    if (ocsp == NULL || ocspRequest == NULL)
-        return BAD_FUNC_ARG;
-
-    if (responseBuffer) {
-        responseBuffer->buffer = NULL;
-        responseBuffer->length = 0;
-    }
-
-    ret = GetOcspEntry(ocsp, ocspRequest, &entry);
-    if (ret != 0)
-        return ret;
-
-    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
-    if (ret != OCSP_INVALID_STATUS)
-        return ret;
-
-    /* get SSL and IOCtx */
-    ssl = (WOLFSSL*)ocspRequest->ssl;
-    ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
-                                        ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    if (ocsp->statusCb != NULL && ssl != NULL) {
-        ret = ocsp->statusCb(ssl, ioCtx);
-        if (ret == 0) {
-            ret = wolfSSL_get_ocsp_response(ssl, &response);
-            ret = CheckResponse(ocsp, response, ret, responseBuffer, status,
-                                entry, NULL);
-            if (response != NULL)
-                XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
-            return ret;
-        }
-        return OCSP_LOOKUP_FAIL;
-    }
-#endif
-
-    if (ocsp->cm->ocspUseOverrideURL) {
-        url = ocsp->cm->ocspOverrideURL;
-        if (url != NULL && url[0] != '\0')
-            urlSz = (int)XSTRLEN(url);
-        else
-            return OCSP_NEED_URL;
-    }
-    else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
-        url = (const char *)ocspRequest->url;
-        urlSz = ocspRequest->urlSz;
-    }
-    else {
-        /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
-        return 0;
-    }
-
-    request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
-    if (request == NULL) {
-        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
-        return MEMORY_ERROR;
-    }
-
-    requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
-    if (requestSz > 0 && ocsp->cm->ocspIOCb) {
-        responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
-                                        request, requestSz, &response);
-    }
-    if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
-        ret = OCSP_WANT_READ;
-    }
-
-    XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
-
-    if (responseSz >= 0 && response) {
-        ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status,
-                            entry, ocspRequest);
-    }
-
-    if (response != NULL && ocsp->cm->ocspRespFreeCb)
-        ocsp->cm->ocspRespFreeCb(ioCtx, response);
-
-    WOLFSSL_LEAVE("CheckOcspRequest", ret);
-    return ret;
-}
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-
-int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
-    WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
-    WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
-    WOLFSSL_ASN1_TIME** nextupd)
-{
-    if (bs == NULL || id == NULL)
-        return WOLFSSL_FAILURE;
-
-    /* Only supporting one certificate status in asn.c. */
-    if (CompareOcspReqResp(id, bs) != 0)
-        return WOLFSSL_FAILURE;
-
-    if (status != NULL)
-        *status = bs->status->status;
-    if (thisupd != NULL)
-        *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn;
-    if (nextupd != NULL)
-        *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn;
-
-    /* TODO: Not needed for Nginx. */
-    if (reason != NULL)
-        *reason = 0;
-    if (revtime != NULL)
-        *revtime = NULL;
-
-    return WOLFSSL_SUCCESS;
-}
-
-const char *wolfSSL_OCSP_cert_status_str(long s)
-{
-    switch (s) {
-        case CERT_GOOD:
-            return "good";
-        case CERT_REVOKED:
-            return "revoked";
-        case CERT_UNKNOWN:
-            return "unknown";
-        default:
-            return "(UNKNOWN)";
-    }
-}
-
-int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
-    WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
-{
-    (void)thisupd;
-    (void)nextupd;
-    (void)sec;
-    (void)maxsec;
-    /* Dates validated in DecodeSingleResponse. */
-    return WOLFSSL_SUCCESS;
-}
-
-void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
-{
-    FreeOcspRequest(certId);
-    XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
-WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
-    const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
-    const WOLFSSL_X509 *issuer)
-{
-    WOLFSSL_OCSP_CERTID* certId;
-    DecodedCert cert;
-    WOLFSSL_CERT_MANAGER* cm;
-    int ret;
-    DerBuffer* derCert = NULL;
-
-    (void)dgst;
-
-    cm = wolfSSL_CertManagerNew();
-    if (cm == NULL)
-        return NULL;
-
-    ret = AllocDer(&derCert, issuer->derCert->length,
-        issuer->derCert->type, NULL);
-    if (ret == 0) {
-        /* AddCA() frees the buffer. */
-        XMEMCPY(derCert->buffer, issuer->derCert->buffer,
-                issuer->derCert->length);
-        AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
-    }
-
-    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) {
-            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);
-    }
-
-    wolfSSL_CertManagerFree(cm);
-
-    return certId;
-}
-
-void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
-{
-    wolfSSL_OCSP_RESPONSE_free(basicResponse);
-}
-
-/* Signature verified in DecodeBasicOcspResponse.
- * But no store available to verify certificate. */
-int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
-    WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
-{
-    DecodedCert cert;
-    int         ret = WOLFSSL_SUCCESS;
-
-    (void)certs;
-
-    if (flags & OCSP_NOVERIFY)
-        return WOLFSSL_SUCCESS;
-
-#ifdef OPENSSL_EXTRA
-    if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
-        return WOLFSSL_FAILURE;
-#endif
-
-    InitDecodedCert(&cert, bs->cert, bs->certSz, NULL);
-    if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0)
-        ret = WOLFSSL_FAILURE;
-    FreeDecodedCert(&cert);
-
-    return ret;
-}
-
-void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
-{
-    if (response->status != NULL)
-        XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (response->source != NULL)
-        XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
-OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
-    OcspResponse** response)
-{
-    byte*         data;
-    byte*         p;
-    int           len;
-    int           dataAlloced = 0;
-    OcspResponse* ret = NULL;
-
-    if (bio == NULL)
-        return NULL;
-
-    if (bio->type == WOLFSSL_BIO_MEMORY) {
-        len = wolfSSL_BIO_get_mem_data(bio, &data);
-        if (len <= 0 || data == NULL) {
-            return NULL;
-        }
-    }
-#ifndef NO_FILESYSTEM
-    else if (bio->type == WOLFSSL_BIO_FILE) {
-        long i;
-        long l;
-
-        i = XFTELL(bio->file);
-        if (i < 0)
-            return NULL;
-        XFSEEK(bio->file, 0, SEEK_END);
-        l = XFTELL(bio->file);
-        if (l < 0)
-            return NULL;
-        if (XFSEEK(bio->file, i, SEEK_SET) != 0)
-            return NULL;
-
-        /* check calculated length */
-        if (l - i <= 0)
-            return NULL;
-
-        data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER);
-        if (data == NULL)
-            return NULL;
-        dataAlloced = 1;
-
-        len = wolfSSL_BIO_read(bio, (char *)data, (int)l);
-    }
-#endif
-    else
-        return NULL;
-
-    if (len > 0) {
-        p = data;
-        ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len);
-    }
-
-    if (dataAlloced)
-        XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return ret;
-}
-
-OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
-    const unsigned char** data, int len)
-{
-    OcspResponse *resp = NULL;
-    word32 idx = 0;
-    int length = 0;
-
-    if (data == NULL)
-        return NULL;
-
-    if (response != NULL)
-        resp = *response;
-    if (resp == NULL) {
-        resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
-                                      DYNAMIC_TYPE_OPENSSL);
-        if (resp == NULL)
-            return NULL;
-        XMEMSET(resp, 0, sizeof(OcspResponse));
-    }
-
-    resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (resp->source == NULL) {
-        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
-        return NULL;
-    }
-    resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (resp->status == NULL) {
-        XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
-        return NULL;
-    }
-
-    XMEMCPY(resp->source, *data, len);
-    resp->maxIdx = len;
-
-    if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
-        wolfSSL_OCSP_RESPONSE_free(resp);
-        return NULL;
-    }
-
-    if (GetSequence(*data, &idx, &length, len) >= 0)
-        (*data) += idx + length;
-
-    return resp;
-}
-
-int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
-    unsigned char** data)
-{
-    if (data == NULL)
-        return response->maxIdx;
-
-    XMEMCPY(*data, response->source, response->maxIdx);
-    return response->maxIdx;
-}
-
-int wolfSSL_OCSP_response_status(OcspResponse *response)
-{
-    return response->responseStatus;
-}
-
-const char *wolfSSL_OCSP_response_status_str(long s)
-{
-    switch (s) {
-        case OCSP_SUCCESSFUL:
-            return "successful";
-        case OCSP_MALFORMED_REQUEST:
-            return "malformedrequest";
-        case OCSP_INTERNAL_ERROR:
-            return "internalerror";
-        case OCSP_TRY_LATER:
-            return "trylater";
-        case OCSP_SIG_REQUIRED:
-            return "sigrequired";
-        case OCSP_UNAUTHROIZED:
-            return "unauthorized";
-        default:
-            return "(UNKNOWN)";
-    }
-}
-
-WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
-{
-    WOLFSSL_OCSP_BASICRESP* bs;
-
-    bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
-                                          DYNAMIC_TYPE_OPENSSL);
-    if (bs == NULL)
-        return NULL;
-
-    XMEMCPY(bs, response, sizeof(OcspResponse));
-    bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                      DYNAMIC_TYPE_TMP_BUFFER);
-    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->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        wolfSSL_OCSP_RESPONSE_free(bs);
-        bs = NULL;
-    }
-    else {
-        XMEMCPY(bs->status, response->status, sizeof(CertStatus));
-        XMEMCPY(bs->source, response->source, response->maxIdx);
-    }
-    return bs;
-}
-
-OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
-{
-    OcspRequest* request;
-
-    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
-                                    DYNAMIC_TYPE_OPENSSL);
-    if (request != NULL)
-        XMEMSET(request, 0, sizeof(OcspRequest));
-
-    return request;
-}
-
-void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
-{
-    FreeOcspRequest(request);
-    XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
-int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
-{
-    word32 size;
-
-    size = EncodeOcspRequest(request, NULL, 0);
-    if (size <= 0 || data == NULL)
-        return size;
-
-    return EncodeOcspRequest(request, *data, size);
-}
-
-WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
-    WOLFSSL_OCSP_CERTID *cid)
-{
-    if (req == NULL || cid == NULL)
-        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);
-
-    return req;
-}
-
-#endif
-
-#else /* HAVE_OCSP */
-
-
-#ifdef _MSC_VER
-    /* 4206 warning for blank file */
-    #pragma warning(disable: 4206)
-#endif
-
-
-#endif /* HAVE_OCSP */
-#endif /* WOLFCRYPT_ONLY */
-
+/* ocsp.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+  /* Name change compatibility layer no longer needs to be included here */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef HAVE_OCSP
+
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/ocsp.h>
+#include <wolfssl/internal.h>
+
+#ifdef NO_INLINE
+    #include <wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("InitOCSP");
+
+    ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
+
+    if (wc_InitMutex(&ocsp->ocspLock) != 0)
+        return BAD_MUTEX_E;
+
+    ocsp->cm = cm;
+
+    return 0;
+}
+
+
+static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
+{
+    WOLFSSL_ENTER("InitOcspEntry");
+
+    ForceZero(entry, sizeof(OcspEntry));
+
+    XMEMCPY(entry->issuerHash,    request->issuerHash,    OCSP_DIGEST_SIZE);
+    XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
+
+    return 0;
+}
+
+
+static void FreeOcspEntry(OcspEntry* entry, void* heap)
+{
+    CertStatus *status, *next;
+
+    WOLFSSL_ENTER("FreeOcspEntry");
+
+    for (status = entry->status; status; status = next) {
+        next = status->next;
+
+        if (status->rawOcspResponse)
+            XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
+
+        XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
+    }
+
+    (void)heap;
+}
+
+
+void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
+{
+    OcspEntry *entry, *next;
+
+    WOLFSSL_ENTER("FreeOCSP");
+
+    for (entry = ocsp->ocspList; entry; entry = next) {
+        next = entry->next;
+        FreeOcspEntry(entry, ocsp->cm->heap);
+        XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+    }
+
+    wc_FreeMutex(&ocsp->ocspLock);
+
+    if (dynamic)
+        XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+
+}
+
+
+static int xstat2err(int st)
+{
+    switch (st) {
+        case CERT_GOOD:
+            return 0;
+        case CERT_REVOKED:
+            return OCSP_CERT_REVOKED;
+        default:
+            return OCSP_CERT_UNKNOWN;
+    }
+}
+
+int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
+{
+    int ret = OCSP_LOOKUP_FAIL;
+
+#ifdef WOLFSSL_SMALL_STACK
+    OcspRequest* ocspRequest;
+#else
+    OcspRequest ocspRequest[1];
+#endif
+
+    WOLFSSL_ENTER("CheckCertOCSP");
+
+
+#ifdef WOLFSSL_SMALL_STACK
+    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (ocspRequest == NULL) {
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        return MEMORY_E;
+    }
+#endif
+
+    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
+                                                         ocsp->cm->heap) == 0) {
+        ocspRequest->ssl = ssl;
+        ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
+
+        FreeOcspRequest(ocspRequest);
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    WOLFSSL_LEAVE("CheckCertOCSP", ret);
+    return ret;
+}
+int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
+{
+    return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
+}
+
+static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
+                                                              OcspEntry** entry)
+{
+    WOLFSSL_ENTER("GetOcspEntry");
+
+    *entry = NULL;
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
+        return BAD_MUTEX_E;
+    }
+
+    for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
+        if (XMEMCMP((*entry)->issuerHash,    request->issuerHash,
+                                                         OCSP_DIGEST_SIZE) == 0
+        &&  XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
+                                                         OCSP_DIGEST_SIZE) == 0)
+            break;
+
+    if (*entry == NULL) {
+        *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
+                                       ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+        if (*entry) {
+            InitOcspEntry(*entry, request);
+            (*entry)->next = ocsp->ocspList;
+            ocsp->ocspList = *entry;
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+    return *entry ? 0 : MEMORY_ERROR;
+}
+
+
+static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
+                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
+{
+    int ret = OCSP_INVALID_STATUS;
+
+    WOLFSSL_ENTER("GetOcspStatus");
+
+    *status = NULL;
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
+        return BAD_MUTEX_E;
+    }
+
+    for (*status = entry->status; *status; *status = (*status)->next)
+        if ((*status)->serialSz == request->serialSz
+        &&  !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
+            break;
+
+    if (responseBuffer && *status && !(*status)->rawOcspResponse) {
+        /* force fetching again */
+        ret = OCSP_INVALID_STATUS;
+    }
+    else if (*status) {
+#ifndef NO_ASN_TIME
+        if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
+        &&  ((*status)->nextDate[0] != 0)
+        &&  ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
+#endif
+        {
+            ret = xstat2err((*status)->status);
+
+            if (responseBuffer) {
+                responseBuffer->buffer = (byte*)XMALLOC(
+                   (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+                if (responseBuffer->buffer) {
+                    responseBuffer->length = (*status)->rawOcspResponseSz;
+                    XMEMCPY(responseBuffer->buffer,
+                            (*status)->rawOcspResponse,
+                            (*status)->rawOcspResponseSz);
+                }
+            }
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+    return ret;
+}
+
+/* Check that the response for validity. Store result in status.
+ *
+ * ocsp           Context object for OCSP status.
+ * response       OCSP response message data.
+ * responseSz     Length of OCSP response message data.
+ * reponseBuffer  Buffer object to return the response with.
+ * status         The certificate status object.
+ * entry          The OCSP entry for this certificate.
+ * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
+ */
+static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz,
+                         buffer* responseBuffer, CertStatus* status,
+                         OcspEntry* entry, OcspRequest* ocspRequest)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    CertStatus*   newStatus;
+    OcspResponse* ocspResponse;
+#else
+    CertStatus    newStatus[1];
+    OcspResponse  ocspResponse[1];
+#endif
+    int           ret;
+    int           validated      = 0;    /* ocsp validation flag */
+
+#ifdef WOLFSSL_SMALL_STACK
+    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    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);
+
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        return MEMORY_E;
+    }
+#endif
+    XMEMSET(newStatus, 0, sizeof(CertStatus));
+
+    InitOcspResponse(ocspResponse, newStatus, response, responseSz);
+    ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
+    if (ret != 0) {
+        WOLFSSL_MSG("OcspResponseDecode failed");
+        goto end;
+    }
+
+    if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
+        WOLFSSL_MSG("OcspResponse status bad");
+        goto end;
+    }
+    if (ocspRequest != NULL) {
+        ret = CompareOcspReqResp(ocspRequest, ocspResponse);
+        if (ret != 0) {
+            goto end;
+        }
+    }
+
+    if (responseBuffer) {
+        responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+
+        if (responseBuffer->buffer) {
+            responseBuffer->length = responseSz;
+            XMEMCPY(responseBuffer->buffer, response, responseSz);
+        }
+    }
+
+    ret = xstat2err(ocspResponse->status->status);
+    if (ret == 0) {
+        validated = 1;
+    }
+
+    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
+        ret = BAD_MUTEX_E;
+        goto end;
+    }
+
+    if (status != NULL) {
+        if (status->rawOcspResponse) {
+            XFREE(status->rawOcspResponse, ocsp->cm->heap,
+                  DYNAMIC_TYPE_OCSP_STATUS);
+        }
+
+        /* Replace existing certificate entry with updated */
+        XMEMCPY(status, newStatus, sizeof(CertStatus));
+    }
+    else {
+        /* Save new certificate entry */
+        status = (CertStatus*)XMALLOC(sizeof(CertStatus),
+                                      ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
+        if (status != NULL) {
+            XMEMCPY(status, newStatus, sizeof(CertStatus));
+            status->next  = entry->status;
+            entry->status = status;
+            entry->totalStatus++;
+        }
+    }
+
+    if (status && responseBuffer && responseBuffer->buffer) {
+        status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
+                                                 ocsp->cm->heap,
+                                                 DYNAMIC_TYPE_OCSP_STATUS);
+
+        if (status->rawOcspResponse) {
+            status->rawOcspResponseSz = responseBuffer->length;
+            XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
+                    responseBuffer->length);
+        }
+    }
+
+    wc_UnLockMutex(&ocsp->ocspLock);
+
+end:
+    if (ret == 0 && validated == 1) {
+        WOLFSSL_MSG("New OcspResponse validated");
+    } else if (ret != OCSP_CERT_REVOKED) {
+        ret = OCSP_LOOKUP_FAIL;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+    return ret;
+}
+
+/* 0 on success */
+int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
+                                                      buffer* responseBuffer)
+{
+    OcspEntry*  entry          = NULL;
+    CertStatus* status         = NULL;
+    byte*       request        = NULL;
+    int         requestSz      = 2048;
+    int         responseSz     = 0;
+    byte*       response       = NULL;
+    const char* url            = NULL;
+    int         urlSz          = 0;
+    int         ret            = -1;
+    WOLFSSL*    ssl;
+    void*       ioCtx;
+
+    WOLFSSL_ENTER("CheckOcspRequest");
+
+    if (ocsp == NULL || ocspRequest == NULL)
+        return BAD_FUNC_ARG;
+
+    if (responseBuffer) {
+        responseBuffer->buffer = NULL;
+        responseBuffer->length = 0;
+    }
+
+    ret = GetOcspEntry(ocsp, ocspRequest, &entry);
+    if (ret != 0)
+        return ret;
+
+    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
+    if (ret != OCSP_INVALID_STATUS)
+        return ret;
+
+    /* get SSL and IOCtx */
+    ssl = (WOLFSSL*)ocspRequest->ssl;
+    ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
+                                        ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    if (ocsp->statusCb != NULL && ssl != NULL) {
+        ret = ocsp->statusCb(ssl, ioCtx);
+        if (ret == 0) {
+            ret = wolfSSL_get_ocsp_response(ssl, &response);
+            ret = CheckResponse(ocsp, response, ret, responseBuffer, status,
+                                entry, NULL);
+            if (response != NULL)
+                XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
+            return ret;
+        }
+        return OCSP_LOOKUP_FAIL;
+    }
+#endif
 
+    if (ocsp->cm->ocspUseOverrideURL) {
+        url = ocsp->cm->ocspOverrideURL;
+        if (url != NULL && url[0] != '\0')
+            urlSz = (int)XSTRLEN(url);
+        else
+            return OCSP_NEED_URL;
+    }
+    else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
+        url = (const char *)ocspRequest->url;
+        urlSz = ocspRequest->urlSz;
+    }
+    else {
+        /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
+        return 0;
+    }
+
+    request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+    if (request == NULL) {
+        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+        return MEMORY_ERROR;
+    }
+
+    requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
+    if (requestSz > 0 && ocsp->cm->ocspIOCb) {
+        responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
+                                        request, requestSz, &response);
+    }
+    if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
+        ret = OCSP_WANT_READ;
+    }
+
+    XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+
+    if (responseSz >= 0 && response) {
+        ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status,
+                            entry, ocspRequest);
+    }
+
+    if (response != NULL && ocsp->cm->ocspRespFreeCb)
+        ocsp->cm->ocspRespFreeCb(ioCtx, response);
+
+    WOLFSSL_LEAVE("CheckOcspRequest", ret);
+    return ret;
+}
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
+    WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
+    WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
+    WOLFSSL_ASN1_TIME** nextupd)
+{
+    if (bs == NULL || id == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Only supporting one certificate status in asn.c. */
+    if (CompareOcspReqResp(id, bs) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (status != NULL)
+        *status = bs->status->status;
+    if (thisupd != NULL)
+        *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn;
+    if (nextupd != NULL)
+        *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn;
+
+    /* TODO: Not needed for Nginx. */
+    if (reason != NULL)
+        *reason = 0;
+    if (revtime != NULL)
+        *revtime = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+const char *wolfSSL_OCSP_cert_status_str(long s)
+{
+    switch (s) {
+        case CERT_GOOD:
+            return "good";
+        case CERT_REVOKED:
+            return "revoked";
+        case CERT_UNKNOWN:
+            return "unknown";
+        default:
+            return "(UNKNOWN)";
+    }
+}
+
+int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
+    WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
+{
+    (void)thisupd;
+    (void)nextupd;
+    (void)sec;
+    (void)maxsec;
+    /* Dates validated in DecodeSingleResponse. */
+    return WOLFSSL_SUCCESS;
+}
+
+void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
+{
+    FreeOcspRequest(certId);
+    XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
+    const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
+    const WOLFSSL_X509 *issuer)
+{
+    WOLFSSL_OCSP_CERTID* certId;
+    DecodedCert cert;
+    WOLFSSL_CERT_MANAGER* cm;
+    int ret;
+    DerBuffer* derCert = NULL;
+
+    (void)dgst;
+
+    cm = wolfSSL_CertManagerNew();
+    if (cm == NULL)
+        return NULL;
+
+    ret = AllocDer(&derCert, issuer->derCert->length,
+        issuer->derCert->type, NULL);
+    if (ret == 0) {
+        /* AddCA() frees the buffer. */
+        XMEMCPY(derCert->buffer, issuer->derCert->buffer,
+                issuer->derCert->length);
+        AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
+    }
+
+    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) {
+            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);
+    }
+
+    wolfSSL_CertManagerFree(cm);
+
+    return certId;
+}
+
+void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
+{
+    wolfSSL_OCSP_RESPONSE_free(basicResponse);
+}
+
+/* Signature verified in DecodeBasicOcspResponse.
+ * But no store available to verify certificate. */
+int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
+    WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
+{
+    DecodedCert cert;
+    int         ret = WOLFSSL_SUCCESS;
+
+    (void)certs;
+
+    if (flags & OCSP_NOVERIFY)
+        return WOLFSSL_SUCCESS;
+
+#ifdef OPENSSL_EXTRA
+    if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
+        return WOLFSSL_FAILURE;
+#endif
+
+    InitDecodedCert(&cert, bs->cert, bs->certSz, NULL);
+    if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0)
+        ret = WOLFSSL_FAILURE;
+    FreeDecodedCert(&cert);
+
+    return ret;
+}
+
+void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
+{
+    if (response->status != NULL)
+        XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (response->source != NULL)
+        XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
+    OcspResponse** response)
+{
+    byte*         data;
+    byte*         p;
+    int           len;
+    int           dataAlloced = 0;
+    OcspResponse* ret = NULL;
+
+    if (bio == NULL)
+        return NULL;
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        len = wolfSSL_BIO_get_mem_data(bio, &data);
+        if (len <= 0 || data == NULL) {
+            return NULL;
+        }
+    }
+#ifndef NO_FILESYSTEM
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        long i;
+        long l;
+
+        i = XFTELL(bio->file);
+        if (i < 0)
+            return NULL;
+        XFSEEK(bio->file, 0, SEEK_END);
+        l = XFTELL(bio->file);
+        if (l < 0)
+            return NULL;
+        if (XFSEEK(bio->file, i, SEEK_SET) != 0)
+            return NULL;
+
+        /* check calculated length */
+        if (l - i <= 0)
+            return NULL;
+
+        data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER);
+        if (data == NULL)
+            return NULL;
+        dataAlloced = 1;
+
+        len = wolfSSL_BIO_read(bio, (char *)data, (int)l);
+    }
+#endif
+    else
+        return NULL;
+
+    if (len > 0) {
+        p = data;
+        ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len);
+    }
+
+    if (dataAlloced)
+        XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return ret;
+}
+
+OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
+    const unsigned char** data, int len)
+{
+    OcspResponse *resp = NULL;
+    word32 idx = 0;
+    int length = 0;
+
+    if (data == NULL)
+        return NULL;
+
+    if (response != NULL)
+        resp = *response;
+    if (resp == NULL) {
+        resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
+                                      DYNAMIC_TYPE_OPENSSL);
+        if (resp == NULL)
+            return NULL;
+        XMEMSET(resp, 0, sizeof(OcspResponse));
+    }
+
+    resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (resp->source == NULL) {
+        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+    resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (resp->status == NULL) {
+        XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+
+    XMEMCPY(resp->source, *data, len);
+    resp->maxIdx = len;
+
+    if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
+        wolfSSL_OCSP_RESPONSE_free(resp);
+        return NULL;
+    }
+
+    if (GetSequence(*data, &idx, &length, len) >= 0)
+        (*data) += idx + length;
+
+    return resp;
+}
+
+int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
+    unsigned char** data)
+{
+    if (data == NULL)
+        return response->maxIdx;
+
+    XMEMCPY(*data, response->source, response->maxIdx);
+    return response->maxIdx;
+}
+
+int wolfSSL_OCSP_response_status(OcspResponse *response)
+{
+    return response->responseStatus;
+}
+
+const char *wolfSSL_OCSP_response_status_str(long s)
+{
+    switch (s) {
+        case OCSP_SUCCESSFUL:
+            return "successful";
+        case OCSP_MALFORMED_REQUEST:
+            return "malformedrequest";
+        case OCSP_INTERNAL_ERROR:
+            return "internalerror";
+        case OCSP_TRY_LATER:
+            return "trylater";
+        case OCSP_SIG_REQUIRED:
+            return "sigrequired";
+        case OCSP_UNAUTHROIZED:
+            return "unauthorized";
+        default:
+            return "(UNKNOWN)";
+    }
+}
+
+WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
+{
+    WOLFSSL_OCSP_BASICRESP* bs;
+
+    bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
+                                          DYNAMIC_TYPE_OPENSSL);
+    if (bs == NULL)
+        return NULL;
+
+    XMEMCPY(bs, response, sizeof(OcspResponse));
+    bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                      DYNAMIC_TYPE_TMP_BUFFER);
+    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->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        wolfSSL_OCSP_RESPONSE_free(bs);
+        bs = NULL;
+    }
+    else {
+        XMEMCPY(bs->status, response->status, sizeof(CertStatus));
+        XMEMCPY(bs->source, response->source, response->maxIdx);
+    }
+    return bs;
+}
+
+OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
+{
+    OcspRequest* request;
+
+    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
+                                    DYNAMIC_TYPE_OPENSSL);
+    if (request != NULL)
+        XMEMSET(request, 0, sizeof(OcspRequest));
+
+    return request;
+}
+
+void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
+{
+    FreeOcspRequest(request);
+    XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
+{
+    word32 size;
+
+    size = EncodeOcspRequest(request, NULL, 0);
+    if (size <= 0 || data == NULL)
+        return size;
+
+    return EncodeOcspRequest(request, *data, size);
+}
+
+WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
+    WOLFSSL_OCSP_CERTID *cid)
+{
+    if (req == NULL || cid == NULL)
+        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);
+
+    return req;
+}
+
+#endif
+
+#else /* HAVE_OCSP */
+
+
+#ifdef _MSC_VER
+    /* 4206 warning for blank file */
+    #pragma warning(disable: 4206)
+#endif
+
+
+#endif /* HAVE_OCSP */
+#endif /* WOLFCRYPT_ONLY */
+
+
--- a/src/sniffer.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/sniffer.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,3612 +1,3612 @@
-/* sniffer.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-#ifdef WOLFSSL_SNIFFER
-
-#include <assert.h>
-#include <time.h>
-
-#ifndef _WIN32
-  #include <arpa/inet.h>
-#endif
-
-#ifdef _WIN32
-    #define SNPRINTF _snprintf
-#else
-    #define SNPRINTF snprintf
-#endif
-
-#include <wolfssl/openssl/ssl.h>
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/sniffer.h>
-#include <wolfssl/sniffer_error.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifndef WOLFSSL_SNIFFER_TIMEOUT
-    #define WOLFSSL_SNIFFER_TIMEOUT 900
-    /* Cache unclosed Sessions for 15 minutes since last used */
-#endif
-
-/* Misc constants */
-enum {
-    MAX_SERVER_ADDRESS = 128, /* maximum server address length */
-    MAX_SERVER_NAME    = 128, /* maximum server name length */
-    MAX_ERROR_LEN      = 80,  /* maximum error length */
-    ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
-    LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
-    TCP_PROTO          = 6,   /* TCP_PROTOCOL */
-    IP_HDR_SZ          = 20,  /* IP header length, min */
-    TCP_HDR_SZ         = 20,  /* TCP header length, min */
-    IPV4               = 4,   /* IP version 4 */
-    TCP_PROTOCOL       = 6,   /* TCP Protocol id */
-    TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
-    HASH_SIZE          = 499, /* Session Hash Table Rows */
-    PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
-    FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
-    TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
-    EXT_TYPE_SZ        = 2,   /* Extension length */
-    MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
-                         MTU_EXTRA,  /* Max input sz of reassembly */
-    EXT_MASTER_SECRET  = 0x17, /* Extended Master Secret Extension ID */
-    TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
-};
-
-
-#ifdef _WIN32
-
-static HMODULE dllModule;  /* for error string resources */
-
-BOOL APIENTRY DllMain( HMODULE hModule,
-                       DWORD  ul_reason_for_call,
-                       LPVOID lpReserved
-                     )
-{
-	static int didInit = 0;
-
-    switch (ul_reason_for_call)
-    {
-    case DLL_PROCESS_ATTACH:
-		if (didInit == 0) {
-            dllModule = hModule;
-			ssl_InitSniffer();
-			didInit = 1;
-		}
-        break;
-    case DLL_THREAD_ATTACH:
-        break;
-    case DLL_THREAD_DETACH:
-        break;
-    case DLL_PROCESS_DETACH:
-		if (didInit) {
-			ssl_FreeSniffer();
-			didInit = 0;
-		}
-        break;
-    }
-    return TRUE;
-}
-
-#endif /* _WIN32 */
-
-
-static int TraceOn = 0;         /* Trace is off by default */
-static FILE* TraceFile = 0;
-
-
-/* windows uses .rc table for this */
-#ifndef _WIN32
-
-static const char* const msgTable[] =
-{
-    /* 1 */
-    "Out of Memory",
-    "New SSL Sniffer Server Registered",
-    "Checking IP Header",
-    "SSL Sniffer Server Not Registered",
-    "Checking TCP Header",
-
-    /* 6 */
-    "SSL Sniffer Server Port Not Registered",
-    "RSA Private Decrypt Error",
-    "RSA Private Decode Error",
-    "Set Cipher Spec Error",
-    "Server Hello Input Malformed",
-
-    /* 11 */
-    "Couldn't Resume Session Error",
-    "Server Did Resumption",
-    "Client Hello Input Malformed",
-    "Client Trying to Resume",
-    "Handshake Input Malformed",
-
-    /* 16 */
-    "Got Hello Verify msg",
-    "Got Server Hello msg",
-    "Got Cert Request msg",
-    "Got Server Key Exchange msg",
-    "Got Cert msg",
-
-    /* 21 */
-    "Got Server Hello Done msg",
-    "Got Finished msg",
-    "Got Client Hello msg",
-    "Got Client Key Exchange msg",
-    "Got Cert Verify msg",
-
-    /* 26 */
-    "Got Unknown Handshake msg",
-    "New SSL Sniffer Session created",
-    "Couldn't create new SSL",
-    "Got a Packet to decode",
-    "No data present",
-
-    /* 31 */
-    "Session Not Found",
-    "Got an Old Client Hello msg",
-    "Old Client Hello Input Malformed",
-    "Old Client Hello OK",
-    "Bad Old Client Hello",
-
-    /* 36 */
-    "Bad Record Header",
-    "Record Header Input Malformed",
-    "Got a HandShake msg",
-    "Bad HandShake msg",
-    "Got a Change Cipher Spec msg",
-
-    /* 41 */
-    "Got Application Data msg",
-    "Bad Application Data",
-    "Got an Alert msg",
-    "Another msg to Process",
-    "Removing Session From Table",
-
-    /* 46 */
-    "Bad Key File",
-    "Wrong IP Version",
-    "Wrong Protocol type",
-    "Packet Short for header processing",
-    "Got Unknown Record Type",
-
-    /* 51 */
-    "Can't Open Trace File",
-    "Session in Fatal Error State",
-    "Partial SSL record received",
-    "Buffer Error, malformed input",
-    "Added to Partial Input",
-
-    /* 56 */
-    "Received a Duplicate Packet",
-    "Received an Out of Order Packet",
-    "Received an Overlap Duplicate Packet",
-    "Received an Overlap Reassembly Begin Duplicate Packet",
-    "Received an Overlap Reassembly End Duplicate Packet",
-
-    /* 61 */
-    "Missed the Client Hello Entirely",
-    "Got Hello Request msg",
-    "Got Session Ticket msg",
-    "Bad Input",
-    "Bad Decrypt Type",
-
-    /* 66 */
-    "Bad Finished Message Processing",
-    "Bad Compression Type",
-    "Bad DeriveKeys Error",
-    "Saw ACK for Missing Packet Error",
-    "Bad Decrypt Operation",
-
-    /* 71 */
-    "Decrypt Keys Not Set Up",
-    "Late Key Load Error",
-    "Got Certificate Status msg",
-    "RSA Key Missing Error",
-    "Secure Renegotiation Not Supported",
-
-    /* 76 */
-    "Get Session Stats Failure",
-    "Reassembly Buffer Size Exceeded",
-    "Dropping Lost Fragment",
-    "Dropping Partial Record",
-    "Clear ACK Fault",
-
-    /* 81 */
-    "Bad Decrypt Size",
-    "Extended Master Secret Hash Error"
-};
-
-
-/* *nix version uses table above */
-static void GetError(int idx, char* str)
-{
-    XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
-}
-
-
-#else /* _WIN32 */
-
-
-/* Windows version uses .rc table */
-static void GetError(int idx, char* buffer)
-{
-    if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
-        buffer[0] = 0;
-}
-
-
-#endif /* _WIN32 */
-
-
-/* Packet Buffer for reassembly list and ready list */
-typedef struct PacketBuffer {
-    word32  begin;      /* relative sequence begin */
-    word32  end;        /* relative sequence end   */
-    byte*   data;       /* actual data             */
-    struct PacketBuffer* next; /* next on reassembly list or ready list */
-} PacketBuffer;
-
-
-#ifdef HAVE_SNI
-
-/* NamedKey maps a SNI name to a specific private key */
-typedef struct NamedKey {
-    char             name[MAX_SERVER_NAME];      /* server DNS name */
-    word32           nameSz;                     /* size of server DNS name */
-    byte*            key;                        /* DER private key */
-    word32           keySz;                      /* size of DER private key */
-    struct NamedKey* next;                       /* for list */
-} NamedKey;
-
-#endif
-
-
-/* Sniffer Server holds info for each server/port monitored */
-typedef struct SnifferServer {
-    SSL_CTX*       ctx;                          /* SSL context */
-    char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
-    word32         server;                       /* netowrk order address */
-    int            port;                         /* server port */
-#ifdef HAVE_SNI
-    NamedKey*      namedKeys;                    /* mapping of names and keys */
-    wolfSSL_Mutex  namedKeysMutex;               /* mutex for namedKey list */
-#endif
-    struct SnifferServer* next;                  /* for list */
-} SnifferServer;
-
-
-/* Session Flags */
-typedef struct Flags {
-    byte           side;            /* which end is current packet headed */
-    byte           serverCipherOn;  /* indicates whether cipher is active */
-    byte           clientCipherOn;  /* indicates whether cipher is active */
-    byte           resuming;        /* did this session come from resumption */
-    byte           cached;          /* have we cached this session yet */
-    byte           clientHello;     /* processed client hello yet, for SSLv2 */
-    byte           finCount;        /* get both FINs before removing */
-    byte           fatalError;      /* fatal error state */
-    byte           cliAckFault;     /* client acked unseen data from server */
-    byte           srvAckFault;     /* server acked unseen data from client */
-    byte           cliSkipPartial;  /* client skips partial data to catch up */
-    byte           srvSkipPartial;  /* server skips partial data to catch up */
-#ifdef HAVE_EXTENDED_MASTER
-    byte           expectEms;       /* expect extended master secret */
-#endif
-} Flags;
-
-
-/* Out of Order FIN caputre */
-typedef struct FinCaputre {
-    word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
-    word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
-    byte   cliCounted;              /* did we count yet, detects duplicates */
-    byte   srvCounted;              /* did we count yet, detects duplicates */
-} FinCaputre;
-
-
-typedef struct HsHashes {
-#ifndef NO_OLD_TLS
-#ifndef NO_SHA
-    wc_Sha hashSha;
-#endif
-#ifndef NO_MD5
-    wc_Md5 hashMd5;
-#endif
-#endif
-#ifndef NO_SHA256
-    wc_Sha256 hashSha256;
-#endif
-#ifdef WOLFSSL_SHA384
-    wc_Sha384 hashSha384;
-#endif
-} HsHashes;
-
-
-/* Sniffer Session holds info for each client/server SSL/TLS session */
-typedef struct SnifferSession {
-    SnifferServer* context;         /* server context */
-    SSL*           sslServer;       /* SSL server side decode */
-    SSL*           sslClient;       /* SSL client side decode */
-    word32         server;          /* server address in network byte order */
-    word32         client;          /* client address in network byte order */
-    word16         srvPort;         /* server port */
-    word16         cliPort;         /* client port */
-    word32         cliSeqStart;     /* client start sequence */
-    word32         srvSeqStart;     /* server start sequence */
-    word32         cliExpected;     /* client expected sequence (relative) */
-    word32         srvExpected;     /* server expected sequence (relative) */
-    FinCaputre     finCaputre;      /* retain out of order FIN s */
-    Flags          flags;           /* session flags */
-    time_t         lastUsed;          /* last used ticks */
-    PacketBuffer*  cliReassemblyList; /* client out of order packets */
-    PacketBuffer*  srvReassemblyList; /* server out of order packets */
-    word32         cliReassemblyMemory; /* client packet memory used */
-    word32         srvReassemblyMemory; /* server packet memory used */
-    struct SnifferSession* next;      /* for hash table list */
-    byte*          ticketID;          /* mac ID of session ticket */
-#ifdef HAVE_EXTENDED_MASTER
-    HsHashes*       hash;
-#endif
-} SnifferSession;
-
-
-/* Sniffer Server List and mutex */
-static SnifferServer* ServerList = 0;
-static wolfSSL_Mutex ServerListMutex;
-
-
-/* Session Hash Table, mutex, and count */
-static SnifferSession* SessionTable[HASH_SIZE];
-static wolfSSL_Mutex SessionMutex;
-static int SessionCount = 0;
-
-/* Recovery of missed data switches and stats */
-static wolfSSL_Mutex RecoveryMutex;      /* for stats */
-static int RecoveryEnabled    = 0;       /* global switch */
-static int MaxRecoveryMemory  = -1;      /* per session max recovery memory */
-static word32 MissedDataSessions = 0;    /* # of sessions with missed data */
-
-
-static void UpdateMissedDataSessions(void)
-{
-    wc_LockMutex(&RecoveryMutex);
-    MissedDataSessions += 1;
-    wc_UnLockMutex(&RecoveryMutex);
-}
-
-
-/* Initialize overall Sniffer */
-void ssl_InitSniffer(void)
-{
-    wolfSSL_Init();
-    wc_InitMutex(&ServerListMutex);
-    wc_InitMutex(&SessionMutex);
-    wc_InitMutex(&RecoveryMutex);
-}
-
-
-#ifdef HAVE_SNI
-
-/* Free Named Key and the zero out the private key it holds */
-static void FreeNamedKey(NamedKey* in)
-{
-    if (in) {
-        if (in->key) {
-            ForceZero(in->key, in->keySz);
-            free(in->key);
-        }
-        free(in);
-    }
-}
-
-
-static void FreeNamedKeyList(NamedKey* in)
-{
-    NamedKey* next;
-
-    while (in) {
-        next = in->next;
-        FreeNamedKey(in);
-        in = next;
-    }
-}
-
-#endif
-
-
-/* Free Sniffer Server's resources/self */
-static void FreeSnifferServer(SnifferServer* srv)
-{
-    if (srv) {
-#ifdef HAVE_SNI
-        wc_LockMutex(&srv->namedKeysMutex);
-        FreeNamedKeyList(srv->namedKeys);
-        wc_UnLockMutex(&srv->namedKeysMutex);
-        wc_FreeMutex(&srv->namedKeysMutex);
-#endif
-        SSL_CTX_free(srv->ctx);
-    }
-    free(srv);
-}
-
-
-/* free PacketBuffer's resources/self */
-static void FreePacketBuffer(PacketBuffer* del)
-{
-    if (del) {
-        free(del->data);
-        free(del);
-    }
-}
-
-
-/* remove PacketBuffer List */
-static void FreePacketList(PacketBuffer* in)
-{
-    if (in) {
-        PacketBuffer* del;
-        PacketBuffer* packet = in;
-
-        while (packet) {
-            del = packet;
-            packet = packet->next;
-            FreePacketBuffer(del);
-        }
-    }
-}
-
-
-/* Free Sniffer Session's resources/self */
-static void FreeSnifferSession(SnifferSession* session)
-{
-    if (session) {
-        SSL_free(session->sslClient);
-        SSL_free(session->sslServer);
-
-        FreePacketList(session->cliReassemblyList);
-        FreePacketList(session->srvReassemblyList);
-
-        free(session->ticketID);
-#ifdef HAVE_EXTENDED_MASTER
-        free(session->hash);
-#endif
-    }
-    free(session);
-}
-
-
-/* Free overall Sniffer */
-void ssl_FreeSniffer(void)
-{
-    SnifferServer*  srv;
-    SnifferServer*  removeServer;
-    SnifferSession* session;
-    SnifferSession* removeSession;
-    int i;
-
-    wc_LockMutex(&ServerListMutex);
-    wc_LockMutex(&SessionMutex);
-
-    srv = ServerList;
-    while (srv) {
-        removeServer = srv;
-        srv = srv->next;
-        FreeSnifferServer(removeServer);
-    }
-
-    for (i = 0; i < HASH_SIZE; i++) {
-        session = SessionTable[i];
-        while (session) {
-            removeSession = session;
-            session = session->next;
-            FreeSnifferSession(removeSession);
-        }
-    }
-
-    wc_UnLockMutex(&SessionMutex);
-    wc_UnLockMutex(&ServerListMutex);
-
-    wc_FreeMutex(&RecoveryMutex);
-    wc_FreeMutex(&SessionMutex);
-    wc_FreeMutex(&ServerListMutex);
-
-    if (TraceFile) {
-        TraceOn = 0;
-        fclose(TraceFile);
-        TraceFile = NULL;
-    }
-
-    wolfSSL_Cleanup();
-}
-
-
-#ifdef HAVE_EXTENDED_MASTER
-
-static int HashInit(HsHashes* hash)
-{
-    int ret = 0;
-
-    XMEMSET(hash, 0, sizeof(HsHashes));
-
-#ifndef NO_OLD_TLS
-#ifndef NO_SHA
-    if (ret == 0)
-        ret = wc_InitSha(&hash->hashSha);
-#endif
-#ifndef NO_MD5
-    if (ret == 0) {
-        ret = wc_InitMd5(&hash->hashMd5);
-    }
-#endif
-#endif
-#ifndef NO_SHA256
-    if (ret == 0)
-        ret = wc_InitSha256(&hash->hashSha256);
-#endif
-#ifdef WOLFSSL_SHA384
-    if (ret == 0)
-        ret = wc_InitSha384(&hash->hashSha384);
-#endif
-
-    return ret;
-}
-
-
-static int HashUpdate(HsHashes* hash, const byte* input, int sz)
-{
-    int ret = 0;
-
-    input -= HANDSHAKE_HEADER_SZ;
-    sz += HANDSHAKE_HEADER_SZ;
-
-#ifndef NO_OLD_TLS
-#ifndef NO_SHA
-    if (ret == 0)
-        ret = wc_ShaUpdate(&hash->hashSha, input, sz);
-#endif
-#ifndef NO_MD5
-    if (ret == 0) {
-        ret = wc_Md5Update(&hash->hashMd5, input, sz);
-    }
-#endif
-#endif
-#ifndef NO_SHA256
-    if (ret == 0)
-        ret = wc_Sha256Update(&hash->hashSha256, input, sz);
-#endif
-#ifdef WOLFSSL_SHA384
-    if (ret == 0)
-        ret = wc_Sha384Update(&hash->hashSha384, input, sz);
-#endif
-
-    return ret;
-}
-
-
-static int HashCopy(HS_Hashes* d, HsHashes* s)
-{
-#ifndef NO_OLD_TLS
-#ifndef NO_SHA
-        XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
-#endif
-#ifndef NO_MD5
-        XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
-#endif
-#endif
-
-#ifndef NO_SHA256
-        XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
-#endif
-#ifdef WOLFSSL_SHA384
-        XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
-#endif
-
-    return 0;
-}
-
-#endif
-
-
-/* Initialize a SnifferServer */
-static void InitSnifferServer(SnifferServer* sniffer)
-{
-    sniffer->ctx = 0;
-    XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
-    sniffer->server   = 0;
-    sniffer->port     = 0;
-#ifdef HAVE_SNI
-    sniffer->namedKeys = 0;
-    wc_InitMutex(&sniffer->namedKeysMutex);
-#endif
-    sniffer->next     = 0;
-}
-
-
-/* Initialize session flags */
-static void InitFlags(Flags* flags)
-{
-    flags->side           = 0;
-    flags->serverCipherOn = 0;
-    flags->clientCipherOn = 0;
-    flags->resuming       = 0;
-    flags->cached         = 0;
-    flags->clientHello    = 0;
-    flags->finCount       = 0;
-    flags->fatalError     = 0;
-    flags->cliAckFault    = 0;
-    flags->srvAckFault    = 0;
-    flags->cliSkipPartial = 0;
-    flags->srvSkipPartial = 0;
-#ifdef HAVE_EXTENDED_MASTER
-    flags->expectEms      = 0;
-#endif
-}
-
-
-/* Initialize FIN Capture */
-static void InitFinCapture(FinCaputre* cap)
-{
-    cap->cliFinSeq  = 0;
-    cap->srvFinSeq  = 0;
-    cap->cliCounted = 0;
-    cap->srvCounted = 0;
-}
-
-
-/* Initialize a Sniffer Session */
-static void InitSession(SnifferSession* session)
-{
-    session->context        = 0;
-    session->sslServer      = 0;
-    session->sslClient      = 0;
-    session->server         = 0;
-    session->client         = 0;
-    session->srvPort        = 0;
-    session->cliPort        = 0;
-    session->cliSeqStart    = 0;
-    session->srvSeqStart    = 0;
-    session->cliExpected    = 0;
-    session->srvExpected    = 0;
-    session->lastUsed       = 0;
-    session->cliReassemblyList = 0;
-    session->srvReassemblyList = 0;
-    session->cliReassemblyMemory = 0;
-    session->srvReassemblyMemory = 0;
-    session->next           = 0;
-    session->ticketID       = 0;
-
-    InitFlags(&session->flags);
-    InitFinCapture(&session->finCaputre);
-#ifdef HAVE_EXTENDED_MASTER
-    session->hash = 0;
-#endif
-}
-
-
-/* IP Info from IP Header */
-typedef struct IpInfo {
-    int    length;        /* length of this header */
-    int    total;         /* total length of fragment */
-    word32 src;           /* network order source address */
-    word32 dst;           /* network order destination address */
-} IpInfo;
-
-
-/* TCP Info from TCP Header */
-typedef struct TcpInfo {
-    int    srcPort;       /* source port */
-    int    dstPort;       /* source port */
-    int    length;        /* length of this header */
-    word32 sequence;      /* sequence number */
-    word32 ackNumber;     /* ack number */
-    byte   fin;           /* FIN set */
-    byte   rst;           /* RST set */
-    byte   syn;           /* SYN set */
-    byte   ack;           /* ACK set */
-} TcpInfo;
-
-
-/* Tcp Pseudo Header for Checksum calculation */
-typedef struct TcpPseudoHdr {
-    word32  src;        /* source address */
-    word32  dst;        /* destination address */
-    byte    rsv;        /* reserved, always 0 */
-    byte    protocol;   /* IP protocol */
-    word16  length;     /* tcp header length + data length (doesn't include */
-                        /* pseudo header length) network order */
-} TcpPseudoHdr;
-
-
-/* Password Setting Callback */
-static int SetPassword(char* passwd, int sz, int rw, void* userdata)
-{
-    (void)rw;
-    XSTRNCPY(passwd, (const char*)userdata, sz);
-    return (int)XSTRLEN((const char*)userdata);
-}
-
-
-/* Ethernet Header */
-typedef struct EthernetHdr {
-    byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */
-    byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */
-    word16 type;                      /* IP, ARP, etc */
-} EthernetHdr;
-
-
-/* IP Header */
-typedef struct IpHdr {
-    byte    ver_hl;              /* version/header length */
-    byte    tos;                 /* type of service */
-    word16  length;              /* total length */
-    word16  id;                  /* identification */
-    word16  offset;              /* fragment offset field */
-    byte    ttl;                 /* time to live */
-    byte    protocol;            /* protocol */
-    word16  sum;                 /* checksum */
-    word32  src;                 /* source address */
-    word32  dst;                 /* destination address */
-} IpHdr;
-
-
-#define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
-#define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
-
-/* TCP Header */
-typedef struct TcpHdr {
-    word16  srcPort;            /* source port */
-    word16  dstPort;            /* destination port */
-    word32  sequence;           /* sequence number */
-    word32  ack;                /* acknoledgment number */
-    byte    offset;             /* data offset, reserved */
-    byte    flags;              /* option flags */
-    word16  window;             /* window */
-    word16  sum;                /* checksum */
-    word16  urgent;             /* urgent pointer */
-} TcpHdr;
-
-#define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
-#define TCP_FIN 0x01
-#define TCP_SYN 0x02
-#define TCP_RST 0x04
-#define TCP_ACK 0x10
-
-
-
-
-
-/* Use platform specific GetError to write to tracfile if tracing */
-static void Trace(int idx)
-{
-    if (TraceOn) {
-        char myBuffer[MAX_ERROR_LEN];
-        GetError(idx, myBuffer);
-        fprintf(TraceFile, "\t%s\n", myBuffer);
-#ifdef DEBUG_SNIFFER
-        fprintf(stderr,    "\t%s\n", myBuffer);
-#endif
-    }
-}
-
-
-/* Show TimeStamp for beginning of packet Trace */
-static void TraceHeader(void)
-{
-    if (TraceOn) {
-        time_t ticks = time(NULL);
-        fprintf(TraceFile, "\n%s", ctime(&ticks));
-    }
-}
-
-
-/* Show Set Server info for Trace */
-static void TraceSetServer(const char* srv, int port, const char* keyFile)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
-        fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
-                                                                    keyFile);
-    }
-}
-
-
-#ifdef HAVE_SNI
-
-/* Show Set Named Server info for Trace */
-static void TraceSetNamedServer(const char* name,
-                                 const char* srv, int port, const char* keyFile)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
-        fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
-                                                      name, srv, port, keyFile);
-    }
-}
-
-#endif
-
-
-/* Trace got packet number */
-static void TracePacket(void)
-{
-    if (TraceOn) {
-        static word32 packetNumber = 0;
-        fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
-                ++packetNumber);
-    }
-}
-
-
-/* Convert network byte order address into human readable */
-static char* IpToS(word32 addr, char* str)
-{
-    byte* p = (byte*)&addr;
-
-    SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-
-    return str;
-}
-
-
-/* Show destination and source address from Ip Hdr for packet Trace */
-static void TraceIP(IpHdr* iphdr)
-{
-    if (TraceOn) {
-        char src[TRACE_MSG_SZ];
-        char dst[TRACE_MSG_SZ];
-        fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
-                IpToS(iphdr->src, src));
-    }
-}
-
-
-/* Show destination and source port from Tcp Hdr for packet Trace */
-static void TraceTcp(TcpHdr* tcphdr)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
-                ntohs(tcphdr->srcPort));
-    }
-}
-
-
-/* Show sequence and payload length for Trace */
-static void TraceSequence(word32 seq, int len)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
-    }
-}
-
-
-/* Show sequence and payload length for Trace */
-static void TraceAck(word32 ack, word32 expected)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
-    }
-}
-
-
-/* Show relative expected and relative received sequences */
-static void TraceRelativeSequence(word32 expected, word32 got)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
-                expected, got);
-    }
-}
-
-
-/* Show server sequence startup from SYN */
-static void TraceServerSyn(word32 seq)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
-    }
-}
-
-
-/* Show client sequence startup from SYN */
-static void TraceClientSyn(word32 seq)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
-    }
-}
-
-
-/* Show client FIN capture */
-static void TraceClientFin(word32 finSeq, word32 relSeq)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
-                finSeq, relSeq);
-    }
-}
-
-
-/* Show server FIN capture */
-static void TraceServerFin(word32 finSeq, word32 relSeq)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
-                finSeq, relSeq);
-    }
-}
-
-
-/* Show number of SSL data bytes decoded, could be 0 (ok) */
-static void TraceGotData(int bytes)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
-    }
-}
-
-
-/* Show bytes added to old SSL App data */
-static void TraceAddedData(int newBytes, int existingBytes)
-{
-    if (TraceOn) {
-        fprintf(TraceFile,
-                "\t%d bytes added to %d existing bytes in User Buffer\n",
-                newBytes, existingBytes);
-    }
-}
-
-
-/* Show Stale Session */
-static void TraceStaleSession(void)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tFound a stale session\n");
-    }
-}
-
-
-/* Show Finding Stale Sessions */
-static void TraceFindingStale(void)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
-    }
-}
-
-
-/* Show Removed Session */
-static void TraceRemovedSession(void)
-{
-    if (TraceOn) {
-        fprintf(TraceFile, "\tRemoved it\n");
-    }
-}
-
-
-/* Set user error string */
-static void SetError(int idx, char* error, SnifferSession* session, int fatal)
-{
-    GetError(idx, error);
-    Trace(idx);
-    if (session && fatal == FATAL_ERROR_STATE)
-        session->flags.fatalError = 1;
-}
-
-
-/* See if this IPV4 network order address has been registered */
-/* return 1 is true, 0 is false */
-static int IsServerRegistered(word32 addr)
-{
-    int ret = 0;     /* false */
-    SnifferServer* sniffer;
-
-    wc_LockMutex(&ServerListMutex);
-
-    sniffer = ServerList;
-    while (sniffer) {
-        if (sniffer->server == addr) {
-            ret = 1;
-            break;
-        }
-        sniffer = sniffer->next;
-    }
-
-    wc_UnLockMutex(&ServerListMutex);
-
-    return ret;
-}
-
-
-/* See if this port has been registered to watch */
-/* return 1 is true, 0 is false */
-static int IsPortRegistered(word32 port)
-{
-    int ret = 0;    /* false */
-    SnifferServer* sniffer;
-
-    wc_LockMutex(&ServerListMutex);
-
-    sniffer = ServerList;
-    while (sniffer) {
-        if (sniffer->port == (int)port) {
-            ret = 1;
-            break;
-        }
-        sniffer = sniffer->next;
-    }
-
-    wc_UnLockMutex(&ServerListMutex);
-
-    return ret;
-}
-
-
-/* Get SnifferServer from IP and Port */
-static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
-{
-    SnifferServer* sniffer;
-
-    wc_LockMutex(&ServerListMutex);
-
-    sniffer = ServerList;
-    while (sniffer) {
-        if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
-            break;
-        if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
-            break;
-        sniffer = sniffer->next;
-    }
-
-    wc_UnLockMutex(&ServerListMutex);
-
-    return sniffer;
-}
-
-
-/* Hash the Session Info, return hash row */
-static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
-{
-    word32 hash = ipInfo->src * ipInfo->dst;
-    hash *= tcpInfo->srcPort * tcpInfo->dstPort;
-
-    return hash % HASH_SIZE;
-}
-
-
-/* Get Exisiting SnifferSession from IP and Port */
-static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
-{
-    SnifferSession* session;
-    time_t          currTime = time(NULL);
-    word32          row = SessionHash(ipInfo, tcpInfo);
-
-    assert(row <= HASH_SIZE);
-
-    wc_LockMutex(&SessionMutex);
-
-    session = SessionTable[row];
-    while (session) {
-        if (session->server == ipInfo->src && session->client == ipInfo->dst &&
-                    session->srvPort == tcpInfo->srcPort &&
-                    session->cliPort == tcpInfo->dstPort)
-            break;
-        if (session->client == ipInfo->src && session->server == ipInfo->dst &&
-                    session->cliPort == tcpInfo->srcPort &&
-                    session->srvPort == tcpInfo->dstPort)
-            break;
-
-        session = session->next;
-    }
-
-    if (session)
-        session->lastUsed= currTime; /* keep session alive, remove stale will */
-                                     /* leave alone */
-    wc_UnLockMutex(&SessionMutex);
-
-    /* determine side */
-    if (session) {
-        if (ipInfo->dst == session->context->server &&
-            tcpInfo->dstPort == session->context->port)
-            session->flags.side = WOLFSSL_SERVER_END;
-        else
-            session->flags.side = WOLFSSL_CLIENT_END;
-    }
-
-    return session;
-}
-
-
-#ifdef HAVE_SNI
-
-static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
-                const char* keyFile, int typeKey,
-                const char* password)
-{
-    byte* loadBuf;
-    long fileSz = 0;
-    XFILE file;
-    int ret;
-
-    if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
-        return -1;
-    }
-
-    file = XFOPEN(keyFile, "rb");
-    if (file == XBADFILE) return -1;
-    XFSEEK(file, 0, XSEEK_END);
-    fileSz = XFTELL(file);
-    XREWIND(file);
-
-    loadBuf = (byte*)malloc(fileSz);
-    if (loadBuf == NULL) {
-        XFCLOSE(file);
-        return -1;
-    }
-
-    ret = (int)XFREAD(loadBuf, 1, fileSz, file);
-    XFCLOSE(file);
-
-    if (ret != fileSz) {
-        free(loadBuf);
-        return -1;
-    }
-
-    if (typeKey == WOLFSSL_FILETYPE_PEM) {
-        byte* saveBuf   = (byte*)malloc(fileSz);
-        int   saveBufSz = 0;
-
-        ret = -1;
-        if (saveBuf != NULL) {
-            saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
-                                                saveBuf, (int)fileSz, password);
-            if (saveBufSz < 0) {
-                saveBufSz = 0;
-                free(saveBuf);
-                saveBuf = NULL;
-            }
-            else
-                ret = 0;
-        }
-
-        ForceZero(loadBuf, (word32)fileSz);
-        free(loadBuf);
-
-        if (saveBuf) {
-            *keyBuf = saveBuf;
-            *keyBufSz = (word32)saveBufSz;
-        }
-    }
-    else {
-        *keyBuf = loadBuf;
-        *keyBufSz = (word32)fileSz;
-    }
-
-    if (ret < 0) {
-        return -1;
-    }
-
-    return ret;
-}
-
-#endif
-
-
-static int SetNamedPrivateKey(const char* name, const char* address, int port,
-            const char* keyFile, int typeKey, const char* password, char* error)
-{
-    SnifferServer* sniffer;
-    int            ret;
-    int            type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
-                                                      WOLFSSL_FILETYPE_ASN1;
-    int            isNew = 0;
-    word32         serverIp;
-
-#ifdef HAVE_SNI
-    NamedKey* namedKey = NULL;
-#endif
-
-    (void)name;
-#ifdef HAVE_SNI
-    if (name != NULL) {
-        namedKey = (NamedKey*)malloc(sizeof(NamedKey));
-        if (namedKey == NULL) {
-            SetError(MEMORY_STR, error, NULL, 0);
-            return -1;
-        }
-        XMEMSET(namedKey, 0, sizeof(NamedKey));
-
-        namedKey->nameSz = (word32)XSTRLEN(name);
-        if (namedKey->nameSz > sizeof(namedKey->name)-1)
-            namedKey->nameSz = sizeof(namedKey->name)-1;
-        XSTRNCPY(namedKey->name, name, namedKey->nameSz);
-        namedKey->name[MAX_SERVER_NAME-1] = '\0';
-
-        ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
-                          keyFile, type, password);
-        if (ret < 0) {
-            SetError(KEY_FILE_STR, error, NULL, 0);
-            FreeNamedKey(namedKey);
-            return -1;
-        }
-    }
-#endif
-
-    serverIp = inet_addr(address);
-    sniffer = ServerList;
-    while (sniffer != NULL &&
-           (sniffer->server != serverIp || sniffer->port != port)) {
-        sniffer = sniffer->next;
-    }
-
-    if (sniffer == NULL) {
-        isNew = 1;
-        sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
-        if (sniffer == NULL) {
-            SetError(MEMORY_STR, error, NULL, 0);
-#ifdef HAVE_SNI
-            FreeNamedKey(namedKey);
-#endif
-            return -1;
-        }
-        InitSnifferServer(sniffer);
-
-        XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
-        sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
-        sniffer->server = serverIp;
-        sniffer->port = port;
-
-        sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
-        if (!sniffer->ctx) {
-            SetError(MEMORY_STR, error, NULL, 0);
-#ifdef HAVE_SNI
-            FreeNamedKey(namedKey);
-#endif
-            FreeSnifferServer(sniffer);
-            return -1;
-        }
-    }
-
-    if (name == NULL) {
-        if (password) {
-    #ifdef WOLFSSL_ENCRYPTED_KEYS
-            SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
-            SSL_CTX_set_default_passwd_cb_userdata(
-                                                 sniffer->ctx, (void*)password);
-    #endif
-        }
-        ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
-        if (ret != WOLFSSL_SUCCESS) {
-            SetError(KEY_FILE_STR, error, NULL, 0);
-            if (isNew)
-                FreeSnifferServer(sniffer);
-            return -1;
-        }
-    }
-#ifdef HAVE_SNI
-    else {
-        wc_LockMutex(&sniffer->namedKeysMutex);
-        namedKey->next = sniffer->namedKeys;
-        sniffer->namedKeys = namedKey;
-        wc_UnLockMutex(&sniffer->namedKeysMutex);
-    }
-#endif
-
-    if (isNew) {
-        sniffer->next = ServerList;
-        ServerList = sniffer;
-    }
-
-    return 0;
-}
-
-
-#ifdef HAVE_SNI
-
-/* Sets the private key for a specific name, server and port  */
-/* returns 0 on success, -1 on error */
-int ssl_SetNamedPrivateKey(const char* name,
-                           const char* address, int port,
-                           const char* keyFile, int typeKey,
-                           const char* password, char* error)
-{
-    int ret;
-
-    TraceHeader();
-    TraceSetNamedServer(name, address, port, keyFile);
-
-    wc_LockMutex(&ServerListMutex);
-    ret = SetNamedPrivateKey(name, address, port, keyFile,
-                             typeKey, password, error);
-    wc_UnLockMutex(&ServerListMutex);
-
-    if (ret == 0)
-        Trace(NEW_SERVER_STR);
-
-    return ret;
-}
-
-#endif
-
-
-/* Sets the private key for a specific server and port  */
-/* returns 0 on success, -1 on error */
-int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
-                      int typeKey, const char* password, char* error)
-{
-    int ret;
-
-    TraceHeader();
-    TraceSetServer(address, port, keyFile);
-
-    wc_LockMutex(&ServerListMutex);
-    ret = SetNamedPrivateKey(NULL, address, port, keyFile,
-                             typeKey, password, error);
-    wc_UnLockMutex(&ServerListMutex);
-
-    if (ret == 0)
-        Trace(NEW_SERVER_STR);
-
-    return ret;
-}
-
-
-/* Check IP Header for IPV4, TCP, and a registered server address */
-/* returns 0 on success, -1 on error */
-static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
-{
-    int    version = IP_V(iphdr);
-
-    TraceIP(iphdr);
-    Trace(IP_CHECK_STR);
-
-    if (version != IPV4) {
-        SetError(BAD_IPVER_STR, error, NULL, 0);
-        return -1;
-    }
-
-    if (iphdr->protocol != TCP_PROTOCOL) {
-        SetError(BAD_PROTO_STR, error, NULL, 0);
-        return -1;
-    }
-
-    if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
-        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
-        return -1;
-    }
-
-    info->length  = IP_HL(iphdr);
-    info->total   = ntohs(iphdr->length);
-    info->src     = iphdr->src;
-    info->dst     = iphdr->dst;
-
-    if (info->total == 0)
-        info->total = length;  /* reassembled may be off */
-
-    return 0;
-}
-
-
-/* Check TCP Header for a registered port */
-/* returns 0 on success, -1 on error */
-static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
-{
-    TraceTcp(tcphdr);
-    Trace(TCP_CHECK_STR);
-    info->srcPort   = ntohs(tcphdr->srcPort);
-    info->dstPort   = ntohs(tcphdr->dstPort);
-    info->length    = TCP_LEN(tcphdr);
-    info->sequence  = ntohl(tcphdr->sequence);
-    info->fin       = tcphdr->flags & TCP_FIN;
-    info->rst       = tcphdr->flags & TCP_RST;
-    info->syn       = tcphdr->flags & TCP_SYN;
-    info->ack       = tcphdr->flags & TCP_ACK;
-    if (info->ack)
-        info->ackNumber = ntohl(tcphdr->ack);
-
-    if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
-        SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/* Decode Record Layer Header */
-static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
-{
-    XMEMCPY(rh, input, RECORD_HEADER_SZ);
-    *size = (rh->length[0] << 8) | rh->length[1];
-
-    if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
-        return LENGTH_ERROR;
-
-    return 0;
-}
-
-
-/* Process Client Key Exchange, RSA only */
-static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
-                                    SnifferSession* session, char* error)
-{
-    word32 idx = 0;
-    RsaKey key;
-    int    ret;
-
-    if (session->sslServer->buffers.key == NULL ||
-        session->sslServer->buffers.key->buffer == NULL ||
-        session->sslServer->buffers.key->length == 0) {
-
-        SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    ret = wc_InitRsaKey(&key, 0);
-    if (ret == 0)
-        ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key->buffer,
-                          &idx, &key, session->sslServer->buffers.key->length);
-    if (ret == 0) {
-        int length = wc_RsaEncryptSize(&key);
-
-        if (IsTLS(session->sslServer))
-            input += 2;     /* tls pre length */
-
-        if (length > *sslBytes) {
-            SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
-            wc_FreeRsaKey(&key);
-            return -1;
-        }
-        #ifdef WC_RSA_BLINDING
-            ret = wc_RsaSetRNG(&key, session->sslServer->rng);
-            if (ret != 0) {
-                SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
-                return -1;
-            }
-        #endif
-        do {
-        #ifdef WOLFSSL_ASYNC_CRYPT
-                ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-        #endif
-            if (ret >= 0) {
-                ret = wc_RsaPrivateDecrypt(input, length,
-                      session->sslServer->arrays->preMasterSecret, SECRET_LEN,
-                      &key);
-            }
-        } while (ret == WC_PENDING_E);
-        if (ret != SECRET_LEN) {
-            SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
-            wc_FreeRsaKey(&key);
-            return -1;
-        }
-        session->sslServer->arrays->preMasterSz = SECRET_LEN;
-
-        /* store for client side as well */
-        XMEMCPY(session->sslClient->arrays->preMasterSecret,
-               session->sslServer->arrays->preMasterSecret, SECRET_LEN);
-        session->sslClient->arrays->preMasterSz = SECRET_LEN;
-
-        #ifdef SHOW_SECRETS
-        {
-            int i;
-            printf("pre master secret: ");
-            for (i = 0; i < SECRET_LEN; i++)
-                printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
-            printf("\n");
-        }
-        #endif
-    }
-    else {
-        SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
-        wc_FreeRsaKey(&key);
-        return -1;
-    }
-
-    if (SetCipherSpecs(session->sslServer) != 0) {
-        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
-        wc_FreeRsaKey(&key);
-        return -1;
-    }
-
-    if (SetCipherSpecs(session->sslClient) != 0) {
-        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
-        wc_FreeRsaKey(&key);
-        return -1;
-    }
-
-    ret  = MakeMasterSecret(session->sslServer);
-    ret += MakeMasterSecret(session->sslClient);
-    ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
-    ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
-
-    if (ret != 0) {
-        SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-#ifdef SHOW_SECRETS
-    {
-        int i;
-        printf("server master secret: ");
-        for (i = 0; i < SECRET_LEN; i++)
-            printf("%02x", session->sslServer->arrays->masterSecret[i]);
-        printf("\n");
-
-        printf("client master secret: ");
-        for (i = 0; i < SECRET_LEN; i++)
-            printf("%02x", session->sslClient->arrays->masterSecret[i]);
-        printf("\n");
-
-        printf("server suite = %d\n", session->sslServer->options.cipherSuite);
-        printf("client suite = %d\n", session->sslClient->options.cipherSuite);
-    }
-#endif
-
-    wc_FreeRsaKey(&key);
-    return ret;
-}
-
-
-/* Process Session Ticket */
-static int ProcessSessionTicket(const byte* input, int* sslBytes,
-                                SnifferSession* session, char* error)
-{
-    word16 len;
-
-    /* make sure can read through hint and len */
-    if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
-        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    input     += TICKET_HINT_LEN;  /* skip over hint */
-    *sslBytes -= TICKET_HINT_LEN;
-
-    len = (word16)((input[0] << 8) | input[1]);
-    input     += LENGTH_SZ;
-    *sslBytes -= LENGTH_SZ;
-
-    /* make sure can read through ticket */
-    if (len > *sslBytes || len < ID_LEN) {
-        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    /* store session with macID as sessionID */
-    session->sslServer->options.haveSessionId = 1;
-    XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
-
-    return 0;
-}
-
-
-/* Process Server Hello */
-static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
-                              SnifferSession* session, char* error)
-{
-    ProtocolVersion pv;
-    byte            b;
-    int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
-    int             doResume     = 0;
-    int             initialBytes = *sslBytes;
-
-    (void)msgSz;
-    (void)initialBytes;
-
-    /* make sure we didn't miss ClientHello */
-    if (session->flags.clientHello == 0) {
-        SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    /* make sure can read through session len */
-    if (toRead > *sslBytes) {
-        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    XMEMCPY(&pv, input, VERSION_SZ);
-    input     += VERSION_SZ;
-    *sslBytes -= VERSION_SZ;
-
-    session->sslServer->version = pv;
-    session->sslClient->version = pv;
-
-    XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
-    XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
-    input    += RAN_LEN;
-    *sslBytes -= RAN_LEN;
-
-    b = *input++;
-    *sslBytes -= 1;
-
-    /* make sure can read through compression */
-    if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
-        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    if (b) {
-        XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
-        session->sslServer->options.haveSessionId = 1;
-    }
-    input     += b;
-    *sslBytes -= b;
-
-    /* cipher suite */
-    b = *input++;  /* first byte, ECC or not */
-    session->sslServer->options.cipherSuite0 = b;
-    session->sslClient->options.cipherSuite0 = b;
-    b = *input++;
-    session->sslServer->options.cipherSuite = b;
-    session->sslClient->options.cipherSuite = b;
-    *sslBytes -= SUITE_LEN;
-
-    /* compression */
-    b = *input++;
-    *sslBytes -= ENUM_LEN;
-
-    if (b) {
-        SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-#ifdef HAVE_EXTENDED_MASTER
-    /* extensions */
-    if ((initialBytes - *sslBytes) < msgSz) {
-        word16 len;
-
-        /* skip extensions until extended master secret */
-        /* make sure can read len */
-        if (SUITE_LEN > *sslBytes) {
-            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        len = (word16)((input[0] << 8) | input[1]);
-        input     += SUITE_LEN;
-        *sslBytes -= SUITE_LEN;
-        /* make sure can read through all extensions */
-        if (len > *sslBytes) {
-            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-
-        while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
-            byte   extType[EXT_TYPE_SZ];
-            word16 extLen;
-
-            extType[0] = input[0];
-            extType[1] = input[1];
-            input     += EXT_TYPE_SZ;
-            *sslBytes -= EXT_TYPE_SZ;
-
-            extLen = (word16)((input[0] << 8) | input[1]);
-            input     += LENGTH_SZ;
-            *sslBytes -= LENGTH_SZ;
-
-            /* make sure can read through individual extension */
-            if (extLen > *sslBytes) {
-                SetError(SERVER_HELLO_INPUT_STR, error, session,
-                         FATAL_ERROR_STATE);
-                return -1;
-            }
-
-            if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
-                session->flags.expectEms = 1;
-            }
-
-            input     += extLen;
-            *sslBytes -= extLen;
-            len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
-        }
-    }
-
-    if (!session->flags.expectEms) {
-        free(session->hash);
-        session->hash = NULL;
-    }
-#endif
-
-    if (session->sslServer->options.haveSessionId &&
-            XMEMCMP(session->sslServer->arrays->sessionID,
-                    session->sslClient->arrays->sessionID, ID_LEN) == 0)
-        doResume = 1;
-    else if (session->sslClient->options.haveSessionId == 0 &&
-             session->sslServer->options.haveSessionId == 0 &&
-             session->ticketID)
-        doResume = 1;
-
-    if (session->ticketID && doResume) {
-        /* use ticketID to retrieve from session, prefer over sessionID */
-        XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
-        session->sslServer->options.haveSessionId = 1;  /* may not have
-                                                           actual sessionID */
-    }
-
-    if (doResume ) {
-        int ret = 0;
-        SSL_SESSION* resume = GetSession(session->sslServer,
-                                  session->sslServer->arrays->masterSecret, 0);
-        if (resume == NULL) {
-            SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        /* make sure client has master secret too */
-        XMEMCPY(session->sslClient->arrays->masterSecret,
-               session->sslServer->arrays->masterSecret, SECRET_LEN);
-        session->flags.resuming = 1;
-
-        Trace(SERVER_DID_RESUMPTION_STR);
-        if (SetCipherSpecs(session->sslServer) != 0) {
-            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-
-        if (SetCipherSpecs(session->sslClient) != 0) {
-            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-
-        if (session->sslServer->options.tls) {
-            ret =  DeriveTlsKeys(session->sslServer);
-            ret += DeriveTlsKeys(session->sslClient);
-        }
-        else {
-            ret =  DeriveKeys(session->sslServer);
-            ret += DeriveKeys(session->sslClient);
-        }
-        ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
-        ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
-
-        if (ret != 0) {
-            SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-    }
-#ifdef SHOW_SECRETS
-    {
-        int i;
-        printf("cipher suite = 0x%02x\n",
-               session->sslServer->options.cipherSuite);
-        printf("server random: ");
-        for (i = 0; i < RAN_LEN; i++)
-            printf("%02x", session->sslServer->arrays->serverRandom[i]);
-        printf("\n");
-    }
-#endif
-    return 0;
-}
-
-
-/* Process normal Client Hello */
-static int ProcessClientHello(const byte* input, int* sslBytes,
-                              SnifferSession* session, char* error)
-{
-    byte   bLen;
-    word16 len;
-    int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
-
-#ifdef HAVE_SNI
-    {
-        byte name[MAX_SERVER_NAME];
-        word32 nameSz = sizeof(name);
-        int ret;
-
-        ret = wolfSSL_SNI_GetFromBuffer(
-                             input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
-                             *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
-                             WOLFSSL_SNI_HOST_NAME, name, &nameSz);
-
-        if (ret == WOLFSSL_SUCCESS) {
-            NamedKey* namedKey;
-
-            if (nameSz > sizeof(name) - 1)
-                nameSz = sizeof(name) - 1;
-            name[nameSz] = 0;
-            wc_LockMutex(&session->context->namedKeysMutex);
-            namedKey = session->context->namedKeys;
-            while (namedKey != NULL) {
-                if (nameSz == namedKey->nameSz &&
-                           XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
-                    if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
-                                            namedKey->key, namedKey->keySz,
-                                            WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
-                        wc_UnLockMutex(&session->context->namedKeysMutex);
-                        SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
-                                                             FATAL_ERROR_STATE);
-                        return -1;
-                    }
-                    break;
-                }
-                else
-                    namedKey = namedKey->next;
-            }
-            wc_UnLockMutex(&session->context->namedKeysMutex);
-        }
-    }
-#endif
-
-    session->flags.clientHello = 1;  /* don't process again */
-
-    /* make sure can read up to session len */
-    if (toRead > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    /* skip, get negotiated one from server hello */
-    input     += VERSION_SZ;
-    *sslBytes -= VERSION_SZ;
-
-    XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
-    XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
-
-    input     += RAN_LEN;
-    *sslBytes -= RAN_LEN;
-
-    /* store session in case trying to resume */
-    bLen = *input++;
-    *sslBytes -= ENUM_LEN;
-    if (bLen) {
-        if (ID_LEN > *sslBytes) {
-            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        Trace(CLIENT_RESUME_TRY_STR);
-        XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
-        session->sslClient->options.haveSessionId = 1;
-    }
-#ifdef SHOW_SECRETS
-    {
-        int i;
-        printf("client random: ");
-        for (i = 0; i < RAN_LEN; i++)
-            printf("%02x", session->sslServer->arrays->clientRandom[i]);
-        printf("\n");
-    }
-#endif
-
-    input     += bLen;
-    *sslBytes -= bLen;
-
-    /* skip cipher suites */
-    /* make sure can read len */
-    if (SUITE_LEN > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    len = (word16)((input[0] << 8) | input[1]);
-    input     += SUITE_LEN;
-    *sslBytes -= SUITE_LEN;
-    /* make sure can read suites + comp len */
-    if (len + ENUM_LEN > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    input     += len;
-    *sslBytes -= len;
-
-    /* skip compression */
-    bLen       = *input++;
-    *sslBytes -= ENUM_LEN;
-    /* make sure can read len */
-    if (bLen > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    input     += bLen;
-    *sslBytes -= bLen;
-
-    if (*sslBytes == 0) {
-        /* no extensions */
-        return 0;
-    }
-
-    /* skip extensions until session ticket */
-    /* make sure can read len */
-    if (SUITE_LEN > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    len = (word16)((input[0] << 8) | input[1]);
-    input     += SUITE_LEN;
-    *sslBytes -= SUITE_LEN;
-    /* make sure can read through all extensions */
-    if (len > *sslBytes) {
-        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
-        byte   extType[EXT_TYPE_SZ];
-        word16 extLen;
-
-        extType[0] = input[0];
-        extType[1] = input[1];
-        input     += EXT_TYPE_SZ;
-        *sslBytes -= EXT_TYPE_SZ;
-
-        extLen = (word16)((input[0] << 8) | input[1]);
-        input     += LENGTH_SZ;
-        *sslBytes -= LENGTH_SZ;
-
-        /* make sure can read through individual extension */
-        if (extLen > *sslBytes) {
-            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-
-        if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
-
-            /* make sure can read through ticket if there is a non blank one */
-            if (extLen && extLen < ID_LEN) {
-                SetError(CLIENT_HELLO_INPUT_STR, error, session,
-                         FATAL_ERROR_STATE);
-                return -1;
-            }
-
-            if (extLen) {
-                if (session->ticketID == 0) {
-                    session->ticketID = (byte*)malloc(ID_LEN);
-                    if (session->ticketID == 0) {
-                        SetError(MEMORY_STR, error, session,
-                                 FATAL_ERROR_STATE);
-                        return -1;
-                    }
-                }
-                XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
-            }
-        }
-
-        input     += extLen;
-        *sslBytes -= extLen;
-        len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
-    }
-
-    return 0;
-}
-
-
-/* Process Finished */
-static int ProcessFinished(const byte* input, int size, int* sslBytes,
-                           SnifferSession* session, char* error)
-{
-    SSL*   ssl;
-    word32 inOutIdx = 0;
-    int    ret;
-
-    if (session->flags.side == WOLFSSL_SERVER_END)
-        ssl = session->sslServer;
-    else
-        ssl = session->sslClient;
-
-    ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
-                                                                         SNIFF);
-    *sslBytes -= (int)inOutIdx;
-
-    if (ret < 0) {
-        SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
-        return ret;
-    }
-
-    if (ret == 0 && session->flags.cached == 0) {
-        if (session->sslServer->options.haveSessionId) {
-            WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
-            if (sess == NULL)
-                AddSession(session->sslServer);  /* don't re add */
-            session->flags.cached = 1;
-         }
-    }
-
-    /* If receiving a finished message from one side, free the resources
-     * from the other side's tracker. */
-    if (session->flags.side == WOLFSSL_SERVER_END)
-        FreeHandshakeResources(session->sslClient);
-    else
-        FreeHandshakeResources(session->sslServer);
-
-    return ret;
-}
-
-
-/* Process HandShake input */
-static int DoHandShake(const byte* input, int* sslBytes,
-                       SnifferSession* session, char* error)
-{
-    byte type;
-    int  size;
-    int  ret = 0;
-    int  startBytes;
-
-    if (*sslBytes < HANDSHAKE_HEADER_SZ) {
-        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    type = input[0];
-    size = (input[1] << 16) | (input[2] << 8) | input[3];
-
-    input     += HANDSHAKE_HEADER_SZ;
-    *sslBytes -= HANDSHAKE_HEADER_SZ;
-    startBytes = *sslBytes;
-
-    if (*sslBytes < size) {
-        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    /* A session's arrays are released when the handshake is completed. */
-    if (session->sslServer->arrays == NULL &&
-        session->sslClient->arrays == NULL) {
-
-        SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-#ifdef HAVE_EXTENDED_MASTER
-    if (session->hash) {
-        if (HashUpdate(session->hash, input, size) != 0) {
-            SetError(EXTENDED_MASTER_HASH_STR, error,
-                     session, FATAL_ERROR_STATE);
-            return -1;
-        }
-    }
-#endif
-
-    switch (type) {
-        case hello_verify_request:
-            Trace(GOT_HELLO_VERIFY_STR);
-            break;
-        case hello_request:
-            Trace(GOT_HELLO_REQUEST_STR);
-            break;
-        case session_ticket:
-            Trace(GOT_SESSION_TICKET_STR);
-            ret = ProcessSessionTicket(input, sslBytes, session, error);
-            break;
-        case server_hello:
-            Trace(GOT_SERVER_HELLO_STR);
-            ret = ProcessServerHello(size, input, sslBytes, session, error);
-            break;
-        case certificate_request:
-            Trace(GOT_CERT_REQ_STR);
-            break;
-        case server_key_exchange:
-            Trace(GOT_SERVER_KEY_EX_STR);
-            /* can't know temp key passively */
-            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
-            ret = -1;
-            break;
-        case certificate:
-            Trace(GOT_CERT_STR);
-            break;
-        case server_hello_done:
-            Trace(GOT_SERVER_HELLO_DONE_STR);
-            break;
-        case finished:
-            Trace(GOT_FINISHED_STR);
-            ret = ProcessFinished(input, size, sslBytes, session, error);
-            break;
-        case client_hello:
-            Trace(GOT_CLIENT_HELLO_STR);
-            ret = ProcessClientHello(input, sslBytes, session, error);
-            break;
-        case client_key_exchange:
-            Trace(GOT_CLIENT_KEY_EX_STR);
-#ifdef HAVE_EXTENDED_MASTER
-            if (session->flags.expectEms && session->hash != NULL) {
-                if (HashCopy(session->sslServer->hsHashes,
-                             session->hash) == 0 &&
-                    HashCopy(session->sslClient->hsHashes,
-                             session->hash) == 0) {
-
-                    session->sslServer->options.haveEMS = 1;
-                    session->sslClient->options.haveEMS = 1;
-                }
-                else {
-                    SetError(EXTENDED_MASTER_HASH_STR, error,
-                             session, FATAL_ERROR_STATE);
-                    ret = -1;
-                }
-                XMEMSET(session->hash, 0, sizeof(HsHashes));
-                free(session->hash);
-                session->hash = NULL;
-            }
-            else {
-                session->sslServer->options.haveEMS = 0;
-                session->sslClient->options.haveEMS = 0;
-            }
-#endif
-            if (ret == 0)
-                ret = ProcessClientKeyExchange(input, sslBytes, session, error);
-            break;
-        case certificate_verify:
-            Trace(GOT_CERT_VER_STR);
-            break;
-        case certificate_status:
-            Trace(GOT_CERT_STATUS_STR);
-            break;
-        default:
-            SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
-            return -1;
-    }
-
-    *sslBytes = startBytes - size;  /* actual bytes of full process */
-
-    return ret;
-}
-
-
-/* Decrypt input into plain output, 0 on success */
-static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
-{
-    int ret = 0;
-
-    (void)output;
-    (void)input;
-    (void)sz;
-
-    switch (ssl->specs.bulk_cipher_algorithm) {
-        #ifdef BUILD_ARC4
-        case wolfssl_rc4:
-            wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
-            break;
-        #endif
-
-        #ifdef BUILD_DES3
-        case wolfssl_triple_des:
-            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
-            break;
-        #endif
-
-        #ifdef BUILD_AES
-        case wolfssl_aes:
-            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
-            break;
-        #endif
-
-        #ifdef HAVE_HC128
-        case wolfssl_hc128:
-            wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
-            break;
-        #endif
-
-        #ifdef BUILD_RABBIT
-        case wolfssl_rabbit:
-            wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
-            break;
-        #endif
-
-        #ifdef HAVE_CAMELLIA
-        case wolfssl_camellia:
-            wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
-            break;
-        #endif
-
-        #ifdef HAVE_IDEA
-        case wolfssl_idea:
-            wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
-            break;
-        #endif
-
-        #ifdef HAVE_AESGCM
-        case wolfssl_aes_gcm:
-            if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
-            {
-                /* scratch buffer, sniffer ignores auth tag*/
-                byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
-
-                byte nonce[AESGCM_NONCE_SZ];
-                XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
-                XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
-
-                if (wc_AesGcmEncrypt(ssl->decrypt.aes,
-                            output,
-                            input + AESGCM_EXP_IV_SZ,
-                            sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
-                            nonce, AESGCM_NONCE_SZ,
-                            authTag, sizeof(authTag),
-                            NULL, 0) < 0) {
-                    Trace(BAD_DECRYPT);
-                    ret = -1;
-                }
-                ForceZero(nonce, AESGCM_NONCE_SZ);
-            }
-            else {
-                Trace(BAD_DECRYPT_SIZE);
-                ret = -1;
-            }
-            break;
-         #endif
-
-        default:
-            Trace(BAD_DECRYPT_TYPE);
-            ret = -1;
-            break;
-    }
-
-    return ret;
-}
-
-
-/* Decrypt input message into output, adjust output steam if needed */
-static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
-                                  byte* output, int* error, int* advance)
-{
-    int ivExtra = 0;
-
-    int ret = Decrypt(ssl, output, input, sz);
-    if (ret != 0) {
-        *error = ret;
-        return NULL;
-    }
-    ssl->keys.encryptSz = sz;
-    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
-        output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
-        ivExtra = ssl->specs.block_size;
-        *advance = ssl->specs.block_size;
-    }
-
-    if (ssl->specs.cipher_type == aead) {
-        *advance = ssl->specs.aead_mac_size;
-        ssl->keys.padSz = ssl->specs.aead_mac_size;
-    }
-    else
-        ssl->keys.padSz = ssl->specs.hash_size;
-
-    if (ssl->specs.cipher_type == block)
-        ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
-
-    return output;
-}
-
-
-/* remove session from table, use rowHint if no info (means we have a lock) */
-static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
-                        TcpInfo* tcpInfo, word32 rowHint)
-{
-    SnifferSession* previous = 0;
-    SnifferSession* current;
-    word32          row = rowHint;
-    int             haveLock = 0;
-
-    if (ipInfo && tcpInfo)
-        row = SessionHash(ipInfo, tcpInfo);
-    else
-        haveLock = 1;
-
-    assert(row <= HASH_SIZE);
-    Trace(REMOVE_SESSION_STR);
-
-    if (!haveLock)
-        wc_LockMutex(&SessionMutex);
-
-    current = SessionTable[row];
-
-    while (current) {
-        if (current == session) {
-            if (previous)
-                previous->next = current->next;
-            else
-                SessionTable[row] = current->next;
-            FreeSnifferSession(session);
-            TraceRemovedSession();
-            break;
-        }
-        previous = current;
-        current  = current->next;
-    }
-
-    if (!haveLock)
-        wc_UnLockMutex(&SessionMutex);
-}
-
-
-/* Remove stale sessions from the Session Table, have a lock */
-static void RemoveStaleSessions(void)
-{
-    word32 i;
-    SnifferSession* session;
-
-    for (i = 0; i < HASH_SIZE; i++) {
-        session = SessionTable[i];
-        while (session) {
-            SnifferSession* next = session->next;
-            if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
-                TraceStaleSession();
-                RemoveSession(session, NULL, NULL, i);
-            }
-            session = next;
-        }
-    }
-}
-
-
-/* Create a new Sniffer Session */
-static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
-                                     char* error)
-{
-    SnifferSession* session = 0;
-    int row;
-
-    Trace(NEW_SESSION_STR);
-    /* create a new one */
-    session = (SnifferSession*)malloc(sizeof(SnifferSession));
-    if (session == NULL) {
-        SetError(MEMORY_STR, error, NULL, 0);
-        return 0;
-    }
-    InitSession(session);
-#ifdef HAVE_EXTENDED_MASTER
-    {
-        HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
-        if (newHash == NULL) {
-            SetError(MEMORY_STR, error, NULL, 0);
-            free(session);
-            return 0;
-        }
-        if (HashInit(newHash) != 0) {
-            SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
-            free(session);
-            return 0;
-        }
-        session->hash = newHash;
-    }
-#endif
-    session->server  = ipInfo->dst;
-    session->client  = ipInfo->src;
-    session->srvPort = (word16)tcpInfo->dstPort;
-    session->cliPort = (word16)tcpInfo->srcPort;
-    session->cliSeqStart = tcpInfo->sequence;
-    session->cliExpected = 1;  /* relative */
-    session->lastUsed= time(NULL);
-
-    session->context = GetSnifferServer(ipInfo, tcpInfo);
-    if (session->context == NULL) {
-        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
-        free(session);
-        return 0;
-    }
-
-    session->sslServer = SSL_new(session->context->ctx);
-    if (session->sslServer == NULL) {
-        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
-        free(session);
-        return 0;
-    }
-    session->sslClient = SSL_new(session->context->ctx);
-    if (session->sslClient == NULL) {
-        SSL_free(session->sslServer);
-        session->sslServer = 0;
-
-        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
-        free(session);
-        return 0;
-    }
-    /* put server back into server mode */
-    session->sslServer->options.side = WOLFSSL_SERVER_END;
-
-    row = SessionHash(ipInfo, tcpInfo);
-
-    /* add it to the session table */
-    wc_LockMutex(&SessionMutex);
-
-    session->next = SessionTable[row];
-    SessionTable[row] = session;
-
-    SessionCount++;
-
-    if ( (SessionCount % HASH_SIZE) == 0) {
-        TraceFindingStale();
-        RemoveStaleSessions();
-    }
-
-    wc_UnLockMutex(&SessionMutex);
-
-    /* determine headed side */
-    if (ipInfo->dst == session->context->server &&
-        tcpInfo->dstPort == session->context->port)
-        session->flags.side = WOLFSSL_SERVER_END;
-    else
-        session->flags.side = WOLFSSL_CLIENT_END;
-
-    return session;
-}
-
-
-#ifdef OLD_HELLO_ALLOWED
-
-/* Process Old Client Hello Input */
-static int DoOldHello(SnifferSession* session, const byte* sslFrame,
-                      int* rhSize, int* sslBytes, char* error)
-{
-    const byte* input = sslFrame;
-    byte        b0, b1;
-    word32      idx = 0;
-    int         ret;
-
-    Trace(GOT_OLD_CLIENT_HELLO_STR);
-    session->flags.clientHello = 1;    /* don't process again */
-    b0 = *input++;
-    b1 = *input++;
-    *sslBytes -= 2;
-    *rhSize = ((b0 & 0x7f) << 8) | b1;
-
-    if (*rhSize > *sslBytes) {
-        SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
-                                (word16)*rhSize);
-    if (ret < 0 && ret != MATCH_SUITE_ERROR) {
-        SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-
-    Trace(OLD_CLIENT_OK_STR);
-    XMEMCPY(session->sslClient->arrays->clientRandom,
-           session->sslServer->arrays->clientRandom, RAN_LEN);
-
-    *sslBytes -= *rhSize;
-    return 0;
-}
-
-#endif /* OLD_HELLO_ALLOWED */
-
-
-#if 0
-/* Calculate the TCP checksum, see RFC 1071 */
-/* return 0 for success, -1 on error */
-/* can be called from decode() with
-   TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
-   could also add a 64bit version if type available and using this
-*/
-int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
-                const byte* packet)
-{
-    TcpPseudoHdr  pseudo;
-    int           count = PSEUDO_HDR_SZ;
-    const word16* data = (word16*)&pseudo;
-    word32        sum = 0;
-    word16        checksum;
-
-    pseudo.src = ipInfo->src;
-    pseudo.dst = ipInfo->dst;
-    pseudo.rsv = 0;
-    pseudo.protocol = TCP_PROTO;
-    pseudo.length = htons(tcpInfo->length + dataLen);
-
-    /* pseudo header sum */
-    while (count >= 2) {
-        sum   += *data++;
-        count -= 2;
-    }
-
-    count = tcpInfo->length + dataLen;
-    data = (word16*)packet;
-
-    /* main sum */
-    while (count > 1) {
-        sum   += *data++;
-        count -=2;
-    }
-
-    /* get left-over, if any */
-    packet = (byte*)data;
-    if (count > 0) {
-        sum += *packet;
-    }
-
-    /* fold 32bit sum into 16 bits */
-    while (sum >> 16)
-        sum = (sum & 0xffff) + (sum >> 16);
-
-    checksum = (word16)~sum;
-    /* checksum should now equal 0, since included already calcd checksum */
-    /* field, but tcp checksum offloading could negate calculation */
-    if (checksum == 0)
-        return 0;
-    return -1;
-}
-#endif
-
-
-/* Check IP and TCP headers, set payload */
-/* returns 0 on success, -1 on error */
-static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
-                  int length, const byte** sslFrame, int* sslBytes, char* error)
-{
-    TraceHeader();
-    TracePacket();
-
-    /* ip header */
-    if (length < IP_HDR_SZ) {
-        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
-        return -1;
-    }
-    if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
-        return -1;
-
-    /* tcp header */
-    if (length < (ipInfo->length + TCP_HDR_SZ)) {
-        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
-        return -1;
-    }
-    if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
-        return -1;
-
-    /* setup */
-    *sslFrame = packet + ipInfo->length + tcpInfo->length;
-    if (*sslFrame > packet + length) {
-        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
-        return -1;
-    }
-    *sslBytes = (int)(packet + length - *sslFrame);
-
-    return 0;
-}
-
-
-/* Create or Find existing session */
-/* returns 0 on success (continue), -1 on error, 1 on success (end) */
-static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
-                        SnifferSession** session, char* error)
-{
-    /* create a new SnifferSession on client SYN */
-    if (tcpInfo->syn && !tcpInfo->ack) {
-        TraceClientSyn(tcpInfo->sequence);
-        *session = CreateSession(ipInfo, tcpInfo, error);
-        if (*session == NULL) {
-            *session = GetSnifferSession(ipInfo, tcpInfo);
-            /* already had existing, so OK */
-            if (*session)
-                return 1;
-
-            SetError(MEMORY_STR, error, NULL, 0);
-            return -1;
-        }
-        return 1;
-    }
-    /* get existing sniffer session */
-    else {
-        *session = GetSnifferSession(ipInfo, tcpInfo);
-        if (*session == NULL) {
-            /* don't worry about extraneous RST or duplicate FINs */
-            if (tcpInfo->fin || tcpInfo->rst)
-                return 1;
-            /* don't worry about duplicate ACKs either */
-            if (sslBytes == 0 && tcpInfo->ack)
-                return 1;
-
-            SetError(BAD_SESSION_STR, error, NULL, 0);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-
-/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
-static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
-                                  int* bytesLeft)
-{
-    PacketBuffer* pb;
-
-    int added = end - *begin + 1;
-    assert(*begin <= end);
-
-    pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
-    if (pb == NULL) return NULL;
-
-    pb->next  = 0;
-    pb->begin = *begin;
-    pb->end   = end;
-    pb->data = (byte*)malloc(added);
-
-    if (pb->data == NULL) {
-        free(pb);
-        return NULL;
-    }
-    XMEMCPY(pb->data, data, added);
-
-    *bytesLeft -= added;
-    *begin      = pb->end + 1;
-
-    return pb;
-}
-
-
-/* Add sslFrame to Reassembly List */
-/* returns 1 (end) on success, -1, on error */
-static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
-                           int sslBytes, SnifferSession* session, char* error)
-{
-    PacketBuffer*  add;
-    PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
-                       &session->cliReassemblyList: &session->srvReassemblyList;
-    PacketBuffer*  curr = *front;
-    PacketBuffer*  prev = curr;
-
-    word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
-                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
-    word32  startSeq = seq;
-    word32  added;
-    int     bytesLeft = sslBytes;  /* could be overlapping fragment */
-
-    /* if list is empty add full frame to front */
-    if (!curr) {
-        if (MaxRecoveryMemory != -1 &&
-                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
-            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
-        if (add == NULL) {
-            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        *front = add;
-        *reassemblyMemory += sslBytes;
-        return 1;
-    }
-
-    /* add to front if before current front, up to next->begin */
-    if (seq < curr->begin) {
-        word32 end = seq + sslBytes - 1;
-
-        if (end >= curr->begin)
-            end = curr->begin - 1;
-
-        if (MaxRecoveryMemory -1 &&
-                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
-            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
-        if (add == NULL) {
-            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        add->next = curr;
-        *front = add;
-        *reassemblyMemory += sslBytes;
-    }
-
-    /* while we have bytes left, try to find a gap to fill */
-    while (bytesLeft > 0) {
-        /* get previous packet in list */
-        while (curr && (seq >= curr->begin)) {
-            prev = curr;
-            curr = curr->next;
-        }
-
-        /* don't add  duplicate data */
-        if (prev->end >= seq) {
-            if ( (seq + bytesLeft - 1) <= prev->end)
-                return 1;
-            seq = prev->end + 1;
-            bytesLeft = startSeq + sslBytes - seq;
-        }
-
-        if (!curr)
-            /* we're at the end */
-            added = bytesLeft;
-        else
-            /* we're in between two frames */
-            added = min((word32)bytesLeft, curr->begin - seq);
-
-        /* data already there */
-        if (added == 0)
-            continue;
-
-        if (MaxRecoveryMemory != -1 &&
-                         (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
-            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
-                           &bytesLeft);
-        if (add == NULL) {
-            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        add->next  = prev->next;
-        prev->next = add;
-        *reassemblyMemory += added;
-    }
-    return 1;
-}
-
-
-/* Add out of order FIN capture */
-/* returns 1 for success (end) */
-static int AddFinCapture(SnifferSession* session, word32 sequence)
-{
-    if (session->flags.side == WOLFSSL_SERVER_END) {
-        if (session->finCaputre.cliCounted == 0)
-            session->finCaputre.cliFinSeq = sequence;
-    }
-    else {
-        if (session->finCaputre.srvCounted == 0)
-            session->finCaputre.srvFinSeq = sequence;
-    }
-    return 1;
-}
-
-
-/* Adjust incoming sequence based on side */
-/* returns 0 on success (continue), -1 on error, 1 on success (end) */
-static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
-                          int* sslBytes, const byte** sslFrame, char* error)
-{
-    word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                     session->cliSeqStart :session->srvSeqStart;
-    word32  real     = tcpInfo->sequence - seqStart;
-    word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                  &session->cliExpected : &session->srvExpected;
-    PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
-                        session->cliReassemblyList : session->srvReassemblyList;
-    byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                session->flags.srvSkipPartial :
-                                session->flags.cliSkipPartial;
-
-    /* handle rollover of sequence */
-    if (tcpInfo->sequence < seqStart)
-        real = 0xffffffffU - seqStart + tcpInfo->sequence;
-
-    TraceRelativeSequence(*expected, real);
-
-    if (real < *expected) {
-        Trace(DUPLICATE_STR);
-        if (real + *sslBytes > *expected) {
-            int overlap = *expected - real;
-            Trace(OVERLAP_DUPLICATE_STR);
-
-            /* adjust to expected, remove duplicate */
-            *sslFrame += overlap;
-            *sslBytes -= overlap;
-
-            /* The following conditional block is duplicated below. It is the
-             * same action but for a different setup case. If changing this
-             * block be sure to also update the block below. */
-            if (reassemblyList) {
-                word32 newEnd = *expected + *sslBytes;
-
-                if (newEnd > reassemblyList->begin) {
-                    Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
-
-                    /* remove bytes already on reassembly list */
-                    *sslBytes -= newEnd - reassemblyList->begin;
-                }
-                if (newEnd > reassemblyList->end) {
-                    Trace(OVERLAP_REASSEMBLY_END_STR);
-
-                    /* may be past reassembly list end (could have more on list)
-                       so try to add what's past the front->end */
-                    AddToReassembly(session->flags.side, reassemblyList->end +1,
-                                *sslFrame + reassemblyList->end - *expected + 1,
-                                 newEnd - reassemblyList->end, session, error);
-                }
-            }
-        }
-        else
-            return 1;
-    }
-    else if (real > *expected) {
-        Trace(OUT_OF_ORDER_STR);
-        if (*sslBytes > 0) {
-            int addResult = AddToReassembly(session->flags.side, real,
-                                          *sslFrame, *sslBytes, session, error);
-            if (skipPartial) {
-                *sslBytes = 0;
-                return 0;
-            }
-            else
-                return addResult;
-        }
-        else if (tcpInfo->fin)
-            return AddFinCapture(session, real);
-    }
-    else if (*sslBytes > 0) {
-        if (skipPartial) {
-            AddToReassembly(session->flags.side, real,
-                                          *sslFrame, *sslBytes, session, error);
-            *expected += *sslBytes;
-            *sslBytes = 0;
-            if (tcpInfo->fin)
-                *expected += 1;
-            return 0;
-        }
-        /* The following conditional block is duplicated above. It is the
-         * same action but for a different setup case. If changing this
-         * block be sure to also update the block above. */
-        else if (reassemblyList) {
-            word32 newEnd = *expected + *sslBytes;
-
-            if (newEnd > reassemblyList->begin) {
-                Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
-
-                /* remove bytes already on reassembly list */
-                *sslBytes -= newEnd - reassemblyList->begin;
-            }
-            if (newEnd > reassemblyList->end) {
-                Trace(OVERLAP_REASSEMBLY_END_STR);
-
-                /* may be past reassembly list end (could have more on list)
-                   so try to add what's past the front->end */
-                AddToReassembly(session->flags.side, reassemblyList->end +1,
-                            *sslFrame + reassemblyList->end - *expected + 1,
-                             newEnd - reassemblyList->end, session, error);
-            }
-        }
-    }
-    /* got expected sequence */
-    *expected += *sslBytes;
-    if (tcpInfo->fin)
-        *expected += 1;
-
-    return 0;
-}
-
-
-static int FindNextRecordInAssembly(SnifferSession* session,
-                                    const byte** sslFrame, int* sslBytes,
-                                    const byte** end, char* error)
-{
-    PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                    &session->cliReassemblyList :
-                                    &session->srvReassemblyList;
-    PacketBuffer*       curr = *front;
-    PacketBuffer*       prev = NULL;
-    byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                    &session->flags.srvSkipPartial :
-                                    &session->flags.cliSkipPartial;
-    word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                    &session->cliReassemblyMemory :
-                                    &session->srvReassemblyMemory;
-    SSL*                 ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                    session->sslServer :
-                                    session->sslClient;
-    ProtocolVersion       pv = ssl->version;
-    word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                    &session->cliExpected :
-                                    &session->srvExpected;
-
-    while (curr != NULL) {
-        *expected = curr->end + 1;
-
-        if (curr->data[0] == application_data &&
-            curr->data[1] == pv.major &&
-            curr->data[2] == pv.minor) {
-
-            if (ssl->buffers.inputBuffer.length > 0)
-                Trace(DROPPING_PARTIAL_RECORD);
-
-            *sslBytes = curr->end - curr->begin + 1;
-            if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
-                if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
-                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-                    return -1;
-                }
-            }
-
-            XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
-
-            *front = curr->next;
-            *reassemblyMemory -= *sslBytes;
-            FreePacketBuffer(curr);
-
-            ssl->buffers.inputBuffer.length = *sslBytes;
-            *sslFrame = ssl->buffers.inputBuffer.buffer;
-            *end = *sslFrame + *sslBytes;
-            *skipPartial = 0;
-
-            return 0;
-        }
-        else if (ssl->specs.cipher_type == block) {
-            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
-#ifdef BUILD_AES
-                wc_AesSetIV(ssl->decrypt.aes,
-                            curr->data + curr->end - curr->begin
-                                       - ssl->specs.block_size + 1);
-#endif
-            }
-            else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
-#ifdef BUILD_DES3
-                wc_Des3_SetIV(ssl->decrypt.des3,
-                              curr->data + curr->end - curr->begin
-                                         - ssl->specs.block_size + 1);
-#endif
-            }
-        }
-
-        Trace(DROPPING_LOST_FRAG_STR);
-        prev = curr;
-        curr = curr->next;
-        *reassemblyMemory -= (prev->end - prev->begin + 1);
-        FreePacketBuffer(prev);
-    }
-
-    *front = curr;
-
-    return 0;
-}
-
-
-static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
-{
-    word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                &session->srvExpected : &session->cliExpected;
-    PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                session->srvReassemblyList :
-                                session->cliReassemblyList;
-    byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
-                                &session->flags.srvSkipPartial :
-                                &session->flags.cliSkipPartial;
-
-    *skipPartial = 1;
-    if (list != NULL)
-        *expected = list->begin;
-    else {
-        word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                session->srvSeqStart : session->cliSeqStart;
-        word32     real = tcpInfo->ackNumber - seqStart;
-
-        *expected = real;
-    }
-
-    return 1;
-}
-
-
-/* Check latest ack number for missing packets
-   return 0 ok, <0 on error */
-static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
-{
-    if (tcpInfo->ack) {
-        word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                     session->srvSeqStart :session->cliSeqStart;
-        word32  real     = tcpInfo->ackNumber - seqStart;
-        word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                  session->srvExpected : session->cliExpected;
-
-        /* handle rollover of sequence */
-        if (tcpInfo->ackNumber < seqStart)
-            real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
-
-        TraceAck(real, expected);
-
-        if (real > expected)
-            return -1;  /* we missed a packet, ACKing data we never saw */
-    }
-    return 0;
-}
-
-
-/* Check TCP Sequence status */
-/* returns 0 on success (continue), -1 on error, 1 on success (end) */
-static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
-                         SnifferSession* session, int* sslBytes,
-                         const byte** sslFrame, char* error)
-{
-    int actualLen;
-    byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
-                        &session->flags.cliAckFault :
-                        &session->flags.srvAckFault;
-
-    /* init SEQ from server to client */
-    if (tcpInfo->syn && tcpInfo->ack) {
-        session->srvSeqStart = tcpInfo->sequence;
-        session->srvExpected = 1;
-        TraceServerSyn(tcpInfo->sequence);
-        return 1;
-    }
-
-    /* adjust potential ethernet trailer */
-    actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
-    if (*sslBytes > actualLen) {
-        *sslBytes = actualLen;
-    }
-
-    TraceSequence(tcpInfo->sequence, *sslBytes);
-    if (CheckAck(tcpInfo, session) < 0) {
-        if (!RecoveryEnabled) {
-            UpdateMissedDataSessions();
-            SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        else {
-            SetError(ACK_MISSED_STR, error, session, 0);
-            if (*ackFault == 0) {
-                *ackFault = 1;
-                UpdateMissedDataSessions();
-            }
-            return FixSequence(tcpInfo, session);
-        }
-    }
-
-    if (*ackFault) {
-        Trace(CLEAR_ACK_FAULT);
-        *ackFault = 0;
-    }
-
-    return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
-}
-
-
-/* Check Status before record processing */
-/* returns 0 on success (continue), -1 on error, 1 on success (end) */
-static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
-                          const byte** sslFrame, SnifferSession** session,
-                          int* sslBytes, const byte** end, char* error)
-{
-    word32 length;
-    SSL*  ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
-                                  (*session)->sslServer : (*session)->sslClient;
-    byte  skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
-                        (*session)->flags.srvSkipPartial :
-                        (*session)->flags.cliSkipPartial;
-    /* remove SnifferSession on 2nd FIN or RST */
-    if (tcpInfo->fin || tcpInfo->rst) {
-        /* flag FIN and RST */
-        if (tcpInfo->fin)
-            (*session)->flags.finCount += 1;
-        else if (tcpInfo->rst)
-            (*session)->flags.finCount += 2;
-
-        if ((*session)->flags.finCount >= 2) {
-            RemoveSession(*session, ipInfo, tcpInfo, 0);
-            *session = NULL;
-            return 1;
-        }
-    }
-
-    if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
-        SetError(FATAL_ERROR_STR, error, NULL, 0);
-        return -1;
-    }
-
-    if (skipPartial) {
-        if (FindNextRecordInAssembly(*session,
-                                     sslFrame, sslBytes, end, error) < 0) {
-            return -1;
-        }
-    }
-
-    if (*sslBytes == 0) {
-        Trace(NO_DATA_STR);
-        return 1;
-    }
-
-    /* if current partial data, add to end of partial */
-    /* if skipping, the data is already at the end of partial */
-    if ( !skipPartial &&
-         (length = ssl->buffers.inputBuffer.length) ) {
-        Trace(PARTIAL_ADD_STR);
-
-        if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
-            if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
-                SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
-                return -1;
-            }
-        }
-        XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
-        *sslBytes += length;
-        ssl->buffers.inputBuffer.length = *sslBytes;
-        *sslFrame = ssl->buffers.inputBuffer.buffer;
-        *end = *sslFrame + *sslBytes;
-    }
-
-    if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
-        /* Sanity check the packet for an old style client hello. */
-        int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
-
-        if ((rhSize <= (*sslBytes - 2)) &&
-            (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
-#ifdef OLD_HELLO_ALLOWED
-        int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
-        if (ret < 0)
-            return -1;  /* error already set */
-        if (*sslBytes <= 0)
-            return 1;
-#endif
-        }
-        else {
-#ifdef STARTTLS_ALLOWED
-            return 1;
-#endif
-        }
-    }
-
-    return 0;
-}
-
-
-/* See if input on the reassembly list is ready for consuming */
-/* returns 1 for TRUE, 0 for FALSE */
-static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
-                         int* sslBytes, const byte** end, char* error)
-{
-    /* sequence and reassembly based on from, not to */
-    int            moreInput = 0;
-    PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
-                      &session->cliReassemblyList : &session->srvReassemblyList;
-    word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                  &session->cliExpected : &session->srvExpected;
-    /* buffer is on receiving end */
-    word32*        length = (session->flags.side == WOLFSSL_SERVER_END) ?
-                               &session->sslServer->buffers.inputBuffer.length :
-                               &session->sslClient->buffers.inputBuffer.length;
-    byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
-                               &session->sslServer->buffers.inputBuffer.buffer :
-                               &session->sslClient->buffers.inputBuffer.buffer;
-    word32*       bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
-                           &session->sslServer->buffers.inputBuffer.bufferSize :
-                           &session->sslClient->buffers.inputBuffer.bufferSize;
-    SSL*               ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
-                            session->sslServer : session->sslClient;
-    word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
-                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
-
-    while (*front && ((*front)->begin == *expected) ) {
-        word32 room = *bufferSize - *length;
-        word32 packetLen = (*front)->end - (*front)->begin + 1;
-
-        if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
-            if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
-                SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-                return 0;
-            }
-            room = *bufferSize - *length;   /* bufferSize is now bigger */
-        }
-
-        if (packetLen <= room) {
-            PacketBuffer* del = *front;
-            byte*         buf = *myBuffer;
-
-            XMEMCPY(&buf[*length], (*front)->data, packetLen);
-            *length   += packetLen;
-            *expected += packetLen;
-
-            /* remove used packet */
-            *front = (*front)->next;
-
-            *reassemblyMemory -= packetLen;
-            FreePacketBuffer(del);
-
-            moreInput = 1;
-        }
-        else
-            break;
-    }
-    if (moreInput) {
-        *sslFrame = *myBuffer;
-        *sslBytes = *length;
-        *end      = *myBuffer + *length;
-    }
-    return moreInput;
-}
-
-
-
-/* Process Message(s) from sslFrame */
-/* return Number of bytes on success, 0 for no data yet, and -1 on error */
-static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
-                          int sslBytes, byte** data, const byte* end,
-                          char* error)
-{
-    const byte*       sslBegin = sslFrame;
-    const byte*       recordEnd;   /* end of record indicator */
-    const byte*       inRecordEnd; /* indicator from input stream not decrypt */
-    RecordLayerHeader rh;
-    int               rhSize = 0;
-    int               ret;
-    int               errCode = 0;
-    int               decoded = 0;      /* bytes stored for user in data */
-    int               notEnough;        /* notEnough bytes yet flag */
-    int               decrypted = 0;    /* was current msg decrypted */
-    SSL*              ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
-                                        session->sslServer : session->sslClient;
-doMessage:
-    notEnough = 0;
-    if (sslBytes < 0) {
-        SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
-        return -1;
-    }
-    if (sslBytes >= RECORD_HEADER_SZ) {
-        if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
-            SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-    }
-    else
-        notEnough = 1;
-
-    if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
-        /* don't have enough input yet to process full SSL record */
-        Trace(PARTIAL_INPUT_STR);
-
-        /* store partial if not there already or we advanced */
-        if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
-            if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
-                if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
-                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-                    return -1;
-                }
-            }
-            XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
-            ssl->buffers.inputBuffer.length = sslBytes;
-        }
-        if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
-            goto doMessage;
-        return decoded;
-    }
-    sslFrame += RECORD_HEADER_SZ;
-    sslBytes -= RECORD_HEADER_SZ;
-    recordEnd = sslFrame + rhSize;   /* may have more than one record */
-    inRecordEnd = recordEnd;
-
-    /* decrypt if needed */
-    if ((session->flags.side == WOLFSSL_SERVER_END &&
-                                               session->flags.serverCipherOn)
-     || (session->flags.side == WOLFSSL_CLIENT_END &&
-                                               session->flags.clientCipherOn)) {
-        int ivAdvance = 0;  /* TLSv1.1 advance amount */
-        if (ssl->decrypt.setup != 1) {
-            SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        if (CheckAvailableSize(ssl, rhSize) < 0) {
-            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-        sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
-                                  ssl->buffers.outputBuffer.buffer, &errCode,
-                                  &ivAdvance);
-        recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
-                                                       should recordEnd */
-        decrypted = 1;
-        if (errCode != 0) {
-            SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
-            return -1;
-        }
-    }
-
-doPart:
-
-    switch ((enum ContentType)rh.type) {
-        case handshake:
-            {
-                int startIdx = sslBytes;
-                int used;
-
-                Trace(GOT_HANDSHAKE_STR);
-                ret = DoHandShake(sslFrame, &sslBytes, session, error);
-                if (ret != 0) {
-                    if (session->flags.fatalError == 0)
-                        SetError(BAD_HANDSHAKE_STR, error, session,
-                                 FATAL_ERROR_STATE);
-                    return -1;
-                }
-
-                /* DoHandShake now fully decrements sslBytes to remaining */
-                used = startIdx - sslBytes;
-                sslFrame += used;
-                if (decrypted)
-                    sslFrame += ssl->keys.padSz;
-            }
-            break;
-        case change_cipher_spec:
-            if (session->flags.side == WOLFSSL_SERVER_END)
-                session->flags.serverCipherOn = 1;
-            else
-                session->flags.clientCipherOn = 1;
-            Trace(GOT_CHANGE_CIPHER_STR);
-            ssl->options.handShakeState = HANDSHAKE_DONE;
-            ssl->options.handShakeDone  = 1;
-
-            sslFrame += 1;
-            sslBytes -= 1;
-
-            break;
-        case application_data:
-            Trace(GOT_APP_DATA_STR);
-            {
-                word32 inOutIdx = 0;
-
-                ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
-                if (ret == 0) {
-                    ret = ssl->buffers.clearOutputBuffer.length;
-                    TraceGotData(ret);
-                    if (ret) {  /* may be blank message */
-                        byte* tmpData;  /* don't leak on realloc free */
-                        /* add an extra byte at end of allocation in case user
-                         * wants to null terminate plaintext */
-                        tmpData = (byte*)realloc(*data, decoded + ret + 1);
-                        if (tmpData == NULL) {
-                            ForceZero(*data, decoded);
-                            free(*data);
-                            *data = NULL;
-                            SetError(MEMORY_STR, error, session,
-                                     FATAL_ERROR_STATE);
-                            return -1;
-                        }
-                        *data = tmpData;
-                        XMEMCPY(*data + decoded,
-                                ssl->buffers.clearOutputBuffer.buffer, ret);
-                        TraceAddedData(ret, decoded);
-                        decoded += ret;
-                        ssl->buffers.clearOutputBuffer.length = 0;
-                    }
-                }
-                else {
-                    SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
-                    return -1;
-                }
-                if (ssl->buffers.outputBuffer.dynamicFlag)
-                    ShrinkOutputBuffer(ssl);
-
-                sslFrame += inOutIdx;
-                sslBytes -= inOutIdx;
-            }
-            break;
-        case alert:
-            Trace(GOT_ALERT_STR);
-            sslFrame += rhSize;
-            sslBytes -= rhSize;
-            break;
-        case no_type:
-        default:
-            SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
-            return -1;
-    }
-
-    /* do we have another msg in record ? */
-    if (sslFrame < recordEnd) {
-        Trace(ANOTHER_MSG_STR);
-        goto doPart;
-    }
-
-    /* back to input stream instead of potential decrypt buffer */
-    recordEnd = inRecordEnd;
-
-    /* do we have more records ? */
-    if (recordEnd < end) {
-        Trace(ANOTHER_MSG_STR);
-        sslFrame = recordEnd;
-        sslBytes = (int)(end - recordEnd);
-        goto doMessage;
-    }
-
-    /* clear used input */
-    ssl->buffers.inputBuffer.length = 0;
-
-    /* could have more input ready now */
-    if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
-        goto doMessage;
-
-    if (ssl->buffers.inputBuffer.dynamicFlag)
-        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
-
-    return decoded;
-}
-
-
-/* See if we need to process any pending FIN captures */
-static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
-                            SnifferSession* session)
-{
-    if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
-                                         session->cliExpected) {
-        if (session->finCaputre.cliCounted == 0) {
-            session->flags.finCount += 1;
-            session->finCaputre.cliCounted = 1;
-            TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
-        }
-    }
-
-    if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
-                                         session->srvExpected) {
-        if (session->finCaputre.srvCounted == 0) {
-            session->flags.finCount += 1;
-            session->finCaputre.srvCounted = 1;
-            TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
-        }
-    }
-
-    if (session->flags.finCount >= 2)
-        RemoveSession(session, ipInfo, tcpInfo, 0);
-}
-
-
-/* If session is in fatal error state free resources now
-   return true if removed, 0 otherwise */
-static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
-                              SnifferSession* session, char* error)
-{
-    if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
-        RemoveSession(session, ipInfo, tcpInfo, 0);
-        SetError(FATAL_ERROR_STR, error, NULL, 0);
-        return 1;
-    }
-    return 0;
-}
-
-
-/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
-/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
-int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
-{
-    TcpInfo           tcpInfo;
-    IpInfo            ipInfo;
-    const byte*       sslFrame;
-    const byte*       end = packet + length;
-    int               sslBytes;                /* ssl bytes unconsumed */
-    int               ret;
-    SnifferSession*   session = 0;
-
-    if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
-                     error) != 0)
-        return -1;
-
-    ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
-    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
-    else if (ret == -1) return -1;
-    else if (ret ==  1) return  0;   /* done for now */
-
-    ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
-    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
-    else if (ret == -1) return -1;
-    else if (ret ==  1) return  0;   /* done for now */
-
-    ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
-                         &end, error);
-    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
-    else if (ret == -1) return -1;
-    else if (ret ==  1) return  0;   /* done for now */
-
-    ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
-    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
-    CheckFinCapture(&ipInfo, &tcpInfo, session);
-    return ret;
-}
-
-
-/* Deallocator for the decoded data buffer. */
-/* returns 0 on success, -1 on error */
-int ssl_FreeDecodeBuffer(byte** data, char* error)
-{
-    return ssl_FreeZeroDecodeBuffer(data, 0, error);
-}
-
-
-/* Deallocator for the decoded data buffer, zeros out buffer. */
-/* returns 0 on success, -1 on error */
-int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
-{
-    (void)error;
-
-    if (sz < 0) {
-        return -1;
-    }
-
-    if (data != NULL) {
-        ForceZero(*data, (word32)sz);
-        free(*data);
-        *data = NULL;
-    }
-
-    return 0;
-}
-
-
-/* Enables (if traceFile)/ Disables debug tracing */
-/* returns 0 on success, -1 on error */
-int ssl_Trace(const char* traceFile, char* error)
-{
-    if (traceFile) {
-        TraceFile = fopen(traceFile, "a");
-        if (!TraceFile) {
-            SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
-            return -1;
-        }
-        TraceOn = 1;
-    }
-    else
-        TraceOn = 0;
-
-    return 0;
-}
-
-
-/* Enables/Disables Recovery of missed data if later packets allow
- * maxMemory is number of bytes to use for reassembly buffering per session,
- * -1 means unlimited
- * returns 0 on success, -1 on error */
-int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
-{
-    (void)error;
-
-    RecoveryEnabled = onOff;
-    if (onOff)
-        MaxRecoveryMemory = maxMemory;
-
-    return 0;
-}
-
-
-
-int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
-                        unsigned int* peak,       unsigned int* maxSessions,
-                        unsigned int* missedData, unsigned int* reassemblyMem,
-                        char* error)
-{
-    int ret;
-
-    if (missedData) {
-        wc_LockMutex(&RecoveryMutex);
-        *missedData = MissedDataSessions;
-        wc_UnLockMutex(&RecoveryMutex);
-    }
-
-    if (reassemblyMem) {
-        SnifferSession* session;
-        int i;
-
-        *reassemblyMem = 0;
-        wc_LockMutex(&SessionMutex);
-        for (i = 0; i < HASH_SIZE; i++) {
-            session = SessionTable[i];
-            while (session) {
-                *reassemblyMem += session->cliReassemblyMemory;
-                *reassemblyMem += session->srvReassemblyMemory;
-                session = session->next;
-            }
-        }
-        wc_UnLockMutex(&SessionMutex);
-    }
-
-    ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
-
-    if (ret == WOLFSSL_SUCCESS)
-        return 0;
-    else {
-        SetError(BAD_SESSION_STATS, error, NULL, 0);
-        return -1;
-    }
-}
-
-
-
-#endif /* WOLFSSL_SNIFFER */
-#endif /* WOLFCRYPT_ONLY */
-
+/* sniffer.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+#ifdef WOLFSSL_SNIFFER
+
+#include <assert.h>
+#include <time.h>
+
+#ifndef _WIN32
+  #include <arpa/inet.h>
+#endif
+
+#ifdef _WIN32
+    #define SNPRINTF _snprintf
+#else
+    #define SNPRINTF snprintf
+#endif
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/sniffer.h>
+#include <wolfssl/sniffer_error.h>
+#ifdef NO_INLINE
+    #include <wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifndef WOLFSSL_SNIFFER_TIMEOUT
+    #define WOLFSSL_SNIFFER_TIMEOUT 900
+    /* Cache unclosed Sessions for 15 minutes since last used */
+#endif
+
+/* Misc constants */
+enum {
+    MAX_SERVER_ADDRESS = 128, /* maximum server address length */
+    MAX_SERVER_NAME    = 128, /* maximum server name length */
+    MAX_ERROR_LEN      = 80,  /* maximum error length */
+    ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
+    LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
+    TCP_PROTO          = 6,   /* TCP_PROTOCOL */
+    IP_HDR_SZ          = 20,  /* IP header length, min */
+    TCP_HDR_SZ         = 20,  /* TCP header length, min */
+    IPV4               = 4,   /* IP version 4 */
+    TCP_PROTOCOL       = 6,   /* TCP Protocol id */
+    TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
+    HASH_SIZE          = 499, /* Session Hash Table Rows */
+    PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
+    FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
+    TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
+    EXT_TYPE_SZ        = 2,   /* Extension length */
+    MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
+                         MTU_EXTRA,  /* Max input sz of reassembly */
+    EXT_MASTER_SECRET  = 0x17, /* Extended Master Secret Extension ID */
+    TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
+};
+
+
+#ifdef _WIN32
+
+static HMODULE dllModule;  /* for error string resources */
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+                       DWORD  ul_reason_for_call,
+                       LPVOID lpReserved
+                     )
+{
+	static int didInit = 0;
+
+    switch (ul_reason_for_call)
+    {
+    case DLL_PROCESS_ATTACH:
+		if (didInit == 0) {
+            dllModule = hModule;
+			ssl_InitSniffer();
+			didInit = 1;
+		}
+        break;
+    case DLL_THREAD_ATTACH:
+        break;
+    case DLL_THREAD_DETACH:
+        break;
+    case DLL_PROCESS_DETACH:
+		if (didInit) {
+			ssl_FreeSniffer();
+			didInit = 0;
+		}
+        break;
+    }
+    return TRUE;
+}
+
+#endif /* _WIN32 */
+
+
+static int TraceOn = 0;         /* Trace is off by default */
+static FILE* TraceFile = 0;
+
+
+/* windows uses .rc table for this */
+#ifndef _WIN32
+
+static const char* const msgTable[] =
+{
+    /* 1 */
+    "Out of Memory",
+    "New SSL Sniffer Server Registered",
+    "Checking IP Header",
+    "SSL Sniffer Server Not Registered",
+    "Checking TCP Header",
+
+    /* 6 */
+    "SSL Sniffer Server Port Not Registered",
+    "RSA Private Decrypt Error",
+    "RSA Private Decode Error",
+    "Set Cipher Spec Error",
+    "Server Hello Input Malformed",
+
+    /* 11 */
+    "Couldn't Resume Session Error",
+    "Server Did Resumption",
+    "Client Hello Input Malformed",
+    "Client Trying to Resume",
+    "Handshake Input Malformed",
+
+    /* 16 */
+    "Got Hello Verify msg",
+    "Got Server Hello msg",
+    "Got Cert Request msg",
+    "Got Server Key Exchange msg",
+    "Got Cert msg",
+
+    /* 21 */
+    "Got Server Hello Done msg",
+    "Got Finished msg",
+    "Got Client Hello msg",
+    "Got Client Key Exchange msg",
+    "Got Cert Verify msg",
+
+    /* 26 */
+    "Got Unknown Handshake msg",
+    "New SSL Sniffer Session created",
+    "Couldn't create new SSL",
+    "Got a Packet to decode",
+    "No data present",
+
+    /* 31 */
+    "Session Not Found",
+    "Got an Old Client Hello msg",
+    "Old Client Hello Input Malformed",
+    "Old Client Hello OK",
+    "Bad Old Client Hello",
+
+    /* 36 */
+    "Bad Record Header",
+    "Record Header Input Malformed",
+    "Got a HandShake msg",
+    "Bad HandShake msg",
+    "Got a Change Cipher Spec msg",
+
+    /* 41 */
+    "Got Application Data msg",
+    "Bad Application Data",
+    "Got an Alert msg",
+    "Another msg to Process",
+    "Removing Session From Table",
+
+    /* 46 */
+    "Bad Key File",
+    "Wrong IP Version",
+    "Wrong Protocol type",
+    "Packet Short for header processing",
+    "Got Unknown Record Type",
+
+    /* 51 */
+    "Can't Open Trace File",
+    "Session in Fatal Error State",
+    "Partial SSL record received",
+    "Buffer Error, malformed input",
+    "Added to Partial Input",
+
+    /* 56 */
+    "Received a Duplicate Packet",
+    "Received an Out of Order Packet",
+    "Received an Overlap Duplicate Packet",
+    "Received an Overlap Reassembly Begin Duplicate Packet",
+    "Received an Overlap Reassembly End Duplicate Packet",
+
+    /* 61 */
+    "Missed the Client Hello Entirely",
+    "Got Hello Request msg",
+    "Got Session Ticket msg",
+    "Bad Input",
+    "Bad Decrypt Type",
+
+    /* 66 */
+    "Bad Finished Message Processing",
+    "Bad Compression Type",
+    "Bad DeriveKeys Error",
+    "Saw ACK for Missing Packet Error",
+    "Bad Decrypt Operation",
+
+    /* 71 */
+    "Decrypt Keys Not Set Up",
+    "Late Key Load Error",
+    "Got Certificate Status msg",
+    "RSA Key Missing Error",
+    "Secure Renegotiation Not Supported",
+
+    /* 76 */
+    "Get Session Stats Failure",
+    "Reassembly Buffer Size Exceeded",
+    "Dropping Lost Fragment",
+    "Dropping Partial Record",
+    "Clear ACK Fault",
+
+    /* 81 */
+    "Bad Decrypt Size",
+    "Extended Master Secret Hash Error"
+};
+
+
+/* *nix version uses table above */
+static void GetError(int idx, char* str)
+{
+    XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
+}
+
+
+#else /* _WIN32 */
+
+
+/* Windows version uses .rc table */
+static void GetError(int idx, char* buffer)
+{
+    if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
+        buffer[0] = 0;
+}
+
+
+#endif /* _WIN32 */
+
+
+/* Packet Buffer for reassembly list and ready list */
+typedef struct PacketBuffer {
+    word32  begin;      /* relative sequence begin */
+    word32  end;        /* relative sequence end   */
+    byte*   data;       /* actual data             */
+    struct PacketBuffer* next; /* next on reassembly list or ready list */
+} PacketBuffer;
+
+
+#ifdef HAVE_SNI
+
+/* NamedKey maps a SNI name to a specific private key */
+typedef struct NamedKey {
+    char             name[MAX_SERVER_NAME];      /* server DNS name */
+    word32           nameSz;                     /* size of server DNS name */
+    byte*            key;                        /* DER private key */
+    word32           keySz;                      /* size of DER private key */
+    struct NamedKey* next;                       /* for list */
+} NamedKey;
+
+#endif
+
+
+/* Sniffer Server holds info for each server/port monitored */
+typedef struct SnifferServer {
+    SSL_CTX*       ctx;                          /* SSL context */
+    char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
+    word32         server;                       /* netowrk order address */
+    int            port;                         /* server port */
+#ifdef HAVE_SNI
+    NamedKey*      namedKeys;                    /* mapping of names and keys */
+    wolfSSL_Mutex  namedKeysMutex;               /* mutex for namedKey list */
+#endif
+    struct SnifferServer* next;                  /* for list */
+} SnifferServer;
+
+
+/* Session Flags */
+typedef struct Flags {
+    byte           side;            /* which end is current packet headed */
+    byte           serverCipherOn;  /* indicates whether cipher is active */
+    byte           clientCipherOn;  /* indicates whether cipher is active */
+    byte           resuming;        /* did this session come from resumption */
+    byte           cached;          /* have we cached this session yet */
+    byte           clientHello;     /* processed client hello yet, for SSLv2 */
+    byte           finCount;        /* get both FINs before removing */
+    byte           fatalError;      /* fatal error state */
+    byte           cliAckFault;     /* client acked unseen data from server */
+    byte           srvAckFault;     /* server acked unseen data from client */
+    byte           cliSkipPartial;  /* client skips partial data to catch up */
+    byte           srvSkipPartial;  /* server skips partial data to catch up */
+#ifdef HAVE_EXTENDED_MASTER
+    byte           expectEms;       /* expect extended master secret */
+#endif
+} Flags;
+
+
+/* Out of Order FIN caputre */
+typedef struct FinCaputre {
+    word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
+    word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
+    byte   cliCounted;              /* did we count yet, detects duplicates */
+    byte   srvCounted;              /* did we count yet, detects duplicates */
+} FinCaputre;
+
+
+typedef struct HsHashes {
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    wc_Sha hashSha;
+#endif
+#ifndef NO_MD5
+    wc_Md5 hashMd5;
+#endif
+#endif
+#ifndef NO_SHA256
+    wc_Sha256 hashSha256;
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384 hashSha384;
+#endif
+} HsHashes;
+
+
+/* Sniffer Session holds info for each client/server SSL/TLS session */
+typedef struct SnifferSession {
+    SnifferServer* context;         /* server context */
+    SSL*           sslServer;       /* SSL server side decode */
+    SSL*           sslClient;       /* SSL client side decode */
+    word32         server;          /* server address in network byte order */
+    word32         client;          /* client address in network byte order */
+    word16         srvPort;         /* server port */
+    word16         cliPort;         /* client port */
+    word32         cliSeqStart;     /* client start sequence */
+    word32         srvSeqStart;     /* server start sequence */
+    word32         cliExpected;     /* client expected sequence (relative) */
+    word32         srvExpected;     /* server expected sequence (relative) */
+    FinCaputre     finCaputre;      /* retain out of order FIN s */
+    Flags          flags;           /* session flags */
+    time_t         lastUsed;          /* last used ticks */
+    PacketBuffer*  cliReassemblyList; /* client out of order packets */
+    PacketBuffer*  srvReassemblyList; /* server out of order packets */
+    word32         cliReassemblyMemory; /* client packet memory used */
+    word32         srvReassemblyMemory; /* server packet memory used */
+    struct SnifferSession* next;      /* for hash table list */
+    byte*          ticketID;          /* mac ID of session ticket */
+#ifdef HAVE_EXTENDED_MASTER
+    HsHashes*       hash;
+#endif
+} SnifferSession;
+
+
+/* Sniffer Server List and mutex */
+static SnifferServer* ServerList = 0;
+static wolfSSL_Mutex ServerListMutex;
+
+
+/* Session Hash Table, mutex, and count */
+static SnifferSession* SessionTable[HASH_SIZE];
+static wolfSSL_Mutex SessionMutex;
+static int SessionCount = 0;
+
+/* Recovery of missed data switches and stats */
+static wolfSSL_Mutex RecoveryMutex;      /* for stats */
+static int RecoveryEnabled    = 0;       /* global switch */
+static int MaxRecoveryMemory  = -1;      /* per session max recovery memory */
+static word32 MissedDataSessions = 0;    /* # of sessions with missed data */
+
+
+static void UpdateMissedDataSessions(void)
+{
+    wc_LockMutex(&RecoveryMutex);
+    MissedDataSessions += 1;
+    wc_UnLockMutex(&RecoveryMutex);
+}
+
+
+/* Initialize overall Sniffer */
+void ssl_InitSniffer(void)
+{
+    wolfSSL_Init();
+    wc_InitMutex(&ServerListMutex);
+    wc_InitMutex(&SessionMutex);
+    wc_InitMutex(&RecoveryMutex);
+}
+
+
+#ifdef HAVE_SNI
+
+/* Free Named Key and the zero out the private key it holds */
+static void FreeNamedKey(NamedKey* in)
+{
+    if (in) {
+        if (in->key) {
+            ForceZero(in->key, in->keySz);
+            free(in->key);
+        }
+        free(in);
+    }
+}
+
+
+static void FreeNamedKeyList(NamedKey* in)
+{
+    NamedKey* next;
+
+    while (in) {
+        next = in->next;
+        FreeNamedKey(in);
+        in = next;
+    }
+}
+
+#endif
+
+
+/* Free Sniffer Server's resources/self */
+static void FreeSnifferServer(SnifferServer* srv)
+{
+    if (srv) {
+#ifdef HAVE_SNI
+        wc_LockMutex(&srv->namedKeysMutex);
+        FreeNamedKeyList(srv->namedKeys);
+        wc_UnLockMutex(&srv->namedKeysMutex);
+        wc_FreeMutex(&srv->namedKeysMutex);
+#endif
+        SSL_CTX_free(srv->ctx);
+    }
+    free(srv);
+}
+
+
+/* free PacketBuffer's resources/self */
+static void FreePacketBuffer(PacketBuffer* del)
+{
+    if (del) {
+        free(del->data);
+        free(del);
+    }
+}
+
+
+/* remove PacketBuffer List */
+static void FreePacketList(PacketBuffer* in)
+{
+    if (in) {
+        PacketBuffer* del;
+        PacketBuffer* packet = in;
+
+        while (packet) {
+            del = packet;
+            packet = packet->next;
+            FreePacketBuffer(del);
+        }
+    }
+}
+
+
+/* Free Sniffer Session's resources/self */
+static void FreeSnifferSession(SnifferSession* session)
+{
+    if (session) {
+        SSL_free(session->sslClient);
+        SSL_free(session->sslServer);
+
+        FreePacketList(session->cliReassemblyList);
+        FreePacketList(session->srvReassemblyList);
+
+        free(session->ticketID);
+#ifdef HAVE_EXTENDED_MASTER
+        free(session->hash);
+#endif
+    }
+    free(session);
+}
+
+
+/* Free overall Sniffer */
+void ssl_FreeSniffer(void)
+{
+    SnifferServer*  srv;
+    SnifferServer*  removeServer;
+    SnifferSession* session;
+    SnifferSession* removeSession;
+    int i;
+
+    wc_LockMutex(&ServerListMutex);
+    wc_LockMutex(&SessionMutex);
+
+    srv = ServerList;
+    while (srv) {
+        removeServer = srv;
+        srv = srv->next;
+        FreeSnifferServer(removeServer);
+    }
+
+    for (i = 0; i < HASH_SIZE; i++) {
+        session = SessionTable[i];
+        while (session) {
+            removeSession = session;
+            session = session->next;
+            FreeSnifferSession(removeSession);
+        }
+    }
+
+    wc_UnLockMutex(&SessionMutex);
+    wc_UnLockMutex(&ServerListMutex);
+
+    wc_FreeMutex(&RecoveryMutex);
+    wc_FreeMutex(&SessionMutex);
+    wc_FreeMutex(&ServerListMutex);
+
+    if (TraceFile) {
+        TraceOn = 0;
+        fclose(TraceFile);
+        TraceFile = NULL;
+    }
+
+    wolfSSL_Cleanup();
+}
+
+
+#ifdef HAVE_EXTENDED_MASTER
+
+static int HashInit(HsHashes* hash)
+{
+    int ret = 0;
+
+    XMEMSET(hash, 0, sizeof(HsHashes));
+
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    if (ret == 0)
+        ret = wc_InitSha(&hash->hashSha);
+#endif
+#ifndef NO_MD5
+    if (ret == 0) {
+        ret = wc_InitMd5(&hash->hashMd5);
+    }
+#endif
+#endif
+#ifndef NO_SHA256
+    if (ret == 0)
+        ret = wc_InitSha256(&hash->hashSha256);
+#endif
+#ifdef WOLFSSL_SHA384
+    if (ret == 0)
+        ret = wc_InitSha384(&hash->hashSha384);
+#endif
+
+    return ret;
+}
+
+
+static int HashUpdate(HsHashes* hash, const byte* input, int sz)
+{
+    int ret = 0;
+
+    input -= HANDSHAKE_HEADER_SZ;
+    sz += HANDSHAKE_HEADER_SZ;
+
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+    if (ret == 0)
+        ret = wc_ShaUpdate(&hash->hashSha, input, sz);
+#endif
+#ifndef NO_MD5
+    if (ret == 0) {
+        ret = wc_Md5Update(&hash->hashMd5, input, sz);
+    }
+#endif
+#endif
+#ifndef NO_SHA256
+    if (ret == 0)
+        ret = wc_Sha256Update(&hash->hashSha256, input, sz);
+#endif
+#ifdef WOLFSSL_SHA384
+    if (ret == 0)
+        ret = wc_Sha384Update(&hash->hashSha384, input, sz);
+#endif
+
+    return ret;
+}
+
+
+static int HashCopy(HS_Hashes* d, HsHashes* s)
+{
+#ifndef NO_OLD_TLS
+#ifndef NO_SHA
+        XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
+#endif
+#ifndef NO_MD5
+        XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
+#endif
+#endif
+
+#ifndef NO_SHA256
+        XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
+#endif
+#ifdef WOLFSSL_SHA384
+        XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
+#endif
+
+    return 0;
+}
+
+#endif
+
+
+/* Initialize a SnifferServer */
+static void InitSnifferServer(SnifferServer* sniffer)
+{
+    sniffer->ctx = 0;
+    XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
+    sniffer->server   = 0;
+    sniffer->port     = 0;
+#ifdef HAVE_SNI
+    sniffer->namedKeys = 0;
+    wc_InitMutex(&sniffer->namedKeysMutex);
+#endif
+    sniffer->next     = 0;
+}
+
+
+/* Initialize session flags */
+static void InitFlags(Flags* flags)
+{
+    flags->side           = 0;
+    flags->serverCipherOn = 0;
+    flags->clientCipherOn = 0;
+    flags->resuming       = 0;
+    flags->cached         = 0;
+    flags->clientHello    = 0;
+    flags->finCount       = 0;
+    flags->fatalError     = 0;
+    flags->cliAckFault    = 0;
+    flags->srvAckFault    = 0;
+    flags->cliSkipPartial = 0;
+    flags->srvSkipPartial = 0;
+#ifdef HAVE_EXTENDED_MASTER
+    flags->expectEms      = 0;
+#endif
+}
+
+
+/* Initialize FIN Capture */
+static void InitFinCapture(FinCaputre* cap)
+{
+    cap->cliFinSeq  = 0;
+    cap->srvFinSeq  = 0;
+    cap->cliCounted = 0;
+    cap->srvCounted = 0;
+}
+
+
+/* Initialize a Sniffer Session */
+static void InitSession(SnifferSession* session)
+{
+    session->context        = 0;
+    session->sslServer      = 0;
+    session->sslClient      = 0;
+    session->server         = 0;
+    session->client         = 0;
+    session->srvPort        = 0;
+    session->cliPort        = 0;
+    session->cliSeqStart    = 0;
+    session->srvSeqStart    = 0;
+    session->cliExpected    = 0;
+    session->srvExpected    = 0;
+    session->lastUsed       = 0;
+    session->cliReassemblyList = 0;
+    session->srvReassemblyList = 0;
+    session->cliReassemblyMemory = 0;
+    session->srvReassemblyMemory = 0;
+    session->next           = 0;
+    session->ticketID       = 0;
+
+    InitFlags(&session->flags);
+    InitFinCapture(&session->finCaputre);
+#ifdef HAVE_EXTENDED_MASTER
+    session->hash = 0;
+#endif
+}
+
+
+/* IP Info from IP Header */
+typedef struct IpInfo {
+    int    length;        /* length of this header */
+    int    total;         /* total length of fragment */
+    word32 src;           /* network order source address */
+    word32 dst;           /* network order destination address */
+} IpInfo;
+
+
+/* TCP Info from TCP Header */
+typedef struct TcpInfo {
+    int    srcPort;       /* source port */
+    int    dstPort;       /* source port */
+    int    length;        /* length of this header */
+    word32 sequence;      /* sequence number */
+    word32 ackNumber;     /* ack number */
+    byte   fin;           /* FIN set */
+    byte   rst;           /* RST set */
+    byte   syn;           /* SYN set */
+    byte   ack;           /* ACK set */
+} TcpInfo;
+
+
+/* Tcp Pseudo Header for Checksum calculation */
+typedef struct TcpPseudoHdr {
+    word32  src;        /* source address */
+    word32  dst;        /* destination address */
+    byte    rsv;        /* reserved, always 0 */
+    byte    protocol;   /* IP protocol */
+    word16  length;     /* tcp header length + data length (doesn't include */
+                        /* pseudo header length) network order */
+} TcpPseudoHdr;
+
+
+/* Password Setting Callback */
+static int SetPassword(char* passwd, int sz, int rw, void* userdata)
+{
+    (void)rw;
+    XSTRNCPY(passwd, (const char*)userdata, sz);
+    return (int)XSTRLEN((const char*)userdata);
+}
+
+
+/* Ethernet Header */
+typedef struct EthernetHdr {
+    byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */
+    byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */
+    word16 type;                      /* IP, ARP, etc */
+} EthernetHdr;
+
+
+/* IP Header */
+typedef struct IpHdr {
+    byte    ver_hl;              /* version/header length */
+    byte    tos;                 /* type of service */
+    word16  length;              /* total length */
+    word16  id;                  /* identification */
+    word16  offset;              /* fragment offset field */
+    byte    ttl;                 /* time to live */
+    byte    protocol;            /* protocol */
+    word16  sum;                 /* checksum */
+    word32  src;                 /* source address */
+    word32  dst;                 /* destination address */
+} IpHdr;
+
+
+#define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
+#define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
+
+/* TCP Header */
+typedef struct TcpHdr {
+    word16  srcPort;            /* source port */
+    word16  dstPort;            /* destination port */
+    word32  sequence;           /* sequence number */
+    word32  ack;                /* acknoledgment number */
+    byte    offset;             /* data offset, reserved */
+    byte    flags;              /* option flags */
+    word16  window;             /* window */
+    word16  sum;                /* checksum */
+    word16  urgent;             /* urgent pointer */
+} TcpHdr;
+
+#define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_ACK 0x10
+
+
+
+
+
+/* Use platform specific GetError to write to tracfile if tracing */
+static void Trace(int idx)
+{
+    if (TraceOn) {
+        char myBuffer[MAX_ERROR_LEN];
+        GetError(idx, myBuffer);
+        fprintf(TraceFile, "\t%s\n", myBuffer);
+#ifdef DEBUG_SNIFFER
+        fprintf(stderr,    "\t%s\n", myBuffer);
+#endif
+    }
+}
+
+
+/* Show TimeStamp for beginning of packet Trace */
+static void TraceHeader(void)
+{
+    if (TraceOn) {
+        time_t ticks = time(NULL);
+        fprintf(TraceFile, "\n%s", ctime(&ticks));
+    }
+}
+
+
+/* Show Set Server info for Trace */
+static void TraceSetServer(const char* srv, int port, const char* keyFile)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
+        fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
+                                                                    keyFile);
+    }
+}
+
+
+#ifdef HAVE_SNI
+
+/* Show Set Named Server info for Trace */
+static void TraceSetNamedServer(const char* name,
+                                 const char* srv, int port, const char* keyFile)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
+        fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
+                                                      name, srv, port, keyFile);
+    }
+}
+
+#endif
+
+
+/* Trace got packet number */
+static void TracePacket(void)
+{
+    if (TraceOn) {
+        static word32 packetNumber = 0;
+        fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
+                ++packetNumber);
+    }
+}
+
+
+/* Convert network byte order address into human readable */
+static char* IpToS(word32 addr, char* str)
+{
+    byte* p = (byte*)&addr;
+
+    SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+    return str;
+}
+
+
+/* Show destination and source address from Ip Hdr for packet Trace */
+static void TraceIP(IpHdr* iphdr)
+{
+    if (TraceOn) {
+        char src[TRACE_MSG_SZ];
+        char dst[TRACE_MSG_SZ];
+        fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
+                IpToS(iphdr->src, src));
+    }
+}
+
+
+/* Show destination and source port from Tcp Hdr for packet Trace */
+static void TraceTcp(TcpHdr* tcphdr)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
+                ntohs(tcphdr->srcPort));
+    }
+}
+
+
+/* Show sequence and payload length for Trace */
+static void TraceSequence(word32 seq, int len)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
+    }
+}
+
+
+/* Show sequence and payload length for Trace */
+static void TraceAck(word32 ack, word32 expected)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
+    }
+}
+
+
+/* Show relative expected and relative received sequences */
+static void TraceRelativeSequence(word32 expected, word32 got)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
+                expected, got);
+    }
+}
+
+
+/* Show server sequence startup from SYN */
+static void TraceServerSyn(word32 seq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
+    }
+}
+
+
+/* Show client sequence startup from SYN */
+static void TraceClientSyn(word32 seq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
+    }
+}
+
+
+/* Show client FIN capture */
+static void TraceClientFin(word32 finSeq, word32 relSeq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
+                finSeq, relSeq);
+    }
+}
+
+
+/* Show server FIN capture */
+static void TraceServerFin(word32 finSeq, word32 relSeq)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
+                finSeq, relSeq);
+    }
+}
+
+
+/* Show number of SSL data bytes decoded, could be 0 (ok) */
+static void TraceGotData(int bytes)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
+    }
+}
+
+
+/* Show bytes added to old SSL App data */
+static void TraceAddedData(int newBytes, int existingBytes)
+{
+    if (TraceOn) {
+        fprintf(TraceFile,
+                "\t%d bytes added to %d existing bytes in User Buffer\n",
+                newBytes, existingBytes);
+    }
+}
+
+
+/* Show Stale Session */
+static void TraceStaleSession(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tFound a stale session\n");
+    }
+}
+
+
+/* Show Finding Stale Sessions */
+static void TraceFindingStale(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
+    }
+}
+
+
+/* Show Removed Session */
+static void TraceRemovedSession(void)
+{
+    if (TraceOn) {
+        fprintf(TraceFile, "\tRemoved it\n");
+    }
+}
+
+
+/* Set user error string */
+static void SetError(int idx, char* error, SnifferSession* session, int fatal)
+{
+    GetError(idx, error);
+    Trace(idx);
+    if (session && fatal == FATAL_ERROR_STATE)
+        session->flags.fatalError = 1;
+}
+
+
+/* See if this IPV4 network order address has been registered */
+/* return 1 is true, 0 is false */
+static int IsServerRegistered(word32 addr)
+{
+    int ret = 0;     /* false */
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->server == addr) {
+            ret = 1;
+            break;
+        }
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return ret;
+}
+
+
+/* See if this port has been registered to watch */
+/* return 1 is true, 0 is false */
+static int IsPortRegistered(word32 port)
+{
+    int ret = 0;    /* false */
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->port == (int)port) {
+            ret = 1;
+            break;
+        }
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return ret;
+}
+
+
+/* Get SnifferServer from IP and Port */
+static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    SnifferServer* sniffer;
+
+    wc_LockMutex(&ServerListMutex);
+
+    sniffer = ServerList;
+    while (sniffer) {
+        if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
+            break;
+        if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
+            break;
+        sniffer = sniffer->next;
+    }
+
+    wc_UnLockMutex(&ServerListMutex);
+
+    return sniffer;
+}
+
+
+/* Hash the Session Info, return hash row */
+static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    word32 hash = ipInfo->src * ipInfo->dst;
+    hash *= tcpInfo->srcPort * tcpInfo->dstPort;
+
+    return hash % HASH_SIZE;
+}
+
+
+/* Get Exisiting SnifferSession from IP and Port */
+static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
+{
+    SnifferSession* session;
+    time_t          currTime = time(NULL);
+    word32          row = SessionHash(ipInfo, tcpInfo);
+
+    assert(row <= HASH_SIZE);
+
+    wc_LockMutex(&SessionMutex);
+
+    session = SessionTable[row];
+    while (session) {
+        if (session->server == ipInfo->src && session->client == ipInfo->dst &&
+                    session->srvPort == tcpInfo->srcPort &&
+                    session->cliPort == tcpInfo->dstPort)
+            break;
+        if (session->client == ipInfo->src && session->server == ipInfo->dst &&
+                    session->cliPort == tcpInfo->srcPort &&
+                    session->srvPort == tcpInfo->dstPort)
+            break;
+
+        session = session->next;
+    }
+
+    if (session)
+        session->lastUsed= currTime; /* keep session alive, remove stale will */
+                                     /* leave alone */
+    wc_UnLockMutex(&SessionMutex);
+
+    /* determine side */
+    if (session) {
+        if (ipInfo->dst == session->context->server &&
+            tcpInfo->dstPort == session->context->port)
+            session->flags.side = WOLFSSL_SERVER_END;
+        else
+            session->flags.side = WOLFSSL_CLIENT_END;
+    }
+
+    return session;
+}
+
+
+#ifdef HAVE_SNI
+
+static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
+                const char* keyFile, int typeKey,
+                const char* password)
+{
+    byte* loadBuf;
+    long fileSz = 0;
+    XFILE file;
+    int ret;
+
+    if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
+        return -1;
+    }
+
+    file = XFOPEN(keyFile, "rb");
+    if (file == XBADFILE) return -1;
+    XFSEEK(file, 0, XSEEK_END);
+    fileSz = XFTELL(file);
+    XREWIND(file);
+
+    loadBuf = (byte*)malloc(fileSz);
+    if (loadBuf == NULL) {
+        XFCLOSE(file);
+        return -1;
+    }
+
+    ret = (int)XFREAD(loadBuf, 1, fileSz, file);
+    XFCLOSE(file);
+
+    if (ret != fileSz) {
+        free(loadBuf);
+        return -1;
+    }
+
+    if (typeKey == WOLFSSL_FILETYPE_PEM) {
+        byte* saveBuf   = (byte*)malloc(fileSz);
+        int   saveBufSz = 0;
+
+        ret = -1;
+        if (saveBuf != NULL) {
+            saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
+                                                saveBuf, (int)fileSz, password);
+            if (saveBufSz < 0) {
+                saveBufSz = 0;
+                free(saveBuf);
+                saveBuf = NULL;
+            }
+            else
+                ret = 0;
+        }
+
+        ForceZero(loadBuf, (word32)fileSz);
+        free(loadBuf);
+
+        if (saveBuf) {
+            *keyBuf = saveBuf;
+            *keyBufSz = (word32)saveBufSz;
+        }
+    }
+    else {
+        *keyBuf = loadBuf;
+        *keyBufSz = (word32)fileSz;
+    }
+
+    if (ret < 0) {
+        return -1;
+    }
+
+    return ret;
+}
+
+#endif
+
+
+static int SetNamedPrivateKey(const char* name, const char* address, int port,
+            const char* keyFile, int typeKey, const char* password, char* error)
+{
+    SnifferServer* sniffer;
+    int            ret;
+    int            type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
+                                                      WOLFSSL_FILETYPE_ASN1;
+    int            isNew = 0;
+    word32         serverIp;
+
+#ifdef HAVE_SNI
+    NamedKey* namedKey = NULL;
+#endif
+
+    (void)name;
+#ifdef HAVE_SNI
+    if (name != NULL) {
+        namedKey = (NamedKey*)malloc(sizeof(NamedKey));
+        if (namedKey == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+            return -1;
+        }
+        XMEMSET(namedKey, 0, sizeof(NamedKey));
+
+        namedKey->nameSz = (word32)XSTRLEN(name);
+        if (namedKey->nameSz > sizeof(namedKey->name)-1)
+            namedKey->nameSz = sizeof(namedKey->name)-1;
+        XSTRNCPY(namedKey->name, name, namedKey->nameSz);
+        namedKey->name[MAX_SERVER_NAME-1] = '\0';
+
+        ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
+                          keyFile, type, password);
+        if (ret < 0) {
+            SetError(KEY_FILE_STR, error, NULL, 0);
+            FreeNamedKey(namedKey);
+            return -1;
+        }
+    }
+#endif
+
+    serverIp = inet_addr(address);
+    sniffer = ServerList;
+    while (sniffer != NULL &&
+           (sniffer->server != serverIp || sniffer->port != port)) {
+        sniffer = sniffer->next;
+    }
+
+    if (sniffer == NULL) {
+        isNew = 1;
+        sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
+        if (sniffer == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+#ifdef HAVE_SNI
+            FreeNamedKey(namedKey);
+#endif
+            return -1;
+        }
+        InitSnifferServer(sniffer);
+
+        XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
+        sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
+        sniffer->server = serverIp;
+        sniffer->port = port;
+
+        sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
+        if (!sniffer->ctx) {
+            SetError(MEMORY_STR, error, NULL, 0);
+#ifdef HAVE_SNI
+            FreeNamedKey(namedKey);
+#endif
+            FreeSnifferServer(sniffer);
+            return -1;
+        }
+    }
+
+    if (name == NULL) {
+        if (password) {
+    #ifdef WOLFSSL_ENCRYPTED_KEYS
+            SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
+            SSL_CTX_set_default_passwd_cb_userdata(
+                                                 sniffer->ctx, (void*)password);
+    #endif
+        }
+        ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
+        if (ret != WOLFSSL_SUCCESS) {
+            SetError(KEY_FILE_STR, error, NULL, 0);
+            if (isNew)
+                FreeSnifferServer(sniffer);
+            return -1;
+        }
+    }
+#ifdef HAVE_SNI
+    else {
+        wc_LockMutex(&sniffer->namedKeysMutex);
+        namedKey->next = sniffer->namedKeys;
+        sniffer->namedKeys = namedKey;
+        wc_UnLockMutex(&sniffer->namedKeysMutex);
+    }
+#endif
+
+    if (isNew) {
+        sniffer->next = ServerList;
+        ServerList = sniffer;
+    }
+
+    return 0;
+}
+
+
+#ifdef HAVE_SNI
+
+/* Sets the private key for a specific name, server and port  */
+/* returns 0 on success, -1 on error */
+int ssl_SetNamedPrivateKey(const char* name,
+                           const char* address, int port,
+                           const char* keyFile, int typeKey,
+                           const char* password, char* error)
+{
+    int ret;
+
+    TraceHeader();
+    TraceSetNamedServer(name, address, port, keyFile);
+
+    wc_LockMutex(&ServerListMutex);
+    ret = SetNamedPrivateKey(name, address, port, keyFile,
+                             typeKey, password, error);
+    wc_UnLockMutex(&ServerListMutex);
+
+    if (ret == 0)
+        Trace(NEW_SERVER_STR);
+
+    return ret;
+}
+
+#endif
+
+
+/* Sets the private key for a specific server and port  */
+/* returns 0 on success, -1 on error */
+int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
+                      int typeKey, const char* password, char* error)
+{
+    int ret;
+
+    TraceHeader();
+    TraceSetServer(address, port, keyFile);
+
+    wc_LockMutex(&ServerListMutex);
+    ret = SetNamedPrivateKey(NULL, address, port, keyFile,
+                             typeKey, password, error);
+    wc_UnLockMutex(&ServerListMutex);
+
+    if (ret == 0)
+        Trace(NEW_SERVER_STR);
+
+    return ret;
+}
+
+
+/* Check IP Header for IPV4, TCP, and a registered server address */
+/* returns 0 on success, -1 on error */
+static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
+{
+    int    version = IP_V(iphdr);
+
+    TraceIP(iphdr);
+    Trace(IP_CHECK_STR);
+
+    if (version != IPV4) {
+        SetError(BAD_IPVER_STR, error, NULL, 0);
+        return -1;
+    }
+
+    if (iphdr->protocol != TCP_PROTOCOL) {
+        SetError(BAD_PROTO_STR, error, NULL, 0);
+        return -1;
+    }
+
+    if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
+        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+        return -1;
+    }
+
+    info->length  = IP_HL(iphdr);
+    info->total   = ntohs(iphdr->length);
+    info->src     = iphdr->src;
+    info->dst     = iphdr->dst;
+
+    if (info->total == 0)
+        info->total = length;  /* reassembled may be off */
+
+    return 0;
+}
+
+
+/* Check TCP Header for a registered port */
+/* returns 0 on success, -1 on error */
+static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
+{
+    TraceTcp(tcphdr);
+    Trace(TCP_CHECK_STR);
+    info->srcPort   = ntohs(tcphdr->srcPort);
+    info->dstPort   = ntohs(tcphdr->dstPort);
+    info->length    = TCP_LEN(tcphdr);
+    info->sequence  = ntohl(tcphdr->sequence);
+    info->fin       = tcphdr->flags & TCP_FIN;
+    info->rst       = tcphdr->flags & TCP_RST;
+    info->syn       = tcphdr->flags & TCP_SYN;
+    info->ack       = tcphdr->flags & TCP_ACK;
+    if (info->ack)
+        info->ackNumber = ntohl(tcphdr->ack);
+
+    if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
+        SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* Decode Record Layer Header */
+static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
+{
+    XMEMCPY(rh, input, RECORD_HEADER_SZ);
+    *size = (rh->length[0] << 8) | rh->length[1];
+
+    if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
+        return LENGTH_ERROR;
+
+    return 0;
+}
+
+
+/* Process Client Key Exchange, RSA only */
+static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
+                                    SnifferSession* session, char* error)
+{
+    word32 idx = 0;
+    RsaKey key;
+    int    ret;
+
+    if (session->sslServer->buffers.key == NULL ||
+        session->sslServer->buffers.key->buffer == NULL ||
+        session->sslServer->buffers.key->length == 0) {
+
+        SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    ret = wc_InitRsaKey(&key, 0);
+    if (ret == 0)
+        ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key->buffer,
+                          &idx, &key, session->sslServer->buffers.key->length);
+    if (ret == 0) {
+        int length = wc_RsaEncryptSize(&key);
+
+        if (IsTLS(session->sslServer))
+            input += 2;     /* tls pre length */
+
+        if (length > *sslBytes) {
+            SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            wc_FreeRsaKey(&key);
+            return -1;
+        }
+        #ifdef WC_RSA_BLINDING
+            ret = wc_RsaSetRNG(&key, session->sslServer->rng);
+            if (ret != 0) {
+                SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
+                return -1;
+            }
+        #endif
+        do {
+        #ifdef WOLFSSL_ASYNC_CRYPT
+                ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
+        #endif
+            if (ret >= 0) {
+                ret = wc_RsaPrivateDecrypt(input, length,
+                      session->sslServer->arrays->preMasterSecret, SECRET_LEN,
+                      &key);
+            }
+        } while (ret == WC_PENDING_E);
+        if (ret != SECRET_LEN) {
+            SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
+            wc_FreeRsaKey(&key);
+            return -1;
+        }
+        session->sslServer->arrays->preMasterSz = SECRET_LEN;
+
+        /* store for client side as well */
+        XMEMCPY(session->sslClient->arrays->preMasterSecret,
+               session->sslServer->arrays->preMasterSecret, SECRET_LEN);
+        session->sslClient->arrays->preMasterSz = SECRET_LEN;
+
+        #ifdef SHOW_SECRETS
+        {
+            int i;
+            printf("pre master secret: ");
+            for (i = 0; i < SECRET_LEN; i++)
+                printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
+            printf("\n");
+        }
+        #endif
+    }
+    else {
+        SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
+        wc_FreeRsaKey(&key);
+        return -1;
+    }
+
+    if (SetCipherSpecs(session->sslServer) != 0) {
+        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+        wc_FreeRsaKey(&key);
+        return -1;
+    }
+
+    if (SetCipherSpecs(session->sslClient) != 0) {
+        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+        wc_FreeRsaKey(&key);
+        return -1;
+    }
+
+    ret  = MakeMasterSecret(session->sslServer);
+    ret += MakeMasterSecret(session->sslClient);
+    ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
+    ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
+
+    if (ret != 0) {
+        SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("server master secret: ");
+        for (i = 0; i < SECRET_LEN; i++)
+            printf("%02x", session->sslServer->arrays->masterSecret[i]);
+        printf("\n");
+
+        printf("client master secret: ");
+        for (i = 0; i < SECRET_LEN; i++)
+            printf("%02x", session->sslClient->arrays->masterSecret[i]);
+        printf("\n");
+
+        printf("server suite = %d\n", session->sslServer->options.cipherSuite);
+        printf("client suite = %d\n", session->sslClient->options.cipherSuite);
+    }
+#endif
+
+    wc_FreeRsaKey(&key);
+    return ret;
+}
+
+
+/* Process Session Ticket */
+static int ProcessSessionTicket(const byte* input, int* sslBytes,
+                                SnifferSession* session, char* error)
+{
+    word16 len;
+
+    /* make sure can read through hint and len */
+    if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
+        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    input     += TICKET_HINT_LEN;  /* skip over hint */
+    *sslBytes -= TICKET_HINT_LEN;
+
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += LENGTH_SZ;
+    *sslBytes -= LENGTH_SZ;
+
+    /* make sure can read through ticket */
+    if (len > *sslBytes || len < ID_LEN) {
+        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* store session with macID as sessionID */
+    session->sslServer->options.haveSessionId = 1;
+    XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
+
+    return 0;
+}
+
+
+/* Process Server Hello */
+static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
+                              SnifferSession* session, char* error)
+{
+    ProtocolVersion pv;
+    byte            b;
+    int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
+    int             doResume     = 0;
+    int             initialBytes = *sslBytes;
+
+    (void)msgSz;
+    (void)initialBytes;
+
+    /* make sure we didn't miss ClientHello */
+    if (session->flags.clientHello == 0) {
+        SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* make sure can read through session len */
+    if (toRead > *sslBytes) {
+        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    XMEMCPY(&pv, input, VERSION_SZ);
+    input     += VERSION_SZ;
+    *sslBytes -= VERSION_SZ;
+
+    session->sslServer->version = pv;
+    session->sslClient->version = pv;
+
+    XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
+    XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
+    input    += RAN_LEN;
+    *sslBytes -= RAN_LEN;
+
+    b = *input++;
+    *sslBytes -= 1;
+
+    /* make sure can read through compression */
+    if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
+        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    if (b) {
+        XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
+        session->sslServer->options.haveSessionId = 1;
+    }
+    input     += b;
+    *sslBytes -= b;
+
+    /* cipher suite */
+    b = *input++;  /* first byte, ECC or not */
+    session->sslServer->options.cipherSuite0 = b;
+    session->sslClient->options.cipherSuite0 = b;
+    b = *input++;
+    session->sslServer->options.cipherSuite = b;
+    session->sslClient->options.cipherSuite = b;
+    *sslBytes -= SUITE_LEN;
+
+    /* compression */
+    b = *input++;
+    *sslBytes -= ENUM_LEN;
+
+    if (b) {
+        SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    /* extensions */
+    if ((initialBytes - *sslBytes) < msgSz) {
+        word16 len;
+
+        /* skip extensions until extended master secret */
+        /* make sure can read len */
+        if (SUITE_LEN > *sslBytes) {
+            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        len = (word16)((input[0] << 8) | input[1]);
+        input     += SUITE_LEN;
+        *sslBytes -= SUITE_LEN;
+        /* make sure can read through all extensions */
+        if (len > *sslBytes) {
+            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
+            byte   extType[EXT_TYPE_SZ];
+            word16 extLen;
+
+            extType[0] = input[0];
+            extType[1] = input[1];
+            input     += EXT_TYPE_SZ;
+            *sslBytes -= EXT_TYPE_SZ;
+
+            extLen = (word16)((input[0] << 8) | input[1]);
+            input     += LENGTH_SZ;
+            *sslBytes -= LENGTH_SZ;
+
+            /* make sure can read through individual extension */
+            if (extLen > *sslBytes) {
+                SetError(SERVER_HELLO_INPUT_STR, error, session,
+                         FATAL_ERROR_STATE);
+                return -1;
+            }
+
+            if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
+                session->flags.expectEms = 1;
+            }
+
+            input     += extLen;
+            *sslBytes -= extLen;
+            len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
+        }
+    }
+
+    if (!session->flags.expectEms) {
+        free(session->hash);
+        session->hash = NULL;
+    }
+#endif
+
+    if (session->sslServer->options.haveSessionId &&
+            XMEMCMP(session->sslServer->arrays->sessionID,
+                    session->sslClient->arrays->sessionID, ID_LEN) == 0)
+        doResume = 1;
+    else if (session->sslClient->options.haveSessionId == 0 &&
+             session->sslServer->options.haveSessionId == 0 &&
+             session->ticketID)
+        doResume = 1;
+
+    if (session->ticketID && doResume) {
+        /* use ticketID to retrieve from session, prefer over sessionID */
+        XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
+        session->sslServer->options.haveSessionId = 1;  /* may not have
+                                                           actual sessionID */
+    }
+
+    if (doResume ) {
+        int ret = 0;
+        SSL_SESSION* resume = GetSession(session->sslServer,
+                                  session->sslServer->arrays->masterSecret, 0);
+        if (resume == NULL) {
+            SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        /* make sure client has master secret too */
+        XMEMCPY(session->sslClient->arrays->masterSecret,
+               session->sslServer->arrays->masterSecret, SECRET_LEN);
+        session->flags.resuming = 1;
+
+        Trace(SERVER_DID_RESUMPTION_STR);
+        if (SetCipherSpecs(session->sslServer) != 0) {
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (SetCipherSpecs(session->sslClient) != 0) {
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (session->sslServer->options.tls) {
+            ret =  DeriveTlsKeys(session->sslServer);
+            ret += DeriveTlsKeys(session->sslClient);
+        }
+        else {
+            ret =  DeriveKeys(session->sslServer);
+            ret += DeriveKeys(session->sslClient);
+        }
+        ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
+        ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
+
+        if (ret != 0) {
+            SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("cipher suite = 0x%02x\n",
+               session->sslServer->options.cipherSuite);
+        printf("server random: ");
+        for (i = 0; i < RAN_LEN; i++)
+            printf("%02x", session->sslServer->arrays->serverRandom[i]);
+        printf("\n");
+    }
+#endif
+    return 0;
+}
+
+
+/* Process normal Client Hello */
+static int ProcessClientHello(const byte* input, int* sslBytes,
+                              SnifferSession* session, char* error)
+{
+    byte   bLen;
+    word16 len;
+    int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
+
+#ifdef HAVE_SNI
+    {
+        byte name[MAX_SERVER_NAME];
+        word32 nameSz = sizeof(name);
+        int ret;
+
+        ret = wolfSSL_SNI_GetFromBuffer(
+                             input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
+                             *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
+                             WOLFSSL_SNI_HOST_NAME, name, &nameSz);
+
+        if (ret == WOLFSSL_SUCCESS) {
+            NamedKey* namedKey;
+
+            if (nameSz > sizeof(name) - 1)
+                nameSz = sizeof(name) - 1;
+            name[nameSz] = 0;
+            wc_LockMutex(&session->context->namedKeysMutex);
+            namedKey = session->context->namedKeys;
+            while (namedKey != NULL) {
+                if (nameSz == namedKey->nameSz &&
+                           XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
+                    if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
+                                            namedKey->key, namedKey->keySz,
+                                            WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
+                        wc_UnLockMutex(&session->context->namedKeysMutex);
+                        SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
+                                                             FATAL_ERROR_STATE);
+                        return -1;
+                    }
+                    break;
+                }
+                else
+                    namedKey = namedKey->next;
+            }
+            wc_UnLockMutex(&session->context->namedKeysMutex);
+        }
+    }
+#endif
+
+    session->flags.clientHello = 1;  /* don't process again */
+
+    /* make sure can read up to session len */
+    if (toRead > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* skip, get negotiated one from server hello */
+    input     += VERSION_SZ;
+    *sslBytes -= VERSION_SZ;
+
+    XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
+    XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
+
+    input     += RAN_LEN;
+    *sslBytes -= RAN_LEN;
+
+    /* store session in case trying to resume */
+    bLen = *input++;
+    *sslBytes -= ENUM_LEN;
+    if (bLen) {
+        if (ID_LEN > *sslBytes) {
+            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        Trace(CLIENT_RESUME_TRY_STR);
+        XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
+        session->sslClient->options.haveSessionId = 1;
+    }
+#ifdef SHOW_SECRETS
+    {
+        int i;
+        printf("client random: ");
+        for (i = 0; i < RAN_LEN; i++)
+            printf("%02x", session->sslServer->arrays->clientRandom[i]);
+        printf("\n");
+    }
+#endif
+
+    input     += bLen;
+    *sslBytes -= bLen;
+
+    /* skip cipher suites */
+    /* make sure can read len */
+    if (SUITE_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += SUITE_LEN;
+    *sslBytes -= SUITE_LEN;
+    /* make sure can read suites + comp len */
+    if (len + ENUM_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    input     += len;
+    *sslBytes -= len;
+
+    /* skip compression */
+    bLen       = *input++;
+    *sslBytes -= ENUM_LEN;
+    /* make sure can read len */
+    if (bLen > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    input     += bLen;
+    *sslBytes -= bLen;
+
+    if (*sslBytes == 0) {
+        /* no extensions */
+        return 0;
+    }
+
+    /* skip extensions until session ticket */
+    /* make sure can read len */
+    if (SUITE_LEN > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    len = (word16)((input[0] << 8) | input[1]);
+    input     += SUITE_LEN;
+    *sslBytes -= SUITE_LEN;
+    /* make sure can read through all extensions */
+    if (len > *sslBytes) {
+        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
+        byte   extType[EXT_TYPE_SZ];
+        word16 extLen;
+
+        extType[0] = input[0];
+        extType[1] = input[1];
+        input     += EXT_TYPE_SZ;
+        *sslBytes -= EXT_TYPE_SZ;
+
+        extLen = (word16)((input[0] << 8) | input[1]);
+        input     += LENGTH_SZ;
+        *sslBytes -= LENGTH_SZ;
+
+        /* make sure can read through individual extension */
+        if (extLen > *sslBytes) {
+            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+
+        if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
+
+            /* make sure can read through ticket if there is a non blank one */
+            if (extLen && extLen < ID_LEN) {
+                SetError(CLIENT_HELLO_INPUT_STR, error, session,
+                         FATAL_ERROR_STATE);
+                return -1;
+            }
+
+            if (extLen) {
+                if (session->ticketID == 0) {
+                    session->ticketID = (byte*)malloc(ID_LEN);
+                    if (session->ticketID == 0) {
+                        SetError(MEMORY_STR, error, session,
+                                 FATAL_ERROR_STATE);
+                        return -1;
+                    }
+                }
+                XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
+            }
+        }
+
+        input     += extLen;
+        *sslBytes -= extLen;
+        len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
+    }
+
+    return 0;
+}
+
+
+/* Process Finished */
+static int ProcessFinished(const byte* input, int size, int* sslBytes,
+                           SnifferSession* session, char* error)
+{
+    SSL*   ssl;
+    word32 inOutIdx = 0;
+    int    ret;
+
+    if (session->flags.side == WOLFSSL_SERVER_END)
+        ssl = session->sslServer;
+    else
+        ssl = session->sslClient;
+
+    ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
+                                                                         SNIFF);
+    *sslBytes -= (int)inOutIdx;
+
+    if (ret < 0) {
+        SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
+        return ret;
+    }
+
+    if (ret == 0 && session->flags.cached == 0) {
+        if (session->sslServer->options.haveSessionId) {
+            WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
+            if (sess == NULL)
+                AddSession(session->sslServer);  /* don't re add */
+            session->flags.cached = 1;
+         }
+    }
+
+    /* If receiving a finished message from one side, free the resources
+     * from the other side's tracker. */
+    if (session->flags.side == WOLFSSL_SERVER_END)
+        FreeHandshakeResources(session->sslClient);
+    else
+        FreeHandshakeResources(session->sslServer);
+
+    return ret;
+}
+
+
+/* Process HandShake input */
+static int DoHandShake(const byte* input, int* sslBytes,
+                       SnifferSession* session, char* error)
+{
+    byte type;
+    int  size;
+    int  ret = 0;
+    int  startBytes;
+
+    if (*sslBytes < HANDSHAKE_HEADER_SZ) {
+        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    type = input[0];
+    size = (input[1] << 16) | (input[2] << 8) | input[3];
+
+    input     += HANDSHAKE_HEADER_SZ;
+    *sslBytes -= HANDSHAKE_HEADER_SZ;
+    startBytes = *sslBytes;
+
+    if (*sslBytes < size) {
+        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    /* A session's arrays are released when the handshake is completed. */
+    if (session->sslServer->arrays == NULL &&
+        session->sslClient->arrays == NULL) {
+
+        SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+#ifdef HAVE_EXTENDED_MASTER
+    if (session->hash) {
+        if (HashUpdate(session->hash, input, size) != 0) {
+            SetError(EXTENDED_MASTER_HASH_STR, error,
+                     session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+#endif
+
+    switch (type) {
+        case hello_verify_request:
+            Trace(GOT_HELLO_VERIFY_STR);
+            break;
+        case hello_request:
+            Trace(GOT_HELLO_REQUEST_STR);
+            break;
+        case session_ticket:
+            Trace(GOT_SESSION_TICKET_STR);
+            ret = ProcessSessionTicket(input, sslBytes, session, error);
+            break;
+        case server_hello:
+            Trace(GOT_SERVER_HELLO_STR);
+            ret = ProcessServerHello(size, input, sslBytes, session, error);
+            break;
+        case certificate_request:
+            Trace(GOT_CERT_REQ_STR);
+            break;
+        case server_key_exchange:
+            Trace(GOT_SERVER_KEY_EX_STR);
+            /* can't know temp key passively */
+            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
+            ret = -1;
+            break;
+        case certificate:
+            Trace(GOT_CERT_STR);
+            break;
+        case server_hello_done:
+            Trace(GOT_SERVER_HELLO_DONE_STR);
+            break;
+        case finished:
+            Trace(GOT_FINISHED_STR);
+            ret = ProcessFinished(input, size, sslBytes, session, error);
+            break;
+        case client_hello:
+            Trace(GOT_CLIENT_HELLO_STR);
+            ret = ProcessClientHello(input, sslBytes, session, error);
+            break;
+        case client_key_exchange:
+            Trace(GOT_CLIENT_KEY_EX_STR);
+#ifdef HAVE_EXTENDED_MASTER
+            if (session->flags.expectEms && session->hash != NULL) {
+                if (HashCopy(session->sslServer->hsHashes,
+                             session->hash) == 0 &&
+                    HashCopy(session->sslClient->hsHashes,
+                             session->hash) == 0) {
+
+                    session->sslServer->options.haveEMS = 1;
+                    session->sslClient->options.haveEMS = 1;
+                }
+                else {
+                    SetError(EXTENDED_MASTER_HASH_STR, error,
+                             session, FATAL_ERROR_STATE);
+                    ret = -1;
+                }
+                XMEMSET(session->hash, 0, sizeof(HsHashes));
+                free(session->hash);
+                session->hash = NULL;
+            }
+            else {
+                session->sslServer->options.haveEMS = 0;
+                session->sslClient->options.haveEMS = 0;
+            }
+#endif
+            if (ret == 0)
+                ret = ProcessClientKeyExchange(input, sslBytes, session, error);
+            break;
+        case certificate_verify:
+            Trace(GOT_CERT_VER_STR);
+            break;
+        case certificate_status:
+            Trace(GOT_CERT_STATUS_STR);
+            break;
+        default:
+            SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
+            return -1;
+    }
+
+    *sslBytes = startBytes - size;  /* actual bytes of full process */
+
+    return ret;
+}
+
+
+/* Decrypt input into plain output, 0 on success */
+static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
+{
+    int ret = 0;
+
+    (void)output;
+    (void)input;
+    (void)sz;
+
+    switch (ssl->specs.bulk_cipher_algorithm) {
+        #ifdef BUILD_ARC4
+        case wolfssl_rc4:
+            wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_DES3
+        case wolfssl_triple_des:
+            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_AES
+        case wolfssl_aes:
+            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_HC128
+        case wolfssl_hc128:
+            wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
+            break;
+        #endif
+
+        #ifdef BUILD_RABBIT
+        case wolfssl_rabbit:
+            wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_IDEA
+        case wolfssl_idea:
+            wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
+            break;
+        #endif
+
+        #ifdef HAVE_AESGCM
+        case wolfssl_aes_gcm:
+            if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
+            {
+                /* scratch buffer, sniffer ignores auth tag*/
+                byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
+
+                byte nonce[AESGCM_NONCE_SZ];
+                XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
+                XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
+
+                if (wc_AesGcmEncrypt(ssl->decrypt.aes,
+                            output,
+                            input + AESGCM_EXP_IV_SZ,
+                            sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+                            nonce, AESGCM_NONCE_SZ,
+                            authTag, sizeof(authTag),
+                            NULL, 0) < 0) {
+                    Trace(BAD_DECRYPT);
+                    ret = -1;
+                }
+                ForceZero(nonce, AESGCM_NONCE_SZ);
+            }
+            else {
+                Trace(BAD_DECRYPT_SIZE);
+                ret = -1;
+            }
+            break;
+         #endif
+
+        default:
+            Trace(BAD_DECRYPT_TYPE);
+            ret = -1;
+            break;
+    }
+
+    return ret;
+}
+
+
+/* Decrypt input message into output, adjust output steam if needed */
+static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
+                                  byte* output, int* error, int* advance)
+{
+    int ivExtra = 0;
+
+    int ret = Decrypt(ssl, output, input, sz);
+    if (ret != 0) {
+        *error = ret;
+        return NULL;
+    }
+    ssl->keys.encryptSz = sz;
+    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
+        output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
+        ivExtra = ssl->specs.block_size;
+        *advance = ssl->specs.block_size;
+    }
+
+    if (ssl->specs.cipher_type == aead) {
+        *advance = ssl->specs.aead_mac_size;
+        ssl->keys.padSz = ssl->specs.aead_mac_size;
+    }
+    else
+        ssl->keys.padSz = ssl->specs.hash_size;
+
+    if (ssl->specs.cipher_type == block)
+        ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
+
+    return output;
+}
+
+
+/* remove session from table, use rowHint if no info (means we have a lock) */
+static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
+                        TcpInfo* tcpInfo, word32 rowHint)
+{
+    SnifferSession* previous = 0;
+    SnifferSession* current;
+    word32          row = rowHint;
+    int             haveLock = 0;
+
+    if (ipInfo && tcpInfo)
+        row = SessionHash(ipInfo, tcpInfo);
+    else
+        haveLock = 1;
+
+    assert(row <= HASH_SIZE);
+    Trace(REMOVE_SESSION_STR);
+
+    if (!haveLock)
+        wc_LockMutex(&SessionMutex);
+
+    current = SessionTable[row];
+
+    while (current) {
+        if (current == session) {
+            if (previous)
+                previous->next = current->next;
+            else
+                SessionTable[row] = current->next;
+            FreeSnifferSession(session);
+            TraceRemovedSession();
+            break;
+        }
+        previous = current;
+        current  = current->next;
+    }
+
+    if (!haveLock)
+        wc_UnLockMutex(&SessionMutex);
+}
+
+
+/* Remove stale sessions from the Session Table, have a lock */
+static void RemoveStaleSessions(void)
+{
+    word32 i;
+    SnifferSession* session;
+
+    for (i = 0; i < HASH_SIZE; i++) {
+        session = SessionTable[i];
+        while (session) {
+            SnifferSession* next = session->next;
+            if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
+                TraceStaleSession();
+                RemoveSession(session, NULL, NULL, i);
+            }
+            session = next;
+        }
+    }
+}
+
+
+/* Create a new Sniffer Session */
+static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                                     char* error)
+{
+    SnifferSession* session = 0;
+    int row;
+
+    Trace(NEW_SESSION_STR);
+    /* create a new one */
+    session = (SnifferSession*)malloc(sizeof(SnifferSession));
+    if (session == NULL) {
+        SetError(MEMORY_STR, error, NULL, 0);
+        return 0;
+    }
+    InitSession(session);
+#ifdef HAVE_EXTENDED_MASTER
+    {
+        HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
+        if (newHash == NULL) {
+            SetError(MEMORY_STR, error, NULL, 0);
+            free(session);
+            return 0;
+        }
+        if (HashInit(newHash) != 0) {
+            SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
+            free(session);
+            return 0;
+        }
+        session->hash = newHash;
+    }
+#endif
+    session->server  = ipInfo->dst;
+    session->client  = ipInfo->src;
+    session->srvPort = (word16)tcpInfo->dstPort;
+    session->cliPort = (word16)tcpInfo->srcPort;
+    session->cliSeqStart = tcpInfo->sequence;
+    session->cliExpected = 1;  /* relative */
+    session->lastUsed= time(NULL);
+
+    session->context = GetSnifferServer(ipInfo, tcpInfo);
+    if (session->context == NULL) {
+        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
+        free(session);
+        return 0;
+    }
+
+    session->sslServer = SSL_new(session->context->ctx);
+    if (session->sslServer == NULL) {
+        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
+        free(session);
+        return 0;
+    }
+    session->sslClient = SSL_new(session->context->ctx);
+    if (session->sslClient == NULL) {
+        SSL_free(session->sslServer);
+        session->sslServer = 0;
+
+        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
+        free(session);
+        return 0;
+    }
+    /* put server back into server mode */
+    session->sslServer->options.side = WOLFSSL_SERVER_END;
+
+    row = SessionHash(ipInfo, tcpInfo);
+
+    /* add it to the session table */
+    wc_LockMutex(&SessionMutex);
+
+    session->next = SessionTable[row];
+    SessionTable[row] = session;
+
+    SessionCount++;
+
+    if ( (SessionCount % HASH_SIZE) == 0) {
+        TraceFindingStale();
+        RemoveStaleSessions();
+    }
+
+    wc_UnLockMutex(&SessionMutex);
+
+    /* determine headed side */
+    if (ipInfo->dst == session->context->server &&
+        tcpInfo->dstPort == session->context->port)
+        session->flags.side = WOLFSSL_SERVER_END;
+    else
+        session->flags.side = WOLFSSL_CLIENT_END;
+
+    return session;
+}
+
+
+#ifdef OLD_HELLO_ALLOWED
+
+/* Process Old Client Hello Input */
+static int DoOldHello(SnifferSession* session, const byte* sslFrame,
+                      int* rhSize, int* sslBytes, char* error)
+{
+    const byte* input = sslFrame;
+    byte        b0, b1;
+    word32      idx = 0;
+    int         ret;
+
+    Trace(GOT_OLD_CLIENT_HELLO_STR);
+    session->flags.clientHello = 1;    /* don't process again */
+    b0 = *input++;
+    b1 = *input++;
+    *sslBytes -= 2;
+    *rhSize = ((b0 & 0x7f) << 8) | b1;
+
+    if (*rhSize > *sslBytes) {
+        SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
+                                (word16)*rhSize);
+    if (ret < 0 && ret != MATCH_SUITE_ERROR) {
+        SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+
+    Trace(OLD_CLIENT_OK_STR);
+    XMEMCPY(session->sslClient->arrays->clientRandom,
+           session->sslServer->arrays->clientRandom, RAN_LEN);
+
+    *sslBytes -= *rhSize;
+    return 0;
+}
+
+#endif /* OLD_HELLO_ALLOWED */
+
+
+#if 0
+/* Calculate the TCP checksum, see RFC 1071 */
+/* return 0 for success, -1 on error */
+/* can be called from decode() with
+   TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
+   could also add a 64bit version if type available and using this
+*/
+int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
+                const byte* packet)
+{
+    TcpPseudoHdr  pseudo;
+    int           count = PSEUDO_HDR_SZ;
+    const word16* data = (word16*)&pseudo;
+    word32        sum = 0;
+    word16        checksum;
+
+    pseudo.src = ipInfo->src;
+    pseudo.dst = ipInfo->dst;
+    pseudo.rsv = 0;
+    pseudo.protocol = TCP_PROTO;
+    pseudo.length = htons(tcpInfo->length + dataLen);
+
+    /* pseudo header sum */
+    while (count >= 2) {
+        sum   += *data++;
+        count -= 2;
+    }
+
+    count = tcpInfo->length + dataLen;
+    data = (word16*)packet;
+
+    /* main sum */
+    while (count > 1) {
+        sum   += *data++;
+        count -=2;
+    }
+
+    /* get left-over, if any */
+    packet = (byte*)data;
+    if (count > 0) {
+        sum += *packet;
+    }
+
+    /* fold 32bit sum into 16 bits */
+    while (sum >> 16)
+        sum = (sum & 0xffff) + (sum >> 16);
+
+    checksum = (word16)~sum;
+    /* checksum should now equal 0, since included already calcd checksum */
+    /* field, but tcp checksum offloading could negate calculation */
+    if (checksum == 0)
+        return 0;
+    return -1;
+}
+#endif
+
+
+/* Check IP and TCP headers, set payload */
+/* returns 0 on success, -1 on error */
+static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
+                  int length, const byte** sslFrame, int* sslBytes, char* error)
+{
+    TraceHeader();
+    TracePacket();
+
+    /* ip header */
+    if (length < IP_HDR_SZ) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
+        return -1;
+
+    /* tcp header */
+    if (length < (ipInfo->length + TCP_HDR_SZ)) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
+        return -1;
+
+    /* setup */
+    *sslFrame = packet + ipInfo->length + tcpInfo->length;
+    if (*sslFrame > packet + length) {
+        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
+        return -1;
+    }
+    *sslBytes = (int)(packet + length - *sslFrame);
+
+    return 0;
+}
+
+
+/* Create or Find existing session */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
+                        SnifferSession** session, char* error)
+{
+    /* create a new SnifferSession on client SYN */
+    if (tcpInfo->syn && !tcpInfo->ack) {
+        TraceClientSyn(tcpInfo->sequence);
+        *session = CreateSession(ipInfo, tcpInfo, error);
+        if (*session == NULL) {
+            *session = GetSnifferSession(ipInfo, tcpInfo);
+            /* already had existing, so OK */
+            if (*session)
+                return 1;
+
+            SetError(MEMORY_STR, error, NULL, 0);
+            return -1;
+        }
+        return 1;
+    }
+    /* get existing sniffer session */
+    else {
+        *session = GetSnifferSession(ipInfo, tcpInfo);
+        if (*session == NULL) {
+            /* don't worry about extraneous RST or duplicate FINs */
+            if (tcpInfo->fin || tcpInfo->rst)
+                return 1;
+            /* don't worry about duplicate ACKs either */
+            if (sslBytes == 0 && tcpInfo->ack)
+                return 1;
+
+            SetError(BAD_SESSION_STR, error, NULL, 0);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+
+/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
+static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
+                                  int* bytesLeft)
+{
+    PacketBuffer* pb;
+
+    int added = end - *begin + 1;
+    assert(*begin <= end);
+
+    pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
+    if (pb == NULL) return NULL;
+
+    pb->next  = 0;
+    pb->begin = *begin;
+    pb->end   = end;
+    pb->data = (byte*)malloc(added);
+
+    if (pb->data == NULL) {
+        free(pb);
+        return NULL;
+    }
+    XMEMCPY(pb->data, data, added);
+
+    *bytesLeft -= added;
+    *begin      = pb->end + 1;
+
+    return pb;
+}
+
+
+/* Add sslFrame to Reassembly List */
+/* returns 1 (end) on success, -1, on error */
+static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
+                           int sslBytes, SnifferSession* session, char* error)
+{
+    PacketBuffer*  add;
+    PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
+                       &session->cliReassemblyList: &session->srvReassemblyList;
+    PacketBuffer*  curr = *front;
+    PacketBuffer*  prev = curr;
+
+    word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
+                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
+    word32  startSeq = seq;
+    word32  added;
+    int     bytesLeft = sslBytes;  /* could be overlapping fragment */
+
+    /* if list is empty add full frame to front */
+    if (!curr) {
+        if (MaxRecoveryMemory != -1 &&
+                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        *front = add;
+        *reassemblyMemory += sslBytes;
+        return 1;
+    }
+
+    /* add to front if before current front, up to next->begin */
+    if (seq < curr->begin) {
+        word32 end = seq + sslBytes - 1;
+
+        if (end >= curr->begin)
+            end = curr->begin - 1;
+
+        if (MaxRecoveryMemory -1 &&
+                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add->next = curr;
+        *front = add;
+        *reassemblyMemory += sslBytes;
+    }
+
+    /* while we have bytes left, try to find a gap to fill */
+    while (bytesLeft > 0) {
+        /* get previous packet in list */
+        while (curr && (seq >= curr->begin)) {
+            prev = curr;
+            curr = curr->next;
+        }
+
+        /* don't add  duplicate data */
+        if (prev->end >= seq) {
+            if ( (seq + bytesLeft - 1) <= prev->end)
+                return 1;
+            seq = prev->end + 1;
+            bytesLeft = startSeq + sslBytes - seq;
+        }
+
+        if (!curr)
+            /* we're at the end */
+            added = bytesLeft;
+        else
+            /* we're in between two frames */
+            added = min((word32)bytesLeft, curr->begin - seq);
+
+        /* data already there */
+        if (added == 0)
+            continue;
+
+        if (MaxRecoveryMemory != -1 &&
+                         (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
+            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
+                           &bytesLeft);
+        if (add == NULL) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        add->next  = prev->next;
+        prev->next = add;
+        *reassemblyMemory += added;
+    }
+    return 1;
+}
+
+
+/* Add out of order FIN capture */
+/* returns 1 for success (end) */
+static int AddFinCapture(SnifferSession* session, word32 sequence)
+{
+    if (session->flags.side == WOLFSSL_SERVER_END) {
+        if (session->finCaputre.cliCounted == 0)
+            session->finCaputre.cliFinSeq = sequence;
+    }
+    else {
+        if (session->finCaputre.srvCounted == 0)
+            session->finCaputre.srvFinSeq = sequence;
+    }
+    return 1;
+}
+
+
+/* Adjust incoming sequence based on side */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
+                          int* sslBytes, const byte** sslFrame, char* error)
+{
+    word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                     session->cliSeqStart :session->srvSeqStart;
+    word32  real     = tcpInfo->sequence - seqStart;
+    word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  &session->cliExpected : &session->srvExpected;
+    PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
+                        session->cliReassemblyList : session->srvReassemblyList;
+    byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->flags.srvSkipPartial :
+                                session->flags.cliSkipPartial;
+
+    /* handle rollover of sequence */
+    if (tcpInfo->sequence < seqStart)
+        real = 0xffffffffU - seqStart + tcpInfo->sequence;
+
+    TraceRelativeSequence(*expected, real);
+
+    if (real < *expected) {
+        Trace(DUPLICATE_STR);
+        if (real + *sslBytes > *expected) {
+            int overlap = *expected - real;
+            Trace(OVERLAP_DUPLICATE_STR);
+
+            /* adjust to expected, remove duplicate */
+            *sslFrame += overlap;
+            *sslBytes -= overlap;
+
+            /* The following conditional block is duplicated below. It is the
+             * same action but for a different setup case. If changing this
+             * block be sure to also update the block below. */
+            if (reassemblyList) {
+                word32 newEnd = *expected + *sslBytes;
+
+                if (newEnd > reassemblyList->begin) {
+                    Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
+
+                    /* remove bytes already on reassembly list */
+                    *sslBytes -= newEnd - reassemblyList->begin;
+                }
+                if (newEnd > reassemblyList->end) {
+                    Trace(OVERLAP_REASSEMBLY_END_STR);
+
+                    /* may be past reassembly list end (could have more on list)
+                       so try to add what's past the front->end */
+                    AddToReassembly(session->flags.side, reassemblyList->end +1,
+                                *sslFrame + reassemblyList->end - *expected + 1,
+                                 newEnd - reassemblyList->end, session, error);
+                }
+            }
+        }
+        else
+            return 1;
+    }
+    else if (real > *expected) {
+        Trace(OUT_OF_ORDER_STR);
+        if (*sslBytes > 0) {
+            int addResult = AddToReassembly(session->flags.side, real,
+                                          *sslFrame, *sslBytes, session, error);
+            if (skipPartial) {
+                *sslBytes = 0;
+                return 0;
+            }
+            else
+                return addResult;
+        }
+        else if (tcpInfo->fin)
+            return AddFinCapture(session, real);
+    }
+    else if (*sslBytes > 0) {
+        if (skipPartial) {
+            AddToReassembly(session->flags.side, real,
+                                          *sslFrame, *sslBytes, session, error);
+            *expected += *sslBytes;
+            *sslBytes = 0;
+            if (tcpInfo->fin)
+                *expected += 1;
+            return 0;
+        }
+        /* The following conditional block is duplicated above. It is the
+         * same action but for a different setup case. If changing this
+         * block be sure to also update the block above. */
+        else if (reassemblyList) {
+            word32 newEnd = *expected + *sslBytes;
+
+            if (newEnd > reassemblyList->begin) {
+                Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
+
+                /* remove bytes already on reassembly list */
+                *sslBytes -= newEnd - reassemblyList->begin;
+            }
+            if (newEnd > reassemblyList->end) {
+                Trace(OVERLAP_REASSEMBLY_END_STR);
+
+                /* may be past reassembly list end (could have more on list)
+                   so try to add what's past the front->end */
+                AddToReassembly(session->flags.side, reassemblyList->end +1,
+                            *sslFrame + reassemblyList->end - *expected + 1,
+                             newEnd - reassemblyList->end, session, error);
+            }
+        }
+    }
+    /* got expected sequence */
+    *expected += *sslBytes;
+    if (tcpInfo->fin)
+        *expected += 1;
+
+    return 0;
+}
+
+
+static int FindNextRecordInAssembly(SnifferSession* session,
+                                    const byte** sslFrame, int* sslBytes,
+                                    const byte** end, char* error)
+{
+    PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliReassemblyList :
+                                    &session->srvReassemblyList;
+    PacketBuffer*       curr = *front;
+    PacketBuffer*       prev = NULL;
+    byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->flags.srvSkipPartial :
+                                    &session->flags.cliSkipPartial;
+    word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliReassemblyMemory :
+                                    &session->srvReassemblyMemory;
+    SSL*                 ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    session->sslServer :
+                                    session->sslClient;
+    ProtocolVersion       pv = ssl->version;
+    word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                    &session->cliExpected :
+                                    &session->srvExpected;
+
+    while (curr != NULL) {
+        *expected = curr->end + 1;
+
+        if (curr->data[0] == application_data &&
+            curr->data[1] == pv.major &&
+            curr->data[2] == pv.minor) {
+
+            if (ssl->buffers.inputBuffer.length > 0)
+                Trace(DROPPING_PARTIAL_RECORD);
+
+            *sslBytes = curr->end - curr->begin + 1;
+            if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
+                if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
+                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                    return -1;
+                }
+            }
+
+            XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
+
+            *front = curr->next;
+            *reassemblyMemory -= *sslBytes;
+            FreePacketBuffer(curr);
+
+            ssl->buffers.inputBuffer.length = *sslBytes;
+            *sslFrame = ssl->buffers.inputBuffer.buffer;
+            *end = *sslFrame + *sslBytes;
+            *skipPartial = 0;
+
+            return 0;
+        }
+        else if (ssl->specs.cipher_type == block) {
+            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
+#ifdef BUILD_AES
+                wc_AesSetIV(ssl->decrypt.aes,
+                            curr->data + curr->end - curr->begin
+                                       - ssl->specs.block_size + 1);
+#endif
+            }
+            else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
+#ifdef BUILD_DES3
+                wc_Des3_SetIV(ssl->decrypt.des3,
+                              curr->data + curr->end - curr->begin
+                                         - ssl->specs.block_size + 1);
+#endif
+            }
+        }
+
+        Trace(DROPPING_LOST_FRAG_STR);
+        prev = curr;
+        curr = curr->next;
+        *reassemblyMemory -= (prev->end - prev->begin + 1);
+        FreePacketBuffer(prev);
+    }
+
+    *front = curr;
+
+    return 0;
+}
+
+
+static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
+{
+    word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                &session->srvExpected : &session->cliExpected;
+    PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->srvReassemblyList :
+                                session->cliReassemblyList;
+    byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
+                                &session->flags.srvSkipPartial :
+                                &session->flags.cliSkipPartial;
+
+    *skipPartial = 1;
+    if (list != NULL)
+        *expected = list->begin;
+    else {
+        word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                session->srvSeqStart : session->cliSeqStart;
+        word32     real = tcpInfo->ackNumber - seqStart;
+
+        *expected = real;
+    }
+
+    return 1;
+}
+
+
+/* Check latest ack number for missing packets
+   return 0 ok, <0 on error */
+static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
+{
+    if (tcpInfo->ack) {
+        word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                     session->srvSeqStart :session->cliSeqStart;
+        word32  real     = tcpInfo->ackNumber - seqStart;
+        word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  session->srvExpected : session->cliExpected;
+
+        /* handle rollover of sequence */
+        if (tcpInfo->ackNumber < seqStart)
+            real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
+
+        TraceAck(real, expected);
+
+        if (real > expected)
+            return -1;  /* we missed a packet, ACKing data we never saw */
+    }
+    return 0;
+}
+
+
+/* Check TCP Sequence status */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                         SnifferSession* session, int* sslBytes,
+                         const byte** sslFrame, char* error)
+{
+    int actualLen;
+    byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
+                        &session->flags.cliAckFault :
+                        &session->flags.srvAckFault;
+
+    /* init SEQ from server to client */
+    if (tcpInfo->syn && tcpInfo->ack) {
+        session->srvSeqStart = tcpInfo->sequence;
+        session->srvExpected = 1;
+        TraceServerSyn(tcpInfo->sequence);
+        return 1;
+    }
+
+    /* adjust potential ethernet trailer */
+    actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
+    if (*sslBytes > actualLen) {
+        *sslBytes = actualLen;
+    }
+
+    TraceSequence(tcpInfo->sequence, *sslBytes);
+    if (CheckAck(tcpInfo, session) < 0) {
+        if (!RecoveryEnabled) {
+            UpdateMissedDataSessions();
+            SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        else {
+            SetError(ACK_MISSED_STR, error, session, 0);
+            if (*ackFault == 0) {
+                *ackFault = 1;
+                UpdateMissedDataSessions();
+            }
+            return FixSequence(tcpInfo, session);
+        }
+    }
+
+    if (*ackFault) {
+        Trace(CLEAR_ACK_FAULT);
+        *ackFault = 0;
+    }
+
+    return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
+}
+
+
+/* Check Status before record processing */
+/* returns 0 on success (continue), -1 on error, 1 on success (end) */
+static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                          const byte** sslFrame, SnifferSession** session,
+                          int* sslBytes, const byte** end, char* error)
+{
+    word32 length;
+    SSL*  ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
+                                  (*session)->sslServer : (*session)->sslClient;
+    byte  skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
+                        (*session)->flags.srvSkipPartial :
+                        (*session)->flags.cliSkipPartial;
+    /* remove SnifferSession on 2nd FIN or RST */
+    if (tcpInfo->fin || tcpInfo->rst) {
+        /* flag FIN and RST */
+        if (tcpInfo->fin)
+            (*session)->flags.finCount += 1;
+        else if (tcpInfo->rst)
+            (*session)->flags.finCount += 2;
+
+        if ((*session)->flags.finCount >= 2) {
+            RemoveSession(*session, ipInfo, tcpInfo, 0);
+            *session = NULL;
+            return 1;
+        }
+    }
+
+    if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
+        SetError(FATAL_ERROR_STR, error, NULL, 0);
+        return -1;
+    }
+
+    if (skipPartial) {
+        if (FindNextRecordInAssembly(*session,
+                                     sslFrame, sslBytes, end, error) < 0) {
+            return -1;
+        }
+    }
+
+    if (*sslBytes == 0) {
+        Trace(NO_DATA_STR);
+        return 1;
+    }
+
+    /* if current partial data, add to end of partial */
+    /* if skipping, the data is already at the end of partial */
+    if ( !skipPartial &&
+         (length = ssl->buffers.inputBuffer.length) ) {
+        Trace(PARTIAL_ADD_STR);
+
+        if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
+            if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
+                SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
+                return -1;
+            }
+        }
+        XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
+        *sslBytes += length;
+        ssl->buffers.inputBuffer.length = *sslBytes;
+        *sslFrame = ssl->buffers.inputBuffer.buffer;
+        *end = *sslFrame + *sslBytes;
+    }
+
+    if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
+        /* Sanity check the packet for an old style client hello. */
+        int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
+
+        if ((rhSize <= (*sslBytes - 2)) &&
+            (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
+#ifdef OLD_HELLO_ALLOWED
+        int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
+        if (ret < 0)
+            return -1;  /* error already set */
+        if (*sslBytes <= 0)
+            return 1;
+#endif
+        }
+        else {
+#ifdef STARTTLS_ALLOWED
+            return 1;
+#endif
+        }
+    }
+
+    return 0;
+}
+
+
+/* See if input on the reassembly list is ready for consuming */
+/* returns 1 for TRUE, 0 for FALSE */
+static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
+                         int* sslBytes, const byte** end, char* error)
+{
+    /* sequence and reassembly based on from, not to */
+    int            moreInput = 0;
+    PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
+                      &session->cliReassemblyList : &session->srvReassemblyList;
+    word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                  &session->cliExpected : &session->srvExpected;
+    /* buffer is on receiving end */
+    word32*        length = (session->flags.side == WOLFSSL_SERVER_END) ?
+                               &session->sslServer->buffers.inputBuffer.length :
+                               &session->sslClient->buffers.inputBuffer.length;
+    byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
+                               &session->sslServer->buffers.inputBuffer.buffer :
+                               &session->sslClient->buffers.inputBuffer.buffer;
+    word32*       bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
+                           &session->sslServer->buffers.inputBuffer.bufferSize :
+                           &session->sslClient->buffers.inputBuffer.bufferSize;
+    SSL*               ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
+                            session->sslServer : session->sslClient;
+    word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
+                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
+
+    while (*front && ((*front)->begin == *expected) ) {
+        word32 room = *bufferSize - *length;
+        word32 packetLen = (*front)->end - (*front)->begin + 1;
+
+        if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
+            if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
+                SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                return 0;
+            }
+            room = *bufferSize - *length;   /* bufferSize is now bigger */
+        }
+
+        if (packetLen <= room) {
+            PacketBuffer* del = *front;
+            byte*         buf = *myBuffer;
+
+            XMEMCPY(&buf[*length], (*front)->data, packetLen);
+            *length   += packetLen;
+            *expected += packetLen;
+
+            /* remove used packet */
+            *front = (*front)->next;
+
+            *reassemblyMemory -= packetLen;
+            FreePacketBuffer(del);
+
+            moreInput = 1;
+        }
+        else
+            break;
+    }
+    if (moreInput) {
+        *sslFrame = *myBuffer;
+        *sslBytes = *length;
+        *end      = *myBuffer + *length;
+    }
+    return moreInput;
+}
+
+
+
+/* Process Message(s) from sslFrame */
+/* return Number of bytes on success, 0 for no data yet, and -1 on error */
+static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
+                          int sslBytes, byte** data, const byte* end,
+                          char* error)
+{
+    const byte*       sslBegin = sslFrame;
+    const byte*       recordEnd;   /* end of record indicator */
+    const byte*       inRecordEnd; /* indicator from input stream not decrypt */
+    RecordLayerHeader rh;
+    int               rhSize = 0;
+    int               ret;
+    int               errCode = 0;
+    int               decoded = 0;      /* bytes stored for user in data */
+    int               notEnough;        /* notEnough bytes yet flag */
+    int               decrypted = 0;    /* was current msg decrypted */
+    SSL*              ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
+                                        session->sslServer : session->sslClient;
+doMessage:
+    notEnough = 0;
+    if (sslBytes < 0) {
+        SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
+        return -1;
+    }
+    if (sslBytes >= RECORD_HEADER_SZ) {
+        if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
+            SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+    else
+        notEnough = 1;
+
+    if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
+        /* don't have enough input yet to process full SSL record */
+        Trace(PARTIAL_INPUT_STR);
+
+        /* store partial if not there already or we advanced */
+        if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
+            if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
+                if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
+                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+                    return -1;
+                }
+            }
+            XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
+            ssl->buffers.inputBuffer.length = sslBytes;
+        }
+        if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
+            goto doMessage;
+        return decoded;
+    }
+    sslFrame += RECORD_HEADER_SZ;
+    sslBytes -= RECORD_HEADER_SZ;
+    recordEnd = sslFrame + rhSize;   /* may have more than one record */
+    inRecordEnd = recordEnd;
+
+    /* decrypt if needed */
+    if ((session->flags.side == WOLFSSL_SERVER_END &&
+                                               session->flags.serverCipherOn)
+     || (session->flags.side == WOLFSSL_CLIENT_END &&
+                                               session->flags.clientCipherOn)) {
+        int ivAdvance = 0;  /* TLSv1.1 advance amount */
+        if (ssl->decrypt.setup != 1) {
+            SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        if (CheckAvailableSize(ssl, rhSize) < 0) {
+            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+        sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
+                                  ssl->buffers.outputBuffer.buffer, &errCode,
+                                  &ivAdvance);
+        recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
+                                                       should recordEnd */
+        decrypted = 1;
+        if (errCode != 0) {
+            SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
+            return -1;
+        }
+    }
+
+doPart:
+
+    switch ((enum ContentType)rh.type) {
+        case handshake:
+            {
+                int startIdx = sslBytes;
+                int used;
+
+                Trace(GOT_HANDSHAKE_STR);
+                ret = DoHandShake(sslFrame, &sslBytes, session, error);
+                if (ret != 0) {
+                    if (session->flags.fatalError == 0)
+                        SetError(BAD_HANDSHAKE_STR, error, session,
+                                 FATAL_ERROR_STATE);
+                    return -1;
+                }
+
+                /* DoHandShake now fully decrements sslBytes to remaining */
+                used = startIdx - sslBytes;
+                sslFrame += used;
+                if (decrypted)
+                    sslFrame += ssl->keys.padSz;
+            }
+            break;
+        case change_cipher_spec:
+            if (session->flags.side == WOLFSSL_SERVER_END)
+                session->flags.serverCipherOn = 1;
+            else
+                session->flags.clientCipherOn = 1;
+            Trace(GOT_CHANGE_CIPHER_STR);
+            ssl->options.handShakeState = HANDSHAKE_DONE;
+            ssl->options.handShakeDone  = 1;
+
+            sslFrame += 1;
+            sslBytes -= 1;
+
+            break;
+        case application_data:
+            Trace(GOT_APP_DATA_STR);
+            {
+                word32 inOutIdx = 0;
+
+                ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
+                if (ret == 0) {
+                    ret = ssl->buffers.clearOutputBuffer.length;
+                    TraceGotData(ret);
+                    if (ret) {  /* may be blank message */
+                        byte* tmpData;  /* don't leak on realloc free */
+                        /* add an extra byte at end of allocation in case user
+                         * wants to null terminate plaintext */
+                        tmpData = (byte*)realloc(*data, decoded + ret + 1);
+                        if (tmpData == NULL) {
+                            ForceZero(*data, decoded);
+                            free(*data);
+                            *data = NULL;
+                            SetError(MEMORY_STR, error, session,
+                                     FATAL_ERROR_STATE);
+                            return -1;
+                        }
+                        *data = tmpData;
+                        XMEMCPY(*data + decoded,
+                                ssl->buffers.clearOutputBuffer.buffer, ret);
+                        TraceAddedData(ret, decoded);
+                        decoded += ret;
+                        ssl->buffers.clearOutputBuffer.length = 0;
+                    }
+                }
+                else {
+                    SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
+                    return -1;
+                }
+                if (ssl->buffers.outputBuffer.dynamicFlag)
+                    ShrinkOutputBuffer(ssl);
+
+                sslFrame += inOutIdx;
+                sslBytes -= inOutIdx;
+            }
+            break;
+        case alert:
+            Trace(GOT_ALERT_STR);
+            sslFrame += rhSize;
+            sslBytes -= rhSize;
+            break;
+        case no_type:
+        default:
+            SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
+            return -1;
+    }
+
+    /* do we have another msg in record ? */
+    if (sslFrame < recordEnd) {
+        Trace(ANOTHER_MSG_STR);
+        goto doPart;
+    }
+
+    /* back to input stream instead of potential decrypt buffer */
+    recordEnd = inRecordEnd;
+
+    /* do we have more records ? */
+    if (recordEnd < end) {
+        Trace(ANOTHER_MSG_STR);
+        sslFrame = recordEnd;
+        sslBytes = (int)(end - recordEnd);
+        goto doMessage;
+    }
+
+    /* clear used input */
+    ssl->buffers.inputBuffer.length = 0;
+
+    /* could have more input ready now */
+    if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
+        goto doMessage;
+
+    if (ssl->buffers.inputBuffer.dynamicFlag)
+        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+    return decoded;
+}
+
+
+/* See if we need to process any pending FIN captures */
+static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                            SnifferSession* session)
+{
+    if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
+                                         session->cliExpected) {
+        if (session->finCaputre.cliCounted == 0) {
+            session->flags.finCount += 1;
+            session->finCaputre.cliCounted = 1;
+            TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
+        }
+    }
+
+    if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
+                                         session->srvExpected) {
+        if (session->finCaputre.srvCounted == 0) {
+            session->flags.finCount += 1;
+            session->finCaputre.srvCounted = 1;
+            TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
+        }
+    }
+
+    if (session->flags.finCount >= 2)
+        RemoveSession(session, ipInfo, tcpInfo, 0);
+}
+
+
+/* If session is in fatal error state free resources now
+   return true if removed, 0 otherwise */
+static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
+                              SnifferSession* session, char* error)
+{
+    if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
+        RemoveSession(session, ipInfo, tcpInfo, 0);
+        SetError(FATAL_ERROR_STR, error, NULL, 0);
+        return 1;
+    }
+    return 0;
+}
+
+
+/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
+/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
+int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
+{
+    TcpInfo           tcpInfo;
+    IpInfo            ipInfo;
+    const byte*       sslFrame;
+    const byte*       end = packet + length;
+    int               sslBytes;                /* ssl bytes unconsumed */
+    int               ret;
+    SnifferSession*   session = 0;
+
+    if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
+                     error) != 0)
+        return -1;
+
+    ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) return  0;   /* done for now */
+
+    ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) return  0;   /* done for now */
+
+    ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
+                         &end, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    else if (ret == -1) return -1;
+    else if (ret ==  1) return  0;   /* done for now */
+
+    ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
+    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
+    CheckFinCapture(&ipInfo, &tcpInfo, session);
+    return ret;
+}
+
+
+/* Deallocator for the decoded data buffer. */
+/* returns 0 on success, -1 on error */
+int ssl_FreeDecodeBuffer(byte** data, char* error)
+{
+    return ssl_FreeZeroDecodeBuffer(data, 0, error);
+}
+
+
+/* Deallocator for the decoded data buffer, zeros out buffer. */
+/* returns 0 on success, -1 on error */
+int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
+{
+    (void)error;
+
+    if (sz < 0) {
+        return -1;
+    }
+
+    if (data != NULL) {
+        ForceZero(*data, (word32)sz);
+        free(*data);
+        *data = NULL;
+    }
+
+    return 0;
+}
+
+
+/* Enables (if traceFile)/ Disables debug tracing */
+/* returns 0 on success, -1 on error */
+int ssl_Trace(const char* traceFile, char* error)
+{
+    if (traceFile) {
+        TraceFile = fopen(traceFile, "a");
+        if (!TraceFile) {
+            SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
+            return -1;
+        }
+        TraceOn = 1;
+    }
+    else
+        TraceOn = 0;
+
+    return 0;
+}
+
+
+/* Enables/Disables Recovery of missed data if later packets allow
+ * maxMemory is number of bytes to use for reassembly buffering per session,
+ * -1 means unlimited
+ * returns 0 on success, -1 on error */
+int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
+{
+    (void)error;
+
+    RecoveryEnabled = onOff;
+    if (onOff)
+        MaxRecoveryMemory = maxMemory;
+
+    return 0;
+}
+
+
+
+int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
+                        unsigned int* peak,       unsigned int* maxSessions,
+                        unsigned int* missedData, unsigned int* reassemblyMem,
+                        char* error)
+{
+    int ret;
+
+    if (missedData) {
+        wc_LockMutex(&RecoveryMutex);
+        *missedData = MissedDataSessions;
+        wc_UnLockMutex(&RecoveryMutex);
+    }
+
+    if (reassemblyMem) {
+        SnifferSession* session;
+        int i;
+
+        *reassemblyMem = 0;
+        wc_LockMutex(&SessionMutex);
+        for (i = 0; i < HASH_SIZE; i++) {
+            session = SessionTable[i];
+            while (session) {
+                *reassemblyMem += session->cliReassemblyMemory;
+                *reassemblyMem += session->srvReassemblyMemory;
+                session = session->next;
+            }
+        }
+        wc_UnLockMutex(&SessionMutex);
+    }
+
+    ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
+
+    if (ret == WOLFSSL_SUCCESS)
+        return 0;
+    else {
+        SetError(BAD_SESSION_STATS, error, NULL, 0);
+        return -1;
+    }
+}
+
+
+
+#endif /* WOLFSSL_SNIFFER */
+#endif /* WOLFCRYPT_ONLY */
+
--- a/src/ssl.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/ssl.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,33665 +1,33665 @@
-/* ssl.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-
-#ifdef HAVE_ERRNO_H
-    #include <errno.h>
-#endif
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/coding.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifndef WOLFSSL_ALLOW_NO_SUITES
-    #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
-                && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
-                && !defined(HAVE_ED25519)
-        #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
-    #endif
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
-        defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN)
-    #include <wolfssl/openssl/evp.h>
-    /* openssl headers end, wolfssl internal headers next */
-#endif
-
-#include <wolfssl/wolfcrypt/wc_encrypt.h>
-
-#ifdef OPENSSL_EXTRA
-    /* openssl headers begin */
-    #include <wolfssl/openssl/aes.h>
-    #include <wolfssl/openssl/hmac.h>
-    #include <wolfssl/openssl/crypto.h>
-    #include <wolfssl/openssl/des.h>
-    #include <wolfssl/openssl/bn.h>
-    #include <wolfssl/openssl/buffer.h>
-    #include <wolfssl/openssl/dh.h>
-    #include <wolfssl/openssl/rsa.h>
-    #include <wolfssl/openssl/pem.h>
-    #include <wolfssl/openssl/ec.h>
-    #include <wolfssl/openssl/ec25519.h>
-    #include <wolfssl/openssl/ed25519.h>
-    #include <wolfssl/openssl/ecdsa.h>
-    #include <wolfssl/openssl/ecdh.h>
-    #include <wolfssl/openssl/rc4.h>
-    /* openssl headers end, wolfssl internal headers next */
-    #include <wolfssl/wolfcrypt/hmac.h>
-    #include <wolfssl/wolfcrypt/random.h>
-    #include <wolfssl/wolfcrypt/des3.h>
-    #include <wolfssl/wolfcrypt/md4.h>
-    #include <wolfssl/wolfcrypt/md5.h>
-    #include <wolfssl/wolfcrypt/arc4.h>
-    #include <wolfssl/wolfcrypt/idea.h>
-    #include <wolfssl/wolfcrypt/curve25519.h>
-    #include <wolfssl/wolfcrypt/ed25519.h>
-    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
-        #include <wolfssl/openssl/ocsp.h>
-    #endif /* WITH_STUNNEL */
-    #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
-        #include <wolfssl/wolfcrypt/sha512.h>
-    #endif
-    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
-        && !defined(WC_NO_RNG)
-        #include <wolfssl/wolfcrypt/srp.h>
-        #include <wolfssl/wolfcrypt/random.h>
-    #endif
-#endif
-
-#ifdef NO_ASN
-    #include <wolfssl/wolfcrypt/dh.h>
-#endif
-
-
-#ifdef WOLFSSL_SESSION_EXPORT
-#ifdef WOLFSSL_DTLS
-int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz)
-{
-    WOLFSSL_ENTER("wolfSSL_session_import");
-
-    if (ssl == NULL || buf == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* sanity checks on buffer and protocol are done in internal function */
-    return wolfSSL_dtls_import_internal(ssl, buf, sz);
-}
-
-
-/* Sets the function to call for serializing the session. This function is
- * called right after the handshake is completed. */
-int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
-{
-
-    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
-
-    /* purposefully allow func to be NULL */
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ctx->dtls_export = func;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Sets the function in WOLFSSL struct to call for serializing the session. This
- * function is called right after the handshake is completed. */
-int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
-{
-
-    WOLFSSL_ENTER("wolfSSL_dtls_set_export");
-
-    /* purposefully allow func to be NULL */
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->dtls_export = func;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* This function allows for directly serializing a session rather than using
- * callbacks. It has less overhead by removing a temporary buffer and gives
- * control over when the session gets serialized. When using callbacks the
- * session is always serialized immediatly after the handshake is finished.
- *
- * buf is the argument to contain the serialized session
- * sz  is the size of the buffer passed in
- * ssl is the WOLFSSL struct to serialize
- * returns the size of serialized session on success, 0 on no action, and
- *         negative value on error */
-int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
-{
-    WOLFSSL_ENTER("wolfSSL_dtls_export");
-
-    if (ssl == NULL || sz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (buf == NULL) {
-        *sz = MAX_EXPORT_BUFFER;
-        return 0;
-    }
-
-    /* if not DTLS do nothing */
-    if (!ssl->options.dtls) {
-        WOLFSSL_MSG("Currently only DTLS export is supported");
-        return 0;
-    }
-
-    /* copy over keys, options, and dtls state struct */
-    return wolfSSL_dtls_export_internal(ssl, buf, *sz);
-}
-
-
-/* returns 0 on success */
-int wolfSSL_send_session(WOLFSSL* ssl)
-{
-    int ret;
-    byte* buf;
-    word16 bufSz = MAX_EXPORT_BUFFER;
-
-    WOLFSSL_ENTER("wolfSSL_send_session");
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buf == NULL) {
-        return MEMORY_E;
-    }
-
-    /* if not DTLS do nothing */
-    if (!ssl->options.dtls) {
-        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_MSG("Currently only DTLS export is supported");
-        return 0;
-    }
-
-    /* copy over keys, options, and dtls state struct */
-    ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz);
-    if (ret < 0) {
-        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-
-    /* if no error ret has size of buffer */
-    ret = ssl->dtls_export(ssl, buf, ret, NULL);
-    if (ret != WOLFSSL_SUCCESS) {
-        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-
-    XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return 0;
-}
-#endif /* WOLFSSL_DTLS */
-#endif /* WOLFSSL_SESSION_EXPORT */
-
-
-/* prevent multiple mutex initializations */
-static volatile int initRefCount = 0;
-static wolfSSL_Mutex count_mutex;   /* init ref count mutex */
-
-/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
-   WOLFSSL_METHOD pointer passed in is given to ctx to manage.
-   This function frees the passed in WOLFSSL_METHOD struct on failure and on
-   success is freed when ctx is freed.
- */
-WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
-{
-    WOLFSSL_CTX* ctx = NULL;
-
-    WOLFSSL_ENTER("WOLFSSL_CTX_new_ex");
-
-    if (initRefCount == 0) {
-        /* user no longer forced to call Init themselves */
-        int ret = wolfSSL_Init();
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("wolfSSL_Init failed");
-            WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
-            if (method != NULL) {
-                XFREE(method, heap, DYNAMIC_TYPE_METHOD);
-            }
-            return NULL;
-        }
-    }
-
-    if (method == NULL)
-        return ctx;
-
-    ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
-    if (ctx) {
-        if (InitSSL_Ctx(ctx, method, heap) < 0) {
-            WOLFSSL_MSG("Init CTX failed");
-            wolfSSL_CTX_free(ctx);
-            ctx = NULL;
-        }
-#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
-                           && !defined(NO_SHA256) && !defined(WC_NO_RNG)
-        else {
-            ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
-            if (ctx->srp == NULL){
-                WOLFSSL_MSG("Init CTX failed");
-                wolfSSL_CTX_free(ctx);
-                return NULL;
-            }
-            XMEMSET(ctx->srp, 0, sizeof(Srp));
-        }
-#endif
-    }
-    else {
-        WOLFSSL_MSG("Alloc CTX failed, method freed");
-        XFREE(method, heap, DYNAMIC_TYPE_METHOD);
-    }
-
-
-    WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
-    return ctx;
-}
-
-
-WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
-{
-#ifdef WOLFSSL_HEAP_TEST
-    /* if testing the heap hint then set top level CTX to have test value */
-    return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST);
-#else
-    return wolfSSL_CTX_new_ex(method, NULL);
-#endif
-}
-
-
-void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("SSL_CTX_free");
-    if (ctx) {
-#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
-&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
-        if (ctx->srp != NULL){
-            if (ctx->srp_password != NULL){
-                XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
-            }
-            wc_SrpTerm(ctx->srp);
-            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
-        }
-#endif
-        FreeSSL_Ctx(ctx);
-    }
-
-    WOLFSSL_LEAVE("SSL_CTX_free", 0);
-}
-
-
-#ifdef SINGLE_THREADED
-/* no locking in single threaded mode, allow a CTX level rng to be shared with
- * WOLFSSL objects, WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx)
-{
-    WC_RNG* rng;
-    int     ret;
-
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    rng = XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
-    if (rng == NULL) {
-        return MEMORY_E;
-    }
-
-#ifndef HAVE_FIPS
-    ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId);
-#else
-    ret = wc_InitRng(rng);
-#endif
-    if (ret != 0) {
-        XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
-        return ret;
-    }
-
-    ctx->rng = rng;
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-
-WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL* ssl = NULL;
-    int ret = 0;
-
-    (void)ret;
-    WOLFSSL_ENTER("SSL_new");
-
-    if (ctx == NULL)
-        return ssl;
-
-    ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
-    if (ssl)
-        if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
-            FreeSSL(ssl, ctx->heap);
-            ssl = 0;
-        }
-
-    WOLFSSL_LEAVE("SSL_new", ret);
-    return ssl;
-}
-
-
-void wolfSSL_free(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_free");
-    if (ssl)
-        FreeSSL(ssl, ssl->ctx->heap);
-    WOLFSSL_LEAVE("SSL_free", 0);
-}
-
-
-int wolfSSL_is_server(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-    return ssl->options.side == WOLFSSL_SERVER_END;
-}
-
-#ifdef HAVE_WRITE_DUP
-
-/*
- * Release resources around WriteDup object
- *
- * ssl WOLFSSL object
- *
- * no return, destruction so make best attempt
-*/
-void FreeWriteDup(WOLFSSL* ssl)
-{
-    int doFree = 0;
-
-    WOLFSSL_ENTER("FreeWriteDup");
-
-    if (ssl->dupWrite) {
-        if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
-            ssl->dupWrite->dupCount--;
-            if (ssl->dupWrite->dupCount == 0) {
-                doFree = 1;
-            } else {
-                WOLFSSL_MSG("WriteDup count not zero, no full free");
-            }
-            wc_UnLockMutex(&ssl->dupWrite->dupMutex);
-        }
-    }
-
-    if (doFree) {
-        WOLFSSL_MSG("Doing WriteDup full free, count to zero");
-        wc_FreeMutex(&ssl->dupWrite->dupMutex);
-        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
-    }
-}
-
-
-/*
- * duplicate existing ssl members into dup needed for writing
- *
- * dup write only WOLFSSL
- * ssl exisiting WOLFSSL
- *
- * 0 on success
-*/
-static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
-{
-    /* shared dupWrite setup */
-    ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
-                                       DYNAMIC_TYPE_WRITEDUP);
-    if (ssl->dupWrite == NULL) {
-        return MEMORY_E;
-    }
-    XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
-
-    if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
-        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
-        ssl->dupWrite = NULL;
-        return BAD_MUTEX_E;
-    }
-    ssl->dupWrite->dupCount = 2;    /* both sides have a count to start */
-    dup->dupWrite = ssl->dupWrite; /* each side uses */
-
-    /* copy write parts over to dup writer */
-    XMEMCPY(&dup->specs,   &ssl->specs,   sizeof(CipherSpecs));
-    XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
-    XMEMCPY(&dup->keys,    &ssl->keys,    sizeof(Keys));
-    XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
-    /* dup side now owns encrypt/write ciphers */
-    XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
-
-    dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
-    dup->wfd    = ssl->wfd;
-    dup->wflags = ssl->wflags;
-    dup->hmac   = ssl->hmac;
-#ifdef HAVE_TRUNCATED_HMAC
-    dup->truncated_hmac = ssl->truncated_hmac;
-#endif
-
-    /* unique side dup setup */
-    dup->dupSide = WRITE_DUP_SIDE;
-    ssl->dupSide = READ_DUP_SIDE;
-
-    return 0;
-}
-
-
-/*
- * duplicate a WOLFSSL object post handshake for writing only
- * turn exisitng object into read only.  Allows concurrent access from two
- * different threads.
- *
- * ssl exisiting WOLFSSL object
- *
- * return dup'd WOLFSSL object on success
-*/
-WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
-{
-    WOLFSSL* dup = NULL;
-    int ret = 0;
-
-    (void)ret;
-    WOLFSSL_ENTER("wolfSSL_write_dup");
-
-    if (ssl == NULL) {
-        return ssl;
-    }
-
-    if (ssl->options.handShakeDone == 0) {
-        WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
-        return NULL;
-    }
-
-    if (ssl->dupWrite) {
-        WOLFSSL_MSG("wolfSSL_write_dup already called once");
-        return NULL;
-    }
-
-    dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
-    if (dup) {
-        if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
-            FreeSSL(dup, ssl->ctx->heap);
-            dup = NULL;
-        } else if ( (ret = DupSSL(dup, ssl) < 0)) {
-            FreeSSL(dup, ssl->ctx->heap);
-            dup = NULL;
-        }
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
-
-    return dup;
-}
-
-
-/*
- * Notify write dup side of fatal error or close notify
- *
- * ssl WOLFSSL object
- * err Notify err
- *
- * 0 on success
-*/
-int NotifyWriteSide(WOLFSSL* ssl, int err)
-{
-    int ret;
-
-    WOLFSSL_ENTER("NotifyWriteSide");
-
-    ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
-    if (ret == 0) {
-        ssl->dupWrite->dupErr = err;
-        ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
-    }
-
-    return ret;
-}
-
-
-#endif /* HAVE_WRITE_DUP */
-
-
-#ifdef HAVE_POLY1305
-/* set if to use old poly 1 for yes 0 to use new poly */
-int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
-{
-    (void)ssl;
-    (void)value;
-
-#ifndef WOLFSSL_NO_TLS12
-    WOLFSSL_ENTER("SSL_use_old_poly");
-    WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
-            "is depriciated");
-    ssl->options.oldPoly = (word16)value;
-    WOLFSSL_LEAVE("SSL_use_old_poly", 0);
-#endif
-    return 0;
-}
-#endif
-
-
-int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
-{
-    int ret;
-
-    WOLFSSL_ENTER("SSL_set_fd");
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret = wolfSSL_set_read_fd(ssl, fd);
-    if (ret == WOLFSSL_SUCCESS) {
-        ret = wolfSSL_set_write_fd(ssl, fd);
-    }
-
-    return ret;
-}
-
-
-int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
-{
-    WOLFSSL_ENTER("SSL_set_read_fd");
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->rfd = fd;      /* not used directly to allow IO callbacks */
-    ssl->IOCB_ReadCtx  = &ssl->rfd;
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
-            ssl->buffers.dtlsCtx.rfd = fd;
-        }
-    #endif
-
-    WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS);
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
-{
-    WOLFSSL_ENTER("SSL_set_write_fd");
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->wfd = fd;      /* not used directly to allow IO callbacks */
-    ssl->IOCB_WriteCtx  = &ssl->wfd;
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->options.dtls) {
-            ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
-            ssl->buffers.dtlsCtx.wfd = fd;
-        }
-    #endif
-
-    WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS);
-    return WOLFSSL_SUCCESS;
-}
-
-
-/**
-  * Get the name of cipher at priority level passed in.
-  */
-char* wolfSSL_get_cipher_list(int priority)
-{
-    const CipherSuiteInfo* ciphers = GetCipherNames();
-
-    if (priority >= GetCipherNamesSize() || priority < 0) {
-        return 0;
-    }
-
-    return (char*)ciphers[priority].name;
-}
-
-
-/**
-  * Get the name of cipher at priority level passed in.
-  */
-char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority)
-{
-
-    if (ssl == NULL) {
-        return NULL;
-    }
-    else {
-        const char* cipher;
-
-        if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) {
-            if (priority == 0) {
-                return (char*)cipher;
-            }
-            else {
-                return NULL;
-            }
-        }
-        else {
-            return wolfSSL_get_cipher_list(priority);
-        }
-    }
-}
-
-
-int wolfSSL_get_ciphers(char* buf, int len)
-{
-    const CipherSuiteInfo* ciphers = GetCipherNames();
-    int  totalInc = 0;
-    int  step     = 0;
-    char delim    = ':';
-    int  size     = GetCipherNamesSize();
-    int  i;
-
-    if (buf == NULL || len <= 0)
-        return BAD_FUNC_ARG;
-
-    /* Add each member to the buffer delimited by a : */
-    for (i = 0; i < size; i++) {
-        step = (int)(XSTRLEN(ciphers[i].name) + 1);  /* delimiter */
-        totalInc += step;
-
-        /* Check to make sure buf is large enough and will not overflow */
-        if (totalInc < len) {
-            size_t cipherLen = XSTRLEN(ciphers[i].name);
-            XSTRNCPY(buf, ciphers[i].name, cipherLen);
-            buf += cipherLen;
-
-            if (i < size - 1)
-                *buf++ = delim;
-            else
-                *buf++ = '\0';
-        }
-        else
-            return BUFFER_E;
-    }
-    return WOLFSSL_SUCCESS;
-}
-
-const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
-{
-    const char* cipher;
-
-    if (ssl == NULL)
-        return NULL;
-
-    cipher = wolfSSL_get_cipher_name_iana(ssl);
-    len = min(len, (int)(XSTRLEN(cipher) + 1));
-    XMEMCPY(buf, cipher, len);
-    return buf;
-}
-
-int wolfSSL_get_fd(const WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_get_fd");
-    WOLFSSL_LEAVE("SSL_get_fd", ssl->rfd);
-    return ssl->rfd;
-}
-
-
-int wolfSSL_dtls(WOLFSSL* ssl)
-{
-    return ssl->options.dtls;
-}
-
-
-#ifndef WOLFSSL_LEANPSK
-int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
-{
-#ifdef WOLFSSL_DTLS
-    void* sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
-    if (sa != NULL) {
-        if (ssl->buffers.dtlsCtx.peer.sa != NULL)
-            XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
-        XMEMCPY(sa, peer, peerSz);
-        ssl->buffers.dtlsCtx.peer.sa = sa;
-        ssl->buffers.dtlsCtx.peer.sz = peerSz;
-        return WOLFSSL_SUCCESS;
-    }
-    return WOLFSSL_FAILURE;
-#else
-    (void)ssl;
-    (void)peer;
-    (void)peerSz;
-    return WOLFSSL_NOT_IMPLEMENTED;
-#endif
-}
-
-int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
-{
-#ifdef WOLFSSL_DTLS
-    if (ssl == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    if (peer != NULL && peerSz != NULL
-            && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
-            && ssl->buffers.dtlsCtx.peer.sa != NULL) {
-        *peerSz = ssl->buffers.dtlsCtx.peer.sz;
-        XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
-        return WOLFSSL_SUCCESS;
-    }
-    return WOLFSSL_FAILURE;
-#else
-    (void)ssl;
-    (void)peer;
-    (void)peerSz;
-    return WOLFSSL_NOT_IMPLEMENTED;
-#endif
-}
-
-
-#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
-
-int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()");
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->dtlsSctp = 1;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()");
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->options.dtlsSctp = 1;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
-{
-    if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
-        return BAD_FUNC_ARG;
-
-    ctx->dtlsMtuSz = newMtu;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (newMtu > MAX_RECORD_SIZE) {
-        ssl->error = BAD_FUNC_ARG;
-        return WOLFSSL_FAILURE;
-    }
-
-    ssl->dtlsMtuSz = newMtu;
-    return WOLFSSL_SUCCESS;
-}
-
-
-#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
-
-
-#ifdef WOLFSSL_DTLS_DROP_STATS
-
-int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
-                                word32* macDropCount, word32* replayDropCount)
-{
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
-
-    if (ssl == NULL)
-        ret = BAD_FUNC_ARG;
-    else {
-        ret = WOLFSSL_SUCCESS;
-        if (macDropCount != NULL)
-            *macDropCount = ssl->macDropCount;
-        if (replayDropCount != NULL)
-            *replayDropCount = ssl->replayDropCount;
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
-    return ret;
-}
-
-#endif /* WOLFSSL_DTLS_DROP_STATS */
-
-
-#if defined(WOLFSSL_MULTICAST)
-
-int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
-
-    if (ctx == NULL || id > 255)
-        ret = BAD_FUNC_ARG;
-
-    if (ret == 0) {
-        ctx->haveEMS = 0;
-        ctx->haveMcast = 1;
-        ctx->mcastID = id;
-#ifndef WOLFSSL_USER_IO
-        ctx->CBIORecv = EmbedReceiveFromMcast;
-#endif /* WOLFSSL_USER_IO */
-    }
-
-    if (ret == 0)
-        ret = WOLFSSL_SUCCESS;
-    WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
-    return ret;
-}
-
-int wolfSSL_mcast_get_max_peers(void)
-{
-    return WOLFSSL_MULTICAST_PEERS;
-}
-
-#ifdef WOLFSSL_DTLS
-static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
-                                         word32 second, word32 max)
-{
-    word32 newCur = 0;
-
-    if (cur < first)
-        newCur = first;
-    else if (cur < second)
-        newCur = second;
-    else if (cur < max)
-        newCur = max;
-
-    return newCur;
-}
-#endif /* WOLFSSL_DTLS */
-
-
-int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
-                       const byte* preMasterSecret, word32 preMasterSz,
-                       const byte* clientRandom, const byte* serverRandom,
-                       const byte* suite)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_set_secret()");
-
-    if (ssl == NULL || preMasterSecret == NULL ||
-        preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
-        clientRandom == NULL || serverRandom == NULL || suite == NULL) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
-        ssl->arrays->preMasterSz = preMasterSz;
-        XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
-        XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
-        ssl->options.cipherSuite0 = suite[0];
-        ssl->options.cipherSuite = suite[1];
-
-        ret = SetCipherSpecs(ssl);
-    }
-
-    if (ret == 0)
-        ret = MakeTlsMasterSecret(ssl);
-
-    if (ret == 0) {
-        ssl->keys.encryptionOn = 1;
-        ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
-    }
-
-    if (ret == 0) {
-        if (ssl->options.dtls) {
-        #ifdef WOLFSSL_DTLS
-            WOLFSSL_DTLS_PEERSEQ* peerSeq;
-            int i;
-
-            ssl->keys.dtls_epoch = epoch;
-            for (i = 0, peerSeq = ssl->keys.peerSeq;
-                 i < WOLFSSL_DTLS_PEERSEQ_SZ;
-                 i++, peerSeq++) {
-
-                peerSeq->nextEpoch = epoch;
-                peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
-                peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
-                peerSeq->nextSeq_lo = 0;
-                peerSeq->nextSeq_hi = 0;
-                XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
-                XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
-                peerSeq->highwaterMark = UpdateHighwaterMark(0,
-                        ssl->ctx->mcastFirstSeq,
-                        ssl->ctx->mcastSecondSeq,
-                        ssl->ctx->mcastMaxSeq);
-            }
-        #else
-            (void)epoch;
-        #endif
-        }
-        FreeHandshakeResources(ssl);
-        ret = WOLFSSL_SUCCESS;
-    }
-    else {
-        if (ssl)
-            ssl->error = ret;
-        ret = WOLFSSL_FATAL_ERROR;
-    }
-    WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
-    return ret;
-}
-
-
-#ifdef WOLFSSL_DTLS
-
-int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove)
-{
-    WOLFSSL_DTLS_PEERSEQ* p = NULL;
-    int ret = WOLFSSL_SUCCESS;
-    int i;
-
-    WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
-    if (ssl == NULL || peerId > 255)
-        return BAD_FUNC_ARG;
-
-    if (!remove) {
-        /* Make sure it isn't already present, while keeping the first
-         * open spot. */
-        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
-            if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
-                p = &ssl->keys.peerSeq[i];
-            if (ssl->keys.peerSeq[i].peerId == peerId) {
-                WOLFSSL_MSG("Peer ID already in multicast peer list.");
-                p = NULL;
-            }
-        }
-
-        if (p != NULL) {
-            XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
-            p->peerId = peerId;
-            p->highwaterMark = UpdateHighwaterMark(0,
-                ssl->ctx->mcastFirstSeq,
-                ssl->ctx->mcastSecondSeq,
-                ssl->ctx->mcastMaxSeq);
-        }
-        else {
-            WOLFSSL_MSG("No room in peer list.");
-            ret = -1;
-        }
-    }
-    else {
-        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
-            if (ssl->keys.peerSeq[i].peerId == peerId)
-                p = &ssl->keys.peerSeq[i];
-        }
-
-        if (p != NULL) {
-            p->peerId = INVALID_PEER_ID;
-        }
-        else {
-            WOLFSSL_MSG("Peer not found in list.");
-        }
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
-    return ret;
-}
-
-
-/* If peerId is in the list of peers and its last sequence number is non-zero,
- * return 1, otherwise return 0. */
-int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
-{
-    int known = 0;
-    int i;
-
-    WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
-
-    if (ssl == NULL || peerId > 255) {
-        return BAD_FUNC_ARG;
-    }
-
-    for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
-        if (ssl->keys.peerSeq[i].peerId == peerId) {
-            if (ssl->keys.peerSeq[i].nextSeq_hi ||
-                ssl->keys.peerSeq[i].nextSeq_lo) {
-
-                known = 1;
-            }
-            break;
-        }
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
-    return known;
-}
-
-
-int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
-                                       word32 first, word32 second,
-                                       CallbackMcastHighwater cb)
-{
-    if (ctx == NULL || (second && first > second) ||
-        first > maxSeq || second > maxSeq || cb == NULL) {
-
-        return BAD_FUNC_ARG;
-    }
-
-    ctx->mcastHwCb = cb;
-    ctx->mcastFirstSeq = first;
-    ctx->mcastSecondSeq = second;
-    ctx->mcastMaxSeq = maxSeq;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
-{
-    if (ssl == NULL || ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->mcastHwCbCtx = ctx;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* WOLFSSL_DTLS */
-
-#endif /* WOLFSSL_MULTICAST */
-
-
-#endif /* WOLFSSL_LEANPSK */
-
-
-/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
-int wolfSSL_negotiate(WOLFSSL* ssl)
-{
-    int err = WOLFSSL_FATAL_ERROR;
-
-    WOLFSSL_ENTER("wolfSSL_negotiate");
-#ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(ssl->version))
-            err = wolfSSL_accept_TLSv13(ssl);
-        else
-#endif
-            err = wolfSSL_accept(ssl);
-    }
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-#ifdef WOLFSSL_TLS13
-        if (IsAtLeastTLSv1_3(ssl->version))
-            err = wolfSSL_connect_TLSv13(ssl);
-        else
-#endif
-            err = wolfSSL_connect(ssl);
-    }
-#endif
-
-    (void)ssl;
-
-    WOLFSSL_LEAVE("wolfSSL_negotiate", err);
-
-    return err;
-}
-
-
-WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
-{
-    if (ssl) {
-        return ssl->rng;
-    }
-
-    return NULL;
-}
-
-
-#ifndef WOLFSSL_LEANPSK
-/* object size based on build */
-int wolfSSL_GetObjectSize(void)
-{
-#ifdef SHOW_SIZES
-    printf("sizeof suites           = %lu\n", sizeof(Suites));
-    printf("sizeof ciphers(2)       = %lu\n", sizeof(Ciphers));
-#ifndef NO_RC4
-    printf("\tsizeof arc4         = %lu\n", sizeof(Arc4));
-#endif
-    printf("\tsizeof aes          = %lu\n", sizeof(Aes));
-#ifndef NO_DES3
-    printf("\tsizeof des3         = %lu\n", sizeof(Des3));
-#endif
-#ifndef NO_RABBIT
-    printf("\tsizeof rabbit       = %lu\n", sizeof(Rabbit));
-#endif
-#ifdef HAVE_CHACHA
-    printf("\tsizeof chacha       = %lu\n", sizeof(ChaCha));
-#endif
-    printf("sizeof cipher specs     = %lu\n", sizeof(CipherSpecs));
-    printf("sizeof keys             = %lu\n", sizeof(Keys));
-    printf("sizeof Hashes(2)        = %lu\n", sizeof(Hashes));
-#ifndef NO_MD5
-    printf("\tsizeof MD5          = %lu\n", sizeof(wc_Md5));
-#endif
-#ifndef NO_SHA
-    printf("\tsizeof SHA          = %lu\n", sizeof(wc_Sha));
-#endif
-#ifdef WOLFSSL_SHA224
-    printf("\tsizeof SHA224       = %lu\n", sizeof(wc_Sha224));
-#endif
-#ifndef NO_SHA256
-    printf("\tsizeof SHA256       = %lu\n", sizeof(wc_Sha256));
-#endif
-#ifdef WOLFSSL_SHA384
-    printf("\tsizeof SHA384       = %lu\n", sizeof(wc_Sha384));
-#endif
-#ifdef WOLFSSL_SHA384
-    printf("\tsizeof SHA512       = %lu\n", sizeof(wc_Sha512));
-#endif
-    printf("sizeof Buffers          = %lu\n", sizeof(Buffers));
-    printf("sizeof Options          = %lu\n", sizeof(Options));
-    printf("sizeof Arrays           = %lu\n", sizeof(Arrays));
-#ifndef NO_RSA
-    printf("sizeof RsaKey           = %lu\n", sizeof(RsaKey));
-#endif
-#ifdef HAVE_ECC
-    printf("sizeof ecc_key          = %lu\n", sizeof(ecc_key));
-#endif
-    printf("sizeof WOLFSSL_CIPHER    = %lu\n", sizeof(WOLFSSL_CIPHER));
-    printf("sizeof WOLFSSL_SESSION   = %lu\n", sizeof(WOLFSSL_SESSION));
-    printf("sizeof WOLFSSL           = %lu\n", sizeof(WOLFSSL));
-    printf("sizeof WOLFSSL_CTX       = %lu\n", sizeof(WOLFSSL_CTX));
-#endif
-
-    return sizeof(WOLFSSL);
-}
-
-int wolfSSL_CTX_GetObjectSize(void)
-{
-    return sizeof(WOLFSSL_CTX);
-}
-
-int wolfSSL_METHOD_GetObjectSize(void)
-{
-    return sizeof(WOLFSSL_METHOD);
-}
-#endif
-
-
-#ifdef WOLFSSL_STATIC_MEMORY
-
-int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method,
-                                   unsigned char* buf, unsigned int sz,
-                                   int flag, int max)
-{
-    WOLFSSL_HEAP*      heap;
-    WOLFSSL_HEAP_HINT* hint;
-    word32 idx = 0;
-
-    if (ctx == NULL || buf == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (*ctx == NULL && method == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (*ctx == NULL || (*ctx)->heap == NULL) {
-        if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) {
-            return BUFFER_E; /* not enough memory for structures */
-        }
-        heap = (WOLFSSL_HEAP*)buf;
-        idx += sizeof(WOLFSSL_HEAP);
-        if (wolfSSL_init_memory_heap(heap) != 0) {
-            return WOLFSSL_FAILURE;
-        }
-        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
-        idx += sizeof(WOLFSSL_HEAP_HINT);
-        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
-        hint->memory = heap;
-
-        if (*ctx && (*ctx)->heap == NULL) {
-            (*ctx)->heap = (void*)hint;
-        }
-    }
-    else {
-#ifdef WOLFSSL_HEAP_TEST
-        /* do not load in memory if test has been set */
-        if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) {
-            return WOLFSSL_SUCCESS;
-        }
-#endif
-        hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap);
-        heap = hint->memory;
-    }
-
-    if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) {
-        WOLFSSL_MSG("Error partitioning memory");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* create ctx if needed */
-    if (*ctx == NULL) {
-        *ctx = wolfSSL_CTX_new_ex(method(hint), hint);
-        if (*ctx == NULL) {
-            WOLFSSL_MSG("Error creating ctx");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    /* determine what max applies too */
-    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
-        heap->maxIO = max;
-    }
-    else { /* general memory used in handshakes */
-        heap->maxHa = max;
-    }
-
-    heap->flag |= flag;
-
-    (void)max;
-    (void)method;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
-{
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    WOLFSSL_ENTER("wolfSSL_is_static_memory");
-
-    /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
-    if (mem_stats != NULL && ssl->heap != NULL) {
-        WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
-        WOLFSSL_HEAP* heap      = hint->memory;
-        if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) {
-            XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
-        }
-    }
-
-    return (ssl->heap) ? 1 : 0;
-}
-
-
-int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
-{
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
-
-    /* fill out statistics if wanted */
-    if (mem_stats != NULL && ctx->heap != NULL) {
-        WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
-        if (wolfSSL_GetMemStats(heap, mem_stats) != 1) {
-            return MEMORY_E;
-        }
-    }
-
-    return (ctx->heap) ? 1 : 0;
-}
-
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-
-/* return max record layer size plaintext input size */
-int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize");
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
-        WOLFSSL_MSG("Handshake not complete yet");
-        return BAD_FUNC_ARG;
-    }
-
-    return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE);
-}
-
-
-/* return record layer size of plaintext input size */
-int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
-{
-    int maxSize;
-
-    WOLFSSL_ENTER("wolfSSL_GetOutputSize");
-
-    if (inSz < 0)
-        return BAD_FUNC_ARG;
-
-    maxSize = wolfSSL_GetMaxOutputSize(ssl);
-    if (maxSize < 0)
-        return maxSize;   /* error */
-    if (inSz > maxSize)
-        return INPUT_SIZE_E;
-
-    return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0);
-}
-
-
-#ifdef HAVE_ECC
-int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
-{
-    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
-        WOLFSSL_MSG("Key size must be divisable by 8 or ctx was null");
-        return BAD_FUNC_ARG;
-    }
-
-    ctx->minEccKeySz     = keySz / 8;
-#ifndef NO_CERTS
-    ctx->cm->minEccKeySz = keySz / 8;
-#endif
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
-{
-    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
-        WOLFSSL_MSG("Key size must be divisable by 8 or ssl was null");
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->options.minEccKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* !NO_RSA */
-
-#ifndef NO_RSA
-int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
-{
-    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
-        WOLFSSL_MSG("Key size must be divisable by 8 or ctx was null");
-        return BAD_FUNC_ARG;
-    }
-
-    ctx->minRsaKeySz     = keySz / 8;
-    ctx->cm->minRsaKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
-{
-    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
-        WOLFSSL_MSG("Key size must be divisable by 8 or ssl was null");
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->options.minRsaKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-#endif /* !NO_RSA */
-
-#ifndef NO_DH
-/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
-int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
-                    const unsigned char* g, int gSz)
-{
-    word16 havePSK = 0;
-    word16 haveRSA = 1;
-    int    keySz   = 0;
-
-    WOLFSSL_ENTER("wolfSSL_SetTmpDH");
-    if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
-
-    if (pSz < ssl->options.minDhKeySz)
-        return DH_KEY_SIZE_E;
-    if (pSz > ssl->options.maxDhKeySz)
-        return DH_KEY_SIZE_E;
-
-    if (ssl->options.side != WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-
-    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        ssl->buffers.serverDH_P.buffer = NULL;
-    }
-    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        ssl->buffers.serverDH_G.buffer = NULL;
-    }
-
-    ssl->buffers.weOwnDH = 1;  /* SSL owns now */
-    ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap,
-                                                    DYNAMIC_TYPE_PUBLIC_KEY);
-    if (ssl->buffers.serverDH_P.buffer == NULL)
-            return MEMORY_E;
-
-    ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap,
-                                                    DYNAMIC_TYPE_PUBLIC_KEY);
-    if (ssl->buffers.serverDH_G.buffer == NULL) {
-        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        ssl->buffers.serverDH_P.buffer = NULL;
-        return MEMORY_E;
-    }
-
-    ssl->buffers.serverDH_P.length = pSz;
-    ssl->buffers.serverDH_G.length = gSz;
-
-    XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz);
-    XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz);
-
-    ssl->options.haveDH = 1;
-    #ifndef NO_PSK
-        havePSK = ssl->options.havePSK;
-    #endif
-    #ifdef NO_RSA
-        haveRSA = 0;
-    #endif
-    #ifndef NO_CERTS
-        keySz = ssl->buffers.keySz;
-    #endif
-    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-               ssl->options.haveDH, ssl->options.haveNTRU,
-               ssl->options.haveECDSAsig, ssl->options.haveECC,
-               ssl->options.haveStaticECC, ssl->options.side);
-
-    WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0);
-    return WOLFSSL_SUCCESS;
-}
-
-/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
-                         const unsigned char* g, int gSz)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
-    if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
-
-    if (pSz < ctx->minDhKeySz)
-        return DH_KEY_SIZE_E;
-    if (pSz > ctx->maxDhKeySz)
-        return DH_KEY_SIZE_E;
-
-    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-
-    ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (ctx->serverDH_P.buffer == NULL)
-       return MEMORY_E;
-
-    ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (ctx->serverDH_G.buffer == NULL) {
-        XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        return MEMORY_E;
-    }
-
-    ctx->serverDH_P.length = pSz;
-    ctx->serverDH_G.length = gSz;
-
-    XMEMCPY(ctx->serverDH_P.buffer, p, pSz);
-    XMEMCPY(ctx->serverDH_G.buffer, g, gSz);
-
-    ctx->haveDH = 1;
-
-    WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
-{
-    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
-        return BAD_FUNC_ARG;
-
-    ctx->minDhKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
-{
-    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
-        return BAD_FUNC_ARG;
-
-    ssl->options.minDhKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
-{
-    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
-        return BAD_FUNC_ARG;
-
-    ctx->maxDhKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz)
-{
-    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
-        return BAD_FUNC_ARG;
-
-    ssl->options.maxDhKeySz = keySz / 8;
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return (ssl->options.dhKeySz * 8);
-}
-
-#endif /* !NO_DH */
-
-
-int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
-{
-    int ret;
-
-    WOLFSSL_ENTER("SSL_write()");
-
-    if (ssl == NULL || data == NULL || sz < 0)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
-        ssl->error = ret;
-        return WOLFSSL_FATAL_ERROR;
-    }
-    ssl->earlyData = no_early_data;
-#endif
-
-#ifdef HAVE_WRITE_DUP
-    { /* local variable scope */
-        int dupErr = 0;   /* local copy */
-
-        ret = 0;
-
-        if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
-            WOLFSSL_MSG("Read dup side cannot write");
-            return WRITE_DUP_WRITE_E;
-        }
-        if (ssl->dupWrite) {
-            if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
-                return BAD_MUTEX_E;
-            }
-            dupErr = ssl->dupWrite->dupErr;
-            ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
-        }
-
-        if (ret != 0) {
-            ssl->error = ret;  /* high priority fatal error */
-            return WOLFSSL_FATAL_ERROR;
-        }
-        if (dupErr != 0) {
-            WOLFSSL_MSG("Write dup error from other side");
-            ssl->error = dupErr;
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-#endif
-
-#ifdef HAVE_ERRNO_H
-    errno = 0;
-#endif
-
-    #ifdef OPENSSL_EXTRA
-    if (ssl->CBIS != NULL) {
-        ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS);
-        ssl->cbmode = SSL_CB_WRITE;
-    }
-    #endif
-    ret = SendData(ssl, data, sz);
-
-    WOLFSSL_LEAVE("SSL_write()", ret);
-
-    if (ret < 0)
-        return WOLFSSL_FATAL_ERROR;
-    else
-        return ret;
-}
-
-static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
-{
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_read_internal()");
-
-    if (ssl == NULL || data == NULL || sz < 0)
-        return BAD_FUNC_ARG;
-
-#ifdef HAVE_WRITE_DUP
-    if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
-        WOLFSSL_MSG("Write dup side cannot read");
-        return WRITE_DUP_READ_E;
-    }
-#endif
-
-#ifdef HAVE_ERRNO_H
-        errno = 0;
-#endif
-
-#ifdef WOLFSSL_DTLS
-    if (ssl->options.dtls) {
-        ssl->dtls_expected_rx = max(sz + 100, MAX_MTU);
-#ifdef WOLFSSL_SCTP
-        if (ssl->options.dtlsSctp)
-            ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz);
-#endif
-    }
-#endif
-
-    sz = wolfSSL_GetMaxRecordSize(ssl, sz);
-
-    ret = ReceiveData(ssl, (byte*)data, sz, peek);
-
-#ifdef HAVE_WRITE_DUP
-    if (ssl->dupWrite) {
-        if (ssl->error != 0 && ssl->error != WANT_READ
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            && ssl->error != WC_PENDING_E
-        #endif
-        ) {
-            int notifyErr;
-
-            WOLFSSL_MSG("Notifying write side of fatal read error");
-            notifyErr  = NotifyWriteSide(ssl, ssl->error);
-            if (notifyErr < 0) {
-                ret = ssl->error = notifyErr;
-            }
-        }
-    }
-#endif
-
-    WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
-
-    if (ret < 0)
-        return WOLFSSL_FATAL_ERROR;
-    else
-        return ret;
-}
-
-
-int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
-{
-    WOLFSSL_ENTER("wolfSSL_peek()");
-
-    return wolfSSL_read_internal(ssl, data, sz, TRUE);
-}
-
-
-int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
-{
-    WOLFSSL_ENTER("wolfSSL_read()");
-
-    #ifdef OPENSSL_EXTRA
-    if (ssl->CBIS != NULL) {
-        ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS);
-        ssl->cbmode = SSL_CB_READ;
-    }
-    #endif
-    return wolfSSL_read_internal(ssl, data, sz, FALSE);
-}
-
-
-#ifdef WOLFSSL_MULTICAST
-
-int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_mcast_read()");
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
-    if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
-        *id = ssl->keys.curPeerId;
-    return ret;
-}
-
-#endif /* WOLFSSL_MULTICAST */
-
-
-/* helpers to set the device id, WOLFSSL_SUCCESS on ok */
-int wolfSSL_SetDevId(WOLFSSL* ssl, int devId)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->devId = devId;
-
-    return WOLFSSL_SUCCESS;
-}
-int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->devId = devId;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* helpers to get device id and heap */
-int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
-{
-    int devId = INVALID_DEVID;
-    if (ctx != NULL)
-        devId = ctx->devId;
-    else if (ssl != NULL)
-        devId = ssl->devId;
-    return devId;
-}
-void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
-{
-    void* heap = NULL;
-    if (ctx != NULL)
-        heap = ctx->heap;
-    else if (ssl != NULL)
-        heap = ssl->heap;
-    return heap;
-}
-
-
-#ifdef HAVE_SNI
-
-int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap);
-}
-
-
-int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data,
-                                                                    word16 size)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap);
-}
-
-#ifndef NO_WOLFSSL_SERVER
-
-void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options)
-{
-    if (ssl && ssl->extensions)
-        TLSX_SNI_SetOptions(ssl->extensions, type, options);
-}
-
-
-void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options)
-{
-    if (ctx && ctx->extensions)
-        TLSX_SNI_SetOptions(ctx->extensions, type, options);
-}
-
-
-byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type)
-{
-    return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type);
-}
-
-
-word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
-{
-    if (data)
-        *data = NULL;
-
-    if (ssl && ssl->extensions)
-        return TLSX_SNI_GetRequest(ssl->extensions, type, data);
-
-    return 0;
-}
-
-
-int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
-                              byte type, byte* sni, word32* inOutSz)
-{
-    if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0)
-        return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz);
-
-    return BAD_FUNC_ARG;
-}
-
-#endif /* NO_WOLFSSL_SERVER */
-
-#endif /* HAVE_SNI */
-
-
-#ifdef HAVE_MAX_FRAGMENT
-#ifndef NO_WOLFSSL_CLIENT
-
-int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap);
-}
-
-
-int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap);
-}
-
-#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_MAX_FRAGMENT */
-
-#ifdef HAVE_TRUNCATED_HMAC
-#ifndef NO_WOLFSSL_CLIENT
-
-int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
-}
-
-
-int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap);
-}
-
-#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_TRUNCATED_HMAC */
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-
-int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
-{
-    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
-                                          options, NULL, ssl->heap, ssl->devId);
-}
-
-
-int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
-                                                                   byte options)
-{
-    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
-                                          options, NULL, ctx->heap, ctx->devId);
-}
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-
-int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
-{
-    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
-                                                options, ssl->heap, ssl->devId);
-}
-
-
-int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
-                                                                   byte options)
-{
-    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
-                                                options, ctx->heap, ctx->devId);
-}
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-
-/* Elliptic Curves */
-#ifdef HAVE_SUPPORTED_CURVES
-#ifndef NO_WOLFSSL_CLIENT
-
-int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (name) {
-        case WOLFSSL_ECC_SECP160K1:
-        case WOLFSSL_ECC_SECP160R1:
-        case WOLFSSL_ECC_SECP160R2:
-        case WOLFSSL_ECC_SECP192K1:
-        case WOLFSSL_ECC_SECP192R1:
-        case WOLFSSL_ECC_SECP224K1:
-        case WOLFSSL_ECC_SECP224R1:
-        case WOLFSSL_ECC_SECP256K1:
-        case WOLFSSL_ECC_SECP256R1:
-        case WOLFSSL_ECC_SECP384R1:
-        case WOLFSSL_ECC_SECP521R1:
-        case WOLFSSL_ECC_BRAINPOOLP256R1:
-        case WOLFSSL_ECC_BRAINPOOLP384R1:
-        case WOLFSSL_ECC_BRAINPOOLP512R1:
-        case WOLFSSL_ECC_X25519:
-            break;
-
-#ifdef WOLFSSL_TLS13
-        case WOLFSSL_FFDHE_2048:
-        case WOLFSSL_FFDHE_3072:
-        case WOLFSSL_FFDHE_4096:
-        case WOLFSSL_FFDHE_6144:
-        case WOLFSSL_FFDHE_8192:
-            if (!IsAtLeastTLSv1_3(ssl->version))
-                return WOLFSSL_SUCCESS;
-            break;
-#endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    ssl->options.userCurves = 1;
-
-    return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
-}
-
-
-int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (name) {
-        case WOLFSSL_ECC_SECP160K1:
-        case WOLFSSL_ECC_SECP160R1:
-        case WOLFSSL_ECC_SECP160R2:
-        case WOLFSSL_ECC_SECP192K1:
-        case WOLFSSL_ECC_SECP192R1:
-        case WOLFSSL_ECC_SECP224K1:
-        case WOLFSSL_ECC_SECP224R1:
-        case WOLFSSL_ECC_SECP256K1:
-        case WOLFSSL_ECC_SECP256R1:
-        case WOLFSSL_ECC_SECP384R1:
-        case WOLFSSL_ECC_SECP521R1:
-        case WOLFSSL_ECC_BRAINPOOLP256R1:
-        case WOLFSSL_ECC_BRAINPOOLP384R1:
-        case WOLFSSL_ECC_BRAINPOOLP512R1:
-        case WOLFSSL_ECC_X25519:
-            break;
-
-#ifdef WOLFSSL_TLS13
-        case WOLFSSL_FFDHE_2048:
-        case WOLFSSL_FFDHE_3072:
-        case WOLFSSL_FFDHE_4096:
-        case WOLFSSL_FFDHE_6144:
-        case WOLFSSL_FFDHE_8192:
-            break;
-#endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    ctx->userCurves = 1;
-
-    return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap);
-}
-
-#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_SUPPORTED_CURVES */
-
-/* QSH quantum safe handshake */
-#ifdef HAVE_QSH
-/* returns 1 if QSH has been used 0 otherwise */
-int wolfSSL_isQSH(WOLFSSL* ssl)
-{
-    /* if no ssl struct than QSH was not used */
-    if (ssl == NULL)
-        return 0;
-
-    return ssl->isQSH;
-}
-
-
-int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (name) {
-    #ifdef HAVE_NTRU
-        case WOLFSSL_NTRU_EESS439:
-        case WOLFSSL_NTRU_EESS593:
-        case WOLFSSL_NTRU_EESS743:
-            break;
-    #endif
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    ssl->user_set_QSHSchemes = 1;
-
-    return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
-}
-
-#ifndef NO_WOLFSSL_CLIENT
-    /* user control over sending client public key in hello
-       when flag = 1 will send keys if flag is 0 or function is not called
-       then will not send keys in the hello extension
-       return 0 on success
-     */
-    int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag)
-    {
-        if (ssl == NULL)
-            return BAD_FUNC_ARG;
-
-        ssl->sendQSHKeys = flag;
-
-        return 0;
-    }
-#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_QSH */
-
-/* Application-Layer Protocol Negotiation */
-#ifdef HAVE_ALPN
-
-int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
-                    word32 protocol_name_listSz, byte options)
-{
-    char    *list, *ptr, *token[10];
-    word16  len;
-    int     idx = 0;
-    int     ret = WOLFSSL_FAILURE;
-
-    WOLFSSL_ENTER("wolfSSL_UseALPN");
-
-    if (ssl == NULL || protocol_name_list == NULL)
-        return BAD_FUNC_ARG;
-
-    if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
-                                WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
-                                WOLFSSL_MAX_ALPN_NUMBER)) {
-        WOLFSSL_MSG("Invalid arguments, protocol name list too long");
-        return BAD_FUNC_ARG;
-    }
-
-    if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
-        !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
-            WOLFSSL_MSG("Invalid arguments, options not supported");
-            return BAD_FUNC_ARG;
-        }
-
-
-    list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap,
-                           DYNAMIC_TYPE_ALPN);
-    if (list == NULL) {
-        WOLFSSL_MSG("Memory failure");
-        return MEMORY_ERROR;
-    }
-
-    XSTRNCPY(list, protocol_name_list, protocol_name_listSz);
-    list[protocol_name_listSz] = '\0';
-
-    /* read all protocol name from the list */
-    token[idx] = XSTRTOK(list, ",", &ptr);
-    while (token[idx] != NULL)
-        token[++idx] = XSTRTOK(NULL, ",", &ptr);
-
-    /* add protocol name list in the TLS extension in reverse order */
-    while ((idx--) > 0) {
-        len = (word16)XSTRLEN(token[idx]);
-
-        ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options,
-                                                                     ssl->heap);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("TLSX_UseALPN failure");
-            break;
-        }
-    }
-
-    XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
-
-    return ret;
-}
-
-int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
-{
-    return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL,
-                               (void **)protocol_name, size);
-}
-
-int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
-{
-    if (list == NULL || listSz == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->alpn_client_list == NULL)
-        return BUFFER_ERROR;
-
-    *listSz = (word16)XSTRLEN(ssl->alpn_client_list);
-    if (*listSz == 0)
-        return BUFFER_ERROR;
-
-    *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
-    if (*list == NULL)
-        return MEMORY_ERROR;
-
-    XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
-    (*list)[*listSz] = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */
-int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
-{
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX);
-    *list = NULL;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* HAVE_ALPN */
-
-/* Secure Renegotiation */
-#ifdef HAVE_SECURE_RENEGOTIATION
-
-/* user is forcing ability to use secure renegotiation, we discourage it */
-int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
-{
-    int ret = BAD_FUNC_ARG;
-
-    if (ssl)
-        ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
-
-    if (ret == WOLFSSL_SUCCESS) {
-        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
-
-        if (extension)
-            ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
-    }
-
-    return ret;
-}
-
-
-/* do a secure renegotiation handshake, user forced, we discourage */
-int wolfSSL_Rehandshake(WOLFSSL* ssl)
-{
-    int ret;
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->secure_renegotiation == NULL) {
-        WOLFSSL_MSG("Secure Renegotiation not forced on by user");
-        return SECURE_RENEGOTIATION_E;
-    }
-
-    if (ssl->secure_renegotiation->enabled == 0) {
-        WOLFSSL_MSG("Secure Renegotiation not enabled at extension level");
-        return SECURE_RENEGOTIATION_E;
-    }
-
-    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
-        WOLFSSL_MSG("Can't renegotiate until previous handshake complete");
-        return SECURE_RENEGOTIATION_E;
-    }
-
-#ifndef NO_FORCE_SCR_SAME_SUITE
-    /* force same suite */
-    if (ssl->suites) {
-        ssl->suites->suiteSz = SUITE_LEN;
-        ssl->suites->suites[0] = ssl->options.cipherSuite0;
-        ssl->suites->suites[1] = ssl->options.cipherSuite;
-    }
-#endif
-
-    /* reset handshake states */
-    ssl->options.serverState = NULL_STATE;
-    ssl->options.clientState = NULL_STATE;
-    ssl->options.connectState  = CONNECT_BEGIN;
-    ssl->options.acceptState   = ACCEPT_BEGIN;
-    ssl->options.handShakeState = NULL_STATE;
-    ssl->options.processReply  = 0;  /* TODO, move states in internal.h */
-
-    XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
-
-    ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
-
-    ret = InitHandshakeHashes(ssl);
-    if (ret !=0)
-        return ret;
-
-    ret = wolfSSL_negotiate(ssl);
-    return ret;
-}
-
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-/* Session Ticket */
-#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
-/* WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->ticketEncCb = cb;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* set hint interval, WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->ticketHint = hint;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* set user context, WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->ticketEncCtx = userCtx;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */
-
-/* Session Ticket */
-#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
-int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
-}
-
-int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap);
-}
-
-WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl,
-                                          byte* buf, word32* bufSz)
-{
-    if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (ssl->session.ticketLen <= *bufSz) {
-        XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen);
-        *bufSz = ssl->session.ticketLen;
-    }
-    else
-        *bufSz = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-
-WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
-                                          word32 bufSz)
-{
-    if (ssl == NULL || (buf == NULL && bufSz > 0))
-        return BAD_FUNC_ARG;
-
-    if (bufSz > 0) {
-        /* Ticket will fit into static ticket */
-        if(bufSz <= SESSION_TICKET_LEN) {
-            if (ssl->session.isDynamic) {
-                XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-                ssl->session.isDynamic = 0;
-                ssl->session.ticket = ssl->session.staticTicket;
-            }
-        } else { /* Ticket requires dynamic ticket storage */
-            if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */
-                if(ssl->session.isDynamic)
-                    XFREE(ssl->session.ticket, ssl->heap,
-                            DYNAMIC_TYPE_SESSION_TICK);
-                ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap,
-                        DYNAMIC_TYPE_SESSION_TICK);
-                if(!ssl->session.ticket) {
-                    ssl->session.ticket = ssl->session.staticTicket;
-                    ssl->session.isDynamic = 0;
-                    return MEMORY_ERROR;
-                }
-                ssl->session.isDynamic = 1;
-            }
-        }
-        XMEMCPY(ssl->session.ticket, buf, bufSz);
-    }
-    ssl->session.ticketLen = (word16)bufSz;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
-                                            CallbackSessionTicket cb, void* ctx)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->session_ticket_cb = cb;
-    ssl->session_ticket_ctx = ctx;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-
-#ifdef HAVE_EXTENDED_MASTER
-#ifndef NO_WOLFSSL_CLIENT
-
-int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->haveEMS = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->options.haveEMS = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif
-#endif
-
-
-#ifndef WOLFSSL_LEANPSK
-
-int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
-{
-    int ret;
-    int oldFlags;
-
-    WOLFSSL_ENTER("wolfSSL_send()");
-
-    if (ssl == NULL || data == NULL || sz < 0)
-        return BAD_FUNC_ARG;
-
-    oldFlags = ssl->wflags;
-
-    ssl->wflags = flags;
-    ret = wolfSSL_write(ssl, data, sz);
-    ssl->wflags = oldFlags;
-
-    WOLFSSL_LEAVE("wolfSSL_send()", ret);
-
-    return ret;
-}
-
-
-int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
-{
-    int ret;
-    int oldFlags;
-
-    WOLFSSL_ENTER("wolfSSL_recv()");
-
-    if (ssl == NULL || data == NULL || sz < 0)
-        return BAD_FUNC_ARG;
-
-    oldFlags = ssl->rflags;
-
-    ssl->rflags = flags;
-    ret = wolfSSL_read(ssl, data, sz);
-    ssl->rflags = oldFlags;
-
-    WOLFSSL_LEAVE("wolfSSL_recv()", ret);
-
-    return ret;
-}
-#endif
-
-
-/* WOLFSSL_SUCCESS on ok */
-int wolfSSL_shutdown(WOLFSSL* ssl)
-{
-    int  ret = WOLFSSL_FATAL_ERROR;
-    byte tmp;
-    WOLFSSL_ENTER("SSL_shutdown()");
-
-    if (ssl == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    if (ssl->options.quietShutdown) {
-        WOLFSSL_MSG("quiet shutdown, no close notify sent");
-        ret = WOLFSSL_SUCCESS;
-    }
-    else {
-        /* try to send close notify, not an error if can't */
-        if (!ssl->options.isClosed && !ssl->options.connReset &&
-                                      !ssl->options.sentNotify) {
-            ssl->error = SendAlert(ssl, alert_warning, close_notify);
-            if (ssl->error < 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.sentNotify = 1;  /* don't send close_notify twice */
-            if (ssl->options.closeNotify)
-                ret = WOLFSSL_SUCCESS;
-            else {
-                ret = WOLFSSL_SHUTDOWN_NOT_DONE;
-                WOLFSSL_LEAVE("SSL_shutdown()", ret);
-                return ret;
-            }
-        }
-
-        /* call wolfSSL_shutdown again for bidirectional shutdown */
-        if (ssl->options.sentNotify && !ssl->options.closeNotify) {
-            ret = wolfSSL_read(ssl, &tmp, 0);
-            if (ret < 0) {
-                WOLFSSL_ERROR(ssl->error);
-                ret = WOLFSSL_FATAL_ERROR;
-            } else if (ssl->options.closeNotify) {
-                ssl->error = WOLFSSL_ERROR_SYSCALL;   /* simulate OpenSSL behavior */
-                ret = WOLFSSL_SUCCESS;
-            }
-        }
-    }
-
-#ifdef OPENSSL_EXTRA
-    /* reset WOLFSSL structure state for possible re-use */
-    if (ret == WOLFSSL_SUCCESS) {
-        if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("could not clear WOLFSSL");
-            ret = WOLFSSL_FATAL_ERROR;
-        }
-    }
-#endif
-
-    WOLFSSL_LEAVE("SSL_shutdown()", ret);
-
-    return ret;
-}
-
-
-/* get current error state value */
-int wolfSSL_state(WOLFSSL* ssl)
-{
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    return ssl->error;
-}
-
-
-int wolfSSL_get_error(WOLFSSL* ssl, int ret)
-{
-    WOLFSSL_ENTER("SSL_get_error");
-
-    if (ret > 0)
-        return WOLFSSL_ERROR_NONE;
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    WOLFSSL_LEAVE("SSL_get_error", ssl->error);
-
-    /* make sure converted types are handled in SetErrorString() too */
-    if (ssl->error == WANT_READ)
-        return WOLFSSL_ERROR_WANT_READ;         /* convert to OpenSSL type */
-    else if (ssl->error == WANT_WRITE)
-        return WOLFSSL_ERROR_WANT_WRITE;        /* convert to OpenSSL type */
-    else if (ssl->error == ZERO_RETURN)
-        return WOLFSSL_ERROR_ZERO_RETURN;       /* convert to OpenSSL type */
-    return ssl->error;
-}
-
-
-/* retrive alert history, WOLFSSL_SUCCESS on ok */
-int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
-{
-    if (ssl && h) {
-        *h = ssl->alert_history;
-    }
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* return TRUE if current error is want read */
-int wolfSSL_want_read(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_want_read");
-    if (ssl->error == WANT_READ)
-        return 1;
-
-    return 0;
-}
-
-
-/* return TRUE if current error is want write */
-int wolfSSL_want_write(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_want_write");
-    if (ssl->error == WANT_WRITE)
-        return 1;
-
-    return 0;
-}
-
-
-char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
-{
-    static const char* const msg = "Please supply a buffer for error string";
-
-    WOLFSSL_ENTER("ERR_error_string");
-    if (data) {
-        SetErrorString((int)errNumber, data);
-        return data;
-    }
-
-    return (char*)msg;
-}
-
-
-void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_error_string_n");
-    if (len >= WOLFSSL_MAX_ERROR_SZ)
-        wolfSSL_ERR_error_string(e, buf);
-    else {
-        char tmp[WOLFSSL_MAX_ERROR_SZ];
-
-        WOLFSSL_MSG("Error buffer too short, truncating");
-        if (len) {
-            wolfSSL_ERR_error_string(e, tmp);
-            XMEMCPY(buf, tmp, len-1);
-            buf[len-1] = '\0';
-        }
-    }
-}
-
-
-/* don't free temporary arrays at end of handshake */
-void wolfSSL_KeepArrays(WOLFSSL* ssl)
-{
-    if (ssl)
-        ssl->options.saveArrays = 1;
-}
-
-
-/* user doesn't need temporary arrays anymore, Free */
-void wolfSSL_FreeArrays(WOLFSSL* ssl)
-{
-    if (ssl && ssl->options.handShakeState == HANDSHAKE_DONE) {
-        ssl->options.saveArrays = 0;
-        FreeArrays(ssl, 1);
-    }
-}
-
-/* Set option to indicate that the resources are not to be freed after
- * handshake.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
-int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->options.keepResources = 1;
-
-    return 0;
-}
-
-/* Free the handshake resources after handshake.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
-int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    FreeHandshakeResources(ssl);
-
-    return 0;
-}
-
-/* Use the client's order of preference when matching cipher suites.
- *
- * ssl  The SSL/TLS context object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
-int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->useClientOrder = 1;
-
-    return 0;
-}
-
-/* Use the client's order of preference when matching cipher suites.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
- */
-int wolfSSL_UseClientSuites(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->options.useClientOrder = 1;
-
-    return 0;
-}
-
-const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
-{
-    if (ssl == NULL)
-        return NULL;
-
-    if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
-         (ssl->options.side == WOLFSSL_SERVER_END &&  verify) )
-        return ssl->keys.client_write_MAC_secret;
-    else
-        return ssl->keys.server_write_MAC_secret;
-}
-
-
-#ifdef ATOMIC_USER
-
-void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX* ctx, CallbackMacEncrypt cb)
-{
-    if (ctx)
-        ctx->MacEncryptCb = cb;
-}
-
-
-void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->MacEncryptCtx = ctx;
-}
-
-
-void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->MacEncryptCtx;
-
-    return NULL;
-}
-
-
-void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX* ctx, CallbackDecryptVerify cb)
-{
-    if (ctx)
-        ctx->DecryptVerifyCb = cb;
-}
-
-
-void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->DecryptVerifyCtx = ctx;
-}
-
-
-void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->DecryptVerifyCtx;
-
-    return NULL;
-}
-
-
-const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->keys.client_write_key;
-
-    return NULL;
-}
-
-
-const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->keys.client_write_IV;
-
-    return NULL;
-}
-
-
-const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->keys.server_write_key;
-
-    return NULL;
-}
-
-
-const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->keys.server_write_IV;
-
-    return NULL;
-}
-
-int wolfSSL_GetKeySize(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->specs.key_size;
-
-    return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_GetIVSize(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->specs.iv_size;
-
-    return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_GetBulkCipher(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->specs.bulk_cipher_algorithm;
-
-    return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_GetCipherType(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->specs.cipher_type == block)
-        return WOLFSSL_BLOCK_TYPE;
-    if (ssl->specs.cipher_type == stream)
-        return WOLFSSL_STREAM_TYPE;
-    if (ssl->specs.cipher_type == aead)
-        return WOLFSSL_AEAD_TYPE;
-
-    return -1;
-}
-
-
-int wolfSSL_GetCipherBlockSize(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return ssl->specs.block_size;
-}
-
-
-int wolfSSL_GetAeadMacSize(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return ssl->specs.aead_mac_size;
-}
-
-
-int wolfSSL_IsTLSv1_1(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->options.tls1_1)
-        return 1;
-
-    return 0;
-}
-
-
-int wolfSSL_GetSide(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->options.side;
-
-    return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_GetHmacSize(WOLFSSL* ssl)
-{
-    /* AEAD ciphers don't have HMAC keys */
-    if (ssl)
-        return (ssl->specs.cipher_type != aead) ? ssl->specs.hash_size : 0;
-
-    return BAD_FUNC_ARG;
-}
-
-#endif /* ATOMIC_USER */
-
-#ifndef NO_CERTS
-
-WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_CERT_MANAGER* cm = NULL;
-    if (ctx)
-        cm = ctx->cm;
-    return cm;
-}
-
-WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
-{
-    WOLFSSL_CERT_MANAGER* cm = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
-
-    cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
-                                         DYNAMIC_TYPE_CERT_MANAGER);
-    if (cm) {
-        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
-
-        if (wc_InitMutex(&cm->caLock) != 0) {
-            WOLFSSL_MSG("Bad mutex init");
-            wolfSSL_CertManagerFree(cm);
-            return NULL;
-        }
-
-        #ifdef WOLFSSL_TRUST_PEER_CERT
-        if (wc_InitMutex(&cm->tpLock) != 0) {
-            WOLFSSL_MSG("Bad mutex init");
-            wolfSSL_CertManagerFree(cm);
-            return NULL;
-        }
-        #endif
-
-        /* set default minimum key size allowed */
-        #ifndef NO_RSA
-            cm->minRsaKeySz = MIN_RSAKEY_SZ;
-        #endif
-        #ifdef HAVE_ECC
-            cm->minEccKeySz = MIN_ECCKEY_SZ;
-        #endif
-            cm->heap = heap;
-    }
-
-    return cm;
-}
-
-
-WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
-{
-    return wolfSSL_CertManagerNew_ex(NULL);
-}
-
-
-void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
-{
-    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(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
-
-        XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
-    }
-
-}
-
-
-/* Unload the CA signer list */
-int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (wc_LockMutex(&cm->caLock) != 0)
-        return BAD_MUTEX_E;
-
-    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL);
-
-    wc_UnLockMutex(&cm->caLock);
-
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (wc_LockMutex(&cm->tpLock) != 0)
-        return BAD_MUTEX_E;
-
-    FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL);
-
-    wc_UnLockMutex(&cm->tpLock);
-
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-#endif /* NO_CERTS */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
-    defined(HAVE_WEBSERVER)
-
-static const struct cipher{
-        unsigned char type;
-        const char *name;
-} cipher_tbl[] = {
-
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-    {AES_128_CBC_TYPE, "AES-128-CBC"},
-    #endif
-    #ifdef WOLFSSL_AES_192
-    {AES_192_CBC_TYPE, "AES-192-CBC"},
-    #endif
-    #ifdef WOLFSSL_AES_256
-    {AES_256_CBC_TYPE, "AES-256-CBC"},
-    #endif
-#if defined(OPENSSL_EXTRA)
-    #ifdef WOLFSSL_AES_128
-        {AES_128_CTR_TYPE, "AES-128-CTR"},
-    #endif
-    #ifdef WOLFSSL_AES_192
-        {AES_192_CTR_TYPE, "AES-192-CTR"},
-    #endif
-    #ifdef WOLFSSL_AES_256
-        {AES_256_CTR_TYPE, "AES-256-CTR"},
-    #endif
-
-    #ifdef WOLFSSL_AES_128
-        {AES_128_ECB_TYPE, "AES-128-ECB"},
-    #endif
-    #ifdef WOLFSSL_AES_192
-        {AES_192_ECB_TYPE, "AES-192-ECB"},
-    #endif
-    #ifdef WOLFSSL_AES_256
-        {AES_256_ECB_TYPE, "AES-256-ECB"},
-    #endif
-#endif
-
-#endif
-
-#ifndef NO_DES3
-    {DES_CBC_TYPE, "DES-CBC"},
-    {DES_ECB_TYPE, "DES-ECB"},
-
-    {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC"},
-    {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB"},
-#endif
-
-#ifndef NO_RC4
-    {ARC4_TYPE, "ARC4"},
-#endif
-
-#ifdef HAVE_IDEA
-    {IDEA_CBC_TYPE, "IDEA-CBC"},
-#endif
-    { 0, NULL}
-};
-
-const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name)
-{
-
-    static const struct alias {
-        const char *name;
-        const char *alias;
-    } alias_tbl[] =
-    {
-#ifndef NO_DES3
-        {"DES-CBC", "DES"},
-        {"DES-CBC", "des"},
-        {"DES-ECB", "DES-ECB"},
-        {"DES-ECB", "des-ecb"},
-        {"DES-EDE3-CBC", "DES3"},
-        {"DES-EDE3-CBC", "des3"},
-        {"DES-EDE3-ECB", "DES-EDE3"},
-        {"DES-EDE3-ECB", "des-ede3"},
-        {"DES-EDE3-ECB", "des-ede3-ecb"},
-#endif
-#ifdef HAVE_IDEA
-        {"IDEA-CBC", "IDEA"},
-        {"IDEA-CBC", "idea"},
-#endif
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-        {"AES-128-CBC", "AES128-CBC"},
-        {"AES-128-CBC", "aes128-cbc"},
-        #endif
-        #ifdef WOLFSSL_AES_192
-        {"AES-192-CBC", "AES192-CBC"},
-        {"AES-192-CBC", "aes192-cbc"},
-        #endif
-        #ifdef WOLFSSL_AES_256
-        {"AES-256-CBC", "AES256-CBC"},
-        {"AES-256-CBC", "aes256-cbc"},
-        #endif
-    #endif
-    #ifdef WOLFSSL_AES_128
-        {"AES-128-ECB", "AES128-ECB"},
-        {"AES-128-ECB", "aes128-ecb"},
-    #endif
-    #ifdef WOLFSSL_AES_192
-        {"AES-192-ECB", "AES192-ECB"},
-        {"AES-192-ECB", "aes192-ecb"},
-    #endif
-    #ifdef WOLFSSL_AES_256
-        {"AES-256-ECB", "AES256-ECB"},
-        {"AES-256-EBC", "aes256-ecb"},
-    #endif
-#endif
-#ifndef NO_RC4
-        {"ARC4", "RC4"},
-#endif
-        { NULL, NULL}
-    };
-
-    const struct cipher *ent;
-    const struct alias  *al;
-
-    WOLFSSL_ENTER("EVP_get_cipherbyname");
-
-    for( al = alias_tbl; al->name != NULL; al++)
-        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
-            name = al->name;
-            break;
-        }
-
-    for( ent = cipher_tbl; ent->name != NULL; ent++)
-        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
-            return (WOLFSSL_EVP_CIPHER *)ent->name;
-        }
-
-    return NULL;
-}
-
-/*
- * return an EVP_CIPHER structure when cipher NID is passed.
- *
- * id  cipher NID
- *
- * retrun WOLFSSL_EVP_CIPHER
-*/
-const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id)
-{
-    WOLFSSL_ENTER("EVP_get_cipherbynid");
-
-    switch(id) {
-
-#if defined(OPENSSL_EXTRA)
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-        case NID_aes_128_cbc:
-            return wolfSSL_EVP_aes_128_cbc();
-        #endif
-        #ifdef WOLFSSL_AES_192
-        case NID_aes_192_cbc:
-            return wolfSSL_EVP_aes_192_cbc();
-        #endif
-        #ifdef WOLFSSL_AES_256
-        case NID_aes_256_cbc:
-            return wolfSSL_EVP_aes_256_cbc();
-        #endif
-    #endif
-    #ifdef WOLFSSL_AES_COUNTER
-        #ifdef WOLFSSL_AES_128
-        case NID_aes_128_ctr:
-            return wolfSSL_EVP_aes_128_ctr();
-        #endif
-        #ifdef WOLFSSL_AES_192
-        case NID_aes_192_ctr:
-            return wolfSSL_EVP_aes_192_ctr();
-        #endif
-        #ifdef WOLFSSL_AES_256
-        case NID_aes_256_ctr:
-            return wolfSSL_EVP_aes_256_ctr();
-        #endif
-    #endif /* WOLFSSL_AES_COUNTER */
-    #ifdef HAVE_AES_ECB
-        #ifdef WOLFSSL_AES_128
-        case NID_aes_128_ecb:
-            return wolfSSL_EVP_aes_128_ecb();
-        #endif
-        #ifdef WOLFSSL_AES_192
-        case NID_aes_192_ecb:
-            return wolfSSL_EVP_aes_192_ecb();
-        #endif
-        #ifdef WOLFSSL_AES_256
-        case NID_aes_256_ecb:
-            return wolfSSL_EVP_aes_256_ecb();
-        #endif
-    #endif /* HAVE_AES_ECB */
-#endif
-
-#ifndef NO_DES3
-        case NID_des_cbc:
-            return wolfSSL_EVP_des_cbc();
-#ifdef WOLFSSL_DES_ECB
-        case NID_des_ecb:
-            return wolfSSL_EVP_des_ecb();
-#endif
-        case NID_des_ede3_cbc:
-            return wolfSSL_EVP_des_ede3_cbc();
-#ifdef WOLFSSL_DES_ECB
-        case NID_des_ede3_ecb:
-            return wolfSSL_EVP_des_ede3_ecb();
-#endif
-#endif /*NO_DES3*/
-
-#ifdef HAVE_IDEA
-        case NID_idea_cbc:
-            return wolfSSL_EVP_idea_cbc();
-#endif
-#endif /*OPENSSL_EXTRA*/
-
-        default:
-            WOLFSSL_MSG("Bad cipher id value");
-    }
-
-    return NULL;
-}
-
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-    #ifdef WOLFSSL_AES_128
-        static char *EVP_AES_128_CBC;
-    #endif
-    #ifdef WOLFSSL_AES_192
-        static char *EVP_AES_192_CBC;
-    #endif
-    #ifdef WOLFSSL_AES_256
-        static char *EVP_AES_256_CBC;
-    #endif
-    #endif /* HAVE_AES_CBC */
-#if defined(OPENSSL_EXTRA)
-    #ifdef WOLFSSL_AES_128
-    static char *EVP_AES_128_CTR;
-    #endif
-    #ifdef WOLFSSL_AES_192
-    static char *EVP_AES_192_CTR;
-    #endif
-    #ifdef WOLFSSL_AES_256
-    static char *EVP_AES_256_CTR;
-    #endif
-
-    #ifdef WOLFSSL_AES_128
-    static char *EVP_AES_128_ECB;
-    #endif
-    #ifdef WOLFSSL_AES_192
-    static char *EVP_AES_192_ECB;
-    #endif
-    #ifdef WOLFSSL_AES_256
-    static char *EVP_AES_256_ECB;
-    #endif
-    static const int  EVP_AES_SIZE = 11;
-#endif
-#endif
-
-#ifndef NO_DES3
-static char *EVP_DES_CBC;
-static char *EVP_DES_ECB;
-
-static char *EVP_DES_EDE3_CBC;
-static char *EVP_DES_EDE3_ECB;
-
-#ifdef OPENSSL_EXTRA
-static const int  EVP_DES_SIZE = 7;
-static const int  EVP_DES_EDE3_SIZE = 12;
-#endif
-
-#endif
-
-#ifdef HAVE_IDEA
-static char *EVP_IDEA_CBC;
-#if defined(OPENSSL_EXTRA)
-static const int  EVP_IDEA_SIZE = 8;
-#endif
-#endif
-
-void wolfSSL_EVP_init(void)
-{
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC");
-        #endif
-    #endif /* HAVE_AES_CBC */
-
-#if defined(OPENSSL_EXTRA)
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR");
-        #endif
-
-        #ifdef WOLFSSL_AES_128
-        EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB");
-        #endif
-        #ifdef WOLFSSL_AES_192
-        EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB");
-        #endif
-        #ifdef WOLFSSL_AES_256
-        EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB");
-        #endif
-#endif
-#endif
-
-#ifndef NO_DES3
-    EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC");
-    EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB");
-
-    EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC");
-    EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB");
-#endif
-
-#ifdef HAVE_IDEA
-    EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC");
-#endif
-}
-
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */
-
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
-
-void wolfSSL_ERR_print_errors_fp(XFILE fp, int err)
-{
-    char data[WOLFSSL_MAX_ERROR_SZ + 1];
-
-    WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp");
-    SetErrorString(err, data);
-    fprintf(fp, "%s", data);
-}
-
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-void wolfSSL_ERR_dump_errors_fp(XFILE fp)
-{
-    wc_ERR_print_errors_fp(fp);
-}
-#endif
-#endif
-
-
-int wolfSSL_pending(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_pending");
-    return ssl->buffers.clearOutputBuffer.length;
-}
-
-
-#ifndef WOLFSSL_LEANPSK
-/* turn on handshake group messages for context */
-int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL)
-       return BAD_FUNC_ARG;
-
-    ctx->groupMessages = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_CLIENT
-/* connect enough to get peer cert chain */
-int wolfSSL_connect_cert(WOLFSSL* ssl)
-{
-    int  ret;
-
-    if (ssl == NULL)
-        return WOLFSSL_FAILURE;
-
-    ssl->options.certOnly = 1;
-    ret = wolfSSL_connect(ssl);
-    ssl->options.certOnly   = 0;
-
-    return ret;
-}
-#endif
-
-
-#ifndef WOLFSSL_LEANPSK
-/* turn on handshake group messages for ssl object */
-int wolfSSL_set_group_messages(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-       return BAD_FUNC_ARG;
-
-    ssl->options.groupMessages = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* make minVersion the internal equivalent SSL version */
-static int SetMinVersionHelper(byte* minVersion, int version)
-{
-#ifdef NO_TLS
-    (void)minVersion;
-#endif
-
-    switch (version) {
-#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-        case WOLFSSL_SSLV3:
-            *minVersion = SSLv3_MINOR;
-            break;
-#endif
-
-#ifndef NO_TLS
-    #ifndef NO_OLD_TLS
-        case WOLFSSL_TLSV1:
-            *minVersion = TLSv1_MINOR;
-            break;
-
-        case WOLFSSL_TLSV1_1:
-            *minVersion = TLSv1_1_MINOR;
-            break;
-    #endif
-    #ifndef WOLFSSL_NO_TLS12
-        case WOLFSSL_TLSV1_2:
-            *minVersion = TLSv1_2_MINOR;
-            break;
-    #endif
-#endif
-    #ifdef WOLFSSL_TLS13
-        case WOLFSSL_TLSV1_3:
-            *minVersion = TLSv1_3_MINOR;
-            break;
-    #endif
-
-        default:
-            WOLFSSL_MSG("Bad function argument");
-            return BAD_FUNC_ARG;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
-int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion");
-
-    if (ctx == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-        return BAD_FUNC_ARG;
-    }
-
-    return SetMinVersionHelper(&ctx->minDowngrade, version);
-}
-
-
-/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
-int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
-{
-    WOLFSSL_ENTER("wolfSSL_SetMinVersion");
-
-    if (ssl == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-        return BAD_FUNC_ARG;
-    }
-
-    return SetMinVersionHelper(&ssl->options.minDowngrade, version);
-}
-
-
-/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */
-int wolfSSL_GetVersion(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ssl->version.major == SSLv3_MAJOR) {
-        switch (ssl->version.minor) {
-            case SSLv3_MINOR :
-                return WOLFSSL_SSLV3;
-            case TLSv1_MINOR :
-                return WOLFSSL_TLSV1;
-            case TLSv1_1_MINOR :
-                return WOLFSSL_TLSV1_1;
-            case TLSv1_2_MINOR :
-                return WOLFSSL_TLSV1_2;
-            case TLSv1_3_MINOR :
-                return WOLFSSL_TLSV1_3;
-            default:
-                break;
-        }
-    }
-
-    return VERSION_ERROR;
-}
-
-int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
-{
-    word16 haveRSA = 1;
-    word16 havePSK = 0;
-    int    keySz   = 0;
-
-    WOLFSSL_ENTER("wolfSSL_SetVersion");
-
-    if (ssl == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-        return BAD_FUNC_ARG;
-    }
-
-    switch (version) {
-#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-        case WOLFSSL_SSLV3:
-            ssl->version = MakeSSLv3();
-            break;
-#endif
-
-#ifndef NO_TLS
-    #ifndef NO_OLD_TLS
-        #ifdef WOLFSSL_ALLOW_TLSV10
-        case WOLFSSL_TLSV1:
-            ssl->version = MakeTLSv1();
-            break;
-        #endif
-
-        case WOLFSSL_TLSV1_1:
-            ssl->version = MakeTLSv1_1();
-            break;
-    #endif
-    #ifndef WOLFSSL_NO_TLS12
-        case WOLFSSL_TLSV1_2:
-            ssl->version = MakeTLSv1_2();
-            break;
-    #endif
-#endif
-#ifdef WOLFSSL_TLS13
-        case WOLFSSL_TLSV1_3:
-            ssl->version = MakeTLSv1_3();
-            break;
-
-#endif
-
-        default:
-            WOLFSSL_MSG("Bad function argument");
-            return BAD_FUNC_ARG;
-    }
-
-    #ifdef NO_RSA
-        haveRSA = 0;
-    #endif
-    #ifndef NO_PSK
-        havePSK = ssl->options.havePSK;
-    #endif
-    #ifndef NO_CERTS
-        keySz = ssl->buffers.keySz;
-    #endif
-
-    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-               ssl->options.haveDH, ssl->options.haveNTRU,
-               ssl->options.haveECDSAsig, ssl->options.haveECC,
-               ssl->options.haveStaticECC, ssl->options.side);
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* !leanpsk */
-
-
-#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE)
-
-/* Make a work from the front of random hash */
-static WC_INLINE word32 MakeWordFromHash(const byte* hashID)
-{
-    return ((word32)hashID[0] << 24) | (hashID[1] << 16) |
-        (hashID[2] <<  8) | hashID[3];
-}
-
-#endif /* !NO_CERTS || !NO_SESSION_CACHE */
-
-
-#ifndef NO_CERTS
-
-/* hash is the SHA digest of name, just use first 32 bits as hash */
-static WC_INLINE word32 HashSigner(const byte* hash)
-{
-    return MakeWordFromHash(hash) % CA_TABLE_SIZE;
-}
-
-
-/* does CA already exist on signer list */
-int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
-{
-    Signer* signers;
-    int     ret = 0;
-    word32  row;
-
-    if (cm == NULL || hash == NULL) {
-        return ret;
-    }
-
-    row = HashSigner(hash);
-
-    if (wc_LockMutex(&cm->caLock) != 0) {
-        return ret;
-    }
-    signers = cm->caTable[row];
-    while (signers) {
-        byte* subjectHash;
-
-    #ifndef NO_SKID
-        subjectHash = signers->subjectKeyIdHash;
-    #else
-        subjectHash = signers->subjectNameHash;
-    #endif
-
-        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
-            ret = 1; /* success */
-            break;
-        }
-        signers = signers->next;
-    }
-    wc_UnLockMutex(&cm->caLock);
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* hash is the SHA digest of name, just use first 32 bits as hash */
-static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
-{
-    return MakeWordFromHash(hash) % TP_TABLE_SIZE;
-}
-
-/* does trusted peer already exist on signer list */
-int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash)
-{
-    TrustedPeerCert* tp;
-    int     ret = 0;
-    word32  row = TrustedPeerHashSigner(hash);
-
-    if (wc_LockMutex(&cm->tpLock) != 0)
-        return  ret;
-    tp = cm->tpTable[row];
-    while (tp) {
-        byte* subjectHash;
-        #ifndef NO_SKID
-            subjectHash = tp->subjectKeyIdHash;
-        #else
-            subjectHash = tp->subjectNameHash;
-        #endif
-        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
-            ret = 1;
-            break;
-        }
-        tp = tp->next;
-    }
-    wc_UnLockMutex(&cm->tpLock);
-
-    return ret;
-}
-
-
-/* return Trusted Peer if found, otherwise NULL
-    type is what to match on
- */
-TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type)
-{
-    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
-    TrustedPeerCert* ret = NULL;
-    TrustedPeerCert* tp  = NULL;
-    word32  row;
-
-    if (cm == NULL || hash == NULL)
-        return NULL;
-
-    row = TrustedPeerHashSigner(hash);
-
-    if (wc_LockMutex(&cm->tpLock) != 0)
-        return ret;
-
-    tp = cm->tpTable[row];
-    while (tp) {
-        byte* subjectHash;
-        switch (type) {
-            #ifndef NO_SKID
-            case WC_MATCH_SKID:
-                subjectHash = tp->subjectKeyIdHash;
-                break;
-            #endif
-            case WC_MATCH_NAME:
-                subjectHash = tp->subjectNameHash;
-                break;
-            default:
-                WOLFSSL_MSG("Unknown search type");
-                wc_UnLockMutex(&cm->tpLock);
-                return NULL;
-        }
-        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
-            ret = tp;
-            break;
-        }
-        tp = tp->next;
-    }
-    wc_UnLockMutex(&cm->tpLock);
-
-    return ret;
-}
-
-
-int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
-{
-    if (tp == NULL || cert == NULL)
-        return BAD_FUNC_ARG;
-
-    /* subject key id or subject hash has been compared when searching
-       tpTable for the cert from function GetTrustedPeer */
-
-    /* compare signatures */
-    if (tp->sigLen == cert->sigLength) {
-        if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
-            return WOLFSSL_FAILURE;
-        }
-    }
-    else {
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-/* return CA if found, otherwise NULL */
-Signer* GetCA(void* vp, byte* hash)
-{
-    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
-    Signer* ret = NULL;
-    Signer* signers;
-    word32  row = HashSigner(hash);
-
-    if (cm == NULL)
-        return NULL;
-
-    if (wc_LockMutex(&cm->caLock) != 0)
-        return ret;
-
-    signers = cm->caTable[row];
-    while (signers) {
-        byte* subjectHash;
-        #ifndef NO_SKID
-            subjectHash = signers->subjectKeyIdHash;
-        #else
-            subjectHash = signers->subjectNameHash;
-        #endif
-        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
-            ret = signers;
-            break;
-        }
-        signers = signers->next;
-    }
-    wc_UnLockMutex(&cm->caLock);
-
-    return ret;
-}
-
-
-#ifndef NO_SKID
-/* return CA if found, otherwise NULL. Walk through hash table. */
-Signer* GetCAByName(void* vp, byte* hash)
-{
-    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
-    Signer* ret = NULL;
-    Signer* signers;
-    word32  row;
-
-    if (cm == NULL)
-        return NULL;
-
-    if (wc_LockMutex(&cm->caLock) != 0)
-        return ret;
-
-    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
-        signers = cm->caTable[row];
-        while (signers && ret == NULL) {
-            if (XMEMCMP(hash, signers->subjectNameHash,
-                        SIGNER_DIGEST_SIZE) == 0) {
-                ret = signers;
-            }
-            signers = signers->next;
-        }
-    }
-    wc_UnLockMutex(&cm->caLock);
-
-    return ret;
-}
-#endif
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* add a trusted peer cert to linked list */
-int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
-{
-    int ret, row;
-    TrustedPeerCert* peerCert;
-    DecodedCert* cert = NULL;
-    DerBuffer*   der = *pDer;
-    byte* subjectHash = NULL;
-
-    WOLFSSL_MSG("Adding a Trusted Peer Cert");
-
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
-                                 DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return MEMORY_E;
-
-    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
-    if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
-        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-        return ret;
-    }
-    WOLFSSL_MSG("\tParsed new trusted peer cert");
-
-    peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
-                                                             DYNAMIC_TYPE_CERT);
-    if (peerCert == NULL) {
-        FreeDecodedCert(cert);
-        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-        return MEMORY_E;
-    }
-    XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
-
-#ifndef NO_SKID
-    if (cert->extAuthKeyIdSet) {
-        subjectHash = cert->extSubjKeyId;
-    }
-    else {
-        subjectHash = cert->subjectHash;
-    }
-#else
-    subjectHash = cert->subjectHash;
-#endif
-
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        if (peerCert->permittedNames)
-            FreeNameSubtrees(peerCert->permittedNames, cm->heap);
-        if (peerCert->excludedNames)
-            FreeNameSubtrees(peerCert->excludedNames, cm->heap);
-    #endif
-
-    if (AlreadyTrustedPeer(cm, subjectHash)) {
-        WOLFSSL_MSG("\tAlready have this CA, not adding again");
-        (void)ret;
-    }
-    else {
-        /* add trusted peer signature */
-        peerCert->sigLen = cert->sigLength;
-        peerCert->sig = XMALLOC(cert->sigLength, cm->heap,
-                                                        DYNAMIC_TYPE_SIGNATURE);
-        if (peerCert->sig == NULL) {
-            FreeDecodedCert(cert);
-            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-            FreeTrustedPeer(peerCert, cm->heap);
-            return MEMORY_E;
-        }
-        XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
-
-        /* add trusted peer name */
-        peerCert->nameLen = cert->subjectCNLen;
-        peerCert->name    = cert->subjectCN;
-        #ifndef IGNORE_NAME_CONSTRAINTS
-            peerCert->permittedNames = cert->permittedNames;
-            peerCert->excludedNames  = cert->excludedNames;
-        #endif
-
-        /* add SKID when available and hash of name */
-        #ifndef NO_SKID
-            XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
-                    SIGNER_DIGEST_SIZE);
-        #endif
-            XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
-                    SIGNER_DIGEST_SIZE);
-            peerCert->next    = NULL; /* If Key Usage not set, all uses valid. */
-            cert->subjectCN = 0;
-        #ifndef IGNORE_NAME_CONSTRAINTS
-            cert->permittedNames = NULL;
-            cert->excludedNames = NULL;
-        #endif
-
-        #ifndef NO_SKID
-            if (cert->extAuthKeyIdSet) {
-                row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash);
-            }
-            else {
-                row = TrustedPeerHashSigner(peerCert->subjectNameHash);
-            }
-        #else
-            row = TrustedPeerHashSigner(peerCert->subjectNameHash);
-        #endif
-
-            if (wc_LockMutex(&cm->tpLock) == 0) {
-                peerCert->next = cm->tpTable[row];
-                cm->tpTable[row] = peerCert;   /* takes ownership */
-                wc_UnLockMutex(&cm->tpLock);
-            }
-            else {
-                WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
-                FreeDecodedCert(cert);
-                XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-                FreeTrustedPeer(peerCert, cm->heap);
-                return BAD_MUTEX_E;
-            }
-        }
-
-    WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
-    FreeDecodedCert(cert);
-    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-    WOLFSSL_MSG("\tFreeing der trusted peer cert");
-    FreeDer(&der);
-    WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
-    WOLFSSL_LEAVE("AddTrustedPeer", ret);
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-/* owns der, internal now uses too */
-/* type flag ids from user or from chain received during verify
-   don't allow chain ones to be added w/o isCA extension */
-int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
-{
-    int         ret;
-    Signer*     signer = NULL;
-    word32      row;
-    byte*       subjectHash;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-    DerBuffer*   der = *pDer;
-
-    WOLFSSL_MSG("Adding a CA");
-
-#ifdef WOLFSSL_SMALL_STACK
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                 DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
-    ret = ParseCert(cert, CA_TYPE, verify, cm);
-    WOLFSSL_MSG("\tParsed new CA");
-
-#ifndef NO_SKID
-    subjectHash = cert->extSubjKeyId;
-#else
-    subjectHash = cert->subjectHash;
-#endif
-
-    /* check CA key size */
-    if (verify) {
-        switch (cert->keyOID) {
-            #ifndef NO_RSA
-            case RSAk:
-                if (cm->minRsaKeySz < 0 ||
-                                   cert->pubKeySize < (word16)cm->minRsaKeySz) {
-                    ret = RSA_KEY_SIZE_E;
-                    WOLFSSL_MSG("\tCA RSA key size error");
-                }
-                break;
-            #endif /* !NO_RSA */
-            #ifdef HAVE_ECC
-            case ECDSAk:
-                if (cm->minEccKeySz < 0 ||
-                                   cert->pubKeySize < (word16)cm->minEccKeySz) {
-                    ret = ECC_KEY_SIZE_E;
-                    WOLFSSL_MSG("\tCA ECC key size error");
-                }
-                break;
-            #endif /* HAVE_ECC */
-            #ifdef HAVE_ED25519
-            case ED25519k:
-                if (cm->minEccKeySz < 0 ||
-                                   ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
-                    ret = ECC_KEY_SIZE_E;
-                    WOLFSSL_MSG("\tCA ECC key size error");
-                }
-                break;
-            #endif /* HAVE_ED25519 */
-
-            default:
-                WOLFSSL_MSG("\tNo key size check done on CA");
-                break; /* no size check if key type is not in switch */
-        }
-    }
-
-    if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
-        WOLFSSL_MSG("\tCan't add as CA if not actually one");
-        ret = NOT_CA_ERROR;
-    }
-#ifndef ALLOW_INVALID_CERTSIGN
-    else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
-             (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
-        /* Intermediate CA certs are required to have the keyCertSign
-        * extension set. User loaded root certs are not. */
-        WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
-        ret = NOT_CA_ERROR;
-    }
-#endif
-    else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
-        WOLFSSL_MSG("\tAlready have this CA, not adding again");
-        (void)ret;
-    }
-    else if (ret == 0) {
-        /* take over signer parts */
-        signer = MakeSigner(cm->heap);
-        if (!signer)
-            ret = MEMORY_ERROR;
-    }
-    if (ret == 0 && signer != NULL) {
-    #ifdef WOLFSSL_SIGNER_DER_CERT
-        ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
-    }
-    if (ret == 0 && signer != NULL) {
-        XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
-    #endif
-        signer->keyOID         = cert->keyOID;
-        if (cert->pubKeyStored) {
-            signer->publicKey      = cert->publicKey;
-            signer->pubKeySize     = cert->pubKeySize;
-        }
-        if (cert->subjectCNStored) {
-            signer->nameLen        = cert->subjectCNLen;
-            signer->name           = cert->subjectCN;
-        }
-        signer->pathLength     = cert->pathLength;
-        signer->pathLengthSet  = cert->pathLengthSet;
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        signer->permittedNames = cert->permittedNames;
-        signer->excludedNames  = cert->excludedNames;
-    #endif
-    #ifndef NO_SKID
-        XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
-                SIGNER_DIGEST_SIZE);
-    #endif
-        XMEMCPY(signer->subjectNameHash, cert->subjectHash,
-                SIGNER_DIGEST_SIZE);
-        signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
-                                                : 0xFFFF;
-        signer->next    = NULL; /* If Key Usage not set, all uses valid. */
-        cert->publicKey = 0;    /* in case lock fails don't free here.   */
-        cert->subjectCN = 0;
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        cert->permittedNames = NULL;
-        cert->excludedNames = NULL;
-    #endif
-
-    #ifndef NO_SKID
-        row = HashSigner(signer->subjectKeyIdHash);
-    #else
-        row = HashSigner(signer->subjectNameHash);
-    #endif
-
-        if (wc_LockMutex(&cm->caLock) == 0) {
-            signer->next = cm->caTable[row];
-            cm->caTable[row] = signer;   /* takes ownership */
-            wc_UnLockMutex(&cm->caLock);
-            if (cm->caCacheCallback)
-                cm->caCacheCallback(der->buffer, (int)der->length, type);
-        }
-        else {
-            WOLFSSL_MSG("\tCA Mutex Lock failed");
-            ret = BAD_MUTEX_E;
-            FreeSigner(signer, cm->heap);
-        }
-    }
-
-    WOLFSSL_MSG("\tFreeing Parsed CA");
-    FreeDecodedCert(cert);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-#endif
-    WOLFSSL_MSG("\tFreeing der CA");
-    FreeDer(pDer);
-    WOLFSSL_MSG("\t\tOK Freeing der CA");
-
-    WOLFSSL_LEAVE("AddCA", ret);
-
-    return ret == 0 ? WOLFSSL_SUCCESS : ret;
-}
-
-#endif /* !NO_CERTS */
-
-
-#ifndef NO_SESSION_CACHE
-
-    /* basic config gives a cache with 33 sessions, adequate for clients and
-       embedded servers
-
-       MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
-       aren't under heavy load, basically allows 200 new sessions per minute
-
-       BIG_SESSION_CACHE yields 20,027 sessions
-
-       HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
-       allows over 13,000 new sessions per minute or over 200 new sessions per
-       second
-
-       SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
-       or systems where the default of nearly 3kB is too much RAM, this define
-       uses less than 500 bytes RAM
-
-       default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
-    */
-    #ifdef HUGE_SESSION_CACHE
-        #define SESSIONS_PER_ROW 11
-        #define SESSION_ROWS 5981
-    #elif defined(BIG_SESSION_CACHE)
-        #define SESSIONS_PER_ROW 7
-        #define SESSION_ROWS 2861
-    #elif defined(MEDIUM_SESSION_CACHE)
-        #define SESSIONS_PER_ROW 5
-        #define SESSION_ROWS 211
-    #elif defined(SMALL_SESSION_CACHE)
-        #define SESSIONS_PER_ROW 2
-        #define SESSION_ROWS 3
-    #else
-        #define SESSIONS_PER_ROW 3
-        #define SESSION_ROWS 11
-    #endif
-
-    typedef struct SessionRow {
-        int nextIdx;                           /* where to place next one   */
-        int totalCount;                        /* sessions ever on this row */
-        WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
-    } SessionRow;
-
-    static SessionRow SessionCache[SESSION_ROWS];
-
-    #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
-        static word32 PeakSessions;
-    #endif
-
-    static wolfSSL_Mutex session_mutex;   /* SessionCache mutex */
-
-    #ifndef NO_CLIENT_CACHE
-
-        typedef struct ClientSession {
-            word16 serverRow;            /* SessionCache Row id */
-            word16 serverIdx;            /* SessionCache Idx (column) */
-        } ClientSession;
-
-        typedef struct ClientRow {
-            int nextIdx;                /* where to place next one   */
-            int totalCount;             /* sessions ever on this row */
-            ClientSession Clients[SESSIONS_PER_ROW];
-        } ClientRow;
-
-        static ClientRow ClientCache[SESSION_ROWS];  /* Client Cache */
-                                                     /* uses session mutex */
-    #endif  /* NO_CLIENT_CACHE */
-
-#endif /* NO_SESSION_CACHE */
-
-int wolfSSL_Init(void)
-{
-    WOLFSSL_ENTER("wolfSSL_Init");
-
-    if (initRefCount == 0) {
-        /* Initialize crypto for use with TLS connection */
-        if (wolfCrypt_Init() != 0) {
-            WOLFSSL_MSG("Bad wolfCrypt Init");
-            return WC_INIT_E;
-        }
-#ifndef NO_SESSION_CACHE
-        if (wc_InitMutex(&session_mutex) != 0) {
-            WOLFSSL_MSG("Bad Init Mutex session");
-            return BAD_MUTEX_E;
-        }
-#endif
-        if (wc_InitMutex(&count_mutex) != 0) {
-            WOLFSSL_MSG("Bad Init Mutex count");
-            return BAD_MUTEX_E;
-        }
-    }
-
-    if (wc_LockMutex(&count_mutex) != 0) {
-        WOLFSSL_MSG("Bad Lock Mutex count");
-        return BAD_MUTEX_E;
-    }
-
-    initRefCount++;
-    wc_UnLockMutex(&count_mutex);
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-
-#ifndef NO_CERTS
-
-/* process user cert chain to pass during the handshake */
-static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
-                         long sz, int format, int type, WOLFSSL* ssl,
-                         long* used, EncryptedInfo* info)
-{
-    int ret = 0;
-    void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
-#ifdef WOLFSSL_TLS13
-    int cnt = 0;
-#endif
-
-    /* we may have a user cert chain, try to consume */
-    if (type == CERT_TYPE && info->consumed < sz) {
-    #ifdef WOLFSSL_SMALL_STACK
-        byte   staticBuffer[1];                 /* force heap usage */
-    #else
-        byte   staticBuffer[FILE_BUFFER_SIZE];  /* tmp chain buffer */
-    #endif
-        byte*  chainBuffer = staticBuffer;
-        int    dynamicBuffer = 0;
-        word32 bufferSz;
-        long   consumed = info->consumed;
-        word32 idx = 0;
-        int    gotOne = 0;
-
-        /* Calculate max possible size, including max headers */
-        bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
-        if (bufferSz > sizeof(staticBuffer)) {
-            WOLFSSL_MSG("Growing Tmp Chain Buffer");
-            /* will shrink to actual size */
-            chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
-            if (chainBuffer == NULL) {
-                return MEMORY_E;
-            }
-            dynamicBuffer = 1;
-        }
-
-        WOLFSSL_MSG("Processing Cert Chain");
-        while (consumed < sz) {
-            DerBuffer* part = NULL;
-            word32 remain = (word32)(sz - consumed);
-            info->consumed = 0;
-
-            if (format == WOLFSSL_FILETYPE_PEM) {
-            #ifdef WOLFSSL_PEM_TO_DER
-                ret = PemToDer(buff + consumed, remain, type, &part,
-                               heap, info, NULL);
-            #else
-                ret = NOT_COMPILED_IN;
-            #endif
-            }
-            else {
-                int length = remain;
-                if (format == WOLFSSL_FILETYPE_ASN1) {
-                    /* get length of der (read sequence) */
-                    word32 inOutIdx = 0;
-                    if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) {
-                        ret = ASN_NO_PEM_HEADER;
-                    }
-                    length += inOutIdx; /* include leading sequence */
-                }
-                info->consumed = length;
-                if (ret == 0) {
-                    ret = AllocDer(&part, length, type, heap);
-                    if (ret == 0) {
-                        XMEMCPY(part->buffer, buff + consumed, length);
-                    }
-                }
-            }
-            if (ret == 0) {
-                gotOne = 1;
-#ifdef WOLFSSL_TLS13
-                cnt++;
-#endif
-                if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
-                    WOLFSSL_MSG("   Cert Chain bigger than buffer");
-                    ret = BUFFER_E;
-                }
-                else {
-                    c32to24(part->length, &chainBuffer[idx]);
-                    idx += CERT_HEADER_SZ;
-                    XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
-                    idx += part->length;
-                    consumed  += info->consumed;
-                    if (used)
-                        *used += info->consumed;
-                }
-            }
-            FreeDer(&part);
-
-            if (ret == ASN_NO_PEM_HEADER && gotOne) {
-                WOLFSSL_MSG("We got one good cert, so stuff at end ok");
-                break;
-            }
-
-            if (ret < 0) {
-                WOLFSSL_MSG("   Error in Cert in Chain");
-                if (dynamicBuffer)
-                    XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
-                return ret;
-            }
-            WOLFSSL_MSG("   Consumed another Cert in Chain");
-        }
-        WOLFSSL_MSG("Finished Processing Cert Chain");
-
-        /* only retain actual size used */
-        ret = 0;
-        if (idx > 0) {
-            if (ssl) {
-                if (ssl->buffers.weOwnCertChain) {
-                    FreeDer(&ssl->buffers.certChain);
-                }
-                ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
-                if (ret == 0) {
-                    XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, idx);
-                    ssl->buffers.weOwnCertChain = 1;
-                }
-#ifdef WOLFSSL_TLS13
-                ssl->buffers.certChainCnt = cnt;
-#endif
-            } else if (ctx) {
-                FreeDer(&ctx->certChain);
-                ret = AllocDer(&ctx->certChain, idx, type, heap);
-                if (ret == 0) {
-                    XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
-                }
-#ifdef WOLFSSL_TLS13
-                ctx->certChainCnt = cnt;
-#endif
-            }
-        }
-
-        if (dynamicBuffer)
-            XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
-    }
-
-    return ret;
-}
-/* process the buffer buff, length sz, into ctx of format and type
-   used tracks bytes consumed, userChain specifies a user cert chain
-   to pass during the handshake */
-int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
-                         long sz, int format, int type, WOLFSSL* ssl,
-                         long* used, int userChain)
-{
-    DerBuffer*    der = NULL;        /* holds DER or RAW (for NTRU) */
-    int           ret = 0;
-    int           eccKey = 0;
-    int           ed25519Key = 0;
-    int           rsaKey = 0;
-    int           resetSuites = 0;
-    void*         heap = wolfSSL_CTX_GetHeap(ctx, ssl);
-    int           devId = wolfSSL_CTX_GetDevId(ctx, ssl);
-#ifdef WOLFSSL_SMALL_STACK
-    EncryptedInfo* info = NULL;
-#else
-    EncryptedInfo  info[1];
-#endif
-
-    (void)rsaKey;
-    (void)devId;
-
-    if (used)
-        *used = sz;     /* used bytes default to sz, PEM chain may shorten*/
-
-    /* check args */
-    if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM
-                                    && format != WOLFSSL_FILETYPE_RAW)
-        return WOLFSSL_BAD_FILETYPE;
-
-    if (ctx == NULL && ssl == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
-                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
-    if (info == NULL)
-        return MEMORY_E;
-#endif
-
-    XMEMSET(info, 0, sizeof(EncryptedInfo));
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    if (ctx) {
-        info->passwd_cb       = ctx->passwd_cb;
-        info->passwd_userdata = ctx->passwd_userdata;
-    }
-#endif
-
-    if (format == WOLFSSL_FILETYPE_PEM) {
-    #ifdef WOLFSSL_PEM_TO_DER
-        ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey);
-    #else
-        ret = NOT_COMPILED_IN;
-    #endif
-    }
-    else {
-        /* ASN1 (DER) or RAW (NTRU) */
-        int length = (int)sz;
-        if (format == WOLFSSL_FILETYPE_ASN1) {
-            /* get length of der (read sequence) */
-            word32 inOutIdx = 0;
-            if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) {
-                ret = ASN_PARSE_E;
-            }
-            length += inOutIdx; /* include leading sequence */
-        }
-
-        info->consumed = length;
-
-        if (ret == 0) {
-            ret = AllocDer(&der, (word32)length, type, heap);
-            if (ret == 0) {
-                XMEMCPY(der->buffer, buff, length);
-            }
-        }
-    }
-
-    if (used) {
-        *used = info->consumed;
-    }
-
-    /* process user chain */
-    if (ret >= 0) {
-        /* First certificate in chain is loaded into ssl->buffers.certificate.
-         * Remainder are loaded into ssl->buffers.certChain.
-         * Chain should have server cert first, then intermediates, then root.
-         */
-        if (userChain) {
-            ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info);
-        }
-    }
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    /* for WOLFSSL_FILETYPE_PEM, PemToDer manage the decryption if required */
-    if (ret >= 0 && info->set && format != WOLFSSL_FILETYPE_PEM) {
-        /* decrypt */
-        int   passwordSz = NAME_SZ;
-#ifdef WOLFSSL_SMALL_STACK
-        char* password = NULL;
-#else
-        char  password[NAME_SZ];
-#endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
-        if (password == NULL)
-            ret = MEMORY_E;
-        else
-    #endif
-        if (info->passwd_cb == NULL) {
-            WOLFSSL_MSG("No password callback set");
-            ret = NO_PASSWORD;
-        }
-        else {
-            ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
-                info->passwd_userdata);
-            if (ret >= 0) {
-                passwordSz = ret;
-
-                /* decrypt the key */
-                ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
-                    (byte*)password, passwordSz, WC_MD5);
-
-                ForceZero(password, passwordSz);
-            }
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(password, heap, DYNAMIC_TYPE_STRING);
-    #endif
-    }
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-
-    /* check for error */
-    if (ret < 0) {
-        FreeDer(&der);
-        return ret;
-    }
-
-    /* Handle DER owner */
-    if (type == CA_TYPE) {
-        if (ctx == NULL) {
-            WOLFSSL_MSG("Need context for CA load");
-            FreeDer(&der);
-            return BAD_FUNC_ARG;
-        }
-        /* verify CA unless user set to no verify */
-        return AddCA(ctx->cm, &der, WOLFSSL_USER_CA, !ctx->verifyNone);
-    }
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    else if (type == TRUSTED_PEER_TYPE) {
-        if (ctx == NULL) {
-            WOLFSSL_MSG("Need context for trusted peer cert load");
-            FreeDer(&der);
-            return BAD_FUNC_ARG;
-        }
-        /* add trusted peer cert */
-        return AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
-    }
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-    else if (type == CERT_TYPE) {
-        if (ssl) {
-             /* Make sure previous is free'd */
-            if (ssl->buffers.weOwnCert) {
-                FreeDer(&ssl->buffers.certificate);
-            #ifdef KEEP_OUR_CERT
-                FreeX509(ssl->ourCert);
-                if (ssl->ourCert) {
-                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
-                    ssl->ourCert = NULL;
-                }
-            #endif
-            }
-            ssl->buffers.certificate = der;
-        #ifdef KEEP_OUR_CERT
-            ssl->keepCert = 1; /* hold cert for ssl lifetime */
-        #endif
-            ssl->buffers.weOwnCert = 1;
-        }
-        else if (ctx) {
-            FreeDer(&ctx->certificate); /* Make sure previous is free'd */
-        #ifdef KEEP_OUR_CERT
-            if (ctx->ourCert) {
-                if (ctx->ownOurCert) {
-                    FreeX509(ctx->ourCert);
-                    XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
-                }
-                ctx->ourCert = NULL;
-            }
-        #endif
-            ctx->certificate = der;
-        }
-    }
-    else if (type == PRIVATEKEY_TYPE) {
-        if (ssl) {
-             /* Make sure previous is free'd */
-            if (ssl->buffers.weOwnKey) {
-                FreeDer(&ssl->buffers.key);
-            }
-            ssl->buffers.key = der;
-            ssl->buffers.weOwnKey = 1;
-        }
-        else if (ctx) {
-            FreeDer(&ctx->privateKey);
-            ctx->privateKey = der;
-        }
-    }
-    else {
-        FreeDer(&der);
-        return WOLFSSL_BAD_CERTTYPE;
-    }
-
-    if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
-    #ifndef NO_RSA
-        if (!eccKey && !ed25519Key) {
-            /* make sure RSA key can be used */
-            word32 idx = 0;
-        #ifdef WOLFSSL_SMALL_STACK
-            RsaKey* key = NULL;
-        #else
-            RsaKey  key[1];
-        #endif
-
-        #ifdef WOLFSSL_SMALL_STACK
-            key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
-            if (key == NULL)
-                return MEMORY_E;
-        #endif
-
-            ret = wc_InitRsaKey_ex(key, heap, devId);
-            if (ret == 0) {
-                if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length)
-                    != 0) {
-                #ifdef HAVE_ECC
-                    /* could have DER ECC (or pkcs8 ecc), no easy way to tell */
-                    eccKey = 1;  /* try it next */
-                #elif defined(HAVE_ED25519)
-                    ed25519Key = 1; /* try it next */
-                #else
-                    WOLFSSL_MSG("RSA decode failed and ECC not enabled to try");
-                    ret = WOLFSSL_BAD_FILE;
-                #endif
-                }
-                else {
-                    /* check that the size of the RSA key is enough */
-                    int rsaSz = wc_RsaEncryptSize((RsaKey*)key);
-                    int minRsaSz;
-
-                    minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
-                    if (rsaSz < minRsaSz) {
-                        ret = RSA_KEY_SIZE_E;
-                        WOLFSSL_MSG("Private Key size too small");
-                    }
-
-                    if (ssl) {
-                        ssl->buffers.keyType = rsa_sa_algo;
-                        ssl->buffers.keySz = rsaSz;
-                    }
-                    else if(ctx) {
-                        ctx->privateKeyType = rsa_sa_algo;
-                        ctx->privateKeySz = rsaSz;
-                    }
-
-                    rsaKey = 1;
-                    (void)rsaKey;  /* for no ecc builds */
-
-                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-                        ssl->options.haveStaticECC = 0;
-                        resetSuites = 1;
-                    }
-                }
-
-                wc_FreeRsaKey(key);
-            }
-
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(key, heap, DYNAMIC_TYPE_RSA);
-        #endif
-
-            if (ret != 0)
-                return ret;
-        }
-    #endif
-    #ifdef HAVE_ECC
-        if (!rsaKey && !ed25519Key) {
-            /* make sure ECC key can be used */
-            word32   idx = 0;
-        #ifdef WOLFSSL_SMALL_STACK
-            ecc_key* key = NULL;
-        #else
-            ecc_key  key[1];
-        #endif
-
-        #ifdef WOLFSSL_SMALL_STACK
-            key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
-            if (key == NULL)
-                return MEMORY_E;
-        #endif
-
-            if (wc_ecc_init_ex(key, heap, devId) == 0) {
-                if (wc_EccPrivateKeyDecode(der->buffer, &idx, key,
-                                                            der->length) == 0) {
-                    int keySz = wc_ecc_size(key);
-                    int minKeySz;
-
-                    /* check for minimum ECC key size and then free */
-                    minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
-                    if (keySz < minKeySz) {
-                        wc_ecc_free(key);
-                        WOLFSSL_MSG("ECC private key too small");
-                        return ECC_KEY_SIZE_E;
-                    }
-
-                    eccKey = 1;
-                    if (ssl) {
-                        ssl->options.haveStaticECC = 1;
-                        ssl->buffers.keyType = ecc_dsa_sa_algo;
-                        ssl->buffers.keySz = keySz;
-                    }
-                    else if (ctx) {
-                        ctx->haveStaticECC = 1;
-                        ctx->privateKeyType = ecc_dsa_sa_algo;
-                        ctx->privateKeySz = keySz;
-                    }
-
-                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-                        resetSuites = 1;
-                    }
-                }
-                else
-                    eccKey = 0;
-
-                wc_ecc_free(key);
-            }
-
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(key, heap, DYNAMIC_TYPE_ECC);
-        #endif
-        }
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        if (!rsaKey && !eccKey) {
-            /* make sure Ed25519 key can be used */
-            word32       idx = 0;
-        #ifdef WOLFSSL_SMALL_STACK
-            ed25519_key* key = NULL;
-        #else
-            ed25519_key  key[1];
-        #endif
-
-        #ifdef WOLFSSL_SMALL_STACK
-            key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
-                                                          DYNAMIC_TYPE_ED25519);
-            if (key == NULL)
-                return MEMORY_E;
-        #endif
-
-            ret = wc_ed25519_init(key);
-            if (ret == 0) {
-                if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key,
-                                                            der->length) != 0) {
-                    ret = WOLFSSL_BAD_FILE;
-                }
-
-                if (ret == 0) {
-                    /* check for minimum key size and then free */
-                    int minKeySz = ssl ? ssl->options.minEccKeySz :
-                                                               ctx->minEccKeySz;
-                    if (ED25519_KEY_SIZE < minKeySz) {
-                        WOLFSSL_MSG("ED25519 private key too small");
-                        ret = ECC_KEY_SIZE_E;
-                    }
-                }
-                if (ret == 0) {
-                    if (ssl) {
-                        ssl->buffers.keyType = ed25519_sa_algo;
-                        ssl->buffers.keySz = ED25519_KEY_SIZE;
-                    }
-                    else if (ctx) {
-                        ctx->privateKeyType = ed25519_sa_algo;
-                        ctx->privateKeySz = ED25519_KEY_SIZE;
-                    }
-
-                    ed25519Key = 1;
-                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-                        resetSuites = 1;
-                    }
-                }
-
-                wc_ed25519_free(key);
-            }
-
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(key, heap, DYNAMIC_TYPE_ED25519);
-        #endif
-            if (ret != 0)
-                return ret;
-        }
-    #else
-        if (!rsaKey && !eccKey && !ed25519Key)
-            return WOLFSSL_BAD_FILE;
-    #endif
-        (void)ed25519Key;
-        (void)devId;
-    }
-    else if (type == CERT_TYPE) {
-    #ifdef WOLFSSL_SMALL_STACK
-        DecodedCert* cert = NULL;
-    #else
-        DecodedCert  cert[1];
-    #endif
-    #ifdef HAVE_PK_CALLBACKS
-        int keyType = 0, keySz = 0;
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
-                                     DYNAMIC_TYPE_DCERT);
-        if (cert == NULL)
-            return MEMORY_E;
-    #endif
-
-        WOLFSSL_MSG("Checking cert signature type");
-        InitDecodedCert(cert, der->buffer, der->length, heap);
-
-        if (DecodeToKey(cert, 0) < 0) {
-            WOLFSSL_MSG("Decode to key failed");
-            FreeDecodedCert(cert);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
-        #endif
-            return WOLFSSL_BAD_FILE;
-        }
-
-        if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
-            resetSuites = 1;
-        }
-        if (ssl && ssl->ctx->haveECDSAsig) {
-            WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off");
-            ssl->options.haveECDSAsig = 0;   /* may turn back on next */
-        }
-
-        switch (cert->signatureOID) {
-            case CTC_SHAwECDSA:
-            case CTC_SHA256wECDSA:
-            case CTC_SHA384wECDSA:
-            case CTC_SHA512wECDSA:
-                WOLFSSL_MSG("ECDSA cert signature");
-                if (ssl)
-                    ssl->options.haveECDSAsig = 1;
-                else if (ctx)
-                    ctx->haveECDSAsig = 1;
-                break;
-            case CTC_ED25519:
-                WOLFSSL_MSG("ED25519 cert signature");
-                if (ssl)
-                    ssl->options.haveECDSAsig = 1;
-                else if (ctx)
-                    ctx->haveECDSAsig = 1;
-                break;
-            default:
-                WOLFSSL_MSG("Not ECDSA cert signature");
-                break;
-        }
-
-    #if defined(HAVE_ECC) || defined(HAVE_ED25519)
-        if (ssl) {
-            ssl->pkCurveOID = cert->pkCurveOID;
-        #ifndef WC_STRICT_SIG
-            if (cert->keyOID == ECDSAk) {
-                ssl->options.haveECC = 1;
-            }
-            #ifdef HAVE_ED25519
-                else if (cert->keyOID == ED25519k) {
-                    ssl->options.haveECC = 1;
-                }
-            #endif
-        #else
-            ssl->options.haveECC = ssl->options.haveECDSAsig;
-        #endif
-        }
-        else if (ctx) {
-            ctx->pkCurveOID = cert->pkCurveOID;
-        #ifndef WC_STRICT_SIG
-            if (cert->keyOID == ECDSAk) {
-                ctx->haveECC = 1;
-            }
-            #ifdef HAVE_ED25519
-                else if (cert->keyOID == ED25519k) {
-                    ctx->haveECC = 1;
-                }
-            #endif
-        #else
-            ctx->haveECC = ctx->haveECDSAsig;
-        #endif
-        }
-    #endif
-
-        /* check key size of cert unless specified not to */
-        switch (cert->keyOID) {
-        #ifndef NO_RSA
-            case RSAk:
-                if (ssl && !ssl->options.verifyNone) {
-                    if (ssl->options.minRsaKeySz < 0 ||
-                          cert->pubKeySize < (word16)ssl->options.minRsaKeySz) {
-                        ret = RSA_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate RSA key size too small");
-                    }
-                }
-                else if (ctx && !ctx->verifyNone) {
-                    if (ctx->minRsaKeySz < 0 ||
-                                  cert->pubKeySize < (word16)ctx->minRsaKeySz) {
-                        ret = RSA_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate RSA key size too small");
-                    }
-                }
-            #ifdef HAVE_PK_CALLBACKS
-                keyType = rsa_sa_algo;
-                /* pubKeySize is the encoded public key */
-                /* mask lsb 5-bits to round by 16 to get actual key size */
-                keySz = cert->pubKeySize & ~0x1FL;
-            #endif
-                break;
-        #endif /* !NO_RSA */
-        #ifdef HAVE_ECC
-            case ECDSAk:
-                if (ssl && !ssl->options.verifyNone) {
-                    if (ssl->options.minEccKeySz < 0 ||
-                          cert->pubKeySize < (word16)ssl->options.minEccKeySz) {
-                        ret = ECC_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate ECC key size error");
-                    }
-                }
-                else if (ctx && !ctx->verifyNone) {
-                    if (ctx->minEccKeySz < 0 ||
-                                  cert->pubKeySize < (word16)ctx->minEccKeySz) {
-                        ret = ECC_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate ECC key size error");
-                    }
-                }
-            #ifdef HAVE_PK_CALLBACKS
-                keyType = ecc_dsa_sa_algo;
-                /* pubKeySize is encByte + x + y */
-                keySz = (cert->pubKeySize - 1) / 2;
-            #endif
-                break;
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            case ED25519k:
-                if (ssl && !ssl->options.verifyNone) {
-                    if (ssl->options.minEccKeySz < 0 ||
-                          ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
-                        ret = ECC_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate Ed key size error");
-                    }
-                }
-                else if (ctx && !ctx->verifyNone) {
-                    if (ctx->minEccKeySz < 0 ||
-                                  ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) {
-                        ret = ECC_KEY_SIZE_E;
-                        WOLFSSL_MSG("Certificate ECC key size error");
-                    }
-                }
-            #ifdef HAVE_PK_CALLBACKS
-                keyType = ed25519_sa_algo;
-                keySz = ED25519_KEY_SIZE;
-            #endif
-                break;
-        #endif /* HAVE_ED25519 */
-
-            default:
-                WOLFSSL_MSG("No key size check done on certificate");
-                break; /* do no check if not a case for the key */
-        }
-
-    #ifdef HAVE_PK_CALLBACKS
-        if (ssl && ssl->buffers.keyType == 0) {
-            ssl->buffers.keyType = keyType;
-            ssl->buffers.keySz = keySz;
-        }
-        else if (ctx && ctx->privateKeyType == 0) {
-            ctx->privateKeyType = keyType;
-            ctx->privateKeySz = keySz;
-        }
-    #endif
-
-        FreeDecodedCert(cert);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
-    #endif
-
-        if (ret != 0) {
-            return ret;
-        }
-    }
-
-    if (ssl && resetSuites) {
-        word16 havePSK = 0;
-        word16 haveRSA = 0;
-        int    keySz   = 0;
-
-        #ifndef NO_PSK
-        if (ssl->options.havePSK) {
-            havePSK = 1;
-        }
-        #endif
-        #ifndef NO_RSA
-            haveRSA = 1;
-        #endif
-        #ifndef NO_CERTS
-            keySz = ssl->buffers.keySz;
-        #endif
-
-        /* let's reset suites */
-        InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
-                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
-                   ssl->options.haveECDSAsig, ssl->options.haveECC,
-                   ssl->options.haveStaticECC, ssl->options.side);
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* CA PEM file for verification, may have multiple/chain certs to process */
-static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
-                            long sz, int format, int type, WOLFSSL* ssl)
-{
-    long used   = 0;
-    int  ret    = 0;
-    int  gotOne = 0;
-
-    WOLFSSL_MSG("Processing CA PEM file");
-    while (used < sz) {
-        long consumed = 0;
-
-        ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
-                            &consumed, 0);
-
-#ifdef WOLFSSL_WPAS
-#ifdef HAVE_CRL
-        if (ret < 0) {
-            DerBuffer*    der = NULL;
-            EncryptedInfo info;
-
-            WOLFSSL_MSG("Trying a CRL");
-            if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
-                                                                   NULL) == 0) {
-                WOLFSSL_MSG("   Proccessed a CRL");
-                wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
-                                                der->length, WOLFSSL_FILETYPE_ASN1);
-                FreeDer(&der);
-                used += info.consumed;
-                continue;
-            }
-        }
-#endif
-#endif
-        if (ret < 0)
-        {
-            if(consumed > 0) { /* Made progress in file */
-                WOLFSSL_ERROR(ret);
-                WOLFSSL_MSG("CA Parse failed, with progress in file.");
-                WOLFSSL_MSG("Search for other certs in file");
-            } else {
-                WOLFSSL_MSG("CA Parse failed, no progress in file.");
-                WOLFSSL_MSG("Do not continue search for other certs in file");
-                break;
-            }
-        } else {
-            WOLFSSL_MSG("   Processed a CA");
-            gotOne = 1;
-        }
-        used += consumed;
-    }
-
-    if(gotOne)
-    {
-        WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
-        return WOLFSSL_SUCCESS;
-    }
-    return ret;
-}
-
-
-static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
-{
-    #ifndef NO_WOLFSSL_CLIENT
-        #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-            return wolfSSLv3_client_method();
-        #elif !defined(WOLFSSL_NO_TLS12)
-            return wolfTLSv1_2_client_method();
-        #elif defined(WOLFSSL_TLS13)
-            return wolfTLSv1_3_client_method();
-        #endif
-    #elif !defined(NO_WOLFSSL_SERVER)
-        #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-            return wolfSSLv3_server_method();
-        #elif !defined(WOLFSSL_NO_TLS12)
-            return wolfTLSv1_2_server_method();
-        #elif defined(WOLFSSL_TLS13)
-            return wolfTLSv1_3_server_method();
-        #endif
-    #else
-        return NULL;
-    #endif
-}
-
-
-/* like load verify locations, 1 for success, < 0 for error */
-int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
-                                   const unsigned char* in, long sz, int format)
-{
-    int ret = WOLFSSL_FATAL_ERROR;
-    WOLFSSL_CTX* tmp;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer");
-
-    if (cm == NULL) {
-        WOLFSSL_MSG("No CertManager error");
-        return ret;
-    }
-    tmp = wolfSSL_CTX_new(cm_pick_method());
-
-    if (tmp == NULL) {
-        WOLFSSL_MSG("CTX new failed");
-        return ret;
-    }
-
-    /* for tmp use */
-    wolfSSL_CertManagerFree(tmp->cm);
-    tmp->cm = cm;
-
-    ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format);
-
-    /* don't loose our good one */
-    tmp->cm = NULL;
-    wolfSSL_CTX_free(tmp);
-
-    return ret;
-}
-
-#ifdef HAVE_CRL
-
-int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
-                                   const unsigned char* buff, long sz, int type)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (cm->crl == NULL) {
-        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("Enable CRL failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    return BufferLoadCRL(cm->crl, buff, sz, type, 0);
-}
-
-
-int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
-                              long sz, int type)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
-}
-
-
-int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
-                          long sz, int type)
-{
-    WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
-
-    if (ssl == NULL || ssl->ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type);
-}
-
-
-#endif /* HAVE_CRL */
-
-/* turn on CRL if off and compiled in, set options */
-int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    (void)options;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    #ifdef HAVE_CRL
-        if (cm->crl == NULL) {
-            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
-                                            DYNAMIC_TYPE_CRL);
-            if (cm->crl == NULL)
-                return MEMORY_E;
-
-            if (InitCRL(cm->crl, cm) != 0) {
-                WOLFSSL_MSG("Init CRL failed");
-                FreeCRL(cm->crl, 1);
-                cm->crl = NULL;
-                return WOLFSSL_FAILURE;
-            }
-
-        #ifdef HAVE_CRL_IO
-            cm->crl->crlIOCb = EmbedCrlLookup;
-        #endif
-        }
-
-        cm->crlEnabled = 1;
-        if (options & WOLFSSL_CRL_CHECKALL)
-            cm->crlCheckAll = 1;
-    #else
-        ret = NOT_COMPILED_IN;
-    #endif
-
-    return ret;
-}
-
-
-int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    cm->crlEnabled = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
-int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
-                                    long sz, int format)
-{
-    int ret = 0;
-    DerBuffer* der = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
-
-#ifdef WOLFSSL_SMALL_STACK
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
-                                 DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return MEMORY_E;
-#endif
-
-    if (format == WOLFSSL_FILETYPE_PEM) {
-#ifdef WOLFSSL_PEM_TO_DER
-        ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
-        if (ret != 0) {
-            FreeDer(&der);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-        #endif
-            return ret;
-        }
-        InitDecodedCert(cert, der->buffer, der->length, cm->heap);
-#else
-        ret = NOT_COMPILED_IN;
-#endif
-    }
-    else {
-        InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap);
-    }
-
-    if (ret == 0)
-        ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
-
-#ifdef HAVE_CRL
-    if (ret == 0 && cm->crlEnabled)
-        ret = CheckCertCRL(cm->crl, cert);
-#endif
-
-    FreeDecodedCert(cert);
-    FreeDer(&der);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
-#endif
-
-    return ret == 0 ? WOLFSSL_SUCCESS : ret;
-}
-
-
-/* turn on OCSP if off and compiled in, set options */
-int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    (void)options;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    #ifdef HAVE_OCSP
-        if (cm->ocsp == NULL) {
-            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
-                                              DYNAMIC_TYPE_OCSP);
-            if (cm->ocsp == NULL)
-                return MEMORY_E;
-
-            if (InitOCSP(cm->ocsp, cm) != 0) {
-                WOLFSSL_MSG("Init OCSP failed");
-                FreeOCSP(cm->ocsp, 1);
-                cm->ocsp = NULL;
-                return WOLFSSL_FAILURE;
-            }
-        }
-        cm->ocspEnabled = 1;
-        if (options & WOLFSSL_OCSP_URL_OVERRIDE)
-            cm->ocspUseOverrideURL = 1;
-        if (options & WOLFSSL_OCSP_NO_NONCE)
-            cm->ocspSendNonce = 0;
-        else
-            cm->ocspSendNonce = 1;
-        if (options & WOLFSSL_OCSP_CHECKALL)
-            cm->ocspCheckAll = 1;
-        #ifndef WOLFSSL_USER_IO
-            cm->ocspIOCb = EmbedOcspLookup;
-            cm->ocspRespFreeCb = EmbedOcspRespFree;
-            cm->ocspIOCtx = cm->heap;
-        #endif /* WOLFSSL_USER_IO */
-    #else
-        ret = NOT_COMPILED_IN;
-    #endif
-
-    return ret;
-}
-
-
-int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    cm->ocspEnabled = 0;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* turn on OCSP Stapling if off and compiled in, set options */
-int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-    if (cm->ocsp_stapling == NULL) {
-        cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
-                                               cm->heap, DYNAMIC_TYPE_OCSP);
-        if (cm->ocsp_stapling == NULL)
-            return MEMORY_E;
-
-        if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
-            WOLFSSL_MSG("Init OCSP failed");
-            FreeOCSP(cm->ocsp_stapling, 1);
-            cm->ocsp_stapling = NULL;
-            return WOLFSSL_FAILURE;
-        }
-    }
-    cm->ocspStaplingEnabled = 1;
-
-    #ifndef WOLFSSL_USER_IO
-        cm->ocspIOCb = EmbedOcspLookup;
-        cm->ocspRespFreeCb = EmbedOcspRespFree;
-        cm->ocspIOCtx = cm->heap;
-    #endif /* WOLFSSL_USER_IO */
-#else
-    ret = NOT_COMPILED_IN;
-#endif
-
-    return ret;
-}
-
-int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-    cm->ocspStaplingEnabled = 0;
-#else
-    ret = NOT_COMPILED_IN;
-#endif
-    return ret;
-}
-#if defined(SESSION_CERTS)
-WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
-    if ((ssl == NULL) || (ssl->session.chain.count == 0))
-        return NULL;
-    else
-        return (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain;
-}
-#endif
-#ifdef HAVE_OCSP
-
-/* check CRL if enabled, WOLFSSL_SUCCESS  */
-int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (cm->ocspEnabled == 0)
-        return WOLFSSL_SUCCESS;
-
-#ifdef WOLFSSL_SMALL_STACK
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(cert, der, sz, NULL);
-
-    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
-        WOLFSSL_MSG("ParseCert failed");
-    }
-    else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
-        WOLFSSL_MSG("CheckCertOCSP failed");
-    }
-
-    FreeDecodedCert(cert);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-#endif
-
-    return ret == 0 ? WOLFSSL_SUCCESS : ret;
-}
-
-
-int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
-                                          const char* url)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
-    if (url != NULL) {
-        int urlSz = (int)XSTRLEN(url) + 1;
-        cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL);
-        if (cm->ocspOverrideURL != NULL) {
-            XMEMCPY(cm->ocspOverrideURL, url, urlSz);
-        }
-        else
-            return MEMORY_E;
-    }
-    else
-        cm->ocspOverrideURL = NULL;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
-                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    cm->ocspIOCb = ioCb;
-    cm->ocspRespFreeCb = respFreeCb;
-    cm->ocspIOCtx = ioCbCtx;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
-{
-    WOLFSSL_ENTER("wolfSSL_EnableOCSP");
-    if (ssl)
-        return wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options);
-    else
-        return BAD_FUNC_ARG;
-}
-
-int wolfSSL_DisableOCSP(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_DisableOCSP");
-    if (ssl)
-        return wolfSSL_CertManagerDisableOCSP(ssl->ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
-    if (ssl)
-        return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
-    if (ssl)
-        return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
-{
-    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
-    if (ssl)
-        return wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
-                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
-{
-    WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
-    if (ssl) {
-        ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
-        return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm,
-                                             ioCb, respFreeCb, NULL);
-    }
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
-    if (ctx)
-        return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
-    if (ctx)
-        return wolfSSL_CertManagerDisableOCSP(ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
-{
-    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
-    if (ctx)
-        return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
-                           CbOCSPRespFree respFreeCb, void* ioCbCtx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
-    if (ctx)
-        return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
-                                             respFreeCb, ioCbCtx);
-    else
-        return BAD_FUNC_ARG;
-}
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
-    if (ctx)
-        return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
-    if (ctx)
-        return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-
-#endif /* HAVE_OCSP */
-
-
-#ifndef NO_FILESYSTEM
-
-/* process a file with name fname into ctx of format and type
-   userChain specifies a user certificate chain to pass during handshake */
-int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
-                WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force heap usage */
-#else
-    byte   staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte*  myBuffer = staticBuffer;
-    int    dynamic = 0;
-    int    ret;
-    long   sz = 0;
-    XFILE  file;
-    void*  heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
-
-    (void)crl;
-    (void)heapHint;
-
-    if (fname == NULL) return WOLFSSL_BAD_FILE;
-
-    file = XFOPEN(fname, "rb");
-    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
-    XFSEEK(file, 0, XSEEK_END);
-    sz = XFTELL(file);
-    XREWIND(file);
-
-    if (sz > (long)sizeof(staticBuffer)) {
-        WOLFSSL_MSG("Getting dynamic buffer");
-        myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
-        if (myBuffer == NULL) {
-            XFCLOSE(file);
-            return WOLFSSL_BAD_FILE;
-        }
-        dynamic = 1;
-    }
-    else if (sz <= 0) {
-        XFCLOSE(file);
-        return WOLFSSL_BAD_FILE;
-    }
-
-    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
-        ret = WOLFSSL_BAD_FILE;
-    else {
-        if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
-                                                  && format == WOLFSSL_FILETYPE_PEM)
-            ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl);
-#ifdef HAVE_CRL
-        else if (type == CRL_TYPE)
-            ret = BufferLoadCRL(crl, myBuffer, sz, format, 0);
-#endif
-        else
-            ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL,
-                                userChain);
-    }
-
-    XFCLOSE(file);
-    if (dynamic)
-        XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
-
-    return ret;
-}
-
-
-/* loads file then loads each file in path, no c_rehash */
-int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
-                                     const char* path)
-{
-    int ret = WOLFSSL_SUCCESS;
-#ifndef NO_WOLFSSL_DIR
-    int fileRet;
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations");
-
-    if (ctx == NULL || (file == NULL && path == NULL) )
-        return WOLFSSL_FAILURE;
-
-    if (file)
-        ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL);
-
-    if (ret == WOLFSSL_SUCCESS && path) {
-#ifndef NO_WOLFSSL_DIR
-        char* name = NULL;
-    #ifdef WOLFSSL_SMALL_STACK
-        ReadDirCtx* readCtx = NULL;
-        readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
-                                                       DYNAMIC_TYPE_DIRCTX);
-        if (readCtx == NULL)
-            return MEMORY_E;
-    #else
-        ReadDirCtx readCtx[1];
-    #endif
-
-        /* try to load each regular file in path */
-        fileRet = wc_ReadDirFirst(readCtx, path, &name);
-        while (fileRet == 0 && name) {
-            ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE,
-                                                          NULL, 0, NULL);
-            if (ret != WOLFSSL_SUCCESS)
-                break;
-            fileRet = wc_ReadDirNext(readCtx, path, &name);
-        }
-        wc_ReadDirClose(readCtx);
-
-        /* pass directory read failure to response code */
-        if (ret == WOLFSSL_SUCCESS && fileRet != -1) {
-            ret = fileRet;
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
-    #endif
-#else
-        ret = NOT_COMPILED_IN;
-#endif
-    }
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* Used to specify a peer cert to match when connecting
-    ctx : the ctx structure to load in peer cert
-    file: the string name of cert file
-    type: type of format such as PEM/DER
- */
-int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
-
-    if (ctx == NULL || file == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL);
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
-int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
-                             int format)
-{
-    int    ret = WOLFSSL_FATAL_ERROR;
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force heap usage */
-#else
-    byte   staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte*  myBuffer = staticBuffer;
-    int    dynamic = 0;
-    long   sz = 0;
-    XFILE  file = XFOPEN(fname, "rb");
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
-
-    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
-    XFSEEK(file, 0, XSEEK_END);
-    sz = XFTELL(file);
-    XREWIND(file);
-
-    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
-        WOLFSSL_MSG("CertManagerVerify file bad size");
-        XFCLOSE(file);
-        return WOLFSSL_BAD_FILE;
-    }
-
-    if (sz > (long)sizeof(staticBuffer)) {
-        WOLFSSL_MSG("Getting dynamic buffer");
-        myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
-        if (myBuffer == NULL) {
-            XFCLOSE(file);
-            return WOLFSSL_BAD_FILE;
-        }
-        dynamic = 1;
-    }
-
-    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
-        ret = WOLFSSL_BAD_FILE;
-    else
-        ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
-
-    XFCLOSE(file);
-    if (dynamic)
-        XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE);
-
-    return ret;
-}
-
-
-/* like load verify locations, 1 for success, < 0 for error */
-int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
-                             const char* path)
-{
-    int ret = WOLFSSL_FATAL_ERROR;
-    WOLFSSL_CTX* tmp;
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
-
-    if (cm == NULL) {
-        WOLFSSL_MSG("No CertManager error");
-        return ret;
-    }
-    tmp = wolfSSL_CTX_new(cm_pick_method());
-
-    if (tmp == NULL) {
-        WOLFSSL_MSG("CTX new failed");
-        return ret;
-    }
-
-    /* for tmp use */
-    wolfSSL_CertManagerFree(tmp->cm);
-    tmp->cm = cm;
-
-    ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
-
-    /* don't loose our good one */
-    tmp->cm = NULL;
-    wolfSSL_CTX_free(tmp);
-
-    return ret;
-}
-
-
-/* Check private against public in certificate for match
- *
- * ctx  WOLFSSL_CTX structure to check private key in
- *
- * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */
-int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* der = NULL;
-#else
-    DecodedCert  der[1];
-#endif
-    word32 size;
-    byte*  buff;
-    int    ret;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_check_private_key");
-
-    if (ctx == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-#ifndef NO_CERTS
-#ifdef WOLFSSL_SMALL_STACK
-    der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
-    if (der == NULL)
-        return MEMORY_E;
-#endif
-
-    size = ctx->certificate->length;
-    buff = ctx->certificate->buffer;
-    InitDecodedCert(der, buff, size, ctx->heap);
-    if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
-        FreeDecodedCert(der);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
-    #endif
-        return WOLFSSL_FAILURE;
-    }
-
-    size = ctx->privateKey->length;
-    buff = ctx->privateKey->buffer;
-    ret  = wc_CheckPrivateKey(buff, size, der);
-    FreeDecodedCert(der);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
-#endif
-
-    if (ret == 1) {
-        return WOLFSSL_SUCCESS;
-    }
-    else {
-        return WOLFSSL_FAILURE;
-    }
-#else
-    WOLFSSL_MSG("NO_CERTS is defined, can not check private key");
-    return WOLFSSL_FAILURE;
-#endif
-}
-
-#ifdef HAVE_CRL
-
-
-/* check CRL if enabled, WOLFSSL_SUCCESS  */
-int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
-
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (cm->crlEnabled == 0)
-        return WOLFSSL_SUCCESS;
-
-#ifdef WOLFSSL_SMALL_STACK
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(cert, der, sz, NULL);
-
-    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) {
-        WOLFSSL_MSG("ParseCert failed");
-    }
-    else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
-        WOLFSSL_MSG("CheckCertCRL failed");
-    }
-
-    FreeDecodedCert(cert);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-#endif
-
-    return ret == 0 ? WOLFSSL_SUCCESS : ret;
-}
-
-
-int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    cm->cbMissingCRL = cb;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifdef HAVE_CRL_IO
-int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
-{
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    cm->crl->crlIOCb = cb;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
-                              int type, int monitor)
-{
-    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
-    if (cm == NULL)
-        return BAD_FUNC_ARG;
-
-    if (cm->crl == NULL) {
-        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("Enable CRL failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    return LoadCRL(cm->crl, path, type, monitor);
-}
-
-
-int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
-{
-    WOLFSSL_ENTER("wolfSSL_EnableCRL");
-    if (ssl)
-        return wolfSSL_CertManagerEnableCRL(ssl->ctx->cm, options);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_DisableCRL(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_DisableCRL");
-    if (ssl)
-        return wolfSSL_CertManagerDisableCRL(ssl->ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
-{
-    WOLFSSL_ENTER("wolfSSL_LoadCRL");
-    if (ssl)
-        return wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
-{
-    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
-    if (ssl)
-        return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb);
-    else
-        return BAD_FUNC_ARG;
-}
-
-#ifdef HAVE_CRL_IO
-int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
-{
-    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
-    if (ssl)
-        return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb);
-    else
-        return BAD_FUNC_ARG;
-}
-#endif
-
-int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
-    if (ctx)
-        return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
-    if (ctx)
-        return wolfSSL_CertManagerDisableCRL(ctx->cm);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
-                        int type, int monitor)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
-    if (ctx)
-        return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
-    else
-        return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
-    if (ctx)
-        return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
-    else
-        return BAD_FUNC_ARG;
-}
-
-#ifdef HAVE_CRL_IO
-int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
-    if (ctx)
-        return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
-    else
-        return BAD_FUNC_ARG;
-}
-#endif
-
-
-#endif /* HAVE_CRL */
-
-
-#ifdef WOLFSSL_DER_LOAD
-
-/* Add format parameter to allow DER load of CA files */
-int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
-                                          int format)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
-    if (ctx == NULL || file == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-#endif /* WOLFSSL_DER_LOAD */
-
-
-
-int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
-                                     int format)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
-    if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
-                                    int format)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
-    if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL)
-                    == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Sets the max chain depth when verifying a certificate chain. Default depth
- * is set to MAX_CHAIN_DEPTH.
- *
- * ctx   WOLFSSL_CTX structure to set depth in
- * depth max depth
- */
-void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
-    WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
-
-    if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
-        WOLFSSL_MSG("Bad depth argument, too large or less than 0");
-        return;
-    }
-
-    ctx->verifyDepth = (byte)depth;
-}
-
-
-/* get cert chaining depth using ssl struct */
-long wolfSSL_get_verify_depth(WOLFSSL* ssl)
-{
-    if(ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-#ifndef OPENSSL_EXTRA
-    return MAX_CHAIN_DEPTH;
-#else
-    return ssl->options.verifyDepth;
-#endif
-}
-
-
-/* get cert chaining depth using ctx struct */
-long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
-{
-    if(ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-#ifndef OPENSSL_EXTRA
-    return MAX_CHAIN_DEPTH;
-#else
-    return ctx->verifyDepth;
-#endif
-}
-
-
-int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
-{
-   /* process up to MAX_CHAIN_DEPTH plus subject cert */
-   WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
-   if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL)
-                   == WOLFSSL_SUCCESS)
-       return WOLFSSL_SUCCESS;
-
-   return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
-                                                  const char* file, int format)
-{
-   /* process up to MAX_CHAIN_DEPTH plus subject cert */
-   WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
-   if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL)
-                   == WOLFSSL_SUCCESS)
-       return WOLFSSL_SUCCESS;
-
-   return WOLFSSL_FAILURE;
-}
-
-
-#ifndef NO_DH
-
-/* server Diffie-Hellman parameters */
-static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
-                                        const char* fname, int format)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force heap usage */
-#else
-    byte   staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte*  myBuffer = staticBuffer;
-    int    dynamic = 0;
-    int    ret;
-    long   sz = 0;
-    XFILE  file;
-
-    if (ctx == NULL || fname == NULL)
-        return BAD_FUNC_ARG;
-
-    file = XFOPEN(fname, "rb");
-    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
-    XFSEEK(file, 0, XSEEK_END);
-    sz = XFTELL(file);
-    XREWIND(file);
-
-    if (sz > (long)sizeof(staticBuffer)) {
-        WOLFSSL_MSG("Getting dynamic buffer");
-        myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
-        if (myBuffer == NULL) {
-            XFCLOSE(file);
-            return WOLFSSL_BAD_FILE;
-        }
-        dynamic = 1;
-    }
-    else if (sz <= 0) {
-        XFCLOSE(file);
-        return WOLFSSL_BAD_FILE;
-    }
-
-    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
-        ret = WOLFSSL_BAD_FILE;
-    else {
-        if (ssl)
-            ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
-        else
-            ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format);
-    }
-
-    XFCLOSE(file);
-    if (dynamic)
-        XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
-
-    return ret;
-}
-
-/* server Diffie-Hellman parameters */
-int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
-}
-
-
-/* server Diffie-Hellman parameters */
-int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
-{
-    return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
-}
-
-#endif /* NO_DH */
-
-#endif /* NO_FILESYSTEM */
-
-
-#if defined(OPENSSL_EXTRA) || !defined(NO_PWDBASED) && \
-    (defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER))
-
-static int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
-    int* pHash, int* pHashSz)
-{
-    enum wc_HashType hash = WC_HASH_TYPE_NONE;
-    int hashSz;
-
-    if (XSTRLEN(evp) < 3) {
-        /* do not try comparing strings if size is too small */
-        return WOLFSSL_FAILURE;
-    }
-
-    if (XSTRNCMP("SHA", evp, 3) == 0) {
-        if (XSTRLEN(evp) > 3) {
-        #ifndef NO_SHA256
-            if (XSTRNCMP("SHA256", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA256;
-            }
-            else
-        #endif
-        #ifdef WOLFSSL_SHA384
-            if (XSTRNCMP("SHA384", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA384;
-            }
-            else
-        #endif
-        #ifdef WOLFSSL_SHA512
-            if (XSTRNCMP("SHA512", evp, 6) == 0) {
-                hash = WC_HASH_TYPE_SHA512;
-            }
-            else
-        #endif
-            {
-                WOLFSSL_MSG("Unknown SHA hash");
-            }
-        }
-        else {
-            hash = WC_HASH_TYPE_SHA;
-        }
-    }
-#ifdef WOLFSSL_MD2
-    else if (XSTRNCMP("MD2", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD2;
-    }
-#endif
-#ifndef NO_MD4
-    else if (XSTRNCMP("MD4", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD4;
-    }
-#endif
-#ifndef NO_MD5
-    else if (XSTRNCMP("MD5", evp, 3) == 0) {
-        hash = WC_HASH_TYPE_MD5;
-    }
-#endif
-
-    if (pHash)
-        *pHash = hash;
-
-    hashSz = wc_HashGetDigestSize(hash);
-    if (pHashSz)
-        *pHashSz = hashSz;
-
-    if (hashSz < 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif
-
-
-#ifdef OPENSSL_EXTRA
-/* put SSL type in extra for now, not very common */
-
-/* Converts a DER format key read from "bio" to a PKCS8 structure.
- *
- * bio  input bio to read DER from
- * pkey If not NULL then this pointer will be overwritten with a new PKCS8
- *      structure.
- *
- * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
- *         case.
- */
-WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
-        WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
-{
-    WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
-#ifdef WOLFSSL_PEM_TO_DER
-    unsigned char* mem;
-    int memSz;
-    int keySz;
-
-    WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()");
-
-    if (bio == NULL) {
-        return NULL;
-    }
-
-    if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
-        return NULL;
-    }
-
-    if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) {
-        WOLFSSL_MSG("Not PEM format");
-        keySz = memSz;
-        if ((keySz = ToTraditional((byte*)mem, (word32)keySz)) < 0) {
-            return NULL;
-        }
-    }
-
-    pkcs8 = wolfSSL_PKEY_new();
-    if (pkcs8 == NULL) {
-        return NULL;
-    }
-
-    pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (pkcs8->pkey.ptr == NULL) {
-        wolfSSL_EVP_PKEY_free(pkcs8);
-        return NULL;
-    }
-    XMEMCPY(pkcs8->pkey.ptr, mem, keySz);
-    pkcs8->pkey_sz = keySz;
-
-    if (pkey != NULL) {
-        *pkey = pkcs8;
-    }
-#else
-    (void)bio;
-    (void)pkey;
-#endif /* WOLFSSL_PEM_TO_DER */
-
-    return pkcs8;
-}
-
-
-/* expecting DER format public key
- *
- * bio  input bio to read DER from
- * out  If not NULL then this pointer will be overwritten with a new
- * WOLFSSL_EVP_PKEY pointer
- *
- * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
-                                         WOLFSSL_EVP_PKEY** out)
-{
-    unsigned char* mem;
-    long memSz;
-    WOLFSSL_EVP_PKEY* pkey = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()");
-
-    if (bio == NULL) {
-        return NULL;
-    }
-    (void)out;
-
-    memSz = wolfSSL_BIO_pending(bio);
-    if (memSz <= 0) {
-        return NULL;
-    }
-
-    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (mem == NULL) {
-        return NULL;
-    }
-
-    if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
-        pkey = wolfSSL_d2i_PUBKEY(NULL, &mem, memSz);
-        if (out != NULL && pkey != NULL) {
-            *out = pkey;
-        }
-    }
-
-    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return pkey;
-}
-
-
-
-/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
- *
- * out  pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
- * in   DER buffer to convert
- * inSz size of in buffer
- *
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- *         on fail
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in,
-        long inSz)
-{
-    WOLFSSL_EVP_PKEY* pkey = NULL;
-    const unsigned char* mem;
-    long memSz = inSz;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
-
-    if (in == NULL || inSz < 0) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-    mem = *in;
-
-    #if !defined(NO_RSA)
-    {
-        RsaKey rsa;
-        word32 keyIdx = 0;
-
-        /* test if RSA key */
-        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
-            wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
-            wc_FreeRsaKey(&rsa);
-            pkey = wolfSSL_PKEY_new();
-            if (pkey != NULL) {
-                pkey->pkey_sz = keyIdx;
-                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
-                        DYNAMIC_TYPE_PUBLIC_KEY);
-                if (pkey->pkey.ptr == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
-                pkey->type = EVP_PKEY_RSA;
-                if (out != NULL) {
-                    *out = pkey;
-                }
-
-                pkey->ownRsa = 1;
-                pkey->rsa = wolfSSL_RSA_new();
-                if (pkey->rsa == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-
-                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
-                            (const unsigned char*)pkey->pkey.ptr,
-                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-
-                return pkey;
-            }
-        }
-        wc_FreeRsaKey(&rsa);
-    }
-    #endif /* NO_RSA */
-
-    #ifdef HAVE_ECC
-    {
-        word32  keyIdx = 0;
-        ecc_key ecc;
-
-        if (wc_ecc_init(&ecc) == 0 &&
-            wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
-            wc_ecc_free(&ecc);
-            pkey = wolfSSL_PKEY_new();
-            if (pkey != NULL) {
-                pkey->pkey_sz = keyIdx;
-                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
-                        DYNAMIC_TYPE_PUBLIC_KEY);
-                if (pkey->pkey.ptr == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
-                pkey->type = EVP_PKEY_EC;
-                if (out != NULL) {
-                    *out = pkey;
-                }
-                return pkey;
-            }
-        }
-        wc_ecc_free(&ecc);
-    }
-    #endif /* HAVE_ECC */
-
-    return pkey;
-
-}
-
-
-/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
- *
- * type  type of key
- * out   newly created WOLFSSL_EVP_PKEY structure
- * in    pointer to input key DER
- * inSz  size of in buffer
- *
- * On success a non null pointer is returned and the pointer in is advanced the
- * same number of bytes read.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
-        const unsigned char **in, long inSz)
-{
-    WOLFSSL_EVP_PKEY* local;
-    word32 idx = 0;
-    int    ret;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
-
-    if (in == NULL || inSz < 0) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-
-    /* Check if input buffer has PKCS8 header. In the case that it does not
-     * have a PKCS8 header then do not error out. */
-    if ((ret = ToTraditionalInline((const byte*)(*in), &idx, (word32)inSz))
-            > 0) {
-        WOLFSSL_MSG("Found and removed PKCS8 header");
-    }
-    else {
-        if (ret != ASN_PARSE_E) {
-            WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
-            return NULL;
-        }
-    }
-
-    if (out != NULL && *out != NULL) {
-        wolfSSL_EVP_PKEY_free(*out);
-    }
-    local = wolfSSL_PKEY_new();
-    if (local == NULL) {
-        return NULL;
-    }
-
-    /* sanity check on idx before use */
-    if ((int)idx > inSz) {
-        WOLFSSL_MSG("Issue with index pointer");
-        wolfSSL_EVP_PKEY_free(local);
-        local = NULL;
-        return NULL;
-    }
-
-    local->type     = type;
-    local->pkey_sz  = (int)inSz - idx;
-    local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (local->pkey.ptr == NULL) {
-        wolfSSL_EVP_PKEY_free(local);
-        local = NULL;
-        return NULL;
-    }
-    else {
-        XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx);
-    }
-
-    switch (type) {
-#ifndef NO_RSA
-        case EVP_PKEY_RSA:
-            local->ownRsa = 1;
-            local->rsa = wolfSSL_RSA_new();
-            if (local->rsa == NULL) {
-                wolfSSL_EVP_PKEY_free(local);
-                return NULL;
-            }
-            if (wolfSSL_RSA_LoadDer_ex(local->rsa,
-                      (const unsigned char*)local->pkey.ptr, local->pkey_sz,
-                      WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) {
-                wolfSSL_EVP_PKEY_free(local);
-                return NULL;
-            }
-            break;
-#endif /* NO_RSA */
-#ifdef HAVE_ECC
-        case EVP_PKEY_EC:
-            local->ownEcc = 1;
-            local->ecc = wolfSSL_EC_KEY_new();
-            if (local->ecc == NULL) {
-                wolfSSL_EVP_PKEY_free(local);
-                return NULL;
-            }
-            if (wolfSSL_EC_KEY_LoadDer(local->ecc,
-                      (const unsigned char*)local->pkey.ptr, local->pkey_sz)
-                      != SSL_SUCCESS) {
-                wolfSSL_EVP_PKEY_free(local);
-                return NULL;
-            }
-            break;
-#endif /* HAVE_ECC */
-
-        default:
-            WOLFSSL_MSG("Unsupported key type");
-            wolfSSL_EVP_PKEY_free(local);
-            return NULL;
-    }
-
-    /* advance pointer with success */
-    if (local != NULL) {
-        if ((idx + local->pkey_sz) <= (word32)inSz) {
-            *in = *in + idx + local->pkey_sz;
-        }
-
-        if (out != NULL) {
-            *out = local;
-        }
-    }
-
-    return local;
-}
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
-{
-    WOLFSSL_STUB("SSL_ctrl");
-    (void)ssl;
-    (void)cmd;
-    (void)opt;
-    (void)pt;
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
-{
-    WOLFSSL_STUB("SSL_CTX_ctrl");
-    (void)ctx;
-    (void)cmd;
-    (void)opt;
-    (void)pt;
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_CERTS
-
-int wolfSSL_check_private_key(const WOLFSSL* ssl)
-{
-    DecodedCert der;
-    word32 size;
-    byte*  buff;
-    int    ret;
-
-    if (ssl == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    size = ssl->buffers.certificate->length;
-    buff = ssl->buffers.certificate->buffer;
-    InitDecodedCert(&der, buff, size, ssl->heap);
-#ifdef HAVE_PK_CALLBACKS
-    ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx);
-    if (ret != 0) {
-        FreeDecodedCert(&der);
-        return ret;
-    }
-#endif
-
-    if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
-        FreeDecodedCert(&der);
-        return WOLFSSL_FAILURE;
-    }
-
-    size = ssl->buffers.key->length;
-    buff = ssl->buffers.key->buffer;
-    ret  = wc_CheckPrivateKey(buff, size, &der);
-    FreeDecodedCert(&der);
-    return ret;
-}
-
-
-/* Looks for the extension matching the passed in nid
- *
- * c   : if not null then is set to status value -2 if multiple occurances
- *       of the extension are found, -1 if not found, 0 if found and not
- *       critical, and 1 if found and critical.
- * nid : Extension OID to be found.
- * idx : if NULL return first extension found match, otherwise start search at
- *       idx location and set idx to the location of extension returned.
- * returns NULL or a pointer to an WOLFSSL_STACK holding extension structure
- *
- * NOTE code for decoding extensions is in asn.c DecodeCertExtensions --
- * use already decoded extension in this function to avoid decoding twice.
- * Currently we do not make use of idx since getting pre decoded extensions.
- */
-void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509,
-                                                     int nid, int* c, int* idx)
-{
-    WOLFSSL_STACK* sk = NULL;
-    WOLFSSL_ASN1_OBJECT* obj = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i");
-
-    if (x509 == NULL) {
-        return NULL;
-    }
-
-    if (c != NULL) {
-        *c = -1; /* default to not found */
-    }
-
-    sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC(
-                sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1);
-    if (sk == NULL) {
-        return NULL;
-    }
-    XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)));
-
-    switch (nid) {
-        case BASIC_CA_OID:
-            if (x509->basicConstSet) {
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                if (c != NULL) {
-                    *c = x509->basicConstCrit;
-                }
-                obj->type = BASIC_CA_OID;
-                obj->grp  = oidCertExtType;
-            }
-            else {
-                WOLFSSL_MSG("No Basic Constraint set");
-            }
-            break;
-
-        case ALT_NAMES_OID:
-            {
-                DNS_entry* dns = NULL;
-
-                if (x509->subjAltNameSet && x509->altNames != NULL) {
-                    /* alt names are DNS_entry structs */
-                    if (c != NULL) {
-                        if (x509->altNames->next != NULL) {
-                            *c = -2; /* more then one found */
-                        }
-                        else {
-                            *c = x509->subjAltNameCrit;
-                        }
-                    }
-
-                    dns = x509->altNames;
-                    while (dns != NULL) {
-                        obj = wolfSSL_ASN1_OBJECT_new();
-                        if (obj == NULL) {
-                            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                            wolfSSL_sk_ASN1_OBJECT_free(sk);
-                            return NULL;
-                        }
-                        obj->type = dns->type;
-                        obj->grp  = oidCertExtType;
-                        obj->obj  = (byte*)dns->name;
-
-                        /* set app derefrenced pointers */
-                        obj->d.ia5_internal.data   = dns->name;
-                        obj->d.ia5_internal.length = (int)XSTRLEN(dns->name);
-                        dns = dns->next;
-                        /* last dns in list add at end of function */
-                        if (dns != NULL) {
-                            if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) !=
-                                                                  WOLFSSL_SUCCESS) {
-                            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
-                            wolfSSL_ASN1_OBJECT_free(obj);
-                            wolfSSL_sk_ASN1_OBJECT_free(sk);
-                            sk = NULL;
-                            }
-                        }
-                    }
-                }
-                else {
-                    WOLFSSL_MSG("No Alt Names set");
-                }
-            }
-            break;
-
-        case CRL_DIST_OID:
-            if (x509->CRLdistSet && x509->CRLInfo != NULL) {
-                if (c != NULL) {
-                    *c = x509->CRLdistCrit;
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = CRL_DIST_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = x509->CRLInfo;
-                obj->objSz = x509->CRLInfoSz;
-            }
-            else {
-                WOLFSSL_MSG("No CRL dist set");
-            }
-            break;
-
-        case AUTH_INFO_OID:
-            if (x509->authInfoSet && x509->authInfo != NULL) {
-                if (c != NULL) {
-                    *c = x509->authInfoCrit;
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = AUTH_INFO_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = x509->authInfo;
-                obj->objSz = x509->authInfoSz;
-            }
-            else {
-                WOLFSSL_MSG("No Auth Info set");
-            }
-            break;
-
-        case AUTH_KEY_OID:
-            if (x509->authKeyIdSet) {
-                if (c != NULL) {
-                    *c = x509->authKeyIdCrit;
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = AUTH_KEY_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = x509->authKeyId;
-                obj->objSz = x509->authKeyIdSz;
-            }
-            else {
-                WOLFSSL_MSG("No Auth Key set");
-            }
-            break;
-
-        case SUBJ_KEY_OID:
-            if (x509->subjKeyIdSet) {
-                if (c != NULL) {
-                    *c = x509->subjKeyIdCrit;
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = SUBJ_KEY_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = x509->subjKeyId;
-                obj->objSz = x509->subjKeyIdSz;
-            }
-            else {
-                WOLFSSL_MSG("No Subject Key set");
-            }
-            break;
-
-        case CERT_POLICY_OID:
-            #ifdef WOLFSSL_CERT_EXT
-            {
-                int i;
-
-                if (x509->certPoliciesNb > 0) {
-                    if (c != NULL) {
-                        if (x509->certPoliciesNb > 1) {
-                            *c = -2;
-                        }
-                        else {
-                            *c = 0;
-                        }
-                    }
-
-                    for (i = 0; i < x509->certPoliciesNb - 1; i++) {
-                        obj = wolfSSL_ASN1_OBJECT_new();
-                        if (obj == NULL) {
-                            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                            wolfSSL_sk_ASN1_OBJECT_free(sk);
-                            return NULL;
-                        }
-                        obj->type  = CERT_POLICY_OID;
-                        obj->grp   = oidCertExtType;
-                        obj->obj   = (byte*)(x509->certPolicies[i]);
-                        obj->objSz = MAX_CERTPOL_SZ;
-                        if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj)
-                                                               != WOLFSSL_SUCCESS) {
-                            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
-                            wolfSSL_ASN1_OBJECT_free(obj);
-                            wolfSSL_sk_ASN1_OBJECT_free(sk);
-                            sk = NULL;
-                        }
-                    }
-                    obj = wolfSSL_ASN1_OBJECT_new();
-                    if (obj == NULL) {
-                        WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                        wolfSSL_sk_ASN1_OBJECT_free(sk);
-                        return NULL;
-                    }
-                    obj->type  = CERT_POLICY_OID;
-                    obj->grp   = oidCertExtType;
-                    obj->obj   = (byte*)(x509->certPolicies[i]);
-                    obj->objSz = MAX_CERTPOL_SZ;
-                }
-                else {
-                    WOLFSSL_MSG("No Cert Policy set");
-                }
-            }
-            #else
-                #ifdef WOLFSSL_SEP
-                if (x509->certPolicySet) {
-                    if (c != NULL) {
-                        *c = x509->certPolicyCrit;
-                    }
-                    obj = wolfSSL_ASN1_OBJECT_new();
-                    if (obj == NULL) {
-                        WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                        wolfSSL_sk_ASN1_OBJECT_free(sk);
-                        return NULL;
-                    }
-                    obj->type  = CERT_POLICY_OID;
-                    obj->grp   = oidCertExtType;
-                }
-                else {
-                    WOLFSSL_MSG("No Cert Policy set");
-                }
-                #else
-                WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT");
-                #endif /* WOLFSSL_SEP */
-            #endif /* WOLFSSL_CERT_EXT */
-            break;
-
-        case KEY_USAGE_OID:
-            if (x509->keyUsageSet) {
-                if (c != NULL) {
-                    *c = x509->keyUsageCrit;
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = KEY_USAGE_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = (byte*)&(x509->keyUsage);
-                obj->objSz = sizeof(word16);
-            }
-            else {
-                WOLFSSL_MSG("No Key Usage set");
-            }
-            break;
-
-        case INHIBIT_ANY_OID:
-            WOLFSSL_MSG("INHIBIT ANY extension not supported");
-            break;
-
-        case EXT_KEY_USAGE_OID:
-            if (x509->extKeyUsageSrc != NULL) {
-                if (c != NULL) {
-                    if (x509->extKeyUsageCount > 1) {
-                        *c = -2;
-                    }
-                    else {
-                        *c = x509->extKeyUsageCrit;
-                    }
-                }
-                obj = wolfSSL_ASN1_OBJECT_new();
-                if (obj == NULL) {
-                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-                    wolfSSL_sk_ASN1_OBJECT_free(sk);
-                    return NULL;
-                }
-                obj->type  = EXT_KEY_USAGE_OID;
-                obj->grp   = oidCertExtType;
-                obj->obj   = x509->extKeyUsageSrc;
-                obj->objSz = x509->extKeyUsageSz;
-            }
-            else {
-                WOLFSSL_MSG("No Extended Key Usage set");
-            }
-            break;
-
-        case NAME_CONS_OID:
-            WOLFSSL_MSG("Name Constraint OID extension not supported");
-            break;
-
-        case PRIV_KEY_USAGE_PERIOD_OID:
-            WOLFSSL_MSG("Private Key Usage Period extension not supported");
-            break;
-
-        case SUBJECT_INFO_ACCESS:
-            WOLFSSL_MSG("Subject Info Access extension not supported");
-            break;
-
-        case POLICY_MAP_OID:
-            WOLFSSL_MSG("Policy Map extension not supported");
-            break;
-
-        case POLICY_CONST_OID:
-            WOLFSSL_MSG("Policy Constraint extension not supported");
-            break;
-
-        case ISSUE_ALT_NAMES_OID:
-            WOLFSSL_MSG("Issue Alt Names extension not supported");
-            break;
-
-        case TLS_FEATURE_OID:
-            WOLFSSL_MSG("TLS Feature extension not supported");
-            break;
-
-        default:
-            WOLFSSL_MSG("Unsupported/Unknown extension OID");
-    }
-
-    if (obj != NULL) {
-        if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
-            wolfSSL_ASN1_OBJECT_free(obj);
-            wolfSSL_sk_ASN1_OBJECT_free(sk);
-            sk = NULL;
-        }
-    }
-    else { /* no ASN1 object found for extension, free stack */
-        wolfSSL_sk_ASN1_OBJECT_free(sk);
-        sk = NULL;
-    }
-
-    (void)idx;
-
-    return sk;
-}
-
-
-/* this function makes the assumption that out buffer is big enough for digest*/
-static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out,
-                              unsigned int* outSz, const WOLFSSL_EVP_MD* evp,
-                              WOLFSSL_ENGINE* eng)
-{
-    int err;
-    int hashType = WC_HASH_TYPE_NONE;
-    int hashSz;
-
-    (void)eng;
-
-    err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz);
-    if (err != WOLFSSL_SUCCESS)
-        return err;
-
-    *outSz = hashSz;
-
-    if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, *outSz) != 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest,
-        unsigned char* buf, unsigned int* len)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_digest");
-
-    if (x509 == NULL || digest == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf,
-                              len, digest, NULL);
-}
-
-
-int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
-{
-    WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
-    if (ssl == NULL || pkey == NULL ) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
-                                         pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
-}
-
-
-int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der,
-                                long derSz)
-{
-    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
-    if (ssl == NULL || der == NULL ) {
-        return WOLFSSL_FAILURE;
-    }
-
-    (void)pri; /* type of private key */
-    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
-}
-
-
-#ifndef NO_RSA
-int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
-{
-    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
-    if (ssl == NULL || der == NULL ) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
-}
-#endif
-
-int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz)
-{
-    long idx;
-
-    WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
-    if (der != NULL && ssl != NULL) {
-        if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl,
-                                                        &idx, 0) == WOLFSSL_SUCCESS)
-            return WOLFSSL_SUCCESS;
-    }
-
-    (void)idx;
-    return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
-{
-    long idx;
-
-    WOLFSSL_ENTER("wolfSSL_use_certificate");
-    if (x509 != NULL && ssl != NULL && x509->derCert != NULL) {
-        if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
-                     WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == WOLFSSL_SUCCESS)
-            return WOLFSSL_SUCCESS;
-    }
-
-    (void)idx;
-    return WOLFSSL_FAILURE;
-}
-#endif /* NO_CERTS */
-
-#ifndef NO_FILESYSTEM
-
-int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
-{
-    WOLFSSL_ENTER("wolfSSL_use_certificate_file");
-    if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
-                    ssl, 0, NULL) == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
-{
-    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
-    if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
-                    ssl, 0, NULL) == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
-{
-   /* process up to MAX_CHAIN_DEPTH plus subject cert */
-   WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
-   if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
-                   ssl, 1, NULL) == WOLFSSL_SUCCESS)
-       return WOLFSSL_SUCCESS;
-
-   return WOLFSSL_FAILURE;
-}
-
-int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
-                                              int format)
-{
-   /* process up to MAX_CHAIN_DEPTH plus subject cert */
-   WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
-   if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
-                   NULL) == WOLFSSL_SUCCESS)
-       return WOLFSSL_SUCCESS;
-
-   return WOLFSSL_FAILURE;
-}
-
-
-#ifdef HAVE_ECC
-
-/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
-int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
-{
-    if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
-        return BAD_FUNC_ARG;
-
-    ctx->eccTempKeySz = sz;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
-int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
-{
-    if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
-        return BAD_FUNC_ARG;
-
-    ssl->eccTempKeySz = sz;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* HAVE_ECC */
-
-
-
-
-int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
-                                   int format)
-{
-    WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file");
-
-    return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
-}
-
-
-int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
-{
-    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
-
-    return wolfSSL_use_PrivateKey_file(ssl, file, format);
-}
-
-#endif /* NO_FILESYSTEM */
-
-/* Copies the master secret over to out buffer. If outSz is 0 returns the size
- * of master secret.
- *
- * ses : a session from completed TLS/SSL handshake
- * out : buffer to hold copy of master secret
- * outSz : size of out buffer
- * returns : number of bytes copied into out buffer on success
- *           less then or equal to 0 is considered a failure case
- */
-int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
-        unsigned char* out, int outSz)
-{
-    int size;
-
-    if (outSz == 0) {
-        return SECRET_LEN;
-    }
-
-    if (ses == NULL || out == NULL || outSz < 0) {
-        return 0;
-    }
-
-    if (outSz > SECRET_LEN) {
-        size = SECRET_LEN;
-    }
-    else {
-        size = outSz;
-    }
-
-    XMEMCPY(out, ses->masterSecret, size);
-    return size;
-}
-
-
-int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
-{
-    (void)ses;
-    return SECRET_LEN;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#ifndef NO_FILESYSTEM
-#ifdef HAVE_NTRU
-
-int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file");
-    if (ctx == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL)
-                         == WOLFSSL_SUCCESS) {
-        ctx->haveNTRU = 1;
-        return WOLFSSL_SUCCESS;
-    }
-
-    return WOLFSSL_FAILURE;
-}
-
-#endif /* HAVE_NTRU */
-
-
-#endif /* NO_FILESYSTEM */
-
-
-void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
-    if (mode & WOLFSSL_VERIFY_PEER) {
-        ctx->verifyPeer = 1;
-        ctx->verifyNone = 0;  /* in case previously set */
-    }
-
-    if (mode == WOLFSSL_VERIFY_NONE) {
-        ctx->verifyNone = 1;
-        ctx->verifyPeer = 0;  /* in case previously set */
-    }
-
-    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
-        ctx->failNoCert = 1;
-
-    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
-        ctx->failNoCert    = 0; /* fail on all is set to fail on PSK */
-        ctx->failNoCertxPSK = 1;
-    }
-
-    ctx->verifyCallback = vc;
-}
-
-
-void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
-{
-    WOLFSSL_ENTER("wolfSSL_set_verify");
-    if (mode & WOLFSSL_VERIFY_PEER) {
-        ssl->options.verifyPeer = 1;
-        ssl->options.verifyNone = 0;  /* in case previously set */
-    }
-
-    if (mode == WOLFSSL_VERIFY_NONE) {
-        ssl->options.verifyNone = 1;
-        ssl->options.verifyPeer = 0;  /* in case previously set */
-    }
-
-    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
-        ssl->options.failNoCert = 1;
-
-    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
-        ssl->options.failNoCert    = 0; /* fail on all is set to fail on PSK */
-        ssl->options.failNoCertxPSK = 1;
-    }
-
-    ssl->verifyCallback = vc;
-}
-
-
-/* store user ctx for verify callback */
-void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
-    if (ssl)
-        ssl->verifyCbCtx = ctx;
-}
-
-
-/* store context CA Cache addition callback */
-void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
-{
-    if (ctx && ctx->cm)
-        ctx->cm->caCacheCallback = cb;
-}
-
-
-#if defined(PERSIST_CERT_CACHE)
-
-#if !defined(NO_FILESYSTEM)
-
-/* Persist cert cache to file */
-int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
-
-    if (ctx == NULL || fname == NULL)
-        return BAD_FUNC_ARG;
-
-    return CM_SaveCertCache(ctx->cm, fname);
-}
-
-
-/* Persist cert cache from file */
-int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
-
-    if (ctx == NULL || fname == NULL)
-        return BAD_FUNC_ARG;
-
-    return CM_RestoreCertCache(ctx->cm, fname);
-}
-
-#endif /* NO_FILESYSTEM */
-
-/* Persist cert cache to memory */
-int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
-                                   int sz, int* used)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
-
-    if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
-        return BAD_FUNC_ARG;
-
-    return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
-}
-
-
-/* Restore cert cache from memory */
-int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
-
-    if (ctx == NULL || mem == NULL || sz <= 0)
-        return BAD_FUNC_ARG;
-
-    return CM_MemRestoreCertCache(ctx->cm, mem, sz);
-}
-
-
-/* get how big the the cert cache save buffer needs to be */
-int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    return CM_GetCertCacheMemSize(ctx->cm);
-}
-
-#endif /* PERSIST_CERT_CACHE */
-#endif /* !NO_CERTS */
-
-
-#ifndef NO_SESSION_CACHE
-
-WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_get_session");
-    if (ssl)
-        return GetSession(ssl, 0, 0);
-
-    return NULL;
-}
-
-
-int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
-{
-    WOLFSSL_ENTER("SSL_set_session");
-    if (session)
-        return SetSession(ssl, session);
-
-    return WOLFSSL_FAILURE;
-}
-
-
-#ifndef NO_CLIENT_CACHE
-
-/* Associate client session with serverID, find existing or store for saving
-   if newSession flag on, don't reuse existing session
-   WOLFSSL_SUCCESS on ok */
-int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
-{
-    WOLFSSL_SESSION* session = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_SetServerID");
-
-    if (ssl == NULL || id == NULL || len <= 0)
-        return BAD_FUNC_ARG;
-
-    if (newSession == 0) {
-        session = GetSessionClient(ssl, id, len);
-        if (session) {
-            if (SetSession(ssl, session) != WOLFSSL_SUCCESS) {
-    #ifdef HAVE_EXT_CACHE
-                wolfSSL_SESSION_free(session);
-    #endif
-                WOLFSSL_MSG("SetSession failed");
-                session = NULL;
-            }
-        }
-    }
-
-    if (session == NULL) {
-        WOLFSSL_MSG("Valid ServerID not cached already");
-
-        ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len);
-        XMEMCPY(ssl->session.serverID, id, ssl->session.idLen);
-    }
-    #ifdef HAVE_EXT_CACHE
-    else
-        wolfSSL_SESSION_free(session);
-    #endif
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_CLIENT_CACHE */
-
-#if defined(PERSIST_SESSION_CACHE)
-
-/* for persistence, if changes to layout need to increment and modify
-   save_session_cache() and restore_session_cache and memory versions too */
-#define WOLFSSL_CACHE_VERSION 2
-
-/* Session Cache Header information */
-typedef struct {
-    int version;     /* cache layout version id */
-    int rows;        /* session rows */
-    int columns;     /* session columns */
-    int sessionSz;   /* sizeof WOLFSSL_SESSION */
-} cache_header_t;
-
-/* current persistence layout is:
-
-   1) cache_header_t
-   2) SessionCache
-   3) ClientCache
-
-   update WOLFSSL_CACHE_VERSION if change layout for the following
-   PERSISTENT_SESSION_CACHE functions
-*/
-
-
-/* get how big the the session cache save buffer needs to be */
-int wolfSSL_get_session_cache_memsize(void)
-{
-    int sz  = (int)(sizeof(SessionCache) + sizeof(cache_header_t));
-
-    #ifndef NO_CLIENT_CACHE
-        sz += (int)(sizeof(ClientCache));
-    #endif
-
-    return sz;
-}
-
-
-/* Persist session cache to memory */
-int wolfSSL_memsave_session_cache(void* mem, int sz)
-{
-    int i;
-    cache_header_t cache_header;
-    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
-#ifndef NO_CLIENT_CACHE
-    ClientRow*     clRow;
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_memsave_session_cache");
-
-    if (sz < wolfSSL_get_session_cache_memsize()) {
-        WOLFSSL_MSG("Memory buffer too small");
-        return BUFFER_E;
-    }
-
-    cache_header.version   = WOLFSSL_CACHE_VERSION;
-    cache_header.rows      = SESSION_ROWS;
-    cache_header.columns   = SESSIONS_PER_ROW;
-    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
-    XMEMCPY(mem, &cache_header, sizeof(cache_header));
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        WOLFSSL_MSG("Session cache mutex lock failed");
-        return BAD_MUTEX_E;
-    }
-
-    for (i = 0; i < cache_header.rows; ++i)
-        XMEMCPY(row++, SessionCache + i, sizeof(SessionRow));
-
-#ifndef NO_CLIENT_CACHE
-    clRow = (ClientRow*)row;
-    for (i = 0; i < cache_header.rows; ++i)
-        XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow));
-#endif
-
-    wc_UnLockMutex(&session_mutex);
-
-    WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Restore the persistent session cache from memory */
-int wolfSSL_memrestore_session_cache(const void* mem, int sz)
-{
-    int    i;
-    cache_header_t cache_header;
-    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
-#ifndef NO_CLIENT_CACHE
-    ClientRow*     clRow;
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_memrestore_session_cache");
-
-    if (sz < wolfSSL_get_session_cache_memsize()) {
-        WOLFSSL_MSG("Memory buffer too small");
-        return BUFFER_E;
-    }
-
-    XMEMCPY(&cache_header, mem, sizeof(cache_header));
-    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
-        cache_header.rows      != SESSION_ROWS ||
-        cache_header.columns   != SESSIONS_PER_ROW ||
-        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
-
-        WOLFSSL_MSG("Session cache header match failed");
-        return CACHE_MATCH_ERROR;
-    }
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        WOLFSSL_MSG("Session cache mutex lock failed");
-        return BAD_MUTEX_E;
-    }
-
-    for (i = 0; i < cache_header.rows; ++i)
-        XMEMCPY(SessionCache + i, row++, sizeof(SessionRow));
-
-#ifndef NO_CLIENT_CACHE
-    clRow = (ClientRow*)row;
-    for (i = 0; i < cache_header.rows; ++i)
-        XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow));
-#endif
-
-    wc_UnLockMutex(&session_mutex);
-
-    WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
-
-    return WOLFSSL_SUCCESS;
-}
-
-#if !defined(NO_FILESYSTEM)
-
-/* Persist session cache to file */
-/* doesn't use memsave because of additional memory use */
-int wolfSSL_save_session_cache(const char *fname)
-{
-    XFILE  file;
-    int    ret;
-    int    rc = WOLFSSL_SUCCESS;
-    int    i;
-    cache_header_t cache_header;
-
-    WOLFSSL_ENTER("wolfSSL_save_session_cache");
-
-    file = XFOPEN(fname, "w+b");
-    if (file == XBADFILE) {
-        WOLFSSL_MSG("Couldn't open session cache save file");
-        return WOLFSSL_BAD_FILE;
-    }
-    cache_header.version   = WOLFSSL_CACHE_VERSION;
-    cache_header.rows      = SESSION_ROWS;
-    cache_header.columns   = SESSIONS_PER_ROW;
-    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
-
-    /* cache header */
-    ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file);
-    if (ret != 1) {
-        WOLFSSL_MSG("Session cache header file write failed");
-        XFCLOSE(file);
-        return FWRITE_ERROR;
-    }
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        WOLFSSL_MSG("Session cache mutex lock failed");
-        XFCLOSE(file);
-        return BAD_MUTEX_E;
-    }
-
-    /* session cache */
-    for (i = 0; i < cache_header.rows; ++i) {
-        ret = (int)XFWRITE(SessionCache + i, sizeof(SessionRow), 1, file);
-        if (ret != 1) {
-            WOLFSSL_MSG("Session cache member file write failed");
-            rc = FWRITE_ERROR;
-            break;
-        }
-    }
-
-#ifndef NO_CLIENT_CACHE
-    /* client cache */
-    for (i = 0; i < cache_header.rows; ++i) {
-        ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file);
-        if (ret != 1) {
-            WOLFSSL_MSG("Client cache member file write failed");
-            rc = FWRITE_ERROR;
-            break;
-        }
-    }
-#endif /* NO_CLIENT_CACHE */
-
-    wc_UnLockMutex(&session_mutex);
-
-    XFCLOSE(file);
-    WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
-
-    return rc;
-}
-
-
-/* Restore the persistent session cache from file */
-/* doesn't use memstore because of additional memory use */
-int wolfSSL_restore_session_cache(const char *fname)
-{
-    XFILE  file;
-    int    rc = WOLFSSL_SUCCESS;
-    int    ret;
-    int    i;
-    cache_header_t cache_header;
-
-    WOLFSSL_ENTER("wolfSSL_restore_session_cache");
-
-    file = XFOPEN(fname, "rb");
-    if (file == XBADFILE) {
-        WOLFSSL_MSG("Couldn't open session cache save file");
-        return WOLFSSL_BAD_FILE;
-    }
-    /* cache header */
-    ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file);
-    if (ret != 1) {
-        WOLFSSL_MSG("Session cache header file read failed");
-        XFCLOSE(file);
-        return FREAD_ERROR;
-    }
-    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
-        cache_header.rows      != SESSION_ROWS ||
-        cache_header.columns   != SESSIONS_PER_ROW ||
-        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
-
-        WOLFSSL_MSG("Session cache header match failed");
-        XFCLOSE(file);
-        return CACHE_MATCH_ERROR;
-    }
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        WOLFSSL_MSG("Session cache mutex lock failed");
-        XFCLOSE(file);
-        return BAD_MUTEX_E;
-    }
-
-    /* session cache */
-    for (i = 0; i < cache_header.rows; ++i) {
-        ret = (int)XFREAD(SessionCache + i, sizeof(SessionRow), 1, file);
-        if (ret != 1) {
-            WOLFSSL_MSG("Session cache member file read failed");
-            XMEMSET(SessionCache, 0, sizeof SessionCache);
-            rc = FREAD_ERROR;
-            break;
-        }
-    }
-
-#ifndef NO_CLIENT_CACHE
-    /* client cache */
-    for (i = 0; i < cache_header.rows; ++i) {
-        ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file);
-        if (ret != 1) {
-            WOLFSSL_MSG("Client cache member file read failed");
-            XMEMSET(ClientCache, 0, sizeof ClientCache);
-            rc = FREAD_ERROR;
-            break;
-        }
-    }
-
-#endif /* NO_CLIENT_CACHE */
-
-    wc_UnLockMutex(&session_mutex);
-
-    XFCLOSE(file);
-    WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
-
-    return rc;
-}
-
-#endif /* !NO_FILESYSTEM */
-#endif /* PERSIST_SESSION_CACHE */
-#endif /* NO_SESSION_CACHE */
-
-
-void wolfSSL_load_error_strings(void)   /* compatibility only */
-{}
-
-
-int wolfSSL_library_init(void)
-{
-    WOLFSSL_ENTER("SSL_library_init");
-    if (wolfSSL_Init() == WOLFSSL_SUCCESS)
-        return WOLFSSL_SUCCESS;
-    else
-        return WOLFSSL_FATAL_ERROR;
-}
-
-
-#ifdef HAVE_SECRET_CALLBACK
-
-int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_set_session_secret_cb");
-    if (ssl == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    ssl->sessionSecretCb = cb;
-    ssl->sessionSecretCtx = ctx;
-    /* If using a pre-set key, assume session resumption. */
-    ssl->session.sessionIDSz = 0;
-    ssl->options.resuming = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif
-
-
-#ifndef NO_SESSION_CACHE
-
-/* on by default if built in but allow user to turn off */
-long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
-{
-    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
-    if (mode == WOLFSSL_SESS_CACHE_OFF)
-        ctx->sessionCacheOff = 1;
-
-    if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
-        ctx->sessionCacheFlushOff = 1;
-
-#ifdef HAVE_EXT_CACHE
-    if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
-        ctx->internalCacheOff = 1;
-#endif
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_SESSION_CACHE */
-
-
-#if !defined(NO_CERTS)
-#if defined(PERSIST_CERT_CACHE)
-
-
-#define WOLFSSL_CACHE_CERT_VERSION 1
-
-typedef struct {
-    int version;                 /* cache cert layout version id */
-    int rows;                    /* hash table rows, CA_TABLE_SIZE */
-    int columns[CA_TABLE_SIZE];  /* columns per row on list */
-    int signerSz;                /* sizeof Signer object */
-} CertCacheHeader;
-
-/* current cert persistence layout is:
-
-   1) CertCacheHeader
-   2) caTable
-
-   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
-   PERSIST_CERT_CACHE functions
-*/
-
-
-/* Return memory needed to persist this signer, have lock */
-static WC_INLINE int GetSignerMemory(Signer* signer)
-{
-    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
-           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
-
-#if !defined(NO_SKID)
-        sz += (int)sizeof(signer->subjectKeyIdHash);
-#endif
-
-    /* add dynamic bytes needed */
-    sz += signer->pubKeySize;
-    sz += signer->nameLen;
-
-    return sz;
-}
-
-
-/* Return memory needed to persist this row, have lock */
-static WC_INLINE int GetCertCacheRowMemory(Signer* row)
-{
-    int sz = 0;
-
-    while (row) {
-        sz += GetSignerMemory(row);
-        row = row->next;
-    }
-
-    return sz;
-}
-
-
-/* get the size of persist cert cache, have lock */
-static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
-{
-    int sz;
-    int i;
-
-    sz = sizeof(CertCacheHeader);
-
-    for (i = 0; i < CA_TABLE_SIZE; i++)
-        sz += GetCertCacheRowMemory(cm->caTable[i]);
-
-    return sz;
-}
-
-
-/* Store cert cache header columns with number of items per list, have lock */
-static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
-{
-    int     i;
-    Signer* row;
-
-    for (i = 0; i < CA_TABLE_SIZE; i++) {
-        int count = 0;
-        row = cm->caTable[i];
-
-        while (row) {
-            ++count;
-            row = row->next;
-        }
-        columns[i] = count;
-    }
-}
-
-
-/* Restore whole cert row from memory, have lock, return bytes consumed,
-   < 0 on error, have lock */
-static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
-                                 int row, int listSz, const byte* end)
-{
-    int idx = 0;
-
-    if (listSz < 0) {
-        WOLFSSL_MSG("Row header corrupted, negative value");
-        return PARSE_ERROR;
-    }
-
-    while (listSz) {
-        Signer* signer;
-        byte*   start = current + idx;  /* for end checks on this signer */
-        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
-                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
-        #ifndef NO_SKID
-                minSz += (int)sizeof(signer->subjectKeyIdHash);
-        #endif
-
-        if (start + minSz > end) {
-            WOLFSSL_MSG("Would overread restore buffer");
-            return BUFFER_E;
-        }
-        signer = MakeSigner(cm->heap);
-        if (signer == NULL)
-            return MEMORY_E;
-
-        /* pubKeySize */
-        XMEMCPY(&signer->pubKeySize, current + idx, sizeof(signer->pubKeySize));
-        idx += (int)sizeof(signer->pubKeySize);
-
-        /* keyOID */
-        XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
-        idx += (int)sizeof(signer->keyOID);
-
-        /* pulicKey */
-        if (start + minSz + signer->pubKeySize > end) {
-            WOLFSSL_MSG("Would overread restore buffer");
-            FreeSigner(signer, cm->heap);
-            return BUFFER_E;
-        }
-        signer->publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
-                                           DYNAMIC_TYPE_KEY);
-        if (signer->publicKey == NULL) {
-            FreeSigner(signer, cm->heap);
-            return MEMORY_E;
-        }
-
-        XMEMCPY(signer->publicKey, current + idx, signer->pubKeySize);
-        idx += signer->pubKeySize;
-
-        /* nameLen */
-        XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
-        idx += (int)sizeof(signer->nameLen);
-
-        /* name */
-        if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
-            WOLFSSL_MSG("Would overread restore buffer");
-            FreeSigner(signer, cm->heap);
-            return BUFFER_E;
-        }
-        signer->name = (char*)XMALLOC(signer->nameLen, cm->heap,
-                                      DYNAMIC_TYPE_SUBJECT_CN);
-        if (signer->name == NULL) {
-            FreeSigner(signer, cm->heap);
-            return MEMORY_E;
-        }
-
-        XMEMCPY(signer->name, current + idx, signer->nameLen);
-        idx += signer->nameLen;
-
-        /* subjectNameHash */
-        XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
-        idx += SIGNER_DIGEST_SIZE;
-
-        #ifndef NO_SKID
-            /* subjectKeyIdHash */
-            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
-            idx += SIGNER_DIGEST_SIZE;
-        #endif
-
-        signer->next = cm->caTable[row];
-        cm->caTable[row] = signer;
-
-        --listSz;
-    }
-
-    return idx;
-}
-
-
-/* Store whole cert row into memory, have lock, return bytes added */
-static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
-{
-    int     added  = 0;
-    Signer* list   = cm->caTable[row];
-
-    while (list) {
-        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
-        added += (int)sizeof(list->pubKeySize);
-
-        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
-        added += (int)sizeof(list->keyOID);
-
-        XMEMCPY(current + added, list->publicKey, list->pubKeySize);
-        added += list->pubKeySize;
-
-        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
-        added += (int)sizeof(list->nameLen);
-
-        XMEMCPY(current + added, list->name, list->nameLen);
-        added += list->nameLen;
-
-        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
-        added += SIGNER_DIGEST_SIZE;
-
-        #ifndef NO_SKID
-            XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
-            added += SIGNER_DIGEST_SIZE;
-        #endif
-
-        list = list->next;
-    }
-
-    return added;
-}
-
-
-/* Persist cert cache to memory, have lock */
-static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm,
-                                     void* mem, int sz)
-{
-    int realSz;
-    int ret = WOLFSSL_SUCCESS;
-    int i;
-
-    WOLFSSL_ENTER("DoMemSaveCertCache");
-
-    realSz = GetCertCacheMemSize(cm);
-    if (realSz > sz) {
-        WOLFSSL_MSG("Mem output buffer too small");
-        ret = BUFFER_E;
-    }
-    else {
-        byte*           current;
-        CertCacheHeader hdr;
-
-        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
-        hdr.rows     = CA_TABLE_SIZE;
-        SetCertHeaderColumns(cm, hdr.columns);
-        hdr.signerSz = (int)sizeof(Signer);
-
-        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
-        current = (byte*)mem + sizeof(CertCacheHeader);
-
-        for (i = 0; i < CA_TABLE_SIZE; ++i)
-            current += StoreCertRow(cm, current, i);
-    }
-
-    return ret;
-}
-
-
-#if !defined(NO_FILESYSTEM)
-
-/* Persist cert cache to file */
-int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
-{
-    XFILE file;
-    int   rc = WOLFSSL_SUCCESS;
-    int   memSz;
-    byte* mem;
-
-    WOLFSSL_ENTER("CM_SaveCertCache");
-
-    file = XFOPEN(fname, "w+b");
-    if (file == XBADFILE) {
-       WOLFSSL_MSG("Couldn't open cert cache save file");
-       return WOLFSSL_BAD_FILE;
-    }
-
-    if (wc_LockMutex(&cm->caLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex on caLock failed");
-        XFCLOSE(file);
-        return BAD_MUTEX_E;
-    }
-
-    memSz = GetCertCacheMemSize(cm);
-    mem   = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (mem == NULL) {
-        WOLFSSL_MSG("Alloc for tmp buffer failed");
-        rc = MEMORY_E;
-    } else {
-        rc = DoMemSaveCertCache(cm, mem, memSz);
-        if (rc == WOLFSSL_SUCCESS) {
-            int ret = (int)XFWRITE(mem, memSz, 1, file);
-            if (ret != 1) {
-                WOLFSSL_MSG("Cert cache file write failed");
-                rc = FWRITE_ERROR;
-            }
-        }
-        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    wc_UnLockMutex(&cm->caLock);
-    XFCLOSE(file);
-
-    return rc;
-}
-
-
-/* Restore cert cache from file */
-int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
-{
-    XFILE file;
-    int   rc = WOLFSSL_SUCCESS;
-    int   ret;
-    int   memSz;
-    byte* mem;
-
-    WOLFSSL_ENTER("CM_RestoreCertCache");
-
-    file = XFOPEN(fname, "rb");
-    if (file == XBADFILE) {
-       WOLFSSL_MSG("Couldn't open cert cache save file");
-       return WOLFSSL_BAD_FILE;
-    }
-
-    XFSEEK(file, 0, XSEEK_END);
-    memSz = (int)XFTELL(file);
-    XREWIND(file);
-
-    if (memSz <= 0) {
-        WOLFSSL_MSG("Bad file size");
-        XFCLOSE(file);
-        return WOLFSSL_BAD_FILE;
-    }
-
-    mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (mem == NULL) {
-        WOLFSSL_MSG("Alloc for tmp buffer failed");
-        XFCLOSE(file);
-        return MEMORY_E;
-    }
-
-    ret = (int)XFREAD(mem, memSz, 1, file);
-    if (ret != 1) {
-        WOLFSSL_MSG("Cert file read error");
-        rc = FREAD_ERROR;
-    } else {
-        rc = CM_MemRestoreCertCache(cm, mem, memSz);
-        if (rc != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("Mem restore cert cache failed");
-        }
-    }
-
-    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFCLOSE(file);
-
-    return rc;
-}
-
-#endif /* NO_FILESYSTEM */
-
-
-/* Persist cert cache to memory */
-int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("CM_MemSaveCertCache");
-
-    if (wc_LockMutex(&cm->caLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex on caLock failed");
-        return BAD_MUTEX_E;
-    }
-
-    ret = DoMemSaveCertCache(cm, mem, sz);
-    if (ret == WOLFSSL_SUCCESS)
-        *used  = GetCertCacheMemSize(cm);
-
-    wc_UnLockMutex(&cm->caLock);
-
-    return ret;
-}
-
-
-/* Restore cert cache from memory */
-int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
-{
-    int ret = WOLFSSL_SUCCESS;
-    int i;
-    CertCacheHeader* hdr = (CertCacheHeader*)mem;
-    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
-    byte*            end     = (byte*)mem + sz;  /* don't go over */
-
-    WOLFSSL_ENTER("CM_MemRestoreCertCache");
-
-    if (current > end) {
-        WOLFSSL_MSG("Cert Cache Memory buffer too small");
-        return BUFFER_E;
-    }
-
-    if (hdr->version  != WOLFSSL_CACHE_CERT_VERSION ||
-        hdr->rows     != CA_TABLE_SIZE ||
-        hdr->signerSz != (int)sizeof(Signer)) {
-
-        WOLFSSL_MSG("Cert Cache Memory header mismatch");
-        return CACHE_MATCH_ERROR;
-    }
-
-    if (wc_LockMutex(&cm->caLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex on caLock failed");
-        return BAD_MUTEX_E;
-    }
-
-    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
-
-    for (i = 0; i < CA_TABLE_SIZE; ++i) {
-        int added = RestoreCertRow(cm, current, i, hdr->columns[i], end);
-        if (added < 0) {
-            WOLFSSL_MSG("RestoreCertRow error");
-            ret = added;
-            break;
-        }
-        current += added;
-    }
-
-    wc_UnLockMutex(&cm->caLock);
-
-    return ret;
-}
-
-
-/* get how big the the cert cache save buffer needs to be */
-int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
-{
-    int sz;
-
-    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
-
-    if (wc_LockMutex(&cm->caLock) != 0) {
-        WOLFSSL_MSG("wc_LockMutex on caLock failed");
-        return BAD_MUTEX_E;
-    }
-
-    sz = GetCertCacheMemSize(cm);
-
-    wc_UnLockMutex(&cm->caLock);
-
-    return sz;
-}
-
-#endif /* PERSIST_CERT_CACHE */
-#endif /* NO_CERTS */
-
-
-int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
-
-    /* alloc/init on demand only */
-    if (ctx->suites == NULL) {
-        ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
-                                       DYNAMIC_TYPE_SUITES);
-        if (ctx->suites == NULL) {
-            WOLFSSL_MSG("Memory alloc for Suites failed");
-            return WOLFSSL_FAILURE;
-        }
-        XMEMSET(ctx->suites, 0, sizeof(Suites));
-    }
-
-    return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
-{
-    WOLFSSL_ENTER("wolfSSL_set_cipher_list");
-    return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
-{
-    int useNb = 0;
-
-    WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
-    if (ssl->options.dtls) {
-#ifdef WOLFSSL_DTLS
-        useNb = ssl->options.dtlsUseNonblock;
-#endif
-    }
-    else {
-        WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
-                    "DEPRECATED for non-DTLS use.");
-    }
-    return useNb;
-}
-
-
-#ifndef WOLFSSL_LEANPSK
-
-void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
-{
-    (void)nonblock;
-
-    WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
-    if (ssl->options.dtls) {
-#ifdef WOLFSSL_DTLS
-        ssl->options.dtlsUseNonblock = (nonblock != 0);
-#endif
-    }
-    else {
-        WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
-                    "DEPRECATED for non-DTLS use.");
-    }
-}
-
-
-#ifdef WOLFSSL_DTLS
-
-int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
-{
-    return ssl->dtls_timeout;
-}
-
-
-/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */
-int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
-{
-    if (ssl == NULL || timeout < 0)
-        return BAD_FUNC_ARG;
-
-    if (timeout > ssl->dtls_timeout_max) {
-        WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max");
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->dtls_timeout_init = timeout;
-    ssl->dtls_timeout = timeout;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
-int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
-{
-    if (ssl == NULL || timeout < 0)
-        return BAD_FUNC_ARG;
-
-    if (timeout < ssl->dtls_timeout_init) {
-        WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
-        return BAD_FUNC_ARG;
-    }
-
-    ssl->dtls_timeout_max = timeout;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
-{
-    int result = WOLFSSL_SUCCESS;
-
-    if (!ssl->options.handShakeDone &&
-        (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) {
-
-        result = WOLFSSL_FATAL_ERROR;
-    }
-    return result;
-}
-
-#endif /* DTLS */
-#endif /* LEANPSK */
-
-
-#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
-
-/* Not an SSL function, return 0 for success, error code otherwise */
-/* Prereq: ssl's RNG needs to be initialized. */
-int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
-                                 const byte* secret, word32 secretSz)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
-
-    if (ssl == NULL) {
-        WOLFSSL_MSG("need a SSL object");
-        return BAD_FUNC_ARG;
-    }
-
-    if (secret != NULL && secretSz == 0) {
-        WOLFSSL_MSG("can't have a new secret without a size");
-        return BAD_FUNC_ARG;
-    }
-
-    /* If secretSz is 0, use the default size. */
-    if (secretSz == 0)
-        secretSz = COOKIE_SECRET_SZ;
-
-    if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
-        byte* newSecret;
-
-        if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
-            ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
-                      ssl->buffers.dtlsCookieSecret.length);
-            XFREE(ssl->buffers.dtlsCookieSecret.buffer,
-                  ssl->heap, DYNAMIC_TYPE_NONE);
-        }
-
-        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
-        if (newSecret == NULL) {
-            ssl->buffers.dtlsCookieSecret.buffer = NULL;
-            ssl->buffers.dtlsCookieSecret.length = 0;
-            WOLFSSL_MSG("couldn't allocate new cookie secret");
-            return MEMORY_ERROR;
-        }
-        ssl->buffers.dtlsCookieSecret.buffer = newSecret;
-        ssl->buffers.dtlsCookieSecret.length = secretSz;
-    }
-
-    /* If the supplied secret is NULL, randomly generate a new secret. */
-    if (secret == NULL) {
-        ret = wc_RNG_GenerateBlock(ssl->rng,
-                             ssl->buffers.dtlsCookieSecret.buffer, secretSz);
-    }
-    else
-        XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
-
-    WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
-    return ret;
-}
-
-#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
-
-#ifdef OPENSSL_EXTRA
-    WOLFSSL_METHOD* wolfSSLv23_method(void) {
-        WOLFSSL_METHOD* m = NULL;
-        WOLFSSL_ENTER("wolfSSLv23_method");
-#if !defined(NO_WOLFSSL_CLIENT)
-        m = wolfSSLv23_client_method();
-#elif !defined(NO_WOLFSSL_SERVER)
-        m = wolfSSLv23_server_method();
-#endif
-        if (m != NULL) {
-            m->side = WOLFSSL_NEITHER_END;
-        }
-
-        return m;
-    }
-#endif /* OPENSSL_EXTRA */
-
-/* client only parts */
-#ifndef NO_WOLFSSL_CLIENT
-
-    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-    WOLFSSL_METHOD* wolfSSLv3_client_method(void)
-    {
-        WOLFSSL_ENTER("SSLv3_client_method");
-        return wolfSSLv3_client_method_ex(NULL);
-    }
-    #endif
-
-    #ifdef WOLFSSL_DTLS
-
-        #ifndef NO_OLD_TLS
-        WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
-        {
-            WOLFSSL_ENTER("DTLSv1_client_method");
-            return wolfDTLSv1_client_method_ex(NULL);
-        }
-        #endif  /* NO_OLD_TLS */
-
-        WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
-        {
-            WOLFSSL_ENTER("DTLSv1_2_client_method");
-            return wolfDTLSv1_2_client_method_ex(NULL);
-        }
-    #endif
-
-    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-    WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
-    {
-        WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-        WOLFSSL_ENTER("SSLv3_client_method_ex");
-        if (method)
-            InitSSL_Method(method, MakeSSLv3());
-        return method;
-    }
-    #endif
-
-    #ifdef WOLFSSL_DTLS
-
-        #ifndef NO_OLD_TLS
-        WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap)
-        {
-            WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-            WOLFSSL_ENTER("DTLSv1_client_method_ex");
-            if (method)
-                InitSSL_Method(method, MakeDTLSv1());
-            return method;
-        }
-        #endif  /* NO_OLD_TLS */
-
-        WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap)
-        {
-            WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-            WOLFSSL_ENTER("DTLSv1_2_client_method_ex");
-            if (method)
-                InitSSL_Method(method, MakeDTLSv1_2());
-            (void)heap;
-            return method;
-        }
-    #endif
-
-    /* If SCTP is not enabled returns the state of the dtls option.
-     * If SCTP is enabled returns dtls && !sctp. */
-    static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
-    {
-        int result = ssl->options.dtls;
-
-        if (result) {
-        #ifdef WOLFSSL_SCTP
-            result = !ssl->options.dtlsSctp;
-        #endif
-        }
-
-        return result;
-    }
-
-
-    /* please see note at top of README if you get an error from connect */
-    int wolfSSL_connect(WOLFSSL* ssl)
-    {
-    #ifndef WOLFSSL_NO_TLS12
-        int neededState;
-    #endif
-
-        WOLFSSL_ENTER("SSL_connect()");
-
-        #ifdef HAVE_ERRNO_H
-            errno = 0;
-        #endif
-
-        if (ssl == NULL)
-            return BAD_FUNC_ARG;
-
-        #ifdef OPENSSL_EXTRA
-            if (ssl->CBIS != NULL) {
-                ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS);
-                ssl->cbmode = SSL_CB_WRITE;
-            }
-        #endif
-        if (ssl->options.side != WOLFSSL_CLIENT_END) {
-            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-    #ifdef WOLFSSL_NO_TLS12
-        return wolfSSL_connect_TLSv13(ssl);
-    #else
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3)
-                return wolfSSL_connect_TLSv13(ssl);
-        #endif
-
-        #ifdef WOLFSSL_DTLS
-            if (ssl->version.major == DTLS_MAJOR) {
-                ssl->options.dtls   = 1;
-                ssl->options.tls    = 1;
-                ssl->options.tls1_1 = 1;
-            }
-        #endif
-
-        if (ssl->buffers.outputBuffer.length > 0) {
-            if ( (ssl->error = SendBuffered(ssl)) == 0) {
-                /* fragOffset is non-zero when sending fragments. On the last
-                 * fragment, fragOffset is zero again, and the state can be
-                 * advanced. */
-                if (ssl->fragOffset == 0) {
-                    ssl->options.connectState++;
-                    WOLFSSL_MSG("connect state: "
-                                "Advanced from last buffered fragment send");
-                }
-                else {
-                    WOLFSSL_MSG("connect state: "
-                                "Not advanced, more fragments to send");
-                }
-            }
-            else {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-        }
-
-#ifdef WOLFSSL_TLS13
-        if (ssl->options.tls1_3)
-            return wolfSSL_connect_TLSv13(ssl);
-#endif
-
-        switch (ssl->options.connectState) {
-
-        case CONNECT_BEGIN :
-            /* always send client hello first */
-            if ( (ssl->error = SendClientHello(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.connectState = CLIENT_HELLO_SENT;
-            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
-            FALL_THROUGH;
-
-        case CLIENT_HELLO_SENT :
-            neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
-                                          SERVER_HELLODONE_COMPLETE;
-            #ifdef WOLFSSL_DTLS
-                /* In DTLS, when resuming, we can go straight to FINISHED,
-                 * or do a cookie exchange and then skip to FINISHED, assume
-                 * we need the cookie exchange first. */
-                if (IsDtlsNotSctpMode(ssl))
-                    neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
-            #endif
-            /* get response */
-            while (ssl->options.serverState < neededState) {
-                #ifdef WOLFSSL_TLS13
-                    if (ssl->options.tls1_3)
-                        return wolfSSL_connect_TLSv13(ssl);
-                #endif
-                if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                /* if resumption failed, reset needed state */
-                else if (neededState == SERVER_FINISHED_COMPLETE)
-                    if (!ssl->options.resuming) {
-                        if (!IsDtlsNotSctpMode(ssl))
-                            neededState = SERVER_HELLODONE_COMPLETE;
-                        else
-                            neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
-                    }
-            }
-
-            ssl->options.connectState = HELLO_AGAIN;
-            WOLFSSL_MSG("connect state: HELLO_AGAIN");
-            FALL_THROUGH;
-
-        case HELLO_AGAIN :
-            if (ssl->options.certOnly)
-                return WOLFSSL_SUCCESS;
-
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3)
-                return wolfSSL_connect_TLSv13(ssl);
-        #endif
-
-            #ifdef WOLFSSL_DTLS
-                if (IsDtlsNotSctpMode(ssl)) {
-                    /* re-init hashes, exclude first hello and verify request */
-                    if ((ssl->error = InitHandshakeHashes(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                    if ( (ssl->error = SendClientHello(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                }
-            #endif
-
-            ssl->options.connectState = HELLO_AGAIN_REPLY;
-            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
-            FALL_THROUGH;
-
-        case HELLO_AGAIN_REPLY :
-            #ifdef WOLFSSL_DTLS
-                if (IsDtlsNotSctpMode(ssl)) {
-                    neededState = ssl->options.resuming ?
-                           SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
-
-                    /* get response */
-                    while (ssl->options.serverState < neededState) {
-                        if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                            WOLFSSL_ERROR(ssl->error);
-                            return WOLFSSL_FATAL_ERROR;
-                        }
-                        /* if resumption failed, reset needed state */
-                        if (neededState == SERVER_FINISHED_COMPLETE) {
-                            if (!ssl->options.resuming)
-                                neededState = SERVER_HELLODONE_COMPLETE;
-                        }
-                    }
-                }
-            #endif
-
-            ssl->options.connectState = FIRST_REPLY_DONE;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_DONE :
-            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
-                #ifdef WOLFSSL_TLS13
-                    if (ssl->options.tls1_3)
-                        return wolfSSL_connect_TLSv13(ssl);
-                #endif
-                if (ssl->options.sendVerify) {
-                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                    WOLFSSL_MSG("sent: certificate");
-                }
-
-            #endif
-            ssl->options.connectState = FIRST_REPLY_FIRST;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_FIRST :
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3)
-                return wolfSSL_connect_TLSv13(ssl);
-        #endif
-            if (!ssl->options.resuming) {
-                if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                WOLFSSL_MSG("sent: client key exchange");
-            }
-
-            ssl->options.connectState = FIRST_REPLY_SECOND;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_SECOND :
-            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
-                if (ssl->options.sendVerify) {
-                    if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                    WOLFSSL_MSG("sent: certificate verify");
-                }
-            #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
-            ssl->options.connectState = FIRST_REPLY_THIRD;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_THIRD :
-            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            WOLFSSL_MSG("sent: change cipher spec");
-            ssl->options.connectState = FIRST_REPLY_FOURTH;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_FOURTH :
-            if ( (ssl->error = SendFinished(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            WOLFSSL_MSG("sent: finished");
-            ssl->options.connectState = FINISHED_DONE;
-            WOLFSSL_MSG("connect state: FINISHED_DONE");
-            FALL_THROUGH;
-
-        case FINISHED_DONE :
-            /* get response */
-            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
-                if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-
-            ssl->options.connectState = SECOND_REPLY_DONE;
-            WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
-            FALL_THROUGH;
-
-        case SECOND_REPLY_DONE:
-#ifndef NO_HANDSHAKE_DONE_CB
-            if (ssl->hsDoneCb) {
-                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
-                if (cbret < 0) {
-                    ssl->error = cbret;
-                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif /* NO_HANDSHAKE_DONE_CB */
-
-            if (!ssl->options.dtls) {
-                if (!ssl->options.keepResources) {
-                    FreeHandshakeResources(ssl);
-                }
-            }
-#ifdef WOLFSSL_DTLS
-            else {
-                ssl->options.dtlsHsRetain = 1;
-            }
-#endif /* WOLFSSL_DTLS */
-
-            WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
-            return WOLFSSL_SUCCESS;
-
-        default:
-            WOLFSSL_MSG("Unknown connect state ERROR");
-            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
-        }
-    #endif /* !WOLFSSL_NO_TLS12 */
-    }
-
-#endif /* NO_WOLFSSL_CLIENT */
-
-
-/* server only parts */
-#ifndef NO_WOLFSSL_SERVER
-
-    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-    WOLFSSL_METHOD* wolfSSLv3_server_method(void)
-    {
-        WOLFSSL_ENTER("SSLv3_server_method");
-        return wolfSSLv3_server_method_ex(NULL);
-    }
-    #endif
-
-
-    #ifdef WOLFSSL_DTLS
-
-        #ifndef NO_OLD_TLS
-        WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
-        {
-            WOLFSSL_ENTER("DTLSv1_server_method");
-            return wolfDTLSv1_server_method_ex(NULL);
-        }
-        #endif /* NO_OLD_TLS */
-
-        WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
-        {
-            WOLFSSL_ENTER("DTLSv1_2_server_method");
-            return wolfDTLSv1_2_server_method_ex(NULL);
-        }
-    #endif
-
-    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
-    WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
-    {
-        WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-        WOLFSSL_ENTER("SSLv3_server_method_ex");
-        if (method) {
-            InitSSL_Method(method, MakeSSLv3());
-            method->side = WOLFSSL_SERVER_END;
-        }
-        return method;
-    }
-    #endif
-
-
-    #ifdef WOLFSSL_DTLS
-
-        #ifndef NO_OLD_TLS
-        WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap)
-        {
-            WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-            WOLFSSL_ENTER("DTLSv1_server_method_ex");
-            if (method) {
-                InitSSL_Method(method, MakeDTLSv1());
-                method->side = WOLFSSL_SERVER_END;
-            }
-            return method;
-        }
-        #endif /* NO_OLD_TLS */
-
-        WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap)
-        {
-            WOLFSSL_METHOD* method =
-                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
-                                                     heap, DYNAMIC_TYPE_METHOD);
-            WOLFSSL_ENTER("DTLSv1_2_server_method_ex");
-            if (method) {
-                InitSSL_Method(method, MakeDTLSv1_2());
-                method->side = WOLFSSL_SERVER_END;
-            }
-            (void)heap;
-            return method;
-        }
-    #endif
-
-
-    int wolfSSL_accept(WOLFSSL* ssl)
-    {
-#ifndef WOLFSSL_NO_TLS12
-        word16 havePSK = 0;
-        word16 haveAnon = 0;
-        word16 haveMcast = 0;
-#endif
-
-#ifdef WOLFSSL_NO_TLS12
-        return wolfSSL_accept_TLSv13(ssl);
-#else
-    #ifdef WOLFSSL_TLS13
-        if (ssl->options.tls1_3)
-            return wolfSSL_accept_TLSv13(ssl);
-    #endif
-        WOLFSSL_ENTER("SSL_accept()");
-
-        #ifdef HAVE_ERRNO_H
-            errno = 0;
-        #endif
-
-        #ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-        #endif
-        (void)havePSK;
-
-        #ifdef HAVE_ANON
-            haveAnon = ssl->options.haveAnon;
-        #endif
-        (void)haveAnon;
-
-        #ifdef WOLFSSL_MULTICAST
-            haveMcast = ssl->options.haveMcast;
-        #endif
-        (void)haveMcast;
-
-        if (ssl->options.side != WOLFSSL_SERVER_END) {
-            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-    #ifndef NO_CERTS
-        /* in case used set_accept_state after init */
-        /* allow no private key if using PK callbacks and CB is set */
-        if (!havePSK && !haveAnon && !haveMcast) {
-            if (!ssl->buffers.certificate ||
-                !ssl->buffers.certificate->buffer) {
-
-                WOLFSSL_MSG("accept error: server cert required");
-                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
-                return WOLFSSL_FATAL_ERROR;
-            }
-
-        #ifdef HAVE_PK_CALLBACKS
-            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
-                WOLFSSL_MSG("Using PK for server private key");
-            }
-            else
-        #endif
-            if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
-                WOLFSSL_MSG("accept error: server key required");
-                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
-                return WOLFSSL_FATAL_ERROR;
-            }
-        }
-    #endif
-
-    #ifdef WOLFSSL_DTLS
-        if (ssl->version.major == DTLS_MAJOR) {
-            ssl->options.dtls   = 1;
-            ssl->options.tls    = 1;
-            ssl->options.tls1_1 = 1;
-        }
-    #endif
-
-        if (ssl->buffers.outputBuffer.length > 0) {
-            if ( (ssl->error = SendBuffered(ssl)) == 0) {
-                /* fragOffset is non-zero when sending fragments. On the last
-                 * fragment, fragOffset is zero again, and the state can be
-                 * advanced. */
-                if (ssl->fragOffset == 0) {
-                    ssl->options.acceptState++;
-                    WOLFSSL_MSG("accept state: "
-                                "Advanced from last buffered fragment send");
-                }
-                else {
-                    WOLFSSL_MSG("accept state: "
-                                "Not advanced, more fragments to send");
-                }
-            }
-            else {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-        }
-
-        switch (ssl->options.acceptState) {
-
-        case ACCEPT_BEGIN :
-            /* get response */
-            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
-                if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-#ifdef WOLFSSL_TLS13
-            ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
-            FALL_THROUGH;
-
-        case ACCEPT_CLIENT_HELLO_DONE :
-            if (ssl->options.tls1_3) {
-                return wolfSSL_accept_TLSv13(ssl);
-            }
-#endif
-            ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
-            FALL_THROUGH;
-
-        case ACCEPT_FIRST_REPLY_DONE :
-            if ( (ssl->error = SendServerHello(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.acceptState = SERVER_HELLO_SENT;
-            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
-            FALL_THROUGH;
-
-        case SERVER_HELLO_SENT :
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3) {
-                return wolfSSL_accept_TLSv13(ssl);
-            }
-        #endif
-            #ifndef NO_CERTS
-                if (!ssl->options.resuming)
-                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-            #endif
-            ssl->options.acceptState = CERT_SENT;
-            WOLFSSL_MSG("accept state CERT_SENT");
-            FALL_THROUGH;
-
-        case CERT_SENT :
-            #ifndef NO_CERTS
-            if (!ssl->options.resuming)
-                if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            #endif
-            ssl->options.acceptState = CERT_STATUS_SENT;
-            WOLFSSL_MSG("accept state CERT_STATUS_SENT");
-            FALL_THROUGH;
-
-        case CERT_STATUS_SENT :
-        #ifdef WOLFSSL_TLS13
-            if (ssl->options.tls1_3) {
-                return wolfSSL_accept_TLSv13(ssl);
-            }
-        #endif
-            if (!ssl->options.resuming)
-                if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            ssl->options.acceptState = KEY_EXCHANGE_SENT;
-            WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT");
-            FALL_THROUGH;
-
-        case KEY_EXCHANGE_SENT :
-            #ifndef NO_CERTS
-                if (!ssl->options.resuming) {
-                    if (ssl->options.verifyPeer) {
-                        if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
-                            WOLFSSL_ERROR(ssl->error);
-                            return WOLFSSL_FATAL_ERROR;
-                        }
-                    }
-                }
-            #endif
-            ssl->options.acceptState = CERT_REQ_SENT;
-            WOLFSSL_MSG("accept state CERT_REQ_SENT");
-            FALL_THROUGH;
-
-        case CERT_REQ_SENT :
-            if (!ssl->options.resuming)
-                if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            ssl->options.acceptState = SERVER_HELLO_DONE;
-            WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
-            FALL_THROUGH;
-
-        case SERVER_HELLO_DONE :
-            if (!ssl->options.resuming) {
-                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
-                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-            }
-            ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
-            WOLFSSL_MSG("accept state  ACCEPT_SECOND_REPLY_DONE");
-            FALL_THROUGH;
-
-        case ACCEPT_SECOND_REPLY_DONE :
-#ifdef HAVE_SESSION_TICKET
-            if (ssl->options.createTicket) {
-                if ( (ssl->error = SendTicket(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif /* HAVE_SESSION_TICKET */
-            ssl->options.acceptState = TICKET_SENT;
-            WOLFSSL_MSG("accept state  TICKET_SENT");
-            FALL_THROUGH;
-
-        case TICKET_SENT:
-            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.acceptState = CHANGE_CIPHER_SENT;
-            WOLFSSL_MSG("accept state  CHANGE_CIPHER_SENT");
-            FALL_THROUGH;
-
-        case CHANGE_CIPHER_SENT :
-            if ( (ssl->error = SendFinished(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-
-            ssl->options.acceptState = ACCEPT_FINISHED_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
-            FALL_THROUGH;
-
-        case ACCEPT_FINISHED_DONE :
-            if (ssl->options.resuming)
-                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
-                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-
-            ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
-            FALL_THROUGH;
-
-        case ACCEPT_THIRD_REPLY_DONE :
-#ifndef NO_HANDSHAKE_DONE_CB
-            if (ssl->hsDoneCb) {
-                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
-                if (cbret < 0) {
-                    ssl->error = cbret;
-                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif /* NO_HANDSHAKE_DONE_CB */
-
-            if (!ssl->options.dtls) {
-                if (!ssl->options.keepResources) {
-                    FreeHandshakeResources(ssl);
-                }
-            }
-#ifdef WOLFSSL_DTLS
-            else {
-                ssl->options.dtlsHsRetain = 1;
-            }
-#endif /* WOLFSSL_DTLS */
-
-#ifdef WOLFSSL_SESSION_EXPORT
-            if (ssl->dtls_export) {
-                if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
-                    WOLFSSL_MSG("Export DTLS session error");
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif
-
-            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
-            return WOLFSSL_SUCCESS;
-
-        default :
-            WOLFSSL_MSG("Unknown accept state ERROR");
-            return WOLFSSL_FATAL_ERROR;
-        }
-#endif /* !WOLFSSL_NO_TLS12 */
-    }
-
-#endif /* NO_WOLFSSL_SERVER */
-
-
-#ifndef NO_HANDSHAKE_DONE_CB
-
-int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ssl->hsDoneCb  = cb;
-    ssl->hsDoneCtx = user_ctx;
-
-
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_HANDSHAKE_DONE_CB */
-
-int wolfSSL_Cleanup(void)
-{
-    int ret = WOLFSSL_SUCCESS;
-    int release = 0;
-
-    WOLFSSL_ENTER("wolfSSL_Cleanup");
-
-    if (initRefCount == 0)
-        return ret;  /* possibly no init yet, but not failure either way */
-
-    if (wc_LockMutex(&count_mutex) != 0) {
-        WOLFSSL_MSG("Bad Lock Mutex count");
-        return BAD_MUTEX_E;
-    }
-
-    release = initRefCount-- == 1;
-    if (initRefCount < 0)
-        initRefCount = 0;
-
-    wc_UnLockMutex(&count_mutex);
-
-    if (!release)
-        return ret;
-
-#ifndef NO_SESSION_CACHE
-    if (wc_FreeMutex(&session_mutex) != 0)
-        ret = BAD_MUTEX_E;
-#endif
-    if (wc_FreeMutex(&count_mutex) != 0)
-        ret = BAD_MUTEX_E;
-
-    if (wolfCrypt_Cleanup() != 0) {
-        WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
-        ret = WC_CLEANUP_E;
-    }
-
-    return ret;
-}
-
-
-#ifndef NO_SESSION_CACHE
-
-
-/* some session IDs aren't random after all, let's make them random */
-static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
-{
-    byte digest[WC_MAX_DIGEST_SIZE];
-
-#ifndef NO_MD5
-    *error =  wc_Md5Hash(sessionID, len, digest);
-#elif !defined(NO_SHA)
-    *error =  wc_ShaHash(sessionID, len, digest);
-#elif !defined(NO_SHA256)
-    *error =  wc_Sha256Hash(sessionID, len, digest);
-#else
-    #error "We need a digest to hash the session IDs"
-#endif
-
-    return *error == 0 ? MakeWordFromHash(digest) : 0; /* 0 on failure */
-}
-
-
-void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
-{
-    /* static table now, no flushing needed */
-    (void)ctx;
-    (void)tm;
-}
-
-
-/* set ssl session timeout in seconds */
-int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to)
-{
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    if (to == 0)
-        to = WOLFSSL_SESSION_TIMEOUT;
-    ssl->timeout = to;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* set ctx session timeout in seconds */
-int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    if (to == 0)
-        to = WOLFSSL_SESSION_TIMEOUT;
-    ctx->timeout = to;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-#ifndef NO_CLIENT_CACHE
-
-/* Get Session from Client cache based on id/len, return NULL on failure */
-WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
-{
-    WOLFSSL_SESSION* ret = NULL;
-    word32          row;
-    int             idx;
-    int             count;
-    int             error = 0;
-
-    WOLFSSL_ENTER("GetSessionClient");
-
-    if (ssl->ctx->sessionCacheOff)
-        return NULL;
-
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        return NULL;
-
-    len = min(SERVER_ID_LEN, (word32)len);
-
-#ifdef HAVE_EXT_CACHE
-    if (ssl->ctx->get_sess_cb != NULL) {
-        int copy = 0;
-        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, &copy);
-        if (ret != NULL)
-            return ret;
-    }
-
-    if (ssl->ctx->internalCacheOff)
-        return NULL;
-#endif
-
-    row = HashSession(id, len, &error) % SESSION_ROWS;
-    if (error != 0) {
-        WOLFSSL_MSG("Hash session failed");
-        return NULL;
-    }
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        WOLFSSL_MSG("Lock session mutex failed");
-        return NULL;
-    }
-
-    /* start from most recently used */
-    count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW);
-    idx = ClientCache[row].nextIdx - 1;
-    if (idx < 0)
-        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
-
-    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
-        WOLFSSL_SESSION* current;
-        ClientSession   clSess;
-
-        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
-            WOLFSSL_MSG("Bad idx");
-            break;
-        }
-
-        clSess = ClientCache[row].Clients[idx];
-
-        current = &SessionCache[clSess.serverRow].Sessions[clSess.serverIdx];
-        if (XMEMCMP(current->serverID, id, len) == 0) {
-            WOLFSSL_MSG("Found a serverid match for client");
-            if (LowResTimer() < (current->bornOn + current->timeout)) {
-                WOLFSSL_MSG("Session valid");
-                ret = current;
-                break;
-            } else {
-                WOLFSSL_MSG("Session timed out");  /* could have more for id */
-            }
-        } else {
-            WOLFSSL_MSG("ServerID not a match from client table");
-        }
-    }
-
-    wc_UnLockMutex(&session_mutex);
-
-    return ret;
-}
-
-#endif /* NO_CLIENT_CACHE */
-
-/* Restore the master secret and session information for certificates.
- *
- * ssl                  The SSL/TLS object.
- * session              The cached session to restore.
- * masterSecret         The master secret from the cached session.
- * restoreSessionCerts  Restoring session certificates is required.
- */
-static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session,
-        byte* masterSecret, byte restoreSessionCerts)
-{
-    (void)ssl;
-    (void)restoreSessionCerts;
-
-    if (masterSecret)
-        XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN);
-#ifdef SESSION_CERTS
-    /* If set, we should copy the session certs into the ssl object
-     * from the session we are returning so we can resume */
-    if (restoreSessionCerts) {
-        ssl->session.chain        = session->chain;
-        ssl->session.version      = session->version;
-        ssl->session.cipherSuite0 = session->cipherSuite0;
-        ssl->session.cipherSuite  = session->cipherSuite;
-    }
-#endif /* SESSION_CERTS */
-}
-
-WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
-        byte restoreSessionCerts)
-{
-    WOLFSSL_SESSION* ret = 0;
-    const byte*  id = NULL;
-    word32       row;
-    int          idx;
-    int          count;
-    int          error = 0;
-
-    (void)       restoreSessionCerts;
-
-    if (ssl->options.sessionCacheOff)
-        return NULL;
-
-    if (ssl->options.haveSessionId == 0)
-        return NULL;
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
-        return NULL;
-#endif
-
-    if (ssl->arrays)
-        id = ssl->arrays->sessionID;
-    else
-        id = ssl->session.sessionID;
-
-#ifdef HAVE_EXT_CACHE
-    if (ssl->ctx->get_sess_cb != NULL) {
-        int copy = 0;
-        /* Attempt to retrieve the session from the external cache. */
-        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, &copy);
-        if (ret != NULL) {
-            RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
-            return ret;
-        }
-    }
-
-    if (ssl->ctx->internalCacheOff)
-        return NULL;
-#endif
-
-    row = HashSession(id, ID_LEN, &error) % SESSION_ROWS;
-    if (error != 0) {
-        WOLFSSL_MSG("Hash session failed");
-        return NULL;
-    }
-
-    if (wc_LockMutex(&session_mutex) != 0)
-        return 0;
-
-    /* start from most recently used */
-    count = min((word32)SessionCache[row].totalCount, SESSIONS_PER_ROW);
-    idx = SessionCache[row].nextIdx - 1;
-    if (idx < 0)
-        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
-
-    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
-        WOLFSSL_SESSION* current;
-
-        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
-            WOLFSSL_MSG("Bad idx");
-            break;
-        }
-
-        current = &SessionCache[row].Sessions[idx];
-        if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) {
-            WOLFSSL_MSG("Found a session match");
-            if (LowResTimer() < (current->bornOn + current->timeout)) {
-                WOLFSSL_MSG("Session valid");
-                ret = current;
-                RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
-            } else {
-                WOLFSSL_MSG("Session timed out");
-            }
-            break;  /* no more sessionIDs whether valid or not that match */
-        } else {
-            WOLFSSL_MSG("SessionID not a match at this idx");
-        }
-    }
-
-    wc_UnLockMutex(&session_mutex);
-
-    return ret;
-}
-
-
-static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom)
-{
-    WOLFSSL_SESSION* copyInto = &ssl->session;
-    void* tmpBuff             = NULL;
-    int ticketLen             = 0;
-    int doDynamicCopy         = 0;
-    int ret                   = WOLFSSL_SUCCESS;
-
-    (void)ticketLen;
-    (void)doDynamicCopy;
-    (void)tmpBuff;
-
-    if (!ssl || !copyFrom)
-        return BAD_FUNC_ARG;
-
-#ifdef HAVE_SESSION_TICKET
-    /* Free old dynamic ticket if we had one to avoid leak */
-    if (copyInto->isDynamic) {
-        XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        copyInto->ticket = copyInto->staticTicket;
-        copyInto->isDynamic = 0;
-    }
-#endif
-
-    if (wc_LockMutex(&session_mutex) != 0)
-        return BAD_MUTEX_E;
-
-#ifdef HAVE_SESSION_TICKET
-    /* Size of ticket to alloc if needed; Use later for alloc outside lock */
-    doDynamicCopy = copyFrom->isDynamic;
-    ticketLen = copyFrom->ticketLen;
-#endif
-
-    *copyInto = *copyFrom;
-
-    /* Default ticket to non dynamic. This will avoid crash if we fail below */
-#ifdef HAVE_SESSION_TICKET
-    copyInto->ticket = copyInto->staticTicket;
-    copyInto->isDynamic = 0;
-#endif
-
-    if (wc_UnLockMutex(&session_mutex) != 0) {
-        return BAD_MUTEX_E;
-    }
-
-#ifdef HAVE_SESSION_TICKET
-#ifdef WOLFSSL_TLS13
-    if (wc_LockMutex(&session_mutex) != 0) {
-        XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        return BAD_MUTEX_E;
-    }
-
-    copyInto->cipherSuite0   = copyFrom->cipherSuite0;
-    copyInto->cipherSuite    = copyFrom->cipherSuite;
-    copyInto->namedGroup     = copyFrom->namedGroup;
-    copyInto->ticketSeen     = copyFrom->ticketSeen;
-    copyInto->ticketAdd      = copyFrom->ticketAdd;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    XMEMCPY(&copyInto->ticketNonce, &copyFrom->ticketNonce,
-                                                           sizeof(TicketNonce));
-#endif
-#ifdef WOLFSSL_EARLY_DATA
-    copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz;
-#endif
-    XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN);
-
-    if (wc_UnLockMutex(&session_mutex) != 0) {
-        if (ret == WOLFSSL_SUCCESS)
-            ret = BAD_MUTEX_E;
-    }
-#endif
-    /* If doing dynamic copy, need to alloc outside lock, then inside a lock
-     * confirm the size still matches and memcpy */
-    if (doDynamicCopy) {
-        tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap,
-                                                     DYNAMIC_TYPE_SESSION_TICK);
-        if (!tmpBuff)
-            return MEMORY_ERROR;
-
-        if (wc_LockMutex(&session_mutex) != 0) {
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-            return BAD_MUTEX_E;
-        }
-
-        if (ticketLen != copyFrom->ticketLen) {
-            /* Another thread modified the ssl-> session ticket during alloc.
-             * Treat as error, since ticket different than when copy requested */
-            ret = VAR_STATE_CHANGE_E;
-        }
-
-        if (ret == WOLFSSL_SUCCESS) {
-            copyInto->ticket = (byte*)tmpBuff;
-            copyInto->isDynamic = 1;
-            XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen);
-        }
-    } else {
-        /* Need to ensure ticket pointer gets updated to own buffer
-         * and is not pointing to buff of session copied from */
-        copyInto->ticket = copyInto->staticTicket;
-    }
-
-    if (doDynamicCopy) {
-        if (wc_UnLockMutex(&session_mutex) != 0) {
-            if (ret == WOLFSSL_SUCCESS)
-                ret = BAD_MUTEX_E;
-        }
-    }
-
-    if (ret != WOLFSSL_SUCCESS) {
-        /* cleanup */
-        if (tmpBuff)
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-        copyInto->ticket = copyInto->staticTicket;
-        copyInto->isDynamic = 0;
-    }
-#endif /* HAVE_SESSION_TICKET */
-    return ret;
-}
-
-
-int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
-{
-    if (ssl->options.sessionCacheOff)
-        return WOLFSSL_FAILURE;
-
-#ifdef OPENSSL_EXTRA
-    /* check for application context id */
-    if (ssl->sessionCtxSz > 0) {
-        if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) {
-            /* context id did not match! */
-            WOLFSSL_MSG("Session context did not match");
-            return SSL_FAILURE;
-        }
-    }
-#endif /* OPENSSL_EXTRA */
-
-    if (LowResTimer() < (session->bornOn + session->timeout)) {
-        int ret = GetDeepCopySession(ssl, session);
-        if (ret == WOLFSSL_SUCCESS) {
-            ssl->options.resuming = 1;
-
-#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
-                               defined(HAVE_SESSION_TICKET))
-            ssl->version              = session->version;
-            ssl->options.cipherSuite0 = session->cipherSuite0;
-            ssl->options.cipherSuite  = session->cipherSuite;
-#endif
-        }
-
-        return ret;
-    }
-    return WOLFSSL_FAILURE;  /* session timed out */
-}
-
-
-#ifdef WOLFSSL_SESSION_STATS
-static int get_locked_session_stats(word32* active, word32* total,
-                                    word32* peak);
-#endif
-
-int AddSession(WOLFSSL* ssl)
-{
-    word32 row = 0;
-    word32 idx = 0;
-    int    error = 0;
-#ifdef HAVE_SESSION_TICKET
-    byte*  tmpBuff = NULL;
-    int    ticLen  = 0;
-#endif
-    WOLFSSL_SESSION* session;
-
-    if (ssl->options.sessionCacheOff)
-        return 0;
-
-    if (ssl->options.haveSessionId == 0)
-        return 0;
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
-        return 0;
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-    ticLen = ssl->session.ticketLen;
-    /* Alloc Memory here so if Malloc fails can exit outside of lock */
-    if(ticLen > SESSION_TICKET_LEN) {
-        tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap,
-                DYNAMIC_TYPE_SESSION_TICK);
-        if(!tmpBuff)
-            return MEMORY_E;
-    }
-#endif
-
-#ifdef HAVE_EXT_CACHE
-    if (ssl->options.internalCacheOff) {
-        /* Create a new session object to be stored. */
-        session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
-                                            DYNAMIC_TYPE_OPENSSL);
-        if (session == NULL) {
-#ifdef HAVE_SESSION_TICKET
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-#endif
-            return MEMORY_E;
-        }
-        XMEMSET(session, 0, sizeof(WOLFSSL_SESSION));
-        session->isAlloced = 1;
-    }
-    else
-#endif
-    {
-        /* Use the session object in the cache for external cache if required.
-         */
-        row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) %
-                SESSION_ROWS;
-        if (error != 0) {
-            WOLFSSL_MSG("Hash session failed");
-#ifdef HAVE_SESSION_TICKET
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-#endif
-            return error;
-        }
-
-        if (wc_LockMutex(&session_mutex) != 0) {
-#ifdef HAVE_SESSION_TICKET
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-#endif
-            return BAD_MUTEX_E;
-        }
-
-        idx = SessionCache[row].nextIdx++;
-#ifdef SESSION_INDEX
-        ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
-#endif
-        session = &SessionCache[row].Sessions[idx];
-    }
-
-    if (!ssl->options.tls1_3)
-        XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN);
-    else
-        XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN);
-    session->haveEMS = ssl->options.haveEMS;
-    XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN);
-    session->sessionIDSz = ssl->arrays->sessionIDSz;
-
-#ifdef OPENSSL_EXTRA
-    /* If using compatibilty layer then check for and copy over session context
-     * id. */
-    if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) {
-        XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz);
-    }
-#endif
-
-    session->timeout = ssl->timeout;
-    session->bornOn  = LowResTimer();
-
-#ifdef HAVE_SESSION_TICKET
-    /* Check if another thread modified ticket since alloc */
-    if (ticLen != ssl->session.ticketLen) {
-        error = VAR_STATE_CHANGE_E;
-    }
-
-    if (error == 0) {
-        /* Cleanup cache row's old Dynamic buff if exists */
-        if(session->isDynamic) {
-            XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-            session->ticket = NULL;
-        }
-
-        /* If too large to store in static buffer, use dyn buffer */
-        if (ticLen > SESSION_TICKET_LEN) {
-            session->ticket = tmpBuff;
-            session->isDynamic = 1;
-        } else {
-            session->ticket = session->staticTicket;
-            session->isDynamic = 0;
-        }
-    }
-
-    if (error == 0) {
-        session->ticketLen = (word16)ticLen;
-        XMEMCPY(session->ticket, ssl->session.ticket, ticLen);
-    } else { /* cleanup, reset state */
-        session->ticket    = session->staticTicket;
-        session->isDynamic = 0;
-        session->ticketLen = 0;
-        if (tmpBuff) {
-            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
-            tmpBuff = NULL;
-        }
-    }
-#endif
-
-#ifdef SESSION_CERTS
-    if (error == 0) {
-        session->chain.count = ssl->session.chain.count;
-        XMEMCPY(session->chain.certs, ssl->session.chain.certs,
-                sizeof(x509_buffer) * MAX_CHAIN_DEPTH);
-    }
-#endif /* SESSION_CERTS */
-#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
-                               defined(HAVE_SESSION_TICKET))
-    if (error == 0) {
-        session->version      = ssl->version;
-        session->cipherSuite0 = ssl->options.cipherSuite0;
-        session->cipherSuite  = ssl->options.cipherSuite;
-    }
-#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */
-#if defined(WOLFSSL_TLS13)
-    if (error == 0) {
-        session->namedGroup     = ssl->session.namedGroup;
-    }
-#endif
-#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
-    if (error == 0) {
-        session->ticketSeen     = ssl->session.ticketSeen;
-        session->ticketAdd      = ssl->session.ticketAdd;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-        XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce,
-                                                           sizeof(TicketNonce));
-#endif
-    #ifdef WOLFSSL_EARLY_DATA
-        session->maxEarlyDataSz = ssl->session.maxEarlyDataSz;
-    #endif
-    }
-#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */
-#ifdef HAVE_EXT_CACHE
-    if (!ssl->options.internalCacheOff)
-#endif
-    {
-        if (error == 0) {
-            SessionCache[row].totalCount++;
-            if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
-                SessionCache[row].nextIdx = 0;
-        }
-    }
-#ifndef NO_CLIENT_CACHE
-    if (error == 0) {
-        if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) {
-            word32 clientRow, clientIdx;
-
-            WOLFSSL_MSG("Adding client cache entry");
-
-            session->idLen = ssl->session.idLen;
-            XMEMCPY(session->serverID, ssl->session.serverID,
-                    ssl->session.idLen);
-
-#ifdef HAVE_EXT_CACHE
-            if (!ssl->options.internalCacheOff)
-#endif
-            {
-                clientRow = HashSession(ssl->session.serverID,
-                        ssl->session.idLen, &error) % SESSION_ROWS;
-                if (error != 0) {
-                    WOLFSSL_MSG("Hash session failed");
-                } else {
-                    clientIdx = ClientCache[clientRow].nextIdx++;
-
-                    ClientCache[clientRow].Clients[clientIdx].serverRow =
-                                                                   (word16)row;
-                    ClientCache[clientRow].Clients[clientIdx].serverIdx =
-                                                                   (word16)idx;
-
-                    ClientCache[clientRow].totalCount++;
-                    if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW)
-                        ClientCache[clientRow].nextIdx = 0;
-                }
-            }
-        }
-        else
-            session->idLen = 0;
-    }
-#endif /* NO_CLIENT_CACHE */
-
-#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
-#ifdef HAVE_EXT_CACHE
-    if (!ssl->options.internalCacheOff)
-#endif
-    {
-        if (error == 0) {
-            word32 active = 0;
-
-            error = get_locked_session_stats(&active, NULL, NULL);
-            if (error == WOLFSSL_SUCCESS) {
-                error = 0;  /* back to this function ok */
-
-                if (active > PeakSessions)
-                    PeakSessions = active;
-            }
-        }
-    }
-#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */
-
-#ifdef HAVE_EXT_CACHE
-    if (!ssl->options.internalCacheOff)
-#endif
-    {
-        if (wc_UnLockMutex(&session_mutex) != 0)
-            return BAD_MUTEX_E;
-    }
-
-#ifdef HAVE_EXT_CACHE
-    if (error == 0 && ssl->ctx->new_sess_cb != NULL)
-        ssl->ctx->new_sess_cb(ssl, session);
-    if (ssl->options.internalCacheOff)
-        wolfSSL_SESSION_free(session);
-#endif
-
-    return error;
-}
-
-
-#ifdef SESSION_INDEX
-
-int wolfSSL_GetSessionIndex(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_GetSessionIndex");
-    WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex);
-    return ssl->sessionIndex;
-}
-
-
-int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
-{
-    int row, col, result = WOLFSSL_FAILURE;
-
-    WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
-
-    row = idx >> SESSIDX_ROW_SHIFT;
-    col = idx & SESSIDX_IDX_MASK;
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        return BAD_MUTEX_E;
-    }
-
-    if (row < SESSION_ROWS &&
-        col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) {
-        XMEMCPY(session,
-                 &SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION));
-        result = WOLFSSL_SUCCESS;
-    }
-
-    if (wc_UnLockMutex(&session_mutex) != 0)
-        result = BAD_MUTEX_E;
-
-    WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result);
-    return result;
-}
-
-#endif /* SESSION_INDEX */
-
-#if defined(SESSION_INDEX) && defined(SESSION_CERTS)
-
-WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
-{
-    WOLFSSL_X509_CHAIN* chain = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
-    if (session)
-        chain = &session->chain;
-
-    WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0);
-    return chain;
-}
-
-#endif /* SESSION_INDEX && SESSION_CERTS */
-
-
-#ifdef WOLFSSL_SESSION_STATS
-
-/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */
-static int get_locked_session_stats(word32* active, word32* total, word32* peak)
-{
-    int result = WOLFSSL_SUCCESS;
-    int i;
-    int count;
-    int idx;
-    word32 now   = 0;
-    word32 seen  = 0;
-    word32 ticks = LowResTimer();
-
-    (void)peak;
-
-    WOLFSSL_ENTER("get_locked_session_stats");
-
-    for (i = 0; i < SESSION_ROWS; i++) {
-        seen += SessionCache[i].totalCount;
-
-        if (active == NULL)
-            continue;  /* no need to calculate what we can't set */
-
-        count = min((word32)SessionCache[i].totalCount, SESSIONS_PER_ROW);
-        idx   = SessionCache[i].nextIdx - 1;
-        if (idx < 0)
-            idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */
-
-        for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
-            if (idx >= SESSIONS_PER_ROW || idx < 0) {  /* sanity check */
-                WOLFSSL_MSG("Bad idx");
-                break;
-            }
-
-            /* if not expried then good */
-            if (ticks < (SessionCache[i].Sessions[idx].bornOn +
-                         SessionCache[i].Sessions[idx].timeout) ) {
-                now++;
-            }
-        }
-    }
-
-    if (active)
-        *active = now;
-
-    if (total)
-        *total = seen;
-
-#ifdef WOLFSSL_PEAK_SESSIONS
-    if (peak)
-        *peak = PeakSessions;
-#endif
-
-    WOLFSSL_LEAVE("get_locked_session_stats", result);
-
-    return result;
-}
-
-
-/* return WOLFSSL_SUCCESS on ok */
-int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
-                              word32* maxSessions)
-{
-    int result = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("wolfSSL_get_session_stats");
-
-    if (maxSessions) {
-        *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS;
-
-        if (active == NULL && total == NULL && peak == NULL)
-            return result;  /* we're done */
-    }
-
-    /* user must provide at least one query value */
-    if (active == NULL && total == NULL && peak == NULL)
-        return BAD_FUNC_ARG;
-
-    if (wc_LockMutex(&session_mutex) != 0) {
-        return BAD_MUTEX_E;
-    }
-
-    result = get_locked_session_stats(active, total, peak);
-
-    if (wc_UnLockMutex(&session_mutex) != 0)
-        result = BAD_MUTEX_E;
-
-    WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
-
-    return result;
-}
-
-#endif /* WOLFSSL_SESSION_STATS */
-
-
-    #ifdef PRINT_SESSION_STATS
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_PrintSessionStats(void)
-    {
-        word32 totalSessionsSeen = 0;
-        word32 totalSessionsNow = 0;
-        word32 peak = 0;
-        word32 maxSessions = 0;
-        int    i;
-        int    ret;
-        double E;               /* expected freq */
-        double chiSquare = 0;
-
-        ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen,
-                                        &peak, &maxSessions);
-        if (ret != WOLFSSL_SUCCESS)
-            return ret;
-        printf("Total Sessions Seen = %d\n", totalSessionsSeen);
-        printf("Total Sessions Now  = %d\n", totalSessionsNow);
-#ifdef WOLFSSL_PEAK_SESSIONS
-        printf("Peak  Sessions      = %d\n", peak);
-#endif
-        printf("Max   Sessions      = %d\n", maxSessions);
-
-        E = (double)totalSessionsSeen / SESSION_ROWS;
-
-        for (i = 0; i < SESSION_ROWS; i++) {
-            double diff = SessionCache[i].totalCount - E;
-            diff *= diff;                /* square    */
-            diff /= E;                   /* normalize */
-
-            chiSquare += diff;
-        }
-        printf("  chi-square = %5.1f, d.f. = %d\n", chiSquare,
-                                                     SESSION_ROWS - 1);
-        #if (SESSION_ROWS == 11)
-            printf(" .05 p value =  18.3, chi-square should be less\n");
-        #elif (SESSION_ROWS == 211)
-            printf(".05 p value  = 244.8, chi-square should be less\n");
-        #elif (SESSION_ROWS == 5981)
-            printf(".05 p value  = 6161.0, chi-square should be less\n");
-        #elif (SESSION_ROWS == 3)
-            printf(".05 p value  =   6.0, chi-square should be less\n");
-        #elif (SESSION_ROWS == 2861)
-            printf(".05 p value  = 2985.5, chi-square should be less\n");
-        #endif
-        printf("\n");
-
-        return ret;
-    }
-
-    #endif /* SESSION_STATS */
-
-#else  /* NO_SESSION_CACHE */
-
-/* No session cache version */
-WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
-        byte restoreSessionCerts)
-{
-    (void)ssl;
-    (void)masterSecret;
-    (void)restoreSessionCerts;
-
-    return NULL;
-}
-
-#endif /* NO_SESSION_CACHE */
-
-
-/* call before SSL_connect, if verifying will add name check to
-   date check and signature check */
-int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
-{
-    WOLFSSL_ENTER("wolfSSL_check_domain_name");
-
-    if (ssl == NULL || dn == NULL) {
-        WOLFSSL_MSG("Bad function argument: NULL");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (ssl->buffers.domainName.buffer)
-        XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
-
-    ssl->buffers.domainName.length = (word32)XSTRLEN(dn);
-    ssl->buffers.domainName.buffer = (byte*)XMALLOC(
-            ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN);
-
-    if (ssl->buffers.domainName.buffer) {
-        char* domainName = (char*)ssl->buffers.domainName.buffer;
-        XSTRNCPY(domainName, dn, ssl->buffers.domainName.length);
-        domainName[ssl->buffers.domainName.length] = '\0';
-        return WOLFSSL_SUCCESS;
-    }
-    else {
-        ssl->error = MEMORY_ERROR;
-        return WOLFSSL_FAILURE;
-    }
-}
-
-
-/* turn on wolfSSL zlib compression
-   returns WOLFSSL_SUCCESS for success, else error (not built in)
-*/
-int wolfSSL_set_compression(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_set_compression");
-    (void)ssl;
-#ifdef HAVE_LIBZ
-    ssl->options.usingCompression = 1;
-    return WOLFSSL_SUCCESS;
-#else
-    return NOT_COMPILED_IN;
-#endif
-}
-
-
-#ifndef USE_WINDOWS_API
-    #ifndef NO_WRITEV
-
-        /* simulate writev semantics, doesn't actually do block at a time though
-           because of SSL_write behavior and because front adds may be small */
-        int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt)
-        {
-        #ifdef WOLFSSL_SMALL_STACK
-            byte   staticBuffer[1]; /* force heap usage */
-        #else
-            byte   staticBuffer[FILE_BUFFER_SIZE];
-        #endif
-            byte* myBuffer  = staticBuffer;
-            int   dynamic   = 0;
-            int   sending   = 0;
-            int   idx       = 0;
-            int   i;
-            int   ret;
-
-            WOLFSSL_ENTER("wolfSSL_writev");
-
-            for (i = 0; i < iovcnt; i++)
-                sending += (int)iov[i].iov_len;
-
-            if (sending > (int)sizeof(staticBuffer)) {
-                myBuffer = (byte*)XMALLOC(sending, ssl->heap,
-                                                           DYNAMIC_TYPE_WRITEV);
-                if (!myBuffer)
-                    return MEMORY_ERROR;
-
-                dynamic = 1;
-            }
-
-            for (i = 0; i < iovcnt; i++) {
-                XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
-                idx += (int)iov[i].iov_len;
-            }
-
-            ret = wolfSSL_write(ssl, myBuffer, sending);
-
-            if (dynamic)
-                XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
-
-            return ret;
-        }
-    #endif
-#endif
-
-
-#ifdef WOLFSSL_CALLBACKS
-
-    typedef struct itimerval Itimerval;
-
-    /* don't keep calling simple functions while setting up timer and signals
-       if no inlining these are the next best */
-
-    #define AddTimes(a, b, c)                       \
-        do {                                        \
-            c.tv_sec  = a.tv_sec  + b.tv_sec;       \
-            c.tv_usec = a.tv_usec + b.tv_usec;      \
-            if (c.tv_usec >=  1000000) {            \
-                c.tv_sec++;                         \
-                c.tv_usec -= 1000000;               \
-            }                                       \
-        } while (0)
-
-
-    #define SubtractTimes(a, b, c)                  \
-        do {                                        \
-            c.tv_sec  = a.tv_sec  - b.tv_sec;       \
-            c.tv_usec = a.tv_usec - b.tv_usec;      \
-            if (c.tv_usec < 0) {                    \
-                c.tv_sec--;                         \
-                c.tv_usec += 1000000;               \
-            }                                       \
-        } while (0)
-
-    #define CmpTimes(a, b, cmp)                     \
-        ((a.tv_sec  ==  b.tv_sec) ?                 \
-            (a.tv_usec cmp b.tv_usec) :             \
-            (a.tv_sec  cmp b.tv_sec))               \
-
-
-    /* do nothing handler */
-    static void myHandler(int signo)
-    {
-        (void)signo;
-        return;
-    }
-
-
-    static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
-                                 TimeoutCallBack toCb, Timeval timeout)
-    {
-        int       ret        = WOLFSSL_FATAL_ERROR;
-        int       oldTimerOn = 0;   /* was timer already on */
-        Timeval   startTime;
-        Timeval   endTime;
-        Timeval   totalTime;
-        Itimerval myTimeout;
-        Itimerval oldTimeout; /* if old timer adjust from total time to reset */
-        struct sigaction act, oact;
-
-        #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
-
-        if (hsCb) {
-            ssl->hsInfoOn = 1;
-            InitHandShakeInfo(&ssl->handShakeInfo, ssl);
-        }
-        if (toCb) {
-            ssl->toInfoOn = 1;
-            InitTimeoutInfo(&ssl->timeoutInfo);
-
-            if (gettimeofday(&startTime, 0) < 0)
-                ERR_OUT(GETTIME_ERROR);
-
-            /* use setitimer to simulate getitimer, init 0 myTimeout */
-            myTimeout.it_interval.tv_sec  = 0;
-            myTimeout.it_interval.tv_usec = 0;
-            myTimeout.it_value.tv_sec     = 0;
-            myTimeout.it_value.tv_usec    = 0;
-            if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
-                ERR_OUT(SETITIMER_ERROR);
-
-            if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
-                oldTimerOn = 1;
-
-                /* is old timer going to expire before ours */
-                if (CmpTimes(oldTimeout.it_value, timeout, <)) {
-                    timeout.tv_sec  = oldTimeout.it_value.tv_sec;
-                    timeout.tv_usec = oldTimeout.it_value.tv_usec;
-                }
-            }
-            myTimeout.it_value.tv_sec  = timeout.tv_sec;
-            myTimeout.it_value.tv_usec = timeout.tv_usec;
-
-            /* set up signal handler, don't restart socket send/recv */
-            act.sa_handler = myHandler;
-            sigemptyset(&act.sa_mask);
-            act.sa_flags = 0;
-#ifdef SA_INTERRUPT
-            act.sa_flags |= SA_INTERRUPT;
-#endif
-            if (sigaction(SIGALRM, &act, &oact) < 0)
-                ERR_OUT(SIGACT_ERROR);
-
-            if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
-                ERR_OUT(SETITIMER_ERROR);
-        }
-
-        /* do main work */
-#ifndef NO_WOLFSSL_CLIENT
-        if (ssl->options.side == WOLFSSL_CLIENT_END)
-            ret = wolfSSL_connect(ssl);
-#endif
-#ifndef NO_WOLFSSL_SERVER
-        if (ssl->options.side == WOLFSSL_SERVER_END)
-            ret = wolfSSL_accept(ssl);
-#endif
-
-        /* do callbacks */
-        if (toCb) {
-            if (oldTimerOn) {
-                gettimeofday(&endTime, 0);
-                SubtractTimes(endTime, startTime, totalTime);
-                /* adjust old timer for elapsed time */
-                if (CmpTimes(totalTime, oldTimeout.it_value, <))
-                    SubtractTimes(oldTimeout.it_value, totalTime,
-                                  oldTimeout.it_value);
-                else {
-                    /* reset value to interval, may be off */
-                    oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
-                    oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
-                }
-                /* keep iter the same whether there or not */
-            }
-            /* restore old handler */
-            if (sigaction(SIGALRM, &oact, 0) < 0)
-                ret = SIGACT_ERROR;    /* more pressing error, stomp */
-            else
-                /* use old settings which may turn off (expired or not there) */
-                if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
-                    ret = SETITIMER_ERROR;
-
-            /* if we had a timeout call callback */
-            if (ssl->timeoutInfo.timeoutName[0]) {
-                ssl->timeoutInfo.timeoutValue.tv_sec  = timeout.tv_sec;
-                ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
-                (toCb)(&ssl->timeoutInfo);
-            }
-            /* clean up */
-            FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
-            ssl->toInfoOn = 0;
-        }
-        if (hsCb) {
-            FinishHandShakeInfo(&ssl->handShakeInfo);
-            (hsCb)(&ssl->handShakeInfo);
-            ssl->hsInfoOn = 0;
-        }
-        return ret;
-    }
-
-
-#ifndef NO_WOLFSSL_CLIENT
-
-    int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
-                          TimeoutCallBack toCb, Timeval timeout)
-    {
-        WOLFSSL_ENTER("wolfSSL_connect_ex");
-        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
-    }
-
-#endif
-
-
-#ifndef NO_WOLFSSL_SERVER
-
-    int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
-                         TimeoutCallBack toCb,Timeval timeout)
-    {
-        WOLFSSL_ENTER("wolfSSL_accept_ex");
-        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
-    }
-
-#endif
-
-#endif /* WOLFSSL_CALLBACKS */
-
-
-#ifndef NO_PSK
-
-    void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
-                                         wc_psk_client_callback cb)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback");
-        ctx->havePSK = 1;
-        ctx->client_psk_cb = cb;
-    }
-
-
-    void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
-    {
-        byte haveRSA = 1;
-        int  keySz   = 0;
-
-        WOLFSSL_ENTER("SSL_set_psk_client_callback");
-        ssl->options.havePSK = 1;
-        ssl->options.client_psk_cb = cb;
-
-        #ifdef NO_RSA
-            haveRSA = 0;
-        #endif
-        #ifndef NO_CERTS
-            keySz = ssl->buffers.keySz;
-        #endif
-        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
-                   ssl->options.haveDH, ssl->options.haveNTRU,
-                   ssl->options.haveECDSAsig, ssl->options.haveECC,
-                   ssl->options.haveStaticECC, ssl->options.side);
-    }
-
-
-    void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
-                                         wc_psk_server_callback cb)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback");
-        ctx->havePSK = 1;
-        ctx->server_psk_cb = cb;
-    }
-
-
-    void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
-    {
-        byte haveRSA = 1;
-        int  keySz   = 0;
-
-        WOLFSSL_ENTER("SSL_set_psk_server_callback");
-        ssl->options.havePSK = 1;
-        ssl->options.server_psk_cb = cb;
-
-        #ifdef NO_RSA
-            haveRSA = 0;
-        #endif
-        #ifndef NO_CERTS
-            keySz = ssl->buffers.keySz;
-        #endif
-        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
-                   ssl->options.haveDH, ssl->options.haveNTRU,
-                   ssl->options.haveECDSAsig, ssl->options.haveECC,
-                   ssl->options.haveStaticECC, ssl->options.side);
-    }
-
-
-    const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
-    {
-        WOLFSSL_ENTER("SSL_get_psk_identity_hint");
-
-        if (ssl == NULL || ssl->arrays == NULL)
-            return NULL;
-
-        return ssl->arrays->server_hint;
-    }
-
-
-    const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
-    {
-        WOLFSSL_ENTER("SSL_get_psk_identity");
-
-        if (ssl == NULL || ssl->arrays == NULL)
-            return NULL;
-
-        return ssl->arrays->client_identity;
-    }
-
-
-    int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint)
-    {
-        WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint");
-        if (hint == 0)
-            ctx->server_hint[0] = '\0';
-        else {
-            XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint));
-            ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
-        }
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
-    {
-        WOLFSSL_ENTER("SSL_use_psk_identity_hint");
-
-        if (ssl == NULL || ssl->arrays == NULL)
-            return WOLFSSL_FAILURE;
-
-        if (hint == 0)
-            ssl->arrays->server_hint[0] = 0;
-        else {
-            XSTRNCPY(ssl->arrays->server_hint, hint,
-                                            sizeof(ssl->arrays->server_hint));
-            ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
-        }
-        return WOLFSSL_SUCCESS;
-    }
-
-#endif /* NO_PSK */
-
-
-#ifdef HAVE_ANON
-
-    int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
-
-        if (ctx == NULL)
-            return WOLFSSL_FAILURE;
-
-        ctx->haveAnon = 1;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-#endif /* HAVE_ANON */
-
-
-#ifndef NO_CERTS
-/* used to be defined on NO_FILESYSTEM only, but are generally useful */
-
-    /* wolfSSL extension allows DER files to be loaded from buffers as well */
-    int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx,
-                                       const unsigned char* in,
-                                       long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer");
-        if (format == WOLFSSL_FILETYPE_PEM)
-            return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL);
-        else
-            return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0);
-    }
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx,
-                                       const unsigned char* in,
-                                       long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
-
-        /* sanity check on arguments */
-        if (sz < 0 || in == NULL || ctx == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (format == WOLFSSL_FILETYPE_PEM)
-            return ProcessChainBuffer(ctx, in, sz, format,
-                                                       TRUSTED_PEER_TYPE, NULL);
-        else
-            return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE,
-                                                                   NULL,NULL,0);
-    }
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-    int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
-        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0);
-    }
-
-
-    int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
-        return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL,NULL,0);
-    }
-
-
-    int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
-        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1);
-    }
-
-    int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
-                                 const unsigned char* in, long sz)
-    {
-        return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
-                                                            WOLFSSL_FILETYPE_PEM);
-    }
-
-
-#ifndef NO_DH
-
-    /* server wrapper for ctx or ssl Diffie-Hellman parameters */
-    static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
-                                               const unsigned char* buf,
-                                               long sz, int format)
-    {
-        DerBuffer* der = NULL;
-        int    ret      = 0;
-        word32 pSz = MAX_DH_SIZE;
-        word32 gSz = MAX_DH_SIZE;
-    #ifdef WOLFSSL_SMALL_STACK
-        byte*  p = NULL;
-        byte*  g = NULL;
-    #else
-        byte   p[MAX_DH_SIZE];
-        byte   g[MAX_DH_SIZE];
-    #endif
-
-        if (ctx == NULL || buf == NULL)
-            return BAD_FUNC_ARG;
-
-        ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap);
-        if (ret != 0) {
-            return ret;
-        }
-        der->buffer = (byte*)buf;
-        der->length = (word32)sz;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-
-        if (p == NULL || g == NULL) {
-            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-            return MEMORY_E;
-        }
-    #endif
-
-        if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
-            ret = WOLFSSL_BAD_FILETYPE;
-        else {
-            if (format == WOLFSSL_FILETYPE_PEM) {
-#ifdef WOLFSSL_PEM_TO_DER
-                FreeDer(&der);
-                ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap,
-                               NULL, NULL);
-    #ifdef WOLFSSL_WPAS
-        #ifndef NO_DSA
-                if (ret < 0) {
-                    ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap,
-                               NULL, NULL);
-                }
-        #endif
-    #endif /* WOLFSSL_WPAS */
-#else
-                ret = NOT_COMPILED_IN;
-#endif /* WOLFSSL_PEM_TO_DER */
-            }
-
-            if (ret == 0) {
-                if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
-                    ret = WOLFSSL_BAD_FILETYPE;
-                else if (ssl)
-                    ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
-                else
-                    ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
-            }
-        }
-
-        FreeDer(&der);
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    #endif
-
-        return ret;
-    }
-
-
-    /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
-    int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
-                               int format)
-    {
-        if (ssl == NULL)
-            return BAD_FUNC_ARG;
-
-        return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
-    }
-
-
-    /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
-    int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
-                                   long sz, int format)
-    {
-        return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
-    }
-
-#endif /* NO_DH */
-
-
-    int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
-        return ProcessBuffer(ssl->ctx, in, sz, format,CERT_TYPE,ssl,NULL,0);
-    }
-
-
-    int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
-        return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
-                             ssl, NULL, 0);
-    }
-
-    int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
-                                 const unsigned char* in, long sz, int format)
-    {
-        WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
-        return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE,
-                             ssl, NULL, 1);
-    }
-
-    int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
-                                 const unsigned char* in, long sz)
-    {
-        return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
-                                                            WOLFSSL_FILETYPE_PEM);
-    }
-
-
-    /* unload any certs or keys that SSL owns, leave CTX as is
-       WOLFSSL_SUCCESS on ok */
-    int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
-    {
-        if (ssl == NULL) {
-            WOLFSSL_MSG("Null function arg");
-            return BAD_FUNC_ARG;
-        }
-
-        if (ssl->buffers.weOwnCert && !ssl->keepCert) {
-            WOLFSSL_MSG("Unloading cert");
-            FreeDer(&ssl->buffers.certificate);
-            #ifdef KEEP_OUR_CERT
-                FreeX509(ssl->ourCert);
-                if (ssl->ourCert) {
-                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
-                    ssl->ourCert = NULL;
-                }
-            #endif
-            ssl->buffers.weOwnCert = 0;
-        }
-
-        if (ssl->buffers.weOwnCertChain) {
-            WOLFSSL_MSG("Unloading cert chain");
-            FreeDer(&ssl->buffers.certChain);
-            ssl->buffers.weOwnCertChain = 0;
-        }
-
-        if (ssl->buffers.weOwnKey) {
-            WOLFSSL_MSG("Unloading key");
-            FreeDer(&ssl->buffers.key);
-            ssl->buffers.weOwnKey = 0;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
-
-        if (ctx == NULL)
-            return BAD_FUNC_ARG;
-
-        return wolfSSL_CertManagerUnloadCAs(ctx->cm);
-    }
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
-
-        if (ctx == NULL)
-            return BAD_FUNC_ARG;
-
-        return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
-    }
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-/* old NO_FILESYSTEM end */
-#endif /* !NO_CERTS */
-
-
-#ifdef OPENSSL_EXTRA
-
-    int wolfSSL_add_all_algorithms(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
-        if (wolfSSL_Init() == WOLFSSL_SUCCESS)
-            return WOLFSSL_SUCCESS;
-        else
-            return WOLFSSL_FATAL_ERROR;
-    }
-
-    int wolfSSL_OPENSSL_add_all_algorithms_noconf(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_OPENSSL_add_all_algorithms_noconf");
-
-        if  (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
-            return WOLFSSL_FATAL_ERROR;
-
-        return  WOLFSSL_SUCCESS;
-    }
-
-   /* returns previous set cache size which stays constant */
-    long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz)
-    {
-        /* cache size fixed at compile time in wolfSSL */
-        (void)ctx;
-        (void)sz;
-        WOLFSSL_MSG("session cache is set at compile time");
-        #ifndef NO_SESSION_CACHE
-            return SESSIONS_PER_ROW * SESSION_ROWS;
-        #else
-            return 0;
-        #endif
-    }
-
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
-    void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
-        if (mode)
-            ctx->quietShutdown = 1;
-    }
-
-
-    void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
-        if (mode)
-            ssl->options.quietShutdown = 1;
-    }
-#endif
-
-#ifdef OPENSSL_EXTRA
-    void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
-    {
-        WOLFSSL_ENTER("wolfSSL_set_bio");
-
-        if (ssl == NULL) {
-            WOLFSSL_MSG("Bad argument, ssl was NULL");
-            return;
-        }
-
-        /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */
-        if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) {
-            wolfSSL_set_rfd(ssl, rd->fd);
-        }
-        if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) {
-            wolfSSL_set_wfd(ssl, wr->fd);
-        }
-
-        /* free any existing WOLFSSL_BIOs in use */
-        if (ssl->biord != NULL) {
-            if (ssl->biord != ssl->biowr) {
-                if (ssl->biowr != NULL) {
-                    wolfSSL_BIO_free(ssl->biowr);
-                    ssl->biowr = NULL;
-                }
-            }
-            wolfSSL_BIO_free(ssl->biord);
-            ssl->biord = NULL;
-        }
-
-
-        ssl->biord = rd;
-        ssl->biowr = wr;
-
-        /* set SSL to use BIO callbacks instead */
-        if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) &&
-            (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) {
-            ssl->CBIORecv = BioReceive;
-        }
-        if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) &&
-            (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) {
-            ssl->CBIOSend = BioSend;
-        }
-    }
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
-    void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
-                                       WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
-    {
-        WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list");
-
-        if (ctx != NULL)
-            ctx->ca_names = names;
-    }
-
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list(
-            const WOLFSSL_CTX *s)
-    {
-        WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list");
-
-        if (s == NULL)
-            return NULL;
-
-        return s->ca_names;
-    }
-#endif
-
-#ifdef OPENSSL_EXTRA
-    #if !defined(NO_RSA) && !defined(NO_CERTS)
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
-    {
-        WOLFSSL_STACK *list = NULL;
-        WOLFSSL_STACK *node;
-        WOLFSSL_BIO* bio;
-        WOLFSSL_X509 *cert = NULL;
-        WOLFSSL_X509_NAME *subjectName = NULL;
-
-        WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
-
-        bio = wolfSSL_BIO_new_file(fname, "r");
-        if (bio == NULL)
-            return NULL;
-
-        /* Read each certificate in the chain out of the file. */
-        while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
-            subjectName = wolfSSL_X509_get_subject_name(cert);
-            if (subjectName == NULL)
-                break;
-
-            node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
-                                           DYNAMIC_TYPE_OPENSSL);
-            if (node == NULL)
-                break;
-
-            /* Need a persistent copy of the subject name. */
-            node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
-                    sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL);
-            if (node->data.name == NULL) {
-                XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
-                break;
-            }
-            XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
-            /* Clear pointers so freeing certificate doesn't free memory. */
-            XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
-
-            /* Put node on the front of the list. */
-            node->num  = (list == NULL) ? 1 : list->num + 1;
-            node->next = list;
-            list = node;
-
-            wolfSSL_X509_free(cert);
-            cert = NULL;
-        }
-
-        wolfSSL_X509_free(cert);
-        wolfSSL_BIO_free(bio);
-        return list;
-    }
-
-    int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
-    {
-        WOLFSSL_STACK *node = NULL;
-        WOLFSSL_X509_NAME *subjectName = NULL;
-
-        WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
-
-        if (ctx == NULL || x509 == NULL){
-            WOLFSSL_MSG("Bad argument");
-            return SSL_FAILURE;
-        }
-
-        subjectName = wolfSSL_X509_get_subject_name(x509);
-        if (subjectName == NULL){
-            WOLFSSL_MSG("invalid x509 data");
-            return SSL_FAILURE;
-        }
-
-        /* Alloc stack struct */
-        node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC(
-                                           sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)),
-                                           NULL, DYNAMIC_TYPE_OPENSSL);
-        if (node == NULL){
-            WOLFSSL_MSG("memory allocation error");
-            return SSL_FAILURE;
-        }
-        XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)));
-
-        /* Alloc and copy WOLFSSL_X509_NAME */
-        node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
-                                              sizeof(WOLFSSL_X509_NAME),
-                                              NULL, DYNAMIC_TYPE_OPENSSL);
-        if (node->data.name == NULL) {
-            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
-            WOLFSSL_MSG("memory allocation error");
-            return SSL_FAILURE;
-        }
-        XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
-        XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
-
-        /* push new node onto head of stack */
-        node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1;
-        node->next = ctx->ca_names;
-        ctx->ca_names = node;
-        return SSL_SUCCESS;
-    }
-    #endif
-
-    #ifndef NO_WOLFSSL_STUB
-    int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
-    {
-        /* TODO:, not needed in goahead */
-        (void)ctx;
-        WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
-        return SSL_NOT_IMPLEMENTED;
-    }
-    #endif
-
-    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
-        && !defined(WC_NO_RNG)
-    static const byte srp_N[] = {
-        0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8,
-        0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF,
-        0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6,
-        0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13,
-        0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B,
-        0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7,
-        0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
-        0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
-        0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC,
-        0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E,
-        0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F,
-        0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
-    };
-    static const byte srp_g[] = {
-        0x02
-    };
-
-    int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
-    {
-        int r = 0;
-        SrpSide srp_side = SRP_CLIENT_SIDE;
-        WC_RNG rng;
-        byte salt[SRP_SALT_SIZE];
-
-        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
-        if (ctx == NULL || ctx->srp == NULL || username==NULL)
-            return SSL_FAILURE;
-
-        if (ctx->method->side == WOLFSSL_SERVER_END){
-            srp_side = SRP_SERVER_SIDE;
-        } else if (ctx->method->side == WOLFSSL_CLIENT_END){
-            srp_side = SRP_CLIENT_SIDE;
-        } else {
-            WOLFSSL_MSG("Init CTX failed");
-            return SSL_FAILURE;
-        }
-
-        if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){
-            WOLFSSL_MSG("Init CTX failed");
-            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
-            wolfSSL_CTX_free(ctx);
-            return SSL_FAILURE;
-        }
-        r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
-                              (word32)XSTRLEN(username));
-        if (r < 0) {
-            WOLFSSL_MSG("fail to set srp username.");
-            return SSL_FAILURE;
-        }
-
-        /* if wolfSSL_CTX_set_srp_password has already been called, */
-        /* execute wc_SrpSetPassword here */
-        if (ctx->srp_password != NULL){
-            if (wc_InitRng(&rng) < 0){
-                WOLFSSL_MSG("wc_InitRng failed");
-                return SSL_FAILURE;
-            }
-            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
-            if (wc_RNG_GenerateBlock(&rng, salt,
-                                     sizeof(salt)/sizeof(salt[0])) <  0){
-                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
-                wc_FreeRng(&rng);
-                return SSL_FAILURE;
-            }
-            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
-                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
-                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
-                WOLFSSL_MSG("wc_SrpSetParam failed");
-                wc_FreeRng(&rng);
-                return SSL_FAILURE;
-            }
-            r = wc_SrpSetPassword(ctx->srp,
-                     (const byte*)ctx->srp_password,
-                     (word32)XSTRLEN((char *)ctx->srp_password));
-            if (r < 0) {
-                WOLFSSL_MSG("fail to set srp password.");
-                return SSL_FAILURE;
-            }
-            wc_FreeRng(&rng);
-            XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
-            ctx->srp_password = NULL;
-        }
-
-        return SSL_SUCCESS;
-    }
-
-    int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
-    {
-        int r;
-        WC_RNG rng;
-        byte salt[SRP_SALT_SIZE];
-
-        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
-        if (ctx == NULL || ctx->srp == NULL || password == NULL)
-            return SSL_FAILURE;
-
-        if (ctx->srp->user != NULL){
-            if (wc_InitRng(&rng) < 0){
-                WOLFSSL_MSG("wc_InitRng failed");
-                return SSL_FAILURE;
-            }
-            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
-            if (wc_RNG_GenerateBlock(&rng, salt,
-                                     sizeof(salt)/sizeof(salt[0])) <  0){
-                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
-                wc_FreeRng(&rng);
-                return SSL_FAILURE;
-            }
-            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
-                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
-                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
-                WOLFSSL_MSG("wc_SrpSetParam failed");
-                wc_FreeRng(&rng);
-                return SSL_FAILURE;
-            }
-            r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
-                                  (word32)XSTRLEN(password));
-            if (r < 0) {
-                WOLFSSL_MSG("wc_SrpSetPassword failed.");
-                wc_FreeRng(&rng);
-                return SSL_FAILURE;
-            }
-            if (ctx->srp_password != NULL){
-                XFREE(ctx->srp_password,NULL,
-                      DYNAMIC_TYPE_SRP);
-                ctx->srp_password = NULL;
-            }
-            wc_FreeRng(&rng);
-        } else {
-            /* save password for wolfSSL_set_srp_username */
-            if (ctx->srp_password != NULL)
-                XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP);
-
-            ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap,
-                                               DYNAMIC_TYPE_SRP);
-            if (ctx->srp_password == NULL){
-                WOLFSSL_MSG("memory allocation error");
-                return SSL_FAILURE;
-            }
-            XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1);
-        }
-        return SSL_SUCCESS;
-    }
-    #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
-
-    /* keyblock size in bytes or -1 */
-    int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
-    {
-        if (ssl == NULL)
-            return WOLFSSL_FATAL_ERROR;
-
-        return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
-                    ssl->specs.hash_size);
-    }
-
-
-    /* store keys returns WOLFSSL_SUCCESS or -1 on error */
-    int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen,
-                                     unsigned char** sr, unsigned int* srLen,
-                                     unsigned char** cr, unsigned int* crLen)
-    {
-        if (ssl == NULL || ssl->arrays == NULL)
-            return WOLFSSL_FATAL_ERROR;
-
-        *ms = ssl->arrays->masterSecret;
-        *sr = ssl->arrays->serverRandom;
-        *cr = ssl->arrays->clientRandom;
-
-        *msLen = SECRET_LEN;
-        *srLen = RAN_LEN;
-        *crLen = RAN_LEN;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
-    void wolfSSL_set_accept_state(WOLFSSL* ssl)
-    {
-        word16 haveRSA = 1;
-        word16 havePSK = 0;
-
-        WOLFSSL_ENTER("SSL_set_accept_state");
-        if (ssl->options.side == WOLFSSL_CLIENT_END) {
-    #ifdef HAVE_ECC
-            ecc_key key;
-            word32 idx = 0;
-
-            if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) {
-                wc_ecc_init(&key);
-                if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key,
-                                               ssl->buffers.key->length) != 0) {
-                    ssl->options.haveECDSAsig = 0;
-                    ssl->options.haveECC = 0;
-                    ssl->options.haveStaticECC = 0;
-                }
-                wc_ecc_free(&key);
-            }
-    #endif
-
-    #ifndef NO_DH
-            if (!ssl->options.haveDH && ssl->ctx->haveDH) {
-                ssl->buffers.serverDH_P = ssl->ctx->serverDH_P;
-                ssl->buffers.serverDH_G = ssl->ctx->serverDH_G;
-                ssl->options.haveDH = 1;
-            }
-    #endif
-        }
-        ssl->options.side = WOLFSSL_SERVER_END;
-        /* reset suites in case user switched */
-
-        #ifdef NO_RSA
-            haveRSA = 0;
-        #endif
-        #ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-        #endif
-        InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA,
-                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
-                   ssl->options.haveECDSAsig, ssl->options.haveECC,
-                   ssl->options.haveStaticECC, ssl->options.side);
-    }
-
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
-
-    /* return true if connection established */
-    int wolfSSL_is_init_finished(WOLFSSL* ssl)
-    {
-        if (ssl == NULL)
-            return 0;
-
-        if (ssl->options.handShakeState == HANDSHAKE_DONE)
-            return 1;
-
-        return 0;
-    }
-
-#ifdef OPENSSL_EXTRA
-
-    void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
-                                      WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
-    {
-        /* wolfSSL verifies all these internally */
-        (void)ctx;
-        (void)f;
-    }
-
-
-    void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt)
-    {
-        WOLFSSL_ENTER("wolfSSL_set_shutdown");
-        if(ssl==NULL) {
-            WOLFSSL_MSG("Shutdown not set. ssl is null");
-            return;
-        }
-
-        ssl->options.sentNotify =  (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
-        ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
-    }
-
-
-    long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_CTX_get_options");
-        WOLFSSL_MSG("wolfSSL options are set through API calls and macros");
-        if(ctx == NULL)
-            return BAD_FUNC_ARG;
-        return ctx->mask;
-    }
-
-    static long wolf_set_options(long old_op, long op);
-    long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_options");
-
-        if (ctx == NULL)
-            return BAD_FUNC_ARG;
-
-        ctx->mask = wolf_set_options(ctx->mask, opt);
-
-        return ctx->mask;
-    }
-
-    long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt)
-    {
-        WOLFSSL_ENTER("SSL_CTX_clear_options");
-        if(ctx == NULL)
-            return BAD_FUNC_ARG;
-        ctx->mask &= ~opt;
-        return ctx->mask;
-    }
-
-    int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
-    {
-        WOLFSSL_ENTER("SSL_set_rfd");
-        ssl->rfd = rfd;      /* not used directly to allow IO callbacks */
-
-        ssl->IOCB_ReadCtx  = &ssl->rfd;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd)
-    {
-        WOLFSSL_ENTER("SSL_set_wfd");
-        ssl->wfd = wfd;      /* not used directly to allow IO callbacks */
-
-        ssl->IOCB_WriteCtx  = &ssl->wfd;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-
-
-#ifndef NO_CERTS
-    WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
-    {
-        if (ctx == NULL) {
-            return NULL;
-        }
-
-        return &ctx->x509_store;
-    }
-
-
-    void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
-    {
-        if (ctx == NULL || str == NULL) {
-            return;
-        }
-
-        /* free cert manager if have one */
-        if (ctx->cm != NULL) {
-            wolfSSL_CertManagerFree(ctx->cm);
-        }
-        ctx->cm               = str->cm;
-        ctx->x509_store.cache = str->cache;
-        ctx->x509_store_pt    = str; /* take ownership of store and free it
-                                        with CTX free */
-    }
-
-
-    WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
-                                                    WOLFSSL_X509_STORE_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert");
-        if (ctx)
-            return ctx->current_cert;
-        return NULL;
-    }
-
-
-    int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error");
-        if (ctx != NULL)
-            return ctx->error;
-        return 0;
-    }
-
-
-    int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth");
-        if(ctx)
-            return ctx->error_depth;
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
-                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb");
-        if(ctx == NULL)
-            return;
-        ctx->verify_cb = verify_cb;
-    }
-#endif /* !NO_CERTS */
-
-    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void)
-    {
-        static WOLFSSL_BIO_METHOD meth;
-
-        WOLFSSL_ENTER("BIO_f_buffer");
-        meth.type = WOLFSSL_BIO_BUFFER;
-
-        return &meth;
-    }
-
-    #ifndef NO_WOLFSSL_STUB
-    long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size)
-    {
-        /* wolfSSL has internal buffer, compatibility only */
-        WOLFSSL_ENTER("BIO_set_write_buffer_size");
-        WOLFSSL_STUB("BIO_set_write_buffer_size");
-        (void)bio;
-        return size;
-    }
-    #endif
-
-    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void)
-    {
-        static WOLFSSL_BIO_METHOD bio_meth;
-
-        WOLFSSL_ENTER("wolfSSL_BIO_f_bio");
-        bio_meth.type = WOLFSSL_BIO_BIO;
-
-        return &bio_meth;
-    }
-
-
-#ifndef NO_FILESYSTEM
-    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void)
-    {
-        static WOLFSSL_BIO_METHOD file_meth;
-
-        WOLFSSL_ENTER("wolfSSL_BIO_f_file");
-        file_meth.type = WOLFSSL_BIO_FILE;
-
-        return &file_meth;
-    }
-#endif
-
-
-    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void)
-    {
-        static WOLFSSL_BIO_METHOD meth;
-
-        WOLFSSL_ENTER("BIO_f_ssl");
-        meth.type = WOLFSSL_BIO_SSL;
-
-        return &meth;
-    }
-
-
-    WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void)
-    {
-        static WOLFSSL_BIO_METHOD meth;
-
-        WOLFSSL_ENTER("BIO_s_socket");
-        meth.type = WOLFSSL_BIO_SOCKET;
-
-        return &meth;
-    }
-
-
-    WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF)
-    {
-        WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
-
-        WOLFSSL_ENTER("BIO_new_socket");
-        if (bio) {
-            bio->type  = WOLFSSL_BIO_SOCKET;
-            bio->close = (byte)closeF;
-            bio->fd    = sfd;
-        }
-        return bio;
-    }
-
-
-    int wolfSSL_BIO_eof(WOLFSSL_BIO* b)
-    {
-        WOLFSSL_ENTER("BIO_eof");
-        if (b->eof)
-            return 1;
-
-        return 0;
-    }
-
-
-    long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
-    {
-        WOLFSSL_ENTER("wolfSSL_BIO_set_ssl");
-
-        if (b != NULL) {
-            b->ssl   = ssl;
-            b->close = (byte)closeF;
-    /* add to ssl for bio free if SSL_free called before/instead of free_all? */
-        }
-
-        return 0;
-    }
-
-
-    long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF)
-    {
-        WOLFSSL_ENTER("wolfSSL_BIO_set_fd");
-
-        if (b != NULL) {
-            b->fd    = fd;
-            b->close = (byte)closeF;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method)
-    {
-        WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
-                                                DYNAMIC_TYPE_OPENSSL);
-        WOLFSSL_ENTER("wolfSSL_BIO_new");
-        if (bio) {
-            XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
-            bio->type   = method->type;
-            bio->close  = BIO_CLOSE; /* default to close things */
-            if (method->type != WOLFSSL_BIO_FILE &&
-                    method->type != WOLFSSL_BIO_SOCKET) {
-                bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM),
-                                                       0, DYNAMIC_TYPE_OPENSSL);
-                if (bio->mem_buf == NULL) {
-                    WOLFSSL_MSG("Memory error");
-                    wolfSSL_BIO_free(bio);
-                    return NULL;
-                }
-                bio->mem_buf->data = (char*)bio->mem;
-            }
-        }
-        return bio;
-    }
-
-
-    int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
-    {
-        WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data");
-
-        if (bio == NULL || p == NULL)
-            return WOLFSSL_FATAL_ERROR;
-
-        *(byte **)p = bio->mem;
-
-        return bio->memLen;
-    }
-
-
-    WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len)
-    {
-        WOLFSSL_BIO* bio = NULL;
-
-        if (buf == NULL || len < 0) {
-            return bio;
-        }
-
-        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
-        if (bio == NULL) {
-            return bio;
-        }
-
-        bio->memLen = bio->wrSz = len;
-        bio->mem    = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
-        if (bio->mem == NULL) {
-            wolfSSL_BIO_free(bio);
-            return NULL;
-        }
-        if (bio->mem_buf != NULL) {
-            bio->mem_buf->data = (char*)bio->mem;
-            bio->mem_buf->length = bio->memLen;
-        }
-
-        XMEMCPY(bio->mem, buf, len);
-
-        return bio;
-    }
-
-    /*
-     * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up
-     *        to the application.
-     */
-    int wolfSSL_BIO_free(WOLFSSL_BIO* bio)
-    {
-        /* unchain?, doesn't matter in goahead since from free all */
-        WOLFSSL_ENTER("wolfSSL_BIO_free");
-        if (bio) {
-            /* remove from pair by setting the paired bios pair to NULL */
-            if (bio->pair != NULL) {
-                bio->pair->pair = NULL;
-            }
-
-            if (bio->close) {
-                if (bio->ssl)
-                    wolfSSL_free(bio->ssl);
-                if (bio->fd)
-                    CloseSocket(bio->fd);
-            }
-
-        #ifndef NO_FILESYSTEM
-            if (bio->type == WOLFSSL_BIO_FILE && bio->close == BIO_CLOSE) {
-                if (bio->file) {
-                    XFCLOSE(bio->file);
-                }
-            }
-        #endif
-
-            if (bio->close != BIO_NOCLOSE) {
-                if (bio->mem != NULL) {
-                    if (bio->mem_buf != NULL) {
-                        if (bio->mem_buf->data != (char*)bio->mem) {
-                            XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-                            bio->mem = NULL;
-                        }
-                    }
-                    else {
-                        XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-                        bio->mem = NULL;
-                    }
-                }
-                if (bio->mem_buf != NULL) {
-                    wolfSSL_BUF_MEM_free(bio->mem_buf);
-                    bio->mem_buf = NULL;
-                }
-            }
-
-            XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
-        }
-        return 0;
-    }
-
-
-    int wolfSSL_BIO_free_all(WOLFSSL_BIO* bio)
-    {
-        WOLFSSL_ENTER("BIO_free_all");
-        while (bio) {
-            WOLFSSL_BIO* next = bio->next;
-            wolfSSL_BIO_free(bio);
-            bio = next;
-        }
-        return 0;
-    }
-
-
-    WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append)
-    {
-        WOLFSSL_ENTER("BIO_push");
-        top->next    = append;
-        append->prev = top;
-
-        return top;
-    }
-
-
-    int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
-    {
-        /* for wolfSSL no flushing needed */
-        WOLFSSL_ENTER("BIO_flush");
-        (void)bio;
-        return 1;
-    }
-#endif /* OPENSSL_EXTRA */
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-
-    void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
-                                                   void* userdata)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
-        ctx->passwd_userdata = userdata;
-    }
-
-
-    void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
-        if (ctx != NULL) {
-            ctx->passwd_cb = cb;
-        }
-    }
-
-    pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
-    {
-        if (ctx == NULL || ctx->passwd_cb == NULL) {
-            return NULL;
-        }
-
-        return ctx->passwd_cb;
-    }
-
-
-    void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
-    {
-        if (ctx == NULL) {
-            return NULL;
-        }
-
-        return ctx->passwd_userdata;
-    }
-
-#if !defined(NO_PWDBASED) && (defined(OPENSSL_EXTRA) || \
-        defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER))
-
-    int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type,
-                       const WOLFSSL_EVP_MD* md, const byte* salt,
-                       const byte* data, int sz, int count, byte* key, byte* iv)
-    {
-        int ret;
-        int hashType = WC_HASH_TYPE_NONE;
-    #ifdef WOLFSSL_SMALL_STACK
-        EncryptedInfo* info = NULL;
-    #else
-        EncryptedInfo  info[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
-                                       DYNAMIC_TYPE_ENCRYPTEDINFO);
-        if (info == NULL) {
-            WOLFSSL_MSG("malloc failed");
-            return WOLFSSL_FAILURE;
-        }
-    #endif
-
-        XMEMSET(info, 0, sizeof(EncryptedInfo));
-        info->ivSz = EVP_SALT_SIZE;
-
-        ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL);
-        if (ret == 0)
-            ret = wc_EncryptedInfoGet(info, type);
-        if (ret == 0)
-            ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt,
-                               EVP_SALT_SIZE, count, hashType, NULL);
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-    #endif
-
-        if (ret <= 0)
-            return 0; /* failure - for compatibility */
-
-        return ret;
-    }
-
-#endif /* !NO_PWDBASED && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER) */
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-    int wolfSSL_num_locks(void)
-    {
-        return 0;
-    }
-
-    void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
-    {
-        WOLFSSL_ENTER("wolfSSL_set_locking_callback");
-
-        if (wc_SetMutexCb(f) != 0) {
-            WOLFSSL_MSG("Error when setting mutex call back");
-        }
-    }
-
-
-    typedef unsigned long (idCb)(void);
-    static idCb* inner_idCb = NULL;
-
-    unsigned long wolfSSL_thread_id(void)
-    {
-        if (inner_idCb != NULL) {
-            return inner_idCb();
-        }
-        else {
-            return 0;
-        }
-    }
-
-
-    void wolfSSL_set_id_callback(unsigned long (*f)(void))
-    {
-        inner_idCb = f;
-    }
-
-    unsigned long wolfSSL_ERR_get_error(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_ERR_get_error");
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-        {
-            unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL,
-                                                                 NULL, NULL);
-            wc_RemoveErrorNode(-1);
-            return ret;
-        }
-#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
-        {
-            int ret = wc_PullErrorNode(NULL, NULL, NULL);
-
-            if (ret < 0) {
-                if (ret == BAD_STATE_E) return 0; /* no errors in queue */
-                WOLFSSL_MSG("Error with pulling error node!");
-                WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret);
-                ret = 0 - ret; /* return absolute value of error */
-
-                /* panic and try to clear out nodes */
-                wc_ClearErrorNodes();
-            }
-
-            return (unsigned long)ret;
-        }
-#else
-        return (unsigned long)(0 - NOT_COMPILED_IN);
-#endif
-    }
-
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
-
-
-#ifdef OPENSSL_EXTRA
-
-#if !defined(NO_WOLFSSL_SERVER)
-size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out,
-                                                                   size_t outSz)
-{
-    size_t size;
-
-    /* return max size of buffer */
-    if (outSz == 0) {
-        return RAN_LEN;
-    }
-
-    if (ssl == NULL || out == NULL) {
-        return 0;
-    }
-
-    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
-        WOLFSSL_MSG("Arrays struct not saved after handshake");
-        return 0;
-    }
-
-    if (outSz > RAN_LEN) {
-        size = RAN_LEN;
-    }
-    else {
-        size = outSz;
-    }
-
-    XMEMCPY(out, ssl->arrays->serverRandom, size);
-    return size;
-}
-#endif /* !defined(NO_WOLFSSL_SERVER) */
-
-
-#if !defined(NO_WOLFSSL_CLIENT)
-/* Return the amount of random bytes copied over or error case.
- * ssl : ssl struct after handshake
- * out : buffer to hold random bytes
- * outSz : either 0 (return max buffer sz) or size of out buffer
- *
- * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information.
- */
-size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
-                                                                   size_t outSz)
-{
-    size_t size;
-
-    /* return max size of buffer */
-    if (outSz == 0) {
-        return RAN_LEN;
-    }
-
-    if (ssl == NULL || out == NULL) {
-        return 0;
-    }
-
-    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
-        WOLFSSL_MSG("Arrays struct not saved after handshake");
-        return 0;
-    }
-
-    if (outSz > RAN_LEN) {
-        size = RAN_LEN;
-    }
-    else {
-        size = outSz;
-    }
-
-    XMEMCPY(out, ssl->arrays->clientRandom, size);
-    return size;
-}
-#endif /* !NO_WOLFSSL_CLIENT */
-
-
-    unsigned long wolfSSLeay(void)
-    {
-        return SSLEAY_VERSION_NUMBER;
-    }
-
-
-    const char* wolfSSLeay_version(int type)
-    {
-        static const char* version = "SSLeay wolfSSL compatibility";
-        (void)type;
-        return version;
-    }
-
-
-#ifndef NO_MD5
-    int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
-    {
-        int ret;
-        typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1];
-        (void)sizeof(md5_test);
-
-        WOLFSSL_ENTER("MD5_Init");
-        ret = wc_InitMd5((wc_Md5*)md5);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
-                           unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("wolfSSL_MD5_Update");
-        ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("MD5_Final");
-        ret = wc_Md5Final((wc_Md5*)md5, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-#endif /* !NO_MD5 */
-
-
-#ifndef NO_SHA
-    int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
-    {
-        int ret;
-
-        typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1];
-        (void)sizeof(sha_test);
-
-        WOLFSSL_ENTER("SHA_Init");
-        ret = wc_InitSha((wc_Sha*)sha);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
-                           unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA_Update");
-        ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA_Final");
-        ret = wc_ShaFinal((wc_Sha*)sha, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
-    {
-        WOLFSSL_ENTER("SHA1_Init");
-        return SHA_Init(sha);
-    }
-
-
-    int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
-                            unsigned long sz)
-    {
-        WOLFSSL_ENTER("SHA1_Update");
-        return SHA_Update(sha, input, sz);
-    }
-
-
-    int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha)
-    {
-        WOLFSSL_ENTER("SHA1_Final");
-        return SHA_Final(input, sha);
-    }
-#endif /* !NO_SHA */
-
-#ifdef WOLFSSL_SHA224
-
-    int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha)
-    {
-        int ret;
-
-        typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1];
-        (void)sizeof(sha_test);
-
-        WOLFSSL_ENTER("SHA224_Init");
-        ret = wc_InitSha224((wc_Sha224*)sha);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input,
-                           unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA224_Update");
-        ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA224_Final");
-        ret = wc_Sha224Final((wc_Sha224*)sha, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-#endif /* WOLFSSL_SHA224 */
-
-
-    int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
-    {
-        int ret;
-
-        typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1];
-        (void)sizeof(sha_test);
-
-        WOLFSSL_ENTER("SHA256_Init");
-        ret = wc_InitSha256((wc_Sha256*)sha256);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
-                              unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA256_Update");
-        ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA256_Final");
-        ret = wc_Sha256Final((wc_Sha256*)sha, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-#ifdef WOLFSSL_SHA384
-
-    int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
-    {
-        int ret;
-
-        typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1];
-        (void)sizeof(sha_test);
-
-        WOLFSSL_ENTER("SHA384_Init");
-        ret = wc_InitSha384((wc_Sha384*)sha);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
-                           unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA384_Update");
-        ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA384_Final");
-        ret = wc_Sha384Final((wc_Sha384*)sha, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-#endif /* WOLFSSL_SHA384 */
-
-
-#ifdef WOLFSSL_SHA512
-
-    int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
-    {
-        int ret;
-
-        typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1];
-        (void)sizeof(sha_test);
-
-        WOLFSSL_ENTER("SHA512_Init");
-        ret = wc_InitSha512((wc_Sha512*)sha);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
-                           unsigned long sz)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA512_Update");
-        ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-
-    int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("SHA512_Final");
-        ret = wc_Sha512Final((wc_Sha512*)sha, input);
-
-        /* return 1 on success, 0 otherwise */
-        if (ret == 0)
-            return 1;
-
-        return 0;
-    }
-
-#endif /* WOLFSSL_SHA512 */
-
-    static const struct s_ent {
-        const unsigned char macType;
-        const char *name;
-    } md_tbl[] = {
-    #ifndef NO_MD4
-         {MD4, "MD4"},
-    #endif /* NO_MD4 */
-
-    #ifndef NO_MD5
-        {WC_MD5, "MD5"},
-    #endif /* NO_MD5 */
-
-    #ifndef NO_SHA
-        {WC_SHA, "SHA"},
-    #endif /* NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        {WC_SHA224, "SHA224"},
-    #endif /* WOLFSSL_SHA224 */
-    #ifndef NO_SHA256
-        {WC_SHA256, "SHA256"},
-    #endif
-
-    #ifdef WOLFSSL_SHA384
-        {WC_SHA384, "SHA384"},
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        {WC_SHA512, "SHA512"},
-    #endif /* WOLFSSL_SHA512 */
-        {0, NULL}
-    };
-
-const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name)
-{
-    static const struct alias {
-        const char *name;
-        const char *alias;
-    } alias_tbl[] =
-    {
-        {"MD4", "ssl3-md4"},
-        {"MD5", "ssl3-md5"},
-        {"SHA", "ssl3-sha1"},
-        {"SHA", "SHA1"},
-        { NULL, NULL}
-    };
-
-    const struct alias  *al;
-    const struct s_ent *ent;
-
-    for (al = alias_tbl; al->name != NULL; al++)
-        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
-            name = al->name;
-            break;
-        }
-
-    for (ent = md_tbl; ent->name != NULL; ent++)
-        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
-            return (EVP_MD *)ent->name;
-        }
-    return NULL;
-}
-
-static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type)
-{
-    const struct s_ent *ent ;
-    WOLFSSL_ENTER("EVP_get_md");
-    for( ent = md_tbl; ent->name != NULL; ent++){
-        if(type == ent->macType) {
-            return (WOLFSSL_EVP_MD *)ent->name;
-        }
-    }
-    return (WOLFSSL_EVP_MD *)"";
-}
-
-int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
-{
-    const struct s_ent *ent ;
-    WOLFSSL_ENTER("EVP_MD_type");
-    for( ent = md_tbl; ent->name != NULL; ent++){
-        if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) {
-            return ent->macType;
-        }
-    }
-    return 0;
-}
-
-
-#ifndef NO_MD4
-
-    /* return a pointer to MD4 EVP type */
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_md4");
-        return EVP_get_digestbyname("MD4");
-    }
-
-#endif /* !NO_MD4 */
-
-
-#ifndef NO_MD5
-
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void)
-    {
-        WOLFSSL_ENTER("EVP_md5");
-        return EVP_get_digestbyname("MD5");
-    }
-
-#endif /* !NO_MD5 */
-
-
-#ifndef NO_SHA
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void)
-    {
-        WOLFSSL_ENTER("EVP_sha1");
-        return EVP_get_digestbyname("SHA");
-    }
-#endif /* NO_SHA */
-
-#ifdef WOLFSSL_SHA224
-
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void)
-    {
-        WOLFSSL_ENTER("EVP_sha224");
-        return EVP_get_digestbyname("SHA224");
-    }
-
-#endif /* WOLFSSL_SHA224 */
-
-
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void)
-    {
-        WOLFSSL_ENTER("EVP_sha256");
-        return EVP_get_digestbyname("SHA256");
-    }
-
-#ifdef WOLFSSL_SHA384
-
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void)
-    {
-        WOLFSSL_ENTER("EVP_sha384");
-        return EVP_get_digestbyname("SHA384");
-    }
-
-#endif /* WOLFSSL_SHA384 */
-
-#ifdef WOLFSSL_SHA512
-
-    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void)
-    {
-        WOLFSSL_ENTER("EVP_sha512");
-        return EVP_get_digestbyname("SHA512");
-    }
-
-#endif /* WOLFSSL_SHA512 */
-
-
-    WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void)
-    {
-        WOLFSSL_EVP_MD_CTX* ctx;
-        WOLFSSL_ENTER("EVP_MD_CTX_new");
-        ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL,
-                                                       DYNAMIC_TYPE_OPENSSL);
-        if (ctx){
-            wolfSSL_EVP_MD_CTX_init(ctx);
-        }
-        return ctx;
-    }
-
-    WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx)
-    {
-        if (ctx) {
-            WOLFSSL_ENTER("EVP_MD_CTX_free");
-                wolfSSL_EVP_MD_CTX_cleanup(ctx);
-                XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
-            }
-    }
-
-
-    /* returns the type of message digest used by the ctx */
-    int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) {
-        WOLFSSL_ENTER("EVP_MD_CTX_type");
-        return ctx->macType;
-    }
-
-
-    /* returns WOLFSSL_SUCCESS on success */
-    int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
-    {
-        return wolfSSL_EVP_MD_CTX_copy_ex(out, in);
-    }
-
-
-    /* copies structure in to the structure out
-     *
-     * returns WOLFSSL_SUCCESS on success */
-    int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
-    {
-        if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE;
-        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex");
-        XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX));
-        return WOLFSSL_SUCCESS;
-    }
-
-    void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx)
-    {
-        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init");
-        XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX));
-    }
-
-    const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx)
-    {
-        if (ctx == NULL)
-            return NULL;
-        WOLFSSL_ENTER("EVP_MD_CTX_md");
-        return (const WOLFSSL_EVP_MD *)wolfSSL_EVP_get_md(ctx->macType);
-    }
-
-    #ifndef NO_AES
-
-    #ifdef HAVE_AES_CBC
-    #ifdef WOLFSSL_AES_128
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc");
-        if (EVP_AES_128_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_128_CBC;
-    }
-    #endif /* WOLFSSL_AES_128 */
-
-
-    #ifdef WOLFSSL_AES_192
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc");
-        if (EVP_AES_192_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_192_CBC;
-    }
-    #endif /* WOLFSSL_AES_192 */
-
-
-    #ifdef WOLFSSL_AES_256
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc");
-        if (EVP_AES_256_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_256_CBC;
-    }
-    #endif /* WOLFSSL_AES_256 */
-    #endif /* HAVE_AES_CBC */
-
-
-    #ifdef WOLFSSL_AES_128
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr");
-        if (EVP_AES_128_CTR == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_128_CTR;
-    }
-    #endif /* WOLFSSL_AES_2128 */
-
-
-    #ifdef WOLFSSL_AES_192
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr");
-        if (EVP_AES_192_CTR == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_192_CTR;
-    }
-    #endif /* WOLFSSL_AES_192 */
-
-
-    #ifdef WOLFSSL_AES_256
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr");
-        if (EVP_AES_256_CTR == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_256_CTR;
-    }
-    #endif /* WOLFSSL_AES_256 */
-
-    #ifdef WOLFSSL_AES_128
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb");
-        if (EVP_AES_128_ECB == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_128_ECB;
-    }
-    #endif /* WOLFSSL_AES_128 */
-
-
-    #ifdef WOLFSSL_AES_192
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb");
-        if (EVP_AES_192_ECB == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_192_ECB;
-    }
-    #endif /* WOLFSSL_AES_192*/
-
-
-    #ifdef WOLFSSL_AES_256
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb");
-        if (EVP_AES_256_ECB == NULL)
-            wolfSSL_EVP_init();
-        return EVP_AES_256_ECB;
-    }
-    #endif /* WOLFSSL_AES_256 */
-    #endif /* NO_AES */
-
-#ifndef NO_DES3
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_des_cbc");
-        if (EVP_DES_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_DES_CBC;
-    }
-#ifdef WOLFSSL_DES_ECB
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_des_ecb");
-        if (EVP_DES_ECB == NULL)
-            wolfSSL_EVP_init();
-        return EVP_DES_ECB;
-    }
-#endif
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc");
-        if (EVP_DES_EDE3_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_DES_EDE3_CBC;
-    }
-#ifdef WOLFSSL_DES_ECB
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb");
-        if (EVP_DES_EDE3_ECB == NULL)
-            wolfSSL_EVP_init();
-        return EVP_DES_EDE3_ECB;
-    }
-#endif
-#endif /* NO_DES3 */
-
-#ifndef NO_RC4
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void)
-    {
-        static const char* type = "ARC4";
-        WOLFSSL_ENTER("wolfSSL_EVP_rc4");
-        return type;
-    }
-#endif
-
-#ifdef HAVE_IDEA
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc");
-        if (EVP_IDEA_CBC == NULL)
-            wolfSSL_EVP_init();
-        return EVP_IDEA_CBC;
-    }
-#endif
-    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
-    {
-        static const char* type = "NULL";
-        WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
-        return type;
-    }
-
-
-    int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx)
-    {
-        WOLFSSL_ENTER("EVP_MD_CTX_cleanup");
-        ForceZero(ctx, sizeof(*ctx));
-        ctx->macType = 0xFF;
-        return 1;
-    }
-
-
-
-    void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx)
-    {
-        WOLFSSL_ENTER("EVP_CIPHER_CTX_init");
-        if (ctx) {
-            ctx->cipherType = 0xff;   /* no init */
-            ctx->keyLen     = 0;
-            ctx->enc        = 1;      /* start in encrypt mode */
-        }
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx)
-    {
-        WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup");
-        if (ctx) {
-            ctx->cipherType = 0xff;  /* no more init */
-            ctx->keyLen     = 0;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
-    int  wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                               const WOLFSSL_EVP_CIPHER* type, const byte* key,
-                               const byte* iv, int enc)
-    {
-        int ret = 0;
-        (void)key;
-        (void)iv;
-        (void)enc;
-
-        WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
-        if (ctx == NULL) {
-            WOLFSSL_MSG("no ctx");
-            return 0;   /* failure */
-        }
-
-        if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) {
-            WOLFSSL_MSG("no type set");
-            return 0;   /* failure */
-        }
-        if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){
-            ctx->bufUsed = 0;
-            ctx->lastUsed = 0;
-            ctx->flags   = 0;
-        }
-#ifndef NO_AES
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-        if (ctx->cipherType == AES_128_CBC_TYPE ||
-            (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_128_CBC");
-            ctx->cipherType = AES_128_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = 16;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        #endif /* WOLFSSL_AES_128 */
-        #ifdef WOLFSSL_AES_192
-        if (ctx->cipherType == AES_192_CBC_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_192_CBC");
-            ctx->cipherType = AES_192_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = 24;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        #endif /* WOLFSSL_AES_192 */
-        #ifdef WOLFSSL_AES_256
-        if (ctx->cipherType == AES_256_CBC_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_256_CBC");
-            ctx->cipherType = AES_256_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = 32;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-                if (ret != 0){
-                    WOLFSSL_MSG("wc_AesSetKey() failed");
-                    return ret;
-                }
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0){
-                    WOLFSSL_MSG("wc_AesSetIV() failed");
-                    return ret;
-                }
-            }
-        }
-        #endif /* WOLFSSL_AES_256 */
-    #endif /* HAVE_AES_CBC */
-#ifdef WOLFSSL_AES_COUNTER
-        #ifdef WOLFSSL_AES_128
-        if (ctx->cipherType == AES_128_CTR_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_128_CTR");
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->cipherType = AES_128_CTR_TYPE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
-            ctx->keyLen     = 16;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-              ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                    AES_ENCRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        #endif /* WOLFSSL_AES_128 */
-        #ifdef WOLFSSL_AES_192
-        if (ctx->cipherType == AES_192_CTR_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_192_CTR");
-            ctx->cipherType = AES_192_CTR_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
-            ctx->keyLen     = 24;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                      AES_ENCRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        #endif /* WOLFSSL_AES_192 */
-        #ifdef WOLFSSL_AES_256
-        if (ctx->cipherType == AES_256_CTR_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_256_CTR");
-            ctx->cipherType = AES_256_CTR_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
-            ctx->keyLen     = 32;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
-                      AES_ENCRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-            if (iv && key == NULL) {
-                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        #endif /* WOLFSSL_AES_256 */
-#endif /* WOLFSSL_AES_COUNTER */
-        #ifdef WOLFSSL_AES_128
-        if (ctx->cipherType == AES_128_ECB_TYPE ||
-            (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_128_ECB");
-            ctx->cipherType = AES_128_ECB_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
-            ctx->keyLen     = 16;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
-                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-            }
-            if (ret != 0)
-                return ret;
-        }
-        #endif /* WOLFSSL_AES_128 */
-        #ifdef WOLFSSL_AES_192
-        if (ctx->cipherType == AES_192_ECB_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_192_ECB");
-            ctx->cipherType = AES_192_ECB_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
-            ctx->keyLen     = 24;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
-                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-            }
-            if (ret != 0)
-                return ret;
-        }
-        #endif /* WOLFSSL_AES_192 */
-        #ifdef WOLFSSL_AES_256
-        if (ctx->cipherType == AES_256_ECB_TYPE ||
-                 (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_AES_256_ECB");
-            ctx->cipherType = AES_256_ECB_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
-            ctx->keyLen     = 32;
-            ctx->block_size = AES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-              ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
-                    ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
-            }
-            if (ret != 0)
-                return ret;
-        }
-        #endif /* WOLFSSL_AES_256 */
-#endif /* NO_AES */
-
-#ifndef NO_DES3
-        if (ctx->cipherType == DES_CBC_TYPE ||
-                 (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_DES_CBC");
-            ctx->cipherType = DES_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = 8;
-            ctx->block_size = DES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_Des_SetKey(&ctx->cipher.des, key, iv,
-                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-
-            if (iv && key == NULL)
-                wc_Des_SetIV(&ctx->cipher.des, iv);
-        }
-#ifdef WOLFSSL_DES_ECB
-        else if (ctx->cipherType == DES_ECB_TYPE ||
-                 (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_DES_ECB");
-            ctx->cipherType = DES_ECB_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
-            ctx->keyLen     = 8;
-            ctx->block_size = DES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                WOLFSSL_MSG("Des_SetKey");
-                ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL,
-                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-#endif
-        else if (ctx->cipherType == DES_EDE3_CBC_TYPE ||
-                 (type &&
-                  XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_DES_EDE3_CBC");
-            ctx->cipherType = DES_EDE3_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = 24;
-            ctx->block_size = DES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv,
-                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-
-            if (iv && key == NULL) {
-                ret = wc_Des3_SetIV(&ctx->cipher.des3, iv);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-        else if (ctx->cipherType == DES_EDE3_ECB_TYPE ||
-                 (type &&
-                  XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_DES_EDE3_ECB");
-            ctx->cipherType = DES_EDE3_ECB_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
-            ctx->keyLen     = 24;
-            ctx->block_size = DES_BLOCK_SIZE;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL,
-                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-        }
-#endif /* NO_DES3 */
-#ifndef NO_RC4
-        if (ctx->cipherType == ARC4_TYPE || (type &&
-                                     XSTRNCMP(type, "ARC4", 4) == 0)) {
-            WOLFSSL_MSG("ARC4");
-            ctx->cipherType = ARC4_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_STREAM_CIPHER;
-            ctx->block_size = 1;
-            if (ctx->keyLen == 0)  /* user may have already set */
-                ctx->keyLen = 16;  /* default to 128 */
-            if (key)
-                wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen);
-        }
-#endif /* NO_RC4 */
-#ifdef HAVE_IDEA
-        if (ctx->cipherType == IDEA_CBC_TYPE ||
-                 (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) {
-            WOLFSSL_MSG("EVP_IDEA_CBC");
-            ctx->cipherType = IDEA_CBC_TYPE;
-            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
-            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
-            ctx->keyLen     = IDEA_KEY_SIZE;
-            ctx->block_size = 8;
-            if (enc == 0 || enc == 1)
-                ctx->enc = enc ? 1 : 0;
-            if (key) {
-                ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen,
-                                    iv, ctx->enc ? IDEA_ENCRYPTION :
-                                                   IDEA_DECRYPTION);
-                if (ret != 0)
-                    return ret;
-            }
-
-            if (iv && key == NULL)
-                wc_IdeaSetIV(&ctx->cipher.idea, iv);
-        }
-#endif /* HAVE_IDEA */
-        if (ctx->cipherType == NULL_CIPHER_TYPE || (type &&
-                                     XSTRNCMP(type, "NULL", 4) == 0)) {
-            WOLFSSL_MSG("NULL cipher");
-            ctx->cipherType = NULL_CIPHER_TYPE;
-            ctx->keyLen = 0;
-            ctx->block_size = 16;
-        }
-        (void)ret; /* remove warning. If execution reaches this point, ret=0 */
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length");
-        if (ctx)
-            return ctx->keyLen;
-
-        return 0;   /* failure */
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                             int keylen)
-    {
-        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length");
-        if (ctx)
-            ctx->keyLen = keylen;
-        else
-            return 0;  /* failure */
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
-                          word32 len)
-    {
-        int ret = 0;
-        WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
-
-        if (ctx == NULL || dst == NULL || src == NULL) {
-            WOLFSSL_MSG("Bad function argument");
-            return 0;  /* failure */
-        }
-
-        if (ctx->cipherType == 0xff) {
-            WOLFSSL_MSG("no init");
-            return 0;  /* failure */
-        }
-
-        switch (ctx->cipherType) {
-
-#ifndef NO_AES
-#ifdef HAVE_AES_CBC
-            case AES_128_CBC_TYPE :
-            case AES_192_CBC_TYPE :
-            case AES_256_CBC_TYPE :
-                WOLFSSL_MSG("AES CBC");
-                if (ctx->enc)
-                    ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len);
-                else
-                    ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len);
-                break;
-#endif /* HAVE_AES_CBC */
-#ifdef HAVE_AES_ECB
-            case AES_128_ECB_TYPE :
-            case AES_192_ECB_TYPE :
-            case AES_256_ECB_TYPE :
-                WOLFSSL_MSG("AES ECB");
-                if (ctx->enc)
-                    ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len);
-                else
-                    ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len);
-                break;
-#endif
-#ifdef WOLFSSL_AES_COUNTER
-            case AES_128_CTR_TYPE :
-            case AES_192_CTR_TYPE :
-            case AES_256_CTR_TYPE :
-                    WOLFSSL_MSG("AES CTR");
-                    ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
-                break;
-#endif /* WOLFSSL_AES_COUNTER */
-#endif /* NO_AES */
-
-#ifndef NO_DES3
-            case DES_CBC_TYPE :
-                if (ctx->enc)
-                    wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len);
-                else
-                    wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len);
-                break;
-            case DES_EDE3_CBC_TYPE :
-                if (ctx->enc)
-                    ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len);
-                else
-                    ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len);
-                break;
-#ifdef WOLFSSL_DES_ECB
-            case DES_ECB_TYPE :
-                ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len);
-                break;
-            case DES_EDE3_ECB_TYPE :
-                ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len);
-                break;
-#endif
-#endif /* !NO_DES3 */
-
-#ifndef NO_RC4
-            case ARC4_TYPE :
-                wc_Arc4Process(&ctx->cipher.arc4, dst, src, len);
-                break;
-#endif
-
-#ifdef HAVE_IDEA
-            case IDEA_CBC_TYPE :
-                if (ctx->enc)
-                    wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len);
-                else
-                    wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len);
-                break;
-#endif
-            case NULL_CIPHER_TYPE :
-                XMEMCPY(dst, src, len);
-                break;
-
-            default: {
-                WOLFSSL_MSG("bad type");
-                return 0;  /* failure */
-            }
-        }
-
-        if (ret != 0) {
-            WOLFSSL_MSG("wolfSSL_EVP_Cipher failure");
-            return 0;  /* failure */
-        }
-
-        WOLFSSL_MSG("wolfSSL_EVP_Cipher success");
-        return WOLFSSL_SUCCESS;  /* success */
-    }
-
-#define WOLFSSL_EVP_INCLUDED
-#include "wolfcrypt/src/evp.c"
-
-
-    /* store for external read of iv, WOLFSSL_SUCCESS on success */
-    int  wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
-    {
-        WOLFSSL_ENTER("wolfSSL_StoreExternalIV");
-
-        if (ctx == NULL) {
-            WOLFSSL_MSG("Bad function argument");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        switch (ctx->cipherType) {
-
-#ifndef NO_AES
-            case AES_128_CBC_TYPE :
-            case AES_192_CBC_TYPE :
-            case AES_256_CBC_TYPE :
-                WOLFSSL_MSG("AES CBC");
-                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
-                break;
-
-#ifdef WOLFSSL_AES_COUNTER
-            case AES_128_CTR_TYPE :
-            case AES_192_CTR_TYPE :
-            case AES_256_CTR_TYPE :
-                WOLFSSL_MSG("AES CTR");
-                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
-                break;
-#endif /* WOLFSSL_AES_COUNTER */
-
-#endif /* NO_AES */
-
-#ifndef NO_DES3
-            case DES_CBC_TYPE :
-                WOLFSSL_MSG("DES CBC");
-                XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
-                break;
-
-            case DES_EDE3_CBC_TYPE :
-                WOLFSSL_MSG("DES EDE3 CBC");
-                XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
-                break;
-#endif
-
-#ifdef HAVE_IDEA
-            case IDEA_CBC_TYPE :
-                WOLFSSL_MSG("IDEA CBC");
-                XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE);
-                break;
-#endif
-            case ARC4_TYPE :
-                WOLFSSL_MSG("ARC4");
-                break;
-
-            case NULL_CIPHER_TYPE :
-                WOLFSSL_MSG("NULL");
-                break;
-
-            default: {
-                WOLFSSL_MSG("bad type");
-                return WOLFSSL_FATAL_ERROR;
-            }
-        }
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* set internal IV from external, WOLFSSL_SUCCESS on success */
-    int  wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
-    {
-
-        WOLFSSL_ENTER("wolfSSL_SetInternalIV");
-
-        if (ctx == NULL) {
-            WOLFSSL_MSG("Bad function argument");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        switch (ctx->cipherType) {
-
-#ifndef NO_AES
-            case AES_128_CBC_TYPE :
-            case AES_192_CBC_TYPE :
-            case AES_256_CBC_TYPE :
-                WOLFSSL_MSG("AES CBC");
-                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
-                break;
-
-#ifdef WOLFSSL_AES_COUNTER
-            case AES_128_CTR_TYPE :
-            case AES_192_CTR_TYPE :
-            case AES_256_CTR_TYPE :
-                WOLFSSL_MSG("AES CTR");
-                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
-                break;
-#endif
-
-#endif /* NO_AES */
-
-#ifndef NO_DES3
-            case DES_CBC_TYPE :
-                WOLFSSL_MSG("DES CBC");
-                XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
-                break;
-
-            case DES_EDE3_CBC_TYPE :
-                WOLFSSL_MSG("DES EDE3 CBC");
-                XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
-                break;
-#endif
-
-#ifdef HAVE_IDEA
-            case IDEA_CBC_TYPE :
-                WOLFSSL_MSG("IDEA CBC");
-                XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE);
-                break;
-#endif
-            case ARC4_TYPE :
-                WOLFSSL_MSG("ARC4");
-                break;
-
-            case NULL_CIPHER_TYPE :
-                WOLFSSL_MSG("NULL");
-                break;
-
-            default: {
-                WOLFSSL_MSG("bad type");
-                return WOLFSSL_FATAL_ERROR;
-            }
-        }
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx,
-                               const WOLFSSL_EVP_MD* type)
-    {
-        int ret = WOLFSSL_SUCCESS;
-
-        WOLFSSL_ENTER("EVP_DigestInit");
-
-        if (ctx == NULL || type == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        /* compile-time validation of ASYNC_CTX_SIZE */
-        typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ?
-                                                                        1 : -1];
-        (void)sizeof(async_test);
-    #endif
-
-        if (XSTRNCMP(type, "SHA256", 6) == 0) {
-             ctx->macType = WC_SHA256;
-             ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256));
-        }
-    #ifdef WOLFSSL_SHA224
-        else if (XSTRNCMP(type, "SHA224", 6) == 0) {
-             ctx->macType = WC_SHA224;
-             ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224));
-        }
-    #endif
-    #ifdef WOLFSSL_SHA384
-        else if (XSTRNCMP(type, "SHA384", 6) == 0) {
-             ctx->macType = WC_SHA384;
-             ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384));
-        }
-    #endif
-    #ifdef WOLFSSL_SHA512
-        else if (XSTRNCMP(type, "SHA512", 6) == 0) {
-             ctx->macType = WC_SHA512;
-             ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512));
-        }
-    #endif
-    #ifndef NO_MD4
-        else if (XSTRNCMP(type, "MD4", 3) == 0) {
-            ctx->macType = MD4;
-            wolfSSL_MD4_Init(&(ctx->hash.digest.md4));
-        }
-    #endif
-    #ifndef NO_MD5
-        else if (XSTRNCMP(type, "MD5", 3) == 0) {
-            ctx->macType = WC_MD5;
-            ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5));
-        }
-    #endif
-    #ifndef NO_SHA
-        /* has to be last since would pick or 224, 256, 384, or 512 too */
-        else if (XSTRNCMP(type, "SHA", 3) == 0) {
-             ctx->macType = WC_SHA;
-             ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha));
-        }
-    #endif /* NO_SHA */
-        else
-             return BAD_FUNC_ARG;
-
-        return ret;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */
-    int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data,
-                                size_t sz)
-    {
-        WOLFSSL_ENTER("EVP_DigestUpdate");
-
-        switch (ctx->macType) {
-#ifndef NO_MD4
-            case MD4:
-                wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data,
-                                  (unsigned long)sz);
-                break;
-#endif
-#ifndef NO_MD5
-            case WC_MD5:
-                wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
-                                  (unsigned long)sz);
-                break;
-#endif
-#ifndef NO_SHA
-            case WC_SHA:
-                wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
-                                  (unsigned long)sz);
-                break;
-#endif
-#ifdef WOLFSSL_SHA224
-            case WC_SHA224:
-                wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
-                break;
-#endif
-#ifndef NO_SHA256
-            case WC_SHA256:
-                wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
-                break;
-#endif /* !NO_SHA256 */
-#ifdef WOLFSSL_SHA384
-            case WC_SHA384:
-                wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
-                break;
-#endif
-#ifdef WOLFSSL_SHA512
-            case WC_SHA512:
-                wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
-                                     (unsigned long)sz);
-                break;
-#endif /* WOLFSSL_SHA512 */
-            default:
-                return WOLFSSL_FAILURE;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
-                               unsigned int* s)
-    {
-        WOLFSSL_ENTER("EVP_DigestFinal");
-        switch (ctx->macType) {
-#ifndef NO_MD4
-            case MD4:
-                wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash);
-                if (s) *s = MD4_DIGEST_SIZE;
-                break;
-#endif
-#ifndef NO_MD5
-            case WC_MD5:
-                wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
-                if (s) *s = WC_MD5_DIGEST_SIZE;
-                break;
-#endif
-#ifndef NO_SHA
-            case WC_SHA:
-                wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA_DIGEST_SIZE;
-                break;
-#endif
-#ifdef WOLFSSL_SHA224
-            case WC_SHA224:
-                wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA224_DIGEST_SIZE;
-                break;
-#endif
-#ifndef NO_SHA256
-            case WC_SHA256:
-                wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA256_DIGEST_SIZE;
-                break;
-#endif /* !NO_SHA256 */
-#ifdef WOLFSSL_SHA384
-            case WC_SHA384:
-                wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA384_DIGEST_SIZE;
-                break;
-#endif
-#ifdef WOLFSSL_SHA512
-            case WC_SHA512:
-                wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
-                if (s) *s = WC_SHA512_DIGEST_SIZE;
-                break;
-#endif /* WOLFSSL_SHA512 */
-            default:
-                return WOLFSSL_FAILURE;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* WOLFSSL_SUCCESS on ok */
-    int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
-                                   unsigned int* s)
-    {
-        WOLFSSL_ENTER("EVP_DigestFinal_ex");
-        return EVP_DigestFinal(ctx, md, s);
-    }
-
-
-    unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
-                                int key_len, const unsigned char* d, int n,
-                                unsigned char* md, unsigned int* md_len)
-    {
-        int type;
-        int mdlen;
-        unsigned char* ret = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-        Hmac* hmac = NULL;
-#else
-        Hmac  hmac[1];
-#endif
-        void* heap = NULL;
-
-        WOLFSSL_ENTER("wolfSSL_HMAC");
-        if (!md) {
-            WOLFSSL_MSG("Static buffer not supported, pass in md buffer");
-            return NULL;  /* no static buffer support */
-        }
-
-#ifndef NO_MD5
-        if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
-            type = WC_MD5;
-            mdlen = WC_MD5_DIGEST_SIZE;
-        } else
-#endif
-#ifdef WOLFSSL_SHA224
-        if (XSTRNCMP(evp_md, "SHA224", 6) == 0) {
-            type = WC_SHA224;
-            mdlen = WC_SHA224_DIGEST_SIZE;
-        } else
-#endif
-#ifndef NO_SHA256
-        if (XSTRNCMP(evp_md, "SHA256", 6) == 0) {
-            type = WC_SHA256;
-            mdlen = WC_SHA256_DIGEST_SIZE;
-        } else
-#endif
-#ifdef WOLFSSL_SHA384
-        if (XSTRNCMP(evp_md, "SHA384", 6) == 0) {
-            type = WC_SHA384;
-            mdlen = WC_SHA384_DIGEST_SIZE;
-        } else
-#endif
-#ifdef WOLFSSL_SHA512
-        if (XSTRNCMP(evp_md, "SHA512", 6) == 0) {
-            type = WC_SHA512;
-            mdlen = WC_SHA512_DIGEST_SIZE;
-        } else
-#endif
-#ifndef NO_SHA
-        if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
-            type = WC_SHA;
-            mdlen = WC_SHA_DIGEST_SIZE;
-        } else
-#endif
-        {
-            return NULL;
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
-        if (hmac == NULL)
-            return NULL;
-    #endif
-
-        if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) {
-            if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) {
-                if (wc_HmacUpdate(hmac, d, n) == 0) {
-                    if (wc_HmacFinal(hmac, md) == 0) {
-                        if (md_len)
-                            *md_len = mdlen;
-                        ret = md;
-                    }
-                }
-            }
-            wc_HmacFree(hmac);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
-    #endif
-
-        (void)evp_md;
-        return ret;
-    }
-
-    void wolfSSL_ERR_clear_error(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
-
-#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)
-        wc_ClearErrorNodes();
-#endif
-    }
-
-
-    /* frees all nodes in the current threads error queue
-     *
-     * id  thread id. ERR_remove_state is depriciated and id is ignored. The
-     *     current threads queue will be free'd.
-     */
-    void wolfSSL_ERR_remove_state(unsigned long id)
-    {
-        WOLFSSL_ENTER("wolfSSL_ERR_remove_state");
-        (void)id;
-        if (wc_ERR_remove_state() != 0) {
-            WOLFSSL_MSG("Error with removing the state");
-        }
-    }
-
-
-    int wolfSSL_RAND_status(void)
-    {
-        return WOLFSSL_SUCCESS;  /* wolfCrypt provides enough seed internally */
-    }
-
-
-    #ifndef NO_WOLFSSL_STUB
-    void wolfSSL_RAND_add(const void* add, int len, double entropy)
-    {
-        (void)add;
-        (void)len;
-        (void)entropy;
-        WOLFSSL_STUB("RAND_add");
-        /* wolfSSL seeds/adds internally, use explicit RNG if you want
-           to take control */
-    }
-    #endif
-
-#ifndef NO_DES3
-    /* 0 on ok */
-    int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
-                              WOLFSSL_DES_key_schedule* schedule)
-    {
-        WOLFSSL_ENTER("wolfSSL_DES_key_sched");
-
-        if (key == NULL || schedule == NULL) {
-            WOLFSSL_MSG("Null argument passed in");
-        }
-        else {
-            XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
-        }
-
-        return 0;
-    }
-
-
-    /* intended to behave similar to Kerberos mit_des_cbc_cksum
-     * return the last 4 bytes of cipher text */
-    WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
-            WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
-            WOLFSSL_const_DES_cblock* iv)
-    {
-        WOLFSSL_DES_LONG ret;
-        unsigned char* tmp;
-        unsigned char* data   = (unsigned char*)in;
-        long           dataSz = length;
-        byte dynamicFlag = 0; /* when padding the buffer created needs free'd */
-
-        WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
-
-        if (in == NULL || out == NULL || sc == NULL || iv == NULL) {
-            WOLFSSL_MSG("Bad argument passed in");
-            return 0;
-        }
-
-        /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */
-        if (dataSz % DES_BLOCK_SIZE) {
-            dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
-            data = (unsigned char*)XMALLOC(dataSz, NULL,
-                                           DYNAMIC_TYPE_TMP_BUFFER);
-            if (data == NULL) {
-                WOLFSSL_MSG("Issue creating temporary buffer");
-                return 0;
-            }
-            dynamicFlag = 1; /* set to free buffer at end */
-            XMEMCPY(data, in, length);
-            XMEMSET(data + length, 0, dataSz - length); /* padding */
-        }
-
-        tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (tmp == NULL) {
-            WOLFSSL_MSG("Issue creating temporary buffer");
-            if (dynamicFlag == 1) {
-                XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            }
-            return 0;
-        }
-
-        wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc,
-                (WOLFSSL_DES_cblock*)iv, 1);
-        XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
-                DES_BLOCK_SIZE);
-
-        ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)|
-               ((*((unsigned char*)out + 5) & 0xFF) << 16)|
-               ((*((unsigned char*)out + 6) & 0xFF) << 8) |
-               (*((unsigned char*)out + 7) & 0xFF));
-
-        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (dynamicFlag == 1) {
-            XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        }
-
-        return ret;
-    }
-
-
-    void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
-                                 unsigned char* output, long length,
-                                 WOLFSSL_DES_key_schedule* schedule,
-                                 WOLFSSL_DES_cblock* ivec, int enc)
-    {
-        Des myDes;
-        byte lastblock[DES_BLOCK_SIZE];
-        int  lb_sz;
-        long  blk;
-
-        WOLFSSL_ENTER("DES_cbc_encrypt");
-
-        /* OpenSSL compat, no ret */
-        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
-        lb_sz = length%DES_BLOCK_SIZE;
-        blk   = length/DES_BLOCK_SIZE;
-
-        if (enc){
-            wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
-                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
-                wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
-                    lastblock, (word32)DES_BLOCK_SIZE);
-            }
-        }
-        else {
-            wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
-                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
-            }
-        }
-    }
-
-
-    /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */
-    void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
-                                      unsigned char* output, long sz,
-                                      WOLFSSL_DES_key_schedule* ks1,
-                                      WOLFSSL_DES_key_schedule* ks2,
-                                      WOLFSSL_DES_key_schedule* ks3,
-                                      WOLFSSL_DES_cblock* ivec, int enc)
-    {
-        Des3 des;
-        byte key[24];/* EDE uses 24 size key */
-        byte lastblock[DES_BLOCK_SIZE];
-        int  lb_sz;
-        long  blk;
-
-        WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
-
-        XMEMSET(key, 0, sizeof(key));
-        XMEMCPY(key, *ks1, DES_BLOCK_SIZE);
-        XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE);
-        XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE);
-        lb_sz = sz%DES_BLOCK_SIZE;
-        blk   = sz/DES_BLOCK_SIZE;
-        if (enc) {
-            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION);
-            wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
-                XMEMCPY(lastblock, input+sz-lb_sz, lb_sz);
-                wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE,
-                    lastblock, (word32)DES_BLOCK_SIZE);
-            }
-        }
-        else {
-            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION);
-            wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE);
-                XMEMCPY(output+sz-lb_sz, lastblock, lb_sz);
-            }
-        }
-    }
-
-
-    /* correctly sets ivec for next call */
-    void wolfSSL_DES_ncbc_encrypt(const unsigned char* input,
-                     unsigned char* output, long length,
-                     WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
-                     int enc)
-    {
-        Des myDes;
-        byte lastblock[DES_BLOCK_SIZE];
-        int  lb_sz;
-        long  blk;
-
-        WOLFSSL_ENTER("DES_ncbc_encrypt");
-
-        /* OpenSSL compat, no ret */
-        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
-        lb_sz = length%DES_BLOCK_SIZE;
-        blk   = length/DES_BLOCK_SIZE;
-        if (enc){
-            wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
-                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
-                wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
-                    lastblock, (word32)DES_BLOCK_SIZE);
-            }
-        } else {
-            wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
-            if(lb_sz){
-                wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
-                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
-            }
-        }
-
-        XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock));
-    }
-
-#endif /* NO_DES3 */
-
-
-    void wolfSSL_ERR_free_strings(void)
-    {
-        /* handled internally */
-    }
-
-
-    void wolfSSL_EVP_cleanup(void)
-    {
-        /* nothing to do here */
-    }
-
-
-    void wolfSSL_cleanup_all_ex_data(void)
-    {
-        /* nothing to do here */
-    }
-
-    int wolfSSL_clear(WOLFSSL* ssl)
-    {
-        if (ssl == NULL) {
-            return WOLFSSL_FAILURE;
-        }
-
-        ssl->options.isClosed = 0;
-        ssl->options.connReset = 0;
-        ssl->options.sentNotify = 0;
-
-        ssl->options.serverState = NULL_STATE;
-        ssl->options.clientState = NULL_STATE;
-        ssl->options.connectState = CONNECT_BEGIN;
-        ssl->options.acceptState  = ACCEPT_BEGIN;
-        ssl->options.handShakeState  = NULL_STATE;
-        ssl->options.handShakeDone = 0;
-        /* ssl->options.processReply = doProcessInit; */
-
-        ssl->keys.encryptionOn = 0;
-        XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
-
-        if (ssl->hsHashes != NULL) {
-#ifndef NO_OLD_TLS
-#ifndef NO_MD5
-            wc_InitMd5(&ssl->hsHashes->hashMd5);
-#endif
-#ifndef NO_SHA
-            if (wc_InitSha(&ssl->hsHashes->hashSha) != 0)
-                return WOLFSSL_FAILURE;
-#endif
-#endif
-#ifndef NO_SHA256
-            if (wc_InitSha256(&ssl->hsHashes->hashSha256) != 0)
-                return WOLFSSL_FAILURE;
-#endif
-#ifdef WOLFSSL_SHA384
-            if (wc_InitSha384(&ssl->hsHashes->hashSha384) != 0)
-                return WOLFSSL_FAILURE;
-#endif
-#ifdef WOLFSSL_SHA512
-            if (wc_InitSha512(&ssl->hsHashes->hashSha512) != 0)
-                return WOLFSSL_FAILURE;
-#endif
-        }
-#ifdef SESSION_CERTS
-        ssl->session.chain.count = 0;
-#endif
-#ifdef KEEP_PEER_CERT
-        FreeX509(&ssl->peerCert);
-        InitX509(&ssl->peerCert, 0, ssl->heap);
-#endif
-
-        return WOLFSSL_SUCCESS;
-    }
-
-    long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
-    {
-        word32 tmptime;
-        if (!ses || t < 0)
-            return BAD_FUNC_ARG;
-
-        tmptime = t & 0xFFFFFFFF;
-
-        ses->timeout = tmptime;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
-    {
-        /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
-
-        WOLFSSL_ENTER("SSL_CTX_set_mode");
-        if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE)
-            ctx->partialWrite = 1;
-
-        return mode;
-    }
-
-    #ifndef NO_WOLFSSL_STUB
-    long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
-    {
-        /* TODO: */
-        (void)ssl;
-        WOLFSSL_STUB("SSL_get_mode");
-        return 0;
-    }
-    #endif
-
-    #ifndef NO_WOLFSSL_STUB
-    long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
-    {
-        /* TODO: */
-        (void)ctx;
-        WOLFSSL_STUB("SSL_CTX_get_mode");
-        return 0;
-    }
-    #endif
-
-    #ifndef NO_WOLFSSL_STUB
-    void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m)
-    {
-        /* TODO: maybe? */
-        (void)ctx;
-        (void)m;
-        WOLFSSL_STUB("SSL_CTX_set_default_read_ahead");
-    }
-    #endif
-
-
-    /* Storing app session context id, this value is inherited by WOLFSSL
-     * objects created from WOLFSSL_CTX. Any session that is imported with a
-     * different session context id will be rejected.
-     *
-     * ctx         structure to set context in
-     * sid_ctx     value of context to set
-     * sid_ctx_len length of sid_ctx buffer
-     *
-     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
-     */
-    int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx,
-                                           const unsigned char* sid_ctx,
-                                           unsigned int sid_ctx_len)
-    {
-        WOLFSSL_ENTER("SSL_CTX_set_session_id_context");
-
-        /* No application specific context needed for wolfSSL */
-        if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) {
-            return SSL_FAILURE;
-        }
-        XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len);
-        ctx->sessionCtxSz = (byte)sid_ctx_len;
-
-        return SSL_SUCCESS;
-    }
-
-
-
-    /* Storing app session context id. Any session that is imported with a
-     * different session context id will be rejected.
-     *
-     * ssl  structure to set context in
-     * id   value of context to set
-     * len  length of sid_ctx buffer
-     *
-     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
-     */
-    int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
-                                   unsigned int len)
-    {
-        WOLFSSL_STUB("wolfSSL_set_session_id_context");
-
-        if (len > ID_LEN || ssl == NULL || id == NULL) {
-            return SSL_FAILURE;
-        }
-        XMEMCPY(ssl->sessionCtx, id, len);
-        ssl->sessionCtxSz = (byte)len;
-
-        return SSL_SUCCESS;
-    }
-
-
-    long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
-    {
-        (void)ctx;
-        #ifndef NO_SESSION_CACHE
-            return SESSIONS_PER_ROW * SESSION_ROWS;
-        #else
-            return 0;
-        #endif
-    }
-
-
-    /* returns the unsigned error value and increments the pointer into the
-     * error queue.
-     *
-     * file  pointer to file name
-     * line  gets set to line number of error when not NULL
-     */
-    unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
-    {
-    #ifdef DEBUG_WOLFSSL
-        int ret = wc_PullErrorNode(file, NULL, line);
-        if (ret < 0) {
-            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
-            WOLFSSL_MSG("Issue getting error node");
-            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
-            ret = 0 - ret; /* return absolute value of error */
-
-            /* panic and try to clear out nodes */
-            wc_ClearErrorNodes();
-        }
-        return (unsigned long)ret;
-    #else
-        (void)file;
-        (void)line;
-
-        return 0;
-    #endif
-    }
-
-
-#ifdef DEBUG_WOLFSSL
-    static const char WOLFSSL_SYS_ACCEPT_T[]  = "accept";
-    static const char WOLFSSL_SYS_BIND_T[]    = "bind";
-    static const char WOLFSSL_SYS_CONNECT_T[] = "connect";
-    static const char WOLFSSL_SYS_FOPEN_T[]   = "fopen";
-    static const char WOLFSSL_SYS_FREAD_T[]   = "fread";
-    static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo";
-    static const char WOLFSSL_SYS_GETSOCKOPT_T[]  = "getsockopt";
-    static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname";
-    static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname";
-    static const char WOLFSSL_SYS_GETNAMEINFO_T[]   = "getnameinfo";
-    static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname";
-    static const char WOLFSSL_SYS_IOCTLSOCKET_T[]   = "ioctlsocket";
-    static const char WOLFSSL_SYS_LISTEN_T[]        = "listen";
-    static const char WOLFSSL_SYS_OPENDIR_T[]       = "opendir";
-    static const char WOLFSSL_SYS_SETSOCKOPT_T[]    = "setsockopt";
-    static const char WOLFSSL_SYS_SOCKET_T[]        = "socket";
-
-    /* switch with int mapped to function name for compatibility */
-    static const char* wolfSSL_ERR_sys_func(int fun)
-    {
-        switch (fun) {
-            case WOLFSSL_SYS_ACCEPT:      return WOLFSSL_SYS_ACCEPT_T;
-            case WOLFSSL_SYS_BIND:        return WOLFSSL_SYS_BIND_T;
-            case WOLFSSL_SYS_CONNECT:     return WOLFSSL_SYS_CONNECT_T;
-            case WOLFSSL_SYS_FOPEN:       return WOLFSSL_SYS_FOPEN_T;
-            case WOLFSSL_SYS_FREAD:       return WOLFSSL_SYS_FREAD_T;
-            case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T;
-            case WOLFSSL_SYS_GETSOCKOPT:  return WOLFSSL_SYS_GETSOCKOPT_T;
-            case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T;
-            case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T;
-            case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T;
-            case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T;
-            case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T;
-            case WOLFSSL_SYS_LISTEN:      return WOLFSSL_SYS_LISTEN_T;
-            case WOLFSSL_SYS_OPENDIR:     return WOLFSSL_SYS_OPENDIR_T;
-            case WOLFSSL_SYS_SETSOCKOPT:  return WOLFSSL_SYS_SETSOCKOPT_T;
-            case WOLFSSL_SYS_SOCKET:      return WOLFSSL_SYS_SOCKET_T;
-            default:
-                return "NULL";
-        }
-    }
-#endif /* DEBUG_WOLFSSL */
-
-
-    /* @TODO when having an error queue this needs to push to the queue */
-    void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
-            int line)
-    {
-        WOLFSSL_ENTER("wolfSSL_ERR_put_error");
-
-        #ifndef DEBUG_WOLFSSL
-        (void)fun;
-        (void)err;
-        (void)file;
-        (void)line;
-        WOLFSSL_MSG("Not compiled in debug mode");
-        #else
-        WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line,
-            file, NULL);
-        #endif
-        (void)lib;
-    }
-
-
-    /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
-     * more flexability.
-     *
-     * file  output pointer to file where error happened
-     * line  output to line number of error
-     * data  output data. Is a string if ERR_TXT_STRING flag is used
-     * flags bit flag to adjust data output
-     *
-     * Returns the error value or 0 if no errors are in the queue
-     */
-    unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
-                                                  const char** data, int *flags)
-    {
-        int ret;
-
-        WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data");
-
-        if (flags != NULL) {
-            if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) {
-                ret = wc_PullErrorNode(file, data, line);
-                if (ret < 0) {
-                    if (ret == BAD_STATE_E) return 0; /* no errors in queue */
-                    WOLFSSL_MSG("Error with pulling error node!");
-                    WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
-                    ret = 0 - ret; /* return absolute value of error */
-
-                    /* panic and try to clear out nodes */
-                    wc_ClearErrorNodes();
-                }
-
-                return (unsigned long)ret;
-            }
-        }
-
-        ret = wc_PullErrorNode(file, NULL, line);
-        if (ret < 0) {
-            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
-            WOLFSSL_MSG("Error with pulling error node!");
-            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
-            ret = 0 - ret; /* return absolute value of error */
-
-            /* panic and try to clear out nodes */
-            wc_ClearErrorNodes();
-        }
-
-        return (unsigned long)ret;
-    }
-
-#endif /* OPENSSL_EXTRA */
-
-
-#ifdef KEEP_PEER_CERT
-    #ifdef SESSION_CERTS
-    /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
-     *
-     * x509  WOLFSSL_X509 object to decode into.
-     * in    X509 DER data.
-     * len   Length of the X509 DER data.
-     * returns the new certificate on success, otherwise NULL.
-     */
-    static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
-    {
-        int          ret;
-    #ifdef WOLFSSL_SMALL_STACK
-        DecodedCert* cert = NULL;
-    #else
-        DecodedCert  cert[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                     DYNAMIC_TYPE_DCERT);
-        if (cert == NULL)
-            return MEMORY_E;
-    #endif
-
-        /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
-         */
-        InitDecodedCert(cert, (byte*)in, len, NULL);
-        if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) {
-            InitX509(x509, 0, NULL);
-            ret = CopyDecodedToX509(x509, cert);
-            FreeDecodedCert(cert);
-        }
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-    #endif
-
-        return ret;
-    }
-    #endif /* SESSION_CERTS */
-
-
-    WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
-    {
-        WOLFSSL_ENTER("SSL_get_peer_certificate");
-        if (ssl->peerCert.issuer.sz)
-            return &ssl->peerCert;
-#ifdef SESSION_CERTS
-        else if (ssl->session.chain.count > 0) {
-            if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer,
-                    ssl->session.chain.certs[0].length) == 0) {
-                return &ssl->peerCert;
-            }
-        }
-#endif
-        return 0;
-    }
-
-#endif /* KEEP_PEER_CERT */
-
-
-#ifndef NO_CERTS
-#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
-    defined(OPENSSL_EXTRA)  || defined(OPENSSL_EXTRA_X509_SMALL)
-
-/* user externally called free X509, if dynamic go ahead with free, otherwise
- * don't */
-static void ExternalFreeX509(WOLFSSL_X509* x509)
-{
-    WOLFSSL_ENTER("ExternalFreeX509");
-    if (x509) {
-        if (x509->dynamicMemory) {
-            FreeX509(x509);
-            XFREE(x509, x509->heap, DYNAMIC_TYPE_X509);
-        } else {
-            WOLFSSL_MSG("free called on non dynamic object, not freeing");
-        }
-    }
-}
-
-/* Frees an external WOLFSSL_X509 structure */
-void wolfSSL_X509_free(WOLFSSL_X509* x509)
-{
-    WOLFSSL_ENTER("wolfSSL_FreeX509");
-    ExternalFreeX509(x509);
-}
-
-
-/* copy name into in buffer, at most sz bytes, if buffer is null will
-   malloc buffer, call responsible for freeing                     */
-char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
-{
-    int copySz;
-
-    if (name == NULL) {
-        WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL");
-        return NULL;
-    }
-
-    copySz = min(sz, name->sz);
-
-    WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
-    if (!name->sz) return in;
-
-    if (!in) {
-    #ifdef WOLFSSL_STATIC_MEMORY
-        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
-        return NULL;
-    #else
-        in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL);
-        if (!in ) return in;
-        copySz = name->sz;
-    #endif
-    }
-
-    if (copySz <= 0)
-        return in;
-
-    XMEMCPY(in, name->name, copySz - 1);
-    in[copySz - 1] = 0;
-
-    return in;
-}
-
-
-/* Wraps wolfSSL_X509_d2i
- *
- * returns a WOLFSSL_X509 structure pointer on success and NULL on fail
- */
-WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in,
-        int len)
-{
-    return wolfSSL_X509_d2i(x509, *in, len);
-}
-
-
-WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
-{
-    WOLFSSL_X509 *newX509 = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_X509_d2i");
-
-    if (in != NULL && len != 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-        DecodedCert* cert = NULL;
-    #else
-        DecodedCert  cert[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                     DYNAMIC_TYPE_DCERT);
-        if (cert == NULL)
-            return NULL;
-    #endif
-
-        InitDecodedCert(cert, (byte*)in, len, NULL);
-        if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
-            newX509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
-                                             DYNAMIC_TYPE_X509);
-            if (newX509 != NULL) {
-                InitX509(newX509, 1, NULL);
-                if (CopyDecodedToX509(newX509, cert) != 0) {
-                    XFREE(newX509, NULL, DYNAMIC_TYPE_X509);
-                    newX509 = NULL;
-                }
-            }
-        }
-        FreeDecodedCert(cert);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-    #endif
-    }
-
-    if (x509 != NULL)
-        *x509 = newX509;
-
-    return newX509;
-}
-#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
-          OPENSSL_EXTRA_X509_SMALL */
-
-#if defined(OPENSSL_ALL) || defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
-    /* return the next, if any, altname from the peer cert */
-    char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
-    {
-        char* ret = NULL;
-        WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
-
-        /* don't have any to work with */
-        if (cert == NULL || cert->altNames == NULL)
-            return NULL;
-
-        /* already went through them */
-        if (cert->altNamesNext == NULL)
-            return NULL;
-
-        ret = cert->altNamesNext->name;
-        cert->altNamesNext = cert->altNamesNext->next;
-
-        return ret;
-    }
-
-
-    int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
-    {
-        int isCA = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
-
-        if (x509 != NULL)
-            isCA = x509->isCa;
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
-
-        return isCA;
-    }
-
-    int wolfSSL_X509_get_signature(WOLFSSL_X509* x509,
-                                                 unsigned char* buf, int* bufSz)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_get_signature");
-        if (x509 == NULL || bufSz == NULL || *bufSz < (int)x509->sig.length)
-            return WOLFSSL_FATAL_ERROR;
-
-        if (buf != NULL)
-            XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
-        *bufSz = x509->sig.length;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* write X509 serial number in unsigned binary to buffer
-       buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases
-       return WOLFSSL_SUCCESS on success */
-    int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509,
-                                       byte* in, int* inOutSz)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_get_serial_number");
-        if (x509 == NULL || in == NULL ||
-                                   inOutSz == NULL || *inOutSz < x509->serialSz)
-            return BAD_FUNC_ARG;
-
-        XMEMCPY(in, x509->serial, x509->serialSz);
-        *inOutSz = x509->serialSz;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_get_der");
-
-        if (x509 == NULL || x509->derCert == NULL || outSz == NULL)
-            return NULL;
-
-        *outSz = (int)x509->derCert->length;
-        return x509->derCert->buffer;
-    }
-
-
-    int wolfSSL_X509_version(WOLFSSL_X509* x509)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_version");
-
-        if (x509 == NULL)
-            return 0;
-
-        return x509->version;
-    }
-
-
-    const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_notBefore");
-
-        if (x509 == NULL)
-            return NULL;
-
-        return x509->notBefore;
-    }
-
-
-    const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_notAfter");
-
-        if (x509 == NULL)
-            return NULL;
-
-        return x509->notAfter;
-    }
-
-
-#ifdef WOLFSSL_SEP
-
-/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will
-   malloc buffer, call responsible for freeing. Actual size returned in
-   *inOutSz. Requires inOutSz be non-null */
-byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz)
-{
-    int copySz;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_dev_type");
-    if (inOutSz == NULL) return NULL;
-    if (!x509->deviceTypeSz) return in;
-
-    copySz = min(*inOutSz, x509->deviceTypeSz);
-
-    if (!in) {
-    #ifdef WOLFSSL_STATIC_MEMORY
-        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
-        return NULL;
-    #else
-        in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
-        if (!in) return in;
-        copySz = x509->deviceTypeSz;
-    #endif
-    }
-
-    XMEMCPY(in, x509->deviceType, copySz);
-    *inOutSz = copySz;
-
-    return in;
-}
-
-
-byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
-{
-    int copySz;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_hw_type");
-    if (inOutSz == NULL) return NULL;
-    if (!x509->hwTypeSz) return in;
-
-    copySz = min(*inOutSz, x509->hwTypeSz);
-
-    if (!in) {
-    #ifdef WOLFSSL_STATIC_MEMORY
-        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
-        return NULL;
-    #else
-        in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
-        if (!in) return in;
-        copySz = x509->hwTypeSz;
-    #endif
-    }
-
-    XMEMCPY(in, x509->hwType, copySz);
-    *inOutSz = copySz;
-
-    return in;
-}
-
-
-byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
-                                        int* inOutSz)
-{
-    int copySz;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number");
-    if (inOutSz == NULL) return NULL;
-    if (!x509->hwTypeSz) return in;
-
-    copySz = min(*inOutSz, x509->hwSerialNumSz);
-
-    if (!in) {
-    #ifdef WOLFSSL_STATIC_MEMORY
-        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
-        return NULL;
-    #else
-        in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL);
-        if (!in) return in;
-        copySz = x509->hwSerialNumSz;
-    #endif
-    }
-
-    XMEMCPY(in, x509->hwSerialNum, copySz);
-    *inOutSz = copySz;
-
-    return in;
-}
-
-#endif /* WOLFSSL_SEP */
-
-/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
-#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
-/* return 1 on success 0 on fail */
-int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509)
-{
-    WOLFSSL_STACK* node;
-
-    if (sk == NULL || x509 == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* no previous values in stack */
-    if (sk->data.x509 == NULL) {
-        sk->data.x509 = x509;
-        sk->num += 1;
-        return WOLFSSL_SUCCESS;
-    }
-
-    /* stack already has value(s) create a new node and add more */
-    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
-                                                             DYNAMIC_TYPE_X509);
-    if (node == NULL) {
-        WOLFSSL_MSG("Memory error");
-        return WOLFSSL_FAILURE;
-    }
-    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
-
-    /* push new x509 onto head of stack */
-    node->data.x509 = sk->data.x509;
-    node->next      = sk->next;
-    sk->next        = node;
-    sk->data.x509   = x509;
-    sk->num        += 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
-    WOLFSSL_STACK* node;
-    WOLFSSL_X509*  x509;
-
-    if (sk == NULL) {
-        return NULL;
-    }
-
-    node = sk->next;
-    x509 = sk->data.x509;
-
-    if (node != NULL) { /* update sk and remove node from stack */
-        sk->data.x509 = node->data.x509;
-        sk->next = node->next;
-        XFREE(node, NULL, DYNAMIC_TYPE_X509);
-    }
-    else { /* last x509 in stack */
-        sk->data.x509 = NULL;
-    }
-
-    if (sk->num > 0) {
-        sk->num -= 1;
-    }
-
-    return x509;
-}
-
-
-/* Getter function for WOLFSSL_X509_NAME pointer
- *
- * sk is the stack to retrieve pointer from
- * i  is the index value in stack
- *
- * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on
- *         fail
- */
-void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i)
-{
-    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value");
-
-    for (; sk != NULL && i > 0; i--)
-        sk = sk->next;
-
-    if (i != 0 || sk == NULL)
-        return NULL;
-    return sk->data.name;
-}
-
-
-/* Getter function for WOLFSSL_X509 pointer
- *
- * sk is the stack to retrieve pointer from
- * i  is the index value in stack
- *
- * returns a pointer to a WOLFSSL_X509 structure on success and NULL on
- *         fail
- */
-void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i)
-{
-    WOLFSSL_ENTER("wolfSSL_sk_X509_value");
-
-    for (; sk != NULL && i > 0; i--)
-        sk = sk->next;
-
-    if (i != 0 || sk == NULL)
-        return NULL;
-    return sk->data.x509;
-}
-
-
-/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free
- * in that it allows for choosing the function to use when freeing an X509s.
- *
- * sk  stack to free nodes in
- * f   X509 free function
- */
-void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){
-    WOLFSSL_STACK* node;
-
-    WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free");
-
-    if (sk == NULL) {
-        return;
-    }
-
-    /* parse through stack freeing each node */
-    node = sk->next;
-    while (sk->num > 1) {
-        WOLFSSL_STACK* tmp = node;
-        node = node->next;
-
-        f(tmp->data.x509);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
-        sk->num -= 1;
-    }
-
-    /* free head of stack */
-    if (sk->num == 1) {
-	    f(sk->data.x509);
-    }
-    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
-}
-
-
-/* free structure for x509 stack */
-void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
-    WOLFSSL_STACK* node;
-
-    if (sk == NULL) {
-        return;
-    }
-
-    /* parse through stack freeing each node */
-    node = sk->next;
-    while (sk->num > 1) {
-        WOLFSSL_STACK* tmp = node;
-        node = node->next;
-
-        wolfSSL_X509_free(tmp->data.x509);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
-        sk->num -= 1;
-    }
-
-    /* free head of stack */
-    if (sk->num == 1) {
-    wolfSSL_X509_free(sk->data.x509);
-    }
-    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
-}
-
-#endif /* NO_CERTS && OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-
-/* Returns the general name at index i from the stack
- *
- * sk stack to get general name from
- * i  index to get
- *
- * return a pointer to the internal node of the stack
- */
-WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int i)
-{
-    WOLFSSL_STACK* cur;
-    int j;
-
-    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_value");
-
-    if (i < 0 || sk == NULL) {
-        return NULL;
-    }
-
-    cur = sk;
-    for (j = 0; j < i && cur != NULL; j++) {
-        cur = cur->next;
-    }
-
-    if (cur == NULL) {
-        return NULL;
-    }
-
-    return cur->data.obj;
-}
-
-
-/* Gets the number of nodes in the stack
- *
- * sk  stack to get the number of nodes from
- *
- * returns the number of nodes, -1 if no nodes
- */
-int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
-{
-    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num");
-
-    if (sk == NULL) {
-        return -1;
-    }
-
-    return (int)sk->num;
-}
-
-/* Frees all nodes in a GENERAL NAME stack
- *
- * sk stack of nodes to free
- * f  free function to use, not called with wolfSSL
- */
-void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
-        void f (WOLFSSL_ASN1_OBJECT*))
-{
-    WOLFSSL_STACK* node;
-
-    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free");
-
-    (void)f;
-    if (sk == NULL) {
-        return;
-    }
-
-    /* parse through stack freeing each node */
-    node = sk->next;
-    while (sk->num > 1) {
-        WOLFSSL_STACK* tmp = node;
-        node = node->next;
-
-        wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
-        sk->num -= 1;
-    }
-
-    /* free head of stack */
-    if (sk->num == 1) {
-	    wolfSSL_ASN1_OBJECT_free(sk->data.obj);
-    }
-    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
-
-
-}
-#endif /* OPENSSL_EXTRA */
-
-#ifndef NO_FILESYSTEM
-
-#ifndef NO_STDIO_FILESYSTEM
-
-WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
-{
-    WOLFSSL_X509* newX509 = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_X509_d2i_fp");
-
-    if (file != XBADFILE) {
-        byte* fileBuffer = NULL;
-        long sz = 0;
-
-        XFSEEK(file, 0, XSEEK_END);
-        sz = XFTELL(file);
-        XREWIND(file);
-
-        if (sz < 0) {
-            WOLFSSL_MSG("Bad tell on FILE");
-            return NULL;
-        }
-
-        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
-        if (fileBuffer != NULL) {
-            int ret = (int)XFREAD(fileBuffer, 1, sz, file);
-            if (ret == sz) {
-                newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
-            }
-            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
-        }
-    }
-
-    if (x509 != NULL)
-        *x509 = newX509;
-
-    return newX509;
-}
-
-#endif /* NO_STDIO_FILESYSTEM */
-
-WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte  staticBuffer[1]; /* force heap usage */
-#else
-    byte  staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte* fileBuffer = staticBuffer;
-    int   dynamic = 0;
-    int   ret;
-    long  sz = 0;
-    XFILE file;
-
-    WOLFSSL_X509* x509 = NULL;
-
-    /* Check the inputs */
-    if ((fname == NULL) ||
-        (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM))
-        return NULL;
-
-    file = XFOPEN(fname, "rb");
-    if (file == XBADFILE)
-        return NULL;
-
-    XFSEEK(file, 0, XSEEK_END);
-    sz = XFTELL(file);
-    XREWIND(file);
-
-    if (sz > (long)sizeof(staticBuffer)) {
-        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
-        if (fileBuffer == NULL) {
-            XFCLOSE(file);
-            return NULL;
-        }
-        dynamic = 1;
-    }
-    else if (sz < 0) {
-        XFCLOSE(file);
-        return NULL;
-    }
-
-    ret = (int)XFREAD(fileBuffer, 1, sz, file);
-    if (ret != sz) {
-        XFCLOSE(file);
-        if (dynamic)
-            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
-        return NULL;
-    }
-
-    XFCLOSE(file);
-
-    x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format);
-
-    if (dynamic)
-        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
-
-    return x509;
-}
-
-#endif /* NO_FILESYSTEM */
-
-
-WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
-    const unsigned char* buf, int sz, int format)
-{
-    int ret;
-    WOLFSSL_X509* x509 = NULL;
-    DerBuffer* der = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex");
-
-    if (format == WOLFSSL_FILETYPE_PEM) {
-    #ifdef WOLFSSL_PEM_TO_DER
-        if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) {
-            FreeDer(&der);
-        }
-    #else
-        ret = NOT_COMPILED_IN;
-    #endif
-    }
-    else {
-        ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL);
-        if (ret == 0) {
-            XMEMCPY(der->buffer, buf, sz);
-        }
-    }
-
-    /* At this point we want `der` to have the certificate in DER format */
-    /* ready to be decoded. */
-    if (der != NULL && der->buffer != NULL) {
-    #ifdef WOLFSSL_SMALL_STACK
-        DecodedCert* cert = NULL;
-    #else
-        DecodedCert  cert[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                     DYNAMIC_TYPE_DCERT);
-        if (cert != NULL)
-    #endif
-        {
-            InitDecodedCert(cert, der->buffer, der->length, NULL);
-            if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
-                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
-                                                             DYNAMIC_TYPE_X509);
-                if (x509 != NULL) {
-                    InitX509(x509, 1, NULL);
-                    if (CopyDecodedToX509(x509, cert) != 0) {
-                        XFREE(x509, NULL, DYNAMIC_TYPE_X509);
-                        x509 = NULL;
-                    }
-                }
-            }
-
-            FreeDecodedCert(cert);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-        #endif
-        }
-
-        FreeDer(&der);
-    }
-
-    return x509;
-}
-
-#endif /* KEEP_PEER_CERT || SESSION_CERTS */
-
-/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
-   KEEP_OUR_CERT is to insure ability for returning ssl certificate */
-#if defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT)
-WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
-{
-    if (ssl == NULL) {
-        return NULL;
-    }
-
-    if (ssl->buffers.weOwnCert) {
-        if (ssl->ourCert == NULL) {
-            if (ssl->buffers.certificate == NULL) {
-                WOLFSSL_MSG("Certificate buffer not set!");
-                return NULL;
-            }
-            ssl->ourCert = wolfSSL_X509_d2i(NULL,
-                                              ssl->buffers.certificate->buffer,
-                                              ssl->buffers.certificate->length);
-        }
-        return ssl->ourCert;
-    }
-    else { /* if cert not owned get parent ctx cert or return null */
-        if (ssl->ctx) {
-            if (ssl->ctx->ourCert == NULL) {
-                if (ssl->ctx->certificate == NULL) {
-                    WOLFSSL_MSG("Ctx Certificate buffer not set!");
-                    return NULL;
-                }
-                ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
-                                               ssl->ctx->certificate->buffer,
-                                               ssl->ctx->certificate->length);
-                ssl->ctx->ownOurCert = 1;
-            }
-            return ssl->ctx->ourCert;
-        }
-    }
-
-    return NULL;
-}
-#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
-#endif /* NO_CERTS */
-
-
-#ifdef OPENSSL_EXTRA
-/* return 1 on success 0 on fail */
-int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk,
-                                                      WOLFSSL_ASN1_OBJECT* obj)
-{
-    WOLFSSL_STACK* node;
-
-    if (sk == NULL || obj == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* no previous values in stack */
-    if (sk->data.obj == NULL) {
-        sk->data.obj = obj;
-        sk->num += 1;
-        return WOLFSSL_SUCCESS;
-    }
-
-    /* stack already has value(s) create a new node and add more */
-    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
-                                                             DYNAMIC_TYPE_ASN1);
-    if (node == NULL) {
-        WOLFSSL_MSG("Memory error");
-        return WOLFSSL_FAILURE;
-    }
-    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
-
-    /* push new obj onto head of stack */
-    node->data.obj = sk->data.obj;
-    node->next      = sk->next;
-    sk->next        = node;
-    sk->data.obj   = obj;
-    sk->num        += 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop(
-                                            WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
-{
-    WOLFSSL_STACK* node;
-    WOLFSSL_ASN1_OBJECT*  obj;
-
-    if (sk == NULL) {
-        return NULL;
-    }
-
-    node = sk->next;
-    obj = sk->data.obj;
-
-    if (node != NULL) { /* update sk and remove node from stack */
-        sk->data.obj = node->data.obj;
-        sk->next = node->next;
-        XFREE(node, NULL, DYNAMIC_TYPE_ASN1);
-    }
-    else { /* last obj in stack */
-        sk->data.obj = NULL;
-    }
-
-    if (sk->num > 0) {
-        sk->num -= 1;
-    }
-
-    return obj;
-}
-
-
-#ifndef NO_ASN
-WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void)
-{
-    WOLFSSL_ASN1_OBJECT* obj;
-
-    obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL,
-                                        DYNAMIC_TYPE_ASN1);
-    if (obj == NULL) {
-        return NULL;
-    }
-
-    XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT));
-    obj->d.ia5 = &(obj->d.ia5_internal);
-    return obj;
-}
-
-
-void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj)
-{
-    if (obj == NULL) {
-        return;
-    }
-
-    if (obj->dynamic == 1) {
-        if (obj->obj != NULL) {
-            WOLFSSL_MSG("Freeing ASN1 OBJECT data");
-            XFREE(obj->obj, obj->heap, DYNAMIC_TYPE_ASN1);
-        }
-    }
-
-    XFREE(obj, NULL, DYNAMIC_TYPE_ASN1);
-}
-
-
-/* free structure for x509 stack */
-void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
-{
-    WOLFSSL_STACK* node;
-
-    if (sk == NULL) {
-        return;
-    }
-
-    /* parse through stack freeing each node */
-    node = sk->next;
-    while (sk->num > 1) {
-        WOLFSSL_STACK* tmp = node;
-        node = node->next;
-
-        wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
-        sk->num -= 1;
-    }
-
-    /* free head of stack */
-    if (sk->num == 1) {
-        wolfSSL_ASN1_OBJECT_free(sk->data.obj);
-    }
-    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
-}
-
-int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in)
-{
-    /*
-       ASN1_STRING_to_UTF8() converts the string in to UTF8 format,
-       the converted data is allocated in a buffer in *out.
-       The length of out is returned or a negative error code.
-       The buffer *out should be free using OPENSSL_free().
-       */
-    (void)out;
-    (void)in;
-    WOLFSSL_STUB("ASN1_STRING_to_UTF8");
-    return -1;
-}
-#endif /* NO_ASN */
-
-void wolfSSL_set_connect_state(WOLFSSL* ssl)
-{
-    word16 haveRSA = 1;
-    word16 havePSK = 0;
-
-    if (ssl == NULL) {
-        WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
-        return;
-    }
-
-    #ifndef NO_DH
-    /* client creates its own DH parameters on handshake */
-    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
-            DYNAMIC_TYPE_PUBLIC_KEY);
-    }
-    ssl->buffers.serverDH_P.buffer = NULL;
-    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
-        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
-            DYNAMIC_TYPE_PUBLIC_KEY);
-    }
-    ssl->buffers.serverDH_G.buffer = NULL;
-    #endif
-
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-        #ifdef NO_RSA
-            haveRSA = 0;
-        #endif
-        #ifndef NO_PSK
-            havePSK = ssl->options.havePSK;
-        #endif
-        InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA,
-                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
-                   ssl->options.haveECDSAsig, ssl->options.haveECC,
-                   ssl->options.haveStaticECC, WOLFSSL_CLIENT_END);
-    }
-    ssl->options.side = WOLFSSL_CLIENT_END;
-}
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
-
-
-int wolfSSL_get_shutdown(const WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_shutdown");
-    /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent   *
-     * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */
-    return ((ssl->options.closeNotify||ssl->options.connReset) << 1)
-            | (ssl->options.sentNotify);
-}
-
-
-int wolfSSL_session_reused(WOLFSSL* ssl)
-{
-    return ssl->options.resuming;
-}
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
-void wolfSSL_SESSION_free(WOLFSSL_SESSION* session)
-{
-    if (session == NULL)
-        return;
-
-#ifdef HAVE_EXT_CACHE
-    if (session->isAlloced) {
-    #ifdef HAVE_SESSION_TICKET
-        if (session->isDynamic)
-            XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
-    #endif
-        XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL);
-    }
-#else
-    /* No need to free since cache is static */
-    (void)session;
-#endif
-}
-#endif
-
-const char* wolfSSL_get_version(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_get_version");
-    if (ssl->version.major == SSLv3_MAJOR) {
-        switch (ssl->version.minor) {
-        #ifndef NO_OLD_TLS
-            #ifdef WOLFSSL_ALLOW_SSLV3
-            case SSLv3_MINOR :
-                return "SSLv3";
-            #endif
-            #ifdef WOLFSSL_ALLOW_TLSV10
-            case TLSv1_MINOR :
-                return "TLSv1";
-            #endif
-            case TLSv1_1_MINOR :
-                return "TLSv1.1";
-        #endif
-            case TLSv1_2_MINOR :
-                return "TLSv1.2";
-        #ifdef WOLFSSL_TLS13
-            case TLSv1_3_MINOR :
-            /* TODO: [TLS13] Remove draft versions. */
-            #ifndef WOLFSSL_TLS13_FINAL
-                #ifdef WOLFSSL_TLS13_DRAFT_18
-                    return "TLSv1.3 (Draft 18)";
-                #elif defined(WOLFSSL_TLS13_DRAFT_22)
-                    return "TLSv1.3 (Draft 22)";
-                #elif defined(WOLFSSL_TLS13_DRAFT_23)
-                    return "TLSv1.3 (Draft 23)";
-                #elif defined(WOLFSSL_TLS13_DRAFT_26)
-                    return "TLSv1.3 (Draft 26)";
-                #else
-                    return "TLSv1.3 (Draft 28)";
-                #endif
-            #else
-                return "TLSv1.3";
-            #endif
-        #endif
-            default:
-                return "unknown";
-        }
-    }
-#ifdef WOLFSSL_DTLS
-    else if (ssl->version.major == DTLS_MAJOR) {
-        switch (ssl->version.minor) {
-            case DTLS_MINOR :
-                return "DTLS";
-            case DTLSv1_2_MINOR :
-                return "DTLSv1.2";
-            default:
-                return "unknown";
-        }
-    }
-#endif /* WOLFSSL_DTLS */
-    return "unknown";
-}
-
-
-/* current library version */
-const char* wolfSSL_lib_version(void)
-{
-    return LIBWOLFSSL_VERSION_STRING;
-}
-
-
-/* current library version in hex */
-word32 wolfSSL_lib_version_hex(void)
-{
-    return LIBWOLFSSL_VERSION_HEX;
-}
-
-
-int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_get_current_cipher_suite");
-    if (ssl)
-        return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite;
-    return 0;
-}
-
-WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("SSL_get_current_cipher");
-    if (ssl)
-        return &ssl->cipher;
-    else
-        return NULL;
-}
-
-
-const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
-{
-    WOLFSSL_ENTER("SSL_CIPHER_get_name");
-
-    if (cipher == NULL || cipher->ssl == NULL) {
-        return NULL;
-    }
-
-    return wolfSSL_get_cipher_name_iana(cipher->ssl);
-}
-
-const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session)
-{
-    if (session == NULL) {
-        return NULL;
-    }
-
-#ifdef SESSION_CERTS
-    return GetCipherNameIana(session->cipherSuite0, session->cipherSuite);
-#else
-    return NULL;
-#endif
-}
-
-const char* wolfSSL_get_cipher(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_cipher");
-    return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
-}
-
-/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
-const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
-{
-    /* get access to cipher_name_idx in internal.c */
-    return wolfSSL_get_cipher_name_internal(ssl);
-}
-
-const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
-    const byte cipherSuite)
-{
-    return GetCipherNameInternal(cipherSuite0, cipherSuite);
-}
-
-
-#ifdef HAVE_ECC
-/* Return the name of the curve used for key exchange as a printable string.
- *
- * ssl  The SSL/TLS object.
- * returns NULL if ECDH was not used, otherwise the name as a string.
- */
-const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
-{
-    if (ssl == NULL)
-        return NULL;
-    if (!IsAtLeastTLSv1_3(ssl->version) && ssl->specs.kea != ecdhe_psk_kea &&
-            ssl->specs.kea != ecc_diffie_hellman_kea)
-        return NULL;
-    if (ssl->ecdhCurveOID == 0)
-        return NULL;
-    if (ssl->ecdhCurveOID == ECC_X25519_OID)
-        return "X25519";
-    return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL));
-}
-#endif
-
-
-#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \
-    defined(SESSION_CERTS)
-/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
- * this subset and its memory usage */
-
-#if !defined(NO_CERTS)
-/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on
- * fail
- */
-WOLFSSL_X509* wolfSSL_X509_new()
-{
-    WOLFSSL_X509* x509;
-
-    x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
-            DYNAMIC_TYPE_X509);
-    if (x509 != NULL) {
-        InitX509(x509, 1, NULL);
-    }
-
-    return x509;
-}
-
-WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_get_subject_name");
-    if (cert && cert->subject.sz != 0)
-        return &cert->subject;
-    return NULL;
-}
-
-
-
-WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
-{
-    WOLFSSL_ENTER("X509_get_issuer_name");
-    if (cert && cert->issuer.sz != 0)
-        return &cert->issuer;
-    return NULL;
-}
-
-
-int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
-{
-    int type = 0;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
-
-    if (x509 != NULL)
-        type = x509->sigOID;
-
-    return type;
-}
-
-#if defined(OPENSSL_EXTRA_X509_SMALL)
-#ifdef HAVE_ECC
-    static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey);
-#endif
-
-/* Used to get a string from the WOLFSSL_X509_NAME structure that
- * corresponds with the NID value passed in.
- *
- * name structure to get string from
- * nid  NID value to search for
- * buf  [out] buffer to hold results. If NULL then the buffer size minus the
- *      null char is returned.
- * len  size of "buf" passed in
- *
- * returns the length of string found, not including the NULL terminator.
- *         It's possible the function could return a negative value in the
- *         case that len is less than or equal to 0. A negative value is
- *         considered an error case.
- */
-int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
-                                      int nid, char* buf, int len)
-{
-    char *text = NULL;
-    int textSz = 0;
-
-    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
-
-    switch (nid) {
-        case ASN_COMMON_NAME:
-            text = name->fullName.fullName + name->fullName.cnIdx;
-            textSz = name->fullName.cnLen;
-            break;
-        case ASN_SUR_NAME:
-            text = name->fullName.fullName + name->fullName.snIdx;
-            textSz = name->fullName.snLen;
-            break;
-        case ASN_SERIAL_NUMBER:
-            text = name->fullName.fullName + name->fullName.serialIdx;
-            textSz = name->fullName.serialLen;
-            break;
-        case ASN_COUNTRY_NAME:
-            text = name->fullName.fullName + name->fullName.cIdx;
-            textSz = name->fullName.cLen;
-            break;
-        case ASN_LOCALITY_NAME:
-            text = name->fullName.fullName + name->fullName.lIdx;
-            textSz = name->fullName.lLen;
-            break;
-        case ASN_STATE_NAME:
-            text = name->fullName.fullName + name->fullName.stIdx;
-            textSz = name->fullName.stLen;
-            break;
-        case ASN_ORG_NAME:
-            text = name->fullName.fullName + name->fullName.oIdx;
-            textSz = name->fullName.oLen;
-            break;
-        case ASN_ORGUNIT_NAME:
-            text = name->fullName.fullName + name->fullName.ouIdx;
-            textSz = name->fullName.ouLen;
-            break;
-        case ASN_DOMAIN_COMPONENT:
-            text = name->fullName.fullName + name->fullName.dcIdx[0];
-            textSz = name->fullName.dcLen[0];
-            break;
-        default:
-            WOLFSSL_MSG("Entry type not found");
-            return SSL_FATAL_ERROR;
-    }
-
-    /* if buf is NULL return size of buffer needed (minus null char) */
-    if (buf == NULL) {
-        return textSz;
-    }
-
-    if (buf != NULL && text != NULL) {
-        textSz = min(textSz + 1, len); /* + 1 to account for null char */
-        if (textSz > 0) {
-            XMEMCPY(buf, text, textSz - 1);
-            buf[textSz - 1] = '\0';
-        }
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
-    return (textSz - 1); /* do not include null character in size */
-}
-
-
-/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509
- *
- * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail
- */
-WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
-{
-    WOLFSSL_EVP_PKEY* key = NULL;
-    WOLFSSL_ENTER("X509_get_pubkey");
-    if (x509 != NULL) {
-        key = (WOLFSSL_EVP_PKEY*)XMALLOC(
-                    sizeof(WOLFSSL_EVP_PKEY), x509->heap,
-                                                       DYNAMIC_TYPE_PUBLIC_KEY);
-        if (key != NULL) {
-            XMEMSET(key, 0, sizeof(WOLFSSL_EVP_PKEY));
-            if (x509->pubKeyOID == RSAk) {
-                key->type = EVP_PKEY_RSA;
-            }
-            else {
-                key->type = EVP_PKEY_EC;
-            }
-            key->save_type = 0;
-            key->pkey.ptr = (char*)XMALLOC(
-                        x509->pubKey.length, x509->heap,
-                                                       DYNAMIC_TYPE_PUBLIC_KEY);
-            if (key->pkey.ptr == NULL) {
-                XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                return NULL;
-            }
-            XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
-            key->pkey_sz = x509->pubKey.length;
-
-            #ifdef HAVE_ECC
-                key->pkey_curve = (int)x509->pkCurveOID;
-            #endif /* HAVE_ECC */
-
-            /* decode RSA key */
-            #ifndef NO_RSA
-            if (key->type == EVP_PKEY_RSA) {
-                key->ownRsa = 1;
-                key->rsa = wolfSSL_RSA_new();
-                if (key->rsa == NULL) {
-                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    return NULL;
-                }
-
-                if (wolfSSL_RSA_LoadDer_ex(key->rsa,
-                            (const unsigned char*)key->pkey.ptr, key->pkey_sz,
-                            WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
-                    wolfSSL_RSA_free(key->rsa);
-                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    return NULL;
-                }
-            }
-            #endif /* NO_RSA */
-
-            /* decode ECC key */
-            #ifdef HAVE_ECC
-            if (key->type == EVP_PKEY_EC) {
-                word32 idx = 0;
-
-                key->ownEcc = 1;
-                key->ecc = wolfSSL_EC_KEY_new();
-                if (key->ecc == NULL || key->ecc->internal == NULL) {
-                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    return NULL;
-                }
-
-                /* not using wolfSSL_EC_KEY_LoadDer because public key in x509
-                 * is in the format of x963 (no sequence at start of buffer) */
-                if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
-                        &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) {
-                    WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
-                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    wolfSSL_EC_KEY_free(key->ecc);
-                    return NULL;
-                }
-
-                if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) {
-                    WOLFSSL_MSG("SetECKeyExternal failed");
-                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    wolfSSL_EC_KEY_free(key->ecc);
-                    return NULL;
-                }
-
-                key->ecc->inSet = 1;
-            }
-            #endif /* HAVE_ECC */
-        }
-    }
-    return key;
-}
-#endif /* OPENSSL_EXTRA_X509_SMALL */
-#endif /* !NO_CERTS */
-
-/* End of smaller subset of X509 compatibility functions. Avoid increasing the
- * size of this subset and its memory usage */
-#endif /* OPENSSL_EXTRA_X509_SMALL */
-
-#if defined(OPENSSL_EXTRA)
-#if !defined(NO_CERTS)
-    int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
-    {
-        int isSet = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
-
-        if (x509 != NULL) {
-            switch (nid) {
-                case BASIC_CA_OID: isSet = x509->basicConstSet; break;
-                case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
-                case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
-                case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
-                case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
-                #ifdef WOLFSSL_SEP
-                    case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
-                #endif /* WOLFSSL_SEP */
-            }
-        }
-
-        WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
-
-        return isSet;
-    }
-
-
-    int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
-    {
-        int crit = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
-
-        if (x509 != NULL) {
-            switch (nid) {
-                case BASIC_CA_OID: crit = x509->basicConstCrit; break;
-                case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
-                case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
-                case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
-                case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
-                #ifdef WOLFSSL_SEP
-                    case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
-                #endif /* WOLFSSL_SEP */
-            }
-        }
-
-        WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
-
-        return crit;
-    }
-
-
-    int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
-    {
-        int isSet = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
-
-        if (x509 != NULL)
-            isSet = x509->basicConstPlSet;
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
-
-        return isSet;
-    }
-
-
-    word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
-    {
-        word32 pathLength = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
-
-        if (x509 != NULL)
-            pathLength = x509->pathLength;
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
-
-        return pathLength;
-    }
-
-
-    unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
-    {
-        word16 usage = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
-
-        if (x509 != NULL)
-            usage = x509->keyUsage;
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
-
-        return usage;
-    }
-
-
-    byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509,
-                                          byte* dst, int* dstLen)
-    {
-        byte *id = NULL;
-        int copySz = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
-
-        if (x509 != NULL) {
-            if (x509->authKeyIdSet) {
-                copySz = min(dstLen != NULL ? *dstLen : 0,
-                             (int)x509->authKeyIdSz);
-                id = x509->authKeyId;
-            }
-
-            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
-                XMEMCPY(dst, id, copySz);
-                id = dst;
-                *dstLen = copySz;
-            }
-        }
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
-
-        return id;
-    }
-
-
-    byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
-                                        byte* dst, int* dstLen)
-    {
-        byte *id = NULL;
-        int copySz = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
-
-        if (x509 != NULL) {
-            if (x509->subjKeyIdSet) {
-                copySz = min(dstLen != NULL ? *dstLen : 0,
-                                                        (int)x509->subjKeyIdSz);
-                id = x509->subjKeyId;
-            }
-
-            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
-                XMEMCPY(dst, id, copySz);
-                id = dst;
-                *dstLen = copySz;
-            }
-        }
-
-        WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
-
-        return id;
-    }
-
-
-    int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name)
-    {
-        int count = 0;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count");
-
-        if (name != NULL)
-            count = name->fullName.entryCount;
-
-        WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
-        return count;
-    }
-
-
-
-    int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name,
-                                          int nid, int pos)
-    {
-        int ret    = -1;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID");
-
-        if (name == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        /* these index values are already stored in DecodedName
-           use those when available */
-        if (name->fullName.fullName && name->fullName.fullNameLen > 0) {
-            name->fullName.dcMode = 0;
-            switch (nid) {
-                case ASN_COMMON_NAME:
-                    if (pos != name->fullName.cnIdx)
-                        ret = name->fullName.cnIdx;
-                    break;
-                case ASN_DOMAIN_COMPONENT:
-                    name->fullName.dcMode = 1;
-                    if (pos < name->fullName.dcNum - 1){
-                        ret = pos + 1;
-                    } else {
-                        ret = -1;
-                    }
-                    break;
-                default:
-                    WOLFSSL_MSG("NID not yet implemented");
-                    break;
-            }
-        }
-
-        WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_index_by_NID", ret);
-
-        (void)pos;
-        (void)nid;
-
-        return ret;
-    }
-
-
-    WOLFSSL_ASN1_STRING*  wolfSSL_X509_NAME_ENTRY_get_data(
-                                                    WOLFSSL_X509_NAME_ENTRY* in)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data");
-        return in->value;
-    }
-
-
-    /* Creates a new WOLFSSL_ASN1_STRING structure.
-     *
-     * returns a pointer to the new structure created on success or NULL if fail
-     */
-    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new()
-    {
-        WOLFSSL_ASN1_STRING* asn1;
-
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new");
-
-        asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL,
-                DYNAMIC_TYPE_OPENSSL);
-        if (asn1 != NULL) {
-            XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
-        }
-
-        return asn1; /* no check for null because error case is returning null*/
-    }
-
-
-    /* used to free a WOLFSSL_ASN1_STRING structure */
-    void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1)
-    {
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free");
-
-        if (asn1 != NULL) {
-            if (asn1->length > 0 && asn1->data != NULL) {
-                XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
-            }
-            XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL);
-        }
-    }
-
-
-    /* Creates a new WOLFSSL_ASN1_STRING structure given the input type.
-     *
-     * type is the type of set when WOLFSSL_ASN1_STRING is created
-     *
-     * returns a pointer to the new structure created on success or NULL if fail
-     */
-    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type)
-    {
-        WOLFSSL_ASN1_STRING* asn1;
-
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new");
-
-        asn1 = wolfSSL_ASN1_STRING_new();
-        if (asn1 == NULL) {
-            return NULL;
-        }
-        asn1->type = type;
-
-        return asn1;
-    }
-
-
-    /* if dataSz is negative then use XSTRLEN to find length of data
-     * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
-    int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data,
-            int dataSz)
-    {
-        int sz;
-
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set");
-
-        if (data == NULL || asn1 == NULL) {
-            return WOLFSSL_FAILURE;
-        }
-
-        if (dataSz < 0) {
-            sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */
-        }
-        else {
-            sz = dataSz;
-        }
-
-        if (sz < 0) {
-            return WOLFSSL_FAILURE;
-        }
-
-        /* free any existing data before copying */
-        if (asn1->data != NULL) {
-            XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
-        }
-
-        /* create new data buffer and copy over */
-        asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
-        if (asn1->data == NULL) {
-            return WOLFSSL_FAILURE;
-        }
-        XMEMCPY(asn1->data, data, sz);
-        asn1->length = sz;
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn)
-    {
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data");
-
-        if (asn) {
-            return (unsigned char*)asn->data;
-        }
-        else {
-            return NULL;
-        }
-    }
-
-
-    int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn)
-    {
-        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length");
-
-        if (asn) {
-            return asn->length;
-        }
-        else {
-            return 0;
-        }
-    }
-
-
-#ifdef XSNPRINTF /* a snprintf function needs to be available */
-    /* Writes the human readable form of x509 to bio.
-     *
-     * bio  WOLFSSL_BIO to write to.
-     * x509 Certificate to write.
-     *
-     * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
-     */
-    int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
-    {
-        WOLFSSL_ENTER("wolfSSL_X509_print");
-
-        if (bio == NULL || x509 == NULL) {
-            return WOLFSSL_FAILURE;
-        }
-
-        if (wolfSSL_BIO_write(bio, "Certificate:\n", sizeof("Certificate:\n"))
-            <= 0) {
-                return WOLFSSL_FAILURE;
-        }
-
-        if (wolfSSL_BIO_write(bio, "    Data:\n", sizeof("    Data:\n"))
-            <= 0) {
-                return WOLFSSL_FAILURE;
-        }
-
-        /* print version of cert */
-        {
-            int version;
-            char tmp[17];
-
-            if ((version = wolfSSL_X509_version(x509)) <= 0) {
-                WOLFSSL_MSG("Error getting X509 version");
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "        Version: ",
-                                sizeof("        Version: ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-	        XSNPRINTF(tmp, sizeof(tmp), "%d\n", version);
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print serial number out */
-        {
-            unsigned char serial[32];
-            int  sz = sizeof(serial);
-
-            XMEMSET(serial, 0, sz);
-            if (wolfSSL_X509_get_serial_number(x509, serial, &sz)
-                    != WOLFSSL_SUCCESS) {
-                WOLFSSL_MSG("Error getting x509 serial number");
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "        Serial Number: ",
-                                sizeof("        Serial Number: ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-
-            /* if serial can fit into byte than print on the same line */
-            if (sz <= (int)sizeof(byte)) {
-                char tmp[17];
-                XSNPRINTF(tmp, sizeof(tmp), "%d (0x%x)\n", serial[0],serial[0]);
-                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            else {
-                int i;
-                char tmp[100];
-                int  tmpSz = 100;
-                char val[5];
-                int  valSz = 5;
-
-                /* serial is larger than int size so print off hex values */
-                if (wolfSSL_BIO_write(bio, "\n            ",
-                                sizeof("\n            ")) <= 0) {
-                    return WOLFSSL_FAILURE;
-                }
-                tmp[0] = '\0';
-                for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) {
-                    XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]);
-                    val[3] = '\0'; /* make sure is null terminated */
-                    XSTRNCAT(tmp, val, valSz);
-                }
-                XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]);
-                val[3] = '\0'; /* make sure is null terminated */
-                XSTRNCAT(tmp, val, valSz);
-                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                    return WOLFSSL_FAILURE;
-                }
-            }
-        }
-
-        /* print signature algo */
-        {
-            int   oid;
-            char* sig;
-
-            if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) {
-                WOLFSSL_MSG("Error getting x509 signature type");
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "    Signature Algorithm: ",
-                                sizeof("    Signature Algorithm: ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            sig = GetSigName(oid);
-            if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print issuer */
-        {
-            char* issuer;
-        #ifdef WOLFSSL_SMALL_STACK
-            char* buff  = NULL;
-            int   issSz = 0;
-        #else
-            char buff[256];
-            int  issSz = 256;
-        #endif
-
-            issuer  = wolfSSL_X509_NAME_oneline(
-                             wolfSSL_X509_get_issuer_name(x509), buff, issSz);
-
-            if (wolfSSL_BIO_write(bio, "        Issuer: ",
-                                sizeof("        Issuer: ")) <= 0) {
-                #ifdef WOLFSSL_SMALL_STACK
-                XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-                #endif
-                return WOLFSSL_FAILURE;
-            }
-            if (issuer != NULL) {
-                if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
-                    #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-                    #endif
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            #ifdef WOLFSSL_SMALL_STACK
-            XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-            #endif
-            if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print validity */
-        {
-            char tmp[80];
-
-            if (wolfSSL_BIO_write(bio, "        Validity\n",
-                                sizeof("        Validity\n")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "            Not Before: ",
-                                sizeof("            Not Before: ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (GetTimeString(x509->notBefore + 2, ASN_UTC_TIME,
-                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
-                if (GetTimeString(x509->notBefore + 2, ASN_GENERALIZED_TIME,
-                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
-                    WOLFSSL_MSG("Error getting not before date");
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_BIO_write(bio, "\n            Not After : ",
-                                sizeof("\n            Not After : ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (GetTimeString(x509->notAfter + 2,ASN_UTC_TIME,
-                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
-                if (GetTimeString(x509->notAfter + 2,ASN_GENERALIZED_TIME,
-                    tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
-                    WOLFSSL_MSG("Error getting not before date");
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print subject */
-        {
-            char* subject;
-        #ifdef WOLFSSL_SMALL_STACK
-            char* buff  = NULL;
-            int   subSz = 0;
-        #else
-            char buff[256];
-            int  subSz = 256;
-        #endif
-
-            subject  = wolfSSL_X509_NAME_oneline(
-                             wolfSSL_X509_get_subject_name(x509), buff, subSz);
-
-            if (wolfSSL_BIO_write(bio, "\n        Subject: ",
-                                sizeof("\n        Subject: ")) <= 0) {
-                #ifdef WOLFSSL_SMALL_STACK
-                XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
-                #endif
-                return WOLFSSL_FAILURE;
-            }
-            if (subject != NULL) {
-                if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) {
-                    #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
-                    #endif
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            #ifdef WOLFSSL_SMALL_STACK
-            XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
-            #endif
-        }
-
-        /* get and print public key */
-        if (wolfSSL_BIO_write(bio, "\n        Subject Public Key Info:\n",
-                          sizeof("\n        Subject Public Key Info:\n")) <= 0) {
-            return WOLFSSL_FAILURE;
-        }
-        {
-            char tmp[100];
-
-            switch (x509->pubKeyOID) {
-                #ifndef NO_RSA
-                case RSAk:
-                    if (wolfSSL_BIO_write(bio,
-                                "            Public Key Algorithm: RSA\n",
-                      sizeof("            Public Key Algorithm: RSA\n")) <= 0) {
-                        return WOLFSSL_FAILURE;
-                    }
-                #ifdef HAVE_USER_RSA
-                    if (wolfSSL_BIO_write(bio,
-                        "                Build without user RSA to print key\n",
-                sizeof("                Build without user RSA to print key\n"))
-                        <= 0) {
-                        return WOLFSSL_FAILURE;
-                    }
-                #else
-                    {
-                        RsaKey rsa;
-                        word32 idx = 0;
-                        int  sz;
-                        byte lbit = 0;
-                        int  rawLen;
-                        unsigned char* rawKey;
-
-                        if (wc_InitRsaKey(&rsa, NULL) != 0) {
-                            WOLFSSL_MSG("wc_InitRsaKey failure");
-                            return WOLFSSL_FAILURE;
-                        }
-                        if (wc_RsaPublicKeyDecode(x509->pubKey.buffer,
-                                &idx, &rsa, x509->pubKey.length) != 0) {
-                            WOLFSSL_MSG("Error decoding RSA key");
-                            return WOLFSSL_FAILURE;
-                        }
-                        if ((sz = wc_RsaEncryptSize(&rsa)) < 0) {
-                            WOLFSSL_MSG("Error getting RSA key size");
-                            return WOLFSSL_FAILURE;
-                        }
-                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
-                                "                 ", "Public-Key", 8 * sz,
-                                "                 Modulus:");
-                        tmp[sizeof(tmp) - 1] = '\0';
-                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                            return WOLFSSL_FAILURE;
-                        }
-
-                        /* print out modulus */
-                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                     ");
-                        tmp[sizeof(tmp) - 1] = '\0';
-                        if (mp_leading_bit(&rsa.n)) {
-                            lbit = 1;
-                            XSTRNCAT(tmp, "00", sizeof("00"));
-                        }
-
-                        rawLen = mp_unsigned_bin_size(&rsa.n);
-                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
-                                DYNAMIC_TYPE_TMP_BUFFER);
-                        if (rawKey == NULL) {
-                            WOLFSSL_MSG("Memory error");
-                            return WOLFSSL_FAILURE;
-                        }
-                        mp_to_unsigned_bin(&rsa.n, rawKey);
-                        for (idx = 0; idx < (word32)rawLen; idx++) {
-                            char val[5];
-                            int valSz = 5;
-
-                            if ((idx == 0) && !lbit) {
-                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
-                            }
-                            else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
-                                tmp[sizeof(tmp) - 1] = '\0';
-                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
-                                        <= 0) {
-                                    XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                                    return WOLFSSL_FAILURE;
-                                }
-                                XSNPRINTF(tmp, sizeof(tmp) - 1,
-                                        ":\n                     ");
-                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
-                            }
-                            else {
-                                XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
-                            }
-                            XSTRNCAT(tmp, val, valSz);
-                        }
-                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-                        /* print out remaning modulus values */
-                        if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
-                                tmp[sizeof(tmp) - 1] = '\0';
-                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
-                                        <= 0) {
-                                    return WOLFSSL_FAILURE;
-                                }
-                        }
-
-                        /* print out exponent values */
-                        rawLen = mp_unsigned_bin_size(&rsa.e);
-                        if (rawLen < 0) {
-                            WOLFSSL_MSG("Error getting exponent size");
-                            return WOLFSSL_FAILURE;
-                        }
-
-                        if ((word32)rawLen < sizeof(word32)) {
-                            rawLen = sizeof(word32);
-                        }
-                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
-                                DYNAMIC_TYPE_TMP_BUFFER);
-                        if (rawKey == NULL) {
-                            WOLFSSL_MSG("Memory error");
-                            return WOLFSSL_FAILURE;
-                        }
-                        XMEMSET(rawKey, 0, rawLen);
-                        mp_to_unsigned_bin(&rsa.e, rawKey);
-                        if ((word32)rawLen <= sizeof(word32)) {
-                            idx = *(word32*)rawKey;
-                        }
-                        XSNPRINTF(tmp, sizeof(tmp) - 1,
-                        "\n                 Exponent: %d\n", idx);
-                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                            XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                            return WOLFSSL_FAILURE;
-                        }
-                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                    }
-                #endif /* HAVE_USER_RSA */
-                    break;
-                #endif /* NO_RSA */
-
-                #ifdef HAVE_ECC
-                case ECDSAk:
-                    {
-                        word32 i;
-                        ecc_key ecc;
-
-                        if (wolfSSL_BIO_write(bio,
-                                "            Public Key Algorithm: EC\n",
-                      sizeof("            Public Key Algorithm: EC\n")) <= 0) {
-                        return WOLFSSL_FAILURE;
-                        }
-                        if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID)
-                                != 0) {
-                            return WOLFSSL_FAILURE;
-                        }
-
-                        i = 0;
-                        if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i,
-                                              &ecc, x509->pubKey.length) != 0) {
-                            wc_ecc_free(&ecc);
-                            return WOLFSSL_FAILURE;
-                        }
-                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
-                                "                 ", "Public-Key",
-                                8 * wc_ecc_size(&ecc),
-                                "                 pub:");
-                        tmp[sizeof(tmp) - 1] = '\0';
-                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                            wc_ecc_free(&ecc);
-                            return WOLFSSL_FAILURE;
-                        }
-                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                     ");
-                        {
-                            word32 derSz;
-                            byte*  der;
-
-                            derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE;
-                            der = (byte*)XMALLOC(derSz, x509->heap,
-                                    DYNAMIC_TYPE_TMP_BUFFER);
-                            if (der == NULL) {
-                                wc_ecc_free(&ecc);
-                                return WOLFSSL_FAILURE;
-                            }
-
-                            if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) {
-                                wc_ecc_free(&ecc);
-                                XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                                return WOLFSSL_FAILURE;
-                            }
-                            for (i = 0; i < derSz; i++) {
-                                char val[5];
-                                int valSz = 5;
-
-                                if (i == 0) {
-                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
-                                }
-                                else if ((i % 15) == 0) {
-                                    tmp[sizeof(tmp) - 1] = '\0';
-                                    if (wolfSSL_BIO_write(bio, tmp,
-                                                (int)XSTRLEN(tmp)) <= 0) {
-                                        wc_ecc_free(&ecc);
-                                        XFREE(der, x509->heap,
-                                                DYNAMIC_TYPE_TMP_BUFFER);
-                                        return WOLFSSL_FAILURE;
-                                    }
-                                    XSNPRINTF(tmp, sizeof(tmp) - 1,
-                                        ":\n                     ");
-                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
-                                }
-                                else {
-                                    XSNPRINTF(val, valSz - 1, ":%02x", der[i]);
-                                }
-                                XSTRNCAT(tmp, val, valSz);
-                            }
-
-                            /* print out remaning modulus values */
-                            if ((i > 0) && (((i - 1) % 15) != 0)) {
-                                tmp[sizeof(tmp) - 1] = '\0';
-                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
-                                        <= 0) {
-                                    wc_ecc_free(&ecc);
-                                    XFREE(der, x509->heap,
-                                                DYNAMIC_TYPE_TMP_BUFFER);
-                                    return WOLFSSL_FAILURE;
-                                }
-                            }
-
-                            XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                        }
-                        XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n",
-                                "                ", "ASN1 OID",
-                                ecc.dp->name);
-                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                            wc_ecc_free(&ecc);
-                            return WOLFSSL_FAILURE;
-                        }
-                        wc_ecc_free(&ecc);
-                    }
-                    break;
-                #endif /* HAVE_ECC */
-                default:
-                    WOLFSSL_MSG("Unknown key type");
-                    return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print out extensions */
-        if (wolfSSL_BIO_write(bio, "        X509v3 extensions:\n",
-                            sizeof("        X509v3 extensions:\n")) <= 0) {
-            return WOLFSSL_FAILURE;
-        }
-
-        /* print subject key id */
-        if (x509->subjKeyIdSet && x509->subjKeyId != NULL &&
-                x509->subjKeyIdSz > 0) {
-            char tmp[100];
-            word32 i;
-            char val[5];
-            int valSz = 5;
-
-
-            if (wolfSSL_BIO_write(bio,
-                        "            X509v3 Subject Key Identifier:\n",
-                 sizeof("            X509v3 Subject Key Identifier:\n"))
-                 <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-
-            XSNPRINTF(tmp, sizeof(tmp) - 1, "                 ");
-            for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) {
-                XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]);
-                XSTRNCAT(tmp, val, valSz);
-            }
-            XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]);
-            XSTRNCAT(tmp, val, valSz);
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* printf out authority key id */
-        if (x509->authKeyIdSet && x509->authKeyId != NULL &&
-                x509->authKeyIdSz > 0) {
-            char tmp[100];
-            word32 i;
-            char val[5];
-            int valSz = 5;
-
-            if (wolfSSL_BIO_write(bio,
-                        "            X509v3 Authority Key Identifier:\n",
-                 sizeof("            X509v3 Authority Key Identifier:\n"))
-                 <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-
-            XSNPRINTF(tmp, sizeof(tmp) - 1, "                 keyid");
-            for (i = 0; i < x509->authKeyIdSz; i++) {
-                /* check if buffer is almost full */
-                if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) {
-                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                        return WOLFSSL_FAILURE;
-                    }
-                    tmp[0] = '\0';
-                }
-                XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]);
-                XSTRNCAT(tmp, val, valSz);
-            }
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-
-            /* print issuer */
-            {
-                char* issuer;
-            #ifdef WOLFSSL_SMALL_STACK
-                char* buff  = NULL;
-                int   issSz = 0;
-            #else
-                char buff[256];
-                int  issSz = 256;
-            #endif
-
-                issuer  = wolfSSL_X509_NAME_oneline(
-                               wolfSSL_X509_get_issuer_name(x509), buff, issSz);
-
-                if (wolfSSL_BIO_write(bio, "\n                 DirName:",
-                                  sizeof("\n                 DirName:")) <= 0) {
-                    #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-                    #endif
-                    return WOLFSSL_FAILURE;
-                }
-                if (issuer != NULL) {
-                    if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
-                        #ifdef WOLFSSL_SMALL_STACK
-                        XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-                        #endif
-                        return WOLFSSL_FAILURE;
-                    }
-                }
-                #ifdef WOLFSSL_SMALL_STACK
-                XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
-                #endif
-                if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
-                    return WOLFSSL_FAILURE;
-                }
-            }
-        }
-
-        /* print basic constraint */
-        if (x509->basicConstSet) {
-            char tmp[100];
-
-            if (wolfSSL_BIO_write(bio,
-                        "\n            X509v3 Basic Constraints:\n",
-                 sizeof("\n            X509v3 Basic Constraints:\n"))
-                 <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            XSNPRINTF(tmp, sizeof(tmp),
-                    "                    CA:%s\n",
-                    (x509->isCa)? "TRUE": "FALSE");
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-        }
-
-        /* print out signature */
-        {
-            unsigned char* sig;
-            int sigSz;
-            int i;
-            char tmp[100];
-            int sigOid = wolfSSL_X509_get_signature_type(x509);
-
-            if (wolfSSL_BIO_write(bio,
-                                "    Signature Algorithm: ",
-                      sizeof("    Signature Algorithm: ")) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid));
-            tmp[sizeof(tmp) - 1] = '\0';
-            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-
-            sigSz = (int)x509->sig.length;
-            sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            if (sig == NULL || sigSz <= 0) {
-                return WOLFSSL_FAILURE;
-            }
-            if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) {
-                XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                return WOLFSSL_FAILURE;
-            }
-            XSNPRINTF(tmp, sizeof(tmp) - 1,"         ");
-            tmp[sizeof(tmp) - 1] = '\0';
-            for (i = 0; i < sigSz; i++) {
-                char val[5];
-                int valSz = 5;
-
-                if (i == 0) {
-                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
-                }
-                else if (((i % 18) == 0)) {
-                    tmp[sizeof(tmp) - 1] = '\0';
-                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
-                            <= 0) {
-                        XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                        return WOLFSSL_FAILURE;
-                    }
-                    XSNPRINTF(tmp, sizeof(tmp) - 1,
-                            ":\n         ");
-                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
-                }
-                else {
-                    XSNPRINTF(val, valSz - 1, ":%02x", sig[i]);
-                }
-                XSTRNCAT(tmp, val, valSz);
-            }
-            XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-            /* print out remaning sig values */
-            if ((i > 0) && (((i - 1) % 18) != 0)) {
-                    tmp[sizeof(tmp) - 1] = '\0';
-                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
-                            <= 0) {
-                        return WOLFSSL_FAILURE;
-                    }
-            }
-        }
-
-        /* done with print out */
-        if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
-            return WOLFSSL_FAILURE;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-#endif /* XSNPRINTF */
-
-#endif /* NO_CERTS */
-
-char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in,
-                                 int len)
-{
-    char *ret = in;
-    const char *keaStr, *authStr, *encStr, *macStr;
-    size_t strLen;
-
-    if (cipher == NULL || in == NULL)
-        return NULL;
-
-    switch (cipher->ssl->specs.kea) {
-        case no_kea:
-            keaStr = "None";
-            break;
-#ifndef NO_RSA
-        case rsa_kea:
-            keaStr = "RSA";
-            break;
-#endif
-#ifndef NO_DH
-        case diffie_hellman_kea:
-            keaStr = "DHE";
-            break;
-#endif
-        case fortezza_kea:
-            keaStr = "FZ";
-            break;
-#ifndef NO_PSK
-        case psk_kea:
-            keaStr = "PSK";
-            break;
-    #ifndef NO_DH
-        case dhe_psk_kea:
-            keaStr = "DHEPSK";
-            break;
-    #endif
-    #ifdef HAVE_ECC
-        case ecdhe_psk_kea:
-            keaStr = "ECDHEPSK";
-            break;
-    #endif
-#endif
-#ifdef HAVE_NTRU
-        case ntru_kea:
-            keaStr = "NTRU";
-            break;
-#endif
-#ifdef HAVE_ECC
-        case ecc_diffie_hellman_kea:
-            keaStr = "ECDHE";
-            break;
-        case ecc_static_diffie_hellman_kea:
-            keaStr = "ECDH";
-            break;
-#endif
-        default:
-            keaStr = "unknown";
-            break;
-    }
-
-    switch (cipher->ssl->specs.sig_algo) {
-        case anonymous_sa_algo:
-            authStr = "None";
-            break;
-#ifndef NO_RSA
-        case rsa_sa_algo:
-            authStr = "RSA";
-            break;
-#endif
-#ifndef NO_DSA
-        case dsa_sa_algo:
-            authStr = "DSA";
-            break;
-#endif
-#ifdef HAVE_ECC
-        case ecc_dsa_sa_algo:
-            authStr = "ECDSA";
-            break;
-#endif
-        default:
-            authStr = "unknown";
-            break;
-    }
-
-    switch (cipher->ssl->specs.bulk_cipher_algorithm) {
-        case wolfssl_cipher_null:
-            encStr = "None";
-            break;
-#ifndef NO_RC4
-        case wolfssl_rc4:
-            encStr = "RC4(128)";
-            break;
-#endif
-#ifndef NO_DES3
-        case wolfssl_triple_des:
-            encStr = "3DES(168)";
-            break;
-#endif
-#ifdef HAVE_IDEA
-        case wolfssl_idea:
-            encStr = "IDEA(128)";
-            break;
-#endif
-#ifndef NO_AES
-        case wolfssl_aes:
-            if (cipher->ssl->specs.key_size == 128)
-                encStr = "AES(128)";
-            else if (cipher->ssl->specs.key_size == 256)
-                encStr = "AES(256)";
-            else
-                encStr = "AES(?)";
-            break;
-    #ifdef HAVE_AESGCM
-        case wolfssl_aes_gcm:
-            if (cipher->ssl->specs.key_size == 128)
-                encStr = "AESGCM(128)";
-            else if (cipher->ssl->specs.key_size == 256)
-                encStr = "AESGCM(256)";
-            else
-                encStr = "AESGCM(?)";
-            break;
-    #endif
-    #ifdef HAVE_AESCCM
-        case wolfssl_aes_ccm:
-            if (cipher->ssl->specs.key_size == 128)
-                encStr = "AESCCM(128)";
-            else if (cipher->ssl->specs.key_size == 256)
-                encStr = "AESCCM(256)";
-            else
-                encStr = "AESCCM(?)";
-            break;
-    #endif
-#endif
-#ifdef HAVE_CHACHA
-        case wolfssl_chacha:
-            encStr = "CHACHA20/POLY1305(256)";
-            break;
-#endif
-#ifdef HAVE_CAMELLIA
-        case wolfssl_camellia:
-            if (cipher->ssl->specs.key_size == 128)
-                encStr = "Camellia(128)";
-            else if (cipher->ssl->specs.key_size == 256)
-                encStr = "Camellia(256)";
-            else
-                encStr = "Camellia(?)";
-            break;
-#endif
-#if defined(HAVE_HC128) && !defined(NO_HC128)
-        case wolfssl_hc128:
-            encStr = "HC128(128)";
-            break;
-#endif
-#if defined(HAVE_RABBIT) && !defined(NO_RABBIT)
-        case wolfssl_rabbit:
-            encStr = "RABBIT(128)";
-            break;
-#endif
-        default:
-            encStr = "unknown";
-            break;
-    }
-
-    switch (cipher->ssl->specs.mac_algorithm) {
-        case no_mac:
-            macStr = "None";
-            break;
-#ifndef NO_MD5
-        case md5_mac:
-            macStr = "MD5";
-            break;
-#endif
-#ifndef NO_SHA
-        case sha_mac:
-            macStr = "SHA1";
-            break;
-#endif
-#ifdef HAVE_SHA224
-        case sha224_mac:
-            macStr = "SHA224";
-            break;
-#endif
-#ifndef NO_SHA256
-        case sha256_mac:
-            macStr = "SHA256";
-            break;
-#endif
-#ifdef HAVE_SHA384
-        case sha384_mac:
-            macStr = "SHA384";
-            break;
-#endif
-#ifdef HAVE_SHA512
-        case sha512_mac:
-            macStr = "SHA512";
-            break;
-#endif
-#ifdef HAVE_BLAKE2
-        case blake2b_mac:
-            macStr = "BLAKE2b";
-            break;
-#endif
-        default:
-            macStr = "unknown";
-            break;
-    }
-
-    /* Build up the string by copying onto the end. */
-    XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-
-    XSTRNCPY(in, " ", len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-    XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-
-    XSTRNCPY(in, " Kx=", len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-    XSTRNCPY(in, keaStr, len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-
-    XSTRNCPY(in, " Au=", len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-    XSTRNCPY(in, authStr, len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-
-    XSTRNCPY(in, " Enc=", len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-    XSTRNCPY(in, encStr, len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-
-    XSTRNCPY(in, " Mac=", len);
-    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
-    XSTRNCPY(in, macStr, len);
-    in[len-1] = '\0';
-
-    return ret;
-}
-
-
-#ifndef NO_SESSION_CACHE
-
-WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl)
-{
-    if (ssl == NULL) {
-        return NULL;
-    }
-
-    /* sessions are stored statically, no need for reference count */
-    return wolfSSL_get_session(ssl);
-}
-
-#endif /* NO_SESSION_CACHE */
-
-
-
-/* was do nothing */
-/*
-void OPENSSL_free(void* buf)
-{
-    (void)buf;
-}
-*/
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
-                   int* ssl)
-{
-    (void)url;
-    (void)host;
-    (void)port;
-    (void)path;
-    (void)ssl;
-    WOLFSSL_STUB("OCSP_parse_url");
-    return 0;
-}
-#endif
-
-WOLFSSL_METHOD* wolfSSLv2_client_method(void)
-{
-    return 0;
-}
-
-
-WOLFSSL_METHOD* wolfSSLv2_server_method(void)
-{
-    return 0;
-}
-
-
-#ifndef NO_MD4
-
-void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4)
-{
-    /* make sure we have a big enough buffer */
-    typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
-    (void) sizeof(ok);
-
-    WOLFSSL_ENTER("MD4_Init");
-    wc_InitMd4((Md4*)md4);
-}
-
-
-void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data,
-                       unsigned long len)
-{
-    WOLFSSL_ENTER("MD4_Update");
-    wc_Md4Update((Md4*)md4, (const byte*)data, (word32)len);
-}
-
-
-void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
-{
-    WOLFSSL_ENTER("MD4_Final");
-    wc_Md4Final((Md4*)md4, digest);
-}
-
-#endif /* NO_MD4 */
-
-
-/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list.
- *
- * bio is the WOLFSSL_BIO struct in the list and removed.
- *
- * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if
- * there is none.
- */
-WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio)
-{
-    if (bio == NULL) {
-        WOLFSSL_MSG("Bad argument passed in");
-        return NULL;
-    }
-
-    if (bio->prev != NULL) {
-        bio->prev->next = bio->next;
-    }
-
-    if (bio->next != NULL) {
-        bio->next->prev = bio->prev;
-    }
-
-    return bio->next;
-}
-
-
-int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
-{
-    return (int)wolfSSL_BIO_ctrl_pending(bio);
-}
-
-
-
-WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
-{
-    static WOLFSSL_BIO_METHOD meth;
-
-    WOLFSSL_ENTER("BIO_s_mem");
-    meth.type = WOLFSSL_BIO_MEMORY;
-
-    return &meth;
-}
-
-
-WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void)
-{
-    static WOLFSSL_BIO_METHOD meth;
-
-    WOLFSSL_ENTER("wolfSSL_BIO_f_base64");
-    meth.type = WOLFSSL_BIO_BASE64;
-
-    return &meth;
-}
-
-
-/* Set the flag for the bio.
- *
- * bio   the structre to set the flag in
- * flags the flag to use
- */
-void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags)
-{
-    WOLFSSL_ENTER("wolfSSL_BIO_set_flags");
-
-    if (bio != NULL) {
-        bio->flags |= flags;
-    }
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_RAND_screen(void)
-{
-    WOLFSSL_STUB("RAND_screen");
-}
-#endif
-
-
-
-int wolfSSL_RAND_load_file(const char* fname, long len)
-{
-    (void)fname;
-    /* wolfCrypt provides enough entropy internally or will report error */
-    if (len == -1)
-        return 1024;
-    else
-        return (int)len;
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
-{
-    WOLFSSL_STUB("COMP_zlib");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
-{
-    WOLFSSL_STUB("COMP_rle");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_COMP_add_compression_method(int method, void* data)
-{
-    (void)method;
-    (void)data;
-    WOLFSSL_STUB("COMP_add_compression_method");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)(
-                                                          const char*, int))
-{
-    WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback");
-    (void)f;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_set_dynlock_lock_callback(
-             void (*f)(int, WOLFSSL_dynlock_value*, const char*, int))
-{
-    WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback");
-    (void)f;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_set_dynlock_destroy_callback(
-                  void (*f)(WOLFSSL_dynlock_value*, const char*, int))
-{
-    WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback");
-    (void)f;
-}
-#endif
-
-
-const char* wolfSSL_X509_verify_cert_error_string(long err)
-{
-    return wolfSSL_ERR_reason_error_string(err);
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir,
-                               long len)
-{
-    (void)lookup;
-    (void)dir;
-    (void)len;
-    WOLFSSL_STUB("X509_LOOKUP_add_dir");
-    return 0;
-}
-#endif
-
-int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup,
-                                 const char* file, long type)
-{
-#if !defined(NO_FILESYSTEM) && \
-    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
-    int           ret = WOLFSSL_FAILURE;
-    XFILE         fp;
-    long          sz;
-    byte*         pem = NULL;
-    byte*         curr = NULL;
-    byte*         prev = NULL;
-    WOLFSSL_X509* x509;
-    const char* header = NULL;
-    const char* footer = NULL;
-
-    if (type != X509_FILETYPE_PEM)
-        return BAD_FUNC_ARG;
-
-    fp = XFOPEN(file, "r");
-    if (fp == NULL)
-        return BAD_FUNC_ARG;
-
-    XFSEEK(fp, 0, XSEEK_END);
-    sz = XFTELL(fp);
-    XREWIND(fp);
-
-    if (sz <= 0)
-        goto end;
-
-    pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM);
-    if (pem == NULL) {
-        ret = MEMORY_ERROR;
-        goto end;
-    }
-
-    /* Read in file which may be CRLs or certificates. */
-    if (XFREAD(pem, (size_t)sz, 1, fp) != 1)
-        goto end;
-
-    prev = curr = pem;
-    do {
-        /* get PEM header and footer based on type */
-        if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
-                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
-#ifdef HAVE_CRL
-            WOLFSSL_CERT_MANAGER* cm = lookup->store->cm;
-
-            if (cm->crl == NULL) {
-                if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
-                    WOLFSSL_MSG("Enable CRL failed");
-                    goto end;
-                }
-            }
-
-            ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM, 1);
-            if (ret != WOLFSSL_SUCCESS)
-                goto end;
-#endif
-            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
-        }
-        else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
-                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
-            x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz,
-                                                        WOLFSSL_FILETYPE_PEM);
-            if (x509 == NULL)
-                 goto end;
-            ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509);
-            wolfSSL_X509_free(x509);
-            if (ret != WOLFSSL_SUCCESS)
-                goto end;
-            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
-        }
-        else
-            goto end;
-
-        if (curr == NULL)
-            goto end;
-
-        curr++;
-        sz -= (long)(curr - prev);
-        prev = curr;
-    }
-    while (ret == WOLFSSL_SUCCESS);
-
-end:
-    if (pem != NULL)
-        XFREE(pem, 0, DYNAMIC_TYPE_PEM);
-    XFCLOSE(fp);
-    return ret;
-#else
-    (void)lookup;
-    (void)file;
-    (void)type;
-    return WOLFSSL_FAILURE;
-#endif
-}
-
-WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void)
-{
-    /* Method implementation in functions. */
-    static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 };
-    return &meth;
-}
-
-WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void)
-{
-    /* Method implementation in functions. */
-    static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 };
-    return &meth;
-}
-
-
-WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
-                                               WOLFSSL_X509_LOOKUP_METHOD* m)
-{
-    /* Method is a dummy value and is not needed. */
-    (void)m;
-    /* Make sure the lookup has a back reference to the store. */
-    store->lookup.store = store;
-    return &store->lookup;
-}
-
-
-#ifndef NO_CERTS
-/* Converts the X509 to DER format and outputs it into bio.
- *
- * bio  is the structure to hold output DER
- * x509 certificate to create DER from
- *
- * returns WOLFSSL_SUCCESS on success
- */
-int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
-{
-    WOLFSSL_ENTER("wolfSSL_i2d_X509_bio");
-
-    if (bio == NULL || x509 == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    if (x509->derCert != NULL) {
-        word32 len = x509->derCert->length;
-        byte*  der = x509->derCert->buffer;
-
-        if (wolfSSL_BIO_write(bio, der, len) == (int)len) {
-            return SSL_SUCCESS;
-        }
-    }
-
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Converts an internal structure to a DER buffer
- *
- * x509 structure to get DER buffer from
- * out  buffer to hold result. If NULL then *out is NULL then a new buffer is
- *      created.
- *
- * returns the size of the DER result on success
- */
-int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
-{
-    const unsigned char* der;
-    int derSz = 0;
-
-    if (x509 == NULL || out == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    der = wolfSSL_X509_get_der(x509, &derSz);
-    if (der == NULL) {
-        return MEMORY_E;
-    }
-
-    if (*out == NULL) {
-        *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
-        if (*out == NULL) {
-            return MEMORY_E;
-        }
-    }
-
-    XMEMCPY(*out, der, derSz);
-
-    return derSz;
-}
-
-
-/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
- *
- * bio  is the structure holding DER
- * x509 certificate to create from DER. Can be NULL
- *
- * returns pointer to WOLFSSL_X509 structure on success and NULL on fail
- */
-WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
-{
-    WOLFSSL_X509* localX509 = NULL;
-    unsigned char* mem  = NULL;
-    int    ret;
-    word32 size;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
-
-    if (bio == NULL) {
-        WOLFSSL_MSG("Bad Function Argument bio is NULL");
-        return NULL;
-    }
-
-    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
-    if (mem == NULL || ret <= 0) {
-        WOLFSSL_MSG("Failed to get data from bio struct");
-        return NULL;
-    }
-    size = ret;
-
-    localX509 = wolfSSL_X509_d2i(NULL, mem, size);
-    if (localX509 == NULL) {
-        return NULL;
-    }
-
-    if (x509 != NULL) {
-        *x509 = localX509;
-    }
-
-    return localX509;
-}
-
-
-#if !defined(NO_ASN) && !defined(NO_PWDBASED)
-WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
-{
-    WC_PKCS12* localPkcs12    = NULL;
-    unsigned char* mem  = NULL;
-    int ret;
-    word32 size;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
-
-    if (bio == NULL) {
-        WOLFSSL_MSG("Bad Function Argument bio is NULL");
-        return NULL;
-    }
-
-    localPkcs12 = wc_PKCS12_new();
-    if (localPkcs12 == NULL) {
-        WOLFSSL_MSG("Memory error");
-        return NULL;
-    }
-
-    if (pkcs12 != NULL) {
-        *pkcs12 = localPkcs12;
-    }
-
-    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
-    if (mem == NULL || ret <= 0) {
-        WOLFSSL_MSG("Failed to get data from bio struct");
-        wc_PKCS12_free(localPkcs12);
-        if (pkcs12 != NULL) {
-            *pkcs12 = NULL;
-        }
-        return NULL;
-    }
-    size = ret;
-
-    ret = wc_d2i_PKCS12(mem, size, localPkcs12);
-    if (ret < 0) {
-        WOLFSSL_MSG("Failed to get PKCS12 sequence");
-        wc_PKCS12_free(localPkcs12);
-        if (pkcs12 != NULL) {
-            *pkcs12 = NULL;
-        }
-        return NULL;
-    }
-
-    return localPkcs12;
-}
-
-
-/* helper function to get DER buffer from WOLFSSL_EVP_PKEY */
-static int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der)
-{
-    *der = (unsigned char*)key->pkey.ptr;
-
-    return key->pkey_sz;
-}
-
-
-
-/* Creates a new WC_PKCS12 structure
- *
- * pass  password to use
- * name  friendlyName to use
- * pkey  private key to go into PKCS12 bundle
- * cert  certificate to go into PKCS12 bundle
- * ca    extra certificates that can be added to bundle. Can be NULL
- * keyNID  type of encryption to use on the key (-1 means no encryption)
- * certNID type of ecnryption to use on the certificate
- * itt     number of iterations with encryption
- * macItt  number of iterations with mac creation
- * keyType flag for signature and/or encryption key
- *
- * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
- */
-WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
-        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
-        WOLF_STACK_OF(WOLFSSL_X509)* ca,
-        int keyNID, int certNID, int itt, int macItt, int keyType)
-{
-    WC_PKCS12*      pkcs12;
-    WC_DerCertList* list = NULL;
-    word32 passSz;
-    byte* keyDer;
-    word32 keyDerSz;
-    byte* certDer;
-    int certDerSz;
-
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_PKCS12_create()");
-
-    if (pass == NULL || pkey == NULL || cert == NULL) {
-        WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG);
-        return NULL;
-    }
-    passSz = (word32)XSTRLEN(pass);
-
-    if ((ret = wolfSSL_i2d_PrivateKey(pkey, &keyDer)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret);
-        return NULL;
-    }
-    keyDerSz = ret;
-
-    certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
-    if (certDer == NULL) {
-        return NULL;
-    }
-
-    if (ca != NULL) {
-        WC_DerCertList* cur;
-        unsigned long numCerts = ca->num;
-        byte* curDer;
-        int   curDerSz = 0;
-        WOLFSSL_STACK* sk = ca;
-
-        while (numCerts > 0 && sk != NULL) {
-            cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
-                    DYNAMIC_TYPE_PKCS);
-            if (cur == NULL) {
-                wc_FreeCertList(list, NULL);
-                return NULL;
-            }
-
-            curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
-            if (curDer == NULL || curDerSz < 0) {
-                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
-                wc_FreeCertList(list, NULL);
-                return NULL;
-            }
-
-            cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
-            if (cur->buffer == NULL) {
-                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
-                wc_FreeCertList(list, NULL);
-                return NULL;
-            }
-            XMEMCPY(cur->buffer, curDer, curDerSz);
-            cur->bufferSz = curDerSz;
-            cur->next = list;
-            list = cur;
-
-            sk = sk->next;
-            numCerts--;
-        }
-    }
-
-    pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
-            certDer, certDerSz, list, keyNID, certNID, itt, macItt,
-            keyType, NULL);
-
-    if (ca != NULL) {
-        wc_FreeCertList(list, NULL);
-    }
-
-    return pkcs12;
-}
-
-
-/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
-int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
-      WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca)
-{
-    DecodedCert DeCert;
-    void* heap = NULL;
-    int ret;
-    byte* certData = NULL;
-    word32 certDataSz;
-    byte* pk = NULL;
-    word32 pkSz;
-    WC_DerCertList* certList = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
-
-    if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
-        WOLFSSL_MSG("Bad argument value");
-        return WOLFSSL_FAILURE;
-    }
-
-    heap  = wc_PKCS12_GetHeap(pkcs12);
-    *pkey = NULL;
-    *cert = NULL;
-
-    if (ca == NULL) {
-        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
-            NULL);
-    }
-    else {
-        *ca = NULL;
-        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
-            &certList);
-    }
-    if (ret < 0) {
-        WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* Decode cert and place in X509 stack struct */
-    if (certList != NULL) {
-        WC_DerCertList* current = certList;
-
-        *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)),
-                                               heap, DYNAMIC_TYPE_X509);
-        if (*ca == NULL) {
-            if (pk != NULL) {
-                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            }
-            if (certData != NULL) {
-                XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
-            }
-            /* Free up WC_DerCertList and move on */
-            while (current != NULL) {
-                WC_DerCertList* next = current->next;
-
-                XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
-                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
-                current = next;
-            }
-            return WOLFSSL_FAILURE;
-        }
-        XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
-
-        /* add list of DER certs as X509's to stack */
-        while (current != NULL) {
-            WC_DerCertList*  toFree = current;
-            WOLFSSL_X509* x509;
-
-            x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
-                                                             DYNAMIC_TYPE_X509);
-            InitX509(x509, 1, heap);
-            InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap);
-            if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
-                WOLFSSL_MSG("Issue with parsing certificate");
-                FreeDecodedCert(&DeCert);
-                wolfSSL_X509_free(x509);
-            }
-            else {
-                if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) {
-                    WOLFSSL_MSG("Failed to copy decoded cert");
-                    FreeDecodedCert(&DeCert);
-                    wolfSSL_X509_free(x509);
-                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                    if (pk != NULL) {
-                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    }
-                    if (certData != NULL) {
-                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
-                    }
-                    /* Free up WC_DerCertList */
-                    while (current != NULL) {
-                        WC_DerCertList* next = current->next;
-
-                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
-                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
-                        current = next;
-                    }
-                    return WOLFSSL_FAILURE;
-                }
-                FreeDecodedCert(&DeCert);
-
-                if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
-                    WOLFSSL_MSG("Failed to push x509 onto stack");
-                    wolfSSL_X509_free(x509);
-                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                    if (pk != NULL) {
-                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                    }
-                    if (certData != NULL) {
-                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
-                    }
-
-                    /* Free up WC_DerCertList */
-                    while (current != NULL) {
-                        WC_DerCertList* next = current->next;
-
-                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
-                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
-                        current = next;
-                    }
-                    return WOLFSSL_FAILURE;
-                }
-            }
-            current = current->next;
-            XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
-            XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
-        }
-    }
-
-
-    /* Decode cert and place in X509 struct */
-    if (certData != NULL) {
-        *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
-                                                             DYNAMIC_TYPE_X509);
-        if (*cert == NULL) {
-            if (pk != NULL) {
-                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            }
-            if (ca != NULL) {
-                wolfSSL_sk_X509_free(*ca); *ca = NULL;
-            }
-            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
-            return WOLFSSL_FAILURE;
-        }
-        InitX509(*cert, 1, heap);
-        InitDecodedCert(&DeCert, certData, certDataSz, heap);
-        if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
-            WOLFSSL_MSG("Issue with parsing certificate");
-        }
-        if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) {
-            WOLFSSL_MSG("Failed to copy decoded cert");
-            FreeDecodedCert(&DeCert);
-            if (pk != NULL) {
-                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            }
-            if (ca != NULL) {
-                wolfSSL_sk_X509_free(*ca); *ca = NULL;
-            }
-            wolfSSL_X509_free(*cert); *cert = NULL;
-            return WOLFSSL_FAILURE;
-        }
-        FreeDecodedCert(&DeCert);
-        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
-    }
-
-
-    /* get key type */
-    ret = BAD_STATE_E;
-    if (pk != NULL) { /* decode key if present */
-        *pkey = wolfSSL_PKEY_new_ex(heap);
-        if (*pkey == NULL) {
-            wolfSSL_X509_free(*cert); *cert = NULL;
-            if (ca != NULL) {
-                wolfSSL_sk_X509_free(*ca); *ca = NULL;
-            }
-            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            return WOLFSSL_FAILURE;
-        }
-        #ifndef NO_RSA
-        {
-            word32 keyIdx = 0;
-            RsaKey key;
-
-            if (wc_InitRsaKey(&key, heap) != 0) {
-                ret = BAD_STATE_E;
-            }
-            else {
-                if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
-                                                                         == 0) {
-                    (*pkey)->type = EVP_PKEY_RSA;
-                    (*pkey)->rsa  = wolfSSL_RSA_new();
-                    (*pkey)->ownRsa = 1; /* we own RSA */
-                    if ((*pkey)->rsa == NULL) {
-                        WOLFSSL_MSG("issue creating EVP RSA key");
-                        wolfSSL_X509_free(*cert); *cert = NULL;
-                        if (ca != NULL) {
-                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                        }
-                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
-                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
-                        return WOLFSSL_FAILURE;
-                    }
-                    if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz,
-                                    WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) {
-                        WOLFSSL_MSG("issue loading RSA key");
-                        wolfSSL_X509_free(*cert); *cert = NULL;
-                        if (ca != NULL) {
-                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                        }
-                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
-                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
-                        return WOLFSSL_FAILURE;
-                    }
-
-                    WOLFSSL_MSG("Found PKCS12 RSA key");
-                    ret = 0; /* set in success state for upcoming ECC check */
-                }
-                wc_FreeRsaKey(&key);
-            }
-        }
-        #endif /* NO_RSA */
-
-        #ifdef HAVE_ECC
-        {
-            word32  keyIdx = 0;
-            ecc_key key;
-
-            if (ret != 0) { /* if is in fail state check if ECC key */
-                if (wc_ecc_init(&key) != 0) {
-                    wolfSSL_X509_free(*cert); *cert = NULL;
-                    if (ca != NULL) {
-                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                    }
-                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
-                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
-                    return WOLFSSL_FAILURE;
-                }
-
-                if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
-                                                                         != 0) {
-                    wolfSSL_X509_free(*cert); *cert = NULL;
-                    if (ca != NULL) {
-                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
-                    }
-                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
-                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
-                    WOLFSSL_MSG("Bad PKCS12 key format");
-                    return WOLFSSL_FAILURE;
-                }
-                (*pkey)->type = EVP_PKEY_EC;
-                (*pkey)->pkey_curve = key.dp->oidSum;
-                wc_ecc_free(&key);
-                WOLFSSL_MSG("Found PKCS12 ECC key");
-            }
-        }
-        #else
-        if (ret != 0) { /* if is in fail state and no ECC then fail */
-            wolfSSL_X509_free(*cert); *cert = NULL;
-            if (ca != NULL) {
-                wolfSSL_sk_X509_free(*ca); *ca = NULL;
-            }
-            wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
-            XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
-            WOLFSSL_MSG("Bad PKCS12 key format");
-            return WOLFSSL_FAILURE;
-        }
-        #endif /* HAVE_ECC */
-
-        (*pkey)->save_type = 0;
-        (*pkey)->pkey_sz   = pkSz;
-        (*pkey)->pkey.ptr  = (char*)pk;
-    }
-
-    (void)ret;
-    (void)ca;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */
-
-
-/* no-op function. Was initially used for adding encryption algorithms available
- * for PKCS12 */
-void wolfSSL_PKCS12_PBE_add(void)
-{
-    WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
-}
-
-
-
-WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain");
-
-    if (ctx == NULL) {
-        return NULL;
-    }
-
-#ifdef SESSION_CERTS
-    /* if chain is null but sesChain is available then populate stack */
-    if (ctx->chain == NULL && ctx->sesChain != NULL) {
-        int i;
-        WOLFSSL_X509_CHAIN* c = ctx->sesChain;
-        WOLFSSL_STACK*     sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),
-                                    NULL, DYNAMIC_TYPE_X509);
-
-        if (sk == NULL) {
-            return NULL;
-        }
-
-        XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
-        ctx->chain = sk;
-
-        for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) {
-            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i);
-
-            if (x509 == NULL) {
-                WOLFSSL_MSG("Unable to get x509 from chain");
-                wolfSSL_sk_X509_free(sk);
-                return NULL;
-            }
-
-            if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
-                WOLFSSL_MSG("Unable to load x509 into stack");
-                wolfSSL_sk_X509_free(sk);
-                wolfSSL_X509_free(x509);
-                return NULL;
-            }
-        }
-
-#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
-        /* add CA used to verify top of chain to the list */
-        if (c->count > 0) {
-            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1);
-            if (x509 != NULL) {
-                WOLFSSL_X509* issuer = NULL;
-                if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509)
-                        == WOLFSSL_SUCCESS) {
-                    /* check that the certificate being looked up is not self
-                     * signed and that a issuer was found */
-                    if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer,
-                                &x509->subject) != 0) {
-                        if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) {
-                            WOLFSSL_MSG("Unable to load CA x509 into stack");
-                            wolfSSL_sk_X509_free(sk);
-                            wolfSSL_X509_free(issuer);
-                            return NULL;
-                        }
-                    }
-                    else {
-                        WOLFSSL_MSG("Certificate is self signed");
-                    }
-                }
-                else {
-                    WOLFSSL_MSG("Could not find CA for certificate");
-                }
-            }
-        }
-#endif
-
-    }
-#endif /* SESSION_CERTS */
-
-    return ctx->chain;
-}
-
-
-int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
-{
-    int result = WOLFSSL_FATAL_ERROR;
-
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert");
-    if (store != NULL && store->cm != NULL && x509 != NULL
-                                                && x509->derCert != NULL) {
-        DerBuffer* derCert = NULL;
-
-        result = AllocDer(&derCert, x509->derCert->length,
-            x509->derCert->type, NULL);
-        if (result == 0) {
-            /* AddCA() frees the buffer. */
-            XMEMCPY(derCert->buffer,
-                            x509->derCert->buffer, x509->derCert->length);
-            result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, 1);
-        }
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result);
-
-    if (result != WOLFSSL_SUCCESS) {
-        result = WOLFSSL_FATAL_ERROR;
-    }
-
-    return result;
-}
-
-WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
-{
-    WOLFSSL_X509_STORE* store = NULL;
-
-    if((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL,
-                            DYNAMIC_TYPE_X509_STORE)) == NULL)
-        goto err_exit;
-
-    if((store->cm = wolfSSL_CertManagerNew()) == NULL)
-        goto err_exit;
-
-    store->isDynamic = 1;
-
-#ifdef HAVE_CRL
-    store->crl = NULL;
-    if((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL),
-                                NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
-        goto err_exit;
-    if(InitCRL(store->crl, NULL) < 0)
-        goto err_exit;
-#endif
-
-    return store;
-
-err_exit:
-    if(store == NULL)
-        return NULL;
-    if(store->cm != NULL)
-        wolfSSL_CertManagerFree(store->cm);
-#ifdef HAVE_CRL
-    if(store->crl != NULL)
-        wolfSSL_X509_CRL_free(store->crl);
-#endif
-    wolfSSL_X509_STORE_free(store);
-
-    return NULL;
-}
-
-
-void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
-{
-    if (store != NULL && store->isDynamic) {
-        if (store->cm != NULL)
-            wolfSSL_CertManagerFree(store->cm);
-#ifdef HAVE_CRL
-        if (store->crl != NULL)
-            wolfSSL_X509_CRL_free(store->crl);
-#endif
-        XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE);
-    }
-}
-
-
-int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag)
-{
-    int ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags");
-
-    if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) {
-        ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag);
-    }
-
-    (void)store;
-    (void)flag;
-
-    return ret;
-}
-
-
-int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store)
-{
-    (void)store;
-    return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
-                            WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj)
-{
-    (void)ctx;
-    (void)idx;
-    (void)name;
-    (void)obj;
-    WOLFSSL_STUB("X509_STORE_get_by_subject");
-    return 0;
-}
-#endif
-
-WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void)
-{
-    WOLFSSL_X509_STORE_CTX* ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
-                                    sizeof(WOLFSSL_X509_STORE_CTX), NULL,
-                                    DYNAMIC_TYPE_X509_CTX);
-    if (ctx != NULL) {
-        ctx->param = NULL;
-        wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL);
-    }
-
-    return ctx;
-}
-
-
-int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
-     WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk)
-{
-    (void)sk;
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init");
-    if (ctx != NULL) {
-        ctx->store = store;
-        ctx->current_cert = x509;
-        ctx->chain  = sk;
-        ctx->domain = NULL;
-#ifdef HAVE_EX_DATA
-        ctx->ex_data = NULL;
-#endif
-        ctx->userCtx = NULL;
-        ctx->error = 0;
-        ctx->error_depth = 0;
-        ctx->discardSessionCerts = 0;
-#ifdef OPENSSL_EXTRA
-        if (ctx->param == NULL) {
-            ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
-                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
-                           NULL,DYNAMIC_TYPE_OPENSSL);
-            if (ctx->param == NULL){
-                WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed");
-                return SSL_FATAL_ERROR;
-            }
-        }
-#endif
-        return SSL_SUCCESS;
-    }
-    return WOLFSSL_FATAL_ERROR;
-}
-
-
-void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
-{
-    if (ctx != NULL) {
-        if (ctx->store != NULL)
-            wolfSSL_X509_STORE_free(ctx->store);
-        if (ctx->current_cert != NULL)
-            wolfSSL_FreeX509(ctx->current_cert);
-        if (ctx->chain != NULL)
-            wolfSSL_sk_X509_free(ctx->chain);
-#ifdef OPENSSL_EXTRA
-        if (ctx->param != NULL){
-            XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL);
-        }
-#endif
-        XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX);
-    }
-}
-
-
-void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
-{
-    (void)ctx;
-    /* Do nothing */
-}
-
-
-int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
-{
-    if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL
-         && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
-        return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
-                    ctx->current_cert->derCert->buffer,
-                    ctx->current_cert->derCert->length,
-                    WOLFSSL_FILETYPE_ASN1);
-    }
-    return WOLFSSL_FATAL_ERROR;
-}
-#endif /* NO_CERTS */
-
-#if !defined(NO_FILESYSTEM)
-static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
-{
-    void *newx509 = NULL;
-    DerBuffer*   der = NULL;
-    byte *fileBuffer = NULL;
-
-    if (file != XBADFILE)
-    {
-        long sz = 0;
-
-        XFSEEK(file, 0, XSEEK_END);
-        sz = XFTELL(file);
-        XREWIND(file);
-
-        if (sz < 0)
-        {
-            WOLFSSL_MSG("Bad tell on FILE");
-            return NULL;
-        }
-
-        fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
-        if (fileBuffer != NULL)
-        {
-            if((long)XFREAD(fileBuffer, 1, sz, file) != sz)
-            {
-                WOLFSSL_MSG("File read failed");
-                goto err_exit;
-            }
-            if(type == CERT_TYPE)
-                newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
-            #ifdef HAVE_CRL
-            else if(type == CRL_TYPE)
-                newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
-            #endif
-            #if !defined(NO_ASN) && !defined(NO_PWDBASED)
-            else if(type == PKCS12_TYPE){
-                if((newx509 = wc_PKCS12_new()) == NULL)
-                    goto err_exit;
-                if(wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0)
-                    goto err_exit;
-            }
-            #endif
-            else goto err_exit;
-            if(newx509 == NULL)
-            {
-                WOLFSSL_MSG("X509 failed");
-                goto err_exit;
-            }
-        }
-    }
-    if (x509 != NULL)
-        *x509 = newx509;
-
-    goto _exit;
-
-err_exit:
-    if(newx509 != NULL){
-        if(type == CERT_TYPE)
-            wolfSSL_X509_free((WOLFSSL_X509*)newx509);
-        #ifdef HAVE_CRL
-        else {
-           if(type == CRL_TYPE)
-                wolfSSL_X509_CRL_free((WOLFSSL_X509_CRL*)newx509);
-        }
-        #endif
-    }
-_exit:
-    if(der != NULL)
-        FreeDer(&der);
-    if(fileBuffer != NULL)
-        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
-    return newx509;
-}
-
-WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12)
-{
-    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
-    return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE);
-}
-
-WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
-{
-    WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
-    return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
-}
-#endif /* !NO_FILESYSTEM */
-
-
-#ifdef HAVE_CRL
-#ifndef NO_FILESYSTEM
-WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl)
-{
-    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp");
-    return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE);
-}
-#endif /* !NO_FILESYSTEM */
-
-
-WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl, const unsigned char* in, int len)
-{
-    WOLFSSL_X509_CRL *newcrl = NULL;
-    int ret ;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL");
-
-    if(in == NULL){
-        WOLFSSL_MSG("Bad argument value");
-        return NULL;
-    }
-
-    newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (newcrl == NULL){
-        WOLFSSL_MSG("New CRL allocation failed");
-        return NULL;
-    }
-    if (InitCRL(newcrl, NULL) < 0) {
-        WOLFSSL_MSG("Init tmp CRL failed");
-        goto err_exit;
-    }
-    ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1, 1);
-    if (ret != WOLFSSL_SUCCESS){
-        WOLFSSL_MSG("Buffer Load CRL failed");
-        goto err_exit;
-    }
-    if(crl){
-        *crl = newcrl;
-    }
-    goto _exit;
-
-err_exit:
-    if(newcrl != NULL)
-        wolfSSL_X509_CRL_free(newcrl);
-    newcrl = NULL;
-_exit:
-    return newcrl;
-}
-
-void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_CRL_free");
-
-    FreeCRL(crl, 1);
-    return;
-}
-#endif /* HAVE_CRL */
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
-{
-    (void)crl;
-    WOLFSSL_STUB("X509_CRL_get_lastUpdate");
-    return 0;
-}
-#endif
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
-{
-    (void)crl;
-    WOLFSSL_STUB("X509_CRL_get_nextUpdate");
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
-{
-    (void)crl;
-    (void)key;
-    WOLFSSL_STUB("X509_CRL_verify");
-    return 0;
-}
-#endif
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA_X509_SMALL)
-/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the
- * subset of X509 API */
-
-WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(){
-    return wolfSSL_PKEY_new_ex(NULL);
-}
-
-
-WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap)
-{
-    WOLFSSL_EVP_PKEY* pkey;
-    int ret;
-    WOLFSSL_ENTER("wolfSSL_PKEY_new");
-    pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap,
-            DYNAMIC_TYPE_PUBLIC_KEY);
-    if (pkey != NULL) {
-        XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY));
-        pkey->heap = heap;
-        pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
-#ifndef HAVE_FIPS
-        ret = wc_InitRng_ex(&(pkey->rng), heap, INVALID_DEVID);
-#else
-        ret = wc_InitRng(&(pkey->rng));
-#endif
-        if (ret != 0){
-            wolfSSL_EVP_PKEY_free(pkey);
-            WOLFSSL_MSG("memory falure");
-            return NULL;
-        }
-    }
-    else {
-        WOLFSSL_MSG("memory failure");
-    }
-
-    return pkey;
-}
-
-
-void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
-{
-    WOLFSSL_ENTER("wolfSSL_PKEY_free");
-    if (key != NULL) {
-        wc_FreeRng(&(key->rng));
-        if (key->pkey.ptr != NULL)
-        {
-            XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        }
-        switch(key->type)
-        {
-            #ifndef NO_RSA
-            case EVP_PKEY_RSA:
-                if (key->rsa != NULL && key->ownRsa == 1) {
-                    wolfSSL_RSA_free(key->rsa);
-                }
-                break;
-            #endif /* NO_RSA */
-
-            #ifdef HAVE_ECC
-            case EVP_PKEY_EC:
-                if (key->ecc != NULL && key->ownEcc == 1) {
-                    wolfSSL_EC_KEY_free(key->ecc);
-                }
-                break;
-            #endif /* HAVE_ECC */
-
-            default:
-            break;
-        }
-        XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    }
-}
-#endif /* OPENSSL_EXTRA_X509_SMALL */
-
-
-#ifdef OPENSSL_EXTRA
-
-void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx,
-                                    unsigned long flags,
-                                    time_t t)
-{
-    (void)flags;
-
-    if (ctx == NULL || ctx->param == NULL)
-        return;
-
-    ctx->param->check_time = t;
-    ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
-}
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
-{
-    (void)obj;
-    WOLFSSL_STUB("X509_OBJECT_free_contents");
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime)
-{
-    (void)asnTime;
-    WOLFSSL_STUB("X509_cmp_current_time");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked)
-{
-    (void)revoked;
-    WOLFSSL_STUB("sk_X509_REVOKED_num");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl)
-{
-    (void)crl;
-    WOLFSSL_STUB("X509_CRL_get_REVOKED");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
-                                    WOLFSSL_X509_REVOKED* revoked, int value)
-{
-    (void)revoked;
-    (void)value;
-    WOLFSSL_STUB("sk_X509_REVOKED_value");
-    return 0;
-}
-#endif
-
-/* Used to create a new WOLFSSL_ASN1_INTEGER structure.
- * returns a pointer to new structure on success and NULL on failure
- */
-WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void)
-{
-    WOLFSSL_ASN1_INTEGER* a;
-
-    a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL,
-                                       DYNAMIC_TYPE_OPENSSL);
-    if (a == NULL) {
-        return NULL;
-    }
-
-    XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER));
-    a->data    = a->intData;
-    a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
-    return a;
-}
-
-
-/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */
-void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in)
-{
-    if (in != NULL) {
-        if (in->isDynamic) {
-            XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL);
-        }
-        XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL);
-    }
-}
-
-
-WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509)
-{
-    WOLFSSL_ASN1_INTEGER* a;
-    int i = 0;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber");
-
-    a = wolfSSL_ASN1_INTEGER_new();
-    if (a == NULL)
-        return NULL;
-
-    /* Make sure there is space for the data, ASN.1 type and length. */
-    if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
-        /* dynamicly create data buffer, +2 for type and length */
-        a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL,
-                DYNAMIC_TYPE_OPENSSL);
-        if (a->data == NULL) {
-            wolfSSL_ASN1_INTEGER_free(a);
-            return NULL;
-        }
-        a->dataMax   = x509->serialSz + 2;
-        a->isDynamic = 1;
-    }
-
-    a->data[i++] = ASN_INTEGER;
-    i += SetLength(x509->serialSz, a->data + i);
-    XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
-
-    return a;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
-int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime)
-{
-    char buf[MAX_TIME_STRING_SZ];
-    int  ret = WOLFSSL_SUCCESS;
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print");
-
-    if (bio == NULL || asnTime == NULL) {
-        WOLFSSL_MSG("NULL function argument");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf,
-                sizeof(buf)) == NULL) {
-        XMEMSET(buf, 0, MAX_TIME_STRING_SZ);
-        XMEMCPY(buf, "Bad time value", 14);
-        ret = WOLFSSL_FAILURE;
-    }
-
-    if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) {
-        WOLFSSL_MSG("Unable to write to bio");
-        return WOLFSSL_FAILURE;
-    }
-
-    return ret;
-}
-
-
-char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
-{
-    int format;
-    int dateLen;
-    byte* date = (byte*)t;
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string");
-
-    if (t == NULL || buf == NULL || len < 5) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-
-    format  = *date; date++;
-    dateLen = *date; date++;
-    if (dateLen > len) {
-        WOLFSSL_MSG("Length of date is longer then buffer");
-        return NULL;
-    }
-
-    if (!GetTimeString(date, format, buf, len)) {
-        return NULL;
-    }
-
-    return buf;
-}
-#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
-    OPENSSL_EXTRA*/
-
-
-#ifdef OPENSSL_EXTRA
-
-#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
-    !defined(TIME_OVERRIDES) && !defined(NO_FILESYSTEM)
-
-WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t,
-                                    int offset_day, long offset_sec)
-{
-    const time_t sec_per_day = 24*60*60;
-    struct tm* ts = NULL;
-    struct tm* tmpTime = NULL;
-    time_t t_adj = 0;
-    time_t offset_day_sec = 0;
-
-#if defined(NEED_TMP_TIME)
-    struct tm tmpTimeStorage;
-    tmpTime = &tmpTimeStorage;
-#else
-    (void)tmpTime;
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj");
-
-    if (s == NULL){
-        s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL,
-                                        DYNAMIC_TYPE_OPENSSL);
-        if (s == NULL){
-            return NULL;
-        }
-    }
-
-    /* compute GMT time with offset */
-    offset_day_sec = offset_day * sec_per_day;
-    t_adj          = t + offset_day_sec + offset_sec;
-    ts             = (struct tm *)XGMTIME(&t_adj, tmpTime);
-    if (ts == NULL){
-        WOLFSSL_MSG("failed to get time data.");
-        XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
-        return NULL;
-    }
-
-    /* create ASN1 time notation */
-    /* UTC Time */
-    if (ts->tm_year >= 50 && ts->tm_year < 150){
-        char utc_str[ASN_UTC_TIME_SIZE];
-        int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec;
-        byte *data_ptr = NULL;
-
-        if (ts->tm_year >= 50 && ts->tm_year < 100){
-            utc_year = ts->tm_year;
-        } else if (ts->tm_year >= 100 && ts->tm_year < 150){
-            utc_year = ts->tm_year - 100;
-        }
-        utc_mon  = ts->tm_mon + 1;
-        utc_day  = ts->tm_mday;
-        utc_hour = ts->tm_hour;
-        utc_min  = ts->tm_min;
-        utc_sec  = ts->tm_sec;
-        XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
-                  "%02d%02d%02d%02d%02d%02dZ",
-                  utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec);
-        data_ptr  = s->data;
-        *data_ptr = (byte) ASN_UTC_TIME; data_ptr++;
-        *data_ptr = (byte) ASN_UTC_TIME_SIZE; data_ptr++;
-        XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE);
-    /* GeneralizedTime */
-    } else {
-        char gt_str[ASN_GENERALIZED_TIME_SIZE];
-        int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec;
-        byte *data_ptr = NULL;
-
-        gt_year = ts->tm_year + 1900;
-        gt_mon  = ts->tm_mon + 1;
-        gt_day  = ts->tm_mday;
-        gt_hour = ts->tm_hour;
-        gt_min  = ts->tm_min;
-        gt_sec  = ts->tm_sec;
-        XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
-                  "%4d%02d%02d%02d%02d%02dZ",
-                  gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec);
-        data_ptr  = s->data;
-        *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++;
-        *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE; data_ptr++;
-        XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE);
-    }
-
-    return s;
-}
-#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES && !NO_FILESYSTEM */
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a,
-                            const WOLFSSL_ASN1_INTEGER* b)
-{
-    (void)a;
-    (void)b;
-    WOLFSSL_STUB("ASN1_INTEGER_cmp");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i)
-{
-    (void)i;
-    WOLFSSL_STUB("ASN1_INTEGER_get");
-    return 0;
-}
-#endif
-
-
-void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data");
-#if defined(HAVE_EX_DATA) || defined(FORTRESS)
-    if (ctx != NULL && idx == 0)
-        return ctx->ex_data;
-#else
-    (void)ctx;
-    (void)idx;
-#endif
-    return 0;
-}
-
-
-/* Gets an index to store SSL structure at.
- *
- * Returns positive index on success and negative values on failure
- */
-int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
-{
-    WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
-
-    /* store SSL at index 0 */
-    return 0;
-}
-
-
-/* Set an error stat in the X509 STORE CTX
- *
- */
-void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error");
-
-    if (ctx != NULL) {
-        ctx->error = er;
-    }
-}
-
-
-/* Sets a function callback that will send information about the state of all
- * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
- * in.
- *
- * ctx WOLFSSL_CTX structre to set callback function in
- * f   callback function to use
- */
-void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
-       void (*f)(const WOLFSSL* ssl, int type, int val))
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
-    if (ctx == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-    }
-    else {
-        ctx->CBIS = f;
-    }
-}
-
-
-unsigned long wolfSSL_ERR_peek_error(void)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
-
-    return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
-}
-
-
-/* This function is to find global error values that are the same through out
- * all library version. With wolfSSL having only one set of error codes the
- * return value is pretty straight forward. The only thing needed is all wolfSSL
- * error values are typically negative.
- *
- * Returns the error reason
- */
-int wolfSSL_ERR_GET_REASON(unsigned long err)
-{
-    int ret = (int)err;
-
-    WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    /* Nginx looks for this error to know to stop parsing certificates. */
-    if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE))
-        return PEM_R_NO_START_LINE;
-#endif
-
-    /* check if error value is in range of wolfSSL errors */
-    ret = 0 - ret; /* setting as negative value */
-    /* wolfCrypt range is less than MAX (-100)
-       wolfSSL range is MIN (-300) and lower */
-    if (ret < MAX_CODE_E) {
-        return ret;
-    }
-    else {
-        WOLFSSL_MSG("Not in range of typical error values");
-        ret = (int)err;
-    }
-
-    return ret;
-}
-
-
-/* returns a string that describes the alert
- *
- * alertID the alert value to look up
- */
-const char* wolfSSL_alert_type_string_long(int alertID)
-{
-    WOLFSSL_ENTER("wolfSSL_aalert_type_string_long");
-
-    switch (alertID) {
-        case close_notify:
-            {
-                static const char close_notify_str[] =
-                    "close_notify";
-                return close_notify_str;
-            }
-
-        case unexpected_message:
-            {
-                static const char unexpected_message_str[] =
-                    "unexpected_message";
-                return unexpected_message_str;
-            }
-
-        case bad_record_mac:
-            {
-                static const char bad_record_mac_str[] =
-                    "bad_record_mac";
-                return bad_record_mac_str;
-            }
-
-        case record_overflow:
-            {
-                static const char record_overflow_str[] =
-                    "record_overflow";
-                return record_overflow_str;
-            }
-
-        case decompression_failure:
-            {
-                static const char decompression_failure_str[] =
-                    "decompression_failure";
-                return decompression_failure_str;
-            }
-
-        case handshake_failure:
-            {
-                static const char handshake_failure_str[] =
-                    "handshake_failure";
-                return handshake_failure_str;
-            }
-
-        case no_certificate:
-            {
-                static const char no_certificate_str[] =
-                    "no_certificate";
-                return no_certificate_str;
-            }
-
-        case bad_certificate:
-            {
-                static const char bad_certificate_str[] =
-                    "bad_certificate";
-                return bad_certificate_str;
-            }
-
-        case unsupported_certificate:
-            {
-                static const char unsupported_certificate_str[] =
-                    "unsupported_certificate";
-                return unsupported_certificate_str;
-            }
-
-        case certificate_revoked:
-            {
-                static const char certificate_revoked_str[] =
-                    "certificate_revoked";
-                return certificate_revoked_str;
-            }
-
-        case certificate_expired:
-            {
-                static const char certificate_expired_str[] =
-                    "certificate_expired";
-                return certificate_expired_str;
-            }
-
-        case certificate_unknown:
-            {
-                static const char certificate_unknown_str[] =
-                    "certificate_unknown";
-                return certificate_unknown_str;
-            }
-
-        case illegal_parameter:
-            {
-                static const char illegal_parameter_str[] =
-                    "illegal_parameter";
-                return illegal_parameter_str;
-            }
-
-        case decode_error:
-            {
-                static const char decode_error_str[] =
-                    "decode_error";
-                return decode_error_str;
-            }
-
-        case decrypt_error:
-            {
-                static const char decrypt_error_str[] =
-                    "decrypt_error";
-                return decrypt_error_str;
-            }
-
-    #ifdef WOLFSSL_MYSQL_COMPATIBLE
-    /* catch name conflict for enum protocol with MYSQL build */
-        case wc_protocol_version:
-            {
-                static const char wc_protocol_version_str[] =
-                    "wc_protocol_version";
-                return wc_protocol_version_str;
-            }
-
-    #else
-        case protocol_version:
-            {
-                static const char protocol_version_str[] =
-                    "protocol_version";
-                return protocol_version_str;
-            }
-
-    #endif
-        case no_renegotiation:
-            {
-                static const char no_renegotiation_str[] =
-                    "no_renegotiation";
-                return no_renegotiation_str;
-            }
-
-        case unrecognized_name:
-            {
-                static const char unrecognized_name_str[] =
-                    "unrecognized_name";
-                return unrecognized_name_str;
-            }
-
-        case bad_certificate_status_response:
-            {
-                static const char bad_certificate_status_response_str[] =
-                    "bad_certificate_status_response";
-                return bad_certificate_status_response_str;
-            }
-
-        case no_application_protocol:
-            {
-                static const char no_application_protocol_str[] =
-                    "no_application_protocol";
-                return no_application_protocol_str;
-            }
-
-        default:
-            WOLFSSL_MSG("Unknown Alert");
-            return NULL;
-    }
-}
-
-
-const char* wolfSSL_alert_desc_string_long(int alertID)
-{
-    WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
-    return wolfSSL_alert_type_string_long(alertID);
-}
-
-
-/* Gets the current state of the WOLFSSL structure
- *
- * ssl WOLFSSL structure to get state of
- *
- * Returns a human readable string of the WOLFSSL structure state
- */
-const char* wolfSSL_state_string_long(const WOLFSSL* ssl)
-{
-
-    static const char* OUTPUT_STR[14][6][3] = {
-        {
-            {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"},
-            {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"},
-            {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"},
-            {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"},
-            {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"},
-            {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"},
-        },
-        {
-            {"SSLv3 read Server Hello Verify Request",
-             "SSLv3 write Server Hello Verify Request",
-             "SSLv3 Server Hello Verify Request"},
-            {"TLSv1 read Server Hello Verify Request",
-             "TLSv1 write Server Hello Verify Request",
-             "TLSv1 Server Hello Verify Request"},
-            {"TLSv1_1 read Server Hello Verify Request",
-            "TLSv1_1 write Server Hello Verify Request",
-             "TLSv1_1 Server Hello Verify Request"},
-            {"TLSv1_2 read Server Hello Verify Request",
-            "TLSv1_2 write Server Hello Verify Request",
-             "TLSv1_2 Server Hello Verify Request"},
-            {"DTLSv1 read Server Hello Verify Request",
-             "DTLSv1 write Server Hello Verify Request",
-             "DTLSv1 Server Hello Verify Request"},
-            {"DTLSv1_2 read Server Hello Verify Request",
-             "DTLSv1_2 write Server Hello Verify Request",
-             "DTLSv1_2 Server Hello Verify Request"},
-        },
-        {
-            {"SSLv3 read Server Hello",
-             "SSLv3 write Server Hello",
-             "SSLv3 Server Hello"},
-            {"TLSv1 read Server Hello",
-             "TLSv1 write Server Hello",
-             "TLSv1 Server Hello"},
-            {"TLSv1_1 read Server Hello",
-            "TLSv1_1 write Server Hello",
-             "TLSv1_1 Server Hello"},
-            {"TLSv1_2 read Server Hello",
-            "TLSv1_2 write Server Hello",
-             "TLSv1_2 Server Hello"},
-            {"DTLSv1 read Server Hello",
-            "DTLSv1 write Server Hello",
-             "DTLSv1 Server Hello"},
-            {"DTLSv1_2 read Server Hello"
-             "DTLSv1_2 write Server Hello",
-             "DTLSv1_2 Server Hello",
-            },
-        },
-        {
-            {"SSLv3 read Server Session Ticket",
-             "SSLv3 write Server Session Ticket",
-             "SSLv3 Server Session Ticket"},
-            {"TLSv1 read Server Session Ticket",
-             "TLSv1 write Server Session Ticket",
-             "TLSv1 Server Session Ticket"},
-            {"TLSv1_1 read Server Session Ticket",
-             "TLSv1_1 write Server Session Ticket",
-             "TLSv1_1 Server Session Ticket"},
-            {"TLSv1_2 read Server Session Ticket",
-             "TLSv1_2 write Server Session Ticket",
-             "TLSv1_2 Server Session Ticket"},
-            {"DTLSv1 read Server Session Ticket",
-             "DTLSv1 write Server Session Ticket",
-             "DTLSv1 Server Session Ticket"},
-            {"DTLSv1_2 read Server Session Ticket",
-             "DTLSv1_2 write Server Session Ticket",
-             "DTLSv1_2 Server Session Ticket"},
-        },
-        {
-            {"SSLv3 read Server Cert",
-             "SSLv3 write Server Cert",
-             "SSLv3 Server Cert"},
-            {"TLSv1 read Server Cert",
-             "TLSv1 write Server Cert",
-             "TLSv1 Server Cert"},
-            {"TLSv1_1 read Server Cert",
-             "TLSv1_1 write Server Cert",
-             "TLSv1_1 Server Cert"},
-            {"TLSv1_2 read Server Cert",
-             "TLSv1_2 write Server Cert",
-             "TLSv1_2 Server Cert"},
-            {"DTLSv1 read Server Cert",
-             "DTLSv1 write Server Cert",
-             "DTLSv1 Server Cert"},
-            {"DTLSv1_2 read Server Cert",
-             "DTLSv1_2 write Server Cert",
-             "DTLSv1_2 Server Cert"},
-        },
-        {
-            {"SSLv3 read Server Key Exchange",
-             "SSLv3 write Server Key Exchange",
-             "SSLv3 Server Key Exchange"},
-            {"TLSv1 read Server Key Exchange",
-             "TLSv1 write Server Key Exchange",
-             "TLSv1 Server Key Exchange"},
-            {"TLSv1_1 read Server Key Exchange",
-             "TLSv1_1 write Server Key Exchange",
-             "TLSv1_1 Server Key Exchange"},
-            {"TLSv1_2 read Server Key Exchange",
-             "TLSv1_2 write Server Key Exchange",
-             "TLSv1_2 Server Key Exchange"},
-            {"DTLSv1 read Server Key Exchange",
-             "DTLSv1 write Server Key Exchange",
-             "DTLSv1 Server Key Exchange"},
-            {"DTLSv1_2 read Server Key Exchange",
-             "DTLSv1_2 write Server Key Exchange",
-             "DTLSv1_2 Server Key Exchange"},
-        },
-        {
-            {"SSLv3 read Server Hello Done",
-             "SSLv3 write Server Hello Done",
-             "SSLv3 Server Hello Done"},
-            {"TLSv1 read Server Hello Done",
-             "TLSv1 write Server Hello Done",
-             "TLSv1 Server Hello Done"},
-            {"TLSv1_1 read Server Hello Done",
-             "TLSv1_1 write Server Hello Done",
-             "TLSv1_1 Server Hello Done"},
-            {"TLSv1_2 read Server Hello Done",
-             "TLSv1_2 write Server Hello Done",
-             "TLSv1_2 Server Hello Done"},
-            {"DTLSv1 read Server Hello Done",
-             "DTLSv1 write Server Hello Done",
-             "DTLSv1 Server Hello Done"},
-            {"DTLSv1_2 read Server Hello Done",
-             "DTLSv1_2 write Server Hello Done",
-             "DTLSv1_2 Server Hello Done"},
-        },
-        {
-            {"SSLv3 read Server Change CipherSpec",
-             "SSLv3 write Server Change CipherSpec",
-             "SSLv3 Server Change CipherSpec"},
-            {"TLSv1 read Server Change CipherSpec",
-             "TLSv1 write Server Change CipherSpec",
-             "TLSv1 Server Change CipherSpec"},
-            {"TLSv1_1 read Server Change CipherSpec",
-             "TLSv1_1 write Server Change CipherSpec",
-             "TLSv1_1 Server Change CipherSpec"},
-            {"TLSv1_2 read Server Change CipherSpec",
-             "TLSv1_2 write Server Change CipherSpec",
-             "TLSv1_2 Server Change CipherSpec"},
-            {"DTLSv1 read Server Change CipherSpec",
-             "DTLSv1 write Server Change CipherSpec",
-             "DTLSv1 Server Change CipherSpec"},
-            {"DTLSv1_2 read Server Change CipherSpec",
-             "DTLSv1_2 write Server Change CipherSpec",
-             "DTLSv1_2 Server Change CipherSpec"},
-        },
-        {
-            {"SSLv3 read Server Finished",
-             "SSLv3 write Server Finished",
-             "SSLv3 Server Finished"},
-            {"TLSv1 read Server Finished",
-             "TLSv1 write Server Finished",
-             "TLSv1 Server Finished"},
-            {"TLSv1_1 read Server Finished",
-             "TLSv1_1 write Server Finished",
-             "TLSv1_1 Server Finished"},
-            {"TLSv1_2 read Server Finished",
-             "TLSv1_2 write Server Finished",
-             "TLSv1_2 Server Finished"},
-            {"DTLSv1 read Server Finished",
-             "DTLSv1 write Server Finished",
-             "DTLSv1 Server Finished"},
-            {"DTLSv1_2 read Server Finished",
-             "DTLSv1_2 write Server Finished",
-             "DTLSv1_2 Server Finished"},
-        },
-        {
-            {"SSLv3 read Client Hello",
-             "SSLv3 write Client Hello",
-             "SSLv3 Client Hello"},
-            {"TLSv1 read Client Hello",
-             "TLSv1 write Client Hello",
-             "TLSv1 Client Hello"},
-            {"TLSv1_1 read Client Hello",
-             "TLSv1_1 write Client Hello",
-             "TLSv1_1 Client Hello"},
-            {"TLSv1_2 read Client Hello",
-             "TLSv1_2 write Client Hello",
-             "TLSv1_2 Client Hello"},
-            {"DTLSv1 read Client Hello",
-             "DTLSv1 write Client Hello",
-             "DTLSv1 Client Hello"},
-            {"DTLSv1_2 read Client Hello",
-             "DTLSv1_2 write Client Hello",
-             "DTLSv1_2 Client Hello"},
-        },
-        {
-            {"SSLv3 read Client Key Exchange",
-             "SSLv3 write Client Key Exchange",
-             "SSLv3 Client Key Exchange"},
-            {"TLSv1 read Client Key Exchange",
-             "TLSv1 write Client Key Exchange",
-             "TLSv1 Client Key Exchange"},
-            {"TLSv1_1 read Client Key Exchange",
-             "TLSv1_1 write Client Key Exchange",
-             "TLSv1_1 Client Key Exchange"},
-            {"TLSv1_2 read Client Key Exchange",
-             "TLSv1_2 write Client Key Exchange",
-             "TLSv1_2 Client Key Exchange"},
-            {"DTLSv1 read Client Key Exchange",
-             "DTLSv1 write Client Key Exchange",
-             "DTLSv1 Client Key Exchange"},
-            {"DTLSv1_2 read Client Key Exchange",
-             "DTLSv1_2 write Client Key Exchange",
-             "DTLSv1_2 Client Key Exchange"},
-        },
-        {
-            {"SSLv3 read Client Change CipherSpec",
-             "SSLv3 write Client Change CipherSpec",
-             "SSLv3 Client Change CipherSpec"},
-            {"TLSv1 read Client Change CipherSpec",
-             "TLSv1 write Client Change CipherSpec",
-             "TLSv1 Client Change CipherSpec"},
-            {"TLSv1_1 read Client Change CipherSpec",
-             "TLSv1_1 write Client Change CipherSpec",
-             "TLSv1_1 Client Change CipherSpec"},
-            {"TLSv1_2 read Client Change CipherSpec",
-             "TLSv1_2 write Client Change CipherSpec",
-             "TLSv1_2 Client Change CipherSpec"},
-            {"DTLSv1 read Client Change CipherSpec",
-             "DTLSv1 write Client Change CipherSpec",
-             "DTLSv1 Client Change CipherSpec"},
-            {"DTLSv1_2 read Client Change CipherSpec",
-             "DTLSv1_2 write Client Change CipherSpec",
-             "DTLSv1_2 Client Change CipherSpec"},
-        },
-        {
-            {"SSLv3 read Client Finished",
-             "SSLv3 write Client Finished",
-             "SSLv3 Client Finished"},
-            {"TLSv1 read Client Finished",
-             "TLSv1 write Client Finished",
-             "TLSv1 Client Finished"},
-            {"TLSv1_1 read Client Finished",
-             "TLSv1_1 write Client Finished",
-             "TLSv1_1 Client Finished"},
-            {"TLSv1_2 read Client Finished",
-             "TLSv1_2 write Client Finished",
-             "TLSv1_2 Client Finished"},
-            {"DTLSv1 read Client Finished",
-             "DTLSv1 write Client Finished",
-             "DTLSv1 Client Finished"},
-            {"DTLSv1_2 read Client Finished",
-             "DTLSv1_2 write Client Finished",
-             "DTLSv1_2 Client Finished"},
-        },
-        {
-            {"SSLv3 Handshake Done",
-             "SSLv3 Handshake Done",
-             "SSLv3 Handshake Done"},
-            {"TLSv1 Handshake Done",
-             "TLSv1 Handshake Done",
-             "TLSv1 Handshake Done"},
-            {"TLSv1_1 Handshake Done",
-             "TLSv1_1 Handshake Done",
-             "TLSv1_1 Handshake Done"},
-            {"TLSv1_2 Handshake Done",
-             "TLSv1_2 Handshake Done",
-             "TLSv1_2 Handshake Done"},
-            {"DTLSv1 Handshake Done",
-             "DTLSv1 Handshake Done",
-             "DTLSv1 Handshake Done"},
-            {"DTLSv1_2 Handshake Done"
-             "DTLSv1_2 Handshake Done"
-             "DTLSv1_2 Handshake Done"}
-        }
-    };
-    enum ProtocolVer {
-        SSL_V3 = 0,
-        TLS_V1,
-        TLS_V1_1,
-        TLS_V1_2,
-        DTLS_V1,
-        DTLS_V1_2,
-        UNKNOWN = 100
-    };
-
-    enum IOMode {
-        SS_READ = 0,
-        SS_WRITE,
-        SS_NEITHER
-    };
-
-    enum SslState {
-        ss_null_state = 0,
-        ss_server_helloverify,
-        ss_server_hello,
-        ss_sessionticket,
-        ss_server_cert,
-        ss_server_keyexchange,
-        ss_server_hellodone,
-        ss_server_changecipherspec,
-        ss_server_finished,
-        ss_client_hello,
-        ss_client_keyexchange,
-        ss_client_changecipherspec,
-        ss_client_finished,
-        ss_handshake_done
-    };
-
-    int protocol = 0;
-    int cbmode = 0;
-    int state = 0;
-
-    WOLFSSL_ENTER("wolfSSL_state_string_long");
-    if (ssl == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return NULL;
-    }
-
-    /* Get state of callback */
-    if (ssl->cbmode == SSL_CB_MODE_WRITE){
-        cbmode =  SS_WRITE;
-    } else if (ssl->cbmode == SSL_CB_MODE_READ){
-        cbmode =  SS_READ;
-    } else {
-        cbmode =  SS_NEITHER;
-    }
-
-    /* Get protocol version */
-    switch (ssl->version.major){
-        case SSLv3_MAJOR:
-            switch (ssl->version.minor){
-                case TLSv1_MINOR:
-                    protocol = TLS_V1;
-                    break;
-                case TLSv1_1_MINOR:
-                    protocol = TLS_V1_1;
-                    break;
-                case TLSv1_2_MINOR:
-                    protocol = TLS_V1_2;
-                    break;
-                case SSLv3_MINOR:
-                    protocol = SSL_V3;
-                    break;
-                default:
-                    protocol = UNKNOWN;
-            }
-            break;
-        case DTLS_MAJOR:
-            switch (ssl->version.minor){
-        case DTLS_MINOR:
-            protocol = DTLS_V1;
-            break;
-        case DTLSv1_2_MINOR:
-            protocol = DTLS_V1_2;
-            break;
-        default:
-            protocol = UNKNOWN;
-    }
-    break;
-    default:
-        protocol = UNKNOWN;
-    }
-
-    /* accept process */
-    if (ssl->cbmode == SSL_CB_MODE_READ){
-        state = ssl->cbtype;
-        switch (state) {
-            case hello_verify_request:
-                state = ss_server_helloverify;
-                break;
-            case session_ticket:
-                state = ss_sessionticket;
-                break;
-            case server_hello:
-                state = ss_server_hello;
-                break;
-            case server_hello_done:
-                state = ss_server_hellodone;
-                break;
-            case certificate:
-                state = ss_server_cert;
-                break;
-            case server_key_exchange:
-                state = ss_server_keyexchange;
-                break;
-            case client_hello:
-                state = ss_client_hello;
-                break;
-            case client_key_exchange:
-                state = ss_client_keyexchange;
-                break;
-            case finished:
-                if (ssl->options.side == WOLFSSL_SERVER_END)
-                    state = ss_client_finished;
-                else if (ssl->options.side == WOLFSSL_CLIENT_END)
-                    state = ss_server_finished;
-                break;
-            default:
-                WOLFSSL_MSG("Unknown State");
-                state = ss_null_state;
-        }
-    } else {
-        /* Send process */
-        if (ssl->options.side == WOLFSSL_SERVER_END)
-            state = ssl->options.serverState;
-        else
-            state = ssl->options.clientState;
-
-        switch(state){
-            case SERVER_HELLOVERIFYREQUEST_COMPLETE:
-                state = ss_server_helloverify;
-                break;
-            case SERVER_HELLO_COMPLETE:
-                state = ss_server_hello;
-                break;
-            case SERVER_CERT_COMPLETE:
-                state = ss_server_cert;
-                break;
-            case SERVER_KEYEXCHANGE_COMPLETE:
-                state = ss_server_keyexchange;
-                break;
-            case SERVER_HELLODONE_COMPLETE:
-                state = ss_server_hellodone;
-                break;
-            case SERVER_CHANGECIPHERSPEC_COMPLETE:
-                state = ss_server_changecipherspec;
-                break;
-            case SERVER_FINISHED_COMPLETE:
-                state = ss_server_finished;
-                break;
-            case CLIENT_HELLO_COMPLETE:
-                state = ss_client_hello;
-                break;
-            case CLIENT_KEYEXCHANGE_COMPLETE:
-                state = ss_client_keyexchange;
-                break;
-            case CLIENT_CHANGECIPHERSPEC_COMPLETE:
-                state = ss_client_changecipherspec;
-                break;
-            case CLIENT_FINISHED_COMPLETE:
-                state = ss_client_finished;
-                break;
-            case HANDSHAKE_DONE:
-                state = ss_handshake_done;
-                break;
-            default:
-                WOLFSSL_MSG("Unknown State");
-                state = ss_null_state;
-        }
-    }
-
-    if (protocol == UNKNOWN)
-        return NULL;
-    else
-        return OUTPUT_STR[state][protocol][cbmode];
-}
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
-{
-    (void)name;
-    (void)num;
-    (void)w;
-    (void)key;
-    WOLFSSL_STUB("PEM_def_callback");
-    return 0;
-}
-#endif
-
-static long wolf_set_options(long old_op, long op)
-{
-    /* if SSL_OP_ALL then turn all bug workarounds on */
-    if ((op & SSL_OP_ALL) == SSL_OP_ALL) {
-        WOLFSSL_MSG("\tSSL_OP_ALL");
-
-        op |= SSL_OP_MICROSOFT_SESS_ID_BUG;
-        op |= SSL_OP_NETSCAPE_CHALLENGE_BUG;
-        op |= SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
-        op |= SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
-        op |= SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
-        op |= SSL_OP_MSIE_SSLV2_RSA_PADDING;
-        op |= SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
-        op |= SSL_OP_TLS_D5_BUG;
-        op |= SSL_OP_TLS_BLOCK_PADDING_BUG;
-        op |= SSL_OP_TLS_ROLLBACK_BUG;
-        op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
-    }
-
-    /* by default cookie exchange is on with DTLS */
-    if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) {
-        WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default");
-    }
-
-    if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
-        WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
-    }
-
-    if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
-        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3");
-    }
-
-    if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
-        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
-    }
-
-    if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
-        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
-    }
-
-    if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
-        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
-    }
-
-    if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
-        WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
-    }
-
-    if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
-    #ifdef HAVE_LIBZ
-        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
-    #else
-        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
-    #endif
-    }
-
-    return old_op | op;
-}
-
-long wolfSSL_set_options(WOLFSSL* ssl, long op)
-{
-    word16 haveRSA = 1;
-    word16 havePSK = 0;
-    int    keySz   = 0;
-
-    WOLFSSL_ENTER("wolfSSL_set_options");
-
-    if (ssl == NULL) {
-        return 0;
-    }
-
-    ssl->options.mask = wolf_set_options(ssl->options.mask, op);
-
-    if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
-        if (ssl->version.minor == TLSv1_3_MINOR)
-            ssl->version.minor = TLSv1_2_MINOR;
-    }
-
-    if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
-        if (ssl->version.minor == TLSv1_2_MINOR)
-            ssl->version.minor = TLSv1_1_MINOR;
-    }
-
-    if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
-        if (ssl->version.minor == TLSv1_1_MINOR)
-            ssl->version.minor = TLSv1_MINOR;
-    }
-
-    if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
-        if (ssl->version.minor == TLSv1_MINOR)
-            ssl->version.minor = SSLv3_MINOR;
-    }
-
-    if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
-    #ifdef HAVE_LIBZ
-        ssl->options.usingCompression = 0;
-    #endif
-    }
-
-    /* in the case of a version change the cipher suites should be reset */
-#ifndef NO_PSK
-    havePSK = ssl->options.havePSK;
-#endif
-#ifdef NO_RSA
-    haveRSA = 0;
-#endif
-#ifndef NO_CERTS
-    keySz = ssl->buffers.keySz;
-#endif
-
-    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
-                       ssl->options.haveDH, ssl->options.haveNTRU,
-                       ssl->options.haveECDSAsig, ssl->options.haveECC,
-                       ssl->options.haveStaticECC, ssl->options.side);
-
-    return ssl->options.mask;
-}
-
-
-long wolfSSL_get_options(const WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_options");
-    if(ssl == NULL)
-        return WOLFSSL_FAILURE;
-    return ssl->options.mask;
-}
-
-long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
-{
-    WOLFSSL_ENTER("SSL_clear_options");
-    if(ssl == NULL)
-        return WOLFSSL_FAILURE;
-    ssl->options.mask &= ~opt;
-    return ssl->options.mask;
-}
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s)
-{
-    (void)s;
-    WOLFSSL_STUB("SSL_clear_num_renegotiations");
-    return 0;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s)
-{
-    (void)s;
-    WOLFSSL_STUB("SSL_total_renegotiations");
-    return 0;
-}
-#endif
-
-#ifndef NO_DH
-long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
-{
-    int pSz, gSz;
-    byte *p, *g;
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
-
-    if (!ssl || !dh)
-        return BAD_FUNC_ARG;
-
-    /* Get needed size for p and g */
-    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
-    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
-
-    if (pSz <= 0 || gSz <= 0)
-        return WOLFSSL_FATAL_ERROR;
-
-    p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (!p)
-        return MEMORY_E;
-
-    g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (!g) {
-        XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        return MEMORY_E;
-    }
-
-    pSz = wolfSSL_BN_bn2bin(dh->p, p);
-    gSz = wolfSSL_BN_bn2bin(dh->g, g);
-
-    if (pSz >= 0 && gSz >= 0) /* Conversion successful */
-        ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
-
-    XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-
-    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
-}
-#endif /* !NO_DH */
-
-
-#ifdef HAVE_PK_CALLBACKS
-long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
-{
-    if (ssl == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    ssl->loggingCtx = arg;
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_PK_CALLBACKS */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
-const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length)
-{
-    const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length);
-    return c;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
-{
-    (void)st;
-    WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
-    /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
-{
-    WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
-
-    if (s == NULL){
-        return BAD_FUNC_ARG;
-    }
-
-    if (type == TLSEXT_STATUSTYPE_ocsp){
-        int r = 0;
-        r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s,
-                                                             s->heap, s->devId);
-        return (long)r;
-    } else {
-        WOLFSSL_MSG(
-       "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
-        return SSL_FAILURE;
-    }
-
-}
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
-{
-    (void)s;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
-{
-    (void)s;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
-{
-    (void)s;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
-{
-    (void)s;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
-{
-    (void)s;
-    (void)sid;
-    (void)sid_len;
-    WOLFSSL_STUB("SSL_SESSION_set1_id");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
-{
-    (void)s;
-    (void)sid_ctx;
-    (void)sid_ctx_len;
-    WOLFSSL_STUB("SSL_SESSION_set1_id_context");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x)
-{
-    (void)x;
-    WOLFSSL_STUB("X509_get0_tbs_sigalg");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor)
-{
-    (void)paobj;
-    (void)pptype;
-    (void)ppval;
-    (void)algor;
-    WOLFSSL_STUB("X509_ALGOR_get0");
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API void *X509_get_X509_PUBKEY(void * x)
-{
-    (void)x;
-    WOLFSSL_STUB("X509_get_X509_PUBKEY");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub)
-{
-    (void)ppkalg;
-    (void)pk;
-    (void)ppklen;
-    (void)pa;
-    (void)pub;
-    WOLFSSL_STUB("X509_PUBKEY_get0_param");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
-{
-    (void)ssl;
-    WOLFSSL_STUB("SSL_get_privatekey");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a)
-{
-    (void)buf;
-    (void)buf_len;
-    (void)a;
-    WOLFSSL_STUB("i2t_ASN1_OBJECT");
-    return -1;
-}
-#endif
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count)
-{
-    (void)s;
-    (void)buf;
-    (void)count;
-    WOLFSSL_STUB("SSL_get_finished");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count)
-{
-    (void)s;
-    (void)buf;
-    (void)count;
-    WOLFSSL_STUB("SSL_get_peer_finished");
-    return WOLFSSL_FAILURE;
-}
-#endif
-#endif /* WOLFSSL_HAPROXY */
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
-{
-    (void)ctx;
-    (void)dh;
-    WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
-{
-    WOLFSSL_STUB("SSL_COMP_get_compression_methods");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p)
-{
-    (void)p;
-    WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num");
-    return -1;
-}
-#endif
-
-#if !defined(NO_FILESYSTEM)
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u)
-{
-    (void)fp;
-    (void)x;
-    (void)cb;
-    (void)u;
-    WOLFSSL_STUB("PEM_read_X509");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u)
-{
-    (void)fp;
-    (void)x;
-    (void)cb;
-    (void)u;
-    WOLFSSL_STUB("PEM_read_PrivateKey");
-    return NULL;
-}
-#endif
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir)
-{
-    (void)ctx;
-    (void)file;
-    (void)dir;
-    WOLFSSL_STUB("X509_STORE_load_locations");
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx)
-{
-    (void)ciphers;
-    (void)idx;
-    WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value");
-    return NULL;
-}
-#endif
-
-WOLFSSL_API void ERR_load_SSL_strings(void)
-{
-
-}
-
-#ifdef HAVE_OCSP
-WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
-{
-    if (s == NULL || resp == NULL)
-        return 0;
-
-    *resp = s->ocspResp;
-    return s->ocspRespSz;
-}
-
-WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len)
-{
-    if (s == NULL)
-        return WOLFSSL_FAILURE;
-
-    s->ocspResp   = resp;
-    s->ocspRespSz = len;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_OCSP */
-
-long wolfSSL_get_verify_result(const WOLFSSL *ssl)
-{
-    if (ssl == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return ssl->peerVerifyRet;
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of accepts attempted by CTX in it's lifetime */
-long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of connects attempted CTX in it's lifetime */
-long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of accepts completed by CTX in it's lifetime */
-long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of connects completed by CTX in it's lifetime */
-long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of renegotiation accepts attempted by CTX */
-long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of renegotiation accepts attempted by CTX */
-long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
-    (void)ctx;
-    return 0;
-}
-#endif
-
-
-/* Return the total number of sessions */
-long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
-{
-    word32 total = 0;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
-    (void)ctx;
-
-#ifdef WOLFSSL_SESSION_STATS
-    if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) {
-        WOLFSSL_MSG("Error getting session stats");
-    }
-#else
-    WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
-#endif
-
-    return (long)total;
-}
-
-
-#ifndef NO_CERTS
-long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
-{
-    byte* chain = NULL;
-    long  chainSz = 0;
-    int   derSz;
-    const byte* der;
-    int   ret;
-    int   idx = 0;
-    DerBuffer *derBuffer = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
-
-    if (ctx == NULL || x509 == NULL) {
-        WOLFSSL_MSG("Bad Argument");
-        return WOLFSSL_FAILURE;
-    }
-
-    der = wolfSSL_X509_get_der(x509, &derSz);
-    if (der == NULL || derSz <= 0) {
-        WOLFSSL_MSG("Error getting X509 DER");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (ctx->certificate == NULL) {
-        /* Process buffer makes first certificate the leaf. */
-        ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
-                            NULL, NULL, 1);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
-            return WOLFSSL_FAILURE;
-        }
-    }
-    else {
-        /* TODO: Do this elsewhere. */
-        ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap);
-        if (ret != 0) {
-            WOLFSSL_MSG("Memory Error");
-            return WOLFSSL_FAILURE;
-        }
-        XMEMCPY(derBuffer->buffer, der, derSz);
-        ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
-            return WOLFSSL_FAILURE;
-        }
-
-        /* adding cert to existing chain */
-        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
-            chainSz += ctx->certChain->length;
-        }
-        chainSz += OPAQUE24_LEN + derSz;
-
-        chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
-        if (chain == NULL) {
-            WOLFSSL_MSG("Memory Error");
-            return WOLFSSL_FAILURE;
-        }
-
-        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
-            XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length);
-            idx = ctx->certChain->length;
-        }
-        c32to24(derSz, chain + idx);
-        idx += OPAQUE24_LEN,
-        XMEMCPY(chain + idx, der, derSz);
-        idx += derSz;
-#ifdef WOLFSSL_TLS13
-        ctx->certChainCnt++;
-#endif
-
-        FreeDer(&ctx->certChain);
-        ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
-        if (ret == 0) {
-            XMEMCPY(ctx->certChain->buffer, chain, idx);
-        }
-    }
-
-    /* on success WOLFSSL_X509 memory is responsibility of ctx */
-    wolfSSL_X509_free(x509);
-    if (chain != NULL)
-        XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER);
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
-{
-    if (ctx == NULL || ctx->cm == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    ctx->cm->ocspIOCtx = arg;
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_CERTS */
-
-
-/* Get the session cache mode for CTX
- *
- * ctx  WOLFSSL_CTX struct to get cache mode from
- *
- * Returns a bit mask that has the session cache mode */
-WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx)
-{
-    long m = 0;
-
-    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
-
-    if (ctx == NULL) {
-        return m;
-    }
-
-    if (ctx->sessionCacheOff != 1) {
-        m |= SSL_SESS_CACHE_SERVER;
-    }
-
-    if (ctx->sessionCacheFlushOff == 1) {
-        m |= SSL_SESS_CACHE_NO_AUTO_CLEAR;
-    }
-
-#ifdef HAVE_EXT_CACHE
-    if (ctx->internalCacheOff == 1) {
-        m |= SSL_SESS_CACHE_NO_INTERNAL_STORE;
-    }
-#endif
-
-    return m;
-}
-
-
-int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    return ctx->readAhead;
-}
-
-
-int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
-{
-    if (ctx == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    ctx->readAhead = (byte)v;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
-        void* arg)
-{
-    if (ctx == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    ctx->userPRFArg = arg;
-    return WOLFSSL_SUCCESS;
-}
-
-
-#ifndef NO_DES3
-/* 0 on success */
-int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
-                                               WOLFSSL_DES_key_schedule* key)
-{
-#ifdef WOLFSSL_CHECK_DESKEY
-    return wolfSSL_DES_set_key_checked(myDes, key);
-#else
-    wolfSSL_DES_set_key_unchecked(myDes, key);
-    return 0;
-#endif
-}
-
-
-
-/* return true in fail case (1) */
-static int DES_check(word32 mask, word32 mask2, unsigned char* key)
-{
-    word32 value[2];
-
-    /* sanity check on length made in wolfSSL_DES_set_key_checked */
-    value[0] = mask;
-    value[1] = mask2;
-    return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0;
-}
-
-
-/* check that the key is odd parity and is not a weak key
- * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */
-int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
-                                               WOLFSSL_DES_key_schedule* key)
-{
-    if (myDes == NULL || key == NULL) {
-        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
-        return -2;
-    }
-    else {
-        word32 i;
-        word32 sz = sizeof(WOLFSSL_DES_key_schedule);
-
-        /* sanity check before call to DES_check */
-        if (sz != (sizeof(word32) * 2)) {
-            WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size");
-            return -2;
-        }
-
-        /* check odd parity */
-        for (i = 0; i < sz; i++) {
-            unsigned char c = *((unsigned char*)myDes + i);
-            if (((c & 0x01) ^
-                ((c >> 1) & 0x01) ^
-                ((c >> 2) & 0x01) ^
-                ((c >> 3) & 0x01) ^
-                ((c >> 4) & 0x01) ^
-                ((c >> 5) & 0x01) ^
-                ((c >> 6) & 0x01) ^
-                ((c >> 7) & 0x01)) != 1) {
-                WOLFSSL_MSG("Odd parity test fail");
-                return -1;
-            }
-        }
-
-        if (wolfSSL_DES_is_weak_key(myDes) == 1) {
-            WOLFSSL_MSG("Weak key found");
-            return -2;
-        }
-
-        /* passed tests, now copy over key */
-        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
-
-        return 0;
-    }
-}
-
-
-/* check is not weak. Weak key list from Nist "Recommendation for the Triple
- * Data Encryption Algorithm (TDEA) Block Cipher"
- *
- * returns 1 if is weak 0 if not
- */
-int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
-{
-    word32 mask, mask2;
-
-    WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
-
-    if (key == NULL) {
-        WOLFSSL_MSG("NULL key passed in");
-        return 1;
-    }
-
-    mask = 0x01010101; mask2 = 0x01010101;
-    if (DES_check(mask, mask2, *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE;
-    if (DES_check(mask, mask2, *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1;
-    if (DES_check(mask, mask2, *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E;
-    if (DES_check(mask, mask2, *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    /* semi-weak *key check (list from same Nist paper) */
-    mask  = 0x011F011F; mask2 = 0x010E010E;
-    if (DES_check(mask, mask2, *key) ||
-       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask  = 0x01E001E0; mask2 = 0x01F101F1;
-    if (DES_check(mask, mask2, *key) ||
-       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask  = 0x01FE01FE; mask2 = 0x01FE01FE;
-    if (DES_check(mask, mask2, *key) ||
-       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask  = 0x1FE01FE0; mask2 = 0x0EF10EF1;
-    if (DES_check(mask, mask2, *key) ||
-       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    mask  = 0x1FFE1FFE; mask2 = 0x0EFE0EFE;
-    if (DES_check(mask, mask2, *key) ||
-       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
-        WOLFSSL_MSG("Weak key found");
-        return 1;
-    }
-
-    return 0;
-}
-
-
-void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
-                                               WOLFSSL_DES_key_schedule* key)
-{
-    if (myDes != NULL && key != NULL) {
-        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
-    }
-}
-
-
-/* Sets the parity of the DES key for use */
-void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
-{
-    word32 i;
-    word32 sz = sizeof(WOLFSSL_DES_cblock);
-
-    WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
-
-    for (i = 0; i < sz; i++) {
-        unsigned char c = *((unsigned char*)myDes + i);
-        if ((
-            ((c >> 1) & 0x01) ^
-            ((c >> 2) & 0x01) ^
-            ((c >> 3) & 0x01) ^
-            ((c >> 4) & 0x01) ^
-            ((c >> 5) & 0x01) ^
-            ((c >> 6) & 0x01) ^
-            ((c >> 7) & 0x01)) != 1) {
-            WOLFSSL_MSG("Setting odd parity bit");
-            *((unsigned char*)myDes + i) = *((unsigned char*)myDes + i) | 0x01;
-        }
-    }
-}
-
-
-#ifdef WOLFSSL_DES_ECB
-/* Encrpyt or decrypt input message desa with key and get output in desb.
- * if enc is DES_ENCRYPT,input message is encrypted or
- * if enc is DES_DECRYPT,input message is decrypted.
- * */
-void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
-             WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc)
-{
-    Des myDes;
-
-    WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
-
-    if (desa == NULL || key == NULL || desb == NULL ||
-        (enc != DES_ENCRYPT && enc != DES_DECRYPT)) {
-        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
-    } else {
-        if (wc_Des_SetKey(&myDes, (const byte*) key,
-                           (const byte*) NULL, !enc) != 0) {
-            WOLFSSL_MSG("wc_Des_SetKey return error.");
-            return;
-        }
-        if (enc){
-            if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa,
-                        sizeof(WOLFSSL_DES_cblock)) != 0){
-                WOLFSSL_MSG("wc_Des_EcbEncrpyt return error.");
-            }
-        } else {
-            if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa,
-                        sizeof(WOLFSSL_DES_cblock)) != 0){
-                WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
-            }
-        }
-    }
-}
-#endif
-
-#endif /* NO_DES3 */
-
-#ifndef NO_RC4
-/* Set the key state for Arc4 structure.
- *
- * key  Arc4 structure to use
- * len  length of data buffer
- * data initial state to set Arc4 structure
- */
-void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
-        const unsigned char* data)
-{
-    typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1];
-    (void)sizeof(rc4_test);
-
-    WOLFSSL_ENTER("wolfSSL_RC4_set_key");
-
-    if (key == NULL || len < 0) {
-        WOLFSSL_MSG("bad argument passed in");
-        return;
-    }
-
-    XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
-    wc_Arc4SetKey((Arc4*)key, data, (word32)len);
-}
-
-
-/* Encrypt/decrypt with Arc4 structure.
- *
- * len length of buffer to encrypt/decrypt (in/out)
- * in  buffer to encrypt/decrypt
- * out results of encryption/decryption
- */
-void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
-        const unsigned char* in, unsigned char* out)
-{
-    WOLFSSL_ENTER("wolfSSL_RC4");
-
-    if (key == NULL || in == NULL || out == NULL) {
-        WOLFSSL_MSG("Bad argument passed in");
-        return;
-    }
-
-    wc_Arc4Process((Arc4*)key, out, in, (word32)len);
-}
-#endif /* NO_RC4 */
-
-#ifndef NO_AES
-
-#ifdef WOLFSSL_AES_DIRECT
-/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
- *
- * input  Data to encrypt
- * output Encrypted data after done
- * key    AES key to use for encryption
- */
-void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
-        AES_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_AES_encrypt");
-
-    if (input == NULL || output == NULL || key == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return;
-    }
-
-    wc_AesEncryptDirect((Aes*)key, output, input);
-}
-
-
-/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
- *
- * input  Data to decrypt
- * output Decrypted data after done
- * key    AES key to use for encryption
- */
-void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
-        AES_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_AES_decrypt");
-
-    if (input == NULL || output == NULL || key == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return;
-    }
-
-    wc_AesDecryptDirect((Aes*)key, output, input);
-}
-#endif /* WOLFSSL_AES_DIRECT */
-
-/* Setup of an AES key to use for encryption.
- *
- * key  key in bytes to use for encryption
- * bits size of key in bits
- * aes  AES structure to initialize
- */
-int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
-        AES_KEY *aes)
-{
-    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
-    (void)sizeof(aes_test);
-
-    WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
-
-    if (key == NULL || aes == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return -1;
-    }
-
-    XMEMSET(aes, 0, sizeof(AES_KEY));
-    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) {
-        WOLFSSL_MSG("Error in setting AES key");
-        return -1;
-    }
-    return 0;
-}
-
-
-/* Setup of an AES key to use for decryption.
- *
- * key  key in bytes to use for decryption
- * bits size of key in bits
- * aes  AES structure to initialize
- */
-int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
-        AES_KEY *aes)
-{
-    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
-    (void)sizeof(aes_test);
-
-    WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
-
-    if (key == NULL || aes == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return -1;
-    }
-
-    XMEMSET(aes, 0, sizeof(AES_KEY));
-    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) {
-        WOLFSSL_MSG("Error in setting AES key");
-        return -1;
-    }
-    return 0;
-}
-
-
-#ifdef HAVE_AES_ECB
-/* Encrypt/decrypt a 16 byte block of data using the key passed in.
- *
- * in  buffer to encrypt/decyrpt
- * out buffer to hold result of encryption/decryption
- * key AES structure to use with encryption/decryption
- * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
- */
-void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
-                             AES_KEY *key, const int enc)
-{
-    Aes* aes;
-
-    WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
-
-    if (key == NULL || in == NULL || out == NULL) {
-        WOLFSSL_MSG("Error, Null argument passed in");
-        return;
-    }
-
-    aes = (Aes*)key;
-    if (enc == AES_ENCRYPT) {
-        if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
-            WOLFSSL_MSG("Error with AES CBC encrypt");
-        }
-    }
-    else {
-    #ifdef HAVE_AES_DECRYPT
-        if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
-            WOLFSSL_MSG("Error with AES CBC decrypt");
-        }
-    #else
-        WOLFSSL_MSG("AES decryption not compiled in");
-    #endif
-    }
-}
-#endif /* HAVE_AES_ECB */
-
-
-/* Encrypt data using key and iv passed in. iv gets updated to most recent iv
- * state after encryptiond/decryption.
- *
- * in  buffer to encrypt/decyrpt
- * out buffer to hold result of encryption/decryption
- * len length of input buffer
- * key AES structure to use with encryption/decryption
- * iv  iv to use with operation
- * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
- */
-void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
-        size_t len, AES_KEY *key, unsigned char* iv, const int enc)
-{
-    Aes* aes;
-
-    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
-
-    if (key == NULL || in == NULL || out == NULL || iv == NULL) {
-        WOLFSSL_MSG("Error, Null argument passed in");
-        return;
-    }
-
-    aes = (Aes*)key;
-    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
-        WOLFSSL_MSG("Error with setting iv");
-        return;
-    }
-
-    if (enc == AES_ENCRYPT) {
-        if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) {
-            WOLFSSL_MSG("Error with AES CBC encrypt");
-        }
-    }
-    else {
-        if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) {
-            WOLFSSL_MSG("Error with AES CBC decrypt");
-        }
-    }
-
-    /* to be compatible copy iv to iv buffer after completing operation */
-    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
-}
-
-
-/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to
- * most recent iv state after encryptiond/decryption.
- *
- * in  buffer to encrypt/decyrpt
- * out buffer to hold result of encryption/decryption
- * len length of input buffer
- * key AES structure to use with encryption/decryption
- * iv  iv to use with operation
- * num contains the amount of block used
- * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
- */
-void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
-        size_t len, AES_KEY *key, unsigned char* iv, int* num,
-        const int enc)
-{
-#ifndef WOLFSSL_AES_CFB
-    WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
-    (void)in;
-    (void)out;
-    (void)len;
-    (void)key;
-    (void)iv;
-    (void)num;
-    (void)enc;
-
-    return;
-#else
-    Aes* aes;
-
-    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
-    if (key == NULL || in == NULL || out == NULL || iv == NULL) {
-        WOLFSSL_MSG("Error, Null argument passed in");
-        return;
-    }
-
-    aes = (Aes*)key;
-    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
-        WOLFSSL_MSG("Error with setting iv");
-        return;
-    }
-
-    if (enc == AES_ENCRYPT) {
-        if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) {
-            WOLFSSL_MSG("Error with AES CBC encrypt");
-        }
-    }
-    else {
-        if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) {
-            WOLFSSL_MSG("Error with AES CBC decrypt");
-        }
-    }
-
-    /* to be compatible copy iv to iv buffer after completing operation */
-    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
-
-    /* store number of left over bytes to num */
-    *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
-#endif /* WOLFSSL_AES_CFB */
-}
-#endif /* NO_AES */
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...)
-{
-    (void)bio;
-    (void)format;
-    WOLFSSL_STUB("BIO_printf");
-    return 0;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
-{
-    (void)bio;
-    (void)a;
-    WOLFSSL_STUB("ASN1_UTCTIME_print");
-    return 0;
-}
-#endif
-
-/* Return the month as a string.
- *
- * n  The number of the month as a two characters (1 based).
- * returns the month as a string.
- */
-static WC_INLINE const char* MonthStr(const char* n)
-{
-    static const char monthStr[12][4] = {
-            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-    return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1];
-}
-
-int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio,
-    const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime)
-{
-    const char* p = (const char *)(asnTime->data + 2);
-    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print");
-
-    if (bio == NULL || asnTime == NULL)
-        return BAD_FUNC_ARG;
-
-    /* GetTimeString not always available. */
-    wolfSSL_BIO_write(bio, MonthStr(p + 4), 3);
-    wolfSSL_BIO_write(bio, " ", 1);
-    /* Day */
-    wolfSSL_BIO_write(bio, p + 6, 2);
-    wolfSSL_BIO_write(bio, " ", 1);
-    /* Hour */
-    wolfSSL_BIO_write(bio, p + 8, 2);
-    wolfSSL_BIO_write(bio, ":", 1);
-    /* Min */
-    wolfSSL_BIO_write(bio, p + 10, 2);
-    wolfSSL_BIO_write(bio, ":", 1);
-    /* Secs */
-    wolfSSL_BIO_write(bio, p + 12, 2);
-    wolfSSL_BIO_write(bio, " ", 1);
-    wolfSSL_BIO_write(bio, p, 4);
-
-    return 0;
-}
-
-void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time)
-{
-    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free");
-    if (asn1Time == NULL)
-        return;
-    XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data));
-}
-
-int  wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
-{
-    if (sk == NULL)
-        return 0;
-    return (int)sk->num;
-}
-
-void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, int i)
-{
-    for (; sk != NULL && i > 0; i--)
-        sk = sk->next;
-    if (sk == NULL)
-        return NULL;
-    return (void*)sk->data.obj;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
-/* stunnel 4.28 needs */
-void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
-                    WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*))
-{
-#ifdef HAVE_EXT_CACHE
-    ctx->get_sess_cb = f;
-#else
-    (void)ctx;
-    (void)f;
-#endif
-}
-
-void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
-                             int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
-{
-#ifdef HAVE_EXT_CACHE
-    ctx->new_sess_cb = f;
-#else
-    (void)ctx;
-    (void)f;
-#endif
-}
-
-void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
-                                                        WOLFSSL_SESSION*))
-{
-#ifdef HAVE_EXT_CACHE
-    ctx->rem_sess_cb = f;
-#else
-    (void)ctx;
-    (void)f;
-#endif
-}
-#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
-
-#ifdef OPENSSL_EXTRA
-
-/*
- *
- * Note: It is expected that the importing and exporting function have been
- *       built with the same settings. For example if session tickets was
- *       enabled with the wolfSSL library exporting a session then it is
- *       expected to be turned on with the wolfSSL library importing the session.
- */
-int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
-{
-    int size = 0;
-#ifdef HAVE_EXT_CACHE
-    int idx = 0;
-#ifdef SESSION_CERTS
-    int i;
-#endif
-    unsigned char *data;
-
-    if (sess == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */
-    size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz +
-            SECRET_LEN + OPAQUE8_LEN;
-#ifdef SESSION_CERTS
-    /* Peer chain */
-    size += OPAQUE8_LEN;
-    for (i = 0; i < sess->chain.count; i++)
-        size += OPAQUE16_LEN + sess->chain.certs[i].length;
-    /* Protocol version + cipher suite */
-    size += OPAQUE16_LEN + OPAQUE16_LEN;
-#endif
-#ifndef NO_CLIENT_CACHE
-    /* ServerID len | ServerID */
-    size += OPAQUE16_LEN + sess->idLen;
-#endif
-#ifdef HAVE_SESSION_TICKET
-    /* ticket len | ticket */
-    size += OPAQUE16_LEN + sess->ticketLen;
-#endif
-#ifdef OPENSSL_EXTRA
-    /* session context ID len | session context ID */
-    size += OPAQUE8_LEN + sess->sessionCtxSz;
-#endif
-
-    if (p != NULL) {
-        if (*p == NULL)
-            *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL);
-        if (*p == NULL)
-            return 0;
-        data = *p;
-
-        c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN;
-        c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN;
-        data[idx++] = sess->sessionIDSz;
-        XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz);
-        idx += sess->sessionIDSz;
-        XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN;
-        data[idx++] = (byte)sess->haveEMS;
-#ifdef SESSION_CERTS
-        data[idx++] = (byte)sess->chain.count;
-        for (i = 0; i < sess->chain.count; i++) {
-            c16toa((word16)sess->chain.certs[i].length, data + idx);
-            idx += OPAQUE16_LEN;
-            XMEMCPY(data + idx, sess->chain.certs[i].buffer,
-                    sess->chain.certs[i].length);
-            idx += sess->chain.certs[i].length;
-        }
-        data[idx++] = sess->version.major;
-        data[idx++] = sess->version.minor;
-        data[idx++] = sess->cipherSuite0;
-        data[idx++] = sess->cipherSuite;
-#endif
-#ifndef NO_CLIENT_CACHE
-        c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN;
-        XMEMCPY(data + idx, sess->serverID, sess->idLen);
-        idx += sess->idLen;
-#endif
-#ifdef HAVE_SESSION_TICKET
-        c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN;
-        XMEMCPY(data + idx, sess->ticket, sess->ticketLen);
-        idx += sess->ticketLen;
-#endif
-#ifdef OPENSSL_EXTRA
-        data[idx++] = sess->sessionCtxSz;
-        XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz);
-        idx += sess->sessionCtxSz;
-#endif
-    }
-#endif
-
-    (void)sess;
-    (void)p;
-#ifdef HAVE_EXT_CACHE
-    (void)idx;
-#endif
-
-    return size;
-}
-
-
-/* TODO: no function to free new session.
- *
- * Note: It is expected that the importing and exporting function have been
- *       built with the same settings. For example if session tickets was
- *       enabled with the wolfSSL library exporting a session then it is
- *       expected to be turned on with the wolfSSL library importing the session.
- */
-WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
-                                const unsigned char** p, long i)
-{
-    WOLFSSL_SESSION* s = NULL;
-    int ret = 0;
-#if defined(HAVE_EXT_CACHE)
-    int idx;
-    byte* data;
-#ifdef SESSION_CERTS
-    int j;
-    word16 length;
-#endif
-#endif
-
-    (void)p;
-    (void)i;
-    (void)ret;
-
-    if (sess != NULL)
-        s = *sess;
-
-#ifdef HAVE_EXT_CACHE
-    if (p == NULL || *p == NULL)
-        return NULL;
-
-    if (s == NULL) {
-        s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
-                                      DYNAMIC_TYPE_OPENSSL);
-        if (s == NULL)
-            return NULL;
-        XMEMSET(s, 0, sizeof(WOLFSSL_SESSION));
-        s->isAlloced = 1;
-#ifdef HAVE_SESSION_TICKET
-        s->isDynamic = 0;
-#endif
-    }
-
-    idx = 0;
-    data = (byte*)*p;
-
-    /* bornOn | timeout | sessionID len */
-    if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN;
-    ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN;
-    s->sessionIDSz = data[idx++];
-
-    /* sessionID | secret | haveEMS */
-    if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    XMEMCPY(s->sessionID, data + idx, s->sessionIDSz);
-    idx  += s->sessionIDSz;
-    XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN;
-    s->haveEMS = data[idx++];
-
-#ifdef SESSION_CERTS
-    /* Certificate chain */
-    if (i - idx == 0) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    s->chain.count = data[idx++];
-    for (j = 0; j < s->chain.count; j++) {
-        if (i - idx < OPAQUE16_LEN) {
-            ret = BUFFER_ERROR;
-            goto end;
-        }
-        ato16(data + idx, &length); idx += OPAQUE16_LEN;
-        s->chain.certs[j].length = length;
-        if (i - idx < length) {
-            ret = BUFFER_ERROR;
-            goto end;
-        }
-        XMEMCPY(s->chain.certs[j].buffer, data + idx, length);
-        idx += length;
-    }
-
-    /* Protocol Version | Cipher suite */
-    if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    s->version.major = data[idx++];
-    s->version.minor = data[idx++];
-    s->cipherSuite0 = data[idx++];
-    s->cipherSuite = data[idx++];
-#endif
-#ifndef NO_CLIENT_CACHE
-    /* ServerID len */
-    if (i - idx < OPAQUE16_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN;
-
-    /* ServerID */
-    if (i - idx < s->idLen) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen;
-#endif
-#ifdef HAVE_SESSION_TICKET
-    /* ticket len */
-    if (i - idx < OPAQUE16_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN;
-
-    /* Dispose of ol dynamic ticket and ensure space for new ticket. */
-    if (s->isDynamic)
-        XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
-    if (s->ticketLen <= SESSION_TICKET_LEN)
-        s->ticket = s->staticTicket;
-    else {
-        s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
-                                   DYNAMIC_TYPE_SESSION_TICK);
-        if (s->ticket == NULL) {
-            ret = MEMORY_ERROR;
-            goto end;
-        }
-        s->isDynamic = 1;
-    }
-
-    /* ticket */
-    if (i - idx < s->ticketLen) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen;
-#endif
-#ifdef OPENSSL_EXTRA
-    /* byte for length of session context ID */
-    if (i - idx < OPAQUE8_LEN) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    s->sessionCtxSz = data[idx++];
-
-    /* app session context ID */
-    if (i - idx < s->sessionCtxSz) {
-        ret = BUFFER_ERROR;
-        goto end;
-    }
-    XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz;
-#endif
-    (void)idx;
-
-    if (sess != NULL)
-        *sess = s;
-
-    *p += idx;
-
-end:
-    if (ret != 0 && (sess == NULL || *sess != s))
-        wolfSSL_SESSION_free(s);
-#endif
-    return s;
-}
-
-
-long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
-    return sess->timeout;
-}
-
-
-long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
-    return sess->bornOn;
-}
-
-
-#endif /* OPENSSL_EXTRA */
-
-
-#ifdef KEEP_PEER_CERT
-char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
-{
-    if (x509 == NULL)
-        return NULL;
-
-    return x509->subjectCN;
-}
-#endif /* KEEP_PEER_CERT */
-
-#ifdef OPENSSL_EXTRA
-
-#if defined(FORTRESS) && !defined(NO_FILESYSTEM)
-int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
-{
-    int ret = WOLFSSL_FATAL_ERROR;
-
-    WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
-    if (ssl != NULL && fname != NULL)
-    {
-    #ifdef WOLFSSL_SMALL_STACK
-        byte           staticBuffer[1]; /* force heap usage */
-    #else
-        byte           staticBuffer[FILE_BUFFER_SIZE];
-    #endif
-        byte*          myBuffer  = staticBuffer;
-        int            dynamic   = 0;
-        XFILE          file      = XBADFILE;
-        size_t         sz        = 0;
-        WOLFSSL_CTX*   ctx       = ssl->ctx;
-        WOLFSSL_X509*  peer_cert = &ssl->peerCert;
-        DerBuffer*     fileDer = NULL;
-
-        file = XFOPEN(fname, "rb");
-        if (file == XBADFILE)
-            return WOLFSSL_BAD_FILE;
-
-        XFSEEK(file, 0, XSEEK_END);
-        sz = XFTELL(file);
-        XREWIND(file);
-
-        if (sz > (long)sizeof(staticBuffer)) {
-            WOLFSSL_MSG("Getting dynamic buffer");
-            myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
-            dynamic = 1;
-        }
-
-
-        if ((myBuffer != NULL) &&
-            (sz > 0) &&
-            (XFREAD(myBuffer, 1, sz, file) == sz) &&
-            (PemToDer(myBuffer, (long)sz, CERT_TYPE,
-                      &fileDer, ctx->heap, NULL, NULL) == 0) &&
-            (fileDer->length != 0) &&
-            (fileDer->length == peer_cert->derCert->length) &&
-            (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
-                                                fileDer->length) == 0))
-        {
-            ret = 0;
-        }
-
-        FreeDer(&fileDer);
-
-        if (dynamic)
-            XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
-
-        XFCLOSE(file);
-    }
-
-    return ret;
-}
-#endif
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || \
-    (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA))
-static WC_RNG globalRNG;
-static int initGlobalRNG = 0;
-#endif
-
-#ifdef OPENSSL_EXTRA
-
-/* Not thread safe! Can be called multiple times.
- * Checks if the global RNG has been created. If not then one is created.
- *
- * Returns SSL_SUCCESS when no error is encountered.
- */
-static int wolfSSL_RAND_Init(void)
-{
-    if (initGlobalRNG == 0) {
-        if (wc_InitRng(&globalRNG) < 0) {
-            WOLFSSL_MSG("wolfSSL Init Global RNG failed");
-            return 0;
-        }
-        initGlobalRNG = 1;
-    }
-
-    return SSL_SUCCESS;
-}
-
-
-/* SSL_SUCCESS on ok */
-int wolfSSL_RAND_seed(const void* seed, int len)
-{
-
-    WOLFSSL_MSG("wolfSSL_RAND_seed");
-
-    (void)seed;
-    (void)len;
-
-    return wolfSSL_RAND_Init();
-}
-
-
-/* Returns the path for reading seed data from.
- * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd
- *
- * Note uses stdlib by default unless XGETENV macro is overwritten
- *
- * fname buffer to hold path
- * len   length of fname buffer
- *
- * Returns a pointer to fname on success and NULL on failure
- */
-const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
-{
-#ifndef NO_FILESYSTEM
-    char* rt;
-    char ap[] = "/.rnd";
-
-    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
-
-    if (fname == NULL) {
-        return NULL;
-    }
-
-    XMEMSET(fname, 0, len);
-    /* if access to stdlib.h */
-    if ((rt = XGETENV("RANDFILE")) != NULL) {
-        if (len > XSTRLEN(rt)) {
-            XMEMCPY(fname, rt, XSTRLEN(rt));
-        }
-        else {
-            WOLFSSL_MSG("RANDFILE too large for buffer");
-            rt = NULL;
-        }
-    }
-
-    /* $RANDFILE was not set or is too large, check $HOME */
-    if (rt == NULL) {
-        WOLFSSL_MSG("Environment variable RANDFILE not set");
-        if ((rt = XGETENV("HOME")) == NULL) {
-            WOLFSSL_MSG("Environment variable HOME not set");
-            return NULL;
-        }
-
-        if (len > XSTRLEN(rt) +  XSTRLEN(ap)) {
-            fname[0] = '\0';
-            XSTRNCAT(fname, rt, len);
-            XSTRNCAT(fname, ap, len - XSTRLEN(rt));
-            return fname;
-        }
-        else {
-            WOLFSSL_MSG("HOME too large for buffer");
-            return NULL;
-        }
-    }
-
-    return fname;
-#else
-    /* no filesystem defined */
-    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
-    WOLFSSL_MSG("No filesystem feature enabled, not compiled in");
-    (void)fname;
-    (void)len;
-    return NULL;
-#endif
-}
-
-
-/* Writes 1024 bytes from the RNG to the given file name.
- *
- * fname name of file to write to
- *
- * Returns the number of bytes writen
- */
-int wolfSSL_RAND_write_file(const char* fname)
-{
-    int bytes = 0;
-
-    WOLFSSL_ENTER("RAND_write_file");
-
-    if (fname == NULL) {
-        return SSL_FAILURE;
-    }
-
-#ifndef NO_FILESYSTEM
-    {
-    #ifndef WOLFSSL_SMALL_STACK
-        unsigned char buf[1024];
-    #else
-        unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-        if (buf == NULL) {
-            WOLFSSL_MSG("malloc failed");
-            return SSL_FAILURE;
-        }
-    #endif
-        bytes = 1024; /* default size of buf */
-
-        if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) {
-            WOLFSSL_MSG("No RNG to use");
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-            return 0;
-        }
-
-        if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) {
-            WOLFSSL_MSG("Error generating random buffer");
-            bytes = 0;
-        }
-        else {
-            XFILE f;
-
-            f = XFOPEN(fname, "wb");
-            if (f == NULL) {
-                WOLFSSL_MSG("Error opening the file");
-                bytes = 0;
-            }
-            else {
-                XFWRITE(buf, 1, bytes, f);
-                XFCLOSE(f);
-            }
-        }
-        ForceZero(buf, bytes);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-    }
-#endif
-
-    return bytes;
-}
-
-#ifndef FREERTOS_TCP
-
-/* These constant values are protocol values made by egd */
-#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API)
-    #define WOLFSSL_EGD_NBLOCK 0x01
-    #include <sys/un.h>
-#endif
-
-/* at compile time check for HASH DRBG and throw warning if not found */
-#ifndef HAVE_HASHDRBG
-    #warning HAVE_HASHDRBG is needed for wolfSSL_RAND_egd to seed
-#endif
-
-/* This collects entropy from the path nm and seeds the global PRNG with it.
- * Makes a call to wolfSSL_RAND_Init which is not thread safe.
- *
- * nm is the file path to the egd server
- *
- * Returns the number of bytes read.
- */
-int wolfSSL_RAND_egd(const char* nm)
-{
-#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS)
-    struct sockaddr_un rem;
-    int fd;
-    int ret = WOLFSSL_SUCCESS;
-    word32 bytes = 0;
-    word32 idx   = 0;
-#ifndef WOLFSSL_SMALL_STACK
-    unsigned char buf[256];
-#else
-    unsigned char* buf;
-    buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buf == NULL) {
-        WOLFSSL_MSG("Not enough memory");
-        return WOLFSSL_FATAL_ERROR;
-    }
-#endif
-
-    if (nm == NULL) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (fd < 0) {
-        WOLFSSL_MSG("Error creating socket");
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return WOLFSSL_FATAL_ERROR;
-    }
-    if (ret == WOLFSSL_SUCCESS) {
-        rem.sun_family = AF_UNIX;
-        XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path));
-        rem.sun_path[sizeof(rem.sun_path)-1] = '\0';
-    }
-
-    /* connect to egd server */
-    if (ret == WOLFSSL_SUCCESS) {
-        if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un))
-                == -1) {
-            WOLFSSL_MSG("error connecting to egd server");
-            ret = WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) {
-        if (ret == WOLFSSL_SUCCESS) {
-            buf[idx]     = WOLFSSL_EGD_NBLOCK;
-            buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */
-            ret = (int)write(fd, buf + idx, 2);
-            if (ret <= 0 || ret != 2) {
-                if (errno == EAGAIN) {
-                    ret = WOLFSSL_SUCCESS;
-                    continue;
-                }
-                WOLFSSL_MSG("error requesting entropy from egd server");
-                ret = WOLFSSL_FATAL_ERROR;
-                break;
-            }
-        }
-
-        /* attempting to read */
-        buf[idx] = 0;
-        ret = (int)read(fd, buf + idx, 256 - bytes);
-        if (ret == 0) {
-            WOLFSSL_MSG("error reading entropy from egd server");
-            ret = WOLFSSL_FATAL_ERROR;
-            break;
-        }
-        if (ret > 0 && buf[idx] > 0) {
-            bytes += buf[idx]; /* egd stores amount sent in first byte */
-            if (bytes + idx > 255 || buf[idx] > ret) {
-                WOLFSSL_MSG("Buffer error");
-                ret = WOLFSSL_FATAL_ERROR;
-                break;
-            }
-            XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]);
-            idx = bytes;
-            ret = WOLFSSL_SUCCESS;
-            if (bytes >= 255) {
-                break;
-            }
-        }
-        else {
-            if (errno == EAGAIN || errno == EINTR) {
-                WOLFSSL_MSG("EGD would read");
-                ret = WOLFSSL_SUCCESS; /* try again */
-            }
-            else if (buf[idx] == 0) {
-                /* if egd returned 0 then there is no more entropy to be had.
-                   Do not try more reads. */
-                ret = WOLFSSL_SUCCESS;
-                break;
-            }
-            else {
-                WOLFSSL_MSG("Error with read");
-                ret = WOLFSSL_FATAL_ERROR;
-            }
-        }
-    }
-
-    if (bytes > 0 && ret == WOLFSSL_SUCCESS) {
-        wolfSSL_RAND_Init(); /* call to check global RNG is created */
-        if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes)
-                != 0) {
-            WOLFSSL_MSG("Error with reseeding DRBG structure");
-            ret = WOLFSSL_FATAL_ERROR;
-        }
-        #ifdef SHOW_SECRETS
-        { /* print out entropy found */
-            word32 i;
-            printf("EGD Entropy = ");
-            for (i = 0; i < bytes; i++) {
-                printf("%02X", buf[i]);
-            }
-            printf("\n");
-        }
-        #endif
-    }
-
-    ForceZero(buf, bytes);
-    #ifdef WOLFSSL_SMALL_STACK
-    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-    close(fd);
-
-    if (ret == WOLFSSL_SUCCESS) {
-        return bytes;
-    }
-    else {
-        return ret;
-    }
-#else /* defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !HAVE_FIPS */
-    WOLFSSL_MSG("Type of socket needed is not available");
-    WOLFSSL_MSG("\tor using FIPS mode where RNG API is not available");
-    (void)nm;
-
-    return WOLFSSL_FATAL_ERROR;
-#endif /* defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) */
-}
-
-#endif /* !FREERTOS_TCP */
-
-void wolfSSL_RAND_Cleanup(void)
-{
-    WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()");
-
-    if (initGlobalRNG != 0) {
-        wc_FreeRng(&globalRNG);
-        initGlobalRNG = 0;
-    }
-}
-
-
-int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
-{
-    return wolfSSL_RAND_bytes(buf, num);
-}
-
-
-/* SSL_SUCCESS on ok */
-int wolfSSL_RAND_bytes(unsigned char* buf, int num)
-{
-    int     ret = 0;
-    int     initTmpRng = 0;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_RAND_bytes");
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return ret;
-#endif
-
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else if (initGlobalRNG)
-        rng = &globalRNG;
-
-    if (rng) {
-        if (wc_RNG_GenerateBlock(rng, buf, num) != 0)
-            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
-        else
-            ret = WOLFSSL_SUCCESS;
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-}
-
-
-int wolfSSL_RAND_poll()
-{
-    byte  entropy[16];
-    int  ret = 0;
-    word32 entropy_sz = 16;
-
-    WOLFSSL_ENTER("wolfSSL_RAND_poll");
-    if (initGlobalRNG == 0){
-        WOLFSSL_MSG("Global RNG no Init");
-        return  WOLFSSL_FAILURE;
-    }
-    ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz);
-    if (ret != 0){
-        WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
-        ret = WOLFSSL_FAILURE;
-    }else
-        ret = WOLFSSL_SUCCESS;
-
-    return ret;
-}
-
-WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
-{
-    static int ctx;  /* wolfcrypt doesn't now need ctx */
-
-    WOLFSSL_MSG("wolfSSL_BN_CTX_new");
-    return (WOLFSSL_BN_CTX*)&ctx;
-
-}
-
-void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
-{
-    (void)ctx;
-    WOLFSSL_MSG("wolfSSL_BN_CTX_init");
-}
-
-
-void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
-{
-    (void)ctx;
-    WOLFSSL_MSG("wolfSSL_BN_CTX_free");
-    /* do free since static ctx that does nothing */
-}
-#endif /* OPENSSL_EXTRA */
-
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
-{
-    if (bn) {
-        XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
-        bn->neg      = 0;
-        bn->internal = NULL;
-    }
-}
-
-WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
-{
-    WOLFSSL_BIGNUM* external;
-    mp_int*        mpi;
-
-    WOLFSSL_MSG("wolfSSL_BN_new");
-
-    mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
-    if (mpi == NULL) {
-        WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
-        return NULL;
-    }
-
-    external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
-                                        DYNAMIC_TYPE_BIGINT);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
-        XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
-        return NULL;
-    }
-
-    InitwolfSSL_BigNum(external);
-    external->internal = mpi;
-    if (mp_init(mpi) != MP_OKAY) {
-        wolfSSL_BN_free(external);
-        return NULL;
-    }
-
-    return external;
-}
-
-
-void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_free");
-    if (bn) {
-        if (bn->internal) {
-            mp_forcezero((mp_int*)bn->internal);
-            XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
-            bn->internal = NULL;
-        }
-        XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
-        bn = NULL;
-    }
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
-
-void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_clear_free");
-
-    wolfSSL_BN_free(bn);
-}
-
-
-/* WOLFSSL_SUCCESS on ok */
-int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
-                  const WOLFSSL_BIGNUM* b)
-{
-    WOLFSSL_MSG("wolfSSL_BN_sub");
-
-    if (r == NULL || a == NULL || b == NULL)
-        return 0;
-
-    if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
-               (mp_int*)r->internal) == MP_OKAY)
-        return WOLFSSL_SUCCESS;
-
-    WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
-    return 0;
-}
-
-/* WOLFSSL_SUCCESS on ok */
-int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
-                  const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
-{
-    (void)c;
-    WOLFSSL_MSG("wolfSSL_BN_mod");
-
-    if (r == NULL || a == NULL || b == NULL)
-        return 0;
-
-    if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
-               (mp_int*)r->internal) == MP_OKAY)
-        return WOLFSSL_SUCCESS;
-
-    WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
-    return 0;
-}
-
-
-/* r = (a^p) % m */
-int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
-      const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
-{
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
-
-    (void) ctx;
-    if (r == NULL || a == NULL || p == NULL || m == NULL) {
-        WOLFSSL_MSG("Bad Argument");
-        return WOLFSSL_FAILURE;
-    }
-
-    if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal,
-               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
-        return WOLFSSL_SUCCESS;
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
-    (void)ret;
-
-    return WOLFSSL_FAILURE;
-}
-
-/* r = (a * p) % m */
-int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
-        const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
-{
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
-
-    (void) ctx;
-    if (r == NULL || a == NULL || p == NULL || m == NULL) {
-        WOLFSSL_MSG("Bad Argument");
-        return SSL_FAILURE;
-    }
-
-    if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal,
-               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
-        return SSL_SUCCESS;
-    }
-
-    WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
-    (void)ret;
-
-    return SSL_FAILURE;
-}
-
-const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
-{
-    static WOLFSSL_BIGNUM* bn_one = NULL;
-
-    WOLFSSL_MSG("wolfSSL_BN_value_one");
-
-    if (bn_one == NULL) {
-        bn_one = wolfSSL_BN_new();
-        if (bn_one) {
-            if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) {
-                /* handle error by freeing BN and returning NULL */
-                wolfSSL_BN_free(bn_one);
-                bn_one = NULL;
-            }
-        }
-    }
-
-    return bn_one;
-}
-
-/* return compliant with OpenSSL
- *   size of BIGNUM in bytes, 0 if error */
-int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
-
-    if (bn == NULL || bn->internal == NULL)
-        return WOLFSSL_FAILURE;
-
-    return mp_unsigned_bin_size((mp_int*)bn->internal);
-}
-
-/* return compliant with OpenSSL
- *   size of BIGNUM in bits, 0 if error */
-int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_ENTER("wolfSSL_BN_num_bits");
-
-    if (bn == NULL || bn->internal == NULL)
-        return WOLFSSL_FAILURE;
-
-    return mp_count_bits((mp_int*)bn->internal);
-}
-
-/* return compliant with OpenSSL
- *   1 if BIGNUM is zero, 0 else */
-int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_is_zero");
-
-    if (bn == NULL || bn->internal == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (mp_iszero((mp_int*)bn->internal) == MP_YES)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-/* return compliant with OpenSSL
- *   1 if BIGNUM is one, 0 else */
-int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_is_one");
-
-    if (bn == NULL || bn->internal == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-/* return compliant with OpenSSL
- *   1 if BIGNUM is odd, 0 else */
-int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_is_odd");
-
-    if (bn == NULL || bn->internal == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (mp_isodd((mp_int*)bn->internal) == MP_YES)
-        return WOLFSSL_SUCCESS;
-
-    return WOLFSSL_FAILURE;
-}
-
-/* return compliant with OpenSSL
- *   -1 if a < b, 0 if a == b and 1 if a > b
- */
-int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
-{
-    int ret;
-
-    WOLFSSL_MSG("wolfSSL_BN_cmp");
-
-    if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
-
-    return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1));
-}
-
-/* return compliant with OpenSSL
- *   length of BIGNUM in bytes, -1 if error */
-int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
-{
-    WOLFSSL_MSG("wolfSSL_BN_bn2bin");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("NULL bn error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (r == NULL)
-        return mp_unsigned_bin_size((mp_int*)bn->internal);
-
-    if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
-        WOLFSSL_MSG("mp_to_unsigned_bin error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    return mp_unsigned_bin_size((mp_int*)bn->internal);
-}
-
-
-WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
-                            WOLFSSL_BIGNUM* ret)
-{
-    int weOwn = 0;
-
-    WOLFSSL_MSG("wolfSSL_BN_bin2bn");
-
-    /* if ret is null create a BN */
-    if (ret == NULL) {
-        ret = wolfSSL_BN_new();
-        weOwn = 1;
-        if (ret == NULL)
-            return NULL;
-    }
-
-    /* check ret and ret->internal then read in value */
-    if (ret && ret->internal) {
-        if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
-            WOLFSSL_MSG("mp_read_unsigned_bin failure");
-            if (weOwn)
-                wolfSSL_BN_free(ret);
-            return NULL;
-        }
-    }
-
-    return ret;
-}
-
-/* return compliant with OpenSSL
- *   1 if success, 0 if error */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
-{
-    (void)bn;
-    (void)n;
-    WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
-    WOLFSSL_STUB("BN_mask_bits");
-    return SSL_FAILURE;
-}
-#endif
-
-
-/* WOLFSSL_SUCCESS on ok */
-int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
-{
-    int           ret    = 0;
-    int           len    = bits / 8;
-    int           initTmpRng = 0;
-    WC_RNG*       rng    = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG*       tmpRNG = NULL;
-    byte*         buff   = NULL;
-#else
-    WC_RNG        tmpRNG[1];
-    byte          buff[1024];
-#endif
-
-    (void)top;
-    (void)bottom;
-    WOLFSSL_MSG("wolfSSL_BN_rand");
-
-    if (bits % 8)
-        len++;
-
-#ifdef WOLFSSL_SMALL_STACK
-    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (buff == NULL || tmpRNG == NULL) {
-        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-        return ret;
-    }
-#endif
-
-    if (bn == NULL || bn->internal == NULL)
-        WOLFSSL_MSG("Bad function arguments");
-    else if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else if (initGlobalRNG)
-        rng = &globalRNG;
-
-    if (rng) {
-        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
-            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
-        else {
-            buff[0]     |= 0x80 | 0x40;
-            buff[len-1] |= 0x01;
-
-            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
-                WOLFSSL_MSG("mp read bin failed");
-            else
-                ret = WOLFSSL_SUCCESS;
-        }
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-}
-
-
-/* WOLFSSL_SUCCESS on ok
- * code is same as wolfSSL_BN_rand except for how top and bottom is handled.
- * top -1 then leave most sig bit alone
- * top 0 then most sig is set to 1
- * top is 1 then first two most sig bits are 1
- *
- * bottom is hot then odd number */
-int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
-{
-    int           ret    = 0;
-    int           len    = bits / 8;
-    int           initTmpRng = 0;
-    WC_RNG*       rng    = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG*       tmpRNG = NULL;
-    byte*         buff   = NULL;
-#else
-    WC_RNG        tmpRNG[1];
-    byte          buff[1024];
-#endif
-
-    WOLFSSL_MSG("wolfSSL_BN_rand");
-
-    if (bits % 8)
-        len++;
-
-#ifdef WOLFSSL_SMALL_STACK
-    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buff == NULL || tmpRNG == NULL) {
-        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-#endif
-
-    if (bn == NULL || bn->internal == NULL)
-        WOLFSSL_MSG("Bad function arguments");
-    else if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else if (initGlobalRNG)
-        rng = &globalRNG;
-
-    if (rng) {
-        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
-            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
-        else {
-            switch (top) {
-                case -1:
-                    break;
-
-                case 0:
-                    buff[0] |= 0x80;
-                    break;
-
-                case 1:
-                    buff[0] |= 0x80 | 0x40;
-                    break;
-            }
-
-            if (bottom == 1) {
-                buff[len-1] |= 0x01;
-            }
-
-            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
-                WOLFSSL_MSG("mp read bin failed");
-            else
-                ret = WOLFSSL_SUCCESS;
-        }
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if bit set, 0 else
- */
-int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
-{
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (n > DIGIT_BIT) {
-        WOLFSSL_MSG("input bit count too large");
-        return WOLFSSL_FAILURE;
-    }
-
-    return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
-{
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
-        WOLFSSL_MSG("mp_set_int error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* WOLFSSL_SUCCESS on ok */
-/* Note on use: this function expects str to be an even length. It is
- * converting pairs of bytes into 8-bit values. As an example, the RSA
- * public exponent is commonly 0x010001. To get it to convert, you need
- * to pass in the string "010001", it will fail if you use "10001". This
- * is an affect of how Base16_Decode() works.
- */
-int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
-{
-    int     ret     = 0;
-    word32  decSz   = 1024;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*   decoded = NULL;
-#else
-    byte    decoded[1024];
-#endif
-    int     weOwn = 0;
-
-    WOLFSSL_MSG("wolfSSL_BN_hex2bn");
-
-#ifdef WOLFSSL_SMALL_STACK
-    decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER);
-    if (decoded == NULL)
-        return ret;
-#endif
-
-    if (str == NULL || str[0] == '\0')
-        WOLFSSL_MSG("Bad function argument");
-    else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0)
-        WOLFSSL_MSG("Bad Base16_Decode error");
-    else if (bn == NULL)
-        ret = decSz;
-    else {
-        if (*bn == NULL) {
-            *bn = wolfSSL_BN_new();
-            if (*bn != NULL) {
-                weOwn = 1;
-            }
-        }
-
-        if (*bn == NULL)
-            WOLFSSL_MSG("BN new failed");
-        else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) {
-            WOLFSSL_MSG("Bad bin2bn error");
-            if (weOwn == 1) {
-                wolfSSL_BN_free(*bn); /* Free new BN */
-            }
-        }
-        else
-            ret = WOLFSSL_SUCCESS;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(decoded, NULL, DYNAMIC_TYPE_DER);
-#endif
-
-    return ret;
-}
-
-
-WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_BIGNUM* ret;
-
-    WOLFSSL_MSG("wolfSSL_BN_dup");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return NULL;
-    }
-
-    ret = wolfSSL_BN_new();
-    if (ret == NULL) {
-        WOLFSSL_MSG("bn new error");
-        return NULL;
-    }
-
-    if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        wolfSSL_BN_free(ret);
-        return NULL;
-    }
-
-    ret->neg = bn->neg;
-
-    return ret;
-}
-
-
-WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
-{
-    WOLFSSL_MSG("wolfSSL_BN_copy");
-
-    if (r == NULL || bn == NULL) {
-        WOLFSSL_MSG("r or bn NULL error");
-        return NULL;
-    }
-
-    if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        return NULL;
-    }
-
-    r->neg = bn->neg;
-
-    return r;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
-{
-    WOLFSSL_MSG("wolfSSL_BN_set_word");
-
-    if (bn == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) {
-        WOLFSSL_MSG("mp_init_set_int error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Returns the big number as an unsigned long if possible.
- *
- * bn  big number structure to get value from
- *
- * Returns value or 0xFFFFFFFFL if bigger than unsigned long.
- */
-unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
-{
-    mp_int* mp;
-
-    WOLFSSL_MSG("wolfSSL_BN_get_word");
-
-    if (bn == NULL) {
-        WOLFSSL_MSG("Invalid argument");
-        return 0;
-    }
-
-    if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
-        WOLFSSL_MSG("bignum is larger than unsigned long");
-        return 0xFFFFFFFFL;
-    }
-    mp = (mp_int*)bn->internal;
-
-    return (unsigned long)(mp->dp[0]);
-}
-
-/* return code compliant with OpenSSL :
- *   number length in decimal if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
-{
-    (void)bn;
-    (void)str;
-
-    WOLFSSL_MSG("wolfSSL_BN_dec2bn");
-    WOLFSSL_STUB("BN_dec2bn");
-    return SSL_FAILURE;
-}
-#endif
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
-char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
-{
-    int len = 0;
-    char *buf;
-
-    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return NULL;
-    }
-
-    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) {
-        WOLFSSL_MSG("mp_radix_size failure");
-        return NULL;
-    }
-
-    buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
-    if (buf == NULL) {
-        WOLFSSL_MSG("BN_bn2dec malloc buffer failure");
-        return NULL;
-    }
-
-    if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) {
-        XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
-        return NULL;
-    }
-
-    return buf;
-}
-#else
-char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
-{
-    (void)bn;
-
-    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
-
-    return NULL;
-}
-#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
-{
-    WOLFSSL_MSG("wolfSSL_BN_lshift");
-
-    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) {
-        WOLFSSL_MSG("mp_mul_2d error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
-{
-    WOLFSSL_MSG("wolfSSL_BN_rshift");
-
-    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_div_2d((mp_int*)bn->internal, n,
-                  (mp_int*)r->internal, NULL) != MP_OKAY) {
-        WOLFSSL_MSG("mp_mul_2d error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
-{
-    WOLFSSL_MSG("wolfSSL_BN_add_word");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) {
-        WOLFSSL_MSG("mp_add_d error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 else
- */
-int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
-{
-    WOLFSSL_MSG("wolfSSL_BN_add");
-
-    if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL ||
-        b == NULL || b->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
-               (mp_int*)r->internal) != MP_OKAY) {
-        WOLFSSL_MSG("mp_add_d error");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifdef WOLFSSL_KEY_GEN
-
-/* return code compliant with OpenSSL :
- *   1 if prime, 0 if not, -1 if error
- */
-int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks,
-                           WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
-{
-    int res;
-
-    (void)ctx;
-    (void)cb;
-
-    WOLFSSL_MSG("wolfSSL_BN_is_prime_ex");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) {
-        WOLFSSL_MSG("mp_prime_is_prime error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (res != MP_YES) {
-        WOLFSSL_MSG("mp_prime_is_prime not prime");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* return code compliant with OpenSSL :
- *   (bn mod w) if success, -1 if error
- */
-WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
-                                     WOLFSSL_BN_ULONG w)
-{
-    WOLFSSL_BN_ULONG ret = 0;
-
-    WOLFSSL_MSG("wolfSSL_BN_mod_word");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
-    }
-
-    if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) {
-        WOLFSSL_MSG("mp_add_d error");
-        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
-    }
-
-    return ret;
-}
-#endif /* #ifdef WOLFSSL_KEY_GEN */
-
-char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
-{
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL)
-    int len = 0;
-    char *buf;
-
-    WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return NULL;
-    }
-
-    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) {
-        WOLFSSL_MSG("mp_radix_size failure");
-        return NULL;
-    }
-
-    buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC);
-    if (buf == NULL) {
-        WOLFSSL_MSG("BN_bn2hex malloc buffer failure");
-        return NULL;
-    }
-
-    if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) {
-        XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
-        return NULL;
-    }
-
-    return buf;
-#else
-    (void)bn;
-    WOLFSSL_MSG("wolfSSL_BN_bn2hex not compiled in");
-    return (char*)"";
-#endif
-}
-
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
-{
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL)
-    char *buf;
-
-    WOLFSSL_ENTER("wolfSSL_BN_print_fp");
-
-    if (fp == NULL || bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    buf = wolfSSL_BN_bn2hex(bn);
-    if (buf == NULL) {
-        WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
-        return WOLFSSL_FAILURE;
-    }
-
-    fprintf(fp, "%s", buf);
-    XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
-
-    return WOLFSSL_SUCCESS;
-#else
-    (void)fp;
-    (void)bn;
-
-    WOLFSSL_MSG("wolfSSL_BN_print_fp not compiled in");
-
-    return WOLFSSL_SUCCESS;
-#endif
-}
-#endif /* !NO_FILESYSTEM */
-
-
-WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
-{
-    /* ctx is not used, return new Bignum */
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
-
-    return wolfSSL_BN_new();
-}
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
-{
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
-    WOLFSSL_STUB("BN_CTX_start");
-    WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
-}
-#endif
-
-
-WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r,
-                                       WOLFSSL_BIGNUM *a,
-                                       const WOLFSSL_BIGNUM *n,
-                                       WOLFSSL_BN_CTX *ctx)
-{
-    int dynamic = 0;
-
-    /* ctx is not used */
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
-
-    /* check parameter */
-    if (r == NULL) {
-        r = wolfSSL_BN_new();
-        if (r == NULL){
-            WOLFSSL_MSG("WolfSSL_BN_new() failed");
-            return NULL;
-        }
-        dynamic = 1;
-    }
-
-    if (a == NULL) {
-        WOLFSSL_MSG("a NULL error");
-        if (dynamic == 1) {
-            wolfSSL_BN_free(r);
-        }
-        return NULL;
-    }
-
-    if (n == NULL) {
-        WOLFSSL_MSG("n NULL error");
-        if (dynamic == 1) {
-            wolfSSL_BN_free(r);
-        }
-        return NULL;
-    }
-
-    /* Compute inverse of a modulo n and return r */
-    if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal,
-                  (mp_int*)r->internal) == MP_VAL){
-        WOLFSSL_MSG("mp_invmod() error");
-        if (dynamic == 1) {
-            wolfSSL_BN_free(r);
-        }
-        return NULL;
-    }
-
-    return  r;
-}
-
-#ifndef NO_DH
-
-static void InitwolfSSL_DH(WOLFSSL_DH* dh)
-{
-    if (dh) {
-        dh->p        = NULL;
-        dh->g        = NULL;
-        dh->q        = NULL;
-        dh->pub_key  = NULL;
-        dh->priv_key = NULL;
-        dh->internal = NULL;
-        dh->inSet    = 0;
-        dh->exSet    = 0;
-    }
-}
-
-
-WOLFSSL_DH* wolfSSL_DH_new(void)
-{
-    WOLFSSL_DH* external;
-    DhKey*     key;
-
-    WOLFSSL_MSG("wolfSSL_DH_new");
-
-    key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure");
-        return NULL;
-    }
-
-    external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL,
-                                    DYNAMIC_TYPE_DH);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure");
-        XFREE(key, NULL, DYNAMIC_TYPE_DH);
-        return NULL;
-    }
-
-    InitwolfSSL_DH(external);
-    if (wc_InitDhKey(key) != 0) {
-        WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure");
-        XFREE(key, NULL, DYNAMIC_TYPE_DH);
-        XFREE(external, NULL, DYNAMIC_TYPE_DH);
-        return NULL;
-    }
-    external->internal = key;
-
-    return external;
-}
-
-
-void wolfSSL_DH_free(WOLFSSL_DH* dh)
-{
-    WOLFSSL_MSG("wolfSSL_DH_free");
-
-    if (dh) {
-        if (dh->internal) {
-            wc_FreeDhKey((DhKey*)dh->internal);
-            XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH);
-            dh->internal = NULL;
-        }
-        wolfSSL_BN_free(dh->priv_key);
-        wolfSSL_BN_free(dh->pub_key);
-        wolfSSL_BN_free(dh->g);
-        wolfSSL_BN_free(dh->p);
-        wolfSSL_BN_free(dh->q);
-        InitwolfSSL_DH(dh);  /* set back to NULLs for safety */
-
-        XFREE(dh, NULL, DYNAMIC_TYPE_DH);
-    }
-}
-
-
-static int SetDhInternal(WOLFSSL_DH* dh)
-{
-    int            ret = WOLFSSL_FATAL_ERROR;
-    int            pSz = 1024;
-    int            gSz = 1024;
-#ifdef WOLFSSL_SMALL_STACK
-    unsigned char* p   = NULL;
-    unsigned char* g   = NULL;
-#else
-    unsigned char  p[1024];
-    unsigned char  g[1024];
-#endif
-
-    WOLFSSL_ENTER("SetDhInternal");
-
-    if (dh == NULL || dh->p == NULL || dh->g == NULL)
-        WOLFSSL_MSG("Bad function arguments");
-    else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz)
-        WOLFSSL_MSG("Bad p internal size");
-    else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz)
-        WOLFSSL_MSG("Bad g internal size");
-    else {
-    #ifdef WOLFSSL_SMALL_STACK
-        p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-
-        if (p == NULL || g == NULL) {
-            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-            return ret;
-        }
-    #endif
-
-        pSz = wolfSSL_BN_bn2bin(dh->p, p);
-        gSz = wolfSSL_BN_bn2bin(dh->g, g);
-
-        if (pSz <= 0 || gSz <= 0)
-            WOLFSSL_MSG("Bad BN2bin set");
-        else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0)
-            WOLFSSL_MSG("Bad DH SetKey");
-        else {
-            dh->inSet = 1;
-            ret = WOLFSSL_SUCCESS;
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    #endif
-    }
-
-
-    return ret;
-}
-
-/* return code compliant with OpenSSL :
- *   DH prime size in bytes if success, 0 if error
- */
-int wolfSSL_DH_size(WOLFSSL_DH* dh)
-{
-    WOLFSSL_MSG("wolfSSL_DH_size");
-
-    if (dh == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    return wolfSSL_BN_num_bytes(dh->p);
-}
-
-
-/* This sets a big number with the 1536-bit prime from RFC 3526.
- *
- * bn  if not NULL then the big number structure is used. If NULL then a new
- *     big number structure is created.
- *
- * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
- */
-WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn)
-{
-    const char prm[] = {
-        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
-        "C4C6628B80DC1CD129024E088A67CC74"
-        "020BBEA63B139B22514A08798E3404DD"
-        "EF9519B3CD3A431B302B0A6DF25F1437"
-        "4FE1356D6D51C245E485B576625E7EC6"
-        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
-        "EE386BFB5A899FA5AE9F24117C4B1FE6"
-        "49286651ECE45B3DC2007CB8A163BF05"
-        "98DA48361C55D39A69163FA8FD24CF5F"
-        "83655D23DCA3AD961C62F356208552BB"
-        "9ED529077096966D670C354E4ABC9804"
-        "F1746C08CA237327FFFFFFFFFFFFFFFF"
-    };
-
-    WOLFSSL_ENTER("wolfSSL_DH_1536_prime");
-
-    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
-        WOLFSSL_MSG("Error converting DH 1536 prime to big number");
-        return NULL;
-    }
-
-    return bn;
-}
-
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
-{
-    int            ret    = WOLFSSL_FAILURE;
-    word32         pubSz  = 768;
-    word32         privSz = 768;
-    int            initTmpRng = 0;
-    WC_RNG*        rng    = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    unsigned char* pub    = NULL;
-    unsigned char* priv   = NULL;
-    WC_RNG*        tmpRNG = NULL;
-#else
-    unsigned char  pub [768];
-    unsigned char  priv[768];
-    WC_RNG         tmpRNG[1];
-#endif
-
-    WOLFSSL_MSG("wolfSSL_DH_generate_key");
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    pub    = (unsigned char*)XMALLOC(pubSz,   NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    priv   = (unsigned char*)XMALLOC(privSz,  NULL, DYNAMIC_TYPE_PRIVATE_KEY);
-
-    if (tmpRNG == NULL || pub == NULL || priv == NULL) {
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-        XFREE(pub,    NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        XFREE(priv,   NULL, DYNAMIC_TYPE_PRIVATE_KEY);
-        return ret;
-    }
-#endif
-
-    if (dh == NULL || dh->p == NULL || dh->g == NULL)
-        WOLFSSL_MSG("Bad function arguments");
-    else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS)
-            WOLFSSL_MSG("Bad DH set internal");
-    else if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-       if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz,
-                                                               pub, &pubSz) < 0)
-            WOLFSSL_MSG("Bad wc_DhGenerateKeyPair");
-       else {
-            if (dh->pub_key)
-                wolfSSL_BN_free(dh->pub_key);
-
-            dh->pub_key = wolfSSL_BN_new();
-            if (dh->pub_key == NULL) {
-                WOLFSSL_MSG("Bad DH new pub");
-            }
-            if (dh->priv_key)
-                wolfSSL_BN_free(dh->priv_key);
-
-            dh->priv_key = wolfSSL_BN_new();
-
-            if (dh->priv_key == NULL) {
-                WOLFSSL_MSG("Bad DH new priv");
-            }
-
-            if (dh->pub_key && dh->priv_key) {
-               if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL)
-                   WOLFSSL_MSG("Bad DH bn2bin error pub");
-               else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL)
-                   WOLFSSL_MSG("Bad DH bn2bin error priv");
-               else
-                   ret = WOLFSSL_SUCCESS;
-            }
-        }
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-    XFREE(pub,    NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(priv,   NULL, DYNAMIC_TYPE_PRIVATE_KEY);
-#endif
-
-    return ret;
-}
-
-
-/* return code compliant with OpenSSL :
- *   size of shared secret if success, -1 if error
- */
-int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
-                          WOLFSSL_DH* dh)
-{
-    int            ret    = WOLFSSL_FATAL_ERROR;
-    word32         keySz  = 0;
-    word32         pubSz  = 1024;
-    word32         privSz = 1024;
-#ifdef WOLFSSL_SMALL_STACK
-    unsigned char* pub    = NULL;
-    unsigned char* priv   = NULL;
-#else
-    unsigned char  pub [1024];
-    unsigned char  priv[1024];
-#endif
-
-    WOLFSSL_MSG("wolfSSL_DH_compute_key");
-
-#ifdef WOLFSSL_SMALL_STACK
-    pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (pub == NULL)
-        return ret;
-
-    priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
-    if (priv == NULL) {
-        XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        return ret;
-    }
-#endif
-
-    if (dh == NULL || dh->priv_key == NULL || otherPub == NULL)
-        WOLFSSL_MSG("Bad function arguments");
-    else if ((keySz = (word32)DH_size(dh)) == 0)
-        WOLFSSL_MSG("Bad DH_size");
-    else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz)
-        WOLFSSL_MSG("Bad priv internal size");
-    else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz)
-        WOLFSSL_MSG("Bad otherPub size");
-    else {
-        privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv);
-        pubSz  = wolfSSL_BN_bn2bin(otherPub, pub);
-        if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){
-                WOLFSSL_MSG("Bad DH set internal");
-        }
-        if (privSz <= 0 || pubSz <= 0)
-            WOLFSSL_MSG("Bad BN2bin set");
-        else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz,
-                            priv, privSz, pub, pubSz) < 0)
-            WOLFSSL_MSG("wc_DhAgree failed");
-        else
-            ret = (int)keySz;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(pub,  NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
-#endif
-
-    return ret;
-}
-#endif /* NO_DH */
-
-
-#ifndef NO_DSA
-static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa)
-{
-    if (dsa) {
-        dsa->p        = NULL;
-        dsa->q        = NULL;
-        dsa->g        = NULL;
-        dsa->pub_key  = NULL;
-        dsa->priv_key = NULL;
-        dsa->internal = NULL;
-        dsa->inSet    = 0;
-        dsa->exSet    = 0;
-    }
-}
-
-
-WOLFSSL_DSA* wolfSSL_DSA_new(void)
-{
-    WOLFSSL_DSA* external;
-    DsaKey*     key;
-
-    WOLFSSL_MSG("wolfSSL_DSA_new");
-
-    key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure");
-        return NULL;
-    }
-
-    external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL,
-                                    DYNAMIC_TYPE_DSA);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure");
-        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
-        return NULL;
-    }
-
-    InitwolfSSL_DSA(external);
-    if (wc_InitDsaKey(key) != 0) {
-        WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure");
-        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
-        wolfSSL_DSA_free(external);
-        return NULL;
-    }
-    external->internal = key;
-
-    return external;
-}
-
-
-void wolfSSL_DSA_free(WOLFSSL_DSA* dsa)
-{
-    WOLFSSL_MSG("wolfSSL_DSA_free");
-
-    if (dsa) {
-        if (dsa->internal) {
-            FreeDsaKey((DsaKey*)dsa->internal);
-            XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA);
-            dsa->internal = NULL;
-        }
-        wolfSSL_BN_free(dsa->priv_key);
-        wolfSSL_BN_free(dsa->pub_key);
-        wolfSSL_BN_free(dsa->g);
-        wolfSSL_BN_free(dsa->q);
-        wolfSSL_BN_free(dsa->p);
-        InitwolfSSL_DSA(dsa);  /* set back to NULLs for safety */
-
-        XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
-        dsa = NULL;
-    }
-}
-
-#endif /* NO_DSA */
-
-#endif /* OPENSSL_EXTRA */
-#if !defined(NO_RSA) && defined(OPENSSL_EXTRA_X509_SMALL)
-static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa)
-{
-    if (rsa) {
-        XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
-    }
-}
-
-void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
-{
-    WOLFSSL_ENTER("wolfSSL_RSA_free");
-
-    if (rsa) {
-        if (rsa->internal) {
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
-    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
-            WC_RNG* rng;
-
-            /* check if RNG is owned before freeing it */
-            if (rsa->ownRng) {
-                rng = ((RsaKey*)rsa->internal)->rng;
-                if (rng != NULL && rng != &globalRNG) {
-                    wc_FreeRng(rng);
-                    XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
-                }
-            }
-#endif /* WC_RSA_BLINDING */
-            wc_FreeRsaKey((RsaKey*)rsa->internal);
-            XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA);
-            rsa->internal = NULL;
-        }
-        wolfSSL_BN_free(rsa->iqmp);
-        wolfSSL_BN_free(rsa->dmq1);
-        wolfSSL_BN_free(rsa->dmp1);
-        wolfSSL_BN_free(rsa->q);
-        wolfSSL_BN_free(rsa->p);
-        wolfSSL_BN_free(rsa->d);
-        wolfSSL_BN_free(rsa->e);
-        wolfSSL_BN_free(rsa->n);
-
-    #ifdef WC_RSA_BLINDING
-        if (wc_FreeRng(rsa->rng) != 0) {
-            WOLFSSL_MSG("Issue freeing rng");
-        }
-        XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG);
-    #endif
-
-        InitwolfSSL_Rsa(rsa);  /* set back to NULLs for safety */
-
-        XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
-        rsa = NULL;
-    }
-}
-
-WOLFSSL_RSA* wolfSSL_RSA_new(void)
-{
-    WOLFSSL_RSA* external;
-    RsaKey*     key;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_new");
-
-    key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure");
-        return NULL;
-    }
-
-    external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL,
-                                     DYNAMIC_TYPE_RSA);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
-        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
-        return NULL;
-    }
-
-    InitwolfSSL_Rsa(external);
-    if (wc_InitRsaKey(key, NULL) != 0) {
-        WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure");
-        XFREE(external, NULL, DYNAMIC_TYPE_RSA);
-        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
-        return NULL;
-    }
-
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
-    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
-    {
-        WC_RNG* rng = NULL;
-
-        rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-        if (rng != NULL && wc_InitRng(rng) != 0) {
-            WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
-            XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
-            rng = NULL;
-        }
-
-        external->ownRng = 1;
-        if (rng == NULL && initGlobalRNG) {
-            external->ownRng = 0;
-            rng = &globalRNG;
-        }
-
-        if (rng == NULL) {
-            WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
-            XFREE(external, NULL, DYNAMIC_TYPE_RSA);
-            XFREE(key, NULL, DYNAMIC_TYPE_RSA);
-            return NULL;
-        }
-
-        wc_RsaSetRNG(key, rng);
-    }
-#endif /* WC_RSA_BLINDING */
-
-    external->internal = key;
-    external->inSet = 0;
-    return external;
-}
-#endif /* !NO_RSA && OPENSSL_EXTRA_X509_SMALL */
-
-/* these defines are to make sure the functions SetIndividualExternal is not
- * declared and then not used. */
-#if !defined(NO_ASN) || !defined(NO_DSA) || defined(HAVE_ECC) || \
-    (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA))
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* when calling SetIndividualExternal, mpi should be cleared by caller if no
- * longer used. ie mp_clear(mpi). This is to free data when fastmath is
- * disabled since a copy of mpi is made by this function and placed into bn.
- */
-static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
-{
-    byte dynamic = 0;
-
-    WOLFSSL_MSG("Entering SetIndividualExternal");
-
-    if (mpi == NULL || bn == NULL) {
-        WOLFSSL_MSG("mpi NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (*bn == NULL) {
-        *bn = wolfSSL_BN_new();
-        if (*bn == NULL) {
-            WOLFSSL_MSG("SetIndividualExternal alloc failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-        dynamic = 1;
-    }
-
-    if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        if (dynamic == 1) {
-            wolfSSL_BN_free(*bn);
-        }
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA /* only without X509_SMALL */
-static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi)
-{
-    WOLFSSL_MSG("Entering SetIndividualInternal");
-
-    if (bn == NULL || bn->internal == NULL) {
-        WOLFSSL_MSG("bn NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) {
-        WOLFSSL_MSG("mpi NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
-        WOLFSSL_MSG("mp_copy error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_ASN
-WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
-                                       WOLFSSL_BIGNUM *bn)
-{
-    mp_int mpi;
-    word32 idx = 0;
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN");
-
-    if (ai == NULL) {
-        return NULL;
-    }
-
-    if ((ret = GetInt(&mpi, ai->data, &idx, ai->dataMax)) != 0) {
-        /* expecting ASN1 format for INTEGER */
-        WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret);
-        return NULL;
-    }
-
-    /* mp_clear needs called because mpi is copied and causes memory leak with
-     * --disable-fastmath */
-    ret = SetIndividualExternal(&bn, &mpi);
-    mp_clear(&mpi);
-
-    if (ret != WOLFSSL_SUCCESS) {
-        return NULL;
-    }
-    return bn;
-}
-#endif /* !NO_ASN */
-
-#if !defined(NO_DSA) && !defined(NO_DH)
-WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa)
-{
-    WOLFSSL_DH* dh;
-    DhKey*      key;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_dup_DH");
-
-    if (dsa == NULL) {
-        return NULL;
-    }
-
-    dh = wolfSSL_DH_new();
-    if (dh == NULL) {
-        return NULL;
-    }
-    key = (DhKey*)dh->internal;
-
-    if (dsa->p != NULL &&
-        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa p key error");
-        wolfSSL_DH_free(dh);
-        return NULL;
-    }
-    if (dsa->g != NULL &&
-        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa g key error");
-        wolfSSL_DH_free(dh);
-        return NULL;
-    }
-
-    if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa p key error");
-        wolfSSL_DH_free(dh);
-        return NULL;
-    }
-    if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa g key error");
-        wolfSSL_DH_free(dh);
-        return NULL;
-    }
-
-    return dh;
-}
-#endif /* !defined(NO_DSA) && !defined(NO_DH) */
-
-#endif /* OPENSSL_EXTRA */
-#endif /* !NO_RSA && !NO_DSA */
-
-#ifdef OPENSSL_EXTRA
-
-#ifndef NO_DSA
-/* wolfSSL -> OpenSSL */
-static int SetDsaExternal(WOLFSSL_DSA* dsa)
-{
-    DsaKey* key;
-    WOLFSSL_MSG("Entering SetDsaExternal");
-
-    if (dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("dsa key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (DsaKey*)dsa->internal;
-
-    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa p key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa q key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa g key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa y key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa x key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    dsa->exSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* Openssl -> WolfSSL */
-static int SetDsaInternal(WOLFSSL_DSA* dsa)
-{
-    DsaKey* key;
-    WOLFSSL_MSG("Entering SetDsaInternal");
-
-    if (dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("dsa key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (DsaKey*)dsa->internal;
-
-    if (dsa->p != NULL &&
-        SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa p key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (dsa->q != NULL &&
-        SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa q key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (dsa->g != NULL &&
-        SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa g key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (dsa->pub_key != NULL) {
-        if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa pub_key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* public key */
-        key->type = DSA_PUBLIC;
-    }
-
-    if (dsa->priv_key != NULL) {
-        if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa priv_key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* private key */
-        key->type = DSA_PRIVATE;
-    }
-
-    dsa->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_DSA */
-#endif /* OPENSSL_EXTRA */
-
-#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \
-    !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-/* WolfSSL -> OpenSSL */
-static int SetRsaExternal(WOLFSSL_RSA* rsa)
-{
-    RsaKey* key;
-    WOLFSSL_MSG("Entering SetRsaExternal");
-
-    if (rsa == NULL || rsa->internal == NULL) {
-        WOLFSSL_MSG("rsa key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (RsaKey*)rsa->internal;
-
-    if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa n key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa e key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (key->type == RSA_PRIVATE) {
-        if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa d key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa p key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa q key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-    #ifndef RSA_LOW_MEM
-        if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa dP key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa dQ key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa u key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    #endif /* !RSA_LOW_MEM */
-    }
-    rsa->exSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-#ifdef OPENSSL_EXTRA
-#if !defined(NO_RSA)
-#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-/* Openssl -> WolfSSL */
-static int SetRsaInternal(WOLFSSL_RSA* rsa)
-{
-    RsaKey* key;
-    WOLFSSL_MSG("Entering SetRsaInternal");
-
-    if (rsa == NULL || rsa->internal == NULL) {
-        WOLFSSL_MSG("rsa key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (RsaKey*)rsa->internal;
-
-    if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa n key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa e key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    /* public key */
-    key->type = RSA_PUBLIC;
-
-    if (rsa->d != NULL) {
-        if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("rsa d key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* private key */
-        key->type = RSA_PRIVATE;
-    }
-
-    if (rsa->p != NULL &&
-        SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa p key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (rsa->q != NULL &&
-        SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa q key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-#ifndef RSA_LOW_MEM
-    if (rsa->dmp1 != NULL &&
-        SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa dP key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (rsa->dmq1 != NULL &&
-        SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa dQ key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (rsa->iqmp != NULL &&
-        SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("rsa u key error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-#endif /* !RSA_LOW_MEM */
-
-    rsa->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* SSL_SUCCESS on ok */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn)
-{
-    (void)rsa;
-    (void)bn;
-    WOLFSSL_STUB("RSA_blinding_on");
-    WOLFSSL_MSG("wolfSSL_RSA_blinding_on");
-
-    return WOLFSSL_SUCCESS;  /* on by default */
-}
-#endif
-
-/* return compliant with OpenSSL
- *   size of encrypted data if success , -1 if error
- */
-int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr,
-                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
-    int initTmpRng = 0;
-    WC_RNG *rng = NULL;
-    int outLen;
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-#endif
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-    int  mgf = WC_MGF1NONE;
-    enum wc_HashType hash = WC_HASH_TYPE_NONE;
-#endif
-
-    WOLFSSL_MSG("wolfSSL_RSA_public_encrypt");
-
-    /* Check and remap the padding to internal values, if needed. */
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-    if (padding == RSA_PKCS1_PADDING)
-        padding = WC_RSA_PKCSV15_PAD;
-    else if (padding == RSA_PKCS1_OAEP_PADDING) {
-        padding = WC_RSA_OAEP_PAD;
-        hash = WC_HASH_TYPE_SHA;
-        mgf = WC_MGF1SHA1;
-    }
-#else
-    if (padding == RSA_PKCS1_PADDING)
-      ;
-#endif
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding");
-        return 0;
-    }
-
-    if (rsa->inSet == 0)
-    {
-        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-
-    outLen = wolfSSL_RSA_size(rsa);
-
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
-    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
-    rng = ((RsaKey*)rsa->internal)->rng;
-#endif
-    if (rng == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (tmpRNG == NULL)
-            return 0;
-#endif
-
-        if (wc_InitRng(tmpRNG) == 0) {
-            rng = tmpRNG;
-            initTmpRng = 1;
-        }
-        else {
-            WOLFSSL_MSG("Bad RNG Init, trying global");
-            if (initGlobalRNG == 0)
-                WOLFSSL_MSG("Global RNG no Init");
-            else
-                rng = &globalRNG;
-        }
-    }
-
-    if (outLen == 0) {
-        WOLFSSL_MSG("Bad RSA size");
-    }
-
-    if (rng) {
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-        ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen,
-                             (RsaKey*)rsa->internal, rng, padding,
-                             hash, mgf, NULL, 0);
-#else
-        ret = wc_RsaPublicEncrypt(fr, len, to, outLen,
-                             (RsaKey*)rsa->internal, rng);
-#endif
-        if (ret <= 0) {
-            WOLFSSL_MSG("Bad Rsa Encrypt");
-        }
-        if (len <= 0) {
-            WOLFSSL_MSG("Bad Rsa Encrypt");
-        }
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (ret >= 0)
-        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success");
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed");
-        ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */
-    }
-    return ret;
-}
-
-/* return compliant with OpenSSL
- *   size of plain recovered data if success , -1 if error
- */
-int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr,
-                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
-    int outLen;
-    int ret = 0;
-  #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-    int mgf = WC_MGF1NONE;
-    enum wc_HashType hash = WC_HASH_TYPE_NONE;
-  #endif
-
-    WOLFSSL_MSG("wolfSSL_RSA_private_decrypt");
-
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-    if (padding == RSA_PKCS1_PADDING)
-        padding = WC_RSA_PKCSV15_PAD;
-    else if (padding == RSA_PKCS1_OAEP_PADDING) {
-        padding = WC_RSA_OAEP_PAD;
-        hash = WC_HASH_TYPE_SHA;
-        mgf = WC_MGF1SHA1;
-    }
-#else
-    if (padding == RSA_PKCS1_PADDING)
-        ;
-#endif
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding");
-        return 0;
-    }
-
-    if (rsa->inSet == 0)
-    {
-        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-
-    outLen = wolfSSL_RSA_size(rsa);
-    if (outLen == 0) {
-        WOLFSSL_MSG("Bad RSA size");
-    }
-
-    /* size of 'to' buffer must be size of RSA key */
-#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
-    ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen,
-                            (RsaKey*)rsa->internal, padding,
-                            hash, mgf, NULL, 0);
-#else
-    ret = wc_RsaPrivateDecrypt(fr, len, to, outLen,
-                            (RsaKey*)rsa->internal);
-#endif
-
-    if (len <= 0) {
-        WOLFSSL_MSG("Bad Rsa Decrypt");
-    }
-
-    if (ret > 0)
-        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success");
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed");
-        ret = WOLFSSL_FATAL_ERROR;
-    }
-    return ret;
-}
-
-
-/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA
- * public decrypt.
- *
- * len  Length of input buffer
- * in   Input buffer to sign
- * out  Output buffer (expected to be greater than or equal to RSA key size)
- * rsa     Key to use for encryption
- * padding Type of RSA padding to use.
- */
-int wolfSSL_RSA_private_encrypt(int len, unsigned char* in,
-                            unsigned char* out, WOLFSSL_RSA* rsa, int padding)
-{
-    int sz = 0;
-    WC_RNG* rng = NULL;
-    RsaKey* key;
-
-    WOLFSSL_MSG("wolfSSL_RSA_private_encrypt");
-
-    if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return 0;
-    }
-
-    if (padding != RSA_PKCS1_PADDING) {
-        WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding");
-        return 0;
-    }
-
-    if (rsa->inSet == 0)
-    {
-        WOLFSSL_MSG("Setting internal RSA structure");
-
-        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-
-    key = (RsaKey*)rsa->internal;
-    #if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA)
-    rng = key->rng;
-    #else
-#ifndef HAVE_FIPS
-    if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0) {
-#else
-    if (wc_InitRng(rng) != 0) {
-#endif
-        WOLFSSL_MSG("Error with random number");
-        return SSL_FATAL_ERROR;
-    }
-    #endif
-
-    /* size of output buffer must be size of RSA key */
-    sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng);
-    #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
-    if (wc_FreeRng(rng) != 0) {
-        WOLFSSL_MSG("Error freeing random number generator");
-        return SSL_FATAL_ERROR;
-    }
-    #endif
-    if (sz <= 0) {
-        WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz);
-        return 0;
-    }
-
-    return sz;
-}
-#endif /* HAVE_USER_RSA */
-
-/* return compliant with OpenSSL
- *   RSA modulus size in bytes, -1 if error
- */
-int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
-{
-    WOLFSSL_ENTER("wolfSSL_RSA_size");
-
-    if (rsa == NULL)
-        return WOLFSSL_FATAL_ERROR;
-    if (rsa->inSet == 0)
-    {
-        if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-    return wc_RsaEncryptSize((RsaKey*)rsa->internal);
-}
-
-
-/* Generates a RSA key of length len
- *
- * len  length of RSA key i.e. 2048
- * e    e to use when generating RSA key
- * f    callback function for generation details
- * data user callback argument
- *
- * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly
- *       rounded down. For example generating a key of size 2999 with e =
- *       65537 will make a key of size 374 instead of 375.
- * Returns a new RSA key on success and NULL on failure
- */
-WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e,
-                                      void(*f)(int, int, void*), void* data)
-{
-    WOLFSSL_RSA*    rsa = NULL;
-    WOLFSSL_BIGNUM* bn  = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
-
-    (void)f;
-    (void)data;
-
-    if (len < 0) {
-        WOLFSSL_MSG("Bad argument: length was less than 0");
-        return NULL;
-    }
-
-    bn = wolfSSL_BN_new();
-    if (bn == NULL) {
-        WOLFSSL_MSG("Error creating big number");
-        return NULL;
-    }
-
-    if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) {
-        WOLFSSL_MSG("Error using e value");
-        wolfSSL_BN_free(bn);
-        return NULL;
-    }
-
-    rsa = wolfSSL_RSA_new();
-    if (rsa == NULL) {
-        WOLFSSL_MSG("memory error");
-    }
-    else {
-        if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){
-            wolfSSL_RSA_free(rsa);
-            rsa = NULL;
-        }
-    }
-    wolfSSL_BN_free(bn);
-
-    return rsa;
-}
-
-
-/* return compliant with OpenSSL
- *   1 if success, 0 if error
- */
-int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn,
-                                void* cb)
-{
-    int ret = WOLFSSL_FAILURE;
-
-    (void)cb;
-    (void)bn;
-    (void)bits;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex");
-
-    if (rsa == NULL || rsa->internal == NULL) {
-        /* bit size checked during make key call */
-        WOLFSSL_MSG("bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-#ifdef WOLFSSL_KEY_GEN
-    {
-    #ifdef WOLFSSL_SMALL_STACK
-        WC_RNG* rng = NULL;
-    #else
-        WC_RNG  rng[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-        if (rng == NULL)
-            return WOLFSSL_FAILURE;
-    #endif
-
-        if (wc_InitRng(rng) < 0)
-            WOLFSSL_MSG("RNG init failed");
-        else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits,
-                    wolfSSL_BN_get_word(bn), rng) != MP_OKAY)
-            WOLFSSL_MSG("wc_MakeRsaKey failed");
-        else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS)
-            WOLFSSL_MSG("SetRsaExternal failed");
-        else {
-            rsa->inSet = 1;
-            ret = WOLFSSL_SUCCESS;
-        }
-
-        wc_FreeRng(rng);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
-    #endif
-    }
-#else
-    WOLFSSL_MSG("No Key Gen built in");
-#endif
-    return ret;
-}
-#endif /* NO_RSA */
-
-#ifndef NO_DSA
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
-{
-    int ret = WOLFSSL_FAILURE;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_generate_key");
-
-    if (dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (dsa->inSet == 0) {
-        WOLFSSL_MSG("No DSA internal set, do it");
-
-        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetDsaInternal failed");
-            return ret;
-        }
-    }
-
-#ifdef WOLFSSL_KEY_GEN
-    {
-        int initTmpRng = 0;
-        WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-        WC_RNG *tmpRNG = NULL;
-#else
-        WC_RNG tmpRNG[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-        if (tmpRNG == NULL)
-            return WOLFSSL_FATAL_ERROR;
-#endif
-        if (wc_InitRng(tmpRNG) == 0) {
-            rng = tmpRNG;
-            initTmpRng = 1;
-        }
-        else {
-            WOLFSSL_MSG("Bad RNG Init, trying global");
-            if (initGlobalRNG == 0)
-                WOLFSSL_MSG("Global RNG no Init");
-            else
-                rng = &globalRNG;
-        }
-
-        if (rng) {
-            if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY)
-                WOLFSSL_MSG("wc_MakeDsaKey failed");
-            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
-                WOLFSSL_MSG("SetDsaExternal failed");
-            else
-                ret = WOLFSSL_SUCCESS;
-        }
-
-        if (initTmpRng)
-            wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-    }
-#else /* WOLFSSL_KEY_GEN */
-    WOLFSSL_MSG("No Key Gen built in");
-#endif
-    return ret;
-}
-
-
-/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
- */
-WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed,
-        int seedLen, int* counterRet, unsigned long* hRet,
-        WOLFSSL_BN_CB cb, void* CBArg)
-{
-    WOLFSSL_DSA* dsa;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()");
-
-    (void)cb;
-    (void)CBArg;
-    dsa = wolfSSL_DSA_new();
-    if (dsa == NULL) {
-        return NULL;
-    }
-
-    if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen,
-                                  counterRet, hRet, NULL) != SSL_SUCCESS) {
-        wolfSSL_DSA_free(dsa);
-        return NULL;
-    }
-
-    return dsa;
-}
-
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
-                                       unsigned char* seed, int seedLen,
-                                       int* counterRet,
-                                       unsigned long* hRet, void* cb)
-{
-    int ret = WOLFSSL_FAILURE;
-
-    (void)bits;
-    (void)seed;
-    (void)seedLen;
-    (void)counterRet;
-    (void)hRet;
-    (void)cb;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex");
-
-    if (dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-#ifdef WOLFSSL_KEY_GEN
-    {
-        int initTmpRng = 0;
-        WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-        WC_RNG *tmpRNG = NULL;
-#else
-        WC_RNG tmpRNG[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-        if (tmpRNG == NULL)
-            return WOLFSSL_FATAL_ERROR;
-#endif
-        if (wc_InitRng(tmpRNG) == 0) {
-            rng = tmpRNG;
-            initTmpRng = 1;
-        }
-        else {
-            WOLFSSL_MSG("Bad RNG Init, trying global");
-            if (initGlobalRNG == 0)
-                WOLFSSL_MSG("Global RNG no Init");
-            else
-                rng = &globalRNG;
-        }
-
-        if (rng) {
-            if (wc_MakeDsaParameters(rng, bits,
-                                     (DsaKey*)dsa->internal) != MP_OKAY)
-                WOLFSSL_MSG("wc_MakeDsaParameters failed");
-            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
-                WOLFSSL_MSG("SetDsaExternal failed");
-            else
-                ret = WOLFSSL_SUCCESS;
-        }
-
-        if (initTmpRng)
-            wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-    }
-#else /* WOLFSSL_KEY_GEN */
-    WOLFSSL_MSG("No Key Gen built in");
-#endif
-
-    return ret;
-}
-
-/* return WOLFSSL_SUCCESS on success, < 0 otherwise */
-int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
-                       WOLFSSL_DSA* dsa)
-{
-    int     ret = WOLFSSL_FATAL_ERROR;
-    int     initTmpRng = 0;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
-
-    if (d == NULL || sigRet == NULL || dsa == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return ret;
-    }
-
-    if (dsa->inSet == 0)
-    {
-        WOLFSSL_MSG("No DSA internal set, do it");
-
-        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetDsaInternal failed");
-            return ret;
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return WOLFSSL_FATAL_ERROR;
-#endif
-
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-        if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
-            WOLFSSL_MSG("DsaSign failed");
-        else
-            ret = WOLFSSL_SUCCESS;
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-}
-
-
-int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
-                        WOLFSSL_DSA* dsa, int *dsacheck)
-{
-    int    ret = WOLFSSL_FATAL_ERROR;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
-
-    if (d == NULL || sig == NULL || dsa == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-    if (dsa->inSet == 0)
-    {
-        WOLFSSL_MSG("No DSA internal set, do it");
-
-        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetDsaInternal failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck);
-    if (ret != 0 || *dsacheck != 1) {
-        WOLFSSL_MSG("DsaVerify failed");
-        return ret;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_DSA */
-
-
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-
-#ifdef DEBUG_SIGN
-static void show(const char *title, const unsigned char *out, unsigned int outlen)
-{
-    const unsigned char *pt;
-    printf("%s[%d] = \n", title, (int)outlen);
-    outlen = outlen>100?100:outlen;
-    for (pt = out; pt < out + outlen;
-            printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++);
-    printf("\n");
-}
-#else
-#define show(a,b,c)
-#endif
-
-/* return SSL_SUCCES on ok, 0 otherwise */
-int wolfSSL_RSA_sign(int type, const unsigned char* m,
-                           unsigned int mLen, unsigned char* sigRet,
-                           unsigned int* sigLen, WOLFSSL_RSA* rsa)
-{
-    return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1);
-}
-
-int wolfSSL_RSA_sign_ex(int type, const unsigned char* m,
-                           unsigned int mLen, unsigned char* sigRet,
-                           unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag)
-{
-    word32  outLen;
-    word32  signSz;
-    int     initTmpRng = 0;
-    WC_RNG* rng        = NULL;
-    int     ret        = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG     = NULL;
-    byte*   encodedSig = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-    byte    encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_RSA_sign");
-
-    if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return 0;
-    }
-    show("Message to Sign", m, mLen);
-
-    switch (type) {
-    #ifdef WOLFSSL_MD2
-        case NID_md2:       type = MD2h;    break;
-    #endif
-    #ifndef NO_MD5
-        case NID_md5:       type = MD5h;    break;
-    #endif
-    #ifndef NO_SHA
-        case NID_sha1:      type = SHAh;    break;
-    #endif
-    #ifndef NO_SHA256
-        case NID_sha256:    type = SHA256h; break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case NID_sha384:    type = SHA384h; break;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        case NID_sha512:    type = SHA512h; break;
-    #endif
-        default:
-            WOLFSSL_MSG("This NID (md type) not configured or not implemented");
-            return 0;
-    }
-
-    if (rsa->inSet == 0)
-    {
-        WOLFSSL_MSG("No RSA internal set, do it");
-
-        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-
-    outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return 0;
-
-    encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
-                                                   DYNAMIC_TYPE_SIGNATURE);
-    if (encodedSig == NULL) {
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-        return 0;
-    }
-#endif
-
-    if (outLen == 0)
-        WOLFSSL_MSG("Bad RSA size");
-    else if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-
-        signSz = wc_EncodeSignature(encodedSig, m, mLen, type);
-        if (signSz == 0) {
-            WOLFSSL_MSG("Bad Encode Signature");
-        }
-        else {
-            show("Encoded Message", encodedSig, signSz);
-            if (flag != 0) {
-                ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen,
-                                (RsaKey*)rsa->internal, rng);
-                if (ret <= 0) {
-                    WOLFSSL_MSG("Bad Rsa Sign");
-                    ret = 0;
-                }
-                else {
-                    *sigLen = (unsigned int)ret;
-                    ret = SSL_SUCCESS;
-                    show("Signature", sigRet, *sigLen);
-                }
-            } else {
-                ret = SSL_SUCCESS;
-                XMEMCPY(sigRet, encodedSig, signSz);
-                *sigLen = signSz;
-            }
-        }
-
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG,     NULL, DYNAMIC_TYPE_RNG);
-    XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
-#endif
-
-    if (ret == WOLFSSL_SUCCESS)
-        WOLFSSL_MSG("wolfSSL_RSA_sign success");
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_sign failed");
-    }
-    return ret;
-}
-
-
-/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */
-int wolfSSL_RSA_verify(int type, const unsigned char* m,
-                               unsigned int mLen, const unsigned char* sig,
-                               unsigned int sigLen, WOLFSSL_RSA* rsa)
-{
-    int     ret;
-    unsigned char *sigRet ;
-    unsigned char *sigDec ;
-    unsigned int   len;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_verify");
-    if ((m == NULL) || (sig == NULL)) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (sigRet == NULL) {
-        WOLFSSL_MSG("Memory failure");
-        return WOLFSSL_FAILURE;
-    }
-    sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (sigDec == NULL) {
-        WOLFSSL_MSG("Memory failure");
-        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-    /* get non-encrypted signature to be compared with decrypted sugnature*/
-    ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0);
-    if (ret <= 0) {
-        WOLFSSL_MSG("Message Digest Error");
-        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-    show("Encoded Message", sigRet, len);
-    /* decrypt signature */
-    ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
-        (RsaKey*)rsa->internal);
-    if (ret <= 0) {
-        WOLFSSL_MSG("RSA Decrypt error");
-        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-    show("Decrypted Signature", sigDec, ret);
-
-    if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) {
-        WOLFSSL_MSG("wolfSSL_RSA_verify success");
-        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_SUCCESS;
-    }
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_verify failed");
-        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-}
-
-int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from,
-                          unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
-    int tlen = 0;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
-
-    if (rsa == NULL || rsa->internal == NULL || from == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return 0;
-    }
-
-    if (padding != RSA_PKCS1_PADDING) {
-        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding");
-        return 0;
-    }
-
-    if (rsa->inSet == 0)
-    {
-        WOLFSSL_MSG("No RSA internal set, do it");
-
-        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return 0;
-        }
-    }
-
-    /* size of 'to' buffer must be size of RSA key */
-    tlen = wc_RsaSSL_Verify(from, flen, to, wolfSSL_RSA_size(rsa),
-                            (RsaKey*)rsa->internal);
-    if (tlen <= 0)
-        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed");
-    else {
-        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success");
-    }
-    return tlen;
-}
-
-
-/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */
-int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
-{
-    int    err;
-    mp_int tmp;
-
-    WOLFSSL_MSG("wolfSSL_RsaGenAdd");
-
-    if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL ||
-                       rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
-        WOLFSSL_MSG("rsa no init error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (mp_init(&tmp) != MP_OKAY) {
-        WOLFSSL_MSG("mp_init error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp);
-    if (err != MP_OKAY) {
-        WOLFSSL_MSG("mp_sub_d error");
-    }
-    else
-        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
-                     (mp_int*)rsa->dmp1->internal);
-
-    if (err != MP_OKAY) {
-        WOLFSSL_MSG("mp_mod error");
-    }
-    else
-        err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp);
-    if (err != MP_OKAY) {
-        WOLFSSL_MSG("mp_sub_d error");
-    }
-    else
-        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
-                     (mp_int*)rsa->dmq1->internal);
-
-    mp_clear(&tmp);
-
-    if (err == MP_OKAY)
-        return WOLFSSL_SUCCESS;
-    else
-        return WOLFSSL_FATAL_ERROR;
-}
-#endif /* NO_RSA */
-
-int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
-{
-    WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
-
-    if (ctx != NULL) {
-        /* wc_HmacSetKey sets up ctx->hmac */
-        XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
-                             int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e)
-{
-    WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
-
-    /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */
-    (void)e;
-    return wolfSSL_HMAC_Init(ctx, key, keylen, type);
-}
-
-
-/* Deep copy of information from src to des structure
- *
- * des destination to copy information to
- * src structure to get infromation from
- *
- * Returns SSL_SUCCESS on success and SSL_FAILURE on error
- */
-int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src)
-{
-    void* heap = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
-
-    if (des == NULL || src == NULL) {
-        return SSL_FAILURE;
-    }
-
-#ifndef HAVE_FIPS
-    heap = src->hmac.heap;
-#endif
-
-    if (wc_HmacInit(&des->hmac, heap, 0) != 0) {
-        WOLFSSL_MSG("Error initializing HMAC");
-        return SSL_FAILURE;
-    }
-
-    des->type = src->type;
-
-    /* requires that hash structures have no dynamic parts to them */
-    switch (src->hmac.macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            XMEMCPY(&des->hmac.hash.md5, &src->hmac.hash.md5, sizeof(wc_Md5));
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            XMEMCPY(&des->hmac.hash.sha, &src->hmac.hash.sha, sizeof(wc_Sha));
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            XMEMCPY(&des->hmac.hash.sha224, &src->hmac.hash.sha224,
-                    sizeof(wc_Sha224));
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            XMEMCPY(&des->hmac.hash.sha256, &src->hmac.hash.sha256,
-                    sizeof(wc_Sha256));
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            XMEMCPY(&des->hmac.hash.sha384, &src->hmac.hash.sha384,
-                    sizeof(wc_Sha384));
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            XMEMCPY(&des->hmac.hash.sha512, &src->hmac.hash.sha512,
-                    sizeof(wc_Sha512));
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-        default:
-            WOLFSSL_MSG("Unknown or unsupported hash type");
-            return WOLFSSL_FAILURE;
-    }
-
-    XMEMCPY((byte*)des->hmac.ipad, (byte*)src->hmac.ipad, WC_HMAC_BLOCK_SIZE);
-    XMEMCPY((byte*)des->hmac.opad, (byte*)src->hmac.opad, WC_HMAC_BLOCK_SIZE);
-    XMEMCPY((byte*)des->hmac.innerHash, (byte*)src->hmac.innerHash,
-                                                            WC_MAX_DIGEST_SIZE);
-#ifndef HAVE_FIPS
-    des->hmac.heap    = heap;
-#endif
-    des->hmac.macType = src->hmac.macType;
-    des->hmac.innerHashKeyed = src->hmac.innerHashKeyed;
-    XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad,
-                                        WC_HMAC_BLOCK_SIZE);
-    XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad,
-                                        WC_HMAC_BLOCK_SIZE);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    XMEMCPY(&des->hmac.asyncDev, &src->hmac.asyncDev, sizeof(WC_ASYNC_DEV));
-    des->hmac.keyLen = src->hmac.keyLen;
-    #ifdef HAVE_CAVIUM
-        des->hmac.data = (byte*)XMALLOC(src->hmac.dataLen, des->hmac.heap,
-                DYNAMIC_TYPE_HMAC);
-        if (des->hmac.data == NULL) {
-            return BUFFER_E;
-        }
-        XMEMCPY(des->hmac.data, src->hmac.data, src->hmac.dataLen);
-        des->hmac.dataLen = src->hmac.dataLen;
-    #endif /* HAVE_CAVIUM */
-#endif /* WOLFSSL_ASYNC_CRYPT */
-        return WOLFSSL_SUCCESS;
-}
-
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-static int _HMAC_Init(Hmac* hmac, int type, void* heap)
-{
-    int ret = 0;
-
-    switch (type) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = wc_InitMd5(&hmac->hash.md5);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = wc_InitSha(&hmac->hash.sha);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            ret = wc_InitSha224(&hmac->hash.sha224);
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = wc_InitSha256(&hmac->hash.sha256);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = wc_InitSha384(&hmac->hash.sha384);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = wc_InitSha512(&hmac->hash.sha512);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256);
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_256:
-            ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_384:
-            ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_512:
-            ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-    #endif
-
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    (void)heap;
-
-    return ret;
-}
-
-#else
-    #define _HMAC_Init _InitHmac
-#endif
-
-
-int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
-                  const EVP_MD* type)
-{
-    int hmac_error = 0;
-    void* heap = NULL;
-
-    WOLFSSL_MSG("wolfSSL_HMAC_Init");
-
-    if (ctx == NULL) {
-        WOLFSSL_MSG("no ctx on init");
-        return WOLFSSL_FAILURE;
-    }
-
-#ifndef HAVE_FIPS
-    heap = ctx->hmac.heap;
-#endif
-
-    if (type) {
-        WOLFSSL_MSG("init has type");
-
-#ifndef NO_MD5
-        if (XSTRNCMP(type, "MD5", 3) == 0) {
-            WOLFSSL_MSG("md5 hmac");
-            ctx->type = WC_MD5;
-        }
-        else
-#endif
-#ifdef WOLFSSL_SHA224
-        if (XSTRNCMP(type, "SHA224", 6) == 0) {
-            WOLFSSL_MSG("sha224 hmac");
-            ctx->type = WC_SHA224;
-        }
-        else
-#endif
-#ifndef NO_SHA256
-        if (XSTRNCMP(type, "SHA256", 6) == 0) {
-            WOLFSSL_MSG("sha256 hmac");
-            ctx->type = WC_SHA256;
-        }
-        else
-#endif
-#ifdef WOLFSSL_SHA384
-        if (XSTRNCMP(type, "SHA384", 6) == 0) {
-            WOLFSSL_MSG("sha384 hmac");
-            ctx->type = WC_SHA384;
-        }
-        else
-#endif
-#ifdef WOLFSSL_SHA512
-        if (XSTRNCMP(type, "SHA512", 6) == 0) {
-            WOLFSSL_MSG("sha512 hmac");
-            ctx->type = WC_SHA512;
-        }
-        else
-#endif
-
-#ifndef NO_SHA
-        /* has to be last since would pick or 256, 384, or 512 too */
-        if (XSTRNCMP(type, "SHA", 3) == 0) {
-            WOLFSSL_MSG("sha hmac");
-            ctx->type = WC_SHA;
-        }
-        else
-#endif
-        {
-            WOLFSSL_MSG("bad init type");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    if (key && keylen) {
-        WOLFSSL_MSG("keying hmac");
-
-        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
-            hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
-                                       (word32)keylen);
-            if (hmac_error < 0){
-                wc_HmacFree(&ctx->hmac);
-                return WOLFSSL_FAILURE;
-            }
-            XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
-                                        WC_HMAC_BLOCK_SIZE);
-            XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
-                                        WC_HMAC_BLOCK_SIZE);
-        }
-        /* OpenSSL compat, no error */
-    } else if(ctx->type >= 0) { /* MD5 == 0 */
-        WOLFSSL_MSG("recover hmac");
-        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
-            ctx->hmac.macType = (byte)ctx->type;
-            ctx->hmac.innerHashKeyed = 0;
-            XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
-                                       WC_HMAC_BLOCK_SIZE);
-            XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
-                                       WC_HMAC_BLOCK_SIZE);
-            if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap))
-                    !=0) {
-               return hmac_error;
-            }
-        }
-    }
-
-    (void)hmac_error;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
-                    int len)
-{
-    int hmac_error = 0;
-
-    WOLFSSL_MSG("wolfSSL_HMAC_Update");
-
-    if (ctx == NULL) {
-        WOLFSSL_MSG("no ctx");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (data) {
-        WOLFSSL_MSG("updating hmac");
-        hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
-        if (hmac_error < 0){
-            WOLFSSL_MSG("hmac update error");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
-                   unsigned int* len)
-{
-    int hmac_error;
-
-    WOLFSSL_MSG("wolfSSL_HMAC_Final");
-
-	/* "len" parameter is optional. */
-    if (ctx == NULL || hash == NULL) {
-        WOLFSSL_MSG("invalid parameter");
-        return WOLFSSL_FAILURE;
-    }
-
-    WOLFSSL_MSG("final hmac");
-    hmac_error = wc_HmacFinal(&ctx->hmac, hash);
-    if (hmac_error < 0){
-        WOLFSSL_MSG("final hmac error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (len) {
-        WOLFSSL_MSG("setting output len");
-        switch (ctx->type) {
-            #ifndef NO_MD5
-            case WC_MD5:
-                *len = WC_MD5_DIGEST_SIZE;
-                break;
-            #endif
-
-            #ifndef NO_SHA
-            case WC_SHA:
-                *len = WC_SHA_DIGEST_SIZE;
-                break;
-            #endif
-
-            #ifdef WOLFSSL_SHA224
-            case WC_SHA224:
-                *len = WC_SHA224_DIGEST_SIZE;
-                break;
-            #endif
-
-            #ifndef NO_SHA256
-            case WC_SHA256:
-                *len = WC_SHA256_DIGEST_SIZE;
-                break;
-            #endif
-
-            #ifdef WOLFSSL_SHA384
-            case WC_SHA384:
-                *len = WC_SHA384_DIGEST_SIZE;
-                break;
-            #endif
-
-            #ifdef WOLFSSL_SHA512
-            case WC_SHA512:
-                *len = WC_SHA512_DIGEST_SIZE;
-                break;
-            #endif
-
-            default:
-                WOLFSSL_MSG("bad hmac type");
-                return WOLFSSL_FAILURE;
-        }
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
-{
-    WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
-
-    if (ctx)
-        wc_HmacFree(&ctx->hmac);
-
-    return SSL_SUCCESS;
-}
-
-
-const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id)
-{
-    WOLFSSL_MSG("wolfSSL_get_digestbynid");
-
-    switch(id) {
-#ifndef NO_MD5
-        case NID_md5:
-            return wolfSSL_EVP_md5();
-#endif
-#ifndef NO_SHA
-        case NID_sha1:
-            return wolfSSL_EVP_sha1();
-#endif
-        default:
-            WOLFSSL_MSG("Bad digest id value");
-    }
-
-    return NULL;
-}
-
-
-#ifndef NO_RSA
-WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key)
-{
-    WOLFSSL_RSA* local;
-
-    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA");
-
-    if (key == NULL) {
-        return NULL;
-    }
-
-    local = wolfSSL_RSA_new();
-    if (local == NULL) {
-        WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure");
-        return NULL;
-    }
-
-    if (key->type == EVP_PKEY_RSA) {
-        if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr,
-                    key->pkey_sz) != SSL_SUCCESS) {
-            /* now try public key */
-            if (wolfSSL_RSA_LoadDer_ex(local,
-                        (const unsigned char*)key->pkey.ptr, key->pkey_sz,
-                        WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
-                wolfSSL_RSA_free(local);
-                local = NULL;
-            }
-        }
-    }
-    else {
-        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key");
-        wolfSSL_RSA_free(local);
-        local = NULL;
-    }
-    return local;
-}
-
-
-/* with set1 functions the pkey struct does not own the RSA structure
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
-int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key)
-{
-    if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA");
-    if (pkey->rsa != NULL && pkey->ownRsa == 1) {
-        wolfSSL_RSA_free(pkey->rsa);
-    }
-    pkey->rsa    = key;
-    pkey->ownRsa = 0; /* pkey does not own RSA */
-    pkey->type = EVP_PKEY_RSA;
-#ifdef WC_RSA_BLINDING
-    if (key->ownRng == 0) {
-        if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) {
-            WOLFSSL_MSG("Error setting RSA rng");
-            return SSL_FAILURE;
-        }
-    }
-#endif
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_RSA */
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key)
-{
-    (void)key;
-    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented");
-    WOLFSSL_STUB("EVP_PKEY_get1_DSA");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key)
-{
-    (void)key;
-    WOLFSSL_STUB("EVP_PKEY_get1_EC_KEY");
-    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented");
-
-    return NULL;
-}
-#endif
-
-void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx)
-{
-    WOLFSSL_MSG("wolfSSL_EVP_X_STATE");
-
-    if (ctx) {
-        switch (ctx->cipherType) {
-            case ARC4_TYPE:
-                WOLFSSL_MSG("returning arc4 state");
-                return (void*)&ctx->cipher.arc4.x;
-
-            default:
-                WOLFSSL_MSG("bad x state type");
-                return 0;
-        }
-    }
-
-    return NULL;
-}
-
-
-int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx)
-{
-    WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN");
-
-    if (ctx) {
-        switch (ctx->cipherType) {
-            case ARC4_TYPE:
-                WOLFSSL_MSG("returning arc4 state size");
-                return sizeof(Arc4);
-
-            default:
-                WOLFSSL_MSG("bad x state type");
-                return 0;
-        }
-    }
-
-    return 0;
-}
-
-
-#ifndef NO_DES3
-
-void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
-                            unsigned char* iv, int len)
-{
-    (void)len;
-
-    WOLFSSL_MSG("wolfSSL_3des_iv");
-
-    if (ctx == NULL || iv == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-        return;
-    }
-
-    if (doset)
-        wc_Des3_SetIV(&ctx->cipher.des3, iv);  /* OpenSSL compat, no ret */
-    else
-        XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
-}
-
-#endif /* NO_DES3 */
-
-
-#ifndef NO_AES
-
-void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
-                      unsigned char* iv, int len)
-{
-    (void)len;
-
-    WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
-
-    if (ctx == NULL || iv == NULL) {
-        WOLFSSL_MSG("Bad function argument");
-        return;
-    }
-
-    if (doset)
-       (void)wc_AesSetIV(&ctx->cipher.aes, iv);  /* OpenSSL compat, no ret */
-    else
-        XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
-}
-
-#endif /* NO_AES */
-
-#ifndef NO_WOLFSSL_STUB
-const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void)
-{
-    WOLFSSL_MSG("wolfSSL_ripemd160");
-    WOLFSSL_STUB("EVP_ripemd160");
-    return NULL;
-}
-#endif
-
-int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type)
-{
-    WOLFSSL_MSG("wolfSSL_EVP_MD_size");
-
-    if (type == NULL) {
-        WOLFSSL_MSG("No md type arg");
-        return BAD_FUNC_ARG;
-    }
-
-    if (XSTRNCMP(type, "SHA256", 6) == 0) {
-        return WC_SHA256_DIGEST_SIZE;
-    }
-#ifndef NO_MD5
-    else if (XSTRNCMP(type, "MD5", 3) == 0) {
-        return WC_MD5_DIGEST_SIZE;
-    }
-#endif
-#ifdef WOLFSSL_SHA224
-    else if (XSTRNCMP(type, "SHA224", 6) == 0) {
-        return WC_SHA224_DIGEST_SIZE;
-    }
-#endif
-#ifdef WOLFSSL_SHA384
-    else if (XSTRNCMP(type, "SHA384", 6) == 0) {
-        return WC_SHA384_DIGEST_SIZE;
-    }
-#endif
-#ifdef WOLFSSL_SHA512
-    else if (XSTRNCMP(type, "SHA512", 6) == 0) {
-        return WC_SHA512_DIGEST_SIZE;
-    }
-#endif
-#ifndef NO_SHA
-    /* has to be last since would pick or 256, 384, or 512 too */
-    else if (XSTRNCMP(type, "SHA", 3) == 0) {
-        return WC_SHA_DIGEST_SIZE;
-    }
-#endif
-
-    return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
-{
-    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length");
-
-    switch (ctx->cipherType) {
-
-#ifdef HAVE_AES_CBC
-        case AES_128_CBC_TYPE :
-        case AES_192_CBC_TYPE :
-        case AES_256_CBC_TYPE :
-            WOLFSSL_MSG("AES CBC");
-            return AES_BLOCK_SIZE;
-#endif
-#ifdef WOLFSSL_AES_COUNTER
-        case AES_128_CTR_TYPE :
-        case AES_192_CTR_TYPE :
-        case AES_256_CTR_TYPE :
-            WOLFSSL_MSG("AES CTR");
-            return AES_BLOCK_SIZE;
-#endif
-#ifndef NO_DES3
-        case DES_CBC_TYPE :
-            WOLFSSL_MSG("DES CBC");
-            return DES_BLOCK_SIZE;
-
-        case DES_EDE3_CBC_TYPE :
-            WOLFSSL_MSG("DES EDE3 CBC");
-            return DES_BLOCK_SIZE;
-#endif
-#ifdef HAVE_IDEA
-        case IDEA_CBC_TYPE :
-            WOLFSSL_MSG("IDEA CBC");
-            return IDEA_BLOCK_SIZE;
-#endif
-#ifndef NO_RC4
-        case ARC4_TYPE :
-            WOLFSSL_MSG("ARC4");
-            return 0;
-#endif
-
-        case NULL_CIPHER_TYPE :
-            WOLFSSL_MSG("NULL");
-            return 0;
-
-        default: {
-            WOLFSSL_MSG("bad type");
-        }
-    }
-    return 0;
-}
-
-int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher)
-{
-    const char *name = (const char *)cipher;
-    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length");
-
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-    if (XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-    #ifdef WOLFSSL_AES_192
-    if (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-    #ifdef WOLFSSL_AES_256
-    if (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-#ifdef WOLFSSL_AES_COUNTER
-    #ifdef WOLFSSL_AES_128
-    if (XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-    #ifdef WOLFSSL_AES_192
-    if (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-    #ifdef WOLFSSL_AES_256
-    if (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)
-        return AES_BLOCK_SIZE;
-    #endif
-#endif
-#endif
-
-#ifndef NO_DES3
-    if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) ||
-           (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) {
-        return DES_BLOCK_SIZE;
-    }
-#endif
-
-#ifdef HAVE_IDEA
-    if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0)
-        return IDEA_BLOCK_SIZE;
-#endif
-
-    (void)name;
-
-    return 0;
-}
-
-/* Free the dynamically allocated data.
- *
- * p  Pointer to dynamically allocated memory.
- */
-void wolfSSL_OPENSSL_free(void* p)
-{
-    WOLFSSL_MSG("wolfSSL_OPENSSL_free");
-
-    XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
-void *wolfSSL_OPENSSL_malloc(size_t a)
-{
-  return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
-#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)
-
-static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
-                         unsigned char* passwd, int passwdSz, byte **cipherInfo)
-{
-    int ret, paddingSz;
-    word32 idx, cipherInfoSz;
-#ifdef WOLFSSL_SMALL_STACK
-    EncryptedInfo* info = NULL;
-#else
-    EncryptedInfo  info[1];
-#endif
-
-    WOLFSSL_ENTER("EncryptDerKey");
-
-    if (der == NULL || derSz == NULL || cipher == NULL ||
-        passwd == NULL || cipherInfo == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
-                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
-    if (info == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        return WOLFSSL_FAILURE;
-    }
-#endif
-
-    XMEMSET(info, 0, sizeof(EncryptedInfo));
-
-    /* set the cipher name on info */
-    XSTRNCPY(info->name, cipher, NAME_SZ-1);
-    info->name[NAME_SZ-1] = '\0'; /* null term */
-
-    ret = wc_EncryptedInfoGet(info, info->name);
-    if (ret != 0) {
-        WOLFSSL_MSG("unsupported cipher");
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-    #endif
-        return WOLFSSL_FAILURE;
-    }
-
-    /* Generate a random salt */
-    if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("generate iv failed");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-        return WOLFSSL_FAILURE;
-    }
-
-    /* add the padding before encryption */
-    paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz);
-    if (paddingSz == 0)
-        paddingSz = info->ivSz;
-    XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz);
-    (*derSz) += paddingSz;
-
-    /* encrypt buffer */
-    if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) {
-        WOLFSSL_MSG("encrypt key failed");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-        return WOLFSSL_FAILURE;
-    }
-
-    /* create cipher info : 'cipher_name,Salt(hex)' */
-    cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2);
-    *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL,
-                                DYNAMIC_TYPE_STRING);
-    if (*cipherInfo == NULL) {
-        WOLFSSL_MSG("malloc failed");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-        return WOLFSSL_FAILURE;
-    }
-    XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz);
-    XSTRNCAT((char*)*cipherInfo, ",", 1);
-
-    idx = (word32)XSTRLEN((char*)*cipherInfo);
-    cipherInfoSz -= idx;
-    ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-    if (ret != 0) {
-        WOLFSSL_MSG("Base16_Encode failed");
-        XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */
-
-#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
-/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO
- *
- * bio    the WOLFSSL_BIO to write to
- * key    the WOLFSSL_RSA key to write out
- * cipher cipher used
- * passwd password string if used
- * len    length of password string
- * cb     password callback to use
- * arg    null terminated string for passphrase
- */
-int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key,
-                                        const WOLFSSL_EVP_CIPHER* cipher,
-                                        unsigned char* passwd, int len,
-                                        pem_password_cb* cb, void* arg)
-{
-    int ret;
-    WOLFSSL_EVP_PKEY* pkey;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
-
-
-    pkey = wolfSSL_PKEY_new_ex(bio->heap);
-    if (pkey == NULL) {
-        WOLFSSL_MSG("wolfSSL_PKEY_new_ex failed");
-        return SSL_FAILURE;
-    }
-
-    pkey->type   = EVP_PKEY_RSA;
-    pkey->rsa    = key;
-    pkey->ownRsa = 0;
-#ifdef WOLFSSL_KEY_GEN
-    /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */
-    {
-        int derMax;
-        int derSz;
-        byte* derBuf;
-
-        /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
-         *  informations
-         */
-        derMax = 5 * wolfSSL_RSA_size(key) + AES_BLOCK_SIZE;
-
-        derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (derBuf == NULL) {
-            WOLFSSL_MSG("malloc failed");
-            wolfSSL_EVP_PKEY_free(pkey);
-            return SSL_FAILURE;
-        }
-
-        /* Key to DER */
-        derSz = wc_RsaKeyToDer((RsaKey*)key->internal, derBuf, derMax);
-        if (derSz < 0) {
-            WOLFSSL_MSG("wc_RsaKeyToDer failed");
-            XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            wolfSSL_EVP_PKEY_free(pkey);
-            return SSL_FAILURE;
-        }
-
-        pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
-                DYNAMIC_TYPE_TMP_BUFFER);
-        if (pkey->pkey.ptr == NULL) {
-            WOLFSSL_MSG("key malloc failed");
-            XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            wolfSSL_EVP_PKEY_free(pkey);
-            return SSL_FAILURE;
-        }
-        pkey->pkey_sz = derSz;
-        XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
-        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#endif
-
-    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
-                                        cb, arg);
-
-    wolfSSL_EVP_PKEY_free(pkey);
-
-    return ret;
-}
-
-
-int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
-                                        const WOLFSSL_EVP_CIPHER* cipher,
-                                        unsigned char* passwd, int len,
-                                        pem_password_cb* cb, void* arg)
-{
-    byte* keyDer;
-    int pemSz;
-    int type;
-    int ret;
-    byte* tmp;
-
-    (void)cipher;
-    (void)passwd;
-    (void)len;
-    (void)cb;
-    (void)arg;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
-
-    if (bio == NULL || key == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    keyDer = (byte*)key->pkey.ptr;
-
-    switch (key->type) {
-        case EVP_PKEY_RSA:
-            type = PRIVATEKEY_TYPE;
-            break;
-
-#ifndef NO_DSA
-        case EVP_PKEY_DSA:
-            type = DSA_PRIVATEKEY_TYPE;
-            break;
-#endif
-
-        case EVP_PKEY_EC:
-            type = ECC_PRIVATEKEY_TYPE;
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown Key type!");
-            type = PRIVATEKEY_TYPE;
-    }
-
-    pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type);
-    if (pemSz < 0) {
-        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
-        return WOLFSSL_FAILURE;
-    }
-    tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
-    if (tmp == NULL) {
-        return MEMORY_E;
-    }
-
-    ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
-                                NULL, type);
-    if (ret < 0) {
-        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
-        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
-        return SSL_FAILURE;
-    }
-
-    ret = wolfSSL_BIO_write(bio, tmp, pemSz);
-    XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
-    if (ret != pemSz) {
-        WOLFSSL_MSG("Unable to write full PEM to BIO");
-        return SSL_FAILURE;
-    }
-
-    return SSL_SUCCESS;
-}
-#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */
-
-#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
-    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
-                                        unsigned char* passwd, int passwdSz,
-                                        unsigned char **pem, int *plen)
-{
-    byte *derBuf, *tmp, *cipherInfo = NULL;
-    int  der_max_len = 0, derSz = 0;
-    const int type = PRIVATEKEY_TYPE;
-    const char* header = NULL;
-    const char* footer = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
-
-    if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
-        return WOLFSSL_FAILURE;
-
-    if (rsa->inSet == 0) {
-        WOLFSSL_MSG("No RSA internal set, do it");
-
-        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
-     *  informations
-     */
-    der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE;
-
-    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* Key to DER */
-    derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len);
-    if (derSz < 0) {
-        WOLFSSL_MSG("wc_RsaKeyToDer failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* encrypt DER buffer if required */
-    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
-        int ret;
-
-        ret = EncryptDerKey(derBuf, &derSz, cipher,
-                            passwd, passwdSz, &cipherInfo);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("EncryptDerKey failed");
-            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-            return ret;
-        }
-
-        /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
-    }
-    else {
-        /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1;
-    }
-
-    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
-    if (tmp == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* DER to PEM */
-    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
-    if (*plen <= 0) {
-        WOLFSSL_MSG("wc_DerToPemEx failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-    if (cipherInfo != NULL)
-        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-
-    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
-    if (*pem == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XMEMSET(*pem, 0, (*plen)+1);
-
-    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
-        WOLFSSL_MSG("XMEMCPY failed");
-        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa,
-                                    const EVP_CIPHER *enc,
-                                    unsigned char *kstr, int klen,
-                                    pem_password_cb *cb, void *u)
-{
-    byte *pem;
-    int  plen, ret;
-
-    (void)cb;
-    (void)u;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey");
-
-    if (fp == NULL || rsa == NULL || rsa->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen);
-    if (ret != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = (int)XFWRITE(pem, plen, 1, fp);
-    if (ret != 1) {
-        WOLFSSL_MSG("RSA private key file write failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_FILESYSTEM */
-#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */
-
-
-#ifdef HAVE_ECC
-
-/* EC_POINT Openssl -> WolfSSL */
-static int SetECPointInternal(WOLFSSL_EC_POINT *p)
-{
-    ecc_point* point;
-    WOLFSSL_ENTER("SetECPointInternal");
-
-    if (p == NULL || p->internal == NULL) {
-        WOLFSSL_MSG("ECPoint NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    point = (ecc_point*)p->internal;
-
-    if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point X error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point Y error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point Z error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    p->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_ECC */
-#endif /* OPENSSL_EXTRA */
-
-#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA_X509_SMALL)
-
-/* EC_POINT WolfSSL -> OpenSSL */
-static int SetECPointExternal(WOLFSSL_EC_POINT *p)
-{
-    ecc_point* point;
-
-    WOLFSSL_ENTER("SetECPointExternal");
-
-    if (p == NULL || p->internal == NULL) {
-        WOLFSSL_MSG("ECPoint NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    point = (ecc_point*)p->internal;
-
-    if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point X error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point Y error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("ecc point Z error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    p->exSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* EC_KEY wolfSSL -> OpenSSL */
-static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
-{
-    ecc_key* key;
-
-    WOLFSSL_ENTER("SetECKeyExternal");
-
-    if (eckey == NULL || eckey->internal == NULL) {
-        WOLFSSL_MSG("ec key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (ecc_key*)eckey->internal;
-
-    /* set group (OID, nid and idx) */
-    eckey->group->curve_oid = ecc_sets[key->idx].oidSum;
-    eckey->group->curve_nid = ecc_sets[key->idx].id;
-    eckey->group->curve_idx = key->idx;
-
-    if (eckey->pub_key->internal != NULL) {
-        /* set the internal public key */
-        if (wc_ecc_copy_point(&key->pubkey,
-                             (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
-            WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* set the external pubkey (point) */
-        if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    /* set the external privkey */
-    if (key->type == ECC_PRIVATEKEY) {
-        if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("ec priv key error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    eckey->exSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_ECC && OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
-#ifdef HAVE_ECC
-/* EC_KEY Openssl -> WolfSSL */
-static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
-{
-    ecc_key* key;
-
-    WOLFSSL_ENTER("SetECKeyInternal");
-
-    if (eckey == NULL || eckey->internal == NULL) {
-        WOLFSSL_MSG("ec key NULL error");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key = (ecc_key*)eckey->internal;
-
-    /* validate group */
-    if ((eckey->group->curve_idx < 0) ||
-        (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
-        WOLFSSL_MSG("invalid curve idx");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    /* set group (idx of curve and corresponding domain parameters) */
-    key->idx = eckey->group->curve_idx;
-    key->dp = &ecc_sets[key->idx];
-
-    /* set pubkey (point) */
-    if (eckey->pub_key != NULL) {
-        if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("ec key pub error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* public key */
-        key->type = ECC_PUBLICKEY;
-    }
-
-    /* set privkey */
-    if (eckey->priv_key != NULL) {
-        if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("ec key priv error");
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-        /* private key */
-        key->type = ECC_PRIVATEKEY;
-    }
-
-    eckey->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-
-WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
-
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
-        return NULL;
-    }
-
-    return key->pub_key;
-}
-
-const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
-
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
-        return NULL;
-    }
-
-    return key->group;
-}
-
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
-                                   const WOLFSSL_BIGNUM *priv_key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
-
-    if (key == NULL || priv_key == NULL) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* free key if previously set */
-    if (key->priv_key != NULL)
-        wolfSSL_BN_free(key->priv_key);
-
-    key->priv_key = wolfSSL_BN_dup(priv_key);
-    if (key->priv_key == NULL) {
-        WOLFSSL_MSG("key ecc priv key NULL");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetECKeyInternal failed");
-        wolfSSL_BN_free(key->priv_key);
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
-
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
-        return NULL;
-    }
-
-    return key->priv_key;
-}
-
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
-{
-    WOLFSSL_EC_KEY *key;
-    int x;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
-
-    key = wolfSSL_EC_KEY_new();
-    if (key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
-        return NULL;
-    }
-
-    /* set the nid of the curve */
-    key->group->curve_nid = nid;
-
-    /* search and set the corresponding internal curve idx */
-    for (x = 0; ecc_sets[x].size != 0; x++)
-        if (ecc_sets[x].id == key->group->curve_nid) {
-            key->group->curve_idx = x;
-            key->group->curve_oid = ecc_sets[x].oidSum;
-            break;
-        }
-
-    return key;
-}
-
-#endif /* HAVE_ECC */
-#endif /* OPENSSL_EXTRA */
-
-#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key)
-{
-    if (key) {
-        key->group    = NULL;
-        key->pub_key  = NULL;
-        key->priv_key = NULL;
-        key->internal = NULL;
-        key->inSet    = 0;
-        key->exSet    = 0;
-    }
-}
-
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
-{
-    WOLFSSL_EC_KEY *external;
-    ecc_key* key;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
-
-    external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL,
-                                        DYNAMIC_TYPE_ECC);
-    if (external == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
-        return NULL;
-    }
-    XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY));
-
-    InitwolfSSL_ECKey(external);
-
-    external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
-                                           DYNAMIC_TYPE_ECC);
-    if (external->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
-        wolfSSL_EC_KEY_free(external);
-        return NULL;
-    }
-    XMEMSET(external->internal, 0, sizeof(ecc_key));
-
-    wc_ecc_init((ecc_key*)external->internal);
-
-    /* public key */
-    external->pub_key = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT),
-                                                   NULL, DYNAMIC_TYPE_ECC);
-    if (external->pub_key == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_POINT failure");
-        wolfSSL_EC_KEY_free(external);
-        return NULL;
-    }
-    XMEMSET(external->pub_key, 0, sizeof(WOLFSSL_EC_POINT));
-
-    key = (ecc_key*)external->internal;
-    external->pub_key->internal = wc_ecc_new_point();
-    if (wc_ecc_copy_point((ecc_point*)&key->pubkey,
-                (ecc_point*)external->pub_key->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_copy_point failure");
-        wolfSSL_EC_KEY_free(external);
-        return NULL;
-    }
-
-    /* curve group */
-    external->group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
-                                                 DYNAMIC_TYPE_ECC);
-    if (external->group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
-        wolfSSL_EC_KEY_free(external);
-        return NULL;
-    }
-    XMEMSET(external->group, 0, sizeof(WOLFSSL_EC_GROUP));
-
-    /* private key */
-    external->priv_key = wolfSSL_BN_new();
-    if (external->priv_key == NULL) {
-        WOLFSSL_MSG("wolfSSL_BN_new failure");
-        wolfSSL_EC_KEY_free(external);
-        return NULL;
-    }
-
-    return external;
-}
-
-void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
-
-    if (key != NULL) {
-        if (key->internal != NULL) {
-            wc_ecc_free((ecc_key*)key->internal);
-            XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC);
-        }
-        wolfSSL_BN_free(key->priv_key);
-        wolfSSL_EC_POINT_free(key->pub_key);
-        wolfSSL_EC_GROUP_free(key->group);
-        InitwolfSSL_ECKey(key); /* set back to NULLs for safety */
-
-        XFREE(key, NULL, DYNAMIC_TYPE_ECC);
-        key = NULL;
-    }
-}
-#endif /* HAVE_ECC && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
-
-#ifdef OPENSSL_EXTRA
-#ifdef HAVE_ECC
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
-{
-    (void)key;
-    (void)group;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
-    WOLFSSL_STUB("EC_KEY_set_group");
-
-    return -1;
-}
-#endif
-
-int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
-{
-    int     initTmpRng = 0;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
-
-    if (key == NULL || key->internal == NULL ||
-        key->group == NULL || key->group->curve_idx < 0) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
-        return 0;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return 0;
-#endif
-
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-        return 0;
-    }
-
-    if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal,
-                                        key->group->curve_nid) != MP_OKAY) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-        return 0;
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
-        return 0;
-    }
-
-    return 1;
-}
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
-{
-    (void)key;
-    (void)asn1_flag;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
-    WOLFSSL_STUB("EC_KEY_set_asn1_flag");
-}
-#endif
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
-                                  const WOLFSSL_EC_POINT *pub)
-{
-    ecc_point *pub_p, *key_p;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
-
-    if (key == NULL || key->internal == NULL ||
-        pub == NULL || pub->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (key->inSet == 0) {
-        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    if (pub->inSet == 0) {
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    pub_p = (ecc_point*)pub->internal;
-    key_p = (ecc_point*)key->pub_key->internal;
-
-    /* create new point if required */
-    if (key_p == NULL)
-        key_p = wc_ecc_new_point();
-
-    if (key_p == NULL) {
-        WOLFSSL_MSG("key ecc point NULL");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
-        WOLFSSL_MSG("ecc_copy_point failure");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetECKeyInternal failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    wolfSSL_EC_POINT_dump("pub", pub);
-    wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
-
-    return WOLFSSL_SUCCESS;
-}
-/* End EC_KEY */
-
-void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
-{
-#if defined(DEBUG_WOLFSSL)
-    char *num;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
-
-    if (p == NULL) {
-        printf("%s = NULL", msg);
-        return;
-    }
-
-    printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet);
-    num = wolfSSL_BN_bn2hex(p->X);
-    printf("\tX = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
-    num = wolfSSL_BN_bn2hex(p->Y);
-    printf("\tY = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
-    num = wolfSSL_BN_bn2hex(p->Z);
-    printf("\tZ = %s\n", num);
-    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
-#else
-    (void)msg;
-    (void)p;
-#endif
-}
-
-/* Start EC_GROUP */
-
-/* return code compliant with OpenSSL :
- *   0 if equal, 1 if not and -1 in case of error
- */
-int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
-                         WOLFSSL_BN_CTX *ctx)
-{
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
-
-    if (a == NULL || b == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    /* ok */
-    if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid))
-        return 0;
-
-    /* ko */
-    return 1;
-}
-
-#endif /* HAVE_ECC */
-#endif /* OPENSSL_EXTRA */
-
-#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
-
-    XFREE(group, NULL, DYNAMIC_TYPE_ECC);
-    group = NULL;
-}
-#endif
-
-#ifdef OPENSSL_EXTRA
-#ifdef HAVE_ECC
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
-{
-    (void)group;
-    (void)flag;
-
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
-    WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
-}
-#endif
-
-WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
-{
-    WOLFSSL_EC_GROUP *g;
-    int x;
-
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
-
-    /* curve group */
-    g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
-                                    DYNAMIC_TYPE_ECC);
-    if (g == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
-        return NULL;
-    }
-    XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP));
-
-    /* set the nid of the curve */
-    g->curve_nid = nid;
-
-    /* search and set the corresponding internal curve idx */
-    for (x = 0; ecc_sets[x].size != 0; x++)
-        if (ecc_sets[x].id == g->curve_nid) {
-            g->curve_idx = x;
-            g->curve_oid = ecc_sets[x].oidSum;
-            break;
-        }
-
-    return g;
-}
-
-/* return code compliant with OpenSSL :
- *   the curve nid if success, 0 if error
- */
-int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
-
-    if (group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    return group->curve_nid;
-}
-
-/* return code compliant with OpenSSL :
- *   the degree of the curve if success, 0 if error
- */
-int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
-
-    if (group == NULL || group->curve_idx < 0) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    switch(group->curve_nid) {
-        case NID_secp112r1:
-        case NID_secp112r2:
-            return 112;
-        case NID_secp128r1:
-        case NID_secp128r2:
-            return 128;
-        case NID_secp160k1:
-        case NID_secp160r1:
-        case NID_secp160r2:
-        case NID_brainpoolP160r1:
-            return 160;
-        case NID_secp192k1:
-        case NID_brainpoolP192r1:
-        case NID_X9_62_prime192v1:
-            return 192;
-        case NID_secp224k1:
-        case NID_secp224r1:
-        case NID_brainpoolP224r1:
-            return 224;
-        case NID_secp256k1:
-        case NID_brainpoolP256r1:
-        case NID_X9_62_prime256v1:
-            return 256;
-        case NID_brainpoolP320r1:
-            return 320;
-        case NID_secp384r1:
-        case NID_brainpoolP384r1:
-            return 384;
-        case NID_secp521r1:
-        case NID_brainpoolP512r1:
-            return 521;
-        default:
-            return WOLFSSL_FAILURE;
-    }
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
-                               WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
-{
-    (void)ctx;
-
-    if (group == NULL || order == NULL || order->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_init((mp_int*)order->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (mp_read_radix((mp_int*)order->internal,
-                  ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) {
-        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
-        mp_clear((mp_int*)order->internal);
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-/* End EC_GROUP */
-
-/* Start EC_POINT */
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
-                        const WOLFSSL_EC_POINT *p,
-                        unsigned char *out, unsigned int *len)
-{
-    int err;
-
-    WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
-
-    if (group == NULL || p == NULL || len == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (p->inSet == 0) {
-        WOLFSSL_MSG("No ECPoint internal set, do it");
-
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    if (out != NULL) {
-        wolfSSL_EC_POINT_dump("i2d p", p);
-    }
-
-    err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
-                                  out, len);
-    if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
-                        const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
-{
-    WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
-
-    if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wc_ecc_import_point_der(in, len, group->curve_idx,
-                                (ecc_point*)p->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_import_point_der failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (p->exSet == 0) {
-        WOLFSSL_MSG("No ECPoint external set, do it");
-
-        if (SetECPointExternal(p) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointExternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    wolfSSL_EC_POINT_dump("d2i p", p);
-
-    return WOLFSSL_SUCCESS;
-}
-
-WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
-{
-    WOLFSSL_EC_POINT *p;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
-
-    if (group == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
-        return NULL;
-    }
-
-    p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
-                                    DYNAMIC_TYPE_ECC);
-    if (p == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
-        return NULL;
-    }
-    XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT));
-
-    p->internal = wc_ecc_new_point();
-    if (p->internal == NULL) {
-        WOLFSSL_MSG("ecc_new_point failure");
-        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
-        return NULL;
-    }
-
-    return p;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
-                                                const WOLFSSL_EC_POINT *point,
-                                                WOLFSSL_BIGNUM *x,
-                                                WOLFSSL_BIGNUM *y,
-                                                WOLFSSL_BN_CTX *ctx)
-{
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
-
-    if (group == NULL || point == NULL || point->internal == NULL ||
-        x == NULL || y == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (point->inSet == 0) {
-        WOLFSSL_MSG("No ECPoint internal set, do it");
-
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    BN_copy(x, point->X);
-    BN_copy(y, point->Y);
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifndef WOLFSSL_ATECC508A
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
-                         const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q,
-                         const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
-{
-    mp_int a, prime;
-    int ret;
-
-    (void)ctx;
-    (void)n;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
-
-    if (group == NULL || r == NULL || r->internal == NULL ||
-        q == NULL || q->internal == NULL || m == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (q->inSet == 0) {
-        WOLFSSL_MSG("No ECPoint internal set, do it");
-
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal q failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    /* read the curve prime and a */
-    if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) {
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX);
-    if (ret == MP_OKAY) {
-        ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX);
-    }
-
-    /* r = q * m % prime */
-    if (ret == MP_OKAY) {
-        ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
-                      (ecc_point*)r->internal, &a, &prime, 1);
-    }
-
-    mp_clear(&a);
-    mp_clear(&prime);
-
-    if (ret == MP_OKAY) {
-        r->inSet = 1; /* mark internal set */
-
-        /* set the external value for the computed point */
-        ret = SetECPointExternal(r);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal r failed");
-        }
-    }
-    else {
-        ret = WOLFSSL_FAILURE;
-    }
-
-    return ret;
-}
-#endif
-
-void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
-
-    wolfSSL_EC_POINT_free(p);
-}
-
-/* return code compliant with OpenSSL :
- *   0 if equal, 1 if not and -1 in case of error
- */
-int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
-                         const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
-                         WOLFSSL_BN_CTX *ctx)
-{
-    int ret;
-
-    (void)ctx;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
-
-    if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
-        b->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal);
-    if (ret == MP_EQ)
-        return 0;
-    else if (ret == MP_LT || ret == MP_GT)
-        return 1;
-
-    return WOLFSSL_FATAL_ERROR;
-}
-#endif /* HAVE_ECC */
-#endif /* OPENSSL_EXTRA */
-
-#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
-{
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
-
-    if (p != NULL) {
-        if (p->internal != NULL) {
-            wc_ecc_del_point((ecc_point*)p->internal);
-            p->internal = NULL;
-        }
-
-        wolfSSL_BN_free(p->X);
-        wolfSSL_BN_free(p->Y);
-        wolfSSL_BN_free(p->Z);
-        p->X = NULL;
-        p->Y = NULL;
-        p->Z = NULL;
-        p->inSet = p->exSet = 0;
-
-        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
-        p = NULL;
-    }
-}
-#endif
-
-#ifdef OPENSSL_EXTRA
-#ifdef HAVE_ECC
-/* return code compliant with OpenSSL :
- *   1 if point at infinity, 0 else
- */
-int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
-                                    const WOLFSSL_EC_POINT *point)
-{
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
-
-    if (group == NULL || point == NULL || point->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
-        return WOLFSSL_FAILURE;
-    }
-    if (point->inSet == 0) {
-        WOLFSSL_MSG("No ECPoint internal set, do it");
-
-        if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECPointInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
-    if (ret <= 0) {
-        WOLFSSL_MSG("ecc_point_is_at_infinity failure");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* End EC_POINT */
-
-/* Start ECDSA_SIG */
-void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
-{
-    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
-
-    if (sig) {
-        wolfSSL_BN_free(sig->r);
-        wolfSSL_BN_free(sig->s);
-
-        XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
-    }
-}
-
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
-{
-    WOLFSSL_ECDSA_SIG *sig;
-
-    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
-
-    sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
-                                       DYNAMIC_TYPE_ECC);
-    if (sig == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
-        return NULL;
-    }
-
-    sig->s = NULL;
-    sig->r = wolfSSL_BN_new();
-    if (sig->r == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
-        wolfSSL_ECDSA_SIG_free(sig);
-        return NULL;
-    }
-
-    sig->s = wolfSSL_BN_new();
-    if (sig->s == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
-        wolfSSL_ECDSA_SIG_free(sig);
-        return NULL;
-    }
-
-    return sig;
-}
-
-/* return signature structure on success, NULL otherwise */
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
-                                         WOLFSSL_EC_KEY *key)
-{
-    WOLFSSL_ECDSA_SIG *sig = NULL;
-    int     initTmpRng = 0;
-    WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG* tmpRNG = NULL;
-#else
-    WC_RNG  tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
-
-    if (d == NULL || key == NULL || key->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
-        return NULL;
-    }
-
-    /* set internal key if not done */
-    if (key->inSet == 0)
-    {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
-
-        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
-            return NULL;
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return NULL;
-#endif
-
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-        mp_int sig_r, sig_s;
-
-        if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) {
-            if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal,
-                                    &sig_r, &sig_s) != MP_OKAY) {
-                WOLFSSL_MSG("wc_ecc_sign_hash_ex failed");
-            }
-            else {
-                /* put signature blob in ECDSA structure */
-                sig = wolfSSL_ECDSA_SIG_new();
-                if (sig == NULL)
-                    WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed");
-                else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){
-                    WOLFSSL_MSG("ecdsa r key error");
-                    wolfSSL_ECDSA_SIG_free(sig);
-                    sig = NULL;
-                }
-                else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){
-                    WOLFSSL_MSG("ecdsa s key error");
-                    wolfSSL_ECDSA_SIG_free(sig);
-                    sig = NULL;
-                }
-
-            }
-            mp_free(&sig_r);
-            mp_free(&sig_s);
-        }
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return sig;
-}
-
-/* return code compliant with OpenSSL :
- *   1 for a valid signature, 0 for an invalid signature and -1 on error
- */
-int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
-                            const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
-{
-    int check_sign = 0;
-
-    WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
-
-    if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
-        WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    /* set internal key if not done */
-    if (key->inSet == 0)
-    {
-        WOLFSSL_MSG("No EC key internal set, do it");
-
-        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
-                              (mp_int*)sig->s->internal, d, dlen, &check_sign,
-                              (ecc_key *)key->internal) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_verify_hash failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-    else if (check_sign == 0) {
-        WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
-        return WOLFSSL_FAILURE;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-/* End ECDSA_SIG */
-
-/* Start ECDH */
-/* return code compliant with OpenSSL :
- *   length of computed key if success, -1 if error
- */
-int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
-                             const WOLFSSL_EC_POINT *pub_key,
-                             WOLFSSL_EC_KEY *ecdh,
-                             void *(*KDF) (const void *in, size_t inlen,
-                                           void *out, size_t *outlen))
-{
-    word32 len;
-    (void)KDF;
-
-    (void)KDF;
-
-    WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
-
-    if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
-        ecdh == NULL || ecdh->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    /* set internal key if not done */
-    if (ecdh->inSet == 0)
-    {
-        WOLFSSL_MSG("No EC key internal set, do it");
-
-        if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetECKeyInternal failed");
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    len = (word32)outlen;
-
-    if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal,
-                                 (ecc_point*)pub_key->internal,
-                                 (byte *)out, &len) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ecc_shared_secret failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    return len;
-}
-/* End ECDH */
-
-#if !defined(NO_FILESYSTEM)
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x)
-{
-    (void)fp;
-    (void)x;
-    WOLFSSL_STUB("PEM_write_EC_PUBKEY");
-    WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#endif /* NO_FILESYSTEM */
-
-#if defined(WOLFSSL_KEY_GEN)
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc,
-                                       const EVP_CIPHER* cipher,
-                                       unsigned char* passwd, int len,
-                                       pem_password_cb* cb, void* arg)
-{
-    (void)bio;
-    (void)ecc;
-    (void)cipher;
-    (void)passwd;
-    (void)len;
-    (void)cb;
-    (void)arg;
-    WOLFSSL_STUB("PEM_write_bio_ECPrivateKey");
-    WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
-                                       const EVP_CIPHER* cipher,
-                                       unsigned char* passwd, int passwdSz,
-                                       unsigned char **pem, int *plen)
-{
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-    byte *derBuf, *tmp, *cipherInfo = NULL;
-    int  der_max_len = 0, derSz = 0;
-    const int type = ECC_PRIVATEKEY_TYPE;
-    const char* header = NULL;
-    const char* footer = NULL;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
-
-    if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
-        return WOLFSSL_FAILURE;
-
-    if (ecc->inSet == 0) {
-        WOLFSSL_MSG("No ECC internal set, do it");
-
-        if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetDsaInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    /* 4 > size of pub, priv + ASN.1 additional informations
-     */
-    der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
-
-    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* Key to DER */
-    derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len);
-    if (derSz < 0) {
-        WOLFSSL_MSG("wc_DsaKeyToDer failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* encrypt DER buffer if required */
-    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
-        int ret;
-
-        ret = EncryptDerKey(derBuf, &derSz, cipher,
-                            passwd, passwdSz, &cipherInfo);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("EncryptDerKey failed");
-            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-            return ret;
-        }
-
-        /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
-    }
-    else { /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1;
-    }
-
-    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
-    if (tmp == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* DER to PEM */
-    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
-    if (*plen <= 0) {
-        WOLFSSL_MSG("wc_DerToPemEx failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-    if (cipherInfo != NULL)
-        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-
-    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
-    if (*pem == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XMEMSET(*pem, 0, (*plen)+1);
-
-    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
-        WOLFSSL_MSG("XMEMCPY failed");
-        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-
-    return WOLFSSL_SUCCESS;
-#else
-    (void)ecc;
-    (void)cipher;
-    (void)passwd;
-    (void)passwdSz;
-    (void)pem;
-    (void)plen;
-    return WOLFSSL_FAILURE;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-}
-
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc,
-                                   const EVP_CIPHER *enc,
-                                   unsigned char *kstr, int klen,
-                                   pem_password_cb *cb, void *u)
-{
-    byte *pem;
-    int  plen, ret;
-
-    (void)cb;
-    (void)u;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
-
-    if (fp == NULL || ecc == NULL || ecc->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
-    if (ret != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = (int)XFWRITE(pem, plen, 1, fp);
-    if (ret != 1) {
-        WOLFSSL_MSG("ECC private key file write failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_FILESYSTEM */
-#endif /* defined(WOLFSSL_KEY_GEN) */
-
-#endif /* HAVE_ECC */
-
-
-#ifndef NO_DSA
-
-#if defined(WOLFSSL_KEY_GEN)
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa,
-                                       const EVP_CIPHER* cipher,
-                                       unsigned char* passwd, int len,
-                                       pem_password_cb* cb, void* arg)
-{
-    (void)bio;
-    (void)dsa;
-    (void)cipher;
-    (void)passwd;
-    (void)len;
-    (void)cb;
-    (void)arg;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
-                                        const EVP_CIPHER* cipher,
-                                        unsigned char* passwd, int passwdSz,
-                                        unsigned char **pem, int *plen)
-{
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-    byte *derBuf, *tmp, *cipherInfo = NULL;
-    int  der_max_len = 0, derSz = 0;
-    const int type = DSA_PRIVATEKEY_TYPE;
-    const char* header = NULL;
-    const char* footer = NULL;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey");
-
-    if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
-        return WOLFSSL_FAILURE;
-
-    if (dsa->inSet == 0) {
-        WOLFSSL_MSG("No DSA internal set, do it");
-
-        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetDsaInternal failed");
-            return WOLFSSL_FAILURE;
-        }
-    }
-
-    /* 4 > size of pub, priv, p, q, g + ASN.1 additional informations
-     */
-    der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
-
-    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* Key to DER */
-    derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
-    if (derSz < 0) {
-        WOLFSSL_MSG("wc_DsaKeyToDer failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* encrypt DER buffer if required */
-    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
-        int ret;
-
-        ret = EncryptDerKey(derBuf, &derSz, cipher,
-                            passwd, passwdSz, &cipherInfo);
-        if (ret != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("EncryptDerKey failed");
-            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-            return ret;
-        }
-
-        /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
-    }
-    else { /* tmp buffer with a max size */
-        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
-            (int)XSTRLEN(footer) + 1;
-    }
-
-    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
-    if (tmp == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* DER to PEM */
-    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
-    if (*plen <= 0) {
-        WOLFSSL_MSG("wc_DerToPemEx failed");
-        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        if (cipherInfo != NULL)
-            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
-    if (cipherInfo != NULL)
-        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
-
-    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
-    if (*pem == NULL) {
-        WOLFSSL_MSG("malloc failed");
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XMEMSET(*pem, 0, (*plen)+1);
-
-    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
-        WOLFSSL_MSG("XMEMCPY failed");
-        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-        return WOLFSSL_FAILURE;
-    }
-    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
-
-    return WOLFSSL_SUCCESS;
-#else
-    (void)dsa;
-    (void)cipher;
-    (void)passwd;
-    (void)passwdSz;
-    (void)pem;
-    (void)plen;
-    return WOLFSSL_FAILURE;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-}
-
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa,
-                                    const EVP_CIPHER *enc,
-                                    unsigned char *kstr, int klen,
-                                    pem_password_cb *cb, void *u)
-{
-    byte *pem;
-    int  plen, ret;
-
-    (void)cb;
-    (void)u;
-
-    WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey");
-
-    if (fp == NULL || dsa == NULL || dsa->internal == NULL) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen);
-    if (ret != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    ret = (int)XFWRITE(pem, plen, 1, fp);
-    if (ret != 1) {
-        WOLFSSL_MSG("DSA private key file write failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-    return WOLFSSL_SUCCESS;
-}
-
-#endif /* NO_FILESYSTEM */
-#endif /* defined(WOLFSSL_KEY_GEN) */
-
-#ifndef NO_FILESYSTEM
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x)
-{
-    (void)fp;
-    (void)x;
-    WOLFSSL_STUB("PEM_write_DSA_PUBKEY");
-    WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-#endif /* NO_FILESYSTEM */
-
-#endif /* #ifndef NO_DSA */
-
-
-WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
-                    WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* pass)
-{
-    WOLFSSL_EVP_PKEY* pkey = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    EncryptedInfo* info;
-#else
-    EncryptedInfo info[1];
-#endif /* WOLFSSL_SMALL_STACK */
-    pem_password_cb* localCb = cb;
-    DerBuffer* der = NULL;
-
-    char* mem = NULL;
-    int memSz;
-    int ret;
-    int eccFlag = 0;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
-
-    if (bio == NULL) {
-        return pkey;
-    }
-
-    if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
-        memSz = ret;
-        mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
-        if (mem == NULL) {
-            WOLFSSL_MSG("Memory error");
-            return NULL;
-        }
-
-        if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) {
-            WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", ret);
-            XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-            return NULL;
-        }
-    }
-    else if (bio->type == WOLFSSL_BIO_FILE) {
-        int sz  = 100; /* read from file by 100 byte chuncks */
-        int idx = 0;
-        char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
-
-        memSz = 0;
-        if (tmp == NULL) {
-            WOLFSSL_MSG("Memory error");
-            return NULL;
-        }
-
-        while ((sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) {
-            if (memSz + sz < 0) {
-                /* sanity check */
-                break;
-            }
-            mem = (char*)XREALLOC(mem, memSz + sz, bio->heap,
-                    DYNAMIC_TYPE_OPENSSL);
-            if (mem == NULL) {
-                WOLFSSL_MSG("Memory error");
-                XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
-                return NULL;
-            }
-            XMEMCPY(mem + idx, tmp, sz);
-            memSz += sz;
-            idx   += sz;
-            sz = 100; /* read another 100 byte chunck from file */
-        }
-        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
-        if (memSz <= 0) {
-            WOLFSSL_MSG("No data to read from bio");
-            if (mem != NULL) {
-                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-            }
-            return NULL;
-        }
-    }
-    else {
-        WOLFSSL_MSG("No data to read from bio");
-        return NULL;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
-                                   DYNAMIC_TYPE_TMP_BUFFER);
-    if (info == NULL) {
-        WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
-        XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-        return NULL;
-    }
-#endif
-
-    XMEMSET(info, 0, sizeof(EncryptedInfo));
-    info->passwd_cb       = localCb;
-    info->passwd_userdata = pass;
-    ret = PemToDer((const unsigned char*)mem, memSz, PRIVATEKEY_TYPE, &der,
-        NULL, info, &eccFlag);
-
-    if (ret < 0) {
-        WOLFSSL_MSG("Bad Pem To Der");
-    }
-    else {
-        int type;
-        const unsigned char* ptr = der->buffer;
-
-        /* write left over data back to bio */
-        if ((memSz - (int)info->consumed) > 0 &&
-                bio->type != WOLFSSL_BIO_FILE) {
-            if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
-                                   memSz - (int)info->consumed) <= 0) {
-                WOLFSSL_MSG("Unable to advance bio read pointer");
-            }
-        }
-
-        if (eccFlag) {
-            type = EVP_PKEY_EC;
-        }
-        else {
-            type = EVP_PKEY_RSA;
-        }
-
-        /* handle case where reuse is attempted */
-        if (key != NULL && *key != NULL) {
-            pkey = *key;
-        }
-
-        wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length);
-        if (pkey == NULL) {
-            WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
-    FreeDer(&der);
-
-    if (key != NULL) {
-        *key = pkey;
-    }
-
-    return pkey;
-}
-
-
-#ifndef NO_RSA
-/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
- * the results to be an RSA key.
- *
- * bio  structure to read RSA private key from
- * rsa  if not null is then set to the result
- * cb   password callback for reading PEM
- * pass password string
- *
- * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail
- */
-WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
-        WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass)
-{
-    WOLFSSL_EVP_PKEY* pkey;
-    WOLFSSL_RSA* local;
-
-    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
-    if (pkey == NULL) {
-        return NULL;
-    }
-
-    /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the
-     * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
-     * to avoid having it free'd */
-    pkey->ownRsa = 0;
-    local = pkey->rsa;
-    if (rsa != NULL) {
-        *rsa = local;
-    }
-
-    wolfSSL_EVP_PKEY_free(pkey);
-    return local;
-}
-#endif /* !NO_RSA */
-
-
-/* return of pkey->type which will be EVP_PKEY_RSA for example.
- *
- * type  type of EVP_PKEY
- *
- * returns type or if type is not found then NID_undef
- */
-int wolfSSL_EVP_PKEY_type(int type)
-{
-    WOLFSSL_MSG("wolfSSL_EVP_PKEY_type");
-
-    switch (type) {
-    #ifdef OPENSSL_EXTRA
-        case EVP_PKEY_RSA:
-            return EVP_PKEY_RSA;
-        case EVP_PKEY_DSA:
-            return EVP_PKEY_DSA;
-        case EVP_PKEY_EC:
-            return EVP_PKEY_EC;
-    #endif
-        default:
-            return NID_undef;
-    }
-}
-
-
-int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey)
-{
-    return EVP_PKEY_type(pkey->type);
-}
-
-
-#if !defined(NO_FILESYSTEM)
-WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
-                                          pem_password_cb *cb, void *u)
-{
-    (void)fp;
-    (void)x;
-    (void)cb;
-    (void)u;
-
-    WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented");
-
-    return NULL;
-}
-#endif /* NO_FILESYSTEM */
-
-#ifndef NO_RSA
-
-#if !defined(NO_FILESYSTEM)
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x,
-                                           pem_password_cb *cb, void *u)
-{
-    (void)fp;
-    (void)x;
-    (void)cb;
-    (void)u;
-    WOLFSSL_STUB("PEM_read_RSAPublicKey");
-    WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented");
-
-    return NULL;
-}
-#endif
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x)
-{
-    (void)fp;
-    (void)x;
-    WOLFSSL_STUB("PEM_write_RSAPublicKey");
-    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-/* return code compliant with OpenSSL :
- *   1 if success, 0 if error
- */
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x)
-{
-    (void)fp;
-    (void)x;
-    WOLFSSL_STUB("PEM_write_RSA_PUBKEY");
-    WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#endif /* NO_FILESYSTEM */
-
-WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp, long len)
-{
-    WOLFSSL_RSA *rsa = NULL;
-
-    WOLFSSL_ENTER("d2i_RSAPublicKey");
-
-    if(pp == NULL){
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-    if((rsa = wolfSSL_RSA_new()) == NULL){
-        WOLFSSL_MSG("RSA_new failed");
-        return NULL;
-    }
-
-    if(wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC)
-                                                     != WOLFSSL_SUCCESS){
-        WOLFSSL_MSG("RSA_LoadDer failed");
-        wolfSSL_RSA_free(rsa);
-        rsa = NULL;
-        return NULL;
-    }
-    if(r != NULL)
-        *r = rsa;
-    return rsa;
-}
-
-/* Converts an rsa private key from der format to an rsa structure.
-Returns pointer to the rsa structure on succcess and NULL if error. */
-WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r, 
-                                       const unsigned char **derBuf, long derSz)
-{
-    WOLFSSL_RSA *rsa = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey");
-
-    /* check for bad functions arguments */
-    if (derBuf == NULL) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-    if ((rsa = wolfSSL_RSA_new()) == NULL) {
-        WOLFSSL_MSG("RSA_new failed");
-        return NULL;
-    }
-
-    if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz, 
-                                 WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("RSA_LoadDer failed");
-        wolfSSL_RSA_free(rsa);
-        rsa = NULL;
-        return NULL;
-    }
-    if(r != NULL)
-        *r = rsa;
-
-    return rsa;
-}
-
-#if !defined(HAVE_FAST_RSA)
-#if defined(WOLFSSL_KEY_GEN)
-
-/* Converts an internal rsa structure to der format.
-Returns size of der on success and WOLFSSL_FAILURE if error */
-int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
-{
-    byte* der = NULL;
-    int derMax;
-    int ret;
-    int i;
-
-    WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
-
-    /* check for bad functions arguments */
-    if ((rsa == NULL) || (pp == NULL)) {
-        WOLFSSL_MSG("Bad Function Arguments");
-        return BAD_FUNC_ARG;
-    }
-
-    if (rsa->inSet == 0) {
-        if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
-            WOLFSSL_MSG("SetRsaInternal() Failed");
-            return ret;
-        }
-    }
-
-    /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
-     *  informations
-     */
-    derMax = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE;
-
-    der = (byte*)XMALLOC(derMax, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (der == NULL) {
-        WOLFSSL_MSG("Malloc failed");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* RSA key to DER */
-    if ((ret = wc_RsaKeyToDer((RsaKey *)rsa->internal, der, derMax)) < 0) {
-        WOLFSSL_MSG("wc_RsaKeyToDer() failed");
-        XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        der = NULL;
-        return ret;
-    }
-
-    /* ret is the size of the der buffer */
-    for (i = 0; i < ret; i++) {
-        *(*pp + i) = *(der + i);
-    }
-    *pp += ret;
-
-    XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    return ret; /* returns size of der if successful */
-}
-#endif /* WOLFSSL_KEY_GEN */
-
-
-int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp)
-{
-    byte *der;
-    int derLen;
-    int ret;
-
-    WOLFSSL_ENTER("i2d_RSAPublicKey");
-    if ((rsa == NULL) || (pp == NULL))
-        return WOLFSSL_FATAL_ERROR;
-    if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetRsaInternal Failed");
-        return ret;
-    }
-    if ((derLen = RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0)
-        return WOLFSSL_FATAL_ERROR;
-    der = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (der == NULL) {
-        return WOLFSSL_FATAL_ERROR;
-    }
-    if ((ret = wc_RsaKeyToPublicDer((RsaKey *)rsa->internal, der, derLen)) < 0){
-        WOLFSSL_MSG("RsaKeyToPublicDer failed");
-        XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-
-    *pp = der;
-    return ret;
-}
-#endif /* #if !defined(HAVE_FAST_RSA) */
-
-#endif /* !NO_RSA */
-#endif /* OPENSSL_EXTRA */
-
-#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
-int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz)
-{
-  return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
-}
-
-
-int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
-                                                     int derSz, int opt)
-{
-
-    word32 idx = 0;
-    int    ret;
-
-    WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
-
-    if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
-        ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
-    }
-    else {
-        ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
-    }
-
-    if (ret < 0) {
-        if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
-             WOLFSSL_MSG("RsaPrivateKeyDecode failed");
-        }
-        else {
-             WOLFSSL_MSG("RsaPublicKeyDecode failed");
-        }
-        return SSL_FATAL_ERROR;
-    }
-
-    if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetRsaExternal failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    rsa->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_RSA */
-
-#ifdef OPENSSL_EXTRA
-#ifndef NO_DSA
-/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
-int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz)
-{
-    word32 idx = 0;
-    int    ret;
-
-    WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
-
-    if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
-    if (ret < 0) {
-        WOLFSSL_MSG("DsaPrivateKeyDecode failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetDsaExternal failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    dsa->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* NO_DSA */
-
-#ifdef HAVE_ECC
-/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
-int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key,
-                           const unsigned char* derBuf,  int derSz)
-{
-    word32 idx = 0;
-    int    ret;
-
-    WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
-
-    if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
-        WOLFSSL_MSG("Bad function arguments");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz);
-    if (ret < 0) {
-        WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("SetECKeyExternal failed");
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    key->inSet = 1;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_ECC */
-
-
-#endif /* OPENSSL_EXTRA */
-
-
-#ifdef WOLFSSL_ALT_CERT_CHAINS
-int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl)
-{
-    int isUsing = 0;
-    if (ssl)
-        isUsing = ssl->options.usingAltCertChain;
-    return isUsing;
-}
-#endif /* WOLFSSL_ALT_CERT_CHAINS */
-
-
-#ifdef SESSION_CERTS
-
-#ifdef WOLFSSL_ALT_CERT_CHAINS
-/* Get peer's alternate certificate chain */
-WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
-    if (ssl)
-        return &ssl->session.altChain;
-
-    return 0;
-}
-#endif /* WOLFSSL_ALT_CERT_CHAINS */
-
-
-/* Get peer's certificate chain */
-WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_peer_chain");
-    if (ssl)
-        return &ssl->session.chain;
-
-    return 0;
-}
-
-
-/* Get peer's certificate chain total count */
-int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
-{
-    WOLFSSL_ENTER("wolfSSL_get_chain_count");
-    if (chain)
-        return chain->count;
-
-    return 0;
-}
-
-
-/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
-int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_get_chain_length");
-    if (chain)
-        return chain->certs[idx].length;
-
-    return 0;
-}
-
-
-/* Get peer's ASN.1 DER certificate at index (idx) */
-byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_get_chain_cert");
-    if (chain)
-        return chain->certs[idx].buffer;
-
-    return 0;
-}
-
-
-/* Get peer's wolfSSL X509 certificate at index (idx) */
-WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
-{
-    int          ret;
-    WOLFSSL_X509* x509 = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_get_chain_X509");
-    if (chain != NULL) {
-    #ifdef WOLFSSL_SMALL_STACK
-        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                                       DYNAMIC_TYPE_DCERT);
-        if (cert != NULL)
-    #endif
-        {
-            InitDecodedCert(cert, chain->certs[idx].buffer,
-                                  chain->certs[idx].length, NULL);
-
-            if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) {
-                WOLFSSL_MSG("Failed to parse cert");
-            }
-            else {
-                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
-                                                             DYNAMIC_TYPE_X509);
-                if (x509 == NULL) {
-                    WOLFSSL_MSG("Failed alloc X509");
-                }
-                else {
-                    InitX509(x509, 1, NULL);
-
-                    if ((ret = CopyDecodedToX509(x509, cert)) != 0) {
-                        WOLFSSL_MSG("Failed to copy decoded");
-                        XFREE(x509, NULL, DYNAMIC_TYPE_X509);
-                        x509 = NULL;
-                    }
-                }
-            }
-
-            FreeDecodedCert(cert);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-        #endif
-        }
-    }
-    (void)ret;
-
-    return x509;
-}
-
-
-/* Get peer's PEM certificate at index (idx), output to buffer if inLen big
-   enough else return error (-1). If buffer is NULL only calculate
-   outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
-int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
-                               unsigned char* buf, int inLen, int* outLen)
-{
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-    const char* header = NULL;
-    const char* footer = NULL;
-    int headerLen;
-    int footerLen;
-    int i;
-    int err;
-    word32 szNeeded = 0;
-
-    WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
-    if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
-        return BAD_FUNC_ARG;
-
-    err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer);
-    if (err != 0)
-        return err;
-
-    headerLen = (int)XSTRLEN(header);
-    footerLen = (int)XSTRLEN(footer);
-
-    /* Null output buffer return size needed in outLen */
-    if(!buf) {
-        if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length,
-                    NULL, &szNeeded) != LENGTH_ONLY_E)
-            return WOLFSSL_FAILURE;
-        *outLen = szNeeded + headerLen + footerLen;
-        return LENGTH_ONLY_E;
-    }
-
-    /* don't even try if inLen too short */
-    if (inLen < headerLen + footerLen + chain->certs[idx].length)
-        return BAD_FUNC_ARG;
-
-    /* header */
-    if (XMEMCPY(buf, header, headerLen) == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    i = headerLen;
-
-    /* body */
-    *outLen = inLen;  /* input to Base64_Encode */
-    if ( (err = Base64_Encode(chain->certs[idx].buffer,
-                       chain->certs[idx].length, buf + i, (word32*)outLen)) < 0)
-        return err;
-    i += *outLen;
-
-    /* footer */
-    if ( (i + footerLen) > inLen)
-        return BAD_FUNC_ARG;
-    if (XMEMCPY(buf + i, footer, footerLen) == NULL)
-        return WOLFSSL_FATAL_ERROR;
-    *outLen += headerLen + footerLen;
-
-    return WOLFSSL_SUCCESS;
-#else
-    (void)chain;
-    (void)idx;
-    (void)buf;
-    (void)inLen;
-    (void)outLen;
-    return WOLFSSL_FAILURE;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-}
-
-
-/* get session ID */
-const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session)
-{
-    WOLFSSL_ENTER("wolfSSL_get_sessionID");
-    if (session)
-        return session->sessionID;
-
-    return NULL;
-}
-
-
-#endif /* SESSION_CERTS */
-
-#ifdef HAVE_FUZZER
-void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
-{
-    if (ssl) {
-        ssl->fuzzerCb  = cbf;
-        ssl->fuzzerCtx = fCtx;
-    }
-}
-#endif
-
-#ifndef NO_CERTS
-#ifdef  HAVE_PK_CALLBACKS
-
-#ifdef HAVE_ECC
-void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
-{
-    if (ctx)
-        ctx->EccKeyGenCb = cb;
-}
-void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->EccKeyGenCtx = ctx;
-}
-void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->EccKeyGenCtx;
-
-    return NULL;
-}
-
-void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
-{
-    if (ctx)
-        ctx->EccSignCb = cb;
-}
-void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->EccSignCtx = ctx;
-}
-void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->EccSignCtx;
-
-    return NULL;
-}
-
-void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
-{
-    if (ctx)
-        ctx->EccVerifyCb = cb;
-}
-void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->EccVerifyCtx = ctx;
-}
-void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->EccVerifyCtx;
-
-    return NULL;
-}
-
-void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb)
-{
-    if (ctx)
-        ctx->EccSharedSecretCb = cb;
-}
-void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->EccSharedSecretCtx = ctx;
-}
-void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->EccSharedSecretCtx;
-
-    return NULL;
-}
-#endif /* HAVE_ECC */
-
-#ifdef HAVE_ED25519
-void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
-{
-    if (ctx)
-        ctx->Ed25519SignCb = cb;
-}
-void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->Ed25519SignCtx = ctx;
-}
-void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->Ed25519SignCtx;
-
-    return NULL;
-}
-
-void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
-{
-    if (ctx)
-        ctx->Ed25519VerifyCb = cb;
-}
-void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->Ed25519VerifyCtx = ctx;
-}
-void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->Ed25519VerifyCtx;
-
-    return NULL;
-}
-#endif /* HAVE_ED25519 */
-
-#ifdef HAVE_CURVE25519
-void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
-        CallbackX25519KeyGen cb)
-{
-    if (ctx)
-        ctx->X25519KeyGenCb = cb;
-}
-void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->X25519KeyGenCtx = ctx;
-}
-void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->X25519KeyGenCtx;
-
-    return NULL;
-}
-
-void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
-        CallbackX25519SharedSecret cb)
-{
-    if (ctx)
-        ctx->X25519SharedSecretCb = cb;
-}
-void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->X25519SharedSecretCtx = ctx;
-}
-void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->X25519SharedSecretCtx;
-
-    return NULL;
-}
-#endif /* HAVE_CURVE25519 */
-
-#ifndef NO_RSA
-void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
-{
-    if (ctx)
-        ctx->RsaSignCb = cb;
-}
-void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
-{
-    if (ctx)
-        ctx->RsaSignCheckCb = cb;
-}
-void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaSignCtx = ctx;
-}
-void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaSignCtx;
-
-    return NULL;
-}
-
-
-void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
-{
-    if (ctx)
-        ctx->RsaVerifyCb = cb;
-}
-void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaVerifyCtx = ctx;
-}
-void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaVerifyCtx;
-
-    return NULL;
-}
-
-#ifdef WC_RSA_PSS
-void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
-{
-    if (ctx)
-        ctx->RsaPssSignCb = cb;
-}
-void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
-{
-    if (ctx)
-        ctx->RsaPssSignCheckCb = cb;
-}
-void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaPssSignCtx = ctx;
-}
-void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaPssSignCtx;
-
-    return NULL;
-}
-
-void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
-{
-    if (ctx)
-        ctx->RsaPssVerifyCb = cb;
-}
-void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaPssVerifyCtx = ctx;
-}
-void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaPssVerifyCtx;
-
-    return NULL;
-}
-#endif /* WC_RSA_PSS */
-
-void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
-{
-    if (ctx)
-        ctx->RsaEncCb = cb;
-}
-void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaEncCtx = ctx;
-}
-void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaEncCtx;
-
-    return NULL;
-}
-
-void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
-{
-    if (ctx)
-        ctx->RsaDecCb = cb;
-}
-void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->RsaDecCtx = ctx;
-}
-void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->RsaDecCtx;
-
-    return NULL;
-}
-#endif /* NO_RSA */
-
-#endif /* HAVE_PK_CALLBACKS */
-#endif /* NO_CERTS */
-
-#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
-void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
-{
-    if (ctx)
-        ctx->DhAgreeCb = cb;
-}
-void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
-{
-    if (ssl)
-        ssl->DhAgreeCtx = ctx;
-}
-void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->DhAgreeCtx;
-
-    return NULL;
-}
-#endif /* HAVE_PK_CALLBACKS && !NO_DH */
-
-
-#ifdef WOLFSSL_HAVE_WOLFSCEP
-    /* Used by autoconf to see if wolfSCEP is available */
-    void wolfSSL_wolfSCEP(void) {}
-#endif
-
-
-#ifdef WOLFSSL_HAVE_CERT_SERVICE
-    /* Used by autoconf to see if cert service is available */
-    void wolfSSL_cert_service(void) {}
-#endif
-
-
-#ifdef OPENSSL_EXTRA /*Lighttp compatibility*/
-
-    #ifndef NO_CERTS
-    void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
-        FreeX509Name(name, NULL);
-        XFREE(name, NULL, DYNAMIC_TYPE_X509);
-    }
-
-
-    /* Malloc's a new WOLFSSL_X509_NAME structure
-     *
-     * returns NULL on failure, otherwise returns a new structure.
-     */
-    WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new()
-    {
-        WOLFSSL_X509_NAME* name;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_new");
-
-        name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL,
-                DYNAMIC_TYPE_X509);
-        if (name != NULL) {
-            InitX509Name(name, 1);
-        }
-        return name;
-    }
-
-
-#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA)
-/* needed SetName function from asn.c is wrapped by NO_RSA */
-    /* helper function for CopyX509NameToCertName()
-     *
-     * returns WOLFSSL_SUCCESS on success
-     */
-    static int CopyX509NameEntry(char* out, int mx, char* in, int inLen)
-    {
-        if (inLen > mx) {
-            WOLFSSL_MSG("Name too long");
-            XMEMCPY(out, in, mx);
-        }
-        else {
-            XMEMCPY(out, in, inLen);
-            out[inLen] = '\0';
-        }
-
-        /* make sure is null terminated */
-        out[mx-1] = '\0';
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to
-     * a CertName structure.
-     *
-     * returns WOLFSSL_SUCCESS on success and a negative error value on failure
-     */
-    static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName)
-    {
-        DecodedName* dn = NULL;
-
-        if (n == NULL || cName == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        dn = &(n->fullName);
-
-        /* initialize cert name */
-        cName->country[0] = '\0';
-        cName->countryEnc = CTC_PRINTABLE;
-        cName->state[0] = '\0';
-        cName->stateEnc = CTC_UTF8;
-        cName->locality[0] = '\0';
-        cName->localityEnc = CTC_UTF8;
-        cName->sur[0] = '\0';
-        cName->surEnc = CTC_UTF8;
-        cName->org[0] = '\0';
-        cName->orgEnc = CTC_UTF8;
-        cName->unit[0] = '\0';
-        cName->unitEnc = CTC_UTF8;
-        cName->commonName[0] = '\0';
-        cName->commonNameEnc = CTC_UTF8;
-        cName->email[0] = '\0';
-
-
-        /* ASN_COUNTRY_NAME */
-        WOLFSSL_MSG("Copy Country Name");
-        if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx,
-                    dn->cLen) != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_ORGUNIT_NAME */
-        WOLFSSL_MSG("Copy Org Unit Name");
-        if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx,
-                    dn->ouLen) != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_ORG_NAME */
-        WOLFSSL_MSG("Copy Org Name");
-        if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx,
-                    dn->oLen) != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_STATE_NAME */
-        WOLFSSL_MSG("Copy State Name");
-        if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx,
-                    dn->stLen) != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_LOCALITY_NAME */
-        WOLFSSL_MSG("Copy Locality Name");
-        if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE,
-                    dn->fullName + dn->lIdx, dn->lLen)
-                    != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_SUR_NAME */
-        WOLFSSL_MSG("Copy Sur Name");
-        if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx,
-                    dn->snLen) != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        /* ASN_COMMON_NAME */
-        WOLFSSL_MSG("Copy Common Name");
-        if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE,
-                    dn->fullName + dn->cnIdx, dn->cnLen)
-                    != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        WOLFSSL_MSG("Copy Email");
-        if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE,
-                    dn->fullName + dn->emailIdx, dn->emailLen)
-                    != SSL_SUCCESS) {
-            return BUFFER_E;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-
-    /* 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)
-    {
-        CertName cName;
-        unsigned char buf[256]; /* ASN_MAX_NAME */
-        int sz;
-
-        if (out == NULL || name == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) {
-            WOLFSSL_MSG("Error converting x509 name to internal CertName");
-            return SSL_FATAL_ERROR;
-        }
-
-        sz = SetName(buf, sizeof(buf), &cName);
-        if (sz < 0) {
-            return sz;
-        }
-
-        /* using buffer passed in */
-        if (*out != NULL) {
-            XMEMCPY(*out, buf, sz);
-            *out += sz;
-        }
-        else {
-            *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
-            if (*out == NULL) {
-                return MEMORY_E;
-            }
-            XMEMCPY(*out, buf, sz);
-        }
-
-        return sz;
-    }
-#endif /* WOLFSSL_CERT_GEN */
-
-
-    /* Compares the two X509 names. If the size of x is larger then y then a
-     * positive value is returned if x is smaller a negative value is returned.
-     * In the case that the sizes are equal a the value of memcmp between the
-     * two names is returned.
-     *
-     * x First name for comparision
-     * y Second name to compare with x
-     */
-    int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
-            const WOLFSSL_X509_NAME* y)
-    {
-        WOLFSSL_STUB("wolfSSL_X509_NAME_cmp");
-
-        if (x == NULL || y == NULL) {
-            WOLFSSL_MSG("Bad argument passed in");
-            return -2;
-        }
-
-        if ((x->sz - y->sz) != 0) {
-            return x->sz - y->sz;
-        }
-        else {
-            return XMEMCMP(x->name, y->name, x->sz); /* y sz is the same */
-        }
-    }
-
-
-    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
-                                                 pem_password_cb *cb, void *u)
-    {
-        WOLFSSL_X509* x509 = NULL;
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-        unsigned char* pem = NULL;
-        int pemSz;
-        long  i = 0, l;
-        const char* footer = NULL;
-
-        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
-
-        if (bp == NULL) {
-            WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
-            return NULL;
-        }
-
-        if (bp->type == WOLFSSL_BIO_MEMORY) {
-            l = (long)wolfSSL_BIO_ctrl_pending(bp);
-            if (l <= 0) {
-                WOLFSSL_MSG("No pending data in WOLFSSL_BIO");
-                return NULL;
-            }
-        }
-        else if (bp->type == WOLFSSL_BIO_FILE) {
-#ifndef NO_FILESYSTEM
-            /* Read in next certificate from file but no more. */
-            i = XFTELL(bp->file);
-            if (i < 0)
-                return NULL;
-            if (XFSEEK(bp->file, 0, SEEK_END) != 0)
-                return NULL;
-            l = XFTELL(bp->file);
-            if (l < 0)
-                return NULL;
-            if (XFSEEK(bp->file, i, SEEK_SET) != 0)
-                return NULL;
-
-            /* check calculated length */
-            if (l - i < 0)
-                return NULL;
-
-            l -= i;
-#else
-            WOLFSSL_MSG("Unable to read file with NO_FILESYSTEM defined");
-            return NULL;
-#endif /* !NO_FILESYSTEM */
-        }
-        else
-            return NULL;
-
-        pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
-        if (pem == NULL)
-            return NULL;
-
-        i = 0;
-        if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) {
-            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
-            return NULL;
-        }
-
-        /* TODO: Inefficient
-         * reading in one byte at a time until see "END CERTIFICATE"
-         */
-        while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
-            i++;
-            if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) {
-                if (pem[i-1] == '\r') {
-                    /* found \r , Windows line ending is \r\n so try to read one
-                     * more byte for \n, ignoring return value */
-                    (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
-                }
-                break;
-            }
-        }
-    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-        if (l == 0)
-            WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
-    #endif
-        pemSz = (int)i;
-        x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz,
-                                                              WOLFSSL_FILETYPE_PEM);
-
-        if (x != NULL) {
-            *x = x509;
-        }
-
-        XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
-
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-        (void)bp;
-        (void)x;
-        (void)cb;
-        (void)u;
-
-        return x509;
-    }
-
-#if defined(HAVE_CRL) && !defined(NO_FILESYSTEM)
-    WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl,
-                                                    pem_password_cb *cb, void *u)
-    {
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-        unsigned char* pem = NULL;
-        DerBuffer* der = NULL;
-        int pemSz;
-        int derSz;
-        long  i = 0, l;
-        WOLFSSL_X509_CRL* newcrl;
-
-        WOLFSSL_ENTER("wolfSSL_PEM_read_X509_CRL");
-
-        if (fp == NULL) {
-            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509_CRL", BAD_FUNC_ARG);
-            return NULL;
-        }
-        /* Read in CRL from file */
-        i = XFTELL(fp);
-        if (i < 0) {
-            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509_CRL", BAD_FUNC_ARG);
-            return NULL;
-        }
-
-        if (XFSEEK(fp, 0, SEEK_END) != 0)
-            return NULL;
-        l = XFTELL(fp);
-        if (l < 0)
-            return NULL;
-        if (XFSEEK(fp, i, SEEK_SET) != 0)
-            return NULL;
-        pemSz = (int)(l - i);
-        /* check calculated length */
-        if (pemSz  < 0)
-            return NULL;
-        if((pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM)) == NULL)
-            return NULL;
-
-        if((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz)
-            goto err_exit;
-        if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0)
-            goto err_exit;
-        XFREE(pem, 0, DYNAMIC_TYPE_PEM);
-
-        derSz = der->length;
-        if((newcrl = wolfSSL_d2i_X509_CRL(crl, (const unsigned char *)der->buffer, derSz)) == NULL)
-            goto err_exit;
-        FreeDer(&der);
-
-        return newcrl;
-
-    err_exit:
-        if(pem != NULL)
-            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
-        if(der != NULL)
-            FreeDer(&der);
-        return NULL;
-
-        (void)cb;
-        (void)u;
-    #endif
-
-    }
-#endif
-
-    /*
-     * bp : bio to read X509 from
-     * x  : x509 to write to
-     * cb : password call back for reading PEM
-     * u  : password
-     * _AUX is for working with a trusted X509 certificate
-     */
-    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
-                               WOLFSSL_X509 **x, pem_password_cb *cb, void *u) {
-        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
-
-        /* AUX info is; trusted/rejected uses, friendly name, private key id,
-         * and potentially a stack of "other" info. wolfSSL does not store
-         * friendly name or private key id yet in WOLFSSL_X509 for human
-         * readibility and does not support extra trusted/rejected uses for
-         * root CA. */
-        return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
-    }
-
-    void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
-    {
-        if (ne != NULL) {
-            if (ne->value != NULL && ne->value != &(ne->data)) {
-                wolfSSL_ASN1_STRING_free(ne->value);
-            }
-            XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY);
-        }
-    }
-
-
-    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void)
-    {
-        WOLFSSL_X509_NAME_ENTRY* ne = NULL;
-
-        ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY),
-                NULL, DYNAMIC_TYPE_NAME_ENTRY);
-        if (ne != NULL) {
-            XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
-            ne->value = &(ne->data);
-        }
-
-        return ne;
-    }
-
-
-    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
-            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
-            unsigned char* data, int dataSz)
-    {
-        WOLFSSL_X509_NAME_ENTRY* ne = NULL;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()");
-
-        ne = wolfSSL_X509_NAME_ENTRY_new();
-        if (ne == NULL) {
-            return NULL;
-        }
-
-        ne->nid = nid;
-        ne->value = wolfSSL_ASN1_STRING_type_new(type);
-        wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
-        ne->set = 1;
-
-        if (out != NULL) {
-            *out = ne;
-        }
-
-        return ne;
-    }
-
-
-    /* Copies entry into name. With it being copied freeing entry becomes the
-     * callers responsibility.
-     * returns 1 for success and 0 for error */
-    int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
-            WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set)
-    {
-        int i;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()");
-
-        for (i = 0; i < MAX_NAME_ENTRIES; i++) {
-            if (name->extra[i].set != 1) { /* not set so overwrited */
-                WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]);
-                WOLFSSL_ASN1_STRING*     str;
-
-                WOLFSSL_MSG("Found place for name entry");
-
-                XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY));
-                str = entry->value;
-                XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING));
-                current->value = &(current->data);
-                current->data.data = (char*)XMALLOC(str->length,
-                       name->x509->heap, DYNAMIC_TYPE_OPENSSL);
-
-                if (current->data.data == NULL) {
-                    return SSL_FAILURE;
-                }
-                XMEMCPY(current->data.data, str->data, str->length);
-
-                /* make sure is null terminated */
-                current->data.data[str->length - 1] = '\0';
-
-                current->set = 1; /* make sure now listed as set */
-                break;
-            }
-        }
-
-        if (i == MAX_NAME_ENTRIES) {
-            WOLFSSL_MSG("No spot found for name entry");
-            return SSL_FAILURE;
-        }
-
-        (void)idx;
-        (void)set;
-        return SSL_SUCCESS;
-    }
-    #endif /* ifndef NO_CERTS */
-
-
-    /* NID variables are dependent on compatibility header files currently
-     *
-     * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL
-     *         on fail
-     */
-    WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
-    {
-        word32 oidSz = 0;
-        const byte* oid;
-        word32 type = 0;
-        WOLFSSL_ASN1_OBJECT* obj;
-        byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */
-        word32 objSz = 0;
-        const char* sName;
-
-        WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()");
-
-        /* get OID type */
-        switch (id) {
-            /* oidHashType */
-        #ifdef WOLFSSL_MD2
-            case NID_md2:
-                id = MD2h;
-                type = oidHashType;
-                sName = "md2";
-                break;
-        #endif
-        #ifndef NO_MD5
-            case NID_md5:
-                id = MD5h;
-                type = oidHashType;
-                sName = "md5";
-                break;
-        #endif
-        #ifndef NO_SHA
-            case NID_sha1:
-                id = SHAh;
-                type = oidHashType;
-                sName = "sha";
-                break;
-        #endif
-            case NID_sha224:
-                id = SHA224h;
-                type = oidHashType;
-                sName = "sha224";
-                break;
-        #ifndef NO_SHA256
-            case NID_sha256:
-                id = SHA256h;
-                type = oidHashType;
-                sName = "sha256";
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            case NID_sha384:
-                id = SHA384h;
-                type = oidHashType;
-                sName = "sha384";
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA512
-            case NID_sha512:
-                id = SHA512h;
-                type = oidHashType;
-                sName = "sha512";
-                break;
-        #endif
-
-            /*  oidSigType */
-        #ifndef NO_DSA
-            case CTC_SHAwDSA:
-                sName = "shaWithDSA";
-                type = oidSigType;
-                break;
-
-        #endif /* NO_DSA */
-        #ifndef NO_RSA
-            case CTC_MD2wRSA:
-                sName = "md2WithRSA";
-                type = oidSigType;
-                break;
-
-        #ifndef NO_MD5
-            case CTC_MD5wRSA:
-                sName = "md5WithRSA";
-                type = oidSigType;
-                break;
-        #endif
-
-            case CTC_SHAwRSA:
-                sName = "shaWithRSA";
-                type = oidSigType;
-                break;
-
-        #ifdef WOLFSSL_SHA224
-            case CTC_SHA224wRSA:
-                sName = "sha224WithRSA";
-                type = oidSigType;
-                break;
-        #endif
-
-        #ifndef NO_SHA256
-            case CTC_SHA256wRSA:
-                sName = "sha256WithRSA";
-                type = oidSigType;
-                break;
-        #endif
-
-        #ifdef WOLFSSL_SHA384
-            case CTC_SHA384wRSA:
-                sName = "sha384WithRSA";
-                type = oidSigType;
-                break;
-        #endif
-
-        #ifdef WOLFSSL_SHA512
-            case CTC_SHA512wRSA:
-                sName = "sha512WithRSA";
-                type = oidSigType;
-                break;
-        #endif
-        #endif /* NO_RSA */
-        #ifdef HAVE_ECC
-            case CTC_SHAwECDSA:
-                sName = "shaWithECDSA";
-                type = oidSigType;
-                break;
-
-            case CTC_SHA224wECDSA:
-                sName = "sha224WithECDSA";
-                type = oidSigType;
-                break;
-
-            case CTC_SHA256wECDSA:
-                sName = "sha256WithECDSA";
-                type = oidSigType;
-                break;
-
-            case CTC_SHA384wECDSA:
-                sName = "sha384WithECDSA";
-                type = oidSigType;
-                break;
-
-            case CTC_SHA512wECDSA:
-                sName = "sha512WithECDSA";
-                type = oidSigType;
-                break;
-        #endif /* HAVE_ECC */
-
-            /* oidKeyType */
-        #ifndef NO_DSA
-            case DSAk:
-                sName = "DSA key";
-                type = oidKeyType;
-                break;
-        #endif /* NO_DSA */
-        #ifndef NO_RSA
-            case RSAk:
-                sName = "RSA key";
-                type = oidKeyType;
-                break;
-        #endif /* NO_RSA */
-        #ifdef HAVE_NTRU
-            case NTRUk:
-                sName = "NTRU key";
-                type = oidKeyType;
-                break;
-        #endif /* HAVE_NTRU */
-        #ifdef HAVE_ECC
-            case ECDSAk:
-                sName = "ECDSA key";
-                type = oidKeyType;
-                break;
-        #endif /* HAVE_ECC */
-
-            /* oidBlkType */
-        #ifdef WOLFSSL_AES_128
-            case AES128CBCb:
-                sName = "AES-128-CBC";
-                type = oidBlkType;
-                break;
-        #endif
-        #ifdef WOLFSSL_AES_192
-            case AES192CBCb:
-                sName = "AES-192-CBC";
-                type = oidBlkType;
-                break;
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-            case AES256CBCb:
-                sName = "AES-256-CBC";
-                type = oidBlkType;
-                break;
-        #endif
-
-        #ifndef NO_DES3
-            case NID_des:
-                id = DESb;
-                sName = "DES-CBC";
-                type = oidBlkType;
-                break;
-
-            case NID_des3:
-                id = DES3b;
-                sName = "DES3-CBC";
-                type = oidBlkType;
-                break;
-        #endif /* !NO_DES3 */
-
-        #ifdef HAVE_OCSP
-            case NID_id_pkix_OCSP_basic:
-                id = OCSP_BASIC_OID;
-                sName = "OCSP_basic";
-                type = oidOcspType;
-                break;
-
-            case OCSP_NONCE_OID:
-                sName = "OCSP_nonce";
-                type = oidOcspType;
-                break;
-        #endif /* HAVE_OCSP */
-
-            /* oidCertExtType */
-            case BASIC_CA_OID:
-                sName = "X509 basic ca";
-                type = oidCertExtType;
-                break;
-
-            case ALT_NAMES_OID:
-                sName = "X509 alt names";
-                type = oidCertExtType;
-                break;
-
-            case CRL_DIST_OID:
-                sName = "X509 crl";
-                type = oidCertExtType;
-                break;
-
-            case AUTH_INFO_OID:
-                sName = "X509 auth info";
-                type = oidCertExtType;
-                break;
-
-            case AUTH_KEY_OID:
-                sName = "X509 auth key";
-                type = oidCertExtType;
-                break;
-
-            case SUBJ_KEY_OID:
-                sName = "X509 subject key";
-                type = oidCertExtType;
-                break;
-
-            case KEY_USAGE_OID:
-                sName = "X509 key usage";
-                type = oidCertExtType;
-                break;
-
-            case INHIBIT_ANY_OID:
-                id = INHIBIT_ANY_OID;
-                sName = "X509 inhibit any";
-                type = oidCertExtType;
-                break;
-
-            case NID_ext_key_usage:
-                id = KEY_USAGE_OID;
-                sName = "X509 ext key usage";
-                type = oidCertExtType;
-                break;
-
-            case NID_name_constraints:
-                id = NAME_CONS_OID;
-                sName = "X509 name constraints";
-                type = oidCertExtType;
-                break;
-
-            case NID_certificate_policies:
-                id = CERT_POLICY_OID;
-                sName = "X509 certificate policies";
-                type = oidCertExtType;
-                break;
-
-            /* oidCertAuthInfoType */
-            case AIA_OCSP_OID:
-                sName = "Cert Auth OCSP";
-                type = oidCertAuthInfoType;
-                break;
-
-            case AIA_CA_ISSUER_OID:
-                sName = "Cert Auth CA Issuer";
-                type = oidCertAuthInfoType;
-                break;
-
-            /* oidCertPolicyType */
-            case NID_any_policy:
-                id = CP_ANY_OID;
-                sName = "Cert any policy";
-                type = oidCertPolicyType;
-                break;
-
-                /* oidCertAltNameType */
-            case NID_hw_name_oid:
-                id = HW_NAME_OID;
-                sName = "Hardware name";
-                type = oidCertAltNameType;
-                break;
-
-            /* oidCertKeyUseType */
-            case NID_anyExtendedKeyUsage:
-                id = EKU_ANY_OID;
-                sName = "Cert any extended key";
-                type = oidCertKeyUseType;
-                break;
-
-            case EKU_SERVER_AUTH_OID:
-                sName = "Cert server auth key";
-                type = oidCertKeyUseType;
-                break;
-
-            case EKU_CLIENT_AUTH_OID:
-                sName = "Cert client auth key";
-                type = oidCertKeyUseType;
-                break;
-
-            case EKU_OCSP_SIGN_OID:
-                sName = "Cert OCSP sign key";
-                type = oidCertKeyUseType;
-                break;
-
-            /* oidKdfType */
-            case PBKDF2_OID:
-                sName = "PBKDFv2";
-                type = oidKdfType;
-                break;
-
-                /* oidPBEType */
-            case PBE_SHA1_RC4_128:
-                sName = "PBE shaWithRC4-128";
-                type = oidPBEType;
-                break;
-
-            case PBE_SHA1_DES:
-                sName = "PBE shaWithDES";
-                type = oidPBEType;
-                break;
-
-            case PBE_SHA1_DES3:
-                sName = "PBE shaWithDES3";
-                type = oidPBEType;
-                break;
-
-                /* oidKeyWrapType */
-        #ifdef WOLFSSL_AES_128
-            case AES128_WRAP:
-                sName = "AES-128 wrap";
-                type = oidKeyWrapType;
-                break;
-        #endif
-
-        #ifdef WOLFSSL_AES_192
-            case AES192_WRAP:
-                sName = "AES-192 wrap";
-                type = oidKeyWrapType;
-                break;
-        #endif
-
-        #ifdef WOLFSSL_AES_256
-            case AES256_WRAP:
-                sName = "AES-256 wrap";
-                type = oidKeyWrapType;
-                break;
-        #endif
-
-                /* oidCmsKeyAgreeType */
-        #ifndef NO_SHA
-            case dhSinglePass_stdDH_sha1kdf_scheme:
-                sName = "DH-SHA kdf";
-                type = oidCmsKeyAgreeType;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA224
-            case dhSinglePass_stdDH_sha224kdf_scheme:
-                sName = "DH-SHA224 kdf";
-                type = oidCmsKeyAgreeType;
-                break;
-        #endif
-        #ifndef NO_SHA256
-            case dhSinglePass_stdDH_sha256kdf_scheme:
-                sName = "DH-SHA256 kdf";
-                type = oidCmsKeyAgreeType;
-                break;
-
-        #endif
-        #ifdef WOLFSSL_SHA384
-            case dhSinglePass_stdDH_sha384kdf_scheme:
-                sName = "DH-SHA384 kdf";
-                type = oidCmsKeyAgreeType;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA512
-            case dhSinglePass_stdDH_sha512kdf_scheme:
-                sName = "DH-SHA512 kdf";
-                type = oidCmsKeyAgreeType;
-                break;
-        #endif
-            default:
-                WOLFSSL_MSG("NID not in table");
-                return NULL;
-        }
-
-    #ifdef HAVE_ECC
-         if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) {
-             type = oidCurveType;
-         }
-    #endif /* HAVE_ECC */
-
-        if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
-            WOLFSSL_MSG("Attempted short name is too large");
-            return NULL;
-        }
-
-        oid = OidFromId(id, type, &oidSz);
-
-        /* set object ID to buffer */
-        obj = wolfSSL_ASN1_OBJECT_new();
-        if (obj == NULL) {
-            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
-            return NULL;
-        }
-        obj->type    = id;
-        obj->grp     = type;
-        obj->dynamic = 1;
-        XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
-
-        objBuf[0] = ASN_OBJECT_ID; objSz++;
-        objSz += SetLength(oidSz, objBuf + 1);
-        XMEMCPY(objBuf + objSz, oid, oidSz);
-        objSz     += oidSz;
-        obj->objSz = objSz;
-
-        obj->obj = (byte*)XMALLOC(obj->objSz, NULL, DYNAMIC_TYPE_ASN1);
-        if (obj->obj == NULL) {
-            wolfSSL_ASN1_OBJECT_free(obj);
-            return NULL;
-        }
-        XMEMCPY(obj->obj, objBuf, obj->objSz);
-
-        (void)type;
-
-        return obj;
-    }
-
-
-    /* if no_name is one than use numerical form otherwise can be short name.
-     *
-     * returns the buffer size on success
-     */
-    int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name)
-    {
-        int bufSz;
-
-        WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()");
-
-        if (buf == NULL || bufLen <= 1 || a == NULL) {
-            WOLFSSL_MSG("Bad input argument");
-            return WOLFSSL_FAILURE;
-        }
-
-        if (no_name == 1) {
-            int    length;
-            word32 idx = 0;
-
-            if (a->obj[idx++] != ASN_OBJECT_ID) {
-                WOLFSSL_MSG("Bad ASN1 Object");
-                return WOLFSSL_FAILURE;
-            }
-
-            if (GetLength((const byte*)a->obj, &idx, &length,
-                           a->objSz) < 0 || length < 0) {
-                return ASN_PARSE_E;
-            }
-
-            if (bufLen < MAX_OID_STRING_SZ) {
-                bufSz = bufLen - 1;
-            }
-            else {
-                bufSz = MAX_OID_STRING_SZ;
-            }
-
-            if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
-                        (word32)length)) <= 0) {
-                WOLFSSL_MSG("Error decoding OID");
-                return WOLFSSL_FAILURE;
-            }
-
-        }
-        else { /* return short name */
-            if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) {
-                bufSz = (int)XSTRLEN(a->sName);
-            }
-            else {
-                bufSz = bufLen - 1;
-            }
-            XMEMCPY(buf, a->sName, bufSz);
-        }
-
-        buf[bufSz] = '\0';
-        return bufSz;
-    }
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
-    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
-    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
-    defined(WOLFSSL_HAPROXY)
-
-#ifndef NO_SHA
-    /* One shot SHA1 hash of message.
-     *
-     * d  message to hash
-     * n  size of d buffer
-     * md buffer to hold digest. Should be SHA_DIGEST_SIZE.
-     *
-     * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used.
-     *       When the static buffer is used this function is not thread safe.
-     *
-     * Returns a pointer to the message digest on success and NULL on failure.
-     */
-    unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n,
-            unsigned char *md)
-    {
-        static byte dig[WC_SHA_DIGEST_SIZE];
-        wc_Sha sha;
-
-        WOLFSSL_ENTER("wolfSSL_SHA1");
-
-        if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
-            WOLFSSL_MSG("SHA1 Init failed");
-            return NULL;
-        }
-
-        if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) {
-            WOLFSSL_MSG("SHA1 Update failed");
-            return NULL;
-        }
-
-        if (wc_ShaFinal(&sha, dig) != 0) {
-            WOLFSSL_MSG("SHA1 Final failed");
-            return NULL;
-        }
-
-        wc_ShaFree(&sha);
-
-        if (md != NULL) {
-            XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE);
-            return md;
-        }
-        else {
-            return (unsigned char*)dig;
-        }
-    }
-#endif /* ! NO_SHA */
-
-#ifndef NO_SHA256
-    /* One shot SHA256 hash of message.
-     *
-     * d  message to hash
-     * n  size of d buffer
-     * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
-     *
-     * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
-     *       When the static buffer is used this function is not thread safe.
-     *
-     * Returns a pointer to the message digest on success and NULL on failure.
-     */
-    unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n,
-            unsigned char *md)
-    {
-        static byte dig[WC_SHA256_DIGEST_SIZE];
-        wc_Sha256 sha;
-
-        WOLFSSL_ENTER("wolfSSL_SHA256");
-
-        if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
-            WOLFSSL_MSG("SHA256 Init failed");
-            return NULL;
-        }
-
-        if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) {
-            WOLFSSL_MSG("SHA256 Update failed");
-            return NULL;
-        }
-
-        if (wc_Sha256Final(&sha, dig) != 0) {
-            WOLFSSL_MSG("SHA256 Final failed");
-            return NULL;
-        }
-
-        wc_Sha256Free(&sha);
-
-        if (md != NULL) {
-            XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE);
-            return md;
-        }
-        else {
-            return (unsigned char*)dig;
-        }
-    }
-#endif /* ! NO_SHA256 */
-
-#ifdef WOLFSSL_SHA384
-     /* One shot SHA384 hash of message.
-      *
-      * d  message to hash
-      * n  size of d buffer
-      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
-      *
-      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
-      *       When the static buffer is used this function is not thread safe.
-      *
-      * Returns a pointer to the message digest on success and NULL on failure.
-      */
-     unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n,
-             unsigned char *md)
-     {
-         static byte dig[WC_SHA384_DIGEST_SIZE];
-         wc_Sha384 sha;
-
-         WOLFSSL_ENTER("wolfSSL_SHA384");
-
-         if (wc_InitSha384_ex(&sha, NULL, 0) != 0) {
-             WOLFSSL_MSG("SHA384 Init failed");
-             return NULL;
-         }
-
-         if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) {
-             WOLFSSL_MSG("SHA384 Update failed");
-             return NULL;
-         }
-
-         if (wc_Sha384Final(&sha, dig) != 0) {
-             WOLFSSL_MSG("SHA384 Final failed");
-             return NULL;
-         }
-
-         wc_Sha384Free(&sha);
-
-         if (md != NULL) {
-             XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE);
-             return md;
-         }
-         else {
-             return (unsigned char*)dig;
-         }
-     }
-#endif /* WOLFSSL_SHA384  */
-
-
-#if defined(WOLFSSL_SHA512)
-     /* One shot SHA512 hash of message.
-      *
-      * d  message to hash
-      * n  size of d buffer
-      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
-      *
-      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
-      *       When the static buffer is used this function is not thread safe.
-      *
-      * Returns a pointer to the message digest on success and NULL on failure.
-      */
-     unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n,
-             unsigned char *md)
-     {
-         static byte dig[WC_SHA512_DIGEST_SIZE];
-         wc_Sha512 sha;
-
-         WOLFSSL_ENTER("wolfSSL_SHA512");
-
-         if (wc_InitSha512_ex(&sha, NULL, 0) != 0) {
-             WOLFSSL_MSG("SHA512 Init failed");
-             return NULL;
-         }
-
-         if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) {
-             WOLFSSL_MSG("SHA512 Update failed");
-             return NULL;
-         }
-
-         if (wc_Sha512Final(&sha, dig) != 0) {
-             WOLFSSL_MSG("SHA512 Final failed");
-             return NULL;
-         }
-
-         wc_Sha512Free(&sha);
-
-         if (md != NULL) {
-             XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE);
-             return md;
-         }
-         else {
-             return (unsigned char*)dig;
-         }
-     }
-#endif /* defined(WOLFSSL_SHA512)  */
-
-    char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
-    {
-        int ret;
-
-        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
-
-        FreeDer(&ctx->certificate); /* Make sure previous is free'd */
-        ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE,
-                       ctx->heap);
-        if (ret != 0)
-            return 0;
-
-        XMEMCPY(ctx->certificate->buffer, x->derCert->buffer,
-                x->derCert->length);
-#ifdef KEEP_OUR_CERT
-        if (ctx->ourCert != NULL && ctx->ownOurCert) {
-            FreeX509(ctx->ourCert);
-            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
-        }
-        ctx->ourCert = x;
-        ctx->ownOurCert = 0;
-#endif
-
-        /* Update the available options with public keys. */
-        switch (x->pubKeyOID) {
-            case RSAk:
-                ctx->haveRSA = 1;
-                break;
-        #ifdef HAVE_ED25519
-            case ED25519k:
-        #endif
-            case ECDSAk:
-                ctx->haveECC = 1;
-            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
-                ctx->pkCurveOID = x->pkCurveOID;
-            #endif
-                break;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-
-    #ifndef NO_WOLFSSL_STUB
-    int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) {
-    #ifndef NO_FILESYSTEM
-        XFILE fp;
-
-        WOLFSSL_ENTER("wolfSSL_BIO_new_file");
-
-        if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != NULL))
-        {
-            XFCLOSE(fp);
-        }
-
-        fp = XFOPEN(name, "r");
-        if (fp == NULL)
-            return WOLFSSL_BAD_FILE;
-
-        if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
-            XFCLOSE(fp);
-            return WOLFSSL_BAD_FILE;
-        }
-
-        /* file is closed when bio is free'd */
-        return WOLFSSL_SUCCESS;
-    #else
-        (void)name;
-        (void)b;
-        return WOLFSSL_NOT_IMPLEMENTED;
-    #endif
-    }
-    #endif
-
-#ifdef HAVE_ECC
-    const char * wolfSSL_OBJ_nid2sn(int n) {
-        int i;
-        WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn");
-
-        /* find based on NID and return name */
-        for (i = 0; i < ecc_sets[i].size; i++) {
-            if (n == ecc_sets[i].id) {
-                return ecc_sets[i].name;
-            }
-        }
-        return NULL;
-    }
-
-    int wolfSSL_OBJ_sn2nid(const char *sn) {
-        int i;
-        WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid");
-
-        /* Nginx uses this OpenSSL string. */
-        if (XSTRNCMP(sn, "prime256v1", 10) == 0)
-            sn = "SECP256R1";
-        if (XSTRNCMP(sn, "secp384r1", 10) == 0)
-            sn = "SECP384R1";
-        /* find based on name and return NID */
-        for (i = 0; i < ecc_sets[i].size; i++) {
-            if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
-                return ecc_sets[i].id;
-            }
-        }
-        return -1;
-    }
-#endif /* HAVE_ECC */
-
-    /* Gets the NID value that corresponds with the ASN1 object.
-     *
-     * o ASN1 object to get NID of
-     *
-     * Return NID on success and a negative value on failure
-     */
-    int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) {
-        word32 oid = 0;
-        word32 idx = 0;
-        int id;
-
-        WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
-
-        if (o == NULL) {
-            return -1;
-        }
-
-        if ((id = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) {
-            WOLFSSL_MSG("Issue getting OID of object");
-            return -1;
-        }
-
-        /* get OID type */
-        switch (o->grp) {
-            /* oidHashType */
-            case oidHashType:
-                switch (oid) {
-                #ifdef WOLFSSL_MD2
-                    case MD2h:
-                        return NID_md2;
-                #endif
-                #ifndef NO_MD5
-                    case MD5h:
-                        return NID_md5;
-                #endif
-                #ifndef NO_SHA
-                    case SHAh:
-                        return NID_sha1;
-                #endif
-                    case SHA224h:
-                        return NID_sha224;
-                #ifndef NO_SHA256
-                    case SHA256h:
-                        return NID_sha256;
-                #endif
-                #ifdef WOLFSSL_SHA384
-                    case SHA384h:
-                        return NID_sha384;
-                #endif
-                #ifdef WOLFSSL_SHA512
-                    case SHA512h:
-                        return NID_sha512;
-                #endif
-                }
-                break;
-
-            /*  oidSigType */
-            case oidSigType:
-                switch (oid) {
-                #ifndef NO_DSA
-                    case CTC_SHAwDSA:
-                        return CTC_SHAwDSA;
-                #endif /* NO_DSA */
-                #ifndef NO_RSA
-                    case CTC_MD2wRSA:
-                        return CTC_MD2wRSA;
-                    case CTC_MD5wRSA:
-                        return CTC_MD5wRSA;
-                    case CTC_SHAwRSA:
-                        return CTC_SHAwRSA;
-                    case CTC_SHA224wRSA:
-                        return CTC_SHA224wRSA;
-                    case CTC_SHA256wRSA:
-                        return CTC_SHA256wRSA;
-                    case CTC_SHA384wRSA:
-                        return CTC_SHA384wRSA;
-                    case CTC_SHA512wRSA:
-                        return CTC_SHA512wRSA;
-                #endif /* NO_RSA */
-                #ifdef HAVE_ECC
-                    case CTC_SHAwECDSA:
-                        return CTC_SHAwECDSA;
-                    case CTC_SHA224wECDSA:
-                        return CTC_SHA224wECDSA;
-                    case CTC_SHA256wECDSA:
-                        return CTC_SHA256wECDSA;
-                    case CTC_SHA384wECDSA:
-                        return CTC_SHA384wECDSA;
-                    case CTC_SHA512wECDSA:
-                        return CTC_SHA512wECDSA;
-                #endif /* HAVE_ECC */
-                }
-                break;
-
-            /* oidKeyType */
-            case oidKeyType:
-                switch (oid) {
-                #ifndef NO_DSA
-                    case DSAk:
-                        return DSAk;
-                #endif /* NO_DSA */
-                #ifndef NO_RSA
-                    case RSAk:
-                        return RSAk;
-                #endif /* NO_RSA */
-                #ifdef HAVE_NTRU
-                    case NTRUk:
-                        return NTRUk;
-                #endif /* HAVE_NTRU */
-                #ifdef HAVE_ECC
-                    case ECDSAk:
-                        return ECDSAk;
-                #endif /* HAVE_ECC */
-                }
-                break;
-
-            /* oidBlkType */
-            case oidBlkType:
-                switch (oid) {
-                #ifdef WOLFSSL_AES_128
-                    case AES128CBCb:
-                        return AES128CBCb;
-                #endif
-                #ifdef WOLFSSL_AES_192
-                    case AES192CBCb:
-                        return AES192CBCb;
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    case AES256CBCb:
-                        return AES256CBCb;
-                #endif
-                #ifndef NO_DES3
-                    case DESb:
-                        return NID_des;
-                    case DES3b:
-                        return NID_des3;
-                #endif
-                }
-                break;
-
-        #ifdef HAVE_OCSP
-            case oidOcspType:
-                switch (oid) {
-                    case OCSP_BASIC_OID:
-                        return NID_id_pkix_OCSP_basic;
-                    case OCSP_NONCE_OID:
-                        return OCSP_NONCE_OID;
-                }
-                break;
-        #endif /* HAVE_OCSP */
-
-            /* oidCertExtType */
-            case oidCertExtType:
-                switch (oid) {
-                    case BASIC_CA_OID:
-                        return BASIC_CA_OID;
-                    case ALT_NAMES_OID:
-                        return ALT_NAMES_OID;
-                    case CRL_DIST_OID:
-                        return CRL_DIST_OID;
-                    case AUTH_INFO_OID:
-                        return AUTH_INFO_OID;
-                    case AUTH_KEY_OID:
-                        return AUTH_KEY_OID;
-                    case SUBJ_KEY_OID:
-                        return SUBJ_KEY_OID;
-                    case INHIBIT_ANY_OID:
-                        return INHIBIT_ANY_OID;
-                    case KEY_USAGE_OID:
-                        return NID_ext_key_usage;
-                    case NAME_CONS_OID:
-                        return NID_name_constraints;
-                    case CERT_POLICY_OID:
-                        return NID_certificate_policies;
-                }
-                break;
-
-            /* oidCertAuthInfoType */
-            case oidCertAuthInfoType:
-                switch (oid) {
-                    case AIA_OCSP_OID:
-                        return AIA_OCSP_OID;
-                    case AIA_CA_ISSUER_OID:
-                        return AIA_CA_ISSUER_OID;
-                }
-                break;
-
-            /* oidCertPolicyType */
-            case oidCertPolicyType:
-                switch (oid) {
-                    case CP_ANY_OID:
-                        return NID_any_policy;
-                }
-                break;
-
-            /* oidCertAltNameType */
-            case oidCertAltNameType:
-                switch (oid) {
-                    case HW_NAME_OID:
-                        return NID_hw_name_oid;
-                }
-                break;
-
-            /* oidCertKeyUseType */
-            case oidCertKeyUseType:
-                switch (oid) {
-                    case EKU_ANY_OID:
-                        return NID_anyExtendedKeyUsage;
-                    case EKU_SERVER_AUTH_OID:
-                        return EKU_SERVER_AUTH_OID;
-                    case EKU_CLIENT_AUTH_OID:
-                        return EKU_CLIENT_AUTH_OID;
-                    case EKU_OCSP_SIGN_OID:
-                        return EKU_OCSP_SIGN_OID;
-                }
-                break;
-
-            /* oidKdfType */
-            case oidKdfType:
-                switch (oid) {
-                    case PBKDF2_OID:
-                        return PBKDF2_OID;
-                }
-                break;
-
-            /* oidPBEType */
-            case oidPBEType:
-                switch (oid) {
-                    case PBE_SHA1_RC4_128:
-                        return PBE_SHA1_RC4_128;
-                    case PBE_SHA1_DES:
-                        return PBE_SHA1_DES;
-                    case PBE_SHA1_DES3:
-                        return PBE_SHA1_DES3;
-                }
-                break;
-
-            /* oidKeyWrapType */
-            case oidKeyWrapType:
-                switch (oid) {
-                #ifdef WOLFSSL_AES_128
-                    case AES128_WRAP:
-                        return AES128_WRAP;
-                #endif
-                #ifdef WOLFSSL_AES_192
-                    case AES192_WRAP:
-                        return AES192_WRAP;
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    case AES256_WRAP:
-                        return AES256_WRAP;
-                #endif
-                }
-                break;
-
-            /* oidCmsKeyAgreeType */
-            case oidCmsKeyAgreeType:
-                switch (oid) {
-                    #ifndef NO_SHA
-                    case dhSinglePass_stdDH_sha1kdf_scheme:
-                        return dhSinglePass_stdDH_sha1kdf_scheme;
-                    #endif
-                    #ifdef WOLFSSL_SHA224
-                    case dhSinglePass_stdDH_sha224kdf_scheme:
-                        return dhSinglePass_stdDH_sha224kdf_scheme;
-                    #endif
-                    #ifndef NO_SHA256
-                    case dhSinglePass_stdDH_sha256kdf_scheme:
-                        return dhSinglePass_stdDH_sha256kdf_scheme;
-                    #endif
-                    #ifdef WOLFSSL_SHA384
-                    case dhSinglePass_stdDH_sha384kdf_scheme:
-                        return dhSinglePass_stdDH_sha384kdf_scheme;
-                    #endif
-                    #ifdef WOLFSSL_SHA512
-                    case dhSinglePass_stdDH_sha512kdf_scheme:
-                        return dhSinglePass_stdDH_sha512kdf_scheme;
-                    #endif
-                }
-                break;
-
-            default:
-                WOLFSSL_MSG("NID not in table");
-                return -1;
-        }
-
-        return -1;
-    }
-
-
-#ifndef NO_WOLFSSL_STUB
-    char * wolfSSL_OBJ_nid2ln(int n)
-    {
-        (void)n;
-        WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln");
-        WOLFSSL_STUB("OBJ_nid2ln");
-
-        return NULL;
-    }
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-    int wolfSSL_OBJ_txt2nid(const char* s)
-    {
-        (void)s;
-        WOLFSSL_STUB("OBJ_txt2nid");
-
-        return 0;
-    }
-#endif
-
-    /* compatibility function. It's intended use is to remove OID's from an
-     * internal table that have been added with OBJ_create. wolfSSL manages it's
-     * own interenal OID values and does not currently support OBJ_create. */
-    void wolfSSL_OBJ_cleanup(void)
-    {
-        WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()");
-    }
-
-
-    #ifndef NO_WOLFSSL_STUB
-    void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) {
-        WOLFSSL_ENTER("wolfSSL_set_verify_depth");
-#ifndef OPENSSL_EXTRA
-        (void)ssl;
-        (void)depth;
-        WOLFSSL_STUB("wolfSSL_set_verify_depth");
-#else
-        ssl->options.verifyDepth = (byte)depth;
-#endif
-    }
-    #endif
-
-
-    #ifndef NO_WOLFSSL_STUB
-    WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) {
-        (void)ne;
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
-        WOLFSSL_STUB("X509_NAME_ENTRY_get_object");
-
-        return NULL;
-    }
-    #endif
-
-    WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(
-                                             WOLFSSL_X509_NAME *name, int loc) {
-
-        int maxLoc = name->fullName.fullNameLen;
-
-        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry");
-
-        if (loc < 0 || loc > maxLoc) {
-            WOLFSSL_MSG("Bad argument");
-            return NULL;
-        }
-
-        /* DC component */
-        if (name->fullName.dcMode){
-            if (name->fullName.fullName != NULL){
-                if (loc == name->fullName.dcNum){
-                    name->cnEntry.data.data   = &name->fullName.fullName[name->fullName.cIdx];
-                    name->cnEntry.data.length = name->fullName.cLen;
-                    name->cnEntry.nid         = ASN_COUNTRY_NAME;
-                } else {
-                    name->cnEntry.data.data   = &name->fullName.fullName[name->fullName.dcIdx[loc]];
-                    name->cnEntry.data.length = name->fullName.dcLen[loc];
-                    name->cnEntry.nid         = ASN_DOMAIN_COMPONENT;
-                }
-            }
-            name->cnEntry.data.type = CTC_UTF8;
-            name->cnEntry.set       = 1;
-            return &(name->cnEntry);
-
-         /* common name index case */
-        } else if (loc == name->fullName.cnIdx) {
-            /* get CN shortcut from x509 since it has null terminator */
-            name->cnEntry.data.data   = name->x509->subjectCN;
-            name->cnEntry.data.length = name->fullName.cnLen;
-            name->cnEntry.data.type   = CTC_UTF8;
-            name->cnEntry.nid         = ASN_COMMON_NAME;
-            name->cnEntry.set         = 1;
-            return &(name->cnEntry);
-        }
-
-        /* additionall cases to check for go here */
-
-        WOLFSSL_MSG("Entry not found or implemented");
-        (void)name;
-        (void)loc;
-
-        return NULL;
-    }
-
-    #ifndef NO_WOLFSSL_STUB
-    void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){
-        (void) sk;
-        (void) f;
-        WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free");
-        WOLFSSL_STUB("sk_X509_NAME_pop_free");
-    }
-    #endif
-    #ifndef NO_WOLFSSL_STUB
-    int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key){
-        (void) x509;
-        (void) key;
-        WOLFSSL_ENTER("wolfSSL_X509_check_private_key");
-        WOLFSSL_STUB("X509_check_private_key");
-
-        return WOLFSSL_SUCCESS;
-    }
-
-    WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ){
-        (void) sk;
-        WOLFSSL_ENTER("wolfSSL_dup_CA_list");
-        WOLFSSL_STUB("SSL_dup_CA_list");
-
-        return NULL;
-    }
-    #endif
-
-#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
-#endif /* OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-
-/* wolfSSL uses negative values for error states. This function returns an
- * unsigned type so the value returned is the absolute value of the error.
- */
-unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
-
-    (void)line;
-    (void)file;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY)
-    {
-        int ret;
-
-        if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
-            WOLFSSL_MSG("Issue peeking at error node in queue");
-            return 0;
-        }
-    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-        if (ret == -ASN_NO_PEM_HEADER)
-            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
-    #endif
-        return (unsigned long)ret;
-    }
-#else
-    return (unsigned long)(0 - NOT_COMPILED_IN);
-#endif
-}
-
-
-#ifndef NO_CERTS
-int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
-
-    if (ctx == NULL || pkey == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    if (pkey->pkey.ptr != NULL) {
-        /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
-        return wolfSSL_CTX_use_PrivateKey_buffer(ctx,
-                                       (const unsigned char*)pkey->pkey.ptr,
-                                       pkey->pkey_sz, SSL_FILETYPE_ASN1);
-    }
-
-    WOLFSSL_MSG("wolfSSL private key not set");
-    return BAD_FUNC_ARG;
-}
-#endif /* !NO_CERTS */
-
-
-void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
-    #ifdef HAVE_EX_DATA
-    if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) {
-        return ctx->ex_data[idx];
-    }
-    #else
-    (void)ctx;
-    (void)idx;
-    #endif
-    return NULL;
-}
-
-int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
-                                void* c)
-{
-    static int ctx_idx = 0;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
-    (void)idx;
-    (void)arg;
-    (void)a;
-    (void)b;
-    (void)c;
-
-    return ctx_idx++;
-}
-
-
-/* Return the index that can be used for the WOLFSSL structure to store
- * application data.
- *
- */
-int wolfSSL_get_ex_new_index(long argValue, void* arg,
-        WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2,
-        WOLFSSL_CRYPTO_EX_free* cb3)
-{
-    static int ssl_idx = 0;
-
-    WOLFSSL_ENTER("wolfSSL_get_ex_new_index");
-
-    (void)argValue;
-    (void)arg;
-    (void)cb1;
-    (void)cb2;
-    (void)cb3;
-
-    return ssl_idx++;
-}
-
-
-int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data");
-    #ifdef HAVE_EX_DATA
-    if (ctx != NULL && idx < MAX_EX_DATA)
-    {
-        ctx->ex_data[idx] = data;
-        return WOLFSSL_SUCCESS;
-    }
-    #else
-    (void)ctx;
-    (void)idx;
-    (void)data;
-    #endif
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Returns char* to app data stored in ex[0].
- *
- * ssl WOLFSSL structure to get app data from
- */
-void* wolfSSL_get_app_data(const WOLFSSL *ssl)
-{
-    /* checkout exdata stuff... */
-    WOLFSSL_ENTER("wolfSSL_get_app_data");
-
-    return wolfSSL_get_ex_data(ssl, 0);
-}
-
-
-/* Set ex array 0 to have app data
- *
- * ssl WOLFSSL struct to set app data in
- * arg data to be stored
- *
- * Returns SSL_SUCCESS on sucess and SSL_FAILURE on failure
- */
-int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
-    WOLFSSL_ENTER("wolfSSL_set_app_data");
-
-    return wolfSSL_set_ex_data(ssl, 0, arg);
-}
-
-
-int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
-{
-    WOLFSSL_ENTER("wolfSSL_set_ex_data");
-#if defined(HAVE_EX_DATA) || defined(FORTRESS)
-    if (ssl != NULL && idx < MAX_EX_DATA)
-    {
-        ssl->ex_data[idx] = data;
-        return WOLFSSL_SUCCESS;
-    }
-#else
-    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
-    (void)ssl;
-    (void)idx;
-    (void)data;
-#endif
-    return WOLFSSL_FAILURE;
-}
-
-
-
-void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_get_ex_data");
-#if defined(HAVE_EX_DATA) || defined(FORTRESS)
-    if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0)
-        return ssl->ex_data[idx];
-#else
-    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
-    (void)ssl;
-    (void)idx;
-#endif
-    return 0;
-}
-
-#ifndef NO_DSA
-WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x,
-        pem_password_cb *cb, void *u)
-{
-    WOLFSSL_DSA* dsa;
-    DsaKey* key;
-    int    length;
-    unsigned char*  buf;
-    word32 bufSz;
-    int ret;
-    word32 idx = 0;
-    DerBuffer* pDer;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams");
-
-    ret = wolfSSL_BIO_get_mem_data(bp, &buf);
-    if (ret <= 0) {
-        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
-        return NULL;
-    }
-
-    bufSz = (word32)ret;
-
-    if (cb != NULL || u != NULL) {
-        /*
-         * cb is for a call back when encountering encrypted PEM files
-         * if cb == NULL and u != NULL then u = null terminated password string
-         */
-        WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM");
-    }
-
-    if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL,
-                    NULL)) < 0 ) {
-        WOLFSSL_MSG("Issue converting from PEM to DER");
-        return NULL;
-    }
-
-    if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) {
-        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
-        FreeDer(&pDer);
-        return NULL;
-    }
-
-    dsa = wolfSSL_DSA_new();
-    if (dsa == NULL) {
-        FreeDer(&pDer);
-        WOLFSSL_MSG("Error creating DSA struct");
-        return NULL;
-    }
-
-    key = (DsaKey*)dsa->internal;
-    if (key == NULL) {
-        FreeDer(&pDer);
-        wolfSSL_DSA_free(dsa);
-        WOLFSSL_MSG("Error finding DSA key struct");
-        return NULL;
-    }
-
-    if (GetInt(&key->p,  pDer->buffer, &idx, pDer->length) < 0 ||
-        GetInt(&key->q,  pDer->buffer, &idx, pDer->length) < 0 ||
-        GetInt(&key->g,  pDer->buffer, &idx, pDer->length) < 0 ) {
-        WOLFSSL_MSG("dsa key error");
-        FreeDer(&pDer);
-        wolfSSL_DSA_free(dsa);
-        return NULL;
-    }
-
-    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa p key error");
-        FreeDer(&pDer);
-        wolfSSL_DSA_free(dsa);
-        return NULL;
-    }
-
-    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa q key error");
-        FreeDer(&pDer);
-        wolfSSL_DSA_free(dsa);
-        return NULL;
-    }
-
-    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("dsa g key error");
-        FreeDer(&pDer);
-        wolfSSL_DSA_free(dsa);
-        return NULL;
-    }
-
-    if (x != NULL) {
-        *x = dsa;
-    }
-
-    FreeDer(&pDer);
-    return dsa;
-}
-#endif /* NO_DSA */
-
-#define WOLFSSL_BIO_INCLUDED
-#include "src/bio.c"
-
-/* Begin functions for openssl/buffer.h */
-WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void)
-{
-    WOLFSSL_BUF_MEM* buf;
-    buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL,
-                                                        DYNAMIC_TYPE_OPENSSL);
-    if (buf) {
-        XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM));
-    }
-    return buf;
-}
-
-
-/* returns length of buffer on success */
-int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len)
-{
-    int len_int = (int)len;
-    int mx;
-
-    /* verify provided arguments */
-    if (buf == NULL || len_int < 0) {
-        return 0; /* BAD_FUNC_ARG; */
-    }
-
-    /* check to see if fits in existing length */
-    if (buf->length > len) {
-        buf->length = len;
-        return len_int;
-    }
-
-    /* check to see if fits in max buffer */
-    if (buf->max >= len) {
-        if (buf->data != NULL) {
-            XMEMSET(&buf->data[buf->length], 0, len - buf->length);
-        }
-        buf->length = len;
-        return len_int;
-    }
-
-    /* expand size, to handle growth */
-    mx = (len_int + 3) / 3 * 4;
-
-    /* use realloc */
-    buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buf->data == NULL) {
-        return 0; /* ERR_R_MALLOC_FAILURE; */
-    }
-
-    buf->max = mx;
-    XMEMSET(&buf->data[buf->length], 0, len - buf->length);
-    buf->length = len;
-
-    return len_int;
-}
-
-void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf)
-{
-    if (buf) {
-        if (buf->data) {
-            XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            buf->data = NULL;
-        }
-        buf->max = 0;
-        buf->length = 0;
-        XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
-    }
-}
-/* End Functions for openssl/buffer.h */
-
-#endif /* OPENSSL_EXTRA */
-
-
-#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
-    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
-
-WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
-{
-#ifndef NO_FILESYSTEM
-    WOLFSSL_BIO* bio;
-    XFILE fp;
-
-    WOLFSSL_ENTER("wolfSSL_BIO_new_file");
-
-    fp = XFOPEN(filename, mode);
-    if (fp == NULL)
-        return NULL;
-
-    bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
-    if (bio == NULL) {
-        XFCLOSE(fp);
-        return bio;
-    }
-
-    if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
-        XFCLOSE(fp);
-        wolfSSL_BIO_free(bio);
-        bio = NULL;
-    }
-
-    /* file is closed when BIO is free'd */
-    return bio;
-#else
-    (void)filename;
-    (void)mode;
-    return NULL;
-#endif /* NO_FILESYSTEM */
-}
-
-
-#ifndef NO_DH
-WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x,
-        pem_password_cb *cb, void *u)
-{
-#ifndef NO_FILESYSTEM
-    WOLFSSL_DH* localDh = NULL;
-    unsigned char* mem  = NULL;
-    word32 size;
-    long   sz;
-    int    ret;
-    DerBuffer *der = NULL;
-    byte*  p = NULL;
-    byte*  g = NULL;
-    word32 pSz = MAX_DH_SIZE;
-    word32 gSz = MAX_DH_SIZE;
-    int    memAlloced = 0;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams");
-    (void)cb;
-    (void)u;
-
-    if (bio == NULL) {
-        WOLFSSL_MSG("Bad Function Argument bio is NULL");
-        return NULL;
-    }
-
-    if (bio->type == WOLFSSL_BIO_MEMORY) {
-        /* Use the buffer directly. */
-        ret = wolfSSL_BIO_get_mem_data(bio, &mem);
-        if (mem == NULL || ret <= 0) {
-            WOLFSSL_MSG("Failed to get data from bio struct");
-            goto end;
-        }
-        size = ret;
-    }
-    else if (bio->type == WOLFSSL_BIO_FILE) {
-        /* Read whole file into a new buffer. */
-        XFSEEK(bio->file, 0, SEEK_END);
-        sz = XFTELL(bio->file);
-        XFSEEK(bio->file, 0, SEEK_SET);
-        if (sz <= 0L)
-            goto end;
-        mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM);
-        if (mem == NULL)
-            goto end;
-        memAlloced = 1;
-
-        if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0)
-            goto end;
-        size = (word32)sz;
-    }
-    else {
-        WOLFSSL_MSG("BIO type not supported for reading DH parameters");
-        goto end;
-    }
-
-    ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL);
-    if (ret != 0)
-        goto end;
-
-    /* Use the object passed in, otherwise allocate a new object */
-    if (x != NULL)
-        localDh = *x;
-    if (localDh == NULL) {
-        localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL,
-                                       DYNAMIC_TYPE_OPENSSL);
-        if (localDh == NULL)
-            goto end;
-        XMEMSET(localDh, 0, sizeof(WOLFSSL_DH));
-    }
-
-    /* Load data in manually */
-    p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (p == NULL || g == NULL)
-        goto end;
-
-    /* Extract the p and g as data from the DER encoded DH parameters. */
-    ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz);
-    if (ret != 0) {
-        if (x != NULL && localDh != *x)
-            XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL);
-        localDh = NULL;
-        goto end;
-    }
-
-    if (x != NULL)
-        *x = localDh;
-
-    /* Put p and g in as big numbers. */
-    if (localDh->p != NULL) {
-        wolfSSL_BN_free(localDh->p);
-        localDh->p = NULL;
-    }
-    if (localDh->g != NULL) {
-        wolfSSL_BN_free(localDh->g);
-        localDh->g = NULL;
-    }
-    localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL);
-    localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL);
-    if (localDh->p == NULL || localDh->g == NULL) {
-        if (x != NULL && localDh != *x)
-            wolfSSL_DH_free(localDh);
-        localDh = NULL;
-    }
-
-end:
-    if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM);
-    if (der != NULL) FreeDer(&der);
-    XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    return localDh;
-#else
-    (void)bio;
-    (void)x;
-    (void)cb;
-    (void)u;
-    return NULL;
-#endif
-}
-#endif
-
-#ifdef WOLFSSL_CERT_GEN
-
-#ifdef WOLFSSL_CERT_REQ
-/* writes the x509 from x to the WOLFSSL_BIO bp
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
- */
-int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
-{
-    byte* pem;
-    int   pemSz = 0;
-    const unsigned char* der;
-    int derSz;
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()");
-
-    if (x == NULL || bp == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    der = wolfSSL_X509_get_der(x, &derSz);
-    if (der == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* get PEM size */
-    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE);
-    if (pemSz < 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* create PEM buffer and convert from DER */
-    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pem == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) {
-        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* write the PEM to BIO */
-    ret = wolfSSL_BIO_write(bp, pem, pemSz);
-    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (ret <= 0) return WOLFSSL_FAILURE;
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_CERT_REQ */
-
-
-/* writes the x509 from x to the WOLFSSL_BIO bp
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
- */
-int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
-{
-    byte* pem;
-    int   pemSz = 0;
-    const unsigned char* der;
-    int derSz;
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
-
-    if (bp == NULL || x == NULL) {
-        WOLFSSL_MSG("NULL argument passed in");
-        return WOLFSSL_FAILURE;
-    }
-
-    der = wolfSSL_X509_get_der(x, &derSz);
-    if (der == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* get PEM size */
-    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
-    if (pemSz < 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* create PEM buffer and convert from DER */
-    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pem == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
-        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* write the PEM to BIO */
-    ret = wolfSSL_BIO_write(bp, pem, pemSz);
-    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (ret <= 0) return WOLFSSL_FAILURE;
-    return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_CERT_GEN */
-
-int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert)
-{
-    byte* pem;
-    int   pemSz = 0;
-    const unsigned char* der;
-    int derSz;
-    int ret;
-
-    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
-
-    if (bio == NULL || cert == NULL) {
-        WOLFSSL_MSG("NULL argument passed in");
-        return WOLFSSL_FAILURE;
-    }
-
-    der = wolfSSL_X509_get_der(cert, &derSz);
-    if (der == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* get PEM size */
-    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
-    if (pemSz < 0) {
-        return WOLFSSL_FAILURE;
-    }
-
-    /* create PEM buffer and convert from DER */
-    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pem == NULL) {
-        return WOLFSSL_FAILURE;
-    }
-    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
-        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return WOLFSSL_FAILURE;
-    }
-
-    /* write the PEM to BIO */
-    ret = wolfSSL_BIO_write(bio, pem, pemSz);
-    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (ret <= 0) return WOLFSSL_FAILURE;
-    return WOLFSSL_SUCCESS;
-}
-
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_DH)
-/* Intialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */
-long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
-{
-    int pSz, gSz;
-    byte *p, *g;
-    int ret=0;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
-
-    if(!ctx || !dh)
-        return BAD_FUNC_ARG;
-
-    /* Get needed size for p and g */
-    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
-    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
-
-    if(pSz <= 0 || gSz <= 0)
-        return WOLFSSL_FATAL_ERROR;
-
-    p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if(!p)
-        return MEMORY_E;
-
-    g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if(!g) {
-        XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-        return MEMORY_E;
-    }
-
-    pSz = wolfSSL_BN_bn2bin(dh->p, p);
-    gSz = wolfSSL_BN_bn2bin(dh->g, g);
-
-    if(pSz >= 0 && gSz >= 0) /* Conversion successful */
-        ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
-
-    XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-
-    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
-}
-#endif /* OPENSSL_EXTRA && !NO_DH */
-
-
-/* returns the enum value associated with handshake state
- *
- * ssl the WOLFSSL structure to get state of
- */
-int wolfSSL_get_state(const WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_state");
-
-    if (ssl == NULL) {
-        WOLFSSL_MSG("Null argument passed in");
-        return SSL_FAILURE;
-    }
-
-    return ssl->options.handShakeState;
-}
-#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)
-
-/* Returns the verifyCallback from the ssl structure if successful.
-Returns NULL otherwise. */
-VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_verify_callback()");
-    if (ssl) {
-        return ssl->verifyCallback;
-    }
-    return NULL;
-}
-
-/* Creates a new bio pair.
-Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/
-int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
-                                         WOLFSSL_BIO **bio2_p, size_t writebuf2)
-{
-    WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL;
-    int ret = 1;
-
-    WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()");
-
-    if (bio1_p == NULL || bio2_p == NULL) {
-        WOLFSSL_MSG("Bad Function Argument");
-        return BAD_FUNC_ARG;
-    }
-
-    /* set up the new bio structures and write buf sizes */
-    if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
-        WOLFSSL_MSG("Bio allocation failed");
-        ret = WOLFSSL_FAILURE;
-    }
-    if (ret) {
-        if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
-            WOLFSSL_MSG("Bio allocation failed");
-            ret = WOLFSSL_FAILURE;
-        }
-    }
-    if (ret && writebuf1) {
-        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) {
-            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
-        }
-    }
-    if (ret && writebuf2) {
-        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) {
-            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
-        }
-    }
-
-    if (ret) {
-        if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) {
-            *bio1_p = bio1;
-            *bio2_p = bio2;
-        }
-    }
-    if (!ret) {
-        wolfSSL_BIO_free(bio1);
-        bio1 = NULL;
-        wolfSSL_BIO_free(bio2);
-        bio2 = NULL;
-    }
-    return ret;
-}
-
-
-#if !defined(NO_RSA)
-/* Converts an rsa key from a bio buffer into an internal rsa structure.
-Returns a pointer to the new WOLFSSL_RSA structure. */
-WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
-{
-    const unsigned char* bioMem = NULL;
-    int bioMemSz = 0;
-    WOLFSSL_RSA* key = NULL;
-    unsigned char maxKeyBuf[4096];
-    unsigned char* bufPtr = NULL;
-    unsigned char* extraBioMem = NULL;
-    int extraBioMemSz = 0;
-    int derLength = 0;
-    int j = 0, i = 0;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()");
-
-    if (bio == NULL) {
-        WOLFSSL_MSG("Bad Function Argument");
-        return NULL;
-    }
-    (void)out;
-
-    bioMemSz = wolfSSL_BIO_pending(bio);
-    if (bioMemSz <= 0) {
-        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
-        return NULL;
-    }
-
-    bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (bioMem == NULL) {
-        WOLFSSL_MSG("Malloc failure");
-        return NULL;
-    }
-
-    bufPtr = maxKeyBuf;
-    if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) {
-        if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMem, bioMemSz)) == NULL) {
-            XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return NULL;
-        }
-
-        /* This function is used to get the total length of the rsa key. */
-        derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr);
-
-        /* Write extra data back into bio object if necessary. */
-        extraBioMemSz = (bioMemSz - derLength);
-        if (extraBioMemSz > 0) {
-            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-            if (extraBioMem == NULL) {
-                WOLFSSL_MSG("Malloc failure");;
-                XFREE((unsigned char*)extraBioMem, bio->heap, 
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE((unsigned char*)bioMem, bio->heap, 
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                return NULL;
-            }
-
-            for (i = derLength; i < bioMemSz; i++) {
-                *(extraBioMem + j) = *(bioMem + i);
-                j++;
-            }
-
-            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
-            if (wolfSSL_BIO_pending(bio) <= 0) {
-                WOLFSSL_MSG("Failed to write memory to bio");
-                XFREE((unsigned char*)extraBioMem, bio->heap, 
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE((unsigned char*)bioMem, bio->heap, 
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                return NULL;
-            }
-            XFREE((unsigned char*)extraBioMem, bio->heap, 
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-        }
-
-        if (out != NULL && key != NULL) {
-            *out = key;
-        }
-    }
-    XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return key;
-}
-#endif
-
-
-/* Adds the ASN1 certificate to the user ctx.
-Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
-int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, 
-                                                       const unsigned char *der)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()");
-    if (der != NULL && ctx != NULL) {
-        if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, 
-                                      WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
-            return WOLFSSL_SUCCESS;
-        }
-
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-#if !defined(NO_RSA) && !defined(HAVE_FAST_RSA)
-/* Adds the rsa private key to the user ctx.
-Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
-int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
-{
-    int ret;
-    int derSize;
-    unsigned char maxDerBuf[4096];
-    unsigned char* key = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()");
-
-    if (ctx == NULL || rsa == NULL) {
-        WOLFSSL_MSG("one or more inputs were NULL");
-        return BAD_FUNC_ARG;
-    }
-    key = maxDerBuf;
-    /* convert RSA struct to der encoded buffer and get the size */
-    if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) {
-        WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
-        return WOLFSSL_FAILURE;
-    }
-    ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf, 
-                                                    derSize, SSL_FILETYPE_ASN1);
-    if (ret != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
-        return WOLFSSL_FAILURE;
-    }
-    return ret;
-}
-#endif /* NO_RSA && !HAVE_FAST_RSA */
-
-
-/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
-Returns pointer to private EVP_PKEY struct upon success, NULL if there
-is a failure.*/
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
-                                                         WOLFSSL_EVP_PKEY** out)
-{
-    unsigned char* mem = NULL;
-    int memSz = 0;
-    WOLFSSL_EVP_PKEY* key = NULL;
-    int i = 0, j = 0;
-    unsigned char* extraBioMem = NULL;
-    int extraBioMemSz = 0;
-    int derLength = 0;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()");
-
-    if (bio == NULL) {
-        return NULL;
-    }
-    (void)out;
-
-    memSz = wolfSSL_BIO_pending(bio);
-    if (memSz <= 0) {
-        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
-        return NULL;
-    }
-
-    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (mem == NULL) {
-        WOLFSSL_MSG("Malloc failure");
-        return NULL;
-    }
-
-    if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
-        /* Determines key type and returns the new private EVP_PKEY object */
-        if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) {
-            WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
-            XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return NULL;
-        }
-
-        /* Write extra data back into bio object if necessary. */
-        derLength = key->pkey_sz;
-        extraBioMemSz = (memSz - derLength);
-        if (extraBioMemSz > 0) {
-            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-            if (extraBioMem == NULL) {
-                WOLFSSL_MSG("Malloc failure");
-                XFREE((unsigned char*)extraBioMem, bio->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return NULL;
-            }
-
-            for (i = derLength; i < memSz; i++) {
-                *(extraBioMem + j) = *(mem + i);
-                j++;
-            }
-
-            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
-            if (wolfSSL_BIO_pending(bio) <= 0) {
-                WOLFSSL_MSG("Failed to write memory to bio");
-                XFREE((unsigned char*)extraBioMem, bio->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return NULL;
-            }
-            XFREE((unsigned char*)extraBioMem, bio->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-        }
-
-        if (out != NULL && key != NULL) {
-            *out = key;
-        }
-    }
-    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return key;
-}
-
-
-/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- * on fail */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
-                                                  unsigned char** in, long inSz)
-{
-    WOLFSSL_EVP_PKEY* pkey = NULL;
-    const unsigned char* mem;
-    long memSz = inSz;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()");
-
-    if (in == NULL || inSz < 0) {
-        WOLFSSL_MSG("Bad argument");
-        return NULL;
-    }
-    mem = *in;
-
-    #if !defined(NO_RSA)
-    {
-        RsaKey rsa;
-        word32 keyIdx = 0;
-
-        /* test if RSA key */
-        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
-            wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
-            wc_FreeRsaKey(&rsa);
-            pkey = wolfSSL_PKEY_new();
-            if (pkey != NULL) {
-                pkey->pkey_sz = keyIdx;
-                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
-                        DYNAMIC_TYPE_PRIVATE_KEY);
-                if (pkey->pkey.ptr == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
-                pkey->type = EVP_PKEY_RSA;
-                if (out != NULL) {
-                    *out = pkey;
-                }
-
-                pkey->ownRsa = 1;
-                pkey->rsa = wolfSSL_RSA_new();
-                if (pkey->rsa == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-
-                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
-                            (const unsigned char*)pkey->pkey.ptr,
-                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-
-                return pkey;
-            }
-        }
-        wc_FreeRsaKey(&rsa);
-    }
-    #endif /* NO_RSA */
-
-    #ifdef HAVE_ECC
-    {
-        word32  keyIdx = 0;
-        ecc_key ecc;
-
-        /* test if ecc key */
-        if (wc_ecc_init(&ecc) == 0 &&
-            wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
-            wc_ecc_free(&ecc);
-            pkey = wolfSSL_PKEY_new();
-            if (pkey != NULL) {
-                pkey->pkey_sz = keyIdx;
-                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
-                        DYNAMIC_TYPE_PRIVATE_KEY);
-                if (pkey->pkey.ptr == NULL) {
-                    wolfSSL_EVP_PKEY_free(pkey);
-                    return NULL;
-                }
-                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
-                pkey->type = EVP_PKEY_EC;
-                if (out != NULL) {
-                    *out = pkey;
-                }
-                return pkey;
-            }
-        }
-        wc_ecc_free(&ecc);
-    }
-    #endif /* HAVE_ECC */
-    return pkey;
-}
-#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
-
-
-/* stunnel compatibility functions*/
-#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) \
-                          || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)))
-void wolfSSL_ERR_remove_thread_state(void* pid)
-{
-    (void) pid;
-    return;
-}
-
-#ifndef NO_FILESYSTEM
-/***TBD ***/
-void wolfSSL_print_all_errors_fp(XFILE *fp)
-{
-    (void)fp;
-}
-#endif
-
-int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data");
-#ifdef HAVE_EX_DATA
-    if(session != NULL && idx < MAX_EX_DATA) {
-        session->ex_data[idx] = data;
-        return WOLFSSL_SUCCESS;
-    }
-#else
-    (void)session;
-    (void)idx;
-    (void)data;
-#endif
-    return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1,
-       void* cb2, CRYPTO_free_func* cb3)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index");
-    (void)idx;
-    (void)cb1;
-    (void)cb2;
-    (void)cb3;
-    if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) {
-        return 0;
-    }
-    else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) {
-        return 1;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data");
-#ifdef HAVE_EX_DATA
-    if (session != NULL && idx < MAX_EX_DATA && idx >= 0)
-        return session->ex_data[idx];
-#else
-    (void)session;
-    (void)idx;
-#endif
-    return NULL;
-}
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
-                                void *(*r) (void *, size_t, const char *,
-                                            int), void (*f) (void *))
-{
-    (void) m;
-    (void) r;
-    (void) f;
-    WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions");
-    WOLFSSL_STUB("CRYPTO_set_mem_ex_functions");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-
-void wolfSSL_CRYPTO_cleanup_all_ex_data(void){
-    WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data");
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
-                           void (*callback) (int, int, void *), void *cb_arg)
-{
-    (void)prime_len;
-    (void)generator;
-    (void)callback;
-    (void)cb_arg;
-    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters");
-    WOLFSSL_STUB("DH_generate_parameters");
-
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator,
-                           void (*callback) (int, int, void *))
-{
-    (void)prime_len;
-    (void)generator;
-    (void)callback;
-    (void)dh;
-    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex");
-    WOLFSSL_STUB("DH_generate_parameters_ex");
-
-    return -1;
-}
-#endif
-
-void wolfSSL_ERR_load_crypto_strings(void)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
-    /* Do nothing */
-    return;
-}
-
-#ifndef NO_WOLFSSL_STUB
-unsigned long wolfSSL_ERR_peek_last_error(void)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    {
-        int ret;
-
-        if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
-            WOLFSSL_MSG("Issue peeking at error node in queue");
-            return 0;
-        }
-        if (ret == -ASN_NO_PEM_HEADER)
-            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
-        return (unsigned long)ret;
-    }
-#else
-    return (unsigned long)(0 - NOT_COMPILED_IN);
-#endif
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_FIPS_mode(void)
-{
-    WOLFSSL_ENTER("wolfSSL_FIPS_mode");
-    WOLFSSL_STUB("FIPS_mode");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_FIPS_mode_set(int r)
-{
-    (void)r;
-    WOLFSSL_ENTER("wolfSSL_FIPS_mode_set");
-    WOLFSSL_STUB("FIPS_mode_set");
-
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_RAND_set_rand_method(const void *meth)
-{
-    (void) meth;
-    WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method");
-    WOLFSSL_STUB("RAND_set_rand_method");
-
-    /* if implemented RAND_bytes and RAND_pseudo_bytes need updated
-     * those two functions will call the respective functions from meth */
-    return SSL_FAILURE;
-}
-#endif
-
-int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
-{
-    int ret = WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
-    if(c != NULL && c->ssl != NULL) {
-        ret = 8 * c->ssl->specs.key_size;
-        if(alg_bits != NULL) {
-            *alg_bits = ret;
-        }
-    }
-    return ret;
-}
-
-int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s)
-{
-    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num");
-
-    if (s == NULL)
-        return -1;
-    return (int)s->num;
-}
-
-
-int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s)
-{
-    WOLFSSL_ENTER("wolfSSL_sk_X509_num");
-
-    if (s == NULL)
-        return -1;
-    return (int)s->num;
-}
-
-int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
-                int indent, unsigned long flags)
-{
-    int i;
-    (void)flags;
-    WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex");
-
-    for (i = 0; i < indent; i++) {
-        if (wolfSSL_BIO_write(bio, " ", 1) != 1)
-            return WOLFSSL_FAILURE;
-    }
-
-    if (flags == XN_FLAG_RFC2253) {
-        if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2)
-                                                                != name->sz - 2)
-            return WOLFSSL_FAILURE;
-    }
-    else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz)
-        return WOLFSSL_FAILURE;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)
-{
-    (void)x;
-    WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr");
-    WOLFSSL_STUB("X509_get0_pubkey_bitstr");
-
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
-{
-    (void)ctx;
-    (void)session;
-    WOLFSSL_ENTER("wolfSSL_CTX_add_session");
-    WOLFSSL_STUB("SSL_CTX_add_session");
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-
-int wolfSSL_version(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_version");
-    if (ssl->version.major == SSLv3_MAJOR) {
-        switch (ssl->version.minor) {
-            case SSLv3_MINOR :
-                return SSL3_VERSION;
-            case TLSv1_MINOR :
-            case TLSv1_1_MINOR :
-            case TLSv1_2_MINOR :
-            case TLSv1_3_MINOR :
-                return TLS1_VERSION;
-            default:
-                return WOLFSSL_FAILURE;
-        }
-    }
-    else if (ssl->version.major == DTLS_MAJOR) {
-        switch (ssl->version.minor) {
-            case DTLS_MINOR :
-            case DTLSv1_2_MINOR :
-                return DTLS1_VERSION;
-            default:
-                return WOLFSSL_FAILURE;
-        }
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
-    return ssl->ctx;
-}
-
-int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz");
-    if(!name)
-        return -1;
-    return name->sz;
-}
-
-#ifdef HAVE_SNI
-int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
-{
-    int ret;
-    WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name");
-    ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
-            host_name, (word16)XSTRLEN(host_name));
-    WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret);
-    return ret;
-}
-
-
-#ifndef NO_WOLFSSL_SERVER
-const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
-{
-    void * serverName = NULL;
-    if (ssl == NULL)
-        return NULL;
-    TLSX_SNI_GetRequest(ssl->extensions, type, &serverName);
-    return (const char *)serverName;
-}
-#endif /* NO_WOLFSSL_SERVER */
-#endif /* HAVE_SNI */
-
-WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
-{
-    if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
-        return ssl->ctx;
-    return NULL;
-}
-
-
-VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
-    if(ctx)
-        return ctx->verifyCallback;
-    return NULL;
-}
-
-
-void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
-    if (ctx)
-        ctx->sniRecvCb = cb;
-}
-
-int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
-                                               CallbackSniRecv cb)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
-    if (ctx) {
-        ctx->sniRecvCb = cb;
-        return 1;
-    }
-    return 0;
-}
-
-void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
-    if (ctx)
-        ctx->sniRecvCbArg = arg;
-}
-
-void wolfSSL_ERR_load_BIO_strings(void) {
-    WOLFSSL_ENTER("ERR_load_BIO_strings");
-    /* do nothing */
-}
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*))
-{
-    WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
-    WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
-    (void)threadid_func;
-    return;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
-{
-    WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
-    WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
-    (void)id;
-    (void)val;
-    return;
-}
-#endif
-
-
-#ifndef NO_WOLFSSL_STUB
-WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx,
-                                                WOLFSSL_X509_NAME* name)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs");
-    WOLFSSL_STUB("X509_STORE_get1_certs");
-    (void)ctx;
-    (void)name;
-    return NULL;
-}
-#endif
-
-#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */
-
-
-#if defined(OPENSSL_ALL) || \
-    (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
-     defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY))
-
-const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen)
-{
-    WOLFSSL_ENTER("wolfSSL_SESSION_get_id");
-    if(!sess || !idLen) {
-        WOLFSSL_MSG("Bad func args. Please provide idLen");
-        return NULL;
-    }
-    *idLen = sess->sessionIDSz;
-    return sess->sessionID;
-}
-#endif
-
-#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \
-    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
-
-int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx)
-{
-    int mode = 0;
-    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
-
-    if(!ctx)
-        return WOLFSSL_FATAL_ERROR;
-
-    if (ctx->verifyPeer)
-        mode |= WOLFSSL_VERIFY_PEER;
-    else if (ctx->verifyNone)
-        mode |= WOLFSSL_VERIFY_NONE;
-
-    if (ctx->failNoCert)
-        mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-
-    if (ctx->failNoCertxPSK)
-        mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
-
-    WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
-    return mode;
-}
-#endif
-
-#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
-/* return 1 if success, 0 if error
- * output keys are little endian format
- */
-int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
-                                 unsigned char *pub, unsigned int *pubSz)
-{
-#ifndef WOLFSSL_KEY_GEN
-    WOLFSSL_MSG("No Key Gen built in");
-    (void) priv;
-    (void) privSz;
-    (void) pub;
-    (void) pubSz;
-    return WOLFSSL_FAILURE;
-#else /* WOLFSSL_KEY_GEN */
-    int ret = WOLFSSL_FAILURE;
-    int initTmpRng = 0;
-    WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG *tmpRNG = NULL;
-#else
-    WC_RNG tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
-
-    if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
-        pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return WOLFSSL_FAILURE;
-#endif
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-        curve25519_key key;
-
-        if (wc_curve25519_init(&key) != MP_OKAY)
-            WOLFSSL_MSG("wc_curve25519_init failed");
-        else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
-            WOLFSSL_MSG("wc_curve25519_make_key failed");
-        /* export key pair */
-        else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
-                                                 pubSz, EC25519_LITTLE_ENDIAN)
-                 != MP_OKAY)
-            WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
-        else
-            ret = WOLFSSL_SUCCESS;
-
-        wc_curve25519_free(&key);
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-#endif /* WOLFSSL_KEY_GEN */
-}
-
-/* return 1 if success, 0 if error
- * input and output keys are little endian format
- */
-int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
-                               const unsigned char *priv, unsigned int privSz,
-                               const unsigned char *pub, unsigned int pubSz)
-{
-#ifndef WOLFSSL_KEY_GEN
-    WOLFSSL_MSG("No Key Gen built in");
-    (void) shared;
-    (void) sharedSz;
-    (void) priv;
-    (void) privSz;
-    (void) pub;
-    (void) pubSz;
-    return WOLFSSL_FAILURE;
-#else /* WOLFSSL_KEY_GEN */
-    int ret = WOLFSSL_FAILURE;
-    curve25519_key privkey, pubkey;
-
-    WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
-
-    if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
-        priv == NULL || privSz < CURVE25519_KEYSIZE ||
-        pub == NULL || pubSz < CURVE25519_KEYSIZE) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* import private key */
-    if (wc_curve25519_init(&privkey) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_init privkey failed");
-        return ret;
-    }
-    if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
-                                        EC25519_LITTLE_ENDIAN) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
-        wc_curve25519_free(&privkey);
-        return ret;
-    }
-
-    /* import public key */
-    if (wc_curve25519_init(&pubkey) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_init pubkey failed");
-        wc_curve25519_free(&privkey);
-        return ret;
-    }
-    if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
-                                       EC25519_LITTLE_ENDIAN) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
-        wc_curve25519_free(&privkey);
-        wc_curve25519_free(&pubkey);
-        return ret;
-    }
-
-    if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
-                                       shared, sharedSz,
-                                       EC25519_LITTLE_ENDIAN) != MP_OKAY)
-        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
-    else
-        ret = WOLFSSL_SUCCESS;
-
-    wc_curve25519_free(&privkey);
-    wc_curve25519_free(&pubkey);
-
-    return ret;
-#endif /* WOLFSSL_KEY_GEN */
-}
-#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
-
-#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
-/* return 1 if success, 0 if error
- * output keys are little endian format
- */
-int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
-                                 unsigned char *pub, unsigned int *pubSz)
-{
-#ifndef WOLFSSL_KEY_GEN
-    WOLFSSL_MSG("No Key Gen built in");
-    (void) priv;
-    (void) privSz;
-    (void) pub;
-    (void) pubSz;
-    return WOLFSSL_FAILURE;
-#else /* WOLFSSL_KEY_GEN */
-    int ret = WOLFSSL_FAILURE;
-    int initTmpRng = 0;
-    WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    WC_RNG *tmpRNG = NULL;
-#else
-    WC_RNG tmpRNG[1];
-#endif
-
-    WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
-
-    if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
-        pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
-    if (tmpRNG == NULL)
-        return WOLFSSL_FATAL_ERROR;
-#endif
-    if (wc_InitRng(tmpRNG) == 0) {
-        rng = tmpRNG;
-        initTmpRng = 1;
-    }
-    else {
-        WOLFSSL_MSG("Bad RNG Init, trying global");
-        if (initGlobalRNG == 0)
-            WOLFSSL_MSG("Global RNG no Init");
-        else
-            rng = &globalRNG;
-    }
-
-    if (rng) {
-        ed25519_key key;
-
-        if (wc_ed25519_init(&key) != MP_OKAY)
-            WOLFSSL_MSG("wc_ed25519_init failed");
-        else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
-            WOLFSSL_MSG("wc_ed25519_make_key failed");
-        /* export private key */
-        else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
-            WOLFSSL_MSG("wc_ed25519_export_key failed");
-        else
-            ret = WOLFSSL_SUCCESS;
-
-        wc_ed25519_free(&key);
-    }
-
-    if (initTmpRng)
-        wc_FreeRng(tmpRNG);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-#endif /* WOLFSSL_KEY_GEN */
-}
-
-/* return 1 if success, 0 if error
- * input and output keys are little endian format
- * priv is a buffer containing private and public part of key
- */
-int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
-                         const unsigned char *priv, unsigned int privSz,
-                         unsigned char *sig, unsigned int *sigSz)
-{
-#ifndef WOLFSSL_KEY_GEN
-    WOLFSSL_MSG("No Key Gen built in");
-    (void) msg;
-    (void) msgSz;
-    (void) priv;
-    (void) privSz;
-    (void) sig;
-    (void) sigSz;
-    return WOLFSSL_FAILURE;
-#else /* WOLFSSL_KEY_GEN */
-    ed25519_key key;
-    int ret = WOLFSSL_FAILURE;
-
-    WOLFSSL_ENTER("wolfSSL_ED25519_sign");
-
-    if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
-        msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* import key */
-    if (wc_ed25519_init(&key) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_init failed");
-        return ret;
-    }
-    if (wc_ed25519_import_private_key(priv, privSz/2,
-                                      priv+(privSz/2), ED25519_PUB_KEY_SIZE,
-                                      &key) != MP_OKAY){
-        WOLFSSL_MSG("wc_ed25519_import_private failed");
-        wc_ed25519_free(&key);
-        return ret;
-    }
-
-    if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
-        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
-    else
-        ret = WOLFSSL_SUCCESS;
-
-    wc_ed25519_free(&key);
-
-    return ret;
-#endif /* WOLFSSL_KEY_GEN */
-}
-
-/* return 1 if success, 0 if error
- * input and output keys are little endian format
- * pub is a buffer containing public part of key
- */
-int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
-                           const unsigned char *pub, unsigned int pubSz,
-                           const unsigned char *sig, unsigned int sigSz)
-{
-#ifndef WOLFSSL_KEY_GEN
-    WOLFSSL_MSG("No Key Gen built in");
-    (void) msg;
-    (void) msgSz;
-    (void) pub;
-    (void) pubSz;
-    (void) sig;
-    (void) sigSz;
-    return WOLFSSL_FAILURE;
-#else /* WOLFSSL_KEY_GEN */
-    ed25519_key key;
-    int ret = WOLFSSL_FAILURE, check = 0;
-
-    WOLFSSL_ENTER("wolfSSL_ED25519_verify");
-
-    if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
-        msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
-        WOLFSSL_MSG("Bad arguments");
-        return WOLFSSL_FAILURE;
-    }
-
-    /* import key */
-    if (wc_ed25519_init(&key) != MP_OKAY) {
-        WOLFSSL_MSG("wc_curve25519_init failed");
-        return ret;
-    }
-    if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
-        WOLFSSL_MSG("wc_ed25519_import_public failed");
-        wc_ed25519_free(&key);
-        return ret;
-    }
-
-    if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
-                                     &check, &key)) != MP_OKAY) {
-        WOLFSSL_MSG("wc_ed25519_verify_msg failed");
-    }
-    else if (!check)
-        WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
-    else
-        ret = WOLFSSL_SUCCESS;
-
-    wc_ed25519_free(&key);
-
-    return ret;
-#endif /* WOLFSSL_KEY_GEN */
-}
-
-#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
-
-#ifdef WOLFSSL_JNI
-
-int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
-{
-    WOLFSSL_ENTER("wolfSSL_set_jobject");
-    if (ssl != NULL)
-    {
-        ssl->jObjectRef = objPtr;
-        return WOLFSSL_SUCCESS;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-void* wolfSSL_get_jobject(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_get_jobject");
-    if (ssl != NULL)
-        return ssl->jObjectRef;
-    return NULL;
-}
-
-#endif /* WOLFSSL_JNI */
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
-    WOLF_EVENT_FLAG flags, int* eventCount)
-{
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
-                                        events, maxEvents, flags, eventCount);
-}
-
-int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
-{
-    int ret, eventCount = 0;
-    WOLF_EVENT* events[1];
-
-    if (ssl == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl,
-        events, sizeof(events)/sizeof(events), flags, &eventCount);
-    if (ret == 0) {
-        ret = eventCount;
-    }
-
-    return ret;
-}
-
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-#ifdef OPENSSL_EXTRA
-unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
-                                               const char **data, int *flags)
-{
-    WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
-
-    (void)line;
-    (void)file;
-
-    /* No data or flags stored - error display only in Nginx. */
-    if (data != NULL) {
-        *data = "";
-    }
-    if (flags != NULL) {
-        *flags = 0;
-    }
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_MYSQL_COMPATIBLE)
-    {
-        int ret = 0;
-
-        while (1) {
-            if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
-                WOLFSSL_MSG("Issue peeking at error node in queue");
-                return 0;
-            }
-            ret = -ret;
-
-            if (ret == ASN_NO_PEM_HEADER)
-                return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
-            if (ret != WANT_READ && ret != WANT_WRITE &&
-                    ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN &&
-                    ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E)
-                break;
-
-            wc_RemoveErrorNode(-1);
-        }
-
-        return (unsigned long)ret;
-    }
-#else
-    return (unsigned long)(0 - NOT_COMPILED_IN);
-#endif
-}
-#endif
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-
-#ifndef NO_WOLFSSL_STUB
-WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
-{
-    (void)ssl;
-    WOLFSSL_STUB("wolfSSL_get_ciphers_compat");
-    return NULL;
-}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_OPENSSL_config(char *config_name)
-{
-    (void)config_name;
-    WOLFSSL_STUB("OPENSSL_config");
-}
-#endif
-#endif
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
-    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
-int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c)
-{
-    static int x509_idx = 0;
-
-    WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index");
-    (void)idx;
-    (void)arg;
-    (void)a;
-    (void)b;
-    (void)c;
-
-    return x509_idx++;
-}
-
-void *wolfSSL_X509_get_ex_data(X509 *x509, int idx)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_get_ex_data");
-    #ifdef HAVE_EX_DATA
-    if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) {
-        return x509->ex_data[idx];
-    }
-    #else
-    (void)x509;
-    (void)idx;
-    #endif
-    return NULL;
-}
-int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_set_ex_data");
-    #ifdef HAVE_EX_DATA
-    if (x509 != NULL && idx < MAX_EX_DATA)
-    {
-        x509->ex_data[idx] = data;
-        return WOLFSSL_SUCCESS;
-    }
-    #else
-    (void)x509;
-    (void)idx;
-    (void)data;
-    #endif
-    return WOLFSSL_FAILURE;
-}
-int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
-        const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_NAME_digest");
-
-    if (name == NULL || type == NULL)
-        return WOLFSSL_FAILURE;
-
-#ifndef NO_FILESYSTEM
-    return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName,
-                              name->fullName.fullNameLen, md, len, type, NULL);
-#else
-    (void)md;
-    (void)len;
-    return NOT_COMPILED_IN;
-#endif
-}
-
-long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout");
-
-    if (ctx == NULL)
-        return 0;
-
-    return ctx->timeout;
-}
-
-#ifdef HAVE_ECC
-int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
-
-    if (ctx == NULL || ecdh == NULL)
-        return BAD_FUNC_ARG;
-
-    ctx->ecdhCurveOID = ecdh->group->curve_oid;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-/* Assumes that the session passed in is from the cache. */
-int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session");
-
-    if (ctx == NULL || s == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef HAVE_EXT_CACHE
-    if (!ctx->internalCacheOff)
-#endif
-    {
-        /* Don't remove session just timeout session. */
-        s->timeout = 0;
-    }
-
-#ifdef HAVE_EXT_CACHE
-    if (ctx->rem_sess_cb != NULL)
-        ctx->rem_sess_cb(ctx, s);
-#endif
-
-    return 0;
-}
-
-BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_get_rbio");
-    (void)s;
-    /* Nginx sets the buffer size if the read BIO is different to write BIO.
-     * The setting buffer size doesn't do anything so return NULL for both.
-     */
-    return NULL;
-}
-BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_get_wbio");
-    (void)s;
-    /* Nginx sets the buffer size if the read BIO is different to write BIO.
-     * The setting buffer size doesn't do anything so return NULL for both.
-     */
-    return NULL;
-}
-
-int wolfSSL_SSL_do_handshake(WOLFSSL *s)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_do_handshake");
-
-    if (s == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (s->options.side == WOLFSSL_CLIENT_END) {
-    #ifndef NO_WOLFSSL_CLIENT
-        return wolfSSL_connect(s);
-    #else
-        WOLFSSL_MSG("Client not compiled in");
-        return WOLFSSL_FAILURE;
-    #endif
-    }
-
-#ifndef NO_WOLFSSL_SERVER
-    return wolfSSL_accept(s);
-#else
-    WOLFSSL_MSG("Server not compiled in");
-    return WOLFSSL_FAILURE;
-#endif
-}
-
-int wolfSSL_SSL_in_init(WOLFSSL *s)
-{
-    WOLFSSL_ENTER("wolfSSL_SSL_in_init");
-
-    if (s == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (s->options.side == WOLFSSL_CLIENT_END)
-        return s->options.connectState < SECOND_REPLY_DONE;
-    return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
-}
-
-#ifndef NO_SESSION_CACHE
-
-WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl)
-{
-    WOLFSSL_SESSION *session;
-
-    WOLFSSL_ENTER("wolfSSL_SSL_get0_session");
-
-    if (ssl == NULL) {
-        return NULL;
-    }
-
-    session = wolfSSL_get_session((WOLFSSL*)ssl);
-
-#ifdef HAVE_EXT_CACHE
-    ((WOLFSSL*)ssl)->extSession = session;
-#endif
-
-    return session;
-}
-
-#endif /* NO_SESSION_CACHE */
-
-int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen,
-                    unsigned int flags, char **peername)
-{
-    int         ret;
-    DecodedCert dCert;
-
-    WOLFSSL_ENTER("wolfSSL_X509_check_host");
-
-    /* flags and peername not needed for Nginx. */
-    (void)flags;
-    (void)peername;
-
-    if (flags == WOLFSSL_NO_WILDCARDS) {
-        WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented");
-        return WOLFSSL_FAILURE;
-    }
-
-    InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL);
-    ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL);
-    if (ret != 0)
-        return WOLFSSL_FAILURE;
-
-    ret = CheckHostName(&dCert, (char *)chk, chklen);
-    FreeDecodedCert(&dCert);
-    if (ret != 0)
-        return WOLFSSL_FAILURE;
-    return WOLFSSL_SUCCESS;
-}
-
-int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
-{
-    static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
-                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-    int    i;
-    word32 j;
-    word32 len = 0;
-
-    WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER");
-
-    if (bp == NULL || a == NULL)
-        return WOLFSSL_FAILURE;
-
-    /* Skip ASN.1 INTEGER (type) byte. */
-    i = 1;
-    /* When indefinte length, can't determine length with data available. */
-    if (a->data[i] == 0x80)
-        return 0;
-    /* One length byte if less than 0x80. */
-    if (a->data[i] < 0x80)
-        len = a->data[i++];
-    /* Multiple length byte if greater than 0x80. */
-    else if (a->data[i] > 0x80) {
-        switch (a->data[i++] - 0x80) {
-            case 4:
-                len |= a->data[i++] << 24;
-                FALL_THROUGH;
-            case 3:
-                len |= a->data[i++] << 16;
-                FALL_THROUGH;
-            case 2:
-                len |= a->data[i++] <<  8;
-                FALL_THROUGH;
-            case 1:
-                len |= a->data[i++];
-                break;
-            default:
-                /* Not supporting greater than 4 bytes of length. */
-                return 0;
-        }
-    }
-
-    /* Zero length integer is the value zero. */
-    if (len == 0) {
-        wolfSSL_BIO_write(bp, "00", 2);
-        return 2;
-    }
-
-    /* Don't do negative - just write out every byte. */
-    for (j = 0; j < len; i++,j++) {
-        wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1);
-        wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1);
-    }
-
-    /* Two nibbles written for each byte. */
-    return len * 2;
-}
-
-
-#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
-/* Expected return values from implementations of OpenSSL ticket key callback.
- */
-#define TICKET_KEY_CB_RET_FAILURE    -1
-#define TICKET_KEY_CB_RET_NOT_FOUND   0
-#define TICKET_KEY_CB_RET_OK          1
-#define TICKET_KEY_CB_RET_RENEW       2
-
-/* The ticket key callback as used in OpenSSL is stored here. */
-static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
-    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL;
-
-/* Implementation of session ticket encryption/decryption using OpenSSL
- * callback to initialize the cipher and HMAC.
- *
- * ssl           The SSL/TLS object.
- * keyName       The key name - used to identify the key to be used.
- * iv            The IV to use.
- * mac           The MAC of the encrypted data.
- * enc           Encrypt ticket.
- * encTicket     The ticket data.
- * encTicketLen  The length of the ticket data.
- * encLen        The encrypted/decrypted ticket length - output length.
- * ctx           Ignored. Application specific data.
- * returns WOLFSSL_TICKET_RET_OK to indicate success,
- *         WOLFSSL_TICKET_RET_CREATE if a new ticket is required and
- *         WOLFSSL_TICKET_RET_FATAL on error.
- */
-static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
-                                  unsigned char keyName[WOLFSSL_TICKET_NAME_SZ],
-                                  unsigned char iv[WOLFSSL_TICKET_IV_SZ],
-                                  unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
-                                  int enc, unsigned char* encTicket,
-                                  int encTicketLen, int* encLen, void* ctx)
-{
-    byte                    digest[WC_MAX_DIGEST_SIZE];
-    WOLFSSL_EVP_CIPHER_CTX  evpCtx;
-    WOLFSSL_HMAC_CTX        hmacCtx;
-    unsigned int            mdSz = 0;
-    int                     len = 0;
-    int                     ret = WOLFSSL_TICKET_RET_FATAL;
-    int                     res;
-
-    (void)ctx;
-
-    if (ticketKeyCb == NULL)
-        return WOLFSSL_TICKET_RET_FATAL;
-
-    wolfSSL_EVP_CIPHER_CTX_init(&evpCtx);
-    /* Initialize the cipher and HMAC. */
-    res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
-    if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW)
-        return WOLFSSL_TICKET_RET_FATAL;
-
-    if (enc)
-    {
-        /* Encrypt in place. */
-        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
-                                      encTicket, encTicketLen))
-            goto end;
-        encTicketLen = len;
-        if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
-            goto end;
-        /* Total length of encrypted data. */
-        encTicketLen += len;
-        *encLen = encTicketLen;
-
-        /* HMAC the encrypted data into the parameter 'mac'. */
-        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
-            goto end;
-#ifdef WOLFSSL_SHA512
-        /* Check for SHA512, which would overrun the mac buffer */
-        if (hmacCtx.hmac.macType == WC_SHA512)
-            goto end;
-#endif
-        if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz))
-            goto end;
-    }
-    else
-    {
-        /* HMAC the encrypted data and compare it to the passed in data. */
-        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
-            goto end;
-        if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz))
-            goto end;
-        if (XMEMCMP(mac, digest, mdSz) != 0)
-            goto end;
-
-        /* Decrypt the ticket data in place. */
-        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
-                                      encTicket, encTicketLen))
-            goto end;
-        encTicketLen = len;
-        if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
-            goto end;
-        /* Total length of decrypted data. */
-        *encLen = encTicketLen + len;
-    }
-
-    ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE :
-                                             WOLFSSL_TICKET_RET_OK;
-end:
-    return ret;
-}
-
-/* Set the callback to use when encrypting/decrypting tickets.
- *
- * ctx  The SSL/TLS context object.
- * cb   The OpenSSL session ticket callback.
- * returns WOLFSSL_SUCCESS to indicate success.
- */
-int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)(
-    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
-    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc))
-{
-    /* Store callback in a global. */
-    ticketKeyCb = cb;
-    /* Set the ticket encryption callback to be a wrapper around OpenSSL
-     * callback.
-     */
-    ctx->ticketEncCb = wolfSSL_TicketKeyCb;
-
-    return WOLFSSL_SUCCESS;
-}
-#endif /* HAVE_SESSION_TICKET */
-
-#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
-    OPENSSL_EXTRA || HAVE_LIGHTY */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-#ifdef HAVE_OCSP
-/* Not an OpenSSL API. */
-int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
-{
-    *response = ssl->ocspResp;
-    return ssl->ocspRespSz;
-}
-
-/* Not an OpenSSL API. */
-char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
-{
-    return ssl->url;
-}
-
-/* Not an OpenSSL API. */
-int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
-{
-    if (ssl == NULL)
-        return WOLFSSL_FAILURE;
-
-    ssl->url = url;
-    return WOLFSSL_SUCCESS;
-}
-#endif /* OCSP */
-#endif /* OPENSSL_ALL / WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
-
-#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
-    defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
-int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain)
-{
-    word32         idx;
-    word32         length;
-    WOLFSSL_STACK* node;
-    WOLFSSL_STACK* last = NULL;
-
-    if (ctx == NULL || chain == NULL) {
-        chain = NULL;
-        return WOLFSSL_FAILURE;
-    }
-    if (ctx->x509Chain != NULL) {
-        *chain = ctx->x509Chain;
-        return WOLFSSL_SUCCESS;
-    }
-
-    /* If there are no chains then success! */
-    *chain = NULL;
-    if (ctx->certChain == NULL || ctx->certChain->length == 0) {
-        return WOLFSSL_SUCCESS;
-    }
-
-    /* Create a new stack of WOLFSSL_X509 object from chain buffer. */
-    for (idx = 0; idx < ctx->certChain->length; ) {
-        node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
-                                       DYNAMIC_TYPE_OPENSSL);
-        if (node == NULL)
-            return WOLFSSL_FAILURE;
-        node->next = NULL;
-
-        /* 3 byte length | X509 DER data */
-        ato24(ctx->certChain->buffer + idx, &length);
-        idx += 3;
-
-        /* Create a new X509 from DER encoded data. */
-        node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx,
-            length);
-        if (node->data.x509 == NULL) {
-            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
-            /* Return as much of the chain as we created. */
-            ctx->x509Chain = *chain;
-            return WOLFSSL_FAILURE;
-        }
-        idx += length;
-
-        /* Add object to the end of the stack. */
-        if (last == NULL) {
-            node->num = 1;
-            *chain = node;
-        }
-        else {
-            (*chain)->num++;
-            last->next = node;
-        }
-
-        last = node;
-    }
-
-    ctx->x509Chain = *chain;
-
-    return WOLFSSL_SUCCESS;
-}
-
-int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
-    int(*cb)(WOLFSSL*, void*))
-{
-    if (ctx == NULL || ctx->cm == NULL)
-        return WOLFSSL_FAILURE;
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-    /* Ensure stapling is on for callback to be used. */
-    wolfSSL_CTX_EnableOCSPStapling(ctx);
-
-    if (ctx->cm->ocsp_stapling == NULL)
-        return WOLFSSL_FAILURE;
-
-    ctx->cm->ocsp_stapling->statusCb = cb;
-#else
-    (void)cb;
-#endif
-
-    return WOLFSSL_SUCCESS;
-}
-
-int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
-    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x)
-{
-    WOLFSSL_STACK* node;
-    Signer* ca = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* cert = NULL;
-#else
-    DecodedCert  cert[1];
-#endif
-
-    if (issuer == NULL || ctx == NULL || x == NULL)
-        return WOLFSSL_FATAL_ERROR;
-
-    if (ctx->chain != NULL) {
-        for (node = ctx->chain; node != NULL; node = node->next) {
-            if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) {
-                *issuer = x;
-                return WOLFSSL_SUCCESS;
-            }
-        }
-    }
-
-
-#ifdef WOLFSSL_SMALL_STACK
-    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
-    if (cert == NULL)
-        return WOLFSSL_FAILURE;
-#endif
-
-    /* Use existing CA retrieval APIs that use DecodedCert. */
-    InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL);
-    if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
-    #ifndef NO_SKID
-        if (cert->extAuthKeyIdSet)
-            ca = GetCA(ctx->store->cm, cert->extAuthKeyId);
-        if (ca == NULL)
-            ca = GetCAByName(ctx->store->cm, cert->issuerHash);
-    #else /* NO_SKID */
-        ca = GetCA(ctx->store->cm, cert->issuerHash);
-    #endif /* NO SKID */
-    }
-    FreeDecodedCert(cert);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-#endif
-
-    if (ca == NULL)
-        return WOLFSSL_FAILURE;
-
-    *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0,
-        DYNAMIC_TYPE_OPENSSL);
-    if (*issuer == NULL)
-        return WOLFSSL_FAILURE;
-
-    /* Create an empty certificate as CA doesn't have a certificate. */
-    XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509));
-    (*issuer)->dynamicMemory = 1;
-#ifdef WOLFSSL_SIGNER_DER_CERT
-    if (AllocDer(&(*issuer)->derCert, ca->derCert->length, ca->derCert->type,
-                                                                   NULL) == 0) {
-        XMEMCPY((*issuer)->derCert->buffer, ca->derCert->buffer,
-                                                           ca->derCert->length);
-    }
-    else {
-        XFREE(*issuer, 0, DYNAMIC_TYPE_OPENSSL);
-        return WOLFSSL_FAILURE;
-    }
-#endif
-
-    /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */
-
-    return WOLFSSL_SUCCESS;
-}
-
-void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
-{
-    WOLFSSL_STACK *curr;
-
-    while (sk != NULL) {
-        curr = sk;
-        sk = sk->next;
-
-        XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL);
-    }
-}
-
-WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
-{
-    WOLFSSL_STACK* list = NULL;
-    char*          url;
-
-    if (x->authInfoSz == 0)
-        return NULL;
-
-    list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1,
-                                   NULL, DYNAMIC_TYPE_OPENSSL);
-    if (list == NULL)
-        return NULL;
-
-    url = (char*)list;
-    url += sizeof(WOLFSSL_STACK);
-    XMEMCPY(url, x->authInfo, x->authInfoSz);
-    url[x->authInfoSz] = '\0';
-
-    list->data.string = url;
-    list->next = NULL;
-
-    return list;
-}
-
-int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
-{
-    WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
-    WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer);
-
-    if (issuerName == NULL || subjectName == NULL)
-        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
-
-    /* Literal matching of encoded names and key ids. */
-    if (issuerName->sz != subjectName->sz ||
-           XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) {
-        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
-    }
-
-    if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) {
-        if (subject->authKeyIdSz != issuer->subjKeyIdSz ||
-                XMEMCMP(subject->authKeyId, issuer->subjKeyId,
-                        issuer->subjKeyIdSz) != 0) {
-            return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
-        }
-    }
-
-    return X509_V_OK;
-}
-
-WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x)
-{
-    return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length);
-}
-
-char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings,
-    int idx)
-{
-    for (; idx > 0 && strings != NULL; idx--)
-        strings = strings->next;
-    if (strings == NULL)
-        return NULL;
-    return strings->data.string;
-}
-#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-#ifdef HAVE_ALPN
-void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data,
-                                unsigned int *len)
-{
-    word16 nameLen;
-
-    if (ssl != NULL && data != NULL && len != NULL) {
-        TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
-        *len = nameLen;
-    }
-}
-
-int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
-                              const unsigned char *in, unsigned int inLen,
-                              const unsigned char *clientNames,
-                              unsigned int clientLen)
-{
-    unsigned int i, j;
-    byte lenIn, lenClient;
-
-    if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
-        return OPENSSL_NPN_UNSUPPORTED;
-
-    for (i = 0; i < inLen; i += lenIn) {
-        lenIn = in[i++];
-        for (j = 0; j < clientLen; j += lenClient) {
-            lenClient = clientNames[j++];
-
-            if (lenIn != lenClient)
-                continue;
-
-            if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
-                *out = (unsigned char *)(in + i);
-                *outLen = lenIn;
-                return OPENSSL_NPN_NEGOTIATED;
-            }
-        }
-    }
-
-    *out = (unsigned char *)clientNames + 1;
-    *outLen = clientNames[0];
-    return OPENSSL_NPN_NO_OVERLAP;
-}
-
-void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
-                                    int (*cb) (WOLFSSL *ssl,
-                                               const unsigned char **out,
-                                               unsigned char *outlen,
-                                               const unsigned char *in,
-                                               unsigned int inlen,
-                                               void *arg), void *arg)
-{
-    if (ctx != NULL) {
-        ctx->alpnSelect = cb;
-        ctx->alpnSelectArg = arg;
-    }
-}
-
-void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
-                                           int (*cb) (WOLFSSL *ssl,
-                                                      const unsigned char
-                                                      **out,
-                                                      unsigned int *outlen,
-                                                      void *arg), void *arg)
-{
-    (void)s;
-    (void)cb;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
-}
-
-void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
-                                      int (*cb) (WOLFSSL *ssl,
-                                                 unsigned char **out,
-                                                 unsigned char *outlen,
-                                                 const unsigned char *in,
-                                                 unsigned int inlen,
-                                                 void *arg), void *arg)
-{
-    (void)s;
-    (void)cb;
-    (void)arg;
-    WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb");
-}
-
-void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
-                                    unsigned *len)
-{
-    (void)s;
-    (void)data;
-    (void)len;
-    WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated");
-}
-#endif /* HAVE_ALPN */
-
-#endif /* WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
-
-#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
-WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names)
-{
-    int idx, start = 0, len;
-    int curve;
-    char name[MAX_CURVE_NAME_SZ];
-
-    /* Disable all curves so that only the ones the user wants are enabled. */
-    ctx->disabledCurves = (word32)-1;
-    for (idx = 1; names[idx-1] != '\0'; idx++) {
-        if (names[idx] != ':' && names[idx] != '\0')
-            continue;
-
-        len = idx - 1 - start;
-        if (len > MAX_CURVE_NAME_SZ - 1)
-            return WOLFSSL_FAILURE;
-
-        XMEMCPY(name, names + start, len);
-        name[len] = 0;
-
-        if ((XSTRNCMP(name, "prime256v1", len) == 0) ||
-                                      (XSTRNCMP(name, "secp256r1", len) == 0) ||
-                                      (XSTRNCMP(name, "P-256", len) == 0)) {
-            curve = WOLFSSL_ECC_SECP256R1;
-        }
-        else if ((XSTRNCMP(name, "secp384r1", len) == 0) ||
-                                          (XSTRNCMP(name, "P-384", len) == 0)) {
-            curve = WOLFSSL_ECC_SECP384R1;
-        }
-        else if ((XSTRNCMP(name, "secp521r1", len) == 0) ||
-                                          (XSTRNCMP(name, "P-521", len) == 0)) {
-            curve = WOLFSSL_ECC_SECP521R1;
-        }
-        else if (XSTRNCMP(name, "X25519", len) == 0)
-            curve = WOLFSSL_ECC_X25519;
-        else if ((curve = wc_ecc_get_curve_id_from_name(name)) < 0)
-            return WOLFSSL_FAILURE;
-
-        /* Switch the bit to off and therefore is enabled. */
-        ctx->disabledCurves &= ~(1 << curve);
-        start = idx + 1;
-    }
-
-    return WOLFSSL_SUCCESS;
-}
-#endif
-
-#ifdef OPENSSL_EXTRA
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
-{
-    WOLFSSL_STUB("SSL_CTX_set_msg_callback");
-    (void)ctx;
-    (void)cb;
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-
-/* Sets a callback for when sending and receiving protocol messages.
- *
- * ssl WOLFSSL structure to set callback in
- * cb  callback to use
- *
- * return SSL_SUCCESS on success and SSL_FAILURE with error case
- */
-int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb)
-{
-    WOLFSSL_ENTER("wolfSSL_set_msg_callback");
-
-    if (ssl == NULL) {
-        return SSL_FAILURE;
-    }
-
-    if (cb != NULL) {
-        ssl->toInfoOn = 1;
-    }
-
-    ssl->protoMsgCb = cb;
-    return SSL_SUCCESS;
-}
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
-{
-    WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg");
-    (void)ctx;
-    (void)arg;
-    return WOLFSSL_FAILURE;
-}
-#endif
-
-int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
-{
-    WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
-    ssl->protoMsgCtx = arg;
-    return WOLFSSL_SUCCESS;
-}
-
-void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line)
-{
-    void *ret;
-    (void)file;
-    (void)line;
-
-    if (data == NULL || siz >= INT_MAX)
-        return NULL;
-
-    ret = OPENSSL_malloc(siz);
-    if (ret == NULL) {
-        return NULL;
-    }
-    return XMEMCPY(ret, data, siz);
-}
-
-int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p,
-                            unsigned int p_len)
-{
-    WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos");
-    if(ctx == NULL)
-        return BAD_FUNC_ARG;
-    if((void *)ctx->alpn_cli_protos != NULL)
-        wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos);
-    ctx->alpn_cli_protos =
-        (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0);
-    if (ctx->alpn_cli_protos == NULL) {
-        return SSL_FAILURE;
-    }
-    ctx->alpn_cli_protos_len = p_len;
-
-    return SSL_SUCCESS;
-}
-
-#endif
-
-#endif /* WOLFCRYPT_ONLY */
-
-#if defined(OPENSSL_EXTRA)
-int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509)
-{
-    WOLFSSL_ENTER("X509_check_ca");
-
-    if (x509 == NULL)
-        return WOLFSSL_FAILURE;
-    if (x509->isCa)
-        return 1;
-    if (x509->extKeyUsageCrit)
-        return 4;
-
-    return 0;
-}
-
-
-const char *wolfSSL_ASN1_tag2str(int tag)
-{
-    static const char *const tag_label[31] = {
-        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
-        "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED",
-        "<ASN1 11>", "UTF8STRING", "<ASN1 13>", "<ASN1 14>", "<ASN1 15>",
-        "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
-        "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
-        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING",
-        "<ASN1 29>", "BMPSTRING"
-    };
-
-    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
-        tag &= ~0x100;
-    if (tag < 0 || tag > 30)
-        return "(unknown)";
-    return tag_label[tag];
-}
-
-static int check_esc_char(char c, char *esc)
-{
-    char *ptr = NULL;
-
-    ptr = esc;
-    while(*ptr != 0){
-        if (c == *ptr)
-            return 1;
-        ptr++;
-    }
-    return 0;
-}
-
-int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str,
-                                 unsigned long flags)
-{
-    size_t str_len = 0, type_len = 0;
-    unsigned char *typebuf = NULL;
-    const char *hash="#";
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex");
-    if (out == NULL || str == NULL)
-        return WOLFSSL_FAILURE;
-
-    /* add ASN1 type tag */
-    if (flags & ASN1_STRFLGS_SHOW_TYPE){
-        const char *tag = wolfSSL_ASN1_tag2str(str->type);
-        /* colon len + tag len + null*/
-        type_len = XSTRLEN(tag) + 2;
-        typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (typebuf == NULL){
-            WOLFSSL_MSG("memory alloc failed.");
-            return WOLFSSL_FAILURE;
-        }
-        XMEMSET(typebuf, 0, type_len);
-        XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag);
-        type_len--;
-    }
-
-    /* dump hex */
-    if (flags & ASN1_STRFLGS_DUMP_ALL){
-        static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6',
-                                         '7','8', '9', 'A', 'B', 'C', 'D',
-                                         'E', 'F' };
-        char hex_tmp[4];
-        char *str_ptr, *str_end;
-
-        if (type_len > 0){
-            if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
-                XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                return WOLFSSL_FAILURE;
-            }
-            str_len += type_len;
-        }
-        if (wolfSSL_BIO_write(out, hash, 1) != 1){
-            goto err_exit;
-        }
-        str_len++;
-        if (flags & ASN1_STRFLGS_DUMP_DER){
-            hex_tmp[0] = hex_char[str->type >> 4];
-            hex_tmp[1] = hex_char[str->type & 0xf];
-            hex_tmp[2] = hex_char[str->length >> 4];
-            hex_tmp[3] = hex_char[str->length & 0xf];
-            if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){
-                goto err_exit;
-            }
-            str_len += 4;
-            XMEMSET(hex_tmp, 0, 4);
-        }
-
-        str_ptr = str->data;
-        str_end = str->data + str->length;
-        while (str_ptr < str_end){
-            hex_tmp[0] = hex_char[*str_ptr >> 4];
-            hex_tmp[1] = hex_char[*str_ptr & 0xf];
-            if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){
-                goto err_exit;
-            }
-            str_ptr++;
-            str_len += 2;
-        }
-        if (type_len > 0)
-            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-        return (int)str_len;
-    }
-
-    if (type_len > 0){
-        if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
-            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            return WOLFSSL_FAILURE;
-        }
-        str_len += type_len;
-    }
-
-    if (flags & ASN1_STRFLGS_ESC_2253){
-        char esc_ch[] = "+;<>\\";
-        char* esc_ptr = NULL;
-
-        esc_ptr = str->data;
-        while (*esc_ptr != 0){
-            if (check_esc_char(*esc_ptr, esc_ch)){
-                if (wolfSSL_BIO_write(out,"\\", 1) != 1)
-                    goto err_exit;
-                str_len++;
-            }
-            if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1)
-                goto err_exit;
-            str_len++;
-            esc_ptr++;
-        }
-        if (type_len > 0)
-            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return (int)str_len;
-    }
-
-    if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
-        goto err_exit;
-    }
-    str_len += str->length;
-    if (type_len > 0)
-        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return (int)str_len;
-
-err_exit:
-    if (type_len > 0)
-        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    return WOLFSSL_FAILURE;
-}
-
-#ifndef NO_ASN_TIME
-WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
-                                                        WOLFSSL_ASN1_TIME **out)
-{
-    unsigned char time_type;
-    WOLFSSL_ASN1_TIME *ret = NULL;
-    unsigned char *data_ptr = NULL;
-
-    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime");
-    if (t == NULL)
-        return NULL;
-
-    time_type = t->data[0];
-    if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){
-        WOLFSSL_MSG("Invalid ASN_TIME type.");
-        return NULL;
-    }
-    if (out == NULL || *out == NULL){
-        ret = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL,
-                                        DYNAMIC_TYPE_TMP_BUFFER);
-        if (ret == NULL){
-            WOLFSSL_MSG("memory alloc failed.");
-            return NULL;
-        }
-        XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME));
-    } else
-        ret = *out;
-
-    if (time_type == ASN_GENERALIZED_TIME){
-        XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE);
-        return ret;
-    } else if (time_type == ASN_UTC_TIME){
-        ret->data[0] = ASN_GENERALIZED_TIME;
-        ret->data[1] = ASN_GENERALIZED_TIME_SIZE;
-        data_ptr  = ret->data + 2;
-        if (t->data[2] >= '5')
-            XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, "19%s", t->data + 2);
-        else
-            XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, "20%s", t->data + 2);
-
-        return ret;
-    }
-
-    WOLFSSL_MSG("Invalid ASN_TIME value");
-    return NULL;
-}
-#endif /* !NO_ASN_TIME */
-
-
-#ifndef NO_ASN
-int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp)
-{
-    unsigned char *pptr = NULL;
-    char pad = 0 ;
-    unsigned char pad_val = 0;
-    int ret_size = 0;
-    unsigned char data1 = 0;
-    unsigned char neg = 0;
-    int i = 0;
-
-    WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER");
-    if (a == NULL)
-        return WOLFSSL_FAILURE;
-
-    ret_size = a->intData[1];
-    if (ret_size == 0)
-        ret_size = 1;
-    else{
-        ret_size = (int)a->intData[1];
-        neg = a->negative;
-        data1 = a->intData[2];
-        if (ret_size == 1 && data1 == 0)
-            neg = 0;
-        /* 0x80 or greater positive number in first byte */
-        if (!neg && (data1 > 127)){
-            pad = 1;
-            pad_val = 0;
-        } else if (neg){
-            /* negative number */
-            if (data1 > 128){
-                pad = 1;
-                pad_val = 0xff;
-            } else if (data1 == 128){
-                for (i = 3; i < a->intData[1] + 2; i++){
-                    if (a->intData[i]){
-                        pad = 1;
-                        pad_val = 0xff;
-                        break;
-                    }
-                }
-            }
-        }
-        ret_size += (int)pad;
-    }
-    if (pp == NULL)
-        return ret_size;
-
-    pptr = *pp;
-    if (pad)
-        *(pptr++) = pad_val;
-    if (a->intData[1] == 0)
-        *(pptr++) = 0;
-    else if (!neg){
-        /* positive number */
-        for (i=0; i < a->intData[1]; i++){
-            *pptr = a->intData[i+2];
-            pptr++;
-        }
-    } else {
-        /* negative number */
-        int str_len = 0;
-
-        /* 0 padding from end of buffer */
-        str_len = (int)a->intData[1];
-        pptr += a->intData[1] - 1;
-        while (!a->intData[str_len + 2] && str_len > 1){
-            *(pptr--) = 0;
-            str_len--;
-        }
-        /* 2's complement next octet */
-        *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1;
-        str_len--;
-        /* Complement any octets left */
-        while (str_len > 0){
-            *(pptr--) = a->intData[str_len + 1] ^ 0xff;
-            str_len--;
-        }
-    }
-    *pp += ret_size;
-    return ret_size;
-}
-#endif /* !NO_ASN */
-
-#endif  /* OPENSSLEXTRA */
-
+/* ssl.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef HAVE_ERRNO_H
+    #include <errno.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfcrypt/coding.h>
+#ifdef NO_INLINE
+    #include <wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+
+#ifndef WOLFSSL_ALLOW_NO_SUITES
+    #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
+                && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
+                && !defined(HAVE_ED25519)
+        #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
+    #endif
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+        defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN)
+    #include <wolfssl/openssl/evp.h>
+    /* openssl headers end, wolfssl internal headers next */
+#endif
+
+#include <wolfcrypt/wc_encrypt.h>
+
+#ifdef OPENSSL_EXTRA
+    /* openssl headers begin */
+    #include <wolfssl/openssl/aes.h>
+    #include <wolfssl/openssl/hmac.h>
+    #include <wolfssl/openssl/crypto.h>
+    #include <wolfssl/openssl/des.h>
+    #include <wolfssl/openssl/bn.h>
+    #include <wolfssl/openssl/buffer.h>
+    #include <wolfssl/openssl/dh.h>
+    #include <wolfssl/openssl/rsa.h>
+    #include <wolfssl/openssl/pem.h>
+    #include <wolfssl/openssl/ec.h>
+    #include <wolfssl/openssl/ec25519.h>
+    #include <wolfssl/openssl/ed25519.h>
+    #include <wolfssl/openssl/ecdsa.h>
+    #include <wolfssl/openssl/ecdh.h>
+    #include <wolfssl/openssl/rc4.h>
+    /* openssl headers end, wolfssl internal headers next */
+    #include <wolfcrypt/hmac.h>
+    #include <wolfcrypt/random.h>
+    #include <wolfcrypt/des3.h>
+    #include <wolfcrypt/md4.h>
+    #include <wolfcrypt/md5.h>
+    #include <wolfcrypt/arc4.h>
+    #include <wolfcrypt/idea.h>
+    #include <wolfcrypt/curve25519.h>
+    #include <wolfcrypt/ed25519.h>
+    #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
+        #include <wolfssl/openssl/ocsp.h>
+    #endif /* WITH_STUNNEL */
+    #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
+        #include <wolfcrypt/sha512.h>
+    #endif
+    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+        && !defined(WC_NO_RNG)
+        #include <wolfcrypt/srp.h>
+        #include <wolfcrypt/random.h>
+    #endif
+#endif
+
+#ifdef NO_ASN
+    #include <wolfcrypt/dh.h>
+#endif
+
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_session_import");
+
+    if (ssl == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* sanity checks on buffer and protocol are done in internal function */
+    return wolfSSL_dtls_import_internal(ssl, buf, sz);
+}
+
+
+/* Sets the function to call for serializing the session. This function is
+ * called right after the handshake is completed. */
+int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func)
+{
+
+    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
+
+    /* purposefully allow func to be NULL */
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->dtls_export = func;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Sets the function in WOLFSSL struct to call for serializing the session. This
+ * function is called right after the handshake is completed. */
+int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
+{
+
+    WOLFSSL_ENTER("wolfSSL_dtls_set_export");
+
+    /* purposefully allow func to be NULL */
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_export = func;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* This function allows for directly serializing a session rather than using
+ * callbacks. It has less overhead by removing a temporary buffer and gives
+ * control over when the session gets serialized. When using callbacks the
+ * session is always serialized immediatly after the handshake is finished.
+ *
+ * buf is the argument to contain the serialized session
+ * sz  is the size of the buffer passed in
+ * ssl is the WOLFSSL struct to serialize
+ * returns the size of serialized session on success, 0 on no action, and
+ *         negative value on error */
+int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_export");
+
+    if (ssl == NULL || sz == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (buf == NULL) {
+        *sz = MAX_EXPORT_BUFFER;
+        return 0;
+    }
+
+    /* if not DTLS do nothing */
+    if (!ssl->options.dtls) {
+        WOLFSSL_MSG("Currently only DTLS export is supported");
+        return 0;
+    }
+
+    /* copy over keys, options, and dtls state struct */
+    return wolfSSL_dtls_export_internal(ssl, buf, *sz);
+}
+
+
+/* returns 0 on success */
+int wolfSSL_send_session(WOLFSSL* ssl)
+{
+    int ret;
+    byte* buf;
+    word16 bufSz = MAX_EXPORT_BUFFER;
+
+    WOLFSSL_ENTER("wolfSSL_send_session");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL) {
+        return MEMORY_E;
+    }
+
+    /* if not DTLS do nothing */
+    if (!ssl->options.dtls) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        WOLFSSL_MSG("Currently only DTLS export is supported");
+        return 0;
+    }
+
+    /* copy over keys, options, and dtls state struct */
+    ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz);
+    if (ret < 0) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    /* if no error ret has size of buffer */
+    ret = ssl->dtls_export(ssl, buf, ret, NULL);
+    if (ret != WOLFSSL_SUCCESS) {
+        XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return 0;
+}
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+
+/* prevent multiple mutex initializations */
+static volatile int initRefCount = 0;
+static wolfSSL_Mutex count_mutex;   /* init ref count mutex */
+
+/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
+   WOLFSSL_METHOD pointer passed in is given to ctx to manage.
+   This function frees the passed in WOLFSSL_METHOD struct on failure and on
+   success is freed when ctx is freed.
+ */
+WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
+{
+    WOLFSSL_CTX* ctx = NULL;
+
+    WOLFSSL_ENTER("WOLFSSL_CTX_new_ex");
+
+    if (initRefCount == 0) {
+        /* user no longer forced to call Init themselves */
+        int ret = wolfSSL_Init();
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_Init failed");
+            WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
+            if (method != NULL) {
+                XFREE(method, heap, DYNAMIC_TYPE_METHOD);
+            }
+            return NULL;
+        }
+    }
+
+    if (method == NULL)
+        return ctx;
+
+    ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
+    if (ctx) {
+        if (InitSSL_Ctx(ctx, method, heap) < 0) {
+            WOLFSSL_MSG("Init CTX failed");
+            wolfSSL_CTX_free(ctx);
+            ctx = NULL;
+        }
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+                           && !defined(NO_SHA256) && !defined(WC_NO_RNG)
+        else {
+            ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
+            if (ctx->srp == NULL){
+                WOLFSSL_MSG("Init CTX failed");
+                wolfSSL_CTX_free(ctx);
+                return NULL;
+            }
+            XMEMSET(ctx->srp, 0, sizeof(Srp));
+        }
+#endif
+    }
+    else {
+        WOLFSSL_MSG("Alloc CTX failed, method freed");
+        XFREE(method, heap, DYNAMIC_TYPE_METHOD);
+    }
+
+
+    WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0);
+    return ctx;
+}
+
+
+WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
+{
+#ifdef WOLFSSL_HEAP_TEST
+    /* if testing the heap hint then set top level CTX to have test value */
+    return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST);
+#else
+    return wolfSSL_CTX_new_ex(method, NULL);
+#endif
+}
+
+
+void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("SSL_CTX_free");
+    if (ctx) {
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
+&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
+        if (ctx->srp != NULL){
+            if (ctx->srp_password != NULL){
+                XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+            }
+            wc_SrpTerm(ctx->srp);
+            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+        }
+#endif
+        FreeSSL_Ctx(ctx);
+    }
+
+    WOLFSSL_LEAVE("SSL_CTX_free", 0);
+}
+
+
+#ifdef SINGLE_THREADED
+/* no locking in single threaded mode, allow a CTX level rng to be shared with
+ * WOLFSSL objects, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx)
+{
+    WC_RNG* rng;
+    int     ret;
+
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    rng = XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
+    if (rng == NULL) {
+        return MEMORY_E;
+    }
+
+#ifndef HAVE_FIPS
+    ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId);
+#else
+    ret = wc_InitRng(rng);
+#endif
+    if (ret != 0) {
+        XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+        return ret;
+    }
+
+    ctx->rng = rng;
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL* ssl = NULL;
+    int ret = 0;
+
+    (void)ret;
+    WOLFSSL_ENTER("SSL_new");
+
+    if (ctx == NULL)
+        return ssl;
+
+    ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
+    if (ssl)
+        if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
+            FreeSSL(ssl, ctx->heap);
+            ssl = 0;
+        }
+
+    WOLFSSL_LEAVE("SSL_new", ret);
+    return ssl;
+}
+
+
+void wolfSSL_free(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_free");
+    if (ssl)
+        FreeSSL(ssl, ssl->ctx->heap);
+    WOLFSSL_LEAVE("SSL_free", 0);
+}
+
+
+int wolfSSL_is_server(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+    return ssl->options.side == WOLFSSL_SERVER_END;
+}
+
+#ifdef HAVE_WRITE_DUP
+
+/*
+ * Release resources around WriteDup object
+ *
+ * ssl WOLFSSL object
+ *
+ * no return, destruction so make best attempt
+*/
+void FreeWriteDup(WOLFSSL* ssl)
+{
+    int doFree = 0;
+
+    WOLFSSL_ENTER("FreeWriteDup");
+
+    if (ssl->dupWrite) {
+        if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
+            ssl->dupWrite->dupCount--;
+            if (ssl->dupWrite->dupCount == 0) {
+                doFree = 1;
+            } else {
+                WOLFSSL_MSG("WriteDup count not zero, no full free");
+            }
+            wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+        }
+    }
+
+    if (doFree) {
+        WOLFSSL_MSG("Doing WriteDup full free, count to zero");
+        wc_FreeMutex(&ssl->dupWrite->dupMutex);
+        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+    }
+}
+
+
+/*
+ * duplicate existing ssl members into dup needed for writing
+ *
+ * dup write only WOLFSSL
+ * ssl exisiting WOLFSSL
+ *
+ * 0 on success
+*/
+static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
+{
+    /* shared dupWrite setup */
+    ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
+                                       DYNAMIC_TYPE_WRITEDUP);
+    if (ssl->dupWrite == NULL) {
+        return MEMORY_E;
+    }
+    XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
+
+    if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
+        XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
+        ssl->dupWrite = NULL;
+        return BAD_MUTEX_E;
+    }
+    ssl->dupWrite->dupCount = 2;    /* both sides have a count to start */
+    dup->dupWrite = ssl->dupWrite; /* each side uses */
+
+    /* copy write parts over to dup writer */
+    XMEMCPY(&dup->specs,   &ssl->specs,   sizeof(CipherSpecs));
+    XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
+    XMEMCPY(&dup->keys,    &ssl->keys,    sizeof(Keys));
+    XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
+    /* dup side now owns encrypt/write ciphers */
+    XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
+
+    dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
+    dup->wfd    = ssl->wfd;
+    dup->wflags = ssl->wflags;
+    dup->hmac   = ssl->hmac;
+#ifdef HAVE_TRUNCATED_HMAC
+    dup->truncated_hmac = ssl->truncated_hmac;
+#endif
+
+    /* unique side dup setup */
+    dup->dupSide = WRITE_DUP_SIDE;
+    ssl->dupSide = READ_DUP_SIDE;
+
+    return 0;
+}
+
+
+/*
+ * duplicate a WOLFSSL object post handshake for writing only
+ * turn exisitng object into read only.  Allows concurrent access from two
+ * different threads.
+ *
+ * ssl exisiting WOLFSSL object
+ *
+ * return dup'd WOLFSSL object on success
+*/
+WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
+{
+    WOLFSSL* dup = NULL;
+    int ret = 0;
+
+    (void)ret;
+    WOLFSSL_ENTER("wolfSSL_write_dup");
+
+    if (ssl == NULL) {
+        return ssl;
+    }
+
+    if (ssl->options.handShakeDone == 0) {
+        WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
+        return NULL;
+    }
+
+    if (ssl->dupWrite) {
+        WOLFSSL_MSG("wolfSSL_write_dup already called once");
+        return NULL;
+    }
+
+    dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
+    if (dup) {
+        if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
+            FreeSSL(dup, ssl->ctx->heap);
+            dup = NULL;
+        } else if ( (ret = DupSSL(dup, ssl) < 0)) {
+            FreeSSL(dup, ssl->ctx->heap);
+            dup = NULL;
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
+
+    return dup;
+}
+
+
+/*
+ * Notify write dup side of fatal error or close notify
+ *
+ * ssl WOLFSSL object
+ * err Notify err
+ *
+ * 0 on success
+*/
+int NotifyWriteSide(WOLFSSL* ssl, int err)
+{
+    int ret;
+
+    WOLFSSL_ENTER("NotifyWriteSide");
+
+    ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
+    if (ret == 0) {
+        ssl->dupWrite->dupErr = err;
+        ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+    }
+
+    return ret;
+}
+
+
+#endif /* HAVE_WRITE_DUP */
+
+
+#ifdef HAVE_POLY1305
+/* set if to use old poly 1 for yes 0 to use new poly */
+int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
+{
+    (void)ssl;
+    (void)value;
+
+#ifndef WOLFSSL_NO_TLS12
+    WOLFSSL_ENTER("SSL_use_old_poly");
+    WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
+            "is depriciated");
+    ssl->options.oldPoly = (word16)value;
+    WOLFSSL_LEAVE("SSL_use_old_poly", 0);
+#endif
+    return 0;
+}
+#endif
+
+
+int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
+{
+    int ret;
+
+    WOLFSSL_ENTER("SSL_set_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfSSL_set_read_fd(ssl, fd);
+    if (ret == WOLFSSL_SUCCESS) {
+        ret = wolfSSL_set_write_fd(ssl, fd);
+    }
+
+    return ret;
+}
+
+
+int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
+{
+    WOLFSSL_ENTER("SSL_set_read_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->rfd = fd;      /* not used directly to allow IO callbacks */
+    ssl->IOCB_ReadCtx  = &ssl->rfd;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
+            ssl->buffers.dtlsCtx.rfd = fd;
+        }
+    #endif
+
+    WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
+{
+    WOLFSSL_ENTER("SSL_set_write_fd");
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->wfd = fd;      /* not used directly to allow IO callbacks */
+    ssl->IOCB_WriteCtx  = &ssl->wfd;
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->options.dtls) {
+            ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
+            ssl->buffers.dtlsCtx.wfd = fd;
+        }
+    #endif
+
+    WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS);
+    return WOLFSSL_SUCCESS;
+}
+
+
+/**
+  * Get the name of cipher at priority level passed in.
+  */
+char* wolfSSL_get_cipher_list(int priority)
+{
+    const CipherSuiteInfo* ciphers = GetCipherNames();
+
+    if (priority >= GetCipherNamesSize() || priority < 0) {
+        return 0;
+    }
+
+    return (char*)ciphers[priority].name;
+}
+
+
+/**
+  * Get the name of cipher at priority level passed in.
+  */
+char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority)
+{
+
+    if (ssl == NULL) {
+        return NULL;
+    }
+    else {
+        const char* cipher;
+
+        if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) {
+            if (priority == 0) {
+                return (char*)cipher;
+            }
+            else {
+                return NULL;
+            }
+        }
+        else {
+            return wolfSSL_get_cipher_list(priority);
+        }
+    }
+}
+
+
+int wolfSSL_get_ciphers(char* buf, int len)
+{
+    const CipherSuiteInfo* ciphers = GetCipherNames();
+    int  totalInc = 0;
+    int  step     = 0;
+    char delim    = ':';
+    int  size     = GetCipherNamesSize();
+    int  i;
+
+    if (buf == NULL || len <= 0)
+        return BAD_FUNC_ARG;
+
+    /* Add each member to the buffer delimited by a : */
+    for (i = 0; i < size; i++) {
+        step = (int)(XSTRLEN(ciphers[i].name) + 1);  /* delimiter */
+        totalInc += step;
+
+        /* Check to make sure buf is large enough and will not overflow */
+        if (totalInc < len) {
+            size_t cipherLen = XSTRLEN(ciphers[i].name);
+            XSTRNCPY(buf, ciphers[i].name, cipherLen);
+            buf += cipherLen;
+
+            if (i < size - 1)
+                *buf++ = delim;
+            else
+                *buf++ = '\0';
+        }
+        else
+            return BUFFER_E;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
+{
+    const char* cipher;
+
+    if (ssl == NULL)
+        return NULL;
+
+    cipher = wolfSSL_get_cipher_name_iana(ssl);
+    len = min(len, (int)(XSTRLEN(cipher) + 1));
+    XMEMCPY(buf, cipher, len);
+    return buf;
+}
+
+int wolfSSL_get_fd(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_fd");
+    WOLFSSL_LEAVE("SSL_get_fd", ssl->rfd);
+    return ssl->rfd;
+}
+
+
+int wolfSSL_dtls(WOLFSSL* ssl)
+{
+    return ssl->options.dtls;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
+{
+#ifdef WOLFSSL_DTLS
+    void* sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
+    if (sa != NULL) {
+        if (ssl->buffers.dtlsCtx.peer.sa != NULL)
+            XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
+        XMEMCPY(sa, peer, peerSz);
+        ssl->buffers.dtlsCtx.peer.sa = sa;
+        ssl->buffers.dtlsCtx.peer.sz = peerSz;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+#else
+    (void)ssl;
+    (void)peer;
+    (void)peerSz;
+    return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
+
+int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
+{
+#ifdef WOLFSSL_DTLS
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (peer != NULL && peerSz != NULL
+            && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
+            && ssl->buffers.dtlsCtx.peer.sa != NULL) {
+        *peerSz = ssl->buffers.dtlsCtx.peer.sz;
+        XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+#else
+    (void)ssl;
+    (void)peer;
+    (void)peerSz;
+    return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
+
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->dtlsSctp = 1;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.dtlsSctp = 1;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
+{
+    if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
+        return BAD_FUNC_ARG;
+
+    ctx->dtlsMtuSz = newMtu;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (newMtu > MAX_RECORD_SIZE) {
+        ssl->error = BAD_FUNC_ARG;
+        return WOLFSSL_FAILURE;
+    }
+
+    ssl->dtlsMtuSz = newMtu;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
+
+
+#ifdef WOLFSSL_DTLS_DROP_STATS
+
+int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
+                                word32* macDropCount, word32* replayDropCount)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()");
+
+    if (ssl == NULL)
+        ret = BAD_FUNC_ARG;
+    else {
+        ret = WOLFSSL_SUCCESS;
+        if (macDropCount != NULL)
+            *macDropCount = ssl->macDropCount;
+        if (replayDropCount != NULL)
+            *replayDropCount = ssl->replayDropCount;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret);
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+
+
+#if defined(WOLFSSL_MULTICAST)
+
+int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()");
+
+    if (ctx == NULL || id > 255)
+        ret = BAD_FUNC_ARG;
+
+    if (ret == 0) {
+        ctx->haveEMS = 0;
+        ctx->haveMcast = 1;
+        ctx->mcastID = id;
+#ifndef WOLFSSL_USER_IO
+        ctx->CBIORecv = EmbedReceiveFromMcast;
+#endif /* WOLFSSL_USER_IO */
+    }
+
+    if (ret == 0)
+        ret = WOLFSSL_SUCCESS;
+    WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret);
+    return ret;
+}
+
+int wolfSSL_mcast_get_max_peers(void)
+{
+    return WOLFSSL_MULTICAST_PEERS;
+}
+
+#ifdef WOLFSSL_DTLS
+static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
+                                         word32 second, word32 max)
+{
+    word32 newCur = 0;
+
+    if (cur < first)
+        newCur = first;
+    else if (cur < second)
+        newCur = second;
+    else if (cur < max)
+        newCur = max;
+
+    return newCur;
+}
+#endif /* WOLFSSL_DTLS */
+
+
+int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
+                       const byte* preMasterSecret, word32 preMasterSz,
+                       const byte* clientRandom, const byte* serverRandom,
+                       const byte* suite)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_secret()");
+
+    if (ssl == NULL || preMasterSecret == NULL ||
+        preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
+        clientRandom == NULL || serverRandom == NULL || suite == NULL) {
+
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
+        ssl->arrays->preMasterSz = preMasterSz;
+        XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
+        XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
+        ssl->options.cipherSuite0 = suite[0];
+        ssl->options.cipherSuite = suite[1];
+
+        ret = SetCipherSpecs(ssl);
+    }
+
+    if (ret == 0)
+        ret = MakeTlsMasterSecret(ssl);
+
+    if (ret == 0) {
+        ssl->keys.encryptionOn = 1;
+        ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
+    }
+
+    if (ret == 0) {
+        if (ssl->options.dtls) {
+        #ifdef WOLFSSL_DTLS
+            WOLFSSL_DTLS_PEERSEQ* peerSeq;
+            int i;
+
+            ssl->keys.dtls_epoch = epoch;
+            for (i = 0, peerSeq = ssl->keys.peerSeq;
+                 i < WOLFSSL_DTLS_PEERSEQ_SZ;
+                 i++, peerSeq++) {
+
+                peerSeq->nextEpoch = epoch;
+                peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
+                peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
+                peerSeq->nextSeq_lo = 0;
+                peerSeq->nextSeq_hi = 0;
+                XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
+                XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
+                peerSeq->highwaterMark = UpdateHighwaterMark(0,
+                        ssl->ctx->mcastFirstSeq,
+                        ssl->ctx->mcastSecondSeq,
+                        ssl->ctx->mcastMaxSeq);
+            }
+        #else
+            (void)epoch;
+        #endif
+        }
+        FreeHandshakeResources(ssl);
+        ret = WOLFSSL_SUCCESS;
+    }
+    else {
+        if (ssl)
+            ssl->error = ret;
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    WOLFSSL_LEAVE("wolfSSL_set_secret()", ret);
+    return ret;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove)
+{
+    WOLFSSL_DTLS_PEERSEQ* p = NULL;
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_peer_add()");
+    if (ssl == NULL || peerId > 255)
+        return BAD_FUNC_ARG;
+
+    if (!remove) {
+        /* Make sure it isn't already present, while keeping the first
+         * open spot. */
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+            if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
+                p = &ssl->keys.peerSeq[i];
+            if (ssl->keys.peerSeq[i].peerId == peerId) {
+                WOLFSSL_MSG("Peer ID already in multicast peer list.");
+                p = NULL;
+            }
+        }
+
+        if (p != NULL) {
+            XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
+            p->peerId = peerId;
+            p->highwaterMark = UpdateHighwaterMark(0,
+                ssl->ctx->mcastFirstSeq,
+                ssl->ctx->mcastSecondSeq,
+                ssl->ctx->mcastMaxSeq);
+        }
+        else {
+            WOLFSSL_MSG("No room in peer list.");
+            ret = -1;
+        }
+    }
+    else {
+        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+            if (ssl->keys.peerSeq[i].peerId == peerId)
+                p = &ssl->keys.peerSeq[i];
+        }
+
+        if (p != NULL) {
+            p->peerId = INVALID_PEER_ID;
+        }
+        else {
+            WOLFSSL_MSG("Peer not found in list.");
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret);
+    return ret;
+}
+
+
+/* If peerId is in the list of peers and its last sequence number is non-zero,
+ * return 1, otherwise return 0. */
+int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
+{
+    int known = 0;
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_peer_known()");
+
+    if (ssl == NULL || peerId > 255) {
+        return BAD_FUNC_ARG;
+    }
+
+    for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
+        if (ssl->keys.peerSeq[i].peerId == peerId) {
+            if (ssl->keys.peerSeq[i].nextSeq_hi ||
+                ssl->keys.peerSeq[i].nextSeq_lo) {
+
+                known = 1;
+            }
+            break;
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known);
+    return known;
+}
+
+
+int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
+                                       word32 first, word32 second,
+                                       CallbackMcastHighwater cb)
+{
+    if (ctx == NULL || (second && first > second) ||
+        first > maxSeq || second > maxSeq || cb == NULL) {
+
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->mcastHwCb = cb;
+    ctx->mcastFirstSeq = first;
+    ctx->mcastSecondSeq = second;
+    ctx->mcastMaxSeq = maxSeq;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
+{
+    if (ssl == NULL || ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->mcastHwCbCtx = ctx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_DTLS */
+
+#endif /* WOLFSSL_MULTICAST */
+
+
+#endif /* WOLFSSL_LEANPSK */
+
+
+/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
+int wolfSSL_negotiate(WOLFSSL* ssl)
+{
+    int err = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_negotiate");
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            err = wolfSSL_accept_TLSv13(ssl);
+        else
+#endif
+            err = wolfSSL_accept(ssl);
+    }
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+#ifdef WOLFSSL_TLS13
+        if (IsAtLeastTLSv1_3(ssl->version))
+            err = wolfSSL_connect_TLSv13(ssl);
+        else
+#endif
+            err = wolfSSL_connect(ssl);
+    }
+#endif
+
+    (void)ssl;
+
+    WOLFSSL_LEAVE("wolfSSL_negotiate", err);
+
+    return err;
+}
+
+
+WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
+{
+    if (ssl) {
+        return ssl->rng;
+    }
+
+    return NULL;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+/* object size based on build */
+int wolfSSL_GetObjectSize(void)
+{
+#ifdef SHOW_SIZES
+    printf("sizeof suites           = %lu\n", sizeof(Suites));
+    printf("sizeof ciphers(2)       = %lu\n", sizeof(Ciphers));
+#ifndef NO_RC4
+    printf("\tsizeof arc4         = %lu\n", sizeof(Arc4));
+#endif
+    printf("\tsizeof aes          = %lu\n", sizeof(Aes));
+#ifndef NO_DES3
+    printf("\tsizeof des3         = %lu\n", sizeof(Des3));
+#endif
+#ifndef NO_RABBIT
+    printf("\tsizeof rabbit       = %lu\n", sizeof(Rabbit));
+#endif
+#ifdef HAVE_CHACHA
+    printf("\tsizeof chacha       = %lu\n", sizeof(ChaCha));
+#endif
+    printf("sizeof cipher specs     = %lu\n", sizeof(CipherSpecs));
+    printf("sizeof keys             = %lu\n", sizeof(Keys));
+    printf("sizeof Hashes(2)        = %lu\n", sizeof(Hashes));
+#ifndef NO_MD5
+    printf("\tsizeof MD5          = %lu\n", sizeof(wc_Md5));
+#endif
+#ifndef NO_SHA
+    printf("\tsizeof SHA          = %lu\n", sizeof(wc_Sha));
+#endif
+#ifdef WOLFSSL_SHA224
+    printf("\tsizeof SHA224       = %lu\n", sizeof(wc_Sha224));
+#endif
+#ifndef NO_SHA256
+    printf("\tsizeof SHA256       = %lu\n", sizeof(wc_Sha256));
+#endif
+#ifdef WOLFSSL_SHA384
+    printf("\tsizeof SHA384       = %lu\n", sizeof(wc_Sha384));
+#endif
+#ifdef WOLFSSL_SHA384
+    printf("\tsizeof SHA512       = %lu\n", sizeof(wc_Sha512));
+#endif
+    printf("sizeof Buffers          = %lu\n", sizeof(Buffers));
+    printf("sizeof Options          = %lu\n", sizeof(Options));
+    printf("sizeof Arrays           = %lu\n", sizeof(Arrays));
+#ifndef NO_RSA
+    printf("sizeof RsaKey           = %lu\n", sizeof(RsaKey));
+#endif
+#ifdef HAVE_ECC
+    printf("sizeof ecc_key          = %lu\n", sizeof(ecc_key));
+#endif
+    printf("sizeof WOLFSSL_CIPHER    = %lu\n", sizeof(WOLFSSL_CIPHER));
+    printf("sizeof WOLFSSL_SESSION   = %lu\n", sizeof(WOLFSSL_SESSION));
+    printf("sizeof WOLFSSL           = %lu\n", sizeof(WOLFSSL));
+    printf("sizeof WOLFSSL_CTX       = %lu\n", sizeof(WOLFSSL_CTX));
+#endif
+
+    return sizeof(WOLFSSL);
+}
+
+int wolfSSL_CTX_GetObjectSize(void)
+{
+    return sizeof(WOLFSSL_CTX);
+}
+
+int wolfSSL_METHOD_GetObjectSize(void)
+{
+    return sizeof(WOLFSSL_METHOD);
+}
+#endif
+
+
+#ifdef WOLFSSL_STATIC_MEMORY
+
+int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method,
+                                   unsigned char* buf, unsigned int sz,
+                                   int flag, int max)
+{
+    WOLFSSL_HEAP*      heap;
+    WOLFSSL_HEAP_HINT* hint;
+    word32 idx = 0;
+
+    if (ctx == NULL || buf == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (*ctx == NULL && method == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    if (*ctx == NULL || (*ctx)->heap == NULL) {
+        if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) {
+            return BUFFER_E; /* not enough memory for structures */
+        }
+        heap = (WOLFSSL_HEAP*)buf;
+        idx += sizeof(WOLFSSL_HEAP);
+        if (wolfSSL_init_memory_heap(heap) != 0) {
+            return WOLFSSL_FAILURE;
+        }
+        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
+        idx += sizeof(WOLFSSL_HEAP_HINT);
+        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
+        hint->memory = heap;
+
+        if (*ctx && (*ctx)->heap == NULL) {
+            (*ctx)->heap = (void*)hint;
+        }
+    }
+    else {
+#ifdef WOLFSSL_HEAP_TEST
+        /* do not load in memory if test has been set */
+        if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) {
+            return WOLFSSL_SUCCESS;
+        }
+#endif
+        hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap);
+        heap = hint->memory;
+    }
+
+    if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) {
+        WOLFSSL_MSG("Error partitioning memory");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create ctx if needed */
+    if (*ctx == NULL) {
+        *ctx = wolfSSL_CTX_new_ex(method(hint), hint);
+        if (*ctx == NULL) {
+            WOLFSSL_MSG("Error creating ctx");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* determine what max applies too */
+    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
+        heap->maxIO = max;
+    }
+    else { /* general memory used in handshakes */
+        heap->maxHa = max;
+    }
+
+    heap->flag |= flag;
+
+    (void)max;
+    (void)method;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    WOLFSSL_ENTER("wolfSSL_is_static_memory");
+
+    /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
+    if (mem_stats != NULL && ssl->heap != NULL) {
+        WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
+        WOLFSSL_HEAP* heap      = hint->memory;
+        if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) {
+            XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
+        }
+    }
+
+    return (ssl->heap) ? 1 : 0;
+}
+
+
+int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+    WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
+
+    /* fill out statistics if wanted */
+    if (mem_stats != NULL && ctx->heap != NULL) {
+        WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
+        if (wolfSSL_GetMemStats(heap, mem_stats) != 1) {
+            return MEMORY_E;
+        }
+    }
+
+    return (ctx->heap) ? 1 : 0;
+}
+
+#endif /* WOLFSSL_STATIC_MEMORY */
+
+
+/* return max record layer size plaintext input size */
+int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        WOLFSSL_MSG("Handshake not complete yet");
+        return BAD_FUNC_ARG;
+    }
+
+    return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE);
+}
+
+
+/* return record layer size of plaintext input size */
+int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
+{
+    int maxSize;
+
+    WOLFSSL_ENTER("wolfSSL_GetOutputSize");
+
+    if (inSz < 0)
+        return BAD_FUNC_ARG;
+
+    maxSize = wolfSSL_GetMaxOutputSize(ssl);
+    if (maxSize < 0)
+        return maxSize;   /* error */
+    if (inSz > maxSize)
+        return INPUT_SIZE_E;
+
+    return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0);
+}
+
+
+#ifdef HAVE_ECC
+int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisable by 8 or ctx was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->minEccKeySz     = keySz / 8;
+#ifndef NO_CERTS
+    ctx->cm->minEccKeySz = keySz / 8;
+#endif
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
+{
+    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisable by 8 or ssl was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->options.minEccKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* !NO_RSA */
+
+#ifndef NO_RSA
+int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
+{
+    if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisable by 8 or ctx was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ctx->minRsaKeySz     = keySz / 8;
+    ctx->cm->minRsaKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
+{
+    if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
+        WOLFSSL_MSG("Key size must be divisable by 8 or ssl was null");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->options.minRsaKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !NO_RSA */
+
+#ifndef NO_DH
+/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
+                    const unsigned char* g, int gSz)
+{
+    word16 havePSK = 0;
+    word16 haveRSA = 1;
+    int    keySz   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_SetTmpDH");
+    if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
+
+    if (pSz < ssl->options.minDhKeySz)
+        return DH_KEY_SIZE_E;
+    if (pSz > ssl->options.maxDhKeySz)
+        return DH_KEY_SIZE_E;
+
+    if (ssl->options.side != WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+    }
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_G.buffer = NULL;
+    }
+
+    ssl->buffers.weOwnDH = 1;  /* SSL owns now */
+    ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap,
+                                                    DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_P.buffer == NULL)
+            return MEMORY_E;
+
+    ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap,
+                                                    DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ssl->buffers.serverDH_G.buffer == NULL) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        ssl->buffers.serverDH_P.buffer = NULL;
+        return MEMORY_E;
+    }
+
+    ssl->buffers.serverDH_P.length = pSz;
+    ssl->buffers.serverDH_G.length = gSz;
+
+    XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz);
+    XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz);
+
+    ssl->options.haveDH = 1;
+    #ifndef NO_PSK
+        havePSK = ssl->options.havePSK;
+    #endif
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+               ssl->options.haveDH, ssl->options.haveNTRU,
+               ssl->options.haveECDSAsig, ssl->options.haveECC,
+               ssl->options.haveStaticECC, ssl->options.side);
+
+    WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0);
+    return WOLFSSL_SUCCESS;
+}
+
+/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
+                         const unsigned char* g, int gSz)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
+    if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG;
+
+    if (pSz < ctx->minDhKeySz)
+        return DH_KEY_SIZE_E;
+    if (pSz > ctx->maxDhKeySz)
+        return DH_KEY_SIZE_E;
+
+    XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ctx->serverDH_P.buffer == NULL)
+       return MEMORY_E;
+
+    ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (ctx->serverDH_G.buffer == NULL) {
+        XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return MEMORY_E;
+    }
+
+    ctx->serverDH_P.length = pSz;
+    ctx->serverDH_G.length = gSz;
+
+    XMEMCPY(ctx->serverDH_P.buffer, p, pSz);
+    XMEMCPY(ctx->serverDH_G.buffer, g, gSz);
+
+    ctx->haveDH = 1;
+
+    WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ctx->minDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ssl->options.minDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz)
+{
+    if (ctx == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ctx->maxDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz)
+{
+    if (ssl == NULL || keySz > 16000 || keySz % 8 != 0)
+        return BAD_FUNC_ARG;
+
+    ssl->options.maxDhKeySz = keySz / 8;
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return (ssl->options.dhKeySz * 8);
+}
+
+#endif /* !NO_DH */
+
+
+int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
+{
+    int ret;
+
+    WOLFSSL_ENTER("SSL_write()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) {
+        ssl->error = ret;
+        return WOLFSSL_FATAL_ERROR;
+    }
+    ssl->earlyData = no_early_data;
+#endif
+
+#ifdef HAVE_WRITE_DUP
+    { /* local variable scope */
+        int dupErr = 0;   /* local copy */
+
+        ret = 0;
+
+        if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
+            WOLFSSL_MSG("Read dup side cannot write");
+            return WRITE_DUP_WRITE_E;
+        }
+        if (ssl->dupWrite) {
+            if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
+                return BAD_MUTEX_E;
+            }
+            dupErr = ssl->dupWrite->dupErr;
+            ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
+        }
+
+        if (ret != 0) {
+            ssl->error = ret;  /* high priority fatal error */
+            return WOLFSSL_FATAL_ERROR;
+        }
+        if (dupErr != 0) {
+            WOLFSSL_MSG("Write dup error from other side");
+            ssl->error = dupErr;
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+#ifdef HAVE_ERRNO_H
+    errno = 0;
+#endif
+
+    #ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL) {
+        ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS);
+        ssl->cbmode = SSL_CB_WRITE;
+    }
+    #endif
+    ret = SendData(ssl, data, sz);
+
+    WOLFSSL_LEAVE("SSL_write()", ret);
+
+    if (ret < 0)
+        return WOLFSSL_FATAL_ERROR;
+    else
+        return ret;
+}
+
+static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_read_internal()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
+        WOLFSSL_MSG("Write dup side cannot read");
+        return WRITE_DUP_READ_E;
+    }
+#endif
+
+#ifdef HAVE_ERRNO_H
+        errno = 0;
+#endif
+
+#ifdef WOLFSSL_DTLS
+    if (ssl->options.dtls) {
+        ssl->dtls_expected_rx = max(sz + 100, MAX_MTU);
+#ifdef WOLFSSL_SCTP
+        if (ssl->options.dtlsSctp)
+            ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz);
+#endif
+    }
+#endif
+
+    sz = wolfSSL_GetMaxRecordSize(ssl, sz);
+
+    ret = ReceiveData(ssl, (byte*)data, sz, peek);
+
+#ifdef HAVE_WRITE_DUP
+    if (ssl->dupWrite) {
+        if (ssl->error != 0 && ssl->error != WANT_READ
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            && ssl->error != WC_PENDING_E
+        #endif
+        ) {
+            int notifyErr;
+
+            WOLFSSL_MSG("Notifying write side of fatal read error");
+            notifyErr  = NotifyWriteSide(ssl, ssl->error);
+            if (notifyErr < 0) {
+                ret = ssl->error = notifyErr;
+            }
+        }
+    }
+#endif
+
+    WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
+
+    if (ret < 0)
+        return WOLFSSL_FATAL_ERROR;
+    else
+        return ret;
+}
+
+
+int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_peek()");
+
+    return wolfSSL_read_internal(ssl, data, sz, TRUE);
+}
+
+
+int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_read()");
+
+    #ifdef OPENSSL_EXTRA
+    if (ssl->CBIS != NULL) {
+        ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS);
+        ssl->cbmode = SSL_CB_READ;
+    }
+    #endif
+    return wolfSSL_read_internal(ssl, data, sz, FALSE);
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+
+int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_mcast_read()");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
+    if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
+        *id = ssl->keys.curPeerId;
+    return ret;
+}
+
+#endif /* WOLFSSL_MULTICAST */
+
+
+/* helpers to set the device id, WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetDevId(WOLFSSL* ssl, int devId)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->devId = devId;
+
+    return WOLFSSL_SUCCESS;
+}
+int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->devId = devId;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* helpers to get device id and heap */
+int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+    int devId = INVALID_DEVID;
+    if (ctx != NULL)
+        devId = ctx->devId;
+    else if (ssl != NULL)
+        devId = ssl->devId;
+    return devId;
+}
+void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
+{
+    void* heap = NULL;
+    if (ctx != NULL)
+        heap = ctx->heap;
+    else if (ssl != NULL)
+        heap = ssl->heap;
+    return heap;
+}
+
+
+#ifdef HAVE_SNI
+
+int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data,
+                                                                    word16 size)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap);
+}
+
+#ifndef NO_WOLFSSL_SERVER
+
+void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options)
+{
+    if (ssl && ssl->extensions)
+        TLSX_SNI_SetOptions(ssl->extensions, type, options);
+}
+
+
+void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options)
+{
+    if (ctx && ctx->extensions)
+        TLSX_SNI_SetOptions(ctx->extensions, type, options);
+}
+
+
+byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type)
+{
+    return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type);
+}
+
+
+word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
+{
+    if (data)
+        *data = NULL;
+
+    if (ssl && ssl->extensions)
+        return TLSX_SNI_GetRequest(ssl->extensions, type, data);
+
+    return 0;
+}
+
+
+int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
+                              byte type, byte* sni, word32* inOutSz)
+{
+    if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0)
+        return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz);
+
+    return BAD_FUNC_ARG;
+}
+
+#endif /* NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_SNI */
+
+
+#ifdef HAVE_MAX_FRAGMENT
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_MAX_FRAGMENT */
+
+#ifdef HAVE_TRUNCATED_HMAC
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_TRUNCATED_HMAC */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
+{
+    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
+                                          options, NULL, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
+                                                                   byte options)
+{
+    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
+                                          options, NULL, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
+{
+    if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
+                                                options, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
+                                                                   byte options)
+{
+    if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
+                                                options, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+/* Elliptic Curves */
+#ifdef HAVE_SUPPORTED_CURVES
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+        case WOLFSSL_ECC_SECP160K1:
+        case WOLFSSL_ECC_SECP160R1:
+        case WOLFSSL_ECC_SECP160R2:
+        case WOLFSSL_ECC_SECP192K1:
+        case WOLFSSL_ECC_SECP192R1:
+        case WOLFSSL_ECC_SECP224K1:
+        case WOLFSSL_ECC_SECP224R1:
+        case WOLFSSL_ECC_SECP256K1:
+        case WOLFSSL_ECC_SECP256R1:
+        case WOLFSSL_ECC_SECP384R1:
+        case WOLFSSL_ECC_SECP521R1:
+        case WOLFSSL_ECC_BRAINPOOLP256R1:
+        case WOLFSSL_ECC_BRAINPOOLP384R1:
+        case WOLFSSL_ECC_BRAINPOOLP512R1:
+        case WOLFSSL_ECC_X25519:
+            break;
+
+#ifdef WOLFSSL_TLS13
+        case WOLFSSL_FFDHE_2048:
+        case WOLFSSL_FFDHE_3072:
+        case WOLFSSL_FFDHE_4096:
+        case WOLFSSL_FFDHE_6144:
+        case WOLFSSL_FFDHE_8192:
+            if (!IsAtLeastTLSv1_3(ssl->version))
+                return WOLFSSL_SUCCESS;
+            break;
+#endif
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ssl->options.userCurves = 1;
+
+    return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
+}
+
+
+int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+        case WOLFSSL_ECC_SECP160K1:
+        case WOLFSSL_ECC_SECP160R1:
+        case WOLFSSL_ECC_SECP160R2:
+        case WOLFSSL_ECC_SECP192K1:
+        case WOLFSSL_ECC_SECP192R1:
+        case WOLFSSL_ECC_SECP224K1:
+        case WOLFSSL_ECC_SECP224R1:
+        case WOLFSSL_ECC_SECP256K1:
+        case WOLFSSL_ECC_SECP256R1:
+        case WOLFSSL_ECC_SECP384R1:
+        case WOLFSSL_ECC_SECP521R1:
+        case WOLFSSL_ECC_BRAINPOOLP256R1:
+        case WOLFSSL_ECC_BRAINPOOLP384R1:
+        case WOLFSSL_ECC_BRAINPOOLP512R1:
+        case WOLFSSL_ECC_X25519:
+            break;
+
+#ifdef WOLFSSL_TLS13
+        case WOLFSSL_FFDHE_2048:
+        case WOLFSSL_FFDHE_3072:
+        case WOLFSSL_FFDHE_4096:
+        case WOLFSSL_FFDHE_6144:
+        case WOLFSSL_FFDHE_8192:
+            break;
+#endif
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ctx->userCurves = 1;
+
+    return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap);
+}
+
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_SUPPORTED_CURVES */
+
+/* QSH quantum safe handshake */
+#ifdef HAVE_QSH
+/* returns 1 if QSH has been used 0 otherwise */
+int wolfSSL_isQSH(WOLFSSL* ssl)
+{
+    /* if no ssl struct than QSH was not used */
+    if (ssl == NULL)
+        return 0;
+
+    return ssl->isQSH;
+}
+
+
+int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    switch (name) {
+    #ifdef HAVE_NTRU
+        case WOLFSSL_NTRU_EESS439:
+        case WOLFSSL_NTRU_EESS593:
+        case WOLFSSL_NTRU_EESS743:
+            break;
+    #endif
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    ssl->user_set_QSHSchemes = 1;
+
+    return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+    /* user control over sending client public key in hello
+       when flag = 1 will send keys if flag is 0 or function is not called
+       then will not send keys in the hello extension
+       return 0 on success
+     */
+    int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag)
+    {
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        ssl->sendQSHKeys = flag;
+
+        return 0;
+    }
+#endif /* NO_WOLFSSL_CLIENT */
+#endif /* HAVE_QSH */
+
+/* Application-Layer Protocol Negotiation */
+#ifdef HAVE_ALPN
+
+int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
+                    word32 protocol_name_listSz, byte options)
+{
+    char    *list, *ptr, *token[10];
+    word16  len;
+    int     idx = 0;
+    int     ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_UseALPN");
+
+    if (ssl == NULL || protocol_name_list == NULL)
+        return BAD_FUNC_ARG;
+
+    if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
+                                WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
+                                WOLFSSL_MAX_ALPN_NUMBER)) {
+        WOLFSSL_MSG("Invalid arguments, protocol name list too long");
+        return BAD_FUNC_ARG;
+    }
+
+    if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
+        !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
+            WOLFSSL_MSG("Invalid arguments, options not supported");
+            return BAD_FUNC_ARG;
+        }
+
+
+    list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap,
+                           DYNAMIC_TYPE_ALPN);
+    if (list == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return MEMORY_ERROR;
+    }
+
+    XSTRNCPY(list, protocol_name_list, protocol_name_listSz);
+    list[protocol_name_listSz] = '\0';
+
+    /* read all protocol name from the list */
+    token[idx] = XSTRTOK(list, ",", &ptr);
+    while (token[idx] != NULL)
+        token[++idx] = XSTRTOK(NULL, ",", &ptr);
+
+    /* add protocol name list in the TLS extension in reverse order */
+    while ((idx--) > 0) {
+        len = (word16)XSTRLEN(token[idx]);
+
+        ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options,
+                                                                     ssl->heap);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("TLSX_UseALPN failure");
+            break;
+        }
+    }
+
+    XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN);
+
+    return ret;
+}
+
+int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
+{
+    return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL,
+                               (void **)protocol_name, size);
+}
+
+int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
+{
+    if (list == NULL || listSz == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->alpn_client_list == NULL)
+        return BUFFER_ERROR;
+
+    *listSz = (word16)XSTRLEN(ssl->alpn_client_list);
+    if (*listSz == 0)
+        return BUFFER_ERROR;
+
+    *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
+    if (*list == NULL)
+        return MEMORY_ERROR;
+
+    XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
+    (*list)[*listSz] = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */
+int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX);
+    *list = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_ALPN */
+
+/* Secure Renegotiation */
+#ifdef HAVE_SECURE_RENEGOTIATION
+
+/* user is forcing ability to use secure renegotiation, we discourage it */
+int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
+{
+    int ret = BAD_FUNC_ARG;
+
+    if (ssl)
+        ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
+
+    if (ret == WOLFSSL_SUCCESS) {
+        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
+
+        if (extension)
+            ssl->secure_renegotiation = (SecureRenegotiation*)extension->data;
+    }
+
+    return ret;
+}
+
+
+/* do a secure renegotiation handshake, user forced, we discourage */
+int wolfSSL_Rehandshake(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->secure_renegotiation == NULL) {
+        WOLFSSL_MSG("Secure Renegotiation not forced on by user");
+        return SECURE_RENEGOTIATION_E;
+    }
+
+    if (ssl->secure_renegotiation->enabled == 0) {
+        WOLFSSL_MSG("Secure Renegotiation not enabled at extension level");
+        return SECURE_RENEGOTIATION_E;
+    }
+
+    if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+        WOLFSSL_MSG("Can't renegotiate until previous handshake complete");
+        return SECURE_RENEGOTIATION_E;
+    }
+
+#ifndef NO_FORCE_SCR_SAME_SUITE
+    /* force same suite */
+    if (ssl->suites) {
+        ssl->suites->suiteSz = SUITE_LEN;
+        ssl->suites->suites[0] = ssl->options.cipherSuite0;
+        ssl->suites->suites[1] = ssl->options.cipherSuite;
+    }
+#endif
+
+    /* reset handshake states */
+    ssl->options.serverState = NULL_STATE;
+    ssl->options.clientState = NULL_STATE;
+    ssl->options.connectState  = CONNECT_BEGIN;
+    ssl->options.acceptState   = ACCEPT_BEGIN;
+    ssl->options.handShakeState = NULL_STATE;
+    ssl->options.processReply  = 0;  /* TODO, move states in internal.h */
+
+    XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+    ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
+
+    ret = InitHandshakeHashes(ssl);
+    if (ret !=0)
+        return ret;
+
+    ret = wolfSSL_negotiate(ssl);
+    return ret;
+}
+
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+/* Session Ticket */
+#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketEncCb = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* set hint interval, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketHint = hint;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* set user context, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ticketEncCtx = userCtx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */
+
+/* Session Ticket */
+#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
+int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
+}
+
+int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap);
+}
+
+WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl,
+                                          byte* buf, word32* bufSz)
+{
+    if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
+        return BAD_FUNC_ARG;
+
+    if (ssl->session.ticketLen <= *bufSz) {
+        XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen);
+        *bufSz = ssl->session.ticketLen;
+    }
+    else
+        *bufSz = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
+                                          word32 bufSz)
+{
+    if (ssl == NULL || (buf == NULL && bufSz > 0))
+        return BAD_FUNC_ARG;
+
+    if (bufSz > 0) {
+        /* Ticket will fit into static ticket */
+        if(bufSz <= SESSION_TICKET_LEN) {
+            if (ssl->session.isDynamic) {
+                XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+                ssl->session.isDynamic = 0;
+                ssl->session.ticket = ssl->session.staticTicket;
+            }
+        } else { /* Ticket requires dynamic ticket storage */
+            if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */
+                if(ssl->session.isDynamic)
+                    XFREE(ssl->session.ticket, ssl->heap,
+                            DYNAMIC_TYPE_SESSION_TICK);
+                ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap,
+                        DYNAMIC_TYPE_SESSION_TICK);
+                if(!ssl->session.ticket) {
+                    ssl->session.ticket = ssl->session.staticTicket;
+                    ssl->session.isDynamic = 0;
+                    return MEMORY_ERROR;
+                }
+                ssl->session.isDynamic = 1;
+            }
+        }
+        XMEMCPY(ssl->session.ticket, buf, bufSz);
+    }
+    ssl->session.ticketLen = (word16)bufSz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
+                                            CallbackSessionTicket cb, void* ctx)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->session_ticket_cb = cb;
+    ssl->session_ticket_ctx = ctx;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+#ifdef HAVE_EXTENDED_MASTER
+#ifndef NO_WOLFSSL_CLIENT
+
+int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->haveEMS = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.haveEMS = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif
+#endif
+
+
+#ifndef WOLFSSL_LEANPSK
+
+int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
+{
+    int ret;
+    int oldFlags;
+
+    WOLFSSL_ENTER("wolfSSL_send()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+    oldFlags = ssl->wflags;
+
+    ssl->wflags = flags;
+    ret = wolfSSL_write(ssl, data, sz);
+    ssl->wflags = oldFlags;
+
+    WOLFSSL_LEAVE("wolfSSL_send()", ret);
+
+    return ret;
+}
+
+
+int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
+{
+    int ret;
+    int oldFlags;
+
+    WOLFSSL_ENTER("wolfSSL_recv()");
+
+    if (ssl == NULL || data == NULL || sz < 0)
+        return BAD_FUNC_ARG;
+
+    oldFlags = ssl->rflags;
+
+    ssl->rflags = flags;
+    ret = wolfSSL_read(ssl, data, sz);
+    ssl->rflags = oldFlags;
+
+    WOLFSSL_LEAVE("wolfSSL_recv()", ret);
+
+    return ret;
+}
+#endif
+
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_shutdown(WOLFSSL* ssl)
+{
+    int  ret = WOLFSSL_FATAL_ERROR;
+    byte tmp;
+    WOLFSSL_ENTER("SSL_shutdown()");
+
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ssl->options.quietShutdown) {
+        WOLFSSL_MSG("quiet shutdown, no close notify sent");
+        ret = WOLFSSL_SUCCESS;
+    }
+    else {
+        /* try to send close notify, not an error if can't */
+        if (!ssl->options.isClosed && !ssl->options.connReset &&
+                                      !ssl->options.sentNotify) {
+            ssl->error = SendAlert(ssl, alert_warning, close_notify);
+            if (ssl->error < 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.sentNotify = 1;  /* don't send close_notify twice */
+            if (ssl->options.closeNotify)
+                ret = WOLFSSL_SUCCESS;
+            else {
+                ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+                WOLFSSL_LEAVE("SSL_shutdown()", ret);
+                return ret;
+            }
+        }
+
+        /* call wolfSSL_shutdown again for bidirectional shutdown */
+        if (ssl->options.sentNotify && !ssl->options.closeNotify) {
+            ret = wolfSSL_read(ssl, &tmp, 0);
+            if (ret < 0) {
+                WOLFSSL_ERROR(ssl->error);
+                ret = WOLFSSL_FATAL_ERROR;
+            } else if (ssl->options.closeNotify) {
+                ssl->error = WOLFSSL_ERROR_SYSCALL;   /* simulate OpenSSL behavior */
+                ret = WOLFSSL_SUCCESS;
+            }
+        }
+    }
+
+#ifdef OPENSSL_EXTRA
+    /* reset WOLFSSL structure state for possible re-use */
+    if (ret == WOLFSSL_SUCCESS) {
+        if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("could not clear WOLFSSL");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+    WOLFSSL_LEAVE("SSL_shutdown()", ret);
+
+    return ret;
+}
+
+
+/* get current error state value */
+int wolfSSL_state(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return ssl->error;
+}
+
+
+int wolfSSL_get_error(WOLFSSL* ssl, int ret)
+{
+    WOLFSSL_ENTER("SSL_get_error");
+
+    if (ret > 0)
+        return WOLFSSL_ERROR_NONE;
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    WOLFSSL_LEAVE("SSL_get_error", ssl->error);
+
+    /* make sure converted types are handled in SetErrorString() too */
+    if (ssl->error == WANT_READ)
+        return WOLFSSL_ERROR_WANT_READ;         /* convert to OpenSSL type */
+    else if (ssl->error == WANT_WRITE)
+        return WOLFSSL_ERROR_WANT_WRITE;        /* convert to OpenSSL type */
+    else if (ssl->error == ZERO_RETURN)
+        return WOLFSSL_ERROR_ZERO_RETURN;       /* convert to OpenSSL type */
+    return ssl->error;
+}
+
+
+/* retrive alert history, WOLFSSL_SUCCESS on ok */
+int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
+{
+    if (ssl && h) {
+        *h = ssl->alert_history;
+    }
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* return TRUE if current error is want read */
+int wolfSSL_want_read(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_want_read");
+    if (ssl->error == WANT_READ)
+        return 1;
+
+    return 0;
+}
+
+
+/* return TRUE if current error is want write */
+int wolfSSL_want_write(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_want_write");
+    if (ssl->error == WANT_WRITE)
+        return 1;
+
+    return 0;
+}
+
+
+char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
+{
+    static const char* const msg = "Please supply a buffer for error string";
+
+    WOLFSSL_ENTER("ERR_error_string");
+    if (data) {
+        SetErrorString((int)errNumber, data);
+        return data;
+    }
+
+    return (char*)msg;
+}
+
+
+void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_error_string_n");
+    if (len >= WOLFSSL_MAX_ERROR_SZ)
+        wolfSSL_ERR_error_string(e, buf);
+    else {
+        char tmp[WOLFSSL_MAX_ERROR_SZ];
+
+        WOLFSSL_MSG("Error buffer too short, truncating");
+        if (len) {
+            wolfSSL_ERR_error_string(e, tmp);
+            XMEMCPY(buf, tmp, len-1);
+            buf[len-1] = '\0';
+        }
+    }
+}
+
+
+/* don't free temporary arrays at end of handshake */
+void wolfSSL_KeepArrays(WOLFSSL* ssl)
+{
+    if (ssl)
+        ssl->options.saveArrays = 1;
+}
+
+
+/* user doesn't need temporary arrays anymore, Free */
+void wolfSSL_FreeArrays(WOLFSSL* ssl)
+{
+    if (ssl && ssl->options.handShakeState == HANDSHAKE_DONE) {
+        ssl->options.saveArrays = 0;
+        FreeArrays(ssl, 1);
+    }
+}
+
+/* Set option to indicate that the resources are not to be freed after
+ * handshake.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.keepResources = 1;
+
+    return 0;
+}
+
+/* Free the handshake resources after handshake.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    FreeHandshakeResources(ssl);
+
+    return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl  The SSL/TLS context object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->useClientOrder = 1;
+
+    return 0;
+}
+
+/* Use the client's order of preference when matching cipher suites.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
+ */
+int wolfSSL_UseClientSuites(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->options.useClientOrder = 1;
+
+    return 0;
+}
+
+const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify)
+{
+    if (ssl == NULL)
+        return NULL;
+
+    if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
+         (ssl->options.side == WOLFSSL_SERVER_END &&  verify) )
+        return ssl->keys.client_write_MAC_secret;
+    else
+        return ssl->keys.server_write_MAC_secret;
+}
+
+
+#ifdef ATOMIC_USER
+
+void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX* ctx, CallbackMacEncrypt cb)
+{
+    if (ctx)
+        ctx->MacEncryptCb = cb;
+}
+
+
+void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->MacEncryptCtx = ctx;
+}
+
+
+void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->MacEncryptCtx;
+
+    return NULL;
+}
+
+
+void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX* ctx, CallbackDecryptVerify cb)
+{
+    if (ctx)
+        ctx->DecryptVerifyCb = cb;
+}
+
+
+void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->DecryptVerifyCtx = ctx;
+}
+
+
+void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->DecryptVerifyCtx;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.client_write_key;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.client_write_IV;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.server_write_key;
+
+    return NULL;
+}
+
+
+const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->keys.server_write_IV;
+
+    return NULL;
+}
+
+int wolfSSL_GetKeySize(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.key_size;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetIVSize(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.iv_size;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetBulkCipher(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->specs.bulk_cipher_algorithm;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetCipherType(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->specs.cipher_type == block)
+        return WOLFSSL_BLOCK_TYPE;
+    if (ssl->specs.cipher_type == stream)
+        return WOLFSSL_STREAM_TYPE;
+    if (ssl->specs.cipher_type == aead)
+        return WOLFSSL_AEAD_TYPE;
+
+    return -1;
+}
+
+
+int wolfSSL_GetCipherBlockSize(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return ssl->specs.block_size;
+}
+
+
+int wolfSSL_GetAeadMacSize(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return ssl->specs.aead_mac_size;
+}
+
+
+int wolfSSL_IsTLSv1_1(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->options.tls1_1)
+        return 1;
+
+    return 0;
+}
+
+
+int wolfSSL_GetSide(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->options.side;
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_GetHmacSize(WOLFSSL* ssl)
+{
+    /* AEAD ciphers don't have HMAC keys */
+    if (ssl)
+        return (ssl->specs.cipher_type != aead) ? ssl->specs.hash_size : 0;
+
+    return BAD_FUNC_ARG;
+}
+
+#endif /* ATOMIC_USER */
+
+#ifndef NO_CERTS
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_CERT_MANAGER* cm = NULL;
+    if (ctx)
+        cm = ctx->cm;
+    return cm;
+}
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
+{
+    WOLFSSL_CERT_MANAGER* cm = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
+
+    cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
+                                         DYNAMIC_TYPE_CERT_MANAGER);
+    if (cm) {
+        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
+
+        if (wc_InitMutex(&cm->caLock) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            wolfSSL_CertManagerFree(cm);
+            return NULL;
+        }
+
+        #ifdef WOLFSSL_TRUST_PEER_CERT
+        if (wc_InitMutex(&cm->tpLock) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            wolfSSL_CertManagerFree(cm);
+            return NULL;
+        }
+        #endif
+
+        /* set default minimum key size allowed */
+        #ifndef NO_RSA
+            cm->minRsaKeySz = MIN_RSAKEY_SZ;
+        #endif
+        #ifdef HAVE_ECC
+            cm->minEccKeySz = MIN_ECCKEY_SZ;
+        #endif
+            cm->heap = heap;
+    }
+
+    return cm;
+}
+
+
+WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
+{
+    return wolfSSL_CertManagerNew_ex(NULL);
+}
+
+
+void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
+{
+    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(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
+
+        XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
+    }
+
+}
+
+
+/* Unload the CA signer list */
+int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return BAD_MUTEX_E;
+
+    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL);
+
+    wc_UnLockMutex(&cm->caLock);
+
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return BAD_MUTEX_E;
+
+    FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, NULL);
+
+    wc_UnLockMutex(&cm->tpLock);
+
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+#endif /* NO_CERTS */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+    defined(HAVE_WEBSERVER)
+
+static const struct cipher{
+        unsigned char type;
+        const char *name;
+} cipher_tbl[] = {
+
+#ifndef NO_AES
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CBC_TYPE, "AES-128-CBC"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CBC_TYPE, "AES-192-CBC"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CBC_TYPE, "AES-256-CBC"},
+    #endif
+#if defined(OPENSSL_EXTRA)
+    #ifdef WOLFSSL_AES_128
+        {AES_128_CTR_TYPE, "AES-128-CTR"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {AES_192_CTR_TYPE, "AES-192-CTR"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {AES_256_CTR_TYPE, "AES-256-CTR"},
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+        {AES_128_ECB_TYPE, "AES-128-ECB"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {AES_192_ECB_TYPE, "AES-192-ECB"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {AES_256_ECB_TYPE, "AES-256-ECB"},
+    #endif
+#endif
+
+#endif
+
+#ifndef NO_DES3
+    {DES_CBC_TYPE, "DES-CBC"},
+    {DES_ECB_TYPE, "DES-ECB"},
+
+    {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC"},
+    {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB"},
+#endif
+
+#ifndef NO_RC4
+    {ARC4_TYPE, "ARC4"},
+#endif
+
+#ifdef HAVE_IDEA
+    {IDEA_CBC_TYPE, "IDEA-CBC"},
+#endif
+    { 0, NULL}
+};
+
+const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name)
+{
+
+    static const struct alias {
+        const char *name;
+        const char *alias;
+    } alias_tbl[] =
+    {
+#ifndef NO_DES3
+        {"DES-CBC", "DES"},
+        {"DES-CBC", "des"},
+        {"DES-ECB", "DES-ECB"},
+        {"DES-ECB", "des-ecb"},
+        {"DES-EDE3-CBC", "DES3"},
+        {"DES-EDE3-CBC", "des3"},
+        {"DES-EDE3-ECB", "DES-EDE3"},
+        {"DES-EDE3-ECB", "des-ede3"},
+        {"DES-EDE3-ECB", "des-ede3-ecb"},
+#endif
+#ifdef HAVE_IDEA
+        {"IDEA-CBC", "IDEA"},
+        {"IDEA-CBC", "idea"},
+#endif
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        {"AES-128-CBC", "AES128-CBC"},
+        {"AES-128-CBC", "aes128-cbc"},
+        #endif
+        #ifdef WOLFSSL_AES_192
+        {"AES-192-CBC", "AES192-CBC"},
+        {"AES-192-CBC", "aes192-cbc"},
+        #endif
+        #ifdef WOLFSSL_AES_256
+        {"AES-256-CBC", "AES256-CBC"},
+        {"AES-256-CBC", "aes256-cbc"},
+        #endif
+    #endif
+    #ifdef WOLFSSL_AES_128
+        {"AES-128-ECB", "AES128-ECB"},
+        {"AES-128-ECB", "aes128-ecb"},
+    #endif
+    #ifdef WOLFSSL_AES_192
+        {"AES-192-ECB", "AES192-ECB"},
+        {"AES-192-ECB", "aes192-ecb"},
+    #endif
+    #ifdef WOLFSSL_AES_256
+        {"AES-256-ECB", "AES256-ECB"},
+        {"AES-256-EBC", "aes256-ecb"},
+    #endif
+#endif
+#ifndef NO_RC4
+        {"ARC4", "RC4"},
+#endif
+        { NULL, NULL}
+    };
+
+    const struct cipher *ent;
+    const struct alias  *al;
+
+    WOLFSSL_ENTER("EVP_get_cipherbyname");
+
+    for( al = alias_tbl; al->name != NULL; al++)
+        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
+            name = al->name;
+            break;
+        }
+
+    for( ent = cipher_tbl; ent->name != NULL; ent++)
+        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return (WOLFSSL_EVP_CIPHER *)ent->name;
+        }
+
+    return NULL;
+}
+
+/*
+ * return an EVP_CIPHER structure when cipher NID is passed.
+ *
+ * id  cipher NID
+ *
+ * retrun WOLFSSL_EVP_CIPHER
+*/
+const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id)
+{
+    WOLFSSL_ENTER("EVP_get_cipherbynid");
+
+    switch(id) {
+
+#if defined(OPENSSL_EXTRA)
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_cbc:
+            return wolfSSL_EVP_aes_128_cbc();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_cbc:
+            return wolfSSL_EVP_aes_192_cbc();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_cbc:
+            return wolfSSL_EVP_aes_256_cbc();
+        #endif
+    #endif
+    #ifdef WOLFSSL_AES_COUNTER
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_ctr:
+            return wolfSSL_EVP_aes_128_ctr();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_ctr:
+            return wolfSSL_EVP_aes_192_ctr();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_ctr:
+            return wolfSSL_EVP_aes_256_ctr();
+        #endif
+    #endif /* WOLFSSL_AES_COUNTER */
+    #ifdef HAVE_AES_ECB
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_ecb:
+            return wolfSSL_EVP_aes_128_ecb();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_ecb:
+            return wolfSSL_EVP_aes_192_ecb();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_ecb:
+            return wolfSSL_EVP_aes_256_ecb();
+        #endif
+    #endif /* HAVE_AES_ECB */
+#endif
+
+#ifndef NO_DES3
+        case NID_des_cbc:
+            return wolfSSL_EVP_des_cbc();
+#ifdef WOLFSSL_DES_ECB
+        case NID_des_ecb:
+            return wolfSSL_EVP_des_ecb();
+#endif
+        case NID_des_ede3_cbc:
+            return wolfSSL_EVP_des_ede3_cbc();
+#ifdef WOLFSSL_DES_ECB
+        case NID_des_ede3_ecb:
+            return wolfSSL_EVP_des_ede3_ecb();
+#endif
+#endif /*NO_DES3*/
+
+#ifdef HAVE_IDEA
+        case NID_idea_cbc:
+            return wolfSSL_EVP_idea_cbc();
+#endif
+#endif /*OPENSSL_EXTRA*/
+
+        default:
+            WOLFSSL_MSG("Bad cipher id value");
+    }
+
+    return NULL;
+}
+
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+    #ifdef WOLFSSL_AES_128
+        static char *EVP_AES_128_CBC;
+    #endif
+    #ifdef WOLFSSL_AES_192
+        static char *EVP_AES_192_CBC;
+    #endif
+    #ifdef WOLFSSL_AES_256
+        static char *EVP_AES_256_CBC;
+    #endif
+    #endif /* HAVE_AES_CBC */
+#if defined(OPENSSL_EXTRA)
+    #ifdef WOLFSSL_AES_128
+    static char *EVP_AES_128_CTR;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    static char *EVP_AES_192_CTR;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    static char *EVP_AES_256_CTR;
+    #endif
+
+    #ifdef WOLFSSL_AES_128
+    static char *EVP_AES_128_ECB;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    static char *EVP_AES_192_ECB;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    static char *EVP_AES_256_ECB;
+    #endif
+    static const int  EVP_AES_SIZE = 11;
+#endif
+#endif
+
+#ifndef NO_DES3
+static char *EVP_DES_CBC;
+static char *EVP_DES_ECB;
+
+static char *EVP_DES_EDE3_CBC;
+static char *EVP_DES_EDE3_ECB;
+
+#ifdef OPENSSL_EXTRA
+static const int  EVP_DES_SIZE = 7;
+static const int  EVP_DES_EDE3_SIZE = 12;
+#endif
+
+#endif
+
+#ifdef HAVE_IDEA
+static char *EVP_IDEA_CBC;
+#if defined(OPENSSL_EXTRA)
+static const int  EVP_IDEA_SIZE = 8;
+#endif
+#endif
+
+void wolfSSL_EVP_init(void)
+{
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC");
+        #endif
+    #endif /* HAVE_AES_CBC */
+
+#if defined(OPENSSL_EXTRA)
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR");
+        #endif
+
+        #ifdef WOLFSSL_AES_128
+        EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB");
+        #endif
+        #ifdef WOLFSSL_AES_192
+        EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB");
+        #endif
+        #ifdef WOLFSSL_AES_256
+        EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB");
+        #endif
+#endif
+#endif
+
+#ifndef NO_DES3
+    EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC");
+    EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB");
+
+    EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC");
+    EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB");
+#endif
+
+#ifdef HAVE_IDEA
+    EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC");
+#endif
+}
+
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */
+
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+
+void wolfSSL_ERR_print_errors_fp(XFILE fp, int err)
+{
+    char data[WOLFSSL_MAX_ERROR_SZ + 1];
+
+    WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp");
+    SetErrorString(err, data);
+    fprintf(fp, "%s", data);
+}
+
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+void wolfSSL_ERR_dump_errors_fp(XFILE fp)
+{
+    wc_ERR_print_errors_fp(fp);
+}
+#endif
+#endif
+
+
+int wolfSSL_pending(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_pending");
+    return ssl->buffers.clearOutputBuffer.length;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+/* turn on handshake group messages for context */
+int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL)
+       return BAD_FUNC_ARG;
+
+    ctx->groupMessages = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_CLIENT
+/* connect enough to get peer cert chain */
+int wolfSSL_connect_cert(WOLFSSL* ssl)
+{
+    int  ret;
+
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    ssl->options.certOnly = 1;
+    ret = wolfSSL_connect(ssl);
+    ssl->options.certOnly   = 0;
+
+    return ret;
+}
+#endif
+
+
+#ifndef WOLFSSL_LEANPSK
+/* turn on handshake group messages for ssl object */
+int wolfSSL_set_group_messages(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+       return BAD_FUNC_ARG;
+
+    ssl->options.groupMessages = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* make minVersion the internal equivalent SSL version */
+static int SetMinVersionHelper(byte* minVersion, int version)
+{
+#ifdef NO_TLS
+    (void)minVersion;
+#endif
+
+    switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+        case WOLFSSL_SSLV3:
+            *minVersion = SSLv3_MINOR;
+            break;
+#endif
+
+#ifndef NO_TLS
+    #ifndef NO_OLD_TLS
+        case WOLFSSL_TLSV1:
+            *minVersion = TLSv1_MINOR;
+            break;
+
+        case WOLFSSL_TLSV1_1:
+            *minVersion = TLSv1_1_MINOR;
+            break;
+    #endif
+    #ifndef WOLFSSL_NO_TLS12
+        case WOLFSSL_TLSV1_2:
+            *minVersion = TLSv1_2_MINOR;
+            break;
+    #endif
+#endif
+    #ifdef WOLFSSL_TLS13
+        case WOLFSSL_TLSV1_3:
+            *minVersion = TLSv1_3_MINOR;
+            break;
+    #endif
+
+        default:
+            WOLFSSL_MSG("Bad function argument");
+            return BAD_FUNC_ARG;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
+int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    return SetMinVersionHelper(&ctx->minDowngrade, version);
+}
+
+
+/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
+{
+    WOLFSSL_ENTER("wolfSSL_SetMinVersion");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    return SetMinVersionHelper(&ssl->options.minDowngrade, version);
+}
+
+
+/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */
+int wolfSSL_GetVersion(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (ssl->version.major == SSLv3_MAJOR) {
+        switch (ssl->version.minor) {
+            case SSLv3_MINOR :
+                return WOLFSSL_SSLV3;
+            case TLSv1_MINOR :
+                return WOLFSSL_TLSV1;
+            case TLSv1_1_MINOR :
+                return WOLFSSL_TLSV1_1;
+            case TLSv1_2_MINOR :
+                return WOLFSSL_TLSV1_2;
+            case TLSv1_3_MINOR :
+                return WOLFSSL_TLSV1_3;
+            default:
+                break;
+        }
+    }
+
+    return VERSION_ERROR;
+}
+
+int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
+{
+    word16 haveRSA = 1;
+    word16 havePSK = 0;
+    int    keySz   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_SetVersion");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return BAD_FUNC_ARG;
+    }
+
+    switch (version) {
+#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+        case WOLFSSL_SSLV3:
+            ssl->version = MakeSSLv3();
+            break;
+#endif
+
+#ifndef NO_TLS
+    #ifndef NO_OLD_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case WOLFSSL_TLSV1:
+            ssl->version = MakeTLSv1();
+            break;
+        #endif
+
+        case WOLFSSL_TLSV1_1:
+            ssl->version = MakeTLSv1_1();
+            break;
+    #endif
+    #ifndef WOLFSSL_NO_TLS12
+        case WOLFSSL_TLSV1_2:
+            ssl->version = MakeTLSv1_2();
+            break;
+    #endif
+#endif
+#ifdef WOLFSSL_TLS13
+        case WOLFSSL_TLSV1_3:
+            ssl->version = MakeTLSv1_3();
+            break;
+
+#endif
+
+        default:
+            WOLFSSL_MSG("Bad function argument");
+            return BAD_FUNC_ARG;
+    }
+
+    #ifdef NO_RSA
+        haveRSA = 0;
+    #endif
+    #ifndef NO_PSK
+        havePSK = ssl->options.havePSK;
+    #endif
+    #ifndef NO_CERTS
+        keySz = ssl->buffers.keySz;
+    #endif
+
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+               ssl->options.haveDH, ssl->options.haveNTRU,
+               ssl->options.haveECDSAsig, ssl->options.haveECC,
+               ssl->options.haveStaticECC, ssl->options.side);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !leanpsk */
+
+
+#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE)
+
+/* Make a work from the front of random hash */
+static WC_INLINE word32 MakeWordFromHash(const byte* hashID)
+{
+    return ((word32)hashID[0] << 24) | (hashID[1] << 16) |
+        (hashID[2] <<  8) | hashID[3];
+}
+
+#endif /* !NO_CERTS || !NO_SESSION_CACHE */
+
+
+#ifndef NO_CERTS
+
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 HashSigner(const byte* hash)
+{
+    return MakeWordFromHash(hash) % CA_TABLE_SIZE;
+}
+
+
+/* does CA already exist on signer list */
+int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+    Signer* signers;
+    int     ret = 0;
+    word32  row;
+
+    if (cm == NULL || hash == NULL) {
+        return ret;
+    }
+
+    row = HashSigner(hash);
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        return ret;
+    }
+    signers = cm->caTable[row];
+    while (signers) {
+        byte* subjectHash;
+
+    #ifndef NO_SKID
+        subjectHash = signers->subjectKeyIdHash;
+    #else
+        subjectHash = signers->subjectNameHash;
+    #endif
+
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = 1; /* success */
+            break;
+        }
+        signers = signers->next;
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
+{
+    return MakeWordFromHash(hash) % TP_TABLE_SIZE;
+}
+
+/* does trusted peer already exist on signer list */
+int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+    TrustedPeerCert* tp;
+    int     ret = 0;
+    word32  row = TrustedPeerHashSigner(hash);
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return  ret;
+    tp = cm->tpTable[row];
+    while (tp) {
+        byte* subjectHash;
+        #ifndef NO_SKID
+            subjectHash = tp->subjectKeyIdHash;
+        #else
+            subjectHash = tp->subjectNameHash;
+        #endif
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = 1;
+            break;
+        }
+        tp = tp->next;
+    }
+    wc_UnLockMutex(&cm->tpLock);
+
+    return ret;
+}
+
+
+/* return Trusted Peer if found, otherwise NULL
+    type is what to match on
+ */
+TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    TrustedPeerCert* ret = NULL;
+    TrustedPeerCert* tp  = NULL;
+    word32  row;
+
+    if (cm == NULL || hash == NULL)
+        return NULL;
+
+    row = TrustedPeerHashSigner(hash);
+
+    if (wc_LockMutex(&cm->tpLock) != 0)
+        return ret;
+
+    tp = cm->tpTable[row];
+    while (tp) {
+        byte* subjectHash;
+        switch (type) {
+            #ifndef NO_SKID
+            case WC_MATCH_SKID:
+                subjectHash = tp->subjectKeyIdHash;
+                break;
+            #endif
+            case WC_MATCH_NAME:
+                subjectHash = tp->subjectNameHash;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown search type");
+                wc_UnLockMutex(&cm->tpLock);
+                return NULL;
+        }
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = tp;
+            break;
+        }
+        tp = tp->next;
+    }
+    wc_UnLockMutex(&cm->tpLock);
+
+    return ret;
+}
+
+
+int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
+{
+    if (tp == NULL || cert == NULL)
+        return BAD_FUNC_ARG;
+
+    /* subject key id or subject hash has been compared when searching
+       tpTable for the cert from function GetTrustedPeer */
+
+    /* compare signatures */
+    if (tp->sigLen == cert->sigLength) {
+        if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
+            return WOLFSSL_FAILURE;
+        }
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* return CA if found, otherwise NULL */
+Signer* GetCA(void* vp, byte* hash)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ret = NULL;
+    Signer* signers;
+    word32  row = HashSigner(hash);
+
+    if (cm == NULL)
+        return NULL;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return ret;
+
+    signers = cm->caTable[row];
+    while (signers) {
+        byte* subjectHash;
+        #ifndef NO_SKID
+            subjectHash = signers->subjectKeyIdHash;
+        #else
+            subjectHash = signers->subjectNameHash;
+        #endif
+        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+            ret = signers;
+            break;
+        }
+        signers = signers->next;
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+#ifndef NO_SKID
+/* return CA if found, otherwise NULL. Walk through hash table. */
+Signer* GetCAByName(void* vp, byte* hash)
+{
+    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+    Signer* ret = NULL;
+    Signer* signers;
+    word32  row;
+
+    if (cm == NULL)
+        return NULL;
+
+    if (wc_LockMutex(&cm->caLock) != 0)
+        return ret;
+
+    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+        signers = cm->caTable[row];
+        while (signers && ret == NULL) {
+            if (XMEMCMP(hash, signers->subjectNameHash,
+                        SIGNER_DIGEST_SIZE) == 0) {
+                ret = signers;
+            }
+            signers = signers->next;
+        }
+    }
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+#endif
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* add a trusted peer cert to linked list */
+int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
+{
+    int ret, row;
+    TrustedPeerCert* peerCert;
+    DecodedCert* cert = NULL;
+    DerBuffer*   der = *pDer;
+    byte* subjectHash = NULL;
+
+    WOLFSSL_MSG("Adding a Trusted Peer Cert");
+
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+
+    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+    if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        return ret;
+    }
+    WOLFSSL_MSG("\tParsed new trusted peer cert");
+
+    peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
+                                                             DYNAMIC_TYPE_CERT);
+    if (peerCert == NULL) {
+        FreeDecodedCert(cert);
+        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+        return MEMORY_E;
+    }
+    XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
+
+#ifndef NO_SKID
+    if (cert->extAuthKeyIdSet) {
+        subjectHash = cert->extSubjKeyId;
+    }
+    else {
+        subjectHash = cert->subjectHash;
+    }
+#else
+    subjectHash = cert->subjectHash;
+#endif
+
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        if (peerCert->permittedNames)
+            FreeNameSubtrees(peerCert->permittedNames, cm->heap);
+        if (peerCert->excludedNames)
+            FreeNameSubtrees(peerCert->excludedNames, cm->heap);
+    #endif
+
+    if (AlreadyTrustedPeer(cm, subjectHash)) {
+        WOLFSSL_MSG("\tAlready have this CA, not adding again");
+        (void)ret;
+    }
+    else {
+        /* add trusted peer signature */
+        peerCert->sigLen = cert->sigLength;
+        peerCert->sig = XMALLOC(cert->sigLength, cm->heap,
+                                                        DYNAMIC_TYPE_SIGNATURE);
+        if (peerCert->sig == NULL) {
+            FreeDecodedCert(cert);
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+            FreeTrustedPeer(peerCert, cm->heap);
+            return MEMORY_E;
+        }
+        XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
+
+        /* add trusted peer name */
+        peerCert->nameLen = cert->subjectCNLen;
+        peerCert->name    = cert->subjectCN;
+        #ifndef IGNORE_NAME_CONSTRAINTS
+            peerCert->permittedNames = cert->permittedNames;
+            peerCert->excludedNames  = cert->excludedNames;
+        #endif
+
+        /* add SKID when available and hash of name */
+        #ifndef NO_SKID
+            XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
+                    SIGNER_DIGEST_SIZE);
+        #endif
+            XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
+                    SIGNER_DIGEST_SIZE);
+            peerCert->next    = NULL; /* If Key Usage not set, all uses valid. */
+            cert->subjectCN = 0;
+        #ifndef IGNORE_NAME_CONSTRAINTS
+            cert->permittedNames = NULL;
+            cert->excludedNames = NULL;
+        #endif
+
+        #ifndef NO_SKID
+            if (cert->extAuthKeyIdSet) {
+                row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash);
+            }
+            else {
+                row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+            }
+        #else
+            row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+        #endif
+
+            if (wc_LockMutex(&cm->tpLock) == 0) {
+                peerCert->next = cm->tpTable[row];
+                cm->tpTable[row] = peerCert;   /* takes ownership */
+                wc_UnLockMutex(&cm->tpLock);
+            }
+            else {
+                WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
+                FreeDecodedCert(cert);
+                XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+                FreeTrustedPeer(peerCert, cm->heap);
+                return BAD_MUTEX_E;
+            }
+        }
+
+    WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
+    FreeDecodedCert(cert);
+    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+    WOLFSSL_MSG("\tFreeing der trusted peer cert");
+    FreeDer(&der);
+    WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
+    WOLFSSL_LEAVE("AddTrustedPeer", ret);
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* owns der, internal now uses too */
+/* type flag ids from user or from chain received during verify
+   don't allow chain ones to be added w/o isCA extension */
+int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
+{
+    int         ret;
+    Signer*     signer = NULL;
+    word32      row;
+    byte*       subjectHash;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+    DerBuffer*   der = *pDer;
+
+    WOLFSSL_MSG("Adding a CA");
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+    ret = ParseCert(cert, CA_TYPE, verify, cm);
+    WOLFSSL_MSG("\tParsed new CA");
+
+#ifndef NO_SKID
+    subjectHash = cert->extSubjKeyId;
+#else
+    subjectHash = cert->subjectHash;
+#endif
+
+    /* check CA key size */
+    if (verify) {
+        switch (cert->keyOID) {
+            #ifndef NO_RSA
+            case RSAk:
+                if (cm->minRsaKeySz < 0 ||
+                                   cert->pubKeySize < (word16)cm->minRsaKeySz) {
+                    ret = RSA_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA RSA key size error");
+                }
+                break;
+            #endif /* !NO_RSA */
+            #ifdef HAVE_ECC
+            case ECDSAk:
+                if (cm->minEccKeySz < 0 ||
+                                   cert->pubKeySize < (word16)cm->minEccKeySz) {
+                    ret = ECC_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA ECC key size error");
+                }
+                break;
+            #endif /* HAVE_ECC */
+            #ifdef HAVE_ED25519
+            case ED25519k:
+                if (cm->minEccKeySz < 0 ||
+                                   ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
+                    ret = ECC_KEY_SIZE_E;
+                    WOLFSSL_MSG("\tCA ECC key size error");
+                }
+                break;
+            #endif /* HAVE_ED25519 */
+
+            default:
+                WOLFSSL_MSG("\tNo key size check done on CA");
+                break; /* no size check if key type is not in switch */
+        }
+    }
+
+    if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
+        WOLFSSL_MSG("\tCan't add as CA if not actually one");
+        ret = NOT_CA_ERROR;
+    }
+#ifndef ALLOW_INVALID_CERTSIGN
+    else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
+             (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
+        /* Intermediate CA certs are required to have the keyCertSign
+        * extension set. User loaded root certs are not. */
+        WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
+        ret = NOT_CA_ERROR;
+    }
+#endif
+    else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
+        WOLFSSL_MSG("\tAlready have this CA, not adding again");
+        (void)ret;
+    }
+    else if (ret == 0) {
+        /* take over signer parts */
+        signer = MakeSigner(cm->heap);
+        if (!signer)
+            ret = MEMORY_ERROR;
+    }
+    if (ret == 0 && signer != NULL) {
+    #ifdef WOLFSSL_SIGNER_DER_CERT
+        ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
+    }
+    if (ret == 0 && signer != NULL) {
+        XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
+    #endif
+        signer->keyOID         = cert->keyOID;
+        if (cert->pubKeyStored) {
+            signer->publicKey      = cert->publicKey;
+            signer->pubKeySize     = cert->pubKeySize;
+        }
+        if (cert->subjectCNStored) {
+            signer->nameLen        = cert->subjectCNLen;
+            signer->name           = cert->subjectCN;
+        }
+        signer->pathLength     = cert->pathLength;
+        signer->pathLengthSet  = cert->pathLengthSet;
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        signer->permittedNames = cert->permittedNames;
+        signer->excludedNames  = cert->excludedNames;
+    #endif
+    #ifndef NO_SKID
+        XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
+                SIGNER_DIGEST_SIZE);
+    #endif
+        XMEMCPY(signer->subjectNameHash, cert->subjectHash,
+                SIGNER_DIGEST_SIZE);
+        signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
+                                                : 0xFFFF;
+        signer->next    = NULL; /* If Key Usage not set, all uses valid. */
+        cert->publicKey = 0;    /* in case lock fails don't free here.   */
+        cert->subjectCN = 0;
+    #ifndef IGNORE_NAME_CONSTRAINTS
+        cert->permittedNames = NULL;
+        cert->excludedNames = NULL;
+    #endif
+
+    #ifndef NO_SKID
+        row = HashSigner(signer->subjectKeyIdHash);
+    #else
+        row = HashSigner(signer->subjectNameHash);
+    #endif
+
+        if (wc_LockMutex(&cm->caLock) == 0) {
+            signer->next = cm->caTable[row];
+            cm->caTable[row] = signer;   /* takes ownership */
+            wc_UnLockMutex(&cm->caLock);
+            if (cm->caCacheCallback)
+                cm->caCacheCallback(der->buffer, (int)der->length, type);
+        }
+        else {
+            WOLFSSL_MSG("\tCA Mutex Lock failed");
+            ret = BAD_MUTEX_E;
+            FreeSigner(signer, cm->heap);
+        }
+    }
+
+    WOLFSSL_MSG("\tFreeing Parsed CA");
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+    WOLFSSL_MSG("\tFreeing der CA");
+    FreeDer(pDer);
+    WOLFSSL_MSG("\t\tOK Freeing der CA");
+
+    WOLFSSL_LEAVE("AddCA", ret);
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+#endif /* !NO_CERTS */
+
+
+#ifndef NO_SESSION_CACHE
+
+    /* basic config gives a cache with 33 sessions, adequate for clients and
+       embedded servers
+
+       MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
+       aren't under heavy load, basically allows 200 new sessions per minute
+
+       BIG_SESSION_CACHE yields 20,027 sessions
+
+       HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
+       allows over 13,000 new sessions per minute or over 200 new sessions per
+       second
+
+       SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
+       or systems where the default of nearly 3kB is too much RAM, this define
+       uses less than 500 bytes RAM
+
+       default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
+    */
+    #ifdef HUGE_SESSION_CACHE
+        #define SESSIONS_PER_ROW 11
+        #define SESSION_ROWS 5981
+    #elif defined(BIG_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 7
+        #define SESSION_ROWS 2861
+    #elif defined(MEDIUM_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 5
+        #define SESSION_ROWS 211
+    #elif defined(SMALL_SESSION_CACHE)
+        #define SESSIONS_PER_ROW 2
+        #define SESSION_ROWS 3
+    #else
+        #define SESSIONS_PER_ROW 3
+        #define SESSION_ROWS 11
+    #endif
+
+    typedef struct SessionRow {
+        int nextIdx;                           /* where to place next one   */
+        int totalCount;                        /* sessions ever on this row */
+        WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
+    } SessionRow;
+
+    static SessionRow SessionCache[SESSION_ROWS];
+
+    #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
+        static word32 PeakSessions;
+    #endif
+
+    static wolfSSL_Mutex session_mutex;   /* SessionCache mutex */
+
+    #ifndef NO_CLIENT_CACHE
+
+        typedef struct ClientSession {
+            word16 serverRow;            /* SessionCache Row id */
+            word16 serverIdx;            /* SessionCache Idx (column) */
+        } ClientSession;
+
+        typedef struct ClientRow {
+            int nextIdx;                /* where to place next one   */
+            int totalCount;             /* sessions ever on this row */
+            ClientSession Clients[SESSIONS_PER_ROW];
+        } ClientRow;
+
+        static ClientRow ClientCache[SESSION_ROWS];  /* Client Cache */
+                                                     /* uses session mutex */
+    #endif  /* NO_CLIENT_CACHE */
+
+#endif /* NO_SESSION_CACHE */
+
+int wolfSSL_Init(void)
+{
+    WOLFSSL_ENTER("wolfSSL_Init");
+
+    if (initRefCount == 0) {
+        /* Initialize crypto for use with TLS connection */
+        if (wolfCrypt_Init() != 0) {
+            WOLFSSL_MSG("Bad wolfCrypt Init");
+            return WC_INIT_E;
+        }
+#ifndef NO_SESSION_CACHE
+        if (wc_InitMutex(&session_mutex) != 0) {
+            WOLFSSL_MSG("Bad Init Mutex session");
+            return BAD_MUTEX_E;
+        }
+#endif
+        if (wc_InitMutex(&count_mutex) != 0) {
+            WOLFSSL_MSG("Bad Init Mutex count");
+            return BAD_MUTEX_E;
+        }
+    }
+
+    if (wc_LockMutex(&count_mutex) != 0) {
+        WOLFSSL_MSG("Bad Lock Mutex count");
+        return BAD_MUTEX_E;
+    }
+
+    initRefCount++;
+    wc_UnLockMutex(&count_mutex);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+
+#ifndef NO_CERTS
+
+/* process user cert chain to pass during the handshake */
+static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                         long sz, int format, int type, WOLFSSL* ssl,
+                         long* used, EncryptedInfo* info)
+{
+    int ret = 0;
+    void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+#ifdef WOLFSSL_TLS13
+    int cnt = 0;
+#endif
+
+    /* we may have a user cert chain, try to consume */
+    if (type == CERT_TYPE && info->consumed < sz) {
+    #ifdef WOLFSSL_SMALL_STACK
+        byte   staticBuffer[1];                 /* force heap usage */
+    #else
+        byte   staticBuffer[FILE_BUFFER_SIZE];  /* tmp chain buffer */
+    #endif
+        byte*  chainBuffer = staticBuffer;
+        int    dynamicBuffer = 0;
+        word32 bufferSz;
+        long   consumed = info->consumed;
+        word32 idx = 0;
+        int    gotOne = 0;
+
+        /* Calculate max possible size, including max headers */
+        bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
+        if (bufferSz > sizeof(staticBuffer)) {
+            WOLFSSL_MSG("Growing Tmp Chain Buffer");
+            /* will shrink to actual size */
+            chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE);
+            if (chainBuffer == NULL) {
+                return MEMORY_E;
+            }
+            dynamicBuffer = 1;
+        }
+
+        WOLFSSL_MSG("Processing Cert Chain");
+        while (consumed < sz) {
+            DerBuffer* part = NULL;
+            word32 remain = (word32)(sz - consumed);
+            info->consumed = 0;
+
+            if (format == WOLFSSL_FILETYPE_PEM) {
+            #ifdef WOLFSSL_PEM_TO_DER
+                ret = PemToDer(buff + consumed, remain, type, &part,
+                               heap, info, NULL);
+            #else
+                ret = NOT_COMPILED_IN;
+            #endif
+            }
+            else {
+                int length = remain;
+                if (format == WOLFSSL_FILETYPE_ASN1) {
+                    /* get length of der (read sequence) */
+                    word32 inOutIdx = 0;
+                    if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) {
+                        ret = ASN_NO_PEM_HEADER;
+                    }
+                    length += inOutIdx; /* include leading sequence */
+                }
+                info->consumed = length;
+                if (ret == 0) {
+                    ret = AllocDer(&part, length, type, heap);
+                    if (ret == 0) {
+                        XMEMCPY(part->buffer, buff + consumed, length);
+                    }
+                }
+            }
+            if (ret == 0) {
+                gotOne = 1;
+#ifdef WOLFSSL_TLS13
+                cnt++;
+#endif
+                if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
+                    WOLFSSL_MSG("   Cert Chain bigger than buffer");
+                    ret = BUFFER_E;
+                }
+                else {
+                    c32to24(part->length, &chainBuffer[idx]);
+                    idx += CERT_HEADER_SZ;
+                    XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
+                    idx += part->length;
+                    consumed  += info->consumed;
+                    if (used)
+                        *used += info->consumed;
+                }
+            }
+            FreeDer(&part);
+
+            if (ret == ASN_NO_PEM_HEADER && gotOne) {
+                WOLFSSL_MSG("We got one good cert, so stuff at end ok");
+                break;
+            }
+
+            if (ret < 0) {
+                WOLFSSL_MSG("   Error in Cert in Chain");
+                if (dynamicBuffer)
+                    XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+                return ret;
+            }
+            WOLFSSL_MSG("   Consumed another Cert in Chain");
+        }
+        WOLFSSL_MSG("Finished Processing Cert Chain");
+
+        /* only retain actual size used */
+        ret = 0;
+        if (idx > 0) {
+            if (ssl) {
+                if (ssl->buffers.weOwnCertChain) {
+                    FreeDer(&ssl->buffers.certChain);
+                }
+                ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
+                if (ret == 0) {
+                    XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, idx);
+                    ssl->buffers.weOwnCertChain = 1;
+                }
+#ifdef WOLFSSL_TLS13
+                ssl->buffers.certChainCnt = cnt;
+#endif
+            } else if (ctx) {
+                FreeDer(&ctx->certChain);
+                ret = AllocDer(&ctx->certChain, idx, type, heap);
+                if (ret == 0) {
+                    XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
+                }
+#ifdef WOLFSSL_TLS13
+                ctx->certChainCnt = cnt;
+#endif
+            }
+        }
+
+        if (dynamicBuffer)
+            XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+    }
+
+    return ret;
+}
+/* process the buffer buff, length sz, into ctx of format and type
+   used tracks bytes consumed, userChain specifies a user cert chain
+   to pass during the handshake */
+int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                         long sz, int format, int type, WOLFSSL* ssl,
+                         long* used, int userChain)
+{
+    DerBuffer*    der = NULL;        /* holds DER or RAW (for NTRU) */
+    int           ret = 0;
+    int           eccKey = 0;
+    int           ed25519Key = 0;
+    int           rsaKey = 0;
+    int           resetSuites = 0;
+    void*         heap = wolfSSL_CTX_GetHeap(ctx, ssl);
+    int           devId = wolfSSL_CTX_GetDevId(ctx, ssl);
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo  info[1];
+#endif
+
+    (void)rsaKey;
+    (void)devId;
+
+    if (used)
+        *used = sz;     /* used bytes default to sz, PEM chain may shorten*/
+
+    /* check args */
+    if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM
+                                    && format != WOLFSSL_FILETYPE_RAW)
+        return WOLFSSL_BAD_FILETYPE;
+
+    if (ctx == NULL && ssl == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
+                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
+    if (info == NULL)
+        return MEMORY_E;
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    if (ctx) {
+        info->passwd_cb       = ctx->passwd_cb;
+        info->passwd_userdata = ctx->passwd_userdata;
+    }
+#endif
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey);
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        /* ASN1 (DER) or RAW (NTRU) */
+        int length = (int)sz;
+        if (format == WOLFSSL_FILETYPE_ASN1) {
+            /* get length of der (read sequence) */
+            word32 inOutIdx = 0;
+            if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) {
+                ret = ASN_PARSE_E;
+            }
+            length += inOutIdx; /* include leading sequence */
+        }
+
+        info->consumed = length;
+
+        if (ret == 0) {
+            ret = AllocDer(&der, (word32)length, type, heap);
+            if (ret == 0) {
+                XMEMCPY(der->buffer, buff, length);
+            }
+        }
+    }
+
+    if (used) {
+        *used = info->consumed;
+    }
+
+    /* process user chain */
+    if (ret >= 0) {
+        /* First certificate in chain is loaded into ssl->buffers.certificate.
+         * Remainder are loaded into ssl->buffers.certChain.
+         * Chain should have server cert first, then intermediates, then root.
+         */
+        if (userChain) {
+            ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info);
+        }
+    }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    /* for WOLFSSL_FILETYPE_PEM, PemToDer manage the decryption if required */
+    if (ret >= 0 && info->set && format != WOLFSSL_FILETYPE_PEM) {
+        /* decrypt */
+        int   passwordSz = NAME_SZ;
+#ifdef WOLFSSL_SMALL_STACK
+        char* password = NULL;
+#else
+        char  password[NAME_SZ];
+#endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+        if (password == NULL)
+            ret = MEMORY_E;
+        else
+    #endif
+        if (info->passwd_cb == NULL) {
+            WOLFSSL_MSG("No password callback set");
+            ret = NO_PASSWORD;
+        }
+        else {
+            ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+                info->passwd_userdata);
+            if (ret >= 0) {
+                passwordSz = ret;
+
+                /* decrypt the key */
+                ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
+                    (byte*)password, passwordSz, WC_MD5);
+
+                ForceZero(password, passwordSz);
+            }
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(password, heap, DYNAMIC_TYPE_STRING);
+    #endif
+    }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+
+    /* check for error */
+    if (ret < 0) {
+        FreeDer(&der);
+        return ret;
+    }
+
+    /* Handle DER owner */
+    if (type == CA_TYPE) {
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Need context for CA load");
+            FreeDer(&der);
+            return BAD_FUNC_ARG;
+        }
+        /* verify CA unless user set to no verify */
+        return AddCA(ctx->cm, &der, WOLFSSL_USER_CA, !ctx->verifyNone);
+    }
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    else if (type == TRUSTED_PEER_TYPE) {
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Need context for trusted peer cert load");
+            FreeDer(&der);
+            return BAD_FUNC_ARG;
+        }
+        /* add trusted peer cert */
+        return AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone);
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+    else if (type == CERT_TYPE) {
+        if (ssl) {
+             /* Make sure previous is free'd */
+            if (ssl->buffers.weOwnCert) {
+                FreeDer(&ssl->buffers.certificate);
+            #ifdef KEEP_OUR_CERT
+                FreeX509(ssl->ourCert);
+                if (ssl->ourCert) {
+                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+                    ssl->ourCert = NULL;
+                }
+            #endif
+            }
+            ssl->buffers.certificate = der;
+        #ifdef KEEP_OUR_CERT
+            ssl->keepCert = 1; /* hold cert for ssl lifetime */
+        #endif
+            ssl->buffers.weOwnCert = 1;
+        }
+        else if (ctx) {
+            FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+        #ifdef KEEP_OUR_CERT
+            if (ctx->ourCert) {
+                if (ctx->ownOurCert) {
+                    FreeX509(ctx->ourCert);
+                    XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+                }
+                ctx->ourCert = NULL;
+            }
+        #endif
+            ctx->certificate = der;
+        }
+    }
+    else if (type == PRIVATEKEY_TYPE) {
+        if (ssl) {
+             /* Make sure previous is free'd */
+            if (ssl->buffers.weOwnKey) {
+                FreeDer(&ssl->buffers.key);
+            }
+            ssl->buffers.key = der;
+            ssl->buffers.weOwnKey = 1;
+        }
+        else if (ctx) {
+            FreeDer(&ctx->privateKey);
+            ctx->privateKey = der;
+        }
+    }
+    else {
+        FreeDer(&der);
+        return WOLFSSL_BAD_CERTTYPE;
+    }
+
+    if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) {
+    #ifndef NO_RSA
+        if (!eccKey && !ed25519Key) {
+            /* make sure RSA key can be used */
+            word32 idx = 0;
+        #ifdef WOLFSSL_SMALL_STACK
+            RsaKey* key = NULL;
+        #else
+            RsaKey  key[1];
+        #endif
+
+        #ifdef WOLFSSL_SMALL_STACK
+            key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
+            if (key == NULL)
+                return MEMORY_E;
+        #endif
+
+            ret = wc_InitRsaKey_ex(key, heap, devId);
+            if (ret == 0) {
+                if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length)
+                    != 0) {
+                #ifdef HAVE_ECC
+                    /* could have DER ECC (or pkcs8 ecc), no easy way to tell */
+                    eccKey = 1;  /* try it next */
+                #elif defined(HAVE_ED25519)
+                    ed25519Key = 1; /* try it next */
+                #else
+                    WOLFSSL_MSG("RSA decode failed and ECC not enabled to try");
+                    ret = WOLFSSL_BAD_FILE;
+                #endif
+                }
+                else {
+                    /* check that the size of the RSA key is enough */
+                    int rsaSz = wc_RsaEncryptSize((RsaKey*)key);
+                    int minRsaSz;
+
+                    minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
+                    if (rsaSz < minRsaSz) {
+                        ret = RSA_KEY_SIZE_E;
+                        WOLFSSL_MSG("Private Key size too small");
+                    }
+
+                    if (ssl) {
+                        ssl->buffers.keyType = rsa_sa_algo;
+                        ssl->buffers.keySz = rsaSz;
+                    }
+                    else if(ctx) {
+                        ctx->privateKeyType = rsa_sa_algo;
+                        ctx->privateKeySz = rsaSz;
+                    }
+
+                    rsaKey = 1;
+                    (void)rsaKey;  /* for no ecc builds */
+
+                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                        ssl->options.haveStaticECC = 0;
+                        resetSuites = 1;
+                    }
+                }
+
+                wc_FreeRsaKey(key);
+            }
+
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(key, heap, DYNAMIC_TYPE_RSA);
+        #endif
+
+            if (ret != 0)
+                return ret;
+        }
+    #endif
+    #ifdef HAVE_ECC
+        if (!rsaKey && !ed25519Key) {
+            /* make sure ECC key can be used */
+            word32   idx = 0;
+        #ifdef WOLFSSL_SMALL_STACK
+            ecc_key* key = NULL;
+        #else
+            ecc_key  key[1];
+        #endif
+
+        #ifdef WOLFSSL_SMALL_STACK
+            key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
+            if (key == NULL)
+                return MEMORY_E;
+        #endif
+
+            if (wc_ecc_init_ex(key, heap, devId) == 0) {
+                if (wc_EccPrivateKeyDecode(der->buffer, &idx, key,
+                                                            der->length) == 0) {
+                    int keySz = wc_ecc_size(key);
+                    int minKeySz;
+
+                    /* check for minimum ECC key size and then free */
+                    minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
+                    if (keySz < minKeySz) {
+                        wc_ecc_free(key);
+                        WOLFSSL_MSG("ECC private key too small");
+                        return ECC_KEY_SIZE_E;
+                    }
+
+                    eccKey = 1;
+                    if (ssl) {
+                        ssl->options.haveStaticECC = 1;
+                        ssl->buffers.keyType = ecc_dsa_sa_algo;
+                        ssl->buffers.keySz = keySz;
+                    }
+                    else if (ctx) {
+                        ctx->haveStaticECC = 1;
+                        ctx->privateKeyType = ecc_dsa_sa_algo;
+                        ctx->privateKeySz = keySz;
+                    }
+
+                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                        resetSuites = 1;
+                    }
+                }
+                else
+                    eccKey = 0;
+
+                wc_ecc_free(key);
+            }
+
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(key, heap, DYNAMIC_TYPE_ECC);
+        #endif
+        }
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        if (!rsaKey && !eccKey) {
+            /* make sure Ed25519 key can be used */
+            word32       idx = 0;
+        #ifdef WOLFSSL_SMALL_STACK
+            ed25519_key* key = NULL;
+        #else
+            ed25519_key  key[1];
+        #endif
+
+        #ifdef WOLFSSL_SMALL_STACK
+            key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
+                                                          DYNAMIC_TYPE_ED25519);
+            if (key == NULL)
+                return MEMORY_E;
+        #endif
+
+            ret = wc_ed25519_init(key);
+            if (ret == 0) {
+                if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key,
+                                                            der->length) != 0) {
+                    ret = WOLFSSL_BAD_FILE;
+                }
+
+                if (ret == 0) {
+                    /* check for minimum key size and then free */
+                    int minKeySz = ssl ? ssl->options.minEccKeySz :
+                                                               ctx->minEccKeySz;
+                    if (ED25519_KEY_SIZE < minKeySz) {
+                        WOLFSSL_MSG("ED25519 private key too small");
+                        ret = ECC_KEY_SIZE_E;
+                    }
+                }
+                if (ret == 0) {
+                    if (ssl) {
+                        ssl->buffers.keyType = ed25519_sa_algo;
+                        ssl->buffers.keySz = ED25519_KEY_SIZE;
+                    }
+                    else if (ctx) {
+                        ctx->privateKeyType = ed25519_sa_algo;
+                        ctx->privateKeySz = ED25519_KEY_SIZE;
+                    }
+
+                    ed25519Key = 1;
+                    if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+                        resetSuites = 1;
+                    }
+                }
+
+                wc_ed25519_free(key);
+            }
+
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(key, heap, DYNAMIC_TYPE_ED25519);
+        #endif
+            if (ret != 0)
+                return ret;
+        }
+    #else
+        if (!rsaKey && !eccKey && !ed25519Key)
+            return WOLFSSL_BAD_FILE;
+    #endif
+        (void)ed25519Key;
+        (void)devId;
+    }
+    else if (type == CERT_TYPE) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert = NULL;
+    #else
+        DecodedCert  cert[1];
+    #endif
+    #ifdef HAVE_PK_CALLBACKS
+        int keyType = 0, keySz = 0;
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+
+        WOLFSSL_MSG("Checking cert signature type");
+        InitDecodedCert(cert, der->buffer, der->length, heap);
+
+        if (DecodeToKey(cert, 0) < 0) {
+            WOLFSSL_MSG("Decode to key failed");
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
+        #endif
+            return WOLFSSL_BAD_FILE;
+        }
+
+        if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
+            resetSuites = 1;
+        }
+        if (ssl && ssl->ctx->haveECDSAsig) {
+            WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off");
+            ssl->options.haveECDSAsig = 0;   /* may turn back on next */
+        }
+
+        switch (cert->signatureOID) {
+            case CTC_SHAwECDSA:
+            case CTC_SHA256wECDSA:
+            case CTC_SHA384wECDSA:
+            case CTC_SHA512wECDSA:
+                WOLFSSL_MSG("ECDSA cert signature");
+                if (ssl)
+                    ssl->options.haveECDSAsig = 1;
+                else if (ctx)
+                    ctx->haveECDSAsig = 1;
+                break;
+            case CTC_ED25519:
+                WOLFSSL_MSG("ED25519 cert signature");
+                if (ssl)
+                    ssl->options.haveECDSAsig = 1;
+                else if (ctx)
+                    ctx->haveECDSAsig = 1;
+                break;
+            default:
+                WOLFSSL_MSG("Not ECDSA cert signature");
+                break;
+        }
+
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+        if (ssl) {
+            ssl->pkCurveOID = cert->pkCurveOID;
+        #ifndef WC_STRICT_SIG
+            if (cert->keyOID == ECDSAk) {
+                ssl->options.haveECC = 1;
+            }
+            #ifdef HAVE_ED25519
+                else if (cert->keyOID == ED25519k) {
+                    ssl->options.haveECC = 1;
+                }
+            #endif
+        #else
+            ssl->options.haveECC = ssl->options.haveECDSAsig;
+        #endif
+        }
+        else if (ctx) {
+            ctx->pkCurveOID = cert->pkCurveOID;
+        #ifndef WC_STRICT_SIG
+            if (cert->keyOID == ECDSAk) {
+                ctx->haveECC = 1;
+            }
+            #ifdef HAVE_ED25519
+                else if (cert->keyOID == ED25519k) {
+                    ctx->haveECC = 1;
+                }
+            #endif
+        #else
+            ctx->haveECC = ctx->haveECDSAsig;
+        #endif
+        }
+    #endif
+
+        /* check key size of cert unless specified not to */
+        switch (cert->keyOID) {
+        #ifndef NO_RSA
+            case RSAk:
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minRsaKeySz < 0 ||
+                          cert->pubKeySize < (word16)ssl->options.minRsaKeySz) {
+                        ret = RSA_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate RSA key size too small");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minRsaKeySz < 0 ||
+                                  cert->pubKeySize < (word16)ctx->minRsaKeySz) {
+                        ret = RSA_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate RSA key size too small");
+                    }
+                }
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = rsa_sa_algo;
+                /* pubKeySize is the encoded public key */
+                /* mask lsb 5-bits to round by 16 to get actual key size */
+                keySz = cert->pubKeySize & ~0x1FL;
+            #endif
+                break;
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            case ECDSAk:
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          cert->pubKeySize < (word16)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  cert->pubKeySize < (word16)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = ecc_dsa_sa_algo;
+                /* pubKeySize is encByte + x + y */
+                keySz = (cert->pubKeySize - 1) / 2;
+            #endif
+                break;
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            case ED25519k:
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate Ed key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+            #ifdef HAVE_PK_CALLBACKS
+                keyType = ed25519_sa_algo;
+                keySz = ED25519_KEY_SIZE;
+            #endif
+                break;
+        #endif /* HAVE_ED25519 */
+
+            default:
+                WOLFSSL_MSG("No key size check done on certificate");
+                break; /* do no check if not a case for the key */
+        }
+
+    #ifdef HAVE_PK_CALLBACKS
+        if (ssl && ssl->buffers.keyType == 0) {
+            ssl->buffers.keyType = keyType;
+            ssl->buffers.keySz = keySz;
+        }
+        else if (ctx && ctx->privateKeyType == 0) {
+            ctx->privateKeyType = keyType;
+            ctx->privateKeySz = keySz;
+        }
+    #endif
+
+        FreeDecodedCert(cert);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
+    #endif
+
+        if (ret != 0) {
+            return ret;
+        }
+    }
+
+    if (ssl && resetSuites) {
+        word16 havePSK = 0;
+        word16 haveRSA = 0;
+        int    keySz   = 0;
+
+        #ifndef NO_PSK
+        if (ssl->options.havePSK) {
+            havePSK = 1;
+        }
+        #endif
+        #ifndef NO_RSA
+            haveRSA = 1;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+
+        /* let's reset suites */
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
+                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* CA PEM file for verification, may have multiple/chain certs to process */
+static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                            long sz, int format, int type, WOLFSSL* ssl)
+{
+    long used   = 0;
+    int  ret    = 0;
+    int  gotOne = 0;
+
+    WOLFSSL_MSG("Processing CA PEM file");
+    while (used < sz) {
+        long consumed = 0;
+
+        ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
+                            &consumed, 0);
+
+#ifdef WOLFSSL_WPAS
+#ifdef HAVE_CRL
+        if (ret < 0) {
+            DerBuffer*    der = NULL;
+            EncryptedInfo info;
+
+            WOLFSSL_MSG("Trying a CRL");
+            if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info,
+                                                                   NULL) == 0) {
+                WOLFSSL_MSG("   Proccessed a CRL");
+                wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
+                                                der->length, WOLFSSL_FILETYPE_ASN1);
+                FreeDer(&der);
+                used += info.consumed;
+                continue;
+            }
+        }
+#endif
+#endif
+        if (ret < 0)
+        {
+            if(consumed > 0) { /* Made progress in file */
+                WOLFSSL_ERROR(ret);
+                WOLFSSL_MSG("CA Parse failed, with progress in file.");
+                WOLFSSL_MSG("Search for other certs in file");
+            } else {
+                WOLFSSL_MSG("CA Parse failed, no progress in file.");
+                WOLFSSL_MSG("Do not continue search for other certs in file");
+                break;
+            }
+        } else {
+            WOLFSSL_MSG("   Processed a CA");
+            gotOne = 1;
+        }
+        used += consumed;
+    }
+
+    if(gotOne)
+    {
+        WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
+        return WOLFSSL_SUCCESS;
+    }
+    return ret;
+}
+
+
+static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void)
+{
+    #ifndef NO_WOLFSSL_CLIENT
+        #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+            return wolfSSLv3_client_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_client_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_client_method();
+        #endif
+    #elif !defined(NO_WOLFSSL_SERVER)
+        #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+            return wolfSSLv3_server_method();
+        #elif !defined(WOLFSSL_NO_TLS12)
+            return wolfTLSv1_2_server_method();
+        #elif defined(WOLFSSL_TLS13)
+            return wolfTLSv1_3_server_method();
+        #endif
+    #else
+        return NULL;
+    #endif
+}
+
+
+/* like load verify locations, 1 for success, < 0 for error */
+int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
+                                   const unsigned char* in, long sz, int format)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+    WOLFSSL_CTX* tmp;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer");
+
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        return ret;
+    }
+    tmp = wolfSSL_CTX_new(cm_pick_method());
+
+    if (tmp == NULL) {
+        WOLFSSL_MSG("CTX new failed");
+        return ret;
+    }
+
+    /* for tmp use */
+    wolfSSL_CertManagerFree(tmp->cm);
+    tmp->cm = cm;
+
+    ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format);
+
+    /* don't loose our good one */
+    tmp->cm = NULL;
+    wolfSSL_CTX_free(tmp);
+
+    return ret;
+}
+
+#ifdef HAVE_CRL
+
+int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
+                                   const unsigned char* buff, long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crl == NULL) {
+        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Enable CRL failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return BufferLoadCRL(cm->crl, buff, sz, type, 0);
+}
+
+
+int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                              long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
+}
+
+
+int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
+                          long sz, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
+
+    if (ssl == NULL || ssl->ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type);
+}
+
+
+#endif /* HAVE_CRL */
+
+/* turn on CRL if off and compiled in, set options */
+int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    (void)options;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    #ifdef HAVE_CRL
+        if (cm->crl == NULL) {
+            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
+                                            DYNAMIC_TYPE_CRL);
+            if (cm->crl == NULL)
+                return MEMORY_E;
+
+            if (InitCRL(cm->crl, cm) != 0) {
+                WOLFSSL_MSG("Init CRL failed");
+                FreeCRL(cm->crl, 1);
+                cm->crl = NULL;
+                return WOLFSSL_FAILURE;
+            }
+
+        #ifdef HAVE_CRL_IO
+            cm->crl->crlIOCb = EmbedCrlLookup;
+        #endif
+        }
+
+        cm->crlEnabled = 1;
+        if (options & WOLFSSL_CRL_CHECKALL)
+            cm->crlCheckAll = 1;
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+
+    return ret;
+}
+
+
+int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->crlEnabled = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff,
+                                    long sz, int format)
+{
+    int ret = 0;
+    DerBuffer* der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+                                 DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+        ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
+        if (ret != 0) {
+            FreeDer(&der);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+        #endif
+            return ret;
+        }
+        InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+#else
+        ret = NOT_COMPILED_IN;
+#endif
+    }
+    else {
+        InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap);
+    }
+
+    if (ret == 0)
+        ret = ParseCertRelative(cert, CERT_TYPE, 1, cm);
+
+#ifdef HAVE_CRL
+    if (ret == 0 && cm->crlEnabled)
+        ret = CheckCertCRL(cm->crl, cert);
+#endif
+
+    FreeDecodedCert(cert);
+    FreeDer(&der);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+
+/* turn on OCSP if off and compiled in, set options */
+int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    (void)options;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    #ifdef HAVE_OCSP
+        if (cm->ocsp == NULL) {
+            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
+                                              DYNAMIC_TYPE_OCSP);
+            if (cm->ocsp == NULL)
+                return MEMORY_E;
+
+            if (InitOCSP(cm->ocsp, cm) != 0) {
+                WOLFSSL_MSG("Init OCSP failed");
+                FreeOCSP(cm->ocsp, 1);
+                cm->ocsp = NULL;
+                return WOLFSSL_FAILURE;
+            }
+        }
+        cm->ocspEnabled = 1;
+        if (options & WOLFSSL_OCSP_URL_OVERRIDE)
+            cm->ocspUseOverrideURL = 1;
+        if (options & WOLFSSL_OCSP_NO_NONCE)
+            cm->ocspSendNonce = 0;
+        else
+            cm->ocspSendNonce = 1;
+        if (options & WOLFSSL_OCSP_CHECKALL)
+            cm->ocspCheckAll = 1;
+        #ifndef WOLFSSL_USER_IO
+            cm->ocspIOCb = EmbedOcspLookup;
+            cm->ocspRespFreeCb = EmbedOcspRespFree;
+            cm->ocspIOCtx = cm->heap;
+        #endif /* WOLFSSL_USER_IO */
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+
+    return ret;
+}
+
+
+int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->ocspEnabled = 0;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* turn on OCSP Stapling if off and compiled in, set options */
+int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    if (cm->ocsp_stapling == NULL) {
+        cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
+                                               cm->heap, DYNAMIC_TYPE_OCSP);
+        if (cm->ocsp_stapling == NULL)
+            return MEMORY_E;
+
+        if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
+            WOLFSSL_MSG("Init OCSP failed");
+            FreeOCSP(cm->ocsp_stapling, 1);
+            cm->ocsp_stapling = NULL;
+            return WOLFSSL_FAILURE;
+        }
+    }
+    cm->ocspStaplingEnabled = 1;
+
+    #ifndef WOLFSSL_USER_IO
+        cm->ocspIOCb = EmbedOcspLookup;
+        cm->ocspRespFreeCb = EmbedOcspRespFree;
+        cm->ocspIOCtx = cm->heap;
+    #endif /* WOLFSSL_USER_IO */
+#else
+    ret = NOT_COMPILED_IN;
+#endif
+
+    return ret;
+}
+
+int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    cm->ocspStaplingEnabled = 0;
+#else
+    ret = NOT_COMPILED_IN;
+#endif
+    return ret;
+}
+#if defined(SESSION_CERTS)
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
+    if ((ssl == NULL) || (ssl->session.chain.count == 0))
+        return NULL;
+    else
+        return (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain;
+}
+#endif
+#ifdef HAVE_OCSP
+
+/* check CRL if enabled, WOLFSSL_SUCCESS  */
+int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
+{
+    int ret;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->ocspEnabled == 0)
+        return WOLFSSL_SUCCESS;
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(cert, der, sz, NULL);
+
+    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) {
+        WOLFSSL_MSG("CheckCertOCSP failed");
+    }
+
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+
+int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
+                                          const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+    if (url != NULL) {
+        int urlSz = (int)XSTRLEN(url) + 1;
+        cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL);
+        if (cm->ocspOverrideURL != NULL) {
+            XMEMCPY(cm->ocspOverrideURL, url, urlSz);
+        }
+        else
+            return MEMORY_E;
+    }
+    else
+        cm->ocspOverrideURL = NULL;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm,
+                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->ocspIOCb = ioCb;
+    cm->ocspRespFreeCb = respFreeCb;
+    cm->ocspIOCtx = ioCbCtx;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableOCSP");
+    if (ssl)
+        return wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSP(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableOCSP");
+    if (ssl)
+        return wolfSSL_CertManagerDisableOCSP(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
+    if (ssl)
+        return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
+    if (ssl)
+        return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+    if (ssl)
+        return wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
+                        CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
+    if (ssl) {
+        ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
+        return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm,
+                                             ioCb, respFreeCb, NULL);
+    }
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
+    if (ctx)
+        return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
+    if (ctx)
+        return wolfSSL_CertManagerDisableOCSP(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
+{
+    WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+    if (ctx)
+        return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
+                           CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
+    if (ctx)
+        return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
+                                             respFreeCb, ioCbCtx);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
+    if (ctx)
+        return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
+    if (ctx)
+        return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+#endif /* HAVE_OCSP */
+
+
+#ifndef NO_FILESYSTEM
+
+/* process a file with name fname into ctx of format and type
+   userChain specifies a user certificate chain to pass during handshake */
+int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
+                WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    int    ret;
+    long   sz = 0;
+    XFILE  file;
+    void*  heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
+
+    (void)crl;
+    (void)heapHint;
+
+    if (fname == NULL) return WOLFSSL_BAD_FILE;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    XFSEEK(file, 0, XSEEK_END);
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+    else if (sz <= 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else {
+        if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
+                                                  && format == WOLFSSL_FILETYPE_PEM)
+            ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl);
+#ifdef HAVE_CRL
+        else if (type == CRL_TYPE)
+            ret = BufferLoadCRL(crl, myBuffer, sz, format, 0);
+#endif
+        else
+            ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL,
+                                userChain);
+    }
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+
+/* loads file then loads each file in path, no c_rehash */
+int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
+                                     const char* path)
+{
+    int ret = WOLFSSL_SUCCESS;
+#ifndef NO_WOLFSSL_DIR
+    int fileRet;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations");
+
+    if (ctx == NULL || (file == NULL && path == NULL) )
+        return WOLFSSL_FAILURE;
+
+    if (file)
+        ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL);
+
+    if (ret == WOLFSSL_SUCCESS && path) {
+#ifndef NO_WOLFSSL_DIR
+        char* name = NULL;
+    #ifdef WOLFSSL_SMALL_STACK
+        ReadDirCtx* readCtx = NULL;
+        readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
+                                                       DYNAMIC_TYPE_DIRCTX);
+        if (readCtx == NULL)
+            return MEMORY_E;
+    #else
+        ReadDirCtx readCtx[1];
+    #endif
+
+        /* try to load each regular file in path */
+        fileRet = wc_ReadDirFirst(readCtx, path, &name);
+        while (fileRet == 0 && name) {
+            ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE,
+                                                          NULL, 0, NULL);
+            if (ret != WOLFSSL_SUCCESS)
+                break;
+            fileRet = wc_ReadDirNext(readCtx, path, &name);
+        }
+        wc_ReadDirClose(readCtx);
+
+        /* pass directory read failure to response code */
+        if (ret == WOLFSSL_SUCCESS && fileRet != -1) {
+            ret = fileRet;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
+    #endif
+#else
+        ret = NOT_COMPILED_IN;
+#endif
+    }
+
+    return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Used to specify a peer cert to match when connecting
+    ctx : the ctx structure to load in peer cert
+    file: the string name of cert file
+    type: type of format such as PEM/DER
+ */
+int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
+
+    if (ctx == NULL || file == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL);
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */
+int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
+                             int format)
+{
+    int    ret = WOLFSSL_FATAL_ERROR;
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    long   sz = 0;
+    XFILE  file = XFOPEN(fname, "rb");
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
+
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    XFSEEK(file, 0, XSEEK_END);
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
+        WOLFSSL_MSG("CertManagerVerify file bad size");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else
+        ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format);
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+
+/* like load verify locations, 1 for success, < 0 for error */
+int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
+                             const char* path)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+    WOLFSSL_CTX* tmp;
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
+
+    if (cm == NULL) {
+        WOLFSSL_MSG("No CertManager error");
+        return ret;
+    }
+    tmp = wolfSSL_CTX_new(cm_pick_method());
+
+    if (tmp == NULL) {
+        WOLFSSL_MSG("CTX new failed");
+        return ret;
+    }
+
+    /* for tmp use */
+    wolfSSL_CertManagerFree(tmp->cm);
+    tmp->cm = cm;
+
+    ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
+
+    /* don't loose our good one */
+    tmp->cm = NULL;
+    wolfSSL_CTX_free(tmp);
+
+    return ret;
+}
+
+
+/* Check private against public in certificate for match
+ *
+ * ctx  WOLFSSL_CTX structure to check private key in
+ *
+ * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */
+int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* der = NULL;
+#else
+    DecodedCert  der[1];
+#endif
+    word32 size;
+    byte*  buff;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_check_private_key");
+
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef NO_CERTS
+#ifdef WOLFSSL_SMALL_STACK
+    der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (der == NULL)
+        return MEMORY_E;
+#endif
+
+    size = ctx->certificate->length;
+    buff = ctx->certificate->buffer;
+    InitDecodedCert(der, buff, size, ctx->heap);
+    if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+        FreeDecodedCert(der);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ctx->privateKey->length;
+    buff = ctx->privateKey->buffer;
+    ret  = wc_CheckPrivateKey(buff, size, der);
+    FreeDecodedCert(der);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(der, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    if (ret == 1) {
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        return WOLFSSL_FAILURE;
+    }
+#else
+    WOLFSSL_MSG("NO_CERTS is defined, can not check private key");
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+#ifdef HAVE_CRL
+
+
+/* check CRL if enabled, WOLFSSL_SUCCESS  */
+int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz)
+{
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
+
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crlEnabled == 0)
+        return WOLFSSL_SUCCESS;
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return MEMORY_E;
+#endif
+
+    InitDecodedCert(cert, der, sz, NULL);
+
+    if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) {
+        WOLFSSL_MSG("ParseCert failed");
+    }
+    else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
+        WOLFSSL_MSG("CheckCertCRL failed");
+    }
+
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+
+int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->cbMissingCRL = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
+{
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    cm->crl->crlIOCb = cb;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
+                              int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
+    if (cm == NULL)
+        return BAD_FUNC_ARG;
+
+    if (cm->crl == NULL) {
+        if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Enable CRL failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return LoadCRL(cm->crl, path, type, monitor);
+}
+
+
+int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_EnableCRL");
+    if (ssl)
+        return wolfSSL_CertManagerEnableCRL(ssl->ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_DisableCRL(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_DisableCRL");
+    if (ssl)
+        return wolfSSL_CertManagerDisableCRL(ssl->ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_LoadCRL");
+    if (ssl)
+        return wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+    if (ssl)
+        return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+    if (ssl)
+        return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif
+
+int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
+    if (ctx)
+        return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
+    if (ctx)
+        return wolfSSL_CertManagerDisableCRL(ctx->cm);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
+                        int type, int monitor)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
+    if (ctx)
+        return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
+    else
+        return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
+    if (ctx)
+        return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
+    if (ctx)
+        return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
+    else
+        return BAD_FUNC_ARG;
+}
+#endif
+
+
+#endif /* HAVE_CRL */
+
+
+#ifdef WOLFSSL_DER_LOAD
+
+/* Add format parameter to allow DER load of CA files */
+int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
+                                          int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
+    if (ctx == NULL || file == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* WOLFSSL_DER_LOAD */
+
+
+
+int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
+                                     int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
+    if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
+                                    int format)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
+    if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL)
+                    == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Sets the max chain depth when verifying a certificate chain. Default depth
+ * is set to MAX_CHAIN_DEPTH.
+ *
+ * ctx   WOLFSSL_CTX structure to set depth in
+ * depth max depth
+ */
+void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
+    WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
+
+    if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
+        WOLFSSL_MSG("Bad depth argument, too large or less than 0");
+        return;
+    }
+
+    ctx->verifyDepth = (byte)depth;
+}
+
+
+/* get cert chaining depth using ssl struct */
+long wolfSSL_get_verify_depth(WOLFSSL* ssl)
+{
+    if(ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#ifndef OPENSSL_EXTRA
+    return MAX_CHAIN_DEPTH;
+#else
+    return ssl->options.verifyDepth;
+#endif
+}
+
+
+/* get cert chaining depth using ctx struct */
+long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
+{
+    if(ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+#ifndef OPENSSL_EXTRA
+    return MAX_CHAIN_DEPTH;
+#else
+    return ctx->verifyDepth;
+#endif
+}
+
+
+int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
+{
+   /* process up to MAX_CHAIN_DEPTH plus subject cert */
+   WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
+   if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL)
+                   == WOLFSSL_SUCCESS)
+       return WOLFSSL_SUCCESS;
+
+   return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
+                                                  const char* file, int format)
+{
+   /* process up to MAX_CHAIN_DEPTH plus subject cert */
+   WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
+   if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL)
+                   == WOLFSSL_SUCCESS)
+       return WOLFSSL_SUCCESS;
+
+   return WOLFSSL_FAILURE;
+}
+
+
+#ifndef NO_DH
+
+/* server Diffie-Hellman parameters */
+static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+                                        const char* fname, int format)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte   staticBuffer[1]; /* force heap usage */
+#else
+    byte   staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte*  myBuffer = staticBuffer;
+    int    dynamic = 0;
+    int    ret;
+    long   sz = 0;
+    XFILE  file;
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) return WOLFSSL_BAD_FILE;
+    XFSEEK(file, 0, XSEEK_END);
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        WOLFSSL_MSG("Getting dynamic buffer");
+        myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+        if (myBuffer == NULL) {
+            XFCLOSE(file);
+            return WOLFSSL_BAD_FILE;
+        }
+        dynamic = 1;
+    }
+    else if (sz <= 0) {
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz)
+        ret = WOLFSSL_BAD_FILE;
+    else {
+        if (ssl)
+            ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format);
+        else
+            ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format);
+    }
+
+    XFCLOSE(file);
+    if (dynamic)
+        XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+    return ret;
+}
+
+/* server Diffie-Hellman parameters */
+int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
+}
+
+
+/* server Diffie-Hellman parameters */
+int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
+{
+    return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
+}
+
+#endif /* NO_DH */
+
+#endif /* NO_FILESYSTEM */
+
+
+#if defined(OPENSSL_EXTRA) || !defined(NO_PWDBASED) && \
+    (defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER))
+
+static int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
+    int* pHash, int* pHashSz)
+{
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+    int hashSz;
+
+    if (XSTRLEN(evp) < 3) {
+        /* do not try comparing strings if size is too small */
+        return WOLFSSL_FAILURE;
+    }
+
+    if (XSTRNCMP("SHA", evp, 3) == 0) {
+        if (XSTRLEN(evp) > 3) {
+        #ifndef NO_SHA256
+            if (XSTRNCMP("SHA256", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA256;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA384
+            if (XSTRNCMP("SHA384", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA384;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_SHA512
+            if (XSTRNCMP("SHA512", evp, 6) == 0) {
+                hash = WC_HASH_TYPE_SHA512;
+            }
+            else
+        #endif
+            {
+                WOLFSSL_MSG("Unknown SHA hash");
+            }
+        }
+        else {
+            hash = WC_HASH_TYPE_SHA;
+        }
+    }
+#ifdef WOLFSSL_MD2
+    else if (XSTRNCMP("MD2", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD2;
+    }
+#endif
+#ifndef NO_MD4
+    else if (XSTRNCMP("MD4", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD4;
+    }
+#endif
+#ifndef NO_MD5
+    else if (XSTRNCMP("MD5", evp, 3) == 0) {
+        hash = WC_HASH_TYPE_MD5;
+    }
+#endif
+
+    if (pHash)
+        *pHash = hash;
+
+    hashSz = wc_HashGetDigestSize(hash);
+    if (pHashSz)
+        *pHashSz = hashSz;
+
+    if (hashSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif
+
+
+#ifdef OPENSSL_EXTRA
+/* put SSL type in extra for now, not very common */
+
+/* Converts a DER format key read from "bio" to a PKCS8 structure.
+ *
+ * bio  input bio to read DER from
+ * pkey If not NULL then this pointer will be overwritten with a new PKCS8
+ *      structure.
+ *
+ * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
+ *         case.
+ */
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
+        WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
+{
+    WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+    unsigned char* mem;
+    int memSz;
+    int keySz;
+
+    WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+
+    if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
+        return NULL;
+    }
+
+    if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) {
+        WOLFSSL_MSG("Not PEM format");
+        keySz = memSz;
+        if ((keySz = ToTraditional((byte*)mem, (word32)keySz)) < 0) {
+            return NULL;
+        }
+    }
+
+    pkcs8 = wolfSSL_PKEY_new();
+    if (pkcs8 == NULL) {
+        return NULL;
+    }
+
+    pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pkcs8->pkey.ptr == NULL) {
+        wolfSSL_EVP_PKEY_free(pkcs8);
+        return NULL;
+    }
+    XMEMCPY(pkcs8->pkey.ptr, mem, keySz);
+    pkcs8->pkey_sz = keySz;
+
+    if (pkey != NULL) {
+        *pkey = pkcs8;
+    }
+#else
+    (void)bio;
+    (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+    return pkcs8;
+}
+
+
+/* expecting DER format public key
+ *
+ * bio  input bio to read DER from
+ * out  If not NULL then this pointer will be overwritten with a new
+ * WOLFSSL_EVP_PKEY pointer
+ *
+ * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+                                         WOLFSSL_EVP_PKEY** out)
+{
+    unsigned char* mem;
+    long memSz;
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+    (void)out;
+
+    memSz = wolfSSL_BIO_pending(bio);
+    if (memSz <= 0) {
+        return NULL;
+    }
+
+    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        return NULL;
+    }
+
+    if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
+        pkey = wolfSSL_d2i_PUBKEY(NULL, &mem, memSz);
+        if (out != NULL && pkey != NULL) {
+            *out = pkey;
+        }
+    }
+
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return pkey;
+}
+
+
+
+/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
+ *
+ * out  pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
+ * in   DER buffer to convert
+ * inSz size of in buffer
+ *
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ *         on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in,
+        long inSz)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    const unsigned char* mem;
+    long memSz = inSz;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
+
+    if (in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    mem = *in;
+
+    #if !defined(NO_RSA)
+    {
+        RsaKey rsa;
+        word32 keyIdx = 0;
+
+        /* test if RSA key */
+        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+            wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+            wc_FreeRsaKey(&rsa);
+            pkey = wolfSSL_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_RSA;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownRsa = 1;
+                pkey->rsa = wolfSSL_RSA_new();
+                if (pkey->rsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeRsaKey(&rsa);
+    }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+    {
+        word32  keyIdx = 0;
+        ecc_key ecc;
+
+        if (wc_ecc_init(&ecc) == 0 &&
+            wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+            wc_ecc_free(&ecc);
+            pkey = wolfSSL_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+                        DYNAMIC_TYPE_PUBLIC_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_EC;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+                return pkey;
+            }
+        }
+        wc_ecc_free(&ecc);
+    }
+    #endif /* HAVE_ECC */
+
+    return pkey;
+
+}
+
+
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
+ *
+ * type  type of key
+ * out   newly created WOLFSSL_EVP_PKEY structure
+ * in    pointer to input key DER
+ * inSz  size of in buffer
+ *
+ * On success a non null pointer is returned and the pointer in is advanced the
+ * same number of bytes read.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
+        const unsigned char **in, long inSz)
+{
+    WOLFSSL_EVP_PKEY* local;
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
+
+    if (in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+
+    /* Check if input buffer has PKCS8 header. In the case that it does not
+     * have a PKCS8 header then do not error out. */
+    if ((ret = ToTraditionalInline((const byte*)(*in), &idx, (word32)inSz))
+            > 0) {
+        WOLFSSL_MSG("Found and removed PKCS8 header");
+    }
+    else {
+        if (ret != ASN_PARSE_E) {
+            WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+            return NULL;
+        }
+    }
+
+    if (out != NULL && *out != NULL) {
+        wolfSSL_EVP_PKEY_free(*out);
+    }
+    local = wolfSSL_PKEY_new();
+    if (local == NULL) {
+        return NULL;
+    }
+
+    /* sanity check on idx before use */
+    if ((int)idx > inSz) {
+        WOLFSSL_MSG("Issue with index pointer");
+        wolfSSL_EVP_PKEY_free(local);
+        local = NULL;
+        return NULL;
+    }
+
+    local->type     = type;
+    local->pkey_sz  = (int)inSz - idx;
+    local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (local->pkey.ptr == NULL) {
+        wolfSSL_EVP_PKEY_free(local);
+        local = NULL;
+        return NULL;
+    }
+    else {
+        XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx);
+    }
+
+    switch (type) {
+#ifndef NO_RSA
+        case EVP_PKEY_RSA:
+            local->ownRsa = 1;
+            local->rsa = wolfSSL_RSA_new();
+            if (local->rsa == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_RSA_LoadDer_ex(local->rsa,
+                      (const unsigned char*)local->pkey.ptr, local->pkey_sz,
+                      WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+        case EVP_PKEY_EC:
+            local->ownEcc = 1;
+            local->ecc = wolfSSL_EC_KEY_new();
+            if (local->ecc == NULL) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            if (wolfSSL_EC_KEY_LoadDer(local->ecc,
+                      (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+                      != SSL_SUCCESS) {
+                wolfSSL_EVP_PKEY_free(local);
+                return NULL;
+            }
+            break;
+#endif /* HAVE_ECC */
+
+        default:
+            WOLFSSL_MSG("Unsupported key type");
+            wolfSSL_EVP_PKEY_free(local);
+            return NULL;
+    }
+
+    /* advance pointer with success */
+    if (local != NULL) {
+        if ((idx + local->pkey_sz) <= (word32)inSz) {
+            *in = *in + idx + local->pkey_sz;
+        }
+
+        if (out != NULL) {
+            *out = local;
+        }
+    }
+
+    return local;
+}
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
+{
+    WOLFSSL_STUB("SSL_ctrl");
+    (void)ssl;
+    (void)cmd;
+    (void)opt;
+    (void)pt;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
+{
+    WOLFSSL_STUB("SSL_CTX_ctrl");
+    (void)ctx;
+    (void)cmd;
+    (void)opt;
+    (void)pt;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_CERTS
+
+int wolfSSL_check_private_key(const WOLFSSL* ssl)
+{
+    DecodedCert der;
+    word32 size;
+    byte*  buff;
+    int    ret;
+
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ssl->buffers.certificate->length;
+    buff = ssl->buffers.certificate->buffer;
+    InitDecodedCert(&der, buff, size, ssl->heap);
+#ifdef HAVE_PK_CALLBACKS
+    ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx);
+    if (ret != 0) {
+        FreeDecodedCert(&der);
+        return ret;
+    }
+#endif
+
+    if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+        FreeDecodedCert(&der);
+        return WOLFSSL_FAILURE;
+    }
+
+    size = ssl->buffers.key->length;
+    buff = ssl->buffers.key->buffer;
+    ret  = wc_CheckPrivateKey(buff, size, &der);
+    FreeDecodedCert(&der);
+    return ret;
+}
+
+
+/* Looks for the extension matching the passed in nid
+ *
+ * c   : if not null then is set to status value -2 if multiple occurances
+ *       of the extension are found, -1 if not found, 0 if found and not
+ *       critical, and 1 if found and critical.
+ * nid : Extension OID to be found.
+ * idx : if NULL return first extension found match, otherwise start search at
+ *       idx location and set idx to the location of extension returned.
+ * returns NULL or a pointer to an WOLFSSL_STACK holding extension structure
+ *
+ * NOTE code for decoding extensions is in asn.c DecodeCertExtensions --
+ * use already decoded extension in this function to avoid decoding twice.
+ * Currently we do not make use of idx since getting pre decoded extensions.
+ */
+void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509,
+                                                     int nid, int* c, int* idx)
+{
+    WOLFSSL_STACK* sk = NULL;
+    WOLFSSL_ASN1_OBJECT* obj = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i");
+
+    if (x509 == NULL) {
+        return NULL;
+    }
+
+    if (c != NULL) {
+        *c = -1; /* default to not found */
+    }
+
+    sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC(
+                sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1);
+    if (sk == NULL) {
+        return NULL;
+    }
+    XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)));
+
+    switch (nid) {
+        case BASIC_CA_OID:
+            if (x509->basicConstSet) {
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                if (c != NULL) {
+                    *c = x509->basicConstCrit;
+                }
+                obj->type = BASIC_CA_OID;
+                obj->grp  = oidCertExtType;
+            }
+            else {
+                WOLFSSL_MSG("No Basic Constraint set");
+            }
+            break;
+
+        case ALT_NAMES_OID:
+            {
+                DNS_entry* dns = NULL;
+
+                if (x509->subjAltNameSet && x509->altNames != NULL) {
+                    /* alt names are DNS_entry structs */
+                    if (c != NULL) {
+                        if (x509->altNames->next != NULL) {
+                            *c = -2; /* more then one found */
+                        }
+                        else {
+                            *c = x509->subjAltNameCrit;
+                        }
+                    }
+
+                    dns = x509->altNames;
+                    while (dns != NULL) {
+                        obj = wolfSSL_ASN1_OBJECT_new();
+                        if (obj == NULL) {
+                            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                            wolfSSL_sk_ASN1_OBJECT_free(sk);
+                            return NULL;
+                        }
+                        obj->type = dns->type;
+                        obj->grp  = oidCertExtType;
+                        obj->obj  = (byte*)dns->name;
+
+                        /* set app derefrenced pointers */
+                        obj->d.ia5_internal.data   = dns->name;
+                        obj->d.ia5_internal.length = (int)XSTRLEN(dns->name);
+                        dns = dns->next;
+                        /* last dns in list add at end of function */
+                        if (dns != NULL) {
+                            if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) !=
+                                                                  WOLFSSL_SUCCESS) {
+                            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                            wolfSSL_ASN1_OBJECT_free(obj);
+                            wolfSSL_sk_ASN1_OBJECT_free(sk);
+                            sk = NULL;
+                            }
+                        }
+                    }
+                }
+                else {
+                    WOLFSSL_MSG("No Alt Names set");
+                }
+            }
+            break;
+
+        case CRL_DIST_OID:
+            if (x509->CRLdistSet && x509->CRLInfo != NULL) {
+                if (c != NULL) {
+                    *c = x509->CRLdistCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = CRL_DIST_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->CRLInfo;
+                obj->objSz = x509->CRLInfoSz;
+            }
+            else {
+                WOLFSSL_MSG("No CRL dist set");
+            }
+            break;
+
+        case AUTH_INFO_OID:
+            if (x509->authInfoSet && x509->authInfo != NULL) {
+                if (c != NULL) {
+                    *c = x509->authInfoCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = AUTH_INFO_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->authInfo;
+                obj->objSz = x509->authInfoSz;
+            }
+            else {
+                WOLFSSL_MSG("No Auth Info set");
+            }
+            break;
+
+        case AUTH_KEY_OID:
+            if (x509->authKeyIdSet) {
+                if (c != NULL) {
+                    *c = x509->authKeyIdCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = AUTH_KEY_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->authKeyId;
+                obj->objSz = x509->authKeyIdSz;
+            }
+            else {
+                WOLFSSL_MSG("No Auth Key set");
+            }
+            break;
+
+        case SUBJ_KEY_OID:
+            if (x509->subjKeyIdSet) {
+                if (c != NULL) {
+                    *c = x509->subjKeyIdCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = SUBJ_KEY_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->subjKeyId;
+                obj->objSz = x509->subjKeyIdSz;
+            }
+            else {
+                WOLFSSL_MSG("No Subject Key set");
+            }
+            break;
+
+        case CERT_POLICY_OID:
+            #ifdef WOLFSSL_CERT_EXT
+            {
+                int i;
+
+                if (x509->certPoliciesNb > 0) {
+                    if (c != NULL) {
+                        if (x509->certPoliciesNb > 1) {
+                            *c = -2;
+                        }
+                        else {
+                            *c = 0;
+                        }
+                    }
+
+                    for (i = 0; i < x509->certPoliciesNb - 1; i++) {
+                        obj = wolfSSL_ASN1_OBJECT_new();
+                        if (obj == NULL) {
+                            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                            wolfSSL_sk_ASN1_OBJECT_free(sk);
+                            return NULL;
+                        }
+                        obj->type  = CERT_POLICY_OID;
+                        obj->grp   = oidCertExtType;
+                        obj->obj   = (byte*)(x509->certPolicies[i]);
+                        obj->objSz = MAX_CERTPOL_SZ;
+                        if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj)
+                                                               != WOLFSSL_SUCCESS) {
+                            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+                            wolfSSL_ASN1_OBJECT_free(obj);
+                            wolfSSL_sk_ASN1_OBJECT_free(sk);
+                            sk = NULL;
+                        }
+                    }
+                    obj = wolfSSL_ASN1_OBJECT_new();
+                    if (obj == NULL) {
+                        WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        return NULL;
+                    }
+                    obj->type  = CERT_POLICY_OID;
+                    obj->grp   = oidCertExtType;
+                    obj->obj   = (byte*)(x509->certPolicies[i]);
+                    obj->objSz = MAX_CERTPOL_SZ;
+                }
+                else {
+                    WOLFSSL_MSG("No Cert Policy set");
+                }
+            }
+            #else
+                #ifdef WOLFSSL_SEP
+                if (x509->certPolicySet) {
+                    if (c != NULL) {
+                        *c = x509->certPolicyCrit;
+                    }
+                    obj = wolfSSL_ASN1_OBJECT_new();
+                    if (obj == NULL) {
+                        WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                        wolfSSL_sk_ASN1_OBJECT_free(sk);
+                        return NULL;
+                    }
+                    obj->type  = CERT_POLICY_OID;
+                    obj->grp   = oidCertExtType;
+                }
+                else {
+                    WOLFSSL_MSG("No Cert Policy set");
+                }
+                #else
+                WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT");
+                #endif /* WOLFSSL_SEP */
+            #endif /* WOLFSSL_CERT_EXT */
+            break;
+
+        case KEY_USAGE_OID:
+            if (x509->keyUsageSet) {
+                if (c != NULL) {
+                    *c = x509->keyUsageCrit;
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = KEY_USAGE_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = (byte*)&(x509->keyUsage);
+                obj->objSz = sizeof(word16);
+            }
+            else {
+                WOLFSSL_MSG("No Key Usage set");
+            }
+            break;
+
+        case INHIBIT_ANY_OID:
+            WOLFSSL_MSG("INHIBIT ANY extension not supported");
+            break;
+
+        case EXT_KEY_USAGE_OID:
+            if (x509->extKeyUsageSrc != NULL) {
+                if (c != NULL) {
+                    if (x509->extKeyUsageCount > 1) {
+                        *c = -2;
+                    }
+                    else {
+                        *c = x509->extKeyUsageCrit;
+                    }
+                }
+                obj = wolfSSL_ASN1_OBJECT_new();
+                if (obj == NULL) {
+                    WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+                    wolfSSL_sk_ASN1_OBJECT_free(sk);
+                    return NULL;
+                }
+                obj->type  = EXT_KEY_USAGE_OID;
+                obj->grp   = oidCertExtType;
+                obj->obj   = x509->extKeyUsageSrc;
+                obj->objSz = x509->extKeyUsageSz;
+            }
+            else {
+                WOLFSSL_MSG("No Extended Key Usage set");
+            }
+            break;
+
+        case NAME_CONS_OID:
+            WOLFSSL_MSG("Name Constraint OID extension not supported");
+            break;
+
+        case PRIV_KEY_USAGE_PERIOD_OID:
+            WOLFSSL_MSG("Private Key Usage Period extension not supported");
+            break;
+
+        case SUBJECT_INFO_ACCESS:
+            WOLFSSL_MSG("Subject Info Access extension not supported");
+            break;
+
+        case POLICY_MAP_OID:
+            WOLFSSL_MSG("Policy Map extension not supported");
+            break;
+
+        case POLICY_CONST_OID:
+            WOLFSSL_MSG("Policy Constraint extension not supported");
+            break;
+
+        case ISSUE_ALT_NAMES_OID:
+            WOLFSSL_MSG("Issue Alt Names extension not supported");
+            break;
+
+        case TLS_FEATURE_OID:
+            WOLFSSL_MSG("TLS Feature extension not supported");
+            break;
+
+        default:
+            WOLFSSL_MSG("Unsupported/Unknown extension OID");
+    }
+
+    if (obj != NULL) {
+        if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Error pushing ASN1 object onto stack");
+            wolfSSL_ASN1_OBJECT_free(obj);
+            wolfSSL_sk_ASN1_OBJECT_free(sk);
+            sk = NULL;
+        }
+    }
+    else { /* no ASN1 object found for extension, free stack */
+        wolfSSL_sk_ASN1_OBJECT_free(sk);
+        sk = NULL;
+    }
+
+    (void)idx;
+
+    return sk;
+}
+
+
+/* this function makes the assumption that out buffer is big enough for digest*/
+static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out,
+                              unsigned int* outSz, const WOLFSSL_EVP_MD* evp,
+                              WOLFSSL_ENGINE* eng)
+{
+    int err;
+    int hashType = WC_HASH_TYPE_NONE;
+    int hashSz;
+
+    (void)eng;
+
+    err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz);
+    if (err != WOLFSSL_SUCCESS)
+        return err;
+
+    *outSz = hashSz;
+
+    if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, *outSz) != 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest,
+        unsigned char* buf, unsigned int* len)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_digest");
+
+    if (x509 == NULL || digest == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf,
+                              len, digest, NULL);
+}
+
+
+int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
+    if (ssl == NULL || pkey == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
+                                         pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der,
+                                long derSz)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
+    if (ssl == NULL || der == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    (void)pri; /* type of private key */
+    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+
+
+#ifndef NO_RSA
+int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
+{
+    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
+    if (ssl == NULL || der == NULL ) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
+}
+#endif
+
+int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz)
+{
+    long idx;
+
+    WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
+    if (der != NULL && ssl != NULL) {
+        if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl,
+                                                        &idx, 0) == WOLFSSL_SUCCESS)
+            return WOLFSSL_SUCCESS;
+    }
+
+    (void)idx;
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
+{
+    long idx;
+
+    WOLFSSL_ENTER("wolfSSL_use_certificate");
+    if (x509 != NULL && ssl != NULL && x509->derCert != NULL) {
+        if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
+                     WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == WOLFSSL_SUCCESS)
+            return WOLFSSL_SUCCESS;
+    }
+
+    (void)idx;
+    return WOLFSSL_FAILURE;
+}
+#endif /* NO_CERTS */
+
+#ifndef NO_FILESYSTEM
+
+int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_certificate_file");
+    if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
+                    ssl, 0, NULL) == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
+    if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
+                    ssl, 0, NULL) == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
+{
+   /* process up to MAX_CHAIN_DEPTH plus subject cert */
+   WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
+   if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
+                   ssl, 1, NULL) == WOLFSSL_SUCCESS)
+       return WOLFSSL_SUCCESS;
+
+   return WOLFSSL_FAILURE;
+}
+
+int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
+                                              int format)
+{
+   /* process up to MAX_CHAIN_DEPTH plus subject cert */
+   WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
+   if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
+                   NULL) == WOLFSSL_SUCCESS)
+       return WOLFSSL_SUCCESS;
+
+   return WOLFSSL_FAILURE;
+}
+
+
+#ifdef HAVE_ECC
+
+/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
+int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
+{
+    if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
+        return BAD_FUNC_ARG;
+
+    ctx->eccTempKeySz = sz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */
+int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
+{
+    if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE)
+        return BAD_FUNC_ARG;
+
+    ssl->eccTempKeySz = sz;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* HAVE_ECC */
+
+
+
+
+int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
+                                   int format)
+{
+    WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file");
+
+    return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
+}
+
+
+int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
+{
+    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
+
+    return wolfSSL_use_PrivateKey_file(ssl, file, format);
+}
+
+#endif /* NO_FILESYSTEM */
+
+/* Copies the master secret over to out buffer. If outSz is 0 returns the size
+ * of master secret.
+ *
+ * ses : a session from completed TLS/SSL handshake
+ * out : buffer to hold copy of master secret
+ * outSz : size of out buffer
+ * returns : number of bytes copied into out buffer on success
+ *           less then or equal to 0 is considered a failure case
+ */
+int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
+        unsigned char* out, int outSz)
+{
+    int size;
+
+    if (outSz == 0) {
+        return SECRET_LEN;
+    }
+
+    if (ses == NULL || out == NULL || outSz < 0) {
+        return 0;
+    }
+
+    if (outSz > SECRET_LEN) {
+        size = SECRET_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ses->masterSecret, size);
+    return size;
+}
+
+
+int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses)
+{
+    (void)ses;
+    return SECRET_LEN;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_FILESYSTEM
+#ifdef HAVE_NTRU
+
+int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file");
+    if (ctx == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL)
+                         == WOLFSSL_SUCCESS) {
+        ctx->haveNTRU = 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+#endif /* HAVE_NTRU */
+
+
+#endif /* NO_FILESYSTEM */
+
+
+void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
+    if (mode & WOLFSSL_VERIFY_PEER) {
+        ctx->verifyPeer = 1;
+        ctx->verifyNone = 0;  /* in case previously set */
+    }
+
+    if (mode == WOLFSSL_VERIFY_NONE) {
+        ctx->verifyNone = 1;
+        ctx->verifyPeer = 0;  /* in case previously set */
+    }
+
+    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+        ctx->failNoCert = 1;
+
+    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+        ctx->failNoCert    = 0; /* fail on all is set to fail on PSK */
+        ctx->failNoCertxPSK = 1;
+    }
+
+    ctx->verifyCallback = vc;
+}
+
+
+void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
+{
+    WOLFSSL_ENTER("wolfSSL_set_verify");
+    if (mode & WOLFSSL_VERIFY_PEER) {
+        ssl->options.verifyPeer = 1;
+        ssl->options.verifyNone = 0;  /* in case previously set */
+    }
+
+    if (mode == WOLFSSL_VERIFY_NONE) {
+        ssl->options.verifyNone = 1;
+        ssl->options.verifyPeer = 0;  /* in case previously set */
+    }
+
+    if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+        ssl->options.failNoCert = 1;
+
+    if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) {
+        ssl->options.failNoCert    = 0; /* fail on all is set to fail on PSK */
+        ssl->options.failNoCertxPSK = 1;
+    }
+
+    ssl->verifyCallback = vc;
+}
+
+
+/* store user ctx for verify callback */
+void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
+    if (ssl)
+        ssl->verifyCbCtx = ctx;
+}
+
+
+/* store context CA Cache addition callback */
+void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
+{
+    if (ctx && ctx->cm)
+        ctx->cm->caCacheCallback = cb;
+}
+
+
+#if defined(PERSIST_CERT_CACHE)
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist cert cache to file */
+int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_SaveCertCache(ctx->cm, fname);
+}
+
+
+/* Persist cert cache from file */
+int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
+
+    if (ctx == NULL || fname == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_RestoreCertCache(ctx->cm, fname);
+}
+
+#endif /* NO_FILESYSTEM */
+
+/* Persist cert cache to memory */
+int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
+                                   int sz, int* used)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
+
+    if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
+        return BAD_FUNC_ARG;
+
+    return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
+}
+
+
+/* Restore cert cache from memory */
+int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
+
+    if (ctx == NULL || mem == NULL || sz <= 0)
+        return BAD_FUNC_ARG;
+
+    return CM_MemRestoreCertCache(ctx->cm, mem, sz);
+}
+
+
+/* get how big the the cert cache save buffer needs to be */
+int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
+
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    return CM_GetCertCacheMemSize(ctx->cm);
+}
+
+#endif /* PERSIST_CERT_CACHE */
+#endif /* !NO_CERTS */
+
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_session");
+    if (ssl)
+        return GetSession(ssl, 0, 0);
+
+    return NULL;
+}
+
+
+int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+{
+    WOLFSSL_ENTER("SSL_set_session");
+    if (session)
+        return SetSession(ssl, session);
+
+    return WOLFSSL_FAILURE;
+}
+
+
+#ifndef NO_CLIENT_CACHE
+
+/* Associate client session with serverID, find existing or store for saving
+   if newSession flag on, don't reuse existing session
+   WOLFSSL_SUCCESS on ok */
+int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
+{
+    WOLFSSL_SESSION* session = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_SetServerID");
+
+    if (ssl == NULL || id == NULL || len <= 0)
+        return BAD_FUNC_ARG;
+
+    if (newSession == 0) {
+        session = GetSessionClient(ssl, id, len);
+        if (session) {
+            if (SetSession(ssl, session) != WOLFSSL_SUCCESS) {
+    #ifdef HAVE_EXT_CACHE
+                wolfSSL_SESSION_free(session);
+    #endif
+                WOLFSSL_MSG("SetSession failed");
+                session = NULL;
+            }
+        }
+    }
+
+    if (session == NULL) {
+        WOLFSSL_MSG("Valid ServerID not cached already");
+
+        ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len);
+        XMEMCPY(ssl->session.serverID, id, ssl->session.idLen);
+    }
+    #ifdef HAVE_EXT_CACHE
+    else
+        wolfSSL_SESSION_free(session);
+    #endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_CLIENT_CACHE */
+
+#if defined(PERSIST_SESSION_CACHE)
+
+/* for persistence, if changes to layout need to increment and modify
+   save_session_cache() and restore_session_cache and memory versions too */
+#define WOLFSSL_CACHE_VERSION 2
+
+/* Session Cache Header information */
+typedef struct {
+    int version;     /* cache layout version id */
+    int rows;        /* session rows */
+    int columns;     /* session columns */
+    int sessionSz;   /* sizeof WOLFSSL_SESSION */
+} cache_header_t;
+
+/* current persistence layout is:
+
+   1) cache_header_t
+   2) SessionCache
+   3) ClientCache
+
+   update WOLFSSL_CACHE_VERSION if change layout for the following
+   PERSISTENT_SESSION_CACHE functions
+*/
+
+
+/* get how big the the session cache save buffer needs to be */
+int wolfSSL_get_session_cache_memsize(void)
+{
+    int sz  = (int)(sizeof(SessionCache) + sizeof(cache_header_t));
+
+    #ifndef NO_CLIENT_CACHE
+        sz += (int)(sizeof(ClientCache));
+    #endif
+
+    return sz;
+}
+
+
+/* Persist session cache to memory */
+int wolfSSL_memsave_session_cache(void* mem, int sz)
+{
+    int i;
+    cache_header_t cache_header;
+    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
+#ifndef NO_CLIENT_CACHE
+    ClientRow*     clRow;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_memsave_session_cache");
+
+    if (sz < wolfSSL_get_session_cache_memsize()) {
+        WOLFSSL_MSG("Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    cache_header.version   = WOLFSSL_CACHE_VERSION;
+    cache_header.rows      = SESSION_ROWS;
+    cache_header.columns   = SESSIONS_PER_ROW;
+    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
+    XMEMCPY(mem, &cache_header, sizeof(cache_header));
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        return BAD_MUTEX_E;
+    }
+
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(row++, SessionCache + i, sizeof(SessionRow));
+
+#ifndef NO_CLIENT_CACHE
+    clRow = (ClientRow*)row;
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow));
+#endif
+
+    wc_UnLockMutex(&session_mutex);
+
+    WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Restore the persistent session cache from memory */
+int wolfSSL_memrestore_session_cache(const void* mem, int sz)
+{
+    int    i;
+    cache_header_t cache_header;
+    SessionRow*    row  = (SessionRow*)((byte*)mem + sizeof(cache_header));
+#ifndef NO_CLIENT_CACHE
+    ClientRow*     clRow;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_memrestore_session_cache");
+
+    if (sz < wolfSSL_get_session_cache_memsize()) {
+        WOLFSSL_MSG("Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    XMEMCPY(&cache_header, mem, sizeof(cache_header));
+    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
+        cache_header.rows      != SESSION_ROWS ||
+        cache_header.columns   != SESSIONS_PER_ROW ||
+        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
+
+        WOLFSSL_MSG("Session cache header match failed");
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        return BAD_MUTEX_E;
+    }
+
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(SessionCache + i, row++, sizeof(SessionRow));
+
+#ifndef NO_CLIENT_CACHE
+    clRow = (ClientRow*)row;
+    for (i = 0; i < cache_header.rows; ++i)
+        XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow));
+#endif
+
+    wc_UnLockMutex(&session_mutex);
+
+    WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
+
+    return WOLFSSL_SUCCESS;
+}
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist session cache to file */
+/* doesn't use memsave because of additional memory use */
+int wolfSSL_save_session_cache(const char *fname)
+{
+    XFILE  file;
+    int    ret;
+    int    rc = WOLFSSL_SUCCESS;
+    int    i;
+    cache_header_t cache_header;
+
+    WOLFSSL_ENTER("wolfSSL_save_session_cache");
+
+    file = XFOPEN(fname, "w+b");
+    if (file == XBADFILE) {
+        WOLFSSL_MSG("Couldn't open session cache save file");
+        return WOLFSSL_BAD_FILE;
+    }
+    cache_header.version   = WOLFSSL_CACHE_VERSION;
+    cache_header.rows      = SESSION_ROWS;
+    cache_header.columns   = SESSIONS_PER_ROW;
+    cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
+
+    /* cache header */
+    ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Session cache header file write failed");
+        XFCLOSE(file);
+        return FWRITE_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    /* session cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFWRITE(SessionCache + i, sizeof(SessionRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Session cache member file write failed");
+            rc = FWRITE_ERROR;
+            break;
+        }
+    }
+
+#ifndef NO_CLIENT_CACHE
+    /* client cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Client cache member file write failed");
+            rc = FWRITE_ERROR;
+            break;
+        }
+    }
+#endif /* NO_CLIENT_CACHE */
+
+    wc_UnLockMutex(&session_mutex);
+
+    XFCLOSE(file);
+    WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
+
+    return rc;
+}
+
+
+/* Restore the persistent session cache from file */
+/* doesn't use memstore because of additional memory use */
+int wolfSSL_restore_session_cache(const char *fname)
+{
+    XFILE  file;
+    int    rc = WOLFSSL_SUCCESS;
+    int    ret;
+    int    i;
+    cache_header_t cache_header;
+
+    WOLFSSL_ENTER("wolfSSL_restore_session_cache");
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) {
+        WOLFSSL_MSG("Couldn't open session cache save file");
+        return WOLFSSL_BAD_FILE;
+    }
+    /* cache header */
+    ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Session cache header file read failed");
+        XFCLOSE(file);
+        return FREAD_ERROR;
+    }
+    if (cache_header.version   != WOLFSSL_CACHE_VERSION ||
+        cache_header.rows      != SESSION_ROWS ||
+        cache_header.columns   != SESSIONS_PER_ROW ||
+        cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
+
+        WOLFSSL_MSG("Session cache header match failed");
+        XFCLOSE(file);
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Session cache mutex lock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    /* session cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFREAD(SessionCache + i, sizeof(SessionRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Session cache member file read failed");
+            XMEMSET(SessionCache, 0, sizeof SessionCache);
+            rc = FREAD_ERROR;
+            break;
+        }
+    }
+
+#ifndef NO_CLIENT_CACHE
+    /* client cache */
+    for (i = 0; i < cache_header.rows; ++i) {
+        ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file);
+        if (ret != 1) {
+            WOLFSSL_MSG("Client cache member file read failed");
+            XMEMSET(ClientCache, 0, sizeof ClientCache);
+            rc = FREAD_ERROR;
+            break;
+        }
+    }
+
+#endif /* NO_CLIENT_CACHE */
+
+    wc_UnLockMutex(&session_mutex);
+
+    XFCLOSE(file);
+    WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
+
+    return rc;
+}
+
+#endif /* !NO_FILESYSTEM */
+#endif /* PERSIST_SESSION_CACHE */
+#endif /* NO_SESSION_CACHE */
+
+
+void wolfSSL_load_error_strings(void)   /* compatibility only */
+{}
+
+
+int wolfSSL_library_init(void)
+{
+    WOLFSSL_ENTER("SSL_library_init");
+    if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FATAL_ERROR;
+}
+
+
+#ifdef HAVE_SECRET_CALLBACK
+
+int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_set_session_secret_cb");
+    if (ssl == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    ssl->sessionSecretCb = cb;
+    ssl->sessionSecretCtx = ctx;
+    /* If using a pre-set key, assume session resumption. */
+    ssl->session.sessionIDSz = 0;
+    ssl->options.resuming = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif
+
+
+#ifndef NO_SESSION_CACHE
+
+/* on by default if built in but allow user to turn off */
+long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
+{
+    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
+    if (mode == WOLFSSL_SESS_CACHE_OFF)
+        ctx->sessionCacheOff = 1;
+
+    if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
+        ctx->sessionCacheFlushOff = 1;
+
+#ifdef HAVE_EXT_CACHE
+    if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0)
+        ctx->internalCacheOff = 1;
+#endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+#if !defined(NO_CERTS)
+#if defined(PERSIST_CERT_CACHE)
+
+
+#define WOLFSSL_CACHE_CERT_VERSION 1
+
+typedef struct {
+    int version;                 /* cache cert layout version id */
+    int rows;                    /* hash table rows, CA_TABLE_SIZE */
+    int columns[CA_TABLE_SIZE];  /* columns per row on list */
+    int signerSz;                /* sizeof Signer object */
+} CertCacheHeader;
+
+/* current cert persistence layout is:
+
+   1) CertCacheHeader
+   2) caTable
+
+   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
+   PERSIST_CERT_CACHE functions
+*/
+
+
+/* Return memory needed to persist this signer, have lock */
+static WC_INLINE int GetSignerMemory(Signer* signer)
+{
+    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
+           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
+
+#if !defined(NO_SKID)
+        sz += (int)sizeof(signer->subjectKeyIdHash);
+#endif
+
+    /* add dynamic bytes needed */
+    sz += signer->pubKeySize;
+    sz += signer->nameLen;
+
+    return sz;
+}
+
+
+/* Return memory needed to persist this row, have lock */
+static WC_INLINE int GetCertCacheRowMemory(Signer* row)
+{
+    int sz = 0;
+
+    while (row) {
+        sz += GetSignerMemory(row);
+        row = row->next;
+    }
+
+    return sz;
+}
+
+
+/* get the size of persist cert cache, have lock */
+static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+{
+    int sz;
+    int i;
+
+    sz = sizeof(CertCacheHeader);
+
+    for (i = 0; i < CA_TABLE_SIZE; i++)
+        sz += GetCertCacheRowMemory(cm->caTable[i]);
+
+    return sz;
+}
+
+
+/* Store cert cache header columns with number of items per list, have lock */
+static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns)
+{
+    int     i;
+    Signer* row;
+
+    for (i = 0; i < CA_TABLE_SIZE; i++) {
+        int count = 0;
+        row = cm->caTable[i];
+
+        while (row) {
+            ++count;
+            row = row->next;
+        }
+        columns[i] = count;
+    }
+}
+
+
+/* Restore whole cert row from memory, have lock, return bytes consumed,
+   < 0 on error, have lock */
+static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current,
+                                 int row, int listSz, const byte* end)
+{
+    int idx = 0;
+
+    if (listSz < 0) {
+        WOLFSSL_MSG("Row header corrupted, negative value");
+        return PARSE_ERROR;
+    }
+
+    while (listSz) {
+        Signer* signer;
+        byte*   start = current + idx;  /* for end checks on this signer */
+        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
+                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
+        #ifndef NO_SKID
+                minSz += (int)sizeof(signer->subjectKeyIdHash);
+        #endif
+
+        if (start + minSz > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            return BUFFER_E;
+        }
+        signer = MakeSigner(cm->heap);
+        if (signer == NULL)
+            return MEMORY_E;
+
+        /* pubKeySize */
+        XMEMCPY(&signer->pubKeySize, current + idx, sizeof(signer->pubKeySize));
+        idx += (int)sizeof(signer->pubKeySize);
+
+        /* keyOID */
+        XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
+        idx += (int)sizeof(signer->keyOID);
+
+        /* pulicKey */
+        if (start + minSz + signer->pubKeySize > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            FreeSigner(signer, cm->heap);
+            return BUFFER_E;
+        }
+        signer->publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
+                                           DYNAMIC_TYPE_KEY);
+        if (signer->publicKey == NULL) {
+            FreeSigner(signer, cm->heap);
+            return MEMORY_E;
+        }
+
+        XMEMCPY(signer->publicKey, current + idx, signer->pubKeySize);
+        idx += signer->pubKeySize;
+
+        /* nameLen */
+        XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
+        idx += (int)sizeof(signer->nameLen);
+
+        /* name */
+        if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
+            WOLFSSL_MSG("Would overread restore buffer");
+            FreeSigner(signer, cm->heap);
+            return BUFFER_E;
+        }
+        signer->name = (char*)XMALLOC(signer->nameLen, cm->heap,
+                                      DYNAMIC_TYPE_SUBJECT_CN);
+        if (signer->name == NULL) {
+            FreeSigner(signer, cm->heap);
+            return MEMORY_E;
+        }
+
+        XMEMCPY(signer->name, current + idx, signer->nameLen);
+        idx += signer->nameLen;
+
+        /* subjectNameHash */
+        XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
+        idx += SIGNER_DIGEST_SIZE;
+
+        #ifndef NO_SKID
+            /* subjectKeyIdHash */
+            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
+            idx += SIGNER_DIGEST_SIZE;
+        #endif
+
+        signer->next = cm->caTable[row];
+        cm->caTable[row] = signer;
+
+        --listSz;
+    }
+
+    return idx;
+}
+
+
+/* Store whole cert row into memory, have lock, return bytes added */
+static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row)
+{
+    int     added  = 0;
+    Signer* list   = cm->caTable[row];
+
+    while (list) {
+        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
+        added += (int)sizeof(list->pubKeySize);
+
+        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
+        added += (int)sizeof(list->keyOID);
+
+        XMEMCPY(current + added, list->publicKey, list->pubKeySize);
+        added += list->pubKeySize;
+
+        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
+        added += (int)sizeof(list->nameLen);
+
+        XMEMCPY(current + added, list->name, list->nameLen);
+        added += list->nameLen;
+
+        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
+        added += SIGNER_DIGEST_SIZE;
+
+        #ifndef NO_SKID
+            XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
+            added += SIGNER_DIGEST_SIZE;
+        #endif
+
+        list = list->next;
+    }
+
+    return added;
+}
+
+
+/* Persist cert cache to memory, have lock */
+static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm,
+                                     void* mem, int sz)
+{
+    int realSz;
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+
+    WOLFSSL_ENTER("DoMemSaveCertCache");
+
+    realSz = GetCertCacheMemSize(cm);
+    if (realSz > sz) {
+        WOLFSSL_MSG("Mem output buffer too small");
+        ret = BUFFER_E;
+    }
+    else {
+        byte*           current;
+        CertCacheHeader hdr;
+
+        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
+        hdr.rows     = CA_TABLE_SIZE;
+        SetCertHeaderColumns(cm, hdr.columns);
+        hdr.signerSz = (int)sizeof(Signer);
+
+        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
+        current = (byte*)mem + sizeof(CertCacheHeader);
+
+        for (i = 0; i < CA_TABLE_SIZE; ++i)
+            current += StoreCertRow(cm, current, i);
+    }
+
+    return ret;
+}
+
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist cert cache to file */
+int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   rc = WOLFSSL_SUCCESS;
+    int   memSz;
+    byte* mem;
+
+    WOLFSSL_ENTER("CM_SaveCertCache");
+
+    file = XFOPEN(fname, "w+b");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       return WOLFSSL_BAD_FILE;
+    }
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        XFCLOSE(file);
+        return BAD_MUTEX_E;
+    }
+
+    memSz = GetCertCacheMemSize(cm);
+    mem   = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Alloc for tmp buffer failed");
+        rc = MEMORY_E;
+    } else {
+        rc = DoMemSaveCertCache(cm, mem, memSz);
+        if (rc == WOLFSSL_SUCCESS) {
+            int ret = (int)XFWRITE(mem, memSz, 1, file);
+            if (ret != 1) {
+                WOLFSSL_MSG("Cert cache file write failed");
+                rc = FWRITE_ERROR;
+            }
+        }
+        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+
+    wc_UnLockMutex(&cm->caLock);
+    XFCLOSE(file);
+
+    return rc;
+}
+
+
+/* Restore cert cache from file */
+int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
+{
+    XFILE file;
+    int   rc = WOLFSSL_SUCCESS;
+    int   ret;
+    int   memSz;
+    byte* mem;
+
+    WOLFSSL_ENTER("CM_RestoreCertCache");
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE) {
+       WOLFSSL_MSG("Couldn't open cert cache save file");
+       return WOLFSSL_BAD_FILE;
+    }
+
+    XFSEEK(file, 0, XSEEK_END);
+    memSz = (int)XFTELL(file);
+    XREWIND(file);
+
+    if (memSz <= 0) {
+        WOLFSSL_MSG("Bad file size");
+        XFCLOSE(file);
+        return WOLFSSL_BAD_FILE;
+    }
+
+    mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Alloc for tmp buffer failed");
+        XFCLOSE(file);
+        return MEMORY_E;
+    }
+
+    ret = (int)XFREAD(mem, memSz, 1, file);
+    if (ret != 1) {
+        WOLFSSL_MSG("Cert file read error");
+        rc = FREAD_ERROR;
+    } else {
+        rc = CM_MemRestoreCertCache(cm, mem, memSz);
+        if (rc != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("Mem restore cert cache failed");
+        }
+    }
+
+    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    XFCLOSE(file);
+
+    return rc;
+}
+
+#endif /* NO_FILESYSTEM */
+
+
+/* Persist cert cache to memory */
+int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("CM_MemSaveCertCache");
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    ret = DoMemSaveCertCache(cm, mem, sz);
+    if (ret == WOLFSSL_SUCCESS)
+        *used  = GetCertCacheMemSize(cm);
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+/* Restore cert cache from memory */
+int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int i;
+    CertCacheHeader* hdr = (CertCacheHeader*)mem;
+    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
+    byte*            end     = (byte*)mem + sz;  /* don't go over */
+
+    WOLFSSL_ENTER("CM_MemRestoreCertCache");
+
+    if (current > end) {
+        WOLFSSL_MSG("Cert Cache Memory buffer too small");
+        return BUFFER_E;
+    }
+
+    if (hdr->version  != WOLFSSL_CACHE_CERT_VERSION ||
+        hdr->rows     != CA_TABLE_SIZE ||
+        hdr->signerSz != (int)sizeof(Signer)) {
+
+        WOLFSSL_MSG("Cert Cache Memory header mismatch");
+        return CACHE_MATCH_ERROR;
+    }
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+
+    for (i = 0; i < CA_TABLE_SIZE; ++i) {
+        int added = RestoreCertRow(cm, current, i, hdr->columns[i], end);
+        if (added < 0) {
+            WOLFSSL_MSG("RestoreCertRow error");
+            ret = added;
+            break;
+        }
+        current += added;
+    }
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return ret;
+}
+
+
+/* get how big the the cert cache save buffer needs to be */
+int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
+{
+    int sz;
+
+    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
+
+    if (wc_LockMutex(&cm->caLock) != 0) {
+        WOLFSSL_MSG("wc_LockMutex on caLock failed");
+        return BAD_MUTEX_E;
+    }
+
+    sz = GetCertCacheMemSize(cm);
+
+    wc_UnLockMutex(&cm->caLock);
+
+    return sz;
+}
+
+#endif /* PERSIST_CERT_CACHE */
+#endif /* NO_CERTS */
+
+
+int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
+
+    /* alloc/init on demand only */
+    if (ctx->suites == NULL) {
+        ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap,
+                                       DYNAMIC_TYPE_SUITES);
+        if (ctx->suites == NULL) {
+            WOLFSSL_MSG("Memory alloc for Suites failed");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(ctx->suites, 0, sizeof(Suites));
+    }
+
+    return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
+{
+    WOLFSSL_ENTER("wolfSSL_set_cipher_list");
+    return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
+{
+    int useNb = 0;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
+    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+        useNb = ssl->options.dtlsUseNonblock;
+#endif
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
+                    "DEPRECATED for non-DTLS use.");
+    }
+    return useNb;
+}
+
+
+#ifndef WOLFSSL_LEANPSK
+
+void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
+{
+    (void)nonblock;
+
+    WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
+    if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+        ssl->options.dtlsUseNonblock = (nonblock != 0);
+#endif
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
+                    "DEPRECATED for non-DTLS use.");
+    }
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
+{
+    return ssl->dtls_timeout;
+}
+
+
+/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
+{
+    if (ssl == NULL || timeout < 0)
+        return BAD_FUNC_ARG;
+
+    if (timeout > ssl->dtls_timeout_max) {
+        WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_timeout_init = timeout;
+    ssl->dtls_timeout = timeout;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
+{
+    if (ssl == NULL || timeout < 0)
+        return BAD_FUNC_ARG;
+
+    if (timeout < ssl->dtls_timeout_init) {
+        WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
+        return BAD_FUNC_ARG;
+    }
+
+    ssl->dtls_timeout_max = timeout;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
+{
+    int result = WOLFSSL_SUCCESS;
+
+    if (!ssl->options.handShakeDone &&
+        (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) {
+
+        result = WOLFSSL_FATAL_ERROR;
+    }
+    return result;
+}
+
+#endif /* DTLS */
+#endif /* LEANPSK */
+
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+
+/* Not an SSL function, return 0 for success, error code otherwise */
+/* Prereq: ssl's RNG needs to be initialized. */
+int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
+                                 const byte* secret, word32 secretSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("need a SSL object");
+        return BAD_FUNC_ARG;
+    }
+
+    if (secret != NULL && secretSz == 0) {
+        WOLFSSL_MSG("can't have a new secret without a size");
+        return BAD_FUNC_ARG;
+    }
+
+    /* If secretSz is 0, use the default size. */
+    if (secretSz == 0)
+        secretSz = COOKIE_SECRET_SZ;
+
+    if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
+        byte* newSecret;
+
+        if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
+            ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
+                      ssl->buffers.dtlsCookieSecret.length);
+            XFREE(ssl->buffers.dtlsCookieSecret.buffer,
+                  ssl->heap, DYNAMIC_TYPE_NONE);
+        }
+
+        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
+        if (newSecret == NULL) {
+            ssl->buffers.dtlsCookieSecret.buffer = NULL;
+            ssl->buffers.dtlsCookieSecret.length = 0;
+            WOLFSSL_MSG("couldn't allocate new cookie secret");
+            return MEMORY_ERROR;
+        }
+        ssl->buffers.dtlsCookieSecret.buffer = newSecret;
+        ssl->buffers.dtlsCookieSecret.length = secretSz;
+    }
+
+    /* If the supplied secret is NULL, randomly generate a new secret. */
+    if (secret == NULL) {
+        ret = wc_RNG_GenerateBlock(ssl->rng,
+                             ssl->buffers.dtlsCookieSecret.buffer, secretSz);
+    }
+    else
+        XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
+
+    WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
+    return ret;
+}
+
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_METHOD* wolfSSLv23_method(void) {
+        WOLFSSL_METHOD* m = NULL;
+        WOLFSSL_ENTER("wolfSSLv23_method");
+#if !defined(NO_WOLFSSL_CLIENT)
+        m = wolfSSLv23_client_method();
+#elif !defined(NO_WOLFSSL_SERVER)
+        m = wolfSSLv23_server_method();
+#endif
+        if (m != NULL) {
+            m->side = WOLFSSL_NEITHER_END;
+        }
+
+        return m;
+    }
+#endif /* OPENSSL_EXTRA */
+
+/* client only parts */
+#ifndef NO_WOLFSSL_CLIENT
+
+    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+    WOLFSSL_METHOD* wolfSSLv3_client_method(void)
+    {
+        WOLFSSL_ENTER("SSLv3_client_method");
+        return wolfSSLv3_client_method_ex(NULL);
+    }
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+
+        #ifndef NO_OLD_TLS
+        WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
+        {
+            WOLFSSL_ENTER("DTLSv1_client_method");
+            return wolfDTLSv1_client_method_ex(NULL);
+        }
+        #endif  /* NO_OLD_TLS */
+
+        WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
+        {
+            WOLFSSL_ENTER("DTLSv1_2_client_method");
+            return wolfDTLSv1_2_client_method_ex(NULL);
+        }
+    #endif
+
+    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+    WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        WOLFSSL_ENTER("SSLv3_client_method_ex");
+        if (method)
+            InitSSL_Method(method, MakeSSLv3());
+        return method;
+    }
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+
+        #ifndef NO_OLD_TLS
+        WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap)
+        {
+            WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+            WOLFSSL_ENTER("DTLSv1_client_method_ex");
+            if (method)
+                InitSSL_Method(method, MakeDTLSv1());
+            return method;
+        }
+        #endif  /* NO_OLD_TLS */
+
+        WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap)
+        {
+            WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+            WOLFSSL_ENTER("DTLSv1_2_client_method_ex");
+            if (method)
+                InitSSL_Method(method, MakeDTLSv1_2());
+            (void)heap;
+            return method;
+        }
+    #endif
+
+    /* If SCTP is not enabled returns the state of the dtls option.
+     * If SCTP is enabled returns dtls && !sctp. */
+    static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl)
+    {
+        int result = ssl->options.dtls;
+
+        if (result) {
+        #ifdef WOLFSSL_SCTP
+            result = !ssl->options.dtlsSctp;
+        #endif
+        }
+
+        return result;
+    }
+
+
+    /* please see note at top of README if you get an error from connect */
+    int wolfSSL_connect(WOLFSSL* ssl)
+    {
+    #ifndef WOLFSSL_NO_TLS12
+        int neededState;
+    #endif
+
+        WOLFSSL_ENTER("SSL_connect()");
+
+        #ifdef HAVE_ERRNO_H
+            errno = 0;
+        #endif
+
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        #ifdef OPENSSL_EXTRA
+            if (ssl->CBIS != NULL) {
+                ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS);
+                ssl->cbmode = SSL_CB_WRITE;
+            }
+        #endif
+        if (ssl->options.side != WOLFSSL_CLIENT_END) {
+            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifdef WOLFSSL_NO_TLS12
+        return wolfSSL_connect_TLSv13(ssl);
+    #else
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3)
+                return wolfSSL_connect_TLSv13(ssl);
+        #endif
+
+        #ifdef WOLFSSL_DTLS
+            if (ssl->version.major == DTLS_MAJOR) {
+                ssl->options.dtls   = 1;
+                ssl->options.tls    = 1;
+                ssl->options.tls1_1 = 1;
+            }
+        #endif
+
+        if (ssl->buffers.outputBuffer.length > 0) {
+            if ( (ssl->error = SendBuffered(ssl)) == 0) {
+                /* fragOffset is non-zero when sending fragments. On the last
+                 * fragment, fragOffset is zero again, and the state can be
+                 * advanced. */
+                if (ssl->fragOffset == 0) {
+                    ssl->options.connectState++;
+                    WOLFSSL_MSG("connect state: "
+                                "Advanced from last buffered fragment send");
+                }
+                else {
+                    WOLFSSL_MSG("connect state: "
+                                "Not advanced, more fragments to send");
+                }
+            }
+            else {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+
+#ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3)
+            return wolfSSL_connect_TLSv13(ssl);
+#endif
+
+        switch (ssl->options.connectState) {
+
+        case CONNECT_BEGIN :
+            /* always send client hello first */
+            if ( (ssl->error = SendClientHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.connectState = CLIENT_HELLO_SENT;
+            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
+            FALL_THROUGH;
+
+        case CLIENT_HELLO_SENT :
+            neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
+                                          SERVER_HELLODONE_COMPLETE;
+            #ifdef WOLFSSL_DTLS
+                /* In DTLS, when resuming, we can go straight to FINISHED,
+                 * or do a cookie exchange and then skip to FINISHED, assume
+                 * we need the cookie exchange first. */
+                if (IsDtlsNotSctpMode(ssl))
+                    neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+            #endif
+            /* get response */
+            while (ssl->options.serverState < neededState) {
+                #ifdef WOLFSSL_TLS13
+                    if (ssl->options.tls1_3)
+                        return wolfSSL_connect_TLSv13(ssl);
+                #endif
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                /* if resumption failed, reset needed state */
+                else if (neededState == SERVER_FINISHED_COMPLETE)
+                    if (!ssl->options.resuming) {
+                        if (!IsDtlsNotSctpMode(ssl))
+                            neededState = SERVER_HELLODONE_COMPLETE;
+                        else
+                            neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+                    }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN :
+            if (ssl->options.certOnly)
+                return WOLFSSL_SUCCESS;
+
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3)
+                return wolfSSL_connect_TLSv13(ssl);
+        #endif
+
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    /* re-init hashes, exclude first hello and verify request */
+                    if ((ssl->error = InitHandshakeHashes(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    if ( (ssl->error = SendClientHello(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            #endif
+
+            ssl->options.connectState = HELLO_AGAIN_REPLY;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN_REPLY :
+            #ifdef WOLFSSL_DTLS
+                if (IsDtlsNotSctpMode(ssl)) {
+                    neededState = ssl->options.resuming ?
+                           SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
+
+                    /* get response */
+                    while (ssl->options.serverState < neededState) {
+                        if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                            WOLFSSL_ERROR(ssl->error);
+                            return WOLFSSL_FATAL_ERROR;
+                        }
+                        /* if resumption failed, reset needed state */
+                        if (neededState == SERVER_FINISHED_COMPLETE) {
+                            if (!ssl->options.resuming)
+                                neededState = SERVER_HELLODONE_COMPLETE;
+                        }
+                    }
+                }
+            #endif
+
+            ssl->options.connectState = FIRST_REPLY_DONE;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_DONE :
+            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+                #ifdef WOLFSSL_TLS13
+                    if (ssl->options.tls1_3)
+                        return wolfSSL_connect_TLSv13(ssl);
+                #endif
+                if (ssl->options.sendVerify) {
+                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    WOLFSSL_MSG("sent: certificate");
+                }
+
+            #endif
+            ssl->options.connectState = FIRST_REPLY_FIRST;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FIRST :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3)
+                return wolfSSL_connect_TLSv13(ssl);
+        #endif
+            if (!ssl->options.resuming) {
+                if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: client key exchange");
+            }
+
+            ssl->options.connectState = FIRST_REPLY_SECOND;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_SECOND :
+            #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+                if (ssl->options.sendVerify) {
+                    if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    WOLFSSL_MSG("sent: certificate verify");
+                }
+            #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
+            ssl->options.connectState = FIRST_REPLY_THIRD;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_THIRD :
+            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: change cipher spec");
+            ssl->options.connectState = FIRST_REPLY_FOURTH;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FOURTH :
+            if ( (ssl->error = SendFinished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: finished");
+            ssl->options.connectState = FINISHED_DONE;
+            WOLFSSL_MSG("connect state: FINISHED_DONE");
+            FALL_THROUGH;
+
+        case FINISHED_DONE :
+            /* get response */
+            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+
+            ssl->options.connectState = SECOND_REPLY_DONE;
+            WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case SECOND_REPLY_DONE:
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.dtls) {
+                if (!ssl->options.keepResources) {
+                    FreeHandshakeResources(ssl);
+                }
+            }
+#ifdef WOLFSSL_DTLS
+            else {
+                ssl->options.dtlsHsRetain = 1;
+            }
+#endif /* WOLFSSL_DTLS */
+
+            WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default:
+            WOLFSSL_MSG("Unknown connect state ERROR");
+            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+        }
+    #endif /* !WOLFSSL_NO_TLS12 */
+    }
+
+#endif /* NO_WOLFSSL_CLIENT */
+
+
+/* server only parts */
+#ifndef NO_WOLFSSL_SERVER
+
+    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+    WOLFSSL_METHOD* wolfSSLv3_server_method(void)
+    {
+        WOLFSSL_ENTER("SSLv3_server_method");
+        return wolfSSLv3_server_method_ex(NULL);
+    }
+    #endif
+
+
+    #ifdef WOLFSSL_DTLS
+
+        #ifndef NO_OLD_TLS
+        WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
+        {
+            WOLFSSL_ENTER("DTLSv1_server_method");
+            return wolfDTLSv1_server_method_ex(NULL);
+        }
+        #endif /* NO_OLD_TLS */
+
+        WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
+        {
+            WOLFSSL_ENTER("DTLSv1_2_server_method");
+            return wolfDTLSv1_2_server_method_ex(NULL);
+        }
+    #endif
+
+    #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+    WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
+    {
+        WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+        WOLFSSL_ENTER("SSLv3_server_method_ex");
+        if (method) {
+            InitSSL_Method(method, MakeSSLv3());
+            method->side = WOLFSSL_SERVER_END;
+        }
+        return method;
+    }
+    #endif
+
+
+    #ifdef WOLFSSL_DTLS
+
+        #ifndef NO_OLD_TLS
+        WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap)
+        {
+            WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+            WOLFSSL_ENTER("DTLSv1_server_method_ex");
+            if (method) {
+                InitSSL_Method(method, MakeDTLSv1());
+                method->side = WOLFSSL_SERVER_END;
+            }
+            return method;
+        }
+        #endif /* NO_OLD_TLS */
+
+        WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap)
+        {
+            WOLFSSL_METHOD* method =
+                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+                                                     heap, DYNAMIC_TYPE_METHOD);
+            WOLFSSL_ENTER("DTLSv1_2_server_method_ex");
+            if (method) {
+                InitSSL_Method(method, MakeDTLSv1_2());
+                method->side = WOLFSSL_SERVER_END;
+            }
+            (void)heap;
+            return method;
+        }
+    #endif
+
+
+    int wolfSSL_accept(WOLFSSL* ssl)
+    {
+#ifndef WOLFSSL_NO_TLS12
+        word16 havePSK = 0;
+        word16 haveAnon = 0;
+        word16 haveMcast = 0;
+#endif
+
+#ifdef WOLFSSL_NO_TLS12
+        return wolfSSL_accept_TLSv13(ssl);
+#else
+    #ifdef WOLFSSL_TLS13
+        if (ssl->options.tls1_3)
+            return wolfSSL_accept_TLSv13(ssl);
+    #endif
+        WOLFSSL_ENTER("SSL_accept()");
+
+        #ifdef HAVE_ERRNO_H
+            errno = 0;
+        #endif
+
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+        (void)havePSK;
+
+        #ifdef HAVE_ANON
+            haveAnon = ssl->options.haveAnon;
+        #endif
+        (void)haveAnon;
+
+        #ifdef WOLFSSL_MULTICAST
+            haveMcast = ssl->options.haveMcast;
+        #endif
+        (void)haveMcast;
+
+        if (ssl->options.side != WOLFSSL_SERVER_END) {
+            WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifndef NO_CERTS
+        /* in case used set_accept_state after init */
+        /* allow no private key if using PK callbacks and CB is set */
+        if (!havePSK && !haveAnon && !haveMcast) {
+            if (!ssl->buffers.certificate ||
+                !ssl->buffers.certificate->buffer) {
+
+                WOLFSSL_MSG("accept error: server cert required");
+                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+        #ifdef HAVE_PK_CALLBACKS
+            if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+                WOLFSSL_MSG("Using PK for server private key");
+            }
+            else
+        #endif
+            if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+                WOLFSSL_MSG("accept error: server key required");
+                WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+    #endif
+
+    #ifdef WOLFSSL_DTLS
+        if (ssl->version.major == DTLS_MAJOR) {
+            ssl->options.dtls   = 1;
+            ssl->options.tls    = 1;
+            ssl->options.tls1_1 = 1;
+        }
+    #endif
+
+        if (ssl->buffers.outputBuffer.length > 0) {
+            if ( (ssl->error = SendBuffered(ssl)) == 0) {
+                /* fragOffset is non-zero when sending fragments. On the last
+                 * fragment, fragOffset is zero again, and the state can be
+                 * advanced. */
+                if (ssl->fragOffset == 0) {
+                    ssl->options.acceptState++;
+                    WOLFSSL_MSG("accept state: "
+                                "Advanced from last buffered fragment send");
+                }
+                else {
+                    WOLFSSL_MSG("accept state: "
+                                "Not advanced, more fragments to send");
+                }
+            }
+            else {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+
+        switch (ssl->options.acceptState) {
+
+        case ACCEPT_BEGIN :
+            /* get response */
+            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+#ifdef WOLFSSL_TLS13
+            ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_CLIENT_HELLO_DONE :
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+#endif
+            ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_FIRST_REPLY_DONE :
+            if ( (ssl->error = SendServerHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = SERVER_HELLO_SENT;
+            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
+            FALL_THROUGH;
+
+        case SERVER_HELLO_SENT :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+        #endif
+            #ifndef NO_CERTS
+                if (!ssl->options.resuming)
+                    if ( (ssl->error = SendCertificate(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+            #endif
+            ssl->options.acceptState = CERT_SENT;
+            WOLFSSL_MSG("accept state CERT_SENT");
+            FALL_THROUGH;
+
+        case CERT_SENT :
+            #ifndef NO_CERTS
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            #endif
+            ssl->options.acceptState = CERT_STATUS_SENT;
+            WOLFSSL_MSG("accept state CERT_STATUS_SENT");
+            FALL_THROUGH;
+
+        case CERT_STATUS_SENT :
+        #ifdef WOLFSSL_TLS13
+            if (ssl->options.tls1_3) {
+                return wolfSSL_accept_TLSv13(ssl);
+            }
+        #endif
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            ssl->options.acceptState = KEY_EXCHANGE_SENT;
+            WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT");
+            FALL_THROUGH;
+
+        case KEY_EXCHANGE_SENT :
+            #ifndef NO_CERTS
+                if (!ssl->options.resuming) {
+                    if (ssl->options.verifyPeer) {
+                        if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
+                            WOLFSSL_ERROR(ssl->error);
+                            return WOLFSSL_FATAL_ERROR;
+                        }
+                    }
+                }
+            #endif
+            ssl->options.acceptState = CERT_REQ_SENT;
+            WOLFSSL_MSG("accept state CERT_REQ_SENT");
+            FALL_THROUGH;
+
+        case CERT_REQ_SENT :
+            if (!ssl->options.resuming)
+                if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            ssl->options.acceptState = SERVER_HELLO_DONE;
+            WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
+            FALL_THROUGH;
+
+        case SERVER_HELLO_DONE :
+            if (!ssl->options.resuming) {
+                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+            }
+            ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
+            WOLFSSL_MSG("accept state  ACCEPT_SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_SECOND_REPLY_DONE :
+#ifdef HAVE_SESSION_TICKET
+            if (ssl->options.createTicket) {
+                if ( (ssl->error = SendTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TICKET_SENT;
+            WOLFSSL_MSG("accept state  TICKET_SENT");
+            FALL_THROUGH;
+
+        case TICKET_SENT:
+            if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = CHANGE_CIPHER_SENT;
+            WOLFSSL_MSG("accept state  CHANGE_CIPHER_SENT");
+            FALL_THROUGH;
+
+        case CHANGE_CIPHER_SENT :
+            if ( (ssl->error = SendFinished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.acceptState = ACCEPT_FINISHED_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_FINISHED_DONE :
+            if (ssl->options.resuming)
+                while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                    if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+
+            ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+            FALL_THROUGH;
+
+        case ACCEPT_THIRD_REPLY_DONE :
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            if (!ssl->options.dtls) {
+                if (!ssl->options.keepResources) {
+                    FreeHandshakeResources(ssl);
+                }
+            }
+#ifdef WOLFSSL_DTLS
+            else {
+                ssl->options.dtlsHsRetain = 1;
+            }
+#endif /* WOLFSSL_DTLS */
+
+#ifdef WOLFSSL_SESSION_EXPORT
+            if (ssl->dtls_export) {
+                if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
+                    WOLFSSL_MSG("Export DTLS session error");
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+
+            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default :
+            WOLFSSL_MSG("Unknown accept state ERROR");
+            return WOLFSSL_FATAL_ERROR;
+        }
+#endif /* !WOLFSSL_NO_TLS12 */
+    }
+
+#endif /* NO_WOLFSSL_SERVER */
+
+
+#ifndef NO_HANDSHAKE_DONE_CB
+
+int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ssl->hsDoneCb  = cb;
+    ssl->hsDoneCtx = user_ctx;
+
+
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+int wolfSSL_Cleanup(void)
+{
+    int ret = WOLFSSL_SUCCESS;
+    int release = 0;
+
+    WOLFSSL_ENTER("wolfSSL_Cleanup");
+
+    if (initRefCount == 0)
+        return ret;  /* possibly no init yet, but not failure either way */
+
+    if (wc_LockMutex(&count_mutex) != 0) {
+        WOLFSSL_MSG("Bad Lock Mutex count");
+        return BAD_MUTEX_E;
+    }
+
+    release = initRefCount-- == 1;
+    if (initRefCount < 0)
+        initRefCount = 0;
+
+    wc_UnLockMutex(&count_mutex);
+
+    if (!release)
+        return ret;
+
+#ifndef NO_SESSION_CACHE
+    if (wc_FreeMutex(&session_mutex) != 0)
+        ret = BAD_MUTEX_E;
+#endif
+    if (wc_FreeMutex(&count_mutex) != 0)
+        ret = BAD_MUTEX_E;
+
+    if (wolfCrypt_Cleanup() != 0) {
+        WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
+        ret = WC_CLEANUP_E;
+    }
+
+    return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+
+/* some session IDs aren't random after all, let's make them random */
+static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error)
+{
+    byte digest[WC_MAX_DIGEST_SIZE];
+
+#ifndef NO_MD5
+    *error =  wc_Md5Hash(sessionID, len, digest);
+#elif !defined(NO_SHA)
+    *error =  wc_ShaHash(sessionID, len, digest);
+#elif !defined(NO_SHA256)
+    *error =  wc_Sha256Hash(sessionID, len, digest);
+#else
+    #error "We need a digest to hash the session IDs"
+#endif
+
+    return *error == 0 ? MakeWordFromHash(digest) : 0; /* 0 on failure */
+}
+
+
+void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
+{
+    /* static table now, no flushing needed */
+    (void)ctx;
+    (void)tm;
+}
+
+
+/* set ssl session timeout in seconds */
+int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to)
+{
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    if (to == 0)
+        to = WOLFSSL_SESSION_TIMEOUT;
+    ssl->timeout = to;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* set ctx session timeout in seconds */
+int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to)
+{
+    if (ctx == NULL)
+        return BAD_FUNC_ARG;
+
+    if (to == 0)
+        to = WOLFSSL_SESSION_TIMEOUT;
+    ctx->timeout = to;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_CLIENT_CACHE
+
+/* Get Session from Client cache based on id/len, return NULL on failure */
+WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
+{
+    WOLFSSL_SESSION* ret = NULL;
+    word32          row;
+    int             idx;
+    int             count;
+    int             error = 0;
+
+    WOLFSSL_ENTER("GetSessionClient");
+
+    if (ssl->ctx->sessionCacheOff)
+        return NULL;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return NULL;
+
+    len = min(SERVER_ID_LEN, (word32)len);
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->ctx->get_sess_cb != NULL) {
+        int copy = 0;
+        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, &copy);
+        if (ret != NULL)
+            return ret;
+    }
+
+    if (ssl->ctx->internalCacheOff)
+        return NULL;
+#endif
+
+    row = HashSession(id, len, &error) % SESSION_ROWS;
+    if (error != 0) {
+        WOLFSSL_MSG("Hash session failed");
+        return NULL;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        WOLFSSL_MSG("Lock session mutex failed");
+        return NULL;
+    }
+
+    /* start from most recently used */
+    count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW);
+    idx = ClientCache[row].nextIdx - 1;
+    if (idx < 0)
+        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
+
+    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+        WOLFSSL_SESSION* current;
+        ClientSession   clSess;
+
+        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
+            WOLFSSL_MSG("Bad idx");
+            break;
+        }
+
+        clSess = ClientCache[row].Clients[idx];
+
+        current = &SessionCache[clSess.serverRow].Sessions[clSess.serverIdx];
+        if (XMEMCMP(current->serverID, id, len) == 0) {
+            WOLFSSL_MSG("Found a serverid match for client");
+            if (LowResTimer() < (current->bornOn + current->timeout)) {
+                WOLFSSL_MSG("Session valid");
+                ret = current;
+                break;
+            } else {
+                WOLFSSL_MSG("Session timed out");  /* could have more for id */
+            }
+        } else {
+            WOLFSSL_MSG("ServerID not a match from client table");
+        }
+    }
+
+    wc_UnLockMutex(&session_mutex);
+
+    return ret;
+}
+
+#endif /* NO_CLIENT_CACHE */
+
+/* Restore the master secret and session information for certificates.
+ *
+ * ssl                  The SSL/TLS object.
+ * session              The cached session to restore.
+ * masterSecret         The master secret from the cached session.
+ * restoreSessionCerts  Restoring session certificates is required.
+ */
+static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session,
+        byte* masterSecret, byte restoreSessionCerts)
+{
+    (void)ssl;
+    (void)restoreSessionCerts;
+
+    if (masterSecret)
+        XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN);
+#ifdef SESSION_CERTS
+    /* If set, we should copy the session certs into the ssl object
+     * from the session we are returning so we can resume */
+    if (restoreSessionCerts) {
+        ssl->session.chain        = session->chain;
+        ssl->session.version      = session->version;
+        ssl->session.cipherSuite0 = session->cipherSuite0;
+        ssl->session.cipherSuite  = session->cipherSuite;
+    }
+#endif /* SESSION_CERTS */
+}
+
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+        byte restoreSessionCerts)
+{
+    WOLFSSL_SESSION* ret = 0;
+    const byte*  id = NULL;
+    word32       row;
+    int          idx;
+    int          count;
+    int          error = 0;
+
+    (void)       restoreSessionCerts;
+
+    if (ssl->options.sessionCacheOff)
+        return NULL;
+
+    if (ssl->options.haveSessionId == 0)
+        return NULL;
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
+        return NULL;
+#endif
+
+    if (ssl->arrays)
+        id = ssl->arrays->sessionID;
+    else
+        id = ssl->session.sessionID;
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->ctx->get_sess_cb != NULL) {
+        int copy = 0;
+        /* Attempt to retrieve the session from the external cache. */
+        ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, &copy);
+        if (ret != NULL) {
+            RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
+            return ret;
+        }
+    }
+
+    if (ssl->ctx->internalCacheOff)
+        return NULL;
+#endif
+
+    row = HashSession(id, ID_LEN, &error) % SESSION_ROWS;
+    if (error != 0) {
+        WOLFSSL_MSG("Hash session failed");
+        return NULL;
+    }
+
+    if (wc_LockMutex(&session_mutex) != 0)
+        return 0;
+
+    /* start from most recently used */
+    count = min((word32)SessionCache[row].totalCount, SESSIONS_PER_ROW);
+    idx = SessionCache[row].nextIdx - 1;
+    if (idx < 0)
+        idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */
+
+    for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+        WOLFSSL_SESSION* current;
+
+        if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */
+            WOLFSSL_MSG("Bad idx");
+            break;
+        }
+
+        current = &SessionCache[row].Sessions[idx];
+        if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) {
+            WOLFSSL_MSG("Found a session match");
+            if (LowResTimer() < (current->bornOn + current->timeout)) {
+                WOLFSSL_MSG("Session valid");
+                ret = current;
+                RestoreSession(ssl, ret, masterSecret, restoreSessionCerts);
+            } else {
+                WOLFSSL_MSG("Session timed out");
+            }
+            break;  /* no more sessionIDs whether valid or not that match */
+        } else {
+            WOLFSSL_MSG("SessionID not a match at this idx");
+        }
+    }
+
+    wc_UnLockMutex(&session_mutex);
+
+    return ret;
+}
+
+
+static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom)
+{
+    WOLFSSL_SESSION* copyInto = &ssl->session;
+    void* tmpBuff             = NULL;
+    int ticketLen             = 0;
+    int doDynamicCopy         = 0;
+    int ret                   = WOLFSSL_SUCCESS;
+
+    (void)ticketLen;
+    (void)doDynamicCopy;
+    (void)tmpBuff;
+
+    if (!ssl || !copyFrom)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_SESSION_TICKET
+    /* Free old dynamic ticket if we had one to avoid leak */
+    if (copyInto->isDynamic) {
+        XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        copyInto->ticket = copyInto->staticTicket;
+        copyInto->isDynamic = 0;
+    }
+#endif
+
+    if (wc_LockMutex(&session_mutex) != 0)
+        return BAD_MUTEX_E;
+
+#ifdef HAVE_SESSION_TICKET
+    /* Size of ticket to alloc if needed; Use later for alloc outside lock */
+    doDynamicCopy = copyFrom->isDynamic;
+    ticketLen = copyFrom->ticketLen;
+#endif
+
+    *copyInto = *copyFrom;
+
+    /* Default ticket to non dynamic. This will avoid crash if we fail below */
+#ifdef HAVE_SESSION_TICKET
+    copyInto->ticket = copyInto->staticTicket;
+    copyInto->isDynamic = 0;
+#endif
+
+    if (wc_UnLockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13
+    if (wc_LockMutex(&session_mutex) != 0) {
+        XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        return BAD_MUTEX_E;
+    }
+
+    copyInto->cipherSuite0   = copyFrom->cipherSuite0;
+    copyInto->cipherSuite    = copyFrom->cipherSuite;
+    copyInto->namedGroup     = copyFrom->namedGroup;
+    copyInto->ticketSeen     = copyFrom->ticketSeen;
+    copyInto->ticketAdd      = copyFrom->ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    XMEMCPY(&copyInto->ticketNonce, &copyFrom->ticketNonce,
+                                                           sizeof(TicketNonce));
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz;
+#endif
+    XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN);
+
+    if (wc_UnLockMutex(&session_mutex) != 0) {
+        if (ret == WOLFSSL_SUCCESS)
+            ret = BAD_MUTEX_E;
+    }
+#endif
+    /* If doing dynamic copy, need to alloc outside lock, then inside a lock
+     * confirm the size still matches and memcpy */
+    if (doDynamicCopy) {
+        tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap,
+                                                     DYNAMIC_TYPE_SESSION_TICK);
+        if (!tmpBuff)
+            return MEMORY_ERROR;
+
+        if (wc_LockMutex(&session_mutex) != 0) {
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            return BAD_MUTEX_E;
+        }
+
+        if (ticketLen != copyFrom->ticketLen) {
+            /* Another thread modified the ssl-> session ticket during alloc.
+             * Treat as error, since ticket different than when copy requested */
+            ret = VAR_STATE_CHANGE_E;
+        }
+
+        if (ret == WOLFSSL_SUCCESS) {
+            copyInto->ticket = (byte*)tmpBuff;
+            copyInto->isDynamic = 1;
+            XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen);
+        }
+    } else {
+        /* Need to ensure ticket pointer gets updated to own buffer
+         * and is not pointing to buff of session copied from */
+        copyInto->ticket = copyInto->staticTicket;
+    }
+
+    if (doDynamicCopy) {
+        if (wc_UnLockMutex(&session_mutex) != 0) {
+            if (ret == WOLFSSL_SUCCESS)
+                ret = BAD_MUTEX_E;
+        }
+    }
+
+    if (ret != WOLFSSL_SUCCESS) {
+        /* cleanup */
+        if (tmpBuff)
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+        copyInto->ticket = copyInto->staticTicket;
+        copyInto->isDynamic = 0;
+    }
+#endif /* HAVE_SESSION_TICKET */
+    return ret;
+}
+
+
+int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+{
+    if (ssl->options.sessionCacheOff)
+        return WOLFSSL_FAILURE;
+
+#ifdef OPENSSL_EXTRA
+    /* check for application context id */
+    if (ssl->sessionCtxSz > 0) {
+        if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) {
+            /* context id did not match! */
+            WOLFSSL_MSG("Session context did not match");
+            return SSL_FAILURE;
+        }
+    }
+#endif /* OPENSSL_EXTRA */
+
+    if (LowResTimer() < (session->bornOn + session->timeout)) {
+        int ret = GetDeepCopySession(ssl, session);
+        if (ret == WOLFSSL_SUCCESS) {
+            ssl->options.resuming = 1;
+
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+            ssl->version              = session->version;
+            ssl->options.cipherSuite0 = session->cipherSuite0;
+            ssl->options.cipherSuite  = session->cipherSuite;
+#endif
+        }
+
+        return ret;
+    }
+    return WOLFSSL_FAILURE;  /* session timed out */
+}
+
+
+#ifdef WOLFSSL_SESSION_STATS
+static int get_locked_session_stats(word32* active, word32* total,
+                                    word32* peak);
+#endif
+
+int AddSession(WOLFSSL* ssl)
+{
+    word32 row = 0;
+    word32 idx = 0;
+    int    error = 0;
+#ifdef HAVE_SESSION_TICKET
+    byte*  tmpBuff = NULL;
+    int    ticLen  = 0;
+#endif
+    WOLFSSL_SESSION* session;
+
+    if (ssl->options.sessionCacheOff)
+        return 0;
+
+    if (ssl->options.haveSessionId == 0)
+        return 0;
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
+        return 0;
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    ticLen = ssl->session.ticketLen;
+    /* Alloc Memory here so if Malloc fails can exit outside of lock */
+    if(ticLen > SESSION_TICKET_LEN) {
+        tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap,
+                DYNAMIC_TYPE_SESSION_TICK);
+        if(!tmpBuff)
+            return MEMORY_E;
+    }
+#endif
+
+#ifdef HAVE_EXT_CACHE
+    if (ssl->options.internalCacheOff) {
+        /* Create a new session object to be stored. */
+        session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+                                            DYNAMIC_TYPE_OPENSSL);
+        if (session == NULL) {
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return MEMORY_E;
+        }
+        XMEMSET(session, 0, sizeof(WOLFSSL_SESSION));
+        session->isAlloced = 1;
+    }
+    else
+#endif
+    {
+        /* Use the session object in the cache for external cache if required.
+         */
+        row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) %
+                SESSION_ROWS;
+        if (error != 0) {
+            WOLFSSL_MSG("Hash session failed");
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return error;
+        }
+
+        if (wc_LockMutex(&session_mutex) != 0) {
+#ifdef HAVE_SESSION_TICKET
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+#endif
+            return BAD_MUTEX_E;
+        }
+
+        idx = SessionCache[row].nextIdx++;
+#ifdef SESSION_INDEX
+        ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
+#endif
+        session = &SessionCache[row].Sessions[idx];
+    }
+
+    if (!ssl->options.tls1_3)
+        XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN);
+    else
+        XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN);
+    session->haveEMS = ssl->options.haveEMS;
+    XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN);
+    session->sessionIDSz = ssl->arrays->sessionIDSz;
+
+#ifdef OPENSSL_EXTRA
+    /* If using compatibilty layer then check for and copy over session context
+     * id. */
+    if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) {
+        XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz);
+    }
+#endif
+
+    session->timeout = ssl->timeout;
+    session->bornOn  = LowResTimer();
+
+#ifdef HAVE_SESSION_TICKET
+    /* Check if another thread modified ticket since alloc */
+    if (ticLen != ssl->session.ticketLen) {
+        error = VAR_STATE_CHANGE_E;
+    }
+
+    if (error == 0) {
+        /* Cleanup cache row's old Dynamic buff if exists */
+        if(session->isDynamic) {
+            XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            session->ticket = NULL;
+        }
+
+        /* If too large to store in static buffer, use dyn buffer */
+        if (ticLen > SESSION_TICKET_LEN) {
+            session->ticket = tmpBuff;
+            session->isDynamic = 1;
+        } else {
+            session->ticket = session->staticTicket;
+            session->isDynamic = 0;
+        }
+    }
+
+    if (error == 0) {
+        session->ticketLen = (word16)ticLen;
+        XMEMCPY(session->ticket, ssl->session.ticket, ticLen);
+    } else { /* cleanup, reset state */
+        session->ticket    = session->staticTicket;
+        session->isDynamic = 0;
+        session->ticketLen = 0;
+        if (tmpBuff) {
+            XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
+            tmpBuff = NULL;
+        }
+    }
+#endif
+
+#ifdef SESSION_CERTS
+    if (error == 0) {
+        session->chain.count = ssl->session.chain.count;
+        XMEMCPY(session->chain.certs, ssl->session.chain.certs,
+                sizeof(x509_buffer) * MAX_CHAIN_DEPTH);
+    }
+#endif /* SESSION_CERTS */
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    if (error == 0) {
+        session->version      = ssl->version;
+        session->cipherSuite0 = ssl->options.cipherSuite0;
+        session->cipherSuite  = ssl->options.cipherSuite;
+    }
+#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */
+#if defined(WOLFSSL_TLS13)
+    if (error == 0) {
+        session->namedGroup     = ssl->session.namedGroup;
+    }
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
+    if (error == 0) {
+        session->ticketSeen     = ssl->session.ticketSeen;
+        session->ticketAdd      = ssl->session.ticketAdd;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+        XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce,
+                                                           sizeof(TicketNonce));
+#endif
+    #ifdef WOLFSSL_EARLY_DATA
+        session->maxEarlyDataSz = ssl->session.maxEarlyDataSz;
+    #endif
+    }
+#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (error == 0) {
+            SessionCache[row].totalCount++;
+            if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
+                SessionCache[row].nextIdx = 0;
+        }
+    }
+#ifndef NO_CLIENT_CACHE
+    if (error == 0) {
+        if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) {
+            word32 clientRow, clientIdx;
+
+            WOLFSSL_MSG("Adding client cache entry");
+
+            session->idLen = ssl->session.idLen;
+            XMEMCPY(session->serverID, ssl->session.serverID,
+                    ssl->session.idLen);
+
+#ifdef HAVE_EXT_CACHE
+            if (!ssl->options.internalCacheOff)
+#endif
+            {
+                clientRow = HashSession(ssl->session.serverID,
+                        ssl->session.idLen, &error) % SESSION_ROWS;
+                if (error != 0) {
+                    WOLFSSL_MSG("Hash session failed");
+                } else {
+                    clientIdx = ClientCache[clientRow].nextIdx++;
+
+                    ClientCache[clientRow].Clients[clientIdx].serverRow =
+                                                                   (word16)row;
+                    ClientCache[clientRow].Clients[clientIdx].serverIdx =
+                                                                   (word16)idx;
+
+                    ClientCache[clientRow].totalCount++;
+                    if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW)
+                        ClientCache[clientRow].nextIdx = 0;
+                }
+            }
+        }
+        else
+            session->idLen = 0;
+    }
+#endif /* NO_CLIENT_CACHE */
+
+#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS)
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (error == 0) {
+            word32 active = 0;
+
+            error = get_locked_session_stats(&active, NULL, NULL);
+            if (error == WOLFSSL_SUCCESS) {
+                error = 0;  /* back to this function ok */
+
+                if (active > PeakSessions)
+                    PeakSessions = active;
+            }
+        }
+    }
+#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */
+
+#ifdef HAVE_EXT_CACHE
+    if (!ssl->options.internalCacheOff)
+#endif
+    {
+        if (wc_UnLockMutex(&session_mutex) != 0)
+            return BAD_MUTEX_E;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (error == 0 && ssl->ctx->new_sess_cb != NULL)
+        ssl->ctx->new_sess_cb(ssl, session);
+    if (ssl->options.internalCacheOff)
+        wolfSSL_SESSION_free(session);
+#endif
+
+    return error;
+}
+
+
+#ifdef SESSION_INDEX
+
+int wolfSSL_GetSessionIndex(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_GetSessionIndex");
+    WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex);
+    return ssl->sessionIndex;
+}
+
+
+int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
+{
+    int row, col, result = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
+
+    row = idx >> SESSIDX_ROW_SHIFT;
+    col = idx & SESSIDX_IDX_MASK;
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+    if (row < SESSION_ROWS &&
+        col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) {
+        XMEMCPY(session,
+                 &SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION));
+        result = WOLFSSL_SUCCESS;
+    }
+
+    if (wc_UnLockMutex(&session_mutex) != 0)
+        result = BAD_MUTEX_E;
+
+    WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result);
+    return result;
+}
+
+#endif /* SESSION_INDEX */
+
+#if defined(SESSION_INDEX) && defined(SESSION_CERTS)
+
+WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session)
+{
+    WOLFSSL_X509_CHAIN* chain = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+    if (session)
+        chain = &session->chain;
+
+    WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0);
+    return chain;
+}
+
+#endif /* SESSION_INDEX && SESSION_CERTS */
+
+
+#ifdef WOLFSSL_SESSION_STATS
+
+/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */
+static int get_locked_session_stats(word32* active, word32* total, word32* peak)
+{
+    int result = WOLFSSL_SUCCESS;
+    int i;
+    int count;
+    int idx;
+    word32 now   = 0;
+    word32 seen  = 0;
+    word32 ticks = LowResTimer();
+
+    (void)peak;
+
+    WOLFSSL_ENTER("get_locked_session_stats");
+
+    for (i = 0; i < SESSION_ROWS; i++) {
+        seen += SessionCache[i].totalCount;
+
+        if (active == NULL)
+            continue;  /* no need to calculate what we can't set */
+
+        count = min((word32)SessionCache[i].totalCount, SESSIONS_PER_ROW);
+        idx   = SessionCache[i].nextIdx - 1;
+        if (idx < 0)
+            idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */
+
+        for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) {
+            if (idx >= SESSIONS_PER_ROW || idx < 0) {  /* sanity check */
+                WOLFSSL_MSG("Bad idx");
+                break;
+            }
+
+            /* if not expried then good */
+            if (ticks < (SessionCache[i].Sessions[idx].bornOn +
+                         SessionCache[i].Sessions[idx].timeout) ) {
+                now++;
+            }
+        }
+    }
+
+    if (active)
+        *active = now;
+
+    if (total)
+        *total = seen;
+
+#ifdef WOLFSSL_PEAK_SESSIONS
+    if (peak)
+        *peak = PeakSessions;
+#endif
+
+    WOLFSSL_LEAVE("get_locked_session_stats", result);
+
+    return result;
+}
+
+
+/* return WOLFSSL_SUCCESS on ok */
+int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
+                              word32* maxSessions)
+{
+    int result = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_get_session_stats");
+
+    if (maxSessions) {
+        *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS;
+
+        if (active == NULL && total == NULL && peak == NULL)
+            return result;  /* we're done */
+    }
+
+    /* user must provide at least one query value */
+    if (active == NULL && total == NULL && peak == NULL)
+        return BAD_FUNC_ARG;
+
+    if (wc_LockMutex(&session_mutex) != 0) {
+        return BAD_MUTEX_E;
+    }
+
+    result = get_locked_session_stats(active, total, peak);
+
+    if (wc_UnLockMutex(&session_mutex) != 0)
+        result = BAD_MUTEX_E;
+
+    WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
+
+    return result;
+}
+
+#endif /* WOLFSSL_SESSION_STATS */
+
+
+    #ifdef PRINT_SESSION_STATS
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_PrintSessionStats(void)
+    {
+        word32 totalSessionsSeen = 0;
+        word32 totalSessionsNow = 0;
+        word32 peak = 0;
+        word32 maxSessions = 0;
+        int    i;
+        int    ret;
+        double E;               /* expected freq */
+        double chiSquare = 0;
+
+        ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen,
+                                        &peak, &maxSessions);
+        if (ret != WOLFSSL_SUCCESS)
+            return ret;
+        printf("Total Sessions Seen = %d\n", totalSessionsSeen);
+        printf("Total Sessions Now  = %d\n", totalSessionsNow);
+#ifdef WOLFSSL_PEAK_SESSIONS
+        printf("Peak  Sessions      = %d\n", peak);
+#endif
+        printf("Max   Sessions      = %d\n", maxSessions);
+
+        E = (double)totalSessionsSeen / SESSION_ROWS;
+
+        for (i = 0; i < SESSION_ROWS; i++) {
+            double diff = SessionCache[i].totalCount - E;
+            diff *= diff;                /* square    */
+            diff /= E;                   /* normalize */
+
+            chiSquare += diff;
+        }
+        printf("  chi-square = %5.1f, d.f. = %d\n", chiSquare,
+                                                     SESSION_ROWS - 1);
+        #if (SESSION_ROWS == 11)
+            printf(" .05 p value =  18.3, chi-square should be less\n");
+        #elif (SESSION_ROWS == 211)
+            printf(".05 p value  = 244.8, chi-square should be less\n");
+        #elif (SESSION_ROWS == 5981)
+            printf(".05 p value  = 6161.0, chi-square should be less\n");
+        #elif (SESSION_ROWS == 3)
+            printf(".05 p value  =   6.0, chi-square should be less\n");
+        #elif (SESSION_ROWS == 2861)
+            printf(".05 p value  = 2985.5, chi-square should be less\n");
+        #endif
+        printf("\n");
+
+        return ret;
+    }
+
+    #endif /* SESSION_STATS */
+
+#else  /* NO_SESSION_CACHE */
+
+/* No session cache version */
+WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
+        byte restoreSessionCerts)
+{
+    (void)ssl;
+    (void)masterSecret;
+    (void)restoreSessionCerts;
+
+    return NULL;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+/* call before SSL_connect, if verifying will add name check to
+   date check and signature check */
+int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
+{
+    WOLFSSL_ENTER("wolfSSL_check_domain_name");
+
+    if (ssl == NULL || dn == NULL) {
+        WOLFSSL_MSG("Bad function argument: NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (ssl->buffers.domainName.buffer)
+        XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    ssl->buffers.domainName.length = (word32)XSTRLEN(dn);
+    ssl->buffers.domainName.buffer = (byte*)XMALLOC(
+            ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+    if (ssl->buffers.domainName.buffer) {
+        char* domainName = (char*)ssl->buffers.domainName.buffer;
+        XSTRNCPY(domainName, dn, ssl->buffers.domainName.length);
+        domainName[ssl->buffers.domainName.length] = '\0';
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        ssl->error = MEMORY_ERROR;
+        return WOLFSSL_FAILURE;
+    }
+}
+
+
+/* turn on wolfSSL zlib compression
+   returns WOLFSSL_SUCCESS for success, else error (not built in)
+*/
+int wolfSSL_set_compression(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_set_compression");
+    (void)ssl;
+#ifdef HAVE_LIBZ
+    ssl->options.usingCompression = 1;
+    return WOLFSSL_SUCCESS;
+#else
+    return NOT_COMPILED_IN;
+#endif
+}
+
+
+#ifndef USE_WINDOWS_API
+    #ifndef NO_WRITEV
+
+        /* simulate writev semantics, doesn't actually do block at a time though
+           because of SSL_write behavior and because front adds may be small */
+        int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt)
+        {
+        #ifdef WOLFSSL_SMALL_STACK
+            byte   staticBuffer[1]; /* force heap usage */
+        #else
+            byte   staticBuffer[FILE_BUFFER_SIZE];
+        #endif
+            byte* myBuffer  = staticBuffer;
+            int   dynamic   = 0;
+            int   sending   = 0;
+            int   idx       = 0;
+            int   i;
+            int   ret;
+
+            WOLFSSL_ENTER("wolfSSL_writev");
+
+            for (i = 0; i < iovcnt; i++)
+                sending += (int)iov[i].iov_len;
+
+            if (sending > (int)sizeof(staticBuffer)) {
+                myBuffer = (byte*)XMALLOC(sending, ssl->heap,
+                                                           DYNAMIC_TYPE_WRITEV);
+                if (!myBuffer)
+                    return MEMORY_ERROR;
+
+                dynamic = 1;
+            }
+
+            for (i = 0; i < iovcnt; i++) {
+                XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
+                idx += (int)iov[i].iov_len;
+            }
+
+            ret = wolfSSL_write(ssl, myBuffer, sending);
+
+            if (dynamic)
+                XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+
+            return ret;
+        }
+    #endif
+#endif
+
+
+#ifdef WOLFSSL_CALLBACKS
+
+    typedef struct itimerval Itimerval;
+
+    /* don't keep calling simple functions while setting up timer and signals
+       if no inlining these are the next best */
+
+    #define AddTimes(a, b, c)                       \
+        do {                                        \
+            c.tv_sec  = a.tv_sec  + b.tv_sec;       \
+            c.tv_usec = a.tv_usec + b.tv_usec;      \
+            if (c.tv_usec >=  1000000) {            \
+                c.tv_sec++;                         \
+                c.tv_usec -= 1000000;               \
+            }                                       \
+        } while (0)
+
+
+    #define SubtractTimes(a, b, c)                  \
+        do {                                        \
+            c.tv_sec  = a.tv_sec  - b.tv_sec;       \
+            c.tv_usec = a.tv_usec - b.tv_usec;      \
+            if (c.tv_usec < 0) {                    \
+                c.tv_sec--;                         \
+                c.tv_usec += 1000000;               \
+            }                                       \
+        } while (0)
+
+    #define CmpTimes(a, b, cmp)                     \
+        ((a.tv_sec  ==  b.tv_sec) ?                 \
+            (a.tv_usec cmp b.tv_usec) :             \
+            (a.tv_sec  cmp b.tv_sec))               \
+
+
+    /* do nothing handler */
+    static void myHandler(int signo)
+    {
+        (void)signo;
+        return;
+    }
+
+
+    static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                                 TimeoutCallBack toCb, Timeval timeout)
+    {
+        int       ret        = WOLFSSL_FATAL_ERROR;
+        int       oldTimerOn = 0;   /* was timer already on */
+        Timeval   startTime;
+        Timeval   endTime;
+        Timeval   totalTime;
+        Itimerval myTimeout;
+        Itimerval oldTimeout; /* if old timer adjust from total time to reset */
+        struct sigaction act, oact;
+
+        #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
+
+        if (hsCb) {
+            ssl->hsInfoOn = 1;
+            InitHandShakeInfo(&ssl->handShakeInfo, ssl);
+        }
+        if (toCb) {
+            ssl->toInfoOn = 1;
+            InitTimeoutInfo(&ssl->timeoutInfo);
+
+            if (gettimeofday(&startTime, 0) < 0)
+                ERR_OUT(GETTIME_ERROR);
+
+            /* use setitimer to simulate getitimer, init 0 myTimeout */
+            myTimeout.it_interval.tv_sec  = 0;
+            myTimeout.it_interval.tv_usec = 0;
+            myTimeout.it_value.tv_sec     = 0;
+            myTimeout.it_value.tv_usec    = 0;
+            if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
+                ERR_OUT(SETITIMER_ERROR);
+
+            if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
+                oldTimerOn = 1;
+
+                /* is old timer going to expire before ours */
+                if (CmpTimes(oldTimeout.it_value, timeout, <)) {
+                    timeout.tv_sec  = oldTimeout.it_value.tv_sec;
+                    timeout.tv_usec = oldTimeout.it_value.tv_usec;
+                }
+            }
+            myTimeout.it_value.tv_sec  = timeout.tv_sec;
+            myTimeout.it_value.tv_usec = timeout.tv_usec;
+
+            /* set up signal handler, don't restart socket send/recv */
+            act.sa_handler = myHandler;
+            sigemptyset(&act.sa_mask);
+            act.sa_flags = 0;
+#ifdef SA_INTERRUPT
+            act.sa_flags |= SA_INTERRUPT;
+#endif
+            if (sigaction(SIGALRM, &act, &oact) < 0)
+                ERR_OUT(SIGACT_ERROR);
+
+            if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
+                ERR_OUT(SETITIMER_ERROR);
+        }
+
+        /* do main work */
+#ifndef NO_WOLFSSL_CLIENT
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            ret = wolfSSL_connect(ssl);
+#endif
+#ifndef NO_WOLFSSL_SERVER
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            ret = wolfSSL_accept(ssl);
+#endif
+
+        /* do callbacks */
+        if (toCb) {
+            if (oldTimerOn) {
+                gettimeofday(&endTime, 0);
+                SubtractTimes(endTime, startTime, totalTime);
+                /* adjust old timer for elapsed time */
+                if (CmpTimes(totalTime, oldTimeout.it_value, <))
+                    SubtractTimes(oldTimeout.it_value, totalTime,
+                                  oldTimeout.it_value);
+                else {
+                    /* reset value to interval, may be off */
+                    oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
+                    oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
+                }
+                /* keep iter the same whether there or not */
+            }
+            /* restore old handler */
+            if (sigaction(SIGALRM, &oact, 0) < 0)
+                ret = SIGACT_ERROR;    /* more pressing error, stomp */
+            else
+                /* use old settings which may turn off (expired or not there) */
+                if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
+                    ret = SETITIMER_ERROR;
+
+            /* if we had a timeout call callback */
+            if (ssl->timeoutInfo.timeoutName[0]) {
+                ssl->timeoutInfo.timeoutValue.tv_sec  = timeout.tv_sec;
+                ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
+                (toCb)(&ssl->timeoutInfo);
+            }
+            /* clean up */
+            FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+            ssl->toInfoOn = 0;
+        }
+        if (hsCb) {
+            FinishHandShakeInfo(&ssl->handShakeInfo);
+            (hsCb)(&ssl->handShakeInfo);
+            ssl->hsInfoOn = 0;
+        }
+        return ret;
+    }
+
+
+#ifndef NO_WOLFSSL_CLIENT
+
+    int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                          TimeoutCallBack toCb, Timeval timeout)
+    {
+        WOLFSSL_ENTER("wolfSSL_connect_ex");
+        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+    }
+
+#endif
+
+
+#ifndef NO_WOLFSSL_SERVER
+
+    int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
+                         TimeoutCallBack toCb,Timeval timeout)
+    {
+        WOLFSSL_ENTER("wolfSSL_accept_ex");
+        return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+    }
+
+#endif
+
+#endif /* WOLFSSL_CALLBACKS */
+
+
+#ifndef NO_PSK
+
+    void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
+                                         wc_psk_client_callback cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback");
+        ctx->havePSK = 1;
+        ctx->client_psk_cb = cb;
+    }
+
+
+    void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
+    {
+        byte haveRSA = 1;
+        int  keySz   = 0;
+
+        WOLFSSL_ENTER("SSL_set_psk_client_callback");
+        ssl->options.havePSK = 1;
+        ssl->options.client_psk_cb = cb;
+
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+
+    void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
+                                         wc_psk_server_callback cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback");
+        ctx->havePSK = 1;
+        ctx->server_psk_cb = cb;
+    }
+
+
+    void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
+    {
+        byte haveRSA = 1;
+        int  keySz   = 0;
+
+        WOLFSSL_ENTER("SSL_set_psk_server_callback");
+        ssl->options.havePSK = 1;
+        ssl->options.server_psk_cb = cb;
+
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_CERTS
+            keySz = ssl->buffers.keySz;
+        #endif
+        InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE,
+                   ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+
+    const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_psk_identity_hint");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return NULL;
+
+        return ssl->arrays->server_hint;
+    }
+
+
+    const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_psk_identity");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return NULL;
+
+        return ssl->arrays->client_identity;
+    }
+
+
+    int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint)
+    {
+        WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint");
+        if (hint == 0)
+            ctx->server_hint[0] = '\0';
+        else {
+            XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint));
+            ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
+    {
+        WOLFSSL_ENTER("SSL_use_psk_identity_hint");
+
+        if (ssl == NULL || ssl->arrays == NULL)
+            return WOLFSSL_FAILURE;
+
+        if (hint == 0)
+            ssl->arrays->server_hint[0] = 0;
+        else {
+            XSTRNCPY(ssl->arrays->server_hint, hint,
+                                            sizeof(ssl->arrays->server_hint));
+            ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* NO_PSK */
+
+
+#ifdef HAVE_ANON
+
+    int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
+
+        if (ctx == NULL)
+            return WOLFSSL_FAILURE;
+
+        ctx->haveAnon = 1;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* HAVE_ANON */
+
+
+#ifndef NO_CERTS
+/* used to be defined on NO_FILESYSTEM only, but are generally useful */
+
+    /* wolfSSL extension allows DER files to be loaded from buffers as well */
+    int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx,
+                                       const unsigned char* in,
+                                       long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer");
+        if (format == WOLFSSL_FILETYPE_PEM)
+            return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL);
+        else
+            return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0);
+    }
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx,
+                                       const unsigned char* in,
+                                       long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
+
+        /* sanity check on arguments */
+        if (sz < 0 || in == NULL || ctx == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (format == WOLFSSL_FILETYPE_PEM)
+            return ProcessChainBuffer(ctx, in, sz, format,
+                                                       TRUSTED_PEER_TYPE, NULL);
+        else
+            return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE,
+                                                                   NULL,NULL,0);
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+
+    int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
+        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0);
+    }
+
+
+    int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
+        return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL,NULL,0);
+    }
+
+
+    int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
+        return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1);
+    }
+
+    int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
+                                 const unsigned char* in, long sz)
+    {
+        return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
+                                                            WOLFSSL_FILETYPE_PEM);
+    }
+
+
+#ifndef NO_DH
+
+    /* server wrapper for ctx or ssl Diffie-Hellman parameters */
+    static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+                                               const unsigned char* buf,
+                                               long sz, int format)
+    {
+        DerBuffer* der = NULL;
+        int    ret      = 0;
+        word32 pSz = MAX_DH_SIZE;
+        word32 gSz = MAX_DH_SIZE;
+    #ifdef WOLFSSL_SMALL_STACK
+        byte*  p = NULL;
+        byte*  g = NULL;
+    #else
+        byte   p[MAX_DH_SIZE];
+        byte   g[MAX_DH_SIZE];
+    #endif
+
+        if (ctx == NULL || buf == NULL)
+            return BAD_FUNC_ARG;
+
+        ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap);
+        if (ret != 0) {
+            return ret;
+        }
+        der->buffer = (byte*)buf;
+        der->length = (word32)sz;
+
+    #ifdef WOLFSSL_SMALL_STACK
+        p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+
+        if (p == NULL || g == NULL) {
+            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            return MEMORY_E;
+        }
+    #endif
+
+        if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)
+            ret = WOLFSSL_BAD_FILETYPE;
+        else {
+            if (format == WOLFSSL_FILETYPE_PEM) {
+#ifdef WOLFSSL_PEM_TO_DER
+                FreeDer(&der);
+                ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap,
+                               NULL, NULL);
+    #ifdef WOLFSSL_WPAS
+        #ifndef NO_DSA
+                if (ret < 0) {
+                    ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap,
+                               NULL, NULL);
+                }
+        #endif
+    #endif /* WOLFSSL_WPAS */
+#else
+                ret = NOT_COMPILED_IN;
+#endif /* WOLFSSL_PEM_TO_DER */
+            }
+
+            if (ret == 0) {
+                if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
+                    ret = WOLFSSL_BAD_FILETYPE;
+                else if (ssl)
+                    ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+                else
+                    ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+            }
+        }
+
+        FreeDer(&der);
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    #endif
+
+        return ret;
+    }
+
+
+    /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+    int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
+                               int format)
+    {
+        if (ssl == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
+    }
+
+
+    /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
+    int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
+                                   long sz, int format)
+    {
+        return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format);
+    }
+
+#endif /* NO_DH */
+
+
+    int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
+        return ProcessBuffer(ssl->ctx, in, sz, format,CERT_TYPE,ssl,NULL,0);
+    }
+
+
+    int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
+        return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
+                             ssl, NULL, 0);
+    }
+
+    int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz, int format)
+    {
+        WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
+        return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE,
+                             ssl, NULL, 1);
+    }
+
+    int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
+                                 const unsigned char* in, long sz)
+    {
+        return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
+                                                            WOLFSSL_FILETYPE_PEM);
+    }
+
+
+    /* unload any certs or keys that SSL owns, leave CTX as is
+       WOLFSSL_SUCCESS on ok */
+    int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
+    {
+        if (ssl == NULL) {
+            WOLFSSL_MSG("Null function arg");
+            return BAD_FUNC_ARG;
+        }
+
+        if (ssl->buffers.weOwnCert && !ssl->keepCert) {
+            WOLFSSL_MSG("Unloading cert");
+            FreeDer(&ssl->buffers.certificate);
+            #ifdef KEEP_OUR_CERT
+                FreeX509(ssl->ourCert);
+                if (ssl->ourCert) {
+                    XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509);
+                    ssl->ourCert = NULL;
+                }
+            #endif
+            ssl->buffers.weOwnCert = 0;
+        }
+
+        if (ssl->buffers.weOwnCertChain) {
+            WOLFSSL_MSG("Unloading cert chain");
+            FreeDer(&ssl->buffers.certChain);
+            ssl->buffers.weOwnCertChain = 0;
+        }
+
+        if (ssl->buffers.weOwnKey) {
+            WOLFSSL_MSG("Unloading key");
+            FreeDer(&ssl->buffers.key);
+            ssl->buffers.weOwnKey = 0;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_CertManagerUnloadCAs(ctx->cm);
+    }
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
+    }
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+/* old NO_FILESYSTEM end */
+#endif /* !NO_CERTS */
+
+
+#ifdef OPENSSL_EXTRA
+
+    int wolfSSL_add_all_algorithms(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
+        if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+            return WOLFSSL_SUCCESS;
+        else
+            return WOLFSSL_FATAL_ERROR;
+    }
+
+    int wolfSSL_OPENSSL_add_all_algorithms_noconf(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_OPENSSL_add_all_algorithms_noconf");
+
+        if  (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
+            return WOLFSSL_FATAL_ERROR;
+
+        return  WOLFSSL_SUCCESS;
+    }
+
+   /* returns previous set cache size which stays constant */
+    long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz)
+    {
+        /* cache size fixed at compile time in wolfSSL */
+        (void)ctx;
+        (void)sz;
+        WOLFSSL_MSG("session cache is set at compile time");
+        #ifndef NO_SESSION_CACHE
+            return SESSIONS_PER_ROW * SESSION_ROWS;
+        #else
+            return 0;
+        #endif
+    }
+
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
+        if (mode)
+            ctx->quietShutdown = 1;
+    }
+
+
+    void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
+        if (mode)
+            ssl->options.quietShutdown = 1;
+    }
+#endif
+
+#ifdef OPENSSL_EXTRA
+    void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_bio");
+
+        if (ssl == NULL) {
+            WOLFSSL_MSG("Bad argument, ssl was NULL");
+            return;
+        }
+
+        /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */
+        if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) {
+            wolfSSL_set_rfd(ssl, rd->fd);
+        }
+        if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) {
+            wolfSSL_set_wfd(ssl, wr->fd);
+        }
+
+        /* free any existing WOLFSSL_BIOs in use */
+        if (ssl->biord != NULL) {
+            if (ssl->biord != ssl->biowr) {
+                if (ssl->biowr != NULL) {
+                    wolfSSL_BIO_free(ssl->biowr);
+                    ssl->biowr = NULL;
+                }
+            }
+            wolfSSL_BIO_free(ssl->biord);
+            ssl->biord = NULL;
+        }
+
+
+        ssl->biord = rd;
+        ssl->biowr = wr;
+
+        /* set SSL to use BIO callbacks instead */
+        if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) &&
+            (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) {
+            ssl->CBIORecv = BioReceive;
+        }
+        if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) &&
+            (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) {
+            ssl->CBIOSend = BioSend;
+        }
+    }
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
+                                       WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+    {
+        WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list");
+
+        if (ctx != NULL)
+            ctx->ca_names = names;
+    }
+
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list(
+            const WOLFSSL_CTX *s)
+    {
+        WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list");
+
+        if (s == NULL)
+            return NULL;
+
+        return s->ca_names;
+    }
+#endif
+
+#ifdef OPENSSL_EXTRA
+    #if !defined(NO_RSA) && !defined(NO_CERTS)
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
+    {
+        WOLFSSL_STACK *list = NULL;
+        WOLFSSL_STACK *node;
+        WOLFSSL_BIO* bio;
+        WOLFSSL_X509 *cert = NULL;
+        WOLFSSL_X509_NAME *subjectName = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
+
+        bio = wolfSSL_BIO_new_file(fname, "r");
+        if (bio == NULL)
+            return NULL;
+
+        /* Read each certificate in the chain out of the file. */
+        while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
+            subjectName = wolfSSL_X509_get_subject_name(cert);
+            if (subjectName == NULL)
+                break;
+
+            node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                           DYNAMIC_TYPE_OPENSSL);
+            if (node == NULL)
+                break;
+
+            /* Need a persistent copy of the subject name. */
+            node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
+                    sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL);
+            if (node->data.name == NULL) {
+                XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+                break;
+            }
+            XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
+            /* Clear pointers so freeing certificate doesn't free memory. */
+            XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
+
+            /* Put node on the front of the list. */
+            node->num  = (list == NULL) ? 1 : list->num + 1;
+            node->next = list;
+            list = node;
+
+            wolfSSL_X509_free(cert);
+            cert = NULL;
+        }
+
+        wolfSSL_X509_free(cert);
+        wolfSSL_BIO_free(bio);
+        return list;
+    }
+
+    int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+    {
+        WOLFSSL_STACK *node = NULL;
+        WOLFSSL_X509_NAME *subjectName = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+
+        if (ctx == NULL || x509 == NULL){
+            WOLFSSL_MSG("Bad argument");
+            return SSL_FAILURE;
+        }
+
+        subjectName = wolfSSL_X509_get_subject_name(x509);
+        if (subjectName == NULL){
+            WOLFSSL_MSG("invalid x509 data");
+            return SSL_FAILURE;
+        }
+
+        /* Alloc stack struct */
+        node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC(
+                                           sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)),
+                                           NULL, DYNAMIC_TYPE_OPENSSL);
+        if (node == NULL){
+            WOLFSSL_MSG("memory allocation error");
+            return SSL_FAILURE;
+        }
+        XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)));
+
+        /* Alloc and copy WOLFSSL_X509_NAME */
+        node->data.name = (WOLFSSL_X509_NAME*)XMALLOC(
+                                              sizeof(WOLFSSL_X509_NAME),
+                                              NULL, DYNAMIC_TYPE_OPENSSL);
+        if (node->data.name == NULL) {
+            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+            WOLFSSL_MSG("memory allocation error");
+            return SSL_FAILURE;
+        }
+        XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME));
+        XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME));
+
+        /* push new node onto head of stack */
+        node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1;
+        node->next = ctx->ca_names;
+        ctx->ca_names = node;
+        return SSL_SUCCESS;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
+    {
+        /* TODO:, not needed in goahead */
+        (void)ctx;
+        WOLFSSL_STUB("SSL_CTX_set_default_verify_paths");
+        return SSL_NOT_IMPLEMENTED;
+    }
+    #endif
+
+    #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
+        && !defined(WC_NO_RNG)
+    static const byte srp_N[] = {
+        0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8,
+        0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF,
+        0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6,
+        0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13,
+        0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B,
+        0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7,
+        0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69,
+        0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
+        0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC,
+        0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E,
+        0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F,
+        0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
+    };
+    static const byte srp_g[] = {
+        0x02
+    };
+
+    int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
+    {
+        int r = 0;
+        SrpSide srp_side = SRP_CLIENT_SIDE;
+        WC_RNG rng;
+        byte salt[SRP_SALT_SIZE];
+
+        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
+        if (ctx == NULL || ctx->srp == NULL || username==NULL)
+            return SSL_FAILURE;
+
+        if (ctx->method->side == WOLFSSL_SERVER_END){
+            srp_side = SRP_SERVER_SIDE;
+        } else if (ctx->method->side == WOLFSSL_CLIENT_END){
+            srp_side = SRP_CLIENT_SIDE;
+        } else {
+            WOLFSSL_MSG("Init CTX failed");
+            return SSL_FAILURE;
+        }
+
+        if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){
+            WOLFSSL_MSG("Init CTX failed");
+            XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+            wolfSSL_CTX_free(ctx);
+            return SSL_FAILURE;
+        }
+        r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
+                              (word32)XSTRLEN(username));
+        if (r < 0) {
+            WOLFSSL_MSG("fail to set srp username.");
+            return SSL_FAILURE;
+        }
+
+        /* if wolfSSL_CTX_set_srp_password has already been called, */
+        /* execute wc_SrpSetPassword here */
+        if (ctx->srp_password != NULL){
+            if (wc_InitRng(&rng) < 0){
+                WOLFSSL_MSG("wc_InitRng failed");
+                return SSL_FAILURE;
+            }
+            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+            if (wc_RNG_GenerateBlock(&rng, salt,
+                                     sizeof(salt)/sizeof(salt[0])) <  0){
+                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
+                WOLFSSL_MSG("wc_SrpSetParam failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            r = wc_SrpSetPassword(ctx->srp,
+                     (const byte*)ctx->srp_password,
+                     (word32)XSTRLEN((char *)ctx->srp_password));
+            if (r < 0) {
+                WOLFSSL_MSG("fail to set srp password.");
+                return SSL_FAILURE;
+            }
+            wc_FreeRng(&rng);
+            XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+            ctx->srp_password = NULL;
+        }
+
+        return SSL_SUCCESS;
+    }
+
+    int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
+    {
+        int r;
+        WC_RNG rng;
+        byte salt[SRP_SALT_SIZE];
+
+        WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
+        if (ctx == NULL || ctx->srp == NULL || password == NULL)
+            return SSL_FAILURE;
+
+        if (ctx->srp->user != NULL){
+            if (wc_InitRng(&rng) < 0){
+                WOLFSSL_MSG("wc_InitRng failed");
+                return SSL_FAILURE;
+            }
+            XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
+            if (wc_RNG_GenerateBlock(&rng, salt,
+                                     sizeof(salt)/sizeof(salt[0])) <  0){
+                WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
+                                srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
+                                salt, sizeof(salt)/sizeof(salt[0])) < 0){
+                WOLFSSL_MSG("wc_SrpSetParam failed");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
+                                  (word32)XSTRLEN(password));
+            if (r < 0) {
+                WOLFSSL_MSG("wc_SrpSetPassword failed.");
+                wc_FreeRng(&rng);
+                return SSL_FAILURE;
+            }
+            if (ctx->srp_password != NULL){
+                XFREE(ctx->srp_password,NULL,
+                      DYNAMIC_TYPE_SRP);
+                ctx->srp_password = NULL;
+            }
+            wc_FreeRng(&rng);
+        } else {
+            /* save password for wolfSSL_set_srp_username */
+            if (ctx->srp_password != NULL)
+                XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP);
+
+            ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap,
+                                               DYNAMIC_TYPE_SRP);
+            if (ctx->srp_password == NULL){
+                WOLFSSL_MSG("memory allocation error");
+                return SSL_FAILURE;
+            }
+            XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1);
+        }
+        return SSL_SUCCESS;
+    }
+    #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
+
+    /* keyblock size in bytes or -1 */
+    int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
+    {
+        if (ssl == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+        return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
+                    ssl->specs.hash_size);
+    }
+
+
+    /* store keys returns WOLFSSL_SUCCESS or -1 on error */
+    int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen,
+                                     unsigned char** sr, unsigned int* srLen,
+                                     unsigned char** cr, unsigned int* crLen)
+    {
+        if (ssl == NULL || ssl->arrays == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+        *ms = ssl->arrays->masterSecret;
+        *sr = ssl->arrays->serverRandom;
+        *cr = ssl->arrays->clientRandom;
+
+        *msLen = SECRET_LEN;
+        *srLen = RAN_LEN;
+        *crLen = RAN_LEN;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
+    void wolfSSL_set_accept_state(WOLFSSL* ssl)
+    {
+        word16 haveRSA = 1;
+        word16 havePSK = 0;
+
+        WOLFSSL_ENTER("SSL_set_accept_state");
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+    #ifdef HAVE_ECC
+            ecc_key key;
+            word32 idx = 0;
+
+            if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) {
+                wc_ecc_init(&key);
+                if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key,
+                                               ssl->buffers.key->length) != 0) {
+                    ssl->options.haveECDSAsig = 0;
+                    ssl->options.haveECC = 0;
+                    ssl->options.haveStaticECC = 0;
+                }
+                wc_ecc_free(&key);
+            }
+    #endif
+
+    #ifndef NO_DH
+            if (!ssl->options.haveDH && ssl->ctx->haveDH) {
+                ssl->buffers.serverDH_P = ssl->ctx->serverDH_P;
+                ssl->buffers.serverDH_G = ssl->ctx->serverDH_G;
+                ssl->options.haveDH = 1;
+            }
+    #endif
+        }
+        ssl->options.side = WOLFSSL_SERVER_END;
+        /* reset suites in case user switched */
+
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+        InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA,
+                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, ssl->options.side);
+    }
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
+
+    /* return true if connection established */
+    int wolfSSL_is_init_finished(WOLFSSL* ssl)
+    {
+        if (ssl == NULL)
+            return 0;
+
+        if (ssl->options.handShakeState == HANDSHAKE_DONE)
+            return 1;
+
+        return 0;
+    }
+
+#ifdef OPENSSL_EXTRA
+
+    void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
+                                      WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
+    {
+        /* wolfSSL verifies all these internally */
+        (void)ctx;
+        (void)f;
+    }
+
+
+    void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt)
+    {
+        WOLFSSL_ENTER("wolfSSL_set_shutdown");
+        if(ssl==NULL) {
+            WOLFSSL_MSG("Shutdown not set. ssl is null");
+            return;
+        }
+
+        ssl->options.sentNotify =  (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
+        ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
+    }
+
+
+    long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_CTX_get_options");
+        WOLFSSL_MSG("wolfSSL options are set through API calls and macros");
+        if(ctx == NULL)
+            return BAD_FUNC_ARG;
+        return ctx->mask;
+    }
+
+    static long wolf_set_options(long old_op, long op);
+    long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_options");
+
+        if (ctx == NULL)
+            return BAD_FUNC_ARG;
+
+        ctx->mask = wolf_set_options(ctx->mask, opt);
+
+        return ctx->mask;
+    }
+
+    long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt)
+    {
+        WOLFSSL_ENTER("SSL_CTX_clear_options");
+        if(ctx == NULL)
+            return BAD_FUNC_ARG;
+        ctx->mask &= ~opt;
+        return ctx->mask;
+    }
+
+    int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
+    {
+        WOLFSSL_ENTER("SSL_set_rfd");
+        ssl->rfd = rfd;      /* not used directly to allow IO callbacks */
+
+        ssl->IOCB_ReadCtx  = &ssl->rfd;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd)
+    {
+        WOLFSSL_ENTER("SSL_set_wfd");
+        ssl->wfd = wfd;      /* not used directly to allow IO callbacks */
+
+        ssl->IOCB_WriteCtx  = &ssl->wfd;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+
+
+#ifndef NO_CERTS
+    WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
+    {
+        if (ctx == NULL) {
+            return NULL;
+        }
+
+        return &ctx->x509_store;
+    }
+
+
+    void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
+    {
+        if (ctx == NULL || str == NULL) {
+            return;
+        }
+
+        /* free cert manager if have one */
+        if (ctx->cm != NULL) {
+            wolfSSL_CertManagerFree(ctx->cm);
+        }
+        ctx->cm               = str->cm;
+        ctx->x509_store.cache = str->cache;
+        ctx->x509_store_pt    = str; /* take ownership of store and free it
+                                        with CTX free */
+    }
+
+
+    WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
+                                                    WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert");
+        if (ctx)
+            return ctx->current_cert;
+        return NULL;
+    }
+
+
+    int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error");
+        if (ctx != NULL)
+            return ctx->error;
+        return 0;
+    }
+
+
+    int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth");
+        if(ctx)
+            return ctx->error_depth;
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
+                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb");
+        if(ctx == NULL)
+            return;
+        ctx->verify_cb = verify_cb;
+    }
+#endif /* !NO_CERTS */
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("BIO_f_buffer");
+        meth.type = WOLFSSL_BIO_BUFFER;
+
+        return &meth;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size)
+    {
+        /* wolfSSL has internal buffer, compatibility only */
+        WOLFSSL_ENTER("BIO_set_write_buffer_size");
+        WOLFSSL_STUB("BIO_set_write_buffer_size");
+        (void)bio;
+        return size;
+    }
+    #endif
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void)
+    {
+        static WOLFSSL_BIO_METHOD bio_meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_f_bio");
+        bio_meth.type = WOLFSSL_BIO_BIO;
+
+        return &bio_meth;
+    }
+
+
+#ifndef NO_FILESYSTEM
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void)
+    {
+        static WOLFSSL_BIO_METHOD file_meth;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_f_file");
+        file_meth.type = WOLFSSL_BIO_FILE;
+
+        return &file_meth;
+    }
+#endif
+
+
+    WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("BIO_f_ssl");
+        meth.type = WOLFSSL_BIO_SSL;
+
+        return &meth;
+    }
+
+
+    WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void)
+    {
+        static WOLFSSL_BIO_METHOD meth;
+
+        WOLFSSL_ENTER("BIO_s_socket");
+        meth.type = WOLFSSL_BIO_SOCKET;
+
+        return &meth;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF)
+    {
+        WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
+
+        WOLFSSL_ENTER("BIO_new_socket");
+        if (bio) {
+            bio->type  = WOLFSSL_BIO_SOCKET;
+            bio->close = (byte)closeF;
+            bio->fd    = sfd;
+        }
+        return bio;
+    }
+
+
+    int wolfSSL_BIO_eof(WOLFSSL_BIO* b)
+    {
+        WOLFSSL_ENTER("BIO_eof");
+        if (b->eof)
+            return 1;
+
+        return 0;
+    }
+
+
+    long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_set_ssl");
+
+        if (b != NULL) {
+            b->ssl   = ssl;
+            b->close = (byte)closeF;
+    /* add to ssl for bio free if SSL_free called before/instead of free_all? */
+        }
+
+        return 0;
+    }
+
+
+    long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_set_fd");
+
+        if (b != NULL) {
+            b->fd    = fd;
+            b->close = (byte)closeF;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method)
+    {
+        WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0,
+                                                DYNAMIC_TYPE_OPENSSL);
+        WOLFSSL_ENTER("wolfSSL_BIO_new");
+        if (bio) {
+            XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
+            bio->type   = method->type;
+            bio->close  = BIO_CLOSE; /* default to close things */
+            if (method->type != WOLFSSL_BIO_FILE &&
+                    method->type != WOLFSSL_BIO_SOCKET) {
+                bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM),
+                                                       0, DYNAMIC_TYPE_OPENSSL);
+                if (bio->mem_buf == NULL) {
+                    WOLFSSL_MSG("Memory error");
+                    wolfSSL_BIO_free(bio);
+                    return NULL;
+                }
+                bio->mem_buf->data = (char*)bio->mem;
+            }
+        }
+        return bio;
+    }
+
+
+    int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
+    {
+        WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data");
+
+        if (bio == NULL || p == NULL)
+            return WOLFSSL_FATAL_ERROR;
+
+        *(byte **)p = bio->mem;
+
+        return bio->memLen;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len)
+    {
+        WOLFSSL_BIO* bio = NULL;
+
+        if (buf == NULL || len < 0) {
+            return bio;
+        }
+
+        bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
+        if (bio == NULL) {
+            return bio;
+        }
+
+        bio->memLen = bio->wrSz = len;
+        bio->mem    = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
+        if (bio->mem == NULL) {
+            wolfSSL_BIO_free(bio);
+            return NULL;
+        }
+        if (bio->mem_buf != NULL) {
+            bio->mem_buf->data = (char*)bio->mem;
+            bio->mem_buf->length = bio->memLen;
+        }
+
+        XMEMCPY(bio->mem, buf, len);
+
+        return bio;
+    }
+
+    /*
+     * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up
+     *        to the application.
+     */
+    int wolfSSL_BIO_free(WOLFSSL_BIO* bio)
+    {
+        /* unchain?, doesn't matter in goahead since from free all */
+        WOLFSSL_ENTER("wolfSSL_BIO_free");
+        if (bio) {
+            /* remove from pair by setting the paired bios pair to NULL */
+            if (bio->pair != NULL) {
+                bio->pair->pair = NULL;
+            }
+
+            if (bio->close) {
+                if (bio->ssl)
+                    wolfSSL_free(bio->ssl);
+                if (bio->fd)
+                    CloseSocket(bio->fd);
+            }
+
+        #ifndef NO_FILESYSTEM
+            if (bio->type == WOLFSSL_BIO_FILE && bio->close == BIO_CLOSE) {
+                if (bio->file) {
+                    XFCLOSE(bio->file);
+                }
+            }
+        #endif
+
+            if (bio->close != BIO_NOCLOSE) {
+                if (bio->mem != NULL) {
+                    if (bio->mem_buf != NULL) {
+                        if (bio->mem_buf->data != (char*)bio->mem) {
+                            XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                            bio->mem = NULL;
+                        }
+                    }
+                    else {
+                        XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                        bio->mem = NULL;
+                    }
+                }
+                if (bio->mem_buf != NULL) {
+                    wolfSSL_BUF_MEM_free(bio->mem_buf);
+                    bio->mem_buf = NULL;
+                }
+            }
+
+            XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
+        }
+        return 0;
+    }
+
+
+    int wolfSSL_BIO_free_all(WOLFSSL_BIO* bio)
+    {
+        WOLFSSL_ENTER("BIO_free_all");
+        while (bio) {
+            WOLFSSL_BIO* next = bio->next;
+            wolfSSL_BIO_free(bio);
+            bio = next;
+        }
+        return 0;
+    }
+
+
+    WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append)
+    {
+        WOLFSSL_ENTER("BIO_push");
+        top->next    = append;
+        append->prev = top;
+
+        return top;
+    }
+
+
+    int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
+    {
+        /* for wolfSSL no flushing needed */
+        WOLFSSL_ENTER("BIO_flush");
+        (void)bio;
+        return 1;
+    }
+#endif /* OPENSSL_EXTRA */
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+    void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
+                                                   void* userdata)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata");
+        ctx->passwd_userdata = userdata;
+    }
+
+
+    void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb");
+        if (ctx != NULL) {
+            ctx->passwd_cb = cb;
+        }
+    }
+
+    pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
+    {
+        if (ctx == NULL || ctx->passwd_cb == NULL) {
+            return NULL;
+        }
+
+        return ctx->passwd_cb;
+    }
+
+
+    void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
+    {
+        if (ctx == NULL) {
+            return NULL;
+        }
+
+        return ctx->passwd_userdata;
+    }
+
+#if !defined(NO_PWDBASED) && (defined(OPENSSL_EXTRA) || \
+        defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER))
+
+    int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type,
+                       const WOLFSSL_EVP_MD* md, const byte* salt,
+                       const byte* data, int sz, int count, byte* key, byte* iv)
+    {
+        int ret;
+        int hashType = WC_HASH_TYPE_NONE;
+    #ifdef WOLFSSL_SMALL_STACK
+        EncryptedInfo* info = NULL;
+    #else
+        EncryptedInfo  info[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                       DYNAMIC_TYPE_ENCRYPTEDINFO);
+        if (info == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            return WOLFSSL_FAILURE;
+        }
+    #endif
+
+        XMEMSET(info, 0, sizeof(EncryptedInfo));
+        info->ivSz = EVP_SALT_SIZE;
+
+        ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL);
+        if (ret == 0)
+            ret = wc_EncryptedInfoGet(info, type);
+        if (ret == 0)
+            ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt,
+                               EVP_SALT_SIZE, count, hashType, NULL);
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+
+        if (ret <= 0)
+            return 0; /* failure - for compatibility */
+
+        return ret;
+    }
+
+#endif /* !NO_PWDBASED && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER) */
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    int wolfSSL_num_locks(void)
+    {
+        return 0;
+    }
+
+    void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int))
+    {
+        WOLFSSL_ENTER("wolfSSL_set_locking_callback");
+
+        if (wc_SetMutexCb(f) != 0) {
+            WOLFSSL_MSG("Error when setting mutex call back");
+        }
+    }
+
+
+    typedef unsigned long (idCb)(void);
+    static idCb* inner_idCb = NULL;
+
+    unsigned long wolfSSL_thread_id(void)
+    {
+        if (inner_idCb != NULL) {
+            return inner_idCb();
+        }
+        else {
+            return 0;
+        }
+    }
+
+
+    void wolfSSL_set_id_callback(unsigned long (*f)(void))
+    {
+        inner_idCb = f;
+    }
+
+    unsigned long wolfSSL_ERR_get_error(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_get_error");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+        {
+            unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL,
+                                                                 NULL, NULL);
+            wc_RemoveErrorNode(-1);
+            return ret;
+        }
+#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
+        {
+            int ret = wc_PullErrorNode(NULL, NULL, NULL);
+
+            if (ret < 0) {
+                if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+                WOLFSSL_MSG("Error with pulling error node!");
+                WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret);
+                ret = 0 - ret; /* return absolute value of error */
+
+                /* panic and try to clear out nodes */
+                wc_ClearErrorNodes();
+            }
+
+            return (unsigned long)ret;
+        }
+#else
+        return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+    }
+
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+
+
+#ifdef OPENSSL_EXTRA
+
+#if !defined(NO_WOLFSSL_SERVER)
+size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out,
+                                                                   size_t outSz)
+{
+    size_t size;
+
+    /* return max size of buffer */
+    if (outSz == 0) {
+        return RAN_LEN;
+    }
+
+    if (ssl == NULL || out == NULL) {
+        return 0;
+    }
+
+    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+        WOLFSSL_MSG("Arrays struct not saved after handshake");
+        return 0;
+    }
+
+    if (outSz > RAN_LEN) {
+        size = RAN_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ssl->arrays->serverRandom, size);
+    return size;
+}
+#endif /* !defined(NO_WOLFSSL_SERVER) */
+
+
+#if !defined(NO_WOLFSSL_CLIENT)
+/* Return the amount of random bytes copied over or error case.
+ * ssl : ssl struct after handshake
+ * out : buffer to hold random bytes
+ * outSz : either 0 (return max buffer sz) or size of out buffer
+ *
+ * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information.
+ */
+size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
+                                                                   size_t outSz)
+{
+    size_t size;
+
+    /* return max size of buffer */
+    if (outSz == 0) {
+        return RAN_LEN;
+    }
+
+    if (ssl == NULL || out == NULL) {
+        return 0;
+    }
+
+    if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) {
+        WOLFSSL_MSG("Arrays struct not saved after handshake");
+        return 0;
+    }
+
+    if (outSz > RAN_LEN) {
+        size = RAN_LEN;
+    }
+    else {
+        size = outSz;
+    }
+
+    XMEMCPY(out, ssl->arrays->clientRandom, size);
+    return size;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+
+
+    unsigned long wolfSSLeay(void)
+    {
+        return SSLEAY_VERSION_NUMBER;
+    }
+
+
+    const char* wolfSSLeay_version(int type)
+    {
+        static const char* version = "SSLeay wolfSSL compatibility";
+        (void)type;
+        return version;
+    }
+
+
+#ifndef NO_MD5
+    int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
+    {
+        int ret;
+        typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1];
+        (void)sizeof(md5_test);
+
+        WOLFSSL_ENTER("MD5_Init");
+        ret = wc_InitMd5((wc_Md5*)md5);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("wolfSSL_MD5_Update");
+        ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("MD5_Final");
+        ret = wc_Md5Final((wc_Md5*)md5, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+#endif /* !NO_MD5 */
+
+
+#ifndef NO_SHA
+    int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA_Init");
+        ret = wc_InitSha((wc_Sha*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA_Update");
+        ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA_Final");
+        ret = wc_ShaFinal((wc_Sha*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha)
+    {
+        WOLFSSL_ENTER("SHA1_Init");
+        return SHA_Init(sha);
+    }
+
+
+    int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input,
+                            unsigned long sz)
+    {
+        WOLFSSL_ENTER("SHA1_Update");
+        return SHA_Update(sha, input, sz);
+    }
+
+
+    int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha)
+    {
+        WOLFSSL_ENTER("SHA1_Final");
+        return SHA_Final(input, sha);
+    }
+#endif /* !NO_SHA */
+
+#ifdef WOLFSSL_SHA224
+
+    int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA224_Init");
+        ret = wc_InitSha224((wc_Sha224*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA224_Update");
+        ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA224_Final");
+        ret = wc_Sha224Final((wc_Sha224*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA224 */
+
+
+    int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA256_Init");
+        ret = wc_InitSha256((wc_Sha256*)sha256);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input,
+                              unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA256_Update");
+        ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA256_Final");
+        ret = wc_Sha256Final((wc_Sha256*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+#ifdef WOLFSSL_SHA384
+
+    int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA384_Init");
+        ret = wc_InitSha384((wc_Sha384*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA384_Update");
+        ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA384_Final");
+        ret = wc_Sha384Final((wc_Sha384*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA384 */
+
+
+#ifdef WOLFSSL_SHA512
+
+    int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha)
+    {
+        int ret;
+
+        typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1];
+        (void)sizeof(sha_test);
+
+        WOLFSSL_ENTER("SHA512_Init");
+        ret = wc_InitSha512((wc_Sha512*)sha);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input,
+                           unsigned long sz)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA512_Update");
+        ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+
+    int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("SHA512_Final");
+        ret = wc_Sha512Final((wc_Sha512*)sha, input);
+
+        /* return 1 on success, 0 otherwise */
+        if (ret == 0)
+            return 1;
+
+        return 0;
+    }
+
+#endif /* WOLFSSL_SHA512 */
+
+    static const struct s_ent {
+        const unsigned char macType;
+        const char *name;
+    } md_tbl[] = {
+    #ifndef NO_MD4
+         {MD4, "MD4"},
+    #endif /* NO_MD4 */
+
+    #ifndef NO_MD5
+        {WC_MD5, "MD5"},
+    #endif /* NO_MD5 */
+
+    #ifndef NO_SHA
+        {WC_SHA, "SHA"},
+    #endif /* NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        {WC_SHA224, "SHA224"},
+    #endif /* WOLFSSL_SHA224 */
+    #ifndef NO_SHA256
+        {WC_SHA256, "SHA256"},
+    #endif
+
+    #ifdef WOLFSSL_SHA384
+        {WC_SHA384, "SHA384"},
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        {WC_SHA512, "SHA512"},
+    #endif /* WOLFSSL_SHA512 */
+        {0, NULL}
+    };
+
+const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name)
+{
+    static const struct alias {
+        const char *name;
+        const char *alias;
+    } alias_tbl[] =
+    {
+        {"MD4", "ssl3-md4"},
+        {"MD5", "ssl3-md5"},
+        {"SHA", "ssl3-sha1"},
+        {"SHA", "SHA1"},
+        { NULL, NULL}
+    };
+
+    const struct alias  *al;
+    const struct s_ent *ent;
+
+    for (al = alias_tbl; al->name != NULL; al++)
+        if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) {
+            name = al->name;
+            break;
+        }
+
+    for (ent = md_tbl; ent->name != NULL; ent++)
+        if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return (EVP_MD *)ent->name;
+        }
+    return NULL;
+}
+
+static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type)
+{
+    const struct s_ent *ent ;
+    WOLFSSL_ENTER("EVP_get_md");
+    for( ent = md_tbl; ent->name != NULL; ent++){
+        if(type == ent->macType) {
+            return (WOLFSSL_EVP_MD *)ent->name;
+        }
+    }
+    return (WOLFSSL_EVP_MD *)"";
+}
+
+int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
+{
+    const struct s_ent *ent ;
+    WOLFSSL_ENTER("EVP_MD_type");
+    for( ent = md_tbl; ent->name != NULL; ent++){
+        if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) {
+            return ent->macType;
+        }
+    }
+    return 0;
+}
+
+
+#ifndef NO_MD4
+
+    /* return a pointer to MD4 EVP type */
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_md4");
+        return EVP_get_digestbyname("MD4");
+    }
+
+#endif /* !NO_MD4 */
+
+
+#ifndef NO_MD5
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void)
+    {
+        WOLFSSL_ENTER("EVP_md5");
+        return EVP_get_digestbyname("MD5");
+    }
+
+#endif /* !NO_MD5 */
+
+
+#ifndef NO_SHA
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void)
+    {
+        WOLFSSL_ENTER("EVP_sha1");
+        return EVP_get_digestbyname("SHA");
+    }
+#endif /* NO_SHA */
+
+#ifdef WOLFSSL_SHA224
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void)
+    {
+        WOLFSSL_ENTER("EVP_sha224");
+        return EVP_get_digestbyname("SHA224");
+    }
+
+#endif /* WOLFSSL_SHA224 */
+
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void)
+    {
+        WOLFSSL_ENTER("EVP_sha256");
+        return EVP_get_digestbyname("SHA256");
+    }
+
+#ifdef WOLFSSL_SHA384
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void)
+    {
+        WOLFSSL_ENTER("EVP_sha384");
+        return EVP_get_digestbyname("SHA384");
+    }
+
+#endif /* WOLFSSL_SHA384 */
+
+#ifdef WOLFSSL_SHA512
+
+    const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void)
+    {
+        WOLFSSL_ENTER("EVP_sha512");
+        return EVP_get_digestbyname("SHA512");
+    }
+
+#endif /* WOLFSSL_SHA512 */
+
+
+    WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void)
+    {
+        WOLFSSL_EVP_MD_CTX* ctx;
+        WOLFSSL_ENTER("EVP_MD_CTX_new");
+        ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL,
+                                                       DYNAMIC_TYPE_OPENSSL);
+        if (ctx){
+            wolfSSL_EVP_MD_CTX_init(ctx);
+        }
+        return ctx;
+    }
+
+    WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx)
+    {
+        if (ctx) {
+            WOLFSSL_ENTER("EVP_MD_CTX_free");
+                wolfSSL_EVP_MD_CTX_cleanup(ctx);
+                XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+    }
+
+
+    /* returns the type of message digest used by the ctx */
+    int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) {
+        WOLFSSL_ENTER("EVP_MD_CTX_type");
+        return ctx->macType;
+    }
+
+
+    /* returns WOLFSSL_SUCCESS on success */
+    int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
+    {
+        return wolfSSL_EVP_MD_CTX_copy_ex(out, in);
+    }
+
+
+    /* copies structure in to the structure out
+     *
+     * returns WOLFSSL_SUCCESS on success */
+    int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in)
+    {
+        if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE;
+        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex");
+        XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX));
+        return WOLFSSL_SUCCESS;
+    }
+
+    void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init");
+        XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX));
+    }
+
+    const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx)
+    {
+        if (ctx == NULL)
+            return NULL;
+        WOLFSSL_ENTER("EVP_MD_CTX_md");
+        return (const WOLFSSL_EVP_MD *)wolfSSL_EVP_get_md(ctx->macType);
+    }
+
+    #ifndef NO_AES
+
+    #ifdef HAVE_AES_CBC
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc");
+        if (EVP_AES_128_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CBC;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc");
+        if (EVP_AES_192_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CBC;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc");
+        if (EVP_AES_256_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CBC;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_CBC */
+
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr");
+        if (EVP_AES_128_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_CTR;
+    }
+    #endif /* WOLFSSL_AES_2128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr");
+        if (EVP_AES_192_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_CTR;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr");
+        if (EVP_AES_256_CTR == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_CTR;
+    }
+    #endif /* WOLFSSL_AES_256 */
+
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb");
+        if (EVP_AES_128_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_128_ECB;
+    }
+    #endif /* WOLFSSL_AES_128 */
+
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb");
+        if (EVP_AES_192_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_192_ECB;
+    }
+    #endif /* WOLFSSL_AES_192*/
+
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb");
+        if (EVP_AES_256_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_AES_256_ECB;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* NO_AES */
+
+#ifndef NO_DES3
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_cbc");
+        if (EVP_DES_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_CBC;
+    }
+#ifdef WOLFSSL_DES_ECB
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ecb");
+        if (EVP_DES_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_ECB;
+    }
+#endif
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc");
+        if (EVP_DES_EDE3_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_EDE3_CBC;
+    }
+#ifdef WOLFSSL_DES_ECB
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb");
+        if (EVP_DES_EDE3_ECB == NULL)
+            wolfSSL_EVP_init();
+        return EVP_DES_EDE3_ECB;
+    }
+#endif
+#endif /* NO_DES3 */
+
+#ifndef NO_RC4
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void)
+    {
+        static const char* type = "ARC4";
+        WOLFSSL_ENTER("wolfSSL_EVP_rc4");
+        return type;
+    }
+#endif
+
+#ifdef HAVE_IDEA
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc");
+        if (EVP_IDEA_CBC == NULL)
+            wolfSSL_EVP_init();
+        return EVP_IDEA_CBC;
+    }
+#endif
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void)
+    {
+        static const char* type = "NULL";
+        WOLFSSL_ENTER("wolfSSL_EVP_enc_null");
+        return type;
+    }
+
+
+    int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_MD_CTX_cleanup");
+        ForceZero(ctx, sizeof(*ctx));
+        ctx->macType = 0xFF;
+        return 1;
+    }
+
+
+
+    void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_CTX_init");
+        if (ctx) {
+            ctx->cipherType = 0xff;   /* no init */
+            ctx->keyLen     = 0;
+            ctx->enc        = 1;      /* start in encrypt mode */
+        }
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup");
+        if (ctx) {
+            ctx->cipherType = 0xff;  /* no more init */
+            ctx->keyLen     = 0;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
+    int  wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                               const WOLFSSL_EVP_CIPHER* type, const byte* key,
+                               const byte* iv, int enc)
+    {
+        int ret = 0;
+        (void)key;
+        (void)iv;
+        (void)enc;
+
+        WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
+        if (ctx == NULL) {
+            WOLFSSL_MSG("no ctx");
+            return 0;   /* failure */
+        }
+
+        if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) {
+            WOLFSSL_MSG("no type set");
+            return 0;   /* failure */
+        }
+        if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){
+            ctx->bufUsed = 0;
+            ctx->lastUsed = 0;
+            ctx->flags   = 0;
+        }
+#ifndef NO_AES
+    #ifdef HAVE_AES_CBC
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CBC_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CBC");
+            ctx->cipherType = AES_128_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CBC");
+            ctx->cipherType = AES_192_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CBC");
+            ctx->cipherType = AES_256_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                                ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetKey() failed");
+                    return ret;
+                }
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0){
+                    WOLFSSL_MSG("wc_AesSetIV() failed");
+                    return ret;
+                }
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AES_CBC */
+#ifdef WOLFSSL_AES_COUNTER
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_CTR");
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->cipherType = AES_128_CTR_TYPE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+              ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                    AES_ENCRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_CTR");
+            ctx->cipherType = AES_192_CTR_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                      AES_ENCRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CTR_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_CTR");
+            ctx->cipherType = AES_256_CTR_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CTR_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv,
+                      AES_ENCRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+            if (iv && key == NULL) {
+                ret = wc_AesSetIV(&ctx->cipher.aes, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        #endif /* WOLFSSL_AES_256 */
+#endif /* WOLFSSL_AES_COUNTER */
+        #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_ECB_TYPE ||
+            (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_128_ECB");
+            ctx->cipherType = AES_128_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 16;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+            }
+            if (ret != 0)
+                return ret;
+        }
+        #endif /* WOLFSSL_AES_128 */
+        #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_192_ECB");
+            ctx->cipherType = AES_192_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                      ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+            }
+            if (ret != 0)
+                return ret;
+        }
+        #endif /* WOLFSSL_AES_192 */
+        #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_AES_256_ECB");
+            ctx->cipherType = AES_256_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 32;
+            ctx->block_size = AES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+              ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL,
+                    ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION);
+            }
+            if (ret != 0)
+                return ret;
+        }
+        #endif /* WOLFSSL_AES_256 */
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+        if (ctx->cipherType == DES_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_CBC");
+            ctx->cipherType = DES_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 8;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des_SetKey(&ctx->cipher.des, key, iv,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+
+            if (iv && key == NULL)
+                wc_Des_SetIV(&ctx->cipher.des, iv);
+        }
+#ifdef WOLFSSL_DES_ECB
+        else if (ctx->cipherType == DES_ECB_TYPE ||
+                 (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_ECB");
+            ctx->cipherType = DES_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 8;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                WOLFSSL_MSG("Des_SetKey");
+                ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+#endif
+        else if (ctx->cipherType == DES_EDE3_CBC_TYPE ||
+                 (type &&
+                  XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_EDE3_CBC");
+            ctx->cipherType = DES_EDE3_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+
+            if (iv && key == NULL) {
+                ret = wc_Des3_SetIV(&ctx->cipher.des3, iv);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+        else if (ctx->cipherType == DES_EDE3_ECB_TYPE ||
+                 (type &&
+                  XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_DES_EDE3_ECB");
+            ctx->cipherType = DES_EDE3_ECB_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_ECB_MODE;
+            ctx->keyLen     = 24;
+            ctx->block_size = DES_BLOCK_SIZE;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL,
+                          ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+        }
+#endif /* NO_DES3 */
+#ifndef NO_RC4
+        if (ctx->cipherType == ARC4_TYPE || (type &&
+                                     XSTRNCMP(type, "ARC4", 4) == 0)) {
+            WOLFSSL_MSG("ARC4");
+            ctx->cipherType = ARC4_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_STREAM_CIPHER;
+            ctx->block_size = 1;
+            if (ctx->keyLen == 0)  /* user may have already set */
+                ctx->keyLen = 16;  /* default to 128 */
+            if (key)
+                wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen);
+        }
+#endif /* NO_RC4 */
+#ifdef HAVE_IDEA
+        if (ctx->cipherType == IDEA_CBC_TYPE ||
+                 (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) {
+            WOLFSSL_MSG("EVP_IDEA_CBC");
+            ctx->cipherType = IDEA_CBC_TYPE;
+            ctx->flags     &= ~WOLFSSL_EVP_CIPH_MODE;
+            ctx->flags     |= WOLFSSL_EVP_CIPH_CBC_MODE;
+            ctx->keyLen     = IDEA_KEY_SIZE;
+            ctx->block_size = 8;
+            if (enc == 0 || enc == 1)
+                ctx->enc = enc ? 1 : 0;
+            if (key) {
+                ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen,
+                                    iv, ctx->enc ? IDEA_ENCRYPTION :
+                                                   IDEA_DECRYPTION);
+                if (ret != 0)
+                    return ret;
+            }
+
+            if (iv && key == NULL)
+                wc_IdeaSetIV(&ctx->cipher.idea, iv);
+        }
+#endif /* HAVE_IDEA */
+        if (ctx->cipherType == NULL_CIPHER_TYPE || (type &&
+                                     XSTRNCMP(type, "NULL", 4) == 0)) {
+            WOLFSSL_MSG("NULL cipher");
+            ctx->cipherType = NULL_CIPHER_TYPE;
+            ctx->keyLen = 0;
+            ctx->block_size = 16;
+        }
+        (void)ret; /* remove warning. If execution reaches this point, ret=0 */
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length");
+        if (ctx)
+            return ctx->keyLen;
+
+        return 0;   /* failure */
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                             int keylen)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length");
+        if (ctx)
+            ctx->keyLen = keylen;
+        else
+            return 0;  /* failure */
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
+                          word32 len)
+    {
+        int ret = 0;
+        WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
+
+        if (ctx == NULL || dst == NULL || src == NULL) {
+            WOLFSSL_MSG("Bad function argument");
+            return 0;  /* failure */
+        }
+
+        if (ctx->cipherType == 0xff) {
+            WOLFSSL_MSG("no init");
+            return 0;  /* failure */
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+#ifdef HAVE_AES_CBC
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                if (ctx->enc)
+                    ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* HAVE_AES_CBC */
+#ifdef HAVE_AES_ECB
+            case AES_128_ECB_TYPE :
+            case AES_192_ECB_TYPE :
+            case AES_256_ECB_TYPE :
+                WOLFSSL_MSG("AES ECB");
+                if (ctx->enc)
+                    ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len);
+                else
+                    ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                    WOLFSSL_MSG("AES CTR");
+                    ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len);
+                break;
+#endif /* WOLFSSL_AES_COUNTER */
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                if (ctx->enc)
+                    wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len);
+                else
+                    wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len);
+                break;
+            case DES_EDE3_CBC_TYPE :
+                if (ctx->enc)
+                    ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len);
+                else
+                    ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len);
+                break;
+#ifdef WOLFSSL_DES_ECB
+            case DES_ECB_TYPE :
+                ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len);
+                break;
+            case DES_EDE3_ECB_TYPE :
+                ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len);
+                break;
+#endif
+#endif /* !NO_DES3 */
+
+#ifndef NO_RC4
+            case ARC4_TYPE :
+                wc_Arc4Process(&ctx->cipher.arc4, dst, src, len);
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                if (ctx->enc)
+                    wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len);
+                else
+                    wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len);
+                break;
+#endif
+            case NULL_CIPHER_TYPE :
+                XMEMCPY(dst, src, len);
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return 0;  /* failure */
+            }
+        }
+
+        if (ret != 0) {
+            WOLFSSL_MSG("wolfSSL_EVP_Cipher failure");
+            return 0;  /* failure */
+        }
+
+        WOLFSSL_MSG("wolfSSL_EVP_Cipher success");
+        return WOLFSSL_SUCCESS;  /* success */
+    }
+
+#define WOLFSSL_EVP_INCLUDED
+#include "wolfcrypt/src/evp.c"
+
+
+    /* store for external read of iv, WOLFSSL_SUCCESS on success */
+    int  wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+        WOLFSSL_ENTER("wolfSSL_StoreExternalIV");
+
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Bad function argument");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                break;
+
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                WOLFSSL_MSG("AES CTR");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                break;
+#endif /* WOLFSSL_AES_COUNTER */
+
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                WOLFSSL_MSG("DES CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE);
+                break;
+
+            case DES_EDE3_CBC_TYPE :
+                WOLFSSL_MSG("DES EDE3 CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                WOLFSSL_MSG("IDEA CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE);
+                break;
+#endif
+            case ARC4_TYPE :
+                WOLFSSL_MSG("ARC4");
+                break;
+
+            case NULL_CIPHER_TYPE :
+                WOLFSSL_MSG("NULL");
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* set internal IV from external, WOLFSSL_SUCCESS on success */
+    int  wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx)
+    {
+
+        WOLFSSL_ENTER("wolfSSL_SetInternalIV");
+
+        if (ctx == NULL) {
+            WOLFSSL_MSG("Bad function argument");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        switch (ctx->cipherType) {
+
+#ifndef NO_AES
+            case AES_128_CBC_TYPE :
+            case AES_192_CBC_TYPE :
+            case AES_256_CBC_TYPE :
+                WOLFSSL_MSG("AES CBC");
+                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+                break;
+
+#ifdef WOLFSSL_AES_COUNTER
+            case AES_128_CTR_TYPE :
+            case AES_192_CTR_TYPE :
+            case AES_256_CTR_TYPE :
+                WOLFSSL_MSG("AES CTR");
+                XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE);
+                break;
+#endif
+
+#endif /* NO_AES */
+
+#ifndef NO_DES3
+            case DES_CBC_TYPE :
+                WOLFSSL_MSG("DES CBC");
+                XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE);
+                break;
+
+            case DES_EDE3_CBC_TYPE :
+                WOLFSSL_MSG("DES EDE3 CBC");
+                XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE);
+                break;
+#endif
+
+#ifdef HAVE_IDEA
+            case IDEA_CBC_TYPE :
+                WOLFSSL_MSG("IDEA CBC");
+                XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE);
+                break;
+#endif
+            case ARC4_TYPE :
+                WOLFSSL_MSG("ARC4");
+                break;
+
+            case NULL_CIPHER_TYPE :
+                WOLFSSL_MSG("NULL");
+                break;
+
+            default: {
+                WOLFSSL_MSG("bad type");
+                return WOLFSSL_FATAL_ERROR;
+            }
+        }
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx,
+                               const WOLFSSL_EVP_MD* type)
+    {
+        int ret = WOLFSSL_SUCCESS;
+
+        WOLFSSL_ENTER("EVP_DigestInit");
+
+        if (ctx == NULL || type == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        /* compile-time validation of ASYNC_CTX_SIZE */
+        typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ?
+                                                                        1 : -1];
+        (void)sizeof(async_test);
+    #endif
+
+        if (XSTRNCMP(type, "SHA256", 6) == 0) {
+             ctx->macType = WC_SHA256;
+             ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256));
+        }
+    #ifdef WOLFSSL_SHA224
+        else if (XSTRNCMP(type, "SHA224", 6) == 0) {
+             ctx->macType = WC_SHA224;
+             ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224));
+        }
+    #endif
+    #ifdef WOLFSSL_SHA384
+        else if (XSTRNCMP(type, "SHA384", 6) == 0) {
+             ctx->macType = WC_SHA384;
+             ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384));
+        }
+    #endif
+    #ifdef WOLFSSL_SHA512
+        else if (XSTRNCMP(type, "SHA512", 6) == 0) {
+             ctx->macType = WC_SHA512;
+             ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512));
+        }
+    #endif
+    #ifndef NO_MD4
+        else if (XSTRNCMP(type, "MD4", 3) == 0) {
+            ctx->macType = MD4;
+            wolfSSL_MD4_Init(&(ctx->hash.digest.md4));
+        }
+    #endif
+    #ifndef NO_MD5
+        else if (XSTRNCMP(type, "MD5", 3) == 0) {
+            ctx->macType = WC_MD5;
+            ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5));
+        }
+    #endif
+    #ifndef NO_SHA
+        /* has to be last since would pick or 224, 256, 384, or 512 too */
+        else if (XSTRNCMP(type, "SHA", 3) == 0) {
+             ctx->macType = WC_SHA;
+             ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha));
+        }
+    #endif /* NO_SHA */
+        else
+             return BAD_FUNC_ARG;
+
+        return ret;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */
+    int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data,
+                                size_t sz)
+    {
+        WOLFSSL_ENTER("EVP_DigestUpdate");
+
+        switch (ctx->macType) {
+#ifndef NO_MD4
+            case MD4:
+                wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_MD5
+            case WC_MD5:
+                wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_SHA
+            case WC_SHA:
+                wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data,
+                                  (unsigned long)sz);
+                break;
+#endif
+#ifdef WOLFSSL_SHA224
+            case WC_SHA224:
+                wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif
+#ifndef NO_SHA256
+            case WC_SHA256:
+                wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif /* !NO_SHA256 */
+#ifdef WOLFSSL_SHA384
+            case WC_SHA384:
+                wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif
+#ifdef WOLFSSL_SHA512
+            case WC_SHA512:
+                wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data,
+                                     (unsigned long)sz);
+                break;
+#endif /* WOLFSSL_SHA512 */
+            default:
+                return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
+                               unsigned int* s)
+    {
+        WOLFSSL_ENTER("EVP_DigestFinal");
+        switch (ctx->macType) {
+#ifndef NO_MD4
+            case MD4:
+                wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash);
+                if (s) *s = MD4_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_MD5
+            case WC_MD5:
+                wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash);
+                if (s) *s = WC_MD5_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_SHA
+            case WC_SHA:
+                wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA_DIGEST_SIZE;
+                break;
+#endif
+#ifdef WOLFSSL_SHA224
+            case WC_SHA224:
+                wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA224_DIGEST_SIZE;
+                break;
+#endif
+#ifndef NO_SHA256
+            case WC_SHA256:
+                wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA256_DIGEST_SIZE;
+                break;
+#endif /* !NO_SHA256 */
+#ifdef WOLFSSL_SHA384
+            case WC_SHA384:
+                wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA384_DIGEST_SIZE;
+                break;
+#endif
+#ifdef WOLFSSL_SHA512
+            case WC_SHA512:
+                wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash);
+                if (s) *s = WC_SHA512_DIGEST_SIZE;
+                break;
+#endif /* WOLFSSL_SHA512 */
+            default:
+                return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* WOLFSSL_SUCCESS on ok */
+    int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md,
+                                   unsigned int* s)
+    {
+        WOLFSSL_ENTER("EVP_DigestFinal_ex");
+        return EVP_DigestFinal(ctx, md, s);
+    }
+
+
+    unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key,
+                                int key_len, const unsigned char* d, int n,
+                                unsigned char* md, unsigned int* md_len)
+    {
+        int type;
+        int mdlen;
+        unsigned char* ret = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        Hmac* hmac = NULL;
+#else
+        Hmac  hmac[1];
+#endif
+        void* heap = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_HMAC");
+        if (!md) {
+            WOLFSSL_MSG("Static buffer not supported, pass in md buffer");
+            return NULL;  /* no static buffer support */
+        }
+
+#ifndef NO_MD5
+        if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
+            type = WC_MD5;
+            mdlen = WC_MD5_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA224
+        if (XSTRNCMP(evp_md, "SHA224", 6) == 0) {
+            type = WC_SHA224;
+            mdlen = WC_SHA224_DIGEST_SIZE;
+        } else
+#endif
+#ifndef NO_SHA256
+        if (XSTRNCMP(evp_md, "SHA256", 6) == 0) {
+            type = WC_SHA256;
+            mdlen = WC_SHA256_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA384
+        if (XSTRNCMP(evp_md, "SHA384", 6) == 0) {
+            type = WC_SHA384;
+            mdlen = WC_SHA384_DIGEST_SIZE;
+        } else
+#endif
+#ifdef WOLFSSL_SHA512
+        if (XSTRNCMP(evp_md, "SHA512", 6) == 0) {
+            type = WC_SHA512;
+            mdlen = WC_SHA512_DIGEST_SIZE;
+        } else
+#endif
+#ifndef NO_SHA
+        if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
+            type = WC_SHA;
+            mdlen = WC_SHA_DIGEST_SIZE;
+        } else
+#endif
+        {
+            return NULL;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
+        if (hmac == NULL)
+            return NULL;
+    #endif
+
+        if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) {
+            if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) {
+                if (wc_HmacUpdate(hmac, d, n) == 0) {
+                    if (wc_HmacFinal(hmac, md) == 0) {
+                        if (md_len)
+                            *md_len = mdlen;
+                        ret = md;
+                    }
+                }
+            }
+            wc_HmacFree(hmac);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
+    #endif
+
+        (void)evp_md;
+        return ret;
+    }
+
+    void wolfSSL_ERR_clear_error(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
+
+#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)
+        wc_ClearErrorNodes();
+#endif
+    }
+
+
+    /* frees all nodes in the current threads error queue
+     *
+     * id  thread id. ERR_remove_state is depriciated and id is ignored. The
+     *     current threads queue will be free'd.
+     */
+    void wolfSSL_ERR_remove_state(unsigned long id)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_remove_state");
+        (void)id;
+        if (wc_ERR_remove_state() != 0) {
+            WOLFSSL_MSG("Error with removing the state");
+        }
+    }
+
+
+    int wolfSSL_RAND_status(void)
+    {
+        return WOLFSSL_SUCCESS;  /* wolfCrypt provides enough seed internally */
+    }
+
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_RAND_add(const void* add, int len, double entropy)
+    {
+        (void)add;
+        (void)len;
+        (void)entropy;
+        WOLFSSL_STUB("RAND_add");
+        /* wolfSSL seeds/adds internally, use explicit RNG if you want
+           to take control */
+    }
+    #endif
+
+#ifndef NO_DES3
+    /* 0 on ok */
+    int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key,
+                              WOLFSSL_DES_key_schedule* schedule)
+    {
+        WOLFSSL_ENTER("wolfSSL_DES_key_sched");
+
+        if (key == NULL || schedule == NULL) {
+            WOLFSSL_MSG("Null argument passed in");
+        }
+        else {
+            XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock));
+        }
+
+        return 0;
+    }
+
+
+    /* intended to behave similar to Kerberos mit_des_cbc_cksum
+     * return the last 4 bytes of cipher text */
+    WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in,
+            WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc,
+            WOLFSSL_const_DES_cblock* iv)
+    {
+        WOLFSSL_DES_LONG ret;
+        unsigned char* tmp;
+        unsigned char* data   = (unsigned char*)in;
+        long           dataSz = length;
+        byte dynamicFlag = 0; /* when padding the buffer created needs free'd */
+
+        WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum");
+
+        if (in == NULL || out == NULL || sc == NULL || iv == NULL) {
+            WOLFSSL_MSG("Bad argument passed in");
+            return 0;
+        }
+
+        /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */
+        if (dataSz % DES_BLOCK_SIZE) {
+            dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE);
+            data = (unsigned char*)XMALLOC(dataSz, NULL,
+                                           DYNAMIC_TYPE_TMP_BUFFER);
+            if (data == NULL) {
+                WOLFSSL_MSG("Issue creating temporary buffer");
+                return 0;
+            }
+            dynamicFlag = 1; /* set to free buffer at end */
+            XMEMCPY(data, in, length);
+            XMEMSET(data + length, 0, dataSz - length); /* padding */
+        }
+
+        tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (tmp == NULL) {
+            WOLFSSL_MSG("Issue creating temporary buffer");
+            if (dynamicFlag == 1) {
+                XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            }
+            return 0;
+        }
+
+        wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc,
+                (WOLFSSL_DES_cblock*)iv, 1);
+        XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE),
+                DES_BLOCK_SIZE);
+
+        ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)|
+               ((*((unsigned char*)out + 5) & 0xFF) << 16)|
+               ((*((unsigned char*)out + 6) & 0xFF) << 8) |
+               (*((unsigned char*)out + 7) & 0xFF));
+
+        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (dynamicFlag == 1) {
+            XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        return ret;
+    }
+
+
+    void wolfSSL_DES_cbc_encrypt(const unsigned char* input,
+                                 unsigned char* output, long length,
+                                 WOLFSSL_DES_key_schedule* schedule,
+                                 WOLFSSL_DES_cblock* ivec, int enc)
+    {
+        Des myDes;
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long  blk;
+
+        WOLFSSL_ENTER("DES_cbc_encrypt");
+
+        /* OpenSSL compat, no ret */
+        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+        lb_sz = length%DES_BLOCK_SIZE;
+        blk   = length/DES_BLOCK_SIZE;
+
+        if (enc){
+            wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+                wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            }
+        }
+        else {
+            wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
+                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+            }
+        }
+    }
+
+
+    /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */
+    void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
+                                      unsigned char* output, long sz,
+                                      WOLFSSL_DES_key_schedule* ks1,
+                                      WOLFSSL_DES_key_schedule* ks2,
+                                      WOLFSSL_DES_key_schedule* ks3,
+                                      WOLFSSL_DES_cblock* ivec, int enc)
+    {
+        Des3 des;
+        byte key[24];/* EDE uses 24 size key */
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long  blk;
+
+        WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt");
+
+        XMEMSET(key, 0, sizeof(key));
+        XMEMCPY(key, *ks1, DES_BLOCK_SIZE);
+        XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE);
+        XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE);
+        lb_sz = sz%DES_BLOCK_SIZE;
+        blk   = sz/DES_BLOCK_SIZE;
+        if (enc) {
+            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION);
+            wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+sz-lb_sz, lb_sz);
+                wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            }
+        }
+        else {
+            wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION);
+            wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE);
+                XMEMCPY(output+sz-lb_sz, lastblock, lb_sz);
+            }
+        }
+    }
+
+
+    /* correctly sets ivec for next call */
+    void wolfSSL_DES_ncbc_encrypt(const unsigned char* input,
+                     unsigned char* output, long length,
+                     WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec,
+                     int enc)
+    {
+        Des myDes;
+        byte lastblock[DES_BLOCK_SIZE];
+        int  lb_sz;
+        long  blk;
+
+        WOLFSSL_ENTER("DES_ncbc_encrypt");
+
+        /* OpenSSL compat, no ret */
+        wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc);
+        lb_sz = length%DES_BLOCK_SIZE;
+        blk   = length/DES_BLOCK_SIZE;
+        if (enc){
+            wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                XMEMSET(lastblock, 0, DES_BLOCK_SIZE);
+                XMEMCPY(lastblock, input+length-lb_sz, lb_sz);
+                wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE,
+                    lastblock, (word32)DES_BLOCK_SIZE);
+            }
+        } else {
+            wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE);
+            if(lb_sz){
+                wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE);
+                XMEMCPY(output+length-lb_sz, lastblock, lb_sz);
+            }
+        }
+
+        XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock));
+    }
+
+#endif /* NO_DES3 */
+
+
+    void wolfSSL_ERR_free_strings(void)
+    {
+        /* handled internally */
+    }
+
+
+    void wolfSSL_EVP_cleanup(void)
+    {
+        /* nothing to do here */
+    }
+
+
+    void wolfSSL_cleanup_all_ex_data(void)
+    {
+        /* nothing to do here */
+    }
+
+    int wolfSSL_clear(WOLFSSL* ssl)
+    {
+        if (ssl == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        ssl->options.isClosed = 0;
+        ssl->options.connReset = 0;
+        ssl->options.sentNotify = 0;
+
+        ssl->options.serverState = NULL_STATE;
+        ssl->options.clientState = NULL_STATE;
+        ssl->options.connectState = CONNECT_BEGIN;
+        ssl->options.acceptState  = ACCEPT_BEGIN;
+        ssl->options.handShakeState  = NULL_STATE;
+        ssl->options.handShakeDone = 0;
+        /* ssl->options.processReply = doProcessInit; */
+
+        ssl->keys.encryptionOn = 0;
+        XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
+
+        if (ssl->hsHashes != NULL) {
+#ifndef NO_OLD_TLS
+#ifndef NO_MD5
+            wc_InitMd5(&ssl->hsHashes->hashMd5);
+#endif
+#ifndef NO_SHA
+            if (wc_InitSha(&ssl->hsHashes->hashSha) != 0)
+                return WOLFSSL_FAILURE;
+#endif
+#endif
+#ifndef NO_SHA256
+            if (wc_InitSha256(&ssl->hsHashes->hashSha256) != 0)
+                return WOLFSSL_FAILURE;
+#endif
+#ifdef WOLFSSL_SHA384
+            if (wc_InitSha384(&ssl->hsHashes->hashSha384) != 0)
+                return WOLFSSL_FAILURE;
+#endif
+#ifdef WOLFSSL_SHA512
+            if (wc_InitSha512(&ssl->hsHashes->hashSha512) != 0)
+                return WOLFSSL_FAILURE;
+#endif
+        }
+#ifdef SESSION_CERTS
+        ssl->session.chain.count = 0;
+#endif
+#ifdef KEEP_PEER_CERT
+        FreeX509(&ssl->peerCert);
+        InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
+    {
+        word32 tmptime;
+        if (!ses || t < 0)
+            return BAD_FUNC_ARG;
+
+        tmptime = t & 0xFFFFFFFF;
+
+        ses->timeout = tmptime;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
+    {
+        /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
+
+        WOLFSSL_ENTER("SSL_CTX_set_mode");
+        if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE)
+            ctx->partialWrite = 1;
+
+        return mode;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
+    {
+        /* TODO: */
+        (void)ssl;
+        WOLFSSL_STUB("SSL_get_mode");
+        return 0;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
+    {
+        /* TODO: */
+        (void)ctx;
+        WOLFSSL_STUB("SSL_CTX_get_mode");
+        return 0;
+    }
+    #endif
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m)
+    {
+        /* TODO: maybe? */
+        (void)ctx;
+        (void)m;
+        WOLFSSL_STUB("SSL_CTX_set_default_read_ahead");
+    }
+    #endif
+
+
+    /* Storing app session context id, this value is inherited by WOLFSSL
+     * objects created from WOLFSSL_CTX. Any session that is imported with a
+     * different session context id will be rejected.
+     *
+     * ctx         structure to set context in
+     * sid_ctx     value of context to set
+     * sid_ctx_len length of sid_ctx buffer
+     *
+     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+     */
+    int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx,
+                                           const unsigned char* sid_ctx,
+                                           unsigned int sid_ctx_len)
+    {
+        WOLFSSL_ENTER("SSL_CTX_set_session_id_context");
+
+        /* No application specific context needed for wolfSSL */
+        if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) {
+            return SSL_FAILURE;
+        }
+        XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len);
+        ctx->sessionCtxSz = (byte)sid_ctx_len;
+
+        return SSL_SUCCESS;
+    }
+
+
+
+    /* Storing app session context id. Any session that is imported with a
+     * different session context id will be rejected.
+     *
+     * ssl  structure to set context in
+     * id   value of context to set
+     * len  length of sid_ctx buffer
+     *
+     * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing
+     */
+    int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id,
+                                   unsigned int len)
+    {
+        WOLFSSL_STUB("wolfSSL_set_session_id_context");
+
+        if (len > ID_LEN || ssl == NULL || id == NULL) {
+            return SSL_FAILURE;
+        }
+        XMEMCPY(ssl->sessionCtx, id, len);
+        ssl->sessionCtxSz = (byte)len;
+
+        return SSL_SUCCESS;
+    }
+
+
+    long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx)
+    {
+        (void)ctx;
+        #ifndef NO_SESSION_CACHE
+            return SESSIONS_PER_ROW * SESSION_ROWS;
+        #else
+            return 0;
+        #endif
+    }
+
+
+    /* returns the unsigned error value and increments the pointer into the
+     * error queue.
+     *
+     * file  pointer to file name
+     * line  gets set to line number of error when not NULL
+     */
+    unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
+    {
+    #ifdef DEBUG_WOLFSSL
+        int ret = wc_PullErrorNode(file, NULL, line);
+        if (ret < 0) {
+            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+            WOLFSSL_MSG("Issue getting error node");
+            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
+            ret = 0 - ret; /* return absolute value of error */
+
+            /* panic and try to clear out nodes */
+            wc_ClearErrorNodes();
+        }
+        return (unsigned long)ret;
+    #else
+        (void)file;
+        (void)line;
+
+        return 0;
+    #endif
+    }
+
+
+#ifdef DEBUG_WOLFSSL
+    static const char WOLFSSL_SYS_ACCEPT_T[]  = "accept";
+    static const char WOLFSSL_SYS_BIND_T[]    = "bind";
+    static const char WOLFSSL_SYS_CONNECT_T[] = "connect";
+    static const char WOLFSSL_SYS_FOPEN_T[]   = "fopen";
+    static const char WOLFSSL_SYS_FREAD_T[]   = "fread";
+    static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo";
+    static const char WOLFSSL_SYS_GETSOCKOPT_T[]  = "getsockopt";
+    static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname";
+    static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname";
+    static const char WOLFSSL_SYS_GETNAMEINFO_T[]   = "getnameinfo";
+    static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname";
+    static const char WOLFSSL_SYS_IOCTLSOCKET_T[]   = "ioctlsocket";
+    static const char WOLFSSL_SYS_LISTEN_T[]        = "listen";
+    static const char WOLFSSL_SYS_OPENDIR_T[]       = "opendir";
+    static const char WOLFSSL_SYS_SETSOCKOPT_T[]    = "setsockopt";
+    static const char WOLFSSL_SYS_SOCKET_T[]        = "socket";
+
+    /* switch with int mapped to function name for compatibility */
+    static const char* wolfSSL_ERR_sys_func(int fun)
+    {
+        switch (fun) {
+            case WOLFSSL_SYS_ACCEPT:      return WOLFSSL_SYS_ACCEPT_T;
+            case WOLFSSL_SYS_BIND:        return WOLFSSL_SYS_BIND_T;
+            case WOLFSSL_SYS_CONNECT:     return WOLFSSL_SYS_CONNECT_T;
+            case WOLFSSL_SYS_FOPEN:       return WOLFSSL_SYS_FOPEN_T;
+            case WOLFSSL_SYS_FREAD:       return WOLFSSL_SYS_FREAD_T;
+            case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T;
+            case WOLFSSL_SYS_GETSOCKOPT:  return WOLFSSL_SYS_GETSOCKOPT_T;
+            case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T;
+            case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T;
+            case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T;
+            case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T;
+            case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T;
+            case WOLFSSL_SYS_LISTEN:      return WOLFSSL_SYS_LISTEN_T;
+            case WOLFSSL_SYS_OPENDIR:     return WOLFSSL_SYS_OPENDIR_T;
+            case WOLFSSL_SYS_SETSOCKOPT:  return WOLFSSL_SYS_SETSOCKOPT_T;
+            case WOLFSSL_SYS_SOCKET:      return WOLFSSL_SYS_SOCKET_T;
+            default:
+                return "NULL";
+        }
+    }
+#endif /* DEBUG_WOLFSSL */
+
+
+    /* @TODO when having an error queue this needs to push to the queue */
+    void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
+            int line)
+    {
+        WOLFSSL_ENTER("wolfSSL_ERR_put_error");
+
+        #ifndef DEBUG_WOLFSSL
+        (void)fun;
+        (void)err;
+        (void)file;
+        (void)line;
+        WOLFSSL_MSG("Not compiled in debug mode");
+        #else
+        WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line,
+            file, NULL);
+        #endif
+        (void)lib;
+    }
+
+
+    /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
+     * more flexability.
+     *
+     * file  output pointer to file where error happened
+     * line  output to line number of error
+     * data  output data. Is a string if ERR_TXT_STRING flag is used
+     * flags bit flag to adjust data output
+     *
+     * Returns the error value or 0 if no errors are in the queue
+     */
+    unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
+                                                  const char** data, int *flags)
+    {
+        int ret;
+
+        WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data");
+
+        if (flags != NULL) {
+            if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) {
+                ret = wc_PullErrorNode(file, data, line);
+                if (ret < 0) {
+                    if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+                    WOLFSSL_MSG("Error with pulling error node!");
+                    WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+                    ret = 0 - ret; /* return absolute value of error */
+
+                    /* panic and try to clear out nodes */
+                    wc_ClearErrorNodes();
+                }
+
+                return (unsigned long)ret;
+            }
+        }
+
+        ret = wc_PullErrorNode(file, NULL, line);
+        if (ret < 0) {
+            if (ret == BAD_STATE_E) return 0; /* no errors in queue */
+            WOLFSSL_MSG("Error with pulling error node!");
+            WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+            ret = 0 - ret; /* return absolute value of error */
+
+            /* panic and try to clear out nodes */
+            wc_ClearErrorNodes();
+        }
+
+        return (unsigned long)ret;
+    }
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef KEEP_PEER_CERT
+    #ifdef SESSION_CERTS
+    /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
+     *
+     * x509  WOLFSSL_X509 object to decode into.
+     * in    X509 DER data.
+     * len   Length of the X509 DER data.
+     * returns the new certificate on success, otherwise NULL.
+     */
+    static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
+    {
+        int          ret;
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert = NULL;
+    #else
+        DecodedCert  cert[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return MEMORY_E;
+    #endif
+
+        /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
+         */
+        InitDecodedCert(cert, (byte*)in, len, NULL);
+        if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) {
+            InitX509(x509, 0, NULL);
+            ret = CopyDecodedToX509(x509, cert);
+            FreeDecodedCert(cert);
+        }
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+
+        return ret;
+    }
+    #endif /* SESSION_CERTS */
+
+
+    WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
+    {
+        WOLFSSL_ENTER("SSL_get_peer_certificate");
+        if (ssl->peerCert.issuer.sz)
+            return &ssl->peerCert;
+#ifdef SESSION_CERTS
+        else if (ssl->session.chain.count > 0) {
+            if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer,
+                    ssl->session.chain.certs[0].length) == 0) {
+                return &ssl->peerCert;
+            }
+        }
+#endif
+        return 0;
+    }
+
+#endif /* KEEP_PEER_CERT */
+
+
+#ifndef NO_CERTS
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+    defined(OPENSSL_EXTRA)  || defined(OPENSSL_EXTRA_X509_SMALL)
+
+/* user externally called free X509, if dynamic go ahead with free, otherwise
+ * don't */
+static void ExternalFreeX509(WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("ExternalFreeX509");
+    if (x509) {
+        if (x509->dynamicMemory) {
+            FreeX509(x509);
+            XFREE(x509, x509->heap, DYNAMIC_TYPE_X509);
+        } else {
+            WOLFSSL_MSG("free called on non dynamic object, not freeing");
+        }
+    }
+}
+
+/* Frees an external WOLFSSL_X509 structure */
+void wolfSSL_X509_free(WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_FreeX509");
+    ExternalFreeX509(x509);
+}
+
+
+/* copy name into in buffer, at most sz bytes, if buffer is null will
+   malloc buffer, call responsible for freeing                     */
+char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
+{
+    int copySz;
+
+    if (name == NULL) {
+        WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL");
+        return NULL;
+    }
+
+    copySz = min(sz, name->sz);
+
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
+    if (!name->sz) return in;
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (!in ) return in;
+        copySz = name->sz;
+    #endif
+    }
+
+    if (copySz <= 0)
+        return in;
+
+    XMEMCPY(in, name->name, copySz - 1);
+    in[copySz - 1] = 0;
+
+    return in;
+}
+
+
+/* Wraps wolfSSL_X509_d2i
+ *
+ * returns a WOLFSSL_X509 structure pointer on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in,
+        int len)
+{
+    return wolfSSL_X509_d2i(x509, *in, len);
+}
+
+
+WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
+{
+    WOLFSSL_X509 *newX509 = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_d2i");
+
+    if (in != NULL && len != 0) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert = NULL;
+    #else
+        DecodedCert  cert[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert == NULL)
+            return NULL;
+    #endif
+
+        InitDecodedCert(cert, (byte*)in, len, NULL);
+        if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+            newX509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                             DYNAMIC_TYPE_X509);
+            if (newX509 != NULL) {
+                InitX509(newX509, 1, NULL);
+                if (CopyDecodedToX509(newX509, cert) != 0) {
+                    XFREE(newX509, NULL, DYNAMIC_TYPE_X509);
+                    newX509 = NULL;
+                }
+            }
+        }
+        FreeDecodedCert(cert);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+    #endif
+    }
+
+    if (x509 != NULL)
+        *x509 = newX509;
+
+    return newX509;
+}
+#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
+          OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_ALL) || defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
+    /* return the next, if any, altname from the peer cert */
+    char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
+    {
+        char* ret = NULL;
+        WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
+
+        /* don't have any to work with */
+        if (cert == NULL || cert->altNames == NULL)
+            return NULL;
+
+        /* already went through them */
+        if (cert->altNamesNext == NULL)
+            return NULL;
+
+        ret = cert->altNamesNext->name;
+        cert->altNamesNext = cert->altNamesNext->next;
+
+        return ret;
+    }
+
+
+    int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
+    {
+        int isCA = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
+
+        if (x509 != NULL)
+            isCA = x509->isCa;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
+
+        return isCA;
+    }
+
+    int wolfSSL_X509_get_signature(WOLFSSL_X509* x509,
+                                                 unsigned char* buf, int* bufSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_signature");
+        if (x509 == NULL || bufSz == NULL || *bufSz < (int)x509->sig.length)
+            return WOLFSSL_FATAL_ERROR;
+
+        if (buf != NULL)
+            XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
+        *bufSz = x509->sig.length;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* write X509 serial number in unsigned binary to buffer
+       buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases
+       return WOLFSSL_SUCCESS on success */
+    int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509,
+                                       byte* in, int* inOutSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_serial_number");
+        if (x509 == NULL || in == NULL ||
+                                   inOutSz == NULL || *inOutSz < x509->serialSz)
+            return BAD_FUNC_ARG;
+
+        XMEMCPY(in, x509->serial, x509->serialSz);
+        *inOutSz = x509->serialSz;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_get_der");
+
+        if (x509 == NULL || x509->derCert == NULL || outSz == NULL)
+            return NULL;
+
+        *outSz = (int)x509->derCert->length;
+        return x509->derCert->buffer;
+    }
+
+
+    int wolfSSL_X509_version(WOLFSSL_X509* x509)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_version");
+
+        if (x509 == NULL)
+            return 0;
+
+        return x509->version;
+    }
+
+
+    const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_notBefore");
+
+        if (x509 == NULL)
+            return NULL;
+
+        return x509->notBefore;
+    }
+
+
+    const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_notAfter");
+
+        if (x509 == NULL)
+            return NULL;
+
+        return x509->notAfter;
+    }
+
+
+#ifdef WOLFSSL_SEP
+
+/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will
+   malloc buffer, call responsible for freeing. Actual size returned in
+   *inOutSz. Requires inOutSz be non-null */
+byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_dev_type");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->deviceTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->deviceTypeSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->deviceTypeSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->deviceType, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+
+byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_hw_type");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->hwTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->hwTypeSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->hwTypeSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->hwType, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+
+byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
+                                        int* inOutSz)
+{
+    int copySz;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number");
+    if (inOutSz == NULL) return NULL;
+    if (!x509->hwTypeSz) return in;
+
+    copySz = min(*inOutSz, x509->hwSerialNumSz);
+
+    if (!in) {
+    #ifdef WOLFSSL_STATIC_MEMORY
+        WOLFSSL_MSG("Using static memory -- please pass in a buffer");
+        return NULL;
+    #else
+        in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL);
+        if (!in) return in;
+        copySz = x509->hwSerialNumSz;
+    #endif
+    }
+
+    XMEMCPY(in, x509->hwSerialNum, copySz);
+    *inOutSz = copySz;
+
+    return in;
+}
+
+#endif /* WOLFSSL_SEP */
+
+/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509)
+{
+    WOLFSSL_STACK* node;
+
+    if (sk == NULL || x509 == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.x509 == NULL) {
+        sk->data.x509 = x509;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_X509);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new x509 onto head of stack */
+    node->data.x509 = sk->data.x509;
+    node->next      = sk->next;
+    sk->next        = node;
+    sk->data.x509   = x509;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
+    WOLFSSL_STACK* node;
+    WOLFSSL_X509*  x509;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    x509 = sk->data.x509;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.x509 = node->data.x509;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_X509);
+    }
+    else { /* last x509 in stack */
+        sk->data.x509 = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return x509;
+}
+
+
+/* Getter function for WOLFSSL_X509_NAME pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i  is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on
+ *         fail
+ */
+void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value");
+
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+
+    if (i != 0 || sk == NULL)
+        return NULL;
+    return sk->data.name;
+}
+
+
+/* Getter function for WOLFSSL_X509 pointer
+ *
+ * sk is the stack to retrieve pointer from
+ * i  is the index value in stack
+ *
+ * returns a pointer to a WOLFSSL_X509 structure on success and NULL on
+ *         fail
+ */
+void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_value");
+
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+
+    if (i != 0 || sk == NULL)
+        return NULL;
+    return sk->data.x509;
+}
+
+
+/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free
+ * in that it allows for choosing the function to use when freeing an X509s.
+ *
+ * sk  stack to free nodes in
+ * f   X509 free function
+ */
+void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free");
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        f(tmp->data.x509);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+	    f(sk->data.x509);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+
+/* free structure for x509 stack */
+void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) {
+    WOLFSSL_STACK* node;
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        wolfSSL_X509_free(tmp->data.x509);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+    wolfSSL_X509_free(sk->data.x509);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_X509);
+}
+
+#endif /* NO_CERTS && OPENSSL_EXTRA */
+
+#ifdef OPENSSL_EXTRA
+
+/* Returns the general name at index i from the stack
+ *
+ * sk stack to get general name from
+ * i  index to get
+ *
+ * return a pointer to the internal node of the stack
+ */
+WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int i)
+{
+    WOLFSSL_STACK* cur;
+    int j;
+
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_value");
+
+    if (i < 0 || sk == NULL) {
+        return NULL;
+    }
+
+    cur = sk;
+    for (j = 0; j < i && cur != NULL; j++) {
+        cur = cur->next;
+    }
+
+    if (cur == NULL) {
+        return NULL;
+    }
+
+    return cur->data.obj;
+}
+
+
+/* Gets the number of nodes in the stack
+ *
+ * sk  stack to get the number of nodes from
+ *
+ * returns the number of nodes, -1 if no nodes
+ */
+int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num");
+
+    if (sk == NULL) {
+        return -1;
+    }
+
+    return (int)sk->num;
+}
+
+/* Frees all nodes in a GENERAL NAME stack
+ *
+ * sk stack of nodes to free
+ * f  free function to use, not called with wolfSSL
+ */
+void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
+        void f (WOLFSSL_ASN1_OBJECT*))
+{
+    WOLFSSL_STACK* node;
+
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free");
+
+    (void)f;
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+	    wolfSSL_ASN1_OBJECT_free(sk->data.obj);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+
+
+}
+#endif /* OPENSSL_EXTRA */
+
+#ifndef NO_FILESYSTEM
+
+#ifndef NO_STDIO_FILESYSTEM
+
+WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
+{
+    WOLFSSL_X509* newX509 = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_d2i_fp");
+
+    if (file != XBADFILE) {
+        byte* fileBuffer = NULL;
+        long sz = 0;
+
+        XFSEEK(file, 0, XSEEK_END);
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz < 0) {
+            WOLFSSL_MSG("Bad tell on FILE");
+            return NULL;
+        }
+
+        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+        if (fileBuffer != NULL) {
+            int ret = (int)XFREAD(fileBuffer, 1, sz, file);
+            if (ret == sz) {
+                newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
+            }
+            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+        }
+    }
+
+    if (x509 != NULL)
+        *x509 = newX509;
+
+    return newX509;
+}
+
+#endif /* NO_STDIO_FILESYSTEM */
+
+WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
+{
+#ifdef WOLFSSL_SMALL_STACK
+    byte  staticBuffer[1]; /* force heap usage */
+#else
+    byte  staticBuffer[FILE_BUFFER_SIZE];
+#endif
+    byte* fileBuffer = staticBuffer;
+    int   dynamic = 0;
+    int   ret;
+    long  sz = 0;
+    XFILE file;
+
+    WOLFSSL_X509* x509 = NULL;
+
+    /* Check the inputs */
+    if ((fname == NULL) ||
+        (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM))
+        return NULL;
+
+    file = XFOPEN(fname, "rb");
+    if (file == XBADFILE)
+        return NULL;
+
+    XFSEEK(file, 0, XSEEK_END);
+    sz = XFTELL(file);
+    XREWIND(file);
+
+    if (sz > (long)sizeof(staticBuffer)) {
+        fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+        if (fileBuffer == NULL) {
+            XFCLOSE(file);
+            return NULL;
+        }
+        dynamic = 1;
+    }
+    else if (sz < 0) {
+        XFCLOSE(file);
+        return NULL;
+    }
+
+    ret = (int)XFREAD(fileBuffer, 1, sz, file);
+    if (ret != sz) {
+        XFCLOSE(file);
+        if (dynamic)
+            XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+        return NULL;
+    }
+
+    XFCLOSE(file);
+
+    x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format);
+
+    if (dynamic)
+        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+
+    return x509;
+}
+
+#endif /* NO_FILESYSTEM */
+
+
+WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
+    const unsigned char* buf, int sz, int format)
+{
+    int ret;
+    WOLFSSL_X509* x509 = NULL;
+    DerBuffer* der = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex");
+
+    if (format == WOLFSSL_FILETYPE_PEM) {
+    #ifdef WOLFSSL_PEM_TO_DER
+        if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) {
+            FreeDer(&der);
+        }
+    #else
+        ret = NOT_COMPILED_IN;
+    #endif
+    }
+    else {
+        ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL);
+        if (ret == 0) {
+            XMEMCPY(der->buffer, buf, sz);
+        }
+    }
+
+    /* At this point we want `der` to have the certificate in DER format */
+    /* ready to be decoded. */
+    if (der != NULL && der->buffer != NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        DecodedCert* cert = NULL;
+    #else
+        DecodedCert  cert[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                     DYNAMIC_TYPE_DCERT);
+        if (cert != NULL)
+    #endif
+        {
+            InitDecodedCert(cert, der->buffer, der->length, NULL);
+            if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                                             DYNAMIC_TYPE_X509);
+                if (x509 != NULL) {
+                    InitX509(x509, 1, NULL);
+                    if (CopyDecodedToX509(x509, cert) != 0) {
+                        XFREE(x509, NULL, DYNAMIC_TYPE_X509);
+                        x509 = NULL;
+                    }
+                }
+            }
+
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+
+        FreeDer(&der);
+    }
+
+    return x509;
+}
+
+#endif /* KEEP_PEER_CERT || SESSION_CERTS */
+
+/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
+   KEEP_OUR_CERT is to insure ability for returning ssl certificate */
+#if defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT)
+WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    if (ssl->buffers.weOwnCert) {
+        if (ssl->ourCert == NULL) {
+            if (ssl->buffers.certificate == NULL) {
+                WOLFSSL_MSG("Certificate buffer not set!");
+                return NULL;
+            }
+            ssl->ourCert = wolfSSL_X509_d2i(NULL,
+                                              ssl->buffers.certificate->buffer,
+                                              ssl->buffers.certificate->length);
+        }
+        return ssl->ourCert;
+    }
+    else { /* if cert not owned get parent ctx cert or return null */
+        if (ssl->ctx) {
+            if (ssl->ctx->ourCert == NULL) {
+                if (ssl->ctx->certificate == NULL) {
+                    WOLFSSL_MSG("Ctx Certificate buffer not set!");
+                    return NULL;
+                }
+                ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL,
+                                               ssl->ctx->certificate->buffer,
+                                               ssl->ctx->certificate->length);
+                ssl->ctx->ownOurCert = 1;
+            }
+            return ssl->ctx->ourCert;
+        }
+    }
+
+    return NULL;
+}
+#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
+#endif /* NO_CERTS */
+
+
+#ifdef OPENSSL_EXTRA
+/* return 1 on success 0 on fail */
+int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk,
+                                                      WOLFSSL_ASN1_OBJECT* obj)
+{
+    WOLFSSL_STACK* node;
+
+    if (sk == NULL || obj == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* no previous values in stack */
+    if (sk->data.obj == NULL) {
+        sk->data.obj = obj;
+        sk->num += 1;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* stack already has value(s) create a new node and add more */
+    node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                                             DYNAMIC_TYPE_ASN1);
+    if (node == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
+
+    /* push new obj onto head of stack */
+    node->data.obj = sk->data.obj;
+    node->next      = sk->next;
+    sk->next        = node;
+    sk->data.obj   = obj;
+    sk->num        += 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop(
+                                            WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+    WOLFSSL_STACK* node;
+    WOLFSSL_ASN1_OBJECT*  obj;
+
+    if (sk == NULL) {
+        return NULL;
+    }
+
+    node = sk->next;
+    obj = sk->data.obj;
+
+    if (node != NULL) { /* update sk and remove node from stack */
+        sk->data.obj = node->data.obj;
+        sk->next = node->next;
+        XFREE(node, NULL, DYNAMIC_TYPE_ASN1);
+    }
+    else { /* last obj in stack */
+        sk->data.obj = NULL;
+    }
+
+    if (sk->num > 0) {
+        sk->num -= 1;
+    }
+
+    return obj;
+}
+
+
+#ifndef NO_ASN
+WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void)
+{
+    WOLFSSL_ASN1_OBJECT* obj;
+
+    obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL,
+                                        DYNAMIC_TYPE_ASN1);
+    if (obj == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT));
+    obj->d.ia5 = &(obj->d.ia5_internal);
+    return obj;
+}
+
+
+void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj)
+{
+    if (obj == NULL) {
+        return;
+    }
+
+    if (obj->dynamic == 1) {
+        if (obj->obj != NULL) {
+            WOLFSSL_MSG("Freeing ASN1 OBJECT data");
+            XFREE(obj->obj, obj->heap, DYNAMIC_TYPE_ASN1);
+        }
+    }
+
+    XFREE(obj, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+
+/* free structure for x509 stack */
+void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+    WOLFSSL_STACK* node;
+
+    if (sk == NULL) {
+        return;
+    }
+
+    /* parse through stack freeing each node */
+    node = sk->next;
+    while (sk->num > 1) {
+        WOLFSSL_STACK* tmp = node;
+        node = node->next;
+
+        wolfSSL_ASN1_OBJECT_free(tmp->data.obj);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1);
+        sk->num -= 1;
+    }
+
+    /* free head of stack */
+    if (sk->num == 1) {
+        wolfSSL_ASN1_OBJECT_free(sk->data.obj);
+    }
+    XFREE(sk, NULL, DYNAMIC_TYPE_ASN1);
+}
+
+int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in)
+{
+    /*
+       ASN1_STRING_to_UTF8() converts the string in to UTF8 format,
+       the converted data is allocated in a buffer in *out.
+       The length of out is returned or a negative error code.
+       The buffer *out should be free using OPENSSL_free().
+       */
+    (void)out;
+    (void)in;
+    WOLFSSL_STUB("ASN1_STRING_to_UTF8");
+    return -1;
+}
+#endif /* NO_ASN */
+
+void wolfSSL_set_connect_state(WOLFSSL* ssl)
+{
+    word16 haveRSA = 1;
+    word16 havePSK = 0;
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
+        return;
+    }
+
+    #ifndef NO_DH
+    /* client creates its own DH parameters on handshake */
+    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    ssl->buffers.serverDH_P.buffer = NULL;
+    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
+        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    ssl->buffers.serverDH_G.buffer = NULL;
+    #endif
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        #ifdef NO_RSA
+            haveRSA = 0;
+        #endif
+        #ifndef NO_PSK
+            havePSK = ssl->options.havePSK;
+        #endif
+        InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, haveRSA,
+                   havePSK, ssl->options.haveDH, ssl->options.haveNTRU,
+                   ssl->options.haveECDSAsig, ssl->options.haveECC,
+                   ssl->options.haveStaticECC, WOLFSSL_CLIENT_END);
+    }
+    ssl->options.side = WOLFSSL_CLIENT_END;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
+
+
+int wolfSSL_get_shutdown(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_shutdown");
+    /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent   *
+     * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */
+    return ((ssl->options.closeNotify||ssl->options.connReset) << 1)
+            | (ssl->options.sentNotify);
+}
+
+
+int wolfSSL_session_reused(WOLFSSL* ssl)
+{
+    return ssl->options.resuming;
+}
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+void wolfSSL_SESSION_free(WOLFSSL_SESSION* session)
+{
+    if (session == NULL)
+        return;
+
+#ifdef HAVE_EXT_CACHE
+    if (session->isAlloced) {
+    #ifdef HAVE_SESSION_TICKET
+        if (session->isDynamic)
+            XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+    #endif
+        XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+#else
+    /* No need to free since cache is static */
+    (void)session;
+#endif
+}
+#endif
+
+const char* wolfSSL_get_version(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_version");
+    if (ssl->version.major == SSLv3_MAJOR) {
+        switch (ssl->version.minor) {
+        #ifndef NO_OLD_TLS
+            #ifdef WOLFSSL_ALLOW_SSLV3
+            case SSLv3_MINOR :
+                return "SSLv3";
+            #endif
+            #ifdef WOLFSSL_ALLOW_TLSV10
+            case TLSv1_MINOR :
+                return "TLSv1";
+            #endif
+            case TLSv1_1_MINOR :
+                return "TLSv1.1";
+        #endif
+            case TLSv1_2_MINOR :
+                return "TLSv1.2";
+        #ifdef WOLFSSL_TLS13
+            case TLSv1_3_MINOR :
+            /* TODO: [TLS13] Remove draft versions. */
+            #ifndef WOLFSSL_TLS13_FINAL
+                #ifdef WOLFSSL_TLS13_DRAFT_18
+                    return "TLSv1.3 (Draft 18)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_22)
+                    return "TLSv1.3 (Draft 22)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_23)
+                    return "TLSv1.3 (Draft 23)";
+                #elif defined(WOLFSSL_TLS13_DRAFT_26)
+                    return "TLSv1.3 (Draft 26)";
+                #else
+                    return "TLSv1.3 (Draft 28)";
+                #endif
+            #else
+                return "TLSv1.3";
+            #endif
+        #endif
+            default:
+                return "unknown";
+        }
+    }
+#ifdef WOLFSSL_DTLS
+    else if (ssl->version.major == DTLS_MAJOR) {
+        switch (ssl->version.minor) {
+            case DTLS_MINOR :
+                return "DTLS";
+            case DTLSv1_2_MINOR :
+                return "DTLSv1.2";
+            default:
+                return "unknown";
+        }
+    }
+#endif /* WOLFSSL_DTLS */
+    return "unknown";
+}
+
+
+/* current library version */
+const char* wolfSSL_lib_version(void)
+{
+    return LIBWOLFSSL_VERSION_STRING;
+}
+
+
+/* current library version in hex */
+word32 wolfSSL_lib_version_hex(void)
+{
+    return LIBWOLFSSL_VERSION_HEX;
+}
+
+
+int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_current_cipher_suite");
+    if (ssl)
+        return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite;
+    return 0;
+}
+
+WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("SSL_get_current_cipher");
+    if (ssl)
+        return &ssl->cipher;
+    else
+        return NULL;
+}
+
+
+const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
+{
+    WOLFSSL_ENTER("SSL_CIPHER_get_name");
+
+    if (cipher == NULL || cipher->ssl == NULL) {
+        return NULL;
+    }
+
+    return wolfSSL_get_cipher_name_iana(cipher->ssl);
+}
+
+const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session)
+{
+    if (session == NULL) {
+        return NULL;
+    }
+
+#ifdef SESSION_CERTS
+    return GetCipherNameIana(session->cipherSuite0, session->cipherSuite);
+#else
+    return NULL;
+#endif
+}
+
+const char* wolfSSL_get_cipher(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_cipher");
+    return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
+}
+
+/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
+const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
+{
+    /* get access to cipher_name_idx in internal.c */
+    return wolfSSL_get_cipher_name_internal(ssl);
+}
+
+const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
+    const byte cipherSuite)
+{
+    return GetCipherNameInternal(cipherSuite0, cipherSuite);
+}
+
+
+#ifdef HAVE_ECC
+/* Return the name of the curve used for key exchange as a printable string.
+ *
+ * ssl  The SSL/TLS object.
+ * returns NULL if ECDH was not used, otherwise the name as a string.
+ */
+const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
+{
+    if (ssl == NULL)
+        return NULL;
+    if (!IsAtLeastTLSv1_3(ssl->version) && ssl->specs.kea != ecdhe_psk_kea &&
+            ssl->specs.kea != ecc_diffie_hellman_kea)
+        return NULL;
+    if (ssl->ecdhCurveOID == 0)
+        return NULL;
+    if (ssl->ecdhCurveOID == ECC_X25519_OID)
+        return "X25519";
+    return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL));
+}
+#endif
+
+
+#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \
+    defined(SESSION_CERTS)
+/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
+ * this subset and its memory usage */
+
+#if !defined(NO_CERTS)
+/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on
+ * fail
+ */
+WOLFSSL_X509* wolfSSL_X509_new()
+{
+    WOLFSSL_X509* x509;
+
+    x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+            DYNAMIC_TYPE_X509);
+    if (x509 != NULL) {
+        InitX509(x509, 1, NULL);
+    }
+
+    return x509;
+}
+
+WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_subject_name");
+    if (cert && cert->subject.sz != 0)
+        return &cert->subject;
+    return NULL;
+}
+
+
+
+WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
+{
+    WOLFSSL_ENTER("X509_get_issuer_name");
+    if (cert && cert->issuer.sz != 0)
+        return &cert->issuer;
+    return NULL;
+}
+
+
+int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
+{
+    int type = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
+
+    if (x509 != NULL)
+        type = x509->sigOID;
+
+    return type;
+}
+
+#if defined(OPENSSL_EXTRA_X509_SMALL)
+#ifdef HAVE_ECC
+    static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey);
+#endif
+
+/* Used to get a string from the WOLFSSL_X509_NAME structure that
+ * corresponds with the NID value passed in.
+ *
+ * name structure to get string from
+ * nid  NID value to search for
+ * buf  [out] buffer to hold results. If NULL then the buffer size minus the
+ *      null char is returned.
+ * len  size of "buf" passed in
+ *
+ * returns the length of string found, not including the NULL terminator.
+ *         It's possible the function could return a negative value in the
+ *         case that len is less than or equal to 0. A negative value is
+ *         considered an error case.
+ */
+int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
+                                      int nid, char* buf, int len)
+{
+    char *text = NULL;
+    int textSz = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
+
+    switch (nid) {
+        case ASN_COMMON_NAME:
+            text = name->fullName.fullName + name->fullName.cnIdx;
+            textSz = name->fullName.cnLen;
+            break;
+        case ASN_SUR_NAME:
+            text = name->fullName.fullName + name->fullName.snIdx;
+            textSz = name->fullName.snLen;
+            break;
+        case ASN_SERIAL_NUMBER:
+            text = name->fullName.fullName + name->fullName.serialIdx;
+            textSz = name->fullName.serialLen;
+            break;
+        case ASN_COUNTRY_NAME:
+            text = name->fullName.fullName + name->fullName.cIdx;
+            textSz = name->fullName.cLen;
+            break;
+        case ASN_LOCALITY_NAME:
+            text = name->fullName.fullName + name->fullName.lIdx;
+            textSz = name->fullName.lLen;
+            break;
+        case ASN_STATE_NAME:
+            text = name->fullName.fullName + name->fullName.stIdx;
+            textSz = name->fullName.stLen;
+            break;
+        case ASN_ORG_NAME:
+            text = name->fullName.fullName + name->fullName.oIdx;
+            textSz = name->fullName.oLen;
+            break;
+        case ASN_ORGUNIT_NAME:
+            text = name->fullName.fullName + name->fullName.ouIdx;
+            textSz = name->fullName.ouLen;
+            break;
+        case ASN_DOMAIN_COMPONENT:
+            text = name->fullName.fullName + name->fullName.dcIdx[0];
+            textSz = name->fullName.dcLen[0];
+            break;
+        default:
+            WOLFSSL_MSG("Entry type not found");
+            return SSL_FATAL_ERROR;
+    }
+
+    /* if buf is NULL return size of buffer needed (minus null char) */
+    if (buf == NULL) {
+        return textSz;
+    }
+
+    if (buf != NULL && text != NULL) {
+        textSz = min(textSz + 1, len); /* + 1 to account for null char */
+        if (textSz > 0) {
+            XMEMCPY(buf, text, textSz - 1);
+            buf[textSz - 1] = '\0';
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
+    return (textSz - 1); /* do not include null character in size */
+}
+
+
+/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509
+ *
+ * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
+{
+    WOLFSSL_EVP_PKEY* key = NULL;
+    WOLFSSL_ENTER("X509_get_pubkey");
+    if (x509 != NULL) {
+        key = (WOLFSSL_EVP_PKEY*)XMALLOC(
+                    sizeof(WOLFSSL_EVP_PKEY), x509->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+        if (key != NULL) {
+            XMEMSET(key, 0, sizeof(WOLFSSL_EVP_PKEY));
+            if (x509->pubKeyOID == RSAk) {
+                key->type = EVP_PKEY_RSA;
+            }
+            else {
+                key->type = EVP_PKEY_EC;
+            }
+            key->save_type = 0;
+            key->pkey.ptr = (char*)XMALLOC(
+                        x509->pubKey.length, x509->heap,
+                                                       DYNAMIC_TYPE_PUBLIC_KEY);
+            if (key->pkey.ptr == NULL) {
+                XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                return NULL;
+            }
+            XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
+            key->pkey_sz = x509->pubKey.length;
+
+            #ifdef HAVE_ECC
+                key->pkey_curve = (int)x509->pkCurveOID;
+            #endif /* HAVE_ECC */
+
+            /* decode RSA key */
+            #ifndef NO_RSA
+            if (key->type == EVP_PKEY_RSA) {
+                key->ownRsa = 1;
+                key->rsa = wolfSSL_RSA_new();
+                if (key->rsa == NULL) {
+                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(key->rsa,
+                            (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+                            WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                    wolfSSL_RSA_free(key->rsa);
+                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    return NULL;
+                }
+            }
+            #endif /* NO_RSA */
+
+            /* decode ECC key */
+            #ifdef HAVE_ECC
+            if (key->type == EVP_PKEY_EC) {
+                word32 idx = 0;
+
+                key->ownEcc = 1;
+                key->ecc = wolfSSL_EC_KEY_new();
+                if (key->ecc == NULL || key->ecc->internal == NULL) {
+                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    return NULL;
+                }
+
+                /* not using wolfSSL_EC_KEY_LoadDer because public key in x509
+                 * is in the format of x963 (no sequence at start of buffer) */
+                if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
+                        &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) {
+                    WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    wolfSSL_EC_KEY_free(key->ecc);
+                    return NULL;
+                }
+
+                if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) {
+                    WOLFSSL_MSG("SetECKeyExternal failed");
+                    XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    wolfSSL_EC_KEY_free(key->ecc);
+                    return NULL;
+                }
+
+                key->ecc->inSet = 1;
+            }
+            #endif /* HAVE_ECC */
+        }
+    }
+    return key;
+}
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+#endif /* !NO_CERTS */
+
+/* End of smaller subset of X509 compatibility functions. Avoid increasing the
+ * size of this subset and its memory usage */
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA)
+#if !defined(NO_CERTS)
+    int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
+    {
+        int isSet = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
+
+        if (x509 != NULL) {
+            switch (nid) {
+                case BASIC_CA_OID: isSet = x509->basicConstSet; break;
+                case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break;
+                case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break;
+                case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break;
+                case KEY_USAGE_OID: isSet = x509->keyUsageSet; break;
+                #ifdef WOLFSSL_SEP
+                    case CERT_POLICY_OID: isSet = x509->certPolicySet; break;
+                #endif /* WOLFSSL_SEP */
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
+
+        return isSet;
+    }
+
+
+    int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
+    {
+        int crit = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
+
+        if (x509 != NULL) {
+            switch (nid) {
+                case BASIC_CA_OID: crit = x509->basicConstCrit; break;
+                case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break;
+                case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break;
+                case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break;
+                case KEY_USAGE_OID: crit = x509->keyUsageCrit; break;
+                #ifdef WOLFSSL_SEP
+                    case CERT_POLICY_OID: crit = x509->certPolicyCrit; break;
+                #endif /* WOLFSSL_SEP */
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
+
+        return crit;
+    }
+
+
+    int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
+    {
+        int isSet = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
+
+        if (x509 != NULL)
+            isSet = x509->basicConstPlSet;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
+
+        return isSet;
+    }
+
+
+    word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
+    {
+        word32 pathLength = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
+
+        if (x509 != NULL)
+            pathLength = x509->pathLength;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
+
+        return pathLength;
+    }
+
+
+    unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
+    {
+        word16 usage = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
+
+        if (x509 != NULL)
+            usage = x509->keyUsage;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
+
+        return usage;
+    }
+
+
+    byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509,
+                                          byte* dst, int* dstLen)
+    {
+        byte *id = NULL;
+        int copySz = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
+
+        if (x509 != NULL) {
+            if (x509->authKeyIdSet) {
+                copySz = min(dstLen != NULL ? *dstLen : 0,
+                             (int)x509->authKeyIdSz);
+                id = x509->authKeyId;
+            }
+
+            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+                XMEMCPY(dst, id, copySz);
+                id = dst;
+                *dstLen = copySz;
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
+
+        return id;
+    }
+
+
+    byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
+                                        byte* dst, int* dstLen)
+    {
+        byte *id = NULL;
+        int copySz = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
+
+        if (x509 != NULL) {
+            if (x509->subjKeyIdSet) {
+                copySz = min(dstLen != NULL ? *dstLen : 0,
+                                                        (int)x509->subjKeyIdSz);
+                id = x509->subjKeyId;
+            }
+
+            if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
+                XMEMCPY(dst, id, copySz);
+                id = dst;
+                *dstLen = copySz;
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
+
+        return id;
+    }
+
+
+    int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name)
+    {
+        int count = 0;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count");
+
+        if (name != NULL)
+            count = name->fullName.entryCount;
+
+        WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
+        return count;
+    }
+
+
+
+    int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name,
+                                          int nid, int pos)
+    {
+        int ret    = -1;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID");
+
+        if (name == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        /* these index values are already stored in DecodedName
+           use those when available */
+        if (name->fullName.fullName && name->fullName.fullNameLen > 0) {
+            name->fullName.dcMode = 0;
+            switch (nid) {
+                case ASN_COMMON_NAME:
+                    if (pos != name->fullName.cnIdx)
+                        ret = name->fullName.cnIdx;
+                    break;
+                case ASN_DOMAIN_COMPONENT:
+                    name->fullName.dcMode = 1;
+                    if (pos < name->fullName.dcNum - 1){
+                        ret = pos + 1;
+                    } else {
+                        ret = -1;
+                    }
+                    break;
+                default:
+                    WOLFSSL_MSG("NID not yet implemented");
+                    break;
+            }
+        }
+
+        WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_index_by_NID", ret);
+
+        (void)pos;
+        (void)nid;
+
+        return ret;
+    }
+
+
+    WOLFSSL_ASN1_STRING*  wolfSSL_X509_NAME_ENTRY_get_data(
+                                                    WOLFSSL_X509_NAME_ENTRY* in)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data");
+        return in->value;
+    }
+
+
+    /* Creates a new WOLFSSL_ASN1_STRING structure.
+     *
+     * returns a pointer to the new structure created on success or NULL if fail
+     */
+    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new()
+    {
+        WOLFSSL_ASN1_STRING* asn1;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new");
+
+        asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (asn1 != NULL) {
+            XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
+        }
+
+        return asn1; /* no check for null because error case is returning null*/
+    }
+
+
+    /* used to free a WOLFSSL_ASN1_STRING structure */
+    void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free");
+
+        if (asn1 != NULL) {
+            if (asn1->length > 0 && asn1->data != NULL) {
+                XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+            XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+    }
+
+
+    /* Creates a new WOLFSSL_ASN1_STRING structure given the input type.
+     *
+     * type is the type of set when WOLFSSL_ASN1_STRING is created
+     *
+     * returns a pointer to the new structure created on success or NULL if fail
+     */
+    WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type)
+    {
+        WOLFSSL_ASN1_STRING* asn1;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new");
+
+        asn1 = wolfSSL_ASN1_STRING_new();
+        if (asn1 == NULL) {
+            return NULL;
+        }
+        asn1->type = type;
+
+        return asn1;
+    }
+
+
+    /* if dataSz is negative then use XSTRLEN to find length of data
+     * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
+    int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data,
+            int dataSz)
+    {
+        int sz;
+
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set");
+
+        if (data == NULL || asn1 == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        if (dataSz < 0) {
+            sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */
+        }
+        else {
+            sz = dataSz;
+        }
+
+        if (sz < 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        /* free any existing data before copying */
+        if (asn1->data != NULL) {
+            XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+
+        /* create new data buffer and copy over */
+        asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (asn1->data == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+        XMEMCPY(asn1->data, data, sz);
+        asn1->length = sz;
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data");
+
+        if (asn) {
+            return (unsigned char*)asn->data;
+        }
+        else {
+            return NULL;
+        }
+    }
+
+
+    int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn)
+    {
+        WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length");
+
+        if (asn) {
+            return asn->length;
+        }
+        else {
+            return 0;
+        }
+    }
+
+
+#ifdef XSNPRINTF /* a snprintf function needs to be available */
+    /* Writes the human readable form of x509 to bio.
+     *
+     * bio  WOLFSSL_BIO to write to.
+     * x509 Certificate to write.
+     *
+     * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+     */
+    int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+    {
+        WOLFSSL_ENTER("wolfSSL_X509_print");
+
+        if (bio == NULL || x509 == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+
+        if (wolfSSL_BIO_write(bio, "Certificate:\n", sizeof("Certificate:\n"))
+            <= 0) {
+                return WOLFSSL_FAILURE;
+        }
+
+        if (wolfSSL_BIO_write(bio, "    Data:\n", sizeof("    Data:\n"))
+            <= 0) {
+                return WOLFSSL_FAILURE;
+        }
+
+        /* print version of cert */
+        {
+            int version;
+            char tmp[17];
+
+            if ((version = wolfSSL_X509_version(x509)) <= 0) {
+                WOLFSSL_MSG("Error getting X509 version");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "        Version: ",
+                                sizeof("        Version: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+	        XSNPRINTF(tmp, sizeof(tmp), "%d\n", version);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print serial number out */
+        {
+            unsigned char serial[32];
+            int  sz = sizeof(serial);
+
+            XMEMSET(serial, 0, sz);
+            if (wolfSSL_X509_get_serial_number(x509, serial, &sz)
+                    != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("Error getting x509 serial number");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "        Serial Number: ",
+                                sizeof("        Serial Number: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            /* if serial can fit into byte than print on the same line */
+            if (sz <= (int)sizeof(byte)) {
+                char tmp[17];
+                XSNPRINTF(tmp, sizeof(tmp), "%d (0x%x)\n", serial[0],serial[0]);
+                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            else {
+                int i;
+                char tmp[100];
+                int  tmpSz = 100;
+                char val[5];
+                int  valSz = 5;
+
+                /* serial is larger than int size so print off hex values */
+                if (wolfSSL_BIO_write(bio, "\n            ",
+                                sizeof("\n            ")) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+                tmp[0] = '\0';
+                for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) {
+                    XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]);
+                    val[3] = '\0'; /* make sure is null terminated */
+                    XSTRNCAT(tmp, val, valSz);
+                }
+                XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]);
+                val[3] = '\0'; /* make sure is null terminated */
+                XSTRNCAT(tmp, val, valSz);
+                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+
+        /* print signature algo */
+        {
+            int   oid;
+            char* sig;
+
+            if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) {
+                WOLFSSL_MSG("Error getting x509 signature type");
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "    Signature Algorithm: ",
+                                sizeof("    Signature Algorithm: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            sig = GetSigName(oid);
+            if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print issuer */
+        {
+            char* issuer;
+        #ifdef WOLFSSL_SMALL_STACK
+            char* buff  = NULL;
+            int   issSz = 0;
+        #else
+            char buff[256];
+            int  issSz = 256;
+        #endif
+
+            issuer  = wolfSSL_X509_NAME_oneline(
+                             wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+
+            if (wolfSSL_BIO_write(bio, "        Issuer: ",
+                                sizeof("        Issuer: ")) <= 0) {
+                #ifdef WOLFSSL_SMALL_STACK
+                XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                #endif
+                return WOLFSSL_FAILURE;
+            }
+            if (issuer != NULL) {
+                if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                    #endif
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            #ifdef WOLFSSL_SMALL_STACK
+            XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+            #endif
+            if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print validity */
+        {
+            char tmp[80];
+
+            if (wolfSSL_BIO_write(bio, "        Validity\n",
+                                sizeof("        Validity\n")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "            Not Before: ",
+                                sizeof("            Not Before: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (GetTimeString(x509->notBefore + 2, ASN_UTC_TIME,
+                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                if (GetTimeString(x509->notBefore + 2, ASN_GENERALIZED_TIME,
+                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Error getting not before date");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_BIO_write(bio, "\n            Not After : ",
+                                sizeof("\n            Not After : ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (GetTimeString(x509->notAfter + 2,ASN_UTC_TIME,
+                tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                if (GetTimeString(x509->notAfter + 2,ASN_GENERALIZED_TIME,
+                    tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Error getting not before date");
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print subject */
+        {
+            char* subject;
+        #ifdef WOLFSSL_SMALL_STACK
+            char* buff  = NULL;
+            int   subSz = 0;
+        #else
+            char buff[256];
+            int  subSz = 256;
+        #endif
+
+            subject  = wolfSSL_X509_NAME_oneline(
+                             wolfSSL_X509_get_subject_name(x509), buff, subSz);
+
+            if (wolfSSL_BIO_write(bio, "\n        Subject: ",
+                                sizeof("\n        Subject: ")) <= 0) {
+                #ifdef WOLFSSL_SMALL_STACK
+                XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+                #endif
+                return WOLFSSL_FAILURE;
+            }
+            if (subject != NULL) {
+                if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+                    #endif
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            #ifdef WOLFSSL_SMALL_STACK
+            XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL);
+            #endif
+        }
+
+        /* get and print public key */
+        if (wolfSSL_BIO_write(bio, "\n        Subject Public Key Info:\n",
+                          sizeof("\n        Subject Public Key Info:\n")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+        {
+            char tmp[100];
+
+            switch (x509->pubKeyOID) {
+                #ifndef NO_RSA
+                case RSAk:
+                    if (wolfSSL_BIO_write(bio,
+                                "            Public Key Algorithm: RSA\n",
+                      sizeof("            Public Key Algorithm: RSA\n")) <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                #ifdef HAVE_USER_RSA
+                    if (wolfSSL_BIO_write(bio,
+                        "                Build without user RSA to print key\n",
+                sizeof("                Build without user RSA to print key\n"))
+                        <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                #else
+                    {
+                        RsaKey rsa;
+                        word32 idx = 0;
+                        int  sz;
+                        byte lbit = 0;
+                        int  rawLen;
+                        unsigned char* rawKey;
+
+                        if (wc_InitRsaKey(&rsa, NULL) != 0) {
+                            WOLFSSL_MSG("wc_InitRsaKey failure");
+                            return WOLFSSL_FAILURE;
+                        }
+                        if (wc_RsaPublicKeyDecode(x509->pubKey.buffer,
+                                &idx, &rsa, x509->pubKey.length) != 0) {
+                            WOLFSSL_MSG("Error decoding RSA key");
+                            return WOLFSSL_FAILURE;
+                        }
+                        if ((sz = wc_RsaEncryptSize(&rsa)) < 0) {
+                            WOLFSSL_MSG("Error getting RSA key size");
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+                                "                 ", "Public-Key", 8 * sz,
+                                "                 Modulus:");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        /* print out modulus */
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                     ");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (mp_leading_bit(&rsa.n)) {
+                            lbit = 1;
+                            XSTRNCAT(tmp, "00", sizeof("00"));
+                        }
+
+                        rawLen = mp_unsigned_bin_size(&rsa.n);
+                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+                                DYNAMIC_TYPE_TMP_BUFFER);
+                        if (rawKey == NULL) {
+                            WOLFSSL_MSG("Memory error");
+                            return WOLFSSL_FAILURE;
+                        }
+                        mp_to_unsigned_bin(&rsa.n, rawKey);
+                        for (idx = 0; idx < (word32)rawLen; idx++) {
+                            char val[5];
+                            int valSz = 5;
+
+                            if ((idx == 0) && !lbit) {
+                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                            }
+                            else if ((idx != 0) && (((idx + lbit) % 15) == 0)) {
+                                tmp[sizeof(tmp) - 1] = '\0';
+                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                                        <= 0) {
+                                    XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                                    return WOLFSSL_FAILURE;
+                                }
+                                XSNPRINTF(tmp, sizeof(tmp) - 1,
+                                        ":\n                     ");
+                                XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]);
+                            }
+                            else {
+                                XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]);
+                            }
+                            XSTRNCAT(tmp, val, valSz);
+                        }
+                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+                        /* print out remaning modulus values */
+                        if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) {
+                                tmp[sizeof(tmp) - 1] = '\0';
+                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                                        <= 0) {
+                                    return WOLFSSL_FAILURE;
+                                }
+                        }
+
+                        /* print out exponent values */
+                        rawLen = mp_unsigned_bin_size(&rsa.e);
+                        if (rawLen < 0) {
+                            WOLFSSL_MSG("Error getting exponent size");
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        if ((word32)rawLen < sizeof(word32)) {
+                            rawLen = sizeof(word32);
+                        }
+                        rawKey = (unsigned char*)XMALLOC(rawLen, NULL,
+                                DYNAMIC_TYPE_TMP_BUFFER);
+                        if (rawKey == NULL) {
+                            WOLFSSL_MSG("Memory error");
+                            return WOLFSSL_FAILURE;
+                        }
+                        XMEMSET(rawKey, 0, rawLen);
+                        mp_to_unsigned_bin(&rsa.e, rawKey);
+                        if ((word32)rawLen <= sizeof(word32)) {
+                            idx = *(word32*)rawKey;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,
+                        "\n                 Exponent: %d\n", idx);
+                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                            XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                    }
+                #endif /* HAVE_USER_RSA */
+                    break;
+                #endif /* NO_RSA */
+
+                #ifdef HAVE_ECC
+                case ECDSAk:
+                    {
+                        word32 i;
+                        ecc_key ecc;
+
+                        if (wolfSSL_BIO_write(bio,
+                                "            Public Key Algorithm: EC\n",
+                      sizeof("            Public Key Algorithm: EC\n")) <= 0) {
+                        return WOLFSSL_FAILURE;
+                        }
+                        if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID)
+                                != 0) {
+                            return WOLFSSL_FAILURE;
+                        }
+
+                        i = 0;
+                        if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i,
+                                              &ecc, x509->pubKey.length) != 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n",
+                                "                 ", "Public-Key",
+                                8 * wc_ecc_size(&ecc),
+                                "                 pub:");
+                        tmp[sizeof(tmp) - 1] = '\0';
+                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1,"                     ");
+                        {
+                            word32 derSz;
+                            byte*  der;
+
+                            derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE;
+                            der = (byte*)XMALLOC(derSz, x509->heap,
+                                    DYNAMIC_TYPE_TMP_BUFFER);
+                            if (der == NULL) {
+                                wc_ecc_free(&ecc);
+                                return WOLFSSL_FAILURE;
+                            }
+
+                            if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) {
+                                wc_ecc_free(&ecc);
+                                XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                                return WOLFSSL_FAILURE;
+                            }
+                            for (i = 0; i < derSz; i++) {
+                                char val[5];
+                                int valSz = 5;
+
+                                if (i == 0) {
+                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+                                }
+                                else if ((i % 15) == 0) {
+                                    tmp[sizeof(tmp) - 1] = '\0';
+                                    if (wolfSSL_BIO_write(bio, tmp,
+                                                (int)XSTRLEN(tmp)) <= 0) {
+                                        wc_ecc_free(&ecc);
+                                        XFREE(der, x509->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+                                        return WOLFSSL_FAILURE;
+                                    }
+                                    XSNPRINTF(tmp, sizeof(tmp) - 1,
+                                        ":\n                     ");
+                                    XSNPRINTF(val, valSz - 1, "%02x", der[i]);
+                                }
+                                else {
+                                    XSNPRINTF(val, valSz - 1, ":%02x", der[i]);
+                                }
+                                XSTRNCAT(tmp, val, valSz);
+                            }
+
+                            /* print out remaning modulus values */
+                            if ((i > 0) && (((i - 1) % 15) != 0)) {
+                                tmp[sizeof(tmp) - 1] = '\0';
+                                if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                                        <= 0) {
+                                    wc_ecc_free(&ecc);
+                                    XFREE(der, x509->heap,
+                                                DYNAMIC_TYPE_TMP_BUFFER);
+                                    return WOLFSSL_FAILURE;
+                                }
+                            }
+
+                            XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                        }
+                        XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n",
+                                "                ", "ASN1 OID",
+                                ecc.dp->name);
+                        if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                            wc_ecc_free(&ecc);
+                            return WOLFSSL_FAILURE;
+                        }
+                        wc_ecc_free(&ecc);
+                    }
+                    break;
+                #endif /* HAVE_ECC */
+                default:
+                    WOLFSSL_MSG("Unknown key type");
+                    return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print out extensions */
+        if (wolfSSL_BIO_write(bio, "        X509v3 extensions:\n",
+                            sizeof("        X509v3 extensions:\n")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        /* print subject key id */
+        if (x509->subjKeyIdSet && x509->subjKeyId != NULL &&
+                x509->subjKeyIdSz > 0) {
+            char tmp[100];
+            word32 i;
+            char val[5];
+            int valSz = 5;
+
+
+            if (wolfSSL_BIO_write(bio,
+                        "            X509v3 Subject Key Identifier:\n",
+                 sizeof("            X509v3 Subject Key Identifier:\n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "                 ");
+            for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) {
+                XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]);
+                XSTRNCAT(tmp, val, valSz);
+            }
+            XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]);
+            XSTRNCAT(tmp, val, valSz);
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* printf out authority key id */
+        if (x509->authKeyIdSet && x509->authKeyId != NULL &&
+                x509->authKeyIdSz > 0) {
+            char tmp[100];
+            word32 i;
+            char val[5];
+            int valSz = 5;
+
+            if (wolfSSL_BIO_write(bio,
+                        "            X509v3 Authority Key Identifier:\n",
+                 sizeof("            X509v3 Authority Key Identifier:\n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            XSNPRINTF(tmp, sizeof(tmp) - 1, "                 keyid");
+            for (i = 0; i < x509->authKeyIdSz; i++) {
+                /* check if buffer is almost full */
+                if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) {
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+                    tmp[0] = '\0';
+                }
+                XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]);
+                XSTRNCAT(tmp, val, valSz);
+            }
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            /* print issuer */
+            {
+                char* issuer;
+            #ifdef WOLFSSL_SMALL_STACK
+                char* buff  = NULL;
+                int   issSz = 0;
+            #else
+                char buff[256];
+                int  issSz = 256;
+            #endif
+
+                issuer  = wolfSSL_X509_NAME_oneline(
+                               wolfSSL_X509_get_issuer_name(x509), buff, issSz);
+
+                if (wolfSSL_BIO_write(bio, "\n                 DirName:",
+                                  sizeof("\n                 DirName:")) <= 0) {
+                    #ifdef WOLFSSL_SMALL_STACK
+                    XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                    #endif
+                    return WOLFSSL_FAILURE;
+                }
+                if (issuer != NULL) {
+                    if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) {
+                        #ifdef WOLFSSL_SMALL_STACK
+                        XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                        #endif
+                        return WOLFSSL_FAILURE;
+                    }
+                }
+                #ifdef WOLFSSL_SMALL_STACK
+                XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL);
+                #endif
+                if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
+                    return WOLFSSL_FAILURE;
+                }
+            }
+        }
+
+        /* print basic constraint */
+        if (x509->basicConstSet) {
+            char tmp[100];
+
+            if (wolfSSL_BIO_write(bio,
+                        "\n            X509v3 Basic Constraints:\n",
+                 sizeof("\n            X509v3 Basic Constraints:\n"))
+                 <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp),
+                    "                    CA:%s\n",
+                    (x509->isCa)? "TRUE": "FALSE");
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+
+        /* print out signature */
+        {
+            unsigned char* sig;
+            int sigSz;
+            int i;
+            char tmp[100];
+            int sigOid = wolfSSL_X509_get_signature_type(x509);
+
+            if (wolfSSL_BIO_write(bio,
+                                "    Signature Algorithm: ",
+                      sizeof("    Signature Algorithm: ")) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid));
+            tmp[sizeof(tmp) - 1] = '\0';
+            if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+
+            sigSz = (int)x509->sig.length;
+            sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            if (sig == NULL || sigSz <= 0) {
+                return WOLFSSL_FAILURE;
+            }
+            if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) {
+                XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                return WOLFSSL_FAILURE;
+            }
+            XSNPRINTF(tmp, sizeof(tmp) - 1,"         ");
+            tmp[sizeof(tmp) - 1] = '\0';
+            for (i = 0; i < sigSz; i++) {
+                char val[5];
+                int valSz = 5;
+
+                if (i == 0) {
+                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+                }
+                else if (((i % 18) == 0)) {
+                    tmp[sizeof(tmp) - 1] = '\0';
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                            <= 0) {
+                        XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                        return WOLFSSL_FAILURE;
+                    }
+                    XSNPRINTF(tmp, sizeof(tmp) - 1,
+                            ":\n         ");
+                    XSNPRINTF(val, valSz - 1, "%02x", sig[i]);
+                }
+                else {
+                    XSNPRINTF(val, valSz - 1, ":%02x", sig[i]);
+                }
+                XSTRNCAT(tmp, val, valSz);
+            }
+            XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+            /* print out remaning sig values */
+            if ((i > 0) && (((i - 1) % 18) != 0)) {
+                    tmp[sizeof(tmp) - 1] = '\0';
+                    if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp))
+                            <= 0) {
+                        return WOLFSSL_FAILURE;
+                    }
+            }
+        }
+
+        /* done with print out */
+        if (wolfSSL_BIO_write(bio, "\n", sizeof("\n")) <= 0) {
+            return WOLFSSL_FAILURE;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+#endif /* XSNPRINTF */
+
+#endif /* NO_CERTS */
+
+char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in,
+                                 int len)
+{
+    char *ret = in;
+    const char *keaStr, *authStr, *encStr, *macStr;
+    size_t strLen;
+
+    if (cipher == NULL || in == NULL)
+        return NULL;
+
+    switch (cipher->ssl->specs.kea) {
+        case no_kea:
+            keaStr = "None";
+            break;
+#ifndef NO_RSA
+        case rsa_kea:
+            keaStr = "RSA";
+            break;
+#endif
+#ifndef NO_DH
+        case diffie_hellman_kea:
+            keaStr = "DHE";
+            break;
+#endif
+        case fortezza_kea:
+            keaStr = "FZ";
+            break;
+#ifndef NO_PSK
+        case psk_kea:
+            keaStr = "PSK";
+            break;
+    #ifndef NO_DH
+        case dhe_psk_kea:
+            keaStr = "DHEPSK";
+            break;
+    #endif
+    #ifdef HAVE_ECC
+        case ecdhe_psk_kea:
+            keaStr = "ECDHEPSK";
+            break;
+    #endif
+#endif
+#ifdef HAVE_NTRU
+        case ntru_kea:
+            keaStr = "NTRU";
+            break;
+#endif
+#ifdef HAVE_ECC
+        case ecc_diffie_hellman_kea:
+            keaStr = "ECDHE";
+            break;
+        case ecc_static_diffie_hellman_kea:
+            keaStr = "ECDH";
+            break;
+#endif
+        default:
+            keaStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.sig_algo) {
+        case anonymous_sa_algo:
+            authStr = "None";
+            break;
+#ifndef NO_RSA
+        case rsa_sa_algo:
+            authStr = "RSA";
+            break;
+#endif
+#ifndef NO_DSA
+        case dsa_sa_algo:
+            authStr = "DSA";
+            break;
+#endif
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            authStr = "ECDSA";
+            break;
+#endif
+        default:
+            authStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.bulk_cipher_algorithm) {
+        case wolfssl_cipher_null:
+            encStr = "None";
+            break;
+#ifndef NO_RC4
+        case wolfssl_rc4:
+            encStr = "RC4(128)";
+            break;
+#endif
+#ifndef NO_DES3
+        case wolfssl_triple_des:
+            encStr = "3DES(168)";
+            break;
+#endif
+#ifdef HAVE_IDEA
+        case wolfssl_idea:
+            encStr = "IDEA(128)";
+            break;
+#endif
+#ifndef NO_AES
+        case wolfssl_aes:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AES(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AES(256)";
+            else
+                encStr = "AES(?)";
+            break;
+    #ifdef HAVE_AESGCM
+        case wolfssl_aes_gcm:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AESGCM(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AESGCM(256)";
+            else
+                encStr = "AESGCM(?)";
+            break;
+    #endif
+    #ifdef HAVE_AESCCM
+        case wolfssl_aes_ccm:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "AESCCM(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "AESCCM(256)";
+            else
+                encStr = "AESCCM(?)";
+            break;
+    #endif
+#endif
+#ifdef HAVE_CHACHA
+        case wolfssl_chacha:
+            encStr = "CHACHA20/POLY1305(256)";
+            break;
+#endif
+#ifdef HAVE_CAMELLIA
+        case wolfssl_camellia:
+            if (cipher->ssl->specs.key_size == 128)
+                encStr = "Camellia(128)";
+            else if (cipher->ssl->specs.key_size == 256)
+                encStr = "Camellia(256)";
+            else
+                encStr = "Camellia(?)";
+            break;
+#endif
+#if defined(HAVE_HC128) && !defined(NO_HC128)
+        case wolfssl_hc128:
+            encStr = "HC128(128)";
+            break;
+#endif
+#if defined(HAVE_RABBIT) && !defined(NO_RABBIT)
+        case wolfssl_rabbit:
+            encStr = "RABBIT(128)";
+            break;
+#endif
+        default:
+            encStr = "unknown";
+            break;
+    }
+
+    switch (cipher->ssl->specs.mac_algorithm) {
+        case no_mac:
+            macStr = "None";
+            break;
+#ifndef NO_MD5
+        case md5_mac:
+            macStr = "MD5";
+            break;
+#endif
+#ifndef NO_SHA
+        case sha_mac:
+            macStr = "SHA1";
+            break;
+#endif
+#ifdef HAVE_SHA224
+        case sha224_mac:
+            macStr = "SHA224";
+            break;
+#endif
+#ifndef NO_SHA256
+        case sha256_mac:
+            macStr = "SHA256";
+            break;
+#endif
+#ifdef HAVE_SHA384
+        case sha384_mac:
+            macStr = "SHA384";
+            break;
+#endif
+#ifdef HAVE_SHA512
+        case sha512_mac:
+            macStr = "SHA512";
+            break;
+#endif
+#ifdef HAVE_BLAKE2
+        case blake2b_mac:
+            macStr = "BLAKE2b";
+            break;
+#endif
+        default:
+            macStr = "unknown";
+            break;
+    }
+
+    /* Build up the string by copying onto the end. */
+    XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " ", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Kx=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, keaStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Au=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, authStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Enc=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, encStr, len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+
+    XSTRNCPY(in, " Mac=", len);
+    in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+    XSTRNCPY(in, macStr, len);
+    in[len-1] = '\0';
+
+    return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl)
+{
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    /* sessions are stored statically, no need for reference count */
+    return wolfSSL_get_session(ssl);
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+
+/* was do nothing */
+/*
+void OPENSSL_free(void* buf)
+{
+    (void)buf;
+}
+*/
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path,
+                   int* ssl)
+{
+    (void)url;
+    (void)host;
+    (void)port;
+    (void)path;
+    (void)ssl;
+    WOLFSSL_STUB("OCSP_parse_url");
+    return 0;
+}
+#endif
+
+WOLFSSL_METHOD* wolfSSLv2_client_method(void)
+{
+    return 0;
+}
+
+
+WOLFSSL_METHOD* wolfSSLv2_server_method(void)
+{
+    return 0;
+}
+
+
+#ifndef NO_MD4
+
+void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4)
+{
+    /* make sure we have a big enough buffer */
+    typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
+    (void) sizeof(ok);
+
+    WOLFSSL_ENTER("MD4_Init");
+    wc_InitMd4((Md4*)md4);
+}
+
+
+void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data,
+                       unsigned long len)
+{
+    WOLFSSL_ENTER("MD4_Update");
+    wc_Md4Update((Md4*)md4, (const byte*)data, (word32)len);
+}
+
+
+void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4)
+{
+    WOLFSSL_ENTER("MD4_Final");
+    wc_Md4Final((Md4*)md4, digest);
+}
+
+#endif /* NO_MD4 */
+
+
+/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list.
+ *
+ * bio is the WOLFSSL_BIO struct in the list and removed.
+ *
+ * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if
+ * there is none.
+ */
+WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio)
+{
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return NULL;
+    }
+
+    if (bio->prev != NULL) {
+        bio->prev->next = bio->next;
+    }
+
+    if (bio->next != NULL) {
+        bio->next->prev = bio->prev;
+    }
+
+    return bio->next;
+}
+
+
+int wolfSSL_BIO_pending(WOLFSSL_BIO* bio)
+{
+    return (int)wolfSSL_BIO_ctrl_pending(bio);
+}
+
+
+
+WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
+{
+    static WOLFSSL_BIO_METHOD meth;
+
+    WOLFSSL_ENTER("BIO_s_mem");
+    meth.type = WOLFSSL_BIO_MEMORY;
+
+    return &meth;
+}
+
+
+WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void)
+{
+    static WOLFSSL_BIO_METHOD meth;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_f_base64");
+    meth.type = WOLFSSL_BIO_BASE64;
+
+    return &meth;
+}
+
+
+/* Set the flag for the bio.
+ *
+ * bio   the structre to set the flag in
+ * flags the flag to use
+ */
+void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags)
+{
+    WOLFSSL_ENTER("wolfSSL_BIO_set_flags");
+
+    if (bio != NULL) {
+        bio->flags |= flags;
+    }
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_RAND_screen(void)
+{
+    WOLFSSL_STUB("RAND_screen");
+}
+#endif
+
+
+
+int wolfSSL_RAND_load_file(const char* fname, long len)
+{
+    (void)fname;
+    /* wolfCrypt provides enough entropy internally or will report error */
+    if (len == -1)
+        return 1024;
+    else
+        return (int)len;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
+{
+    WOLFSSL_STUB("COMP_zlib");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
+{
+    WOLFSSL_STUB("COMP_rle");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_COMP_add_compression_method(int method, void* data)
+{
+    (void)method;
+    (void)data;
+    WOLFSSL_STUB("COMP_add_compression_method");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)(
+                                                          const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback");
+    (void)f;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_lock_callback(
+             void (*f)(int, WOLFSSL_dynlock_value*, const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback");
+    (void)f;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_set_dynlock_destroy_callback(
+                  void (*f)(WOLFSSL_dynlock_value*, const char*, int))
+{
+    WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback");
+    (void)f;
+}
+#endif
+
+
+const char* wolfSSL_X509_verify_cert_error_string(long err)
+{
+    return wolfSSL_ERR_reason_error_string(err);
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir,
+                               long len)
+{
+    (void)lookup;
+    (void)dir;
+    (void)len;
+    WOLFSSL_STUB("X509_LOOKUP_add_dir");
+    return 0;
+}
+#endif
+
+int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup,
+                                 const char* file, long type)
+{
+#if !defined(NO_FILESYSTEM) && \
+    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+    int           ret = WOLFSSL_FAILURE;
+    XFILE         fp;
+    long          sz;
+    byte*         pem = NULL;
+    byte*         curr = NULL;
+    byte*         prev = NULL;
+    WOLFSSL_X509* x509;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    if (type != X509_FILETYPE_PEM)
+        return BAD_FUNC_ARG;
+
+    fp = XFOPEN(file, "r");
+    if (fp == NULL)
+        return BAD_FUNC_ARG;
+
+    XFSEEK(fp, 0, XSEEK_END);
+    sz = XFTELL(fp);
+    XREWIND(fp);
+
+    if (sz <= 0)
+        goto end;
+
+    pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM);
+    if (pem == NULL) {
+        ret = MEMORY_ERROR;
+        goto end;
+    }
+
+    /* Read in file which may be CRLs or certificates. */
+    if (XFREAD(pem, (size_t)sz, 1, fp) != 1)
+        goto end;
+
+    prev = curr = pem;
+    do {
+        /* get PEM header and footer based on type */
+        if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
+                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+#ifdef HAVE_CRL
+            WOLFSSL_CERT_MANAGER* cm = lookup->store->cm;
+
+            if (cm->crl == NULL) {
+                if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Enable CRL failed");
+                    goto end;
+                }
+            }
+
+            ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM, 1);
+            if (ret != WOLFSSL_SUCCESS)
+                goto end;
+#endif
+            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+        }
+        else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
+                XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) {
+            x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz,
+                                                        WOLFSSL_FILETYPE_PEM);
+            if (x509 == NULL)
+                 goto end;
+            ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509);
+            wolfSSL_X509_free(x509);
+            if (ret != WOLFSSL_SUCCESS)
+                goto end;
+            curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz);
+        }
+        else
+            goto end;
+
+        if (curr == NULL)
+            goto end;
+
+        curr++;
+        sz -= (long)(curr - prev);
+        prev = curr;
+    }
+    while (ret == WOLFSSL_SUCCESS);
+
+end:
+    if (pem != NULL)
+        XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+    XFCLOSE(fp);
+    return ret;
+#else
+    (void)lookup;
+    (void)file;
+    (void)type;
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void)
+{
+    /* Method implementation in functions. */
+    static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 };
+    return &meth;
+}
+
+WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void)
+{
+    /* Method implementation in functions. */
+    static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 };
+    return &meth;
+}
+
+
+WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
+                                               WOLFSSL_X509_LOOKUP_METHOD* m)
+{
+    /* Method is a dummy value and is not needed. */
+    (void)m;
+    /* Make sure the lookup has a back reference to the store. */
+    store->lookup.store = store;
+    return &store->lookup;
+}
+
+
+#ifndef NO_CERTS
+/* Converts the X509 to DER format and outputs it into bio.
+ *
+ * bio  is the structure to hold output DER
+ * x509 certificate to create DER from
+ *
+ * returns WOLFSSL_SUCCESS on success
+ */
+int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
+{
+    WOLFSSL_ENTER("wolfSSL_i2d_X509_bio");
+
+    if (bio == NULL || x509 == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (x509->derCert != NULL) {
+        word32 len = x509->derCert->length;
+        byte*  der = x509->derCert->buffer;
+
+        if (wolfSSL_BIO_write(bio, der, len) == (int)len) {
+            return SSL_SUCCESS;
+        }
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Converts an internal structure to a DER buffer
+ *
+ * x509 structure to get DER buffer from
+ * out  buffer to hold result. If NULL then *out is NULL then a new buffer is
+ *      created.
+ *
+ * returns the size of the DER result on success
+ */
+int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
+{
+    const unsigned char* der;
+    int derSz = 0;
+
+    if (x509 == NULL || out == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    der = wolfSSL_X509_get_der(x509, &derSz);
+    if (der == NULL) {
+        return MEMORY_E;
+    }
+
+    if (*out == NULL) {
+        *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*out == NULL) {
+            return MEMORY_E;
+        }
+    }
+
+    XMEMCPY(*out, der, derSz);
+
+    return derSz;
+}
+
+
+/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
+ *
+ * bio  is the structure holding DER
+ * x509 certificate to create from DER. Can be NULL
+ *
+ * returns pointer to WOLFSSL_X509 structure on success and NULL on fail
+ */
+WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
+{
+    WOLFSSL_X509* localX509 = NULL;
+    unsigned char* mem  = NULL;
+    int    ret;
+    word32 size;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+    if (mem == NULL || ret <= 0) {
+        WOLFSSL_MSG("Failed to get data from bio struct");
+        return NULL;
+    }
+    size = ret;
+
+    localX509 = wolfSSL_X509_d2i(NULL, mem, size);
+    if (localX509 == NULL) {
+        return NULL;
+    }
+
+    if (x509 != NULL) {
+        *x509 = localX509;
+    }
+
+    return localX509;
+}
+
+
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
+{
+    WC_PKCS12* localPkcs12    = NULL;
+    unsigned char* mem  = NULL;
+    int ret;
+    word32 size;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    localPkcs12 = wc_PKCS12_new();
+    if (localPkcs12 == NULL) {
+        WOLFSSL_MSG("Memory error");
+        return NULL;
+    }
+
+    if (pkcs12 != NULL) {
+        *pkcs12 = localPkcs12;
+    }
+
+    ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+    if (mem == NULL || ret <= 0) {
+        WOLFSSL_MSG("Failed to get data from bio struct");
+        wc_PKCS12_free(localPkcs12);
+        if (pkcs12 != NULL) {
+            *pkcs12 = NULL;
+        }
+        return NULL;
+    }
+    size = ret;
+
+    ret = wc_d2i_PKCS12(mem, size, localPkcs12);
+    if (ret < 0) {
+        WOLFSSL_MSG("Failed to get PKCS12 sequence");
+        wc_PKCS12_free(localPkcs12);
+        if (pkcs12 != NULL) {
+            *pkcs12 = NULL;
+        }
+        return NULL;
+    }
+
+    return localPkcs12;
+}
+
+
+/* helper function to get DER buffer from WOLFSSL_EVP_PKEY */
+static int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+    *der = (unsigned char*)key->pkey.ptr;
+
+    return key->pkey_sz;
+}
+
+
+
+/* Creates a new WC_PKCS12 structure
+ *
+ * pass  password to use
+ * name  friendlyName to use
+ * pkey  private key to go into PKCS12 bundle
+ * cert  certificate to go into PKCS12 bundle
+ * ca    extra certificates that can be added to bundle. Can be NULL
+ * keyNID  type of encryption to use on the key (-1 means no encryption)
+ * certNID type of ecnryption to use on the certificate
+ * itt     number of iterations with encryption
+ * macItt  number of iterations with mac creation
+ * keyType flag for signature and/or encryption key
+ *
+ * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail
+ */
+WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
+        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
+        WOLF_STACK_OF(WOLFSSL_X509)* ca,
+        int keyNID, int certNID, int itt, int macItt, int keyType)
+{
+    WC_PKCS12*      pkcs12;
+    WC_DerCertList* list = NULL;
+    word32 passSz;
+    byte* keyDer;
+    word32 keyDerSz;
+    byte* certDer;
+    int certDerSz;
+
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PKCS12_create()");
+
+    if (pass == NULL || pkey == NULL || cert == NULL) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG);
+        return NULL;
+    }
+    passSz = (word32)XSTRLEN(pass);
+
+    if ((ret = wolfSSL_i2d_PrivateKey(pkey, &keyDer)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret);
+        return NULL;
+    }
+    keyDerSz = ret;
+
+    certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz);
+    if (certDer == NULL) {
+        return NULL;
+    }
+
+    if (ca != NULL) {
+        WC_DerCertList* cur;
+        unsigned long numCerts = ca->num;
+        byte* curDer;
+        int   curDerSz = 0;
+        WOLFSSL_STACK* sk = ca;
+
+        while (numCerts > 0 && sk != NULL) {
+            cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL,
+                    DYNAMIC_TYPE_PKCS);
+            if (cur == NULL) {
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+
+            curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz);
+            if (curDer == NULL || curDerSz < 0) {
+                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+
+            cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS);
+            if (cur->buffer == NULL) {
+                XFREE(cur, NULL, DYNAMIC_TYPE_PKCS);
+                wc_FreeCertList(list, NULL);
+                return NULL;
+            }
+            XMEMCPY(cur->buffer, curDer, curDerSz);
+            cur->bufferSz = curDerSz;
+            cur->next = list;
+            list = cur;
+
+            sk = sk->next;
+            numCerts--;
+        }
+    }
+
+    pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz,
+            certDer, certDerSz, list, keyNID, certNID, itt, macItt,
+            keyType, NULL);
+
+    if (ca != NULL) {
+        wc_FreeCertList(list, NULL);
+    }
+
+    return pkcs12;
+}
+
+
+/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */
+int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+      WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca)
+{
+    DecodedCert DeCert;
+    void* heap = NULL;
+    int ret;
+    byte* certData = NULL;
+    word32 certDataSz;
+    byte* pk = NULL;
+    word32 pkSz;
+    WC_DerCertList* certList = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
+
+    if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
+        WOLFSSL_MSG("Bad argument value");
+        return WOLFSSL_FAILURE;
+    }
+
+    heap  = wc_PKCS12_GetHeap(pkcs12);
+    *pkey = NULL;
+    *cert = NULL;
+
+    if (ca == NULL) {
+        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+            NULL);
+    }
+    else {
+        *ca = NULL;
+        ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
+            &certList);
+    }
+    if (ret < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Decode cert and place in X509 stack struct */
+    if (certList != NULL) {
+        WC_DerCertList* current = certList;
+
+        *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)),
+                                               heap, DYNAMIC_TYPE_X509);
+        if (*ca == NULL) {
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (certData != NULL) {
+                XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
+            }
+            /* Free up WC_DerCertList and move on */
+            while (current != NULL) {
+                WC_DerCertList* next = current->next;
+
+                XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                current = next;
+            }
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509)));
+
+        /* add list of DER certs as X509's to stack */
+        while (current != NULL) {
+            WC_DerCertList*  toFree = current;
+            WOLFSSL_X509* x509;
+
+            x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+                                                             DYNAMIC_TYPE_X509);
+            InitX509(x509, 1, heap);
+            InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap);
+            if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+                WOLFSSL_MSG("Issue with parsing certificate");
+                FreeDecodedCert(&DeCert);
+                wolfSSL_X509_free(x509);
+            }
+            else {
+                if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) {
+                    WOLFSSL_MSG("Failed to copy decoded cert");
+                    FreeDecodedCert(&DeCert);
+                    wolfSSL_X509_free(x509);
+                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    if (pk != NULL) {
+                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    }
+                    if (certData != NULL) {
+                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+                    }
+                    /* Free up WC_DerCertList */
+                    while (current != NULL) {
+                        WC_DerCertList* next = current->next;
+
+                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                        current = next;
+                    }
+                    return WOLFSSL_FAILURE;
+                }
+                FreeDecodedCert(&DeCert);
+
+                if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
+                    WOLFSSL_MSG("Failed to push x509 onto stack");
+                    wolfSSL_X509_free(x509);
+                    wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    if (pk != NULL) {
+                        XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+                    }
+                    if (certData != NULL) {
+                        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+                    }
+
+                    /* Free up WC_DerCertList */
+                    while (current != NULL) {
+                        WC_DerCertList* next = current->next;
+
+                        XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
+                        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
+                        current = next;
+                    }
+                    return WOLFSSL_FAILURE;
+                }
+            }
+            current = current->next;
+            XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS);
+            XFREE(toFree, heap, DYNAMIC_TYPE_PKCS);
+        }
+    }
+
+
+    /* Decode cert and place in X509 struct */
+    if (certData != NULL) {
+        *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
+                                                             DYNAMIC_TYPE_X509);
+        if (*cert == NULL) {
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+            return WOLFSSL_FAILURE;
+        }
+        InitX509(*cert, 1, heap);
+        InitDecodedCert(&DeCert, certData, certDataSz, heap);
+        if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
+            WOLFSSL_MSG("Issue with parsing certificate");
+        }
+        if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) {
+            WOLFSSL_MSG("Failed to copy decoded cert");
+            FreeDecodedCert(&DeCert);
+            if (pk != NULL) {
+                XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            }
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            return WOLFSSL_FAILURE;
+        }
+        FreeDecodedCert(&DeCert);
+        XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
+    }
+
+
+    /* get key type */
+    ret = BAD_STATE_E;
+    if (pk != NULL) { /* decode key if present */
+        *pkey = wolfSSL_PKEY_new_ex(heap);
+        if (*pkey == NULL) {
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+            return WOLFSSL_FAILURE;
+        }
+        #ifndef NO_RSA
+        {
+            word32 keyIdx = 0;
+            RsaKey key;
+
+            if (wc_InitRsaKey(&key, heap) != 0) {
+                ret = BAD_STATE_E;
+            }
+            else {
+                if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+                                                                         == 0) {
+                    (*pkey)->type = EVP_PKEY_RSA;
+                    (*pkey)->rsa  = wolfSSL_RSA_new();
+                    (*pkey)->ownRsa = 1; /* we own RSA */
+                    if ((*pkey)->rsa == NULL) {
+                        WOLFSSL_MSG("issue creating EVP RSA key");
+                        wolfSSL_X509_free(*cert); *cert = NULL;
+                        if (ca != NULL) {
+                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                        }
+                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                        return WOLFSSL_FAILURE;
+                    }
+                    if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz,
+                                    WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) {
+                        WOLFSSL_MSG("issue loading RSA key");
+                        wolfSSL_X509_free(*cert); *cert = NULL;
+                        if (ca != NULL) {
+                            wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                        }
+                        wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                        XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                        return WOLFSSL_FAILURE;
+                    }
+
+                    WOLFSSL_MSG("Found PKCS12 RSA key");
+                    ret = 0; /* set in success state for upcoming ECC check */
+                }
+                wc_FreeRsaKey(&key);
+            }
+        }
+        #endif /* NO_RSA */
+
+        #ifdef HAVE_ECC
+        {
+            word32  keyIdx = 0;
+            ecc_key key;
+
+            if (ret != 0) { /* if is in fail state check if ECC key */
+                if (wc_ecc_init(&key) != 0) {
+                    wolfSSL_X509_free(*cert); *cert = NULL;
+                    if (ca != NULL) {
+                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    }
+                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                    return WOLFSSL_FAILURE;
+                }
+
+                if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
+                                                                         != 0) {
+                    wolfSSL_X509_free(*cert); *cert = NULL;
+                    if (ca != NULL) {
+                        wolfSSL_sk_X509_free(*ca); *ca = NULL;
+                    }
+                    wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+                    XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+                    WOLFSSL_MSG("Bad PKCS12 key format");
+                    return WOLFSSL_FAILURE;
+                }
+                (*pkey)->type = EVP_PKEY_EC;
+                (*pkey)->pkey_curve = key.dp->oidSum;
+                wc_ecc_free(&key);
+                WOLFSSL_MSG("Found PKCS12 ECC key");
+            }
+        }
+        #else
+        if (ret != 0) { /* if is in fail state and no ECC then fail */
+            wolfSSL_X509_free(*cert); *cert = NULL;
+            if (ca != NULL) {
+                wolfSSL_sk_X509_free(*ca); *ca = NULL;
+            }
+            wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL;
+            XFREE(pk, heap, DYNAMIC_TYPE_PKCS);
+            WOLFSSL_MSG("Bad PKCS12 key format");
+            return WOLFSSL_FAILURE;
+        }
+        #endif /* HAVE_ECC */
+
+        (*pkey)->save_type = 0;
+        (*pkey)->pkey_sz   = pkSz;
+        (*pkey)->pkey.ptr  = (char*)pk;
+    }
+
+    (void)ret;
+    (void)ca;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */
+
+
+/* no-op function. Was initially used for adding encryption algorithms available
+ * for PKCS12 */
+void wolfSSL_PKCS12_PBE_add(void)
+{
+    WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
+}
+
+
+
+WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain");
+
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+#ifdef SESSION_CERTS
+    /* if chain is null but sesChain is available then populate stack */
+    if (ctx->chain == NULL && ctx->sesChain != NULL) {
+        int i;
+        WOLFSSL_X509_CHAIN* c = ctx->sesChain;
+        WOLFSSL_STACK*     sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),
+                                    NULL, DYNAMIC_TYPE_X509);
+
+        if (sk == NULL) {
+            return NULL;
+        }
+
+        XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
+        ctx->chain = sk;
+
+        for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) {
+            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i);
+
+            if (x509 == NULL) {
+                WOLFSSL_MSG("Unable to get x509 from chain");
+                wolfSSL_sk_X509_free(sk);
+                return NULL;
+            }
+
+            if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) {
+                WOLFSSL_MSG("Unable to load x509 into stack");
+                wolfSSL_sk_X509_free(sk);
+                wolfSSL_X509_free(x509);
+                return NULL;
+            }
+        }
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
+        /* add CA used to verify top of chain to the list */
+        if (c->count > 0) {
+            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1);
+            if (x509 != NULL) {
+                WOLFSSL_X509* issuer = NULL;
+                if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509)
+                        == WOLFSSL_SUCCESS) {
+                    /* check that the certificate being looked up is not self
+                     * signed and that a issuer was found */
+                    if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer,
+                                &x509->subject) != 0) {
+                        if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) {
+                            WOLFSSL_MSG("Unable to load CA x509 into stack");
+                            wolfSSL_sk_X509_free(sk);
+                            wolfSSL_X509_free(issuer);
+                            return NULL;
+                        }
+                    }
+                    else {
+                        WOLFSSL_MSG("Certificate is self signed");
+                    }
+                }
+                else {
+                    WOLFSSL_MSG("Could not find CA for certificate");
+                }
+            }
+        }
+#endif
+
+    }
+#endif /* SESSION_CERTS */
+
+    return ctx->chain;
+}
+
+
+int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
+{
+    int result = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert");
+    if (store != NULL && store->cm != NULL && x509 != NULL
+                                                && x509->derCert != NULL) {
+        DerBuffer* derCert = NULL;
+
+        result = AllocDer(&derCert, x509->derCert->length,
+            x509->derCert->type, NULL);
+        if (result == 0) {
+            /* AddCA() frees the buffer. */
+            XMEMCPY(derCert->buffer,
+                            x509->derCert->buffer, x509->derCert->length);
+            result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, 1);
+        }
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result);
+
+    if (result != WOLFSSL_SUCCESS) {
+        result = WOLFSSL_FATAL_ERROR;
+    }
+
+    return result;
+}
+
+WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
+{
+    WOLFSSL_X509_STORE* store = NULL;
+
+    if((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL,
+                            DYNAMIC_TYPE_X509_STORE)) == NULL)
+        goto err_exit;
+
+    if((store->cm = wolfSSL_CertManagerNew()) == NULL)
+        goto err_exit;
+
+    store->isDynamic = 1;
+
+#ifdef HAVE_CRL
+    store->crl = NULL;
+    if((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL),
+                                NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL)
+        goto err_exit;
+    if(InitCRL(store->crl, NULL) < 0)
+        goto err_exit;
+#endif
+
+    return store;
+
+err_exit:
+    if(store == NULL)
+        return NULL;
+    if(store->cm != NULL)
+        wolfSSL_CertManagerFree(store->cm);
+#ifdef HAVE_CRL
+    if(store->crl != NULL)
+        wolfSSL_X509_CRL_free(store->crl);
+#endif
+    wolfSSL_X509_STORE_free(store);
+
+    return NULL;
+}
+
+
+void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
+{
+    if (store != NULL && store->isDynamic) {
+        if (store->cm != NULL)
+            wolfSSL_CertManagerFree(store->cm);
+#ifdef HAVE_CRL
+        if (store->crl != NULL)
+            wolfSSL_X509_CRL_free(store->crl);
+#endif
+        XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE);
+    }
+}
+
+
+int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag)
+{
+    int ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags");
+
+    if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) {
+        ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag);
+    }
+
+    (void)store;
+    (void)flag;
+
+    return ret;
+}
+
+
+int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store)
+{
+    (void)store;
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
+                            WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj)
+{
+    (void)ctx;
+    (void)idx;
+    (void)name;
+    (void)obj;
+    WOLFSSL_STUB("X509_STORE_get_by_subject");
+    return 0;
+}
+#endif
+
+WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void)
+{
+    WOLFSSL_X509_STORE_CTX* ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
+                                    sizeof(WOLFSSL_X509_STORE_CTX), NULL,
+                                    DYNAMIC_TYPE_X509_CTX);
+    if (ctx != NULL) {
+        ctx->param = NULL;
+        wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL);
+    }
+
+    return ctx;
+}
+
+
+int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
+     WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk)
+{
+    (void)sk;
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init");
+    if (ctx != NULL) {
+        ctx->store = store;
+        ctx->current_cert = x509;
+        ctx->chain  = sk;
+        ctx->domain = NULL;
+#ifdef HAVE_EX_DATA
+        ctx->ex_data = NULL;
+#endif
+        ctx->userCtx = NULL;
+        ctx->error = 0;
+        ctx->error_depth = 0;
+        ctx->discardSessionCerts = 0;
+#ifdef OPENSSL_EXTRA
+        if (ctx->param == NULL) {
+            ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
+                           NULL,DYNAMIC_TYPE_OPENSSL);
+            if (ctx->param == NULL){
+                WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed");
+                return SSL_FATAL_ERROR;
+            }
+        }
+#endif
+        return SSL_SUCCESS;
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+
+
+void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    if (ctx != NULL) {
+        if (ctx->store != NULL)
+            wolfSSL_X509_STORE_free(ctx->store);
+        if (ctx->current_cert != NULL)
+            wolfSSL_FreeX509(ctx->current_cert);
+        if (ctx->chain != NULL)
+            wolfSSL_sk_X509_free(ctx->chain);
+#ifdef OPENSSL_EXTRA
+        if (ctx->param != NULL){
+            XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL);
+        }
+#endif
+        XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX);
+    }
+}
+
+
+void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    (void)ctx;
+    /* Do nothing */
+}
+
+
+int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
+{
+    if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL
+         && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
+        return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
+                    ctx->current_cert->derCert->buffer,
+                    ctx->current_cert->derCert->length,
+                    WOLFSSL_FILETYPE_ASN1);
+    }
+    return WOLFSSL_FATAL_ERROR;
+}
+#endif /* NO_CERTS */
+
+#if !defined(NO_FILESYSTEM)
+static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
+{
+    void *newx509 = NULL;
+    DerBuffer*   der = NULL;
+    byte *fileBuffer = NULL;
+
+    if (file != XBADFILE)
+    {
+        long sz = 0;
+
+        XFSEEK(file, 0, XSEEK_END);
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz < 0)
+        {
+            WOLFSSL_MSG("Bad tell on FILE");
+            return NULL;
+        }
+
+        fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+        if (fileBuffer != NULL)
+        {
+            if((long)XFREAD(fileBuffer, 1, sz, file) != sz)
+            {
+                WOLFSSL_MSG("File read failed");
+                goto err_exit;
+            }
+            if(type == CERT_TYPE)
+                newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
+            #ifdef HAVE_CRL
+            else if(type == CRL_TYPE)
+                newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
+            #endif
+            #if !defined(NO_ASN) && !defined(NO_PWDBASED)
+            else if(type == PKCS12_TYPE){
+                if((newx509 = wc_PKCS12_new()) == NULL)
+                    goto err_exit;
+                if(wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0)
+                    goto err_exit;
+            }
+            #endif
+            else goto err_exit;
+            if(newx509 == NULL)
+            {
+                WOLFSSL_MSG("X509 failed");
+                goto err_exit;
+            }
+        }
+    }
+    if (x509 != NULL)
+        *x509 = newx509;
+
+    goto _exit;
+
+err_exit:
+    if(newx509 != NULL){
+        if(type == CERT_TYPE)
+            wolfSSL_X509_free((WOLFSSL_X509*)newx509);
+        #ifdef HAVE_CRL
+        else {
+           if(type == CRL_TYPE)
+                wolfSSL_X509_CRL_free((WOLFSSL_X509_CRL*)newx509);
+        }
+        #endif
+    }
+_exit:
+    if(der != NULL)
+        FreeDer(&der);
+    if(fileBuffer != NULL)
+        XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
+    return newx509;
+}
+
+WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp");
+    return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE);
+}
+
+WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
+    return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+
+
+#ifdef HAVE_CRL
+#ifndef NO_FILESYSTEM
+WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl)
+{
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp");
+    return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl, const unsigned char* in, int len)
+{
+    WOLFSSL_X509_CRL *newcrl = NULL;
+    int ret ;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL");
+
+    if(in == NULL){
+        WOLFSSL_MSG("Bad argument value");
+        return NULL;
+    }
+
+    newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (newcrl == NULL){
+        WOLFSSL_MSG("New CRL allocation failed");
+        return NULL;
+    }
+    if (InitCRL(newcrl, NULL) < 0) {
+        WOLFSSL_MSG("Init tmp CRL failed");
+        goto err_exit;
+    }
+    ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1, 1);
+    if (ret != WOLFSSL_SUCCESS){
+        WOLFSSL_MSG("Buffer Load CRL failed");
+        goto err_exit;
+    }
+    if(crl){
+        *crl = newcrl;
+    }
+    goto _exit;
+
+err_exit:
+    if(newcrl != NULL)
+        wolfSSL_X509_CRL_free(newcrl);
+    newcrl = NULL;
+_exit:
+    return newcrl;
+}
+
+void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_CRL_free");
+
+    FreeCRL(crl, 1);
+    return;
+}
+#endif /* HAVE_CRL */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_lastUpdate");
+    return 0;
+}
+#endif
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_nextUpdate");
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
+{
+    (void)crl;
+    (void)key;
+    WOLFSSL_STUB("X509_CRL_verify");
+    return 0;
+}
+#endif
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA_X509_SMALL)
+/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the
+ * subset of X509 API */
+
+WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(){
+    return wolfSSL_PKEY_new_ex(NULL);
+}
+
+
+WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    int ret;
+    WOLFSSL_ENTER("wolfSSL_PKEY_new");
+    pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap,
+            DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pkey != NULL) {
+        XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY));
+        pkey->heap = heap;
+        pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
+#ifndef HAVE_FIPS
+        ret = wc_InitRng_ex(&(pkey->rng), heap, INVALID_DEVID);
+#else
+        ret = wc_InitRng(&(pkey->rng));
+#endif
+        if (ret != 0){
+            wolfSSL_EVP_PKEY_free(pkey);
+            WOLFSSL_MSG("memory falure");
+            return NULL;
+        }
+    }
+    else {
+        WOLFSSL_MSG("memory failure");
+    }
+
+    return pkey;
+}
+
+
+void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_ENTER("wolfSSL_PKEY_free");
+    if (key != NULL) {
+        wc_FreeRng(&(key->rng));
+        if (key->pkey.ptr != NULL)
+        {
+            XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        }
+        switch(key->type)
+        {
+            #ifndef NO_RSA
+            case EVP_PKEY_RSA:
+                if (key->rsa != NULL && key->ownRsa == 1) {
+                    wolfSSL_RSA_free(key->rsa);
+                }
+                break;
+            #endif /* NO_RSA */
+
+            #ifdef HAVE_ECC
+            case EVP_PKEY_EC:
+                if (key->ecc != NULL && key->ownEcc == 1) {
+                    wolfSSL_EC_KEY_free(key->ecc);
+                }
+                break;
+            #endif /* HAVE_ECC */
+
+            default:
+            break;
+        }
+        XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+}
+#endif /* OPENSSL_EXTRA_X509_SMALL */
+
+
+#ifdef OPENSSL_EXTRA
+
+void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx,
+                                    unsigned long flags,
+                                    time_t t)
+{
+    (void)flags;
+
+    if (ctx == NULL || ctx->param == NULL)
+        return;
+
+    ctx->param->check_time = t;
+    ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
+{
+    (void)obj;
+    WOLFSSL_STUB("X509_OBJECT_free_contents");
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime)
+{
+    (void)asnTime;
+    WOLFSSL_STUB("X509_cmp_current_time");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked)
+{
+    (void)revoked;
+    WOLFSSL_STUB("sk_X509_REVOKED_num");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl)
+{
+    (void)crl;
+    WOLFSSL_STUB("X509_CRL_get_REVOKED");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
+                                    WOLFSSL_X509_REVOKED* revoked, int value)
+{
+    (void)revoked;
+    (void)value;
+    WOLFSSL_STUB("sk_X509_REVOKED_value");
+    return 0;
+}
+#endif
+
+/* Used to create a new WOLFSSL_ASN1_INTEGER structure.
+ * returns a pointer to new structure on success and NULL on failure
+ */
+WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void)
+{
+    WOLFSSL_ASN1_INTEGER* a;
+
+    a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+    if (a == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER));
+    a->data    = a->intData;
+    a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
+    return a;
+}
+
+
+/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */
+void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in)
+{
+    if (in != NULL) {
+        if (in->isDynamic) {
+            XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+        XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+
+WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509)
+{
+    WOLFSSL_ASN1_INTEGER* a;
+    int i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber");
+
+    a = wolfSSL_ASN1_INTEGER_new();
+    if (a == NULL)
+        return NULL;
+
+    /* Make sure there is space for the data, ASN.1 type and length. */
+    if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
+        /* dynamicly create data buffer, +2 for type and length */
+        a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (a->data == NULL) {
+            wolfSSL_ASN1_INTEGER_free(a);
+            return NULL;
+        }
+        a->dataMax   = x509->serialSz + 2;
+        a->isDynamic = 1;
+    }
+
+    a->data[i++] = ASN_INTEGER;
+    i += SetLength(x509->serialSz, a->data + i);
+    XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
+
+    return a;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime)
+{
+    char buf[MAX_TIME_STRING_SZ];
+    int  ret = WOLFSSL_SUCCESS;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print");
+
+    if (bio == NULL || asnTime == NULL) {
+        WOLFSSL_MSG("NULL function argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf,
+                sizeof(buf)) == NULL) {
+        XMEMSET(buf, 0, MAX_TIME_STRING_SZ);
+        XMEMCPY(buf, "Bad time value", 14);
+        ret = WOLFSSL_FAILURE;
+    }
+
+    if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) {
+        WOLFSSL_MSG("Unable to write to bio");
+        return WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+
+
+char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
+{
+    int format;
+    int dateLen;
+    byte* date = (byte*)t;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string");
+
+    if (t == NULL || buf == NULL || len < 5) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+
+    format  = *date; date++;
+    dateLen = *date; date++;
+    if (dateLen > len) {
+        WOLFSSL_MSG("Length of date is longer then buffer");
+        return NULL;
+    }
+
+    if (!GetTimeString(date, format, buf, len)) {
+        return NULL;
+    }
+
+    return buf;
+}
+#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+    OPENSSL_EXTRA*/
+
+
+#ifdef OPENSSL_EXTRA
+
+#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && \
+    !defined(TIME_OVERRIDES) && !defined(NO_FILESYSTEM)
+
+WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t,
+                                    int offset_day, long offset_sec)
+{
+    const time_t sec_per_day = 24*60*60;
+    struct tm* ts = NULL;
+    struct tm* tmpTime = NULL;
+    time_t t_adj = 0;
+    time_t offset_day_sec = 0;
+
+#if defined(NEED_TMP_TIME)
+    struct tm tmpTimeStorage;
+    tmpTime = &tmpTimeStorage;
+#else
+    (void)tmpTime;
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj");
+
+    if (s == NULL){
+        s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL,
+                                        DYNAMIC_TYPE_OPENSSL);
+        if (s == NULL){
+            return NULL;
+        }
+    }
+
+    /* compute GMT time with offset */
+    offset_day_sec = offset_day * sec_per_day;
+    t_adj          = t + offset_day_sec + offset_sec;
+    ts             = (struct tm *)XGMTIME(&t_adj, tmpTime);
+    if (ts == NULL){
+        WOLFSSL_MSG("failed to get time data.");
+        XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+
+    /* create ASN1 time notation */
+    /* UTC Time */
+    if (ts->tm_year >= 50 && ts->tm_year < 150){
+        char utc_str[ASN_UTC_TIME_SIZE];
+        int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec;
+        byte *data_ptr = NULL;
+
+        if (ts->tm_year >= 50 && ts->tm_year < 100){
+            utc_year = ts->tm_year;
+        } else if (ts->tm_year >= 100 && ts->tm_year < 150){
+            utc_year = ts->tm_year - 100;
+        }
+        utc_mon  = ts->tm_mon + 1;
+        utc_day  = ts->tm_mday;
+        utc_hour = ts->tm_hour;
+        utc_min  = ts->tm_min;
+        utc_sec  = ts->tm_sec;
+        XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
+                  "%02d%02d%02d%02d%02d%02dZ",
+                  utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec);
+        data_ptr  = s->data;
+        *data_ptr = (byte) ASN_UTC_TIME; data_ptr++;
+        *data_ptr = (byte) ASN_UTC_TIME_SIZE; data_ptr++;
+        XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE);
+    /* GeneralizedTime */
+    } else {
+        char gt_str[ASN_GENERALIZED_TIME_SIZE];
+        int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec;
+        byte *data_ptr = NULL;
+
+        gt_year = ts->tm_year + 1900;
+        gt_mon  = ts->tm_mon + 1;
+        gt_day  = ts->tm_mday;
+        gt_hour = ts->tm_hour;
+        gt_min  = ts->tm_min;
+        gt_sec  = ts->tm_sec;
+        XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
+                  "%4d%02d%02d%02d%02d%02dZ",
+                  gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec);
+        data_ptr  = s->data;
+        *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++;
+        *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE; data_ptr++;
+        XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE);
+    }
+
+    return s;
+}
+#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES && !NO_FILESYSTEM */
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a,
+                            const WOLFSSL_ASN1_INTEGER* b)
+{
+    (void)a;
+    (void)b;
+    WOLFSSL_STUB("ASN1_INTEGER_cmp");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i)
+{
+    (void)i;
+    WOLFSSL_STUB("ASN1_INTEGER_get");
+    return 0;
+}
+#endif
+
+
+void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ctx != NULL && idx == 0)
+        return ctx->ex_data;
+#else
+    (void)ctx;
+    (void)idx;
+#endif
+    return 0;
+}
+
+
+/* Gets an index to store SSL structure at.
+ *
+ * Returns positive index on success and negative values on failure
+ */
+int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
+{
+    WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
+
+    /* store SSL at index 0 */
+    return 0;
+}
+
+
+/* Set an error stat in the X509 STORE CTX
+ *
+ */
+void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error");
+
+    if (ctx != NULL) {
+        ctx->error = er;
+    }
+}
+
+
+/* Sets a function callback that will send information about the state of all
+ * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
+ * in.
+ *
+ * ctx WOLFSSL_CTX structre to set callback function in
+ * f   callback function to use
+ */
+void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
+       void (*f)(const WOLFSSL* ssl, int type, int val))
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
+    if (ctx == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+    }
+    else {
+        ctx->CBIS = f;
+    }
+}
+
+
+unsigned long wolfSSL_ERR_peek_error(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
+
+    return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
+}
+
+
+/* This function is to find global error values that are the same through out
+ * all library version. With wolfSSL having only one set of error codes the
+ * return value is pretty straight forward. The only thing needed is all wolfSSL
+ * error values are typically negative.
+ *
+ * Returns the error reason
+ */
+int wolfSSL_ERR_GET_REASON(unsigned long err)
+{
+    int ret = (int)err;
+
+    WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    /* Nginx looks for this error to know to stop parsing certificates. */
+    if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE))
+        return PEM_R_NO_START_LINE;
+#endif
+
+    /* check if error value is in range of wolfSSL errors */
+    ret = 0 - ret; /* setting as negative value */
+    /* wolfCrypt range is less than MAX (-100)
+       wolfSSL range is MIN (-300) and lower */
+    if (ret < MAX_CODE_E) {
+        return ret;
+    }
+    else {
+        WOLFSSL_MSG("Not in range of typical error values");
+        ret = (int)err;
+    }
+
+    return ret;
+}
+
+
+/* returns a string that describes the alert
+ *
+ * alertID the alert value to look up
+ */
+const char* wolfSSL_alert_type_string_long(int alertID)
+{
+    WOLFSSL_ENTER("wolfSSL_aalert_type_string_long");
+
+    switch (alertID) {
+        case close_notify:
+            {
+                static const char close_notify_str[] =
+                    "close_notify";
+                return close_notify_str;
+            }
+
+        case unexpected_message:
+            {
+                static const char unexpected_message_str[] =
+                    "unexpected_message";
+                return unexpected_message_str;
+            }
+
+        case bad_record_mac:
+            {
+                static const char bad_record_mac_str[] =
+                    "bad_record_mac";
+                return bad_record_mac_str;
+            }
+
+        case record_overflow:
+            {
+                static const char record_overflow_str[] =
+                    "record_overflow";
+                return record_overflow_str;
+            }
+
+        case decompression_failure:
+            {
+                static const char decompression_failure_str[] =
+                    "decompression_failure";
+                return decompression_failure_str;
+            }
+
+        case handshake_failure:
+            {
+                static const char handshake_failure_str[] =
+                    "handshake_failure";
+                return handshake_failure_str;
+            }
+
+        case no_certificate:
+            {
+                static const char no_certificate_str[] =
+                    "no_certificate";
+                return no_certificate_str;
+            }
+
+        case bad_certificate:
+            {
+                static const char bad_certificate_str[] =
+                    "bad_certificate";
+                return bad_certificate_str;
+            }
+
+        case unsupported_certificate:
+            {
+                static const char unsupported_certificate_str[] =
+                    "unsupported_certificate";
+                return unsupported_certificate_str;
+            }
+
+        case certificate_revoked:
+            {
+                static const char certificate_revoked_str[] =
+                    "certificate_revoked";
+                return certificate_revoked_str;
+            }
+
+        case certificate_expired:
+            {
+                static const char certificate_expired_str[] =
+                    "certificate_expired";
+                return certificate_expired_str;
+            }
+
+        case certificate_unknown:
+            {
+                static const char certificate_unknown_str[] =
+                    "certificate_unknown";
+                return certificate_unknown_str;
+            }
+
+        case illegal_parameter:
+            {
+                static const char illegal_parameter_str[] =
+                    "illegal_parameter";
+                return illegal_parameter_str;
+            }
+
+        case decode_error:
+            {
+                static const char decode_error_str[] =
+                    "decode_error";
+                return decode_error_str;
+            }
+
+        case decrypt_error:
+            {
+                static const char decrypt_error_str[] =
+                    "decrypt_error";
+                return decrypt_error_str;
+            }
+
+    #ifdef WOLFSSL_MYSQL_COMPATIBLE
+    /* catch name conflict for enum protocol with MYSQL build */
+        case wc_protocol_version:
+            {
+                static const char wc_protocol_version_str[] =
+                    "wc_protocol_version";
+                return wc_protocol_version_str;
+            }
+
+    #else
+        case protocol_version:
+            {
+                static const char protocol_version_str[] =
+                    "protocol_version";
+                return protocol_version_str;
+            }
+
+    #endif
+        case no_renegotiation:
+            {
+                static const char no_renegotiation_str[] =
+                    "no_renegotiation";
+                return no_renegotiation_str;
+            }
+
+        case unrecognized_name:
+            {
+                static const char unrecognized_name_str[] =
+                    "unrecognized_name";
+                return unrecognized_name_str;
+            }
+
+        case bad_certificate_status_response:
+            {
+                static const char bad_certificate_status_response_str[] =
+                    "bad_certificate_status_response";
+                return bad_certificate_status_response_str;
+            }
+
+        case no_application_protocol:
+            {
+                static const char no_application_protocol_str[] =
+                    "no_application_protocol";
+                return no_application_protocol_str;
+            }
+
+        default:
+            WOLFSSL_MSG("Unknown Alert");
+            return NULL;
+    }
+}
+
+
+const char* wolfSSL_alert_desc_string_long(int alertID)
+{
+    WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
+    return wolfSSL_alert_type_string_long(alertID);
+}
+
+
+/* Gets the current state of the WOLFSSL structure
+ *
+ * ssl WOLFSSL structure to get state of
+ *
+ * Returns a human readable string of the WOLFSSL structure state
+ */
+const char* wolfSSL_state_string_long(const WOLFSSL* ssl)
+{
+
+    static const char* OUTPUT_STR[14][6][3] = {
+        {
+            {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"},
+            {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"},
+            {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"},
+            {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"},
+            {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"},
+            {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"},
+        },
+        {
+            {"SSLv3 read Server Hello Verify Request",
+             "SSLv3 write Server Hello Verify Request",
+             "SSLv3 Server Hello Verify Request"},
+            {"TLSv1 read Server Hello Verify Request",
+             "TLSv1 write Server Hello Verify Request",
+             "TLSv1 Server Hello Verify Request"},
+            {"TLSv1_1 read Server Hello Verify Request",
+            "TLSv1_1 write Server Hello Verify Request",
+             "TLSv1_1 Server Hello Verify Request"},
+            {"TLSv1_2 read Server Hello Verify Request",
+            "TLSv1_2 write Server Hello Verify Request",
+             "TLSv1_2 Server Hello Verify Request"},
+            {"DTLSv1 read Server Hello Verify Request",
+             "DTLSv1 write Server Hello Verify Request",
+             "DTLSv1 Server Hello Verify Request"},
+            {"DTLSv1_2 read Server Hello Verify Request",
+             "DTLSv1_2 write Server Hello Verify Request",
+             "DTLSv1_2 Server Hello Verify Request"},
+        },
+        {
+            {"SSLv3 read Server Hello",
+             "SSLv3 write Server Hello",
+             "SSLv3 Server Hello"},
+            {"TLSv1 read Server Hello",
+             "TLSv1 write Server Hello",
+             "TLSv1 Server Hello"},
+            {"TLSv1_1 read Server Hello",
+            "TLSv1_1 write Server Hello",
+             "TLSv1_1 Server Hello"},
+            {"TLSv1_2 read Server Hello",
+            "TLSv1_2 write Server Hello",
+             "TLSv1_2 Server Hello"},
+            {"DTLSv1 read Server Hello",
+            "DTLSv1 write Server Hello",
+             "DTLSv1 Server Hello"},
+            {"DTLSv1_2 read Server Hello"
+             "DTLSv1_2 write Server Hello",
+             "DTLSv1_2 Server Hello",
+            },
+        },
+        {
+            {"SSLv3 read Server Session Ticket",
+             "SSLv3 write Server Session Ticket",
+             "SSLv3 Server Session Ticket"},
+            {"TLSv1 read Server Session Ticket",
+             "TLSv1 write Server Session Ticket",
+             "TLSv1 Server Session Ticket"},
+            {"TLSv1_1 read Server Session Ticket",
+             "TLSv1_1 write Server Session Ticket",
+             "TLSv1_1 Server Session Ticket"},
+            {"TLSv1_2 read Server Session Ticket",
+             "TLSv1_2 write Server Session Ticket",
+             "TLSv1_2 Server Session Ticket"},
+            {"DTLSv1 read Server Session Ticket",
+             "DTLSv1 write Server Session Ticket",
+             "DTLSv1 Server Session Ticket"},
+            {"DTLSv1_2 read Server Session Ticket",
+             "DTLSv1_2 write Server Session Ticket",
+             "DTLSv1_2 Server Session Ticket"},
+        },
+        {
+            {"SSLv3 read Server Cert",
+             "SSLv3 write Server Cert",
+             "SSLv3 Server Cert"},
+            {"TLSv1 read Server Cert",
+             "TLSv1 write Server Cert",
+             "TLSv1 Server Cert"},
+            {"TLSv1_1 read Server Cert",
+             "TLSv1_1 write Server Cert",
+             "TLSv1_1 Server Cert"},
+            {"TLSv1_2 read Server Cert",
+             "TLSv1_2 write Server Cert",
+             "TLSv1_2 Server Cert"},
+            {"DTLSv1 read Server Cert",
+             "DTLSv1 write Server Cert",
+             "DTLSv1 Server Cert"},
+            {"DTLSv1_2 read Server Cert",
+             "DTLSv1_2 write Server Cert",
+             "DTLSv1_2 Server Cert"},
+        },
+        {
+            {"SSLv3 read Server Key Exchange",
+             "SSLv3 write Server Key Exchange",
+             "SSLv3 Server Key Exchange"},
+            {"TLSv1 read Server Key Exchange",
+             "TLSv1 write Server Key Exchange",
+             "TLSv1 Server Key Exchange"},
+            {"TLSv1_1 read Server Key Exchange",
+             "TLSv1_1 write Server Key Exchange",
+             "TLSv1_1 Server Key Exchange"},
+            {"TLSv1_2 read Server Key Exchange",
+             "TLSv1_2 write Server Key Exchange",
+             "TLSv1_2 Server Key Exchange"},
+            {"DTLSv1 read Server Key Exchange",
+             "DTLSv1 write Server Key Exchange",
+             "DTLSv1 Server Key Exchange"},
+            {"DTLSv1_2 read Server Key Exchange",
+             "DTLSv1_2 write Server Key Exchange",
+             "DTLSv1_2 Server Key Exchange"},
+        },
+        {
+            {"SSLv3 read Server Hello Done",
+             "SSLv3 write Server Hello Done",
+             "SSLv3 Server Hello Done"},
+            {"TLSv1 read Server Hello Done",
+             "TLSv1 write Server Hello Done",
+             "TLSv1 Server Hello Done"},
+            {"TLSv1_1 read Server Hello Done",
+             "TLSv1_1 write Server Hello Done",
+             "TLSv1_1 Server Hello Done"},
+            {"TLSv1_2 read Server Hello Done",
+             "TLSv1_2 write Server Hello Done",
+             "TLSv1_2 Server Hello Done"},
+            {"DTLSv1 read Server Hello Done",
+             "DTLSv1 write Server Hello Done",
+             "DTLSv1 Server Hello Done"},
+            {"DTLSv1_2 read Server Hello Done",
+             "DTLSv1_2 write Server Hello Done",
+             "DTLSv1_2 Server Hello Done"},
+        },
+        {
+            {"SSLv3 read Server Change CipherSpec",
+             "SSLv3 write Server Change CipherSpec",
+             "SSLv3 Server Change CipherSpec"},
+            {"TLSv1 read Server Change CipherSpec",
+             "TLSv1 write Server Change CipherSpec",
+             "TLSv1 Server Change CipherSpec"},
+            {"TLSv1_1 read Server Change CipherSpec",
+             "TLSv1_1 write Server Change CipherSpec",
+             "TLSv1_1 Server Change CipherSpec"},
+            {"TLSv1_2 read Server Change CipherSpec",
+             "TLSv1_2 write Server Change CipherSpec",
+             "TLSv1_2 Server Change CipherSpec"},
+            {"DTLSv1 read Server Change CipherSpec",
+             "DTLSv1 write Server Change CipherSpec",
+             "DTLSv1 Server Change CipherSpec"},
+            {"DTLSv1_2 read Server Change CipherSpec",
+             "DTLSv1_2 write Server Change CipherSpec",
+             "DTLSv1_2 Server Change CipherSpec"},
+        },
+        {
+            {"SSLv3 read Server Finished",
+             "SSLv3 write Server Finished",
+             "SSLv3 Server Finished"},
+            {"TLSv1 read Server Finished",
+             "TLSv1 write Server Finished",
+             "TLSv1 Server Finished"},
+            {"TLSv1_1 read Server Finished",
+             "TLSv1_1 write Server Finished",
+             "TLSv1_1 Server Finished"},
+            {"TLSv1_2 read Server Finished",
+             "TLSv1_2 write Server Finished",
+             "TLSv1_2 Server Finished"},
+            {"DTLSv1 read Server Finished",
+             "DTLSv1 write Server Finished",
+             "DTLSv1 Server Finished"},
+            {"DTLSv1_2 read Server Finished",
+             "DTLSv1_2 write Server Finished",
+             "DTLSv1_2 Server Finished"},
+        },
+        {
+            {"SSLv3 read Client Hello",
+             "SSLv3 write Client Hello",
+             "SSLv3 Client Hello"},
+            {"TLSv1 read Client Hello",
+             "TLSv1 write Client Hello",
+             "TLSv1 Client Hello"},
+            {"TLSv1_1 read Client Hello",
+             "TLSv1_1 write Client Hello",
+             "TLSv1_1 Client Hello"},
+            {"TLSv1_2 read Client Hello",
+             "TLSv1_2 write Client Hello",
+             "TLSv1_2 Client Hello"},
+            {"DTLSv1 read Client Hello",
+             "DTLSv1 write Client Hello",
+             "DTLSv1 Client Hello"},
+            {"DTLSv1_2 read Client Hello",
+             "DTLSv1_2 write Client Hello",
+             "DTLSv1_2 Client Hello"},
+        },
+        {
+            {"SSLv3 read Client Key Exchange",
+             "SSLv3 write Client Key Exchange",
+             "SSLv3 Client Key Exchange"},
+            {"TLSv1 read Client Key Exchange",
+             "TLSv1 write Client Key Exchange",
+             "TLSv1 Client Key Exchange"},
+            {"TLSv1_1 read Client Key Exchange",
+             "TLSv1_1 write Client Key Exchange",
+             "TLSv1_1 Client Key Exchange"},
+            {"TLSv1_2 read Client Key Exchange",
+             "TLSv1_2 write Client Key Exchange",
+             "TLSv1_2 Client Key Exchange"},
+            {"DTLSv1 read Client Key Exchange",
+             "DTLSv1 write Client Key Exchange",
+             "DTLSv1 Client Key Exchange"},
+            {"DTLSv1_2 read Client Key Exchange",
+             "DTLSv1_2 write Client Key Exchange",
+             "DTLSv1_2 Client Key Exchange"},
+        },
+        {
+            {"SSLv3 read Client Change CipherSpec",
+             "SSLv3 write Client Change CipherSpec",
+             "SSLv3 Client Change CipherSpec"},
+            {"TLSv1 read Client Change CipherSpec",
+             "TLSv1 write Client Change CipherSpec",
+             "TLSv1 Client Change CipherSpec"},
+            {"TLSv1_1 read Client Change CipherSpec",
+             "TLSv1_1 write Client Change CipherSpec",
+             "TLSv1_1 Client Change CipherSpec"},
+            {"TLSv1_2 read Client Change CipherSpec",
+             "TLSv1_2 write Client Change CipherSpec",
+             "TLSv1_2 Client Change CipherSpec"},
+            {"DTLSv1 read Client Change CipherSpec",
+             "DTLSv1 write Client Change CipherSpec",
+             "DTLSv1 Client Change CipherSpec"},
+            {"DTLSv1_2 read Client Change CipherSpec",
+             "DTLSv1_2 write Client Change CipherSpec",
+             "DTLSv1_2 Client Change CipherSpec"},
+        },
+        {
+            {"SSLv3 read Client Finished",
+             "SSLv3 write Client Finished",
+             "SSLv3 Client Finished"},
+            {"TLSv1 read Client Finished",
+             "TLSv1 write Client Finished",
+             "TLSv1 Client Finished"},
+            {"TLSv1_1 read Client Finished",
+             "TLSv1_1 write Client Finished",
+             "TLSv1_1 Client Finished"},
+            {"TLSv1_2 read Client Finished",
+             "TLSv1_2 write Client Finished",
+             "TLSv1_2 Client Finished"},
+            {"DTLSv1 read Client Finished",
+             "DTLSv1 write Client Finished",
+             "DTLSv1 Client Finished"},
+            {"DTLSv1_2 read Client Finished",
+             "DTLSv1_2 write Client Finished",
+             "DTLSv1_2 Client Finished"},
+        },
+        {
+            {"SSLv3 Handshake Done",
+             "SSLv3 Handshake Done",
+             "SSLv3 Handshake Done"},
+            {"TLSv1 Handshake Done",
+             "TLSv1 Handshake Done",
+             "TLSv1 Handshake Done"},
+            {"TLSv1_1 Handshake Done",
+             "TLSv1_1 Handshake Done",
+             "TLSv1_1 Handshake Done"},
+            {"TLSv1_2 Handshake Done",
+             "TLSv1_2 Handshake Done",
+             "TLSv1_2 Handshake Done"},
+            {"DTLSv1 Handshake Done",
+             "DTLSv1 Handshake Done",
+             "DTLSv1 Handshake Done"},
+            {"DTLSv1_2 Handshake Done"
+             "DTLSv1_2 Handshake Done"
+             "DTLSv1_2 Handshake Done"}
+        }
+    };
+    enum ProtocolVer {
+        SSL_V3 = 0,
+        TLS_V1,
+        TLS_V1_1,
+        TLS_V1_2,
+        DTLS_V1,
+        DTLS_V1_2,
+        UNKNOWN = 100
+    };
+
+    enum IOMode {
+        SS_READ = 0,
+        SS_WRITE,
+        SS_NEITHER
+    };
+
+    enum SslState {
+        ss_null_state = 0,
+        ss_server_helloverify,
+        ss_server_hello,
+        ss_sessionticket,
+        ss_server_cert,
+        ss_server_keyexchange,
+        ss_server_hellodone,
+        ss_server_changecipherspec,
+        ss_server_finished,
+        ss_client_hello,
+        ss_client_keyexchange,
+        ss_client_changecipherspec,
+        ss_client_finished,
+        ss_handshake_done
+    };
+
+    int protocol = 0;
+    int cbmode = 0;
+    int state = 0;
+
+    WOLFSSL_ENTER("wolfSSL_state_string_long");
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return NULL;
+    }
+
+    /* Get state of callback */
+    if (ssl->cbmode == SSL_CB_MODE_WRITE){
+        cbmode =  SS_WRITE;
+    } else if (ssl->cbmode == SSL_CB_MODE_READ){
+        cbmode =  SS_READ;
+    } else {
+        cbmode =  SS_NEITHER;
+    }
+
+    /* Get protocol version */
+    switch (ssl->version.major){
+        case SSLv3_MAJOR:
+            switch (ssl->version.minor){
+                case TLSv1_MINOR:
+                    protocol = TLS_V1;
+                    break;
+                case TLSv1_1_MINOR:
+                    protocol = TLS_V1_1;
+                    break;
+                case TLSv1_2_MINOR:
+                    protocol = TLS_V1_2;
+                    break;
+                case SSLv3_MINOR:
+                    protocol = SSL_V3;
+                    break;
+                default:
+                    protocol = UNKNOWN;
+            }
+            break;
+        case DTLS_MAJOR:
+            switch (ssl->version.minor){
+        case DTLS_MINOR:
+            protocol = DTLS_V1;
+            break;
+        case DTLSv1_2_MINOR:
+            protocol = DTLS_V1_2;
+            break;
+        default:
+            protocol = UNKNOWN;
+    }
+    break;
+    default:
+        protocol = UNKNOWN;
+    }
+
+    /* accept process */
+    if (ssl->cbmode == SSL_CB_MODE_READ){
+        state = ssl->cbtype;
+        switch (state) {
+            case hello_verify_request:
+                state = ss_server_helloverify;
+                break;
+            case session_ticket:
+                state = ss_sessionticket;
+                break;
+            case server_hello:
+                state = ss_server_hello;
+                break;
+            case server_hello_done:
+                state = ss_server_hellodone;
+                break;
+            case certificate:
+                state = ss_server_cert;
+                break;
+            case server_key_exchange:
+                state = ss_server_keyexchange;
+                break;
+            case client_hello:
+                state = ss_client_hello;
+                break;
+            case client_key_exchange:
+                state = ss_client_keyexchange;
+                break;
+            case finished:
+                if (ssl->options.side == WOLFSSL_SERVER_END)
+                    state = ss_client_finished;
+                else if (ssl->options.side == WOLFSSL_CLIENT_END)
+                    state = ss_server_finished;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown State");
+                state = ss_null_state;
+        }
+    } else {
+        /* Send process */
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            state = ssl->options.serverState;
+        else
+            state = ssl->options.clientState;
+
+        switch(state){
+            case SERVER_HELLOVERIFYREQUEST_COMPLETE:
+                state = ss_server_helloverify;
+                break;
+            case SERVER_HELLO_COMPLETE:
+                state = ss_server_hello;
+                break;
+            case SERVER_CERT_COMPLETE:
+                state = ss_server_cert;
+                break;
+            case SERVER_KEYEXCHANGE_COMPLETE:
+                state = ss_server_keyexchange;
+                break;
+            case SERVER_HELLODONE_COMPLETE:
+                state = ss_server_hellodone;
+                break;
+            case SERVER_CHANGECIPHERSPEC_COMPLETE:
+                state = ss_server_changecipherspec;
+                break;
+            case SERVER_FINISHED_COMPLETE:
+                state = ss_server_finished;
+                break;
+            case CLIENT_HELLO_COMPLETE:
+                state = ss_client_hello;
+                break;
+            case CLIENT_KEYEXCHANGE_COMPLETE:
+                state = ss_client_keyexchange;
+                break;
+            case CLIENT_CHANGECIPHERSPEC_COMPLETE:
+                state = ss_client_changecipherspec;
+                break;
+            case CLIENT_FINISHED_COMPLETE:
+                state = ss_client_finished;
+                break;
+            case HANDSHAKE_DONE:
+                state = ss_handshake_done;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown State");
+                state = ss_null_state;
+        }
+    }
+
+    if (protocol == UNKNOWN)
+        return NULL;
+    else
+        return OUTPUT_STR[state][protocol][cbmode];
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
+{
+    (void)name;
+    (void)num;
+    (void)w;
+    (void)key;
+    WOLFSSL_STUB("PEM_def_callback");
+    return 0;
+}
+#endif
+
+static long wolf_set_options(long old_op, long op)
+{
+    /* if SSL_OP_ALL then turn all bug workarounds on */
+    if ((op & SSL_OP_ALL) == SSL_OP_ALL) {
+        WOLFSSL_MSG("\tSSL_OP_ALL");
+
+        op |= SSL_OP_MICROSOFT_SESS_ID_BUG;
+        op |= SSL_OP_NETSCAPE_CHALLENGE_BUG;
+        op |= SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
+        op |= SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
+        op |= SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
+        op |= SSL_OP_MSIE_SSLV2_RSA_PADDING;
+        op |= SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
+        op |= SSL_OP_TLS_D5_BUG;
+        op |= SSL_OP_TLS_BLOCK_PADDING_BUG;
+        op |= SSL_OP_TLS_ROLLBACK_BUG;
+        op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+    }
+
+    /* by default cookie exchange is on with DTLS */
+    if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) {
+        WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default");
+    }
+
+    if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
+        WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
+    }
+
+    if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+        WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
+    }
+
+    if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+        WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
+    }
+
+    if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+    #ifdef HAVE_LIBZ
+        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
+    #else
+        WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
+    #endif
+    }
+
+    return old_op | op;
+}
+
+long wolfSSL_set_options(WOLFSSL* ssl, long op)
+{
+    word16 haveRSA = 1;
+    word16 havePSK = 0;
+    int    keySz   = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_options");
+
+    if (ssl == NULL) {
+        return 0;
+    }
+
+    ssl->options.mask = wolf_set_options(ssl->options.mask, op);
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+        if (ssl->version.minor == TLSv1_3_MINOR)
+            ssl->version.minor = TLSv1_2_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+        if (ssl->version.minor == TLSv1_2_MINOR)
+            ssl->version.minor = TLSv1_1_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+        if (ssl->version.minor == TLSv1_1_MINOR)
+            ssl->version.minor = TLSv1_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+        if (ssl->version.minor == TLSv1_MINOR)
+            ssl->version.minor = SSLv3_MINOR;
+    }
+
+    if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) {
+    #ifdef HAVE_LIBZ
+        ssl->options.usingCompression = 0;
+    #endif
+    }
+
+    /* in the case of a version change the cipher suites should be reset */
+#ifndef NO_PSK
+    havePSK = ssl->options.havePSK;
+#endif
+#ifdef NO_RSA
+    haveRSA = 0;
+#endif
+#ifndef NO_CERTS
+    keySz = ssl->buffers.keySz;
+#endif
+
+    InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK,
+                       ssl->options.haveDH, ssl->options.haveNTRU,
+                       ssl->options.haveECDSAsig, ssl->options.haveECC,
+                       ssl->options.haveStaticECC, ssl->options.side);
+
+    return ssl->options.mask;
+}
+
+
+long wolfSSL_get_options(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_options");
+    if(ssl == NULL)
+        return WOLFSSL_FAILURE;
+    return ssl->options.mask;
+}
+
+long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
+{
+    WOLFSSL_ENTER("SSL_clear_options");
+    if(ssl == NULL)
+        return WOLFSSL_FAILURE;
+    ssl->options.mask &= ~opt;
+    return ssl->options.mask;
+}
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s)
+{
+    (void)s;
+    WOLFSSL_STUB("SSL_clear_num_renegotiations");
+    return 0;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s)
+{
+    (void)s;
+    WOLFSSL_STUB("SSL_total_renegotiations");
+    return 0;
+}
+#endif
+
+#ifndef NO_DH
+long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
+{
+    int pSz, gSz;
+    byte *p, *g;
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
+
+    if (!ssl || !dh)
+        return BAD_FUNC_ARG;
+
+    /* Get needed size for p and g */
+    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+    if (pSz <= 0 || gSz <= 0)
+        return WOLFSSL_FATAL_ERROR;
+
+    p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (!p)
+        return MEMORY_E;
+
+    g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (!g) {
+        XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return MEMORY_E;
+    }
+
+    pSz = wolfSSL_BN_bn2bin(dh->p, p);
+    gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+    if (pSz >= 0 && gSz >= 0) /* Conversion successful */
+        ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
+
+    XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* !NO_DH */
+
+
+#ifdef HAVE_PK_CALLBACKS
+long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
+{
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ssl->loggingCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_PK_CALLBACKS */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length)
+{
+    const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length);
+    return c;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
+{
+    (void)st;
+    WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
+    /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
+{
+    WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
+
+    if (s == NULL){
+        return BAD_FUNC_ARG;
+    }
+
+    if (type == TLSEXT_STATUSTYPE_ocsp){
+        int r = 0;
+        r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s,
+                                                             s->heap, s->devId);
+        return (long)r;
+    } else {
+        WOLFSSL_MSG(
+       "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
+        return SSL_FAILURE;
+    }
+
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+    (void)s;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len)
+{
+    (void)s;
+    (void)sid;
+    (void)sid_len;
+    WOLFSSL_STUB("SSL_SESSION_set1_id");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len)
+{
+    (void)s;
+    (void)sid_ctx;
+    (void)sid_ctx_len;
+    WOLFSSL_STUB("SSL_SESSION_set1_id_context");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x)
+{
+    (void)x;
+    WOLFSSL_STUB("X509_get0_tbs_sigalg");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor)
+{
+    (void)paobj;
+    (void)pptype;
+    (void)ppval;
+    (void)algor;
+    WOLFSSL_STUB("X509_ALGOR_get0");
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void *X509_get_X509_PUBKEY(void * x)
+{
+    (void)x;
+    WOLFSSL_STUB("X509_get_X509_PUBKEY");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub)
+{
+    (void)ppkalg;
+    (void)pk;
+    (void)ppklen;
+    (void)pa;
+    (void)pub;
+    WOLFSSL_STUB("X509_PUBKEY_get0_param");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
+{
+    (void)ssl;
+    WOLFSSL_STUB("SSL_get_privatekey");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a)
+{
+    (void)buf;
+    (void)buf_len;
+    (void)a;
+    WOLFSSL_STUB("i2t_ASN1_OBJECT");
+    return -1;
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+    (void)s;
+    (void)buf;
+    (void)count;
+    WOLFSSL_STUB("SSL_get_finished");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count)
+{
+    (void)s;
+    (void)buf;
+    (void)count;
+    WOLFSSL_STUB("SSL_get_peer_finished");
+    return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* WOLFSSL_HAPROXY */
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
+{
+    (void)ctx;
+    (void)dh;
+    WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+{
+    WOLFSSL_STUB("SSL_COMP_get_compression_methods");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p)
+{
+    (void)p;
+    WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num");
+    return -1;
+}
+#endif
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+    WOLFSSL_STUB("PEM_read_X509");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+    WOLFSSL_STUB("PEM_read_PrivateKey");
+    return NULL;
+}
+#endif
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir)
+{
+    (void)ctx;
+    (void)file;
+    (void)dir;
+    WOLFSSL_STUB("X509_STORE_load_locations");
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx)
+{
+    (void)ciphers;
+    (void)idx;
+    WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value");
+    return NULL;
+}
+#endif
+
+WOLFSSL_API void ERR_load_SSL_strings(void)
+{
+
+}
+
+#ifdef HAVE_OCSP
+WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
+{
+    if (s == NULL || resp == NULL)
+        return 0;
+
+    *resp = s->ocspResp;
+    return s->ocspRespSz;
+}
+
+WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len)
+{
+    if (s == NULL)
+        return WOLFSSL_FAILURE;
+
+    s->ocspResp   = resp;
+    s->ocspRespSz = len;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_OCSP */
+
+long wolfSSL_get_verify_result(const WOLFSSL *ssl)
+{
+    if (ssl == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ssl->peerVerifyRet;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts attempted by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects attempted CTX in it's lifetime */
+long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts completed by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects completed by CTX in it's lifetime */
+long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
+long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
+long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
+    (void)ctx;
+    return 0;
+}
+#endif
+
+
+/* Return the total number of sessions */
+long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
+{
+    word32 total = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
+    (void)ctx;
+
+#ifdef WOLFSSL_SESSION_STATS
+    if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error getting session stats");
+    }
+#else
+    WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
+#endif
+
+    return (long)total;
+}
+
+
+#ifndef NO_CERTS
+long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+{
+    byte* chain = NULL;
+    long  chainSz = 0;
+    int   derSz;
+    const byte* der;
+    int   ret;
+    int   idx = 0;
+    DerBuffer *derBuffer = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
+
+    if (ctx == NULL || x509 == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x509, &derSz);
+    if (der == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Error getting X509 DER");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (ctx->certificate == NULL) {
+        /* Process buffer makes first certificate the leaf. */
+        ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
+                            NULL, NULL, 1);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+            return WOLFSSL_FAILURE;
+        }
+    }
+    else {
+        /* TODO: Do this elsewhere. */
+        ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap);
+        if (ret != 0) {
+            WOLFSSL_MSG("Memory Error");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMCPY(derBuffer->buffer, der, derSz);
+        ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
+            return WOLFSSL_FAILURE;
+        }
+
+        /* adding cert to existing chain */
+        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+            chainSz += ctx->certChain->length;
+        }
+        chainSz += OPAQUE24_LEN + derSz;
+
+        chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
+        if (chain == NULL) {
+            WOLFSSL_MSG("Memory Error");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (ctx->certChain != NULL && ctx->certChain->length > 0) {
+            XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length);
+            idx = ctx->certChain->length;
+        }
+        c32to24(derSz, chain + idx);
+        idx += OPAQUE24_LEN,
+        XMEMCPY(chain + idx, der, derSz);
+        idx += derSz;
+#ifdef WOLFSSL_TLS13
+        ctx->certChainCnt++;
+#endif
+
+        FreeDer(&ctx->certChain);
+        ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
+        if (ret == 0) {
+            XMEMCPY(ctx->certChain->buffer, chain, idx);
+        }
+    }
+
+    /* on success WOLFSSL_X509 memory is responsibility of ctx */
+    wolfSSL_X509_free(x509);
+    if (chain != NULL)
+        XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+    if (ctx == NULL || ctx->cm == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->cm->ocspIOCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_CERTS */
+
+
+/* Get the session cache mode for CTX
+ *
+ * ctx  WOLFSSL_CTX struct to get cache mode from
+ *
+ * Returns a bit mask that has the session cache mode */
+WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx)
+{
+    long m = 0;
+
+    WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode");
+
+    if (ctx == NULL) {
+        return m;
+    }
+
+    if (ctx->sessionCacheOff != 1) {
+        m |= SSL_SESS_CACHE_SERVER;
+    }
+
+    if (ctx->sessionCacheFlushOff == 1) {
+        m |= SSL_SESS_CACHE_NO_AUTO_CLEAR;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (ctx->internalCacheOff == 1) {
+        m |= SSL_SESS_CACHE_NO_INTERNAL_STORE;
+    }
+#endif
+
+    return m;
+}
+
+
+int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    return ctx->readAhead;
+}
+
+
+int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->readAhead = (byte)v;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
+        void* arg)
+{
+    if (ctx == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ctx->userPRFArg = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_DES3
+/* 0 on success */
+int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+#ifdef WOLFSSL_CHECK_DESKEY
+    return wolfSSL_DES_set_key_checked(myDes, key);
+#else
+    wolfSSL_DES_set_key_unchecked(myDes, key);
+    return 0;
+#endif
+}
+
+
+
+/* return true in fail case (1) */
+static int DES_check(word32 mask, word32 mask2, unsigned char* key)
+{
+    word32 value[2];
+
+    /* sanity check on length made in wolfSSL_DES_set_key_checked */
+    value[0] = mask;
+    value[1] = mask2;
+    return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0;
+}
+
+
+/* check that the key is odd parity and is not a weak key
+ * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */
+int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+    if (myDes == NULL || key == NULL) {
+        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked");
+        return -2;
+    }
+    else {
+        word32 i;
+        word32 sz = sizeof(WOLFSSL_DES_key_schedule);
+
+        /* sanity check before call to DES_check */
+        if (sz != (sizeof(word32) * 2)) {
+            WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size");
+            return -2;
+        }
+
+        /* check odd parity */
+        for (i = 0; i < sz; i++) {
+            unsigned char c = *((unsigned char*)myDes + i);
+            if (((c & 0x01) ^
+                ((c >> 1) & 0x01) ^
+                ((c >> 2) & 0x01) ^
+                ((c >> 3) & 0x01) ^
+                ((c >> 4) & 0x01) ^
+                ((c >> 5) & 0x01) ^
+                ((c >> 6) & 0x01) ^
+                ((c >> 7) & 0x01)) != 1) {
+                WOLFSSL_MSG("Odd parity test fail");
+                return -1;
+            }
+        }
+
+        if (wolfSSL_DES_is_weak_key(myDes) == 1) {
+            WOLFSSL_MSG("Weak key found");
+            return -2;
+        }
+
+        /* passed tests, now copy over key */
+        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+
+        return 0;
+    }
+}
+
+
+/* check is not weak. Weak key list from Nist "Recommendation for the Triple
+ * Data Encryption Algorithm (TDEA) Block Cipher"
+ *
+ * returns 1 if is weak 0 if not
+ */
+int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key)
+{
+    word32 mask, mask2;
+
+    WOLFSSL_ENTER("wolfSSL_DES_is_weak_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("NULL key passed in");
+        return 1;
+    }
+
+    mask = 0x01010101; mask2 = 0x01010101;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E;
+    if (DES_check(mask, mask2, *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    /* semi-weak *key check (list from same Nist paper) */
+    mask  = 0x011F011F; mask2 = 0x010E010E;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x01E001E0; mask2 = 0x01F101F1;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x01FE01FE; mask2 = 0x01FE01FE;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x1FE01FE0; mask2 = 0x0EF10EF1;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    mask  = 0x1FFE1FFE; mask2 = 0x0EFE0EFE;
+    if (DES_check(mask, mask2, *key) ||
+       DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) {
+        WOLFSSL_MSG("Weak key found");
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes,
+                                               WOLFSSL_DES_key_schedule* key)
+{
+    if (myDes != NULL && key != NULL) {
+        XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock));
+    }
+}
+
+
+/* Sets the parity of the DES key for use */
+void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes)
+{
+    word32 i;
+    word32 sz = sizeof(WOLFSSL_DES_cblock);
+
+    WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity");
+
+    for (i = 0; i < sz; i++) {
+        unsigned char c = *((unsigned char*)myDes + i);
+        if ((
+            ((c >> 1) & 0x01) ^
+            ((c >> 2) & 0x01) ^
+            ((c >> 3) & 0x01) ^
+            ((c >> 4) & 0x01) ^
+            ((c >> 5) & 0x01) ^
+            ((c >> 6) & 0x01) ^
+            ((c >> 7) & 0x01)) != 1) {
+            WOLFSSL_MSG("Setting odd parity bit");
+            *((unsigned char*)myDes + i) = *((unsigned char*)myDes + i) | 0x01;
+        }
+    }
+}
+
+
+#ifdef WOLFSSL_DES_ECB
+/* Encrpyt or decrypt input message desa with key and get output in desb.
+ * if enc is DES_ENCRYPT,input message is encrypted or
+ * if enc is DES_DECRYPT,input message is decrypted.
+ * */
+void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa,
+             WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc)
+{
+    Des myDes;
+
+    WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt");
+
+    if (desa == NULL || key == NULL || desb == NULL ||
+        (enc != DES_ENCRYPT && enc != DES_DECRYPT)) {
+        WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt");
+    } else {
+        if (wc_Des_SetKey(&myDes, (const byte*) key,
+                           (const byte*) NULL, !enc) != 0) {
+            WOLFSSL_MSG("wc_Des_SetKey return error.");
+            return;
+        }
+        if (enc){
+            if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa,
+                        sizeof(WOLFSSL_DES_cblock)) != 0){
+                WOLFSSL_MSG("wc_Des_EcbEncrpyt return error.");
+            }
+        } else {
+            if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa,
+                        sizeof(WOLFSSL_DES_cblock)) != 0){
+                WOLFSSL_MSG("wc_Des_EcbDecrpyt return error.");
+            }
+        }
+    }
+}
+#endif
+
+#endif /* NO_DES3 */
+
+#ifndef NO_RC4
+/* Set the key state for Arc4 structure.
+ *
+ * key  Arc4 structure to use
+ * len  length of data buffer
+ * data initial state to set Arc4 structure
+ */
+void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len,
+        const unsigned char* data)
+{
+    typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1];
+    (void)sizeof(rc4_test);
+
+    WOLFSSL_ENTER("wolfSSL_RC4_set_key");
+
+    if (key == NULL || len < 0) {
+        WOLFSSL_MSG("bad argument passed in");
+        return;
+    }
+
+    XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY));
+    wc_Arc4SetKey((Arc4*)key, data, (word32)len);
+}
+
+
+/* Encrypt/decrypt with Arc4 structure.
+ *
+ * len length of buffer to encrypt/decrypt (in/out)
+ * in  buffer to encrypt/decrypt
+ * out results of encryption/decryption
+ */
+void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len,
+        const unsigned char* in, unsigned char* out)
+{
+    WOLFSSL_ENTER("wolfSSL_RC4");
+
+    if (key == NULL || in == NULL || out == NULL) {
+        WOLFSSL_MSG("Bad argument passed in");
+        return;
+    }
+
+    wc_Arc4Process((Arc4*)key, out, in, (word32)len);
+}
+#endif /* NO_RC4 */
+
+#ifndef NO_AES
+
+#ifdef WOLFSSL_AES_DIRECT
+/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input  Data to encrypt
+ * output Encrypted data after done
+ * key    AES key to use for encryption
+ */
+void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output,
+        AES_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_AES_encrypt");
+
+    if (input == NULL || output == NULL || key == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return;
+    }
+
+    wc_AesEncryptDirect((Aes*)key, output, input);
+}
+
+
+/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input.
+ *
+ * input  Data to decrypt
+ * output Decrypted data after done
+ * key    AES key to use for encryption
+ */
+void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
+        AES_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_AES_decrypt");
+
+    if (input == NULL || output == NULL || key == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return;
+    }
+
+    wc_AesDecryptDirect((Aes*)key, output, input);
+}
+#endif /* WOLFSSL_AES_DIRECT */
+
+/* Setup of an AES key to use for encryption.
+ *
+ * key  key in bytes to use for encryption
+ * bits size of key in bits
+ * aes  AES structure to initialize
+ */
+int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits,
+        AES_KEY *aes)
+{
+    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+    (void)sizeof(aes_test);
+
+    WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key");
+
+    if (key == NULL || aes == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return -1;
+    }
+
+    XMEMSET(aes, 0, sizeof(AES_KEY));
+    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) {
+        WOLFSSL_MSG("Error in setting AES key");
+        return -1;
+    }
+    return 0;
+}
+
+
+/* Setup of an AES key to use for decryption.
+ *
+ * key  key in bytes to use for decryption
+ * bits size of key in bits
+ * aes  AES structure to initialize
+ */
+int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits,
+        AES_KEY *aes)
+{
+    typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1];
+    (void)sizeof(aes_test);
+
+    WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key");
+
+    if (key == NULL || aes == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return -1;
+    }
+
+    XMEMSET(aes, 0, sizeof(AES_KEY));
+    if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) {
+        WOLFSSL_MSG("Error in setting AES key");
+        return -1;
+    }
+    return 0;
+}
+
+
+#ifdef HAVE_AES_ECB
+/* Encrypt/decrypt a 16 byte block of data using the key passed in.
+ *
+ * in  buffer to encrypt/decyrpt
+ * out buffer to hold result of encryption/decryption
+ * key AES structure to use with encryption/decryption
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out,
+                             AES_KEY *key, const int enc)
+{
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt");
+
+    if (key == NULL || in == NULL || out == NULL) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+    #ifdef HAVE_AES_DECRYPT
+        if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    #else
+        WOLFSSL_MSG("AES decryption not compiled in");
+    #endif
+    }
+}
+#endif /* HAVE_AES_ECB */
+
+
+/* Encrypt data using key and iv passed in. iv gets updated to most recent iv
+ * state after encryptiond/decryption.
+ *
+ * in  buffer to encrypt/decyrpt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv  iv to use with operation
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
+        size_t len, AES_KEY *key, unsigned char* iv, const int enc)
+{
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
+
+    if (key == NULL || in == NULL || out == NULL || iv == NULL) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+        WOLFSSL_MSG("Error with setting iv");
+        return;
+    }
+
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+        if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    }
+
+    /* to be compatible copy iv to iv buffer after completing operation */
+    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+}
+
+
+/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to
+ * most recent iv state after encryptiond/decryption.
+ *
+ * in  buffer to encrypt/decyrpt
+ * out buffer to hold result of encryption/decryption
+ * len length of input buffer
+ * key AES structure to use with encryption/decryption
+ * iv  iv to use with operation
+ * num contains the amount of block used
+ * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption
+ */
+void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
+        size_t len, AES_KEY *key, unsigned char* iv, int* num,
+        const int enc)
+{
+#ifndef WOLFSSL_AES_CFB
+    WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
+    (void)in;
+    (void)out;
+    (void)len;
+    (void)key;
+    (void)iv;
+    (void)num;
+    (void)enc;
+
+    return;
+#else
+    Aes* aes;
+
+    WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt");
+    if (key == NULL || in == NULL || out == NULL || iv == NULL) {
+        WOLFSSL_MSG("Error, Null argument passed in");
+        return;
+    }
+
+    aes = (Aes*)key;
+    if (wc_AesSetIV(aes, (const byte*)iv) != 0) {
+        WOLFSSL_MSG("Error with setting iv");
+        return;
+    }
+
+    if (enc == AES_ENCRYPT) {
+        if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC encrypt");
+        }
+    }
+    else {
+        if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) {
+            WOLFSSL_MSG("Error with AES CBC decrypt");
+        }
+    }
+
+    /* to be compatible copy iv to iv buffer after completing operation */
+    XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE);
+
+    /* store number of left over bytes to num */
+    *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
+#endif /* WOLFSSL_AES_CFB */
+}
+#endif /* NO_AES */
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...)
+{
+    (void)bio;
+    (void)format;
+    WOLFSSL_STUB("BIO_printf");
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
+{
+    (void)bio;
+    (void)a;
+    WOLFSSL_STUB("ASN1_UTCTIME_print");
+    return 0;
+}
+#endif
+
+/* Return the month as a string.
+ *
+ * n  The number of the month as a two characters (1 based).
+ * returns the month as a string.
+ */
+static WC_INLINE const char* MonthStr(const char* n)
+{
+    static const char monthStr[12][4] = {
+            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+    return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1];
+}
+
+int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio,
+    const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime)
+{
+    const char* p = (const char *)(asnTime->data + 2);
+    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print");
+
+    if (bio == NULL || asnTime == NULL)
+        return BAD_FUNC_ARG;
+
+    /* GetTimeString not always available. */
+    wolfSSL_BIO_write(bio, MonthStr(p + 4), 3);
+    wolfSSL_BIO_write(bio, " ", 1);
+    /* Day */
+    wolfSSL_BIO_write(bio, p + 6, 2);
+    wolfSSL_BIO_write(bio, " ", 1);
+    /* Hour */
+    wolfSSL_BIO_write(bio, p + 8, 2);
+    wolfSSL_BIO_write(bio, ":", 1);
+    /* Min */
+    wolfSSL_BIO_write(bio, p + 10, 2);
+    wolfSSL_BIO_write(bio, ":", 1);
+    /* Secs */
+    wolfSSL_BIO_write(bio, p + 12, 2);
+    wolfSSL_BIO_write(bio, " ", 1);
+    wolfSSL_BIO_write(bio, p, 4);
+
+    return 0;
+}
+
+void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time)
+{
+    WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free");
+    if (asn1Time == NULL)
+        return;
+    XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data));
+}
+
+int  wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk)
+{
+    if (sk == NULL)
+        return 0;
+    return (int)sk->num;
+}
+
+void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, int i)
+{
+    for (; sk != NULL && i > 0; i--)
+        sk = sk->next;
+    if (sk == NULL)
+        return NULL;
+    return (void*)sk->data.obj;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
+/* stunnel 4.28 needs */
+void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
+                    WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*))
+{
+#ifdef HAVE_EXT_CACHE
+    ctx->get_sess_cb = f;
+#else
+    (void)ctx;
+    (void)f;
+#endif
+}
+
+void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
+                             int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
+{
+#ifdef HAVE_EXT_CACHE
+    ctx->new_sess_cb = f;
+#else
+    (void)ctx;
+    (void)f;
+#endif
+}
+
+void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
+                                                        WOLFSSL_SESSION*))
+{
+#ifdef HAVE_EXT_CACHE
+    ctx->rem_sess_cb = f;
+#else
+    (void)ctx;
+    (void)f;
+#endif
+}
+#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
+
+#ifdef OPENSSL_EXTRA
+
+/*
+ *
+ * Note: It is expected that the importing and exporting function have been
+ *       built with the same settings. For example if session tickets was
+ *       enabled with the wolfSSL library exporting a session then it is
+ *       expected to be turned on with the wolfSSL library importing the session.
+ */
+int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p)
+{
+    int size = 0;
+#ifdef HAVE_EXT_CACHE
+    int idx = 0;
+#ifdef SESSION_CERTS
+    int i;
+#endif
+    unsigned char *data;
+
+    if (sess == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */
+    size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz +
+            SECRET_LEN + OPAQUE8_LEN;
+#ifdef SESSION_CERTS
+    /* Peer chain */
+    size += OPAQUE8_LEN;
+    for (i = 0; i < sess->chain.count; i++)
+        size += OPAQUE16_LEN + sess->chain.certs[i].length;
+    /* Protocol version + cipher suite */
+    size += OPAQUE16_LEN + OPAQUE16_LEN;
+#endif
+#ifndef NO_CLIENT_CACHE
+    /* ServerID len | ServerID */
+    size += OPAQUE16_LEN + sess->idLen;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    /* ticket len | ticket */
+    size += OPAQUE16_LEN + sess->ticketLen;
+#endif
+#ifdef OPENSSL_EXTRA
+    /* session context ID len | session context ID */
+    size += OPAQUE8_LEN + sess->sessionCtxSz;
+#endif
+
+    if (p != NULL) {
+        if (*p == NULL)
+            *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*p == NULL)
+            return 0;
+        data = *p;
+
+        c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN;
+        c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN;
+        data[idx++] = sess->sessionIDSz;
+        XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz);
+        idx += sess->sessionIDSz;
+        XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN;
+        data[idx++] = (byte)sess->haveEMS;
+#ifdef SESSION_CERTS
+        data[idx++] = (byte)sess->chain.count;
+        for (i = 0; i < sess->chain.count; i++) {
+            c16toa((word16)sess->chain.certs[i].length, data + idx);
+            idx += OPAQUE16_LEN;
+            XMEMCPY(data + idx, sess->chain.certs[i].buffer,
+                    sess->chain.certs[i].length);
+            idx += sess->chain.certs[i].length;
+        }
+        data[idx++] = sess->version.major;
+        data[idx++] = sess->version.minor;
+        data[idx++] = sess->cipherSuite0;
+        data[idx++] = sess->cipherSuite;
+#endif
+#ifndef NO_CLIENT_CACHE
+        c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN;
+        XMEMCPY(data + idx, sess->serverID, sess->idLen);
+        idx += sess->idLen;
+#endif
+#ifdef HAVE_SESSION_TICKET
+        c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN;
+        XMEMCPY(data + idx, sess->ticket, sess->ticketLen);
+        idx += sess->ticketLen;
+#endif
+#ifdef OPENSSL_EXTRA
+        data[idx++] = sess->sessionCtxSz;
+        XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz);
+        idx += sess->sessionCtxSz;
+#endif
+    }
+#endif
+
+    (void)sess;
+    (void)p;
+#ifdef HAVE_EXT_CACHE
+    (void)idx;
+#endif
+
+    return size;
+}
+
+
+/* TODO: no function to free new session.
+ *
+ * Note: It is expected that the importing and exporting function have been
+ *       built with the same settings. For example if session tickets was
+ *       enabled with the wolfSSL library exporting a session then it is
+ *       expected to be turned on with the wolfSSL library importing the session.
+ */
+WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
+                                const unsigned char** p, long i)
+{
+    WOLFSSL_SESSION* s = NULL;
+    int ret = 0;
+#if defined(HAVE_EXT_CACHE)
+    int idx;
+    byte* data;
+#ifdef SESSION_CERTS
+    int j;
+    word16 length;
+#endif
+#endif
+
+    (void)p;
+    (void)i;
+    (void)ret;
+
+    if (sess != NULL)
+        s = *sess;
+
+#ifdef HAVE_EXT_CACHE
+    if (p == NULL || *p == NULL)
+        return NULL;
+
+    if (s == NULL) {
+        s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL,
+                                      DYNAMIC_TYPE_OPENSSL);
+        if (s == NULL)
+            return NULL;
+        XMEMSET(s, 0, sizeof(WOLFSSL_SESSION));
+        s->isAlloced = 1;
+#ifdef HAVE_SESSION_TICKET
+        s->isDynamic = 0;
+#endif
+    }
+
+    idx = 0;
+    data = (byte*)*p;
+
+    /* bornOn | timeout | sessionID len */
+    if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN;
+    ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN;
+    s->sessionIDSz = data[idx++];
+
+    /* sessionID | secret | haveEMS */
+    if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->sessionID, data + idx, s->sessionIDSz);
+    idx  += s->sessionIDSz;
+    XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN;
+    s->haveEMS = data[idx++];
+
+#ifdef SESSION_CERTS
+    /* Certificate chain */
+    if (i - idx == 0) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->chain.count = data[idx++];
+    for (j = 0; j < s->chain.count; j++) {
+        if (i - idx < OPAQUE16_LEN) {
+            ret = BUFFER_ERROR;
+            goto end;
+        }
+        ato16(data + idx, &length); idx += OPAQUE16_LEN;
+        s->chain.certs[j].length = length;
+        if (i - idx < length) {
+            ret = BUFFER_ERROR;
+            goto end;
+        }
+        XMEMCPY(s->chain.certs[j].buffer, data + idx, length);
+        idx += length;
+    }
+
+    /* Protocol Version | Cipher suite */
+    if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->version.major = data[idx++];
+    s->version.minor = data[idx++];
+    s->cipherSuite0 = data[idx++];
+    s->cipherSuite = data[idx++];
+#endif
+#ifndef NO_CLIENT_CACHE
+    /* ServerID len */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN;
+
+    /* ServerID */
+    if (i - idx < s->idLen) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen;
+#endif
+#ifdef HAVE_SESSION_TICKET
+    /* ticket len */
+    if (i - idx < OPAQUE16_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN;
+
+    /* Dispose of ol dynamic ticket and ensure space for new ticket. */
+    if (s->isDynamic)
+        XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
+    if (s->ticketLen <= SESSION_TICKET_LEN)
+        s->ticket = s->staticTicket;
+    else {
+        s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
+                                   DYNAMIC_TYPE_SESSION_TICK);
+        if (s->ticket == NULL) {
+            ret = MEMORY_ERROR;
+            goto end;
+        }
+        s->isDynamic = 1;
+    }
+
+    /* ticket */
+    if (i - idx < s->ticketLen) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen;
+#endif
+#ifdef OPENSSL_EXTRA
+    /* byte for length of session context ID */
+    if (i - idx < OPAQUE8_LEN) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    s->sessionCtxSz = data[idx++];
+
+    /* app session context ID */
+    if (i - idx < s->sessionCtxSz) {
+        ret = BUFFER_ERROR;
+        goto end;
+    }
+    XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz;
+#endif
+    (void)idx;
+
+    if (sess != NULL)
+        *sess = s;
+
+    *p += idx;
+
+end:
+    if (ret != 0 && (sess == NULL || *sess != s))
+        wolfSSL_SESSION_free(s);
+#endif
+    return s;
+}
+
+
+long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout");
+    return sess->timeout;
+}
+
+
+long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
+    return sess->bornOn;
+}
+
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef KEEP_PEER_CERT
+char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
+{
+    if (x509 == NULL)
+        return NULL;
+
+    return x509->subjectCN;
+}
+#endif /* KEEP_PEER_CERT */
+
+#ifdef OPENSSL_EXTRA
+
+#if defined(FORTRESS) && !defined(NO_FILESYSTEM)
+int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
+{
+    int ret = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
+    if (ssl != NULL && fname != NULL)
+    {
+    #ifdef WOLFSSL_SMALL_STACK
+        byte           staticBuffer[1]; /* force heap usage */
+    #else
+        byte           staticBuffer[FILE_BUFFER_SIZE];
+    #endif
+        byte*          myBuffer  = staticBuffer;
+        int            dynamic   = 0;
+        XFILE          file      = XBADFILE;
+        size_t         sz        = 0;
+        WOLFSSL_CTX*   ctx       = ssl->ctx;
+        WOLFSSL_X509*  peer_cert = &ssl->peerCert;
+        DerBuffer*     fileDer = NULL;
+
+        file = XFOPEN(fname, "rb");
+        if (file == XBADFILE)
+            return WOLFSSL_BAD_FILE;
+
+        XFSEEK(file, 0, XSEEK_END);
+        sz = XFTELL(file);
+        XREWIND(file);
+
+        if (sz > (long)sizeof(staticBuffer)) {
+            WOLFSSL_MSG("Getting dynamic buffer");
+            myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+            dynamic = 1;
+        }
+
+
+        if ((myBuffer != NULL) &&
+            (sz > 0) &&
+            (XFREAD(myBuffer, 1, sz, file) == sz) &&
+            (PemToDer(myBuffer, (long)sz, CERT_TYPE,
+                      &fileDer, ctx->heap, NULL, NULL) == 0) &&
+            (fileDer->length != 0) &&
+            (fileDer->length == peer_cert->derCert->length) &&
+            (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
+                                                fileDer->length) == 0))
+        {
+            ret = 0;
+        }
+
+        FreeDer(&fileDer);
+
+        if (dynamic)
+            XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+        XFCLOSE(file);
+    }
+
+    return ret;
+}
+#endif
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || \
+    (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA))
+static WC_RNG globalRNG;
+static int initGlobalRNG = 0;
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+/* Not thread safe! Can be called multiple times.
+ * Checks if the global RNG has been created. If not then one is created.
+ *
+ * Returns SSL_SUCCESS when no error is encountered.
+ */
+static int wolfSSL_RAND_Init(void)
+{
+    if (initGlobalRNG == 0) {
+        if (wc_InitRng(&globalRNG) < 0) {
+            WOLFSSL_MSG("wolfSSL Init Global RNG failed");
+            return 0;
+        }
+        initGlobalRNG = 1;
+    }
+
+    return SSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+int wolfSSL_RAND_seed(const void* seed, int len)
+{
+
+    WOLFSSL_MSG("wolfSSL_RAND_seed");
+
+    (void)seed;
+    (void)len;
+
+    return wolfSSL_RAND_Init();
+}
+
+
+/* Returns the path for reading seed data from.
+ * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd
+ *
+ * Note uses stdlib by default unless XGETENV macro is overwritten
+ *
+ * fname buffer to hold path
+ * len   length of fname buffer
+ *
+ * Returns a pointer to fname on success and NULL on failure
+ */
+const char* wolfSSL_RAND_file_name(char* fname, unsigned long len)
+{
+#ifndef NO_FILESYSTEM
+    char* rt;
+    char ap[] = "/.rnd";
+
+    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+
+    if (fname == NULL) {
+        return NULL;
+    }
+
+    XMEMSET(fname, 0, len);
+    /* if access to stdlib.h */
+    if ((rt = XGETENV("RANDFILE")) != NULL) {
+        if (len > XSTRLEN(rt)) {
+            XMEMCPY(fname, rt, XSTRLEN(rt));
+        }
+        else {
+            WOLFSSL_MSG("RANDFILE too large for buffer");
+            rt = NULL;
+        }
+    }
+
+    /* $RANDFILE was not set or is too large, check $HOME */
+    if (rt == NULL) {
+        WOLFSSL_MSG("Environment variable RANDFILE not set");
+        if ((rt = XGETENV("HOME")) == NULL) {
+            WOLFSSL_MSG("Environment variable HOME not set");
+            return NULL;
+        }
+
+        if (len > XSTRLEN(rt) +  XSTRLEN(ap)) {
+            fname[0] = '\0';
+            XSTRNCAT(fname, rt, len);
+            XSTRNCAT(fname, ap, len - XSTRLEN(rt));
+            return fname;
+        }
+        else {
+            WOLFSSL_MSG("HOME too large for buffer");
+            return NULL;
+        }
+    }
+
+    return fname;
+#else
+    /* no filesystem defined */
+    WOLFSSL_ENTER("wolfSSL_RAND_file_name");
+    WOLFSSL_MSG("No filesystem feature enabled, not compiled in");
+    (void)fname;
+    (void)len;
+    return NULL;
+#endif
+}
+
+
+/* Writes 1024 bytes from the RNG to the given file name.
+ *
+ * fname name of file to write to
+ *
+ * Returns the number of bytes writen
+ */
+int wolfSSL_RAND_write_file(const char* fname)
+{
+    int bytes = 0;
+
+    WOLFSSL_ENTER("RAND_write_file");
+
+    if (fname == NULL) {
+        return SSL_FAILURE;
+    }
+
+#ifndef NO_FILESYSTEM
+    {
+    #ifndef WOLFSSL_SMALL_STACK
+        unsigned char buf[1024];
+    #else
+        unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        if (buf == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            return SSL_FAILURE;
+        }
+    #endif
+        bytes = 1024; /* default size of buf */
+
+        if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) {
+            WOLFSSL_MSG("No RNG to use");
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
+            return 0;
+        }
+
+        if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) {
+            WOLFSSL_MSG("Error generating random buffer");
+            bytes = 0;
+        }
+        else {
+            XFILE f;
+
+            f = XFOPEN(fname, "wb");
+            if (f == NULL) {
+                WOLFSSL_MSG("Error opening the file");
+                bytes = 0;
+            }
+            else {
+                XFWRITE(buf, 1, bytes, f);
+                XFCLOSE(f);
+            }
+        }
+        ForceZero(buf, bytes);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    }
+#endif
+
+    return bytes;
+}
+
+#ifndef FREERTOS_TCP
+
+/* These constant values are protocol values made by egd */
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API)
+    #define WOLFSSL_EGD_NBLOCK 0x01
+    #include <sys/un.h>
+#endif
+
+/* at compile time check for HASH DRBG and throw warning if not found */
+#ifndef HAVE_HASHDRBG
+    #warning HAVE_HASHDRBG is needed for wolfSSL_RAND_egd to seed
+#endif
+
+/* This collects entropy from the path nm and seeds the global PRNG with it.
+ * Makes a call to wolfSSL_RAND_Init which is not thread safe.
+ *
+ * nm is the file path to the egd server
+ *
+ * Returns the number of bytes read.
+ */
+int wolfSSL_RAND_egd(const char* nm)
+{
+#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS)
+    struct sockaddr_un rem;
+    int fd;
+    int ret = WOLFSSL_SUCCESS;
+    word32 bytes = 0;
+    word32 idx   = 0;
+#ifndef WOLFSSL_SMALL_STACK
+    unsigned char buf[256];
+#else
+    unsigned char* buf;
+    buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf == NULL) {
+        WOLFSSL_MSG("Not enough memory");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#endif
+
+    if (nm == NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0) {
+        WOLFSSL_MSG("Error creating socket");
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+        return WOLFSSL_FATAL_ERROR;
+    }
+    if (ret == WOLFSSL_SUCCESS) {
+        rem.sun_family = AF_UNIX;
+        XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path));
+        rem.sun_path[sizeof(rem.sun_path)-1] = '\0';
+    }
+
+    /* connect to egd server */
+    if (ret == WOLFSSL_SUCCESS) {
+        if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un))
+                == -1) {
+            WOLFSSL_MSG("error connecting to egd server");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) {
+        if (ret == WOLFSSL_SUCCESS) {
+            buf[idx]     = WOLFSSL_EGD_NBLOCK;
+            buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */
+            ret = (int)write(fd, buf + idx, 2);
+            if (ret <= 0 || ret != 2) {
+                if (errno == EAGAIN) {
+                    ret = WOLFSSL_SUCCESS;
+                    continue;
+                }
+                WOLFSSL_MSG("error requesting entropy from egd server");
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
+            }
+        }
+
+        /* attempting to read */
+        buf[idx] = 0;
+        ret = (int)read(fd, buf + idx, 256 - bytes);
+        if (ret == 0) {
+            WOLFSSL_MSG("error reading entropy from egd server");
+            ret = WOLFSSL_FATAL_ERROR;
+            break;
+        }
+        if (ret > 0 && buf[idx] > 0) {
+            bytes += buf[idx]; /* egd stores amount sent in first byte */
+            if (bytes + idx > 255 || buf[idx] > ret) {
+                WOLFSSL_MSG("Buffer error");
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
+            }
+            XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]);
+            idx = bytes;
+            ret = WOLFSSL_SUCCESS;
+            if (bytes >= 255) {
+                break;
+            }
+        }
+        else {
+            if (errno == EAGAIN || errno == EINTR) {
+                WOLFSSL_MSG("EGD would read");
+                ret = WOLFSSL_SUCCESS; /* try again */
+            }
+            else if (buf[idx] == 0) {
+                /* if egd returned 0 then there is no more entropy to be had.
+                   Do not try more reads. */
+                ret = WOLFSSL_SUCCESS;
+                break;
+            }
+            else {
+                WOLFSSL_MSG("Error with read");
+                ret = WOLFSSL_FATAL_ERROR;
+            }
+        }
+    }
+
+    if (bytes > 0 && ret == WOLFSSL_SUCCESS) {
+        wolfSSL_RAND_Init(); /* call to check global RNG is created */
+        if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes)
+                != 0) {
+            WOLFSSL_MSG("Error with reseeding DRBG structure");
+            ret = WOLFSSL_FATAL_ERROR;
+        }
+        #ifdef SHOW_SECRETS
+        { /* print out entropy found */
+            word32 i;
+            printf("EGD Entropy = ");
+            for (i = 0; i < bytes; i++) {
+                printf("%02X", buf[i]);
+            }
+            printf("\n");
+        }
+        #endif
+    }
+
+    ForceZero(buf, bytes);
+    #ifdef WOLFSSL_SMALL_STACK
+    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+    close(fd);
+
+    if (ret == WOLFSSL_SUCCESS) {
+        return bytes;
+    }
+    else {
+        return ret;
+    }
+#else /* defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !HAVE_FIPS */
+    WOLFSSL_MSG("Type of socket needed is not available");
+    WOLFSSL_MSG("\tor using FIPS mode where RNG API is not available");
+    (void)nm;
+
+    return WOLFSSL_FATAL_ERROR;
+#endif /* defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) */
+}
+
+#endif /* !FREERTOS_TCP */
+
+void wolfSSL_RAND_Cleanup(void)
+{
+    WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()");
+
+    if (initGlobalRNG != 0) {
+        wc_FreeRng(&globalRNG);
+        initGlobalRNG = 0;
+    }
+}
+
+
+int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
+{
+    return wolfSSL_RAND_bytes(buf, num);
+}
+
+
+/* SSL_SUCCESS on ok */
+int wolfSSL_RAND_bytes(unsigned char* buf, int num)
+{
+    int     ret = 0;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_RAND_bytes");
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return ret;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else if (initGlobalRNG)
+        rng = &globalRNG;
+
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buf, num) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else
+            ret = WOLFSSL_SUCCESS;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+int wolfSSL_RAND_poll()
+{
+    byte  entropy[16];
+    int  ret = 0;
+    word32 entropy_sz = 16;
+
+    WOLFSSL_ENTER("wolfSSL_RAND_poll");
+    if (initGlobalRNG == 0){
+        WOLFSSL_MSG("Global RNG no Init");
+        return  WOLFSSL_FAILURE;
+    }
+    ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz);
+    if (ret != 0){
+        WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        ret = WOLFSSL_FAILURE;
+    }else
+        ret = WOLFSSL_SUCCESS;
+
+    return ret;
+}
+
+WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void)
+{
+    static int ctx;  /* wolfcrypt doesn't now need ctx */
+
+    WOLFSSL_MSG("wolfSSL_BN_CTX_new");
+    return (WOLFSSL_BN_CTX*)&ctx;
+
+}
+
+void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx)
+{
+    (void)ctx;
+    WOLFSSL_MSG("wolfSSL_BN_CTX_init");
+}
+
+
+void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx)
+{
+    (void)ctx;
+    WOLFSSL_MSG("wolfSSL_BN_CTX_free");
+    /* do free since static ctx that does nothing */
+}
+#endif /* OPENSSL_EXTRA */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn)
+{
+    if (bn) {
+        XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM));
+        bn->neg      = 0;
+        bn->internal = NULL;
+    }
+}
+
+WOLFSSL_BIGNUM* wolfSSL_BN_new(void)
+{
+    WOLFSSL_BIGNUM* external;
+    mp_int*        mpi;
+
+    WOLFSSL_MSG("wolfSSL_BN_new");
+
+    mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+    if (mpi == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL,
+                                        DYNAMIC_TYPE_BIGINT);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure");
+        XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT);
+        return NULL;
+    }
+
+    InitwolfSSL_BigNum(external);
+    external->internal = mpi;
+    if (mp_init(mpi) != MP_OKAY) {
+        wolfSSL_BN_free(external);
+        return NULL;
+    }
+
+    return external;
+}
+
+
+void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_free");
+    if (bn) {
+        if (bn->internal) {
+            mp_forcezero((mp_int*)bn->internal);
+            XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT);
+            bn->internal = NULL;
+        }
+        XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT);
+        bn = NULL;
+    }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+
+void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_clear_free");
+
+    wolfSSL_BN_free(bn);
+}
+
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+                  const WOLFSSL_BIGNUM* b)
+{
+    WOLFSSL_MSG("wolfSSL_BN_sub");
+
+    if (r == NULL || a == NULL || b == NULL)
+        return 0;
+
+    if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal,
+               (mp_int*)r->internal) == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+
+    WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed");
+    return 0;
+}
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a,
+                  const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c)
+{
+    (void)c;
+    WOLFSSL_MSG("wolfSSL_BN_mod");
+
+    if (r == NULL || a == NULL || b == NULL)
+        return 0;
+
+    if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal,
+               (mp_int*)r->internal) == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+
+    WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed");
+    return 0;
+}
+
+
+/* r = (a^p) % m */
+int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+      const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_exp");
+
+    (void) ctx;
+    if (r == NULL || a == NULL || p == NULL || m == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return WOLFSSL_FAILURE;
+    }
+
+    if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal,
+               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret);
+    (void)ret;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* r = (a * p) % m */
+int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a,
+        const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_mul");
+
+    (void) ctx;
+    if (r == NULL || a == NULL || p == NULL || m == NULL) {
+        WOLFSSL_MSG("Bad Argument");
+        return SSL_FAILURE;
+    }
+
+    if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal,
+               (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) {
+        return SSL_SUCCESS;
+    }
+
+    WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret);
+    (void)ret;
+
+    return SSL_FAILURE;
+}
+
+const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
+{
+    static WOLFSSL_BIGNUM* bn_one = NULL;
+
+    WOLFSSL_MSG("wolfSSL_BN_value_one");
+
+    if (bn_one == NULL) {
+        bn_one = wolfSSL_BN_new();
+        if (bn_one) {
+            if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) {
+                /* handle error by freeing BN and returning NULL */
+                wolfSSL_BN_free(bn_one);
+                bn_one = NULL;
+            }
+        }
+    }
+
+    return bn_one;
+}
+
+/* return compliant with OpenSSL
+ *   size of BIGNUM in bytes, 0 if error */
+int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_ENTER("wolfSSL_BN_num_bytes");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ *   size of BIGNUM in bits, 0 if error */
+int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_ENTER("wolfSSL_BN_num_bits");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    return mp_count_bits((mp_int*)bn->internal);
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is zero, 0 else */
+int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_zero");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_iszero((mp_int*)bn->internal) == MP_YES)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is one, 0 else */
+int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_one");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   1 if BIGNUM is odd, 0 else */
+int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_is_odd");
+
+    if (bn == NULL || bn->internal == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (mp_isodd((mp_int*)bn->internal) == MP_YES)
+        return WOLFSSL_SUCCESS;
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return compliant with OpenSSL
+ *   -1 if a < b, 0 if a == b and 1 if a > b
+ */
+int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b)
+{
+    int ret;
+
+    WOLFSSL_MSG("wolfSSL_BN_cmp");
+
+    if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal);
+
+    return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1));
+}
+
+/* return compliant with OpenSSL
+ *   length of BIGNUM in bytes, -1 if error */
+int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r)
+{
+    WOLFSSL_MSG("wolfSSL_BN_bn2bin");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("NULL bn error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (r == NULL)
+        return mp_unsigned_bin_size((mp_int*)bn->internal);
+
+    if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) {
+        WOLFSSL_MSG("mp_to_unsigned_bin error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return mp_unsigned_bin_size((mp_int*)bn->internal);
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len,
+                            WOLFSSL_BIGNUM* ret)
+{
+    int weOwn = 0;
+
+    WOLFSSL_MSG("wolfSSL_BN_bin2bn");
+
+    /* if ret is null create a BN */
+    if (ret == NULL) {
+        ret = wolfSSL_BN_new();
+        weOwn = 1;
+        if (ret == NULL)
+            return NULL;
+    }
+
+    /* check ret and ret->internal then read in value */
+    if (ret && ret->internal) {
+        if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) {
+            WOLFSSL_MSG("mp_read_unsigned_bin failure");
+            if (weOwn)
+                wolfSSL_BN_free(ret);
+            return NULL;
+        }
+    }
+
+    return ret;
+}
+
+/* return compliant with OpenSSL
+ *   1 if success, 0 if error */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n)
+{
+    (void)bn;
+    (void)n;
+    WOLFSSL_ENTER("wolfSSL_BN_mask_bits");
+    WOLFSSL_STUB("BN_mask_bits");
+    return SSL_FAILURE;
+}
+#endif
+
+
+/* WOLFSSL_SUCCESS on ok */
+int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+    int           ret    = 0;
+    int           len    = bits / 8;
+    int           initTmpRng = 0;
+    WC_RNG*       rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*       tmpRNG = NULL;
+    byte*         buff   = NULL;
+#else
+    WC_RNG        tmpRNG[1];
+    byte          buff[1024];
+#endif
+
+    (void)top;
+    (void)bottom;
+    WOLFSSL_MSG("wolfSSL_BN_rand");
+
+    if (bits % 8)
+        len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (buff == NULL || tmpRNG == NULL) {
+        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        return ret;
+    }
+#endif
+
+    if (bn == NULL || bn->internal == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else if (initGlobalRNG)
+        rng = &globalRNG;
+
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else {
+            buff[0]     |= 0x80 | 0x40;
+            buff[len-1] |= 0x01;
+
+            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+                WOLFSSL_MSG("mp read bin failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+/* WOLFSSL_SUCCESS on ok
+ * code is same as wolfSSL_BN_rand except for how top and bottom is handled.
+ * top -1 then leave most sig bit alone
+ * top 0 then most sig is set to 1
+ * top is 1 then first two most sig bits are 1
+ *
+ * bottom is hot then odd number */
+int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom)
+{
+    int           ret    = 0;
+    int           len    = bits / 8;
+    int           initTmpRng = 0;
+    WC_RNG*       rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG*       tmpRNG = NULL;
+    byte*         buff   = NULL;
+#else
+    WC_RNG        tmpRNG[1];
+    byte          buff[1024];
+#endif
+
+    WOLFSSL_MSG("wolfSSL_BN_rand");
+
+    if (bits % 8)
+        len++;
+
+#ifdef WOLFSSL_SMALL_STACK
+    buff   = (byte*)XMALLOC(1024,        NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buff == NULL || tmpRNG == NULL) {
+        XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+#endif
+
+    if (bn == NULL || bn->internal == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else if (initGlobalRNG)
+        rng = &globalRNG;
+
+    if (rng) {
+        if (wc_RNG_GenerateBlock(rng, buff, len) != 0)
+            WOLFSSL_MSG("Bad wc_RNG_GenerateBlock");
+        else {
+            switch (top) {
+                case -1:
+                    break;
+
+                case 0:
+                    buff[0] |= 0x80;
+                    break;
+
+                case 1:
+                    buff[0] |= 0x80 | 0x40;
+                    break;
+            }
+
+            if (bottom == 1) {
+                buff[len-1] |= 0x01;
+            }
+
+            if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY)
+                WOLFSSL_MSG("mp read bin failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(buff,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if bit set, 0 else
+ */
+int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n)
+{
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (n > DIGIT_BIT) {
+        WOLFSSL_MSG("input bit count too large");
+        return WOLFSSL_FAILURE;
+    }
+
+    return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n);
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n)
+{
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) {
+        WOLFSSL_MSG("mp_set_int error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* WOLFSSL_SUCCESS on ok */
+/* Note on use: this function expects str to be an even length. It is
+ * converting pairs of bytes into 8-bit values. As an example, the RSA
+ * public exponent is commonly 0x010001. To get it to convert, you need
+ * to pass in the string "010001", it will fail if you use "10001". This
+ * is an affect of how Base16_Decode() works.
+ */
+int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+    int     ret     = 0;
+    word32  decSz   = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+    byte*   decoded = NULL;
+#else
+    byte    decoded[1024];
+#endif
+    int     weOwn = 0;
+
+    WOLFSSL_MSG("wolfSSL_BN_hex2bn");
+
+#ifdef WOLFSSL_SMALL_STACK
+    decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER);
+    if (decoded == NULL)
+        return ret;
+#endif
+
+    if (str == NULL || str[0] == '\0')
+        WOLFSSL_MSG("Bad function argument");
+    else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0)
+        WOLFSSL_MSG("Bad Base16_Decode error");
+    else if (bn == NULL)
+        ret = decSz;
+    else {
+        if (*bn == NULL) {
+            *bn = wolfSSL_BN_new();
+            if (*bn != NULL) {
+                weOwn = 1;
+            }
+        }
+
+        if (*bn == NULL)
+            WOLFSSL_MSG("BN new failed");
+        else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) {
+            WOLFSSL_MSG("Bad bin2bn error");
+            if (weOwn == 1) {
+                wolfSSL_BN_free(*bn); /* Free new BN */
+            }
+        }
+        else
+            ret = WOLFSSL_SUCCESS;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(decoded, NULL, DYNAMIC_TYPE_DER);
+#endif
+
+    return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_BIGNUM* ret;
+
+    WOLFSSL_MSG("wolfSSL_BN_dup");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    ret = wolfSSL_BN_new();
+    if (ret == NULL) {
+        WOLFSSL_MSG("bn new error");
+        return NULL;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        wolfSSL_BN_free(ret);
+        return NULL;
+    }
+
+    ret->neg = bn->neg;
+
+    return ret;
+}
+
+
+WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn)
+{
+    WOLFSSL_MSG("wolfSSL_BN_copy");
+
+    if (r == NULL || bn == NULL) {
+        WOLFSSL_MSG("r or bn NULL error");
+        return NULL;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        return NULL;
+    }
+
+    r->neg = bn->neg;
+
+    return r;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_MSG("wolfSSL_BN_set_word");
+
+    if (bn == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) {
+        WOLFSSL_MSG("mp_init_set_int error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* Returns the big number as an unsigned long if possible.
+ *
+ * bn  big number structure to get value from
+ *
+ * Returns value or 0xFFFFFFFFL if bigger than unsigned long.
+ */
+unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn)
+{
+    mp_int* mp;
+
+    WOLFSSL_MSG("wolfSSL_BN_get_word");
+
+    if (bn == NULL) {
+        WOLFSSL_MSG("Invalid argument");
+        return 0;
+    }
+
+    if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) {
+        WOLFSSL_MSG("bignum is larger than unsigned long");
+        return 0xFFFFFFFFL;
+    }
+    mp = (mp_int*)bn->internal;
+
+    return (unsigned long)(mp->dp[0]);
+}
+
+/* return code compliant with OpenSSL :
+ *   number length in decimal if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str)
+{
+    (void)bn;
+    (void)str;
+
+    WOLFSSL_MSG("wolfSSL_BN_dec2bn");
+    WOLFSSL_STUB("BN_dec2bn");
+    return SSL_FAILURE;
+}
+#endif
+
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY)
+char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn)
+{
+    int len = 0;
+    char *buf;
+
+    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) {
+        WOLFSSL_MSG("mp_radix_size failure");
+        return NULL;
+    }
+
+    buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+    if (buf == NULL) {
+        WOLFSSL_MSG("BN_bn2dec malloc buffer failure");
+        return NULL;
+    }
+
+    if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) {
+        XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    return buf;
+}
+#else
+char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn)
+{
+    (void)bn;
+
+    WOLFSSL_MSG("wolfSSL_BN_bn2dec");
+
+    return NULL;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+    WOLFSSL_MSG("wolfSSL_BN_lshift");
+
+    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_mul_2d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n)
+{
+    WOLFSSL_MSG("wolfSSL_BN_rshift");
+
+    if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_div_2d((mp_int*)bn->internal, n,
+                  (mp_int*)r->internal, NULL) != MP_OKAY) {
+        WOLFSSL_MSG("mp_mul_2d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_MSG("wolfSSL_BN_add_word");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 else
+ */
+int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b)
+{
+    WOLFSSL_MSG("wolfSSL_BN_add");
+
+    if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL ||
+        b == NULL || b->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_add((mp_int*)a->internal, (mp_int*)b->internal,
+               (mp_int*)r->internal) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* return code compliant with OpenSSL :
+ *   1 if prime, 0 if not, -1 if error
+ */
+int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks,
+                           WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb)
+{
+    int res;
+
+    (void)ctx;
+    (void)cb;
+
+    WOLFSSL_MSG("wolfSSL_BN_is_prime_ex");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) {
+        WOLFSSL_MSG("mp_prime_is_prime error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (res != MP_YES) {
+        WOLFSSL_MSG("mp_prime_is_prime not prime");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   (bn mod w) if success, -1 if error
+ */
+WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn,
+                                     WOLFSSL_BN_ULONG w)
+{
+    WOLFSSL_BN_ULONG ret = 0;
+
+    WOLFSSL_MSG("wolfSSL_BN_mod_word");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) {
+        WOLFSSL_MSG("mp_add_d error");
+        return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR;
+    }
+
+    return ret;
+}
+#endif /* #ifdef WOLFSSL_KEY_GEN */
+
+char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn)
+{
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL)
+    int len = 0;
+    char *buf;
+
+    WOLFSSL_ENTER("wolfSSL_BN_bn2hex");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return NULL;
+    }
+
+    if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) {
+        WOLFSSL_MSG("mp_radix_size failure");
+        return NULL;
+    }
+
+    buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC);
+    if (buf == NULL) {
+        WOLFSSL_MSG("BN_bn2hex malloc buffer failure");
+        return NULL;
+    }
+
+    if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) {
+        XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    return buf;
+#else
+    (void)bn;
+    WOLFSSL_MSG("wolfSSL_BN_bn2hex not compiled in");
+    return (char*)"";
+#endif
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn)
+{
+#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(DEBUG_WOLFSSL)
+    char *buf;
+
+    WOLFSSL_ENTER("wolfSSL_BN_print_fp");
+
+    if (fp == NULL || bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    buf = wolfSSL_BN_bn2hex(bn);
+    if (buf == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_bn2hex failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    fprintf(fp, "%s", buf);
+    XFREE(buf, NULL, DYNAMIC_TYPE_ECC);
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)fp;
+    (void)bn;
+
+    WOLFSSL_MSG("wolfSSL_BN_print_fp not compiled in");
+
+    return WOLFSSL_SUCCESS;
+#endif
+}
+#endif /* !NO_FILESYSTEM */
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx)
+{
+    /* ctx is not used, return new Bignum */
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_CTX_get");
+
+    return wolfSSL_BN_new();
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_CTX_start");
+    WOLFSSL_STUB("BN_CTX_start");
+    WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD");
+}
+#endif
+
+
+WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r,
+                                       WOLFSSL_BIGNUM *a,
+                                       const WOLFSSL_BIGNUM *n,
+                                       WOLFSSL_BN_CTX *ctx)
+{
+    int dynamic = 0;
+
+    /* ctx is not used */
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_BN_mod_inverse");
+
+    /* check parameter */
+    if (r == NULL) {
+        r = wolfSSL_BN_new();
+        if (r == NULL){
+            WOLFSSL_MSG("WolfSSL_BN_new() failed");
+            return NULL;
+        }
+        dynamic = 1;
+    }
+
+    if (a == NULL) {
+        WOLFSSL_MSG("a NULL error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    if (n == NULL) {
+        WOLFSSL_MSG("n NULL error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    /* Compute inverse of a modulo n and return r */
+    if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal,
+                  (mp_int*)r->internal) == MP_VAL){
+        WOLFSSL_MSG("mp_invmod() error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(r);
+        }
+        return NULL;
+    }
+
+    return  r;
+}
+
+#ifndef NO_DH
+
+static void InitwolfSSL_DH(WOLFSSL_DH* dh)
+{
+    if (dh) {
+        dh->p        = NULL;
+        dh->g        = NULL;
+        dh->q        = NULL;
+        dh->pub_key  = NULL;
+        dh->priv_key = NULL;
+        dh->internal = NULL;
+        dh->inSet    = 0;
+        dh->exSet    = 0;
+    }
+}
+
+
+WOLFSSL_DH* wolfSSL_DH_new(void)
+{
+    WOLFSSL_DH* external;
+    DhKey*     key;
+
+    WOLFSSL_MSG("wolfSSL_DH_new");
+
+    key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL,
+                                    DYNAMIC_TYPE_DH);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DH);
+        return NULL;
+    }
+
+    InitwolfSSL_DH(external);
+    if (wc_InitDhKey(key) != 0) {
+        WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DH);
+        XFREE(external, NULL, DYNAMIC_TYPE_DH);
+        return NULL;
+    }
+    external->internal = key;
+
+    return external;
+}
+
+
+void wolfSSL_DH_free(WOLFSSL_DH* dh)
+{
+    WOLFSSL_MSG("wolfSSL_DH_free");
+
+    if (dh) {
+        if (dh->internal) {
+            wc_FreeDhKey((DhKey*)dh->internal);
+            XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH);
+            dh->internal = NULL;
+        }
+        wolfSSL_BN_free(dh->priv_key);
+        wolfSSL_BN_free(dh->pub_key);
+        wolfSSL_BN_free(dh->g);
+        wolfSSL_BN_free(dh->p);
+        wolfSSL_BN_free(dh->q);
+        InitwolfSSL_DH(dh);  /* set back to NULLs for safety */
+
+        XFREE(dh, NULL, DYNAMIC_TYPE_DH);
+    }
+}
+
+
+static int SetDhInternal(WOLFSSL_DH* dh)
+{
+    int            ret = WOLFSSL_FATAL_ERROR;
+    int            pSz = 1024;
+    int            gSz = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+    unsigned char* p   = NULL;
+    unsigned char* g   = NULL;
+#else
+    unsigned char  p[1024];
+    unsigned char  g[1024];
+#endif
+
+    WOLFSSL_ENTER("SetDhInternal");
+
+    if (dh == NULL || dh->p == NULL || dh->g == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz)
+        WOLFSSL_MSG("Bad p internal size");
+    else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz)
+        WOLFSSL_MSG("Bad g internal size");
+    else {
+    #ifdef WOLFSSL_SMALL_STACK
+        p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+
+        if (p == NULL || g == NULL) {
+            XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+            return ret;
+        }
+    #endif
+
+        pSz = wolfSSL_BN_bn2bin(dh->p, p);
+        gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+        if (pSz <= 0 || gSz <= 0)
+            WOLFSSL_MSG("Bad BN2bin set");
+        else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0)
+            WOLFSSL_MSG("Bad DH SetKey");
+        else {
+            dh->inSet = 1;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    #endif
+    }
+
+
+    return ret;
+}
+
+/* return code compliant with OpenSSL :
+ *   DH prime size in bytes if success, 0 if error
+ */
+int wolfSSL_DH_size(WOLFSSL_DH* dh)
+{
+    WOLFSSL_MSG("wolfSSL_DH_size");
+
+    if (dh == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    return wolfSSL_BN_num_bytes(dh->p);
+}
+
+
+/* This sets a big number with the 1536-bit prime from RFC 3526.
+ *
+ * bn  if not NULL then the big number structure is used. If NULL then a new
+ *     big number structure is created.
+ *
+ * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure.
+ */
+WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn)
+{
+    const char prm[] = {
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234"
+        "C4C6628B80DC1CD129024E088A67CC74"
+        "020BBEA63B139B22514A08798E3404DD"
+        "EF9519B3CD3A431B302B0A6DF25F1437"
+        "4FE1356D6D51C245E485B576625E7EC6"
+        "F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        "EE386BFB5A899FA5AE9F24117C4B1FE6"
+        "49286651ECE45B3DC2007CB8A163BF05"
+        "98DA48361C55D39A69163FA8FD24CF5F"
+        "83655D23DCA3AD961C62F356208552BB"
+        "9ED529077096966D670C354E4ABC9804"
+        "F1746C08CA237327FFFFFFFFFFFFFFFF"
+    };
+
+    WOLFSSL_ENTER("wolfSSL_DH_1536_prime");
+
+    if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error converting DH 1536 prime to big number");
+        return NULL;
+    }
+
+    return bn;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
+{
+    int            ret    = WOLFSSL_FAILURE;
+    word32         pubSz  = 768;
+    word32         privSz = 768;
+    int            initTmpRng = 0;
+    WC_RNG*        rng    = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    unsigned char* pub    = NULL;
+    unsigned char* priv   = NULL;
+    WC_RNG*        tmpRNG = NULL;
+#else
+    unsigned char  pub [768];
+    unsigned char  priv[768];
+    WC_RNG         tmpRNG[1];
+#endif
+
+    WOLFSSL_MSG("wolfSSL_DH_generate_key");
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    pub    = (unsigned char*)XMALLOC(pubSz,   NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    priv   = (unsigned char*)XMALLOC(privSz,  NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+
+    if (tmpRNG == NULL || pub == NULL || priv == NULL) {
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        XFREE(pub,    NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        XFREE(priv,   NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+        return ret;
+    }
+#endif
+
+    if (dh == NULL || dh->p == NULL || dh->g == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS)
+            WOLFSSL_MSG("Bad DH set internal");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+       if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz,
+                                                               pub, &pubSz) < 0)
+            WOLFSSL_MSG("Bad wc_DhGenerateKeyPair");
+       else {
+            if (dh->pub_key)
+                wolfSSL_BN_free(dh->pub_key);
+
+            dh->pub_key = wolfSSL_BN_new();
+            if (dh->pub_key == NULL) {
+                WOLFSSL_MSG("Bad DH new pub");
+            }
+            if (dh->priv_key)
+                wolfSSL_BN_free(dh->priv_key);
+
+            dh->priv_key = wolfSSL_BN_new();
+
+            if (dh->priv_key == NULL) {
+                WOLFSSL_MSG("Bad DH new priv");
+            }
+
+            if (dh->pub_key && dh->priv_key) {
+               if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL)
+                   WOLFSSL_MSG("Bad DH bn2bin error pub");
+               else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL)
+                   WOLFSSL_MSG("Bad DH bn2bin error priv");
+               else
+                   ret = WOLFSSL_SUCCESS;
+            }
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+    XFREE(pub,    NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(priv,   NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+#endif
+
+    return ret;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   size of shared secret if success, -1 if error
+ */
+int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub,
+                          WOLFSSL_DH* dh)
+{
+    int            ret    = WOLFSSL_FATAL_ERROR;
+    word32         keySz  = 0;
+    word32         pubSz  = 1024;
+    word32         privSz = 1024;
+#ifdef WOLFSSL_SMALL_STACK
+    unsigned char* pub    = NULL;
+    unsigned char* priv   = NULL;
+#else
+    unsigned char  pub [1024];
+    unsigned char  priv[1024];
+#endif
+
+    WOLFSSL_MSG("wolfSSL_DH_compute_key");
+
+#ifdef WOLFSSL_SMALL_STACK
+    pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (pub == NULL)
+        return ret;
+
+    priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+    if (priv == NULL) {
+        XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+        return ret;
+    }
+#endif
+
+    if (dh == NULL || dh->priv_key == NULL || otherPub == NULL)
+        WOLFSSL_MSG("Bad function arguments");
+    else if ((keySz = (word32)DH_size(dh)) == 0)
+        WOLFSSL_MSG("Bad DH_size");
+    else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz)
+        WOLFSSL_MSG("Bad priv internal size");
+    else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz)
+        WOLFSSL_MSG("Bad otherPub size");
+    else {
+        privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv);
+        pubSz  = wolfSSL_BN_bn2bin(otherPub, pub);
+        if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){
+                WOLFSSL_MSG("Bad DH set internal");
+        }
+        if (privSz <= 0 || pubSz <= 0)
+            WOLFSSL_MSG("Bad BN2bin set");
+        else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz,
+                            priv, privSz, pub, pubSz) < 0)
+            WOLFSSL_MSG("wc_DhAgree failed");
+        else
+            ret = (int)keySz;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(pub,  NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+#endif
+
+    return ret;
+}
+#endif /* NO_DH */
+
+
+#ifndef NO_DSA
+static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa)
+{
+    if (dsa) {
+        dsa->p        = NULL;
+        dsa->q        = NULL;
+        dsa->g        = NULL;
+        dsa->pub_key  = NULL;
+        dsa->priv_key = NULL;
+        dsa->internal = NULL;
+        dsa->inSet    = 0;
+        dsa->exSet    = 0;
+    }
+}
+
+
+WOLFSSL_DSA* wolfSSL_DSA_new(void)
+{
+    WOLFSSL_DSA* external;
+    DsaKey*     key;
+
+    WOLFSSL_MSG("wolfSSL_DSA_new");
+
+    key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL,
+                                    DYNAMIC_TYPE_DSA);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
+        return NULL;
+    }
+
+    InitwolfSSL_DSA(external);
+    if (wc_InitDsaKey(key) != 0) {
+        WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_DSA);
+        wolfSSL_DSA_free(external);
+        return NULL;
+    }
+    external->internal = key;
+
+    return external;
+}
+
+
+void wolfSSL_DSA_free(WOLFSSL_DSA* dsa)
+{
+    WOLFSSL_MSG("wolfSSL_DSA_free");
+
+    if (dsa) {
+        if (dsa->internal) {
+            FreeDsaKey((DsaKey*)dsa->internal);
+            XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA);
+            dsa->internal = NULL;
+        }
+        wolfSSL_BN_free(dsa->priv_key);
+        wolfSSL_BN_free(dsa->pub_key);
+        wolfSSL_BN_free(dsa->g);
+        wolfSSL_BN_free(dsa->q);
+        wolfSSL_BN_free(dsa->p);
+        InitwolfSSL_DSA(dsa);  /* set back to NULLs for safety */
+
+        XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
+        dsa = NULL;
+    }
+}
+
+#endif /* NO_DSA */
+
+#endif /* OPENSSL_EXTRA */
+#if !defined(NO_RSA) && defined(OPENSSL_EXTRA_X509_SMALL)
+static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa)
+{
+    if (rsa) {
+        XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
+    }
+}
+
+void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_free");
+
+    if (rsa) {
+        if (rsa->internal) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+            WC_RNG* rng;
+
+            /* check if RNG is owned before freeing it */
+            if (rsa->ownRng) {
+                rng = ((RsaKey*)rsa->internal)->rng;
+                if (rng != NULL && rng != &globalRNG) {
+                    wc_FreeRng(rng);
+                    XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+                }
+            }
+#endif /* WC_RSA_BLINDING */
+            wc_FreeRsaKey((RsaKey*)rsa->internal);
+            XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA);
+            rsa->internal = NULL;
+        }
+        wolfSSL_BN_free(rsa->iqmp);
+        wolfSSL_BN_free(rsa->dmq1);
+        wolfSSL_BN_free(rsa->dmp1);
+        wolfSSL_BN_free(rsa->q);
+        wolfSSL_BN_free(rsa->p);
+        wolfSSL_BN_free(rsa->d);
+        wolfSSL_BN_free(rsa->e);
+        wolfSSL_BN_free(rsa->n);
+
+    #ifdef WC_RSA_BLINDING
+        if (wc_FreeRng(rsa->rng) != 0) {
+            WOLFSSL_MSG("Issue freeing rng");
+        }
+        XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
+
+        InitwolfSSL_Rsa(rsa);  /* set back to NULLs for safety */
+
+        XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
+        rsa = NULL;
+    }
+}
+
+WOLFSSL_RSA* wolfSSL_RSA_new(void)
+{
+    WOLFSSL_RSA* external;
+    RsaKey*     key;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_new");
+
+    key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure");
+        return NULL;
+    }
+
+    external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL,
+                                     DYNAMIC_TYPE_RSA);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
+        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+        return NULL;
+    }
+
+    InitwolfSSL_Rsa(external);
+    if (wc_InitRsaKey(key, NULL) != 0) {
+        WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure");
+        XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+        XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+        return NULL;
+    }
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+    {
+        WC_RNG* rng = NULL;
+
+        rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (rng != NULL && wc_InitRng(rng) != 0) {
+            WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
+            XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+            rng = NULL;
+        }
+
+        external->ownRng = 1;
+        if (rng == NULL && initGlobalRNG) {
+            external->ownRng = 0;
+            rng = &globalRNG;
+        }
+
+        if (rng == NULL) {
+            WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
+            XFREE(external, NULL, DYNAMIC_TYPE_RSA);
+            XFREE(key, NULL, DYNAMIC_TYPE_RSA);
+            return NULL;
+        }
+
+        wc_RsaSetRNG(key, rng);
+    }
+#endif /* WC_RSA_BLINDING */
+
+    external->internal = key;
+    external->inSet = 0;
+    return external;
+}
+#endif /* !NO_RSA && OPENSSL_EXTRA_X509_SMALL */
+
+/* these defines are to make sure the functions SetIndividualExternal is not
+ * declared and then not used. */
+#if !defined(NO_ASN) || !defined(NO_DSA) || defined(HAVE_ECC) || \
+    (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA))
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* when calling SetIndividualExternal, mpi should be cleared by caller if no
+ * longer used. ie mp_clear(mpi). This is to free data when fastmath is
+ * disabled since a copy of mpi is made by this function and placed into bn.
+ */
+static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi)
+{
+    byte dynamic = 0;
+
+    WOLFSSL_MSG("Entering SetIndividualExternal");
+
+    if (mpi == NULL || bn == NULL) {
+        WOLFSSL_MSG("mpi NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (*bn == NULL) {
+        *bn = wolfSSL_BN_new();
+        if (*bn == NULL) {
+            WOLFSSL_MSG("SetIndividualExternal alloc failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+        dynamic = 1;
+    }
+
+    if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        if (dynamic == 1) {
+            wolfSSL_BN_free(*bn);
+        }
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA /* only without X509_SMALL */
+static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi)
+{
+    WOLFSSL_MSG("Entering SetIndividualInternal");
+
+    if (bn == NULL || bn->internal == NULL) {
+        WOLFSSL_MSG("bn NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) {
+        WOLFSSL_MSG("mpi NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
+        WOLFSSL_MSG("mp_copy error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_ASN
+WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
+                                       WOLFSSL_BIGNUM *bn)
+{
+    mp_int mpi;
+    word32 idx = 0;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN");
+
+    if (ai == NULL) {
+        return NULL;
+    }
+
+    if ((ret = GetInt(&mpi, ai->data, &idx, ai->dataMax)) != 0) {
+        /* expecting ASN1 format for INTEGER */
+        WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret);
+        return NULL;
+    }
+
+    /* mp_clear needs called because mpi is copied and causes memory leak with
+     * --disable-fastmath */
+    ret = SetIndividualExternal(&bn, &mpi);
+    mp_clear(&mpi);
+
+    if (ret != WOLFSSL_SUCCESS) {
+        return NULL;
+    }
+    return bn;
+}
+#endif /* !NO_ASN */
+
+#if !defined(NO_DSA) && !defined(NO_DH)
+WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa)
+{
+    WOLFSSL_DH* dh;
+    DhKey*      key;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_dup_DH");
+
+    if (dsa == NULL) {
+        return NULL;
+    }
+
+    dh = wolfSSL_DH_new();
+    if (dh == NULL) {
+        return NULL;
+    }
+    key = (DhKey*)dh->internal;
+
+    if (dsa->p != NULL &&
+        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+    if (dsa->g != NULL &&
+        SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa g key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+    if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        wolfSSL_DH_free(dh);
+        return NULL;
+    }
+
+    return dh;
+}
+#endif /* !defined(NO_DSA) && !defined(NO_DH) */
+
+#endif /* OPENSSL_EXTRA */
+#endif /* !NO_RSA && !NO_DSA */
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_DSA
+/* wolfSSL -> OpenSSL */
+static int SetDsaExternal(WOLFSSL_DSA* dsa)
+{
+    DsaKey* key;
+    WOLFSSL_MSG("Entering SetDsaExternal");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("dsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (DsaKey*)dsa->internal;
+
+    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa y key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa x key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dsa->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Openssl -> WolfSSL */
+static int SetDsaInternal(WOLFSSL_DSA* dsa)
+{
+    DsaKey* key;
+    WOLFSSL_MSG("Entering SetDsaInternal");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("dsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (DsaKey*)dsa->internal;
+
+    if (dsa->p != NULL &&
+        SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->q != NULL &&
+        SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->g != NULL &&
+        SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa g key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (dsa->pub_key != NULL) {
+        if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa pub_key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* public key */
+        key->type = DSA_PUBLIC;
+    }
+
+    if (dsa->priv_key != NULL) {
+        if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa priv_key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = DSA_PRIVATE;
+    }
+
+    dsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_DSA */
+#endif /* OPENSSL_EXTRA */
+
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \
+    !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* WolfSSL -> OpenSSL */
+static int SetRsaExternal(WOLFSSL_RSA* rsa)
+{
+    RsaKey* key;
+    WOLFSSL_MSG("Entering SetRsaExternal");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("rsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (RsaKey*)rsa->internal;
+
+    if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa n key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa e key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (key->type == RSA_PRIVATE) {
+        if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa d key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa p key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa q key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifndef RSA_LOW_MEM
+        if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa dP key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa dQ key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa u key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    #endif /* !RSA_LOW_MEM */
+    }
+    rsa->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#if !defined(NO_RSA)
+#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+/* Openssl -> WolfSSL */
+static int SetRsaInternal(WOLFSSL_RSA* rsa)
+{
+    RsaKey* key;
+    WOLFSSL_MSG("Entering SetRsaInternal");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("rsa key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (RsaKey*)rsa->internal;
+
+    if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa n key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa e key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* public key */
+    key->type = RSA_PUBLIC;
+
+    if (rsa->d != NULL) {
+        if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("rsa d key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = RSA_PRIVATE;
+    }
+
+    if (rsa->p != NULL &&
+        SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa p key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->q != NULL &&
+        SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa q key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+#ifndef RSA_LOW_MEM
+    if (rsa->dmp1 != NULL &&
+        SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa dP key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->dmq1 != NULL &&
+        SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa dQ key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (rsa->iqmp != NULL &&
+        SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("rsa u key error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+#endif /* !RSA_LOW_MEM */
+
+    rsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* SSL_SUCCESS on ok */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn)
+{
+    (void)rsa;
+    (void)bn;
+    WOLFSSL_STUB("RSA_blinding_on");
+    WOLFSSL_MSG("wolfSSL_RSA_blinding_on");
+
+    return WOLFSSL_SUCCESS;  /* on by default */
+}
+#endif
+
+/* return compliant with OpenSSL
+ *   size of encrypted data if success , -1 if error
+ */
+int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr,
+                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+    int outLen;
+    int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    int  mgf = WC_MGF1NONE;
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+#endif
+
+    WOLFSSL_MSG("wolfSSL_RSA_public_encrypt");
+
+    /* Check and remap the padding to internal values, if needed. */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    if (padding == RSA_PKCS1_PADDING)
+        padding = WC_RSA_PKCSV15_PAD;
+    else if (padding == RSA_PKCS1_OAEP_PADDING) {
+        padding = WC_RSA_OAEP_PAD;
+        hash = WC_HASH_TYPE_SHA;
+        mgf = WC_MGF1SHA1;
+    }
+#else
+    if (padding == RSA_PKCS1_PADDING)
+      ;
+#endif
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = wolfSSL_RSA_size(rsa);
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \
+    !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING)
+    rng = ((RsaKey*)rsa->internal)->rng;
+#endif
+    if (rng == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (tmpRNG == NULL)
+            return 0;
+#endif
+
+        if (wc_InitRng(tmpRNG) == 0) {
+            rng = tmpRNG;
+            initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+        }
+    }
+
+    if (outLen == 0) {
+        WOLFSSL_MSG("Bad RSA size");
+    }
+
+    if (rng) {
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+        ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen,
+                             (RsaKey*)rsa->internal, rng, padding,
+                             hash, mgf, NULL, 0);
+#else
+        ret = wc_RsaPublicEncrypt(fr, len, to, outLen,
+                             (RsaKey*)rsa->internal, rng);
+#endif
+        if (ret <= 0) {
+            WOLFSSL_MSG("Bad Rsa Encrypt");
+        }
+        if (len <= 0) {
+            WOLFSSL_MSG("Bad Rsa Encrypt");
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    if (ret >= 0)
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed");
+        ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */
+    }
+    return ret;
+}
+
+/* return compliant with OpenSSL
+ *   size of plain recovered data if success , -1 if error
+ */
+int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr,
+                            unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int outLen;
+    int ret = 0;
+  #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    int mgf = WC_MGF1NONE;
+    enum wc_HashType hash = WC_HASH_TYPE_NONE;
+  #endif
+
+    WOLFSSL_MSG("wolfSSL_RSA_private_decrypt");
+
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    if (padding == RSA_PKCS1_PADDING)
+        padding = WC_RSA_PKCSV15_PAD;
+    else if (padding == RSA_PKCS1_OAEP_PADDING) {
+        padding = WC_RSA_OAEP_PAD;
+        hash = WC_HASH_TYPE_SHA;
+        mgf = WC_MGF1SHA1;
+    }
+#else
+    if (padding == RSA_PKCS1_PADDING)
+        ;
+#endif
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = wolfSSL_RSA_size(rsa);
+    if (outLen == 0) {
+        WOLFSSL_MSG("Bad RSA size");
+    }
+
+    /* size of 'to' buffer must be size of RSA key */
+#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)
+    ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen,
+                            (RsaKey*)rsa->internal, padding,
+                            hash, mgf, NULL, 0);
+#else
+    ret = wc_RsaPrivateDecrypt(fr, len, to, outLen,
+                            (RsaKey*)rsa->internal);
+#endif
+
+    if (len <= 0) {
+        WOLFSSL_MSG("Bad Rsa Decrypt");
+    }
+
+    if (ret > 0)
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed");
+        ret = WOLFSSL_FATAL_ERROR;
+    }
+    return ret;
+}
+
+
+/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA
+ * public decrypt.
+ *
+ * len  Length of input buffer
+ * in   Input buffer to sign
+ * out  Output buffer (expected to be greater than or equal to RSA key size)
+ * rsa     Key to use for encryption
+ * padding Type of RSA padding to use.
+ */
+int wolfSSL_RSA_private_encrypt(int len, unsigned char* in,
+                            unsigned char* out, WOLFSSL_RSA* rsa, int padding)
+{
+    int sz = 0;
+    WC_RNG* rng = NULL;
+    RsaKey* key;
+
+    WOLFSSL_MSG("wolfSSL_RSA_private_encrypt");
+
+    if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return 0;
+    }
+
+    if (padding != RSA_PKCS1_PADDING) {
+        WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("Setting internal RSA structure");
+
+        if (SetRsaInternal(rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    key = (RsaKey*)rsa->internal;
+    #if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA)
+    rng = key->rng;
+    #else
+#ifndef HAVE_FIPS
+    if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0) {
+#else
+    if (wc_InitRng(rng) != 0) {
+#endif
+        WOLFSSL_MSG("Error with random number");
+        return SSL_FATAL_ERROR;
+    }
+    #endif
+
+    /* size of output buffer must be size of RSA key */
+    sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng);
+    #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA)
+    if (wc_FreeRng(rng) != 0) {
+        WOLFSSL_MSG("Error freeing random number generator");
+        return SSL_FATAL_ERROR;
+    }
+    #endif
+    if (sz <= 0) {
+        WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz);
+        return 0;
+    }
+
+    return sz;
+}
+#endif /* HAVE_USER_RSA */
+
+/* return compliant with OpenSSL
+ *   RSA modulus size in bytes, -1 if error
+ */
+int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
+{
+    WOLFSSL_ENTER("wolfSSL_RSA_size");
+
+    if (rsa == NULL)
+        return WOLFSSL_FATAL_ERROR;
+    if (rsa->inSet == 0)
+    {
+        if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+    return wc_RsaEncryptSize((RsaKey*)rsa->internal);
+}
+
+
+/* Generates a RSA key of length len
+ *
+ * len  length of RSA key i.e. 2048
+ * e    e to use when generating RSA key
+ * f    callback function for generation details
+ * data user callback argument
+ *
+ * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly
+ *       rounded down. For example generating a key of size 2999 with e =
+ *       65537 will make a key of size 374 instead of 375.
+ * Returns a new RSA key on success and NULL on failure
+ */
+WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e,
+                                      void(*f)(int, int, void*), void* data)
+{
+    WOLFSSL_RSA*    rsa = NULL;
+    WOLFSSL_BIGNUM* bn  = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
+
+    (void)f;
+    (void)data;
+
+    if (len < 0) {
+        WOLFSSL_MSG("Bad argument: length was less than 0");
+        return NULL;
+    }
+
+    bn = wolfSSL_BN_new();
+    if (bn == NULL) {
+        WOLFSSL_MSG("Error creating big number");
+        return NULL;
+    }
+
+    if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) {
+        WOLFSSL_MSG("Error using e value");
+        wolfSSL_BN_free(bn);
+        return NULL;
+    }
+
+    rsa = wolfSSL_RSA_new();
+    if (rsa == NULL) {
+        WOLFSSL_MSG("memory error");
+    }
+    else {
+        if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){
+            wolfSSL_RSA_free(rsa);
+            rsa = NULL;
+        }
+    }
+    wolfSSL_BN_free(bn);
+
+    return rsa;
+}
+
+
+/* return compliant with OpenSSL
+ *   1 if success, 0 if error
+ */
+int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn,
+                                void* cb)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    (void)cb;
+    (void)bn;
+    (void)bits;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex");
+
+    if (rsa == NULL || rsa->internal == NULL) {
+        /* bit size checked during make key call */
+        WOLFSSL_MSG("bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+    #ifdef WOLFSSL_SMALL_STACK
+        WC_RNG* rng = NULL;
+    #else
+        WC_RNG  rng[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (rng == NULL)
+            return WOLFSSL_FAILURE;
+    #endif
+
+        if (wc_InitRng(rng) < 0)
+            WOLFSSL_MSG("RNG init failed");
+        else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits,
+                    wolfSSL_BN_get_word(bn), rng) != MP_OKAY)
+            WOLFSSL_MSG("wc_MakeRsaKey failed");
+        else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS)
+            WOLFSSL_MSG("SetRsaExternal failed");
+        else {
+            rsa->inSet = 1;
+            ret = WOLFSSL_SUCCESS;
+        }
+
+        wc_FreeRng(rng);
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+    #endif
+    }
+#else
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+    return ret;
+}
+#endif /* NO_RSA */
+
+#ifndef NO_DSA
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_key");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (dsa->inSet == 0) {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return ret;
+        }
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+        int initTmpRng = 0;
+        WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        WC_RNG *tmpRNG = NULL;
+#else
+        WC_RNG tmpRNG[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (tmpRNG == NULL)
+            return WOLFSSL_FATAL_ERROR;
+#endif
+        if (wc_InitRng(tmpRNG) == 0) {
+            rng = tmpRNG;
+            initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+        }
+
+        if (rng) {
+            if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY)
+                WOLFSSL_MSG("wc_MakeDsaKey failed");
+            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+                WOLFSSL_MSG("SetDsaExternal failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+
+        if (initTmpRng)
+            wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+    }
+#else /* WOLFSSL_KEY_GEN */
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+    return ret;
+}
+
+
+/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail
+ */
+WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed,
+        int seedLen, int* counterRet, unsigned long* hRet,
+        WOLFSSL_BN_CB cb, void* CBArg)
+{
+    WOLFSSL_DSA* dsa;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()");
+
+    (void)cb;
+    (void)CBArg;
+    dsa = wolfSSL_DSA_new();
+    if (dsa == NULL) {
+        return NULL;
+    }
+
+    if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen,
+                                  counterRet, hRet, NULL) != SSL_SUCCESS) {
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    return dsa;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
+                                       unsigned char* seed, int seedLen,
+                                       int* counterRet,
+                                       unsigned long* hRet, void* cb)
+{
+    int ret = WOLFSSL_FAILURE;
+
+    (void)bits;
+    (void)seed;
+    (void)seedLen;
+    (void)counterRet;
+    (void)hRet;
+    (void)cb;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex");
+
+    if (dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_KEY_GEN
+    {
+        int initTmpRng = 0;
+        WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+        WC_RNG *tmpRNG = NULL;
+#else
+        WC_RNG tmpRNG[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+        tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+        if (tmpRNG == NULL)
+            return WOLFSSL_FATAL_ERROR;
+#endif
+        if (wc_InitRng(tmpRNG) == 0) {
+            rng = tmpRNG;
+            initTmpRng = 1;
+        }
+        else {
+            WOLFSSL_MSG("Bad RNG Init, trying global");
+            if (initGlobalRNG == 0)
+                WOLFSSL_MSG("Global RNG no Init");
+            else
+                rng = &globalRNG;
+        }
+
+        if (rng) {
+            if (wc_MakeDsaParameters(rng, bits,
+                                     (DsaKey*)dsa->internal) != MP_OKAY)
+                WOLFSSL_MSG("wc_MakeDsaParameters failed");
+            else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS)
+                WOLFSSL_MSG("SetDsaExternal failed");
+            else
+                ret = WOLFSSL_SUCCESS;
+        }
+
+        if (initTmpRng)
+            wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+    }
+#else /* WOLFSSL_KEY_GEN */
+    WOLFSSL_MSG("No Key Gen built in");
+#endif
+
+    return ret;
+}
+
+/* return WOLFSSL_SUCCESS on success, < 0 otherwise */
+int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
+                       WOLFSSL_DSA* dsa)
+{
+    int     ret = WOLFSSL_FATAL_ERROR;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
+
+    if (d == NULL || sigRet == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return ret;
+    }
+
+    if (dsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return ret;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FATAL_ERROR;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
+            WOLFSSL_MSG("DsaSign failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+}
+
+
+int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
+                        WOLFSSL_DSA* dsa, int *dsacheck)
+{
+    int    ret = WOLFSSL_FATAL_ERROR;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
+
+    if (d == NULL || sig == NULL || dsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+    if (dsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck);
+    if (ret != 0 || *dsacheck != 1) {
+        WOLFSSL_MSG("DsaVerify failed");
+        return ret;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_DSA */
+
+
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+
+#ifdef DEBUG_SIGN
+static void show(const char *title, const unsigned char *out, unsigned int outlen)
+{
+    const unsigned char *pt;
+    printf("%s[%d] = \n", title, (int)outlen);
+    outlen = outlen>100?100:outlen;
+    for (pt = out; pt < out + outlen;
+            printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++);
+    printf("\n");
+}
+#else
+#define show(a,b,c)
+#endif
+
+/* return SSL_SUCCES on ok, 0 otherwise */
+int wolfSSL_RSA_sign(int type, const unsigned char* m,
+                           unsigned int mLen, unsigned char* sigRet,
+                           unsigned int* sigLen, WOLFSSL_RSA* rsa)
+{
+    return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1);
+}
+
+int wolfSSL_RSA_sign_ex(int type, const unsigned char* m,
+                           unsigned int mLen, unsigned char* sigRet,
+                           unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag)
+{
+    word32  outLen;
+    word32  signSz;
+    int     initTmpRng = 0;
+    WC_RNG* rng        = NULL;
+    int     ret        = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG     = NULL;
+    byte*   encodedSig = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+    byte    encodedSig[MAX_ENCODED_SIG_SZ];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_RSA_sign");
+
+    if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return 0;
+    }
+    show("Message to Sign", m, mLen);
+
+    switch (type) {
+    #ifdef WOLFSSL_MD2
+        case NID_md2:       type = MD2h;    break;
+    #endif
+    #ifndef NO_MD5
+        case NID_md5:       type = MD5h;    break;
+    #endif
+    #ifndef NO_SHA
+        case NID_sha1:      type = SHAh;    break;
+    #endif
+    #ifndef NO_SHA256
+        case NID_sha256:    type = SHA256h; break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case NID_sha384:    type = SHA384h; break;
+    #endif
+    #ifdef WOLFSSL_SHA512
+        case NID_sha512:    type = SHA512h; break;
+    #endif
+        default:
+            WOLFSSL_MSG("This NID (md type) not configured or not implemented");
+            return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return 0;
+
+    encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
+                                                   DYNAMIC_TYPE_SIGNATURE);
+    if (encodedSig == NULL) {
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+        return 0;
+    }
+#endif
+
+    if (outLen == 0)
+        WOLFSSL_MSG("Bad RSA size");
+    else if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+
+        signSz = wc_EncodeSignature(encodedSig, m, mLen, type);
+        if (signSz == 0) {
+            WOLFSSL_MSG("Bad Encode Signature");
+        }
+        else {
+            show("Encoded Message", encodedSig, signSz);
+            if (flag != 0) {
+                ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen,
+                                (RsaKey*)rsa->internal, rng);
+                if (ret <= 0) {
+                    WOLFSSL_MSG("Bad Rsa Sign");
+                    ret = 0;
+                }
+                else {
+                    *sigLen = (unsigned int)ret;
+                    ret = SSL_SUCCESS;
+                    show("Signature", sigRet, *sigLen);
+                }
+            } else {
+                ret = SSL_SUCCESS;
+                XMEMCPY(sigRet, encodedSig, signSz);
+                *sigLen = signSz;
+            }
+        }
+
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG,     NULL, DYNAMIC_TYPE_RNG);
+    XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
+#endif
+
+    if (ret == WOLFSSL_SUCCESS)
+        WOLFSSL_MSG("wolfSSL_RSA_sign success");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_sign failed");
+    }
+    return ret;
+}
+
+
+/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */
+int wolfSSL_RSA_verify(int type, const unsigned char* m,
+                               unsigned int mLen, const unsigned char* sig,
+                               unsigned int sigLen, WOLFSSL_RSA* rsa)
+{
+    int     ret;
+    unsigned char *sigRet ;
+    unsigned char *sigDec ;
+    unsigned int   len;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_verify");
+    if ((m == NULL) || (sig == NULL)) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (sigRet == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        return WOLFSSL_FAILURE;
+    }
+    sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (sigDec == NULL) {
+        WOLFSSL_MSG("Memory failure");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    /* get non-encrypted signature to be compared with decrypted sugnature*/
+    ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0);
+    if (ret <= 0) {
+        WOLFSSL_MSG("Message Digest Error");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    show("Encoded Message", sigRet, len);
+    /* decrypt signature */
+    ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
+        (RsaKey*)rsa->internal);
+    if (ret <= 0) {
+        WOLFSSL_MSG("RSA Decrypt error");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+    show("Decrypted Signature", sigDec, ret);
+
+    if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) {
+        WOLFSSL_MSG("wolfSSL_RSA_verify success");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_SUCCESS;
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_verify failed");
+        XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+}
+
+int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from,
+                          unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+    int tlen = 0;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
+
+    if (rsa == NULL || rsa->internal == NULL || from == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return 0;
+    }
+
+    if (padding != RSA_PKCS1_PADDING) {
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding");
+        return 0;
+    }
+
+    if (rsa->inSet == 0)
+    {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return 0;
+        }
+    }
+
+    /* size of 'to' buffer must be size of RSA key */
+    tlen = wc_RsaSSL_Verify(from, flen, to, wolfSSL_RSA_size(rsa),
+                            (RsaKey*)rsa->internal);
+    if (tlen <= 0)
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed");
+    else {
+        WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success");
+    }
+    return tlen;
+}
+
+
+/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */
+int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
+{
+    int    err;
+    mp_int tmp;
+
+    WOLFSSL_MSG("wolfSSL_RsaGenAdd");
+
+    if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL ||
+                       rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
+        WOLFSSL_MSG("rsa no init error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (mp_init(&tmp) != MP_OKAY) {
+        WOLFSSL_MSG("mp_init error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp);
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_sub_d error");
+    }
+    else
+        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
+                     (mp_int*)rsa->dmp1->internal);
+
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_mod error");
+    }
+    else
+        err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp);
+    if (err != MP_OKAY) {
+        WOLFSSL_MSG("mp_sub_d error");
+    }
+    else
+        err = mp_mod((mp_int*)rsa->d->internal, &tmp,
+                     (mp_int*)rsa->dmq1->internal);
+
+    mp_clear(&tmp);
+
+    if (err == MP_OKAY)
+        return WOLFSSL_SUCCESS;
+    else
+        return WOLFSSL_FATAL_ERROR;
+}
+#endif /* NO_RSA */
+
+int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init");
+
+    if (ctx != NULL) {
+        /* wc_HmacSetKey sets up ctx->hmac */
+        XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX));
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key,
+                             int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e)
+{
+    WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex");
+
+    /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */
+    (void)e;
+    return wolfSSL_HMAC_Init(ctx, key, keylen, type);
+}
+
+
+/* Deep copy of information from src to des structure
+ *
+ * des destination to copy information to
+ * src structure to get infromation from
+ *
+ * Returns SSL_SUCCESS on success and SSL_FAILURE on error
+ */
+int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src)
+{
+    void* heap = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy");
+
+    if (des == NULL || src == NULL) {
+        return SSL_FAILURE;
+    }
+
+#ifndef HAVE_FIPS
+    heap = src->hmac.heap;
+#endif
+
+    if (wc_HmacInit(&des->hmac, heap, 0) != 0) {
+        WOLFSSL_MSG("Error initializing HMAC");
+        return SSL_FAILURE;
+    }
+
+    des->type = src->type;
+
+    /* requires that hash structures have no dynamic parts to them */
+    switch (src->hmac.macType) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            XMEMCPY(&des->hmac.hash.md5, &src->hmac.hash.md5, sizeof(wc_Md5));
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            XMEMCPY(&des->hmac.hash.sha, &src->hmac.hash.sha, sizeof(wc_Sha));
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            XMEMCPY(&des->hmac.hash.sha224, &src->hmac.hash.sha224,
+                    sizeof(wc_Sha224));
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            XMEMCPY(&des->hmac.hash.sha256, &src->hmac.hash.sha256,
+                    sizeof(wc_Sha256));
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            XMEMCPY(&des->hmac.hash.sha384, &src->hmac.hash.sha384,
+                    sizeof(wc_Sha384));
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            XMEMCPY(&des->hmac.hash.sha512, &src->hmac.hash.sha512,
+                    sizeof(wc_Sha512));
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+        default:
+            WOLFSSL_MSG("Unknown or unsupported hash type");
+            return WOLFSSL_FAILURE;
+    }
+
+    XMEMCPY((byte*)des->hmac.ipad, (byte*)src->hmac.ipad, WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte*)des->hmac.opad, (byte*)src->hmac.opad, WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte*)des->hmac.innerHash, (byte*)src->hmac.innerHash,
+                                                            WC_MAX_DIGEST_SIZE);
+#ifndef HAVE_FIPS
+    des->hmac.heap    = heap;
+#endif
+    des->hmac.macType = src->hmac.macType;
+    des->hmac.innerHashKeyed = src->hmac.innerHashKeyed;
+    XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad,
+                                        WC_HMAC_BLOCK_SIZE);
+    XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad,
+                                        WC_HMAC_BLOCK_SIZE);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    XMEMCPY(&des->hmac.asyncDev, &src->hmac.asyncDev, sizeof(WC_ASYNC_DEV));
+    des->hmac.keyLen = src->hmac.keyLen;
+    #ifdef HAVE_CAVIUM
+        des->hmac.data = (byte*)XMALLOC(src->hmac.dataLen, des->hmac.heap,
+                DYNAMIC_TYPE_HMAC);
+        if (des->hmac.data == NULL) {
+            return BUFFER_E;
+        }
+        XMEMCPY(des->hmac.data, src->hmac.data, src->hmac.dataLen);
+        des->hmac.dataLen = src->hmac.dataLen;
+    #endif /* HAVE_CAVIUM */
+#endif /* WOLFSSL_ASYNC_CRYPT */
+        return WOLFSSL_SUCCESS;
+}
+
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+
+static int _HMAC_Init(Hmac* hmac, int type, void* heap)
+{
+    int ret = 0;
+
+    switch (type) {
+    #ifndef NO_MD5
+        case WC_MD5:
+            ret = wc_InitMd5(&hmac->hash.md5);
+            break;
+    #endif /* !NO_MD5 */
+
+    #ifndef NO_SHA
+        case WC_SHA:
+            ret = wc_InitSha(&hmac->hash.sha);
+            break;
+    #endif /* !NO_SHA */
+
+    #ifdef WOLFSSL_SHA224
+        case WC_SHA224:
+            ret = wc_InitSha224(&hmac->hash.sha224);
+            break;
+    #endif /* WOLFSSL_SHA224 */
+
+    #ifndef NO_SHA256
+        case WC_SHA256:
+            ret = wc_InitSha256(&hmac->hash.sha256);
+            break;
+    #endif /* !NO_SHA256 */
+
+    #ifdef WOLFSSL_SHA384
+        case WC_SHA384:
+            ret = wc_InitSha384(&hmac->hash.sha384);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_SHA512
+        case WC_SHA512:
+            ret = wc_InitSha512(&hmac->hash.sha512);
+            break;
+    #endif /* WOLFSSL_SHA512 */
+
+    #ifdef HAVE_BLAKE2
+        case BLAKE2B_ID:
+            ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256);
+            break;
+    #endif /* HAVE_BLAKE2 */
+
+    #ifdef WOLFSSL_SHA3
+        case WC_SHA3_224:
+            ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_256:
+            ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_384:
+            ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+        case WC_SHA3_512:
+            ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
+            break;
+    #endif
+
+        default:
+            ret = BAD_FUNC_ARG;
+            break;
+    }
+
+    (void)heap;
+
+    return ret;
+}
+
+#else
+    #define _HMAC_Init _InitHmac
+#endif
+
+
+int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen,
+                  const EVP_MD* type)
+{
+    int hmac_error = 0;
+    void* heap = NULL;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Init");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("no ctx on init");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifndef HAVE_FIPS
+    heap = ctx->hmac.heap;
+#endif
+
+    if (type) {
+        WOLFSSL_MSG("init has type");
+
+#ifndef NO_MD5
+        if (XSTRNCMP(type, "MD5", 3) == 0) {
+            WOLFSSL_MSG("md5 hmac");
+            ctx->type = WC_MD5;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA224
+        if (XSTRNCMP(type, "SHA224", 6) == 0) {
+            WOLFSSL_MSG("sha224 hmac");
+            ctx->type = WC_SHA224;
+        }
+        else
+#endif
+#ifndef NO_SHA256
+        if (XSTRNCMP(type, "SHA256", 6) == 0) {
+            WOLFSSL_MSG("sha256 hmac");
+            ctx->type = WC_SHA256;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA384
+        if (XSTRNCMP(type, "SHA384", 6) == 0) {
+            WOLFSSL_MSG("sha384 hmac");
+            ctx->type = WC_SHA384;
+        }
+        else
+#endif
+#ifdef WOLFSSL_SHA512
+        if (XSTRNCMP(type, "SHA512", 6) == 0) {
+            WOLFSSL_MSG("sha512 hmac");
+            ctx->type = WC_SHA512;
+        }
+        else
+#endif
+
+#ifndef NO_SHA
+        /* has to be last since would pick or 256, 384, or 512 too */
+        if (XSTRNCMP(type, "SHA", 3) == 0) {
+            WOLFSSL_MSG("sha hmac");
+            ctx->type = WC_SHA;
+        }
+        else
+#endif
+        {
+            WOLFSSL_MSG("bad init type");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (key && keylen) {
+        WOLFSSL_MSG("keying hmac");
+
+        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+            hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key,
+                                       (word32)keylen);
+            if (hmac_error < 0){
+                wc_HmacFree(&ctx->hmac);
+                return WOLFSSL_FAILURE;
+            }
+            XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad,
+                                        WC_HMAC_BLOCK_SIZE);
+            XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad,
+                                        WC_HMAC_BLOCK_SIZE);
+        }
+        /* OpenSSL compat, no error */
+    } else if(ctx->type >= 0) { /* MD5 == 0 */
+        WOLFSSL_MSG("recover hmac");
+        if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) {
+            ctx->hmac.macType = (byte)ctx->type;
+            ctx->hmac.innerHashKeyed = 0;
+            XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad,
+                                       WC_HMAC_BLOCK_SIZE);
+            XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad,
+                                       WC_HMAC_BLOCK_SIZE);
+            if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap))
+                    !=0) {
+               return hmac_error;
+            }
+        }
+    }
+
+    (void)hmac_error;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data,
+                    int len)
+{
+    int hmac_error = 0;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Update");
+
+    if (ctx == NULL) {
+        WOLFSSL_MSG("no ctx");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (data) {
+        WOLFSSL_MSG("updating hmac");
+        hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len);
+        if (hmac_error < 0){
+            WOLFSSL_MSG("hmac update error");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash,
+                   unsigned int* len)
+{
+    int hmac_error;
+
+    WOLFSSL_MSG("wolfSSL_HMAC_Final");
+
+	/* "len" parameter is optional. */
+    if (ctx == NULL || hash == NULL) {
+        WOLFSSL_MSG("invalid parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    WOLFSSL_MSG("final hmac");
+    hmac_error = wc_HmacFinal(&ctx->hmac, hash);
+    if (hmac_error < 0){
+        WOLFSSL_MSG("final hmac error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (len) {
+        WOLFSSL_MSG("setting output len");
+        switch (ctx->type) {
+            #ifndef NO_MD5
+            case WC_MD5:
+                *len = WC_MD5_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifndef NO_SHA
+            case WC_SHA:
+                *len = WC_SHA_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA224
+            case WC_SHA224:
+                *len = WC_SHA224_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifndef NO_SHA256
+            case WC_SHA256:
+                *len = WC_SHA256_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA384
+            case WC_SHA384:
+                *len = WC_SHA384_DIGEST_SIZE;
+                break;
+            #endif
+
+            #ifdef WOLFSSL_SHA512
+            case WC_SHA512:
+                *len = WC_SHA512_DIGEST_SIZE;
+                break;
+            #endif
+
+            default:
+                WOLFSSL_MSG("bad hmac type");
+                return WOLFSSL_FAILURE;
+        }
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_HMAC_cleanup");
+
+    if (ctx)
+        wc_HmacFree(&ctx->hmac);
+
+    return SSL_SUCCESS;
+}
+
+
+const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id)
+{
+    WOLFSSL_MSG("wolfSSL_get_digestbynid");
+
+    switch(id) {
+#ifndef NO_MD5
+        case NID_md5:
+            return wolfSSL_EVP_md5();
+#endif
+#ifndef NO_SHA
+        case NID_sha1:
+            return wolfSSL_EVP_sha1();
+#endif
+        default:
+            WOLFSSL_MSG("Bad digest id value");
+    }
+
+    return NULL;
+}
+
+
+#ifndef NO_RSA
+WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key)
+{
+    WOLFSSL_RSA* local;
+
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA");
+
+    if (key == NULL) {
+        return NULL;
+    }
+
+    local = wolfSSL_RSA_new();
+    if (local == NULL) {
+        WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure");
+        return NULL;
+    }
+
+    if (key->type == EVP_PKEY_RSA) {
+        if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr,
+                    key->pkey_sz) != SSL_SUCCESS) {
+            /* now try public key */
+            if (wolfSSL_RSA_LoadDer_ex(local,
+                        (const unsigned char*)key->pkey.ptr, key->pkey_sz,
+                        WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) {
+                wolfSSL_RSA_free(local);
+                local = NULL;
+            }
+        }
+    }
+    else {
+        WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key");
+        wolfSSL_RSA_free(local);
+        local = NULL;
+    }
+    return local;
+}
+
+
+/* with set1 functions the pkey struct does not own the RSA structure
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
+ */
+int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key)
+{
+    if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA");
+    if (pkey->rsa != NULL && pkey->ownRsa == 1) {
+        wolfSSL_RSA_free(pkey->rsa);
+    }
+    pkey->rsa    = key;
+    pkey->ownRsa = 0; /* pkey does not own RSA */
+    pkey->type = EVP_PKEY_RSA;
+#ifdef WC_RSA_BLINDING
+    if (key->ownRng == 0) {
+        if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) {
+            WOLFSSL_MSG("Error setting RSA rng");
+            return SSL_FAILURE;
+        }
+    }
+#endif
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_RSA */
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key)
+{
+    (void)key;
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented");
+    WOLFSSL_STUB("EVP_PKEY_get1_DSA");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key)
+{
+    (void)key;
+    WOLFSSL_STUB("EVP_PKEY_get1_EC_KEY");
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented");
+
+    return NULL;
+}
+#endif
+
+void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_X_STATE");
+
+    if (ctx) {
+        switch (ctx->cipherType) {
+            case ARC4_TYPE:
+                WOLFSSL_MSG("returning arc4 state");
+                return (void*)&ctx->cipher.arc4.x;
+
+            default:
+                WOLFSSL_MSG("bad x state type");
+                return 0;
+        }
+    }
+
+    return NULL;
+}
+
+
+int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN");
+
+    if (ctx) {
+        switch (ctx->cipherType) {
+            case ARC4_TYPE:
+                WOLFSSL_MSG("returning arc4 state size");
+                return sizeof(Arc4);
+
+            default:
+                WOLFSSL_MSG("bad x state type");
+                return 0;
+        }
+    }
+
+    return 0;
+}
+
+
+#ifndef NO_DES3
+
+void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                            unsigned char* iv, int len)
+{
+    (void)len;
+
+    WOLFSSL_MSG("wolfSSL_3des_iv");
+
+    if (ctx == NULL || iv == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return;
+    }
+
+    if (doset)
+        wc_Des3_SetIV(&ctx->cipher.des3, iv);  /* OpenSSL compat, no ret */
+    else
+        XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE);
+}
+
+#endif /* NO_DES3 */
+
+
+#ifndef NO_AES
+
+void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset,
+                      unsigned char* iv, int len)
+{
+    (void)len;
+
+    WOLFSSL_MSG("wolfSSL_aes_ctr_iv");
+
+    if (ctx == NULL || iv == NULL) {
+        WOLFSSL_MSG("Bad function argument");
+        return;
+    }
+
+    if (doset)
+       (void)wc_AesSetIV(&ctx->cipher.aes, iv);  /* OpenSSL compat, no ret */
+    else
+        XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+}
+
+#endif /* NO_AES */
+
+#ifndef NO_WOLFSSL_STUB
+const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void)
+{
+    WOLFSSL_MSG("wolfSSL_ripemd160");
+    WOLFSSL_STUB("EVP_ripemd160");
+    return NULL;
+}
+#endif
+
+int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_MD_size");
+
+    if (type == NULL) {
+        WOLFSSL_MSG("No md type arg");
+        return BAD_FUNC_ARG;
+    }
+
+    if (XSTRNCMP(type, "SHA256", 6) == 0) {
+        return WC_SHA256_DIGEST_SIZE;
+    }
+#ifndef NO_MD5
+    else if (XSTRNCMP(type, "MD5", 3) == 0) {
+        return WC_MD5_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA224
+    else if (XSTRNCMP(type, "SHA224", 6) == 0) {
+        return WC_SHA224_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA384
+    else if (XSTRNCMP(type, "SHA384", 6) == 0) {
+        return WC_SHA384_DIGEST_SIZE;
+    }
+#endif
+#ifdef WOLFSSL_SHA512
+    else if (XSTRNCMP(type, "SHA512", 6) == 0) {
+        return WC_SHA512_DIGEST_SIZE;
+    }
+#endif
+#ifndef NO_SHA
+    /* has to be last since would pick or 256, 384, or 512 too */
+    else if (XSTRNCMP(type, "SHA", 3) == 0) {
+        return WC_SHA_DIGEST_SIZE;
+    }
+#endif
+
+    return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length");
+
+    switch (ctx->cipherType) {
+
+#ifdef HAVE_AES_CBC
+        case AES_128_CBC_TYPE :
+        case AES_192_CBC_TYPE :
+        case AES_256_CBC_TYPE :
+            WOLFSSL_MSG("AES CBC");
+            return AES_BLOCK_SIZE;
+#endif
+#ifdef WOLFSSL_AES_COUNTER
+        case AES_128_CTR_TYPE :
+        case AES_192_CTR_TYPE :
+        case AES_256_CTR_TYPE :
+            WOLFSSL_MSG("AES CTR");
+            return AES_BLOCK_SIZE;
+#endif
+#ifndef NO_DES3
+        case DES_CBC_TYPE :
+            WOLFSSL_MSG("DES CBC");
+            return DES_BLOCK_SIZE;
+
+        case DES_EDE3_CBC_TYPE :
+            WOLFSSL_MSG("DES EDE3 CBC");
+            return DES_BLOCK_SIZE;
+#endif
+#ifdef HAVE_IDEA
+        case IDEA_CBC_TYPE :
+            WOLFSSL_MSG("IDEA CBC");
+            return IDEA_BLOCK_SIZE;
+#endif
+#ifndef NO_RC4
+        case ARC4_TYPE :
+            WOLFSSL_MSG("ARC4");
+            return 0;
+#endif
+
+        case NULL_CIPHER_TYPE :
+            WOLFSSL_MSG("NULL");
+            return 0;
+
+        default: {
+            WOLFSSL_MSG("bad type");
+        }
+    }
+    return 0;
+}
+
+int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher)
+{
+    const char *name = (const char *)cipher;
+    WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length");
+
+#ifndef NO_AES
+    #ifdef WOLFSSL_AES_128
+    if (XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+#ifdef WOLFSSL_AES_COUNTER
+    #ifdef WOLFSSL_AES_128
+    if (XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)
+        return AES_BLOCK_SIZE;
+    #endif
+#endif
+#endif
+
+#ifndef NO_DES3
+    if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) ||
+           (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) {
+        return DES_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef HAVE_IDEA
+    if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0)
+        return IDEA_BLOCK_SIZE;
+#endif
+
+    (void)name;
+
+    return 0;
+}
+
+/* Free the dynamically allocated data.
+ *
+ * p  Pointer to dynamically allocated memory.
+ */
+void wolfSSL_OPENSSL_free(void* p)
+{
+    WOLFSSL_MSG("wolfSSL_OPENSSL_free");
+
+    XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+void *wolfSSL_OPENSSL_malloc(size_t a)
+{
+  return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)
+
+static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
+                         unsigned char* passwd, int passwdSz, byte **cipherInfo)
+{
+    int ret, paddingSz;
+    word32 idx, cipherInfoSz;
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info = NULL;
+#else
+    EncryptedInfo  info[1];
+#endif
+
+    WOLFSSL_ENTER("EncryptDerKey");
+
+    if (der == NULL || derSz == NULL || cipher == NULL ||
+        passwd == NULL || cipherInfo == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
+    if (info == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+
+    /* set the cipher name on info */
+    XSTRNCPY(info->name, cipher, NAME_SZ-1);
+    info->name[NAME_SZ-1] = '\0'; /* null term */
+
+    ret = wc_EncryptedInfoGet(info, info->name);
+    if (ret != 0) {
+        WOLFSSL_MSG("unsupported cipher");
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+    #endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Generate a random salt */
+    if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("generate iv failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* add the padding before encryption */
+    paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz);
+    if (paddingSz == 0)
+        paddingSz = info->ivSz;
+    XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz);
+    (*derSz) += paddingSz;
+
+    /* encrypt buffer */
+    if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) {
+        WOLFSSL_MSG("encrypt key failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create cipher info : 'cipher_name,Salt(hex)' */
+    cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2);
+    *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL,
+                                DYNAMIC_TYPE_STRING);
+    if (*cipherInfo == NULL) {
+        WOLFSSL_MSG("malloc failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+        return WOLFSSL_FAILURE;
+    }
+    XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz);
+    XSTRNCAT((char*)*cipherInfo, ",", 1);
+
+    idx = (word32)XSTRLEN((char*)*cipherInfo);
+    cipherInfoSz -= idx;
+    ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+    if (ret != 0) {
+        WOLFSSL_MSG("Base16_Encode failed");
+        XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */
+
+#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
+/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO
+ *
+ * bio    the WOLFSSL_BIO to write to
+ * key    the WOLFSSL_RSA key to write out
+ * cipher cipher used
+ * passwd password string if used
+ * len    length of password string
+ * cb     password callback to use
+ * arg    null terminated string for passphrase
+ */
+int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key,
+                                        const WOLFSSL_EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg)
+{
+    int ret;
+    WOLFSSL_EVP_PKEY* pkey;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
+
+
+    pkey = wolfSSL_PKEY_new_ex(bio->heap);
+    if (pkey == NULL) {
+        WOLFSSL_MSG("wolfSSL_PKEY_new_ex failed");
+        return SSL_FAILURE;
+    }
+
+    pkey->type   = EVP_PKEY_RSA;
+    pkey->rsa    = key;
+    pkey->ownRsa = 0;
+#ifdef WOLFSSL_KEY_GEN
+    /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */
+    {
+        int derMax;
+        int derSz;
+        byte* derBuf;
+
+        /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
+         *  informations
+         */
+        derMax = 5 * wolfSSL_RSA_size(key) + AES_BLOCK_SIZE;
+
+        derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (derBuf == NULL) {
+            WOLFSSL_MSG("malloc failed");
+            wolfSSL_EVP_PKEY_free(pkey);
+            return SSL_FAILURE;
+        }
+
+        /* Key to DER */
+        derSz = wc_RsaKeyToDer((RsaKey*)key->internal, derBuf, derMax);
+        if (derSz < 0) {
+            WOLFSSL_MSG("wc_RsaKeyToDer failed");
+            XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            wolfSSL_EVP_PKEY_free(pkey);
+            return SSL_FAILURE;
+        }
+
+        pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap,
+                DYNAMIC_TYPE_TMP_BUFFER);
+        if (pkey->pkey.ptr == NULL) {
+            WOLFSSL_MSG("key malloc failed");
+            XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            wolfSSL_EVP_PKEY_free(pkey);
+            return SSL_FAILURE;
+        }
+        pkey->pkey_sz = derSz;
+        XMEMCPY(pkey->pkey.ptr, derBuf, derSz);
+        XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+    ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
+                                        cb, arg);
+
+    wolfSSL_EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+
+int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
+                                        const WOLFSSL_EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int len,
+                                        pem_password_cb* cb, void* arg)
+{
+    byte* keyDer;
+    int pemSz;
+    int type;
+    int ret;
+    byte* tmp;
+
+    (void)cipher;
+    (void)passwd;
+    (void)len;
+    (void)cb;
+    (void)arg;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
+
+    if (bio == NULL || key == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    keyDer = (byte*)key->pkey.ptr;
+
+    switch (key->type) {
+        case EVP_PKEY_RSA:
+            type = PRIVATEKEY_TYPE;
+            break;
+
+#ifndef NO_DSA
+        case EVP_PKEY_DSA:
+            type = DSA_PRIVATEKEY_TYPE;
+            break;
+#endif
+
+        case EVP_PKEY_EC:
+            type = ECC_PRIVATEKEY_TYPE;
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown Key type!");
+            type = PRIVATEKEY_TYPE;
+    }
+
+    pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type);
+    if (pemSz < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz);
+        return WOLFSSL_FAILURE;
+    }
+    tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (tmp == NULL) {
+        return MEMORY_E;
+    }
+
+    ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz,
+                                NULL, type);
+    if (ret < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret);
+        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        return SSL_FAILURE;
+    }
+
+    ret = wolfSSL_BIO_write(bio, tmp, pemSz);
+    XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    if (ret != pemSz) {
+        WOLFSSL_MSG("Unable to write full PEM to BIO");
+        return SSL_FAILURE;
+    }
+
+    return SSL_SUCCESS;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
+    (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int passwdSz,
+                                        unsigned char **pem, int *plen)
+{
+    byte *derBuf, *tmp, *cipherInfo = NULL;
+    int  der_max_len = 0, derSz = 0;
+    const int type = PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
+
+    if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (rsa->inSet == 0) {
+        WOLFSSL_MSG("No RSA internal set, do it");
+
+        if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
+     *  informations
+     */
+    der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_RsaKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else {
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey");
+
+    if (fp == NULL || rsa == NULL || rsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("RSA private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */
+
+
+#ifdef HAVE_ECC
+
+/* EC_POINT Openssl -> WolfSSL */
+static int SetECPointInternal(WOLFSSL_EC_POINT *p)
+{
+    ecc_point* point;
+    WOLFSSL_ENTER("SetECPointInternal");
+
+    if (p == NULL || p->internal == NULL) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    point = (ecc_point*)p->internal;
+
+    if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point X error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Y error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Z error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    p->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA_X509_SMALL)
+
+/* EC_POINT WolfSSL -> OpenSSL */
+static int SetECPointExternal(WOLFSSL_EC_POINT *p)
+{
+    ecc_point* point;
+
+    WOLFSSL_ENTER("SetECPointExternal");
+
+    if (p == NULL || p->internal == NULL) {
+        WOLFSSL_MSG("ECPoint NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    point = (ecc_point*)p->internal;
+
+    if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point X error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Y error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("ecc point Z error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    p->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+/* EC_KEY wolfSSL -> OpenSSL */
+static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
+{
+    ecc_key* key;
+
+    WOLFSSL_ENTER("SetECKeyExternal");
+
+    if (eckey == NULL || eckey->internal == NULL) {
+        WOLFSSL_MSG("ec key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (ecc_key*)eckey->internal;
+
+    /* set group (OID, nid and idx) */
+    eckey->group->curve_oid = ecc_sets[key->idx].oidSum;
+    eckey->group->curve_nid = ecc_sets[key->idx].id;
+    eckey->group->curve_idx = key->idx;
+
+    if (eckey->pub_key->internal != NULL) {
+        /* set the internal public key */
+        if (wc_ecc_copy_point(&key->pubkey,
+                             (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
+            WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* set the external pubkey (point) */
+        if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    /* set the external privkey */
+    if (key->type == ECC_PRIVATEKEY) {
+        if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec priv key error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    eckey->exSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC && OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+/* EC_KEY Openssl -> WolfSSL */
+static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
+{
+    ecc_key* key;
+
+    WOLFSSL_ENTER("SetECKeyInternal");
+
+    if (eckey == NULL || eckey->internal == NULL) {
+        WOLFSSL_MSG("ec key NULL error");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key = (ecc_key*)eckey->internal;
+
+    /* validate group */
+    if ((eckey->group->curve_idx < 0) ||
+        (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
+        WOLFSSL_MSG("invalid curve idx");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set group (idx of curve and corresponding domain parameters) */
+    key->idx = eckey->group->curve_idx;
+    key->dp = &ecc_sets[key->idx];
+
+    /* set pubkey (point) */
+    if (eckey->pub_key != NULL) {
+        if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec key pub error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* public key */
+        key->type = ECC_PUBLICKEY;
+    }
+
+    /* set privkey */
+    if (eckey->priv_key != NULL) {
+        if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("ec key priv error");
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+        /* private key */
+        key->type = ECC_PRIVATEKEY;
+    }
+
+    eckey->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
+        return NULL;
+    }
+
+    return key->pub_key;
+}
+
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments");
+        return NULL;
+    }
+
+    return key->group;
+}
+
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+                                   const WOLFSSL_BIGNUM *priv_key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
+
+    if (key == NULL || priv_key == NULL) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* free key if previously set */
+    if (key->priv_key != NULL)
+        wolfSSL_BN_free(key->priv_key);
+
+    key->priv_key = wolfSSL_BN_dup(priv_key);
+    if (key->priv_key == NULL) {
+        WOLFSSL_MSG("key ecc priv key NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        wolfSSL_BN_free(key->priv_key);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
+
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
+        return NULL;
+    }
+
+    return key->priv_key;
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
+{
+    WOLFSSL_EC_KEY *key;
+    int x;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
+
+    key = wolfSSL_EC_KEY_new();
+    if (key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
+        return NULL;
+    }
+
+    /* set the nid of the curve */
+    key->group->curve_nid = nid;
+
+    /* search and set the corresponding internal curve idx */
+    for (x = 0; ecc_sets[x].size != 0; x++)
+        if (ecc_sets[x].id == key->group->curve_nid) {
+            key->group->curve_idx = x;
+            key->group->curve_oid = ecc_sets[x].oidSum;
+            break;
+        }
+
+    return key;
+}
+
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key)
+{
+    if (key) {
+        key->group    = NULL;
+        key->pub_key  = NULL;
+        key->priv_key = NULL;
+        key->internal = NULL;
+        key->inSet    = 0;
+        key->exSet    = 0;
+    }
+}
+
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
+{
+    WOLFSSL_EC_KEY *external;
+    ecc_key* key;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
+
+    external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL,
+                                        DYNAMIC_TYPE_ECC);
+    if (external == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
+        return NULL;
+    }
+    XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY));
+
+    InitwolfSSL_ECKey(external);
+
+    external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
+                                           DYNAMIC_TYPE_ECC);
+    if (external->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
+        wolfSSL_EC_KEY_free(external);
+        return NULL;
+    }
+    XMEMSET(external->internal, 0, sizeof(ecc_key));
+
+    wc_ecc_init((ecc_key*)external->internal);
+
+    /* public key */
+    external->pub_key = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT),
+                                                   NULL, DYNAMIC_TYPE_ECC);
+    if (external->pub_key == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_POINT failure");
+        wolfSSL_EC_KEY_free(external);
+        return NULL;
+    }
+    XMEMSET(external->pub_key, 0, sizeof(WOLFSSL_EC_POINT));
+
+    key = (ecc_key*)external->internal;
+    external->pub_key->internal = wc_ecc_new_point();
+    if (wc_ecc_copy_point((ecc_point*)&key->pubkey,
+                (ecc_point*)external->pub_key->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_copy_point failure");
+        wolfSSL_EC_KEY_free(external);
+        return NULL;
+    }
+
+    /* curve group */
+    external->group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+                                                 DYNAMIC_TYPE_ECC);
+    if (external->group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
+        wolfSSL_EC_KEY_free(external);
+        return NULL;
+    }
+    XMEMSET(external->group, 0, sizeof(WOLFSSL_EC_GROUP));
+
+    /* private key */
+    external->priv_key = wolfSSL_BN_new();
+    if (external->priv_key == NULL) {
+        WOLFSSL_MSG("wolfSSL_BN_new failure");
+        wolfSSL_EC_KEY_free(external);
+        return NULL;
+    }
+
+    return external;
+}
+
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
+
+    if (key != NULL) {
+        if (key->internal != NULL) {
+            wc_ecc_free((ecc_key*)key->internal);
+            XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC);
+        }
+        wolfSSL_BN_free(key->priv_key);
+        wolfSSL_EC_POINT_free(key->pub_key);
+        wolfSSL_EC_GROUP_free(key->group);
+        InitwolfSSL_ECKey(key); /* set back to NULLs for safety */
+
+        XFREE(key, NULL, DYNAMIC_TYPE_ECC);
+        key = NULL;
+    }
+}
+#endif /* HAVE_ECC && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
+{
+    (void)key;
+    (void)group;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
+    WOLFSSL_STUB("EC_KEY_set_group");
+
+    return -1;
+}
+#endif
+
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
+{
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
+
+    if (key == NULL || key->internal == NULL ||
+        key->group == NULL || key->group->curve_idx < 0) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
+        return 0;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return 0;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+        return 0;
+    }
+
+    if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal,
+                                        key->group->curve_nid) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+        return 0;
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
+{
+    (void)key;
+    (void)asn1_flag;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
+    WOLFSSL_STUB("EC_KEY_set_asn1_flag");
+}
+#endif
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+                                  const WOLFSSL_EC_POINT *pub)
+{
+    ecc_point *pub_p, *key_p;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
+
+    if (key == NULL || key->internal == NULL ||
+        pub == NULL || pub->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (key->inSet == 0) {
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (pub->inSet == 0) {
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    pub_p = (ecc_point*)pub->internal;
+    key_p = (ecc_point*)key->pub_key->internal;
+
+    /* create new point if required */
+    if (key_p == NULL)
+        key_p = wc_ecc_new_point();
+
+    if (key_p == NULL) {
+        WOLFSSL_MSG("key ecc point NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
+        WOLFSSL_MSG("ecc_copy_point failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyInternal failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    wolfSSL_EC_POINT_dump("pub", pub);
+    wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
+
+    return WOLFSSL_SUCCESS;
+}
+/* End EC_KEY */
+
+void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
+{
+#if defined(DEBUG_WOLFSSL)
+    char *num;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
+
+    if (p == NULL) {
+        printf("%s = NULL", msg);
+        return;
+    }
+
+    printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet);
+    num = wolfSSL_BN_bn2hex(p->X);
+    printf("\tX = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+    num = wolfSSL_BN_bn2hex(p->Y);
+    printf("\tY = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+    num = wolfSSL_BN_bn2hex(p->Z);
+    printf("\tZ = %s\n", num);
+    XFREE(num, NULL, DYNAMIC_TYPE_ECC);
+#else
+    (void)msg;
+    (void)p;
+#endif
+}
+
+/* Start EC_GROUP */
+
+/* return code compliant with OpenSSL :
+ *   0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+                         WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
+
+    if (a == NULL || b == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* ok */
+    if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid))
+        return 0;
+
+    /* ko */
+    return 1;
+}
+
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+
+    XFREE(group, NULL, DYNAMIC_TYPE_ECC);
+    group = NULL;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+{
+    (void)group;
+    (void)flag;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
+    WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
+}
+#endif
+
+WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+{
+    WOLFSSL_EC_GROUP *g;
+    int x;
+
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+
+    /* curve group */
+    g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+                                    DYNAMIC_TYPE_ECC);
+    if (g == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
+        return NULL;
+    }
+    XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP));
+
+    /* set the nid of the curve */
+    g->curve_nid = nid;
+
+    /* search and set the corresponding internal curve idx */
+    for (x = 0; ecc_sets[x].size != 0; x++)
+        if (ecc_sets[x].id == g->curve_nid) {
+            g->curve_idx = x;
+            g->curve_oid = ecc_sets[x].oidSum;
+            break;
+        }
+
+    return g;
+}
+
+/* return code compliant with OpenSSL :
+ *   the curve nid if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    return group->curve_nid;
+}
+
+/* return code compliant with OpenSSL :
+ *   the degree of the curve if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+
+    if (group == NULL || group->curve_idx < 0) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch(group->curve_nid) {
+        case NID_secp112r1:
+        case NID_secp112r2:
+            return 112;
+        case NID_secp128r1:
+        case NID_secp128r2:
+            return 128;
+        case NID_secp160k1:
+        case NID_secp160r1:
+        case NID_secp160r2:
+        case NID_brainpoolP160r1:
+            return 160;
+        case NID_secp192k1:
+        case NID_brainpoolP192r1:
+        case NID_X9_62_prime192v1:
+            return 192;
+        case NID_secp224k1:
+        case NID_secp224r1:
+        case NID_brainpoolP224r1:
+            return 224;
+        case NID_secp256k1:
+        case NID_brainpoolP256r1:
+        case NID_X9_62_prime256v1:
+            return 256;
+        case NID_brainpoolP320r1:
+            return 320;
+        case NID_secp384r1:
+        case NID_brainpoolP384r1:
+            return 384;
+        case NID_secp521r1:
+        case NID_brainpoolP512r1:
+            return 521;
+        default:
+            return WOLFSSL_FAILURE;
+    }
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+                               WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    if (group == NULL || order == NULL || order->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_init((mp_int*)order->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (mp_read_radix((mp_int*)order->internal,
+                  ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) {
+        WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
+        mp_clear((mp_int*)order->internal);
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+/* End EC_GROUP */
+
+/* Start EC_POINT */
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
+                        const WOLFSSL_EC_POINT *p,
+                        unsigned char *out, unsigned int *len)
+{
+    int err;
+
+    WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
+
+    if (group == NULL || p == NULL || len == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (p->inSet == 0) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    if (out != NULL) {
+        wolfSSL_EC_POINT_dump("i2d p", p);
+    }
+
+    err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal,
+                                  out, len);
+    if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
+                        const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
+
+    if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_ecc_import_point_der(in, len, group->curve_idx,
+                                (ecc_point*)p->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_import_point_der failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (p->exSet == 0) {
+        WOLFSSL_MSG("No ECPoint external set, do it");
+
+        if (SetECPointExternal(p) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointExternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    wolfSSL_EC_POINT_dump("d2i p", p);
+
+    return WOLFSSL_SUCCESS;
+}
+
+WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
+{
+    WOLFSSL_EC_POINT *p;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+
+    if (group == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
+        return NULL;
+    }
+
+    p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
+                                    DYNAMIC_TYPE_ECC);
+    if (p == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
+        return NULL;
+    }
+    XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT));
+
+    p->internal = wc_ecc_new_point();
+    if (p->internal == NULL) {
+        WOLFSSL_MSG("ecc_new_point failure");
+        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+        return NULL;
+    }
+
+    return p;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group,
+                                                const WOLFSSL_EC_POINT *point,
+                                                WOLFSSL_BIGNUM *x,
+                                                WOLFSSL_BIGNUM *y,
+                                                WOLFSSL_BN_CTX *ctx)
+{
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
+
+    if (group == NULL || point == NULL || point->internal == NULL ||
+        x == NULL || y == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (point->inSet == 0) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    BN_copy(x, point->X);
+    BN_copy(y, point->Y);
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef WOLFSSL_ATECC508A
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+                         const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q,
+                         const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx)
+{
+    mp_int a, prime;
+    int ret;
+
+    (void)ctx;
+    (void)n;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
+
+    if (group == NULL || r == NULL || r->internal == NULL ||
+        q == NULL || q->internal == NULL || m == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (q->inSet == 0) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal q failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* read the curve prime and a */
+    if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) {
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX);
+    if (ret == MP_OKAY) {
+        ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX);
+    }
+
+    /* r = q * m % prime */
+    if (ret == MP_OKAY) {
+        ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
+                      (ecc_point*)r->internal, &a, &prime, 1);
+    }
+
+    mp_clear(&a);
+    mp_clear(&prime);
+
+    if (ret == MP_OKAY) {
+        r->inSet = 1; /* mark internal set */
+
+        /* set the external value for the computed point */
+        ret = SetECPointExternal(r);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal r failed");
+        }
+    }
+    else {
+        ret = WOLFSSL_FAILURE;
+    }
+
+    return ret;
+}
+#endif
+
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+
+    wolfSSL_EC_POINT_free(p);
+}
+
+/* return code compliant with OpenSSL :
+ *   0 if equal, 1 if not and -1 in case of error
+ */
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+                         const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
+                         WOLFSSL_BN_CTX *ctx)
+{
+    int ret;
+
+    (void)ctx;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
+
+    if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
+        b->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal);
+    if (ret == MP_EQ)
+        return 0;
+    else if (ret == MP_LT || ret == MP_GT)
+        return 1;
+
+    return WOLFSSL_FATAL_ERROR;
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
+{
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
+
+    if (p != NULL) {
+        if (p->internal != NULL) {
+            wc_ecc_del_point((ecc_point*)p->internal);
+            p->internal = NULL;
+        }
+
+        wolfSSL_BN_free(p->X);
+        wolfSSL_BN_free(p->Y);
+        wolfSSL_BN_free(p->Z);
+        p->X = NULL;
+        p->Y = NULL;
+        p->Z = NULL;
+        p->inSet = p->exSet = 0;
+
+        XFREE(p, NULL, DYNAMIC_TYPE_ECC);
+        p = NULL;
+    }
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_ECC
+/* return code compliant with OpenSSL :
+ *   1 if point at infinity, 0 else
+ */
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+                                    const WOLFSSL_EC_POINT *point)
+{
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
+
+    if (group == NULL || point == NULL || point->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
+        return WOLFSSL_FAILURE;
+    }
+    if (point->inSet == 0) {
+        WOLFSSL_MSG("No ECPoint internal set, do it");
+
+        if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECPointInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
+    if (ret <= 0) {
+        WOLFSSL_MSG("ecc_point_is_at_infinity failure");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* End EC_POINT */
+
+/* Start ECDSA_SIG */
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
+{
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
+
+    if (sig) {
+        wolfSSL_BN_free(sig->r);
+        wolfSSL_BN_free(sig->s);
+
+        XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
+    }
+}
+
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
+{
+    WOLFSSL_ECDSA_SIG *sig;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
+
+    sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
+                                       DYNAMIC_TYPE_ECC);
+    if (sig == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
+        return NULL;
+    }
+
+    sig->s = NULL;
+    sig->r = wolfSSL_BN_new();
+    if (sig->r == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
+        wolfSSL_ECDSA_SIG_free(sig);
+        return NULL;
+    }
+
+    sig->s = wolfSSL_BN_new();
+    if (sig->s == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
+        wolfSSL_ECDSA_SIG_free(sig);
+        return NULL;
+    }
+
+    return sig;
+}
+
+/* return signature structure on success, NULL otherwise */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
+                                         WOLFSSL_EC_KEY *key)
+{
+    WOLFSSL_ECDSA_SIG *sig = NULL;
+    int     initTmpRng = 0;
+    WC_RNG* rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG* tmpRNG = NULL;
+#else
+    WC_RNG  tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
+
+    if (d == NULL || key == NULL || key->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
+        return NULL;
+    }
+
+    /* set internal key if not done */
+    if (key->inSet == 0)
+    {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
+
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
+            return NULL;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return NULL;
+#endif
+
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        mp_int sig_r, sig_s;
+
+        if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) {
+            if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal,
+                                    &sig_r, &sig_s) != MP_OKAY) {
+                WOLFSSL_MSG("wc_ecc_sign_hash_ex failed");
+            }
+            else {
+                /* put signature blob in ECDSA structure */
+                sig = wolfSSL_ECDSA_SIG_new();
+                if (sig == NULL)
+                    WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed");
+                else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){
+                    WOLFSSL_MSG("ecdsa r key error");
+                    wolfSSL_ECDSA_SIG_free(sig);
+                    sig = NULL;
+                }
+                else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){
+                    WOLFSSL_MSG("ecdsa s key error");
+                    wolfSSL_ECDSA_SIG_free(sig);
+                    sig = NULL;
+                }
+
+            }
+            mp_free(&sig_r);
+            mp_free(&sig_s);
+        }
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return sig;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 for a valid signature, 0 for an invalid signature and -1 on error
+ */
+int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
+                            const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+{
+    int check_sign = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
+
+    if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
+        WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set internal key if not done */
+    if (key->inSet == 0)
+    {
+        WOLFSSL_MSG("No EC key internal set, do it");
+
+        if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
+                              (mp_int*)sig->s->internal, d, dlen, &check_sign,
+                              (ecc_key *)key->internal) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_verify_hash failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+    else if (check_sign == 0) {
+        WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+/* End ECDSA_SIG */
+
+/* Start ECDH */
+/* return code compliant with OpenSSL :
+ *   length of computed key if success, -1 if error
+ */
+int wolfSSL_ECDH_compute_key(void *out, size_t outlen,
+                             const WOLFSSL_EC_POINT *pub_key,
+                             WOLFSSL_EC_KEY *ecdh,
+                             void *(*KDF) (const void *in, size_t inlen,
+                                           void *out, size_t *outlen))
+{
+    word32 len;
+    (void)KDF;
+
+    (void)KDF;
+
+    WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
+
+    if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
+        ecdh == NULL || ecdh->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    /* set internal key if not done */
+    if (ecdh->inSet == 0)
+    {
+        WOLFSSL_MSG("No EC key internal set, do it");
+
+        if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetECKeyInternal failed");
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    len = (word32)outlen;
+
+    if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal,
+                                 (ecc_point*)pub_key->internal,
+                                 (byte *)out, &len) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ecc_shared_secret failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    return len;
+}
+/* End ECDH */
+
+#if !defined(NO_FILESYSTEM)
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_EC_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#endif /* NO_FILESYSTEM */
+
+#if defined(WOLFSSL_KEY_GEN)
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       pem_password_cb* cb, void* arg)
+{
+    (void)bio;
+    (void)ecc;
+    (void)cipher;
+    (void)passwd;
+    (void)len;
+    (void)cb;
+    (void)arg;
+    WOLFSSL_STUB("PEM_write_bio_ECPrivateKey");
+    WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int passwdSz,
+                                       unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    byte *derBuf, *tmp, *cipherInfo = NULL;
+    int  der_max_len = 0, derSz = 0;
+    const int type = ECC_PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
+
+    if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (ecc->inSet == 0) {
+        WOLFSSL_MSG("No ECC internal set, do it");
+
+        if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* 4 > size of pub, priv + ASN.1 additional informations
+     */
+    der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else { /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)ecc;
+    (void)cipher;
+    (void)passwd;
+    (void)passwdSz;
+    (void)pem;
+    (void)plen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc,
+                                   const EVP_CIPHER *enc,
+                                   unsigned char *kstr, int klen,
+                                   pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
+
+    if (fp == NULL || ecc == NULL || ecc->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("ECC private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+
+#endif /* HAVE_ECC */
+
+
+#ifndef NO_DSA
+
+#if defined(WOLFSSL_KEY_GEN)
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa,
+                                       const EVP_CIPHER* cipher,
+                                       unsigned char* passwd, int len,
+                                       pem_password_cb* cb, void* arg)
+{
+    (void)bio;
+    (void)dsa;
+    (void)cipher;
+    (void)passwd;
+    (void)len;
+    (void)cb;
+    (void)arg;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
+                                        const EVP_CIPHER* cipher,
+                                        unsigned char* passwd, int passwdSz,
+                                        unsigned char **pem, int *plen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    byte *derBuf, *tmp, *cipherInfo = NULL;
+    int  der_max_len = 0, derSz = 0;
+    const int type = DSA_PRIVATEKEY_TYPE;
+    const char* header = NULL;
+    const char* footer = NULL;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey");
+
+    if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
+        return WOLFSSL_FAILURE;
+
+    if (dsa->inSet == 0) {
+        WOLFSSL_MSG("No DSA internal set, do it");
+
+        if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetDsaInternal failed");
+            return WOLFSSL_FAILURE;
+        }
+    }
+
+    /* 4 > size of pub, priv, p, q, g + ASN.1 additional informations
+     */
+    der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE;
+
+    derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* Key to DER */
+    derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len);
+    if (derSz < 0) {
+        WOLFSSL_MSG("wc_DsaKeyToDer failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* encrypt DER buffer if required */
+    if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
+        int ret;
+
+        ret = EncryptDerKey(derBuf, &derSz, cipher,
+                            passwd, passwdSz, &cipherInfo);
+        if (ret != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("EncryptDerKey failed");
+            XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+            return ret;
+        }
+
+        /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE;
+    }
+    else { /* tmp buffer with a max size */
+        *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 +
+            (int)XSTRLEN(footer) + 1;
+    }
+
+    tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM);
+    if (tmp == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* DER to PEM */
+    *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type);
+    if (*plen <= 0) {
+        WOLFSSL_MSG("wc_DerToPemEx failed");
+        XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        if (cipherInfo != NULL)
+            XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+    if (cipherInfo != NULL)
+        XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+
+    *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY);
+    if (*pem == NULL) {
+        WOLFSSL_MSG("malloc failed");
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XMEMSET(*pem, 0, (*plen)+1);
+
+    if (XMEMCPY(*pem, tmp, *plen) == NULL) {
+        WOLFSSL_MSG("XMEMCPY failed");
+        XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+        XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+        return WOLFSSL_FAILURE;
+    }
+    XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)dsa;
+    (void)cipher;
+    (void)passwd;
+    (void)passwdSz;
+    (void)pem;
+    (void)plen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa,
+                                    const EVP_CIPHER *enc,
+                                    unsigned char *kstr, int klen,
+                                    pem_password_cb *cb, void *u)
+{
+    byte *pem;
+    int  plen, ret;
+
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey");
+
+    if (fp == NULL || dsa == NULL || dsa->internal == NULL) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    ret = (int)XFWRITE(pem, plen, 1, fp);
+    if (ret != 1) {
+        WOLFSSL_MSG("DSA private key file write failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+    return WOLFSSL_SUCCESS;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* defined(WOLFSSL_KEY_GEN) */
+
+#ifndef NO_FILESYSTEM
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_DSA_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+#endif /* NO_FILESYSTEM */
+
+#endif /* #ifndef NO_DSA */
+
+
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
+                    WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* pass)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    EncryptedInfo* info;
+#else
+    EncryptedInfo info[1];
+#endif /* WOLFSSL_SMALL_STACK */
+    pem_password_cb* localCb = cb;
+    DerBuffer* der = NULL;
+
+    char* mem = NULL;
+    int memSz;
+    int ret;
+    int eccFlag = 0;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
+
+    if (bio == NULL) {
+        return pkey;
+    }
+
+    if ((ret = wolfSSL_BIO_pending(bio)) > 0) {
+        memSz = ret;
+        mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        if (mem == NULL) {
+            WOLFSSL_MSG("Memory error");
+            return NULL;
+        }
+
+        if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", ret);
+            XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            return NULL;
+        }
+    }
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        int sz  = 100; /* read from file by 100 byte chuncks */
+        int idx = 0;
+        char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL);
+
+        memSz = 0;
+        if (tmp == NULL) {
+            WOLFSSL_MSG("Memory error");
+            return NULL;
+        }
+
+        while ((sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) {
+            if (memSz + sz < 0) {
+                /* sanity check */
+                break;
+            }
+            mem = (char*)XREALLOC(mem, memSz + sz, bio->heap,
+                    DYNAMIC_TYPE_OPENSSL);
+            if (mem == NULL) {
+                WOLFSSL_MSG("Memory error");
+                XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+                return NULL;
+            }
+            XMEMCPY(mem + idx, tmp, sz);
+            memSz += sz;
+            idx   += sz;
+            sz = 100; /* read another 100 byte chunck from file */
+        }
+        XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        if (memSz <= 0) {
+            WOLFSSL_MSG("No data to read from bio");
+            if (mem != NULL) {
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+            }
+            return NULL;
+        }
+    }
+    else {
+        WOLFSSL_MSG("No data to read from bio");
+        return NULL;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+                                   DYNAMIC_TYPE_TMP_BUFFER);
+    if (info == NULL) {
+        WOLFSSL_MSG("Error getting memory for EncryptedInfo structure");
+        XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+        return NULL;
+    }
+#endif
+
+    XMEMSET(info, 0, sizeof(EncryptedInfo));
+    info->passwd_cb       = localCb;
+    info->passwd_userdata = pass;
+    ret = PemToDer((const unsigned char*)mem, memSz, PRIVATEKEY_TYPE, &der,
+        NULL, info, &eccFlag);
+
+    if (ret < 0) {
+        WOLFSSL_MSG("Bad Pem To Der");
+    }
+    else {
+        int type;
+        const unsigned char* ptr = der->buffer;
+
+        /* write left over data back to bio */
+        if ((memSz - (int)info->consumed) > 0 &&
+                bio->type != WOLFSSL_BIO_FILE) {
+            if (wolfSSL_BIO_write(bio, mem + (int)info->consumed,
+                                   memSz - (int)info->consumed) <= 0) {
+                WOLFSSL_MSG("Unable to advance bio read pointer");
+            }
+        }
+
+        if (eccFlag) {
+            type = EVP_PKEY_EC;
+        }
+        else {
+            type = EVP_PKEY_RSA;
+        }
+
+        /* handle case where reuse is attempted */
+        if (key != NULL && *key != NULL) {
+            pkey = *key;
+        }
+
+        wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length);
+        if (pkey == NULL) {
+            WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+    FreeDer(&der);
+
+    if (key != NULL) {
+        *key = pkey;
+    }
+
+    return pkey;
+}
+
+
+#ifndef NO_RSA
+/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
+ * the results to be an RSA key.
+ *
+ * bio  structure to read RSA private key from
+ * rsa  if not null is then set to the result
+ * cb   password callback for reading PEM
+ * pass password string
+ *
+ * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail
+ */
+WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
+        WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass)
+{
+    WOLFSSL_EVP_PKEY* pkey;
+    WOLFSSL_RSA* local;
+
+    pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
+    if (pkey == NULL) {
+        return NULL;
+    }
+
+    /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the
+     * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE
+     * to avoid having it free'd */
+    pkey->ownRsa = 0;
+    local = pkey->rsa;
+    if (rsa != NULL) {
+        *rsa = local;
+    }
+
+    wolfSSL_EVP_PKEY_free(pkey);
+    return local;
+}
+#endif /* !NO_RSA */
+
+
+/* return of pkey->type which will be EVP_PKEY_RSA for example.
+ *
+ * type  type of EVP_PKEY
+ *
+ * returns type or if type is not found then NID_undef
+ */
+int wolfSSL_EVP_PKEY_type(int type)
+{
+    WOLFSSL_MSG("wolfSSL_EVP_PKEY_type");
+
+    switch (type) {
+    #ifdef OPENSSL_EXTRA
+        case EVP_PKEY_RSA:
+            return EVP_PKEY_RSA;
+        case EVP_PKEY_DSA:
+            return EVP_PKEY_DSA;
+        case EVP_PKEY_EC:
+            return EVP_PKEY_EC;
+    #endif
+        default:
+            return NID_undef;
+    }
+}
+
+
+int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey)
+{
+    return EVP_PKEY_type(pkey->type);
+}
+
+
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
+                                          pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+
+    WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented");
+
+    return NULL;
+}
+#endif /* NO_FILESYSTEM */
+
+#ifndef NO_RSA
+
+#if !defined(NO_FILESYSTEM)
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x,
+                                           pem_password_cb *cb, void *u)
+{
+    (void)fp;
+    (void)x;
+    (void)cb;
+    (void)u;
+    WOLFSSL_STUB("PEM_read_RSAPublicKey");
+    WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented");
+
+    return NULL;
+}
+#endif
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_RSAPublicKey");
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+/* return code compliant with OpenSSL :
+ *   1 if success, 0 if error
+ */
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x)
+{
+    (void)fp;
+    (void)x;
+    WOLFSSL_STUB("PEM_write_RSA_PUBKEY");
+    WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#endif /* NO_FILESYSTEM */
+
+WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp, long len)
+{
+    WOLFSSL_RSA *rsa = NULL;
+
+    WOLFSSL_ENTER("d2i_RSAPublicKey");
+
+    if(pp == NULL){
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    if((rsa = wolfSSL_RSA_new()) == NULL){
+        WOLFSSL_MSG("RSA_new failed");
+        return NULL;
+    }
+
+    if(wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC)
+                                                     != WOLFSSL_SUCCESS){
+        WOLFSSL_MSG("RSA_LoadDer failed");
+        wolfSSL_RSA_free(rsa);
+        rsa = NULL;
+        return NULL;
+    }
+    if(r != NULL)
+        *r = rsa;
+    return rsa;
+}
+
+/* Converts an rsa private key from der format to an rsa structure.
+Returns pointer to the rsa structure on succcess and NULL if error. */
+WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r, 
+                                       const unsigned char **derBuf, long derSz)
+{
+    WOLFSSL_RSA *rsa = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey");
+
+    /* check for bad functions arguments */
+    if (derBuf == NULL) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    if ((rsa = wolfSSL_RSA_new()) == NULL) {
+        WOLFSSL_MSG("RSA_new failed");
+        return NULL;
+    }
+
+    if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz, 
+                                 WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("RSA_LoadDer failed");
+        wolfSSL_RSA_free(rsa);
+        rsa = NULL;
+        return NULL;
+    }
+    if(r != NULL)
+        *r = rsa;
+
+    return rsa;
+}
+
+#if !defined(HAVE_FAST_RSA)
+#if defined(WOLFSSL_KEY_GEN)
+
+/* Converts an internal rsa structure to der format.
+Returns size of der on success and WOLFSSL_FAILURE if error */
+int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
+{
+    byte* der = NULL;
+    int derMax;
+    int ret;
+    int i;
+
+    WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
+
+    /* check for bad functions arguments */
+    if ((rsa == NULL) || (pp == NULL)) {
+        WOLFSSL_MSG("Bad Function Arguments");
+        return BAD_FUNC_ARG;
+    }
+
+    if (rsa->inSet == 0) {
+        if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("SetRsaInternal() Failed");
+            return ret;
+        }
+    }
+
+    /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional
+     *  informations
+     */
+    derMax = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE;
+
+    der = (byte*)XMALLOC(derMax, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (der == NULL) {
+        WOLFSSL_MSG("Malloc failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* RSA key to DER */
+    if ((ret = wc_RsaKeyToDer((RsaKey *)rsa->internal, der, derMax)) < 0) {
+        WOLFSSL_MSG("wc_RsaKeyToDer() failed");
+        XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        der = NULL;
+        return ret;
+    }
+
+    /* ret is the size of the der buffer */
+    for (i = 0; i < ret; i++) {
+        *(*pp + i) = *(der + i);
+    }
+    *pp += ret;
+
+    XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    return ret; /* returns size of der if successful */
+}
+#endif /* WOLFSSL_KEY_GEN */
+
+
+int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp)
+{
+    byte *der;
+    int derLen;
+    int ret;
+
+    WOLFSSL_ENTER("i2d_RSAPublicKey");
+    if ((rsa == NULL) || (pp == NULL))
+        return WOLFSSL_FATAL_ERROR;
+    if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetRsaInternal Failed");
+        return ret;
+    }
+    if ((derLen = RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0)
+        return WOLFSSL_FATAL_ERROR;
+    der = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (der == NULL) {
+        return WOLFSSL_FATAL_ERROR;
+    }
+    if ((ret = wc_RsaKeyToPublicDer((RsaKey *)rsa->internal, der, derLen)) < 0){
+        WOLFSSL_MSG("RsaKeyToPublicDer failed");
+        XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return ret;
+    }
+
+    *pp = der;
+    return ret;
+}
+#endif /* #if !defined(HAVE_FAST_RSA) */
+
+#endif /* !NO_RSA */
+#endif /* OPENSSL_EXTRA */
+
+#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz)
+{
+  return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
+}
+
+
+int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
+                                                     int derSz, int opt)
+{
+
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
+
+    if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+        ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
+    }
+    else {
+        ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz);
+    }
+
+    if (ret < 0) {
+        if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+             WOLFSSL_MSG("RsaPrivateKeyDecode failed");
+        }
+        else {
+             WOLFSSL_MSG("RsaPublicKeyDecode failed");
+        }
+        return SSL_FATAL_ERROR;
+    }
+
+    if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetRsaExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    rsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_RSA */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_DSA
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz)
+{
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_DSA_LoadDer");
+
+    if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz);
+    if (ret < 0) {
+        WOLFSSL_MSG("DsaPrivateKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetDsaExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    dsa->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* NO_DSA */
+
+#ifdef HAVE_ECC
+/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */
+int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key,
+                           const unsigned char* derBuf,  int derSz)
+{
+    word32 idx = 0;
+    int    ret;
+
+    WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
+
+    if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
+        WOLFSSL_MSG("Bad function arguments");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz);
+    if (ret < 0) {
+        WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("SetECKeyExternal failed");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    key->inSet = 1;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_ECC */
+
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl)
+{
+    int isUsing = 0;
+    if (ssl)
+        isUsing = ssl->options.usingAltCertChain;
+    return isUsing;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+
+#ifdef SESSION_CERTS
+
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+/* Get peer's alternate certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
+    if (ssl)
+        return &ssl->session.altChain;
+
+    return 0;
+}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
+
+
+/* Get peer's certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_peer_chain");
+    if (ssl)
+        return &ssl->session.chain;
+
+    return 0;
+}
+
+
+/* Get peer's certificate chain total count */
+int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_count");
+    if (chain)
+        return chain->count;
+
+    return 0;
+}
+
+
+/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
+int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_length");
+    if (chain)
+        return chain->certs[idx].length;
+
+    return 0;
+}
+
+
+/* Get peer's ASN.1 DER certificate at index (idx) */
+byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_chain_cert");
+    if (chain)
+        return chain->certs[idx].buffer;
+
+    return 0;
+}
+
+
+/* Get peer's wolfSSL X509 certificate at index (idx) */
+WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+    int          ret;
+    WOLFSSL_X509* x509 = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_get_chain_X509");
+    if (chain != NULL) {
+    #ifdef WOLFSSL_SMALL_STACK
+        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+                                                       DYNAMIC_TYPE_DCERT);
+        if (cert != NULL)
+    #endif
+        {
+            InitDecodedCert(cert, chain->certs[idx].buffer,
+                                  chain->certs[idx].length, NULL);
+
+            if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) {
+                WOLFSSL_MSG("Failed to parse cert");
+            }
+            else {
+                x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
+                                                             DYNAMIC_TYPE_X509);
+                if (x509 == NULL) {
+                    WOLFSSL_MSG("Failed alloc X509");
+                }
+                else {
+                    InitX509(x509, 1, NULL);
+
+                    if ((ret = CopyDecodedToX509(x509, cert)) != 0) {
+                        WOLFSSL_MSG("Failed to copy decoded");
+                        XFREE(x509, NULL, DYNAMIC_TYPE_X509);
+                        x509 = NULL;
+                    }
+                }
+            }
+
+            FreeDecodedCert(cert);
+        #ifdef WOLFSSL_SMALL_STACK
+            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+        #endif
+        }
+    }
+    (void)ret;
+
+    return x509;
+}
+
+
+/* Get peer's PEM certificate at index (idx), output to buffer if inLen big
+   enough else return error (-1). If buffer is NULL only calculate
+   outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
+int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
+                               unsigned char* buf, int inLen, int* outLen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+    const char* header = NULL;
+    const char* footer = NULL;
+    int headerLen;
+    int footerLen;
+    int i;
+    int err;
+    word32 szNeeded = 0;
+
+    WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
+    if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
+        return BAD_FUNC_ARG;
+
+    err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer);
+    if (err != 0)
+        return err;
+
+    headerLen = (int)XSTRLEN(header);
+    footerLen = (int)XSTRLEN(footer);
+
+    /* Null output buffer return size needed in outLen */
+    if(!buf) {
+        if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length,
+                    NULL, &szNeeded) != LENGTH_ONLY_E)
+            return WOLFSSL_FAILURE;
+        *outLen = szNeeded + headerLen + footerLen;
+        return LENGTH_ONLY_E;
+    }
+
+    /* don't even try if inLen too short */
+    if (inLen < headerLen + footerLen + chain->certs[idx].length)
+        return BAD_FUNC_ARG;
+
+    /* header */
+    if (XMEMCPY(buf, header, headerLen) == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    i = headerLen;
+
+    /* body */
+    *outLen = inLen;  /* input to Base64_Encode */
+    if ( (err = Base64_Encode(chain->certs[idx].buffer,
+                       chain->certs[idx].length, buf + i, (word32*)outLen)) < 0)
+        return err;
+    i += *outLen;
+
+    /* footer */
+    if ( (i + footerLen) > inLen)
+        return BAD_FUNC_ARG;
+    if (XMEMCPY(buf + i, footer, footerLen) == NULL)
+        return WOLFSSL_FATAL_ERROR;
+    *outLen += headerLen + footerLen;
+
+    return WOLFSSL_SUCCESS;
+#else
+    (void)chain;
+    (void)idx;
+    (void)buf;
+    (void)inLen;
+    (void)outLen;
+    return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+
+/* get session ID */
+const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session)
+{
+    WOLFSSL_ENTER("wolfSSL_get_sessionID");
+    if (session)
+        return session->sessionID;
+
+    return NULL;
+}
+
+
+#endif /* SESSION_CERTS */
+
+#ifdef HAVE_FUZZER
+void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
+{
+    if (ssl) {
+        ssl->fuzzerCb  = cbf;
+        ssl->fuzzerCtx = fCtx;
+    }
+}
+#endif
+
+#ifndef NO_CERTS
+#ifdef  HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
+{
+    if (ctx)
+        ctx->EccKeyGenCb = cb;
+}
+void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccKeyGenCtx = ctx;
+}
+void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccKeyGenCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
+{
+    if (ctx)
+        ctx->EccSignCb = cb;
+}
+void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccSignCtx = ctx;
+}
+void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccSignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
+{
+    if (ctx)
+        ctx->EccVerifyCb = cb;
+}
+void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccVerifyCtx = ctx;
+}
+void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccVerifyCtx;
+
+    return NULL;
+}
+
+void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb)
+{
+    if (ctx)
+        ctx->EccSharedSecretCb = cb;
+}
+void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->EccSharedSecretCtx = ctx;
+}
+void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->EccSharedSecretCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
+{
+    if (ctx)
+        ctx->Ed25519SignCb = cb;
+}
+void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed25519SignCtx = ctx;
+}
+void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed25519SignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
+{
+    if (ctx)
+        ctx->Ed25519VerifyCb = cb;
+}
+void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->Ed25519VerifyCtx = ctx;
+}
+void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->Ed25519VerifyCtx;
+
+    return NULL;
+}
+#endif /* HAVE_ED25519 */
+
+#ifdef HAVE_CURVE25519
+void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
+        CallbackX25519KeyGen cb)
+{
+    if (ctx)
+        ctx->X25519KeyGenCb = cb;
+}
+void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X25519KeyGenCtx = ctx;
+}
+void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X25519KeyGenCtx;
+
+    return NULL;
+}
+
+void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
+        CallbackX25519SharedSecret cb)
+{
+    if (ctx)
+        ctx->X25519SharedSecretCb = cb;
+}
+void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->X25519SharedSecretCtx = ctx;
+}
+void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->X25519SharedSecretCtx;
+
+    return NULL;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifndef NO_RSA
+void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
+{
+    if (ctx)
+        ctx->RsaSignCb = cb;
+}
+void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+    if (ctx)
+        ctx->RsaSignCheckCb = cb;
+}
+void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaSignCtx = ctx;
+}
+void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaSignCtx;
+
+    return NULL;
+}
+
+
+void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+    if (ctx)
+        ctx->RsaVerifyCb = cb;
+}
+void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaVerifyCtx;
+
+    return NULL;
+}
+
+#ifdef WC_RSA_PSS
+void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
+{
+    if (ctx)
+        ctx->RsaPssSignCb = cb;
+}
+void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+    if (ctx)
+        ctx->RsaPssSignCheckCb = cb;
+}
+void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaPssSignCtx = ctx;
+}
+void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaPssSignCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+    if (ctx)
+        ctx->RsaPssVerifyCb = cb;
+}
+void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaPssVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaPssVerifyCtx;
+
+    return NULL;
+}
+#endif /* WC_RSA_PSS */
+
+void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
+{
+    if (ctx)
+        ctx->RsaEncCb = cb;
+}
+void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaEncCtx = ctx;
+}
+void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaEncCtx;
+
+    return NULL;
+}
+
+void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
+{
+    if (ctx)
+        ctx->RsaDecCb = cb;
+}
+void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->RsaDecCtx = ctx;
+}
+void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->RsaDecCtx;
+
+    return NULL;
+}
+#endif /* NO_RSA */
+
+#endif /* HAVE_PK_CALLBACKS */
+#endif /* NO_CERTS */
+
+#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
+void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
+{
+    if (ctx)
+        ctx->DhAgreeCb = cb;
+}
+void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
+{
+    if (ssl)
+        ssl->DhAgreeCtx = ctx;
+}
+void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->DhAgreeCtx;
+
+    return NULL;
+}
+#endif /* HAVE_PK_CALLBACKS && !NO_DH */
+
+
+#ifdef WOLFSSL_HAVE_WOLFSCEP
+    /* Used by autoconf to see if wolfSCEP is available */
+    void wolfSSL_wolfSCEP(void) {}
+#endif
+
+
+#ifdef WOLFSSL_HAVE_CERT_SERVICE
+    /* Used by autoconf to see if cert service is available */
+    void wolfSSL_cert_service(void) {}
+#endif
+
+
+#ifdef OPENSSL_EXTRA /*Lighttp compatibility*/
+
+    #ifndef NO_CERTS
+    void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
+        FreeX509Name(name, NULL);
+        XFREE(name, NULL, DYNAMIC_TYPE_X509);
+    }
+
+
+    /* Malloc's a new WOLFSSL_X509_NAME structure
+     *
+     * returns NULL on failure, otherwise returns a new structure.
+     */
+    WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new()
+    {
+        WOLFSSL_X509_NAME* name;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_new");
+
+        name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL,
+                DYNAMIC_TYPE_X509);
+        if (name != NULL) {
+            InitX509Name(name, 1);
+        }
+        return name;
+    }
+
+
+#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA)
+/* needed SetName function from asn.c is wrapped by NO_RSA */
+    /* helper function for CopyX509NameToCertName()
+     *
+     * returns WOLFSSL_SUCCESS on success
+     */
+    static int CopyX509NameEntry(char* out, int mx, char* in, int inLen)
+    {
+        if (inLen > mx) {
+            WOLFSSL_MSG("Name too long");
+            XMEMCPY(out, in, mx);
+        }
+        else {
+            XMEMCPY(out, in, inLen);
+            out[inLen] = '\0';
+        }
+
+        /* make sure is null terminated */
+        out[mx-1] = '\0';
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to
+     * a CertName structure.
+     *
+     * returns WOLFSSL_SUCCESS on success and a negative error value on failure
+     */
+    static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName)
+    {
+        DecodedName* dn = NULL;
+
+        if (n == NULL || cName == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        dn = &(n->fullName);
+
+        /* initialize cert name */
+        cName->country[0] = '\0';
+        cName->countryEnc = CTC_PRINTABLE;
+        cName->state[0] = '\0';
+        cName->stateEnc = CTC_UTF8;
+        cName->locality[0] = '\0';
+        cName->localityEnc = CTC_UTF8;
+        cName->sur[0] = '\0';
+        cName->surEnc = CTC_UTF8;
+        cName->org[0] = '\0';
+        cName->orgEnc = CTC_UTF8;
+        cName->unit[0] = '\0';
+        cName->unitEnc = CTC_UTF8;
+        cName->commonName[0] = '\0';
+        cName->commonNameEnc = CTC_UTF8;
+        cName->email[0] = '\0';
+
+
+        /* ASN_COUNTRY_NAME */
+        WOLFSSL_MSG("Copy Country Name");
+        if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx,
+                    dn->cLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_ORGUNIT_NAME */
+        WOLFSSL_MSG("Copy Org Unit Name");
+        if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx,
+                    dn->ouLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_ORG_NAME */
+        WOLFSSL_MSG("Copy Org Name");
+        if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx,
+                    dn->oLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_STATE_NAME */
+        WOLFSSL_MSG("Copy State Name");
+        if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx,
+                    dn->stLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_LOCALITY_NAME */
+        WOLFSSL_MSG("Copy Locality Name");
+        if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE,
+                    dn->fullName + dn->lIdx, dn->lLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_SUR_NAME */
+        WOLFSSL_MSG("Copy Sur Name");
+        if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx,
+                    dn->snLen) != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        /* ASN_COMMON_NAME */
+        WOLFSSL_MSG("Copy Common Name");
+        if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE,
+                    dn->fullName + dn->cnIdx, dn->cnLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        WOLFSSL_MSG("Copy Email");
+        if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE,
+                    dn->fullName + dn->emailIdx, dn->emailLen)
+                    != SSL_SUCCESS) {
+            return BUFFER_E;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+
+    /* 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)
+    {
+        CertName cName;
+        unsigned char buf[256]; /* ASN_MAX_NAME */
+        int sz;
+
+        if (out == NULL || name == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) {
+            WOLFSSL_MSG("Error converting x509 name to internal CertName");
+            return SSL_FATAL_ERROR;
+        }
+
+        sz = SetName(buf, sizeof(buf), &cName);
+        if (sz < 0) {
+            return sz;
+        }
+
+        /* using buffer passed in */
+        if (*out != NULL) {
+            XMEMCPY(*out, buf, sz);
+            *out += sz;
+        }
+        else {
+            *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
+            if (*out == NULL) {
+                return MEMORY_E;
+            }
+            XMEMCPY(*out, buf, sz);
+        }
+
+        return sz;
+    }
+#endif /* WOLFSSL_CERT_GEN */
+
+
+    /* Compares the two X509 names. If the size of x is larger then y then a
+     * positive value is returned if x is smaller a negative value is returned.
+     * In the case that the sizes are equal a the value of memcmp between the
+     * two names is returned.
+     *
+     * x First name for comparision
+     * y Second name to compare with x
+     */
+    int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
+            const WOLFSSL_X509_NAME* y)
+    {
+        WOLFSSL_STUB("wolfSSL_X509_NAME_cmp");
+
+        if (x == NULL || y == NULL) {
+            WOLFSSL_MSG("Bad argument passed in");
+            return -2;
+        }
+
+        if ((x->sz - y->sz) != 0) {
+            return x->sz - y->sz;
+        }
+        else {
+            return XMEMCMP(x->name, y->name, x->sz); /* y sz is the same */
+        }
+    }
+
+
+    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
+                                                 pem_password_cb *cb, void *u)
+    {
+        WOLFSSL_X509* x509 = NULL;
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+        unsigned char* pem = NULL;
+        int pemSz;
+        long  i = 0, l;
+        const char* footer = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+        if (bp == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
+            return NULL;
+        }
+
+        if (bp->type == WOLFSSL_BIO_MEMORY) {
+            l = (long)wolfSSL_BIO_ctrl_pending(bp);
+            if (l <= 0) {
+                WOLFSSL_MSG("No pending data in WOLFSSL_BIO");
+                return NULL;
+            }
+        }
+        else if (bp->type == WOLFSSL_BIO_FILE) {
+#ifndef NO_FILESYSTEM
+            /* Read in next certificate from file but no more. */
+            i = XFTELL(bp->file);
+            if (i < 0)
+                return NULL;
+            if (XFSEEK(bp->file, 0, SEEK_END) != 0)
+                return NULL;
+            l = XFTELL(bp->file);
+            if (l < 0)
+                return NULL;
+            if (XFSEEK(bp->file, i, SEEK_SET) != 0)
+                return NULL;
+
+            /* check calculated length */
+            if (l - i < 0)
+                return NULL;
+
+            l -= i;
+#else
+            WOLFSSL_MSG("Unable to read file with NO_FILESYSTEM defined");
+            return NULL;
+#endif /* !NO_FILESYSTEM */
+        }
+        else
+            return NULL;
+
+        pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
+        if (pem == NULL)
+            return NULL;
+
+        i = 0;
+        if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) {
+            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+            return NULL;
+        }
+
+        /* TODO: Inefficient
+         * reading in one byte at a time until see "END CERTIFICATE"
+         */
+        while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
+            i++;
+            if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) {
+                if (pem[i-1] == '\r') {
+                    /* found \r , Windows line ending is \r\n so try to read one
+                     * more byte for \n, ignoring return value */
+                    (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
+                }
+                break;
+            }
+        }
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+        if (l == 0)
+            WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
+    #endif
+        pemSz = (int)i;
+        x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz,
+                                                              WOLFSSL_FILETYPE_PEM);
+
+        if (x != NULL) {
+            *x = x509;
+        }
+
+        XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
+
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+        (void)bp;
+        (void)x;
+        (void)cb;
+        (void)u;
+
+        return x509;
+    }
+
+#if defined(HAVE_CRL) && !defined(NO_FILESYSTEM)
+    WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl,
+                                                    pem_password_cb *cb, void *u)
+    {
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+        unsigned char* pem = NULL;
+        DerBuffer* der = NULL;
+        int pemSz;
+        int derSz;
+        long  i = 0, l;
+        WOLFSSL_X509_CRL* newcrl;
+
+        WOLFSSL_ENTER("wolfSSL_PEM_read_X509_CRL");
+
+        if (fp == NULL) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509_CRL", BAD_FUNC_ARG);
+            return NULL;
+        }
+        /* Read in CRL from file */
+        i = XFTELL(fp);
+        if (i < 0) {
+            WOLFSSL_LEAVE("wolfSSL_PEM_read_X509_CRL", BAD_FUNC_ARG);
+            return NULL;
+        }
+
+        if (XFSEEK(fp, 0, SEEK_END) != 0)
+            return NULL;
+        l = XFTELL(fp);
+        if (l < 0)
+            return NULL;
+        if (XFSEEK(fp, i, SEEK_SET) != 0)
+            return NULL;
+        pemSz = (int)(l - i);
+        /* check calculated length */
+        if (pemSz  < 0)
+            return NULL;
+        if((pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM)) == NULL)
+            return NULL;
+
+        if((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz)
+            goto err_exit;
+        if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0)
+            goto err_exit;
+        XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+
+        derSz = der->length;
+        if((newcrl = wolfSSL_d2i_X509_CRL(crl, (const unsigned char *)der->buffer, derSz)) == NULL)
+            goto err_exit;
+        FreeDer(&der);
+
+        return newcrl;
+
+    err_exit:
+        if(pem != NULL)
+            XFREE(pem, 0, DYNAMIC_TYPE_PEM);
+        if(der != NULL)
+            FreeDer(&der);
+        return NULL;
+
+        (void)cb;
+        (void)u;
+    #endif
+
+    }
+#endif
+
+    /*
+     * bp : bio to read X509 from
+     * x  : x509 to write to
+     * cb : password call back for reading PEM
+     * u  : password
+     * _AUX is for working with a trusted X509 certificate
+     */
+    WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
+                               WOLFSSL_X509 **x, pem_password_cb *cb, void *u) {
+        WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
+
+        /* AUX info is; trusted/rejected uses, friendly name, private key id,
+         * and potentially a stack of "other" info. wolfSSL does not store
+         * friendly name or private key id yet in WOLFSSL_X509 for human
+         * readibility and does not support extra trusted/rejected uses for
+         * root CA. */
+        return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
+    }
+
+    void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
+    {
+        if (ne != NULL) {
+            if (ne->value != NULL && ne->value != &(ne->data)) {
+                wolfSSL_ASN1_STRING_free(ne->value);
+            }
+            XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY);
+        }
+    }
+
+
+    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void)
+    {
+        WOLFSSL_X509_NAME_ENTRY* ne = NULL;
+
+        ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY),
+                NULL, DYNAMIC_TYPE_NAME_ENTRY);
+        if (ne != NULL) {
+            XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
+            ne->value = &(ne->data);
+        }
+
+        return ne;
+    }
+
+
+    WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
+            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
+            unsigned char* data, int dataSz)
+    {
+        WOLFSSL_X509_NAME_ENTRY* ne = NULL;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()");
+
+        ne = wolfSSL_X509_NAME_ENTRY_new();
+        if (ne == NULL) {
+            return NULL;
+        }
+
+        ne->nid = nid;
+        ne->value = wolfSSL_ASN1_STRING_type_new(type);
+        wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz);
+        ne->set = 1;
+
+        if (out != NULL) {
+            *out = ne;
+        }
+
+        return ne;
+    }
+
+
+    /* Copies entry into name. With it being copied freeing entry becomes the
+     * callers responsibility.
+     * returns 1 for success and 0 for error */
+    int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
+            WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set)
+    {
+        int i;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()");
+
+        for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+            if (name->extra[i].set != 1) { /* not set so overwrited */
+                WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]);
+                WOLFSSL_ASN1_STRING*     str;
+
+                WOLFSSL_MSG("Found place for name entry");
+
+                XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY));
+                str = entry->value;
+                XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING));
+                current->value = &(current->data);
+                current->data.data = (char*)XMALLOC(str->length,
+                       name->x509->heap, DYNAMIC_TYPE_OPENSSL);
+
+                if (current->data.data == NULL) {
+                    return SSL_FAILURE;
+                }
+                XMEMCPY(current->data.data, str->data, str->length);
+
+                /* make sure is null terminated */
+                current->data.data[str->length - 1] = '\0';
+
+                current->set = 1; /* make sure now listed as set */
+                break;
+            }
+        }
+
+        if (i == MAX_NAME_ENTRIES) {
+            WOLFSSL_MSG("No spot found for name entry");
+            return SSL_FAILURE;
+        }
+
+        (void)idx;
+        (void)set;
+        return SSL_SUCCESS;
+    }
+    #endif /* ifndef NO_CERTS */
+
+
+    /* NID variables are dependent on compatibility header files currently
+     *
+     * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL
+     *         on fail
+     */
+    WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
+    {
+        word32 oidSz = 0;
+        const byte* oid;
+        word32 type = 0;
+        WOLFSSL_ASN1_OBJECT* obj;
+        byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */
+        word32 objSz = 0;
+        const char* sName;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()");
+
+        /* get OID type */
+        switch (id) {
+            /* oidHashType */
+        #ifdef WOLFSSL_MD2
+            case NID_md2:
+                id = MD2h;
+                type = oidHashType;
+                sName = "md2";
+                break;
+        #endif
+        #ifndef NO_MD5
+            case NID_md5:
+                id = MD5h;
+                type = oidHashType;
+                sName = "md5";
+                break;
+        #endif
+        #ifndef NO_SHA
+            case NID_sha1:
+                id = SHAh;
+                type = oidHashType;
+                sName = "sha";
+                break;
+        #endif
+            case NID_sha224:
+                id = SHA224h;
+                type = oidHashType;
+                sName = "sha224";
+                break;
+        #ifndef NO_SHA256
+            case NID_sha256:
+                id = SHA256h;
+                type = oidHashType;
+                sName = "sha256";
+                break;
+        #endif
+        #ifdef WOLFSSL_SHA384
+            case NID_sha384:
+                id = SHA384h;
+                type = oidHashType;
+                sName = "sha384";
+                break;
+        #endif
+        #ifdef WOLFSSL_SHA512
+            case NID_sha512:
+                id = SHA512h;
+                type = oidHashType;
+                sName = "sha512";
+                break;
+        #endif
+
+            /*  oidSigType */
+        #ifndef NO_DSA
+            case CTC_SHAwDSA:
+                sName = "shaWithDSA";
+                type = oidSigType;
+                break;
+
+        #endif /* NO_DSA */
+        #ifndef NO_RSA
+            case CTC_MD2wRSA:
+                sName = "md2WithRSA";
+                type = oidSigType;
+                break;
+
+        #ifndef NO_MD5
+            case CTC_MD5wRSA:
+                sName = "md5WithRSA";
+                type = oidSigType;
+                break;
+        #endif
+
+            case CTC_SHAwRSA:
+                sName = "shaWithRSA";
+                type = oidSigType;
+                break;
+
+        #ifdef WOLFSSL_SHA224
+            case CTC_SHA224wRSA:
+                sName = "sha224WithRSA";
+                type = oidSigType;
+                break;
+        #endif
+
+        #ifndef NO_SHA256
+            case CTC_SHA256wRSA:
+                sName = "sha256WithRSA";
+                type = oidSigType;
+                break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+            case CTC_SHA384wRSA:
+                sName = "sha384WithRSA";
+                type = oidSigType;
+                break;
+        #endif
+
+        #ifdef WOLFSSL_SHA512
+            case CTC_SHA512wRSA:
+                sName = "sha512WithRSA";
+                type = oidSigType;
+                break;
+        #endif
+        #endif /* NO_RSA */
+        #ifdef HAVE_ECC
+            case CTC_SHAwECDSA:
+                sName = "shaWithECDSA";
+                type = oidSigType;
+                break;
+
+            case CTC_SHA224wECDSA:
+                sName = "sha224WithECDSA";
+                type = oidSigType;
+                break;
+
+            case CTC_SHA256wECDSA:
+                sName = "sha256WithECDSA";
+                type = oidSigType;
+                break;
+
+            case CTC_SHA384wECDSA:
+                sName = "sha384WithECDSA";
+                type = oidSigType;
+                break;
+
+            case CTC_SHA512wECDSA:
+                sName = "sha512WithECDSA";
+                type = oidSigType;
+                break;
+        #endif /* HAVE_ECC */
+
+            /* oidKeyType */
+        #ifndef NO_DSA
+            case DSAk:
+                sName = "DSA key";
+                type = oidKeyType;
+                break;
+        #endif /* NO_DSA */
+        #ifndef NO_RSA
+            case RSAk:
+                sName = "RSA key";
+                type = oidKeyType;
+                break;
+        #endif /* NO_RSA */
+        #ifdef HAVE_NTRU
+            case NTRUk:
+                sName = "NTRU key";
+                type = oidKeyType;
+                break;
+        #endif /* HAVE_NTRU */
+        #ifdef HAVE_ECC
+            case ECDSAk:
+                sName = "ECDSA key";
+                type = oidKeyType;
+                break;
+        #endif /* HAVE_ECC */
+
+            /* oidBlkType */
+        #ifdef WOLFSSL_AES_128
+            case AES128CBCb:
+                sName = "AES-128-CBC";
+                type = oidBlkType;
+                break;
+        #endif
+        #ifdef WOLFSSL_AES_192
+            case AES192CBCb:
+                sName = "AES-192-CBC";
+                type = oidBlkType;
+                break;
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+            case AES256CBCb:
+                sName = "AES-256-CBC";
+                type = oidBlkType;
+                break;
+        #endif
+
+        #ifndef NO_DES3
+            case NID_des:
+                id = DESb;
+                sName = "DES-CBC";
+                type = oidBlkType;
+                break;
+
+            case NID_des3:
+                id = DES3b;
+                sName = "DES3-CBC";
+                type = oidBlkType;
+                break;
+        #endif /* !NO_DES3 */
+
+        #ifdef HAVE_OCSP
+            case NID_id_pkix_OCSP_basic:
+                id = OCSP_BASIC_OID;
+                sName = "OCSP_basic";
+                type = oidOcspType;
+                break;
+
+            case OCSP_NONCE_OID:
+                sName = "OCSP_nonce";
+                type = oidOcspType;
+                break;
+        #endif /* HAVE_OCSP */
+
+            /* oidCertExtType */
+            case BASIC_CA_OID:
+                sName = "X509 basic ca";
+                type = oidCertExtType;
+                break;
+
+            case ALT_NAMES_OID:
+                sName = "X509 alt names";
+                type = oidCertExtType;
+                break;
+
+            case CRL_DIST_OID:
+                sName = "X509 crl";
+                type = oidCertExtType;
+                break;
+
+            case AUTH_INFO_OID:
+                sName = "X509 auth info";
+                type = oidCertExtType;
+                break;
+
+            case AUTH_KEY_OID:
+                sName = "X509 auth key";
+                type = oidCertExtType;
+                break;
+
+            case SUBJ_KEY_OID:
+                sName = "X509 subject key";
+                type = oidCertExtType;
+                break;
+
+            case KEY_USAGE_OID:
+                sName = "X509 key usage";
+                type = oidCertExtType;
+                break;
+
+            case INHIBIT_ANY_OID:
+                id = INHIBIT_ANY_OID;
+                sName = "X509 inhibit any";
+                type = oidCertExtType;
+                break;
+
+            case NID_ext_key_usage:
+                id = KEY_USAGE_OID;
+                sName = "X509 ext key usage";
+                type = oidCertExtType;
+                break;
+
+            case NID_name_constraints:
+                id = NAME_CONS_OID;
+                sName = "X509 name constraints";
+                type = oidCertExtType;
+                break;
+
+            case NID_certificate_policies:
+                id = CERT_POLICY_OID;
+                sName = "X509 certificate policies";
+                type = oidCertExtType;
+                break;
+
+            /* oidCertAuthInfoType */
+            case AIA_OCSP_OID:
+                sName = "Cert Auth OCSP";
+                type = oidCertAuthInfoType;
+                break;
+
+            case AIA_CA_ISSUER_OID:
+                sName = "Cert Auth CA Issuer";
+                type = oidCertAuthInfoType;
+                break;
+
+            /* oidCertPolicyType */
+            case NID_any_policy:
+                id = CP_ANY_OID;
+                sName = "Cert any policy";
+                type = oidCertPolicyType;
+                break;
+
+                /* oidCertAltNameType */
+            case NID_hw_name_oid:
+                id = HW_NAME_OID;
+                sName = "Hardware name";
+                type = oidCertAltNameType;
+                break;
+
+            /* oidCertKeyUseType */
+            case NID_anyExtendedKeyUsage:
+                id = EKU_ANY_OID;
+                sName = "Cert any extended key";
+                type = oidCertKeyUseType;
+                break;
+
+            case EKU_SERVER_AUTH_OID:
+                sName = "Cert server auth key";
+                type = oidCertKeyUseType;
+                break;
+
+            case EKU_CLIENT_AUTH_OID:
+                sName = "Cert client auth key";
+                type = oidCertKeyUseType;
+                break;
+
+            case EKU_OCSP_SIGN_OID:
+                sName = "Cert OCSP sign key";
+                type = oidCertKeyUseType;
+                break;
+
+            /* oidKdfType */
+            case PBKDF2_OID:
+                sName = "PBKDFv2";
+                type = oidKdfType;
+                break;
+
+                /* oidPBEType */
+            case PBE_SHA1_RC4_128:
+                sName = "PBE shaWithRC4-128";
+                type = oidPBEType;
+                break;
+
+            case PBE_SHA1_DES:
+                sName = "PBE shaWithDES";
+                type = oidPBEType;
+                break;
+
+            case PBE_SHA1_DES3:
+                sName = "PBE shaWithDES3";
+                type = oidPBEType;
+                break;
+
+                /* oidKeyWrapType */
+        #ifdef WOLFSSL_AES_128
+            case AES128_WRAP:
+                sName = "AES-128 wrap";
+                type = oidKeyWrapType;
+                break;
+        #endif
+
+        #ifdef WOLFSSL_AES_192
+            case AES192_WRAP:
+                sName = "AES-192 wrap";
+                type = oidKeyWrapType;
+                break;
+        #endif
+
+        #ifdef WOLFSSL_AES_256
+            case AES256_WRAP:
+                sName = "AES-256 wrap";
+                type = oidKeyWrapType;
+                break;
+        #endif
+
+                /* oidCmsKeyAgreeType */
+        #ifndef NO_SHA
+            case dhSinglePass_stdDH_sha1kdf_scheme:
+                sName = "DH-SHA kdf";
+                type = oidCmsKeyAgreeType;
+                break;
+        #endif
+        #ifdef WOLFSSL_SHA224
+            case dhSinglePass_stdDH_sha224kdf_scheme:
+                sName = "DH-SHA224 kdf";
+                type = oidCmsKeyAgreeType;
+                break;
+        #endif
+        #ifndef NO_SHA256
+            case dhSinglePass_stdDH_sha256kdf_scheme:
+                sName = "DH-SHA256 kdf";
+                type = oidCmsKeyAgreeType;
+                break;
+
+        #endif
+        #ifdef WOLFSSL_SHA384
+            case dhSinglePass_stdDH_sha384kdf_scheme:
+                sName = "DH-SHA384 kdf";
+                type = oidCmsKeyAgreeType;
+                break;
+        #endif
+        #ifdef WOLFSSL_SHA512
+            case dhSinglePass_stdDH_sha512kdf_scheme:
+                sName = "DH-SHA512 kdf";
+                type = oidCmsKeyAgreeType;
+                break;
+        #endif
+            default:
+                WOLFSSL_MSG("NID not in table");
+                return NULL;
+        }
+
+    #ifdef HAVE_ECC
+         if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) {
+             type = oidCurveType;
+         }
+    #endif /* HAVE_ECC */
+
+        if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
+            WOLFSSL_MSG("Attempted short name is too large");
+            return NULL;
+        }
+
+        oid = OidFromId(id, type, &oidSz);
+
+        /* set object ID to buffer */
+        obj = wolfSSL_ASN1_OBJECT_new();
+        if (obj == NULL) {
+            WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+            return NULL;
+        }
+        obj->type    = id;
+        obj->grp     = type;
+        obj->dynamic = 1;
+        XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
+
+        objBuf[0] = ASN_OBJECT_ID; objSz++;
+        objSz += SetLength(oidSz, objBuf + 1);
+        XMEMCPY(objBuf + objSz, oid, oidSz);
+        objSz     += oidSz;
+        obj->objSz = objSz;
+
+        obj->obj = (byte*)XMALLOC(obj->objSz, NULL, DYNAMIC_TYPE_ASN1);
+        if (obj->obj == NULL) {
+            wolfSSL_ASN1_OBJECT_free(obj);
+            return NULL;
+        }
+        XMEMCPY(obj->obj, objBuf, obj->objSz);
+
+        (void)type;
+
+        return obj;
+    }
+
+
+    /* if no_name is one than use numerical form otherwise can be short name.
+     *
+     * returns the buffer size on success
+     */
+    int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name)
+    {
+        int bufSz;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()");
+
+        if (buf == NULL || bufLen <= 1 || a == NULL) {
+            WOLFSSL_MSG("Bad input argument");
+            return WOLFSSL_FAILURE;
+        }
+
+        if (no_name == 1) {
+            int    length;
+            word32 idx = 0;
+
+            if (a->obj[idx++] != ASN_OBJECT_ID) {
+                WOLFSSL_MSG("Bad ASN1 Object");
+                return WOLFSSL_FAILURE;
+            }
+
+            if (GetLength((const byte*)a->obj, &idx, &length,
+                           a->objSz) < 0 || length < 0) {
+                return ASN_PARSE_E;
+            }
+
+            if (bufLen < MAX_OID_STRING_SZ) {
+                bufSz = bufLen - 1;
+            }
+            else {
+                bufSz = MAX_OID_STRING_SZ;
+            }
+
+            if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
+                        (word32)length)) <= 0) {
+                WOLFSSL_MSG("Error decoding OID");
+                return WOLFSSL_FAILURE;
+            }
+
+        }
+        else { /* return short name */
+            if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) {
+                bufSz = (int)XSTRLEN(a->sName);
+            }
+            else {
+                bufSz = bufLen - 1;
+            }
+            XMEMCPY(buf, a->sName, bufSz);
+        }
+
+        buf[bufSz] = '\0';
+        return bufSz;
+    }
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
+    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
+    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
+    defined(WOLFSSL_HAPROXY)
+
+#ifndef NO_SHA
+    /* One shot SHA1 hash of message.
+     *
+     * d  message to hash
+     * n  size of d buffer
+     * md buffer to hold digest. Should be SHA_DIGEST_SIZE.
+     *
+     * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used.
+     *       When the static buffer is used this function is not thread safe.
+     *
+     * Returns a pointer to the message digest on success and NULL on failure.
+     */
+    unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n,
+            unsigned char *md)
+    {
+        static byte dig[WC_SHA_DIGEST_SIZE];
+        wc_Sha sha;
+
+        WOLFSSL_ENTER("wolfSSL_SHA1");
+
+        if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
+            WOLFSSL_MSG("SHA1 Init failed");
+            return NULL;
+        }
+
+        if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) {
+            WOLFSSL_MSG("SHA1 Update failed");
+            return NULL;
+        }
+
+        if (wc_ShaFinal(&sha, dig) != 0) {
+            WOLFSSL_MSG("SHA1 Final failed");
+            return NULL;
+        }
+
+        wc_ShaFree(&sha);
+
+        if (md != NULL) {
+            XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE);
+            return md;
+        }
+        else {
+            return (unsigned char*)dig;
+        }
+    }
+#endif /* ! NO_SHA */
+
+#ifndef NO_SHA256
+    /* One shot SHA256 hash of message.
+     *
+     * d  message to hash
+     * n  size of d buffer
+     * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+     *
+     * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+     *       When the static buffer is used this function is not thread safe.
+     *
+     * Returns a pointer to the message digest on success and NULL on failure.
+     */
+    unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n,
+            unsigned char *md)
+    {
+        static byte dig[WC_SHA256_DIGEST_SIZE];
+        wc_Sha256 sha;
+
+        WOLFSSL_ENTER("wolfSSL_SHA256");
+
+        if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
+            WOLFSSL_MSG("SHA256 Init failed");
+            return NULL;
+        }
+
+        if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) {
+            WOLFSSL_MSG("SHA256 Update failed");
+            return NULL;
+        }
+
+        if (wc_Sha256Final(&sha, dig) != 0) {
+            WOLFSSL_MSG("SHA256 Final failed");
+            return NULL;
+        }
+
+        wc_Sha256Free(&sha);
+
+        if (md != NULL) {
+            XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE);
+            return md;
+        }
+        else {
+            return (unsigned char*)dig;
+        }
+    }
+#endif /* ! NO_SHA256 */
+
+#ifdef WOLFSSL_SHA384
+     /* One shot SHA384 hash of message.
+      *
+      * d  message to hash
+      * n  size of d buffer
+      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+      *
+      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+      *       When the static buffer is used this function is not thread safe.
+      *
+      * Returns a pointer to the message digest on success and NULL on failure.
+      */
+     unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n,
+             unsigned char *md)
+     {
+         static byte dig[WC_SHA384_DIGEST_SIZE];
+         wc_Sha384 sha;
+
+         WOLFSSL_ENTER("wolfSSL_SHA384");
+
+         if (wc_InitSha384_ex(&sha, NULL, 0) != 0) {
+             WOLFSSL_MSG("SHA384 Init failed");
+             return NULL;
+         }
+
+         if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) {
+             WOLFSSL_MSG("SHA384 Update failed");
+             return NULL;
+         }
+
+         if (wc_Sha384Final(&sha, dig) != 0) {
+             WOLFSSL_MSG("SHA384 Final failed");
+             return NULL;
+         }
+
+         wc_Sha384Free(&sha);
+
+         if (md != NULL) {
+             XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE);
+             return md;
+         }
+         else {
+             return (unsigned char*)dig;
+         }
+     }
+#endif /* WOLFSSL_SHA384  */
+
+
+#if defined(WOLFSSL_SHA512)
+     /* One shot SHA512 hash of message.
+      *
+      * d  message to hash
+      * n  size of d buffer
+      * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE.
+      *
+      * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used.
+      *       When the static buffer is used this function is not thread safe.
+      *
+      * Returns a pointer to the message digest on success and NULL on failure.
+      */
+     unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n,
+             unsigned char *md)
+     {
+         static byte dig[WC_SHA512_DIGEST_SIZE];
+         wc_Sha512 sha;
+
+         WOLFSSL_ENTER("wolfSSL_SHA512");
+
+         if (wc_InitSha512_ex(&sha, NULL, 0) != 0) {
+             WOLFSSL_MSG("SHA512 Init failed");
+             return NULL;
+         }
+
+         if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) {
+             WOLFSSL_MSG("SHA512 Update failed");
+             return NULL;
+         }
+
+         if (wc_Sha512Final(&sha, dig) != 0) {
+             WOLFSSL_MSG("SHA512 Final failed");
+             return NULL;
+         }
+
+         wc_Sha512Free(&sha);
+
+         if (md != NULL) {
+             XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE);
+             return md;
+         }
+         else {
+             return (unsigned char*)dig;
+         }
+     }
+#endif /* defined(WOLFSSL_SHA512)  */
+
+    char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
+    {
+        int ret;
+
+        WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
+
+        FreeDer(&ctx->certificate); /* Make sure previous is free'd */
+        ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE,
+                       ctx->heap);
+        if (ret != 0)
+            return 0;
+
+        XMEMCPY(ctx->certificate->buffer, x->derCert->buffer,
+                x->derCert->length);
+#ifdef KEEP_OUR_CERT
+        if (ctx->ourCert != NULL && ctx->ownOurCert) {
+            FreeX509(ctx->ourCert);
+            XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509);
+        }
+        ctx->ourCert = x;
+        ctx->ownOurCert = 0;
+#endif
+
+        /* Update the available options with public keys. */
+        switch (x->pubKeyOID) {
+            case RSAk:
+                ctx->haveRSA = 1;
+                break;
+        #ifdef HAVE_ED25519
+            case ED25519k:
+        #endif
+            case ECDSAk:
+                ctx->haveECC = 1;
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+                ctx->pkCurveOID = x->pkCurveOID;
+            #endif
+                break;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) {
+    #ifndef NO_FILESYSTEM
+        XFILE fp;
+
+        WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+        if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != NULL))
+        {
+            XFCLOSE(fp);
+        }
+
+        fp = XFOPEN(name, "r");
+        if (fp == NULL)
+            return WOLFSSL_BAD_FILE;
+
+        if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+            XFCLOSE(fp);
+            return WOLFSSL_BAD_FILE;
+        }
+
+        /* file is closed when bio is free'd */
+        return WOLFSSL_SUCCESS;
+    #else
+        (void)name;
+        (void)b;
+        return WOLFSSL_NOT_IMPLEMENTED;
+    #endif
+    }
+    #endif
+
+#ifdef HAVE_ECC
+    const char * wolfSSL_OBJ_nid2sn(int n) {
+        int i;
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn");
+
+        /* find based on NID and return name */
+        for (i = 0; i < ecc_sets[i].size; i++) {
+            if (n == ecc_sets[i].id) {
+                return ecc_sets[i].name;
+            }
+        }
+        return NULL;
+    }
+
+    int wolfSSL_OBJ_sn2nid(const char *sn) {
+        int i;
+        WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid");
+
+        /* Nginx uses this OpenSSL string. */
+        if (XSTRNCMP(sn, "prime256v1", 10) == 0)
+            sn = "SECP256R1";
+        if (XSTRNCMP(sn, "secp384r1", 10) == 0)
+            sn = "SECP384R1";
+        /* find based on name and return NID */
+        for (i = 0; i < ecc_sets[i].size; i++) {
+            if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
+                return ecc_sets[i].id;
+            }
+        }
+        return -1;
+    }
+#endif /* HAVE_ECC */
+
+    /* Gets the NID value that corresponds with the ASN1 object.
+     *
+     * o ASN1 object to get NID of
+     *
+     * Return NID on success and a negative value on failure
+     */
+    int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) {
+        word32 oid = 0;
+        word32 idx = 0;
+        int id;
+
+        WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
+
+        if (o == NULL) {
+            return -1;
+        }
+
+        if ((id = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) {
+            WOLFSSL_MSG("Issue getting OID of object");
+            return -1;
+        }
+
+        /* get OID type */
+        switch (o->grp) {
+            /* oidHashType */
+            case oidHashType:
+                switch (oid) {
+                #ifdef WOLFSSL_MD2
+                    case MD2h:
+                        return NID_md2;
+                #endif
+                #ifndef NO_MD5
+                    case MD5h:
+                        return NID_md5;
+                #endif
+                #ifndef NO_SHA
+                    case SHAh:
+                        return NID_sha1;
+                #endif
+                    case SHA224h:
+                        return NID_sha224;
+                #ifndef NO_SHA256
+                    case SHA256h:
+                        return NID_sha256;
+                #endif
+                #ifdef WOLFSSL_SHA384
+                    case SHA384h:
+                        return NID_sha384;
+                #endif
+                #ifdef WOLFSSL_SHA512
+                    case SHA512h:
+                        return NID_sha512;
+                #endif
+                }
+                break;
+
+            /*  oidSigType */
+            case oidSigType:
+                switch (oid) {
+                #ifndef NO_DSA
+                    case CTC_SHAwDSA:
+                        return CTC_SHAwDSA;
+                #endif /* NO_DSA */
+                #ifndef NO_RSA
+                    case CTC_MD2wRSA:
+                        return CTC_MD2wRSA;
+                    case CTC_MD5wRSA:
+                        return CTC_MD5wRSA;
+                    case CTC_SHAwRSA:
+                        return CTC_SHAwRSA;
+                    case CTC_SHA224wRSA:
+                        return CTC_SHA224wRSA;
+                    case CTC_SHA256wRSA:
+                        return CTC_SHA256wRSA;
+                    case CTC_SHA384wRSA:
+                        return CTC_SHA384wRSA;
+                    case CTC_SHA512wRSA:
+                        return CTC_SHA512wRSA;
+                #endif /* NO_RSA */
+                #ifdef HAVE_ECC
+                    case CTC_SHAwECDSA:
+                        return CTC_SHAwECDSA;
+                    case CTC_SHA224wECDSA:
+                        return CTC_SHA224wECDSA;
+                    case CTC_SHA256wECDSA:
+                        return CTC_SHA256wECDSA;
+                    case CTC_SHA384wECDSA:
+                        return CTC_SHA384wECDSA;
+                    case CTC_SHA512wECDSA:
+                        return CTC_SHA512wECDSA;
+                #endif /* HAVE_ECC */
+                }
+                break;
+
+            /* oidKeyType */
+            case oidKeyType:
+                switch (oid) {
+                #ifndef NO_DSA
+                    case DSAk:
+                        return DSAk;
+                #endif /* NO_DSA */
+                #ifndef NO_RSA
+                    case RSAk:
+                        return RSAk;
+                #endif /* NO_RSA */
+                #ifdef HAVE_NTRU
+                    case NTRUk:
+                        return NTRUk;
+                #endif /* HAVE_NTRU */
+                #ifdef HAVE_ECC
+                    case ECDSAk:
+                        return ECDSAk;
+                #endif /* HAVE_ECC */
+                }
+                break;
+
+            /* oidBlkType */
+            case oidBlkType:
+                switch (oid) {
+                #ifdef WOLFSSL_AES_128
+                    case AES128CBCb:
+                        return AES128CBCb;
+                #endif
+                #ifdef WOLFSSL_AES_192
+                    case AES192CBCb:
+                        return AES192CBCb;
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    case AES256CBCb:
+                        return AES256CBCb;
+                #endif
+                #ifndef NO_DES3
+                    case DESb:
+                        return NID_des;
+                    case DES3b:
+                        return NID_des3;
+                #endif
+                }
+                break;
+
+        #ifdef HAVE_OCSP
+            case oidOcspType:
+                switch (oid) {
+                    case OCSP_BASIC_OID:
+                        return NID_id_pkix_OCSP_basic;
+                    case OCSP_NONCE_OID:
+                        return OCSP_NONCE_OID;
+                }
+                break;
+        #endif /* HAVE_OCSP */
+
+            /* oidCertExtType */
+            case oidCertExtType:
+                switch (oid) {
+                    case BASIC_CA_OID:
+                        return BASIC_CA_OID;
+                    case ALT_NAMES_OID:
+                        return ALT_NAMES_OID;
+                    case CRL_DIST_OID:
+                        return CRL_DIST_OID;
+                    case AUTH_INFO_OID:
+                        return AUTH_INFO_OID;
+                    case AUTH_KEY_OID:
+                        return AUTH_KEY_OID;
+                    case SUBJ_KEY_OID:
+                        return SUBJ_KEY_OID;
+                    case INHIBIT_ANY_OID:
+                        return INHIBIT_ANY_OID;
+                    case KEY_USAGE_OID:
+                        return NID_ext_key_usage;
+                    case NAME_CONS_OID:
+                        return NID_name_constraints;
+                    case CERT_POLICY_OID:
+                        return NID_certificate_policies;
+                }
+                break;
+
+            /* oidCertAuthInfoType */
+            case oidCertAuthInfoType:
+                switch (oid) {
+                    case AIA_OCSP_OID:
+                        return AIA_OCSP_OID;
+                    case AIA_CA_ISSUER_OID:
+                        return AIA_CA_ISSUER_OID;
+                }
+                break;
+
+            /* oidCertPolicyType */
+            case oidCertPolicyType:
+                switch (oid) {
+                    case CP_ANY_OID:
+                        return NID_any_policy;
+                }
+                break;
+
+            /* oidCertAltNameType */
+            case oidCertAltNameType:
+                switch (oid) {
+                    case HW_NAME_OID:
+                        return NID_hw_name_oid;
+                }
+                break;
+
+            /* oidCertKeyUseType */
+            case oidCertKeyUseType:
+                switch (oid) {
+                    case EKU_ANY_OID:
+                        return NID_anyExtendedKeyUsage;
+                    case EKU_SERVER_AUTH_OID:
+                        return EKU_SERVER_AUTH_OID;
+                    case EKU_CLIENT_AUTH_OID:
+                        return EKU_CLIENT_AUTH_OID;
+                    case EKU_OCSP_SIGN_OID:
+                        return EKU_OCSP_SIGN_OID;
+                }
+                break;
+
+            /* oidKdfType */
+            case oidKdfType:
+                switch (oid) {
+                    case PBKDF2_OID:
+                        return PBKDF2_OID;
+                }
+                break;
+
+            /* oidPBEType */
+            case oidPBEType:
+                switch (oid) {
+                    case PBE_SHA1_RC4_128:
+                        return PBE_SHA1_RC4_128;
+                    case PBE_SHA1_DES:
+                        return PBE_SHA1_DES;
+                    case PBE_SHA1_DES3:
+                        return PBE_SHA1_DES3;
+                }
+                break;
+
+            /* oidKeyWrapType */
+            case oidKeyWrapType:
+                switch (oid) {
+                #ifdef WOLFSSL_AES_128
+                    case AES128_WRAP:
+                        return AES128_WRAP;
+                #endif
+                #ifdef WOLFSSL_AES_192
+                    case AES192_WRAP:
+                        return AES192_WRAP;
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    case AES256_WRAP:
+                        return AES256_WRAP;
+                #endif
+                }
+                break;
+
+            /* oidCmsKeyAgreeType */
+            case oidCmsKeyAgreeType:
+                switch (oid) {
+                    #ifndef NO_SHA
+                    case dhSinglePass_stdDH_sha1kdf_scheme:
+                        return dhSinglePass_stdDH_sha1kdf_scheme;
+                    #endif
+                    #ifdef WOLFSSL_SHA224
+                    case dhSinglePass_stdDH_sha224kdf_scheme:
+                        return dhSinglePass_stdDH_sha224kdf_scheme;
+                    #endif
+                    #ifndef NO_SHA256
+                    case dhSinglePass_stdDH_sha256kdf_scheme:
+                        return dhSinglePass_stdDH_sha256kdf_scheme;
+                    #endif
+                    #ifdef WOLFSSL_SHA384
+                    case dhSinglePass_stdDH_sha384kdf_scheme:
+                        return dhSinglePass_stdDH_sha384kdf_scheme;
+                    #endif
+                    #ifdef WOLFSSL_SHA512
+                    case dhSinglePass_stdDH_sha512kdf_scheme:
+                        return dhSinglePass_stdDH_sha512kdf_scheme;
+                    #endif
+                }
+                break;
+
+            default:
+                WOLFSSL_MSG("NID not in table");
+                return -1;
+        }
+
+        return -1;
+    }
+
+
+#ifndef NO_WOLFSSL_STUB
+    char * wolfSSL_OBJ_nid2ln(int n)
+    {
+        (void)n;
+        WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln");
+        WOLFSSL_STUB("OBJ_nid2ln");
+
+        return NULL;
+    }
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+    int wolfSSL_OBJ_txt2nid(const char* s)
+    {
+        (void)s;
+        WOLFSSL_STUB("OBJ_txt2nid");
+
+        return 0;
+    }
+#endif
+
+    /* compatibility function. It's intended use is to remove OID's from an
+     * internal table that have been added with OBJ_create. wolfSSL manages it's
+     * own interenal OID values and does not currently support OBJ_create. */
+    void wolfSSL_OBJ_cleanup(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()");
+    }
+
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) {
+        WOLFSSL_ENTER("wolfSSL_set_verify_depth");
+#ifndef OPENSSL_EXTRA
+        (void)ssl;
+        (void)depth;
+        WOLFSSL_STUB("wolfSSL_set_verify_depth");
+#else
+        ssl->options.verifyDepth = (byte)depth;
+#endif
+    }
+    #endif
+
+
+    #ifndef NO_WOLFSSL_STUB
+    WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) {
+        (void)ne;
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
+        WOLFSSL_STUB("X509_NAME_ENTRY_get_object");
+
+        return NULL;
+    }
+    #endif
+
+    WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(
+                                             WOLFSSL_X509_NAME *name, int loc) {
+
+        int maxLoc = name->fullName.fullNameLen;
+
+        WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry");
+
+        if (loc < 0 || loc > maxLoc) {
+            WOLFSSL_MSG("Bad argument");
+            return NULL;
+        }
+
+        /* DC component */
+        if (name->fullName.dcMode){
+            if (name->fullName.fullName != NULL){
+                if (loc == name->fullName.dcNum){
+                    name->cnEntry.data.data   = &name->fullName.fullName[name->fullName.cIdx];
+                    name->cnEntry.data.length = name->fullName.cLen;
+                    name->cnEntry.nid         = ASN_COUNTRY_NAME;
+                } else {
+                    name->cnEntry.data.data   = &name->fullName.fullName[name->fullName.dcIdx[loc]];
+                    name->cnEntry.data.length = name->fullName.dcLen[loc];
+                    name->cnEntry.nid         = ASN_DOMAIN_COMPONENT;
+                }
+            }
+            name->cnEntry.data.type = CTC_UTF8;
+            name->cnEntry.set       = 1;
+            return &(name->cnEntry);
+
+         /* common name index case */
+        } else if (loc == name->fullName.cnIdx) {
+            /* get CN shortcut from x509 since it has null terminator */
+            name->cnEntry.data.data   = name->x509->subjectCN;
+            name->cnEntry.data.length = name->fullName.cnLen;
+            name->cnEntry.data.type   = CTC_UTF8;
+            name->cnEntry.nid         = ASN_COMMON_NAME;
+            name->cnEntry.set         = 1;
+            return &(name->cnEntry);
+        }
+
+        /* additionall cases to check for go here */
+
+        WOLFSSL_MSG("Entry not found or implemented");
+        (void)name;
+        (void)loc;
+
+        return NULL;
+    }
+
+    #ifndef NO_WOLFSSL_STUB
+    void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){
+        (void) sk;
+        (void) f;
+        WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free");
+        WOLFSSL_STUB("sk_X509_NAME_pop_free");
+    }
+    #endif
+    #ifndef NO_WOLFSSL_STUB
+    int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key){
+        (void) x509;
+        (void) key;
+        WOLFSSL_ENTER("wolfSSL_X509_check_private_key");
+        WOLFSSL_STUB("X509_check_private_key");
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ){
+        (void) sk;
+        WOLFSSL_ENTER("wolfSSL_dup_CA_list");
+        WOLFSSL_STUB("SSL_dup_CA_list");
+
+        return NULL;
+    }
+    #endif
+
+#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_EXTRA
+
+/* wolfSSL uses negative values for error states. This function returns an
+ * unsigned type so the value returned is the absolute value of the error.
+ */
+unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+    (void)line;
+    (void)file;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY)
+    {
+        int ret;
+
+        if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+            WOLFSSL_MSG("Issue peeking at error node in queue");
+            return 0;
+        }
+    #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+        if (ret == -ASN_NO_PEM_HEADER)
+            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+    #endif
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+
+
+#ifndef NO_CERTS
+int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
+
+    if (ctx == NULL || pkey == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    if (pkey->pkey.ptr != NULL) {
+        /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
+        return wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+                                       (const unsigned char*)pkey->pkey.ptr,
+                                       pkey->pkey_sz, SSL_FILETYPE_ASN1);
+    }
+
+    WOLFSSL_MSG("wolfSSL private key not set");
+    return BAD_FUNC_ARG;
+}
+#endif /* !NO_CERTS */
+
+
+void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data");
+    #ifdef HAVE_EX_DATA
+    if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) {
+        return ctx->ex_data[idx];
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    #endif
+    return NULL;
+}
+
+int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b,
+                                void* c)
+{
+    static int ctx_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
+    (void)idx;
+    (void)arg;
+    (void)a;
+    (void)b;
+    (void)c;
+
+    return ctx_idx++;
+}
+
+
+/* Return the index that can be used for the WOLFSSL structure to store
+ * application data.
+ *
+ */
+int wolfSSL_get_ex_new_index(long argValue, void* arg,
+        WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2,
+        WOLFSSL_CRYPTO_EX_free* cb3)
+{
+    static int ssl_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_get_ex_new_index");
+
+    (void)argValue;
+    (void)arg;
+    (void)cb1;
+    (void)cb2;
+    (void)cb3;
+
+    return ssl_idx++;
+}
+
+
+int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (ctx != NULL && idx < MAX_EX_DATA)
+    {
+        ctx->ex_data[idx] = data;
+        return WOLFSSL_SUCCESS;
+    }
+    #else
+    (void)ctx;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+
+
+/* Returns char* to app data stored in ex[0].
+ *
+ * ssl WOLFSSL structure to get app data from
+ */
+void* wolfSSL_get_app_data(const WOLFSSL *ssl)
+{
+    /* checkout exdata stuff... */
+    WOLFSSL_ENTER("wolfSSL_get_app_data");
+
+    return wolfSSL_get_ex_data(ssl, 0);
+}
+
+
+/* Set ex array 0 to have app data
+ *
+ * ssl WOLFSSL struct to set app data in
+ * arg data to be stored
+ *
+ * Returns SSL_SUCCESS on sucess and SSL_FAILURE on failure
+ */
+int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
+    WOLFSSL_ENTER("wolfSSL_set_app_data");
+
+    return wolfSSL_set_ex_data(ssl, 0, arg);
+}
+
+
+int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_set_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ssl != NULL && idx < MAX_EX_DATA)
+    {
+        ssl->ex_data[idx] = data;
+        return WOLFSSL_SUCCESS;
+    }
+#else
+    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+    (void)ssl;
+    (void)idx;
+    (void)data;
+#endif
+    return WOLFSSL_FAILURE;
+}
+
+
+
+void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_get_ex_data");
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0)
+        return ssl->ex_data[idx];
+#else
+    WOLFSSL_MSG("HAVE_EX_DATA macro is not defined");
+    (void)ssl;
+    (void)idx;
+#endif
+    return 0;
+}
+
+#ifndef NO_DSA
+WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x,
+        pem_password_cb *cb, void *u)
+{
+    WOLFSSL_DSA* dsa;
+    DsaKey* key;
+    int    length;
+    unsigned char*  buf;
+    word32 bufSz;
+    int ret;
+    word32 idx = 0;
+    DerBuffer* pDer;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams");
+
+    ret = wolfSSL_BIO_get_mem_data(bp, &buf);
+    if (ret <= 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+        return NULL;
+    }
+
+    bufSz = (word32)ret;
+
+    if (cb != NULL || u != NULL) {
+        /*
+         * cb is for a call back when encountering encrypted PEM files
+         * if cb == NULL and u != NULL then u = null terminated password string
+         */
+        WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM");
+    }
+
+    if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL,
+                    NULL)) < 0 ) {
+        WOLFSSL_MSG("Issue converting from PEM to DER");
+        return NULL;
+    }
+
+    if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) {
+        WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret);
+        FreeDer(&pDer);
+        return NULL;
+    }
+
+    dsa = wolfSSL_DSA_new();
+    if (dsa == NULL) {
+        FreeDer(&pDer);
+        WOLFSSL_MSG("Error creating DSA struct");
+        return NULL;
+    }
+
+    key = (DsaKey*)dsa->internal;
+    if (key == NULL) {
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        WOLFSSL_MSG("Error finding DSA key struct");
+        return NULL;
+    }
+
+    if (GetInt(&key->p,  pDer->buffer, &idx, pDer->length) < 0 ||
+        GetInt(&key->q,  pDer->buffer, &idx, pDer->length) < 0 ||
+        GetInt(&key->g,  pDer->buffer, &idx, pDer->length) < 0 ) {
+        WOLFSSL_MSG("dsa key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa p key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa q key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("dsa g key error");
+        FreeDer(&pDer);
+        wolfSSL_DSA_free(dsa);
+        return NULL;
+    }
+
+    if (x != NULL) {
+        *x = dsa;
+    }
+
+    FreeDer(&pDer);
+    return dsa;
+}
+#endif /* NO_DSA */
+
+#define WOLFSSL_BIO_INCLUDED
+#include "src/bio.c"
+
+/* Begin functions for openssl/buffer.h */
+WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void)
+{
+    WOLFSSL_BUF_MEM* buf;
+    buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL,
+                                                        DYNAMIC_TYPE_OPENSSL);
+    if (buf) {
+        XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM));
+    }
+    return buf;
+}
+
+
+/* returns length of buffer on success */
+int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len)
+{
+    int len_int = (int)len;
+    int mx;
+
+    /* verify provided arguments */
+    if (buf == NULL || len_int < 0) {
+        return 0; /* BAD_FUNC_ARG; */
+    }
+
+    /* check to see if fits in existing length */
+    if (buf->length > len) {
+        buf->length = len;
+        return len_int;
+    }
+
+    /* check to see if fits in max buffer */
+    if (buf->max >= len) {
+        if (buf->data != NULL) {
+            XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+        }
+        buf->length = len;
+        return len_int;
+    }
+
+    /* expand size, to handle growth */
+    mx = (len_int + 3) / 3 * 4;
+
+    /* use realloc */
+    buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (buf->data == NULL) {
+        return 0; /* ERR_R_MALLOC_FAILURE; */
+    }
+
+    buf->max = mx;
+    XMEMSET(&buf->data[buf->length], 0, len - buf->length);
+    buf->length = len;
+
+    return len_int;
+}
+
+void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf)
+{
+    if (buf) {
+        if (buf->data) {
+            XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            buf->data = NULL;
+        }
+        buf->max = 0;
+        buf->length = 0;
+        XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+/* End Functions for openssl/buffer.h */
+
+#endif /* OPENSSL_EXTRA */
+
+
+#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
+
+WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
+{
+#ifndef NO_FILESYSTEM
+    WOLFSSL_BIO* bio;
+    XFILE fp;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_new_file");
+
+    fp = XFOPEN(filename, mode);
+    if (fp == NULL)
+        return NULL;
+
+    bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
+    if (bio == NULL) {
+        XFCLOSE(fp);
+        return bio;
+    }
+
+    if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+        XFCLOSE(fp);
+        wolfSSL_BIO_free(bio);
+        bio = NULL;
+    }
+
+    /* file is closed when BIO is free'd */
+    return bio;
+#else
+    (void)filename;
+    (void)mode;
+    return NULL;
+#endif /* NO_FILESYSTEM */
+}
+
+
+#ifndef NO_DH
+WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x,
+        pem_password_cb *cb, void *u)
+{
+#ifndef NO_FILESYSTEM
+    WOLFSSL_DH* localDh = NULL;
+    unsigned char* mem  = NULL;
+    word32 size;
+    long   sz;
+    int    ret;
+    DerBuffer *der = NULL;
+    byte*  p = NULL;
+    byte*  g = NULL;
+    word32 pSz = MAX_DH_SIZE;
+    word32 gSz = MAX_DH_SIZE;
+    int    memAlloced = 0;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams");
+    (void)cb;
+    (void)u;
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument bio is NULL");
+        return NULL;
+    }
+
+    if (bio->type == WOLFSSL_BIO_MEMORY) {
+        /* Use the buffer directly. */
+        ret = wolfSSL_BIO_get_mem_data(bio, &mem);
+        if (mem == NULL || ret <= 0) {
+            WOLFSSL_MSG("Failed to get data from bio struct");
+            goto end;
+        }
+        size = ret;
+    }
+    else if (bio->type == WOLFSSL_BIO_FILE) {
+        /* Read whole file into a new buffer. */
+        XFSEEK(bio->file, 0, SEEK_END);
+        sz = XFTELL(bio->file);
+        XFSEEK(bio->file, 0, SEEK_SET);
+        if (sz <= 0L)
+            goto end;
+        mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM);
+        if (mem == NULL)
+            goto end;
+        memAlloced = 1;
+
+        if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0)
+            goto end;
+        size = (word32)sz;
+    }
+    else {
+        WOLFSSL_MSG("BIO type not supported for reading DH parameters");
+        goto end;
+    }
+
+    ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL);
+    if (ret != 0)
+        goto end;
+
+    /* Use the object passed in, otherwise allocate a new object */
+    if (x != NULL)
+        localDh = *x;
+    if (localDh == NULL) {
+        localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+        if (localDh == NULL)
+            goto end;
+        XMEMSET(localDh, 0, sizeof(WOLFSSL_DH));
+    }
+
+    /* Load data in manually */
+    p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    if (p == NULL || g == NULL)
+        goto end;
+
+    /* Extract the p and g as data from the DER encoded DH parameters. */
+    ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz);
+    if (ret != 0) {
+        if (x != NULL && localDh != *x)
+            XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL);
+        localDh = NULL;
+        goto end;
+    }
+
+    if (x != NULL)
+        *x = localDh;
+
+    /* Put p and g in as big numbers. */
+    if (localDh->p != NULL) {
+        wolfSSL_BN_free(localDh->p);
+        localDh->p = NULL;
+    }
+    if (localDh->g != NULL) {
+        wolfSSL_BN_free(localDh->g);
+        localDh->g = NULL;
+    }
+    localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL);
+    localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL);
+    if (localDh->p == NULL || localDh->g == NULL) {
+        if (x != NULL && localDh != *x)
+            wolfSSL_DH_free(localDh);
+        localDh = NULL;
+    }
+
+end:
+    if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM);
+    if (der != NULL) FreeDer(&der);
+    XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    return localDh;
+#else
+    (void)bio;
+    (void)x;
+    (void)cb;
+    (void)u;
+    return NULL;
+#endif
+}
+#endif
+
+#ifdef WOLFSSL_CERT_GEN
+
+#ifdef WOLFSSL_CERT_REQ
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()");
+
+    if (x == NULL || bp == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bp, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_REQ */
+
+
+/* writes the x509 from x to the WOLFSSL_BIO bp
+ *
+ * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
+ */
+int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+    if (bp == NULL || x == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(x, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bp, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert)
+{
+    byte* pem;
+    int   pemSz = 0;
+    const unsigned char* der;
+    int derSz;
+    int ret;
+
+    WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()");
+
+    if (bio == NULL || cert == NULL) {
+        WOLFSSL_MSG("NULL argument passed in");
+        return WOLFSSL_FAILURE;
+    }
+
+    der = wolfSSL_X509_get_der(cert, &derSz);
+    if (der == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* get PEM size */
+    pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE);
+    if (pemSz < 0) {
+        return WOLFSSL_FAILURE;
+    }
+
+    /* create PEM buffer and convert from DER */
+    pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (pem == NULL) {
+        return WOLFSSL_FAILURE;
+    }
+    if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
+        XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return WOLFSSL_FAILURE;
+    }
+
+    /* write the PEM to BIO */
+    ret = wolfSSL_BIO_write(bio, pem, pemSz);
+    XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret <= 0) return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_DH)
+/* Intialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */
+long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
+{
+    int pSz, gSz;
+    byte *p, *g;
+    int ret=0;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
+
+    if(!ctx || !dh)
+        return BAD_FUNC_ARG;
+
+    /* Get needed size for p and g */
+    pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
+    gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
+
+    if(pSz <= 0 || gSz <= 0)
+        return WOLFSSL_FATAL_ERROR;
+
+    p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if(!p)
+        return MEMORY_E;
+
+    g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    if(!g) {
+        XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+        return MEMORY_E;
+    }
+
+    pSz = wolfSSL_BN_bn2bin(dh->p, p);
+    gSz = wolfSSL_BN_bn2bin(dh->g, g);
+
+    if(pSz >= 0 && gSz >= 0) /* Conversion successful */
+        ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+
+    XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+    XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+
+    return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR;
+}
+#endif /* OPENSSL_EXTRA && !NO_DH */
+
+
+/* returns the enum value associated with handshake state
+ *
+ * ssl the WOLFSSL structure to get state of
+ */
+int wolfSSL_get_state(const WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_state");
+
+    if (ssl == NULL) {
+        WOLFSSL_MSG("Null argument passed in");
+        return SSL_FAILURE;
+    }
+
+    return ssl->options.handShakeState;
+}
+#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)
+
+/* Returns the verifyCallback from the ssl structure if successful.
+Returns NULL otherwise. */
+VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_verify_callback()");
+    if (ssl) {
+        return ssl->verifyCallback;
+    }
+    return NULL;
+}
+
+/* Creates a new bio pair.
+Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1,
+                                         WOLFSSL_BIO **bio2_p, size_t writebuf2)
+{
+    WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL;
+    int ret = 1;
+
+    WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()");
+
+    if (bio1_p == NULL || bio2_p == NULL) {
+        WOLFSSL_MSG("Bad Function Argument");
+        return BAD_FUNC_ARG;
+    }
+
+    /* set up the new bio structures and write buf sizes */
+    if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+        WOLFSSL_MSG("Bio allocation failed");
+        ret = WOLFSSL_FAILURE;
+    }
+    if (ret) {
+        if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) {
+            WOLFSSL_MSG("Bio allocation failed");
+            ret = WOLFSSL_FAILURE;
+        }
+    }
+    if (ret && writebuf1) {
+        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) {
+            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+        }
+    }
+    if (ret && writebuf2) {
+        if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) {
+            WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure");
+        }
+    }
+
+    if (ret) {
+        if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) {
+            *bio1_p = bio1;
+            *bio2_p = bio2;
+        }
+    }
+    if (!ret) {
+        wolfSSL_BIO_free(bio1);
+        bio1 = NULL;
+        wolfSSL_BIO_free(bio2);
+        bio2 = NULL;
+    }
+    return ret;
+}
+
+
+#if !defined(NO_RSA)
+/* Converts an rsa key from a bio buffer into an internal rsa structure.
+Returns a pointer to the new WOLFSSL_RSA structure. */
+WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+    const unsigned char* bioMem = NULL;
+    int bioMemSz = 0;
+    WOLFSSL_RSA* key = NULL;
+    unsigned char maxKeyBuf[4096];
+    unsigned char* bufPtr = NULL;
+    unsigned char* extraBioMem = NULL;
+    int extraBioMemSz = 0;
+    int derLength = 0;
+    int j = 0, i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()");
+
+    if (bio == NULL) {
+        WOLFSSL_MSG("Bad Function Argument");
+        return NULL;
+    }
+    (void)out;
+
+    bioMemSz = wolfSSL_BIO_pending(bio);
+    if (bioMemSz <= 0) {
+        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+        return NULL;
+    }
+
+    bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (bioMem == NULL) {
+        WOLFSSL_MSG("Malloc failure");
+        return NULL;
+    }
+
+    bufPtr = maxKeyBuf;
+    if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) {
+        if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMem, bioMemSz)) == NULL) {
+            XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return NULL;
+        }
+
+        /* This function is used to get the total length of the rsa key. */
+        derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr);
+
+        /* Write extra data back into bio object if necessary. */
+        extraBioMemSz = (bioMemSz - derLength);
+        if (extraBioMemSz > 0) {
+            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (extraBioMem == NULL) {
+                WOLFSSL_MSG("Malloc failure");;
+                XFREE((unsigned char*)extraBioMem, bio->heap, 
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE((unsigned char*)bioMem, bio->heap, 
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+
+            for (i = derLength; i < bioMemSz; i++) {
+                *(extraBioMem + j) = *(bioMem + i);
+                j++;
+            }
+
+            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+            if (wolfSSL_BIO_pending(bio) <= 0) {
+                WOLFSSL_MSG("Failed to write memory to bio");
+                XFREE((unsigned char*)extraBioMem, bio->heap, 
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE((unsigned char*)bioMem, bio->heap, 
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+            XFREE((unsigned char*)extraBioMem, bio->heap, 
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        if (out != NULL && key != NULL) {
+            *out = key;
+        }
+    }
+    XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return key;
+}
+#endif
+
+
+/* Adds the ASN1 certificate to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, 
+                                                       const unsigned char *der)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()");
+    if (der != NULL && ctx != NULL) {
+        if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, 
+                                      WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
+            return WOLFSSL_SUCCESS;
+        }
+
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+#if !defined(NO_RSA) && !defined(HAVE_FAST_RSA)
+/* Adds the rsa private key to the user ctx.
+Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/
+int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
+{
+    int ret;
+    int derSize;
+    unsigned char maxDerBuf[4096];
+    unsigned char* key = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()");
+
+    if (ctx == NULL || rsa == NULL) {
+        WOLFSSL_MSG("one or more inputs were NULL");
+        return BAD_FUNC_ARG;
+    }
+    key = maxDerBuf;
+    /* convert RSA struct to der encoded buffer and get the size */
+    if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) {
+        WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
+        return WOLFSSL_FAILURE;
+    }
+    ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf, 
+                                                    derSize, SSL_FILETYPE_ASN1);
+    if (ret != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
+        return WOLFSSL_FAILURE;
+    }
+    return ret;
+}
+#endif /* NO_RSA && !HAVE_FAST_RSA */
+
+
+/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
+Returns pointer to private EVP_PKEY struct upon success, NULL if there
+is a failure.*/
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
+                                                         WOLFSSL_EVP_PKEY** out)
+{
+    unsigned char* mem = NULL;
+    int memSz = 0;
+    WOLFSSL_EVP_PKEY* key = NULL;
+    int i = 0, j = 0;
+    unsigned char* extraBioMem = NULL;
+    int extraBioMemSz = 0;
+    int derLength = 0;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()");
+
+    if (bio == NULL) {
+        return NULL;
+    }
+    (void)out;
+
+    memSz = wolfSSL_BIO_pending(bio);
+    if (memSz <= 0) {
+        WOLFSSL_MSG("wolfSSL_BIO_pending() failure");
+        return NULL;
+    }
+
+    mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (mem == NULL) {
+        WOLFSSL_MSG("Malloc failure");
+        return NULL;
+    }
+
+    if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
+        /* Determines key type and returns the new private EVP_PKEY object */
+        if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) {
+            WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
+            XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            return NULL;
+        }
+
+        /* Write extra data back into bio object if necessary. */
+        derLength = key->pkey_sz;
+        extraBioMemSz = (memSz - derLength);
+        if (extraBioMemSz > 0) {
+            extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+            if (extraBioMem == NULL) {
+                WOLFSSL_MSG("Malloc failure");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+
+            for (i = derLength; i < memSz; i++) {
+                *(extraBioMem + j) = *(mem + i);
+                j++;
+            }
+
+            wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
+            if (wolfSSL_BIO_pending(bio) <= 0) {
+                WOLFSSL_MSG("Failed to write memory to bio");
+                XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                return NULL;
+            }
+            XFREE((unsigned char*)extraBioMem, bio->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        if (out != NULL && key != NULL) {
+            *out = key;
+        }
+    }
+    XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    return key;
+}
+
+
+/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ * on fail */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
+                                                  unsigned char** in, long inSz)
+{
+    WOLFSSL_EVP_PKEY* pkey = NULL;
+    const unsigned char* mem;
+    long memSz = inSz;
+
+    WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()");
+
+    if (in == NULL || inSz < 0) {
+        WOLFSSL_MSG("Bad argument");
+        return NULL;
+    }
+    mem = *in;
+
+    #if !defined(NO_RSA)
+    {
+        RsaKey rsa;
+        word32 keyIdx = 0;
+
+        /* test if RSA key */
+        if (wc_InitRsaKey(&rsa, NULL) == 0 &&
+            wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) {
+            wc_FreeRsaKey(&rsa);
+            pkey = wolfSSL_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL,
+                        DYNAMIC_TYPE_PRIVATE_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_RSA;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+
+                pkey->ownRsa = 1;
+                pkey->rsa = wolfSSL_RSA_new();
+                if (pkey->rsa == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                if (wolfSSL_RSA_LoadDer_ex(pkey->rsa,
+                            (const unsigned char*)pkey->pkey.ptr,
+                            pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+
+                return pkey;
+            }
+        }
+        wc_FreeRsaKey(&rsa);
+    }
+    #endif /* NO_RSA */
+
+    #ifdef HAVE_ECC
+    {
+        word32  keyIdx = 0;
+        ecc_key ecc;
+
+        /* test if ecc key */
+        if (wc_ecc_init(&ecc) == 0 &&
+            wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) {
+            wc_ecc_free(&ecc);
+            pkey = wolfSSL_PKEY_new();
+            if (pkey != NULL) {
+                pkey->pkey_sz = keyIdx;
+                pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+                        DYNAMIC_TYPE_PRIVATE_KEY);
+                if (pkey->pkey.ptr == NULL) {
+                    wolfSSL_EVP_PKEY_free(pkey);
+                    return NULL;
+                }
+                XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+                pkey->type = EVP_PKEY_EC;
+                if (out != NULL) {
+                    *out = pkey;
+                }
+                return pkey;
+            }
+        }
+        wc_ecc_free(&ecc);
+    }
+    #endif /* HAVE_ECC */
+    return pkey;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
+
+
+/* stunnel compatibility functions*/
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) \
+                          || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)))
+void wolfSSL_ERR_remove_thread_state(void* pid)
+{
+    (void) pid;
+    return;
+}
+
+#ifndef NO_FILESYSTEM
+/***TBD ***/
+void wolfSSL_print_all_errors_fp(XFILE *fp)
+{
+    (void)fp;
+}
+#endif
+
+int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data");
+#ifdef HAVE_EX_DATA
+    if(session != NULL && idx < MAX_EX_DATA) {
+        session->ex_data[idx] = data;
+        return WOLFSSL_SUCCESS;
+    }
+#else
+    (void)session;
+    (void)idx;
+    (void)data;
+#endif
+    return WOLFSSL_FAILURE;
+}
+
+
+int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1,
+       void* cb2, CRYPTO_free_func* cb3)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index");
+    (void)idx;
+    (void)cb1;
+    (void)cb2;
+    (void)cb3;
+    if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) {
+        return 0;
+    }
+    else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) {
+        return 1;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data");
+#ifdef HAVE_EX_DATA
+    if (session != NULL && idx < MAX_EX_DATA && idx >= 0)
+        return session->ex_data[idx];
+#else
+    (void)session;
+    (void)idx;
+#endif
+    return NULL;
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+                                void *(*r) (void *, size_t, const char *,
+                                            int), void (*f) (void *))
+{
+    (void) m;
+    (void) r;
+    (void) f;
+    WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions");
+    WOLFSSL_STUB("CRYPTO_set_mem_ex_functions");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+
+void wolfSSL_CRYPTO_cleanup_all_ex_data(void){
+    WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data");
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
+                           void (*callback) (int, int, void *), void *cb_arg)
+{
+    (void)prime_len;
+    (void)generator;
+    (void)callback;
+    (void)cb_arg;
+    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters");
+    WOLFSSL_STUB("DH_generate_parameters");
+
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator,
+                           void (*callback) (int, int, void *))
+{
+    (void)prime_len;
+    (void)generator;
+    (void)callback;
+    (void)dh;
+    WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex");
+    WOLFSSL_STUB("DH_generate_parameters_ex");
+
+    return -1;
+}
+#endif
+
+void wolfSSL_ERR_load_crypto_strings(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
+    /* Do nothing */
+    return;
+}
+
+#ifndef NO_WOLFSSL_STUB
+unsigned long wolfSSL_ERR_peek_last_error(void)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    {
+        int ret;
+
+        if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
+            WOLFSSL_MSG("Issue peeking at error node in queue");
+            return 0;
+        }
+        if (ret == -ASN_NO_PEM_HEADER)
+            return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode(void)
+{
+    WOLFSSL_ENTER("wolfSSL_FIPS_mode");
+    WOLFSSL_STUB("FIPS_mode");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_FIPS_mode_set(int r)
+{
+    (void)r;
+    WOLFSSL_ENTER("wolfSSL_FIPS_mode_set");
+    WOLFSSL_STUB("FIPS_mode_set");
+
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_RAND_set_rand_method(const void *meth)
+{
+    (void) meth;
+    WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method");
+    WOLFSSL_STUB("RAND_set_rand_method");
+
+    /* if implemented RAND_bytes and RAND_pseudo_bytes need updated
+     * those two functions will call the respective functions from meth */
+    return SSL_FAILURE;
+}
+#endif
+
+int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
+{
+    int ret = WOLFSSL_FAILURE;
+    WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
+    if(c != NULL && c->ssl != NULL) {
+        ret = 8 * c->ssl->specs.key_size;
+        if(alg_bits != NULL) {
+            *alg_bits = ret;
+        }
+    }
+    return ret;
+}
+
+int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num");
+
+    if (s == NULL)
+        return -1;
+    return (int)s->num;
+}
+
+
+int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s)
+{
+    WOLFSSL_ENTER("wolfSSL_sk_X509_num");
+
+    if (s == NULL)
+        return -1;
+    return (int)s->num;
+}
+
+int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
+                int indent, unsigned long flags)
+{
+    int i;
+    (void)flags;
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex");
+
+    for (i = 0; i < indent; i++) {
+        if (wolfSSL_BIO_write(bio, " ", 1) != 1)
+            return WOLFSSL_FAILURE;
+    }
+
+    if (flags == XN_FLAG_RFC2253) {
+        if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2)
+                                                                != name->sz - 2)
+            return WOLFSSL_FAILURE;
+    }
+    else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz)
+        return WOLFSSL_FAILURE;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)
+{
+    (void)x;
+    WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr");
+    WOLFSSL_STUB("X509_get0_pubkey_bitstr");
+
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+{
+    (void)ctx;
+    (void)session;
+    WOLFSSL_ENTER("wolfSSL_CTX_add_session");
+    WOLFSSL_STUB("SSL_CTX_add_session");
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+
+int wolfSSL_version(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_version");
+    if (ssl->version.major == SSLv3_MAJOR) {
+        switch (ssl->version.minor) {
+            case SSLv3_MINOR :
+                return SSL3_VERSION;
+            case TLSv1_MINOR :
+            case TLSv1_1_MINOR :
+            case TLSv1_2_MINOR :
+            case TLSv1_3_MINOR :
+                return TLS1_VERSION;
+            default:
+                return WOLFSSL_FAILURE;
+        }
+    }
+    else if (ssl->version.major == DTLS_MAJOR) {
+        switch (ssl->version.minor) {
+            case DTLS_MINOR :
+            case DTLSv1_2_MINOR :
+                return DTLS1_VERSION;
+            default:
+                return WOLFSSL_FAILURE;
+        }
+    }
+    return WOLFSSL_FAILURE;
+}
+
+
+WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
+    return ssl->ctx;
+}
+
+int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz");
+    if(!name)
+        return -1;
+    return name->sz;
+}
+
+#ifdef HAVE_SNI
+int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
+{
+    int ret;
+    WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name");
+    ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
+            host_name, (word16)XSTRLEN(host_name));
+    WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret);
+    return ret;
+}
+
+
+#ifndef NO_WOLFSSL_SERVER
+const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
+{
+    void * serverName = NULL;
+    if (ssl == NULL)
+        return NULL;
+    TLSX_SNI_GetRequest(ssl->extensions, type, &serverName);
+    return (const char *)serverName;
+}
+#endif /* NO_WOLFSSL_SERVER */
+#endif /* HAVE_SNI */
+
+WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
+{
+    if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
+        return ssl->ctx;
+    return NULL;
+}
+
+
+VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
+    if(ctx)
+        return ctx->verifyCallback;
+    return NULL;
+}
+
+
+void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
+    if (ctx)
+        ctx->sniRecvCb = cb;
+}
+
+int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
+                                               CallbackSniRecv cb)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
+    if (ctx) {
+        ctx->sniRecvCb = cb;
+        return 1;
+    }
+    return 0;
+}
+
+void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
+    if (ctx)
+        ctx->sniRecvCbArg = arg;
+}
+
+void wolfSSL_ERR_load_BIO_strings(void) {
+    WOLFSSL_ENTER("ERR_load_BIO_strings");
+    /* do nothing */
+}
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*))
+{
+    WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
+    WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
+    (void)threadid_func;
+    return;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
+{
+    WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
+    WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
+    (void)id;
+    (void)val;
+    return;
+}
+#endif
+
+
+#ifndef NO_WOLFSSL_STUB
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx,
+                                                WOLFSSL_X509_NAME* name)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs");
+    WOLFSSL_STUB("X509_STORE_get1_certs");
+    (void)ctx;
+    (void)name;
+    return NULL;
+}
+#endif
+
+#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */
+
+
+#if defined(OPENSSL_ALL) || \
+    (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
+     defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY))
+
+const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen)
+{
+    WOLFSSL_ENTER("wolfSSL_SESSION_get_id");
+    if(!sess || !idLen) {
+        WOLFSSL_MSG("Bad func args. Please provide idLen");
+        return NULL;
+    }
+    *idLen = sess->sessionIDSz;
+    return sess->sessionID;
+}
+#endif
+
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
+
+int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx)
+{
+    int mode = 0;
+    WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
+
+    if(!ctx)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ctx->verifyPeer)
+        mode |= WOLFSSL_VERIFY_PEER;
+    else if (ctx->verifyNone)
+        mode |= WOLFSSL_VERIFY_NONE;
+
+    if (ctx->failNoCert)
+        mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+    if (ctx->failNoCertxPSK)
+        mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK;
+
+    WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
+    return mode;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
+        pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        curve25519_key key;
+
+        if (wc_curve25519_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_init failed");
+        else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_make_key failed");
+        /* export key pair */
+        else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
+                                                 pubSz, EC25519_LITTLE_ENDIAN)
+                 != MP_OKAY)
+            WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_curve25519_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ */
+int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
+                               const unsigned char *priv, unsigned int privSz,
+                               const unsigned char *pub, unsigned int pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) shared;
+    (void) sharedSz;
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    curve25519_key privkey, pubkey;
+
+    WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
+
+    if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
+        priv == NULL || privSz < CURVE25519_KEYSIZE ||
+        pub == NULL || pubSz < CURVE25519_KEYSIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import private key */
+    if (wc_curve25519_init(&privkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init privkey failed");
+        return ret;
+    }
+    if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
+                                        EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
+        wc_curve25519_free(&privkey);
+        return ret;
+    }
+
+    /* import public key */
+    if (wc_curve25519_init(&pubkey) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init pubkey failed");
+        wc_curve25519_free(&privkey);
+        return ret;
+    }
+    if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
+                                       EC25519_LITTLE_ENDIAN) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
+        wc_curve25519_free(&privkey);
+        wc_curve25519_free(&pubkey);
+        return ret;
+    }
+
+    if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
+                                       shared, sharedSz,
+                                       EC25519_LITTLE_ENDIAN) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_curve25519_free(&privkey);
+    wc_curve25519_free(&pubkey);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
+/* return 1 if success, 0 if error
+ * output keys are little endian format
+ */
+int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
+                                 unsigned char *pub, unsigned int *pubSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) priv;
+    (void) privSz;
+    (void) pub;
+    (void) pubSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    int ret = WOLFSSL_FAILURE;
+    int initTmpRng = 0;
+    WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    WC_RNG *tmpRNG = NULL;
+#else
+    WC_RNG tmpRNG[1];
+#endif
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
+
+    if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
+        pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+    if (tmpRNG == NULL)
+        return WOLFSSL_FATAL_ERROR;
+#endif
+    if (wc_InitRng(tmpRNG) == 0) {
+        rng = tmpRNG;
+        initTmpRng = 1;
+    }
+    else {
+        WOLFSSL_MSG("Bad RNG Init, trying global");
+        if (initGlobalRNG == 0)
+            WOLFSSL_MSG("Global RNG no Init");
+        else
+            rng = &globalRNG;
+    }
+
+    if (rng) {
+        ed25519_key key;
+
+        if (wc_ed25519_init(&key) != MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_init failed");
+        else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_make_key failed");
+        /* export private key */
+        else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
+            WOLFSSL_MSG("wc_ed25519_export_key failed");
+        else
+            ret = WOLFSSL_SUCCESS;
+
+        wc_ed25519_free(&key);
+    }
+
+    if (initTmpRng)
+        wc_FreeRng(tmpRNG);
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG);
+#endif
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * priv is a buffer containing private and public part of key
+ */
+int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
+                         const unsigned char *priv, unsigned int privSz,
+                         unsigned char *sig, unsigned int *sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) priv;
+    (void) privSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed25519_key key;
+    int ret = WOLFSSL_FAILURE;
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_sign");
+
+    if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
+        msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed25519_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init failed");
+        return ret;
+    }
+    if (wc_ed25519_import_private_key(priv, privSz/2,
+                                      priv+(privSz/2), ED25519_PUB_KEY_SIZE,
+                                      &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed25519_import_private failed");
+        wc_ed25519_free(&key);
+        return ret;
+    }
+
+    if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
+        WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed25519_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+/* return 1 if success, 0 if error
+ * input and output keys are little endian format
+ * pub is a buffer containing public part of key
+ */
+int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
+                           const unsigned char *pub, unsigned int pubSz,
+                           const unsigned char *sig, unsigned int sigSz)
+{
+#ifndef WOLFSSL_KEY_GEN
+    WOLFSSL_MSG("No Key Gen built in");
+    (void) msg;
+    (void) msgSz;
+    (void) pub;
+    (void) pubSz;
+    (void) sig;
+    (void) sigSz;
+    return WOLFSSL_FAILURE;
+#else /* WOLFSSL_KEY_GEN */
+    ed25519_key key;
+    int ret = WOLFSSL_FAILURE, check = 0;
+
+    WOLFSSL_ENTER("wolfSSL_ED25519_verify");
+
+    if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
+        msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
+        WOLFSSL_MSG("Bad arguments");
+        return WOLFSSL_FAILURE;
+    }
+
+    /* import key */
+    if (wc_ed25519_init(&key) != MP_OKAY) {
+        WOLFSSL_MSG("wc_curve25519_init failed");
+        return ret;
+    }
+    if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
+        WOLFSSL_MSG("wc_ed25519_import_public failed");
+        wc_ed25519_free(&key);
+        return ret;
+    }
+
+    if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
+                                     &check, &key)) != MP_OKAY) {
+        WOLFSSL_MSG("wc_ed25519_verify_msg failed");
+    }
+    else if (!check)
+        WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
+    else
+        ret = WOLFSSL_SUCCESS;
+
+    wc_ed25519_free(&key);
+
+    return ret;
+#endif /* WOLFSSL_KEY_GEN */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
+
+#ifdef WOLFSSL_JNI
+
+int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
+{
+    WOLFSSL_ENTER("wolfSSL_set_jobject");
+    if (ssl != NULL)
+    {
+        ssl->jObjectRef = objPtr;
+        return WOLFSSL_SUCCESS;
+    }
+    return WOLFSSL_FAILURE;
+}
+
+void* wolfSSL_get_jobject(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_get_jobject");
+    if (ssl != NULL)
+        return ssl->jObjectRef;
+    return NULL;
+}
+
+#endif /* WOLFSSL_JNI */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
+    WOLF_EVENT_FLAG flags, int* eventCount)
+{
+    if (ctx == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
+                                        events, maxEvents, flags, eventCount);
+}
+
+int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
+{
+    int ret, eventCount = 0;
+    WOLF_EVENT* events[1];
+
+    if (ssl == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl,
+        events, sizeof(events)/sizeof(events), flags, &eventCount);
+    if (ret == 0) {
+        ret = eventCount;
+    }
+
+    return ret;
+}
+
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef OPENSSL_EXTRA
+unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
+                                               const char **data, int *flags)
+{
+    WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
+
+    (void)line;
+    (void)file;
+
+    /* No data or flags stored - error display only in Nginx. */
+    if (data != NULL) {
+        *data = "";
+    }
+    if (flags != NULL) {
+        *flags = 0;
+    }
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_MYSQL_COMPATIBLE)
+    {
+        int ret = 0;
+
+        while (1) {
+            if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) {
+                WOLFSSL_MSG("Issue peeking at error node in queue");
+                return 0;
+            }
+            ret = -ret;
+
+            if (ret == ASN_NO_PEM_HEADER)
+                return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE;
+            if (ret != WANT_READ && ret != WANT_WRITE &&
+                    ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN &&
+                    ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E)
+                break;
+
+            wc_RemoveErrorNode(-1);
+        }
+
+        return (unsigned long)ret;
+    }
+#else
+    return (unsigned long)(0 - NOT_COMPILED_IN);
+#endif
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+#ifndef NO_WOLFSSL_STUB
+WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
+{
+    (void)ssl;
+    WOLFSSL_STUB("wolfSSL_get_ciphers_compat");
+    return NULL;
+}
+#endif
+
+#ifndef NO_WOLFSSL_STUB
+void wolfSSL_OPENSSL_config(char *config_name)
+{
+    (void)config_name;
+    WOLFSSL_STUB("OPENSSL_config");
+}
+#endif
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
+int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c)
+{
+    static int x509_idx = 0;
+
+    WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index");
+    (void)idx;
+    (void)arg;
+    (void)a;
+    (void)b;
+    (void)c;
+
+    return x509_idx++;
+}
+
+void *wolfSSL_X509_get_ex_data(X509 *x509, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_get_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) {
+        return x509->ex_data[idx];
+    }
+    #else
+    (void)x509;
+    (void)idx;
+    #endif
+    return NULL;
+}
+int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_set_ex_data");
+    #ifdef HAVE_EX_DATA
+    if (x509 != NULL && idx < MAX_EX_DATA)
+    {
+        x509->ex_data[idx] = data;
+        return WOLFSSL_SUCCESS;
+    }
+    #else
+    (void)x509;
+    (void)idx;
+    (void)data;
+    #endif
+    return WOLFSSL_FAILURE;
+}
+int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
+        const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_NAME_digest");
+
+    if (name == NULL || type == NULL)
+        return WOLFSSL_FAILURE;
+
+#ifndef NO_FILESYSTEM
+    return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName,
+                              name->fullName.fullNameLen, md, len, type, NULL);
+#else
+    (void)md;
+    (void)len;
+    return NOT_COMPILED_IN;
+#endif
+}
+
+long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout");
+
+    if (ctx == NULL)
+        return 0;
+
+    return ctx->timeout;
+}
+
+#ifdef HAVE_ECC
+int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
+
+    if (ctx == NULL || ecdh == NULL)
+        return BAD_FUNC_ARG;
+
+    ctx->ecdhCurveOID = ecdh->group->curve_oid;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+/* Assumes that the session passed in is from the cache. */
+int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session");
+
+    if (ctx == NULL || s == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef HAVE_EXT_CACHE
+    if (!ctx->internalCacheOff)
+#endif
+    {
+        /* Don't remove session just timeout session. */
+        s->timeout = 0;
+    }
+
+#ifdef HAVE_EXT_CACHE
+    if (ctx->rem_sess_cb != NULL)
+        ctx->rem_sess_cb(ctx, s);
+#endif
+
+    return 0;
+}
+
+BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_get_rbio");
+    (void)s;
+    /* Nginx sets the buffer size if the read BIO is different to write BIO.
+     * The setting buffer size doesn't do anything so return NULL for both.
+     */
+    return NULL;
+}
+BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_get_wbio");
+    (void)s;
+    /* Nginx sets the buffer size if the read BIO is different to write BIO.
+     * The setting buffer size doesn't do anything so return NULL for both.
+     */
+    return NULL;
+}
+
+int wolfSSL_SSL_do_handshake(WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_do_handshake");
+
+    if (s == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (s->options.side == WOLFSSL_CLIENT_END) {
+    #ifndef NO_WOLFSSL_CLIENT
+        return wolfSSL_connect(s);
+    #else
+        WOLFSSL_MSG("Client not compiled in");
+        return WOLFSSL_FAILURE;
+    #endif
+    }
+
+#ifndef NO_WOLFSSL_SERVER
+    return wolfSSL_accept(s);
+#else
+    WOLFSSL_MSG("Server not compiled in");
+    return WOLFSSL_FAILURE;
+#endif
+}
+
+int wolfSSL_SSL_in_init(WOLFSSL *s)
+{
+    WOLFSSL_ENTER("wolfSSL_SSL_in_init");
+
+    if (s == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (s->options.side == WOLFSSL_CLIENT_END)
+        return s->options.connectState < SECOND_REPLY_DONE;
+    return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
+
+#ifndef NO_SESSION_CACHE
+
+WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl)
+{
+    WOLFSSL_SESSION *session;
+
+    WOLFSSL_ENTER("wolfSSL_SSL_get0_session");
+
+    if (ssl == NULL) {
+        return NULL;
+    }
+
+    session = wolfSSL_get_session((WOLFSSL*)ssl);
+
+#ifdef HAVE_EXT_CACHE
+    ((WOLFSSL*)ssl)->extSession = session;
+#endif
+
+    return session;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen,
+                    unsigned int flags, char **peername)
+{
+    int         ret;
+    DecodedCert dCert;
+
+    WOLFSSL_ENTER("wolfSSL_X509_check_host");
+
+    /* flags and peername not needed for Nginx. */
+    (void)flags;
+    (void)peername;
+
+    if (flags == WOLFSSL_NO_WILDCARDS) {
+        WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented");
+        return WOLFSSL_FAILURE;
+    }
+
+    InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL);
+    ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL);
+    if (ret != 0)
+        return WOLFSSL_FAILURE;
+
+    ret = CheckHostName(&dCert, (char *)chk, chklen);
+    FreeDecodedCert(&dCert);
+    if (ret != 0)
+        return WOLFSSL_FAILURE;
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
+{
+    static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+    int    i;
+    word32 j;
+    word32 len = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER");
+
+    if (bp == NULL || a == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Skip ASN.1 INTEGER (type) byte. */
+    i = 1;
+    /* When indefinte length, can't determine length with data available. */
+    if (a->data[i] == 0x80)
+        return 0;
+    /* One length byte if less than 0x80. */
+    if (a->data[i] < 0x80)
+        len = a->data[i++];
+    /* Multiple length byte if greater than 0x80. */
+    else if (a->data[i] > 0x80) {
+        switch (a->data[i++] - 0x80) {
+            case 4:
+                len |= a->data[i++] << 24;
+                FALL_THROUGH;
+            case 3:
+                len |= a->data[i++] << 16;
+                FALL_THROUGH;
+            case 2:
+                len |= a->data[i++] <<  8;
+                FALL_THROUGH;
+            case 1:
+                len |= a->data[i++];
+                break;
+            default:
+                /* Not supporting greater than 4 bytes of length. */
+                return 0;
+        }
+    }
+
+    /* Zero length integer is the value zero. */
+    if (len == 0) {
+        wolfSSL_BIO_write(bp, "00", 2);
+        return 2;
+    }
+
+    /* Don't do negative - just write out every byte. */
+    for (j = 0; j < len; i++,j++) {
+        wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1);
+        wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1);
+    }
+
+    /* Two nibbles written for each byte. */
+    return len * 2;
+}
+
+
+#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+/* Expected return values from implementations of OpenSSL ticket key callback.
+ */
+#define TICKET_KEY_CB_RET_FAILURE    -1
+#define TICKET_KEY_CB_RET_NOT_FOUND   0
+#define TICKET_KEY_CB_RET_OK          1
+#define TICKET_KEY_CB_RET_RENEW       2
+
+/* The ticket key callback as used in OpenSSL is stored here. */
+static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL;
+
+/* Implementation of session ticket encryption/decryption using OpenSSL
+ * callback to initialize the cipher and HMAC.
+ *
+ * ssl           The SSL/TLS object.
+ * keyName       The key name - used to identify the key to be used.
+ * iv            The IV to use.
+ * mac           The MAC of the encrypted data.
+ * enc           Encrypt ticket.
+ * encTicket     The ticket data.
+ * encTicketLen  The length of the ticket data.
+ * encLen        The encrypted/decrypted ticket length - output length.
+ * ctx           Ignored. Application specific data.
+ * returns WOLFSSL_TICKET_RET_OK to indicate success,
+ *         WOLFSSL_TICKET_RET_CREATE if a new ticket is required and
+ *         WOLFSSL_TICKET_RET_FATAL on error.
+ */
+static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
+                                  unsigned char keyName[WOLFSSL_TICKET_NAME_SZ],
+                                  unsigned char iv[WOLFSSL_TICKET_IV_SZ],
+                                  unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
+                                  int enc, unsigned char* encTicket,
+                                  int encTicketLen, int* encLen, void* ctx)
+{
+    byte                    digest[WC_MAX_DIGEST_SIZE];
+    WOLFSSL_EVP_CIPHER_CTX  evpCtx;
+    WOLFSSL_HMAC_CTX        hmacCtx;
+    unsigned int            mdSz = 0;
+    int                     len = 0;
+    int                     ret = WOLFSSL_TICKET_RET_FATAL;
+    int                     res;
+
+    (void)ctx;
+
+    if (ticketKeyCb == NULL)
+        return WOLFSSL_TICKET_RET_FATAL;
+
+    wolfSSL_EVP_CIPHER_CTX_init(&evpCtx);
+    /* Initialize the cipher and HMAC. */
+    res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
+    if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW)
+        return WOLFSSL_TICKET_RET_FATAL;
+
+    if (enc)
+    {
+        /* Encrypt in place. */
+        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+                                      encTicket, encTicketLen))
+            goto end;
+        encTicketLen = len;
+        if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+            goto end;
+        /* Total length of encrypted data. */
+        encTicketLen += len;
+        *encLen = encTicketLen;
+
+        /* HMAC the encrypted data into the parameter 'mac'. */
+        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+            goto end;
+#ifdef WOLFSSL_SHA512
+        /* Check for SHA512, which would overrun the mac buffer */
+        if (hmacCtx.hmac.macType == WC_SHA512)
+            goto end;
+#endif
+        if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz))
+            goto end;
+    }
+    else
+    {
+        /* HMAC the encrypted data and compare it to the passed in data. */
+        if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen))
+            goto end;
+        if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz))
+            goto end;
+        if (XMEMCMP(mac, digest, mdSz) != 0)
+            goto end;
+
+        /* Decrypt the ticket data in place. */
+        if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len,
+                                      encTicket, encTicketLen))
+            goto end;
+        encTicketLen = len;
+        if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len))
+            goto end;
+        /* Total length of decrypted data. */
+        *encLen = encTicketLen + len;
+    }
+
+    ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE :
+                                             WOLFSSL_TICKET_RET_OK;
+end:
+    return ret;
+}
+
+/* Set the callback to use when encrypting/decrypting tickets.
+ *
+ * ctx  The SSL/TLS context object.
+ * cb   The OpenSSL session ticket callback.
+ * returns WOLFSSL_SUCCESS to indicate success.
+ */
+int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)(
+    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc))
+{
+    /* Store callback in a global. */
+    ticketKeyCb = cb;
+    /* Set the ticket encryption callback to be a wrapper around OpenSSL
+     * callback.
+     */
+    ctx->ticketEncCb = wolfSSL_TicketKeyCb;
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_SESSION_TICKET */
+
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
+    OPENSSL_EXTRA || HAVE_LIGHTY */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_OCSP
+/* Not an OpenSSL API. */
+int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
+{
+    *response = ssl->ocspResp;
+    return ssl->ocspRespSz;
+}
+
+/* Not an OpenSSL API. */
+char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
+{
+    return ssl->url;
+}
+
+/* Not an OpenSSL API. */
+int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
+{
+    if (ssl == NULL)
+        return WOLFSSL_FAILURE;
+
+    ssl->url = url;
+    return WOLFSSL_SUCCESS;
+}
+#endif /* OCSP */
+#endif /* OPENSSL_ALL / WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+    defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain)
+{
+    word32         idx;
+    word32         length;
+    WOLFSSL_STACK* node;
+    WOLFSSL_STACK* last = NULL;
+
+    if (ctx == NULL || chain == NULL) {
+        chain = NULL;
+        return WOLFSSL_FAILURE;
+    }
+    if (ctx->x509Chain != NULL) {
+        *chain = ctx->x509Chain;
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* If there are no chains then success! */
+    *chain = NULL;
+    if (ctx->certChain == NULL || ctx->certChain->length == 0) {
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* Create a new stack of WOLFSSL_X509 object from chain buffer. */
+    for (idx = 0; idx < ctx->certChain->length; ) {
+        node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
+                                       DYNAMIC_TYPE_OPENSSL);
+        if (node == NULL)
+            return WOLFSSL_FAILURE;
+        node->next = NULL;
+
+        /* 3 byte length | X509 DER data */
+        ato24(ctx->certChain->buffer + idx, &length);
+        idx += 3;
+
+        /* Create a new X509 from DER encoded data. */
+        node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx,
+            length);
+        if (node->data.x509 == NULL) {
+            XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+            /* Return as much of the chain as we created. */
+            ctx->x509Chain = *chain;
+            return WOLFSSL_FAILURE;
+        }
+        idx += length;
+
+        /* Add object to the end of the stack. */
+        if (last == NULL) {
+            node->num = 1;
+            *chain = node;
+        }
+        else {
+            (*chain)->num++;
+            last->next = node;
+        }
+
+        last = node;
+    }
+
+    ctx->x509Chain = *chain;
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
+    int(*cb)(WOLFSSL*, void*))
+{
+    if (ctx == NULL || ctx->cm == NULL)
+        return WOLFSSL_FAILURE;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    /* Ensure stapling is on for callback to be used. */
+    wolfSSL_CTX_EnableOCSPStapling(ctx);
+
+    if (ctx->cm->ocsp_stapling == NULL)
+        return WOLFSSL_FAILURE;
+
+    ctx->cm->ocsp_stapling->statusCb = cb;
+#else
+    (void)cb;
+#endif
+
+    return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
+    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x)
+{
+    WOLFSSL_STACK* node;
+    Signer* ca = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    DecodedCert* cert = NULL;
+#else
+    DecodedCert  cert[1];
+#endif
+
+    if (issuer == NULL || ctx == NULL || x == NULL)
+        return WOLFSSL_FATAL_ERROR;
+
+    if (ctx->chain != NULL) {
+        for (node = ctx->chain; node != NULL; node = node->next) {
+            if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) {
+                *issuer = x;
+                return WOLFSSL_SUCCESS;
+            }
+        }
+    }
+
+
+#ifdef WOLFSSL_SMALL_STACK
+    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+    if (cert == NULL)
+        return WOLFSSL_FAILURE;
+#endif
+
+    /* Use existing CA retrieval APIs that use DecodedCert. */
+    InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL);
+    if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) {
+    #ifndef NO_SKID
+        if (cert->extAuthKeyIdSet)
+            ca = GetCA(ctx->store->cm, cert->extAuthKeyId);
+        if (ca == NULL)
+            ca = GetCAByName(ctx->store->cm, cert->issuerHash);
+    #else /* NO_SKID */
+        ca = GetCA(ctx->store->cm, cert->issuerHash);
+    #endif /* NO SKID */
+    }
+    FreeDecodedCert(cert);
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+#endif
+
+    if (ca == NULL)
+        return WOLFSSL_FAILURE;
+
+    *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0,
+        DYNAMIC_TYPE_OPENSSL);
+    if (*issuer == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* Create an empty certificate as CA doesn't have a certificate. */
+    XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509));
+    (*issuer)->dynamicMemory = 1;
+#ifdef WOLFSSL_SIGNER_DER_CERT
+    if (AllocDer(&(*issuer)->derCert, ca->derCert->length, ca->derCert->type,
+                                                                   NULL) == 0) {
+        XMEMCPY((*issuer)->derCert->buffer, ca->derCert->buffer,
+                                                           ca->derCert->length);
+    }
+    else {
+        XFREE(*issuer, 0, DYNAMIC_TYPE_OPENSSL);
+        return WOLFSSL_FAILURE;
+    }
+#endif
+
+    /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */
+
+    return WOLFSSL_SUCCESS;
+}
+
+void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
+{
+    WOLFSSL_STACK *curr;
+
+    while (sk != NULL) {
+        curr = sk;
+        sk = sk->next;
+
+        XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
+{
+    WOLFSSL_STACK* list = NULL;
+    char*          url;
+
+    if (x->authInfoSz == 0)
+        return NULL;
+
+    list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1,
+                                   NULL, DYNAMIC_TYPE_OPENSSL);
+    if (list == NULL)
+        return NULL;
+
+    url = (char*)list;
+    url += sizeof(WOLFSSL_STACK);
+    XMEMCPY(url, x->authInfo, x->authInfoSz);
+    url[x->authInfoSz] = '\0';
+
+    list->data.string = url;
+    list->next = NULL;
+
+    return list;
+}
+
+int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
+{
+    WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
+    WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer);
+
+    if (issuerName == NULL || subjectName == NULL)
+        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+
+    /* Literal matching of encoded names and key ids. */
+    if (issuerName->sz != subjectName->sz ||
+           XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) {
+        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+    }
+
+    if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) {
+        if (subject->authKeyIdSz != issuer->subjKeyIdSz ||
+                XMEMCMP(subject->authKeyId, issuer->subjKeyId,
+                        issuer->subjKeyIdSz) != 0) {
+            return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+        }
+    }
+
+    return X509_V_OK;
+}
+
+WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x)
+{
+    return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length);
+}
+
+char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings,
+    int idx)
+{
+    for (; idx > 0 && strings != NULL; idx--)
+        strings = strings->next;
+    if (strings == NULL)
+        return NULL;
+    return strings->data.string;
+}
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#ifdef HAVE_ALPN
+void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data,
+                                unsigned int *len)
+{
+    word16 nameLen;
+
+    if (ssl != NULL && data != NULL && len != NULL) {
+        TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
+        *len = nameLen;
+    }
+}
+
+int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
+                              const unsigned char *in, unsigned int inLen,
+                              const unsigned char *clientNames,
+                              unsigned int clientLen)
+{
+    unsigned int i, j;
+    byte lenIn, lenClient;
+
+    if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
+        return OPENSSL_NPN_UNSUPPORTED;
+
+    for (i = 0; i < inLen; i += lenIn) {
+        lenIn = in[i++];
+        for (j = 0; j < clientLen; j += lenClient) {
+            lenClient = clientNames[j++];
+
+            if (lenIn != lenClient)
+                continue;
+
+            if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
+                *out = (unsigned char *)(in + i);
+                *outLen = lenIn;
+                return OPENSSL_NPN_NEGOTIATED;
+            }
+        }
+    }
+
+    *out = (unsigned char *)clientNames + 1;
+    *outLen = clientNames[0];
+    return OPENSSL_NPN_NO_OVERLAP;
+}
+
+void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
+                                    int (*cb) (WOLFSSL *ssl,
+                                               const unsigned char **out,
+                                               unsigned char *outlen,
+                                               const unsigned char *in,
+                                               unsigned int inlen,
+                                               void *arg), void *arg)
+{
+    if (ctx != NULL) {
+        ctx->alpnSelect = cb;
+        ctx->alpnSelectArg = arg;
+    }
+}
+
+void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
+                                           int (*cb) (WOLFSSL *ssl,
+                                                      const unsigned char
+                                                      **out,
+                                                      unsigned int *outlen,
+                                                      void *arg), void *arg)
+{
+    (void)s;
+    (void)cb;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
+}
+
+void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
+                                      int (*cb) (WOLFSSL *ssl,
+                                                 unsigned char **out,
+                                                 unsigned char *outlen,
+                                                 const unsigned char *in,
+                                                 unsigned int inlen,
+                                                 void *arg), void *arg)
+{
+    (void)s;
+    (void)cb;
+    (void)arg;
+    WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb");
+}
+
+void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
+                                    unsigned *len)
+{
+    (void)s;
+    (void)data;
+    (void)len;
+    WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated");
+}
+#endif /* HAVE_ALPN */
+
+#endif /* WOLFSSL_NGINX  / WOLFSSL_HAPROXY */
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
+WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names)
+{
+    int idx, start = 0, len;
+    int curve;
+    char name[MAX_CURVE_NAME_SZ];
+
+    /* Disable all curves so that only the ones the user wants are enabled. */
+    ctx->disabledCurves = (word32)-1;
+    for (idx = 1; names[idx-1] != '\0'; idx++) {
+        if (names[idx] != ':' && names[idx] != '\0')
+            continue;
+
+        len = idx - 1 - start;
+        if (len > MAX_CURVE_NAME_SZ - 1)
+            return WOLFSSL_FAILURE;
+
+        XMEMCPY(name, names + start, len);
+        name[len] = 0;
+
+        if ((XSTRNCMP(name, "prime256v1", len) == 0) ||
+                                      (XSTRNCMP(name, "secp256r1", len) == 0) ||
+                                      (XSTRNCMP(name, "P-256", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP256R1;
+        }
+        else if ((XSTRNCMP(name, "secp384r1", len) == 0) ||
+                                          (XSTRNCMP(name, "P-384", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP384R1;
+        }
+        else if ((XSTRNCMP(name, "secp521r1", len) == 0) ||
+                                          (XSTRNCMP(name, "P-521", len) == 0)) {
+            curve = WOLFSSL_ECC_SECP521R1;
+        }
+        else if (XSTRNCMP(name, "X25519", len) == 0)
+            curve = WOLFSSL_ECC_X25519;
+        else if ((curve = wc_ecc_get_curve_id_from_name(name)) < 0)
+            return WOLFSSL_FAILURE;
+
+        /* Switch the bit to off and therefore is enabled. */
+        ctx->disabledCurves &= ~(1 << curve);
+        start = idx + 1;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
+{
+    WOLFSSL_STUB("SSL_CTX_set_msg_callback");
+    (void)ctx;
+    (void)cb;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+
+/* Sets a callback for when sending and receiving protocol messages.
+ *
+ * ssl WOLFSSL structure to set callback in
+ * cb  callback to use
+ *
+ * return SSL_SUCCESS on success and SSL_FAILURE with error case
+ */
+int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb)
+{
+    WOLFSSL_ENTER("wolfSSL_set_msg_callback");
+
+    if (ssl == NULL) {
+        return SSL_FAILURE;
+    }
+
+    if (cb != NULL) {
+        ssl->toInfoOn = 1;
+    }
+
+    ssl->protoMsgCb = cb;
+    return SSL_SUCCESS;
+}
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
+{
+    WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg");
+    (void)ctx;
+    (void)arg;
+    return WOLFSSL_FAILURE;
+}
+#endif
+
+int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
+{
+    WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
+    ssl->protoMsgCtx = arg;
+    return WOLFSSL_SUCCESS;
+}
+
+void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line)
+{
+    void *ret;
+    (void)file;
+    (void)line;
+
+    if (data == NULL || siz >= INT_MAX)
+        return NULL;
+
+    ret = OPENSSL_malloc(siz);
+    if (ret == NULL) {
+        return NULL;
+    }
+    return XMEMCPY(ret, data, siz);
+}
+
+int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p,
+                            unsigned int p_len)
+{
+    WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos");
+    if(ctx == NULL)
+        return BAD_FUNC_ARG;
+    if((void *)ctx->alpn_cli_protos != NULL)
+        wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos);
+    ctx->alpn_cli_protos =
+        (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0);
+    if (ctx->alpn_cli_protos == NULL) {
+        return SSL_FAILURE;
+    }
+    ctx->alpn_cli_protos_len = p_len;
+
+    return SSL_SUCCESS;
+}
+
+#endif
+
+#endif /* WOLFCRYPT_ONLY */
+
+#if defined(OPENSSL_EXTRA)
+int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509)
+{
+    WOLFSSL_ENTER("X509_check_ca");
+
+    if (x509 == NULL)
+        return WOLFSSL_FAILURE;
+    if (x509->isCa)
+        return 1;
+    if (x509->extKeyUsageCrit)
+        return 4;
+
+    return 0;
+}
+
+
+const char *wolfSSL_ASN1_tag2str(int tag)
+{
+    static const char *const tag_label[31] = {
+        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
+        "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED",
+        "<ASN1 11>", "UTF8STRING", "<ASN1 13>", "<ASN1 14>", "<ASN1 15>",
+        "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
+        "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
+        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING",
+        "<ASN1 29>", "BMPSTRING"
+    };
+
+    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+        tag &= ~0x100;
+    if (tag < 0 || tag > 30)
+        return "(unknown)";
+    return tag_label[tag];
+}
+
+static int check_esc_char(char c, char *esc)
+{
+    char *ptr = NULL;
+
+    ptr = esc;
+    while(*ptr != 0){
+        if (c == *ptr)
+            return 1;
+        ptr++;
+    }
+    return 0;
+}
+
+int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str,
+                                 unsigned long flags)
+{
+    size_t str_len = 0, type_len = 0;
+    unsigned char *typebuf = NULL;
+    const char *hash="#";
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex");
+    if (out == NULL || str == NULL)
+        return WOLFSSL_FAILURE;
+
+    /* add ASN1 type tag */
+    if (flags & ASN1_STRFLGS_SHOW_TYPE){
+        const char *tag = wolfSSL_ASN1_tag2str(str->type);
+        /* colon len + tag len + null*/
+        type_len = XSTRLEN(tag) + 2;
+        typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (typebuf == NULL){
+            WOLFSSL_MSG("memory alloc failed.");
+            return WOLFSSL_FAILURE;
+        }
+        XMEMSET(typebuf, 0, type_len);
+        XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag);
+        type_len--;
+    }
+
+    /* dump hex */
+    if (flags & ASN1_STRFLGS_DUMP_ALL){
+        static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6',
+                                         '7','8', '9', 'A', 'B', 'C', 'D',
+                                         'E', 'F' };
+        char hex_tmp[4];
+        char *str_ptr, *str_end;
+
+        if (type_len > 0){
+            if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+                XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                return WOLFSSL_FAILURE;
+            }
+            str_len += type_len;
+        }
+        if (wolfSSL_BIO_write(out, hash, 1) != 1){
+            goto err_exit;
+        }
+        str_len++;
+        if (flags & ASN1_STRFLGS_DUMP_DER){
+            hex_tmp[0] = hex_char[str->type >> 4];
+            hex_tmp[1] = hex_char[str->type & 0xf];
+            hex_tmp[2] = hex_char[str->length >> 4];
+            hex_tmp[3] = hex_char[str->length & 0xf];
+            if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){
+                goto err_exit;
+            }
+            str_len += 4;
+            XMEMSET(hex_tmp, 0, 4);
+        }
+
+        str_ptr = str->data;
+        str_end = str->data + str->length;
+        while (str_ptr < str_end){
+            hex_tmp[0] = hex_char[*str_ptr >> 4];
+            hex_tmp[1] = hex_char[*str_ptr & 0xf];
+            if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){
+                goto err_exit;
+            }
+            str_ptr++;
+            str_len += 2;
+        }
+        if (type_len > 0)
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+        return (int)str_len;
+    }
+
+    if (type_len > 0){
+        if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            return WOLFSSL_FAILURE;
+        }
+        str_len += type_len;
+    }
+
+    if (flags & ASN1_STRFLGS_ESC_2253){
+        char esc_ch[] = "+;<>\\";
+        char* esc_ptr = NULL;
+
+        esc_ptr = str->data;
+        while (*esc_ptr != 0){
+            if (check_esc_char(*esc_ptr, esc_ch)){
+                if (wolfSSL_BIO_write(out,"\\", 1) != 1)
+                    goto err_exit;
+                str_len++;
+            }
+            if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1)
+                goto err_exit;
+            str_len++;
+            esc_ptr++;
+        }
+        if (type_len > 0)
+            XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return (int)str_len;
+    }
+
+    if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){
+        goto err_exit;
+    }
+    str_len += str->length;
+    if (type_len > 0)
+        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    return (int)str_len;
+
+err_exit:
+    if (type_len > 0)
+        XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    return WOLFSSL_FAILURE;
+}
+
+#ifndef NO_ASN_TIME
+WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
+                                                        WOLFSSL_ASN1_TIME **out)
+{
+    unsigned char time_type;
+    WOLFSSL_ASN1_TIME *ret = NULL;
+    unsigned char *data_ptr = NULL;
+
+    WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime");
+    if (t == NULL)
+        return NULL;
+
+    time_type = t->data[0];
+    if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){
+        WOLFSSL_MSG("Invalid ASN_TIME type.");
+        return NULL;
+    }
+    if (out == NULL || *out == NULL){
+        ret = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL,
+                                        DYNAMIC_TYPE_TMP_BUFFER);
+        if (ret == NULL){
+            WOLFSSL_MSG("memory alloc failed.");
+            return NULL;
+        }
+        XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME));
+    } else
+        ret = *out;
+
+    if (time_type == ASN_GENERALIZED_TIME){
+        XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE);
+        return ret;
+    } else if (time_type == ASN_UTC_TIME){
+        ret->data[0] = ASN_GENERALIZED_TIME;
+        ret->data[1] = ASN_GENERALIZED_TIME_SIZE;
+        data_ptr  = ret->data + 2;
+        if (t->data[2] >= '5')
+            XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, "19%s", t->data + 2);
+        else
+            XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, "20%s", t->data + 2);
+
+        return ret;
+    }
+
+    WOLFSSL_MSG("Invalid ASN_TIME value");
+    return NULL;
+}
+#endif /* !NO_ASN_TIME */
+
+
+#ifndef NO_ASN
+int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp)
+{
+    unsigned char *pptr = NULL;
+    char pad = 0 ;
+    unsigned char pad_val = 0;
+    int ret_size = 0;
+    unsigned char data1 = 0;
+    unsigned char neg = 0;
+    int i = 0;
+
+    WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER");
+    if (a == NULL)
+        return WOLFSSL_FAILURE;
+
+    ret_size = a->intData[1];
+    if (ret_size == 0)
+        ret_size = 1;
+    else{
+        ret_size = (int)a->intData[1];
+        neg = a->negative;
+        data1 = a->intData[2];
+        if (ret_size == 1 && data1 == 0)
+            neg = 0;
+        /* 0x80 or greater positive number in first byte */
+        if (!neg && (data1 > 127)){
+            pad = 1;
+            pad_val = 0;
+        } else if (neg){
+            /* negative number */
+            if (data1 > 128){
+                pad = 1;
+                pad_val = 0xff;
+            } else if (data1 == 128){
+                for (i = 3; i < a->intData[1] + 2; i++){
+                    if (a->intData[i]){
+                        pad = 1;
+                        pad_val = 0xff;
+                        break;
+                    }
+                }
+            }
+        }
+        ret_size += (int)pad;
+    }
+    if (pp == NULL)
+        return ret_size;
+
+    pptr = *pp;
+    if (pad)
+        *(pptr++) = pad_val;
+    if (a->intData[1] == 0)
+        *(pptr++) = 0;
+    else if (!neg){
+        /* positive number */
+        for (i=0; i < a->intData[1]; i++){
+            *pptr = a->intData[i+2];
+            pptr++;
+        }
+    } else {
+        /* negative number */
+        int str_len = 0;
+
+        /* 0 padding from end of buffer */
+        str_len = (int)a->intData[1];
+        pptr += a->intData[1] - 1;
+        while (!a->intData[str_len + 2] && str_len > 1){
+            *(pptr--) = 0;
+            str_len--;
+        }
+        /* 2's complement next octet */
+        *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1;
+        str_len--;
+        /* Complement any octets left */
+        while (str_len > 0){
+            *(pptr--) = a->intData[str_len + 1] ^ 0xff;
+            str_len--;
+        }
+    }
+    *pp += ret_size;
+    return ret_size;
+}
+#endif /* !NO_ASN */
+
+#endif  /* OPENSSLEXTRA */
+
--- a/src/tls.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/tls.c	Wed Nov 20 13:27:48 2019 +0000
@@ -25,28 +25,28 @@
     #include <config.h>
 #endif
 
-#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfcrypt/settings.h>
 
 #ifndef WOLFCRYPT_ONLY
 
 #include <wolfssl/ssl.h>
 #include <wolfssl/internal.h>
 #include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/hmac.h>
+#include <wolfcrypt/hmac.h>
 #ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
+    #include <wolfcrypt/misc.h>
 #else
     #define WOLFSSL_MISC_INCLUDED
     #include <wolfcrypt/src/misc.c>
 #endif
 
 #ifdef HAVE_CURVE25519
-    #include <wolfssl/wolfcrypt/curve25519.h>
+    #include <wolfcrypt/curve25519.h>
 #endif
 
 #ifdef HAVE_NTRU
     #include "libntruencrypt/ntru_crypto.h"
-    #include <wolfssl/wolfcrypt/random.h>
+    #include <wolfcrypt/random.h>
 #endif
 
 #ifdef HAVE_QSH
--- a/src/tls13.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/tls13.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,8409 +1,8409 @@
-/* tls13.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/*
- * BUILD_GCM
- *    Enables AES-GCM ciphersuites.
- * HAVE_AESCCM
- *    Enables AES-CCM ciphersuites.
- * HAVE_SESSION_TICKET
- *    Enables session tickets - required for TLS 1.3 resumption.
- * NO_PSK
- *    Do not enable Pre-Shared Keys.
- * TLS13_SUPPORTS_EXPORTERS
- *    Gaurd to compile out any code for exporter keys.
- *    Feature not supported yet.
- * WOLFSSL_ASYNC_CRYPT
- *    Enables the use of asynchornous cryptographic operations.
- *    This is available for ciphers and certificates.
- * HAVE_CHACHA && HAVE_POLY1305
- *    Enables use of CHACHA20-POLY1305 ciphersuites.
- * WOLFSSL_DEBUG_TLS
- *    Writes out details of TLS 1.3 protocol including hanshake message buffers
- *    and key generation input and output.
- * WOLFSSL_EARLY_DATA
- *    Allow 0-RTT Handshake using Early Data extensions and handshake message
- * WOLFSSL_NO_SERVER_GROUPS_EXT
- *    Do not send the server's groups in an extension when the server's top
- *    preference is not in client's list.
- * WOLFSSL_POST_HANDSHAKE_AUTH
- *    Allow TLS v1.3 code to perform post-handshake authentication of the
- *    client.
- * WOLFSSL_SEND_HRR_COOKIE
- *    Send a cookie in hello_retry_request message to enable stateless tracking
- *    of ClientHello replies.
- * WOLFSSL_TLS13
- *    Enable TLS 1.3 protocol implementation.
- * WOLFSSL_TLS13_DRAFT_18
- *    Conform with Draft 18 of the TLS v1.3 specification.
- * WOLFSSL_TLS13_DRAFT_22
- *    Conform with Draft 22 of the TLS v1.3 specification.
- * WOLFSSL_TLS13_DRAFT_23
- *    Conform with Draft 23 of the TLS v1.3 specification.
- * WOLFSSL_TLS13_MIDDLEBOX_COMPAT
- *    Enable middlebox compatability in the TLS 1.3 handshake.
- *    This includes sending ChangeCipherSpec before encrypted messages and
- *    including a session id.
- * WOLFSSL_TLS13_SHA512
- *    Allow generation of SHA-512 digests in handshake - no ciphersuite
- *    requires SHA-512 at this time.
- * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
- *    Allow a NewSessionTicket message to be sent by server before Client's
- *    Finished message.
- *    See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note).
- */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef WOLFSSL_TLS13
-#ifdef HAVE_SESSION_TICKET
-    #include <wolfssl/wolfcrypt/wc_port.h>
-#endif
-
-#ifndef WOLFCRYPT_ONLY
-
-#ifdef HAVE_ERRNO_H
-    #include <errno.h>
-#endif
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/dh.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef HAVE_NTRU
-    #include "libntruencrypt/ntru_crypto.h"
-#endif
-
-#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \
-    defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #else
-        #include <stdio.h>
-    #endif
-#endif
-
-#ifdef __sun
-    #include <sys/filio.h>
-#endif
-
-#ifndef TRUE
-    #define TRUE  1
-#endif
-#ifndef FALSE
-    #define FALSE 0
-#endif
-
-#ifndef HAVE_HKDF
-    #error The build option HAVE_HKDF is required for TLS 1.3
-#endif
-
-
-/* Set ret to error value and jump to label.
- *
- * err     The error value to set.
- * eLabel  The label to jump to.
- */
-#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
-
-
-/* Extract data using HMAC, salt and input.
- * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
- *
- * prk      The generated pseudorandom key.
- * salt     The salt.
- * saltLen  The length of the salt.
- * ikm      The input keying material.
- * ikmLen   The length of the input keying material.
- * mac      The type of digest to use.
- * returns 0 on success, otherwise failure.
- */
-static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
-                             byte* ikm, int ikmLen, int mac)
-{
-    int ret;
-    int hash = 0;
-    int len = 0;
-
-    switch (mac) {
-        #ifndef NO_SHA256
-        case sha256_mac:
-            hash = WC_SHA256;
-            len = WC_SHA256_DIGEST_SIZE;
-            break;
-        #endif
-
-        #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            hash = WC_SHA384;
-            len = WC_SHA384_DIGEST_SIZE;
-            break;
-        #endif
-
-        #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            hash = WC_SHA512;
-            len = WC_SHA512_DIGEST_SIZE;
-            break;
-        #endif
-    }
-
-    /* When length is 0 then use zeroed data of digest length. */
-    if (ikmLen == 0) {
-        ikmLen = len;
-        XMEMSET(ikm, 0, len);
-    }
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("  Salt");
-    WOLFSSL_BUFFER(salt, saltLen);
-    WOLFSSL_MSG("  IKM");
-    WOLFSSL_BUFFER(ikm, ikmLen);
-#endif
-
-    ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk);
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("  PRK");
-    WOLFSSL_BUFFER(prk, len);
-#endif
-
-    return ret;
-}
-
-/* Expand data using HMAC, salt and label and info.
- * TLS v1.3 defines this function.
- *
- * okm          The generated pseudorandom key - output key material.
- * okmLen       The length of generated pseudorandom key - output key material.
- * prk          The salt - pseudo-random key.
- * prkLen       The length of the salt - pseudo-random key.
- * protocol     The TLS protocol label.
- * protocolLen  The length of the TLS protocol label.
- * info         The information to expand.
- * infoLen      The length of the information.
- * digest       The type of digest to use.
- * returns 0 on success, otherwise failure.
- */
-static int HKDF_Expand_Label(byte* okm, word32 okmLen,
-                             const byte* prk, word32 prkLen,
-                             const byte* protocol, word32 protocolLen,
-                             const byte* label, word32 labelLen,
-                             const byte* info, word32 infoLen,
-                             int digest)
-{
-    int    ret = 0;
-    int    idx = 0;
-    byte   data[MAX_HKDF_LABEL_SZ];
-
-    /* Output length. */
-    data[idx++] = (byte)(okmLen >> 8);
-    data[idx++] = (byte)okmLen;
-    /* Length of protocol | label. */
-    data[idx++] = (byte)(protocolLen + labelLen);
-    /* Protocol */
-    XMEMCPY(&data[idx], protocol, protocolLen);
-    idx += protocolLen;
-    /* Label */
-    XMEMCPY(&data[idx], label, labelLen);
-    idx += labelLen;
-    /* Length of hash of messages */
-    data[idx++] = (byte)infoLen;
-    /* Hash of messages */
-    XMEMCPY(&data[idx], info, infoLen);
-    idx += infoLen;
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("  PRK");
-    WOLFSSL_BUFFER(prk, prkLen);
-    WOLFSSL_MSG("  Info");
-    WOLFSSL_BUFFER(data, idx);
-#endif
-
-    ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("  OKM");
-    WOLFSSL_BUFFER(okm, okmLen);
-#endif
-
-    ForceZero(data, idx);
-
-    return ret;
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* Size of the TLS v1.3 label use when deriving keys. */
-#define TLS13_PROTOCOL_LABEL_SZ    9
-/* The protocol label for TLS v1.3. */
-static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, ";
-#else
-/* Size of the TLS v1.3 label use when deriving keys. */
-#define TLS13_PROTOCOL_LABEL_SZ    6
-/* The protocol label for TLS v1.3. */
-static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
-#endif
-
-#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \
-                                        !defined(NO_PSK)
-/* Derive a key from a message.
- *
- * ssl        The SSL/TLS object.
- * output     The buffer to hold the derived key.
- * outputLen  The length of the derived key.
- * secret     The secret used to derive the key (HMAC secret).
- * label      The label used to distinguish the context.
- * labelLen   The length of the label.
- * msg        The message data to derive key from.
- * msgLen     The length of the message data to derive key from.
- * hashAlgo   The hash algorithm to use in the HMAC.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
-                        const byte* secret, const byte* label, word32 labelLen,
-                        byte* msg, int msgLen, int hashAlgo)
-{
-    byte        hash[WC_MAX_DIGEST_SIZE];
-    Digest      digest;
-    word32      hashSz = 0;
-    const byte* protocol;
-    word32      protocolLen;
-    int         digestAlg = -1;
-    int         ret = BAD_FUNC_ARG;
-
-    switch (hashAlgo) {
-#ifndef NO_WOLFSSL_SHA256
-        case sha256_mac:
-            ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID);
-            if (ret == 0) {
-                    ret = wc_Sha256Update(&digest.sha256, msg, msgLen);
-                if (ret == 0)
-                    ret = wc_Sha256Final(&digest.sha256, hash);
-                wc_Sha256Free(&digest.sha256);
-            }
-            hashSz = WC_SHA256_DIGEST_SIZE;
-            digestAlg = WC_SHA256;
-            break;
-#endif
-#ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID);
-            if (ret == 0) {
-                ret = wc_Sha384Update(&digest.sha384, msg, msgLen);
-                if (ret == 0)
-                    ret = wc_Sha384Final(&digest.sha384, hash);
-                wc_Sha384Free(&digest.sha384);
-            }
-            hashSz = WC_SHA384_DIGEST_SIZE;
-            digestAlg = WC_SHA384;
-            break;
-#endif
-#ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID);
-            if (ret == 0) {
-                ret = wc_Sha512Update(&digest.sha512, msg, msgLen);
-                if (ret == 0)
-                    ret = wc_Sha512Final(&digest.sha512, hash);
-                wc_Sha512Free(&digest.sha512);
-            }
-            hashSz = WC_SHA512_DIGEST_SIZE;
-            digestAlg = WC_SHA512;
-            break;
-#endif
-        default:
-            digestAlg = -1;
-            break;
-    }
-
-    if (digestAlg < 0)
-        return HASH_TYPE_E;
-
-    if (ret != 0)
-        return ret;
-
-    switch (ssl->version.minor) {
-        case TLSv1_3_MINOR:
-            protocol = tls13ProtocolLabel;
-            protocolLen = TLS13_PROTOCOL_LABEL_SZ;
-            break;
-
-        default:
-            return VERSION_ERROR;
-    }
-    if (outputLen == -1)
-        outputLen = hashSz;
-
-    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
-                             protocol, protocolLen, label, labelLen,
-                             hash, hashSz, digestAlg);
-}
-#endif
-
-/* Derive a key.
- *
- * ssl          The SSL/TLS object.
- * output       The buffer to hold the derived key.
- * outputLen    The length of the derived key.
- * secret       The secret used to derive the key (HMAC secret).
- * label        The label used to distinguish the context.
- * labelLen     The length of the label.
- * hashAlgo     The hash algorithm to use in the HMAC.
- * includeMsgs  Whether to include a hash of the handshake messages so far.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
-                     const byte* secret, const byte* label, word32 labelLen,
-                     int hashAlgo, int includeMsgs)
-{
-    int         ret = 0;
-    byte        hash[WC_MAX_DIGEST_SIZE];
-    word32      hashSz = 0;
-    word32      hashOutSz = 0;
-    const byte* protocol;
-    word32      protocolLen;
-    int         digestAlg = 0;
-
-    switch (hashAlgo) {
-        #ifndef NO_SHA256
-            case sha256_mac:
-                hashSz    = WC_SHA256_DIGEST_SIZE;
-                digestAlg = WC_SHA256;
-                if (includeMsgs)
-                    ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
-            break;
-        #endif
-
-        #ifdef WOLFSSL_SHA384
-            case sha384_mac:
-                hashSz    = WC_SHA384_DIGEST_SIZE;
-                digestAlg = WC_SHA384;
-                if (includeMsgs)
-                    ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
-            break;
-        #endif
-
-        #ifdef WOLFSSL_TLS13_SHA512
-            case sha512_mac:
-                hashSz    = WC_SHA512_DIGEST_SIZE;
-                digestAlg = WC_SHA512;
-                if (includeMsgs)
-                    ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
-            break;
-        #endif
-    }
-    if (ret != 0)
-        return ret;
-
-    /* Only one protocol version defined at this time. */
-    protocol = tls13ProtocolLabel;
-    protocolLen = TLS13_PROTOCOL_LABEL_SZ;
-
-    if (outputLen == -1)
-        outputLen = hashSz;
-    if (includeMsgs)
-        hashOutSz = hashSz;
-
-    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
-                             protocol, protocolLen, label, labelLen,
-                             hash, hashOutSz, digestAlg);
-}
-
-
-#ifndef NO_PSK
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the binder key label. */
-#define BINDER_KEY_LABEL_SZ         23
-/* The binder key label. */
-static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
-    "external psk binder key";
-#else
-/* The length of the binder key label. */
-#define BINDER_KEY_LABEL_SZ         10
-/* The binder key label. */
-static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
-    "ext binder";
-#endif
-/* Derive the binder key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveBinderKey(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Binder Key");
-    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
-                        binderKeyLabel, BINDER_KEY_LABEL_SZ,
-                        NULL, 0, ssl->specs.mac_algorithm);
-}
-#endif /* !NO_PSK */
-
-#ifdef HAVE_SESSION_TICKET
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the binder key resume label. */
-#define BINDER_KEY_RESUME_LABEL_SZ  25
-/* The binder key resume label. */
-static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
-    "resumption psk binder key";
-#else
-/* The length of the binder key resume label. */
-#define BINDER_KEY_RESUME_LABEL_SZ  10
-/* The binder key resume label. */
-static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
-    "res binder";
-#endif
-/* Derive the binder resumption key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Binder Key - Resumption");
-    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
-                        binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ,
-                        NULL, 0, ssl->specs.mac_algorithm);
-}
-#endif /* HAVE_SESSION_TICKET */
-
-#ifdef WOLFSSL_EARLY_DATA
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the early traffic label. */
-#define EARLY_TRAFFIC_LABEL_SZ      27
-/* The early traffic label. */
-static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
-    "client early traffic secret";
-#else
-/* The length of the early traffic label. */
-#define EARLY_TRAFFIC_LABEL_SZ      11
-/* The early traffic label. */
-static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
-    "c e traffic";
-#endif
-/* Derive the early traffic key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Early Traffic Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->secret,
-                     earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-
-#ifdef TLS13_SUPPORTS_EXPORTERS
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the early exporter label. */
-#define EARLY_EXPORTER_LABEL_SZ     28
-/* The early exporter label. */
-static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
-    "early exporter master secret";
-#else
-/* The length of the early exporter label. */
-#define EARLY_EXPORTER_LABEL_SZ     12
-/* The early exporter label. */
-static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
-    "e exp master";
-#endif
-/* Derive the early exporter key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Early Exporter Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->secret,
-                     earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-#endif
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the client hanshake label. */
-#define CLIENT_HANDSHAKE_LABEL_SZ   31
-/* The client hanshake label. */
-static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
-    "client handshake traffic secret";
-#else
-/* The length of the client hanshake label. */
-#define CLIENT_HANDSHAKE_LABEL_SZ   12
-/* The client hanshake label. */
-static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
-    "c hs traffic";
-#endif
-/* Derive the client handshake key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Client Handshake Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
-                     clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the server handshake label. */
-#define SERVER_HANDSHAKE_LABEL_SZ   31
-/* The server handshake label. */
-static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
-    "server handshake traffic secret";
-#else
-/* The length of the server handshake label. */
-#define SERVER_HANDSHAKE_LABEL_SZ   12
-/* The server handshake label. */
-static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
-    "s hs traffic";
-#endif
-/* Derive the server handshake key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Server Handshake Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
-                     serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the client application traffic label. */
-#define CLIENT_APP_LABEL_SZ         33
-/* The client application traffic label. */
-static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
-    "client application traffic secret";
-#else
-/* The length of the client application traffic label. */
-#define CLIENT_APP_LABEL_SZ         12
-/* The client application traffic label. */
-static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
-    "c ap traffic";
-#endif
-/* Derive the client application traffic key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Client Traffic Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
-                     clientAppLabel, CLIENT_APP_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the server application traffic label. */
-#define SERVER_APP_LABEL_SZ         33
-/* The  server application traffic label. */
-static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
-    "server application traffic secret";
-#else
-/* The length of the server application traffic label. */
-#define SERVER_APP_LABEL_SZ         12
-/* The  server application traffic label. */
-static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
-    "s ap traffic";
-#endif
-/* Derive the server application traffic key.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Server Traffic Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
-                     serverAppLabel, SERVER_APP_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-
-#ifdef TLS13_SUPPORTS_EXPORTERS
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the exporter master secret label. */
-#define EXPORTER_MASTER_LABEL_SZ    22
-/* The exporter master secret label. */
-static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
-    "exporter master secret";
-#else
-/* The length of the exporter master secret label. */
-#define EXPORTER_MASTER_LABEL_SZ    10
-/* The exporter master secret label. */
-static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
-    "exp master";
-#endif
-/* Derive the exporter secret.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveExporterSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Exporter Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
-                     exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-#endif
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the resumption master secret label. */
-#define RESUME_MASTER_LABEL_SZ      24
-/* The resumption master secret label. */
-static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
-    "resumption master secret";
-#else
-/* The length of the resumption master secret label. */
-#define RESUME_MASTER_LABEL_SZ      10
-/* The resumption master secret label. */
-static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
-    "res master";
-#endif
-/* Derive the resumption secret.
- *
- * ssl  The SSL/TLS object.
- * key  The derived key.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
-{
-    WOLFSSL_MSG("Derive Resumption Secret");
-    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
-                     resumeMasterLabel, RESUME_MASTER_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 1);
-}
-#endif
-
-/* Length of the finished label. */
-#define FINISHED_LABEL_SZ           8
-/* Finished label for generating finished key. */
-static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished";
-/* Derive the finished secret.
- *
- * ssl     The SSL/TLS object.
- * key     The key to use with the HMAC.
- * secret  The derived secret.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret)
-{
-    WOLFSSL_MSG("Derive Finished Secret");
-    return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 0);
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* The length of the application traffic label. */
-#define APP_TRAFFIC_LABEL_SZ        26
-/* The application traffic label. */
-static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
-    "application traffic secret";
-#else
-/* The length of the application traffic label. */
-#define APP_TRAFFIC_LABEL_SZ        11
-/* The application traffic label. */
-static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
-    "traffic upd";
-#endif
-/* Update the traffic secret.
- *
- * ssl     The SSL/TLS object.
- * secret  The previous secret and derived secret.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret)
-{
-    WOLFSSL_MSG("Derive New Application Traffic Secret");
-    return DeriveKey(ssl, secret, -1, secret,
-                     appTrafficLabel, APP_TRAFFIC_LABEL_SZ,
-                     ssl->specs.mac_algorithm, 0);
-}
-
-/* Derive the early secret using HKDF Extract.
- *
- * ssl  The SSL/TLS object.
- */
-static int DeriveEarlySecret(WOLFSSL* ssl)
-{
-    WOLFSSL_MSG("Derive Early Secret");
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
-            ssl->arrays->psk_key, ssl->arrays->psk_keySz,
-            ssl->specs.mac_algorithm);
-#else
-    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
-            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
-#endif
-}
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-/* The length of the derived label. */
-#define DERIVED_LABEL_SZ        7
-/* The derived label. */
-static const byte derivedLabel[DERIVED_LABEL_SZ + 1] =
-    "derived";
-#endif
-/* Derive the handshake secret using HKDF Extract.
- *
- * ssl  The SSL/TLS object.
- */
-static int DeriveHandshakeSecret(WOLFSSL* ssl)
-{
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    WOLFSSL_MSG("Derive Handshake Secret");
-    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
-            ssl->arrays->secret, ssl->specs.hash_size,
-            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
-            ssl->specs.mac_algorithm);
-#else
-    byte key[WC_MAX_DIGEST_SIZE];
-    int ret;
-
-    WOLFSSL_MSG("Derive Handshake Secret");
-
-    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
-                        derivedLabel, DERIVED_LABEL_SZ,
-                        NULL, 0, ssl->specs.mac_algorithm);
-    if (ret != 0)
-        return ret;
-
-    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
-            key, ssl->specs.hash_size,
-            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
-            ssl->specs.mac_algorithm);
-#endif
-}
-
-/* Derive the master secret using HKDF Extract.
- *
- * ssl  The SSL/TLS object.
- */
-static int DeriveMasterSecret(WOLFSSL* ssl)
-{
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    WOLFSSL_MSG("Derive Master Secret");
-    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
-            ssl->arrays->preMasterSecret, ssl->specs.hash_size,
-            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
-#else
-    byte key[WC_MAX_DIGEST_SIZE];
-    int ret;
-
-    WOLFSSL_MSG("Derive Master Secret");
-
-    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret,
-                        derivedLabel, DERIVED_LABEL_SZ,
-                        NULL, 0, ssl->specs.mac_algorithm);
-    if (ret != 0)
-        return ret;
-
-    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
-            key, ssl->specs.hash_size,
-            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
-#endif
-}
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-#if defined(HAVE_SESSION_TICKET)
-/* Length of the resumption label. */
-#define RESUMPTION_LABEL_SZ         10
-/* Resumption label for generating PSK assocated with the ticket. */
-static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption";
-/* Derive the PSK assocated with the ticket.
- *
- * ssl       The SSL/TLS object.
- * nonce     The nonce to derive with.
- * nonceLen  The length of the nonce to derive with.
- * secret    The derived secret.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen,
-                               byte* secret)
-{
-    int         digestAlg;
-    /* Only one protocol version defined at this time. */
-    const byte* protocol    = tls13ProtocolLabel;
-    word32      protocolLen = TLS13_PROTOCOL_LABEL_SZ;
-
-    WOLFSSL_MSG("Derive Resumption PSK");
-
-    switch (ssl->specs.mac_algorithm) {
-        #ifndef NO_SHA256
-        case sha256_mac:
-            digestAlg = WC_SHA256;
-            break;
-        #endif
-
-        #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            digestAlg = WC_SHA384;
-            break;
-        #endif
-
-        #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            digestAlg = WC_SHA512;
-            break;
-        #endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    return HKDF_Expand_Label(secret, ssl->specs.hash_size,
-                             ssl->session.masterSecret, ssl->specs.hash_size,
-                             protocol, protocolLen, resumptionLabel,
-                             RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);
-}
-#endif /* HAVE_SESSION_TICKET */
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-
-
-/* Calculate the HMAC of message data to this point.
- *
- * ssl   The SSL/TLS object.
- * key   The HMAC key.
- * hash  The hash result - verify data.
- * returns length of verify data generated.
- */
-static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
-    word32* pHashSz)
-{
-    Hmac verifyHmac;
-    int  hashType = WC_SHA256;
-    int  hashSz = WC_SHA256_DIGEST_SIZE;
-    int  ret = BAD_FUNC_ARG;
-
-    /* Get the hash of the previous handshake messages. */
-    switch (ssl->specs.mac_algorithm) {
-    #ifndef NO_SHA256
-        case sha256_mac:
-            hashType = WC_SHA256;
-            hashSz = WC_SHA256_DIGEST_SIZE;
-            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
-            break;
-    #endif /* !NO_SHA256 */
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            hashType = WC_SHA384;
-            hashSz = WC_SHA384_DIGEST_SIZE;
-            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            hashType = WC_SHA512;
-            hashSz = WC_SHA512_DIGEST_SIZE;
-            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
-            break;
-    #endif /* WOLFSSL_TLS13_SHA512 */
-    }
-    if (ret != 0)
-        return ret;
-
-    /* Calculate the verify data. */
-    ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId);
-    if (ret == 0) {
-        ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size);
-        if (ret == 0)
-            ret = wc_HmacUpdate(&verifyHmac, hash, hashSz);
-        if (ret == 0)
-            ret = wc_HmacFinal(&verifyHmac, hash);
-        wc_HmacFree(&verifyHmac);
-    }
-
-    if (pHashSz)
-        *pHashSz = hashSz;
-
-    return ret;
-}
-
-/* The length of the label to use when deriving keys. */
-#define WRITE_KEY_LABEL_SZ     3
-/* The length of the label to use when deriving IVs. */
-#define WRITE_IV_LABEL_SZ      2
-/* The label to use when deriving keys. */
-static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key";
-/* The label to use when deriving IVs. */
-static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1]   = "iv";
-
-/* Derive the keys and IVs for TLS v1.3.
- *
- * ssl      The SSL/TLS object.
- * sercret  early_data_key when deriving the key and IV for encrypting early
- *          data application data and end_of_early_data messages.
- *          handshake_key when deriving keys and IVs for encrypting handshake
- *          messages.
- *          traffic_key when deriving first keys and IVs for encrypting
- *          traffic messages.
- *          update_traffic_key when deriving next keys and IVs for encrypting
- *          traffic messages.
- * side     ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived.
- *          DECRYPT_SIDE_ONLY when only decryption secret needs to be derived.
- *          ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived.
- * store    1 indicates to derive the keys and IVs from derived secret and
- *          store ready for provisioning.
- * returns 0 on success, otherwise failure.
- */
-static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
-{
-    int   ret = BAD_FUNC_ARG; /* Assume failure */
-    int   i = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* key_dig;
-#else
-    byte  key_dig[MAX_PRF_DIG];
-#endif
-    int   provision;
-
-#ifdef WOLFSSL_SMALL_STACK
-    key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
-    if (key_dig == NULL)
-        return MEMORY_E;
-#endif
-
-    if (side == ENCRYPT_AND_DECRYPT_SIDE) {
-        provision = PROVISION_CLIENT_SERVER;
-    }
-    else {
-        provision = ((ssl->options.side != WOLFSSL_CLIENT_END) ^
-                     (side == ENCRYPT_SIDE_ONLY)) ? PROVISION_CLIENT :
-                                                    PROVISION_SERVER;
-    }
-
-    /* Derive the appropriate secret to use in the HKDF. */
-    switch (secret) {
-#ifdef WOLFSSL_EARLY_DATA
-        case early_data_key:
-            ret = DeriveEarlyTrafficSecret(ssl, ssl->arrays->clientSecret);
-            if (ret != 0)
-                goto end;
-            break;
-#endif
-
-        case handshake_key:
-            if (provision & PROVISION_CLIENT) {
-                ret = DeriveClientHandshakeSecret(ssl,
-                                                  ssl->arrays->clientSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            if (provision & PROVISION_SERVER) {
-                ret = DeriveServerHandshakeSecret(ssl,
-                                                  ssl->arrays->serverSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            break;
-
-        case traffic_key:
-            if (provision & PROVISION_CLIENT) {
-                ret = DeriveClientTrafficSecret(ssl, ssl->arrays->clientSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            if (provision & PROVISION_SERVER) {
-                ret = DeriveServerTrafficSecret(ssl, ssl->arrays->serverSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            break;
-
-        case update_traffic_key:
-            if (provision & PROVISION_CLIENT) {
-                ret = DeriveTrafficSecret(ssl, ssl->arrays->clientSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            if (provision & PROVISION_SERVER) {
-                ret = DeriveTrafficSecret(ssl, ssl->arrays->serverSecret);
-                if (ret != 0)
-                    goto end;
-            }
-            break;
-    }
-
-    if (!store)
-        goto end;
-
-    /* Key data = client key | server key | client IV | server IV */
-
-    if (provision & PROVISION_CLIENT) {
-        /* Derive the client key.  */
-        WOLFSSL_MSG("Derive Client Key");
-        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
-                        ssl->arrays->clientSecret, writeKeyLabel,
-                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
-        if (ret != 0)
-            goto end;
-        i += ssl->specs.key_size;
-    }
-
-    if (provision & PROVISION_SERVER) {
-        /* Derive the server key.  */
-        WOLFSSL_MSG("Derive Server Key");
-        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
-                        ssl->arrays->serverSecret, writeKeyLabel,
-                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
-        if (ret != 0)
-            goto end;
-        i += ssl->specs.key_size;
-    }
-
-    if (provision & PROVISION_CLIENT) {
-        /* Derive the client IV.  */
-        WOLFSSL_MSG("Derive Client IV");
-        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
-                        ssl->arrays->clientSecret, writeIVLabel,
-                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
-        if (ret != 0)
-            goto end;
-        i += ssl->specs.iv_size;
-    }
-
-    if (provision & PROVISION_SERVER) {
-        /* Derive the server IV.  */
-        WOLFSSL_MSG("Derive Server IV");
-        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
-                        ssl->arrays->serverSecret, writeIVLabel,
-                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
-        if (ret != 0)
-            goto end;
-    }
-
-    /* Store keys and IVs but don't activate them. */
-    ret = StoreKeys(ssl, key_dig, provision);
-
-end:
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
-#endif
-
-    return ret;
-}
-
-#ifdef HAVE_SESSION_TICKET
-#if defined(USER_TICKS)
-#if 0
-    word32 TimeNowInMilliseconds(void)
-    {
-        /*
-        write your own clock tick function if don't want gettimeofday()
-        needs millisecond accuracy but doesn't have to correlated to EPOCH
-        */
-    }
-#endif
-
-#elif defined(TIME_OVERRIDES)
-    #ifndef HAVE_TIME_T_TYPE
-        typedef long time_t;
-    #endif
-    extern time_t XTIME(time_t * timer);
-
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32) XTIME(0) * 1000;
-    }
-#elif defined(USE_WINDOWS_API)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        static int           init = 0;
-        static LARGE_INTEGER freq;
-        LARGE_INTEGER        count;
-
-        if (!init) {
-            QueryPerformanceFrequency(&freq);
-            init = 1;
-        }
-
-        QueryPerformanceCounter(&count);
-
-        return (word32)(count.QuadPart / (freq.QuadPart / 1000));
-    }
-
-#elif defined(HAVE_RTP_SYS)
-    #include "rtptime.h"
-
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32)rtp_get_system_sec() * 1000;
-    }
-#elif defined(MICRIUM)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        OS_TICK ticks = 0;
-        OS_ERR  err;
-
-        ticks = OSTimeGet(&err);
-
-        return (word32) (ticks / OSCfg_TickRate_Hz) * 1000;
-    }
-#elif defined(MICROCHIP_TCPIP_V5)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32) (TickGet() / (TICKS_PER_SECOND / 1000));
-    }
-#elif defined(MICROCHIP_TCPIP)
-    #if defined(MICROCHIP_MPLAB_HARMONY)
-        #include <system/tmr/sys_tmr.h>
-
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32)(SYS_TMR_TickCountGet() /
-                        (SYS_TMR_TickCounterFrequencyGet() / 1000));
-    }
-    #else
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32)(SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000));
-    }
-
-    #endif
-
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        TIME_STRUCT mqxTime;
-
-        _time_get_elapsed(&mqxTime);
-
-        return (word32) mqxTime.SECONDS * 1000;
-    }
-#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
-    #include "include/task.h"
-
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (unsigned int)(((float)xTaskGetTickCount()) /
-                              (configTICK_RATE_HZ / 1000));
-    }
-#elif defined(FREESCALE_KSDK_BM)
-    #include "lwip/sys.h" /* lwIP */
-
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return sys_now();
-    }
-#elif defined(WOLFSSL_TIRTOS)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32) Seconds_get() * 1000;
-    }
-#elif defined(WOLFSSL_UTASKER)
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000));
-    }
-#else
-    /* The time in milliseconds.
-     * Used for tickets to represent difference between when first seen and when
-     * sending.
-     *
-     * returns the time in milliseconds as a 32-bit value.
-     */
-    word32 TimeNowInMilliseconds(void)
-    {
-        struct timeval now;
-
-        if (gettimeofday(&now, 0) < 0)
-            return GETTIME_ERROR;
-        /* Convert to milliseconds number. */
-        return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000);
-    }
-#endif
-#endif /* HAVE_SESSION_TICKET || !NO_PSK */
-
-
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \
-                                    !defined(NO_PSK))
-/* Add input to all handshake hashes.
- *
- * ssl    The SSL/TLS object.
- * input  The data to hash.
- * sz     The size of the data to hash.
- * returns 0 on success, otherwise failure.
- */
-static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz)
-{
-    int ret = BAD_FUNC_ARG;
-
-#ifndef NO_SHA256
-    ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_SHA384
-    ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-#ifdef WOLFSSL_TLS13_SHA512
-    ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz);
-    if (ret != 0)
-        return ret;
-#endif
-
-    return ret;
-}
-#endif
-
-/* Extract the handshake header information.
- *
- * ssl       The SSL/TLS object.
- * input     The buffer holding the message data.
- * inOutIdx  On entry, the index into the buffer of the handshake data.
- *           On exit, the start of the hanshake data.
- * type      Type of handshake message.
- * size      The length of the handshake message data.
- * totalSz   The total size of data in the buffer.
- * returns BUFFER_E if there is not enough input data and 0 on success.
- */
-static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                              byte* type, word32* size, word32 totalSz)
-{
-    const byte* ptr = input + *inOutIdx;
-    (void)ssl;
-
-    *inOutIdx += HANDSHAKE_HEADER_SZ;
-    if (*inOutIdx > totalSz)
-        return BUFFER_E;
-
-    *type = ptr[0];
-    c24to32(&ptr[1], size);
-
-    return 0;
-}
-
-/* Add record layer header to message.
- *
- * output  The buffer to write the record layer header into.
- * length  The length of the record data.
- * type    The type of record message.
- * ssl     The SSL/TLS object.
- */
-static void AddTls13RecordHeader(byte* output, word32 length, byte type,
-                                 WOLFSSL* ssl)
-{
-    RecordLayerHeader* rl;
-
-    rl = (RecordLayerHeader*)output;
-    rl->type    = type;
-    rl->pvMajor = ssl->version.major;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    rl->pvMinor = TLSv1_MINOR;
-#else
-    rl->pvMinor = TLSv1_2_MINOR;
-#endif
-    c16toa((word16)length, rl->length);
-}
-
-/* Add handshake header to message.
- *
- * output      The buffer to write the hanshake header into.
- * length      The length of the handshake data.
- * fragOffset  The offset of the fragment data. (DTLS)
- * fragLength  The length of the fragment data. (DTLS)
- * type        The type of handshake message.
- * ssl         The SSL/TLS object. (DTLS)
- */
-static void AddTls13HandShakeHeader(byte* output, word32 length,
-                                    word32 fragOffset, word32 fragLength,
-                                    byte type, WOLFSSL* ssl)
-{
-    HandShakeHeader* hs;
-    (void)fragOffset;
-    (void)fragLength;
-    (void)ssl;
-
-    /* handshake header */
-    hs = (HandShakeHeader*)output;
-    hs->type = type;
-    c32to24(length, hs->length);
-}
-
-
-/* Add both record layer and handshake header to message.
- *
- * output      The buffer to write the headers into.
- * length      The length of the handshake data.
- * type        The type of record layer message.
- * ssl         The SSL/TLS object. (DTLS)
- */
-static void AddTls13Headers(byte* output, word32 length, byte type,
-                            WOLFSSL* ssl)
-{
-    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
-    word32 outputAdj = RECORD_HEADER_SZ;
-
-    AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl);
-    AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
-}
-
-
-#ifndef NO_CERTS
-/* Add both record layer and fragement handshake header to message.
- *
- * output      The buffer to write the headers into.
- * fragOffset  The offset of the fragment data. (DTLS)
- * fragLength  The length of the fragment data. (DTLS)
- * length      The length of the handshake data.
- * type        The type of record layer message.
- * ssl         The SSL/TLS object. (DTLS)
- */
-static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset,
-                                word32 length, byte type, WOLFSSL* ssl)
-{
-    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
-    word32 outputAdj = RECORD_HEADER_SZ;
-    (void)fragSz;
-
-    AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl);
-    AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz,
-                            type, ssl);
-}
-#endif /* NO_CERTS */
-
-/* Write the sequence number into the buffer.
- * No DTLS v1.3 support.
- *
- * ssl          The SSL/TLS object.
- * verifyOrder  Which set of sequence numbers to use.
- * out          The buffer to write into.
- */
-static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
-{
-    word32 seq[2] = {0, 0};
-
-    if (verifyOrder) {
-        seq[0] = ssl->keys.peer_sequence_number_hi;
-        seq[1] = ssl->keys.peer_sequence_number_lo++;
-        /* handle rollover */
-        if (seq[1] > ssl->keys.peer_sequence_number_lo)
-            ssl->keys.peer_sequence_number_hi++;
-    }
-    else {
-        seq[0] = ssl->keys.sequence_number_hi;
-        seq[1] = ssl->keys.sequence_number_lo++;
-        /* handle rollover */
-        if (seq[1] > ssl->keys.sequence_number_lo)
-            ssl->keys.sequence_number_hi++;
-    }
-
-    c32toa(seq[0], out);
-    c32toa(seq[1], out + OPAQUE32_LEN);
-}
-
-/* Build the nonce for TLS v1.3 encryption and decryption.
- *
- * ssl    The SSL/TLS object.
- * nonce  The nonce data to use when encrypting or decrypting.
- * iv     The derived IV.
- * order  The side on which the message is to be or was sent.
- */
-static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
-                                   int order)
-{
-    int  i;
-
-    /* The nonce is the IV with the sequence XORed into the last bytes. */
-    WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
-    for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++)
-        nonce[i] = iv[i];
-    for (; i < AEAD_NONCE_SZ; i++)
-        nonce[i] ^= iv[i];
-}
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-/* Encrypt with ChaCha20 and create authenication tag with Poly1305.
- *
- * ssl     The SSL/TLS object.
- * output  The buffer to write encrypted data and authentication tag into.
- *         May be the same pointer as input.
- * input   The data to encrypt.
- * sz      The number of bytes to encrypt.
- * nonce   The nonce to use with ChaCha20.
- * aad     The additional authentication data.
- * aadSz   The size of the addition authentication data.
- * tag     The authentication tag buffer.
- * returns 0 on success, otherwise failure.
- */
-static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
-                                    const byte* input, word16 sz, byte* nonce,
-                                    const byte* aad, word16 aadSz, byte* tag)
-{
-    int    ret    = 0;
-    byte   poly[CHACHA20_256_KEY_SIZE];
-
-    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
-    XMEMSET(poly, 0, sizeof(poly));
-
-    /* Set the nonce for ChaCha and get Poly1305 key. */
-    ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0);
-    if (ret != 0)
-        return ret;
-    /* Create Poly1305 key using ChaCha20 keystream. */
-    ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly));
-    if (ret != 0)
-        return ret;
-    /* Encrypt the plain text. */
-    ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz);
-    if (ret != 0) {
-        ForceZero(poly, sizeof(poly));
-        return ret;
-    }
-
-    /* Set key for Poly1305. */
-    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
-    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
-    if (ret != 0)
-        return ret;
-    /* Add authentication code of encrypted data to end. */
-    ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz,
-                          tag, POLY1305_AUTH_SZ);
-
-    return ret;
-}
-#endif
-
-/* Encrypt data for TLS v1.3.
- *
- * ssl     The SSL/TLS object.
- * output  The buffer to write encrypted data and authentication tag into.
- *         May be the same pointer as input.
- * input   The record header and data to encrypt.
- * sz      The number of bytes to encrypt.
- * aad     The additional authentication data.
- * aadSz   The size of the addition authentication data.
- * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto
- * returns 0 on success, otherwise failure.
- */
-static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
-                        word16 sz, const byte* aad, word16 aadSz, int asyncOkay)
-{
-    int    ret    = 0;
-    word16 dataSz = sz - ssl->specs.aead_mac_size;
-    word16 macSz  = ssl->specs.aead_mac_size;
-    word32 nonceSz = 0;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV* asyncDev = NULL;
-    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
-#endif
-
-    WOLFSSL_ENTER("EncryptTls13");
-
-    (void)output;
-    (void)input;
-    (void)sz;
-    (void)dataSz;
-    (void)macSz;
-    (void)asyncOkay;
-    (void)nonceSz;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ssl->error == WC_PENDING_E) {
-        ssl->error = 0; /* clear async */
-    }
-#endif
-
-    switch (ssl->encrypt.state) {
-        case CIPHER_STATE_BEGIN:
-        {
-        #ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Data to encrypt");
-            WOLFSSL_BUFFER(input, dataSz);
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
-                                        !defined(WOLFSSL_TLS13_DRAFT_23)
-            WOLFSSL_MSG("Additional Authentication Data");
-            WOLFSSL_BUFFER(aad, aadSz);
-#endif
-        #endif
-
-            if (ssl->encrypt.nonce == NULL)
-                ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
-                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-            if (ssl->encrypt.nonce == NULL)
-                return MEMORY_E;
-
-            BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV,
-                            CUR_ORDER);
-
-            /* Advance state and proceed */
-            ssl->encrypt.state = CIPHER_STATE_DO;
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_DO:
-        {
-            switch (ssl->specs.bulk_cipher_algorithm) {
-            #ifdef BUILD_AESGCM
-                case wolfssl_aes_gcm:
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    /* initialize event */
-                    asyncDev = &ssl->encrypt.aes->asyncDev;
-                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
-                    if (ret != 0)
-                        break;
-                #endif
-
-                    nonceSz = AESGCM_NONCE_SZ;
-                    ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input,
-                        dataSz, ssl->encrypt.nonce, nonceSz,
-                        output + dataSz, macSz, aad, aadSz);
-                    break;
-            #endif
-
-            #ifdef HAVE_AESCCM
-                case wolfssl_aes_ccm:
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    /* initialize event */
-                    asyncDev = &ssl->encrypt.aes->asyncDev;
-                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
-                    if (ret != 0)
-                        break;
-                #endif
-
-                    nonceSz = AESCCM_NONCE_SZ;
-                    ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input,
-                        dataSz, ssl->encrypt.nonce, nonceSz,
-                        output + dataSz, macSz, aad, aadSz);
-                    break;
-            #endif
-
-            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-                case wolfssl_chacha:
-                    ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz,
-                        ssl->encrypt.nonce, aad, aadSz, output + dataSz);
-                    break;
-            #endif
-
-                default:
-                    WOLFSSL_MSG("wolfSSL Encrypt programming error");
-                    return ENCRYPT_ERROR;
-            }
-
-            /* Advance state */
-            ssl->encrypt.state = CIPHER_STATE_END;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E) {
-                /* if async is not okay, then block */
-                if (!asyncOkay) {
-                    ret = wc_AsyncWait(ret, asyncDev, event_flags);
-                }
-                else {
-                    /* If pending, then leave and return will resume below */
-                    return wolfSSL_AsyncPush(ssl, asyncDev);
-                }
-            }
-        #endif
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_END:
-        {
-            #ifdef WOLFSSL_DEBUG_TLS
-                WOLFSSL_MSG("Nonce");
-                WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size);
-                WOLFSSL_MSG("Encrypted data");
-                WOLFSSL_BUFFER(output, dataSz);
-                WOLFSSL_MSG("Authentication Tag");
-                WOLFSSL_BUFFER(output + dataSz, macSz);
-            #endif
-
-            ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ);
-
-            break;
-        }
-    }
-
-    /* Reset state */
-    ssl->encrypt.state = CIPHER_STATE_BEGIN;
-
-    return ret;
-}
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-/* Decrypt with ChaCha20 and check authenication tag with Poly1305.
- *
- * ssl     The SSL/TLS object.
- * output  The buffer to write decrypted data into.
- *         May be the same pointer as input.
- * input   The data to decrypt.
- * sz      The number of bytes to decrypt.
- * nonce   The nonce to use with ChaCha20.
- * aad     The additional authentication data.
- * aadSz   The size of the addition authentication data.
- * tagIn   The authentication tag data from packet.
- * returns 0 on success, otherwise failure.
- */
-static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
-                                    const byte* input, word16 sz, byte* nonce,
-                                    const byte* aad, word16 aadSz,
-                                    const byte* tagIn)
-{
-    int ret;
-    byte tag[POLY1305_AUTH_SZ];
-    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
-
-    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
-    XMEMSET(poly, 0, sizeof(poly));
-
-    /* Set nonce and get Poly1305 key. */
-    ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0);
-    if (ret != 0)
-        return ret;
-    /* Use ChaCha20 keystream to get Poly1305 key for tag. */
-    ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly));
-    if (ret != 0)
-        return ret;
-
-    /* Set key for Poly1305. */
-    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
-    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
-    if (ret != 0)
-        return ret;
-    /* Generate authentication tag for encrypted data. */
-    if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz,
-                                    (byte*)input, sz, tag, sizeof(tag))) != 0) {
-        return ret;
-    }
-
-    /* Check tag sent along with packet. */
-    if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) {
-        WOLFSSL_MSG("MAC did not match");
-        return VERIFY_MAC_ERROR;
-    }
-
-    /* If the tag was good decrypt message. */
-    ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz);
-
-    return ret;
-}
-#endif
-
-/* Decrypt data for TLS v1.3.
- *
- * ssl     The SSL/TLS object.
- * output  The buffer to write decrypted data into.
- *         May be the same pointer as input.
- * input   The data to decrypt and authentication tag.
- * sz      The length of the encrypted data plus authentication tag.
- * aad     The additional authentication data.
- * aadSz   The size of the addition authentication data.
- * returns 0 on success, otherwise failure.
- */
-int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
-                 const byte* aad, word16 aadSz)
-{
-    int    ret    = 0;
-    word16 dataSz = sz - ssl->specs.aead_mac_size;
-    word16 macSz  = ssl->specs.aead_mac_size;
-    word32 nonceSz = 0;
-
-    WOLFSSL_ENTER("DecryptTls13");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
-    if (ret != WC_NOT_PENDING_E) {
-        /* check for still pending */
-        if (ret == WC_PENDING_E)
-            return ret;
-
-        ssl->error = 0; /* clear async */
-
-        /* let failures through so CIPHER_STATE_END logic is run */
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->decrypt.state = CIPHER_STATE_BEGIN;
-    }
-
-    (void)output;
-    (void)input;
-    (void)sz;
-    (void)dataSz;
-    (void)macSz;
-    (void)nonceSz;
-
-    switch (ssl->decrypt.state) {
-        case CIPHER_STATE_BEGIN:
-        {
-        #ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Data to decrypt");
-            WOLFSSL_BUFFER(input, dataSz);
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
-                                        !defined(WOLFSSL_TLS13_DRAFT_23)
-            WOLFSSL_MSG("Additional Authentication Data");
-            WOLFSSL_BUFFER(aad, aadSz);
-#endif
-            WOLFSSL_MSG("Authentication tag");
-            WOLFSSL_BUFFER(input + dataSz, macSz);
-        #endif
-
-            if (ssl->decrypt.nonce == NULL)
-                ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
-                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
-            if (ssl->decrypt.nonce == NULL)
-                return MEMORY_E;
-
-            BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
-                            PEER_ORDER);
-
-            /* Advance state and proceed */
-            ssl->decrypt.state = CIPHER_STATE_DO;
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_DO:
-        {
-            switch (ssl->specs.bulk_cipher_algorithm) {
-            #ifdef BUILD_AESGCM
-                case wolfssl_aes_gcm:
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    /* initialize event */
-                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
-                        WC_ASYNC_FLAG_CALL_AGAIN);
-                    if (ret != 0)
-                        break;
-                #endif
-
-                    nonceSz = AESGCM_NONCE_SZ;
-                    ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input,
-                        dataSz, ssl->decrypt.nonce, nonceSz,
-                        input + dataSz, macSz, aad, aadSz);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                                                   &ssl->decrypt.aes->asyncDev);
-                    }
-                #endif
-                    break;
-            #endif
-
-            #ifdef HAVE_AESCCM
-                case wolfssl_aes_ccm:
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    /* initialize event */
-                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
-                        WC_ASYNC_FLAG_CALL_AGAIN);
-                    if (ret != 0)
-                        break;
-                #endif
-
-                    nonceSz = AESCCM_NONCE_SZ;
-                    ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input,
-                        dataSz, ssl->decrypt.nonce, nonceSz,
-                        input + dataSz, macSz, aad, aadSz);
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    if (ret == WC_PENDING_E) {
-                        ret = wolfSSL_AsyncPush(ssl,
-                                                   &ssl->decrypt.aes->asyncDev);
-                    }
-                #endif
-                    break;
-            #endif
-
-            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-                case wolfssl_chacha:
-                    ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz,
-                        ssl->decrypt.nonce, aad, aadSz, input + dataSz);
-                    break;
-            #endif
-
-                default:
-                    WOLFSSL_MSG("wolfSSL Decrypt programming error");
-                    return DECRYPT_ERROR;
-            }
-
-            /* Advance state */
-            ssl->decrypt.state = CIPHER_STATE_END;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            /* If pending, leave now */
-            if (ret == WC_PENDING_E) {
-                return ret;
-            }
-        #endif
-        }
-        FALL_THROUGH;
-
-        case CIPHER_STATE_END:
-        {
-        #ifdef WOLFSSL_DEBUG_TLS
-            WOLFSSL_MSG("Nonce");
-            WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size);
-            WOLFSSL_MSG("Decrypted data");
-            WOLFSSL_BUFFER(output, dataSz);
-        #endif
-
-            ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ);
-
-            break;
-        }
-    }
-
-#ifndef WOLFSSL_EARLY_DATA
-    if (ret < 0) {
-        SendAlert(ssl, alert_fatal, bad_record_mac);
-        ret = VERIFY_MAC_ERROR;
-    }
-#endif
-
-    return ret;
-}
-
-/* Persistable BuildTls13Message arguments */
-typedef struct BuildMsg13Args {
-    word32 sz;
-    word32 idx;
-    word32 headerSz;
-    word16 size;
-} BuildMsg13Args;
-
-static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs)
-{
-    BuildMsg13Args* args = (BuildMsg13Args*)pArgs;
-
-    (void)ssl;
-    (void)args;
-
-    /* no allocations in BuildTls13Message */
-}
-
-/* Build SSL Message, encrypted.
- * TLS v1.3 encryption is AEAD only.
- *
- * ssl         The SSL/TLS object.
- * output      The buffer to write record message to.
- * outSz       Size of the buffer being written into.
- * input       The record data to encrypt (excluding record header).
- * inSz        The size of the record data.
- * type        The recorder header content type.
- * hashOutput  Whether to hash the unencrypted record data.
- * sizeOnly    Only want the size of the record message.
- * asyncOkay   If non-zero can return WC_PENDING_E, otherwise blocks on crypto
- * returns the size of the encrypted record message or negative value on error.
- */
-int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
-                int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
-{
-    int ret = 0;
-    BuildMsg13Args* args;
-    BuildMsg13Args  lcl_args;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    args = (BuildMsg13Args*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#endif
-
-    WOLFSSL_ENTER("BuildTls13Message");
-
-    ret = WC_NOT_PENDING_E;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (asyncOkay) {
-        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
-        if (ret != WC_NOT_PENDING_E) {
-            /* Check for error */
-            if (ret < 0)
-                goto exit_buildmsg;
-        }
-    }
-    else
-#endif
-    {
-        args = &lcl_args;
-    }
-
-    /* Reset state */
-    if (ret == WC_NOT_PENDING_E) {
-        ret = 0;
-        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
-        XMEMSET(args, 0, sizeof(BuildMsg13Args));
-
-        args->sz = RECORD_HEADER_SZ + inSz;
-        args->idx  = RECORD_HEADER_SZ;
-        args->headerSz = RECORD_HEADER_SZ;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeBuildMsg13Args;
-    #endif
-    }
-
-    switch (ssl->options.buildMsgState) {
-        case BUILD_MSG_BEGIN:
-        {
-           /* catch mistaken sizeOnly parameter */
-            if (sizeOnly) {
-                if (output || input) {
-                    WOLFSSL_MSG("BuildTls13Message with sizeOnly "
-                                "doesn't need input or output");
-                    return BAD_FUNC_ARG;
-                }
-            }
-            else if (output == NULL || input == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            /* Record layer content type at the end of record data. */
-            args->sz++;
-            /* Authentication data at the end. */
-            args->sz += ssl->specs.aead_mac_size;
-
-            if (sizeOnly)
-                return args->sz;
-
-            if (args->sz > (word32)outSz) {
-                WOLFSSL_MSG("Oops, want to write past output buffer size");
-                return BUFFER_E;
-            }
-
-            /* Record data length. */
-            args->size = (word16)(args->sz - args->headerSz);
-            /* Write/update the record header with the new size.
-             * Always have the content type as application data for encrypted
-             * messages in TLS v1.3.
-             */
-            AddTls13RecordHeader(output, args->size, application_data, ssl);
-
-            /* TLS v1.3 can do in place encryption. */
-            if (input != output + args->idx)
-                XMEMCPY(output + args->idx, input, inSz);
-            args->idx += inSz;
-
-            ssl->options.buildMsgState = BUILD_MSG_HASH;
-        }
-        FALL_THROUGH;
-
-        case BUILD_MSG_HASH:
-        {
-            if (hashOutput) {
-                ret = HashOutput(ssl, output, args->headerSz + inSz, 0);
-                if (ret != 0)
-                    goto exit_buildmsg;
-            }
-
-            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
-        }
-        FALL_THROUGH;
-
-        case BUILD_MSG_ENCRYPT:
-        {
-            /* The real record content type goes at the end of the data. */
-            output[args->idx++] = (byte)type;
-
-        #ifdef ATOMIC_USER
-            if (ssl->ctx->MacEncryptCb) {
-                /* User Record Layer Callback handling */
-                byte* mac = output + args->idx;
-                output += args->headerSz;
-
-                ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0,
-                        output, output, args->size, ssl->MacEncryptCtx);
-            }
-            else
-        #endif
-            {
-#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \
-                                       defined(WOLFSSL_TLS13_DRAFT_23)
-                output += args->headerSz;
-                ret = EncryptTls13(ssl, output, output, args->size, NULL, 0,
-                                                                     asyncOkay);
-#else
-                const byte* aad = output;
-                output += args->headerSz;
-                ret = EncryptTls13(ssl, output, output, args->size, aad,
-                                   RECORD_HEADER_SZ, asyncOkay);
-#endif
-            }
-            break;
-        }
-    }
-
-exit_buildmsg:
-
-    WOLFSSL_LEAVE("BuildTls13Message", ret);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-#endif
-
-    /* make sure build message state is reset */
-    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
-
-    /* return sz on success */
-    if (ret == 0)
-        ret = args->sz;
-
-    /* Final cleanup */
-    FreeBuildMsg13Args(ssl, args);
-
-    return ret;
-}
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-/* Find the cipher suite in the suites set in the SSL.
- *
- * ssl    SSL/TLS object.
- * suite  Cipher suite to look for.
- * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise.
- */
-static int FindSuite(WOLFSSL* ssl, byte* suite)
-{
-    int i;
-
-    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
-        if (ssl->suites->suites[i+0] == suite[0] &&
-            ssl->suites->suites[i+1] == suite[1]) {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-#endif
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
-/* Create Cookie extension using the hash of the first ClientHello.
- *
- * ssl     SSL/TLS object.
- * hash    The hash data.
- * hashSz  The size of the hash data in bytes.
- * returns 0 on success, otherwise failure.
- */
-static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
-{
-    int  ret;
-    byte mac[WC_MAX_DIGEST_SIZE];
-    Hmac cookieHmac;
-    byte cookieType;
-    byte macSz;
-
-#if !defined(NO_SHA) && defined(NO_SHA256)
-    cookieType = SHA;
-    macSz = WC_SHA_DIGEST_SIZE;
-#endif /* NO_SHA */
-#ifndef NO_SHA256
-    cookieType = WC_SHA256;
-    macSz = WC_SHA256_DIGEST_SIZE;
-#endif /* NO_SHA256 */
-
-    ret = wc_HmacSetKey(&cookieHmac, cookieType,
-                        ssl->buffers.tls13CookieSecret.buffer,
-                        ssl->buffers.tls13CookieSecret.length);
-    if (ret != 0)
-        return ret;
-    if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0)
-        return ret;
-    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
-        return ret;
-
-    /* The cookie data is the hash and the integrity check. */
-    return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1);
-}
-#endif
-
-/* Restart the Hanshake hash with a hash of the previous messages.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int RestartHandshakeHash(WOLFSSL* ssl)
-{
-    int    ret;
-    Hashes hashes;
-    byte   header[HANDSHAKE_HEADER_SZ];
-    byte*  hash = NULL;
-    byte   hashSz = 0;
-
-    ret = BuildCertHashes(ssl, &hashes);
-    if (ret != 0)
-        return ret;
-    switch (ssl->specs.mac_algorithm) {
-    #ifndef NO_SHA256
-        case sha256_mac:
-            hash = hashes.sha256;
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            hash = hashes.sha384;
-            break;
-    #endif
-    #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            hash = hashes.sha512;
-            break;
-    #endif
-    }
-    hashSz = ssl->specs.hash_size;
-    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
-
-    WOLFSSL_MSG("Restart Hash");
-    WOLFSSL_BUFFER(hash, hashSz);
-
-#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
-    if (ssl->options.sendCookie) {
-        byte   cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
-        TLSX*  ext;
-        word32 idx = 0;
-
-        /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */
-        cookie[idx++] = hashSz;
-        XMEMCPY(cookie + idx, hash, hashSz);
-        idx += hashSz;
-        cookie[idx++] = ssl->options.cipherSuite0;
-        cookie[idx++] = ssl->options.cipherSuite;
-        if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) {
-            KeyShareEntry* kse = (KeyShareEntry*)ext->data;
-            c16toa(kse->group, cookie + idx);
-            idx += OPAQUE16_LEN;
-        }
-        return CreateCookie(ssl, cookie, idx);
-    }
-#endif
-
-    ret = InitHandshakeHashes(ssl);
-    if (ret != 0)
-        return ret;
-    ret = HashOutputRaw(ssl, header, sizeof(header));
-    if (ret != 0)
-        return ret;
-    return HashOutputRaw(ssl, hash, hashSz);
-}
-
-/* The value in the random field of a ServerHello to indicate
- * HelloRetryRequest.
- */
-static byte helloRetryRequestRandom[] = {
-    0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
-    0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
-    0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
-    0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
-};
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-
-#ifndef NO_WOLFSSL_CLIENT
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-/* Setup pre-shared key based on the details in the extension data.
- *
- * ssl  SSL/TLS object.
- * psk  Pre-shared key extension data.
- * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and
- * other negative value on failure.
- */
-static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk)
-{
-    int ret;
-    byte suite[2];
-
-    if (ssl->options.noPskDheKe && ssl->arrays->preMasterSz != 0)
-        return PSK_KEY_ERROR;
-
-    suite[0] = psk->cipherSuite0;
-    suite[1] = psk->cipherSuite;
-    if (!FindSuite(ssl, suite))
-        return PSK_KEY_ERROR;
-
-    ssl->options.cipherSuite0 = psk->cipherSuite0;
-    ssl->options.cipherSuite  = psk->cipherSuite;
-    if ((ret = SetCipherSpecs(ssl)) != 0)
-        return ret;
-
-#ifdef HAVE_SESSION_TICKET
-    if (psk->resumption) {
-    #ifdef WOLFSSL_EARLY_DATA
-        if (ssl->session.maxEarlyDataSz == 0)
-            ssl->earlyData = no_early_data;
-    #endif
-        /* Resumption PSK is master secret. */
-        ssl->arrays->psk_keySz = ssl->specs.hash_size;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-        XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
-                ssl->arrays->psk_keySz);
-#else
-        if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
-                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
-            return ret;
-        }
-#endif
-    }
-#endif
-#ifndef NO_PSK
-    if (!psk->resumption) {
-        /* Get the pre-shared key. */
-        ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
-                (char *)psk->identity, ssl->arrays->client_identity,
-                MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
-        if (ssl->arrays->psk_keySz == 0 ||
-                                 ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
-            return PSK_KEY_ERROR;
-        }
-        /* TODO: Callback should be able to specify ciphersuite. */
-
-        if (psk->cipherSuite0 != TLS13_BYTE ||
-            psk->cipherSuite  != WOLFSSL_DEF_PSK_CIPHER) {
-            return PSK_KEY_ERROR;
-        }
-    }
-#endif
-
-    /* Derive the early secret using the PSK. */
-    return DeriveEarlySecret(ssl);
-}
-
-/* Derive and write the binders into the ClientHello in space left when
- * writing the Pre-Shared Key extension.
- *
- * ssl     The SSL/TLS object.
- * output  The buffer containing the ClientHello.
- * idx     The index at the end of the completed ClientHello.
- * returns 0 on success and otherwise failure.
- */
-static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx)
-{
-    int           ret;
-    TLSX*         ext;
-    PreSharedKey* current;
-    byte          binderKey[WC_MAX_DIGEST_SIZE];
-    word16        len;
-
-    WOLFSSL_ENTER("WritePSKBinders");
-
-    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
-    if (ext == NULL)
-        return SANITY_MSG_E;
-
-    /* Get the size of the binders to determine where to write binders. */
-    idx -= TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
-                                            client_hello);
-
-    /* Hash truncated ClientHello - up to binders. */
-    ret = HashOutput(ssl, output, idx, 0);
-    if (ret != 0)
-        return ret;
-
-    current = (PreSharedKey*)ext->data;
-    /* Calculate the binder for each identity based on previous handshake data.
-     */
-    while (current != NULL) {
-        if ((ret = SetupPskKey(ssl, current)) != 0)
-            return ret;
-
-    #ifdef HAVE_SESSION_TICKET
-        if (current->resumption)
-            ret = DeriveBinderKeyResume(ssl, binderKey);
-    #endif
-    #ifndef NO_PSK
-        if (!current->resumption)
-            ret = DeriveBinderKey(ssl, binderKey);
-    #endif
-        if (ret != 0)
-            return ret;
-
-        /* Derive the Finished message secret. */
-        ret = DeriveFinishedSecret(ssl, binderKey,
-                                             ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        /* Build the HMAC of the handshake message data = binder. */
-        ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret,
-            current->binder, &current->binderLen);
-        if (ret != 0)
-            return ret;
-
-        current = current->next;
-    }
-
-    /* Data entered into extension, now write to message. */
-    len = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx,
-                                         client_hello);
-
-    /* Hash binders to complete the hash of the ClientHello. */
-    ret = HashOutputRaw(ssl, output + idx, len);
-    if (ret < 0)
-        return ret;
-
-    #ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-        if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0)
-            return ret;
-
-        /* Derive early data encryption key. */
-        ret = DeriveTls13Keys(ssl, early_data_key, ENCRYPT_SIDE_ONLY, 1);
-        if (ret != 0)
-            return ret;
-        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-            return ret;
-    }
-    #endif
-
-    WOLFSSL_LEAVE("WritePSKBinders", ret);
-
-    return ret;
-}
-#endif
-
-/* handle generation of TLS 1.3 client_hello (1) */
-/* Send a ClientHello message to the server.
- * Include the information required to start a handshake with servers using
- * protocol versions less than TLS v1.3.
- * Only a client will send this message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success and otherwise failure.
- */
-int SendTls13ClientHello(WOLFSSL* ssl)
-{
-    byte*  output;
-    word16 length;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    int    sendSz;
-    int    ret;
-
-    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
-    WOLFSSL_ENTER("SendTls13ClientHello");
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->options.resuming &&
-            (ssl->session.version.major != ssl->version.major ||
-             ssl->session.version.minor != ssl->version.minor)) {
-    #ifndef WOLFSSL_NO_TLS12
-        if (ssl->session.version.major == ssl->version.major &&
-            ssl->session.version.minor < ssl->version.minor) {
-            /* Cannot resume with a different protocol version. */
-            ssl->options.resuming = 0;
-            ssl->version.major = ssl->session.version.major;
-            ssl->version.minor = ssl->session.version.minor;
-            return SendClientHello(ssl);
-        }
-        else
-    #endif
-            return VERSION_ERROR;
-    }
-#endif
-
-    if (ssl->suites == NULL) {
-        WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello");
-        return SUITES_ERROR;
-    }
-
-    /* Version | Random | Session Id | Cipher Suites | Compression */
-    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz +
-             SUITE_LEN + COMP_LEN + ENUM_LEN;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-    length += ID_LEN;
-    #else
-    if (ssl->session.sessionIDSz > 0)
-        length += ssl->session.sessionIDSz;
-    #endif
-#endif
-
-    /* Auto populate extensions supported unless user defined. */
-    if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
-        return ret;
-#ifdef WOLFSSL_EARLY_DATA
-    #ifndef NO_PSK
-        if (!ssl->options.resuming && ssl->options.client_psk_cb == NULL)
-    #else
-        if (!ssl->options.resuming)
-    #endif
-            ssl->earlyData = no_early_data;
-    if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
-        ssl->earlyData = no_early_data;
-    if (ssl->earlyData == no_early_data)
-        TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap);
-    if (ssl->earlyData != no_early_data &&
-                                       (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) {
-        return ret;
-    }
-#endif
-#ifdef HAVE_QSH
-    if (QSH_Init(ssl) != 0)
-        return MEMORY_E;
-#endif
-    /* Include length of TLS extensions. */
-    ret = TLSX_GetRequestSize(ssl, client_hello, &length);
-    if (ret != 0)
-        return ret;
-
-    /* Total message size. */
-    sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, length, client_hello, ssl);
-
-    /* Protocol version - negotiation now in extension: supported_versions. */
-    output[idx++] = SSLv3_MAJOR;
-    output[idx++] = TLSv1_2_MINOR;
-    /* Keep for downgrade. */
-    ssl->chVersion = ssl->version;
-
-    /* Client Random */
-    if (ssl->options.connectState == CONNECT_BEGIN) {
-        ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
-        if (ret != 0)
-            return ret;
-
-        /* Store random for possible second ClientHello. */
-        XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
-    }
-    else
-        XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
-    idx += RAN_LEN;
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* TLS v1.3 does not use session id - 0 length. */
-    output[idx++] = 0;
-#else
-    if (ssl->session.sessionIDSz > 0) {
-        /* Session resumption for old versions of protocol. */
-        output[idx++] = ID_LEN;
-        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
-        idx += ID_LEN;
-    }
-    else {
-    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
-        output[idx++] = ID_LEN;
-        XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN);
-        idx += ID_LEN;
-    #else
-        /* TLS v1.3 does not use session id - 0 length. */
-        output[idx++] = 0;
-    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
-    }
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-
-    /* Cipher suites */
-    c16toa(ssl->suites->suiteSz, output + idx);
-    idx += OPAQUE16_LEN;
-    XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
-    idx += ssl->suites->suiteSz;
-
-    /* Compression not supported in TLS v1.3. */
-    output[idx++] = COMP_LEN;
-    output[idx++] = NO_COMPRESSION;
-
-    /* Write out extensions for a request. */
-    length = 0;
-    ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length);
-    if (ret != 0)
-        return ret;
-    idx += length;
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    /* Resumption has a specific set of extensions and binder is calculated
-     * for each identity.
-     */
-    if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY))
-        ret = WritePSKBinders(ssl, output, idx);
-    else
-#endif
-        ret = HashOutput(ssl, output, idx, 0);
-    if (ret != 0)
-        return ret;
-
-    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
-    if (ssl->toInfoOn) {
-        AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
-                      WRITE_PROTO, ssl->heap);
-    }
-#endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13ClientHello", ret);
-    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
-
-    return ret;
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* handle rocessing of TLS 1.3 hello_retry_request (6) */
-/* Parse and handle a HelloRetryRequest message.
- * Only a client will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of
- *           HelloRetryRequest.
- *           On exit, the index of byte after the HelloRetryRequest message.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input,
-                                    word32* inOutIdx, word32 totalSz)
-{
-    int             ret;
-    word32          begin = *inOutIdx;
-    word32          i = begin;
-    word16          totalExtSz;
-    ProtocolVersion pv;
-
-    WOLFSSL_ENTER("DoTls13HelloRetryRequest");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "HelloRetryRequest");
-    if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo);
-#endif
-
-    /* Version info and length field of extension data. */
-    if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-        return BUFFER_ERROR;
-
-    /* Protocol version. */
-    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-    i += OPAQUE16_LEN;
-    ret = CheckVersion(ssl, pv);
-    if (ret != 0)
-        return ret;
-
-    /* Length of extension data. */
-    ato16(&input[i], &totalExtSz);
-    i += OPAQUE16_LEN;
-    if (totalExtSz == 0) {
-        WOLFSSL_MSG("HelloRetryRequest must contain extensions");
-        return MISSING_HANDSHAKE_DATA;
-    }
-
-    /* Extension data. */
-    if (i - begin + totalExtSz > totalSz)
-        return BUFFER_ERROR;
-    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
-                          hello_retry_request, NULL)) != 0)
-        return ret;
-    /* The KeyShare extension parsing fails when not valid. */
-
-    /* Move index to byte after message. */
-    *inOutIdx = i + totalExtSz;
-
-    ssl->options.tls1_3 = 1;
-    ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
-
-    WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret);
-
-    return ret;
-}
-#endif
-
-
-/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
-/* Handle the ServerHello message from the server.
- * Only a client will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of ServerHello.
- *           On exit, the index of byte after the ServerHello message.
- * helloSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                       word32 helloSz, byte* extMsgType)
-{
-    ProtocolVersion pv;
-    word32          i = *inOutIdx;
-    word32          begin = i;
-    int             ret;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    byte            sessIdSz;
-    const byte*     sessId;
-    byte            b;
-#endif
-    word16          totalExtSz;
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    TLSX*           ext;
-    PreSharedKey*   psk = NULL;
-#endif
-
-    WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
-    WOLFSSL_ENTER("DoTls13ServerHello");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
-    if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
-#endif
-
-    /* Protocol version length check. */
-    if (OPAQUE16_LEN > helloSz)
-        return BUFFER_ERROR;
-
-    /* Protocol version */
-    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-    i += OPAQUE16_LEN;
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ret = CheckVersion(ssl, pv);
-    if (ret != 0)
-        return ret;
-    if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) {
-#ifndef WOLFSSL_NO_TLS12
-        if (ssl->options.downgrade) {
-            ssl->version = pv;
-            return DoServerHello(ssl, input, inOutIdx, helloSz);
-        }
-#endif
-
-        WOLFSSL_MSG("Client using higher version, fatal error");
-        return VERSION_ERROR;
-    }
-#else
-#ifndef WOLFSSL_NO_TLS12
-    if (pv.major == ssl->version.major  && pv.minor < TLSv1_2_MINOR &&
-                                                       ssl->options.downgrade) {
-        /* Force client hello version 1.2 to work for static RSA. */
-        ssl->chVersion.minor = TLSv1_2_MINOR;
-        ssl->version.minor = TLSv1_2_MINOR;
-        return DoServerHello(ssl, input, inOutIdx, helloSz);
-    }
-#endif
-    if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR)
-        return VERSION_ERROR;
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Random length check */
-    if ((i - begin) + RAN_LEN > helloSz)
-        return BUFFER_ERROR;
-#else
-    /* Random and session id length check */
-    if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz)
-        return BUFFER_ERROR;
-
-    if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0)
-        *extMsgType = hello_retry_request;
-#endif
-
-    /* Server random - keep for debugging. */
-    XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
-    i += RAN_LEN;
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Session id */
-    sessIdSz = input[i++];
-    if ((i - begin) + sessIdSz > helloSz)
-        return BUFFER_ERROR;
-    sessId = input + i;
-    i += sessIdSz;
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-    ssl->options.haveSessionId = 1;
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Ciphersuite check */
-    if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
-        return BUFFER_ERROR;
-#else
-    /* Ciphersuite and compression check */
-    if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
-        return BUFFER_ERROR;
-#endif
-
-    /* Set the cipher suite from the message. */
-    ssl->options.cipherSuite0 = input[i++];
-    ssl->options.cipherSuite  = input[i++];
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Compression */
-    b = input[i++];
-    if (b != 0) {
-        WOLFSSL_MSG("Must be no compression types in list");
-        return INVALID_PARAMETER;
-    }
-#endif
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    if ((i - begin) + OPAQUE16_LEN > helloSz) {
-        if (!ssl->options.downgrade)
-            return BUFFER_ERROR;
-#ifndef WOLFSSL_NO_TLS12
-        ssl->version.minor = TLSv1_2_MINOR;
-#endif
-        ssl->options.haveEMS = 0;
-    }
-    if ((i - begin) < helloSz)
-#endif
-    {
-        /* Get extension length and length check. */
-        if ((i - begin) + OPAQUE16_LEN > helloSz)
-            return BUFFER_ERROR;
-        ato16(&input[i], &totalExtSz);
-        i += OPAQUE16_LEN;
-        if ((i - begin) + totalExtSz > helloSz)
-            return BUFFER_ERROR;
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-        if (ssl->options.downgrade)
-            ssl->version.minor = TLSv1_2_MINOR;
-#endif
-        /* Parse and handle extensions. */
-        ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType,
-                                                                          NULL);
-        if (ret != 0)
-            return ret;
-
-        i += totalExtSz;
-    }
-    *inOutIdx = i;
-
-    ssl->options.serverState = SERVER_HELLO_COMPLETE;
-
-#ifdef HAVE_SECRET_CALLBACK
-    if (ssl->sessionSecretCb != NULL) {
-        int secretSz = SECRET_LEN;
-        ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
-                                   &secretSz, ssl->sessionSecretCtx);
-        if (ret != 0 || secretSz != SECRET_LEN)
-            return SESSION_SECRET_CB_E;
-    }
-#endif /* HAVE_SECRET_CALLBACK */
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Version only negotiated in extensions for TLS v1.3.
-     * Only now do we know how to deal with session id.
-     */
-    if (!IsAtLeastTLSv1_3(ssl->version)) {
-#ifndef WOLFSSL_NO_TLS12
-        ssl->arrays->sessionIDSz = sessIdSz;
-
-        if (ssl->arrays->sessionIDSz > ID_LEN) {
-            WOLFSSL_MSG("Invalid session ID size");
-            ssl->arrays->sessionIDSz = 0;
-            return BUFFER_ERROR;
-        }
-        else if (ssl->arrays->sessionIDSz) {
-            XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz);
-            ssl->options.haveSessionId = 1;
-        }
-
-        /* Force client hello version 1.2 to work for static RSA. */
-        ssl->chVersion.minor = TLSv1_2_MINOR;
-        /* Complete TLS v1.2 processing of ServerHello. */
-        ret = CompleteServerHello(ssl);
-#else
-        WOLFSSL_MSG("Client using higher version, fatal error");
-        ret = VERSION_ERROR;
-#endif
-
-        WOLFSSL_LEAVE("DoTls13ServerHello", ret);
-
-        return ret;
-    }
-
-    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
-    if (sessIdSz == 0)
-        return INVALID_PARAMETER;
-    if (ssl->session.sessionIDSz != 0) {
-        if (ssl->session.sessionIDSz != sessIdSz ||
-                   XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) {
-            return INVALID_PARAMETER;
-        }
-    }
-    else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0)
-        return INVALID_PARAMETER;
-    #else
-    if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
-                  XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) {
-        WOLFSSL_MSG("Server sent different session id");
-        return INVALID_PARAMETER;
-    }
-    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
-#endif
-
-    ret = SetCipherSpecs(ssl);
-    if (ret != 0)
-        return ret;
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    if (*extMsgType == server_hello)
-#endif
-    {
-        ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
-        if (ext != NULL)
-            psk = (PreSharedKey*)ext->data;
-        while (psk != NULL && !psk->chosen)
-            psk = psk->next;
-        if (psk == NULL) {
-            ssl->options.resuming = 0;
-            ssl->arrays->psk_keySz = 0;
-            XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN);
-        }
-        else if ((ret = SetupPskKey(ssl, psk)) != 0)
-            return ret;
-    }
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ssl->keys.encryptionOn = 1;
-#else
-    if (*extMsgType == server_hello) {
-        ssl->keys.encryptionOn = 1;
-        ssl->options.serverState = SERVER_HELLO_COMPLETE;
-    }
-    else {
-        ssl->options.tls1_3 = 1;
-        ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
-
-        ret = RestartHandshakeHash(ssl);
-    }
-#endif
-
-    WOLFSSL_LEAVE("DoTls13ServerHello", ret);
-    WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
-
-    return ret;
-}
-
-/* handle processing TLS 1.3 encrypted_extensions (8) */
-/* Parse and handle an EncryptedExtensions message.
- * Only a client will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of
- *           EncryptedExtensions.
- *           On exit, the index of byte after the EncryptedExtensions
- *           message.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input,
-                                      word32* inOutIdx, word32 totalSz)
-{
-    int    ret;
-    word32 begin = *inOutIdx;
-    word32 i = begin;
-    word16 totalExtSz;
-
-    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
-    WOLFSSL_ENTER("DoTls13EncryptedExtensions");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "EncryptedExtensions");
-    if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo);
-#endif
-
-    /* Length field of extension data. */
-    if (totalSz < i - begin + OPAQUE16_LEN)
-        return BUFFER_ERROR;
-    ato16(&input[i], &totalExtSz);
-    i += OPAQUE16_LEN;
-
-    /* Extension data. */
-    if (i - begin + totalExtSz > totalSz)
-        return BUFFER_ERROR;
-    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
-                          encrypted_extensions, NULL)))
-        return ret;
-
-    /* Move index to byte after message. */
-    *inOutIdx = i + totalExtSz;
-
-    /* Always encrypted. */
-    *inOutIdx += ssl->keys.padSz;
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-        TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
-        if (ext == NULL || !ext->val)
-            ssl->earlyData = no_early_data;
-    }
-#endif
-
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData == no_early_data) {
-        ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY);
-        if (ret != 0)
-            return ret;
-    }
-#endif
-
-    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
-
-    WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret);
-    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
-
-    return ret;
-}
-
-/* handle processing TLS v1.3 certificate_request (13) */
-/* Handle a TLS v1.3 CertificateRequest message.
- * This message is always encrypted.
- * Only a client will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of CertificateRequest.
- *           On exit, the index of byte after the CertificateRequest message.
- * size      The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
-                                     word32* inOutIdx, word32 size)
-{
-    word16      len;
-    word32      begin = *inOutIdx;
-    int         ret = 0;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    Suites      peerSuites;
-#endif
-#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-    CertReqCtx* certReqCtx;
-#endif
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
-    WOLFSSL_ENTER("DoTls13CertificateRequest");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest");
-    if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo);
-#endif
-
-    if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
-        return BUFFER_ERROR;
-
-    /* Length of the request context. */
-    len = input[(*inOutIdx)++];
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    if (ssl->options.connectState < FINISHED_DONE && len > 0)
-        return BUFFER_ERROR;
-
-#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-    /* CertReqCtx has one byte at end for context value.
-     * Increase size to handle other implementations sending more than one byte.
-     * That is, allocate extra space, over one byte, to hold the context value.
-     */
-    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (certReqCtx == NULL)
-        return MEMORY_E;
-    certReqCtx->next = ssl->certReqCtx;
-    certReqCtx->len = len;
-    XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
-    ssl->certReqCtx = certReqCtx;
-#endif
-    *inOutIdx += len;
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Signature and hash algorithms. */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    PickHashSigAlgo(ssl, input + *inOutIdx, len);
-    *inOutIdx += len;
-
-    /* Length of certificate authority data. */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-
-    /* Certificate authorities. */
-    while (len) {
-        word16 dnSz;
-
-        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-            return BUFFER_ERROR;
-
-        ato16(input + *inOutIdx, &dnSz);
-        *inOutIdx += OPAQUE16_LEN;
-
-        if ((*inOutIdx - begin) + dnSz > size)
-            return BUFFER_ERROR;
-
-        *inOutIdx += dnSz;
-        len -= OPAQUE16_LEN + dnSz;
-    }
-
-    /* Certificate extensions */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    *inOutIdx += len;
-#else
-    /* TODO: Add support for more extensions:
-     *   signed_certificate_timestamp, certificate_authorities, oid_filters.
-     */
-    /* Certificate extensions */
-    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &len);
-    *inOutIdx += OPAQUE16_LEN;
-    if ((*inOutIdx - begin) + len > size)
-        return BUFFER_ERROR;
-    if (len == 0)
-        return INVALID_PARAMETER;
-    if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len,
-                                           certificate_request, &peerSuites))) {
-        return ret;
-    }
-    *inOutIdx += len;
-
-    PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz);
-#endif
-
-    if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
-        ssl->buffers.key && ssl->buffers.key->buffer)
-        ssl->options.sendVerify = SEND_CERT;
-    else
-        ssl->options.sendVerify = SEND_BLANK_CERT;
-
-    /* This message is always encrypted so add encryption padding. */
-    *inOutIdx += ssl->keys.padSz;
-
-    WOLFSSL_LEAVE("DoTls13CertificateRequest", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
-
-    return ret;
-}
-
-#endif /* !NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-/* Refine list of supported cipher suites to those common to server and client.
- *
- * ssl         SSL/TLS object.
- * peerSuites  The peer's advertised list of supported cipher suites.
- */
-static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites)
-{
-    byte suites[WOLFSSL_MAX_SUITE_SZ];
-    int suiteSz = 0;
-    int i, j;
-
-    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
-        for (j = 0; j < peerSuites->suiteSz; j += 2) {
-            if (ssl->suites->suites[i+0] == peerSuites->suites[j+0] &&
-                ssl->suites->suites[i+1] == peerSuites->suites[j+1]) {
-                suites[suiteSz++] = peerSuites->suites[j+0];
-                suites[suiteSz++] = peerSuites->suites[j+1];
-            }
-        }
-    }
-
-    ssl->suites->suiteSz = suiteSz;
-    XMEMCPY(ssl->suites->suites, &suites, sizeof(suites));
-}
-
-/* Handle any Pre-Shared Key (PSK) extension.
- * Must do this in ClientHello as it requires a hash of the truncated message.
- * Don't know size of binders until Pre-Shared Key extension has been parsed.
- *
- * ssl       The SSL/TLS object.
- * input     The ClientHello message.
- * helloSz   The size of the ClientHello message (including binders if present).
- * usingPSK  Indicates handshake is using Pre-Shared Keys.
- * returns 0 on success and otherwise failure.
- */
-static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
-                           int* usingPSK)
-{
-    int           ret;
-    TLSX*         ext;
-    word16        bindersLen;
-    PreSharedKey* current;
-    byte          binderKey[WC_MAX_DIGEST_SIZE];
-    byte          binder[WC_MAX_DIGEST_SIZE];
-    word32        binderLen;
-    word16        modes;
-    byte          suite[2];
-#ifdef WOLFSSL_EARLY_DATA
-    int           pskCnt = 0;
-    TLSX*         extEarlyData;
-#endif
-
-    WOLFSSL_ENTER("DoPreSharedKeys");
-
-    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
-    if (ext == NULL) {
-#ifdef WOLFSSL_EARLY_DATA
-        ssl->earlyData = no_early_data;
-#endif
-        return 0;
-    }
-
-    /* Extensions pushed on stack/list and PSK must be last. */
-    if (ssl->extensions != ext)
-        return PSK_KEY_ERROR;
-
-    /* Assume we are going to resume with a pre-shared key. */
-    ssl->options.resuming = 1;
-
-    /* Find the pre-shared key extension and calculate hash of truncated
-     * ClientHello for binders.
-     */
-    bindersLen = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
-                                                  client_hello);
-
-    /* Hash data up to binders for deriving binders in PSK extension. */
-    ret = HashInput(ssl, input,  helloSz - bindersLen);
-    if (ret != 0)
-        return ret;
-
-    /* Look through all client's pre-shared keys for a match. */
-    current = (PreSharedKey*)ext->data;
-    while (current != NULL) {
-    #ifdef WOLFSSL_EARLY_DATA
-        pskCnt++;
-    #endif
-
-    #ifndef NO_PSK
-        XMEMCPY(ssl->arrays->client_identity, current->identity,
-                current->identityLen);
-        ssl->arrays->client_identity[current->identityLen] = '\0';
-    #endif
-
-    #ifdef HAVE_SESSION_TICKET
-        /* Decode the identity. */
-        if ((ret = DoClientTicket(ssl, current->identity, current->identityLen))
-                                                     == WOLFSSL_TICKET_RET_OK) {
-            word32 now;
-            int    diff;
-
-            now = TimeNowInMilliseconds();
-            if (now == (word32)GETTIME_ERROR)
-                return now;
-            diff = now - ssl->session.ticketSeen;
-            diff -= current->ticketAge - ssl->session.ticketAdd;
-            /* Check session and ticket age timeout.
-             * Allow +/- 1000 milliseconds on ticket age.
-             */
-            if (diff > (int)ssl->timeout * 1000 || diff < -1000 ||
-                                     diff - MAX_TICKET_AGE_SECS * 1000 > 1000) {
-                /* Invalid difference, fallback to full handshake. */
-                ssl->options.resuming = 0;
-                break;
-            }
-
-            /* Check whether resumption is possible based on suites in SSL and
-             * ciphersuite in ticket.
-             */
-            suite[0] = ssl->session.cipherSuite0;
-            suite[1] = ssl->session.cipherSuite;
-            if (!FindSuite(ssl, suite)) {
-                current = current->next;
-                continue;
-            }
-
-        #ifdef WOLFSSL_EARLY_DATA
-            ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz;
-        #endif
-            /* Use the same cipher suite as before and set up for use. */
-            ssl->options.cipherSuite0   = ssl->session.cipherSuite0;
-            ssl->options.cipherSuite    = ssl->session.cipherSuite;
-            ret = SetCipherSpecs(ssl);
-            if (ret != 0)
-                return ret;
-
-            /* Resumption PSK is resumption master secret. */
-            ssl->arrays->psk_keySz = ssl->specs.hash_size;
-        #ifdef WOLFSSL_TLS13_DRAFT_18
-            XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
-                    ssl->arrays->psk_keySz);
-        #else
-            if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
-                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
-                return ret;
-            }
-        #endif
-
-            /* Derive the early secret using the PSK. */
-            ret = DeriveEarlySecret(ssl);
-            if (ret != 0)
-                return ret;
-            /* Derive the binder key to use to with HMAC. */
-            ret = DeriveBinderKeyResume(ssl, binderKey);
-            if (ret != 0)
-                return ret;
-        }
-        else
-    #endif
-    #ifndef NO_PSK
-        if (ssl->options.server_psk_cb != NULL &&
-            (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
-                             ssl->arrays->client_identity, ssl->arrays->psk_key,
-                             MAX_PSK_KEY_LEN)) != 0) {
-            if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
-                return PSK_KEY_ERROR;
-            /* TODO: Callback should be able to specify ciphersuite. */
-
-            suite[0] = TLS13_BYTE;
-            suite[1] = WOLFSSL_DEF_PSK_CIPHER;
-            if (!FindSuite(ssl, suite)) {
-                current = current->next;
-                continue;
-            }
-
-            /* Default to ciphersuite if cb doesn't specify. */
-            ssl->options.resuming = 0;
-
-            /* PSK age is always zero. */
-            if (current->ticketAge != ssl->session.ticketAdd)
-                return PSK_KEY_ERROR;
-
-            /* Check whether PSK ciphersuite is in SSL. */
-            ssl->options.cipherSuite0 = TLS13_BYTE;
-            ssl->options.cipherSuite  = WOLFSSL_DEF_PSK_CIPHER;
-            ret = SetCipherSpecs(ssl);
-            if (ret != 0)
-                return ret;
-
-            /* Derive the early secret using the PSK. */
-            ret = DeriveEarlySecret(ssl);
-            if (ret != 0)
-                return ret;
-            /* Derive the binder key to use to with HMAC. */
-            ret = DeriveBinderKey(ssl, binderKey);
-            if (ret != 0)
-                return ret;
-        }
-        else
-    #endif
-        {
-            current = current->next;
-            continue;
-        }
-
-        ssl->options.sendVerify = 0;
-
-        /* Derive the Finished message secret. */
-        ret = DeriveFinishedSecret(ssl, binderKey,
-                                             ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        /* Derive the binder and compare with the one in the extension. */
-        ret = BuildTls13HandshakeHmac(ssl,
-                         ssl->keys.client_write_MAC_secret, binder, &binderLen);
-        if (ret != 0)
-            return ret;
-        if (binderLen != current->binderLen ||
-                             XMEMCMP(binder, current->binder, binderLen) != 0) {
-            return BAD_BINDER;
-        }
-
-        /* This PSK works, no need to try any more. */
-        current->chosen = 1;
-        ext->resp = 1;
-        break;
-    }
-
-    if (current == NULL) {
-#ifdef WOLFSSL_PSK_ID_PROTECTION
-    #ifndef NO_CERTS
-        if (ssl->buffers.certChainCnt != 0)
-            return 0;
-    #endif
-        return BAD_BINDER;
-#else
-        return 0;
-#endif
-    }
-
-    /* Hash the rest of the ClientHello. */
-    ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
-    if (ret != 0)
-        return ret;
-
-#ifdef WOLFSSL_EARLY_DATA
-    extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
-    if (extEarlyData != NULL) {
-        if (ssl->earlyData != no_early_data && current == ext->data) {
-            extEarlyData->resp = 1;
-
-            /* Derive early data decryption key. */
-            ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1);
-            if (ret != 0)
-                return ret;
-            if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-                return ret;
-
-            ssl->earlyData = process_early_data;
-        }
-        else
-            extEarlyData->resp = 0;
-    }
-#endif
-
-    /* Get the PSK key exchange modes the client wants to negotiate. */
-    ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
-    if (ext == NULL)
-        return MISSING_HANDSHAKE_DATA;
-    modes = ext->val;
-
-    ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
-    /* Use (EC)DHE for forward-security if possible. */
-    if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
-                                                                  ext != NULL) {
-        /* Only use named group used in last session. */
-        ssl->namedGroup = ssl->session.namedGroup;
-
-        /* Pick key share and Generate a new key if not present. */
-        ret = TLSX_KeyShare_Establish(ssl);
-        if (ret == KEY_SHARE_ERROR) {
-            ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
-            ret = 0;
-        }
-        else if (ret < 0)
-            return ret;
-
-        /* Send new public key to client. */
-        ext->resp = 1;
-    }
-    else {
-        if ((modes & (1 << PSK_KE)) == 0)
-            return PSK_KEY_ERROR;
-        ssl->options.noPskDheKe = 1;
-    }
-
-    *usingPSK = 1;
-
-    WOLFSSL_LEAVE("DoPreSharedKeys", ret);
-
-    return ret;
-}
-#endif
-
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
-/* Check that the Cookie data's integrity.
- *
- * ssl       SSL/TLS object.
- * cookie    The cookie data - hash and MAC.
- * cookieSz  The length of the cookie data in bytes.
- * returns Length of the hash on success, otherwise failure.
- */
-static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz)
-{
-    int  ret;
-    byte mac[WC_MAX_DIGEST_SIZE];
-    Hmac cookieHmac;
-    byte cookieType;
-    byte macSz;
-
-#if !defined(NO_SHA) && defined(NO_SHA256)
-    cookieType = SHA;
-    macSz = WC_SHA_DIGEST_SIZE;
-#endif /* NO_SHA */
-#ifndef NO_SHA256
-    cookieType = WC_SHA256;
-    macSz = WC_SHA256_DIGEST_SIZE;
-#endif /* NO_SHA256 */
-
-    if (cookieSz < ssl->specs.hash_size + macSz)
-        return HRR_COOKIE_ERROR;
-    cookieSz -= macSz;
-
-    ret = wc_HmacSetKey(&cookieHmac, cookieType,
-                        ssl->buffers.tls13CookieSecret.buffer,
-                        ssl->buffers.tls13CookieSecret.length);
-    if (ret != 0)
-        return ret;
-    if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0)
-        return ret;
-    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
-        return ret;
-
-    if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0)
-        return HRR_COOKIE_ERROR;
-    return cookieSz;
-}
-
-/* Length of the KeyShare Extension */
-#define HRR_KEY_SHARE_SZ   (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-/* Length of the Supported Vresions Extension */
-#define HRR_VERSIONS_SZ    (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-/* Length of the Cookie Extension excluding cookie data */
-#define HRR_COOKIE_HDR_SZ  (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* PV | CipherSuite | Ext Len */
-#define HRR_BODY_SZ        (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
-/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */
-#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
-                        HRR_BODY_SZ         + \
-                          HRR_KEY_SHARE_SZ  + \
-                          HRR_COOKIE_HDR_SZ)
-#else
-/* PV | Random | Session Id | CipherSuite | Compression | Ext Len */
-#define HRR_BODY_SZ        (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \
-                            SUITE_LEN + COMP_LEN + OPAQUE16_LEN)
-/* HH | PV | CipherSuite | Ext Len | Key Share | Supported Version | Cookie */
-#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
-                        HRR_BODY_SZ         + \
-                          HRR_KEY_SHARE_SZ  + \
-                          HRR_VERSIONS_SZ   + \
-                          HRR_COOKIE_HDR_SZ)
-#endif
-
-/* Restart the Hanshake hash from the cookie value.
- *
- * ssl     SSL/TLS object.
- * cookie  Cookie data from client.
- * returns 0 on success, otherwise failure.
- */
-static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
-{
-    byte   header[HANDSHAKE_HEADER_SZ];
-    byte   hrr[MAX_HRR_SZ];
-    int    hrrIdx;
-    word32 idx;
-    byte   hashSz;
-    byte*  cookieData;
-    byte   cookieDataSz;
-    word16 length;
-    int    keyShareExt = 0;
-    int    ret;
-
-    cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len);
-    if (ret < 0)
-        return ret;
-    hashSz = cookie->data;
-    cookieData = &cookie->data;
-    idx = OPAQUE8_LEN;
-
-    /* Restart handshake hash with synthetic message hash. */
-    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
-    if ((ret = InitHandshakeHashes(ssl)) != 0)
-        return ret;
-    if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0)
-        return ret;
-    if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0)
-        return ret;
-
-    /* Reconstruct the HelloRetryMessage for handshake hash. */
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len;
-#else
-    length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz +
-             HRR_COOKIE_HDR_SZ + cookie->len;
-    length += HRR_VERSIONS_SZ;
-#endif
-    if (cookieDataSz > hashSz + OPAQUE16_LEN) {
-        keyShareExt = 1;
-        length += HRR_KEY_SHARE_SZ;
-    }
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl);
-
-    idx += hashSz;
-    hrrIdx = HANDSHAKE_HEADER_SZ;
-    /* TODO: [TLS13] Replace existing code with code in comment.
-     * Use the TLS v1.3 draft version for now.
-     *
-     * Change to:
-     * hrr[hrrIdx++] = ssl->version.major;
-     * hrr[hrrIdx++] = ssl->version.minor;
-     */
-    /* The negotiated protocol version. */
-    hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
-    hrr[hrrIdx++] = TLS_DRAFT_MINOR;
-    /* Cipher Suite */
-    hrr[hrrIdx++] = cookieData[idx++];
-    hrr[hrrIdx++] = cookieData[idx++];
-
-    /* Extensions' length */
-    length -= HRR_BODY_SZ;
-    c16toa(length, hrr + hrrIdx);
-    hrrIdx += 2;
-#else
-    AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl);
-
-    idx += hashSz;
-    hrrIdx = HANDSHAKE_HEADER_SZ;
-
-    /* The negotiated protocol version. */
-    hrr[hrrIdx++] = ssl->version.major;
-    hrr[hrrIdx++] = TLSv1_2_MINOR;
-
-    /* HelloRetryRequest message has fixed value for random. */
-    XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN);
-    hrrIdx += RAN_LEN;
-
-    hrr[hrrIdx++] = ssl->session.sessionIDSz;
-    if (ssl->session.sessionIDSz > 0) {
-        XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz);
-        hrrIdx += ssl->session.sessionIDSz;
-    }
-
-    /* Cipher Suite */
-    hrr[hrrIdx++] = cookieData[idx++];
-    hrr[hrrIdx++] = cookieData[idx++];
-
-    /* Compression not supported in TLS v1.3. */
-    hrr[hrrIdx++] = 0;
-
-    /* Extensions' length */
-    length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz;
-    c16toa(length, hrr + hrrIdx);
-    hrrIdx += 2;
-
-#endif
-    /* Optional KeyShare Extension */
-    if (keyShareExt) {
-        c16toa(TLSX_KEY_SHARE, hrr + hrrIdx);
-        hrrIdx += 2;
-        c16toa(OPAQUE16_LEN, hrr + hrrIdx);
-        hrrIdx += 2;
-        hrr[hrrIdx++] = cookieData[idx++];
-        hrr[hrrIdx++] = cookieData[idx++];
-    }
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx);
-    hrrIdx += 2;
-    c16toa(OPAQUE16_LEN, hrr + hrrIdx);
-    hrrIdx += 2;
-    /* TODO: [TLS13] Change to ssl->version.major and minor once final. */
-    #ifdef WOLFSSL_TLS13_FINAL
-        hrr[hrrIdx++] = ssl->version.major;
-        hrr[hrrIdx++] = ssl->version.minor;
-    #else
-        hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
-        hrr[hrrIdx++] = TLS_DRAFT_MINOR;
-    #endif
-#endif
-    /* Mandatory Cookie Extension */
-    c16toa(TLSX_COOKIE, hrr + hrrIdx);
-    hrrIdx += 2;
-    c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx);
-    hrrIdx += 2;
-    c16toa(cookie->len, hrr + hrrIdx);
-    hrrIdx += 2;
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("Reconstucted HelloRetryRequest");
-    WOLFSSL_BUFFER(hrr, hrrIdx);
-    WOLFSSL_MSG("Cookie");
-    WOLFSSL_BUFFER(cookieData, cookie->len);
-#endif
-
-    if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0)
-        return ret;
-    return HashOutputRaw(ssl, cookieData, cookie->len);
-}
-#endif
-
-/* Handle a ClientHello handshake message.
- * If the protocol version in the message is not TLS v1.3 or higher, use
- * DoClientHello()
- * Only a server will receive this message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of ClientHello.
- *           On exit, the index of byte after the ClientHello message and
- *           padding.
- * helloSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                       word32 helloSz)
-{
-    int             ret = VERSION_ERROR;
-    byte            b;
-    ProtocolVersion pv;
-    Suites          clSuites;
-    word32          i = *inOutIdx;
-    word32          begin = i;
-    word16          totalExtSz = 0;
-    int             usingPSK = 0;
-    byte            sessIdSz;
-#ifndef WOLFSSL_NO_TLS12
-    int             bogusID = 0;
-#endif
-
-    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
-    WOLFSSL_ENTER("DoTls13ClientHello");
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
-    if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
-#endif
-
-    /* protocol version, random and session id length check */
-    if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
-        return BUFFER_ERROR;
-
-    /* Protocol version */
-    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
-    ssl->chVersion = pv;   /* store */
-    i += OPAQUE16_LEN;
-    /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
-    if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
-        pv.minor = TLSv1_2_MINOR;
-
-#ifndef WOLFSSL_NO_TLS12
-    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor < TLSv1_3_MINOR)
-        return DoClientHello(ssl, input, inOutIdx, helloSz);
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-    if (ssl->options.downgrade) {
-       if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
-            return ret;
-    }
-#endif
-
-    /* Client random */
-    XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
-    i += RAN_LEN;
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("client random");
-    WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN);
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Session id - empty in TLS v1.3 */
-    sessIdSz = input[i++];
-    if (sessIdSz > 0 && !ssl->options.downgrade) {
-        WOLFSSL_MSG("Client sent session id - not supported");
-        return BUFFER_ERROR;
-    }
-#else
-    sessIdSz = input[i++];
-    if (sessIdSz != ID_LEN && sessIdSz != 0)
-        return INVALID_PARAMETER;
-#endif
-    ssl->session.sessionIDSz = sessIdSz;
-    if (sessIdSz == ID_LEN) {
-        XMEMCPY(ssl->session.sessionID, input + i, sessIdSz);
-        i += ID_LEN;
-    }
-#ifndef WOLFSSL_NO_TLS12
-    #ifdef HAVE_SESSION_TICKET
-        if (sessIdSz > 0 && sessIdSz < ID_LEN)
-            bogusID = 1;
-    #endif
-#endif
-
-    /* Cipher suites */
-    if ((i - begin) + OPAQUE16_LEN > helloSz)
-        return BUFFER_ERROR;
-    ato16(&input[i], &clSuites.suiteSz);
-    i += OPAQUE16_LEN;
-    /* suites and compression length check */
-    if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
-        return BUFFER_ERROR;
-    if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
-        return BUFFER_ERROR;
-    XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
-    i += clSuites.suiteSz;
-    clSuites.hashSigAlgoSz = 0;
-
-    /* Compression */
-    b = input[i++];
-    if ((i - begin) + b > helloSz)
-        return BUFFER_ERROR;
-    if (b != COMP_LEN) {
-        WOLFSSL_MSG("Must be one compression type in list");
-        return INVALID_PARAMETER;
-    }
-    b = input[i++];
-    if (b != NO_COMPRESSION) {
-        WOLFSSL_MSG("Must be no compression type in list");
-        return INVALID_PARAMETER;
-    }
-
-    if ((i - begin) < helloSz) {
-        if ((i - begin) + OPAQUE16_LEN > helloSz)
-            return BUFFER_ERROR;
-        ato16(&input[i], &totalExtSz);
-        i += OPAQUE16_LEN;
-        if ((i - begin) + totalExtSz > helloSz)
-            return BUFFER_ERROR;
-
-    #ifdef HAVE_QSH
-        QSH_Init(ssl);
-    #endif
-
-        /* Auto populate extensions supported unless user defined. */
-        if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
-            return ret;
-
-        /* Parse extensions */
-        if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello,
-                                                                  &clSuites))) {
-            return ret;
-        }
-
-#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
-                                                        defined(WOLFSSL_HAPROXY)
-        if ((ret = SNI_Callback(ssl)) != 0)
-            return ret;
-        ssl->options.side = WOLFSSL_SERVER_END;
-#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-    }
-
-    i += totalExtSz;
-    *inOutIdx = i;
-
-    if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) {
-        if (!ssl->options.downgrade) {
-            WOLFSSL_MSG("Client trying to connect with lesser version than "
-                        "TLS v1.3");
-            return VERSION_ERROR;
-        }
-
-        if (pv.minor < ssl->options.minDowngrade)
-            return VERSION_ERROR;
-        ssl->version.minor = pv.minor;
-    }
-
-    ssl->options.sendVerify = SEND_CERT;
-
-    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-    ssl->options.haveSessionId = 1;
-
-    if (IsAtLeastTLSv1_3(ssl->version)) {
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
-        if (ssl->options.sendCookie &&
-              ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-            TLSX* ext;
-
-            if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
-                return HRR_COOKIE_ERROR;
-            /* Ensure the cookie came from client and isn't the one in the
-             * response - HelloRetryRequest.
-             */
-            if (ext->resp == 1)
-                return HRR_COOKIE_ERROR;
-            ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
-            if (ret != 0)
-                return ret;
-        }
-#endif
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-        if (ssl->options.downgrade) {
-            if ((ret = InitHandshakeHashes(ssl)) != 0)
-                return ret;
-        }
-
-        /* Refine list for PSK processing. */
-        RefineSuites(ssl, &clSuites);
-
-        /* Process the Pre-Shared Key extension if present. */
-        ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK);
-        if (ret != 0)
-            return ret;
-#endif
-    }
-#ifndef WOLFSSL_NO_TLS12
-    else if (ssl->options.resuming) {
-        ret = HandleTlsResumption(ssl, bogusID, &clSuites);
-        if (ret != 0)
-            return ret;
-        /* Check wheter resuming has been chosen */
-        if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
-            WOLFSSL_LEAVE("DoTls13ClientHello", ret);
-            WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
-
-            return ret;
-        }
-    }
-#else
-    else {
-        WOLFSSL_MSG("Negotiated lesser version than TLS v1.3");
-        return VERSION_ERROR;
-    }
-#endif
-
-    if (!usingPSK) {
-        if ((ret = MatchSuite(ssl, &clSuites)) < 0) {
-            WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
-            return ret;
-        }
-
-        /* Check that the negotiated ciphersuite matches protocol version. */
-        if (IsAtLeastTLSv1_3(ssl->version)) {
-            if (ssl->options.cipherSuite0 != TLS13_BYTE) {
-                WOLFSSL_MSG("Negotiated ciphersuite from lesser version than "
-                            "TLS v1.3");
-                return VERSION_ERROR;
-            }
-        }
-        /* VerifyServerSuite handles when version is less than 1.3 */
-
-#ifdef HAVE_SESSION_TICKET
-        if (ssl->options.resuming) {
-            ssl->options.resuming = 0;
-            XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size);
-            /* May or may not have done any hashing. */
-            if ((ret = InitHandshakeHashes(ssl)) != 0)
-                return ret;
-        }
-#endif
-
-#ifdef HAVE_SESSION_TICKET
-        if (IsAtLeastTLSv1_3(ssl->version) || !ssl->options.downgrade)
-#endif
-        {
-            if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
-                return ret;
-        }
-
-        if (IsAtLeastTLSv1_3(ssl->version)) {
-            /* Derive early secret for handshake secret. */
-            if ((ret = DeriveEarlySecret(ssl)) != 0)
-                return ret;
-        }
-    }
-
-    WOLFSSL_LEAVE("DoTls13ClientHello", ret);
-    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
-
-    return ret;
-}
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-/* handle generation of TLS 1.3 hello_retry_request (6) */
-/* Send the HelloRetryRequest message to indicate the negotiated protocol
- * version and security parameters the server is willing to use.
- * Only a server will send this message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-int SendTls13HelloRetryRequest(WOLFSSL* ssl)
-{
-    int    ret;
-    byte*  output;
-    word32 length;
-    word16 len;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    int    sendSz;
-
-    WOLFSSL_ENTER("SendTls13HelloRetryRequest");
-
-    /* Get the length of the extensions that will be written. */
-    len = 0;
-    ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len);
-    /* There must be extensions sent to indicate what client needs to do. */
-    if (ret != 0)
-        return MISSING_HANDSHAKE_DATA;
-
-    /* Protocol version + Extensions */
-    length = OPAQUE16_LEN + len;
-    sendSz = idx + length;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-    /* Add record and hanshake headers. */
-    AddTls13Headers(output, length, hello_retry_request, ssl);
-
-    /* TODO: [TLS13] Replace existing code with code in comment.
-     * Use the TLS v1.3 draft version for now.
-     *
-     * Change to:
-     * output[idx++] = ssl->version.major;
-     * output[idx++] = ssl->version.minor;
-     */
-    /* The negotiated protocol version. */
-    output[idx++] = TLS_DRAFT_MAJOR;
-    output[idx++] = TLS_DRAFT_MINOR;
-
-    /* Add TLS extensions. */
-    ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL);
-    if (ret != 0)
-        return ret;
-    idx += len;
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn)
-        AddPacketName(ssl, "HelloRetryRequest");
-    if (ssl->toInfoOn) {
-        AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz,
-                      WRITE_PROTO, ssl->heap);
-    }
-#endif
-    if ((ret = HashOutput(ssl, output, idx, 0)) != 0)
-        return ret;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret);
-
-    return ret;
-}
-#endif /* WOLFSSL_TLS13_DRAFT_18 */
-
-/* Send TLS v1.3 ServerHello message to client.
- * Only a server will send this message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-#ifdef WOLFSSL_TLS13_DRAFT_18
-static
-#endif
-/* handle generation of TLS 1.3 server_hello (2) */
-int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
-{
-    int    ret;
-    byte*  output;
-    word16 length;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    int    sendSz;
-
-    WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
-    WOLFSSL_ENTER("SendTls13ServerHello");
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    if (extMsgType == hello_retry_request) {
-        if ((ret = RestartHandshakeHash(ssl)) < 0)
-            return ret;
-    }
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* Protocol version, server random, cipher suite and extensions. */
-    length = VERSION_SZ + RAN_LEN + SUITE_LEN;
-    ret = TLSX_GetResponseSize(ssl, server_hello, &length);
-    if (ret != 0)
-        return ret;
-#else
-    /* Protocol version, server random, session id, cipher suite, compression
-     * and extensions.
-     */
-    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz +
-             SUITE_LEN + COMP_LEN;
-    ret = TLSX_GetResponseSize(ssl, extMsgType, &length);
-    if (ret != 0)
-        return ret;
-#endif
-    sendSz = idx + length;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, length, server_hello, ssl);
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    /* TODO: [TLS13] Replace existing code with code in comment.
-     * Use the TLS v1.3 draft version for now.
-     *
-     * Change to:
-     * output[idx++] = ssl->version.major;
-     * output[idx++] = ssl->version.minor;
-     */
-    /* The negotiated protocol version. */
-    output[idx++] = TLS_DRAFT_MAJOR;
-    output[idx++] = TLS_DRAFT_MINOR;
-#else
-    /* The protocol version must be TLS v1.2 for middleboxes. */
-    output[idx++] = ssl->version.major;
-    output[idx++] = TLSv1_2_MINOR;
-#endif
-
-    if (extMsgType == server_hello) {
-        /* Generate server random. */
-        if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0)
-            return ret;
-    }
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    else {
-        /* HelloRetryRequest message has fixed value for random. */
-        XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
-    }
-#endif
-    /* Store in SSL for debugging. */
-    XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
-    idx += RAN_LEN;
-
-#ifdef WOLFSSL_DEBUG_TLS
-    WOLFSSL_MSG("Server random");
-    WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN);
-#endif
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    output[idx++] = ssl->session.sessionIDSz;
-    if (ssl->session.sessionIDSz > 0) {
-        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
-        idx += ssl->session.sessionIDSz;
-    }
-#endif
-
-    /* Chosen cipher suite */
-    output[idx++] = ssl->options.cipherSuite0;
-    output[idx++] = ssl->options.cipherSuite;
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Compression not supported in TLS v1.3. */
-    output[idx++] = 0;
-#endif
-
-    /* Extensions */
-    ret = TLSX_WriteResponse(ssl, output + idx, extMsgType, NULL);
-    if (ret != 0)
-        return ret;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0)
-        return ret;
-
-    #ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn)
-        AddPacketName(ssl, "ServerHello");
-    if (ssl->toInfoOn) {
-        AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
-                      WRITE_PROTO, ssl->heap);
-    }
-    #endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    ssl->options.serverState = SERVER_HELLO_COMPLETE;
-#else
-    if (extMsgType == server_hello)
-        ssl->options.serverState = SERVER_HELLO_COMPLETE;
-#endif
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13ServerHello", ret);
-    WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
-
-    return ret;
-}
-
-/* handle generation of TLS 1.3 encrypted_extensions (8) */
-/* Send the rest of the extensions encrypted under the handshake key.
- * This message is always encrypted in TLS v1.3.
- * Only a server will send this message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13EncryptedExtensions(WOLFSSL* ssl)
-{
-    int    ret;
-    byte*  output;
-    word16 length = 0;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    int    sendSz;
-
-    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
-    WOLFSSL_ENTER("SendTls13EncryptedExtensions");
-
-    ssl->keys.encryptionOn = 1;
-
-#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
-    if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0)
-        return ret;
-#endif
-
-    /* Derive the handshake secret now that we are at first message to be
-     * encrypted under the keys.
-     */
-    if ((ret = DeriveHandshakeSecret(ssl)) != 0)
-        return ret;
-    if ((ret = DeriveTls13Keys(ssl, handshake_key,
-                               ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0)
-        return ret;
-
-    /* Setup encrypt/decrypt keys for following messages. */
-#ifdef WOLFSSL_EARLY_DATA
-    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-        return ret;
-    if (ssl->earlyData != process_early_data) {
-        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-            return ret;
-    }
-#else
-    if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
-        return ret;
-#endif
-
-    ret = TLSX_GetResponseSize(ssl, encrypted_extensions, &length);
-    if (ret != 0)
-        return ret;
-
-    sendSz = idx + length;
-    /* Encryption always on. */
-    sendSz += MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    ret = CheckAvailableSize(ssl, sendSz);
-    if (ret != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, length, encrypted_extensions, ssl);
-
-    ret = TLSX_WriteResponse(ssl, output + idx, encrypted_extensions, NULL);
-    if (ret != 0)
-        return ret;
-    idx += length;
-
-#ifdef WOLFSSL_CALLBACKS
-    if (ssl->hsInfoOn)
-        AddPacketName(ssl, "EncryptedExtensions");
-    if (ssl->toInfoOn) {
-        AddPacketInfo(ssl, "EncryptedExtensions", handshake, output,
-                      sendSz, WRITE_PROTO, ssl->heap);
-    }
-#endif
-
-    /* This handshake message is always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
-                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
-    if (sendSz < 0)
-        return sendSz;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13EncryptedExtensions", ret);
-    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
-
-    return ret;
-}
-
-#ifndef NO_CERTS
-/* handle generation TLS v1.3 certificate_request (13) */
-/* Send the TLS v1.3 CertificateRequest message.
- * This message is always encrypted in TLS v1.3.
- * Only a server will send this message.
- *
- * ssl        SSL/TLS object.
- * reqCtx     Request context.
- * reqCtxLen  Length of context. 0 when sending as part of handshake.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
-                                       int reqCtxLen)
-{
-    byte*   output;
-    int    ret;
-    int    sendSz;
-    word32 i;
-    word16 reqSz;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    TLSX*  ext;
-#endif
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
-    WOLFSSL_ENTER("SendTls13CertificateRequest");
-
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz);
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ;
-    reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
-
-    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
-    /* Always encrypted and make room for padding. */
-    sendSz += MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, reqSz, certificate_request, ssl);
-
-    /* Certificate request context. */
-    output[i++] = reqCtxLen;
-    if (reqCtxLen != 0) {
-        XMEMCPY(output + i, reqCtx, reqCtxLen);
-        i += reqCtxLen;
-    }
-
-    /* supported hash/sig */
-    c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
-    i += LENGTH_SZ;
-
-    XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
-    i += ssl->suites->hashSigAlgoSz;
-
-    /* Certificate authorities not supported yet - empty buffer. */
-    c16toa(0, &output[i]);
-    i += REQ_HEADER_SZ;
-
-    /* Certificate extensions. */
-    c16toa(0, &output[i]);  /* auth's */
-    i += REQ_HEADER_SZ;
-#else
-    ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS);
-    if (ext == NULL)
-        return EXT_MISSING;
-    ext->resp = 0;
-
-    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-    reqSz = (word16)(OPAQUE8_LEN + reqCtxLen);
-    ret = TLSX_GetRequestSize(ssl, certificate_request, &reqSz);
-    if (ret != 0)
-        return ret;
-
-    sendSz = i + reqSz;
-    /* Always encrypted and make room for padding. */
-    sendSz += MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, reqSz, certificate_request, ssl);
-
-    /* Certificate request context. */
-    output[i++] = (byte)reqCtxLen;
-    if (reqCtxLen != 0) {
-        XMEMCPY(output + i, reqCtx, reqCtxLen);
-        i += reqCtxLen;
-    }
-
-    /* Certificate extensions. */
-    reqSz = 0;
-    ret = TLSX_WriteRequest(ssl, output + i, certificate_request, &reqSz);
-    if (ret != 0)
-        return ret;
-    i += reqSz;
-#endif
-
-    /* Always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
-                               i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
-    if (sendSz < 0)
-        return sendSz;
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn)
-            AddPacketName(ssl, "CertificateRequest");
-        if (ssl->toInfoOn) {
-            AddPacketInfo(ssl, "CertificateRequest", handshake, output,
-                          sendSz, WRITE_PROTO, ssl->heap);
-        }
-    #endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13CertificateRequest", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
-
-    return ret;
-}
-#endif /* NO_CERTS */
-#endif /* NO_WOLFSSL_SERVER */
-
-#ifndef NO_CERTS
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-/* Encode the signature algorithm into buffer.
- *
- * hashalgo  The hash algorithm.
- * hsType   The signature type.
- * output    The buffer to encode into.
- */
-static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
-{
-    switch (hsType) {
-#ifdef HAVE_ECC
-        case ecc_dsa_sa_algo:
-            output[0] = hashAlgo;
-            output[1] = ecc_dsa_sa_algo;
-            break;
-#endif
-#ifdef HAVE_ED25519
-        /* ED25519: 0x0807 */
-        case ed25519_sa_algo:
-            output[0] = ED25519_SA_MAJOR;
-            output[1] = ED25519_SA_MINOR;
-            (void)hashAlgo;
-            break;
-#endif
-#ifndef NO_RSA
-        /* PSS signatures: 0x080[4-6] */
-        case rsa_pss_sa_algo:
-            output[0] = rsa_pss_sa_algo;
-            output[1] = hashAlgo;
-            break;
-#endif
-        /* ED448: 0x0808 */
-    }
-}
-
-/* Decode the signature algorithm.
- *
- * input     The encoded signature algorithm.
- * hashalgo  The hash algorithm.
- * hsType   The signature type.
- */
-static WC_INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType)
-{
-    switch (input[0]) {
-        case NEW_SA_MAJOR:
-            /* PSS signatures: 0x080[4-6] */
-            if (input[1] <= sha512_mac) {
-                *hsType   = input[0];
-                *hashAlgo = input[1];
-            }
-    #ifdef HAVE_ED25519
-            /* ED25519: 0x0807 */
-            if (input[1] == ED25519_SA_MINOR) {
-                *hsType = ed25519_sa_algo;
-                /* Hash performed as part of sign/verify operation. */
-                *hashAlgo = sha512_mac;
-            }
-    #endif
-            /* ED448: 0x0808 */
-            break;
-        default:
-            *hashAlgo = input[0];
-            *hsType   = input[1];
-            break;
-    }
-}
-
-/* Get the hash of the messages so far.
- *
- * ssl   The SSL/TLS object.
- * hash  The buffer to write the hash to.
- * returns the length of the hash.
- */
-static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash)
-{
-    int ret = 0;
-    switch (ssl->specs.mac_algorithm) {
-    #ifndef NO_SHA256
-        case sha256_mac:
-            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
-            if (ret == 0)
-                ret = WC_SHA256_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA256 */
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
-            if (ret == 0)
-                ret = WC_SHA384_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
-            if (ret == 0)
-                ret = WC_SHA512_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_TLS13_SHA512 */
-    }
-    return ret;
-}
-
-/* The length of the certificate verification label - client and server. */
-#define CERT_VFY_LABEL_SZ    34
-/* The server certificate verification label. */
-static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] =
-    "TLS 1.3, server CertificateVerify";
-/* The client certificate verification label. */
-static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] =
-    "TLS 1.3, client CertificateVerify";
-
-/* The number of prefix bytes for signature data. */
-#define SIGNING_DATA_PREFIX_SZ     64
-/* The prefix byte in the signature data. */
-#define SIGNING_DATA_PREFIX_BYTE   0x20
-/* Maximum length of the signature data. */
-#define MAX_SIG_DATA_SZ            (SIGNING_DATA_PREFIX_SZ + \
-                                    CERT_VFY_LABEL_SZ      + \
-                                    WC_MAX_DIGEST_SIZE)
-
-/* Create the signature data for TLS v1.3 certificate verification.
- *
- * ssl        The SSL/TLS object.
- * sigData    The signature data.
- * sigDataSz  The length of the signature data.
- * check      Indicates this is a check not create.
- */
-static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz,
-                          int check)
-{
-    word16 idx;
-    int side = ssl->options.side;
-    int ret;
-
-    /* Signature Data = Prefix | Label | Handshake Hash */
-    XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ);
-    idx = SIGNING_DATA_PREFIX_SZ;
-
-    if ((side == WOLFSSL_SERVER_END && check) ||
-        (side == WOLFSSL_CLIENT_END && !check)) {
-        XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ);
-    }
-    if ((side == WOLFSSL_CLIENT_END && check) ||
-        (side == WOLFSSL_SERVER_END && !check)) {
-        XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ);
-    }
-    idx += CERT_VFY_LABEL_SZ;
-
-    ret = GetMsgHash(ssl, &sigData[idx]);
-    if (ret < 0)
-        return ret;
-
-    *sigDataSz = (word16)(idx + ret);
-    ret = 0;
-
-    return ret;
-}
-
-#ifndef NO_RSA
-/* Encode the PKCS #1.5 RSA signature.
- *
- * sig        The buffer to place the encoded signature into.
- * sigData    The data to be signed.
- * sigDataSz  The size of the data to be signed.
- * hashAlgo   The hash algorithm to use when signing.
- * returns the length of the encoded signature or negative on error.
- */
-static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz,
-                               int sigAlgo, int hashAlgo)
-{
-    Digest digest;
-    int    hashSz = 0;
-    int    ret = BAD_FUNC_ARG;
-    byte*  hash;
-
-    (void)sigAlgo;
-
-    hash = sig;
-
-    /* Digest the signature data. */
-    switch (hashAlgo) {
-#ifndef NO_WOLFSSL_SHA256
-        case sha256_mac:
-            ret = wc_InitSha256(&digest.sha256);
-            if (ret == 0) {
-                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha256Final(&digest.sha256, hash);
-                wc_Sha256Free(&digest.sha256);
-            }
-            hashSz = WC_SHA256_DIGEST_SIZE;
-            break;
-#endif
-#ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_InitSha384(&digest.sha384);
-            if (ret == 0) {
-                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha384Final(&digest.sha384, hash);
-                wc_Sha384Free(&digest.sha384);
-            }
-            hashSz = WC_SHA384_DIGEST_SIZE;
-            break;
-#endif
-#ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            ret = wc_InitSha512(&digest.sha512);
-            if (ret == 0) {
-                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha512Final(&digest.sha512, hash);
-                wc_Sha512Free(&digest.sha512);
-            }
-            hashSz = WC_SHA512_DIGEST_SIZE;
-            break;
-#endif
-    }
-
-    if (ret != 0)
-        return ret;
-
-    return hashSz;
-}
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-/* Encode the ECC signature.
- *
- * sigData    The data to be signed.
- * sigDataSz  The size of the data to be signed.
- * hashAlgo   The hash algorithm to use when signing.
- * returns the length of the encoded signature or negative on error.
- */
-static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo)
-{
-    Digest digest;
-    int    hashSz = 0;
-    int    ret = BAD_FUNC_ARG;
-
-    /* Digest the signature data. */
-    switch (hashAlgo) {
-#ifndef NO_WOLFSSL_SHA256
-        case sha256_mac:
-            ret = wc_InitSha256(&digest.sha256);
-            if (ret == 0) {
-                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha256Final(&digest.sha256, sigData);
-                wc_Sha256Free(&digest.sha256);
-            }
-            hashSz = WC_SHA256_DIGEST_SIZE;
-            break;
-#endif
-#ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_InitSha384(&digest.sha384);
-            if (ret == 0) {
-                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha384Final(&digest.sha384, sigData);
-                wc_Sha384Free(&digest.sha384);
-            }
-            hashSz = WC_SHA384_DIGEST_SIZE;
-            break;
-#endif
-#ifdef WOLFSSL_SHA512
-        case sha512_mac:
-            ret = wc_InitSha512(&digest.sha512);
-            if (ret == 0) {
-                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
-                if (ret == 0)
-                    ret = wc_Sha512Final(&digest.sha512, sigData);
-                wc_Sha512Free(&digest.sha512);
-            }
-            hashSz = WC_SHA512_DIGEST_SIZE;
-            break;
-#endif
-    }
-
-    if (ret != 0)
-        return ret;
-
-    return hashSz;
-}
-#endif /* HAVE_ECC */
-
-#ifndef NO_RSA
-/* Check that the decrypted signature matches the encoded signature
- * based on the digest of the signature data.
- *
- * ssl       The SSL/TLS object.
- * sigAlgo   The signature algorithm used to generate signature.
- * hashAlgo  The hash algorithm used to generate signature.
- * decSig    The decrypted signature.
- * decSigSz  The size of the decrypted signature.
- * returns 0 on success, otherwise failure.
- */
-static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo,
-                             byte* decSig, word32 decSigSz)
-{
-    int    ret = 0;
-    byte   sigData[MAX_SIG_DATA_SZ];
-    word16 sigDataSz;
-    word32 sigSz;
-
-    ret = CreateSigData(ssl, sigData, &sigDataSz, 1);
-    if (ret != 0)
-        return ret;
-
-    if (sigAlgo == rsa_pss_sa_algo) {
-        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
-
-        ret = ConvertHashPss(hashAlgo, &hashType, NULL);
-        if (ret < 0)
-            return ret;
-
-        /* PSS signature can be done in-place */
-        ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz,
-                                  sigAlgo, hashAlgo);
-        if (ret < 0)
-            return ret;
-        sigSz = ret;
-
-        ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz,
-                                     hashType);
-    }
-
-    return ret;
-}
-#endif /* !NO_RSA */
-#endif /* !NO_RSA || HAVE_ECC */
-
-/* Get the next certificate from the list for writing into the TLS v1.3
- * Certificate message.
- *
- * data    The certificate list.
- * length  The length of the certificate data in the list.
- * idx     The index of the next certificate.
- * returns the length of the certificate data. 0 indicates no more certificates
- * in the list.
- */
-static word32 NextCert(byte* data, word32 length, word32* idx)
-{
-    word32 len;
-
-    /* Is index at end of list. */
-    if (*idx == length)
-        return 0;
-
-    /* Length of the current ASN.1 encoded certificate. */
-    c24to32(data + *idx, &len);
-    /* Include the length field. */
-    len += 3;
-
-    /* Move index to next certificate and return the current certificate's
-     * length.
-     */
-    *idx += len;
-    return len;
-}
-
-/* Add certificate data and empty extension to output up to the fragment size.
- *
- * ssl     SSL/TLS object.
- * cert    The certificate data to write out.
- * len     The length of the certificate data.
- * extSz   Length of the extension data with the certificate.
- * idx     The start of the certificate data to write out.
- * fragSz  The maximum size of this fragment.
- * output  The buffer to write to.
- * returns the number of bytes written.
- */
-static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz,
-                         word32 idx, word32 fragSz, byte* output)
-{
-    word32 i = 0;
-    word32 copySz = min(len - idx, fragSz);
-
-    if (idx < len) {
-        XMEMCPY(output, cert + idx, copySz);
-        i = copySz;
-        if (copySz == fragSz)
-            return i;
-    }
-    copySz = len + extSz - idx - i;
-
-    if (extSz == OPAQUE16_LEN) {
-        if (copySz <= fragSz) {
-            /* Empty extension */
-            output[i++] = 0;
-            output[i++] = 0;
-        }
-    }
-    else {
-        byte* certExts = ssl->buffers.certExts->buffer + idx + i - len;
-        /* Put out as much of the extensions' data as will fit in fragment. */
-        if (copySz > fragSz - i)
-            copySz = fragSz - i;
-        XMEMCPY(output + i, certExts, copySz);
-        i += copySz;
-    }
-
-    return i;
-}
-
-/* handle generation TLS v1.3 certificate (11) */
-/* Send the certificate for this end and any CAs that help with validation.
- * This message is always encrypted in TLS v1.3.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13Certificate(WOLFSSL* ssl)
-{
-    int    ret = 0;
-    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
-    word16 extSz = 0;
-    word32 length, maxFragment;
-    word32 len = 0;
-    word32 idx = 0;
-    word32 offset = OPAQUE16_LEN;
-    byte*  p = NULL;
-    byte   certReqCtxLen = 0;
-    byte*  certReqCtx = NULL;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
-    WOLFSSL_ENTER("SendTls13Certificate");
-
-#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
-        certReqCtxLen = ssl->certReqCtx->len;
-        certReqCtx = &ssl->certReqCtx->ctx;
-    }
-#endif
-
-    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
-        certSz = 0;
-        certChainSz = 0;
-        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ;
-        length = headerSz;
-        listSz = 0;
-    }
-    else {
-        if (!ssl->buffers.certificate) {
-            WOLFSSL_MSG("Send Cert missing certificate buffer");
-            return BUFFER_ERROR;
-        }
-        /* Certificate Data */
-        certSz = ssl->buffers.certificate->length;
-        /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
-        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
-                   CERT_HEADER_SZ;
-
-        ret = TLSX_GetResponseSize(ssl, certificate, &extSz);
-        if (ret < 0)
-            return ret;
-
-        /* Create extensions' data if none already present. */
-        if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) {
-            ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap);
-            if (ret < 0)
-                return ret;
-
-            ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer,
-                                                           certificate, &extSz);
-            if (ret < 0)
-                return ret;
-        }
-
-        /* Length of message data with one certificate and extensions. */
-        length = headerSz + certSz + extSz;
-        /* Length of list data with one certificate and extensions. */
-        listSz = CERT_HEADER_SZ + certSz + extSz;
-
-        /* Send rest of chain if sending cert (chain has leading size/s). */
-        if (certSz > 0 && ssl->buffers.certChainCnt > 0) {
-            p = ssl->buffers.certChain->buffer;
-            /* Chain length including extensions. */
-            certChainSz = ssl->buffers.certChain->length +
-                          OPAQUE16_LEN * ssl->buffers.certChainCnt;
-            length += certChainSz;
-            listSz += certChainSz;
-        }
-        else
-            certChainSz = 0;
-    }
-
-    payloadSz = length;
-
-    if (ssl->fragOffset != 0)
-        length -= (ssl->fragOffset + headerSz);
-
-    maxFragment = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE);
-
-    while (length > 0 && ret == 0) {
-        byte*  output = NULL;
-        word32 fragSz = 0;
-        word32 i = RECORD_HEADER_SZ;
-        int    sendSz = RECORD_HEADER_SZ;
-
-        if (ssl->fragOffset == 0)  {
-            if (headerSz + certSz + extSz + certChainSz <=
-                                            maxFragment - HANDSHAKE_HEADER_SZ) {
-                fragSz = headerSz + certSz + extSz + certChainSz;
-            }
-            else
-                fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
-
-            sendSz += fragSz + HANDSHAKE_HEADER_SZ;
-            i += HANDSHAKE_HEADER_SZ;
-        }
-        else {
-            fragSz = min(length, maxFragment);
-            sendSz += fragSz;
-        }
-
-        sendSz += MAX_MSG_EXTRA;
-
-        /* Check buffers are big enough and grow if needed. */
-        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-            return ret;
-
-        /* Get position in output buffer to write new message to. */
-        output = ssl->buffers.outputBuffer.buffer +
-                 ssl->buffers.outputBuffer.length;
-
-        if (ssl->fragOffset == 0) {
-            AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
-
-            /* Request context. */
-            output[i++] = certReqCtxLen;
-            if (certReqCtxLen > 0) {
-                XMEMCPY(output + i, certReqCtx, certReqCtxLen);
-                i += certReqCtxLen;
-            }
-            length -= OPAQUE8_LEN + certReqCtxLen;
-            fragSz -= OPAQUE8_LEN + certReqCtxLen;
-            /* Certificate list length. */
-            c32to24(listSz, output + i);
-            i += CERT_HEADER_SZ;
-            length -= CERT_HEADER_SZ;
-            fragSz -= CERT_HEADER_SZ;
-            /* Leaf certificate data length. */
-            if (certSz > 0) {
-                c32to24(certSz, output + i);
-                i += CERT_HEADER_SZ;
-                length -= CERT_HEADER_SZ;
-                fragSz -= CERT_HEADER_SZ;
-            }
-        }
-        else
-            AddTls13RecordHeader(output, fragSz, handshake, ssl);
-
-        if (certSz > 0 && ssl->fragOffset < certSz + extSz) {
-            /* Put in the leaf certificate with extensions. */
-            word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer,
-                            certSz, extSz, ssl->fragOffset, fragSz, output + i);
-            i += copySz;
-            ssl->fragOffset += copySz;
-            length -= copySz;
-            fragSz -= copySz;
-            if (ssl->fragOffset == certSz + extSz)
-                FreeDer(&ssl->buffers.certExts);
-        }
-        if (certChainSz > 0 && fragSz > 0) {
-            /* Put in the CA certificates with empty extensions. */
-            while (fragSz > 0) {
-                word32 l;
-
-                if (offset == len + OPAQUE16_LEN) {
-                    /* Find next CA certificate to write out. */
-                    offset = 0;
-                    /* Point to the start of current cert in chain buffer. */
-                    p = ssl->buffers.certChain->buffer + idx;
-                    len = NextCert(ssl->buffers.certChain->buffer,
-                                   ssl->buffers.certChain->length, &idx);
-                    if (len == 0)
-                        break;
-                }
-
-                /* Write out certificate and empty extension. */
-                l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz,
-                                                                    output + i);
-                i += l;
-                ssl->fragOffset += l;
-                length -= l;
-                fragSz -= l;
-                offset += l;
-            }
-        }
-
-        if ((int)i - RECORD_HEADER_SZ < 0) {
-            WOLFSSL_MSG("Send Cert bad inputSz");
-            return BUFFER_E;
-        }
-
-        /* This message is always encrypted. */
-        sendSz = BuildTls13Message(ssl, output, sendSz,
-                                   output + RECORD_HEADER_SZ,
-                                   i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
-        if (sendSz < 0)
-            return sendSz;
-
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "Certificate");
-            if (ssl->toInfoOn) {
-                AddPacketInfo(ssl, "Certificate", handshake, output,
-                        sendSz, WRITE_PROTO, ssl->heap);
-            }
-        #endif
-
-        ssl->buffers.outputBuffer.length += sendSz;
-        if (!ssl->options.groupMessages)
-            ret = SendBuffered(ssl);
-    }
-
-    if (ret != WANT_WRITE) {
-        /* Clean up the fragment offset. */
-        ssl->fragOffset = 0;
-        if (ssl->options.side == WOLFSSL_SERVER_END)
-            ssl->options.serverState = SERVER_CERT_COMPLETE;
-    }
-
-#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
-        CertReqCtx* ctx = ssl->certReqCtx;
-        ssl->certReqCtx = ssl->certReqCtx->next;
-        XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#endif
-
-    WOLFSSL_LEAVE("SendTls13Certificate", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
-
-    return ret;
-}
-
-typedef struct Scv13Args {
-    byte*  output; /* not allocated */
-#ifndef NO_RSA
-    byte*  verifySig;
-#endif
-    byte*  verify; /* not allocated */
-    word32 idx;
-    word32 sigLen;
-    int    sendSz;
-    word16 length;
-
-    byte   sigAlgo;
-    byte*  sigData;
-    word16 sigDataSz;
-} Scv13Args;
-
-static void FreeScv13Args(WOLFSSL* ssl, void* pArgs)
-{
-    Scv13Args* args = (Scv13Args*)pArgs;
-
-    (void)ssl;
-
-#ifndef NO_RSA
-    if (args->verifySig) {
-        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        args->verifySig = NULL;
-    }
-#endif
-    if (args->sigData) {
-        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        args->sigData = NULL;
-    }
-}
-
-/* handle generation TLS v1.3 certificate_verify (15) */
-/* Send the TLS v1.3 CertificateVerify message.
- * A hash of all the message so far is used.
- * The signed data is:
- *     0x20 * 64 | context string | 0x00 | hash of messages
- * This message is always encrypted in TLS v1.3.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13CertificateVerify(WOLFSSL* ssl)
-{
-    int ret = 0;
-    buffer* sig = &ssl->buffers.sig;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    Scv13Args* args = (Scv13Args*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#else
-    Scv13Args  args[1];
-#endif
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
-    WOLFSSL_ENTER("SendTls13CertificateVerify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_scv;
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(Scv13Args));
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeScv13Args;
-    #endif
-    }
-
-    switch(ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
-                return 0;  /* sent blank cert, can't verify */
-            }
-
-            args->sendSz = MAX_CERT_VERIFY_SZ;
-            /* Always encrypted.  */
-            args->sendSz += MAX_MSG_EXTRA;
-
-            /* check for available size */
-            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
-                goto exit_scv;
-            }
-
-            /* get output buffer */
-            args->output = ssl->buffers.outputBuffer.buffer +
-                           ssl->buffers.outputBuffer.length;
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            /* idx is used to track verify pointer offset to output */
-            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-            args->verify =
-                          &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
-
-            if (ssl->buffers.key == NULL) {
-            #ifdef HAVE_PK_CALLBACKS
-                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
-                    args->length = GetPrivateKeySigSize(ssl);
-                else
-            #endif
-                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
-            }
-            else {
-                ret = DecodePrivateKey(ssl, &args->length);
-                if (ret != 0)
-                    goto exit_scv;
-            }
-
-            if (args->length <= 0) {
-                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
-            }
-
-            /* Add signature algorithm. */
-            if (ssl->hsType == DYNAMIC_TYPE_RSA)
-                args->sigAlgo = rsa_pss_sa_algo;
-            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
-                args->sigAlgo = ecc_dsa_sa_algo;
-        #ifdef HAVE_ED25519
-            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
-                args->sigAlgo = ed25519_sa_algo;
-        #endif
-            EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify);
-
-            /* Create the data to be signed. */
-            args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
-                                                    DYNAMIC_TYPE_SIGNATURE);
-            if (args->sigData == NULL) {
-                ERROR_OUT(MEMORY_E, exit_scv);
-            }
-
-            ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0);
-            if (ret != 0)
-                goto exit_scv;
-
-        #ifndef NO_RSA
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-                /* build encoded signature buffer */
-                sig->length = MAX_ENCODED_SIG_SZ;
-                sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap,
-                                                    DYNAMIC_TYPE_SIGNATURE);
-                if (sig->buffer == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_scv);
-                }
-
-                ret = CreateRSAEncodedSig(sig->buffer, args->sigData,
-                    args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo);
-                if (ret < 0)
-                    goto exit_scv;
-                sig->length = ret;
-                ret = 0;
-
-                /* Maximum size of RSA Signature. */
-                args->sigLen = args->length;
-            }
-        #endif /* !NO_RSA */
-        #ifdef HAVE_ECC
-            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                sig->length = args->sendSz - args->idx - HASH_SIG_SIZE -
-                              VERIFY_HEADER;
-                ret = CreateECCEncodedSig(args->sigData,
-                    args->sigDataSz, ssl->suites->hashAlgo);
-                if (ret < 0)
-                    goto exit_scv;
-                args->sigDataSz = (word16)ret;
-                ret = 0;
-            }
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
-                ret = Ed25519CheckPubKey(ssl);
-                if (ret < 0) {
-                    ERROR_OUT(ret, exit_scv);
-                }
-                sig->length = ED25519_SIG_SIZE;
-            }
-        #endif /* HAVE_ECC */
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-        #ifdef HAVE_ECC
-           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                ret = EccSign(ssl, args->sigData, args->sigDataSz,
-                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
-                    &sig->length, (ecc_key*)ssl->hsKey,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
-            #endif
-                );
-                args->length = (word16)sig->length;
-            }
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
-                ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz,
-                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
-                    &sig->length, (ed25519_key*)ssl->hsKey,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
-            #endif
-                );
-                args->length = sig->length;
-            }
-        #endif
-        #ifndef NO_RSA
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-
-                ret = RsaSign(ssl, sig->buffer, sig->length,
-                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen,
-                    args->sigAlgo, ssl->suites->hashAlgo,
-                    (RsaKey*)ssl->hsKey,
-                    ssl->buffers.key
-                );
-                args->length = (word16)args->sigLen;
-            }
-        #endif /* !NO_RSA */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-            /* Add signature length. */
-            c16toa(args->length, args->verify + HASH_SIG_SIZE);
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-        #ifndef NO_RSA
-            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
-                if (args->verifySig == NULL) {
-                    args->verifySig = (byte*)XMALLOC(args->sigLen, ssl->heap,
-                                                   DYNAMIC_TYPE_SIGNATURE);
-                    if (args->verifySig == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_scv);
-                    }
-                    XMEMCPY(args->verifySig,
-                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
-                        args->sigLen);
-                }
-
-                /* check for signature faults */
-                ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen,
-                    sig->buffer, sig->length, args->sigAlgo,
-                    ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey,
-                    ssl->buffers.key
-                );
-            }
-        #endif /* !NO_RSA */
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_scv;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-            /* Put the record and handshake headers on. */
-            AddTls13Headers(args->output, args->length + HASH_SIG_SIZE +
-                            VERIFY_HEADER, certificate_verify, ssl);
-
-            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
-                                   args->length + HASH_SIG_SIZE + VERIFY_HEADER;
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_END:
-        {
-            /* This message is always encrypted. */
-            ret = BuildTls13Message(ssl, args->output,
-                                    MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
-                                    args->output + RECORD_HEADER_SZ,
-                                    args->sendSz - RECORD_HEADER_SZ, handshake,
-                                    1, 0, 0);
-
-            if (ret < 0) {
-                goto exit_scv;
-            }
-            else {
-                args->sendSz = ret;
-                ret = 0;
-            }
-
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn)
-                AddPacketName(ssl, "CertificateVerify");
-            if (ssl->toInfoOn) {
-                AddPacketInfo(ssl, "CertificateVerify", handshake,
-                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
-            }
-        #endif
-
-            ssl->buffers.outputBuffer.length += args->sendSz;
-
-            if (!ssl->options.groupMessages)
-                ret = SendBuffered(ssl);
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-    } /* switch(ssl->options.asyncState) */
-
-exit_scv:
-
-    WOLFSSL_LEAVE("SendTls13CertificateVerify", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Handle async operation */
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* Final cleanup */
-    FreeScv13Args(ssl, args);
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-
-/* handle processing TLS v1.3 certificate (11) */
-/* Parse and handle a TLS v1.3 Certificate message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of Certificate.
- *           On exit, the index of byte after the Certificate message.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                              word32 totalSz)
-{
-    int ret;
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
-    WOLFSSL_ENTER("DoTls13Certificate");
-
-    ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz);
-    if (ret == 0) {
-#if !defined(NO_WOLFSSL_CLIENT)
-        if (ssl->options.side == WOLFSSL_CLIENT_END)
-            ssl->options.serverState = SERVER_CERT_COMPLETE;
-#endif
-#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-        if (ssl->options.side == WOLFSSL_SERVER_END &&
-                                ssl->options.handShakeState == HANDSHAKE_DONE) {
-            /* reset handshake states */
-            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-            ssl->options.acceptState  = TICKET_SENT;
-            ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
-        }
-#endif
-    }
-
-    WOLFSSL_LEAVE("DoTls13Certificate", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
-
-    return ret;
-}
-
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-
-typedef struct Dcv13Args {
-    byte*  output; /* not allocated */
-    word32 sendSz;
-    word16 sz;
-    word32 sigSz;
-    word32 idx;
-    word32 begin;
-    byte   hashAlgo;
-    byte   sigAlgo;
-
-    byte*  sigData;
-    word16 sigDataSz;
-} Dcv13Args;
-
-static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs)
-{
-    Dcv13Args* args = (Dcv13Args*)pArgs;
-
-    if (args->sigData != NULL) {
-        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
-        args->sigData = NULL;
-    }
-
-    (void)ssl;
-}
-
-/* handle processing TLS v1.3 certificate_verify (15) */
-/* Parse and handle a TLS v1.3 CertificateVerify message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of
- *           CertificateVerify.
- *           On exit, the index of byte after the CertificateVerify message.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
-                                    word32* inOutIdx, word32 totalSz)
-{
-    int         ret = 0;
-    buffer*     sig = &ssl->buffers.sig;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    Dcv13Args* args = (Dcv13Args*)ssl->async.args;
-    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
-    (void)sizeof(args_test);
-#else
-    Dcv13Args  args[1];
-#endif
-
-    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
-    WOLFSSL_ENTER("DoTls13CertificateVerify");
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
-    if (ret != WC_NOT_PENDING_E) {
-        /* Check for error */
-        if (ret < 0)
-            goto exit_dcv;
-    }
-    else
-#endif
-    {
-        /* Reset state */
-        ret = 0;
-        ssl->options.asyncState = TLS_ASYNC_BEGIN;
-        XMEMSET(args, 0, sizeof(Dcv13Args));
-        args->hashAlgo = sha_mac;
-        args->sigAlgo = anonymous_sa_algo;
-        args->idx = *inOutIdx;
-        args->begin = *inOutIdx;
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ssl->async.freeArgs = FreeDcv13Args;
-    #endif
-    }
-
-    switch(ssl->options.asyncState)
-    {
-        case TLS_ASYNC_BEGIN:
-        {
-        #ifdef WOLFSSL_CALLBACKS
-            if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateVerify");
-            if (ssl->toInfoOn) AddLateName("CertificateVerify",
-                                           &ssl->timeoutInfo);
-        #endif
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_BUILD;
-        } /* case TLS_ASYNC_BEGIN */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_BUILD:
-        {
-            /* Signature algorithm. */
-            if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) {
-                ERROR_OUT(BUFFER_ERROR, exit_dcv);
-            }
-            DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo);
-            args->idx += OPAQUE16_LEN;
-
-            /* Signature length. */
-            if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) {
-                ERROR_OUT(BUFFER_ERROR, exit_dcv);
-            }
-            ato16(input + args->idx, &args->sz);
-            args->idx += OPAQUE16_LEN;
-
-            /* Signature data. */
-            if ((args->idx - args->begin) + args->sz > totalSz ||
-                                                       args->sz > ENCRYPT_LEN) {
-                ERROR_OUT(BUFFER_ERROR, exit_dcv);
-            }
-
-            /* Check for public key of required type. */
-        #ifdef HAVE_ED25519
-            if (args->sigAlgo == ed25519_sa_algo &&
-                                                  !ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify");
-            }
-        #endif
-        #ifdef HAVE_ECC
-            if (args->sigAlgo == ecc_dsa_sa_algo &&
-                                                   !ssl->peerEccDsaKeyPresent) {
-                WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
-            }
-        #endif
-        #ifndef NO_RSA
-            if ((args->sigAlgo == rsa_sa_algo ||
-                 args->sigAlgo == rsa_pss_sa_algo) &&
-                         (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
-                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
-            }
-        #endif
-
-            sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap,
-                                         DYNAMIC_TYPE_SIGNATURE);
-            if (sig->buffer == NULL) {
-                ERROR_OUT(MEMORY_E, exit_dcv);
-            }
-            sig->length = args->sz;
-            XMEMCPY(sig->buffer, input + args->idx, args->sz);
-
-        #ifdef HAVE_ECC
-            if (ssl->peerEccDsaKeyPresent) {
-                WOLFSSL_MSG("Doing ECC peer cert verify");
-
-                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
-                                                    DYNAMIC_TYPE_SIGNATURE);
-                if (args->sigData == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_dcv);
-                }
-
-                ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
-                if (ret != 0)
-                    goto exit_dcv;
-                ret = CreateECCEncodedSig(args->sigData,
-                    args->sigDataSz, args->hashAlgo);
-                if (ret < 0)
-                    goto exit_dcv;
-                args->sigDataSz = (word16)ret;
-                ret = 0;
-            }
-        #endif
-        #ifdef HAVE_ED25519
-            if (ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Doing ED25519 peer cert verify");
-
-                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
-                                                    DYNAMIC_TYPE_SIGNATURE);
-                if (args->sigData == NULL) {
-                    ERROR_OUT(MEMORY_E, exit_dcv);
-                }
-
-                CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
-                ret = 0;
-            }
-        #endif
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_DO;
-        } /* case TLS_ASYNC_BUILD */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_DO:
-        {
-        #ifndef NO_RSA
-            if (args->sigAlgo == rsa_sa_algo ||
-                                             args->sigAlgo == rsa_pss_sa_algo) {
-                WOLFSSL_MSG("Doing RSA peer cert verify");
-
-                ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output,
-                    args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
-                #ifdef HAVE_PK_CALLBACKS
-                    &ssl->buffers.peerRsaKey
-                #else
-                    NULL
-                #endif
-                );
-                if (ret >= 0) {
-                    args->sendSz = ret;
-                    ret = 0;
-                }
-            }
-        #endif /* !NO_RSA */
-        #ifdef HAVE_ECC
-            if (ssl->peerEccDsaKeyPresent) {
-                WOLFSSL_MSG("Doing ECC peer cert verify");
-
-                ret = EccVerify(ssl, input + args->idx, args->sz,
-                    args->sigData, args->sigDataSz,
-                    ssl->peerEccDsaKey,
-                #ifdef HAVE_PK_CALLBACKS
-                    &ssl->buffers.peerEccDsaKey
-                #else
-                    NULL
-                #endif
-                );
-            }
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            if (ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Doing ED25519 peer cert verify");
-
-                ret = Ed25519Verify(ssl, input + args->idx, args->sz,
-                    args->sigData, args->sigDataSz,
-                    ssl->peerEd25519Key,
-                #ifdef HAVE_PK_CALLBACKS
-                    &ssl->buffers.peerEd25519Key
-                #else
-                    NULL
-                #endif
-                );
-            }
-        #endif
-
-            /* Check for error */
-            if (ret != 0) {
-                goto exit_dcv;
-            }
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_VERIFY;
-        } /* case TLS_ASYNC_DO */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_VERIFY:
-        {
-        #ifndef NO_RSA
-            if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
-                ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo,
-                                        args->output, args->sendSz);
-                if (ret != 0)
-                    goto exit_dcv;
-            }
-        #endif /* !NO_RSA */
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
-        } /* case TLS_ASYNC_VERIFY */
-        FALL_THROUGH;
-
-        case TLS_ASYNC_FINALIZE:
-        {
-            ssl->options.havePeerVerify = 1;
-
-            /* Set final index */
-            args->idx += args->sz;
-            *inOutIdx = args->idx;
-
-            /* Encryption is always on: add padding */
-            *inOutIdx += ssl->keys.padSz;
-
-            /* Advance state and proceed */
-            ssl->options.asyncState = TLS_ASYNC_END;
-        } /* case TLS_ASYNC_FINALIZE */
-
-        case TLS_ASYNC_END:
-        {
-            break;
-        }
-        default:
-            ret = INPUT_CASE_ERROR;
-    } /* switch(ssl->options.asyncState) */
-
-exit_dcv:
-
-    WOLFSSL_LEAVE("DoTls13CertificateVerify", ret);
-    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Handle async operation */
-    if (ret == WC_PENDING_E) {
-        /* Mark message as not recevied so it can process again */
-        ssl->msgsReceived.got_certificate_verify = 0;
-
-        return ret;
-    }
-    else
-#endif /* WOLFSSL_ASYNC_CRYPT */
-    if (ret != 0)
-        SendAlert(ssl, alert_fatal, decrypt_error);
-
-    /* Final cleanup */
-    FreeDcv13Args(ssl, args);
-    FreeKeyExchange(ssl);
-
-    return ret;
-}
-#endif /* !NO_RSA || HAVE_ECC */
-
-/* Parse and handle a TLS v1.3 Finished message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of Finished.
- *           On exit, the index of byte after the Finished message and padding.
- * size      Length of message data.
- * totalSz   Length of remaining data in the message buffer.
- * sniff     Indicates whether we are sniffing packets.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                           word32 size, word32 totalSz, int sniff)
-{
-    int    ret;
-    word32 finishedSz = 0;
-    byte*  secret;
-    byte   mac[WC_MAX_DIGEST_SIZE];
-
-    WOLFSSL_START(WC_FUNC_FINISHED_DO);
-    WOLFSSL_ENTER("DoTls13Finished");
-
-    /* check against totalSz */
-    if (*inOutIdx + size + ssl->keys.padSz > totalSz)
-        return BUFFER_E;
-
-    if (ssl->options.handShakeDone) {
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
-                                   ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        secret = ssl->keys.client_write_MAC_secret;
-    }
-    else if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        /* All the handshake messages have been received to calculate
-         * client and server finished keys.
-         */
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
-                                   ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret,
-                                   ssl->keys.server_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        secret = ssl->keys.server_write_MAC_secret;
-    }
-    else
-        secret = ssl->keys.client_write_MAC_secret;
-
-    ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
-    if (ret != 0)
-        return ret;
-    if (size != finishedSz)
-        return BUFFER_ERROR;
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
-        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
-    #endif
-
-    if (sniff == NO_SNIFF) {
-        /* Actually check verify data. */
-        if (XMEMCMP(input + *inOutIdx, mac, size) != 0){
-            WOLFSSL_MSG("Verify finished error on hashes");
-            SendAlert(ssl, alert_fatal, decrypt_error);
-            return VERIFY_FINISHED_ERROR;
-        }
-    }
-
-    /* Force input exhaustion at ProcessReply by consuming padSz. */
-    *inOutIdx += size + ssl->keys.padSz;
-
-    if (ssl->options.side == WOLFSSL_SERVER_END &&
-                                                  !ssl->options.handShakeDone) {
-#ifdef WOLFSSL_EARLY_DATA
-        if (ssl->earlyData != no_early_data) {
-            if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0)
-                return ret;
-        }
-#endif
-        /* Setup keys for application data messages from client. */
-        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-            return ret;
-    }
-
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-#endif
-#ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-        ssl->options.handShakeState = HANDSHAKE_DONE;
-        ssl->options.handShakeDone  = 1;
-    }
-#endif
-
-    WOLFSSL_LEAVE("DoTls13Finished", 0);
-    WOLFSSL_END(WC_FUNC_FINISHED_DO);
-
-    return 0;
-}
-#endif /* NO_CERTS */
-
-/* Send the TLS v1.3 Finished message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13Finished(WOLFSSL* ssl)
-{
-    int   sendSz;
-    int   finishedSz = ssl->specs.hash_size;
-    byte* input;
-    byte* output;
-    int   ret;
-    int   headerSz = HANDSHAKE_HEADER_SZ;
-    int   outputSz;
-    byte* secret;
-
-    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
-    WOLFSSL_ENTER("SendTls13Finished");
-
-    outputSz = WC_MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA;
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
-        return ret;
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-    input = output + RECORD_HEADER_SZ;
-
-    AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
-
-    /* make finished hashes */
-    if (ssl->options.handShakeDone) {
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
-                                   ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        secret = ssl->keys.client_write_MAC_secret;
-    }
-    else if (ssl->options.side == WOLFSSL_CLIENT_END)
-        secret = ssl->keys.client_write_MAC_secret;
-    else {
-        /* All the handshake messages have been done to calculate client and
-         * server finished keys.
-         */
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
-                                   ssl->keys.client_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret,
-                                   ssl->keys.server_write_MAC_secret);
-        if (ret != 0)
-            return ret;
-
-        secret = ssl->keys.server_write_MAC_secret;
-    }
-    ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL);
-    if (ret != 0)
-        return ret;
-
-    /* This message is always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, outputSz, input,
-                               headerSz + finishedSz, handshake, 1, 0, 0);
-    if (sendSz < 0)
-        return BUILD_MSG_ERROR;
-
-    if (!ssl->options.resuming) {
-#ifndef NO_SESSION_CACHE
-        AddSession(ssl);    /* just try */
-#endif
-    }
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
-        if (ssl->toInfoOn) {
-            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
-                          WRITE_PROTO, ssl->heap);
-        }
-    #endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-        /* Can send application data now. */
-        if ((ret = DeriveMasterSecret(ssl)) != 0)
-            return ret;
-#ifdef WOLFSSL_EARLY_DATA
-        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_SIDE_ONLY, 1))
-                                                                         != 0) {
-            return ret;
-        }
-        if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY,
-                                       ssl->earlyData == no_early_data)) != 0) {
-            return ret;
-        }
-#else
-        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE,
-                                                                     1)) != 0) {
-            return ret;
-        }
-#endif
-        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-            return ret;
-    }
-
-    if (ssl->options.side == WOLFSSL_CLIENT_END &&
-                                                  !ssl->options.handShakeDone) {
-#ifdef WOLFSSL_EARLY_DATA
-        if (ssl->earlyData != no_early_data) {
-            if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE,
-                                                                     1)) != 0) {
-                    return ret;
-            }
-        }
-#endif
-        /* Setup keys for application data messages. */
-        if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
-            return ret;
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-        ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
-        if (ret != 0)
-            return ret;
-#endif
-    }
-
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_CLIENT_END) {
-        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
-        ssl->options.handShakeState = HANDSHAKE_DONE;
-        ssl->options.handShakeDone  = 1;
-    }
-#endif
-#ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_SERVER_END) {
-        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
-    }
-#endif
-
-    if ((ret = SendBuffered(ssl)) != 0)
-        return ret;
-
-    WOLFSSL_LEAVE("SendTls13Finished", ret);
-    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
-
-    return ret;
-}
-
-/* handle generation TLS v1.3 key_update (24) */
-/* Send the TLS v1.3 KeyUpdate message.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-static int SendTls13KeyUpdate(WOLFSSL* ssl)
-{
-    int    sendSz;
-    byte*  input;
-    byte*  output;
-    int    ret;
-    int    headerSz = HANDSHAKE_HEADER_SZ;
-    int    outputSz;
-    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
-    WOLFSSL_START(WC_FUNC_KEY_UPDATE_SEND);
-    WOLFSSL_ENTER("SendTls13KeyUpdate");
-
-    outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA;
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
-        return ret;
-
-    /* get output buffer */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-    input = output + RECORD_HEADER_SZ;
-
-    AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl);
-
-    /* If:
-     *   1. I haven't sent a KeyUpdate requesting a response and
-     *   2. This isn't responding to peer KeyUpdate requiring a response then,
-     * I want a response.
-     */
-    ssl->keys.updateResponseReq = output[i++] =
-         !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond;
-    /* Sent response, no longer need to respond. */
-    ssl->keys.keyUpdateRespond = 0;
-
-    /* This message is always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, outputSz, input,
-                               headerSz + OPAQUE8_LEN, handshake, 0, 0, 0);
-    if (sendSz < 0)
-        return BUILD_MSG_ERROR;
-
-    #ifdef WOLFSSL_CALLBACKS
-        if (ssl->hsInfoOn) AddPacketName(ssl, "KeyUpdate");
-        if (ssl->toInfoOn) {
-            AddPacketInfo(ssl, "KeyUpdate", handshake, output, sendSz,
-                          WRITE_PROTO, ssl->heap);
-        }
-    #endif
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    ret = SendBuffered(ssl);
-    if (ret != 0 && ret != WANT_WRITE)
-        return ret;
-
-    /* Future traffic uses new encryption keys. */
-    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1))
-                                                                           != 0)
-        return ret;
-    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-        return ret;
-
-    WOLFSSL_LEAVE("SendTls13KeyUpdate", ret);
-    WOLFSSL_END(WC_FUNC_KEY_UPDATE_SEND);
-
-    return ret;
-}
-
-/* handle processing TLS v1.3 key_update (24) */
-/* Parse and handle a TLS v1.3 KeyUpdate message.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of Finished.
- *           On exit, the index of byte after the Finished message and padding.
- * totalSz   The length of the current handshake message.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                            word32 totalSz)
-{
-    int    ret;
-    word32 i = *inOutIdx;
-
-    WOLFSSL_START(WC_FUNC_KEY_UPDATE_DO);
-    WOLFSSL_ENTER("DoTls13KeyUpdate");
-
-    /* check against totalSz */
-    if (OPAQUE8_LEN != totalSz)
-        return BUFFER_E;
-
-    switch (input[i]) {
-        case update_not_requested:
-            /* This message in response to any oustanding request. */
-            ssl->keys.keyUpdateRespond = 0;
-            ssl->keys.updateResponseReq = 0;
-            break;
-        case update_requested:
-            /* New key update requiring a response. */
-            ssl->keys.keyUpdateRespond = 1;
-            break;
-        default:
-            return INVALID_PARAMETER;
-            break;
-    }
-
-    /* Move index to byte after message. */
-    *inOutIdx += totalSz;
-    /* Always encrypted. */
-    *inOutIdx += ssl->keys.padSz;
-
-    /* Future traffic uses new decryption keys. */
-    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1))
-                                                                         != 0) {
-        return ret;
-    }
-    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-        return ret;
-
-    if (ssl->keys.keyUpdateRespond)
-        return SendTls13KeyUpdate(ssl);
-
-    WOLFSSL_LEAVE("DoTls13KeyUpdate", ret);
-    WOLFSSL_END(WC_FUNC_KEY_UPDATE_DO);
-
-    return 0;
-}
-
-#ifdef WOLFSSL_EARLY_DATA
-#ifndef NO_WOLFSSL_CLIENT
-/* Send the TLS v1.3 EndOfEarlyData message to indicate that there will be no
- * more early application data.
- * The encryption key now changes to the pre-calculated handshake key.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success and otherwise failure.
- */
-static int SendTls13EndOfEarlyData(WOLFSSL* ssl)
-{
-    byte*  output;
-    int    ret;
-    int    sendSz;
-    word32 length;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
-    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_SEND);
-    WOLFSSL_ENTER("SendTls13EndOfEarlyData");
-
-    length = 0;
-    sendSz = idx + length + MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, length, end_of_early_data, ssl);
-
-    /* This message is always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
-                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
-    if (sendSz < 0)
-        return sendSz;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
-        return ret;
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret);
-    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_SEND);
-
-    return ret;
-}
-#endif /* !NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-/* handle processing of TLS 1.3 end_of_early_data (5) */
-/* Parse the TLS v1.3 EndOfEarlyData message that indicates that there will be
- * no more early application data.
- * The decryption key now changes to the pre-calculated handshake key.
- *
- * ssl  The SSL/TLS object.
- * returns 0 on success and otherwise failure.
- */
-static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input,
-                                 word32* inOutIdx, word32 size)
-{
-    int    ret;
-    word32 begin = *inOutIdx;
-
-    (void)input;
-
-    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_DO);
-    WOLFSSL_ENTER("DoTls13EndOfEarlyData");
-
-    if ((*inOutIdx - begin) != size)
-        return BUFFER_ERROR;
-
-    if (ssl->earlyData == no_early_data) {
-        WOLFSSL_MSG("EndOfEarlyData recieved unexpectedly");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    ssl->earlyData = done_early_data;
-
-    /* Always encrypted. */
-    *inOutIdx += ssl->keys.padSz;
-
-    ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY);
-
-    WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret);
-    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO);
-
-    return ret;
-}
-#endif /* !NO_WOLFSSL_SERVER */
-#endif /* WOLFSSL_EARLY_DATA */
-
-#ifndef NO_WOLFSSL_CLIENT
-/* Handle a New Session Ticket handshake message.
- * Message contains the information required to perform resumption.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the message buffer of Finished.
- *           On exit, the index of byte after the Finished message and padding.
- * size      The length of the current handshake message.
- * retuns 0 on success, otherwise failure.
- */
-static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
-                                   word32* inOutIdx, word32 size)
-{
-#ifdef HAVE_SESSION_TICKET
-    int    ret;
-    word32 begin = *inOutIdx;
-    word32 lifetime;
-    word32 ageAdd;
-    word16 length;
-    word32 now;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    const byte*  nonce;
-    byte         nonceLength;
-#endif
-
-    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO);
-    WOLFSSL_ENTER("DoTls13NewSessionTicket");
-
-    /* Lifetime hint. */
-    if ((*inOutIdx - begin) + SESSION_HINT_SZ > size)
-        return BUFFER_ERROR;
-    ato32(input + *inOutIdx, &lifetime);
-    *inOutIdx += SESSION_HINT_SZ;
-    if (lifetime > MAX_LIFETIME)
-        return SERVER_HINT_ERROR;
-
-    /* Age add. */
-    if ((*inOutIdx - begin) + SESSION_ADD_SZ > size)
-        return BUFFER_ERROR;
-    ato32(input + *inOutIdx, &ageAdd);
-    *inOutIdx += SESSION_ADD_SZ;
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Ticket nonce. */
-    if ((*inOutIdx - begin) + 1 > size)
-        return BUFFER_ERROR;
-    nonceLength = input[*inOutIdx];
-    if (nonceLength > MAX_TICKET_NONCE_SZ) {
-        WOLFSSL_MSG("Nonce length not supported");
-        return INVALID_PARAMETER;
-    }
-    *inOutIdx += 1;
-    if ((*inOutIdx - begin) + nonceLength > size)
-        return BUFFER_ERROR;
-    nonce = input + *inOutIdx;
-    *inOutIdx += nonceLength;
-#endif
-
-    /* Ticket length. */
-    if ((*inOutIdx - begin) + LENGTH_SZ > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &length);
-    *inOutIdx += LENGTH_SZ;
-    if ((*inOutIdx - begin) + length > size)
-        return BUFFER_ERROR;
-
-    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
-        return ret;
-    *inOutIdx += length;
-
-    now = TimeNowInMilliseconds();
-    if (now == (word32)GETTIME_ERROR)
-        return now;
-    /* Copy in ticket data (server identity). */
-    ssl->timeout                = lifetime;
-    ssl->session.timeout        = lifetime;
-    ssl->session.cipherSuite0   = ssl->options.cipherSuite0;
-    ssl->session.cipherSuite    = ssl->options.cipherSuite;
-    ssl->session.ticketSeen     = now;
-    ssl->session.ticketAdd      = ageAdd;
-    #ifdef WOLFSSL_EARLY_DATA
-    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
-    #endif
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    ssl->session.ticketNonce.len = nonceLength;
-    if (nonceLength > 0)
-        XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength);
-#endif
-    ssl->session.namedGroup     = ssl->namedGroup;
-
-    if ((*inOutIdx - begin) + EXTS_SZ > size)
-        return BUFFER_ERROR;
-    ato16(input + *inOutIdx, &length);
-    *inOutIdx += EXTS_SZ;
-    if ((*inOutIdx - begin) + length != size)
-        return BUFFER_ERROR;
-    #ifdef WOLFSSL_EARLY_DATA
-    ret = TLSX_Parse(ssl, (byte *)input + (*inOutIdx), length, session_ticket,
-                     NULL);
-    if (ret != 0)
-        return ret;
-    #endif
-    *inOutIdx += length;
-
-    #ifndef NO_SESSION_CACHE
-    AddSession(ssl);
-    #endif
-
-    /* Always encrypted. */
-    *inOutIdx += ssl->keys.padSz;
-
-    ssl->expect_session_ticket = 0;
-#else
-    (void)ssl;
-    (void)input;
-
-    WOLFSSL_ENTER("DoTls13NewSessionTicket");
-
-    *inOutIdx += size + ssl->keys.padSz;
-#endif /* HAVE_SESSION_TICKET */
-
-    WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0);
-    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_DO);
-
-    return 0;
-}
-#endif /* NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-    #ifdef HAVE_SESSION_TICKET
-
-#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
-/* Offset of the MAC size in the finished message. */
-#define FINISHED_MSG_SIZE_OFFSET    3
-
-/* Calculate the resumption secret which includes the unseen client finished
- * message.
- *
- * ssl  The SSL/TLS object.
- * retuns 0 on success, otherwise failure.
- */
-static int ExpectedResumptionSecret(WOLFSSL* ssl)
-{
-    int         ret;
-    word32      finishedSz = 0;
-    byte        mac[WC_MAX_DIGEST_SIZE];
-    Digest      digest;
-    static byte header[] = { 0x14, 0x00, 0x00, 0x00 };
-
-    /* Copy the running hash so we cna restore it after. */
-    switch (ssl->specs.mac_algorithm) {
-    #ifndef NO_SHA256
-        case sha256_mac:
-            ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    }
-
-    /* Generate the Client's Finished message and hash it. */
-    ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac,
-                                  &finishedSz);
-    if (ret != 0)
-        return ret;
-    header[FINISHED_MSG_SIZE_OFFSET] = finishedSz;
-#ifdef WOLFSSL_EARLY_DATA
-    if (ssl->earlyData != no_early_data) {
-        static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 };
-        ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
-        if (ret != 0)
-            return ret;
-    }
-#endif
-    if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0)
-        return ret;
-    if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0)
-        return ret;
-
-    if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0)
-        return ret;
-
-    /* Restore the hash inline with currently seen messages. */
-    switch (ssl->specs.mac_algorithm) {
-    #ifndef NO_SHA256
-        case sha256_mac:
-            ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case sha384_mac:
-            ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    #ifdef WOLFSSL_TLS13_SHA512
-        case sha512_mac:
-            ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384);
-            if (ret != 0)
-                return ret;
-            break;
-    #endif
-    }
-
-    return ret;
-}
-#endif
-
-/* Send New Session Ticket handshake message.
- * Message contains the information required to perform resumption.
- *
- * ssl  The SSL/TLS object.
- * retuns 0 on success, otherwise failure.
- */
-static int SendTls13NewSessionTicket(WOLFSSL* ssl)
-{
-    byte*  output;
-    int    ret;
-    int    sendSz;
-    word16 extSz;
-    word32 length;
-    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-
-    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_SEND);
-    WOLFSSL_ENTER("SendTls13NewSessionTicket");
-
-#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
-    if (!ssl->msgsReceived.got_finished) {
-        if ((ret = ExpectedResumptionSecret(ssl)) != 0)
-            return ret;
-    }
-#endif
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Start ticket nonce at 0 and go up to 255. */
-    if (ssl->session.ticketNonce.len == 0) {
-        ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ;
-        ssl->session.ticketNonce.data[0] = 0;
-    }
-    else
-        ssl->session.ticketNonce.data[0]++;
-#endif
-
-    if (!ssl->options.noTicketTls13) {
-        if ((ret = CreateTicket(ssl)) != 0)
-            return ret;
-    }
-
-#ifdef WOLFSSL_EARLY_DATA
-    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
-    if (ssl->session.maxEarlyDataSz > 0)
-        TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz);
-    extSz = 0;
-    ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz);
-    if (ret != 0)
-        return ret;
-#else
-    extSz = EXTS_SZ;
-#endif
-
-    /* Lifetime | Age Add | Ticket | Extensions */
-    length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ +
-             ssl->session.ticketLen + extSz;
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    /* Nonce */
-    length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ;
-#endif
-    sendSz = idx + length + MAX_MSG_EXTRA;
-
-    /* Check buffers are big enough and grow if needed. */
-    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
-        return ret;
-
-    /* Get position in output buffer to write new message to. */
-    output = ssl->buffers.outputBuffer.buffer +
-             ssl->buffers.outputBuffer.length;
-
-    /* Put the record and handshake headers on. */
-    AddTls13Headers(output, length, session_ticket, ssl);
-
-    /* Lifetime hint */
-    c32toa(ssl->ctx->ticketHint, output + idx);
-    idx += SESSION_HINT_SZ;
-    /* Age add - obfuscator */
-    c32toa(ssl->session.ticketAdd, output + idx);
-    idx += SESSION_ADD_SZ;
-
-#ifndef WOLFSSL_TLS13_DRAFT_18
-    output[idx++] = ssl->session.ticketNonce.len;
-    output[idx++] = ssl->session.ticketNonce.data[0];
-#endif
-
-    /* length */
-    c16toa(ssl->session.ticketLen, output + idx);
-    idx += LENGTH_SZ;
-    /* ticket */
-    XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
-    idx += ssl->session.ticketLen;
-
-#ifdef WOLFSSL_EARLY_DATA
-    extSz = 0;
-    ret = TLSX_WriteResponse(ssl, output + idx, session_ticket, &extSz);
-    if (ret != 0)
-        return ret;
-    idx += extSz;
-#else
-    /* No extension support - empty extensions. */
-    c16toa(0, output + idx);
-    idx += EXTS_SZ;
-#endif
-
-    ssl->options.haveSessionId = 1;
-
-#ifndef NO_SESSION_CACHE
-    AddSession(ssl);
-#endif
-
-    /* This message is always encrypted. */
-    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
-                               idx - RECORD_HEADER_SZ, handshake, 0, 0, 0);
-    if (sendSz < 0)
-        return sendSz;
-
-    ssl->buffers.outputBuffer.length += sendSz;
-
-    if (!ssl->options.groupMessages)
-        ret = SendBuffered(ssl);
-
-    WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0);
-    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_SEND);
-
-    return ret;
-}
-    #endif /* HAVE_SESSION_TICKET */
-#endif /* NO_WOLFSSL_SERVER */
-
-/* Make sure no duplicates, no fast forward, or other problems
- *
- * ssl   The SSL/TLS object.
- * type  Type of handshake message received.
- * returns 0 on success, otherwise failure.
- */
-static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
-{
-    /* verify not a duplicate, mark received, check state */
-    switch (type) {
-
-#ifndef NO_WOLFSSL_SERVER
-        case client_hello:
-        #ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_MSG("ClientHello received by client");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) {
-                WOLFSSL_MSG("ClientHello received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_client_hello == 2) {
-                WOLFSSL_MSG("Too many ClientHello received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_client_hello++;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case server_hello:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("ServerHello received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-        #ifdef WOLFSSL_TLS13_DRAFT_18
-            if (ssl->msgsReceived.got_server_hello) {
-                WOLFSSL_MSG("Duplicate ServerHello received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_server_hello = 1;
-        #else
-            if (ssl->msgsReceived.got_server_hello == 2) {
-                WOLFSSL_MSG("Duplicate ServerHello received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_server_hello++;
-        #endif
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case session_ticket:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("NewSessionTicket received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("NewSessionTicket received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            ssl->msgsReceived.got_session_ticket = 1;
-
-            break;
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-    #ifdef WOLFSSL_EARLY_DATA
-        case end_of_early_data:
-        #ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                WOLFSSL_MSG("EndOfEarlyData received by client");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("EndOfEarlyData received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("EndOfEarlyData received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_end_of_early_data == 1) {
-                WOLFSSL_MSG("Too many EndOfEarlyData received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_end_of_early_data++;
-
-            break;
-    #endif
-#endif
-
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    #ifndef NO_WOLFSSL_CLIENT
-        case hello_retry_request:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("HelloRetryRequest received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("HelloRetryRequest received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_hello_retry_request) {
-                WOLFSSL_MSG("Duplicate HelloRetryRequest received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_hello_retry_request = 1;
-
-            break;
-    #endif
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-        case encrypted_extensions:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("EncryptedExtensions received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-            if (ssl->options.serverState != SERVER_HELLO_COMPLETE) {
-                WOLFSSL_MSG("EncryptedExtensions received out of order");
-                return OUT_OF_ORDER_E;
-            }
-            if (ssl->msgsReceived.got_encrypted_extensions) {
-                WOLFSSL_MSG("Duplicate EncryptedExtensions received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_encrypted_extensions = 1;
-
-            break;
-#endif
-
-        case certificate:
-    #ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END &&
-                ssl->options.serverState !=
-                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
-                WOLFSSL_MSG("Certificate received out of order - Client");
-                return OUT_OF_ORDER_E;
-            }
-        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-            /* Server's authenticating with PSK must not send this. */
-            if (ssl->options.side == WOLFSSL_CLIENT_END &&
-                             ssl->options.serverState == SERVER_CERT_COMPLETE &&
-                             ssl->arrays->psk_keySz != 0) {
-                WOLFSSL_MSG("Certificate received while using PSK");
-                return SANITY_MSG_E;
-            }
-        #endif
-    #endif
-    #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END &&
-                ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
-                WOLFSSL_MSG("Certificate received out of order - Server");
-                return OUT_OF_ORDER_E;
-            }
-    #endif
-            if (ssl->msgsReceived.got_certificate) {
-                WOLFSSL_MSG("Duplicate Certificate received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate = 1;
-
-            break;
-
-#ifndef NO_WOLFSSL_CLIENT
-        case certificate_request:
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                WOLFSSL_MSG("CertificateRequest received by server");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
-            if (ssl->options.serverState !=
-                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
-                WOLFSSL_MSG("CertificateRequest received out of order");
-                return OUT_OF_ORDER_E;
-            }
-        #else
-            if (ssl->options.serverState !=
-                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
-                       (ssl->options.serverState != SERVER_FINISHED_COMPLETE ||
-                        ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) {
-                WOLFSSL_MSG("CertificateRequest received out of order");
-                return OUT_OF_ORDER_E;
-            }
-        #endif
-        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-            /* Server's authenticating with PSK must not send this. */
-            if (ssl->options.serverState ==
-                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
-                                                  ssl->arrays->psk_keySz != 0) {
-                WOLFSSL_MSG("CertificateRequset received while using PSK");
-                return SANITY_MSG_E;
-            }
-        #endif
-        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
-            if (ssl->msgsReceived.got_certificate_request) {
-                WOLFSSL_MSG("Duplicate CertificateRequest received");
-                return DUPLICATE_MSG_E;
-            }
-        #endif
-            ssl->msgsReceived.got_certificate_request = 1;
-
-            break;
-#endif
-
-        case certificate_verify:
-    #ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                if (ssl->options.serverState != SERVER_CERT_COMPLETE) {
-                    WOLFSSL_MSG("No Cert before CertVerify");
-                    return OUT_OF_ORDER_E;
-                }
-            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-                /* Server's authenticating with PSK must not send this. */
-                if (ssl->options.serverState == SERVER_CERT_COMPLETE &&
-                                                  ssl->arrays->psk_keySz != 0) {
-                    WOLFSSL_MSG("CertificateVerify received while using PSK");
-                    return SANITY_MSG_E;
-                }
-            #endif
-            }
-    #endif
-    #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
-                    WOLFSSL_MSG("CertificateVerify received out of order");
-                    return OUT_OF_ORDER_E;
-                }
-                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                    WOLFSSL_MSG("CertificateVerify before ClientHello done");
-                    return OUT_OF_ORDER_E;
-                }
-                if (!ssl->msgsReceived.got_certificate) {
-                    WOLFSSL_MSG("No Cert before CertificateVerify");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-    #endif
-            if (ssl->msgsReceived.got_certificate_verify) {
-                WOLFSSL_MSG("Duplicate CertificateVerify received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_certificate_verify = 1;
-
-            break;
-
-        case finished:
-        #ifndef NO_WOLFSSL_CLIENT
-            if (ssl->options.side == WOLFSSL_CLIENT_END) {
-                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                    WOLFSSL_MSG("Finished received out of order");
-                    return OUT_OF_ORDER_E;
-                }
-                if (ssl->options.serverState <
-                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
-                    WOLFSSL_MSG("Finished received out of order");
-                    return OUT_OF_ORDER_E;
-                }
-            }
-        #endif
-        #ifndef NO_WOLFSSL_SERVER
-            if (ssl->options.side == WOLFSSL_SERVER_END) {
-                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
-                    WOLFSSL_MSG("Finished received out of order");
-                    return OUT_OF_ORDER_E;
-                }
-                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                    WOLFSSL_MSG("Finished received out of order");
-                    return OUT_OF_ORDER_E;
-                }
-            #ifdef WOLFSSL_EARLY_DATA
-                if (ssl->earlyData == process_early_data) {
-                    return OUT_OF_ORDER_E;
-                }
-            #endif
-            }
-        #endif
-            if (ssl->msgsReceived.got_finished) {
-                WOLFSSL_MSG("Duplicate Finished received");
-                return DUPLICATE_MSG_E;
-            }
-            ssl->msgsReceived.got_finished = 1;
-
-            break;
-
-        case key_update:
-            if (!ssl->msgsReceived.got_finished) {
-                WOLFSSL_MSG("No KeyUpdate before Finished");
-                return OUT_OF_ORDER_E;
-            }
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown message type");
-            return SANITY_MSG_E;
-    }
-
-    return 0;
-}
-
-/* Handle a type of handshake message that has been received.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the buffer of the current message.
- *           On exit, the index into the buffer of the next message.
- * size      The length of the current handshake message.
- * totalSz   Length of remaining data in the message buffer.
- * returns 0 on success and otherwise failure.
- */
-int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                            byte type, word32 size, word32 totalSz)
-{
-    int ret = 0;
-    word32 inIdx = *inOutIdx;
-
-    (void)totalSz;
-
-    WOLFSSL_ENTER("DoTls13HandShakeMsgType");
-
-    /* make sure can read the message */
-    if (*inOutIdx + size > totalSz)
-        return INCOMPLETE_DATA;
-
-    /* sanity check msg received */
-    if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) {
-        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return ret;
-    }
-
-#ifdef WOLFSSL_CALLBACKS
-    /* add name later, add on record and handshake header part back on */
-    if (ssl->toInfoOn) {
-        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
-        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
-                      size + add, READ_PROTO, ssl->heap);
-        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
-    }
-#endif
-
-    if (ssl->options.handShakeState == HANDSHAKE_DONE &&
-            type != session_ticket && type != certificate_request &&
-            type != certificate && type != key_update) {
-        WOLFSSL_MSG("HandShake message after handshake complete");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->options.side == WOLFSSL_CLIENT_END &&
-               ssl->options.serverState == NULL_STATE &&
-               type != server_hello && type != hello_retry_request) {
-        WOLFSSL_MSG("First server message not server hello");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    if (ssl->options.side == WOLFSSL_SERVER_END &&
-               ssl->options.clientState == NULL_STATE && type != client_hello) {
-        WOLFSSL_MSG("First client message not client hello");
-        SendAlert(ssl, alert_fatal, unexpected_message);
-        return OUT_OF_ORDER_E;
-    }
-
-    /* above checks handshake state */
-    switch (type) {
-#ifndef NO_WOLFSSL_CLIENT
-    /* Messages only recieved by client. */
-    #ifdef WOLFSSL_TLS13_DRAFT_18
-    case hello_retry_request:
-        WOLFSSL_MSG("processing hello rety request");
-        ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size);
-        break;
-    #endif
-
-    case server_hello:
-        WOLFSSL_MSG("processing server hello");
-        ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type);
-        break;
-
-    case encrypted_extensions:
-        WOLFSSL_MSG("processing encrypted extensions");
-        ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size);
-        break;
-
-    #ifndef NO_CERTS
-    case certificate_request:
-        WOLFSSL_MSG("processing certificate request");
-        ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size);
-        break;
-    #endif
-
-    case session_ticket:
-        WOLFSSL_MSG("processing new session ticket");
-        ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size);
-        break;
-#endif /* !NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-    /* Messages only recieved by server. */
-    case client_hello:
-        WOLFSSL_MSG("processing client hello");
-        ret = DoTls13ClientHello(ssl, input, inOutIdx, size);
-        break;
-
-    #ifdef WOLFSSL_EARLY_DATA
-    case end_of_early_data:
-        WOLFSSL_MSG("processing end of early data");
-        ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size);
-        break;
-    #endif
-#endif /* !NO_WOLFSSL_SERVER */
-
-    /* Messages recieved by both client and server. */
-#ifndef NO_CERTS
-    case certificate:
-        WOLFSSL_MSG("processing certificate");
-        ret = DoTls13Certificate(ssl, input, inOutIdx, size);
-        break;
-#endif
-
-#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
-    case certificate_verify:
-        WOLFSSL_MSG("processing certificate verify");
-        ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size);
-        break;
-#endif /* !NO_RSA || HAVE_ECC */
-
-    case finished:
-        WOLFSSL_MSG("processing finished");
-        ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
-        break;
-
-    case key_update:
-        WOLFSSL_MSG("processing finished");
-        ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size);
-        break;
-
-    default:
-        WOLFSSL_MSG("Unknown handshake message type");
-        ret = UNKNOWN_HANDSHAKE_TYPE;
-        break;
-    }
-
-    /* reset error */
-    if (ret == 0 && ssl->error == WC_PENDING_E)
-        ssl->error = 0;
-
-    if (ret == 0 && type != client_hello && type != session_ticket &&
-                                                           type != key_update) {
-        ret = HashInput(ssl, input + inIdx, size);
-    }
-
-    if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA)
-        SendAlert(ssl, alert_fatal, decode_error);
-    else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR ||
-                        ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA ||
-                        ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) {
-        SendAlert(ssl, alert_fatal, illegal_parameter);
-    }
-
-    if (ssl->options.tls1_3) {
-        /* Need to hash input message before deriving secrets. */
-    #ifndef NO_WOLFSSL_CLIENT
-        if (ssl->options.side == WOLFSSL_CLIENT_END) {
-            if (type == server_hello) {
-                if ((ret = DeriveEarlySecret(ssl)) != 0)
-                    return ret;
-                if ((ret = DeriveHandshakeSecret(ssl)) != 0)
-                    return ret;
-
-                if ((ret = DeriveTls13Keys(ssl, handshake_key,
-                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
-                    return ret;
-                }
-        #ifdef WOLFSSL_EARLY_DATA
-                if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
-                    return ret;
-        #else
-                if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
-                    return ret;
-        #endif
-            }
-
-            if (type == finished) {
-                if ((ret = DeriveMasterSecret(ssl)) != 0)
-                    return ret;
-        #ifdef WOLFSSL_EARLY_DATA
-                if ((ret = DeriveTls13Keys(ssl, traffic_key,
-                                       ENCRYPT_AND_DECRYPT_SIDE,
-                                       ssl->earlyData == no_early_data)) != 0) {
-                    return ret;
-                }
-        #else
-                if ((ret = DeriveTls13Keys(ssl, traffic_key,
-                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
-                    return ret;
-                }
-        #endif
-            }
-        #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-            if (type == certificate_request &&
-                                ssl->options.handShakeState == HANDSHAKE_DONE) {
-                /* reset handshake states */
-                ssl->options.clientState = CLIENT_HELLO_COMPLETE;
-                ssl->options.connectState  = FIRST_REPLY_DONE;
-                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
-
-                if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS)
-                    ret = POST_HAND_AUTH_ERROR;
-            }
-        #endif
-        }
-    #endif /* NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-        if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) {
-            ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
-            if (ret != 0)
-                return ret;
-        }
-    #endif
-#endif /* NO_WOLFSSL_SERVER */
-    }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* if async, offset index so this msg will be processed again */
-    if (ret == WC_PENDING_E && *inOutIdx > 0) {
-        *inOutIdx -= HANDSHAKE_HEADER_SZ;
-    }
-#endif
-
-    WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret);
-    return ret;
-}
-
-
-/* Handle a handshake message that has been received.
- *
- * ssl       The SSL/TLS object.
- * input     The message buffer.
- * inOutIdx  On entry, the index into the buffer of the current message.
- *           On exit, the index into the buffer of the next message.
- * totalSz   Length of remaining data in the message buffer.
- * returns 0 on success and otherwise failure.
- */
-int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
-                        word32 totalSz)
-{
-    int    ret = 0;
-    word32 inputLength;
-
-    WOLFSSL_ENTER("DoTls13HandShakeMsg()");
-
-    if (ssl->arrays == NULL) {
-        byte   type;
-        word32 size;
-
-        if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
-            return PARSE_ERROR;
-
-        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
-                                       totalSz);
-    }
-
-    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz;
-
-    /* If there is a pending fragmented handshake message,
-     * pending message size will be non-zero. */
-    if (ssl->arrays->pendingMsgSz == 0) {
-        byte   type;
-        word32 size;
-
-        if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
-            return PARSE_ERROR;
-
-        /* Cap the maximum size of a handshake message to something reasonable.
-         * By default is the maximum size of a certificate message assuming
-         * nine 2048-bit RSA certificates in the chain. */
-        if (size > MAX_HANDSHAKE_SZ) {
-            WOLFSSL_MSG("Handshake message too large");
-            return HANDSHAKE_SIZE_ERROR;
-        }
-
-        /* size is the size of the certificate message payload */
-        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
-            ssl->arrays->pendingMsgType = type;
-            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
-            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
-                                                     ssl->heap,
-                                                     DYNAMIC_TYPE_ARRAYS);
-            if (ssl->arrays->pendingMsg == NULL)
-                return MEMORY_E;
-            XMEMCPY(ssl->arrays->pendingMsg,
-                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
-                    inputLength);
-            ssl->arrays->pendingMsgOffset = inputLength;
-            *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ;
-            return 0;
-        }
-
-        ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
-                                      totalSz);
-    }
-    else {
-        if (inputLength + ssl->arrays->pendingMsgOffset >
-                                                    ssl->arrays->pendingMsgSz) {
-            inputLength = ssl->arrays->pendingMsgSz -
-                                                  ssl->arrays->pendingMsgOffset;
-        }
-        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
-                input + *inOutIdx, inputLength);
-        ssl->arrays->pendingMsgOffset += inputLength;
-        *inOutIdx += inputLength + ssl->keys.padSz;
-
-        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
-        {
-            word32 idx = 0;
-            ret = DoTls13HandShakeMsgType(ssl,
-                                ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ,
-                                &idx, ssl->arrays->pendingMsgType,
-                                ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ,
-                                ssl->arrays->pendingMsgSz);
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (ret == WC_PENDING_E) {
-                /* setup to process fragment again */
-                ssl->arrays->pendingMsgOffset -= inputLength;
-                *inOutIdx -= inputLength + ssl->keys.padSz;
-            }
-            else
-        #endif
-            {
-                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
-                ssl->arrays->pendingMsg = NULL;
-                ssl->arrays->pendingMsgSz = 0;
-            }
-        }
-    }
-
-    WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret);
-    return ret;
-}
-
-#ifndef NO_WOLFSSL_CLIENT
-
-/* The client connecting to the server.
- * The protocol version is expecting to be TLS v1.3.
- * If the server downgrades, and older versions of the protocol are compiled
- * in, the client will fallback to wolfSSL_connect().
- * Please see note at top of README if you get an error from connect.
- *
- * ssl  The SSL/TLS object.
- * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
- * unrecoverable error occurs and 0 otherwise.
- * For more error information use wolfSSL_get_error().
- */
-int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
-{
-    WOLFSSL_ENTER("wolfSSL_connect_TLSv13()");
-
-    #ifdef HAVE_ERRNO_H
-    errno = 0;
-    #endif
-
-    if (ssl->options.side != WOLFSSL_CLIENT_END) {
-        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-    if (ssl->buffers.outputBuffer.length > 0) {
-        if ((ssl->error = SendBuffered(ssl)) == 0) {
-            /* fragOffset is non-zero when sending fragments. On the last
-             * fragment, fragOffset is zero again, and the state can be
-             * advanced. */
-            if (ssl->fragOffset == 0) {
-                ssl->options.connectState++;
-                WOLFSSL_MSG("connect state: "
-                            "Advanced from last buffered fragment send");
-            }
-            else {
-                WOLFSSL_MSG("connect state: "
-                            "Not advanced, more fragments to send");
-            }
-        }
-        else {
-            WOLFSSL_ERROR(ssl->error);
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    switch (ssl->options.connectState) {
-
-        case CONNECT_BEGIN:
-            /* Always send client hello first. */
-            if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-
-            ssl->options.connectState = CLIENT_HELLO_SENT;
-            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
-    #ifdef WOLFSSL_EARLY_DATA
-            if (ssl->earlyData != no_early_data) {
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                ssl->options.sentChangeCipher = 1;
-        #endif
-                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
-                return WOLFSSL_SUCCESS;
-            }
-    #endif
-            FALL_THROUGH;
-
-        case CLIENT_HELLO_SENT:
-            /* Get the response/s from the server. */
-            while (ssl->options.serverState <
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                if ((ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.connectState = HELLO_AGAIN;
-            WOLFSSL_MSG("connect state: HELLO_AGAIN");
-            FALL_THROUGH;
-
-        case HELLO_AGAIN:
-            if (ssl->options.certOnly)
-                return WOLFSSL_SUCCESS;
-
-            if (!ssl->options.tls1_3) {
-    #ifndef WOLFSSL_NO_TLS12
-                if (ssl->options.downgrade)
-                    return wolfSSL_connect(ssl);
-    #endif
-
-                WOLFSSL_MSG("Client using higher version, fatal error");
-                return VERSION_ERROR;
-            }
-
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-                if (!ssl->options.sentChangeCipher) {
-                    if ((ssl->error = SendChangeCipher(ssl)) != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                    ssl->options.sentChangeCipher = 1;
-                }
-        #endif
-                /* Try again with different security parameters. */
-                if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.connectState = HELLO_AGAIN_REPLY;
-            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
-            FALL_THROUGH;
-
-        case HELLO_AGAIN_REPLY:
-            /* Get the response/s from the server. */
-            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
-                if ((ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.connectState = FIRST_REPLY_DONE;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_DONE:
-        #ifdef WOLFSSL_EARLY_DATA
-            if (ssl->earlyData != no_early_data) {
-                if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                WOLFSSL_MSG("sent: end_of_early_data");
-            }
-        #endif
-
-            ssl->options.connectState = FIRST_REPLY_FIRST;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_FIRST:
-        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-            if (!ssl->options.sentChangeCipher) {
-                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                ssl->options.sentChangeCipher = 1;
-            }
-        #endif
-
-            ssl->options.connectState = FIRST_REPLY_SECOND;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_SECOND:
-        #ifndef NO_CERTS
-            if (!ssl->options.resuming && ssl->options.sendVerify) {
-                ssl->error = SendTls13Certificate(ssl);
-                if (ssl->error != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                WOLFSSL_MSG("sent: certificate");
-            }
-        #endif
-
-            ssl->options.connectState = FIRST_REPLY_THIRD;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_THIRD:
-        #ifndef NO_CERTS
-            if (!ssl->options.resuming && ssl->options.sendVerify) {
-                ssl->error = SendTls13CertificateVerify(ssl);
-                if (ssl->error != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                WOLFSSL_MSG("sent: certificate verify");
-            }
-        #endif
-
-            ssl->options.connectState = FIRST_REPLY_FOURTH;
-            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
-            FALL_THROUGH;
-
-        case FIRST_REPLY_FOURTH:
-            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            WOLFSSL_MSG("sent: finished");
-
-            ssl->options.connectState = FINISHED_DONE;
-            WOLFSSL_MSG("connect state: FINISHED_DONE");
-            FALL_THROUGH;
-
-        case FINISHED_DONE:
-        #ifndef NO_HANDSHAKE_DONE_CB
-            if (ssl->hsDoneCb != NULL) {
-                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
-                if (cbret < 0) {
-                    ssl->error = cbret;
-                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-        #endif /* NO_HANDSHAKE_DONE_CB */
-
-            WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS);
-            return WOLFSSL_SUCCESS;
-
-        default:
-            WOLFSSL_MSG("Unknown connect state ERROR");
-            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
-    }
-}
-#endif
-
-#if defined(WOLFSSL_SEND_HRR_COOKIE)
-/* Send a cookie with the HelloRetryRequest to avoid storing state.
- *
- * ssl       SSL/TLS object.
- * secret    Secret to use when generating integrity check for cookie.
- *           A value of NULL indicates to generate a new random secret.
- * secretSz  Size of secret data in bytes.
- *           Use a value of 0 to indicate use of default size.
- * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, SIDE_ERROR when
- * called on a client; WOLFSSL_SUCCESS on success and otherwise failure.
- */
-int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret,
-                            unsigned int secretSz)
-{
-    int ret;
-
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
- #ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-    if (secretSz == 0) {
-    #if !defined(NO_SHA) && defined(NO_SHA256)
-        secretSz = WC_SHA_DIGEST_SIZE;
-    #endif /* NO_SHA */
-    #ifndef NO_SHA256
-        secretSz = WC_SHA256_DIGEST_SIZE;
-    #endif /* NO_SHA256 */
-    }
-
-    if (secretSz != ssl->buffers.tls13CookieSecret.length) {
-        byte* newSecret;
-
-        if (ssl->buffers.tls13CookieSecret.buffer != NULL) {
-            ForceZero(ssl->buffers.tls13CookieSecret.buffer,
-                      ssl->buffers.tls13CookieSecret.length);
-            XFREE(ssl->buffers.tls13CookieSecret.buffer,
-                  ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
-        }
-
-        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,
-                                   DYNAMIC_TYPE_COOKIE_PWD);
-        if (newSecret == NULL) {
-            ssl->buffers.tls13CookieSecret.buffer = NULL;
-            ssl->buffers.tls13CookieSecret.length = 0;
-            WOLFSSL_MSG("couldn't allocate new cookie secret");
-            return MEMORY_ERROR;
-        }
-        ssl->buffers.tls13CookieSecret.buffer = newSecret;
-        ssl->buffers.tls13CookieSecret.length = secretSz;
-    }
-
-    /* If the supplied secret is NULL, randomly generate a new secret. */
-    if (secret == NULL) {
-        ret = wc_RNG_GenerateBlock(ssl->rng,
-                               ssl->buffers.tls13CookieSecret.buffer, secretSz);
-        if (ret < 0)
-            return ret;
-    }
-    else
-        XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz);
-
-    ssl->options.sendCookie = 1;
-
-    ret = WOLFSSL_SUCCESS;
-#else
-    (void)secret;
-    (void)secretSz;
-
-    ret = SIDE_ERROR;
-#endif
-
-    return ret;
-}
-#endif
-
-/* Create a key share entry from group.
- * Generates a key pair.
- *
- * ssl    The SSL/TLS object.
- * group  The named group.
- * returns 0 on success, otherwise failure.
- */
-int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group)
-{
-    int ret;
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
-    if (ret != 0)
-        return ret;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* Send no key share entries - use HelloRetryRequest to negotiate shared group.
- *
- * ssl    The SSL/TLS object.
- * returns 0 on success, otherwise failure.
- */
-int wolfSSL_NoKeyShares(WOLFSSL* ssl)
-{
-    int ret;
-
-    if (ssl == NULL)
-        return BAD_FUNC_ARG;
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-
-    ret = TLSX_KeyShare_Empty(ssl);
-    if (ret != 0)
-        return ret;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* Do not send a ticket after TLS v1.3 handshake for resumption.
- *
- * ctx  The SSL/TLS CTX object.
- * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
- */
-int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
-        return BAD_FUNC_ARG;
-    if (ctx->method->side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-#ifdef HAVE_SESSION_TICKET
-    ctx->noTicketTls13 = 1;
-#endif
-
-    return 0;
-}
-
-/* Do not send a ticket after TLS v1.3 handshake for resumption.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on
- * a client and 0 on success.
- */
-int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl)
-{
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-#ifdef HAVE_SESSION_TICKET
-    ssl->options.noTicketTls13 = 1;
-#endif
-
-    return 0;
-}
-
-/* Disallow (EC)DHE key exchange when using pre-shared keys.
- *
- * ctx  The SSL/TLS CTX object.
- * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
- */
-int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
-        return BAD_FUNC_ARG;
-
-    ctx->noPskDheKe = 1;
-
-    return 0;
-}
-
-/* Disallow (EC)DHE key exchange when using pre-shared keys.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on
- * success.
- */
-int wolfSSL_no_dhe_psk(WOLFSSL* ssl)
-{
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-
-    ssl->options.noPskDheKe = 1;
-
-    return 0;
-}
-
-/* Update the keys for encryption and decryption.
- * If using non-blocking I/O and WOLFSSL_ERROR_WANT_WRITE is returned then
- * calling wolfSSL_write() will have the message sent when ready.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
- * WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write,
- * WOLFSSL_SUCCESS on success and otherwise failure.
- */
-int wolfSSL_update_keys(WOLFSSL* ssl)
-{
-    int ret;
-
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-
-    ret = SendTls13KeyUpdate(ssl);
-    if (ret == WANT_WRITE)
-        ret = WOLFSSL_ERROR_WANT_WRITE;
-    else if (ret == 0)
-        ret = WOLFSSL_SUCCESS;
-    return ret;
-}
-
-#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-/* Allow post-handshake authentication in TLS v1.3 connections.
- *
- * ctx  The SSL/TLS CTX object.
- * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a client and
- * 0 on success.
- */
-int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx)
-{
-    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
-        return BAD_FUNC_ARG;
-    if (ctx->method->side == WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-
-    ctx->postHandshakeAuth = 1;
-
-    return 0;
-}
-
-/* Allow post-handshake authentication in TLS v1.3 connection.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
- * SIDE_ERROR when not a client and 0 on success.
- */
-int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl)
-{
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-
-    ssl->options.postHandshakeAuth = 1;
-
-    return 0;
-}
-
-/* Request a certificate of the client.
- * Can be called any time after handshake completion.
- * A maximum of 256 requests can be sent on a connection.
- *
- * ssl  SSL/TLS object.
- */
-int wolfSSL_request_certificate(WOLFSSL* ssl)
-{
-    int         ret;
-#ifndef NO_WOLFSSL_SERVER
-    CertReqCtx* certReqCtx;
-#endif
-
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-#ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-    if (ssl->options.handShakeState != HANDSHAKE_DONE)
-        return NOT_READY_ERROR;
-    if (!ssl->options.postHandshakeAuth)
-        return POST_HAND_AUTH_ERROR;
-
-    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx), ssl->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (certReqCtx == NULL)
-        return MEMORY_E;
-    XMEMSET(certReqCtx, 0, sizeof(CertReqCtx));
-    certReqCtx->next = ssl->certReqCtx;
-    certReqCtx->len = 1;
-    if (certReqCtx->next != NULL)
-        certReqCtx->ctx = certReqCtx->next->ctx + 1;
-    ssl->certReqCtx = certReqCtx;
-
-    ssl->msgsReceived.got_certificate = 0;
-    ssl->msgsReceived.got_certificate_verify = 0;
-    ssl->msgsReceived.got_finished = 0;
-
-    ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len);
-    if (ret == WANT_WRITE)
-        ret = WOLFSSL_ERROR_WANT_WRITE;
-    else if (ret == 0)
-        ret = WOLFSSL_SUCCESS;
-#else
-    ret = SIDE_ERROR;
-#endif
-
-    return ret;
-}
-#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */
-
-#if !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
-/* Get the preferred key exchange group.
- *
- * ssl  The SSL/TLS object.
- * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3,
- * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete
- * and group number on success.
- */
-int wolfSSL_preferred_group(WOLFSSL* ssl)
-{
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-    if (ssl->options.handShakeState != HANDSHAKE_DONE)
-        return NOT_READY_ERROR;
-
-    /* Return supported groups only. */
-    return TLSX_SupportedCurve_Preferred(ssl, 1);
-#else
-    return SIDE_ERROR;
-#endif
-}
-#endif
-
-/* Sets the key exchange groups in rank order on a context.
- *
- * ctx     SSL/TLS context object.
- * groups  Array of groups.
- * count   Number of groups in array.
- * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or
- * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
- */
-int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count)
-{
-    int i;
-
-    if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
-        return BAD_FUNC_ARG;
-    if (!IsAtLeastTLSv1_3(ctx->method->version))
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < count; i++)
-        ctx->group[i] = (word16)groups[i];
-    ctx->numGroups = (byte)count;
-
-    return WOLFSSL_SUCCESS;
-}
-
-/* Sets the key exchange groups in rank order.
- *
- * ssl     SSL/TLS object.
- * groups  Array of groups.
- * count   Number of groups in array.
- * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or
- * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
- */
-int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count)
-{
-    int i;
-
-    if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
-        return BAD_FUNC_ARG;
-    if (!IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < count; i++)
-        ssl->group[i] = (word16)groups[i];
-    ssl->numGroups = (byte)count;
-
-    return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_WOLFSSL_SERVER
-/* The server accepting a connection from a client.
- * The protocol version is expecting to be TLS v1.3.
- * If the client downgrades, and older versions of the protocol are compiled
- * in, the server will fallback to wolfSSL_accept().
- * Please see note at top of README if you get an error from accept.
- *
- * ssl  The SSL/TLS object.
- * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
- * unrecoverable error occurs and 0 otherwise.
- * For more error information use wolfSSL_get_error().
- */
-int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
-{
-    word16 havePSK = 0;
-    WOLFSSL_ENTER("SSL_accept_TLSv13()");
-
-#ifdef HAVE_ERRNO_H
-    errno = 0;
-#endif
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    havePSK = ssl->options.havePSK;
-#endif
-    (void)havePSK;
-
-    if (ssl->options.side != WOLFSSL_SERVER_END) {
-        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
-        return WOLFSSL_FATAL_ERROR;
-    }
-
-#ifndef NO_CERTS
-    /* allow no private key if using PK callbacks and CB is set */
-    if (!havePSK) {
-        if (!ssl->buffers.certificate ||
-            !ssl->buffers.certificate->buffer) {
-
-            WOLFSSL_MSG("accept error: server cert required");
-            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
-            return WOLFSSL_FATAL_ERROR;
-        }
-
-    #ifdef HAVE_PK_CALLBACKS
-        if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
-            WOLFSSL_MSG("Using PK for server private key");
-        }
-        else
-    #endif
-        if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
-            WOLFSSL_MSG("accept error: server key required");
-            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-#endif
-
-    if (ssl->buffers.outputBuffer.length > 0) {
-        if ((ssl->error = SendBuffered(ssl)) == 0) {
-            /* fragOffset is non-zero when sending fragments. On the last
-             * fragment, fragOffset is zero again, and the state can be
-             * advanced. */
-            if (ssl->fragOffset == 0) {
-                ssl->options.acceptState++;
-                WOLFSSL_MSG("accept state: "
-                            "Advanced from last buffered fragment send");
-            }
-            else {
-                WOLFSSL_MSG("accept state: "
-                            "Not advanced, more fragments to send");
-            }
-        }
-        else {
-            WOLFSSL_ERROR(ssl->error);
-            return WOLFSSL_FATAL_ERROR;
-        }
-    }
-
-    switch (ssl->options.acceptState) {
-
-        case TLS13_ACCEPT_BEGIN :
-            /* get client_hello */
-            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                if ((ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_CLIENT_HELLO_DONE :
-#ifdef WOLFSSL_TLS13_DRAFT_18
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
-#else
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                if ((ssl->error = SendTls13ServerHello(ssl,
-                                                   hello_retry_request)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
-    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                ssl->options.sentChangeCipher = 1;
-            }
-    #endif
-            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
-            FALL_THROUGH;
-#endif
-
-        case TLS13_ACCEPT_FIRST_REPLY_DONE :
-            if (ssl->options.serverState ==
-                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
-                ssl->options.clientState = NULL_STATE;
-                while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
-                    if ((ssl->error = ProcessReply(ssl)) < 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                }
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_SECOND_REPLY_DONE :
-            if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.acceptState = TLS13_SERVER_HELLO_SENT;
-            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
-            FALL_THROUGH;
-
-        case TLS13_SERVER_HELLO_SENT :
-    #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
-                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-            if (!ssl->options.sentChangeCipher) {
-                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-                ssl->options.sentChangeCipher = 1;
-            }
-    #endif
-
-            ssl->options.acceptState = TLS13_ACCEPT_THIRD_REPLY_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_THIRD_REPLY_DONE :
-            if (!ssl->options.noPskDheKe) {
-                ssl->error = TLSX_KeyShare_DeriveSecret(ssl);
-                if (ssl->error != 0)
-                    return WOLFSSL_FATAL_ERROR;
-            }
-
-            if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-            ssl->options.acceptState = TLS13_SERVER_EXTENSIONS_SENT;
-            WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT");
-            FALL_THROUGH;
-
-        case TLS13_SERVER_EXTENSIONS_SENT :
-#ifndef NO_CERTS
-            if (!ssl->options.resuming) {
-                if (ssl->options.verifyPeer) {
-                    ssl->error = SendTls13CertificateRequest(ssl, NULL, 0);
-                    if (ssl->error != 0) {
-                        WOLFSSL_ERROR(ssl->error);
-                        return WOLFSSL_FATAL_ERROR;
-                    }
-                }
-            }
-#endif
-            ssl->options.acceptState = TLS13_CERT_REQ_SENT;
-            WOLFSSL_MSG("accept state CERT_REQ_SENT");
-            FALL_THROUGH;
-
-        case TLS13_CERT_REQ_SENT :
-#ifndef NO_CERTS
-            if (!ssl->options.resuming && ssl->options.sendVerify) {
-                if ((ssl->error = SendTls13Certificate(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif
-            ssl->options.acceptState = TLS13_CERT_SENT;
-            WOLFSSL_MSG("accept state CERT_SENT");
-            FALL_THROUGH;
-
-        case TLS13_CERT_SENT :
-#ifndef NO_CERTS
-            if (!ssl->options.resuming && ssl->options.sendVerify) {
-                if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif
-            ssl->options.acceptState = TLS13_CERT_VERIFY_SENT;
-            WOLFSSL_MSG("accept state CERT_VERIFY_SENT");
-            FALL_THROUGH;
-
-        case TLS13_CERT_VERIFY_SENT :
-            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
-                WOLFSSL_ERROR(ssl->error);
-                return WOLFSSL_FATAL_ERROR;
-            }
-
-            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT;
-            WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT");
-#ifdef WOLFSSL_EARLY_DATA
-            if (ssl->earlyData != no_early_data) {
-                ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
-                return WOLFSSL_SUCCESS;
-            }
-#endif
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_FINISHED_SENT :
-#ifdef HAVE_SESSION_TICKET
-    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
-            if (!ssl->options.resuming && !ssl->options.verifyPeer &&
-                !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
-                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-    #endif
-#endif /* HAVE_SESSION_TICKET */
-            ssl->options.acceptState = TLS13_PRE_TICKET_SENT;
-            WOLFSSL_MSG("accept state  TICKET_SENT");
-            FALL_THROUGH;
-
-        case TLS13_PRE_TICKET_SENT :
-            while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
-                if ( (ssl->error = ProcessReply(ssl)) < 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-
-            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_DONE;
-            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
-            FALL_THROUGH;
-
-        case TLS13_ACCEPT_FINISHED_DONE :
-#ifdef HAVE_SESSION_TICKET
-    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
-            if (!ssl->options.verifyPeer) {
-            }
-            else
-    #endif
-            if (!ssl->options.resuming &&
-                !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
-                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
-                    WOLFSSL_ERROR(ssl->error);
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif /* HAVE_SESSION_TICKET */
-            ssl->options.acceptState = TLS13_TICKET_SENT;
-            WOLFSSL_MSG("accept state TICKET_SENT");
-            FALL_THROUGH;
-
-        case TLS13_TICKET_SENT :
-#ifndef NO_HANDSHAKE_DONE_CB
-            if (ssl->hsDoneCb) {
-                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
-                if (cbret < 0) {
-                    ssl->error = cbret;
-                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
-                    return WOLFSSL_FATAL_ERROR;
-                }
-            }
-#endif /* NO_HANDSHAKE_DONE_CB */
-
-            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
-            return WOLFSSL_SUCCESS;
-
-        default :
-            WOLFSSL_MSG("Unknown accept state ERROR");
-            return WOLFSSL_FATAL_ERROR;
-    }
-}
-#endif
-
-#ifdef WOLFSSL_EARLY_DATA
-/* Sets the maximum amount of early data that can be seen by server when using
- * session tickets for resumption.
- * A value of zero indicates no early data is to be sent by client using session
- * tickets.
- *
- * ctx  The SSL/TLS CTX object.
- * sz   Maximum size of the early data.
- * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
- * 0 on success.
- */
-int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz)
-{
-    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
-        return BAD_FUNC_ARG;
-    if (ctx->method->side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-    ctx->maxEarlyDataSz = sz;
-
-    return 0;
-}
-
-/* Sets the maximum amount of early data that can be seen by server when using
- * session tickets for resumption.
- * A value of zero indicates no early data is to be sent by client using session
- * tickets.
- *
- * ssl  The SSL/TLS object.
- * sz   Maximum size of the early data.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
- * SIDE_ERROR when not a server and 0 on success.
- */
-int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz)
-{
-    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-    ssl->options.maxEarlyDataSz = sz;
-
-    return 0;
-}
-
-/* Write early data to the server.
- *
- * ssl    The SSL/TLS object.
- * data   Early data to write
- * sz     The size of the eary data in bytes.
- * outSz  The number of early data bytes written.
- * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
- * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
- * early data bytes written.
- */
-int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("SSL_write_early_data()");
-
-    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
-        return BAD_FUNC_ARG;
-    if (!IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-
-#ifndef NO_WOLFSSL_CLIENT
-    if (ssl->options.side == WOLFSSL_SERVER_END)
-        return SIDE_ERROR;
-
-    if (ssl->options.handShakeState == NULL_STATE) {
-        ssl->earlyData = expecting_early_data;
-        ret = wolfSSL_connect_TLSv13(ssl);
-        if (ret <= 0)
-            return WOLFSSL_FATAL_ERROR;
-    }
-    if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) {
-        ret = SendData(ssl, data, sz);
-        if (ret > 0)
-            *outSz = ret;
-    }
-#else
-    return SIDE_ERROR;
-#endif
-
-    WOLFSSL_LEAVE("SSL_write_early_data()", ret);
-
-    if (ret < 0)
-        ret = WOLFSSL_FATAL_ERROR;
-    return ret;
-}
-
-/* Read the any early data from the client.
- *
- * ssl    The SSL/TLS object.
- * data   Buffer to put the early data into.
- * sz     The size of the buffer in bytes.
- * outSz  The number of early data bytes read.
- * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
- * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
- * early data bytes read.
- */
-int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz)
-{
-    int ret = 0;
-
-    WOLFSSL_ENTER("wolfSSL_read_early_data()");
-
-
-    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
-        return BAD_FUNC_ARG;
-    if (!IsAtLeastTLSv1_3(ssl->version))
-        return BAD_FUNC_ARG;
-
-#ifndef NO_WOLFSSL_SERVER
-    if (ssl->options.side == WOLFSSL_CLIENT_END)
-        return SIDE_ERROR;
-
-    if (ssl->options.handShakeState == NULL_STATE) {
-        ssl->earlyData = expecting_early_data;
-        ret = wolfSSL_accept_TLSv13(ssl);
-        if (ret <= 0)
-            return WOLFSSL_FATAL_ERROR;
-    }
-    if (ssl->options.handShakeState == SERVER_FINISHED_COMPLETE) {
-        ret = ReceiveData(ssl, (byte*)data, sz, FALSE);
-        if (ret > 0)
-            *outSz = ret;
-        if (ssl->error == ZERO_RETURN)
-            ssl->error = WOLFSSL_ERROR_NONE;
-    }
-    else
-        ret = 0;
-#else
-    return SIDE_ERROR;
-#endif
-
-    WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret);
-
-    if (ret < 0)
-        ret = WOLFSSL_FATAL_ERROR;
-    return ret;
-}
-#endif
-
-#undef ERROR_OUT
-
-#endif /* !WOLFCRYPT_ONLY */
-
-#endif /* WOLFSSL_TLS13 */
-
+/* tls13.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+ * BUILD_GCM
+ *    Enables AES-GCM ciphersuites.
+ * HAVE_AESCCM
+ *    Enables AES-CCM ciphersuites.
+ * HAVE_SESSION_TICKET
+ *    Enables session tickets - required for TLS 1.3 resumption.
+ * NO_PSK
+ *    Do not enable Pre-Shared Keys.
+ * TLS13_SUPPORTS_EXPORTERS
+ *    Gaurd to compile out any code for exporter keys.
+ *    Feature not supported yet.
+ * WOLFSSL_ASYNC_CRYPT
+ *    Enables the use of asynchornous cryptographic operations.
+ *    This is available for ciphers and certificates.
+ * HAVE_CHACHA && HAVE_POLY1305
+ *    Enables use of CHACHA20-POLY1305 ciphersuites.
+ * WOLFSSL_DEBUG_TLS
+ *    Writes out details of TLS 1.3 protocol including hanshake message buffers
+ *    and key generation input and output.
+ * WOLFSSL_EARLY_DATA
+ *    Allow 0-RTT Handshake using Early Data extensions and handshake message
+ * WOLFSSL_NO_SERVER_GROUPS_EXT
+ *    Do not send the server's groups in an extension when the server's top
+ *    preference is not in client's list.
+ * WOLFSSL_POST_HANDSHAKE_AUTH
+ *    Allow TLS v1.3 code to perform post-handshake authentication of the
+ *    client.
+ * WOLFSSL_SEND_HRR_COOKIE
+ *    Send a cookie in hello_retry_request message to enable stateless tracking
+ *    of ClientHello replies.
+ * WOLFSSL_TLS13
+ *    Enable TLS 1.3 protocol implementation.
+ * WOLFSSL_TLS13_DRAFT_18
+ *    Conform with Draft 18 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_DRAFT_22
+ *    Conform with Draft 22 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_DRAFT_23
+ *    Conform with Draft 23 of the TLS v1.3 specification.
+ * WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+ *    Enable middlebox compatability in the TLS 1.3 handshake.
+ *    This includes sending ChangeCipherSpec before encrypted messages and
+ *    including a session id.
+ * WOLFSSL_TLS13_SHA512
+ *    Allow generation of SHA-512 digests in handshake - no ciphersuite
+ *    requires SHA-512 at this time.
+ * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+ *    Allow a NewSessionTicket message to be sent by server before Client's
+ *    Finished message.
+ *    See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note).
+ */
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_TLS13
+#ifdef HAVE_SESSION_TICKET
+    #include <wolfcrypt/wc_port.h>
+#endif
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef HAVE_ERRNO_H
+    #include <errno.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfcrypt/asn.h>
+#include <wolfcrypt/dh.h>
+#ifdef NO_INLINE
+    #include <wolfcrypt/misc.h>
+#else
+    #define WOLFSSL_MISC_INCLUDED
+    #include <wolfcrypt/src/misc.c>
+#endif
+
+#ifdef HAVE_NTRU
+    #include "libntruencrypt/ntru_crypto.h"
+#endif
+
+#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \
+    defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG)
+    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+        #if MQX_USE_IO_OLD
+            #include <fio.h>
+        #else
+            #include <nio.h>
+        #endif
+    #else
+        #include <stdio.h>
+    #endif
+#endif
+
+#ifdef __sun
+    #include <sys/filio.h>
+#endif
+
+#ifndef TRUE
+    #define TRUE  1
+#endif
+#ifndef FALSE
+    #define FALSE 0
+#endif
+
+#ifndef HAVE_HKDF
+    #error The build option HAVE_HKDF is required for TLS 1.3
+#endif
+
+
+/* Set ret to error value and jump to label.
+ *
+ * err     The error value to set.
+ * eLabel  The label to jump to.
+ */
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+
+/* Extract data using HMAC, salt and input.
+ * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+ *
+ * prk      The generated pseudorandom key.
+ * salt     The salt.
+ * saltLen  The length of the salt.
+ * ikm      The input keying material.
+ * ikmLen   The length of the input keying material.
+ * mac      The type of digest to use.
+ * returns 0 on success, otherwise failure.
+ */
+static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
+                             byte* ikm, int ikmLen, int mac)
+{
+    int ret;
+    int hash = 0;
+    int len = 0;
+
+    switch (mac) {
+        #ifndef NO_SHA256
+        case sha256_mac:
+            hash = WC_SHA256;
+            len = WC_SHA256_DIGEST_SIZE;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hash = WC_SHA384;
+            len = WC_SHA384_DIGEST_SIZE;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hash = WC_SHA512;
+            len = WC_SHA512_DIGEST_SIZE;
+            break;
+        #endif
+    }
+
+    /* When length is 0 then use zeroed data of digest length. */
+    if (ikmLen == 0) {
+        ikmLen = len;
+        XMEMSET(ikm, 0, len);
+    }
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  Salt");
+    WOLFSSL_BUFFER(salt, saltLen);
+    WOLFSSL_MSG("  IKM");
+    WOLFSSL_BUFFER(ikm, ikmLen);
+#endif
+
+    ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  PRK");
+    WOLFSSL_BUFFER(prk, len);
+#endif
+
+    return ret;
+}
+
+/* Expand data using HMAC, salt and label and info.
+ * TLS v1.3 defines this function.
+ *
+ * okm          The generated pseudorandom key - output key material.
+ * okmLen       The length of generated pseudorandom key - output key material.
+ * prk          The salt - pseudo-random key.
+ * prkLen       The length of the salt - pseudo-random key.
+ * protocol     The TLS protocol label.
+ * protocolLen  The length of the TLS protocol label.
+ * info         The information to expand.
+ * infoLen      The length of the information.
+ * digest       The type of digest to use.
+ * returns 0 on success, otherwise failure.
+ */
+static int HKDF_Expand_Label(byte* okm, word32 okmLen,
+                             const byte* prk, word32 prkLen,
+                             const byte* protocol, word32 protocolLen,
+                             const byte* label, word32 labelLen,
+                             const byte* info, word32 infoLen,
+                             int digest)
+{
+    int    ret = 0;
+    int    idx = 0;
+    byte   data[MAX_HKDF_LABEL_SZ];
+
+    /* Output length. */
+    data[idx++] = (byte)(okmLen >> 8);
+    data[idx++] = (byte)okmLen;
+    /* Length of protocol | label. */
+    data[idx++] = (byte)(protocolLen + labelLen);
+    /* Protocol */
+    XMEMCPY(&data[idx], protocol, protocolLen);
+    idx += protocolLen;
+    /* Label */
+    XMEMCPY(&data[idx], label, labelLen);
+    idx += labelLen;
+    /* Length of hash of messages */
+    data[idx++] = (byte)infoLen;
+    /* Hash of messages */
+    XMEMCPY(&data[idx], info, infoLen);
+    idx += infoLen;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  PRK");
+    WOLFSSL_BUFFER(prk, prkLen);
+    WOLFSSL_MSG("  Info");
+    WOLFSSL_BUFFER(data, idx);
+#endif
+
+    ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("  OKM");
+    WOLFSSL_BUFFER(okm, okmLen);
+#endif
+
+    ForceZero(data, idx);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* Size of the TLS v1.3 label use when deriving keys. */
+#define TLS13_PROTOCOL_LABEL_SZ    9
+/* The protocol label for TLS v1.3. */
+static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, ";
+#else
+/* Size of the TLS v1.3 label use when deriving keys. */
+#define TLS13_PROTOCOL_LABEL_SZ    6
+/* The protocol label for TLS v1.3. */
+static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
+#endif
+
+#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \
+                                        !defined(NO_PSK)
+/* Derive a key from a message.
+ *
+ * ssl        The SSL/TLS object.
+ * output     The buffer to hold the derived key.
+ * outputLen  The length of the derived key.
+ * secret     The secret used to derive the key (HMAC secret).
+ * label      The label used to distinguish the context.
+ * labelLen   The length of the label.
+ * msg        The message data to derive key from.
+ * msgLen     The length of the message data to derive key from.
+ * hashAlgo   The hash algorithm to use in the HMAC.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
+                        const byte* secret, const byte* label, word32 labelLen,
+                        byte* msg, int msgLen, int hashAlgo)
+{
+    byte        hash[WC_MAX_DIGEST_SIZE];
+    Digest      digest;
+    word32      hashSz = 0;
+    const byte* protocol;
+    word32      protocolLen;
+    int         digestAlg = -1;
+    int         ret = BAD_FUNC_ARG;
+
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                    ret = wc_Sha256Update(&digest.sha256, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, hash);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            digestAlg = WC_SHA256;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, hash);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            digestAlg = WC_SHA384;
+            break;
+#endif
+#ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, hash);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            digestAlg = WC_SHA512;
+            break;
+#endif
+        default:
+            digestAlg = -1;
+            break;
+    }
+
+    if (digestAlg < 0)
+        return HASH_TYPE_E;
+
+    if (ret != 0)
+        return ret;
+
+    switch (ssl->version.minor) {
+        case TLSv1_3_MINOR:
+            protocol = tls13ProtocolLabel;
+            protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+            break;
+
+        default:
+            return VERSION_ERROR;
+    }
+    if (outputLen == -1)
+        outputLen = hashSz;
+
+    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
+                             protocol, protocolLen, label, labelLen,
+                             hash, hashSz, digestAlg);
+}
+#endif
+
+/* Derive a key.
+ *
+ * ssl          The SSL/TLS object.
+ * output       The buffer to hold the derived key.
+ * outputLen    The length of the derived key.
+ * secret       The secret used to derive the key (HMAC secret).
+ * label        The label used to distinguish the context.
+ * labelLen     The length of the label.
+ * hashAlgo     The hash algorithm to use in the HMAC.
+ * includeMsgs  Whether to include a hash of the handshake messages so far.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
+                     const byte* secret, const byte* label, word32 labelLen,
+                     int hashAlgo, int includeMsgs)
+{
+    int         ret = 0;
+    byte        hash[WC_MAX_DIGEST_SIZE];
+    word32      hashSz = 0;
+    word32      hashOutSz = 0;
+    const byte* protocol;
+    word32      protocolLen;
+    int         digestAlg = 0;
+
+    switch (hashAlgo) {
+        #ifndef NO_SHA256
+            case sha256_mac:
+                hashSz    = WC_SHA256_DIGEST_SIZE;
+                digestAlg = WC_SHA256;
+                if (includeMsgs)
+                    ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+            case sha384_mac:
+                hashSz    = WC_SHA384_DIGEST_SIZE;
+                digestAlg = WC_SHA384;
+                if (includeMsgs)
+                    ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+            case sha512_mac:
+                hashSz    = WC_SHA512_DIGEST_SIZE;
+                digestAlg = WC_SHA512;
+                if (includeMsgs)
+                    ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            break;
+        #endif
+    }
+    if (ret != 0)
+        return ret;
+
+    /* Only one protocol version defined at this time. */
+    protocol = tls13ProtocolLabel;
+    protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+
+    if (outputLen == -1)
+        outputLen = hashSz;
+    if (includeMsgs)
+        hashOutSz = hashSz;
+
+    return HKDF_Expand_Label(output, outputLen, secret, hashSz,
+                             protocol, protocolLen, label, labelLen,
+                             hash, hashOutSz, digestAlg);
+}
+
+
+#ifndef NO_PSK
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the binder key label. */
+#define BINDER_KEY_LABEL_SZ         23
+/* The binder key label. */
+static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
+    "external psk binder key";
+#else
+/* The length of the binder key label. */
+#define BINDER_KEY_LABEL_SZ         10
+/* The binder key label. */
+static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] =
+    "ext binder";
+#endif
+/* Derive the binder key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveBinderKey(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Binder Key");
+    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        binderKeyLabel, BINDER_KEY_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+}
+#endif /* !NO_PSK */
+
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the binder key resume label. */
+#define BINDER_KEY_RESUME_LABEL_SZ  25
+/* The binder key resume label. */
+static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
+    "resumption psk binder key";
+#else
+/* The length of the binder key resume label. */
+#define BINDER_KEY_RESUME_LABEL_SZ  10
+/* The binder key resume label. */
+static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] =
+    "res binder";
+#endif
+/* Derive the binder resumption key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Binder Key - Resumption");
+    return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+}
+#endif /* HAVE_SESSION_TICKET */
+
+#ifdef WOLFSSL_EARLY_DATA
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the early traffic label. */
+#define EARLY_TRAFFIC_LABEL_SZ      27
+/* The early traffic label. */
+static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
+    "client early traffic secret";
+#else
+/* The length of the early traffic label. */
+#define EARLY_TRAFFIC_LABEL_SZ      11
+/* The early traffic label. */
+static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] =
+    "c e traffic";
+#endif
+/* Derive the early traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Early Traffic Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->secret,
+                     earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+
+#ifdef TLS13_SUPPORTS_EXPORTERS
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the early exporter label. */
+#define EARLY_EXPORTER_LABEL_SZ     28
+/* The early exporter label. */
+static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
+    "early exporter master secret";
+#else
+/* The length of the early exporter label. */
+#define EARLY_EXPORTER_LABEL_SZ     12
+/* The early exporter label. */
+static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] =
+    "e exp master";
+#endif
+/* Derive the early exporter key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Early Exporter Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->secret,
+                     earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+#endif
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the client hanshake label. */
+#define CLIENT_HANDSHAKE_LABEL_SZ   31
+/* The client hanshake label. */
+static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
+    "client handshake traffic secret";
+#else
+/* The length of the client hanshake label. */
+#define CLIENT_HANDSHAKE_LABEL_SZ   12
+/* The client hanshake label. */
+static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] =
+    "c hs traffic";
+#endif
+/* Derive the client handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Client Handshake Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
+                     clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the server handshake label. */
+#define SERVER_HANDSHAKE_LABEL_SZ   31
+/* The server handshake label. */
+static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
+    "server handshake traffic secret";
+#else
+/* The length of the server handshake label. */
+#define SERVER_HANDSHAKE_LABEL_SZ   12
+/* The server handshake label. */
+static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] =
+    "s hs traffic";
+#endif
+/* Derive the server handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Server Handshake Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret,
+                     serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the client application traffic label. */
+#define CLIENT_APP_LABEL_SZ         33
+/* The client application traffic label. */
+static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
+    "client application traffic secret";
+#else
+/* The length of the client application traffic label. */
+#define CLIENT_APP_LABEL_SZ         12
+/* The client application traffic label. */
+static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] =
+    "c ap traffic";
+#endif
+/* Derive the client application traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Client Traffic Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                     clientAppLabel, CLIENT_APP_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the server application traffic label. */
+#define SERVER_APP_LABEL_SZ         33
+/* The  server application traffic label. */
+static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
+    "server application traffic secret";
+#else
+/* The length of the server application traffic label. */
+#define SERVER_APP_LABEL_SZ         12
+/* The  server application traffic label. */
+static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] =
+    "s ap traffic";
+#endif
+/* Derive the server application traffic key.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Server Traffic Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                     serverAppLabel, SERVER_APP_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+
+#ifdef TLS13_SUPPORTS_EXPORTERS
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the exporter master secret label. */
+#define EXPORTER_MASTER_LABEL_SZ    22
+/* The exporter master secret label. */
+static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
+    "exporter master secret";
+#else
+/* The length of the exporter master secret label. */
+#define EXPORTER_MASTER_LABEL_SZ    10
+/* The exporter master secret label. */
+static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] =
+    "exp master";
+#endif
+/* Derive the exporter secret.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveExporterSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Exporter Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                     exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+#endif
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the resumption master secret label. */
+#define RESUME_MASTER_LABEL_SZ      24
+/* The resumption master secret label. */
+static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
+    "resumption master secret";
+#else
+/* The length of the resumption master secret label. */
+#define RESUME_MASTER_LABEL_SZ      10
+/* The resumption master secret label. */
+static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
+    "res master";
+#endif
+/* Derive the resumption secret.
+ *
+ * ssl  The SSL/TLS object.
+ * key  The derived key.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
+{
+    WOLFSSL_MSG("Derive Resumption Secret");
+    return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret,
+                     resumeMasterLabel, RESUME_MASTER_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 1);
+}
+#endif
+
+/* Length of the finished label. */
+#define FINISHED_LABEL_SZ           8
+/* Finished label for generating finished key. */
+static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished";
+/* Derive the finished secret.
+ *
+ * ssl     The SSL/TLS object.
+ * key     The key to use with the HMAC.
+ * secret  The derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret)
+{
+    WOLFSSL_MSG("Derive Finished Secret");
+    return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 0);
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* The length of the application traffic label. */
+#define APP_TRAFFIC_LABEL_SZ        26
+/* The application traffic label. */
+static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
+    "application traffic secret";
+#else
+/* The length of the application traffic label. */
+#define APP_TRAFFIC_LABEL_SZ        11
+/* The application traffic label. */
+static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
+    "traffic upd";
+#endif
+/* Update the traffic secret.
+ *
+ * ssl     The SSL/TLS object.
+ * secret  The previous secret and derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret)
+{
+    WOLFSSL_MSG("Derive New Application Traffic Secret");
+    return DeriveKey(ssl, secret, -1, secret,
+                     appTrafficLabel, APP_TRAFFIC_LABEL_SZ,
+                     ssl->specs.mac_algorithm, 0);
+}
+
+/* Derive the early secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveEarlySecret(WOLFSSL* ssl)
+{
+    WOLFSSL_MSG("Derive Early Secret");
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
+            ssl->arrays->psk_key, ssl->arrays->psk_keySz,
+            ssl->specs.mac_algorithm);
+#else
+    return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#endif
+}
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+/* The length of the derived label. */
+#define DERIVED_LABEL_SZ        7
+/* The derived label. */
+static const byte derivedLabel[DERIVED_LABEL_SZ + 1] =
+    "derived";
+#endif
+/* Derive the handshake secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveHandshakeSecret(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    WOLFSSL_MSG("Derive Handshake Secret");
+    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
+            ssl->arrays->secret, ssl->specs.hash_size,
+            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+            ssl->specs.mac_algorithm);
+#else
+    byte key[WC_MAX_DIGEST_SIZE];
+    int ret;
+
+    WOLFSSL_MSG("Derive Handshake Secret");
+
+    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret,
+                        derivedLabel, DERIVED_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+    if (ret != 0)
+        return ret;
+
+    return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
+            key, ssl->specs.hash_size,
+            ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
+            ssl->specs.mac_algorithm);
+#endif
+}
+
+/* Derive the master secret using HKDF Extract.
+ *
+ * ssl  The SSL/TLS object.
+ */
+static int DeriveMasterSecret(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    WOLFSSL_MSG("Derive Master Secret");
+    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
+            ssl->arrays->preMasterSecret, ssl->specs.hash_size,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#else
+    byte key[WC_MAX_DIGEST_SIZE];
+    int ret;
+
+    WOLFSSL_MSG("Derive Master Secret");
+
+    ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret,
+                        derivedLabel, DERIVED_LABEL_SZ,
+                        NULL, 0, ssl->specs.mac_algorithm);
+    if (ret != 0)
+        return ret;
+
+    return Tls13_HKDF_Extract(ssl->arrays->masterSecret,
+            key, ssl->specs.hash_size,
+            ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
+#endif
+}
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+#if defined(HAVE_SESSION_TICKET)
+/* Length of the resumption label. */
+#define RESUMPTION_LABEL_SZ         10
+/* Resumption label for generating PSK assocated with the ticket. */
+static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption";
+/* Derive the PSK assocated with the ticket.
+ *
+ * ssl       The SSL/TLS object.
+ * nonce     The nonce to derive with.
+ * nonceLen  The length of the nonce to derive with.
+ * secret    The derived secret.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen,
+                               byte* secret)
+{
+    int         digestAlg;
+    /* Only one protocol version defined at this time. */
+    const byte* protocol    = tls13ProtocolLabel;
+    word32      protocolLen = TLS13_PROTOCOL_LABEL_SZ;
+
+    WOLFSSL_MSG("Derive Resumption PSK");
+
+    switch (ssl->specs.mac_algorithm) {
+        #ifndef NO_SHA256
+        case sha256_mac:
+            digestAlg = WC_SHA256;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            digestAlg = WC_SHA384;
+            break;
+        #endif
+
+        #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            digestAlg = WC_SHA512;
+            break;
+        #endif
+
+        default:
+            return BAD_FUNC_ARG;
+    }
+
+    return HKDF_Expand_Label(secret, ssl->specs.hash_size,
+                             ssl->session.masterSecret, ssl->specs.hash_size,
+                             protocol, protocolLen, resumptionLabel,
+                             RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);
+}
+#endif /* HAVE_SESSION_TICKET */
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+
+/* Calculate the HMAC of message data to this point.
+ *
+ * ssl   The SSL/TLS object.
+ * key   The HMAC key.
+ * hash  The hash result - verify data.
+ * returns length of verify data generated.
+ */
+static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
+    word32* pHashSz)
+{
+    Hmac verifyHmac;
+    int  hashType = WC_SHA256;
+    int  hashSz = WC_SHA256_DIGEST_SIZE;
+    int  ret = BAD_FUNC_ARG;
+
+    /* Get the hash of the previous handshake messages. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            hashType = WC_SHA256;
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hashType = WC_SHA384;
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hashType = WC_SHA512;
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            break;
+    #endif /* WOLFSSL_TLS13_SHA512 */
+    }
+    if (ret != 0)
+        return ret;
+
+    /* Calculate the verify data. */
+    ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId);
+    if (ret == 0) {
+        ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size);
+        if (ret == 0)
+            ret = wc_HmacUpdate(&verifyHmac, hash, hashSz);
+        if (ret == 0)
+            ret = wc_HmacFinal(&verifyHmac, hash);
+        wc_HmacFree(&verifyHmac);
+    }
+
+    if (pHashSz)
+        *pHashSz = hashSz;
+
+    return ret;
+}
+
+/* The length of the label to use when deriving keys. */
+#define WRITE_KEY_LABEL_SZ     3
+/* The length of the label to use when deriving IVs. */
+#define WRITE_IV_LABEL_SZ      2
+/* The label to use when deriving keys. */
+static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key";
+/* The label to use when deriving IVs. */
+static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1]   = "iv";
+
+/* Derive the keys and IVs for TLS v1.3.
+ *
+ * ssl      The SSL/TLS object.
+ * sercret  early_data_key when deriving the key and IV for encrypting early
+ *          data application data and end_of_early_data messages.
+ *          handshake_key when deriving keys and IVs for encrypting handshake
+ *          messages.
+ *          traffic_key when deriving first keys and IVs for encrypting
+ *          traffic messages.
+ *          update_traffic_key when deriving next keys and IVs for encrypting
+ *          traffic messages.
+ * side     ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived.
+ *          DECRYPT_SIDE_ONLY when only decryption secret needs to be derived.
+ *          ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived.
+ * store    1 indicates to derive the keys and IVs from derived secret and
+ *          store ready for provisioning.
+ * returns 0 on success, otherwise failure.
+ */
+static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
+{
+    int   ret = BAD_FUNC_ARG; /* Assume failure */
+    int   i = 0;
+#ifdef WOLFSSL_SMALL_STACK
+    byte* key_dig;
+#else
+    byte  key_dig[MAX_PRF_DIG];
+#endif
+    int   provision;
+
+#ifdef WOLFSSL_SMALL_STACK
+    key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
+    if (key_dig == NULL)
+        return MEMORY_E;
+#endif
+
+    if (side == ENCRYPT_AND_DECRYPT_SIDE) {
+        provision = PROVISION_CLIENT_SERVER;
+    }
+    else {
+        provision = ((ssl->options.side != WOLFSSL_CLIENT_END) ^
+                     (side == ENCRYPT_SIDE_ONLY)) ? PROVISION_CLIENT :
+                                                    PROVISION_SERVER;
+    }
+
+    /* Derive the appropriate secret to use in the HKDF. */
+    switch (secret) {
+#ifdef WOLFSSL_EARLY_DATA
+        case early_data_key:
+            ret = DeriveEarlyTrafficSecret(ssl, ssl->arrays->clientSecret);
+            if (ret != 0)
+                goto end;
+            break;
+#endif
+
+        case handshake_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveClientHandshakeSecret(ssl,
+                                                  ssl->arrays->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveServerHandshakeSecret(ssl,
+                                                  ssl->arrays->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+
+        case traffic_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveClientTrafficSecret(ssl, ssl->arrays->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveServerTrafficSecret(ssl, ssl->arrays->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+
+        case update_traffic_key:
+            if (provision & PROVISION_CLIENT) {
+                ret = DeriveTrafficSecret(ssl, ssl->arrays->clientSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            if (provision & PROVISION_SERVER) {
+                ret = DeriveTrafficSecret(ssl, ssl->arrays->serverSecret);
+                if (ret != 0)
+                    goto end;
+            }
+            break;
+    }
+
+    if (!store)
+        goto end;
+
+    /* Key data = client key | server key | client IV | server IV */
+
+    if (provision & PROVISION_CLIENT) {
+        /* Derive the client key.  */
+        WOLFSSL_MSG("Derive Client Key");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
+                        ssl->arrays->clientSecret, writeKeyLabel,
+                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.key_size;
+    }
+
+    if (provision & PROVISION_SERVER) {
+        /* Derive the server key.  */
+        WOLFSSL_MSG("Derive Server Key");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
+                        ssl->arrays->serverSecret, writeKeyLabel,
+                        WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.key_size;
+    }
+
+    if (provision & PROVISION_CLIENT) {
+        /* Derive the client IV.  */
+        WOLFSSL_MSG("Derive Client IV");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
+                        ssl->arrays->clientSecret, writeIVLabel,
+                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+        i += ssl->specs.iv_size;
+    }
+
+    if (provision & PROVISION_SERVER) {
+        /* Derive the server IV.  */
+        WOLFSSL_MSG("Derive Server IV");
+        ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
+                        ssl->arrays->serverSecret, writeIVLabel,
+                        WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0);
+        if (ret != 0)
+            goto end;
+    }
+
+    /* Store keys and IVs but don't activate them. */
+    ret = StoreKeys(ssl, key_dig, provision);
+
+end:
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
+#endif
+
+    return ret;
+}
+
+#ifdef HAVE_SESSION_TICKET
+#if defined(USER_TICKS)
+#if 0
+    word32 TimeNowInMilliseconds(void)
+    {
+        /*
+        write your own clock tick function if don't want gettimeofday()
+        needs millisecond accuracy but doesn't have to correlated to EPOCH
+        */
+    }
+#endif
+
+#elif defined(TIME_OVERRIDES)
+    #ifndef HAVE_TIME_T_TYPE
+        typedef long time_t;
+    #endif
+    extern time_t XTIME(time_t * timer);
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) XTIME(0) * 1000;
+    }
+#elif defined(USE_WINDOWS_API)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        static int           init = 0;
+        static LARGE_INTEGER freq;
+        LARGE_INTEGER        count;
+
+        if (!init) {
+            QueryPerformanceFrequency(&freq);
+            init = 1;
+        }
+
+        QueryPerformanceCounter(&count);
+
+        return (word32)(count.QuadPart / (freq.QuadPart / 1000));
+    }
+
+#elif defined(HAVE_RTP_SYS)
+    #include "rtptime.h"
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)rtp_get_system_sec() * 1000;
+    }
+#elif defined(MICRIUM)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        OS_TICK ticks = 0;
+        OS_ERR  err;
+
+        ticks = OSTimeGet(&err);
+
+        return (word32) (ticks / OSCfg_TickRate_Hz) * 1000;
+    }
+#elif defined(MICROCHIP_TCPIP_V5)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) (TickGet() / (TICKS_PER_SECOND / 1000));
+    }
+#elif defined(MICROCHIP_TCPIP)
+    #if defined(MICROCHIP_MPLAB_HARMONY)
+        #include <system/tmr/sys_tmr.h>
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(SYS_TMR_TickCountGet() /
+                        (SYS_TMR_TickCounterFrequencyGet() / 1000));
+    }
+    #else
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000));
+    }
+
+    #endif
+
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        TIME_STRUCT mqxTime;
+
+        _time_get_elapsed(&mqxTime);
+
+        return (word32) mqxTime.SECONDS * 1000;
+    }
+#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
+    #include "include/task.h"
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (unsigned int)(((float)xTaskGetTickCount()) /
+                              (configTICK_RATE_HZ / 1000));
+    }
+#elif defined(FREESCALE_KSDK_BM)
+    #include "lwip/sys.h" /* lwIP */
+
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return sys_now();
+    }
+#elif defined(WOLFSSL_TIRTOS)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32) Seconds_get() * 1000;
+    }
+#elif defined(WOLFSSL_UTASKER)
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000));
+    }
+#else
+    /* The time in milliseconds.
+     * Used for tickets to represent difference between when first seen and when
+     * sending.
+     *
+     * returns the time in milliseconds as a 32-bit value.
+     */
+    word32 TimeNowInMilliseconds(void)
+    {
+        struct timeval now;
+
+        if (gettimeofday(&now, 0) < 0)
+            return GETTIME_ERROR;
+        /* Convert to milliseconds number. */
+        return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000);
+    }
+#endif
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \
+                                    !defined(NO_PSK))
+/* Add input to all handshake hashes.
+ *
+ * ssl    The SSL/TLS object.
+ * input  The data to hash.
+ * sz     The size of the data to hash.
+ * returns 0 on success, otherwise failure.
+ */
+static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz)
+{
+    int ret = BAD_FUNC_ARG;
+
+#ifndef NO_SHA256
+    ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_SHA384
+    ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+#ifdef WOLFSSL_TLS13_SHA512
+    ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz);
+    if (ret != 0)
+        return ret;
+#endif
+
+    return ret;
+}
+#endif
+
+/* Extract the handshake header information.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The buffer holding the message data.
+ * inOutIdx  On entry, the index into the buffer of the handshake data.
+ *           On exit, the start of the hanshake data.
+ * type      Type of handshake message.
+ * size      The length of the handshake message data.
+ * totalSz   The total size of data in the buffer.
+ * returns BUFFER_E if there is not enough input data and 0 on success.
+ */
+static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                              byte* type, word32* size, word32 totalSz)
+{
+    const byte* ptr = input + *inOutIdx;
+    (void)ssl;
+
+    *inOutIdx += HANDSHAKE_HEADER_SZ;
+    if (*inOutIdx > totalSz)
+        return BUFFER_E;
+
+    *type = ptr[0];
+    c24to32(&ptr[1], size);
+
+    return 0;
+}
+
+/* Add record layer header to message.
+ *
+ * output  The buffer to write the record layer header into.
+ * length  The length of the record data.
+ * type    The type of record message.
+ * ssl     The SSL/TLS object.
+ */
+static void AddTls13RecordHeader(byte* output, word32 length, byte type,
+                                 WOLFSSL* ssl)
+{
+    RecordLayerHeader* rl;
+
+    rl = (RecordLayerHeader*)output;
+    rl->type    = type;
+    rl->pvMajor = ssl->version.major;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    rl->pvMinor = TLSv1_MINOR;
+#else
+    rl->pvMinor = TLSv1_2_MINOR;
+#endif
+    c16toa((word16)length, rl->length);
+}
+
+/* Add handshake header to message.
+ *
+ * output      The buffer to write the hanshake header into.
+ * length      The length of the handshake data.
+ * fragOffset  The offset of the fragment data. (DTLS)
+ * fragLength  The length of the fragment data. (DTLS)
+ * type        The type of handshake message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13HandShakeHeader(byte* output, word32 length,
+                                    word32 fragOffset, word32 fragLength,
+                                    byte type, WOLFSSL* ssl)
+{
+    HandShakeHeader* hs;
+    (void)fragOffset;
+    (void)fragLength;
+    (void)ssl;
+
+    /* handshake header */
+    hs = (HandShakeHeader*)output;
+    hs->type = type;
+    c32to24(length, hs->length);
+}
+
+
+/* Add both record layer and handshake header to message.
+ *
+ * output      The buffer to write the headers into.
+ * length      The length of the handshake data.
+ * type        The type of record layer message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13Headers(byte* output, word32 length, byte type,
+                            WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+
+    AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl);
+    AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
+}
+
+
+#ifndef NO_CERTS
+/* Add both record layer and fragement handshake header to message.
+ *
+ * output      The buffer to write the headers into.
+ * fragOffset  The offset of the fragment data. (DTLS)
+ * fragLength  The length of the fragment data. (DTLS)
+ * length      The length of the handshake data.
+ * type        The type of record layer message.
+ * ssl         The SSL/TLS object. (DTLS)
+ */
+static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset,
+                                word32 length, byte type, WOLFSSL* ssl)
+{
+    word32 lengthAdj = HANDSHAKE_HEADER_SZ;
+    word32 outputAdj = RECORD_HEADER_SZ;
+    (void)fragSz;
+
+    AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl);
+    AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz,
+                            type, ssl);
+}
+#endif /* NO_CERTS */
+
+/* Write the sequence number into the buffer.
+ * No DTLS v1.3 support.
+ *
+ * ssl          The SSL/TLS object.
+ * verifyOrder  Which set of sequence numbers to use.
+ * out          The buffer to write into.
+ */
+static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
+{
+    word32 seq[2] = {0, 0};
+
+    if (verifyOrder) {
+        seq[0] = ssl->keys.peer_sequence_number_hi;
+        seq[1] = ssl->keys.peer_sequence_number_lo++;
+        /* handle rollover */
+        if (seq[1] > ssl->keys.peer_sequence_number_lo)
+            ssl->keys.peer_sequence_number_hi++;
+    }
+    else {
+        seq[0] = ssl->keys.sequence_number_hi;
+        seq[1] = ssl->keys.sequence_number_lo++;
+        /* handle rollover */
+        if (seq[1] > ssl->keys.sequence_number_lo)
+            ssl->keys.sequence_number_hi++;
+    }
+
+    c32toa(seq[0], out);
+    c32toa(seq[1], out + OPAQUE32_LEN);
+}
+
+/* Build the nonce for TLS v1.3 encryption and decryption.
+ *
+ * ssl    The SSL/TLS object.
+ * nonce  The nonce data to use when encrypting or decrypting.
+ * iv     The derived IV.
+ * order  The side on which the message is to be or was sent.
+ */
+static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
+                                   int order)
+{
+    int  i;
+
+    /* The nonce is the IV with the sequence XORed into the last bytes. */
+    WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
+    for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++)
+        nonce[i] = iv[i];
+    for (; i < AEAD_NONCE_SZ; i++)
+        nonce[i] ^= iv[i];
+}
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+/* Encrypt with ChaCha20 and create authenication tag with Poly1305.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write encrypted data and authentication tag into.
+ *         May be the same pointer as input.
+ * input   The data to encrypt.
+ * sz      The number of bytes to encrypt.
+ * nonce   The nonce to use with ChaCha20.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tag     The authentication tag buffer.
+ * returns 0 on success, otherwise failure.
+ */
+static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
+                                    const byte* input, word16 sz, byte* nonce,
+                                    const byte* aad, word16 aadSz, byte* tag)
+{
+    int    ret    = 0;
+    byte   poly[CHACHA20_256_KEY_SIZE];
+
+    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
+    XMEMSET(poly, 0, sizeof(poly));
+
+    /* Set the nonce for ChaCha and get Poly1305 key. */
+    ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0);
+    if (ret != 0)
+        return ret;
+    /* Create Poly1305 key using ChaCha20 keystream. */
+    ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly));
+    if (ret != 0)
+        return ret;
+    /* Encrypt the plain text. */
+    ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz);
+    if (ret != 0) {
+        ForceZero(poly, sizeof(poly));
+        return ret;
+    }
+
+    /* Set key for Poly1305. */
+    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+    if (ret != 0)
+        return ret;
+    /* Add authentication code of encrypted data to end. */
+    ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz,
+                          tag, POLY1305_AUTH_SZ);
+
+    return ret;
+}
+#endif
+
+/* Encrypt data for TLS v1.3.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write encrypted data and authentication tag into.
+ *         May be the same pointer as input.
+ * input   The record header and data to encrypt.
+ * sz      The number of bytes to encrypt.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto
+ * returns 0 on success, otherwise failure.
+ */
+static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
+                        word16 sz, const byte* aad, word16 aadSz, int asyncOkay)
+{
+    int    ret    = 0;
+    word16 dataSz = sz - ssl->specs.aead_mac_size;
+    word16 macSz  = ssl->specs.aead_mac_size;
+    word32 nonceSz = 0;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WC_ASYNC_DEV* asyncDev = NULL;
+    word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN;
+#endif
+
+    WOLFSSL_ENTER("EncryptTls13");
+
+    (void)output;
+    (void)input;
+    (void)sz;
+    (void)dataSz;
+    (void)macSz;
+    (void)asyncOkay;
+    (void)nonceSz;
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ssl->error == WC_PENDING_E) {
+        ssl->error = 0; /* clear async */
+    }
+#endif
+
+    switch (ssl->encrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Data to encrypt");
+            WOLFSSL_BUFFER(input, dataSz);
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
+                                        !defined(WOLFSSL_TLS13_DRAFT_23)
+            WOLFSSL_MSG("Additional Authentication Data");
+            WOLFSSL_BUFFER(aad, aadSz);
+#endif
+        #endif
+
+            if (ssl->encrypt.nonce == NULL)
+                ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
+                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+            if (ssl->encrypt.nonce == NULL)
+                return MEMORY_E;
+
+            BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV,
+                            CUR_ORDER);
+
+            /* Advance state and proceed */
+            ssl->encrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            switch (ssl->specs.bulk_cipher_algorithm) {
+            #ifdef BUILD_AESGCM
+                case wolfssl_aes_gcm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    asyncDev = &ssl->encrypt.aes->asyncDev;
+                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESGCM_NONCE_SZ;
+                    ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz,
+                        output + dataSz, macSz, aad, aadSz);
+                    break;
+            #endif
+
+            #ifdef HAVE_AESCCM
+                case wolfssl_aes_ccm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    asyncDev = &ssl->encrypt.aes->asyncDev;
+                    ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESCCM_NONCE_SZ;
+                    ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz,
+                        output + dataSz, macSz, aad, aadSz);
+                    break;
+            #endif
+
+            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+                case wolfssl_chacha:
+                    ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz,
+                        ssl->encrypt.nonce, aad, aadSz, output + dataSz);
+                    break;
+            #endif
+
+                default:
+                    WOLFSSL_MSG("wolfSSL Encrypt programming error");
+                    return ENCRYPT_ERROR;
+            }
+
+            /* Advance state */
+            ssl->encrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* if async is not okay, then block */
+                if (!asyncOkay) {
+                    ret = wc_AsyncWait(ret, asyncDev, event_flags);
+                }
+                else {
+                    /* If pending, then leave and return will resume below */
+                    return wolfSSL_AsyncPush(ssl, asyncDev);
+                }
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+            #ifdef WOLFSSL_DEBUG_TLS
+                WOLFSSL_MSG("Nonce");
+                WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size);
+                WOLFSSL_MSG("Encrypted data");
+                WOLFSSL_BUFFER(output, dataSz);
+                WOLFSSL_MSG("Authentication Tag");
+                WOLFSSL_BUFFER(output + dataSz, macSz);
+            #endif
+
+            ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ);
+
+            break;
+        }
+    }
+
+    /* Reset state */
+    ssl->encrypt.state = CIPHER_STATE_BEGIN;
+
+    return ret;
+}
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+/* Decrypt with ChaCha20 and check authenication tag with Poly1305.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write decrypted data into.
+ *         May be the same pointer as input.
+ * input   The data to decrypt.
+ * sz      The number of bytes to decrypt.
+ * nonce   The nonce to use with ChaCha20.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * tagIn   The authentication tag data from packet.
+ * returns 0 on success, otherwise failure.
+ */
+static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
+                                    const byte* input, word16 sz, byte* nonce,
+                                    const byte* aad, word16 aadSz,
+                                    const byte* tagIn)
+{
+    int ret;
+    byte tag[POLY1305_AUTH_SZ];
+    byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
+
+    /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */
+    XMEMSET(poly, 0, sizeof(poly));
+
+    /* Set nonce and get Poly1305 key. */
+    ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0);
+    if (ret != 0)
+        return ret;
+    /* Use ChaCha20 keystream to get Poly1305 key for tag. */
+    ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly));
+    if (ret != 0)
+        return ret;
+
+    /* Set key for Poly1305. */
+    ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly));
+    ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
+    if (ret != 0)
+        return ret;
+    /* Generate authentication tag for encrypted data. */
+    if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz,
+                                    (byte*)input, sz, tag, sizeof(tag))) != 0) {
+        return ret;
+    }
+
+    /* Check tag sent along with packet. */
+    if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) {
+        WOLFSSL_MSG("MAC did not match");
+        return VERIFY_MAC_ERROR;
+    }
+
+    /* If the tag was good decrypt message. */
+    ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz);
+
+    return ret;
+}
+#endif
+
+/* Decrypt data for TLS v1.3.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer to write decrypted data into.
+ *         May be the same pointer as input.
+ * input   The data to decrypt and authentication tag.
+ * sz      The length of the encrypted data plus authentication tag.
+ * aad     The additional authentication data.
+ * aadSz   The size of the addition authentication data.
+ * returns 0 on success, otherwise failure.
+ */
+int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
+                 const byte* aad, word16 aadSz)
+{
+    int    ret    = 0;
+    word16 dataSz = sz - ssl->specs.aead_mac_size;
+    word16 macSz  = ssl->specs.aead_mac_size;
+    word32 nonceSz = 0;
+
+    WOLFSSL_ENTER("DecryptTls13");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
+    if (ret != WC_NOT_PENDING_E) {
+        /* check for still pending */
+        if (ret == WC_PENDING_E)
+            return ret;
+
+        ssl->error = 0; /* clear async */
+
+        /* let failures through so CIPHER_STATE_END logic is run */
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->decrypt.state = CIPHER_STATE_BEGIN;
+    }
+
+    (void)output;
+    (void)input;
+    (void)sz;
+    (void)dataSz;
+    (void)macSz;
+    (void)nonceSz;
+
+    switch (ssl->decrypt.state) {
+        case CIPHER_STATE_BEGIN:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Data to decrypt");
+            WOLFSSL_BUFFER(input, dataSz);
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
+                                        !defined(WOLFSSL_TLS13_DRAFT_23)
+            WOLFSSL_MSG("Additional Authentication Data");
+            WOLFSSL_BUFFER(aad, aadSz);
+#endif
+            WOLFSSL_MSG("Authentication tag");
+            WOLFSSL_BUFFER(input + dataSz, macSz);
+        #endif
+
+            if (ssl->decrypt.nonce == NULL)
+                ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
+                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
+            if (ssl->decrypt.nonce == NULL)
+                return MEMORY_E;
+
+            BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
+                            PEER_ORDER);
+
+            /* Advance state and proceed */
+            ssl->decrypt.state = CIPHER_STATE_DO;
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_DO:
+        {
+            switch (ssl->specs.bulk_cipher_algorithm) {
+            #ifdef BUILD_AESGCM
+                case wolfssl_aes_gcm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESGCM_NONCE_SZ;
+                    ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz,
+                        input + dataSz, macSz, aad, aadSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                                                   &ssl->decrypt.aes->asyncDev);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #ifdef HAVE_AESCCM
+                case wolfssl_aes_ccm:
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    /* initialize event */
+                    ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
+                        WC_ASYNC_FLAG_CALL_AGAIN);
+                    if (ret != 0)
+                        break;
+                #endif
+
+                    nonceSz = AESCCM_NONCE_SZ;
+                    ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz,
+                        input + dataSz, macSz, aad, aadSz);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (ret == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPush(ssl,
+                                                   &ssl->decrypt.aes->asyncDev);
+                    }
+                #endif
+                    break;
+            #endif
+
+            #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+                case wolfssl_chacha:
+                    ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz,
+                        ssl->decrypt.nonce, aad, aadSz, input + dataSz);
+                    break;
+            #endif
+
+                default:
+                    WOLFSSL_MSG("wolfSSL Decrypt programming error");
+                    return DECRYPT_ERROR;
+            }
+
+            /* Advance state */
+            ssl->decrypt.state = CIPHER_STATE_END;
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            /* If pending, leave now */
+            if (ret == WC_PENDING_E) {
+                return ret;
+            }
+        #endif
+        }
+        FALL_THROUGH;
+
+        case CIPHER_STATE_END:
+        {
+        #ifdef WOLFSSL_DEBUG_TLS
+            WOLFSSL_MSG("Nonce");
+            WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size);
+            WOLFSSL_MSG("Decrypted data");
+            WOLFSSL_BUFFER(output, dataSz);
+        #endif
+
+            ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ);
+
+            break;
+        }
+    }
+
+#ifndef WOLFSSL_EARLY_DATA
+    if (ret < 0) {
+        SendAlert(ssl, alert_fatal, bad_record_mac);
+        ret = VERIFY_MAC_ERROR;
+    }
+#endif
+
+    return ret;
+}
+
+/* Persistable BuildTls13Message arguments */
+typedef struct BuildMsg13Args {
+    word32 sz;
+    word32 idx;
+    word32 headerSz;
+    word16 size;
+} BuildMsg13Args;
+
+static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs)
+{
+    BuildMsg13Args* args = (BuildMsg13Args*)pArgs;
+
+    (void)ssl;
+    (void)args;
+
+    /* no allocations in BuildTls13Message */
+}
+
+/* Build SSL Message, encrypted.
+ * TLS v1.3 encryption is AEAD only.
+ *
+ * ssl         The SSL/TLS object.
+ * output      The buffer to write record message to.
+ * outSz       Size of the buffer being written into.
+ * input       The record data to encrypt (excluding record header).
+ * inSz        The size of the record data.
+ * type        The recorder header content type.
+ * hashOutput  Whether to hash the unencrypted record data.
+ * sizeOnly    Only want the size of the record message.
+ * asyncOkay   If non-zero can return WC_PENDING_E, otherwise blocks on crypto
+ * returns the size of the encrypted record message or negative value on error.
+ */
+int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+                int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
+{
+    int ret = 0;
+    BuildMsg13Args* args;
+    BuildMsg13Args  lcl_args;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    args = (BuildMsg13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#endif
+
+    WOLFSSL_ENTER("BuildTls13Message");
+
+    ret = WC_NOT_PENDING_E;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (asyncOkay) {
+        ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
+        if (ret != WC_NOT_PENDING_E) {
+            /* Check for error */
+            if (ret < 0)
+                goto exit_buildmsg;
+        }
+    }
+    else
+#endif
+    {
+        args = &lcl_args;
+    }
+
+    /* Reset state */
+    if (ret == WC_NOT_PENDING_E) {
+        ret = 0;
+        ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+        XMEMSET(args, 0, sizeof(BuildMsg13Args));
+
+        args->sz = RECORD_HEADER_SZ + inSz;
+        args->idx  = RECORD_HEADER_SZ;
+        args->headerSz = RECORD_HEADER_SZ;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeBuildMsg13Args;
+    #endif
+    }
+
+    switch (ssl->options.buildMsgState) {
+        case BUILD_MSG_BEGIN:
+        {
+           /* catch mistaken sizeOnly parameter */
+            if (sizeOnly) {
+                if (output || input) {
+                    WOLFSSL_MSG("BuildTls13Message with sizeOnly "
+                                "doesn't need input or output");
+                    return BAD_FUNC_ARG;
+                }
+            }
+            else if (output == NULL || input == NULL) {
+                return BAD_FUNC_ARG;
+            }
+
+            /* Record layer content type at the end of record data. */
+            args->sz++;
+            /* Authentication data at the end. */
+            args->sz += ssl->specs.aead_mac_size;
+
+            if (sizeOnly)
+                return args->sz;
+
+            if (args->sz > (word32)outSz) {
+                WOLFSSL_MSG("Oops, want to write past output buffer size");
+                return BUFFER_E;
+            }
+
+            /* Record data length. */
+            args->size = (word16)(args->sz - args->headerSz);
+            /* Write/update the record header with the new size.
+             * Always have the content type as application data for encrypted
+             * messages in TLS v1.3.
+             */
+            AddTls13RecordHeader(output, args->size, application_data, ssl);
+
+            /* TLS v1.3 can do in place encryption. */
+            if (input != output + args->idx)
+                XMEMCPY(output + args->idx, input, inSz);
+            args->idx += inSz;
+
+            ssl->options.buildMsgState = BUILD_MSG_HASH;
+        }
+        FALL_THROUGH;
+
+        case BUILD_MSG_HASH:
+        {
+            if (hashOutput) {
+                ret = HashOutput(ssl, output, args->headerSz + inSz, 0);
+                if (ret != 0)
+                    goto exit_buildmsg;
+            }
+
+            ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
+        }
+        FALL_THROUGH;
+
+        case BUILD_MSG_ENCRYPT:
+        {
+            /* The real record content type goes at the end of the data. */
+            output[args->idx++] = (byte)type;
+
+        #ifdef ATOMIC_USER
+            if (ssl->ctx->MacEncryptCb) {
+                /* User Record Layer Callback handling */
+                byte* mac = output + args->idx;
+                output += args->headerSz;
+
+                ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0,
+                        output, output, args->size, ssl->MacEncryptCtx);
+            }
+            else
+        #endif
+            {
+#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \
+                                       defined(WOLFSSL_TLS13_DRAFT_23)
+                output += args->headerSz;
+                ret = EncryptTls13(ssl, output, output, args->size, NULL, 0,
+                                                                     asyncOkay);
+#else
+                const byte* aad = output;
+                output += args->headerSz;
+                ret = EncryptTls13(ssl, output, output, args->size, aad,
+                                   RECORD_HEADER_SZ, asyncOkay);
+#endif
+            }
+            break;
+        }
+    }
+
+exit_buildmsg:
+
+    WOLFSSL_LEAVE("BuildTls13Message", ret);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif
+
+    /* make sure build message state is reset */
+    ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+
+    /* return sz on success */
+    if (ret == 0)
+        ret = args->sz;
+
+    /* Final cleanup */
+    FreeBuildMsg13Args(ssl, args);
+
+    return ret;
+}
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Find the cipher suite in the suites set in the SSL.
+ *
+ * ssl    SSL/TLS object.
+ * suite  Cipher suite to look for.
+ * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise.
+ */
+static int FindSuite(WOLFSSL* ssl, byte* suite)
+{
+    int i;
+
+    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+        if (ssl->suites->suites[i+0] == suite[0] &&
+            ssl->suites->suites[i+1] == suite[1]) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+/* Create Cookie extension using the hash of the first ClientHello.
+ *
+ * ssl     SSL/TLS object.
+ * hash    The hash data.
+ * hashSz  The size of the hash data in bytes.
+ * returns 0 on success, otherwise failure.
+ */
+static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
+{
+    int  ret;
+    byte mac[WC_MAX_DIGEST_SIZE];
+    Hmac cookieHmac;
+    byte cookieType;
+    byte macSz;
+
+#if !defined(NO_SHA) && defined(NO_SHA256)
+    cookieType = SHA;
+    macSz = WC_SHA_DIGEST_SIZE;
+#endif /* NO_SHA */
+#ifndef NO_SHA256
+    cookieType = WC_SHA256;
+    macSz = WC_SHA256_DIGEST_SIZE;
+#endif /* NO_SHA256 */
+
+    ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                        ssl->buffers.tls13CookieSecret.buffer,
+                        ssl->buffers.tls13CookieSecret.length);
+    if (ret != 0)
+        return ret;
+    if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0)
+        return ret;
+    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
+        return ret;
+
+    /* The cookie data is the hash and the integrity check. */
+    return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1);
+}
+#endif
+
+/* Restart the Hanshake hash with a hash of the previous messages.
+ *
+ * ssl The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int RestartHandshakeHash(WOLFSSL* ssl)
+{
+    int    ret;
+    Hashes hashes;
+    byte   header[HANDSHAKE_HEADER_SZ];
+    byte*  hash = NULL;
+    byte   hashSz = 0;
+
+    ret = BuildCertHashes(ssl, &hashes);
+    if (ret != 0)
+        return ret;
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            hash = hashes.sha256;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            hash = hashes.sha384;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            hash = hashes.sha512;
+            break;
+    #endif
+    }
+    hashSz = ssl->specs.hash_size;
+    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
+
+    WOLFSSL_MSG("Restart Hash");
+    WOLFSSL_BUFFER(hash, hashSz);
+
+#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
+    if (ssl->options.sendCookie) {
+        byte   cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
+        TLSX*  ext;
+        word32 idx = 0;
+
+        /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */
+        cookie[idx++] = hashSz;
+        XMEMCPY(cookie + idx, hash, hashSz);
+        idx += hashSz;
+        cookie[idx++] = ssl->options.cipherSuite0;
+        cookie[idx++] = ssl->options.cipherSuite;
+        if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) {
+            KeyShareEntry* kse = (KeyShareEntry*)ext->data;
+            c16toa(kse->group, cookie + idx);
+            idx += OPAQUE16_LEN;
+        }
+        return CreateCookie(ssl, cookie, idx);
+    }
+#endif
+
+    ret = InitHandshakeHashes(ssl);
+    if (ret != 0)
+        return ret;
+    ret = HashOutputRaw(ssl, header, sizeof(header));
+    if (ret != 0)
+        return ret;
+    return HashOutputRaw(ssl, hash, hashSz);
+}
+
+/* The value in the random field of a ServerHello to indicate
+ * HelloRetryRequest.
+ */
+static byte helloRetryRequestRandom[] = {
+    0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
+    0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
+    0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
+    0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
+};
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+#ifndef NO_WOLFSSL_CLIENT
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Setup pre-shared key based on the details in the extension data.
+ *
+ * ssl  SSL/TLS object.
+ * psk  Pre-shared key extension data.
+ * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and
+ * other negative value on failure.
+ */
+static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk)
+{
+    int ret;
+    byte suite[2];
+
+    if (ssl->options.noPskDheKe && ssl->arrays->preMasterSz != 0)
+        return PSK_KEY_ERROR;
+
+    suite[0] = psk->cipherSuite0;
+    suite[1] = psk->cipherSuite;
+    if (!FindSuite(ssl, suite))
+        return PSK_KEY_ERROR;
+
+    ssl->options.cipherSuite0 = psk->cipherSuite0;
+    ssl->options.cipherSuite  = psk->cipherSuite;
+    if ((ret = SetCipherSpecs(ssl)) != 0)
+        return ret;
+
+#ifdef HAVE_SESSION_TICKET
+    if (psk->resumption) {
+    #ifdef WOLFSSL_EARLY_DATA
+        if (ssl->session.maxEarlyDataSz == 0)
+            ssl->earlyData = no_early_data;
+    #endif
+        /* Resumption PSK is master secret. */
+        ssl->arrays->psk_keySz = ssl->specs.hash_size;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+        XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
+                ssl->arrays->psk_keySz);
+#else
+        if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
+                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
+            return ret;
+        }
+#endif
+    }
+#endif
+#ifndef NO_PSK
+    if (!psk->resumption) {
+        /* Get the pre-shared key. */
+        ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
+                (char *)psk->identity, ssl->arrays->client_identity,
+                MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+        if (ssl->arrays->psk_keySz == 0 ||
+                                 ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+            return PSK_KEY_ERROR;
+        }
+        /* TODO: Callback should be able to specify ciphersuite. */
+
+        if (psk->cipherSuite0 != TLS13_BYTE ||
+            psk->cipherSuite  != WOLFSSL_DEF_PSK_CIPHER) {
+            return PSK_KEY_ERROR;
+        }
+    }
+#endif
+
+    /* Derive the early secret using the PSK. */
+    return DeriveEarlySecret(ssl);
+}
+
+/* Derive and write the binders into the ClientHello in space left when
+ * writing the Pre-Shared Key extension.
+ *
+ * ssl     The SSL/TLS object.
+ * output  The buffer containing the ClientHello.
+ * idx     The index at the end of the completed ClientHello.
+ * returns 0 on success and otherwise failure.
+ */
+static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx)
+{
+    int           ret;
+    TLSX*         ext;
+    PreSharedKey* current;
+    byte          binderKey[WC_MAX_DIGEST_SIZE];
+    word16        len;
+
+    WOLFSSL_ENTER("WritePSKBinders");
+
+    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+    if (ext == NULL)
+        return SANITY_MSG_E;
+
+    /* Get the size of the binders to determine where to write binders. */
+    idx -= TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
+                                            client_hello);
+
+    /* Hash truncated ClientHello - up to binders. */
+    ret = HashOutput(ssl, output, idx, 0);
+    if (ret != 0)
+        return ret;
+
+    current = (PreSharedKey*)ext->data;
+    /* Calculate the binder for each identity based on previous handshake data.
+     */
+    while (current != NULL) {
+        if ((ret = SetupPskKey(ssl, current)) != 0)
+            return ret;
+
+    #ifdef HAVE_SESSION_TICKET
+        if (current->resumption)
+            ret = DeriveBinderKeyResume(ssl, binderKey);
+    #endif
+    #ifndef NO_PSK
+        if (!current->resumption)
+            ret = DeriveBinderKey(ssl, binderKey);
+    #endif
+        if (ret != 0)
+            return ret;
+
+        /* Derive the Finished message secret. */
+        ret = DeriveFinishedSecret(ssl, binderKey,
+                                             ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        /* Build the HMAC of the handshake message data = binder. */
+        ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret,
+            current->binder, &current->binderLen);
+        if (ret != 0)
+            return ret;
+
+        current = current->next;
+    }
+
+    /* Data entered into extension, now write to message. */
+    len = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx,
+                                         client_hello);
+
+    /* Hash binders to complete the hash of the ClientHello. */
+    ret = HashOutputRaw(ssl, output + idx, len);
+    if (ret < 0)
+        return ret;
+
+    #ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0)
+            return ret;
+
+        /* Derive early data encryption key. */
+        ret = DeriveTls13Keys(ssl, early_data_key, ENCRYPT_SIDE_ONLY, 1);
+        if (ret != 0)
+            return ret;
+        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+    #endif
+
+    WOLFSSL_LEAVE("WritePSKBinders", ret);
+
+    return ret;
+}
+#endif
+
+/* handle generation of TLS 1.3 client_hello (1) */
+/* Send a ClientHello message to the server.
+ * Include the information required to start a handshake with servers using
+ * protocol versions less than TLS v1.3.
+ * Only a client will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+int SendTls13ClientHello(WOLFSSL* ssl)
+{
+    byte*  output;
+    word16 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+    int    ret;
+
+    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
+    WOLFSSL_ENTER("SendTls13ClientHello");
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.resuming &&
+            (ssl->session.version.major != ssl->version.major ||
+             ssl->session.version.minor != ssl->version.minor)) {
+    #ifndef WOLFSSL_NO_TLS12
+        if (ssl->session.version.major == ssl->version.major &&
+            ssl->session.version.minor < ssl->version.minor) {
+            /* Cannot resume with a different protocol version. */
+            ssl->options.resuming = 0;
+            ssl->version.major = ssl->session.version.major;
+            ssl->version.minor = ssl->session.version.minor;
+            return SendClientHello(ssl);
+        }
+        else
+    #endif
+            return VERSION_ERROR;
+    }
+#endif
+
+    if (ssl->suites == NULL) {
+        WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello");
+        return SUITES_ERROR;
+    }
+
+    /* Version | Random | Session Id | Cipher Suites | Compression */
+    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz +
+             SUITE_LEN + COMP_LEN + ENUM_LEN;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+    length += ID_LEN;
+    #else
+    if (ssl->session.sessionIDSz > 0)
+        length += ssl->session.sessionIDSz;
+    #endif
+#endif
+
+    /* Auto populate extensions supported unless user defined. */
+    if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0)
+        return ret;
+#ifdef WOLFSSL_EARLY_DATA
+    #ifndef NO_PSK
+        if (!ssl->options.resuming && ssl->options.client_psk_cb == NULL)
+    #else
+        if (!ssl->options.resuming)
+    #endif
+            ssl->earlyData = no_early_data;
+    if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
+        ssl->earlyData = no_early_data;
+    if (ssl->earlyData == no_early_data)
+        TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap);
+    if (ssl->earlyData != no_early_data &&
+                                       (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) {
+        return ret;
+    }
+#endif
+#ifdef HAVE_QSH
+    if (QSH_Init(ssl) != 0)
+        return MEMORY_E;
+#endif
+    /* Include length of TLS extensions. */
+    ret = TLSX_GetRequestSize(ssl, client_hello, &length);
+    if (ret != 0)
+        return ret;
+
+    /* Total message size. */
+    sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, client_hello, ssl);
+
+    /* Protocol version - negotiation now in extension: supported_versions. */
+    output[idx++] = SSLv3_MAJOR;
+    output[idx++] = TLSv1_2_MINOR;
+    /* Keep for downgrade. */
+    ssl->chVersion = ssl->version;
+
+    /* Client Random */
+    if (ssl->options.connectState == CONNECT_BEGIN) {
+        ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN);
+        if (ret != 0)
+            return ret;
+
+        /* Store random for possible second ClientHello. */
+        XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN);
+    }
+    else
+        XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN);
+    idx += RAN_LEN;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* TLS v1.3 does not use session id - 0 length. */
+    output[idx++] = 0;
+#else
+    if (ssl->session.sessionIDSz > 0) {
+        /* Session resumption for old versions of protocol. */
+        output[idx++] = ID_LEN;
+        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        idx += ID_LEN;
+    }
+    else {
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+        output[idx++] = ID_LEN;
+        XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN);
+        idx += ID_LEN;
+    #else
+        /* TLS v1.3 does not use session id - 0 length. */
+        output[idx++] = 0;
+    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
+    }
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+    /* Cipher suites */
+    c16toa(ssl->suites->suiteSz, output + idx);
+    idx += OPAQUE16_LEN;
+    XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz);
+    idx += ssl->suites->suiteSz;
+
+    /* Compression not supported in TLS v1.3. */
+    output[idx++] = COMP_LEN;
+    output[idx++] = NO_COMPRESSION;
+
+    /* Write out extensions for a request. */
+    length = 0;
+    ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length);
+    if (ret != 0)
+        return ret;
+    idx += length;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    /* Resumption has a specific set of extensions and binder is calculated
+     * for each identity.
+     */
+    if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY))
+        ret = WritePSKBinders(ssl, output, idx);
+    else
+#endif
+        ret = HashOutput(ssl, output, idx, 0);
+    if (ret != 0)
+        return ret;
+
+    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+#endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13ClientHello", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* handle rocessing of TLS 1.3 hello_retry_request (6) */
+/* Parse and handle a HelloRetryRequest message.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           HelloRetryRequest.
+ *           On exit, the index of byte after the HelloRetryRequest message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input,
+                                    word32* inOutIdx, word32 totalSz)
+{
+    int             ret;
+    word32          begin = *inOutIdx;
+    word32          i = begin;
+    word16          totalExtSz;
+    ProtocolVersion pv;
+
+    WOLFSSL_ENTER("DoTls13HelloRetryRequest");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "HelloRetryRequest");
+    if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo);
+#endif
+
+    /* Version info and length field of extension data. */
+    if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+
+    /* Protocol version. */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    i += OPAQUE16_LEN;
+    ret = CheckVersion(ssl, pv);
+    if (ret != 0)
+        return ret;
+
+    /* Length of extension data. */
+    ato16(&input[i], &totalExtSz);
+    i += OPAQUE16_LEN;
+    if (totalExtSz == 0) {
+        WOLFSSL_MSG("HelloRetryRequest must contain extensions");
+        return MISSING_HANDSHAKE_DATA;
+    }
+
+    /* Extension data. */
+    if (i - begin + totalExtSz > totalSz)
+        return BUFFER_ERROR;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
+                          hello_retry_request, NULL)) != 0)
+        return ret;
+    /* The KeyShare extension parsing fails when not valid. */
+
+    /* Move index to byte after message. */
+    *inOutIdx = i + totalExtSz;
+
+    ssl->options.tls1_3 = 1;
+    ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+
+    WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret);
+
+    return ret;
+}
+#endif
+
+
+/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
+/* Handle the ServerHello message from the server.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of ServerHello.
+ *           On exit, the index of byte after the ServerHello message.
+ * helloSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                       word32 helloSz, byte* extMsgType)
+{
+    ProtocolVersion pv;
+    word32          i = *inOutIdx;
+    word32          begin = i;
+    int             ret;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    byte            sessIdSz;
+    const byte*     sessId;
+    byte            b;
+#endif
+    word16          totalExtSz;
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX*           ext;
+    PreSharedKey*   psk = NULL;
+#endif
+
+    WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO);
+    WOLFSSL_ENTER("DoTls13ServerHello");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello");
+    if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+
+    /* Protocol version length check. */
+    if (OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    /* Protocol version */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    i += OPAQUE16_LEN;
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ret = CheckVersion(ssl, pv);
+    if (ret != 0)
+        return ret;
+    if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) {
+#ifndef WOLFSSL_NO_TLS12
+        if (ssl->options.downgrade) {
+            ssl->version = pv;
+            return DoServerHello(ssl, input, inOutIdx, helloSz);
+        }
+#endif
+
+        WOLFSSL_MSG("Client using higher version, fatal error");
+        return VERSION_ERROR;
+    }
+#else
+#ifndef WOLFSSL_NO_TLS12
+    if (pv.major == ssl->version.major  && pv.minor < TLSv1_2_MINOR &&
+                                                       ssl->options.downgrade) {
+        /* Force client hello version 1.2 to work for static RSA. */
+        ssl->chVersion.minor = TLSv1_2_MINOR;
+        ssl->version.minor = TLSv1_2_MINOR;
+        return DoServerHello(ssl, input, inOutIdx, helloSz);
+    }
+#endif
+    if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR)
+        return VERSION_ERROR;
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Random length check */
+    if ((i - begin) + RAN_LEN > helloSz)
+        return BUFFER_ERROR;
+#else
+    /* Random and session id length check */
+    if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0)
+        *extMsgType = hello_retry_request;
+#endif
+
+    /* Server random - keep for debugging. */
+    XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
+    i += RAN_LEN;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Session id */
+    sessIdSz = input[i++];
+    if ((i - begin) + sessIdSz > helloSz)
+        return BUFFER_ERROR;
+    sessId = input + i;
+    i += sessIdSz;
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+    ssl->options.haveSessionId = 1;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Ciphersuite check */
+    if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+#else
+    /* Ciphersuite and compression check */
+    if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+#endif
+
+    /* Set the cipher suite from the message. */
+    ssl->options.cipherSuite0 = input[i++];
+    ssl->options.cipherSuite  = input[i++];
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Compression */
+    b = input[i++];
+    if (b != 0) {
+        WOLFSSL_MSG("Must be no compression types in list");
+        return INVALID_PARAMETER;
+    }
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if ((i - begin) + OPAQUE16_LEN > helloSz) {
+        if (!ssl->options.downgrade)
+            return BUFFER_ERROR;
+#ifndef WOLFSSL_NO_TLS12
+        ssl->version.minor = TLSv1_2_MINOR;
+#endif
+        ssl->options.haveEMS = 0;
+    }
+    if ((i - begin) < helloSz)
+#endif
+    {
+        /* Get extension length and length check. */
+        if ((i - begin) + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+        ato16(&input[i], &totalExtSz);
+        i += OPAQUE16_LEN;
+        if ((i - begin) + totalExtSz > helloSz)
+            return BUFFER_ERROR;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+        if (ssl->options.downgrade)
+            ssl->version.minor = TLSv1_2_MINOR;
+#endif
+        /* Parse and handle extensions. */
+        ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType,
+                                                                          NULL);
+        if (ret != 0)
+            return ret;
+
+        i += totalExtSz;
+    }
+    *inOutIdx = i;
+
+    ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+#ifdef HAVE_SECRET_CALLBACK
+    if (ssl->sessionSecretCb != NULL) {
+        int secretSz = SECRET_LEN;
+        ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret,
+                                   &secretSz, ssl->sessionSecretCtx);
+        if (ret != 0 || secretSz != SECRET_LEN)
+            return SESSION_SECRET_CB_E;
+    }
+#endif /* HAVE_SECRET_CALLBACK */
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Version only negotiated in extensions for TLS v1.3.
+     * Only now do we know how to deal with session id.
+     */
+    if (!IsAtLeastTLSv1_3(ssl->version)) {
+#ifndef WOLFSSL_NO_TLS12
+        ssl->arrays->sessionIDSz = sessIdSz;
+
+        if (ssl->arrays->sessionIDSz > ID_LEN) {
+            WOLFSSL_MSG("Invalid session ID size");
+            ssl->arrays->sessionIDSz = 0;
+            return BUFFER_ERROR;
+        }
+        else if (ssl->arrays->sessionIDSz) {
+            XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz);
+            ssl->options.haveSessionId = 1;
+        }
+
+        /* Force client hello version 1.2 to work for static RSA. */
+        ssl->chVersion.minor = TLSv1_2_MINOR;
+        /* Complete TLS v1.2 processing of ServerHello. */
+        ret = CompleteServerHello(ssl);
+#else
+        WOLFSSL_MSG("Client using higher version, fatal error");
+        ret = VERSION_ERROR;
+#endif
+
+        WOLFSSL_LEAVE("DoTls13ServerHello", ret);
+
+        return ret;
+    }
+
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+    if (sessIdSz == 0)
+        return INVALID_PARAMETER;
+    if (ssl->session.sessionIDSz != 0) {
+        if (ssl->session.sessionIDSz != sessIdSz ||
+                   XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) {
+            return INVALID_PARAMETER;
+        }
+    }
+    else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0)
+        return INVALID_PARAMETER;
+    #else
+    if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 &&
+                  XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) {
+        WOLFSSL_MSG("Server sent different session id");
+        return INVALID_PARAMETER;
+    }
+    #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */
+#endif
+
+    ret = SetCipherSpecs(ssl);
+    if (ret != 0)
+        return ret;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if (*extMsgType == server_hello)
+#endif
+    {
+        ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+        if (ext != NULL)
+            psk = (PreSharedKey*)ext->data;
+        while (psk != NULL && !psk->chosen)
+            psk = psk->next;
+        if (psk == NULL) {
+            ssl->options.resuming = 0;
+            ssl->arrays->psk_keySz = 0;
+            XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN);
+        }
+        else if ((ret = SetupPskKey(ssl, psk)) != 0)
+            return ret;
+    }
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ssl->keys.encryptionOn = 1;
+#else
+    if (*extMsgType == server_hello) {
+        ssl->keys.encryptionOn = 1;
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+    }
+    else {
+        ssl->options.tls1_3 = 1;
+        ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+
+        ret = RestartHandshakeHash(ssl);
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13ServerHello", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO);
+
+    return ret;
+}
+
+/* handle processing TLS 1.3 encrypted_extensions (8) */
+/* Parse and handle an EncryptedExtensions message.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           EncryptedExtensions.
+ *           On exit, the index of byte after the EncryptedExtensions
+ *           message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input,
+                                      word32* inOutIdx, word32 totalSz)
+{
+    int    ret;
+    word32 begin = *inOutIdx;
+    word32 i = begin;
+    word16 totalExtSz;
+
+    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
+    WOLFSSL_ENTER("DoTls13EncryptedExtensions");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "EncryptedExtensions");
+    if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo);
+#endif
+
+    /* Length field of extension data. */
+    if (totalSz < i - begin + OPAQUE16_LEN)
+        return BUFFER_ERROR;
+    ato16(&input[i], &totalExtSz);
+    i += OPAQUE16_LEN;
+
+    /* Extension data. */
+    if (i - begin + totalExtSz > totalSz)
+        return BUFFER_ERROR;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz,
+                          encrypted_extensions, NULL)))
+        return ret;
+
+    /* Move index to byte after message. */
+    *inOutIdx = i + totalExtSz;
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+        if (ext == NULL || !ext->val)
+            ssl->earlyData = no_early_data;
+    }
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData == no_early_data) {
+        ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY);
+        if (ret != 0)
+            return ret;
+    }
+#endif
+
+    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
+
+    WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret);
+    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 certificate_request (13) */
+/* Handle a TLS v1.3 CertificateRequest message.
+ * This message is always encrypted.
+ * Only a client will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of CertificateRequest.
+ *           On exit, the index of byte after the CertificateRequest message.
+ * size      The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 size)
+{
+    word16      len;
+    word32      begin = *inOutIdx;
+    int         ret = 0;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    Suites      peerSuites;
+#endif
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    CertReqCtx* certReqCtx;
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO);
+    WOLFSSL_ENTER("DoTls13CertificateRequest");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest");
+    if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo);
+#endif
+
+    if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
+        return BUFFER_ERROR;
+
+    /* Length of the request context. */
+    len = input[(*inOutIdx)++];
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    if (ssl->options.connectState < FINISHED_DONE && len > 0)
+        return BUFFER_ERROR;
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    /* CertReqCtx has one byte at end for context value.
+     * Increase size to handle other implementations sending more than one byte.
+     * That is, allocate extra space, over one byte, to hold the context value.
+     */
+    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (certReqCtx == NULL)
+        return MEMORY_E;
+    certReqCtx->next = ssl->certReqCtx;
+    certReqCtx->len = len;
+    XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
+    ssl->certReqCtx = certReqCtx;
+#endif
+    *inOutIdx += len;
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Signature and hash algorithms. */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    PickHashSigAlgo(ssl, input + *inOutIdx, len);
+    *inOutIdx += len;
+
+    /* Length of certificate authority data. */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+
+    /* Certificate authorities. */
+    while (len) {
+        word16 dnSz;
+
+        if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+            return BUFFER_ERROR;
+
+        ato16(input + *inOutIdx, &dnSz);
+        *inOutIdx += OPAQUE16_LEN;
+
+        if ((*inOutIdx - begin) + dnSz > size)
+            return BUFFER_ERROR;
+
+        *inOutIdx += dnSz;
+        len -= OPAQUE16_LEN + dnSz;
+    }
+
+    /* Certificate extensions */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    *inOutIdx += len;
+#else
+    /* TODO: Add support for more extensions:
+     *   signed_certificate_timestamp, certificate_authorities, oid_filters.
+     */
+    /* Certificate extensions */
+    if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &len);
+    *inOutIdx += OPAQUE16_LEN;
+    if ((*inOutIdx - begin) + len > size)
+        return BUFFER_ERROR;
+    if (len == 0)
+        return INVALID_PARAMETER;
+    if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len,
+                                           certificate_request, &peerSuites))) {
+        return ret;
+    }
+    *inOutIdx += len;
+
+    PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz);
+#endif
+
+    if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
+        ssl->buffers.key && ssl->buffers.key->buffer)
+        ssl->options.sendVerify = SEND_CERT;
+    else
+        ssl->options.sendVerify = SEND_BLANK_CERT;
+
+    /* This message is always encrypted so add encryption padding. */
+    *inOutIdx += ssl->keys.padSz;
+
+    WOLFSSL_LEAVE("DoTls13CertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
+
+    return ret;
+}
+
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+/* Refine list of supported cipher suites to those common to server and client.
+ *
+ * ssl         SSL/TLS object.
+ * peerSuites  The peer's advertised list of supported cipher suites.
+ */
+static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites)
+{
+    byte suites[WOLFSSL_MAX_SUITE_SZ];
+    int suiteSz = 0;
+    int i, j;
+
+    for (i = 0; i < ssl->suites->suiteSz; i += 2) {
+        for (j = 0; j < peerSuites->suiteSz; j += 2) {
+            if (ssl->suites->suites[i+0] == peerSuites->suites[j+0] &&
+                ssl->suites->suites[i+1] == peerSuites->suites[j+1]) {
+                suites[suiteSz++] = peerSuites->suites[j+0];
+                suites[suiteSz++] = peerSuites->suites[j+1];
+            }
+        }
+    }
+
+    ssl->suites->suiteSz = suiteSz;
+    XMEMCPY(ssl->suites->suites, &suites, sizeof(suites));
+}
+
+/* Handle any Pre-Shared Key (PSK) extension.
+ * Must do this in ClientHello as it requires a hash of the truncated message.
+ * Don't know size of binders until Pre-Shared Key extension has been parsed.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The ClientHello message.
+ * helloSz   The size of the ClientHello message (including binders if present).
+ * usingPSK  Indicates handshake is using Pre-Shared Keys.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
+                           int* usingPSK)
+{
+    int           ret;
+    TLSX*         ext;
+    word16        bindersLen;
+    PreSharedKey* current;
+    byte          binderKey[WC_MAX_DIGEST_SIZE];
+    byte          binder[WC_MAX_DIGEST_SIZE];
+    word32        binderLen;
+    word16        modes;
+    byte          suite[2];
+#ifdef WOLFSSL_EARLY_DATA
+    int           pskCnt = 0;
+    TLSX*         extEarlyData;
+#endif
+
+    WOLFSSL_ENTER("DoPreSharedKeys");
+
+    ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
+    if (ext == NULL) {
+#ifdef WOLFSSL_EARLY_DATA
+        ssl->earlyData = no_early_data;
+#endif
+        return 0;
+    }
+
+    /* Extensions pushed on stack/list and PSK must be last. */
+    if (ssl->extensions != ext)
+        return PSK_KEY_ERROR;
+
+    /* Assume we are going to resume with a pre-shared key. */
+    ssl->options.resuming = 1;
+
+    /* Find the pre-shared key extension and calculate hash of truncated
+     * ClientHello for binders.
+     */
+    bindersLen = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data,
+                                                  client_hello);
+
+    /* Hash data up to binders for deriving binders in PSK extension. */
+    ret = HashInput(ssl, input,  helloSz - bindersLen);
+    if (ret != 0)
+        return ret;
+
+    /* Look through all client's pre-shared keys for a match. */
+    current = (PreSharedKey*)ext->data;
+    while (current != NULL) {
+    #ifdef WOLFSSL_EARLY_DATA
+        pskCnt++;
+    #endif
+
+    #ifndef NO_PSK
+        XMEMCPY(ssl->arrays->client_identity, current->identity,
+                current->identityLen);
+        ssl->arrays->client_identity[current->identityLen] = '\0';
+    #endif
+
+    #ifdef HAVE_SESSION_TICKET
+        /* Decode the identity. */
+        if ((ret = DoClientTicket(ssl, current->identity, current->identityLen))
+                                                     == WOLFSSL_TICKET_RET_OK) {
+            word32 now;
+            int    diff;
+
+            now = TimeNowInMilliseconds();
+            if (now == (word32)GETTIME_ERROR)
+                return now;
+            diff = now - ssl->session.ticketSeen;
+            diff -= current->ticketAge - ssl->session.ticketAdd;
+            /* Check session and ticket age timeout.
+             * Allow +/- 1000 milliseconds on ticket age.
+             */
+            if (diff > (int)ssl->timeout * 1000 || diff < -1000 ||
+                                     diff - MAX_TICKET_AGE_SECS * 1000 > 1000) {
+                /* Invalid difference, fallback to full handshake. */
+                ssl->options.resuming = 0;
+                break;
+            }
+
+            /* Check whether resumption is possible based on suites in SSL and
+             * ciphersuite in ticket.
+             */
+            suite[0] = ssl->session.cipherSuite0;
+            suite[1] = ssl->session.cipherSuite;
+            if (!FindSuite(ssl, suite)) {
+                current = current->next;
+                continue;
+            }
+
+        #ifdef WOLFSSL_EARLY_DATA
+            ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz;
+        #endif
+            /* Use the same cipher suite as before and set up for use. */
+            ssl->options.cipherSuite0   = ssl->session.cipherSuite0;
+            ssl->options.cipherSuite    = ssl->session.cipherSuite;
+            ret = SetCipherSpecs(ssl);
+            if (ret != 0)
+                return ret;
+
+            /* Resumption PSK is resumption master secret. */
+            ssl->arrays->psk_keySz = ssl->specs.hash_size;
+        #ifdef WOLFSSL_TLS13_DRAFT_18
+            XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret,
+                    ssl->arrays->psk_keySz);
+        #else
+            if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data,
+                    ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) {
+                return ret;
+            }
+        #endif
+
+            /* Derive the early secret using the PSK. */
+            ret = DeriveEarlySecret(ssl);
+            if (ret != 0)
+                return ret;
+            /* Derive the binder key to use to with HMAC. */
+            ret = DeriveBinderKeyResume(ssl, binderKey);
+            if (ret != 0)
+                return ret;
+        }
+        else
+    #endif
+    #ifndef NO_PSK
+        if (ssl->options.server_psk_cb != NULL &&
+            (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+                             ssl->arrays->client_identity, ssl->arrays->psk_key,
+                             MAX_PSK_KEY_LEN)) != 0) {
+            if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
+                return PSK_KEY_ERROR;
+            /* TODO: Callback should be able to specify ciphersuite. */
+
+            suite[0] = TLS13_BYTE;
+            suite[1] = WOLFSSL_DEF_PSK_CIPHER;
+            if (!FindSuite(ssl, suite)) {
+                current = current->next;
+                continue;
+            }
+
+            /* Default to ciphersuite if cb doesn't specify. */
+            ssl->options.resuming = 0;
+
+            /* PSK age is always zero. */
+            if (current->ticketAge != ssl->session.ticketAdd)
+                return PSK_KEY_ERROR;
+
+            /* Check whether PSK ciphersuite is in SSL. */
+            ssl->options.cipherSuite0 = TLS13_BYTE;
+            ssl->options.cipherSuite  = WOLFSSL_DEF_PSK_CIPHER;
+            ret = SetCipherSpecs(ssl);
+            if (ret != 0)
+                return ret;
+
+            /* Derive the early secret using the PSK. */
+            ret = DeriveEarlySecret(ssl);
+            if (ret != 0)
+                return ret;
+            /* Derive the binder key to use to with HMAC. */
+            ret = DeriveBinderKey(ssl, binderKey);
+            if (ret != 0)
+                return ret;
+        }
+        else
+    #endif
+        {
+            current = current->next;
+            continue;
+        }
+
+        ssl->options.sendVerify = 0;
+
+        /* Derive the Finished message secret. */
+        ret = DeriveFinishedSecret(ssl, binderKey,
+                                             ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        /* Derive the binder and compare with the one in the extension. */
+        ret = BuildTls13HandshakeHmac(ssl,
+                         ssl->keys.client_write_MAC_secret, binder, &binderLen);
+        if (ret != 0)
+            return ret;
+        if (binderLen != current->binderLen ||
+                             XMEMCMP(binder, current->binder, binderLen) != 0) {
+            return BAD_BINDER;
+        }
+
+        /* This PSK works, no need to try any more. */
+        current->chosen = 1;
+        ext->resp = 1;
+        break;
+    }
+
+    if (current == NULL) {
+#ifdef WOLFSSL_PSK_ID_PROTECTION
+    #ifndef NO_CERTS
+        if (ssl->buffers.certChainCnt != 0)
+            return 0;
+    #endif
+        return BAD_BINDER;
+#else
+        return 0;
+#endif
+    }
+
+    /* Hash the rest of the ClientHello. */
+    ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen);
+    if (ret != 0)
+        return ret;
+
+#ifdef WOLFSSL_EARLY_DATA
+    extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
+    if (extEarlyData != NULL) {
+        if (ssl->earlyData != no_early_data && current == ext->data) {
+            extEarlyData->resp = 1;
+
+            /* Derive early data decryption key. */
+            ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1);
+            if (ret != 0)
+                return ret;
+            if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                return ret;
+
+            ssl->earlyData = process_early_data;
+        }
+        else
+            extEarlyData->resp = 0;
+    }
+#endif
+
+    /* Get the PSK key exchange modes the client wants to negotiate. */
+    ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
+    if (ext == NULL)
+        return MISSING_HANDSHAKE_DATA;
+    modes = ext->val;
+
+    ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
+    /* Use (EC)DHE for forward-security if possible. */
+    if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
+                                                                  ext != NULL) {
+        /* Only use named group used in last session. */
+        ssl->namedGroup = ssl->session.namedGroup;
+
+        /* Pick key share and Generate a new key if not present. */
+        ret = TLSX_KeyShare_Establish(ssl);
+        if (ret == KEY_SHARE_ERROR) {
+            ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
+            ret = 0;
+        }
+        else if (ret < 0)
+            return ret;
+
+        /* Send new public key to client. */
+        ext->resp = 1;
+    }
+    else {
+        if ((modes & (1 << PSK_KE)) == 0)
+            return PSK_KEY_ERROR;
+        ssl->options.noPskDheKe = 1;
+    }
+
+    *usingPSK = 1;
+
+    WOLFSSL_LEAVE("DoPreSharedKeys", ret);
+
+    return ret;
+}
+#endif
+
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+/* Check that the Cookie data's integrity.
+ *
+ * ssl       SSL/TLS object.
+ * cookie    The cookie data - hash and MAC.
+ * cookieSz  The length of the cookie data in bytes.
+ * returns Length of the hash on success, otherwise failure.
+ */
+static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz)
+{
+    int  ret;
+    byte mac[WC_MAX_DIGEST_SIZE];
+    Hmac cookieHmac;
+    byte cookieType;
+    byte macSz;
+
+#if !defined(NO_SHA) && defined(NO_SHA256)
+    cookieType = SHA;
+    macSz = WC_SHA_DIGEST_SIZE;
+#endif /* NO_SHA */
+#ifndef NO_SHA256
+    cookieType = WC_SHA256;
+    macSz = WC_SHA256_DIGEST_SIZE;
+#endif /* NO_SHA256 */
+
+    if (cookieSz < ssl->specs.hash_size + macSz)
+        return HRR_COOKIE_ERROR;
+    cookieSz -= macSz;
+
+    ret = wc_HmacSetKey(&cookieHmac, cookieType,
+                        ssl->buffers.tls13CookieSecret.buffer,
+                        ssl->buffers.tls13CookieSecret.length);
+    if (ret != 0)
+        return ret;
+    if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0)
+        return ret;
+    if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
+        return ret;
+
+    if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0)
+        return HRR_COOKIE_ERROR;
+    return cookieSz;
+}
+
+/* Length of the KeyShare Extension */
+#define HRR_KEY_SHARE_SZ   (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* Length of the Supported Vresions Extension */
+#define HRR_VERSIONS_SZ    (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* Length of the Cookie Extension excluding cookie data */
+#define HRR_COOKIE_HDR_SZ  (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* PV | CipherSuite | Ext Len */
+#define HRR_BODY_SZ        (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
+/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */
+#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
+                        HRR_BODY_SZ         + \
+                          HRR_KEY_SHARE_SZ  + \
+                          HRR_COOKIE_HDR_SZ)
+#else
+/* PV | Random | Session Id | CipherSuite | Compression | Ext Len */
+#define HRR_BODY_SZ        (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \
+                            SUITE_LEN + COMP_LEN + OPAQUE16_LEN)
+/* HH | PV | CipherSuite | Ext Len | Key Share | Supported Version | Cookie */
+#define MAX_HRR_SZ   (HANDSHAKE_HEADER_SZ   + \
+                        HRR_BODY_SZ         + \
+                          HRR_KEY_SHARE_SZ  + \
+                          HRR_VERSIONS_SZ   + \
+                          HRR_COOKIE_HDR_SZ)
+#endif
+
+/* Restart the Hanshake hash from the cookie value.
+ *
+ * ssl     SSL/TLS object.
+ * cookie  Cookie data from client.
+ * returns 0 on success, otherwise failure.
+ */
+static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
+{
+    byte   header[HANDSHAKE_HEADER_SZ];
+    byte   hrr[MAX_HRR_SZ];
+    int    hrrIdx;
+    word32 idx;
+    byte   hashSz;
+    byte*  cookieData;
+    byte   cookieDataSz;
+    word16 length;
+    int    keyShareExt = 0;
+    int    ret;
+
+    cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len);
+    if (ret < 0)
+        return ret;
+    hashSz = cookie->data;
+    cookieData = &cookie->data;
+    idx = OPAQUE8_LEN;
+
+    /* Restart handshake hash with synthetic message hash. */
+    AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
+    if ((ret = InitHandshakeHashes(ssl)) != 0)
+        return ret;
+    if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0)
+        return ret;
+
+    /* Reconstruct the HelloRetryMessage for handshake hash. */
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len;
+#else
+    length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz +
+             HRR_COOKIE_HDR_SZ + cookie->len;
+    length += HRR_VERSIONS_SZ;
+#endif
+    if (cookieDataSz > hashSz + OPAQUE16_LEN) {
+        keyShareExt = 1;
+        length += HRR_KEY_SHARE_SZ;
+    }
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl);
+
+    idx += hashSz;
+    hrrIdx = HANDSHAKE_HEADER_SZ;
+    /* TODO: [TLS13] Replace existing code with code in comment.
+     * Use the TLS v1.3 draft version for now.
+     *
+     * Change to:
+     * hrr[hrrIdx++] = ssl->version.major;
+     * hrr[hrrIdx++] = ssl->version.minor;
+     */
+    /* The negotiated protocol version. */
+    hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
+    hrr[hrrIdx++] = TLS_DRAFT_MINOR;
+    /* Cipher Suite */
+    hrr[hrrIdx++] = cookieData[idx++];
+    hrr[hrrIdx++] = cookieData[idx++];
+
+    /* Extensions' length */
+    length -= HRR_BODY_SZ;
+    c16toa(length, hrr + hrrIdx);
+    hrrIdx += 2;
+#else
+    AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl);
+
+    idx += hashSz;
+    hrrIdx = HANDSHAKE_HEADER_SZ;
+
+    /* The negotiated protocol version. */
+    hrr[hrrIdx++] = ssl->version.major;
+    hrr[hrrIdx++] = TLSv1_2_MINOR;
+
+    /* HelloRetryRequest message has fixed value for random. */
+    XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN);
+    hrrIdx += RAN_LEN;
+
+    hrr[hrrIdx++] = ssl->session.sessionIDSz;
+    if (ssl->session.sessionIDSz > 0) {
+        XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        hrrIdx += ssl->session.sessionIDSz;
+    }
+
+    /* Cipher Suite */
+    hrr[hrrIdx++] = cookieData[idx++];
+    hrr[hrrIdx++] = cookieData[idx++];
+
+    /* Compression not supported in TLS v1.3. */
+    hrr[hrrIdx++] = 0;
+
+    /* Extensions' length */
+    length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz;
+    c16toa(length, hrr + hrrIdx);
+    hrrIdx += 2;
+
+#endif
+    /* Optional KeyShare Extension */
+    if (keyShareExt) {
+        c16toa(TLSX_KEY_SHARE, hrr + hrrIdx);
+        hrrIdx += 2;
+        c16toa(OPAQUE16_LEN, hrr + hrrIdx);
+        hrrIdx += 2;
+        hrr[hrrIdx++] = cookieData[idx++];
+        hrr[hrrIdx++] = cookieData[idx++];
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(OPAQUE16_LEN, hrr + hrrIdx);
+    hrrIdx += 2;
+    /* TODO: [TLS13] Change to ssl->version.major and minor once final. */
+    #ifdef WOLFSSL_TLS13_FINAL
+        hrr[hrrIdx++] = ssl->version.major;
+        hrr[hrrIdx++] = ssl->version.minor;
+    #else
+        hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
+        hrr[hrrIdx++] = TLS_DRAFT_MINOR;
+    #endif
+#endif
+    /* Mandatory Cookie Extension */
+    c16toa(TLSX_COOKIE, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx);
+    hrrIdx += 2;
+    c16toa(cookie->len, hrr + hrrIdx);
+    hrrIdx += 2;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Reconstucted HelloRetryRequest");
+    WOLFSSL_BUFFER(hrr, hrrIdx);
+    WOLFSSL_MSG("Cookie");
+    WOLFSSL_BUFFER(cookieData, cookie->len);
+#endif
+
+    if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0)
+        return ret;
+    return HashOutputRaw(ssl, cookieData, cookie->len);
+}
+#endif
+
+/* Handle a ClientHello handshake message.
+ * If the protocol version in the message is not TLS v1.3 or higher, use
+ * DoClientHello()
+ * Only a server will receive this message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of ClientHello.
+ *           On exit, the index of byte after the ClientHello message and
+ *           padding.
+ * helloSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                       word32 helloSz)
+{
+    int             ret = VERSION_ERROR;
+    byte            b;
+    ProtocolVersion pv;
+    Suites          clSuites;
+    word32          i = *inOutIdx;
+    word32          begin = i;
+    word16          totalExtSz = 0;
+    int             usingPSK = 0;
+    byte            sessIdSz;
+#ifndef WOLFSSL_NO_TLS12
+    int             bogusID = 0;
+#endif
+
+    WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
+    WOLFSSL_ENTER("DoTls13ClientHello");
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
+    if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+    /* protocol version, random and session id length check */
+    if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+
+    /* Protocol version */
+    XMEMCPY(&pv, input + i, OPAQUE16_LEN);
+    ssl->chVersion = pv;   /* store */
+    i += OPAQUE16_LEN;
+    /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */
+    if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
+        pv.minor = TLSv1_2_MINOR;
+
+#ifndef WOLFSSL_NO_TLS12
+    if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor < TLSv1_3_MINOR)
+        return DoClientHello(ssl, input, inOutIdx, helloSz);
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    if (ssl->options.downgrade) {
+       if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
+            return ret;
+    }
+#endif
+
+    /* Client random */
+    XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
+    i += RAN_LEN;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("client random");
+    WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN);
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Session id - empty in TLS v1.3 */
+    sessIdSz = input[i++];
+    if (sessIdSz > 0 && !ssl->options.downgrade) {
+        WOLFSSL_MSG("Client sent session id - not supported");
+        return BUFFER_ERROR;
+    }
+#else
+    sessIdSz = input[i++];
+    if (sessIdSz != ID_LEN && sessIdSz != 0)
+        return INVALID_PARAMETER;
+#endif
+    ssl->session.sessionIDSz = sessIdSz;
+    if (sessIdSz == ID_LEN) {
+        XMEMCPY(ssl->session.sessionID, input + i, sessIdSz);
+        i += ID_LEN;
+    }
+#ifndef WOLFSSL_NO_TLS12
+    #ifdef HAVE_SESSION_TICKET
+        if (sessIdSz > 0 && sessIdSz < ID_LEN)
+            bogusID = 1;
+    #endif
+#endif
+
+    /* Cipher suites */
+    if ((i - begin) + OPAQUE16_LEN > helloSz)
+        return BUFFER_ERROR;
+    ato16(&input[i], &clSuites.suiteSz);
+    i += OPAQUE16_LEN;
+    /* suites and compression length check */
+    if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
+        return BUFFER_ERROR;
+    if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ)
+        return BUFFER_ERROR;
+    XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+    i += clSuites.suiteSz;
+    clSuites.hashSigAlgoSz = 0;
+
+    /* Compression */
+    b = input[i++];
+    if ((i - begin) + b > helloSz)
+        return BUFFER_ERROR;
+    if (b != COMP_LEN) {
+        WOLFSSL_MSG("Must be one compression type in list");
+        return INVALID_PARAMETER;
+    }
+    b = input[i++];
+    if (b != NO_COMPRESSION) {
+        WOLFSSL_MSG("Must be no compression type in list");
+        return INVALID_PARAMETER;
+    }
+
+    if ((i - begin) < helloSz) {
+        if ((i - begin) + OPAQUE16_LEN > helloSz)
+            return BUFFER_ERROR;
+        ato16(&input[i], &totalExtSz);
+        i += OPAQUE16_LEN;
+        if ((i - begin) + totalExtSz > helloSz)
+            return BUFFER_ERROR;
+
+    #ifdef HAVE_QSH
+        QSH_Init(ssl);
+    #endif
+
+        /* Auto populate extensions supported unless user defined. */
+        if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
+            return ret;
+
+        /* Parse extensions */
+        if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello,
+                                                                  &clSuites))) {
+            return ret;
+        }
+
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
+                                                        defined(WOLFSSL_HAPROXY)
+        if ((ret = SNI_Callback(ssl)) != 0)
+            return ret;
+        ssl->options.side = WOLFSSL_SERVER_END;
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+    }
+
+    i += totalExtSz;
+    *inOutIdx = i;
+
+    if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) {
+        if (!ssl->options.downgrade) {
+            WOLFSSL_MSG("Client trying to connect with lesser version than "
+                        "TLS v1.3");
+            return VERSION_ERROR;
+        }
+
+        if (pv.minor < ssl->options.minDowngrade)
+            return VERSION_ERROR;
+        ssl->version.minor = pv.minor;
+    }
+
+    ssl->options.sendVerify = SEND_CERT;
+
+    ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+    ssl->options.haveSessionId = 1;
+
+    if (IsAtLeastTLSv1_3(ssl->version)) {
+#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
+        if (ssl->options.sendCookie &&
+              ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+            TLSX* ext;
+
+            if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
+                return HRR_COOKIE_ERROR;
+            /* Ensure the cookie came from client and isn't the one in the
+             * response - HelloRetryRequest.
+             */
+            if (ext->resp == 1)
+                return HRR_COOKIE_ERROR;
+            ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
+            if (ret != 0)
+                return ret;
+        }
+#endif
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        if (ssl->options.downgrade) {
+            if ((ret = InitHandshakeHashes(ssl)) != 0)
+                return ret;
+        }
+
+        /* Refine list for PSK processing. */
+        RefineSuites(ssl, &clSuites);
+
+        /* Process the Pre-Shared Key extension if present. */
+        ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK);
+        if (ret != 0)
+            return ret;
+#endif
+    }
+#ifndef WOLFSSL_NO_TLS12
+    else if (ssl->options.resuming) {
+        ret = HandleTlsResumption(ssl, bogusID, &clSuites);
+        if (ret != 0)
+            return ret;
+        /* Check wheter resuming has been chosen */
+        if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) {
+            WOLFSSL_LEAVE("DoTls13ClientHello", ret);
+            WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+            return ret;
+        }
+    }
+#else
+    else {
+        WOLFSSL_MSG("Negotiated lesser version than TLS v1.3");
+        return VERSION_ERROR;
+    }
+#endif
+
+    if (!usingPSK) {
+        if ((ret = MatchSuite(ssl, &clSuites)) < 0) {
+            WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
+            return ret;
+        }
+
+        /* Check that the negotiated ciphersuite matches protocol version. */
+        if (IsAtLeastTLSv1_3(ssl->version)) {
+            if (ssl->options.cipherSuite0 != TLS13_BYTE) {
+                WOLFSSL_MSG("Negotiated ciphersuite from lesser version than "
+                            "TLS v1.3");
+                return VERSION_ERROR;
+            }
+        }
+        /* VerifyServerSuite handles when version is less than 1.3 */
+
+#ifdef HAVE_SESSION_TICKET
+        if (ssl->options.resuming) {
+            ssl->options.resuming = 0;
+            XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size);
+            /* May or may not have done any hashing. */
+            if ((ret = InitHandshakeHashes(ssl)) != 0)
+                return ret;
+        }
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+        if (IsAtLeastTLSv1_3(ssl->version) || !ssl->options.downgrade)
+#endif
+        {
+            if ((ret = HashInput(ssl, input + begin, helloSz)) != 0)
+                return ret;
+        }
+
+        if (IsAtLeastTLSv1_3(ssl->version)) {
+            /* Derive early secret for handshake secret. */
+            if ((ret = DeriveEarlySecret(ssl)) != 0)
+                return ret;
+        }
+    }
+
+    WOLFSSL_LEAVE("DoTls13ClientHello", ret);
+    WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
+
+    return ret;
+}
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+/* handle generation of TLS 1.3 hello_retry_request (6) */
+/* Send the HelloRetryRequest message to indicate the negotiated protocol
+ * version and security parameters the server is willing to use.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+int SendTls13HelloRetryRequest(WOLFSSL* ssl)
+{
+    int    ret;
+    byte*  output;
+    word32 length;
+    word16 len;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_ENTER("SendTls13HelloRetryRequest");
+
+    /* Get the length of the extensions that will be written. */
+    len = 0;
+    ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len);
+    /* There must be extensions sent to indicate what client needs to do. */
+    if (ret != 0)
+        return MISSING_HANDSHAKE_DATA;
+
+    /* Protocol version + Extensions */
+    length = OPAQUE16_LEN + len;
+    sendSz = idx + length;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    /* Add record and hanshake headers. */
+    AddTls13Headers(output, length, hello_retry_request, ssl);
+
+    /* TODO: [TLS13] Replace existing code with code in comment.
+     * Use the TLS v1.3 draft version for now.
+     *
+     * Change to:
+     * output[idx++] = ssl->version.major;
+     * output[idx++] = ssl->version.minor;
+     */
+    /* The negotiated protocol version. */
+    output[idx++] = TLS_DRAFT_MAJOR;
+    output[idx++] = TLS_DRAFT_MINOR;
+
+    /* Add TLS extensions. */
+    ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL);
+    if (ret != 0)
+        return ret;
+    idx += len;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "HelloRetryRequest");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+#endif
+    if ((ret = HashOutput(ssl, output, idx, 0)) != 0)
+        return ret;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret);
+
+    return ret;
+}
+#endif /* WOLFSSL_TLS13_DRAFT_18 */
+
+/* Send TLS v1.3 ServerHello message to client.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+#ifdef WOLFSSL_TLS13_DRAFT_18
+static
+#endif
+/* handle generation of TLS 1.3 server_hello (2) */
+int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
+{
+    int    ret;
+    byte*  output;
+    word16 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
+    WOLFSSL_ENTER("SendTls13ServerHello");
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    if (extMsgType == hello_retry_request) {
+        if ((ret = RestartHandshakeHash(ssl)) < 0)
+            return ret;
+    }
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* Protocol version, server random, cipher suite and extensions. */
+    length = VERSION_SZ + RAN_LEN + SUITE_LEN;
+    ret = TLSX_GetResponseSize(ssl, server_hello, &length);
+    if (ret != 0)
+        return ret;
+#else
+    /* Protocol version, server random, session id, cipher suite, compression
+     * and extensions.
+     */
+    length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz +
+             SUITE_LEN + COMP_LEN;
+    ret = TLSX_GetResponseSize(ssl, extMsgType, &length);
+    if (ret != 0)
+        return ret;
+#endif
+    sendSz = idx + length;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, server_hello, ssl);
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    /* TODO: [TLS13] Replace existing code with code in comment.
+     * Use the TLS v1.3 draft version for now.
+     *
+     * Change to:
+     * output[idx++] = ssl->version.major;
+     * output[idx++] = ssl->version.minor;
+     */
+    /* The negotiated protocol version. */
+    output[idx++] = TLS_DRAFT_MAJOR;
+    output[idx++] = TLS_DRAFT_MINOR;
+#else
+    /* The protocol version must be TLS v1.2 for middleboxes. */
+    output[idx++] = ssl->version.major;
+    output[idx++] = TLSv1_2_MINOR;
+#endif
+
+    if (extMsgType == server_hello) {
+        /* Generate server random. */
+        if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0)
+            return ret;
+    }
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    else {
+        /* HelloRetryRequest message has fixed value for random. */
+        XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
+    }
+#endif
+    /* Store in SSL for debugging. */
+    XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
+    idx += RAN_LEN;
+
+#ifdef WOLFSSL_DEBUG_TLS
+    WOLFSSL_MSG("Server random");
+    WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN);
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    output[idx++] = ssl->session.sessionIDSz;
+    if (ssl->session.sessionIDSz > 0) {
+        XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz);
+        idx += ssl->session.sessionIDSz;
+    }
+#endif
+
+    /* Chosen cipher suite */
+    output[idx++] = ssl->options.cipherSuite0;
+    output[idx++] = ssl->options.cipherSuite;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Compression not supported in TLS v1.3. */
+    output[idx++] = 0;
+#endif
+
+    /* Extensions */
+    ret = TLSX_WriteResponse(ssl, output + idx, extMsgType, NULL);
+    if (ret != 0)
+        return ret;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0)
+        return ret;
+
+    #ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "ServerHello");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
+                      WRITE_PROTO, ssl->heap);
+    }
+    #endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    ssl->options.serverState = SERVER_HELLO_COMPLETE;
+#else
+    if (extMsgType == server_hello)
+        ssl->options.serverState = SERVER_HELLO_COMPLETE;
+#endif
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13ServerHello", ret);
+    WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND);
+
+    return ret;
+}
+
+/* handle generation of TLS 1.3 encrypted_extensions (8) */
+/* Send the rest of the extensions encrypted under the handshake key.
+ * This message is always encrypted in TLS v1.3.
+ * Only a server will send this message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13EncryptedExtensions(WOLFSSL* ssl)
+{
+    int    ret;
+    byte*  output;
+    word16 length = 0;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    int    sendSz;
+
+    WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
+    WOLFSSL_ENTER("SendTls13EncryptedExtensions");
+
+    ssl->keys.encryptionOn = 1;
+
+#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
+    if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0)
+        return ret;
+#endif
+
+    /* Derive the handshake secret now that we are at first message to be
+     * encrypted under the keys.
+     */
+    if ((ret = DeriveHandshakeSecret(ssl)) != 0)
+        return ret;
+    if ((ret = DeriveTls13Keys(ssl, handshake_key,
+                               ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0)
+        return ret;
+
+    /* Setup encrypt/decrypt keys for following messages. */
+#ifdef WOLFSSL_EARLY_DATA
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+    if (ssl->earlyData != process_early_data) {
+        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+#else
+    if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+        return ret;
+#endif
+
+    ret = TLSX_GetResponseSize(ssl, encrypted_extensions, &length);
+    if (ret != 0)
+        return ret;
+
+    sendSz = idx + length;
+    /* Encryption always on. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    ret = CheckAvailableSize(ssl, sendSz);
+    if (ret != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, encrypted_extensions, ssl);
+
+    ret = TLSX_WriteResponse(ssl, output + idx, encrypted_extensions, NULL);
+    if (ret != 0)
+        return ret;
+    idx += length;
+
+#ifdef WOLFSSL_CALLBACKS
+    if (ssl->hsInfoOn)
+        AddPacketName(ssl, "EncryptedExtensions");
+    if (ssl->toInfoOn) {
+        AddPacketInfo(ssl, "EncryptedExtensions", handshake, output,
+                      sendSz, WRITE_PROTO, ssl->heap);
+    }
+#endif
+
+    /* This handshake message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13EncryptedExtensions", ret);
+    WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND);
+
+    return ret;
+}
+
+#ifndef NO_CERTS
+/* handle generation TLS v1.3 certificate_request (13) */
+/* Send the TLS v1.3 CertificateRequest message.
+ * This message is always encrypted in TLS v1.3.
+ * Only a server will send this message.
+ *
+ * ssl        SSL/TLS object.
+ * reqCtx     Request context.
+ * reqCtxLen  Length of context. 0 when sending as part of handshake.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
+                                       int reqCtxLen)
+{
+    byte*   output;
+    int    ret;
+    int    sendSz;
+    word32 i;
+    word16 reqSz;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    TLSX*  ext;
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+    WOLFSSL_ENTER("SendTls13CertificateRequest");
+
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz);
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ;
+    reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
+
+    sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+    /* Always encrypted and make room for padding. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, reqSz, certificate_request, ssl);
+
+    /* Certificate request context. */
+    output[i++] = reqCtxLen;
+    if (reqCtxLen != 0) {
+        XMEMCPY(output + i, reqCtx, reqCtxLen);
+        i += reqCtxLen;
+    }
+
+    /* supported hash/sig */
+    c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
+    i += LENGTH_SZ;
+
+    XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz);
+    i += ssl->suites->hashSigAlgoSz;
+
+    /* Certificate authorities not supported yet - empty buffer. */
+    c16toa(0, &output[i]);
+    i += REQ_HEADER_SZ;
+
+    /* Certificate extensions. */
+    c16toa(0, &output[i]);  /* auth's */
+    i += REQ_HEADER_SZ;
+#else
+    ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS);
+    if (ext == NULL)
+        return EXT_MISSING;
+    ext->resp = 0;
+
+    i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+    reqSz = (word16)(OPAQUE8_LEN + reqCtxLen);
+    ret = TLSX_GetRequestSize(ssl, certificate_request, &reqSz);
+    if (ret != 0)
+        return ret;
+
+    sendSz = i + reqSz;
+    /* Always encrypted and make room for padding. */
+    sendSz += MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, reqSz, certificate_request, ssl);
+
+    /* Certificate request context. */
+    output[i++] = (byte)reqCtxLen;
+    if (reqCtxLen != 0) {
+        XMEMCPY(output + i, reqCtx, reqCtxLen);
+        i += reqCtxLen;
+    }
+
+    /* Certificate extensions. */
+    reqSz = 0;
+    ret = TLSX_WriteRequest(ssl, output + i, certificate_request, &reqSz);
+    if (ret != 0)
+        return ret;
+    i += reqSz;
+#endif
+
+    /* Always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn)
+            AddPacketName(ssl, "CertificateRequest");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "CertificateRequest", handshake, output,
+                          sendSz, WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13CertificateRequest", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
+
+    return ret;
+}
+#endif /* NO_CERTS */
+#endif /* NO_WOLFSSL_SERVER */
+
+#ifndef NO_CERTS
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+/* Encode the signature algorithm into buffer.
+ *
+ * hashalgo  The hash algorithm.
+ * hsType   The signature type.
+ * output    The buffer to encode into.
+ */
+static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
+{
+    switch (hsType) {
+#ifdef HAVE_ECC
+        case ecc_dsa_sa_algo:
+            output[0] = hashAlgo;
+            output[1] = ecc_dsa_sa_algo;
+            break;
+#endif
+#ifdef HAVE_ED25519
+        /* ED25519: 0x0807 */
+        case ed25519_sa_algo:
+            output[0] = ED25519_SA_MAJOR;
+            output[1] = ED25519_SA_MINOR;
+            (void)hashAlgo;
+            break;
+#endif
+#ifndef NO_RSA
+        /* PSS signatures: 0x080[4-6] */
+        case rsa_pss_sa_algo:
+            output[0] = rsa_pss_sa_algo;
+            output[1] = hashAlgo;
+            break;
+#endif
+        /* ED448: 0x0808 */
+    }
+}
+
+/* Decode the signature algorithm.
+ *
+ * input     The encoded signature algorithm.
+ * hashalgo  The hash algorithm.
+ * hsType   The signature type.
+ */
+static WC_INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType)
+{
+    switch (input[0]) {
+        case NEW_SA_MAJOR:
+            /* PSS signatures: 0x080[4-6] */
+            if (input[1] <= sha512_mac) {
+                *hsType   = input[0];
+                *hashAlgo = input[1];
+            }
+    #ifdef HAVE_ED25519
+            /* ED25519: 0x0807 */
+            if (input[1] == ED25519_SA_MINOR) {
+                *hsType = ed25519_sa_algo;
+                /* Hash performed as part of sign/verify operation. */
+                *hashAlgo = sha512_mac;
+            }
+    #endif
+            /* ED448: 0x0808 */
+            break;
+        default:
+            *hashAlgo = input[0];
+            *hsType   = input[1];
+            break;
+    }
+}
+
+/* Get the hash of the messages so far.
+ *
+ * ssl   The SSL/TLS object.
+ * hash  The buffer to write the hash to.
+ * returns the length of the hash.
+ */
+static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash)
+{
+    int ret = 0;
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
+            if (ret == 0)
+                ret = WC_SHA256_DIGEST_SIZE;
+            break;
+    #endif /* !NO_SHA256 */
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
+            if (ret == 0)
+                ret = WC_SHA384_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SHA384 */
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
+            if (ret == 0)
+                ret = WC_SHA512_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_TLS13_SHA512 */
+    }
+    return ret;
+}
+
+/* The length of the certificate verification label - client and server. */
+#define CERT_VFY_LABEL_SZ    34
+/* The server certificate verification label. */
+static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] =
+    "TLS 1.3, server CertificateVerify";
+/* The client certificate verification label. */
+static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] =
+    "TLS 1.3, client CertificateVerify";
+
+/* The number of prefix bytes for signature data. */
+#define SIGNING_DATA_PREFIX_SZ     64
+/* The prefix byte in the signature data. */
+#define SIGNING_DATA_PREFIX_BYTE   0x20
+/* Maximum length of the signature data. */
+#define MAX_SIG_DATA_SZ            (SIGNING_DATA_PREFIX_SZ + \
+                                    CERT_VFY_LABEL_SZ      + \
+                                    WC_MAX_DIGEST_SIZE)
+
+/* Create the signature data for TLS v1.3 certificate verification.
+ *
+ * ssl        The SSL/TLS object.
+ * sigData    The signature data.
+ * sigDataSz  The length of the signature data.
+ * check      Indicates this is a check not create.
+ */
+static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz,
+                          int check)
+{
+    word16 idx;
+    int side = ssl->options.side;
+    int ret;
+
+    /* Signature Data = Prefix | Label | Handshake Hash */
+    XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ);
+    idx = SIGNING_DATA_PREFIX_SZ;
+
+    if ((side == WOLFSSL_SERVER_END && check) ||
+        (side == WOLFSSL_CLIENT_END && !check)) {
+        XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ);
+    }
+    if ((side == WOLFSSL_CLIENT_END && check) ||
+        (side == WOLFSSL_SERVER_END && !check)) {
+        XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ);
+    }
+    idx += CERT_VFY_LABEL_SZ;
+
+    ret = GetMsgHash(ssl, &sigData[idx]);
+    if (ret < 0)
+        return ret;
+
+    *sigDataSz = (word16)(idx + ret);
+    ret = 0;
+
+    return ret;
+}
+
+#ifndef NO_RSA
+/* Encode the PKCS #1.5 RSA signature.
+ *
+ * sig        The buffer to place the encoded signature into.
+ * sigData    The data to be signed.
+ * sigDataSz  The size of the data to be signed.
+ * hashAlgo   The hash algorithm to use when signing.
+ * returns the length of the encoded signature or negative on error.
+ */
+static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz,
+                               int sigAlgo, int hashAlgo)
+{
+    Digest digest;
+    int    hashSz = 0;
+    int    ret = BAD_FUNC_ARG;
+    byte*  hash;
+
+    (void)sigAlgo;
+
+    hash = sig;
+
+    /* Digest the signature data. */
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256(&digest.sha256);
+            if (ret == 0) {
+                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, hash);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384(&digest.sha384);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, hash);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512(&digest.sha512);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, hash);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            break;
+#endif
+    }
+
+    if (ret != 0)
+        return ret;
+
+    return hashSz;
+}
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+/* Encode the ECC signature.
+ *
+ * sigData    The data to be signed.
+ * sigDataSz  The size of the data to be signed.
+ * hashAlgo   The hash algorithm to use when signing.
+ * returns the length of the encoded signature or negative on error.
+ */
+static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo)
+{
+    Digest digest;
+    int    hashSz = 0;
+    int    ret = BAD_FUNC_ARG;
+
+    /* Digest the signature data. */
+    switch (hashAlgo) {
+#ifndef NO_WOLFSSL_SHA256
+        case sha256_mac:
+            ret = wc_InitSha256(&digest.sha256);
+            if (ret == 0) {
+                ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha256Final(&digest.sha256, sigData);
+                wc_Sha256Free(&digest.sha256);
+            }
+            hashSz = WC_SHA256_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_InitSha384(&digest.sha384);
+            if (ret == 0) {
+                ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha384Final(&digest.sha384, sigData);
+                wc_Sha384Free(&digest.sha384);
+            }
+            hashSz = WC_SHA384_DIGEST_SIZE;
+            break;
+#endif
+#ifdef WOLFSSL_SHA512
+        case sha512_mac:
+            ret = wc_InitSha512(&digest.sha512);
+            if (ret == 0) {
+                ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz);
+                if (ret == 0)
+                    ret = wc_Sha512Final(&digest.sha512, sigData);
+                wc_Sha512Free(&digest.sha512);
+            }
+            hashSz = WC_SHA512_DIGEST_SIZE;
+            break;
+#endif
+    }
+
+    if (ret != 0)
+        return ret;
+
+    return hashSz;
+}
+#endif /* HAVE_ECC */
+
+#ifndef NO_RSA
+/* Check that the decrypted signature matches the encoded signature
+ * based on the digest of the signature data.
+ *
+ * ssl       The SSL/TLS object.
+ * sigAlgo   The signature algorithm used to generate signature.
+ * hashAlgo  The hash algorithm used to generate signature.
+ * decSig    The decrypted signature.
+ * decSigSz  The size of the decrypted signature.
+ * returns 0 on success, otherwise failure.
+ */
+static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo,
+                             byte* decSig, word32 decSigSz)
+{
+    int    ret = 0;
+    byte   sigData[MAX_SIG_DATA_SZ];
+    word16 sigDataSz;
+    word32 sigSz;
+
+    ret = CreateSigData(ssl, sigData, &sigDataSz, 1);
+    if (ret != 0)
+        return ret;
+
+    if (sigAlgo == rsa_pss_sa_algo) {
+        enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+
+        ret = ConvertHashPss(hashAlgo, &hashType, NULL);
+        if (ret < 0)
+            return ret;
+
+        /* PSS signature can be done in-place */
+        ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz,
+                                  sigAlgo, hashAlgo);
+        if (ret < 0)
+            return ret;
+        sigSz = ret;
+
+        ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz,
+                                     hashType);
+    }
+
+    return ret;
+}
+#endif /* !NO_RSA */
+#endif /* !NO_RSA || HAVE_ECC */
+
+/* Get the next certificate from the list for writing into the TLS v1.3
+ * Certificate message.
+ *
+ * data    The certificate list.
+ * length  The length of the certificate data in the list.
+ * idx     The index of the next certificate.
+ * returns the length of the certificate data. 0 indicates no more certificates
+ * in the list.
+ */
+static word32 NextCert(byte* data, word32 length, word32* idx)
+{
+    word32 len;
+
+    /* Is index at end of list. */
+    if (*idx == length)
+        return 0;
+
+    /* Length of the current ASN.1 encoded certificate. */
+    c24to32(data + *idx, &len);
+    /* Include the length field. */
+    len += 3;
+
+    /* Move index to next certificate and return the current certificate's
+     * length.
+     */
+    *idx += len;
+    return len;
+}
+
+/* Add certificate data and empty extension to output up to the fragment size.
+ *
+ * ssl     SSL/TLS object.
+ * cert    The certificate data to write out.
+ * len     The length of the certificate data.
+ * extSz   Length of the extension data with the certificate.
+ * idx     The start of the certificate data to write out.
+ * fragSz  The maximum size of this fragment.
+ * output  The buffer to write to.
+ * returns the number of bytes written.
+ */
+static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz,
+                         word32 idx, word32 fragSz, byte* output)
+{
+    word32 i = 0;
+    word32 copySz = min(len - idx, fragSz);
+
+    if (idx < len) {
+        XMEMCPY(output, cert + idx, copySz);
+        i = copySz;
+        if (copySz == fragSz)
+            return i;
+    }
+    copySz = len + extSz - idx - i;
+
+    if (extSz == OPAQUE16_LEN) {
+        if (copySz <= fragSz) {
+            /* Empty extension */
+            output[i++] = 0;
+            output[i++] = 0;
+        }
+    }
+    else {
+        byte* certExts = ssl->buffers.certExts->buffer + idx + i - len;
+        /* Put out as much of the extensions' data as will fit in fragment. */
+        if (copySz > fragSz - i)
+            copySz = fragSz - i;
+        XMEMCPY(output + i, certExts, copySz);
+        i += copySz;
+    }
+
+    return i;
+}
+
+/* handle generation TLS v1.3 certificate (11) */
+/* Send the certificate for this end and any CAs that help with validation.
+ * This message is always encrypted in TLS v1.3.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13Certificate(WOLFSSL* ssl)
+{
+    int    ret = 0;
+    word32 certSz, certChainSz, headerSz, listSz, payloadSz;
+    word16 extSz = 0;
+    word32 length, maxFragment;
+    word32 len = 0;
+    word32 idx = 0;
+    word32 offset = OPAQUE16_LEN;
+    byte*  p = NULL;
+    byte   certReqCtxLen = 0;
+    byte*  certReqCtx = NULL;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND);
+    WOLFSSL_ENTER("SendTls13Certificate");
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
+        certReqCtxLen = ssl->certReqCtx->len;
+        certReqCtx = &ssl->certReqCtx->ctx;
+    }
+#endif
+
+    if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+        certSz = 0;
+        certChainSz = 0;
+        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ;
+        length = headerSz;
+        listSz = 0;
+    }
+    else {
+        if (!ssl->buffers.certificate) {
+            WOLFSSL_MSG("Send Cert missing certificate buffer");
+            return BUFFER_ERROR;
+        }
+        /* Certificate Data */
+        certSz = ssl->buffers.certificate->length;
+        /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
+        headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
+                   CERT_HEADER_SZ;
+
+        ret = TLSX_GetResponseSize(ssl, certificate, &extSz);
+        if (ret < 0)
+            return ret;
+
+        /* Create extensions' data if none already present. */
+        if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) {
+            ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap);
+            if (ret < 0)
+                return ret;
+
+            ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer,
+                                                           certificate, &extSz);
+            if (ret < 0)
+                return ret;
+        }
+
+        /* Length of message data with one certificate and extensions. */
+        length = headerSz + certSz + extSz;
+        /* Length of list data with one certificate and extensions. */
+        listSz = CERT_HEADER_SZ + certSz + extSz;
+
+        /* Send rest of chain if sending cert (chain has leading size/s). */
+        if (certSz > 0 && ssl->buffers.certChainCnt > 0) {
+            p = ssl->buffers.certChain->buffer;
+            /* Chain length including extensions. */
+            certChainSz = ssl->buffers.certChain->length +
+                          OPAQUE16_LEN * ssl->buffers.certChainCnt;
+            length += certChainSz;
+            listSz += certChainSz;
+        }
+        else
+            certChainSz = 0;
+    }
+
+    payloadSz = length;
+
+    if (ssl->fragOffset != 0)
+        length -= (ssl->fragOffset + headerSz);
+
+    maxFragment = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE);
+
+    while (length > 0 && ret == 0) {
+        byte*  output = NULL;
+        word32 fragSz = 0;
+        word32 i = RECORD_HEADER_SZ;
+        int    sendSz = RECORD_HEADER_SZ;
+
+        if (ssl->fragOffset == 0)  {
+            if (headerSz + certSz + extSz + certChainSz <=
+                                            maxFragment - HANDSHAKE_HEADER_SZ) {
+                fragSz = headerSz + certSz + extSz + certChainSz;
+            }
+            else
+                fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
+
+            sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+            i += HANDSHAKE_HEADER_SZ;
+        }
+        else {
+            fragSz = min(length, maxFragment);
+            sendSz += fragSz;
+        }
+
+        sendSz += MAX_MSG_EXTRA;
+
+        /* Check buffers are big enough and grow if needed. */
+        if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+            return ret;
+
+        /* Get position in output buffer to write new message to. */
+        output = ssl->buffers.outputBuffer.buffer +
+                 ssl->buffers.outputBuffer.length;
+
+        if (ssl->fragOffset == 0) {
+            AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
+
+            /* Request context. */
+            output[i++] = certReqCtxLen;
+            if (certReqCtxLen > 0) {
+                XMEMCPY(output + i, certReqCtx, certReqCtxLen);
+                i += certReqCtxLen;
+            }
+            length -= OPAQUE8_LEN + certReqCtxLen;
+            fragSz -= OPAQUE8_LEN + certReqCtxLen;
+            /* Certificate list length. */
+            c32to24(listSz, output + i);
+            i += CERT_HEADER_SZ;
+            length -= CERT_HEADER_SZ;
+            fragSz -= CERT_HEADER_SZ;
+            /* Leaf certificate data length. */
+            if (certSz > 0) {
+                c32to24(certSz, output + i);
+                i += CERT_HEADER_SZ;
+                length -= CERT_HEADER_SZ;
+                fragSz -= CERT_HEADER_SZ;
+            }
+        }
+        else
+            AddTls13RecordHeader(output, fragSz, handshake, ssl);
+
+        if (certSz > 0 && ssl->fragOffset < certSz + extSz) {
+            /* Put in the leaf certificate with extensions. */
+            word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer,
+                            certSz, extSz, ssl->fragOffset, fragSz, output + i);
+            i += copySz;
+            ssl->fragOffset += copySz;
+            length -= copySz;
+            fragSz -= copySz;
+            if (ssl->fragOffset == certSz + extSz)
+                FreeDer(&ssl->buffers.certExts);
+        }
+        if (certChainSz > 0 && fragSz > 0) {
+            /* Put in the CA certificates with empty extensions. */
+            while (fragSz > 0) {
+                word32 l;
+
+                if (offset == len + OPAQUE16_LEN) {
+                    /* Find next CA certificate to write out. */
+                    offset = 0;
+                    /* Point to the start of current cert in chain buffer. */
+                    p = ssl->buffers.certChain->buffer + idx;
+                    len = NextCert(ssl->buffers.certChain->buffer,
+                                   ssl->buffers.certChain->length, &idx);
+                    if (len == 0)
+                        break;
+                }
+
+                /* Write out certificate and empty extension. */
+                l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz,
+                                                                    output + i);
+                i += l;
+                ssl->fragOffset += l;
+                length -= l;
+                fragSz -= l;
+                offset += l;
+            }
+        }
+
+        if ((int)i - RECORD_HEADER_SZ < 0) {
+            WOLFSSL_MSG("Send Cert bad inputSz");
+            return BUFFER_E;
+        }
+
+        /* This message is always encrypted. */
+        sendSz = BuildTls13Message(ssl, output, sendSz,
+                                   output + RECORD_HEADER_SZ,
+                                   i - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+        if (sendSz < 0)
+            return sendSz;
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "Certificate");
+            if (ssl->toInfoOn) {
+                AddPacketInfo(ssl, "Certificate", handshake, output,
+                        sendSz, WRITE_PROTO, ssl->heap);
+            }
+        #endif
+
+        ssl->buffers.outputBuffer.length += sendSz;
+        if (!ssl->options.groupMessages)
+            ret = SendBuffered(ssl);
+    }
+
+    if (ret != WANT_WRITE) {
+        /* Clean up the fragment offset. */
+        ssl->fragOffset = 0;
+        if (ssl->options.side == WOLFSSL_SERVER_END)
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+    }
+
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
+        CertReqCtx* ctx = ssl->certReqCtx;
+        ssl->certReqCtx = ssl->certReqCtx->next;
+        XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
+
+    WOLFSSL_LEAVE("SendTls13Certificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND);
+
+    return ret;
+}
+
+typedef struct Scv13Args {
+    byte*  output; /* not allocated */
+#ifndef NO_RSA
+    byte*  verifySig;
+#endif
+    byte*  verify; /* not allocated */
+    word32 idx;
+    word32 sigLen;
+    int    sendSz;
+    word16 length;
+
+    byte   sigAlgo;
+    byte*  sigData;
+    word16 sigDataSz;
+} Scv13Args;
+
+static void FreeScv13Args(WOLFSSL* ssl, void* pArgs)
+{
+    Scv13Args* args = (Scv13Args*)pArgs;
+
+    (void)ssl;
+
+#ifndef NO_RSA
+    if (args->verifySig) {
+        XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->verifySig = NULL;
+    }
+#endif
+    if (args->sigData) {
+        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->sigData = NULL;
+    }
+}
+
+/* handle generation TLS v1.3 certificate_verify (15) */
+/* Send the TLS v1.3 CertificateVerify message.
+ * A hash of all the message so far is used.
+ * The signed data is:
+ *     0x20 * 64 | context string | 0x00 | hash of messages
+ * This message is always encrypted in TLS v1.3.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13CertificateVerify(WOLFSSL* ssl)
+{
+    int ret = 0;
+    buffer* sig = &ssl->buffers.sig;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    Scv13Args* args = (Scv13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    Scv13Args  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+    WOLFSSL_ENTER("SendTls13CertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_scv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(Scv13Args));
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeScv13Args;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+            if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+                return 0;  /* sent blank cert, can't verify */
+            }
+
+            args->sendSz = MAX_CERT_VERIFY_SZ;
+            /* Always encrypted.  */
+            args->sendSz += MAX_MSG_EXTRA;
+
+            /* check for available size */
+            if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
+                goto exit_scv;
+            }
+
+            /* get output buffer */
+            args->output = ssl->buffers.outputBuffer.buffer +
+                           ssl->buffers.outputBuffer.length;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            /* idx is used to track verify pointer offset to output */
+            args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+            args->verify =
+                          &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
+
+            if (ssl->buffers.key == NULL) {
+            #ifdef HAVE_PK_CALLBACKS
+                if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx))
+                    args->length = GetPrivateKeySigSize(ssl);
+                else
+            #endif
+                    ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+            else {
+                ret = DecodePrivateKey(ssl, &args->length);
+                if (ret != 0)
+                    goto exit_scv;
+            }
+
+            if (args->length <= 0) {
+                ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
+            }
+
+            /* Add signature algorithm. */
+            if (ssl->hsType == DYNAMIC_TYPE_RSA)
+                args->sigAlgo = rsa_pss_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
+                args->sigAlgo = ecc_dsa_sa_algo;
+        #ifdef HAVE_ED25519
+            else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
+                args->sigAlgo = ed25519_sa_algo;
+        #endif
+            EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify);
+
+            /* Create the data to be signed. */
+            args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+            if (args->sigData == NULL) {
+                ERROR_OUT(MEMORY_E, exit_scv);
+            }
+
+            ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0);
+            if (ret != 0)
+                goto exit_scv;
+
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                /* build encoded signature buffer */
+                sig->length = MAX_ENCODED_SIG_SZ;
+                sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+                if (sig->buffer == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_scv);
+                }
+
+                ret = CreateRSAEncodedSig(sig->buffer, args->sigData,
+                    args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo);
+                if (ret < 0)
+                    goto exit_scv;
+                sig->length = ret;
+                ret = 0;
+
+                /* Maximum size of RSA Signature. */
+                args->sigLen = args->length;
+            }
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                sig->length = args->sendSz - args->idx - HASH_SIG_SIZE -
+                              VERIFY_HEADER;
+                ret = CreateECCEncodedSig(args->sigData,
+                    args->sigDataSz, ssl->suites->hashAlgo);
+                if (ret < 0)
+                    goto exit_scv;
+                args->sigDataSz = (word16)ret;
+                ret = 0;
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ret = Ed25519CheckPubKey(ssl);
+                if (ret < 0) {
+                    ERROR_OUT(ret, exit_scv);
+                }
+                sig->length = ED25519_SIG_SIZE;
+            }
+        #endif /* HAVE_ECC */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifdef HAVE_ECC
+           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+                ret = EccSign(ssl, args->sigData, args->sigDataSz,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                    &sig->length, (ecc_key*)ssl->hsKey,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+                args->length = (word16)sig->length;
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->hsType == DYNAMIC_TYPE_ED25519) {
+                ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                    &sig->length, (ed25519_key*)ssl->hsKey,
+            #ifdef HAVE_PK_CALLBACKS
+                    ssl->buffers.key
+            #else
+                    NULL
+            #endif
+                );
+                args->length = sig->length;
+            }
+        #endif
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+
+                ret = RsaSign(ssl, sig->buffer, sig->length,
+                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen,
+                    args->sigAlgo, ssl->suites->hashAlgo,
+                    (RsaKey*)ssl->hsKey,
+                    ssl->buffers.key
+                );
+                args->length = (word16)args->sigLen;
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Add signature length. */
+            c16toa(args->length, args->verify + HASH_SIG_SIZE);
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+        #ifndef NO_RSA
+            if (ssl->hsType == DYNAMIC_TYPE_RSA) {
+                if (args->verifySig == NULL) {
+                    args->verifySig = (byte*)XMALLOC(args->sigLen, ssl->heap,
+                                                   DYNAMIC_TYPE_SIGNATURE);
+                    if (args->verifySig == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_scv);
+                    }
+                    XMEMCPY(args->verifySig,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        args->sigLen);
+                }
+
+                /* check for signature faults */
+                ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen,
+                    sig->buffer, sig->length, args->sigAlgo,
+                    ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey,
+                    ssl->buffers.key
+                );
+            }
+        #endif /* !NO_RSA */
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_scv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            /* Put the record and handshake headers on. */
+            AddTls13Headers(args->output, args->length + HASH_SIG_SIZE +
+                            VERIFY_HEADER, certificate_verify, ssl);
+
+            args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ +
+                                   args->length + HASH_SIG_SIZE + VERIFY_HEADER;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_END:
+        {
+            /* This message is always encrypted. */
+            ret = BuildTls13Message(ssl, args->output,
+                                    MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA,
+                                    args->output + RECORD_HEADER_SZ,
+                                    args->sendSz - RECORD_HEADER_SZ, handshake,
+                                    1, 0, 0);
+
+            if (ret < 0) {
+                goto exit_scv;
+            }
+            else {
+                args->sendSz = ret;
+                ret = 0;
+            }
+
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn)
+                AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn) {
+                AddPacketInfo(ssl, "CertificateVerify", handshake,
+                            args->output, args->sendSz, WRITE_PROTO, ssl->heap);
+            }
+        #endif
+
+            ssl->buffers.outputBuffer.length += args->sendSz;
+
+            if (!ssl->options.groupMessages)
+                ret = SendBuffered(ssl);
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_scv:
+
+    WOLFSSL_LEAVE("SendTls13CertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        return ret;
+    }
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    /* Final cleanup */
+    FreeScv13Args(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 certificate (11) */
+/* Parse and handle a TLS v1.3 Certificate message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Certificate.
+ *           On exit, the index of byte after the Certificate message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                              word32 totalSz)
+{
+    int ret;
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_DO);
+    WOLFSSL_ENTER("DoTls13Certificate");
+
+    ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz);
+    if (ret == 0) {
+#if !defined(NO_WOLFSSL_CLIENT)
+        if (ssl->options.side == WOLFSSL_CLIENT_END)
+            ssl->options.serverState = SERVER_CERT_COMPLETE;
+#endif
+#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+            /* reset handshake states */
+            ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+            ssl->options.acceptState  = TICKET_SENT;
+            ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
+        }
+#endif
+    }
+
+    WOLFSSL_LEAVE("DoTls13Certificate", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_DO);
+
+    return ret;
+}
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+
+typedef struct Dcv13Args {
+    byte*  output; /* not allocated */
+    word32 sendSz;
+    word16 sz;
+    word32 sigSz;
+    word32 idx;
+    word32 begin;
+    byte   hashAlgo;
+    byte   sigAlgo;
+
+    byte*  sigData;
+    word16 sigDataSz;
+} Dcv13Args;
+
+static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs)
+{
+    Dcv13Args* args = (Dcv13Args*)pArgs;
+
+    if (args->sigData != NULL) {
+        XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+        args->sigData = NULL;
+    }
+
+    (void)ssl;
+}
+
+/* handle processing TLS v1.3 certificate_verify (15) */
+/* Parse and handle a TLS v1.3 CertificateVerify message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of
+ *           CertificateVerify.
+ *           On exit, the index of byte after the CertificateVerify message.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
+                                    word32* inOutIdx, word32 totalSz)
+{
+    int         ret = 0;
+    buffer*     sig = &ssl->buffers.sig;
+#ifdef WOLFSSL_ASYNC_CRYPT
+    Dcv13Args* args = (Dcv13Args*)ssl->async.args;
+    typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
+    (void)sizeof(args_test);
+#else
+    Dcv13Args  args[1];
+#endif
+
+    WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO);
+    WOLFSSL_ENTER("DoTls13CertificateVerify");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
+    if (ret != WC_NOT_PENDING_E) {
+        /* Check for error */
+        if (ret < 0)
+            goto exit_dcv;
+    }
+    else
+#endif
+    {
+        /* Reset state */
+        ret = 0;
+        ssl->options.asyncState = TLS_ASYNC_BEGIN;
+        XMEMSET(args, 0, sizeof(Dcv13Args));
+        args->hashAlgo = sha_mac;
+        args->sigAlgo = anonymous_sa_algo;
+        args->idx = *inOutIdx;
+        args->begin = *inOutIdx;
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ssl->async.freeArgs = FreeDcv13Args;
+    #endif
+    }
+
+    switch(ssl->options.asyncState)
+    {
+        case TLS_ASYNC_BEGIN:
+        {
+        #ifdef WOLFSSL_CALLBACKS
+            if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateVerify");
+            if (ssl->toInfoOn) AddLateName("CertificateVerify",
+                                           &ssl->timeoutInfo);
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_BUILD;
+        } /* case TLS_ASYNC_BEGIN */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_BUILD:
+        {
+            /* Signature algorithm. */
+            if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+            DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo);
+            args->idx += OPAQUE16_LEN;
+
+            /* Signature length. */
+            if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+            ato16(input + args->idx, &args->sz);
+            args->idx += OPAQUE16_LEN;
+
+            /* Signature data. */
+            if ((args->idx - args->begin) + args->sz > totalSz ||
+                                                       args->sz > ENCRYPT_LEN) {
+                ERROR_OUT(BUFFER_ERROR, exit_dcv);
+            }
+
+            /* Check for public key of required type. */
+        #ifdef HAVE_ED25519
+            if (args->sigAlgo == ed25519_sa_algo &&
+                                                  !ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify");
+            }
+        #endif
+        #ifdef HAVE_ECC
+            if (args->sigAlgo == ecc_dsa_sa_algo &&
+                                                   !ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+            }
+        #endif
+        #ifndef NO_RSA
+            if ((args->sigAlgo == rsa_sa_algo ||
+                 args->sigAlgo == rsa_pss_sa_algo) &&
+                         (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) {
+                WOLFSSL_MSG("Oops, peer sent RSA key but not in verify");
+            }
+        #endif
+
+            sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap,
+                                         DYNAMIC_TYPE_SIGNATURE);
+            if (sig->buffer == NULL) {
+                ERROR_OUT(MEMORY_E, exit_dcv);
+            }
+            sig->length = args->sz;
+            XMEMCPY(sig->buffer, input + args->idx, args->sz);
+
+        #ifdef HAVE_ECC
+            if (ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+                if (args->sigData == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_dcv);
+                }
+
+                ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
+                if (ret != 0)
+                    goto exit_dcv;
+                ret = CreateECCEncodedSig(args->sigData,
+                    args->sigDataSz, args->hashAlgo);
+                if (ret < 0)
+                    goto exit_dcv;
+                args->sigDataSz = (word16)ret;
+                ret = 0;
+            }
+        #endif
+        #ifdef HAVE_ED25519
+            if (ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Doing ED25519 peer cert verify");
+
+                args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
+                                                    DYNAMIC_TYPE_SIGNATURE);
+                if (args->sigData == NULL) {
+                    ERROR_OUT(MEMORY_E, exit_dcv);
+                }
+
+                CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
+                ret = 0;
+            }
+        #endif
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_DO;
+        } /* case TLS_ASYNC_BUILD */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_DO:
+        {
+        #ifndef NO_RSA
+            if (args->sigAlgo == rsa_sa_algo ||
+                                             args->sigAlgo == rsa_pss_sa_algo) {
+                WOLFSSL_MSG("Doing RSA peer cert verify");
+
+                ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output,
+                    args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerRsaKey
+                #else
+                    NULL
+                #endif
+                );
+                if (ret >= 0) {
+                    args->sendSz = ret;
+                    ret = 0;
+                }
+            }
+        #endif /* !NO_RSA */
+        #ifdef HAVE_ECC
+            if (ssl->peerEccDsaKeyPresent) {
+                WOLFSSL_MSG("Doing ECC peer cert verify");
+
+                ret = EccVerify(ssl, input + args->idx, args->sz,
+                    args->sigData, args->sigDataSz,
+                    ssl->peerEccDsaKey,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerEccDsaKey
+                #else
+                    NULL
+                #endif
+                );
+            }
+        #endif /* HAVE_ECC */
+        #ifdef HAVE_ED25519
+            if (ssl->peerEd25519KeyPresent) {
+                WOLFSSL_MSG("Doing ED25519 peer cert verify");
+
+                ret = Ed25519Verify(ssl, input + args->idx, args->sz,
+                    args->sigData, args->sigDataSz,
+                    ssl->peerEd25519Key,
+                #ifdef HAVE_PK_CALLBACKS
+                    &ssl->buffers.peerEd25519Key
+                #else
+                    NULL
+                #endif
+                );
+            }
+        #endif
+
+            /* Check for error */
+            if (ret != 0) {
+                goto exit_dcv;
+            }
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_VERIFY;
+        } /* case TLS_ASYNC_DO */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_VERIFY:
+        {
+        #ifndef NO_RSA
+            if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
+                ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo,
+                                        args->output, args->sendSz);
+                if (ret != 0)
+                    goto exit_dcv;
+            }
+        #endif /* !NO_RSA */
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_FINALIZE;
+        } /* case TLS_ASYNC_VERIFY */
+        FALL_THROUGH;
+
+        case TLS_ASYNC_FINALIZE:
+        {
+            ssl->options.havePeerVerify = 1;
+
+            /* Set final index */
+            args->idx += args->sz;
+            *inOutIdx = args->idx;
+
+            /* Encryption is always on: add padding */
+            *inOutIdx += ssl->keys.padSz;
+
+            /* Advance state and proceed */
+            ssl->options.asyncState = TLS_ASYNC_END;
+        } /* case TLS_ASYNC_FINALIZE */
+
+        case TLS_ASYNC_END:
+        {
+            break;
+        }
+        default:
+            ret = INPUT_CASE_ERROR;
+    } /* switch(ssl->options.asyncState) */
+
+exit_dcv:
+
+    WOLFSSL_LEAVE("DoTls13CertificateVerify", ret);
+    WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* Handle async operation */
+    if (ret == WC_PENDING_E) {
+        /* Mark message as not recevied so it can process again */
+        ssl->msgsReceived.got_certificate_verify = 0;
+
+        return ret;
+    }
+    else
+#endif /* WOLFSSL_ASYNC_CRYPT */
+    if (ret != 0)
+        SendAlert(ssl, alert_fatal, decrypt_error);
+
+    /* Final cleanup */
+    FreeDcv13Args(ssl, args);
+    FreeKeyExchange(ssl);
+
+    return ret;
+}
+#endif /* !NO_RSA || HAVE_ECC */
+
+/* Parse and handle a TLS v1.3 Finished message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * size      Length of message data.
+ * totalSz   Length of remaining data in the message buffer.
+ * sniff     Indicates whether we are sniffing packets.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                           word32 size, word32 totalSz, int sniff)
+{
+    int    ret;
+    word32 finishedSz = 0;
+    byte*  secret;
+    byte   mac[WC_MAX_DIGEST_SIZE];
+
+    WOLFSSL_START(WC_FUNC_FINISHED_DO);
+    WOLFSSL_ENTER("DoTls13Finished");
+
+    /* check against totalSz */
+    if (*inOutIdx + size + ssl->keys.padSz > totalSz)
+        return BUFFER_E;
+
+    if (ssl->options.handShakeDone) {
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.client_write_MAC_secret;
+    }
+    else if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        /* All the handshake messages have been received to calculate
+         * client and server finished keys.
+         */
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret,
+                                   ssl->keys.server_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.server_write_MAC_secret;
+    }
+    else
+        secret = ssl->keys.client_write_MAC_secret;
+
+    ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
+    if (ret != 0)
+        return ret;
+    if (size != finishedSz)
+        return BUFFER_ERROR;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+    #endif
+
+    if (sniff == NO_SNIFF) {
+        /* Actually check verify data. */
+        if (XMEMCMP(input + *inOutIdx, mac, size) != 0){
+            WOLFSSL_MSG("Verify finished error on hashes");
+            SendAlert(ssl, alert_fatal, decrypt_error);
+            return VERIFY_FINISHED_ERROR;
+        }
+    }
+
+    /* Force input exhaustion at ProcessReply by consuming padSz. */
+    *inOutIdx += size + ssl->keys.padSz;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+                                                  !ssl->options.handShakeDone) {
+#ifdef WOLFSSL_EARLY_DATA
+        if (ssl->earlyData != no_early_data) {
+            if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0)
+                return ret;
+        }
+#endif
+        /* Setup keys for application data messages from client. */
+        if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+#endif
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone  = 1;
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13Finished", 0);
+    WOLFSSL_END(WC_FUNC_FINISHED_DO);
+
+    return 0;
+}
+#endif /* NO_CERTS */
+
+/* Send the TLS v1.3 Finished message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13Finished(WOLFSSL* ssl)
+{
+    int   sendSz;
+    int   finishedSz = ssl->specs.hash_size;
+    byte* input;
+    byte* output;
+    int   ret;
+    int   headerSz = HANDSHAKE_HEADER_SZ;
+    int   outputSz;
+    byte* secret;
+
+    WOLFSSL_START(WC_FUNC_FINISHED_SEND);
+    WOLFSSL_ENTER("SendTls13Finished");
+
+    outputSz = WC_MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA;
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    input = output + RECORD_HEADER_SZ;
+
+    AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
+
+    /* make finished hashes */
+    if (ssl->options.handShakeDone) {
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.client_write_MAC_secret;
+    }
+    else if (ssl->options.side == WOLFSSL_CLIENT_END)
+        secret = ssl->keys.client_write_MAC_secret;
+    else {
+        /* All the handshake messages have been done to calculate client and
+         * server finished keys.
+         */
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret,
+                                   ssl->keys.client_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret,
+                                   ssl->keys.server_write_MAC_secret);
+        if (ret != 0)
+            return ret;
+
+        secret = ssl->keys.server_write_MAC_secret;
+    }
+    ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL);
+    if (ret != 0)
+        return ret;
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, outputSz, input,
+                               headerSz + finishedSz, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    if (!ssl->options.resuming) {
+#ifndef NO_SESSION_CACHE
+        AddSession(ssl);    /* just try */
+#endif
+    }
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "Finished", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        /* Can send application data now. */
+        if ((ret = DeriveMasterSecret(ssl)) != 0)
+            return ret;
+#ifdef WOLFSSL_EARLY_DATA
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_SIDE_ONLY, 1))
+                                                                         != 0) {
+            return ret;
+        }
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY,
+                                       ssl->earlyData == no_early_data)) != 0) {
+            return ret;
+        }
+#else
+        if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE,
+                                                                     1)) != 0) {
+            return ret;
+        }
+#endif
+        if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+            return ret;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                                                  !ssl->options.handShakeDone) {
+#ifdef WOLFSSL_EARLY_DATA
+        if (ssl->earlyData != no_early_data) {
+            if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE,
+                                                                     1)) != 0) {
+                    return ret;
+            }
+        }
+#endif
+        /* Setup keys for application data messages. */
+        if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+            return ret;
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
+        if (ret != 0)
+            return ret;
+#endif
+    }
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_CLIENT_END) {
+        ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+        ssl->options.handShakeState = HANDSHAKE_DONE;
+        ssl->options.handShakeDone  = 1;
+    }
+#endif
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_SERVER_END) {
+        ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+    }
+#endif
+
+    if ((ret = SendBuffered(ssl)) != 0)
+        return ret;
+
+    WOLFSSL_LEAVE("SendTls13Finished", ret);
+    WOLFSSL_END(WC_FUNC_FINISHED_SEND);
+
+    return ret;
+}
+
+/* handle generation TLS v1.3 key_update (24) */
+/* Send the TLS v1.3 KeyUpdate message.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+static int SendTls13KeyUpdate(WOLFSSL* ssl)
+{
+    int    sendSz;
+    byte*  input;
+    byte*  output;
+    int    ret;
+    int    headerSz = HANDSHAKE_HEADER_SZ;
+    int    outputSz;
+    word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_KEY_UPDATE_SEND);
+    WOLFSSL_ENTER("SendTls13KeyUpdate");
+
+    outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA;
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
+        return ret;
+
+    /* get output buffer */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+    input = output + RECORD_HEADER_SZ;
+
+    AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl);
+
+    /* If:
+     *   1. I haven't sent a KeyUpdate requesting a response and
+     *   2. This isn't responding to peer KeyUpdate requiring a response then,
+     * I want a response.
+     */
+    ssl->keys.updateResponseReq = output[i++] =
+         !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond;
+    /* Sent response, no longer need to respond. */
+    ssl->keys.keyUpdateRespond = 0;
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, outputSz, input,
+                               headerSz + OPAQUE8_LEN, handshake, 0, 0, 0);
+    if (sendSz < 0)
+        return BUILD_MSG_ERROR;
+
+    #ifdef WOLFSSL_CALLBACKS
+        if (ssl->hsInfoOn) AddPacketName(ssl, "KeyUpdate");
+        if (ssl->toInfoOn) {
+            AddPacketInfo(ssl, "KeyUpdate", handshake, output, sendSz,
+                          WRITE_PROTO, ssl->heap);
+        }
+    #endif
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    ret = SendBuffered(ssl);
+    if (ret != 0 && ret != WANT_WRITE)
+        return ret;
+
+    /* Future traffic uses new encryption keys. */
+    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1))
+                                                                           != 0)
+        return ret;
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    WOLFSSL_LEAVE("SendTls13KeyUpdate", ret);
+    WOLFSSL_END(WC_FUNC_KEY_UPDATE_SEND);
+
+    return ret;
+}
+
+/* handle processing TLS v1.3 key_update (24) */
+/* Parse and handle a TLS v1.3 KeyUpdate message.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * totalSz   The length of the current handshake message.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                            word32 totalSz)
+{
+    int    ret;
+    word32 i = *inOutIdx;
+
+    WOLFSSL_START(WC_FUNC_KEY_UPDATE_DO);
+    WOLFSSL_ENTER("DoTls13KeyUpdate");
+
+    /* check against totalSz */
+    if (OPAQUE8_LEN != totalSz)
+        return BUFFER_E;
+
+    switch (input[i]) {
+        case update_not_requested:
+            /* This message in response to any oustanding request. */
+            ssl->keys.keyUpdateRespond = 0;
+            ssl->keys.updateResponseReq = 0;
+            break;
+        case update_requested:
+            /* New key update requiring a response. */
+            ssl->keys.keyUpdateRespond = 1;
+            break;
+        default:
+            return INVALID_PARAMETER;
+            break;
+    }
+
+    /* Move index to byte after message. */
+    *inOutIdx += totalSz;
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    /* Future traffic uses new decryption keys. */
+    if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1))
+                                                                         != 0) {
+        return ret;
+    }
+    if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    if (ssl->keys.keyUpdateRespond)
+        return SendTls13KeyUpdate(ssl);
+
+    WOLFSSL_LEAVE("DoTls13KeyUpdate", ret);
+    WOLFSSL_END(WC_FUNC_KEY_UPDATE_DO);
+
+    return 0;
+}
+
+#ifdef WOLFSSL_EARLY_DATA
+#ifndef NO_WOLFSSL_CLIENT
+/* Send the TLS v1.3 EndOfEarlyData message to indicate that there will be no
+ * more early application data.
+ * The encryption key now changes to the pre-calculated handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+static int SendTls13EndOfEarlyData(WOLFSSL* ssl)
+{
+    byte*  output;
+    int    ret;
+    int    sendSz;
+    word32 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_SEND);
+    WOLFSSL_ENTER("SendTls13EndOfEarlyData");
+
+    length = 0;
+    sendSz = idx + length + MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, end_of_early_data, ssl);
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 1, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
+        return ret;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret);
+    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_SEND);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+/* handle processing of TLS 1.3 end_of_early_data (5) */
+/* Parse the TLS v1.3 EndOfEarlyData message that indicates that there will be
+ * no more early application data.
+ * The decryption key now changes to the pre-calculated handshake key.
+ *
+ * ssl  The SSL/TLS object.
+ * returns 0 on success and otherwise failure.
+ */
+static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input,
+                                 word32* inOutIdx, word32 size)
+{
+    int    ret;
+    word32 begin = *inOutIdx;
+
+    (void)input;
+
+    WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_DO);
+    WOLFSSL_ENTER("DoTls13EndOfEarlyData");
+
+    if ((*inOutIdx - begin) != size)
+        return BUFFER_ERROR;
+
+    if (ssl->earlyData == no_early_data) {
+        WOLFSSL_MSG("EndOfEarlyData recieved unexpectedly");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    ssl->earlyData = done_early_data;
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY);
+
+    WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret);
+    WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO);
+
+    return ret;
+}
+#endif /* !NO_WOLFSSL_SERVER */
+#endif /* WOLFSSL_EARLY_DATA */
+
+#ifndef NO_WOLFSSL_CLIENT
+/* Handle a New Session Ticket handshake message.
+ * Message contains the information required to perform resumption.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the message buffer of Finished.
+ *           On exit, the index of byte after the Finished message and padding.
+ * size      The length of the current handshake message.
+ * retuns 0 on success, otherwise failure.
+ */
+static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
+                                   word32* inOutIdx, word32 size)
+{
+#ifdef HAVE_SESSION_TICKET
+    int    ret;
+    word32 begin = *inOutIdx;
+    word32 lifetime;
+    word32 ageAdd;
+    word16 length;
+    word32 now;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    const byte*  nonce;
+    byte         nonceLength;
+#endif
+
+    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO);
+    WOLFSSL_ENTER("DoTls13NewSessionTicket");
+
+    /* Lifetime hint. */
+    if ((*inOutIdx - begin) + SESSION_HINT_SZ > size)
+        return BUFFER_ERROR;
+    ato32(input + *inOutIdx, &lifetime);
+    *inOutIdx += SESSION_HINT_SZ;
+    if (lifetime > MAX_LIFETIME)
+        return SERVER_HINT_ERROR;
+
+    /* Age add. */
+    if ((*inOutIdx - begin) + SESSION_ADD_SZ > size)
+        return BUFFER_ERROR;
+    ato32(input + *inOutIdx, &ageAdd);
+    *inOutIdx += SESSION_ADD_SZ;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Ticket nonce. */
+    if ((*inOutIdx - begin) + 1 > size)
+        return BUFFER_ERROR;
+    nonceLength = input[*inOutIdx];
+    if (nonceLength > MAX_TICKET_NONCE_SZ) {
+        WOLFSSL_MSG("Nonce length not supported");
+        return INVALID_PARAMETER;
+    }
+    *inOutIdx += 1;
+    if ((*inOutIdx - begin) + nonceLength > size)
+        return BUFFER_ERROR;
+    nonce = input + *inOutIdx;
+    *inOutIdx += nonceLength;
+#endif
+
+    /* Ticket length. */
+    if ((*inOutIdx - begin) + LENGTH_SZ > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += LENGTH_SZ;
+    if ((*inOutIdx - begin) + length > size)
+        return BUFFER_ERROR;
+
+    if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
+        return ret;
+    *inOutIdx += length;
+
+    now = TimeNowInMilliseconds();
+    if (now == (word32)GETTIME_ERROR)
+        return now;
+    /* Copy in ticket data (server identity). */
+    ssl->timeout                = lifetime;
+    ssl->session.timeout        = lifetime;
+    ssl->session.cipherSuite0   = ssl->options.cipherSuite0;
+    ssl->session.cipherSuite    = ssl->options.cipherSuite;
+    ssl->session.ticketSeen     = now;
+    ssl->session.ticketAdd      = ageAdd;
+    #ifdef WOLFSSL_EARLY_DATA
+    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    #endif
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    ssl->session.ticketNonce.len = nonceLength;
+    if (nonceLength > 0)
+        XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength);
+#endif
+    ssl->session.namedGroup     = ssl->namedGroup;
+
+    if ((*inOutIdx - begin) + EXTS_SZ > size)
+        return BUFFER_ERROR;
+    ato16(input + *inOutIdx, &length);
+    *inOutIdx += EXTS_SZ;
+    if ((*inOutIdx - begin) + length != size)
+        return BUFFER_ERROR;
+    #ifdef WOLFSSL_EARLY_DATA
+    ret = TLSX_Parse(ssl, (byte *)input + (*inOutIdx), length, session_ticket,
+                     NULL);
+    if (ret != 0)
+        return ret;
+    #endif
+    *inOutIdx += length;
+
+    #ifndef NO_SESSION_CACHE
+    AddSession(ssl);
+    #endif
+
+    /* Always encrypted. */
+    *inOutIdx += ssl->keys.padSz;
+
+    ssl->expect_session_ticket = 0;
+#else
+    (void)ssl;
+    (void)input;
+
+    WOLFSSL_ENTER("DoTls13NewSessionTicket");
+
+    *inOutIdx += size + ssl->keys.padSz;
+#endif /* HAVE_SESSION_TICKET */
+
+    WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0);
+    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_DO);
+
+    return 0;
+}
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    #ifdef HAVE_SESSION_TICKET
+
+#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+/* Offset of the MAC size in the finished message. */
+#define FINISHED_MSG_SIZE_OFFSET    3
+
+/* Calculate the resumption secret which includes the unseen client finished
+ * message.
+ *
+ * ssl  The SSL/TLS object.
+ * retuns 0 on success, otherwise failure.
+ */
+static int ExpectedResumptionSecret(WOLFSSL* ssl)
+{
+    int         ret;
+    word32      finishedSz = 0;
+    byte        mac[WC_MAX_DIGEST_SIZE];
+    Digest      digest;
+    static byte header[] = { 0x14, 0x00, 0x00, 0x00 };
+
+    /* Copy the running hash so we cna restore it after. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    }
+
+    /* Generate the Client's Finished message and hash it. */
+    ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac,
+                                  &finishedSz);
+    if (ret != 0)
+        return ret;
+    header[FINISHED_MSG_SIZE_OFFSET] = finishedSz;
+#ifdef WOLFSSL_EARLY_DATA
+    if (ssl->earlyData != no_early_data) {
+        static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 };
+        ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
+        if (ret != 0)
+            return ret;
+    }
+#endif
+    if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0)
+        return ret;
+    if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0)
+        return ret;
+
+    if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0)
+        return ret;
+
+    /* Restore the hash inline with currently seen messages. */
+    switch (ssl->specs.mac_algorithm) {
+    #ifndef NO_SHA256
+        case sha256_mac:
+            ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_SHA384
+        case sha384_mac:
+            ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    #ifdef WOLFSSL_TLS13_SHA512
+        case sha512_mac:
+            ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
+    }
+
+    return ret;
+}
+#endif
+
+/* Send New Session Ticket handshake message.
+ * Message contains the information required to perform resumption.
+ *
+ * ssl  The SSL/TLS object.
+ * retuns 0 on success, otherwise failure.
+ */
+static int SendTls13NewSessionTicket(WOLFSSL* ssl)
+{
+    byte*  output;
+    int    ret;
+    int    sendSz;
+    word16 extSz;
+    word32 length;
+    word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+    WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_SEND);
+    WOLFSSL_ENTER("SendTls13NewSessionTicket");
+
+#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+    if (!ssl->msgsReceived.got_finished) {
+        if ((ret = ExpectedResumptionSecret(ssl)) != 0)
+            return ret;
+    }
+#endif
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Start ticket nonce at 0 and go up to 255. */
+    if (ssl->session.ticketNonce.len == 0) {
+        ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ;
+        ssl->session.ticketNonce.data[0] = 0;
+    }
+    else
+        ssl->session.ticketNonce.data[0]++;
+#endif
+
+    if (!ssl->options.noTicketTls13) {
+        if ((ret = CreateTicket(ssl)) != 0)
+            return ret;
+    }
+
+#ifdef WOLFSSL_EARLY_DATA
+    ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz;
+    if (ssl->session.maxEarlyDataSz > 0)
+        TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz);
+    extSz = 0;
+    ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz);
+    if (ret != 0)
+        return ret;
+#else
+    extSz = EXTS_SZ;
+#endif
+
+    /* Lifetime | Age Add | Ticket | Extensions */
+    length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ +
+             ssl->session.ticketLen + extSz;
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    /* Nonce */
+    length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ;
+#endif
+    sendSz = idx + length + MAX_MSG_EXTRA;
+
+    /* Check buffers are big enough and grow if needed. */
+    if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
+        return ret;
+
+    /* Get position in output buffer to write new message to. */
+    output = ssl->buffers.outputBuffer.buffer +
+             ssl->buffers.outputBuffer.length;
+
+    /* Put the record and handshake headers on. */
+    AddTls13Headers(output, length, session_ticket, ssl);
+
+    /* Lifetime hint */
+    c32toa(ssl->ctx->ticketHint, output + idx);
+    idx += SESSION_HINT_SZ;
+    /* Age add - obfuscator */
+    c32toa(ssl->session.ticketAdd, output + idx);
+    idx += SESSION_ADD_SZ;
+
+#ifndef WOLFSSL_TLS13_DRAFT_18
+    output[idx++] = ssl->session.ticketNonce.len;
+    output[idx++] = ssl->session.ticketNonce.data[0];
+#endif
+
+    /* length */
+    c16toa(ssl->session.ticketLen, output + idx);
+    idx += LENGTH_SZ;
+    /* ticket */
+    XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
+    idx += ssl->session.ticketLen;
+
+#ifdef WOLFSSL_EARLY_DATA
+    extSz = 0;
+    ret = TLSX_WriteResponse(ssl, output + idx, session_ticket, &extSz);
+    if (ret != 0)
+        return ret;
+    idx += extSz;
+#else
+    /* No extension support - empty extensions. */
+    c16toa(0, output + idx);
+    idx += EXTS_SZ;
+#endif
+
+    ssl->options.haveSessionId = 1;
+
+#ifndef NO_SESSION_CACHE
+    AddSession(ssl);
+#endif
+
+    /* This message is always encrypted. */
+    sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ,
+                               idx - RECORD_HEADER_SZ, handshake, 0, 0, 0);
+    if (sendSz < 0)
+        return sendSz;
+
+    ssl->buffers.outputBuffer.length += sendSz;
+
+    if (!ssl->options.groupMessages)
+        ret = SendBuffered(ssl);
+
+    WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0);
+    WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_SEND);
+
+    return ret;
+}
+    #endif /* HAVE_SESSION_TICKET */
+#endif /* NO_WOLFSSL_SERVER */
+
+/* Make sure no duplicates, no fast forward, or other problems
+ *
+ * ssl   The SSL/TLS object.
+ * type  Type of handshake message received.
+ * returns 0 on success, otherwise failure.
+ */
+static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
+{
+    /* verify not a duplicate, mark received, check state */
+    switch (type) {
+
+#ifndef NO_WOLFSSL_SERVER
+        case client_hello:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_MSG("ClientHello received by client");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) {
+                WOLFSSL_MSG("ClientHello received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_client_hello == 2) {
+                WOLFSSL_MSG("Too many ClientHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_client_hello++;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case server_hello:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("ServerHello received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #ifdef WOLFSSL_TLS13_DRAFT_18
+            if (ssl->msgsReceived.got_server_hello) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello = 1;
+        #else
+            if (ssl->msgsReceived.got_server_hello == 2) {
+                WOLFSSL_MSG("Duplicate ServerHello received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_server_hello++;
+        #endif
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case session_ticket:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("NewSessionTicket received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("NewSessionTicket received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            ssl->msgsReceived.got_session_ticket = 1;
+
+            break;
+#endif
+
+#ifndef NO_WOLFSSL_SERVER
+    #ifdef WOLFSSL_EARLY_DATA
+        case end_of_early_data:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                WOLFSSL_MSG("EndOfEarlyData received by client");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("EndOfEarlyData received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("EndOfEarlyData received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_end_of_early_data == 1) {
+                WOLFSSL_MSG("Too many EndOfEarlyData received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_end_of_early_data++;
+
+            break;
+    #endif
+#endif
+
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    #ifndef NO_WOLFSSL_CLIENT
+        case hello_retry_request:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("HelloRetryRequest received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("HelloRetryRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_hello_retry_request) {
+                WOLFSSL_MSG("Duplicate HelloRetryRequest received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_hello_retry_request = 1;
+
+            break;
+    #endif
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+        case encrypted_extensions:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("EncryptedExtensions received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+            if (ssl->options.serverState != SERVER_HELLO_COMPLETE) {
+                WOLFSSL_MSG("EncryptedExtensions received out of order");
+                return OUT_OF_ORDER_E;
+            }
+            if (ssl->msgsReceived.got_encrypted_extensions) {
+                WOLFSSL_MSG("Duplicate EncryptedExtensions received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_encrypted_extensions = 1;
+
+            break;
+#endif
+
+        case certificate:
+    #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                WOLFSSL_MSG("Certificate received out of order - Client");
+                return OUT_OF_ORDER_E;
+            }
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            /* Server's authenticating with PSK must not send this. */
+            if (ssl->options.side == WOLFSSL_CLIENT_END &&
+                             ssl->options.serverState == SERVER_CERT_COMPLETE &&
+                             ssl->arrays->psk_keySz != 0) {
+                WOLFSSL_MSG("Certificate received while using PSK");
+                return SANITY_MSG_E;
+            }
+        #endif
+    #endif
+    #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END &&
+                ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                WOLFSSL_MSG("Certificate received out of order - Server");
+                return OUT_OF_ORDER_E;
+            }
+    #endif
+            if (ssl->msgsReceived.got_certificate) {
+                WOLFSSL_MSG("Duplicate Certificate received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate = 1;
+
+            break;
+
+#ifndef NO_WOLFSSL_CLIENT
+        case certificate_request:
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                WOLFSSL_MSG("CertificateRequest received by server");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                WOLFSSL_MSG("CertificateRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+        #else
+            if (ssl->options.serverState !=
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
+                       (ssl->options.serverState != SERVER_FINISHED_COMPLETE ||
+                        ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) {
+                WOLFSSL_MSG("CertificateRequest received out of order");
+                return OUT_OF_ORDER_E;
+            }
+        #endif
+        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+            /* Server's authenticating with PSK must not send this. */
+            if (ssl->options.serverState ==
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE &&
+                                                  ssl->arrays->psk_keySz != 0) {
+                WOLFSSL_MSG("CertificateRequset received while using PSK");
+                return SANITY_MSG_E;
+            }
+        #endif
+        #ifndef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (ssl->msgsReceived.got_certificate_request) {
+                WOLFSSL_MSG("Duplicate CertificateRequest received");
+                return DUPLICATE_MSG_E;
+            }
+        #endif
+            ssl->msgsReceived.got_certificate_request = 1;
+
+            break;
+#endif
+
+        case certificate_verify:
+    #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (ssl->options.serverState != SERVER_CERT_COMPLETE) {
+                    WOLFSSL_MSG("No Cert before CertVerify");
+                    return OUT_OF_ORDER_E;
+                }
+            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+                /* Server's authenticating with PSK must not send this. */
+                if (ssl->options.serverState == SERVER_CERT_COMPLETE &&
+                                                  ssl->arrays->psk_keySz != 0) {
+                    WOLFSSL_MSG("CertificateVerify received while using PSK");
+                    return SANITY_MSG_E;
+                }
+            #endif
+            }
+    #endif
+    #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                    WOLFSSL_MSG("CertificateVerify received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("CertificateVerify before ClientHello done");
+                    return OUT_OF_ORDER_E;
+                }
+                if (!ssl->msgsReceived.got_certificate) {
+                    WOLFSSL_MSG("No Cert before CertificateVerify");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+    #endif
+            if (ssl->msgsReceived.got_certificate_verify) {
+                WOLFSSL_MSG("Duplicate CertificateVerify received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_certificate_verify = 1;
+
+            break;
+
+        case finished:
+        #ifndef NO_WOLFSSL_CLIENT
+            if (ssl->options.side == WOLFSSL_CLIENT_END) {
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.serverState <
+                                         SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+            }
+        #endif
+        #ifndef NO_WOLFSSL_SERVER
+            if (ssl->options.side == WOLFSSL_SERVER_END) {
+                if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+                if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    WOLFSSL_MSG("Finished received out of order");
+                    return OUT_OF_ORDER_E;
+                }
+            #ifdef WOLFSSL_EARLY_DATA
+                if (ssl->earlyData == process_early_data) {
+                    return OUT_OF_ORDER_E;
+                }
+            #endif
+            }
+        #endif
+            if (ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("Duplicate Finished received");
+                return DUPLICATE_MSG_E;
+            }
+            ssl->msgsReceived.got_finished = 1;
+
+            break;
+
+        case key_update:
+            if (!ssl->msgsReceived.got_finished) {
+                WOLFSSL_MSG("No KeyUpdate before Finished");
+                return OUT_OF_ORDER_E;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("Unknown message type");
+            return SANITY_MSG_E;
+    }
+
+    return 0;
+}
+
+/* Handle a type of handshake message that has been received.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the buffer of the current message.
+ *           On exit, the index into the buffer of the next message.
+ * size      The length of the current handshake message.
+ * totalSz   Length of remaining data in the message buffer.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                            byte type, word32 size, word32 totalSz)
+{
+    int ret = 0;
+    word32 inIdx = *inOutIdx;
+
+    (void)totalSz;
+
+    WOLFSSL_ENTER("DoTls13HandShakeMsgType");
+
+    /* make sure can read the message */
+    if (*inOutIdx + size > totalSz)
+        return INCOMPLETE_DATA;
+
+    /* sanity check msg received */
+    if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) {
+        WOLFSSL_MSG("Sanity Check on handshake message type received failed");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return ret;
+    }
+
+#ifdef WOLFSSL_CALLBACKS
+    /* add name later, add on record and handshake header part back on */
+    if (ssl->toInfoOn) {
+        int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+        AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add,
+                      size + add, READ_PROTO, ssl->heap);
+        AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+    }
+#endif
+
+    if (ssl->options.handShakeState == HANDSHAKE_DONE &&
+            type != session_ticket && type != certificate_request &&
+            type != certificate && type != key_update) {
+        WOLFSSL_MSG("HandShake message after handshake complete");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_CLIENT_END &&
+               ssl->options.serverState == NULL_STATE &&
+               type != server_hello && type != hello_retry_request) {
+        WOLFSSL_MSG("First server message not server hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    if (ssl->options.side == WOLFSSL_SERVER_END &&
+               ssl->options.clientState == NULL_STATE && type != client_hello) {
+        WOLFSSL_MSG("First client message not client hello");
+        SendAlert(ssl, alert_fatal, unexpected_message);
+        return OUT_OF_ORDER_E;
+    }
+
+    /* above checks handshake state */
+    switch (type) {
+#ifndef NO_WOLFSSL_CLIENT
+    /* Messages only recieved by client. */
+    #ifdef WOLFSSL_TLS13_DRAFT_18
+    case hello_retry_request:
+        WOLFSSL_MSG("processing hello rety request");
+        ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size);
+        break;
+    #endif
+
+    case server_hello:
+        WOLFSSL_MSG("processing server hello");
+        ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type);
+        break;
+
+    case encrypted_extensions:
+        WOLFSSL_MSG("processing encrypted extensions");
+        ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size);
+        break;
+
+    #ifndef NO_CERTS
+    case certificate_request:
+        WOLFSSL_MSG("processing certificate request");
+        ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size);
+        break;
+    #endif
+
+    case session_ticket:
+        WOLFSSL_MSG("processing new session ticket");
+        ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size);
+        break;
+#endif /* !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    /* Messages only recieved by server. */
+    case client_hello:
+        WOLFSSL_MSG("processing client hello");
+        ret = DoTls13ClientHello(ssl, input, inOutIdx, size);
+        break;
+
+    #ifdef WOLFSSL_EARLY_DATA
+    case end_of_early_data:
+        WOLFSSL_MSG("processing end of early data");
+        ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size);
+        break;
+    #endif
+#endif /* !NO_WOLFSSL_SERVER */
+
+    /* Messages recieved by both client and server. */
+#ifndef NO_CERTS
+    case certificate:
+        WOLFSSL_MSG("processing certificate");
+        ret = DoTls13Certificate(ssl, input, inOutIdx, size);
+        break;
+#endif
+
+#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
+    case certificate_verify:
+        WOLFSSL_MSG("processing certificate verify");
+        ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size);
+        break;
+#endif /* !NO_RSA || HAVE_ECC */
+
+    case finished:
+        WOLFSSL_MSG("processing finished");
+        ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF);
+        break;
+
+    case key_update:
+        WOLFSSL_MSG("processing finished");
+        ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size);
+        break;
+
+    default:
+        WOLFSSL_MSG("Unknown handshake message type");
+        ret = UNKNOWN_HANDSHAKE_TYPE;
+        break;
+    }
+
+    /* reset error */
+    if (ret == 0 && ssl->error == WC_PENDING_E)
+        ssl->error = 0;
+
+    if (ret == 0 && type != client_hello && type != session_ticket &&
+                                                           type != key_update) {
+        ret = HashInput(ssl, input + inIdx, size);
+    }
+
+    if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA)
+        SendAlert(ssl, alert_fatal, decode_error);
+    else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR ||
+                        ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA ||
+                        ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) {
+        SendAlert(ssl, alert_fatal, illegal_parameter);
+    }
+
+    if (ssl->options.tls1_3) {
+        /* Need to hash input message before deriving secrets. */
+    #ifndef NO_WOLFSSL_CLIENT
+        if (ssl->options.side == WOLFSSL_CLIENT_END) {
+            if (type == server_hello) {
+                if ((ret = DeriveEarlySecret(ssl)) != 0)
+                    return ret;
+                if ((ret = DeriveHandshakeSecret(ssl)) != 0)
+                    return ret;
+
+                if ((ret = DeriveTls13Keys(ssl, handshake_key,
+                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                    return ret;
+                }
+        #ifdef WOLFSSL_EARLY_DATA
+                if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
+                    return ret;
+        #else
+                if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
+                    return ret;
+        #endif
+            }
+
+            if (type == finished) {
+                if ((ret = DeriveMasterSecret(ssl)) != 0)
+                    return ret;
+        #ifdef WOLFSSL_EARLY_DATA
+                if ((ret = DeriveTls13Keys(ssl, traffic_key,
+                                       ENCRYPT_AND_DECRYPT_SIDE,
+                                       ssl->earlyData == no_early_data)) != 0) {
+                    return ret;
+                }
+        #else
+                if ((ret = DeriveTls13Keys(ssl, traffic_key,
+                                           ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
+                    return ret;
+                }
+        #endif
+            }
+        #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+            if (type == certificate_request &&
+                                ssl->options.handShakeState == HANDSHAKE_DONE) {
+                /* reset handshake states */
+                ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+                ssl->options.connectState  = FIRST_REPLY_DONE;
+                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
+
+                if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS)
+                    ret = POST_HAND_AUTH_ERROR;
+            }
+        #endif
+        }
+    #endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+        if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) {
+            ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
+            if (ret != 0)
+                return ret;
+        }
+    #endif
+#endif /* NO_WOLFSSL_SERVER */
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    /* if async, offset index so this msg will be processed again */
+    if (ret == WC_PENDING_E && *inOutIdx > 0) {
+        *inOutIdx -= HANDSHAKE_HEADER_SZ;
+    }
+#endif
+
+    WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret);
+    return ret;
+}
+
+
+/* Handle a handshake message that has been received.
+ *
+ * ssl       The SSL/TLS object.
+ * input     The message buffer.
+ * inOutIdx  On entry, the index into the buffer of the current message.
+ *           On exit, the index into the buffer of the next message.
+ * totalSz   Length of remaining data in the message buffer.
+ * returns 0 on success and otherwise failure.
+ */
+int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+                        word32 totalSz)
+{
+    int    ret = 0;
+    word32 inputLength;
+
+    WOLFSSL_ENTER("DoTls13HandShakeMsg()");
+
+    if (ssl->arrays == NULL) {
+        byte   type;
+        word32 size;
+
+        if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                       totalSz);
+    }
+
+    inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz;
+
+    /* If there is a pending fragmented handshake message,
+     * pending message size will be non-zero. */
+    if (ssl->arrays->pendingMsgSz == 0) {
+        byte   type;
+        word32 size;
+
+        if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0)
+            return PARSE_ERROR;
+
+        /* Cap the maximum size of a handshake message to something reasonable.
+         * By default is the maximum size of a certificate message assuming
+         * nine 2048-bit RSA certificates in the chain. */
+        if (size > MAX_HANDSHAKE_SZ) {
+            WOLFSSL_MSG("Handshake message too large");
+            return HANDSHAKE_SIZE_ERROR;
+        }
+
+        /* size is the size of the certificate message payload */
+        if (inputLength - HANDSHAKE_HEADER_SZ < size) {
+            ssl->arrays->pendingMsgType = type;
+            ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
+            ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
+                                                     ssl->heap,
+                                                     DYNAMIC_TYPE_ARRAYS);
+            if (ssl->arrays->pendingMsg == NULL)
+                return MEMORY_E;
+            XMEMCPY(ssl->arrays->pendingMsg,
+                    input + *inOutIdx - HANDSHAKE_HEADER_SZ,
+                    inputLength);
+            ssl->arrays->pendingMsgOffset = inputLength;
+            *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ;
+            return 0;
+        }
+
+        ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
+                                      totalSz);
+    }
+    else {
+        if (inputLength + ssl->arrays->pendingMsgOffset >
+                                                    ssl->arrays->pendingMsgSz) {
+            inputLength = ssl->arrays->pendingMsgSz -
+                                                  ssl->arrays->pendingMsgOffset;
+        }
+        XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
+                input + *inOutIdx, inputLength);
+        ssl->arrays->pendingMsgOffset += inputLength;
+        *inOutIdx += inputLength + ssl->keys.padSz;
+
+        if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
+        {
+            word32 idx = 0;
+            ret = DoTls13HandShakeMsgType(ssl,
+                                ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ,
+                                &idx, ssl->arrays->pendingMsgType,
+                                ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ,
+                                ssl->arrays->pendingMsgSz);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (ret == WC_PENDING_E) {
+                /* setup to process fragment again */
+                ssl->arrays->pendingMsgOffset -= inputLength;
+                *inOutIdx -= inputLength + ssl->keys.padSz;
+            }
+            else
+        #endif
+            {
+                XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
+                ssl->arrays->pendingMsg = NULL;
+                ssl->arrays->pendingMsgSz = 0;
+            }
+        }
+    }
+
+    WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret);
+    return ret;
+}
+
+#ifndef NO_WOLFSSL_CLIENT
+
+/* The client connecting to the server.
+ * The protocol version is expecting to be TLS v1.3.
+ * If the server downgrades, and older versions of the protocol are compiled
+ * in, the client will fallback to wolfSSL_connect().
+ * Please see note at top of README if you get an error from connect.
+ *
+ * ssl  The SSL/TLS object.
+ * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
+ * unrecoverable error occurs and 0 otherwise.
+ * For more error information use wolfSSL_get_error().
+ */
+int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
+{
+    WOLFSSL_ENTER("wolfSSL_connect_TLSv13()");
+
+    #ifdef HAVE_ERRNO_H
+    errno = 0;
+    #endif
+
+    if (ssl->options.side != WOLFSSL_CLIENT_END) {
+        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    if (ssl->buffers.outputBuffer.length > 0) {
+        if ((ssl->error = SendBuffered(ssl)) == 0) {
+            /* fragOffset is non-zero when sending fragments. On the last
+             * fragment, fragOffset is zero again, and the state can be
+             * advanced. */
+            if (ssl->fragOffset == 0) {
+                ssl->options.connectState++;
+                WOLFSSL_MSG("connect state: "
+                            "Advanced from last buffered fragment send");
+            }
+            else {
+                WOLFSSL_MSG("connect state: "
+                            "Not advanced, more fragments to send");
+            }
+        }
+        else {
+            WOLFSSL_ERROR(ssl->error);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    switch (ssl->options.connectState) {
+
+        case CONNECT_BEGIN:
+            /* Always send client hello first. */
+            if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.connectState = CLIENT_HELLO_SENT;
+            WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT");
+    #ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+        #endif
+                ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
+                return WOLFSSL_SUCCESS;
+            }
+    #endif
+            FALL_THROUGH;
+
+        case CLIENT_HELLO_SENT:
+            /* Get the response/s from the server. */
+            while (ssl->options.serverState <
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN:
+            if (ssl->options.certOnly)
+                return WOLFSSL_SUCCESS;
+
+            if (!ssl->options.tls1_3) {
+    #ifndef WOLFSSL_NO_TLS12
+                if (ssl->options.downgrade)
+                    return wolfSSL_connect(ssl);
+    #endif
+
+                WOLFSSL_MSG("Client using higher version, fatal error");
+                return VERSION_ERROR;
+            }
+
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+                if (!ssl->options.sentChangeCipher) {
+                    if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                    ssl->options.sentChangeCipher = 1;
+                }
+        #endif
+                /* Try again with different security parameters. */
+                if ((ssl->error = SendTls13ClientHello(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = HELLO_AGAIN_REPLY;
+            WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+            FALL_THROUGH;
+
+        case HELLO_AGAIN_REPLY:
+            /* Get the response/s from the server. */
+            while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.connectState = FIRST_REPLY_DONE;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_DONE:
+        #ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+                if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: end_of_early_data");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_FIRST;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FIRST:
+        #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+            if (!ssl->options.sentChangeCipher) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_SECOND;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_SECOND:
+        #ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                ssl->error = SendTls13Certificate(ssl);
+                if (ssl->error != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: certificate");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_THIRD;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_THIRD:
+        #ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                ssl->error = SendTls13CertificateVerify(ssl);
+                if (ssl->error != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                WOLFSSL_MSG("sent: certificate verify");
+            }
+        #endif
+
+            ssl->options.connectState = FIRST_REPLY_FOURTH;
+            WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH");
+            FALL_THROUGH;
+
+        case FIRST_REPLY_FOURTH:
+            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            WOLFSSL_MSG("sent: finished");
+
+            ssl->options.connectState = FINISHED_DONE;
+            WOLFSSL_MSG("connect state: FINISHED_DONE");
+            FALL_THROUGH;
+
+        case FINISHED_DONE:
+        #ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb != NULL) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+        #endif /* NO_HANDSHAKE_DONE_CB */
+
+            WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default:
+            WOLFSSL_MSG("Unknown connect state ERROR");
+            return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+    }
+}
+#endif
+
+#if defined(WOLFSSL_SEND_HRR_COOKIE)
+/* Send a cookie with the HelloRetryRequest to avoid storing state.
+ *
+ * ssl       SSL/TLS object.
+ * secret    Secret to use when generating integrity check for cookie.
+ *           A value of NULL indicates to generate a new random secret.
+ * secretSz  Size of secret data in bytes.
+ *           Use a value of 0 to indicate use of default size.
+ * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, SIDE_ERROR when
+ * called on a client; WOLFSSL_SUCCESS on success and otherwise failure.
+ */
+int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret,
+                            unsigned int secretSz)
+{
+    int ret;
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+ #ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    if (secretSz == 0) {
+    #if !defined(NO_SHA) && defined(NO_SHA256)
+        secretSz = WC_SHA_DIGEST_SIZE;
+    #endif /* NO_SHA */
+    #ifndef NO_SHA256
+        secretSz = WC_SHA256_DIGEST_SIZE;
+    #endif /* NO_SHA256 */
+    }
+
+    if (secretSz != ssl->buffers.tls13CookieSecret.length) {
+        byte* newSecret;
+
+        if (ssl->buffers.tls13CookieSecret.buffer != NULL) {
+            ForceZero(ssl->buffers.tls13CookieSecret.buffer,
+                      ssl->buffers.tls13CookieSecret.length);
+            XFREE(ssl->buffers.tls13CookieSecret.buffer,
+                  ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
+        }
+
+        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,
+                                   DYNAMIC_TYPE_COOKIE_PWD);
+        if (newSecret == NULL) {
+            ssl->buffers.tls13CookieSecret.buffer = NULL;
+            ssl->buffers.tls13CookieSecret.length = 0;
+            WOLFSSL_MSG("couldn't allocate new cookie secret");
+            return MEMORY_ERROR;
+        }
+        ssl->buffers.tls13CookieSecret.buffer = newSecret;
+        ssl->buffers.tls13CookieSecret.length = secretSz;
+    }
+
+    /* If the supplied secret is NULL, randomly generate a new secret. */
+    if (secret == NULL) {
+        ret = wc_RNG_GenerateBlock(ssl->rng,
+                               ssl->buffers.tls13CookieSecret.buffer, secretSz);
+        if (ret < 0)
+            return ret;
+    }
+    else
+        XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz);
+
+    ssl->options.sendCookie = 1;
+
+    ret = WOLFSSL_SUCCESS;
+#else
+    (void)secret;
+    (void)secretSz;
+
+    ret = SIDE_ERROR;
+#endif
+
+    return ret;
+}
+#endif
+
+/* Create a key share entry from group.
+ * Generates a key pair.
+ *
+ * ssl    The SSL/TLS object.
+ * group  The named group.
+ * returns 0 on success, otherwise failure.
+ */
+int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
+    if (ret != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Send no key share entries - use HelloRetryRequest to negotiate shared group.
+ *
+ * ssl    The SSL/TLS object.
+ * returns 0 on success, otherwise failure.
+ */
+int wolfSSL_NoKeyShares(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ret = TLSX_KeyShare_Empty(ssl);
+    if (ret != 0)
+        return ret;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Do not send a ticket after TLS v1.3 handshake for resumption.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
+ */
+int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+#ifdef HAVE_SESSION_TICKET
+    ctx->noTicketTls13 = 1;
+#endif
+
+    return 0;
+}
+
+/* Do not send a ticket after TLS v1.3 handshake for resumption.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on
+ * a client and 0 on success.
+ */
+int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+#ifdef HAVE_SESSION_TICKET
+    ssl->options.noTicketTls13 = 1;
+#endif
+
+    return 0;
+}
+
+/* Disallow (EC)DHE key exchange when using pre-shared keys.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL and 0 on success.
+ */
+int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+
+    ctx->noPskDheKe = 1;
+
+    return 0;
+}
+
+/* Disallow (EC)DHE key exchange when using pre-shared keys.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on
+ * success.
+ */
+int wolfSSL_no_dhe_psk(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    ssl->options.noPskDheKe = 1;
+
+    return 0;
+}
+
+/* Update the keys for encryption and decryption.
+ * If using non-blocking I/O and WOLFSSL_ERROR_WANT_WRITE is returned then
+ * calling wolfSSL_write() will have the message sent when ready.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write,
+ * WOLFSSL_SUCCESS on success and otherwise failure.
+ */
+int wolfSSL_update_keys(WOLFSSL* ssl)
+{
+    int ret;
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    ret = SendTls13KeyUpdate(ssl);
+    if (ret == WANT_WRITE)
+        ret = WOLFSSL_ERROR_WANT_WRITE;
+    else if (ret == 0)
+        ret = WOLFSSL_SUCCESS;
+    return ret;
+}
+
+#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+/* Allow post-handshake authentication in TLS v1.3 connections.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a client and
+ * 0 on success.
+ */
+int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ctx->postHandshakeAuth = 1;
+
+    return 0;
+}
+
+/* Allow post-handshake authentication in TLS v1.3 connection.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a client and 0 on success.
+ */
+int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    ssl->options.postHandshakeAuth = 1;
+
+    return 0;
+}
+
+/* Request a certificate of the client.
+ * Can be called any time after handshake completion.
+ * A maximum of 256 requests can be sent on a connection.
+ *
+ * ssl  SSL/TLS object.
+ */
+int wolfSSL_request_certificate(WOLFSSL* ssl)
+{
+    int         ret;
+#ifndef NO_WOLFSSL_SERVER
+    CertReqCtx* certReqCtx;
+#endif
+
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+    if (ssl->options.handShakeState != HANDSHAKE_DONE)
+        return NOT_READY_ERROR;
+    if (!ssl->options.postHandshakeAuth)
+        return POST_HAND_AUTH_ERROR;
+
+    certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx), ssl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (certReqCtx == NULL)
+        return MEMORY_E;
+    XMEMSET(certReqCtx, 0, sizeof(CertReqCtx));
+    certReqCtx->next = ssl->certReqCtx;
+    certReqCtx->len = 1;
+    if (certReqCtx->next != NULL)
+        certReqCtx->ctx = certReqCtx->next->ctx + 1;
+    ssl->certReqCtx = certReqCtx;
+
+    ssl->msgsReceived.got_certificate = 0;
+    ssl->msgsReceived.got_certificate_verify = 0;
+    ssl->msgsReceived.got_finished = 0;
+
+    ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len);
+    if (ret == WANT_WRITE)
+        ret = WOLFSSL_ERROR_WANT_WRITE;
+    else if (ret == 0)
+        ret = WOLFSSL_SUCCESS;
+#else
+    ret = SIDE_ERROR;
+#endif
+
+    return ret;
+}
+#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */
+
+#if !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
+/* Get the preferred key exchange group.
+ *
+ * ssl  The SSL/TLS object.
+ * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3,
+ * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete
+ * and group number on success.
+ */
+int wolfSSL_preferred_group(WOLFSSL* ssl)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+    if (ssl->options.handShakeState != HANDSHAKE_DONE)
+        return NOT_READY_ERROR;
+
+    /* Return supported groups only. */
+    return TLSX_SupportedCurve_Preferred(ssl, 1);
+#else
+    return SIDE_ERROR;
+#endif
+}
+#endif
+
+/* Sets the key exchange groups in rank order on a context.
+ *
+ * ctx     SSL/TLS context object.
+ * groups  Array of groups.
+ * count   Number of groups in array.
+ * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or
+ * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count)
+{
+    int i;
+
+    if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < count; i++)
+        ctx->group[i] = (word16)groups[i];
+    ctx->numGroups = (byte)count;
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Sets the key exchange groups in rank order.
+ *
+ * ssl     SSL/TLS object.
+ * groups  Array of groups.
+ * count   Number of groups in array.
+ * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or
+ * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
+ */
+int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count)
+{
+    int i;
+
+    if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+    for (i = 0; i < count; i++)
+        ssl->group[i] = (word16)groups[i];
+    ssl->numGroups = (byte)count;
+
+    return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+/* The server accepting a connection from a client.
+ * The protocol version is expecting to be TLS v1.3.
+ * If the client downgrades, and older versions of the protocol are compiled
+ * in, the server will fallback to wolfSSL_accept().
+ * Please see note at top of README if you get an error from accept.
+ *
+ * ssl  The SSL/TLS object.
+ * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when
+ * unrecoverable error occurs and 0 otherwise.
+ * For more error information use wolfSSL_get_error().
+ */
+int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
+{
+    word16 havePSK = 0;
+    WOLFSSL_ENTER("SSL_accept_TLSv13()");
+
+#ifdef HAVE_ERRNO_H
+    errno = 0;
+#endif
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    havePSK = ssl->options.havePSK;
+#endif
+    (void)havePSK;
+
+    if (ssl->options.side != WOLFSSL_SERVER_END) {
+        WOLFSSL_ERROR(ssl->error = SIDE_ERROR);
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+#ifndef NO_CERTS
+    /* allow no private key if using PK callbacks and CB is set */
+    if (!havePSK) {
+        if (!ssl->buffers.certificate ||
+            !ssl->buffers.certificate->buffer) {
+
+            WOLFSSL_MSG("accept error: server cert required");
+            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+            return WOLFSSL_FATAL_ERROR;
+        }
+
+    #ifdef HAVE_PK_CALLBACKS
+        if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
+            WOLFSSL_MSG("Using PK for server private key");
+        }
+        else
+    #endif
+        if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+            WOLFSSL_MSG("accept error: server key required");
+            WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+#endif
+
+    if (ssl->buffers.outputBuffer.length > 0) {
+        if ((ssl->error = SendBuffered(ssl)) == 0) {
+            /* fragOffset is non-zero when sending fragments. On the last
+             * fragment, fragOffset is zero again, and the state can be
+             * advanced. */
+            if (ssl->fragOffset == 0) {
+                ssl->options.acceptState++;
+                WOLFSSL_MSG("accept state: "
+                            "Advanced from last buffered fragment send");
+            }
+            else {
+                WOLFSSL_MSG("accept state: "
+                            "Not advanced, more fragments to send");
+            }
+        }
+        else {
+            WOLFSSL_ERROR(ssl->error);
+            return WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    switch (ssl->options.acceptState) {
+
+        case TLS13_ACCEPT_BEGIN :
+            /* get client_hello */
+            while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                if ((ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_CLIENT_HELLO_DONE :
+#ifdef WOLFSSL_TLS13_DRAFT_18
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
+#else
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendTls13ServerHello(ssl,
+                                                   hello_retry_request)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE :
+    #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+            }
+    #endif
+            ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+            FALL_THROUGH;
+#endif
+
+        case TLS13_ACCEPT_FIRST_REPLY_DONE :
+            if (ssl->options.serverState ==
+                                          SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
+                ssl->options.clientState = NULL_STATE;
+                while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
+                    if ((ssl->error = ProcessReply(ssl)) < 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_SECOND_REPLY_DONE :
+            if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = TLS13_SERVER_HELLO_SENT;
+            WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
+            FALL_THROUGH;
+
+        case TLS13_SERVER_HELLO_SENT :
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && \
+                                         defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+            if (!ssl->options.sentChangeCipher) {
+                if ((ssl->error = SendChangeCipher(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+                ssl->options.sentChangeCipher = 1;
+            }
+    #endif
+
+            ssl->options.acceptState = TLS13_ACCEPT_THIRD_REPLY_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_THIRD_REPLY_DONE :
+            if (!ssl->options.noPskDheKe) {
+                ssl->error = TLSX_KeyShare_DeriveSecret(ssl);
+                if (ssl->error != 0)
+                    return WOLFSSL_FATAL_ERROR;
+            }
+
+            if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+            ssl->options.acceptState = TLS13_SERVER_EXTENSIONS_SENT;
+            WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT");
+            FALL_THROUGH;
+
+        case TLS13_SERVER_EXTENSIONS_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming) {
+                if (ssl->options.verifyPeer) {
+                    ssl->error = SendTls13CertificateRequest(ssl, NULL, 0);
+                    if (ssl->error != 0) {
+                        WOLFSSL_ERROR(ssl->error);
+                        return WOLFSSL_FATAL_ERROR;
+                    }
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_REQ_SENT;
+            WOLFSSL_MSG("accept state CERT_REQ_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_REQ_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                if ((ssl->error = SendTls13Certificate(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_SENT;
+            WOLFSSL_MSG("accept state CERT_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_SENT :
+#ifndef NO_CERTS
+            if (!ssl->options.resuming && ssl->options.sendVerify) {
+                if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif
+            ssl->options.acceptState = TLS13_CERT_VERIFY_SENT;
+            WOLFSSL_MSG("accept state CERT_VERIFY_SENT");
+            FALL_THROUGH;
+
+        case TLS13_CERT_VERIFY_SENT :
+            if ((ssl->error = SendTls13Finished(ssl)) != 0) {
+                WOLFSSL_ERROR(ssl->error);
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT");
+#ifdef WOLFSSL_EARLY_DATA
+            if (ssl->earlyData != no_early_data) {
+                ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
+                return WOLFSSL_SUCCESS;
+            }
+#endif
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_FINISHED_SENT :
+#ifdef HAVE_SESSION_TICKET
+    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+            if (!ssl->options.resuming && !ssl->options.verifyPeer &&
+                !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
+                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+    #endif
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TLS13_PRE_TICKET_SENT;
+            WOLFSSL_MSG("accept state  TICKET_SENT");
+            FALL_THROUGH;
+
+        case TLS13_PRE_TICKET_SENT :
+            while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+                if ( (ssl->error = ProcessReply(ssl)) < 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+
+            ssl->options.acceptState = TLS13_ACCEPT_FINISHED_DONE;
+            WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+            FALL_THROUGH;
+
+        case TLS13_ACCEPT_FINISHED_DONE :
+#ifdef HAVE_SESSION_TICKET
+    #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
+            if (!ssl->options.verifyPeer) {
+            }
+            else
+    #endif
+            if (!ssl->options.resuming &&
+                !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
+                if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
+                    WOLFSSL_ERROR(ssl->error);
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* HAVE_SESSION_TICKET */
+            ssl->options.acceptState = TLS13_TICKET_SENT;
+            WOLFSSL_MSG("accept state TICKET_SENT");
+            FALL_THROUGH;
+
+        case TLS13_TICKET_SENT :
+#ifndef NO_HANDSHAKE_DONE_CB
+            if (ssl->hsDoneCb) {
+                int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
+                if (cbret < 0) {
+                    ssl->error = cbret;
+                    WOLFSSL_MSG("HandShake Done Cb don't continue error");
+                    return WOLFSSL_FATAL_ERROR;
+                }
+            }
+#endif /* NO_HANDSHAKE_DONE_CB */
+
+            WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS);
+            return WOLFSSL_SUCCESS;
+
+        default :
+            WOLFSSL_MSG("Unknown accept state ERROR");
+            return WOLFSSL_FATAL_ERROR;
+    }
+}
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+/* Sets the maximum amount of early data that can be seen by server when using
+ * session tickets for resumption.
+ * A value of zero indicates no early data is to be sent by client using session
+ * tickets.
+ *
+ * ctx  The SSL/TLS CTX object.
+ * sz   Maximum size of the early data.
+ * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
+ * 0 on success.
+ */
+int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz)
+{
+    if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
+        return BAD_FUNC_ARG;
+    if (ctx->method->side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    ctx->maxEarlyDataSz = sz;
+
+    return 0;
+}
+
+/* Sets the maximum amount of early data that can be seen by server when using
+ * session tickets for resumption.
+ * A value of zero indicates no early data is to be sent by client using session
+ * tickets.
+ *
+ * ssl  The SSL/TLS object.
+ * sz   Maximum size of the early data.
+ * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
+ * SIDE_ERROR when not a server and 0 on success.
+ */
+int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz)
+{
+    if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    ssl->options.maxEarlyDataSz = sz;
+
+    return 0;
+}
+
+/* Write early data to the server.
+ *
+ * ssl    The SSL/TLS object.
+ * data   Early data to write
+ * sz     The size of the eary data in bytes.
+ * outSz  The number of early data bytes written.
+ * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
+ * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
+ * early data bytes written.
+ */
+int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("SSL_write_early_data()");
+
+    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+#ifndef NO_WOLFSSL_CLIENT
+    if (ssl->options.side == WOLFSSL_SERVER_END)
+        return SIDE_ERROR;
+
+    if (ssl->options.handShakeState == NULL_STATE) {
+        ssl->earlyData = expecting_early_data;
+        ret = wolfSSL_connect_TLSv13(ssl);
+        if (ret <= 0)
+            return WOLFSSL_FATAL_ERROR;
+    }
+    if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) {
+        ret = SendData(ssl, data, sz);
+        if (ret > 0)
+            *outSz = ret;
+    }
+#else
+    return SIDE_ERROR;
+#endif
+
+    WOLFSSL_LEAVE("SSL_write_early_data()", ret);
+
+    if (ret < 0)
+        ret = WOLFSSL_FATAL_ERROR;
+    return ret;
+}
+
+/* Read the any early data from the client.
+ *
+ * ssl    The SSL/TLS object.
+ * data   Buffer to put the early data into.
+ * sz     The size of the buffer in bytes.
+ * outSz  The number of early data bytes read.
+ * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative;
+ * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of
+ * early data bytes read.
+ */
+int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz)
+{
+    int ret = 0;
+
+    WOLFSSL_ENTER("wolfSSL_read_early_data()");
+
+
+    if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL)
+        return BAD_FUNC_ARG;
+    if (!IsAtLeastTLSv1_3(ssl->version))
+        return BAD_FUNC_ARG;
+
+#ifndef NO_WOLFSSL_SERVER
+    if (ssl->options.side == WOLFSSL_CLIENT_END)
+        return SIDE_ERROR;
+
+    if (ssl->options.handShakeState == NULL_STATE) {
+        ssl->earlyData = expecting_early_data;
+        ret = wolfSSL_accept_TLSv13(ssl);
+        if (ret <= 0)
+            return WOLFSSL_FATAL_ERROR;
+    }
+    if (ssl->options.handShakeState == SERVER_FINISHED_COMPLETE) {
+        ret = ReceiveData(ssl, (byte*)data, sz, FALSE);
+        if (ret > 0)
+            *outSz = ret;
+        if (ssl->error == ZERO_RETURN)
+            ssl->error = WOLFSSL_ERROR_NONE;
+    }
+    else
+        ret = 0;
+#else
+    return SIDE_ERROR;
+#endif
+
+    WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret);
+
+    if (ret < 0)
+        ret = WOLFSSL_FATAL_ERROR;
+    return ret;
+}
+#endif
+
+#undef ERROR_OUT
+
+#endif /* !WOLFCRYPT_ONLY */
+
+#endif /* WOLFSSL_TLS13 */
+
--- a/src/wolfio.c	Tue Nov 19 14:32:16 2019 +0000
+++ b/src/wolfio.c	Wed Nov 20 13:27:48 2019 +0000
@@ -1,1862 +1,1862 @@
-/* wolfio.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-
-#ifdef _WIN32_WCE
-    /* On WinCE winsock2.h must be included before windows.h for socket stuff */
-    #include <winsock2.h>
-#endif
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfio.h>
-
-#if defined(HAVE_HTTP_CLIENT)
-    #include <stdlib.h>   /* atoi(), strtol() */
-#endif
-
-/*
-Possible IO enable options:
- * WOLFSSL_USER_IO:     Disables default Embed* callbacks and     default: off
-                        allows user to define their own using
-                        wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
- * USE_WOLFSSL_IO:      Enables the wolfSSL IO functions          default: off
- * HAVE_HTTP_CLIENT:    Enables HTTP client API's                 default: off
-                                     (unless HAVE_OCSP or HAVE_CRL_IO defined)
- * HAVE_IO_TIMEOUT:     Enables support for connect timeout       default: off
- */
-
-
-/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
-   automatic setting of default I/O functions EmbedSend() and EmbedReceive()
-   but they'll still need SetCallback xxx() at end of file
-*/
-
-#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
-
-/* Translates return codes returned from
- * send() and recv() if need be.
- */
-static WC_INLINE int TranslateReturnCode(int old, int sd)
-{
-    (void)sd;
-
-#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    if (old == 0) {
-        errno = SOCKET_EWOULDBLOCK;
-        return -1;  /* convert to BSD style wouldblock as error */
-    }
-
-    if (old < 0) {
-        errno = RTCS_geterror(sd);
-        if (errno == RTCSERR_TCP_CONN_CLOSING)
-            return 0;   /* convert to BSD style closing */
-        if (errno == RTCSERR_TCP_CONN_RLSD)
-            errno = SOCKET_ECONNRESET;
-        if (errno == RTCSERR_TCP_TIMED_OUT)
-            errno = SOCKET_EAGAIN;
-    }
-#endif
-
-    return old;
-}
-
-static WC_INLINE int wolfSSL_LastError(void)
-{
-#ifdef USE_WINDOWS_API
-    return WSAGetLastError();
-#elif defined(EBSNET)
-    return xn_getlasterror();
-#else
-    return errno;
-#endif
-}
-
-#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
-
-
-#ifdef OPENSSL_EXTRA
-/* Use the WOLFSSL read BIO for receiving data. This is set by the function
- * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
- *
- * ssl  WOLFSSL struct passed in that has this function set as the receive
- *      callback.
- * buf  buffer to fill with data read
- * sz   size of buf buffer
- * ctx  a user set context
- *
- * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
- */
-int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
-{
-    int recvd = WOLFSSL_CBIO_ERR_GENERAL;
-
-    WOLFSSL_ENTER("BioReceive");
-
-    if (ssl->biord == NULL) {
-        WOLFSSL_MSG("WOLFSSL biord not set");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    switch (ssl->biord->type) {
-        case WOLFSSL_BIO_MEMORY:
-        case WOLFSSL_BIO_BIO:
-            if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
-               return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-            recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
-            if (recvd <= 0) {
-                return WOLFSSL_CBIO_ERR_GENERAL;
-            }
-            break;
-
-       default:
-            WOLFSSL_MSG("This BIO type is unknown / unsupported");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    (void)ctx;
-    return recvd;
-}
-
-
-/* Use the WOLFSSL write BIO for sending data. This is set by the function
- * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
- *
- * ssl  WOLFSSL struct passed in that has this function set as the send callback.
- * buf  buffer with data to write out
- * sz   size of buf buffer
- * ctx  a user set context
- *
- * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
- */
-int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
-    int sent = WOLFSSL_CBIO_ERR_GENERAL;
-
-    if (ssl->biowr == NULL) {
-        WOLFSSL_MSG("WOLFSSL biowr not set\n");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    switch (ssl->biowr->type) {
-        case WOLFSSL_BIO_MEMORY:
-        case WOLFSSL_BIO_BIO:
-            sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
-            if (sent < 0) {
-                return WOLFSSL_CBIO_ERR_GENERAL;
-            }
-            break;
-
-        default:
-            WOLFSSL_MSG("This BIO type is unknown / unsupported");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-    (void)ctx;
-
-    return sent;
-}
-#endif
-
-
-#ifdef USE_WOLFSSL_IO
-
-/* The receive embedded callback
- *  return : nb bytes read, or error
- */
-int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    int sd = *(int*)ctx;
-    int recvd;
-
-    recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
-    if (recvd < 0) {
-        int err = wolfSSL_LastError();
-        WOLFSSL_MSG("Embed Receive error");
-
-        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
-            WOLFSSL_MSG("\tWould block");
-            return WOLFSSL_CBIO_ERR_WANT_READ;
-        }
-        else if (err == SOCKET_ECONNRESET) {
-            WOLFSSL_MSG("\tConnection reset");
-            return WOLFSSL_CBIO_ERR_CONN_RST;
-        }
-        else if (err == SOCKET_EINTR) {
-            WOLFSSL_MSG("\tSocket interrupted");
-            return WOLFSSL_CBIO_ERR_ISR;
-        }
-        else if (err == SOCKET_ECONNABORTED) {
-            WOLFSSL_MSG("\tConnection aborted");
-            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
-        }
-        else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-    else if (recvd == 0) {
-        WOLFSSL_MSG("Embed receive connection closed");
-        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
-    }
-
-    return recvd;
-}
-
-/* The send embedded callback
- *  return : nb bytes sent, or error
- */
-int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
-    int sd = *(int*)ctx;
-    int sent;
-
-    sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
-    if (sent < 0) {
-        int err = wolfSSL_LastError();
-        WOLFSSL_MSG("Embed Send error");
-
-        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
-            WOLFSSL_MSG("\tWould Block");
-            return WOLFSSL_CBIO_ERR_WANT_WRITE;
-        }
-        else if (err == SOCKET_ECONNRESET) {
-            WOLFSSL_MSG("\tConnection reset");
-            return WOLFSSL_CBIO_ERR_CONN_RST;
-        }
-        else if (err == SOCKET_EINTR) {
-            WOLFSSL_MSG("\tSocket interrupted");
-            return WOLFSSL_CBIO_ERR_ISR;
-        }
-        else if (err == SOCKET_EPIPE) {
-            WOLFSSL_MSG("\tSocket EPIPE");
-            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
-        }
-        else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return sent;
-}
-
-
-#ifdef WOLFSSL_DTLS
-
-#include <wolfssl/wolfcrypt/sha.h>
-
-#define SENDTO_FUNCTION sendto
-#define RECVFROM_FUNCTION recvfrom
-
-
-/* The receive embedded callback
- *  return : nb bytes read, or error
- */
-int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
-    int recvd;
-    int err;
-    int sd = dtlsCtx->rfd;
-    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
-    SOCKADDR_S peer;
-    XSOCKLENT peerSz = sizeof(peer);
-
-    WOLFSSL_ENTER("EmbedReceiveFrom()");
-
-    if (ssl->options.handShakeDone)
-        dtls_timeout = 0;
-
-    if (!wolfSSL_get_using_nonblock(ssl)) {
-        #ifdef USE_WINDOWS_API
-            DWORD timeout = dtls_timeout * 1000;
-        #else
-            struct timeval timeout;
-            XMEMSET(&timeout, 0, sizeof(timeout));
-            timeout.tv_sec = dtls_timeout;
-        #endif
-        if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
-                       sizeof(timeout)) != 0) {
-                WOLFSSL_MSG("setsockopt rcvtimeo failed");
-        }
-    }
-
-    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
-                                  (SOCKADDR*)&peer, &peerSz);
-
-    recvd = TranslateReturnCode(recvd, sd);
-
-    if (recvd < 0) {
-        err = wolfSSL_LastError();
-        WOLFSSL_MSG("Embed Receive From error");
-
-        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
-            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
-                WOLFSSL_MSG("\tWould block");
-                return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-            else {
-                WOLFSSL_MSG("\tSocket timeout");
-                return WOLFSSL_CBIO_ERR_TIMEOUT;
-            }
-        }
-        else if (err == SOCKET_ECONNRESET) {
-            WOLFSSL_MSG("\tConnection reset");
-            return WOLFSSL_CBIO_ERR_CONN_RST;
-        }
-        else if (err == SOCKET_EINTR) {
-            WOLFSSL_MSG("\tSocket interrupted");
-            return WOLFSSL_CBIO_ERR_ISR;
-        }
-        else if (err == SOCKET_ECONNREFUSED) {
-            WOLFSSL_MSG("\tConnection refused");
-            return WOLFSSL_CBIO_ERR_WANT_READ;
-        }
-        else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-    else {
-        if (dtlsCtx->peer.sz > 0
-                && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
-                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
-            WOLFSSL_MSG("    Ignored packet from invalid peer");
-            return WOLFSSL_CBIO_ERR_WANT_READ;
-        }
-    }
-
-    return recvd;
-}
-
-
-/* The send embedded callback
- *  return : nb bytes sent, or error
- */
-int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
-    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
-    int sd = dtlsCtx->wfd;
-    int sent;
-    int len = sz;
-    int err;
-
-    WOLFSSL_ENTER("EmbedSendTo()");
-
-    sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
-                                (const SOCKADDR*)dtlsCtx->peer.sa,
-                                dtlsCtx->peer.sz);
-
-    sent = TranslateReturnCode(sent, sd);
-
-    if (sent < 0) {
-        err = wolfSSL_LastError();
-        WOLFSSL_MSG("Embed Send To error");
-
-        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
-            WOLFSSL_MSG("\tWould Block");
-            return WOLFSSL_CBIO_ERR_WANT_WRITE;
-        }
-        else if (err == SOCKET_ECONNRESET) {
-            WOLFSSL_MSG("\tConnection reset");
-            return WOLFSSL_CBIO_ERR_CONN_RST;
-        }
-        else if (err == SOCKET_EINTR) {
-            WOLFSSL_MSG("\tSocket interrupted");
-            return WOLFSSL_CBIO_ERR_ISR;
-        }
-        else if (err == SOCKET_EPIPE) {
-            WOLFSSL_MSG("\tSocket EPIPE");
-            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
-        }
-        else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return sent;
-}
-
-
-#ifdef WOLFSSL_MULTICAST
-
-/* The alternate receive embedded callback for Multicast
- *  return : nb bytes read, or error
- */
-int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
-    int recvd;
-    int err;
-    int sd = dtlsCtx->rfd;
-
-    WOLFSSL_ENTER("EmbedReceiveFromMcast()");
-
-    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
-
-    recvd = TranslateReturnCode(recvd, sd);
-
-    if (recvd < 0) {
-        err = wolfSSL_LastError();
-        WOLFSSL_MSG("Embed Receive From error");
-
-        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
-            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
-                WOLFSSL_MSG("\tWould block");
-                return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-            else {
-                WOLFSSL_MSG("\tSocket timeout");
-                return WOLFSSL_CBIO_ERR_TIMEOUT;
-            }
-        }
-        else if (err == SOCKET_ECONNRESET) {
-            WOLFSSL_MSG("\tConnection reset");
-            return WOLFSSL_CBIO_ERR_CONN_RST;
-        }
-        else if (err == SOCKET_EINTR) {
-            WOLFSSL_MSG("\tSocket interrupted");
-            return WOLFSSL_CBIO_ERR_ISR;
-        }
-        else if (err == SOCKET_ECONNREFUSED) {
-            WOLFSSL_MSG("\tConnection refused");
-            return WOLFSSL_CBIO_ERR_WANT_READ;
-        }
-        else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return recvd;
-}
-#endif /* WOLFSSL_MULTICAST */
-
-
-/* The DTLS Generate Cookie callback
- *  return : number of bytes copied into buf, or error
- */
-int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
-{
-    int sd = ssl->wfd;
-    SOCKADDR_S peer;
-    XSOCKLENT peerSz = sizeof(peer);
-    byte digest[WC_SHA256_DIGEST_SIZE];
-    int  ret = 0;
-
-    (void)ctx;
-
-    XMEMSET(&peer, 0, sizeof(peer));
-    if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
-        WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
-        return GEN_COOKIE_E;
-    }
-
-    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
-    if (ret != 0)
-        return ret;
-
-    if (sz > WC_SHA256_DIGEST_SIZE)
-        sz = WC_SHA256_DIGEST_SIZE;
-    XMEMCPY(buf, digest, sz);
-
-    return sz;
-}
-
-#ifdef WOLFSSL_SESSION_EXPORT
-
-    /* get the peer information in human readable form (ip, port, family)
-     * default function assumes BSD sockets
-     * can be overriden with wolfSSL_CTX_SetIOGetPeer
-     */
-    int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
-                                                 unsigned short* port, int* fam)
-    {
-        SOCKADDR_S peer;
-        word32     peerSz;
-        int        ret;
-
-        if (ssl == NULL || ip == NULL || ipSz == NULL ||
-                                                  port == NULL || fam == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        /* get peer information stored in ssl struct */
-        peerSz = sizeof(SOCKADDR_S);
-        if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
-                                                               != WOLFSSL_SUCCESS) {
-            return ret;
-        }
-
-        /* extract family, ip, and port */
-        *fam = ((SOCKADDR_S*)&peer)->ss_family;
-        switch (*fam) {
-            case WOLFSSL_IP4:
-                if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
-                                                           ip, *ipSz) == NULL) {
-                    WOLFSSL_MSG("XINET_NTOP error");
-                    return SOCKET_ERROR_E;
-                }
-                *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
-                break;
-
-            case WOLFSSL_IP6:
-            #ifdef WOLFSSL_IPV6
-                if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
-                                                           ip, *ipSz) == NULL) {
-                    WOLFSSL_MSG("XINET_NTOP error");
-                    return SOCKET_ERROR_E;
-                }
-                *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
-            #endif /* WOLFSSL_IPV6 */
-                break;
-
-            default:
-                WOLFSSL_MSG("Unknown family type");
-                return SOCKET_ERROR_E;
-        }
-        ip[*ipSz - 1] = '\0'; /* make sure has terminator */
-        *ipSz = (word16)XSTRLEN(ip);
-
-        return WOLFSSL_SUCCESS;
-    }
-
-    /* set the peer information in human readable form (ip, port, family)
-     * default function assumes BSD sockets
-     * can be overriden with wolfSSL_CTX_SetIOSetPeer
-     */
-    int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
-                                                   unsigned short port, int fam)
-    {
-        int    ret;
-        SOCKADDR_S addr;
-
-        /* sanity checks on arguments */
-        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
-            return BAD_FUNC_ARG;
-        }
-
-        addr.ss_family = fam;
-        switch (addr.ss_family) {
-            case WOLFSSL_IP4:
-                if (XINET_PTON(addr.ss_family, ip,
-                                     &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
-                    WOLFSSL_MSG("XINET_PTON error");
-                    return SOCKET_ERROR_E;
-                }
-                ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
-
-                /* peer sa is free'd in SSL_ResourceFree */
-                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
-                                          sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
-                    WOLFSSL_MSG("Import DTLS peer info error");
-                    return ret;
-                }
-                break;
-
-            case WOLFSSL_IP6:
-            #ifdef WOLFSSL_IPV6
-                if (XINET_PTON(addr.ss_family, ip,
-                                   &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
-                    WOLFSSL_MSG("XINET_PTON error");
-                    return SOCKET_ERROR_E;
-                }
-                ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
-
-                /* peer sa is free'd in SSL_ResourceFree */
-                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
-                                         sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
-                    WOLFSSL_MSG("Import DTLS peer info error");
-                    return ret;
-                }
-            #endif /* WOLFSSL_IPV6 */
-                break;
-
-            default:
-                WOLFSSL_MSG("Unknown address family");
-                return BUFFER_E;
-        }
-
-        return WOLFSSL_SUCCESS;
-    }
-#endif /* WOLFSSL_SESSION_EXPORT */
-#endif /* WOLFSSL_DTLS */
-
-
-int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
-{
-    int recvd;
-
-    recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
-    recvd = TranslateReturnCode(recvd, sd);
-
-    return recvd;
-}
-
-int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
-{
-    int sent;
-
-    sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
-    sent = TranslateReturnCode(sent, sd);
-
-    return sent;
-}
-
-#endif /* USE_WOLFSSL_IO */
-
-
-#ifdef HAVE_HTTP_CLIENT
-
-#ifndef HAVE_IO_TIMEOUT
-    #define io_timeout_sec 0
-#else
-
-    #ifndef DEFAULT_TIMEOUT_SEC
-        #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
-    #endif
-
-    static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
-
-    void wolfIO_SetTimeout(int to_sec)
-    {
-        io_timeout_sec = to_sec;
-    }
-
-    int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
-    {
-        int ret = 0;
-
-    #ifdef USE_WINDOWS_API
-        unsigned long blocking = non_blocking;
-        ret = ioctlsocket(sockfd, FIONBIO, &blocking);
-        if (ret == SOCKET_ERROR)
-            ret = -1;
-    #else
-        ret = fcntl(sockfd, F_GETFL, 0);
-        if (ret >= 0) {
-            if (non_blocking)
-                ret |= O_NONBLOCK;
-            else
-                ret &= ~O_NONBLOCK;
-            ret = fcntl(sockfd, F_SETFL, ret);
-        }
-    #endif
-        if (ret < 0) {
-            WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
-        }
-
-        return ret;
-    }
-
-    int wolfIO_Select(SOCKET_T sockfd, int to_sec)
-    {
-        fd_set rfds, wfds;
-        int nfds = 0;
-        struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
-        int ret;
-
-    #ifndef USE_WINDOWS_API
-        nfds = (int)sockfd + 1;
-    #endif
-
-        FD_ZERO(&rfds);
-        FD_SET(sockfd, &rfds);
-        wfds = rfds;
-
-        ret = select(nfds, &rfds, &wfds, NULL, &timeout);
-        if (ret == 0) {
-        #ifdef DEBUG_HTTP
-            printf("Timeout: %d\n", ret);
-        #endif
-            return HTTP_TIMEOUT;
-        }
-        else if (ret > 0) {
-            if (FD_ISSET(sockfd, &wfds)) {
-                if (!FD_ISSET(sockfd, &rfds)) {
-                    return 0;
-                }
-            }
-        }
-        return SOCKET_ERROR_E;
-    }
-#endif /* HAVE_IO_TIMEOUT */
-
-static int wolfIO_Word16ToString(char* d, word16 number)
-{
-    int i = 0;
-    word16 order = 10000;
-    word16 digit;
-
-    if (d == NULL)
-        return i;
-
-    if (number == 0)
-        d[i++] = '0';
-    else {
-        while (order) {
-            digit = number / order;
-            if (i > 0 || digit != 0)
-                d[i++] = (char)digit + '0';
-            if (digit != 0)
-                number %= digit * order;
-
-            order = (order > 1) ? order / 10 : 0;
-        }
-    }
-    d[i] = 0; /* null terminate */
-
-    return i;
-}
-
-int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
-{
-#ifdef HAVE_SOCKADDR
-    int ret = 0;
-    SOCKADDR_S addr;
-    int sockaddr_len = sizeof(SOCKADDR_IN);
-#ifdef HAVE_GETADDRINFO
-    ADDRINFO hints;
-    ADDRINFO* answer = NULL;
-    char strPort[6];
-#else
-    HOSTENT* entry;
-    SOCKADDR_IN *sin;
-#endif
-
-    XMEMSET(&addr, 0, sizeof(addr));
-
-#ifdef WOLFIO_DEBUG
-    printf("TCP Connect: %s:%d\n", ip, port);
-#endif
-
-#ifdef HAVE_GETADDRINFO
-    XMEMSET(&hints, 0, sizeof(hints));
-    hints.ai_family = AF_UNSPEC;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_protocol = IPPROTO_TCP;
-
-    if (wolfIO_Word16ToString(strPort, port) == 0) {
-        WOLFSSL_MSG("invalid port number for responder");
-        return -1;
-    }
-
-    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
-        WOLFSSL_MSG("no addr info for responder");
-        return -1;
-    }
-
-    sockaddr_len = answer->ai_addrlen;
-    XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
-    freeaddrinfo(answer);
-#else
-    entry = gethostbyname(ip);
-    sin = (SOCKADDR_IN *)&addr;
-
-    if (entry) {
-        sin->sin_family = AF_INET;
-        sin->sin_port = XHTONS(port);
-        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
-    }
-    else {
-        WOLFSSL_MSG("no addr info for responder");
-        return -1;
-    }
-#endif
-
-    *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
-
-#ifdef USE_WINDOWS_API
-    if (*sockfd == INVALID_SOCKET) {
-        WOLFSSL_MSG("bad socket fd, out of fds?");
-        return -1;
-    }
-#else
-     if (*sockfd < 0) {
-         WOLFSSL_MSG("bad socket fd, out of fds?");
-         return -1;
-     }
-#endif
-
-#ifdef HAVE_IO_TIMEOUT
-    /* if timeout value provided then set socket non-blocking */
-    if (to_sec > 0) {
-        wolfIO_SetBlockingMode(*sockfd, 1);
-    }
-#else
-    (void)to_sec;
-#endif
-
-    ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
-#ifdef HAVE_IO_TIMEOUT
-    if (ret != 0) {
-        if ((errno == EINPROGRESS) && (to_sec > 0)) {
-            /* wait for connect to complete */
-            ret = wolfIO_Select(*sockfd, to_sec);
-
-            /* restore blocking mode */
-            wolfIO_SetBlockingMode(*sockfd, 0);
-        }
-    }
-#endif
-    if (ret != 0) {
-        WOLFSSL_MSG("Responder tcp connect failed");
-        return -1;
-    }
-    return ret;
-#else
-    (void)sockfd;
-    (void)ip;
-    (void)port;
-    (void)to_sec;
-    return -1;
-#endif /* HAVE_SOCKADDR */
-}
-
-#ifndef HTTP_SCRATCH_BUFFER_SIZE
-    #define HTTP_SCRATCH_BUFFER_SIZE 512
-#endif
-#ifndef MAX_URL_ITEM_SIZE
-    #define MAX_URL_ITEM_SIZE   80
-#endif
-
-int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
-    word16* outPort)
-{
-    int result = -1;
-
-    if (url == NULL || urlSz == 0) {
-        if (outName)
-            *outName = 0;
-        if (outPath)
-            *outPath = 0;
-        if (outPort)
-            *outPort = 0;
-    }
-    else {
-        int i, cur;
-
-        /* need to break the url down into scheme, address, and port */
-        /*     "http://example.com:8080/" */
-        /*     "http://[::1]:443/"        */
-        if (XSTRNCMP(url, "http://", 7) == 0) {
-            cur = 7;
-        } else cur = 0;
-
-        i = 0;
-        if (url[cur] == '[') {
-            cur++;
-            /* copy until ']' */
-            while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
-                if (outName)
-                    outName[i] = url[cur];
-                i++; cur++;
-            }
-            cur++; /* skip ']' */
-        }
-        else {
-            while (url[cur] != 0 && url[cur] != ':' &&
-                                           url[cur] != '/' && cur < urlSz) {
-                if (outName)
-                    outName[i] = url[cur];
-                i++; cur++;
-            }
-        }
-        if (outName)
-            outName[i] = 0;
-        /* Need to pick out the path after the domain name */
-
-        if (cur < urlSz && url[cur] == ':') {
-            char port[6];
-            int j;
-            word32 bigPort = 0;
-            i = 0;
-            cur++;
-            while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
-                    i < 6) {
-                port[i++] = url[cur++];
-            }
-
-            for (j = 0; j < i; j++) {
-                if (port[j] < '0' || port[j] > '9') return -1;
-                bigPort = (bigPort * 10) + (port[j] - '0');
-            }
-            if (outPort)
-                *outPort = (word16)bigPort;
-        }
-        else if (outPort)
-            *outPort = 80;
-
-
-        if (cur < urlSz && url[cur] == '/') {
-            i = 0;
-            while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
-                if (outPath)
-                    outPath[i] = url[cur];
-                i++; cur++;
-            }
-            if (outPath)
-                outPath[i] = 0;
-        }
-        else if (outPath) {
-            outPath[0] = '/';
-            outPath[1] = 0;
-        }
-
-        result = 0;
-    }
-
-    return result;
-}
-
-static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
-    int chunkSz, char* start, int len, int dynType, void* heap)
-{
-    byte* newRecvBuf = NULL;
-    int newRecvSz = *recvBufSz + chunkSz;
-    int pos = 0;
-
-    WOLFSSL_MSG("Processing HTTP response");
-#ifdef WOLFIO_DEBUG
-    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
-#endif
-
-    newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
-    if (newRecvBuf == NULL) {
-        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
-        return MEMORY_E;
-    }
-
-    /* if buffer already exists, then we are growing it */
-    if (*recvBuf) {
-        XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
-        XFREE(*recvBuf, heap, dynType);
-        pos += *recvBufSz;
-        *recvBuf = NULL;
-    }
-
-    /* copy the remainder of the httpBuf into the respBuf */
-    if (len != 0) {
-        XMEMCPY(&newRecvBuf[pos], start, len);
-        pos += len;
-    }
-
-    /* receive the remainder of chunk */
-    while (len < chunkSz) {
-        int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
-        if (rxSz > 0) {
-            len += rxSz;
-            pos += rxSz;
-        }
-        else {
-            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
-            XFREE(newRecvBuf, heap, dynType);
-            return -1;
-        }
-    }
-
-    *recvBuf = newRecvBuf;
-    *recvBufSz = newRecvSz;
-
-    return 0;
-}
-
-int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
-    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
-{
-    int result = 0;
-    int len = 0;
-    char *start, *end;
-    int respBufSz = 0;
-    int isChunked = 0, chunkSz = 0;
-    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
-                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
-                     phr_http_end
-    } state = phr_init;
-
-    *respBuf = NULL;
-    start = end = NULL;
-    do {
-        if (state == phr_get_chunk_data) {
-            /* get chunk of data */
-            result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
-                chunkSz, start, len, dynType, heap);
-
-            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
-            end = NULL;
-            len = 0;
-        }
-
-        /* read data if no \r\n or first time */
-        if (end == NULL) {
-            result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
-            if (result > 0) {
-                len += result;
-                start = (char*)httpBuf;
-                start[len] = 0;
-            }
-            else {
-                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
-                return -1;
-            }
-        }
-        end = XSTRSTR(start, "\r\n"); /* locate end */
-
-        /* handle incomplete rx */
-        if (end == NULL) {
-            if (len != 0)
-                XMEMMOVE(httpBuf, start, len);
-            start = end = NULL;
-        }
-        /* when start is "\r\n" */
-        else if (end == start) {
-            /* if waiting for end or need chunk len */
-            if (state == phr_wait_end || state == phr_get_chunk_len) {
-                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
-                len -= 2; start += 2; /* skip \r\n */
-             }
-             else {
-                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
-                return -1;
-             }
-        }
-        else {
-            *end = 0; /* null terminate */
-            len -= (int)(end - start) + 2;
-                /* adjust len to remove the first line including the /r/n */
-
-        #ifdef WOLFIO_DEBUG
-            printf("HTTP Resp: %s\n", start);
-        #endif
-
-            switch (state) {
-                case phr_init:
-                    if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
-                        start += 9;
-                        if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
-                            WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
-                            return -1;
-                        }
-                        state = phr_http_start;
-                    }
-                    break;
-                case phr_http_start:
-                case phr_have_length:
-                case phr_have_type:
-                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
-                        int i;
-
-                        start += 13;
-                        while (*start == ' ' && *start != '\0') start++;
-
-                        /* try and match against appStrList */
-                        i = 0;
-                        while (appStrList[i] != NULL) {
-                            if (XSTRNCASECMP(start, appStrList[i],
-                                                XSTRLEN(appStrList[i])) == 0) {
-                                break;
-                            }
-                            i++;
-                        }
-                        if (appStrList[i] == NULL) {
-                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
-                            return -1;
-                        }
-                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
-                    }
-                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
-                        start += 15;
-                        while (*start == ' ' && *start != '\0') start++;
-                        chunkSz = atoi(start);
-                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
-                    }
-                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
-                        start += 18;
-                        while (*start == ' ' && *start != '\0') start++;
-                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
-                            isChunked = 1;
-                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
-                        }
-                    }
-                    break;
-                case phr_get_chunk_len:
-                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
-                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
-                    break;
-                case phr_get_chunk_data:
-                    /* processing for chunk data done above, since \r\n isn't required */
-                case phr_wait_end:
-                case phr_http_end:
-                    /* do nothing */
-                    break;
-            } /* switch (state) */
-
-            /* skip to end plus \r\n */
-            start = end + 2;
-        }
-    } while (state != phr_http_end);
-
-    if (!isChunked) {
-        result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
-                                                    start, len, dynType, heap);
-    }
-
-    if (result >= 0) {
-        result = respBufSz;
-    }
-    else {
-        WOLFSSL_ERROR(result);
-    }
-
-    return result;
-}
-
-int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
-    const char* path, int pathLen, int reqSz, const char* contentType,
-    byte* buf, int bufSize)
-{
-    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
-    char reqSzStr[6];
-    char* req = (char*)buf;
-    const char* blankStr = " ";
-    const char* http11Str = " HTTP/1.1";
-    const char* hostStr = "\r\nHost: ";
-    const char* contentLenStr = "\r\nContent-Length: ";
-    const char* contentTypeStr = "\r\nContent-Type: ";
-    const char* doubleCrLfStr = "\r\n\r\n";
-    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
-        contentTypeStrLen, doubleCrLfStrLen;
-
-    reqTypeLen = (word32)XSTRLEN(reqType);
-    domainNameLen = (word32)XSTRLEN(domainName);
-    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
-    contentTypeLen = (word32)XSTRLEN(contentType);
-
-    blankStrLen = (word32)XSTRLEN(blankStr);
-    http11StrLen = (word32)XSTRLEN(http11Str);
-    hostStrLen = (word32)XSTRLEN(hostStr);
-    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
-    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
-    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
-
-    /* determine max length and check it */
-    maxLen =
-        reqTypeLen +
-        blankStrLen +
-        pathLen +
-        http11StrLen +
-        hostStrLen +
-        domainNameLen +
-        contentLenStrLen +
-        reqSzStrLen +
-        contentTypeStrLen +
-        contentTypeLen +
-        doubleCrLfStrLen +
-        1 /* null term */;
-    if (maxLen > (word32)bufSize)
-        return 0;
-
-    XSTRNCPY((char*)buf, reqType, reqTypeLen);
-    buf += reqTypeLen;
-    XSTRNCPY((char*)buf, blankStr, blankStrLen+1);
-    buf += blankStrLen;
-    XSTRNCPY((char*)buf, path, pathLen);
-    buf += pathLen;
-    XSTRNCPY((char*)buf, http11Str, http11StrLen+1);
-    buf += http11StrLen;
-    if (domainNameLen > 0) {
-        XSTRNCPY((char*)buf, hostStr, hostStrLen+1);
-        buf += hostStrLen;
-        XSTRNCPY((char*)buf, domainName, domainNameLen);
-        buf += domainNameLen;
-    }
-    if (reqSz > 0 && reqSzStrLen > 0) {
-        XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1);
-        buf += contentLenStrLen;
-        XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen);
-        buf += reqSzStrLen;
-    }
-    if (contentTypeLen > 0) {
-        XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1);
-        buf += contentTypeStrLen;
-        XSTRNCPY((char*)buf, contentType, contentTypeLen);
-        buf += contentTypeLen;
-    }
-    XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1);
-    buf += doubleCrLfStrLen;
-
-#ifdef WOLFIO_DEBUG
-    printf("HTTP %s: %s", reqType, req);
-#endif
-
-    /* calculate actual length based on original and new pointer */
-    return (int)((char*)buf - req);
-}
-
-
-#ifdef HAVE_OCSP
-
-int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
-                                    int ocspReqSz, byte* buf, int bufSize)
-{
-    return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
-        ocspReqSz, "application/ocsp-request", buf, bufSize);
-}
-
-/* return: >0 OCSP Response Size
- *         -1 error */
-int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
-                                       byte* httpBuf, int httpBufSz, void* heap)
-{
-    const char* appStrList[] = {
-        "application/ocsp-response",
-        NULL
-    };
-
-    return wolfIO_HttpProcessResponse(sfd, appStrList,
-        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
-}
-
-/* in default wolfSSL callback ctx is the heap pointer */
-int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
-                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
-{
-    SOCKET_T sfd = 0;
-    word16   port;
-    int      ret = -1;
-#ifdef WOLFSSL_SMALL_STACK
-    char*    path;
-    char*    domainName;
-#else
-    char     path[MAX_URL_ITEM_SIZE];
-    char     domainName[MAX_URL_ITEM_SIZE];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (path == NULL)
-        return MEMORY_E;
-
-    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (domainName == NULL) {
-        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    if (ocspReqBuf == NULL || ocspReqSz == 0) {
-        WOLFSSL_MSG("OCSP request is required for lookup");
-    }
-    else if (ocspRespBuf == NULL) {
-        WOLFSSL_MSG("Cannot save OCSP response");
-    }
-    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
-        WOLFSSL_MSG("Unable to decode OCSP URL");
-    }
-    else {
-        /* Note, the library uses the EmbedOcspRespFree() callback to
-         * free this buffer. */
-        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
-        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
-
-        if (httpBuf == NULL) {
-            WOLFSSL_MSG("Unable to create OCSP response buffer");
-        }
-        else {
-            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
-                                                            httpBuf, httpBufSz);
-
-            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
-            if ((ret != 0) || (sfd < 0)) {
-                WOLFSSL_MSG("OCSP Responder connection failed");
-            }
-            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
-                                                                    httpBufSz) {
-                WOLFSSL_MSG("OCSP http request failed");
-            }
-            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
-                                                                    ocspReqSz) {
-                WOLFSSL_MSG("OCSP ocsp request failed");
-            }
-            else {
-                ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
-                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
-            }
-
-            CloseSocket(sfd);
-            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-/* in default callback ctx is heap hint */
-void EmbedOcspRespFree(void* ctx, byte *resp)
-{
-    if (resp)
-        XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
-
-    (void)ctx;
-}
-#endif /* HAVE_OCSP */
-
-
-#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
-
-int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
-    const char* domainName, byte* buf, int bufSize)
-{
-    return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
-        buf, bufSize);
-}
-
-int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
-    int httpBufSz)
-{
-    int result;
-    byte *respBuf = NULL;
-
-    const char* appStrList[] = {
-        "application/pkix-crl",
-        "application/x-pkcs7-crl",
-        NULL
-    };
-
-    result = wolfIO_HttpProcessResponse(sfd, appStrList,
-        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
-    if (result >= 0) {
-        result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
-    }
-    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
-
-    return result;
-}
-
-int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
-{
-    SOCKET_T sfd = 0;
-    word16   port;
-    int      ret = -1;
-#ifdef WOLFSSL_SMALL_STACK
-    char*    domainName;
-#else
-    char     domainName[MAX_URL_ITEM_SIZE];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (domainName == NULL) {
-        return MEMORY_E;
-    }
-#endif
-
-    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
-        WOLFSSL_MSG("Unable to decode CRL URL");
-    }
-    else {
-        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
-        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, crl->heap,
-                                                              DYNAMIC_TYPE_CRL);
-        if (httpBuf == NULL) {
-            WOLFSSL_MSG("Unable to create CRL response buffer");
-        }
-        else {
-            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
-                httpBuf, httpBufSz);
-
-            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
-            if ((ret != 0) || (sfd < 0)) {
-                WOLFSSL_MSG("CRL connection failed");
-            }
-            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
-                                                                 != httpBufSz) {
-                WOLFSSL_MSG("CRL http get failed");
-            }
-            else {
-                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
-                                                      HTTP_SCRATCH_BUFFER_SIZE);
-            }
-
-            CloseSocket(sfd);
-            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-#endif /* HAVE_CRL && HAVE_CRL_IO */
-
-#endif /* HAVE_HTTP_CLIENT */
-
-
-
-WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
-{
-    ctx->CBIORecv = CBIORecv;
-    #ifdef OPENSSL_EXTRA
-    ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
-    #endif
-}
-
-
-WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
-{
-    ctx->CBIOSend = CBIOSend;
-    #ifdef OPENSSL_EXTRA
-    ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
-    #endif
-}
-
-
-WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
-{
-    ssl->IOCB_ReadCtx = rctx;
-}
-
-
-WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
-{
-    ssl->IOCB_WriteCtx = wctx;
-}
-
-
-WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->IOCB_ReadCtx;
-
-    return NULL;
-}
-
-
-WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->IOCB_WriteCtx;
-
-    return NULL;
-}
-
-
-WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
-{
-    ssl->rflags = flags;
-}
-
-
-WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
-{
-    ssl->wflags = flags;
-}
-
-
-#ifdef WOLFSSL_DTLS
-
-WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
-{
-    ctx->CBIOCookie = cb;
-}
-
-
-WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
-{
-    ssl->IOCB_CookieCtx = ctx;
-}
-
-
-WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
-{
-    if (ssl)
-        return ssl->IOCB_CookieCtx;
-
-    return NULL;
-}
-
-#ifdef WOLFSSL_SESSION_EXPORT
-
-WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
-{
-    ctx->CBGetPeer = cb;
-}
-
-
-WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
-{
-    ctx->CBSetPeer = cb;
-}
-
-#endif /* WOLFSSL_SESSION_EXPORT */
-#endif /* WOLFSSL_DTLS */
-
-
-#ifdef HAVE_NETX
-
-/* The NetX receive callback
- *  return :  bytes read, or error
- */
-int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
-    ULONG left;
-    ULONG total;
-    ULONG copied = 0;
-    UINT  status;
-
-    (void)ssl;
-
-    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
-        WOLFSSL_MSG("NetX Recv NULL parameters");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    if (nxCtx->nxPacket == NULL) {
-        status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
-                                       nxCtx->nxWait);
-        if (status != NX_SUCCESS) {
-            WOLFSSL_MSG("NetX Recv receive error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    if (nxCtx->nxPacket) {
-        status = nx_packet_length_get(nxCtx->nxPacket, &total);
-        if (status != NX_SUCCESS) {
-            WOLFSSL_MSG("NetX Recv length get error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-
-        left = total - nxCtx->nxOffset;
-        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
-                                               buf, sz, &copied);
-        if (status != NX_SUCCESS) {
-            WOLFSSL_MSG("NetX Recv data extract offset error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-
-        nxCtx->nxOffset += copied;
-
-        if (copied == left) {
-            WOLFSSL_MSG("NetX Recv Drained packet");
-            nx_packet_release(nxCtx->nxPacket);
-            nxCtx->nxPacket = NULL;
-            nxCtx->nxOffset = 0;
-        }
-    }
-
-    return copied;
-}
-
-
-/* The NetX send callback
- *  return : bytes sent, or error
- */
-int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
-    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
-    NX_PACKET*      packet;
-    NX_PACKET_POOL* pool;   /* shorthand */
-    UINT            status;
-
-    (void)ssl;
-
-    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
-        WOLFSSL_MSG("NetX Send NULL parameters");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
-    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
-                                nxCtx->nxWait);
-    if (status != NX_SUCCESS) {
-        WOLFSSL_MSG("NetX Send packet alloc error");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
-    if (status != NX_SUCCESS) {
-        nx_packet_release(packet);
-        WOLFSSL_MSG("NetX Send data append error");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
-    if (status != NX_SUCCESS) {
-        nx_packet_release(packet);
-        WOLFSSL_MSG("NetX Send socket send error");
-        return WOLFSSL_CBIO_ERR_GENERAL;
-    }
-
-    return sz;
-}
-
-
-/* like set_fd, but for default NetX context */
-void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
-{
-    if (ssl) {
-        ssl->nxCtx.nxSocket = nxSocket;
-        ssl->nxCtx.nxWait   = waitOption;
-    }
-}
-
-#endif /* HAVE_NETX */
-
-
-#ifdef MICRIUM
-
-/* Micrium uTCP/IP port, using the NetSock API
- * TCP and UDP are currently supported with the callbacks below.
- *
- * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
- * and EmbedSetPeer() callbacks implemented.
- *
- * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
- * callback implemented.
- *
- * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
- * callback implemented.
- */
-
-/* The Micrium uTCP/IP send callback
- * return : bytes sent, or error
- */
-int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
-{
-    NET_SOCK_ID sd = *(int*)ctx;
-    NET_SOCK_RTN_CODE ret;
-    NET_ERR err;
-
-    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
-    if (ret < 0) {
-        WOLFSSL_MSG("Embed Send error");
-
-        if (err == NET_ERR_TX) {
-            WOLFSSL_MSG("\tWould block");
-            return WOLFSSL_CBIO_ERR_WANT_WRITE;
-
-        } else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return ret;
-}
-
-/* The Micrium uTCP/IP receive callback
- *  return : nb bytes read, or error
- */
-int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    NET_SOCK_ID sd = *(int*)ctx;
-    NET_SOCK_RTN_CODE ret;
-    NET_ERR err;
-
-#ifdef WOLFSSL_DTLS
-    {
-        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
-        if (wolfSSL_dtls(ssl)
-                     && !wolfSSL_dtls_get_using_nonblock(ssl)
-                     && dtls_timeout != 0) {
-            /* needs timeout in milliseconds */
-            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
-            if (err != NET_SOCK_ERR_NONE) {
-                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
-            }
-        }
-    }
-#endif
-
-    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
-    if (ret < 0) {
-        WOLFSSL_MSG("Embed Receive error");
-
-        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
-            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
-            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
-                WOLFSSL_MSG("\tWould block");
-                return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-            else {
-                WOLFSSL_MSG("\tSocket timeout");
-                return WOLFSSL_CBIO_ERR_TIMEOUT;
-            }
-
-        } else if (err == NET_SOCK_ERR_CLOSED) {
-            WOLFSSL_MSG("Embed receive connection closed");
-            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
-
-        } else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return ret;
-}
-
-/* The Micrium uTCP/IP receivefrom callback
- *  return : nb bytes read, or error
- */
-int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
-{
-    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
-    NET_SOCK_ID       sd = dtlsCtx->rfd;
-    NET_SOCK_ADDR     peer;
-    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
-    NET_SOCK_RTN_CODE ret;
-    NET_ERR err;
-    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
-
-    WOLFSSL_ENTER("MicriumReceiveFrom()");
-
-    if (ssl->options.handShakeDone)
-        dtls_timeout = 0;
-
-    if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
-        /* needs timeout in milliseconds */
-        NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
-        if (err != NET_SOCK_ERR_NONE) {
-            WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
-        }
-    }
-
-    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
-                             0, 0, 0, &err);
-    if (ret < 0) {
-        WOLFSSL_MSG("Embed Receive From error");
-
-        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
-            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
-            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
-                WOLFSSL_MSG("\tWould block");
-                return WOLFSSL_CBIO_ERR_WANT_READ;
-            }
-            else {
-                WOLFSSL_MSG("\tSocket timeout");
-                return WOLFSSL_CBIO_ERR_TIMEOUT;
-            }
-        } else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-    else {
-        if (dtlsCtx->peer.sz > 0
-                && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
-                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
-            WOLFSSL_MSG("\tIgnored packet from invalid peer");
-            return WOLFSSL_CBIO_ERR_WANT_READ;
-        }
-    }
-
-    return ret;
-}
-
-/* The Micrium uTCP/IP sendto callback
- *  return : nb bytes sent, or error
- */
-int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
-    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
-    NET_SOCK_ID sd = dtlsCtx->wfd;
-    NET_SOCK_RTN_CODE ret;
-    int len = sz;
-    NET_ERR err;
-
-    WOLFSSL_ENTER("MicriumSendTo()");
-
-    ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags,
-                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
-                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
-                           &err);
-    if (err < 0) {
-        WOLFSSL_MSG("Embed Send To error");
-
-        if (err == NET_ERR_TX) {
-            WOLFSSL_MSG("\tWould block");
-            return WOLFSSL_CBIO_ERR_WANT_WRITE;
-
-        } else {
-            WOLFSSL_MSG("\tGeneral error");
-            return WOLFSSL_CBIO_ERR_GENERAL;
-        }
-    }
-
-    return ret;
-}
-
-/* Micrium DTLS Generate Cookie callback
- *  return : number of bytes copied into buf, or error
- */
-int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
-{
-    NET_SOCK_ADDR peer;
-    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
-    byte digest[WC_SHA_DIGEST_SIZE];
-    int  ret = 0;
-
-    (void)ctx;
-
-    XMEMSET(&peer, 0, sizeof(peer));
-    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
-                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
-        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
-        return GEN_COOKIE_E;
-    }
-
-    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
-    if (ret != 0)
-        return ret;
-
-    if (sz > WC_SHA_DIGEST_SIZE)
-        sz = WC_SHA_DIGEST_SIZE;
-    XMEMCPY(buf, digest, sz);
-
-    return sz;
-}
-
-#endif /* MICRIUM */
-
-#endif /* WOLFCRYPT_ONLY */
+/* wolfio.c
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfcrypt/settings.h>
+
+#ifndef WOLFCRYPT_ONLY
+
+#ifdef _WIN32_WCE
+    /* On WinCE winsock2.h must be included before windows.h for socket stuff */
+    #include <winsock2.h>
+#endif
+
+#include <wolfssl/internal.h>
+#include <wolfssl/error-ssl.h>
+#include <wolfssl/wolfio.h>
+
+#if defined(HAVE_HTTP_CLIENT)
+    #include <stdlib.h>   /* atoi(), strtol() */
+#endif
+
+/*
+Possible IO enable options:
+ * WOLFSSL_USER_IO:     Disables default Embed* callbacks and     default: off
+                        allows user to define their own using
+                        wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
+ * USE_WOLFSSL_IO:      Enables the wolfSSL IO functions          default: off
+ * HAVE_HTTP_CLIENT:    Enables HTTP client API's                 default: off
+                                     (unless HAVE_OCSP or HAVE_CRL_IO defined)
+ * HAVE_IO_TIMEOUT:     Enables support for connect timeout       default: off
+ */
+
+
+/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
+   automatic setting of default I/O functions EmbedSend() and EmbedReceive()
+   but they'll still need SetCallback xxx() at end of file
+*/
+
+#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
+
+/* Translates return codes returned from
+ * send() and recv() if need be.
+ */
+static WC_INLINE int TranslateReturnCode(int old, int sd)
+{
+    (void)sd;
+
+#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    if (old == 0) {
+        errno = SOCKET_EWOULDBLOCK;
+        return -1;  /* convert to BSD style wouldblock as error */
+    }
+
+    if (old < 0) {
+        errno = RTCS_geterror(sd);
+        if (errno == RTCSERR_TCP_CONN_CLOSING)
+            return 0;   /* convert to BSD style closing */
+        if (errno == RTCSERR_TCP_CONN_RLSD)
+            errno = SOCKET_ECONNRESET;
+        if (errno == RTCSERR_TCP_TIMED_OUT)
+            errno = SOCKET_EAGAIN;
+    }
+#endif
+
+    return old;
+}
+
+static WC_INLINE int wolfSSL_LastError(void)
+{
+#ifdef USE_WINDOWS_API
+    return WSAGetLastError();
+#elif defined(EBSNET)
+    return xn_getlasterror();
+#else
+    return errno;
+#endif
+}
+
+#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
+
+
+#ifdef OPENSSL_EXTRA
+/* Use the WOLFSSL read BIO for receiving data. This is set by the function
+ * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
+ *
+ * ssl  WOLFSSL struct passed in that has this function set as the receive
+ *      callback.
+ * buf  buffer to fill with data read
+ * sz   size of buf buffer
+ * ctx  a user set context
+ *
+ * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
+ */
+int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    int recvd = WOLFSSL_CBIO_ERR_GENERAL;
+
+    WOLFSSL_ENTER("BioReceive");
+
+    if (ssl->biord == NULL) {
+        WOLFSSL_MSG("WOLFSSL biord not set");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    switch (ssl->biord->type) {
+        case WOLFSSL_BIO_MEMORY:
+        case WOLFSSL_BIO_BIO:
+            if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
+               return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
+            if (recvd <= 0) {
+                return WOLFSSL_CBIO_ERR_GENERAL;
+            }
+            break;
+
+       default:
+            WOLFSSL_MSG("This BIO type is unknown / unsupported");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    (void)ctx;
+    return recvd;
+}
+
+
+/* Use the WOLFSSL write BIO for sending data. This is set by the function
+ * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
+ *
+ * ssl  WOLFSSL struct passed in that has this function set as the send callback.
+ * buf  buffer with data to write out
+ * sz   size of buf buffer
+ * ctx  a user set context
+ *
+ * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
+ */
+int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    int sent = WOLFSSL_CBIO_ERR_GENERAL;
+
+    if (ssl->biowr == NULL) {
+        WOLFSSL_MSG("WOLFSSL biowr not set\n");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    switch (ssl->biowr->type) {
+        case WOLFSSL_BIO_MEMORY:
+        case WOLFSSL_BIO_BIO:
+            sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
+            if (sent < 0) {
+                return WOLFSSL_CBIO_ERR_GENERAL;
+            }
+            break;
+
+        default:
+            WOLFSSL_MSG("This BIO type is unknown / unsupported");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+    (void)ctx;
+
+    return sent;
+}
+#endif
+
+
+#ifdef USE_WOLFSSL_IO
+
+/* The receive embedded callback
+ *  return : nb bytes read, or error
+ */
+int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    int sd = *(int*)ctx;
+    int recvd;
+
+    recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
+    if (recvd < 0) {
+        int err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNABORTED) {
+            WOLFSSL_MSG("\tConnection aborted");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else if (recvd == 0) {
+        WOLFSSL_MSG("Embed receive connection closed");
+        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+    }
+
+    return recvd;
+}
+
+/* The send embedded callback
+ *  return : nb bytes sent, or error
+ */
+int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    int sd = *(int*)ctx;
+    int sent;
+
+    sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
+    if (sent < 0) {
+        int err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Send error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould Block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_EPIPE) {
+            WOLFSSL_MSG("\tSocket EPIPE");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+#include <wolfssl/wolfcrypt/sha.h>
+
+#define SENDTO_FUNCTION sendto
+#define RECVFROM_FUNCTION recvfrom
+
+
+/* The receive embedded callback
+ *  return : nb bytes read, or error
+ */
+int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int recvd;
+    int err;
+    int sd = dtlsCtx->rfd;
+    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+    SOCKADDR_S peer;
+    XSOCKLENT peerSz = sizeof(peer);
+
+    WOLFSSL_ENTER("EmbedReceiveFrom()");
+
+    if (ssl->options.handShakeDone)
+        dtls_timeout = 0;
+
+    if (!wolfSSL_get_using_nonblock(ssl)) {
+        #ifdef USE_WINDOWS_API
+            DWORD timeout = dtls_timeout * 1000;
+        #else
+            struct timeval timeout;
+            XMEMSET(&timeout, 0, sizeof(timeout));
+            timeout.tv_sec = dtls_timeout;
+        #endif
+        if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
+                       sizeof(timeout)) != 0) {
+                WOLFSSL_MSG("setsockopt rcvtimeo failed");
+        }
+    }
+
+    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
+                                  (SOCKADDR*)&peer, &peerSz);
+
+    recvd = TranslateReturnCode(recvd, sd);
+
+    if (recvd < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNREFUSED) {
+            WOLFSSL_MSG("\tConnection refused");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else {
+        if (dtlsCtx->peer.sz > 0
+                && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
+                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
+            WOLFSSL_MSG("    Ignored packet from invalid peer");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+    }
+
+    return recvd;
+}
+
+
+/* The send embedded callback
+ *  return : nb bytes sent, or error
+ */
+int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int sd = dtlsCtx->wfd;
+    int sent;
+    int len = sz;
+    int err;
+
+    WOLFSSL_ENTER("EmbedSendTo()");
+
+    sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
+                                (const SOCKADDR*)dtlsCtx->peer.sa,
+                                dtlsCtx->peer.sz);
+
+    sent = TranslateReturnCode(sent, sd);
+
+    if (sent < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Send To error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould Block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_EPIPE) {
+            WOLFSSL_MSG("\tSocket EPIPE");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+
+
+#ifdef WOLFSSL_MULTICAST
+
+/* The alternate receive embedded callback for Multicast
+ *  return : nb bytes read, or error
+ */
+int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    int recvd;
+    int err;
+    int sd = dtlsCtx->rfd;
+
+    WOLFSSL_ENTER("EmbedReceiveFromMcast()");
+
+    recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
+
+    recvd = TranslateReturnCode(recvd, sd);
+
+    if (recvd < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_ECONNREFUSED) {
+            WOLFSSL_MSG("\tConnection refused");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return recvd;
+}
+#endif /* WOLFSSL_MULTICAST */
+
+
+/* The DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
+{
+    int sd = ssl->wfd;
+    SOCKADDR_S peer;
+    XSOCKLENT peerSz = sizeof(peer);
+    byte digest[WC_SHA256_DIGEST_SIZE];
+    int  ret = 0;
+
+    (void)ctx;
+
+    XMEMSET(&peer, 0, sizeof(peer));
+    if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
+        WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
+        return GEN_COOKIE_E;
+    }
+
+    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
+    if (ret != 0)
+        return ret;
+
+    if (sz > WC_SHA256_DIGEST_SIZE)
+        sz = WC_SHA256_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+
+    return sz;
+}
+
+#ifdef WOLFSSL_SESSION_EXPORT
+
+    /* get the peer information in human readable form (ip, port, family)
+     * default function assumes BSD sockets
+     * can be overriden with wolfSSL_CTX_SetIOGetPeer
+     */
+    int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
+                                                 unsigned short* port, int* fam)
+    {
+        SOCKADDR_S peer;
+        word32     peerSz;
+        int        ret;
+
+        if (ssl == NULL || ip == NULL || ipSz == NULL ||
+                                                  port == NULL || fam == NULL) {
+            return BAD_FUNC_ARG;
+        }
+
+        /* get peer information stored in ssl struct */
+        peerSz = sizeof(SOCKADDR_S);
+        if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
+                                                               != WOLFSSL_SUCCESS) {
+            return ret;
+        }
+
+        /* extract family, ip, and port */
+        *fam = ((SOCKADDR_S*)&peer)->ss_family;
+        switch (*fam) {
+            case WOLFSSL_IP4:
+                if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
+                                                           ip, *ipSz) == NULL) {
+                    WOLFSSL_MSG("XINET_NTOP error");
+                    return SOCKET_ERROR_E;
+                }
+                *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
+                break;
+
+            case WOLFSSL_IP6:
+            #ifdef WOLFSSL_IPV6
+                if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
+                                                           ip, *ipSz) == NULL) {
+                    WOLFSSL_MSG("XINET_NTOP error");
+                    return SOCKET_ERROR_E;
+                }
+                *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
+            #endif /* WOLFSSL_IPV6 */
+                break;
+
+            default:
+                WOLFSSL_MSG("Unknown family type");
+                return SOCKET_ERROR_E;
+        }
+        ip[*ipSz - 1] = '\0'; /* make sure has terminator */
+        *ipSz = (word16)XSTRLEN(ip);
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    /* set the peer information in human readable form (ip, port, family)
+     * default function assumes BSD sockets
+     * can be overriden with wolfSSL_CTX_SetIOSetPeer
+     */
+    int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
+                                                   unsigned short port, int fam)
+    {
+        int    ret;
+        SOCKADDR_S addr;
+
+        /* sanity checks on arguments */
+        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
+            return BAD_FUNC_ARG;
+        }
+
+        addr.ss_family = fam;
+        switch (addr.ss_family) {
+            case WOLFSSL_IP4:
+                if (XINET_PTON(addr.ss_family, ip,
+                                     &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
+                    WOLFSSL_MSG("XINET_PTON error");
+                    return SOCKET_ERROR_E;
+                }
+                ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
+
+                /* peer sa is free'd in SSL_ResourceFree */
+                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
+                                          sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Import DTLS peer info error");
+                    return ret;
+                }
+                break;
+
+            case WOLFSSL_IP6:
+            #ifdef WOLFSSL_IPV6
+                if (XINET_PTON(addr.ss_family, ip,
+                                   &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
+                    WOLFSSL_MSG("XINET_PTON error");
+                    return SOCKET_ERROR_E;
+                }
+                ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
+
+                /* peer sa is free'd in SSL_ResourceFree */
+                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
+                                         sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
+                    WOLFSSL_MSG("Import DTLS peer info error");
+                    return ret;
+                }
+            #endif /* WOLFSSL_IPV6 */
+                break;
+
+            default:
+                WOLFSSL_MSG("Unknown address family");
+                return BUFFER_E;
+        }
+
+        return WOLFSSL_SUCCESS;
+    }
+#endif /* WOLFSSL_SESSION_EXPORT */
+#endif /* WOLFSSL_DTLS */
+
+
+int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
+{
+    int recvd;
+
+    recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
+    recvd = TranslateReturnCode(recvd, sd);
+
+    return recvd;
+}
+
+int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
+{
+    int sent;
+
+    sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
+    sent = TranslateReturnCode(sent, sd);
+
+    return sent;
+}
+
+#endif /* USE_WOLFSSL_IO */
+
+
+#ifdef HAVE_HTTP_CLIENT
+
+#ifndef HAVE_IO_TIMEOUT
+    #define io_timeout_sec 0
+#else
+
+    #ifndef DEFAULT_TIMEOUT_SEC
+        #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
+    #endif
+
+    static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
+
+    void wolfIO_SetTimeout(int to_sec)
+    {
+        io_timeout_sec = to_sec;
+    }
+
+    int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
+    {
+        int ret = 0;
+
+    #ifdef USE_WINDOWS_API
+        unsigned long blocking = non_blocking;
+        ret = ioctlsocket(sockfd, FIONBIO, &blocking);
+        if (ret == SOCKET_ERROR)
+            ret = -1;
+    #else
+        ret = fcntl(sockfd, F_GETFL, 0);
+        if (ret >= 0) {
+            if (non_blocking)
+                ret |= O_NONBLOCK;
+            else
+                ret &= ~O_NONBLOCK;
+            ret = fcntl(sockfd, F_SETFL, ret);
+        }
+    #endif
+        if (ret < 0) {
+            WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
+        }
+
+        return ret;
+    }
+
+    int wolfIO_Select(SOCKET_T sockfd, int to_sec)
+    {
+        fd_set rfds, wfds;
+        int nfds = 0;
+        struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
+        int ret;
+
+    #ifndef USE_WINDOWS_API
+        nfds = (int)sockfd + 1;
+    #endif
+
+        FD_ZERO(&rfds);
+        FD_SET(sockfd, &rfds);
+        wfds = rfds;
+
+        ret = select(nfds, &rfds, &wfds, NULL, &timeout);
+        if (ret == 0) {
+        #ifdef DEBUG_HTTP
+            printf("Timeout: %d\n", ret);
+        #endif
+            return HTTP_TIMEOUT;
+        }
+        else if (ret > 0) {
+            if (FD_ISSET(sockfd, &wfds)) {
+                if (!FD_ISSET(sockfd, &rfds)) {
+                    return 0;
+                }
+            }
+        }
+        return SOCKET_ERROR_E;
+    }
+#endif /* HAVE_IO_TIMEOUT */
+
+static int wolfIO_Word16ToString(char* d, word16 number)
+{
+    int i = 0;
+    word16 order = 10000;
+    word16 digit;
+
+    if (d == NULL)
+        return i;
+
+    if (number == 0)
+        d[i++] = '0';
+    else {
+        while (order) {
+            digit = number / order;
+            if (i > 0 || digit != 0)
+                d[i++] = (char)digit + '0';
+            if (digit != 0)
+                number %= digit * order;
+
+            order = (order > 1) ? order / 10 : 0;
+        }
+    }
+    d[i] = 0; /* null terminate */
+
+    return i;
+}
+
+int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
+{
+#ifdef HAVE_SOCKADDR
+    int ret = 0;
+    SOCKADDR_S addr;
+    int sockaddr_len = sizeof(SOCKADDR_IN);
+#ifdef HAVE_GETADDRINFO
+    ADDRINFO hints;
+    ADDRINFO* answer = NULL;
+    char strPort[6];
+#else
+    HOSTENT* entry;
+    SOCKADDR_IN *sin;
+#endif
+
+    XMEMSET(&addr, 0, sizeof(addr));
+
+#ifdef WOLFIO_DEBUG
+    printf("TCP Connect: %s:%d\n", ip, port);
+#endif
+
+#ifdef HAVE_GETADDRINFO
+    XMEMSET(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    if (wolfIO_Word16ToString(strPort, port) == 0) {
+        WOLFSSL_MSG("invalid port number for responder");
+        return -1;
+    }
+
+    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
+        WOLFSSL_MSG("no addr info for responder");
+        return -1;
+    }
+
+    sockaddr_len = answer->ai_addrlen;
+    XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
+    freeaddrinfo(answer);
+#else
+    entry = gethostbyname(ip);
+    sin = (SOCKADDR_IN *)&addr;
+
+    if (entry) {
+        sin->sin_family = AF_INET;
+        sin->sin_port = XHTONS(port);
+        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
+    }
+    else {
+        WOLFSSL_MSG("no addr info for responder");
+        return -1;
+    }
+#endif
+
+    *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
+
+#ifdef USE_WINDOWS_API
+    if (*sockfd == INVALID_SOCKET) {
+        WOLFSSL_MSG("bad socket fd, out of fds?");
+        return -1;
+    }
+#else
+     if (*sockfd < 0) {
+         WOLFSSL_MSG("bad socket fd, out of fds?");
+         return -1;
+     }
+#endif
+
+#ifdef HAVE_IO_TIMEOUT
+    /* if timeout value provided then set socket non-blocking */
+    if (to_sec > 0) {
+        wolfIO_SetBlockingMode(*sockfd, 1);
+    }
+#else
+    (void)to_sec;
+#endif
+
+    ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
+#ifdef HAVE_IO_TIMEOUT
+    if (ret != 0) {
+        if ((errno == EINPROGRESS) && (to_sec > 0)) {
+            /* wait for connect to complete */
+            ret = wolfIO_Select(*sockfd, to_sec);
+
+            /* restore blocking mode */
+            wolfIO_SetBlockingMode(*sockfd, 0);
+        }
+    }
+#endif
+    if (ret != 0) {
+        WOLFSSL_MSG("Responder tcp connect failed");
+        return -1;
+    }
+    return ret;
+#else
+    (void)sockfd;
+    (void)ip;
+    (void)port;
+    (void)to_sec;
+    return -1;
+#endif /* HAVE_SOCKADDR */
+}
+
+#ifndef HTTP_SCRATCH_BUFFER_SIZE
+    #define HTTP_SCRATCH_BUFFER_SIZE 512
+#endif
+#ifndef MAX_URL_ITEM_SIZE
+    #define MAX_URL_ITEM_SIZE   80
+#endif
+
+int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
+    word16* outPort)
+{
+    int result = -1;
+
+    if (url == NULL || urlSz == 0) {
+        if (outName)
+            *outName = 0;
+        if (outPath)
+            *outPath = 0;
+        if (outPort)
+            *outPort = 0;
+    }
+    else {
+        int i, cur;
+
+        /* need to break the url down into scheme, address, and port */
+        /*     "http://example.com:8080/" */
+        /*     "http://[::1]:443/"        */
+        if (XSTRNCMP(url, "http://", 7) == 0) {
+            cur = 7;
+        } else cur = 0;
+
+        i = 0;
+        if (url[cur] == '[') {
+            cur++;
+            /* copy until ']' */
+            while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
+                if (outName)
+                    outName[i] = url[cur];
+                i++; cur++;
+            }
+            cur++; /* skip ']' */
+        }
+        else {
+            while (url[cur] != 0 && url[cur] != ':' &&
+                                           url[cur] != '/' && cur < urlSz) {
+                if (outName)
+                    outName[i] = url[cur];
+                i++; cur++;
+            }
+        }
+        if (outName)
+            outName[i] = 0;
+        /* Need to pick out the path after the domain name */
+
+        if (cur < urlSz && url[cur] == ':') {
+            char port[6];
+            int j;
+            word32 bigPort = 0;
+            i = 0;
+            cur++;
+            while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
+                    i < 6) {
+                port[i++] = url[cur++];
+            }
+
+            for (j = 0; j < i; j++) {
+                if (port[j] < '0' || port[j] > '9') return -1;
+                bigPort = (bigPort * 10) + (port[j] - '0');
+            }
+            if (outPort)
+                *outPort = (word16)bigPort;
+        }
+        else if (outPort)
+            *outPort = 80;
+
 
+        if (cur < urlSz && url[cur] == '/') {
+            i = 0;
+            while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
+                if (outPath)
+                    outPath[i] = url[cur];
+                i++; cur++;
+            }
+            if (outPath)
+                outPath[i] = 0;
+        }
+        else if (outPath) {
+            outPath[0] = '/';
+            outPath[1] = 0;
+        }
+
+        result = 0;
+    }
+
+    return result;
+}
+
+static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
+    int chunkSz, char* start, int len, int dynType, void* heap)
+{
+    byte* newRecvBuf = NULL;
+    int newRecvSz = *recvBufSz + chunkSz;
+    int pos = 0;
+
+    WOLFSSL_MSG("Processing HTTP response");
+#ifdef WOLFIO_DEBUG
+    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
+#endif
+
+    newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
+    if (newRecvBuf == NULL) {
+        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
+        return MEMORY_E;
+    }
+
+    /* if buffer already exists, then we are growing it */
+    if (*recvBuf) {
+        XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
+        XFREE(*recvBuf, heap, dynType);
+        pos += *recvBufSz;
+        *recvBuf = NULL;
+    }
+
+    /* copy the remainder of the httpBuf into the respBuf */
+    if (len != 0) {
+        XMEMCPY(&newRecvBuf[pos], start, len);
+        pos += len;
+    }
+
+    /* receive the remainder of chunk */
+    while (len < chunkSz) {
+        int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
+        if (rxSz > 0) {
+            len += rxSz;
+            pos += rxSz;
+        }
+        else {
+            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
+            XFREE(newRecvBuf, heap, dynType);
+            return -1;
+        }
+    }
+
+    *recvBuf = newRecvBuf;
+    *recvBufSz = newRecvSz;
+
+    return 0;
+}
+
+int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
+    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
+{
+    int result = 0;
+    int len = 0;
+    char *start, *end;
+    int respBufSz = 0;
+    int isChunked = 0, chunkSz = 0;
+    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
+                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
+                     phr_http_end
+    } state = phr_init;
+
+    *respBuf = NULL;
+    start = end = NULL;
+    do {
+        if (state == phr_get_chunk_data) {
+            /* get chunk of data */
+            result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
+                chunkSz, start, len, dynType, heap);
+
+            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
+            end = NULL;
+            len = 0;
+        }
+
+        /* read data if no \r\n or first time */
+        if (end == NULL) {
+            result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
+            if (result > 0) {
+                len += result;
+                start = (char*)httpBuf;
+                start[len] = 0;
+            }
+            else {
+                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
+                return -1;
+            }
+        }
+        end = XSTRSTR(start, "\r\n"); /* locate end */
+
+        /* handle incomplete rx */
+        if (end == NULL) {
+            if (len != 0)
+                XMEMMOVE(httpBuf, start, len);
+            start = end = NULL;
+        }
+        /* when start is "\r\n" */
+        else if (end == start) {
+            /* if waiting for end or need chunk len */
+            if (state == phr_wait_end || state == phr_get_chunk_len) {
+                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
+                len -= 2; start += 2; /* skip \r\n */
+             }
+             else {
+                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
+                return -1;
+             }
+        }
+        else {
+            *end = 0; /* null terminate */
+            len -= (int)(end - start) + 2;
+                /* adjust len to remove the first line including the /r/n */
+
+        #ifdef WOLFIO_DEBUG
+            printf("HTTP Resp: %s\n", start);
+        #endif
+
+            switch (state) {
+                case phr_init:
+                    if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
+                        start += 9;
+                        if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
+                            WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
+                            return -1;
+                        }
+                        state = phr_http_start;
+                    }
+                    break;
+                case phr_http_start:
+                case phr_have_length:
+                case phr_have_type:
+                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
+                        int i;
+
+                        start += 13;
+                        while (*start == ' ' && *start != '\0') start++;
+
+                        /* try and match against appStrList */
+                        i = 0;
+                        while (appStrList[i] != NULL) {
+                            if (XSTRNCASECMP(start, appStrList[i],
+                                                XSTRLEN(appStrList[i])) == 0) {
+                                break;
+                            }
+                            i++;
+                        }
+                        if (appStrList[i] == NULL) {
+                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
+                            return -1;
+                        }
+                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
+                    }
+                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
+                        start += 15;
+                        while (*start == ' ' && *start != '\0') start++;
+                        chunkSz = atoi(start);
+                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
+                    }
+                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
+                        start += 18;
+                        while (*start == ' ' && *start != '\0') start++;
+                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
+                            isChunked = 1;
+                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
+                        }
+                    }
+                    break;
+                case phr_get_chunk_len:
+                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
+                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
+                    break;
+                case phr_get_chunk_data:
+                    /* processing for chunk data done above, since \r\n isn't required */
+                case phr_wait_end:
+                case phr_http_end:
+                    /* do nothing */
+                    break;
+            } /* switch (state) */
+
+            /* skip to end plus \r\n */
+            start = end + 2;
+        }
+    } while (state != phr_http_end);
+
+    if (!isChunked) {
+        result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
+                                                    start, len, dynType, heap);
+    }
+
+    if (result >= 0) {
+        result = respBufSz;
+    }
+    else {
+        WOLFSSL_ERROR(result);
+    }
+
+    return result;
+}
+
+int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
+    const char* path, int pathLen, int reqSz, const char* contentType,
+    byte* buf, int bufSize)
+{
+    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
+    char reqSzStr[6];
+    char* req = (char*)buf;
+    const char* blankStr = " ";
+    const char* http11Str = " HTTP/1.1";
+    const char* hostStr = "\r\nHost: ";
+    const char* contentLenStr = "\r\nContent-Length: ";
+    const char* contentTypeStr = "\r\nContent-Type: ";
+    const char* doubleCrLfStr = "\r\n\r\n";
+    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
+        contentTypeStrLen, doubleCrLfStrLen;
+
+    reqTypeLen = (word32)XSTRLEN(reqType);
+    domainNameLen = (word32)XSTRLEN(domainName);
+    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
+    contentTypeLen = (word32)XSTRLEN(contentType);
+
+    blankStrLen = (word32)XSTRLEN(blankStr);
+    http11StrLen = (word32)XSTRLEN(http11Str);
+    hostStrLen = (word32)XSTRLEN(hostStr);
+    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
+    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
+    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
+
+    /* determine max length and check it */
+    maxLen =
+        reqTypeLen +
+        blankStrLen +
+        pathLen +
+        http11StrLen +
+        hostStrLen +
+        domainNameLen +
+        contentLenStrLen +
+        reqSzStrLen +
+        contentTypeStrLen +
+        contentTypeLen +
+        doubleCrLfStrLen +
+        1 /* null term */;
+    if (maxLen > (word32)bufSize)
+        return 0;
+
+    XSTRNCPY((char*)buf, reqType, reqTypeLen);
+    buf += reqTypeLen;
+    XSTRNCPY((char*)buf, blankStr, blankStrLen+1);
+    buf += blankStrLen;
+    XSTRNCPY((char*)buf, path, pathLen);
+    buf += pathLen;
+    XSTRNCPY((char*)buf, http11Str, http11StrLen+1);
+    buf += http11StrLen;
+    if (domainNameLen > 0) {
+        XSTRNCPY((char*)buf, hostStr, hostStrLen+1);
+        buf += hostStrLen;
+        XSTRNCPY((char*)buf, domainName, domainNameLen);
+        buf += domainNameLen;
+    }
+    if (reqSz > 0 && reqSzStrLen > 0) {
+        XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1);
+        buf += contentLenStrLen;
+        XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen);
+        buf += reqSzStrLen;
+    }
+    if (contentTypeLen > 0) {
+        XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1);
+        buf += contentTypeStrLen;
+        XSTRNCPY((char*)buf, contentType, contentTypeLen);
+        buf += contentTypeLen;
+    }
+    XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1);
+    buf += doubleCrLfStrLen;
+
+#ifdef WOLFIO_DEBUG
+    printf("HTTP %s: %s", reqType, req);
+#endif
+
+    /* calculate actual length based on original and new pointer */
+    return (int)((char*)buf - req);
+}
+
+
+#ifdef HAVE_OCSP
+
+int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
+                                    int ocspReqSz, byte* buf, int bufSize)
+{
+    return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
+        ocspReqSz, "application/ocsp-request", buf, bufSize);
+}
+
+/* return: >0 OCSP Response Size
+ *         -1 error */
+int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
+                                       byte* httpBuf, int httpBufSz, void* heap)
+{
+    const char* appStrList[] = {
+        "application/ocsp-response",
+        NULL
+    };
+
+    return wolfIO_HttpProcessResponse(sfd, appStrList,
+        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
+}
+
+/* in default wolfSSL callback ctx is the heap pointer */
+int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
+                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
+{
+    SOCKET_T sfd = 0;
+    word16   port;
+    int      ret = -1;
+#ifdef WOLFSSL_SMALL_STACK
+    char*    path;
+    char*    domainName;
+#else
+    char     path[MAX_URL_ITEM_SIZE];
+    char     domainName[MAX_URL_ITEM_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (path == NULL)
+        return MEMORY_E;
+
+    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (domainName == NULL) {
+        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        return MEMORY_E;
+    }
+#endif
+
+    if (ocspReqBuf == NULL || ocspReqSz == 0) {
+        WOLFSSL_MSG("OCSP request is required for lookup");
+    }
+    else if (ocspRespBuf == NULL) {
+        WOLFSSL_MSG("Cannot save OCSP response");
+    }
+    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
+        WOLFSSL_MSG("Unable to decode OCSP URL");
+    }
+    else {
+        /* Note, the library uses the EmbedOcspRespFree() callback to
+         * free this buffer. */
+        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
+        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
+
+        if (httpBuf == NULL) {
+            WOLFSSL_MSG("Unable to create OCSP response buffer");
+        }
+        else {
+            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
+                                                            httpBuf, httpBufSz);
+
+            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
+            if ((ret != 0) || (sfd < 0)) {
+                WOLFSSL_MSG("OCSP Responder connection failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
+                                                                    httpBufSz) {
+                WOLFSSL_MSG("OCSP http request failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
+                                                                    ocspReqSz) {
+                WOLFSSL_MSG("OCSP ocsp request failed");
+            }
+            else {
+                ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
+                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
+            }
+
+            CloseSocket(sfd);
+            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+
+/* in default callback ctx is heap hint */
+void EmbedOcspRespFree(void* ctx, byte *resp)
+{
+    if (resp)
+        XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
+
+    (void)ctx;
+}
+#endif /* HAVE_OCSP */
+
+
+#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
+
+int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
+    const char* domainName, byte* buf, int bufSize)
+{
+    return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
+        buf, bufSize);
+}
+
+int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
+    int httpBufSz)
+{
+    int result;
+    byte *respBuf = NULL;
+
+    const char* appStrList[] = {
+        "application/pkix-crl",
+        "application/x-pkcs7-crl",
+        NULL
+    };
+
+    result = wolfIO_HttpProcessResponse(sfd, appStrList,
+        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
+    if (result >= 0) {
+        result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
+    }
+    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
+
+    return result;
+}
+
+int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
+{
+    SOCKET_T sfd = 0;
+    word16   port;
+    int      ret = -1;
+#ifdef WOLFSSL_SMALL_STACK
+    char*    domainName;
+#else
+    char     domainName[MAX_URL_ITEM_SIZE];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (domainName == NULL) {
+        return MEMORY_E;
+    }
+#endif
+
+    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
+        WOLFSSL_MSG("Unable to decode CRL URL");
+    }
+    else {
+        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
+        byte* httpBuf   = (byte*)XMALLOC(httpBufSz, crl->heap,
+                                                              DYNAMIC_TYPE_CRL);
+        if (httpBuf == NULL) {
+            WOLFSSL_MSG("Unable to create CRL response buffer");
+        }
+        else {
+            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
+                httpBuf, httpBufSz);
+
+            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
+            if ((ret != 0) || (sfd < 0)) {
+                WOLFSSL_MSG("CRL connection failed");
+            }
+            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
+                                                                 != httpBufSz) {
+                WOLFSSL_MSG("CRL http get failed");
+            }
+            else {
+                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
+                                                      HTTP_SCRATCH_BUFFER_SIZE);
+            }
+
+            CloseSocket(sfd);
+            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    return ret;
+}
+#endif /* HAVE_CRL && HAVE_CRL_IO */
+
+#endif /* HAVE_HTTP_CLIENT */
+
+
+
+WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
+{
+    ctx->CBIORecv = CBIORecv;
+    #ifdef OPENSSL_EXTRA
+    ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
+    #endif
+}
+
+
+WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
+{
+    ctx->CBIOSend = CBIOSend;
+    #ifdef OPENSSL_EXTRA
+    ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
+    #endif
+}
+
+
+WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
+{
+    ssl->IOCB_ReadCtx = rctx;
+}
+
+
+WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
+{
+    ssl->IOCB_WriteCtx = wctx;
+}
+
+
+WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_ReadCtx;
+
+    return NULL;
+}
+
+
+WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_WriteCtx;
+
+    return NULL;
+}
+
+
+WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
+{
+    ssl->rflags = flags;
+}
+
+
+WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
+{
+    ssl->wflags = flags;
+}
+
+
+#ifdef WOLFSSL_DTLS
+
+WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
+{
+    ctx->CBIOCookie = cb;
+}
+
+
+WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
+{
+    ssl->IOCB_CookieCtx = ctx;
+}
+
+
+WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
+{
+    if (ssl)
+        return ssl->IOCB_CookieCtx;
+
+    return NULL;
+}
+
+#ifdef WOLFSSL_SESSION_EXPORT
+
+WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
+{
+    ctx->CBGetPeer = cb;
+}
+
+
+WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
+{
+    ctx->CBSetPeer = cb;
+}
+
+#endif /* WOLFSSL_SESSION_EXPORT */
+#endif /* WOLFSSL_DTLS */
+
+
+#ifdef HAVE_NETX
+
+/* The NetX receive callback
+ *  return :  bytes read, or error
+ */
+int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
+    ULONG left;
+    ULONG total;
+    ULONG copied = 0;
+    UINT  status;
+
+    (void)ssl;
+
+    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
+        WOLFSSL_MSG("NetX Recv NULL parameters");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    if (nxCtx->nxPacket == NULL) {
+        status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
+                                       nxCtx->nxWait);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv receive error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    if (nxCtx->nxPacket) {
+        status = nx_packet_length_get(nxCtx->nxPacket, &total);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv length get error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+
+        left = total - nxCtx->nxOffset;
+        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
+                                               buf, sz, &copied);
+        if (status != NX_SUCCESS) {
+            WOLFSSL_MSG("NetX Recv data extract offset error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+
+        nxCtx->nxOffset += copied;
+
+        if (copied == left) {
+            WOLFSSL_MSG("NetX Recv Drained packet");
+            nx_packet_release(nxCtx->nxPacket);
+            nxCtx->nxPacket = NULL;
+            nxCtx->nxOffset = 0;
+        }
+    }
+
+    return copied;
+}
+
+
+/* The NetX send callback
+ *  return : bytes sent, or error
+ */
+int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
+    NX_PACKET*      packet;
+    NX_PACKET_POOL* pool;   /* shorthand */
+    UINT            status;
+
+    (void)ssl;
+
+    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
+        WOLFSSL_MSG("NetX Send NULL parameters");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
+    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
+                                nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        WOLFSSL_MSG("NetX Send packet alloc error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        nx_packet_release(packet);
+        WOLFSSL_MSG("NetX Send data append error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
+    if (status != NX_SUCCESS) {
+        nx_packet_release(packet);
+        WOLFSSL_MSG("NetX Send socket send error");
+        return WOLFSSL_CBIO_ERR_GENERAL;
+    }
+
+    return sz;
+}
+
+
+/* like set_fd, but for default NetX context */
+void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
+{
+    if (ssl) {
+        ssl->nxCtx.nxSocket = nxSocket;
+        ssl->nxCtx.nxWait   = waitOption;
+    }
+}
+
+#endif /* HAVE_NETX */
+
+
+#ifdef MICRIUM
+
+/* Micrium uTCP/IP port, using the NetSock API
+ * TCP and UDP are currently supported with the callbacks below.
+ *
+ * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
+ * and EmbedSetPeer() callbacks implemented.
+ *
+ * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
+ * callback implemented.
+ *
+ * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
+ * callback implemented.
+ */
+
+/* The Micrium uTCP/IP send callback
+ * return : bytes sent, or error
+ */
+int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    NET_SOCK_ID sd = *(int*)ctx;
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+
+    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Send error");
+
+        if (err == NET_ERR_TX) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP receive callback
+ *  return : nb bytes read, or error
+ */
+int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    NET_SOCK_ID sd = *(int*)ctx;
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+
+#ifdef WOLFSSL_DTLS
+    {
+        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+        if (wolfSSL_dtls(ssl)
+                     && !wolfSSL_dtls_get_using_nonblock(ssl)
+                     && dtls_timeout != 0) {
+            /* needs timeout in milliseconds */
+            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
+            if (err != NET_SOCK_ERR_NONE) {
+                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
+            }
+        }
+    }
+#endif
+
+    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Receive error");
+
+        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
+            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
+            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+
+        } else if (err == NET_SOCK_ERR_CLOSED) {
+            WOLFSSL_MSG("Embed receive connection closed");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP receivefrom callback
+ *  return : nb bytes read, or error
+ */
+int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    NET_SOCK_ID       sd = dtlsCtx->rfd;
+    NET_SOCK_ADDR     peer;
+    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
+    NET_SOCK_RTN_CODE ret;
+    NET_ERR err;
+    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+
+    WOLFSSL_ENTER("MicriumReceiveFrom()");
+
+    if (ssl->options.handShakeDone)
+        dtls_timeout = 0;
+
+    if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
+        /* needs timeout in milliseconds */
+        NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
+        if (err != NET_SOCK_ERR_NONE) {
+            WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
+        }
+    }
+
+    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
+                             0, 0, 0, &err);
+    if (ret < 0) {
+        WOLFSSL_MSG("Embed Receive From error");
+
+        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
+            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                WOLFSSL_MSG("\tWould block");
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                WOLFSSL_MSG("\tSocket timeout");
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else {
+        if (dtlsCtx->peer.sz > 0
+                && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
+                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
+            WOLFSSL_MSG("\tIgnored packet from invalid peer");
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+    }
+
+    return ret;
+}
+
+/* The Micrium uTCP/IP sendto callback
+ *  return : nb bytes sent, or error
+ */
+int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
+    NET_SOCK_ID sd = dtlsCtx->wfd;
+    NET_SOCK_RTN_CODE ret;
+    int len = sz;
+    NET_ERR err;
+
+    WOLFSSL_ENTER("MicriumSendTo()");
+
+    ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags,
+                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
+                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
+                           &err);
+    if (err < 0) {
+        WOLFSSL_MSG("Embed Send To error");
+
+        if (err == NET_ERR_TX) {
+            WOLFSSL_MSG("\tWould block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+
+        } else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return ret;
+}
+
+/* Micrium DTLS Generate Cookie callback
+ *  return : number of bytes copied into buf, or error
+ */
+int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
+{
+    NET_SOCK_ADDR peer;
+    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
+    byte digest[WC_SHA_DIGEST_SIZE];
+    int  ret = 0;
+
+    (void)ctx;
+
+    XMEMSET(&peer, 0, sizeof(peer));
+    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
+                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
+        return GEN_COOKIE_E;
+    }
+
+    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
+    if (ret != 0)
+        return ret;
+
+    if (sz > WC_SHA_DIGEST_SIZE)
+        sz = WC_SHA_DIGEST_SIZE;
+    XMEMCPY(buf, digest, sz);
+
+    return sz;
+}
+
+#endif /* MICRIUM */
+
+#endif /* WOLFCRYPT_ONLY */
+
--- a/wolfcrypt/src/aes.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10428 +0,0 @@
-/* aes.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#if !defined(NO_AES)
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$g")
-        #pragma const_seg(".fipsB$g")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/aes.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-
-
-/* fips wrapper calls, user can call direct */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv,
-                              int dir)
-    {
-        if (aes == NULL ||  !( (len == 16) || (len == 24) || (len == 32)) ) {
-            return BAD_FUNC_ARG;
-        }
-
-        return AesSetKey_fips(aes, key, len, iv, dir);
-    }
-    int wc_AesSetIV(Aes* aes, const byte* iv)
-    {
-        if (aes == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        return AesSetIV_fips(aes, iv);
-    }
-    #ifdef HAVE_AES_CBC
-        int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-        {
-            if (aes == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            return AesCbcEncrypt_fips(aes, out, in, sz);
-        }
-        #ifdef HAVE_AES_DECRYPT
-            int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-            {
-                if (aes == NULL || out == NULL || in == NULL
-                                            || sz % AES_BLOCK_SIZE != 0) {
-                    return BAD_FUNC_ARG;
-                }
-
-                return AesCbcDecrypt_fips(aes, out, in, sz);
-            }
-        #endif /* HAVE_AES_DECRYPT */
-    #endif /* HAVE_AES_CBC */
-
-    /* AES-CTR */
-    #ifdef WOLFSSL_AES_COUNTER
-        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-        {
-            if (aes == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            return AesCtrEncrypt(aes, out, in, sz);
-        }
-    #endif
-
-    /* AES-DIRECT */
-    #if defined(WOLFSSL_AES_DIRECT)
-        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
-        {
-            AesEncryptDirect(aes, out, in);
-        }
-
-        #ifdef HAVE_AES_DECRYPT
-            void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
-            {
-                AesDecryptDirect(aes, out, in);
-            }
-        #endif /* HAVE_AES_DECRYPT */
-
-        int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
-                                        const byte* iv, int dir)
-        {
-            return AesSetKeyDirect(aes, key, len, iv, dir);
-        }
-    #endif /* WOLFSSL_AES_DIRECT */
-
-    /* AES-GCM */
-    #ifdef HAVE_AESGCM
-        int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
-        {
-            if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) {
-                return BAD_FUNC_ARG;
-            }
-
-            return AesGcmSetKey_fips(aes, key, len);
-        }
-        int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                                      const byte* iv, word32 ivSz,
-                                      byte* authTag, word32 authTagSz,
-                                      const byte* authIn, word32 authInSz)
-        {
-            if (aes == NULL || authTagSz > AES_BLOCK_SIZE
-                                    || authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ ||
-                                    ivSz > AES_BLOCK_SIZE) {
-                return BAD_FUNC_ARG;
-            }
-
-            return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag,
-                authTagSz, authIn, authInSz);
-        }
-
-        #ifdef HAVE_AES_DECRYPT
-            int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                                          const byte* iv, word32 ivSz,
-                                          const byte* authTag, word32 authTagSz,
-                                          const byte* authIn, word32 authInSz)
-            {
-                if (aes == NULL || out == NULL || in == NULL || iv == NULL
-                        || authTag == NULL || authTagSz > AES_BLOCK_SIZE ||
-                        ivSz > AES_BLOCK_SIZE) {
-                    return BAD_FUNC_ARG;
-                }
-
-                return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag,
-                    authTagSz, authIn, authInSz);
-            }
-        #endif /* HAVE_AES_DECRYPT */
-
-        int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
-        {
-            if (gmac == NULL || key == NULL || !((len == 16) ||
-                                (len == 24) || (len == 32)) ) {
-                return BAD_FUNC_ARG;
-            }
-
-            return GmacSetKey(gmac, key, len);
-        }
-        int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
-                                      const byte* authIn, word32 authInSz,
-                                      byte* authTag, word32 authTagSz)
-        {
-            if (gmac == NULL || authTagSz > AES_BLOCK_SIZE ||
-                               authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
-                return BAD_FUNC_ARG;
-            }
-
-            return GmacUpdate(gmac, iv, ivSz, authIn, authInSz,
-                              authTag, authTagSz);
-        }
-    #endif /* HAVE_AESGCM */
-
-    /* AES-CCM */
-    #if defined(HAVE_AESCCM) && \
-        defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-        int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
-        {
-            return AesCcmSetKey(aes, key, keySz);
-        }
-        int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
-                                      const byte* nonce, word32 nonceSz,
-                                      byte* authTag, word32 authTagSz,
-                                      const byte* authIn, word32 authInSz)
-        {
-            /* sanity check on arguments */
-            if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-                    || authTag == NULL || nonceSz < 7 || nonceSz > 13)
-                return BAD_FUNC_ARG;
-
-            AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag,
-                authTagSz, authIn, authInSz);
-            return 0;
-        }
-
-        #ifdef HAVE_AES_DECRYPT
-            int  wc_AesCcmDecrypt(Aes* aes, byte* out,
-                const byte* in, word32 inSz,
-                const byte* nonce, word32 nonceSz,
-                const byte* authTag, word32 authTagSz,
-                const byte* authIn, word32 authInSz)
-            {
-
-                if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-                    || authTag == NULL || nonceSz < 7 || nonceSz > 13) {
-                        return BAD_FUNC_ARG;
-                }
-
-                return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz,
-                    authTag, authTagSz, authIn, authInSz);
-            }
-        #endif /* HAVE_AES_DECRYPT */
-    #endif /* HAVE_AESCCM && HAVE_FIPS_VERSION 2 */
-
-    int  wc_AesInit(Aes* aes, void* h, int i)
-    {
-        (void)aes;
-        (void)h;
-        (void)i;
-        /* FIPS doesn't support:
-            return AesInit(aes, h, i); */
-        return 0;
-    }
-    void wc_AesFree(Aes* aes)
-    {
-        (void)aes;
-        /* FIPS doesn't support:
-            AesFree(aes); */
-    }
-
-#else /* else build without fips, or for FIPS v2 */
-
-
-#if defined(WOLFSSL_TI_CRYPT)
-    #include <wolfcrypt/src/port/ti/ti-aes.c>
-#else
-
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if !defined(WOLFSSL_ARMASM)
-
-#ifdef WOLFSSL_IMX6_CAAM_BLOB
-    /* case of possibly not using hardware acceleration for AES but using key
-       blobs */
-    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
-#endif
-
-#ifdef DEBUG_AESNI
-    #include <stdio.h>
-#endif
-
-#ifdef _MSC_VER
-    /* 4127 warning constant while(1)  */
-    #pragma warning(disable: 4127)
-#endif
-
-
-/* Define AES implementation includes and functions */
-#if defined(STM32_CRYPTO)
-     /* STM32F2/F4 hardware AES support for CBC, CTR modes */
-
-    #ifdef WOLFSSL_STM32L4
-        #define CRYP AES
-    #endif
-
-    /* CRYPT_AES_GCM starts the IV with 2 */
-    #define STM32_GCM_IV_START 2
-
-#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
-    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        switch(aes->rounds) {
-            case 10: /* 128-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-                break;
-	#ifdef CRYP_KEYSIZE_192B
-            case 12: /* 192-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-                break;
-	#endif
-            case 14: /* 256-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-                break;
-            default:
-                break;
-        }
-        hcryp.Instance = CRYP;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)aes->key;
-
-        HAL_CRYP_Init(&hcryp);
-
-        if (HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
-                                    outBlock, STM32_HAL_TIMEOUT) != HAL_OK) {
-            ret = WC_TIMEOUT_E;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-    #else
-        word32 *enc_key;
-        CRYP_InitTypeDef AES_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
-
-        enc_key = aes->key;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
-        CRYP_StructInit(&AES_CRYP_InitStructure);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* load key into correct registers */
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3];
-                break;
-
-            case 12: /* 192-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b;
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5];
-                break;
-
-            case 14: /* 256-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b;
-                AES_CRYP_KeyInitStructure.CRYP_Key0Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[6];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7];
-                break;
-
-            default:
-                break;
-        }
-        CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
-
-        /* set direction, mode, and datatype */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        /* flush IN/OUT FIFOs */
-        CRYP_FIFOFlush();
-
-        CRYP_DataIn(*(uint32_t*)&inBlock[0]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[4]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[8]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[12]);
-
-        /* wait until the complete message has been processed */
-        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-        *(uint32_t*)&outBlock[0]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[4]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[8]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[12] = CRYP_DataOut();
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-    #endif /* WOLFSSL_STM32_CUBEMX */
-        return ret;
-    }
-#endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */
-
-#ifdef HAVE_AES_DECRYPT
-    #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM)
-    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        switch(aes->rounds) {
-            case 10: /* 128-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-                break;
-	#ifdef CRYP_KEYSIZE_192B
-            case 12: /* 192-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-                break;
-	#endif
-            case 14: /* 256-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-                break;
-            default:
-                break;
-        }
-        hcryp.Instance = CRYP;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)aes->key;
-
-        HAL_CRYP_Init(&hcryp);
-
-        if (HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE,
-                                       outBlock, STM32_HAL_TIMEOUT) != HAL_OK) {
-            ret = WC_TIMEOUT_E;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-    #else
-        word32 *enc_key;
-        CRYP_InitTypeDef AES_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
-
-        enc_key = aes->key;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
-        CRYP_StructInit(&AES_CRYP_InitStructure);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* load key into correct registers */
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3];
-                break;
-
-            case 12: /* 192-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b;
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5];
-                break;
-
-            case 14: /* 256-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b;
-                AES_CRYP_KeyInitStructure.CRYP_Key0Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[6];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7];
-                break;
-
-            default:
-                break;
-        }
-        CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
-
-        /* set direction, key, and datatype */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        /* wait until decrypt key has been intialized */
-        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-        /* set direction, mode, and datatype */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        /* flush IN/OUT FIFOs */
-        CRYP_FIFOFlush();
-
-        CRYP_DataIn(*(uint32_t*)&inBlock[0]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[4]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[8]);
-        CRYP_DataIn(*(uint32_t*)&inBlock[12]);
-
-        /* wait until the complete message has been processed */
-        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-        *(uint32_t*)&outBlock[0]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[4]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[8]  = CRYP_DataOut();
-        *(uint32_t*)&outBlock[12] = CRYP_DataOut();
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-    #endif /* WOLFSSL_STM32_CUBEMX */
-        return ret;
-    }
-    #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */
-#endif /* HAVE_AES_DECRYPT */
-
-#elif defined(HAVE_COLDFIRE_SEC)
-    /* Freescale Coldfire SEC support for CBC mode.
-     * NOTE: no support for AES-CTR/GCM/CCM/Direct */
-    #include <wolfssl/wolfcrypt/types.h>
-    #include "sec.h"
-    #include "mcf5475_sec.h"
-    #include "mcf5475_siu.h"
-#elif defined(FREESCALE_LTC)
-    #include "fsl_ltc.h"
-    #if defined(FREESCALE_LTC_AES_GCM)
-        #undef NEED_AES_TABLES
-        #undef GCM_TABLE
-    #else
-        /* if LTC doesn't have GCM, use software with LTC AES ECB mode */
-        static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-        {
-            wc_AesEncryptDirect(aes, outBlock, inBlock);
-            return 0;
-        }
-        static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-        {
-            wc_AesDecryptDirect(aes, outBlock, inBlock);
-            return 0;
-        }
-    #endif
-#elif defined(FREESCALE_MMCAU)
-    /* Freescale mmCAU hardware AES support for Direct, CBC, CCM, GCM modes
-     * through the CAU/mmCAU library. Documentation located in
-     * ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library User
-     * Guide (See note in README). */
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        /* MMCAU 1.4 library used with non-KSDK / classic MQX builds */
-        #include "cau_api.h"
-    #else
-        #include "fsl_mmcau.h"
-    #endif
-
-    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        int ret;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad cau_aes_encrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if(ret == 0) {
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
-        #else
-            MMCAU_AES_EncryptEcb(inBlock, (byte*)aes->key, aes->rounds,
-                                 outBlock);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-    #ifdef HAVE_AES_DECRYPT
-    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        int ret;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad cau_aes_decrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if(ret == 0) {
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_aes_decrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
-        #else
-            MMCAU_AES_DecryptEcb(inBlock, (byte*)aes->key, aes->rounds,
-                                 outBlock);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(WOLFSSL_PIC32MZ_CRYPT)
-
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-
-    #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)
-    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0,
-            outBlock, inBlock, AES_BLOCK_SIZE,
-            PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB);
-    }
-    #endif
-
-    #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT)
-    static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0,
-            outBlock, inBlock, AES_BLOCK_SIZE,
-            PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB);
-    }
-    #endif
-
-#elif defined(WOLFSSL_NRF51_AES)
-    /* Use built-in AES hardware - AES 128 ECB Encrypt Only */
-    #include "wolfssl/wolfcrypt/port/nrf51.h"
-
-    static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-    {
-        return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock);
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-        #error nRF51 AES Hardware does not support decrypt
-    #endif /* HAVE_AES_DECRYPT */
-
-
-#elif defined(WOLFSSL_AESNI)
-
-    #define NEED_AES_TABLES
-
-    /* Each platform needs to query info type 1 from cpuid to see if aesni is
-     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
-     */
-
-    #ifndef AESNI_ALIGN
-        #define AESNI_ALIGN 16
-    #endif
-
-    #ifndef _MSC_VER
-        #define XASM_LINK(f) asm(f)
-    #else
-        #define XASM_LINK(f)
-    #endif /* _MSC_VER */
-
-    static int checkAESNI = 0;
-    static int haveAESNI  = 0;
-    static word32 intel_flags = 0;
-
-    static int Check_CPU_support_AES(void)
-    {
-        intel_flags = cpuid_get_flags();
-
-        return IS_INTEL_AESNI(intel_flags) != 0;
-    }
-
-
-    /* tell C compiler these are asm functions in case any mix up of ABI underscore
-       prefix between clang/gcc/llvm etc */
-    #ifdef HAVE_AES_CBC
-        void AES_CBC_encrypt(const unsigned char* in, unsigned char* out,
-                             unsigned char* ivec, unsigned long length,
-                             const unsigned char* KS, int nr)
-                             XASM_LINK("AES_CBC_encrypt");
-
-        #ifdef HAVE_AES_DECRYPT
-            #if defined(WOLFSSL_AESNI_BY4)
-                void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out,
-                                         unsigned char* ivec, unsigned long length,
-                                         const unsigned char* KS, int nr)
-                                         XASM_LINK("AES_CBC_decrypt_by4");
-            #elif defined(WOLFSSL_AESNI_BY6)
-                void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out,
-                                         unsigned char* ivec, unsigned long length,
-                                         const unsigned char* KS, int nr)
-                                         XASM_LINK("AES_CBC_decrypt_by6");
-            #else /* WOLFSSL_AESNI_BYx */
-                void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out,
-                                         unsigned char* ivec, unsigned long length,
-                                         const unsigned char* KS, int nr)
-                                         XASM_LINK("AES_CBC_decrypt_by8");
-            #endif /* WOLFSSL_AESNI_BYx */
-        #endif /* HAVE_AES_DECRYPT */
-    #endif /* HAVE_AES_CBC */
-
-    void AES_ECB_encrypt(const unsigned char* in, unsigned char* out,
-                         unsigned long length, const unsigned char* KS, int nr)
-                         XASM_LINK("AES_ECB_encrypt");
-
-    #ifdef HAVE_AES_DECRYPT
-        void AES_ECB_decrypt(const unsigned char* in, unsigned char* out,
-                             unsigned long length, const unsigned char* KS, int nr)
-                             XASM_LINK("AES_ECB_decrypt");
-    #endif
-
-    void AES_128_Key_Expansion(const unsigned char* userkey,
-                               unsigned char* key_schedule)
-                               XASM_LINK("AES_128_Key_Expansion");
-
-    void AES_192_Key_Expansion(const unsigned char* userkey,
-                               unsigned char* key_schedule)
-                               XASM_LINK("AES_192_Key_Expansion");
-
-    void AES_256_Key_Expansion(const unsigned char* userkey,
-                               unsigned char* key_schedule)
-                               XASM_LINK("AES_256_Key_Expansion");
-
-
-    static int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
-                                   Aes* aes)
-    {
-        int ret;
-
-        if (!userKey || !aes)
-            return BAD_FUNC_ARG;
-
-        switch (bits) {
-            case 128:
-               AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10;
-               return 0;
-            case 192:
-               AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12;
-               return 0;
-            case 256:
-               AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14;
-               return 0;
-            default:
-                ret = BAD_FUNC_ARG;
-        }
-
-        return ret;
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-        static int AES_set_decrypt_key(const unsigned char* userKey,
-                                                    const int bits, Aes* aes)
-        {
-            int nr;
-            Aes temp_key;
-            __m128i *Key_Schedule = (__m128i*)aes->key;
-            __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key;
-
-            if (!userKey || !aes)
-                return BAD_FUNC_ARG;
-
-            if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG)
-                return BAD_FUNC_ARG;
-
-            nr = temp_key.rounds;
-            aes->rounds = nr;
-
-            Key_Schedule[nr] = Temp_Key_Schedule[0];
-            Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]);
-            Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]);
-            Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]);
-            Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]);
-            Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]);
-            Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]);
-            Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]);
-            Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]);
-            Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]);
-
-            if (nr>10) {
-                Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]);
-                Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]);
-            }
-
-            if (nr>12) {
-                Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]);
-                Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]);
-            }
-
-            Key_Schedule[0] = Temp_Key_Schedule[nr];
-
-            return 0;
-        }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-        static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-        {
-            wc_AesEncryptDirect(aes, outBlock, inBlock);
-            return 0;
-        }
-#else
-
-    /* using wolfCrypt software AES implementation */
-    #define NEED_AES_TABLES
-#endif
-
-
-
-#ifdef NEED_AES_TABLES
-
-static const word32 rcon[] = {
-    0x01000000, 0x02000000, 0x04000000, 0x08000000,
-    0x10000000, 0x20000000, 0x40000000, 0x80000000,
-    0x1B000000, 0x36000000,
-    /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
-};
-
-static const word32 Te[4][256] = {
-{
-    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
-    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
-    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
-    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
-    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
-    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
-    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
-    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
-    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
-    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
-    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
-    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
-    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
-    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
-    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
-    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
-    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
-    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
-    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
-    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
-    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
-    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
-    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
-    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
-    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
-    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
-    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
-    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
-    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
-    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
-    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
-    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
-    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
-    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
-    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
-    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
-    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
-    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
-    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
-    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
-    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
-    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
-    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
-    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
-    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
-    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
-    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
-    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
-    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
-    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
-    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
-    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
-    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
-    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
-    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
-    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
-    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
-    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
-    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
-    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
-    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
-    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
-    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
-    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-},
-{
-    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
-    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
-    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
-    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
-    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
-    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
-    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
-    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
-    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
-    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
-    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
-    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
-    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
-    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
-    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
-    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
-    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
-    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
-    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
-    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
-    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
-    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
-    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
-    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
-    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
-    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
-    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
-    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
-    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
-    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
-    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
-    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
-    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
-    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
-    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
-    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
-    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
-    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
-    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
-    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
-    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
-    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
-    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
-    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
-    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
-    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
-    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
-    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
-    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
-    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
-    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
-    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
-    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
-    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
-    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
-    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
-    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
-    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
-    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
-    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
-    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
-    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
-    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
-    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
-},
-{
-    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
-    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
-    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
-    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
-    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
-    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
-    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
-    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
-    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
-    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
-    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
-    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
-    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
-    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
-    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
-    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
-    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
-    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
-    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
-    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
-    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
-    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
-    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
-    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
-    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
-    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
-    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
-    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
-    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
-    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
-    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
-    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
-    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
-    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
-    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
-    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
-    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
-    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
-    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
-    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
-    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
-    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
-    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
-    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
-    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
-    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
-    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
-    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
-    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
-    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
-    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
-    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
-    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
-    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
-    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
-    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
-    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
-    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
-    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
-    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
-    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
-    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
-    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
-    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
-},
-{
-    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
-    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
-    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
-    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
-    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
-    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
-    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
-    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
-    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
-    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
-    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
-    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
-    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
-    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
-    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
-    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
-    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
-    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
-    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
-    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
-    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
-    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
-    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
-    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
-    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
-    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
-    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
-    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
-    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
-    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
-    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
-    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
-    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
-    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
-    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
-    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
-    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
-    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
-    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
-    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
-    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
-    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
-    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
-    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
-    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
-    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
-    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
-    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
-    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
-    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
-    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
-    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
-    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
-    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
-    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
-    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
-    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
-    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
-    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
-    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
-    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
-    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
-    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
-    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
-}
-};
-
-#ifdef HAVE_AES_DECRYPT
-static const word32 Td[4][256] = {
-{
-    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
-    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
-    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
-    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
-    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
-    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
-    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
-    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
-    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
-    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
-    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
-    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
-    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
-    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
-    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
-    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
-    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
-    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
-    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
-    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
-    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
-    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
-    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
-    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
-    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
-    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
-    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
-    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
-    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
-    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
-    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
-    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
-    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
-    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
-    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
-    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
-    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
-    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
-    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
-    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
-    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
-    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
-    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
-    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
-    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
-    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
-    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
-    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
-    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
-    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
-    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
-    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
-    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
-    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
-    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
-    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
-    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
-    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
-    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
-    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
-    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
-    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
-    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
-    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
-},
-{
-    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
-    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
-    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
-    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
-    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
-    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
-    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
-    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
-    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
-    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
-    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
-    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
-    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
-    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
-    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
-    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
-    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
-    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
-    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
-    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
-    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
-    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
-    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
-    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
-    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
-    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
-    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
-    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
-    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
-    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
-    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
-    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
-    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
-    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
-    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
-    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
-    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
-    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
-    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
-    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
-    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
-    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
-    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
-    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
-    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
-    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
-    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
-    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
-    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
-    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
-    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
-    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
-    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
-    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
-    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
-    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
-    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
-    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
-    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
-    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
-    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
-    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
-    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
-    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
-},
-{
-    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
-    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
-    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
-    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
-    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
-    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
-    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
-    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
-    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
-    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
-    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
-    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
-    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
-    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
-    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
-    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
-    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
-    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
-    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
-    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
-
-    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
-    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
-    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
-    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
-    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
-    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
-    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
-    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
-    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
-    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
-    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
-    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
-    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
-    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
-    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
-    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
-    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
-    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
-    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
-    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
-    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
-    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
-    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
-    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
-    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
-    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
-    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
-    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
-    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
-    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
-    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
-    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
-    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
-    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
-    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
-    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
-    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
-    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
-    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
-    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
-    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
-    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
-    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
-    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
-},
-{
-    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
-    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
-    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
-    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
-    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
-    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
-    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
-    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
-    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
-    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
-    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
-    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
-    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
-    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
-    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
-    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
-    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
-    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
-    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
-    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
-    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
-    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
-    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
-    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
-    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
-    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
-    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
-    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
-    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
-    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
-    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
-    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
-    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
-    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
-    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
-    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
-    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
-    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
-    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
-    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
-    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
-    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
-    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
-    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
-    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
-    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
-    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
-    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
-    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
-    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
-    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
-    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
-    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
-    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
-    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
-    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
-    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
-    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
-    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
-    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
-    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
-    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
-    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
-    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
-}
-};
-
-
-static const byte Td4[256] =
-{
-    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
-    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
-    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
-    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
-    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
-    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
-    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
-    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
-    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
-    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
-    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
-    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
-    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
-    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
-    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
-    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
-    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
-    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
-    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
-    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
-    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
-    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
-    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
-    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
-    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
-    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
-    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
-    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
-    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
-    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
-    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
-    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
-};
-#endif /* HAVE_AES_DECRYPT */
-
-#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y))))
-
-
-
-#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM)
-
-#ifndef WC_CACHE_LINE_SZ
-    #if defined(__x86_64__) || defined(_M_X64) || \
-       (defined(__ILP32__) && (__ILP32__ >= 1))
-        #define WC_CACHE_LINE_SZ 64
-    #else
-        /* default cache line size */
-        #define WC_CACHE_LINE_SZ 32
-    #endif
-#endif
-
-
-/* load 4 Te Tables into cache by cache line stride */
-static WC_INLINE word32 PreFetchTe(void)
-{
-    word32 x = 0;
-    int i,j;
-
-    for (i = 0; i < 4; i++) {
-        /* 256 elements, each one is 4 bytes */
-        for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) {
-            x &= Te[i][j];
-        }
-    }
-    return x;
-}
-
-
-static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-{
-    word32 s0, s1, s2, s3;
-    word32 t0, t1, t2, t3;
-    word32 r = aes->rounds >> 1;
-    const word32* rk = aes->key;
-
-    if (r > 7 || r == 0) {
-        WOLFSSL_MSG("AesEncrypt encountered improper key, set it up");
-        return;  /* stop instead of segfaulting, set up your keys! */
-    }
-
-#ifdef WOLFSSL_AESNI
-    if (haveAESNI && aes->use_aesni) {
-        #ifdef DEBUG_AESNI
-            printf("about to aes encrypt\n");
-            printf("in  = %p\n", inBlock);
-            printf("out = %p\n", outBlock);
-            printf("aes->key = %p\n", aes->key);
-            printf("aes->rounds = %d\n", aes->rounds);
-            printf("sz = %d\n", AES_BLOCK_SIZE);
-        #endif
-
-        /* check alignment, decrypt doesn't need alignment */
-        if ((wolfssl_word)inBlock % AESNI_ALIGN) {
-        #ifndef NO_WOLFSSL_ALLOC_ALIGN
-            byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE + AESNI_ALIGN, aes->heap,
-                                                      DYNAMIC_TYPE_TMP_BUFFER);
-            byte* tmp_align;
-            if (tmp == NULL) return;
-
-            tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN));
-
-            XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE);
-            AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE, (byte*)aes->key,
-                            aes->rounds);
-            XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE);
-            XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return;
-        #else
-            WOLFSSL_MSG("AES-ECB encrypt with bad alignment");
-            return;
-        #endif
-        }
-
-        AES_ECB_encrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key,
-                        aes->rounds);
-
-        return;
-    }
-    else {
-        #ifdef DEBUG_AESNI
-            printf("Skipping AES-NI\n");
-        #endif
-    }
-#endif
-
-    /*
-     * map byte array block to cipher state
-     * and add initial round key:
-     */
-    XMEMCPY(&s0, inBlock,                  sizeof(s0));
-    XMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));
-    XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
-    XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
-
-#ifdef LITTLE_ENDIAN_ORDER
-    s0 = ByteReverseWord32(s0);
-    s1 = ByteReverseWord32(s1);
-    s2 = ByteReverseWord32(s2);
-    s3 = ByteReverseWord32(s3);
-#endif
-
-    s0 ^= rk[0];
-    s1 ^= rk[1];
-    s2 ^= rk[2];
-    s3 ^= rk[3];
-
-    s0 |= PreFetchTe();
-
-    /*
-     * Nr - 1 full rounds:
-     */
-
-    for (;;) {
-        t0 =
-            Te[0][GETBYTE(s0, 3)]  ^
-            Te[1][GETBYTE(s1, 2)]  ^
-            Te[2][GETBYTE(s2, 1)]  ^
-            Te[3][GETBYTE(s3, 0)]  ^
-            rk[4];
-        t1 =
-            Te[0][GETBYTE(s1, 3)]  ^
-            Te[1][GETBYTE(s2, 2)]  ^
-            Te[2][GETBYTE(s3, 1)]  ^
-            Te[3][GETBYTE(s0, 0)]  ^
-            rk[5];
-        t2 =
-            Te[0][GETBYTE(s2, 3)] ^
-            Te[1][GETBYTE(s3, 2)]  ^
-            Te[2][GETBYTE(s0, 1)]  ^
-            Te[3][GETBYTE(s1, 0)]  ^
-            rk[6];
-        t3 =
-            Te[0][GETBYTE(s3, 3)] ^
-            Te[1][GETBYTE(s0, 2)]  ^
-            Te[2][GETBYTE(s1, 1)]  ^
-            Te[3][GETBYTE(s2, 0)]  ^
-            rk[7];
-
-        rk += 8;
-        if (--r == 0) {
-            break;
-        }
-
-        s0 =
-            Te[0][GETBYTE(t0, 3)] ^
-            Te[1][GETBYTE(t1, 2)] ^
-            Te[2][GETBYTE(t2, 1)] ^
-            Te[3][GETBYTE(t3, 0)] ^
-            rk[0];
-        s1 =
-            Te[0][GETBYTE(t1, 3)] ^
-            Te[1][GETBYTE(t2, 2)] ^
-            Te[2][GETBYTE(t3, 1)] ^
-            Te[3][GETBYTE(t0, 0)] ^
-            rk[1];
-        s2 =
-            Te[0][GETBYTE(t2, 3)] ^
-            Te[1][GETBYTE(t3, 2)] ^
-            Te[2][GETBYTE(t0, 1)] ^
-            Te[3][GETBYTE(t1, 0)] ^
-            rk[2];
-        s3 =
-            Te[0][GETBYTE(t3, 3)] ^
-            Te[1][GETBYTE(t0, 2)] ^
-            Te[2][GETBYTE(t1, 1)] ^
-            Te[3][GETBYTE(t2, 0)] ^
-            rk[3];
-    }
-
-    /*
-     * apply last round and
-     * map cipher state to byte array block:
-     */
-
-    s0 =
-        (Te[2][GETBYTE(t0, 3)] & 0xff000000) ^
-        (Te[3][GETBYTE(t1, 2)] & 0x00ff0000) ^
-        (Te[0][GETBYTE(t2, 1)] & 0x0000ff00) ^
-        (Te[1][GETBYTE(t3, 0)] & 0x000000ff) ^
-        rk[0];
-    s1 =
-        (Te[2][GETBYTE(t1, 3)] & 0xff000000) ^
-        (Te[3][GETBYTE(t2, 2)] & 0x00ff0000) ^
-        (Te[0][GETBYTE(t3, 1)] & 0x0000ff00) ^
-        (Te[1][GETBYTE(t0, 0)] & 0x000000ff) ^
-        rk[1];
-    s2 =
-        (Te[2][GETBYTE(t2, 3)] & 0xff000000) ^
-        (Te[3][GETBYTE(t3, 2)] & 0x00ff0000) ^
-        (Te[0][GETBYTE(t0, 1)] & 0x0000ff00) ^
-        (Te[1][GETBYTE(t1, 0)] & 0x000000ff) ^
-        rk[2];
-    s3 =
-        (Te[2][GETBYTE(t3, 3)] & 0xff000000) ^
-        (Te[3][GETBYTE(t0, 2)] & 0x00ff0000) ^
-        (Te[0][GETBYTE(t1, 1)] & 0x0000ff00) ^
-        (Te[1][GETBYTE(t2, 0)] & 0x000000ff) ^
-        rk[3];
-
-    /* write out */
-#ifdef LITTLE_ENDIAN_ORDER
-    s0 = ByteReverseWord32(s0);
-    s1 = ByteReverseWord32(s1);
-    s2 = ByteReverseWord32(s2);
-    s3 = ByteReverseWord32(s3);
-#endif
-
-    XMEMCPY(outBlock,                  &s0, sizeof(s0));
-    XMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));
-    XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
-    XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
-
-}
-#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */
-
-#if defined(HAVE_AES_DECRYPT)
-#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)
-
-/* load 4 Td Tables into cache by cache line stride */
-static WC_INLINE word32 PreFetchTd(void)
-{
-    word32 x = 0;
-    int i,j;
-
-    for (i = 0; i < 4; i++) {
-        /* 256 elements, each one is 4 bytes */
-        for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) {
-            x &= Td[i][j];
-        }
-    }
-    return x;
-}
-
-/* load Td Table4 into cache by cache line stride */
-static WC_INLINE word32 PreFetchTd4(void)
-{
-    word32 x = 0;
-    int i;
-
-    for (i = 0; i < 256; i += WC_CACHE_LINE_SZ) {
-        x &= (word32)Td4[i];
-    }
-    return x;
-}
-
-static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
-{
-    word32 s0, s1, s2, s3;
-    word32 t0, t1, t2, t3;
-    word32 r = aes->rounds >> 1;
-
-    const word32* rk = aes->key;
-    if (r > 7 || r == 0) {
-        WOLFSSL_MSG("AesDecrypt encountered improper key, set it up");
-        return;  /* stop instead of segfaulting, set up your keys! */
-    }
-#ifdef WOLFSSL_AESNI
-    if (haveAESNI && aes->use_aesni) {
-        #ifdef DEBUG_AESNI
-            printf("about to aes decrypt\n");
-            printf("in  = %p\n", inBlock);
-            printf("out = %p\n", outBlock);
-            printf("aes->key = %p\n", aes->key);
-            printf("aes->rounds = %d\n", aes->rounds);
-            printf("sz = %d\n", AES_BLOCK_SIZE);
-        #endif
-
-        /* if input and output same will overwrite input iv */
-        XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE);
-        AES_ECB_decrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key,
-                        aes->rounds);
-        return;
-    }
-    else {
-        #ifdef DEBUG_AESNI
-            printf("Skipping AES-NI\n");
-        #endif
-    }
-#endif /* WOLFSSL_AESNI */
-
-    /*
-     * map byte array block to cipher state
-     * and add initial round key:
-     */
-    XMEMCPY(&s0, inBlock,                  sizeof(s0));
-    XMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));
-    XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
-    XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
-
-#ifdef LITTLE_ENDIAN_ORDER
-    s0 = ByteReverseWord32(s0);
-    s1 = ByteReverseWord32(s1);
-    s2 = ByteReverseWord32(s2);
-    s3 = ByteReverseWord32(s3);
-#endif
-
-    s0 ^= rk[0];
-    s1 ^= rk[1];
-    s2 ^= rk[2];
-    s3 ^= rk[3];
-
-    s0 |= PreFetchTd();
-
-    /*
-     * Nr - 1 full rounds:
-     */
-
-    for (;;) {
-        t0 =
-            Td[0][GETBYTE(s0, 3)] ^
-            Td[1][GETBYTE(s3, 2)] ^
-            Td[2][GETBYTE(s2, 1)] ^
-            Td[3][GETBYTE(s1, 0)] ^
-            rk[4];
-        t1 =
-            Td[0][GETBYTE(s1, 3)] ^
-            Td[1][GETBYTE(s0, 2)] ^
-            Td[2][GETBYTE(s3, 1)] ^
-            Td[3][GETBYTE(s2, 0)] ^
-            rk[5];
-        t2 =
-            Td[0][GETBYTE(s2, 3)] ^
-            Td[1][GETBYTE(s1, 2)] ^
-            Td[2][GETBYTE(s0, 1)] ^
-            Td[3][GETBYTE(s3, 0)] ^
-            rk[6];
-        t3 =
-            Td[0][GETBYTE(s3, 3)] ^
-            Td[1][GETBYTE(s2, 2)] ^
-            Td[2][GETBYTE(s1, 1)] ^
-            Td[3][GETBYTE(s0, 0)] ^
-            rk[7];
-
-        rk += 8;
-        if (--r == 0) {
-            break;
-        }
-
-        s0 =
-            Td[0][GETBYTE(t0, 3)] ^
-            Td[1][GETBYTE(t3, 2)] ^
-            Td[2][GETBYTE(t2, 1)] ^
-            Td[3][GETBYTE(t1, 0)] ^
-            rk[0];
-        s1 =
-            Td[0][GETBYTE(t1, 3)] ^
-            Td[1][GETBYTE(t0, 2)] ^
-            Td[2][GETBYTE(t3, 1)] ^
-            Td[3][GETBYTE(t2, 0)] ^
-            rk[1];
-        s2 =
-            Td[0][GETBYTE(t2, 3)] ^
-            Td[1][GETBYTE(t1, 2)] ^
-            Td[2][GETBYTE(t0, 1)] ^
-            Td[3][GETBYTE(t3, 0)] ^
-            rk[2];
-        s3 =
-            Td[0][GETBYTE(t3, 3)] ^
-            Td[1][GETBYTE(t2, 2)] ^
-            Td[2][GETBYTE(t1, 1)] ^
-            Td[3][GETBYTE(t0, 0)] ^
-            rk[3];
-    }
-    /*
-     * apply last round and
-     * map cipher state to byte array block:
-     */
-
-    t0 |= PreFetchTd4();
-
-    s0 =
-        ((word32)Td4[GETBYTE(t0, 3)] << 24) ^
-        ((word32)Td4[GETBYTE(t3, 2)] << 16) ^
-        ((word32)Td4[GETBYTE(t2, 1)] <<  8) ^
-        ((word32)Td4[GETBYTE(t1, 0)]) ^
-        rk[0];
-    s1 =
-        ((word32)Td4[GETBYTE(t1, 3)] << 24) ^
-        ((word32)Td4[GETBYTE(t0, 2)] << 16) ^
-        ((word32)Td4[GETBYTE(t3, 1)] <<  8) ^
-        ((word32)Td4[GETBYTE(t2, 0)]) ^
-        rk[1];
-    s2 =
-        ((word32)Td4[GETBYTE(t2, 3)] << 24) ^
-        ((word32)Td4[GETBYTE(t1, 2)] << 16) ^
-        ((word32)Td4[GETBYTE(t0, 1)] <<  8) ^
-        ((word32)Td4[GETBYTE(t3, 0)]) ^
-        rk[2];
-    s3 =
-        ((word32)Td4[GETBYTE(t3, 3)] << 24) ^
-        ((word32)Td4[GETBYTE(t2, 2)] << 16) ^
-        ((word32)Td4[GETBYTE(t1, 1)] <<  8) ^
-        ((word32)Td4[GETBYTE(t0, 0)]) ^
-        rk[3];
-
-    /* write out */
-#ifdef LITTLE_ENDIAN_ORDER
-    s0 = ByteReverseWord32(s0);
-    s1 = ByteReverseWord32(s1);
-    s2 = ByteReverseWord32(s2);
-    s3 = ByteReverseWord32(s3);
-#endif
-
-    XMEMCPY(outBlock,                  &s0, sizeof(s0));
-    XMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));
-    XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
-    XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
-}
-#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */
-#endif /* HAVE_AES_DECRYPT */
-
-#endif /* NEED_AES_TABLES */
-
-
-
-/* wc_AesSetKey */
-#if defined(STM32_CRYPTO)
-
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
-            const byte* iv, int dir)
-    {
-        word32 *rk = aes->key;
-
-        (void)dir;
-
-        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
-            return BAD_FUNC_ARG;
-
-        aes->keylen = keylen;
-        aes->rounds = keylen/4 + 6;
-        XMEMCPY(rk, userKey, keylen);
-    #ifndef WOLFSSL_STM32_CUBEMX
-        ByteReverseWords(rk, rk, keylen);
-    #endif
-    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-        aes->left = 0;
-    #endif
-
-        return wc_AesSetIV(aes, iv);
-    }
-    #if defined(WOLFSSL_AES_DIRECT)
-        int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
-                            const byte* iv, int dir)
-        {
-            return wc_AesSetKey(aes, userKey, keylen, iv, dir);
-        }
-    #endif
-
-#elif defined(HAVE_COLDFIRE_SEC)
-    #if defined (HAVE_THREADX)
-        #include "memory_pools.h"
-        extern TX_BYTE_POOL mp_ncached;  /* Non Cached memory pool */
-    #endif
-
-    #define AES_BUFFER_SIZE (AES_BLOCK_SIZE * 64)
-    static unsigned char *AESBuffIn = NULL;
-    static unsigned char *AESBuffOut = NULL;
-    static byte *secReg;
-    static byte *secKey;
-    static volatile SECdescriptorType *secDesc;
-
-    static wolfSSL_Mutex Mutex_AesSEC;
-
-    #define SEC_DESC_AES_CBC_ENCRYPT 0x60300010
-    #define SEC_DESC_AES_CBC_DECRYPT 0x60200010
-
-    extern volatile unsigned char __MBAR[];
-
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
-        const byte* iv, int dir)
-    {
-        if (AESBuffIn == NULL) {
-        #if defined (HAVE_THREADX)
-            int s1, s2, s3, s4, s5;
-            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
-                                  sizeof(SECdescriptorType), TX_NO_WAIT);
-            s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn,
-                                  AES_BUFFER_SIZE, TX_NO_WAIT);
-            s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut,
-                                  AES_BUFFER_SIZE, TX_NO_WAIT);
-            s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey,
-                                  AES_BLOCK_SIZE*2, TX_NO_WAIT);
-            s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg,
-                                  AES_BLOCK_SIZE, TX_NO_WAIT);
-
-            if (s1 || s2 || s3 || s4 || s5)
-                return BAD_FUNC_ARG;
-        #else
-            #warning "Allocate non-Cache buffers"
-        #endif
-
-            wc_InitMutex(&Mutex_AesSEC);
-        }
-
-        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
-            return BAD_FUNC_ARG;
-
-        if (aes == NULL)
-            return BAD_FUNC_ARG;
-
-        aes->keylen = keylen;
-        aes->rounds = keylen/4 + 6;
-        XMEMCPY(aes->key, userKey, keylen);
-
-        if (iv)
-            XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
-
-    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-        aes->left = 0;
-    #endif
-
-        return 0;
-    }
-#elif defined(FREESCALE_LTC)
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv,
-                  int dir)
-    {
-        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
-            return BAD_FUNC_ARG;
-
-        aes->rounds = keylen/4 + 6;
-        XMEMCPY(aes->key, userKey, keylen);
-
-    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-        aes->left = 0;
-    #endif
-
-        return wc_AesSetIV(aes, iv);
-    }
-
-    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
-                        const byte* iv, int dir)
-    {
-        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
-    }
-#elif defined(FREESCALE_MMCAU)
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
-        const byte* iv, int dir)
-    {
-        int ret;
-        byte *rk = (byte*)aes->key;
-
-        (void)dir;
-
-        if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
-            return BAD_FUNC_ARG;
-
-        if (rk == NULL)
-            return BAD_FUNC_ARG;
-
-    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-        aes->left = 0;
-    #endif
-
-        aes->rounds = keylen/4 + 6;
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if(ret == 0) {
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_aes_set_key(userKey, keylen*8, rk);
-        #else
-            MMCAU_AES_SetKey(userKey, keylen, rk);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-
-            ret = wc_AesSetIV(aes, iv);
-        }
-
-        return ret;
-    }
-
-    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
-                        const byte* iv, int dir)
-    {
-        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
-    }
-
-#elif defined(WOLFSSL_NRF51_AES)
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
-        const byte* iv, int dir)
-    {
-        int ret;
-
-        (void)dir;
-        (void)iv;
-
-        if (keylen != 16)
-            return BAD_FUNC_ARG;
-
-        aes->keylen = keylen;
-        aes->rounds = keylen/4 + 6;
-        ret = nrf51_aes_set_key(userKey);
-
-    #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-        aes->left = 0;
-    #endif
-
-        return ret;
-    }
-
-    int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
-                        const byte* iv, int dir)
-    {
-        return wc_AesSetKey(aes, userKey, keylen, iv, dir);
-    }
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
-
-#else
-    static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen,
-                const byte* iv, int dir)
-    {
-        word32 *rk = aes->key;
-    #ifdef NEED_AES_TABLES
-        word32 temp;
-        unsigned int i = 0;
-    #endif
-
-        #ifdef WOLFSSL_AESNI
-            aes->use_aesni = 0;
-        #endif /* WOLFSSL_AESNI */
-        #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER)
-            aes->left = 0;
-        #endif
-
-        aes->keylen = keylen;
-        aes->rounds = (keylen/4) + 6;
-
-        XMEMCPY(rk, userKey, keylen);
-    #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT)
-        ByteReverseWords(rk, rk, keylen);
-    #endif
-
-#ifdef NEED_AES_TABLES
-
-        switch (keylen) {
-    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \
-            defined(WOLFSSL_AES_128)
-        case 16:
-            while (1)
-            {
-                temp  = rk[3];
-                rk[4] = rk[0] ^
-                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
-                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
-                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
-                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
-                    rcon[i];
-                rk[5] = rk[1] ^ rk[4];
-                rk[6] = rk[2] ^ rk[5];
-                rk[7] = rk[3] ^ rk[6];
-                if (++i == 10)
-                    break;
-                rk += 4;
-            }
-            break;
-    #endif /* 128 */
-
-    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 && \
-            defined(WOLFSSL_AES_192)
-        case 24:
-            /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */
-            while (1)
-            {
-                temp = rk[ 5];
-                rk[ 6] = rk[ 0] ^
-                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
-                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
-                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
-                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
-                    rcon[i];
-                rk[ 7] = rk[ 1] ^ rk[ 6];
-                rk[ 8] = rk[ 2] ^ rk[ 7];
-                rk[ 9] = rk[ 3] ^ rk[ 8];
-                if (++i == 8)
-                    break;
-                rk[10] = rk[ 4] ^ rk[ 9];
-                rk[11] = rk[ 5] ^ rk[10];
-                rk += 6;
-            }
-            break;
-    #endif /* 192 */
-
-    #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 && \
-            defined(WOLFSSL_AES_256)
-        case 32:
-            while (1)
-            {
-                temp = rk[ 7];
-                rk[ 8] = rk[ 0] ^
-                    (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^
-                    (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^
-                    (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^
-                    (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^
-                    rcon[i];
-                rk[ 9] = rk[ 1] ^ rk[ 8];
-                rk[10] = rk[ 2] ^ rk[ 9];
-                rk[11] = rk[ 3] ^ rk[10];
-                if (++i == 7)
-                    break;
-                temp = rk[11];
-                rk[12] = rk[ 4] ^
-                    (Te[2][GETBYTE(temp, 3)] & 0xff000000) ^
-                    (Te[3][GETBYTE(temp, 2)] & 0x00ff0000) ^
-                    (Te[0][GETBYTE(temp, 1)] & 0x0000ff00) ^
-                    (Te[1][GETBYTE(temp, 0)] & 0x000000ff);
-                rk[13] = rk[ 5] ^ rk[12];
-                rk[14] = rk[ 6] ^ rk[13];
-                rk[15] = rk[ 7] ^ rk[14];
-
-                rk += 8;
-            }
-            break;
-    #endif /* 256 */
-
-        default:
-            return BAD_FUNC_ARG;
-        } /* switch */
-
-    #ifdef HAVE_AES_DECRYPT
-        if (dir == AES_DECRYPTION) {
-            unsigned int j;
-            rk = aes->key;
-
-            /* invert the order of the round keys: */
-            for (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) {
-                temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
-                temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
-                temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
-                temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
-            }
-            /* apply the inverse MixColumn transform to all round keys but the
-               first and the last: */
-            for (i = 1; i < aes->rounds; i++) {
-                rk += 4;
-                rk[0] =
-                    Td[0][Te[1][GETBYTE(rk[0], 3)] & 0xff] ^
-                    Td[1][Te[1][GETBYTE(rk[0], 2)] & 0xff] ^
-                    Td[2][Te[1][GETBYTE(rk[0], 1)] & 0xff] ^
-                    Td[3][Te[1][GETBYTE(rk[0], 0)] & 0xff];
-                rk[1] =
-                    Td[0][Te[1][GETBYTE(rk[1], 3)] & 0xff] ^
-                    Td[1][Te[1][GETBYTE(rk[1], 2)] & 0xff] ^
-                    Td[2][Te[1][GETBYTE(rk[1], 1)] & 0xff] ^
-                    Td[3][Te[1][GETBYTE(rk[1], 0)] & 0xff];
-                rk[2] =
-                    Td[0][Te[1][GETBYTE(rk[2], 3)] & 0xff] ^
-                    Td[1][Te[1][GETBYTE(rk[2], 2)] & 0xff] ^
-                    Td[2][Te[1][GETBYTE(rk[2], 1)] & 0xff] ^
-                    Td[3][Te[1][GETBYTE(rk[2], 0)] & 0xff];
-                rk[3] =
-                    Td[0][Te[1][GETBYTE(rk[3], 3)] & 0xff] ^
-                    Td[1][Te[1][GETBYTE(rk[3], 2)] & 0xff] ^
-                    Td[2][Te[1][GETBYTE(rk[3], 1)] & 0xff] ^
-                    Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff];
-            }
-        }
-    #else
-        (void)dir;
-    #endif /* HAVE_AES_DECRYPT */
-#endif /* NEED_AES_TABLES */
-
-        return wc_AesSetIV(aes, iv);
-    }
-
-    int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
-        const byte* iv, int dir)
-    {
-        int ret;
-    #if defined(AES_MAX_KEY_SIZE)
-        const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
-    #endif
-
-    #ifdef WOLFSSL_IMX6_CAAM_BLOB
-        byte   local[32];
-        word32 localSz = 32;
-
-        if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
-                keylen == (24 + WC_CAAM_BLOB_SZ) ||
-                keylen == (32 + WC_CAAM_BLOB_SZ)) {
-            if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) {
-                return BAD_FUNC_ARG;
-            }
-
-            /* set local values */
-            userKey = local;
-            keylen = localSz;
-        }
-    #endif
-        if (aes == NULL ||
-                !((keylen == 16) || (keylen == 24) || (keylen == 32))) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(AES_MAX_KEY_SIZE)
-        /* Check key length */
-        if (keylen > max_key_len) {
-            return BAD_FUNC_ARG;
-        }
-    #endif
-        aes->keylen = keylen;
-        aes->rounds = keylen/4 + 6;
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-        if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) {
-            XMEMCPY(aes->asyncKey, userKey, keylen);
-            if (iv)
-                XMEMCPY(aes->asyncIv, iv, AES_BLOCK_SIZE);
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-    #ifdef WOLFSSL_AESNI
-        if (checkAESNI == 0) {
-            haveAESNI  = Check_CPU_support_AES();
-            checkAESNI = 1;
-        }
-        if (haveAESNI) {
-            #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB)
-                aes->left = 0;
-            #endif /* WOLFSSL_AES_COUNTER */
-            aes->use_aesni = 1;
-            if (iv)
-                XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
-            if (dir == AES_ENCRYPTION)
-                return AES_set_encrypt_key(userKey, keylen * 8, aes);
-        #ifdef HAVE_AES_DECRYPT
-            else
-                return AES_set_decrypt_key(userKey, keylen * 8, aes);
-        #endif
-        }
-    #endif /* WOLFSSL_AESNI */
-
-        ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
-
-    #ifdef WOLFSSL_IMX6_CAAM_BLOB
-        ForceZero(local, sizeof(local));
-    #endif
-        return ret;
-    }
-
-    #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER)
-        /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */
-        int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
-                            const byte* iv, int dir)
-        {
-            int ret;
-
-        #ifdef WOLFSSL_IMX6_CAAM_BLOB
-            byte   local[32];
-            word32 localSz = 32;
-
-            if (keylen == (16 + WC_CAAM_BLOB_SZ) ||
-             keylen == (24 + WC_CAAM_BLOB_SZ) ||
-             keylen == (32 + WC_CAAM_BLOB_SZ)) {
-                if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz)
-                        != 0) {
-                    return BAD_FUNC_ARG;
-                }
-
-                /* set local values */
-                userKey = local;
-                keylen = localSz;
-            }
-        #endif
-            ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);
-
-        #ifdef WOLFSSL_IMX6_CAAM_BLOB
-            ForceZero(local, sizeof(local));
-        #endif
-
-            return ret;
-        }
-    #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */
-#endif /* wc_AesSetKey block */
-
-
-/* wc_AesSetIV is shared between software and hardware */
-int wc_AesSetIV(Aes* aes, const byte* iv)
-{
-    if (aes == NULL)
-        return BAD_FUNC_ARG;
-
-    if (iv)
-        XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
-    else
-        XMEMSET(aes->reg,  0, AES_BLOCK_SIZE);
-
-    return 0;
-}
-
-/* AES-DIRECT */
-#if defined(WOLFSSL_AES_DIRECT)
-    #if defined(HAVE_COLDFIRE_SEC)
-        #error "Coldfire SEC doesn't yet support AES direct"
-
-    #elif defined(FREESCALE_LTC)
-        /* Allow direct access to one block encrypt */
-        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
-        {
-            byte *key;
-            uint32_t keySize;
-
-            key = (byte*)aes->key;
-            wc_AesGetKeySize(aes, &keySize);
-
-            LTC_AES_EncryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
-                key, keySize);
-        }
-
-        /* Allow direct access to one block decrypt */
-        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
-        {
-            byte *key;
-            uint32_t keySize;
-
-            key = (byte*)aes->key;
-            wc_AesGetKeySize(aes, &keySize);
-
-            LTC_AES_DecryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE,
-                key, keySize, kLTC_EncryptKey);
-        }
-
-    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
-
-    #else
-        /* Allow direct access to one block encrypt */
-        void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
-        {
-            wc_AesEncrypt(aes, in, out);
-        }
-    #ifdef HAVE_AES_DECRYPT
-        /* Allow direct access to one block decrypt */
-        void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
-        {
-            wc_AesDecrypt(aes, in, out);
-        }
-    #endif /* HAVE_AES_DECRYPT */
-    #endif /* AES direct block */
-#endif /* WOLFSSL_AES_DIRECT */
-
-
-/* AES-CBC */
-#ifdef HAVE_AES_CBC
-#if defined(STM32_CRYPTO)
-
-#ifdef WOLFSSL_STM32_CUBEMX
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int ret = 0;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-                break;
-	#ifdef CRYP_KEYSIZE_192B
-            case 12: /* 192-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-                break;
-	#endif
-            case 14: /* 256-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-                break;
-            default:
-                break;
-        }
-        hcryp.Instance = CRYP;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)aes->key;
-        hcryp.Init.pInitVect = (uint8_t*)aes->reg;
-
-        HAL_CRYP_Init(&hcryp);
-
-        while (blocks--) {
-            if (HAL_CRYP_AESCBC_Encrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
-                                           out, STM32_HAL_TIMEOUT) != HAL_OK) {
-                ret = WC_TIMEOUT_E;
-                break;
-            }
-
-            /* store iv for next call */
-            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-            sz  -= AES_BLOCK_SIZE;
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-
-        return ret;
-    }
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int ret = 0;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-                break;
-	#ifdef CRYP_KEYSIZE_192B
-            case 12: /* 192-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-                break;
-	#endif
-            case 14: /* 256-bit key */
-                hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-                break;
-            default:
-                break;
-        }
-        hcryp.Instance = CRYP;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)aes->key;
-        hcryp.Init.pInitVect = (uint8_t*)aes->reg;
-
-        HAL_CRYP_Init(&hcryp);
-
-        while (blocks--) {
-            if (HAL_CRYP_AESCBC_Decrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE,
-                                           out, STM32_HAL_TIMEOUT) != HAL_OK) {
-                ret = WC_TIMEOUT_E;
-            }
-
-            /* store iv for next call */
-            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
-
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-
-        return ret;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-#else
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        word32 *enc_key, *iv;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        CRYP_InitTypeDef AES_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
-        CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
-
-        enc_key = aes->key;
-        iv = aes->reg;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
-        CRYP_StructInit(&AES_CRYP_InitStructure);
-        CRYP_IVStructInit(&AES_CRYP_IVInitStructure);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* load key into correct registers */
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3];
-                break;
-
-            case 12: /* 192-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b;
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5];
-                break;
-
-            case 14: /* 256-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b;
-                AES_CRYP_KeyInitStructure.CRYP_Key0Left  = enc_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[6];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7];
-                break;
-
-            default:
-                break;
-        }
-        CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
-
-        /* set iv */
-        ByteReverseWords(iv, iv, AES_BLOCK_SIZE);
-        AES_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
-        AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
-        AES_CRYP_IVInitStructure.CRYP_IV1Left  = iv[2];
-        AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3];
-        CRYP_IVInit(&AES_CRYP_IVInitStructure);
-
-        /* set direction, mode, and datatype */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        while (blocks--) {
-            /* flush IN/OUT FIFOs */
-            CRYP_FIFOFlush();
-
-            CRYP_DataIn(*(uint32_t*)&in[0]);
-            CRYP_DataIn(*(uint32_t*)&in[4]);
-            CRYP_DataIn(*(uint32_t*)&in[8]);
-            CRYP_DataIn(*(uint32_t*)&in[12]);
-
-            /* wait until the complete message has been processed */
-            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-            *(uint32_t*)&out[0]  = CRYP_DataOut();
-            *(uint32_t*)&out[4]  = CRYP_DataOut();
-            *(uint32_t*)&out[8]  = CRYP_DataOut();
-            *(uint32_t*)&out[12] = CRYP_DataOut();
-
-            /* store iv for next call */
-            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-            sz  -= AES_BLOCK_SIZE;
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-        }
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-
-        return 0;
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        word32 *dec_key, *iv;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        CRYP_InitTypeDef AES_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
-        CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
-
-        dec_key = aes->key;
-        iv = aes->reg;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
-        CRYP_StructInit(&AES_CRYP_InitStructure);
-        CRYP_IVStructInit(&AES_CRYP_IVInitStructure);
-
-        /* if input and output same will overwrite input iv */
-        XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* load key into correct registers */
-        switch (aes->rounds) {
-            case 10: /* 128-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = dec_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = dec_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[3];
-                break;
-
-            case 12: /* 192-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b;
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = dec_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = dec_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = dec_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[5];
-                break;
-
-            case 14: /* 256-bit key */
-                AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b;
-                AES_CRYP_KeyInitStructure.CRYP_Key0Left  = dec_key[0];
-                AES_CRYP_KeyInitStructure.CRYP_Key0Right = dec_key[1];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Left  = dec_key[2];
-                AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[3];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Left  = dec_key[4];
-                AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[5];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Left  = dec_key[6];
-                AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[7];
-                break;
-
-            default:
-                break;
-        }
-
-        /* set direction, mode, and datatype for key preparation */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-        CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        /* wait until key has been prepared */
-        while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-        /* set direction, mode, and datatype for decryption */
-        AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
-        AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&AES_CRYP_InitStructure);
-
-        /* set iv */
-        ByteReverseWords(iv, iv, AES_BLOCK_SIZE);
-
-        AES_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
-        AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
-        AES_CRYP_IVInitStructure.CRYP_IV1Left  = iv[2];
-        AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3];
-        CRYP_IVInit(&AES_CRYP_IVInitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        while (blocks--) {
-            /* flush IN/OUT FIFOs */
-            CRYP_FIFOFlush();
-
-            CRYP_DataIn(*(uint32_t*)&in[0]);
-            CRYP_DataIn(*(uint32_t*)&in[4]);
-            CRYP_DataIn(*(uint32_t*)&in[8]);
-            CRYP_DataIn(*(uint32_t*)&in[12]);
-
-            /* wait until the complete message has been processed */
-            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-            *(uint32_t*)&out[0]  = CRYP_DataOut();
-            *(uint32_t*)&out[4]  = CRYP_DataOut();
-            *(uint32_t*)&out[8]  = CRYP_DataOut();
-            *(uint32_t*)&out[12] = CRYP_DataOut();
-
-            /* store iv for next call */
-            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
-
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-        }
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-
-        return 0;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-#endif /* WOLFSSL_STM32_CUBEMX */
-
-#elif defined(HAVE_COLDFIRE_SEC)
-    static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz,
-        word32 descHeader)
-    {
-        #ifdef DEBUG_WOLFSSL
-            int i; int stat1, stat2; int ret;
-        #endif
-
-        int size;
-        volatile int v;
-
-        if ((pi == NULL) || (po == NULL))
-            return BAD_FUNC_ARG;    /*wrong pointer*/
-
-        wc_LockMutex(&Mutex_AesSEC);
-
-        /* Set descriptor for SEC */
-        secDesc->length1 = 0x0;
-        secDesc->pointer1 = NULL;
-
-        secDesc->length2 = AES_BLOCK_SIZE;
-        secDesc->pointer2 = (byte *)secReg; /* Initial Vector */
-
-        switch(aes->rounds) {
-            case 10: secDesc->length3 = 16; break;
-            case 12: secDesc->length3 = 24; break;
-            case 14: secDesc->length3 = 32; break;
-        }
-        XMEMCPY(secKey, aes->key, secDesc->length3);
-
-        secDesc->pointer3 = (byte *)secKey;
-        secDesc->pointer4 = AESBuffIn;
-        secDesc->pointer5 = AESBuffOut;
-        secDesc->length6 = 0x0;
-        secDesc->pointer6 = NULL;
-        secDesc->length7 = 0x0;
-        secDesc->pointer7 = NULL;
-        secDesc->nextDescriptorPtr = NULL;
-
-        while (sz) {
-            secDesc->header = descHeader;
-            XMEMCPY(secReg, aes->reg, AES_BLOCK_SIZE);
-            if ((sz % AES_BUFFER_SIZE) == sz) {
-                size = sz;
-                sz = 0;
-            } else {
-                size = AES_BUFFER_SIZE;
-                sz -= AES_BUFFER_SIZE;
-            }
-            secDesc->length4 = size;
-            secDesc->length5 = size;
-
-            XMEMCPY(AESBuffIn, pi, size);
-            if(descHeader == SEC_DESC_AES_CBC_DECRYPT) {
-                XMEMCPY((void*)aes->tmp, (void*)&(pi[size-AES_BLOCK_SIZE]),
-                        AES_BLOCK_SIZE);
-            }
-
-            /* Point SEC to the location of the descriptor */
-            MCF_SEC_FR0 = (uint32)secDesc;
-            /* Initialize SEC and wait for encryption to complete */
-            MCF_SEC_CCCR0 = 0x0000001a;
-            /* poll SISR to determine when channel is complete */
-            v=0;
-
-            while ((secDesc->header>> 24) != 0xff) v++;
-
-            #ifdef DEBUG_WOLFSSL
-                ret = MCF_SEC_SISRH;
-                stat1 = MCF_SEC_AESSR;
-                stat2 = MCF_SEC_AESISR;
-                if (ret & 0xe0000000) {
-                    db_printf("Aes_Cbc(i=%d):ISRH=%08x, AESSR=%08x, "
-                              "AESISR=%08x\n", i, ret, stat1, stat2);
-                }
-            #endif
-
-            XMEMCPY(po, AESBuffOut, size);
-
-            if (descHeader == SEC_DESC_AES_CBC_ENCRYPT) {
-                XMEMCPY((void*)aes->reg, (void*)&(po[size-AES_BLOCK_SIZE]),
-                        AES_BLOCK_SIZE);
-            } else {
-                XMEMCPY((void*)aes->reg, (void*)aes->tmp, AES_BLOCK_SIZE);
-            }
-
-            pi += size;
-            po += size;
-        }
-
-        wc_UnLockMutex(&Mutex_AesSEC);
-        return 0;
-    }
-
-    int wc_AesCbcEncrypt(Aes* aes, byte* po, const byte* pi, word32 sz)
-    {
-        return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_ENCRYPT));
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* po, const byte* pi, word32 sz)
-    {
-        return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT));
-    }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(FREESCALE_LTC)
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        uint32_t keySize;
-        status_t status;
-        byte *iv, *enc_key;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-
-        iv      = (byte*)aes->reg;
-        enc_key = (byte*)aes->key;
-
-        status = wc_AesGetKeySize(aes, &keySize);
-        if (status != 0) {
-            return status;
-        }
-
-        status = LTC_AES_EncryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE,
-            iv, enc_key, keySize);
-        return (status == kStatus_Success) ? 0 : -1;
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        uint32_t keySize;
-        status_t status;
-        byte* iv, *dec_key;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-
-        iv      = (byte*)aes->reg;
-        dec_key = (byte*)aes->key;
-
-        status = wc_AesGetKeySize(aes, &keySize);
-        if (status != 0) {
-            return status;
-        }
-
-        status = LTC_AES_DecryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE,
-            iv, dec_key, keySize, kLTC_EncryptKey);
-        return (status == kStatus_Success) ? 0 : -1;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(FREESCALE_MMCAU)
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        byte *iv;
-        byte temp_block[AES_BLOCK_SIZE];
-
-        iv      = (byte*)aes->reg;
-
-        while (blocks--) {
-            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < AES_BLOCK_SIZE; i++)
-                temp_block[i] ^= iv[i];
-
-            wc_AesEncrypt(aes, temp_block, out + offset);
-
-            offset += AES_BLOCK_SIZE;
-
-            /* store IV for next block */
-            XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-        }
-
-        return 0;
-    }
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-        byte* iv;
-        byte temp_block[AES_BLOCK_SIZE];
-
-        iv      = (byte*)aes->reg;
-
-        while (blocks--) {
-            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
-
-            wc_AesDecrypt(aes, in + offset, out + offset);
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < AES_BLOCK_SIZE; i++)
-                (out + offset)[i] ^= iv[i];
-
-            /* store IV for next block */
-            XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
-
-            offset += AES_BLOCK_SIZE;
-        }
-
-        return 0;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(WOLFSSL_PIC32MZ_CRYPT)
-
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int ret;
-
-        /* hardware fails on input that is not a multiple of AES block size */
-        if (sz % AES_BLOCK_SIZE != 0) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wc_Pic32AesCrypt(
-            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
-            out, in, sz, PIC32_ENCRYPTION,
-            PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC);
-
-        /* store iv for next call */
-        if (ret == 0) {
-            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-        }
-
-        return ret;
-    }
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        int ret;
-        byte scratch[AES_BLOCK_SIZE];
-
-        /* hardware fails on input that is not a multiple of AES block size */
-        if (sz % AES_BLOCK_SIZE != 0) {
-            return BAD_FUNC_ARG;
-        }
-        XMEMCPY(scratch, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-        ret = wc_Pic32AesCrypt(
-            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
-            out, in, sz, PIC32_DECRYPTION,
-            PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC);
-
-        /* store iv for next call */
-        if (ret == 0) {
-            XMEMCPY((byte*)aes->reg, scratch, AES_BLOCK_SIZE);
-        }
-
-        return ret;
-    }
-    #endif /* HAVE_AES_DECRYPT */
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-      /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
-
-#else
-
-    int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = (sz / AES_BLOCK_SIZE);
-
-        if (aes == NULL || out == NULL || in == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-        /* if async and byte count above threshold */
-        if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
-                                                sz >= WC_ASYNC_THRESH_AES_CBC) {
-        #if defined(HAVE_CAVIUM)
-            return NitroxAesCbcEncrypt(aes, out, in, sz);
-        #elif defined(HAVE_INTEL_QA)
-            return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz,
-                (const byte*)aes->asyncKey, aes->keylen,
-                (const byte*)aes->asyncIv, AES_BLOCK_SIZE);
-        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-            if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_ENCRYPT)) {
-                WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
-                testDev->aes.aes = aes;
-                testDev->aes.out = out;
-                testDev->aes.in = in;
-                testDev->aes.sz = sz;
-                return WC_PENDING_E;
-            }
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-    #ifdef WOLFSSL_AESNI
-        if (haveAESNI) {
-            #ifdef DEBUG_AESNI
-                printf("about to aes cbc encrypt\n");
-                printf("in  = %p\n", in);
-                printf("out = %p\n", out);
-                printf("aes->key = %p\n", aes->key);
-                printf("aes->reg = %p\n", aes->reg);
-                printf("aes->rounds = %d\n", aes->rounds);
-                printf("sz = %d\n", sz);
-            #endif
-
-            /* check alignment, decrypt doesn't need alignment */
-            if ((wolfssl_word)in % AESNI_ALIGN) {
-            #ifndef NO_WOLFSSL_ALLOC_ALIGN
-                byte* tmp = (byte*)XMALLOC(sz + AES_BLOCK_SIZE + AESNI_ALIGN,
-                                            aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                byte* tmp_align;
-                if (tmp == NULL) return MEMORY_E;
-
-                tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN));
-                XMEMCPY(tmp_align, in, sz);
-                AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz,
-                                                  (byte*)aes->key, aes->rounds);
-                /* store iv for next call */
-                XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-                XMEMCPY(out, tmp_align, sz);
-                XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return 0;
-            #else
-                WOLFSSL_MSG("AES-CBC encrypt with bad alignment");
-                return BAD_ALIGN_E;
-            #endif
-            }
-
-            AES_CBC_encrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
-                            aes->rounds);
-            /* store iv for next call */
-            XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-            return 0;
-        }
-    #endif
-
-        while (blocks--) {
-            xorbuf((byte*)aes->reg, in, AES_BLOCK_SIZE);
-            wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg);
-            XMEMCPY(out, aes->reg, AES_BLOCK_SIZE);
-
-            out += AES_BLOCK_SIZE;
-            in  += AES_BLOCK_SIZE;
-        }
-
-        return 0;
-    }
-
-    #ifdef HAVE_AES_DECRYPT
-    int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks;
-
-        if (aes == NULL || out == NULL || in == NULL
-                                       || sz % AES_BLOCK_SIZE != 0) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-        /* if async and byte count above threshold */
-        if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
-                                                sz >= WC_ASYNC_THRESH_AES_CBC) {
-        #if defined(HAVE_CAVIUM)
-            return NitroxAesCbcDecrypt(aes, out, in, sz);
-        #elif defined(HAVE_INTEL_QA)
-            return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz,
-                (const byte*)aes->asyncKey, aes->keylen,
-                (const byte*)aes->asyncIv, AES_BLOCK_SIZE);
-        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-            if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_DECRYPT)) {
-                WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
-                testDev->aes.aes = aes;
-                testDev->aes.out = out;
-                testDev->aes.in = in;
-                testDev->aes.sz = sz;
-                return WC_PENDING_E;
-            }
-        #endif
-        }
-    #endif
-
-    #ifdef WOLFSSL_AESNI
-        if (haveAESNI) {
-            #ifdef DEBUG_AESNI
-                printf("about to aes cbc decrypt\n");
-                printf("in  = %p\n", in);
-                printf("out = %p\n", out);
-                printf("aes->key = %p\n", aes->key);
-                printf("aes->reg = %p\n", aes->reg);
-                printf("aes->rounds = %d\n", aes->rounds);
-                printf("sz = %d\n", sz);
-            #endif
-
-            /* if input and output same will overwrite input iv */
-            XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-            #if defined(WOLFSSL_AESNI_BY4)
-            AES_CBC_decrypt_by4(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
-                            aes->rounds);
-            #elif defined(WOLFSSL_AESNI_BY6)
-            AES_CBC_decrypt_by6(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
-                            aes->rounds);
-            #else /* WOLFSSL_AESNI_BYx */
-            AES_CBC_decrypt_by8(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
-                            aes->rounds);
-            #endif /* WOLFSSL_AESNI_BYx */
-            /* store iv for next call */
-            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
-            return 0;
-        }
-    #endif
-
-        blocks = sz / AES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE);
-            wc_AesDecrypt(aes, (byte*)aes->tmp, out);
-            xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE);
-            XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
-
-            out += AES_BLOCK_SIZE;
-            in  += AES_BLOCK_SIZE;
-        }
-
-        return 0;
-    }
-    #endif
-
-#endif /* AES-CBC block */
-#endif /* HAVE_AES_CBC */
-
-/* AES-CTR */
-#if defined(WOLFSSL_AES_COUNTER)
-
-    #ifdef STM32_CRYPTO
-        #define NEED_AES_CTR_SOFT
-        #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock
-
-        int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in)
-        {
-            int ret = 0;
-        #ifdef WOLFSSL_STM32_CUBEMX
-            CRYP_HandleTypeDef hcryp;
-
-            XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-            switch (aes->rounds) {
-                case 10: /* 128-bit key */
-                    hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-                    break;
-	#ifdef CRYP_KEYSIZE_192B
-                case 12: /* 192-bit key */
-                    hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-                    break;
-	#endif
-                case 14: /* 256-bit key */
-                    hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-                    break;
-                default:
-                    break;
-            }
-            hcryp.Instance = CRYP;
-            hcryp.Init.DataType = CRYP_DATATYPE_8B;
-            hcryp.Init.pKey = (byte*)aes->key;
-            hcryp.Init.pInitVect = (byte*)aes->reg;
-
-            HAL_CRYP_Init(&hcryp);
-
-            if (HAL_CRYP_AESCTR_Encrypt(&hcryp, (byte*)in, AES_BLOCK_SIZE, out,
-                                                STM32_HAL_TIMEOUT) != HAL_OK) {
-                /* failed */
-                ret = WC_TIMEOUT_E;
-            }
-
-            HAL_CRYP_DeInit(&hcryp);
-
-        #else /* STD_PERI_LIB */
-            word32 *enc_key, *iv;
-            CRYP_InitTypeDef AES_CRYP_InitStructure;
-            CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure;
-            CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
-
-            enc_key = aes->key;
-            iv = aes->reg;
-
-            /* crypto structure initialization */
-            CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
-            CRYP_StructInit(&AES_CRYP_InitStructure);
-            CRYP_IVStructInit(&AES_CRYP_IVInitStructure);
-
-            /* reset registers to their default values */
-            CRYP_DeInit();
-
-            /* load key into correct registers */
-            switch (aes->rounds) {
-                case 10: /* 128-bit key */
-                    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b;
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[0];
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[2];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3];
-                    break;
-                case 12: /* 192-bit key */
-                    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b;
-                    AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[0];
-                    AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1];
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[2];
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[4];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5];
-                    break;
-                case 14: /* 256-bit key */
-                    AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b;
-                    AES_CRYP_KeyInitStructure.CRYP_Key0Left  = enc_key[0];
-                    AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1];
-                    AES_CRYP_KeyInitStructure.CRYP_Key1Left  = enc_key[2];
-                    AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3];
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Left  = enc_key[4];
-                    AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Left  = enc_key[6];
-                    AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7];
-                    break;
-                default:
-                    break;
-            }
-            CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
-
-            /* set iv */
-            AES_CRYP_IVInitStructure.CRYP_IV0Left  = ByteReverseWord32(iv[0]);
-            AES_CRYP_IVInitStructure.CRYP_IV0Right = ByteReverseWord32(iv[1]);
-            AES_CRYP_IVInitStructure.CRYP_IV1Left  = ByteReverseWord32(iv[2]);
-            AES_CRYP_IVInitStructure.CRYP_IV1Right = ByteReverseWord32(iv[3]);
-            CRYP_IVInit(&AES_CRYP_IVInitStructure);
-
-            /* set direction, mode, and datatype */
-            AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
-            AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR;
-            AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-            CRYP_Init(&AES_CRYP_InitStructure);
-
-            /* enable crypto processor */
-            CRYP_Cmd(ENABLE);
-
-            /* flush IN/OUT FIFOs */
-            CRYP_FIFOFlush();
-
-            CRYP_DataIn(*(uint32_t*)&in[0]);
-            CRYP_DataIn(*(uint32_t*)&in[4]);
-            CRYP_DataIn(*(uint32_t*)&in[8]);
-            CRYP_DataIn(*(uint32_t*)&in[12]);
-
-            /* wait until the complete message has been processed */
-            while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-            *(uint32_t*)&out[0]  = CRYP_DataOut();
-            *(uint32_t*)&out[4]  = CRYP_DataOut();
-            *(uint32_t*)&out[8]  = CRYP_DataOut();
-            *(uint32_t*)&out[12] = CRYP_DataOut();
-
-            /* disable crypto processor */
-            CRYP_Cmd(DISABLE);
-
-        #endif /* WOLFSSL_STM32_CUBEMX */
-            return ret;
-        }
-
-
-    #elif defined(WOLFSSL_PIC32MZ_CRYPT)
-
-        #define NEED_AES_CTR_SOFT
-        #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock
-
-        int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in)
-        {
-            word32 tmpIv[AES_BLOCK_SIZE / sizeof(word32)];
-            XMEMCPY(tmpIv, aes->reg, AES_BLOCK_SIZE);
-            return wc_Pic32AesCrypt(
-                aes->key, aes->keylen, tmpIv, AES_BLOCK_SIZE,
-                out, in, AES_BLOCK_SIZE,
-                PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR);
-        }
-
-    #elif defined(HAVE_COLDFIRE_SEC)
-        #error "Coldfire SEC doesn't currently support AES-CTR mode"
-
-    #elif defined(FREESCALE_LTC)
-        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-        {
-            uint32_t keySize;
-            byte *iv, *enc_key;
-            byte* tmp;
-
-            if (aes == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            /* consume any unused bytes left in aes->tmp */
-            tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
-            while (aes->left && sz) {
-                *(out++) = *(in++) ^ *(tmp++);
-                aes->left--;
-                sz--;
-            }
-
-            if (sz) {
-                iv      = (byte*)aes->reg;
-                enc_key = (byte*)aes->key;
-
-                wc_AesGetKeySize(aes, &keySize);
-
-                LTC_AES_CryptCtr(LTC_BASE, in, out, sz,
-                    iv, enc_key, keySize, (byte*)aes->tmp,
-                    (uint32_t*)&aes->left);
-            }
-
-            return 0;
-        }
-
-    #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-        /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
-
-    #else
-
-        /* Use software based AES counter */
-        #define NEED_AES_CTR_SOFT
-    #endif
-
-    #ifdef NEED_AES_CTR_SOFT
-        /* Increment AES counter */
-        static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
-        {
-            /* in network byte order so start at end and work back */
-            int i;
-            for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
-                if (++inOutCtr[i])  /* we're done unless we overflow */
-                    return;
-            }
-        }
-
-        int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-        {
-            byte* tmp;
-
-            if (aes == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            /* consume any unused bytes left in aes->tmp */
-            tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
-            while (aes->left && sz) {
-               *(out++) = *(in++) ^ *(tmp++);
-               aes->left--;
-               sz--;
-            }
-
-            /* do as many block size ops as possible */
-            while (sz >= AES_BLOCK_SIZE) {
-            #ifdef XTRANSFORM_AESCTRBLOCK
-                XTRANSFORM_AESCTRBLOCK(aes, out, in);
-            #else
-                wc_AesEncrypt(aes, (byte*)aes->reg, out);
-                xorbuf(out, in, AES_BLOCK_SIZE);
-            #endif
-                IncrementAesCounter((byte*)aes->reg);
-
-                out += AES_BLOCK_SIZE;
-                in  += AES_BLOCK_SIZE;
-                sz  -= AES_BLOCK_SIZE;
-                aes->left = 0;
-            }
-
-            /* handle non block size remaining and store unused byte count in left */
-            if (sz) {
-                wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp);
-                IncrementAesCounter((byte*)aes->reg);
-
-                aes->left = AES_BLOCK_SIZE;
-                tmp = (byte*)aes->tmp;
-
-                while (sz--) {
-                    *(out++) = *(in++) ^ *(tmp++);
-                    aes->left--;
-                }
-            }
-
-            return 0;
-        }
-
-    #endif /* NEED_AES_CTR_SOFT */
-
-#endif /* WOLFSSL_AES_COUNTER */
-#endif /* !WOLFSSL_ARMASM */
-
-
-/*
- * The IV for AES GCM and CCM, stored in struct Aes's member reg, is comprised
- * of two parts in order:
- *   1. The fixed field which may be 0 or 4 bytes long. In TLS, this is set
- *      to the implicit IV.
- *   2. The explicit IV is generated by wolfCrypt. It needs to be managed
- *      by wolfCrypt to ensure the IV is unique for each call to encrypt.
- * The IV may be a 96-bit random value, or the 32-bit fixed value and a
- * 64-bit set of 0 or random data. The final 32-bits of reg is used as a
- * block counter during the encryption.
- */
-
-#if (defined(HAVE_AESGCM) && !defined(WC_NO_RNG)) || defined(HAVE_AESCCM)
-static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
-{
-    int i;
-    for (i = ctrSz-1; i >= 0; i--) {
-        if (++ctr[i])
-            break;
-    }
-}
-#endif /* HAVE_AESGCM || HAVE_AESCCM */
-
-
-#ifdef HAVE_AESGCM
-
-#if defined(HAVE_COLDFIRE_SEC)
-    #error "Coldfire SEC doesn't currently support AES-GCM mode"
-
-#elif defined(WOLFSSL_NRF51_AES)
-    #error "nRF51 doesn't currently support AES-GCM mode"
-
-#endif
-
-#ifdef WOLFSSL_ARMASM
-    /* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */
-#else /* software + AESNI implementation */
-
-#if !defined(FREESCALE_LTC_AES_GCM)
-static WC_INLINE void IncrementGcmCounter(byte* inOutCtr)
-{
-    int i;
-
-    /* in network byte order so start at end and work back */
-    for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) {
-        if (++inOutCtr[i])  /* we're done unless we overflow */
-            return;
-    }
-}
-#endif /* !FREESCALE_LTC_AES_GCM */
-
-#if defined(GCM_SMALL) || defined(GCM_TABLE)
-
-static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz)
-{
-    /* Multiply the sz by 8 */
-    word32 szHi = (sz >> (8*sizeof(sz) - 3));
-    sz <<= 3;
-
-    /* copy over the words of the sz into the destination buffer */
-    buf[0] = (szHi >> 24) & 0xff;
-    buf[1] = (szHi >> 16) & 0xff;
-    buf[2] = (szHi >>  8) & 0xff;
-    buf[3] = szHi & 0xff;
-    buf[4] = (sz >> 24) & 0xff;
-    buf[5] = (sz >> 16) & 0xff;
-    buf[6] = (sz >>  8) & 0xff;
-    buf[7] = sz & 0xff;
-}
-
-
-static WC_INLINE void RIGHTSHIFTX(byte* x)
-{
-    int i;
-    int carryOut = 0;
-    int carryIn = 0;
-    int borrow = x[15] & 0x01;
-
-    for (i = 0; i < AES_BLOCK_SIZE; i++) {
-        carryOut = x[i] & 0x01;
-        x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0);
-        carryIn = carryOut;
-    }
-    if (borrow) x[0] ^= 0xE1;
-}
-
-#endif /* defined(GCM_SMALL) || defined(GCM_TABLE) */
-
-
-#ifdef GCM_TABLE
-
-static void GenerateM0(Aes* aes)
-{
-    int i, j;
-    byte (*m)[AES_BLOCK_SIZE] = aes->M0;
-
-    XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE);
-
-    for (i = 64; i > 0; i /= 2) {
-        XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE);
-        RIGHTSHIFTX(m[i]);
-    }
-
-    for (i = 2; i < 256; i *= 2) {
-        for (j = 1; j < i; j++) {
-            XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE);
-            xorbuf(m[i+j], m[j], AES_BLOCK_SIZE);
-        }
-    }
-
-    XMEMSET(m[0], 0, AES_BLOCK_SIZE);
-}
-
-#endif /* GCM_TABLE */
-
-
-int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
-{
-    int  ret;
-    byte iv[AES_BLOCK_SIZE];
-
-    #ifdef WOLFSSL_IMX6_CAAM_BLOB
-        byte   local[32];
-        word32 localSz = 32;
-
-        if (len == (16 + WC_CAAM_BLOB_SZ) ||
-          len == (24 + WC_CAAM_BLOB_SZ) ||
-          len == (32 + WC_CAAM_BLOB_SZ)) {
-            if (wc_caamOpenBlob((byte*)key, len, local, &localSz) != 0) {
-                 return BAD_FUNC_ARG;
-            }
-
-            /* set local values */
-            key = local;
-            len = localSz;
-        }
-    #endif
-
-    if (!((len == 16) || (len == 24) || (len == 32)))
-        return BAD_FUNC_ARG;
-
-    XMEMSET(iv, 0, AES_BLOCK_SIZE);
-    ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
-
-    #ifdef WOLFSSL_AESNI
-        /* AES-NI code generates its own H value. */
-        if (haveAESNI)
-            return ret;
-    #endif /* WOLFSSL_AESNI */
-
-#if !defined(FREESCALE_LTC_AES_GCM)
-    if (ret == 0) {
-        wc_AesEncrypt(aes, iv, aes->H);
-    #ifdef GCM_TABLE
-        GenerateM0(aes);
-    #endif /* GCM_TABLE */
-    }
-#endif /* FREESCALE_LTC_AES_GCM */
-
-#if defined(WOLFSSL_XILINX_CRYPT)
-    wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP);
-#endif
-
-#ifdef WOLFSSL_IMX6_CAAM_BLOB
-    ForceZero(local, sizeof(local));
-#endif
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_AESNI
-
-#if defined(USE_INTEL_SPEEDUP)
-    #define HAVE_INTEL_AVX1
-    #define HAVE_INTEL_AVX2
-#endif /* USE_INTEL_SPEEDUP */
-
-#ifdef _MSC_VER
-    #define S(w,z) ((char)((unsigned long long)(w) >> (8*(7-(z))) & 0xFF))
-    #define M128_INIT(x,y) { S((x),7), S((x),6), S((x),5), S((x),4), \
-                             S((x),3), S((x),2), S((x),1), S((x),0), \
-                             S((y),7), S((y),6), S((y),5), S((y),4), \
-                             S((y),3), S((y),2), S((y),1), S((y),0) }
-#else
-    #define M128_INIT(x,y) { (x), (y) }
-#endif
-
-static const __m128i MOD2_128 = M128_INIT(0x1,
-                                           (long long int)0xc200000000000000UL);
-
-
-/* See Intel® Carry-Less Multiplication Instruction
- * and its Usage for Computing the GCM Mode White Paper
- * by Shay Gueron, Intel Mobility Group, Israel Development Center;
- * and Michael E. Kounavis, Intel Labs, Circuits and Systems Research */
-
-
-/* Figure 9. AES-GCM – Encrypt With Single Block Ghash at a Time */
-
-static const __m128i ONE   = M128_INIT(0x0, 0x1);
-#ifndef AES_GCM_AESNI_NO_UNROLL
-static const __m128i TWO   = M128_INIT(0x0, 0x2);
-static const __m128i THREE = M128_INIT(0x0, 0x3);
-static const __m128i FOUR  = M128_INIT(0x0, 0x4);
-static const __m128i FIVE  = M128_INIT(0x0, 0x5);
-static const __m128i SIX   = M128_INIT(0x0, 0x6);
-static const __m128i SEVEN = M128_INIT(0x0, 0x7);
-static const __m128i EIGHT = M128_INIT(0x0, 0x8);
-#endif
-static const __m128i BSWAP_EPI64 = M128_INIT(0x0001020304050607, 0x08090a0b0c0d0e0f);
-static const __m128i BSWAP_MASK  = M128_INIT(0x08090a0b0c0d0e0f, 0x0001020304050607);
-
-
-#ifndef _MSC_VER
-
-#define _VAR(a) "" #a ""
-#define VAR(a) _VAR(a)
-
-#define HR     %%xmm14
-#define XR     %%xmm15
-#define KR     %%ebx
-#define KR64   %%rbx
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-#define CTR1   128(%%rsp)
-#define TR     144(%%rsp)
-#define HTR    %%rsp
-#define STACK_OFFSET    160
-#else
-#define CTR1   (%%rsp)
-#define TR     16(%%rsp)
-#define STACK_OFFSET    32
-#endif
-
-#define AESENC()                      \
-    "aesenc	%%xmm12, %%xmm4\n\t"  \
-    "aesenc	%%xmm12, %%xmm5\n\t"  \
-    "aesenc	%%xmm12, %%xmm6\n\t"  \
-    "aesenc	%%xmm12, %%xmm7\n\t"  \
-    "aesenc	%%xmm12, %%xmm8\n\t"  \
-    "aesenc	%%xmm12, %%xmm9\n\t"  \
-    "aesenc	%%xmm12, %%xmm10\n\t" \
-    "aesenc	%%xmm12, %%xmm11\n\t"
-
-#define AESENC_SET(o)                        \
-    "movdqa	" #o "(%[KEY]), %%xmm12\n\t" \
-    AESENC()
-
-#define AESENC_CTR()                        \
-    "movdqu	" VAR(CTR1) ", %%xmm4\n\t"  \
-    "movdqa	%[BSWAP_EPI64], %%xmm1\n\t" \
-    "movdqu	%%xmm4, %%xmm0\n\t"         \
-    "pshufb	%%xmm1, %%xmm4\n\t"         \
-    "movdqa	%%xmm0, %%xmm5\n\t"         \
-    "paddd	%[ONE], %%xmm5\n\t"         \
-    "pshufb	%%xmm1, %%xmm5\n\t"         \
-    "movdqa	%%xmm0, %%xmm6\n\t"         \
-    "paddd	%[TWO], %%xmm6\n\t"         \
-    "pshufb	%%xmm1, %%xmm6\n\t"         \
-    "movdqa	%%xmm0, %%xmm7\n\t"         \
-    "paddd	%[THREE], %%xmm7\n\t"       \
-    "pshufb	%%xmm1, %%xmm7\n\t"         \
-    "movdqa	%%xmm0, %%xmm8\n\t"         \
-    "paddd	%[FOUR], %%xmm8\n\t"        \
-    "pshufb	%%xmm1, %%xmm8\n\t"         \
-    "movdqa	%%xmm0, %%xmm9\n\t"         \
-    "paddd	%[FIVE], %%xmm9\n\t"        \
-    "pshufb	%%xmm1, %%xmm9\n\t"         \
-    "movdqa	%%xmm0, %%xmm10\n\t"        \
-    "paddd	%[SIX], %%xmm10\n\t"        \
-    "pshufb	%%xmm1, %%xmm10\n\t"        \
-    "movdqa	%%xmm0, %%xmm11\n\t"        \
-    "paddd	%[SEVEN], %%xmm11\n\t"      \
-    "pshufb	%%xmm1, %%xmm11\n\t"        \
-    "paddd	%[EIGHT], %%xmm0\n\t"
-
-#define AESENC_XOR()                       \
-    "movdqa	(%[KEY]), %%xmm12\n\t"     \
-    "movdqu	%%xmm0, " VAR(CTR1) "\n\t" \
-    "pxor	%%xmm12, %%xmm4\n\t"       \
-    "pxor	%%xmm12, %%xmm5\n\t"       \
-    "pxor	%%xmm12, %%xmm6\n\t"       \
-    "pxor	%%xmm12, %%xmm7\n\t"       \
-    "pxor	%%xmm12, %%xmm8\n\t"       \
-    "pxor	%%xmm12, %%xmm9\n\t"       \
-    "pxor	%%xmm12, %%xmm10\n\t"      \
-    "pxor	%%xmm12, %%xmm11\n\t"
-
-/* Encrypt and carry-less multiply for AVX1. */
-#define AESENC_PCLMUL_1(src, o1, o2, o3)            \
-    "movdqu	" #o3 "(" VAR(HTR) "), %%xmm12\n\t" \
-    "movdqu	" #o2 "(" #src "), %%xmm0\n\t"      \
-    "aesenc	" #o1 "(%[KEY]), %%xmm4\n\t"        \
-    "pshufb	%[BSWAP_MASK], %%xmm0\n\t"          \
-    "pxor	%%xmm2, %%xmm0\n\t"                 \
-    "pshufd	$0x4e, %%xmm12, %%xmm1\n\t"         \
-    "pshufd	$0x4e, %%xmm0, %%xmm14\n\t"         \
-    "pxor	%%xmm12, %%xmm1\n\t"                \
-    "pxor	%%xmm0, %%xmm14\n\t"                \
-    "movdqa	%%xmm0, %%xmm3\n\t"                 \
-    "pclmulqdq	$0x11, %%xmm12, %%xmm3\n\t"         \
-    "aesenc	" #o1 "(%[KEY]), %%xmm5\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm6\n\t"        \
-    "movdqa	%%xmm0, %%xmm2\n\t"                 \
-    "pclmulqdq	$0x00, %%xmm12, %%xmm2\n\t"         \
-    "aesenc	" #o1 "(%[KEY]), %%xmm7\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm8\n\t"        \
-    "pclmulqdq	$0x00, %%xmm14, %%xmm1\n\t"         \
-    "aesenc	" #o1 "(%[KEY]), %%xmm9\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm10\n\t"       \
-    "aesenc	" #o1 "(%[KEY]), %%xmm11\n\t"       \
-    "pxor      %%xmm2, %%xmm1\n\t"                  \
-    "pxor      %%xmm3, %%xmm1\n\t"                  \
-
-#define AESENC_PCLMUL_N(src, o1, o2, o3)            \
-    "movdqu	" #o3 "(" VAR(HTR) "), %%xmm12\n\t" \
-    "movdqu	" #o2 "(" #src" ), %%xmm0\n\t"      \
-    "pshufd	$0x4e, %%xmm12, %%xmm13\n\t"        \
-    "pshufb	%[BSWAP_MASK], %%xmm0\n\t"          \
-    "aesenc	" #o1 "(%[KEY]), %%xmm4\n\t"        \
-    "pxor	%%xmm12, %%xmm13\n\t"               \
-    "pshufd	$0x4e, %%xmm0, %%xmm14\n\t"         \
-    "pxor	%%xmm0, %%xmm14\n\t"                \
-    "movdqa	%%xmm0, %%xmm15\n\t"                \
-    "pclmulqdq	$0x11, %%xmm12, %%xmm15\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm5\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm6\n\t"        \
-    "pclmulqdq	$0x00, %%xmm0, %%xmm12\n\t"         \
-    "aesenc	" #o1 "(%[KEY]), %%xmm7\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm8\n\t"        \
-    "pclmulqdq	$0x00, %%xmm14, %%xmm13\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm9\n\t"        \
-    "aesenc	" #o1 "(%[KEY]), %%xmm10\n\t"       \
-    "aesenc	" #o1 "(%[KEY]), %%xmm11\n\t"       \
-    "pxor      %%xmm12, %%xmm1\n\t"                 \
-    "pxor      %%xmm12, %%xmm2\n\t"                 \
-    "pxor      %%xmm15, %%xmm1\n\t"                 \
-    "pxor      %%xmm15, %%xmm3\n\t"                 \
-    "pxor      %%xmm13, %%xmm1\n\t"                 \
-
-#define AESENC_PCLMUL_L(o)                   \
-    "movdqa	%%xmm1, %%xmm14\n\t"         \
-    "psrldq	$8, %%xmm1\n\t"              \
-    "pslldq	$8, %%xmm14\n\t"             \
-    "aesenc	" #o "(%[KEY]), %%xmm4\n\t"  \
-    "pxor      %%xmm14, %%xmm2\n\t"          \
-    "pxor      %%xmm1, %%xmm3\n\t"           \
-    "movdqa	%%xmm2, %%xmm12\n\t"         \
-    "movdqa	%%xmm2, %%xmm13\n\t"         \
-    "movdqa	%%xmm2, %%xmm14\n\t"         \
-    "aesenc	" #o "(%[KEY]), %%xmm5\n\t"  \
-    "pslld	$31, %%xmm12\n\t"            \
-    "pslld	$30, %%xmm13\n\t"            \
-    "pslld	$25, %%xmm14\n\t"            \
-    "aesenc	" #o "(%[KEY]), %%xmm6\n\t"  \
-    "pxor	%%xmm13, %%xmm12\n\t"        \
-    "pxor	%%xmm14, %%xmm12\n\t"        \
-    "aesenc	" #o "(%[KEY]), %%xmm7\n\t"  \
-    "movdqa	%%xmm12, %%xmm13\n\t"        \
-    "pslldq	$12, %%xmm12\n\t"            \
-    "psrldq	$4, %%xmm13\n\t"             \
-    "aesenc	" #o "(%[KEY]), %%xmm8\n\t"  \
-    "pxor	%%xmm12, %%xmm2\n\t"         \
-    "movdqa	%%xmm2, %%xmm14\n\t"         \
-    "movdqa	%%xmm2, %%xmm1\n\t"          \
-    "movdqa	%%xmm2, %%xmm0\n\t"          \
-    "aesenc	" #o "(%[KEY]), %%xmm9\n\t"  \
-    "psrld	$1, %%xmm14\n\t"             \
-    "psrld	$2, %%xmm1\n\t"              \
-    "psrld	$7, %%xmm0\n\t"              \
-    "aesenc	" #o "(%[KEY]), %%xmm10\n\t" \
-    "pxor	%%xmm1, %%xmm14\n\t"         \
-    "pxor	%%xmm0, %%xmm14\n\t"         \
-    "aesenc	" #o "(%[KEY]), %%xmm11\n\t" \
-    "pxor	%%xmm13, %%xmm14\n\t"        \
-    "pxor	%%xmm14, %%xmm2\n\t"         \
-    "pxor	%%xmm3, %%xmm2\n\t"          \
-
-/* Encrypt and carry-less multiply with last key. */
-#define AESENC_LAST(in, out)                \
-    "aesenclast	%%xmm12, %%xmm4\n\t"        \
-    "aesenclast	%%xmm12, %%xmm5\n\t"        \
-    "movdqu	   (" #in "),%%xmm0\n\t"    \
-    "movdqu	 16(" #in "),%%xmm1\n\t"    \
-    "pxor	%%xmm0, %%xmm4\n\t"         \
-    "pxor	%%xmm1, %%xmm5\n\t"         \
-    "movdqu	%%xmm4,    (" #out ")\n\t"  \
-    "movdqu	%%xmm5,  16(" #out ")\n\t"  \
-    "aesenclast	%%xmm12, %%xmm6\n\t"        \
-    "aesenclast	%%xmm12, %%xmm7\n\t"        \
-    "movdqu	 32(" #in "),%%xmm0\n\t"    \
-    "movdqu	 48(" #in "),%%xmm1\n\t"    \
-    "pxor	%%xmm0, %%xmm6\n\t"         \
-    "pxor	%%xmm1, %%xmm7\n\t"         \
-    "movdqu	%%xmm6,  32(" #out ")\n\t"  \
-    "movdqu	%%xmm7,  48(" #out ")\n\t"  \
-    "aesenclast	%%xmm12, %%xmm8\n\t"        \
-    "aesenclast	%%xmm12, %%xmm9\n\t"        \
-    "movdqu	 64(" #in "),%%xmm0\n\t"    \
-    "movdqu	 80(" #in "),%%xmm1\n\t"    \
-    "pxor	%%xmm0, %%xmm8\n\t"         \
-    "pxor	%%xmm1, %%xmm9\n\t"         \
-    "movdqu	%%xmm8,  64(" #out ")\n\t"  \
-    "movdqu	%%xmm9,  80(" #out ")\n\t"  \
-    "aesenclast	%%xmm12, %%xmm10\n\t"       \
-    "aesenclast	%%xmm12, %%xmm11\n\t"       \
-    "movdqu	 96(" #in "),%%xmm0\n\t"    \
-    "movdqu	112(" #in "),%%xmm1\n\t"    \
-    "pxor	%%xmm0, %%xmm10\n\t"        \
-    "pxor	%%xmm1, %%xmm11\n\t"        \
-    "movdqu	%%xmm10,  96(" #out ")\n\t" \
-    "movdqu	%%xmm11, 112(" #out ")\n\t"
-
-#define _AESENC_AVX(r)                    \
-    "aesenc	16(%[KEY]), " #r "\n\t"   \
-    "aesenc	32(%[KEY]), " #r "\n\t"   \
-    "aesenc	48(%[KEY]), " #r "\n\t"   \
-    "aesenc	64(%[KEY]), " #r "\n\t"   \
-    "aesenc	80(%[KEY]), " #r "\n\t"   \
-    "aesenc	96(%[KEY]), " #r "\n\t"   \
-    "aesenc	112(%[KEY]), " #r "\n\t"  \
-    "aesenc	128(%[KEY]), " #r "\n\t"  \
-    "aesenc	144(%[KEY]), " #r "\n\t"  \
-    "cmpl	$11, %[nr]\n\t"           \
-    "movdqa	160(%[KEY]), %%xmm5\n\t"  \
-    "jl		%=f\n\t"                  \
-    "aesenc	%%xmm5, " #r "\n\t"       \
-    "aesenc	176(%[KEY]), " #r "\n\t"  \
-    "cmpl	$13, %[nr]\n\t"           \
-    "movdqa	192(%[KEY]), %%xmm5\n\t"  \
-    "jl		%=f\n\t"                  \
-    "aesenc	%%xmm5, " #r "\n\t"       \
-    "aesenc	208(%[KEY]), " #r "\n\t"  \
-    "movdqa	224(%[KEY]), %%xmm5\n\t"  \
-    "%=:\n\t"                             \
-    "aesenclast	%%xmm5, " #r "\n\t"
-#define AESENC_AVX(r)                     \
-        _AESENC_AVX(r)
-
-#define AESENC_BLOCK(in, out)               \
-    "movdqu	" VAR(CTR1) ", %%xmm4\n\t"  \
-    "movdqu	%%xmm4, %%xmm5\n\t"         \
-    "pshufb	%[BSWAP_EPI64], %%xmm4\n\t" \
-    "paddd	%[ONE], %%xmm5\n\t"         \
-    "pxor	(%[KEY]), %%xmm4\n\t"       \
-    "movdqu	%%xmm5, " VAR(CTR1) "\n\t"  \
-    AESENC_AVX(%%xmm4)                      \
-    "movdqu	(" #in "), %%xmm5\n\t"      \
-    "pxor	%%xmm5, %%xmm4\n\t"         \
-    "movdqu	%%xmm4, (" #out ")\n\t"     \
-    "pshufb	%[BSWAP_MASK], %%xmm4\n\t"  \
-    "pxor	%%xmm4, " VAR(XR) "\n\t"
-
-#define _AESENC_GFMUL(in, out, H, X)            \
-    "movdqu	" VAR(CTR1) ", %%xmm4\n\t"      \
-    "movdqu	%%xmm4, %%xmm5\n\t"             \
-    "pshufb	%[BSWAP_EPI64], %%xmm4\n\t"     \
-    "paddd	%[ONE], %%xmm5\n\t"             \
-    "pxor	(%[KEY]), %%xmm4\n\t"           \
-    "movdqu	%%xmm5, " VAR(CTR1) "\n\t"      \
-    "movdqa	" #X ", %%xmm6\n\t"             \
-    "pclmulqdq	$0x10, " #H ", %%xmm6\n\t"      \
-    "aesenc	16(%[KEY]), %%xmm4\n\t"         \
-    "aesenc	32(%[KEY]), %%xmm4\n\t"         \
-    "movdqa	" #X ", %%xmm7\n\t"             \
-    "pclmulqdq	$0x01, " #H ", %%xmm7\n\t"      \
-    "aesenc	48(%[KEY]), %%xmm4\n\t"         \
-    "aesenc	64(%[KEY]), %%xmm4\n\t"         \
-    "movdqa	" #X ", %%xmm8\n\t"             \
-    "pclmulqdq	$0x00, " #H ", %%xmm8\n\t"      \
-    "aesenc	80(%[KEY]), %%xmm4\n\t"         \
-    "movdqa	" #X ", %%xmm1\n\t"             \
-    "pclmulqdq	$0x11, " #H ", %%xmm1\n\t"      \
-    "aesenc	96(%[KEY]), %%xmm4\n\t"         \
-    "pxor	%%xmm7, %%xmm6\n\t"             \
-    "movdqa	%%xmm6, %%xmm2\n\t"             \
-    "psrldq	$8, %%xmm6\n\t"                 \
-    "pslldq	$8, %%xmm2\n\t"                 \
-    "aesenc	112(%[KEY]), %%xmm4\n\t"        \
-    "movdqa	%%xmm1, %%xmm3\n\t"             \
-    "pxor	%%xmm8, %%xmm2\n\t"             \
-    "pxor	%%xmm6, %%xmm3\n\t"             \
-    "movdqa	%[MOD2_128], %%xmm0\n\t"        \
-    "movdqa	%%xmm2, %%xmm7\n\t"             \
-    "pclmulqdq	$0x10, %%xmm0, %%xmm7\n\t"      \
-    "aesenc	128(%[KEY]), %%xmm4\n\t"        \
-    "pshufd	$0x4e, %%xmm2, %%xmm6\n\t"      \
-    "pxor	%%xmm7, %%xmm6\n\t"             \
-    "movdqa	%%xmm6, %%xmm7\n\t"             \
-    "pclmulqdq	$0x10, %%xmm0, %%xmm7\n\t"      \
-    "aesenc	144(%[KEY]), %%xmm4\n\t"        \
-    "pshufd	$0x4e, %%xmm6, " VAR(XR) "\n\t" \
-    "pxor	%%xmm7, " VAR(XR) "\n\t"        \
-    "pxor	%%xmm3, " VAR(XR) "\n\t"        \
-    "cmpl	$11, %[nr]\n\t"                 \
-    "movdqu	160(%[KEY]), %%xmm5\n\t"        \
-    "jl		%=f\n\t"                        \
-    "aesenc	%%xmm5, %%xmm4\n\t"             \
-    "aesenc	176(%[KEY]), %%xmm4\n\t"        \
-    "cmpl	$13, %[nr]\n\t"                 \
-    "movdqu	192(%[KEY]), %%xmm5\n\t"        \
-    "jl		%=f\n\t"                        \
-    "aesenc	%%xmm5, %%xmm4\n\t"             \
-    "aesenc	208(%[KEY]), %%xmm4\n\t"        \
-    "movdqa	224(%[KEY]), %%xmm5\n\t"        \
-    "%=:\n\t"                                   \
-    "aesenclast	%%xmm5, %%xmm4\n\t"             \
-    "movdqu	(" #in "), %%xmm5\n\t"          \
-    "pxor	%%xmm5, %%xmm4\n\t"             \
-    "movdqu	%%xmm4, (" #out ")\n\t"
-#define AESENC_GFMUL(in, out, H, X)             \
-       _AESENC_GFMUL(in, out, H, X)
-
-#define _GHASH_GFMUL_AVX(r, r2, a, b)      \
-    "pshufd	$0x4e, "#a", %%xmm1\n\t"   \
-    "pshufd	$0x4e, "#b", %%xmm2\n\t"   \
-    "movdqa	"#b", %%xmm3\n\t"          \
-    "movdqa	"#b", %%xmm0\n\t"          \
-    "pclmulqdq	$0x11, "#a", %%xmm3\n\t"   \
-    "pclmulqdq	$0x00, "#a", %%xmm0\n\t"   \
-    "pxor	"#a", %%xmm1\n\t"          \
-    "pxor	"#b", %%xmm2\n\t"          \
-    "pclmulqdq	$0x00, %%xmm2, %%xmm1\n\t" \
-    "pxor	%%xmm0, %%xmm1\n\t"        \
-    "pxor	%%xmm3, %%xmm1\n\t"        \
-    "movdqa	%%xmm1, %%xmm2\n\t"        \
-    "movdqa	%%xmm0, "#r2"\n\t"         \
-    "movdqa	%%xmm3, " #r "\n\t"        \
-    "pslldq	$8, %%xmm2\n\t"            \
-    "psrldq	$8, %%xmm1\n\t"            \
-    "pxor	%%xmm2, "#r2"\n\t"         \
-    "pxor	%%xmm1, " #r "\n\t"
-#define GHASH_GFMUL_AVX(r, r2, a, b)       \
-       _GHASH_GFMUL_AVX(r, r2, a, b)
-
-#define _GHASH_GFMUL_XOR_AVX(r, r2, a, b)  \
-    "pshufd	$0x4e, "#a", %%xmm1\n\t"   \
-    "pshufd	$0x4e, "#b", %%xmm2\n\t"   \
-    "movdqa	"#b", %%xmm3\n\t"          \
-    "movdqa	"#b", %%xmm0\n\t"          \
-    "pclmulqdq	$0x11, "#a", %%xmm3\n\t"   \
-    "pclmulqdq	$0x00, "#a", %%xmm0\n\t"   \
-    "pxor	"#a", %%xmm1\n\t"          \
-    "pxor	"#b", %%xmm2\n\t"          \
-    "pclmulqdq	$0x00, %%xmm2, %%xmm1\n\t" \
-    "pxor	%%xmm0, %%xmm1\n\t"        \
-    "pxor	%%xmm3, %%xmm1\n\t"        \
-    "movdqa	%%xmm1, %%xmm2\n\t"        \
-    "pxor	%%xmm0, "#r2"\n\t"         \
-    "pxor	%%xmm3, " #r "\n\t"        \
-    "pslldq	$8, %%xmm2\n\t"            \
-    "psrldq	$8, %%xmm1\n\t"            \
-    "pxor	%%xmm2, "#r2"\n\t"         \
-    "pxor	%%xmm1, " #r "\n\t"
-#define GHASH_GFMUL_XOR_AVX(r, r2, a, b)   \
-       _GHASH_GFMUL_XOR_AVX(r, r2, a, b)
-
-#define GHASH_MID_AVX(r, r2)        \
-    "movdqa	"#r2", %%xmm0\n\t"  \
-    "movdqa	" #r ", %%xmm1\n\t" \
-    "psrld	$31, %%xmm0\n\t"    \
-    "psrld	$31, %%xmm1\n\t"    \
-    "pslld	$1, "#r2"\n\t"      \
-    "pslld	$1, " #r "\n\t"     \
-    "movdqa	%%xmm0, %%xmm2\n\t" \
-    "pslldq	$4, %%xmm0\n\t"     \
-    "psrldq	$12, %%xmm2\n\t"    \
-    "pslldq	$4, %%xmm1\n\t"     \
-    "por	%%xmm2, " #r "\n\t" \
-    "por	%%xmm0, "#r2"\n\t"  \
-    "por	%%xmm1, " #r "\n\t"
-
-#define _GHASH_GFMUL_RED_AVX(r, a, b)      \
-    "pshufd	$0x4e, "#a", %%xmm5\n\t"   \
-    "pshufd	$0x4e, "#b", %%xmm6\n\t"   \
-    "movdqa	"#b", %%xmm7\n\t"          \
-    "movdqa	"#b", %%xmm4\n\t"          \
-    "pclmulqdq	$0x11, "#a", %%xmm7\n\t"   \
-    "pclmulqdq	$0x00, "#a", %%xmm4\n\t"   \
-    "pxor	"#a", %%xmm5\n\t"          \
-    "pxor	"#b", %%xmm6\n\t"          \
-    "pclmulqdq	$0x00, %%xmm6, %%xmm5\n\t" \
-    "pxor	%%xmm4, %%xmm5\n\t"        \
-    "pxor	%%xmm7, %%xmm5\n\t"        \
-    "movdqa	%%xmm5, %%xmm6\n\t"        \
-    "movdqa	%%xmm7, " #r "\n\t"        \
-    "pslldq	$8, %%xmm6\n\t"            \
-    "psrldq	$8, %%xmm5\n\t"            \
-    "pxor	%%xmm6, %%xmm4\n\t"        \
-    "pxor	%%xmm5, " #r "\n\t"        \
-    "movdqa	%%xmm4, %%xmm8\n\t"        \
-    "movdqa	%%xmm4, %%xmm9\n\t"        \
-    "movdqa	%%xmm4, %%xmm10\n\t"       \
-    "pslld	$31, %%xmm8\n\t"           \
-    "pslld	$30, %%xmm9\n\t"           \
-    "pslld	$25, %%xmm10\n\t"          \
-    "pxor	%%xmm9, %%xmm8\n\t"        \
-    "pxor	%%xmm10, %%xmm8\n\t"       \
-    "movdqa	%%xmm8, %%xmm9\n\t"        \
-    "psrldq	$4, %%xmm9\n\t"            \
-    "pslldq	$12, %%xmm8\n\t"           \
-    "pxor	%%xmm8, %%xmm4\n\t"        \
-    "movdqa	%%xmm4, %%xmm10\n\t"       \
-    "movdqa	%%xmm4, %%xmm6\n\t"        \
-    "movdqa	%%xmm4, %%xmm5\n\t"        \
-    "psrld	$1, %%xmm10\n\t"           \
-    "psrld	$2, %%xmm6\n\t"            \
-    "psrld	$7, %%xmm5\n\t"            \
-    "pxor	%%xmm6, %%xmm10\n\t"       \
-    "pxor	%%xmm5, %%xmm10\n\t"       \
-    "pxor	%%xmm9, %%xmm10\n\t"       \
-    "pxor	%%xmm4, %%xmm10\n\t"       \
-    "pxor	%%xmm10, " #r "\n\t"
-#define GHASH_GFMUL_RED_AVX(r, a, b)       \
-       _GHASH_GFMUL_RED_AVX(r, a, b)
-
-#define GHASH_RED_AVX(r, r2)           \
-    "movdqa	"#r2", %%xmm0\n\t"     \
-    "movdqa	"#r2", %%xmm1\n\t"     \
-    "movdqa	"#r2", %%xmm2\n\t"     \
-    "pslld	$31, %%xmm0\n\t"       \
-    "pslld	$30, %%xmm1\n\t"       \
-    "pslld	$25, %%xmm2\n\t"       \
-    "pxor	%%xmm1, %%xmm0\n\t"    \
-    "pxor	%%xmm2, %%xmm0\n\t"    \
-    "movdqa	%%xmm0, %%xmm1\n\t"    \
-    "psrldq	$4, %%xmm1\n\t"        \
-    "pslldq	$12, %%xmm0\n\t"       \
-    "pxor	%%xmm0, "#r2"\n\t"     \
-    "movdqa	"#r2", %%xmm2\n\t"     \
-    "movdqa	"#r2", %%xmm3\n\t"     \
-    "movdqa	"#r2", %%xmm0\n\t"     \
-    "psrld	$1, %%xmm2\n\t"        \
-    "psrld	$2, %%xmm3\n\t"        \
-    "psrld	$7, %%xmm0\n\t"        \
-    "pxor	%%xmm3, %%xmm2\n\t"    \
-    "pxor	%%xmm0, %%xmm2\n\t"    \
-    "pxor	%%xmm1, %%xmm2\n\t"    \
-    "pxor	"#r2", %%xmm2\n\t"     \
-    "pxor	%%xmm2, " #r "\n\t"
-
-#define GHASH_GFMUL_RED_XOR_AVX(r, r2, a, b) \
-    GHASH_GFMUL_XOR_AVX(r, r2, a, b)         \
-    GHASH_RED_AVX(r, r2)
-
-#define GHASH_FULL_AVX(r, r2, a, b) \
-    GHASH_GFMUL_AVX(r, r2, a, b)    \
-    GHASH_MID_AVX(r, r2)            \
-    GHASH_RED_AVX(r, r2)
-
-#define CALC_IV_12() \
-    "# Calculate values when IV is 12 bytes\n\t"      \
-    "# Set counter based on IV\n\t"                   \
-    "movl	$0x01000000, %%ecx\n\t"               \
-    "pinsrq	$0, 0(%%rax), %%xmm13\n\t"            \
-    "pinsrd	$2, 8(%%rax), %%xmm13\n\t"            \
-    "pinsrd	$3, %%ecx, %%xmm13\n\t"               \
-    "# H = Encrypt X(=0) and T = Encrypt counter\n\t" \
-    "movdqu	%%xmm13, %%xmm1\n\t"                  \
-    "movdqa	  0(%[KEY]), " VAR(HR) "\n\t"         \
-    "pxor	" VAR(HR) ", %%xmm1\n\t"              \
-    "movdqa	 16(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	 32(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	 48(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	 64(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	 80(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	 96(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	112(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	128(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	144(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "cmpl	$11, %[nr]\n\t"                       \
-    "movdqa	160(%[KEY]), %%xmm12\n\t"             \
-    "jl	31f\n\t"                                      \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqa	176(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "cmpl	$13, %[nr]\n\t"                       \
-    "movdqa	192(%[KEY]), %%xmm12\n\t"             \
-    "jl	31f\n\t"                                      \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqu	208(%[KEY]), %%xmm12\n\t"             \
-    "aesenc	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenc	%%xmm12, %%xmm1\n\t"                  \
-    "movdqu	224(%[KEY]), %%xmm12\n\t"             \
-    "31:\n\t"                                         \
-    "aesenclast	%%xmm12, " VAR(HR) "\n\t"             \
-    "aesenclast	%%xmm12, %%xmm1\n\t"                  \
-    "pshufb	%[BSWAP_MASK], " VAR(HR) "\n\t"       \
-    "movdqu	%%xmm1, " VAR(TR) "\n\t"              \
-    "jmp	39f\n\t"
-
-#define CALC_IV()                                    \
-    "# Calculate values when IV is not 12 bytes\n\t" \
-    "# H = Encrypt X(=0)\n\t"                        \
-    "movdqa	0(%[KEY]), " VAR(HR) "\n\t"          \
-    AESENC_AVX(HR)                                   \
-    "pshufb	%[BSWAP_MASK], " VAR(HR) "\n\t"      \
-    "# Calc counter\n\t"                             \
-    "# Initialization vector\n\t"                    \
-    "cmpl	$0, %%edx\n\t"                       \
-    "movq	$0, %%rcx\n\t"                       \
-    "je	45f\n\t"                                     \
-    "cmpl	$16, %%edx\n\t"                      \
-    "jl	44f\n\t"                                     \
-    "andl	$0xfffffff0, %%edx\n\t"              \
-    "\n"                                             \
-    "43:\n\t"                                        \
-    "movdqu	(%%rax,%%rcx,1), %%xmm4\n\t"         \
-    "pshufb	%[BSWAP_MASK], %%xmm4\n\t"           \
-    "pxor	%%xmm4, %%xmm13\n\t"                 \
-    GHASH_FULL_AVX(%%xmm13, %%xmm12, %%xmm13, HR)    \
-    "addl	$16, %%ecx\n\t"                      \
-    "cmpl	%%edx, %%ecx\n\t"                    \
-    "jl	43b\n\t"                                     \
-    "movl	%[ibytes], %%edx\n\t"                \
-    "cmpl	%%edx, %%ecx\n\t"                    \
-    "je	45f\n\t"                                     \
-    "\n"                                             \
-    "44:\n\t"                                        \
-    "subq	$16, %%rsp\n\t"                      \
-    "pxor	%%xmm4, %%xmm4\n\t"                  \
-    "xorl	%%ebx, %%ebx\n\t"                    \
-    "movdqu	%%xmm4, (%%rsp)\n\t"                 \
-    "42:\n\t"                                        \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t"         \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t"         \
-    "incl	%%ecx\n\t"                           \
-    "incl	%%ebx\n\t"                           \
-    "cmpl	%%edx, %%ecx\n\t"                    \
-    "jl	42b\n\t"                                     \
-    "movdqu	(%%rsp), %%xmm4\n\t"                 \
-    "addq	$16, %%rsp\n\t"                      \
-    "pshufb	%[BSWAP_MASK], %%xmm4\n\t"           \
-    "pxor	%%xmm4, %%xmm13\n\t"                 \
-    GHASH_FULL_AVX(%%xmm13, %%xmm12, %%xmm13, HR)    \
-    "\n"                                             \
-    "45:\n\t"                                        \
-    "# T = Encrypt counter\n\t"                      \
-    "pxor	%%xmm0, %%xmm0\n\t"                  \
-    "shll	$3, %%edx\n\t"                       \
-    "pinsrq	$0, %%rdx, %%xmm0\n\t"               \
-    "pxor	%%xmm0, %%xmm13\n\t"                 \
-    GHASH_FULL_AVX(%%xmm13, %%xmm12, %%xmm13, HR)    \
-    "pshufb	%[BSWAP_MASK], %%xmm13\n\t"          \
-    "#   Encrypt counter\n\t"                        \
-    "movdqa	0(%[KEY]), %%xmm4\n\t"               \
-    "pxor	%%xmm13, %%xmm4\n\t"                 \
-    AESENC_AVX(%%xmm4)                               \
-    "movdqu	%%xmm4, " VAR(TR) "\n\t"
-
-#define CALC_AAD()                           \
-    "# Additional authentication data\n\t"   \
-    "movl	%[abytes], %%edx\n\t"        \
-    "cmpl	$0, %%edx\n\t"               \
-    "je		25f\n\t"                     \
-    "movq	%[addt], %%rax\n\t"          \
-    "xorl	%%ecx, %%ecx\n\t"            \
-    "cmpl	$16, %%edx\n\t"              \
-    "jl		24f\n\t"                     \
-    "andl	$0xfffffff0, %%edx\n\t"      \
-    "\n"                                     \
-    "23:\n\t"                                \
-    "movdqu	(%%rax,%%rcx,1), %%xmm4\n\t" \
-    "pshufb	%[BSWAP_MASK], %%xmm4\n\t"   \
-    "pxor	%%xmm4, " VAR(XR) "\n\t"     \
-    GHASH_FULL_AVX(XR, %%xmm12, XR, HR)      \
-    "addl	$16, %%ecx\n\t"              \
-    "cmpl	%%edx, %%ecx\n\t"            \
-    "jl		23b\n\t"                     \
-    "movl	%[abytes], %%edx\n\t"        \
-    "cmpl	%%edx, %%ecx\n\t"            \
-    "je		25f\n\t"                     \
-    "\n"                                     \
-    "24:\n\t"                                \
-    "subq	$16, %%rsp\n\t"              \
-    "pxor	%%xmm4, %%xmm4\n\t"          \
-    "xorl	%%ebx, %%ebx\n\t"            \
-    "movdqu	%%xmm4, (%%rsp)\n\t"         \
-    "22:\n\t"                                \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t" \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t" \
-    "incl	%%ecx\n\t"                   \
-    "incl	%%ebx\n\t"                   \
-    "cmpl	%%edx, %%ecx\n\t"            \
-    "jl		22b\n\t"                     \
-    "movdqu	(%%rsp), %%xmm4\n\t"         \
-    "addq	$16, %%rsp\n\t"              \
-    "pshufb	%[BSWAP_MASK], %%xmm4\n\t"   \
-    "pxor	%%xmm4, " VAR(XR) "\n\t"     \
-    GHASH_FULL_AVX(XR, %%xmm12, XR, HR)      \
-    "\n"                                     \
-    "25:\n\t"
-
-#define CALC_HT_8_AVX()                            \
-    "movdqa	" VAR(XR) ", %%xmm2\n\t"           \
-    "# H ^ 1\n\t"                                  \
-    "movdqu	" VAR(HR) ", 0(" VAR(HTR) ")\n\t"  \
-    "# H ^ 2\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm0, HR, HR)            \
-    "movdqu	%%xmm0 ,  16(" VAR(HTR) ")\n\t"    \
-    "# H ^ 3\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm1, HR, %%xmm0)        \
-    "movdqu	%%xmm1 ,  32(" VAR(HTR) ")\n\t"    \
-    "# H ^ 4\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm3, %%xmm0, %%xmm0)    \
-    "movdqu	%%xmm3 ,  48(" VAR(HTR) ")\n\t"    \
-    "# H ^ 5\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm12, %%xmm0, %%xmm1)   \
-    "movdqu	%%xmm12,  64(" VAR(HTR) ")\n\t"    \
-    "# H ^ 6\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm12, %%xmm1, %%xmm1)   \
-    "movdqu	%%xmm12,  80(" VAR(HTR) ")\n\t"    \
-    "# H ^ 7\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm12, %%xmm1, %%xmm3)   \
-    "movdqu	%%xmm12,  96(" VAR(HTR) ")\n\t"    \
-    "# H ^ 8\n\t"                                  \
-    GHASH_GFMUL_RED_AVX(%%xmm12, %%xmm3, %%xmm3)   \
-    "movdqu	%%xmm12, 112(" VAR(HTR) ")\n\t"
-
-#define AESENC_128_GHASH_AVX(src, o)                 \
-    "leaq	(%[in]," VAR(KR64) ",1), %%rcx\n\t"  \
-    "leaq	(%[out]," VAR(KR64) ",1), %%rdx\n\t" \
-    /* src is either %%rcx or %%rdx */               \
-    AESENC_CTR()                                     \
-    AESENC_XOR()                                     \
-    AESENC_PCLMUL_1(src,  16, o-128, 112)            \
-    AESENC_PCLMUL_N(src,  32, o-112,  96)            \
-    AESENC_PCLMUL_N(src,  48, o -96,  80)            \
-    AESENC_PCLMUL_N(src,  64, o -80,  64)            \
-    AESENC_PCLMUL_N(src,  80, o -64,  48)            \
-    AESENC_PCLMUL_N(src,  96, o -48,  32)            \
-    AESENC_PCLMUL_N(src, 112, o -32,  16)            \
-    AESENC_PCLMUL_N(src, 128, o -16,   0)            \
-    AESENC_PCLMUL_L(144)                             \
-    "cmpl	$11, %[nr]\n\t"                      \
-    "movdqa	160(%[KEY]), %%xmm12\n\t"            \
-    "jl		4f\n\t"                              \
-    AESENC()                                         \
-    AESENC_SET(176)                                  \
-    "cmpl	$13, %[nr]\n\t"                      \
-    "movdqa	192(%[KEY]), %%xmm12\n\t"            \
-    "jl		4f\n\t"                              \
-    AESENC()                                         \
-    AESENC_SET(208)                                  \
-    "movdqa	224(%[KEY]), %%xmm12\n\t"            \
-    "\n"                                             \
-"4:\n\t"                                             \
-    AESENC_LAST(%%rcx, %%rdx)
-
-#define AESENC_LAST15_ENC_AVX()                       \
-    "movl	%[nbytes], %%ecx\n\t"                 \
-    "movl	%%ecx, %%edx\n\t"                     \
-    "andl	$0x0f, %%ecx\n\t"                     \
-    "jz		55f\n\t"                              \
-    "movdqu	" VAR(CTR1) ", %%xmm13\n\t"           \
-    "pshufb	%[BSWAP_EPI64], %%xmm13\n\t"          \
-    "pxor	0(%[KEY]), %%xmm13\n\t"               \
-    AESENC_AVX(%%xmm13)                               \
-    "subq	$16, %%rsp\n\t"                       \
-    "xorl	%%ecx, %%ecx\n\t"                     \
-    "movdqu	%%xmm13, (%%rsp)\n\t"                 \
-    "\n"                                              \
-    "51:\n\t"                                         \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"  \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"          \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t" \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"          \
-    "incl	" VAR(KR) "\n\t"                      \
-    "incl	%%ecx\n\t"                            \
-    "cmpl	%%edx, " VAR(KR) "\n\t"               \
-    "jl		51b\n\t"                              \
-    "xorq	%%r13, %%r13\n\t"                     \
-    "cmpl	$16, %%ecx\n\t"                       \
-    "je		53f\n\t"                              \
-    "\n"                                              \
-    "52:\n\t"                                         \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"          \
-    "incl	%%ecx\n\t"                            \
-    "cmpl	$16, %%ecx\n\t"                       \
-    "jl		52b\n\t"                              \
-    "53:\n\t"                                         \
-    "movdqu	(%%rsp), %%xmm13\n\t"                 \
-    "addq	$16, %%rsp\n\t"                       \
-    "pshufb	%[BSWAP_MASK], %%xmm13\n\t"           \
-    "pxor	%%xmm13, " VAR(XR) "\n\t"             \
-    GHASH_GFMUL_RED_AVX(XR, HR, XR)                   \
-
-#define AESENC_LAST15_DEC_AVX()                       \
-    "movl	%[nbytes], %%ecx\n\t"                 \
-    "movl	%%ecx, %%edx\n\t"                     \
-    "andl	$0x0f, %%ecx\n\t"                     \
-    "jz		55f\n\t"                              \
-    "movdqu	" VAR(CTR1) ", %%xmm13\n\t"           \
-    "pshufb	%[BSWAP_EPI64], %%xmm13\n\t"          \
-    "pxor	0(%[KEY]), %%xmm13\n\t"               \
-    AESENC_AVX(%%xmm13)                               \
-    "subq	$32, %%rsp\n\t"                       \
-    "xorl	%%ecx, %%ecx\n\t"                     \
-    "movdqu	%%xmm13, (%%rsp)\n\t"                 \
-    "pxor	%%xmm0, %%xmm0\n\t"                   \
-    "movdqu	%%xmm0, 16(%%rsp)\n\t"                \
-    "\n"                                              \
-    "51:\n\t"                                         \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"  \
-    "movb	%%r13b, 16(%%rsp,%%rcx,1)\n\t"        \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"          \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t" \
-    "incl	" VAR(KR) "\n\t"                      \
-    "incl	%%ecx\n\t"                            \
-    "cmpl	%%edx, " VAR(KR) "\n\t"               \
-    "jl		51b\n\t"                              \
-    "53:\n\t"                                         \
-    "movdqu	16(%%rsp), %%xmm13\n\t"               \
-    "addq	$32, %%rsp\n\t"                       \
-    "pshufb	%[BSWAP_MASK], %%xmm13\n\t"           \
-    "pxor	%%xmm13, " VAR(XR) "\n\t"             \
-    GHASH_GFMUL_RED_AVX(XR, HR, XR)                   \
-
-#define CALC_TAG()                              \
-    "movl	%[nbytes], %%edx\n\t"           \
-    "movl	%[abytes], %%ecx\n\t"           \
-    "shlq	$3, %%rdx\n\t"                  \
-    "shlq	$3, %%rcx\n\t"                  \
-    "pinsrq	$0, %%rdx, %%xmm0\n\t"          \
-    "pinsrq	$1, %%rcx, %%xmm0\n\t"          \
-    "pxor	%%xmm0, " VAR(XR) "\n\t"        \
-    GHASH_GFMUL_RED_AVX(XR, HR, XR)             \
-    "pshufb	%[BSWAP_MASK], " VAR(XR) "\n\t" \
-    "movdqu	" VAR(TR) ", %%xmm0\n\t"        \
-    "pxor	" VAR(XR) ", %%xmm0\n\t"        \
-
-#define STORE_TAG()                           \
-    "cmpl	$16, %[tbytes]\n\t"           \
-    "je		71f\n\t"                      \
-    "xorq	%%rcx, %%rcx\n\t"             \
-    "movdqu	%%xmm0, (%%rsp)\n\t"          \
-    "73:\n\t"                                 \
-    "movzbl	(%%rsp,%%rcx,1), %%r13d\n\t"  \
-    "movb	%%r13b, (%[tag],%%rcx,1)\n\t" \
-    "incl	%%ecx\n\t"                    \
-    "cmpl	%[tbytes], %%ecx\n\t"         \
-    "jne	73b\n\t"                      \
-    "jmp	72f\n\t"                      \
-    "\n"                                      \
-    "71:\n\t"                                 \
-    "movdqu	%%xmm0, (%[tag])\n\t"         \
-    "\n"                                      \
-    "72:\n\t"
-
-#define CMP_TAG()                                          \
-    "cmpl	$16, %[tbytes]\n\t"                        \
-    "je		71f\n\t"                                   \
-    "subq	$16, %%rsp\n\t"                            \
-    "xorq	%%rcx, %%rcx\n\t"                          \
-    "xorq	%%rax, %%rax\n\t"                          \
-    "movdqu	%%xmm0, (%%rsp)\n\t"                       \
-    "\n"                                                   \
-    "73:\n\t"                                              \
-    "movzbl	(%%rsp,%%rcx,1), %%r13d\n\t"               \
-    "xorb	(%[tag],%%rcx,1), %%r13b\n\t"              \
-    "orb	%%r13b, %%al\n\t"                          \
-    "incl	%%ecx\n\t"                                 \
-    "cmpl	%[tbytes], %%ecx\n\t"                      \
-    "jne	73b\n\t"                                   \
-    "cmpb	$0x00, %%al\n\t"                           \
-    "sete	%%al\n\t"                                  \
-    "addq	$16, %%rsp\n\t"                            \
-    "xorq	%%rcx, %%rcx\n\t"                          \
-    "jmp	72f\n\t"                                   \
-    "\n"                                                   \
-    "71:\n\t"                                              \
-    "movdqu	(%[tag]), %%xmm1\n\t"                      \
-    "pcmpeqb	%%xmm1, %%xmm0\n\t"                        \
-    "pmovmskb	%%xmm0, %%edx\n\t"                         \
-    "# %%edx == 0xFFFF then return 1 else => return 0\n\t" \
-    "xorl	%%eax, %%eax\n\t"                          \
-    "cmpl	$0xffff, %%edx\n\t"                        \
-    "sete	%%al\n\t"                                  \
-    "\n"                                                   \
-    "72:\n\t"                                              \
-    "movl	%%eax, (%[res])\n\t"
-
-static void AES_GCM_encrypt(const unsigned char *in, unsigned char *out,
-                            const unsigned char* addt,
-                            const unsigned char* ivec, unsigned char *tag,
-                            unsigned int nbytes, unsigned int abytes,
-                            unsigned int ibytes, unsigned int tbytes,
-                            const unsigned char* key, int nr)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register unsigned int ivLen asm("ebx") = ibytes;
-
-    __asm__ __volatile__ (
-        "subq	$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "pxor	%%xmm13, %%xmm13\n\t"
-        "pxor	" VAR(XR) ", " VAR(XR) "\n\t"
-        "movl	%[ibytes], %%edx\n\t"
-        "cmpl	$12, %%edx\n\t"
-        "jne	35f\n\t"
-        CALC_IV_12()
-        "\n"
-        "35:\n\t"
-        CALC_IV()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD()
-
-        "# Calculate counter and H\n\t"
-        "pshufb	%[BSWAP_EPI64], %%xmm13\n\t"
-        "movdqa	" VAR(HR) ", %%xmm5\n\t"
-        "paddd	%[ONE], %%xmm13\n\t"
-        "movdqa	" VAR(HR) ", %%xmm4\n\t"
-        "movdqu	%%xmm13, " VAR(CTR1) "\n\t"
-        "psrlq	$63, %%xmm5\n\t"
-        "psllq	$1, %%xmm4\n\t"
-        "pslldq	$8, %%xmm5\n\t"
-        "por	%%xmm5, %%xmm4\n\t"
-        "pshufd	$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "psrad	$31, " VAR(HR) "\n\t"
-        "pand	%[MOD2_128], " VAR(HR) "\n\t"
-        "pxor	%%xmm4, " VAR(HR) "\n\t"
-
-        "xorl	" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-        "cmpl	$128, %[nbytes]\n\t"
-        "movl	%[nbytes], %%r13d\n\t"
-        "jl	5f\n\t"
-        "andl	$0xffffff80, %%r13d\n\t"
-
-        CALC_HT_8_AVX()
-
-        "# First 128 bytes of input\n\t"
-        AESENC_CTR()
-        AESENC_XOR()
-        AESENC_SET(16)
-        AESENC_SET(32)
-        AESENC_SET(48)
-        AESENC_SET(64)
-        AESENC_SET(80)
-        AESENC_SET(96)
-        AESENC_SET(112)
-        AESENC_SET(128)
-        AESENC_SET(144)
-        "cmpl	$11, %[nr]\n\t"
-        "movdqa	160(%[KEY]), %%xmm12\n\t"
-        "jl	1f\n\t"
-        AESENC()
-        AESENC_SET(176)
-        "cmpl	$13, %[nr]\n\t"
-        "movdqa	192(%[KEY]), %%xmm12\n\t"
-        "jl	1f\n\t"
-        AESENC()
-        AESENC_SET(208)
-        "movdqa	224(%[KEY]), %%xmm12\n\t"
-        "\n"
-    "1:\n\t"
-        AESENC_LAST(%[in], %[out])
-
-        "cmpl	$128, %%r13d\n\t"
-        "movl	$128, " VAR(KR) "\n\t"
-        "jle	2f\n\t"
-
-        "# More 128 bytes of input\n\t"
-        "\n"
-    "3:\n\t"
-        AESENC_128_GHASH_AVX(%%rdx, 0)
-        "addl	$128, " VAR(KR) "\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jl	3b\n\t"
-        "\n"
-    "2:\n\t"
-        "movdqa	%[BSWAP_MASK], %%xmm13\n\t"
-        "pshufb	%%xmm13, %%xmm4\n\t"
-        "pshufb	%%xmm13, %%xmm5\n\t"
-        "pshufb	%%xmm13, %%xmm6\n\t"
-        "pshufb	%%xmm13, %%xmm7\n\t"
-        "pxor	%%xmm2, %%xmm4\n\t"
-        "pshufb	%%xmm13, %%xmm8\n\t"
-        "pshufb	%%xmm13, %%xmm9\n\t"
-        "pshufb	%%xmm13, %%xmm10\n\t"
-        "pshufb	%%xmm13, %%xmm11\n\t"
-
-        "movdqu	112(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_AVX(XR, %%xmm13, %%xmm4, %%xmm12)
-        "movdqu	 96(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm5, %%xmm12)
-        "movdqu	 80(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm6, %%xmm12)
-        "movdqu	 64(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm7, %%xmm12)
-        "movdqu	 48(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm8, %%xmm12)
-        "movdqu	 32(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm9, %%xmm12)
-        "movdqu	 16(" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_XOR_AVX(XR, %%xmm13, %%xmm10, %%xmm12)
-        "movdqu	   (" VAR(HTR) "), %%xmm12\n\t"
-        GHASH_GFMUL_RED_XOR_AVX(XR, %%xmm13, %%xmm11, %%xmm12)
-
-        "movdqu	0(" VAR(HTR) "), " VAR(HR) "\n\t"
-        "\n"
-    "5:\n\t"
-        "movl	%[nbytes], %%edx\n\t"
-        "cmpl	%%edx, " VAR(KR) "\n\t"
-        "jge	55f\n\t"
-#endif
-
-        "movl	%[nbytes], %%r13d\n\t"
-        "andl	$0xfffffff0, %%r13d\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jge	14f\n\t"
-
-        "leaq	(%[in]," VAR(KR64) ",1), %%rcx\n\t"
-        "leaq	(%[out]," VAR(KR64) ",1), %%rdx\n\t"
-        AESENC_BLOCK(%%rcx, %%rdx)
-        "addl	$16, " VAR(KR) "\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jge	13f\n\t"
-        "\n"
-        "12:\n\t"
-        "leaq	(%[in]," VAR(KR64) ",1), %%rcx\n\t"
-        "leaq	(%[out]," VAR(KR64) ",1), %%rdx\n\t"
-        AESENC_GFMUL(%%rcx, %%rdx, HR, XR)
-        "pshufb	%[BSWAP_MASK], %%xmm4\n\t"
-        "pxor	%%xmm4, " VAR(XR) "\n\t"
-        "addl	$16, " VAR(KR) "\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jl	12b\n\t"
-        "\n"
-        "13:\n\t"
-        GHASH_GFMUL_RED_AVX(XR, HR, XR)
-        "\n"
-        "14:\n\t"
-
-        AESENC_LAST15_ENC_AVX()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG()
-        STORE_TAG()
-        "addq	$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tbytes),
-          [tag] "r" (tag),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "rdx", "r13"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX1
-/* Encrypt with key in xmm12. */
-#define VAESENC()                              \
-    "vaesenc	%%xmm12, %%xmm4, %%xmm4\n\t"   \
-    "vaesenc	%%xmm12, %%xmm5, %%xmm5\n\t"   \
-    "vaesenc	%%xmm12, %%xmm6, %%xmm6\n\t"   \
-    "vaesenc	%%xmm12, %%xmm7, %%xmm7\n\t"   \
-    "vaesenc	%%xmm12, %%xmm8, %%xmm8\n\t"   \
-    "vaesenc	%%xmm12, %%xmm9, %%xmm9\n\t"   \
-    "vaesenc	%%xmm12, %%xmm10, %%xmm10\n\t" \
-    "vaesenc	%%xmm12, %%xmm11, %%xmm11\n\t"
-
-#define VAESENC_SET(o)                         \
-    "vmovdqa	"#o"(%[KEY]), %%xmm12\n\t"     \
-    VAESENC()
-
-#define VAESENC_CTR()                          \
-    "vmovdqu	" VAR(CTR1) ", %%xmm0\n\t"     \
-    "vmovdqa	%[BSWAP_EPI64], %%xmm1\n\t"    \
-    "vpshufb	%%xmm1, %%xmm0, %%xmm4\n\t"    \
-    "vpaddd	%[ONE], %%xmm0, %%xmm5\n\t"    \
-    "vpshufb	%%xmm1, %%xmm5, %%xmm5\n\t"    \
-    "vpaddd	%[TWO], %%xmm0, %%xmm6\n\t"    \
-    "vpshufb	%%xmm1, %%xmm6, %%xmm6\n\t"    \
-    "vpaddd	%[THREE], %%xmm0, %%xmm7\n\t"  \
-    "vpshufb	%%xmm1, %%xmm7, %%xmm7\n\t"    \
-    "vpaddd	%[FOUR], %%xmm0, %%xmm8\n\t"   \
-    "vpshufb	%%xmm1, %%xmm8, %%xmm8\n\t"    \
-    "vpaddd	%[FIVE], %%xmm0, %%xmm9\n\t"   \
-    "vpshufb	%%xmm1, %%xmm9, %%xmm9\n\t"    \
-    "vpaddd	%[SIX], %%xmm0, %%xmm10\n\t"   \
-    "vpshufb	%%xmm1, %%xmm10, %%xmm10\n\t"  \
-    "vpaddd	%[SEVEN], %%xmm0, %%xmm11\n\t" \
-    "vpshufb	%%xmm1, %%xmm11, %%xmm11\n\t"  \
-    "vpaddd	%[EIGHT], %%xmm0, %%xmm0\n\t"
-
-#define VAESENC_XOR()                          \
-    "vmovdqa	(%[KEY]), %%xmm12\n\t"         \
-    "vmovdqu	%%xmm0, " VAR(CTR1) "\n\t"     \
-    "vpxor	%%xmm12, %%xmm4, %%xmm4\n\t"   \
-    "vpxor	%%xmm12, %%xmm5, %%xmm5\n\t"   \
-    "vpxor	%%xmm12, %%xmm6, %%xmm6\n\t"   \
-    "vpxor	%%xmm12, %%xmm7, %%xmm7\n\t"   \
-    "vpxor	%%xmm12, %%xmm8, %%xmm8\n\t"   \
-    "vpxor	%%xmm12, %%xmm9, %%xmm9\n\t"   \
-    "vpxor	%%xmm12, %%xmm10, %%xmm10\n\t" \
-    "vpxor	%%xmm12, %%xmm11, %%xmm11\n\t"
-
-#define VAESENC_128()                     \
-    VAESENC_CTR()                         \
-    VAESENC_XOR()                         \
-    VAESENC_SET(16)                       \
-    VAESENC_SET(32)                       \
-    VAESENC_SET(48)                       \
-    VAESENC_SET(64)                       \
-    VAESENC_SET(80)                       \
-    VAESENC_SET(96)                       \
-    VAESENC_SET(112)                      \
-    VAESENC_SET(128)                      \
-    VAESENC_SET(144)                      \
-    "cmpl	$11, %[nr]\n\t"           \
-    "vmovdqa	160(%[KEY]), %%xmm12\n\t" \
-    "jl	1f\n\t"                           \
-    VAESENC()                             \
-    VAESENC_SET(176)                      \
-    "cmpl	$13, %[nr]\n\t"           \
-    "vmovdqa	192(%[KEY]), %%xmm12\n\t" \
-    "jl	1f\n\t"                           \
-    VAESENC()                             \
-    VAESENC_SET(208)                      \
-    "vmovdqa	224(%[KEY]), %%xmm12\n\t" \
-    "\n"                                  \
-"1:\n\t"                                  \
-    VAESENC_LAST(%[in], %[out])
-
-/* Encrypt and carry-less multiply for AVX1. */
-#define VAESENC_PCLMUL_1(src, o1, o2, o3)              \
-    "vmovdqu	" #o3 "(" VAR(HTR) "), %%xmm12\n\t"    \
-    "vmovdqu	" #o2 "(" #src "), %%xmm0\n\t"         \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm4, %%xmm4\n\t"   \
-    "vpshufb	%[BSWAP_MASK], %%xmm0, %%xmm0\n\t"     \
-    "vpxor	%%xmm2, %%xmm0, %%xmm0\n\t"            \
-    "vpshufd	$0x4e, %%xmm12, %%xmm1\n\t"            \
-    "vpshufd	$0x4e, %%xmm0, %%xmm14\n\t"            \
-    "vpxor	%%xmm12, %%xmm1, %%xmm1\n\t"           \
-    "vpxor	%%xmm0, %%xmm14, %%xmm14\n\t"          \
-    "vpclmulqdq	$0x11, %%xmm12, %%xmm0, %%xmm3\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm5, %%xmm5\n\t"   \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm6, %%xmm6\n\t"   \
-    "vpclmulqdq	$0x00, %%xmm12, %%xmm0, %%xmm2\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm7, %%xmm7\n\t"   \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm8, %%xmm8\n\t"   \
-    "vpclmulqdq	$0x00, %%xmm14, %%xmm1, %%xmm1\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm9, %%xmm9\n\t"   \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm10, %%xmm10\n\t" \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm11, %%xmm11\n\t" \
-    "vpxor      %%xmm2, %%xmm1, %%xmm1\n\t"            \
-    "vpxor      %%xmm3, %%xmm1, %%xmm1\n\t"            \
-
-#define VAESENC_PCLMUL_N(src, o1, o2, o3)               \
-    "vmovdqu	" #o3 "(" VAR(HTR) "), %%xmm12\n\t"     \
-    "vmovdqu	" #o2 "(" #src "), %%xmm0\n\t"          \
-    "vpshufd	$0x4e, %%xmm12, %%xmm13\n\t"            \
-    "vpshufb	%[BSWAP_MASK], %%xmm0, %%xmm0\n\t"      \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpxor	%%xmm12, %%xmm13, %%xmm13\n\t"          \
-    "vpshufd	$0x4e, %%xmm0, %%xmm14\n\t"             \
-    "vpxor	%%xmm0, %%xmm14, %%xmm14\n\t"           \
-    "vpclmulqdq	$0x11, %%xmm12, %%xmm0, %%xmm15\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm5, %%xmm5\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm6, %%xmm6\n\t"    \
-    "vpclmulqdq	$0x00, %%xmm12, %%xmm0, %%xmm12\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm7, %%xmm7\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm8, %%xmm8\n\t"    \
-    "vpclmulqdq	$0x00, %%xmm14, %%xmm13, %%xmm13\n\t"   \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm9, %%xmm9\n\t"    \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm10, %%xmm10\n\t"  \
-    "vaesenc	" #o1 "(%[KEY]), %%xmm11, %%xmm11\n\t"  \
-    "vpxor      %%xmm12, %%xmm1, %%xmm1\n\t"            \
-    "vpxor      %%xmm12, %%xmm2, %%xmm2\n\t"            \
-    "vpxor      %%xmm15, %%xmm1, %%xmm1\n\t"            \
-    "vpxor      %%xmm15, %%xmm3, %%xmm3\n\t"            \
-    "vpxor      %%xmm13, %%xmm1, %%xmm1\n\t"            \
-
-#define VAESENC_PCLMUL_L(o)                         \
-    "vpslldq	$8, %%xmm1, %%xmm14\n\t"            \
-    "vpsrldq	$8, %%xmm1, %%xmm1\n\t"             \
-    "vaesenc	"#o"(%[KEY]), %%xmm4, %%xmm4\n\t"   \
-    "vpxor      %%xmm14, %%xmm2, %%xmm2\n\t"        \
-    "vpxor      %%xmm1, %%xmm3, %%xmm3\n\t"         \
-    "vaesenc	"#o"(%[KEY]), %%xmm5, %%xmm5\n\t"   \
-    "vpslld	$31, %%xmm2, %%xmm12\n\t"           \
-    "vpslld	$30, %%xmm2, %%xmm13\n\t"           \
-    "vpslld	$25, %%xmm2, %%xmm14\n\t"           \
-    "vaesenc	"#o"(%[KEY]), %%xmm6, %%xmm6\n\t"   \
-    "vpxor	%%xmm13, %%xmm12, %%xmm12\n\t"      \
-    "vpxor	%%xmm14, %%xmm12, %%xmm12\n\t"      \
-    "vaesenc	"#o"(%[KEY]), %%xmm7, %%xmm7\n\t"   \
-    "vpsrldq	$4, %%xmm12, %%xmm13\n\t"           \
-    "vpslldq	$12, %%xmm12, %%xmm12\n\t"          \
-    "vaesenc	"#o"(%[KEY]), %%xmm8, %%xmm8\n\t"   \
-    "vpxor	%%xmm12, %%xmm2, %%xmm2\n\t"        \
-    "vpsrld	$1, %%xmm2, %%xmm14\n\t"            \
-    "vaesenc	"#o"(%[KEY]), %%xmm9, %%xmm9\n\t"   \
-    "vpsrld	$2, %%xmm2, %%xmm1\n\t"             \
-    "vpsrld	$7, %%xmm2, %%xmm0\n\t"             \
-    "vaesenc	"#o"(%[KEY]), %%xmm10, %%xmm10\n\t" \
-    "vpxor	%%xmm1, %%xmm14, %%xmm14\n\t"       \
-    "vpxor	%%xmm0, %%xmm14, %%xmm14\n\t"       \
-    "vaesenc	"#o"(%[KEY]), %%xmm11, %%xmm11\n\t" \
-    "vpxor	%%xmm13, %%xmm14, %%xmm14\n\t"      \
-    "vpxor	%%xmm14, %%xmm2, %%xmm2\n\t"        \
-    "vpxor	%%xmm3, %%xmm2, %%xmm2\n\t"         \
-
-
-/* Encrypt and carry-less multiply with last key. */
-#define VAESENC_LAST(in, out)                          \
-    "vaesenclast	%%xmm12, %%xmm4, %%xmm4\n\t"   \
-    "vaesenclast	%%xmm12, %%xmm5, %%xmm5\n\t"   \
-    "vmovdqu		   (" #in "), %%xmm0\n\t"      \
-    "vmovdqu		 16(" #in "), %%xmm1\n\t"      \
-    "vpxor		%%xmm0, %%xmm4, %%xmm4\n\t"    \
-    "vpxor		%%xmm1, %%xmm5, %%xmm5\n\t"    \
-    "vmovdqu		%%xmm4,    (" #out ")\n\t"     \
-    "vmovdqu		%%xmm5,  16(" #out ")\n\t"     \
-    "vaesenclast	%%xmm12, %%xmm6, %%xmm6\n\t"   \
-    "vaesenclast	%%xmm12, %%xmm7, %%xmm7\n\t"   \
-    "vmovdqu		 32(" #in "), %%xmm0\n\t"      \
-    "vmovdqu		 48(" #in "), %%xmm1\n\t"      \
-    "vpxor		%%xmm0, %%xmm6, %%xmm6\n\t"    \
-    "vpxor		%%xmm1, %%xmm7, %%xmm7\n\t"    \
-    "vmovdqu		%%xmm6,  32(" #out ")\n\t"     \
-    "vmovdqu		%%xmm7,  48(" #out ")\n\t"     \
-    "vaesenclast	%%xmm12, %%xmm8, %%xmm8\n\t"   \
-    "vaesenclast	%%xmm12, %%xmm9, %%xmm9\n\t"   \
-    "vmovdqu		 64(" #in "), %%xmm0\n\t"      \
-    "vmovdqu		 80(" #in "), %%xmm1\n\t"      \
-    "vpxor		%%xmm0, %%xmm8, %%xmm8\n\t"    \
-    "vpxor		%%xmm1, %%xmm9, %%xmm9\n\t"    \
-    "vmovdqu		%%xmm8,  64(" #out ")\n\t"     \
-    "vmovdqu		%%xmm9,  80(" #out ")\n\t"     \
-    "vaesenclast	%%xmm12, %%xmm10, %%xmm10\n\t" \
-    "vaesenclast	%%xmm12, %%xmm11, %%xmm11\n\t" \
-    "vmovdqu		 96(" #in "), %%xmm0\n\t"      \
-    "vmovdqu		112(" #in "), %%xmm1\n\t"      \
-    "vpxor		%%xmm0, %%xmm10, %%xmm10\n\t"  \
-    "vpxor		%%xmm1, %%xmm11, %%xmm11\n\t"  \
-    "vmovdqu		%%xmm10,  96(" #out ")\n\t"    \
-    "vmovdqu		%%xmm11, 112(" #out ")\n\t"
-
-#define VAESENC_BLOCK()                                       \
-    "vmovdqu		" VAR(CTR1) ", %%xmm5\n\t"            \
-    "vpshufb		%[BSWAP_EPI64], %%xmm5, %%xmm4\n\t"   \
-    "vpaddd		%[ONE], %%xmm5, %%xmm5\n\t"           \
-    "vmovdqu		%%xmm5, " VAR(CTR1) "\n\t"            \
-    "vpxor		(%[KEY]), %%xmm4, %%xmm4\n\t"         \
-    "vaesenc		16(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		32(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		48(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		64(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		80(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		96(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		112(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		128(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		144(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "cmpl		$11, %[nr]\n\t"                       \
-    "vmovdqa		160(%[KEY]), %%xmm5\n\t"              \
-    "jl			%=f\n\t"                              \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		176(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "cmpl		$13, %[nr]\n\t"                       \
-    "vmovdqa		192(%[KEY]), %%xmm5\n\t"              \
-    "jl			%=f\n\t"                              \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		208(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vmovdqa		224(%[KEY]), %%xmm5\n\t"              \
-    "%=:\n\t"                                                 \
-    "vaesenclast	%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		(%[in]," VAR(KR64) ",1), %%xmm5\n\t"  \
-    "vpxor		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		%%xmm4, (%[out]," VAR(KR64) ",1)\n\t" \
-    "vpshufb		%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"    \
-    "vpxor		%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"
-
-#define _VAESENC_GFMUL(in, H, X)                              \
-    "vmovdqu		" VAR(CTR1) ", %%xmm5\n\t"            \
-    "vpshufb		%[BSWAP_EPI64], %%xmm5, %%xmm4\n\t"   \
-    "vpaddd		%[ONE], %%xmm5, %%xmm5\n\t"           \
-    "vmovdqu		%%xmm5, " VAR(CTR1) "\n\t"            \
-    "vpxor		(%[KEY]), %%xmm4, %%xmm4\n\t"         \
-    "vpclmulqdq		$0x10, " #H ", " #X ", %%xmm6\n\t"    \
-    "vaesenc		16(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		32(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vpclmulqdq		$0x01, " #H ", " #X ", %%xmm7\n\t"    \
-    "vaesenc		48(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vaesenc		64(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vpclmulqdq		$0x00, " #H ", " #X ", %%xmm8\n\t"    \
-    "vaesenc		80(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vpclmulqdq		$0x11, " #H ", " #X ", %%xmm1\n\t"    \
-    "vaesenc		96(%[KEY]), %%xmm4, %%xmm4\n\t"       \
-    "vpxor		%%xmm7, %%xmm6, %%xmm6\n\t"           \
-    "vpslldq		$8, %%xmm6, %%xmm2\n\t"               \
-    "vpsrldq		$8, %%xmm6, %%xmm6\n\t"               \
-    "vaesenc		112(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vpxor		%%xmm8, %%xmm2, %%xmm2\n\t"           \
-    "vpxor		%%xmm6, %%xmm1, %%xmm3\n\t"           \
-    "vmovdqa		%[MOD2_128], %%xmm0\n\t"              \
-    "vpclmulqdq		$0x10, %%xmm0, %%xmm2, %%xmm7\n\t"    \
-    "vaesenc		128(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vpshufd		$0x4e, %%xmm2, %%xmm6\n\t"            \
-    "vpxor		%%xmm7, %%xmm6, %%xmm6\n\t"           \
-    "vpclmulqdq		$0x10, %%xmm0, %%xmm6, %%xmm7\n\t"    \
-    "vaesenc		144(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vpshufd		$0x4e, %%xmm6, %%xmm6\n\t"            \
-    "vpxor		%%xmm7, %%xmm6, %%xmm6\n\t"           \
-    "vpxor		%%xmm3, %%xmm6, " VAR(XR) "\n\t"      \
-    "cmpl		$11, %[nr]\n\t"                       \
-    "vmovdqa		160(%[KEY]), %%xmm5\n\t"              \
-    "jl			1f\n\t"                               \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		176(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "cmpl		$13, %[nr]\n\t"                       \
-    "vmovdqa		192(%[KEY]), %%xmm5\n\t"              \
-    "jl			1f\n\t"                               \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		208(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vmovdqa		224(%[KEY]), %%xmm5\n\t"              \
-    "1:\n\t"                                                  \
-    "vaesenclast	%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		" #in ", %%xmm0\n\t"                  \
-    "vpxor		%%xmm0, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		%%xmm4, (%[out]," VAR(KR64) ",1)\n\t"
-#define VAESENC_GFMUL(in, H, X)                               \
-       _VAESENC_GFMUL(in, H, X)
-
-
-#define _GHASH_GFMUL_AVX1(r, r2, a, b)             \
-    "vpshufd	$0x4e, "#a", %%xmm1\n\t"           \
-    "vpshufd	$0x4e, "#b", %%xmm2\n\t"           \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm3\n\t"     \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm0\n\t"     \
-    "vpxor	"#a", %%xmm1, %%xmm1\n\t"          \
-    "vpxor	"#b", %%xmm2, %%xmm2\n\t"          \
-    "vpclmulqdq	$0x00, %%xmm2, %%xmm1, %%xmm1\n\t" \
-    "vpxor	%%xmm0, %%xmm1, %%xmm1\n\t"        \
-    "vpxor	%%xmm3, %%xmm1, %%xmm1\n\t"        \
-    "vmovdqa	%%xmm0, "#r2"\n\t"                 \
-    "vmovdqa	%%xmm3, " #r "\n\t"                \
-    "vpslldq	$8, %%xmm1, %%xmm2\n\t"            \
-    "vpsrldq	$8, %%xmm1, %%xmm1\n\t"            \
-    "vpxor	%%xmm2, "#r2", "#r2"\n\t"          \
-    "vpxor	%%xmm1, " #r ", " #r "\n\t"
-#define GHASH_GFMUL_AVX1(r, r2, a, b)              \
-       _GHASH_GFMUL_AVX1(r, r2, a, b)
-
-#define _GHASH_GFMUL_XOR_AVX1(r, r2, a, b)         \
-    "vpshufd	$0x4e, "#a", %%xmm1\n\t"           \
-    "vpshufd	$0x4e, "#b", %%xmm2\n\t"           \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm3\n\t"     \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm0\n\t"     \
-    "vpxor	"#a", %%xmm1, %%xmm1\n\t"          \
-    "vpxor	"#b", %%xmm2, %%xmm2\n\t"          \
-    "vpclmulqdq	$0x00, %%xmm2, %%xmm1, %%xmm1\n\t" \
-    "vpxor	%%xmm0, %%xmm1, %%xmm1\n\t"        \
-    "vpxor	%%xmm3, %%xmm1, %%xmm1\n\t"        \
-    "vpxor	%%xmm0, "#r2", "#r2"\n\t"          \
-    "vpxor	%%xmm3, " #r ", " #r "\n\t"        \
-    "vpslldq	$8, %%xmm1, %%xmm2\n\t"            \
-    "vpsrldq	$8, %%xmm1, %%xmm1\n\t"            \
-    "vpxor	%%xmm2, "#r2", "#r2"\n\t"          \
-    "vpxor	%%xmm1, " #r ", " #r "\n\t"
-#define GHASH_GFMUL_XOR_AVX1(r, r2, a, b)          \
-       _GHASH_GFMUL_XOR_AVX1(r, r2, a, b)
-
-#define GHASH_MID_AVX1(r, r2)               \
-    "vpsrld	$31, "#r2", %%xmm0\n\t"     \
-    "vpsrld	$31, " #r ", %%xmm1\n\t"    \
-    "vpslld	$1, "#r2", "#r2"\n\t"       \
-    "vpslld	$1, " #r ", " #r "\n\t"     \
-    "vpsrldq	$12, %%xmm0, %%xmm2\n\t"    \
-    "vpslldq	$4, %%xmm0, %%xmm0\n\t"     \
-    "vpslldq	$4, %%xmm1, %%xmm1\n\t"     \
-    "vpor	%%xmm2, " #r ", " #r "\n\t" \
-    "vpor	%%xmm0, "#r2", "#r2"\n\t"   \
-    "vpor	%%xmm1, " #r ", " #r "\n\t"
-
-#define _GHASH_GFMUL_RED_AVX1(r, a, b)             \
-    "vpshufd	$0x4e, "#a", %%xmm5\n\t"           \
-    "vpshufd	$0x4e, "#b", %%xmm6\n\t"           \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm7\n\t"     \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm4\n\t"     \
-    "vpxor	"#a", %%xmm5, %%xmm5\n\t"          \
-    "vpxor	"#b", %%xmm6, %%xmm6\n\t"          \
-    "vpclmulqdq	$0x00, %%xmm6, %%xmm5, %%xmm5\n\t" \
-    "vpxor	%%xmm4, %%xmm5, %%xmm5\n\t"        \
-    "vpxor	%%xmm7, %%xmm5, %%xmm5\n\t"        \
-    "vpslldq	$8, %%xmm5, %%xmm6\n\t"            \
-    "vpsrldq	$8, %%xmm5, %%xmm5\n\t"            \
-    "vpxor	%%xmm6, %%xmm4, %%xmm4\n\t"        \
-    "vpxor	%%xmm5, %%xmm7, " #r "\n\t"        \
-    "vpslld	$31, %%xmm4, %%xmm8\n\t"           \
-    "vpslld	$30, %%xmm4, %%xmm9\n\t"           \
-    "vpslld	$25, %%xmm4, %%xmm10\n\t"          \
-    "vpxor	%%xmm9, %%xmm8, %%xmm8\n\t"        \
-    "vpxor	%%xmm10, %%xmm8, %%xmm8\n\t"       \
-    "vpsrldq	$4, %%xmm8, %%xmm9\n\t"            \
-    "vpslldq	$12, %%xmm8, %%xmm8\n\t"           \
-    "vpxor	%%xmm8, %%xmm4, %%xmm4\n\t"        \
-    "vpsrld	$1, %%xmm4, %%xmm10\n\t"           \
-    "vpsrld	$2, %%xmm4, %%xmm6\n\t"            \
-    "vpsrld	$7, %%xmm4, %%xmm5\n\t"            \
-    "vpxor	%%xmm6, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm5, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm9, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm4, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm10, " #r ", " #r "\n\t"
-#define GHASH_GFMUL_RED_AVX1(r, a, b)              \
-       _GHASH_GFMUL_RED_AVX1(r, a, b)
-
-#define _GHASH_GFSQR_RED_AVX1(r, a)                \
-    "vpclmulqdq	$0x00, "#a", "#a", %%xmm4\n\t"     \
-    "vpclmulqdq	$0x11, "#a", "#a", " #r "\n\t"     \
-    "vpslld	$31, %%xmm4, %%xmm8\n\t"           \
-    "vpslld	$30, %%xmm4, %%xmm9\n\t"           \
-    "vpslld	$25, %%xmm4, %%xmm10\n\t"          \
-    "vpxor	%%xmm9, %%xmm8, %%xmm8\n\t"        \
-    "vpxor	%%xmm10, %%xmm8, %%xmm8\n\t"       \
-    "vpsrldq	$4, %%xmm8, %%xmm9\n\t"            \
-    "vpslldq	$12, %%xmm8, %%xmm8\n\t"           \
-    "vpxor	%%xmm8, %%xmm4, %%xmm4\n\t"        \
-    "vpsrld	$1, %%xmm4, %%xmm10\n\t"           \
-    "vpsrld	$2, %%xmm4, %%xmm6\n\t"            \
-    "vpsrld	$7, %%xmm4, %%xmm5\n\t"            \
-    "vpxor	%%xmm6, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm5, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm9, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm4, %%xmm10, %%xmm10\n\t"      \
-    "vpxor	%%xmm10, " #r ", " #r "\n\t"
-#define GHASH_GFSQR_RED_AVX1(r, a)                 \
-       _GHASH_GFSQR_RED_AVX1(r, a)
-
-#define GHASH_RED_AVX1(r, r2)                \
-    "vpslld	$31, "#r2", %%xmm0\n\t"      \
-    "vpslld	$30, "#r2", %%xmm1\n\t"      \
-    "vpslld	$25, "#r2", %%xmm2\n\t"      \
-    "vpxor	%%xmm1, %%xmm0, %%xmm0\n\t"  \
-    "vpxor	%%xmm2, %%xmm0, %%xmm0\n\t"  \
-    "vmovdqa	%%xmm0, %%xmm1\n\t"          \
-    "vpsrldq	$4, %%xmm1, %%xmm1\n\t"      \
-    "vpslldq	$12, %%xmm0, %%xmm0\n\t"     \
-    "vpxor	%%xmm0, "#r2", "#r2"\n\t"    \
-    "vpsrld	$1, "#r2", %%xmm2\n\t"       \
-    "vpsrld	$2, "#r2", %%xmm3\n\t"       \
-    "vpsrld	$7, "#r2", %%xmm0\n\t"       \
-    "vpxor	%%xmm3, %%xmm2, %%xmm2\n\t"  \
-    "vpxor	%%xmm0, %%xmm2, %%xmm2\n\t"  \
-    "vpxor	%%xmm1, %%xmm2, %%xmm2\n\t"  \
-    "vpxor	"#r2", %%xmm2, %%xmm2\n\t"   \
-    "vpxor	%%xmm2, " #r ", " #r "\n\t"
-
-#define GHASH_GFMUL_RED_XOR_AVX1(r, r2, a, b) \
-    GHASH_GFMUL_XOR_AVX1(r, r2, a, b)         \
-    GHASH_RED_AVX1(r, r2)
-
-#define GHASH_FULL_AVX1(r, r2, a, b) \
-    GHASH_GFMUL_AVX1(r, r2, a, b)    \
-    GHASH_MID_AVX1(r, r2)            \
-    GHASH_RED_AVX1(r, r2)
-
-#define CALC_IV_12_AVX1()                                            \
-    "# Calculate values when IV is 12 bytes\n\t"                     \
-    "# Set counter based on IV\n\t"                                  \
-    "movl		$0x01000000, %%ecx\n\t"                      \
-    "vpinsrq		$0, 0(%%rax), %%xmm13, %%xmm13\n\t"          \
-    "vpinsrd		$2, 8(%%rax), %%xmm13, %%xmm13\n\t"          \
-    "vpinsrd		$3, %%ecx, %%xmm13, %%xmm13\n\t"             \
-    "# H = Encrypt X(=0) and T = Encrypt counter\n\t"                \
-    "vmovdqa		  0(%[KEY]), " VAR(HR) "\n\t"                \
-    "vpxor		" VAR(HR) ", %%xmm13, %%xmm1\n\t"            \
-    "vmovdqa		 16(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 32(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 48(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 64(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 80(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 96(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		112(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		128(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		144(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "cmpl		$11, %[nr]\n\t"                              \
-    "vmovdqa		160(%[KEY]), %%xmm12\n\t"                    \
-    "jl	31f\n\t"                                                     \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		176(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "cmpl		$13, %[nr]\n\t"                              \
-    "vmovdqa		192(%[KEY]), %%xmm12\n\t"                    \
-    "jl	31f\n\t"                                                     \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		208(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqu		224(%[KEY]), %%xmm12\n\t"                    \
-    "31:\n\t"                                                        \
-    "vaesenclast	%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenclast	%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vpshufb		%[BSWAP_MASK], " VAR(HR) ", " VAR(HR) "\n\t" \
-    "vmovdqu		%%xmm1, " VAR(TR) "\n\t"                     \
-    "jmp		39f\n\t"
-
-#define CALC_IV_AVX1()                                       \
-    "# Calculate values when IV is not 12 bytes\n\t"         \
-    "# H = Encrypt X(=0)\n\t"                                \
-    "vmovdqa	0(%[KEY]), " VAR(HR) "\n\t"                  \
-    VAESENC_AVX(HR)                                          \
-    "vpshufb	%[BSWAP_MASK], " VAR(HR) ", " VAR(HR) "\n\t" \
-    "# Calc counter\n\t"                                     \
-    "# Initialization vector\n\t"                            \
-    "cmpl	$0, %%edx\n\t"                               \
-    "movq	$0, %%rcx\n\t"                               \
-    "je	45f\n\t"                                             \
-    "cmpl	$16, %%edx\n\t"                              \
-    "jl	44f\n\t"                                             \
-    "andl	$0xfffffff0, %%edx\n\t"                      \
-    "\n"                                                     \
-    "43:\n\t"                                                \
-    "vmovdqu	(%%rax,%%rcx,1), %%xmm4\n\t"                 \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"           \
-    "vpxor	%%xmm4, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX1(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "addl	$16, %%ecx\n\t"                              \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "jl	43b\n\t"                                             \
-    "movl	%[ibytes], %%edx\n\t"                        \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "je	45f\n\t"                                             \
-    "\n"                                                     \
-    "44:\n\t"                                                \
-    "subq	$16, %%rsp\n\t"                              \
-    "vpxor	%%xmm4, %%xmm4, %%xmm4\n\t"                  \
-    "xorl	%%ebx, %%ebx\n\t"                            \
-    "vmovdqu	%%xmm4, (%%rsp)\n\t"                         \
-    "42:\n\t"                                                \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t"                 \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t"                 \
-    "incl	%%ecx\n\t"                                   \
-    "incl	%%ebx\n\t"                                   \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "jl	42b\n\t"                                             \
-    "vmovdqu	(%%rsp), %%xmm4\n\t"                         \
-    "addq	$16, %%rsp\n\t"                              \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"           \
-    "vpxor	%%xmm4, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX1(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "\n"                                                     \
-    "45:\n\t"                                                \
-    "# T = Encrypt counter\n\t"                              \
-    "vpxor	%%xmm0, %%xmm0, %%xmm0\n\t"                  \
-    "shll	$3, %%edx\n\t"                               \
-    "vpinsrq	$0, %%rdx, %%xmm0, %%xmm0\n\t"               \
-    "vpxor	%%xmm0, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX1(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"         \
-    "#   Encrypt counter\n\t"                                \
-    "vmovdqa	0(%[KEY]), %%xmm4\n\t"                       \
-    "vpxor	%%xmm13, %%xmm4, %%xmm4\n\t"                 \
-    VAESENC_AVX(%%xmm4)                                      \
-    "vmovdqu	%%xmm4, " VAR(TR) "\n\t"
-
-#define CALC_AAD_AVX1()                                \
-    "# Additional authentication data\n\t"             \
-    "movl	%[abytes], %%edx\n\t"                  \
-    "cmpl	$0, %%edx\n\t"                         \
-    "je		25f\n\t"                               \
-    "movq	%[addt], %%rax\n\t"                    \
-    "xorl	%%ecx, %%ecx\n\t"                      \
-    "cmpl	$16, %%edx\n\t"                        \
-    "jl		24f\n\t"                               \
-    "andl	$0xfffffff0, %%edx\n\t"                \
-    "\n"                                               \
-    "23:\n\t"                                          \
-    "vmovdqu	(%%rax,%%rcx,1), %%xmm4\n\t"           \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"     \
-    "vpxor	%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_FULL_AVX1(XR, %%xmm12, XR, HR)               \
-    "addl	$16, %%ecx\n\t"                        \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "jl		23b\n\t"                               \
-    "movl	%[abytes], %%edx\n\t"                  \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "je		25f\n\t"                               \
-    "\n"                                               \
-    "24:\n\t"                                          \
-    "subq	$16, %%rsp\n\t"                        \
-    "vpxor	%%xmm4, %%xmm4, %%xmm4\n\t"            \
-    "xorl	%%ebx, %%ebx\n\t"                      \
-    "vmovdqu	%%xmm4, (%%rsp)\n\t"                   \
-    "22:\n\t"                                          \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t"           \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t"           \
-    "incl	%%ecx\n\t"                             \
-    "incl	%%ebx\n\t"                             \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "jl		22b\n\t"                               \
-    "vmovdqu	(%%rsp), %%xmm4\n\t"                   \
-    "addq	$16, %%rsp\n\t"                        \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"     \
-    "vpxor	%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_FULL_AVX1(XR, %%xmm12, XR, HR)               \
-    "\n"                                               \
-    "25:\n\t"
-
-#define CALC_HT_8_AVX1()                          \
-    "vmovdqa	" VAR(XR) ", %%xmm2\n\t"          \
-    "# H ^ 1\n\t"                                 \
-    "vmovdqu	" VAR(HR) ", 0(" VAR(HTR) ")\n\t" \
-    "# H ^ 2\n\t"                                 \
-    GHASH_GFSQR_RED_AVX1(%%xmm0, HR)              \
-    "vmovdqu	%%xmm0 ,  16(" VAR(HTR) ")\n\t"   \
-    "# H ^ 3\n\t"                                 \
-    GHASH_GFMUL_RED_AVX1(%%xmm1, HR, %%xmm0)      \
-    "vmovdqu	%%xmm1 ,  32(" VAR(HTR) ")\n\t"   \
-    "# H ^ 4\n\t"                                 \
-    GHASH_GFSQR_RED_AVX1(%%xmm3, %%xmm0)          \
-    "vmovdqu	%%xmm3 ,  48(" VAR(HTR) ")\n\t"   \
-    "# H ^ 5\n\t"                                 \
-    GHASH_GFMUL_RED_AVX1(%%xmm12, %%xmm0, %%xmm1) \
-    "vmovdqu	%%xmm12,  64(" VAR(HTR) ")\n\t"   \
-    "# H ^ 6\n\t"                                 \
-    GHASH_GFSQR_RED_AVX1(%%xmm12, %%xmm1)         \
-    "vmovdqu	%%xmm12,  80(" VAR(HTR) ")\n\t"   \
-    "# H ^ 7\n\t"                                 \
-    GHASH_GFMUL_RED_AVX1(%%xmm12, %%xmm1, %%xmm3) \
-    "vmovdqu	%%xmm12,  96(" VAR(HTR) ")\n\t"   \
-    "# H ^ 8\n\t"                                 \
-    GHASH_GFSQR_RED_AVX1(%%xmm12, %%xmm3)         \
-    "vmovdqu	%%xmm12, 112(" VAR(HTR) ")\n\t"
-
-#define VAESENC_128_GHASH_AVX1(src, o)               \
-    "leaq	(%[in]," VAR(KR64) ",1), %%rcx\n\t"  \
-    "leaq	(%[out]," VAR(KR64) ",1), %%rdx\n\t" \
-    /* src is either %%rcx or %%rdx */             \
-    VAESENC_CTR()                                  \
-    VAESENC_XOR()                                  \
-    VAESENC_PCLMUL_1(src,  16, (o-128), 112)       \
-    VAESENC_PCLMUL_N(src,  32, (o-112),  96)       \
-    VAESENC_PCLMUL_N(src,  48, (o- 96),  80)       \
-    VAESENC_PCLMUL_N(src,  64, (o- 80),  64)       \
-    VAESENC_PCLMUL_N(src,  80, (o- 64),  48)       \
-    VAESENC_PCLMUL_N(src,  96, (o- 48),  32)       \
-    VAESENC_PCLMUL_N(src, 112, (o- 32),  16)       \
-    VAESENC_PCLMUL_N(src, 128, (o- 16),   0)       \
-    VAESENC_PCLMUL_L(144)                          \
-    "cmpl	$11, %[nr]\n\t"                    \
-    "vmovdqa	160(%[KEY]), %%xmm12\n\t"          \
-    "jl		4f\n\t"                            \
-    VAESENC()                                      \
-    VAESENC_SET(176)                               \
-    "cmpl	$13, %[nr]\n\t"                    \
-    "vmovdqa	192(%[KEY]), %%xmm12\n\t"          \
-    "jl		4f\n\t"                            \
-    VAESENC()                                      \
-    VAESENC_SET(208)                               \
-    "vmovdqa	224(%[KEY]), %%xmm12\n\t"          \
-    "\n"                                           \
-"4:\n\t"                                           \
-    VAESENC_LAST(%%rcx, %%rdx)
-
-#define _VAESENC_AVX(r)                                  \
-    "vaesenc		16(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		32(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		48(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		64(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		80(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		96(%[KEY]), " #r ", " #r "\n\t"  \
-    "vaesenc		112(%[KEY]), " #r ", " #r "\n\t" \
-    "vaesenc		128(%[KEY]), " #r ", " #r "\n\t" \
-    "vaesenc		144(%[KEY]), " #r ", " #r "\n\t" \
-    "cmpl		$11, %[nr]\n\t"                  \
-    "vmovdqa		160(%[KEY]), %%xmm5\n\t"         \
-    "jl			%=f\n\t"                         \
-    "vaesenc		%%xmm5, " #r ", " #r "\n\t"      \
-    "vaesenc		176(%[KEY]), " #r ", " #r "\n\t" \
-    "cmpl		$13, %[nr]\n\t"                  \
-    "vmovdqa		192(%[KEY]), %%xmm5\n\t"         \
-    "jl			%=f\n\t"                         \
-    "vaesenc		%%xmm5, " #r ", " #r "\n\t"      \
-    "vaesenc		208(%[KEY]), " #r ", " #r "\n\t" \
-    "vmovdqa		224(%[KEY]), %%xmm5\n\t"         \
-    "%=:\n\t"                                            \
-    "vaesenclast	%%xmm5, " #r ", " #r "\n\t"
-#define VAESENC_AVX(r)                                   \
-        _VAESENC_AVX(r)
-
-#define AESENC_LAST15_ENC_AVX1()                        \
-    "movl	%[nbytes], %%ecx\n\t"                   \
-    "movl	%%ecx, %%edx\n\t"                       \
-    "andl	$0x0f, %%ecx\n\t"                       \
-    "jz		55f\n\t"                                \
-    "vmovdqu	" VAR(CTR1) ", %%xmm13\n\t"             \
-    "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"   \
-    "vpxor	0(%[KEY]), %%xmm13, %%xmm13\n\t"        \
-    VAESENC_AVX(%%xmm13)                                \
-    "subq	$16, %%rsp\n\t"                         \
-    "xorl	%%ecx, %%ecx\n\t"                       \
-    "vmovdqu	%%xmm13, (%%rsp)\n\t"                   \
-    "\n"                                                \
-    "51:\n\t"                                           \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"    \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"            \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t"   \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"            \
-    "incl	" VAR(KR) "\n\t"                        \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	%%edx, " VAR(KR) "\n\t"                 \
-    "jl		51b\n\t"                                \
-    "xorq	%%r13, %%r13\n\t"                       \
-    "cmpl	$16, %%ecx\n\t"                         \
-    "je		53f\n\t"                                \
-    "\n"                                                \
-    "52:\n\t"                                           \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"            \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	$16, %%ecx\n\t"                         \
-    "jl		52b\n\t"                                \
-    "53:\n\t"                                           \
-    "vmovdqu	(%%rsp), %%xmm13\n\t"                   \
-    "addq	$16, %%rsp\n\t"                         \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"    \
-    "vpxor	%%xmm13, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_GFMUL_RED_AVX1(XR, HR, XR)                    \
-
-#define AESENC_LAST15_DEC_AVX1()                        \
-    "movl	%[nbytes], %%ecx\n\t"                   \
-    "movl	%%ecx, %%edx\n\t"                       \
-    "andl	$0x0f, %%ecx\n\t"                       \
-    "jz		55f\n\t"                                \
-    "vmovdqu	" VAR(CTR1) ", %%xmm13\n\t"             \
-    "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"   \
-    "vpxor	0(%[KEY]), %%xmm13, %%xmm13\n\t"        \
-    VAESENC_AVX(%%xmm13)                                \
-    "subq	$32, %%rsp\n\t"                         \
-    "xorl	%%ecx, %%ecx\n\t"                       \
-    "vmovdqu	%%xmm13, (%%rsp)\n\t"                   \
-    "vpxor	%%xmm0, %%xmm0, %%xmm0\n\t"             \
-    "vmovdqu	%%xmm0, 16(%%rsp)\n\t"                  \
-    "\n"                                                \
-    "51:\n\t"                                           \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"    \
-    "movb	%%r13b, 16(%%rsp,%%rcx,1)\n\t"          \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"            \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t"   \
-    "incl	" VAR(KR) "\n\t"                        \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	%%edx, " VAR(KR) "\n\t"                 \
-    "jl		51b\n\t"                                \
-    "53:\n\t"                                           \
-    "vmovdqu	16(%%rsp), %%xmm13\n\t"                 \
-    "addq	$32, %%rsp\n\t"                         \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"    \
-    "vpxor	%%xmm13, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_GFMUL_RED_AVX1(XR, HR, XR)                    \
-
-#define CALC_TAG_AVX1()                                      \
-    "movl	%[nbytes], %%edx\n\t"                        \
-    "movl	%[abytes], %%ecx\n\t"                        \
-    "shlq	$3, %%rdx\n\t"                               \
-    "shlq	$3, %%rcx\n\t"                               \
-    "vpinsrq	$0, %%rdx, %%xmm0, %%xmm0\n\t"               \
-    "vpinsrq	$1, %%rcx, %%xmm0, %%xmm0\n\t"               \
-    "vpxor	%%xmm0, " VAR(XR) ", " VAR(XR) "\n\t"        \
-    GHASH_GFMUL_RED_AVX1(XR, HR, XR)                         \
-    "vpshufb	%[BSWAP_MASK], " VAR(XR) ", " VAR(XR) "\n\t" \
-    "vpxor	" VAR(TR) ", " VAR(XR) ", %%xmm0\n\t"        \
-
-#define STORE_TAG_AVX()                       \
-    "cmpl	$16, %[tbytes]\n\t"           \
-    "je		71f\n\t"                      \
-    "xorq	%%rcx, %%rcx\n\t"             \
-    "vmovdqu	%%xmm0, (%%rsp)\n\t"          \
-    "73:\n\t"                                 \
-    "movzbl	(%%rsp,%%rcx,1), %%r13d\n\t"  \
-    "movb	%%r13b, (%[tag],%%rcx,1)\n\t" \
-    "incl	%%ecx\n\t"                    \
-    "cmpl	%[tbytes], %%ecx\n\t"         \
-    "jne	73b\n\t"                      \
-    "jmp	72f\n\t"                      \
-    "\n"                                      \
-    "71:\n\t"                                 \
-    "vmovdqu	%%xmm0, (%[tag])\n\t"         \
-    "\n"                                      \
-    "72:\n\t"
-
-#define CMP_TAG_AVX()                                      \
-    "cmpl	$16, %[tbytes]\n\t"                        \
-    "je		71f\n\t"                                   \
-    "subq	$16, %%rsp\n\t"                            \
-    "xorq	%%rcx, %%rcx\n\t"                          \
-    "xorq	%%rax, %%rax\n\t"                          \
-    "vmovdqu	%%xmm0, (%%rsp)\n\t"                       \
-    "\n"                                                   \
-    "73:\n\t"                                              \
-    "movzbl	(%%rsp,%%rcx,1), %%r13d\n\t"               \
-    "xorb	(%[tag],%%rcx,1), %%r13b\n\t"              \
-    "orb	%%r13b, %%al\n\t"                          \
-    "incl	%%ecx\n\t"                                 \
-    "cmpl	%[tbytes], %%ecx\n\t"                      \
-    "jne	73b\n\t"                                   \
-    "cmpb	$0x00, %%al\n\t"                           \
-    "sete	%%al\n\t"                                  \
-    "addq	$16, %%rsp\n\t"                            \
-    "jmp	72f\n\t"                                   \
-    "\n"                                                   \
-    "71:\n\t"                                              \
-    "vmovdqu	(%[tag]), %%xmm1\n\t"                      \
-    "vpcmpeqb	%%xmm1, %%xmm0, %%xmm0\n\t"                \
-    "vpmovmskb	%%xmm0, %%edx\n\t"                         \
-    "# %%edx == 0xFFFF then return 1 else => return 0\n\t" \
-    "xorl	%%eax, %%eax\n\t"                          \
-    "cmpl	$0xffff, %%edx\n\t"                        \
-    "sete	%%al\n\t"                                  \
-    "\n"                                                   \
-    "72:\n\t"                                              \
-    "movl	%%eax, (%[res])\n\t"
-
-static void AES_GCM_encrypt_avx1(const unsigned char *in, unsigned char *out,
-                                 const unsigned char* addt,
-                                 const unsigned char* ivec, unsigned char *tag,
-                                 unsigned int nbytes, unsigned int abytes,
-                                 unsigned int ibytes, unsigned int tbytes,
-                                 const unsigned char* key, int nr)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register unsigned int ivLen asm("ebx") = ibytes;
-
-    __asm__ __volatile__ (
-        "subq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "vpxor		%%xmm13, %%xmm13, %%xmm13\n\t"
-        "vpxor		" VAR(XR) ", " VAR(XR) ", " VAR(XR) "\n\t"
-        "movl		%[ibytes], %%edx\n\t"
-        "cmpl		$12, %%edx\n\t"
-        "jne		35f\n\t"
-        CALC_IV_12_AVX1()
-        "\n"
-        "35:\n\t"
-        CALC_IV_AVX1()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD_AVX1()
-
-        "# Calculate counter and H\n\t"
-        "vpsrlq		$63, " VAR(HR) ", %%xmm5\n\t"
-        "vpsllq		$1, " VAR(HR) ", %%xmm4\n\t"
-        "vpslldq	$8, %%xmm5, %%xmm5\n\t"
-        "vpor		%%xmm5, %%xmm4, %%xmm4\n\t"
-        "vpshufd	$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpsrad		$31, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"
-        "vpand		%[MOD2_128], " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpaddd		%[ONE], %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm4, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vmovdqu	%%xmm13, " VAR(CTR1) "\n\t"
-
-        "xorl		" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-        "cmpl	$128, %[nbytes]\n\t"
-        "movl	%[nbytes], %%r13d\n\t"
-        "jl	5f\n\t"
-        "andl	$0xffffff80, %%r13d\n\t"
-
-        CALC_HT_8_AVX1()
-
-        "# First 128 bytes of input\n\t"
-        VAESENC_128()
-
-        "cmpl	$128, %%r13d\n\t"
-        "movl	$128, " VAR(KR) "\n\t"
-        "jle	2f\n\t"
-
-        "# More 128 bytes of input\n\t"
-        "\n"
-    "3:\n\t"
-        VAESENC_128_GHASH_AVX1(%%rdx, 0)
-        "addl	$128, " VAR(KR) "\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jl	3b\n\t"
-        "\n"
-    "2:\n\t"
-        "vmovdqa	%[BSWAP_MASK], %%xmm13\n\t"
-        "vpshufb	%%xmm13, %%xmm4, %%xmm4\n\t"
-        "vpshufb	%%xmm13, %%xmm5, %%xmm5\n\t"
-        "vpshufb	%%xmm13, %%xmm6, %%xmm6\n\t"
-        "vpshufb	%%xmm13, %%xmm7, %%xmm7\n\t"
-        "vpxor		%%xmm2, %%xmm4, %%xmm4\n\t"
-        "vpshufb	%%xmm13, %%xmm8, %%xmm8\n\t"
-        "vpshufb	%%xmm13, %%xmm9, %%xmm9\n\t"
-        "vpshufb	%%xmm13, %%xmm10, %%xmm10\n\t"
-        "vpshufb	%%xmm13, %%xmm11, %%xmm11\n\t"
-
-        "vmovdqu	   (" VAR(HTR) "), %%xmm12\n\t"
-        "vmovdqu	 16(" VAR(HTR) "), %%xmm14\n\t"
-        GHASH_GFMUL_AVX1(XR, %%xmm13, %%xmm11, %%xmm12)
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm10, %%xmm14)
-        "vmovdqu	 32(" VAR(HTR) "), %%xmm12\n\t"
-        "vmovdqu	 48(" VAR(HTR) "), %%xmm14\n\t"
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm9, %%xmm12)
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm8, %%xmm14)
-        "vmovdqu	 64(" VAR(HTR) "), %%xmm12\n\t"
-        "vmovdqu	 80(" VAR(HTR) "), %%xmm14\n\t"
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm7, %%xmm12)
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm6, %%xmm14)
-        "vmovdqu	 96(" VAR(HTR) "), %%xmm12\n\t"
-        "vmovdqu	112(" VAR(HTR) "), %%xmm14\n\t"
-        GHASH_GFMUL_XOR_AVX1(XR, %%xmm13, %%xmm5, %%xmm12)
-        GHASH_GFMUL_RED_XOR_AVX1(XR, %%xmm13, %%xmm4, %%xmm14)
-
-        "vmovdqu	0(" VAR(HTR) "), " VAR(HR) "\n\t"
-        "\n"
-    "5:\n\t"
-        "movl		%[nbytes], %%edx\n\t"
-        "cmpl		%%edx, " VAR(KR) "\n\t"
-        "jge		55f\n\t"
-#endif
-
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xfffffff0, %%r13d\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		14f\n\t"
-
-        VAESENC_BLOCK()
-        "addl		$16, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		13f\n\t"
-        "\n"
-        "12:\n\t"
-        "vmovdqu	(%[in]," VAR(KR64) ",1), %%xmm9\n\t"
-        VAESENC_GFMUL(%%xmm9, HR, XR)
-        "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"
-        "addl		$16, " VAR(KR) "\n\t"
-        "vpxor		%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		12b\n\t"
-        "\n"
-        "13:\n\t"
-        GHASH_GFMUL_RED_AVX1(XR, HR, XR)
-        "\n"
-        "14:\n\t"
-
-        AESENC_LAST15_ENC_AVX1()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG_AVX1()
-        STORE_TAG_AVX()
-        "addq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        "vzeroupper\n\t"
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tbytes),
-          [tag] "r" (tag),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "rdx", "r13"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Encrypt and carry-less multiply for AVX2. */
-#define VAESENC_PCLMUL_AVX2_1(src, o1, o2, o3)        \
-    "vmovdqu	" #o2 "(" #src "), %%xmm12\n\t"       \
-    "vmovdqa	" #o1 "(%[KEY]), %%xmm0\n\t"          \
-    "vpshufb	%[BSWAP_MASK], %%xmm12, %%xmm12\n\t"  \
-    "vmovdqu	" #o3 "(" VAR(HTR) "), %%xmm13\n\t"   \
-    "vpxor	%%xmm2, %%xmm12, %%xmm12\n\t"         \
-    "vpclmulqdq	$0x10, %%xmm13, %%xmm12, %%xmm1\n\t"  \
-    "vpclmulqdq	$0x01, %%xmm13, %%xmm12, %%xmm14\n\t" \
-    "vpclmulqdq	$0x00, %%xmm13, %%xmm12, %%xmm2\n\t"  \
-    "vpclmulqdq	$0x11, %%xmm13, %%xmm12, %%xmm3\n\t"  \
-    "vaesenc	%%xmm0, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc	%%xmm0, %%xmm5, %%xmm5\n\t"           \
-    "vaesenc	%%xmm0, %%xmm6, %%xmm6\n\t"           \
-    "vaesenc	%%xmm0, %%xmm7, %%xmm7\n\t"           \
-    "vaesenc	%%xmm0, %%xmm8, %%xmm8\n\t"           \
-    "vaesenc	%%xmm0, %%xmm9, %%xmm9\n\t"           \
-    "vaesenc	%%xmm0, %%xmm10, %%xmm10\n\t"         \
-    "vaesenc	%%xmm0, %%xmm11, %%xmm11\n\t"         \
-
-#define VAESENC_PCLMUL_AVX2_2(src, o1, o2, o3)        \
-    "vmovdqu	" #o2 "(" #src "), %%xmm12\n\t"       \
-    "vmovdqu	" #o3 "(" VAR(HTR) "), %%xmm0\n\t"    \
-    "vpshufb	%[BSWAP_MASK], %%xmm12, %%xmm12\n\t"  \
-    "vpxor	%%xmm14, %%xmm1, %%xmm1\n\t"          \
-    "vpclmulqdq	$0x10, %%xmm0, %%xmm12, %%xmm13\n\t"  \
-    "vpclmulqdq	$0x01, %%xmm0, %%xmm12, %%xmm14\n\t"  \
-    "vpclmulqdq	$0x00, %%xmm0, %%xmm12, %%xmm15\n\t"  \
-    "vpclmulqdq	$0x11, %%xmm0, %%xmm12, %%xmm12\n\t"  \
-    "vmovdqa	" #o1 "(%[KEY]), %%xmm0\n\t"          \
-    "vpxor	%%xmm13, %%xmm1, %%xmm1\n\t"          \
-    "vpxor	%%xmm12, %%xmm3, %%xmm3\n\t"          \
-    "vaesenc	%%xmm0, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc	%%xmm0, %%xmm5, %%xmm5\n\t"           \
-    "vaesenc	%%xmm0, %%xmm6, %%xmm6\n\t"           \
-    "vaesenc	%%xmm0, %%xmm7, %%xmm7\n\t"           \
-    "vaesenc	%%xmm0, %%xmm8, %%xmm8\n\t"           \
-    "vaesenc	%%xmm0, %%xmm9, %%xmm9\n\t"           \
-    "vaesenc	%%xmm0, %%xmm10, %%xmm10\n\t"         \
-    "vaesenc	%%xmm0, %%xmm11, %%xmm11\n\t"         \
-
-#define VAESENC_PCLMUL_AVX2_N(src, o1, o2, o3)        \
-    "vmovdqu	" #o2 "(" #src "), %%xmm12\n\t"       \
-    "vmovdqu	" #o3 "(" VAR(HTR) "), %%xmm0\n\t"    \
-    "vpshufb	%[BSWAP_MASK], %%xmm12, %%xmm12\n\t"  \
-    "vpxor	%%xmm14, %%xmm1, %%xmm1\n\t"          \
-    "vpxor	%%xmm15, %%xmm2, %%xmm2\n\t"          \
-    "vpclmulqdq	$0x10, %%xmm0, %%xmm12, %%xmm13\n\t"  \
-    "vpclmulqdq	$0x01, %%xmm0, %%xmm12, %%xmm14\n\t"  \
-    "vpclmulqdq	$0x00, %%xmm0, %%xmm12, %%xmm15\n\t"  \
-    "vpclmulqdq	$0x11, %%xmm0, %%xmm12, %%xmm12\n\t"  \
-    "vmovdqa	" #o1 "(%[KEY]), %%xmm0\n\t"          \
-    "vpxor	%%xmm13, %%xmm1, %%xmm1\n\t"          \
-    "vpxor	%%xmm12, %%xmm3, %%xmm3\n\t"          \
-    "vaesenc	%%xmm0, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc	%%xmm0, %%xmm5, %%xmm5\n\t"           \
-    "vaesenc	%%xmm0, %%xmm6, %%xmm6\n\t"           \
-    "vaesenc	%%xmm0, %%xmm7, %%xmm7\n\t"           \
-    "vaesenc	%%xmm0, %%xmm8, %%xmm8\n\t"           \
-    "vaesenc	%%xmm0, %%xmm9, %%xmm9\n\t"           \
-    "vaesenc	%%xmm0, %%xmm10, %%xmm10\n\t"         \
-    "vaesenc	%%xmm0, %%xmm11, %%xmm11\n\t"         \
-
-#define VAESENC_PCLMUL_AVX2_L(o)                      \
-    "vpxor	%%xmm14, %%xmm1, %%xmm1\n\t"          \
-    "vpxor	%%xmm15, %%xmm2, %%xmm2\n\t"          \
-    "vpslldq	$8, %%xmm1, %%xmm12\n\t"              \
-    "vpsrldq	$8, %%xmm1, %%xmm1\n\t"               \
-    "vmovdqa	"#o"(%[KEY]), %%xmm15\n\t"            \
-    "vmovdqa	%[MOD2_128], %%xmm0\n\t"              \
-    "vaesenc	%%xmm15, %%xmm4, %%xmm4\n\t"          \
-    "vpxor	%%xmm12, %%xmm2, %%xmm2\n\t"          \
-    "vpxor	%%xmm1, %%xmm3, %%xmm3\n\t"           \
-    "vpclmulqdq	$0x10, %%xmm0, %%xmm2, %%xmm14\n\t"   \
-    "vaesenc	%%xmm15, %%xmm5, %%xmm5\n\t"          \
-    "vaesenc	%%xmm15, %%xmm6, %%xmm6\n\t"          \
-    "vaesenc	%%xmm15, %%xmm7, %%xmm7\n\t"          \
-    "vpshufd	$0x4e, %%xmm2, %%xmm2\n\t"            \
-    "vpxor	%%xmm14, %%xmm2, %%xmm2\n\t"          \
-    "vpclmulqdq	$0x10, %%xmm0, %%xmm2, %%xmm14\n\t"   \
-    "vaesenc	%%xmm15, %%xmm8, %%xmm8\n\t"          \
-    "vaesenc	%%xmm15, %%xmm9, %%xmm9\n\t"          \
-    "vaesenc	%%xmm15, %%xmm10, %%xmm10\n\t"        \
-    "vpshufd	$0x4e, %%xmm2, %%xmm2\n\t"            \
-    "vpxor	%%xmm14, %%xmm2, %%xmm2\n\t"          \
-    "vpxor	%%xmm3, %%xmm2, %%xmm2\n\t"           \
-    "vaesenc	%%xmm15, %%xmm11, %%xmm11\n\t"
-
-#define VAESENC_BLOCK_AVX2()                                  \
-    "vmovdqu		" VAR(CTR1) ", %%xmm5\n\t"            \
-    "vpshufb		%[BSWAP_EPI64], %%xmm5, %%xmm4\n\t"   \
-    "vpaddd		%[ONE], %%xmm5, %%xmm5\n\t"           \
-    "vmovdqu		%%xmm5, " VAR(CTR1) "\n\t"            \
-    "vpxor		   (%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 16(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 32(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 48(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 64(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 80(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		 96(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		112(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		128(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vaesenc		144(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "cmpl		$11, %[nr]\n\t"                       \
-    "vmovdqa		160(%[KEY]), %%xmm5\n\t"              \
-    "jl			%=f\n\t"                              \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		176(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "cmpl		$13, %[nr]\n\t"                       \
-    "vmovdqa		192(%[KEY]), %%xmm5\n\t"              \
-    "jl			%=f\n\t"                              \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vaesenc		208(%[KEY]), %%xmm4, %%xmm4\n\t"      \
-    "vmovdqa		224(%[KEY]), %%xmm5\n\t"              \
-    "%=:\n\t"                                                 \
-    "vaesenclast	%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		(%[in]," VAR(KR64) ",1), %%xmm5\n\t"  \
-    "vpxor		%%xmm5, %%xmm4, %%xmm4\n\t"           \
-    "vmovdqu		%%xmm4, (%[out]," VAR(KR64) ",1)\n\t" \
-    "vpshufb		%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"    \
-    "vpxor		%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"
-
-/* Karatsuba multiplication - slower
- * H01 = H[1] ^ H[0] (top and bottom 64-bits XORed)
- */
-#define _VAESENC_GFMUL_AVX2(in, H, X, ctr1, H01)            \
-    "vpxor		   (%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 16(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 32(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 48(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 64(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 80(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 96(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		112(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		128(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		144(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "cmpl		$11, %[nr]\n\t"                     \
-    "vmovdqa		160(%[KEY]), %%xmm5\n\t"            \
-    "jl			%=f\n\t"                            \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"         \
-    "vaesenc		176(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "cmpl		$13, %[nr]\n\t"                     \
-    "vmovdqa		192(%[KEY]), %%xmm5\n\t"            \
-    "jl			%=f\n\t"                            \
-    "vaesenc		%%xmm5, %%xmm4, %%xmm4\n\t"         \
-    "vaesenc		208(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vmovdqa		224(%[KEY]), %%xmm5\n\t"            \
-    "%=:\n\t"                                               \
-    "vaesenclast	%%xmm5, %%xmm4, %%xmm4\n\t"         \
-    "vmovdqu		" #in ", %%xmm0\n\t"                \
-    "vpxor		%%xmm0, %%xmm4, %%xmm4\n\t"         \
-                                                            \
-    "vpsrldq	$8, " #X ", %%xmm2\n\t"                     \
-    "vpxor	" #X ", %%xmm2, %%xmm2\n\t"                 \
-    "vpclmulqdq	$0x00, " #H ", " #X ", %%xmm5\n\t"          \
-    "vpclmulqdq	$0x11, " #H ", " #X ", %%xmm8\n\t"          \
-    "vpclmulqdq	$0x00, "#H01", %%xmm2, %%xmm7\n\t"          \
-    "vpxor	%%xmm5, %%xmm7, %%xmm7\n\t"                 \
-    "vpxor	%%xmm8, %%xmm7, %%xmm7\n\t"                 \
-    "vpslldq	$8, %%xmm7, %%xmm6\n\t"                     \
-    "vpsrldq	$8, %%xmm7, %%xmm7\n\t"                     \
-    "vpxor	%%xmm7, %%xmm8, %%xmm8\n\t"                 \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"                 \
-                                                            \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t"     \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"                  \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"                 \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t"     \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"                  \
-    "vpxor	%%xmm8, %%xmm6, %%xmm6\n\t"                 \
-    "vpxor	%%xmm5, %%xmm6, " VAR(XR) "\n\t"
-#define VAESENC_GFMUL_AVX2(in, H, X, ctr1)                  \
-       _VAESENC_GFMUL_AVX2(in, H, X, ctr1)
-
-#define _VAESENC_GFMUL_SB_AVX2(in, H, X, ctr1)              \
-    "vpclmulqdq	$0x10, " #H ", " #X ", %%xmm7\n\t"          \
-    "vpclmulqdq	$0x01, " #H ", " #X ", %%xmm6\n\t"          \
-    "vpclmulqdq	$0x00, " #H ", " #X ", %%xmm5\n\t"          \
-    "vpclmulqdq	$0x11, " #H ", " #X ", %%xmm8\n\t"          \
-    "vpxor		   (%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 16(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpxor	%%xmm6, %%xmm7, %%xmm7\n\t"                 \
-    "vpslldq	$8, %%xmm7, %%xmm6\n\t"                     \
-    "vpsrldq	$8, %%xmm7, %%xmm7\n\t"                     \
-    "vaesenc		 32(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"                 \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t"     \
-    "vaesenc		 48(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 64(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		 80(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"                  \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"                 \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t"     \
-    "vaesenc		 96(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		112(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vaesenc		128(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"                  \
-    "vaesenc		144(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vpxor	%%xmm7, %%xmm8, %%xmm8\n\t"                 \
-    "vpxor	%%xmm8, %%xmm6, %%xmm6\n\t"                 \
-    "cmpl		$11, %[nr]\n\t"                     \
-    "vmovdqa		160(%[KEY]), %%xmm3\n\t"            \
-    "jl			%=f\n\t"                            \
-    "vaesenc		%%xmm3, %%xmm4, %%xmm4\n\t"         \
-    "vaesenc		176(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "cmpl		$13, %[nr]\n\t"                     \
-    "vmovdqa		192(%[KEY]), %%xmm3\n\t"            \
-    "jl			%=f\n\t"                            \
-    "vaesenc		%%xmm3, %%xmm4, %%xmm4\n\t"         \
-    "vaesenc		208(%[KEY]), %%xmm4, %%xmm4\n\t"    \
-    "vmovdqa		224(%[KEY]), %%xmm3\n\t"            \
-    "%=:\n\t"                                               \
-    "vaesenclast	%%xmm3, %%xmm4, %%xmm4\n\t"         \
-    "vpxor	%%xmm5, %%xmm6, " VAR(XR) "\n\t"            \
-    "vmovdqu		" #in ", %%xmm5\n\t"                \
-    "vpxor		%%xmm5, %%xmm4, %%xmm4\n\t"
-#define VAESENC_GFMUL_SB_AVX2(in, H, X, ctr1)               \
-       _VAESENC_GFMUL_SB_AVX2(in, H, X, ctr1)
-
-
-#define _GHASH_GFMUL_AVX2(r, r2, a, b)         \
-    "vpclmulqdq	$0x10, "#a", "#b", %%xmm2\n\t" \
-    "vpclmulqdq	$0x01, "#a", "#b", %%xmm1\n\t" \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm0\n\t" \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm3\n\t" \
-    "vpxor	%%xmm1, %%xmm2, %%xmm2\n\t"    \
-    "vpslldq	$8, %%xmm2, %%xmm1\n\t"        \
-    "vpsrldq	$8, %%xmm2, %%xmm2\n\t"        \
-    "vpxor	%%xmm1, %%xmm0, "#r2"\n\t"     \
-    "vpxor	%%xmm2, %%xmm3, " #r "\n\t"
-#define GHASH_GFMUL_AVX2(r, r2, a, b)          \
-       _GHASH_GFMUL_AVX2(r, r2, a, b)
-
-#define GHASH_MID_AVX2(r, r2)               \
-    "vpsrld	$31, "#r2", %%xmm0\n\t"     \
-    "vpsrld	$31, " #r ", %%xmm1\n\t"    \
-    "vpslld	$1, "#r2", "#r2"\n\t"       \
-    "vpslld	$1, " #r ", " #r "\n\t"     \
-    "vpsrldq	$12, %%xmm0, %%xmm2\n\t"    \
-    "vpslldq	$4, %%xmm0, %%xmm0\n\t"     \
-    "vpslldq	$4, %%xmm1, %%xmm1\n\t"     \
-    "vpor	%%xmm2, " #r ", " #r "\n\t" \
-    "vpor	%%xmm0, "#r2", "#r2"\n\t"   \
-    "vpor	%%xmm1, " #r ", " #r "\n\t"
-
-#define _GHASH_GFMUL_RED_AVX2(r, a, b)                  \
-    "vpclmulqdq	$0x10, "#a", "#b", %%xmm7\n\t"          \
-    "vpclmulqdq	$0x01, "#a", "#b", %%xmm6\n\t"          \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm5\n\t"          \
-    "vpxor	%%xmm6, %%xmm7, %%xmm7\n\t"             \
-    "vpslldq	$8, %%xmm7, %%xmm6\n\t"                 \
-    "vpsrldq	$8, %%xmm7, %%xmm7\n\t"                 \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"             \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm8\n\t"          \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t" \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"             \
-    "vpclmulqdq	$0x10, %[MOD2_128], %%xmm6, %%xmm5\n\t" \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm7, %%xmm8, %%xmm8\n\t"             \
-    "vpxor	%%xmm8, %%xmm6, %%xmm6\n\t"             \
-    "vpxor	%%xmm5, %%xmm6, " #r "\n\t"
-#define GHASH_GFMUL_RED_AVX2(r, a, b)                   \
-       _GHASH_GFMUL_RED_AVX2(r, a, b)
-
-#define _GHASH_GFSQR_RED2_AVX2(r, a, mod128)            \
-    "vpclmulqdq	$0x00, "#a", "#a", %%xmm6\n\t"          \
-    "vpclmulqdq	$0x11, "#a", "#a", %%xmm8\n\t"          \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm6, %%xmm5\n\t"   \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"             \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm6, %%xmm5\n\t"   \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"             \
-    "vpxor	%%xmm6, %%xmm8, " #r "\n\t"
-#define GHASH_GFSQR_RED2_AVX2(r, a, mod128)             \
-       _GHASH_GFSQR_RED2_AVX2(r, a, mod128)
-
-#define _GHASH_GFMUL_SQR_RED2_AVX2(rm, rs, a, b, mod128) \
-    "vpclmulqdq	$0x10, "#a", "#b", %%xmm7\n\t"           \
-    "vpclmulqdq	$0x01, "#a", "#b", %%xmm6\n\t"           \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm5\n\t"           \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm8\n\t"           \
-    "vpclmulqdq	$0x00, "#b", "#b", %%xmm9\n\t"           \
-    "vpclmulqdq	$0x11, "#b", "#b", %%xmm10\n\t"          \
-    "vpxor	%%xmm6, %%xmm7, %%xmm7\n\t"              \
-    "vpslldq	$8, %%xmm7, %%xmm6\n\t"                  \
-    "vpsrldq	$8, %%xmm7, %%xmm7\n\t"                  \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"              \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm9, %%xmm4\n\t"    \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm6, %%xmm5\n\t"    \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"               \
-    "vpshufd	$0x4e, %%xmm9, %%xmm9\n\t"               \
-    "vpxor	%%xmm5, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm4, %%xmm9, %%xmm9\n\t"              \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm6, %%xmm5\n\t"    \
-    "vpclmulqdq	$0x10, "#mod128", %%xmm9, %%xmm4\n\t"    \
-    "vpshufd	$0x4e, %%xmm6, %%xmm6\n\t"               \
-    "vpshufd	$0x4e, %%xmm9, %%xmm9\n\t"               \
-    "vpxor	%%xmm7, %%xmm8, %%xmm8\n\t"              \
-    "vpxor	%%xmm4, %%xmm9, %%xmm9\n\t"              \
-    "vpxor	%%xmm8, %%xmm6, %%xmm6\n\t"              \
-    "vpxor	%%xmm10, %%xmm9, "#rs"\n\t"              \
-    "vpxor	%%xmm5, %%xmm6, "#rm"\n\t"
-#define GHASH_GFMUL_SQR_RED2_AVX2(rm, rs, a, b, mod128)  \
-       _GHASH_GFMUL_SQR_RED2_AVX2(rm, rs, a, b, mod128)
-
-#define CALC_HT_8_AVX2()                                                \
-    "vmovdqa	%[MOD2_128], %%xmm11\n\t"                               \
-    "vmovdqa	" VAR(XR) ", %%xmm2\n\t"                                \
-    "# H ^ 1 and H ^ 2\n\t"                                             \
-    GHASH_GFSQR_RED2_AVX2(%%xmm0, HR, %%xmm11)                          \
-    "vmovdqu	" VAR(HR) ", 0(" VAR(HTR) ")\n\t"                       \
-    "vmovdqu	%%xmm0 ,  16(" VAR(HTR) ")\n\t"                         \
-    "# H ^ 3 and H ^ 4\n\t"                                             \
-    GHASH_GFMUL_SQR_RED2_AVX2(%%xmm1, %%xmm3, HR, %%xmm0, %%xmm11)      \
-    "vmovdqu	%%xmm1 ,  32(" VAR(HTR) ")\n\t"                         \
-    "vmovdqu	%%xmm3 ,  48(" VAR(HTR) ")\n\t"                         \
-    "# H ^ 5 and H ^ 6\n\t"                                             \
-    GHASH_GFMUL_SQR_RED2_AVX2(%%xmm12, %%xmm0, %%xmm0, %%xmm1, %%xmm11) \
-    "vmovdqu	%%xmm12,  64(" VAR(HTR) ")\n\t"                         \
-    "vmovdqu	%%xmm0 ,  80(" VAR(HTR) ")\n\t"                         \
-    "# H ^ 7 and H ^ 8\n\t"                                             \
-    GHASH_GFMUL_SQR_RED2_AVX2(%%xmm12, %%xmm0, %%xmm1, %%xmm3, %%xmm11) \
-    "vmovdqu	%%xmm12,  96(" VAR(HTR) ")\n\t"                         \
-    "vmovdqu	%%xmm0 , 112(" VAR(HTR) ")\n\t"
-
-#define _GHASH_RED_AVX2(r, r2)                     \
-    "vmovdqa	%[MOD2_128], %%xmm2\n\t"           \
-    "vpclmulqdq	$0x10, %%xmm2, "#r2", %%xmm0\n\t"  \
-    "vpshufd	$0x4e, "#r2", %%xmm1\n\t"          \
-    "vpxor	%%xmm0, %%xmm1, %%xmm1\n\t"        \
-    "vpclmulqdq	$0x10, %%xmm2, %%xmm1, %%xmm0\n\t" \
-    "vpshufd	$0x4e, %%xmm1, %%xmm1\n\t"         \
-    "vpxor	%%xmm0, %%xmm1, %%xmm1\n\t"        \
-    "vpxor	%%xmm1, " #r ", " #r "\n\t"
-#define GHASH_RED_AVX2(r, r2)                      \
-       _GHASH_RED_AVX2(r, r2)
-
-#define GHASH_FULL_AVX2(r, r2, a, b) \
-    GHASH_GFMUL_AVX2(r, r2, a, b)    \
-    GHASH_MID_AVX2(r, r2)            \
-    GHASH_RED_AVX2(r, r2)
-
-#define _GFMUL_3V_AVX2(r, r2, r3, a, b)        \
-    "vpclmulqdq	$0x10, "#a", "#b", "#r3"\n\t"  \
-    "vpclmulqdq	$0x01, "#a", "#b", %%xmm1\n\t" \
-    "vpclmulqdq	$0x00, "#a", "#b", "#r2"\n\t"  \
-    "vpclmulqdq	$0x11, "#a", "#b", " #r "\n\t" \
-    "vpxor	%%xmm1, "#r3", "#r3"\n\t"
-#define GFMUL_3V_AVX2(r, r2, r3, a, b)         \
-       _GFMUL_3V_AVX2(r, r2, r3, a, b)
-
-#define _GFMUL_XOR_3V_AVX2(r, r2, r3, a, b)    \
-    "vpclmulqdq	$0x10, "#a", "#b", %%xmm2\n\t" \
-    "vpclmulqdq	$0x01, "#a", "#b", %%xmm1\n\t" \
-    "vpclmulqdq	$0x00, "#a", "#b", %%xmm0\n\t" \
-    "vpclmulqdq	$0x11, "#a", "#b", %%xmm3\n\t" \
-    "vpxor	%%xmm1, %%xmm2, %%xmm2\n\t"    \
-    "vpxor	%%xmm3, " #r ", " #r "\n\t"    \
-    "vpxor	%%xmm2, "#r3", "#r3"\n\t"      \
-    "vpxor	%%xmm0, "#r2", "#r2"\n\t"
-#define GFMUL_XOR_3V_AVX2(r, r2, r3, a, b)     \
-       _GFMUL_XOR_3V_AVX2(r, r2, r3, a, b)
-
-#define GHASH_GFMUL_RED_8_AVX2()                              \
-    "vmovdqu	   (" VAR(HTR) "), %%xmm12\n\t"               \
-    GFMUL_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm11, %%xmm12)     \
-    "vmovdqu	 16(" VAR(HTR) "), %%xmm12\n\t"               \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm10, %%xmm12) \
-    "vmovdqu	 32(" VAR(HTR) "), %%xmm11\n\t"               \
-    "vmovdqu	 48(" VAR(HTR) "), %%xmm12\n\t"               \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm9, %%xmm11)  \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm8, %%xmm12)  \
-    "vmovdqu	 64(" VAR(HTR) "), %%xmm11\n\t"               \
-    "vmovdqu	 80(" VAR(HTR) "), %%xmm12\n\t"               \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm7, %%xmm11)  \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm6, %%xmm12)  \
-    "vmovdqu	 96(" VAR(HTR) "), %%xmm11\n\t"               \
-    "vmovdqu	112(" VAR(HTR) "), %%xmm12\n\t"               \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm5, %%xmm11)  \
-    GFMUL_XOR_3V_AVX2(XR, %%xmm13, %%xmm14, %%xmm4, %%xmm12)  \
-    "vpslldq	$8, %%xmm14, %%xmm12\n\t"                     \
-    "vpsrldq	$8, %%xmm14, %%xmm14\n\t"                     \
-    "vpxor	%%xmm12, %%xmm13, %%xmm13\n\t"                \
-    "vpxor	%%xmm14, " VAR(XR) ", " VAR(XR) "\n\t"        \
-    GHASH_RED_AVX2(XR, %%xmm13)
-
-#define CALC_IV_12_AVX2()                                            \
-    "# Calculate values when IV is 12 bytes\n\t"                     \
-    "# Set counter based on IV\n\t"                                  \
-    "movl		$0x01000000, %%ecx\n\t"                      \
-    "vpinsrq		$0, 0(%%rax), %%xmm13, %%xmm13\n\t"          \
-    "vpinsrd		$2, 8(%%rax), %%xmm13, %%xmm13\n\t"          \
-    "vpinsrd		$3, %%ecx, %%xmm13, %%xmm13\n\t"             \
-    "# H = Encrypt X(=0) and T = Encrypt counter\n\t"                \
-    "vmovdqa		  0(%[KEY]), " VAR(HR) "\n\t"                \
-    "vmovdqa		 16(%[KEY]), %%xmm12\n\t"                    \
-    "vpxor		" VAR(HR) ", %%xmm13, %%xmm1\n\t"            \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 32(%[KEY]), %%xmm0\n\t"                     \
-    "vmovdqa		 48(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 64(%[KEY]), %%xmm0\n\t"                     \
-    "vmovdqa		 80(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		 96(%[KEY]), %%xmm0\n\t"                     \
-    "vmovdqa		112(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqa		128(%[KEY]), %%xmm0\n\t"                     \
-    "vmovdqa		144(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "cmpl		$11, %[nr]\n\t"                              \
-    "vmovdqa		160(%[KEY]), %%xmm0\n\t"                     \
-    "jl	31f\n\t"                                                     \
-    "vmovdqa		176(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "cmpl		$13, %[nr]\n\t"                              \
-    "vmovdqa		192(%[KEY]), %%xmm0\n\t"                     \
-    "jl	31f\n\t"                                                     \
-    "vmovdqa		208(%[KEY]), %%xmm12\n\t"                    \
-    "vaesenc		%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenc		%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vaesenc		%%xmm12, " VAR(HR) ", " VAR(HR) "\n\t"       \
-    "vaesenc		%%xmm12, %%xmm1, %%xmm1\n\t"                 \
-    "vmovdqu		224(%[KEY]), %%xmm0\n\t"                     \
-    "31:\n\t"                                                        \
-    "vaesenclast	%%xmm0, " VAR(HR) ", " VAR(HR) "\n\t"        \
-    "vaesenclast	%%xmm0, %%xmm1, %%xmm1\n\t"                  \
-    "vpshufb		%[BSWAP_MASK], " VAR(HR) ", " VAR(HR) "\n\t" \
-    "vmovdqu		%%xmm1, " VAR(TR) "\n\t"                     \
-
-#define CALC_IV_AVX2()                                       \
-    "# Calculate values when IV is not 12 bytes\n\t"         \
-    "# H = Encrypt X(=0)\n\t"                                \
-    "vmovdqa	0(%[KEY]), " VAR(HR) "\n\t"                  \
-    VAESENC_AVX(HR)                                          \
-    "vpshufb	%[BSWAP_MASK], " VAR(HR) ", " VAR(HR) "\n\t" \
-    "# Calc counter\n\t"                                     \
-    "# Initialization vector\n\t"                            \
-    "cmpl	$0, %%edx\n\t"                               \
-    "movq	$0, %%rcx\n\t"                               \
-    "je	45f\n\t"                                             \
-    "cmpl	$16, %%edx\n\t"                              \
-    "jl	44f\n\t"                                             \
-    "andl	$0xfffffff0, %%edx\n\t"                      \
-    "\n"                                                     \
-    "43:\n\t"                                                \
-    "vmovdqu	(%%rax,%%rcx,1), %%xmm4\n\t"                 \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"           \
-    "vpxor	%%xmm4, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX2(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "addl	$16, %%ecx\n\t"                              \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "jl	43b\n\t"                                             \
-    "movl	%[ibytes], %%edx\n\t"                        \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "je	45f\n\t"                                             \
-    "\n"                                                     \
-    "44:\n\t"                                                \
-    "subq	$16, %%rsp\n\t"                              \
-    "vpxor	%%xmm4, %%xmm4, %%xmm4\n\t"                  \
-    "xorl	%%ebx, %%ebx\n\t"                            \
-    "vmovdqu	%%xmm4, (%%rsp)\n\t"                         \
-    "42:\n\t"                                                \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t"                 \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t"                 \
-    "incl	%%ecx\n\t"                                   \
-    "incl	%%ebx\n\t"                                   \
-    "cmpl	%%edx, %%ecx\n\t"                            \
-    "jl	42b\n\t"                                             \
-    "vmovdqu	(%%rsp), %%xmm4\n\t"                         \
-    "addq	$16, %%rsp\n\t"                              \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"           \
-    "vpxor	%%xmm4, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX2(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "\n"                                                     \
-    "45:\n\t"                                                \
-    "# T = Encrypt counter\n\t"                              \
-    "vpxor	%%xmm0, %%xmm0, %%xmm0\n\t"                  \
-    "shll	$3, %%edx\n\t"                               \
-    "vpinsrq	$0, %%rdx, %%xmm0, %%xmm0\n\t"               \
-    "vpxor	%%xmm0, %%xmm13, %%xmm13\n\t"                \
-    GHASH_FULL_AVX2(%%xmm13, %%xmm12, %%xmm13, HR)           \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"         \
-    "#   Encrypt counter\n\t"                                \
-    "vmovdqa	0(%[KEY]), %%xmm4\n\t"                       \
-    "vpxor	%%xmm13, %%xmm4, %%xmm4\n\t"                 \
-    VAESENC_AVX(%%xmm4)                                      \
-    "vmovdqu	%%xmm4, " VAR(TR) "\n\t"
-
-#define CALC_AAD_AVX2()                                \
-    "# Additional authentication data\n\t"             \
-    "movl	%[abytes], %%edx\n\t"                  \
-    "cmpl	$0, %%edx\n\t"                         \
-    "je		25f\n\t"                               \
-    "movq	%[addt], %%rax\n\t"                    \
-    "xorl	%%ecx, %%ecx\n\t"                      \
-    "cmpl	$16, %%edx\n\t"                        \
-    "jl		24f\n\t"                               \
-    "andl	$0xfffffff0, %%edx\n\t"                \
-    "\n"                                               \
-    "23:\n\t"                                          \
-    "vmovdqu	(%%rax,%%rcx,1), %%xmm4\n\t"           \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"     \
-    "vpxor	%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_FULL_AVX2(XR, %%xmm12, XR, HR)               \
-    "addl	$16, %%ecx\n\t"                        \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "jl		23b\n\t"                               \
-    "movl	%[abytes], %%edx\n\t"                  \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "je		25f\n\t"                               \
-    "\n"                                               \
-    "24:\n\t"                                          \
-    "subq	$16, %%rsp\n\t"                        \
-    "vpxor	%%xmm4, %%xmm4, %%xmm4\n\t"            \
-    "xorl	%%ebx, %%ebx\n\t"                      \
-    "vmovdqu	%%xmm4, (%%rsp)\n\t"                   \
-    "22:\n\t"                                          \
-    "movzbl	(%%rax,%%rcx,1), %%r13d\n\t"           \
-    "movb	%%r13b, (%%rsp,%%rbx,1)\n\t"           \
-    "incl	%%ecx\n\t"                             \
-    "incl	%%ebx\n\t"                             \
-    "cmpl	%%edx, %%ecx\n\t"                      \
-    "jl		22b\n\t"                               \
-    "vmovdqu	(%%rsp), %%xmm4\n\t"                   \
-    "addq	$16, %%rsp\n\t"                        \
-    "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"     \
-    "vpxor	%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_FULL_AVX2(XR, %%xmm12, XR, HR)               \
-    "\n"                                               \
-    "25:\n\t"
-
-#define VAESENC_128_GHASH_AVX2(src, o)               \
-    "leaq	(%[in]," VAR(KR64) ",1), %%rcx\n\t"  \
-    "leaq	(%[out]," VAR(KR64) ",1), %%rdx\n\t" \
-    /* src is either %%rcx or %%rdx */             \
-    VAESENC_CTR()                                  \
-    VAESENC_XOR()                                  \
-    VAESENC_PCLMUL_AVX2_1(src,  16, (o-128), 112)  \
-    VAESENC_PCLMUL_AVX2_2(src,  32, (o-112),  96)  \
-    VAESENC_PCLMUL_AVX2_N(src,  48, (o- 96),  80)  \
-    VAESENC_PCLMUL_AVX2_N(src,  64, (o- 80),  64)  \
-    VAESENC_PCLMUL_AVX2_N(src,  80, (o- 64),  48)  \
-    VAESENC_PCLMUL_AVX2_N(src,  96, (o- 48),  32)  \
-    VAESENC_PCLMUL_AVX2_N(src, 112, (o- 32),  16)  \
-    VAESENC_PCLMUL_AVX2_N(src, 128, (o- 16),   0)  \
-    VAESENC_PCLMUL_AVX2_L(144)                     \
-    "cmpl	$11, %[nr]\n\t"                    \
-    "vmovdqa	160(%[KEY]), %%xmm12\n\t"          \
-    "jl		4f\n\t"                            \
-    VAESENC()                                      \
-    VAESENC_SET(176)                               \
-    "cmpl	$13, %[nr]\n\t"                    \
-    "vmovdqa	192(%[KEY]), %%xmm12\n\t"          \
-    "jl		4f\n\t"                            \
-    VAESENC()                                      \
-    VAESENC_SET(208)                               \
-    "vmovdqa	224(%[KEY]), %%xmm12\n\t"          \
-    "\n"                                           \
-"4:\n\t"                                           \
-    VAESENC_LAST(%%rcx, %%rdx)
-
-#define AESENC_LAST15_ENC_AVX2()                        \
-    "movl	%[nbytes], %%ecx\n\t"                   \
-    "movl	%%ecx, %%edx\n\t"                       \
-    "andl	$0x0f, %%ecx\n\t"                       \
-    "jz		55f\n\t"                                \
-    "vmovdqu	" VAR(CTR1) ", %%xmm13\n\t"             \
-    "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"   \
-    "vpxor	0(%[KEY]), %%xmm13, %%xmm13\n\t"        \
-    VAESENC_AVX(%%xmm13)                                \
-    "subq	$16, %%rsp\n\t"                         \
-    "xorl	%%ecx, %%ecx\n\t"                       \
-    "vmovdqu	%%xmm13, (%%rsp)\n\t"                   \
-    "\n"                                                \
-    "51:\n\t"                                           \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"    \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"            \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t"   \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"            \
-    "incl	" VAR(KR) "\n\t"                        \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	%%edx, " VAR(KR) "\n\t"                 \
-    "jl		51b\n\t"                                \
-    "xorq	%%r13, %%r13\n\t"                       \
-    "cmpl	$16, %%ecx\n\t"                         \
-    "je		53f\n\t"                                \
-    "\n"                                                \
-    "52:\n\t"                                           \
-    "movb	%%r13b, (%%rsp,%%rcx,1)\n\t"            \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	$16, %%ecx\n\t"                         \
-    "jl		52b\n\t"                                \
-    "53:\n\t"                                           \
-    "vmovdqu	(%%rsp), %%xmm13\n\t"                   \
-    "addq	$16, %%rsp\n\t"                         \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"    \
-    "vpxor	%%xmm13, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_GFMUL_RED_AVX2(XR, HR, XR)                    \
-
-#define AESENC_LAST15_DEC_AVX2()                        \
-    "movl	%[nbytes], %%ecx\n\t"                   \
-    "movl	%%ecx, %%edx\n\t"                       \
-    "andl	$0x0f, %%ecx\n\t"                       \
-    "jz		55f\n\t"                                \
-    "vmovdqu	" VAR(CTR1) ", %%xmm13\n\t"             \
-    "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"   \
-    "vpxor	0(%[KEY]), %%xmm13, %%xmm13\n\t"        \
-    VAESENC_AVX(%%xmm13)                                \
-    "subq	$32, %%rsp\n\t"                         \
-    "xorl	%%ecx, %%ecx\n\t"                       \
-    "vmovdqu	%%xmm13, (%%rsp)\n\t"                   \
-    "vpxor	%%xmm0, %%xmm0, %%xmm0\n\t"             \
-    "vmovdqu	%%xmm0, 16(%%rsp)\n\t"                  \
-    "\n"                                                \
-    "51:\n\t"                                           \
-    "movzbl	(%[in]," VAR(KR64) ",1), %%r13d\n\t"    \
-    "movb	%%r13b, 16(%%rsp,%%rcx,1)\n\t"          \
-    "xorb	(%%rsp,%%rcx,1), %%r13b\n\t"            \
-    "movb	%%r13b, (%[out]," VAR(KR64) ",1)\n\t"   \
-    "incl	" VAR(KR) "\n\t"                        \
-    "incl	%%ecx\n\t"                              \
-    "cmpl	%%edx, " VAR(KR) "\n\t"                 \
-    "jl		51b\n\t"                                \
-    "53:\n\t"                                           \
-    "vmovdqu	16(%%rsp), %%xmm13\n\t"                 \
-    "addq	$32, %%rsp\n\t"                         \
-    "vpshufb	%[BSWAP_MASK], %%xmm13, %%xmm13\n\t"    \
-    "vpxor	%%xmm13, " VAR(XR) ", " VAR(XR) "\n\t"  \
-    GHASH_GFMUL_RED_AVX2(XR, HR, XR)                    \
-
-#define CALC_TAG_AVX2()                                      \
-    "movl	%[nbytes], %%edx\n\t"                        \
-    "movl	%[abytes], %%ecx\n\t"                        \
-    "shlq	$3, %%rdx\n\t"                               \
-    "shlq	$3, %%rcx\n\t"                               \
-    "vpinsrq	$0, %%rdx, %%xmm0, %%xmm0\n\t"               \
-    "vpinsrq	$1, %%rcx, %%xmm0, %%xmm0\n\t"               \
-    "vpxor	%%xmm0, " VAR(XR) ", " VAR(XR) "\n\t"        \
-    GHASH_GFMUL_RED_AVX2(XR, HR, XR)                         \
-    "vpshufb	%[BSWAP_MASK], " VAR(XR) ", " VAR(XR) "\n\t" \
-    "vpxor	" VAR(TR) ", " VAR(XR) ", %%xmm0\n\t"        \
-
-
-static void AES_GCM_encrypt_avx2(const unsigned char *in, unsigned char *out,
-                                 const unsigned char* addt,
-                                 const unsigned char* ivec, unsigned char *tag,
-                                 unsigned int nbytes, unsigned int abytes,
-                                 unsigned int ibytes, unsigned int tbytes,
-                                 const unsigned char* key, int nr)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register unsigned int ivLen asm("ebx") = ibytes;
-
-    __asm__ __volatile__ (
-        "subq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "vpxor		%%xmm13, %%xmm13, %%xmm13\n\t"
-        "vpxor		" VAR(XR) ", " VAR(XR) ", " VAR(XR) "\n\t"
-        "movl		%[ibytes], %%edx\n\t"
-        "cmpl		$12, %%edx\n\t"
-        "jne		35f\n\t"
-        CALC_IV_12_AVX2()
-        "jmp		39f\n\t"
-        "\n"
-        "35:\n\t"
-        CALC_IV_AVX2()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD_AVX2()
-
-        "# Calculate counter and H\n\t"
-        "vpsrlq		$63, " VAR(HR) ", %%xmm5\n\t"
-        "vpsllq		$1, " VAR(HR) ", %%xmm4\n\t"
-        "vpslldq	$8, %%xmm5, %%xmm5\n\t"
-        "vpor		%%xmm5, %%xmm4, %%xmm4\n\t"
-        "vpshufd	$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpsrad		$31, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"
-        "vpand		%[MOD2_128], " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpaddd		%[ONE], %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm4, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vmovdqu	%%xmm13, " VAR(CTR1) "\n\t"
-
-        "xorl		" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX2_NO_UNROLL)
-        "cmpl	$128, %[nbytes]\n\t"
-        "movl	%[nbytes], %%r13d\n\t"
-        "jl	5f\n\t"
-        "andl	$0xffffff80, %%r13d\n\t"
-
-        CALC_HT_8_AVX2()
-
-        "# First 128 bytes of input\n\t"
-        VAESENC_128()
-
-        "cmpl	$128, %%r13d\n\t"
-        "movl	$128, " VAR(KR) "\n\t"
-        "jle	2f\n\t"
-
-        "# More 128 bytes of input\n\t"
-        "\n"
-    "3:\n\t"
-        VAESENC_128_GHASH_AVX2(%%rdx, 0)
-        "addl	$128, " VAR(KR) "\n\t"
-        "cmpl	%%r13d, " VAR(KR) "\n\t"
-        "jl	3b\n\t"
-        "\n"
-    "2:\n\t"
-        "vmovdqa	%[BSWAP_MASK], %%xmm13\n\t"
-        "vpshufb	%%xmm13, %%xmm4, %%xmm4\n\t"
-        "vpshufb	%%xmm13, %%xmm5, %%xmm5\n\t"
-        "vpshufb	%%xmm13, %%xmm6, %%xmm6\n\t"
-        "vpshufb	%%xmm13, %%xmm7, %%xmm7\n\t"
-        "vpshufb	%%xmm13, %%xmm8, %%xmm8\n\t"
-        "vpshufb	%%xmm13, %%xmm9, %%xmm9\n\t"
-        "vpshufb	%%xmm13, %%xmm10, %%xmm10\n\t"
-        "vpshufb	%%xmm13, %%xmm11, %%xmm11\n\t"
-        "vpxor		%%xmm2, %%xmm4, %%xmm4\n\t"
-
-        GHASH_GFMUL_RED_8_AVX2()
-
-        "vmovdqu	0(" VAR(HTR) "), " VAR(HR) "\n\t"
-        "\n"
-    "5:\n\t"
-        "movl		%[nbytes], %%edx\n\t"
-        "cmpl		%%edx, " VAR(KR) "\n\t"
-        "jge		55f\n\t"
-#endif
-
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xfffffff0, %%r13d\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		14f\n\t"
-
-        VAESENC_BLOCK_AVX2()
-        "addl		$16, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		13f\n\t"
-        "vmovdqa	%[MOD2_128], %%xmm0\n\t"
-        "\n"
-        "12:\n\t"
-        "vmovdqu	(%[in]," VAR(KR64) ",1), %%xmm9\n\t"
-        "vmovdqu	" VAR(CTR1) ", %%xmm5\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm5, %%xmm4\n\t"
-        "vpaddd		%[ONE], %%xmm5, %%xmm5\n\t"
-        "vmovdqu	%%xmm5, " VAR(CTR1) "\n\t"
-        VAESENC_GFMUL_SB_AVX2(%%xmm9, HR, XR, CTR1)
-        "vmovdqu	%%xmm4, (%[out]," VAR(KR64) ",1)\n\t"
-        "vpshufb	%[BSWAP_MASK], %%xmm4, %%xmm4\n\t"
-        "addl		$16, " VAR(KR) "\n\t"
-        "vpxor		%%xmm4, " VAR(XR) ", " VAR(XR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		12b\n\t"
-        "\n"
-        "13:\n\t"
-        GHASH_GFMUL_RED_AVX2(XR, HR, XR)
-        "\n"
-        "14:\n\t"
-
-        AESENC_LAST15_ENC_AVX2()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG_AVX2()
-        STORE_TAG_AVX()
-        "addq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        "vzeroupper\n\t"
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tbytes),
-          [tag] "r" (tag),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX2_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "rdx", "r13"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_INTEL_AVX1 */
-
-#ifdef HAVE_AES_DECRYPT
-/* Figure 10. AES-GCM – Decrypt With Single Block Ghash at a Time */
-
-static void AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
-                            const unsigned char* addt,
-                            const unsigned char* ivec, const unsigned char *tag,
-                            int nbytes, int abytes, int ibytes, int tbytes,
-                            const unsigned char* key, int nr, int* res)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register int ivLen asm("ebx") = ibytes;
-    register int tagLen asm("edx") = tbytes;
-
-    __asm__ __volatile__ (
-        "pushq		%%rdx\n\t"
-        "subq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "pxor		%%xmm13, %%xmm13\n\t"
-        "pxor		%%xmm15, %%xmm15\n\t"
-        "movl		%[ibytes], %%edx\n\t"
-        "cmpl		$12, %%edx\n\t"
-        "jne		35f\n\t"
-        CALC_IV_12()
-        "\n"
-        "35:\n\t"
-        CALC_IV()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD()
-
-        "# Calculate counter and H\n\t"
-        "pshufb		%[BSWAP_EPI64], %%xmm13\n\t"
-        "movdqa		" VAR(HR) ", %%xmm5\n\t"
-        "paddd		%[ONE], %%xmm13\n\t"
-        "movdqa		" VAR(HR) ", %%xmm4\n\t"
-        "movdqu		%%xmm13, " VAR(CTR1) "\n\t"
-        "psrlq		$63, %%xmm5\n\t"
-        "psllq		$1, %%xmm4\n\t"
-        "pslldq		$8, %%xmm5\n\t"
-        "por		%%xmm5, %%xmm4\n\t"
-        "pshufd		$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "psrad		$31, " VAR(HR) "\n\t"
-        "pand		%[MOD2_128], " VAR(HR) "\n\t"
-        "pxor		%%xmm4, " VAR(HR) "\n\t"
-
-        "xorl		" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-        "cmpl		$128, %[nbytes]\n\t"
-        "jl		5f\n\t"
-
-        CALC_HT_8_AVX()
-
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xffffff80, %%r13d\n\t"
-        "\n"
-        "2:\n\t"
-        AESENC_128_GHASH_AVX(%%rcx, 128)
-        "addl		$128, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		2b\n\t"
-
-        "movdqa		%%xmm2, " VAR(XR) "\n\t"
-        "movdqu		(%%rsp), " VAR(HR) "\n\t"
-    "5:\n\t"
-        "movl		%[nbytes], %%edx\n\t"
-        "cmpl		%%edx, " VAR(KR) "\n\t"
-        "jge		55f\n\t"
-#endif
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xfffffff0, %%r13d\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		13f\n\t"
-
-        "\n"
-        "12:\n\t"
-        "leaq		(%[in]," VAR(KR64) ",1), %%rcx\n\t"
-        "leaq		(%[out]," VAR(KR64) ",1), %%rdx\n\t"
-        "movdqu		(%%rcx), %%xmm1\n\t"
-        "movdqa		" VAR(HR) ", %%xmm0\n\t"
-        "pshufb		%[BSWAP_MASK], %%xmm1\n\t"
-        "pxor		" VAR(XR) ", %%xmm1\n\t"
-        AESENC_GFMUL(%%rcx, %%rdx, %%xmm0, %%xmm1)
-        "addl		$16, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		12b\n\t"
-        "\n"
-        "13:\n\t"
-
-        AESENC_LAST15_DEC_AVX()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG()
-        "addq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        "popq		%%rdx\n\t"
-        CMP_TAG()
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tagLen),
-          [tag] "r" (tag), [res] "r" (res),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "r13"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX1
-static void AES_GCM_decrypt_avx1(const unsigned char *in, unsigned char *out,
-                                 const unsigned char* addt,
-                                 const unsigned char* ivec,
-                                 const unsigned char *tag, int nbytes,
-                                 int abytes, int ibytes, int tbytes,
-                                 const unsigned char* key, int nr, int* res)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register int ivLen asm("ebx") = ibytes;
-    register int tagLen asm("edx") = tbytes;
-
-    __asm__ __volatile__ (
-        "pushq		%%rdx\n\t"
-        "subq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "vpxor		%%xmm13, %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm15, %%xmm15, %%xmm15\n\t"
-        "movl		%[ibytes], %%edx\n\t"
-        "cmpl		$12, %%edx\n\t"
-        "jne		35f\n\t"
-        CALC_IV_12_AVX1()
-        "\n"
-        "35:\n\t"
-        CALC_IV_AVX1()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD_AVX1()
-
-        "# Calculate counter and H\n\t"
-        "vpsrlq		$63, " VAR(HR) ", %%xmm5\n\t"
-        "vpsllq		$1, " VAR(HR) ", %%xmm4\n\t"
-        "vpslldq	$8, %%xmm5, %%xmm5\n\t"
-        "vpor		%%xmm5, %%xmm4, %%xmm4\n\t"
-        "vpshufd	$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpsrad		$31, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"
-        "vpand		%[MOD2_128], " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpaddd		%[ONE], %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm4, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vmovdqu	%%xmm13, " VAR(CTR1) "\n\t"
-
-        "xorl		" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-        "cmpl		$128, %[nbytes]\n\t"
-        "jl		5f\n\t"
-
-        CALC_HT_8_AVX1()
-
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xffffff80, %%r13d\n\t"
-        "\n"
-        "2:\n\t"
-        VAESENC_128_GHASH_AVX1(%%rcx, 128)
-        "addl		$128, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		2b\n\t"
-
-        "vmovdqa	%%xmm2, " VAR(XR) "\n\t"
-        "vmovdqu	(%%rsp), " VAR(HR) "\n\t"
-    "5:\n\t"
-        "movl		%[nbytes], %%edx\n\t"
-        "cmpl		%%edx, " VAR(KR) "\n\t"
-        "jge		55f\n\t"
-#endif
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xfffffff0, %%r13d\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		13f\n\t"
-
-        "\n"
-        "12:\n\t"
-        "vmovdqu	(%[in]," VAR(KR64) ",1), %%xmm9\n\t"
-        "vmovdqa	" VAR(HR) ", %%xmm0\n\t"
-        "vpshufb	%[BSWAP_MASK], %%xmm9, %%xmm1\n\t"
-        "vpxor		" VAR(XR) ", %%xmm1, %%xmm1\n\t"
-        VAESENC_GFMUL(%%xmm9, %%xmm0, %%xmm1)
-        "addl		$16, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		12b\n\t"
-        "\n"
-        "13:\n\t"
-
-        AESENC_LAST15_DEC_AVX1()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG_AVX1()
-        "addq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        "popq		%%rdx\n\t"
-        CMP_TAG_AVX()
-        "vzeroupper\n\t"
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tagLen),
-          [tag] "r" (tag), [res] "r" (res),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX1_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "r13"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-static void AES_GCM_decrypt_avx2(const unsigned char *in, unsigned char *out,
-                                 const unsigned char* addt,
-                                 const unsigned char* ivec,
-                                 const unsigned char *tag, int nbytes,
-                                 int abytes, int ibytes, int tbytes,
-                                 const unsigned char* key, int nr, int* res)
-{
-    register const unsigned char* iv asm("rax") = ivec;
-    register int ivLen asm("ebx") = ibytes;
-    register int tagLen asm("edx") = tbytes;
-
-    __asm__ __volatile__ (
-        "pushq		%%rdx\n\t"
-        "subq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        /* Counter is xmm13 */
-        "vpxor		%%xmm13, %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm15, %%xmm15, %%xmm15\n\t"
-        "movl		%[ibytes], %%edx\n\t"
-        "cmpl		$12, %%edx\n\t"
-        "jne		35f\n\t"
-        CALC_IV_12_AVX2()
-        "jmp		39f\n\t"
-        "\n"
-        "35:\n\t"
-        CALC_IV_AVX2()
-        "\n"
-        "39:\n\t"
-
-        CALC_AAD_AVX2()
-
-        "# Calculate counter and H\n\t"
-        "vpsrlq		$63, " VAR(HR) ", %%xmm5\n\t"
-        "vpsllq		$1, " VAR(HR) ", %%xmm4\n\t"
-        "vpslldq	$8, %%xmm5, %%xmm5\n\t"
-        "vpor		%%xmm5, %%xmm4, %%xmm4\n\t"
-        "vpshufd	$0xff, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpsrad		$31, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm13, %%xmm13\n\t"
-        "vpand		%[MOD2_128], " VAR(HR) ", " VAR(HR) "\n\t"
-        "vpaddd		%[ONE], %%xmm13, %%xmm13\n\t"
-        "vpxor		%%xmm4, " VAR(HR) ", " VAR(HR) "\n\t"
-        "vmovdqu	%%xmm13, " VAR(CTR1) "\n\t"
-
-        "xorl		" VAR(KR) ", " VAR(KR) "\n\t"
-
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX2_NO_UNROLL)
-        "cmpl		$128, %[nbytes]\n\t"
-        "jl		5f\n\t"
-
-        CALC_HT_8_AVX2()
-
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xffffff80, %%r13d\n\t"
-        "\n"
-        "2:\n\t"
-        VAESENC_128_GHASH_AVX2(%%rcx, 128)
-        "addl		$128, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		2b\n\t"
-
-        "vmovdqa	%%xmm2, " VAR(XR) "\n\t"
-        "vmovdqu	(%%rsp), " VAR(HR) "\n\t"
-    "5:\n\t"
-        "movl		%[nbytes], %%edx\n\t"
-        "cmpl		%%edx, " VAR(KR) "\n\t"
-        "jge		55f\n\t"
-#endif
-        "movl		%[nbytes], %%r13d\n\t"
-        "andl		$0xfffffff0, %%r13d\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jge		13f\n\t"
-
-        "vmovdqa	%[MOD2_128], %%xmm0\n\t"
-        "\n"
-        "12:\n\t"
-        "vmovdqu	(%[in]," VAR(KR64) ",1), %%xmm9\n\t"
-        "vmovdqu	" VAR(CTR1) ", %%xmm5\n\t"
-        "vpshufb	%[BSWAP_MASK], %%xmm9, %%xmm1\n\t"
-        "vpshufb	%[BSWAP_EPI64], %%xmm5, %%xmm4\n\t"
-        "vpaddd		%[ONE], %%xmm5, %%xmm5\n\t"
-        "vpxor		" VAR(XR) ", %%xmm1, %%xmm1\n\t"
-        "vmovdqu	%%xmm5, " VAR(CTR1) "\n\t"
-        VAESENC_GFMUL_SB_AVX2(%%xmm9, HR, %%xmm1, CTR1)
-        "vmovdqu	%%xmm4, (%[out]," VAR(KR64) ",1)\n\t"
-        "addl		$16, " VAR(KR) "\n\t"
-        "cmpl		%%r13d, " VAR(KR) "\n\t"
-        "jl		12b\n\t"
-        "\n"
-        "13:\n\t"
-
-        AESENC_LAST15_DEC_AVX2()
-        "\n"
-        "55:\n\t"
-
-        CALC_TAG_AVX2()
-        "addq		$" VAR(STACK_OFFSET) ", %%rsp\n\t"
-        "popq		%%rdx\n\t"
-        CMP_TAG_AVX()
-        "vzeroupper\n\t"
-
-        :
-        : [KEY] "r" (key),
-          [in] "r" (in), [out] "r" (out), [nr] "r" (nr),
-          [nbytes] "r" (nbytes), [abytes] "r" (abytes), [addt] "r" (addt),
-          [ivec] "r" (iv), [ibytes] "r" (ivLen), [tbytes] "r" (tagLen),
-          [tag] "r" (tag), [res] "r" (res),
-          [BSWAP_MASK] "m" (BSWAP_MASK),
-          [BSWAP_EPI64] "m" (BSWAP_EPI64),
-          [ONE] "m" (ONE),
-#if !defined(AES_GCM_AESNI_NO_UNROLL) && !defined(AES_GCM_AVX2_NO_UNROLL)
-          [TWO] "m" (TWO), [THREE] "m" (THREE), [FOUR] "m" (FOUR),
-          [FIVE] "m" (FIVE), [SIX] "m" (SIX), [SEVEN] "m" (SEVEN),
-          [EIGHT] "m" (EIGHT),
-#endif
-          [MOD2_128] "m" (MOD2_128)
-        : "xmm15", "xmm14", "xmm13", "xmm12",
-          "xmm0", "xmm1", "xmm2", "xmm3", "memory",
-          "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
-          "rcx", "r13"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_INTEL_AVX1 */
-#endif /* HAVE_AES_DECRYPT */
-
-#else /* _MSC_VER */
-/* The following are for MSC based builds which do not allow
- * inline assembly. Intrinsic functions are used instead. */
-
-#define aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T)         \
-do                                                         \
-{                                                          \
-    word32 iv12[4];                                        \
-    iv12[0] = *(word32*)&ivec[0];                          \
-    iv12[1] = *(word32*)&ivec[4];                          \
-    iv12[2] = *(word32*)&ivec[8];                          \
-    iv12[3] = 0x01000000;                                  \
-    Y = _mm_loadu_si128((__m128i*)iv12);                   \
-                                                           \
-    /* (Compute E[ZERO, KS] and E[Y0, KS] together */      \
-    tmp1 = _mm_load_si128(&KEY[0]);                        \
-    tmp2 = _mm_xor_si128(Y, KEY[0]);                       \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);                 \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                 \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);                 \
-    lastKey = KEY[10];                                     \
-    if (nr > 10) {                                         \
-        tmp1 = _mm_aesenc_si128(tmp1, lastKey);            \
-        tmp2 = _mm_aesenc_si128(tmp2, lastKey);            \
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);            \
-        tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);            \
-        lastKey = KEY[12];                                 \
-        if (nr > 12) {                                     \
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);        \
-            tmp2 = _mm_aesenc_si128(tmp2, lastKey);        \
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);        \
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);        \
-            lastKey = KEY[14];                             \
-        }                                                  \
-    }                                                      \
-    H = _mm_aesenclast_si128(tmp1, lastKey);               \
-    T = _mm_aesenclast_si128(tmp2, lastKey);               \
-    H = _mm_shuffle_epi8(H, BSWAP_MASK);                   \
-}                                                          \
-while (0)
-
-#define aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T)         \
-do                                                              \
-{                                                               \
-    if (ibytes % 16) {                                          \
-        i = ibytes / 16;                                        \
-        for (j=0; j < (int)(ibytes%16); j++)                    \
-            ((unsigned char*)&last_block)[j] = ivec[i*16+j];    \
-    }                                                           \
-    tmp1 = _mm_load_si128(&KEY[0]);                             \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                      \
-    lastKey = KEY[10];                                          \
-    if (nr > 10) {                                              \
-        tmp1 = _mm_aesenc_si128(tmp1, lastKey);                 \
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);                 \
-        lastKey = KEY[12];                                      \
-        if (nr > 12) {                                          \
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);             \
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);             \
-            lastKey = KEY[14];                                  \
-        }                                                       \
-    }                                                           \
-    H = _mm_aesenclast_si128(tmp1, lastKey);                    \
-    H = _mm_shuffle_epi8(H, BSWAP_MASK);                        \
-    Y = _mm_setzero_si128();                                    \
-    for (i=0; i < (int)(ibytes/16); i++) {                      \
-        tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]);           \
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);              \
-        Y = _mm_xor_si128(Y, tmp1);                             \
-        Y = gfmul_sw(Y, H);                                     \
-    }                                                           \
-    if (ibytes % 16) {                                          \
-        tmp1 = last_block;                                      \
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);              \
-        Y = _mm_xor_si128(Y, tmp1);                             \
-        Y = gfmul_sw(Y, H);                                     \
-    }                                                           \
-    tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0);                 \
-    tmp1 = _mm_insert_epi64(tmp1, 0, 1);                        \
-    Y = _mm_xor_si128(Y, tmp1);                                 \
-    Y = gfmul_sw(Y, H);                                         \
-    Y = _mm_shuffle_epi8(Y, BSWAP_MASK); /* Compute E(K, Y0) */ \
-    tmp1 = _mm_xor_si128(Y, KEY[0]);                            \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);                      \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);                      \
-    lastKey = KEY[10];                                          \
-    if (nr > 10) {                                              \
-        tmp1 = _mm_aesenc_si128(tmp1, lastKey);                 \
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);                 \
-        lastKey = KEY[12];                                      \
-        if (nr > 12) {                                          \
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);             \
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);             \
-            lastKey = KEY[14];                                  \
-        }                                                       \
-    }                                                           \
-    T = _mm_aesenclast_si128(tmp1, lastKey);                    \
-}                                                               \
-while (0)
-
-#define AES_ENC_8(j)                       \
-    tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); \
-    tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); \
-    tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); \
-    tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); \
-    tmp5 = _mm_aesenc_si128(tmp5, KEY[j]); \
-    tmp6 = _mm_aesenc_si128(tmp6, KEY[j]); \
-    tmp7 = _mm_aesenc_si128(tmp7, KEY[j]); \
-    tmp8 = _mm_aesenc_si128(tmp8, KEY[j]);
-
-#define AES_ENC_LAST_8()                                                  \
-    tmp1 =_mm_aesenclast_si128(tmp1, lastKey);                            \
-    tmp2 =_mm_aesenclast_si128(tmp2, lastKey);                            \
-    tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*8+0]));  \
-    tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*8+1]));  \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+0], tmp1);                      \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+1], tmp2);                      \
-    tmp3 =_mm_aesenclast_si128(tmp3, lastKey);                            \
-    tmp4 =_mm_aesenclast_si128(tmp4, lastKey);                            \
-    tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*8+2]));  \
-    tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*8+3]));  \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+2], tmp3);                      \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+3], tmp4);                      \
-    tmp5 =_mm_aesenclast_si128(tmp5, lastKey);                            \
-    tmp6 =_mm_aesenclast_si128(tmp6, lastKey);                            \
-    tmp5 = _mm_xor_si128(tmp5, _mm_loadu_si128(&((__m128i*)in)[i*8+4]));  \
-    tmp6 = _mm_xor_si128(tmp6, _mm_loadu_si128(&((__m128i*)in)[i*8+5]));  \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+4], tmp5);                      \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+5], tmp6);                      \
-    tmp7 =_mm_aesenclast_si128(tmp7, lastKey);                            \
-    tmp8 =_mm_aesenclast_si128(tmp8, lastKey);                            \
-    tmp7 = _mm_xor_si128(tmp7, _mm_loadu_si128(&((__m128i*)in)[i*8+6]));  \
-    tmp8 = _mm_xor_si128(tmp8, _mm_loadu_si128(&((__m128i*)in)[i*8+7]));  \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+6], tmp7);                      \
-    _mm_storeu_si128(&((__m128i*)out)[i*8+7], tmp8);
-
-
-static __m128i gfmul_sw(__m128i a, __m128i b)
-{
-    __m128i r, t1, t2, t3, t4, t5, t6, t7;
-    t2 = _mm_shuffle_epi32(b, 78);
-    t3 = _mm_shuffle_epi32(a, 78);
-    t2 = _mm_xor_si128(t2, b);
-    t3 = _mm_xor_si128(t3, a);
-    t4 = _mm_clmulepi64_si128(b, a, 0x11);
-    t1 = _mm_clmulepi64_si128(b, a, 0x00);
-    t2 = _mm_clmulepi64_si128(t2, t3, 0x00);
-    t2 = _mm_xor_si128(t2, t1);
-    t2 = _mm_xor_si128(t2, t4);
-    t3 = _mm_slli_si128(t2, 8);
-    t2 = _mm_srli_si128(t2, 8);
-    t1 = _mm_xor_si128(t1, t3);
-    t4 = _mm_xor_si128(t4, t2);
-
-    t5 = _mm_srli_epi32(t1, 31);
-    t6 = _mm_srli_epi32(t4, 31);
-    t1 = _mm_slli_epi32(t1, 1);
-    t4 = _mm_slli_epi32(t4, 1);
-    t7 = _mm_srli_si128(t5, 12);
-    t5 = _mm_slli_si128(t5, 4);
-    t6 = _mm_slli_si128(t6, 4);
-    t4 = _mm_or_si128(t4, t7);
-    t1 = _mm_or_si128(t1, t5);
-    t4 = _mm_or_si128(t4, t6);
-
-    t5 = _mm_slli_epi32(t1, 31);
-    t6 = _mm_slli_epi32(t1, 30);
-    t7 = _mm_slli_epi32(t1, 25);
-    t5 = _mm_xor_si128(t5, t6);
-    t5 = _mm_xor_si128(t5, t7);
-
-    t6 = _mm_srli_si128(t5, 4);
-    t5 = _mm_slli_si128(t5, 12);
-    t1 = _mm_xor_si128(t1, t5);
-    t7 = _mm_srli_epi32(t1, 1);
-    t3 = _mm_srli_epi32(t1, 2);
-    t2 = _mm_srli_epi32(t1, 7);
-
-    t7 = _mm_xor_si128(t7, t3);
-    t7 = _mm_xor_si128(t7, t2);
-    t7 = _mm_xor_si128(t7, t6);
-    t7 = _mm_xor_si128(t7, t1);
-    r = _mm_xor_si128(t4, t7);
-
-    return r;
-}
-
-static void gfmul_only(__m128i a, __m128i b, __m128i* r0, __m128i* r1)
-{
-    __m128i t1, t2, t3, t4;
-
-    /* 128 x 128 Carryless Multiply */
-    t2 = _mm_shuffle_epi32(b, 78);
-    t3 = _mm_shuffle_epi32(a, 78);
-    t2 = _mm_xor_si128(t2, b);
-    t3 = _mm_xor_si128(t3, a);
-    t4 = _mm_clmulepi64_si128(b, a, 0x11);
-    t1 = _mm_clmulepi64_si128(b, a, 0x00);
-    t2 = _mm_clmulepi64_si128(t2, t3, 0x00);
-    t2 = _mm_xor_si128(t2, t1);
-    t2 = _mm_xor_si128(t2, t4);
-    t3 = _mm_slli_si128(t2, 8);
-    t2 = _mm_srli_si128(t2, 8);
-    t1 = _mm_xor_si128(t1, t3);
-    t4 = _mm_xor_si128(t4, t2);
-    *r0 = _mm_xor_si128(t1, *r0);
-    *r1 = _mm_xor_si128(t4, *r1);
-}
-
-static __m128i gfmul_shl1(__m128i a)
-{
-    __m128i t1 = a, t2;
-    t2 = _mm_srli_epi64(t1, 63);
-    t1 = _mm_slli_epi64(t1, 1);
-    t2 = _mm_slli_si128(t2, 8);
-    t1 = _mm_or_si128(t1, t2);
-    /* if (a[1] >> 63) t1 = _mm_xor_si128(t1, MOD2_128); */
-    a = _mm_shuffle_epi32(a, 0xff);
-    a = _mm_srai_epi32(a, 31);
-    a = _mm_and_si128(a, MOD2_128);
-    t1 = _mm_xor_si128(t1, a);
-    return t1;
-}
-
-static __m128i ghash_red(__m128i r0, __m128i r1)
-{
-    __m128i t2, t3;
-    __m128i t5, t6, t7;
-
-    t5 = _mm_slli_epi32(r0, 31);
-    t6 = _mm_slli_epi32(r0, 30);
-    t7 = _mm_slli_epi32(r0, 25);
-    t5 = _mm_xor_si128(t5, t6);
-    t5 = _mm_xor_si128(t5, t7);
-
-    t6 = _mm_srli_si128(t5, 4);
-    t5 = _mm_slli_si128(t5, 12);
-    r0 = _mm_xor_si128(r0, t5);
-    t7 = _mm_srli_epi32(r0, 1);
-    t3 = _mm_srli_epi32(r0, 2);
-    t2 = _mm_srli_epi32(r0, 7);
-
-    t7 = _mm_xor_si128(t7, t3);
-    t7 = _mm_xor_si128(t7, t2);
-    t7 = _mm_xor_si128(t7, t6);
-    t7 = _mm_xor_si128(t7, r0);
-    return _mm_xor_si128(r1, t7);
-}
-
-static __m128i gfmul_shifted(__m128i a, __m128i b)
-{
-    __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128();
-    gfmul_only(a, b, &t0, &t1);
-    return ghash_red(t0, t1);
-}
-
-#ifndef AES_GCM_AESNI_NO_UNROLL
-static __m128i gfmul8(__m128i a1, __m128i a2, __m128i a3, __m128i a4,
-                      __m128i a5, __m128i a6, __m128i a7, __m128i a8,
-                      __m128i b1, __m128i b2, __m128i b3, __m128i b4,
-                      __m128i b5, __m128i b6, __m128i b7, __m128i b8)
-{
-    __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128();
-    gfmul_only(a1, b8, &t0, &t1);
-    gfmul_only(a2, b7, &t0, &t1);
-    gfmul_only(a3, b6, &t0, &t1);
-    gfmul_only(a4, b5, &t0, &t1);
-    gfmul_only(a5, b4, &t0, &t1);
-    gfmul_only(a6, b3, &t0, &t1);
-    gfmul_only(a7, b2, &t0, &t1);
-    gfmul_only(a8, b1, &t0, &t1);
-    return ghash_red(t0, t1);
-}
-#endif
-
-
-static void AES_GCM_encrypt(const unsigned char *in,
-                              unsigned char *out,
-                              const unsigned char* addt,
-                              const unsigned char* ivec,
-                              unsigned char *tag, unsigned int nbytes,
-                              unsigned int abytes, unsigned int ibytes,
-                              unsigned int tbytes,
-                              const unsigned char* key, int nr)
-{
-    int i, j ,k;
-    __m128i ctr1;
-    __m128i H, Y, T;
-    __m128i X = _mm_setzero_si128();
-    __m128i *KEY = (__m128i*)key, lastKey;
-    __m128i last_block = _mm_setzero_si128();
-    __m128i tmp1, tmp2;
-#ifndef AES_GCM_AESNI_NO_UNROLL
-    __m128i HT[8];
-    __m128i r0, r1;
-    __m128i XV;
-    __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
-#endif
-
-    if (ibytes == 12)
-        aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T);
-    else
-        aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T);
-
-    for (i=0; i < (int)(abytes/16); i++) {
-        tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]);
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X = _mm_xor_si128(X, tmp1);
-        X = gfmul_sw(X, H);
-    }
-    if (abytes%16) {
-        last_block = _mm_setzero_si128();
-        for (j=0; j < (int)(abytes%16); j++)
-            ((unsigned char*)&last_block)[j] = addt[i*16+j];
-        tmp1 = last_block;
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X = _mm_xor_si128(X, tmp1);
-        X = gfmul_sw(X, H);
-    }
-    tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64);
-    ctr1 = _mm_add_epi32(tmp1, ONE);
-    H = gfmul_shl1(H);
-
-#ifndef AES_GCM_AESNI_NO_UNROLL
-    i = 0;
-    if (nbytes >= 16*8) {
-        HT[0] = H;
-        HT[1] = gfmul_shifted(H, H);
-        HT[2] = gfmul_shifted(H, HT[1]);
-        HT[3] = gfmul_shifted(HT[1], HT[1]);
-        HT[4] = gfmul_shifted(HT[1], HT[2]);
-        HT[5] = gfmul_shifted(HT[2], HT[2]);
-        HT[6] = gfmul_shifted(HT[2], HT[3]);
-        HT[7] = gfmul_shifted(HT[3], HT[3]);
-
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        tmp2 = _mm_add_epi32(ctr1, ONE);
-        tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
-        tmp3 = _mm_add_epi32(ctr1, TWO);
-        tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
-        tmp4 = _mm_add_epi32(ctr1, THREE);
-        tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
-        tmp5 = _mm_add_epi32(ctr1, FOUR);
-        tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
-        tmp6 = _mm_add_epi32(ctr1, FIVE);
-        tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
-        tmp7 = _mm_add_epi32(ctr1, SIX);
-        tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
-        tmp8 = _mm_add_epi32(ctr1, SEVEN);
-        tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
-        ctr1 = _mm_add_epi32(ctr1, EIGHT);
-        tmp1 =_mm_xor_si128(tmp1, KEY[0]);
-        tmp2 =_mm_xor_si128(tmp2, KEY[0]);
-        tmp3 =_mm_xor_si128(tmp3, KEY[0]);
-        tmp4 =_mm_xor_si128(tmp4, KEY[0]);
-        tmp5 =_mm_xor_si128(tmp5, KEY[0]);
-        tmp6 =_mm_xor_si128(tmp6, KEY[0]);
-        tmp7 =_mm_xor_si128(tmp7, KEY[0]);
-        tmp8 =_mm_xor_si128(tmp8, KEY[0]);
-        AES_ENC_8(1);
-        AES_ENC_8(2);
-        AES_ENC_8(3);
-        AES_ENC_8(4);
-        AES_ENC_8(5);
-        AES_ENC_8(6);
-        AES_ENC_8(7);
-        AES_ENC_8(8);
-        AES_ENC_8(9);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            AES_ENC_8(10);
-            AES_ENC_8(11);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                AES_ENC_8(12);
-                AES_ENC_8(13);
-                lastKey = KEY[14];
-            }
-        }
-        AES_ENC_LAST_8();
-
-        for (i=1; i < (int)(nbytes/16/8); i++) {
-                r0 = _mm_setzero_si128();
-                r1 = _mm_setzero_si128();
-            tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-            tmp2 = _mm_add_epi32(ctr1, ONE);
-            tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
-            tmp3 = _mm_add_epi32(ctr1, TWO);
-            tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
-            tmp4 = _mm_add_epi32(ctr1, THREE);
-            tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
-            tmp5 = _mm_add_epi32(ctr1, FOUR);
-            tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
-            tmp6 = _mm_add_epi32(ctr1, FIVE);
-            tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
-            tmp7 = _mm_add_epi32(ctr1, SIX);
-            tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
-            tmp8 = _mm_add_epi32(ctr1, SEVEN);
-            tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
-            ctr1 = _mm_add_epi32(ctr1, EIGHT);
-            tmp1 =_mm_xor_si128(tmp1, KEY[0]);
-            tmp2 =_mm_xor_si128(tmp2, KEY[0]);
-            tmp3 =_mm_xor_si128(tmp3, KEY[0]);
-            tmp4 =_mm_xor_si128(tmp4, KEY[0]);
-            tmp5 =_mm_xor_si128(tmp5, KEY[0]);
-            tmp6 =_mm_xor_si128(tmp6, KEY[0]);
-            tmp7 =_mm_xor_si128(tmp7, KEY[0]);
-            tmp8 =_mm_xor_si128(tmp8, KEY[0]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+0]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                XV = _mm_xor_si128(XV, X);
-                gfmul_only(XV, HT[7], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[1]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[1]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[1]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[1]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[1]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[1]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+1]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[6], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[2]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[2]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[2]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[2]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[2]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[2]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+2]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[5], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[3]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[3]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[3]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[3]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[3]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[3]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+3]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[4], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[4]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[4]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[4]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[4]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[4]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[4]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+4]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[3], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[5]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[5]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[5]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[5]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[5]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[5]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+5]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[2], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[6]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[6]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[6]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[6]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[6]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[6]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+6]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[1], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[7]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[7]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[7]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[7]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[7]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[7]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+7]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[0], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[8]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[8]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[8]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[8]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[8]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[8]);
-                /* Reduction */
-                X = ghash_red(r0, r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[9]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[9]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[9]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[9]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[9]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[9]);
-            lastKey = KEY[10];
-            if (nr > 10) {
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[10]);
-                tmp2 = _mm_aesenc_si128(tmp2, KEY[10]);
-                tmp3 = _mm_aesenc_si128(tmp3, KEY[10]);
-                tmp4 = _mm_aesenc_si128(tmp4, KEY[10]);
-                tmp5 = _mm_aesenc_si128(tmp5, KEY[10]);
-                tmp6 = _mm_aesenc_si128(tmp6, KEY[10]);
-                tmp7 = _mm_aesenc_si128(tmp7, KEY[10]);
-                tmp8 = _mm_aesenc_si128(tmp8, KEY[10]);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-                tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);
-                tmp3 = _mm_aesenc_si128(tmp3, KEY[11]);
-                tmp4 = _mm_aesenc_si128(tmp4, KEY[11]);
-                tmp5 = _mm_aesenc_si128(tmp5, KEY[11]);
-                tmp6 = _mm_aesenc_si128(tmp6, KEY[11]);
-                tmp7 = _mm_aesenc_si128(tmp7, KEY[11]);
-                tmp8 = _mm_aesenc_si128(tmp8, KEY[11]);
-                lastKey = KEY[12];
-                if (nr > 12) {
-                    tmp1 = _mm_aesenc_si128(tmp1, KEY[12]);
-                    tmp2 = _mm_aesenc_si128(tmp2, KEY[12]);
-                    tmp3 = _mm_aesenc_si128(tmp3, KEY[12]);
-                    tmp4 = _mm_aesenc_si128(tmp4, KEY[12]);
-                    tmp5 = _mm_aesenc_si128(tmp5, KEY[12]);
-                    tmp6 = _mm_aesenc_si128(tmp6, KEY[12]);
-                    tmp7 = _mm_aesenc_si128(tmp7, KEY[12]);
-                    tmp8 = _mm_aesenc_si128(tmp8, KEY[12]);
-                    tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                    tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);
-                    tmp3 = _mm_aesenc_si128(tmp3, KEY[13]);
-                    tmp4 = _mm_aesenc_si128(tmp4, KEY[13]);
-                    tmp5 = _mm_aesenc_si128(tmp5, KEY[13]);
-                    tmp6 = _mm_aesenc_si128(tmp6, KEY[13]);
-                    tmp7 = _mm_aesenc_si128(tmp7, KEY[13]);
-                    tmp8 = _mm_aesenc_si128(tmp8, KEY[13]);
-                    lastKey = KEY[14];
-                }
-            }
-            AES_ENC_LAST_8();
-        }
-
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK);
-        tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK);
-        tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK);
-        tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK);
-        tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK);
-        tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK);
-        tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK);
-        tmp1 = _mm_xor_si128(X, tmp1);
-        X = gfmul8(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8,
-                   HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]);
-    }
-    for (k = i*8; k < (int)(nbytes/16); k++) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        ctr1 = _mm_add_epi32(ctr1, ONE);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
-        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X =_mm_xor_si128(X, tmp1);
-        X = gfmul_shifted(X, H);
-    }
-#else /* AES_GCM_AESNI_NO_UNROLL */
-    for (k = 0; k < (int)(nbytes/16) && k < 1; k++) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        ctr1 = _mm_add_epi32(ctr1, ONE);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
-        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X =_mm_xor_si128(X, tmp1);
-    }
-    for (; k < (int)(nbytes/16); k++) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        ctr1 = _mm_add_epi32(ctr1, ONE);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        X = gfmul_shifted(X, H);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k]));
-        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X =_mm_xor_si128(X, tmp1);
-    }
-    if (k > 0) {
-        X = gfmul_shifted(X, H);
-    }
-#endif /* AES_GCM_AESNI_NO_UNROLL */
-
-    /* If one partial block remains */
-    if (nbytes % 16) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        last_block = tmp1;
-        for (j=0; j < (int)(nbytes%16); j++)
-            ((unsigned char*)&last_block)[j] = in[k*16+j];
-        tmp1 = _mm_xor_si128(tmp1, last_block);
-        last_block = tmp1;
-        for (j=0; j < (int)(nbytes%16); j++)
-            out[k*16+j] = ((unsigned char*)&last_block)[j];
-        tmp1 = last_block;
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X =_mm_xor_si128(X, tmp1);
-        X = gfmul_shifted(X, H);
-    }
-    tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0);
-    tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1);
-    X = _mm_xor_si128(X, tmp1);
-    X = gfmul_shifted(X, H);
-    X = _mm_shuffle_epi8(X, BSWAP_MASK);
-    T = _mm_xor_si128(X, T);
-    /*_mm_storeu_si128((__m128i*)tag, T);*/
-    XMEMCPY(tag, &T, tbytes);
-}
-
-#ifdef HAVE_AES_DECRYPT
-
-static void AES_GCM_decrypt(const unsigned char *in,
-                           unsigned char *out,
-                           const unsigned char* addt,
-                           const unsigned char* ivec,
-                           const unsigned char *tag, int nbytes, int abytes,
-                           int ibytes, word32 tbytes, const unsigned char* key,
-                           int nr, int* res)
-{
-    int i, j ,k;
-    __m128i H, Y, T;
-    __m128i *KEY = (__m128i*)key, lastKey;
-    __m128i ctr1;
-    __m128i last_block = _mm_setzero_si128();
-    __m128i X = _mm_setzero_si128();
-    __m128i tmp1, tmp2, XV;
-#ifndef AES_GCM_AESNI_NO_UNROLL
-    __m128i HT[8];
-    __m128i r0, r1;
-    __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
-#endif /* AES_GCM_AESNI_NO_UNROLL */
-
-    if (ibytes == 12)
-        aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T);
-    else
-        aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T);
-
-    for (i=0; i<abytes/16; i++) {
-        tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]);
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X = _mm_xor_si128(X, tmp1);
-        X = gfmul_sw(X, H);
-    }
-    if (abytes%16) {
-        last_block = _mm_setzero_si128();
-        for (j=0; j<abytes%16; j++)
-            ((unsigned char*)&last_block)[j] = addt[i*16+j];
-        tmp1 = last_block;
-        tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK);
-        X = _mm_xor_si128(X, tmp1);
-        X = gfmul_sw(X, H);
-    }
-
-    tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64);
-    ctr1 = _mm_add_epi32(tmp1, ONE);
-    H = gfmul_shl1(H);
-    i = 0;
-
-#ifndef AES_GCM_AESNI_NO_UNROLL
-
-    if (0 < nbytes/16/8) {
-        HT[0] = H;
-        HT[1] = gfmul_shifted(H, H);
-        HT[2] = gfmul_shifted(H, HT[1]);
-        HT[3] = gfmul_shifted(HT[1], HT[1]);
-        HT[4] = gfmul_shifted(HT[1], HT[2]);
-        HT[5] = gfmul_shifted(HT[2], HT[2]);
-        HT[6] = gfmul_shifted(HT[2], HT[3]);
-        HT[7] = gfmul_shifted(HT[3], HT[3]);
-
-        for (; i < nbytes/16/8; i++) {
-                r0 = _mm_setzero_si128();
-                r1 = _mm_setzero_si128();
-
-            tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-            tmp2 = _mm_add_epi32(ctr1, ONE);
-            tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64);
-            tmp3 = _mm_add_epi32(ctr1, TWO);
-            tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64);
-            tmp4 = _mm_add_epi32(ctr1, THREE);
-            tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64);
-            tmp5 = _mm_add_epi32(ctr1, FOUR);
-            tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64);
-            tmp6 = _mm_add_epi32(ctr1, FIVE);
-            tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64);
-            tmp7 = _mm_add_epi32(ctr1, SIX);
-            tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64);
-            tmp8 = _mm_add_epi32(ctr1, SEVEN);
-            tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64);
-            ctr1 = _mm_add_epi32(ctr1, EIGHT);
-            tmp1 =_mm_xor_si128(tmp1, KEY[0]);
-            tmp2 =_mm_xor_si128(tmp2, KEY[0]);
-            tmp3 =_mm_xor_si128(tmp3, KEY[0]);
-            tmp4 =_mm_xor_si128(tmp4, KEY[0]);
-            tmp5 =_mm_xor_si128(tmp5, KEY[0]);
-            tmp6 =_mm_xor_si128(tmp6, KEY[0]);
-            tmp7 =_mm_xor_si128(tmp7, KEY[0]);
-            tmp8 =_mm_xor_si128(tmp8, KEY[0]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+0]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                XV = _mm_xor_si128(XV, X);
-                gfmul_only(XV, HT[7], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[1]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[1]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[1]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[1]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[1]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[1]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[1]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+1]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[6], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[2]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[2]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[2]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[2]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[2]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[2]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[2]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+2]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[5], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[3]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[3]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[3]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[3]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[3]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[3]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[3]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+3]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[4], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[4]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[4]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[4]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[4]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[4]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[4]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[4]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+4]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[3], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[5]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[5]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[5]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[5]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[5]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[5]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[5]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+5]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[2], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[6]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[6]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[6]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[6]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[6]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[6]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[6]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+6]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[1], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[7]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[7]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[7]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[7]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[7]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[7]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[7]);
-                /* 128 x 128 Carryless Multiply */
-                XV = _mm_loadu_si128(&((__m128i*)in)[i*8+7]);
-                XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-                gfmul_only(XV, HT[0], &r0, &r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[8]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[8]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[8]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[8]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[8]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[8]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[8]);
-                /* Reduction */
-                X = ghash_red(r0, r1);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-            tmp2 = _mm_aesenc_si128(tmp2, KEY[9]);
-            tmp3 = _mm_aesenc_si128(tmp3, KEY[9]);
-            tmp4 = _mm_aesenc_si128(tmp4, KEY[9]);
-            tmp5 = _mm_aesenc_si128(tmp5, KEY[9]);
-            tmp6 = _mm_aesenc_si128(tmp6, KEY[9]);
-            tmp7 = _mm_aesenc_si128(tmp7, KEY[9]);
-            tmp8 = _mm_aesenc_si128(tmp8, KEY[9]);
-            lastKey = KEY[10];
-            if (nr > 10) {
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[10]);
-                tmp2 = _mm_aesenc_si128(tmp2, KEY[10]);
-                tmp3 = _mm_aesenc_si128(tmp3, KEY[10]);
-                tmp4 = _mm_aesenc_si128(tmp4, KEY[10]);
-                tmp5 = _mm_aesenc_si128(tmp5, KEY[10]);
-                tmp6 = _mm_aesenc_si128(tmp6, KEY[10]);
-                tmp7 = _mm_aesenc_si128(tmp7, KEY[10]);
-                tmp8 = _mm_aesenc_si128(tmp8, KEY[10]);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-                tmp2 = _mm_aesenc_si128(tmp2, KEY[11]);
-                tmp3 = _mm_aesenc_si128(tmp3, KEY[11]);
-                tmp4 = _mm_aesenc_si128(tmp4, KEY[11]);
-                tmp5 = _mm_aesenc_si128(tmp5, KEY[11]);
-                tmp6 = _mm_aesenc_si128(tmp6, KEY[11]);
-                tmp7 = _mm_aesenc_si128(tmp7, KEY[11]);
-                tmp8 = _mm_aesenc_si128(tmp8, KEY[11]);
-                lastKey = KEY[12];
-                if (nr > 12) {
-                    tmp1 = _mm_aesenc_si128(tmp1, KEY[12]);
-                    tmp2 = _mm_aesenc_si128(tmp2, KEY[12]);
-                    tmp3 = _mm_aesenc_si128(tmp3, KEY[12]);
-                    tmp4 = _mm_aesenc_si128(tmp4, KEY[12]);
-                    tmp5 = _mm_aesenc_si128(tmp5, KEY[12]);
-                    tmp6 = _mm_aesenc_si128(tmp6, KEY[12]);
-                    tmp7 = _mm_aesenc_si128(tmp7, KEY[12]);
-                    tmp8 = _mm_aesenc_si128(tmp8, KEY[12]);
-                    tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                    tmp2 = _mm_aesenc_si128(tmp2, KEY[13]);
-                    tmp3 = _mm_aesenc_si128(tmp3, KEY[13]);
-                    tmp4 = _mm_aesenc_si128(tmp4, KEY[13]);
-                    tmp5 = _mm_aesenc_si128(tmp5, KEY[13]);
-                    tmp6 = _mm_aesenc_si128(tmp6, KEY[13]);
-                    tmp7 = _mm_aesenc_si128(tmp7, KEY[13]);
-                    tmp8 = _mm_aesenc_si128(tmp8, KEY[13]);
-                    lastKey = KEY[14];
-                }
-            }
-            AES_ENC_LAST_8();
-        }
-    }
-
-#endif /* AES_GCM_AESNI_NO_UNROLL */
-
-    for (k = i*8; k < nbytes/16; k++) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        ctr1 = _mm_add_epi32(ctr1, ONE);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        /* 128 x 128 Carryless Multiply */
-        XV = _mm_loadu_si128(&((__m128i*)in)[k]);
-        XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-        XV = _mm_xor_si128(XV, X);
-        X = gfmul_shifted(XV, H);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        tmp2 = _mm_loadu_si128(&((__m128i*)in)[k]);
-        tmp1 = _mm_xor_si128(tmp1, tmp2);
-        _mm_storeu_si128(&((__m128i*)out)[k], tmp1);
-    }
-
-    /* If one partial block remains */
-    if (nbytes % 16) {
-        tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
-        tmp1 = _mm_xor_si128(tmp1, KEY[0]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[1]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[2]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[3]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[4]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[5]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[6]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[7]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[8]);
-        tmp1 = _mm_aesenc_si128(tmp1, KEY[9]);
-        lastKey = KEY[10];
-        if (nr > 10) {
-            tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-            tmp1 = _mm_aesenc_si128(tmp1, KEY[11]);
-            lastKey = KEY[12];
-            if (nr > 12) {
-                tmp1 = _mm_aesenc_si128(tmp1, lastKey);
-                tmp1 = _mm_aesenc_si128(tmp1, KEY[13]);
-                lastKey = KEY[14];
-            }
-        }
-        tmp1 = _mm_aesenclast_si128(tmp1, lastKey);
-        last_block = _mm_setzero_si128();
-        for (j=0; j < nbytes%16; j++)
-            ((unsigned char*)&last_block)[j] = in[k*16+j];
-        XV = last_block;
-        tmp1 = _mm_xor_si128(tmp1, last_block);
-        last_block = tmp1;
-        for (j=0; j < nbytes%16; j++)
-            out[k*16+j] = ((unsigned char*)&last_block)[j];
-        XV = _mm_shuffle_epi8(XV, BSWAP_MASK);
-        XV = _mm_xor_si128(XV, X);
-        X = gfmul_shifted(XV, H);
-    }
-
-    tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0);
-    tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1);
-    /* 128 x 128 Carryless Multiply */
-    X = _mm_xor_si128(X, tmp1);
-    X = gfmul_shifted(X, H);
-    X = _mm_shuffle_epi8(X, BSWAP_MASK);
-    T = _mm_xor_si128(X, T);
-
-/*    if (0xffff !=
-           _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) */
-    if (XMEMCMP(tag, &T, tbytes) != 0)
-        *res = 0; /* in case the authentication failed */
-    else
-        *res = 1; /* when successful returns 1 */
-}
-
-#endif /* HAVE_AES_DECRYPT */
-#endif /* _MSC_VER */
-#endif /* WOLFSSL_AESNI */
-
-
-#if defined(GCM_SMALL)
-static void GMULT(byte* X, byte* Y)
-{
-    byte Z[AES_BLOCK_SIZE];
-    byte V[AES_BLOCK_SIZE];
-    int i, j;
-
-    XMEMSET(Z, 0, AES_BLOCK_SIZE);
-    XMEMCPY(V, X, AES_BLOCK_SIZE);
-    for (i = 0; i < AES_BLOCK_SIZE; i++)
-    {
-        byte y = Y[i];
-        for (j = 0; j < 8; j++)
-        {
-            if (y & 0x80) {
-                xorbuf(Z, V, AES_BLOCK_SIZE);
-            }
-
-            RIGHTSHIFTX(V);
-            y = y << 1;
-        }
-    }
-    XMEMCPY(X, Z, AES_BLOCK_SIZE);
-}
-
-
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-    word32 cSz, byte* s, word32 sSz)
-{
-    byte x[AES_BLOCK_SIZE];
-    byte scratch[AES_BLOCK_SIZE];
-    word32 blocks, partial;
-    byte* h = aes->H;
-
-    XMEMSET(x, 0, AES_BLOCK_SIZE);
-
-    /* Hash in A, the Additional Authentication Data */
-    if (aSz != 0 && a != NULL) {
-        blocks = aSz / AES_BLOCK_SIZE;
-        partial = aSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            xorbuf(x, a, AES_BLOCK_SIZE);
-            GMULT(x, h);
-            a += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
-            XMEMCPY(scratch, a, partial);
-            xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, h);
-        }
-    }
-
-    /* Hash in C, the Ciphertext */
-    if (cSz != 0 && c != NULL) {
-        blocks = cSz / AES_BLOCK_SIZE;
-        partial = cSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            xorbuf(x, c, AES_BLOCK_SIZE);
-            GMULT(x, h);
-            c += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
-            XMEMCPY(scratch, c, partial);
-            xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, h);
-        }
-    }
-
-    /* Hash in the lengths of A and C in bits */
-    FlattenSzInBits(&scratch[0], aSz);
-    FlattenSzInBits(&scratch[8], cSz);
-    xorbuf(x, scratch, AES_BLOCK_SIZE);
-    GMULT(x, h);
-
-    /* Copy the result into s. */
-    XMEMCPY(s, x, sSz);
-}
-
-/* end GCM_SMALL */
-#elif defined(GCM_TABLE)
-
-static const byte R[256][2] = {
-    {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46},
-    {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e},
-    {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56},
-    {0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e},
-    {0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66},
-    {0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e},
-    {0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76},
-    {0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e},
-    {0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06},
-    {0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e},
-    {0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16},
-    {0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e},
-    {0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26},
-    {0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e},
-    {0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36},
-    {0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e},
-    {0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6},
-    {0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce},
-    {0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6},
-    {0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde},
-    {0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6},
-    {0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee},
-    {0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6},
-    {0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe},
-    {0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86},
-    {0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e},
-    {0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96},
-    {0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e},
-    {0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6},
-    {0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae},
-    {0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6},
-    {0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe},
-    {0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46},
-    {0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e},
-    {0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56},
-    {0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e},
-    {0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66},
-    {0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e},
-    {0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76},
-    {0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e},
-    {0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06},
-    {0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e},
-    {0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16},
-    {0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e},
-    {0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26},
-    {0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e},
-    {0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36},
-    {0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e},
-    {0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6},
-    {0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce},
-    {0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6},
-    {0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde},
-    {0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6},
-    {0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee},
-    {0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6},
-    {0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe},
-    {0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86},
-    {0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e},
-    {0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96},
-    {0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e},
-    {0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6},
-    {0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae},
-    {0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6},
-    {0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} };
-
-
-static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE])
-{
-    int i, j;
-    byte Z[AES_BLOCK_SIZE];
-    byte a;
-
-    XMEMSET(Z, 0, sizeof(Z));
-
-    for (i = 15; i > 0; i--) {
-        xorbuf(Z, m[x[i]], AES_BLOCK_SIZE);
-        a = Z[15];
-
-        for (j = 15; j > 0; j--) {
-            Z[j] = Z[j-1];
-        }
-
-        Z[0] = R[a][0];
-        Z[1] ^= R[a][1];
-    }
-    xorbuf(Z, m[x[0]], AES_BLOCK_SIZE);
-
-    XMEMCPY(x, Z, AES_BLOCK_SIZE);
-}
-
-
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-    word32 cSz, byte* s, word32 sSz)
-{
-    byte x[AES_BLOCK_SIZE];
-    byte scratch[AES_BLOCK_SIZE];
-    word32 blocks, partial;
-
-    XMEMSET(x, 0, AES_BLOCK_SIZE);
-
-    /* Hash in A, the Additional Authentication Data */
-    if (aSz != 0 && a != NULL) {
-        blocks = aSz / AES_BLOCK_SIZE;
-        partial = aSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            xorbuf(x, a, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
-            a += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
-            XMEMCPY(scratch, a, partial);
-            xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
-        }
-    }
-
-    /* Hash in C, the Ciphertext */
-    if (cSz != 0 && c != NULL) {
-        blocks = cSz / AES_BLOCK_SIZE;
-        partial = cSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            xorbuf(x, c, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
-            c += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(scratch, 0, AES_BLOCK_SIZE);
-            XMEMCPY(scratch, c, partial);
-            xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
-        }
-    }
-
-    /* Hash in the lengths of A and C in bits */
-    FlattenSzInBits(&scratch[0], aSz);
-    FlattenSzInBits(&scratch[8], cSz);
-    xorbuf(x, scratch, AES_BLOCK_SIZE);
-    GMULT(x, aes->M0);
-
-    /* Copy the result into s. */
-    XMEMCPY(s, x, sSz);
-}
-
-/* end GCM_TABLE */
-#elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32)
-
-#if !defined(FREESCALE_LTC_AES_GCM)
-static void GMULT(word64* X, word64* Y)
-{
-    word64 Z[2] = {0,0};
-    word64 V[2];
-    int i, j;
-    V[0] = X[0];  V[1] = X[1];
-
-    for (i = 0; i < 2; i++)
-    {
-        word64 y = Y[i];
-        for (j = 0; j < 64; j++)
-        {
-            if (y & 0x8000000000000000ULL) {
-                Z[0] ^= V[0];
-                Z[1] ^= V[1];
-            }
-
-            if (V[1] & 0x0000000000000001) {
-                V[1] >>= 1;
-                V[1] |= ((V[0] & 0x0000000000000001) ?
-                    0x8000000000000000ULL : 0);
-                V[0] >>= 1;
-                V[0] ^= 0xE100000000000000ULL;
-            }
-            else {
-                V[1] >>= 1;
-                V[1] |= ((V[0] & 0x0000000000000001) ?
-                    0x8000000000000000ULL : 0);
-                V[0] >>= 1;
-            }
-            y <<= 1;
-        }
-    }
-    X[0] = Z[0];
-    X[1] = Z[1];
-}
-
-
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-    word32 cSz, byte* s, word32 sSz)
-{
-    word64 x[2] = {0,0};
-    word32 blocks, partial;
-    word64 bigH[2];
-
-    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE);
-    #endif
-
-    /* Hash in A, the Additional Authentication Data */
-    if (aSz != 0 && a != NULL) {
-        word64 bigA[2];
-        blocks = aSz / AES_BLOCK_SIZE;
-        partial = aSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(bigA, a, AES_BLOCK_SIZE);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigA[0];
-            x[1] ^= bigA[1];
-            GMULT(x, bigH);
-            a += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(bigA, 0, AES_BLOCK_SIZE);
-            XMEMCPY(bigA, a, partial);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigA[0];
-            x[1] ^= bigA[1];
-            GMULT(x, bigH);
-        }
-    }
-
-    /* Hash in C, the Ciphertext */
-    if (cSz != 0 && c != NULL) {
-        word64 bigC[2];
-        blocks = cSz / AES_BLOCK_SIZE;
-        partial = cSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(bigC, c, AES_BLOCK_SIZE);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigC[0];
-            x[1] ^= bigC[1];
-            GMULT(x, bigH);
-            c += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(bigC, 0, AES_BLOCK_SIZE);
-            XMEMCPY(bigC, c, partial);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigC[0];
-            x[1] ^= bigC[1];
-            GMULT(x, bigH);
-        }
-    }
-
-    /* Hash in the lengths in bits of A and C */
-    {
-        word64 len[2];
-        len[0] = aSz; len[1] = cSz;
-
-        /* Lengths are in bytes. Convert to bits. */
-        len[0] *= 8;
-        len[1] *= 8;
-
-        x[0] ^= len[0];
-        x[1] ^= len[1];
-        GMULT(x, bigH);
-    }
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords64(x, x, AES_BLOCK_SIZE);
-    #endif
-    XMEMCPY(s, x, sSz);
-}
-#endif /* !FREESCALE_LTC_AES_GCM */
-
-/* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */
-#else /* GCM_WORD32 */
-
-static void GMULT(word32* X, word32* Y)
-{
-    word32 Z[4] = {0,0,0,0};
-    word32 V[4];
-    int i, j;
-
-    V[0] = X[0];  V[1] = X[1]; V[2] =  X[2]; V[3] =  X[3];
-
-    for (i = 0; i < 4; i++)
-    {
-        word32 y = Y[i];
-        for (j = 0; j < 32; j++)
-        {
-            if (y & 0x80000000) {
-                Z[0] ^= V[0];
-                Z[1] ^= V[1];
-                Z[2] ^= V[2];
-                Z[3] ^= V[3];
-            }
-
-            if (V[3] & 0x00000001) {
-                V[3] >>= 1;
-                V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
-                V[2] >>= 1;
-                V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
-                V[1] >>= 1;
-                V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
-                V[0] >>= 1;
-                V[0] ^= 0xE1000000;
-            } else {
-                V[3] >>= 1;
-                V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0);
-                V[2] >>= 1;
-                V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0);
-                V[1] >>= 1;
-                V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0);
-                V[0] >>= 1;
-            }
-            y <<= 1;
-        }
-    }
-    X[0] = Z[0];
-    X[1] = Z[1];
-    X[2] = Z[2];
-    X[3] = Z[3];
-}
-
-
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-    word32 cSz, byte* s, word32 sSz)
-{
-    word32 x[4] = {0,0,0,0};
-    word32 blocks, partial;
-    word32 bigH[4];
-
-    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE);
-    #endif
-
-    /* Hash in A, the Additional Authentication Data */
-    if (aSz != 0 && a != NULL) {
-        word32 bigA[4];
-        blocks = aSz / AES_BLOCK_SIZE;
-        partial = aSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(bigA, a, AES_BLOCK_SIZE);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigA[0];
-            x[1] ^= bigA[1];
-            x[2] ^= bigA[2];
-            x[3] ^= bigA[3];
-            GMULT(x, bigH);
-            a += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(bigA, 0, AES_BLOCK_SIZE);
-            XMEMCPY(bigA, a, partial);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigA[0];
-            x[1] ^= bigA[1];
-            x[2] ^= bigA[2];
-            x[3] ^= bigA[3];
-            GMULT(x, bigH);
-        }
-    }
-
-    /* Hash in C, the Ciphertext */
-    if (cSz != 0 && c != NULL) {
-        word32 bigC[4];
-        blocks = cSz / AES_BLOCK_SIZE;
-        partial = cSz % AES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(bigC, c, AES_BLOCK_SIZE);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigC[0];
-            x[1] ^= bigC[1];
-            x[2] ^= bigC[2];
-            x[3] ^= bigC[3];
-            GMULT(x, bigH);
-            c += AES_BLOCK_SIZE;
-        }
-        if (partial != 0) {
-            XMEMSET(bigC, 0, AES_BLOCK_SIZE);
-            XMEMCPY(bigC, c, partial);
-            #ifdef LITTLE_ENDIAN_ORDER
-                ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE);
-            #endif
-            x[0] ^= bigC[0];
-            x[1] ^= bigC[1];
-            x[2] ^= bigC[2];
-            x[3] ^= bigC[3];
-            GMULT(x, bigH);
-        }
-    }
-
-    /* Hash in the lengths in bits of A and C */
-    {
-        word32 len[4];
-
-        /* Lengths are in bytes. Convert to bits. */
-        len[0] = (aSz >> (8*sizeof(aSz) - 3));
-        len[1] = aSz << 3;
-        len[2] = (cSz >> (8*sizeof(cSz) - 3));
-        len[3] = cSz << 3;
-
-        x[0] ^= len[0];
-        x[1] ^= len[1];
-        x[2] ^= len[2];
-        x[3] ^= len[3];
-        GMULT(x, bigH);
-    }
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords(x, x, AES_BLOCK_SIZE);
-    #endif
-    XMEMCPY(s, x, sSz);
-}
-
-#endif /* end GCM_WORD32 */
-
-
-#if !defined(WOLFSSL_XILINX_CRYPT)
-#ifdef FREESCALE_LTC_AES_GCM
-int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                   const byte* iv, word32 ivSz,
-                   byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    status_t status;
-    word32 keySize;
-
-    /* argument checks */
-    if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
-        WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
-        return BAD_FUNC_ARG;
-    }
-
-    status = wc_AesGetKeySize(aes, &keySize);
-    if (status)
-        return status;
-
-    status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz,
-        authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz);
-
-    return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E;
-}
-#else
-#if defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || \
-                              defined(WOLFSSL_STM32F7) || \
-                              defined(WOLFSSL_STM32L4))
-
-static WC_INLINE int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in,
-                                         word32 sz, const byte* iv, word32 ivSz,
-                                         byte* authTag, word32 authTagSz,
-                                         const byte* authIn, word32 authInSz)
-{
-    int ret;
-    word32 keySize;
-    byte initialCounter[AES_BLOCK_SIZE];
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-    #else
-        byte keyCopy[AES_BLOCK_SIZE * 2];
-    #endif /* WOLFSSL_STM32_CUBEMX */
-    int status = 0;
-    byte* authInPadded = NULL;
-    byte tag[AES_BLOCK_SIZE];
-    int authPadSz;
-
-    ret = wc_AesGetKeySize(aes, &keySize);
-    if (ret != 0)
-        return ret;
-
-    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
-    XMEMCPY(initialCounter, iv, ivSz);
-    initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START;
-
-    /* pad authIn if it is not a block multiple */
-    if ((authInSz % AES_BLOCK_SIZE) != 0) {
-        authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
-        /* Need to pad the AAD to a full block with zeros. */
-        authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (authInPadded == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(authInPadded, 0, authPadSz);
-        XMEMCPY(authInPadded, authIn, authInSz);
-    } else {
-        authPadSz = authInSz;
-        authInPadded = (byte*)authIn;
-    }
-
-
-#ifdef WOLFSSL_STM32_CUBEMX
-    XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-    switch (keySize) {
-        case 16: /* 128-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-            break;
-#ifdef CRYP_KEYSIZE_192B
-        case 24: /* 192-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-            break;
-#endif
-    	case 32: /* 256-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-            break;
-        default:
-            break;
-    }
-    hcryp.Instance = CRYP;
-    hcryp.Init.DataType = CRYP_DATATYPE_8B;
-    hcryp.Init.pKey = (byte*)aes->key;
-    hcryp.Init.pInitVect = initialCounter;
-    hcryp.Init.Header = authInPadded;
-    hcryp.Init.HeaderSize = authInSz;
-
-#ifdef WOLFSSL_STM32L4
-    /* Set the CRYP parameters */
-    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
-    hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
-    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
-    HAL_CRYP_Init(&hcryp);
-
-    /* GCM init phase */
-    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
-    if (status == HAL_OK) {
-        /* GCM header phase */
-        hcryp.Init.GCMCMACPhase  = CRYP_HEADER_PHASE;
-        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
-        if (status == HAL_OK) {
-            /* GCM payload phase */
-            hcryp.Init.GCMCMACPhase  = CRYP_PAYLOAD_PHASE;
-            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, sz, out, STM32_HAL_TIMEOUT);
-            if (status == HAL_OK) {
-                /* GCM final phase */
-                hcryp.Init.GCMCMACPhase  = CRYP_FINAL_PHASE;
-                status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT);
-            }
-        }
-    }
-#else
-    HAL_CRYP_Init(&hcryp);
-
-    status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in, sz,
-                                       out, STM32_HAL_TIMEOUT);
-    /* Compute the authTag */
-    if (status == HAL_OK) {
-        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT);
-    }
-#endif
-
-    if (status != HAL_OK)
-        ret = AES_GCM_AUTH_E;
-    HAL_CRYP_DeInit(&hcryp);
-#else
-    ByteReverseWords((word32*)keyCopy, (word32*)aes->key, keySize);
-    status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)initialCounter,
-                         (uint8_t*)keyCopy,     keySize * 8,
-                         (uint8_t*)in,          sz,
-                         (uint8_t*)authInPadded,authInSz,
-                         (uint8_t*)out,         tag);
-    if (status != SUCCESS)
-        ret = AES_GCM_AUTH_E;
-#endif /* WOLFSSL_STM32_CUBEMX */
-
-    /* authTag may be shorter than AES_BLOCK_SZ, store separately */
-    if (ret == 0)
-    	XMEMCPY(authTag, tag, authTagSz);
-
-    /* We only allocate extra memory if authInPadded is not a multiple of AES_BLOCK_SZ */
-    if (authInPadded != NULL && authInSz != authPadSz) {
-        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return ret;
-}
-#endif /* STM32_CRYPTO */
-
-#ifdef WOLFSSL_AESNI
-int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
-                      const byte* iv, word32 ivSz,
-                      byte* authTag, word32 authTagSz,
-                      const byte* authIn, word32 authInSz);
-#else
-static
-#endif
-int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
-                      const byte* iv, word32 ivSz,
-                      byte* authTag, word32 authTagSz,
-                      const byte* authIn, word32 authInSz)
-{
-    int ret = 0;
-    word32 blocks = sz / AES_BLOCK_SIZE;
-    word32 partial = sz % AES_BLOCK_SIZE;
-    const byte* p = in;
-    byte* c = out;
-    byte counter[AES_BLOCK_SIZE];
-    byte initialCounter[AES_BLOCK_SIZE];
-    byte *ctr;
-    byte scratch[AES_BLOCK_SIZE];
-
-    ctr = counter;
-    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
-    if (ivSz == GCM_NONCE_MID_SZ) {
-        XMEMCPY(initialCounter, iv, ivSz);
-        initialCounter[AES_BLOCK_SIZE - 1] = 1;
-    }
-    else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-    }
-    XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
-
-#ifdef WOLFSSL_PIC32MZ_CRYPT
-    if (blocks) {
-        /* use intitial IV for PIC32 HW, but don't use it below */
-        XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
-
-        ret = wc_Pic32AesCrypt(
-            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
-            out, in, (blocks * AES_BLOCK_SIZE),
-            PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM);
-        if (ret != 0)
-            return ret;
-    }
-    /* process remainder using partial handling */
-#endif
-
-#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
-    /* some hardware acceleration can gain performance from doing AES encryption
-     * of the whole buffer at once */
-    if (c != p) { /* can not handle inline encryption */
-        while (blocks--) {
-            IncrementGcmCounter(ctr);
-            XMEMCPY(c, ctr, AES_BLOCK_SIZE);
-            c += AES_BLOCK_SIZE;
-        }
-
-        /* reset number of blocks and then do encryption */
-        blocks = sz / AES_BLOCK_SIZE;
-        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
-        xorbuf(out, p, AES_BLOCK_SIZE * blocks);
-        p += AES_BLOCK_SIZE * blocks;
-    }
-    else
-#endif /* HAVE_AES_ECB */
-
-    while (blocks--) {
-        IncrementGcmCounter(ctr);
-    #ifndef WOLFSSL_PIC32MZ_CRYPT
-        wc_AesEncrypt(aes, ctr, scratch);
-        xorbuf(scratch, p, AES_BLOCK_SIZE);
-        XMEMCPY(c, scratch, AES_BLOCK_SIZE);
-    #endif
-        p += AES_BLOCK_SIZE;
-        c += AES_BLOCK_SIZE;
-    }
-
-    if (partial != 0) {
-        IncrementGcmCounter(ctr);
-        wc_AesEncrypt(aes, ctr, scratch);
-        xorbuf(scratch, p, partial);
-        XMEMCPY(c, scratch, partial);
-    }
-
-    GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
-    wc_AesEncrypt(aes, initialCounter, scratch);
-    xorbuf(authTag, scratch, authTagSz);
-
-    return ret;
-}
-
-int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                   const byte* iv, word32 ivSz,
-                   byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    /* argument checks */
-    if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
-        WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || \
-                              defined(WOLFSSL_STM32F7) || \
-                              defined(WOLFSSL_STM32L4))
-
-    /* additional argument checks - STM32 HW only supports 12 byte IV */
-    if (ivSz != GCM_NONCE_MID_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* STM32 HW AES-GCM requires / assumes inputs are a multiple of block size.
-     * We can avoid this by zero padding (authIn) AAD, but zero-padded plaintext
-     * will be encrypted and output incorrectly, causing a bad authTag.
-     * We will use HW accelerated AES-GCM if plain%AES_BLOCK_SZ==0.
-     * Otherwise, we will use accelerated AES_CTR for encrypt, and then
-     * perform GHASH in software.
-     * See NIST SP 800-38D */
-
-    /* Plain text is a multiple of block size, so use HW-Accelerated AES_GCM */
-    if (sz % AES_BLOCK_SIZE == 0) {
-        return wc_AesGcmEncrypt_STM32(aes, out, in, sz, iv, ivSz,
-                                      authTag, authTagSz, authIn, authInSz);
-    }
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-    /* if async and byte count above threshold */
-    /* only 12-byte IV is supported in HW */
-    if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
-                    sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) {
-    #if defined(HAVE_CAVIUM)
-        #ifdef HAVE_CAVIUM_V
-        if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */
-            return NitroxAesGcmEncrypt(aes, out, in, sz,
-                (const byte*)aes->asyncKey, aes->keylen, iv, ivSz,
-                authTag, authTagSz, authIn, authInSz);
-        }
-        #endif
-    #elif defined(HAVE_INTEL_QA)
-        return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz,
-            (const byte*)aes->asyncKey, aes->keylen, iv, ivSz,
-            authTag, authTagSz, authIn, authInSz);
-    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-        if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_ENCRYPT)) {
-            WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
-            testDev->aes.aes = aes;
-            testDev->aes.out = out;
-            testDev->aes.in = in;
-            testDev->aes.sz = sz;
-            testDev->aes.iv = iv;
-            testDev->aes.ivSz = ivSz;
-            testDev->aes.authTag = authTag;
-            testDev->aes.authTagSz = authTagSz;
-            testDev->aes.authIn = authIn;
-            testDev->aes.authInSz = authInSz;
-            return WC_PENDING_E;
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* Software AES-GCM */
-
-#ifdef WOLFSSL_AESNI
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(intel_flags)) {
-        AES_GCM_encrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (const byte*)aes->key, aes->rounds);
-        return 0;
-    }
-    else
-    #endif
-    #ifdef HAVE_INTEL_AVX1
-    if (IS_INTEL_AVX1(intel_flags)) {
-        AES_GCM_encrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (const byte*)aes->key, aes->rounds);
-        return 0;
-    }
-    else
-    #endif
-    if (haveAESNI) {
-        AES_GCM_encrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (const byte*)aes->key, aes->rounds);
-        return 0;
-    }
-    else
-#endif
-    {
-        return AES_GCM_encrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
-                                                              authIn, authInSz);
-    }
-}
-#endif
-
-
-#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
-#ifdef FREESCALE_LTC_AES_GCM
-int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                   const byte* iv, word32 ivSz,
-                   const byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    int ret;
-    word32 keySize;
-    status_t status;
-
-    /* argument checks */
-    if (aes == NULL || out == NULL || in == NULL || iv == NULL ||
-        authTag == NULL || authTagSz > AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret = wc_AesGetKeySize(aes, &keySize);
-    if (ret != 0) {
-        return ret;
-    }
-
-    status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz,
-        authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz);
-
-    return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E;
-}
-#elif defined(STM32_CRYPTO) && (defined(WOLFSSL_STM32F4) || \
-                                defined(WOLFSSL_STM32F7) || \
-                                defined(WOLFSSL_STM32L4))
-int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                   const byte* iv, word32 ivSz,
-                   const byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    int ret;
-    word32 keySize;
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-    #else
-        byte keyCopy[AES_BLOCK_SIZE * 2];
-    #endif /* WOLFSSL_STM32_CUBEMX */
-    int  status;
-    int  inPadSz, authPadSz;
-    byte tag[AES_BLOCK_SIZE];
-    byte *inPadded = NULL;
-    byte *authInPadded = NULL;
-    byte initialCounter[AES_BLOCK_SIZE];
-
-    /* argument checks */
-    if (aes == NULL || out == NULL || in == NULL || iv == NULL ||
-        authTag == NULL || authTagSz > AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret = wc_AesGetKeySize(aes, &keySize);
-    if (ret != 0) {
-        return ret;
-    }
-
-    /* additional argument checks - STM32 HW only supports 12 byte IV */
-    if (ivSz != GCM_NONCE_MID_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
-    XMEMCPY(initialCounter, iv, ivSz);
-    initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START;
-
-    /* Need to pad the AAD and input cipher text to a full block size since
-     * CRYP_AES_GCM will assume these are a multiple of AES_BLOCK_SIZE.
-     * It is okay to pad with zeros because GCM does this before GHASH already.
-     * See NIST SP 800-38D */
-
-    if ((sz % AES_BLOCK_SIZE) > 0) {
-        inPadSz = ((sz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
-        inPadded = XMALLOC(inPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (inPadded == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(inPadded, 0, inPadSz);
-        XMEMCPY(inPadded, in, sz);
-    } else {
-        inPadSz = sz;
-        inPadded = (byte*)in;
-    }
-
-    if ((authInSz % AES_BLOCK_SIZE) > 0) {
-        authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
-        authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (authInPadded == NULL) {
-            if (inPadded != NULL && inPadSz != sz)
-                XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-        XMEMSET(authInPadded, 0, authPadSz);
-        XMEMCPY(authInPadded, authIn, authInSz);
-    } else {
-        authPadSz = authInSz;
-        authInPadded = (byte*)authIn;
-    }
-
-#ifdef WOLFSSL_STM32_CUBEMX
-    XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-    switch(keySize) {
-        case 16: /* 128-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
-            break;
-#ifdef CRYP_KEYSIZE_192B
-        case 24: /* 192-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_192B;
-            break;
-#endif
-        case 32: /* 256-bit key */
-            hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
-            break;
-        default:
-            break;
-    }
-    hcryp.Instance = CRYP;
-    hcryp.Init.DataType = CRYP_DATATYPE_8B;
-    hcryp.Init.pKey = (byte*)aes->key;
-    hcryp.Init.pInitVect = initialCounter;
-    hcryp.Init.Header = authInPadded;
-    hcryp.Init.HeaderSize = authInSz;
-
-#ifdef WOLFSSL_STM32L4
-    /* Set the CRYP parameters */
-    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
-    hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT;
-    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
-    HAL_CRYP_Init(&hcryp);
-
-    /* GCM init phase */
-    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
-    if (status == HAL_OK) {
-        /* GCM header phase */
-        hcryp.Init.GCMCMACPhase  = CRYP_HEADER_PHASE;
-        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
-        if (status == HAL_OK) {
-            /* GCM payload phase */
-            hcryp.Init.GCMCMACPhase  = CRYP_PAYLOAD_PHASE;
-            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)inPadded, sz, inPadded,
-                STM32_HAL_TIMEOUT);
-            if (status == HAL_OK) {
-                /* GCM final phase */
-                hcryp.Init.GCMCMACPhase  = CRYP_FINAL_PHASE;
-                status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag,
-                    STM32_HAL_TIMEOUT);
-            }
-        }
-    }
-#else
-    HAL_CRYP_Init(&hcryp);
-    /* Use inPadded for output buffer instead of
-    * out so that we don't overflow our size. */
-    status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)inPadded,
-                                    sz, inPadded, STM32_HAL_TIMEOUT);
-    /* Compute the authTag */
-    if (status == HAL_OK) {
-        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT);
-    }
-#endif
-
-    if (status != HAL_OK)
-        ret = AES_GCM_AUTH_E;
-
-    HAL_CRYP_DeInit(&hcryp);
-#else
-    ByteReverseWords((word32*)keyCopy, (word32*)aes->key, keySize);
-
-    /* Input size and auth size need to be the actual sizes, even though
-     * they are not block aligned, because this length (in bits) is used
-     * in the final GHASH. Use inPadded for output buffer instead of
-     * out so that we don't overflow our size.                         */
-    status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)initialCounter,
-                         (uint8_t*)keyCopy,     keySize * 8,
-                         (uint8_t*)inPadded,    sz,
-                         (uint8_t*)authInPadded,authInSz,
-                         (uint8_t*)inPadded,    tag);
-    if (status != SUCCESS)
-        ret = AES_GCM_AUTH_E;
-#endif /* WOLFSSL_STM32_CUBEMX */
-
-    if (ret == 0 && ConstantCompare(authTag, tag, authTagSz) == 0) {
-        /* Only keep the decrypted data if authTag success. */
-        XMEMCPY(out, inPadded, sz);
-        ret = 0; /* success */
-    }
-
-    /* only allocate padding buffers if the inputs are not a multiple of block sz */
-    if (inPadded != NULL && inPadSz != sz)
-        XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (authInPadded != NULL && authPadSz != authInSz)
-        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return ret;
-}
-#else
-#ifdef WOLFSSL_AESNI
-int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
-                      const byte* iv, word32 ivSz,
-                      const byte* authTag, word32 authTagSz,
-                      const byte* authIn, word32 authInSz);
-#else
-static
-#endif
-int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
-                      const byte* iv, word32 ivSz,
-                      const byte* authTag, word32 authTagSz,
-                      const byte* authIn, word32 authInSz)
-{
-    int ret = 0;
-    word32 blocks = sz / AES_BLOCK_SIZE;
-    word32 partial = sz % AES_BLOCK_SIZE;
-    const byte* c = in;
-    byte* p = out;
-    byte counter[AES_BLOCK_SIZE];
-    byte initialCounter[AES_BLOCK_SIZE];
-    byte *ctr;
-    byte scratch[AES_BLOCK_SIZE];
-    byte Tprime[AES_BLOCK_SIZE];
-    byte EKY0[AES_BLOCK_SIZE];
-    ctr = counter;
-
-    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
-    if (ivSz == GCM_NONCE_MID_SZ) {
-        XMEMCPY(initialCounter, iv, ivSz);
-        initialCounter[AES_BLOCK_SIZE - 1] = 1;
-    }
-    else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-    }
-    XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
-
-    /* Calc the authTag again using the received auth data and the cipher text */
-    GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
-    wc_AesEncrypt(aes, ctr, EKY0);
-    xorbuf(Tprime, EKY0, sizeof(Tprime));
-
-    if (ConstantCompare(authTag, Tprime, authTagSz) != 0) {
-        return AES_GCM_AUTH_E;
-    }
-
-#ifdef WOLFSSL_PIC32MZ_CRYPT
-    if (blocks) {
-        /* use intitial IV for PIC32 HW, but don't use it below */
-        XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
-
-        ret = wc_Pic32AesCrypt(
-            aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE,
-            out, in, (blocks * AES_BLOCK_SIZE),
-            PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM);
-        if (ret != 0)
-            return ret;
-    }
-    /* process remainder using partial handling */
-#endif
-
-#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT)
-    /* some hardware acceleration can gain performance from doing AES encryption
-     * of the whole buffer at once */
-    if (c != p) { /* can not handle inline decryption */
-        while (blocks--) {
-            IncrementGcmCounter(ctr);
-            XMEMCPY(p, ctr, AES_BLOCK_SIZE);
-            p += AES_BLOCK_SIZE;
-        }
-
-        /* reset number of blocks and then do encryption */
-        blocks = sz / AES_BLOCK_SIZE;
-        wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks);
-        xorbuf(out, c, AES_BLOCK_SIZE * blocks);
-        c += AES_BLOCK_SIZE * blocks;
-    }
-    else
-#endif /* HAVE_AES_ECB */
-    while (blocks--) {
-        IncrementGcmCounter(ctr);
-    #ifndef WOLFSSL_PIC32MZ_CRYPT
-        wc_AesEncrypt(aes, ctr, scratch);
-        xorbuf(scratch, c, AES_BLOCK_SIZE);
-        XMEMCPY(p, scratch, AES_BLOCK_SIZE);
-    #endif
-        p += AES_BLOCK_SIZE;
-        c += AES_BLOCK_SIZE;
-    }
-
-    if (partial != 0) {
-        IncrementGcmCounter(ctr);
-        wc_AesEncrypt(aes, ctr, scratch);
-        xorbuf(scratch, c, partial);
-        XMEMCPY(p, scratch, partial);
-    }
-
-    return ret;
-}
-
-int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
-                     const byte* iv, word32 ivSz,
-                     const byte* authTag, word32 authTagSz,
-                     const byte* authIn, word32 authInSz)
-{
-#ifdef WOLFSSL_AESNI
-    int res;
-#endif
-
-    /* argument checks */
-    /* If the sz is non-zero, both in and out must be set. If sz is 0,
-     * in and out are don't cares, as this is is the GMAC case. */
-    if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
-        authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0) {
-
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-    /* if async and byte count above threshold */
-    /* only 12-byte IV is supported in HW */
-    if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES &&
-                    sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) {
-    #if defined(HAVE_CAVIUM)
-        #ifdef HAVE_CAVIUM_V
-        if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */
-            return NitroxAesGcmDecrypt(aes, out, in, sz,
-                (const byte*)aes->asyncKey, aes->keylen, iv, ivSz,
-                authTag, authTagSz, authIn, authInSz);
-        }
-        #endif
-    #elif defined(HAVE_INTEL_QA)
-        return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz,
-            (const byte*)aes->asyncKey, aes->keylen, iv, ivSz,
-            authTag, authTagSz, authIn, authInSz);
-    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-        if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_DECRYPT)) {
-            WC_ASYNC_TEST* testDev = &aes->asyncDev.test;
-            testDev->aes.aes = aes;
-            testDev->aes.out = out;
-            testDev->aes.in = in;
-            testDev->aes.sz = sz;
-            testDev->aes.iv = iv;
-            testDev->aes.ivSz = ivSz;
-            testDev->aes.authTag = (byte*)authTag;
-            testDev->aes.authTagSz = authTagSz;
-            testDev->aes.authIn = authIn;
-            testDev->aes.authInSz = authInSz;
-            return WC_PENDING_E;
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* software AES GCM */
-
-#ifdef WOLFSSL_AESNI
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(intel_flags)) {
-        AES_GCM_decrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
-        if (res == 0)
-            return AES_GCM_AUTH_E;
-        return 0;
-    }
-    else
-    #endif
-    #ifdef HAVE_INTEL_AVX1
-    if (IS_INTEL_AVX1(intel_flags)) {
-        AES_GCM_decrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
-        if (res == 0)
-            return AES_GCM_AUTH_E;
-        return 0;
-    }
-    else
-    #endif
-    if (haveAESNI) {
-        AES_GCM_decrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz,
-                                 authTagSz, (byte*)aes->key, aes->rounds, &res);
-        if (res == 0)
-            return AES_GCM_AUTH_E;
-        return 0;
-    }
-    else
-#endif
-    {
-        return AES_GCM_decrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
-                                                              authIn, authInSz);
-    }
-}
-#endif
-#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
-#endif /* (WOLFSSL_XILINX_CRYPT) */
-#endif /* end of block for AESGCM implementation selection */
-
-
-/* Common to all, abstract functions that build off of lower level AESGCM
- * functions */
-#ifndef WC_NO_RNG
-
-int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz)
-{
-    int ret = 0;
-
-    if (aes == NULL || iv == NULL ||
-        (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ &&
-         ivSz != GCM_NONCE_MAX_SZ)) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        XMEMCPY((byte*)aes->reg, iv, ivSz);
-
-        /* If the IV is 96, allow for a 2^64 invocation counter.
-         * For any other size for the nonce, limit the invocation
-         * counter to 32-bits. (SP 800-38D 8.3) */
-        aes->invokeCtr[0] = 0;
-        aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF;
-        aes->nonceSz = ivSz;
-    }
-
-    return ret;
-}
-
-
-int wc_AesGcmSetIV(Aes* aes, word32 ivSz,
-                   const byte* ivFixed, word32 ivFixedSz,
-                   WC_RNG* rng)
-{
-    int ret = 0;
-
-    if (aes == NULL || rng == NULL ||
-        (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ &&
-         ivSz != GCM_NONCE_MAX_SZ) ||
-        (ivFixed == NULL && ivFixedSz != 0) ||
-        (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        byte* iv = (byte*)aes->reg;
-
-        if (ivFixedSz)
-            XMEMCPY(iv, ivFixed, ivFixedSz);
-
-        ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz);
-    }
-
-    if (ret == 0) {
-        /* If the IV is 96, allow for a 2^64 invocation counter.
-         * For any other size for the nonce, limit the invocation
-         * counter to 32-bits. (SP 800-38D 8.3) */
-        aes->invokeCtr[0] = 0;
-        aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF;
-        aes->nonceSz = ivSz;
-    }
-
-    return ret;
-}
-
-
-int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
-                        byte* ivOut, word32 ivOutSz,
-                        byte* authTag, word32 authTagSz,
-                        const byte* authIn, word32 authInSz)
-{
-    int ret = 0;
-
-    if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
-        ivOut == NULL || ivOutSz != aes->nonceSz ||
-        (authIn == NULL && authInSz != 0)) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        aes->invokeCtr[0]++;
-        if (aes->invokeCtr[0] == 0) {
-            aes->invokeCtr[1]++;
-            if (aes->invokeCtr[1] == 0)
-                ret = AES_GCM_OVERFLOW_E;
-        }
-    }
-
-    if (ret == 0) {
-        XMEMCPY(ivOut, aes->reg, ivOutSz);
-        ret = wc_AesGcmEncrypt(aes, out, in, sz,
-                               (byte*)aes->reg, ivOutSz,
-                               authTag, authTagSz,
-                               authIn, authInSz);
-        IncCtr((byte*)aes->reg, ivOutSz);
-    }
-
-    return ret;
-}
-
-int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
-            const byte* authIn, word32 authInSz,
-            byte* authTag, word32 authTagSz, WC_RNG* rng)
-{
-    Aes aes;
-    int ret = 0;
-
-    if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
-        authTag == NULL || authTagSz == 0 || rng == NULL) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0)
-        ret = wc_AesGcmSetKey(&aes, key, keySz);
-    if (ret == 0)
-        ret = wc_AesGcmSetIV(&aes, ivSz, NULL, 0, rng);
-    if (ret == 0)
-        ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz,
-                                  authTag, authTagSz, authIn, authInSz);
-    ForceZero(&aes, sizeof(aes));
-
-    return ret;
-}
-
-int wc_GmacVerify(const byte* key, word32 keySz,
-                  const byte* iv, word32 ivSz,
-                  const byte* authIn, word32 authInSz,
-                  const byte* authTag, word32 authTagSz)
-{
-    Aes aes;
-    int ret = 0;
-
-    if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
-        authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0)
-        ret = wc_AesGcmSetKey(&aes, key, keySz);
-    if (ret == 0)
-        ret = wc_AesGcmDecrypt(&aes, NULL, NULL, 0, iv, ivSz,
-                                  authTag, authTagSz, authIn, authInSz);
-    ForceZero(&aes, sizeof(aes));
-
-    return ret;
-}
-
-#endif /* WC_NO_RNG */
-
-
-WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
-{
-    if (gmac == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return wc_AesGcmSetKey(&gmac->aes, key, len);
-}
-
-
-WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
-                              const byte* authIn, word32 authInSz,
-                              byte* authTag, word32 authTagSz)
-{
-    return wc_AesGcmEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz,
-                                         authTag, authTagSz, authIn, authInSz);
-}
-
-#endif /* HAVE_AESGCM */
-
-
-#ifdef HAVE_AESCCM
-
-int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
-{
-    if (!((keySz == 16) || (keySz == 24) || (keySz == 32)))
-        return BAD_FUNC_ARG;
-
-    return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION);
-}
-
-#ifdef WOLFSSL_ARMASM
-    /* implementation located in wolfcrypt/src/port/arm/armv8-aes.c */
-
-#elif defined(HAVE_COLDFIRE_SEC)
-    #error "Coldfire SEC doesn't currently support AES-CCM mode"
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-    /* implemented in wolfcrypt/src/port/caam_aes.c */
-
-#elif defined(FREESCALE_LTC)
-
-/* return 0 on success */
-int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
-                   const byte* nonce, word32 nonceSz,
-                   byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    byte *key;
-    uint32_t keySize;
-    status_t status;
-
-    /* sanity check on arguments */
-    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-            || authTag == NULL || nonceSz < 7 || nonceSz > 13)
-        return BAD_FUNC_ARG;
-
-    key = (byte*)aes->key;
-
-    status = wc_AesGetKeySize(aes, &keySize);
-    if (status != 0) {
-        return status;
-    }
-
-    status = LTC_AES_EncryptTagCcm(LTC_BASE, in, out, inSz,
-        nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz);
-
-    return (kStatus_Success == status) ? 0 : BAD_FUNC_ARG;
-}
-
-#ifdef HAVE_AES_DECRYPT
-int  wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
-                   const byte* nonce, word32 nonceSz,
-                   const byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    byte *key;
-    uint32_t keySize;
-    status_t status;
-
-    /* sanity check on arguments */
-    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-            || authTag == NULL || nonceSz < 7 || nonceSz > 13)
-        return BAD_FUNC_ARG;
-
-    key = (byte*)aes->key;
-
-    status = wc_AesGetKeySize(aes, &keySize);
-    if (status != 0) {
-        return status;
-    }
-
-    status = LTC_AES_DecryptTagCcm(LTC_BASE, in, out, inSz,
-        nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz);
-
-    if (status == kStatus_Success) {
-        return 0;
-    }
-    else {
-        XMEMSET(out, 0, inSz);
-        return AES_CCM_AUTH_E;
-    }
-}
-#endif /* HAVE_AES_DECRYPT */
-
-
-/* software AES CCM */
-#else
-
-static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out)
-{
-    /* process the bulk of the data */
-    while (inSz >= AES_BLOCK_SIZE) {
-        xorbuf(out, in, AES_BLOCK_SIZE);
-        in += AES_BLOCK_SIZE;
-        inSz -= AES_BLOCK_SIZE;
-
-        wc_AesEncrypt(aes, out, out);
-    }
-
-    /* process remainder of the data */
-    if (inSz > 0) {
-        xorbuf(out, in, inSz);
-        wc_AesEncrypt(aes, out, out);
-    }
-}
-
-static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out)
-{
-    word32 authLenSz;
-    word32 remainder;
-
-    /* encode the length in */
-    if (inSz <= 0xFEFF) {
-        authLenSz = 2;
-        out[0] ^= ((inSz & 0xFF00) >> 8);
-        out[1] ^=  (inSz & 0x00FF);
-    }
-    else if (inSz <= 0xFFFFFFFF) {
-        authLenSz = 6;
-        out[0] ^= 0xFF; out[1] ^= 0xFE;
-        out[2] ^= ((inSz & 0xFF000000) >> 24);
-        out[3] ^= ((inSz & 0x00FF0000) >> 16);
-        out[4] ^= ((inSz & 0x0000FF00) >>  8);
-        out[5] ^=  (inSz & 0x000000FF);
-    }
-    /* Note, the protocol handles auth data up to 2^64, but we are
-     * using 32-bit sizes right now, so the bigger data isn't handled
-     * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */
-    else
-        return;
-
-    /* start fill out the rest of the first block */
-    remainder = AES_BLOCK_SIZE - authLenSz;
-    if (inSz >= remainder) {
-        /* plenty of bulk data to fill the remainder of this block */
-        xorbuf(out + authLenSz, in, remainder);
-        inSz -= remainder;
-        in += remainder;
-    }
-    else {
-        /* not enough bulk data, copy what is available, and pad zero */
-        xorbuf(out + authLenSz, in, inSz);
-        inSz = 0;
-    }
-    wc_AesEncrypt(aes, out, out);
-
-    if (inSz > 0)
-        roll_x(aes, in, inSz, out);
-}
-
-
-static WC_INLINE void AesCcmCtrInc(byte* B, word32 lenSz)
-{
-    word32 i;
-
-    for (i = 0; i < lenSz; i++) {
-        if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return;
-    }
-}
-
-/* return 0 on success */
-int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
-                   const byte* nonce, word32 nonceSz,
-                   byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    byte A[AES_BLOCK_SIZE];
-    byte B[AES_BLOCK_SIZE];
-    byte lenSz;
-    word32 i;
-    byte mask = 0xFF;
-    const word32 wordSz = (word32)sizeof(word32);
-
-    /* sanity check on arguments */
-    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-            || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
-            authTagSz > AES_BLOCK_SIZE)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(B+1, nonce, nonceSz);
-    lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
-    B[0] = (authInSz > 0 ? 64 : 0)
-         + (8 * (((byte)authTagSz - 2) / 2))
-         + (lenSz - 1);
-    for (i = 0; i < lenSz; i++) {
-        if (mask && i >= wordSz)
-            mask = 0x00;
-        B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
-    }
-
-    wc_AesEncrypt(aes, B, A);
-
-    if (authInSz > 0)
-        roll_auth(aes, authIn, authInSz, A);
-    if (inSz > 0)
-        roll_x(aes, in, inSz, A);
-    XMEMCPY(authTag, A, authTagSz);
-
-    B[0] = lenSz - 1;
-    for (i = 0; i < lenSz; i++)
-        B[AES_BLOCK_SIZE - 1 - i] = 0;
-    wc_AesEncrypt(aes, B, A);
-    xorbuf(authTag, A, authTagSz);
-
-    B[15] = 1;
-    while (inSz >= AES_BLOCK_SIZE) {
-        wc_AesEncrypt(aes, B, A);
-        xorbuf(A, in, AES_BLOCK_SIZE);
-        XMEMCPY(out, A, AES_BLOCK_SIZE);
-
-        AesCcmCtrInc(B, lenSz);
-        inSz -= AES_BLOCK_SIZE;
-        in += AES_BLOCK_SIZE;
-        out += AES_BLOCK_SIZE;
-    }
-    if (inSz > 0) {
-        wc_AesEncrypt(aes, B, A);
-        xorbuf(A, in, inSz);
-        XMEMCPY(out, A, inSz);
-    }
-
-    ForceZero(A, AES_BLOCK_SIZE);
-    ForceZero(B, AES_BLOCK_SIZE);
-
-    return 0;
-}
-
-#ifdef HAVE_AES_DECRYPT
-int  wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
-                   const byte* nonce, word32 nonceSz,
-                   const byte* authTag, word32 authTagSz,
-                   const byte* authIn, word32 authInSz)
-{
-    byte A[AES_BLOCK_SIZE];
-    byte B[AES_BLOCK_SIZE];
-    byte* o;
-    byte lenSz;
-    word32 i, oSz;
-    int result = 0;
-    byte mask = 0xFF;
-    const word32 wordSz = (word32)sizeof(word32);
-
-    /* sanity check on arguments */
-    if (aes == NULL || out == NULL || in == NULL || nonce == NULL
-            || authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
-            authTagSz > AES_BLOCK_SIZE)
-        return BAD_FUNC_ARG;
-
-    o = out;
-    oSz = inSz;
-    XMEMCPY(B+1, nonce, nonceSz);
-    lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
-
-    B[0] = lenSz - 1;
-    for (i = 0; i < lenSz; i++)
-        B[AES_BLOCK_SIZE - 1 - i] = 0;
-    B[15] = 1;
-
-    while (oSz >= AES_BLOCK_SIZE) {
-        wc_AesEncrypt(aes, B, A);
-        xorbuf(A, in, AES_BLOCK_SIZE);
-        XMEMCPY(o, A, AES_BLOCK_SIZE);
-
-        AesCcmCtrInc(B, lenSz);
-        oSz -= AES_BLOCK_SIZE;
-        in += AES_BLOCK_SIZE;
-        o += AES_BLOCK_SIZE;
-    }
-    if (inSz > 0) {
-        wc_AesEncrypt(aes, B, A);
-        xorbuf(A, in, oSz);
-        XMEMCPY(o, A, oSz);
-    }
-
-    for (i = 0; i < lenSz; i++)
-        B[AES_BLOCK_SIZE - 1 - i] = 0;
-    wc_AesEncrypt(aes, B, A);
-
-    o = out;
-    oSz = inSz;
-
-    B[0] = (authInSz > 0 ? 64 : 0)
-         + (8 * (((byte)authTagSz - 2) / 2))
-         + (lenSz - 1);
-    for (i = 0; i < lenSz; i++) {
-        if (mask && i >= wordSz)
-            mask = 0x00;
-        B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
-    }
-
-    wc_AesEncrypt(aes, B, A);
-
-    if (authInSz > 0)
-        roll_auth(aes, authIn, authInSz, A);
-    if (inSz > 0)
-        roll_x(aes, o, oSz, A);
-
-    B[0] = lenSz - 1;
-    for (i = 0; i < lenSz; i++)
-        B[AES_BLOCK_SIZE - 1 - i] = 0;
-    wc_AesEncrypt(aes, B, B);
-    xorbuf(A, B, authTagSz);
-
-    if (ConstantCompare(A, authTag, authTagSz) != 0) {
-        /* If the authTag check fails, don't keep the decrypted data.
-         * Unfortunately, you need the decrypted data to calculate the
-         * check value. */
-        XMEMSET(out, 0, inSz);
-        result = AES_CCM_AUTH_E;
-    }
-
-    ForceZero(A, AES_BLOCK_SIZE);
-    ForceZero(B, AES_BLOCK_SIZE);
-    o = NULL;
-
-    return result;
-}
-
-#endif /* HAVE_AES_DECRYPT */
-#endif /* software AES CCM */
-
-/* abstract functions that call lower level AESCCM functions */
-#ifndef WC_NO_RNG
-
-int wc_AesCcmSetNonce(Aes* aes, const byte* nonce, word32 nonceSz)
-{
-    int ret = 0;
-
-    if (aes == NULL || nonce == NULL ||
-        nonceSz < CCM_NONCE_MIN_SZ || nonceSz > CCM_NONCE_MAX_SZ) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        XMEMCPY(aes->reg, nonce, nonceSz);
-        aes->nonceSz = nonceSz;
-
-        /* Invocation counter should be 2^61 */
-        aes->invokeCtr[0] = 0;
-        aes->invokeCtr[1] = 0xE0000000;
-    }
-
-    return ret;
-}
-
-
-int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
-                        byte* ivOut, word32 ivOutSz,
-                        byte* authTag, word32 authTagSz,
-                        const byte* authIn, word32 authInSz)
-{
-    int ret = 0;
-
-    if (aes == NULL || out == NULL ||
-        (in == NULL && sz != 0) ||
-        ivOut == NULL ||
-        (authIn == NULL && authInSz != 0) ||
-        (ivOutSz != aes->nonceSz)) {
-
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        aes->invokeCtr[0]++;
-        if (aes->invokeCtr[0] == 0) {
-            aes->invokeCtr[1]++;
-            if (aes->invokeCtr[1] == 0)
-                ret = AES_CCM_OVERFLOW_E;
-        }
-    }
-
-    if (ret == 0) {
-        ret = wc_AesCcmEncrypt(aes, out, in, sz,
-                               (byte*)aes->reg, aes->nonceSz,
-                               authTag, authTagSz,
-                               authIn, authInSz);
-        XMEMCPY(ivOut, aes->reg, aes->nonceSz);
-        IncCtr((byte*)aes->reg, aes->nonceSz);
-    }
-
-    return ret;
-}
-
-#endif /* WC_NO_RNG */
-
-#endif /* HAVE_AESCCM */
-
-
-/* Initialize Aes for use with async hardware */
-int wc_AesInit(Aes* aes, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (aes == NULL)
-        return BAD_FUNC_ARG;
-
-    aes->heap = heap;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-    ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES,
-                                                        aes->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-/* Free Aes from use with async hardware */
-void wc_AesFree(Aes* aes)
-{
-    if (aes == NULL)
-        return;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)
-    wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-
-int wc_AesGetKeySize(Aes* aes, word32* keySize)
-{
-    int ret = 0;
-
-    if (aes == NULL || keySize == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    switch (aes->rounds) {
-    #ifdef WOLFSSL_AES_128
-    case 10:
-        *keySize = 16;
-        break;
-    #endif
-    #ifdef WOLFSSL_AES_192
-    case 12:
-        *keySize = 24;
-        break;
-    #endif
-    #ifdef WOLFSSL_AES_256
-    case 14:
-        *keySize = 32;
-        break;
-    #endif
-    default:
-        *keySize = 0;
-        ret = BAD_FUNC_ARG;
-    }
-
-    return ret;
-}
-
-#endif /* !WOLFSSL_TI_CRYPT */
-
-#ifdef HAVE_AES_ECB
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)
-    /* implemented in wolfcrypt/src/port/caam/caam_aes.c */
-#else
-
-/* software implementation */
-int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-{
-    word32 blocks = sz / AES_BLOCK_SIZE;
-
-    if ((in == NULL) || (out == NULL) || (aes == NULL))
-      return BAD_FUNC_ARG;
-    while (blocks>0) {
-      wc_AesEncryptDirect(aes, out, in);
-      out += AES_BLOCK_SIZE;
-      in  += AES_BLOCK_SIZE;
-      sz  -= AES_BLOCK_SIZE;
-      blocks--;
-    }
-    return 0;
-}
-
-
-int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-{
-    word32 blocks = sz / AES_BLOCK_SIZE;
-
-    if ((in == NULL) || (out == NULL) || (aes == NULL))
-      return BAD_FUNC_ARG;
-    while (blocks>0) {
-      wc_AesDecryptDirect(aes, out, in);
-      out += AES_BLOCK_SIZE;
-      in  += AES_BLOCK_SIZE;
-      sz  -= AES_BLOCK_SIZE;
-      blocks--;
-    }
-    return 0;
-}
-#endif
-#endif /* HAVE_AES_ECB */
-
-#ifdef WOLFSSL_AES_CFB
-/* CFB 128
- *
- * aes structure holding key to use for encryption
- * out buffer to hold result of encryption (must be at least as large as input
- *     buffer)
- * in  buffer to encrypt
- * sz  size of input buffer
- *
- * returns 0 on success and negative error values on failure
- */
-int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-{
-    byte*  tmp = NULL;
-    byte*  reg = NULL;
-
-    WOLFSSL_ENTER("wc_AesCfbEncrypt");
-
-    if (aes == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (aes->left && sz) {
-        reg = (byte*)aes->reg + AES_BLOCK_SIZE - aes->left;
-    }
-
-    /* consume any unused bytes left in aes->tmp */
-    tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
-    while (aes->left && sz) {
-        *(out++) = *(reg++) = *(in++) ^ *(tmp++);
-        aes->left--;
-        sz--;
-    }
-
-    while (sz >= AES_BLOCK_SIZE) {
-        wc_AesEncryptDirect(aes, out, (byte*)aes->reg);
-        xorbuf(out, in, AES_BLOCK_SIZE);
-        XMEMCPY(aes->reg, out, AES_BLOCK_SIZE);
-        out += AES_BLOCK_SIZE;
-        in  += AES_BLOCK_SIZE;
-        sz  -= AES_BLOCK_SIZE;
-        aes->left = 0;
-    }
-
-    /* encrypt left over data */
-    if (sz) {
-        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
-        aes->left = AES_BLOCK_SIZE;
-        tmp = (byte*)aes->tmp;
-        reg = (byte*)aes->reg;
-
-        while (sz--) {
-            *(out++) = *(reg++) = *(in++) ^ *(tmp++);
-            aes->left--;
-        }
-    }
-
-    return 0;
-}
-
-
-#ifdef HAVE_AES_DECRYPT
-/* CFB 128
- *
- * aes structure holding key to use for decryption
- * out buffer to hold result of decryption (must be at least as large as input
- *     buffer)
- * in  buffer to decrypt
- * sz  size of input buffer
- *
- * returns 0 on success and negative error values on failure
- */
-int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
-{
-    byte*  tmp;
-
-    WOLFSSL_ENTER("wc_AesCfbDecrypt");
-
-    if (aes == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* check if more input needs copied over to aes->reg */
-    if (aes->left && sz) {
-        int size = min(aes->left, sz);
-        XMEMCPY((byte*)aes->reg + AES_BLOCK_SIZE - aes->left, in, size);
-    }
-
-    /* consume any unused bytes left in aes->tmp */
-    tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
-    while (aes->left && sz) {
-        *(out++) = *(in++) ^ *(tmp++);
-        aes->left--;
-        sz--;
-    }
-
-    while (sz > AES_BLOCK_SIZE) {
-        wc_AesEncryptDirect(aes, out, (byte*)aes->reg);
-        xorbuf(out, in, AES_BLOCK_SIZE);
-        XMEMCPY(aes->reg, in, AES_BLOCK_SIZE);
-        out += AES_BLOCK_SIZE;
-        in  += AES_BLOCK_SIZE;
-        sz  -= AES_BLOCK_SIZE;
-        aes->left = 0;
-    }
-
-    /* decrypt left over data */
-    if (sz) {
-        wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
-        XMEMCPY(aes->reg, in, sz);
-        aes->left = AES_BLOCK_SIZE;
-        tmp = (byte*)aes->tmp;
-
-        while (sz--) {
-            *(out++) = *(in++) ^ *(tmp++);
-            aes->left--;
-        }
-    }
-
-    return 0;
-}
-#endif /* HAVE_AES_DECRYPT */
-#endif /* WOLFSSL_AES_CFB */
-
-
-#ifdef HAVE_AES_KEYWRAP
-
-/* Initialize key wrap counter with value */
-static WC_INLINE void InitKeyWrapCounter(byte* inOutCtr, word32 value)
-{
-    int i;
-    word32 bytes;
-
-    bytes = sizeof(word32);
-    for (i = 0; i < (int)sizeof(word32); i++) {
-        inOutCtr[i+sizeof(word32)] = (value >> ((bytes - 1) * 8)) & 0xFF;
-        bytes--;
-    }
-}
-
-/* Increment key wrap counter */
-static WC_INLINE void IncrementKeyWrapCounter(byte* inOutCtr)
-{
-    int i;
-
-    /* in network byte order so start at end and work back */
-    for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
-        if (++inOutCtr[i])  /* we're done unless we overflow */
-            return;
-    }
-}
-
-/* Decrement key wrap counter */
-static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr)
-{
-    int i;
-
-    for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) {
-        if (--inOutCtr[i] != 0xFF)  /* we're done unless we underflow */
-            return;
-    }
-}
-
-/* perform AES key wrap (RFC3394), return out sz on success, negative on err */
-int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
-                  byte* out, word32 outSz, const byte* iv)
-{
-    Aes aes;
-    byte* r;
-    word32 i;
-    int ret, j;
-
-    byte t[KEYWRAP_BLOCK_SIZE];
-    byte tmp[AES_BLOCK_SIZE];
-
-    /* n must be at least 2, output size is n + 8 bytes */
-    if (key == NULL || in  == NULL || inSz < 2 ||
-        out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE))
-        return BAD_FUNC_ARG;
-
-    /* input must be multiple of 64-bits */
-    if (inSz % KEYWRAP_BLOCK_SIZE != 0)
-        return BAD_FUNC_ARG;
-
-    /* user IV is optional */
-    if (iv == NULL) {
-        XMEMSET(tmp, 0xA6, KEYWRAP_BLOCK_SIZE);
-    } else {
-        XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE);
-    }
-
-    r = out + 8;
-    XMEMCPY(r, in, inSz);
-    XMEMSET(t, 0, sizeof(t));
-
-    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
-    if (ret != 0)
-        return ret;
-
-    ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_ENCRYPTION);
-    if (ret != 0)
-        return ret;
-
-    for (j = 0; j <= 5; j++) {
-        for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) {
-
-            /* load R[i] */
-            XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
-
-            wc_AesEncryptDirect(&aes, tmp, tmp);
-
-            /* calculate new A */
-            IncrementKeyWrapCounter(t);
-            xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
-
-            /* save R[i] */
-            XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
-            r += KEYWRAP_BLOCK_SIZE;
-        }
-        r = out + KEYWRAP_BLOCK_SIZE;
-    }
-
-    /* C[0] = A */
-    XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE);
-
-    wc_AesFree(&aes);
-
-    return inSz + KEYWRAP_BLOCK_SIZE;
-}
-
-int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
-                    byte* out, word32 outSz, const byte* iv)
-{
-    Aes aes;
-    byte* r;
-    word32 i, n;
-    int ret, j;
-
-    byte t[KEYWRAP_BLOCK_SIZE];
-    byte tmp[AES_BLOCK_SIZE];
-
-    const byte* expIv;
-    const byte defaultIV[] = {
-        0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
-    };
-
-    (void)iv;
-
-    if (key == NULL || in == NULL || inSz < 3 ||
-        out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE))
-        return BAD_FUNC_ARG;
-
-    /* input must be multiple of 64-bits */
-    if (inSz % KEYWRAP_BLOCK_SIZE != 0)
-        return BAD_FUNC_ARG;
-
-    /* user IV optional */
-    if (iv != NULL) {
-        expIv = iv;
-    } else {
-        expIv = defaultIV;
-    }
-
-    /* A = C[0], R[i] = C[i] */
-    XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE);
-    XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE);
-    XMEMSET(t, 0, sizeof(t));
-
-    ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
-    if (ret != 0)
-        return ret;
-
-    ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_DECRYPTION);
-    if (ret != 0)
-        return ret;
-
-    /* initialize counter to 6n */
-    n = (inSz - 1) / KEYWRAP_BLOCK_SIZE;
-    InitKeyWrapCounter(t, 6 * n);
-
-    for (j = 5; j >= 0; j--) {
-        for (i = n; i >= 1; i--) {
-
-            /* calculate A */
-            xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE);
-            DecrementKeyWrapCounter(t);
-
-            /* load R[i], starting at end of R */
-            r = out + ((i - 1) * KEYWRAP_BLOCK_SIZE);
-            XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
-            wc_AesDecryptDirect(&aes, tmp, tmp);
-
-            /* save R[i] */
-            XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE);
-        }
-    }
-
-    wc_AesFree(&aes);
-
-    /* verify IV */
-    if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
-        return BAD_KEYWRAP_IV_E;
-
-    return inSz - KEYWRAP_BLOCK_SIZE;
-}
-
-#endif /* HAVE_AES_KEYWRAP */
-
-#ifdef WOLFSSL_AES_XTS
-
-/* Galios Field to use */
-#define GF_XTS 0x87
-
-/* This is to help with setting keys to correct encrypt or decrypt type.
- *
- * tweak AES key for tweak in XTS
- * aes   AES key for encrypt/decrypt process
- * key   buffer holding aes key | tweak key
- * len   length of key buffer in bytes. Should be twice that of key size. i.e.
- *       32 for a 16 byte key.
- * dir   direction, either AES_ENCRYPTION or AES_DECRYPTION
- * heap  heap hint to use for memory. Can be NULL
- * devId id to use with async crypto. Can be 0
- *
- * Note: is up to user to call wc_AesFree on tweak and aes key when done.
- *
- * return 0 on success
- */
-int wc_AesXtsSetKey(XtsAes* aes, const byte* key, word32 len, int dir,
-        void* heap, int devId)
-{
-    word32 keySz;
-    int    ret = 0;
-
-    if (aes == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) {
-        return ret;
-    }
-    if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) {
-        return ret;
-    }
-
-    keySz = len/2;
-    if (keySz != 16 && keySz != 32) {
-        WOLFSSL_MSG("Unsupported key size");
-        return WC_KEY_SIZE_E;
-    }
-
-    if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) {
-        ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL,
-                AES_ENCRYPTION);
-        if (ret != 0) {
-            wc_AesFree(&aes->aes);
-        }
-    }
-
-    return ret;
-}
-
-
-/* This is used to free up resources used by Aes structs
- *
- * aes AES keys to free
- *
- * return 0 on success
- */
-int wc_AesXtsFree(XtsAes* aes)
-{
-    if (aes != NULL) {
-        wc_AesFree(&aes->aes);
-        wc_AesFree(&aes->tweak);
-    }
-
-    return 0;
-}
-
-
-/* Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak value
- * instead of a byte array. This just converts the word64 to a byte array and
- * calls wc_AesXtsEncrypt.
- *
- * aes    AES keys to use for block encrypt/decrypt
- * out    output buffer to hold cipher text
- * in     input plain text buffer to encrypt
- * sz     size of both out and in buffers
- * sector value to use for tweak
- *
- * returns 0 on success
- */
-int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, const byte* in,
-        word32 sz, word64 sector)
-{
-    byte* pt;
-    byte  i[AES_BLOCK_SIZE];
-
-    XMEMSET(i, 0, AES_BLOCK_SIZE);
-#ifdef BIG_ENDIAN_ORDER
-    sector = ByteReverseWord64(sector);
-#endif
-    pt = (byte*)&sector;
-    XMEMCPY(i, pt, sizeof(word64));
-
-    return wc_AesXtsEncrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE);
-}
-
-
-/* Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak value
- * instead of a byte array. This just converts the word64 to a byte array.
- *
- * aes    AES keys to use for block encrypt/decrypt
- * out    output buffer to hold plain text
- * in     input cipher text buffer to encrypt
- * sz     size of both out and in buffers
- * sector value to use for tweak
- *
- * returns 0 on success
- */
-int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, const byte* in, word32 sz,
-        word64 sector)
-{
-    byte* pt;
-    byte  i[AES_BLOCK_SIZE];
-
-    XMEMSET(i, 0, AES_BLOCK_SIZE);
-#ifdef BIG_ENDIAN_ORDER
-    sector = ByteReverseWord64(sector);
-#endif
-    pt = (byte*)&sector;
-    XMEMCPY(i, pt, sizeof(word64));
-
-    return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE);
-}
-
-#ifdef HAVE_AES_ECB
-/* helper function for encrypting / decrypting full buffer at once */
-static int _AesXtsHelper(Aes* aes, byte* out, const byte* in, word32 sz, int dir)
-{
-    word32 outSz   = sz;
-    word32 totalSz = (sz / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; /* total bytes */
-    byte*  pt      = out;
-
-    outSz -= AES_BLOCK_SIZE;
-
-    while (outSz > 0) {
-        word32 j;
-        byte carry = 0;
-
-        /* multiply by shift left and propogate carry */
-        for (j = 0; j < AES_BLOCK_SIZE && outSz > 0; j++, outSz--) {
-            byte tmpC;
-
-            tmpC   = (pt[j] >> 7) & 0x01;
-            pt[j+AES_BLOCK_SIZE] = ((pt[j] << 1) + carry) & 0xFF;
-            carry  = tmpC;
-        }
-        if (carry) {
-            pt[AES_BLOCK_SIZE] ^= GF_XTS;
-        }
-
-        pt += AES_BLOCK_SIZE;
-    }
-
-    xorbuf(out, in, totalSz);
-    if (dir == AES_ENCRYPTION) {
-        return wc_AesEcbEncrypt(aes, out, out, totalSz);
-    }
-    else {
-        return wc_AesEcbDecrypt(aes, out, out, totalSz);
-    }
-}
-#endif /* HAVE_AES_ECB */
-
-
-/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing.
- *
- * xaes  AES keys to use for block encrypt/decrypt
- * out   output buffer to hold cipher text
- * in    input plain text buffer to encrypt
- * sz    size of both out and in buffers
- * i     value to use for tweak
- * iSz   size of i buffer, should always be AES_BLOCK_SIZE but having this input
- *       adds a sanity check on how the user calls the function.
- *
- * returns 0 on success
- */
-int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
-        const byte* i, word32 iSz)
-{
-    int ret = 0;
-    word32 blocks = (sz / AES_BLOCK_SIZE);
-    Aes *aes, *tweak;
-
-    if (xaes == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    aes   = &xaes->aes;
-    tweak = &xaes->tweak;
-
-    if (iSz < AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (blocks > 0) {
-        byte tmp[AES_BLOCK_SIZE];
-
-        XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
-                                          * key setup passed to encrypt direct*/
-
-        wc_AesEncryptDirect(tweak, tmp, i);
-
-    #ifdef HAVE_AES_ECB
-        /* encrypt all of buffer at once when possible */
-        if (in != out) { /* can not handle inline */
-            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
-            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) {
-                return ret;
-            }
-        }
-    #endif
-
-        while (blocks > 0) {
-            word32 j;
-            byte carry = 0;
-            byte buf[AES_BLOCK_SIZE];
-
-    #ifdef HAVE_AES_ECB
-            if (in == out) { /* check for if inline */
-    #endif
-            XMEMCPY(buf, in, AES_BLOCK_SIZE);
-            xorbuf(buf, tmp, AES_BLOCK_SIZE);
-            wc_AesEncryptDirect(aes, out, buf);
-    #ifdef HAVE_AES_ECB
-            }
-    #endif
-            xorbuf(out, tmp, AES_BLOCK_SIZE);
-
-            /* multiply by shift left and propogate carry */
-            for (j = 0; j < AES_BLOCK_SIZE; j++) {
-                byte tmpC;
-
-                tmpC   = (tmp[j] >> 7) & 0x01;
-                tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
-                carry  = tmpC;
-            }
-            if (carry) {
-                tmp[0] ^= GF_XTS;
-            }
-
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-            sz  -= AES_BLOCK_SIZE;
-            blocks--;
-        }
-
-        /* stealing operation of XTS to handle left overs */
-        if (sz > 0) {
-            byte buf[AES_BLOCK_SIZE];
-
-            XMEMCPY(buf, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-            if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
-                return BUFFER_E;
-            }
-            XMEMCPY(out, buf, sz);
-            XMEMCPY(buf, in, sz);
-
-            xorbuf(buf, tmp, AES_BLOCK_SIZE);
-            wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf);
-            xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE);
-        }
-    }
-    else {
-        WOLFSSL_MSG("Plain text input too small for encryption");
-        return BAD_FUNC_ARG;
-    }
-
-    return ret;
-}
-
-
-/* Same process as encryption but Aes key is AES_DECRYPTION type.
- *
- * xaes  AES keys to use for block encrypt/decrypt
- * out   output buffer to hold plain text
- * in    input cipher text buffer to decrypt
- * sz    size of both out and in buffers
- * i     value to use for tweak
- * iSz   size of i buffer, should always be AES_BLOCK_SIZE but having this input
- *       adds a sanity check on how the user calls the function.
- *
- * returns 0 on success
- */
-int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
-        const byte* i, word32 iSz)
-{
-    int ret = 0;
-    word32 blocks = (sz / AES_BLOCK_SIZE);
-    Aes *aes, *tweak;
-
-    if (xaes == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    aes   = &xaes->aes;
-    tweak = &xaes->tweak;
-
-    if (iSz < AES_BLOCK_SIZE) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (blocks > 0) {
-        word32 j;
-        byte carry = 0;
-        byte tmp[AES_BLOCK_SIZE];
-        byte stl = (sz % AES_BLOCK_SIZE);
-
-        XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
-                                          * key setup passed to decrypt direct*/
-
-        wc_AesEncryptDirect(tweak, tmp, i);
-
-        /* if Stealing then break out of loop one block early to handle special
-         * case */
-        if (stl > 0) {
-            blocks--;
-        }
-
-    #ifdef HAVE_AES_ECB
-        /* decrypt all of buffer at once when possible */
-        if (in != out) { /* can not handle inline */
-            XMEMCPY(out, tmp, AES_BLOCK_SIZE);
-            if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) {
-                return ret;
-            }
-        }
-    #endif
-
-        while (blocks > 0) {
-            byte buf[AES_BLOCK_SIZE];
-
-    #ifdef HAVE_AES_ECB
-            if (in == out) { /* check for if inline */
-    #endif
-            XMEMCPY(buf, in, AES_BLOCK_SIZE);
-            xorbuf(buf, tmp, AES_BLOCK_SIZE);
-            wc_AesDecryptDirect(aes, out, buf);
-    #ifdef HAVE_AES_ECB
-            }
-    #endif
-            xorbuf(out, tmp, AES_BLOCK_SIZE);
-
-            /* multiply by shift left and propogate carry */
-            for (j = 0; j < AES_BLOCK_SIZE; j++) {
-                byte tmpC;
-
-                tmpC   = (tmp[j] >> 7) & 0x01;
-                tmp[j] = ((tmp[j] << 1) + carry) & 0xFF;
-                carry  = tmpC;
-            }
-            if (carry) {
-                tmp[0] ^= GF_XTS;
-            }
-            carry = 0;
-
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-            sz  -= AES_BLOCK_SIZE;
-            blocks--;
-        }
-
-        /* stealing operation of XTS to handle left overs */
-        if (sz > 0) {
-            byte buf[AES_BLOCK_SIZE];
-            byte tmp2[AES_BLOCK_SIZE];
-
-            /* multiply by shift left and propogate carry */
-            for (j = 0; j < AES_BLOCK_SIZE; j++) {
-                byte tmpC;
-
-                tmpC   = (tmp[j] >> 7) & 0x01;
-                tmp2[j] = ((tmp[j] << 1) + carry) & 0xFF;
-                carry  = tmpC;
-            }
-            if (carry) {
-                tmp2[0] ^= GF_XTS;
-            }
-
-            XMEMCPY(buf, in, AES_BLOCK_SIZE);
-            xorbuf(buf, tmp2, AES_BLOCK_SIZE);
-            wc_AesDecryptDirect(aes, out, buf);
-            xorbuf(out, tmp2, AES_BLOCK_SIZE);
-
-            /* tmp2 holds partial | last */
-            XMEMCPY(tmp2, out, AES_BLOCK_SIZE);
-            in  += AES_BLOCK_SIZE;
-            out += AES_BLOCK_SIZE;
-            sz  -= AES_BLOCK_SIZE;
-
-            /* Make buffer with end of cipher text | last */
-            XMEMCPY(buf, tmp2, AES_BLOCK_SIZE);
-            if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */
-                return BUFFER_E;
-            }
-            XMEMCPY(buf, in,   sz);
-            XMEMCPY(out, tmp2, sz);
-
-            xorbuf(buf, tmp, AES_BLOCK_SIZE);
-            wc_AesDecryptDirect(aes, tmp2, buf);
-            xorbuf(tmp2, tmp, AES_BLOCK_SIZE);
-            XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE);
-        }
-    }
-    else {
-        WOLFSSL_MSG("Plain text input too small for encryption");
-        return BAD_FUNC_ARG;
-    }
-
-    return ret;
-}
-
-#endif /* WOLFSSL_AES_XTS */
-
-#endif /* HAVE_FIPS */
-#endif /* !NO_AES */
-
--- a/wolfcrypt/src/arc4.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/* arc4.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_RC4
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/arc4.h>
-
-
-int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length)
-{
-    int ret = 0;
-    word32 i;
-    word32 keyIndex = 0, stateIndex = 0;
-
-    if (arc4 == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
-        defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
-    if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
-        return NitroxArc4SetKey(arc4, key, length);
-    }
-#endif
-
-    arc4->x = 1;
-    arc4->y = 0;
-
-    for (i = 0; i < ARC4_STATE_SIZE; i++)
-        arc4->state[i] = (byte)i;
-
-    for (i = 0; i < ARC4_STATE_SIZE; i++) {
-        word32 a = arc4->state[i];
-        stateIndex += key[keyIndex] + a;
-        stateIndex &= 0xFF;
-        arc4->state[i] = arc4->state[stateIndex];
-        arc4->state[stateIndex] = (byte)a;
-
-        if (++keyIndex >= length)
-            keyIndex = 0;
-    }
-
-    return ret;
-}
-
-
-static WC_INLINE byte MakeByte(word32* x, word32* y, byte* s)
-{
-    word32 a = s[*x], b;
-    *y = (*y+a) & 0xff;
-
-    b = s[*y];
-    s[*x] = (byte)b;
-    s[*y] = (byte)a;
-    *x = (*x+1) & 0xff;
-
-    return s[(a+b) & 0xff];
-}
-
-
-int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length)
-{
-    int ret = 0;
-    word32 x;
-    word32 y;
-
-    if (arc4 == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
-        defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
-    if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
-        return NitroxArc4Process(arc4, out, in, length);
-    }
-#endif
-
-    x = arc4->x;
-    y = arc4->y;
-
-    while(length--)
-        *out++ = *in++ ^ MakeByte(&x, &y, arc4->state);
-
-    arc4->x = (byte)x;
-    arc4->y = (byte)y;
-
-    return ret;
-}
-
-/* Initialize Arc4 for use with async device */
-int wc_Arc4Init(Arc4* arc4, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (arc4 == NULL)
-        return BAD_FUNC_ARG;
-
-    arc4->heap = heap;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
-    ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4,
-        arc4->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-
-/* Free Arc4 from use with async device */
-void wc_Arc4Free(Arc4* arc4)
-{
-    if (arc4 == NULL)
-        return;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
-    wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-#endif /* NO_RC4 */
-
-
--- a/wolfcrypt/src/asm.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1784 +0,0 @@
-/* asm.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-/*
- * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca,
- * http://math.libtomcrypt.com
- */
-
-
-/******************************************************************/
-/* fp_montgomery_reduce.c asm or generic */
-
-
-/* Each platform needs to query info type 1 from cpuid to see if aesni is
- * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
- */
-
-#if defined(HAVE_INTEL_MULX)
-#ifndef _MSC_VER
-    #define cpuid(reg, leaf, sub)\
-            __asm__ __volatile__ ("cpuid":\
-             "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\
-             "a" (leaf), "c"(sub));
-
-    #define XASM_LINK(f) asm(f)
-#else
-
-    #include <intrin.h>
-    #define cpuid(a,b,c) __cpuidex((int*)a,b,c)
-
-    #define XASM_LINK(f)
-
-#endif /* _MSC_VER */
-
-#define EAX 0
-#define EBX 1
-#define ECX 2
-#define EDX 3
-
-#define CPUID_AVX1   0x1
-#define CPUID_AVX2   0x2
-#define CPUID_RDRAND 0x4
-#define CPUID_RDSEED 0x8
-#define CPUID_BMI2   0x10   /* MULX, RORX */
-#define CPUID_ADX    0x20   /* ADCX, ADOX */
-
-#define IS_INTEL_AVX1       (cpuid_flags&CPUID_AVX1)
-#define IS_INTEL_AVX2       (cpuid_flags&CPUID_AVX2)
-#define IS_INTEL_BMI2       (cpuid_flags&CPUID_BMI2)
-#define IS_INTEL_ADX        (cpuid_flags&CPUID_ADX)
-#define IS_INTEL_RDRAND     (cpuid_flags&CPUID_RDRAND)
-#define IS_INTEL_RDSEED     (cpuid_flags&CPUID_RDSEED)
-#define SET_FLAGS
-
-static word32 cpuid_check = 0 ;
-static word32 cpuid_flags = 0 ;
-
-static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) {
-    int got_intel_cpu = 0;
-    int got_amd_cpu = 0;
-    unsigned int reg[5];
-
-    reg[4] = '\0' ;
-    cpuid(reg, 0, 0);
-
-    /* check for intel cpu */
-    if( memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 &&
-        memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 &&
-        memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) {
-        got_intel_cpu = 1;
-    }
-
-    /* check for AMD cpu */
-    if( memcmp((char *)&(reg[EBX]), "Auth", 4) == 0 &&
-        memcmp((char *)&(reg[EDX]), "enti", 4) == 0 &&
-        memcmp((char *)&(reg[ECX]), "cAMD", 4) == 0) {
-        got_amd_cpu = 1;
-    }
-    if (got_intel_cpu || got_amd_cpu) {
-        cpuid(reg, leaf, sub);
-        return((reg[num]>>bit)&0x1) ;
-    }
-    return 0 ;
-}
-
-WC_INLINE static int set_cpuid_flags(void) {
-    if(cpuid_check == 0) {
-        if(cpuid_flag(7, 0, EBX, 8)){  cpuid_flags |= CPUID_BMI2 ; }
-        if(cpuid_flag(7, 0, EBX,19)){  cpuid_flags |= CPUID_ADX  ; }
-		cpuid_check = 1 ;
-		return 0 ;
-    }
-    return 1 ;
-}
-
-#define RETURN return
-#define IF_HAVE_INTEL_MULX(func, ret)    \
-   if(cpuid_check==0)set_cpuid_flags() ; \
-   if(IS_INTEL_BMI2 && IS_INTEL_ADX){  func;  ret ;  }
-
-#else
-    #define IF_HAVE_INTEL_MULX(func, ret)
-#endif
-
-#if defined(TFM_X86) && !defined(TFM_SSE2)
-/* x86-32 code */
-
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                                          \
-__asm__(                                                  \
-   "movl %5,%%eax \n\t"                                   \
-   "mull %4       \n\t"                                   \
-   "addl %1,%%eax \n\t"                                   \
-   "adcl $0,%%edx \n\t"                                   \
-   "addl %%eax,%0 \n\t"                                   \
-   "adcl $0,%%edx \n\t"                                   \
-   "movl %%edx,%1 \n\t"                                   \
-:"=g"(_c[LO]), "=r"(cy)                                   \
-:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++)              \
-: "%eax", "%edx", "cc")
-
-#define PROPCARRY                           \
-__asm__(                                    \
-   "addl   %1,%0    \n\t"                   \
-   "setb   %%al     \n\t"                   \
-   "movzbl %%al,%1 \n\t"                    \
-:"=g"(_c[LO]), "=r"(cy)                     \
-:"0"(_c[LO]), "1"(cy)                       \
-: "%eax", "cc")
-
-/******************************************************************/
-#elif defined(TFM_X86_64)
-/* x86-64 code */
-
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                                          \
-__asm__(                                                  \
-   "movq %5,%%rax \n\t"                                   \
-   "mulq %4       \n\t"                                   \
-   "addq %1,%%rax \n\t"                                   \
-   "adcq $0,%%rdx \n\t"                                   \
-   "addq %%rax,%0 \n\t"                                   \
-   "adcq $0,%%rdx \n\t"                                   \
-   "movq %%rdx,%1 \n\t"                                   \
-:"=g"(_c[LO]), "=r"(cy)                                   \
-:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++)              \
-: "%rax", "%rdx", "cc")
-
-#if defined(HAVE_INTEL_MULX)
-#define MULX_INNERMUL8(x,y,z,cy)                                       \
-    __asm__  volatile (                                                \
-        "movq	%[yn], %%rdx\n\t"                                      \
-        "xorq	%%rcx, %%rcx\n\t"                                      \
-        "movq   0(%[c]), %%r8\n\t"                                     \
-        "movq   8(%[c]), %%r9\n\t"                                     \
-        "movq   16(%[c]), %%r10\n\t"                                   \
-        "movq   24(%[c]), %%r11\n\t"                                   \
-        "movq   32(%[c]), %%r12\n\t"                                   \
-        "movq   40(%[c]), %%r13\n\t"                                   \
-        "movq   48(%[c]), %%r14\n\t"                                   \
-        "movq   56(%[c]), %%r15\n\t"                                   \
-                                                                       \
-        "mulx	0(%[xp]), %%rax, %%rcx\n\t"                            \
-        "adcxq	%[cy], %%r8\n\t"                                       \
-        "adoxq	%%rax, %%r8\n\t"                                       \
-        "mulx	8(%[xp]), %%rax, %[cy]\n\t"                            \
-        "adcxq	%%rcx, %%r9\n\t"                                       \
-        "adoxq	%%rax, %%r9\n\t"                                       \
-        "mulx	16(%[xp]), %%rax, %%rcx\n\t"                           \
-        "adcxq	%[cy], %%r10\n\t"                                      \
-        "adoxq	%%rax, %%r10\n\t"                                      \
-        "mulx	24(%[xp]), %%rax, %[cy]\n\t"                           \
-        "adcxq	%%rcx, %%r11\n\t"                                      \
-        "adoxq	%%rax, %%r11\n\t"                                      \
-        "mulx	32(%[xp]), %%rax, %%rcx\n\t"                           \
-        "adcxq	%[cy], %%r12\n\t"                                      \
-        "adoxq	%%rax, %%r12\n\t"                                      \
-        "mulx	40(%[xp]), %%rax, %[cy]\n\t"                           \
-        "adcxq	%%rcx, %%r13\n\t"                                      \
-        "adoxq	%%rax, %%r13\n\t"                                      \
-        "mulx	48(%[xp]), %%rax, %%rcx\n\t"                           \
-        "adcxq	%[cy], %%r14\n\t"                                      \
-        "adoxq	%%rax, %%r14\n\t"                                      \
-        "adcxq	%%rcx, %%r15\n\t"                                      \
-        "mulx	56(%[xp]), %%rax, %[cy]\n\t"                           \
-        "movq	$0, %%rdx\n\t"                                         \
-        "adoxq	%%rdx, %%rax\n\t"                                      \
-        "adcxq	%%rdx, %[cy]\n\t"                                      \
-        "adoxq	%%rdx, %[cy]\n\t"                                      \
-        "addq   %%rax, %%r15\n\t"                                      \
-        "adcq   $0, %[cy]\n\t"                                         \
-                                                                       \
-        "movq   %%r8,   0(%[c])\n\t"                                   \
-        "movq   %%r9,   8(%[c])\n\t"                                   \
-        "movq   %%r10, 16(%[c])\n\t"                                   \
-        "movq   %%r11, 24(%[c])\n\t"                                   \
-        "movq   %%r12, 32(%[c])\n\t"                                   \
-        "movq   %%r13, 40(%[c])\n\t"                                   \
-        "movq   %%r14, 48(%[c])\n\t"                                   \
-        "movq   %%r15, 56(%[c])\n\t"                                   \
-        : [cy] "+r" (cy)                                               \
-        : [xp] "r" (x), [c] "r" (c_mulx), [yn] "rm" (y)                \
-        :"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
-         "%rdx", "%rax", "%rcx" \
-    )
-
-#define INNERMUL8_MULX \
-{\
-    MULX_INNERMUL8(tmpm, mu, _c, cy);\
-}
-#endif
-
-#define INNERMUL8 \
- __asm__(                    \
- "movq 0(%5),%%rax    \n\t"  \
- "movq 0(%2),%%r10    \n\t"  \
- "movq 0x8(%5),%%r11  \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x8(%2),%%r10  \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0(%0)    \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x10(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x10(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x8(%0)  \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x18(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x18(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x10(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x20(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x20(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x18(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x28(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x28(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x20(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x30(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x30(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x28(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "movq 0x38(%5),%%r11 \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq 0x38(%2),%%r10 \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x30(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
- "movq %%r11,%%rax    \n\t"  \
- "mulq %4             \n\t"  \
- "addq %%r10,%%rax    \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "addq %3,%%rax       \n\t"  \
- "adcq $0,%%rdx       \n\t"  \
- "movq %%rax,0x38(%0) \n\t"  \
- "movq %%rdx,%1       \n\t"  \
- \
-:"=r"(_c), "=r"(cy)                    \
-: "0"(_c),  "1"(cy), "g"(mu), "r"(tmpm)\
-: "%rax", "%rdx", "%r10", "%r11", "cc")
-
-#define PROPCARRY                           \
-__asm__(                                    \
-   "addq   %1,%0    \n\t"                   \
-   "setb   %%al     \n\t"                   \
-   "movzbq %%al,%1 \n\t"                    \
-:"=g"(_c[LO]), "=r"(cy)                     \
-:"0"(_c[LO]), "1"(cy)                       \
-: "%rax", "cc")
-
-/******************************************************************/
-#elif defined(TFM_SSE2)
-/* SSE2 code (assumes 32-bit fp_digits) */
-/* XMM register assignments:
- * xmm0  *tmpm++, then Mu * (*tmpm++)
- * xmm1  c[x], then Mu
- * xmm2  mp
- * xmm3  cy
- * xmm4  _c[LO]
- */
-
-#define MONT_START \
-   __asm__("movd %0,%%mm2"::"g"(mp))
-
-#define MONT_FINI \
-   __asm__("emms")
-
-#define LOOP_START          \
-__asm__(                    \
-"movd %0,%%mm1        \n\t" \
-"pxor %%mm3,%%mm3     \n\t" \
-"pmuludq %%mm2,%%mm1  \n\t" \
-:: "g"(c[x]))
-
-/* pmuludq on mmx registers does a 32x32->64 multiply. */
-#define INNERMUL               \
-__asm__(                       \
-   "movd %1,%%mm4        \n\t" \
-   "movd %2,%%mm0        \n\t" \
-   "paddq %%mm4,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm0  \n\t" \
-   "paddq %%mm0,%%mm3    \n\t" \
-   "movd %%mm3,%0        \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-:"=g"(_c[LO]) : "0"(_c[LO]), "g"(*tmpm++) );
-
-#define INNERMUL8 \
-__asm__(                       \
-   "movd 0(%1),%%mm4     \n\t" \
-   "movd 0(%2),%%mm0     \n\t" \
-   "paddq %%mm4,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm0  \n\t" \
-   "movd 4(%2),%%mm5     \n\t" \
-   "paddq %%mm0,%%mm3    \n\t" \
-   "movd 4(%1),%%mm6     \n\t" \
-   "movd %%mm3,0(%0)     \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm6,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm5  \n\t" \
-   "movd 8(%2),%%mm6     \n\t" \
-   "paddq %%mm5,%%mm3    \n\t" \
-   "movd 8(%1),%%mm7     \n\t" \
-   "movd %%mm3,4(%0)     \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm7,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm6  \n\t" \
-   "movd 12(%2),%%mm7    \n\t" \
-   "paddq %%mm6,%%mm3    \n\t" \
-   "movd 12(%1),%%mm5     \n\t" \
-   "movd %%mm3,8(%0)     \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm5,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm7  \n\t" \
-   "movd 16(%2),%%mm5    \n\t" \
-   "paddq %%mm7,%%mm3    \n\t" \
-   "movd 16(%1),%%mm6    \n\t" \
-   "movd %%mm3,12(%0)    \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm6,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm5  \n\t" \
-   "movd 20(%2),%%mm6    \n\t" \
-   "paddq %%mm5,%%mm3    \n\t" \
-   "movd 20(%1),%%mm7    \n\t" \
-   "movd %%mm3,16(%0)    \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm7,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm6  \n\t" \
-   "movd 24(%2),%%mm7    \n\t" \
-   "paddq %%mm6,%%mm3    \n\t" \
-   "movd 24(%1),%%mm5     \n\t" \
-   "movd %%mm3,20(%0)    \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm5,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm7  \n\t" \
-   "movd 28(%2),%%mm5    \n\t" \
-   "paddq %%mm7,%%mm3    \n\t" \
-   "movd 28(%1),%%mm6    \n\t" \
-   "movd %%mm3,24(%0)    \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-\
-   "paddq %%mm6,%%mm3    \n\t" \
-   "pmuludq %%mm1,%%mm5  \n\t" \
-   "paddq %%mm5,%%mm3    \n\t" \
-   "movd %%mm3,28(%0)    \n\t" \
-   "psrlq $32, %%mm3     \n\t" \
-:"=r"(_c) : "0"(_c), "r"(tmpm) );
-
-/* TAO switched tmpm from "g" to "r" after gcc tried to index the indexed stack
-   pointer */
-
-#define LOOP_END \
-__asm__( "movd %%mm3,%0  \n" :"=r"(cy))
-
-#define PROPCARRY                           \
-__asm__(                                    \
-   "addl   %1,%0    \n\t"                   \
-   "setb   %%al     \n\t"                   \
-   "movzbl %%al,%1 \n\t"                    \
-:"=g"(_c[LO]), "=r"(cy)                     \
-:"0"(_c[LO]), "1"(cy)                       \
-: "%eax", "cc")
-
-/******************************************************************/
-#elif defined(TFM_ARM)
-   /* ARMv4 code */
-
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-
-#ifdef __thumb__
-
-#define INNERMUL                    \
-__asm__(                            \
-    " LDR    r0,%1            \n\t" \
-    " ADDS   r0,r0,%0         \n\t" \
-    " ITE    CS               \n\t" \
-    " MOVCS  %0,#1            \n\t" \
-    " MOVCC  %0,#0            \n\t" \
-    " UMLAL  r0,%0,%3,%4      \n\t" \
-    " STR    r0,%1            \n\t" \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0]):"r0","cc");
-
-#define PROPCARRY                  \
-__asm__(                           \
-    " LDR   r0,%1            \n\t" \
-    " ADDS  r0,r0,%0         \n\t" \
-    " STR   r0,%1            \n\t" \
-    " ITE   CS               \n\t" \
-    " MOVCS %0,#1            \n\t" \
-    " MOVCC %0,#0            \n\t" \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"m"(_c[0]):"r0","cc");
-
-
-/* TAO thumb mode uses ite (if then else) to detect carry directly
- * fixed unmatched constraint warning by changing 1 to m  */
-
-#else  /* __thumb__ */
-
-#define INNERMUL                    \
-__asm__(                            \
-    " LDR    r0,%1            \n\t" \
-    " ADDS   r0,r0,%0         \n\t" \
-    " MOVCS  %0,#1            \n\t" \
-    " MOVCC  %0,#0            \n\t" \
-    " UMLAL  r0,%0,%3,%4      \n\t" \
-    " STR    r0,%1            \n\t" \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c[0]):"r0","cc");
-
-#define PROPCARRY                  \
-__asm__(                           \
-    " LDR   r0,%1            \n\t" \
-    " ADDS  r0,r0,%0         \n\t" \
-    " STR   r0,%1            \n\t" \
-    " MOVCS %0,#1            \n\t" \
-    " MOVCC %0,#0            \n\t" \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r0","cc");
-
-#endif /* __thumb__ */
-
-#elif defined(TFM_PPC32)
-
-/* PPC32 */
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                     \
-__asm__(                             \
-   " mullw    16,%3,%4       \n\t"   \
-   " mulhwu   17,%3,%4       \n\t"   \
-   " addc     16,16,%2       \n\t"   \
-   " addze    17,17          \n\t"   \
-   " addc     %1,16,%5       \n\t"   \
-   " addze    %0,17          \n\t"   \
-:"=r"(cy),"=r"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "cc"); ++tmpm;
-
-#define PROPCARRY                    \
-__asm__(                             \
-   " addc     %1,%3,%2      \n\t"    \
-   " xor      %0,%2,%2      \n\t"    \
-   " addze    %0,%2         \n\t"    \
-:"=r"(cy),"=r"(_c[0]):"0"(cy),"1"(_c[0]):"cc");
-
-#elif defined(TFM_PPC64)
-
-/* PPC64 */
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                      \
-__asm__(                              \
-   " mulld    r16,%3,%4       \n\t"   \
-   " mulhdu   r17,%3,%4       \n\t"   \
-   " addc     r16,16,%0       \n\t"   \
-   " addze    r17,r17         \n\t"   \
-   " ldx      r18,0,%1        \n\t"   \
-   " addc     r16,r16,r18     \n\t"   \
-   " addze    %0,r17          \n\t"   \
-   " sdx      r16,0,%1        \n\t"   \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"r16", "r17", "r18","cc"); ++tmpm;
-
-#define PROPCARRY                     \
-__asm__(                              \
-   " ldx      r16,0,%1       \n\t"    \
-   " addc     r16,r16,%0     \n\t"    \
-   " sdx      r16,0,%1       \n\t"    \
-   " xor      %0,%0,%0       \n\t"    \
-   " addze    %0,%0          \n\t"    \
-:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r16","cc");
-
-/******************************************************************/
-
-#elif defined(TFM_AVR32)
-
-/* AVR32 */
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                    \
-__asm__(                            \
-    " ld.w   r2,%1            \n\t" \
-    " add    r2,%0            \n\t" \
-    " eor    r3,r3            \n\t" \
-    " acr    r3               \n\t" \
-    " macu.d r2,%3,%4         \n\t" \
-    " st.w   %1,r2            \n\t" \
-    " mov    %0,r3            \n\t" \
-:"=r"(cy),"=r"(_c):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c):"r2","r3");
-
-#define PROPCARRY                    \
-__asm__(                             \
-   " ld.w     r2,%1         \n\t"    \
-   " add      r2,%0         \n\t"    \
-   " st.w     %1,r2         \n\t"    \
-   " eor      %0,%0         \n\t"    \
-   " acr      %0            \n\t"    \
-:"=r"(cy),"=r"(&_c[0]):"0"(cy),"1"(&_c[0]):"r2","cc");
-
-/******************************************************************/
-#elif defined(TFM_MIPS)
-
-/* MIPS */
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                     \
-__asm__(                             \
-   " multu    %3,%4          \n\t"   \
-   " mflo     $12            \n\t"   \
-   " mfhi     $13            \n\t"   \
-   " addu     $12,$12,%0     \n\t"   \
-   " sltu     $10,$12,%0     \n\t"   \
-   " addu     $13,$13,$10    \n\t"   \
-   " lw       $10,%1         \n\t"   \
-   " addu     $12,$12,$10    \n\t"   \
-   " sltu     $10,$12,$10    \n\t"   \
-   " addu     %0,$13,$10     \n\t"   \
-   " sw       $12,%1         \n\t"   \
-:"+r"(cy),"+m"(_c[0]):""(cy),"r"(mu),"r"(tmpm[0]),""(_c[0]):"$10","$12","$13"); ++tmpm;
-
-#define PROPCARRY                    \
-__asm__(                             \
-   " lw       $10,%1        \n\t"    \
-   " addu     $10,$10,%0    \n\t"    \
-   " sw       $10,%1        \n\t"    \
-   " sltu     %0,$10,%0     \n\t"    \
-:"+r"(cy),"+m"(_c[0]):""(cy),""(_c[0]):"$10");
-
-/******************************************************************/
-#else
-
-/* ISO C code */
-#define MONT_START
-#define MONT_FINI
-#define LOOP_END
-#define LOOP_START \
-   mu = c[x] * mp
-
-#define INNERMUL                                      \
-   do { fp_word t;                                    \
-   t  = ((fp_word)_c[0] + (fp_word)cy) +              \
-                (((fp_word)mu) * ((fp_word)*tmpm++)); \
-   _c[0] = (fp_digit)t;                               \
-   cy = (fp_digit)(t >> DIGIT_BIT);                   \
-   } while (0)
-
-#define PROPCARRY \
-   do { fp_digit t = _c[0] += cy; cy = (t < cy); } while (0)
-
-#endif
-/******************************************************************/
-
-
-#define LO  0
-/* end fp_montogomery_reduce.c asm */
-
-
-/* start fp_sqr_comba.c asm */
-#if defined(TFM_X86)
-
-/* x86-32 optimized */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-#define SQRADD(i, j)                                      \
-__asm__(                                                  \
-     "movl  %6,%%eax     \n\t"                            \
-     "mull  %%eax        \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","cc");
-
-#define SQRADD2(i, j)                                     \
-__asm__(                                                  \
-     "movl  %6,%%eax     \n\t"                            \
-     "mull  %7           \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx", "cc");
-
-#define SQRADDSC(i, j)                                    \
-__asm__(                                                     \
-     "movl  %3,%%eax     \n\t"                            \
-     "mull  %4           \n\t"                            \
-     "movl  %%eax,%0     \n\t"                            \
-     "movl  %%edx,%1     \n\t"                            \
-     "xorl  %2,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%eax","%edx","cc");
-
-#define SQRADDAC(i, j)                                    \
-__asm__(                                                  \
-     "movl  %6,%%eax     \n\t"                            \
-     "mull  %7           \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc");
-
-#define SQRADDDB                                          \
-__asm__(                                                  \
-     "addl %6,%0         \n\t"                            \
-     "adcl %7,%1         \n\t"                            \
-     "adcl %8,%2         \n\t"                            \
-     "addl %6,%0         \n\t"                            \
-     "adcl %7,%1         \n\t"                            \
-     "adcl %8,%2         \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
-
-#elif defined(TFM_X86_64)
-/* x86-64 optimized */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-#define SQRADD(i, j)                                      \
-__asm__(                                                  \
-     "movq  %6,%%rax     \n\t"                            \
-     "mulq  %%rax        \n\t"                            \
-     "addq  %%rax,%0     \n\t"                            \
-     "adcq  %%rdx,%1     \n\t"                            \
-     "adcq  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "x"(i) :"%rax","%rdx","cc");
-
-#define SQRADD2(i, j)                                     \
-__asm__(                                                  \
-     "movq  %6,%%rax     \n\t"                            \
-     "mulq  %7           \n\t"                            \
-     "addq  %%rax,%0     \n\t"                            \
-     "adcq  %%rdx,%1     \n\t"                            \
-     "adcq  $0,%2        \n\t"                            \
-     "addq  %%rax,%0     \n\t"                            \
-     "adcq  %%rdx,%1     \n\t"                            \
-     "adcq  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j)  :"%rax","%rdx","cc");
-
-#define SQRADDSC(i, j)                                    \
-__asm__(                                                  \
-     "movq  %3,%%rax     \n\t"                            \
-     "mulq  %4           \n\t"                            \
-     "movq  %%rax,%0     \n\t"                            \
-     "movq  %%rdx,%1     \n\t"                            \
-     "xorq  %2,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%rax","%rdx","cc");
-
-#define SQRADDAC(i, j)                                                         \
-__asm__(                                                  \
-     "movq  %6,%%rax     \n\t"                            \
-     "mulq  %7           \n\t"                            \
-     "addq  %%rax,%0     \n\t"                            \
-     "adcq  %%rdx,%1     \n\t"                            \
-     "adcq  $0,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
-
-#define SQRADDDB                                          \
-__asm__(                                                  \
-     "addq %6,%0         \n\t"                            \
-     "adcq %7,%1         \n\t"                            \
-     "adcq %8,%2         \n\t"                            \
-     "addq %6,%0         \n\t"                            \
-     "adcq %7,%1         \n\t"                            \
-     "adcq %8,%2         \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
-
-#elif defined(TFM_SSE2)
-
-/* SSE2 Optimized */
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI \
-   __asm__("emms");
-
-#define SQRADD(i, j)                                      \
-__asm__(                                                  \
-     "movd  %6,%%mm0     \n\t"                            \
-     "pmuludq %%mm0,%%mm0\n\t"                            \
-     "movd  %%mm0,%%eax  \n\t"                            \
-     "psrlq $32,%%mm0    \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "movd  %%mm0,%%eax  \n\t"                            \
-     "adcl  %%eax,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","cc");
-
-#define SQRADD2(i, j)                                     \
-__asm__(                                                  \
-     "movd  %6,%%mm0     \n\t"                            \
-     "movd  %7,%%mm1     \n\t"                            \
-     "pmuludq %%mm1,%%mm0\n\t"                            \
-     "movd  %%mm0,%%eax  \n\t"                            \
-     "psrlq $32,%%mm0    \n\t"                            \
-     "movd  %%mm0,%%edx  \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","cc");
-
-#define SQRADDSC(i, j)                                                         \
-__asm__(                                                  \
-     "movd  %3,%%mm0     \n\t"                            \
-     "movd  %4,%%mm1     \n\t"                            \
-     "pmuludq %%mm1,%%mm0\n\t"                            \
-     "movd  %%mm0,%0     \n\t"                            \
-     "psrlq $32,%%mm0    \n\t"                            \
-     "movd  %%mm0,%1     \n\t"                            \
-     "xorl  %2,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "m"(i), "m"(j));
-
-/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */
-
-#define SQRADDAC(i, j)                                                         \
-__asm__(                                                  \
-     "movd  %6,%%mm0     \n\t"                            \
-     "movd  %7,%%mm1     \n\t"                            \
-     "pmuludq %%mm1,%%mm0\n\t"                            \
-     "movd  %%mm0,%%eax  \n\t"                            \
-     "psrlq $32,%%mm0    \n\t"                            \
-     "movd  %%mm0,%%edx  \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j)  :"%eax","%edx","cc");
-
-#define SQRADDDB                                          \
-__asm__(                                                  \
-     "addl %6,%0         \n\t"                            \
-     "adcl %7,%1         \n\t"                            \
-     "adcl %8,%2         \n\t"                            \
-     "addl %6,%0         \n\t"                            \
-     "adcl %7,%1         \n\t"                            \
-     "adcl %8,%2         \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
-
-#elif defined(TFM_ARM)
-
-/* ARM code */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)                                             \
-__asm__(                                                         \
-"  UMULL  r0,r1,%6,%6              \n\t"                         \
-"  ADDS   %0,%0,r0                 \n\t"                         \
-"  ADCS   %1,%1,r1                 \n\t"                         \
-"  ADC    %2,%2,#0                 \n\t"                         \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "cc");
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)                                            \
-__asm__(                                                         \
-"  UMULL  r0,r1,%6,%7              \n\t"                         \
-"  ADDS   %0,%0,r0                 \n\t"                         \
-"  ADCS   %1,%1,r1                 \n\t"                         \
-"  ADC    %2,%2,#0                 \n\t"                         \
-"  ADDS   %0,%0,r0                 \n\t"                         \
-"  ADCS   %1,%1,r1                 \n\t"                         \
-"  ADC    %2,%2,#0                 \n\t"                         \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc");
-
-#define SQRADDSC(i, j)                                           \
-__asm__(                                                         \
-"  UMULL  %0,%1,%3,%4              \n\t"                         \
-"  SUB    %2,%2,%2                 \n\t"                         \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "r"(i), "r"(j) : "cc");
-
-/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */
-
-#define SQRADDAC(i, j)                                           \
-__asm__(                                                         \
-"  UMULL  r0,r1,%6,%7              \n\t"                         \
-"  ADDS   %0,%0,r0                 \n\t"                         \
-"  ADCS   %1,%1,r1                 \n\t"                         \
-"  ADC    %2,%2,#0                 \n\t"                         \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "cc");
-
-#define SQRADDDB                                                 \
-__asm__(                                                         \
-"  ADDS  %0,%0,%3                     \n\t"                      \
-"  ADCS  %1,%1,%4                     \n\t"                      \
-"  ADC   %2,%2,%5                     \n\t"                      \
-"  ADDS  %0,%0,%3                     \n\t"                      \
-"  ADCS  %1,%1,%4                     \n\t"                      \
-"  ADC   %2,%2,%5                     \n\t"                      \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
-
-#elif defined(TFM_PPC32)
-
-/* PPC32 */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)             \
-__asm__(                         \
-   " mullw  16,%6,%6       \n\t" \
-   " addc   %0,%0,16       \n\t" \
-   " mulhwu 16,%6,%6       \n\t" \
-   " adde   %1,%1,16       \n\t" \
-   " addze  %2,%2          \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"16","cc");
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)            \
-__asm__(                         \
-   " mullw  16,%6,%7       \n\t" \
-   " mulhwu 17,%6,%7       \n\t" \
-   " addc   %0,%0,16       \n\t" \
-   " adde   %1,%1,17       \n\t" \
-   " addze  %2,%2          \n\t" \
-   " addc   %0,%0,16       \n\t" \
-   " adde   %1,%1,17       \n\t" \
-   " addze  %2,%2          \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16", "17","cc");
-
-#define SQRADDSC(i, j)            \
-__asm__(                          \
-   " mullw  %0,%6,%7        \n\t" \
-   " mulhwu %1,%6,%7        \n\t" \
-   " xor    %2,%2,%2        \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
-
-#define SQRADDAC(i, j)           \
-__asm__(                         \
-   " mullw  16,%6,%7       \n\t" \
-   " addc   %0,%0,16       \n\t" \
-   " mulhwu 16,%6,%7       \n\t" \
-   " adde   %1,%1,16       \n\t" \
-   " addze  %2,%2          \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"16", "cc");
-
-#define SQRADDDB                  \
-__asm__(                          \
-   " addc   %0,%0,%3        \n\t" \
-   " adde   %1,%1,%4        \n\t" \
-   " adde   %2,%2,%5        \n\t" \
-   " addc   %0,%0,%3        \n\t" \
-   " adde   %1,%1,%4        \n\t" \
-   " adde   %2,%2,%5        \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
-
-#elif defined(TFM_PPC64)
-/* PPC64 */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)              \
-__asm__(                          \
-   " mulld  r16,%6,%6       \n\t" \
-   " addc   %0,%0,r16       \n\t" \
-   " mulhdu r16,%6,%6       \n\t" \
-   " adde   %1,%1,r16       \n\t" \
-   " addze  %2,%2           \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r16","cc");
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)             \
-__asm__(                          \
-   " mulld  r16,%6,%7       \n\t" \
-   " mulhdu r17,%6,%7       \n\t" \
-   " addc   %0,%0,r16       \n\t" \
-   " adde   %1,%1,r17       \n\t" \
-   " addze  %2,%2           \n\t" \
-   " addc   %0,%0,r16       \n\t" \
-   " adde   %1,%1,r17       \n\t" \
-   " addze  %2,%2           \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16", "r17","cc");
-
-#define SQRADDSC(i, j)            \
-__asm__(                          \
-   " mulld  %0,%6,%7        \n\t" \
-   " mulhdu %1,%6,%7        \n\t" \
-   " xor    %2,%2,%2        \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
-
-#define SQRADDAC(i, j)            \
-__asm__(                          \
-   " mulld  r16,%6,%7       \n\t" \
-   " addc   %0,%0,r16       \n\t" \
-   " mulhdu r16,%6,%7       \n\t" \
-   " adde   %1,%1,r16       \n\t" \
-   " addze  %2,%2           \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r16", "cc");
-
-#define SQRADDDB                  \
-__asm__(                          \
-   " addc   %0,%0,%3        \n\t" \
-   " adde   %1,%1,%4        \n\t" \
-   " adde   %2,%2,%5        \n\t" \
-   " addc   %0,%0,%3        \n\t" \
-   " adde   %1,%1,%4        \n\t" \
-   " adde   %2,%2,%5        \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
-
-
-#elif defined(TFM_AVR32)
-
-/* AVR32 */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)             \
-__asm__(                         \
-   " mulu.d r2,%6,%6       \n\t" \
-   " add    %0,%0,r2       \n\t" \
-   " adc    %1,%1,r3       \n\t" \
-   " acr    %2             \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r2","r3");
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)            \
-__asm__(                         \
-   " mulu.d r2,%6,%7       \n\t" \
-   " add    %0,%0,r2       \n\t" \
-   " adc    %1,%1,r3       \n\t" \
-   " acr    %2,            \n\t" \
-   " add    %0,%0,r2       \n\t" \
-   " adc    %1,%1,r3       \n\t" \
-   " acr    %2,            \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2", "r3");
-
-#define SQRADDSC(i, j)            \
-__asm__(                          \
-   " mulu.d r2,%6,%7        \n\t" \
-   " mov    %0,r2           \n\t" \
-   " mov    %1,r3           \n\t" \
-   " eor    %2,%2           \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "r2", "r3");
-
-#define SQRADDAC(i, j)           \
-__asm__(                         \
-   " mulu.d r2,%6,%7       \n\t" \
-   " add    %0,%0,r2       \n\t" \
-   " adc    %1,%1,r3       \n\t" \
-   " acr    %2             \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r2", "r3");
-
-#define SQRADDDB                  \
-__asm__(                          \
-   " add    %0,%0,%3        \n\t" \
-   " adc    %1,%1,%4        \n\t" \
-   " adc    %2,%2,%5        \n\t" \
-   " add    %0,%0,%3        \n\t" \
-   " adc    %1,%1,%4        \n\t" \
-   " adc    %2,%2,%5        \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc");
-
-#elif defined(TFM_MIPS)
-
-/* MIPS */
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)              \
-__asm__(                          \
-   " multu  %6,%6          \n\t"  \
-   " mflo   $12            \n\t"  \
-   " mfhi   $13            \n\t"  \
-   " addu    %0,%0,$12     \n\t"  \
-   " sltu   $12,%0,$12     \n\t"  \
-   " addu    %1,%1,$13     \n\t"  \
-   " sltu   $13,%1,$13     \n\t"  \
-   " addu    %1,%1,$12     \n\t"  \
-   " sltu   $12,%1,$12     \n\t"  \
-   " addu    %2,%2,$13     \n\t"  \
-   " addu    %2,%2,$12     \n\t"  \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13");
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)            \
-__asm__(                         \
-   " multu  %6,%7          \n\t" \
-   " mflo   $12            \n\t" \
-   " mfhi   $13            \n\t" \
-                                 \
-   " addu    %0,%0,$12     \n\t" \
-   " sltu   $14,%0,$12     \n\t" \
-   " addu    %1,%1,$13     \n\t" \
-   " sltu   $15,%1,$13     \n\t" \
-   " addu    %1,%1,$14     \n\t" \
-   " sltu   $14,%1,$14     \n\t" \
-   " addu    %2,%2,$15     \n\t" \
-   " addu    %2,%2,$14     \n\t" \
-                                 \
-   " addu    %0,%0,$12     \n\t" \
-   " sltu   $14,%0,$12     \n\t" \
-   " addu    %1,%1,$13     \n\t" \
-   " sltu   $15,%1,$13     \n\t" \
-   " addu    %1,%1,$14     \n\t" \
-   " sltu   $14,%1,$14     \n\t" \
-   " addu    %2,%2,$15     \n\t" \
-   " addu    %2,%2,$14     \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15");
-
-#define SQRADDSC(i, j)            \
-__asm__(                          \
-   " multu  %6,%7          \n\t"  \
-   " mflo   %0             \n\t"  \
-   " mfhi   %1             \n\t"  \
-   " xor    %2,%2,%2       \n\t"  \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc");
-
-#define SQRADDAC(i, j)           \
-__asm__(                         \
-   " multu  %6,%7          \n\t" \
-   " mflo   $12            \n\t" \
-   " mfhi   $13            \n\t" \
-   " addu    %0,%0,$12     \n\t" \
-   " sltu   $12,%0,$12     \n\t" \
-   " addu    %1,%1,$13     \n\t" \
-   " sltu   $13,%1,$13     \n\t" \
-   " addu    %1,%1,$12     \n\t" \
-   " sltu   $12,%1,$12     \n\t" \
-   " addu    %2,%2,$13     \n\t" \
-   " addu    %2,%2,$12     \n\t" \
-:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14");
-
-#define SQRADDDB                  \
-__asm__(                          \
-   " addu    %0,%0,%3       \n\t" \
-   " sltu   $10,%0,%3       \n\t" \
-   " addu    %1,%1,$10      \n\t" \
-   " sltu   $10,%1,$10      \n\t" \
-   " addu    %1,%1,%4       \n\t" \
-   " sltu   $11,%1,%4       \n\t" \
-   " addu    %2,%2,$10      \n\t" \
-   " addu    %2,%2,$11      \n\t" \
-   " addu    %2,%2,%5       \n\t" \
-                                  \
-   " addu    %0,%0,%3       \n\t" \
-   " sltu   $10,%0,%3       \n\t" \
-   " addu    %1,%1,$10      \n\t" \
-   " sltu   $10,%1,$10      \n\t" \
-   " addu    %1,%1,%4       \n\t" \
-   " sltu   $11,%1,%4       \n\t" \
-   " addu    %2,%2,$10      \n\t" \
-   " addu    %2,%2,$11      \n\t" \
-   " addu    %2,%2,%5       \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11");
-
-#else
-
-#define TFM_ISO
-
-/* ISO C portable code */
-
-#define COMBA_START
-
-#define CLEAR_CARRY \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define CARRY_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_FINI
-
-/* multiplies point i and j, updates carry "c1" and digit c2 */
-#define SQRADD(i, j)                                 \
-   do { fp_word t;                                   \
-   t = c0 + ((fp_word)i) * ((fp_word)j);  c0 = (fp_digit)t;    \
-   t = c1 + (t >> DIGIT_BIT);             c1 = (fp_digit)t;    \
-                                          c2 +=(fp_digit) (t >> DIGIT_BIT); \
-   } while (0);
-
-
-/* for squaring some of the terms are doubled... */
-#define SQRADD2(i, j)                                                 \
-   do { fp_word t;                                                    \
-   t  = ((fp_word)i) * ((fp_word)j);                                  \
-   tt = (fp_word)c0 + t;                 c0 = (fp_digit)tt;           \
-   tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt;           \
-                                         c2 +=(fp_digit)(tt >> DIGIT_BIT);     \
-   tt = (fp_word)c0 + t;                 c0 = (fp_digit)tt;                    \
-   tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt;            \
-                                         c2 +=(fp_digit)(tt >> DIGIT_BIT);     \
-   } while (0);
-
-#define SQRADDSC(i, j)                                                         \
-   do { fp_word t;                                                             \
-      t =  ((fp_word)i) * ((fp_word)j);                                        \
-      sc0 = (fp_digit)t; sc1 = (t >> DIGIT_BIT); sc2 = 0;                      \
-   } while (0);
-
-#define SQRADDAC(i, j)                                                         \
-   do { fp_word t;                                                             \
-   t = sc0 + ((fp_word)i) * ((fp_word)j);  sc0 =  (fp_digit)t;                 \
-   t = sc1 + (t >> DIGIT_BIT);             sc1 =  (fp_digit)t;                 \
-                                           sc2 += (fp_digit)(t >> DIGIT_BIT);  \
-   } while (0);
-
-#define SQRADDDB                                                               \
-   do { fp_word t;                                                             \
-   t = ((fp_word)sc0) + ((fp_word)sc0) + c0; c0 = (fp_digit)t;                 \
-   t = ((fp_word)sc1) + ((fp_word)sc1) + c1 + (t >> DIGIT_BIT);                \
-                                             c1 = (fp_digit)t;                 \
-   c2 = c2 + (fp_digit)(((fp_word)sc2) + ((fp_word)sc2) + (t >> DIGIT_BIT));   \
-   } while (0);
-
-#endif
-
-#ifdef TFM_SMALL_SET
-    #include "fp_sqr_comba_small_set.i"
-#endif
-
-#if defined(TFM_SQR3) && FP_SIZE >= 6
-    #include "fp_sqr_comba_3.i"
-#endif
-#if defined(TFM_SQR4) && FP_SIZE >= 8
-    #include "fp_sqr_comba_4.i"
-#endif
-#if defined(TFM_SQR6) && FP_SIZE >= 12
-    #include "fp_sqr_comba_6.i"
-#endif
-#if defined(TFM_SQR7) && FP_SIZE >= 14
-    #include "fp_sqr_comba_7.i"
-#endif
-#if defined(TFM_SQR8) && FP_SIZE >= 16
-    #include "fp_sqr_comba_8.i"
-#endif
-#if defined(TFM_SQR9) && FP_SIZE >= 18
-    #include "fp_sqr_comba_9.i"
-#endif
-#if defined(TFM_SQR12) && FP_SIZE >= 24
-    #include "fp_sqr_comba_12.i"
-#endif
-#if defined(TFM_SQR17) && FP_SIZE >= 34
-    #include "fp_sqr_comba_17.i"
-#endif
-#if defined(TFM_SQR20) && FP_SIZE >= 40
-    #include "fp_sqr_comba_20.i"
-#endif
-#if defined(TFM_SQR24) && FP_SIZE >= 48
-    #include "fp_sqr_comba_24.i"
-#endif
-#if defined(TFM_SQR28) && FP_SIZE >= 56
-    #include "fp_sqr_comba_28.i"
-#endif
-#if defined(TFM_SQR32) && FP_SIZE >= 64
-    #include "fp_sqr_comba_32.i"
-#endif
-#if defined(TFM_SQR48) && FP_SIZE >= 96
-    #include "fp_sqr_comba_48.i"
-#endif
-#if defined(TFM_SQR64) && FP_SIZE >= 128
-    #include "fp_sqr_comba_64.i"
-#endif
-/* end fp_sqr_comba.c asm */
-
-/* start fp_mul_comba.c asm */
-/* these are the combas.  Worship them. */
-#if defined(TFM_X86)
-/* Generic x86 optimized code */
-
-/* anything you need at the start */
-#define COMBA_START
-
-/* clear the chaining variables */
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-/* forward the carry to the next digit */
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-/* store the first sum */
-#define COMBA_STORE(x) \
-   x = c0;
-
-/* store the second sum [carry] */
-#define COMBA_STORE2(x) \
-   x = c1;
-
-/* anything you need at the end */
-#define COMBA_FINI
-
-/* this should multiply i and j  */
-#define MULADD(i, j)                                      \
-__asm__(                                                  \
-     "movl  %6,%%eax     \n\t"                            \
-     "mull  %7           \n\t"                            \
-     "addl  %%eax,%0     \n\t"                            \
-     "adcl  %%edx,%1     \n\t"                            \
-     "adcl  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","cc");
-
-#elif defined(TFM_X86_64)
-/* x86-64 optimized */
-
-/* anything you need at the start */
-#define COMBA_START
-
-/* clear the chaining variables */
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-/* forward the carry to the next digit */
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-/* store the first sum */
-#define COMBA_STORE(x) \
-   x = c0;
-
-/* store the second sum [carry] */
-#define COMBA_STORE2(x) \
-   x = c1;
-
-/* anything you need at the end */
-#define COMBA_FINI
-
-/* this should multiply i and j  */
-#define MULADD(i, j)                                      \
-__asm__  (                                                \
-     "movq  %6,%%rax     \n\t"                            \
-     "mulq  %7           \n\t"                            \
-     "addq  %%rax,%0     \n\t"                            \
-     "adcq  %%rdx,%1     \n\t"                            \
-     "adcq  $0,%2        \n\t"                            \
-     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j)  :"%rax","%rdx","cc");
-
-
-#if defined(HAVE_INTEL_MULX)
-#define MULADD_BODY(a,b,c)                              \
-    __asm__ volatile(                                   \
-         "movq  %[a0],%%rdx\n\t"                        \
-         "xorq  %%rcx, %%rcx\n\t"                       \
-         "movq  0(%[cp]),%%r8\n\t"                      \
-         "movq  8(%[cp]),%%r9\n\t"                      \
-         "movq  16(%[cp]),%%r10\n\t"                    \
-         "movq  24(%[cp]),%%r11\n\t"                    \
-         "movq  32(%[cp]),%%r12\n\t"                    \
-         "movq  40(%[cp]),%%r13\n\t"                    \
-                                                        \
-         "mulx  (%[bp]),%%rax, %%rbx\n\t"               \
-         "adoxq  %%rax, %%r8\n\t"                       \
-         "mulx  8(%[bp]),%%rax, %%rcx\n\t"              \
-         "adcxq  %%rbx, %%r9\n\t"                       \
-         "adoxq  %%rax, %%r9\n\t"                       \
-         "mulx  16(%[bp]),%%rax, %%rbx\n\t"             \
-         "adcxq  %%rcx, %%r10\n\t"                      \
-         "adoxq  %%rax, %%r10\n\t"                      \
-         "mulx  24(%[bp]),%%rax, %%rcx\n\t"             \
-         "adcxq  %%rbx, %%r11\n\t"                      \
-         "adoxq  %%rax, %%r11\n\t"                      \
-         "adcxq  %%rcx, %%r12\n\t"                      \
-         "mov $0, %%rdx\n\t"                            \
-         "adox %%rdx, %%r12\n\t"                        \
-         "adcx %%rdx, %%r13\n\t"                        \
-                                                        \
-         "movq  %%r8, 0(%[cp])\n\t"                     \
-         "movq  %%r9, 8(%[cp])\n\t"                     \
-         "movq  %%r10, 16(%[cp])\n\t"                   \
-         "movq  %%r11, 24(%[cp])\n\t"                   \
-         "movq  %%r12, 32(%[cp])\n\t"                   \
-         "movq  %%r13, 40(%[cp])\n\t"                   \
-      :                                                 \
-      : [a0] "r" (a->dp[ix]), [bp] "r" (&(b->dp[iy])),  \
-        [cp] "r" (&(c->dp[iz]))                         \
-      : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13",   \
-        "%rdx", "%rax", "%rcx", "%rbx"                  \
-    )
-
-#define TFM_INTEL_MUL_COMBA(a, b, c)       \
-    for (iz=0; iz<pa; iz++) c->dp[iz] = 0; \
-    for (ix=0; ix<a->used; ix++) {         \
-        for (iy=0; iy<b->used; iy+=4) {    \
-            iz = ix + iy;                  \
-            MULADD_BODY(a, b, c);          \
-        }                                  \
-    }
-#endif
-
-#elif defined(TFM_SSE2)
-/* use SSE2 optimizations */
-
-/* anything you need at the start */
-#define COMBA_START
-
-/* clear the chaining variables */
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-/* forward the carry to the next digit */
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-/* store the first sum */
-#define COMBA_STORE(x) \
-   x = c0;
-
-/* store the second sum [carry] */
-#define COMBA_STORE2(x) \
-   x = c1;
-
-/* anything you need at the end */
-#define COMBA_FINI \
-   __asm__("emms");
-
-/* this should multiply i and j  */
-#define MULADD(i, j)                                     \
-__asm__(                                                 \
-    "movd  %6,%%mm0     \n\t"                            \
-    "movd  %7,%%mm1     \n\t"                            \
-    "pmuludq %%mm1,%%mm0\n\t"                            \
-    "movd  %%mm0,%%eax  \n\t"                            \
-    "psrlq $32,%%mm0    \n\t"                            \
-    "addl  %%eax,%0     \n\t"                            \
-    "movd  %%mm0,%%eax  \n\t"                            \
-    "adcl  %%eax,%1     \n\t"                            \
-    "adcl  $0,%2        \n\t"                            \
-    :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","cc");
-
-#elif defined(TFM_ARM)
-/* ARM code */
-
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-#define MULADD(i, j)                                          \
-__asm__(                                                      \
-"  UMULL  r0,r1,%6,%7           \n\t"                         \
-"  ADDS   %0,%0,r0              \n\t"                         \
-"  ADCS   %1,%1,r1              \n\t"                         \
-"  ADC    %2,%2,#0              \n\t"                         \
-:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc");
-
-#elif defined(TFM_PPC32)
-/* For 32-bit PPC */
-
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-/* untested: will mulhwu change the flags?  Docs say no */
-#define MULADD(i, j)             \
-__asm__(                         \
-   " mullw  16,%6,%7       \n\t" \
-   " addc   %0,%0,16       \n\t" \
-   " mulhwu 16,%6,%7       \n\t" \
-   " adde   %1,%1,16       \n\t" \
-   " addze  %2,%2          \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16");
-
-#elif defined(TFM_PPC64)
-/* For 64-bit PPC */
-
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-/* untested: will mulhdu change the flags?  Docs say no */
-#define MULADD(i, j)              \
-____asm__(                        \
-   " mulld  r16,%6,%7       \n\t" \
-   " addc   %0,%0,16        \n\t" \
-   " mulhdu r16,%6,%7       \n\t" \
-   " adde   %1,%1,16        \n\t" \
-   " addze  %2,%2           \n\t" \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16");
-
-#elif defined(TFM_AVR32)
-
-/* ISO C code */
-
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-#define MULADD(i, j)             \
-____asm__(                       \
-   " mulu.d r2,%6,%7        \n\t"\
-   " add    %0,r2           \n\t"\
-   " adc    %1,%1,r3        \n\t"\
-   " acr    %2              \n\t"\
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2","r3");
-
-#elif defined(TFM_MIPS)
-
-/* MIPS */
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-#define MULADD(i, j)              \
-__asm__(                          \
-   " multu  %6,%7          \n\t"  \
-   " mflo   $12            \n\t"  \
-   " mfhi   $13            \n\t"  \
-   " addu    %0,%0,$12     \n\t"  \
-   " sltu   $12,%0,$12     \n\t"  \
-   " addu    %1,%1,$13     \n\t"  \
-   " sltu   $13,%1,$13     \n\t"  \
-   " addu    %1,%1,$12     \n\t"  \
-   " sltu   $12,%1,$12     \n\t"  \
-   " addu    %2,%2,$13     \n\t"  \
-   " addu    %2,%2,$12     \n\t"  \
-:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
-
-#else
-/* ISO C code */
-
-#define COMBA_START
-
-#define COMBA_CLEAR \
-   c0 = c1 = c2 = 0;
-
-#define COMBA_FORWARD \
-   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
-
-#define COMBA_STORE(x) \
-   x = c0;
-
-#define COMBA_STORE2(x) \
-   x = c1;
-
-#define COMBA_FINI
-
-#define MULADD(i, j)                                                                                                                                  \
-   do { fp_word t;                                      \
-   t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j);       \
-   c0 = (fp_digit)t;                                    \
-   t = (fp_word)c1 + (t >> DIGIT_BIT);                  \
-   c1 = (fp_digit)t;                                    \
-   c2 += (fp_digit)(t >> DIGIT_BIT);                    \
-   } while (0);
-
-#endif
-
-
-#ifdef TFM_SMALL_SET
-    #include "fp_mul_comba_small_set.i"
-#endif
-
-#if defined(TFM_MUL3) && FP_SIZE >= 6
-    #include "fp_mul_comba_3.i"
-#endif
-#if defined(TFM_MUL4) && FP_SIZE >= 8
-    #include "fp_mul_comba_4.i"
-#endif
-#if defined(TFM_MUL6) && FP_SIZE >= 12
-    #include "fp_mul_comba_6.i"
-#endif
-#if defined(TFM_MUL7) && FP_SIZE >= 14
-    #include "fp_mul_comba_7.i"
-#endif
-#if defined(TFM_MUL8) && FP_SIZE >= 16
-    #include "fp_mul_comba_8.i"
-#endif
-#if defined(TFM_MUL9) && FP_SIZE >= 18
-    #include "fp_mul_comba_9.i"
-#endif
-#if defined(TFM_MUL12) && FP_SIZE >= 24
-    #include "fp_mul_comba_12.i"
-#endif
-#if defined(TFM_MUL17) && FP_SIZE >= 34
-    #include "fp_mul_comba_17.i"
-#endif
-#if defined(TFM_MUL20) && FP_SIZE >= 40
-    #include "fp_mul_comba_20.i"
-#endif
-#if defined(TFM_MUL24) && FP_SIZE >= 48
-    #include "fp_mul_comba_24.i"
-#endif
-#if defined(TFM_MUL28) && FP_SIZE >= 56
-    #include "fp_mul_comba_28.i"
-#endif
-#if defined(TFM_MUL32) && FP_SIZE >= 64
-    #include "fp_mul_comba_32.i"
-#endif
-#if defined(TFM_MUL48) && FP_SIZE >= 96
-    #include "fp_mul_comba_48.i"
-#endif
-#if defined(TFM_MUL64) && FP_SIZE >= 128
-    #include "fp_mul_comba_64.i"
-#endif
-
-/* end fp_mul_comba.c asm */
-
-
--- a/wolfcrypt/src/asn.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13749 +0,0 @@
-/* asn.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-/*
-ASN Options:
- * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC
-    or wishing to save space.
- * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks.
- * ASN_DUMP_OID: Allows dump of OID information for debugging.
- * RSA_DECODE_EXTRA: Decodes extra information in RSA public key.
- * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName.
- * WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to
-    restore 3.13.0 behavior.
- * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer
-    must still be trusted)
- * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert
-    chain is not loaded. This only matches on subject and public key and
-    does not perform a PKI validation, so it is not a secure solution.
-    Only enabled for OCSP.
- * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
-    disable checking of OCSP subject hash with issuer hash.
- * WOLFSSL_ALT_CERT_CHAINS: Allows matching multiple CA's to validate
-    chain based on issuer and public key (includes signature confirmation)
-*/
-
-#ifndef NO_ASN
-
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/coding.h>
-#include <wolfssl/wolfcrypt/md2.h>
-#include <wolfssl/wolfcrypt/hmac.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/pwdbased.h>
-#include <wolfssl/wolfcrypt/des3.h>
-#include <wolfssl/wolfcrypt/aes.h>
-#include <wolfssl/wolfcrypt/wc_encrypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifndef NO_PWDBASED
-    #include <wolfssl/wolfcrypt/aes.h>
-#endif
-#ifndef NO_RC4
-    #include <wolfssl/wolfcrypt/arc4.h>
-#endif
-
-#ifdef HAVE_NTRU
-    #include "libntruencrypt/ntru_crypto.h"
-#endif
-
-#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
-    #include <wolfssl/wolfcrypt/sha512.h>
-#endif
-
-#ifndef NO_SHA256
-    #include <wolfssl/wolfcrypt/sha256.h>
-#endif
-
-#ifdef HAVE_ECC
-    #include <wolfssl/wolfcrypt/ecc.h>
-#endif
-
-#ifdef HAVE_ED25519
-    #include <wolfssl/wolfcrypt/ed25519.h>
-#endif
-
-#ifndef NO_RSA
-    #include <wolfssl/wolfcrypt/rsa.h>
-#endif
-
-#ifdef WOLFSSL_DEBUG_ENCODING
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #else
-        #include <stdio.h>
-    #endif
-#endif
-
-
-#ifdef _MSC_VER
-    /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
-    #pragma warning(disable: 4996)
-#endif
-
-#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
-
-WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
-                           word32 maxIdx)
-{
-    int     length = 0;
-    word32  idx = *inOutIdx;
-    byte    b;
-
-    *len = 0;    /* default length */
-
-    if ((idx + 1) > maxIdx) {   /* for first read */
-        WOLFSSL_MSG("GetLength bad index on input");
-        return BUFFER_E;
-    }
-
-    b = input[idx++];
-    if (b >= ASN_LONG_LENGTH) {
-        word32 bytes = b & 0x7F;
-
-        if ((idx + bytes) > maxIdx) {   /* for reading bytes */
-            WOLFSSL_MSG("GetLength bad long length");
-            return BUFFER_E;
-        }
-
-        while (bytes--) {
-            b = input[idx++];
-            length = (length << 8) | b;
-        }
-    }
-    else
-        length = b;
-
-    if ((idx + length) > maxIdx) {   /* for user of length */
-        WOLFSSL_MSG("GetLength value exceeds buffer length");
-        return BUFFER_E;
-    }
-
-    *inOutIdx = idx;
-    if (length > 0)
-        *len = length;
-
-    return length;
-}
-
-
-/* Get the DER/BER encoding of an ASN.1 header.
- *
- * input     Buffer holding DER/BER encoded data.
- * tag       ASN.1 tag value expected in header.
- * inOutIdx  Current index into buffer to parse.
- * len       The number of bytes in the ASN.1 data.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_PARSE_E when the expected tag is not found or length is invalid.
- *         Otherwise, the number of bytes in the ASN.1 data.
- */
-static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
-                        word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    byte   b;
-    int    length;
-
-    if ((idx + 1) > maxIdx)
-        return BUFFER_E;
-
-    b = input[idx++];
-    if (b != tag)
-        return ASN_PARSE_E;
-
-    if (GetLength(input, &idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    *len      = length;
-    *inOutIdx = idx;
-    return length;
-}
-
-WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
-                           word32 maxIdx)
-{
-    return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
-                        maxIdx);
-}
-
-
-WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
-                        word32 maxIdx)
-{
-    return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
-                        maxIdx);
-}
-
-/* Get the DER/BER encoded ASN.1 NULL element.
- * Ensure that the all fields are as expected and move index past the element.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_TAG_NULL_E when the NULL tag is not found.
- *         ASN_EXPECT_0_E when the length is not zero.
- *         Otherwise, 0 to indicate success.
- */
-static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    byte   b;
-
-    if ((idx + 2) > maxIdx)
-        return BUFFER_E;
-
-    b = input[idx++];
-    if (b != ASN_TAG_NULL)
-        return ASN_TAG_NULL_E;
-
-    if (input[idx++] != 0)
-        return ASN_EXPECT_0_E;
-
-    *inOutIdx = idx;
-    return 0;
-}
-
-/* Set the DER/BER encoding of the ASN.1 NULL element.
- *
- * output  Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static int SetASNNull(byte* output)
-{
-    output[0] = ASN_TAG_NULL;
-    output[1] = 0;
-
-    return 2;
-}
-
-/* Get the DER/BER encoding of an ASN.1 BOOLEAN.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1.
- *         Otherwise, 0 to indicate the value was false and 1 to indicate true.
- */
-static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    byte   b;
-
-    if ((idx + 3) > maxIdx)
-        return BUFFER_E;
-
-    b = input[idx++];
-    if (b != ASN_BOOLEAN)
-        return ASN_PARSE_E;
-
-    if (input[idx++] != 1)
-        return ASN_PARSE_E;
-
-    b = input[idx++] != 0;
-
-    *inOutIdx = idx;
-    return b;
-}
-
-#ifdef ASN1_SET_BOOLEAN
-/* Set the DER/BER encoding of the ASN.1 NULL element.
- * Note: Function not required as yet.
- *
- * val     Boolean value to encode.
- * output  Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static int SetBoolean(int val, byte* output)
-{
-    output[0] = ASN_BOOLEAN;
-    output[1] = 1;
-    output[2] = val ? -1 : 0;
-
-    return 3;
-}
-#endif
-
-/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * len       The number of bytes in the ASN.1 data.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_PARSE_E when the OCTET_STRING tag is not found or length is
- *         invalid.
- *         Otherwise, the number of bytes in the ASN.1 data.
- */
-static int GetOctetString(const byte* input, word32* inOutIdx, int* len,
-                          word32 maxIdx)
-{
-    return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx);
-}
-
-/* Get the DER/BER encoding of an ASN.1 INTEGER header.
- * Removes the leading zero byte when found.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * len       The number of bytes in the ASN.1 data (excluding any leading zero).
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_PARSE_E when the INTEGER tag is not found, length is invalid,
- *         or invalid use of or missing leading zero.
- *         Otherwise, 0 to indicate success.
- */
-static int GetASNInt(const byte* input, word32* inOutIdx, int* len,
-                     word32 maxIdx)
-{
-    int    ret;
-
-    ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx);
-    if (ret < 0)
-        return ret;
-
-    if (*len > 0) {
-        /* remove leading zero, unless there is only one 0x00 byte */
-        if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
-            (*inOutIdx)++;
-            (*len)--;
-
-            if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
-                return ASN_PARSE_E;
-        }
-    }
-
-    return 0;
-}
-
-/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
- * 7 bits.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_PARSE_E when the INTEGER tag is not found or length is invalid.
- *         Otherwise, the 7-bit value.
- */
-static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    byte   b;
-
-    if ((idx + 3) > maxIdx)
-        return BUFFER_E;
-
-    if (input[idx++] != ASN_INTEGER)
-        return ASN_PARSE_E;
-    if (input[idx++] != 1)
-        return ASN_PARSE_E;
-    b = input[idx++];
-
-    *inOutIdx = idx;
-    return b;
-}
-
-
-#if !defined(NO_DSA) && !defined(NO_SHA)
-static char sigSha1wDsaName[] = "SHAwDSA";
-#endif /* NO_DSA */
-#ifndef NO_RSA
-#ifdef WOLFSSL_MD2
-    static char sigMd2wRsaName[] = "MD2wRSA";
-#endif
-#ifndef NO_MD5
-    static char sigMd5wRsaName[] = "MD5wRSA";
-#endif
-#ifndef NO_SHA
-    static char sigSha1wRsaName[] = "SHAwRSA";
-#endif
-#ifdef WOLFSSL_SHA224
-    static char sigSha224wRsaName[] = "SHA224wRSA";
-#endif
-#ifndef NO_SHA256
-    static char sigSha256wRsaName[] = "SHA256wRSA";
-#endif
-#ifdef WOLFSSL_SHA384
-    static char sigSha384wRsaName[] = "SHA384wRSA";
-#endif
-#ifdef WOLFSSL_SHA512
-    static char sigSha512wRsaName[] = "SHA512wRSA";
-#endif
-#endif /* NO_RSA */
-#ifdef HAVE_ECC
-#ifndef NO_SHA
-    static char sigSha1wEcdsaName[] = "SHAwECDSA";
-#endif
-#ifdef WOLFSSL_SHA224
-    static char sigSha224wEcdsaName[] = "SHA224wECDSA";
-#endif
-#ifndef NO_SHA256
-    static char sigSha256wEcdsaName[] = "SHA256wECDSA";
-#endif
-#ifdef WOLFSSL_SHA384
-    static char sigSha384wEcdsaName[] = "SHA384wECDSA";
-#endif
-#ifdef WOLFSSL_SHA512
-    static char sigSha512wEcdsaName[] = "SHA512wECDSA";
-#endif
-#endif /* HAVE_ECC */
-static char sigUnknownName[] = "Unknown";
-
-
-/* Get the human readable string for a signature type
- *
- * oid  Oid value for signature
- */
-char* GetSigName(int oid) {
-    switch (oid) {
-    #if !defined(NO_DSA) && !defined(NO_SHA)
-        case CTC_SHAwDSA:
-            return sigSha1wDsaName;
-    #endif /* NO_DSA && NO_SHA */
-    #ifndef NO_RSA
-        #ifdef WOLFSSL_MD2
-        case CTC_MD2wRSA:
-            return sigMd2wRsaName;
-        #endif
-        #ifndef NO_MD5
-        case CTC_MD5wRSA:
-            return sigMd5wRsaName;
-        #endif
-        #ifndef NO_SHA
-        case CTC_SHAwRSA:
-            return sigSha1wRsaName;
-        #endif
-        #ifdef WOLFSSL_SHA224
-        case CTC_SHA224wRSA:
-            return sigSha224wRsaName;
-        #endif
-        #ifndef NO_SHA256
-        case CTC_SHA256wRSA:
-            return sigSha256wRsaName;
-        #endif
-        #ifdef WOLFSSL_SHA384
-        case CTC_SHA384wRSA:
-            return sigSha384wRsaName;
-        #endif
-        #ifdef WOLFSSL_SHA512
-        case CTC_SHA512wRSA:
-            return sigSha512wRsaName;
-        #endif
-    #endif /* NO_RSA */
-    #ifdef HAVE_ECC
-        #ifndef NO_SHA
-        case CTC_SHAwECDSA:
-            return sigSha1wEcdsaName;
-        #endif
-        #ifdef WOLFSSL_SHA224
-        case CTC_SHA224wECDSA:
-            return sigSha224wEcdsaName;
-        #endif
-        #ifndef NO_SHA256
-        case CTC_SHA256wECDSA:
-            return sigSha256wEcdsaName;
-        #endif
-        #ifdef WOLFSSL_SHA384
-        case CTC_SHA384wECDSA:
-            return sigSha384wEcdsaName;
-        #endif
-        #ifdef WOLFSSL_SHA512
-        case CTC_SHA512wECDSA:
-            return sigSha512wEcdsaName;
-        #endif
-    #endif /* HAVE_ECC */
-        default:
-            return sigUnknownName;
-    }
-}
-
-
-#if !defined(NO_DSA) || defined(HAVE_ECC) || \
-   (!defined(NO_RSA) && \
-        (defined(WOLFSSL_CERT_GEN) || \
-        ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))))
-/* Set the DER/BER encoding of the ASN.1 INTEGER header.
- *
- * len        Length of data to encode.
- * firstByte  First byte of data, most significant byte of integer, to encode.
- * output     Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static int SetASNInt(int len, byte firstByte, byte* output)
-{
-    word32 idx = 0;
-
-    output[idx++] = ASN_INTEGER;
-    if (firstByte & 0x80)
-        len++;
-    idx += SetLength(len, output + idx);
-    if (firstByte & 0x80)
-        output[idx++] = 0x00;
-
-    return idx;
-}
-#endif
-
-#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_CERT_GEN) || \
-    ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA))
-/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int.
- * The number is assumed to be positive.
- *
- * n       Multi-precision integer to encode.
- * maxSz   Maximum size of the encoded integer.
- *         A negative value indicates no check of length requested.
- * output  Buffer to write into.
- * returns BUFFER_E when the data is too long for the buffer.
- *         MP_TO_E when encoding the integer fails.
- *         Otherwise, the number of bytes added to the buffer.
- */
-static int SetASNIntMP(mp_int* n, int maxSz, byte* output)
-{
-    int idx = 0;
-    int leadingBit;
-    int length;
-    int err;
-
-    leadingBit = mp_leading_bit(n);
-    length = mp_unsigned_bin_size(n);
-    idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
-    if (maxSz >= 0 && (idx + length) > maxSz)
-        return BUFFER_E;
-
-    err = mp_to_unsigned_bin(n, output + idx);
-    if (err != MP_OKAY)
-        return MP_TO_E;
-    idx += length;
-
-    return idx;
-}
-#endif
-
-#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && defined(WOLFSSL_CERT_GEN)
-/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from
- * an RSA key.
- * The number is assumed to be positive.
- *
- * n       Multi-precision integer to encode.
- * output  Buffer to write into.
- * returns BUFFER_E when the data is too long for the buffer.
- *         MP_TO_E when encoding the integer fails.
- *         Otherwise, the number of bytes added to the buffer.
- */
-static int SetASNIntRSA(mp_int* n, byte* output)
-{
-    int idx = 0;
-    int leadingBit;
-    int length;
-    int err;
-
-    leadingBit = wc_Rsa_leading_bit(n);
-    length = wc_Rsa_unsigned_bin_size(n);
-    idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
-    if ((idx + length) > MAX_RSA_INT_SZ)
-        return BUFFER_E;
-
-    err = wc_Rsa_to_unsigned_bin(n, output + idx, length);
-    if (err != MP_OKAY)
-        return MP_TO_E;
-    idx += length;
-
-    return idx;
-}
-#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */
-
-/* Windows header clash for WinCE using GetVersion */
-WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
-                               int* version, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-
-    if ((idx + MIN_VERSION_SZ) > maxIdx)
-        return ASN_PARSE_E;
-
-    if (input[idx++] != ASN_INTEGER)
-        return ASN_PARSE_E;
-
-    if (input[idx++] != 0x01)
-        return ASN_VERSION_E;
-
-    *version  = input[idx++];
-    *inOutIdx = idx;
-
-    return *version;
-}
-
-
-#ifndef NO_PWDBASED
-/* Get small count integer, 32 bits or less */
-int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    word32 len;
-
-    *number = 0;
-
-    /* check for type and length bytes */
-    if ((idx + 2) > maxIdx)
-        return BUFFER_E;
-
-    if (input[idx++] != ASN_INTEGER)
-        return ASN_PARSE_E;
-
-    len = input[idx++];
-    if (len > 4)
-        return ASN_PARSE_E;
-
-    if (len + idx > maxIdx)
-        return ASN_PARSE_E;
-
-    while (len--) {
-        *number  = *number << 8 | input[idx++];
-    }
-
-    *inOutIdx = idx;
-
-    return *number;
-}
-
-
-/* Set small integer, 32 bits or less. DER encoding with no leading 0s
- * returns total amount written including ASN tag and length byte on success */
-static int SetShortInt(byte* input, word32* inOutIdx, word32 number,
-        word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    word32 len = 0;
-    int    i;
-    byte ar[MAX_LENGTH_SZ];
-
-    /* check for room for type and length bytes */
-    if ((idx + 2) > maxIdx)
-        return BUFFER_E;
-
-    input[idx++] = ASN_INTEGER;
-    idx++; /* place holder for length byte */
-    if (MAX_LENGTH_SZ + idx > maxIdx)
-        return ASN_PARSE_E;
-
-    /* find first non zero byte */
-    XMEMSET(ar, 0, MAX_LENGTH_SZ);
-    c32toa(number, ar);
-    for (i = 0; i < MAX_LENGTH_SZ; i++) {
-        if (ar[i] != 0) {
-            break;
-        }
-    }
-
-    /* handle case of 0 */
-    if (i == MAX_LENGTH_SZ) {
-        input[idx++] = 0; len++;
-    }
-
-    for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) {
-        input[idx++] = ar[i]; len++;
-    }
-
-    /* jump back to beginning of input buffer using unaltered inOutIdx value
-     * and set number of bytes for integer, then update the index value */
-    input[*inOutIdx + 1] = (byte)len;
-    *inOutIdx = idx;
-
-    return len + 2; /* size of integer bytes plus ASN TAG and length byte */
-}
-#endif /* !NO_PWDBASED */
-
-/* May not have one, not an error */
-static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version,
-                              word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-
-    WOLFSSL_ENTER("GetExplicitVersion");
-
-    if ((idx + 1) > maxIdx)
-        return BUFFER_E;
-
-    if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
-        *inOutIdx = ++idx;  /* skip header */
-        return GetMyVersion(input, inOutIdx, version, maxIdx);
-    }
-
-    /* go back as is */
-    *version = 0;
-
-    return 0;
-}
-
-int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    int    ret;
-    int    length;
-
-    ret = GetASNInt(input, &idx, &length, maxIdx);
-    if (ret != 0)
-        return ret;
-
-    if (mp_init(mpi) != MP_OKAY)
-        return MP_INIT_E;
-
-    if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) {
-        mp_clear(mpi);
-        return ASN_GETINT_E;
-    }
-
-#ifdef HAVE_WOLF_BIGINT
-    if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) {
-        mp_clear(mpi);
-        return ASN_GETINT_E;
-    }
-#endif /* HAVE_WOLF_BIGINT */
-
-    *inOutIdx = idx + length;
-
-    return 0;
-}
-
-#if !defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    int    ret;
-    int    length;
-
-    ret = GetASNInt(input, &idx, &length, maxIdx);
-    if (ret != 0)
-        return ret;
-
-    *inOutIdx = idx + length;
-
-    return 0;
-}
-#endif
-#endif
-
-static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
-                          word32 maxIdx, int zeroBits, byte* unusedBits)
-{
-    word32 idx = *inOutIdx;
-    int    length;
-    byte   b;
-
-    if ((idx + 1) > maxIdx)
-        return BUFFER_E;
-
-    if (input[idx++] != ASN_BIT_STRING)
-        return ASN_BITSTR_E;
-
-    if (GetLength(input, &idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    /* extra sanity check that length is greater than 0 */
-    if (length <= 0) {
-        WOLFSSL_MSG("Error length was 0 in CheckBitString");
-        return BUFFER_E;
-    }
-
-    if (idx + 1 > maxIdx) {
-        WOLFSSL_MSG("Attempted buffer read larger than input buffer");
-        return BUFFER_E;
-    }
-
-    b = input[idx];
-    if (zeroBits && b != 0x00)
-        return ASN_EXPECT_0_E;
-    if (b >= 0x08)
-        return ASN_PARSE_E;
-    if (b != 0) {
-        if ((byte)(input[idx + length - 1] << (8 - b)) != 0)
-            return ASN_PARSE_E;
-    }
-    idx++;
-    length--; /* length has been checked for greater than 0 */
-
-    *inOutIdx = idx;
-    if (len != NULL)
-        *len = length;
-    if (unusedBits != NULL)
-        *unusedBits = b;
-
-    return 0;
-}
-
-/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 (with CertGen or KeyGen) */
-#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
-        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
-     defined(HAVE_ECC) || \
-    (defined(HAVE_ED25519) && \
-        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
-
-/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
- *
- * len         Length of data to encode.
- * unusedBits  The number of unused bits in the last byte of data.
- *             That is, the number of least significant zero bits before a one.
- *             The last byte is the most-significant non-zero byte of a number.
- * output      Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static word32 SetBitString(word32 len, byte unusedBits, byte* output)
-{
-    word32 idx = 0;
-
-    output[idx++] = ASN_BIT_STRING;
-    idx += SetLength(len + 1, output + idx);
-    output[idx++] = unusedBits;
-
-    return idx;
-}
-#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */
-
-#ifdef ASN_BER_TO_DER
-/* Convert a BER encoding with indefinite length items to DER.
- *
- * ber    BER encoded data.
- * berSz  Length of BER encoded data.
- * der    Buffer to hold DER encoded version of data.
- *        NULL indicates only the length is required.
- * derSz  The size of the buffer to hold the DER encoded data.
- *        Will be set if der is NULL, otherwise the value is checked as der is
- *        filled.
- * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
- * derSz are NULL.
- */
-int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz)
-{
-    int ret;
-    word32 i, j, k;
-    int len, l;
-    int indef;
-    int depth = 0;
-    byte type;
-    word32 cnt, sz;
-    word32 outSz;
-    byte lenBytes[4];
-
-    if (ber == NULL || derSz == NULL)
-        return BAD_FUNC_ARG;
-
-    outSz = *derSz;
-
-    for (i = 0, j = 0; i < berSz; ) {
-        /* Check that there is data for an ASN item to parse. */
-        if (i + 2 > berSz)
-            return ASN_PARSE_E;
-
-        /* End Of Content (EOC) mark end of indefinite length items.
-         * EOCs are not encoded in DER.
-         * Keep track of no. indefinite length items that have not been
-         * terminated in depth.
-         */
-        if (ber[i] == 0 && ber[i+1] == 0) {
-            if (depth == 0)
-                break;
-            if (--depth == 0)
-                break;
-
-            i += 2;
-            continue;
-        }
-
-        /* Indefinite length is encoded as: 0x80 */
-        type = ber[i];
-        indef = ber[i+1] == ASN_INDEF_LENGTH;
-        if (indef && (type & 0xC0) == 0 &&
-                                   ber[i] != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
-                                   ber[i] != (ASN_SET      | ASN_CONSTRUCTED)) {
-            /* Indefinite length OCTET STRING or other simple type.
-             * Put all the data into one entry.
-             */
-
-            /* Type no longer constructed. */
-            type &= ~ASN_CONSTRUCTED;
-            if (der != NULL) {
-                /* Ensure space for type. */
-                if (j + 1 >= outSz)
-                    return BUFFER_E;
-                der[j] = type;
-            }
-            i++; j++;
-            /* Skip indefinite length. */
-            i++;
-
-            /* There must be further ASN1 items to combine. */
-            if (i + 2 > berSz)
-                return ASN_PARSE_E;
-
-            /* Calculate length of combined data. */
-            len = 0;
-            k = i;
-            while (ber[k] != 0x00) {
-                /* Each ASN item must be the same type as the constructed. */
-                if (ber[k] != type)
-                    return ASN_PARSE_E;
-                k++;
-
-                ret = GetLength(ber, &k, &l, berSz);
-                if (ret < 0)
-                    return ASN_PARSE_E;
-                k += l;
-                len += l;
-
-                /* Must at least have terminating EOC. */
-                if (k + 2 > berSz)
-                    return ASN_PARSE_E;
-            }
-            /* Ensure a valid EOC ASN item. */
-            if (ber[k+1] != 0x00)
-                return ASN_PARSE_E;
-
-            if (der == NULL) {
-                /* Add length of ASN item length encoding and data. */
-                j += SetLength(len, lenBytes);
-                j += len;
-            }
-            else {
-                /* Check space for encoded length. */
-                if (SetLength(len, lenBytes) > outSz - j)
-                    return BUFFER_E;
-                /* Encode new length. */
-                j += SetLength(len, der + j);
-
-                /* Encode data in single item. */
-                k = i;
-                while (ber[k] != 0x00) {
-                    /* Skip ASN type. */
-                    k++;
-
-                    /* Find length of data in ASN item. */
-                    ret = GetLength(ber, &k, &l, berSz);
-                    if (ret < 0)
-                        return ASN_PARSE_E;
-
-                    /* Ensure space for data and copy in. */
-                    if (j + l > outSz)
-                        return BUFFER_E;
-                    XMEMCPY(der + j, ber + k, l);
-                    k += l; j += l;
-                }
-            }
-            /* Continue conversion after EOC. */
-            i = k + 2;
-
-            continue;
-        }
-
-        if (der != NULL) {
-            /* Ensure space for type and at least one byte of length. */
-            if (j + 1 >= outSz)
-                return BUFFER_E;
-            /* Put in type. */
-            der[j] = ber[i];
-        }
-        i++; j++;
-
-        if (indef) {
-            /* Skip indefinite length. */
-            i++;
-            /* Calculate the size of the data inside constructed. */
-            ret = wc_BerToDer(ber + i, berSz - i, NULL, &sz);
-            if (ret != LENGTH_ONLY_E)
-                return ret;
-
-            if (der != NULL) {
-                /* Ensure space for encoded length. */
-                if (SetLength(sz, lenBytes) > outSz - j)
-                    return BUFFER_E;
-                /* Encode real length. */
-                j += SetLength(sz, der + j);
-            }
-            else {
-                /* Add size of encoded length. */
-                j += SetLength(sz, lenBytes);
-            }
-
-            /* Another EOC to find. */
-            depth++;
-        }
-        else {
-            /* Get the size of the encode length and length value. */
-            cnt = i;
-            ret = GetLength(ber, &cnt, &len, berSz);
-            if (ret < 0)
-                return ASN_PARSE_E;
-            cnt -= i;
-
-            /* Check there is enough data to copy out. */
-            if (i + cnt + len > berSz)
-                return ASN_PARSE_E;
-
-            if (der != NULL) {
-                /* Ensure space in DER buffer. */
-                if (j + cnt + len > outSz)
-                    return BUFFER_E;
-                /* Copy length and data into DER buffer. */
-                XMEMCPY(der + j, ber + i, cnt + len);
-            }
-            /* Continue conversion after this ASN item. */
-            i += cnt + len;
-            j += cnt + len;
-        }
-    }
-
-    if (depth >= 1)
-        return ASN_PARSE_E;
-
-    /* Return length if no buffer to write to. */
-    if (der == NULL) {
-        *derSz = j;
-        return LENGTH_ONLY_E;
-    }
-
-    return 0;
-}
-#endif
-
-#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
-
-#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
-    defined(HAVE_ECC) || defined(HAVE_ED25519)
-
-#ifdef WOLFSSL_CERT_EXT
-/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
- *
- * val         16-bit value to encode.
- * output      Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static word32 SetBitString16Bit(word16 val, byte* output)
-{
-    word32 idx;
-    int    len;
-    byte   lastByte;
-    byte   unusedBits = 0;
-
-    if ((val >> 8) != 0) {
-        len = 2;
-        lastByte = (byte)(val >> 8);
-    }
-    else {
-        len = 1;
-        lastByte = (byte)val;
-    }
-
-    while (((lastByte >> unusedBits) & 0x01) == 0x00)
-        unusedBits++;
-
-    idx = SetBitString(len, unusedBits, output);
-    output[idx++] = (byte)val;
-    if (len > 1)
-        output[idx++] = (byte)(val >> 8);
-
-    return idx;
-}
-#endif /* WOLFSSL_CERT_EXT */
-#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */
-#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */
-
-
-
-/* hashType */
-#ifdef WOLFSSL_MD2
-    static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2};
-#endif
-#ifndef NO_MD5
-    static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5};
-#endif
-#ifndef NO_SHA
-    static const byte hashSha1hOid[] = {43, 14, 3, 2, 26};
-#endif
-#ifdef WOLFSSL_SHA224
-    static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4};
-#endif
-#ifndef NO_SHA256
-    static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1};
-#endif
-#ifdef WOLFSSL_SHA384
-    static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2};
-#endif
-#ifdef WOLFSSL_SHA512
-    static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3};
-#endif
-
-/* hmacType */
-#ifndef NO_HMAC
-    #ifdef WOLFSSL_SHA224
-    static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8};
-    #endif
-    #ifndef NO_SHA256
-    static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9};
-    #endif
-    #ifdef WOLFSSL_SHA384
-    static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10};
-    #endif
-    #ifdef WOLFSSL_SHA512
-    static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11};
-    #endif
-#endif
-
-/* sigType */
-#if !defined(NO_DSA) && !defined(NO_SHA)
-    static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3};
-#endif /* NO_DSA */
-#ifndef NO_RSA
-    #ifdef WOLFSSL_MD2
-    static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2};
-    #endif
-    #ifndef NO_MD5
-    static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4};
-    #endif
-    #ifndef NO_SHA
-    static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5};
-    #endif
-    #ifdef WOLFSSL_SHA224
-    static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14};
-    #endif
-    #ifndef NO_SHA256
-    static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11};
-    #endif
-    #ifdef WOLFSSL_SHA384
-    static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12};
-    #endif
-    #ifdef WOLFSSL_SHA512
-    static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13};
-    #endif
-#endif /* NO_RSA */
-#ifdef HAVE_ECC
-    #ifndef NO_SHA
-    static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1};
-    #endif
-    #ifdef WOLFSSL_SHA224
-    static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1};
-    #endif
-    #ifndef NO_SHA256
-    static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2};
-    #endif
-    #ifdef WOLFSSL_SHA384
-    static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3};
-    #endif
-    #ifdef WOLFSSL_SHA512
-    static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4};
-    #endif
-#endif /* HAVE_ECC */
-#ifdef HAVE_ED25519
-    static const byte sigEd25519Oid[] = {43, 101, 112};
-#endif /* HAVE_ED25519 */
-
-/* keyType */
-#ifndef NO_DSA
-    static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1};
-#endif /* NO_DSA */
-#ifndef NO_RSA
-    static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1};
-#endif /* NO_RSA */
-#ifdef HAVE_NTRU
-    static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1};
-#endif /* HAVE_NTRU */
-#ifdef HAVE_ECC
-    static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1};
-#endif /* HAVE_ECC */
-#ifdef HAVE_ED25519
-    static const byte keyEd25519Oid[] = {43, 101, 112};
-#endif /* HAVE_ED25519 */
-
-/* curveType */
-#ifdef HAVE_ECC
-    /* See "ecc_sets" table in ecc.c */
-#endif /* HAVE_ECC */
-
-#ifdef HAVE_AES_CBC
-/* blkType */
-    #ifdef WOLFSSL_AES_128
-    static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2};
-    #endif
-    #ifdef WOLFSSL_AES_192
-    static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22};
-    #endif
-    #ifdef WOLFSSL_AES_256
-    static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42};
-    #endif
-#endif /* HAVE_AES_CBC */
-
-#ifndef NO_DES3
-    static const byte blkDesCbcOid[]  = {43, 14, 3, 2, 7};
-    static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7};
-#endif
-
-/* keyWrapType */
-#ifdef WOLFSSL_AES_128
-    static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5};
-#endif
-#ifdef WOLFSSL_AES_192
-    static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25};
-#endif
-#ifdef WOLFSSL_AES_256
-    static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45};
-#endif
-
-/* cmsKeyAgreeType */
-#ifndef NO_SHA
-    static const byte dhSinglePass_stdDH_sha1kdf_Oid[]   =
-                                          {43, 129, 5, 16, 134, 72, 63, 0, 2};
-#endif
-#ifdef WOLFSSL_SHA224
-    static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0};
-#endif
-#ifndef NO_SHA256
-    static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1};
-#endif
-#ifdef WOLFSSL_SHA384
-    static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2};
-#endif
-#ifdef WOLFSSL_SHA512
-    static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3};
-#endif
-
-/* 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};
-#endif /* HAVE_OCSP */
-
-/* certExtType */
-static const byte extBasicCaOid[] = {85, 29, 19};
-static const byte extAltNamesOid[] = {85, 29, 17};
-static const byte extCrlDistOid[] = {85, 29, 31};
-static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1};
-static const byte extAuthKeyOid[] = {85, 29, 35};
-static const byte extSubjKeyOid[] = {85, 29, 14};
-static const byte extCertPolicyOid[] = {85, 29, 32};
-static const byte extKeyUsageOid[] = {85, 29, 15};
-static const byte extInhibitAnyOid[] = {85, 29, 54};
-static const byte extExtKeyUsageOid[] = {85, 29, 37};
-#ifndef IGNORE_NAME_CONSTRAINTS
-    static const byte extNameConsOid[] = {85, 29, 30};
-#endif
-
-/* certAuthInfoType */
-#ifdef HAVE_OCSP
-    static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1};
-#endif
-static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2};
-
-/* certPolicyType */
-static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0};
-
-/* certKeyUseType */
-static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4};
-
-/* certKeyUseType */
-static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0};
-static const byte extExtKeyUsageServerAuthOid[]   = {43, 6, 1, 5, 5, 7, 3, 1};
-static const byte extExtKeyUsageClientAuthOid[]   = {43, 6, 1, 5, 5, 7, 3, 2};
-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};
-
-/* kdfType */
-static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12};
-
-/* PKCS5 */
-#if !defined(NO_DES3) && !defined(NO_SHA)
-static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10};
-#endif
-
-/* PKCS12 */
-#if !defined(NO_RC4) && !defined(NO_SHA)
-static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1};
-#endif
-#if !defined(NO_DES3) && !defined(NO_SHA)
-static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3};
-#endif
-
-
-/* returns a pointer to the OID string on success and NULL on fail */
-const byte* OidFromId(word32 id, word32 type, word32* oidSz)
-{
-    const byte* oid = NULL;
-
-    *oidSz = 0;
-
-    switch (type) {
-
-        case oidHashType:
-            switch (id) {
-            #ifdef WOLFSSL_MD2
-                case MD2h:
-                    oid = hashMd2hOid;
-                    *oidSz = sizeof(hashMd2hOid);
-                    break;
-            #endif
-            #ifndef NO_MD5
-                case MD5h:
-                    oid = hashMd5hOid;
-                    *oidSz = sizeof(hashMd5hOid);
-                    break;
-            #endif
-            #ifndef NO_SHA
-                case SHAh:
-                    oid = hashSha1hOid;
-                    *oidSz = sizeof(hashSha1hOid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA224
-                case SHA224h:
-                    oid = hashSha224hOid;
-                    *oidSz = sizeof(hashSha224hOid);
-                    break;
-            #endif
-            #ifndef NO_SHA256
-                case SHA256h:
-                    oid = hashSha256hOid;
-                    *oidSz = sizeof(hashSha256hOid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA384
-                case SHA384h:
-                    oid = hashSha384hOid;
-                    *oidSz = sizeof(hashSha384hOid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA512
-                case SHA512h:
-                    oid = hashSha512hOid;
-                    *oidSz = sizeof(hashSha512hOid);
-                    break;
-            #endif
-            }
-            break;
-
-        case oidSigType:
-            switch (id) {
-                #if !defined(NO_DSA) && !defined(NO_SHA)
-                case CTC_SHAwDSA:
-                    oid = sigSha1wDsaOid;
-                    *oidSz = sizeof(sigSha1wDsaOid);
-                    break;
-                #endif /* NO_DSA */
-                #ifndef NO_RSA
-                #ifdef WOLFSSL_MD2
-                case CTC_MD2wRSA:
-                    oid = sigMd2wRsaOid;
-                    *oidSz = sizeof(sigMd2wRsaOid);
-                    break;
-                #endif
-                #ifndef NO_MD5
-                case CTC_MD5wRSA:
-                    oid = sigMd5wRsaOid;
-                    *oidSz = sizeof(sigMd5wRsaOid);
-                    break;
-                #endif
-                #ifndef NO_SHA
-                case CTC_SHAwRSA:
-                    oid = sigSha1wRsaOid;
-                    *oidSz = sizeof(sigSha1wRsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA224
-                case CTC_SHA224wRSA:
-                    oid = sigSha224wRsaOid;
-                    *oidSz = sizeof(sigSha224wRsaOid);
-                    break;
-                #endif
-                #ifndef NO_SHA256
-                case CTC_SHA256wRSA:
-                    oid = sigSha256wRsaOid;
-                    *oidSz = sizeof(sigSha256wRsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA384
-                case CTC_SHA384wRSA:
-                    oid = sigSha384wRsaOid;
-                    *oidSz = sizeof(sigSha384wRsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA512
-                case CTC_SHA512wRSA:
-                    oid = sigSha512wRsaOid;
-                    *oidSz = sizeof(sigSha512wRsaOid);
-                    break;
-                #endif /* WOLFSSL_SHA512 */
-                #endif /* NO_RSA */
-                #ifdef HAVE_ECC
-                #ifndef NO_SHA
-                case CTC_SHAwECDSA:
-                    oid = sigSha1wEcdsaOid;
-                    *oidSz = sizeof(sigSha1wEcdsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA224
-                case CTC_SHA224wECDSA:
-                    oid = sigSha224wEcdsaOid;
-                    *oidSz = sizeof(sigSha224wEcdsaOid);
-                    break;
-                #endif
-                #ifndef NO_SHA256
-                case CTC_SHA256wECDSA:
-                    oid = sigSha256wEcdsaOid;
-                    *oidSz = sizeof(sigSha256wEcdsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA384
-                case CTC_SHA384wECDSA:
-                    oid = sigSha384wEcdsaOid;
-                    *oidSz = sizeof(sigSha384wEcdsaOid);
-                    break;
-                #endif
-                #ifdef WOLFSSL_SHA512
-                case CTC_SHA512wECDSA:
-                    oid = sigSha512wEcdsaOid;
-                    *oidSz = sizeof(sigSha512wEcdsaOid);
-                    break;
-                #endif
-                #endif /* HAVE_ECC */
-                #ifdef HAVE_ED25519
-                case CTC_ED25519:
-                    oid = sigEd25519Oid;
-                    *oidSz = sizeof(sigEd25519Oid);
-                    break;
-                #endif
-                default:
-                    break;
-            }
-            break;
-
-        case oidKeyType:
-            switch (id) {
-                #ifndef NO_DSA
-                case DSAk:
-                    oid = keyDsaOid;
-                    *oidSz = sizeof(keyDsaOid);
-                    break;
-                #endif /* NO_DSA */
-                #ifndef NO_RSA
-                case RSAk:
-                    oid = keyRsaOid;
-                    *oidSz = sizeof(keyRsaOid);
-                    break;
-                #endif /* NO_RSA */
-                #ifdef HAVE_NTRU
-                case NTRUk:
-                    oid = keyNtruOid;
-                    *oidSz = sizeof(keyNtruOid);
-                    break;
-                #endif /* HAVE_NTRU */
-                #ifdef HAVE_ECC
-                case ECDSAk:
-                    oid = keyEcdsaOid;
-                    *oidSz = sizeof(keyEcdsaOid);
-                    break;
-                #endif /* HAVE_ECC */
-                #ifdef HAVE_ED25519
-                case ED25519k:
-                    oid = keyEd25519Oid;
-                    *oidSz = sizeof(keyEd25519Oid);
-                    break;
-                #endif /* HAVE_ED25519 */
-                default:
-                    break;
-            }
-            break;
-
-        #ifdef HAVE_ECC
-        case oidCurveType:
-            if (wc_ecc_get_oid(id, &oid, oidSz) < 0) {
-                WOLFSSL_MSG("ECC OID not found");
-            }
-            break;
-        #endif /* HAVE_ECC */
-
-        case oidBlkType:
-            switch (id) {
-    #ifdef HAVE_AES_CBC
-        #ifdef WOLFSSL_AES_128
-                case AES128CBCb:
-                    oid = blkAes128CbcOid;
-                    *oidSz = sizeof(blkAes128CbcOid);
-                    break;
-        #endif
-        #ifdef WOLFSSL_AES_192
-                case AES192CBCb:
-                    oid = blkAes192CbcOid;
-                    *oidSz = sizeof(blkAes192CbcOid);
-                    break;
-        #endif
-        #ifdef WOLFSSL_AES_256
-                case AES256CBCb:
-                    oid = blkAes256CbcOid;
-                    *oidSz = sizeof(blkAes256CbcOid);
-                    break;
-        #endif
-    #endif /* HAVE_AES_CBC */
-    #ifndef NO_DES3
-                case DESb:
-                    oid = blkDesCbcOid;
-                    *oidSz = sizeof(blkDesCbcOid);
-                    break;
-                case DES3b:
-                    oid = blkDes3CbcOid;
-                    *oidSz = sizeof(blkDes3CbcOid);
-                    break;
-    #endif /* !NO_DES3 */
-            }
-            break;
-
-        #ifdef HAVE_OCSP
-        case oidOcspType:
-            switch (id) {
-                case OCSP_BASIC_OID:
-                    oid = ocspBasicOid;
-                    *oidSz = sizeof(ocspBasicOid);
-                    break;
-                case OCSP_NONCE_OID:
-                    oid = ocspNonceOid;
-                    *oidSz = sizeof(ocspNonceOid);
-                    break;
-            }
-            break;
-        #endif /* HAVE_OCSP */
-
-        case oidCertExtType:
-            switch (id) {
-                case BASIC_CA_OID:
-                    oid = extBasicCaOid;
-                    *oidSz = sizeof(extBasicCaOid);
-                    break;
-                case ALT_NAMES_OID:
-                    oid = extAltNamesOid;
-                    *oidSz = sizeof(extAltNamesOid);
-                    break;
-                case CRL_DIST_OID:
-                    oid = extCrlDistOid;
-                    *oidSz = sizeof(extCrlDistOid);
-                    break;
-                case AUTH_INFO_OID:
-                    oid = extAuthInfoOid;
-                    *oidSz = sizeof(extAuthInfoOid);
-                    break;
-                case AUTH_KEY_OID:
-                    oid = extAuthKeyOid;
-                    *oidSz = sizeof(extAuthKeyOid);
-                    break;
-                case SUBJ_KEY_OID:
-                    oid = extSubjKeyOid;
-                    *oidSz = sizeof(extSubjKeyOid);
-                    break;
-                case CERT_POLICY_OID:
-                    oid = extCertPolicyOid;
-                    *oidSz = sizeof(extCertPolicyOid);
-                    break;
-                case KEY_USAGE_OID:
-                    oid = extKeyUsageOid;
-                    *oidSz = sizeof(extKeyUsageOid);
-                    break;
-                case INHIBIT_ANY_OID:
-                    oid = extInhibitAnyOid;
-                    *oidSz = sizeof(extInhibitAnyOid);
-                    break;
-                case EXT_KEY_USAGE_OID:
-                    oid = extExtKeyUsageOid;
-                    *oidSz = sizeof(extExtKeyUsageOid);
-                    break;
-            #ifndef IGNORE_NAME_CONSTRAINTS
-                case NAME_CONS_OID:
-                    oid = extNameConsOid;
-                    *oidSz = sizeof(extNameConsOid);
-                    break;
-            #endif
-            }
-            break;
-
-        case oidCertAuthInfoType:
-            switch (id) {
-            #ifdef HAVE_OCSP
-                case AIA_OCSP_OID:
-                    oid = extAuthInfoOcspOid;
-                    *oidSz = sizeof(extAuthInfoOcspOid);
-                    break;
-            #endif
-                case AIA_CA_ISSUER_OID:
-                    oid = extAuthInfoCaIssuerOid;
-                    *oidSz = sizeof(extAuthInfoCaIssuerOid);
-                    break;
-            }
-            break;
-
-        case oidCertPolicyType:
-            switch (id) {
-                case CP_ANY_OID:
-                    oid = extCertPolicyAnyOid;
-                    *oidSz = sizeof(extCertPolicyAnyOid);
-                    break;
-            }
-            break;
-
-        case oidCertAltNameType:
-            switch (id) {
-                case HW_NAME_OID:
-                    oid = extAltNamesHwNameOid;
-                    *oidSz = sizeof(extAltNamesHwNameOid);
-                    break;
-            }
-            break;
-
-        case oidCertKeyUseType:
-            switch (id) {
-                case EKU_ANY_OID:
-                    oid = extExtKeyUsageAnyOid;
-                    *oidSz = sizeof(extExtKeyUsageAnyOid);
-                    break;
-                case EKU_SERVER_AUTH_OID:
-                    oid = extExtKeyUsageServerAuthOid;
-                    *oidSz = sizeof(extExtKeyUsageServerAuthOid);
-                    break;
-                case EKU_CLIENT_AUTH_OID:
-                    oid = extExtKeyUsageClientAuthOid;
-                    *oidSz = sizeof(extExtKeyUsageClientAuthOid);
-                    break;
-                case EKU_CODESIGNING_OID:
-                    oid = extExtKeyUsageCodeSigningOid;
-                    *oidSz = sizeof(extExtKeyUsageCodeSigningOid);
-                    break;
-                case EKU_EMAILPROTECT_OID:
-                    oid = extExtKeyUsageEmailProtectOid;
-                    *oidSz = sizeof(extExtKeyUsageEmailProtectOid);
-                    break;
-                case EKU_TIMESTAMP_OID:
-                    oid = extExtKeyUsageTimestampOid;
-                    *oidSz = sizeof(extExtKeyUsageTimestampOid);
-                    break;
-                case EKU_OCSP_SIGN_OID:
-                    oid = extExtKeyUsageOcspSignOid;
-                    *oidSz = sizeof(extExtKeyUsageOcspSignOid);
-                    break;
-            }
-            break;
-
-        case oidKdfType:
-            switch (id) {
-                case PBKDF2_OID:
-                    oid = pbkdf2Oid;
-                    *oidSz = sizeof(pbkdf2Oid);
-                    break;
-            }
-            break;
-
-        case oidPBEType:
-            switch (id) {
-        #if !defined(NO_SHA) && !defined(NO_RC4)
-                case PBE_SHA1_RC4_128:
-                    oid = pbeSha1RC4128;
-                    *oidSz = sizeof(pbeSha1RC4128);
-                    break;
-        #endif
-        #if !defined(NO_SHA) && !defined(NO_DES3)
-                case PBE_SHA1_DES:
-                    oid = pbeSha1Des;
-                    *oidSz = sizeof(pbeSha1Des);
-                    break;
-
-        #endif
-        #if !defined(NO_SHA) && !defined(NO_DES3)
-                case PBE_SHA1_DES3:
-                    oid = pbeSha1Des3;
-                    *oidSz = sizeof(pbeSha1Des3);
-                    break;
-        #endif
-            }
-            break;
-
-        case oidKeyWrapType:
-            switch (id) {
-            #ifdef WOLFSSL_AES_128
-                case AES128_WRAP:
-                    oid = wrapAes128Oid;
-                    *oidSz = sizeof(wrapAes128Oid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_AES_192
-                case AES192_WRAP:
-                    oid = wrapAes192Oid;
-                    *oidSz = sizeof(wrapAes192Oid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_AES_256
-                case AES256_WRAP:
-                    oid = wrapAes256Oid;
-                    *oidSz = sizeof(wrapAes256Oid);
-                    break;
-            #endif
-            }
-            break;
-
-        case oidCmsKeyAgreeType:
-            switch (id) {
-            #ifndef NO_SHA
-                case dhSinglePass_stdDH_sha1kdf_scheme:
-                    oid = dhSinglePass_stdDH_sha1kdf_Oid;
-                    *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA224
-                case dhSinglePass_stdDH_sha224kdf_scheme:
-                    oid = dhSinglePass_stdDH_sha224kdf_Oid;
-                    *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid);
-                    break;
-            #endif
-            #ifndef NO_SHA256
-                case dhSinglePass_stdDH_sha256kdf_scheme:
-                    oid = dhSinglePass_stdDH_sha256kdf_Oid;
-                    *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA384
-                case dhSinglePass_stdDH_sha384kdf_scheme:
-                    oid = dhSinglePass_stdDH_sha384kdf_Oid;
-                    *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid);
-                    break;
-            #endif
-            #ifdef WOLFSSL_SHA512
-                case dhSinglePass_stdDH_sha512kdf_scheme:
-                    oid = dhSinglePass_stdDH_sha512kdf_Oid;
-                    *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid);
-                    break;
-            #endif
-            }
-            break;
-
-#ifndef NO_HMAC
-        case oidHmacType:
-            switch (id) {
-        #ifdef WOLFSSL_SHA224
-                case HMAC_SHA224_OID:
-                    oid = hmacSha224Oid;
-                    *oidSz = sizeof(hmacSha224Oid);
-                    break;
-        #endif
-        #ifndef NO_SHA256
-                case HMAC_SHA256_OID:
-                    oid = hmacSha256Oid;
-                    *oidSz = sizeof(hmacSha256Oid);
-                    break;
-        #endif
-        #ifdef WOLFSSL_SHA384
-                case HMAC_SHA384_OID:
-                    oid = hmacSha384Oid;
-                    *oidSz = sizeof(hmacSha384Oid);
-                    break;
-        #endif
-        #ifdef WOLFSSL_SHA512
-                case HMAC_SHA512_OID:
-                    oid = hmacSha512Oid;
-                    *oidSz = sizeof(hmacSha512Oid);
-                    break;
-        #endif
-            }
-            break;
-#endif /* !NO_HMAC */
-
-        case oidIgnoreType:
-        default:
-            break;
-    }
-
-    return oid;
-}
-
-#ifdef HAVE_OID_ENCODING
-int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz)
-{
-    int i, x, len;
-    word32 d, t;
-
-    /* check args */
-    if (in == NULL || outSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* compute length of encoded OID */
-    d = (in[0] * 40) + in[1];
-    len = 0;
-    for (i = 1; i < (int)inSz; i++) {
-        x = 0;
-        t = d;
-        while (t) {
-            x++;
-            t >>= 1;
-        }
-        len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0);
-
-        if (i < (int)inSz - 1) {
-            d = in[i + 1];
-        }
-    }
-
-    if (out) {
-        /* verify length */
-        if ((int)*outSz < len) {
-            return BUFFER_E; /* buffer provided is not large enough */
-        }
-
-        /* calc first byte */
-        d = (in[0] * 40) + in[1];
-
-        /* encode bytes */
-        x = 0;
-        for (i = 1; i < (int)inSz; i++) {
-            if (d) {
-                int y = x, z;
-                byte mask = 0;
-                while (d) {
-                    out[x++] = (byte)((d & 0x7F) | mask);
-                    d     >>= 7;
-                    mask  |= 0x80;  /* upper bit is set on all but the last byte */
-                }
-                /* now swap bytes y...x-1 */
-                z = x - 1;
-                while (y < z) {
-                    mask = out[y];
-                    out[y] = out[z];
-                    out[z] = mask;
-                    ++y;
-                    --z;
-                }
-            }
-            else {
-              out[x++] = 0x00; /* zero value */
-            }
-
-            /* next word */
-            if (i < (int)inSz - 1) {
-                d = in[i + 1];
-            }
-        }
-    }
-
-    /* return length */
-    *outSz = len;
-
-    return 0;
-}
-#endif /* HAVE_OID_ENCODING */
-
-#ifdef HAVE_OID_DECODING
-int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz)
-{
-    int x = 0, y = 0;
-    word32 t = 0;
-
-    /* check args */
-    if (in == NULL || outSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* decode bytes */
-    while (inSz--) {
-        t = (t << 7) | (in[x] & 0x7F);
-        if (!(in[x] & 0x80)) {
-            if (y >= (int)*outSz) {
-                return BUFFER_E;
-            }
-            if (y == 0) {
-                out[0] = (t / 40);
-                out[1] = (t % 40);
-                y = 2;
-            }
-            else {
-                out[y++] = t;
-            }
-            t = 0; /* reset tmp */
-        }
-        x++;
-    }
-
-    /* return length */
-    *outSz = y;
-
-    return 0;
-}
-#endif /* HAVE_OID_DECODING */
-
-/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header.
- *
- * input     Buffer holding DER/BER encoded data.
- * inOutIdx  Current index into buffer to parse.
- * len       The number of bytes in the ASN.1 data.
- * maxIdx    Length of data in buffer.
- * returns BUFFER_E when there is not enough data to parse.
- *         ASN_OBJECt_ID_E when the OBJECT_ID tag is not found.
- *         ASN_PARSE_E when length is invalid.
- *         Otherwise, 0 to indicate success.
- */
-static int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,
-                          word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    byte   b;
-    int    length;
-
-    if ((idx + 1) > maxIdx)
-        return BUFFER_E;
-
-    b = input[idx++];
-    if (b != ASN_OBJECT_ID)
-        return ASN_OBJECT_ID_E;
-
-    if (GetLength(input, &idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    *len = length;
-    *inOutIdx = idx;
-    return 0;
-}
-
-/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header.
- *
- * len         Length of the OBJECT_ID data.
- * output      Buffer to write into.
- * returns the number of bytes added to the buffer.
- */
-static int SetObjectId(int len, byte* output)
-{
-    int idx = 0;
-
-    output[idx++] = ASN_OBJECT_ID;
-    idx += SetLength(len, output + idx);
-
-    return idx;
-}
-
-int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
-                                  word32 oidType, word32 maxIdx)
-{
-    int    ret = 0, length;
-    word32 idx = *inOutIdx;
-#ifndef NO_VERIFY_OID
-    word32 actualOidSz = 0;
-    const byte* actualOid;
-#endif /* NO_VERIFY_OID */
-
-    (void)oidType;
-    WOLFSSL_ENTER("GetObjectId()");
-    *oid = 0;
-
-    ret = GetASNObjectId(input, &idx, &length, maxIdx);
-    if (ret != 0)
-        return ret;
-
-#ifndef NO_VERIFY_OID
-    actualOid = &input[idx];
-    if (length > 0)
-        actualOidSz = (word32)length;
-#endif /* NO_VERIFY_OID */
-
-    while (length--) {
-        /* odd HC08 compiler behavior here when input[idx++] */
-        *oid += (word32)input[idx];
-        idx++;
-    }
-    /* just sum it up for now */
-
-    *inOutIdx = idx;
-
-#ifndef NO_VERIFY_OID
-    {
-        const byte* checkOid = NULL;
-        word32 checkOidSz;
-    #ifdef ASN_DUMP_OID
-        word32 i;
-    #endif
-
-        if (oidType != oidIgnoreType) {
-            checkOid = OidFromId(*oid, oidType, &checkOidSz);
-
-        #ifdef ASN_DUMP_OID
-            /* support for dumping OID information */
-            printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid);
-            for (i=0; i<actualOidSz; i++) {
-                printf("%d, ", actualOid[i]);
-            }
-            printf("\n");
-            #ifdef HAVE_OID_DECODING
-            {
-                word16 decOid[16];
-                word32 decOidSz = sizeof(decOid);
-                ret = DecodeObjectId(actualOid, actualOidSz, decOid, &decOidSz);
-                if (ret == 0) {
-                    printf("  Decoded (Sz %d): ", decOidSz);
-                    for (i=0; i<decOidSz; i++) {
-                        printf("%d.", decOid[i]);
-                    }
-                    printf("\n");
-                }
-                else {
-                    printf("DecodeObjectId failed: %d\n", ret);
-                }
-            }
-            #endif /* HAVE_OID_DECODING */
-        #endif /* ASN_DUMP_OID */
-
-            if (checkOid != NULL &&
-                (checkOidSz != actualOidSz ||
-                    XMEMCMP(actualOid, checkOid, checkOidSz) != 0)) {
-                WOLFSSL_MSG("OID Check Failed");
-                return ASN_UNKNOWN_OID_E;
-            }
-        }
-    }
-#endif /* NO_VERIFY_OID */
-
-    return ret;
-}
-
-static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx)
-{
-    word32 idx = *inOutIdx;
-    int    length;
-    int ret;
-
-    ret = GetASNObjectId(input, &idx, &length, maxIdx);
-    if (ret != 0)
-        return ret;
-
-    idx += length;
-    *inOutIdx = idx;
-
-    return 0;
-}
-
-WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
-                     word32 oidType, word32 maxIdx)
-{
-    int    length;
-    word32 idx = *inOutIdx;
-    int    ret;
-    *oid = 0;
-
-    WOLFSSL_ENTER("GetAlgoId");
-
-    if (GetSequence(input, &idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    if (GetObjectId(input, &idx, oid, oidType, maxIdx) < 0)
-        return ASN_OBJECT_ID_E;
-
-    /* could have NULL tag and 0 terminator, but may not */
-    if (idx < maxIdx && input[idx] == ASN_TAG_NULL) {
-        ret = GetASNNull(input, &idx, maxIdx);
-        if (ret != 0)
-            return ret;
-    }
-
-    *inOutIdx = idx;
-
-    return 0;
-}
-
-#ifndef NO_RSA
-
-#ifndef HAVE_USER_RSA
-int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
-                        word32 inSz)
-{
-    int version, length;
-
-    if (inOutIdx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
-        return ASN_PARSE_E;
-
-    key->type = RSA_PRIVATE;
-
-    if (GetInt(&key->n,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->e,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->d,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->q,  input, inOutIdx, inSz) < 0)   return ASN_RSA_KEY_E;
-#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
-    if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->u,  input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
-#else
-    if (SkipInt(input, inOutIdx, inSz) < 0 ||
-        SkipInt(input, inOutIdx, inSz) < 0 ||
-        SkipInt(input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
-#endif
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    if (wc_InitRsaHw(key) != 0) {
-        return BAD_STATE_E;
-    }
-#endif
-
-    return 0;
-}
-#endif /* HAVE_USER_RSA */
-#endif /* NO_RSA */
-
-/* Remove PKCS8 header, place inOutIdx at beginning of traditional,
- * return traditional length on success, negative on error */
-int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz)
-{
-    word32 idx, oid;
-    int    version, length;
-    int    ret;
-
-    if (input == NULL || inOutIdx == NULL)
-        return BAD_FUNC_ARG;
-
-    idx = *inOutIdx;
-
-    if (GetSequence(input, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetMyVersion(input, &idx, &version, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetAlgoId(input, &idx, &oid, oidKeyType, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (input[idx] == ASN_OBJECT_ID) {
-        if (SkipObjectId(input, &idx, sz) < 0)
-            return ASN_PARSE_E;
-    }
-
-    ret = GetOctetString(input, &idx, &length, sz);
-    if (ret < 0)
-        return ret;
-
-    *inOutIdx = idx;
-
-    return length;
-}
-
-/* Remove PKCS8 header, move beginning of traditional to beginning of input */
-int ToTraditional(byte* input, word32 sz)
-{
-    word32 inOutIdx = 0;
-    int    length;
-
-    if (input == NULL)
-        return BAD_FUNC_ARG;
-
-    length = ToTraditionalInline(input, &inOutIdx, sz);
-    if (length < 0)
-        return length;
-
-    XMEMMOVE(input, input + inOutIdx, length);
-
-    return length;
-}
-
-
-/* find beginning of traditional key inside PKCS#8 unencrypted buffer
- * return traditional length on success, with inOutIdx at beginning of
- * traditional
- * return negative on failure/error */
-int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz)
-{
-    int length;
-
-    if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz))
-        return BAD_FUNC_ARG;
-
-    length = ToTraditionalInline(input, inOutIdx, sz);
-
-    return length;
-}
-
-
-/* PKCS#8 from RFC 5208
- * This function takes in a DER key and converts it to PKCS#8 format. Used
- * in creating PKCS#12 shrouded key bags.
- * Reverse of ToTraditional
- *
- * PrivateKeyInfo ::= SEQUENCE {
- *  version Version,
- *  privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
- *  privateKey          PrivateKey,
- *  attributes          optional
- *  }
- *  Version ::= INTEGER
- *  PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
- *  PrivateKey ::= OCTET STRING
- *
- * out      buffer to place result in
- * outSz    size of out buffer
- * key      buffer with DER key
- * keySz    size of key buffer
- * algoID   algorithm ID i.e. RSAk
- * curveOID ECC curve oid if used. Should be NULL for RSA keys.
- * oidSz    size of curve oid. Is set to 0 if curveOID is NULL.
- *
- * Returns the size of PKCS#8 placed into out. In error cases returns negative
- * values.
- */
-int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz,
-        int algoID, const byte* curveOID, word32 oidSz)
-{
-        word32 keyIdx = 0;
-        word32 tmpSz  = 0;
-        word32 sz;
-
-
-        /* If out is NULL then return the max size needed
-         * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */
-        if (out == NULL && outSz != NULL) {
-            *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
-                     + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2;
-
-            if (curveOID != NULL)
-                *outSz += oidSz + MAX_LENGTH_SZ + 1;
-
-            WOLFSSL_MSG("Checking size of PKCS8");
-
-            return LENGTH_ONLY_E;
-        }
-
-        WOLFSSL_ENTER("wc_CreatePKCS8Key()");
-
-        if (key == NULL || out == NULL || outSz == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        /* check the buffer has enough room for largest possible size */
-        if (curveOID != NULL) {
-            if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
-                   + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ))
-                return BUFFER_E;
-        }
-        else {
-            oidSz = 0; /* with no curveOID oid size must be 0 */
-            if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
-                      + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2))
-                return BUFFER_E;
-        }
-
-        /* PrivateKeyInfo ::= SEQUENCE */
-        keyIdx += MAX_SEQ_SZ; /* save room for sequence */
-
-        /*  version Version
-         *  no header information just INTEGER */
-        sz = SetMyVersion(PKCS8v0, out + keyIdx, 0);
-        tmpSz += sz; keyIdx += sz;
-
-        /*  privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */
-        sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */
-        if (curveOID != NULL && oidSz > 0) {
-            byte buf[MAX_LENGTH_SZ];
-            sz = SetLength(oidSz, buf);
-            sz += 1; /* plus one for ASN object id */
-        }
-        sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz);
-        tmpSz += sz; keyIdx += sz;
-
-        /*  privateKey          PrivateKey *
-         * pkcs8 ecc uses slightly different format. Places curve oid in
-         * buffer */
-        if (curveOID != NULL && oidSz > 0) {
-            sz = SetObjectId(oidSz, out + keyIdx);
-            keyIdx += sz; tmpSz += sz;
-            XMEMCPY(out + keyIdx, curveOID, oidSz);
-            keyIdx += oidSz; tmpSz += oidSz;
-        }
-
-        sz = SetOctetString(keySz, out + keyIdx);
-        keyIdx += sz; tmpSz += sz;
-        XMEMCPY(out + keyIdx, key, keySz);
-        tmpSz += keySz;
-
-        /*  attributes          optional
-         * No attributes currently added */
-
-        /* rewind and add sequence */
-        sz = SetSequence(tmpSz, out);
-        XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz);
-
-        return tmpSz + sz;
-}
-
-
-/* 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 fromat key
- * keySz : size of key buffer
- * der   : a initialized and parsed DecodedCert holding a certificate */
-int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
-{
-    int ret;
-    (void)keySz;
-
-    if (key == NULL || der == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    #if !defined(NO_RSA)
-    /* test if RSA key */
-    if (der->keyOID == RSAk) {
-    #ifdef WOLFSSL_SMALL_STACK
-        RsaKey* a = NULL;
-        RsaKey* b = NULL;
-    #else
-        RsaKey a[1], b[1];
-    #endif
-        word32 keyIdx = 0;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
-        if (a == NULL)
-            return MEMORY_E;
-        b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
-        if (b == NULL) {
-            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
-            return MEMORY_E;
-        }
-    #endif
-
-        if ((ret = wc_InitRsaKey(a, NULL)) < 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-            XFREE(b, NULL, DYNAMIC_TYPE_RSA);
-            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
-    #endif
-            return ret;
-        }
-        if ((ret = wc_InitRsaKey(b, NULL)) < 0) {
-            wc_FreeRsaKey(a);
-    #ifdef WOLFSSL_SMALL_STACK
-            XFREE(b, NULL, DYNAMIC_TYPE_RSA);
-            XFREE(a, NULL, DYNAMIC_TYPE_RSA);
-    #endif
-            return ret;
-        }
-        if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 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) {
-                /* limit for user RSA crypto because of RsaKey
-                 * dereference. */
-            #if defined(HAVE_USER_RSA)
-                WOLFSSL_MSG("Cannot verify RSA pair with user RSA");
-                ret = 1; /* return first RSA cert as match */
-            #else
-                /* both keys extracted successfully now check n and e
-                 * values are the same. This is dereferencing RsaKey */
-                if (mp_cmp(&(a->n), &(b->n)) != MP_EQ ||
-                    mp_cmp(&(a->e), &(b->e)) != MP_EQ) {
-                    ret = MP_CMP_E;
-                }
-                else
-                    ret = 1;
-            #endif
-            }
-        }
-        wc_FreeRsaKey(b);
-        wc_FreeRsaKey(a);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(b, NULL, DYNAMIC_TYPE_RSA);
-        XFREE(a, NULL, DYNAMIC_TYPE_RSA);
-    #endif
-    }
-    else
-    #endif /* NO_RSA */
-
-    #ifdef HAVE_ECC
-    if (der->keyOID == ECDSAk) {
-    #ifdef WOLFSSL_SMALL_STACK
-        ecc_key* key_pair = NULL;
-        byte*    privDer;
-    #else
-        ecc_key  key_pair[1];
-        byte     privDer[MAX_ECC_BYTES];
-    #endif
-        word32   privSz = MAX_ECC_BYTES;
-        word32   keyIdx = 0;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
-        if (key_pair == NULL)
-            return MEMORY_E;
-        privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (privDer == NULL) {
-            XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
-            return MEMORY_E;
-        }
-    #endif
-
-        if ((ret = wc_ecc_init(key_pair)) < 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-            XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-            return ret;
-        }
-
-        if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair,
-                                                                 keySz)) == 0) {
-            WOLFSSL_MSG("Checking ECC key pair");
-
-            if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz))
-                                                                         == 0) {
-                wc_ecc_free(key_pair);
-                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);
-                }
-
-                /* public and private extracted successfuly now check if is
-                 * a pair and also do sanity checks on key. wc_ecc_check_key
-                 * checks that private * base generator equals pubkey */
-                if (ret == 0) {
-                    if ((ret = wc_ecc_check_key(key_pair)) == 0) {
-                        ret = 1;
-                    }
-                }
-                ForceZero(privDer, privSz);
-            }
-        }
-        wc_ecc_free(key_pair);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-    }
-    else
-    #endif /* HAVE_ECC */
-
-    #ifdef HAVE_ED25519
-    if (der->keyOID == ED25519k) {
-    #ifdef WOLFSSL_SMALL_STACK
-        ed25519_key* key_pair = NULL;
-    #else
-        ed25519_key  key_pair[1];
-    #endif
-        word32       keyIdx = 0;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL,
-                                                          DYNAMIC_TYPE_ED25519);
-        if (key_pair == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_ed25519_init(key_pair)) < 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-            XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
-    #endif
-            return ret;
-        }
-        if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair,
-                                                                 keySz)) == 0) {
-            WOLFSSL_MSG("Checking ED25519 key pair");
-            keyIdx = 0;
-            if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize,
-                                                              key_pair)) == 0) {
-                /* public and private extracted successfuly no check if is
-                 * a pair and also do sanity checks on key. wc_ecc_check_key
-                 * checks that private * base generator equals pubkey */
-                if ((ret = wc_ed25519_check_key(key_pair)) == 0)
-                    ret = 1;
-            }
-        }
-        wc_ed25519_free(key_pair);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
-    #endif
-    }
-    else
-    #endif
-    {
-        ret = 0;
-    }
-
-    (void)keySz;
-
-    return ret;
-}
-
-#ifndef NO_PWDBASED
-
-/* Check To see if PKCS version algo is supported, set id if it is return 0
-   < 0 on error */
-static int CheckAlgo(int first, int second, int* id, int* version)
-{
-    *id      = ALGO_ID_E;
-    *version = PKCS5;   /* default */
-
-    if (first == 1) {
-        switch (second) {
-#if !defined(NO_SHA)
-    #ifndef NO_RC4
-        case PBE_SHA1_RC4_128:
-            *id = PBE_SHA1_RC4_128;
-            *version = PKCS12v1;
-            return 0;
-    #endif
-    #ifndef NO_DES3
-        case PBE_SHA1_DES3:
-            *id = PBE_SHA1_DES3;
-            *version = PKCS12v1;
-            return 0;
-    #endif
-#endif /* !NO_SHA */
-        default:
-            return ALGO_ID_E;
-        }
-    }
-
-    if (first != PKCS5)
-        return ASN_INPUT_E;  /* VERSION ERROR */
-
-    if (second == PBES2) {
-        *version = PKCS5v2;
-        return 0;
-    }
-
-    switch (second) {
-#ifndef NO_DES3
-    #ifndef NO_MD5
-    case 3:                   /* see RFC 2898 for ids */
-        *id = PBE_MD5_DES;
-        return 0;
-    #endif
-    #ifndef NO_SHA
-    case 10:
-        *id = PBE_SHA1_DES;
-        return 0;
-    #endif
-#endif /* !NO_DES3 */
-    default:
-        return ALGO_ID_E;
-
-    }
-}
-
-
-/* Check To see if PKCS v2 algo is supported, set id if it is return 0
-   < 0 on error */
-static int CheckAlgoV2(int oid, int* id)
-{
-    (void)id; /* not used if AES and DES3 disabled */
-    switch (oid) {
-#if !defined(NO_DES3) && !defined(NO_SHA)
-    case DESb:
-        *id = PBE_SHA1_DES;
-        return 0;
-    case DES3b:
-        *id = PBE_SHA1_DES3;
-        return 0;
-#endif
-#ifdef WOLFSSL_AES_256
-    case AES256CBCb:
-        *id = PBE_AES256_CBC;
-        return 0;
-#endif
-    default:
-        return ALGO_ID_E;
-
-    }
-}
-
-
-int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
-        int* algoID, void* heap)
-{
-    word32 tmpIdx = 0;
-
-    if (key == NULL || algoID == NULL)
-        return BAD_FUNC_ARG;
-
-    *algoID = 0;
-
-    #ifndef NO_RSA
-    {
-        RsaKey rsa;
-
-        wc_InitRsaKey(&rsa, heap);
-        if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) {
-            *algoID = RSAk;
-        }
-        else {
-            WOLFSSL_MSG("Not RSA DER key");
-        }
-        wc_FreeRsaKey(&rsa);
-    }
-    #endif /* NO_RSA */
-    #ifdef HAVE_ECC
-    if (*algoID == 0) {
-        ecc_key ecc;
-
-        tmpIdx = 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) {
-                WOLFSSL_MSG("Error getting ECC curve OID");
-                wc_ecc_free(&ecc);
-                return BAD_FUNC_ARG;
-            }
-        }
-        else {
-            WOLFSSL_MSG("Not ECC DER key either");
-        }
-        wc_ecc_free(&ecc);
-    }
-#endif /* HAVE_ECC */
-#ifdef HAVE_ED25519
-    if (*algoID != RSAk && *algoID != ECDSAk) {
-        ed25519_key ed25519;
-
-        tmpIdx = 0;
-        if (wc_ed25519_init(&ed25519) == 0) {
-            if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz)
-                                                                         == 0) {
-                *algoID = ED25519k;
-            }
-            else {
-                WOLFSSL_MSG("Not ED25519 DER key");
-            }
-            wc_ed25519_free(&ed25519);
-        }
-        else {
-            WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed");
-        }
-    }
-#endif
-
-    /* if flag is not set then is neither RSA or ECC key that could be
-     * found */
-    if (*algoID == 0) {
-        WOLFSSL_MSG("Bad key DER or compile options");
-        return BAD_FUNC_ARG;
-    }
-
-    (void)curveOID;
-    (void)oidSz;
-
-    return 1;
-}
-
-
-/*
- * Used when creating PKCS12 shrouded key bags
- * vPKCS is the version of PKCS to use
- * vAlgo is the algorithm version to use
- *
- * if salt is NULL a random number is generated
- *
- * returns the size of encrypted data on success
- */
-int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
-        const char* password,int passwordSz, int vPKCS, int vAlgo,
-        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
-{
-    int algoID = 0;
-    byte*  tmp;
-    word32 tmpSz = 0;
-    word32 sz;
-    word32 seqSz;
-    word32 inOutIdx = 0;
-    word32 totalSz = 0;
-    int    version, id;
-    int    ret;
-
-    const byte* curveOID = NULL;
-    word32 oidSz   = 0;
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  saltTmp = NULL;
-    byte*  cbcIv   = NULL;
-#else
-    byte   saltTmp[MAX_IV_SIZE];
-    byte   cbcIv[MAX_IV_SIZE];
-#endif
-
-    WOLFSSL_ENTER("UnTraditionalEnc()");
-
-    if (saltSz > MAX_SALT_SIZE)
-        return ASN_PARSE_E;
-
-
-    inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */
-    if (CheckAlgo(vPKCS, vAlgo, &id, &version) < 0) {
-        WOLFSSL_MSG("Bad/Unsupported algorithm ID");
-        return ASN_INPUT_E;  /* Algo ID error */
-    }
-
-    if (out != NULL) {
-        if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 +
-                MAX_LENGTH_SZ + MAX_SHORT_SZ + 1)
-                return BUFFER_E;
-
-        if (version == PKCS5v2) {
-            WOLFSSL_MSG("PKCS5v2 Not supported yet\n");
-            return ASN_VERSION_E;
-        }
-
-        if (salt == NULL || saltSz <= 0) {
-            saltSz = 8;
-        #ifdef WOLFSSL_SMALL_STACK
-            saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            if (saltTmp == NULL)
-                return MEMORY_E;
-        #endif
-            salt = saltTmp;
-
-            if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
-                WOLFSSL_MSG("Error generating random salt");
-            #ifdef WOLFSSL_SMALL_STACK
-                if (saltTmp != NULL)
-                    XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            #endif
-                return ret;
-            }
-        }
-
-
-        /* leave room for a sequence (contains salt and iterations int) */
-        inOutIdx += MAX_SEQ_SZ; sz = 0;
-        inOutIdx += MAX_ALGO_SZ;
-
-        /* place salt in buffer */
-        out[inOutIdx++] = ASN_OCTET_STRING; sz++;
-        tmpSz = SetLength(saltSz, out + inOutIdx);
-        inOutIdx += tmpSz; sz += tmpSz;
-        XMEMCPY(out + inOutIdx, salt, saltSz);
-        inOutIdx += saltSz; sz += saltSz;
-
-        /* place iteration count in buffer */
-        ret = SetShortInt(out, &inOutIdx, itt, *outSz);
-        if (ret < 0) {
-            return ret;
-        }
-        sz += (word32)ret;
-
-        /* wind back index and set sequence then clean up buffer */
-        inOutIdx -= (sz + MAX_SEQ_SZ);
-        tmpSz = SetSequence(sz, out + inOutIdx);
-        XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz);
-        totalSz += tmpSz + sz; sz += tmpSz;
-
-        /* add in algo ID */
-        inOutIdx -= MAX_ALGO_SZ;
-        tmpSz =  SetAlgoID(id, out + inOutIdx, oidPBEType, sz);
-        XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz);
-        totalSz += tmpSz; inOutIdx += tmpSz + sz;
-
-        /* octet string containing encrypted key */
-        out[inOutIdx++] = ASN_OCTET_STRING; totalSz++;
-    }
-
-    /* check key type and get OID if ECC */
-    if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) {
-            return ret;
-    }
-
-    /* PKCS#8 wrapping around key */
-    if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz)
-            != LENGTH_ONLY_E) {
-    #ifdef WOLFSSL_SMALL_STACK
-        if (saltTmp != NULL)
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return MEMORY_E;
-    }
-
-    /* check if should return max size */
-    if (out == NULL) {
-        /* account for salt size */
-        if (salt == NULL || saltSz <= 0) {
-            tmpSz += MAX_SALT_SIZE;
-        }
-        else {
-            tmpSz += saltSz;
-        }
-
-        /* plus 3 for tags */
-        *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ
-            + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3;
-        return LENGTH_ONLY_E;
-    }
-
-    tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (tmp == NULL) {
-    #ifdef WOLFSSL_SMALL_STACK
-        if (saltTmp != NULL)
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return MEMORY_E;
-    }
-
-    if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID,
-                    oidSz)) < 0) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_MSG("Error wrapping key with PKCS#8");
-    #ifdef WOLFSSL_SMALL_STACK
-        if (saltTmp != NULL)
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return ret;
-    }
-    tmpSz = ret;
-
-#ifdef WOLFSSL_SMALL_STACK
-    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cbcIv == NULL) {
-        if (saltTmp != NULL)
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    /* encrypt PKCS#8 wrapped key */
-    if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
-               tmp, tmpSz, version, cbcIv, 1)) < 0) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_MSG("Error encrypting key");
-    #ifdef WOLFSSL_SMALL_STACK
-        if (saltTmp != NULL)
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (cbcIv != NULL)
-            XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return ret;  /* encryption failure */
-    }
-    totalSz += tmpSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (saltTmp != NULL)
-        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cbcIv != NULL)
-        XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return BUFFER_E;
-    }
-
-    /* set length of key and copy over encrypted key */
-    seqSz = SetLength(tmpSz, out + inOutIdx);
-    inOutIdx += seqSz; totalSz += seqSz;
-    XMEMCPY(out + inOutIdx, tmp, tmpSz);
-    XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    /* set total size at begining */
-    sz = SetSequence(totalSz, out);
-    XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz);
-
-    return totalSz + sz;
-}
-
-
-/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
-   of input */
-int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
-{
-    word32 inOutIdx = 0, seqEnd, oid;
-    int    ret = 0, first, second, length = 0, version, saltSz, id;
-    int    iterations = 0, keySz = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  salt = NULL;
-    byte*  cbcIv = NULL;
-#else
-    byte   salt[MAX_SALT_SIZE];
-    byte   cbcIv[MAX_IV_SIZE];
-#endif
-
-    if (passwordSz < 0) {
-        WOLFSSL_MSG("Bad password size");
-        return BAD_FUNC_ARG;
-    }
-
-    if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_tte);
-    }
-
-    if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_tte);
-    }
-
-    first  = input[inOutIdx - 2];   /* PKCS version always 2nd to last byte */
-    second = input[inOutIdx - 1];   /* version.algo, algo id last byte */
-
-    if (CheckAlgo(first, second, &id, &version) < 0) {
-        ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */
-    }
-
-    if (version == PKCS5v2) {
-        if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-
-        if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-
-        if (oid != PBKDF2_OID) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-    }
-
-    if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_tte);
-    }
-    /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
-     * DEFAULT items. */
-    seqEnd = inOutIdx + length;
-
-    ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
-    if (ret < 0)
-        goto exit_tte;
-
-    if (saltSz > MAX_SALT_SIZE) {
-        ERROR_OUT(ASN_PARSE_E, exit_tte);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (salt == NULL) {
-        ERROR_OUT(MEMORY_E, exit_tte);
-    }
-#endif
-
-    XMEMCPY(salt, &input[inOutIdx], saltSz);
-    inOutIdx += saltSz;
-
-    if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_tte);
-    }
-
-    /* OPTIONAL key length */
-    if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) {
-        if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-    }
-
-    /* DEFAULT HMAC is SHA-1 */
-    if (seqEnd > inOutIdx) {
-        if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cbcIv == NULL) {
-        ERROR_OUT(MEMORY_E, exit_tte);
-    }
-#endif
-
-    if (version == PKCS5v2) {
-        /* get encryption algo */
-        if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-
-        if (CheckAlgoV2(oid, &id) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */
-        }
-
-        ret = GetOctetString(input, &inOutIdx, &length, sz);
-        if (ret < 0)
-            goto exit_tte;
-
-        if (length > MAX_IV_SIZE) {
-            ERROR_OUT(ASN_PARSE_E, exit_tte);
-        }
-
-        XMEMCPY(cbcIv, &input[inOutIdx], length);
-        inOutIdx += length;
-    }
-
-    ret = GetOctetString(input, &inOutIdx, &length, sz);
-    if (ret < 0)
-        goto exit_tte;
-
-    ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
-                   input + inOutIdx, length, version, cbcIv, 0);
-
-exit_tte:
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (ret == 0) {
-        XMEMMOVE(input, input + inOutIdx, length);
-        ret = ToTraditional(input, length);
-    }
-
-    return ret;
-}
-
-
-/* encrypt PKCS 12 content
- *
- * NOTE: if out is NULL then outSz is set with the total buffer size needed and
- *       the error value LENGTH_ONLY_E is returned.
- *
- * input      data to encrypt
- * inputSz    size of input buffer
- * out        buffer to hold the result
- * outSz      size of out buffer
- * password   password if used. Can be NULL for no password
- * passwordSz size of password buffer
- * vPKCS      version of PKCS i.e. PKCS5v2
- * vAlgo      algorithm version
- * salt       buffer holding salt if used. If NULL then a random salt is created
- * saltSz     size of salt buffer if it is not NULL
- * itt        number of iterations used
- * rng        random number generator to use
- * heap       possible heap hint for mallocs/frees
- *
- * returns the total size of encrypted content on success.
- */
-int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
-        const char* password, int passwordSz, int vPKCS, int vAlgo,
-        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
-{
-    word32 sz;
-    word32 inOutIdx = 0;
-    word32 tmpIdx   = 0;
-    word32 totalSz  = 0;
-    word32 seqSz;
-    int    ret;
-    int    version, id;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  saltTmp = NULL;
-    byte*  cbcIv   = NULL;
-#else
-    byte   saltTmp[MAX_SALT_SIZE];
-    byte   cbcIv[MAX_IV_SIZE];
-#endif
-
-    (void)heap;
-
-    WOLFSSL_ENTER("EncryptContent()");
-
-    if (CheckAlgo(vPKCS, vAlgo, &id, &version) < 0)
-        return ASN_INPUT_E;  /* Algo ID error */
-
-    if (version == PKCS5v2) {
-        WOLFSSL_MSG("PKCS#5 version 2 not supported yet");
-        return BAD_FUNC_ARG;
-    }
-
-    if (saltSz > MAX_SALT_SIZE)
-        return ASN_PARSE_E;
-
-    if (outSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (out == NULL) {
-        sz = inputSz;
-        switch (id) {
-        #if !defined(NO_DES3) && (!defined(NO_MD5) || !defined(NO_SHA))
-            case PBE_MD5_DES:
-            case PBE_SHA1_DES:
-            case PBE_SHA1_DES3:
-                /* set to block size of 8 for DES operations. This rounds up
-                 * to the nearset multiple of 8 */
-                sz &= 0xfffffff8;
-                sz += 8;
-                break;
-        #endif /* !NO_DES3 && (!NO_MD5 || !NO_SHA) */
-        #if !defined(NO_RC4) && !defined(NO_SHA)
-            case PBE_SHA1_RC4_128:
-                break;
-        #endif
-            case -1:
-                break;
-
-            default:
-                return ALGO_ID_E;
-        }
-
-        if (saltSz <= 0) {
-            sz += MAX_SALT_SIZE;
-        }
-        else {
-            sz += saltSz;
-        }
-
-        /* add 2 for tags */
-        *outSz = sz + MAX_ALGO_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ +
-            MAX_LENGTH_SZ + MAX_LENGTH_SZ + MAX_SHORT_SZ + 2;
-
-        return LENGTH_ONLY_E;
-    }
-
-    if (inOutIdx + MAX_ALGO_SZ + MAX_SEQ_SZ + 1 > *outSz)
-        return BUFFER_E;
-
-    sz = SetAlgoID(id, out + inOutIdx, oidPBEType, 0);
-    inOutIdx += sz; totalSz += sz;
-    tmpIdx = inOutIdx;
-    tmpIdx += MAX_SEQ_SZ; /* save room for salt and itter sequence */
-    out[tmpIdx++] = ASN_OCTET_STRING;
-
-    /* create random salt if one not provided */
-    if (salt == NULL || saltSz <= 0) {
-        saltSz = 8;
-    #ifdef WOLFSSL_SMALL_STACK
-        saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (saltTmp == NULL)
-            return MEMORY_E;
-    #endif
-        salt = saltTmp;
-
-        if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
-            WOLFSSL_MSG("Error generating random salt");
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-            return ret;
-        }
-    }
-
-    if (tmpIdx + MAX_LENGTH_SZ + saltSz + MAX_SHORT_SZ > *outSz) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return BUFFER_E;
-    }
-
-    sz = SetLength(saltSz, out + tmpIdx);
-    tmpIdx += sz;
-
-    XMEMCPY(out + tmpIdx, salt, saltSz);
-    tmpIdx += saltSz;
-
-    /* place itteration setting in buffer */
-    ret = SetShortInt(out, &tmpIdx, itt, *outSz);
-    if (ret < 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return ret;
-    }
-
-    /* rewind and place sequence */
-    sz = tmpIdx - inOutIdx - MAX_SEQ_SZ;
-    seqSz = SetSequence(sz, out + inOutIdx);
-    XMEMMOVE(out + inOutIdx + seqSz, out + inOutIdx + MAX_SEQ_SZ, sz);
-    inOutIdx += seqSz; totalSz += seqSz;
-    inOutIdx += sz; totalSz += sz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cbcIv == NULL) {
-        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
-                   input, inputSz, version, cbcIv, 1)) < 0) {
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return ret;  /* encrypt failure */
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (inOutIdx + 1 + MAX_LENGTH_SZ + inputSz > *outSz)
-        return BUFFER_E;
-
-    out[inOutIdx++] = ASN_LONG_LENGTH; totalSz++;
-    sz = SetLength(inputSz, out + inOutIdx);
-    inOutIdx += sz; totalSz += sz;
-    XMEMCPY(out + inOutIdx, input, inputSz);
-    totalSz += inputSz;
-
-    return totalSz;
-}
-
-
-/* decrypt PKCS
- *
- * NOTE: input buffer is overwritten with decrypted data!
- *
- * input[in/out] data to decrypt and results are written to
- * sz            size of input buffer
- * password      password if used. Can be NULL for no password
- * passwordSz    size of password buffer
- *
- * returns the total size of decrypted content on success.
- */
-int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz)
-{
-    word32 inOutIdx = 0, seqEnd, oid;
-    int    ret = 0;
-    int    first, second, length = 0, version, saltSz, id;
-    int    iterations = 0, keySz = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  salt = NULL;
-    byte*  cbcIv = NULL;
-#else
-    byte   salt[MAX_SALT_SIZE];
-    byte   cbcIv[MAX_IV_SIZE];
-#endif
-
-    if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-
-    first  = input[inOutIdx - 2];   /* PKCS version always 2nd to last byte */
-    second = input[inOutIdx - 1];   /* version.algo, algo id last byte */
-
-    if (CheckAlgo(first, second, &id, &version) < 0) {
-        ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
-    }
-
-    if (version == PKCS5v2) {
-        if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-
-        if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-
-        if (oid != PBKDF2_OID) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-    }
-
-    if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-    /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
-     * DEFAULT items. */
-    seqEnd = inOutIdx + length;
-
-    ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
-    if (ret < 0)
-        goto exit_dc;
-
-    if (saltSz > MAX_SALT_SIZE) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (salt == NULL) {
-        ERROR_OUT(MEMORY_E, exit_dc);
-    }
-#endif
-
-    XMEMCPY(salt, &input[inOutIdx], saltSz);
-    inOutIdx += saltSz;
-
-    if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-
-    /* OPTIONAL key length */
-    if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) {
-        if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-    }
-
-    /* DEFAULT HMAC is SHA-1 */
-    if (seqEnd > inOutIdx) {
-        if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cbcIv == NULL) {
-        ERROR_OUT(MEMORY_E, exit_dc);
-    }
-#endif
-
-    if (version == PKCS5v2) {
-        /* get encryption algo */
-        if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-
-        if (CheckAlgoV2(oid, &id) < 0) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
-        }
-
-        ret = GetOctetString(input, &inOutIdx, &length, sz);
-        if (ret < 0)
-            goto exit_dc;
-
-        if (length > MAX_IV_SIZE) {
-            ERROR_OUT(ASN_PARSE_E, exit_dc);
-        }
-
-        XMEMCPY(cbcIv, &input[inOutIdx], length);
-        inOutIdx += length;
-    }
-
-    if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-
-    if (GetLength(input, &inOutIdx, &length, sz) < 0) {
-        ERROR_OUT(ASN_PARSE_E, exit_dc);
-    }
-
-    ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
-                   input + inOutIdx, length, version, cbcIv, 0);
-
-exit_dc:
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (ret == 0) {
-        XMEMMOVE(input, input + inOutIdx, length);
-        ret = length;
-    }
-
-    return ret;
-}
-#endif /* NO_PWDBASED */
-
-#ifndef NO_RSA
-
-#ifndef HAVE_USER_RSA
-int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
-                       word32 inSz)
-{
-    int  length;
-#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
-    byte b;
-#endif
-    int ret;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    key->type = RSA_PUBLIC;
-
-#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
-    if ((*inOutIdx + 1) > inSz)
-        return BUFFER_E;
-
-    b = input[*inOutIdx];
-    if (b != ASN_INTEGER) {
-        /* not from decoded cert, will have algo id, skip past */
-        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-            return ASN_PARSE_E;
-
-        if (SkipObjectId(input, inOutIdx, inSz) < 0)
-            return ASN_PARSE_E;
-
-        /* Option NULL ASN.1 tag */
-        if (*inOutIdx  >= inSz) {
-            return BUFFER_E;
-        }
-        if (input[*inOutIdx] == ASN_TAG_NULL) {
-            ret = GetASNNull(input, inOutIdx, inSz);
-            if (ret != 0)
-                return ret;
-        }
-
-        /* should have bit tag length and seq next */
-        ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
-        if (ret != 0)
-            return ret;
-
-        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-            return ASN_PARSE_E;
-    }
-#endif /* OPENSSL_EXTRA */
-
-    if (GetInt(&key->n,  input, inOutIdx, inSz) < 0)
-        return ASN_RSA_KEY_E;
-    if (GetInt(&key->e,  input, inOutIdx, inSz) < 0) {
-        mp_clear(&key->n);
-        return ASN_RSA_KEY_E;
-    }
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    if (wc_InitRsaHw(key) != 0) {
-        return BAD_STATE_E;
-    }
-#endif
-
-    return 0;
-}
-
-/* import RSA public key elements (n, e) into RsaKey structure (key) */
-int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
-                             word32 eSz, RsaKey* key)
-{
-    if (n == NULL || e == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    key->type = RSA_PUBLIC;
-
-    if (mp_init(&key->n) != MP_OKAY)
-        return MP_INIT_E;
-
-    if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) {
-        mp_clear(&key->n);
-        return ASN_GETINT_E;
-    }
-
-    if (mp_init(&key->e) != MP_OKAY) {
-        mp_clear(&key->n);
-        return MP_INIT_E;
-    }
-
-    if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) {
-        mp_clear(&key->n);
-        mp_clear(&key->e);
-        return ASN_GETINT_E;
-    }
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    if (wc_InitRsaHw(key) != 0) {
-        return BAD_STATE_E;
-    }
-#endif
-
-    return 0;
-}
-#endif /* HAVE_USER_RSA */
-#endif
-
-#ifndef NO_DH
-
-int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
-{
-    int    length;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->g,  input, inOutIdx, inSz) < 0) {
-        return ASN_DH_KEY_E;
-    }
-
-    return 0;
-}
-
-
-int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
-                 byte* g, word32* gInOutSz)
-{
-    word32 idx = 0;
-    int    ret;
-    int    length;
-
-    if (GetSequence(input, &idx, &length, inSz) <= 0)
-        return ASN_PARSE_E;
-
-    ret = GetASNInt(input, &idx, &length, inSz);
-    if (ret != 0)
-        return ret;
-
-    if (length <= (int)*pInOutSz) {
-        XMEMCPY(p, &input[idx], length);
-        *pInOutSz = length;
-    }
-    else {
-        return BUFFER_E;
-    }
-    idx += length;
-
-    ret = GetASNInt(input, &idx, &length, inSz);
-    if (ret != 0)
-        return ret;
-
-    if (length <= (int)*gInOutSz) {
-        XMEMCPY(g, &input[idx], length);
-        *gInOutSz = length;
-    }
-    else {
-        return BUFFER_E;
-    }
-
-    return 0;
-}
-
-#endif /* NO_DH */
-
-
-#ifndef NO_DSA
-
-int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
-                        word32 inSz)
-{
-    int    length;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->y,  input, inOutIdx, inSz) < 0 )
-        return ASN_DH_KEY_E;
-
-    key->type = DSA_PUBLIC;
-    return 0;
-}
-
-
-int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
-                        word32 inSz)
-{
-    int    length, version;
-
-    /* Sanity checks on input */
-    if (input == NULL || inOutIdx == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->y,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->x,  input, inOutIdx, inSz) < 0 )
-        return ASN_DH_KEY_E;
-
-    key->type = DSA_PRIVATE;
-    return 0;
-}
-
-static mp_int* GetDsaInt(DsaKey* key, int idx)
-{
-    if (idx == 0)
-        return &key->p;
-    if (idx == 1)
-        return &key->q;
-    if (idx == 2)
-        return &key->g;
-    if (idx == 3)
-        return &key->y;
-    if (idx == 4)
-        return &key->x;
-
-    return NULL;
-}
-
-/* Release Tmp DSA resources */
-static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap)
-{
-    int i;
-
-    for (i = 0; i < DSA_INTS; i++)
-        XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA);
-
-    (void)heap;
-}
-
-/* Convert DsaKey key to DER format, write to output (inLen), return bytes
- written */
-int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen)
-{
-    word32 seqSz, verSz, rawLen, intTotalLen = 0;
-    word32 sizes[DSA_INTS];
-    int    i, j, outLen, ret = 0, mpSz;
-
-    byte  seq[MAX_SEQ_SZ];
-    byte  ver[MAX_VERSION_SZ];
-    byte* tmps[DSA_INTS];
-
-    if (!key || !output)
-        return BAD_FUNC_ARG;
-
-    if (key->type != DSA_PRIVATE)
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < DSA_INTS; i++)
-        tmps[i] = NULL;
-
-    /* write all big ints from key to DER tmps */
-    for (i = 0; i < DSA_INTS; i++) {
-        mp_int* keyInt = GetDsaInt(key, i);
-
-        rawLen = mp_unsigned_bin_size(keyInt) + 1;
-        tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
-                                                              DYNAMIC_TYPE_DSA);
-        if (tmps[i] == NULL) {
-            ret = MEMORY_E;
-            break;
-        }
-
-        mpSz = SetASNIntMP(keyInt, -1, tmps[i]);
-        if (mpSz < 0) {
-            ret = mpSz;
-            break;
-        }
-        intTotalLen += (sizes[i] = mpSz);
-    }
-
-    if (ret != 0) {
-        FreeTmpDsas(tmps, key->heap);
-        return ret;
-    }
-
-    /* make headers */
-    verSz = SetMyVersion(0, ver, FALSE);
-    seqSz = SetSequence(verSz + intTotalLen, seq);
-
-    outLen = seqSz + verSz + intTotalLen;
-    if (outLen > (int)inLen)
-        return BAD_FUNC_ARG;
-
-    /* write to output */
-    XMEMCPY(output, seq, seqSz);
-    j = seqSz;
-    XMEMCPY(output + j, ver, verSz);
-    j += verSz;
-
-    for (i = 0; i < DSA_INTS; i++) {
-        XMEMCPY(output + j, tmps[i], sizes[i]);
-        j += sizes[i];
-    }
-    FreeTmpDsas(tmps, key->heap);
-
-    return outLen;
-}
-
-#endif /* NO_DSA */
-
-
-void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
-{
-    if (cert != NULL) {
-        XMEMSET(cert, 0, sizeof(DecodedCert));
-
-        cert->subjectCNEnc    = CTC_UTF8;
-        cert->issuer[0]       = '\0';
-        cert->subject[0]      = '\0';
-        cert->source          = source;  /* don't own */
-        cert->maxIdx          = inSz;    /* can't go over this index */
-        cert->heap            = heap;
-    #ifdef WOLFSSL_CERT_GEN
-        cert->subjectSNEnc    = CTC_UTF8;
-        cert->subjectCEnc     = CTC_PRINTABLE;
-        cert->subjectLEnc     = CTC_UTF8;
-        cert->subjectSTEnc    = CTC_UTF8;
-        cert->subjectOEnc     = CTC_UTF8;
-        cert->subjectOUEnc    = CTC_UTF8;
-    #endif /* WOLFSSL_CERT_GEN */
-
-        InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID);
-    }
-}
-
-
-void FreeAltNames(DNS_entry* altNames, void* heap)
-{
-    (void)heap;
-
-    while (altNames) {
-        DNS_entry* tmp = altNames->next;
-
-        XFREE(altNames->name, heap, DYNAMIC_TYPE_ALTNAME);
-        XFREE(altNames,       heap, DYNAMIC_TYPE_ALTNAME);
-        altNames = tmp;
-    }
-}
-
-#ifndef IGNORE_NAME_CONSTRAINTS
-
-void FreeNameSubtrees(Base_entry* names, void* heap)
-{
-    (void)heap;
-
-    while (names) {
-        Base_entry* tmp = names->next;
-
-        XFREE(names->name, heap, DYNAMIC_TYPE_ALTNAME);
-        XFREE(names,       heap, DYNAMIC_TYPE_ALTNAME);
-        names = tmp;
-    }
-}
-
-#endif /* IGNORE_NAME_CONSTRAINTS */
-
-void FreeDecodedCert(DecodedCert* cert)
-{
-    if (cert->subjectCNStored == 1)
-        XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
-    if (cert->pubKeyStored == 1)
-        XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-    if (cert->weOwnAltNames && cert->altNames)
-        FreeAltNames(cert->altNames, cert->heap);
-#ifndef IGNORE_NAME_CONSTRAINTS
-    if (cert->altEmailNames)
-        FreeAltNames(cert->altEmailNames, cert->heap);
-    if (cert->permittedNames)
-        FreeNameSubtrees(cert->permittedNames, cert->heap);
-    if (cert->excludedNames)
-        FreeNameSubtrees(cert->excludedNames, cert->heap);
-#endif /* IGNORE_NAME_CONSTRAINTS */
-#ifdef WOLFSSL_SEP
-    XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT);
-    XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT);
-    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);
-#endif /* OPENSSL_EXTRA */
-    FreeSignatureCtx(&cert->sigCtx);
-}
-
-static int GetCertHeader(DecodedCert* cert)
-{
-    int ret = 0, len;
-
-    if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    cert->certBegin = cert->srcIdx;
-
-    if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-    cert->sigIndex = len + cert->srcIdx;
-
-    if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version,
-                                                              cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial,
-                                        &cert->serialSz, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    return ret;
-}
-
-#if !defined(NO_RSA)
-/* Store Rsa Key, may save later, Dsa could use in future */
-static int StoreRsaKey(DecodedCert* cert)
-{
-    int    length;
-    word32 recvd = cert->srcIdx;
-
-    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    recvd = cert->srcIdx - recvd;
-    length += recvd;
-
-    while (recvd--)
-       cert->srcIdx--;
-
-    cert->pubKeySize = length;
-    cert->publicKey = cert->source + cert->srcIdx;
-    cert->srcIdx += length;
-
-    return 0;
-}
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-
-    /* return 0 on success if the ECC curve oid sum is supported */
-    static int CheckCurve(word32 oid)
-    {
-        int ret = 0;
-        word32 oidSz = 0;
-
-        ret = wc_ecc_get_oid(oid, NULL, &oidSz);
-        if (ret < 0 || oidSz <= 0) {
-            WOLFSSL_MSG("CheckCurve not found");
-            ret = ALGO_ID_E;
-        }
-
-        return ret;
-    }
-
-#endif /* HAVE_ECC */
-
-static int GetKey(DecodedCert* cert)
-{
-    int length;
-#if defined(HAVE_ECC) || defined(HAVE_NTRU)
-    int tmpIdx = cert->srcIdx;
-#endif
-
-    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    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, NULL,
-                                 cert->maxIdx, 1, NULL);
-            if (ret != 0)
-                return ret;
-
-            return StoreRsaKey(cert);
-        }
-
-    #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;
-#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);
-
-            cert->publicKey = (byte*)XMALLOC(keyLen, cert->heap,
-                                             DYNAMIC_TYPE_PUBLIC_KEY);
-            if (cert->publicKey == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return MEMORY_E;
-            }
-            XMEMCPY(cert->publicKey, keyBlob, keyLen);
-            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);
-
-            if (cert->source[cert->srcIdx] !=
-                                             (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;
-            }
-
-            cert->publicKey = (byte*)XMALLOC(pubLen, cert->heap,
-                                             DYNAMIC_TYPE_PUBLIC_KEY);
-            if (cert->publicKey == NULL)
-                return MEMORY_E;
-            XMEMCPY(cert->publicKey, &cert->source[tmpIdx], pubLen);
-            cert->pubKeyStored = 1;
-            cert->pubKeySize   = pubLen;
-
-            cert->srcIdx = tmpIdx + pubLen;
-
-            return 0;
-        }
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        case ED25519k:
-        {
-            int ret;
-
-            cert->pkCurveOID = ED25519k;
-
-            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
-                                 cert->maxIdx, 1, NULL);
-            if (ret != 0)
-                return ret;
-
-            cert->publicKey = (byte*) XMALLOC(length, cert->heap,
-                                              DYNAMIC_TYPE_PUBLIC_KEY);
-            if (cert->publicKey == NULL)
-                return MEMORY_E;
-            XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
-            cert->pubKeyStored = 1;
-            cert->pubKeySize   = length;
-
-            cert->srcIdx += length;
-
-            return 0;
-        }
-    #endif /* HAVE_ED25519 */
-        default:
-            return ASN_UNKNOWN_OID_E;
-    }
-}
-
-/* process NAME, either issuer or subject */
-static int GetName(DecodedCert* cert, int nameType)
-{
-    int    length;  /* length of all distinguished names */
-    int    dummy;
-    int    ret;
-    char*  full;
-    byte*  hash;
-    word32 idx;
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        DecodedName* dName =
-                  (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
-        int dcnum = 0;
-    #endif /* OPENSSL_EXTRA */
-
-    WOLFSSL_MSG("Getting Cert Name");
-
-    if (nameType == ISSUER) {
-        full = cert->issuer;
-        hash = cert->issuerHash;
-    }
-    else {
-        full = cert->subject;
-        hash = cert->subjectHash;
-    }
-
-    if (cert->srcIdx >= cert->maxIdx) {
-        return BUFFER_E;
-    }
-
-    if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) {
-        WOLFSSL_MSG("Trying optional prefix...");
-
-        if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0)
-            return ASN_PARSE_E;
-        WOLFSSL_MSG("Got optional prefix");
-    }
-
-    /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
-     * calculated over the entire DER encoding of the Name field, including
-     * the tag and length. */
-    idx = cert->srcIdx;
-    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-#ifdef NO_SHA
-    ret = wc_Sha256Hash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#else
-    ret = wc_ShaHash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#endif
-    if (ret != 0)
-        return ret;
-
-    length += cert->srcIdx;
-    idx = 0;
-
-#ifdef HAVE_PKCS7
-    /* store pointer to raw issuer */
-    if (nameType == ISSUER) {
-        cert->issuerRaw = &cert->source[cert->srcIdx];
-        cert->issuerRawLen = length - cert->srcIdx;
-    }
-#endif
-#ifndef IGNORE_NAME_CONSTRAINTS
-    if (nameType == SUBJECT) {
-        cert->subjectRaw = &cert->source[cert->srcIdx];
-        cert->subjectRawLen = length - cert->srcIdx;
-    }
-#endif
-
-    while (cert->srcIdx < (word32)length) {
-        byte   b;
-        byte   joint[2];
-        byte   tooBig = FALSE;
-        int    oidSz;
-
-        if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) {
-            WOLFSSL_MSG("Cert name lacks set header, trying sequence");
-        }
-
-        if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) <= 0)
-            return ASN_PARSE_E;
-
-        ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx);
-        if (ret != 0)
-            return ret;
-
-        /* make sure there is room for joint */
-        if ((cert->srcIdx + sizeof(joint)) > cert->maxIdx)
-            return ASN_PARSE_E;
-
-        XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
-
-        /* v1 name types */
-        if (joint[0] == 0x55 && joint[1] == 0x04) {
-            const char*  copy = NULL;
-            int    strLen;
-            byte   id;
-
-            cert->srcIdx += 2;
-            id = cert->source[cert->srcIdx++];
-            b  = cert->source[cert->srcIdx++]; /* encoding */
-
-            if (GetLength(cert->source, &cert->srcIdx, &strLen,
-                          cert->maxIdx) < 0)
-                return ASN_PARSE_E;
-
-            if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) {
-                /* include biggest pre fix header too 4 = "/serialNumber=" */
-                WOLFSSL_MSG("ASN Name too big, skipping");
-                tooBig = TRUE;
-            }
-
-            if (id == ASN_COMMON_NAME) {
-                if (nameType == SUBJECT) {
-                    cert->subjectCN = (char *)&cert->source[cert->srcIdx];
-                    cert->subjectCNLen = strLen;
-                    cert->subjectCNEnc = b;
-                }
-
-                copy = WOLFSSL_COMMON_NAME;
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->cnIdx = cert->srcIdx;
-                    dName->cnLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_SUR_NAME) {
-                copy = WOLFSSL_SUR_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectSN = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectSNLen = strLen;
-                        cert->subjectSNEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->snIdx = cert->srcIdx;
-                    dName->snLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_COUNTRY_NAME) {
-                copy = WOLFSSL_COUNTRY_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectC = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectCLen = strLen;
-                        cert->subjectCEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->cIdx = cert->srcIdx;
-                    dName->cLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_LOCALITY_NAME) {
-                copy = WOLFSSL_LOCALITY_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectL = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectLLen = strLen;
-                        cert->subjectLEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->lIdx = cert->srcIdx;
-                    dName->lLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_STATE_NAME) {
-                copy = WOLFSSL_STATE_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectST = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectSTLen = strLen;
-                        cert->subjectSTEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->stIdx = cert->srcIdx;
-                    dName->stLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_ORG_NAME) {
-                copy = WOLFSSL_ORG_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectO = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectOLen = strLen;
-                        cert->subjectOEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->oIdx = cert->srcIdx;
-                    dName->oLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_ORGUNIT_NAME) {
-                copy = WOLFSSL_ORGUNIT_NAME;
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectOU = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectOULen = strLen;
-                        cert->subjectOUEnc = b;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->ouIdx = cert->srcIdx;
-                    dName->ouLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            else if (id == ASN_SERIAL_NUMBER) {
-                copy = WOLFSSL_SERIAL_NUMBER;
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->snIdx = cert->srcIdx;
-                    dName->snLen = strLen;
-                #endif /* OPENSSL_EXTRA */
-            }
-            if (copy && !tooBig) {
-                XMEMCPY(&full[idx], copy, XSTRLEN(copy));
-                idx += (word32)XSTRLEN(copy);
-            #ifdef WOLFSSL_WPAS
-                full[idx] = '=';
-                idx++;
-            #endif
-                XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
-                idx += strLen;
-            }
-
-            cert->srcIdx += strLen;
-        }
-        else {
-            /* skip */
-            byte email = FALSE;
-            byte pilot = FALSE;
-            byte id    = 0;
-            int  adv;
-
-            if (joint[0] == 0x2a && joint[1] == 0x86)  /* email id hdr */
-                email = TRUE;
-
-            if (joint[0] == 0x9  && joint[1] == 0x92) { /* uid id hdr */
-                /* last value of OID is the type of pilot attribute */
-                id    = cert->source[cert->srcIdx + oidSz - 1];
-                pilot = TRUE;
-            }
-
-            cert->srcIdx += oidSz + 1;
-
-            if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0)
-                return ASN_PARSE_E;
-
-            if (adv > (int)(ASN_NAME_MAX - idx)) {
-                WOLFSSL_MSG("ASN name too big, skipping");
-                tooBig = TRUE;
-            }
-
-            if (email) {
-                if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) {
-                    WOLFSSL_MSG("ASN name too big, skipping");
-                    tooBig = TRUE;
-                }
-                if (!tooBig) {
-                    XMEMCPY(&full[idx], "/emailAddress=", 14);
-                    idx += 14;
-                }
-
-                #ifdef WOLFSSL_CERT_GEN
-                    if (nameType == SUBJECT) {
-                        cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
-                        cert->subjectEmailLen = adv;
-                    }
-                #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->emailIdx = cert->srcIdx;
-                    dName->emailLen = adv;
-                #endif /* OPENSSL_EXTRA */
-                #ifndef IGNORE_NAME_CONSTRAINTS
-                    {
-                        DNS_entry* emailName = NULL;
-
-                        emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
-                                              cert->heap, DYNAMIC_TYPE_ALTNAME);
-                        if (emailName == NULL) {
-                            WOLFSSL_MSG("\tOut of Memory");
-                            return MEMORY_E;
-                        }
-                        emailName->type = 0;
-                        emailName->name = (char*)XMALLOC(adv + 1,
-                                              cert->heap, DYNAMIC_TYPE_ALTNAME);
-                        if (emailName->name == NULL) {
-                            WOLFSSL_MSG("\tOut of Memory");
-                            XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME);
-                            return MEMORY_E;
-                        }
-                        emailName->len = adv;
-                        XMEMCPY(emailName->name,
-                                              &cert->source[cert->srcIdx], adv);
-                        emailName->name[adv] = '\0';
-
-                        emailName->next = cert->altEmailNames;
-                        cert->altEmailNames = emailName;
-                    }
-                #endif /* IGNORE_NAME_CONSTRAINTS */
-                if (!tooBig) {
-                    XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
-                    idx += adv;
-                }
-            }
-
-            if (pilot) {
-                if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) {
-                    WOLFSSL_MSG("ASN name too big, skipping");
-                    tooBig = TRUE;
-                }
-                if (!tooBig) {
-                    switch (id) {
-                        case ASN_USER_ID:
-                            XMEMCPY(&full[idx], "/UID=", 5);
-                            idx += 5;
-                        #if defined(OPENSSL_EXTRA) || \
-                            defined(OPENSSL_EXTRA_X509_SMALL)
-                            dName->uidIdx = cert->srcIdx;
-                            dName->uidLen = adv;
-                        #endif /* OPENSSL_EXTRA */
-                            break;
-
-                        case ASN_DOMAIN_COMPONENT:
-                            XMEMCPY(&full[idx], "/DC=", 4);
-                            idx += 4;
-                        #if defined(OPENSSL_EXTRA) || \
-                            defined(OPENSSL_EXTRA_X509_SMALL)
-                            dName->dcIdx[dcnum] = cert->srcIdx;
-                            dName->dcLen[dcnum] = adv;
-                            dName->dcNum = dcnum + 1;
-                            dcnum++;
-                        #endif /* OPENSSL_EXTRA */
-                            break;
-
-                        default:
-                            WOLFSSL_MSG("Unknown pilot attribute type");
-                            return ASN_PARSE_E;
-                    }
-                    XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
-                    idx += adv;
-                }
-            }
-
-            cert->srcIdx += adv;
-        }
-    }
-    full[idx++] = 0;
-
-    #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);
-                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);
-                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);
-                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);
-                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);
-                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);
-                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);
-                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);
-                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);
-                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);
-                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 */
-
-    return 0;
-}
-
-
-#ifndef NO_ASN_TIME
-
-/* two byte date/time, add to value */
-static WC_INLINE void GetTime(int* value, const byte* date, int* idx)
-{
-    int i = *idx;
-
-    *value += btoi(date[i++]) * 10;
-    *value += btoi(date[i++]);
-
-    *idx = i;
-}
-
-int ExtractDate(const unsigned char* date, unsigned char format,
-                                                  struct tm* certTime, int* idx)
-{
-    XMEMSET(certTime, 0, sizeof(certTime));
-
-    if (format == ASN_UTC_TIME) {
-        /*if (btoi(date[0]) >= 5)
-            certTime->tm_year = 1900;
-        else
-            certTime->tm_year = 2000;*/
-    }
-    else  { /* format == GENERALIZED_TIME */
-        //certTime->tm_year += btoi(date[*idx]) * 1000; *idx = *idx + 1;
-        //certTime->tm_year += btoi(date[*idx]) * 100;  *idx = *idx + 1;
-    }
-
-    /* adjust tm_year, tm_mon */
-    /*GetTime((int*)&certTime->tm_year, date, idx); certTime->tm_year -= 1900;
-    GetTime((int*)&certTime->tm_mon,  date, idx); certTime->tm_mon  -= 1;
-    GetTime((int*)&certTime->tm_mday, date, idx);
-    GetTime((int*)&certTime->tm_hour, date, idx);
-    GetTime((int*)&certTime->tm_min,  date, idx);
-    GetTime((int*)&certTime->tm_sec,  date, idx);*/
-
-    return 1;
-}
-
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
-    defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-int GetTimeString(byte* date, int format, char* buf, int len)
-{
-    struct tm t;
-    int idx = 0;
-
-    if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
-        return 0;
-    }
-
-    if (date[idx] != 'Z') {
-        WOLFSSL_MSG("UTCtime, not Zulu") ;
-        return 0;
-    }
-
-    /* place month in buffer */
-    buf[0] = '\0';
-    switch(t.tm_mon) {
-        case 0:  XSTRNCAT(buf, "Jan ", 4); break;
-        case 1:  XSTRNCAT(buf, "Feb ", 4); break;
-        case 2:  XSTRNCAT(buf, "Mar ", 4); break;
-        case 3:  XSTRNCAT(buf, "Apr ", 4); break;
-        case 4:  XSTRNCAT(buf, "May ", 4); break;
-        case 5:  XSTRNCAT(buf, "Jun ", 4); break;
-        case 6:  XSTRNCAT(buf, "Jul ", 4); break;
-        case 7:  XSTRNCAT(buf, "Aug ", 4); break;
-        case 8:  XSTRNCAT(buf, "Sep ", 4); break;
-        case 9:  XSTRNCAT(buf, "Oct ", 4); break;
-        case 10: XSTRNCAT(buf, "Nov ", 4); break;
-        case 11: XSTRNCAT(buf, "Dec ", 4); break;
-        default:
-            return 0;
-
-    }
-    idx = 4; /* use idx now for char buffer */
-    buf[idx] = ' ';
-
-    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);
-
-    return 1;
-}
-#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-
-
-#if defined(USE_WOLF_VALIDDATE)
-
-/* to the second */
-static int DateGreaterThan(const struct tm* a, const struct tm* b)
-{
-    /*if (a->tm_year > b->tm_year)
-        return 1;
-
-    if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
-        return 1;
-
-    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
-           a->tm_mday > b->tm_mday)
-        return 1;
-
-    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
-        a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour)
-        return 1;
-
-    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
-        a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
-        a->tm_min > b->tm_min)
-        return 1;
-
-    if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
-        a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
-        a->tm_min  == b->tm_min  && a->tm_sec > b->tm_sec)
-        return 1;*/
-
-    return 0; /* false */
-}
-
-
-static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
-{
-    return DateGreaterThan(b,a);
-}
-
-/* like atoi but only use first byte */
-/* Make sure before and after dates are valid */
-int ValidateDate(const byte* date, byte format, int dateType)
-{
-    time_t ltime;
-    struct tm  certTime;
-    struct tm* localTime;
-    struct tm* tmpTime = NULL;
-    int    i = 0;
-    int    timeDiff = 0 ;
-    int    diffHH = 0 ; int diffMM = 0 ;
-    int    diffSign = 0 ;
-
-#if defined(NEED_TMP_TIME)
-    struct tm tmpTimeStorage;
-    tmpTime = &tmpTimeStorage;
-#else
-    (void)tmpTime;
-#endif
-
-    ltime = XTIME(0);
-
-#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW
-    if (dateType == BEFORE) {
-        WOLFSSL_MSG("Skewing local time for before date check");
-        ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW;
-    }
-#endif
-
-#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW
-    if (dateType == AFTER) {
-        WOLFSSL_MSG("Skewing local time for after date check");
-        ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW;
-    }
-#endif
-
-    if (!ExtractDate(date, format, &certTime, &i)) {
-        WOLFSSL_MSG("Error extracting the date");
-        return 0;
-    }
-
-    if ((date[i] == '+') || (date[i] == '-')) {
-        WOLFSSL_MSG("Using time differential, not Zulu") ;
-        diffSign = date[i++] == '+' ? 1 : -1 ;
-        GetTime(&diffHH, date, &i);
-        GetTime(&diffMM, date, &i);
-        timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
-    } else if (date[i] != 'Z') {
-        WOLFSSL_MSG("UTCtime, niether Zulu or time differential") ;
-        return 0;
-    }
-
-    ltime -= (time_t)timeDiff ;
-    localTime = XGMTIME(&ltime, tmpTime);
-
-    if (localTime == NULL) {
-        WOLFSSL_MSG("XGMTIME failed");
-        return 0;
-    }
-
-    if (dateType == BEFORE) {
-        if (DateLessThan(localTime, &certTime)) {
-            WOLFSSL_MSG("Date BEFORE check failed");
-            return 0;
-        }
-    }
-    else {  /* dateType == AFTER */
-        if (DateGreaterThan(localTime, &certTime)) {
-            WOLFSSL_MSG("Date AFTER check failed");
-            return 0;
-        }
-    }
-
-    return 1;
-}
-#endif /* USE_WOLF_VALIDDATE */
-
-int wc_GetTime(void* timePtr, word32 timeSize)
-{
-    time_t* ltime = (time_t*)timePtr;
-
-    if (timePtr == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if ((word32)sizeof(time_t) > timeSize) {
-        return BUFFER_E;
-    }
-
-    *ltime = XTIME(0);
-
-    return 0;
-}
-
-#endif /* !NO_ASN_TIME */
-
-
-/* Get date buffer, format and length. Returns 0=success or error */
-static int GetDateInfo(const byte* source, word32* idx, const byte** pDate,
-                        byte* pFormat, int* pLength, word32 maxIdx)
-{
-    int length;
-    byte format;
-
-    if (source == NULL || idx == NULL)
-        return BAD_FUNC_ARG;
-
-    /* get ASN format header */
-    if (*idx+1 > maxIdx)
-        return BUFFER_E;
-    format = source[*idx];
-    *idx += 1;
-    if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME)
-        return ASN_TIME_E;
-
-    /* get length */
-    if (GetLength(source, idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-    if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
-        return ASN_DATE_SZ_E;
-
-    /* return format, date and length */
-    if (pFormat)
-        *pFormat = format;
-    if (pDate)
-        *pDate = &source[*idx];
-    if (pLength)
-        *pLength = length;
-
-    *idx += length;
-
-    return 0;
-}
-
-static int GetDate(DecodedCert* cert, int dateType, int verify)
-{
-    int    ret, length;
-    const byte *datePtr = NULL;
-    byte   date[MAX_DATE_SIZE];
-    byte   format;
-    word32 startIdx = 0;
-
-    if (dateType == BEFORE)
-        cert->beforeDate = &cert->source[cert->srcIdx];
-    else
-        cert->afterDate = &cert->source[cert->srcIdx];
-    startIdx = cert->srcIdx;
-
-    ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format,
-                      &length, cert->maxIdx);
-    if (ret < 0)
-        return ret;
-
-    XMEMSET(date, 0, MAX_DATE_SIZE);
-    XMEMCPY(date, datePtr, length);
-
-    if (dateType == BEFORE)
-        cert->beforeDateLen = cert->srcIdx - startIdx;
-    else
-        cert->afterDateLen  = cert->srcIdx - startIdx;
-
-#ifndef NO_ASN_TIME
-    if (verify != NO_VERIFY && !XVALIDATE_DATE(date, format, dateType)) {
-        if (dateType == BEFORE)
-            return ASN_BEFORE_DATE_E;
-        else
-            return ASN_AFTER_DATE_E;
-    }
-#else
-    (void)verify;
-#endif
-
-    return 0;
-}
-
-static int GetValidity(DecodedCert* cert, int verify)
-{
-    int length;
-    int badDate = 0;
-
-    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    if (GetDate(cert, BEFORE, verify) < 0)
-        badDate = ASN_BEFORE_DATE_E; /* continue parsing */
-
-    if (GetDate(cert, AFTER, verify) < 0)
-        return ASN_AFTER_DATE_E;
-
-    if (badDate != 0)
-        return badDate;
-
-    return 0;
-}
-
-
-int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date,
-    byte* format, int* length)
-{
-    int ret;
-    word32 idx = 0;
-
-    ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz);
-    if (ret < 0)
-        return ret;
-
-    return 0;
-}
-
-#ifndef NO_ASN_TIME
-int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
-    struct tm* timearg)
-{
-    int idx = 0;
-    (void)length;
-    if (!ExtractDate(date, format, timearg, &idx))
-        return ASN_TIME_E;
-    return 0;
-}
-
-#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES)
-int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after)
-{
-    int ret = 0;
-    const byte* date;
-    byte format;
-    int length;
-
-    if (cert == NULL)
-        return BAD_FUNC_ARG;
-
-    if (before && cert->beforeDateSz > 0) {
-        ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date,
-                             &format, &length);
-        if (ret == 0)
-            ret = wc_GetDateAsCalendarTime(date, length, format, before);
-    }
-    if (after && cert->afterDateSz > 0) {
-        ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date,
-                             &format, &length);
-        if (ret == 0)
-            ret = wc_GetDateAsCalendarTime(date, length, format, after);
-    }
-
-    return ret;
-}
-#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */
-#endif /* !NO_ASN_TIME */
-
-
-int DecodeToKey(DecodedCert* cert, int verify)
-{
-    int badDate = 0;
-    int ret;
-
-    if ( (ret = GetCertHeader(cert)) < 0)
-        return ret;
-
-    WOLFSSL_MSG("Got Cert Header");
-
-    if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
-                          oidSigType, cert->maxIdx)) < 0)
-        return ret;
-
-    WOLFSSL_MSG("Got Algo ID");
-
-    if ( (ret = GetName(cert, ISSUER)) < 0)
-        return ret;
-
-    if ( (ret = GetValidity(cert, verify)) < 0)
-        badDate = ret;
-
-    if ( (ret = GetName(cert, SUBJECT)) < 0)
-        return ret;
-
-    WOLFSSL_MSG("Got Subject Name");
-
-    if ( (ret = GetKey(cert)) < 0)
-        return ret;
-
-    WOLFSSL_MSG("Got Key");
-
-    if (badDate != 0)
-        return badDate;
-
-    return ret;
-}
-
-static int GetSignature(DecodedCert* cert)
-{
-    int length;
-    int ret;
-    ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1,
-                         NULL);
-    if (ret != 0)
-        return ret;
-
-    cert->sigLength = length;
-    cert->signature = &cert->source[cert->srcIdx];
-    cert->srcIdx += cert->sigLength;
-
-    return 0;
-}
-
-static word32 SetOctetString8Bit(word32 len, byte* output)
-{
-    output[0] = ASN_OCTET_STRING;
-    output[1] = (byte)len;
-    return 2;
-}
-
-static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
-{
-    word32 idx = SetOctetString8Bit(digSz, output);
-    XMEMCPY(&output[idx], digest, digSz);
-
-    return idx + digSz;
-}
-
-
-static word32 BytePrecision(word32 value)
-{
-    word32 i;
-    for (i = sizeof(value); i; --i)
-        if (value >> ((i - 1) * WOLFSSL_BIT_SIZE))
-            break;
-
-    return i;
-}
-
-
-WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output)
-{
-    word32 i = 0, j;
-
-    if (length < ASN_LONG_LENGTH)
-        output[i++] = (byte)length;
-    else {
-        output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
-
-        for (j = BytePrecision(length); j; --j) {
-            output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
-            i++;
-        }
-    }
-
-    return i;
-}
-
-
-WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output)
-{
-    output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
-    return SetLength(len, output + 1) + 1;
-}
-
-WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output)
-{
-    output[0] = ASN_OCTET_STRING;
-    return SetLength(len, output + 1) + 1;
-}
-
-/* Write a set header to output */
-WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output)
-{
-    output[0] = ASN_SET | ASN_CONSTRUCTED;
-    return SetLength(len, output + 1) + 1;
-}
-
-WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
-{
-
-    output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
-                    | ASN_CONTEXT_SPECIFIC | number;
-    return SetLength(len, output + 1) + 1;
-}
-
-WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output)
-{
-    output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
-    return SetLength(len, output + 1) + 1;
-}
-
-
-#if defined(HAVE_ECC)
-
-static int SetCurve(ecc_key* key, byte* output)
-{
-#ifdef HAVE_OID_ENCODING
-    int ret;
-#endif
-    int idx = 0;
-    word32 oidSz = 0;
-
-    /* validate key */
-    if (key == NULL || key->dp == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef HAVE_OID_ENCODING
-    ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz);
-    if (ret != 0) {
-        return ret;
-    }
-#else
-    oidSz = key->dp->oidSz;
-#endif
-
-    idx += SetObjectId(oidSz, output);
-
-#ifdef HAVE_OID_ENCODING
-    ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz);
-    if (ret != 0) {
-        return ret;
-    }
-#else
-    XMEMCPY(output+idx, key->dp->oid, oidSz);
-#endif
-    idx += oidSz;
-
-    return idx;
-}
-
-#endif /* HAVE_ECC */
-
-
-#ifdef HAVE_ECC
-static WC_INLINE int IsSigAlgoECDSA(int algoOID)
-{
-    /* ECDSA sigAlgo must not have ASN1 NULL parameters */
-    if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA ||
-        algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) {
-        return 1;
-    }
-
-    return 0;
-}
-#endif
-
-WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
-{
-    word32 tagSz, idSz, seqSz, algoSz = 0;
-    const  byte* algoName = 0;
-    byte   ID_Length[1 + MAX_LENGTH_SZ];
-    byte   seqArray[MAX_SEQ_SZ + 1];  /* add object_id to end */
-
-    tagSz = (type == oidHashType ||
-             (type == oidSigType
-        #ifdef HAVE_ECC
-              && !IsSigAlgoECDSA(algoOID)
-        #endif
-        #ifdef HAVE_ED25519
-              && algoOID != ED25519k
-        #endif
-              ) ||
-             (type == oidKeyType && algoOID == RSAk)) ? 2 : 0;
-
-    algoName = OidFromId(algoOID, type, &algoSz);
-
-    if (algoName == NULL) {
-        WOLFSSL_MSG("Unknown Algorithm");
-        return 0;
-    }
-
-    idSz  = SetObjectId(algoSz, ID_Length);
-    seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray);
-
-    XMEMCPY(output, seqArray, seqSz);
-    XMEMCPY(output + seqSz, ID_Length, idSz);
-    XMEMCPY(output + seqSz + idSz, algoName, algoSz);
-    if (tagSz == 2)
-        SetASNNull(&output[seqSz + idSz + algoSz]);
-
-    return seqSz + idSz + algoSz + tagSz;
-
-}
-
-
-word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
-                          int hashOID)
-{
-    byte digArray[MAX_ENCODED_DIG_SZ];
-    byte algoArray[MAX_ALGO_SZ];
-    byte seqArray[MAX_SEQ_SZ];
-    word32 encDigSz, algoSz, seqSz;
-
-    encDigSz = SetDigest(digest, digSz, digArray);
-    algoSz   = SetAlgoID(hashOID, algoArray, oidHashType, 0);
-    seqSz    = SetSequence(encDigSz + algoSz, seqArray);
-
-    XMEMCPY(out, seqArray, seqSz);
-    XMEMCPY(out + seqSz, algoArray, algoSz);
-    XMEMCPY(out + seqSz + algoSz, digArray, encDigSz);
-
-    return encDigSz + algoSz + seqSz;
-}
-
-
-int wc_GetCTC_HashOID(int type)
-{
-    int ret;
-    enum wc_HashType hType;
-
-    hType = wc_HashTypeConvert(type);
-    ret = wc_HashGetOID(hType);
-    if (ret < 0)
-        ret = 0; /* backwards compatibility */
-
-    return ret;
-}
-
-void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId)
-{
-    if (sigCtx) {
-        XMEMSET(sigCtx, 0, sizeof(SignatureCtx));
-        sigCtx->devId = devId;
-        sigCtx->heap = heap;
-    }
-}
-
-void FreeSignatureCtx(SignatureCtx* sigCtx)
-{
-    if (sigCtx == NULL)
-        return;
-
-    if (sigCtx->digest) {
-        XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST);
-        sigCtx->digest = NULL;
-    }
-#ifndef NO_RSA
-    if (sigCtx->plain) {
-        XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
-        sigCtx->plain = NULL;
-    }
-#endif
-    if (sigCtx->key.ptr) {
-        switch (sigCtx->keyOID) {
-        #ifndef NO_RSA
-            case RSAk:
-                wc_FreeRsaKey(sigCtx->key.rsa);
-                XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA);
-                break;
-        #endif /* !NO_RSA */
-        #ifdef HAVE_ECC
-            case ECDSAk:
-                wc_ecc_free(sigCtx->key.ecc);
-                XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC);
-                break;
-        #endif /* HAVE_ECC */
-        #ifdef HAVE_ED25519
-            case ED25519k:
-                wc_ed25519_free(sigCtx->key.ed25519);
-                XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519);
-                break;
-        #endif /* HAVE_ED25519 */
-            default:
-                break;
-        } /* switch (keyOID) */
-        sigCtx->key.ptr = NULL;
-    }
-
-    /* reset state, we are done */
-    sigCtx->state = SIG_STATE_BEGIN;
-}
-
-static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
-                            byte* digest, int* typeH, int* digestSz, int verify)
-{
-    int ret = 0;
-
-    (void)verify;
-
-    switch (sigOID) {
-    #if defined(WOLFSSL_MD2)
-        case CTC_MD2wRSA:
-            if (!verify) {
-                ret = HASH_TYPE_E;
-                WOLFSSL_MSG("MD2 not supported for signing");
-            }
-            else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = MD2h;
-                *digestSz = MD2_DIGEST_SIZE;
-            }
-        break;
-    #endif
-    #ifndef NO_MD5
-        case CTC_MD5wRSA:
-            if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = MD5h;
-                *digestSz = WC_MD5_DIGEST_SIZE;
-            }
-            break;
-    #endif
-    #ifndef NO_SHA
-        case CTC_SHAwRSA:
-        case CTC_SHAwDSA:
-        case CTC_SHAwECDSA:
-            if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) {
-                *typeH    = SHAh;
-                *digestSz = WC_SHA_DIGEST_SIZE;
-            }
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA224
-        case CTC_SHA224wRSA:
-        case CTC_SHA224wECDSA:
-            if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = SHA224h;
-                *digestSz = WC_SHA224_DIGEST_SIZE;
-            }
-            break;
-    #endif
-    #ifndef NO_SHA256
-        case CTC_SHA256wRSA:
-        case CTC_SHA256wECDSA:
-            if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = SHA256h;
-                *digestSz = WC_SHA256_DIGEST_SIZE;
-            }
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case CTC_SHA384wRSA:
-        case CTC_SHA384wECDSA:
-            if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = SHA384h;
-                *digestSz = WC_SHA384_DIGEST_SIZE;
-            }
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        case CTC_SHA512wRSA:
-        case CTC_SHA512wECDSA:
-            if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) {
-                *typeH    = SHA512h;
-                *digestSz = WC_SHA512_DIGEST_SIZE;
-            }
-            break;
-    #endif
-        case CTC_ED25519:
-            /* Hashes done in signing operation.
-             * Two dependent hashes with prefixes performed.
-             */
-            break;
-        default:
-            ret = HASH_TYPE_E;
-            WOLFSSL_MSG("Hash for Signature has unsupported type");
-    }
-
-    return ret;
-}
-
-/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
-static int ConfirmSignature(SignatureCtx* sigCtx,
-    const byte* buf, word32 bufSz,
-    const byte* key, word32 keySz, word32 keyOID,
-    const byte* sig, word32 sigSz, word32 sigOID)
-{
-    int ret = 0;
-
-    if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL ||
-        keySz == 0 || sig == NULL || sigSz == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    (void)key;
-    (void)keySz;
-    (void)sig;
-    (void)sigSz;
-
-    WOLFSSL_ENTER("ConfirmSignature");
-
-    switch (sigCtx->state) {
-        case SIG_STATE_BEGIN:
-        {
-            sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap,
-                                                    DYNAMIC_TYPE_DIGEST);
-            if (sigCtx->digest == NULL) {
-                ERROR_OUT(MEMORY_E, exit_cs);
-            }
-
-            sigCtx->state = SIG_STATE_HASH;
-        } /* SIG_STATE_BEGIN */
-        FALL_THROUGH;
-
-        case SIG_STATE_HASH:
-        {
-            ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest,
-                                   &sigCtx->typeH, &sigCtx->digestSz, 1);
-            if (ret != 0) {
-                goto exit_cs;
-            }
-
-            sigCtx->state = SIG_STATE_KEY;
-        } /* SIG_STATE_HASH */
-        FALL_THROUGH;
-
-        case SIG_STATE_KEY:
-        {
-            sigCtx->keyOID = keyOID;
-
-            switch (keyOID) {
-            #ifndef NO_RSA
-                case RSAk:
-                {
-                    word32 idx = 0;
-
-                    sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
-                                                sigCtx->heap, DYNAMIC_TYPE_RSA);
-                    sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
-                                         sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
-                    if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_cs);
-                    }
-                    if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap,
-                                                        sigCtx->devId)) != 0) {
-                        goto exit_cs;
-                    }
-                    if (sigSz > MAX_ENCODED_SIG_SZ) {
-                        WOLFSSL_MSG("Verify Signature is too big");
-                        ERROR_OUT(BUFFER_E, exit_cs);
-                    }
-                    if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa,
-                                                                 keySz)) != 0) {
-                        WOLFSSL_MSG("ASN Key decode error RSA");
-                        goto exit_cs;
-                    }
-                    XMEMCPY(sigCtx->plain, sig, sigSz);
-                    sigCtx->out = NULL;
-
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev;
-                #endif
-                    break;
-                }
-            #endif /* !NO_RSA */
-            #ifdef HAVE_ECC
-                case ECDSAk:
-                {
-                    word32 idx = 0;
-
-                    sigCtx->verify = 0;
-                    sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key),
-                                                sigCtx->heap, DYNAMIC_TYPE_ECC);
-                    if (sigCtx->key.ecc == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_cs);
-                    }
-                    if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap,
-                                                          sigCtx->devId)) < 0) {
-                        goto exit_cs;
-                    }
-                    ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc,
-                                                                         keySz);
-                    if (ret < 0) {
-                        WOLFSSL_MSG("ASN Key import error ECC");
-                        goto exit_cs;
-                    }
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev;
-                #endif
-                    break;
-                }
-            #endif /* HAVE_ECC */
-            #ifdef HAVE_ED25519
-                case ED25519k:
-                {
-                    sigCtx->verify = 0;
-                    sigCtx->key.ed25519 = (ed25519_key*)XMALLOC(
-                                              sizeof(ed25519_key), sigCtx->heap,
-                                              DYNAMIC_TYPE_ED25519);
-                    if (sigCtx->key.ed25519 == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_cs);
-                    }
-                    if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
-                        goto exit_cs;
-                    }
-                    if ((ret = wc_ed25519_import_public(key, keySz,
-                                                    sigCtx->key.ed25519)) < 0) {
-                        WOLFSSL_MSG("ASN Key import error ED25519");
-                        goto exit_cs;
-                    }
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev;
-                #endif
-                    break;
-                }
-            #endif
-                default:
-                    WOLFSSL_MSG("Verify Key type unknown");
-                    ret = ASN_UNKNOWN_OID_E;
-                    break;
-            } /* switch (keyOID) */
-
-            if (ret != 0) {
-                goto exit_cs;
-            }
-
-            sigCtx->state = SIG_STATE_DO;
-
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) {
-                /* make sure event is intialized */
-                WOLF_EVENT* event = &sigCtx->asyncDev->event;
-                ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
-                    sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN);
-            }
-        #endif
-        } /* SIG_STATE_KEY */
-        FALL_THROUGH;
-
-        case SIG_STATE_DO:
-        {
-            switch (keyOID) {
-            #ifndef NO_RSA
-                case RSAk:
-                {
-                #ifdef HAVE_PK_CALLBACKS
-                    if (sigCtx->pkCbRsa) {
-                        ret = sigCtx->pkCbRsa(
-                                sigCtx->plain, sigSz, &sigCtx->out,
-                                key, keySz,
-                                sigCtx->pkCtxRsa);
-                    }
-                    else
-                #endif /* HAVE_PK_CALLBACKS */
-                    {
-                        ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz,
-                                                 &sigCtx->out, sigCtx->key.rsa);
-                    }
-                    break;
-                }
-            #endif /* !NO_RSA */
-            #ifdef HAVE_ECC
-                case ECDSAk:
-                {
-                #ifdef HAVE_PK_CALLBACKS
-                    if (sigCtx->pkCbEcc) {
-                        ret = sigCtx->pkCbEcc(
-                                sig, sigSz,
-                                sigCtx->digest, sigCtx->digestSz,
-                                key, keySz, &sigCtx->verify,
-                                sigCtx->pkCtxEcc);
-                    }
-                    else
-                #endif /* HAVE_PK_CALLBACKS */
-                    {
-                        ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest,
-                                            sigCtx->digestSz, &sigCtx->verify,
-                                            sigCtx->key.ecc);
-                    }
-                    break;
-                }
-            #endif /* HAVE_ECC */
-            #ifdef HAVE_ED25519
-                case ED25519k:
-                {
-                    ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz,
-                                          &sigCtx->verify, sigCtx->key.ed25519);
-                    break;
-                }
-            #endif
-                default:
-                    break;
-            }  /* switch (keyOID) */
-
-            if (ret < 0) {
-                /* treat all non async RSA errors as ASN_SIG_CONFIRM_E */
-                if (ret != WC_PENDING_E)
-                    ret = ASN_SIG_CONFIRM_E;
-                goto exit_cs;
-            }
-
-            sigCtx->state = SIG_STATE_CHECK;
-        } /* SIG_STATE_DO */
-        FALL_THROUGH;
-
-        case SIG_STATE_CHECK:
-        {
-            switch (keyOID) {
-            #ifndef NO_RSA
-                case RSAk:
-                {
-                    int encodedSigSz, verifySz;
-                #ifdef WOLFSSL_SMALL_STACK
-                    byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
-                                        sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                    if (encodedSig == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_cs);
-                    }
-                #else
-                    byte encodedSig[MAX_ENCODED_SIG_SZ];
-                #endif
-
-                    verifySz = ret;
-
-                    /* make sure we're right justified */
-                    encodedSigSz = wc_EncodeSignature(encodedSig,
-                            sigCtx->digest, sigCtx->digestSz, sigCtx->typeH);
-                    if (encodedSigSz == verifySz && sigCtx->out != NULL &&
-                        XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) {
-                        ret = 0;
-                    }
-                    else {
-                        WOLFSSL_MSG("RSA SSL verify match encode error");
-                        ret = ASN_SIG_CONFIRM_E;
-                    }
-
-                #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                #endif
-                    break;
-                }
-            #endif /* NO_RSA */
-            #ifdef HAVE_ECC
-                case ECDSAk:
-                {
-                    if (sigCtx->verify == 1) {
-                        ret = 0;
-                    }
-                    else {
-                        WOLFSSL_MSG("ECC Verify didn't match");
-                        ret = ASN_SIG_CONFIRM_E;
-                    }
-                    break;
-                }
-            #endif /* HAVE_ECC */
-            #ifdef HAVE_ED25519
-                case ED25519k:
-                {
-                    if (sigCtx->verify == 1) {
-                        ret = 0;
-                    }
-                    else {
-                        WOLFSSL_MSG("ED25519 Verify didn't match");
-                        ret = ASN_SIG_CONFIRM_E;
-                    }
-                    break;
-                }
-            #endif /* HAVE_ED25519 */
-                default:
-                    break;
-            }  /* switch (keyOID) */
-
-            break;
-        } /* SIG_STATE_CHECK */
-    } /* switch (sigCtx->state) */
-
-exit_cs:
-
-    WOLFSSL_LEAVE("ConfirmSignature", ret);
-
-    if (ret != WC_PENDING_E) {
-        FreeSignatureCtx(sigCtx);
-    }
-
-    return ret;
-}
-
-
-#ifndef IGNORE_NAME_CONSTRAINTS
-
-static int MatchBaseName(int type, const char* name, int nameSz,
-                         const char* base, int baseSz)
-{
-    if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
-            name[0] == '.' || nameSz < baseSz ||
-            (type != ASN_RFC822_TYPE && type != ASN_DNS_TYPE))
-        return 0;
-
-    /* If an email type, handle special cases where the base is only
-     * a domain, or is an email address itself. */
-    if (type == ASN_RFC822_TYPE) {
-        const char* p = NULL;
-        int count = 0;
-
-        if (base[0] != '.') {
-            p = base;
-            count = 0;
-
-            /* find the '@' in the base */
-            while (*p != '@' && count < baseSz) {
-                count++;
-                p++;
-            }
-
-            /* No '@' in base, reset p to NULL */
-            if (count >= baseSz)
-                p = NULL;
-        }
-
-        if (p == NULL) {
-            /* Base isn't an email address, it is a domain name,
-             * wind the name forward one character past its '@'. */
-            p = name;
-            count = 0;
-            while (*p != '@' && count < baseSz) {
-                count++;
-                p++;
-            }
-
-            if (count < baseSz && *p == '@') {
-                name = p + 1;
-                nameSz -= count + 1;
-            }
-        }
-    }
-
-    if ((type == ASN_DNS_TYPE || type == ASN_RFC822_TYPE) && base[0] == '.') {
-        int szAdjust = nameSz - baseSz;
-        name += szAdjust;
-        nameSz -= szAdjust;
-    }
-
-    while (nameSz > 0) {
-        if (XTOLOWER((unsigned char)*name++) !=
-                                               XTOLOWER((unsigned char)*base++))
-            return 0;
-        nameSz--;
-    }
-
-    return 1;
-}
-
-
-static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
-{
-    if (signer == NULL || cert == NULL)
-        return 0;
-
-    /* Check against the excluded list */
-    if (signer->excludedNames) {
-        Base_entry* base = signer->excludedNames;
-
-        while (base != NULL) {
-            switch (base->type) {
-                case ASN_DNS_TYPE:
-                {
-                    DNS_entry* name = cert->altNames;
-                    while (name != NULL) {
-                        if (MatchBaseName(ASN_DNS_TYPE,
-                                          name->name, name->len,
-                                          base->name, base->nameSz)) {
-                            return 0;
-                        }
-                        name = name->next;
-                    }
-                    break;
-                }
-                case ASN_RFC822_TYPE:
-                {
-                    DNS_entry* name = cert->altEmailNames;
-                    while (name != NULL) {
-                        if (MatchBaseName(ASN_RFC822_TYPE,
-                                          name->name, name->len,
-                                          base->name, base->nameSz)) {
-                            return 0;
-                        }
-                        name = name->next;
-                    }
-                    break;
-                }
-                case ASN_DIR_TYPE:
-                {
-                    /* allow permitted dirName smaller than actual subject */
-                    if (cert->subjectRawLen >= base->nameSz &&
-                        XMEMCMP(cert->subjectRaw, base->name,
-                                                        base->nameSz) == 0) {
-                        return 0;
-                    }
-                    break;
-                }
-            }; /* switch */
-            base = base->next;
-        }
-    }
-
-    /* Check against the permitted list */
-    if (signer->permittedNames != NULL) {
-        int needDns = 0;
-        int matchDns = 0;
-        int needEmail = 0;
-        int matchEmail = 0;
-        int needDir = 0;
-        int matchDir = 0;
-        Base_entry* base = signer->permittedNames;
-
-        while (base != NULL) {
-            switch (base->type) {
-                case ASN_DNS_TYPE:
-                {
-                    DNS_entry* name = cert->altNames;
-
-                    if (name != NULL)
-                        needDns = 1;
-
-                    while (name != NULL) {
-                        matchDns = MatchBaseName(ASN_DNS_TYPE,
-                                          name->name, name->len,
-                                          base->name, base->nameSz);
-                        name = name->next;
-                    }
-                    break;
-                }
-                case ASN_RFC822_TYPE:
-                {
-                    DNS_entry* name = cert->altEmailNames;
-
-                    if (name != NULL)
-                        needEmail = 1;
-
-                    while (name != NULL) {
-                        matchEmail = MatchBaseName(ASN_DNS_TYPE,
-                                          name->name, name->len,
-                                          base->name, base->nameSz);
-                        name = name->next;
-                    }
-                    break;
-                }
-                case ASN_DIR_TYPE:
-                {
-                    /* allow permitted dirName smaller than actual subject */
-                    needDir = 1;
-                    if (cert->subjectRaw != NULL &&
-                        cert->subjectRawLen >= base->nameSz &&
-                        XMEMCMP(cert->subjectRaw, base->name,
-                                                        base->nameSz) == 0) {
-                        matchDir = 1;
-                    }
-                    break;
-                }
-            } /* switch */
-            base = base->next;
-        }
-
-        if ((needDns   && !matchDns) ||
-            (needEmail && !matchEmail) ||
-            (needDir   && !matchDir)) {
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-#endif /* IGNORE_NAME_CONSTRAINTS */
-
-static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0;
-
-    WOLFSSL_ENTER("DecodeAltNames");
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tBad Sequence");
-        return ASN_PARSE_E;
-    }
-
-    cert->weOwnAltNames = 1;
-
-    while (length > 0) {
-        byte b = input[idx++];
-
-        length--;
-
-        /* Save DNS Type names in the altNames list. */
-        /* Save Other Type names in the cert's OidMap */
-        if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
-            DNS_entry* dnsEntry;
-            int strLen;
-            word32 lenStartIdx = idx;
-
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: str length");
-                return ASN_PARSE_E;
-            }
-            length -= (idx - lenStartIdx);
-
-            dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
-                                        DYNAMIC_TYPE_ALTNAME);
-            if (dnsEntry == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                return MEMORY_E;
-            }
-
-            dnsEntry->type = ASN_DNS_TYPE;
-            dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
-                                         DYNAMIC_TYPE_ALTNAME);
-            if (dnsEntry->name == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
-                return MEMORY_E;
-            }
-            dnsEntry->len = strLen;
-            XMEMCPY(dnsEntry->name, &input[idx], strLen);
-            dnsEntry->name[strLen] = '\0';
-
-            dnsEntry->next = cert->altNames;
-            cert->altNames = dnsEntry;
-
-            length -= strLen;
-            idx    += strLen;
-        }
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
-            DNS_entry* emailEntry;
-            int strLen;
-            word32 lenStartIdx = idx;
-
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: str length");
-                return ASN_PARSE_E;
-            }
-            length -= (idx - lenStartIdx);
-
-            emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
-                                        DYNAMIC_TYPE_ALTNAME);
-            if (emailEntry == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                return MEMORY_E;
-            }
-
-            emailEntry->type = ASN_RFC822_TYPE;
-            emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
-                                         DYNAMIC_TYPE_ALTNAME);
-            if (emailEntry->name == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
-                return MEMORY_E;
-            }
-            emailEntry->len = strLen;
-            XMEMCPY(emailEntry->name, &input[idx], strLen);
-            emailEntry->name[strLen] = '\0';
-
-            emailEntry->next = cert->altEmailNames;
-            cert->altEmailNames = emailEntry;
-
-            length -= strLen;
-            idx    += strLen;
-        }
-        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) {
-            DNS_entry* uriEntry;
-            int strLen;
-            word32 lenStartIdx = idx;
-
-            WOLFSSL_MSG("\tPutting URI into list but not using");
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: str length");
-                return ASN_PARSE_E;
-            }
-            length -= (idx - lenStartIdx);
-
-            /* check that strLen at index is not past input buffer */
-            if (strLen + (int)idx > sz) {
-                return BUFFER_E;
-            }
-
-        #ifndef WOLFSSL_NO_ASN_STRICT
-            /* Verify RFC 5280 Sec 4.2.1.6 rule:
-                "The name MUST NOT be a relative URI" */
-
-            {
-                int i;
-
-                /* skip past scheme (i.e http,ftp,...) finding first ':' char */
-                for (i = 0; i < strLen; i++) {
-                    if (input[idx + i] == ':') {
-                        break;
-                    }
-                    if (input[idx + i] == '/') {
-                        i = strLen; /* error, found relative path since '/' was
-                                     * encountered before ':'. Returning error
-                                     * value in next if statement. */
-                    }
-                }
-
-                /* test if no ':' char was found and test that the next two
-                 * chars are // to match the pattern "://" */
-                if (i >= strLen - 2 || (input[idx + i + 1] != '/' ||
-                                        input[idx + i + 2] != '/')) {
-                    WOLFSSL_MSG("\tAlt Name must be absolute URI");
-                    return ASN_ALT_NAME_E;
-                }
-            }
-        #endif
-
-            uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
-                                        DYNAMIC_TYPE_ALTNAME);
-            if (uriEntry == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                return MEMORY_E;
-            }
-
-            uriEntry->type = ASN_URI_TYPE;
-            uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
-                                         DYNAMIC_TYPE_ALTNAME);
-            if (uriEntry->name == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
-                return MEMORY_E;
-            }
-            uriEntry->len = strLen;
-            XMEMCPY(uriEntry->name, &input[idx], strLen);
-            uriEntry->name[strLen] = '\0';
-
-            uriEntry->next = cert->altNames;
-            cert->altNames = uriEntry;
-
-            length -= strLen;
-            idx    += strLen;
-        }
-#endif /* IGNORE_NAME_CONSTRAINTS */
-#ifdef WOLFSSL_SEP
-        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
-        {
-            int strLen;
-            word32 lenStartIdx = idx;
-            word32 oid = 0;
-            int    ret;
-
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: other name length");
-                return ASN_PARSE_E;
-            }
-            /* Consume the rest of this sequence. */
-            length -= (strLen + idx - lenStartIdx);
-
-            if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) {
-                WOLFSSL_MSG("\tbad OID");
-                return ASN_PARSE_E;
-            }
-
-            if (oid != HW_NAME_OID) {
-                WOLFSSL_MSG("\tincorrect OID");
-                return ASN_PARSE_E;
-            }
-
-            if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
-                WOLFSSL_MSG("\twrong type");
-                return ASN_PARSE_E;
-            }
-
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: str len");
-                return ASN_PARSE_E;
-            }
-
-            if (GetSequence(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tBad Sequence");
-                return ASN_PARSE_E;
-            }
-
-            ret = GetASNObjectId(input, &idx, &strLen, sz);
-            if (ret != 0) {
-                WOLFSSL_MSG("\tbad OID");
-                return ret;
-            }
-
-            cert->hwType = (byte*)XMALLOC(strLen, cert->heap,
-                                          DYNAMIC_TYPE_X509_EXT);
-            if (cert->hwType == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                return MEMORY_E;
-            }
-
-            XMEMCPY(cert->hwType, &input[idx], strLen);
-            cert->hwTypeSz = strLen;
-            idx += strLen;
-
-            ret = GetOctetString(input, &idx, &strLen, sz);
-            if (ret < 0)
-                return ret;
-
-            cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap,
-                                               DYNAMIC_TYPE_X509_EXT);
-            if (cert->hwSerialNum == NULL) {
-                WOLFSSL_MSG("\tOut of Memory");
-                return MEMORY_E;
-            }
-
-            XMEMCPY(cert->hwSerialNum, &input[idx], strLen);
-            cert->hwSerialNum[strLen] = '\0';
-            cert->hwSerialNumSz = strLen;
-            idx += strLen;
-        }
-    #endif /* WOLFSSL_SEP */
-        else {
-            int strLen;
-            word32 lenStartIdx = idx;
-
-            WOLFSSL_MSG("\tUnsupported name type, skipping");
-
-            if (GetLength(input, &idx, &strLen, sz) < 0) {
-                WOLFSSL_MSG("\tfail: unsupported name length");
-                return ASN_PARSE_E;
-            }
-            length -= (strLen + idx - lenStartIdx);
-            idx += strLen;
-        }
-    }
-    return 0;
-}
-
-static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0;
-    int ret;
-
-    WOLFSSL_ENTER("DecodeBasicCaConstraint");
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: bad SEQUENCE");
-        return ASN_PARSE_E;
-    }
-
-    if (length == 0)
-        return 0;
-
-    /* If the basic ca constraint is false, this extension may be named, but
-     * left empty. So, if the length is 0, just return. */
-
-    ret = GetBoolean(input, &idx, sz);
-    if (ret < 0) {
-        WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN");
-        return ret;
-    }
-
-    cert->isCA = (byte)ret;
-
-    /* If there isn't any more data, return. */
-    if (idx >= (word32)sz)
-        return 0;
-
-    ret = GetInteger7Bit(input, &idx, sz);
-    if (ret < 0)
-        return ret;
-
-    cert->pathLength = (byte)ret;
-    cert->pathLengthSet = 1;
-
-    return 0;
-}
-
-
-#define CRLDP_FULL_NAME 0
-    /* From RFC3280 SS4.2.1.14, Distribution Point Name*/
-#define GENERALNAME_URI 6
-    /* From RFC3280 SS4.2.1.7, GeneralName */
-
-static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0;
-
-    WOLFSSL_ENTER("DecodeCrlDist");
-
-    /* Unwrap the list of Distribution Points*/
-    if (GetSequence(input, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    /* Unwrap a single Distribution Point */
-    if (GetSequence(input, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    /* The Distribution Point has three explicit optional members
-     *  First check for a DistributionPointName
-     */
-    if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
-    {
-        idx++;
-        if (GetLength(input, &idx, &length, sz) < 0)
-            return ASN_PARSE_E;
-
-        if (input[idx] ==
-                    (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME))
-        {
-            idx++;
-            if (GetLength(input, &idx, &length, sz) < 0)
-                return ASN_PARSE_E;
-
-            if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
-            {
-                idx++;
-                if (GetLength(input, &idx, &length, sz) < 0)
-                    return ASN_PARSE_E;
-
-                cert->extCrlInfoSz = length;
-                cert->extCrlInfo = input + idx;
-                idx += length;
-            }
-            else
-                /* This isn't a URI, skip it. */
-                idx += length;
-        }
-        else {
-            /* This isn't a FULLNAME, skip it. */
-            idx += length;
-        }
-    }
-
-    /* Check for reasonFlags */
-    if (idx < (word32)sz &&
-        input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
-    {
-        idx++;
-        if (GetLength(input, &idx, &length, sz) < 0)
-            return ASN_PARSE_E;
-        idx += length;
-    }
-
-    /* Check for cRLIssuer */
-    if (idx < (word32)sz &&
-        input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
-    {
-        idx++;
-        if (GetLength(input, &idx, &length, sz) < 0)
-            return ASN_PARSE_E;
-        idx += length;
-    }
-
-    if (idx < (word32)sz)
-    {
-        WOLFSSL_MSG("\tThere are more CRL Distribution Point records, "
-                   "but we only use the first one.");
-    }
-
-    return 0;
-}
-
-
-static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
-/*
- *  Read the first of the Authority Information Access records. If there are
- *  any issues, return without saving the record.
- */
-{
-    word32 idx = 0;
-    int length = 0;
-    byte b;
-    word32 oid;
-
-    WOLFSSL_ENTER("DecodeAuthInfo");
-
-    /* Unwrap the list of AIAs */
-    if (GetSequence(input, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    while (idx < (word32)sz) {
-        /* Unwrap a single AIA */
-        if (GetSequence(input, &idx, &length, sz) < 0)
-            return ASN_PARSE_E;
-
-        oid = 0;
-        if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0)
-            return ASN_PARSE_E;
-
-
-        /* Only supporting URIs right now. */
-        b = input[idx++];
-        if (GetLength(input, &idx, &length, sz) < 0)
-            return ASN_PARSE_E;
-
-        if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) &&
-            oid == AIA_OCSP_OID)
-        {
-            cert->extAuthInfoSz = length;
-            cert->extAuthInfo = input + idx;
-            break;
-        }
-        idx += length;
-    }
-
-    return 0;
-}
-
-
-static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0, ret = 0;
-
-    WOLFSSL_ENTER("DecodeAuthKeyId");
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: should be a SEQUENCE\n");
-        return ASN_PARSE_E;
-    }
-
-    if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
-        WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
-        return 0;
-    }
-
-    if (GetLength(input, &idx, &length, sz) <= 0) {
-        WOLFSSL_MSG("\tfail: extension data length");
-        return ASN_PARSE_E;
-    }
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    cert->extAuthKeyIdSrc = &input[idx];
-    cert->extAuthKeyIdSz = length;
-#endif /* OPENSSL_EXTRA */
-
-    if (length == KEYID_SIZE) {
-        XMEMCPY(cert->extAuthKeyId, input + idx, length);
-    }
-    else {
-    #ifdef NO_SHA
-        ret = wc_Sha256Hash(input + idx, length, cert->extAuthKeyId);
-    #else
-        ret = wc_ShaHash(input + idx, length, cert->extAuthKeyId);
-    #endif
-    }
-
-    return ret;
-}
-
-
-static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0, ret = 0;
-
-    WOLFSSL_ENTER("DecodeSubjKeyId");
-
-    if (sz <= 0)
-        return ASN_PARSE_E;
-
-    ret = GetOctetString(input, &idx, &length, sz);
-    if (ret < 0)
-        return ret;
-
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        cert->extSubjKeyIdSrc = &input[idx];
-        cert->extSubjKeyIdSz = length;
-    #endif /* OPENSSL_EXTRA */
-
-    if (length == SIGNER_DIGEST_SIZE) {
-        XMEMCPY(cert->extSubjKeyId, input + idx, length);
-    }
-    else {
-    #ifdef NO_SHA
-        ret = wc_Sha256Hash(input + idx, length, cert->extSubjKeyId);
-    #else
-        ret = wc_ShaHash(input + idx, length, cert->extSubjKeyId);
-    #endif
-    }
-
-    return ret;
-}
-
-
-static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length;
-    int ret;
-    WOLFSSL_ENTER("DecodeKeyUsage");
-
-    ret = CheckBitString(input, &idx, &length, sz, 0, NULL);
-    if (ret != 0)
-        return ret;
-
-    cert->extKeyUsage = (word16)(input[idx]);
-    if (length == 2)
-        cert->extKeyUsage |= (word16)(input[idx+1] << 8);
-
-    return 0;
-}
-
-
-static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0, oid;
-    int length;
-
-    WOLFSSL_ENTER("DecodeExtKeyUsage");
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: should be a SEQUENCE");
-        return ASN_PARSE_E;
-    }
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    cert->extExtKeyUsageSrc = input + idx;
-    cert->extExtKeyUsageSz = length;
-#endif
-
-    while (idx < (word32)sz) {
-        if (GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz) < 0)
-            return ASN_PARSE_E;
-
-        switch (oid) {
-            case EKU_ANY_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_ANY;
-                break;
-            case EKU_SERVER_AUTH_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_SERVER_AUTH;
-                break;
-            case EKU_CLIENT_AUTH_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
-                break;
-            case EKU_CODESIGNING_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN;
-                break;
-            case EKU_EMAILPROTECT_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT;
-                break;
-            case EKU_TIMESTAMP_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP;
-                break;
-            case EKU_OCSP_SIGN_OID:
-                cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
-                break;
-        }
-
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        cert->extExtKeyUsageCount++;
-    #endif
-    }
-
-    return 0;
-}
-
-
-#ifndef IGNORE_NAME_CONSTRAINTS
-#define ASN_TYPE_MASK 0xF
-static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
-{
-    word32 idx = 0;
-
-    (void)heap;
-
-    while (idx < (word32)sz) {
-        int seqLength, strLength;
-        word32 nameIdx;
-        byte b, bType;
-
-        if (GetSequence(input, &idx, &seqLength, sz) < 0) {
-            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
-            return ASN_PARSE_E;
-        }
-        nameIdx = idx;
-        b = input[nameIdx++];
-
-        if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
-            WOLFSSL_MSG("\tinvalid length");
-            return ASN_PARSE_E;
-        }
-
-        /* Get type, LSB 4-bits */
-        bType = (b & ASN_TYPE_MASK);
-
-        if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE ||
-                                                        bType == ASN_DIR_TYPE) {
-            Base_entry* entry;
-
-            /* if constructed has leading sequence */
-            if (b & ASN_CONSTRUCTED) {
-                if (GetSequence(input, &nameIdx, &strLength, sz) < 0) {
-                    WOLFSSL_MSG("\tfail: constructed be a SEQUENCE");
-                    return ASN_PARSE_E;
-                }
-            }
-
-            entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap,
-                                                          DYNAMIC_TYPE_ALTNAME);
-            if (entry == NULL) {
-                WOLFSSL_MSG("allocate error");
-                return MEMORY_E;
-            }
-
-            entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
-            if (entry->name == NULL) {
-                WOLFSSL_MSG("allocate error");
-                XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME);
-                return MEMORY_E;
-            }
-
-            XMEMCPY(entry->name, &input[nameIdx], strLength);
-            entry->nameSz = strLength;
-            entry->type = bType;
-
-            entry->next = *head;
-            *head = entry;
-        }
-
-        idx += seqLength;
-    }
-
-    return 0;
-}
-
-
-static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
-{
-    word32 idx = 0;
-    int length = 0;
-
-    WOLFSSL_ENTER("DecodeNameConstraints");
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: should be a SEQUENCE");
-        return ASN_PARSE_E;
-    }
-
-    while (idx < (word32)sz) {
-        byte b = input[idx++];
-        Base_entry** subtree = NULL;
-
-        if (GetLength(input, &idx, &length, sz) <= 0) {
-            WOLFSSL_MSG("\tinvalid length");
-            return ASN_PARSE_E;
-        }
-
-        if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
-            subtree = &cert->permittedNames;
-        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
-            subtree = &cert->excludedNames;
-        else {
-            WOLFSSL_MSG("\tinvalid subtree");
-            return ASN_PARSE_E;
-        }
-
-        DecodeSubtree(input + idx, length, subtree, cert->heap);
-
-        idx += length;
-    }
-
-    return 0;
-}
-#endif /* IGNORE_NAME_CONSTRAINTS */
-
-#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA)
-
-static int Word32ToString(char* d, word32 number)
-{
-    int i = 0;
-
-    if (d != NULL) {
-        word32 order = 1000000000;
-        word32 digit;
-
-        if (number == 0) {
-            d[i++] = '0';
-        }
-        else {
-            while (order) {
-                digit = number / order;
-                if (i > 0 || digit != 0) {
-                    d[i++] = (char)digit + '0';
-                }
-                if (digit != 0)
-                    number %= digit * order;
-                if (order > 1)
-                    order /= 10;
-                else
-                    order = 0;
-            }
-        }
-        d[i] = 0;
-    }
-
-    return i;
-}
-
-
-/* Decode ITU-T X.690 OID format to a string representation
- * return string length */
-int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
-{
-    word32 val, idx = 0, nb_bytes;
-    size_t w_bytes = 0;
-
-    if (out == NULL || in == NULL || outSz < 4 || inSz < 2)
-        return BAD_FUNC_ARG;
-
-    /* first two byte must be interpreted as : 40 * int1 + int2 */
-    val = (word16)in[idx++];
-
-    w_bytes = Word32ToString(out, val / 40);
-    out[w_bytes++] = '.';
-    w_bytes += Word32ToString(out+w_bytes, val % 40);
-
-    while (idx < inSz) {
-        /* init value */
-        val = 0;
-        nb_bytes = 0;
-
-        /* check that output size is ok */
-        if (w_bytes > (outSz - 3))
-            return BUFFER_E;
-
-        /* first bit is used to set if value is coded on 1 or multiple bytes */
-        while ((in[idx+nb_bytes] & 0x80))
-            nb_bytes++;
-
-        if (!nb_bytes)
-            val = (word32)(in[idx++] & 0x7f);
-        else {
-            word32 base = 1, tmp = nb_bytes;
-
-            while (tmp != 0) {
-                val += (word32)(in[idx+tmp] & 0x7f) * base;
-                base *= 128;
-                tmp--;
-            }
-            val += (word32)(in[idx++] & 0x7f) * base;
-
-            idx += nb_bytes;
-        }
-
-        out[w_bytes++] = '.';
-        w_bytes += Word32ToString(out+w_bytes, val);
-    }
-
-    return (int)w_bytes;
-}
-#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */
-
-#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
-    /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */
-    static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
-    {
-        word32 idx = 0;
-        word32 oldIdx;
-        int ret;
-        int total_length = 0, policy_length = 0, length = 0;
-    #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \
-        !defined(WOLFSSL_DUP_CERTPOL)
-        int i;
-    #endif
-
-        WOLFSSL_ENTER("DecodeCertPolicy");
-
-        if (GetSequence(input, &idx, &total_length, sz) < 0) {
-            WOLFSSL_MSG("\tGet CertPolicy total seq failed");
-            return ASN_PARSE_E;
-        }
-
-        /* Validate total length */
-        if (total_length > (sz - (int)idx)) {
-            WOLFSSL_MSG("\tCertPolicy length mismatch");
-            return ASN_PARSE_E;
-        }
-
-        /* Unwrap certificatePolicies */
-        do {
-            if (GetSequence(input, &idx, &policy_length, sz) < 0) {
-                WOLFSSL_MSG("\tGet CertPolicy seq failed");
-                return ASN_PARSE_E;
-            }
-
-            oldIdx = idx;
-            ret = GetASNObjectId(input, &idx, &length, sz);
-            if (ret != 0)
-                return ret;
-            policy_length -= idx - oldIdx;
-
-            if (length > 0) {
-                /* Verify length won't overrun buffer */
-                if (length > (sz - (int)idx)) {
-                    WOLFSSL_MSG("\tCertPolicy length exceeds input buffer");
-                    return ASN_PARSE_E;
-                }
-
-        #if defined(WOLFSSL_SEP)
-                cert->deviceType = (byte*)XMALLOC(length, cert->heap,
-                                                  DYNAMIC_TYPE_X509_EXT);
-                if (cert->deviceType == NULL) {
-                    WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
-                    return MEMORY_E;
-                }
-                cert->deviceTypeSz = length;
-                XMEMCPY(cert->deviceType, input + idx, length);
-                break;
-        #elif defined(WOLFSSL_CERT_EXT)
-                /* decode cert policy */
-                if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
-                                    input + idx, length) <= 0) {
-                    WOLFSSL_MSG("\tCouldn't decode CertPolicy");
-                    return ASN_PARSE_E;
-                }
-            #ifndef WOLFSSL_DUP_CERTPOL
-                /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST
-                 * NOT appear more than once in a certificate policies
-                 * extension". This is a sanity check for duplicates.
-                 * extCertPolicies should only have OID values, additional
-                 * qualifiers need to be stored in a seperate array. */
-                for (i = 0; i < cert->extCertPoliciesNb; i++) {
-                    if (XMEMCMP(cert->extCertPolicies[i],
-                            cert->extCertPolicies[cert->extCertPoliciesNb],
-                            MAX_CERTPOL_SZ) == 0) {
-                            WOLFSSL_MSG("Duplicate policy OIDs not allowed");
-                            WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted");
-                            return CERTPOLICIES_E;
-                    }
-                }
-            #endif /* !WOLFSSL_DUP_CERTPOL */
-                cert->extCertPoliciesNb++;
-        #else
-                WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0);
-                return 0;
-        #endif
-            }
-            idx += policy_length;
-        } while((int)idx < total_length
-    #if defined(WOLFSSL_CERT_EXT)
-            && cert->extCertPoliciesNb < MAX_CERTPOL_NB
-    #endif
-        );
-
-        WOLFSSL_LEAVE("DecodeCertPolicy", 0);
-        return 0;
-    }
-#endif /* WOLFSSL_SEP */
-
-/* Macro to check if bit is set, if not sets and return success.
-    Otherwise returns failure */
-/* Macro required here because bit-field operation */
-#ifndef WOLFSSL_NO_ASN_STRICT
-    #define VERIFY_AND_SET_OID(bit) \
-        if (bit == 0) \
-            bit = 1; \
-        else \
-            return ASN_OBJECT_ID_E;
-#else
-    /* With no strict defined, the verify is skipped */
-#define VERIFY_AND_SET_OID(bit) bit = 1;
-#endif
-
-static int DecodeCertExtensions(DecodedCert* cert)
-/*
- *  Processing the Certificate Extensions. This does not modify the current
- *  index. It is works starting with the recorded extensions pointer.
- */
-{
-    int ret = 0;
-    word32 idx = 0;
-    int sz = cert->extensionsSz;
-    byte* input = cert->extensions;
-    int length;
-    word32 oid;
-    byte critical = 0;
-    byte criticalFail = 0;
-
-    WOLFSSL_ENTER("DecodeCertExtensions");
-
-    if (input == NULL || sz == 0)
-        return BAD_FUNC_ARG;
-
-    if (input[idx++] != 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;
-    }
-
-    if (GetSequence(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
-        return ASN_PARSE_E;
-    }
-
-    while (idx < (word32)sz) {
-        if (GetSequence(input, &idx, &length, sz) < 0) {
-            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
-            return ASN_PARSE_E;
-        }
-
-        oid = 0;
-        if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) {
-            WOLFSSL_MSG("\tfail: OBJECT ID");
-            return ret;
-        }
-
-        /* check for critical flag */
-        critical = 0;
-        if (input[idx] == ASN_BOOLEAN) {
-            ret = GetBoolean(input, &idx, sz);
-            if (ret < 0) {
-                WOLFSSL_MSG("\tfail: critical boolean");
-                return ret;
-            }
-
-            critical = (byte)ret;
-        }
-
-        /* process the extension based on the OID */
-        ret = GetOctetString(input, &idx, &length, sz);
-        if (ret < 0) {
-            WOLFSSL_MSG("\tfail: bad OCTET STRING");
-            return ret;
-        }
-
-        switch (oid) {
-            case BASIC_CA_OID:
-                VERIFY_AND_SET_OID(cert->extBasicConstSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extBasicConstCrit = critical;
-                #endif
-                if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case CRL_DIST_OID:
-                VERIFY_AND_SET_OID(cert->extCRLdistSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extCRLdistCrit = critical;
-                #endif
-                if (DecodeCrlDist(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case AUTH_INFO_OID:
-                VERIFY_AND_SET_OID(cert->extAuthInfoSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extAuthInfoCrit = critical;
-                #endif
-                if (DecodeAuthInfo(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case ALT_NAMES_OID:
-                VERIFY_AND_SET_OID(cert->extSubjAltNameSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extSubjAltNameCrit = critical;
-                #endif
-                ret = DecodeAltNames(&input[idx], length, cert);
-                if (ret < 0)
-                    return ret;
-                break;
-
-            case AUTH_KEY_OID:
-                VERIFY_AND_SET_OID(cert->extAuthKeyIdSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extAuthKeyIdCrit = critical;
-                #endif
-                #ifndef WOLFSSL_ALLOW_CRIT_SKID
-                    /* This check is added due to RFC 5280 section 4.2.1.1
-                     * stating that conforming CA's must mark this extension
-                     * as non-critical. When parsing extensions check that
-                     * certificate was made in compliance with this. */
-                    if (critical) {
-                        WOLFSSL_MSG("Critical Auth Key ID is not allowed");
-                        WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
-                        return ASN_CRIT_EXT_E;
-                    }
-                #endif
-                if (DecodeAuthKeyId(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case SUBJ_KEY_OID:
-                VERIFY_AND_SET_OID(cert->extSubjKeyIdSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extSubjKeyIdCrit = critical;
-                #endif
-                #ifndef WOLFSSL_ALLOW_CRIT_SKID
-                    /* This check is added due to RFC 5280 section 4.2.1.2
-                     * stating that conforming CA's must mark this extension
-                     * as non-critical. When parsing extensions check that
-                     * certificate was made in compliance with this. */
-                    if (critical) {
-                        WOLFSSL_MSG("Critical Subject Key ID is not allowed");
-                        WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
-                        return ASN_CRIT_EXT_E;
-                    }
-                #endif
-
-                if (DecodeSubjKeyId(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case CERT_POLICY_OID:
-                #ifdef WOLFSSL_SEP
-                    VERIFY_AND_SET_OID(cert->extCertPolicySet);
-                    #if defined(OPENSSL_EXTRA) || \
-                        defined(OPENSSL_EXTRA_X509_SMALL)
-                        cert->extCertPolicyCrit = critical;
-                    #endif
-                #endif
-                #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
-                    if (DecodeCertPolicy(&input[idx], length, cert) < 0) {
-                        return ASN_PARSE_E;
-                    }
-                #else
-                    WOLFSSL_MSG("Certificate Policy extension not supported yet.");
-                #endif
-                break;
-
-            case KEY_USAGE_OID:
-                VERIFY_AND_SET_OID(cert->extKeyUsageSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extKeyUsageCrit = critical;
-                #endif
-                if (DecodeKeyUsage(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            case EXT_KEY_USAGE_OID:
-                VERIFY_AND_SET_OID(cert->extExtKeyUsageSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extExtKeyUsageCrit = critical;
-                #endif
-                if (DecodeExtKeyUsage(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-
-            #ifndef IGNORE_NAME_CONSTRAINTS
-            case NAME_CONS_OID:
-            #ifndef WOLFSSL_NO_ASN_STRICT
-                /* Verify RFC 5280 Sec 4.2.1.10 rule:
-                    "The name constraints extension,
-                    which MUST be used only in a CA certificate" */
-                if (!cert->isCA) {
-                    WOLFSSL_MSG("Name constraints allowed only for CA certs");
-                    return ASN_NAME_INVALID_E;
-                }
-            #endif
-                VERIFY_AND_SET_OID(cert->extNameConstraintSet);
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    cert->extNameConstraintCrit = critical;
-                #endif
-                if (DecodeNameConstraints(&input[idx], length, cert) < 0)
-                    return ASN_PARSE_E;
-                break;
-            #endif /* IGNORE_NAME_CONSTRAINTS */
-
-            case INHIBIT_ANY_OID:
-                VERIFY_AND_SET_OID(cert->inhibitAnyOidSet);
-                WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet.");
-                break;
-
-            default:
-                /* While it is a failure to not support critical extensions,
-                 * still parse the certificate ignoring the unsupported
-                 * extension to allow caller to accept it with the verify
-                 * callback. */
-                if (critical)
-                    criticalFail = 1;
-                break;
-        }
-        idx += length;
-    }
-
-    return criticalFail ? ASN_CRIT_EXT_E : 0;
-}
-
-int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
-{
-    int   ret;
-    char* ptr;
-
-    ret = ParseCertRelative(cert, type, verify, cm);
-    if (ret < 0)
-        return ret;
-
-    if (cert->subjectCNLen > 0) {
-        ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
-                              DYNAMIC_TYPE_SUBJECT_CN);
-        if (ptr == NULL)
-            return MEMORY_E;
-        XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen);
-        ptr[cert->subjectCNLen] = '\0';
-        cert->subjectCN = ptr;
-        cert->subjectCNStored = 1;
-    }
-
-    if (cert->keyOID == RSAk &&
-                          cert->publicKey != NULL  && cert->pubKeySize > 0) {
-        ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
-                              DYNAMIC_TYPE_PUBLIC_KEY);
-        if (ptr == NULL)
-            return MEMORY_E;
-        XMEMCPY(ptr, cert->publicKey, cert->pubKeySize);
-        cert->publicKey = (byte *)ptr;
-        cert->pubKeyStored = 1;
-    }
-
-    return ret;
-}
-
-/* from SSL proper, for locking can't do find here anymore */
-#ifdef __cplusplus
-    extern "C" {
-#endif
-    WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash);
-    #ifndef NO_SKID
-        WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash);
-    #endif
-#ifdef __cplusplus
-    }
-#endif
-
-
-#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS)
-
-/* dummy functions, not using wolfSSL so don't need actual ones */
-Signer* GetCA(void* signers, byte* hash)
-{
-    (void)hash;
-
-    return (Signer*)signers;
-}
-
-#ifndef NO_SKID
-Signer* GetCAByName(void* signers, byte* hash)
-{
-    (void)hash;
-
-    return (Signer*)signers;
-}
-#endif /* NO_SKID */
-
-#endif /* WOLFCRYPT_ONLY || NO_CERTS */
-
-#if (defined(WOLFSSL_ALT_CERT_CHAINS) || \
-    defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY)) && !defined(NO_SKID)
-static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
-{
-    Signer* ca = NULL;
-    if (cert->extSubjKeyIdSet)
-        ca = GetCA(cm, cert->extSubjKeyId);
-    if (ca == NULL)
-        ca = GetCAByName(cm, cert->subjectHash);
-    if (ca) {
-        if ((ca->pubKeySize == cert->pubKeySize) &&
-               (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) {
-            return ca;
-        }
-    }
-    return NULL;
-}
-#endif
-
-int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
-{
-    int    ret = 0;
-    int    badDate = 0;
-    int    criticalExt = 0;
-    word32 confirmOID;
-    int    selfSigned = 0;
-
-    if (cert == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (cert->sigCtx.state == SIG_STATE_BEGIN) {
-        if ((ret = DecodeToKey(cert, verify)) < 0) {
-            if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
-                badDate = ret;
-            else
-                return ret;
-        }
-
-        WOLFSSL_MSG("Parsed Past Key");
-
-        if (cert->srcIdx < cert->sigIndex) {
-        #ifndef ALLOW_V1_EXTENSIONS
-            if (cert->version < 2) {
-                WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions");
-                return ASN_VERSION_E;
-            }
-        #endif
-
-            /* save extensions */
-            cert->extensions    = &cert->source[cert->srcIdx];
-            cert->extensionsSz  = cert->sigIndex - cert->srcIdx;
-            cert->extensionsIdx = cert->srcIdx;   /* for potential later use */
-
-            if ((ret = DecodeCertExtensions(cert)) < 0) {
-                if (ret == ASN_CRIT_EXT_E)
-                    criticalExt = ret;
-                else
-                    return ret;
-            }
-
-            /* advance past extensions */
-            cert->srcIdx = cert->sigIndex;
-        }
-
-        if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
-                             oidSigType, cert->maxIdx)) < 0)
-            return ret;
-
-        if ((ret = GetSignature(cert)) < 0)
-            return ret;
-
-        if (confirmOID != cert->signatureOID)
-            return ASN_SIG_OID_E;
-
-    #ifndef NO_SKID
-        if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL &&
-                                                        cert->pubKeySize > 0) {
-        #ifdef NO_SHA
-            ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize,
-                                                            cert->extSubjKeyId);
-        #else
-            ret = wc_ShaHash(cert->publicKey, cert->pubKeySize,
-                                                            cert->extSubjKeyId);
-        #endif /* NO_SHA */
-            if (ret != 0)
-                return ret;
-        }
-    #endif /* !NO_SKID */
-
-        if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) {
-            cert->ca = NULL;
-    #ifndef NO_SKID
-            if (cert->extAuthKeyIdSet)
-                cert->ca = GetCA(cm, cert->extAuthKeyId);
-            if (cert->ca == NULL)
-                cert->ca = GetCAByName(cm, cert->issuerHash);
-
-            /* OCSP Only: alt lookup using subject and pub key w/o sig check */
-        #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY
-            if (cert->ca == NULL && verify == VERIFY_OCSP) {
-                cert->ca = GetCABySubjectAndPubKey(cert, cm);
-                if (cert->ca) {
-                    ret = 0; /* success */
-                    goto exit_pcr;
-                }
-            }
-        #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
-
-            /* alt lookup using subject and public key */
-        #ifdef WOLFSSL_ALT_CERT_CHAINS
-            if (cert->ca == NULL)
-                cert->ca = GetCABySubjectAndPubKey(cert, cm);
-        #endif
-    #else
-            cert->ca = GetCA(cm, cert->issuerHash);
-            if (XMEMCMP(cert->issuerHash, cert->subjectHash, KEYID_SIZE) == 0)
-                selfSigned = 1;
-    #endif /* !NO_SKID */
-
-            WOLFSSL_MSG("About to verify certificate signature");
-            if (cert->ca) {
-                if (cert->isCA && cert->ca->pathLengthSet) {
-                    if (selfSigned) {
-                        if (cert->ca->pathLength != 0) {
-                           WOLFSSL_MSG("Root CA with path length > 0");
-                           return ASN_PATHLEN_INV_E;
-                        }
-                    }
-                    else {
-                        if (cert->ca->pathLength == 0) {
-                            WOLFSSL_MSG("CA with path length 0 signing a CA");
-                            return ASN_PATHLEN_INV_E;
-                        }
-                        else if (cert->pathLength >= cert->ca->pathLength) {
-
-                            WOLFSSL_MSG("CA signing CA with longer path length");
-                            return ASN_PATHLEN_INV_E;
-                        }
-                    }
-                }
-
-        #ifdef HAVE_OCSP
-                /* Need the CA's public key hash for OCSP */
-            #ifdef NO_SHA
-                ret = wc_Sha256Hash(cert->ca->publicKey, cert->ca->pubKeySize,
-                                                           cert->issuerKeyHash);
-            #else
-                ret = wc_ShaHash(cert->ca->publicKey, cert->ca->pubKeySize,
-                                                           cert->issuerKeyHash);
-            #endif /* NO_SHA */
-                if (ret != 0)
-                    return ret;
-        #endif /* HAVE_OCSP */
-            }
-        }
-    }
-
-    if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) {
-        if (cert->ca) {
-            if (verify == VERIFY || verify == VERIFY_OCSP) {
-                /* try to confirm/verify signature */
-                if ((ret = ConfirmSignature(&cert->sigCtx,
-                        cert->source + cert->certBegin,
-                        cert->sigIndex - cert->certBegin,
-                        cert->ca->publicKey, cert->ca->pubKeySize,
-                        cert->ca->keyOID, cert->signature,
-                        cert->sigLength, cert->signatureOID)) != 0) {
-                    if (ret != WC_PENDING_E) {
-                        WOLFSSL_MSG("Confirm signature failed");
-                    }
-                    return ret;
-                }
-            #ifndef IGNORE_NAME_CONSTRAINTS
-                /* check that this cert's name is permitted by the signer's
-                 * name constraints */
-                if (!ConfirmNameConstraints(cert->ca, cert)) {
-                    WOLFSSL_MSG("Confirm name constraint failed");
-                    return ASN_NAME_INVALID_E;
-                }
-            #endif /* IGNORE_NAME_CONSTRAINTS */
-            }
-        }
-        else {
-            /* no signer */
-            WOLFSSL_MSG("No CA signer to verify with");
-            return ASN_NO_SIGNER_E;
-        }
-    }
-
-#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
-exit_pcr:
-#endif
-
-    if (badDate != 0)
-        return badDate;
-
-    if (criticalExt != 0)
-        return criticalExt;
-
-    return ret;
-}
-
-/* Create and init an new signer */
-Signer* MakeSigner(void* heap)
-{
-    Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
-                                       DYNAMIC_TYPE_SIGNER);
-    if (signer) {
-        signer->pubKeySize = 0;
-        signer->keyOID     = 0;
-        signer->publicKey  = NULL;
-        signer->nameLen    = 0;
-        signer->name       = NULL;
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        signer->permittedNames = NULL;
-        signer->excludedNames = NULL;
-    #endif /* IGNORE_NAME_CONSTRAINTS */
-        signer->pathLengthSet = 0;
-        signer->pathLength = 0;
-    #ifdef WOLFSSL_SIGNER_DER_CERT
-        signer->derCert    = NULL;
-    #endif
-        signer->next       = NULL;
-    }
-    (void)heap;
-
-    return signer;
-}
-
-
-/* Free an individual signer */
-void FreeSigner(Signer* signer, void* heap)
-{
-    XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
-    XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-#ifndef IGNORE_NAME_CONSTRAINTS
-    if (signer->permittedNames)
-        FreeNameSubtrees(signer->permittedNames, heap);
-    if (signer->excludedNames)
-        FreeNameSubtrees(signer->excludedNames, heap);
-#endif
-#ifdef WOLFSSL_SIGNER_DER_CERT
-    FreeDer(&signer->derCert);
-#endif
-    XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
-
-    (void)heap;
-}
-
-
-/* Free the whole singer table with number of rows */
-void FreeSignerTable(Signer** table, int rows, void* heap)
-{
-    int i;
-
-    for (i = 0; i < rows; i++) {
-        Signer* signer = table[i];
-        while (signer) {
-            Signer* next = signer->next;
-            FreeSigner(signer, heap);
-            signer = next;
-        }
-        table[i] = NULL;
-    }
-}
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* Free an individual trusted peer cert */
-void FreeTrustedPeer(TrustedPeerCert* tp, void* heap)
-{
-    if (tp == NULL) {
-        return;
-    }
-
-    if (tp->name) {
-        XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
-    }
-
-    if (tp->sig) {
-        XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE);
-    }
-#ifndef IGNORE_NAME_CONSTRAINTS
-    if (tp->permittedNames)
-        FreeNameSubtrees(tp->permittedNames, heap);
-    if (tp->excludedNames)
-        FreeNameSubtrees(tp->excludedNames, heap);
-#endif
-    XFREE(tp, heap, DYNAMIC_TYPE_CERT);
-
-    (void)heap;
-}
-
-/* Free the whole Trusted Peer linked list */
-void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap)
-{
-    int i;
-
-    for (i = 0; i < rows; i++) {
-        TrustedPeerCert* tp = table[i];
-        while (tp) {
-            TrustedPeerCert* next = tp->next;
-            FreeTrustedPeer(tp, heap);
-            tp = next;
-        }
-        table[i] = NULL;
-    }
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
-{
-    int i = 0;
-
-    if (output == NULL)
-        return BAD_FUNC_ARG;
-
-    if (header) {
-        output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
-        output[i++] = 3;
-    }
-    output[i++] = ASN_INTEGER;
-    output[i++] = 0x01;
-    output[i++] = (byte)version;
-
-    return i;
-}
-
-
-WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
-    int maxSnSz)
-{
-    int i = 0;
-    int snSzInt = (int)snSz;
-
-    if (sn == NULL || output == NULL || snSzInt < 0)
-        return BAD_FUNC_ARG;
-
-    /* remove leading zeros */
-    while (snSzInt > 0 && sn[0] == 0) {
-        snSzInt--;
-        sn++;
-    }
-
-    /* truncate if input is too long */
-    if (snSzInt > maxSnSz)
-        snSzInt = maxSnSz;
-
-    /* encode ASN Integer, with length and value */
-    output[i++] = ASN_INTEGER;
-
-    /* handle MSB, to make sure value is positive */
-    if (sn[0] & 0x80) {
-        /* make room for zero pad */
-        if (snSzInt > maxSnSz-1)
-            snSzInt = maxSnSz-1;
-
-        /* add zero pad */
-        i += SetLength(snSzInt+1, &output[i]);
-        output[i++] = 0x00;
-        XMEMCPY(&output[i], sn, snSzInt);
-    }
-    else {
-        i += SetLength(snSzInt, &output[i]);
-        XMEMCPY(&output[i], sn, snSzInt);
-    }
-
-    /* compute final length */
-    i += snSzInt;
-
-    return i;
-}
-
-WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx,
-    byte* serial, int* serialSz, word32 maxIdx)
-{
-    int result = 0;
-    int ret;
-
-    WOLFSSL_ENTER("GetSerialNumber");
-
-    if (serial == NULL || input == NULL || serialSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* First byte is ASN type */
-    if ((*inOutIdx+1) > maxIdx) {
-        WOLFSSL_MSG("Bad idx first");
-        return BUFFER_E;
-    }
-
-    ret = GetASNInt(input, inOutIdx, serialSz, maxIdx);
-    if (ret != 0)
-        return ret;
-
-    if (*serialSz > EXTERNAL_SERIAL_SIZE) {
-        WOLFSSL_MSG("Serial size bad");
-        return ASN_PARSE_E;
-    }
-
-    /* return serial */
-    XMEMCPY(serial, &input[*inOutIdx], *serialSz);
-    *inOutIdx += *serialSz;
-
-    return result;
-}
-
-
-int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
-{
-    int ret = BAD_FUNC_ARG;
-    if (pDer) {
-        int dynType = 0;
-        DerBuffer* der;
-
-        /* Determine dynamic type */
-        switch (type) {
-            case CA_TYPE:   dynType = DYNAMIC_TYPE_CA;   break;
-            case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
-            case CRL_TYPE:  dynType = DYNAMIC_TYPE_CRL;  break;
-            case DSA_TYPE:  dynType = DYNAMIC_TYPE_DSA;  break;
-            case ECC_TYPE:  dynType = DYNAMIC_TYPE_ECC;  break;
-            case RSA_TYPE:  dynType = DYNAMIC_TYPE_RSA;  break;
-            default:        dynType = DYNAMIC_TYPE_KEY;  break;
-        }
-
-        /* Setup new buffer */
-        *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
-        if (*pDer == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
-
-        der = *pDer;
-        der->type = type;
-        der->dynType = dynType; /* Cache this for FreeDer */
-        der->heap = heap;
-        der->buffer = (byte*)der + sizeof(DerBuffer);
-        der->length = length;
-        ret = 0; /* Success */
-    }
-    return ret;
-}
-
-void FreeDer(DerBuffer** pDer)
-{
-    if (pDer && *pDer)
-    {
-        DerBuffer* der = (DerBuffer*)*pDer;
-
-        /* ForceZero private keys */
-        if (der->type == PRIVATEKEY_TYPE) {
-            ForceZero(der->buffer, der->length);
-        }
-        der->buffer = NULL;
-        der->length = 0;
-        XFREE(der, der->heap, der->dynType);
-
-        *pDer = NULL;
-    }
-}
-
-
-#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)
-
-const char* const BEGIN_CERT           = "-----BEGIN CERTIFICATE-----";
-const char* const END_CERT             = "-----END CERTIFICATE-----";
-#ifdef WOLFSSL_CERT_REQ
-    const char* const BEGIN_CERT_REQ   = "-----BEGIN CERTIFICATE REQUEST-----";
-    const char* const END_CERT_REQ     = "-----END CERTIFICATE REQUEST-----";
-#endif
-#ifndef NO_DH
-    const char* const BEGIN_DH_PARAM   = "-----BEGIN DH PARAMETERS-----";
-    const char* const END_DH_PARAM     = "-----END DH PARAMETERS-----";
-#endif
-#ifndef NO_DSA
-    const char* const BEGIN_DSA_PARAM  = "-----BEGIN DSA PARAMETERS-----";
-    const char* const END_DSA_PARAM    = "-----END DSA PARAMETERS-----";
-#endif
-const char* const BEGIN_X509_CRL       = "-----BEGIN X509 CRL-----";
-const char* const END_X509_CRL         = "-----END X509 CRL-----";
-const char* const BEGIN_RSA_PRIV       = "-----BEGIN RSA PRIVATE KEY-----";
-const char* const END_RSA_PRIV         = "-----END RSA PRIVATE KEY-----";
-const char* const BEGIN_PRIV_KEY       = "-----BEGIN PRIVATE KEY-----";
-const char* const END_PRIV_KEY         = "-----END PRIVATE KEY-----";
-const char* const BEGIN_ENC_PRIV_KEY   = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
-const char* const END_ENC_PRIV_KEY     = "-----END ENCRYPTED PRIVATE KEY-----";
-#ifdef HAVE_ECC
-    const char* const BEGIN_EC_PRIV    = "-----BEGIN EC PRIVATE KEY-----";
-    const char* const END_EC_PRIV      = "-----END EC PRIVATE KEY-----";
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_DSA)
-    const char* const BEGIN_DSA_PRIV   = "-----BEGIN DSA PRIVATE KEY-----";
-    const char* const END_DSA_PRIV     = "-----END DSA PRIVATE KEY-----";
-#endif
-const char* const BEGIN_PUB_KEY        = "-----BEGIN PUBLIC KEY-----";
-const char* const END_PUB_KEY          = "-----END PUBLIC KEY-----";
-#ifdef HAVE_ED25519
-    const char* const BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----";
-    const char* const END_EDDSA_PRIV   = "-----END EDDSA PRIVATE KEY-----";
-#endif
-#ifdef HAVE_CRL
-    const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----";
-    const char* const END_CRL   = "-----END X509 CRL-----";
-#endif
-
-
-
-int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
-{
-    int ret = BAD_FUNC_ARG;
-
-    switch (type) {
-        case CA_TYPE:       /* same as below */
-        case TRUSTED_PEER_TYPE:
-        case CERT_TYPE:
-            if (header) *header = BEGIN_CERT;
-            if (footer) *footer = END_CERT;
-            ret = 0;
-            break;
-
-        case CRL_TYPE:
-            if (header) *header = BEGIN_X509_CRL;
-            if (footer) *footer = END_X509_CRL;
-            ret = 0;
-            break;
-    #ifndef NO_DH
-        case DH_PARAM_TYPE:
-            if (header) *header = BEGIN_DH_PARAM;
-            if (footer) *footer = END_DH_PARAM;
-            ret = 0;
-            break;
-    #endif
-    #ifndef NO_DSA
-        case DSA_PARAM_TYPE:
-            if (header) *header = BEGIN_DSA_PARAM;
-            if (footer) *footer = END_DSA_PARAM;
-            ret = 0;
-            break;
-    #endif
-    #ifdef WOLFSSL_CERT_REQ
-        case CERTREQ_TYPE:
-            if (header) *header = BEGIN_CERT_REQ;
-            if (footer) *footer = END_CERT_REQ;
-            ret = 0;
-            break;
-    #endif
-    #ifndef NO_DSA
-        case DSA_TYPE:
-        case DSA_PRIVATEKEY_TYPE:
-            if (header) *header = BEGIN_DSA_PRIV;
-            if (footer) *footer = END_DSA_PRIV;
-            ret = 0;
-            break;
-    #endif
-    #ifdef HAVE_ECC
-        case ECC_TYPE:
-        case ECC_PRIVATEKEY_TYPE:
-            if (header) *header = BEGIN_EC_PRIV;
-            if (footer) *footer = END_EC_PRIV;
-            ret = 0;
-            break;
-    #endif
-        case RSA_TYPE:
-        case PRIVATEKEY_TYPE:
-            if (header) *header = BEGIN_RSA_PRIV;
-            if (footer) *footer = END_RSA_PRIV;
-            ret = 0;
-            break;
-    #ifdef HAVE_ED25519
-        case ED25519_TYPE:
-        case EDDSA_PRIVATEKEY_TYPE:
-            if (header) *header = BEGIN_EDDSA_PRIV;
-            if (footer) *footer = END_EDDSA_PRIV;
-            ret = 0;
-            break;
-    #endif
-        case PUBLICKEY_TYPE:
-            if (header) *header = BEGIN_PUB_KEY;
-            if (footer) *footer = END_PUB_KEY;
-            ret = 0;
-            break;
-        default:
-            break;
-    }
-    return ret;
-}
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-
-static const char* const kProcTypeHeader = "Proc-Type";
-static const char* const kDecInfoHeader = "DEK-Info";
-
-#ifdef WOLFSSL_PEM_TO_DER
-#ifndef NO_DES3
-    static const char* const kEncTypeDes = "DES-CBC";
-    static const char* const kEncTypeDes3 = "DES-EDE3-CBC";
-#endif
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
-    static const char* const kEncTypeAesCbc128 = "AES-128-CBC";
-#endif
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
-    static const char* const kEncTypeAesCbc192 = "AES-192-CBC";
-#endif
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
-    static const char* const kEncTypeAesCbc256 = "AES-256-CBC";
-#endif
-
-int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo)
-{
-    int ret = 0;
-
-    if (info == NULL || cipherInfo == NULL)
-        return BAD_FUNC_ARG;
-
-    /* determine cipher information */
-#ifndef NO_DES3
-    if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) {
-        info->cipherType = WC_CIPHER_DES;
-        info->keySz = DES_KEY_SIZE;
-        if (info->ivSz == 0) info->ivSz  = DES_IV_SIZE;
-    }
-    else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) {
-        info->cipherType = WC_CIPHER_DES3;
-        info->keySz = DES3_KEY_SIZE;
-        if (info->ivSz == 0) info->ivSz  = DES_IV_SIZE;
-    }
-    else
-#endif /* !NO_DES3 */
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
-    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) {
-        info->cipherType = WC_CIPHER_AES_CBC;
-        info->keySz = AES_128_KEY_SIZE;
-        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
-    }
-    else
-#endif
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
-    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) {
-        info->cipherType = WC_CIPHER_AES_CBC;
-        info->keySz = AES_192_KEY_SIZE;
-        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
-    }
-    else
-#endif
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
-    if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) {
-        info->cipherType = WC_CIPHER_AES_CBC;
-        info->keySz = AES_256_KEY_SIZE;
-        if (info->ivSz == 0) info->ivSz  = AES_IV_SIZE;
-    }
-    else
-#endif
-    {
-        ret = NOT_COMPILED_IN;
-    }
-    return ret;
-}
-
-static int wc_EncryptedInfoParse(EncryptedInfo* info,
-    char** pBuffer, size_t bufSz)
-{
-    int err = 0;
-    char*  bufferStart;
-    char*  bufferEnd;
-    char*  line;
-    word32 lineSz;
-    char*  finish;
-    word32 finishSz;
-    char*  start = NULL;
-    word32 startSz;
-    char*  newline = NULL;
-
-    if (info == NULL || pBuffer == NULL || bufSz == 0)
-        return BAD_FUNC_ARG;
-
-    bufferStart = *pBuffer;
-    bufferEnd = bufferStart + bufSz;
-
-    /* find encrypted info marker */
-    line = XSTRNSTR(bufferStart, kProcTypeHeader,
-                    min((word32)bufSz, PEM_LINE_LEN));
-    if (line != NULL) {
-        if (line >= bufferEnd) {
-            return BUFFER_E;
-        }
-
-        lineSz = (word32)(bufferEnd - line);
-
-        /* find DEC-Info marker */
-        start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN));
-
-        if (start == NULL)
-            return BUFFER_E;
-
-        /* skip dec-info and ": " */
-        start += XSTRLEN(kDecInfoHeader);
-        if (start >= bufferEnd)
-            return BUFFER_E;
-
-        if (start[0] == ':') {
-            start++;
-            if (start >= bufferEnd)
-                return BUFFER_E;
-        }
-        if (start[0] == ' ')
-            start++;
-
-        startSz = (word32)(bufferEnd - start);
-        finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
-
-        if ((start != NULL) && (finish != NULL) && (start < finish)) {
-            if (finish >= bufferEnd) {
-                return BUFFER_E;
-            }
-
-            finishSz = (word32)(bufferEnd - finish);
-            newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
-
-            /* get cipher name */
-            if (NAME_SZ < (finish - start)) /* buffer size of info->name */
-                return BUFFER_E;
-            if (XMEMCPY(info->name, start, finish - start) == NULL)
-                return BUFFER_E;
-            info->name[finish - start] = '\0'; /* null term */
-
-            /* get IV */
-            if (finishSz < sizeof(info->iv) + 1)
-                return BUFFER_E;
-            if (XMEMCPY(info->iv, finish + 1, sizeof(info->iv)) == NULL)
-                return BUFFER_E;
-
-            if (newline == NULL)
-                newline = XSTRNSTR(finish, "\n", min(finishSz,
-                                                     PEM_LINE_LEN));
-            if ((newline != NULL) && (newline > finish)) {
-                info->ivSz = (word32)(newline - (finish + 1));
-                info->set = 1;
-            }
-            else
-                return BUFFER_E;
-        }
-        else
-            return BUFFER_E;
-
-        /* eat blank line */
-        while (newline < bufferEnd &&
-                (*newline == '\r' || *newline == '\n')) {
-            newline++;
-        }
-
-        /* return new headerEnd */
-        if (pBuffer)
-            *pBuffer = newline;
-
-        /* populate info */
-        err = wc_EncryptedInfoGet(info, info->name);
-    }
-
-    return err;
-}
-#endif /* WOLFSSL_PEM_TO_DER */
-
-#ifdef WOLFSSL_DER_TO_PEM
-static int wc_EncryptedInfoAppend(char* dest, char* cipherInfo)
-{
-    if (cipherInfo != NULL) {
-        size_t cipherInfoStrLen = XSTRLEN(cipherInfo);
-        if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3))
-            cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3);
-
-        XSTRNCAT(dest, kProcTypeHeader, 9);
-        XSTRNCAT(dest, ": 4,ENCRYPTED\n", 14);
-        XSTRNCAT(dest, kDecInfoHeader, 8);
-        XSTRNCAT(dest, ": ", 2);
-        XSTRNCAT(dest, cipherInfo, cipherInfoStrLen);
-        XSTRNCAT(dest, "\n\n", 3);
-    }
-    return 0;
-}
-#endif /* WOLFSSL_DER_TO_PEM */
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-#ifdef WOLFSSL_DER_TO_PEM
-
-/* Used for compatibility API */
-int wc_DerToPem(const byte* der, word32 derSz,
-                byte* output, word32 outSz, int type)
-{
-    return wc_DerToPemEx(der, derSz, output, outSz, NULL, type);
-}
-
-/* convert der buffer to pem into output, can't do inplace, der and output
-   need to be different */
-int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
-             byte *cipher_info, int type)
-{
-    const char* headerStr = NULL;
-    const char* footerStr = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    char* header = NULL;
-    char* footer = NULL;
-#else
-    char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE];
-    char footer[MAX_X509_HEADER_SZ];
-#endif
-    int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE;
-    int footerLen = MAX_X509_HEADER_SZ;
-    int i;
-    int err;
-    int outLen;   /* return length or error */
-
-    (void)cipher_info;
-
-    if (der == output)      /* no in place conversion */
-        return BAD_FUNC_ARG;
-
-    err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr);
-    if (err != 0)
-        return err;
-
-#ifdef WOLFSSL_SMALL_STACK
-    header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (header == NULL)
-        return MEMORY_E;
-
-    footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (footer == NULL) {
-        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    /* null term and leave room for newline */
-    header[--headerLen] = '\0'; header[--headerLen] = '\0';
-    footer[--footerLen] = '\0'; footer[--footerLen] = '\0';
-
-    /* build header and footer based on type */
-    XSTRNCPY(header, headerStr, headerLen);
-    XSTRNCPY(footer, footerStr, footerLen);
-
-    /* add new line to end */
-    XSTRNCAT(header, "\n", 2);
-    XSTRNCAT(footer, "\n", 2);
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    err = wc_EncryptedInfoAppend(header, (char*)cipher_info);
-    if (err != 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return err;
-    }
-#endif
-
-    headerLen = (int)XSTRLEN(header);
-    footerLen = (int)XSTRLEN(footer);
-
-    /* if null output and 0 size passed in then return size needed */
-    if (!output && outSz == 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        outLen = 0;
-        if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen))
-                != LENGTH_ONLY_E) {
-            return err;
-        }
-        return headerLen + footerLen + outLen;
-    }
-
-    if (!der || !output) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BAD_FUNC_ARG;
-    }
-
-    /* don't even try if outSz too short */
-    if (outSz < headerLen + footerLen + derSz) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BAD_FUNC_ARG;
-    }
-
-    /* header */
-    XMEMCPY(output, header, headerLen);
-    i = headerLen;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    /* body */
-    outLen = outSz - (headerLen + footerLen);  /* input to Base64_Encode */
-    if ( (err = Base64_Encode(der, derSz, output + i, (word32*)&outLen)) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return err;
-    }
-    i += outLen;
-
-    /* footer */
-    if ( (i + footerLen) > (int)outSz) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BAD_FUNC_ARG;
-    }
-    XMEMCPY(output + i, footer, footerLen);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return outLen + headerLen + footerLen;
-}
-
-#endif /* WOLFSSL_DER_TO_PEM */
-
-#ifdef WOLFSSL_PEM_TO_DER
-
-/* Remove PEM header/footer, convert to ASN1, store any encrypted data
-   info->consumed tracks of PEM bytes consumed in case multiple parts */
-int PemToDer(const unsigned char* buff, long longSz, int type,
-              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
-{
-    const char* header      = NULL;
-    const char* footer      = NULL;
-    char*       headerEnd;
-    char*       footerEnd;
-    char*       consumedEnd;
-    char*       bufferEnd   = (char*)(buff + longSz);
-    long        neededSz;
-    int         ret         = 0;
-    int         sz          = (int)longSz;
-    int         encrypted_key = 0;
-    DerBuffer*  der;
-
-    WOLFSSL_ENTER("PemToDer");
-
-    /* get PEM header and footer based on type */
-    ret = wc_PemGetHeaderFooter(type, &header, &footer);
-    if (ret != 0)
-        return ret;
-
-    /* map header if not found for type */
-    for (;;) {
-        headerEnd = XSTRNSTR((char*)buff, header, sz);
-
-        if (headerEnd || type != PRIVATEKEY_TYPE) {
-            break;
-        } else
-        if (header == BEGIN_RSA_PRIV) {
-            header =  BEGIN_PRIV_KEY;       footer = END_PRIV_KEY;
-        } else
-        if (header == BEGIN_PRIV_KEY) {
-            header =  BEGIN_ENC_PRIV_KEY;   footer = END_ENC_PRIV_KEY;
-        } else
-#ifdef HAVE_ECC
-        if (header == BEGIN_ENC_PRIV_KEY) {
-            header =  BEGIN_EC_PRIV;        footer = END_EC_PRIV;
-        } else
-        if (header == BEGIN_EC_PRIV) {
-            header =  BEGIN_DSA_PRIV;       footer = END_DSA_PRIV;
-        } else
-#endif
-#ifdef HAVE_ED25519
-    #ifdef HAVE_ECC
-        if (header == BEGIN_DSA_PRIV)
-    #else
-        if (header == BEGIN_ENC_PRIV_KEY)
-    #endif
-        {
-            header =  BEGIN_EDDSA_PRIV;     footer = END_EDDSA_PRIV;
-        } else
-#endif
-#ifdef HAVE_CRL
-        if (type == CRL_TYPE) {
-            header =  BEGIN_CRL;        footer = END_CRL;
-        } else
-#endif
-        {
-            break;
-        }
-    }
-
-    if (!headerEnd) {
-        WOLFSSL_MSG("Couldn't find PEM header");
-        return ASN_NO_PEM_HEADER;
-    }
-
-    headerEnd += XSTRLEN(header);
-
-    if ((headerEnd + 1) >= bufferEnd)
-        return BUFFER_E;
-
-    /* eat end of line */
-    if (headerEnd[0] == '\n')
-        headerEnd++;
-    else if (headerEnd[1] == '\n')
-        headerEnd += 2;
-    else {
-        if (info)
-            info->consumed = (long)(headerEnd+2 - (char*)buff);
-        return BUFFER_E;
-    }
-
-    if (type == PRIVATEKEY_TYPE) {
-        if (eccKey) {
-        #ifdef HAVE_ECC
-            *eccKey = (header == BEGIN_EC_PRIV) ? 1 : 0;
-        #else
-            *eccKey = 0;
-        #endif
-        }
-    }
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    if (info) {
-        ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd);
-        if (ret < 0)
-            return ret;
-        if (info->set)
-            encrypted_key = 1;
-    }
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-    /* find footer */
-    footerEnd = XSTRNSTR((char*)buff, footer, sz);
-    if (!footerEnd) {
-        if (info)
-            info->consumed = longSz; /* No more certs if no footer */
-        return BUFFER_E;
-    }
-
-    consumedEnd = footerEnd + XSTRLEN(footer);
-
-    if (consumedEnd < bufferEnd) {  /* handle no end of line on last line */
-        /* eat end of line */
-        if (consumedEnd[0] == '\n')
-            consumedEnd++;
-        else if ((consumedEnd + 1 < bufferEnd) && consumedEnd[1] == '\n')
-            consumedEnd += 2;
-        else {
-            if (info)
-                info->consumed = (long)(consumedEnd+2 - (char*)buff);
-            return BUFFER_E;
-        }
-    }
-
-    if (info)
-        info->consumed = (long)(consumedEnd - (char*)buff);
-
-    /* set up der buffer */
-    neededSz = (long)(footerEnd - headerEnd);
-    if (neededSz > sz || neededSz <= 0)
-        return BUFFER_E;
-
-    ret = AllocDer(pDer, (word32)neededSz, type, heap);
-    if (ret < 0) {
-        return ret;
-    }
-    der = *pDer;
-
-    if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
-                      der->buffer, &der->length) < 0)
-        return BUFFER_E;
-
-    if (header == BEGIN_PRIV_KEY && !encrypted_key) {
-        /* pkcs8 key, convert and adjust length */
-        if ((ret = ToTraditional(der->buffer, der->length)) < 0)
-            return ret;
-
-        der->length = ret;
-        return 0;
-    }
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
-        int   passwordSz = NAME_SZ;
-    #ifdef WOLFSSL_SMALL_STACK
-        char* password = NULL;
-    #else
-        char  password[NAME_SZ];
-    #endif
-
-        if (!info || !info->passwd_cb) {
-            WOLFSSL_MSG("No password callback set");
-            return NO_PASSWORD;
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
-        if (password == NULL)
-            return MEMORY_E;
-    #endif
-
-        /* get password */
-        ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
-            info->passwd_userdata);
-        if (ret >= 0) {
-            passwordSz = ret;
-
-            /* convert and adjust length */
-            if (header == BEGIN_ENC_PRIV_KEY) {
-            #ifndef NO_PWDBASED
-                ret = ToTraditionalEnc(der->buffer, der->length,
-                                       password, passwordSz);
-
-                if (ret >= 0) {
-                    der->length = ret;
-                }
-            #else
-                ret = NOT_COMPILED_IN;
-            #endif
-            }
-            /* decrypt the key */
-            else {
-                ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
-                    (byte*)password, passwordSz, WC_MD5);
-            }
-            ForceZero(password, passwordSz);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(password, heap, DYNAMIC_TYPE_STRING);
-    #endif
-    }
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-    return ret;
-}
-
-int wc_PemToDer(const unsigned char* buff, long longSz, int type,
-              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
-{
-    return PemToDer(buff, longSz, type, pDer, heap, info, eccKey);
-}
-
-
-/* our KeyPemToDer password callback, password in userData */
-static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
-{
-    (void)rw;
-
-    if (userdata == NULL)
-        return 0;
-
-    XSTRNCPY(passwd, (char*)userdata, sz);
-    return min((word32)sz, (word32)XSTRLEN((char*)userdata));
-}
-
-/* Return bytes written to buff or < 0 for error */
-int wc_KeyPemToDer(const unsigned char* pem, int pemSz,
-                        unsigned char* buff, int buffSz, const char* pass)
-{
-    int            eccKey = 0;
-    int            ret;
-    DerBuffer*     der = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-    EncryptedInfo* info = NULL;
-#else
-    EncryptedInfo  info[1];
-#endif
-
-    WOLFSSL_ENTER("wc_KeyPemToDer");
-
-    if (pem == NULL || buff == NULL || buffSz <= 0) {
-        WOLFSSL_MSG("Bad pem der args");
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
-                                   DYNAMIC_TYPE_ENCRYPTEDINFO);
-    if (info == NULL)
-        return MEMORY_E;
-#endif
-
-    XMEMSET(info, 0, sizeof(EncryptedInfo));
-    info->passwd_cb = OurPasswordCb;
-    info->passwd_userdata = (void*)pass;
-
-    ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
-
-    if (ret < 0) {
-        WOLFSSL_MSG("Bad Pem To Der");
-    }
-    else {
-        if (der->length <= (word32)buffSz) {
-            XMEMCPY(buff, der->buffer, der->length);
-            ret = der->length;
-        }
-        else {
-            WOLFSSL_MSG("Bad der length");
-            ret = BAD_FUNC_ARG;
-        }
-    }
-
-    FreeDer(&der);
-    return ret;
-}
-
-
-/* Return bytes written to buff or < 0 for error */
-int wc_CertPemToDer(const unsigned char* pem, int pemSz,
-                        unsigned char* buff, int buffSz, int type)
-{
-    int            eccKey = 0;
-    int            ret;
-    DerBuffer*     der = NULL;
-
-    WOLFSSL_ENTER("wc_CertPemToDer");
-
-    if (pem == NULL || buff == NULL || buffSz <= 0) {
-        WOLFSSL_MSG("Bad pem der args");
-        return BAD_FUNC_ARG;
-    }
-
-    if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
-        WOLFSSL_MSG("Bad cert type");
-        return BAD_FUNC_ARG;
-    }
-
-
-    ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey);
-    if (ret < 0) {
-        WOLFSSL_MSG("Bad Pem To Der");
-    }
-    else {
-        if (der->length <= (word32)buffSz) {
-            XMEMCPY(buff, der->buffer, der->length);
-            ret = der->length;
-        }
-        else {
-            WOLFSSL_MSG("Bad der length");
-            ret = BAD_FUNC_ARG;
-        }
-    }
-
-    FreeDer(&der);
-    return ret;
-}
-
-#endif /* WOLFSSL_PEM_TO_DER */
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-
-
-#ifdef WOLFSSL_PEM_TO_DER
-#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
-/* Return bytes written to buff or < 0 for error */
-int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz,
-                           unsigned char* buff, int buffSz)
-{
-    int ret;
-    DerBuffer* der = NULL;
-
-    WOLFSSL_ENTER("wc_PubKeyPemToDer");
-
-    if (pem == NULL || buff == NULL || buffSz <= 0) {
-        WOLFSSL_MSG("Bad pem der args");
-        return BAD_FUNC_ARG;
-    }
-
-    ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL);
-    if (ret < 0) {
-        WOLFSSL_MSG("Bad Pem To Der");
-    }
-    else {
-        if (der->length <= (word32)buffSz) {
-            XMEMCPY(buff, der->buffer, der->length);
-            ret = der->length;
-        }
-        else {
-            WOLFSSL_MSG("Bad der length");
-            ret = BAD_FUNC_ARG;
-        }
-    }
-
-    FreeDer(&der);
-    return ret;
-}
-#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
-#endif /* WOLFSSL_PEM_TO_DER */
-
-#ifndef NO_FILESYSTEM
-
-#ifdef WOLFSSL_CERT_GEN
-/* load pem cert from file into der buffer, return der size or error */
-int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force XMALLOC */
-#else
-    byte   staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte*  fileBuf = staticBuffer;
-    int    dynamic = 0;
-    int    ret     = 0;
-    long   sz      = 0;
-    XFILE  file    = XFOPEN(fileName, "rb");
-    DerBuffer* converted = NULL;
-
-    WOLFSSL_ENTER("wc_PemCertToDer");
-
-    if (file == XBADFILE) {
-        ret = BUFFER_E;
-    }
-    else {
-        XFSEEK(file, 0, XSEEK_END);
-        sz = XFTELL(file);
-        XREWIND(file);
-
-        if (sz <= 0) {
-            ret = BUFFER_E;
-        }
-        else if (sz > (long)sizeof(staticBuffer)) {
-        #ifdef WOLFSSL_STATIC_MEMORY
-            WOLFSSL_MSG("File was larger then static buffer");
-            return MEMORY_E;
-        #endif
-            fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
-            if (fileBuf == NULL)
-                ret = MEMORY_E;
-            else
-                dynamic = 1;
-        }
-
-        if (ret == 0) {
-            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
-                ret = BUFFER_E;
-            }
-        #ifdef WOLFSSL_PEM_TO_DER
-            else {
-                ret = PemToDer(fileBuf, sz, CA_TYPE, &converted,  0, NULL,NULL);
-            }
-        #endif
-
-            if (ret == 0) {
-                if (converted->length < (word32)derSz) {
-                    XMEMCPY(derBuf, converted->buffer, converted->length);
-                    ret = converted->length;
-                }
-                else
-                    ret = BUFFER_E;
-            }
-
-            FreeDer(&converted);
-        }
-
-        XFCLOSE(file);
-        if (dynamic)
-            XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
-    }
-
-    return ret;
-}
-#endif /* WOLFSSL_CERT_GEN */
-
-#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
-/* load pem public key from file into der buffer, return der size or error */
-int wc_PemPubKeyToDer(const char* fileName,
-                           unsigned char* derBuf, int derSz)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force XMALLOC */
-#else
-    byte   staticBuffer[FILE_BUFFER_SIZE];
-#endif
-    byte*  fileBuf = staticBuffer;
-    int    dynamic = 0;
-    int    ret     = 0;
-    long   sz      = 0;
-    XFILE  file    = XFOPEN(fileName, "rb");
-    DerBuffer* converted = NULL;
-
-    WOLFSSL_ENTER("wc_PemPubKeyToDer");
-
-    if (file == XBADFILE) {
-        ret = BUFFER_E;
-    }
-    else {
-        XFSEEK(file, 0, XSEEK_END);
-        sz = XFTELL(file);
-        XREWIND(file);
-
-        if (sz <= 0) {
-            ret = BUFFER_E;
-        }
-        else if (sz > (long)sizeof(staticBuffer)) {
-        #ifdef WOLFSSL_STATIC_MEMORY
-            WOLFSSL_MSG("File was larger then static buffer");
-            return MEMORY_E;
-        #endif
-            fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
-            if (fileBuf == NULL)
-                ret = MEMORY_E;
-            else
-                dynamic = 1;
-        }
-        if (ret == 0) {
-            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
-                ret = BUFFER_E;
-            }
-        #ifdef WOLFSSL_PEM_TO_DER
-            else {
-                ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
-                               0, NULL, NULL);
-            }
-        #endif
-
-            if (ret == 0) {
-                if (converted->length < (word32)derSz) {
-                    XMEMCPY(derBuf, converted->buffer, converted->length);
-                    ret = converted->length;
-                }
-                else
-                    ret = BUFFER_E;
-            }
-
-            FreeDer(&converted);
-        }
-
-        XFCLOSE(file);
-        if (dynamic)
-            XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
-    }
-
-    return ret;
-}
-#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
-
-#endif /* !NO_FILESYSTEM */
-
-
-#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
-    ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA)))
-/* USER RSA ifdef portions used instead of refactor in consideration for
-   possible fips build */
-/* Write a public RSA key to output */
-static int SetRsaPublicKey(byte* output, RsaKey* key,
-                           int outLen, int with_header)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    byte* n = NULL;
-    byte* e = NULL;
-#else
-    byte n[MAX_RSA_INT_SZ];
-    byte e[MAX_RSA_E_SZ];
-#endif
-    byte seq[MAX_SEQ_SZ];
-    byte bitString[1 + MAX_LENGTH_SZ + 1];
-    int  nSz;
-    int  eSz;
-    int  seqSz;
-    int  bitStringSz;
-    int  idx;
-
-    if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ)
-        return BAD_FUNC_ARG;
-
-    /* n */
-#ifdef WOLFSSL_SMALL_STACK
-    n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (n == NULL)
-        return MEMORY_E;
-#endif
-
-#ifdef HAVE_USER_RSA
-    nSz = SetASNIntRSA(key->n, n);
-#else
-    nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n);
-#endif
-    if (nSz < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return nSz;
-    }
-
-    /* e */
-#ifdef WOLFSSL_SMALL_STACK
-    e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (e == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return MEMORY_E;
-    }
-#endif
-
-#ifdef HAVE_USER_RSA
-    eSz = SetASNIntRSA(key->e, e);
-#else
-    eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e);
-#endif
-    if (eSz < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return eSz;
-    }
-
-    seqSz  = SetSequence(nSz + eSz, seq);
-
-    /* check output size */
-    if ( (seqSz + nSz + eSz) > outLen) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BUFFER_E;
-    }
-
-    /* headers */
-    if (with_header) {
-        int  algoSz;
-#ifdef WOLFSSL_SMALL_STACK
-        byte* algo = NULL;
-
-        algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (algo == NULL) {
-            XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-#else
-        byte algo[MAX_ALGO_SZ];
-#endif
-        algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0);
-        bitStringSz  = SetBitString(seqSz + nSz + eSz, 0, bitString);
-
-        idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output);
-
-        /* check output size */
-        if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) {
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            #endif
-
-            return BUFFER_E;
-        }
-
-        /* algo */
-        XMEMCPY(output + idx, algo, algoSz);
-        idx += algoSz;
-        /* bit string */
-        XMEMCPY(output + idx, bitString, bitStringSz);
-        idx += bitStringSz;
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-    }
-    else
-        idx = 0;
-
-    /* seq */
-    XMEMCPY(output + idx, seq, seqSz);
-    idx += seqSz;
-    /* n */
-    XMEMCPY(output + idx, n, nSz);
-    idx += nSz;
-    /* e */
-    XMEMCPY(output + idx, e, eSz);
-    idx += eSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(n,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(e,    key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return idx;
-}
-
-int RsaPublicKeyDerSize(RsaKey* key, int with_header)
-{
-    byte* dummy = NULL;
-    byte seq[MAX_SEQ_SZ];
-    byte bitString[1 + MAX_LENGTH_SZ + 1];
-    int  nSz;
-    int  eSz;
-    int  seqSz;
-    int  bitStringSz;
-    int  idx;
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* n */
-    dummy = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (dummy == NULL)
-        return MEMORY_E;
-
-#ifdef HAVE_USER_RSA
-    nSz = SetASNIntRSA(key->n, dummy);
-#else
-    nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, dummy);
-#endif
-    XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (nSz < 0) {
-        return nSz;
-    }
-
-    /* e */
-    dummy = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (dummy == NULL) {
-        XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-
-#ifdef HAVE_USER_RSA
-    eSz = SetASNIntRSA(key->e, dummy);
-#else
-    eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, dummy);
-#endif
-    XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (eSz < 0) {
-        return eSz;
-    }
-
-    seqSz  = SetSequence(nSz + eSz, seq);
-
-    /* headers */
-    if (with_header) {
-        int  algoSz;
-        dummy = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (dummy == NULL)
-            return MEMORY_E;
-
-        algoSz = SetAlgoID(RSAk, dummy, oidKeyType, 0);
-        bitStringSz  = SetBitString(seqSz + nSz + eSz, 0, bitString);
-
-        idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, dummy);
-        XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-        /* algo */
-        idx += algoSz;
-        /* bit string */
-        idx += bitStringSz;
-    }
-    else
-        idx = 0;
-
-    /* seq */
-    idx += seqSz;
-    /* n */
-    idx += nSz;
-    /* e */
-    idx += eSz;
-
-    return idx;
-}
-#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN &&
-                                           !HAVE_USER_RSA))) */
-
-
-#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-
-
-static mp_int* GetRsaInt(RsaKey* key, int idx)
-{
-    if (idx == 0)
-        return &key->n;
-    if (idx == 1)
-        return &key->e;
-    if (idx == 2)
-        return &key->d;
-    if (idx == 3)
-        return &key->p;
-    if (idx == 4)
-        return &key->q;
-    if (idx == 5)
-        return &key->dP;
-    if (idx == 6)
-        return &key->dQ;
-    if (idx == 7)
-        return &key->u;
-
-    return NULL;
-}
-
-
-/* Release Tmp RSA resources */
-static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap)
-{
-    int i;
-
-    (void)heap;
-
-    for (i = 0; i < RSA_INTS; i++)
-        XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
-}
-
-
-/* Convert RsaKey key to DER format, write to output (inLen), return bytes
-   written */
-int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
-{
-    word32 seqSz, verSz, rawLen, intTotalLen = 0;
-    word32 sizes[RSA_INTS];
-    int    i, j, outLen, ret = 0, mpSz;
-
-    byte  seq[MAX_SEQ_SZ];
-    byte  ver[MAX_VERSION_SZ];
-    byte* tmps[RSA_INTS];
-
-    if (!key || !output)
-        return BAD_FUNC_ARG;
-
-    if (key->type != RSA_PRIVATE)
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < RSA_INTS; i++)
-        tmps[i] = NULL;
-
-    /* write all big ints from key to DER tmps */
-    for (i = 0; i < RSA_INTS; i++) {
-        mp_int* keyInt = GetRsaInt(key, i);
-
-        rawLen = mp_unsigned_bin_size(keyInt) + 1;
-        tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
-                                 DYNAMIC_TYPE_RSA);
-        if (tmps[i] == NULL) {
-            ret = MEMORY_E;
-            break;
-        }
-
-        mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]);
-        if (mpSz < 0) {
-            ret = mpSz;
-            break;
-        }
-        intTotalLen += (sizes[i] = mpSz);
-    }
-
-    if (ret != 0) {
-        FreeTmpRsas(tmps, key->heap);
-        return ret;
-    }
-
-    /* make headers */
-    verSz = SetMyVersion(0, ver, FALSE);
-    seqSz = SetSequence(verSz + intTotalLen, seq);
-
-    outLen = seqSz + verSz + intTotalLen;
-    if (outLen > (int)inLen) {
-        FreeTmpRsas(tmps, key->heap);
-        return BAD_FUNC_ARG;
-    }
-
-    /* write to output */
-    XMEMCPY(output, seq, seqSz);
-    j = seqSz;
-    XMEMCPY(output + j, ver, verSz);
-    j += verSz;
-
-    for (i = 0; i < RSA_INTS; i++) {
-        XMEMCPY(output + j, tmps[i], sizes[i]);
-        j += sizes[i];
-    }
-    FreeTmpRsas(tmps, key->heap);
-
-    return outLen;
-}
-#endif
-
-#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-/* Convert Rsa Public key to DER format, write to output (inLen), return bytes
-   written */
-int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen)
-{
-    return SetRsaPublicKey(output, key, inLen, 1);
-}
-
-#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */
-
-
-#ifdef WOLFSSL_CERT_GEN
-
-/* Initialize and Set Certificate defaults:
-   version    = 3 (0x2)
-   serial     = 0
-   sigType    = SHA_WITH_RSA
-   issuer     = blank
-   daysValid  = 500
-   selfSigned = 1 (true) use subject as issuer
-   subject    = blank
-*/
-int wc_InitCert(Cert* cert)
-{
-#ifdef WOLFSSL_MULTI_ATTRIB
-    int i = 0;
-#endif
-    if (cert == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(cert, 0, sizeof(Cert));
-
-    cert->version    = 2;   /* version 3 is hex 2 */
-#ifndef NO_SHA
-    cert->sigType    = CTC_SHAwRSA;
-#elif !defined(NO_SHA256)
-    cert->sigType    = CTC_SHA256wRSA;
-#else
-    cert->sigType    = 0;
-#endif
-    cert->daysValid  = 500;
-    cert->selfSigned = 1;
-    cert->keyType    = RSA_KEY;
-
-    cert->issuer.countryEnc = CTC_PRINTABLE;
-    cert->issuer.stateEnc = CTC_UTF8;
-    cert->issuer.localityEnc = CTC_UTF8;
-    cert->issuer.surEnc = CTC_UTF8;
-    cert->issuer.orgEnc = CTC_UTF8;
-    cert->issuer.unitEnc = CTC_UTF8;
-    cert->issuer.commonNameEnc = CTC_UTF8;
-
-    cert->subject.countryEnc = CTC_PRINTABLE;
-    cert->subject.stateEnc = CTC_UTF8;
-    cert->subject.localityEnc = CTC_UTF8;
-    cert->subject.surEnc = CTC_UTF8;
-    cert->subject.orgEnc = CTC_UTF8;
-    cert->subject.unitEnc = CTC_UTF8;
-    cert->subject.commonNameEnc = CTC_UTF8;
-
-#ifdef WOLFSSL_MULTI_ATTRIB
-    for (i = 0; i < CTC_MAX_ATTRIB; i++) {
-        cert->issuer.name[i].type   = CTC_UTF8;
-        cert->subject.name[i].type  = CTC_UTF8;
-    }
-#endif /* WOLFSSL_MULTI_ATTRIB */
-
-#ifdef WOLFSSL_HEAP_TEST
-    cert->heap = (void*)WOLFSSL_HEAP_TEST;
-#endif
-
-    return 0;
-}
-
-
-/* DER encoded x509 Certificate */
-typedef struct DerCert {
-    byte size[MAX_LENGTH_SZ];          /* length encoded */
-    byte version[MAX_VERSION_SZ];      /* version encoded */
-    byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */
-    byte sigAlgo[MAX_ALGO_SZ];         /* signature algo encoded */
-    byte issuer[ASN_NAME_MAX];         /* issuer  encoded */
-    byte subject[ASN_NAME_MAX];        /* subject encoded */
-    byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2];  /* before and after dates */
-    byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
-    byte ca[MAX_CA_SZ];                /* basic constraint CA true size */
-    byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
-#ifdef WOLFSSL_CERT_EXT
-    byte skid[MAX_KID_SZ];             /* Subject Key Identifier extension */
-    byte akid[MAX_KID_SZ];             /* Authority Key Identifier extension */
-    byte keyUsage[MAX_KEYUSAGE_SZ];    /* Key Usage extension */
-    byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */
-    byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
-#endif
-#ifdef WOLFSSL_CERT_REQ
-    byte attrib[MAX_ATTRIB_SZ];        /* Cert req attributes encoded */
-#endif
-#ifdef WOLFSSL_ALT_NAMES
-    byte altNames[CTC_MAX_ALT_SIZE];   /* Alternative Names encoded */
-#endif
-    int  sizeSz;                       /* encoded size length */
-    int  versionSz;                    /* encoded version length */
-    int  serialSz;                     /* encoded serial length */
-    int  sigAlgoSz;                    /* encoded sig alog length */
-    int  issuerSz;                     /* encoded issuer length */
-    int  subjectSz;                    /* encoded subject length */
-    int  validitySz;                   /* encoded validity length */
-    int  publicKeySz;                  /* encoded public key length */
-    int  caSz;                         /* encoded CA extension length */
-#ifdef WOLFSSL_CERT_EXT
-    int  skidSz;                       /* encoded SKID extension length */
-    int  akidSz;                       /* encoded SKID extension length */
-    int  keyUsageSz;                   /* encoded KeyUsage extension length */
-    int  extKeyUsageSz;                /* encoded ExtendedKeyUsage extension length */
-    int  certPoliciesSz;               /* encoded CertPolicies extension length*/
-#endif
-#ifdef WOLFSSL_ALT_NAMES
-    int  altNamesSz;                   /* encoded AltNames extension length */
-#endif
-    int  extensionsSz;                 /* encoded extensions total length */
-    int  total;                        /* total encoded lengths */
-#ifdef WOLFSSL_CERT_REQ
-    int  attribSz;
-#endif
-} DerCert;
-
-
-#ifdef WOLFSSL_CERT_REQ
-
-/* Write a set header to output */
-static word32 SetUTF8String(word32 len, byte* output)
-{
-    output[0] = ASN_UTF8STRING;
-    return SetLength(len, output + 1) + 1;
-}
-
-#endif /* WOLFSSL_CERT_REQ */
-
-#endif /*WOLFSSL_CERT_GEN */
-
-#if defined(HAVE_ECC)
-
-/* Write a public ECC key to output */
-static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
-{
-    byte bitString[1 + MAX_LENGTH_SZ + 1];
-    int  algoSz;
-    int  curveSz;
-    int  bitStringSz;
-    int  idx;
-    word32 pubSz = ECC_BUFSIZE;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* algo = NULL;
-    byte* curve = NULL;
-    byte* pub = NULL;
-#else
-    byte algo[MAX_ALGO_SZ];
-    byte curve[MAX_ALGO_SZ];
-    byte pub[ECC_BUFSIZE];
-#endif
-    int ret;
-
-#ifdef WOLFSSL_SMALL_STACK
-    pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pub == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_ecc_export_x963(key, pub, &pubSz);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* headers */
-    if (with_header) {
-#ifdef WOLFSSL_SMALL_STACK
-        curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (curve == NULL) {
-            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-#endif
-        curveSz = SetCurve(key, curve);
-        if (curveSz <= 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return curveSz;
-        }
-
-#ifdef WOLFSSL_SMALL_STACK
-        algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (algo == NULL) {
-            XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-#endif
-        algoSz  = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz);
-
-        bitStringSz = SetBitString(pubSz, 0, bitString);
-
-        idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output);
-        /* algo */
-        XMEMCPY(output + idx, algo, algoSz);
-        idx += algoSz;
-       /* curve */
-        XMEMCPY(output + idx, curve, curveSz);
-        idx += curveSz;
-        /* bit string */
-        XMEMCPY(output + idx, bitString, bitStringSz);
-        idx += bitStringSz;
-    }
-    else
-        idx = 0;
-
-    /* pub */
-    XMEMCPY(output + idx, pub, pubSz);
-    idx += pubSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (with_header) {
-        XFREE(algo,  key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return idx;
-}
-
-
-/* returns the size of buffer used, the public ECC key in DER format is stored
-   in output buffer
-   with_AlgCurve is a flag for when to include a header that has the Algorithm
-   and Curve infromation */
-int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
-                                                              int with_AlgCurve)
-{
-    word32 infoSz = 0;
-    word32 keySz  = 0;
-    int ret;
-
-    if (output == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (with_AlgCurve) {
-        /* buffer space for algorithm/curve */
-        infoSz += MAX_SEQ_SZ;
-        infoSz += 2 * MAX_ALGO_SZ;
-
-        /* buffer space for public key sequence */
-        infoSz += MAX_SEQ_SZ;
-        infoSz += TRAILING_ZERO;
-    }
-
-    if ((ret = wc_ecc_export_x963(key, NULL, &keySz)) != LENGTH_ONLY_E) {
-        WOLFSSL_MSG("Error in getting ECC public key size");
-        return ret;
-    }
-
-    if (inLen < keySz + infoSz) {
-        return BUFFER_E;
-    }
-
-    return SetEccPublicKey(output, key, with_AlgCurve);
-}
-#endif /* HAVE_ECC */
-
-#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
-                              defined(WOLFSSL_KEY_GEN))
-
-/* Write a public ECC key to output */
-static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header)
-{
-    byte bitString[1 + MAX_LENGTH_SZ + 1];
-    int  algoSz;
-    int  bitStringSz;
-    int  idx;
-    word32 pubSz = ED25519_PUB_KEY_SIZE;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* algo = NULL;
-    byte* pub = NULL;
-#else
-    byte algo[MAX_ALGO_SZ];
-    byte pub[ED25519_PUB_KEY_SIZE];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pub == NULL)
-        return MEMORY_E;
-#endif
-
-    int ret = wc_ed25519_export_public(key, pub, &pubSz);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* headers */
-    if (with_header) {
-#ifdef WOLFSSL_SMALL_STACK
-        algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (algo == NULL) {
-            XFREE(pub,   key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-#endif
-        algoSz  = SetAlgoID(ED25519k, algo, oidKeyType, 0);
-
-        bitStringSz = SetBitString(pubSz, 0, bitString);
-
-        idx = SetSequence(pubSz + bitStringSz + algoSz, output);
-        /* algo */
-        XMEMCPY(output + idx, algo, algoSz);
-        idx += algoSz;
-        /* bit string */
-        XMEMCPY(output + idx, bitString, bitStringSz);
-        idx += bitStringSz;
-    }
-    else
-        idx = 0;
-
-    /* pub */
-    XMEMCPY(output + idx, pub, pubSz);
-    idx += pubSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (with_header) {
-        XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return idx;
-}
-
-int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen,
-                                                                    int withAlg)
-{
-    word32 infoSz = 0;
-    word32 keySz  = 0;
-    int ret;
-
-    if (output == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (withAlg) {
-        /* buffer space for algorithm */
-        infoSz += MAX_SEQ_SZ;
-        infoSz += MAX_ALGO_SZ;
-
-        /* buffer space for public key sequence */
-        infoSz += MAX_SEQ_SZ;
-        infoSz += TRAILING_ZERO;
-    }
-
-    if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) {
-        WOLFSSL_MSG("Error in getting ECC public key size");
-        return ret;
-    }
-
-    if (inLen < keySz + infoSz) {
-        return BUFFER_E;
-    }
-
-    return SetEd25519PublicKey(output, key, withAlg);
-}
-#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
-
-
-#ifdef WOLFSSL_CERT_GEN
-
-static WC_INLINE byte itob(int number)
-{
-    return (byte)number + 0x30;
-}
-
-
-/* write time to output, format */
-static void SetTime(struct tm* date, byte* output)
-{
-    int i = 0;
-
-    output[i++] = itob((date->tm_year % 10000) / 1000);
-    output[i++] = itob((date->tm_year % 1000)  /  100);
-    output[i++] = itob((date->tm_year % 100)   /   10);
-    output[i++] = itob( date->tm_year % 10);
-
-    output[i++] = itob(date->tm_mon / 10);
-    output[i++] = itob(date->tm_mon % 10);
-
-    output[i++] = itob(date->tm_mday / 10);
-    output[i++] = itob(date->tm_mday % 10);
-
-    output[i++] = itob(date->tm_hour / 10);
-    output[i++] = itob(date->tm_hour % 10);
-
-    output[i++] = itob(date->tm_min / 10);
-    output[i++] = itob(date->tm_min % 10);
-
-    output[i++] = itob(date->tm_sec / 10);
-    output[i++] = itob(date->tm_sec % 10);
-
-    output[i] = 'Z';  /* Zulu profile */
-}
-
-
-#ifdef WOLFSSL_ALT_NAMES
-
-/* Copy Dates from cert, return bytes written */
-static int CopyValidity(byte* output, Cert* cert)
-{
-    int seqSz;
-
-    WOLFSSL_ENTER("CopyValidity");
-
-    /* headers and output */
-    seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
-    XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
-    XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
-                                                 cert->afterDateSz);
-    return seqSz + cert->beforeDateSz + cert->afterDateSz;
-}
-
-#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 = NULL;
-    struct tm* expandedTime;
-    struct tm localTime;
-
-#if defined(NEED_TMP_TIME)
-    /* for use with gmtime_r */
-    struct tm tmpTimeStorage;
-    tmpTime = &tmpTimeStorage;
-#else
-    (void)tmpTime;
-#endif
-
-    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 * 3600);
-    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 */
-typedef struct EncodedName {
-    int  nameLen;                /* actual string value length */
-    int  totalLen;               /* total encoded length */
-    int  type;                   /* type of name */
-    int  used;                   /* are we actually using this one */
-    byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
-} EncodedName;
-
-
-/* Get Which Name from index */
-static const char* GetOneName(CertName* name, int idx)
-{
-    switch (idx) {
-    case 0:
-       return name->country;
-
-    case 1:
-       return name->state;
-
-    case 2:
-       return name->locality;
-
-    case 3:
-       return name->sur;
-
-    case 4:
-       return name->org;
-
-    case 5:
-       return name->unit;
-
-    case 6:
-       return name->commonName;
-
-    case 7:
-       return name->email;
-
-    default:
-       return 0;
-    }
-}
-
-
-/* Get Which Name Encoding from index */
-static char GetNameType(CertName* name, int idx)
-{
-    switch (idx) {
-    case 0:
-       return name->countryEnc;
-
-    case 1:
-       return name->stateEnc;
-
-    case 2:
-       return name->localityEnc;
-
-    case 3:
-       return name->surEnc;
-
-    case 4:
-       return name->orgEnc;
-
-    case 5:
-       return name->unitEnc;
-
-    case 6:
-       return name->commonNameEnc;
-
-    default:
-       return 0;
-    }
-}
-
-
-/* Get ASN Name from index */
-static byte GetNameId(int idx)
-{
-    switch (idx) {
-    case 0:
-       return ASN_COUNTRY_NAME;
-
-    case 1:
-       return ASN_STATE_NAME;
-
-    case 2:
-       return ASN_LOCALITY_NAME;
-
-    case 3:
-       return ASN_SUR_NAME;
-
-    case 4:
-       return ASN_ORG_NAME;
-
-    case 5:
-       return ASN_ORGUNIT_NAME;
-
-    case 6:
-       return ASN_COMMON_NAME;
-
-    case 7:
-       return ASN_EMAIL_NAME;
-
-    default:
-       return 0;
-    }
-}
-
-/*
- Extensions ::= SEQUENCE OF Extension
-
- Extension ::= SEQUENCE {
- extnId     OBJECT IDENTIFIER,
- critical   BOOLEAN DEFAULT FALSE,
- extnValue  OCTET STRING }
- */
-
-/* encode all extensions, return total bytes written */
-static int SetExtensions(byte* out, word32 outSz, int *IdxInOut,
-                         const byte* ext, int extSz)
-{
-    if (out == NULL || IdxInOut == NULL || ext == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outSz < (word32)(*IdxInOut+extSz))
-        return BUFFER_E;
-
-    XMEMCPY(&out[*IdxInOut], ext, extSz);  /* extensions */
-    *IdxInOut += extSz;
-
-    return *IdxInOut;
-}
-
-/* encode extensions header, return total bytes written */
-static int SetExtensionsHeader(byte* out, word32 outSz, int extSz)
-{
-    byte sequence[MAX_SEQ_SZ];
-    byte len[MAX_LENGTH_SZ];
-    int seqSz, lenSz, idx = 0;
-
-    if (out == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outSz < 3)
-        return BUFFER_E;
-
-    seqSz = SetSequence(extSz, sequence);
-
-    /* encode extensions length provided */
-    lenSz = SetLength(extSz+seqSz, len);
-
-    if (outSz < (word32)(lenSz+seqSz+1))
-        return BUFFER_E;
-
-    out[idx++] = ASN_EXTENSIONS; /* extensions id */
-    XMEMCPY(&out[idx], len, lenSz);  /* length */
-    idx += lenSz;
-
-    XMEMCPY(&out[idx], sequence, seqSz);  /* sequence */
-    idx += seqSz;
-
-    return idx;
-}
-
-
-/* encode CA basic constraint true, return total bytes written */
-static int SetCa(byte* out, word32 outSz)
-{
-    static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
-                               0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
-
-    if (out == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outSz < sizeof(ca))
-        return BUFFER_E;
-
-    XMEMCPY(out, ca, sizeof(ca));
-
-    return (int)sizeof(ca);
-}
-
-
-#ifdef WOLFSSL_CERT_EXT
-/* encode OID and associated value, return total bytes written */
-static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz,
-                       byte *in, word32 inSz)
-{
-    int idx = 0;
-
-    if (out == NULL || oid == NULL || in == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outSz < 3)
-        return BUFFER_E;
-
-    /* sequence,  + 1 => byte to put value size */
-    idx = SetSequence(inSz + oidSz + 1, out);
-
-    if ((idx + inSz + oidSz + 1) > outSz)
-        return BUFFER_E;
-
-    XMEMCPY(out+idx, oid, oidSz);
-    idx += oidSz;
-    out[idx++] = (byte)inSz;
-    XMEMCPY(out+idx, in, inSz);
-
-    return (idx+inSz);
-}
-
-/* encode Subject Key Identifier, return total bytes written
- * RFC5280 : non-critical */
-static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length)
-{
-    byte skid_len[1 + MAX_LENGTH_SZ];
-    byte skid_enc_len[MAX_LENGTH_SZ];
-    int idx = 0, skid_lenSz, skid_enc_lenSz;
-    static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 };
-
-    if (output == NULL || input == NULL)
-        return BAD_FUNC_ARG;
-
-    /* Octet String header */
-    skid_lenSz = SetOctetString(length, skid_len);
-
-    /* length of encoded value */
-    skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len);
-
-    if (outSz < 3)
-        return BUFFER_E;
-
-    idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz,
-                      output);
-
-    if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz)
-        return BUFFER_E;
-
-    /* put oid */
-    XMEMCPY(output+idx, skid_oid, sizeof(skid_oid));
-    idx += sizeof(skid_oid);
-
-    /* put encoded len */
-    XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz);
-    idx += skid_enc_lenSz;
-
-    /* put octet header */
-    XMEMCPY(output+idx, skid_len, skid_lenSz);
-    idx += skid_lenSz;
-
-    /* put value */
-    XMEMCPY(output+idx, input, length);
-    idx += length;
-
-    return idx;
-}
-
-/* encode Authority Key Identifier, return total bytes written
- * RFC5280 : non-critical */
-static int SetAKID(byte* output, word32 outSz,
-                                         byte *input, word32 length, void* heap)
-{
-    byte    *enc_val;
-    int     ret, enc_valSz;
-    static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 };
-    static const byte akid_cs[] = { 0x80 };
-
-    if (output == NULL || input == NULL)
-        return BAD_FUNC_ARG;
-
-    enc_valSz = length + 3 + sizeof(akid_cs);
-    enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (enc_val == NULL)
-        return MEMORY_E;
-
-    /* sequence for ContentSpec & value */
-    ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs),
-                      input, length);
-    if (ret > 0) {
-        enc_valSz = ret;
-
-        ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid),
-                          enc_val, enc_valSz);
-    }
-
-    XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return ret;
-}
-
-/* encode Key Usage, return total bytes written
- * RFC5280 : critical */
-static int SetKeyUsage(byte* output, word32 outSz, word16 input)
-{
-    byte ku[5];
-    int  idx;
-    static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f,
-                                         0x01, 0x01, 0xff, 0x04};
-    if (output == NULL)
-        return BAD_FUNC_ARG;
-
-    idx = SetBitString16Bit(input, ku);
-    return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid),
-                       ku, idx);
-}
-
-static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
-    const byte* oid, word32 oidSz)
-{
-    /* verify room */
-    if (*idx + 2 + oidSz >= outSz)
-        return ASN_PARSE_E;
-
-    *idx += SetObjectId(oidSz, &output[*idx]);
-    XMEMCPY(&output[*idx], oid, oidSz);
-    *idx += oidSz;
-
-    return 0;
-}
-
-/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */
-static int SetExtKeyUsage(Cert* cert, byte* output, word32 outSz, byte input)
-{
-    int idx = 0, oidListSz = 0, totalSz, ret = 0;
-    static const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 };
-
-    if (output == NULL)
-        return BAD_FUNC_ARG;
-
-    /* Skip to OID List */
-    totalSz = 2 + sizeof(extkeyusage_oid) + 4;
-    idx = totalSz;
-
-    /* Build OID List */
-    /* If any set, then just use it */
-    if (input & EXTKEYUSE_ANY) {
-        ret |= SetOjectIdValue(output, outSz, &idx,
-            extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid));
-    }
-    else {
-        if (input & EXTKEYUSE_SERVER_AUTH)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid));
-        if (input & EXTKEYUSE_CLIENT_AUTH)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid));
-        if (input & EXTKEYUSE_CODESIGN)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid));
-        if (input & EXTKEYUSE_EMAILPROT)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid));
-        if (input & EXTKEYUSE_TIMESTAMP)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid));
-        if (input & EXTKEYUSE_OCSP_SIGN)
-            ret |= SetOjectIdValue(output, outSz, &idx,
-                extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid));
-    #ifdef WOLFSSL_EKU_OID
-        /* iterate through OID values */
-        if (input & EXTKEYUSE_USER) {
-            int i, sz;
-            for (i = 0; i < CTC_MAX_EKU_NB; i++) {
-                sz = cert->extKeyUsageOIDSz[i];
-                if (sz > 0) {
-                    ret |= SetOjectIdValue(output, outSz, &idx,
-                        cert->extKeyUsageOID[i], sz);
-                }
-            }
-        }
-    #endif /* WOLFSSL_EKU_OID */
-    }
-    if (ret != 0)
-        return ASN_PARSE_E;
-
-    /* Calculate Sizes */
-    oidListSz = idx - totalSz;
-    totalSz = idx - 2; /* exclude first seq/len (2) */
-
-    /* 1. Seq + Total Len (2) */
-    idx = SetSequence(totalSz, output);
-
-    /* 2. Object ID (2) */
-    XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid));
-    idx += sizeof(extkeyusage_oid);
-
-    /* 3. Octect String (2) */
-    idx += SetOctetString(totalSz - idx, &output[idx]);
-
-    /* 4. Seq + OidListLen (2) */
-    idx += SetSequence(oidListSz, &output[idx]);
-
-    /* 5. Oid List (already set in-place above) */
-    idx += oidListSz;
-
-    (void)cert;
-    return idx;
-}
-
-/* Encode OID string representation to ITU-T X.690 format */
-static int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap)
-{
-    word32 val, idx = 0, nb_val;
-    char *token, *str, *ptr;
-    word32 len;
-
-    if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL)
-        return BAD_FUNC_ARG;
-
-    len = (word32)XSTRLEN(in);
-
-    str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (str == NULL)
-        return MEMORY_E;
-
-    XSTRNCPY(str, in, len);
-    str[len] = '\0';
-
-    nb_val = 0;
-
-    /* parse value, and set corresponding Policy OID value */
-    token = XSTRTOK(str, ".", &ptr);
-    while (token != NULL)
-    {
-        val = (word32)atoi(token);
-
-        if (nb_val == 0) {
-            if (val > 2) {
-                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return ASN_OBJECT_ID_E;
-            }
-
-            out[idx] = (byte)(40 * val);
-        }
-        else if (nb_val == 1) {
-            if (val > 127) {
-                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return ASN_OBJECT_ID_E;
-            }
-
-            if (idx > *outSz) {
-                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return BUFFER_E;
-            }
-
-            out[idx++] += (byte)val;
-        }
-        else {
-            word32  tb = 0, x;
-            int     i = 0;
-            byte    oid[MAX_OID_SZ];
-
-            while (val >= 128) {
-                x = val % 128;
-                val /= 128;
-                oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x);
-            }
-
-            if ((idx+(word32)i) > *outSz) {
-                XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                return BUFFER_E;
-            }
-
-            oid[i] = (byte) (((tb++) ? 0x80 : 0) | val);
-
-            /* push value in the right order */
-            while (i >= 0)
-                out[idx++] = oid[i--];
-        }
-
-        token = XSTRTOK(NULL, ".", &ptr);
-        nb_val++;
-    }
-
-    *outSz = idx;
-
-    XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return 0;
-}
-
-/* encode Certificate Policies, return total bytes written
- * each input value must be ITU-T X.690 formatted : a.b.c...
- * input must be an array of values with a NULL terminated for the latest
- * RFC5280 : non-critical */
-static int SetCertificatePolicies(byte *output,
-                                  word32 outputSz,
-                                  char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ],
-                                  word16 nb_certpol,
-                                  void* heap)
-{
-    byte    oid[MAX_OID_SZ],
-            der_oid[MAX_CERTPOL_NB][MAX_OID_SZ],
-            out[MAX_CERTPOL_SZ];
-    word32  oidSz;
-    word32  outSz, i = 0, der_oidSz[MAX_CERTPOL_NB];
-    int     ret;
-
-    static const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 };
-    static const byte oid_oid[] = { 0x06 };
-
-    if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB)
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < nb_certpol; i++) {
-        oidSz = sizeof(oid);
-        XMEMSET(oid, 0, oidSz);
-
-        ret = EncodePolicyOID(oid, &oidSz, input[i], heap);
-        if (ret != 0)
-            return ret;
-
-        /* compute sequence value for the oid */
-        ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid,
-                          sizeof(oid_oid), oid, oidSz);
-        if (ret <= 0)
-            return ret;
-        else
-            der_oidSz[i] = (word32)ret;
-    }
-
-    /* concatenate oid, keep two byte for sequence/size of the created value */
-    for (i = 0, outSz = 2; i < nb_certpol; i++) {
-        XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]);
-        outSz += der_oidSz[i];
-    }
-
-    /* add sequence */
-    ret = SetSequence(outSz-2, out);
-    if (ret <= 0)
-        return ret;
-
-    /* add Policy OID to compute final value */
-    return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid),
-                      out, outSz);
-}
-#endif /* WOLFSSL_CERT_EXT */
-
-#ifdef WOLFSSL_ALT_NAMES
-/* encode Alternative Names, return total bytes written */
-static int SetAltNames(byte *out, word32 outSz, byte *input, word32 length)
-{
-    if (out == NULL || input == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outSz < length)
-        return BUFFER_E;
-
-    /* Alternative Names come from certificate or computed by
-     * external function, so already encoded. Just copy value */
-    XMEMCPY(out, input, length);
-    return length;
-}
-#endif /* WOLFSL_ALT_NAMES */
-
-/* Encodes one attribute of the name (issuer/subject)
- *
- * name     structure to hold result of encoding
- * nameStr  value to be encoded
- * nameType type of encoding i.e CTC_UTF8
- * type     id of attribute i.e ASN_COMMON_NAME
- *
- * returns length on success
- */
-static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType,
-        byte type)
-{
-    word32 idx = 0;
-
-    if (nameStr) {
-        /* bottom up */
-        byte firstLen[1 + MAX_LENGTH_SZ];
-        byte secondLen[MAX_LENGTH_SZ];
-        byte sequence[MAX_SEQ_SZ];
-        byte set[MAX_SET_SZ];
-
-        int strLen  = (int)XSTRLEN(nameStr);
-        int thisLen = strLen;
-        int firstSz, secondSz, seqSz, setSz;
-
-        if (strLen == 0) { /* no user data for this item */
-            name->used = 0;
-            return 0;
-        }
-
-        /* Restrict country code size */
-        if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
-            return ASN_COUNTRY_SIZE_E;
-        }
-
-        secondSz = SetLength(strLen, secondLen);
-        thisLen += secondSz;
-        switch (type) {
-            case ASN_EMAIL_NAME: /* email */
-                thisLen += EMAIL_JOINT_LEN;
-                firstSz  = EMAIL_JOINT_LEN;
-                break;
-
-            case ASN_DOMAIN_COMPONENT:
-                thisLen += PILOT_JOINT_LEN;
-                firstSz  = PILOT_JOINT_LEN;
-                break;
-
-            default:
-                thisLen++;                                 /* str type */
-                thisLen += JOINT_LEN;
-                firstSz  = JOINT_LEN + 1;
-        }
-        thisLen++; /* id  type */
-        firstSz  = SetObjectId(firstSz, firstLen);
-        thisLen += firstSz;
-
-        seqSz = SetSequence(thisLen, sequence);
-        thisLen += seqSz;
-        setSz = SetSet(thisLen, set);
-        thisLen += setSz;
-
-        if (thisLen > (int)sizeof(name->encoded)) {
-            return BUFFER_E;
-        }
-
-        /* store it */
-        idx = 0;
-        /* set */
-        XMEMCPY(name->encoded, set, setSz);
-        idx += setSz;
-        /* seq */
-        XMEMCPY(name->encoded + idx, sequence, seqSz);
-        idx += seqSz;
-        /* asn object id */
-        XMEMCPY(name->encoded + idx, firstLen, firstSz);
-        idx += firstSz;
-        switch (type) {
-            case ASN_EMAIL_NAME:
-                {
-                    const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-                                       0x01, 0x09, 0x01, 0x16 };
-                    /* email joint id */
-                    XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
-                    idx += (int)sizeof(EMAIL_OID);
-                }
-                break;
-
-            case ASN_DOMAIN_COMPONENT:
-                {
-                    const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89,
-                                    0x93, 0xF2, 0x2C, 0x64, 0x01
-                    };
-
-                    XMEMCPY(name->encoded + idx, PILOT_OID,
-                                                     sizeof(PILOT_OID));
-                    idx += (int)sizeof(PILOT_OID);
-                    /* id type */
-                    name->encoded[idx++] = type;
-                    /* str type */
-                    name->encoded[idx++] = nameType;
-                }
-                break;
-
-            default:
-                name->encoded[idx++] = 0x55;
-                name->encoded[idx++] = 0x04;
-                /* id type */
-                name->encoded[idx++] = type;
-                /* str type */
-                name->encoded[idx++] = nameType;
-        }
-        /* second length */
-        XMEMCPY(name->encoded + idx, secondLen, secondSz);
-        idx += secondSz;
-        /* str value */
-        XMEMCPY(name->encoded + idx, nameStr, strLen);
-        idx += strLen;
-
-        name->type = type;
-        name->totalLen = idx;
-        name->used = 1;
-    }
-    else
-        name->used = 0;
-
-    return idx;
-}
-
-/* encode CertName into output, return total bytes written */
-int SetName(byte* output, word32 outputSz, CertName* name)
-{
-    int          totalBytes = 0, i, idx;
-#ifdef WOLFSSL_SMALL_STACK
-    EncodedName* names = NULL;
-#else
-    EncodedName  names[NAME_ENTRIES];
-#endif
-#ifdef WOLFSSL_MULTI_ATTRIB
-    EncodedName addNames[CTC_MAX_ATTRIB];
-    int j, type;
-#endif
-
-    if (output == NULL || name == NULL)
-        return BAD_FUNC_ARG;
-
-    if (outputSz < 3)
-        return BUFFER_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (names == NULL)
-        return MEMORY_E;
-#endif
-
-    for (i = 0; i < NAME_ENTRIES; i++) {
-        int ret;
-        const char* nameStr = GetOneName(name, i);
-
-        ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i),
-                          GetNameId(i));
-        if (ret < 0) {
-        #ifdef WOLFSSL_SMALL_STACK
-                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-                return BUFFER_E;
-        }
-        totalBytes += ret;
-    }
-#ifdef WOLFSSL_MULTI_ATTRIB
-    for (i = 0; i < CTC_MAX_ATTRIB; i++) {
-        if (name->name[i].sz > 0) {
-            int ret;
-            ret = wc_EncodeName(&addNames[i], name->name[i].value,
-                        name->name[i].type, name->name[i].id);
-            if (ret < 0) {
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            #endif
-                return BUFFER_E;
-            }
-            totalBytes += ret;
-        }
-        else {
-            addNames[i].used = 0;
-        }
-    }
-#endif /* WOLFSSL_MULTI_ATTRIB */
-
-    /* header */
-    idx = SetSequence(totalBytes, output);
-    totalBytes += idx;
-    if (totalBytes > ASN_NAME_MAX) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BUFFER_E;
-    }
-
-    for (i = 0; i < NAME_ENTRIES; i++) {
-    #ifdef WOLFSSL_MULTI_ATTRIB
-        type = GetNameId(i);
-
-        /* list all DC values before OUs */
-        if (type == ASN_ORGUNIT_NAME) {
-            type = ASN_DOMAIN_COMPONENT;
-            for (j = 0; j < CTC_MAX_ATTRIB; j++) {
-                if (name->name[j].sz > 0 && type == name->name[j].id) {
-                    if (outputSz < (word32)(idx+addNames[j].totalLen)) {
-                    #ifdef WOLFSSL_SMALL_STACK
-                        XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                    #endif
-                        return BUFFER_E;
-                    }
-
-                    XMEMCPY(output + idx, addNames[j].encoded,
-                            addNames[j].totalLen);
-                    idx += addNames[j].totalLen;
-                }
-            }
-            type = ASN_ORGUNIT_NAME;
-        }
-
-        /* write all similar types to the buffer */
-        for (j = 0; j < CTC_MAX_ATTRIB; j++) {
-            if (name->name[j].sz > 0 && type == name->name[j].id) {
-                if (outputSz < (word32)(idx+addNames[j].totalLen)) {
-                #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                #endif
-                    return BUFFER_E;
-                }
-
-                XMEMCPY(output + idx, addNames[j].encoded,
-                        addNames[j].totalLen);
-                idx += addNames[j].totalLen;
-            }
-        }
-    #endif /* WOLFSSL_MULTI_ATTRIB */
-
-        if (names[i].used) {
-            if (outputSz < (word32)(idx+names[i].totalLen)) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return BUFFER_E;
-            }
-
-            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
-
-    return totalBytes;
-}
-
-/* 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,
-                      ed25519_key* ed25519Key)
-{
-    int ret;
-
-    if (cert == NULL || der == NULL || rng == NULL)
-        return BAD_FUNC_ARG;
-
-    /* make sure at least one key type is provided */
-    if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && ntruKey == NULL)
-        return PUBLIC_KEY_E;
-
-    /* init */
-    XMEMSET(der, 0, sizeof(DerCert));
-
-    /* version */
-    der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
-
-    /* serial number (must be positive) */
-    if (cert->serialSz == 0) {
-        /* generate random serial */
-        cert->serialSz = CTC_SERIAL_SIZE;
-        ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz);
-        if (ret != 0)
-            return ret;
-    }
-    der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial,
-        CTC_SERIAL_SIZE);
-    if (der->serialSz < 0)
-        return der->serialSz;
-
-    /* signature algo */
-    der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0);
-    if (der->sigAlgoSz <= 0)
-        return ALGO_ID_E;
-
-    /* public key */
-#ifndef NO_RSA
-    if (cert->keyType == RSA_KEY) {
-        if (rsaKey == NULL)
-            return PUBLIC_KEY_E;
-        der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
-                                           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);
-    }
-#endif
-
-#ifdef HAVE_ED25519
-    if (cert->keyType == ED25519_KEY) {
-        if (ed25519Key == NULL)
-            return PUBLIC_KEY_E;
-        der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
-    }
-#endif
-
-#ifdef HAVE_NTRU
-    if (cert->keyType == NTRU_KEY) {
-        word32 rc;
-        word16 encodedSz;
-
-        if (ntruKey == NULL)
-            return PUBLIC_KEY_E;
-
-        rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
-                                                   ntruKey, &encodedSz, NULL);
-        if (rc != NTRU_OK)
-            return PUBLIC_KEY_E;
-        if (encodedSz > MAX_PUBLIC_KEY_SZ)
-            return PUBLIC_KEY_E;
-
-        rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
-                                         ntruKey, &encodedSz, der->publicKey);
-        if (rc != NTRU_OK)
-            return PUBLIC_KEY_E;
-
-        der->publicKeySz = encodedSz;
-    }
-#else
-    (void)ntruSz;
-#endif /* HAVE_NTRU */
-
-    if (der->publicKeySz <= 0)
-        return PUBLIC_KEY_E;
-
-    der->validitySz = 0;
-#ifdef WOLFSSL_ALT_NAMES
-    /* date validity copy ? */
-    if (cert->beforeDateSz && cert->afterDateSz) {
-        der->validitySz = CopyValidity(der->validity, cert);
-        if (der->validitySz <= 0)
-            return DATE_E;
-    }
-#endif
-
-    /* date validity */
-    if (der->validitySz == 0) {
-        der->validitySz = SetValidity(der->validity, cert->daysValid);
-        if (der->validitySz <= 0)
-            return DATE_E;
-    }
-
-    /* subject name */
-    der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
-    if (der->subjectSz <= 0)
-        return SUBJECT_E;
-
-    /* issuer name */
-    der->issuerSz = SetName(der->issuer, sizeof(der->issuer), cert->selfSigned ?
-             &cert->subject : &cert->issuer);
-    if (der->issuerSz <= 0)
-        return ISSUER_E;
-
-    /* set the extensions */
-    der->extensionsSz = 0;
-
-    /* CA */
-    if (cert->isCA) {
-        der->caSz = SetCa(der->ca, sizeof(der->ca));
-        if (der->caSz <= 0)
-            return CA_TRUE_E;
-
-        der->extensionsSz += der->caSz;
-    }
-    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
-    /* SKID */
-    if (cert->skidSz) {
-        /* check the provided SKID size */
-        if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
-            return SKID_E;
-
-        /* Note: different skid buffers sizes for der (MAX_KID_SZ) and
-            cert (CTC_MAX_SKID_SIZE). */
-        der->skidSz = SetSKID(der->skid, sizeof(der->skid),
-                              cert->skid, cert->skidSz);
-        if (der->skidSz <= 0)
-            return SKID_E;
-
-        der->extensionsSz += der->skidSz;
-    }
-    else
-        der->skidSz = 0;
-
-    /* AKID */
-    if (cert->akidSz) {
-        /* check the provided AKID size */
-        if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid)))
-            return AKID_E;
-
-        der->akidSz = SetAKID(der->akid, sizeof(der->akid),
-                              cert->akid, cert->akidSz, cert->heap);
-        if (der->akidSz <= 0)
-            return AKID_E;
-
-        der->extensionsSz += der->akidSz;
-    }
-    else
-        der->akidSz = 0;
-
-    /* Key Usage */
-    if (cert->keyUsage != 0){
-        der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
-                                      cert->keyUsage);
-        if (der->keyUsageSz <= 0)
-            return KEYUSAGE_E;
-
-        der->extensionsSz += der->keyUsageSz;
-    }
-    else
-        der->keyUsageSz = 0;
-
-    /* Extended Key Usage */
-    if (cert->extKeyUsage != 0){
-        der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
-                                sizeof(der->extKeyUsage), cert->extKeyUsage);
-        if (der->extKeyUsageSz <= 0)
-            return EXTKEYUSAGE_E;
-
-        der->extensionsSz += der->extKeyUsageSz;
-    }
-    else
-        der->extKeyUsageSz = 0;
-
-    /* Certificate Policies */
-    if (cert->certPoliciesNb != 0) {
-        der->certPoliciesSz = SetCertificatePolicies(der->certPolicies,
-                                                     sizeof(der->certPolicies),
-                                                     cert->certPolicies,
-                                                     cert->certPoliciesNb,
-                                                     cert->heap);
-        if (der->certPoliciesSz <= 0)
-            return CERTPOLICIES_E;
-
-        der->extensionsSz += der->certPoliciesSz;
-    }
-    else
-        der->certPoliciesSz = 0;
-#endif /* WOLFSSL_CERT_EXT */
-
-    /* put extensions */
-    if (der->extensionsSz > 0) {
-
-        /* put the start of extensions sequence (ID, Size) */
-        der->extensionsSz = SetExtensionsHeader(der->extensions,
-                                                sizeof(der->extensions),
-                                                der->extensionsSz);
-        if (der->extensionsSz <= 0)
-            return EXTENSIONS_E;
-
-        /* put CA */
-        if (der->caSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->ca, der->caSz);
-            if (ret == 0)
-                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
-        /* put SKID */
-        if (der->skidSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->skid, der->skidSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put AKID */
-        if (der->akidSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->akid, der->akidSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put KeyUsage */
-        if (der->keyUsageSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->keyUsage, der->keyUsageSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put ExtendedKeyUsage */
-        if (der->extKeyUsageSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->extKeyUsage, der->extKeyUsageSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put Certificate Policies */
-        if (der->certPoliciesSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->certPolicies, der->certPoliciesSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-#endif /* WOLFSSL_CERT_EXT */
-    }
-
-    der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
-        der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
-        der->extensionsSz;
-
-    return 0;
-}
-
-
-/* write DER encoded cert to buffer, size already checked */
-static int WriteCertBody(DerCert* der, byte* buffer)
-{
-    int idx;
-
-    /* signed part header */
-    idx = SetSequence(der->total, buffer);
-    /* version */
-    XMEMCPY(buffer + idx, der->version, der->versionSz);
-    idx += der->versionSz;
-    /* serial */
-    XMEMCPY(buffer + idx, der->serial, der->serialSz);
-    idx += der->serialSz;
-    /* sig algo */
-    XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
-    idx += der->sigAlgoSz;
-    /* issuer */
-    XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
-    idx += der->issuerSz;
-    /* validity */
-    XMEMCPY(buffer + idx, der->validity, der->validitySz);
-    idx += der->validitySz;
-    /* subject */
-    XMEMCPY(buffer + idx, der->subject, der->subjectSz);
-    idx += der->subjectSz;
-    /* public key */
-    XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
-    idx += der->publicKeySz;
-    if (der->extensionsSz) {
-        /* extensions */
-        XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
-                                                   (int)sizeof(der->extensions)));
-        idx += der->extensionsSz;
-    }
-
-    return idx;
-}
-
-
-/* Make RSA signature from buffer (sz), write to sig (sigSz) */
-static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz,
-    byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey,
-    ed25519_key* ed25519Key, WC_RNG* rng, int sigAlgoType, void* heap)
-{
-    int digestSz = 0, typeH = 0, ret = 0;
-
-    (void)digestSz;
-    (void)typeH;
-    (void)buffer;
-    (void)sz;
-    (void)sig;
-    (void)sigSz;
-    (void)rsaKey;
-    (void)eccKey;
-    (void)ed25519Key;
-    (void)rng;
-
-    switch (certSignCtx->state) {
-    case CERTSIGN_STATE_BEGIN:
-    case CERTSIGN_STATE_DIGEST:
-
-        certSignCtx->state = CERTSIGN_STATE_DIGEST;
-        certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (certSignCtx->digest == NULL) {
-            ret = MEMORY_E; goto exit_ms;
-        }
-
-        ret = HashForSignature(buffer, sz, sigAlgoType, certSignCtx->digest,
-                               &typeH, &digestSz, 0);
-        /* set next state, since WC_PENDING rentry for these are not "call again" */
-        certSignCtx->state = CERTSIGN_STATE_ENCODE;
-        if (ret != 0) {
-            goto exit_ms;
-        }
-        FALL_THROUGH;
-
-    case CERTSIGN_STATE_ENCODE:
-    #ifndef NO_RSA
-        if (rsaKey) {
-            certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap,
-                DYNAMIC_TYPE_TMP_BUFFER);
-            if (certSignCtx->encSig == NULL) {
-                ret = MEMORY_E; goto exit_ms;
-            }
-
-            /* signature */
-            certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig,
-                                          certSignCtx->digest, digestSz, typeH);
-        }
-    #endif /* !NO_RSA */
-        FALL_THROUGH;
-
-    case CERTSIGN_STATE_DO:
-        certSignCtx->state = CERTSIGN_STATE_DO;
-        ret = ALGO_ID_E; /* default to error */
-
-    #ifndef NO_RSA
-        if (rsaKey) {
-            /* signature */
-            ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz,
-                                 sig, sigSz, rsaKey, rng);
-        }
-    #endif /* !NO_RSA */
-
-    #ifdef HAVE_ECC
-        if (!rsaKey && eccKey) {
-            word32 outSz = sigSz;
-
-            ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz,
-                                   sig, &outSz, rng, eccKey);
-            if (ret == 0)
-                ret = outSz;
-        }
-    #endif /* HAVE_ECC */
-
-    #ifdef HAVE_ED25519
-        if (!rsaKey && !eccKey && ed25519Key) {
-            word32 outSz = sigSz;
-
-            ret = wc_ed25519_sign_msg(buffer, sz, sig, &outSz, ed25519Key);
-            if (ret == 0)
-                ret = outSz;
-        }
-    #endif /* HAVE_ECC */
-        break;
-    }
-
-exit_ms:
-
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-
-#ifndef NO_RSA
-    if (rsaKey) {
-        XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#endif /* !NO_RSA */
-
-    XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    certSignCtx->digest = NULL;
-
-    /* reset state */
-    certSignCtx->state = CERTSIGN_STATE_BEGIN;
-
-    return ret;
-}
-
-
-/* add signature to end of buffer, size of buffer assumed checked, return
-   new length */
-static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
-                        int sigAlgoType)
-{
-    byte seq[MAX_SEQ_SZ];
-    int  idx = bodySz, seqSz;
-
-    /* algo */
-    idx += SetAlgoID(sigAlgoType, buffer + idx, oidSigType, 0);
-    /* bit string */
-    idx += SetBitString(sigSz, 0, buffer + idx);
-    /* signature */
-    XMEMCPY(buffer + idx, sig, sigSz);
-    idx += sigSz;
-
-    /* make room for overall header */
-    seqSz = SetSequence(idx, seq);
-    XMEMMOVE(buffer + seqSz, buffer, idx);
-    XMEMCPY(buffer, seq, seqSz);
-
-    return idx + seqSz;
-}
-
-
-/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
-static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
-                       RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng,
-                       const byte* ntruKey, word16 ntruSz,
-                       ed25519_key* ed25519Key)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK
-    DerCert* der;
-#else
-    DerCert der[1];
-#endif
-
-    cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY :
-                                         (ed25519Key ? ED25519_KEY : NTRU_KEY));
-
-#ifdef WOLFSSL_SMALL_STACK
-    der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (der == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz,
-                     ed25519Key);
-    if (ret == 0) {
-        if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
-            ret = BUFFER_E;
-        else
-            ret = cert->bodySz = WriteCertBody(der, derBuffer);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
-int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
-                   void* key, WC_RNG* rng)
-{
-    RsaKey* rsaKey = NULL;
-    ecc_key* eccKey = NULL;
-    ed25519_key* ed25519Key = NULL;
-
-    if (keyType == RSA_TYPE)
-        rsaKey = (RsaKey*)key;
-    else if (keyType == ECC_TYPE)
-        eccKey = (ecc_key*)key;
-    else if (keyType == ED25519_TYPE)
-        ed25519Key = (ed25519_key*)key;
-
-    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
-                       ed25519Key);
-}
-/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
-int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
-             ecc_key* eccKey, WC_RNG* rng)
-{
-    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
-                       NULL);
-}
-
-
-#ifdef HAVE_NTRU
-
-int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
-                  const byte* ntruKey, word16 keySz, WC_RNG* rng)
-{
-    return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL);
-}
-
-#endif /* HAVE_NTRU */
-
-
-#ifdef WOLFSSL_CERT_REQ
-
-static int SetReqAttrib(byte* output, char* pw, int extSz)
-{
-    static const byte cpOid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-                         0x09, 0x07 };
-    static const byte erOid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-                         0x09, 0x0e };
-
-    int sz      = 0; /* overall size */
-    int cpSz    = 0; /* Challenge Password section size */
-    int cpSeqSz = 0;
-    int cpSetSz = 0;
-    int cpStrSz = 0;
-    int pwSz    = 0;
-    int erSz    = 0; /* Extension Request section size */
-    int erSeqSz = 0;
-    int erSetSz = 0;
-    byte cpSeq[MAX_SEQ_SZ];
-    byte cpSet[MAX_SET_SZ];
-    byte cpStr[MAX_PRSTR_SZ];
-    byte erSeq[MAX_SEQ_SZ];
-    byte erSet[MAX_SET_SZ];
-
-    output[0] = 0xa0;
-    sz++;
-
-    if (pw && pw[0]) {
-        pwSz = (int)XSTRLEN(pw);
-        cpStrSz = SetUTF8String(pwSz, cpStr);
-        cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
-        cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
-        cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
-    }
-
-    if (extSz) {
-        erSetSz = SetSet(extSz, erSet);
-        erSeqSz = SetSequence(erSetSz + sizeof(erOid) + extSz, erSeq);
-        erSz = extSz + erSetSz + erSeqSz + sizeof(erOid);
-    }
-
-    /* Put the pieces together. */
-    sz += SetLength(cpSz + erSz, &output[sz]);
-
-    if (cpSz) {
-        XMEMCPY(&output[sz], cpSeq, cpSeqSz);
-        sz += cpSeqSz;
-        XMEMCPY(&output[sz], cpOid, sizeof(cpOid));
-        sz += sizeof(cpOid);
-        XMEMCPY(&output[sz], cpSet, cpSetSz);
-        sz += cpSetSz;
-        XMEMCPY(&output[sz], cpStr, cpStrSz);
-        sz += cpStrSz;
-        XMEMCPY(&output[sz], pw, pwSz);
-        sz += pwSz;
-    }
-
-    if (erSz) {
-        XMEMCPY(&output[sz], erSeq, erSeqSz);
-        sz += erSeqSz;
-        XMEMCPY(&output[sz], erOid, sizeof(erOid));
-        sz += sizeof(erOid);
-        XMEMCPY(&output[sz], erSet, erSetSz);
-        sz += erSetSz;
-        /* The actual extension data will be tacked onto the output later. */
-    }
-
-    return sz;
-}
-
-
-/* encode info from cert into DER encoded format */
-static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
-                         ecc_key* eccKey, ed25519_key* ed25519Key)
-{
-    (void)eccKey;
-    (void)ed25519Key;
-
-    if (cert == NULL || der == NULL)
-        return BAD_FUNC_ARG;
-
-    if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL)
-            return PUBLIC_KEY_E;
-
-    /* init */
-    XMEMSET(der, 0, sizeof(DerCert));
-
-    /* version */
-    der->versionSz = SetMyVersion(cert->version, der->version, FALSE);
-
-    /* subject name */
-    der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
-    if (der->subjectSz <= 0)
-        return SUBJECT_E;
-
-    /* public key */
-#ifndef NO_RSA
-    if (cert->keyType == RSA_KEY) {
-        if (rsaKey == NULL)
-            return PUBLIC_KEY_E;
-        der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
-                                           sizeof(der->publicKey), 1);
-    }
-#endif
-
-#ifdef HAVE_ECC
-    if (cert->keyType == ECC_KEY) {
-        der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
-    }
-#endif
-
-#ifdef HAVE_ED25519
-    if (cert->keyType == ED25519_KEY) {
-        if (ed25519Key == NULL)
-            return PUBLIC_KEY_E;
-        der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
-    }
-#endif
-
-    if (der->publicKeySz <= 0)
-        return PUBLIC_KEY_E;
-
-    /* set the extensions */
-    der->extensionsSz = 0;
-
-    /* CA */
-    if (cert->isCA) {
-        der->caSz = SetCa(der->ca, sizeof(der->ca));
-        if (der->caSz <= 0)
-            return CA_TRUE_E;
-
-        der->extensionsSz += der->caSz;
-    }
-    else
-        der->caSz = 0;
-
-#ifdef WOLFSSL_CERT_EXT
-    /* SKID */
-    if (cert->skidSz) {
-        /* check the provided SKID size */
-        if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
-            return SKID_E;
-
-        der->skidSz = SetSKID(der->skid, sizeof(der->skid),
-                              cert->skid, cert->skidSz);
-        if (der->skidSz <= 0)
-            return SKID_E;
-
-        der->extensionsSz += der->skidSz;
-    }
-    else
-        der->skidSz = 0;
-
-    /* Key Usage */
-    if (cert->keyUsage != 0){
-        der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
-                                      cert->keyUsage);
-        if (der->keyUsageSz <= 0)
-            return KEYUSAGE_E;
-
-        der->extensionsSz += der->keyUsageSz;
-    }
-    else
-        der->keyUsageSz = 0;
-
-    /* Extended Key Usage */
-    if (cert->extKeyUsage != 0){
-        der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
-                                sizeof(der->extKeyUsage), cert->extKeyUsage);
-        if (der->extKeyUsageSz <= 0)
-            return EXTKEYUSAGE_E;
-
-        der->extensionsSz += der->extKeyUsageSz;
-    }
-    else
-        der->extKeyUsageSz = 0;
-
-#endif /* WOLFSSL_CERT_EXT */
-
-    /* put extensions */
-    if (der->extensionsSz > 0) {
-        int ret;
-
-        /* put the start of sequence (ID, Size) */
-        der->extensionsSz = SetSequence(der->extensionsSz, der->extensions);
-        if (der->extensionsSz <= 0)
-            return EXTENSIONS_E;
-
-        /* put CA */
-        if (der->caSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->ca, der->caSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-#ifdef WOLFSSL_CERT_EXT
-        /* put SKID */
-        if (der->skidSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->skid, der->skidSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put AKID */
-        if (der->akidSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->akid, der->akidSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put KeyUsage */
-        if (der->keyUsageSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->keyUsage, der->keyUsageSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-        /* put ExtendedKeyUsage */
-        if (der->extKeyUsageSz) {
-            ret = SetExtensions(der->extensions, sizeof(der->extensions),
-                                &der->extensionsSz,
-                                der->extKeyUsage, der->extKeyUsageSz);
-            if (ret <= 0)
-                return EXTENSIONS_E;
-        }
-
-#endif /* WOLFSSL_CERT_EXT */
-    }
-
-    der->attribSz = SetReqAttrib(der->attrib,
-                                 cert->challengePw, der->extensionsSz);
-    if (der->attribSz <= 0)
-        return REQ_ATTRIBUTE_E;
-
-    der->total = der->versionSz + der->subjectSz + der->publicKeySz +
-        der->extensionsSz + der->attribSz;
-
-    return 0;
-}
-
-
-/* write DER encoded cert req to buffer, size already checked */
-static int WriteCertReqBody(DerCert* der, byte* buffer)
-{
-    int idx;
-
-    /* signed part header */
-    idx = SetSequence(der->total, buffer);
-    /* version */
-    XMEMCPY(buffer + idx, der->version, der->versionSz);
-    idx += der->versionSz;
-    /* subject */
-    XMEMCPY(buffer + idx, der->subject, der->subjectSz);
-    idx += der->subjectSz;
-    /* public key */
-    XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
-    idx += der->publicKeySz;
-    /* attributes */
-    XMEMCPY(buffer + idx, der->attrib, der->attribSz);
-    idx += der->attribSz;
-    /* extensions */
-    if (der->extensionsSz) {
-        XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
-                                               (int)sizeof(der->extensions)));
-        idx += der->extensionsSz;
-    }
-
-    return idx;
-}
-
-
-static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
-                   RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK
-    DerCert* der;
-#else
-    DerCert der[1];
-#endif
-
-    cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY : RSA_KEY);
-
-#ifdef WOLFSSL_SMALL_STACK
-    der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap,
-                                                    DYNAMIC_TYPE_TMP_BUFFER);
-    if (der == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key);
-
-    if (ret == 0) {
-        if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
-            ret = BUFFER_E;
-        else
-            ret = cert->bodySz = WriteCertReqBody(der, derBuffer);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
-                      void* key)
-{
-    RsaKey* rsaKey = NULL;
-    ecc_key* eccKey = NULL;
-    ed25519_key* ed25519Key = NULL;
-
-    if (keyType == RSA_TYPE)
-        rsaKey = (RsaKey*)key;
-    else if (keyType == ECC_TYPE)
-        eccKey = (ecc_key*)key;
-    else if (keyType == ED25519_TYPE)
-        ed25519Key = (ed25519_key*)key;
-
-    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key);
-}
-
-int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
-                   RsaKey* rsaKey, ecc_key* eccKey)
-{
-    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL);
-}
-#endif /* WOLFSSL_CERT_REQ */
-
-
-static int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz,
-                    RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
-                    WC_RNG* rng)
-{
-    int sigSz = 0;
-    void* heap = NULL;
-    CertSignCtx* certSignCtx = NULL;
-#ifndef WOLFSSL_ASYNC_CRYPT
-    CertSignCtx  certSignCtx_lcl;
-    certSignCtx = &certSignCtx_lcl;
-    XMEMSET(certSignCtx, 0, sizeof(CertSignCtx));
-#endif
-
-    if (requestSz < 0)
-        return requestSz;
-
-    /* locate ctx */
-    if (rsaKey) {
-    #ifndef NO_RSA
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        certSignCtx = &rsaKey->certSignCtx;
-    #endif
-        heap = rsaKey->heap;
-    #else
-        return NOT_COMPILED_IN;
-    #endif /* NO_RSA */
-    }
-    else if (eccKey) {
-    #ifdef HAVE_ECC
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        certSignCtx = &eccKey->certSignCtx;
-    #endif
-        heap = eccKey->heap;
-    #else
-        return NOT_COMPILED_IN;
-    #endif /* HAVE_ECC */
-    }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (certSignCtx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-#endif
-
-    if (certSignCtx->sig == NULL) {
-        certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (certSignCtx->sig == NULL)
-            return MEMORY_E;
-    }
-
-    sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig,
-        MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, rng, sType, heap);
-    if (sigSz == WC_PENDING_E) {
-        /* Not free'ing certSignCtx->sig here because it could still be in use
-         * with async operations. */
-        return sigSz;
-    }
-
-    if (sigSz >= 0) {
-        if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
-            sigSz = BUFFER_E;
-        else
-            sigSz = AddSignature(buffer, requestSz, certSignCtx->sig, sigSz,
-                                 sType);
-    }
-
-    XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    certSignCtx->sig = NULL;
-
-    return sigSz;
-}
-
-int wc_SignCert_ex(int requestSz, int sType, byte* buffer, word32 buffSz,
-                   int keyType, void* key, WC_RNG* rng)
-{
-    RsaKey* rsaKey = NULL;
-    ecc_key* eccKey = NULL;
-    ed25519_key* ed25519Key = NULL;
-
-    if (keyType == RSA_TYPE)
-        rsaKey = (RsaKey*)key;
-    else if (keyType == ECC_TYPE)
-        eccKey = (ecc_key*)key;
-    else if (keyType == ED25519_TYPE)
-        ed25519Key = (ed25519_key*)key;
-
-    return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey,
-                    ed25519Key, rng);
-}
-
-int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz,
-                RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng)
-{
-    return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, NULL,
-                    rng);
-}
-
-int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz,
-                    RsaKey* key, WC_RNG* rng)
-{
-    int ret;
-
-    ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng);
-    if (ret < 0)
-        return ret;
-
-    return wc_SignCert(cert->bodySz, cert->sigType,
-                       buffer, buffSz, key, NULL, rng);
-}
-
-
-#ifdef WOLFSSL_CERT_EXT
-
-/* Set KID from public key */
-static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
-                                 byte *ntruKey, word16 ntruKeySz,
-                                 ed25519_key* ed25519Key, int kid_type)
-{
-    byte *buffer;
-    int   bufferSz, ret;
-
-    if (cert == NULL ||
-        (rsakey == NULL && eckey == NULL && ntruKey == NULL &&
-                                            ed25519Key == NULL) ||
-        (kid_type != SKID_TYPE && kid_type != AKID_TYPE))
-        return BAD_FUNC_ARG;
-
-    buffer = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (buffer == NULL)
-        return MEMORY_E;
-
-    /* Public Key */
-    bufferSz = -1;
-#ifndef NO_RSA
-    /* RSA public key */
-    if (rsakey != NULL)
-        bufferSz = SetRsaPublicKey(buffer, rsakey, MAX_PUBLIC_KEY_SZ, 0);
-#endif
-#ifdef HAVE_ECC
-    /* ECC public key */
-    if (eckey != NULL)
-        bufferSz = SetEccPublicKey(buffer, eckey, 0);
-#endif
-#ifdef HAVE_NTRU
-    /* NTRU public key */
-    if (ntruKey != NULL) {
-        bufferSz = MAX_PUBLIC_KEY_SZ;
-        ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
-                        ntruKeySz, ntruKey, (word16 *)(&bufferSz), buffer);
-        if (ret != NTRU_OK)
-            bufferSz = -1;
-    }
-#else
-    (void)ntruKeySz;
-#endif
-#ifdef HAVE_ED25519
-    /* ED25519 public key */
-    if (ed25519Key != NULL)
-        bufferSz = SetEd25519PublicKey(buffer, ed25519Key, 0);
-#endif
-
-    if (bufferSz <= 0) {
-        XFREE(buffer, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return PUBLIC_KEY_E;
-    }
-
-    /* Compute SKID by hashing public key */
-#ifdef NO_SHA
-    if (kid_type == SKID_TYPE) {
-        ret = wc_Sha256Hash(buffer, bufferSz, cert->skid);
-        cert->skidSz = WC_SHA256_DIGEST_SIZE;
-    }
-    else if (kid_type == AKID_TYPE) {
-        ret = wc_Sha256Hash(buffer, bufferSz, cert->akid);
-        cert->akidSz = WC_SHA256_DIGEST_SIZE;
-    }
-    else
-        ret = BAD_FUNC_ARG;
-#else /* NO_SHA */
-    if (kid_type == SKID_TYPE) {
-        ret = wc_ShaHash(buffer, bufferSz, cert->skid);
-        cert->skidSz = WC_SHA_DIGEST_SIZE;
-    }
-    else if (kid_type == AKID_TYPE) {
-        ret = wc_ShaHash(buffer, bufferSz, cert->akid);
-        cert->akidSz = WC_SHA_DIGEST_SIZE;
-    }
-    else
-        ret = BAD_FUNC_ARG;
-#endif /* NO_SHA */
-
-    XFREE(buffer, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return ret;
-}
-
-int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
-{
-    RsaKey* rsaKey = NULL;
-    ecc_key* eccKey = NULL;
-    ed25519_key* ed25519Key = NULL;
-
-    if (keyType == RSA_TYPE)
-        rsaKey = (RsaKey*)key;
-    else if (keyType == ECC_TYPE)
-        eccKey = (ecc_key*)key;
-    else if (keyType == ED25519_TYPE)
-        ed25519Key = (ed25519_key*)key;
-
-    return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
-                                 SKID_TYPE);
-}
-
-/* Set SKID from RSA or ECC public key */
-int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
-{
-    return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, SKID_TYPE);
-}
-
-#ifdef HAVE_NTRU
-/* Set SKID from NTRU public key */
-int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert,
-                                        byte *ntruKey, word16 ntruKeySz)
-{
-    return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL,
-                                 SKID_TYPE);
-}
-#endif
-
-int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
-{
-    RsaKey* rsaKey = NULL;
-    ecc_key* eccKey = NULL;
-    ed25519_key* ed25519Key = NULL;
-
-    if (keyType == RSA_TYPE)
-        rsaKey = (RsaKey*)key;
-    else if (keyType == ECC_TYPE)
-        eccKey = (ecc_key*)key;
-    else if (keyType == ED25519_TYPE)
-        ed25519Key = (ed25519_key*)key;
-
-    return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
-                                 AKID_TYPE);
-}
-
-/* Set SKID from RSA or ECC public key */
-int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
-{
-    return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, AKID_TYPE);
-}
-
-
-#ifndef NO_FILESYSTEM
-
-/* Set SKID from public key file in PEM */
-int wc_SetSubjectKeyId(Cert *cert, const char* file)
-{
-    int     ret, derSz;
-    byte*   der;
-    word32  idx;
-    RsaKey  *rsakey = NULL;
-    ecc_key *eckey = NULL;
-
-    if (cert == NULL || file == NULL)
-        return BAD_FUNC_ARG;
-
-    der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT);
-    if (der == NULL) {
-        WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem");
-        return MEMORY_E;
-    }
-
-    derSz = wc_PemPubKeyToDer(file, der, MAX_PUBLIC_KEY_SZ);
-    if (derSz <= 0)
-    {
-        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-        return derSz;
-    }
-
-    /* Load PubKey in internal structure */
-#ifndef NO_RSA
-    rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA);
-    if (rsakey == NULL) {
-        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-        return MEMORY_E;
-    }
-
-    if (wc_InitRsaKey(rsakey, cert->heap) != 0) {
-        WOLFSSL_MSG("wc_InitRsaKey failure");
-        XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
-        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-        return MEMORY_E;
-    }
-
-    idx = 0;
-    ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz);
-    if (ret != 0)
-#endif
-    {
-#ifndef NO_RSA
-        WOLFSSL_MSG("wc_RsaPublicKeyDecode failed");
-        wc_FreeRsaKey(rsakey);
-        XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
-        rsakey = NULL;
-#endif
-#ifdef HAVE_ECC
-        /* Check to load ecc public key */
-        eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap,
-                                                              DYNAMIC_TYPE_ECC);
-        if (eckey == NULL) {
-            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-            return MEMORY_E;
-        }
-
-        if (wc_ecc_init(eckey) != 0) {
-            WOLFSSL_MSG("wc_ecc_init failure");
-            wc_ecc_free(eckey);
-            XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
-            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-            return MEMORY_E;
-        }
-
-        idx = 0;
-        ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz);
-        if (ret != 0) {
-            WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
-            XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-            wc_ecc_free(eckey);
-            XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
-            return PUBLIC_KEY_E;
-        }
-#else
-        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-        return PUBLIC_KEY_E;
-#endif /* HAVE_ECC */
-    }
-
-    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-
-    ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey);
-
-#ifndef NO_RSA
-    wc_FreeRsaKey(rsakey);
-    XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
-#endif
-#ifdef HAVE_ECC
-    wc_ecc_free(eckey);
-    XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
-#endif
-    return ret;
-}
-
-#endif /* NO_FILESYSTEM */
-
-/* Set AKID from certificate contains in buffer (DER encoded) */
-int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz)
-{
-    int ret;
-
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* decoded;
-#else
-    DecodedCert decoded[1];
-#endif
-
-    if (cert == NULL || der == NULL || derSz <= 0)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
-                                    cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (decoded == NULL)
-        return MEMORY_E;
-#endif
-
-    /* decode certificate and get SKID that will be AKID of current cert */
-    InitDecodedCert(decoded, (byte*)der, derSz, NULL);
-    ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0);
-    if (ret != 0) {
-        FreeDecodedCert(decoded);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-        return ret;
-    }
-
-    /* Subject Key Id not found !! */
-    if (decoded->extSubjKeyIdSet == 0) {
-        FreeDecodedCert(decoded);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-        return ASN_NO_SKID;
-    }
-
-    /* SKID invalid size */
-    if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) {
-        FreeDecodedCert(decoded);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        #endif
-        return MEMORY_E;
-    }
-
-    /* Put the SKID of CA to AKID of certificate */
-    XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE);
-    cert->akidSz = KEYID_SIZE;
-
-    FreeDecodedCert(decoded);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-    return 0;
-}
-
-
-#ifndef NO_FILESYSTEM
-
-/* Set AKID from certificate file in PEM */
-int wc_SetAuthKeyId(Cert *cert, const char* file)
-{
-    int         ret;
-    int         derSz;
-    byte*       der;
-
-    if (cert == NULL || file == NULL)
-        return BAD_FUNC_ARG;
-
-    der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
-    if (der == NULL) {
-        WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem");
-        return MEMORY_E;
-    }
-
-    derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
-    if (derSz <= 0)
-    {
-        XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-        return derSz;
-    }
-
-    ret = wc_SetAuthKeyIdFromCert(cert, der, derSz);
-    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-
-    return ret;
-}
-
-#endif /* NO_FILESYSTEM */
-
-/* Set KeyUsage from human readable string */
-int wc_SetKeyUsage(Cert *cert, const char *value)
-{
-    int ret = 0;
-    char *token, *str, *ptr;
-    word32 len;
-
-    if (cert == NULL || value == NULL)
-        return BAD_FUNC_ARG;
-
-    cert->keyUsage = 0;
-
-    len = (word32)XSTRLEN(value);
-    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (str == NULL)
-        return MEMORY_E;
-
-    XSTRNCPY(str, value, len);
-    str[len] = '\0';
-
-    /* parse value, and set corresponding Key Usage value */
-    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
-        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return KEYUSAGE_E;
-    }
-    while (token != NULL)
-    {
-        len = (word32)XSTRLEN(token);
-
-        if (!XSTRNCASECMP(token, "digitalSignature", len))
-            cert->keyUsage |= KEYUSE_DIGITAL_SIG;
-        else if (!XSTRNCASECMP(token, "nonRepudiation", len) ||
-                 !XSTRNCASECMP(token, "contentCommitment", len))
-            cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
-        else if (!XSTRNCASECMP(token, "keyEncipherment", len))
-            cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
-        else if (!XSTRNCASECMP(token, "dataEncipherment", len))
-            cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
-        else if (!XSTRNCASECMP(token, "keyAgreement", len))
-            cert->keyUsage |= KEYUSE_KEY_AGREE;
-        else if (!XSTRNCASECMP(token, "keyCertSign", len))
-            cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
-        else if (!XSTRNCASECMP(token, "cRLSign", len))
-            cert->keyUsage |= KEYUSE_CRL_SIGN;
-        else if (!XSTRNCASECMP(token, "encipherOnly", len))
-            cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
-        else if (!XSTRNCASECMP(token, "decipherOnly", len))
-            cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
-        else {
-            ret = KEYUSAGE_E;
-            break;
-        }
-
-        token = XSTRTOK(NULL, ",", &ptr);
-    }
-
-    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return ret;
-}
-
-/* Set ExtendedKeyUsage from human readable string */
-int wc_SetExtKeyUsage(Cert *cert, const char *value)
-{
-    int ret = 0;
-    char *token, *str, *ptr;
-    word32 len;
-
-    if (cert == NULL || value == NULL)
-        return BAD_FUNC_ARG;
-
-    cert->extKeyUsage = 0;
-
-    len = (word32)XSTRLEN(value);
-    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (str == NULL)
-        return MEMORY_E;
-
-    XSTRNCPY(str, value, len);
-    str[len] = '\0';
-
-    /* parse value, and set corresponding Key Usage value */
-    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
-        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return EXTKEYUSAGE_E;
-    }
-
-    while (token != NULL)
-    {
-        len = (word32)XSTRLEN(token);
-
-        if (!XSTRNCASECMP(token, "any", len))
-            cert->extKeyUsage |= EXTKEYUSE_ANY;
-        else if (!XSTRNCASECMP(token, "serverAuth", len))
-            cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
-        else if (!XSTRNCASECMP(token, "clientAuth", len))
-            cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
-        else if (!XSTRNCASECMP(token, "codeSigning", len))
-            cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
-        else if (!XSTRNCASECMP(token, "emailProtection", len))
-            cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
-        else if (!XSTRNCASECMP(token, "timeStamping", len))
-            cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
-        else if (!XSTRNCASECMP(token, "OCSPSigning", len))
-            cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
-        else {
-            ret = EXTKEYUSAGE_E;
-            break;
-        }
-
-        token = XSTRTOK(NULL, ",", &ptr);
-    }
-
-    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    return ret;
-}
-
-#ifdef WOLFSSL_EKU_OID
-/*
- * cert structure to set EKU oid in
- * oid  the oid in byte representation
- * sz   size of oid buffer
- * idx  index of array to place oid
- *
- * returns 0 on success
- */
-int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx,
-        void* heap)
-{
-    byte oid[MAX_OID_SZ];
-    word32 oidSz = MAX_OID_SZ;
-
-    if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) {
-        WOLFSSL_MSG("Either idx or sz was too large");
-        return BAD_FUNC_ARG;
-    }
-
-    if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) {
-        return BUFFER_E;
-    }
-
-    XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz);
-    cert->extKeyUsageOIDSz[idx] = oidSz;
-    cert->extKeyUsage |= EXTKEYUSE_USER;
-
-    return 0;
-}
-#endif /* WOLFSSL_EKU_OID */
-#endif /* WOLFSSL_CERT_EXT */
-
-
-#ifdef WOLFSSL_ALT_NAMES
-
-/* Set Alt Names from der cert, return 0 on success */
-static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* decoded;
-#else
-    DecodedCert decoded[1];
-#endif
-
-    if (derSz < 0)
-        return derSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (decoded == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(decoded, (byte*)der, derSz, NULL);
-    ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
-
-    if (ret < 0) {
-        WOLFSSL_MSG("ParseCertRelative error");
-    }
-    else if (decoded->extensions) {
-        byte   b;
-        int    length;
-        word32 maxExtensionsIdx;
-
-        decoded->srcIdx = decoded->extensionsIdx;
-        b = decoded->source[decoded->srcIdx++];
-
-        if (b != 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;
-            }
-        }
-    }
-
-    FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret < 0 ? ret : 0;
-}
-
-
-/* Set Dates from der cert, return 0 on success */
-static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* decoded;
-#else
-    DecodedCert decoded[1];
-#endif
-
-    WOLFSSL_ENTER("SetDatesFromCert");
-    if (derSz < 0)
-        return derSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (decoded == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(decoded, (byte*)der, derSz, NULL);
-    ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
-
-    if (ret < 0) {
-        WOLFSSL_MSG("ParseCertRelative error");
-    }
-    else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
-        WOLFSSL_MSG("Couldn't extract dates");
-        ret = -1;
-    }
-    else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
-                                        decoded->afterDateLen > MAX_DATE_SIZE) {
-        WOLFSSL_MSG("Bad date size");
-        ret = -1;
-    }
-    else {
-        XMEMCPY(cert->beforeDate, decoded->beforeDate, decoded->beforeDateLen);
-        XMEMCPY(cert->afterDate,  decoded->afterDate,  decoded->afterDateLen);
-
-        cert->beforeDateSz = decoded->beforeDateLen;
-        cert->afterDateSz  = decoded->afterDateLen;
-    }
-
-    FreeDecodedCert(decoded);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret < 0 ? ret : 0;
-}
-
-#endif /* WOLFSSL_ALT_NAMES */
-
-/* Set cn name from der buffer, return 0 on success */
-static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
-{
-    int ret, sz;
-#ifdef WOLFSSL_SMALL_STACK
-    DecodedCert* decoded;
-#else
-    DecodedCert decoded[1];
-#endif
-
-    if (derSz < 0)
-        return derSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (decoded == NULL)
-        return MEMORY_E;
-#endif
-
-    InitDecodedCert(decoded, (byte*)der, derSz, NULL);
-    ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
-
-    if (ret < 0) {
-        WOLFSSL_MSG("ParseCertRelative error");
-    }
-    else {
-        if (decoded->subjectCN) {
-            sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
-                                                         : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE);
-            cn->commonName[sz] = '\0';
-            cn->commonNameEnc = decoded->subjectCNEnc;
-        }
-        if (decoded->subjectC) {
-            sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
-                                                        : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->country, decoded->subjectC, CTC_NAME_SIZE);
-            cn->country[sz] = '\0';
-            cn->countryEnc = decoded->subjectCEnc;
-        }
-        if (decoded->subjectST) {
-            sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
-                                                         : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->state, decoded->subjectST, CTC_NAME_SIZE);
-            cn->state[sz] = '\0';
-            cn->stateEnc = decoded->subjectSTEnc;
-        }
-        if (decoded->subjectL) {
-            sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
-                                                        : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->locality, decoded->subjectL, CTC_NAME_SIZE);
-            cn->locality[sz] = '\0';
-            cn->localityEnc = decoded->subjectLEnc;
-        }
-        if (decoded->subjectO) {
-            sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
-                                                        : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->org, decoded->subjectO, CTC_NAME_SIZE);
-            cn->org[sz] = '\0';
-            cn->orgEnc = decoded->subjectOEnc;
-        }
-        if (decoded->subjectOU) {
-            sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
-                                                         : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->unit, decoded->subjectOU, CTC_NAME_SIZE);
-            cn->unit[sz] = '\0';
-            cn->unitEnc = decoded->subjectOUEnc;
-        }
-        if (decoded->subjectSN) {
-            sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
-                                                         : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->sur, decoded->subjectSN, CTC_NAME_SIZE);
-            cn->sur[sz] = '\0';
-            cn->surEnc = decoded->subjectSNEnc;
-        }
-        if (decoded->subjectEmail) {
-            sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
-               ?  decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
-            XSTRNCPY(cn->email, decoded->subjectEmail, CTC_NAME_SIZE);
-            cn->email[sz] = '\0';
-        }
-    }
-
-    FreeDecodedCert(decoded);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret < 0 ? ret : 0;
-}
-
-
-#ifndef NO_FILESYSTEM
-
-/* Set cert issuer from issuerFile in PEM */
-int wc_SetIssuer(Cert* cert, const char* issuerFile)
-{
-    int         ret;
-    int         derSz;
-    byte*       der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
-
-    if (der == NULL) {
-        WOLFSSL_MSG("wc_SetIssuer OOF Problem");
-        return MEMORY_E;
-    }
-    derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF);
-    cert->selfSigned = 0;
-    ret = SetNameFromCert(&cert->issuer, der, derSz);
-    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-
-    return ret;
-}
-
-
-/* Set cert subject from subjectFile in PEM */
-int wc_SetSubject(Cert* cert, const char* subjectFile)
-{
-    int         ret;
-    int         derSz;
-    byte*       der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
-
-    if (der == NULL) {
-        WOLFSSL_MSG("wc_SetSubject OOF Problem");
-        return MEMORY_E;
-    }
-    derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF);
-    ret = SetNameFromCert(&cert->subject, der, derSz);
-    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_ALT_NAMES
-
-/* Set alt names from file in PEM */
-int wc_SetAltNames(Cert* cert, const char* file)
-{
-    int         ret;
-    int         derSz;
-    byte*       der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
-
-    if (der == NULL) {
-        WOLFSSL_MSG("wc_SetAltNames OOF Problem");
-        return MEMORY_E;
-    }
-    derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
-    ret = SetAltNamesFromCert(cert, der, derSz);
-    XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
-
-    return ret;
-}
-
-#endif /* WOLFSSL_ALT_NAMES */
-
-#endif /* NO_FILESYSTEM */
-
-/* Set cert issuer from DER buffer */
-int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
-{
-    cert->selfSigned = 0;
-    return SetNameFromCert(&cert->issuer, der, derSz);
-}
-
-
-/* Set cert subject from DER buffer */
-int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
-{
-    return SetNameFromCert(&cert->subject, der, derSz);
-}
-
-
-#ifdef WOLFSSL_ALT_NAMES
-
-/* Set cert alt names from DER buffer */
-int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
-{
-    return SetAltNamesFromCert(cert, der, derSz);
-}
-
-/* Set cert dates from DER buffer */
-int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
-{
-    return SetDatesFromCert(cert, der, derSz);
-}
-
-#endif /* WOLFSSL_ALT_NAMES */
-
-#endif /* WOLFSSL_CERT_GEN */
-
-
-#ifdef HAVE_ECC
-
-/* Der Encode r & s ints into out, outLen is (in/out) size */
-int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
-{
-    word32 idx = 0;
-    int    rSz;                           /* encoding size */
-    int    sSz;
-    word32 headerSz = 4;   /* 2*ASN_TAG + 2*LEN(ENUM) */
-
-    /* If the leading bit on the INTEGER is a 1, add a leading zero */
-    int rLeadingZero = mp_leading_bit(r);
-    int sLeadingZero = mp_leading_bit(s);
-    int rLen = mp_unsigned_bin_size(r);   /* big int size */
-    int sLen = mp_unsigned_bin_size(s);
-
-    if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero +
-                   headerSz + 2))  /* SEQ_TAG + LEN(ENUM) */
-        return BUFFER_E;
-
-    idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out);
-
-    /* store r */
-    rSz = SetASNIntMP(r, -1, &out[idx]);
-    if (rSz < 0)
-        return rSz;
-    idx += rSz;
-
-    /* store s */
-    sSz = SetASNIntMP(s, -1, &out[idx]);
-    if (sSz < 0)
-        return sSz;
-    idx += sSz;
-
-    *outLen = idx;
-
-    return 0;
-}
-
-
-/* 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)
-{
-    word32 idx = 0;
-    int    len = 0;
-
-    if (GetSequence(sig, &idx, &len, sigLen) < 0) {
-        return ASN_ECC_KEY_E;
-    }
-
-    if ((word32)len > (sigLen - idx)) {
-        return ASN_ECC_KEY_E;
-    }
-
-    if (GetInt(r, sig, &idx, sigLen) < 0) {
-        return ASN_ECC_KEY_E;
-    }
-
-    if (GetInt(s, sig, &idx, sigLen) < 0) {
-        return ASN_ECC_KEY_E;
-    }
-
-    return 0;
-}
-
-
-int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
-                        word32 inSz)
-{
-    word32 oidSum;
-    int    version, length;
-    int    privSz, pubSz = 0;
-    byte   b;
-    int    ret = 0;
-    int    curve_id = ECC_CURVE_DEF;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* priv;
-    byte* pub;
-#else
-    byte priv[ECC_MAXSIZE+1];
-    byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */
-#endif
-    byte* pubData = NULL;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (*inOutIdx >= inSz)
-        return ASN_PARSE_E;
-
-    b = input[*inOutIdx];
-    *inOutIdx += 1;
-
-    /* priv type */
-    if (b != 4 && b != 6 && b != 7)
-        return ASN_PARSE_E;
-
-    if (GetLength(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length > ECC_MAXSIZE)
-        return BUFFER_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    priv = (byte*)XMALLOC(ECC_MAXSIZE+1, 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;
-
-    if (ret == 0 && (*inOutIdx + 1) < inSz) {
-        /* prefix 0, may have */
-        b = input[*inOutIdx];
-        if (b == ECC_PREFIX_0) {
-            *inOutIdx += 1;
-
-            if (GetLength(input, inOutIdx, &length, inSz) <= 0)
-                ret = ASN_PARSE_E;
-            else {
-                ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType,
-                                  inSz);
-                if (ret == 0) {
-                    if ((ret = CheckCurve(oidSum)) < 0)
-                        ret = ECC_CURVE_OID_E;
-                    else {
-                        curve_id = ret;
-                        ret = 0;
-                    }
-                }
-            }
-        }
-    }
-
-    if (ret == 0 && (*inOutIdx + 1) < inSz) {
-        /* prefix 1 */
-        b = input[*inOutIdx];
-        *inOutIdx += 1;
-
-        if (b != ECC_PREFIX_1) {
-            ret = ASN_ECC_KEY_E;
-        }
-        else if (GetLength(input, inOutIdx, &length, inSz) <= 0) {
-            ret = ASN_PARSE_E;
-        }
-        else {
-            /* key header */
-            ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL);
-            if (ret == 0) {
-                /* pub key */
-                pubSz = length;
-                if (pubSz < 2*(ECC_MAXSIZE+1)) {
-                    XMEMCPY(pub, &input[*inOutIdx], pubSz);
-                    *inOutIdx += length;
-                    pubData = pub;
-                }
-                else
-                    ret = BUFFER_E;
-            }
-        }
-    }
-
-    if (ret == 0) {
-        ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key,
-                                                                      curve_id);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(pub,  key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-static void ByteToHex(byte n, char* str)
-{
-    static const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
-                                    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
-    str[0] = hexChar[n >> 4];
-    str[1] = hexChar[n & 0xf];
-}
-
-/* returns 0 on success */
-static int ASNToHexString(const byte* input, word32* inOutIdx, char** out,
-                          word32 inSz, void* heap, int heapType)
-{
-    int len;
-    int i;
-    char* str;
-
-    if (*inOutIdx >= inSz) {
-        return BUFFER_E;
-    }
-
-    if (input[*inOutIdx] == ASN_INTEGER) {
-        if (GetASNInt(input, inOutIdx, &len, inSz) < 0)
-            return ASN_PARSE_E;
-    }
-    else {
-        if (GetOctetString(input, inOutIdx, &len, inSz) < 0)
-            return ASN_PARSE_E;
-    }
-
-    str = (char*)XMALLOC(len * 2 + 1, heap, heapType);
-    for (i=0; i<len; i++)
-        ByteToHex(input[*inOutIdx + i], str + i*2);
-    str[len*2] = '\0';
-
-    *inOutIdx += len;
-    *out = str;
-
-    return 0;
-}
-#endif
-
-int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
-                          ecc_key* key, word32 inSz)
-{
-    int    length;
-    int    ret;
-    int    curve_id = ECC_CURVE_DEF;
-    word32 oidSum;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        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;
-
-    if (*inOutIdx >= inSz) {
-        return BUFFER_E;
-    }
-
-    if (input[*inOutIdx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
-#ifdef WOLFSSL_CUSTOM_CURVES
-        ecc_set_type* curve;
-        int len;
-        char* point;
-
-        ret = 0;
-
-        curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap,
-                                                       DYNAMIC_TYPE_ECC_BUFFER);
-        if (curve == NULL)
-            ret = MEMORY_E;
-
-        if (ret == 0) {
-            XMEMSET(curve, 0, sizeof(*curve));
-            curve->name = "Custom";
-            curve->id = ECC_CURVE_CUSTOM;
-
-            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-                ret = ASN_PARSE_E;
-        }
-
-        if (ret == 0) {
-            GetInteger7Bit(input, inOutIdx, inSz);
-            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-                ret = ASN_PARSE_E;
-        }
-        if (ret == 0) {
-            SkipObjectId(input, inOutIdx, inSz);
-            ret = ASNToHexString(input, inOutIdx, (char**)&curve->prime, inSz,
-                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-        }
-        if (ret == 0) {
-            curve->size = (int)XSTRLEN(curve->prime) / 2;
-
-            if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-                ret = ASN_PARSE_E;
-        }
-        if (ret == 0) {
-            ret = ASNToHexString(input, inOutIdx, (char**)&curve->Af, inSz,
-                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-        }
-        if (ret == 0) {
-            ret = ASNToHexString(input, inOutIdx, (char**)&curve->Bf, inSz,
-                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-        }
-        if (ret == 0) {
-            if (*inOutIdx < inSz && input[*inOutIdx] == ASN_BIT_STRING) {
-                len = 0;
-                ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz);
-                *inOutIdx += len;
-            }
-        }
-        if (ret == 0) {
-            ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz,
-                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-
-            /* sanity check that point buffer is not smaller than the expected
-             * size to hold ( 0 4 || Gx || Gy )
-             * where Gx and Gy are each the size of curve->size * 2 */
-            if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) {
-                XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-                ret = BUFFER_E;
-            }
-        }
-        if (ret == 0) {
-            curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
-                                                       DYNAMIC_TYPE_ECC_BUFFER);
-            curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
-                                                       DYNAMIC_TYPE_ECC_BUFFER);
-            if (curve->Gx == NULL || curve->Gy == NULL) {
-                XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-                ret = MEMORY_E;
-            }
-        }
-        if (ret == 0) {
-            XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2);
-            XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2,
-                                                               curve->size * 2);
-            ((char*)curve->Gx)[curve->size * 2] = '\0';
-            ((char*)curve->Gy)[curve->size * 2] = '\0';
-            XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-            ret = ASNToHexString(input, inOutIdx, (char**)&curve->order, inSz,
-                                            key->heap, DYNAMIC_TYPE_ECC_BUFFER);
-        }
-        if (ret == 0) {
-            curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz);
-
-            curve->oid = NULL;
-            curve->oidSz = 0;
-            curve->oidSum = 0;
-
-            if (wc_ecc_set_custom_curve(key, curve) < 0) {
-                ret = ASN_PARSE_E;
-            }
-            key->deallocSet = 1;
-            curve = NULL;
-        }
-        if (curve != NULL)
-            wc_ecc_free_curve(curve, key->heap);
-
-        if (ret < 0)
-            return ret;
-#else
-        return ASN_PARSE_E;
-#endif
-    }
-    else {
-        /* ecc params information */
-        ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz);
-        if (ret != 0)
-            return ret;
-
-        /* get curve id */
-        curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
-        if (curve_id < 0)
-            return ECC_CURVE_OID_E;
-    }
-
-    /* key header */
-    ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
-    if (ret != 0)
-        return ret;
-
-    /* This is the raw point data compressed or uncompressed. */
-    if (wc_ecc_import_x963_ex(input + *inOutIdx, inSz - *inOutIdx, key,
-                                                            curve_id) != 0) {
-        return ASN_ECC_KEY_E;
-    }
-
-    return 0;
-}
-
-
-/* build DER formatted ECC key, include optional public key if requested,
- * return length on success, negative on error */
-static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
-                             int pubIn)
-{
-    byte   curve[MAX_ALGO_SZ+2];
-    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;
-
-    word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0;
-    word32 seqSz, privSz, pubSz = ECC_BUFSIZE;
-
-    if (key == NULL || output == NULL || inLen == 0)
-        return BAD_FUNC_ARG;
-
-    /* curve */
-    curve[curveidx++] = ECC_PREFIX_0;
-    curveidx++ /* to put the size after computation */;
-    curveSz = SetCurve(key, curve+curveidx);
-    if (curveSz < 0)
-        return curveSz;
-    /* set computed size */
-    curve[1] = (byte)curveSz;
-    curveidx += curveSz;
-
-    /* private */
-    privSz = key->dp->size;
-    prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
-                         key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (prv == NULL) {
-        return MEMORY_E;
-    }
-    prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
-    ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
-    if (ret < 0) {
-        XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-    prvidx += privSz;
-
-    /* pubIn */
-    if (pubIn) {
-        ret = wc_ecc_export_x963(key, NULL, &pubSz);
-        if (ret != LENGTH_ONLY_E) {
-            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return ret;
-        }
-
-        pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ,
-                             key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (pub == NULL) {
-            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return MEMORY_E;
-        }
-
-        pub[pubidx++] = ECC_PREFIX_1;
-        if (pubSz > 128) /* leading zero + extra size byte */
-            pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx);
-        else /* leading zero */
-            pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx);
-
-        /* SetBitString adds leading zero */
-        pubidx += SetBitString(pubSz, 0, pub + pubidx);
-        ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz);
-        if (ret != 0) {
-            XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return ret;
-        }
-        pubidx += pubSz;
-    }
-
-    /* make headers */
-    verSz = SetMyVersion(1, ver, FALSE);
-    seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq);
-
-    totalSz = prvidx + pubidx + curveidx + verSz + seqSz;
-    if (totalSz > (int)inLen) {
-        XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (pubIn) {
-            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        }
-        return BAD_FUNC_ARG;
-    }
-
-    /* write out */
-    /* seq */
-    XMEMCPY(output + idx, seq, seqSz);
-    idx = seqSz;
-
-    /* ver */
-    XMEMCPY(output + idx, ver, verSz);
-    idx += verSz;
-
-    /* private */
-    XMEMCPY(output + idx, prv, prvidx);
-    idx += prvidx;
-    XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    /* curve */
-    XMEMCPY(output + idx, curve, curveidx);
-    idx += curveidx;
-
-    /* pubIn */
-    if (pubIn) {
-        XMEMCPY(output + idx, pub, pubidx);
-        /* idx += pubidx;  not used after write, if more data remove comment */
-        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return totalSz;
-}
-
-
-/* Write a Private ecc key, including public to DER format,
- * length on success else < 0 */
-int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
-{
-    return wc_BuildEccKeyDer(key, output, inLen, 1);
-}
-
-
-/* Write only private ecc key to DER format,
- * length on success else < 0 */
-int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen)
-{
-    return wc_BuildEccKeyDer(key, output, inLen, 0);
-}
-
-/* Write only private ecc key to unencrypted PKCS#8 format.
- *
- * If output is NULL, places required PKCS#8 buffer size in outLen and
- * returns LENGTH_ONLY_E.
- *
- * return length on success else < 0 */
-int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
-{
-    int ret, tmpDerSz;
-    int algoID = 0;
-    word32 oidSz = 0;
-    word32 pkcs8Sz = 0;
-    const byte* curveOID = NULL;
-    byte* tmpDer = NULL;
-
-    if (key == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    /* set algoID, get curve OID */
-    algoID = ECDSAk;
-    ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz);
-    if (ret < 0)
-        return ret;
-
-    /* temp buffer for plain DER key */
-    tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (tmpDer == NULL)
-        return MEMORY_E;
-
-    XMEMSET(tmpDer, 0, ECC_BUFSIZE);
-
-    tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0);
-    if (tmpDerSz < 0) {
-        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return tmpDerSz;
-    }
-
-    /* get pkcs8 expected output size */
-    ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID,
-                            curveOID, oidSz);
-    if (ret != LENGTH_ONLY_E) {
-        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-
-    if (output == NULL) {
-        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        *outLen = pkcs8Sz;
-        return LENGTH_ONLY_E;
-
-    } else if (*outLen < pkcs8Sz) {
-        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key");
-        return BUFFER_E;
-    }
-
-    ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz,
-                            algoID, curveOID, oidSz);
-    if (ret < 0) {
-        XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-
-    XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    *outLen = ret;
-    return ret;
-}
-
-#endif  /* HAVE_ECC */
-
-
-#ifdef HAVE_ED25519
-
-int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
-                               ed25519_key* key, word32 inSz)
-{
-    word32      oid;
-    int         ret, version, length, endKeyIdx, privSz, pubSz;
-    const byte* priv;
-    const byte* pub;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
-        endKeyIdx = *inOutIdx + length;
-
-        if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
-            return ASN_PARSE_E;
-        if (version != 0) {
-            WOLFSSL_MSG("Unrecognized version of ED25519 private key");
-            return ASN_PARSE_E;
-        }
-
-        if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
-            return ASN_PARSE_E;
-        if (oid != ED25519k)
-            return ASN_PARSE_E;
-
-        if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
-            return ASN_PARSE_E;
-
-        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
-            return ASN_PARSE_E;
-
-        priv = input + *inOutIdx;
-        *inOutIdx += privSz;
-    }
-    else {
-        if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
-            return ASN_PARSE_E;
-
-        priv = input + *inOutIdx;
-        *inOutIdx += privSz;
-        endKeyIdx = *inOutIdx;
-    }
-
-    if (endKeyIdx == (int)*inOutIdx) {
-        ret = wc_ed25519_import_private_only(priv, privSz, key);
-    }
-    else {
-        if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
-                         inOutIdx, &length, inSz) < 0) {
-            return ASN_PARSE_E;
-        }
-        if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
-            return ASN_PARSE_E;
-        pub = input + *inOutIdx;
-        *inOutIdx += pubSz;
-
-        ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key);
-    }
-    if (ret == 0 && endKeyIdx != (int)*inOutIdx)
-        return ASN_PARSE_E;
-
-    return ret;
-}
-
-
-int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
-                              ed25519_key* key, word32 inSz)
-{
-    int    length;
-    int    ret;
-
-    if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        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;
-
-    /* key header */
-    ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
-    if (ret != 0)
-        return ret;
-
-    /* This is the raw point data compressed or uncompressed. */
-    if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
-        return ASN_ECC_KEY_E;
-
-    return 0;
-}
-
-
-#ifdef WOLFSSL_KEY_GEN
-
-/* build DER formatted ED25519 key,
- * return length on success, negative on error */
-static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen,
-                                 int pubOut)
-{
-    byte   algoArray[MAX_ALGO_SZ];
-    byte   ver[MAX_VERSION_SZ];
-    byte   seq[MAX_SEQ_SZ];
-    int    ret;
-    word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
-
-    if (key == NULL || output == NULL || inLen == 0)
-        return BAD_FUNC_ARG;
-
-    if (pubOut)
-        pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE;
-    privSz = 2 + 2 + ED25519_KEY_SIZE;
-    algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0);
-    verSz  = SetMyVersion(0, ver, FALSE);
-    seqSz  = SetSequence(verSz + algoSz + privSz + pubSz, seq);
-
-    if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
-        return BAD_FUNC_ARG;
-
-    /* write out */
-    /* seq */
-    XMEMCPY(output + idx, seq, seqSz);
-    idx = seqSz;
-    /* ver */
-    XMEMCPY(output + idx, ver, verSz);
-    idx += verSz;
-    /* algo */
-    XMEMCPY(output + idx, algoArray, algoSz);
-    idx += algoSz;
-    /* privKey */
-    idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx);
-    idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
-    ret = wc_ed25519_export_private_only(key, output + idx, &privSz);
-    if (ret != 0)
-        return ret;
-    idx += privSz;
-    /* pubKey */
-    if (pubOut) {
-        idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx);
-        idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
-        ret = wc_ed25519_export_public(key, output + idx, &pubSz);
-        if (ret != 0)
-            return ret;
-        idx += pubSz;
-    }
-
-    return idx;
-}
-
-/* Write a Private ecc key, including public to DER format,
- * length on success else < 0 */
-int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen)
-{
-    return wc_BuildEd25519KeyDer(key, output, inLen, 1);
-}
-
-
-
-/* Write only private ecc key to DER format,
- * length on success else < 0 */
-int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen)
-{
-    return wc_BuildEd25519KeyDer(key, output, inLen, 0);
-}
-
-#endif /* WOLFSSL_KEY_GEN */
-
-#endif  /* HAVE_ED25519 */
-
-
-#if defined(HAVE_OCSP) || defined(HAVE_CRL)
-
-/* Get raw Date only, no processing, 0 on success */
-static int GetBasicDate(const byte* source, word32* idx, byte* date,
-                        byte* format, int maxIdx)
-{
-    int    ret, length;
-    const byte *datePtr = NULL;
-
-    WOLFSSL_ENTER("GetBasicDate");
-
-    ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx);
-    if (ret < 0)
-        return ret;
-
-    XMEMCPY(date, datePtr, length);
-
-    return 0;
-}
-
-#endif
-
-
-#ifdef HAVE_OCSP
-
-static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
-{
-    word32 idx = *inOutIdx;
-    word32 len;
-
-    WOLFSSL_ENTER("GetEnumerated");
-
-    *value = 0;
-
-    if (input[idx++] != ASN_ENUMERATED)
-        return ASN_PARSE_E;
-
-    len = input[idx++];
-    if (len > 4)
-        return ASN_PARSE_E;
-
-    while (len--) {
-        *value  = *value << 8 | input[idx++];
-    }
-
-    *inOutIdx = idx;
-
-    return *value;
-}
-
-
-static int DecodeSingleResponse(byte* source,
-                            word32* ioIndex, OcspResponse* resp, word32 size)
-{
-    word32 idx = *ioIndex, prevIndex, oid;
-    int length, wrapperSz;
-    CertStatus* cs = resp->status;
-    int ret;
-
-    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 */
-    if (GetSequence(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-
-    /* Wrapper around the CertID */
-    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;
-    /* Save reference to the hash of CN */
-    ret = GetOctetString(source, &idx, &length, size);
-    if (ret < 0)
-        return ret;
-    resp->issuerHash = source + idx;
-    idx += length;
-    /* Save reference to the hash of the issuer public key */
-    ret = GetOctetString(source, &idx, &length, size);
-    if (ret < 0)
-        return ret;
-    resp->issuerKeyHash = source + idx;
-    idx += length;
-
-    /* Get serial number */
-    if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0)
-        return ASN_PARSE_E;
-
-    /* CertStatus */
-    switch (source[idx++])
-    {
-        case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
-            cs->status = CERT_GOOD;
-            idx++;
-            break;
-        case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
-            cs->status = CERT_REVOKED;
-            if (GetLength(source, &idx, &length, size) < 0)
-                return ASN_PARSE_E;
-            idx += length;
-            break;
-        case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
-            cs->status = CERT_UNKNOWN;
-            idx++;
-            break;
-        default:
-            return ASN_PARSE_E;
-    }
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    cs->thisDateAsn = source + idx;
-#endif
-    if (GetBasicDate(source, &idx, cs->thisDate,
-                                                &cs->thisDateFormat, size) < 0)
-        return ASN_PARSE_E;
-
-#ifndef NO_ASN_TIME
-    if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
-        return ASN_BEFORE_DATE_E;
-#endif
-
-    /* The following items are optional. Only check for them if there is more
-     * unprocessed data in the singleResponse wrapper. */
-
-    if (((int)(idx - prevIndex) < wrapperSz) &&
-        (source[idx] == (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)
-        cs->nextDateAsn = source + idx;
-#endif
-        if (GetBasicDate(source, &idx, cs->nextDate,
-                                                &cs->nextDateFormat, size) < 0)
-            return ASN_PARSE_E;
-
-#ifndef NO_ASN_TIME
-        if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER))
-            return ASN_AFTER_DATE_E;
-#endif
-    }
-    if (((int)(idx - prevIndex) < wrapperSz) &&
-        (source[idx] == (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 DecodeOcspRespExtensions(byte* source,
-                            word32* ioIndex, OcspResponse* resp, word32 sz)
-{
-    word32 idx = *ioIndex;
-    int length;
-    int ext_bound; /* boundary index for the sequence of extensions */
-    word32 oid;
-    int ret;
-
-    WOLFSSL_ENTER("DecodeOcspRespExtensions");
-
-    if ((idx + 1) > sz)
-        return BUFFER_E;
-
-    if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
-        return ASN_PARSE_E;
-
-    if (GetLength(source, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetSequence(source, &idx, &length, sz) < 0)
-        return ASN_PARSE_E;
-
-    ext_bound = idx + length;
-
-    while (idx < (word32)ext_bound) {
-        if (GetSequence(source, &idx, &length, sz) < 0) {
-            WOLFSSL_MSG("\tfail: should be a SEQUENCE");
-            return ASN_PARSE_E;
-        }
-
-        oid = 0;
-        if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) {
-            WOLFSSL_MSG("\tfail: OBJECT ID");
-            return ASN_PARSE_E;
-        }
-
-        /* check for critical flag */
-        if (source[idx] == ASN_BOOLEAN) {
-            WOLFSSL_MSG("\tfound optional critical flag, moving past");
-            ret = GetBoolean(source, &idx, sz);
-            if (ret < 0)
-                return ret;
-        }
-
-        ret = GetOctetString(source, &idx, &length, sz);
-        if (ret < 0)
-            return ret;
-
-        if (oid == OCSP_NONCE_OID) {
-            /* get data inside extra OCTET_STRING */
-            ret = GetOctetString(source, &idx, &length, sz);
-            if (ret < 0)
-                return ret;
-
-            resp->nonce = source + idx;
-            resp->nonceSz = length;
-        }
-
-        idx += length;
-    }
-
-    *ioIndex = idx;
-    return 0;
-}
-
-
-static int DecodeResponseData(byte* source,
-                            word32* ioIndex, OcspResponse* resp, word32 size)
-{
-    word32 idx = *ioIndex, prev_idx;
-    int length;
-    int version;
-    word32 responderId = 0;
-
-    WOLFSSL_ENTER("DecodeResponseData");
-
-    resp->response = source + idx;
-    prev_idx = idx;
-    if (GetSequence(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-    resp->responseSz = length + idx - prev_idx;
-
-    /* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
-     * item isn't an EXPLICIT[0], then set version to zero and move
-     * onto the next item.
-     */
-    if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
-    {
-        idx += 2; /* Eat the value and length */
-        if (GetMyVersion(source, &idx, &version, size) < 0)
-            return ASN_PARSE_E;
-    } else
-        version = 0;
-
-    responderId = source[idx++];
-    if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
-        (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
-    {
-        if (GetLength(source, &idx, &length, size) < 0)
-            return ASN_PARSE_E;
-        idx += length;
-    }
-    else
-        return ASN_PARSE_E;
-
-    /* save pointer to the producedAt time */
-    if (GetBasicDate(source, &idx, resp->producedDate,
-                                        &resp->producedDateFormat, size) < 0)
-        return ASN_PARSE_E;
-
-    if (DecodeSingleResponse(source, &idx, resp, size) < 0)
-        return ASN_PARSE_E;
-
-    /*
-     * Check the length of the ResponseData against the current index to
-     * see if there are extensions, they are optional.
-     */
-    if (idx - prev_idx < resp->responseSz)
-        if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
-            return ASN_PARSE_E;
-
-    *ioIndex = idx;
-    return 0;
-}
-
-
-#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
-
-static int DecodeCerts(byte* source,
-                            word32* ioIndex, OcspResponse* resp, word32 size)
-{
-    word32 idx = *ioIndex;
-
-    WOLFSSL_ENTER("DecodeCerts");
-
-    if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
-    {
-        int length;
-
-        if (GetLength(source, &idx, &length, size) < 0)
-            return ASN_PARSE_E;
-
-        if (GetSequence(source, &idx, &length, size) < 0)
-            return ASN_PARSE_E;
-
-        resp->cert = source + idx;
-        resp->certSz = length;
-
-        idx += length;
-    }
-    *ioIndex = idx;
-    return 0;
-}
-
-#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
-
-
-static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
-            OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
-{
-    int    length;
-    word32 idx = *ioIndex;
-    word32 end_index;
-    int    ret;
-    int    sigLength;
-
-    WOLFSSL_ENTER("DecodeBasicOcspResponse");
-    (void)heap;
-
-    if (GetSequence(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-
-    if (idx + length > size)
-        return ASN_INPUT_E;
-    end_index = idx + length;
-
-    if (DecodeResponseData(source, &idx, resp, size) < 0)
-        return ASN_PARSE_E;
-
-    /* Get the signature algorithm */
-    if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0)
-        return ASN_PARSE_E;
-
-    ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL);
-    if (ret != 0)
-        return ret;
-
-    resp->sigSz = sigLength;
-    resp->sig = source + idx;
-    idx += sigLength;
-
-    /*
-     * Check the length of the BasicOcspResponse against the current index to
-     * see if there are certificates, they are optional.
-     */
-#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
-    if (idx < end_index)
-    {
-        DecodedCert cert;
-
-        if (DecodeCerts(source, &idx, resp, size) < 0)
-            return ASN_PARSE_E;
-
-        InitDecodedCert(&cert, resp->cert, resp->certSz, heap);
-
-        /* Don't verify if we don't have access to Cert Manager. */
-        ret = ParseCertRelative(&cert, CERT_TYPE,
-                                noVerify ? NO_VERIFY : VERIFY_OCSP, cm);
-        if (ret < 0) {
-            WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
-            FreeDecodedCert(&cert);
-            return ret;
-        }
-
-#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
-        if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
-            if (XMEMCMP(cert.subjectHash,
-                        resp->issuerHash, KEYID_SIZE) == 0) {
-                WOLFSSL_MSG("\tOCSP Response signed by issuer");
-            }
-            else {
-                WOLFSSL_MSG("\tOCSP Responder key usage check failed");
-    #ifdef OPENSSL_EXTRA
-                resp->verifyError = OCSP_BAD_ISSUER;
-    #else
-                FreeDecodedCert(&cert);
-                return BAD_OCSP_RESPONDER;
-    #endif
-            }
-        }
-#endif
-
-        /* ConfirmSignature is blocking here */
-        ret = ConfirmSignature(&cert.sigCtx,
-            resp->response, resp->responseSz,
-            cert.publicKey, cert.pubKeySize, cert.keyOID,
-            resp->sig, resp->sigSz, resp->sigOID);
-        FreeDecodedCert(&cert);
-
-        if (ret != 0) {
-            WOLFSSL_MSG("\tOCSP Confirm signature failed");
-            return ASN_OCSP_CONFIRM_E;
-        }
-    }
-    else
-#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
-    {
-        Signer* ca = NULL;
-        int sigValid = -1;
-
-        #ifndef NO_SKID
-            ca = GetCA(cm, resp->issuerKeyHash);
-        #else
-            ca = GetCA(cm, resp->issuerHash);
-        #endif
-
-        if (ca) {
-            SignatureCtx sigCtx;
-            InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
-
-            /* ConfirmSignature is blocking here */
-            sigValid = ConfirmSignature(&sigCtx, resp->response,
-                resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
-                                resp->sig, resp->sigSz, resp->sigOID);
-        }
-        if (ca == NULL || sigValid != 0) {
-            WOLFSSL_MSG("\tOCSP Confirm signature failed");
-            return ASN_OCSP_CONFIRM_E;
-        }
-
-        (void)noVerify;
-    }
-
-    *ioIndex = idx;
-    return 0;
-}
-
-
-void InitOcspResponse(OcspResponse* resp, CertStatus* status,
-                                                    byte* source, word32 inSz)
-{
-    WOLFSSL_ENTER("InitOcspResponse");
-
-    XMEMSET(status, 0, sizeof(CertStatus));
-    XMEMSET(resp,   0, sizeof(OcspResponse));
-
-    resp->responseStatus = -1;
-    resp->status         = status;
-    resp->source         = source;
-    resp->maxIdx         = inSz;
-}
-
-
-int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
-{
-    int ret;
-    int length = 0;
-    word32 idx = 0;
-    byte* source = resp->source;
-    word32 size = resp->maxIdx;
-    word32 oid;
-
-    WOLFSSL_ENTER("OcspResponseDecode");
-
-    /* peel the outer SEQUENCE wrapper */
-    if (GetSequence(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-
-    /* First get the responseStatus, an ENUMERATED */
-    if (GetEnumerated(source, &idx, &resp->responseStatus) < 0)
-        return ASN_PARSE_E;
-
-    if (resp->responseStatus != OCSP_SUCCESSFUL)
-        return 0;
-
-    /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
-    if (idx >= size)
-        return ASN_INPUT_E;
-    if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
-        return ASN_PARSE_E;
-    if (GetLength(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-
-    /* Get the responseBytes SEQUENCE */
-    if (GetSequence(source, &idx, &length, size) < 0)
-        return ASN_PARSE_E;
-
-    /* Check ObjectID for the resposeBytes */
-    if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0)
-        return ASN_PARSE_E;
-    if (oid != OCSP_BASIC_OID)
-        return ASN_PARSE_E;
-    ret = GetOctetString(source, &idx, &length, size);
-    if (ret < 0)
-        return ret;
-
-    ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
-    if (ret < 0)
-        return ret;
-
-    return 0;
-}
-
-
-word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
-{
-    static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
-                                       0x30, 0x01, 0x02 };
-    byte seqArray[5][MAX_SEQ_SZ];
-    word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId);
-
-    WOLFSSL_ENTER("SetOcspReqExtensions");
-
-    if (!req || !output || !req->nonceSz)
-        return 0;
-
-    totalSz += req->nonceSz;
-    totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]);
-    totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]);
-    totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]);
-    totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]);
-    totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]);
-
-    if (totalSz > size)
-        return 0;
-
-    totalSz = 0;
-
-    XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
-    totalSz += seqSz[4];
-
-    XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
-    totalSz += seqSz[3];
-
-    XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
-    totalSz += seqSz[2];
-
-    XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
-    totalSz += (word32)sizeof(NonceObjId);
-
-    XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
-    totalSz += seqSz[1];
-
-    XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
-    totalSz += seqSz[0];
-
-    XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
-    totalSz += req->nonceSz;
-
-    return totalSz;
-}
-
-
-int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
-{
-    byte seqArray[5][MAX_SEQ_SZ];
-    /* The ASN.1 of the OCSP Request is an onion of sequences */
-    byte algoArray[MAX_ALGO_SZ];
-    byte issuerArray[MAX_ENCODED_DIG_SZ];
-    byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
-    byte snArray[MAX_SN_SZ];
-    byte extArray[MAX_OCSP_EXT_SZ];
-    word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz;
-    int i, snSz;
-
-    WOLFSSL_ENTER("EncodeOcspRequest");
-
-#ifdef NO_SHA
-    algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0);
-#else
-    algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0);
-#endif
-
-    issuerSz    = SetDigest(req->issuerHash,    KEYID_SIZE,    issuerArray);
-    issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE,    issuerKeyArray);
-    snSz        = SetSerialNumber(req->serial,  req->serialSz, snArray, MAX_SN_SZ);
-    extSz       = 0;
-
-    if (snSz < 0)
-        return snSz;
-
-    if (req->nonceSz) {
-        /* TLS Extensions use this function too - put extensions after
-         * ASN.1: Context Specific [2].
-         */
-        extSz = EncodeOcspRequestExtensions(req, extArray + 2,
-                                            OCSP_NONCE_EXT_SZ);
-        extSz += SetExplicit(2, extSz, extArray);
-    }
-
-    totalSz = algoSz + issuerSz + issuerKeySz + snSz;
-    for (i = 4; i >= 0; i--) {
-        seqSz[i] = SetSequence(totalSz, seqArray[i]);
-        totalSz += seqSz[i];
-        if (i == 2) totalSz += extSz;
-    }
-
-    if (output == NULL)
-        return totalSz;
-    if (totalSz > size)
-        return BUFFER_E;
-
-    totalSz = 0;
-    for (i = 0; i < 5; i++) {
-        XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
-        totalSz += seqSz[i];
-    }
-
-    XMEMCPY(output + totalSz, algoArray, algoSz);
-    totalSz += algoSz;
-
-    XMEMCPY(output + totalSz, issuerArray, issuerSz);
-    totalSz += issuerSz;
-
-    XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
-    totalSz += issuerKeySz;
-
-    XMEMCPY(output + totalSz, snArray, snSz);
-    totalSz += snSz;
-
-    if (extSz != 0) {
-        XMEMCPY(output + totalSz, extArray, extSz);
-        totalSz += extSz;
-    }
-
-    return totalSz;
-}
-
-
-int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
-                                                                     void* heap)
-{
-    int ret;
-
-    WOLFSSL_ENTER("InitOcspRequest");
-
-    if (req == NULL)
-        return BAD_FUNC_ARG;
-
-    ForceZero(req, sizeof(OcspRequest));
-    req->heap = heap;
-
-    if (cert) {
-        XMEMCPY(req->issuerHash,    cert->issuerHash,    KEYID_SIZE);
-        XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE);
-
-        req->serial = (byte*)XMALLOC(cert->serialSz, req->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-        if (req->serial == NULL)
-            return MEMORY_E;
-
-        XMEMCPY(req->serial, cert->serial, cert->serialSz);
-        req->serialSz = cert->serialSz;
-
-        if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
-            req->url = (byte*)XMALLOC(cert->extAuthInfoSz, req->heap,
-                                                     DYNAMIC_TYPE_OCSP_REQUEST);
-            if (req->url == NULL) {
-                XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
-                return MEMORY_E;
-            }
-
-            XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
-            req->urlSz = cert->extAuthInfoSz;
-        }
-    }
-
-    if (useNonce) {
-        WC_RNG rng;
-
-    #ifndef HAVE_FIPS
-        ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID);
-    #else
-        ret = wc_InitRng(&rng);
-    #endif
-        if (ret != 0) {
-            WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
-        } else {
-            if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
-                WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
-            else
-                req->nonceSz = MAX_OCSP_NONCE_SZ;
-
-            wc_FreeRng(&rng);
-        }
-    }
-
-    return 0;
-}
-
-void FreeOcspRequest(OcspRequest* req)
-{
-    WOLFSSL_ENTER("FreeOcspRequest");
-
-    if (req) {
-        if (req->serial)
-            XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-
-        if (req->url)
-            XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
-    }
-}
-
-
-int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
-{
-    int cmp;
-
-    WOLFSSL_ENTER("CompareOcspReqResp");
-
-    if (req == NULL)
-    {
-        WOLFSSL_MSG("\tReq missing");
-        return -1;
-    }
-
-    if (resp == NULL)
-    {
-        WOLFSSL_MSG("\tResp missing");
-        return 1;
-    }
-
-    /* Nonces are not critical. The responder may not necessarily add
-     * the nonce to the response. */
-    if (resp->nonceSz != 0) {
-        cmp = req->nonceSz - resp->nonceSz;
-        if (cmp != 0)
-        {
-            WOLFSSL_MSG("\tnonceSz mismatch");
-            return cmp;
-        }
-
-        cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
-        if (cmp != 0)
-        {
-            WOLFSSL_MSG("\tnonce mismatch");
-            return cmp;
-        }
-    }
-
-    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");
-        return cmp;
-    }
-
-    return 0;
-}
-
-#endif
-
-
-/* store WC_SHA hash of NAME */
-WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
-                             int maxIdx)
-{
-    int    length;  /* length of all distinguished names */
-    int    ret;
-    word32 dummy;
-
-    WOLFSSL_ENTER("GetNameHash");
-
-    if (source[*idx] == ASN_OBJECT_ID) {
-        WOLFSSL_MSG("Trying optional prefix...");
-
-        if (GetLength(source, idx, &length, maxIdx) < 0)
-            return ASN_PARSE_E;
-
-        *idx += length;
-        WOLFSSL_MSG("Got optional prefix");
-    }
-
-    /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
-     * calculated over the entire DER encoding of the Name field, including
-     * the tag and length. */
-    dummy = *idx;
-    if (GetSequence(source, idx, &length, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-#ifdef NO_SHA
-    ret = wc_Sha256Hash(source + dummy, length + *idx - dummy, hash);
-#else
-    ret = wc_ShaHash(source + dummy, length + *idx - dummy, hash);
-#endif
-
-    *idx += length;
-
-    return ret;
-}
-
-
-#ifdef HAVE_CRL
-
-/* initialize decoded CRL */
-void InitDecodedCRL(DecodedCRL* dcrl, void* heap)
-{
-    WOLFSSL_MSG("InitDecodedCRL");
-
-    dcrl->certBegin    = 0;
-    dcrl->sigIndex     = 0;
-    dcrl->sigLength    = 0;
-    dcrl->signatureOID = 0;
-    dcrl->certs        = NULL;
-    dcrl->totalCerts   = 0;
-    dcrl->heap         = heap;
-    #ifdef WOLFSSL_HEAP_TEST
-        dcrl->heap = (void*)WOLFSSL_HEAP_TEST;
-    #endif
-}
-
-
-/* free decoded CRL resources */
-void FreeDecodedCRL(DecodedCRL* dcrl)
-{
-    RevokedCert* tmp = dcrl->certs;
-
-    WOLFSSL_MSG("FreeDecodedCRL");
-
-    while(tmp) {
-        RevokedCert* next = tmp->next;
-        XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED);
-        tmp = next;
-    }
-}
-
-
-/* Get Revoked Cert list, 0 on success */
-static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
-                      int maxIdx)
-{
-    int    ret, len;
-    word32 end;
-    byte   b;
-    RevokedCert* rc;
-
-    WOLFSSL_ENTER("GetRevoked");
-
-    if (GetSequence(buff, idx, &len, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    end = *idx + len;
-
-    rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
-                                                          DYNAMIC_TYPE_REVOKED);
-    if (rc == NULL) {
-        WOLFSSL_MSG("Alloc Revoked Cert failed");
-        return MEMORY_E;
-    }
-
-    if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,
-                                                                maxIdx) < 0) {
-        XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED);
-        return ASN_PARSE_E;
-    }
-
-    /* add to list */
-    rc->next = dcrl->certs;
-    dcrl->certs = rc;
-    dcrl->totalCerts++;
-
-    /* get date */
-    ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx);
-    if (ret < 0) {
-        WOLFSSL_MSG("Expecting Date");
-        return ret;
-    }
-
-    if (*idx != end)  /* skip extensions */
-        *idx = end;
-
-    return 0;
-}
-
-
-/* Get CRL Signature, 0 on success */
-static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
-                            int maxIdx)
-{
-    int    length;
-    int    ret;
-
-    WOLFSSL_ENTER("GetCRL_Signature");
-
-    ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL);
-    if (ret != 0)
-        return ret;
-    dcrl->sigLength = length;
-
-    dcrl->signature = (byte*)&source[*idx];
-    *idx += dcrl->sigLength;
-
-    return 0;
-}
-
-int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned,
-                        word32 tbsSz, const byte* signature, word32 sigSz,
-                        word32 signatureOID, Signer *ca, void* heap)
-{
-    /* try to confirm/verify signature */
-#ifndef IGNORE_KEY_EXTENSIONS
-    if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
-        WOLFSSL_MSG("CA cannot sign CRLs");
-        return ASN_CRL_NO_SIGNER_E;
-    }
-#endif /* IGNORE_KEY_EXTENSIONS */
-
-    InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
-    if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey,
-                         ca->pubKeySize, ca->keyOID, signature, sigSz,
-                         signatureOID) != 0) {
-        WOLFSSL_MSG("CRL Confirm signature failed");
-        return ASN_CRL_CONFIRM_E;
-    }
-
-    return 0;
-}
-
-/* prase crl buffer into decoded state, 0 on success */
-int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
-{
-    int          version, len, doNextDate = 1;
-    word32       oid, idx = 0, dateIdx;
-    Signer*      ca = NULL;
-    SignatureCtx sigCtx;
-
-    WOLFSSL_MSG("ParseCRL");
-
-    /* raw crl hash */
-    /* hash here if needed for optimized comparisons
-     * wc_Sha sha;
-     * wc_InitSha(&sha);
-     * wc_ShaUpdate(&sha, buff, sz);
-     * wc_ShaFinal(&sha, dcrl->crlHash); */
-
-    if (GetSequence(buff, &idx, &len, sz) < 0)
-        return ASN_PARSE_E;
-
-    dcrl->certBegin = idx;
-
-    if (GetSequence(buff, &idx, &len, sz) < 0)
-        return ASN_PARSE_E;
-    dcrl->sigIndex = len + idx;
-
-    /* may have version */
-    if (buff[idx] == ASN_INTEGER) {
-        if (GetMyVersion(buff, &idx, &version, sz) < 0)
-            return ASN_PARSE_E;
-    }
-
-    if (GetAlgoId(buff, &idx, &oid, oidIgnoreType, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
-        return ASN_PARSE_E;
-
-    dateIdx = idx;
-
-    if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
-    {
-#ifndef WOLFSSL_NO_CRL_NEXT_DATE
-        (void)dateIdx;
-        return ASN_PARSE_E;
-#else
-        dcrl->nextDateFormat = ASN_OTHER_TYPE;  /* skip flag */
-        doNextDate = 0;
-        idx = dateIdx;
-#endif
-    }
-
-    if (doNextDate) {
-#ifndef NO_ASN_TIME
-        if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
-            WOLFSSL_MSG("CRL after date is no longer valid");
-            return ASN_AFTER_DATE_E;
-        }
-#endif
-    }
-
-    if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) {
-        if (GetSequence(buff, &idx, &len, sz) < 0)
-            return ASN_PARSE_E;
-
-        len += idx;
-
-        while (idx < (word32)len) {
-            if (GetRevoked(buff, &idx, dcrl, sz) < 0)
-                return ASN_PARSE_E;
-        }
-    }
-
-    if (idx != dcrl->sigIndex)
-        idx = dcrl->sigIndex;   /* skip extensions */
-
-    if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
-        return ASN_PARSE_E;
-
-    /* openssl doesn't add skid by default for CRLs cause firefox chokes
-       we're not assuming it's available yet */
-#if !defined(NO_SKID) && defined(CRL_SKID_READY)
-    if (dcrl->extAuthKeyIdSet)
-        ca = GetCA(cm, dcrl->extAuthKeyId);
-    if (ca == NULL)
-        ca = GetCAByName(cm, dcrl->issuerHash);
-#else
-    ca = GetCA(cm, dcrl->issuerHash);
-#endif /* !NO_SKID && CRL_SKID_READY */
-    WOLFSSL_MSG("About to verify CRL signature");
-
-    if (ca == NULL) {
-        WOLFSSL_MSG("Did NOT find CRL issuer CA");
-        return ASN_CRL_NO_SIGNER_E;
-    }
-
-    WOLFSSL_MSG("Found CRL issuer CA");
-    return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin,
-           dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength,
-           dcrl->signatureOID, ca, dcrl->heap);
-}
-
-#endif /* HAVE_CRL */
-
-#undef ERROR_OUT
-
-#endif /* !NO_ASN */
-
-#ifdef WOLFSSL_SEP
-
-
-#endif /* WOLFSSL_SEP */
-
--- a/wolfcrypt/src/async.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfcrypt/src/blake2b.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,454 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
-
-   To the extent possible under law, the author(s) have dedicated all copyright
-   and related and neighboring rights to this software to the public domain
-   worldwide. This software is distributed without any warranty.
-
-   You should have received a copy of the CC0 Public Domain Dedication along with
-   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-*/
-/* blake2b.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_BLAKE2
-
-#include <wolfssl/wolfcrypt/blake2.h>
-#include <wolfssl/wolfcrypt/blake2-impl.h>
-
-
-static const word64 blake2b_IV[8] =
-{
-  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
-  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
-  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
-  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
-};
-
-static const byte blake2b_sigma[12][16] =
-{
-  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
-  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
-  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
-  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
-  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
-  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
-  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
-  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
-  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
-  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
-  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
-  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
-};
-
-
-static WC_INLINE int blake2b_set_lastnode( blake2b_state *S )
-{
-  S->f[1] = ~0ULL;
-  return 0;
-}
-
-/* Some helper functions, not necessarily useful */
-static WC_INLINE int blake2b_set_lastblock( blake2b_state *S )
-{
-  if( S->last_node ) blake2b_set_lastnode( S );
-
-  S->f[0] = ~0ULL;
-  return 0;
-}
-
-static WC_INLINE int blake2b_increment_counter( blake2b_state *S, const word64
-                                             inc )
-{
-  S->t[0] += inc;
-  S->t[1] += ( S->t[0] < inc );
-  return 0;
-}
-
-static WC_INLINE int blake2b_init0( blake2b_state *S )
-{
-  int i;
-  XMEMSET( S, 0, sizeof( blake2b_state ) );
-
-  for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
-
-  return 0;
-}
-
-/* init xors IV with input parameter block */
-int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
-{
-  word32 i;
-  byte *p ;
-  blake2b_init0( S );
-  p =  ( byte * )( P );
-
-  /* IV XOR ParamBlock */
-  for( i = 0; i < 8; ++i )
-    S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
-
-  return 0;
-}
-
-
-
-int blake2b_init( blake2b_state *S, const byte outlen )
-{
-  blake2b_param P[1];
-
-  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
-
-#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD
-  P->digest_length = outlen;
-  P->key_length    = 0;
-  P->fanout        = 1;
-  P->depth         = 1;
-  store32( &P->leaf_length, 0 );
-  store64( &P->node_offset, 0 );
-  P->node_depth    = 0;
-  P->inner_length  = 0;
-  XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
-  XMEMSET( P->salt,     0, sizeof( P->salt ) );
-  XMEMSET( P->personal, 0, sizeof( P->personal ) );
-#else
-  XMEMSET( P, 0, sizeof( *P ) );
-  P->digest_length = outlen;
-  P->fanout        = 1;
-  P->depth         = 1;
-#endif
-  return blake2b_init_param( S, P );
-}
-
-
-int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key,
-                      const byte keylen )
-{
-  blake2b_param P[1];
-
-  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
-
-  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
-
-#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD
-  P->digest_length = outlen;
-  P->key_length    = keylen;
-  P->fanout        = 1;
-  P->depth         = 1;
-  store32( &P->leaf_length, 0 );
-  store64( &P->node_offset, 0 );
-  P->node_depth    = 0;
-  P->inner_length  = 0;
-  XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
-  XMEMSET( P->salt,     0, sizeof( P->salt ) );
-  XMEMSET( P->personal, 0, sizeof( P->personal ) );
-#else
-  XMEMSET( P, 0, sizeof( *P ) );
-  P->digest_length = outlen;
-  P->key_length    = keylen;
-  P->fanout        = 1;
-  P->depth         = 1;
-#endif
-
-  if( blake2b_init_param( S, P ) < 0 ) return -1;
-
-  {
-#ifdef WOLFSSL_SMALL_STACK
-    byte* block;
-
-    block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    if ( block == NULL ) return -1;
-#else
-    byte block[BLAKE2B_BLOCKBYTES];
-#endif
-
-    XMEMSET( block, 0, BLAKE2B_BLOCKBYTES );
-    XMEMCPY( block, key, keylen );
-    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
-    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */
-                                                     /* memory */
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-  }
-  return 0;
-}
-
-static int blake2b_compress( blake2b_state *S,
-                             const byte block[BLAKE2B_BLOCKBYTES] )
-{
-  int i;
-
-#ifdef WOLFSSL_SMALL_STACK
-  word64* m;
-  word64* v;
-
-  m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-  if ( m == NULL ) return -1;
-
-  v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-  if ( v == NULL )
-  {
-    XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    return -1;
-  }
-#else
-  word64 m[16];
-  word64 v[16];
-#endif
-
-  for( i = 0; i < 16; ++i )
-    m[i] = load64( block + i * sizeof( m[i] ) );
-
-  for( i = 0; i < 8; ++i )
-    v[i] = S->h[i];
-
-  v[ 8] = blake2b_IV[0];
-  v[ 9] = blake2b_IV[1];
-  v[10] = blake2b_IV[2];
-  v[11] = blake2b_IV[3];
-  v[12] = S->t[0] ^ blake2b_IV[4];
-  v[13] = S->t[1] ^ blake2b_IV[5];
-  v[14] = S->f[0] ^ blake2b_IV[6];
-  v[15] = S->f[1] ^ blake2b_IV[7];
-#define G(r,i,a,b,c,d) \
-  do { \
-    a = a + b + m[blake2b_sigma[r][2*i+0]]; \
-    d = rotr64(d ^ a, 32); \
-    c = c + d; \
-    b = rotr64(b ^ c, 24); \
-    a = a + b + m[blake2b_sigma[r][2*i+1]]; \
-    d = rotr64(d ^ a, 16); \
-    c = c + d; \
-    b = rotr64(b ^ c, 63); \
-  } while(0)
-#define ROUND(r)  \
-  do { \
-    G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
-    G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
-    G(r,2,v[ 2],v[ 6],v[10],v[14]); \
-    G(r,3,v[ 3],v[ 7],v[11],v[15]); \
-    G(r,4,v[ 0],v[ 5],v[10],v[15]); \
-    G(r,5,v[ 1],v[ 6],v[11],v[12]); \
-    G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
-    G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
-  } while(0)
-  ROUND( 0 );
-  ROUND( 1 );
-  ROUND( 2 );
-  ROUND( 3 );
-  ROUND( 4 );
-  ROUND( 5 );
-  ROUND( 6 );
-  ROUND( 7 );
-  ROUND( 8 );
-  ROUND( 9 );
-  ROUND( 10 );
-  ROUND( 11 );
-
-  for( i = 0; i < 8; ++i )
-    S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
-
-#undef G
-#undef ROUND
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-  XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-  return 0;
-}
-
-/* inlen now in bytes */
-int blake2b_update( blake2b_state *S, const byte *in, word64 inlen )
-{
-  while( inlen > 0 )
-  {
-    word64 left = S->buflen;
-    word64 fill = 2 * BLAKE2B_BLOCKBYTES - left;
-
-    if( inlen > fill )
-    {
-      XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */
-      S->buflen += fill;
-      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
-
-      if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */
-
-      XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
-              /* Shift buffer left */
-      S->buflen -= BLAKE2B_BLOCKBYTES;
-      in += fill;
-      inlen -= fill;
-    }
-    else /* inlen <= fill */
-    {
-      XMEMCPY( S->buf + left, in, (wolfssl_word)inlen );
-      S->buflen += inlen; /* Be lazy, do not compress */
-      in += inlen;
-      inlen -= inlen;
-    }
-  }
-
-  return 0;
-}
-
-/* Is this correct? */
-int blake2b_final( blake2b_state *S, byte *out, byte outlen )
-{
-  byte buffer[BLAKE2B_OUTBYTES];
-  int     i;
-
-  if( S->buflen > BLAKE2B_BLOCKBYTES )
-  {
-    blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
-
-    if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
-
-    S->buflen -= BLAKE2B_BLOCKBYTES;
-    XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (wolfssl_word)S->buflen );
-  }
-
-  blake2b_increment_counter( S, S->buflen );
-  blake2b_set_lastblock( S );
-  XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) );
-         /* Padding */
-  if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
-
-  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
-    store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
-
-  XMEMCPY( out, buffer, outlen );
-  return 0;
-}
-
-/* inlen, at least, should be word64. Others can be size_t. */
-int blake2b( byte *out, const void *in, const void *key, const byte outlen,
-             const word64 inlen, byte keylen )
-{
-  blake2b_state S[1];
-
-  /* Verify parameters */
-  if ( NULL == in ) return -1;
-
-  if ( NULL == out ) return -1;
-
-  if( NULL == key ) keylen = 0;
-
-  if( keylen > 0 )
-  {
-    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
-  }
-  else
-  {
-    if( blake2b_init( S, outlen ) < 0 ) return -1;
-  }
-
-  if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1;
-
-  return blake2b_final( S, out, outlen );
-}
-
-#if defined(BLAKE2B_SELFTEST)
-#include <string.h>
-#include "blake2-kat.h"
-int main( int argc, char **argv )
-{
-  byte key[BLAKE2B_KEYBYTES];
-  byte buf[KAT_LENGTH];
-
-  for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i )
-    key[i] = ( byte )i;
-
-  for( word32 i = 0; i < KAT_LENGTH; ++i )
-    buf[i] = ( byte )i;
-
-  for( word32 i = 0; i < KAT_LENGTH; ++i )
-  {
-    byte hash[BLAKE2B_OUTBYTES];
-    if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 )
-    {
-      puts( "error" );
-      return -1;
-    }
-
-    if( 0 != XMEMCMP( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
-    {
-      puts( "error" );
-      return -1;
-    }
-  }
-
-  puts( "ok" );
-  return 0;
-}
-#endif
-
-
-/* wolfCrypt API */
-
-/* Init Blake2b digest, track size in case final doesn't want to "remember" */
-int wc_InitBlake2b(Blake2b* b2b, word32 digestSz)
-{
-    if (b2b == NULL){
-        return -1;
-    }
-    b2b->digestSz = digestSz;
-
-    return blake2b_init(b2b->S, (byte)digestSz);
-}
-
-
-/* Blake2b Update */
-int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz)
-{
-    return blake2b_update(b2b->S, data, sz);
-}
-
-
-/* Blake2b Final, if pass in zero size we use init digestSz */
-int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz)
-{
-    word32 sz = requestSz ? requestSz : b2b->digestSz;
-
-    return blake2b_final(b2b->S, final, (byte)sz);
-}
-
-
-/* end CTaoCrypt API */
-
-#endif  /* HAVE_BLAKE2 */
-
-
--- a/wolfcrypt/src/camellia.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1645 +0,0 @@
-/* camellia.c ver 1.2.0
- *
- * Copyright (c) 2006,2007
- * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer as
- *   the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* camellia.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/*
- * Algorithm Specification
- *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_CAMELLIA
-
-#include <wolfssl/wolfcrypt/camellia.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-/* u32 must be 32bit word */
-typedef unsigned int u32;
-typedef unsigned char u8;
-
-/* key constants */
-
-#define CAMELLIA_SIGMA1L ((u32)0xA09E667FL)
-#define CAMELLIA_SIGMA1R ((u32)0x3BCC908BL)
-#define CAMELLIA_SIGMA2L ((u32)0xB67AE858L)
-#define CAMELLIA_SIGMA2R ((u32)0x4CAA73B2L)
-#define CAMELLIA_SIGMA3L ((u32)0xC6EF372FL)
-#define CAMELLIA_SIGMA3R ((u32)0xE94F82BEL)
-#define CAMELLIA_SIGMA4L ((u32)0x54FF53A5L)
-#define CAMELLIA_SIGMA4R ((u32)0xF1D36F1CL)
-#define CAMELLIA_SIGMA5L ((u32)0x10E527FAL)
-#define CAMELLIA_SIGMA5R ((u32)0xDE682D1DL)
-#define CAMELLIA_SIGMA6L ((u32)0xB05688C2L)
-#define CAMELLIA_SIGMA6R ((u32)0xB3E6C1FDL)
-
-/*
- *  macros
- */
-
-
-#if defined(_MSC_VER)
-
-# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
-# define GETU32(p) SWAP(*((u32 *)(p)))
-# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));}
-
-#else /* not MS-VC */
-
-# define GETU32(pt)				\
-    (((u32)(pt)[0] << 24)			\
-     ^ ((u32)(pt)[1] << 16)			\
-     ^ ((u32)(pt)[2] <<  8)			\
-     ^ ((u32)(pt)[3]))
-
-# define PUTU32(ct, st)  {			\
-	(ct)[0] = (u8)((st) >> 24);		\
-	(ct)[1] = (u8)((st) >> 16);		\
-	(ct)[2] = (u8)((st) >>  8);		\
-	(ct)[3] = (u8)(st); }
-
-#endif
-
-#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2])
-#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1])
-
-/* rotation right shift 1byte */
-#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
-/* rotation left shift 1bit */
-#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
-/* rotation left shift 1byte */
-#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
-
-#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
-    do {						\
-	w0 = ll;					\
-	ll = (ll << bits) + (lr >> (32 - bits));	\
-	lr = (lr << bits) + (rl >> (32 - bits));	\
-	rl = (rl << bits) + (rr >> (32 - bits));	\
-	rr = (rr << bits) + (w0 >> (32 - bits));	\
-    } while(0)
-
-#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
-    do {						\
-	w0 = ll;					\
-	w1 = lr;					\
-	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
-	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
-	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
-	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
-    } while(0)
-
-#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
-#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
-#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
-#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
-
-#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
-    do {							\
-	il = xl ^ kl;						\
-	ir = xr ^ kr;						\
-	t0 = il >> 16;						\
-	t1 = ir >> 16;						\
-	yl = CAMELLIA_SP1110(ir & 0xff)				\
-	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
-	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
-	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
-	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
-	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
-	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
-	    ^ CAMELLIA_SP4404(il & 0xff);			\
-	yl ^= yr;						\
-	yr = CAMELLIA_RR8(yr);					\
-	yr ^= yl;						\
-    } while(0)
-
-
-/*
- * for speed up
- *
- */
-#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
-    do {								\
-	t0 = kll;							\
-	t0 &= ll;							\
-	lr ^= CAMELLIA_RL1(t0);						\
-	t1 = klr;							\
-	t1 |= lr;							\
-	ll ^= t1;							\
-									\
-	t2 = krr;							\
-	t2 |= rr;							\
-	rl ^= t2;							\
-	t3 = krl;							\
-	t3 &= rl;							\
-	rr ^= CAMELLIA_RL1(t3);						\
-    } while(0)
-
-#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
-    do {								\
-	ir = CAMELLIA_SP1110(xr & 0xff)					\
-	    ^ CAMELLIA_SP0222((xr >> 24) & 0xff)			\
-	    ^ CAMELLIA_SP3033((xr >> 16) & 0xff)			\
-	    ^ CAMELLIA_SP4404((xr >> 8) & 0xff);			\
-	il = CAMELLIA_SP1110((xl >> 24) & 0xff)				\
-	    ^ CAMELLIA_SP0222((xl >> 16) & 0xff)			\
-	    ^ CAMELLIA_SP3033((xl >> 8) & 0xff)				\
-	    ^ CAMELLIA_SP4404(xl & 0xff);				\
-	il ^= kl;							\
-	ir ^= kr;							\
-	ir ^= il;							\
-	il = CAMELLIA_RR8(il);						\
-	il ^= ir;							\
-	yl ^= ir;							\
-	yr ^= il;							\
-    } while(0)
-
-
-static const u32 camellia_sp1110[256] = {
-    0x70707000,0x82828200,0x2c2c2c00,0xececec00,
-    0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
-    0xe4e4e400,0x85858500,0x57575700,0x35353500,
-    0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
-    0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
-    0x45454500,0x19191900,0xa5a5a500,0x21212100,
-    0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
-    0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
-    0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
-    0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
-    0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
-    0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
-    0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
-    0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
-    0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
-    0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
-    0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
-    0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
-    0x74747400,0x12121200,0x2b2b2b00,0x20202000,
-    0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
-    0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
-    0x34343400,0x7e7e7e00,0x76767600,0x05050500,
-    0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
-    0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
-    0x14141400,0x58585800,0x3a3a3a00,0x61616100,
-    0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
-    0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
-    0x53535300,0x18181800,0xf2f2f200,0x22222200,
-    0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
-    0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
-    0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
-    0x60606000,0xfcfcfc00,0x69696900,0x50505000,
-    0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
-    0xa1a1a100,0x89898900,0x62626200,0x97979700,
-    0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
-    0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
-    0x10101000,0xc4c4c400,0x00000000,0x48484800,
-    0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
-    0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
-    0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
-    0x87878700,0x5c5c5c00,0x83838300,0x02020200,
-    0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
-    0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
-    0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
-    0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
-    0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
-    0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
-    0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
-    0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
-    0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
-    0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
-    0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
-    0x78787800,0x98989800,0x06060600,0x6a6a6a00,
-    0xe7e7e700,0x46464600,0x71717100,0xbababa00,
-    0xd4d4d400,0x25252500,0xababab00,0x42424200,
-    0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
-    0x72727200,0x07070700,0xb9b9b900,0x55555500,
-    0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
-    0x36363600,0x49494900,0x2a2a2a00,0x68686800,
-    0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
-    0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
-    0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
-    0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
-    0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
-};
-
-static const u32 camellia_sp0222[256] = {
-    0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
-    0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
-    0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
-    0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
-    0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
-    0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
-    0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
-    0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
-    0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
-    0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
-    0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
-    0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
-    0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
-    0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
-    0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
-    0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
-    0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
-    0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
-    0x00e8e8e8,0x00242424,0x00565656,0x00404040,
-    0x00e1e1e1,0x00636363,0x00090909,0x00333333,
-    0x00bfbfbf,0x00989898,0x00979797,0x00858585,
-    0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
-    0x00dadada,0x006f6f6f,0x00535353,0x00626262,
-    0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
-    0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
-    0x00bdbdbd,0x00363636,0x00222222,0x00383838,
-    0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
-    0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
-    0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
-    0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
-    0x00484848,0x00101010,0x00d1d1d1,0x00515151,
-    0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
-    0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
-    0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
-    0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
-    0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
-    0x00202020,0x00898989,0x00000000,0x00909090,
-    0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
-    0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
-    0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
-    0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
-    0x009b9b9b,0x00949494,0x00212121,0x00666666,
-    0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
-    0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
-    0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
-    0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
-    0x00030303,0x002d2d2d,0x00dedede,0x00969696,
-    0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
-    0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
-    0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
-    0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
-    0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
-    0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
-    0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
-    0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
-    0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
-    0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
-    0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
-    0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
-    0x00787878,0x00707070,0x00e3e3e3,0x00494949,
-    0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
-    0x00777777,0x00939393,0x00868686,0x00838383,
-    0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
-    0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
-};
-
-static const u32 camellia_sp3033[256] = {
-    0x38003838,0x41004141,0x16001616,0x76007676,
-    0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
-    0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
-    0x75007575,0x06000606,0x57005757,0xa000a0a0,
-    0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
-    0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
-    0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
-    0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
-    0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
-    0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
-    0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
-    0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
-    0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
-    0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
-    0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
-    0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
-    0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
-    0xfd00fdfd,0x66006666,0x58005858,0x96009696,
-    0x3a003a3a,0x09000909,0x95009595,0x10001010,
-    0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
-    0xef00efef,0x26002626,0xe500e5e5,0x61006161,
-    0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
-    0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
-    0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
-    0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
-    0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
-    0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
-    0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
-    0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
-    0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
-    0x12001212,0x04000404,0x74007474,0x54005454,
-    0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
-    0x55005555,0x68006868,0x50005050,0xbe00bebe,
-    0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
-    0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
-    0x70007070,0xff00ffff,0x32003232,0x69006969,
-    0x08000808,0x62006262,0x00000000,0x24002424,
-    0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
-    0x45004545,0x81008181,0x73007373,0x6d006d6d,
-    0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
-    0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
-    0xe600e6e6,0x25002525,0x48004848,0x99009999,
-    0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
-    0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
-    0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
-    0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
-    0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
-    0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
-    0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
-    0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
-    0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
-    0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
-    0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
-    0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
-    0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
-    0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
-    0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
-    0x7c007c7c,0x77007777,0x56005656,0x05000505,
-    0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
-    0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
-    0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
-    0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
-    0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
-    0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
-};
-
-static const u32 camellia_sp4404[256] = {
-    0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
-    0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
-    0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
-    0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
-    0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
-    0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
-    0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
-    0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
-    0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
-    0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
-    0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
-    0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
-    0x14140014,0x3a3a003a,0xdede00de,0x11110011,
-    0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
-    0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
-    0x24240024,0xe8e800e8,0x60600060,0x69690069,
-    0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
-    0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
-    0x10100010,0x00000000,0xa3a300a3,0x75750075,
-    0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
-    0x87870087,0x83830083,0xcdcd00cd,0x90900090,
-    0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
-    0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
-    0x81810081,0x6f6f006f,0x13130013,0x63630063,
-    0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
-    0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
-    0x78780078,0x06060006,0xe7e700e7,0x71710071,
-    0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
-    0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
-    0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
-    0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
-    0x15150015,0xadad00ad,0x77770077,0x80800080,
-    0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
-    0x85850085,0x35350035,0x0c0c000c,0x41410041,
-    0xefef00ef,0x93930093,0x19190019,0x21210021,
-    0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
-    0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
-    0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
-    0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
-    0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
-    0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
-    0x12120012,0x20200020,0xb1b100b1,0x99990099,
-    0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
-    0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
-    0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
-    0x0f0f000f,0x16160016,0x18180018,0x22220022,
-    0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
-    0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
-    0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
-    0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
-    0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
-    0x03030003,0xdada00da,0x3f3f003f,0x94940094,
-    0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
-    0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
-    0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
-    0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
-    0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
-    0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
-    0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
-    0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
-    0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
-    0x49490049,0x68680068,0x38380038,0xa4a400a4,
-    0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
-    0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
-};
-
-
-/**
- * Stuff related to the Camellia key schedule
- */
-#define subl(x) subL[(x)]
-#define subr(x) subR[(x)]
-
-static int camellia_setup128(const unsigned char *key, u32 *subkey)
-{
-    u32 kll, klr, krl, krr;
-    u32 il, ir, t0, t1, w0, w1;
-    u32 kw4l, kw4r, dw, tl, tr;
-
-#ifdef WOLFSSL_SMALL_STACK
-    u32* subL;
-    u32* subR;
-
-    subL = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (subL == NULL)
-        return MEMORY_E;
-
-    subR = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (subR == NULL) {
-        XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#else
-    u32 subL[26];
-    u32 subR[26];
-#endif
-
-    /**
-     *  k == kll || klr || krl || krr (|| is concatenation)
-     */
-    kll = GETU32(key     );
-    klr = GETU32(key +  4);
-    krl = GETU32(key +  8);
-    krr = GETU32(key + 12);
-    /**
-     * generate KL dependent subkeys
-     */
-    subl(0) = kll; subr(0) = klr;
-    subl(1) = krl; subr(1) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(4) = kll; subr(4) = klr;
-    subl(5) = krl; subr(5) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
-    subl(10) = kll; subr(10) = klr;
-    subl(11) = krl; subr(11) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(13) = krl; subr(13) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-    subl(16) = kll; subr(16) = klr;
-    subl(17) = krl; subr(17) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-    subl(18) = kll; subr(18) = klr;
-    subl(19) = krl; subr(19) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-    subl(22) = kll; subr(22) = klr;
-    subl(23) = krl; subr(23) = krr;
-
-    /* generate KA */
-    kll = subl(0); klr = subr(0);
-    krl = subl(1); krr = subr(1);
-    CAMELLIA_F(kll, klr,
-	       CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
-	       w0, w1, il, ir, t0, t1);
-    krl ^= w0; krr ^= w1;
-    CAMELLIA_F(krl, krr,
-	       CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
-	       kll, klr, il, ir, t0, t1);
-    CAMELLIA_F(kll, klr,
-	       CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
-	       krl, krr, il, ir, t0, t1);
-    krl ^= w0; krr ^= w1;
-    CAMELLIA_F(krl, krr,
-	       CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
-	       w0, w1, il, ir, t0, t1);
-    kll ^= w0; klr ^= w1;
-
-    /* generate KA dependent subkeys */
-    subl(2) = kll; subr(2) = klr;
-    subl(3) = krl; subr(3) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(6) = kll; subr(6) = klr;
-    subl(7) = krl; subr(7) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(8) = kll; subr(8) = klr;
-    subl(9) = krl; subr(9) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(12) = kll; subr(12) = klr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(14) = kll; subr(14) = klr;
-    subl(15) = krl; subr(15) = krr;
-    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
-    subl(20) = kll; subr(20) = klr;
-    subl(21) = krl; subr(21) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-    subl(24) = kll; subr(24) = klr;
-    subl(25) = krl; subr(25) = krr;
-
-
-    /* absorb kw2 to other subkeys */
-    subl(3) ^= subl(1); subr(3) ^= subr(1);
-    subl(5) ^= subl(1); subr(5) ^= subr(1);
-    subl(7) ^= subl(1); subr(7) ^= subr(1);
-    subl(1) ^= subr(1) & ~subr(9);
-    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
-    subl(11) ^= subl(1); subr(11) ^= subr(1);
-    subl(13) ^= subl(1); subr(13) ^= subr(1);
-    subl(15) ^= subl(1); subr(15) ^= subr(1);
-    subl(1) ^= subr(1) & ~subr(17);
-    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
-    subl(19) ^= subl(1); subr(19) ^= subr(1);
-    subl(21) ^= subl(1); subr(21) ^= subr(1);
-    subl(23) ^= subl(1); subr(23) ^= subr(1);
-    subl(24) ^= subl(1); subr(24) ^= subr(1);
-
-    /* absorb kw4 to other subkeys */
-    kw4l = subl(25); kw4r = subr(25);
-    subl(22) ^= kw4l; subr(22) ^= kw4r;
-    subl(20) ^= kw4l; subr(20) ^= kw4r;
-    subl(18) ^= kw4l; subr(18) ^= kw4r;
-    kw4l ^= kw4r & ~subr(16);
-    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
-    subl(14) ^= kw4l; subr(14) ^= kw4r;
-    subl(12) ^= kw4l; subr(12) ^= kw4r;
-    subl(10) ^= kw4l; subr(10) ^= kw4r;
-    kw4l ^= kw4r & ~subr(8);
-    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
-    subl(6) ^= kw4l; subr(6) ^= kw4r;
-    subl(4) ^= kw4l; subr(4) ^= kw4r;
-    subl(2) ^= kw4l; subr(2) ^= kw4r;
-    subl(0) ^= kw4l; subr(0) ^= kw4r;
-
-    /* key XOR is end of F-function */
-    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
-    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
-    CamelliaSubkeyL(2) = subl(3);
-    CamelliaSubkeyR(2) = subr(3);
-    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
-    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
-    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
-    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
-    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
-    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
-    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
-    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
-    tl = subl(10) ^ (subr(10) & ~subr(8));
-    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(7) = subl(6) ^ tl;
-    CamelliaSubkeyR(7) = subr(6) ^ tr;
-    CamelliaSubkeyL(8) = subl(8);
-    CamelliaSubkeyR(8) = subr(8);
-    CamelliaSubkeyL(9) = subl(9);
-    CamelliaSubkeyR(9) = subr(9);
-    tl = subl(7) ^ (subr(7) & ~subr(9));
-    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(10) = tl ^ subl(11);
-    CamelliaSubkeyR(10) = tr ^ subr(11);
-    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
-    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
-    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
-    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
-    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
-    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
-    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
-    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
-    tl = subl(18) ^ (subr(18) & ~subr(16));
-    dw = tl & subl(16),	tr = subr(18) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(15) = subl(14) ^ tl;
-    CamelliaSubkeyR(15) = subr(14) ^ tr;
-    CamelliaSubkeyL(16) = subl(16);
-    CamelliaSubkeyR(16) = subr(16);
-    CamelliaSubkeyL(17) = subl(17);
-    CamelliaSubkeyR(17) = subr(17);
-    tl = subl(15) ^ (subr(15) & ~subr(17));
-    dw = tl & subl(17),	tr = subr(15) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(18) = tl ^ subl(19);
-    CamelliaSubkeyR(18) = tr ^ subr(19);
-    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
-    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
-    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
-    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
-    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
-    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
-    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
-    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
-    CamelliaSubkeyL(23) = subl(22);
-    CamelliaSubkeyR(23) = subr(22);
-    CamelliaSubkeyL(24) = subl(24) ^ subl(23);
-    CamelliaSubkeyR(24) = subr(24) ^ subr(23);
-
-    /* apply the inverse of the last half of P-function */
-    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
-    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
-    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
-    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
-    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
-    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
-    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
-    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
-    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
-    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
-    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
-    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
-    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
-    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
-    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
-    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
-    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
-    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-static int camellia_setup256(const unsigned char *key, u32 *subkey)
-{
-    u32 kll,klr,krl,krr;           /* left half of key */
-    u32 krll,krlr,krrl,krrr;       /* right half of key */
-    u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
-    u32 kw4l, kw4r, dw, tl, tr;
-
-#ifdef WOLFSSL_SMALL_STACK
-    u32* subL;
-    u32* subR;
-
-    subL = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (subL == NULL)
-        return MEMORY_E;
-
-    subR = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (subR == NULL) {
-        XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#else
-    u32 subL[34];
-    u32 subR[34];
-#endif
-
-    /**
-     *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
-     *  (|| is concatenation)
-     */
-
-    kll  = GETU32(key     );
-    klr  = GETU32(key +  4);
-    krl  = GETU32(key +  8);
-    krr  = GETU32(key + 12);
-    krll = GETU32(key + 16);
-    krlr = GETU32(key + 20);
-    krrl = GETU32(key + 24);
-    krrr = GETU32(key + 28);
-
-    /* generate KL dependent subkeys */
-    subl(0) = kll; subr(0) = klr;
-    subl(1) = krl; subr(1) = krr;
-    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
-    subl(12) = kll; subr(12) = klr;
-    subl(13) = krl; subr(13) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(16) = kll; subr(16) = klr;
-    subl(17) = krl; subr(17) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-    subl(22) = kll; subr(22) = klr;
-    subl(23) = krl; subr(23) = krr;
-    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
-    subl(30) = kll; subr(30) = klr;
-    subl(31) = krl; subr(31) = krr;
-
-    /* generate KR dependent subkeys */
-    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
-    subl(4) = krll; subr(4) = krlr;
-    subl(5) = krrl; subr(5) = krrr;
-    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
-    subl(8) = krll; subr(8) = krlr;
-    subl(9) = krrl; subr(9) = krrr;
-    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-    subl(18) = krll; subr(18) = krlr;
-    subl(19) = krrl; subr(19) = krrr;
-    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
-    subl(26) = krll; subr(26) = krlr;
-    subl(27) = krrl; subr(27) = krrr;
-    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
-
-    /* generate KA */
-    kll = subl(0) ^ krll; klr = subr(0) ^ krlr;
-    krl = subl(1) ^ krrl; krr = subr(1) ^ krrr;
-    CAMELLIA_F(kll, klr,
-	       CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
-	       w0, w1, il, ir, t0, t1);
-    krl ^= w0; krr ^= w1;
-    CAMELLIA_F(krl, krr,
-	       CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
-	       kll, klr, il, ir, t0, t1);
-    kll ^= krll; klr ^= krlr;
-    CAMELLIA_F(kll, klr,
-	       CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
-	       krl, krr, il, ir, t0, t1);
-    krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
-    CAMELLIA_F(krl, krr,
-	       CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
-	       w0, w1, il, ir, t0, t1);
-    kll ^= w0; klr ^= w1;
-
-    /* generate KB */
-    krll ^= kll; krlr ^= klr;
-    krrl ^= krl; krrr ^= krr;
-    CAMELLIA_F(krll, krlr,
-	       CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
-	       w0, w1, il, ir, t0, t1);
-    krrl ^= w0; krrr ^= w1;
-    CAMELLIA_F(krrl, krrr,
-	       CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
-	       w0, w1, il, ir, t0, t1);
-    krll ^= w0; krlr ^= w1;
-
-    /* generate KA dependent subkeys */
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-    subl(6) = kll; subr(6) = klr;
-    subl(7) = krl; subr(7) = krr;
-    CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
-    subl(14) = kll; subr(14) = klr;
-    subl(15) = krl; subr(15) = krr;
-    subl(24) = klr; subr(24) = krl;
-    subl(25) = krr; subr(25) = kll;
-    CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
-    subl(28) = kll; subr(28) = klr;
-    subl(29) = krl; subr(29) = krr;
-
-    /* generate KB dependent subkeys */
-    subl(2) = krll; subr(2) = krlr;
-    subl(3) = krrl; subr(3) = krrr;
-    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-    subl(10) = krll; subr(10) = krlr;
-    subl(11) = krrl; subr(11) = krrr;
-    CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-    subl(20) = krll; subr(20) = krlr;
-    subl(21) = krrl; subr(21) = krrr;
-    CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
-    subl(32) = krll; subr(32) = krlr;
-    subl(33) = krrl; subr(33) = krrr;
-
-    /* absorb kw2 to other subkeys */
-    subl(3) ^= subl(1); subr(3) ^= subr(1);
-    subl(5) ^= subl(1); subr(5) ^= subr(1);
-    subl(7) ^= subl(1); subr(7) ^= subr(1);
-    subl(1) ^= subr(1) & ~subr(9);
-    dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
-    subl(11) ^= subl(1); subr(11) ^= subr(1);
-    subl(13) ^= subl(1); subr(13) ^= subr(1);
-    subl(15) ^= subl(1); subr(15) ^= subr(1);
-    subl(1) ^= subr(1) & ~subr(17);
-    dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
-    subl(19) ^= subl(1); subr(19) ^= subr(1);
-    subl(21) ^= subl(1); subr(21) ^= subr(1);
-    subl(23) ^= subl(1); subr(23) ^= subr(1);
-    subl(1) ^= subr(1) & ~subr(25);
-    dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw);
-    subl(27) ^= subl(1); subr(27) ^= subr(1);
-    subl(29) ^= subl(1); subr(29) ^= subr(1);
-    subl(31) ^= subl(1); subr(31) ^= subr(1);
-    subl(32) ^= subl(1); subr(32) ^= subr(1);
-
-    /* absorb kw4 to other subkeys */
-    kw4l = subl(33); kw4r = subr(33);
-    subl(30) ^= kw4l; subr(30) ^= kw4r;
-    subl(28) ^= kw4l; subr(28) ^= kw4r;
-    subl(26) ^= kw4l; subr(26) ^= kw4r;
-    kw4l ^= kw4r & ~subr(24);
-    dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw);
-    subl(22) ^= kw4l; subr(22) ^= kw4r;
-    subl(20) ^= kw4l; subr(20) ^= kw4r;
-    subl(18) ^= kw4l; subr(18) ^= kw4r;
-    kw4l ^= kw4r & ~subr(16);
-    dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
-    subl(14) ^= kw4l; subr(14) ^= kw4r;
-    subl(12) ^= kw4l; subr(12) ^= kw4r;
-    subl(10) ^= kw4l; subr(10) ^= kw4r;
-    kw4l ^= kw4r & ~subr(8);
-    dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
-    subl(6) ^= kw4l; subr(6) ^= kw4r;
-    subl(4) ^= kw4l; subr(4) ^= kw4r;
-    subl(2) ^= kw4l; subr(2) ^= kw4r;
-    subl(0) ^= kw4l; subr(0) ^= kw4r;
-
-    /* key XOR is end of F-function */
-    CamelliaSubkeyL(0) = subl(0) ^ subl(2);
-    CamelliaSubkeyR(0) = subr(0) ^ subr(2);
-    CamelliaSubkeyL(2) = subl(3);
-    CamelliaSubkeyR(2) = subr(3);
-    CamelliaSubkeyL(3) = subl(2) ^ subl(4);
-    CamelliaSubkeyR(3) = subr(2) ^ subr(4);
-    CamelliaSubkeyL(4) = subl(3) ^ subl(5);
-    CamelliaSubkeyR(4) = subr(3) ^ subr(5);
-    CamelliaSubkeyL(5) = subl(4) ^ subl(6);
-    CamelliaSubkeyR(5) = subr(4) ^ subr(6);
-    CamelliaSubkeyL(6) = subl(5) ^ subl(7);
-    CamelliaSubkeyR(6) = subr(5) ^ subr(7);
-    tl = subl(10) ^ (subr(10) & ~subr(8));
-    dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(7) = subl(6) ^ tl;
-    CamelliaSubkeyR(7) = subr(6) ^ tr;
-    CamelliaSubkeyL(8) = subl(8);
-    CamelliaSubkeyR(8) = subr(8);
-    CamelliaSubkeyL(9) = subl(9);
-    CamelliaSubkeyR(9) = subr(9);
-    tl = subl(7) ^ (subr(7) & ~subr(9));
-    dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(10) = tl ^ subl(11);
-    CamelliaSubkeyR(10) = tr ^ subr(11);
-    CamelliaSubkeyL(11) = subl(10) ^ subl(12);
-    CamelliaSubkeyR(11) = subr(10) ^ subr(12);
-    CamelliaSubkeyL(12) = subl(11) ^ subl(13);
-    CamelliaSubkeyR(12) = subr(11) ^ subr(13);
-    CamelliaSubkeyL(13) = subl(12) ^ subl(14);
-    CamelliaSubkeyR(13) = subr(12) ^ subr(14);
-    CamelliaSubkeyL(14) = subl(13) ^ subl(15);
-    CamelliaSubkeyR(14) = subr(13) ^ subr(15);
-    tl = subl(18) ^ (subr(18) & ~subr(16));
-    dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(15) = subl(14) ^ tl;
-    CamelliaSubkeyR(15) = subr(14) ^ tr;
-    CamelliaSubkeyL(16) = subl(16);
-    CamelliaSubkeyR(16) = subr(16);
-    CamelliaSubkeyL(17) = subl(17);
-    CamelliaSubkeyR(17) = subr(17);
-    tl = subl(15) ^ (subr(15) & ~subr(17));
-    dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(18) = tl ^ subl(19);
-    CamelliaSubkeyR(18) = tr ^ subr(19);
-    CamelliaSubkeyL(19) = subl(18) ^ subl(20);
-    CamelliaSubkeyR(19) = subr(18) ^ subr(20);
-    CamelliaSubkeyL(20) = subl(19) ^ subl(21);
-    CamelliaSubkeyR(20) = subr(19) ^ subr(21);
-    CamelliaSubkeyL(21) = subl(20) ^ subl(22);
-    CamelliaSubkeyR(21) = subr(20) ^ subr(22);
-    CamelliaSubkeyL(22) = subl(21) ^ subl(23);
-    CamelliaSubkeyR(22) = subr(21) ^ subr(23);
-    tl = subl(26) ^ (subr(26) & ~subr(24));
-    dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(23) = subl(22) ^ tl;
-    CamelliaSubkeyR(23) = subr(22) ^ tr;
-    CamelliaSubkeyL(24) = subl(24);
-    CamelliaSubkeyR(24) = subr(24);
-    CamelliaSubkeyL(25) = subl(25);
-    CamelliaSubkeyR(25) = subr(25);
-    tl = subl(23) ^ (subr(23) &  ~subr(25));
-    dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw);
-    CamelliaSubkeyL(26) = tl ^ subl(27);
-    CamelliaSubkeyR(26) = tr ^ subr(27);
-    CamelliaSubkeyL(27) = subl(26) ^ subl(28);
-    CamelliaSubkeyR(27) = subr(26) ^ subr(28);
-    CamelliaSubkeyL(28) = subl(27) ^ subl(29);
-    CamelliaSubkeyR(28) = subr(27) ^ subr(29);
-    CamelliaSubkeyL(29) = subl(28) ^ subl(30);
-    CamelliaSubkeyR(29) = subr(28) ^ subr(30);
-    CamelliaSubkeyL(30) = subl(29) ^ subl(31);
-    CamelliaSubkeyR(30) = subr(29) ^ subr(31);
-    CamelliaSubkeyL(31) = subl(30);
-    CamelliaSubkeyR(31) = subr(30);
-    CamelliaSubkeyL(32) = subl(32) ^ subl(31);
-    CamelliaSubkeyR(32) = subr(32) ^ subr(31);
-
-    /* apply the inverse of the last half of P-function */
-    dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw;
-    dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw;
-    dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw;
-    dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw;
-    dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw;
-    dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw;
-    dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw;
-    dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw;
-    dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw;
-    dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw;
-    dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw;
-    dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw;
-    dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw;
-    dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw;
-    dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw;
-    dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw;
-    dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw;
-    dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw;
-    dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw;
-    dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw;
-    dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw;
-    dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw;
-    dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw;
-    dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw);
-    CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-static int camellia_setup192(const unsigned char *key, u32 *subkey)
-{
-    unsigned char kk[32];
-    u32 krll, krlr, krrl,krrr;
-
-    XMEMCPY(kk, key, 24);
-    XMEMCPY((unsigned char *)&krll, key+16,4);
-    XMEMCPY((unsigned char *)&krlr, key+20,4);
-    krrl = ~krll;
-    krrr = ~krlr;
-    XMEMCPY(kk+24, (unsigned char *)&krrl, 4);
-    XMEMCPY(kk+28, (unsigned char *)&krrr, 4);
-
-    return camellia_setup256(kk, subkey);
-}
-
-
-/**
- * Stuff related to camellia encryption/decryption
- *
- * "io" must be 4byte aligned and big-endian data.
- */
-static void camellia_encrypt128(const u32 *subkey, u32 *io)
-{
-    u32 il, ir, t0, t1;
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(0);
-    io[1] ^= CamelliaSubkeyR(0);
-    /* main iteration */
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(24);
-    io[3] ^= CamelliaSubkeyR(24);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-static void camellia_decrypt128(const u32 *subkey, u32 *io)
-{
-    u32 il,ir,t0,t1;               /* temporary variables */
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(24);
-    io[1] ^= CamelliaSubkeyR(24);
-
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(0);
-    io[3] ^= CamelliaSubkeyR(0);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-/**
- * stuff for 192 and 256bit encryption/decryption
- */
-static void camellia_encrypt256(const u32 *subkey, u32 *io)
-{
-    u32 il,ir,t0,t1;           /* temporary variables */
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(0);
-    io[1] ^= CamelliaSubkeyR(0);
-
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
-		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(32);
-    io[3] ^= CamelliaSubkeyR(32);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-static void camellia_decrypt256(const u32 *subkey, u32 *io)
-{
-    u32 il,ir,t0,t1;           /* temporary variables */
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(32);
-    io[1] ^= CamelliaSubkeyR(32);
-
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
-		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(0);
-    io[3] ^= CamelliaSubkeyR(0);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-/***
- *
- * API for compatibility
- */
-
-static void Camellia_EncryptBlock(const int keyBitLength,
-			   const unsigned char *plaintext,
-			   const KEY_TABLE_TYPE keyTable,
-			   unsigned char *ciphertext)
-{
-    u32 tmp[4];
-
-    tmp[0] = GETU32(plaintext);
-    tmp[1] = GETU32(plaintext + 4);
-    tmp[2] = GETU32(plaintext + 8);
-    tmp[3] = GETU32(plaintext + 12);
-
-    switch (keyBitLength) {
-    case 128:
-	camellia_encrypt128(keyTable, tmp);
-	break;
-    case 192:
-	/* fall through */
-    case 256:
-	camellia_encrypt256(keyTable, tmp);
-	break;
-    default:
-	break;
-    }
-
-    PUTU32(ciphertext, tmp[0]);
-    PUTU32(ciphertext + 4, tmp[1]);
-    PUTU32(ciphertext + 8, tmp[2]);
-    PUTU32(ciphertext + 12, tmp[3]);
-}
-
-static void Camellia_DecryptBlock(const int keyBitLength,
-			   const unsigned char *ciphertext,
-			   const KEY_TABLE_TYPE keyTable,
-			   unsigned char *plaintext)
-{
-    u32 tmp[4];
-
-    tmp[0] = GETU32(ciphertext);
-    tmp[1] = GETU32(ciphertext + 4);
-    tmp[2] = GETU32(ciphertext + 8);
-    tmp[3] = GETU32(ciphertext + 12);
-
-    switch (keyBitLength) {
-    case 128:
-	camellia_decrypt128(keyTable, tmp);
-	break;
-    case 192:
-	/* fall through */
-    case 256:
-	camellia_decrypt256(keyTable, tmp);
-	break;
-    default:
-	break;
-    }
-    PUTU32(plaintext, tmp[0]);
-    PUTU32(plaintext + 4, tmp[1]);
-    PUTU32(plaintext + 8, tmp[2]);
-    PUTU32(plaintext + 12, tmp[3]);
-}
-
-
-
-/* wolfCrypt wrappers to the Camellia code */
-
-int wc_CamelliaSetKey(Camellia* cam, const byte* key, word32 len, const byte* iv)
-{
-    int ret = 0;
-
-    if (cam == NULL) return BAD_FUNC_ARG;
-
-    XMEMSET(cam->key, 0, sizeof(KEY_TABLE_TYPE));
-
-    switch (len) {
-        case 16:
-        	ret = camellia_setup128(key, cam->key);
-            break;
-        case 24:
-        	ret = camellia_setup192(key, cam->key);
-            break;
-        case 32:
-            ret = camellia_setup256(key, cam->key);
-            break;
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    if (ret != 0)
-        return ret;
-
-    cam->keySz = len * 8;
-
-    return wc_CamelliaSetIV(cam, iv);
-}
-
-
-int wc_CamelliaSetIV(Camellia* cam, const byte* iv)
-{
-    if (cam == NULL)
-        return BAD_FUNC_ARG;
-
-    if (iv)
-        XMEMCPY(cam->reg, iv, CAMELLIA_BLOCK_SIZE);
-    else
-        XMEMSET(cam->reg,  0, CAMELLIA_BLOCK_SIZE);
-
-    return 0;
-}
-
-
-int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in)
-{
-    if (cam == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    Camellia_EncryptBlock(cam->keySz, in, cam->key, out);
-
-    return 0;
-}
-
-
-int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in)
-{
-    if (cam == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    Camellia_DecryptBlock(cam->keySz, in, cam->key, out);
-
-    return 0;
-}
-
-
-int wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz)
-{
-    word32 blocks;
-    if (cam == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    blocks = sz / CAMELLIA_BLOCK_SIZE;
-
-    while (blocks--) {
-        xorbuf((byte*)cam->reg, in, CAMELLIA_BLOCK_SIZE);
-        Camellia_EncryptBlock(cam->keySz, (byte*)cam->reg,
-                                                     cam->key, (byte*)cam->reg);
-        XMEMCPY(out, cam->reg, CAMELLIA_BLOCK_SIZE);
-
-        out += CAMELLIA_BLOCK_SIZE;
-        in  += CAMELLIA_BLOCK_SIZE;
-    }
-
-    return 0;
-}
-
-
-int wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz)
-{
-    word32 blocks;
-    if (cam == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    blocks = sz / CAMELLIA_BLOCK_SIZE;
-
-    while (blocks--) {
-        XMEMCPY(cam->tmp, in, CAMELLIA_BLOCK_SIZE);
-        Camellia_DecryptBlock(cam->keySz, (byte*)cam->tmp, cam->key, out);
-        xorbuf(out, (byte*)cam->reg, CAMELLIA_BLOCK_SIZE);
-        XMEMCPY(cam->reg, cam->tmp, CAMELLIA_BLOCK_SIZE);
-
-        out += CAMELLIA_BLOCK_SIZE;
-        in  += CAMELLIA_BLOCK_SIZE;
-    }
-
-    return 0;
-}
-
-
-#endif /* HAVE_CAMELLIA */
-
-
--- a/wolfcrypt/src/chacha.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1516 +0,0 @@
-/* chacha.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- *
- *  based from
- *  chacha-ref.c version 20080118
- *  D. J. Bernstein
- *  Public domain.
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_CHACHA
-
-#include <wolfssl/wolfcrypt/chacha.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef CHACHA_AEAD_TEST
-    #include <stdio.h>
-#endif
-
-#ifdef USE_INTEL_CHACHA_SPEEDUP
-    #include <emmintrin.h>
-    #include <immintrin.h>
-
-    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
-                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
-        #define NO_AVX2_SUPPORT
-    #endif
-    #if defined(__clang__) && ((__clang_major__ < 3) || \
-                               (__clang_major__ == 3 && __clang_minor__ <= 5))
-        #define NO_AVX2_SUPPORT
-    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
-        #undef NO_AVX2_SUPPORT
-    #endif
-
-    #ifndef NO_AVX2_SUPPORT
-        #define HAVE_INTEL_AVX2
-    #endif
-
-    #if defined(_MSC_VER)
-        #define CHACHA20_NOINLINE __declspec(noinline)
-    #elif defined(__GNUC__)
-        #define CHACHA20_NOINLINE __attribute__((noinline))
-    #else
-        #define CHACHA20_NOINLINE
-    #endif
-
-    static int cpuidFlagsSet = 0;
-    static int cpuidFlags = 0;
-#endif
-
-#ifdef BIG_ENDIAN_ORDER
-    #define LITTLE32(x) ByteReverseWord32(x)
-#else
-    #define LITTLE32(x) (x)
-#endif
-
-/* Number of rounds */
-#define ROUNDS  20
-
-#define U32C(v) (v##U)
-#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF))
-#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0])
-
-#define ROTATE(v,c) rotlFixed(v, c)
-#define XOR(v,w)    ((v) ^ (w))
-#define PLUS(v,w)   (U32V((v) + (w)))
-#define PLUSONE(v)  (PLUS((v),1))
-
-#define QUARTERROUND(a,b,c,d) \
-  x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
-  x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
-  x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
-  x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
-
-
-
-#define QUARTERROUND_INTEL_ASM(a0,b0,c0,d0,   \
-                               a1,b1,c1,d1,   \
-                               a2,b2,c2,d2,   \
-                               a3,b3,c3,d3,   \
-                               t1,o1)         \
-       "vpaddd	"#b0", "#a0", "#a0"\n\t"      \
-       "vpxor	"#a0", "#d0", "#d0"\n\t"      \
-       "vmovdqa	"#o1"(%[x]), "#c3"\n\t"       \
-       "vpshufb	%[rotl16], "#d0", "#d0"\n\t"  \
-       "vpaddd	"#d0", "#c0", "#c0"\n\t"      \
-       "vpxor	"#c0", "#b0", "#b0"\n\t"      \
-       "vpaddd	"#b1", "#a1", "#a1"\n\t"      \
-       "vpxor	"#a1", "#d1", "#d1"\n\t"      \
-       "vpshufb	%[rotl16], "#d1", "#d1"\n\t"  \
-       "vpaddd	"#d1", "#c1", "#c1"\n\t"      \
-       "vpxor	"#c1", "#b1", "#b1"\n\t"      \
-       "vpaddd	"#b2", "#a2", "#a2"\n\t"      \
-       "vpxor	"#a2", "#d2", "#d2"\n\t"      \
-       "vpshufb	%[rotl16], "#d2", "#d2"\n\t"  \
-       "vpaddd	"#d2", "#c2", "#c2"\n\t"      \
-       "vpxor	"#c2", "#b2", "#b2"\n\t"      \
-       "vpaddd	"#b3", "#a3", "#a3"\n\t"      \
-       "vpxor	"#a3", "#d3", "#d3"\n\t"      \
-       "vpshufb	%[rotl16], "#d3", "#d3"\n\t"  \
-       "vpaddd  "#d3", "#c3", "#c3"\n\t"      \
-       "vpxor	"#c3", "#b3", "#b3"\n\t"      \
-       "vmovdqa	"#c3", "#o1"(%[x])\n\t"       \
-       "vpsrld	$20, "#b0", "#t1"\n\t"        \
-       "vpslld	$12, "#b0", "#b0"\n\t"        \
-       "vpxor	"#t1", "#b0", "#b0"\n\t"      \
-       "vpsrld	$20, "#b1", "#t1"\n\t"        \
-       "vpslld	$12, "#b1", "#b1"\n\t"        \
-       "vpxor	"#t1", "#b1", "#b1"\n\t"      \
-       "vpsrld	$20, "#b2", "#t1"\n\t"        \
-       "vpslld	$12, "#b2", "#b2"\n\t"        \
-       "vpxor	"#t1", "#b2", "#b2"\n\t"      \
-       "vpsrld	$20, "#b3", "#t1"\n\t"        \
-       "vpslld	$12, "#b3", "#b3"\n\t"        \
-       "vpxor	"#t1", "#b3", "#b3"\n\t"      \
-       "vpaddd	"#b0", "#a0", "#a0"\n\t"      \
-       "vpxor	"#a0", "#d0", "#d0"\n\t"      \
-       "vmovdqa	"#o1"(%[x]), "#c3"\n\t"       \
-       "vpshufb	%[rotl8], "#d0", "#d0"\n\t"   \
-       "vpaddd	"#d0", "#c0", "#c0"\n\t"      \
-       "vpxor	"#c0", "#b0", "#b0"\n\t"      \
-       "vpaddd	"#b1", "#a1", "#a1"\n\t"      \
-       "vpxor	"#a1", "#d1", "#d1"\n\t"      \
-       "vpshufb	%[rotl8], "#d1", "#d1"\n\t"   \
-       "vpaddd	"#d1", "#c1", "#c1"\n\t"      \
-       "vpxor	"#c1", "#b1", "#b1"\n\t"      \
-       "vpaddd	"#b2", "#a2", "#a2"\n\t"      \
-       "vpxor	"#a2", "#d2", "#d2"\n\t"      \
-       "vpshufb	%[rotl8], "#d2", "#d2"\n\t"   \
-       "vpaddd	"#d2", "#c2", "#c2"\n\t"      \
-       "vpxor	"#c2", "#b2", "#b2"\n\t"      \
-       "vpaddd	"#b3", "#a3", "#a3"\n\t"      \
-       "vpxor	"#a3", "#d3", "#d3"\n\t"      \
-       "vpshufb	%[rotl8], "#d3", "#d3"\n\t"   \
-       "vpaddd	"#d3", "#c3", "#c3"\n\t"      \
-       "vpxor	"#c3", "#b3", "#b3"\n\t"      \
-       "vmovdqa	"#c3", "#o1"(%[x])\n\t"       \
-       "vpsrld	$25, "#b0", "#t1"\n\t"        \
-       "vpslld	 $7, "#b0", "#b0"\n\t"        \
-       "vpxor	"#t1", "#b0", "#b0"\n\t"      \
-       "vpsrld	$25, "#b1", "#t1"\n\t"        \
-       "vpslld	 $7, "#b1", "#b1"\n\t"        \
-       "vpxor	"#t1", "#b1", "#b1"\n\t"      \
-       "vpsrld	$25, "#b2", "#t1"\n\t"        \
-       "vpslld	 $7, "#b2", "#b2"\n\t"        \
-       "vpxor	"#t1", "#b2", "#b2"\n\t"      \
-       "vpsrld	$25, "#b3", "#t1"\n\t"        \
-       "vpslld	 $7, "#b3", "#b3"\n\t"        \
-       "vpxor	"#t1", "#b3", "#b3"\n\t"
-
-#define QUARTERROUND_INTEL_ASM_2(a0,b0,c0,d0, \
-                                 a1,b1,c1,d1, \
-                                 a2,b2,c2,d2, \
-                                 a3,b3,c3,d3, \
-                                 t1,o1)       \
-       "vpaddd	"#b0", "#a0", "#a0"\n\t"      \
-       "vpxor	"#a0", "#d0", "#d0"\n\t"      \
-       "vmovdqa	"#o1"(%[x]), "#c1"\n\t"       \
-       "vpshufb	%[rotl16], "#d0", "#d0"\n\t"  \
-       "vpaddd	"#d0", "#c0", "#c0"\n\t"      \
-       "vpxor	"#c0", "#b0", "#b0"\n\t"      \
-       "vpaddd	"#b1", "#a1", "#a1"\n\t"      \
-       "vpxor	"#a1", "#d1", "#d1"\n\t"      \
-       "vpshufb	%[rotl16], "#d1", "#d1"\n\t"  \
-       "vpaddd	"#d1", "#c1", "#c1"\n\t"      \
-       "vpxor	"#c1", "#b1", "#b1"\n\t"      \
-       "vpaddd	"#b2", "#a2", "#a2"\n\t"      \
-       "vpxor	"#a2", "#d2", "#d2"\n\t"      \
-       "vpshufb	%[rotl16], "#d2", "#d2"\n\t"  \
-       "vpaddd	"#d2", "#c2", "#c2"\n\t"      \
-       "vpxor	"#c2", "#b2", "#b2"\n\t"      \
-       "vpaddd	"#b3", "#a3", "#a3"\n\t"      \
-       "vpxor	"#a3", "#d3", "#d3"\n\t"      \
-       "vpshufb	%[rotl16], "#d3", "#d3"\n\t"  \
-       "vpaddd	"#d3", "#c3", "#c3"\n\t"      \
-       "vpxor	"#c3", "#b3", "#b3"\n\t"      \
-       "vmovdqa	"#c1", "#o1"(%[x])\n\t"       \
-       "vpsrld	$20, "#b0", "#t1"\n\t"        \
-       "vpslld	$12, "#b0", "#b0"\n\t"        \
-       "vpxor	"#t1", "#b0", "#b0"\n\t"      \
-       "vpsrld	$20, "#b1", "#t1"\n\t"        \
-       "vpslld	$12, "#b1", "#b1"\n\t"        \
-       "vpxor	"#t1", "#b1", "#b1"\n\t"      \
-       "vpsrld	$20, "#b2", "#t1"\n\t"        \
-       "vpslld	$12, "#b2", "#b2"\n\t"        \
-       "vpxor	"#t1", "#b2", "#b2"\n\t"      \
-       "vpsrld	$20, "#b3", "#t1"\n\t"        \
-       "vpslld	$12, "#b3", "#b3"\n\t"        \
-       "vpxor	"#t1", "#b3", "#b3"\n\t"      \
-       "vpaddd	"#b0", "#a0", "#a0"\n\t"      \
-       "vpxor	"#a0", "#d0", "#d0"\n\t"      \
-       "vmovdqa	"#o1"(%[x]), "#c1"\n\t"       \
-       "vpshufb	%[rotl8], "#d0", "#d0"\n\t"   \
-       "vpaddd	"#d0", "#c0", "#c0"\n\t"      \
-       "vpxor	"#c0", "#b0", "#b0"\n\t"      \
-       "vpaddd	"#b1", "#a1", "#a1"\n\t"      \
-       "vpxor	"#a1", "#d1", "#d1"\n\t"      \
-       "vpshufb	%[rotl8], "#d1", "#d1"\n\t"   \
-       "vpaddd	"#d1", "#c1", "#c1"\n\t"      \
-       "vpxor	"#c1", "#b1", "#b1"\n\t"      \
-       "vpaddd	"#b2", "#a2", "#a2"\n\t"      \
-       "vpxor	"#a2", "#d2", "#d2"\n\t"      \
-       "vpshufb	%[rotl8], "#d2", "#d2"\n\t"   \
-       "vpaddd	"#d2", "#c2", "#c2"\n\t"      \
-       "vpxor	"#c2", "#b2", "#b2"\n\t"      \
-       "vpaddd	"#b3", "#a3", "#a3"\n\t"      \
-       "vpxor	"#a3", "#d3", "#d3"\n\t"      \
-       "vpshufb	%[rotl8], "#d3", "#d3"\n\t"   \
-       "vpaddd	"#d3", "#c3", "#c3"\n\t"      \
-       "vpxor	"#c3", "#b3", "#b3"\n\t"      \
-       "vmovdqa	"#c1", "#o1"(%[x])\n\t"       \
-       "vpsrld	$25, "#b0", "#t1"\n\t"        \
-       "vpslld	 $7, "#b0", "#b0"\n\t"        \
-       "vpxor	"#t1", "#b0", "#b0"\n\t"      \
-       "vpsrld	$25, "#b1", "#t1"\n\t"        \
-       "vpslld	 $7, "#b1", "#b1"\n\t"        \
-       "vpxor	"#t1", "#b1", "#b1"\n\t"      \
-       "vpsrld	$25, "#b2", "#t1"\n\t"        \
-       "vpslld	 $7, "#b2", "#b2"\n\t"        \
-       "vpxor	"#t1", "#b2", "#b2"\n\t"      \
-       "vpsrld	$25, "#b3", "#t1"\n\t"        \
-       "vpslld	 $7, "#b3", "#b3"\n\t"        \
-       "vpxor	"#t1", "#b3", "#b3"\n\t"
-
-
-#define QUARTERROUND_XMM()                                      \
-        QUARTERROUND_INTEL_ASM(%%xmm0,%%xmm4,%%xmm8,%%xmm12,    \
-                               %%xmm1,%%xmm5,%%xmm9,%%xmm13,    \
-                               %%xmm2,%%xmm6,%%xmm10,%%xmm14,   \
-                               %%xmm3,%%xmm7,%%xmm11,%%xmm15,   \
-                               %%xmm11,48)
-#define QUARTERROUND_XMM_2()                                    \
-        QUARTERROUND_INTEL_ASM_2(%%xmm0,%%xmm5,%%xmm10,%%xmm15, \
-                                 %%xmm1,%%xmm6,%%xmm11,%%xmm12, \
-                                 %%xmm2,%%xmm7,%%xmm8,%%xmm13,  \
-                                 %%xmm3,%%xmm4,%%xmm9,%%xmm14,  \
-                                 %%xmm11,48)
-
-#define QUARTERROUND_YMM()                                      \
-        QUARTERROUND_INTEL_ASM(%%ymm0,%%ymm4,%%ymm8,%%ymm12,    \
-                               %%ymm1,%%ymm5,%%ymm9,%%ymm13,    \
-                               %%ymm2,%%ymm6,%%ymm10,%%ymm14,   \
-                               %%ymm3,%%ymm7,%%ymm11,%%ymm15,   \
-                               %%ymm11,96)
-#define QUARTERROUND_YMM_2()                                    \
-        QUARTERROUND_INTEL_ASM_2(%%ymm0,%%ymm5,%%ymm10,%%ymm15, \
-                                 %%ymm1,%%ymm6,%%ymm11,%%ymm12, \
-                                 %%ymm2,%%ymm7,%%ymm8,%%ymm13,  \
-                                 %%ymm3,%%ymm4,%%ymm9,%%ymm14,  \
-                                 %%ymm11,96)
-
-/**
-  * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version
-  * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB.
-  */
-int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter)
-{
-    word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */
-
-#ifdef CHACHA_AEAD_TEST
-    word32 i;
-    printf("NONCE : ");
-    for (i = 0; i < CHACHA_IV_BYTES; i++) {
-        printf("%02x", inIv[i]);
-    }
-    printf("\n\n");
-#endif
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(temp, inIv, CHACHA_IV_BYTES);
-
-    ctx->X[CHACHA_IV_BYTES+0] = counter;           /* block counter */
-    ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */
-    ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */
-    ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */
-
-    return 0;
-}
-
-/* "expand 32-byte k" as unsigned 32 byte */
-static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
-/* "expand 16-byte k" as unsigned 16 byte */
-static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574};
-
-/**
-  * Key setup. 8 word iv (nonce)
-  */
-int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz)
-{
-    const word32* constants;
-    const byte*   k;
-
-#ifdef XSTREAM_ALIGN
-    word32 alignKey[8];
-#endif
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-    if (keySz != (CHACHA_MAX_KEY_SZ/2) && keySz != CHACHA_MAX_KEY_SZ)
-        return BAD_FUNC_ARG;
-
-#ifdef XSTREAM_ALIGN
-    if ((wolfssl_word)key % 4) {
-        WOLFSSL_MSG("wc_ChachaSetKey unaligned key");
-        XMEMCPY(alignKey, key, keySz);
-        k = (byte*)alignKey;
-    }
-    else {
-        k = key;
-    }
-#else
-    k = key;
-#endif /* XSTREAM_ALIGN */
-
-#ifdef CHACHA_AEAD_TEST
-    word32 i;
-    printf("ChaCha key used :\n");
-    for (i = 0; i < keySz; i++) {
-        printf("%02x", key[i]);
-        if ((i + 1) % 8 == 0)
-           printf("\n");
-    }
-    printf("\n\n");
-#endif
-
-    ctx->X[4] = U8TO32_LITTLE(k +  0);
-    ctx->X[5] = U8TO32_LITTLE(k +  4);
-    ctx->X[6] = U8TO32_LITTLE(k +  8);
-    ctx->X[7] = U8TO32_LITTLE(k + 12);
-    if (keySz == CHACHA_MAX_KEY_SZ) {
-        k += 16;
-        constants = sigma;
-    }
-    else {
-        constants = tau;
-    }
-    ctx->X[ 8] = U8TO32_LITTLE(k +  0);
-    ctx->X[ 9] = U8TO32_LITTLE(k +  4);
-    ctx->X[10] = U8TO32_LITTLE(k +  8);
-    ctx->X[11] = U8TO32_LITTLE(k + 12);
-    ctx->X[ 0] = constants[0];
-    ctx->X[ 1] = constants[1];
-    ctx->X[ 2] = constants[2];
-    ctx->X[ 3] = constants[3];
-
-    return 0;
-}
-
-/**
-  * Converts word into bytes with rotations having been done.
-  */
-static WC_INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS],
-    const word32 input[CHACHA_CHUNK_WORDS])
-{
-    word32 x[CHACHA_CHUNK_WORDS];
-    word32 i;
-
-    for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
-        x[i] = input[i];
-    }
-
-    for (i = (ROUNDS); i > 0; i -= 2) {
-        QUARTERROUND(0, 4,  8, 12)
-        QUARTERROUND(1, 5,  9, 13)
-        QUARTERROUND(2, 6, 10, 14)
-        QUARTERROUND(3, 7, 11, 15)
-        QUARTERROUND(0, 5, 10, 15)
-        QUARTERROUND(1, 6, 11, 12)
-        QUARTERROUND(2, 7,  8, 13)
-        QUARTERROUND(3, 4,  9, 14)
-    }
-
-    for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
-        x[i] = PLUS(x[i], input[i]);
-    }
-
-    for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
-        output[i] = LITTLE32(x[i]);
-    }
-}
-
-
-#ifdef USE_INTEL_CHACHA_SPEEDUP
-
-#define QUARTERROUND_2_X64(r11, r12, r13, r14, r21, r22, r23, r24) \
-        "addl	"#r12", "#r11"\n\t"                                \
-        "addl	"#r22", "#r21"\n\t"                                \
-        "xorl	"#r11", "#r14"\n\t"                                \
-        "xorl	"#r21", "#r24"\n\t"                                \
-        "roll	$16, "#r14"\n\t"                                   \
-        "roll	$16, "#r24"\n\t"                                   \
-        "addl	"#r14", "#r13"\n\t"                                \
-        "addl	"#r24", "#r23"\n\t"                                \
-        "xorl	"#r13", "#r12"\n\t"                                \
-        "xorl	"#r23", "#r22"\n\t"                                \
-        "roll	$12, "#r12"\n\t"                                   \
-        "roll	$12, "#r22"\n\t"                                   \
-        "addl	"#r12", "#r11"\n\t"                                \
-        "addl	"#r22", "#r21"\n\t"                                \
-        "xorl	"#r11", "#r14"\n\t"                                \
-        "xorl	"#r21", "#r24"\n\t"                                \
-        "roll	$8, "#r14"\n\t"                                    \
-        "roll	$8, "#r24"\n\t"                                    \
-        "addl	"#r14", "#r13"\n\t"                                \
-        "addl	"#r24", "#r23"\n\t"                                \
-        "xorl	"#r13", "#r12"\n\t"                                \
-        "xorl	"#r23", "#r22"\n\t"                                \
-        "roll	$7, "#r12"\n\t"                                    \
-        "roll	$7, "#r22"\n\t"                                    \
-
-#define CHACHA_CRYPT_X64()                                                     \
-        "subq	$40, %%rsp\n\t"                                                \
-        "movq	32(%[input]), %%rax\n\t"                                       \
-        "movq	40(%[input]), %%rdx\n\t"                                       \
-        "movq	%%rax,  8(%%rsp)\n\t"                                          \
-        "movq	%%rdx, 16(%%rsp)\n\t"                                          \
-        "movl	 0(%[input]), %%eax\n\t"                                       \
-        "movl	 4(%[input]), %%ebx\n\t"                                       \
-        "movl	 8(%[input]), %%ecx\n\t"                                       \
-        "movl	12(%[input]), %%edx\n\t"                                       \
-        "movl	16(%[input]), %%r8d\n\t"                                       \
-        "movl	20(%[input]), %%r9d\n\t"                                       \
-        "movl	24(%[input]), %%r10d\n\t"                                      \
-        "movl	28(%[input]), %%r11d\n\t"                                      \
-        "movl	48(%[input]), %%r12d\n\t"                                      \
-        "movl	52(%[input]), %%r13d\n\t"                                      \
-        "movl	56(%[input]), %%r14d\n\t"                                      \
-        "movl	60(%[input]), %%r15d\n\t"                                      \
-        "movb	$10, (%%rsp)\n\t"                                              \
-        "movq	%%rsi, 32(%%rsp)\n\t"                                          \
-        "movq	%%rdi, 24(%%rsp)\n\t"                                          \
-        "movl	 8(%%rsp), %%esi\n\t"                                          \
-        "movl	12(%%rsp), %%edi\n\t"                                          \
-        "\n"                                                                   \
-        "1:\n\t"                                                               \
-        QUARTERROUND_2_X64(%%eax,  %%r8d, %%esi, %%r12d,                       \
-                           %%ebx,  %%r9d, %%edi, %%r13d)                       \
-        "movl	%%esi,  8(%%rsp)\n\t"                                          \
-        "movl	%%edi, 12(%%rsp)\n\t"                                          \
-        "movl	16(%%rsp), %%esi\n\t"                                          \
-        "movl	20(%%rsp), %%edi\n\t"                                          \
-        QUARTERROUND_2_X64(%%ecx, %%r10d, %%esi, %%r14d,                       \
-                           %%edx, %%r11d, %%edi, %%r15d)                       \
-        QUARTERROUND_2_X64(%%eax,  %%r9d, %%esi, %%r15d,                       \
-                           %%ebx, %%r10d, %%edi, %%r12d)                       \
-        "movl	%%esi, 16(%%rsp)\n\t"                                          \
-        "movl	%%edi, 20(%%rsp)\n\t"                                          \
-        "movl	 8(%%rsp), %%esi\n\t"                                          \
-        "movl	12(%%rsp), %%edi\n\t"                                          \
-        QUARTERROUND_2_X64(%%ecx, %%r11d, %%esi, %%r13d,                       \
-                           %%edx,  %%r8d, %%edi, %%r14d)                       \
-        "decb	(%%rsp)\n\t"                                                   \
-        "jnz	1b\n\t"                                                        \
-        "movl	%%esi,  8(%%rsp)\n\t"                                          \
-        "movl	%%edi, 12(%%rsp)\n\t"                                          \
-        "movq	32(%%rsp), %%rsi\n\t"                                          \
-        "movq	24(%%rsp), %%rdi\n\t"                                          \
-        "addl	 0(%[input]), %%eax\n\t"                                       \
-        "addl	 4(%[input]), %%ebx\n\t"                                       \
-        "addl	 8(%[input]), %%ecx\n\t"                                       \
-        "addl	12(%[input]), %%edx\n\t"                                       \
-        "addl	16(%[input]), %%r8d\n\t"                                       \
-        "addl	20(%[input]), %%r9d\n\t"                                       \
-        "addl	24(%[input]), %%r10d\n\t"                                      \
-        "addl	28(%[input]), %%r11d\n\t"                                      \
-        "addl	48(%[input]), %%r12d\n\t"                                      \
-        "addl	52(%[input]), %%r13d\n\t"                                      \
-        "addl	56(%[input]), %%r14d\n\t"                                      \
-        "addl	60(%[input]), %%r15d\n\t"                                      \
-
-#define CHACHA_PARTIAL_CHUNK_X64()                                             \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_X64()                                                     \
-        "movl	%%eax ,  0(%[c])\n\t"                                          \
-        "movl	%%ebx ,  4(%[c])\n\t"                                          \
-        "movl	%%ecx ,  8(%[c])\n\t"                                          \
-        "movl	%%edx , 12(%[c])\n\t"                                          \
-        "movl	%%r8d , 16(%[c])\n\t"                                          \
-        "movl	%%r9d , 20(%[c])\n\t"                                          \
-        "movl	%%r10d, 24(%[c])\n\t"                                          \
-        "movl	%%r11d, 28(%[c])\n\t"                                          \
-        "movl	%%r12d, 48(%[c])\n\t"                                          \
-        "movl	%%r13d, 52(%[c])\n\t"                                          \
-        "movl	%%r14d, 56(%[c])\n\t"                                          \
-        "movl	%%r15d, 60(%[c])\n\t"                                          \
-        "movl	 8(%%rsp), %%eax\n\t"                                          \
-        "movl	12(%%rsp), %%ebx\n\t"                                          \
-        "movl	16(%%rsp), %%ecx\n\t"                                          \
-        "movl	20(%%rsp), %%edx\n\t"                                          \
-        "addl	32(%[input]), %%eax\n\t"                                       \
-        "addl	36(%[input]), %%ebx\n\t"                                       \
-        "addl	40(%[input]), %%ecx\n\t"                                       \
-        "addl	44(%[input]), %%edx\n\t"                                       \
-        "movl	%%eax , 32(%[c])\n\t"                                          \
-        "movl	%%ebx , 36(%[c])\n\t"                                          \
-        "movl	%%ecx , 40(%[c])\n\t"                                          \
-        "movl	%%edx , 44(%[c])\n\t"                                          \
-        "addl	$1, 48(%[input])\n\t"                                          \
-        "addq	$40, %%rsp\n\t"                                                \
-        "movq	%[output], %%rax\n\t"                                          \
-        "movq	%[m], %%rbx\n\t"                                               \
-        "movl	%[bytes], %%r8d\n\t"                                           \
-        "xorq	%%rdx, %%rdx\n\t"                                              \
-        "movl	%%r8d, %%r9d\n\t"                                              \
-        "andl	$7, %%r9d\n\t"                                                 \
-        "jz	4f\n\t"                                                        \
-        "\n"                                                                   \
-        "2:\n\t"                                                               \
-        "movzbl	(%[c],%%rdx,1), %%ecx\n\t"                                     \
-        "xorb	(%%rbx,%%rdx,1), %%cl\n\t"                                     \
-        "movb	%%cl, (%%rax,%%rdx,1)\n\t"                                     \
-        "incl	%%edx\n\t"                                                     \
-        "cmpl	%%r9d, %%edx\n\t"                                              \
-        "jne	2b\n\t"                                                        \
-        "je	3f\n\t"                                                        \
-        "\n"                                                                   \
-        "4:\n\t"                                                               \
-        "movq	(%[c],%%rdx,1), %%rcx\n\t"                                     \
-        "xorq	(%%rbx,%%rdx,1), %%rcx\n\t"                                    \
-        "movq	%%rcx, (%%rax,%%rdx,1)\n\t"                                    \
-        "addl	$8, %%edx\n\t"                                                 \
-        "\n"                                                                   \
-        "3:\n\t"                                                               \
-        "cmpl	%%r8d, %%edx\n\t"                                              \
-        "jne	4b\n\t"                                                        \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (x),                                   \
-          [output] "m" (c), [bytes] "m" (bytes), [m] "m" (m)                   \
-        : "eax", "ebx", "ecx", "edx", "r8", "r9", "r10", "r11", "r12", "r13",  \
-          "r14", "r15", "memory"                                               \
-    )
-
-
-#define CHACHA_CHUNK_X64()                                                     \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_X64()                                                     \
-        "movq	%%rsi, 32(%%rsp)\n\t"                                          \
-        "addq	$40, %%rsp\n\t"                                                \
-        "movq	%[m], %%rsi\n\t"                                               \
-        "subq	$40, %%rsp\n\t"                                                \
-        "xorl	 0(%%rsi), %%eax\n\t"                                          \
-        "xorl	 4(%%rsi), %%ebx\n\t"                                          \
-        "xorl	 8(%%rsi), %%ecx\n\t"                                          \
-        "xorl	12(%%rsi), %%edx\n\t"                                          \
-        "xorl	16(%%rsi), %%r8d\n\t"                                          \
-        "xorl	20(%%rsi), %%r9d\n\t"                                          \
-        "xorl	24(%%rsi), %%r10d\n\t"                                         \
-        "xorl	28(%%rsi), %%r11d\n\t"                                         \
-        "xorl	48(%%rsi), %%r12d\n\t"                                         \
-        "xorl	52(%%rsi), %%r13d\n\t"                                         \
-        "xorl	56(%%rsi), %%r14d\n\t"                                         \
-        "xorl	60(%%rsi), %%r15d\n\t"                                         \
-        "movq	32(%%rsp), %%rsi\n\t"                                          \
-        "movl	%%eax ,  0(%[c])\n\t"                                          \
-        "movl	%%ebx ,  4(%[c])\n\t"                                          \
-        "movl	%%ecx ,  8(%[c])\n\t"                                          \
-        "movl	%%edx , 12(%[c])\n\t"                                          \
-        "movl	%%r8d , 16(%[c])\n\t"                                          \
-        "movl	%%r9d , 20(%[c])\n\t"                                          \
-        "movl	%%r10d, 24(%[c])\n\t"                                          \
-        "movl	%%r11d, 28(%[c])\n\t"                                          \
-        "movl	%%r12d, 48(%[c])\n\t"                                          \
-        "movl	%%r13d, 52(%[c])\n\t"                                          \
-        "movl	%%r14d, 56(%[c])\n\t"                                          \
-        "movl	%%r15d, 60(%[c])\n\t"                                          \
-        "addq	$40, %%rsp\n\t"                                                \
-        "movq	%[m], %%r8\n\t"                                                \
-        "subq	$40, %%rsp\n\t"                                                \
-        "movl	 8(%%rsp), %%eax\n\t"                                          \
-        "movl	12(%%rsp), %%ebx\n\t"                                          \
-        "movl	16(%%rsp), %%ecx\n\t"                                          \
-        "movl	20(%%rsp), %%edx\n\t"                                          \
-        "addl	32(%[input]), %%eax\n\t"                                       \
-        "addl	36(%[input]), %%ebx\n\t"                                       \
-        "addl	40(%[input]), %%ecx\n\t"                                       \
-        "addl	44(%[input]), %%edx\n\t"                                       \
-        "xorl	32(%%r8), %%eax\n\t"                                           \
-        "xorl	36(%%r8), %%ebx\n\t"                                           \
-        "xorl	40(%%r8), %%ecx\n\t"                                           \
-        "xorl	44(%%r8), %%edx\n\t"                                           \
-        "movl	%%eax , 32(%[c])\n\t"                                          \
-        "movl	%%ebx , 36(%[c])\n\t"                                          \
-        "movl	%%ecx , 40(%[c])\n\t"                                          \
-        "movl	%%edx , 44(%[c])\n\t"                                          \
-        "addl	$1, 48(%[input])\n\t"                                          \
-        "addq	$40, %%rsp\n\t"                                                \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (c), [m] "m" (m)                       \
-        : "eax", "ebx", "ecx", "edx", "r8", "r9", "r10", "r11", "r12", "r13",  \
-          "r14", "r15", "memory"                                               \
-    )
-
-
-static void chacha_encrypt_x64(ChaCha* ctx, const byte* m, byte* c,
-                               word32 bytes)
-{
-    word32 x[CHACHA_CHUNK_WORDS];
-
-    if (bytes == 0)
-        return;
-
-    for (; bytes >= CHACHA_CHUNK_BYTES;) {
-        CHACHA_CHUNK_X64();
-        bytes -= CHACHA_CHUNK_BYTES;
-        c += CHACHA_CHUNK_BYTES;
-        m += CHACHA_CHUNK_BYTES;
-    }
-    if (bytes > 0) {
-        CHACHA_PARTIAL_CHUNK_X64();
-    }
-}
-
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-static const __m128i rotl8 =  { 0x0605040702010003UL,0x0e0d0c0f0a09080bUL };
-static const __m128i rotl16 = { 0x0504070601000302UL,0x0d0c0f0e09080b0aUL };
-#endif /* HAVE_INTEL_AVX1 || HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX1
-#define QUARTERROUND_2_AVX()               \
-        "paddd	%%xmm1, %%xmm0\n\t"        \
-        "pxor	%%xmm0, %%xmm3\n\t"        \
-        "pshufb	%[rotl16], %%xmm3\n\t"     \
-        "paddd	%%xmm3, %%xmm2\n\t"        \
-        "pxor	%%xmm2, %%xmm1\n\t"        \
-        "movdqa	%%xmm1, %%xmm4\n\t"        \
-        "pslld	$12, %%xmm1\n\t"           \
-        "psrld	$20, %%xmm4\n\t"           \
-        "pxor	%%xmm4, %%xmm1\n\t"        \
-        "paddd	%%xmm1, %%xmm0\n\t"        \
-        "pxor	%%xmm0, %%xmm3\n\t"        \
-        "pshufb	%[rotl8], %%xmm3\n\t"      \
-        "paddd	%%xmm3, %%xmm2\n\t"        \
-        "pxor	%%xmm2, %%xmm1\n\t"        \
-        "movdqa	%%xmm1, %%xmm4\n\t"        \
-        "pslld	$7, %%xmm1\n\t"            \
-        "psrld	$25, %%xmm4\n\t"           \
-        "pxor	%%xmm4, %%xmm1\n\t"        \
-        "# Swap words for next round\n\t"  \
-        "pshufd	$0x39, %%xmm1, %%xmm1\n\t" \
-        "pshufd	$0x4e, %%xmm2, %%xmm2\n\t" \
-        "pshufd	$0x93, %%xmm3, %%xmm3\n\t" \
-        "paddd	%%xmm1, %%xmm0\n\t"        \
-        "pxor	%%xmm0, %%xmm3\n\t"        \
-        "pshufb	%[rotl16], %%xmm3\n\t"     \
-        "paddd	%%xmm3, %%xmm2\n\t"        \
-        "pxor	%%xmm2, %%xmm1\n\t"        \
-        "movdqa	%%xmm1, %%xmm4\n\t"        \
-        "pslld	$12, %%xmm1\n\t"           \
-        "psrld	$20, %%xmm4\n\t"           \
-        "pxor	%%xmm4, %%xmm1\n\t"        \
-        "paddd	%%xmm1, %%xmm0\n\t"        \
-        "pxor	%%xmm0, %%xmm3\n\t"        \
-        "pshufb	%[rotl8], %%xmm3\n\t"      \
-        "paddd	%%xmm3, %%xmm2\n\t"        \
-        "pxor	%%xmm2, %%xmm1\n\t"        \
-        "movdqa	%%xmm1, %%xmm4\n\t"        \
-        "pslld	$7, %%xmm1\n\t"            \
-        "psrld	$25, %%xmm4\n\t"           \
-        "pxor	%%xmm4, %%xmm1\n\t"        \
-        "# Swap words back\n\t"            \
-        "pshufd	$0x93, %%xmm1, %%xmm1\n\t" \
-        "pshufd	$0x4e, %%xmm2, %%xmm2\n\t" \
-        "pshufd	$0x39, %%xmm3, %%xmm3\n\t" \
-
-#define CHACHA_CRYPT_AVX()                                                     \
-        "movdqu	 0(%[input]), %%xmm0\n\t"                                      \
-        "movdqu	16(%[input]), %%xmm1\n\t"                                      \
-        "movdqu	32(%[input]), %%xmm2\n\t"                                      \
-        "movdqu	48(%[input]), %%xmm3\n\t"                                      \
-        "movb	$10, %%al\n\t"                                                 \
-        "\n"                                                                   \
-        "1:\n\t"                                                               \
-        QUARTERROUND_2_AVX()                                                   \
-        "decb	%%al\n\t"                                                      \
-        "jnz	1b\n\t"                                                        \
-        "movdqu	 0(%[input]), %%xmm4\n\t"                                      \
-        "movdqu	16(%[input]), %%xmm5\n\t"                                      \
-        "movdqu	32(%[input]), %%xmm6\n\t"                                      \
-        "movdqu	48(%[input]), %%xmm7\n\t"                                      \
-        "paddd	%%xmm4, %%xmm0\n\t"                                            \
-        "paddd	%%xmm5, %%xmm1\n\t"                                            \
-        "paddd	%%xmm6, %%xmm2\n\t"                                            \
-        "paddd	%%xmm7, %%xmm3\n\t"                                            \
-
-#define CHACHA_PARTIAL_CHUNK_AVX()                                             \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_AVX()                                                     \
-        "movdqu	%%xmm0,  0(%[c])\n\t"                                          \
-        "movdqu	%%xmm1, 16(%[c])\n\t"                                          \
-        "movdqu	%%xmm2, 32(%[c])\n\t"                                          \
-        "movdqu	%%xmm3, 48(%[c])\n\t"                                          \
-        "addl	$1, 48(%[input])\n\t"                                          \
-        "movl	%[bytes], %%r8d\n\t"                                           \
-        "xorq	%%rdx, %%rdx\n\t"                                              \
-        "movl	%%r8d, %%r9d\n\t"                                              \
-        "andl	$7, %%r9d\n\t"                                                 \
-        "jz	4f\n\t"                                                        \
-        "\n"                                                                   \
-        "2:\n\t"                                                               \
-        "movzbl	(%[c],%%rdx,1), %%ecx\n\t"                                     \
-        "xorb	(%[m],%%rdx,1), %%cl\n\t"                                      \
-        "movb	%%cl, (%[output],%%rdx,1)\n\t"                                 \
-        "incl	%%edx\n\t"                                                     \
-        "cmpl	%%r9d, %%edx\n\t"                                              \
-        "jne	2b\n\t"                                                        \
-        "je	3f\n\t"                                                        \
-        "\n"                                                                   \
-        "4:\n\t"                                                               \
-        "movq	(%[c],%%rdx,1), %%rcx\n\t"                                     \
-        "xorq	(%[m],%%rdx,1), %%rcx\n\t"                                     \
-        "movq	%%rcx, (%[output],%%rdx,1)\n\t"                                \
-        "addl	$8, %%edx\n\t"                                                 \
-        "\n"                                                                   \
-        "3:\n\t"                                                               \
-        "cmpl	%%r8d, %%edx\n\t"                                              \
-        "jne	4b\n\t"                                                        \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (x),                                   \
-          [output] "r" (c), [bytes] "r" (bytes), [m] "r" (m),                  \
-          [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16)                       \
-        : "eax", "ecx", "edx", "r8", "r9", "memory",                           \
-          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"       \
-    )
-
-
-#define CHACHA_CHUNK_AVX()                                                     \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_AVX()                                                     \
-        "movdqu	 0(%[m]), %%xmm4\n\t"                                          \
-        "movdqu	16(%[m]), %%xmm5\n\t"                                          \
-        "movdqu	32(%[m]), %%xmm6\n\t"                                          \
-        "movdqu	48(%[m]), %%xmm7\n\t"                                          \
-        "pxor	%%xmm4, %%xmm0\n\t"                                            \
-        "pxor	%%xmm5, %%xmm1\n\t"                                            \
-        "pxor	%%xmm6, %%xmm2\n\t"                                            \
-        "pxor	%%xmm7, %%xmm3\n\t"                                            \
-        "movdqu	%%xmm0,  0(%[c])\n\t"                                          \
-        "movdqu	%%xmm1, 16(%[c])\n\t"                                          \
-        "movdqu	%%xmm2, 32(%[c])\n\t"                                          \
-        "movdqu	%%xmm3, 48(%[c])\n\t"                                          \
-        "addl	$1, 48(%[input])\n\t"                                          \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (c), [m] "r" (m),                      \
-          [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16)                       \
-        : "rax", "memory",                                                     \
-          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"       \
-    )
-
-CHACHA20_NOINLINE static void chacha_encrypt_avx(ChaCha* ctx, const byte* m,
-                                                 byte* c, word32 bytes)
-{
-    ALIGN128 word32 X[4*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
-    ALIGN128 word32 x[2*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
-    word32 cnt = 0;
-    static const __m128i add =    { 0x0000000100000000UL,0x0000000300000002UL };
-    static const __m128i four =   { 0x0000000400000004UL,0x0000000400000004UL };
-
-    if (bytes == 0)
-        return;
-
-    __asm__ __volatile__ (
-       "movl	%[bytes], %[cnt]\n\t"
-       "shrl	$8, %[cnt]\n\t"
-       "jz      L_end128\n\t"
-
-       "vpshufd	$0,   (%[key]), %%xmm0\n\t"
-       "vpshufd	$0,  4(%[key]), %%xmm1\n\t"
-       "vpshufd	$0,  8(%[key]), %%xmm2\n\t"
-       "vpshufd	$0, 12(%[key]), %%xmm3\n\t"
-       "vpshufd	$0, 16(%[key]), %%xmm4\n\t"
-       "vpshufd	$0, 20(%[key]), %%xmm5\n\t"
-       "vpshufd	$0, 24(%[key]), %%xmm6\n\t"
-       "vpshufd	$0, 28(%[key]), %%xmm7\n\t"
-       "vpshufd	$0, 32(%[key]), %%xmm8\n\t"
-       "vpshufd	$0, 36(%[key]), %%xmm9\n\t"
-       "vpshufd	$0, 40(%[key]), %%xmm10\n\t"
-       "vpshufd	$0, 44(%[key]), %%xmm11\n\t"
-       "vpshufd	$0, 48(%[key]), %%xmm12\n\t"
-       "vpshufd	$0, 52(%[key]), %%xmm13\n\t"
-       "vpshufd	$0, 56(%[key]), %%xmm14\n\t"
-       "vpshufd	$0, 60(%[key]), %%xmm15\n\t"
-
-       "vpaddd	%[add], %%xmm12, %%xmm12\n\t"
-
-       "vmovdqa	%%xmm0,     (%[X])\n\t"
-       "vmovdqa	%%xmm1,   16(%[X])\n\t"
-       "vmovdqa	%%xmm2,   32(%[X])\n\t"
-       "vmovdqa	%%xmm3,   48(%[X])\n\t"
-       "vmovdqa	%%xmm4,   64(%[X])\n\t"
-       "vmovdqa	%%xmm5,   80(%[X])\n\t"
-       "vmovdqa	%%xmm6,   96(%[X])\n\t"
-       "vmovdqa	%%xmm7,  112(%[X])\n\t"
-       "vmovdqa	%%xmm8,  128(%[X])\n\t"
-       "vmovdqa	%%xmm9,  144(%[X])\n\t"
-       "vmovdqa	%%xmm10, 160(%[X])\n\t"
-       "vmovdqa	%%xmm11, 176(%[X])\n\t"
-       "vmovdqa	%%xmm12, 192(%[X])\n\t"
-       "vmovdqa	%%xmm13, 208(%[X])\n\t"
-       "vmovdqa	%%xmm14, 224(%[X])\n\t"
-       "vmovdqa	%%xmm15, 240(%[X])\n\t"
-       "\n"
-   "L_enc128_loop:\n\t"
-       "vmovdqa	%%xmm11, 48(%[x])\n\t"
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       QUARTERROUND_XMM()
-       QUARTERROUND_XMM_2()
-       "vmovdqa	48(%[x]), %%xmm11\n\t"
-
-       "vpaddd	   (%[X]), %%xmm0,  %%xmm0\n\t"
-       "vpaddd	 16(%[X]), %%xmm1,  %%xmm1\n\t"
-       "vpaddd	 32(%[X]), %%xmm2,  %%xmm2\n\t"
-       "vpaddd	 48(%[X]), %%xmm3,  %%xmm3\n\t"
-       "vpaddd	 64(%[X]), %%xmm4,  %%xmm4\n\t"
-       "vpaddd	 80(%[X]), %%xmm5,  %%xmm5\n\t"
-       "vpaddd	 96(%[X]), %%xmm6,  %%xmm6\n\t"
-       "vpaddd	112(%[X]), %%xmm7,  %%xmm7\n\t"
-       "vpaddd	128(%[X]), %%xmm8,  %%xmm8\n\t"
-       "vpaddd	144(%[X]), %%xmm9,  %%xmm9\n\t"
-       "vpaddd	160(%[X]), %%xmm10, %%xmm10\n\t"
-       "vpaddd	176(%[X]), %%xmm11, %%xmm11\n\t"
-       "vpaddd	192(%[X]), %%xmm12, %%xmm12\n\t"
-       "vpaddd	208(%[X]), %%xmm13, %%xmm13\n\t"
-       "vpaddd	224(%[X]), %%xmm14, %%xmm14\n\t"
-       "vpaddd	240(%[X]), %%xmm15, %%xmm15\n\t"
-
-       "vmovdqa	%%xmm8,     (%[x])\n\t"
-       "vmovdqa	%%xmm9,   16(%[x])\n\t"
-       "vmovdqa	%%xmm10,  32(%[x])\n\t"
-       "vmovdqa	%%xmm11,  48(%[x])\n\t"
-       "vmovdqa	%%xmm12,  64(%[x])\n\t"
-       "vmovdqa	%%xmm13,  80(%[x])\n\t"
-       "vmovdqa	%%xmm14,  96(%[x])\n\t"
-       "vmovdqa	%%xmm15, 112(%[x])\n\t"
-
-       "vpunpckldq %%xmm1, %%xmm0, %%xmm8\n\t"
-       "vpunpckldq %%xmm3, %%xmm2, %%xmm9\n\t"
-       "vpunpckhdq %%xmm1, %%xmm0, %%xmm12\n\t"
-       "vpunpckhdq %%xmm3, %%xmm2, %%xmm13\n\t"
-       "vpunpckldq %%xmm5, %%xmm4, %%xmm10\n\t"
-       "vpunpckldq %%xmm7, %%xmm6, %%xmm11\n\t"
-       "vpunpckhdq %%xmm5, %%xmm4, %%xmm14\n\t"
-       "vpunpckhdq %%xmm7, %%xmm6, %%xmm15\n\t"
-       "vpunpcklqdq %%xmm9,  %%xmm8,  %%xmm0\n\t"
-       "vpunpcklqdq %%xmm11, %%xmm10, %%xmm1\n\t"
-       "vpunpckhqdq %%xmm9,  %%xmm8,  %%xmm2\n\t"
-       "vpunpckhqdq %%xmm11, %%xmm10, %%xmm3\n\t"
-       "vpunpcklqdq %%xmm13, %%xmm12, %%xmm4\n\t"
-       "vpunpcklqdq %%xmm15, %%xmm14, %%xmm5\n\t"
-       "vpunpckhqdq %%xmm13, %%xmm12, %%xmm6\n\t"
-       "vpunpckhqdq %%xmm15, %%xmm14, %%xmm7\n\t"
-       "vmovdqu	   (%[in]), %%xmm8\n\t"
-       "vmovdqu	 16(%[in]), %%xmm9\n\t"
-       "vmovdqu	 64(%[in]), %%xmm10\n\t"
-       "vmovdqu	 80(%[in]), %%xmm11\n\t"
-       "vmovdqu	128(%[in]), %%xmm12\n\t"
-       "vmovdqu	144(%[in]), %%xmm13\n\t"
-       "vmovdqu	192(%[in]), %%xmm14\n\t"
-       "vmovdqu	208(%[in]), %%xmm15\n\t"
-       "vpxor	%%xmm8,  %%xmm0, %%xmm0\n\t"
-       "vpxor	%%xmm9,  %%xmm1, %%xmm1\n\t"
-       "vpxor	%%xmm10, %%xmm2, %%xmm2\n\t"
-       "vpxor	%%xmm11, %%xmm3, %%xmm3\n\t"
-       "vpxor	%%xmm12, %%xmm4, %%xmm4\n\t"
-       "vpxor	%%xmm13, %%xmm5, %%xmm5\n\t"
-       "vpxor	%%xmm14, %%xmm6, %%xmm6\n\t"
-       "vpxor	%%xmm15, %%xmm7, %%xmm7\n\t"
-       "vmovdqu	%%xmm0,    (%[out])\n\t"
-       "vmovdqu	%%xmm1,  16(%[out])\n\t"
-       "vmovdqu	%%xmm2,  64(%[out])\n\t"
-       "vmovdqu	%%xmm3,  80(%[out])\n\t"
-       "vmovdqu	%%xmm4, 128(%[out])\n\t"
-       "vmovdqu	%%xmm5, 144(%[out])\n\t"
-       "vmovdqu	%%xmm6, 192(%[out])\n\t"
-       "vmovdqu	%%xmm7, 208(%[out])\n\t"
-
-       "vmovdqa	   (%[x]), %%xmm0\n\t"
-       "vmovdqa	 16(%[x]), %%xmm1\n\t"
-       "vmovdqa	 32(%[x]), %%xmm2\n\t"
-       "vmovdqa	 48(%[x]), %%xmm3\n\t"
-       "vmovdqa	 64(%[x]), %%xmm4\n\t"
-       "vmovdqa	 80(%[x]), %%xmm5\n\t"
-       "vmovdqa	 96(%[x]), %%xmm6\n\t"
-       "vmovdqa	112(%[x]), %%xmm7\n\t"
-
-       "vpunpckldq %%xmm1, %%xmm0, %%xmm8\n\t"
-       "vpunpckldq %%xmm3, %%xmm2, %%xmm9\n\t"
-       "vpunpckhdq %%xmm1, %%xmm0, %%xmm12\n\t"
-       "vpunpckhdq %%xmm3, %%xmm2, %%xmm13\n\t"
-       "vpunpckldq %%xmm5, %%xmm4, %%xmm10\n\t"
-       "vpunpckldq %%xmm7, %%xmm6, %%xmm11\n\t"
-       "vpunpckhdq %%xmm5, %%xmm4, %%xmm14\n\t"
-       "vpunpckhdq %%xmm7, %%xmm6, %%xmm15\n\t"
-       "vpunpcklqdq %%xmm9,  %%xmm8,  %%xmm0\n\t"
-       "vpunpcklqdq %%xmm11, %%xmm10, %%xmm1\n\t"
-       "vpunpckhqdq %%xmm9,  %%xmm8,  %%xmm2\n\t"
-       "vpunpckhqdq %%xmm11, %%xmm10, %%xmm3\n\t"
-       "vpunpcklqdq %%xmm13, %%xmm12, %%xmm4\n\t"
-       "vpunpcklqdq %%xmm15, %%xmm14, %%xmm5\n\t"
-       "vpunpckhqdq %%xmm13, %%xmm12, %%xmm6\n\t"
-       "vpunpckhqdq %%xmm15, %%xmm14, %%xmm7\n\t"
-       "vmovdqu	 32(%[in]), %%xmm8\n\t"
-       "vmovdqu	 48(%[in]), %%xmm9\n\t"
-       "vmovdqu	 96(%[in]), %%xmm10\n\t"
-       "vmovdqu	112(%[in]), %%xmm11\n\t"
-       "vmovdqu	160(%[in]), %%xmm12\n\t"
-       "vmovdqu	176(%[in]), %%xmm13\n\t"
-       "vmovdqu	224(%[in]), %%xmm14\n\t"
-       "vmovdqu	240(%[in]), %%xmm15\n\t"
-       "vpxor	%%xmm8,  %%xmm0, %%xmm0\n\t"
-       "vpxor	%%xmm9,  %%xmm1, %%xmm1\n\t"
-       "vpxor	%%xmm10, %%xmm2, %%xmm2\n\t"
-       "vpxor	%%xmm11, %%xmm3, %%xmm3\n\t"
-       "vpxor	%%xmm12, %%xmm4, %%xmm4\n\t"
-       "vpxor	%%xmm13, %%xmm5, %%xmm5\n\t"
-       "vpxor	%%xmm14, %%xmm6, %%xmm6\n\t"
-       "vpxor	%%xmm15, %%xmm7, %%xmm7\n\t"
-       "vmovdqu	%%xmm0,  32(%[out])\n\t"
-       "vmovdqu	%%xmm1,  48(%[out])\n\t"
-       "vmovdqu	%%xmm2,  96(%[out])\n\t"
-       "vmovdqu	%%xmm3, 112(%[out])\n\t"
-       "vmovdqu	%%xmm4, 160(%[out])\n\t"
-       "vmovdqu	%%xmm5, 176(%[out])\n\t"
-       "vmovdqu	%%xmm6, 224(%[out])\n\t"
-       "vmovdqu	%%xmm7, 240(%[out])\n\t"
-
-       "vmovdqa	192(%[X]), %%xmm12\n\t"
-       "add	$256, %[in]\n\t"
-       "add	$256, %[out]\n\t"
-       "vpaddd	%[four], %%xmm12, %%xmm12\n\t"
-       "sub	$256, %[bytes]\n\t"
-       "vmovdqa	%%xmm12, 192(%[X])\n\t"
-       "cmp	$256, %[bytes]\n\t"
-       "jl	L_done\n\t"
-
-       "vmovdqa	   (%[X]), %%xmm0\n\t"
-       "vmovdqa	 16(%[X]), %%xmm1\n\t"
-       "vmovdqa	 32(%[X]), %%xmm2\n\t"
-       "vmovdqa	 48(%[X]), %%xmm3\n\t"
-       "vmovdqa	 64(%[X]), %%xmm4\n\t"
-       "vmovdqa	 80(%[X]), %%xmm5\n\t"
-       "vmovdqa	 96(%[X]), %%xmm6\n\t"
-       "vmovdqa	112(%[X]), %%xmm7\n\t"
-       "vmovdqa	128(%[X]), %%xmm8\n\t"
-       "vmovdqa	144(%[X]), %%xmm9\n\t"
-       "vmovdqa	160(%[X]), %%xmm10\n\t"
-       "vmovdqa	176(%[X]), %%xmm11\n\t"
-       "vmovdqa	192(%[X]), %%xmm12\n\t"
-       "vmovdqa	208(%[X]), %%xmm13\n\t"
-       "vmovdqa	224(%[X]), %%xmm14\n\t"
-       "vmovdqa	240(%[X]), %%xmm15\n\t"
-       "jmp	L_enc128_loop\n\t"
-
-       "\n"
-   "L_done:\n\t"
-
-       "shl	$2, %[cnt]\n\t"
-       "add	48(%[key]), %[cnt]\n\t"
-       "movl	%[cnt], 48(%[key])\n\t"
-       "\n"
-   "L_end128:\n\t"
-       : [bytes] "+r" (bytes), [cnt] "+r" (cnt),
-         [in] "+r" (m), [out] "+r" (c)
-       : [X] "r" (X), [x] "r" (x), [key] "r" (ctx->X),
-         [add] "xrm" (add), [four] "xrm" (four),
-         [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16)
-       : "xmm0", "xmm1", "xmm2", "xmm3",
-         "xmm4", "xmm5", "xmm6", "xmm7",
-         "xmm8", "xmm9", "xmm10", "xmm11",
-         "xmm12", "xmm13", "xmm14", "xmm15", "memory"
-    );
-
-    for (; bytes >= CHACHA_CHUNK_BYTES;) {
-        CHACHA_CHUNK_AVX();
-        bytes -= CHACHA_CHUNK_BYTES;
-        c += CHACHA_CHUNK_BYTES;
-        m += CHACHA_CHUNK_BYTES;
-    }
-    if (bytes > 0) {
-        CHACHA_PARTIAL_CHUNK_AVX();
-    }
-}
-#endif /* HAVE_INTEL_AVX1 */
-
-#ifdef HAVE_INTEL_AVX2
-#define QUARTERROUND_2_AVX2()                          \
-        "vpaddd		%%xmm1, %%xmm0, %%xmm0\n\t"    \
-        "vpxor		%%xmm0, %%xmm3, %%xmm3\n\t"    \
-        "vpshufb	%[rotl16], %%xmm3, %%xmm3\n\t" \
-        "vpaddd		%%xmm3, %%xmm2, %%xmm2\n\t"    \
-        "vpxor		%%xmm2, %%xmm1, %%xmm1\n\t"    \
-        "vpsrld		$20, %%xmm1, %%xmm4\n\t"       \
-        "vpslld		$12, %%xmm1, %%xmm1\n\t"       \
-        "vpxor		%%xmm4, %%xmm1, %%xmm1\n\t"    \
-        "vpaddd		%%xmm1, %%xmm0, %%xmm0\n\t"    \
-        "vpxor		%%xmm0, %%xmm3, %%xmm3\n\t"    \
-        "vpshufb	%[rotl8], %%xmm3, %%xmm3\n\t"  \
-        "vpaddd		%%xmm3, %%xmm2, %%xmm2\n\t"    \
-        "vpxor		%%xmm2, %%xmm1, %%xmm1\n\t"    \
-        "vpsrld		$25, %%xmm1, %%xmm4\n\t"       \
-        "vpslld		$7, %%xmm1, %%xmm1\n\t"        \
-        "vpxor		%%xmm4, %%xmm1, %%xmm1\n\t"    \
-        "# Swap words for next round\n\t"              \
-        "vpshufd	$0x39, %%xmm1, %%xmm1\n\t"     \
-        "vpshufd	$0x4e, %%xmm2, %%xmm2\n\t"     \
-        "vpshufd	$0x93, %%xmm3, %%xmm3\n\t"     \
-        "vpaddd		%%xmm1, %%xmm0, %%xmm0\n\t"    \
-        "vpxor		%%xmm0, %%xmm3, %%xmm3\n\t"    \
-        "vpshufb	%[rotl16], %%xmm3, %%xmm3\n\t" \
-        "vpaddd		%%xmm3, %%xmm2, %%xmm2\n\t"    \
-        "vpxor		%%xmm2, %%xmm1, %%xmm1\n\t"    \
-        "vpsrld		$20, %%xmm1, %%xmm4\n\t"       \
-        "vpslld		$12, %%xmm1, %%xmm1\n\t"       \
-        "vpxor		%%xmm4, %%xmm1, %%xmm1\n\t"    \
-        "vpaddd		%%xmm1, %%xmm0, %%xmm0\n\t"    \
-        "vpxor		%%xmm0, %%xmm3, %%xmm3\n\t"    \
-        "vpshufb	%[rotl8], %%xmm3, %%xmm3\n\t"  \
-        "vpaddd		%%xmm3, %%xmm2, %%xmm2\n\t"    \
-        "vpxor		%%xmm2, %%xmm1, %%xmm1\n\t"    \
-        "vpsrld		$25, %%Xmm1, %%xmm4\n\t"       \
-        "vpslld		$7, %%xmm1, %%xmm1\n\t"        \
-        "vpxor		%%xmm4, %%xmm1, %%xmm1\n\t"    \
-        "# Swap words back\n\t"                        \
-        "vpshufd	$0x93, %%xmm1, %%xmm1\n\t"     \
-        "vpshufd	$0x4e, %%xmm2, %%xmm2\n\t"     \
-        "vpshufd	$0x39, %%xmm3, %%xmm3\n\t"     \
-
-#define CHACHA_CRYPT_AVX2()                                                    \
-        "vmovdqu	 0(%[input]), %%xmm8\n\t"                              \
-        "vmovdqu	16(%[input]), %%xmm9\n\t"                              \
-        "vmovdqu	32(%[input]), %%xmm10\n\t"                             \
-        "vmovdqu	48(%[input]), %%xmm11\n\t"                             \
-        "vmovdqu	%%xmm8, %%xmm0\n\t"                                    \
-        "vmovdqu	%%xmm9, %%xmm1\n\t"                                    \
-        "vmovdqu	%%xmm10, %%xmm2\n\t"                                   \
-        "vmovdqu	%%xmm11, %%xmm3\n\t"                                   \
-        "movb		$10, %%al\n\t"                                         \
-        "\n"                                                                   \
-        "1:\n\t"                                                               \
-        QUARTERROUND_2_AVX2()                                                  \
-        "decb		%%al\n\t"                                              \
-        "jnz		1b\n\t"                                                \
-        "vpaddd		%%xmm8, %%xmm0, %%xmm0\n\t"                            \
-        "vpaddd		%%xmm9, %%xmm1, %%xmm1\n\t"                            \
-        "vpaddd		%%xmm10, %%xmm2, %%xmm2\n\t"                           \
-        "vpaddd		%%xmm11, %%xmm3, %%xmm3\n\t"                           \
-
-#define CHACHA_PARTIAL_CHUNK_AVX2()                                            \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_AVX2()                                                    \
-        "vmovdqu	%%xmm0,  0(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm1, 16(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm2, 32(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm3, 48(%[c])\n\t"                                  \
-        "addl		$1, 48(%[input])\n\t"                                  \
-        "movl		%[bytes], %%r8d\n\t"                                   \
-        "xorq		%%rdx, %%rdx\n\t"                                      \
-        "movl		%%r8d, %%r9d\n\t"                                      \
-        "andl		$7, %%r9d\n\t"                                         \
-        "jz		4f\n\t"                                                \
-        "\n"                                                                   \
-        "2:\n\t"                                                               \
-        "movzbl		(%[c],%%rdx,1), %%ecx\n\t"                             \
-        "xorb		(%[m],%%rdx,1), %%cl\n\t"                              \
-        "movb		%%cl, (%[output],%%rdx,1)\n\t"                         \
-        "incl		%%edx\n\t"                                             \
-        "cmpl		%%r9d, %%edx\n\t"                                      \
-        "jne		2b\n\t"                                                \
-        "je		3f\n\t"                                                \
-        "\n"                                                                   \
-        "4:\n\t"                                                               \
-        "movq		(%[c],%%rdx,1), %%rcx\n\t"                             \
-        "xorq		(%[m],%%rdx,1), %%rcx\n\t"                             \
-        "movq		%%rcx, (%[output],%%rdx,1)\n\t"                        \
-        "addl		$8, %%edx\n\t"                                         \
-        "\n"                                                                   \
-        "3:\n\t"                                                               \
-        "cmpl		%%r8d, %%edx\n\t"                                      \
-        "jne		4b\n\t"                                                \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (x),                                   \
-          [output] "r" (c), [bytes] "r" (bytes), [m] "r" (m),                  \
-          [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16)                       \
-        : "eax", "ecx", "edx", "r8", "r9", "memory",                           \
-          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",      \
-          "xmm8", "xmm9", "xmm10", "xmm11"                                     \
-    )
-
-
-#define CHACHA_CHUNK_AVX2()                                                    \
-    __asm__ __volatile__ (                                                     \
-        CHACHA_CRYPT_AVX2()                                                    \
-        "vmovdqu	 0(%[m]), %%xmm4\n\t"                                  \
-        "vmovdqu	16(%[m]), %%xmm5\n\t"                                  \
-        "vmovdqu	32(%[m]), %%xmm6\n\t"                                  \
-        "vmovdqu	48(%[m]), %%xmm7\n\t"                                  \
-        "vpxor		%%xmm4, %%xmm0, %%xmm0\n\t"                            \
-        "vpxor		%%xmm5, %%xmm1, %%xmm1\n\t"                            \
-        "vpxor		%%xmm6, %%xmm2, %%xmm2\n\t"                            \
-        "vpxor		%%xmm7, %%xmm3, %%xmm3\n\t"                            \
-        "vmovdqu	%%xmm0,  0(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm1, 16(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm2, 32(%[c])\n\t"                                  \
-        "vmovdqu	%%xmm3, 48(%[c])\n\t"                                  \
-        "addl		$1, 48(%[input])\n\t"                                  \
-        :                                                                      \
-        : [input] "r" (ctx->X), [c] "r" (c), [m] "r" (m),                      \
-          [rotl8] "xrm" (rotl8), [rotl16] "xrm" (rotl16)                       \
-        : "rax", "memory",                                                     \
-          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",      \
-          "xmm8", "xmm9", "xmm10", "xmm11"                                     \
-    )
-
-
-static void chacha_encrypt_avx2(ChaCha* ctx, const byte* m, byte* c,
-                                 word32 bytes)
-{
-    ALIGN256 word32 X[8*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
-    ALIGN256 word32 x[4*CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
-    word32 cnt = 0;
-    static const __m256i add    = { 0x0000000100000000UL,0x0000000300000002UL,
-                                    0x0000000500000004UL,0x0000000700000006UL };
-    static const __m256i eight  = { 0x0000000800000008UL,0x0000000800000008UL,
-                                    0x0000000800000008UL,0x0000000800000008UL };
-    static const __m256i rotl8_256  =
-                                  { 0x0605040702010003UL,0x0e0d0c0f0a09080bUL,
-                                    0x0605040702010003UL,0x0e0d0c0f0a09080bUL };
-    static const __m256i rotl16_256 =
-                                  { 0x0504070601000302UL,0x0d0c0f0e09080b0aUL,
-                                    0x0504070601000302UL,0x0d0c0f0e09080b0aUL };
-
-    if (bytes == 0)
-        return;
-
-    __asm__ __volatile__ (
-       "movl	%[bytes], %[cnt]\n\t"
-       "shrl	$9, %[cnt]\n\t"
-       "jz      L_end256\n\t"
-
-       "vpbroadcastd	  (%[key]), %%ymm0\n\t"
-       "vpbroadcastd	 4(%[key]), %%ymm1\n\t"
-       "vpbroadcastd	 8(%[key]), %%ymm2\n\t"
-       "vpbroadcastd	12(%[key]), %%ymm3\n\t"
-       "vpbroadcastd	16(%[key]), %%ymm4\n\t"
-       "vpbroadcastd	20(%[key]), %%ymm5\n\t"
-       "vpbroadcastd	24(%[key]), %%ymm6\n\t"
-       "vpbroadcastd	28(%[key]), %%ymm7\n\t"
-       "vpbroadcastd	32(%[key]), %%ymm8\n\t"
-       "vpbroadcastd	36(%[key]), %%ymm9\n\t"
-       "vpbroadcastd	40(%[key]), %%ymm10\n\t"
-       "vpbroadcastd	44(%[key]), %%ymm11\n\t"
-       "vpbroadcastd	48(%[key]), %%ymm12\n\t"
-       "vpbroadcastd	52(%[key]), %%ymm13\n\t"
-       "vpbroadcastd	56(%[key]), %%ymm14\n\t"
-       "vpbroadcastd	60(%[key]), %%ymm15\n\t"
-
-       "vpaddd	%[add], %%ymm12, %%ymm12\n\t"
-
-       "vmovdqa	%%ymm0,     (%[X])\n\t"
-       "vmovdqa	%%ymm1,   32(%[X])\n\t"
-       "vmovdqa	%%ymm2,   64(%[X])\n\t"
-       "vmovdqa	%%ymm3,   96(%[X])\n\t"
-       "vmovdqa	%%ymm4,  128(%[X])\n\t"
-       "vmovdqa	%%ymm5,  160(%[X])\n\t"
-       "vmovdqa	%%ymm6,  192(%[X])\n\t"
-       "vmovdqa	%%ymm7,  224(%[X])\n\t"
-       "vmovdqa	%%ymm8,  256(%[X])\n\t"
-       "vmovdqa	%%ymm9,  288(%[X])\n\t"
-       "vmovdqa	%%ymm10, 320(%[X])\n\t"
-       "vmovdqa	%%ymm11, 352(%[X])\n\t"
-       "vmovdqa	%%ymm12, 384(%[X])\n\t"
-       "vmovdqa	%%ymm13, 416(%[X])\n\t"
-       "vmovdqa	%%ymm14, 448(%[X])\n\t"
-       "vmovdqa	%%ymm15, 480(%[X])\n\t"
-       "\n"
-   "L_enc256_loop:\n\t"
-       "vmovdqa	%%ymm11, 96(%[x])\n\t"
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       QUARTERROUND_YMM()
-       QUARTERROUND_YMM_2()
-       "vmovdqa	96(%[x]), %%ymm11\n\t"
-
-       "vpaddd	   (%[X]), %%ymm0,  %%ymm0\n\t"
-       "vpaddd	 32(%[X]), %%ymm1,  %%ymm1\n\t"
-       "vpaddd	 64(%[X]), %%ymm2,  %%ymm2\n\t"
-       "vpaddd	 96(%[X]), %%ymm3,  %%ymm3\n\t"
-       "vpaddd	128(%[X]), %%ymm4,  %%ymm4\n\t"
-       "vpaddd	160(%[X]), %%ymm5,  %%ymm5\n\t"
-       "vpaddd	192(%[X]), %%ymm6,  %%ymm6\n\t"
-       "vpaddd	224(%[X]), %%ymm7,  %%ymm7\n\t"
-       "vpaddd	256(%[X]), %%ymm8,  %%ymm8\n\t"
-       "vpaddd	288(%[X]), %%ymm9,  %%ymm9\n\t"
-       "vpaddd	320(%[X]), %%ymm10, %%ymm10\n\t"
-       "vpaddd	352(%[X]), %%ymm11, %%ymm11\n\t"
-       "vpaddd	384(%[X]), %%ymm12, %%ymm12\n\t"
-       "vpaddd	416(%[X]), %%ymm13, %%ymm13\n\t"
-       "vpaddd	448(%[X]), %%ymm14, %%ymm14\n\t"
-       "vpaddd	480(%[X]), %%ymm15, %%ymm15\n\t"
-
-       "vmovdqa	%%ymm8,     (%[x])\n\t"
-       "vmovdqa	%%ymm9,   32(%[x])\n\t"
-       "vmovdqa	%%ymm10,  64(%[x])\n\t"
-       "vmovdqa	%%ymm11,  96(%[x])\n\t"
-       "vmovdqa	%%ymm12, 128(%[x])\n\t"
-       "vmovdqa	%%ymm13, 160(%[x])\n\t"
-       "vmovdqa	%%ymm14, 192(%[x])\n\t"
-       "vmovdqa	%%ymm15, 224(%[x])\n\t"
-
-       "vpunpckldq	%%ymm1, %%ymm0, %%ymm8\n\t"
-       "vpunpckldq	%%ymm3, %%ymm2, %%ymm9\n\t"
-       "vpunpckhdq	%%ymm1, %%ymm0, %%ymm12\n\t"
-       "vpunpckhdq	%%ymm3, %%ymm2, %%ymm13\n\t"
-       "vpunpckldq	%%ymm5, %%ymm4, %%ymm10\n\t"
-       "vpunpckldq	%%ymm7, %%ymm6, %%ymm11\n\t"
-       "vpunpckhdq	%%ymm5, %%ymm4, %%ymm14\n\t"
-       "vpunpckhdq	%%ymm7, %%ymm6, %%ymm15\n\t"
-       "vpunpcklqdq	%%ymm9,  %%ymm8,  %%ymm0\n\t"
-       "vpunpcklqdq	%%ymm11, %%ymm10, %%ymm1\n\t"
-       "vpunpckhqdq	%%ymm9,  %%ymm8,  %%ymm2\n\t"
-       "vpunpckhqdq	%%ymm11, %%ymm10, %%ymm3\n\t"
-       "vpunpcklqdq	%%ymm13, %%ymm12, %%ymm4\n\t"
-       "vpunpcklqdq	%%ymm15, %%ymm14, %%ymm5\n\t"
-       "vpunpckhqdq	%%ymm13, %%ymm12, %%ymm6\n\t"
-       "vpunpckhqdq	%%ymm15, %%ymm14, %%ymm7\n\t"
-       "vperm2i128	$0x20, %%ymm1, %%ymm0, %%ymm8\n\t"
-       "vperm2i128	$0x20, %%ymm3, %%ymm2, %%ymm9\n\t"
-       "vperm2i128	$0x31, %%ymm1, %%ymm0, %%ymm12\n\t"
-       "vperm2i128	$0x31, %%ymm3, %%ymm2, %%ymm13\n\t"
-       "vperm2i128	$0x20, %%ymm5, %%ymm4, %%ymm10\n\t"
-       "vperm2i128	$0x20, %%ymm7, %%ymm6, %%ymm11\n\t"
-       "vperm2i128	$0x31, %%ymm5, %%ymm4, %%ymm14\n\t"
-       "vperm2i128	$0x31, %%ymm7, %%ymm6, %%ymm15\n\t"
-
-       "vmovdqu	   (%[in]), %%ymm0\n\t"
-       "vmovdqu	 64(%[in]), %%ymm1\n\t"
-       "vmovdqu	128(%[in]), %%ymm2\n\t"
-       "vmovdqu	192(%[in]), %%ymm3\n\t"
-       "vmovdqu	256(%[in]), %%ymm4\n\t"
-       "vmovdqu	320(%[in]), %%ymm5\n\t"
-       "vmovdqu	384(%[in]), %%ymm6\n\t"
-       "vmovdqu	448(%[in]), %%ymm7\n\t"
-       "vpxor	%%ymm0, %%ymm8,  %%ymm8\n\t"
-       "vpxor	%%ymm1, %%ymm9,  %%ymm9\n\t"
-       "vpxor	%%ymm2, %%ymm10, %%ymm10\n\t"
-       "vpxor	%%ymm3, %%ymm11, %%ymm11\n\t"
-       "vpxor	%%ymm4, %%ymm12, %%ymm12\n\t"
-       "vpxor	%%ymm5, %%ymm13, %%ymm13\n\t"
-       "vpxor	%%ymm6, %%ymm14, %%ymm14\n\t"
-       "vpxor	%%ymm7, %%ymm15, %%ymm15\n\t"
-       "vmovdqu	%%ymm8,     (%[out])\n\t"
-       "vmovdqu	%%ymm9,   64(%[out])\n\t"
-       "vmovdqu	%%ymm10, 128(%[out])\n\t"
-       "vmovdqu	%%ymm11, 192(%[out])\n\t"
-       "vmovdqu	%%ymm12, 256(%[out])\n\t"
-       "vmovdqu	%%ymm13, 320(%[out])\n\t"
-       "vmovdqu	%%ymm14, 384(%[out])\n\t"
-       "vmovdqu	%%ymm15, 448(%[out])\n\t"
-
-       "vmovdqa	   (%[x]), %%ymm0\n\t"
-       "vmovdqa	 32(%[x]), %%ymm1\n\t"
-       "vmovdqa	 64(%[x]), %%ymm2\n\t"
-       "vmovdqa	 96(%[x]), %%ymm3\n\t"
-       "vmovdqa	128(%[x]), %%ymm4\n\t"
-       "vmovdqa	160(%[x]), %%ymm5\n\t"
-       "vmovdqa	192(%[x]), %%ymm6\n\t"
-       "vmovdqa	224(%[x]), %%ymm7\n\t"
-
-       "vpunpckldq	%%ymm1, %%ymm0, %%ymm8\n\t"
-       "vpunpckldq	%%ymm3, %%ymm2, %%ymm9\n\t"
-       "vpunpckhdq	%%ymm1, %%ymm0, %%ymm12\n\t"
-       "vpunpckhdq	%%ymm3, %%ymm2, %%ymm13\n\t"
-       "vpunpckldq	%%ymm5, %%ymm4, %%ymm10\n\t"
-       "vpunpckldq	%%ymm7, %%ymm6, %%ymm11\n\t"
-       "vpunpckhdq	%%ymm5, %%ymm4, %%ymm14\n\t"
-       "vpunpckhdq	%%ymm7, %%ymm6, %%ymm15\n\t"
-       "vpunpcklqdq	%%ymm9,  %%ymm8,  %%ymm0\n\t"
-       "vpunpcklqdq	%%ymm11, %%ymm10, %%ymm1\n\t"
-       "vpunpckhqdq	%%ymm9 , %%ymm8,  %%ymm2\n\t"
-       "vpunpckhqdq	%%ymm11, %%ymm10, %%ymm3\n\t"
-       "vpunpcklqdq	%%ymm13, %%ymm12, %%ymm4\n\t"
-       "vpunpcklqdq	%%ymm15, %%ymm14, %%ymm5\n\t"
-       "vpunpckhqdq	%%ymm13, %%ymm12, %%ymm6\n\t"
-       "vpunpckhqdq	%%ymm15, %%ymm14, %%ymm7\n\t"
-       "vperm2i128	$0x20, %%ymm1, %%ymm0, %%ymm8\n\t"
-       "vperm2i128	$0x20, %%ymm3, %%ymm2, %%ymm9\n\t"
-       "vperm2i128	$0x31, %%ymm1, %%ymm0, %%ymm12\n\t"
-       "vperm2i128	$0x31, %%ymm3, %%ymm2, %%ymm13\n\t"
-       "vperm2i128	$0x20, %%ymm5, %%ymm4, %%ymm10\n\t"
-       "vperm2i128	$0x20, %%ymm7, %%ymm6, %%ymm11\n\t"
-       "vperm2i128	$0x31, %%ymm5, %%ymm4, %%ymm14\n\t"
-       "vperm2i128	$0x31, %%ymm7, %%ymm6, %%ymm15\n\t"
-
-       "vmovdqu	 32(%[in]), %%ymm0\n\t"
-       "vmovdqu	 96(%[in]), %%ymm1\n\t"
-       "vmovdqu	160(%[in]), %%ymm2\n\t"
-       "vmovdqu	224(%[in]), %%ymm3\n\t"
-       "vmovdqu	288(%[in]), %%ymm4\n\t"
-       "vmovdqu	352(%[in]), %%ymm5\n\t"
-       "vmovdqu	416(%[in]), %%ymm6\n\t"
-       "vmovdqu	480(%[in]), %%ymm7\n\t"
-       "vpxor	%%ymm0, %%ymm8,  %%ymm8\n\t"
-       "vpxor	%%ymm1, %%ymm9,  %%ymm9\n\t"
-       "vpxor	%%ymm2, %%ymm10, %%ymm10\n\t"
-       "vpxor	%%ymm3, %%ymm11, %%ymm11\n\t"
-       "vpxor	%%ymm4, %%ymm12, %%ymm12\n\t"
-       "vpxor	%%ymm5, %%ymm13, %%ymm13\n\t"
-       "vpxor	%%ymm6, %%ymm14, %%ymm14\n\t"
-       "vpxor	%%ymm7, %%ymm15, %%ymm15\n\t"
-       "vmovdqu	%%ymm8,   32(%[out])\n\t"
-       "vmovdqu	%%ymm9,   96(%[out])\n\t"
-       "vmovdqu	%%ymm10, 160(%[out])\n\t"
-       "vmovdqu	%%ymm11, 224(%[out])\n\t"
-       "vmovdqu	%%ymm12, 288(%[out])\n\t"
-       "vmovdqu	%%ymm13, 352(%[out])\n\t"
-       "vmovdqu	%%ymm14, 416(%[out])\n\t"
-       "vmovdqu	%%ymm15, 480(%[out])\n\t"
-
-       "vmovdqa	384(%[X]), %%ymm12\n\t"
-       "add	$512, %[in]\n\t"
-       "add	$512, %[out]\n\t"
-       "vpaddd	%[eight], %%ymm12, %%ymm12\n\t"
-       "sub	$512, %[bytes]\n\t"
-       "vmovdqa	%%ymm12, 384(%[X])\n\t"
-       "cmp	$512, %[bytes]\n\t"
-       "jl	L_done256\n\t"
-
-       "vmovdqa	   (%[X]), %%ymm0\n\t"
-       "vmovdqa	 32(%[X]), %%ymm1\n\t"
-       "vmovdqa	 64(%[X]), %%ymm2\n\t"
-       "vmovdqa	 96(%[X]), %%ymm3\n\t"
-       "vmovdqa	128(%[X]), %%ymm4\n\t"
-       "vmovdqa	160(%[X]), %%ymm5\n\t"
-       "vmovdqa	192(%[X]), %%ymm6\n\t"
-       "vmovdqa	224(%[X]), %%ymm7\n\t"
-       "vmovdqa	256(%[X]), %%ymm8\n\t"
-       "vmovdqa	288(%[X]), %%ymm9\n\t"
-       "vmovdqa	320(%[X]), %%ymm10\n\t"
-       "vmovdqa	352(%[X]), %%ymm11\n\t"
-       "vmovdqa	384(%[X]), %%ymm12\n\t"
-       "vmovdqa	416(%[X]), %%ymm13\n\t"
-       "vmovdqa	448(%[X]), %%ymm14\n\t"
-       "vmovdqa	480(%[X]), %%ymm15\n\t"
-       "jmp	L_enc256_loop\n\t"
-       "\n"
-   "L_done256:\n\t"
-       "shl	$3, %[cnt]\n\t"
-       "add	48(%[key]), %[cnt]\n\t"
-       "movl	%[cnt], 48(%[key])\n\t"
-       "\n"
-   "L_end256:\n\t"
-       : [bytes] "+r" (bytes), [cnt] "+r" (cnt),
-         [in] "+r" (m), [out] "+r" (c)
-       : [X] "r" (X), [x] "r" (x), [key] "r" (ctx->X),
-         [add] "m" (add), [eight] "m" (eight),
-         [rotl8] "m" (rotl8_256), [rotl16] "m" (rotl16_256)
-       : "ymm0", "ymm1", "ymm2", "ymm3",
-         "ymm4", "ymm5", "ymm6", "ymm7",
-         "ymm8", "ymm9", "ymm10", "ymm11",
-         "ymm12", "ymm13", "ymm14", "ymm15", "memory"
-    );
-
-    /* AVX code optimised for multiples of 256 bytes. */
-    if (bytes == 256) {
-        chacha_encrypt_avx(ctx, m, c, bytes);
-        bytes -= 256;
-    }
-
-    for (; bytes >= CHACHA_CHUNK_BYTES;) {
-        CHACHA_CHUNK_AVX2();
-        bytes -= CHACHA_CHUNK_BYTES;
-        c += CHACHA_CHUNK_BYTES;
-        m += CHACHA_CHUNK_BYTES;
-    }
-    if (bytes > 0) {
-        CHACHA_PARTIAL_CHUNK_AVX2();
-    }
-}
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* USE_INTEL_CHACHA_SPEEDUP */
-
-/**
-  * Encrypt a stream of bytes
-  */
-static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c,
-                                    word32 bytes)
-{
-    byte*  output;
-    word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
-    word32 i;
-
-    output = (byte*)temp;
-
-    for (; bytes > 0;) {
-        wc_Chacha_wordtobyte(temp, ctx->X);
-        ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]);
-        if (bytes <= CHACHA_CHUNK_BYTES) {
-            for (i = 0; i < bytes; ++i) {
-                c[i] = m[i] ^ output[i];
-            }
-            return;
-        }
-        for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) {
-            c[i] = m[i] ^ output[i];
-        }
-        bytes -= CHACHA_CHUNK_BYTES;
-        c += CHACHA_CHUNK_BYTES;
-        m += CHACHA_CHUNK_BYTES;
-    }
-}
-
-/**
-  * API to encrypt/decrypt a message of any size.
-  */
-int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input,
-                      word32 msglen)
-{
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef USE_INTEL_CHACHA_SPEEDUP
-    if (!cpuidFlagsSet) {
-        cpuidFlags = cpuid_get_flags();
-        cpuidFlagsSet = 1;
-    }
-
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(cpuidFlags)) {
-        chacha_encrypt_avx2(ctx, input, output, msglen);
-        return 0;
-    }
-    #endif
-    if (IS_INTEL_AVX1(cpuidFlags)) {
-        chacha_encrypt_avx(ctx, input, output, msglen);
-        return 0;
-    }
-    else {
-        chacha_encrypt_x64(ctx, input, output, msglen);
-        return 0;
-    }
-#endif
-    wc_Chacha_encrypt_bytes(ctx, input, output, msglen);
-
-    return 0;
-}
-
-#endif /* HAVE_CHACHA*/
-
-
--- a/wolfcrypt/src/chacha20_poly1305.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/* chacha.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-
-#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/chacha.h>
-#include <wolfssl/wolfcrypt/poly1305.h>
-
-#ifdef NO_INLINE
-#include <wolfssl/wolfcrypt/misc.h>
-#else
-#define WOLFSSL_MISC_INCLUDED
-#include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef CHACHA_AEAD_TEST
-#include <stdio.h>
-#endif
-
-#define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER  0
-#define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16
-
-static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]);
-static int calculateAuthTag(
-                  const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                  const byte* inAAD, const word32 inAADLen,
-                  const byte *inCiphertext, const word32 inCiphertextLen,
-                  byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
-
-int wc_ChaCha20Poly1305_Encrypt(
-                const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
-                const byte* inAAD, const word32 inAADLen,
-                const byte* inPlaintext, const word32 inPlaintextLen,
-                byte* outCiphertext,
-                byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
-{
-    int err;
-    byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
-    ChaCha chaChaCtx;
-
-    /* Validate function arguments */
-
-    if (!inKey || !inIV ||
-        !inPlaintext || !inPlaintextLen ||
-        !outCiphertext ||
-        !outAuthTag)
-    {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
-
-    /* Create the Poly1305 key */
-    err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
-    if (err != 0) return err;
-
-    err = wc_Chacha_SetIV(&chaChaCtx, inIV,
-                           CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
-    if (err != 0) return err;
-
-    err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
-                             CHACHA20_POLY1305_AEAD_KEYSIZE);
-    if (err != 0) return err;
-
-    /* Encrypt the plaintext using ChaCha20 */
-    err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext,
-                            inPlaintextLen);
-    /* Calculate the Poly1305 auth tag */
-    if (err == 0)
-        err = calculateAuthTag(poly1305Key,
-                               inAAD, inAADLen,
-                               outCiphertext, inPlaintextLen,
-                               outAuthTag);
-    ForceZero(poly1305Key, sizeof(poly1305Key));
-
-    return err;
-}
-
-
-int wc_ChaCha20Poly1305_Decrypt(
-                const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
-                const byte* inAAD, const word32 inAADLen,
-                const byte* inCiphertext, const word32 inCiphertextLen,
-                const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
-                byte* outPlaintext)
-{
-    int err;
-    byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
-    ChaCha chaChaCtx;
-    byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
-
-    /* Validate function arguments */
-
-    if (!inKey || !inIV ||
-        !inCiphertext || !inCiphertextLen ||
-        !inAuthTag ||
-        !outPlaintext)
-    {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag));
-    XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
-
-    /* Create the Poly1305 key */
-    err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
-    if (err != 0) return err;
-
-    err = wc_Chacha_SetIV(&chaChaCtx, inIV,
-                           CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
-    if (err != 0) return err;
-
-    err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
-                             CHACHA20_POLY1305_AEAD_KEYSIZE);
-    if (err != 0) return err;
-
-    /* Calculate the Poly1305 auth tag */
-    err = calculateAuthTag(poly1305Key,
-                           inAAD, inAADLen,
-                           inCiphertext, inCiphertextLen,
-                           calculatedAuthTag);
-
-    /* Compare the calculated auth tag with the received one */
-    if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag,
-                                    CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0)
-    {
-        err = MAC_CMP_FAILED_E;
-    }
-
-    /* Decrypt the received ciphertext */
-    if (err == 0)
-        err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext,
-                                inCiphertextLen);
-    ForceZero(poly1305Key, sizeof(poly1305Key));
-
-    return err;
-}
-
-
-static int calculateAuthTag(
-                const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                const byte *inAAD, const word32 inAADLen,
-                const byte *inCiphertext, const word32 inCiphertextLen,
-                 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
-{
-    int err;
-    Poly1305 poly1305Ctx;
-    byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
-    word32 paddingLen;
-    byte little64[16];
-
-    XMEMSET(padding, 0, sizeof(padding));
-
-    /* Initialize Poly1305 */
-    err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
-                            CHACHA20_POLY1305_AEAD_KEYSIZE);
-    if (err)
-        return err;
-
-    /* Create the authTag by MAC'ing the following items: */
-    /* -- AAD */
-    if (inAAD && inAADLen)
-    {
-        err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen);
-        /* -- padding1: pad the AAD to 16 bytes */
-        paddingLen = -(int)inAADLen &
-                                  (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
-        if (paddingLen)
-            err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
-
-        if (err)
-            return err;
-    }
-
-    /* -- Ciphertext */
-    err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
-    if (err)
-        return err;
-
-    /* -- padding2: pad the ciphertext to 16 bytes */
-    paddingLen = -(int)inCiphertextLen &
-                                  (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
-    if (paddingLen)
-    {
-        err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
-        if (err)
-            return err;
-    }
-
-    /* -- AAD length as a 64-bit little endian integer */
-    word32ToLittle64(inAADLen, little64);
-    /* -- Ciphertext length as a 64-bit little endian integer */
-    word32ToLittle64(inCiphertextLen, little64 + 8);
-    err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
-    if (err)
-        return err;
-
-    /* Finalize the auth tag */
-    err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
-
-    return err;
-}
-
-
-static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8])
-{
-#ifndef WOLFSSL_X86_64_BUILD
-    XMEMSET(outLittle64 + 4, 0, 4);
-
-    outLittle64[0] = (byte)(inLittle32 & 0x000000FF);
-    outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8);
-    outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16);
-    outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24);
-#else
-    *(word64*)outLittle64 = inLittle32;
-#endif
-}
-
-
-#endif /* HAVE_CHACHA && HAVE_POLY1305 */
-
--- a/wolfcrypt/src/cmac.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/* cmac.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$n")
-        #pragma const_seg(".fipsB$n")
-    #endif
-#endif
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/aes.h>
-#include <wolfssl/wolfcrypt/cmac.h>
-
-
-static void ShiftAndXorRb(byte* out, byte* in)
-{
-    int i, j, xorRb;
-    int mask = 0, last = 0;
-    byte Rb = 0x87;
-
-    xorRb = (in[0] & 0x80) != 0;
-
-    for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) {
-        last = (in[j] & 0x80) ? 1 : 0;
-        out[j] = (byte)((in[j] << 1) | mask);
-        mask = last;
-        if (xorRb) {
-            out[j] ^= Rb;
-            Rb = 0;
-        }
-    }
-}
-
-
-int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz,
-                int type, void* unused)
-{
-    int ret;
-
-    (void)unused;
-
-    if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES)
-        return BAD_FUNC_ARG;
-
-    XMEMSET(cmac, 0, sizeof(Cmac));
-    ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION);
-    if (ret == 0) {
-        byte l[AES_BLOCK_SIZE];
-
-        XMEMSET(l, 0, AES_BLOCK_SIZE);
-        wc_AesEncryptDirect(&cmac->aes, l, l);
-        ShiftAndXorRb(cmac->k1, l);
-        ShiftAndXorRb(cmac->k2, cmac->k1);
-        ForceZero(l, AES_BLOCK_SIZE);
-    }
-    return ret;
-}
-
-
-int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
-{
-    if ((cmac == NULL) || (in == NULL && inSz != 0))
-        return BAD_FUNC_ARG;
-
-    while (inSz != 0) {
-        word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz);
-        XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
-
-        cmac->bufferSz += add;
-        in += add;
-        inSz -= add;
-
-        if (cmac->bufferSz == AES_BLOCK_SIZE && inSz != 0) {
-            if (cmac->totalSz != 0)
-                xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
-            wc_AesEncryptDirect(&cmac->aes,
-                                cmac->digest,
-                                cmac->buffer);
-            cmac->totalSz += AES_BLOCK_SIZE;
-            cmac->bufferSz = 0;
-        }
-    }
-
-    return 0;
-}
-
-
-int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz)
-{
-    const byte* subKey;
-
-    if (cmac == NULL || out == NULL || outSz == NULL)
-        return BAD_FUNC_ARG;
-
-    if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ)
-        return BUFFER_E;
-
-    if (cmac->bufferSz == AES_BLOCK_SIZE) {
-        subKey = cmac->k1;
-    }
-    else {
-        word32 remainder = AES_BLOCK_SIZE - cmac->bufferSz;
-
-        if (remainder == 0)
-            remainder = AES_BLOCK_SIZE;
-
-        if (remainder > 1)
-            XMEMSET(cmac->buffer + AES_BLOCK_SIZE - remainder, 0, remainder);
-        cmac->buffer[AES_BLOCK_SIZE - remainder] = 0x80;
-        subKey = cmac->k2;
-    }
-    xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE);
-    xorbuf(cmac->buffer, subKey, AES_BLOCK_SIZE);
-    wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer);
-
-    XMEMCPY(out, cmac->digest, *outSz);
-
-    ForceZero(cmac, sizeof(Cmac));
-
-    return 0;
-}
-
-
-int wc_AesCmacGenerate(byte* out, word32* outSz,
-                       const byte* in, word32 inSz,
-                       const byte* key, word32 keySz)
-{
-    Cmac cmac;
-    int ret;
-
-    if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0)
-        return BAD_FUNC_ARG;
-
-    ret = wc_InitCmac(&cmac, key, keySz, WC_CMAC_AES, NULL);
-    if (ret != 0)
-        return ret;
-
-    ret = wc_CmacUpdate(&cmac, in, inSz);
-    if (ret != 0)
-        return ret;
-
-    ret = wc_CmacFinal(&cmac, out, outSz);
-    if (ret != 0)
-        return ret;
-
-    return 0;
-}
-
-
-int wc_AesCmacVerify(const byte* check, word32 checkSz,
-                     const byte* in, word32 inSz,
-                     const byte* key, word32 keySz)
-{
-    byte a[AES_BLOCK_SIZE];
-    word32 aSz = sizeof(a);
-    int result;
-    int compareRet;
-
-    if (check == NULL || checkSz == 0 || (in == NULL && inSz != 0) ||
-        key == NULL || keySz == 0)
-
-        return BAD_FUNC_ARG;
-
-    XMEMSET(a, 0, aSz);
-    result = wc_AesCmacGenerate(a, &aSz, in, inSz, key, keySz);
-    compareRet = ConstantCompare(check, a, min(checkSz, aSz));
-
-    if (result == 0)
-        result = compareRet ? 1 : 0;
-
-    return result;
-}
-
-
-#endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */
-
--- a/wolfcrypt/src/coding.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,459 +0,0 @@
-/* coding.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_CODING
-
-#include <wolfssl/wolfcrypt/coding.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-
-enum {
-    BAD         = 0xFF,  /* invalid encoding */
-    PAD         = '=',
-    PEM_LINE_SZ = 64
-};
-
-
-static
-const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
-                              52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-                              BAD, BAD, BAD, BAD, BAD, BAD, BAD,
-                              0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-                              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
-                              20, 21, 22, 23, 24, 25,
-                              BAD, BAD, BAD, BAD, BAD, BAD,
-                              26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
-                              36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
-                              46, 47, 48, 49, 50, 51
-                            };
-
-
-int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    word32 i = 0;
-    word32 j = 0;
-    word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
-    const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
-
-    plainSz = (plainSz * 3 + 3) / 4;
-    if (plainSz > *outLen) return BAD_FUNC_ARG;
-
-    while (inLen > 3) {
-        byte b1, b2, b3;
-        byte e1 = in[j++];
-        byte e2 = in[j++];
-        byte e3 = in[j++];
-        byte e4 = in[j++];
-
-        int pad3 = 0;
-        int pad4 = 0;
-
-        if (e1 == 0)            /* end file 0's */
-            break;
-        if (e3 == PAD)
-            pad3 = 1;
-        if (e4 == PAD)
-            pad4 = 1;
-
-        if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
-            WOLFSSL_MSG("Bad Base64 Decode data, too small");
-            return ASN_INPUT_E;
-        }
-
-        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
-            WOLFSSL_MSG("Bad Base64 Decode data, too big");
-            return ASN_INPUT_E;
-        }
-
-        e1 = base64Decode[e1 - 0x2B];
-        e2 = base64Decode[e2 - 0x2B];
-        e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
-        e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
-
-        b1 = (byte)((e1 << 2) | (e2 >> 4));
-        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
-        b3 = (byte)(((e3 & 0x3) << 6) | e4);
-
-        out[i++] = b1;
-        if (!pad3)
-            out[i++] = b2;
-        if (!pad4)
-            out[i++] = b3;
-        else
-            break;
-
-        inLen -= 4;
-        if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
-            byte endLine = in[j++];
-            inLen--;
-            while (inLen && endLine == ' ') {   /* allow trailing whitespace */
-                endLine = in[j++];
-                inLen--;
-            }
-            if (endLine == '\r') {
-                if (inLen) {
-                    endLine = in[j++];
-                    inLen--;
-                }
-            }
-            if (endLine != '\n') {
-                WOLFSSL_MSG("Bad end of line in Base64 Decode");
-                return ASN_INPUT_E;
-            }
-        }
-    }
-    *outLen = i;
-
-    return 0;
-}
-
-
-#if defined(WOLFSSL_BASE64_ENCODE)
-
-static
-const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-                              'U', 'V', 'W', 'X', 'Y', 'Z',
-                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
-                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-                              'u', 'v', 'w', 'x', 'y', 'z',
-                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-                              '+', '/'
-                            };
-
-
-/* make sure *i (idx) won't exceed max, store and possibly escape to out,
- * raw means use e w/o decode,  0 on success */
-static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max,
-                  int raw, int getSzOnly)
-{
-    int    doEscape = 0;
-    word32 needed = 1;
-    word32 idx = *i;
-
-    byte basic;
-    byte plus    = 0;
-    byte equals  = 0;
-    byte newline = 0;
-
-    if (raw)
-        basic = e;
-    else
-        basic = base64Encode[e];
-
-    /* check whether to escape. Only escape for EncodeEsc */
-    if (escaped == WC_ESC_NL_ENC) {
-        switch ((char)basic) {
-            case '+' :
-                plus     = 1;
-                doEscape = 1;
-                needed  += 2;
-                break;
-            case '=' :
-                equals   = 1;
-                doEscape = 1;
-                needed  += 2;
-                break;
-            case '\n' :
-                newline  = 1;
-                doEscape = 1;
-                needed  += 2;
-                break;
-            default:
-                /* do nothing */
-                break;
-        }
-    }
-
-    /* check size */
-    if ( (idx+needed) > max && !getSzOnly) {
-        WOLFSSL_MSG("Escape buffer max too small");
-        return BUFFER_E;
-    }
-
-    /* store it */
-    if (doEscape == 0) {
-        if(getSzOnly)
-            idx++;
-        else
-            out[idx++] = basic;
-    }
-    else {
-        if(getSzOnly)
-            idx+=3;
-        else {
-            out[idx++] = '%';  /* start escape */
-
-            if (plus) {
-                out[idx++] = '2';
-                out[idx++] = 'B';
-            }
-            else if (equals) {
-                out[idx++] = '3';
-                out[idx++] = 'D';
-            }
-            else if (newline) {
-                out[idx++] = '0';
-                out[idx++] = 'A';
-            }
-        }
-    }
-    *i = idx;
-
-    return 0;
-}
-
-
-/* internal worker, handles both escaped and normal line endings.
-   If out buffer is NULL, will return sz needed in outLen */
-static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
-                           word32* outLen, int escaped)
-{
-    int    ret = 0;
-    word32 i = 0,
-           j = 0,
-           n = 0;   /* new line counter */
-
-    int    getSzOnly = (out == NULL);
-
-    word32 outSz = (inLen + 3 - 1) / 3 * 4;
-    word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
-
-    if (escaped == WC_ESC_NL_ENC)
-        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
-    else if (escaped == WC_NO_NL_ENC)
-        addSz = 0;    /* encode without \n */
-
-    outSz += addSz;
-
-    /* if escaped we can't predetermine size for one pass encoding, but
-     * make sure we have enough if no escapes are in input
-     * Also need to ensure outLen valid before dereference */
-    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
-
-    while (inLen > 2) {
-        byte b1 = in[j++];
-        byte b2 = in[j++];
-        byte b3 = in[j++];
-
-        /* encoded idx */
-        byte e1 = b1 >> 2;
-        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
-        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
-        byte e4 = b3 & 0x3F;
-
-        /* store */
-        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
-        if (ret != 0) break;
-        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
-        if (ret != 0) break;
-        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
-        if (ret != 0) break;
-        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
-        if (ret != 0) break;
-
-        inLen -= 3;
-
-        /* Insert newline after PEM_LINE_SZ, unless no \n requested */
-        if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen){
-            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
-            if (ret != 0) break;
-        }
-    }
-
-    /* last integral */
-    if (inLen && ret == 0) {
-        int twoBytes = (inLen == 2);
-
-        byte b1 = in[j++];
-        byte b2 = (twoBytes) ? in[j++] : 0;
-
-        byte e1 = b1 >> 2;
-        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
-        byte e3 = (byte)((b2 & 0xF) << 2);
-
-        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
-        if (ret == 0)
-            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
-        if (ret == 0) {
-            /* third */
-            if (twoBytes)
-                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
-            else
-                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
-        }
-        /* fourth always pad */
-        if (ret == 0)
-            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
-    }
-
-    if (ret == 0 && escaped != WC_NO_NL_ENC)
-        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
-
-    if (i != outSz && escaped != 1 && ret == 0)
-        return ASN_INPUT_E;
-
-    *outLen = i;
-    if(ret == 0)
-        return getSzOnly ? LENGTH_ONLY_E : 0;
-    return ret;
-}
-
-
-/* Base64 Encode, PEM style, with \n line endings */
-int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
-}
-
-
-/* Base64 Encode, with %0A escaped line endings instead of \n */
-int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
-}
-
-int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
-}
-
-#endif /* WOLFSSL_BASE64_ENCODE */
-
-
-#ifdef WOLFSSL_BASE16
-
-static
-const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
-                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
-                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
-                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
-                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
-                           BAD, BAD,  /* G - ` */
-                           10, 11, 12, 13, 14, 15   /* lower case a-f */
-                         };  /* A starts at 0x41 not 0x3A */
-
-int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    word32 inIdx  = 0;
-    word32 outIdx = 0;
-
-    if (in == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    if (inLen == 1 && *outLen && in) {
-        byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
-
-        /* sanity check */
-        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
-            return ASN_INPUT_E;
-
-        b  = hexDecode[b];
-
-        if (b == BAD)
-            return ASN_INPUT_E;
-
-        out[outIdx++] = b;
-
-        *outLen = outIdx;
-        return 0;
-    }
-
-    if (inLen % 2)
-        return BAD_FUNC_ARG;
-
-    if (*outLen < (inLen / 2))
-        return BAD_FUNC_ARG;
-
-    while (inLen) {
-        byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
-        byte b2 = in[inIdx++] - 0x30;
-
-        /* sanity checks */
-        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
-            return ASN_INPUT_E;
-        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
-            return ASN_INPUT_E;
-
-        b  = hexDecode[b];
-        b2 = hexDecode[b2];
-
-        if (b == BAD || b2 == BAD)
-            return ASN_INPUT_E;
-
-        out[outIdx++] = (byte)((b << 4) | b2);
-        inLen -= 2;
-    }
-
-    *outLen = outIdx;
-    return 0;
-}
-
-int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
-{
-    word32 outIdx = 0;
-    word32 i;
-    byte   hb, lb;
-
-    if (in == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    if (*outLen < (2 * inLen + 1))
-        return BAD_FUNC_ARG;
-
-    for (i = 0; i < inLen; i++) {
-        hb = in[i] >> 4;
-        lb = in[i] & 0x0f;
-
-        /* ASCII value */
-        hb += '0';
-        if (hb > '9')
-            hb += 7;
-
-        /* ASCII value */
-        lb += '0';
-        if (lb>'9')
-            lb += 7;
-
-        out[outIdx++] = hb;
-        out[outIdx++] = lb;
-    }
-
-    /* force 0 at this end */
-    out[outIdx++] = 0;
-
-    *outLen = outIdx;
-    return 0;
-}
-
-#endif /* WOLFSSL_BASE16 */
-
-#endif /* !NO_CODING */
-
--- a/wolfcrypt/src/compress.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/* compress.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_LIBZ
-
-
-#include <wolfssl/wolfcrypt/compress.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#include <zlib.h>
-
-
-/* alloc user allocs to work with zlib */
-static void* myAlloc(void* opaque, unsigned int item, unsigned int size)
-{
-    (void)opaque;
-    return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
-}
-
-
-static void myFree(void* opaque, void* memory)
-{
-    (void)opaque;
-    XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
-}
-
-
-#ifdef HAVE_MCAPI
-    #define DEFLATE_DEFAULT_WINDOWBITS  11
-    #define DEFLATE_DEFAULT_MEMLEVEL     1
-#else
-    #define DEFLATE_DEFAULT_WINDOWBITS 15
-    #define DEFLATE_DEFAULT_MEMLEVEL    8
-#endif
-
-
-int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 flags)
-/*
- * out - pointer to destination buffer
- * outSz - size of destination buffer
- * in - pointer to source buffer to compress
- * inSz - size of source to compress
- * flags - flags to control how compress operates
- *
- * return:
- *    negative - error code
- *    positive - bytes stored in out buffer
- *
- * Note, the output buffer still needs to be larger than the input buffer.
- * The right chunk of data won't compress at all, and the lookup table will
- * add to the size of the output. The libz code says the compressed
- * buffer should be srcSz + 0.1% + 12.
- */
-{
-    z_stream stream;
-    int result = 0;
-
-    stream.next_in = (Bytef*)in;
-    stream.avail_in = (uInt)inSz;
-#ifdef MAXSEG_64K
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != inSz) return COMPRESS_INIT_E;
-#endif
-    stream.next_out = out;
-    stream.avail_out = (uInt)outSz;
-    if ((uLong)stream.avail_out != outSz) return COMPRESS_INIT_E;
-
-    stream.zalloc = (alloc_func)myAlloc;
-    stream.zfree = (free_func)myFree;
-    stream.opaque = (voidpf)0;
-
-    if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-                     DEFLATE_DEFAULT_WINDOWBITS, DEFLATE_DEFAULT_MEMLEVEL,
-                     flags ? Z_FIXED : Z_DEFAULT_STRATEGY) != Z_OK)
-        return COMPRESS_INIT_E;
-
-    if (deflate(&stream, Z_FINISH) != Z_STREAM_END) {
-        deflateEnd(&stream);
-        return COMPRESS_E;
-    }
-
-    result = (int)stream.total_out;
-
-    if (deflateEnd(&stream) != Z_OK)
-        result = COMPRESS_E;
-
-    return result;
-}
-
-
-int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz)
-/*
- * out - pointer to destination buffer
- * outSz - size of destination buffer
- * in - pointer to source buffer to compress
- * inSz - size of source to compress
- * flags - flags to control how compress operates
- *
- * return:
- *    negative - error code
- *    positive - bytes stored in out buffer
- */
-{
-    z_stream stream;
-    int result = 0;
-
-    stream.next_in = (Bytef*)in;
-    stream.avail_in = (uInt)inSz;
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != inSz) return DECOMPRESS_INIT_E;
-
-    stream.next_out = out;
-    stream.avail_out = (uInt)outSz;
-    if ((uLong)stream.avail_out != outSz) return DECOMPRESS_INIT_E;
-
-    stream.zalloc = (alloc_func)myAlloc;
-    stream.zfree = (free_func)myFree;
-    stream.opaque = (voidpf)0;
-
-    if (inflateInit2(&stream, DEFLATE_DEFAULT_WINDOWBITS) != Z_OK)
-        return DECOMPRESS_INIT_E;
-
-    if (inflate(&stream, Z_FINISH) != Z_STREAM_END) {
-        inflateEnd(&stream);
-        return DECOMPRESS_E;
-    }
-
-    result = (int)stream.total_out;
-
-    if (inflateEnd(&stream) != Z_OK)
-        result = DECOMPRESS_E;
-
-    return result;
-}
-
-
-#endif /* HAVE_LIBZ */
-
-
--- a/wolfcrypt/src/cpuid.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/* cpuid.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#include <wolfssl/wolfcrypt/cpuid.h>
-
-#if (defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \
-     defined(WOLFSSL_AESNI)) && !defined(WOLFSSL_NO_ASM)
-    /* Each platform needs to query info type 1 from cpuid to see if aesni is
-     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
-     */
-
-    #ifndef _MSC_VER
-        #define cpuid(reg, leaf, sub)\
-            __asm__ __volatile__ ("cpuid":\
-                "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\
-                "a" (leaf), "c"(sub));
-
-        #define XASM_LINK(f) asm(f)
-    #else
-        #include <intrin.h>
-
-        #define cpuid(a,b,c) __cpuidex((int*)a,b,c)
-
-        #define XASM_LINK(f)
-    #endif /* _MSC_VER */
-
-    #define EAX 0
-    #define EBX 1
-    #define ECX 2
-    #define EDX 3
-
-    static word32 cpuid_check = 0;
-    static word32 cpuid_flags = 0;
-
-    static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit)
-    {
-        int got_intel_cpu = 0;
-        int got_amd_cpu = 0;
-        unsigned int reg[5];
-        reg[4] = '\0';
-        cpuid(reg, 0, 0);
-
-        /* check for Intel cpu */
-        if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 &&
-            XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 &&
-            XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) {
-            got_intel_cpu = 1;
-        }
-
-        /* check for AMD cpu */
-        if (XMEMCMP((char *)&(reg[EBX]), "Auth", 4) == 0 &&
-            XMEMCMP((char *)&(reg[EDX]), "enti", 4) == 0 &&
-            XMEMCMP((char *)&(reg[ECX]), "cAMD", 4) == 0) {
-            got_amd_cpu = 1;
-        }
-
-        if (got_intel_cpu || got_amd_cpu) {
-            cpuid(reg, leaf, sub);
-            return ((reg[num] >> bit) & 0x1);
-        }
-        return 0;
-    }
-
-
-    void cpuid_set_flags(void)
-    {
-        if (!cpuid_check) {
-            if (cpuid_flag(1, 0, ECX, 28)) { cpuid_flags |= CPUID_AVX1  ; }
-            if (cpuid_flag(7, 0, EBX,  5)) { cpuid_flags |= CPUID_AVX2  ; }
-            if (cpuid_flag(7, 0, EBX,  8)) { cpuid_flags |= CPUID_BMI2  ; }
-            if (cpuid_flag(1, 0, ECX, 30)) { cpuid_flags |= CPUID_RDRAND; }
-            if (cpuid_flag(7, 0, EBX, 18)) { cpuid_flags |= CPUID_RDSEED; }
-            if (cpuid_flag(1, 0, ECX, 26)) { cpuid_flags |= CPUID_AESNI ; }
-            if (cpuid_flag(7, 0, EBX, 19)) { cpuid_flags |= CPUID_ADX   ; }
-            cpuid_check = 1;
-        }
-    }
-
-    word32 cpuid_get_flags(void)
-    {
-        if (!cpuid_check)
-            cpuid_set_flags();
-        return cpuid_flags;
-    }
-#endif
-
--- a/wolfcrypt/src/cryptodev.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* cryptodev.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* This framework provides a central place for crypto hardware integration
-   using the devId scheme. If not supported return `NOT_COMPILED_IN`. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef WOLF_CRYPTO_DEV
-
-#include <wolfssl/wolfcrypt/cryptodev.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-
-/* TODO: Consider linked list with mutex */
-#ifndef MAX_CRYPTO_DEVICES
-#define MAX_CRYPTO_DEVICES 8
-#endif
-
-typedef struct CryptoDev {
-    int devId;
-    CryptoDevCallbackFunc cb;
-    void* ctx;
-} CryptoDev;
-static CryptoDev gCryptoDev[MAX_CRYPTO_DEVICES];
-
-static CryptoDev* wc_CryptoDev_FindDevice(int devId)
-{
-    int i;
-    for (i=0; i<MAX_CRYPTO_DEVICES; i++) {
-        if (gCryptoDev[i].devId == devId)
-            return &gCryptoDev[i];
-    }
-    return NULL;
-}
-
-void wc_CryptoDev_Init(void)
-{
-    int i;
-    for (i=0; i<MAX_CRYPTO_DEVICES; i++)
-        gCryptoDev[i].devId = INVALID_DEVID;
-}
-
-int wc_CryptoDev_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx)
-{
-    /* find existing or new */
-    CryptoDev* dev = wc_CryptoDev_FindDevice(devId);
-    if (dev == NULL)
-        dev = wc_CryptoDev_FindDevice(INVALID_DEVID);
-
-    if (dev == NULL)
-        return BUFFER_E; /* out of devices */
-
-    dev->devId = devId;
-    dev->cb = cb;
-    dev->ctx = ctx;
-
-    return 0;
-}
-
-void wc_CryptoDev_UnRegisterDevice(int devId)
-{
-    CryptoDev* dev = wc_CryptoDev_FindDevice(devId);
-    if (dev) {
-        XMEMSET(dev, 0, sizeof(*dev));
-        dev->devId = INVALID_DEVID;
-    }
-}
-
-#ifndef NO_RSA
-int wc_CryptoDev_Rsa(const byte* in, word32 inLen, byte* out,
-    word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-    int ret = NOT_COMPILED_IN;
-    CryptoDev* dev;
-
-    /* locate registered callback */
-    dev = wc_CryptoDev_FindDevice(key->devId);
-    if (dev) {
-        if (dev->cb) {
-            wc_CryptoInfo cryptoInfo;
-            XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
-            cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
-            cryptoInfo.pk.type = WC_PK_TYPE_RSA;
-            cryptoInfo.pk.rsa.in = in;
-            cryptoInfo.pk.rsa.inLen = inLen;
-            cryptoInfo.pk.rsa.out = out;
-            cryptoInfo.pk.rsa.outLen = outLen;
-            cryptoInfo.pk.rsa.type = type;
-            cryptoInfo.pk.rsa.key = key;
-            cryptoInfo.pk.rsa.rng = rng;
-
-            ret = dev->cb(key->devId, &cryptoInfo, dev->ctx);
-        }
-    }
-
-    return ret;
-}
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-int wc_CryptoDev_Ecdh(ecc_key* private_key, ecc_key* public_key,
-    byte* out, word32* outlen)
-{
-    int ret = NOT_COMPILED_IN;
-    CryptoDev* dev;
-
-    /* locate registered callback */
-    dev = wc_CryptoDev_FindDevice(private_key->devId);
-    if (dev) {
-        if (dev->cb) {
-            wc_CryptoInfo cryptoInfo;
-            XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
-            cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
-            cryptoInfo.pk.type = WC_PK_TYPE_ECDH;
-            cryptoInfo.pk.ecdh.private_key = private_key;
-            cryptoInfo.pk.ecdh.public_key = public_key;
-            cryptoInfo.pk.ecdh.out = out;
-            cryptoInfo.pk.ecdh.outlen = outlen;
-
-            ret = dev->cb(private_key->devId, &cryptoInfo, dev->ctx);
-        }
-    }
-
-    return ret;
-}
-
-int wc_CryptoDev_EccSign(const byte* in, word32 inlen, byte* out,
-    word32 *outlen, WC_RNG* rng, ecc_key* key)
-{
-    int ret = NOT_COMPILED_IN;
-    CryptoDev* dev;
-
-    /* locate registered callback */
-    dev = wc_CryptoDev_FindDevice(key->devId);
-    if (dev) {
-        if (dev->cb) {
-            wc_CryptoInfo cryptoInfo;
-            XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
-            cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
-            cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_SIGN;
-            cryptoInfo.pk.eccsign.in = in;
-            cryptoInfo.pk.eccsign.inlen = inlen;
-            cryptoInfo.pk.eccsign.out = out;
-            cryptoInfo.pk.eccsign.outlen = outlen;
-            cryptoInfo.pk.eccsign.rng = rng;
-            cryptoInfo.pk.eccsign.key = key;
-
-            ret = dev->cb(key->devId, &cryptoInfo, dev->ctx);
-        }
-    }
-
-    return ret;
-}
-
-int wc_CryptoDev_EccVerify(const byte* sig, word32 siglen,
-    const byte* hash, word32 hashlen, int* res, ecc_key* key)
-{
-    int ret = NOT_COMPILED_IN;
-    CryptoDev* dev;
-
-    /* locate registered callback */
-    dev = wc_CryptoDev_FindDevice(key->devId);
-    if (dev) {
-        if (dev->cb) {
-            wc_CryptoInfo cryptoInfo;
-            XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
-            cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
-            cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_VERIFY;
-            cryptoInfo.pk.eccverify.sig = sig;
-            cryptoInfo.pk.eccverify.siglen = siglen;
-            cryptoInfo.pk.eccverify.hash = hash;
-            cryptoInfo.pk.eccverify.hashlen = hashlen;
-            cryptoInfo.pk.eccverify.res = res;
-            cryptoInfo.pk.eccverify.key = key;
-
-            ret = dev->cb(key->devId, &cryptoInfo, dev->ctx);
-        }
-    }
-
-    return ret;
-}
-#endif /* HAVE_ECC */
-
-#endif /* WOLF_CRYPTO_DEV */
-
--- a/wolfcrypt/src/curve25519.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,456 +0,0 @@
-/* curve25519.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_CURVE25519
-
-#include <wolfssl/wolfcrypt/curve25519.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(FREESCALE_LTC_ECC)
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-
-const curve25519_set_type curve25519_sets[] = {
-    {
-        CURVE25519_KEYSIZE,
-        "CURVE25519",
-    }
-};
-
-int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
-{
-#ifdef FREESCALE_LTC_ECC
-    const ECPoint* basepoint = wc_curve25519_GetBasePoint();
-#else
-    unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
-#endif
-    int  ret;
-
-    if (key == NULL || rng == NULL)
-        return BAD_FUNC_ARG;
-
-    /* currently only a key size of 32 bytes is used */
-    if (keysize != CURVE25519_KEYSIZE)
-        return ECC_BAD_ARG_E;
-
-#ifndef FREESCALE_LTC_ECC
-    fe_init();
-#endif
-
-    /* random number for private key */
-    ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize);
-    if (ret != 0)
-        return ret;
-
-    /* Clamp the private key */
-    key->k.point[0] &= 248;
-    key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */
-    key->k.point[CURVE25519_KEYSIZE-1] |= 64;
-
-    /* compute public key */
-    #ifdef FREESCALE_LTC_ECC
-        ret = wc_curve25519(&key->p, key->k.point, basepoint, kLTC_Weierstrass); /* input basepoint on Weierstrass curve */
-    #else
-        ret = curve25519(key->p.point, key->k.point, basepoint);
-    #endif
-    if (ret != 0) {
-        ForceZero(key->k.point, keysize);
-        ForceZero(key->p.point, keysize);
-        return ret;
-    }
-
-    return ret;
-}
-
-#ifdef HAVE_CURVE25519_SHARED_SECRET
-
-int wc_curve25519_shared_secret(curve25519_key* private_key,
-                                curve25519_key* public_key,
-                                byte* out, word32* outlen)
-{
-    return wc_curve25519_shared_secret_ex(private_key, public_key,
-                                          out, outlen, EC25519_BIG_ENDIAN);
-}
-
-int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
-                                   curve25519_key* public_key,
-                                   byte* out, word32* outlen, int endian)
-{
-    #ifdef FREESCALE_LTC_ECC
-        ECPoint o = {{0}};
-    #else
-        unsigned char o[CURVE25519_KEYSIZE];
-    #endif
-    int ret = 0;
-
-    /* sanity check */
-    if (private_key == NULL || public_key == NULL ||
-        out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE)
-        return BAD_FUNC_ARG;
-
-    /* avoid implementation fingerprinting */
-    if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F)
-        return ECC_BAD_ARG_E;
-
-    #ifdef FREESCALE_LTC_ECC
-        ret = wc_curve25519(&o, private_key->k.point, &public_key->p, kLTC_Curve25519 /* input point P on Curve25519 */);
-    #else
-        ret = curve25519(o, private_key->k.point, public_key->p.point);
-    #endif
-    if (ret != 0) {
-        #ifdef FREESCALE_LTC_ECC
-            ForceZero(o.point, CURVE25519_KEYSIZE);
-            ForceZero(o.pointY, CURVE25519_KEYSIZE);
-        #else
-            ForceZero(o, CURVE25519_KEYSIZE);
-        #endif
-        return ret;
-    }
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-        /* put shared secret key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            #ifdef FREESCALE_LTC_ECC
-                out[i] = o.point[CURVE25519_KEYSIZE - i -1];
-            #else
-                out[i] = o[CURVE25519_KEYSIZE - i -1];
-            #endif
-    }
-    else /* put shared secret key in Little Endian format */
-        #ifdef FREESCALE_LTC_ECC
-            XMEMCPY(out, o.point, CURVE25519_KEYSIZE);
-        #else
-            XMEMCPY(out, o, CURVE25519_KEYSIZE);
-        #endif
-
-    *outlen = CURVE25519_KEYSIZE;
-
-    #ifdef FREESCALE_LTC_ECC
-        ForceZero(o.point, CURVE25519_KEYSIZE);
-        ForceZero(o.pointY, CURVE25519_KEYSIZE);
-    #else
-        ForceZero(o, CURVE25519_KEYSIZE);
-    #endif
-
-    return ret;
-}
-
-#endif /* HAVE_CURVE25519_SHARED_SECRET */
-
-#ifdef HAVE_CURVE25519_KEY_EXPORT
-
-/* export curve25519 public key (Big endian)
- * return 0 on success */
-int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
-{
-    return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
-}
-
-/* export curve25519 public key (Big or Little endian)
- * return 0 on success */
-int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
-                                   word32* outLen, int endian)
-{
-    if (key == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    /* check and set outgoing key size */
-    if (*outLen < CURVE25519_KEYSIZE) {
-        *outLen = CURVE25519_KEYSIZE;
-        return ECC_BAD_ARG_E;
-    }
-    *outLen = CURVE25519_KEYSIZE;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* read keys in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1];
-    }
-    else
-        XMEMCPY(out, key->p.point, CURVE25519_KEYSIZE);
-
-    return 0;
-}
-
-#endif /* HAVE_CURVE25519_KEY_EXPORT */
-
-#ifdef HAVE_CURVE25519_KEY_IMPORT
-
-/* import curve25519 public key (Big endian)
- *  return 0 on success */
-int wc_curve25519_import_public(const byte* in, word32 inLen,
-                                curve25519_key* key)
-{
-    return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
-}
-
-/* import curve25519 public key (Big or Little endian)
- * return 0 on success */
-int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
-                                curve25519_key* key, int endian)
-{
-    /* sanity check */
-    if (key == NULL || in == NULL)
-        return BAD_FUNC_ARG;
-
-    /* check size of incoming keys */
-    if (inLen != CURVE25519_KEYSIZE)
-       return ECC_BAD_ARG_E;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* read keys in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1];
-    }
-    else
-        XMEMCPY(key->p.point, in, inLen);
-
-    key->dp = &curve25519_sets[0];
-
-    /* LTC needs also Y coordinate - let's compute it */
-    #ifdef FREESCALE_LTC_ECC
-        ltc_pkha_ecc_point_t ltcPoint;
-        ltcPoint.X = &key->p.point[0];
-        ltcPoint.Y = &key->p.pointY[0];
-        LTC_PKHA_Curve25519ComputeY(&ltcPoint);
-    #endif
-
-    return 0;
-}
-
-#endif /* HAVE_CURVE25519_KEY_IMPORT */
-
-
-#ifdef HAVE_CURVE25519_KEY_EXPORT
-
-/* export curve25519 private key only raw (Big endian)
- * outLen is in/out size
- * return 0 on success */
-int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
-                                     word32* outLen)
-{
-    return wc_curve25519_export_private_raw_ex(key, out, outLen,
-                                               EC25519_BIG_ENDIAN);
-}
-
-/* export curve25519 private key only raw (Big or Little endian)
- * outLen is in/out size
- * return 0 on success */
-int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
-                                        word32* outLen, int endian)
-{
-    /* sanity check */
-    if (key == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    /* check size of outgoing buffer */
-    if (*outLen < CURVE25519_KEYSIZE) {
-        *outLen = CURVE25519_KEYSIZE;
-        return ECC_BAD_ARG_E;
-    }
-    *outLen = CURVE25519_KEYSIZE;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* put the key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1];
-    }
-    else
-        XMEMCPY(out, key->k.point, CURVE25519_KEYSIZE);
-
-    return 0;
-}
-
-/* curve25519 key pair export (Big or Little endian)
- * return 0 on success */
-int wc_curve25519_export_key_raw(curve25519_key* key,
-                                 byte* priv, word32 *privSz,
-                                 byte* pub, word32 *pubSz)
-{
-    return wc_curve25519_export_key_raw_ex(key, priv, privSz,
-                                           pub, pubSz, EC25519_BIG_ENDIAN);
-}
-
-/* curve25519 key pair export (Big or Little endian)
- * return 0 on success */
-int wc_curve25519_export_key_raw_ex(curve25519_key* key,
-                                    byte* priv, word32 *privSz,
-                                    byte* pub, word32 *pubSz,
-                                    int endian)
-{
-    int ret;
-
-    /* export private part */
-    ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
-    if (ret != 0)
-        return ret;
-
-    /* export public part */
-    return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
-}
-
-#endif /* HAVE_CURVE25519_KEY_EXPORT */
-
-#ifdef HAVE_CURVE25519_KEY_IMPORT
-
-/* curve25519 private key import (Big endian)
- * Public key to match private key needs to be imported too
- * return 0 on success */
-int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
-                                     const byte* pub, word32 pubSz,
-                                     curve25519_key* key)
-{
-    return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
-                                               key, EC25519_BIG_ENDIAN);
-}
-
-/* curve25519 private key import (Big or Little endian)
- * Public key to match private key needs to be imported too
- * return 0 on success */
-int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
-                                        const byte* pub, word32 pubSz,
-                                        curve25519_key* key, int endian)
-{
-    int ret;
-
-    /* import private part */
-    ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
-    if (ret != 0)
-        return ret;
-
-    /* import public part */
-    return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
-}
-
-/* curve25519 private key import only. (Big endian)
- * return 0 on success */
-int wc_curve25519_import_private(const byte* priv, word32 privSz,
-                                 curve25519_key* key)
-{
-    return wc_curve25519_import_private_ex(priv, privSz,
-                                           key, EC25519_BIG_ENDIAN);
-}
-
-/* curve25519 private key import only. (Big or Little endian)
- * return 0 on success */
-int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
-                                    curve25519_key* key, int endian)
-{
-    /* sanity check */
-    if (key == NULL || priv == NULL)
-        return BAD_FUNC_ARG;
-
-    /* check size of incoming keys */
-    if ((int)privSz != CURVE25519_KEYSIZE)
-        return ECC_BAD_ARG_E;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* read the key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1];
-    }
-    else
-        XMEMCPY(key->k.point, priv, CURVE25519_KEYSIZE);
-
-    key->dp = &curve25519_sets[0];
-
-    /* Clamp the key */
-    key->k.point[0] &= 248;
-    key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */
-    key->k.point[privSz-1] |= 64;
-
-    return 0;
-}
-
-#endif /* HAVE_CURVE25519_KEY_IMPORT */
-
-
-int wc_curve25519_init(curve25519_key* key)
-{
-    if (key == NULL)
-       return BAD_FUNC_ARG;
-
-    XMEMSET(key, 0, sizeof(*key));
-
-    /* currently the format for curve25519 */
-    key->dp = &curve25519_sets[0];
-
-#ifndef FREESCALE_LTC_ECC
-    fe_init();
-#endif
-
-    return 0;
-}
-
-
-/* Clean the memory of a key */
-void wc_curve25519_free(curve25519_key* key)
-{
-   if (key == NULL)
-       return;
-
-   key->dp = NULL;
-   ForceZero(key->p.point, sizeof(key->p.point));
-   ForceZero(key->k.point, sizeof(key->k.point));
-   #ifdef FREESCALE_LTC_ECC
-       ForceZero(key->p.point, sizeof(key->p.pointY));
-       ForceZero(key->k.point, sizeof(key->k.pointY));
-   #endif
-}
-
-
-/* get key size */
-int wc_curve25519_size(curve25519_key* key)
-{
-    if (key == NULL)
-        return 0;
-
-    return key->dp->size;
-}
-
-#endif /*HAVE_CURVE25519*/
-
-
--- a/wolfcrypt/src/des3.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1761 +0,0 @@
-/* des3.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-
-#ifndef NO_DES3
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$i")
-        #pragma const_seg(".fipsB$i")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/des3.h>
-
-/* fips wrapper calls, user can call direct */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        return Des_SetKey(des, key, iv, dir);
-    }
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-        if (des == NULL || key == NULL || dir < 0) {
-            return BAD_FUNC_ARG;
-        }
-
-        return Des3_SetKey_fips(des, key, iv, dir);
-    }
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        return Des_CbcEncrypt(des, out, in, sz);
-    }
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        return Des_CbcDecrypt(des, out, in, sz);
-    }
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        if (des == NULL || out == NULL || in == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return Des3_CbcEncrypt_fips(des, out, in, sz);
-    }
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        if (des == NULL || out == NULL || in == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return Des3_CbcDecrypt_fips(des, out, in, sz);
-    }
-
-    #ifdef WOLFSSL_DES_ECB
-        /* One block, compatibility only */
-        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-        {
-            return Des_EcbEncrypt(des, out, in, sz);
-        }
-        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-        {
-            return Des3_EcbEncrypt(des, out, in, sz);
-        }
-    #endif /* WOLFSSL_DES_ECB */
-
-    void wc_Des_SetIV(Des* des, const byte* iv)
-    {
-        Des_SetIV(des, iv);
-    }
-    int wc_Des3_SetIV(Des3* des, const byte* iv)
-    {
-        return Des3_SetIV_fips(des, iv);
-    }
-
-    int wc_Des3Init(Des3* des3, void* heap, int devId)
-    {
-        (void)des3;
-        (void)heap;
-        (void)devId;
-        /* FIPS doesn't support:
-            return Des3Init(des3, heap, devId); */
-        return 0;
-    }
-    void wc_Des3Free(Des3* des3)
-    {
-        (void)des3;
-        /* FIPS doesn't support:
-            Des3Free(des3); */
-    }
-
-#else /* else build without fips, or for FIPS v2 */
-
-
-#if defined(WOLFSSL_TI_CRYPT)
-    #include <wolfcrypt/src/port/ti/ti-des3.c>
-#else
-
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* Hardware Acceleration */
-#if defined(STM32_CRYPTO)
-
-    /*
-     * STM32F2/F4 hardware DES/3DES support through the standard
-     * peripheral library. (See note in README).
-     */
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        word32 *dkey = des->key;
-
-        (void)dir;
-
-        XMEMCPY(dkey, key, 8);
-    #ifndef WOLFSSL_STM32_CUBEMX
-        ByteReverseWords(dkey, dkey, 8);
-    #endif
-
-        wc_Des_SetIV(des, iv);
-
-        return 0;
-    }
-
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-    #ifndef WOLFSSL_STM32_CUBEMX
-        word32 *dkey1 = des->key[0];
-        word32 *dkey2 = des->key[1];
-        word32 *dkey3 = des->key[2];
-
-        (void)dir;
-
-        XMEMCPY(dkey1, key, 8);         /* set key 1 */
-        XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
-        XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
-
-        ByteReverseWords(dkey1, dkey1, 8);
-        ByteReverseWords(dkey2, dkey2, 8);
-        ByteReverseWords(dkey3, dkey3, 8);
-    #else
-        (void)dir;
-        XMEMCPY(des->key[0], key, DES3_KEYLEN); /* CUBEMX wants keys in sequential memory */
-    #endif
-
-        return wc_Des3_SetIV(des, iv);
-    }
-
-    static void DesCrypt(Des* des, byte* out, const byte* in, word32 sz,
-                  int dir, int mode)
-    {
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        hcryp.Instance = CRYP;
-        hcryp.Init.KeySize  = CRYP_KEYSIZE_128B;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)des->key;
-        hcryp.Init.pInitVect = (uint8_t*)des->reg;
-
-        HAL_CRYP_Init(&hcryp);
-
-        while (sz > 0)
-        {
-            /* if input and output same will overwrite input iv */
-            XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-
-            if (mode == DES_CBC) {
-                if (dir == DES_ENCRYPTION) {
-                    HAL_CRYP_DESCBC_Encrypt(&hcryp, (uint8_t*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-                }
-                else {
-                    HAL_CRYP_DESCBC_Decrypt(&hcryp, (uint8_t*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-                }
-            }
-            else {
-                if (dir == DES_ENCRYPTION) {
-                    HAL_CRYP_DESECB_Encrypt(&hcryp, (uint8_t*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-                }
-                else {
-                    HAL_CRYP_DESECB_Decrypt(&hcryp, (uint8_t*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-                }
-            }
-
-            /* store iv for next call */
-            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
-
-            sz  -= DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-            out += DES_BLOCK_SIZE;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-    #else
-        word32 *dkey, *iv;
-        CRYP_InitTypeDef DES_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure;
-        CRYP_IVInitTypeDef DES_CRYP_IVInitStructure;
-
-        dkey = des->key;
-        iv = des->reg;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure);
-        CRYP_StructInit(&DES_CRYP_InitStructure);
-        CRYP_IVStructInit(&DES_CRYP_IVInitStructure);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* set direction, mode, and datatype */
-        if (dir == DES_ENCRYPTION) {
-            DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
-        } else { /* DES_DECRYPTION */
-            DES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        }
-
-        if (mode == DES_CBC) {
-            DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_CBC;
-        } else { /* DES_ECB */
-            DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_ECB;
-        }
-
-        DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&DES_CRYP_InitStructure);
-
-        /* load key into correct registers */
-        DES_CRYP_KeyInitStructure.CRYP_Key1Left  = dkey[0];
-        DES_CRYP_KeyInitStructure.CRYP_Key1Right = dkey[1];
-        CRYP_KeyInit(&DES_CRYP_KeyInitStructure);
-
-        /* set iv */
-        ByteReverseWords(iv, iv, DES_BLOCK_SIZE);
-        DES_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
-        DES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
-        CRYP_IVInit(&DES_CRYP_IVInitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        while (sz > 0)
-        {
-            /* flush IN/OUT FIFOs */
-            CRYP_FIFOFlush();
-
-            /* if input and output same will overwrite input iv */
-            XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-
-            CRYP_DataIn(*(uint32_t*)&in[0]);
-            CRYP_DataIn(*(uint32_t*)&in[4]);
-
-            /* wait until the complete message has been processed */
-            while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-            *(uint32_t*)&out[0]  = CRYP_DataOut();
-            *(uint32_t*)&out[4]  = CRYP_DataOut();
-
-            /* store iv for next call */
-            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
-
-            sz  -= DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-            out += DES_BLOCK_SIZE;
-        }
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-    #endif /* WOLFSSL_STM32_CUBEMX */
-    }
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_CBC);
-        return 0;
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        DesCrypt(des, out, in, sz, DES_DECRYPTION, DES_CBC);
-        return 0;
-    }
-
-    int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_ECB);
-        return 0;
-    }
-
-    static void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz,
-                   int dir)
-    {
-    #ifdef WOLFSSL_STM32_CUBEMX
-        CRYP_HandleTypeDef hcryp;
-
-        XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef));
-        hcryp.Instance = CRYP;
-        hcryp.Init.KeySize  = CRYP_KEYSIZE_128B;
-        hcryp.Init.DataType = CRYP_DATATYPE_8B;
-        hcryp.Init.pKey = (uint8_t*)des->key;
-        hcryp.Init.pInitVect = (uint8_t*)des->reg;
-
-        HAL_CRYP_Init(&hcryp);
-
-        while (sz > 0)
-        {
-            if (dir == DES_ENCRYPTION) {
-                HAL_CRYP_TDESCBC_Encrypt(&hcryp, (byte*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-            }
-            else {
-                HAL_CRYP_TDESCBC_Decrypt(&hcryp, (byte*)in,
-                                    DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT);
-            }
-
-            /* store iv for next call */
-            XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-
-            sz  -= DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-            out += DES_BLOCK_SIZE;
-        }
-
-        HAL_CRYP_DeInit(&hcryp);
-    #else
-        word32 *dkey1, *dkey2, *dkey3, *iv;
-        CRYP_InitTypeDef DES3_CRYP_InitStructure;
-        CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure;
-        CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure;
-
-        dkey1 = des->key[0];
-        dkey2 = des->key[1];
-        dkey3 = des->key[2];
-        iv = des->reg;
-
-        /* crypto structure initialization */
-        CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
-        CRYP_StructInit(&DES3_CRYP_InitStructure);
-        CRYP_IVStructInit(&DES3_CRYP_IVInitStructure);
-
-        /* reset registers to their default values */
-        CRYP_DeInit();
-
-        /* set direction, mode, and datatype */
-        if (dir == DES_ENCRYPTION) {
-            DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
-        } else {
-            DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
-        }
-
-        DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC;
-        DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
-        CRYP_Init(&DES3_CRYP_InitStructure);
-
-        /* load key into correct registers */
-        DES3_CRYP_KeyInitStructure.CRYP_Key1Left  = dkey1[0];
-        DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1];
-        DES3_CRYP_KeyInitStructure.CRYP_Key2Left  = dkey2[0];
-        DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1];
-        DES3_CRYP_KeyInitStructure.CRYP_Key3Left  = dkey3[0];
-        DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1];
-        CRYP_KeyInit(&DES3_CRYP_KeyInitStructure);
-
-        /* set iv */
-        ByteReverseWords(iv, iv, DES_BLOCK_SIZE);
-        DES3_CRYP_IVInitStructure.CRYP_IV0Left  = iv[0];
-        DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1];
-        CRYP_IVInit(&DES3_CRYP_IVInitStructure);
-
-        /* enable crypto processor */
-        CRYP_Cmd(ENABLE);
-
-        while (sz > 0)
-        {
-            /* flush IN/OUT FIFOs */
-            CRYP_FIFOFlush();
-
-            CRYP_DataIn(*(uint32_t*)&in[0]);
-            CRYP_DataIn(*(uint32_t*)&in[4]);
-
-            /* wait until the complete message has been processed */
-            while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
-
-            *(uint32_t*)&out[0]  = CRYP_DataOut();
-            *(uint32_t*)&out[4]  = CRYP_DataOut();
-
-            /* store iv for next call */
-            XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-
-            sz  -= DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-            out += DES_BLOCK_SIZE;
-        }
-
-        /* disable crypto processor */
-        CRYP_Cmd(DISABLE);
-    #endif /* WOLFSSL_STM32_CUBEMX */
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        Des3Crypt(des, out, in, sz, DES_ENCRYPTION);
-        return 0;
-    }
-
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        Des3Crypt(des, out, in, sz, DES_DECRYPTION);
-        return 0;
-    }
-
-#elif defined(HAVE_COLDFIRE_SEC)
-
-    #include <wolfssl/ctaocrypt/types.h>
-
-    #include "sec.h"
-    #include "mcf5475_sec.h"
-    #include "mcf5475_siu.h"
-
-    #if defined (HAVE_THREADX)
-    #include "memory_pools.h"
-    extern TX_BYTE_POOL mp_ncached;  /* Non Cached memory pool */
-    #endif
-
-    #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64)
-    static unsigned char *desBuffIn = NULL;
-    static unsigned char *desBuffOut = NULL;
-    static byte *secIV;
-    static byte *secKey;
-    static volatile SECdescriptorType *secDesc;
-
-    static wolfSSL_Mutex Mutex_DesSEC;
-
-    #define SEC_DESC_DES_CBC_ENCRYPT  0x20500010
-    #define SEC_DESC_DES_CBC_DECRYPT  0x20400010
-    #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010
-    #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010
-
-    #define DES_IVLEN 8
-    #define DES_KEYLEN 8
-    #define DES3_IVLEN 8
-    #define DES3_KEYLEN 24
-
-    extern volatile unsigned char __MBAR[];
-
-    static void wc_Des_Cbc(byte* out, const byte* in, word32 sz,
-                        byte *key, byte *iv, word32 desc)
-    {
-        #ifdef DEBUG_WOLFSSL
-        int ret;  int stat1,stat2;
-    	  #endif
-        int size;
-        volatile int v;
-
-        wc_LockMutex(&Mutex_DesSEC) ;
-
-        secDesc->length1 = 0x0;
-        secDesc->pointer1 = NULL;
-        if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){
-            secDesc->length2 = DES_IVLEN;
-            secDesc->length3 = DES_KEYLEN;
-        } else {
-            secDesc->length2 = DES3_IVLEN;
-            secDesc->length3 = DES3_KEYLEN;
-        }
-        secDesc->pointer2 = secIV;
-        secDesc->pointer3 = secKey;
-        secDesc->pointer4 = desBuffIn;
-        secDesc->pointer5 = desBuffOut;
-        secDesc->length6 = 0;
-        secDesc->pointer6 = NULL;
-        secDesc->length7 = 0x0;
-        secDesc->pointer7 = NULL;
-        secDesc->nextDescriptorPtr = NULL;
-
-        while(sz) {
-            XMEMCPY(secIV, iv, secDesc->length2);
-            if((sz%DES_BUFFER_SIZE) == sz) {
-                size = sz;
-                sz = 0;
-            } else {
-                size = DES_BUFFER_SIZE;
-                sz -= DES_BUFFER_SIZE;
-            }
-
-            XMEMCPY(desBuffIn, in, size);
-            XMEMCPY(secKey, key, secDesc->length3);
-
-            secDesc->header = desc;
-            secDesc->length4 = size;
-            secDesc->length5 = size;
-            /* Point SEC to the location of the descriptor */
-            MCF_SEC_FR0 = (uint32)secDesc;
-            /* Initialize SEC and wait for encryption to complete */
-            MCF_SEC_CCCR0 = 0x0000001a;
-            /* poll SISR to determine when channel is complete */
-            v=0;
-            while((secDesc->header>> 24) != 0xff) {
-                if(v++ > 1000)break;
-            }
-
-        #ifdef DEBUG_WOLFSSL
-            ret = MCF_SEC_SISRH;
-            stat1 = MCF_SEC_DSR;
-            stat2 = MCF_SEC_DISR;
-            if(ret & 0xe0000000) {
-                /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */
-            }
-        #endif
-
-            XMEMCPY(out, desBuffOut, size);
-
-            if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) {
-                XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2);
-            } else {
-                XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2);
-            }
-
-            in  += size;
-            out += size;
-
-        }
-        wc_UnLockMutex(&Mutex_DesSEC) ;
-
-    }
-
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        wc_Des_Cbc(out, in, sz,  (byte *)des->key,  (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT);
-        return 0;
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        wc_Des_Cbc(out, in, sz,   (byte *)des->key,  (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT);
-        return 0;
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz)
-    {
-        wc_Des_Cbc(out, in, sz,  (byte *)des3->key,  (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT);
-    	  return 0;
-    }
-
-
-    int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz)
-    {
-        wc_Des_Cbc(out, in, sz,   (byte *)des3->key,  (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT);
-    	  return 0;
-    }
-
-    static void setParity(byte *buf, int len)
-    {
-        int i, j;
-        byte v;
-        int bits;
-
-        for (i=0; i<len; i++) {
-            v = buf[i] >> 1;
-            buf[i] = v << 1;
-            bits = 0;
-            for (j=0; j<7; j++) {
-                bits += (v&0x1);
-                v = v >> 1;
-            }
-            buf[i] |= (1 - (bits&0x1));
-        }
-
-    }
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        if(desBuffIn == NULL) {
-        #if defined (HAVE_THREADX)
-    			  int s1, s2, s3, s4, s5;
-            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
-                                                         sizeof(SECdescriptorType), TX_NO_WAIT);
-            s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn,  DES_BUFFER_SIZE, TX_NO_WAIT);
-            s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT);
-            /* Don't know des or des3 to be used. Allocate larger buffers */
-            s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey,     DES3_KEYLEN,TX_NO_WAIT);
-            s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV,      DES3_IVLEN,  TX_NO_WAIT);
-        #else
-            #warning "Allocate non-Cache buffers"
-        #endif
-
-            InitMutex(&Mutex_DesSEC);
-        }
-
-        XMEMCPY(des->key, key, DES_KEYLEN);
-        setParity((byte *)des->key, DES_KEYLEN);
-
-        if (iv) {
-            XMEMCPY(des->reg, iv, DES_IVLEN);
-        }   else {
-            XMEMSET(des->reg, 0x0, DES_IVLEN);
-        }
-    		return 0;
-    }
-
-    int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir)
-    {
-
-        if(desBuffIn == NULL) {
-        #if defined (HAVE_THREADX)
-    			  int s1, s2, s3, s4, s5;
-            s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc,
-                                                         sizeof(SECdescriptorType), TX_NO_WAIT);
-            s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn,  DES_BUFFER_SIZE, TX_NO_WAIT);
-            s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT);
-            s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey,     DES3_KEYLEN,TX_NO_WAIT);
-            s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV,      DES3_IVLEN,  TX_NO_WAIT);
-        #else
-            #warning "Allocate non-Cache buffers"
-        #endif
-
-            InitMutex(&Mutex_DesSEC);
-        }
-
-        XMEMCPY(des3->key[0], key, DES3_KEYLEN);
-        setParity((byte *)des3->key[0], DES3_KEYLEN);
-
-        if (iv) {
-            XMEMCPY(des3->reg, iv, DES3_IVLEN);
-        }   else {
-            XMEMSET(des3->reg, 0x0, DES3_IVLEN);
-        }
-        return 0;
-
-    }
-#elif defined(FREESCALE_LTC_DES)
-
-    #include "fsl_ltc.h"
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        byte* dkey = (byte*)des->key;
-
-        XMEMCPY(dkey, key, 8);
-
-        wc_Des_SetIV(des, iv);
-
-        return 0;
-    }
-
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-        int ret = 0;
-        byte* dkey1 = (byte*)des->key[0];
-        byte* dkey2 = (byte*)des->key[1];
-        byte* dkey3 = (byte*)des->key[2];
-
-        XMEMCPY(dkey1, key, 8);         /* set key 1 */
-        XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
-        XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
-
-        ret = wc_Des3_SetIV(des, iv);
-        if (ret != 0)
-            return ret;
-
-        return ret;
-    }
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        status_t status;
-        status = LTC_DES_EncryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key);
-        if (status == kStatus_Success)
-            return 0;
-        else
-            return -1;
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        status_t status;
-        status = LTC_DES_DecryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key);
-        if (status == kStatus_Success)
-            return 0;
-        else
-            return -1;
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        status_t status;
-        status = LTC_DES3_EncryptCbc(LTC_BASE,
-                                 in,
-                                 out,
-                                 sz,
-                                 (byte*)des->reg,
-                                 (byte*)des->key[0],
-                                 (byte*)des->key[1],
-                                 (byte*)des->key[2]);
-        if (status == kStatus_Success)
-            return 0;
-        else
-            return -1;
-    }
-
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        status_t status;
-        status = LTC_DES3_DecryptCbc(LTC_BASE,
-                                 in,
-                                 out,
-                                 sz,
-                                 (byte*)des->reg,
-                                 (byte*)des->key[0],
-                                 (byte*)des->key[1],
-                                 (byte*)des->key[2]);
-        if (status == kStatus_Success)
-            return 0;
-        else
-            return -1;
-
-    }
-
-#elif defined(FREESCALE_MMCAU)
-    /*
-     * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library.
-     * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU
-     * Software Library User Guide (See note in README).
-     */
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        #include "cau_api.h"
-    #else
-        #include "fsl_mmcau.h"
-    #endif
-
-    const unsigned char parityLookup[128] = {
-        1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
-        0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-        0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-        1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
-     };
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        int i = 0;
-        byte* dkey = (byte*)des->key;
-
-        XMEMCPY(dkey, key, 8);
-
-        wc_Des_SetIV(des, iv);
-
-        /* fix key parity, if needed */
-        for (i = 0; i < 8; i++) {
-            dkey[i] = ((dkey[i] & 0xFE) | parityLookup[dkey[i] >> 1]);
-        }
-
-        return 0;
-    }
-
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-        int i = 0, ret = 0;
-        byte* dkey1 = (byte*)des->key[0];
-        byte* dkey2 = (byte*)des->key[1];
-        byte* dkey3 = (byte*)des->key[2];
-
-        XMEMCPY(dkey1, key, 8);         /* set key 1 */
-        XMEMCPY(dkey2, key + 8, 8);     /* set key 2 */
-        XMEMCPY(dkey3, key + 16, 8);    /* set key 3 */
-
-        ret = wc_Des3_SetIV(des, iv);
-        if (ret != 0)
-            return ret;
-
-        /* fix key parity if needed */
-        for (i = 0; i < 8; i++)
-           dkey1[i] = ((dkey1[i] & 0xFE) | parityLookup[dkey1[i] >> 1]);
-
-        for (i = 0; i < 8; i++)
-           dkey2[i] = ((dkey2[i] & 0xFE) | parityLookup[dkey2[i] >> 1]);
-
-        for (i = 0; i < 8; i++)
-           dkey3[i] = ((dkey3[i] & 0xFE) | parityLookup[dkey3[i] >> 1]);
-
-        return ret;
-    }
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        int len = sz;
-        int ret = 0;
-        byte *iv;
-        byte temp_block[DES_BLOCK_SIZE];
-
-        iv = (byte*)des->reg;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad cau_des_encrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        while (len > 0)
-        {
-            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < DES_BLOCK_SIZE; i++)
-                temp_block[i] ^= iv[i];
-
-            ret = wolfSSL_CryptHwMutexLock();
-            if(ret != 0) {
-                return ret;
-            }
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_des_encrypt(temp_block, (byte*)des->key, out + offset);
-        #else
-            MMCAU_DES_EncryptEcb(temp_block, (byte*)des->key, out + offset);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-
-            len    -= DES_BLOCK_SIZE;
-            offset += DES_BLOCK_SIZE;
-
-            /* store IV for next block */
-            XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-        }
-
-        return ret;
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        int len = sz;
-        int ret = 0;
-        byte* iv;
-        byte temp_block[DES_BLOCK_SIZE];
-
-        iv = (byte*)des->reg;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad cau_des_decrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        while (len > 0)
-        {
-            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
-
-            ret = wolfSSL_CryptHwMutexLock();
-            if(ret != 0) {
-                return ret;
-            }
-
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_des_decrypt(in + offset, (byte*)des->key, out + offset);
-        #else
-            MMCAU_DES_DecryptEcb(in + offset, (byte*)des->key, out + offset);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < DES_BLOCK_SIZE; i++)
-                (out + offset)[i] ^= iv[i];
-
-            /* store IV for next block */
-            XMEMCPY(iv, temp_block, DES_BLOCK_SIZE);
-
-            len     -= DES_BLOCK_SIZE;
-            offset += DES_BLOCK_SIZE;
-        }
-
-        return ret;
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        int len = sz;
-        int ret = 0;
-
-        byte *iv;
-        byte temp_block[DES_BLOCK_SIZE];
-
-        iv = (byte*)des->reg;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        while (len > 0)
-        {
-            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < DES_BLOCK_SIZE; i++)
-                temp_block[i] ^= iv[i];
-
-            ret = wolfSSL_CryptHwMutexLock();
-            if(ret != 0) {
-                return ret;
-            }
-    #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_des_encrypt(temp_block,   (byte*)des->key[0], out + offset);
-            cau_des_decrypt(out + offset, (byte*)des->key[1], out + offset);
-            cau_des_encrypt(out + offset, (byte*)des->key[2], out + offset);
-    #else
-            MMCAU_DES_EncryptEcb(temp_block  , (byte*)des->key[0], out + offset);
-            MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[1], out + offset);
-            MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[2], out + offset);
-    #endif
-            wolfSSL_CryptHwMutexUnLock();
-
-            len    -= DES_BLOCK_SIZE;
-            offset += DES_BLOCK_SIZE;
-
-            /* store IV for next block */
-            XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
-        }
-
-        return ret;
-    }
-
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        int i;
-        int offset = 0;
-        int len = sz;
-        int ret = 0;
-
-        byte* iv;
-        byte temp_block[DES_BLOCK_SIZE];
-
-        iv = (byte*)des->reg;
-
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) {
-            WOLFSSL_MSG("Bad 3ede cau_des_decrypt alignment");
-            return BAD_ALIGN_E;
-        }
-    #endif
-
-        while (len > 0)
-        {
-            XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE);
-
-            ret = wolfSSL_CryptHwMutexLock();
-            if(ret != 0) {
-                return ret;
-            }
-        #ifdef FREESCALE_MMCAU_CLASSIC
-            cau_des_decrypt(in + offset,  (byte*)des->key[2], out + offset);
-            cau_des_encrypt(out + offset, (byte*)des->key[1], out + offset);
-            cau_des_decrypt(out + offset, (byte*)des->key[0], out + offset);
-        #else
-            MMCAU_DES_DecryptEcb(in + offset , (byte*)des->key[2], out + offset);
-            MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[1], out + offset);
-            MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[0], out + offset);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-
-            /* XOR block with IV for CBC */
-            for (i = 0; i < DES_BLOCK_SIZE; i++)
-                (out + offset)[i] ^= iv[i];
-
-            /* store IV for next block */
-            XMEMCPY(iv, temp_block, DES_BLOCK_SIZE);
-
-            len    -= DES_BLOCK_SIZE;
-            offset += DES_BLOCK_SIZE;
-        }
-
-        return ret;
-    }
-
-
-#elif defined(WOLFSSL_PIC32MZ_CRYPT)
-
-    /* PIC32MZ DES hardware requires size multiple of block size */
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        if (des == NULL || key == NULL || iv == NULL)
-            return BAD_FUNC_ARG;
-
-        XMEMCPY(des->key, key, DES_KEYLEN);
-        XMEMCPY(des->reg, iv, DES_IVLEN);
-
-        return 0;
-    }
-
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-        if (des == NULL || key == NULL || iv == NULL)
-            return BAD_FUNC_ARG;
-
-        XMEMCPY(des->key[0], key, DES3_KEYLEN);
-        XMEMCPY(des->reg, iv, DES3_IVLEN);
-
-        return 0;
-    }
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        if (des == NULL || out == NULL || in == NULL)
-            return BAD_FUNC_ARG;
-
-        return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
-            out, in, (blocks * DES_BLOCK_SIZE),
-            PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC);
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        if (des == NULL || out == NULL || in == NULL)
-            return BAD_FUNC_ARG;
-
-        return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
-            out, in, (blocks * DES_BLOCK_SIZE),
-            PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC);
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        if (des == NULL || out == NULL || in == NULL)
-            return BAD_FUNC_ARG;
-
-        return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
-            out, in, (blocks * DES_BLOCK_SIZE),
-            PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC);
-    }
-
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        if (des == NULL || out == NULL || in == NULL)
-            return BAD_FUNC_ARG;
-
-        return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
-            out, in, (blocks * DES_BLOCK_SIZE),
-            PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC);
-    }
-
-    #ifdef WOLFSSL_DES_ECB
-        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-        {
-            word32 blocks = sz / DES_BLOCK_SIZE;
-
-            if (des == NULL || out == NULL || in == NULL)
-                return BAD_FUNC_ARG;
-
-            return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN,
-                out, in, (blocks * DES_BLOCK_SIZE),
-                    PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_ECB);
-        }
-
-        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-        {
-            word32 blocks = sz / DES_BLOCK_SIZE;
-
-            if (des == NULL || out == NULL || in == NULL)
-                return BAD_FUNC_ARG;
-
-            return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN,
-                out, in, (blocks * DES_BLOCK_SIZE),
-                PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TECB);
-        }
-    #endif /* WOLFSSL_DES_ECB */
-
-#else
-    #define NEED_SOFT_DES
-
-#endif
-
-
-#ifdef NEED_SOFT_DES
-
-    /* permuted choice table (key) */
-    static const byte pc1[] = {
-           57, 49, 41, 33, 25, 17,  9,
-            1, 58, 50, 42, 34, 26, 18,
-           10,  2, 59, 51, 43, 35, 27,
-           19, 11,  3, 60, 52, 44, 36,
-
-           63, 55, 47, 39, 31, 23, 15,
-            7, 62, 54, 46, 38, 30, 22,
-           14,  6, 61, 53, 45, 37, 29,
-           21, 13,  5, 28, 20, 12,  4
-    };
-
-    /* number left rotations of pc1 */
-    static const byte totrot[] = {
-           1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
-    };
-
-    /* permuted choice key (table) */
-    static const byte pc2[] = {
-           14, 17, 11, 24,  1,  5,
-            3, 28, 15,  6, 21, 10,
-           23, 19, 12,  4, 26,  8,
-           16,  7, 27, 20, 13,  2,
-           41, 52, 31, 37, 47, 55,
-           30, 40, 51, 45, 33, 48,
-           44, 49, 39, 56, 34, 53,
-           46, 42, 50, 36, 29, 32
-    };
-
-    /* End of DES-defined tables */
-
-    /* bit 0 is left-most in byte */
-    static const int bytebit[] = {
-        0200,0100,040,020,010,04,02,01
-    };
-
-    static const word32 Spbox[8][64] = {
-    {   0x01010400,0x00000000,0x00010000,0x01010404,
-        0x01010004,0x00010404,0x00000004,0x00010000,
-        0x00000400,0x01010400,0x01010404,0x00000400,
-        0x01000404,0x01010004,0x01000000,0x00000004,
-        0x00000404,0x01000400,0x01000400,0x00010400,
-        0x00010400,0x01010000,0x01010000,0x01000404,
-        0x00010004,0x01000004,0x01000004,0x00010004,
-        0x00000000,0x00000404,0x00010404,0x01000000,
-        0x00010000,0x01010404,0x00000004,0x01010000,
-        0x01010400,0x01000000,0x01000000,0x00000400,
-        0x01010004,0x00010000,0x00010400,0x01000004,
-        0x00000400,0x00000004,0x01000404,0x00010404,
-        0x01010404,0x00010004,0x01010000,0x01000404,
-        0x01000004,0x00000404,0x00010404,0x01010400,
-        0x00000404,0x01000400,0x01000400,0x00000000,
-        0x00010004,0x00010400,0x00000000,0x01010004},
-    {   0x80108020,0x80008000,0x00008000,0x00108020,
-        0x00100000,0x00000020,0x80100020,0x80008020,
-        0x80000020,0x80108020,0x80108000,0x80000000,
-        0x80008000,0x00100000,0x00000020,0x80100020,
-        0x00108000,0x00100020,0x80008020,0x00000000,
-        0x80000000,0x00008000,0x00108020,0x80100000,
-        0x00100020,0x80000020,0x00000000,0x00108000,
-        0x00008020,0x80108000,0x80100000,0x00008020,
-        0x00000000,0x00108020,0x80100020,0x00100000,
-        0x80008020,0x80100000,0x80108000,0x00008000,
-        0x80100000,0x80008000,0x00000020,0x80108020,
-        0x00108020,0x00000020,0x00008000,0x80000000,
-        0x00008020,0x80108000,0x00100000,0x80000020,
-        0x00100020,0x80008020,0x80000020,0x00100020,
-        0x00108000,0x00000000,0x80008000,0x00008020,
-        0x80000000,0x80100020,0x80108020,0x00108000},
-    {   0x00000208,0x08020200,0x00000000,0x08020008,
-        0x08000200,0x00000000,0x00020208,0x08000200,
-        0x00020008,0x08000008,0x08000008,0x00020000,
-        0x08020208,0x00020008,0x08020000,0x00000208,
-        0x08000000,0x00000008,0x08020200,0x00000200,
-        0x00020200,0x08020000,0x08020008,0x00020208,
-        0x08000208,0x00020200,0x00020000,0x08000208,
-        0x00000008,0x08020208,0x00000200,0x08000000,
-        0x08020200,0x08000000,0x00020008,0x00000208,
-        0x00020000,0x08020200,0x08000200,0x00000000,
-        0x00000200,0x00020008,0x08020208,0x08000200,
-        0x08000008,0x00000200,0x00000000,0x08020008,
-        0x08000208,0x00020000,0x08000000,0x08020208,
-        0x00000008,0x00020208,0x00020200,0x08000008,
-        0x08020000,0x08000208,0x00000208,0x08020000,
-        0x00020208,0x00000008,0x08020008,0x00020200},
-    {   0x00802001,0x00002081,0x00002081,0x00000080,
-        0x00802080,0x00800081,0x00800001,0x00002001,
-        0x00000000,0x00802000,0x00802000,0x00802081,
-        0x00000081,0x00000000,0x00800080,0x00800001,
-        0x00000001,0x00002000,0x00800000,0x00802001,
-        0x00000080,0x00800000,0x00002001,0x00002080,
-        0x00800081,0x00000001,0x00002080,0x00800080,
-        0x00002000,0x00802080,0x00802081,0x00000081,
-        0x00800080,0x00800001,0x00802000,0x00802081,
-        0x00000081,0x00000000,0x00000000,0x00802000,
-        0x00002080,0x00800080,0x00800081,0x00000001,
-        0x00802001,0x00002081,0x00002081,0x00000080,
-        0x00802081,0x00000081,0x00000001,0x00002000,
-        0x00800001,0x00002001,0x00802080,0x00800081,
-        0x00002001,0x00002080,0x00800000,0x00802001,
-        0x00000080,0x00800000,0x00002000,0x00802080},
-    {   0x00000100,0x02080100,0x02080000,0x42000100,
-        0x00080000,0x00000100,0x40000000,0x02080000,
-        0x40080100,0x00080000,0x02000100,0x40080100,
-        0x42000100,0x42080000,0x00080100,0x40000000,
-        0x02000000,0x40080000,0x40080000,0x00000000,
-        0x40000100,0x42080100,0x42080100,0x02000100,
-        0x42080000,0x40000100,0x00000000,0x42000000,
-        0x02080100,0x02000000,0x42000000,0x00080100,
-        0x00080000,0x42000100,0x00000100,0x02000000,
-        0x40000000,0x02080000,0x42000100,0x40080100,
-        0x02000100,0x40000000,0x42080000,0x02080100,
-        0x40080100,0x00000100,0x02000000,0x42080000,
-        0x42080100,0x00080100,0x42000000,0x42080100,
-        0x02080000,0x00000000,0x40080000,0x42000000,
-        0x00080100,0x02000100,0x40000100,0x00080000,
-        0x00000000,0x40080000,0x02080100,0x40000100},
-    {   0x20000010,0x20400000,0x00004000,0x20404010,
-        0x20400000,0x00000010,0x20404010,0x00400000,
-        0x20004000,0x00404010,0x00400000,0x20000010,
-        0x00400010,0x20004000,0x20000000,0x00004010,
-        0x00000000,0x00400010,0x20004010,0x00004000,
-        0x00404000,0x20004010,0x00000010,0x20400010,
-        0x20400010,0x00000000,0x00404010,0x20404000,
-        0x00004010,0x00404000,0x20404000,0x20000000,
-        0x20004000,0x00000010,0x20400010,0x00404000,
-        0x20404010,0x00400000,0x00004010,0x20000010,
-        0x00400000,0x20004000,0x20000000,0x00004010,
-        0x20000010,0x20404010,0x00404000,0x20400000,
-        0x00404010,0x20404000,0x00000000,0x20400010,
-        0x00000010,0x00004000,0x20400000,0x00404010,
-        0x00004000,0x00400010,0x20004010,0x00000000,
-        0x20404000,0x20000000,0x00400010,0x20004010},
-    {   0x00200000,0x04200002,0x04000802,0x00000000,
-        0x00000800,0x04000802,0x00200802,0x04200800,
-        0x04200802,0x00200000,0x00000000,0x04000002,
-        0x00000002,0x04000000,0x04200002,0x00000802,
-        0x04000800,0x00200802,0x00200002,0x04000800,
-        0x04000002,0x04200000,0x04200800,0x00200002,
-        0x04200000,0x00000800,0x00000802,0x04200802,
-        0x00200800,0x00000002,0x04000000,0x00200800,
-        0x04000000,0x00200800,0x00200000,0x04000802,
-        0x04000802,0x04200002,0x04200002,0x00000002,
-        0x00200002,0x04000000,0x04000800,0x00200000,
-        0x04200800,0x00000802,0x00200802,0x04200800,
-        0x00000802,0x04000002,0x04200802,0x04200000,
-        0x00200800,0x00000000,0x00000002,0x04200802,
-        0x00000000,0x00200802,0x04200000,0x00000800,
-        0x04000002,0x04000800,0x00000800,0x00200002},
-    {   0x10001040,0x00001000,0x00040000,0x10041040,
-        0x10000000,0x10001040,0x00000040,0x10000000,
-        0x00040040,0x10040000,0x10041040,0x00041000,
-        0x10041000,0x00041040,0x00001000,0x00000040,
-        0x10040000,0x10000040,0x10001000,0x00001040,
-        0x00041000,0x00040040,0x10040040,0x10041000,
-        0x00001040,0x00000000,0x00000000,0x10040040,
-        0x10000040,0x10001000,0x00041040,0x00040000,
-        0x00041040,0x00040000,0x10041000,0x00001000,
-        0x00000040,0x10040040,0x00001000,0x00041040,
-        0x10001000,0x00000040,0x10000040,0x10040000,
-        0x10040040,0x10000000,0x00040000,0x10001040,
-        0x00000000,0x10041040,0x00040040,0x10000040,
-        0x10040000,0x10001000,0x10001040,0x00000000,
-        0x10041040,0x00041000,0x00041000,0x00001040,
-        0x00001040,0x00040040,0x10000000,0x10041000}
-    };
-
-    static WC_INLINE void IPERM(word32* left, word32* right)
-    {
-        word32 work;
-
-        *right = rotlFixed(*right, 4U);
-        work = (*left ^ *right) & 0xf0f0f0f0;
-        *left ^= work;
-
-        *right = rotrFixed(*right^work, 20U);
-        work = (*left ^ *right) & 0xffff0000;
-        *left ^= work;
-
-        *right = rotrFixed(*right^work, 18U);
-        work = (*left ^ *right) & 0x33333333;
-        *left ^= work;
-
-        *right = rotrFixed(*right^work, 6U);
-        work = (*left ^ *right) & 0x00ff00ff;
-        *left ^= work;
-
-        *right = rotlFixed(*right^work, 9U);
-        work = (*left ^ *right) & 0xaaaaaaaa;
-        *left = rotlFixed(*left^work, 1U);
-        *right ^= work;
-    }
-
-    static WC_INLINE void FPERM(word32* left, word32* right)
-    {
-        word32 work;
-
-        *right = rotrFixed(*right, 1U);
-        work = (*left ^ *right) & 0xaaaaaaaa;
-        *right ^= work;
-
-        *left = rotrFixed(*left^work, 9U);
-        work = (*left ^ *right) & 0x00ff00ff;
-        *right ^= work;
-
-        *left = rotlFixed(*left^work, 6U);
-        work = (*left ^ *right) & 0x33333333;
-        *right ^= work;
-
-        *left = rotlFixed(*left^work, 18U);
-        work = (*left ^ *right) & 0xffff0000;
-        *right ^= work;
-
-        *left = rotlFixed(*left^work, 20U);
-        work = (*left ^ *right) & 0xf0f0f0f0;
-        *right ^= work;
-
-        *left = rotrFixed(*left^work, 4U);
-    }
-
-    static int DesSetKey(const byte* key, int dir, word32* out)
-    {
-        #define DES_KEY_BUFFER_SIZE (56+56+8)
-    #ifdef WOLFSSL_SMALL_STACK
-        byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-        if (buffer == NULL)
-            return MEMORY_E;
-    #else
-        byte buffer[DES_KEY_BUFFER_SIZE];
-    #endif
-
-        {
-            byte* const  pc1m = buffer;            /* place to modify pc1 into */
-            byte* const  pcr  = pc1m + 56;         /* place to rotate pc1 into */
-            byte* const  ks   = pcr  + 56;
-            register int i, j, l;
-            int          m;
-
-            for (j = 0; j < 56; j++) {             /* convert pc1 to bits of key  */
-                l = pc1[j] - 1;                    /* integer bit location        */
-                m = l & 07;                        /* find bit                    */
-                pc1m[j] = (key[l >> 3] &           /* find which key byte l is in */
-                    bytebit[m])                    /* and which bit of that byte  */
-                    ? 1 : 0;                       /* and store 1-bit result      */
-            }
-
-            for (i = 0; i < 16; i++) {            /* key chunk for each iteration */
-                XMEMSET(ks, 0, 8);                /* Clear key schedule */
-
-                for (j = 0; j < 56; j++)          /* rotate pc1 the right amount  */
-                    pcr[j] =
-                          pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28];
-
-                /* rotate left and right halves independently */
-                for (j = 0; j < 48; j++) {        /* select bits individually     */
-                    if (pcr[pc2[j] - 1]) {        /* check bit that goes to ks[j] */
-                        l= j % 6;                 /* mask it in if it's there     */
-                        ks[j/6] |= bytebit[l] >> 2;
-                    }
-                }
-
-                /* Now convert to odd/even interleaved form for use in F */
-                out[2*i] = ((word32) ks[0] << 24)
-                         | ((word32) ks[2] << 16)
-                         | ((word32) ks[4] << 8)
-                         | ((word32) ks[6]);
-
-                out[2*i + 1] = ((word32) ks[1] << 24)
-                             | ((word32) ks[3] << 16)
-                             | ((word32) ks[5] << 8)
-                             | ((word32) ks[7]);
-            }
-
-            /* reverse key schedule order */
-            if (dir == DES_DECRYPTION) {
-                for (i = 0; i < 16; i += 2) {
-                    word32 swap = out[i];
-                    out[i] = out[DES_KS_SIZE - 2 - i];
-                    out[DES_KS_SIZE - 2 - i] = swap;
-
-                    swap = out[i + 1];
-                    out[i + 1] = out[DES_KS_SIZE - 1 - i];
-                    out[DES_KS_SIZE - 1 - i] = swap;
-                }
-            }
-
-    #ifdef WOLFSSL_SMALL_STACK
-            XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        }
-
-        return 0;
-    }
-
-    int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
-    {
-        wc_Des_SetIV(des, iv);
-
-        return DesSetKey(key, dir, des->key);
-    }
-
-    int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
-    {
-        int ret;
-
-        if (des == NULL || key == NULL || dir < 0) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
-        if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) {
-            /* key_raw holds orignal key copy */
-            des->key_raw = key;
-            des->iv_raw = iv;
-
-            /* continue on to set normal key for smaller DES operations */
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]);
-        if (ret != 0)
-            return ret;
-
-        ret = DesSetKey(key + 8, !dir, des->key[1]);
-        if (ret != 0)
-            return ret;
-
-        ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]);
-        if (ret != 0)
-            return ret;
-
-        return wc_Des3_SetIV(des, iv);
-    }
-
-    static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr)
-    {
-        word32 l = *lIn, r = *rIn, i;
-
-        for (i=0; i<8; i++)
-        {
-            word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
-            l ^= Spbox[6][(work) & 0x3f]
-              ^  Spbox[4][(work >> 8) & 0x3f]
-              ^  Spbox[2][(work >> 16) & 0x3f]
-              ^  Spbox[0][(work >> 24) & 0x3f];
-            work = r ^ kptr[4*i+1];
-            l ^= Spbox[7][(work) & 0x3f]
-              ^  Spbox[5][(work >> 8) & 0x3f]
-              ^  Spbox[3][(work >> 16) & 0x3f]
-              ^  Spbox[1][(work >> 24) & 0x3f];
-
-            work = rotrFixed(l, 4U) ^ kptr[4*i+2];
-            r ^= Spbox[6][(work) & 0x3f]
-              ^  Spbox[4][(work >> 8) & 0x3f]
-              ^  Spbox[2][(work >> 16) & 0x3f]
-              ^  Spbox[0][(work >> 24) & 0x3f];
-            work = l ^ kptr[4*i+3];
-            r ^= Spbox[7][(work) & 0x3f]
-              ^  Spbox[5][(work >> 8) & 0x3f]
-              ^  Spbox[3][(work >> 16) & 0x3f]
-              ^  Spbox[1][(work >> 24) & 0x3f];
-        }
-
-        *lIn = l; *rIn = r;
-    }
-
-    static void DesProcessBlock(Des* des, const byte* in, byte* out)
-    {
-        word32 l, r;
-
-        XMEMCPY(&l, in, sizeof(l));
-        XMEMCPY(&r, in + sizeof(l), sizeof(r));
-        #ifdef LITTLE_ENDIAN_ORDER
-            l = ByteReverseWord32(l);
-            r = ByteReverseWord32(r);
-        #endif
-        IPERM(&l,&r);
-
-        DesRawProcessBlock(&l, &r, des->key);
-
-        FPERM(&l,&r);
-        #ifdef LITTLE_ENDIAN_ORDER
-            l = ByteReverseWord32(l);
-            r = ByteReverseWord32(r);
-        #endif
-        XMEMCPY(out, &r, sizeof(r));
-        XMEMCPY(out + sizeof(r), &l, sizeof(l));
-    }
-
-    static void Des3ProcessBlock(Des3* des, const byte* in, byte* out)
-    {
-        word32 l, r;
-
-        XMEMCPY(&l, in, sizeof(l));
-        XMEMCPY(&r, in + sizeof(l), sizeof(r));
-        #ifdef LITTLE_ENDIAN_ORDER
-            l = ByteReverseWord32(l);
-            r = ByteReverseWord32(r);
-        #endif
-        IPERM(&l,&r);
-
-        DesRawProcessBlock(&l, &r, des->key[0]);
-        DesRawProcessBlock(&r, &l, des->key[1]);
-        DesRawProcessBlock(&l, &r, des->key[2]);
-
-        FPERM(&l,&r);
-        #ifdef LITTLE_ENDIAN_ORDER
-            l = ByteReverseWord32(l);
-            r = ByteReverseWord32(r);
-        #endif
-        XMEMCPY(out, &r, sizeof(r));
-        XMEMCPY(out + sizeof(r), &l, sizeof(l));
-    }
-
-    int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        while (blocks--) {
-            xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
-            DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
-            XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
-
-            out += DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-        }
-        return 0;
-    }
-
-    int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks = sz / DES_BLOCK_SIZE;
-
-        while (blocks--) {
-            XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
-            DesProcessBlock(des, (byte*)des->tmp, out);
-            xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
-            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
-
-            out += DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-        }
-        return 0;
-    }
-
-    int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks;
-
-        if (des == NULL || out == NULL || in == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
-        if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES &&
-                                            sz >= WC_ASYNC_THRESH_DES3_CBC) {
-        #if defined(HAVE_CAVIUM)
-            return NitroxDes3CbcEncrypt(des, out, in, sz);
-        #elif defined(HAVE_INTEL_QA)
-            return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz,
-                des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN);
-        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-            if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_ENCRYPT)) {
-                WC_ASYNC_TEST* testDev = &des->asyncDev.test;
-                testDev->des.des = des;
-                testDev->des.out = out;
-                testDev->des.in = in;
-                testDev->des.sz = sz;
-                return WC_PENDING_E;
-            }
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        blocks = sz / DES_BLOCK_SIZE;
-        while (blocks--) {
-            xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
-            Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
-            XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
-
-            out += DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-        }
-        return 0;
-    }
-
-
-    int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
-    {
-        word32 blocks;
-
-        if (des == NULL || out == NULL || in == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT)
-        if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES &&
-                                            sz >= WC_ASYNC_THRESH_DES3_CBC) {
-        #if defined(HAVE_CAVIUM)
-            return NitroxDes3CbcDecrypt(des, out, in, sz);
-        #elif defined(HAVE_INTEL_QA)
-            return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz,
-                des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN);
-        #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-            if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_DECRYPT)) {
-                WC_ASYNC_TEST* testDev = &des->asyncDev.test;
-                testDev->des.des = des;
-                testDev->des.out = out;
-                testDev->des.in = in;
-                testDev->des.sz = sz;
-                return WC_PENDING_E;
-            }
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        blocks = sz / DES_BLOCK_SIZE;
-        while (blocks--) {
-            XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
-            Des3ProcessBlock(des, (byte*)des->tmp, out);
-            xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
-            XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
-
-            out += DES_BLOCK_SIZE;
-            in  += DES_BLOCK_SIZE;
-        }
-        return 0;
-    }
-
-    #ifdef WOLFSSL_DES_ECB
-        /* One block, compatibility only */
-        int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
-        {
-            word32 blocks = sz / DES_BLOCK_SIZE;
-
-            if (des == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            while (blocks--) {
-                DesProcessBlock(des, in, out);
-
-                out += DES_BLOCK_SIZE;
-                in  += DES_BLOCK_SIZE;
-            }
-            return 0;
-        }
-
-        int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
-        {
-            word32 blocks = sz / DES_BLOCK_SIZE;
-
-            if (des == NULL || out == NULL || in == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            while (blocks--) {
-                Des3ProcessBlock(des, in, out);
-
-                out += DES_BLOCK_SIZE;
-                in  += DES_BLOCK_SIZE;
-            }
-            return 0;
-        }
-    #endif /* WOLFSSL_DES_ECB */
-
-#endif /* NEED_SOFT_DES */
-
-
-void wc_Des_SetIV(Des* des, const byte* iv)
-{
-    if (des && iv)
-        XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
-    else if (des)
-        XMEMSET(des->reg,  0, DES_BLOCK_SIZE);
-}
-
-int wc_Des3_SetIV(Des3* des, const byte* iv)
-{
-    if (des == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    if (des && iv)
-        XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
-    else if (des)
-        XMEMSET(des->reg,  0, DES_BLOCK_SIZE);
-
-    return 0;
-}
-
-
-/* Initialize Des3 for use with async device */
-int wc_Des3Init(Des3* des3, void* heap, int devId)
-{
-    int ret = 0;
-    if (des3 == NULL)
-        return BAD_FUNC_ARG;
-
-    des3->heap = heap;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
-    ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES,
-                                                        des3->heap, devId);
-#else
-    (void)devId;
-#endif
-
-    return ret;
-}
-
-/* Free Des3 from use with async device */
-void wc_Des3Free(Des3* des3)
-{
-    if (des3 == NULL)
-        return;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)
-    wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-#endif /* WOLFSSL_TI_CRYPT */
-#endif /* HAVE_FIPS */
-#endif /* NO_DES3 */
-
--- a/wolfcrypt/src/dh.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2252 +0,0 @@
-/* dh.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_DH
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$m")
-        #pragma const_seg(".fipsB$m")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/dh.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef WOLFSSL_HAVE_SP_DH
-#include <wolfssl/wolfcrypt/sp.h>
-#endif
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST)
-    #include <math.h>
-    #define XPOW(x,y) pow((x),(y))
-    #define XLOG(x)   log((x))
-#else
-    /* user's own math lib */
-#endif
-
-#ifdef HAVE_FFDHE_2048
-static const byte dh_ffdhe2048_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-static const byte dh_ffdhe2048_g[] = { 0x02 };
-#ifdef HAVE_FFDHE_Q
-static const byte dh_ffdhe2048_q[] = {
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
-    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
-    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
-    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
-    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
-    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
-    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
-    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
-    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
-    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
-    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
-    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
-    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
-    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
-    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
-    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
-    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
-    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
-    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
-    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
-    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
-    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
-    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
-    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
-    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
-    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
-    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
-    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
-    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
-    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x94, 0x2E, 0x4B,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-#endif /* HAVE_FFDHE_Q */
-
-const DhParams* wc_Dh_ffdhe2048_Get(void)
-{
-    static const DhParams ffdhe2048 = {
-        #ifdef HAVE_FFDHE_Q
-            dh_ffdhe2048_q, sizeof(dh_ffdhe2048_q),
-        #endif /* HAVE_FFDHE_Q */
-        dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p),
-        dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g)
-    };
-    return &ffdhe2048;
-}
-#endif
-
-#ifdef HAVE_FFDHE_3072
-static const byte dh_ffdhe3072_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-static const byte dh_ffdhe3072_g[] = { 0x02 };
-#ifdef HAVE_FFDHE_Q
-static const byte dh_ffdhe3072_q[] = {
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
-    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
-    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
-    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
-    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
-    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
-    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
-    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
-    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
-    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
-    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
-    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
-    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
-    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
-    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
-    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
-    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
-    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
-    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
-    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
-    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
-    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
-    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
-    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
-    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
-    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
-    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
-    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
-    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
-    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
-    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
-    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
-    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
-    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
-    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
-    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
-    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
-    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
-    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
-    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
-    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
-    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
-    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
-    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
-    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
-    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x63, 0x17, 0x1B,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-#endif /* HAVE_FFDHE_Q */
-
-const DhParams* wc_Dh_ffdhe3072_Get(void)
-{
-    static const DhParams ffdhe3072 = {
-        #ifdef HAVE_FFDHE_Q
-            dh_ffdhe3072_q, sizeof(dh_ffdhe3072_q),
-        #endif /* HAVE_FFDHE_Q */
-        dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p),
-        dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g)
-    };
-    return &ffdhe3072;
-}
-#endif
-
-#ifdef HAVE_FFDHE_4096
-static const byte dh_ffdhe4096_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-static const byte dh_ffdhe4096_g[] = { 0x02 };
-#ifdef HAVE_FFDHE_Q
-static const byte dh_ffdhe4096_q[] = {
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
-    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
-    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
-    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
-    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
-    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
-    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
-    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
-    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
-    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
-    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
-    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
-    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
-    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
-    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
-    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
-    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
-    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
-    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
-    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
-    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
-    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
-    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
-    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
-    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
-    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
-    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
-    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
-    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
-    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
-    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
-    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
-    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
-    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
-    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
-    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
-    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
-    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
-    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
-    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
-    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
-    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
-    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
-    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
-    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
-    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
-    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
-    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
-    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
-    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
-    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
-    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
-    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
-    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
-    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
-    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
-    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
-    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
-    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
-    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
-    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
-    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x32, 0xAF, 0xB5,
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-#endif /* HAVE_FFDHE_Q */
-
-const DhParams* wc_Dh_ffdhe4096_Get(void)
-{
-    static const DhParams ffdhe4096 = {
-        #ifdef HAVE_FFDHE_Q
-            dh_ffdhe4096_q, sizeof(dh_ffdhe4096_q),
-        #endif /* HAVE_FFDHE_Q */
-        dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p),
-        dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g)
-    };
-    return &ffdhe4096;
-}
-#endif
-
-#ifdef HAVE_FFDHE_6144
-static const byte dh_ffdhe6144_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
-    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
-    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
-    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
-    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
-    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
-    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
-    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
-    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
-    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
-    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
-    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
-    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
-    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
-    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
-    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
-    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
-    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
-    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
-    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
-    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
-    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
-    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
-    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
-    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
-    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
-    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
-    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
-    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
-    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
-    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
-    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
-    0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-static const byte dh_ffdhe6144_g[] = { 0x02 };
-#ifdef HAVE_FFDHE_Q
-static const byte dh_ffdhe6144_q[] = {
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
-    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
-    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
-    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
-    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
-    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
-    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
-    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
-    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
-    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
-    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
-    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
-    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
-    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
-    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
-    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
-    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
-    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
-    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
-    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
-    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
-    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
-    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
-    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
-    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
-    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
-    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
-    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
-    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
-    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
-    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
-    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
-    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
-    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
-    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
-    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
-    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
-    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
-    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
-    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
-    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
-    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
-    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
-    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
-    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
-    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
-    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
-    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
-    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
-    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
-    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
-    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
-    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
-    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
-    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
-    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
-    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
-    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
-    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
-    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
-    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
-    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81,
-    0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D,
-    0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D,
-    0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53,
-    0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64,
-    0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6,
-    0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D,
-    0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38,
-    0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F,
-    0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B,
-    0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88,
-    0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C,
-    0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1,
-    0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37,
-    0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1,
-    0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA,
-    0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0,
-    0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9,
-    0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB,
-    0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41,
-    0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F,
-    0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6,
-    0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF,
-    0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23,
-    0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5,
-    0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B,
-    0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01,
-    0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82,
-    0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B,
-    0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34,
-    0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0,
-    0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A,
-    0x52, 0x07, 0x19, 0x4E, 0x68, 0x72, 0x07, 0x32,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-#endif /* HAVE_FFDHE_Q */
-
-const DhParams* wc_Dh_ffdhe6144_Get(void)
-{
-    static const DhParams ffdhe6144 = {
-        #ifdef HAVE_FFDHE_Q
-            dh_ffdhe6144_q, sizeof(dh_ffdhe6144_q),
-        #endif /* HAVE_FFDHE_Q */
-        dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p),
-        dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g)
-    };
-    return &ffdhe6144;
-}
-#endif
-
-#ifdef HAVE_FFDHE_8192
-static const byte dh_ffdhe8192_p[] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A,
-    0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
-    0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95,
-    0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB,
-    0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
-    0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8,
-    0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A,
-    0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
-    0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0,
-    0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3,
-    0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
-    0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77,
-    0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72,
-    0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
-    0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A,
-    0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61,
-    0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
-    0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68,
-    0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4,
-    0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
-    0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70,
-    0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC,
-    0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
-    0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF,
-    0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83,
-    0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
-    0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05,
-    0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2,
-    0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
-    0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC,
-    0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B,
-    0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
-    0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07,
-    0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE,
-    0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
-    0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70,
-    0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44,
-    0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
-    0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF,
-    0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E,
-    0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
-    0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA,
-    0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E,
-    0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
-    0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C,
-    0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1,
-    0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
-    0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6,
-    0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18,
-    0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
-    0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A,
-    0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A,
-    0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
-    0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4,
-    0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38,
-    0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
-    0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C,
-    0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC,
-    0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
-    0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B,
-    0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1,
-    0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
-    0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A,
-    0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A,
-    0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
-    0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8,
-    0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C,
-    0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
-    0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71,
-    0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F,
-    0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
-    0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10,
-    0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8,
-    0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
-    0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E,
-    0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3,
-    0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
-    0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1,
-    0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92,
-    0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
-    0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82,
-    0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE,
-    0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
-    0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E,
-    0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46,
-    0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
-    0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17,
-    0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03,
-    0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
-    0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6,
-    0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69,
-    0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
-    0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4,
-    0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA,
-    0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38,
-    0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64,
-    0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43,
-    0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E,
-    0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF,
-    0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29,
-    0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65,
-    0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02,
-    0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4,
-    0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82,
-    0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C,
-    0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51,
-    0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22,
-    0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74,
-    0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE,
-    0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C,
-    0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC,
-    0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B,
-    0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9,
-    0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0,
-    0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31,
-    0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57,
-    0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8,
-    0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E,
-    0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30,
-    0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E,
-    0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE,
-    0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D,
-    0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D,
-    0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E,
-    0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C,
-    0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-static const byte dh_ffdhe8192_g[] = { 0x02 };
-#ifdef HAVE_FFDHE_Q
-static const byte dh_ffdhe8192_g[] = {
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D,
-    0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78,
-    0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A,
-    0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD,
-    0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C,
-    0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC,
-    0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD,
-    0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0,
-    0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68,
-    0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79,
-    0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A,
-    0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB,
-    0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39,
-    0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A,
-    0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD,
-    0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0,
-    0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD,
-    0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34,
-    0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA,
-    0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C,
-    0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8,
-    0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76,
-    0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0,
-    0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF,
-    0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1,
-    0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9,
-    0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02,
-    0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9,
-    0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD,
-    0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE,
-    0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD,
-    0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C,
-    0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83,
-    0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7,
-    0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E,
-    0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38,
-    0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2,
-    0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9,
-    0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF,
-    0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F,
-    0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06,
-    0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D,
-    0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27,
-    0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7,
-    0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE,
-    0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78,
-    0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D,
-    0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB,
-    0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C,
-    0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02,
-    0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D,
-    0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5,
-    0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19,
-    0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62,
-    0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C,
-    0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD,
-    0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E,
-    0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66,
-    0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7,
-    0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35,
-    0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70,
-    0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81,
-    0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D,
-    0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D,
-    0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53,
-    0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64,
-    0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6,
-    0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D,
-    0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38,
-    0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F,
-    0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B,
-    0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88,
-    0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C,
-    0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1,
-    0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37,
-    0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1,
-    0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA,
-    0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0,
-    0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9,
-    0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB,
-    0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41,
-    0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F,
-    0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6,
-    0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF,
-    0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23,
-    0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5,
-    0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B,
-    0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01,
-    0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82,
-    0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B,
-    0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34,
-    0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0,
-    0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A,
-    0x52, 0x07, 0x19, 0x4E, 0x67, 0xFA, 0x35, 0x55,
-    0x1B, 0x56, 0x80, 0x26, 0x7B, 0x00, 0x64, 0x1C,
-    0x0F, 0x21, 0x2D, 0x18, 0xEC, 0xA8, 0xD7, 0x32,
-    0x7E, 0xD9, 0x1F, 0xE7, 0x64, 0xA8, 0x4E, 0xA1,
-    0xB4, 0x3F, 0xF5, 0xB4, 0xF6, 0xE8, 0xE6, 0x2F,
-    0x05, 0xC6, 0x61, 0xDE, 0xFB, 0x25, 0x88, 0x77,
-    0xC3, 0x5B, 0x18, 0xA1, 0x51, 0xD5, 0xC4, 0x14,
-    0xAA, 0xAD, 0x97, 0xBA, 0x3E, 0x49, 0x93, 0x32,
-    0xE5, 0x96, 0x07, 0x8E, 0x60, 0x0D, 0xEB, 0x81,
-    0x14, 0x9C, 0x44, 0x1C, 0xE9, 0x57, 0x82, 0xF2,
-    0x2A, 0x28, 0x25, 0x63, 0xC5, 0xBA, 0xC1, 0x41,
-    0x14, 0x23, 0x60, 0x5D, 0x1A, 0xE1, 0xAF, 0xAE,
-    0x2C, 0x8B, 0x06, 0x60, 0x23, 0x7E, 0xC1, 0x28,
-    0xAA, 0x0F, 0xE3, 0x46, 0x4E, 0x43, 0x58, 0x11,
-    0x5D, 0xB8, 0x4C, 0xC3, 0xB5, 0x23, 0x07, 0x3A,
-    0x28, 0xD4, 0x54, 0x98, 0x84, 0xB8, 0x1F, 0xF7,
-    0x0E, 0x10, 0xBF, 0x36, 0x1C, 0x13, 0x72, 0x96,
-    0x28, 0xD5, 0x34, 0x8F, 0x07, 0x21, 0x1E, 0x7E,
-    0x4C, 0xF4, 0xF1, 0x8B, 0x28, 0x60, 0x90, 0xBD,
-    0xB1, 0x24, 0x0B, 0x66, 0xD6, 0xCD, 0x4A, 0xFC,
-    0xEA, 0xDC, 0x00, 0xCA, 0x44, 0x6C, 0xE0, 0x50,
-    0x50, 0xFF, 0x18, 0x3A, 0xD2, 0xBB, 0xF1, 0x18,
-    0xC1, 0xFC, 0x0E, 0xA5, 0x1F, 0x97, 0xD2, 0x2B,
-    0x8F, 0x7E, 0x46, 0x70, 0x5D, 0x45, 0x27, 0xF4,
-    0x5B, 0x42, 0xAE, 0xFF, 0x39, 0x58, 0x53, 0x37,
-    0x6F, 0x69, 0x7D, 0xD5, 0xFD, 0xF2, 0xC5, 0x18,
-    0x7D, 0x7D, 0x5F, 0x0E, 0x2E, 0xB8, 0xD4, 0x3F,
-    0x17, 0xBA, 0x0F, 0x7C, 0x60, 0xFF, 0x43, 0x7F,
-    0x53, 0x5D, 0xFE, 0xF2, 0x98, 0x33, 0xBF, 0x86,
-    0xCB, 0xE8, 0x8E, 0xA4, 0xFB, 0xD4, 0x22, 0x1E,
-    0x84, 0x11, 0x72, 0x83, 0x54, 0xFA, 0x30, 0xA7,
-    0x00, 0x8F, 0x15, 0x4A, 0x41, 0xC7, 0xFC, 0x46,
-    0x6B, 0x46, 0x45, 0xDB, 0xE2, 0xE3, 0x21, 0x26,
-    0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-#endif /* HAVE_FFDHE_Q */
-
-const DhParams* wc_Dh_ffdhe8192_Get(void)
-{
-    static const DhParams ffdhe8192 = {
-        #ifdef HAVE_FFDHE_Q
-            dh_ffdhe8192_q, sizeof(dh_ffdhe8192_q),
-        #endif /* HAVE_FFDHE_Q */
-        dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p),
-        dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g)
-    };
-    return &ffdhe8192;
-}
-#endif
-
-int wc_InitDhKey_ex(DhKey* key, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    key->heap = heap; /* for XMALLOC/XFREE in future */
-
-    if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY)
-        return MEMORY_E;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-    /* handle as async */
-    ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH,
-        key->heap, devId);
-#else
-    (void)devId;
-#endif
-
-    return ret;
-}
-
-int wc_InitDhKey(DhKey* key)
-{
-    return wc_InitDhKey_ex(key, NULL, INVALID_DEVID);
-}
-
-
-int wc_FreeDhKey(DhKey* key)
-{
-    if (key) {
-        mp_clear(&key->p);
-        mp_clear(&key->g);
-        mp_clear(&key->q);
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-        wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH);
-    #endif
-    }
-    return 0;
-}
-
-
-/* if defined to not use floating point values do not compile in */
-#ifndef WOLFSSL_DH_CONST
-    static word32 DiscreteLogWorkFactor(word32 n)
-    {
-        /* assuming discrete log takes about the same time as factoring */
-        if (n < 5)
-            return 0;
-        else
-            return (word32)(2.4 * XPOW((double)n, 1.0/3.0) *
-                    XPOW(XLOG((double)n), 2.0/3.0) - 5);
-    }
-#endif /* WOLFSSL_DH_CONST*/
-
-
-/* if not using fixed points use DiscreteLogWorkFactor function for unsual size
-   otherwise round up on size needed */
-#ifndef WOLFSSL_DH_CONST
-    #define WOLFSSL_DH_ROUND(x)
-#else
-    #define WOLFSSL_DH_ROUND(x) \
-        do {                    \
-            if (x % 128) {      \
-                x &= 0xffffff80;\
-                x += 128;       \
-            }                   \
-        }                       \
-        while (0)
-#endif
-
-
-#ifndef WOLFSSL_NO_DH186
-/* validate that (L,N) match allowed sizes from SP 800-56A, Section 5.5.1.1.
- * modLen - represents L, the size of p in bits
- * divLen - represents N, the size of q in bits
- * return 0 on success, -1 on error */
-static int CheckDhLN(int modLen, int divLen)
-{
-    int ret = -1;
-
-    switch (modLen) {
-        /* FA */
-        case 1024:
-            if (divLen == 160)
-                ret = 0;
-            break;
-        /* FB, FC */
-        case 2048:
-            if (divLen == 224 || divLen == 256)
-                ret = 0;
-            break;
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-
-/* Create DH private key
- *
- * Based on NIST FIPS 186-4,
- * "B.1.1 Key Pair Generation Using Extra Random Bits"
- *
- * dh     - pointer to initialized DhKey structure, needs to have dh->q
- * rng    - pointer to initialized WC_RNG structure
- * priv   - output location for generated private key
- * privSz - IN/OUT, size of priv buffer, size of generated private key
- *
- * return 0 on success, negative on error */
-static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv,
-                                word32* privSz)
-{
-    byte* cBuf;
-    int qSz, pSz, cSz, err;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* tmpQ = NULL;
-    mp_int* tmpX = NULL;
-#else
-    mp_int tmpQ[1], tmpX[1];
-#endif
-
-    /* Parameters validated in calling functions. */
-
-    if (mp_iszero(&key->q) == MP_YES) {
-        WOLFSSL_MSG("DH q parameter needed for FIPS 186-4 key generation");
-        return BAD_FUNC_ARG;
-    }
-
-    qSz = mp_unsigned_bin_size(&key->q);
-    pSz = mp_unsigned_bin_size(&key->p);
-
-    /* verify (L,N) pair bit lengths */
-    if (CheckDhLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) {
-        WOLFSSL_MSG("DH param sizes do not match SP 800-56A requirements");
-        return BAD_FUNC_ARG;
-    }
-
-    /* generate extra 64 bits so that bias from mod function is negligible */
-    cSz = qSz + (64 / WOLFSSL_BIT_SIZE);
-    cBuf = (byte*)XMALLOC(cSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cBuf == NULL) {
-        return MEMORY_E;
-    }
-#ifdef WOLFSSL_SMALL_STACK
-    tmpQ = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (tmpQ == NULL) {
-        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-    tmpX = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (tmpX == NULL) {
-        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-
-
-    if ((err = mp_init_multi(tmpX, tmpQ, NULL, NULL, NULL, NULL))
-                   != MP_OKAY) {
-        XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
-#endif
-        return err;
-    }
-
-    do {
-        /* generate N+64 bits (c) from RBG into tmpX, making sure positive.
-         * Hash_DRBG uses SHA-256 which matches maximum
-         * requested_security_strength of (L,N) */
-        err = wc_RNG_GenerateBlock(rng, cBuf, cSz);
-        if (err == MP_OKAY)
-            err = mp_read_unsigned_bin(tmpX, cBuf, cSz);
-        if (err != MP_OKAY) {
-            mp_clear(tmpX);
-            mp_clear(tmpQ);
-            XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
-            XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
-#endif
-            return err;
-        }
-    } while (mp_cmp_d(tmpX, 1) != MP_GT);
-
-    ForceZero(cBuf, cSz);
-    XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    /* tmpQ = q - 1 */
-    if (err == MP_OKAY)
-        err = mp_copy(&key->q, tmpQ);
-
-    if (err == MP_OKAY)
-        err = mp_sub_d(tmpQ, 1, tmpQ);
-
-    /* x = c mod (q-1), tmpX holds c */
-    if (err == MP_OKAY)
-        err = mp_mod(tmpX, tmpQ, tmpX);
-
-    /* x = c mod (q-1) + 1 */
-    if (err == MP_OKAY)
-        err = mp_add_d(tmpX, 1, tmpX);
-
-    /* copy tmpX into priv */
-    if (err == MP_OKAY) {
-        pSz = mp_unsigned_bin_size(tmpX);
-        if (pSz > (int)*privSz) {
-            WOLFSSL_MSG("DH private key output buffer too small");
-            err = BAD_FUNC_ARG;
-        } else {
-            *privSz = pSz;
-            err = mp_to_unsigned_bin(tmpX, priv);
-        }
-    }
-
-    mp_forcezero(tmpX);
-    mp_clear(tmpX);
-    mp_clear(tmpQ);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_NO_DH186 */
-
-
-static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv,
-                             word32* privSz)
-{
-    int ret = 0;
-    word32 sz = 0;
-
-#ifndef WOLFSSL_NO_DH186
-    if (mp_iszero(&key->q) == MP_NO) {
-
-        /* q param available, use NIST FIPS 186-4, "B.1.1 Key Pair
-         * Generation Using Extra Random Bits" */
-        ret = GeneratePrivateDh186(key, rng, priv, privSz);
-
-    } else
-#endif
-    {
-
-        sz = mp_unsigned_bin_size(&key->p);
-
-        /* Table of predetermined values from the operation
-           2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /
-           WOLFSSL_BIT_SIZE + 1
-           Sizes in table checked against RFC 3526
-         */
-        WOLFSSL_DH_ROUND(sz); /* if using fixed points only, then round up */
-        switch (sz) {
-            case 128:  sz = 21; break;
-            case 256:  sz = 29; break;
-            case 384:  sz = 34; break;
-            case 512:  sz = 39; break;
-            case 640:  sz = 42; break;
-            case 768:  sz = 46; break;
-            case 896:  sz = 49; break;
-            case 1024: sz = 52; break;
-            default:
-            #ifndef WOLFSSL_DH_CONST
-                /* if using floating points and size of p is not in table */
-                sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) /
-                                           WOLFSSL_BIT_SIZE + 1);
-                break;
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-        }
-
-        ret = wc_RNG_GenerateBlock(rng, priv, sz);
-
-        if (ret == 0) {
-            priv[0] |= 0x0C;
-            *privSz = sz;
-        }
-    }
-
-    return ret;
-}
-
-
-static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz,
-    byte* pub, word32* pubSz)
-{
-    int ret = 0;
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* x = NULL;
-    mp_int* y = NULL;
-#else
-    mp_int x[1];
-    mp_int y[1];
-#endif
-#endif
-
-#ifdef WOLFSSL_HAVE_SP_DH
-#ifndef WOLFSSL_SP_NO_2048
-    if (mp_count_bits(&key->p) == 2048)
-        return sp_DhExp_2048(&key->g, priv, privSz, &key->p, pub, pubSz);
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-    if (mp_count_bits(&key->p) == 3072)
-        return sp_DhExp_3072(&key->g, priv, privSz, &key->p, pub, pubSz);
-#endif
-#endif
-
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (x == NULL)
-        return MEMORY_E;
-    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (y == NULL) {
-        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-    if (mp_init_multi(x, y, 0, 0, 0, 0) != MP_OKAY)
-        return MP_INIT_E;
-
-    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY)
-        ret = MP_READ_E;
-
-    if (ret == 0 && mp_exptmod(&key->g, x, &key->p, y) != MP_OKAY)
-        ret = MP_EXPTMOD_E;
-
-    if (ret == 0 && mp_to_unsigned_bin(y, pub) != MP_OKAY)
-        ret = MP_TO_E;
-
-    if (ret == 0)
-        *pubSz = mp_unsigned_bin_size(y);
-
-    mp_clear(y);
-    mp_clear(x);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-#endif
-#else
-    ret = WC_KEY_SIZE_E;
-#endif
-
-    return ret;
-}
-
-static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng,
-    byte* priv, word32* privSz, byte* pub, word32* pubSz)
-{
-    int ret;
-
-    if (key == NULL || rng == NULL || priv == NULL || privSz == NULL ||
-        pub == NULL || pubSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret = GeneratePrivateDh(key, rng, priv, privSz);
-
-    return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz);
-}
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng,
-    byte* priv, word32* privSz, byte* pub, word32* pubSz)
-{
-    int ret;
-
-#if defined(HAVE_INTEL_QA)
-    word32 sz;
-
-    /* verify prime is at least 768-bits */
-    /* QAT HW must have prime at least 768-bits */
-    sz = mp_unsigned_bin_size(&key->p);
-    if (sz >= (768/8)) {
-        mp_int x;
-
-        ret = mp_init(&x);
-        if (ret != MP_OKAY)
-            return ret;
-
-        ret = GeneratePrivateDh(key, rng, priv, privSz);
-        if (ret == 0)
-            ret = mp_read_unsigned_bin(&x, priv, *privSz);
-        if (ret == MP_OKAY)
-            ret = wc_mp_to_bigint(&x, &x.raw);
-        if (ret == MP_OKAY)
-            ret = wc_mp_to_bigint(&key->p, &key->p.raw);
-        if (ret == MP_OKAY)
-            ret = wc_mp_to_bigint(&key->g, &key->g.raw);
-        if (ret == MP_OKAY)
-            ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw,
-                &x.raw, pub, pubSz);
-        mp_clear(&x);
-
-        return ret;
-    }
-
-#elif defined(HAVE_CAVIUM)
-    /* TODO: Not implemented - use software for now */
-
-#else /* WOLFSSL_ASYNC_CRYPT_TEST */
-    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_GEN)) {
-        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-        testDev->dhGen.key = key;
-        testDev->dhGen.rng = rng;
-        testDev->dhGen.priv = priv;
-        testDev->dhGen.privSz = privSz;
-        testDev->dhGen.pub = pub;
-        testDev->dhGen.pubSz = pubSz;
-        return WC_PENDING_E;
-    }
-#endif
-
-    /* otherwise use software DH */
-    ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz);
-
-    return ret;
-}
-#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */
-
-
-/* Check DH Public Key for invalid numbers, optionally allowing
- * the public key to be checked against the large prime (q).
- * Check per process in SP 800-56Ar3, section 5.6.2.3.1.
- *
- * key     DH key group parameters.
- * pub     Public Key.
- * pubSz   Public Key size.
- * prime   Large prime (q), optionally NULL to skip check
- * primeSz Size of large prime
- *
- *  returns 0 on success or error code
- */
-int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
-                        const byte* prime, word32 primeSz)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* y = NULL;
-    mp_int* p = NULL;
-    mp_int* q = NULL;
-#else
-    mp_int y[1];
-    mp_int p[1];
-    mp_int q[1];
-#endif
-
-    if (key == NULL || pub == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (y == NULL)
-        return MEMORY_E;
-    p = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (p == NULL) {
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-    q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (q == NULL) {
-        XFREE(p, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-
-    if (mp_init_multi(y, p, q, NULL, NULL, NULL) != MP_OKAY) {
-        return MP_INIT_E;
-    }
-
-    if (mp_read_unsigned_bin(y, pub, pubSz) != MP_OKAY) {
-        ret = MP_READ_E;
-    }
-
-    if (ret == 0 && prime != NULL) {
-        if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY)
-            ret = MP_READ_E;
-
-    } else if (mp_iszero(&key->q) == MP_NO) {
-        /* use q available in DhKey */
-        if (mp_copy(&key->q, q) != MP_OKAY)
-            ret = MP_INIT_E;
-    }
-
-    /* SP 800-56Ar3, section 5.6.2.3.1, process step 1 */
-    /* pub (y) should not be 0 or 1 */
-    if (ret == 0 && mp_cmp_d(y, 2) == MP_LT) {
-        ret = MP_CMP_E;
-    }
-
-    /* pub (y) shouldn't be greater than or equal to p - 1 */
-    if (ret == 0 && mp_copy(&key->p, p) != MP_OKAY) {
-        ret = MP_INIT_E;
-    }
-    if (ret == 0 && mp_sub_d(p, 2, p) != MP_OKAY) {
-        ret = MP_SUB_E;
-    }
-    if (ret == 0 && mp_cmp(y, p) == MP_GT) {
-        ret = MP_CMP_E;
-    }
-
-    if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) {
-
-        /* restore key->p into p */
-        if (mp_copy(&key->p, p) != MP_OKAY)
-            ret = MP_INIT_E;
-    }
-
-    if (ret == 0 && prime != NULL) {
-#ifdef WOLFSSL_HAVE_SP_DH
-#ifndef WOLFSSL_SP_NO_2048
-        if (mp_count_bits(&key->p) == 2048) {
-            ret = sp_ModExp_2048(y, q, p, y);
-            if (ret != 0)
-                ret = MP_EXPTMOD_E;
-        }
-        else
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-        if (mp_count_bits(&key->p) == 3072) {
-            ret = sp_ModExp_3072(y, q, p, y);
-            if (ret != 0)
-                ret = MP_EXPTMOD_E;
-        }
-        else
-#endif
-#endif
-
-        {
-    /* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */
-#ifndef WOLFSSL_SP_MATH
-            /* calculate (y^q) mod(p), store back into y */
-            if (ret == 0 && mp_exptmod(y, q, p, y) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-#else
-            ret = WC_KEY_SIZE_E;
-#endif
-        }
-
-        /* verify above == 1 */
-        if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ)
-            ret = MP_CMP_E;
-    }
-
-    mp_clear(y);
-    mp_clear(p);
-    mp_clear(q);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(q, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(p, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-#endif
-
-    return ret;
-}
-
-
-/* Check DH Public Key for invalid numbers
- *
- * key   DH key group parameters.
- * pub   Public Key.
- * pubSz Public Key size.
- *
- *  returns 0 on success or error code
- */
-int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz)
-{
-    return wc_DhCheckPubKey_ex(key, pub, pubSz, NULL, 0);
-}
-
-
-/* Check DH Private Key for invalid numbers, optionally allowing
- * the private key to be checked against the large prime (q).
- * Check per process in SP 800-56Ar3, section 5.6.2.1.2.
- *
- * key     DH key group parameters.
- * priv    Private Key.
- * privSz  Private Key size.
- * prime   Large prime (q), optionally NULL to skip check
- * primeSz Size of large prime
- *
- *  returns 0 on success or error code
- */
-int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 privSz,
-                         const byte* prime, word32 primeSz)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* x = NULL;
-    mp_int* q = NULL;
-#else
-    mp_int x[1];
-    mp_int q[1];
-#endif
-
-    if (key == NULL || priv == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (x == NULL)
-        return MEMORY_E;
-    q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (q == NULL) {
-        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-
-    if (mp_init_multi(x, q, NULL, NULL, NULL, NULL) != MP_OKAY) {
-        return MP_INIT_E;
-    }
-
-    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) {
-        ret = MP_READ_E;
-    }
-
-    if (ret == 0) {
-        if (prime != NULL) {
-            if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY)
-                ret = MP_READ_E;
-        }
-        else if (mp_iszero(&key->q) == MP_NO) {
-            /* use q available in DhKey */
-            if (mp_copy(&key->q, q) != MP_OKAY)
-                ret = MP_INIT_E;
-        }
-    }
-
-    /* priv (x) should not be 0 */
-    if (ret == 0) {
-        if (mp_cmp_d(x, 0) == MP_EQ)
-            ret = MP_CMP_E;
-    }
-
-    if (ret == 0) {
-        if (mp_iszero(q) == MP_NO) {
-            /* priv (x) shouldn't be greater than q - 1 */
-            if (ret == 0) {
-                if (mp_copy(&key->q, q) != MP_OKAY)
-                    ret = MP_INIT_E;
-            }
-            if (ret == 0) {
-                if (mp_sub_d(q, 1, q) != MP_OKAY)
-                    ret = MP_SUB_E;
-            }
-            if (ret == 0) {
-                if (mp_cmp(x, q) == MP_GT)
-                    ret = DH_CHECK_PRIV_E;
-            }
-        }
-    }
-
-    mp_clear(x);
-    mp_clear(q);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(q, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-#endif
-
-    return ret;
-}
-
-
-/* Check DH Private Key for invalid numbers
- *
- * key    DH key group parameters.
- * priv   Private Key.
- * privSz Private Key size.
- *
- *  returns 0 on success or error code
- */
-int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 privSz)
-{
-    return wc_DhCheckPrivKey_ex(key, priv, privSz, NULL, 0);
-}
-
-
-/* Check DH Keys for pair-wise consistency per process in
- * SP 800-56Ar3, section 5.6.2.1.4, method (b) for FFC.
- *
- * key    DH key group parameters.
- * pub    Public Key.
- * pubSz  Public Key size.
- * priv   Private Key.
- * privSz Private Key size.
- *
- *  returns 0 on success or error code
- */
-int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz,
-                      const byte* priv, word32 privSz)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* publicKey = NULL;
-    mp_int* privateKey = NULL;
-    mp_int* checkKey = NULL;
-#else
-    mp_int publicKey[1];
-    mp_int privateKey[1];
-    mp_int checkKey[1];
-#endif
-    int ret = 0;
-
-    if (key == NULL || pub == NULL || priv == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (publicKey == NULL)
-        return MEMORY_E;
-    privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (privateKey == NULL) {
-        XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-    checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (checkKey == NULL) {
-        XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-
-    if (mp_init_multi(publicKey, privateKey, checkKey,
-                      NULL, NULL, NULL) != MP_OKAY) {
-
-        return MP_INIT_E;
-    }
-
-    /* Load the private and public keys into big integers. */
-    if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY ||
-        mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) {
-
-        ret = MP_READ_E;
-    }
-
-    /* Calculate checkKey = g^privateKey mod p */
-    if (ret == 0) {
-#ifdef WOLFSSL_HAVE_SP_DH
-#ifndef WOLFSSL_SP_NO_2048
-        if (mp_count_bits(&key->p) == 2048) {
-            ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey);
-            if (ret != 0)
-                ret = MP_EXPTMOD_E;
-        }
-        else
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-        if (mp_count_bits(&key->p) == 3072) {
-            ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey);
-            if (ret != 0)
-                ret = MP_EXPTMOD_E;
-        }
-        else
-#endif
-#endif
-        {
-#ifndef WOLFSSL_SP_MATH
-            if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-#else
-            ret = WC_KEY_SIZE_E;
-#endif
-        }
-    }
-
-    /* Compare the calculated public key to the supplied check value. */
-    if (ret == 0) {
-        if (mp_cmp(checkKey, publicKey) != MP_EQ)
-            ret = MP_CMP_E;
-    }
-
-    mp_forcezero(privateKey);
-    mp_clear(privateKey);
-    mp_clear(publicKey);
-    mp_clear(checkKey);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH);
-#endif
-
-    return ret;
-}
-
-
-int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng,
-    byte* priv, word32* privSz, byte* pub, word32* pubSz)
-{
-    int ret;
-
-    if (key == NULL || rng == NULL || priv == NULL || privSz == NULL ||
-                                                pub == NULL || pubSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
-        ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz);
-    }
-    else
-#endif
-    {
-        ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz);
-    }
-
-    return ret;
-}
-
-
-static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
-    const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* y = NULL;
-#ifndef WOLFSSL_SP_MATH
-    mp_int* x = NULL;
-    mp_int* z = NULL;
-#endif
-#else
-    mp_int y[1];
-#ifndef WOLFSSL_SP_MATH
-    mp_int x[1];
-    mp_int z[1];
-#endif
-#endif
-
-#ifdef WOLFSSL_VALIDATE_FFC_IMPORT
-    if (wc_DhCheckPrivKey(key, priv, privSz) != 0) {
-        WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed");
-        return DH_CHECK_PRIV_E;
-    }
-
-    if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
-        WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
-        return DH_CHECK_PUB_E;
-    }
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (y == NULL)
-        return MEMORY_E;
-#ifndef WOLFSSL_SP_MATH
-    x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (x == NULL) {
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-    z = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
-    if (z == NULL) {
-        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-        return MEMORY_E;
-    }
-#endif
-#endif
-
-#ifdef WOLFSSL_HAVE_SP_DH
-#ifndef WOLFSSL_SP_NO_2048
-    if (mp_count_bits(&key->p) == 2048) {
-        if (mp_init(y) != MP_OKAY)
-            return MP_INIT_E;
-
-        if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
-            ret = MP_READ_E;
-
-        if (ret == 0)
-            ret = sp_DhExp_2048(y, priv, privSz, &key->p, agree, agreeSz);
-
-        mp_clear(y);
-    #ifdef WOLFSSL_SMALL_STACK
-    #ifndef WOLFSSL_SP_MATH
-        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-    #endif
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-    #endif
-        return ret;
-    }
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-    if (mp_count_bits(&key->p) == 3072) {
-        if (mp_init(y) != MP_OKAY)
-            return MP_INIT_E;
-
-        if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
-            ret = MP_READ_E;
-
-        if (ret == 0)
-            ret = sp_DhExp_3072(y, priv, privSz, &key->p, agree, agreeSz);
-
-        mp_clear(y);
-    #ifdef WOLFSSL_SMALL_STACK
-    #ifndef WOLFSSL_SP_MATH
-        XFREE(z, key->heap, DYNAMIC_TYPE_DH);
-        XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-    #endif
-        XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-    #endif
-        return ret;
-    }
-#endif
-#endif
-
-#ifndef WOLFSSL_SP_MATH
-    if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY)
-        return MP_INIT_E;
-
-    if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY)
-        ret = MP_READ_E;
-
-    if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
-        ret = MP_READ_E;
-
-    if (ret == 0 && mp_exptmod(y, x, &key->p, z) != MP_OKAY)
-        ret = MP_EXPTMOD_E;
-
-    /* make sure z is not one (SP800-56A, 5.7.1.1) */
-    if (ret == 0 && (mp_cmp_d(z, 1) == MP_EQ))
-        ret = MP_VAL;
-
-    if (ret == 0 && mp_to_unsigned_bin(z, agree) != MP_OKAY)
-        ret = MP_TO_E;
-
-    if (ret == 0)
-        *agreeSz = mp_unsigned_bin_size(z);
-
-    mp_clear(z);
-    mp_clear(y);
-    mp_forcezero(x);
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifndef WOLFSSL_SP_MATH
-    XFREE(z, key->heap, DYNAMIC_TYPE_DH);
-    XFREE(x, key->heap, DYNAMIC_TYPE_DH);
-#endif
-    XFREE(y, key->heap, DYNAMIC_TYPE_DH);
-#endif
-
-    return ret;
-}
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz,
-    const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz)
-{
-    int ret;
-
-#ifdef HAVE_CAVIUM
-    /* TODO: Not implemented - use software for now */
-    ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
-
-#elif defined(HAVE_INTEL_QA)
-    ret = wc_mp_to_bigint(&key->p, &key->p.raw);
-    if (ret == MP_OKAY)
-        ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw,
-            agree, agreeSz, priv, privSz, otherPub, pubSz);
-#else /* WOLFSSL_ASYNC_CRYPT_TEST */
-    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_AGREE)) {
-        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-        testDev->dhAgree.key = key;
-        testDev->dhAgree.agree = agree;
-        testDev->dhAgree.agreeSz = agreeSz;
-        testDev->dhAgree.priv = priv;
-        testDev->dhAgree.privSz = privSz;
-        testDev->dhAgree.otherPub = otherPub;
-        testDev->dhAgree.pubSz = pubSz;
-        return WC_PENDING_E;
-    }
-    ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
-#endif
-
-    return ret;
-}
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
-            word32 privSz, const byte* otherPub, word32 pubSz)
-{
-    int ret = 0;
-
-    if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL ||
-                                                            otherPub == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
-        ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
-    }
-    else
-#endif
-    {
-        ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
-    }
-
-    return ret;
-}
-
-
-int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g,
-                   word32 gSz, const byte* q, word32 qSz)
-{
-    int ret = 0;
-    mp_int* keyP = NULL;
-    mp_int* keyG = NULL;
-    mp_int* keyQ = NULL;
-
-    if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) {
-        ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        /* may have leading 0 */
-        if (p[0] == 0) {
-            pSz--; p++;
-        }
-
-        if (g[0] == 0) {
-            gSz--; g++;
-        }
-
-        if (q != NULL) {
-            if (q[0] == 0) {
-                qSz--; q++;
-            }
-        }
-
-        if (mp_init(&key->p) != MP_OKAY)
-            ret = MP_INIT_E;
-    }
-
-    if (ret == 0) {
-        if (mp_read_unsigned_bin(&key->p, p, pSz) != MP_OKAY)
-            ret = ASN_DH_KEY_E;
-        else
-            keyP = &key->p;
-    }
-    if (ret == 0 && mp_init(&key->g) != MP_OKAY)
-        ret = MP_INIT_E;
-    if (ret == 0) {
-        if (mp_read_unsigned_bin(&key->g, g, gSz) != MP_OKAY)
-            ret = ASN_DH_KEY_E;
-        else
-            keyG = &key->g;
-    }
-
-    if (ret == 0 && q != NULL) {
-        if (mp_init(&key->q) != MP_OKAY)
-            ret = MP_INIT_E;
-    }
-    if (ret == 0 && q != NULL) {
-        if (mp_read_unsigned_bin(&key->q, q, qSz) != MP_OKAY)
-            ret = MP_INIT_E;
-        else
-            keyQ = &key->q;
-    }
-
-    if (ret != 0 && key != NULL) {
-        if (keyQ)
-            mp_clear(keyQ);
-        if (keyG)
-            mp_clear(keyG);
-        if (keyP)
-            mp_clear(keyP);
-    }
-
-    return ret;
-}
-
-
-/* not in asn anymore since no actual asn types used */
-int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
-                word32 gSz)
-{
-    return wc_DhSetKey_ex(key, p, pSz, g, gSz, NULL, 0);
-}
-
-
-#ifdef WOLFSSL_KEY_GEN
-
-/* modulus_size in bits */
-int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh)
-{
-    mp_int  tmp, tmp2;
-    int     groupSz = 0, bufSz = 0,
-            primeCheckCount = 0,
-            primeCheck = MP_NO,
-            ret = 0;
-    unsigned char *buf = NULL;
-
-    if (rng == NULL || dh == NULL)
-        ret = BAD_FUNC_ARG;
-
-    /* set group size in bytes from modulus size
-     * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
-     */
-    if (ret == 0) {
-        switch (modSz) {
-            case 1024:
-                groupSz = 20;
-                break;
-            case 2048:
-            case 3072:
-                groupSz = 32;
-                break;
-            default:
-                ret = BAD_FUNC_ARG;
-                break;
-        }
-    }
-
-    if (ret == 0) {
-        /* modulus size in bytes */
-        modSz /= WOLFSSL_BIT_SIZE;
-        bufSz = modSz - groupSz;
-
-        /* allocate ram */
-        buf = (unsigned char *)XMALLOC(bufSz,
-                                       dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (buf == NULL)
-            ret = MEMORY_E;
-    }
-
-    /* make a random string that will be multplied against q */
-    if (ret == 0)
-        ret = wc_RNG_GenerateBlock(rng, buf, bufSz);
-
-    if (ret == 0) {
-        /* force magnitude */
-        buf[0] |= 0xC0;
-        /* force even */
-        buf[bufSz - 1] &= ~1;
-
-        if (mp_init_multi(&tmp, &tmp2, &dh->p, &dh->q, &dh->g, 0)
-                != MP_OKAY) {
-            ret = MP_INIT_E;
-        }
-    }
-
-    if (ret == 0) {
-        if (mp_read_unsigned_bin(&tmp2, buf, bufSz) != MP_OKAY)
-            ret = MP_READ_E;
-    }
-
-    /* make our prime q */
-    if (ret == 0) {
-        if (mp_rand_prime(&dh->q, groupSz, rng, NULL) != MP_OKAY)
-            ret = PRIME_GEN_E;
-    }
-
-    /* p = random * q */
-    if (ret == 0) {
-        if (mp_mul(&dh->q, &tmp2, &dh->p) != MP_OKAY)
-            ret = MP_MUL_E;
-    }
-
-    /* p = random * q + 1, so q is a prime divisor of p-1 */
-    if (ret == 0) {
-        if (mp_add_d(&dh->p, 1, &dh->p) != MP_OKAY)
-            ret = MP_ADD_E;
-    }
-
-    /* tmp = 2q  */
-    if (ret == 0) {
-        if (mp_add(&dh->q, &dh->q, &tmp) != MP_OKAY)
-            ret = MP_ADD_E;
-    }
-
-    /* loop until p is prime */
-    if (ret == 0) {
-        do {
-            if (mp_prime_is_prime(&dh->p, 8, &primeCheck) != MP_OKAY)
-                ret = PRIME_GEN_E;
-
-            if (primeCheck != MP_YES) {
-                /* p += 2q */
-                if (mp_add(&tmp, &dh->p, &dh->p) != MP_OKAY)
-                    ret = MP_ADD_E;
-                else
-                    primeCheckCount++;
-            }
-        } while (ret == 0 && primeCheck == MP_NO);
-    }
-
-    /* tmp2 += (2*loop_check_prime)
-     * to have p = (q * tmp2) + 1 prime
-     */
-    if (primeCheckCount) {
-        if (mp_add_d(&tmp2, 2 * primeCheckCount, &tmp2) != MP_OKAY)
-            ret = MP_ADD_E;
-    }
-
-    /* find a value g for which g^tmp2 != 1 */
-    if (mp_set(&dh->g, 1) != MP_OKAY)
-        ret = MP_ZERO_E;
-
-    if (ret == 0) {
-        do {
-            if (mp_add_d(&dh->g, 1, &dh->g) != MP_OKAY)
-                ret = MP_ADD_E;
-            else if (mp_exptmod(&dh->g, &tmp2, &dh->p, &tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        } while (ret == 0 && mp_cmp_d(&tmp, 1) == MP_EQ);
-    }
-
-    /* at this point tmp generates a group of order q mod p */
-    mp_exch(&tmp, &dh->g);
-
-    /* clear the parameters if there was an error */
-    if (ret != 0) {
-        mp_clear(&dh->q);
-        mp_clear(&dh->p);
-        mp_clear(&dh->g);
-    }
-
-    ForceZero(buf, bufSz);
-    XFREE(buf, dh->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    mp_clear(&tmp);
-    mp_clear(&tmp2);
-
-    return ret;
-}
-
-
-/* Export raw DH parameters from DhKey structure
- *
- * dh   - pointer to initialized DhKey structure
- * p    - output location for DH (p) parameter
- * pSz  - [IN/OUT] size of output buffer for p, size of p
- * q    - output location for DH (q) parameter
- * qSz  - [IN/OUT] size of output buffer for q, size of q
- * g    - output location for DH (g) parameter
- * gSz  - [IN/OUT] size of output buffer for g, size of g
- *
- * If p, q, and g pointers are all passed in as NULL, the function
- * will set pSz, qSz, and gSz to the required output buffer sizes for p,
- * q, and g. In this case, the function will return LENGTH_ONLY_E.
- *
- * returns 0 on success, negative upon failure
- */
-int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
-                         byte* q, word32* qSz, byte* g, word32* gSz)
-{
-    int ret = 0;
-    word32 pLen = 0, qLen = 0, gLen = 0;
-
-    if (dh == NULL || pSz == NULL || qSz == NULL || gSz == NULL)
-        ret = BAD_FUNC_ARG;
-
-    /* get required output buffer sizes */
-    if (ret == 0) {
-        pLen = mp_unsigned_bin_size(&dh->p);
-        qLen = mp_unsigned_bin_size(&dh->q);
-        gLen = mp_unsigned_bin_size(&dh->g);
-
-        /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
-        if (p == NULL && q == NULL && g == NULL) {
-            *pSz = pLen;
-            *qSz = qLen;
-            *gSz = gLen;
-            ret = LENGTH_ONLY_E;
-        }
-    }
-
-    if (ret == 0) {
-        if (p == NULL || q == NULL || g == NULL)
-            ret = BAD_FUNC_ARG;
-    }
-
-    /* export p */
-    if (ret == 0) {
-        if (*pSz < pLen) {
-            WOLFSSL_MSG("Output buffer for DH p parameter too small, "
-                        "required size placed into pSz");
-            *pSz = pLen;
-            ret = BUFFER_E;
-        }
-    }
-
-    if (ret == 0) {
-        *pSz = pLen;
-        if (mp_to_unsigned_bin(&dh->p, p) != MP_OKAY)
-            ret = MP_TO_E;
-    }
-
-    /* export q */
-    if (ret == 0) {
-        if (*qSz < qLen) {
-            WOLFSSL_MSG("Output buffer for DH q parameter too small, "
-                        "required size placed into qSz");
-            *qSz = qLen;
-            ret = BUFFER_E;
-        }
-    }
-
-    if (ret == 0) {
-        *qSz = qLen;
-        if (mp_to_unsigned_bin(&dh->q, q) != MP_OKAY)
-            ret = MP_TO_E;
-    }
-
-    /* export g */
-    if (ret == 0) {
-        if (*gSz < gLen) {
-            WOLFSSL_MSG("Output buffer for DH g parameter too small, "
-                        "required size placed into gSz");
-            *gSz = gLen;
-            ret = BUFFER_E;
-        }
-    }
-
-    if (ret == 0) {
-        *gSz = gLen;
-        if (mp_to_unsigned_bin(&dh->g, g) != MP_OKAY)
-            ret = MP_TO_E;
-    }
-
-    return ret;
-}
-
-#endif /* WOLFSSL_KEY_GEN */
-
-#endif /* NO_DH */
-
--- a/wolfcrypt/src/dsa.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,791 +0,0 @@
-/* dsa.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_DSA
-
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/sha.h>
-#include <wolfssl/wolfcrypt/dsa.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-enum {
-    DSA_HALF_SIZE = 20,   /* r and s size  */
-    DSA_SIG_SIZE  = 40    /* signature size */
-};
-
-
-
-int wc_InitDsaKey(DsaKey* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    key->type = -1;  /* haven't decided yet */
-    key->heap = NULL;
-
-    return mp_init_multi(
-        /* public  alloc parts */
-        &key->p,
-        &key->q,
-        &key->g,
-        &key->y,
-
-        /* private alloc parts */
-        &key->x,
-        NULL
-    );
-}
-
-
-int wc_InitDsaKey_h(DsaKey* key, void* h)
-{
-    int ret = wc_InitDsaKey(key);
-    if (ret == 0)
-        key->heap = h;
-
-    return ret;
-}
-
-
-void wc_FreeDsaKey(DsaKey* key)
-{
-    if (key == NULL)
-        return;
-
-    if (key->type == DSA_PRIVATE)
-        mp_forcezero(&key->x);
-
-    mp_clear(&key->x);
-    mp_clear(&key->y);
-    mp_clear(&key->g);
-    mp_clear(&key->q);
-    mp_clear(&key->p);
-}
-
-
-/* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2.
- * modLen - represents L, the size of p (prime modulus) in bits
- * divLen - represents N, the size of q (prime divisor) in bits
- * return 0 on success, -1 on error */
-static int CheckDsaLN(int modLen, int divLen)
-{
-    int ret = -1;
-
-    switch (modLen) {
-        case 1024:
-            if (divLen == 160)
-                ret = 0;
-            break;
-        case 2048:
-            if (divLen == 224 || divLen == 256)
-                ret = 0;
-            break;
-        case 3072:
-            if (divLen == 256)
-                ret = 0;
-            break;
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_KEY_GEN
-
-/* Create DSA key pair (&dsa->x, &dsa->y)
- *
- * Based on NIST FIPS 186-4,
- * "B.1.1 Key Pair Generation Using Extra Random Bits"
- *
- * rng - pointer to initialized WC_RNG structure
- * dsa - pointer to initialized DsaKey structure, will hold generated key
- *
- * return 0 on success, negative on error */
-int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa)
-{
-    byte* cBuf;
-    int qSz, pSz, cSz, err;
-    mp_int tmpQ;
-
-    if (rng == NULL || dsa == NULL)
-        return BAD_FUNC_ARG;
-
-    qSz = mp_unsigned_bin_size(&dsa->q);
-    pSz = mp_unsigned_bin_size(&dsa->p);
-
-    /* verify (L,N) pair bit lengths */
-    if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0)
-        return BAD_FUNC_ARG;
-
-    /* generate extra 64 bits so that bias from mod function is negligible */
-    cSz = qSz + (64 / WOLFSSL_BIT_SIZE);
-    cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (cBuf == NULL) {
-        return MEMORY_E;
-    }
-
-    if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL))
-                   != MP_OKAY) {
-        XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return err;
-    }
-
-    do {
-        /* generate N+64 bits (c) from RBG into &dsa->x, making sure positive.
-         * Hash_DRBG uses SHA-256 which matches maximum
-         * requested_security_strength of (L,N) */
-        err = wc_RNG_GenerateBlock(rng, cBuf, cSz);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->x);
-            mp_clear(&dsa->y);
-            mp_clear(&tmpQ);
-            XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return err;
-        }
-
-        err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->x);
-            mp_clear(&dsa->y);
-            mp_clear(&tmpQ);
-            XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return err;
-        }
-    } while (mp_cmp_d(&dsa->x, 1) != MP_GT);
-
-    XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    /* tmpQ = q - 1 */
-    if (err == MP_OKAY)
-        err = mp_copy(&dsa->q, &tmpQ);
-
-    if (err == MP_OKAY)
-        err = mp_sub_d(&tmpQ, 1, &tmpQ);
-
-    /* x = c mod (q-1), &dsa->x holds c */
-    if (err == MP_OKAY)
-        err = mp_mod(&dsa->x, &tmpQ, &dsa->x);
-
-    /* x = c mod (q-1) + 1 */
-    if (err == MP_OKAY)
-        err = mp_add_d(&dsa->x, 1, &dsa->x);
-
-    /* public key : y = g^x mod p */
-    if (err == MP_OKAY)
-        err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y);
-
-    if (err == MP_OKAY)
-        dsa->type = DSA_PRIVATE;
-
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->x);
-        mp_clear(&dsa->y);
-    }
-    mp_clear(&tmpQ);
-
-    return err;
-}
-
-
-/* modulus_size in bits */
-int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa)
-{
-    mp_int  tmp, tmp2;
-    int     err, msize, qsize,
-            loop_check_prime = 0,
-            check_prime = MP_NO;
-    unsigned char   *buf;
-
-    if (rng == NULL || dsa == NULL)
-        return BAD_FUNC_ARG;
-
-    /* set group size in bytes from modulus size
-     * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
-     */
-    switch (modulus_size) {
-        case 1024:
-            qsize = 20;
-            break;
-        case 2048:
-        case 3072:
-            qsize = 32;
-            break;
-        default:
-            return BAD_FUNC_ARG;
-            break;
-    }
-
-    /* modulus size in bytes */
-    msize = modulus_size / WOLFSSL_BIT_SIZE;
-
-    /* allocate ram */
-    buf = (unsigned char *)XMALLOC(msize - qsize,
-                                   dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buf == NULL) {
-        return MEMORY_E;
-    }
-
-    /* make a random string that will be multplied against q */
-    err = wc_RNG_GenerateBlock(rng, buf, msize - qsize);
-    if (err != MP_OKAY) {
-        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return err;
-    }
-
-    /* force magnitude */
-    buf[0] |= 0xC0;
-
-    /* force even */
-    buf[msize - qsize - 1] &= ~1;
-
-    if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) {
-        mp_clear(&dsa->q);
-        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MP_INIT_E;
-    }
-
-    err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize);
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp2);
-        XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return err;
-    }
-    XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    /* make our prime q */
-    err = mp_rand_prime(&dsa->q, qsize, rng, NULL);
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp2);
-        return err;
-    }
-
-    /* p = random * q */
-    err = mp_mul(&dsa->q, &tmp2, &dsa->p);
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp2);
-        return err;
-    }
-
-    /* p = random * q + 1, so q is a prime divisor of p-1 */
-    err = mp_add_d(&dsa->p, 1, &dsa->p);
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp2);
-        return err;
-    }
-
-    if (mp_init(&tmp) != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp2);
-        return MP_INIT_E;
-    }
-
-    /* tmp = 2q  */
-    err = mp_add(&dsa->q, &dsa->q, &tmp);
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp);
-        mp_clear(&tmp2);
-        return err;
-    }
-
-    /* loop until p is prime */
-    while (check_prime == MP_NO) {
-        err = mp_prime_is_prime(&dsa->p, 8, &check_prime);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->q);
-            mp_clear(&dsa->p);
-            mp_clear(&tmp);
-            mp_clear(&tmp2);
-            return err;
-        }
-
-        if (check_prime != MP_YES) {
-            /* p += 2q */
-            err = mp_add(&tmp, &dsa->p, &dsa->p);
-            if (err != MP_OKAY) {
-                mp_clear(&dsa->q);
-                mp_clear(&dsa->p);
-                mp_clear(&tmp);
-                mp_clear(&tmp2);
-                return err;
-            }
-
-            loop_check_prime++;
-        }
-    }
-
-    /* tmp2 += (2*loop_check_prime)
-     * to have p = (q * tmp2) + 1 prime
-     */
-    if (loop_check_prime) {
-        err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->q);
-            mp_clear(&dsa->p);
-            mp_clear(&tmp);
-            mp_clear(&tmp2);
-            return err;
-        }
-    }
-
-    if (mp_init(&dsa->g) != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp);
-        mp_clear(&tmp2);
-        return MP_INIT_E;
-    }
-
-    /* find a value g for which g^tmp2 != 1 */
-    if (mp_set(&dsa->g, 1) != MP_OKAY) {
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->p);
-        mp_clear(&tmp);
-        mp_clear(&tmp2);
-        return MP_INIT_E;
-    }
-
-    do {
-        err = mp_add_d(&dsa->g, 1, &dsa->g);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->q);
-            mp_clear(&dsa->p);
-            mp_clear(&dsa->g);
-            mp_clear(&tmp);
-            mp_clear(&tmp2);
-            return err;
-        }
-
-        err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp);
-        if (err != MP_OKAY) {
-            mp_clear(&dsa->q);
-            mp_clear(&dsa->p);
-            mp_clear(&dsa->g);
-            mp_clear(&tmp);
-            mp_clear(&tmp2);
-            return err;
-        }
-
-    } while (mp_cmp_d(&tmp, 1) == MP_EQ);
-
-    /* at this point tmp generates a group of order q mod p */
-    mp_exch(&tmp, &dsa->g);
-
-    mp_clear(&tmp);
-    mp_clear(&tmp2);
-
-    return MP_OKAY;
-}
-#endif /* WOLFSSL_KEY_GEN */
-
-
-/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(),
- * input parameters (p,q,g) should be represented as ASCII hex values.
- *
- * dsa  - pointer to initialized DsaKey structure
- * p    - DSA (p) parameter, ASCII hex string
- * pSz  - length of p
- * q    - DSA (q) parameter, ASCII hex string
- * qSz  - length of q
- * g    - DSA (g) parameter, ASCII hex string
- * gSz  - length of g
- *
- * returns 0 on success, negative upon failure
- */
-int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q,
-                          const char* g)
-{
-    int err;
-    word32 pSz, qSz;
-
-    if (dsa == NULL || p == NULL || q == NULL || g == NULL)
-        return BAD_FUNC_ARG;
-
-    /* read p */
-    err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX);
-
-    /* read q */
-    if (err == MP_OKAY)
-        err = mp_read_radix(&dsa->q, q, MP_RADIX_HEX);
-
-    /* read g */
-    if (err == MP_OKAY)
-        err = mp_read_radix(&dsa->g, g, MP_RADIX_HEX);
-
-    /* verify (L,N) pair bit lengths */
-    pSz = mp_unsigned_bin_size(&dsa->p);
-    qSz = mp_unsigned_bin_size(&dsa->q);
-
-    if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) {
-        WOLFSSL_MSG("Invalid DSA p or q parameter size");
-        err = BAD_FUNC_ARG;
-    }
-
-    if (err != MP_OKAY) {
-        mp_clear(&dsa->p);
-        mp_clear(&dsa->q);
-        mp_clear(&dsa->g);
-    }
-
-    return err;
-}
-
-
-/* Export raw DSA parameters from DsaKey structure
- *
- * dsa  - pointer to initialized DsaKey structure
- * p    - output location for DSA (p) parameter
- * pSz  - [IN/OUT] size of output buffer for p, size of p
- * q    - output location for DSA (q) parameter
- * qSz  - [IN/OUT] size of output buffer for q, size of q
- * g    - output location for DSA (g) parameter
- * gSz  - [IN/OUT] size of output buffer for g, size of g
- *
- * If p, q, and g pointers are all passed in as NULL, the function
- * will set pSz, qSz, and gSz to the required output buffer sizes for p,
- * q, and g. In this case, the function will return LENGTH_ONLY_E.
- *
- * returns 0 on success, negative upon failure
- */
-int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz,
-                          byte* q, word32* qSz, byte* g, word32* gSz)
-{
-    int err;
-    word32 pLen, qLen, gLen;
-
-    if (dsa == NULL || pSz == NULL || qSz == NULL || gSz == NULL)
-        return BAD_FUNC_ARG;
-
-    /* get required output buffer sizes */
-    pLen = mp_unsigned_bin_size(&dsa->p);
-    qLen = mp_unsigned_bin_size(&dsa->q);
-    gLen = mp_unsigned_bin_size(&dsa->g);
-
-    /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
-    if (p == NULL && q == NULL && g == NULL) {
-        *pSz = pLen;
-        *qSz = qLen;
-        *gSz = gLen;
-        return LENGTH_ONLY_E;
-    }
-
-    if (p == NULL || q == NULL || g == NULL)
-        return BAD_FUNC_ARG;
-
-    /* export p */
-    if (*pSz < pLen) {
-        WOLFSSL_MSG("Output buffer for DSA p parameter too small, "
-                    "required size placed into pSz");
-        *pSz = pLen;
-        return BUFFER_E;
-    }
-    *pSz = pLen;
-    err = mp_to_unsigned_bin(&dsa->p, p);
-
-    /* export q */
-    if (err == MP_OKAY) {
-        if (*qSz < qLen) {
-            WOLFSSL_MSG("Output buffer for DSA q parameter too small, "
-                        "required size placed into qSz");
-            *qSz = qLen;
-            return BUFFER_E;
-        }
-        *qSz = qLen;
-        err = mp_to_unsigned_bin(&dsa->q, q);
-    }
-
-    /* export g */
-    if (err == MP_OKAY) {
-        if (*gSz < gLen) {
-            WOLFSSL_MSG("Output buffer for DSA g parameter too small, "
-                        "required size placed into gSz");
-            *gSz = gLen;
-            return BUFFER_E;
-        }
-        *gSz = gLen;
-        err = mp_to_unsigned_bin(&dsa->g, g);
-    }
-
-    return err;
-}
-
-
-/* Export raw DSA key (x, y) from DsaKey structure
- *
- * dsa  - pointer to initialized DsaKey structure
- * x    - output location for private key
- * xSz  - [IN/OUT] size of output buffer for x, size of x
- * y    - output location for public key
- * ySz  - [IN/OUT] size of output buffer for y, size of y
- *
- * If x and y pointers are all passed in as NULL, the function
- * will set xSz and ySz to the required output buffer sizes for x
- * and y. In this case, the function will return LENGTH_ONLY_E.
- *
- * returns 0 on success, negative upon failure
- */
-int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz)
-{
-    int err;
-    word32 xLen, yLen;
-
-    if (dsa == NULL || xSz == NULL || ySz == NULL)
-        return BAD_FUNC_ARG;
-
-    /* get required output buffer sizes */
-    xLen = mp_unsigned_bin_size(&dsa->x);
-    yLen = mp_unsigned_bin_size(&dsa->y);
-
-    /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */
-    if (x == NULL && y == NULL) {
-        *xSz = xLen;
-        *ySz = yLen;
-        return LENGTH_ONLY_E;
-    }
-
-    if (x == NULL || y == NULL)
-        return BAD_FUNC_ARG;
-
-    /* export x */
-    if (*xSz < xLen) {
-        WOLFSSL_MSG("Output buffer for DSA private key (x) too small, "
-                    "required size placed into xSz");
-        *xSz = xLen;
-        return BUFFER_E;
-    }
-    *xSz = xLen;
-    err = mp_to_unsigned_bin(&dsa->x, x);
-
-    /* export y */
-    if (err == MP_OKAY) {
-        if (*ySz < yLen) {
-            WOLFSSL_MSG("Output buffer to DSA public key (y) too small, "
-                        "required size placed into ySz");
-            *ySz = yLen;
-            return BUFFER_E;
-        }
-        *ySz = yLen;
-        err = mp_to_unsigned_bin(&dsa->y, y);
-    }
-
-    return err;
-}
-
-
-int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng)
-{
-    mp_int k, kInv, r, s, H;
-    int    ret, sz;
-    byte   buffer[DSA_HALF_SIZE];
-    byte*  tmp;  /* initial output pointer */
-
-    if (digest == NULL || out == NULL || key == NULL || rng == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    tmp = out;
-
-    sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q));
-
-    if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY)
-        return MP_INIT_E;
-
-    do {
-        /* generate k */
-        ret = wc_RNG_GenerateBlock(rng, buffer, sz);
-        if (ret != 0)
-            return ret;
-
-        buffer[0] |= 0x0C;
-
-        if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY)
-            ret = MP_READ_E;
-
-        /* k is a random numnber and it should be less than q
-         * if k greater than repeat
-         */
-    } while (mp_cmp(&k, &key->q) != MP_LT);
-
-    if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT)
-        ret = MP_CMP_E;
-
-    /* inverse k mod q */
-    if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
-        ret = MP_INVMOD_E;
-
-    /* generate r, r = (g exp k mod p) mod q */
-    if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY)
-        ret = MP_EXPTMOD_E;
-
-    if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
-        ret = MP_MOD_E;
-
-    /* generate H from sha digest */
-    if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
-        ret = MP_READ_E;
-
-    /* generate s, s = (kInv * (H + x*r)) % q */
-    if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
-        ret = MP_MUL_E;
-
-    if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
-        ret = MP_ADD_E;
-
-    if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
-        ret = MP_MULMOD_E;
-
-    /* detect zero r or s */
-    if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES))
-        ret = MP_ZERO_E;
-
-    /* write out */
-    if (ret == 0)  {
-        int rSz = mp_unsigned_bin_size(&r);
-        int sSz = mp_unsigned_bin_size(&s);
-
-        while (rSz++ < DSA_HALF_SIZE) {
-            *out++ = 0x00;  /* pad front with zeros */
-        }
-
-        if (mp_to_unsigned_bin(&r, out) != MP_OKAY)
-            ret = MP_TO_E;
-        else {
-            out = tmp + DSA_HALF_SIZE;  /* advance to s in output */
-            while (sSz++ < DSA_HALF_SIZE) {
-                *out++ = 0x00;  /* pad front with zeros */
-            }
-            ret = mp_to_unsigned_bin(&s, out);
-        }
-    }
-
-    mp_clear(&H);
-    mp_clear(&s);
-    mp_clear(&r);
-    mp_clear(&kInv);
-    mp_clear(&k);
-
-    return ret;
-}
-
-
-int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
-{
-    mp_int w, u1, u2, v, r, s;
-    int    ret = 0;
-
-    if (digest == NULL || sig == NULL || key == NULL || answer == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
-        return MP_INIT_E;
-
-    /* set r and s from signature */
-    if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
-        mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
-        ret = MP_READ_E;
-
-    /* sanity checks */
-    if (ret == 0) {
-        if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES ||
-                mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) {
-            ret = MP_ZERO_E;
-        }
-    }
-
-    /* put H into u1 from sha digest */
-    if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
-        ret = MP_READ_E;
-
-    /* w = s invmod q */
-    if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
-        ret = MP_INVMOD_E;
-
-    /* u1 = (H * w) % q */
-    if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
-        ret = MP_MULMOD_E;
-
-    /* u2 = (r * w) % q */
-    if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
-        ret = MP_MULMOD_E;
-
-    /* verify v = ((g^u1 * y^u2) mod p) mod q */
-    if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
-        ret = MP_EXPTMOD_E;
-
-    if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
-        ret = MP_EXPTMOD_E;
-
-    if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
-        ret = MP_MULMOD_E;
-
-    if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
-        ret = MP_MULMOD_E;
-
-    /* do they match */
-    if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
-        *answer = 1;
-    else
-        *answer = 0;
-
-    mp_clear(&s);
-    mp_clear(&r);
-    mp_clear(&u1);
-    mp_clear(&u2);
-    mp_clear(&w);
-    mp_clear(&v);
-
-    return ret;
-}
-
-
-#endif /* NO_DSA */
-
-
--- a/wolfcrypt/src/ecc.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9590 +0,0 @@
-/* ecc.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-/* in case user set HAVE_ECC there */
-#include <wolfssl/wolfcrypt/settings.h>
-
-/*
-Possible ECC enable options:
- * HAVE_ECC:            Overall control of ECC                  default: on
- * HAVE_ECC_ENCRYPT:    ECC encrypt/decrypt w/AES and HKDF      default: off
- * HAVE_ECC_SIGN:       ECC sign                                default: on
- * HAVE_ECC_VERIFY:     ECC verify                              default: on
- * HAVE_ECC_DHE:        ECC build shared secret                 default: on
- * HAVE_ECC_CDH:        ECC cofactor DH shared secret           default: off
- * HAVE_ECC_KEY_IMPORT: ECC Key import                          default: on
- * HAVE_ECC_KEY_EXPORT: ECC Key export                          default: on
- * ECC_SHAMIR:          Enables Shamir calc method              default: on
- * HAVE_COMP_KEY:       Enables compressed key                  default: off
- * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import      default: off
- * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen            default: off
- * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves.            default: off
- *                        Includes the curve "a" variable in calculation
- * ECC_DUMP_OID:        Enables dump of OID encoding and sum    default: off
- * ECC_CACHE_CURVE:     Enables cache of curve info to improve perofrmance
-                                                                default: off
- * FP_ECC:              ECC Fixed Point Cache                   default: off
- * USE_ECC_B_PARAM:     Enable ECC curve B param                default: off
-                         (on for HAVE_COMP_KEY)
- */
-
-/*
-ECC Curve Types:
- * NO_ECC_SECP          Disables SECP curves                    default: off (not defined)
- * HAVE_ECC_SECPR2      Enables SECP R2 curves                  default: off
- * HAVE_ECC_SECPR3      Enables SECP R3 curves                  default: off
- * HAVE_ECC_BRAINPOOL   Enables Brainpool curves                default: off
- * HAVE_ECC_KOBLITZ     Enables Koblitz curves                  default: off
- */
-
-/*
-ECC Curve Sizes:
- * ECC_USER_CURVES: Allows custom combination of key sizes below
- * HAVE_ALL_CURVES: Enable all key sizes (on unless ECC_USER_CURVES is defined)
- * HAVE_ECC112: 112 bit key
- * HAVE_ECC128: 128 bit key
- * HAVE_ECC160: 160 bit key
- * HAVE_ECC192: 192 bit key
- * HAVE_ECC224: 224 bit key
- * HAVE_ECC239: 239 bit key
- * NO_ECC256: Disables 256 bit key (on by default)
- * HAVE_ECC320: 320 bit key
- * HAVE_ECC384: 384 bit key
- * HAVE_ECC512: 512 bit key
- * HAVE_ECC521: 521 bit key
- */
-
-
-#ifdef HAVE_ECC
-
-/* Make sure custom curves is enabled for Brainpool or Koblitz curve types */
-#if (defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ)) &&\
-    !defined(WOLFSSL_CUSTOM_CURVES)
-    #error Brainpool and Koblitz curves requires WOLFSSL_CUSTOM_CURVES
-#endif
-
-/* Make sure ASN is enabled for ECC sign/verify */
-#if (defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)) && defined(NO_ASN)
-    #error ASN must be enabled for ECC sign/verify
-#endif
-
-
-#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-	#ifdef USE_WINDOWS_API
-		#pragma code_seg(".fipsA$f")
-		#pragma const_seg(".fipsB$f")
-	#endif
-#endif
-
-#include <wolfssl/wolfcrypt/ecc.h>
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-#include <wolfssl/wolfcrypt/sp.h>
-#endif
-
-#ifdef HAVE_ECC_ENCRYPT
-    #include <wolfssl/wolfcrypt/hmac.h>
-    #include <wolfssl/wolfcrypt/aes.h>
-#endif
-
-#ifdef HAVE_X963_KDF
-    #include <wolfssl/wolfcrypt/hash.h>
-#endif
-
-#ifdef WOLF_CRYPTO_DEV
-    #include <wolfssl/wolfcrypt/cryptodev.h>
-#endif
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(FREESCALE_LTC_ECC)
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-
-#ifdef WOLFSSL_SP_MATH
-    #define GEN_MEM_ERR MP_MEM
-#elif defined(USE_FAST_MATH)
-    #define GEN_MEM_ERR FP_MEM
-#else
-    #define GEN_MEM_ERR MP_MEM
-#endif
-
-
-/* internal ECC states */
-enum {
-    ECC_STATE_NONE = 0,
-
-    ECC_STATE_SHARED_SEC_GEN,
-    ECC_STATE_SHARED_SEC_RES,
-
-    ECC_STATE_SIGN_DO,
-    ECC_STATE_SIGN_ENCODE,
-
-    ECC_STATE_VERIFY_DECODE,
-    ECC_STATE_VERIFY_DO,
-    ECC_STATE_VERIFY_RES,
-};
-
-
-/* map
-   ptmul -> mulmod
-*/
-
-/* 256-bit curve on by default whether user curves or not */
-#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES)
-    #define ECC112
-#endif
-#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES)
-    #define ECC128
-#endif
-#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
-    #define ECC160
-#endif
-#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
-    #define ECC192
-#endif
-#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
-    #define ECC224
-#endif
-#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES)
-    #define ECC239
-#endif
-#if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
-    #define ECC256
-#endif
-#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES)
-    #define ECC320
-#endif
-#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
-    #define ECC384
-#endif
-#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
-    #define ECC512
-#endif
-#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
-    #define ECC521
-#endif
-
-/* The encoded OID's for ECC curves */
-#ifdef ECC112
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP112R1    {1,3,132,0,6}
-            #define CODED_SECP112R1_SZ 5
-        #else
-            #define CODED_SECP112R1    {0x2B,0x81,0x04,0x00,0x06}
-            #define CODED_SECP112R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp112r1[] = CODED_SECP112R1;
-        #else
-            #define ecc_oid_secp112r1 CODED_SECP112R1
-        #endif
-        #define ecc_oid_secp112r1_sz CODED_SECP112R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP112R2    {1,3,132,0,7}
-            #define CODED_SECP112R2_SZ 5
-        #else
-            #define CODED_SECP112R2    {0x2B,0x81,0x04,0x00,0x07}
-            #define CODED_SECP112R2_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp112r2[] = CODED_SECP112R2;
-        #else
-            #define ecc_oid_secp112r2 CODED_SECP112R2
-        #endif
-        #define ecc_oid_secp112r2_sz CODED_SECP112R2_SZ
-    #endif /* HAVE_ECC_SECPR2 */
-#endif /* ECC112 */
-#ifdef ECC128
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP128R1    {1,3,132,0,28}
-            #define CODED_SECP128R1_SZ 5
-        #else
-            #define CODED_SECP128R1    {0x2B,0x81,0x04,0x00,0x1C}
-            #define CODED_SECP128R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp128r1[] = CODED_SECP128R1;
-        #else
-            #define ecc_oid_secp128r1 CODED_SECP128R1
-        #endif
-        #define ecc_oid_secp128r1_sz CODED_SECP128R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP128R2    {1,3,132,0,29}
-            #define CODED_SECP128R2_SZ 5
-        #else
-            #define CODED_SECP128R2    {0x2B,0x81,0x04,0x00,0x1D}
-            #define CODED_SECP128R2_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp128r2[] = CODED_SECP128R2;
-        #else
-            #define ecc_oid_secp128r2 CODED_SECP128R2
-        #endif
-        #define ecc_oid_secp128r2_sz CODED_SECP128R2_SZ
-    #endif /* HAVE_ECC_SECPR2 */
-#endif /* ECC128 */
-#ifdef ECC160
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP160R1    {1,3,132,0,8}
-            #define CODED_SECP160R1_SZ 5
-        #else
-            #define CODED_SECP160R1    {0x2B,0x81,0x04,0x00,0x08}
-            #define CODED_SECP160R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp160r1[] = CODED_SECP160R1;
-        #else
-            #define ecc_oid_secp160r1 CODED_SECP160R1
-        #endif
-        #define ecc_oid_secp160r1_sz CODED_SECP160R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP160R2    {1,3,132,0,30}
-            #define CODED_SECP160R1_SZ 5
-        #else
-            #define CODED_SECP160R2    {0x2B,0x81,0x04,0x00,0x1E}
-            #define CODED_SECP160R2_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp160r2[] = CODED_SECP160R2;
-        #else
-            #define ecc_oid_secp160r2 CODED_SECP160R2
-        #endif
-        #define ecc_oid_secp160r2_sz CODED_SECP160R2_SZ
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_KOBLITZ
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP160K1    {1,3,132,0,9}
-            #define CODED_SECP160K1_SZ 5
-        #else
-            #define CODED_SECP160K1    {0x2B,0x81,0x04,0x00,0x09}
-            #define CODED_SECP160K1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp160k1[] = CODED_SECP160K1;
-        #else
-            #define ecc_oid_secp160k1 CODED_SECP160K1
-        #endif
-        #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP160R1    {1,3,36,3,3,2,8,1,1,1}
-            #define CODED_BRAINPOOLP160R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP160R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01}
-            #define CODED_BRAINPOOLP160R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp160r1[] = CODED_BRAINPOOLP160R1;
-        #else
-            #define ecc_oid_brainpoolp160r1 CODED_BRAINPOOLP160R1
-        #endif
-        #define ecc_oid_brainpoolp160r1_sz CODED_BRAINPOOLP160R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC160 */
-#ifdef ECC192
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP192R1    {1,2,840,10045,3,1,1}
-            #define CODED_SECP192R1_SZ 7
-        #else
-            #define CODED_SECP192R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01}
-            #define CODED_SECP192R1_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp192r1[] = CODED_SECP192R1;
-        #else
-            #define ecc_oid_secp192r1 CODED_SECP192R1
-        #endif
-        #define ecc_oid_secp192r1_sz CODED_SECP192R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_PRIME192V2    {1,2,840,10045,3,1,2}
-            #define CODED_PRIME192V2_SZ 7
-        #else
-            #define CODED_PRIME192V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02}
-            #define CODED_PRIME192V2_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_prime192v2[] = CODED_PRIME192V2;
-        #else
-            #define ecc_oid_prime192v2 CODED_PRIME192V2
-        #endif
-        #define ecc_oid_prime192v2_sz CODED_PRIME192V2_SZ
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_SECPR3
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_PRIME192V3    {1,2,840,10045,3,1,3}
-            #define CODED_PRIME192V3_SZ 7
-        #else
-            #define CODED_PRIME192V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03}
-            #define CODED_PRIME192V3_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_prime192v3[] = CODED_PRIME192V3;
-        #else
-            #define ecc_oid_prime192v3 CODED_PRIME192V3
-        #endif
-        #define ecc_oid_prime192v3_sz CODED_PRIME192V3_SZ
-    #endif /* HAVE_ECC_SECPR3 */
-    #ifdef HAVE_ECC_KOBLITZ
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP192K1    {1,3,132,0,31}
-            #define CODED_SECP192K1_SZ 5
-        #else
-            #define CODED_SECP192K1    {0x2B,0x81,0x04,0x00,0x1F}
-            #define CODED_SECP192K1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp192k1[] = CODED_SECP192K1;
-        #else
-            #define ecc_oid_secp192k1 CODED_SECP192K1
-        #endif
-        #define ecc_oid_secp192k1_sz CODED_SECP192K1_SZ
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP192R1    {1,3,36,3,3,2,8,1,1,3}
-            #define CODED_BRAINPOOLP192R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP192R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03}
-            #define CODED_BRAINPOOLP192R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp192r1[] = CODED_BRAINPOOLP192R1;
-        #else
-            #define ecc_oid_brainpoolp192r1 CODED_BRAINPOOLP192R1
-        #endif
-        #define ecc_oid_brainpoolp192r1_sz CODED_BRAINPOOLP192R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC192 */
-#ifdef ECC224
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP224R1    {1,3,132,0,33}
-            #define CODED_SECP224R1_SZ 5
-        #else
-            #define CODED_SECP224R1    {0x2B,0x81,0x04,0x00,0x21}
-            #define CODED_SECP224R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp224r1[] = CODED_SECP224R1;
-        #else
-            #define ecc_oid_secp224r1 CODED_SECP224R1
-        #endif
-        #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_KOBLITZ
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP224K1    {1,3,132,0,32}
-            #define CODED_SECP224K1_SZ 5
-        #else
-            #define CODED_SECP224K1    {0x2B,0x81,0x04,0x00,0x20}
-            #define CODED_SECP224K1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp224k1[] = CODED_SECP224K1;
-        #else
-            #define ecc_oid_secp224k1 CODED_SECP224K1
-        #endif
-        #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP224R1    {1,3,36,3,3,2,8,1,1,5}
-            #define CODED_BRAINPOOLP224R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP224R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05}
-            #define CODED_BRAINPOOLP224R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp224r1[] = CODED_BRAINPOOLP224R1;
-        #else
-            #define ecc_oid_brainpoolp224r1 CODED_BRAINPOOLP224R1
-        #endif
-        #define ecc_oid_brainpoolp224r1_sz CODED_BRAINPOOLP224R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC224 */
-#ifdef ECC239
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_PRIME239V1    {1,2,840,10045,3,1,4}
-            #define CODED_PRIME239V1_SZ 7
-        #else
-            #define CODED_PRIME239V1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04}
-            #define CODED_PRIME239V1_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_prime239v1[] = CODED_PRIME239V1;
-        #else
-            #define ecc_oid_prime239v1 CODED_PRIME239V1
-        #endif
-        #define ecc_oid_prime239v1_sz CODED_PRIME239V1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_PRIME239V2    {1,2,840,10045,3,1,5}
-            #define CODED_PRIME239V2_SZ 7
-        #else
-            #define CODED_PRIME239V2    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05}
-            #define CODED_PRIME239V2_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_prime239v2[] = CODED_PRIME239V2;
-        #else
-            #define ecc_oid_prime239v2 CODED_PRIME239V2
-        #endif
-        #define ecc_oid_prime239v2_sz CODED_PRIME239V2_SZ
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_SECPR3
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_PRIME239V3    {1,2,840,10045,3,1,6}
-            #define CODED_PRIME239V3_SZ 7
-        #else
-            #define CODED_PRIME239V3    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06}
-            #define CODED_PRIME239V3_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_prime239v3[] = CODED_PRIME239V3;
-        #else
-            #define ecc_oid_prime239v3 CODED_PRIME239V3
-        #endif
-        #define ecc_oid_prime239v3_sz CODED_PRIME239V3_SZ
-    #endif /* HAVE_ECC_SECPR3 */
-#endif /* ECC239 */
-#ifdef ECC256
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP256R1    {1,2,840,10045,3,1,7}
-            #define CODED_SECP256R1_SZ 7
-        #else
-            #define CODED_SECP256R1    {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07}
-            #define CODED_SECP256R1_SZ 8
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp256r1[] = CODED_SECP256R1;
-        #else
-            #define ecc_oid_secp256r1 CODED_SECP256R1
-        #endif
-        #define ecc_oid_secp256r1_sz CODED_SECP256R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_KOBLITZ
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP256K1    {1,3,132,0,10}
-            #define CODED_SECP256K1_SZ 5
-        #else
-            #define CODED_SECP256K1    {0x2B,0x81,0x04,0x00,0x0A}
-            #define CODED_SECP256K1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp256k1[] = CODED_SECP256K1;
-        #else
-            #define ecc_oid_secp256k1 CODED_SECP256K1
-        #endif
-        #define ecc_oid_secp256k1_sz CODED_SECP256K1_SZ
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP256R1    {1,3,36,3,3,2,8,1,1,7}
-            #define CODED_BRAINPOOLP256R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP256R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07}
-            #define CODED_BRAINPOOLP256R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp256r1[] = CODED_BRAINPOOLP256R1;
-        #else
-            #define ecc_oid_brainpoolp256r1 CODED_BRAINPOOLP256R1
-        #endif
-        #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC256 */
-#ifdef ECC320
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP320R1    {1,3,36,3,3,2,8,1,1,9}
-            #define CODED_BRAINPOOLP320R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP320R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09}
-            #define CODED_BRAINPOOLP320R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp320r1[] = CODED_BRAINPOOLP320R1;
-        #else
-            #define ecc_oid_brainpoolp320r1 CODED_BRAINPOOLP320R1
-        #endif
-        #define ecc_oid_brainpoolp320r1_sz CODED_BRAINPOOLP320R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC320 */
-#ifdef ECC384
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP384R1    {1,3,132,0,34}
-            #define CODED_SECP384R1_SZ 5
-        #else
-            #define CODED_SECP384R1    {0x2B,0x81,0x04,0x00,0x22}
-            #define CODED_SECP384R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp384r1[] = CODED_SECP384R1;
-            #define CODED_SECP384R1_OID ecc_oid_secp384r1
-        #else
-			#define ecc_oid_secp384r1 CODED_SECP384R1
-        #endif
-        #define ecc_oid_secp384r1_sz CODED_SECP384R1_SZ
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP384R1    {1,3,36,3,3,2,8,1,1,11}
-            #define CODED_BRAINPOOLP384R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP384R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B}
-            #define CODED_BRAINPOOLP384R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp384r1[] = CODED_BRAINPOOLP384R1;
-        #else
-            #define ecc_oid_brainpoolp384r1 CODED_BRAINPOOLP384R1
-        #endif
-        #define ecc_oid_brainpoolp384r1_sz CODED_BRAINPOOLP384R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC384 */
-#ifdef ECC512
-    #ifdef HAVE_ECC_BRAINPOOL
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_BRAINPOOLP512R1    {1,3,36,3,3,2,8,1,1,13}
-            #define CODED_BRAINPOOLP512R1_SZ 10
-        #else
-            #define CODED_BRAINPOOLP512R1    {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D}
-            #define CODED_BRAINPOOLP512R1_SZ 9
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_brainpoolp512r1[] = CODED_BRAINPOOLP512R1;
-        #else
-            #define ecc_oid_brainpoolp512r1 CODED_BRAINPOOLP512R1
-        #endif
-        #define ecc_oid_brainpoolp512r1_sz CODED_BRAINPOOLP512R1_SZ
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC512 */
-#ifdef ECC521
-    #ifndef NO_ECC_SECP
-        #ifdef HAVE_OID_ENCODING
-            #define CODED_SECP521R1     {1,3,132,0,35}
-            #define CODED_SECP521R1_SZ 5
-        #else
-            #define CODED_SECP521R1     {0x2B,0x81,0x04,0x00,0x23}
-            #define CODED_SECP521R1_SZ 5
-        #endif
-        #ifndef USE_WINDOWS_API
-            static const ecc_oid_t ecc_oid_secp521r1[] = CODED_SECP521R1;
-        #else
-            #define ecc_oid_secp521r1 CODED_SECP521R1
-        #endif
-        #define ecc_oid_secp521r1_sz CODED_SECP521R1_SZ
-    #endif /* !NO_ECC_SECP */
-#endif /* ECC521 */
-
-
-/* This holds the key settings.
-   ***MUST*** be organized by size from smallest to largest. */
-
-const ecc_set_type ecc_sets[] = {
-#ifdef ECC112
-    #ifndef NO_ECC_SECP
-    {
-        14,                             /* size/bytes */
-        ECC_SECP112R1,                  /* ID         */
-        "SECP112R1",                    /* curve name */
-        "DB7C2ABF62E35E668076BEAD208B", /* prime      */
-        "DB7C2ABF62E35E668076BEAD2088", /* A          */
-        "659EF8BA043916EEDE8911702B22", /* B          */
-        "DB7C2ABF62E35E7628DFAC6561C5", /* order      */
-        "9487239995A5EE76B55F9C2F098",  /* Gx         */
-        "A89CE5AF8724C0A23E0E0FF77500", /* Gy         */
-        ecc_oid_secp112r1,              /* oid/oidSz  */
-        ecc_oid_secp112r1_sz,
-        ECC_SECP112R1_OID,              /* oid sum    */
-        1,                              /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-    {
-        14,                             /* size/bytes */
-        ECC_SECP112R2,                  /* ID         */
-        "SECP112R2",                    /* curve name */
-        "DB7C2ABF62E35E668076BEAD208B", /* prime      */
-        "6127C24C05F38A0AAAF65C0EF02C", /* A          */
-        "51DEF1815DB5ED74FCC34C85D709", /* B          */
-        "36DF0AAFD8B8D7597CA10520D04B", /* order      */
-        "4BA30AB5E892B4E1649DD0928643", /* Gx         */
-        "ADCD46F5882E3747DEF36E956E97", /* Gy         */
-        ecc_oid_secp112r2,              /* oid/oidSz  */
-        ecc_oid_secp112r2_sz,
-        ECC_SECP112R2_OID,              /* oid sum    */
-        4,                              /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR2 */
-#endif /* ECC112 */
-#ifdef ECC128
-    #ifndef NO_ECC_SECP
-    {
-        16,                                 /* size/bytes */
-        ECC_SECP128R1,                      /* ID         */
-        "SECP128R1",                        /* curve name */
-        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
-        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
-        "E87579C11079F43DD824993C2CEE5ED3", /* B          */
-        "FFFFFFFE0000000075A30D1B9038A115", /* order      */
-        "161FF7528B899B2D0C28607CA52C5B86", /* Gx         */
-        "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy         */
-        ecc_oid_secp128r1,                  /* oid/oidSz  */
-        ecc_oid_secp128r1_sz,
-        ECC_SECP128R1_OID,                  /* oid sum    */
-        1,                                  /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-    {
-        16,                                 /* size/bytes */
-        ECC_SECP128R2,                      /* ID         */
-        "SECP128R2",                        /* curve name */
-        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
-        "D6031998D1B3BBFEBF59CC9BBFF9AEE1", /* A          */
-        "5EEEFCA380D02919DC2C6558BB6D8A5D", /* B          */
-        "3FFFFFFF7FFFFFFFBE0024720613B5A3", /* order      */
-        "7B6AA5D85E572983E6FB32A7CDEBC140", /* Gx         */
-        "27B6916A894D3AEE7106FE805FC34B44", /* Gy         */
-        ecc_oid_secp128r2,                  /* oid/oidSz  */
-        ecc_oid_secp128r2_sz,
-        ECC_SECP128R2_OID,                  /* oid sum    */
-        4,                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR2 */
-#endif /* ECC128 */
-#ifdef ECC160
-    #ifndef NO_ECC_SECP
-    {
-        20,                                         /* size/bytes */
-        ECC_SECP160R1,                              /* ID         */
-        "SECP160R1",                                /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* A          */
-        "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* B          */
-        "100000000000000000001F4C8F927AED3CA752257",/* order      */
-        "4A96B5688EF573284664698968C38BB913CBFC82", /* Gx         */
-        "23A628553168947D59DCC912042351377AC5FB32", /* Gy         */
-        ecc_oid_secp160r1,                          /* oid/oidSz  */
-        ecc_oid_secp160r1_sz,
-        ECC_SECP160R1_OID,                          /* oid sum    */
-        1,                                          /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-    {
-        20,                                         /* size/bytes */
-        ECC_SECP160R2,                              /* ID         */
-        "SECP160R2",                                /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", /* A          */
-        "B4E134D3FB59EB8BAB57274904664D5AF50388BA", /* B          */
-        "100000000000000000000351EE786A818F3A1A16B",/* order      */
-        "52DCB034293A117E1F4FF11B30F7199D3144CE6D", /* Gx         */
-        "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* Gy         */
-        ecc_oid_secp160r2,                          /* oid/oidSz  */
-        ecc_oid_secp160r2_sz,
-        ECC_SECP160R2_OID,                          /* oid sum    */
-        1,                                          /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_KOBLITZ
-    {
-        20,                                         /* size/bytes */
-        ECC_SECP160K1,                              /* ID         */
-        "SECP160K1",                                /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime      */
-        "0000000000000000000000000000000000000000", /* A          */
-        "0000000000000000000000000000000000000007", /* B          */
-        "100000000000000000001B8FA16DFAB9ACA16B6B3",/* order      */
-        "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", /* Gx         */
-        "938CF935318FDCED6BC28286531733C3F03C4FEE", /* Gy         */
-        ecc_oid_secp160k1,                          /* oid/oidSz  */
-        ecc_oid_secp160k1_sz,
-        ECC_SECP160K1_OID,                          /* oid sum    */
-        1,                                          /* cofactor   */
-    },
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        20,                                         /* size/bytes */
-        ECC_BRAINPOOLP160R1,                        /* ID         */
-        "BRAINPOOLP160R1",                          /* curve name */
-        "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* prime      */
-        "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", /* A          */
-        "1E589A8595423412134FAA2DBDEC95C8D8675E58", /* B          */
-        "E95E4A5F737059DC60DF5991D45029409E60FC09", /* order      */
-        "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", /* Gx         */
-        "1667CB477A1A8EC338F94741669C976316DA6321", /* Gy         */
-        ecc_oid_brainpoolp160r1,                    /* oid/oidSz  */
-        ecc_oid_brainpoolp160r1_sz,
-        ECC_BRAINPOOLP160R1_OID,                    /* oid sum    */
-        1,                                          /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC160 */
-#ifdef ECC192
-    #ifndef NO_ECC_SECP
-    {
-        24,                                                 /* size/bytes */
-        ECC_SECP192R1,                                      /* ID         */
-        "SECP192R1",                                        /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
-        "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order      */
-        "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx         */
-        "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",  /* Gy         */
-        ecc_oid_secp192r1,                                  /* oid/oidSz  */
-        ecc_oid_secp192r1_sz,
-        ECC_SECP192R1_OID,                                  /* oid sum    */
-        1,                                                  /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-    {
-        24,                                                 /* size/bytes */
-        ECC_PRIME192V2,                                     /* ID         */
-        "PRIME192V2",                                       /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
-        "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", /* order      */
-        "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", /* Gx         */
-        "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* Gy         */
-        ecc_oid_prime192v2,                                 /* oid/oidSz  */
-        ecc_oid_prime192v2_sz,
-        ECC_PRIME192V2_OID,                                 /* oid sum    */
-        1,                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_SECPR3
-    {
-        24,                                                 /* size/bytes */
-        ECC_PRIME192V3,                                     /* ID         */
-        "PRIME192V3",                                       /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A          */
-        "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", /* order      */
-        "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", /* Gx         */
-        "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* Gy         */
-        ecc_oid_prime192v3,                                 /* oid/oidSz  */
-        ecc_oid_prime192v3_sz,
-        ECC_PRIME192V3_OID,                                 /* oid sum    */
-        1,                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR3 */
-    #ifdef HAVE_ECC_KOBLITZ
-    {
-        24,                                                 /* size/bytes */
-        ECC_SECP192K1,                                      /* ID         */
-        "SECP192K1",                                        /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* prime      */
-        "000000000000000000000000000000000000000000000000", /* A          */
-        "000000000000000000000000000000000000000000000003", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* order      */
-        "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", /* Gx         */
-        "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* Gy         */
-        ecc_oid_secp192k1,                                  /* oid/oidSz  */
-        ecc_oid_secp192k1_sz,
-        ECC_SECP192K1_OID,                                  /* oid sum    */
-        1,                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        24,                                                 /* size/bytes */
-        ECC_BRAINPOOLP192R1,                                /* ID         */
-        "BRAINPOOLP192R1",                                  /* curve name */
-        "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* prime      */
-        "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", /* A          */
-        "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", /* B          */
-        "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* order      */
-        "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", /* Gx         */
-        "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* Gy         */
-        ecc_oid_brainpoolp192r1,                            /* oid/oidSz  */
-        ecc_oid_brainpoolp192r1_sz,
-        ECC_BRAINPOOLP192R1_OID,                            /* oid sum    */
-        1,                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC192 */
-#ifdef ECC224
-    #ifndef NO_ECC_SECP
-    {
-        28,                                                         /* size/bytes */
-        ECC_SECP224R1,                                              /* ID         */
-        "SECP224R1",                                                /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A          */
-        "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order      */
-        "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx         */
-        "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy         */
-        ecc_oid_secp224r1,                                          /* oid/oidSz  */
-        ecc_oid_secp224r1_sz,
-        ECC_SECP224R1_OID,                                          /* oid sum    */
-        1,                                                          /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_KOBLITZ
-    {
-        28,                                                         /* size/bytes */
-        ECC_SECP224K1,                                              /* ID         */
-        "SECP224K1",                                                /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* prime      */
-        "00000000000000000000000000000000000000000000000000000000", /* A          */
-        "00000000000000000000000000000000000000000000000000000005", /* B          */
-        "10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",/* order      */
-        "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gx         */
-        "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy         */
-        ecc_oid_secp224k1,                                          /* oid/oidSz  */
-        ecc_oid_secp224k1_sz,
-        ECC_SECP224K1_OID,                                          /* oid sum    */
-        1,                                                          /* cofactor   */
-    },
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        28,                                                         /* size/bytes */
-        ECC_BRAINPOOLP224R1,                                        /* ID         */
-        "BRAINPOOLP224R1",                                          /* curve name */
-        "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* prime      */
-        "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", /* A          */
-        "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", /* B          */
-        "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* order      */
-        "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", /* Gx         */
-        "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* Gy         */
-        ecc_oid_brainpoolp224r1,                                    /* oid/oidSz  */
-        ecc_oid_brainpoolp224r1_sz,
-        ECC_BRAINPOOLP224R1_OID,                                    /* oid sum    */
-        1,                                                          /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC224 */
-#ifdef ECC239
-    #ifndef NO_ECC_SECP
-    {
-        30,                                                             /* size/bytes */
-        ECC_PRIME239V1,                                                 /* ID         */
-        "PRIME239V1",                                                   /* curve name */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
-        "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", /* B          */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", /* order      */
-        "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", /* Gx         */
-        "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* Gy         */
-        ecc_oid_prime239v1,                                             /* oid/oidSz  */
-        ecc_oid_prime239v1_sz,
-        ECC_PRIME239V1_OID,                                             /* oid sum    */
-        1,                                                              /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_SECPR2
-    {
-        30,                                                             /* size/bytes */
-        ECC_PRIME239V2,                                                 /* ID         */
-        "PRIME239V2",                                                   /* curve name */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
-        "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", /* B          */
-        "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", /* order      */
-        "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", /* Gx         */
-        "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* Gy         */
-        ecc_oid_prime239v2,                                             /* oid/oidSz  */
-        ecc_oid_prime239v2_sz,
-        ECC_PRIME239V2_OID,                                             /* oid sum    */
-        1,                                                              /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR2 */
-    #ifdef HAVE_ECC_SECPR3
-    {
-        30,                                                             /* size/bytes */
-        ECC_PRIME239V3,                                                 /* ID         */
-        "PRIME239V3",                                                   /* curve name */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime      */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A          */
-        "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", /* B          */
-        "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", /* order      */
-        "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", /* Gx         */
-        "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* Gy         */
-        ecc_oid_prime239v3,                                             /* oid/oidSz  */
-        ecc_oid_prime239v3_sz,
-        ECC_PRIME239V3_OID,                                             /* oid sum    */
-        1,                                                              /* cofactor   */
-    },
-    #endif /* HAVE_ECC_SECPR3 */
-#endif /* ECC239 */
-#ifdef ECC256
-    #ifndef NO_ECC_SECP
-    {
-        32,                                                                 /* size/bytes */
-        ECC_SECP256R1,                                                      /* ID         */
-        "SECP256R1",                                                        /* curve name */
-        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
-        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
-        "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B          */
-        "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* order      */
-        "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx         */
-        "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy         */
-		ecc_oid_secp256r1,                                                  /* oid/oidSz  */
-        ecc_oid_secp256r1_sz,
-        ECC_SECP256R1_OID,                                                  /* oid sum    */
-        1,                                                                  /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_KOBLITZ
-    {
-        32,                                                                 /* size/bytes */
-        ECC_SECP256K1,                                                      /* ID         */
-        "SECP256K1",                                                        /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* prime      */
-        "0000000000000000000000000000000000000000000000000000000000000000", /* A          */
-        "0000000000000000000000000000000000000000000000000000000000000007", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* order      */
-        "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gx         */
-        "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy         */
-        ecc_oid_secp256k1,                                                  /* oid/oidSz  */
-        ecc_oid_secp256k1_sz,
-        ECC_SECP256K1_OID,                                                  /* oid sum    */
-        1,                                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_KOBLITZ */
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        32,                                                                 /* size/bytes */
-        ECC_BRAINPOOLP256R1,                                                /* ID         */
-        "BRAINPOOLP256R1",                                                  /* curve name */
-        "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* prime      */
-        "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A          */
-        "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B          */
-        "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* order      */
-        "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gx         */
-        "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy         */
-        ecc_oid_brainpoolp256r1,                                            /* oid/oidSz  */
-        ecc_oid_brainpoolp256r1_sz,
-        ECC_BRAINPOOLP256R1_OID,                                            /* oid sum    */
-        1,                                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC256 */
-#ifdef ECC320
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        40,                                                                                 /* size/bytes */
-        ECC_BRAINPOOLP320R1,                                                                /* ID         */
-        "BRAINPOOLP320R1",                                                                  /* curve name */
-        "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* prime      */
-        "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", /* A          */
-        "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", /* B          */
-        "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* order      */
-        "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gx         */
-        "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* Gy         */
-        ecc_oid_brainpoolp320r1, ecc_oid_brainpoolp320r1_sz,                                /* oid/oidSz  */
-        ECC_BRAINPOOLP320R1_OID,                                                            /* oid sum    */
-        1,                                                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC320 */
-#ifdef ECC384
-    #ifndef NO_ECC_SECP
-    {
-        48,                                                                                                 /* size/bytes */
-        ECC_SECP384R1,                                                                                      /* ID         */
-        "SECP384R1",                                                                                        /* curve name */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* prime      */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* A          */
-        "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* B          */
-        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* order      */
-        "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx         */
-        "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy         */
-        ecc_oid_secp384r1, ecc_oid_secp384r1_sz,                                                            /* oid/oidSz  */
-        ECC_SECP384R1_OID,                                                                                  /* oid sum    */
-        1,                                                                                                  /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        48,                                                                                                 /* size/bytes */
-        ECC_BRAINPOOLP384R1,                                                                                /* ID         */
-        "BRAINPOOLP384R1",                                                                                  /* curve name */
-        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* prime      */
-        "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* A          */
-        "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* B          */
-        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* order      */
-        "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gx         */
-        "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* Gy         */
-        ecc_oid_brainpoolp384r1, ecc_oid_brainpoolp384r1_sz,                                                /* oid/oidSz  */
-        ECC_BRAINPOOLP384R1_OID,                                                                            /* oid sum    */
-        1,                                                                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC384 */
-#ifdef ECC512
-    #ifdef HAVE_ECC_BRAINPOOL
-    {
-        64,                                                                                                                                 /* size/bytes */
-        ECC_BRAINPOOLP512R1,                                                                                                                /* ID         */
-        "BRAINPOOLP512R1",                                                                                                                  /* curve name */
-        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* prime      */
-        "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* A          */
-        "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* B          */
-        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* order      */
-        "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gx         */
-        "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* Gy         */
-        ecc_oid_brainpoolp512r1, ecc_oid_brainpoolp512r1_sz,                                                                                /* oid/oidSz  */
-        ECC_BRAINPOOLP512R1_OID,                                                                                                            /* oid sum    */
-        1,                                                                                                                                  /* cofactor   */
-    },
-    #endif /* HAVE_ECC_BRAINPOOL */
-#endif /* ECC512 */
-#ifdef ECC521
-    #ifndef NO_ECC_SECP
-    {
-        66,                                                                                                                                    /* size/bytes */
-        ECC_SECP521R1,                                                                                                                         /* ID         */
-        "SECP521R1",                                                                                                                           /* curve name */
-        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* prime      */
-        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* A          */
-        "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",  /* B          */
-        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* order      */
-        "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",  /* Gx         */
-        "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy         */
-        ecc_oid_secp521r1, ecc_oid_secp521r1_sz,                                                                                               /* oid/oidSz  */
-        ECC_SECP521R1_OID,                                                                                                                     /* oid sum    */
-        1,                                                                                                                                     /* cofactor   */
-    },
-    #endif /* !NO_ECC_SECP */
-#endif /* ECC521 */
-#if defined(WOLFSSL_CUSTOM_CURVES) && defined(ECC_CACHE_CURVE)
-    /* place holder for custom curve index for cache */
-    {
-        1, /* non-zero */
-        ECC_CURVE_CUSTOM,
-        #ifndef USE_WINDOWS_API
-            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-        #else
-            0, 0, 0, 0, 0, 0, 0, 0,
-        #endif
-        0, 0, 0
-    },
-#endif
-    {
-        0, -1,
-        #ifndef USE_WINDOWS_API
-            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-        #else
-            0, 0, 0, 0, 0, 0, 0, 0,
-        #endif
-        0, 0, 0
-    }
-};
-#define ECC_SET_COUNT   (sizeof(ecc_sets)/sizeof(ecc_set_type))
-
-
-#ifdef HAVE_OID_ENCODING
-    /* encoded OID cache */
-    typedef struct {
-        word32 oidSz;
-        byte oid[ECC_MAX_OID_LEN];
-    } oid_cache_t;
-    static oid_cache_t ecc_oid_cache[ECC_SET_COUNT];
-#endif
-
-
-#ifdef HAVE_COMP_KEY
-static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
-#endif
-
-#ifdef WOLFSSL_ATECC508A
-    typedef void* ecc_curve_spec;
-#else
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
-static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
-        mp_int* prime, mp_int* order);
-#endif
-
-int mp_jacobi(mp_int* a, mp_int* n, int* c);
-int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
-
-
-/* Curve Specs */
-typedef struct ecc_curve_spec {
-    const ecc_set_type* dp;
-
-    mp_int* prime;
-    mp_int* Af;
-    #ifdef USE_ECC_B_PARAM
-        mp_int* Bf;
-    #endif
-    mp_int* order;
-    mp_int* Gx;
-    mp_int* Gy;
-
-#ifdef ECC_CACHE_CURVE
-    mp_int prime_lcl;
-    mp_int Af_lcl;
-    #ifdef USE_ECC_B_PARAM
-        mp_int Bf_lcl;
-    #endif
-    mp_int order_lcl;
-    mp_int Gx_lcl;
-    mp_int Gy_lcl;
-#else
-    mp_int* spec_ints;
-    word32 spec_count;
-    word32 spec_use;
-#endif
-
-    byte load_mask;
-} ecc_curve_spec;
-
-enum ecc_curve_load_mask {
-    ECC_CURVE_FIELD_NONE    = 0x00,
-    ECC_CURVE_FIELD_PRIME   = 0x01,
-    ECC_CURVE_FIELD_AF      = 0x02,
-#ifdef USE_ECC_B_PARAM
-    ECC_CURVE_FIELD_BF      = 0x04,
-#endif
-    ECC_CURVE_FIELD_ORDER   = 0x08,
-    ECC_CURVE_FIELD_GX      = 0x10,
-    ECC_CURVE_FIELD_GY      = 0x20,
-#ifdef USE_ECC_B_PARAM
-    ECC_CURVE_FIELD_ALL     = 0x3F,
-    ECC_CURVE_FIELD_COUNT   = 6,
-#else
-    ECC_CURVE_FIELD_ALL     = 0x3B,
-    ECC_CURVE_FIELD_COUNT   = 5,
-#endif
-};
-
-#ifdef ECC_CACHE_CURVE
-    /* cache (mp_int) of the curve parameters */
-    static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT];
-    #ifndef SINGLE_THREADED
-        static wolfSSL_Mutex ecc_curve_cache_mutex;
-    #endif
-
-    #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL
-    #define ALLOC_CURVE_SPECS(intcount)
-    #define FREE_CURVE_SPECS()
-#elif defined(WOLFSSL_SMALL_STACK)
-    #define DECLARE_CURVE_SPECS(curve, intcount)                        \
-        mp_int* spec_ints = NULL;                                       \
-        ecc_curve_spec curve_lcl;                                       \
-        ecc_curve_spec* curve = &curve_lcl;                             \
-        XMEMSET(curve, 0, sizeof(ecc_curve_spec));                      \
-        curve->spec_count = intcount
-
-    #define ALLOC_CURVE_SPECS(intcount)                                 \
-        spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \
-                            DYNAMIC_TYPE_ECC);                          \
-        if (spec_ints == NULL)                                          \
-            return MEMORY_E;                                            \
-        curve->spec_ints = spec_ints
-    #define FREE_CURVE_SPECS()                                          \
-        XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC)
-#else
-    #define DECLARE_CURVE_SPECS(curve, intcount) \
-        mp_int spec_ints[(intcount)]; \
-        ecc_curve_spec curve_lcl; \
-        ecc_curve_spec* curve = &curve_lcl; \
-        XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \
-        curve->spec_ints = spec_ints; \
-        curve->spec_count = intcount
-    #define ALLOC_CURVE_SPECS(intcount)
-    #define FREE_CURVE_SPECS()
-#endif /* ECC_CACHE_CURVE */
-
-static void _wc_ecc_curve_free(ecc_curve_spec* curve)
-{
-    if (curve == NULL) {
-        return;
-    }
-
-    if (curve->load_mask & ECC_CURVE_FIELD_PRIME)
-        mp_clear(curve->prime);
-    if (curve->load_mask & ECC_CURVE_FIELD_AF)
-        mp_clear(curve->Af);
-#ifdef USE_ECC_B_PARAM
-    if (curve->load_mask & ECC_CURVE_FIELD_BF)
-        mp_clear(curve->Bf);
-#endif
-    if (curve->load_mask & ECC_CURVE_FIELD_ORDER)
-        mp_clear(curve->order);
-    if (curve->load_mask & ECC_CURVE_FIELD_GX)
-        mp_clear(curve->Gx);
-    if (curve->load_mask & ECC_CURVE_FIELD_GY)
-        mp_clear(curve->Gy);
-
-    curve->load_mask = 0;
-}
-
-static void wc_ecc_curve_free(ecc_curve_spec* curve)
-{
-    /* don't free cached curves */
-#ifndef ECC_CACHE_CURVE
-    _wc_ecc_curve_free(curve);
-#endif
-    (void)curve;
-}
-
-static int wc_ecc_curve_load_item(const char* src, mp_int** dst,
-    ecc_curve_spec* curve, byte mask)
-{
-    int err;
-
-#ifndef ECC_CACHE_CURVE
-    /* get mp_int from temp */
-    if (curve->spec_use >= curve->spec_count) {
-        WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count");
-        return ECC_BAD_ARG_E;
-    }
-    *dst = &curve->spec_ints[curve->spec_use++];
-#endif
-
-    err = mp_init(*dst);
-    if (err == MP_OKAY) {
-        curve->load_mask |= mask;
-
-        err = mp_read_radix(*dst, src, MP_RADIX_HEX);
-
-    #ifdef HAVE_WOLF_BIGINT
-        if (err == MP_OKAY)
-            err = wc_mp_to_bigint(*dst, &(*dst)->raw);
-    #endif
-    }
-    return err;
-}
-
-static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
-    byte load_mask)
-{
-    int ret = 0, x;
-    ecc_curve_spec* curve;
-    byte load_items = 0; /* mask of items to load */
-
-    if (dp == NULL || pCurve == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef ECC_CACHE_CURVE
-    x = wc_ecc_get_curve_idx(dp->id);
-    if (x == ECC_CURVE_INVALID)
-        return ECC_BAD_ARG_E;
-
-#if !defined(SINGLE_THREADED)
-    ret = wc_LockMutex(&ecc_curve_cache_mutex);
-    if (ret != 0) {
-        return ret;
-    }
-#endif
-
-    /* make sure cache has been allocated */
-    if (ecc_curve_spec_cache[x] == NULL) {
-        ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC(
-            sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC);
-        if (ecc_curve_spec_cache[x] == NULL) {
-        #if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
-            wc_UnLockMutex(&ecc_curve_cache_mutex);
-        #endif
-            return MEMORY_E;
-        }
-        XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec));
-    }
-
-    /* set curve pointer to cache */
-    *pCurve = ecc_curve_spec_cache[x];
-
-#endif /* ECC_CACHE_CURVE */
-    curve = *pCurve;
-
-    /* make sure the curve is initialized */
-    if (curve->dp != dp) {
-        curve->load_mask = 0;
-
-    #ifdef ECC_CACHE_CURVE
-        curve->prime = &curve->prime_lcl;
-        curve->Af = &curve->Af_lcl;
-        #ifdef USE_ECC_B_PARAM
-            curve->Bf = &curve->Bf_lcl;
-        #endif
-        curve->order = &curve->order_lcl;
-        curve->Gx = &curve->Gx_lcl;
-        curve->Gy = &curve->Gy_lcl;
-    #endif
-    }
-    curve->dp = dp; /* set dp info */
-
-    /* determine items to load */
-    load_items = (((byte)~(word32)curve->load_mask) & load_mask);
-    curve->load_mask |= load_items;
-
-    /* load items */
-    x = 0;
-    if (load_items & ECC_CURVE_FIELD_PRIME)
-        x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve,
-            ECC_CURVE_FIELD_PRIME);
-    if (load_items & ECC_CURVE_FIELD_AF)
-        x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve,
-            ECC_CURVE_FIELD_AF);
-#ifdef USE_ECC_B_PARAM
-    if (load_items & ECC_CURVE_FIELD_BF)
-        x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve,
-            ECC_CURVE_FIELD_BF);
-#endif
-    if (load_items & ECC_CURVE_FIELD_ORDER)
-        x += wc_ecc_curve_load_item(dp->order, &curve->order, curve,
-            ECC_CURVE_FIELD_ORDER);
-    if (load_items & ECC_CURVE_FIELD_GX)
-        x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve,
-            ECC_CURVE_FIELD_GX);
-    if (load_items & ECC_CURVE_FIELD_GY)
-        x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve,
-            ECC_CURVE_FIELD_GY);
-
-    /* check for error */
-    if (x != 0) {
-        wc_ecc_curve_free(curve);
-        ret = MP_READ_E;
-    }
-
-#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
-    wc_UnLockMutex(&ecc_curve_cache_mutex);
-#endif
-
-    return ret;
-}
-
-#ifdef ECC_CACHE_CURVE
-int wc_ecc_curve_cache_init(void)
-{
-    int ret = 0;
-#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
-    ret = wc_InitMutex(&ecc_curve_cache_mutex);
-#endif
-    return ret;
-}
-
-void wc_ecc_curve_cache_free(void)
-{
-    int x;
-
-    /* free all ECC curve caches */
-    for (x = 0; x < (int)ECC_SET_COUNT; x++) {
-        if (ecc_curve_spec_cache[x]) {
-            _wc_ecc_curve_free(ecc_curve_spec_cache[x]);
-            XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC);
-            ecc_curve_spec_cache[x] = NULL;
-        }
-    }
-
-#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED)
-    wc_FreeMutex(&ecc_curve_cache_mutex);
-#endif
-}
-#endif /* ECC_CACHE_CURVE */
-
-#endif /* WOLFSSL_ATECC508A */
-
-
-/* Retrieve the curve name for the ECC curve id.
- *
- * curve_id  The id of the curve.
- * returns the name stored from the curve if available, otherwise NULL.
- */
-const char* wc_ecc_get_name(int curve_id)
-{
-    int curve_idx = wc_ecc_get_curve_idx(curve_id);
-    if (curve_idx == ECC_CURVE_INVALID)
-        return NULL;
-    return ecc_sets[curve_idx].name;
-}
-
-int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id)
-{
-    if (keysize <= 0 && curve_id < 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (keysize > ECC_MAXSIZE) {
-        return ECC_BAD_ARG_E;
-    }
-
-    /* handle custom case */
-    if (key->idx != ECC_CUSTOM_IDX) {
-        int x;
-
-        /* default values */
-        key->idx = 0;
-        key->dp = NULL;
-
-        /* find ecc_set based on curve_id or key size */
-        for (x = 0; ecc_sets[x].size != 0; x++) {
-            if (curve_id > ECC_CURVE_DEF) {
-                if (curve_id == ecc_sets[x].id)
-                  break;
-            }
-            else if (keysize <= ecc_sets[x].size) {
-                break;
-            }
-        }
-        if (ecc_sets[x].size == 0) {
-            WOLFSSL_MSG("ECC Curve not found");
-            return ECC_CURVE_OID_E;
-        }
-
-        key->idx = x;
-        key->dp  = &ecc_sets[x];
-    }
-
-    return 0;
-}
-
-
-#ifdef ALT_ECC_SIZE
-static void alt_fp_init(fp_int* a)
-{
-    a->size = FP_SIZE_ECC;
-    fp_zero(a);
-}
-#endif /* ALT_ECC_SIZE */
-
-
-#ifndef WOLFSSL_ATECC508A
-
-#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)
-
-/**
-   Add two ECC points
-   P        The point to add
-   Q        The point to add
-   R        [out] The destination of the double
-   a        ECC curve parameter a
-   modulus  The modulus of the field the ECC curve is in
-   mp       The "b" value from montgomery_setup()
-   return   MP_OKAY on success
-*/
-int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
-                             mp_int* a, mp_int* modulus, mp_digit mp)
-{
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int* t1 = NULL;
-   mp_int* t2 = NULL;
-#ifdef ALT_ECC_SIZE
-   mp_int* rx = NULL;
-   mp_int* ry = NULL;
-   mp_int* rz = NULL;
-#endif
-#else
-   mp_int  t1[1], t2[1];
-#ifdef ALT_ECC_SIZE
-   mp_int  rx[1], ry[1], rz[1];
-#endif
-#endif
-   mp_int  *x, *y, *z;
-   int     err;
-
-   if (P == NULL || Q == NULL || R == NULL || modulus == NULL) {
-       return ECC_BAD_ARG_E;
-   }
-
-   /* if Q == R then swap P and Q, so we don't require a local x,y,z */
-   if (Q == R) {
-      ecc_point* tPt  = P;
-      P = Q;
-      Q = tPt;
-   }
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (R->key != NULL) {
-       t1 = R->key->t1;
-       t2 = R->key->t2;
-#ifdef ALT_ECC_SIZE
-       rx = R->key->x;
-       ry = R->key->y;
-       rz = R->key->z;
-#endif
-   }
-   else
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-   {
-       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (t1 == NULL || t2 == NULL) {
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-#ifdef ALT_ECC_SIZE
-       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (rx == NULL || ry == NULL || rz == NULL) {
-           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-#endif
-   }
-#endif /* WOLFSSL_SMALL_STACK */
-
-   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK
-   #ifdef WOLFSSL_SMALL_STACK_CACHE
-       if (R->key == NULL)
-   #endif
-       {
-       #ifdef ALT_ECC_SIZE
-          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-       #endif
-          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-       }
-#endif
-      return err;
-   }
-
-   /* should we dbl instead? */
-   if (err == MP_OKAY)
-       err = mp_sub(modulus, Q->y, t1);
-   if (err == MP_OKAY) {
-       if ( (mp_cmp(P->x, Q->x) == MP_EQ) &&
-            (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) &&
-            (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) {
-           mp_clear(t1);
-           mp_clear(t2);
-    #ifdef WOLFSSL_SMALL_STACK
-       #ifdef WOLFSSL_SMALL_STACK_CACHE
-           if (R->key == NULL)
-       #endif
-           {
-            #ifdef ALT_ECC_SIZE
-               XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-               XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-               XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-            #endif
-               XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-               XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           }
-        #endif
-          return ecc_projective_dbl_point(P, R, a, modulus, mp);
-       }
-   }
-
-   if (err != MP_OKAY) {
-      goto done;
-   }
-
-/* If use ALT_ECC_SIZE we need to use local stack variable since
-   ecc_point x,y,z is reduced size */
-#ifdef ALT_ECC_SIZE
-   /* Use local stack variable */
-   x = rx;
-   y = ry;
-   z = rz;
-
-   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
-      goto done;
-   }
-#else
-   /* Use destination directly */
-   x = R->x;
-   y = R->y;
-   z = R->z;
-#endif
-
-   if (err == MP_OKAY)
-       err = mp_copy(P->x, x);
-   if (err == MP_OKAY)
-       err = mp_copy(P->y, y);
-   if (err == MP_OKAY)
-       err = mp_copy(P->z, z);
-
-   /* if Z is one then these are no-operations */
-   if (err == MP_OKAY) {
-       if (!mp_iszero(Q->z)) {
-           /* T1 = Z' * Z' */
-           err = mp_sqr(Q->z, t1);
-           if (err == MP_OKAY)
-               err = mp_montgomery_reduce(t1, modulus, mp);
-
-           /* X = X * T1 */
-           if (err == MP_OKAY)
-               err = mp_mul(t1, x, x);
-           if (err == MP_OKAY)
-               err = mp_montgomery_reduce(x, modulus, mp);
-
-           /* T1 = Z' * T1 */
-           if (err == MP_OKAY)
-               err = mp_mul(Q->z, t1, t1);
-           if (err == MP_OKAY)
-               err = mp_montgomery_reduce(t1, modulus, mp);
-
-           /* Y = Y * T1 */
-           if (err == MP_OKAY)
-               err = mp_mul(t1, y, y);
-           if (err == MP_OKAY)
-               err = mp_montgomery_reduce(y, modulus, mp);
-       }
-   }
-
-   /* T1 = Z*Z */
-   if (err == MP_OKAY)
-       err = mp_sqr(z, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* T2 = X' * T1 */
-   if (err == MP_OKAY)
-       err = mp_mul(Q->x, t1, t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t2, modulus, mp);
-
-   /* T1 = Z * T1 */
-   if (err == MP_OKAY)
-       err = mp_mul(z, t1, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* T1 = Y' * T1 */
-   if (err == MP_OKAY)
-       err = mp_mul(Q->y, t1, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* Y = Y - T1 */
-   if (err == MP_OKAY)
-       err = mp_sub(y, t1, y);
-   if (err == MP_OKAY) {
-       if (mp_isneg(y))
-           err = mp_add(y, modulus, y);
-   }
-   /* T1 = 2T1 */
-   if (err == MP_OKAY)
-       err = mp_add(t1, t1, t1);
-   if (err == MP_OKAY) {
-       if (mp_cmp(t1, modulus) != MP_LT)
-           err = mp_sub(t1, modulus, t1);
-   }
-   /* T1 = Y + T1 */
-   if (err == MP_OKAY)
-       err = mp_add(t1, y, t1);
-   if (err == MP_OKAY) {
-       if (mp_cmp(t1, modulus) != MP_LT)
-           err = mp_sub(t1, modulus, t1);
-   }
-   /* X = X - T2 */
-   if (err == MP_OKAY)
-       err = mp_sub(x, t2, x);
-   if (err == MP_OKAY) {
-       if (mp_isneg(x))
-           err = mp_add(x, modulus, x);
-   }
-   /* T2 = 2T2 */
-   if (err == MP_OKAY)
-       err = mp_add(t2, t2, t2);
-   if (err == MP_OKAY) {
-       if (mp_cmp(t2, modulus) != MP_LT)
-           err = mp_sub(t2, modulus, t2);
-   }
-   /* T2 = X + T2 */
-   if (err == MP_OKAY)
-       err = mp_add(t2, x, t2);
-   if (err == MP_OKAY) {
-       if (mp_cmp(t2, modulus) != MP_LT)
-           err = mp_sub(t2, modulus, t2);
-   }
-
-   if (err == MP_OKAY) {
-       if (!mp_iszero(Q->z)) {
-           /* Z = Z * Z' */
-           err = mp_mul(z, Q->z, z);
-           if (err == MP_OKAY)
-               err = mp_montgomery_reduce(z, modulus, mp);
-       }
-   }
-
-   /* Z = Z * X */
-   if (err == MP_OKAY)
-       err = mp_mul(z, x, z);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(z, modulus, mp);
-
-   /* T1 = T1 * X  */
-   if (err == MP_OKAY)
-       err = mp_mul(t1, x, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* X = X * X */
-   if (err == MP_OKAY)
-       err = mp_sqr(x, x);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(x, modulus, mp);
-
-   /* T2 = T2 * x */
-   if (err == MP_OKAY)
-       err = mp_mul(t2, x, t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t2, modulus, mp);
-
-   /* T1 = T1 * X  */
-   if (err == MP_OKAY)
-       err = mp_mul(t1, x, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* X = Y*Y */
-   if (err == MP_OKAY)
-       err = mp_sqr(y, x);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(x, modulus, mp);
-
-   /* X = X - T2 */
-   if (err == MP_OKAY)
-       err = mp_sub(x, t2, x);
-   if (err == MP_OKAY) {
-       if (mp_isneg(x))
-           err = mp_add(x, modulus, x);
-   }
-   /* T2 = T2 - X */
-   if (err == MP_OKAY)
-       err = mp_sub(t2, x, t2);
-   if (err == MP_OKAY) {
-       if (mp_isneg(t2))
-           err = mp_add(t2, modulus, t2);
-   }
-   /* T2 = T2 - X */
-   if (err == MP_OKAY)
-       err = mp_sub(t2, x, t2);
-   if (err == MP_OKAY) {
-       if (mp_isneg(t2))
-           err = mp_add(t2, modulus, t2);
-   }
-   /* T2 = T2 * Y */
-   if (err == MP_OKAY)
-       err = mp_mul(t2, y, t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t2, modulus, mp);
-
-   /* Y = T2 - T1 */
-   if (err == MP_OKAY)
-       err = mp_sub(t2, t1, y);
-   if (err == MP_OKAY) {
-       if (mp_isneg(y))
-           err = mp_add(y, modulus, y);
-   }
-   /* Y = Y/2 */
-   if (err == MP_OKAY) {
-       if (mp_isodd(y) == MP_YES)
-           err = mp_add(y, modulus, y);
-   }
-   if (err == MP_OKAY)
-       err = mp_div_2(y, y);
-
-#ifdef ALT_ECC_SIZE
-   if (err == MP_OKAY)
-       err = mp_copy(x, R->x);
-   if (err == MP_OKAY)
-       err = mp_copy(y, R->y);
-   if (err == MP_OKAY)
-       err = mp_copy(z, R->z);
-#endif
-
-done:
-
-   /* clean up */
-   mp_clear(t1);
-   mp_clear(t2);
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (R->key == NULL)
-#endif
-   {
-   #ifdef ALT_ECC_SIZE
-      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-   #endif
-      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-   }
-#endif
-
-   return err;
-#else
-    if (P == NULL || Q == NULL || R == NULL || modulus == NULL) {
-        return ECC_BAD_ARG_E;
-    }
-
-    (void)a;
-    (void)mp;
-
-    return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z,
-                                     R->x, R->y, R->z);
-#endif
-}
-
-/* ### Point doubling in Jacobian coordinate system ###
- *
- * let us have a curve:                 y^2 = x^3 + a*x + b
- * in Jacobian coordinates it becomes:  y^2 = x^3 + a*x*z^4 + b*z^6
- *
- * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where:
- * Xr = M^2 - 2*S
- * Yr = M * (S - Xr) - 8*T
- * Zr = 2 * Yp * Zp
- *
- * M = 3 * Xp^2 + a*Zp^4
- * T = Yp^4
- * S = 4 * Xp * Yp^2
- *
- * SPECIAL CASE: when a == 3 we can compute M as
- * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2)
- */
-
-/**
-   Double an ECC point
-   P   The point to double
-   R   [out] The destination of the double
-   a   ECC curve parameter a
-   modulus  The modulus of the field the ECC curve is in
-   mp       The "b" value from montgomery_setup()
-   return   MP_OKAY on success
-*/
-int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a,
-                                       mp_int* modulus, mp_digit mp)
-{
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int* t1 = NULL;
-   mp_int* t2 = NULL;
-#ifdef ALT_ECC_SIZE
-   mp_int* rx = NULL;
-   mp_int* ry = NULL;
-   mp_int* rz = NULL;
-#endif
-#else
-   mp_int  t1[1], t2[1];
-#ifdef ALT_ECC_SIZE
-   mp_int  rx[1], ry[1], rz[1];
-#endif
-#endif
-   mp_int *x, *y, *z;
-   int    err;
-
-   if (P == NULL || R == NULL || modulus == NULL)
-       return ECC_BAD_ARG_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (R->key != NULL) {
-       t1 = R->key->t1;
-       t2 = R->key->t2;
-   #ifdef ALT_ECC_SIZE
-       rx = R->key->x;
-       ry = R->key->y;
-       rz = R->key->z;
-   #endif
-   }
-   else
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-   {
-       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (t1 == NULL || t2 == NULL) {
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-    #ifdef ALT_ECC_SIZE
-       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (rx == NULL || ry == NULL || rz == NULL) {
-           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-    #endif
-    }
-#endif
-
-   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    if (R->key == NULL)
-#endif
-    {
-    #ifdef ALT_ECC_SIZE
-       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-     }
-#endif
-      return err;
-   }
-
-/* If use ALT_ECC_SIZE we need to use local stack variable since
-   ecc_point x,y,z is reduced size */
-#ifdef ALT_ECC_SIZE
-   /* Use local stack variable */
-   x = rx;
-   y = ry;
-   z = rz;
-
-   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
-       mp_clear(t1);
-       mp_clear(t2);
-    #ifdef WOLFSSL_SMALL_STACK
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-       if (R->key == NULL)
-    #endif
-       {
-       #ifdef ALT_ECC_SIZE
-          XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-       #endif
-          XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-          XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-       }
-    #endif
-       return err;
-   }
-#else
-   /* Use destination directly */
-   x = R->x;
-   y = R->y;
-   z = R->z;
-#endif
-
-   if (err == MP_OKAY)
-       err = mp_copy(P->x, x);
-   if (err == MP_OKAY)
-       err = mp_copy(P->y, y);
-   if (err == MP_OKAY)
-       err = mp_copy(P->z, z);
-
-   /* T1 = Z * Z */
-   if (err == MP_OKAY)
-       err = mp_sqr(z, t1);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t1, modulus, mp);
-
-   /* Z = Y * Z */
-   if (err == MP_OKAY)
-       err = mp_mul(z, y, z);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(z, modulus, mp);
-
-   /* Z = 2Z */
-   if (err == MP_OKAY)
-       err = mp_add(z, z, z);
-   if (err == MP_OKAY) {
-       if (mp_cmp(z, modulus) != MP_LT)
-           err = mp_sub(z, modulus, z);
-   }
-
-   /* Determine if curve "a" should be used in calc */
-#ifdef WOLFSSL_CUSTOM_CURVES
-   if (err == MP_OKAY) {
-      /* Use a and prime to determine if a == 3 */
-      err = mp_submod(modulus, a, modulus, t2);
-   }
-   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
-      /* use "a" in calc */
-
-      /* T2 = T1 * T1 */
-      if (err == MP_OKAY)
-          err = mp_sqr(t1, t2);
-      if (err == MP_OKAY)
-          err = mp_montgomery_reduce(t2, modulus, mp);
-      /* T1 = T2 * a */
-      if (err == MP_OKAY)
-          err = mp_mulmod(t2, a, modulus, t1);
-      /* T2 = X * X */
-      if (err == MP_OKAY)
-          err = mp_sqr(x, t2);
-      if (err == MP_OKAY)
-          err = mp_montgomery_reduce(t2, modulus, mp);
-      /* T1 = T2 + T1 */
-      if (err == MP_OKAY)
-          err = mp_add(t1, t2, t1);
-      if (err == MP_OKAY) {
-         if (mp_cmp(t1, modulus) != MP_LT)
-            err = mp_sub(t1, modulus, t1);
-      }
-      /* T1 = T2 + T1 */
-      if (err == MP_OKAY)
-          err = mp_add(t1, t2, t1);
-      if (err == MP_OKAY) {
-          if (mp_cmp(t1, modulus) != MP_LT)
-              err = mp_sub(t1, modulus, t1);
-      }
-      /* T1 = T2 + T1 */
-      if (err == MP_OKAY)
-          err = mp_add(t1, t2, t1);
-      if (err == MP_OKAY) {
-         if (mp_cmp(t1, modulus) != MP_LT)
-            err = mp_sub(t1, modulus, t1);
-      }
-   }
-   else
-#endif /* WOLFSSL_CUSTOM_CURVES */
-   {
-      /* assumes "a" == 3 */
-      (void)a;
-
-      /* T2 = X - T1 */
-      if (err == MP_OKAY)
-          err = mp_sub(x, t1, t2);
-      if (err == MP_OKAY) {
-          if (mp_isneg(t2))
-              err = mp_add(t2, modulus, t2);
-      }
-      /* T1 = X + T1 */
-      if (err == MP_OKAY)
-          err = mp_add(t1, x, t1);
-      if (err == MP_OKAY) {
-          if (mp_cmp(t1, modulus) != MP_LT)
-              err = mp_sub(t1, modulus, t1);
-      }
-      /* T2 = T1 * T2 */
-      if (err == MP_OKAY)
-          err = mp_mul(t1, t2, t2);
-      if (err == MP_OKAY)
-          err = mp_montgomery_reduce(t2, modulus, mp);
-
-      /* T1 = 2T2 */
-      if (err == MP_OKAY)
-          err = mp_add(t2, t2, t1);
-      if (err == MP_OKAY) {
-          if (mp_cmp(t1, modulus) != MP_LT)
-              err = mp_sub(t1, modulus, t1);
-      }
-      /* T1 = T1 + T2 */
-      if (err == MP_OKAY)
-          err = mp_add(t1, t2, t1);
-      if (err == MP_OKAY) {
-          if (mp_cmp(t1, modulus) != MP_LT)
-              err = mp_sub(t1, modulus, t1);
-      }
-   }
-
-   /* Y = 2Y */
-   if (err == MP_OKAY)
-       err = mp_add(y, y, y);
-   if (err == MP_OKAY) {
-       if (mp_cmp(y, modulus) != MP_LT)
-           err = mp_sub(y, modulus, y);
-   }
-   /* Y = Y * Y */
-   if (err == MP_OKAY)
-       err = mp_sqr(y, y);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(y, modulus, mp);
-
-   /* T2 = Y * Y */
-   if (err == MP_OKAY)
-       err = mp_sqr(y, t2);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(t2, modulus, mp);
-
-   /* T2 = T2/2 */
-   if (err == MP_OKAY) {
-       if (mp_isodd(t2) == MP_YES)
-           err = mp_add(t2, modulus, t2);
-   }
-   if (err == MP_OKAY)
-       err = mp_div_2(t2, t2);
-
-   /* Y = Y * X */
-   if (err == MP_OKAY)
-       err = mp_mul(y, x, y);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(y, modulus, mp);
-
-   /* X = T1 * T1 */
-   if (err == MP_OKAY)
-       err = mp_sqr(t1, x);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(x, modulus, mp);
-
-   /* X = X - Y */
-   if (err == MP_OKAY)
-       err = mp_sub(x, y, x);
-   if (err == MP_OKAY) {
-       if (mp_isneg(x))
-           err = mp_add(x, modulus, x);
-   }
-   /* X = X - Y */
-   if (err == MP_OKAY)
-       err = mp_sub(x, y, x);
-   if (err == MP_OKAY) {
-       if (mp_isneg(x))
-           err = mp_add(x, modulus, x);
-   }
-
-   /* Y = Y - X */
-   if (err == MP_OKAY)
-       err = mp_sub(y, x, y);
-   if (err == MP_OKAY) {
-       if (mp_isneg(y))
-           err = mp_add(y, modulus, y);
-   }
-   /* Y = Y * T1 */
-   if (err == MP_OKAY)
-       err = mp_mul(y, t1, y);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(y, modulus, mp);
-
-   /* Y = Y - T2 */
-   if (err == MP_OKAY)
-       err = mp_sub(y, t2, y);
-   if (err == MP_OKAY) {
-       if (mp_isneg(y))
-           err = mp_add(y, modulus, y);
-   }
-
-#ifdef ALT_ECC_SIZE
-   if (err == MP_OKAY)
-       err = mp_copy(x, R->x);
-   if (err == MP_OKAY)
-       err = mp_copy(y, R->y);
-   if (err == MP_OKAY)
-       err = mp_copy(z, R->z);
-#endif
-
-   /* clean up */
-   mp_clear(t1);
-   mp_clear(t2);
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (R->key == NULL)
-#endif
-   {
-    #ifdef ALT_ECC_SIZE
-       XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-       XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-    }
-#endif
-
-   return err;
-#else
-    if (P == NULL || R == NULL || modulus == NULL)
-        return ECC_BAD_ARG_E;
-
-    (void)a;
-    (void)mp;
-
-    return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z);
-#endif
-}
-
-
-/**
-  Map a projective jacbobian point back to affine space
-  P        [in/out] The point to map
-  modulus  The modulus of the field the ECC curve is in
-  mp       The "b" value from montgomery_setup()
-  return   MP_OKAY on success
-*/
-int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
-{
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int* t1 = NULL;
-   mp_int* t2 = NULL;
-#ifdef ALT_ECC_SIZE
-   mp_int* rx = NULL;
-   mp_int* ry = NULL;
-   mp_int* rz = NULL;
-#endif
-#else
-   mp_int  t1[1], t2[1];
-#ifdef ALT_ECC_SIZE
-   mp_int  rx[1], ry[1], rz[1];
-#endif
-#endif /* WOLFSSL_SMALL_STACK */
-   mp_int *x, *y, *z;
-   int    err;
-
-   if (P == NULL || modulus == NULL)
-       return ECC_BAD_ARG_E;
-
-   /* special case for point at infinity */
-   if (mp_cmp_d(P->z, 0) == MP_EQ) {
-       err = mp_set(P->x, 0);
-       if (err == MP_OKAY)
-           err = mp_set(P->y, 0);
-       if (err == MP_OKAY)
-           err = mp_set(P->z, 1);
-       return err;
-   }
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (P->key != NULL) {
-       t1 = P->key->t1;
-       t2 = P->key->t2;
-   #ifdef ALT_ECC_SIZE
-       rx = P->key->x;
-       ry = P->key->y;
-       rz = P->key->z;
-   #endif
-   }
-   else
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-   {
-       t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (t1 == NULL || t2 == NULL) {
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-#ifdef ALT_ECC_SIZE
-       rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-       if (rx == NULL || ry == NULL || rz == NULL) {
-           XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-           XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-           return MEMORY_E;
-       }
-#endif
-   }
-#endif /* WOLFSSL_SMALL_STACK */
-
-   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-      if (P->key == NULL)
-#endif
-      {
-      #ifdef ALT_ECC_SIZE
-         XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-         XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-         XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-      #endif
-         XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-         XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-      }
-#endif
-      return MEMORY_E;
-   }
-
-#ifdef ALT_ECC_SIZE
-   /* Use local stack variable */
-   x = rx;
-   y = ry;
-   z = rz;
-
-   if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) {
-       goto done;
-   }
-
-   if (err == MP_OKAY)
-       err = mp_copy(P->x, x);
-   if (err == MP_OKAY)
-       err = mp_copy(P->y, y);
-   if (err == MP_OKAY)
-       err = mp_copy(P->z, z);
-
-   if (err != MP_OKAY) {
-      goto done;
-   }
-#else
-   /* Use destination directly */
-   x = P->x;
-   y = P->y;
-   z = P->z;
-#endif
-
-   /* first map z back to normal */
-   err = mp_montgomery_reduce(z, modulus, mp);
-
-   /* get 1/z */
-   if (err == MP_OKAY)
-       err = mp_invmod(z, modulus, t1);
-
-   /* get 1/z^2 and 1/z^3 */
-   if (err == MP_OKAY)
-       err = mp_sqr(t1, t2);
-   if (err == MP_OKAY)
-       err = mp_mod(t2, modulus, t2);
-   if (err == MP_OKAY)
-       err = mp_mul(t1, t2, t1);
-   if (err == MP_OKAY)
-       err = mp_mod(t1, modulus, t1);
-
-   /* multiply against x/y */
-   if (err == MP_OKAY)
-       err = mp_mul(x, t2, x);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(x, modulus, mp);
-   if (err == MP_OKAY)
-       err = mp_mul(y, t1, y);
-   if (err == MP_OKAY)
-       err = mp_montgomery_reduce(y, modulus, mp);
-
-   if (err == MP_OKAY)
-       err = mp_set(z, 1);
-
-#ifdef ALT_ECC_SIZE
-   /* return result */
-   if (err == MP_OKAY)
-      err = mp_copy(x, P->x);
-   if (err == MP_OKAY)
-      err = mp_copy(y, P->y);
-   if (err == MP_OKAY)
-      err = mp_copy(z, P->z);
-
-done:
-#endif
-
-   /* clean up */
-   mp_clear(t1);
-   mp_clear(t2);
-
-#ifdef WOLFSSL_SMALL_STACK
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   if (P->key == NULL)
-#endif
-   {
-   #ifdef ALT_ECC_SIZE
-      XFREE(rz, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(ry, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(rx, NULL, DYNAMIC_TYPE_ECC);
-   #endif
-      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-   }
-#endif
-
-   return err;
-#else
-    if (P == NULL || modulus == NULL)
-        return ECC_BAD_ARG_E;
-
-    (void)mp;
-
-    return sp_ecc_map_256(P->x, P->y, P->z);
-#endif
-}
-
-#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */
-
-#if !defined(FREESCALE_LTC_ECC)
-
-#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH)
-/**
-   Perform a point multiplication
-   k    The scalar to multiply by
-   G    The base point
-   R    [out] Destination for kG
-   a    ECC curve parameter a
-   modulus  The modulus of the field the ECC curve is in
-   map      Boolean whether to map back to affine or not
-                (1==map, 0 == leave in projective)
-   return MP_OKAY on success
-*/
-#ifdef FP_ECC
-static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
-                  mp_int* a, mp_int* modulus, int map,
-                  void* heap)
-#else
-int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
-                  mp_int* a, mp_int* modulus, int map,
-                  void* heap)
-#endif
-{
-#ifndef WOLFSSL_SP_MATH
-#ifndef ECC_TIMING_RESISTANT
-   /* size of sliding window, don't change this! */
-   #define WINSIZE  4
-   #define M_POINTS 8
-   int           first = 1, bitbuf = 0, bitcpy = 0, j;
-#else
-   #define M_POINTS 3
-#endif
-
-   ecc_point     *tG, *M[M_POINTS];
-   int           i, err;
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int*       mu = NULL;
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   ecc_key       key;
-#endif
-#else
-   mp_int        mu[1];
-#endif
-   mp_digit      mp;
-   mp_digit      buf;
-   int           bitcnt = 0, mode = 0, digidx = 0;
-
-   if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
-       return ECC_BAD_ARG_E;
-   }
-
-   /* init variables */
-   tG = NULL;
-   XMEMSET(M, 0, sizeof(M));
-#ifdef WOLFSSL_SMALL_STACK
-   mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-   if (mu == NULL)
-       return MEMORY_E;
-#endif
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-   key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-#ifdef ALT_ECC_SIZE
-   key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-   key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-   key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-#endif
-   if (key.t1 == NULL || key.t2 == NULL
-#ifdef ALT_ECC_SIZE
-      || key.x == NULL || key.y == NULL || key.z == NULL
-#endif
-   ) {
-#ifdef ALT_ECC_SIZE
-       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-       return MEMORY_E;
-   }
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-
-   /* init montgomery reduction */
-   if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-#ifdef ALT_ECC_SIZE
-       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-#ifdef WOLFSSL_SMALL_STACK
-       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-#endif
-       return err;
-   }
-
-   if ((err = mp_init(mu)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-#ifdef ALT_ECC_SIZE
-       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-#ifdef WOLFSSL_SMALL_STACK
-       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-#endif
-       return err;
-   }
-   if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) {
-       mp_clear(mu);
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-#ifdef ALT_ECC_SIZE
-       XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-       XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-       XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-#ifdef WOLFSSL_SMALL_STACK
-       XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-#endif
-       return err;
-   }
-
-  /* alloc ram for window temps */
-  for (i = 0; i < M_POINTS; i++) {
-      M[i] = wc_ecc_new_point_h(heap);
-      if (M[i] == NULL) {
-         mp_clear(mu);
-         err = MEMORY_E; goto exit;
-      }
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-      M[i]->key = &key;
-#endif
-  }
-
-   /* make a copy of G in case R==G */
-   tG = wc_ecc_new_point_h(heap);
-   if (tG == NULL)
-       err = MEMORY_E;
-
-   /* tG = G  and convert to montgomery */
-   if (err == MP_OKAY) {
-       if (mp_cmp_d(mu, 1) == MP_EQ) {
-           err = mp_copy(G->x, tG->x);
-           if (err == MP_OKAY)
-               err = mp_copy(G->y, tG->y);
-           if (err == MP_OKAY)
-               err = mp_copy(G->z, tG->z);
-       } else {
-           err = mp_mulmod(G->x, mu, modulus, tG->x);
-           if (err == MP_OKAY)
-               err = mp_mulmod(G->y, mu, modulus, tG->y);
-           if (err == MP_OKAY)
-               err = mp_mulmod(G->z, mu, modulus, tG->z);
-       }
-   }
-
-   /* done with mu */
-   mp_clear(mu);
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   R->key = &key;
-#endif
-#ifndef ECC_TIMING_RESISTANT
-
-   /* calc the M tab, which holds kG for k==8..15 */
-   /* M[0] == 8G */
-   if (err == MP_OKAY)
-       err = ecc_projective_dbl_point(tG, M[0], a, modulus, mp);
-   if (err == MP_OKAY)
-       err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp);
-   if (err == MP_OKAY)
-       err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp);
-
-   /* now find (8+k)G for k=1..7 */
-   if (err == MP_OKAY)
-       for (j = 9; j < 16; j++) {
-           err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a,
-                                                                modulus, mp);
-           if (err != MP_OKAY) break;
-       }
-
-   /* setup sliding window */
-   if (err == MP_OKAY) {
-       mode   = 0;
-       bitcnt = 1;
-       buf    = 0;
-       digidx = get_digit_count(k) - 1;
-       bitcpy = bitbuf = 0;
-       first  = 1;
-
-       /* perform ops */
-       for (;;) {
-           /* grab next digit as required */
-           if (--bitcnt == 0) {
-               if (digidx == -1) {
-                   break;
-               }
-               buf    = get_digit(k, digidx);
-               bitcnt = (int) DIGIT_BIT;
-               --digidx;
-           }
-
-           /* grab the next msb from the ltiplicand */
-           i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
-           buf <<= 1;
-
-           /* skip leading zero bits */
-           if (mode == 0 && i == 0)
-               continue;
-
-           /* if the bit is zero and mode == 1 then we double */
-           if (mode == 1 && i == 0) {
-               err = ecc_projective_dbl_point(R, R, a, modulus, mp);
-               if (err != MP_OKAY) break;
-               continue;
-           }
-
-           /* else we add it to the window */
-           bitbuf |= (i << (WINSIZE - ++bitcpy));
-           mode = 2;
-
-           if (bitcpy == WINSIZE) {
-               /* if this is the first window we do a simple copy */
-               if (first == 1) {
-                   /* R = kG [k = first window] */
-                   err = mp_copy(M[bitbuf-M_POINTS]->x, R->x);
-                   if (err != MP_OKAY) break;
-
-                   err = mp_copy(M[bitbuf-M_POINTS]->y, R->y);
-                   if (err != MP_OKAY) break;
-
-                   err = mp_copy(M[bitbuf-M_POINTS]->z, R->z);
-                   first = 0;
-               } else {
-                   /* normal window */
-                   /* ok window is filled so double as required and add  */
-                   /* double first */
-                   for (j = 0; j < WINSIZE; j++) {
-                       err = ecc_projective_dbl_point(R, R, a, modulus, mp);
-                       if (err != MP_OKAY) break;
-                   }
-                   if (err != MP_OKAY) break;  /* out of first for(;;) */
-
-                   /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
-                   err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a,
-                                                               modulus, mp);
-               }
-               if (err != MP_OKAY) break;
-               /* empty window and reset */
-               bitcpy = bitbuf = 0;
-               mode = 1;
-           }
-       }
-   }
-
-   /* if bits remain then double/add */
-   if (err == MP_OKAY) {
-       if (mode == 2 && bitcpy > 0) {
-           /* double then add */
-           for (j = 0; j < bitcpy; j++) {
-               /* only double if we have had at least one add first */
-               if (first == 0) {
-                   err = ecc_projective_dbl_point(R, R, a, modulus, mp);
-                   if (err != MP_OKAY) break;
-               }
-
-               bitbuf <<= 1;
-               if ((bitbuf & (1 << WINSIZE)) != 0) {
-                   if (first == 1) {
-                       /* first add, so copy */
-                       err = mp_copy(tG->x, R->x);
-                       if (err != MP_OKAY) break;
-
-                       err = mp_copy(tG->y, R->y);
-                       if (err != MP_OKAY) break;
-
-                       err = mp_copy(tG->z, R->z);
-                       if (err != MP_OKAY) break;
-                       first = 0;
-                   } else {
-                       /* then add */
-                       err = ecc_projective_add_point(R, tG, R, a, modulus,
-                                                                       mp);
-                       if (err != MP_OKAY) break;
-                   }
-               }
-           }
-       }
-   }
-
-   #undef WINSIZE
-
-#else /* ECC_TIMING_RESISTANT */
-
-   /* calc the M tab */
-   /* M[0] == G */
-   if (err == MP_OKAY)
-       err = mp_copy(tG->x, M[0]->x);
-   if (err == MP_OKAY)
-       err = mp_copy(tG->y, M[0]->y);
-   if (err == MP_OKAY)
-       err = mp_copy(tG->z, M[0]->z);
-
-   /* M[1] == 2G */
-   if (err == MP_OKAY)
-       err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp);
-
-   /* setup sliding window */
-   mode   = 0;
-   bitcnt = 1;
-   buf    = 0;
-   digidx = get_digit_count(k) - 1;
-
-   /* perform ops */
-   if (err == MP_OKAY) {
-       for (;;) {
-           /* grab next digit as required */
-           if (--bitcnt == 0) {
-               if (digidx == -1) {
-                   break;
-               }
-               buf = get_digit(k, digidx);
-               bitcnt = (int)DIGIT_BIT;
-               --digidx;
-           }
-
-           /* grab the next msb from the multiplicand */
-           i = (buf >> (DIGIT_BIT - 1)) & 1;
-           buf <<= 1;
-
-           if (mode == 0 && i == 0) {
-               /* timing resistant - dummy operations */
-               if (err == MP_OKAY)
-                   err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus,
-                                                  mp);
-               if (err == MP_OKAY)
-                   err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp);
-               if (err == MP_OKAY)
-                   continue;
-           }
-
-           if (mode == 0 && i == 1) {
-               mode = 1;
-               /* timing resistant - dummy operations */
-               if (err == MP_OKAY)
-                   err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus,
-                                                  mp);
-               if (err == MP_OKAY)
-                   err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp);
-               if (err == MP_OKAY)
-                   continue;
-           }
-
-           if (err == MP_OKAY)
-               err = ecc_projective_add_point(M[0], M[1], M[i^1], a, modulus,
-                                                                       mp);
-#ifdef WC_NO_CACHE_RESISTANT
-           if (err == MP_OKAY)
-               err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp);
-#else
-            /* instead of using M[i] for double, which leaks key bit to cache
-             * monitor, use M[2] as temp, make sure address calc is constant,
-             * keep M[0] and M[1] in cache */
-           if (err == MP_OKAY)
-               err = mp_copy((mp_int*)
-                             ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->x & wc_off_on_addr[i])),
-                             M[2]->x);
-           if (err == MP_OKAY)
-               err = mp_copy((mp_int*)
-                             ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->y & wc_off_on_addr[i])),
-                             M[2]->y);
-           if (err == MP_OKAY)
-               err = mp_copy((mp_int*)
-                             ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->z & wc_off_on_addr[i])),
-                             M[2]->z);
-           if (err == MP_OKAY)
-               err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp);
-           /* copy M[2] back to M[i] */
-           if (err == MP_OKAY)
-               err = mp_copy(M[2]->x,
-                             (mp_int*)
-                             ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) );
-           if (err == MP_OKAY)
-               err = mp_copy(M[2]->y,
-                             (mp_int*)
-                             ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) );
-           if (err == MP_OKAY)
-               err = mp_copy(M[2]->z,
-                             (mp_int*)
-                             ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) +
-                               ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) );
-           if (err != MP_OKAY)
-               break;
-#endif /* WC_NO_CACHE_RESISTANT */
-       } /* end for */
-   }
-
-   /* copy result out */
-   if (err == MP_OKAY)
-       err = mp_copy(M[0]->x, R->x);
-   if (err == MP_OKAY)
-       err = mp_copy(M[0]->y, R->y);
-   if (err == MP_OKAY)
-       err = mp_copy(M[0]->z, R->z);
-
-#endif /* ECC_TIMING_RESISTANT */
-
-   /* map R back from projective space */
-   if (err == MP_OKAY && map)
-       err = ecc_map(R, modulus, mp);
-
-exit:
-
-   /* done */
-   wc_ecc_del_point_h(tG, heap);
-   for (i = 0; i < M_POINTS; i++) {
-       wc_ecc_del_point_h(M[i], heap);
-   }
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-   R->key = NULL;
-#ifdef ALT_ECC_SIZE
-   XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-   XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-   XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-   XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-   XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-   return err;
-#else
-   if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
-       return ECC_BAD_ARG_E;
-   }
-
-   (void)a;
-
-   return sp_ecc_mulmod_256(k, G, R, map, heap);
-#endif
-}
-
-#endif /* !FP_ECC || !WOLFSSL_SP_MATH */
-
-#endif /* !FREESCALE_LTC_ECC */
-
-/** ECC Fixed Point mulmod global
-    k        The multiplicand
-    G        Base point to multiply
-    R        [out] Destination of product
-    a        ECC curve parameter a
-    modulus  The modulus for the curve
-    map      [boolean] If non-zero maps the point back to affine co-ordinates,
-             otherwise it's left in jacobian-montgomery form
-    return MP_OKAY if successful
-*/
-int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
-                  mp_int* modulus, int map)
-{
-    return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL);
-}
-
-#endif /* !WOLFSSL_ATECC508A */
-
-/**
- * use a heap hint when creating new ecc_point
- * return an allocated point on success or NULL on failure
- */
-ecc_point* wc_ecc_new_point_h(void* heap)
-{
-   ecc_point* p;
-
-   (void)heap;
-
-   p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC);
-   if (p == NULL) {
-      return NULL;
-   }
-   XMEMSET(p, 0, sizeof(ecc_point));
-
-#ifndef ALT_ECC_SIZE
-   if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) {
-      XFREE(p, heap, DYNAMIC_TYPE_ECC);
-      return NULL;
-   }
-#else
-   p->x = (mp_int*)&p->xyz[0];
-   p->y = (mp_int*)&p->xyz[1];
-   p->z = (mp_int*)&p->xyz[2];
-   alt_fp_init(p->x);
-   alt_fp_init(p->y);
-   alt_fp_init(p->z);
-#endif
-
-   return p;
-}
-
-
-/**
-   Allocate a new ECC point
-   return A newly allocated point or NULL on error
-*/
-ecc_point* wc_ecc_new_point(void)
-{
-  return wc_ecc_new_point_h(NULL);
-}
-
-
-void wc_ecc_del_point_h(ecc_point* p, void* heap)
-{
-   /* prevents free'ing null arguments */
-   if (p != NULL) {
-      mp_clear(p->x);
-      mp_clear(p->y);
-      mp_clear(p->z);
-      XFREE(p, heap, DYNAMIC_TYPE_ECC);
-   }
-   (void)heap;
-}
-
-
-/** Free an ECC point from memory
-  p   The point to free
-*/
-void wc_ecc_del_point(ecc_point* p)
-{
-    wc_ecc_del_point_h(p, NULL);
-}
-
-
-/** Copy the value of a point to an other one
-  p    The point to copy
-  r    The created point
-*/
-int wc_ecc_copy_point(ecc_point* p, ecc_point *r)
-{
-    int ret;
-
-    /* prevents null arguments */
-    if (p == NULL || r == NULL)
-        return ECC_BAD_ARG_E;
-
-    ret = mp_copy(p->x, r->x);
-    if (ret != MP_OKAY)
-        return ret;
-    ret = mp_copy(p->y, r->y);
-    if (ret != MP_OKAY)
-        return ret;
-    ret = mp_copy(p->z, r->z);
-    if (ret != MP_OKAY)
-        return ret;
-
-    return MP_OKAY;
-}
-
-/** Compare the value of a point with an other one
- a    The point to compare
- b    The other point to compare
-
- return MP_EQ if equal, MP_LT/MP_GT if not, < 0 in case of error
- */
-int wc_ecc_cmp_point(ecc_point* a, ecc_point *b)
-{
-    int ret;
-
-    /* prevents null arguments */
-    if (a == NULL || b == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = mp_cmp(a->x, b->x);
-    if (ret != MP_EQ)
-        return ret;
-    ret = mp_cmp(a->y, b->y);
-    if (ret != MP_EQ)
-        return ret;
-    ret = mp_cmp(a->z, b->z);
-    if (ret != MP_EQ)
-        return ret;
-
-    return MP_EQ;
-}
-
-
-/** Returns whether an ECC idx is valid or not
-  n      The idx number to check
-  return 1 if valid, 0 if not
-*/
-int wc_ecc_is_valid_idx(int n)
-{
-   int x;
-
-   for (x = 0; ecc_sets[x].size != 0; x++)
-       ;
-   /* -1 is a valid index --- indicating that the domain params
-      were supplied by the user */
-   if ((n >= ECC_CUSTOM_IDX) && (n < x)) {
-      return 1;
-   }
-
-   return 0;
-}
-
-int wc_ecc_get_curve_idx(int curve_id)
-{
-    int curve_idx;
-    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
-        if (curve_id == ecc_sets[curve_idx].id)
-            break;
-    }
-    if (ecc_sets[curve_idx].size == 0) {
-        return ECC_CURVE_INVALID;
-    }
-    return curve_idx;
-}
-
-int wc_ecc_get_curve_id(int curve_idx)
-{
-    if (wc_ecc_is_valid_idx(curve_idx)) {
-        return ecc_sets[curve_idx].id;
-    }
-    return ECC_CURVE_INVALID;
-}
-
-/* Returns the curve size that corresponds to a given ecc_curve_id identifier
- *
- * id      curve id, from ecc_curve_id enum in ecc.h
- * return  curve size, from ecc_sets[] on success, negative on error
- */
-int wc_ecc_get_curve_size_from_id(int curve_id)
-{
-    int curve_idx = wc_ecc_get_curve_idx(curve_id);
-    if (curve_idx == ECC_CURVE_INVALID)
-        return ECC_BAD_ARG_E;
-    return ecc_sets[curve_idx].size;
-}
-
-/* Returns the curve index that corresponds to a given curve name in
- * ecc_sets[] of ecc.c
- *
- * name    curve name, from ecc_sets[].name in ecc.c
- * return  curve index in ecc_sets[] on success, negative on error
- */
-int wc_ecc_get_curve_idx_from_name(const char* curveName)
-{
-    int curve_idx;
-    word32 len;
-
-    if (curveName == NULL)
-        return BAD_FUNC_ARG;
-
-    len = (word32)XSTRLEN(curveName);
-
-    for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) {
-        if (ecc_sets[curve_idx].name &&
-                XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) {
-            break;
-        }
-    }
-    if (ecc_sets[curve_idx].size == 0) {
-        WOLFSSL_MSG("ecc_set curve name not found");
-        return ECC_CURVE_INVALID;
-    }
-    return curve_idx;
-}
-
-/* Returns the curve size that corresponds to a given curve name,
- * as listed in ecc_sets[] of ecc.c.
- *
- * name    curve name, from ecc_sets[].name in ecc.c
- * return  curve size, from ecc_sets[] on success, negative on error
- */
-int wc_ecc_get_curve_size_from_name(const char* curveName)
-{
-    int curve_idx;
-
-    if (curveName == NULL)
-        return BAD_FUNC_ARG;
-
-    curve_idx = wc_ecc_get_curve_idx_from_name(curveName);
-    if (curve_idx < 0)
-        return curve_idx;
-
-    return ecc_sets[curve_idx].size;
-}
-
-/* Returns the curve id that corresponds to a given curve name,
- * as listed in ecc_sets[] of ecc.c.
- *
- * name   curve name, from ecc_sets[].name in ecc.c
- * return curve id, from ecc_sets[] on success, negative on error
- */
-int wc_ecc_get_curve_id_from_name(const char* curveName)
-{
-    int curve_idx;
-
-    if (curveName == NULL)
-        return BAD_FUNC_ARG;
-
-    curve_idx = wc_ecc_get_curve_idx_from_name(curveName);
-    if (curve_idx < 0)
-        return curve_idx;
-
-    return ecc_sets[curve_idx].id;
-}
-
-/* Compares a curve parameter (hex, from ecc_sets[]) to given input
- * parameter (byte array) for equality.
- *
- * Returns MP_EQ on success, negative on error */
-static int wc_ecc_cmp_param(const char* curveParam,
-                            const byte* param, word32 paramSz)
-{
-    int err = MP_OKAY;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* a = NULL;
-    mp_int* b = NULL;
-#else
-    mp_int  a[1], b[1];
-#endif
-
-    if (param == NULL || curveParam == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (a == NULL)
-        return MEMORY_E;
-    b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (b == NULL) {
-        XFREE(a, NULL, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-
-    if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY)
-        return err;
-
-    if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(a, param, paramSz);
-
-    if (err == MP_OKAY)
-        err = mp_read_radix(b, curveParam, MP_RADIX_HEX);
-
-    if (err == MP_OKAY) {
-        if (mp_cmp(a, b) != MP_EQ) {
-            err = -1;
-        } else {
-            err = MP_EQ;
-        }
-    }
-
-    mp_clear(a);
-    mp_clear(b);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(b, NULL, DYNAMIC_TYPE_ECC);
-    XFREE(a, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Returns the curve id in ecc_sets[] that corresponds to a given set of
- * curve parameters.
- *
- * fieldSize  the field size in bits
- * prime      prime of the finite field
- * primeSz    size of prime in octets
- * Af         first coefficient a of the curve
- * AfSz       size of Af in octets
- * Bf         second coefficient b of the curve
- * BfSz       size of Bf in octets
- * order      curve order
- * orderSz    size of curve in octets
- * Gx         affine x coordinate of base point
- * GxSz       size of Gx in octets
- * Gy         affine y coordinate of base point
- * GySz       size of Gy in octets
- * cofactor   curve cofactor
- *
- * return curve id, from ecc_sets[] on success, negative on error
- */
-int wc_ecc_get_curve_id_from_params(int fieldSize,
-        const byte* prime, word32 primeSz, const byte* Af, word32 AfSz,
-        const byte* Bf, word32 BfSz, const byte* order, word32 orderSz,
-        const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor)
-{
-    int idx;
-    int curveSz;
-
-    if (prime == NULL || Af == NULL || Bf == NULL || order == NULL ||
-        Gx == NULL || Gy == NULL)
-        return BAD_FUNC_ARG;
-
-    curveSz = (fieldSize + 1) / 8;    /* round up */
-
-    for (idx = 0; ecc_sets[idx].size != 0; idx++) {
-        if (curveSz == ecc_sets[idx].size) {
-            if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime,
-                            primeSz) == MP_EQ) &&
-                (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz) == MP_EQ) &&
-                (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz) == MP_EQ) &&
-                (wc_ecc_cmp_param(ecc_sets[idx].order, order,
-                                  orderSz) == MP_EQ) &&
-                (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz) == MP_EQ) &&
-                (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz) == MP_EQ) &&
-                (cofactor == ecc_sets[idx].cofactor)) {
-                    break;
-            }
-        }
-    }
-
-    if (ecc_sets[idx].size == 0)
-        return ECC_CURVE_INVALID;
-
-    return ecc_sets[idx].id;
-}
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-static WC_INLINE int wc_ecc_alloc_mpint(ecc_key* key, mp_int** mp)
-{
-   if (key == NULL || mp == NULL)
-      return BAD_FUNC_ARG;
-   if (*mp == NULL) {
-      *mp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT);
-      if (*mp == NULL) {
-         return MEMORY_E;
-      }
-      XMEMSET(*mp, 0, sizeof(mp_int));
-   }
-   return 0;
-}
-static WC_INLINE void wc_ecc_free_mpint(ecc_key* key, mp_int** mp)
-{
-   if (key && mp && *mp) {
-      mp_clear(*mp);
-      XFREE(*mp, key->heap, DYNAMIC_TYPE_BIGINT);
-      *mp = NULL;
-   }
-}
-
-static int wc_ecc_alloc_async(ecc_key* key)
-{
-    int err = wc_ecc_alloc_mpint(key, &key->r);
-    if (err == 0)
-        err = wc_ecc_alloc_mpint(key, &key->s);
-    return err;
-}
-
-static void wc_ecc_free_async(ecc_key* key)
-{
-    wc_ecc_free_mpint(key, &key->r);
-    wc_ecc_free_mpint(key, &key->s);
-#ifdef HAVE_CAVIUM_V
-    wc_ecc_free_mpint(key, &key->e);
-    wc_ecc_free_mpint(key, &key->signK);
-#endif /* HAVE_CAVIUM_V */
-}
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-
-#ifdef HAVE_ECC_DHE
-/**
-  Create an ECC shared secret between two keys
-  private_key      The private ECC key (heap hint based off of private key)
-  public_key       The public key
-  out              [out] Destination of the shared secret
-                         Conforms to EC-DH from ANSI X9.63
-  outlen           [in/out] The max size and resulting size of the shared secret
-  return           MP_OKAY if successful
-*/
-int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
-                      word32* outlen)
-{
-   int err;
-
-   if (private_key == NULL || public_key == NULL || out == NULL ||
-                                                            outlen == NULL) {
-       return BAD_FUNC_ARG;
-   }
-
-#ifdef WOLF_CRYPTO_DEV
-    if (private_key->devId != INVALID_DEVID) {
-        err = wc_CryptoDev_Ecdh(private_key, public_key, out, outlen);
-        if (err != NOT_COMPILED_IN)
-            return err;
-    }
-#endif
-
-   /* type valid? */
-   if (private_key->type != ECC_PRIVATEKEY &&
-           private_key->type != ECC_PRIVATEKEY_ONLY) {
-      return ECC_BAD_ARG_E;
-   }
-
-   /* Verify domain params supplied */
-   if (wc_ecc_is_valid_idx(private_key->idx) == 0 ||
-       wc_ecc_is_valid_idx(public_key->idx)  == 0) {
-      return ECC_BAD_ARG_E;
-   }
-
-   /* Verify curve id matches */
-   if (private_key->dp->id != public_key->dp->id) {
-      return ECC_BAD_ARG_E;
-   }
-
-#ifdef WOLFSSL_ATECC508A
-   err = atcatls_ecdh(private_key->slot, public_key->pubkey_raw, out);
-   if (err != ATCA_SUCCESS) {
-      err = BAD_COND_E;
-   }
-   *outlen = private_key->dp->size;
-#else
-   err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen);
-#endif /* WOLFSSL_ATECC508A */
-
-   return err;
-}
-
-
-#ifndef WOLFSSL_ATECC508A
-
-static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
-                               byte* out, word32* outlen, ecc_curve_spec* curve)
-{
-    int err;
-#ifndef WOLFSSL_SP_MATH
-    ecc_point* result = NULL;
-    word32 x = 0;
-#endif
-    mp_int* k = &private_key->k;
-#ifdef HAVE_ECC_CDH
-    mp_int k_lcl;
-
-    /* if cofactor flag has been set */
-    if (private_key->flags & WC_ECC_FLAG_COFACTOR) {
-        mp_digit cofactor = (mp_digit)private_key->dp->cofactor;
-        /* only perform cofactor calc if not equal to 1 */
-        if (cofactor != 1) {
-            k = &k_lcl;
-            if (mp_init(k) != MP_OKAY)
-                return MEMORY_E;
-            /* multiply cofactor times private key "k" */
-            err = mp_mul_d(&private_key->k, cofactor, k);
-            if (err != MP_OKAY) {
-                mp_clear(k);
-                return err;
-            }
-        }
-    }
-#endif
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-    if (private_key->idx != ECC_CUSTOM_IDX &&
-                               ecc_sets[private_key->idx].id == ECC_SECP256R1) {
-        err = sp_ecc_secret_gen_256(k, point, out, outlen, private_key->heap);
-    }
-    else
-#endif
-#endif
-#ifdef WOLFSSL_SP_MATH
-    {
-        err = WC_KEY_SIZE_E;
-
-        (void)curve;
-    }
-#else
-    {
-        /* make new point */
-        result = wc_ecc_new_point_h(private_key->heap);
-        if (result == NULL) {
-#ifdef HAVE_ECC_CDH
-            if (k == &k_lcl)
-                mp_clear(k);
-#endif
-            return MEMORY_E;
-        }
-
-        err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 1,
-                                                             private_key->heap);
-        if (err == MP_OKAY) {
-            x = mp_unsigned_bin_size(curve->prime);
-            if (*outlen < x) {
-                err = BUFFER_E;
-            }
-        }
-
-        if (err == MP_OKAY) {
-            XMEMSET(out, 0, x);
-            err = mp_to_unsigned_bin(result->x,out +
-                                     (x - mp_unsigned_bin_size(result->x)));
-        }
-        *outlen = x;
-
-        wc_ecc_del_point_h(result, private_key->heap);
-    }
-#endif
-#ifdef HAVE_ECC_CDH
-    if (k == &k_lcl)
-        mp_clear(k);
-#endif
-
-    return err;
-}
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-static int wc_ecc_shared_secret_gen_async(ecc_key* private_key,
-            ecc_point* point, byte* out, word32 *outlen,
-            ecc_curve_spec* curve)
-{
-    int err;
-
-#if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
-#ifdef HAVE_CAVIUM_V
-    /* verify the curve is supported by hardware */
-    if (NitroxEccIsCurveSupported(private_key))
-#endif
-    {
-        word32 keySz = private_key->dp->size;
-
-        /* sync public key x/y */
-        err = wc_mp_to_bigint_sz(&private_key->k, &private_key->k.raw, keySz);
-        if (err == MP_OKAY)
-            err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz);
-        if (err == MP_OKAY)
-            err = wc_mp_to_bigint_sz(point->y, &point->y->raw, keySz);
-    #ifdef HAVE_CAVIUM_V
-        /* allocate buffer for output */
-        if (err == MP_OKAY)
-            err = wc_ecc_alloc_mpint(private_key, &private_key->e);
-        if (err == MP_OKAY)
-            err = wc_bigint_alloc(&private_key->e->raw,
-                NitroxEccGetSize(private_key)*2);
-        if (err == MP_OKAY)
-            err = NitroxEcdh(private_key,
-                &private_key->k.raw, &point->x->raw, &point->y->raw,
-                private_key->e->raw.buf, &private_key->e->raw.len,
-                &curve->prime->raw);
-    #else
-        if (err == MP_OKAY)
-            err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF);
-        if (err == MP_OKAY)
-            err = IntelQaEcdh(&private_key->asyncDev,
-                &private_key->k.raw, &point->x->raw, &point->y->raw,
-                out, outlen,
-                &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw,
-                private_key->dp->cofactor);
-    #endif
-        return err;
-    }
-#elif defined(WOLFSSL_ASYNC_CRYPT_TEST)
-    if (wc_AsyncTestInit(&private_key->asyncDev, ASYNC_TEST_ECC_SHARED_SEC)) {
-        WC_ASYNC_TEST* testDev = &private_key->asyncDev.test;
-        testDev->eccSharedSec.private_key = private_key;
-        testDev->eccSharedSec.public_point = point;
-        testDev->eccSharedSec.out = out;
-        testDev->eccSharedSec.outLen = outlen;
-        return WC_PENDING_E;
-    }
-#endif
-
-    /* use sync in other cases */
-    err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve);
-
-    return err;
-}
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point,
-                                                    byte* out, word32 *outlen)
-{
-    int err;
-    DECLARE_CURVE_SPECS(curve, 2);
-
-    if (private_key == NULL || point == NULL || out == NULL ||
-                                                            outlen == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ALLOC_CURVE_SPECS(2);
-
-    /* load curve info */
-    err = wc_ecc_curve_load(private_key->dp, &curve,
-        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF));
-    if (err != MP_OKAY) {
-        FREE_CURVE_SPECS();
-        return err;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-    if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-        err = wc_ecc_shared_secret_gen_async(private_key, point,
-            out, outlen, curve);
-    }
-    else
-#endif
-    {
-        err = wc_ecc_shared_secret_gen_sync(private_key, point,
-            out, outlen, curve);
-    }
-
-    wc_ecc_curve_free(curve);
-    FREE_CURVE_SPECS();
-
-    return err;
-}
-
-/**
- Create an ECC shared secret between private key and public point
- private_key      The private ECC key (heap hint based on private key)
- point            The point to use (public key)
- out              [out] Destination of the shared secret
-                        Conforms to EC-DH from ANSI X9.63
- outlen           [in/out] The max size and resulting size of the shared secret
- return           MP_OKAY if successful
-*/
-int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point,
-                            byte* out, word32 *outlen)
-{
-    int err;
-
-    if (private_key == NULL || point == NULL || out == NULL ||
-                                                            outlen == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* type valid? */
-    if (private_key->type != ECC_PRIVATEKEY &&
-            private_key->type != ECC_PRIVATEKEY_ONLY) {
-        return ECC_BAD_ARG_E;
-    }
-
-    /* Verify domain params supplied */
-    if (wc_ecc_is_valid_idx(private_key->idx) == 0)
-        return ECC_BAD_ARG_E;
-
-    switch(private_key->state) {
-        case ECC_STATE_NONE:
-        case ECC_STATE_SHARED_SEC_GEN:
-            private_key->state = ECC_STATE_SHARED_SEC_GEN;
-
-            err = wc_ecc_shared_secret_gen(private_key, point, out, outlen);
-            if (err < 0) {
-                break;
-            }
-            FALL_THROUGH;
-
-        case ECC_STATE_SHARED_SEC_RES:
-            private_key->state = ECC_STATE_SHARED_SEC_RES;
-        #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-            if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-            #ifdef HAVE_CAVIUM_V
-                /* verify the curve is supported by hardware */
-                if (NitroxEccIsCurveSupported(private_key)) {
-                    /* copy output */
-                    *outlen = private_key->dp->size;
-                    XMEMCPY(out, private_key->e->raw.buf, *outlen);
-                }
-            #endif /* HAVE_CAVIUM_V */
-            }
-        #endif /* WOLFSSL_ASYNC_CRYPT */
-            err = 0;
-            break;
-
-        default:
-            err = BAD_STATE_E;
-    } /* switch */
-
-    /* if async pending then return and skip done cleanup below */
-    if (err == WC_PENDING_E) {
-        private_key->state++;
-        return err;
-    }
-
-    /* cleanup */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    wc_ecc_free_async(private_key);
-#endif
-    private_key->state = ECC_STATE_NONE;
-
-    return err;
-}
-#endif /* !WOLFSSL_ATECC508A */
-#endif /* HAVE_ECC_DHE */
-
-
-#ifndef WOLFSSL_ATECC508A
-/* return 1 if point is at infinity, 0 if not, < 0 on error */
-int wc_ecc_point_is_at_infinity(ecc_point* p)
-{
-    if (p == NULL)
-        return BAD_FUNC_ARG;
-
-    if (get_digit_count(p->x) == 0 && get_digit_count(p->y) == 0)
-        return 1;
-
-    return 0;
-}
-
-#ifndef WOLFSSL_SP_MATH
-/* generate random and ensure its greater than 0 and less than order */
-static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
-{
-    int err;
-    DECLARE_VAR(buf, byte, ECC_MAXSIZE_GEN, rng->heap);
-
-    /*generate 8 extra bytes to mitigate bias from the modulo operation below*/
-    /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/
-    size += 8;
-
-    /* make up random string */
-    err = wc_RNG_GenerateBlock(rng, buf, size);
-
-    /* load random buffer data into k */
-    if (err == 0)
-        err = mp_read_unsigned_bin(k, (byte*)buf, size);
-
-    /* the key should be smaller than the order of base point */
-    if (err == MP_OKAY) {
-        if (mp_cmp(k, order) != MP_LT) {
-            err = mp_mod(k, order, k);
-        }
-    }
-
-    /* quick sanity check to make sure we're not dealing with a 0 key */
-    if (err == MP_OKAY) {
-        if (mp_iszero(k) == MP_YES)
-          err = MP_ZERO_E;
-    }
-
-    ForceZero(buf, ECC_MAXSIZE);
-    FREE_VAR(buf, rng->heap);
-
-    return err;
-}
-#endif
-#endif /* !WOLFSSL_ATECC508A */
-
-static WC_INLINE void wc_ecc_reset(ecc_key* key)
-{
-    /* make sure required key variables are reset */
-    key->state = ECC_STATE_NONE;
-}
-
-
-/* create the public ECC key from a private key
- *
- * key     an initialized private key to generate public part from
- * curveIn [in]curve for key, can be NULL
- * pubOut  [out]ecc_point holding the public key, if NULL then public key part
- *         is cached in key instead.
- *
- * Note this function is local to the file because of the argument type
- *      ecc_curve_spec. Having this argument allows for not having to load the
- *      curve type multiple times when generating a key with wc_ecc_make_key().
- *
- * returns MP_OKAY on success
- */
-static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
-        ecc_point* pubOut)
-{
-    int err = MP_OKAY;
-#ifndef WOLFSSL_ATECC508A
-#ifndef WOLFSSL_SP_MATH
-    ecc_point* base = NULL;
-#endif
-    ecc_point* pub;
-    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
-#endif
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef WOLFSSL_ATECC508A
-
-    /* if ecc_point passed in then use it as output for public key point */
-    if (pubOut != NULL) {
-        pub = pubOut;
-    }
-    else {
-        /* caching public key making it a ECC_PRIVATEKEY instead of
-           ECC_PRIVATEKEY_ONLY */
-        pub = &key->pubkey;
-        key->type = ECC_PRIVATEKEY_ONLY;
-    }
-
-    /* avoid loading the curve unless it is not passed in */
-    if (curveIn != NULL) {
-        curve = curveIn;
-    }
-    else {
-        ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
-
-        /* load curve info */
-        if (err == MP_OKAY)
-            err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
-    }
-
-    if (err == MP_OKAY) {
-    #ifndef ALT_ECC_SIZE
-        err = mp_init_multi(pub->x, pub->y, pub->z, NULL, NULL, NULL);
-    #else
-        pub->x = (mp_int*)&pub->xyz[0];
-        pub->y = (mp_int*)&pub->xyz[1];
-        pub->z = (mp_int*)&pub->xyz[2];
-        alt_fp_init(pub->x);
-        alt_fp_init(pub->y);
-        alt_fp_init(pub->z);
-    #endif
-    }
-
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
-        if (err == MP_OKAY)
-            err = sp_ecc_mulmod_base_256(&key->k, pub, 1, key->heap);
-    }
-    else
-#endif
-#endif
-#ifdef WOLFSSL_SP_MATH
-        err = WC_KEY_SIZE_E;
-#else
-    {
-        if (err == MP_OKAY) {
-            base = wc_ecc_new_point_h(key->heap);
-            if (base == NULL)
-                err = MEMORY_E;
-        }
-        /* read in the x/y for this key */
-        if (err == MP_OKAY)
-            err = mp_copy(curve->Gx, base->x);
-        if (err == MP_OKAY)
-            err = mp_copy(curve->Gy, base->y);
-        if (err == MP_OKAY)
-            err = mp_set(base->z, 1);
-
-        /* make the public key */
-        if (err == MP_OKAY) {
-            err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime,
-                                                                  1, key->heap);
-        }
-
-        wc_ecc_del_point_h(base, key->heap);
-    }
-#endif
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    /* validate the public key, order * pubkey = point at infinity */
-    if (err == MP_OKAY)
-        err = ecc_check_pubkey_order(key, pub, curve->Af, curve->prime,
-                curve->order);
-#endif /* WOLFSSL_VALIDATE_KEYGEN */
-
-    if (err != MP_OKAY) {
-        /* clean up if failed */
-    #ifndef ALT_ECC_SIZE
-        mp_clear(pub->x);
-        mp_clear(pub->y);
-        mp_clear(pub->z);
-    #endif
-    }
-
-    /* free up local curve */
-    if (curveIn == NULL) {
-        wc_ecc_curve_free(curve);
-    #ifndef WOLFSSL_ATECC508A
-        FREE_CURVE_SPECS();
-    #endif
-    }
-
-#else
-    (void)curveIn;
-#endif /* WOLFSSL_ATECC508A */
-
-    /* change key state if public part is cached */
-    if (key->type == ECC_PRIVATEKEY_ONLY && pubOut == NULL) {
-        key->type = ECC_PRIVATEKEY;
-    }
-
-    return err;
-}
-
-
-/* create the public ECC key from a private key
- *
- * key     an initialized private key to generate public part from
- * pubOut  [out]ecc_point holding the public key, if NULL then public key part
- *         is cached in key instead.
- *
- *
- * returns MP_OKAY on success
- */
-int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut)
-{
-    WOLFSSL_ENTER("wc_ecc_make_pub");
-
-    return wc_ecc_make_pub_ex(key, NULL, pubOut);
-}
-
-
-int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
-{
-    int            err;
-#ifndef WOLFSSL_ATECC508A
-#ifndef WOLFSSL_SP_MATH
-    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
-#endif
-#endif
-
-    if (key == NULL || rng == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* make sure required variables are reset */
-    wc_ecc_reset(key);
-
-    err = wc_ecc_set_curve(key, keysize, curve_id);
-    if (err != 0) {
-        return err;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-    #ifdef HAVE_CAVIUM
-        /* TODO: Not implemented */
-    #elif defined(HAVE_INTEL_QA)
-        /* TODO: Not implemented */
-    #else
-        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_MAKE)) {
-            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-            testDev->eccMake.rng = rng;
-            testDev->eccMake.key = key;
-            testDev->eccMake.size = keysize;
-            testDev->eccMake.curve_id = curve_id;
-            return WC_PENDING_E;
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-#ifdef WOLFSSL_ATECC508A
-   key->type = ECC_PRIVATEKEY;
-   err = atcatls_create_key(key->slot, key->pubkey_raw);
-   if (err != ATCA_SUCCESS) {
-      err = BAD_COND_E;
-   }
-
-   /* populate key->pubkey */
-   err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw,
-                              ECC_MAX_CRYPTO_HW_SIZE);
-   if (err == MP_OKAY)
-       err = mp_read_unsigned_bin(key->pubkey.y,
-                                  key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE,
-                                  ECC_MAX_CRYPTO_HW_SIZE);
-#else
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
-        err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap);
-        if (err == MP_OKAY)
-            key->type = ECC_PRIVATEKEY;
-    }
-    else
-#endif
-#endif
-#ifdef WOLFSSL_SP_MATH
-        err = WC_KEY_SIZE_E;
-#else
-    {
-        ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
-
-        /* setup the key variables */
-        err = mp_init(&key->k);
-
-        /* load curve info */
-        if (err == MP_OKAY)
-            err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
-
-        /* generate k */
-        if (err == MP_OKAY)
-            err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order);
-
-        /* generate public key from k */
-        if (err == MP_OKAY)
-            err = wc_ecc_make_pub_ex(key, curve, NULL);
-
-        if (err == MP_OKAY)
-            key->type = ECC_PRIVATEKEY;
-
-        /* cleanup these on failure case only */
-        if (err != MP_OKAY) {
-            /* clean up */
-            mp_forcezero(&key->k);
-        }
-
-        /* cleanup allocations */
-        wc_ecc_curve_free(curve);
-    #ifndef WOLFSSL_ATECC508A
-        FREE_CURVE_SPECS();
-    #endif
-    }
-#endif
-
-#endif /* WOLFSSL_ATECC508A */
-
-    return err;
-}
-
-#ifdef ECC_DUMP_OID
-/* Optional dump of encoded OID for adding new curves */
-static int mOidDumpDone;
-static void wc_ecc_dump_oids(void)
-{
-    int x;
-
-    if (mOidDumpDone) {
-        return;
-    }
-
-    /* find matching OID sum (based on encoded value) */
-    for (x = 0; ecc_sets[x].size != 0; x++) {
-        int i;
-        byte* oid;
-        word32 oidSz, sum = 0;
-
-        printf("ECC %s (%d):\n", ecc_sets[x].name, x);
-
-    #ifdef HAVE_OID_ENCODING
-        byte oidEnc[ECC_MAX_OID_LEN];
-
-        oid = oidEnc;
-        oidSz = ECC_MAX_OID_LEN;
-
-        printf("OID: ");
-        for (i = 0; i < (int)ecc_sets[x].oidSz; i++) {
-            printf("%d.", ecc_sets[x].oid[i]);
-        }
-        printf("\n");
-
-        EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, oidEnc, &oidSz);
-    #else
-        oid = (byte*)ecc_sets[x].oid;
-        oidSz = ecc_sets[x].oidSz;
-    #endif
-
-        printf("OID Encoded: ");
-        for (i = 0; i < (int)oidSz; i++) {
-            printf("0x%02X,", oid[i]);
-        }
-        printf("\n");
-
-        for (i = 0; i < (int)oidSz; i++) {
-            sum += oid[i];
-        }
-        printf("Sum: %d\n", sum);
-
-        /* validate sum */
-        if (ecc_sets[x].oidSum != sum) {
-            printf("  Sum %d Not Valid!\n", ecc_sets[x].oidSum);
-        }
-    }
-    mOidDumpDone = 1;
-}
-#endif /* ECC_DUMP_OID */
-
-/**
- Make a new ECC key
- rng          An active RNG state
- keysize      The keysize for the new key (in octets from 20 to 65 bytes)
- key          [out] Destination of the newly created key
- return       MP_OKAY if successful,
- upon error all allocated memory will be freed
- */
-int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key)
-{
-    return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF);
-}
-
-/* Setup dynamic pointers if using normal math for proper freeing */
-int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef ECC_DUMP_OID
-    wc_ecc_dump_oids();
-#endif
-
-    XMEMSET(key, 0, sizeof(ecc_key));
-    key->state = ECC_STATE_NONE;
-
-#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV)
-    key->devId = devId;
-#else
-    (void)devId;
-#endif
-
-#ifdef WOLFSSL_ATECC508A
-    key->slot = atmel_ecc_alloc();
-    if (key->slot == ATECC_INVALID_SLOT) {
-        return ECC_BAD_ARG_E;
-    }
-#else
-#ifdef ALT_ECC_SIZE
-    key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
-    key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
-    key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
-    alt_fp_init(key->pubkey.x);
-    alt_fp_init(key->pubkey.y);
-    alt_fp_init(key->pubkey.z);
-    ret = mp_init(&key->k);
-#else
-    ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
-                                                                    NULL, NULL);
-#endif /* ALT_ECC_SIZE */
-    if (ret != MP_OKAY) {
-        return MEMORY_E;
-    }
-#endif /* WOLFSSL_ATECC508A */
-
-#ifdef WOLFSSL_HEAP_TEST
-    key->heap = (void*)WOLFSSL_HEAP_TEST;
-#else
-    key->heap = heap;
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-    /* handle as async */
-    ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC,
-                                                            key->heap, devId);
-#endif
-
-    return ret;
-}
-
-int wc_ecc_init(ecc_key* key)
-{
-    return wc_ecc_init_ex(key, NULL, INVALID_DEVID);
-}
-
-int wc_ecc_set_flags(ecc_key* key, word32 flags)
-{
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    key->flags |= flags;
-    return 0;
-}
-
-#ifdef HAVE_ECC_SIGN
-
-#ifndef NO_ASN
-
-#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC)
-static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen,
-    mp_int* r, mp_int* s, byte* out, word32 *outlen, WC_RNG* rng,
-    ecc_key* key)
-{
-    int err;
-
-#ifdef PLUTON_CRYPTO_ECC
-    if (key->devId != INVALID_DEVID) /* use hardware */
-#endif
-    {
-        word32 keysize = (word32)key->dp->size;
-
-        /* Check args */
-        if (keysize > ECC_MAX_CRYPTO_HW_SIZE || inlen != keysize ||
-                                                *outlen < keysize*2) {
-            return ECC_BAD_ARG_E;
-        }
-
-    #if defined(WOLFSSL_ATECC508A)
-        /* Sign: Result is 32-bytes of R then 32-bytes of S */
-        err = atcatls_sign(key->slot, in, out);
-        if (err != ATCA_SUCCESS) {
-           return BAD_COND_E;
-        }
-    #elif defined(PLUTON_CRYPTO_ECC)
-        {
-            /* perform ECC sign */
-            word32 raw_sig_size = *outlen;
-            err = Crypto_EccSign(in, inlen, out, &raw_sig_size);
-            if (err != CRYPTO_RES_SUCCESS || raw_sig_size != keysize*2){
-               return BAD_COND_E;
-            }
-        }
-    #endif
-
-        /* Load R and S */
-        err = mp_read_unsigned_bin(r, &out[0], keysize);
-        if (err != MP_OKAY) {
-            return err;
-        }
-        err = mp_read_unsigned_bin(s, &out[keysize], keysize);
-        if (err != MP_OKAY) {
-            return err;
-        }
-
-        /* Check for zeros */
-        if (mp_iszero(r) || mp_iszero(s)) {
-            return MP_ZERO_E;
-        }
-    }
-#ifdef PLUTON_CRYPTO_ECC
-    else {
-        err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
-    }
-#endif
-    (void)rng;
-
-    return err;
-}
-#endif /* WOLFSSL_ATECC508A || PLUTON_CRYPTO_ECC */
-
-/**
- Sign a message digest
- in        The message digest to sign
- inlen     The length of the digest
- out       [out] The destination for the signature
- outlen    [in/out] The max size and resulting size of the signature
- key       A private ECC key
- return    MP_OKAY if successful
- */
-int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
-                     WC_RNG* rng, ecc_key* key)
-{
-    int err;
-    mp_int *r = NULL, *s = NULL;
-#if !defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLFSSL_SMALL_STACK)
-    mp_int r_lcl, s_lcl;
-#endif
-
-    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
-                                                                rng == NULL) {
-        return ECC_BAD_ARG_E;
-    }
-
-#ifdef WOLF_CRYPTO_DEV
-    if (key->devId != INVALID_DEVID) {
-        err = wc_CryptoDev_EccSign(in, inlen, out, outlen, rng, key);
-        if (err != NOT_COMPILED_IN)
-            return err;
-    }
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    err = wc_ecc_alloc_async(key);
-    if (err != 0)
-        return err;
-    r = key->r;
-    s = key->s;
-#elif !defined(WOLFSSL_SMALL_STACK)
-    r = &r_lcl;
-    s = &s_lcl;
-#else
-    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-    if (r == NULL)
-        return MEMORY_E;
-    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-    if (s == NULL) {
-        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-
-    switch(key->state) {
-        case ECC_STATE_NONE:
-        case ECC_STATE_SIGN_DO:
-            key->state = ECC_STATE_SIGN_DO;
-
-            if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
-                break;
-            }
-
-        /* hardware crypto */
-        #if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC)
-            err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
-        #else
-            err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
-        #endif
-            if (err < 0) {
-                break;
-            }
-
-            FALL_THROUGH;
-
-        case ECC_STATE_SIGN_ENCODE:
-            key->state = ECC_STATE_SIGN_ENCODE;
-
-        #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-            if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-                #ifdef HAVE_CAVIUM_V
-                    /* Nitrox requires r and s in sep buffer, so split it */
-                    NitroxEccRsSplit(key, &r->raw, &s->raw);
-                #endif
-                #ifndef WOLFSSL_ASYNC_CRYPT_TEST
-                    /* only do this if not simulator, since it overwrites result */
-                    wc_bigint_to_mp(&r->raw, r);
-                    wc_bigint_to_mp(&s->raw, s);
-                #endif
-            }
-        #endif /* WOLFSSL_ASYNC_CRYPT */
-
-            /* encoded with DSA header */
-            err = StoreECC_DSA_Sig(out, outlen, r, s);
-
-            /* done with R/S */
-            mp_clear(r);
-            mp_clear(s);
-        #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK)
-            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
-            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
-        #endif
-            break;
-
-        default:
-            err = BAD_STATE_E;
-            break;
-    }
-
-    /* if async pending then return and skip done cleanup below */
-    if (err == WC_PENDING_E) {
-        key->state++;
-        return err;
-    }
-
-    /* cleanup */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    wc_ecc_free_async(key);
-#endif
-    key->state = ECC_STATE_NONE;
-
-    return err;
-}
-#endif /* !NO_ASN */
-
-#ifndef WOLFSSL_ATECC508A
-/**
-  Sign a message digest
-  in        The message digest to sign
-  inlen     The length of the digest
-  key       A private ECC key
-  r         [out] The destination for r component of the signature
-  s         [out] The destination for s component of the signature
-  return    MP_OKAY if successful
-*/
-int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
-                     ecc_key* key, mp_int *r, mp_int *s)
-{
-   int    err;
-#ifndef WOLFSSL_SP_MATH
-   mp_int* e;
-#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \
-                                                   !defined(WOLFSSL_SMALL_STACK)
-   mp_int  e_lcl;
-#endif
-   DECLARE_CURVE_SPECS(curve, 1);
-#endif /* !WOLFSSL_SP_MATH */
-
-   if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL)
-       return ECC_BAD_ARG_E;
-
-   /* is this a private key? */
-   if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) {
-      return ECC_BAD_ARG_E;
-   }
-
-   /* is the IDX valid ?  */
-   if (wc_ecc_is_valid_idx(key->idx) != 1) {
-      return ECC_BAD_ARG_E;
-   }
-
-#ifdef WOLFSSL_SP_MATH
-    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
-        return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap);
-    else
-        return WC_KEY_SIZE_E;
-#else
-#ifdef WOLFSSL_HAVE_SP_ECC
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
-           defined(WOLFSSL_ASYNC_CRYPT_TEST)
-    if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC)
-    #endif
-    {
-#ifndef WOLFSSL_SP_NO_256
-        if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
-            return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap);
-#endif
-    }
-#endif /* WOLFSSL_HAVE_SP_ECC */
-
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
-       defined(WOLFSSL_ASYNC_CRYPT_TEST)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_SIGN)) {
-            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-            testDev->eccSign.in = in;
-            testDev->eccSign.inSz = inlen;
-            testDev->eccSign.rng = rng;
-            testDev->eccSign.key = key;
-            testDev->eccSign.r = r;
-            testDev->eccSign.s = s;
-            return WC_PENDING_E;
-        }
-    }
-#endif
-
-   ALLOC_CURVE_SPECS(1);
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
-   err = wc_ecc_alloc_mpint(key, &key->e);
-   if (err != 0) {
-      FREE_CURVE_SPECS();
-      return err;
-   }
-   e = key->e;
-#elif !defined(WOLFSSL_SMALL_STACK)
-   e = &e_lcl;
-#else
-   e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-   if (e == NULL) {
-      FREE_CURVE_SPECS();
-      return MEMORY_E;
-   }
-#endif
-
-   /* get the hash and load it as a bignum into 'e' */
-   /* init the bignums */
-   if ((err = mp_init(e)) != MP_OKAY) {
-   #ifdef WOLFSSL_SMALL_STACK
-      XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
-   #endif
-      FREE_CURVE_SPECS();
-      return err;
-   }
-
-   /* load curve info */
-   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER);
-
-   /* load digest into e */
-   if (err == MP_OKAY) {
-       /* we may need to truncate if hash is longer than key size */
-       word32 orderBits = mp_count_bits(curve->order);
-
-       /* truncate down to byte size, may be all that's needed */
-       if ((WOLFSSL_BIT_SIZE * inlen) > orderBits)
-           inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
-       err = mp_read_unsigned_bin(e, (byte*)in, inlen);
-
-       /* may still need bit truncation too */
-       if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits)
-           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
-   }
-
-   /* make up a key and export the public copy */
-   if (err == MP_OKAY) {
-       int      loop_check = 0;
-   #ifdef WOLFSSL_SMALL_STACK
-       ecc_key* pubkey = NULL;
-   #else
-       ecc_key  pubkey[1];
-   #endif
-
-   #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-        #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
-        #ifdef HAVE_CAVIUM_V
-            if (NitroxEccIsCurveSupported(key))
-        #endif
-            {
-               word32 keySz = key->dp->size;
-               mp_int* k;
-            #ifdef HAVE_CAVIUM_V
-               err = wc_ecc_alloc_mpint(key, &key->signK);
-               if (err != 0)
-                  return err;
-               k = key->signK;
-            #else
-               mp_int k_lcl;
-               k = &k_lcl;
-            #endif
-
-               err = mp_init(k);
-
-                /* make sure r and s are allocated */
-           #ifdef HAVE_CAVIUM_V
-               /* Nitrox V needs single buffer for R and S */
-               if (err == MP_OKAY)
-                   err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2);
-               /* Nitrox V only needs Prime and Order */
-               if (err == MP_OKAY)
-                   err = wc_ecc_curve_load(key->dp, &curve,
-                        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER));
-           #else
-               if (err == MP_OKAY)
-                   err = wc_bigint_alloc(&key->r->raw, key->dp->size);
-               if (err == MP_OKAY)
-                   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
-           #endif
-               if (err == MP_OKAY)
-                   err = wc_bigint_alloc(&key->s->raw, key->dp->size);
-
-               /* load e and k */
-               if (err == MP_OKAY)
-                   err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
-               if (err == MP_OKAY)
-                   err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz);
-               if (err == MP_OKAY)
-                   err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order);
-               if (err == MP_OKAY)
-                   err = wc_mp_to_bigint_sz(k, &k->raw, keySz);
-
-           #ifdef HAVE_CAVIUM_V
-               if (err == MP_OKAY)
-                   err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw,
-                    &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw);
-           #else
-               if (err == MP_OKAY)
-                   err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw,
-                      &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw,
-                      &curve->prime->raw, &curve->order->raw, &curve->Gx->raw,
-                      &curve->Gy->raw);
-           #endif
-
-           #ifndef HAVE_CAVIUM_V
-               mp_clear(e);
-               mp_clear(k);
-           #endif
-               wc_ecc_curve_free(curve);
-               FREE_CURVE_SPECS();
-
-               return err;
-           }
-       #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
-       }
-   #endif /* WOLFSSL_ASYNC_CRYPT */
-
-   #ifdef WOLFSSL_SMALL_STACK
-       pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC);
-       if (pubkey == NULL)
-           err = MEMORY_E;
-   #endif
-
-       /* don't use async for key, since we don't support async return here */
-       if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap,
-                                                   INVALID_DEVID)) == MP_OKAY) {
-       #ifdef WOLFSSL_SMALL_STACK
-           mp_int* b = NULL;
-       #else
-           mp_int  b[1];
-       #endif
-
-       #ifdef WOLFSSL_SMALL_STACK
-           if (err == MP_OKAY) {
-               b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap,
-                                                              DYNAMIC_TYPE_ECC);
-               if (b == NULL)
-                   err = MEMORY_E;
-           }
-       #endif
-
-           if (err == MP_OKAY) {
-               err = mp_init(b);
-           }
-
-       #ifdef WOLFSSL_CUSTOM_CURVES
-           /* if custom curve, apply params to pubkey */
-           if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) {
-               err = wc_ecc_set_custom_curve(pubkey, key->dp);
-           }
-       #endif
-
-           if (err == MP_OKAY) {
-               /* Generate blinding value - non-zero value. */
-               do {
-                   if (++loop_check > 64) {
-                        err = RNG_FAILURE_E;
-                        break;
-                   }
-
-                   err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order);
-               }
-               while (err == MP_ZERO_E);
-               loop_check = 0;
-           }
-
-           for (; err == MP_OKAY;) {
-               if (++loop_check > 64) {
-                    err = RNG_FAILURE_E;
-                    break;
-               }
-               err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey,
-                                                                   key->dp->id);
-               if (err != MP_OKAY) break;
-
-               /* find r = x1 mod n */
-               err = mp_mod(pubkey->pubkey.x, curve->order, r);
-               if (err != MP_OKAY) break;
-
-               if (mp_iszero(r) == MP_YES) {
-                #ifndef ALT_ECC_SIZE
-                   mp_clear(pubkey->pubkey.x);
-                   mp_clear(pubkey->pubkey.y);
-                   mp_clear(pubkey->pubkey.z);
-                #endif
-                   mp_forcezero(&pubkey->k);
-               }
-               else {
-                   /* find s = (e + xr)/k
-                             = b.(e/k.b + x.r/k.b) */
-
-                   /* k = k.b */
-                   err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k);
-                   if (err != MP_OKAY) break;
-
-                   /* k = 1/k.b */
-                   err = mp_invmod(&pubkey->k, curve->order, &pubkey->k);
-                   if (err != MP_OKAY) break;
-
-                   /* s = x.r */
-                   err = mp_mulmod(&key->k, r, curve->order, s);
-                   if (err != MP_OKAY) break;
-
-                   /* s = x.r/k.b */
-                   err = mp_mulmod(&pubkey->k, s, curve->order, s);
-                   if (err != MP_OKAY) break;
-
-                   /* e = e/k.b */
-                   err = mp_mulmod(&pubkey->k, e, curve->order, e);
-                   if (err != MP_OKAY) break;
-
-                   /* s = e/k.b + x.r/k.b
-                        = (e + x.r)/k.b */
-                   err = mp_add(e, s, s);
-                   if (err != MP_OKAY) break;
-
-                   /* s = b.(e + x.r)/k.b
-                        = (e + x.r)/k */
-                   err = mp_mulmod(s, b, curve->order, s);
-                   if (err != MP_OKAY) break;
-
-                   /* s = (e + xr)/k */
-                   err = mp_mod(s, curve->order, s);
-                   if (err != MP_OKAY) break;
-
-                   if (mp_iszero(s) == MP_NO)
-                       break;
-                }
-           }
-           mp_clear(b);
-           mp_free(b);
-       #ifdef WOLFSSL_SMALL_STACK
-           XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
-       #endif
-           wc_ecc_free(pubkey);
-       #ifdef WOLFSSL_SMALL_STACK
-           XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC);
-       #endif
-       }
-   }
-
-   mp_clear(e);
-   wc_ecc_curve_free(curve);
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(e, key->heap, DYNAMIC_TYPE_ECC);
-#endif
-   FREE_CURVE_SPECS();
-#endif /* WOLFSSL_SP_MATH */
-
-   return err;
-}
-#endif /* WOLFSSL_ATECC508A */
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-void wc_ecc_free_curve(const ecc_set_type* curve, void* heap)
-{
-    if (curve->prime != NULL)
-        XFREE((void*)curve->prime, heap, DYNAMIC_TYPE_ECC_BUFFER);
-    if (curve->Af != NULL)
-        XFREE((void*)curve->Af, heap, DYNAMIC_TYPE_ECC_BUFFER);
-    if (curve->Bf != NULL)
-        XFREE((void*)curve->Bf, heap, DYNAMIC_TYPE_ECC_BUFFER);
-    if (curve->order != NULL)
-        XFREE((void*)curve->order, heap, DYNAMIC_TYPE_ECC_BUFFER);
-    if (curve->Gx != NULL)
-        XFREE((void*)curve->Gx, heap, DYNAMIC_TYPE_ECC_BUFFER);
-    if (curve->Gy != NULL)
-        XFREE((void*)curve->Gy, heap, DYNAMIC_TYPE_ECC_BUFFER);
-
-    XFREE((void*)curve, heap, DYNAMIC_TYPE_ECC_BUFFER);
-
-    (void)heap;
-}
-#endif /* WOLFSSL_CUSTOM_CURVES */
-
-/**
-  Free an ECC key from memory
-  key   The key you wish to free
-*/
-int wc_ecc_free(ecc_key* key)
-{
-    if (key == NULL) {
-        return 0;
-    }
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #ifdef WC_ASYNC_ENABLE_ECC
-    wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC);
-    #endif
-    wc_ecc_free_async(key);
-#endif
-
-#ifdef WOLFSSL_ATECC508A
-    atmel_ecc_free(key->slot);
-    key->slot = -1;
-#else
-
-    mp_clear(key->pubkey.x);
-    mp_clear(key->pubkey.y);
-    mp_clear(key->pubkey.z);
-
-    mp_forcezero(&key->k);
-#endif /* WOLFSSL_ATECC508A */
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-    if (key->deallocSet && key->dp != NULL)
-        wc_ecc_free_curve(key->dp, key->heap);
-#endif
-
-    return 0;
-}
-
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_ATECC508A)
-#ifdef ECC_SHAMIR
-
-/** Computes kA*A + kB*B = C using Shamir's Trick
-  A        First point to multiply
-  kA       What to multiple A by
-  B        Second point to multiply
-  kB       What to multiple B by
-  C        [out] Destination point (can overlap with A or B)
-  a        ECC curve parameter a
-  modulus  Modulus for curve
-  return MP_OKAY on success
-*/
-#ifdef FP_ECC
-static int normal_ecc_mul2add(ecc_point* A, mp_int* kA,
-                             ecc_point* B, mp_int* kB,
-                             ecc_point* C, mp_int* a, mp_int* modulus,
-                             void* heap)
-#else
-int ecc_mul2add(ecc_point* A, mp_int* kA,
-                    ecc_point* B, mp_int* kB,
-                    ecc_point* C, mp_int* a, mp_int* modulus,
-                    void* heap)
-#endif
-{
-#ifdef WOLFSSL_SMALL_STACK
-  ecc_point**    precomp = NULL;
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-  ecc_key        key;
-#endif
-#else
-  ecc_point*     precomp[SHAMIR_PRECOMP_SZ];
-#endif
-  unsigned       bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
-  unsigned char* tA;
-  unsigned char* tB;
-  int            err = MP_OKAY, first, x, y;
-  mp_digit       mp = 0;
-
-  /* argchks */
-  if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL ||
-                                                         modulus == NULL) {
-     return ECC_BAD_ARG_E;
-  }
-
-  /* allocate memory */
-  tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER);
-  if (tA == NULL) {
-     return GEN_MEM_ERR;
-  }
-  tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER);
-  if (tB == NULL) {
-     XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
-     return GEN_MEM_ERR;
-  }
-#ifdef WOLFSSL_SMALL_STACK
-  precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap,
-                                                       DYNAMIC_TYPE_ECC_BUFFER);
-  if (precomp == NULL) {
-     XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
-     XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
-     return GEN_MEM_ERR;
-  }
-#endif
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-  key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-  key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-#ifdef ALT_ECC_SIZE
-  key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-  key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-  key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-#endif
-  if (key.t1 == NULL || key.t2 == NULL
-#ifdef ALT_ECC_SIZE
-     || key.x == NULL || key.y == NULL || key.z == NULL
-#endif
-  ) {
-#ifdef ALT_ECC_SIZE
-      XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-      XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-      XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-      XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-      XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-      XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
-      XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
-      XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
-      return MEMORY_E;
-  }
-  C->key = &key;
-#endif /* WOLFSSL_SMALL_STACK_CACHE */
-
-  /* init variables */
-  XMEMSET(tA, 0, ECC_BUFSIZE);
-  XMEMSET(tB, 0, ECC_BUFSIZE);
-#ifndef WOLFSSL_SMALL_STACK
-  XMEMSET(precomp, 0, sizeof(precomp));
-#else
-  XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ);
-#endif
-
-  /* get sizes */
-  lenA = mp_unsigned_bin_size(kA);
-  lenB = mp_unsigned_bin_size(kB);
-  len  = MAX(lenA, lenB);
-
-  /* sanity check */
-  if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) {
-    err = BAD_FUNC_ARG;
-  }
-
-  if (err == MP_OKAY) {
-    /* extract and justify kA */
-    err = mp_to_unsigned_bin(kA, (len - lenA) + tA);
-
-    /* extract and justify kB */
-    if (err == MP_OKAY)
-        err = mp_to_unsigned_bin(kB, (len - lenB) + tB);
-
-    /* allocate the table */
-    if (err == MP_OKAY) {
-        for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
-            precomp[x] = wc_ecc_new_point_h(heap);
-            if (precomp[x] == NULL) {
-                err = GEN_MEM_ERR;
-                break;
-            }
-        #ifdef WOLFSSL_SMALL_STACK_CACHE
-            precomp[x]->key = &key;
-        #endif
-        }
-    }
-  }
-
-  if (err == MP_OKAY)
-    /* init montgomery reduction */
-    err = mp_montgomery_setup(modulus, &mp);
-
-  if (err == MP_OKAY) {
-  #ifdef WOLFSSL_SMALL_STACK
-    mp_int* mu = NULL;
-  #else
-    mp_int  mu[1];
-  #endif
-  #ifdef WOLFSSL_SMALL_STACK
-    mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC);
-    if (mu == NULL)
-        err = MEMORY_E;
-  #endif
-    if (err == MP_OKAY) {
-        err = mp_init(mu);
-    }
-    if (err == MP_OKAY) {
-      err = mp_montgomery_calc_normalization(mu, modulus);
-
-      if (err == MP_OKAY)
-        /* copy ones ... */
-        err = mp_mulmod(A->x, mu, modulus, precomp[1]->x);
-
-      if (err == MP_OKAY)
-        err = mp_mulmod(A->y, mu, modulus, precomp[1]->y);
-      if (err == MP_OKAY)
-        err = mp_mulmod(A->z, mu, modulus, precomp[1]->z);
-
-      if (err == MP_OKAY)
-        err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x);
-      if (err == MP_OKAY)
-        err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y);
-      if (err == MP_OKAY)
-        err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z);
-
-      /* done with mu */
-      mp_clear(mu);
-  #ifdef WOLFSSL_SMALL_STACK
-      XFREE(mu, heap, DYNAMIC_TYPE_ECC);
-  #endif
-    }
-  }
-
-  if (err == MP_OKAY)
-    /* precomp [i,0](A + B) table */
-    err = ecc_projective_dbl_point(precomp[1], precomp[2], a, modulus, mp);
-
-  if (err == MP_OKAY)
-    err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3],
-                                   a, modulus, mp);
-  if (err == MP_OKAY)
-    /* precomp [0,i](A + B) table */
-    err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], a, modulus, mp);
-
-  if (err == MP_OKAY)
-    err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2],
-                                   a, modulus, mp);
-
-  if (err == MP_OKAY) {
-    /* precomp [i,j](A + B) table (i != 0, j != 0) */
-    for (x = 1; x < 4; x++) {
-      for (y = 1; y < 4; y++) {
-        if (err == MP_OKAY) {
-          err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
-                                             precomp[x+(y<<2)], a, modulus, mp);
-        }
-      }
-    }
-  }
-
-  if (err == MP_OKAY) {
-    nibble  = 3;
-    first   = 1;
-    bitbufA = tA[0];
-    bitbufB = tB[0];
-
-    /* for every byte of the multiplicands */
-    for (x = 0;; ) {
-        /* grab a nibble */
-        if (++nibble == 4) {
-            if (x == (int)len) break;
-            bitbufA = tA[x];
-            bitbufB = tB[x];
-            nibble  = 0;
-            x++;
-        }
-
-        /* extract two bits from both, shift/update */
-        nA = (bitbufA >> 6) & 0x03;
-        nB = (bitbufB >> 6) & 0x03;
-        bitbufA = (bitbufA << 2) & 0xFF;
-        bitbufB = (bitbufB << 2) & 0xFF;
-
-        /* if both zero, if first, continue */
-        if ((nA == 0) && (nB == 0) && (first == 1)) {
-            continue;
-        }
-
-        /* double twice, only if this isn't the first */
-        if (first == 0) {
-            /* double twice */
-            if (err == MP_OKAY)
-                err = ecc_projective_dbl_point(C, C, a, modulus, mp);
-            if (err == MP_OKAY)
-                err = ecc_projective_dbl_point(C, C, a, modulus, mp);
-            else
-                break;
-        }
-
-        /* if not both zero */
-        if ((nA != 0) || (nB != 0)) {
-            if (first == 1) {
-                /* if first, copy from table */
-                first = 0;
-                if (err == MP_OKAY)
-                    err = mp_copy(precomp[nA + (nB<<2)]->x, C->x);
-
-                if (err == MP_OKAY)
-                    err = mp_copy(precomp[nA + (nB<<2)]->y, C->y);
-
-                if (err == MP_OKAY)
-                    err = mp_copy(precomp[nA + (nB<<2)]->z, C->z);
-                else
-                    break;
-            } else {
-                /* if not first, add from table */
-                if (err == MP_OKAY)
-                    err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
-                                                   a, modulus, mp);
-                else
-                    break;
-            }
-        }
-    }
-  }
-
-  /* reduce to affine */
-  if (err == MP_OKAY)
-    err = ecc_map(C, modulus, mp);
-
-  /* clean up */
-  for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) {
-     wc_ecc_del_point_h(precomp[x], heap);
-  }
-
-  ForceZero(tA, ECC_BUFSIZE);
-  ForceZero(tB, ECC_BUFSIZE);
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-#ifdef ALT_ECC_SIZE
-  XFREE(key.z, heap, DYNAMIC_TYPE_ECC);
-  XFREE(key.y, heap, DYNAMIC_TYPE_ECC);
-  XFREE(key.x, heap, DYNAMIC_TYPE_ECC);
-#endif
-  XFREE(key.t2, heap, DYNAMIC_TYPE_ECC);
-  XFREE(key.t1, heap, DYNAMIC_TYPE_ECC);
-  C->key = NULL;
-#endif
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-  XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER);
-  XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER);
-
-  return err;
-}
-
-#endif /* ECC_SHAMIR */
-#endif /* !WOLFSSL_SP_MATH && !WOLFSSL_ATECC508A */
-
-
-#ifdef HAVE_ECC_VERIFY
-#ifndef NO_ASN
-/* verify
- *
- * w  = s^-1 mod n
- * u1 = xw
- * u2 = rw
- * X = u1*G + u2*Q
- * v = X_x1 mod n
- * accept if v == r
- */
-
-/**
- Verify an ECC signature
- sig         The signature to verify
- siglen      The length of the signature (octets)
- hash        The hash (message digest) that was signed
- hashlen     The length of the hash (octets)
- res         Result of signature, 1==valid, 0==invalid
- key         The corresponding public ECC key
- return      MP_OKAY if successful (even if the signature is not valid)
- */
-int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
-                       word32 hashlen, int* res, ecc_key* key)
-{
-    int err;
-    mp_int *r = NULL, *s = NULL;
-#ifndef WOLFSSL_ASYNC_CRYPT
-#ifndef WOLFSSL_SMALL_STACK
-    mp_int r_lcl[1], s_lcl[1];
-#endif
-#endif
-
-    if (sig == NULL || hash == NULL || res == NULL || key == NULL) {
-        return ECC_BAD_ARG_E;
-    }
-
-#ifdef WOLF_CRYPTO_DEV
-    if (key->devId != INVALID_DEVID) {
-        err = wc_CryptoDev_EccVerify(sig, siglen, hash, hashlen, res, key);
-        if (err != NOT_COMPILED_IN)
-            return err;
-    }
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    err = wc_ecc_alloc_async(key);
-    if (err != 0)
-        return err;
-    r = key->r;
-    s = key->s;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    r = r_lcl;
-    s = s_lcl;
-#else
-    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-    if (r == NULL)
-        return MEMORY_E;
-    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-    if (s == NULL) {
-        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-#endif
-
-    switch(key->state) {
-        case ECC_STATE_NONE:
-        case ECC_STATE_VERIFY_DECODE:
-            key->state = ECC_STATE_VERIFY_DECODE;
-
-            /* default to invalid signature */
-            *res = 0;
-
-            /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
-             * If either of those don't allocate correctly, none of
-             * the rest of this function will execute, and everything
-             * gets cleaned up at the end. */
-            /* decode DSA header */
-            err = DecodeECC_DSA_Sig(sig, siglen, r, s);
-            if (err < 0) {
-                break;
-            }
-            FALL_THROUGH;
-
-        case ECC_STATE_VERIFY_DO:
-            key->state = ECC_STATE_VERIFY_DO;
-
-            err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key);
-
-        #ifndef WOLFSSL_ASYNC_CRYPT
-            /* done with R/S */
-            mp_clear(r);
-            mp_clear(s);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
-            XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
-        #endif
-        #endif
-
-            if (err < 0) {
-                break;
-            }
-            FALL_THROUGH;
-
-        case ECC_STATE_VERIFY_RES:
-            key->state = ECC_STATE_VERIFY_RES;
-            err = 0;
-            break;
-
-        default:
-            err = BAD_STATE_E;
-    }
-
-    /* if async pending then return and skip done cleanup below */
-    if (err == WC_PENDING_E) {
-        key->state++;
-        return err;
-    }
-
-    /* cleanup */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    wc_ecc_free_async(key);
-#endif
-    key->state = ECC_STATE_NONE;
-
-    return err;
-}
-#endif /* !NO_ASN */
-
-
-/**
-   Verify an ECC signature
-   r           The signature R component to verify
-   s           The signature S component to verify
-   hash        The hash (message digest) that was signed
-   hashlen     The length of the hash (octets)
-   res         Result of signature, 1==valid, 0==invalid
-   key         The corresponding public ECC key
-   return      MP_OKAY if successful (even if the signature is not valid)
-*/
-int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
-                    word32 hashlen, int* res, ecc_key* key)
-{
-   int           err;
-#ifdef WOLFSSL_ATECC508A
-   byte sigRS[ATECC_KEY_SIZE*2];
-#elif !defined(WOLFSSL_SP_MATH)
-   int          did_init = 0;
-   ecc_point    *mG = NULL, *mQ = NULL;
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int*       v = NULL;
-   mp_int*       w = NULL;
-   mp_int*       u1 = NULL;
-   mp_int*       u2 = NULL;
-#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
-   mp_int*       e_lcl = NULL;
-#endif
-#else /* WOLFSSL_SMALL_STACK */
-   mp_int        v[1];
-   mp_int        w[1];
-   mp_int        u1[1];
-   mp_int        u2[1];
-#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
-   mp_int        e_lcl[1];
-#endif
-#endif /* WOLFSSL_SMALL_STACK */
-   mp_int*       e;
-   DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
-#endif
-
-   if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL)
-       return ECC_BAD_ARG_E;
-
-   /* default to invalid signature */
-   *res = 0;
-
-   /* is the IDX valid ?  */
-   if (wc_ecc_is_valid_idx(key->idx) != 1) {
-      return ECC_BAD_ARG_E;
-   }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
-       defined(WOLFSSL_ASYNC_CRYPT_TEST)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_VERIFY)) {
-            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-            testDev->eccVerify.r = r;
-            testDev->eccVerify.s = s;
-            testDev->eccVerify.hash = hash;
-            testDev->eccVerify.hashlen = hashlen;
-            testDev->eccVerify.stat = res;
-            testDev->eccVerify.key = key;
-            return WC_PENDING_E;
-        }
-    }
-#endif
-
-#ifdef WOLFSSL_ATECC508A
-    /* Extract R and S */
-    err = mp_to_unsigned_bin(r, &sigRS[0]);
-    if (err != MP_OKAY) {
-        return err;
-    }
-    err = mp_to_unsigned_bin(s, &sigRS[ATECC_KEY_SIZE]);
-    if (err != MP_OKAY) {
-        return err;
-    }
-
-    err = atcatls_verify(hash, sigRS, key->pubkey_raw, (bool*)res);
-    if (err != ATCA_SUCCESS) {
-       return BAD_COND_E;
-    }
-    (void)hashlen;
-
-#else
-  /* checking if private key with no public part */
-  if (key->type == ECC_PRIVATEKEY_ONLY) {
-      WOLFSSL_MSG("Verify called with private key, generating public part");
-      err = wc_ecc_make_pub_ex(key, NULL, NULL);
-      if (err != MP_OKAY) {
-           WOLFSSL_MSG("Unable to extract public key");
-           return err;
-      }
-  }
-
-#ifdef WOLFSSL_SP_MATH
-  if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
-      return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y,
-                                           key->pubkey.z, r, s, res, key->heap);
-  }
-  else
-      return WC_KEY_SIZE_E;
-#else
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
-           defined(WOLFSSL_ASYNC_CRYPT_TEST)
-    if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC)
-    #endif
-    {
-        if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
-            return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y,
-                                     key->pubkey.z,r, s, res, key->heap);
-    }
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-
-   ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
-   err = wc_ecc_alloc_mpint(key, &key->e);
-   if (err != 0) {
-      FREE_CURVE_SPECS();
-      return err;
-   }
-   e = key->e;
-#else
-#ifdef WOLFSSL_SMALL_STACK
-   e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-   if (e_lcl == NULL) {
-       FREE_CURVE_SPECS();
-       return MEMORY_E;
-   }
-#endif
-   e = e_lcl;
-#endif
-
-   err = mp_init(e);
-   if (err != MP_OKAY)
-      return MEMORY_E;
-
-   /* read in the specs for this curve */
-   err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
-
-   /* check for zero */
-   if (err == MP_OKAY) {
-       if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES ||
-           mp_cmp(r, curve->order) != MP_LT ||
-           mp_cmp(s, curve->order) != MP_LT) {
-           err = MP_ZERO_E;
-       }
-   }
-
-   /* read hash */
-   if (err == MP_OKAY) {
-       /* we may need to truncate if hash is longer than key size */
-       unsigned int orderBits = mp_count_bits(curve->order);
-
-       /* truncate down to byte size, may be all that's needed */
-       if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
-           hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE;
-       err = mp_read_unsigned_bin(e, hash, hashlen);
-
-       /* may still need bit truncation too */
-       if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
-           mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
-   }
-
-   /* check for async hardware acceleration */
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
-   if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
-   #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)
-   #ifdef HAVE_CAVIUM_V
-      if (NitroxEccIsCurveSupported(key))
-   #endif
-      {
-          word32 keySz = key->dp->size;
-
-          err = wc_mp_to_bigint_sz(e, &e->raw, keySz);
-          if (err == MP_OKAY)
-              err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz);
-          if (err == MP_OKAY)
-              err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz);
-          if (err == MP_OKAY)
-          #ifdef HAVE_CAVIUM_V
-              err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw,
-                    &key->pubkey.y->raw, &r->raw, &s->raw,
-                    &curve->prime->raw, &curve->order->raw, res);
-          #else
-              err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw,
-                    &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw,
-                    &curve->Bf->raw, &curve->prime->raw, &curve->order->raw,
-                    &curve->Gx->raw, &curve->Gy->raw, res);
-          #endif
-
-      #ifndef HAVE_CAVIUM_V
-          mp_clear(e);
-      #endif
-          wc_ecc_curve_free(curve);
-          FREE_CURVE_SPECS();
-
-          return err;
-      }
-   #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */
-   }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-#ifdef WOLFSSL_SMALL_STACK
-   if (err == MP_OKAY) {
-       v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-       if (v == NULL)
-           err = MEMORY_E;
-   }
-   if (err == MP_OKAY) {
-       w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-       if (w == NULL)
-           err = MEMORY_E;
-   }
-   if (err == MP_OKAY) {
-       u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-       if (u1 == NULL)
-           err = MEMORY_E;
-   }
-   if (err == MP_OKAY) {
-       u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-       if (u2 == NULL)
-           err = MEMORY_E;
-   }
-#endif
-
-   /* allocate ints */
-   if (err == MP_OKAY) {
-       if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) {
-          err = MEMORY_E;
-       }
-       did_init = 1;
-   }
-
-   /* allocate points */
-   if (err == MP_OKAY) {
-       mG = wc_ecc_new_point_h(key->heap);
-       mQ = wc_ecc_new_point_h(key->heap);
-       if (mQ  == NULL || mG == NULL)
-          err = MEMORY_E;
-   }
-
-   /*  w  = s^-1 mod n */
-   if (err == MP_OKAY)
-       err = mp_invmod(s, curve->order, w);
-
-   /* u1 = ew */
-   if (err == MP_OKAY)
-       err = mp_mulmod(e, w, curve->order, u1);
-
-   /* u2 = rw */
-   if (err == MP_OKAY)
-       err = mp_mulmod(r, w, curve->order, u2);
-
-   /* find mG and mQ */
-   if (err == MP_OKAY)
-       err = mp_copy(curve->Gx, mG->x);
-   if (err == MP_OKAY)
-       err = mp_copy(curve->Gy, mG->y);
-   if (err == MP_OKAY)
-       err = mp_set(mG->z, 1);
-
-   if (err == MP_OKAY)
-       err = mp_copy(key->pubkey.x, mQ->x);
-   if (err == MP_OKAY)
-       err = mp_copy(key->pubkey.y, mQ->y);
-   if (err == MP_OKAY)
-       err = mp_copy(key->pubkey.z, mQ->z);
-
-#ifdef FREESCALE_LTC_ECC
-   /* use PKHA to compute u1*mG + u2*mQ */
-   if (err == MP_OKAY)
-       err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap);
-   if (err == MP_OKAY)
-       err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap);
-   if (err == MP_OKAY)
-       err = wc_ecc_point_add(mG, mQ, mG, curve->prime);
-#else
-#ifndef ECC_SHAMIR
-    {
-        mp_digit      mp = 0;
-
-        /* compute u1*mG + u2*mQ = mG */
-        if (err == MP_OKAY) {
-            err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
-                                                                     key->heap);
-        }
-        if (err == MP_OKAY) {
-            err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
-                                                                     key->heap);
-        }
-
-        /* find the montgomery mp */
-        if (err == MP_OKAY)
-            err = mp_montgomery_setup(curve->prime, &mp);
-
-        /* add them */
-        if (err == MP_OKAY)
-            err = ecc_projective_add_point(mQ, mG, mG, curve->Af,
-                                                             curve->prime, mp);
-
-        /* reduce */
-        if (err == MP_OKAY)
-            err = ecc_map(mG, curve->prime, mp);
-    }
-#else
-       /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
-        if (err == MP_OKAY) {
-            err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime,
-                                                                    key->heap);
-        }
-#endif /* ECC_SHAMIR */
-#endif /* FREESCALE_LTC_ECC */
-   /* v = X_x1 mod n */
-   if (err == MP_OKAY)
-       err = mp_mod(mG->x, curve->order, v);
-
-   /* does v == r */
-   if (err == MP_OKAY) {
-       if (mp_cmp(v, r) == MP_EQ)
-           *res = 1;
-   }
-
-   /* cleanup */
-   wc_ecc_del_point_h(mG, key->heap);
-   wc_ecc_del_point_h(mQ, key->heap);
-
-   mp_clear(e);
-   if (did_init) {
-       mp_clear(v);
-       mp_clear(w);
-       mp_clear(u1);
-       mp_clear(u2);
-   }
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(u2, key->heap, DYNAMIC_TYPE_ECC);
-   XFREE(u1, key->heap, DYNAMIC_TYPE_ECC);
-   XFREE(w, key->heap, DYNAMIC_TYPE_ECC);
-   XFREE(v, key->heap, DYNAMIC_TYPE_ECC);
-#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
-   XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC);
-#endif
-#endif
-
-   wc_ecc_curve_free(curve);
-   FREE_CURVE_SPECS();
-
-#endif /* WOLFSSL_SP_MATH */
-#endif /* WOLFSSL_ATECC508A */
-
-   return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_KEY_IMPORT
-/* import point from der */
-int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
-                            ecc_point* point)
-{
-    int err = 0;
-#ifndef WOLFSSL_ATECC508A
-    int compressed = 0;
-    int keysize;
-    byte pointType;
-
-    if (in == NULL || point == NULL || (curve_idx < 0) ||
-        (wc_ecc_is_valid_idx(curve_idx) == 0))
-        return ECC_BAD_ARG_E;
-
-    /* must be odd */
-    if ((inLen & 1) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-
-    /* init point */
-#ifdef ALT_ECC_SIZE
-    point->x = (mp_int*)&point->xyz[0];
-    point->y = (mp_int*)&point->xyz[1];
-    point->z = (mp_int*)&point->xyz[2];
-    alt_fp_init(point->x);
-    alt_fp_init(point->y);
-    alt_fp_init(point->z);
-#else
-    err = mp_init_multi(point->x, point->y, point->z, NULL, NULL, NULL);
-#endif
-    if (err != MP_OKAY)
-        return MEMORY_E;
-
-    /* check for point type (4, 2, or 3) */
-    pointType = in[0];
-    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
-                                         pointType != ECC_POINT_COMP_ODD) {
-        err = ASN_PARSE_E;
-    }
-
-    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
-#ifdef HAVE_COMP_KEY
-        compressed = 1;
-#else
-        err = NOT_COMPILED_IN;
-#endif
-    }
-
-    /* adjust to skip first byte */
-    inLen -= 1;
-    in += 1;
-
-    /* calculate key size based on inLen / 2 */
-    keysize = inLen>>1;
-
-#ifdef WOLFSSL_ATECC508A
-    /* populate key->pubkey_raw */
-    XMEMCPY(key->pubkey_raw, (byte*)in, sizeof(key->pubkey_raw));
-#endif
-
-    /* read data */
-    if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(point->x, (byte*)in, keysize);
-
-#ifdef HAVE_COMP_KEY
-    if (err == MP_OKAY && compressed == 1) {   /* build y */
-#ifndef WOLFSSL_SP_MATH
-        int did_init = 0;
-        mp_int t1, t2;
-        DECLARE_CURVE_SPECS(curve, 3);
-
-        ALLOC_CURVE_SPECS(3);
-
-        if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
-            err = MEMORY_E;
-        else
-            did_init = 1;
-
-        /* load curve info */
-        if (err == MP_OKAY)
-            err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve,
-                (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF |
-                    ECC_CURVE_FIELD_BF));
-
-        /* compute x^3 */
-        if (err == MP_OKAY)
-            err = mp_sqr(point->x, &t1);
-        if (err == MP_OKAY)
-            err = mp_mulmod(&t1, point->x, curve->prime, &t1);
-
-        /* compute x^3 + a*x */
-        if (err == MP_OKAY)
-            err = mp_mulmod(curve->Af, point->x, curve->prime, &t2);
-        if (err == MP_OKAY)
-            err = mp_add(&t1, &t2, &t1);
-
-        /* compute x^3 + a*x + b */
-        if (err == MP_OKAY)
-            err = mp_add(&t1, curve->Bf, &t1);
-
-        /* compute sqrt(x^3 + a*x + b) */
-        if (err == MP_OKAY)
-            err = mp_sqrtmod_prime(&t1, curve->prime, &t2);
-
-        /* adjust y */
-        if (err == MP_OKAY) {
-            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
-                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
-                err = mp_mod(&t2, curve->prime, point->y);
-            }
-            else {
-                err = mp_submod(curve->prime, &t2, curve->prime, point->y);
-            }
-        }
-
-        if (did_init) {
-            mp_clear(&t2);
-            mp_clear(&t1);
-        }
-
-        wc_ecc_curve_free(curve);
-        FREE_CURVE_SPECS();
-#else
-        sp_ecc_uncompress_256(point->x, pointType, point->y);
-#endif
-    }
-#endif
-
-    if (err == MP_OKAY && compressed == 0)
-        err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize);
-    if (err == MP_OKAY)
-        err = mp_set(point->z, 1);
-
-    if (err != MP_OKAY) {
-        mp_clear(point->x);
-        mp_clear(point->y);
-        mp_clear(point->z);
-    }
-
-#else
-    err = NOT_COMPILED_IN;
-    (void)in;
-    (void)inLen;
-    (void)curve_idx;
-    (void)point;
-#endif /* !WOLFSSL_ATECC508A */
-
-    return err;
-}
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-#ifdef HAVE_ECC_KEY_EXPORT
-/* export point to der */
-int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out,
-                            word32* outLen)
-{
-    int    ret = MP_OKAY;
-    word32 numlen;
-#ifndef WOLFSSL_ATECC508A
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  buf;
-#else
-    byte   buf[ECC_BUFSIZE];
-#endif
-#endif /* !WOLFSSL_ATECC508A */
-
-    if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
-        return ECC_BAD_ARG_E;
-
-    /* return length needed only */
-    if (point != NULL && out == NULL && outLen != NULL) {
-        numlen = ecc_sets[curve_idx].size;
-        *outLen = 1 + 2*numlen;
-        return LENGTH_ONLY_E;
-    }
-
-    if (point == NULL || out == NULL || outLen == NULL)
-        return ECC_BAD_ARG_E;
-
-    numlen = ecc_sets[curve_idx].size;
-
-    if (*outLen < (1 + 2*numlen)) {
-        *outLen = 1 + 2*numlen;
-        return BUFFER_E;
-    }
-
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   ret = BAD_COND_E;
-
-#else
-
-    /* store byte point type */
-    out[0] = ECC_POINT_UNCOMP;
-
-#ifdef WOLFSSL_SMALL_STACK
-    buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (buf == NULL)
-        return MEMORY_E;
-#endif
-
-    /* pad and store x */
-    XMEMSET(buf, 0, ECC_BUFSIZE);
-    ret = mp_to_unsigned_bin(point->x, buf +
-                                 (numlen - mp_unsigned_bin_size(point->x)));
-    if (ret != MP_OKAY)
-        goto done;
-    XMEMCPY(out+1, buf, numlen);
-
-    /* pad and store y */
-    XMEMSET(buf, 0, ECC_BUFSIZE);
-    ret = mp_to_unsigned_bin(point->y, buf +
-                                 (numlen - mp_unsigned_bin_size(point->y)));
-    if (ret != MP_OKAY)
-        goto done;
-    XMEMCPY(out+1+numlen, buf, numlen);
-
-    *outLen = 1 + 2*numlen;
-
-done:
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-#endif /* WOLFSSL_ATECC508A */
-
-    return ret;
-}
-
-
-/* export public ECC key in ANSI X9.63 format */
-int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
-{
-   int    ret = MP_OKAY;
-   word32 numlen;
-#ifdef WOLFSSL_SMALL_STACK
-   byte*  buf;
-#else
-   byte   buf[ECC_BUFSIZE];
-#endif
-   word32 pubxlen, pubylen;
-
-   /* return length needed only */
-   if (key != NULL && out == NULL && outLen != NULL) {
-      numlen = key->dp->size;
-      *outLen = 1 + 2*numlen;
-      return LENGTH_ONLY_E;
-   }
-
-   if (key == NULL || out == NULL || outLen == NULL)
-      return ECC_BAD_ARG_E;
-
-   if (key->type == ECC_PRIVATEKEY_ONLY)
-       return ECC_PRIVATEONLY_E;
-
-   if (wc_ecc_is_valid_idx(key->idx) == 0) {
-      return ECC_BAD_ARG_E;
-   }
-   numlen = key->dp->size;
-
-    /* verify room in out buffer */
-   if (*outLen < (1 + 2*numlen)) {
-      *outLen = 1 + 2*numlen;
-      return BUFFER_E;
-   }
-
-   /* verify public key length is less than key size */
-   pubxlen = mp_unsigned_bin_size(key->pubkey.x);
-   pubylen = mp_unsigned_bin_size(key->pubkey.y);
-   if ((pubxlen > numlen) || (pubylen > numlen)) {
-      WOLFSSL_MSG("Public key x/y invalid!");
-      return BUFFER_E;
-   }
-
-   /* store byte point type */
-   out[0] = ECC_POINT_UNCOMP;
-
-#ifdef WOLFSSL_SMALL_STACK
-   buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-   if (buf == NULL)
-      return MEMORY_E;
-#endif
-
-   /* pad and store x */
-   XMEMSET(buf, 0, ECC_BUFSIZE);
-   ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen));
-   if (ret != MP_OKAY)
-      goto done;
-   XMEMCPY(out+1, buf, numlen);
-
-   /* pad and store y */
-   XMEMSET(buf, 0, ECC_BUFSIZE);
-   ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen));
-   if (ret != MP_OKAY)
-      goto done;
-   XMEMCPY(out+1+numlen, buf, numlen);
-
-   *outLen = 1 + 2*numlen;
-
-done:
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-
-   return ret;
-}
-
-
-/* export public ECC key in ANSI X9.63 format, extended with
- * compression option */
-int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen,
-                          int compressed)
-{
-    if (compressed == 0)
-        return wc_ecc_export_x963(key, out, outLen);
-#ifdef HAVE_COMP_KEY
-    else
-        return wc_ecc_export_x963_compressed(key, out, outLen);
-#else
-    return NOT_COMPILED_IN;
-#endif
-}
-#endif /* HAVE_ECC_KEY_EXPORT */
-
-
-#ifndef WOLFSSL_ATECC508A
-
-/* is ecc point on curve described by dp ? */
-int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime)
-{
-#ifndef WOLFSSL_SP_MATH
-   int err;
-#ifdef WOLFSSL_SMALL_STACK
-   mp_int* t1 = NULL;
-   mp_int* t2 = NULL;
-#else
-   mp_int  t1[1], t2[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-   t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-   if (t1 == NULL)
-       return MEMORY_E;
-   t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-   if (t2 == NULL) {
-       XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-       return MEMORY_E;
-   }
-#endif
-
-   if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-   #ifdef WOLFSSL_SMALL_STACK
-      XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-      XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-   #endif
-      return err;
-   }
-
-   /* compute y^2 */
-   if (err == MP_OKAY)
-       err = mp_sqr(ecp->y, t1);
-
-   /* compute x^3 */
-   if (err == MP_OKAY)
-       err = mp_sqr(ecp->x, t2);
-   if (err == MP_OKAY)
-       err = mp_mod(t2, prime, t2);
-   if (err == MP_OKAY)
-       err = mp_mul(ecp->x, t2, t2);
-
-   /* compute y^2 - x^3 */
-   if (err == MP_OKAY)
-       err = mp_sub(t1, t2, t1);
-
-   /* Determine if curve "a" should be used in calc */
-#ifdef WOLFSSL_CUSTOM_CURVES
-   if (err == MP_OKAY) {
-      /* Use a and prime to determine if a == 3 */
-      err = mp_set(t2, 0);
-      if (err == MP_OKAY)
-          err = mp_submod(prime, a, prime, t2);
-   }
-   if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) {
-      /* compute y^2 - x^3 + a*x */
-      if (err == MP_OKAY)
-          err = mp_mulmod(t2, ecp->x, prime, t2);
-      if (err == MP_OKAY)
-          err = mp_addmod(t1, t2, prime, t1);
-   }
-   else
-#endif /* WOLFSSL_CUSTOM_CURVES */
-   {
-      /* assumes "a" == 3 */
-      (void)a;
-
-      /* compute y^2 - x^3 + 3x */
-      if (err == MP_OKAY)
-          err = mp_add(t1, ecp->x, t1);
-      if (err == MP_OKAY)
-          err = mp_add(t1, ecp->x, t1);
-      if (err == MP_OKAY)
-          err = mp_add(t1, ecp->x, t1);
-      if (err == MP_OKAY)
-          err = mp_mod(t1, prime, t1);
-  }
-
-   /* adjust range (0, prime) */
-   while (err == MP_OKAY && mp_isneg(t1)) {
-      err = mp_add(t1, prime, t1);
-   }
-   while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) {
-      err = mp_sub(t1, prime, t1);
-   }
-
-   /* compare to b */
-   if (err == MP_OKAY) {
-       if (mp_cmp(t1, b) != MP_EQ) {
-          err = MP_VAL;
-       } else {
-          err = MP_OKAY;
-       }
-   }
-
-   mp_clear(t1);
-   mp_clear(t2);
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(t2, NULL, DYNAMIC_TYPE_ECC);
-   XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-   return err;
-#else
-   (void)a;
-   (void)b;
-   (void)prime;
-
-   return sp_ecc_is_point_256(ecp->x, ecp->y);
-#endif
-}
-
-#ifndef WOLFSSL_SP_MATH
-/* validate privkey * generator == pubkey, 0 on success */
-static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
-{
-    int        err = MP_OKAY;
-    ecc_point* base = NULL;
-    ecc_point* res  = NULL;
-    DECLARE_CURVE_SPECS(curve, 2);
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    ALLOC_CURVE_SPECS(2);
-
-    res = wc_ecc_new_point_h(key->heap);
-    if (res == NULL)
-        err = MEMORY_E;
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
-        if (err == MP_OKAY)
-            err = sp_ecc_mulmod_base_256(&key->k, res, 1, key->heap);
-    }
-    else
-#endif
-#endif
-    {
-        base = wc_ecc_new_point_h(key->heap);
-        if (base == NULL)
-            err = MEMORY_E;
-
-        if (err == MP_OKAY) {
-            /* load curve info */
-            err = wc_ecc_curve_load(key->dp, &curve,
-                                      (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY));
-        }
-
-        /* set up base generator */
-        if (err == MP_OKAY)
-            err = mp_copy(curve->Gx, base->x);
-        if (err == MP_OKAY)
-            err = mp_copy(curve->Gy, base->y);
-        if (err == MP_OKAY)
-            err = mp_set(base->z, 1);
-
-        if (err == MP_OKAY)
-            err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* compare result to public key */
-        if (mp_cmp(res->x, key->pubkey.x) != MP_EQ ||
-            mp_cmp(res->y, key->pubkey.y) != MP_EQ ||
-            mp_cmp(res->z, key->pubkey.z) != MP_EQ) {
-            /* didn't match */
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-    wc_ecc_curve_free(curve);
-    wc_ecc_del_point_h(res, key->heap);
-    wc_ecc_del_point_h(base, key->heap);
-    FREE_CURVE_SPECS();
-
-    return err;
-}
-#endif
-
-#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
-
-/* check privkey generator helper, creates prime needed */
-static int ecc_check_privkey_gen_helper(ecc_key* key)
-{
-    int    err;
-#ifndef WOLFSSL_ATECC508A
-    DECLARE_CURVE_SPECS(curve, 2);
-#endif
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    err = BAD_COND_E;
-
-#else
-    ALLOC_CURVE_SPECS(2);
-
-    /* load curve info */
-    err = wc_ecc_curve_load(key->dp, &curve,
-        (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF));
-
-    if (err == MP_OKAY)
-        err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
-
-    wc_ecc_curve_free(curve);
-    FREE_CURVE_SPECS();
-
-#endif /* WOLFSSL_ATECC508A */
-
-    return err;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
-
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)
-/* validate order * pubkey = point at infinity, 0 on success */
-static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
-        mp_int* prime, mp_int* order)
-{
-    ecc_point* inf = NULL;
-    int        err;
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    inf = wc_ecc_new_point_h(key->heap);
-    if (inf == NULL)
-        err = MEMORY_E;
-    else {
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-        if (key->idx != ECC_CUSTOM_IDX &&
-                                       ecc_sets[key->idx].id == ECC_SECP256R1) {
-            err = sp_ecc_mulmod_256(order, pubkey, inf, 1, key->heap);
-        }
-        else
-#endif
-#endif
-#ifndef WOLFSSL_SP_MATH
-            err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap);
-        if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf))
-            err = ECC_INF_E;
-#else
-            (void)a;
-            (void)prime;
-
-            err = WC_KEY_SIZE_E;
-#endif
-    }
-
-    wc_ecc_del_point_h(inf, key->heap);
-
-    return err;
-}
-#endif
-#endif /* !WOLFSSL_ATECC508A */
-
-
-/* perform sanity checks on ecc key validity, 0 on success */
-int wc_ecc_check_key(ecc_key* key)
-{
-    int    err;
-#ifndef WOLFSSL_SP_MATH
-#ifndef WOLFSSL_ATECC508A
-    mp_int* b = NULL;
-#ifdef USE_ECC_B_PARAM
-    DECLARE_CURVE_SPECS(curve, 4);
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    mp_int b_lcl;
-#endif
-    DECLARE_CURVE_SPECS(curve, 3);
-#endif /* USE_ECC_B_PARAM */
-#endif /* WOLFSSL_ATECC508A */
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_ATECC508A
-
-    if (key->slot == ATECC_INVALID_SLOT)
-        return ECC_BAD_ARG_E;
-
-    err = 0; /* consider key check success on ECC508A */
-
-#else
-    #ifdef USE_ECC_B_PARAM
-        ALLOC_CURVE_SPECS(4);
-    #else
-        ALLOC_CURVE_SPECS(3);
-        #ifndef WOLFSSL_SMALL_STACK
-            b = &b_lcl;
-        #else
-            b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
-            if (b == NULL) {
-                FREE_CURVE_SPECS();
-                return MEMORY_E;
-            }
-        #endif
-        XMEMSET(b, 0, sizeof(mp_int));
-    #endif
-
-    /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
-    /* pubkey point cannot be at infinity */
-    if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
-    #endif
-        FREE_CURVE_SPECS();
-        return ECC_INF_E;
-    }
-
-    /* load curve info */
-    err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME |
-            ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER
-#ifdef USE_ECC_B_PARAM
-            | ECC_CURVE_FIELD_BF
-#endif
-    ));
-
-#ifndef USE_ECC_B_PARAM
-    /* load curve b parameter */
-    if (err == MP_OKAY)
-        err = mp_init(b);
-    if (err == MP_OKAY)
-        err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX);
-#else
-    b = curve->Bf;
-#endif
-
-    /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */
-    /* Qx must be in the range [0, p-1] */
-    if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT)
-        err = ECC_OUT_OF_RANGE_E;
-
-    /* Qy must be in the range [0, p-1] */
-    if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT)
-        err = ECC_OUT_OF_RANGE_E;
-
-    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */
-    /* make sure point is actually on curve */
-    if (err == MP_OKAY)
-        err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
-
-    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */
-    /* pubkey * order must be at infinity */
-    if (err == MP_OKAY)
-        err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime,
-                curve->order);
-
-    /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
-    /* private * base generator must equal pubkey */
-    if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
-        err = ecc_check_privkey_gen(key, curve->Af, curve->prime);
-
-    wc_ecc_curve_free(curve);
-
-#ifndef USE_ECC_B_PARAM
-    mp_clear(b);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
-    #endif
-#endif
-
-    FREE_CURVE_SPECS();
-
-#endif /* WOLFSSL_ATECC508A */
-#else
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* pubkey point cannot be at infinity */
-    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
-        err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k,
-                                                                     key->heap);
-    }
-    else
-        err = WC_KEY_SIZE_E;
-#endif
-
-    return err;
-}
-
-#ifdef HAVE_ECC_KEY_IMPORT
-/* import public ECC key in ANSI X9.63 format */
-int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
-                          int curve_id)
-{
-    int err = MP_OKAY;
-    int compressed = 0;
-    int keysize = 0;
-    byte pointType;
-
-    if (in == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* must be odd */
-    if ((inLen & 1) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-
-    /* make sure required variables are reset */
-    wc_ecc_reset(key);
-
-    /* init key */
-    #ifdef ALT_ECC_SIZE
-        key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
-        key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
-        key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
-        alt_fp_init(key->pubkey.x);
-        alt_fp_init(key->pubkey.y);
-        alt_fp_init(key->pubkey.z);
-        err = mp_init(&key->k);
-    #else
-        err = mp_init_multi(&key->k,
-                    key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL);
-    #endif
-    if (err != MP_OKAY)
-        return MEMORY_E;
-
-    /* check for point type (4, 2, or 3) */
-    pointType = in[0];
-    if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN &&
-                                         pointType != ECC_POINT_COMP_ODD) {
-        err = ASN_PARSE_E;
-    }
-
-    if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) {
-    #ifdef HAVE_COMP_KEY
-        compressed = 1;
-    #else
-        err = NOT_COMPILED_IN;
-    #endif
-    }
-
-    /* adjust to skip first byte */
-    inLen -= 1;
-    in += 1;
-
-    if (err == MP_OKAY) {
-    #ifdef HAVE_COMP_KEY
-        /* adjust inLen if compressed */
-        if (compressed)
-            inLen = inLen*2 + 1;  /* used uncompressed len */
-    #endif
-
-        /* determine key size */
-        keysize = (inLen>>1);
-        err = wc_ecc_set_curve(key, keysize, curve_id);
-        key->type = ECC_PUBLICKEY;
-    }
-
-    /* read data */
-    if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize);
-
-#ifdef HAVE_COMP_KEY
-    if (err == MP_OKAY && compressed == 1) {   /* build y */
-#ifndef WOLFSSL_SP_MATH
-        mp_int t1, t2;
-        int did_init = 0;
-
-        DECLARE_CURVE_SPECS(curve, 3);
-        ALLOC_CURVE_SPECS(3);
-
-        if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY)
-            err = MEMORY_E;
-        else
-            did_init = 1;
-
-        /* load curve info */
-        if (err == MP_OKAY)
-            err = wc_ecc_curve_load(key->dp, &curve,
-                (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF |
-                 ECC_CURVE_FIELD_BF));
-
-        /* compute x^3 */
-        if (err == MP_OKAY)
-            err = mp_sqr(key->pubkey.x, &t1);
-        if (err == MP_OKAY)
-            err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1);
-
-        /* compute x^3 + a*x */
-        if (err == MP_OKAY)
-            err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2);
-        if (err == MP_OKAY)
-            err = mp_add(&t1, &t2, &t1);
-
-        /* compute x^3 + a*x + b */
-        if (err == MP_OKAY)
-            err = mp_add(&t1, curve->Bf, &t1);
-
-        /* compute sqrt(x^3 + a*x + b) */
-        if (err == MP_OKAY)
-            err = mp_sqrtmod_prime(&t1, curve->prime, &t2);
-
-        /* adjust y */
-        if (err == MP_OKAY) {
-            if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) ||
-                (mp_isodd(&t2) == MP_NO &&  pointType == ECC_POINT_COMP_EVEN)) {
-                err = mp_mod(&t2, curve->prime, &t2);
-            }
-            else {
-                err = mp_submod(curve->prime, &t2, curve->prime, &t2);
-            }
-            if (err == MP_OKAY)
-                err = mp_copy(&t2, key->pubkey.y);
-        }
-
-        if (did_init) {
-            mp_clear(&t2);
-            mp_clear(&t1);
-        }
-
-        wc_ecc_curve_free(curve);
-        FREE_CURVE_SPECS();
-#else
-        sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y);
-#endif
-    }
-#endif /* HAVE_COMP_KEY */
-
-    if (err == MP_OKAY && compressed == 0)
-        err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize, keysize);
-    if (err == MP_OKAY)
-        err = mp_set(key->pubkey.z, 1);
-
-#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
-    if (err == MP_OKAY)
-        err = wc_ecc_check_key(key);
-#endif
-
-    if (err != MP_OKAY) {
-        mp_clear(key->pubkey.x);
-        mp_clear(key->pubkey.y);
-        mp_clear(key->pubkey.z);
-        mp_clear(&key->k);
-    }
-
-    return err;
-}
-
-int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
-{
-    return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF);
-}
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-#ifdef HAVE_ECC_KEY_EXPORT
-/* export ecc private key only raw, outLen is in/out size
-   return MP_OKAY on success */
-int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
-{
-    word32 numlen;
-
-    if (key == NULL || out == NULL || outLen == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (wc_ecc_is_valid_idx(key->idx) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-    numlen = key->dp->size;
-
-    if (*outLen < numlen) {
-        *outLen = numlen;
-        return BUFFER_E;
-    }
-    *outLen = numlen;
-    XMEMSET(out, 0, *outLen);
-
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   return BAD_COND_E;
-
-#else
-
-    return mp_to_unsigned_bin(&key->k, out + (numlen -
-                                           mp_unsigned_bin_size(&key->k)));
-#endif /* WOLFSSL_ATECC508A */
-}
-
-
-/* export ecc key to component form, d is optional if only exporting public
- * return MP_OKAY on success */
-static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen,
-                             byte* qy, word32* qyLen, byte* d, word32* dLen)
-{
-    int  err;
-    byte exportPriv = 0;
-    word32 numLen;
-
-    if (key == NULL || qx == NULL || qxLen == NULL || qy == NULL ||
-        qyLen == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (key->type == ECC_PRIVATEKEY_ONLY) {
-        return ECC_PRIVATEONLY_E;
-    }
-
-    if (wc_ecc_is_valid_idx(key->idx) == 0) {
-        return ECC_BAD_ARG_E;
-    }
-    numLen = key->dp->size;
-
-    if (d != NULL) {
-        if (dLen == NULL || key->type != ECC_PRIVATEKEY)
-            return BAD_FUNC_ARG;
-        exportPriv = 1;
-    }
-
-    /* check public buffer sizes */
-    if ((*qxLen < numLen) || (*qyLen < numLen)) {
-        *qxLen = numLen;
-        *qyLen = numLen;
-        return BUFFER_E;
-    }
-
-    *qxLen = numLen;
-    *qyLen = numLen;
-
-    XMEMSET(qx, 0, *qxLen);
-    XMEMSET(qy, 0, *qyLen);
-
-    /* private d component */
-    if (exportPriv == 1) {
-
-        /* check private buffer size */
-        if (*dLen < numLen) {
-            *dLen = numLen;
-            return BUFFER_E;
-        }
-
-        *dLen = numLen;
-        XMEMSET(d, 0, *dLen);
-
-    #ifdef WOLFSSL_ATECC508A
-       /* TODO: Implement equiv call to ATECC508A */
-       return BAD_COND_E;
-
-    #else
-
-        /* private key, d */
-        err = mp_to_unsigned_bin(&key->k, d +
-                            (numLen - mp_unsigned_bin_size(&key->k)));
-        if (err != MP_OKAY)
-            return err;
-    #endif /* WOLFSSL_ATECC508A */
-    }
-
-    /* public x component */
-    err = mp_to_unsigned_bin(key->pubkey.x, qx +
-                            (numLen - mp_unsigned_bin_size(key->pubkey.x)));
-    if (err != MP_OKAY)
-        return err;
-
-    /* public y component */
-    err = mp_to_unsigned_bin(key->pubkey.y, qy +
-                            (numLen - mp_unsigned_bin_size(key->pubkey.y)));
-    if (err != MP_OKAY)
-        return err;
-
-    return 0;
-}
-
-
-/* export public key to raw elements including public (Qx,Qy)
- * return MP_OKAY on success, negative on error */
-int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
-                             byte* qy, word32* qyLen)
-{
-    return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, NULL, NULL);
-}
-
-
-/* export ecc key to raw elements including public (Qx,Qy) and private (d)
- * return MP_OKAY on success, negative on error */
-int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen,
-                              byte* qy, word32* qyLen, byte* d, word32* dLen)
-{
-    /* sanitize d and dLen, other args are checked later */
-    if (d == NULL || dLen == NULL)
-        return BAD_FUNC_ARG;
-
-    return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, d, dLen);
-}
-
-#endif /* HAVE_ECC_KEY_EXPORT */
-
-#ifdef HAVE_ECC_KEY_IMPORT
-/* import private key, public part optional if (pub) passed as NULL */
-int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
-                                 const byte* pub, word32 pubSz, ecc_key* key,
-                                 int curve_id)
-{
-    int ret;
-    word32 idx = 0;
-
-    if (key == NULL || priv == NULL)
-        return BAD_FUNC_ARG;
-
-    /* public optional, NULL if only importing private */
-    if (pub != NULL) {
-        ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id);
-        if (ret < 0)
-            ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz);
-        key->type = ECC_PRIVATEKEY;
-    }
-    else {
-        /* make sure required variables are reset */
-        wc_ecc_reset(key);
-
-        /* set key size */
-        ret = wc_ecc_set_curve(key, privSz, curve_id);
-        key->type = ECC_PRIVATEKEY_ONLY;
-    }
-
-    if (ret != 0)
-        return ret;
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    return BAD_COND_E;
-
-#else
-
-    ret = mp_read_unsigned_bin(&key->k, priv, privSz);
-
-#endif /* WOLFSSL_ATECC508A */
-
-#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
-    if ((pub != NULL) && (ret == MP_OKAY))
-        /* public key needed to perform key validation */
-        ret = ecc_check_privkey_gen_helper(key);
-#endif
-
-    return ret;
-}
-
-/* ecc private key import, public key in ANSI X9.63 format, private raw */
-int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
-                           word32 pubSz, ecc_key* key)
-{
-    return wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, key,
-                                                                ECC_CURVE_DEF);
-}
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-#ifndef NO_ASN
-/**
-   Convert ECC R,S to signature
-   r       R component of signature
-   s       S component of signature
-   out     DER-encoded ECDSA signature
-   outlen  [in/out] output buffer size, output signature size
-   return  MP_OKAY on success
-*/
-int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
-{
-    int err;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* rtmp = NULL;
-    mp_int* stmp = NULL;
-#else
-    mp_int  rtmp[1];
-    mp_int  stmp[1];
-#endif
-
-    if (r == NULL || s == NULL || out == NULL || outlen == NULL)
-        return ECC_BAD_ARG_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (rtmp == NULL)
-        return MEMORY_E;
-    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (stmp == NULL) {
-        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-
-    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
-    if (err != MP_OKAY) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
-        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-        return err;
-    }
-
-    err = mp_read_radix(rtmp, r, MP_RADIX_HEX);
-    if (err == MP_OKAY)
-        err = mp_read_radix(stmp, s, MP_RADIX_HEX);
-
-    /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
-    if (err == MP_OKAY)
-        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
-
-    if (err == MP_OKAY) {
-        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
-            err = MP_ZERO_E;
-    }
-
-    mp_clear(rtmp);
-    mp_clear(stmp);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
-    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/**
-   Convert ECC R,S raw unsigned bin to signature
-   r       R component of signature
-   rSz     R size
-   s       S component of signature
-   sSz     S size
-   out     DER-encoded ECDSA signature
-   outlen  [in/out] output buffer size, output signature size
-   return  MP_OKAY on success
-*/
-int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
-    byte* out, word32* outlen)
-{
-    int err;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* rtmp = NULL;
-    mp_int* stmp = NULL;
-#else
-    mp_int  rtmp[1];
-    mp_int  stmp[1];
-#endif
-
-    if (r == NULL || s == NULL || out == NULL || outlen == NULL)
-        return ECC_BAD_ARG_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (rtmp == NULL)
-        return MEMORY_E;
-    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (stmp == NULL) {
-        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-
-    err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
-    if (err != MP_OKAY) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
-        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-    #endif
-        return err;
-    }
-
-    err = mp_read_unsigned_bin(rtmp, r, rSz);
-    if (err == MP_OKAY)
-        err = mp_read_unsigned_bin(stmp, s, sSz);
-
-    /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
-    if (err == MP_OKAY)
-        err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
-
-    if (err == MP_OKAY) {
-        if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
-            err = MP_ZERO_E;
-    }
-
-    mp_clear(rtmp);
-    mp_clear(stmp);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
-    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/**
-   Convert ECC signature to R,S
-   sig     DER-encoded ECDSA signature
-   sigLen  length of signature in octets
-   r       R component of signature
-   rLen    [in/out] output "r" buffer size, output "r" size
-   s       S component of signature
-   sLen    [in/out] output "s" buffer size, output "s" size
-   return  MP_OKAY on success, negative on error
-*/
-int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen,
-                     byte* s, word32* sLen)
-{
-    int err;
-    word32 x = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* rtmp = NULL;
-    mp_int* stmp = NULL;
-#else
-    mp_int  rtmp[1];
-    mp_int  stmp[1];
-#endif
-
-    if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL)
-        return ECC_BAD_ARG_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (rtmp == NULL)
-        return MEMORY_E;
-    stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
-    if (stmp == NULL) {
-        XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-        return MEMORY_E;
-    }
-#endif
-
-    err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp);
-
-    /* extract r */
-    if (err == MP_OKAY) {
-        x = mp_unsigned_bin_size(rtmp);
-        if (*rLen < x)
-            err = BUFFER_E;
-
-        if (err == MP_OKAY) {
-            *rLen = x;
-            err = mp_to_unsigned_bin(rtmp, r);
-        }
-    }
-
-    /* extract s */
-    if (err == MP_OKAY) {
-        x = mp_unsigned_bin_size(stmp);
-        if (*sLen < x)
-            err = BUFFER_E;
-
-        if (err == MP_OKAY) {
-            *sLen = x;
-            err = mp_to_unsigned_bin(stmp, s);
-        }
-    }
-
-    mp_clear(rtmp);
-    mp_clear(stmp);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
-    XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif /* !NO_ASN */
-
-#ifdef HAVE_ECC_KEY_IMPORT
-static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
-          const char* qy, const char* d, int curve_id, int encType)
-{
-    int err = MP_OKAY;
-
-    /* if d is NULL, only import as public key using Qx,Qy */
-    if (key == NULL || qx == NULL || qy == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* make sure required variables are reset */
-    wc_ecc_reset(key);
-
-    /* set curve type and index */
-    err = wc_ecc_set_curve(key, 0, curve_id);
-    if (err != 0) {
-        return err;
-    }
-
-#ifdef WOLFSSL_ATECC508A
-    /* TODO: Implement equiv call to ATECC508A */
-    err = BAD_COND_E;
-    (void)d;
-    (void)encType;
-
-#else
-
-    /* init key */
-#ifdef ALT_ECC_SIZE
-    key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
-    key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
-    key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
-    alt_fp_init(key->pubkey.x);
-    alt_fp_init(key->pubkey.y);
-    alt_fp_init(key->pubkey.z);
-    err = mp_init(&key->k);
-#else
-    err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
-                                                                  NULL, NULL);
-#endif
-    if (err != MP_OKAY)
-        return MEMORY_E;
-
-    /* read Qx */
-    if (err == MP_OKAY) {
-        if (encType == ECC_TYPE_HEX_STR)
-            err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX);
-        else
-            err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx,
-                key->dp->size);
-    }
-
-    /* read Qy */
-    if (err == MP_OKAY) {
-        if (encType == ECC_TYPE_HEX_STR)
-            err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX);
-        else
-            err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy,
-                key->dp->size);
-
-    }
-
-    if (err == MP_OKAY)
-        err = mp_set(key->pubkey.z, 1);
-
-    /* import private key */
-    if (err == MP_OKAY) {
-        if (d != NULL) {
-            key->type = ECC_PRIVATEKEY;
-
-            if (encType == ECC_TYPE_HEX_STR)
-                err = mp_read_radix(&key->k, d, MP_RADIX_HEX);
-            else
-                err = mp_read_unsigned_bin(&key->k, (const byte*)d,
-                    key->dp->size);
-
-        } else {
-            key->type = ECC_PUBLICKEY;
-        }
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
-    if (err == MP_OKAY)
-        err = wc_ecc_check_key(key);
-#endif
-
-    if (err != MP_OKAY) {
-        mp_clear(key->pubkey.x);
-        mp_clear(key->pubkey.y);
-        mp_clear(key->pubkey.z);
-        mp_clear(&key->k);
-    }
-#endif /* WOLFSSL_ATECC508A */
-
-    return err;
-}
-
-/**
-   Import raw ECC key
-   key       The destination ecc_key structure
-   qx        x component of the public key, as ASCII hex string
-   qy        y component of the public key, as ASCII hex string
-   d         private key, as ASCII hex string, optional if importing public
-             key only
-   dp        Custom ecc_set_type
-   return    MP_OKAY on success
-*/
-int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
-                   const char* d, int curve_id)
-{
-    return wc_ecc_import_raw_private(key, qx, qy, d, curve_id,
-        ECC_TYPE_HEX_STR);
-
-}
-
-/* Import x, y and optional private (d) as unsigned binary */
-int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
-                   byte* d, int curve_id)
-{
-    return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy,
-        (const char*)d, curve_id, ECC_TYPE_UNSIGNED_BIN);
-}
-
-/**
-   Import raw ECC key
-   key       The destination ecc_key structure
-   qx        x component of the public key, as ASCII hex string
-   qy        y component of the public key, as ASCII hex string
-   d         private key, as ASCII hex string, optional if importing public
-             key only
-   curveName ECC curve name, from ecc_sets[]
-   return    MP_OKAY on success
-*/
-int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
-                   const char* d, const char* curveName)
-{
-    int err, x;
-
-    /* if d is NULL, only import as public key using Qx,Qy */
-    if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* set curve type and index */
-    for (x = 0; ecc_sets[x].size != 0; x++) {
-        if (XSTRNCMP(ecc_sets[x].name, curveName,
-                     XSTRLEN(curveName)) == 0) {
-            break;
-        }
-    }
-
-    if (ecc_sets[x].size == 0) {
-        WOLFSSL_MSG("ecc_set curve name not found");
-        err = ASN_PARSE_E;
-    } else {
-        return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id,
-            ECC_TYPE_HEX_STR);
-    }
-
-    return err;
-}
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-/* key size in octets */
-int wc_ecc_size(ecc_key* key)
-{
-    if (key == NULL) return 0;
-
-    return key->dp->size;
-}
-
-int wc_ecc_sig_size_calc(int sz)
-{
-    return (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ;
-}
-
-/* worst case estimate, check actual return from wc_ecc_sign_hash for actual
-   value of signature size in octets */
-int wc_ecc_sig_size(ecc_key* key)
-{
-    int sz = wc_ecc_size(key);
-    if (sz <= 0)
-        return sz;
-
-    return wc_ecc_sig_size_calc(sz);
-}
-
-
-#ifdef FP_ECC
-
-/* fixed point ECC cache */
-/* number of entries in the cache */
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 15
-#endif
-
-/* number of bits in LUT */
-#ifndef FP_LUT
-    #define FP_LUT     8U
-#endif
-
-#ifdef ECC_SHAMIR
-    /* Sharmir requires a bigger LUT, TAO */
-    #if (FP_LUT > 12) || (FP_LUT < 4)
-        #error FP_LUT must be between 4 and 12 inclusively
-    #endif
-#else
-    #if (FP_LUT > 12) || (FP_LUT < 2)
-        #error FP_LUT must be between 2 and 12 inclusively
-    #endif
-#endif
-
-
-#ifndef WOLFSSL_SP_MATH
-
-/** Our FP cache */
-typedef struct {
-   ecc_point* g;               /* cached COPY of base point */
-   ecc_point* LUT[1U<<FP_LUT]; /* fixed point lookup */
-   mp_int     mu;              /* copy of the montgomery constant */
-   int        lru_count;       /* amount of times this entry has been used */
-   int        lock;            /* flag to indicate cache eviction */
-                               /* permitted (0) or not (1) */
-} fp_cache_t;
-
-/* if HAVE_THREAD_LS this cache is per thread, no locking needed */
-static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES];
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initMutex = 0;  /* prevent multiple mutex inits */
-    static wolfSSL_Mutex ecc_fp_lock;
-#endif /* HAVE_THREAD_LS */
-
-/* simple table to help direct the generation of the LUT */
-static const struct {
-   int ham, terma, termb;
-} lut_orders[] = {
-   { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 }, { 2, 1, 2 }, { 1, 0, 0 }, { 2, 1, 4 }, { 2, 2, 4 }, { 3, 3, 4 },
-   { 1, 0, 0 }, { 2, 1, 8 }, { 2, 2, 8 }, { 3, 3, 8 }, { 2, 4, 8 }, { 3, 5, 8 }, { 3, 6, 8 }, { 4, 7, 8 },
-   { 1, 0, 0 }, { 2, 1, 16 }, { 2, 2, 16 }, { 3, 3, 16 }, { 2, 4, 16 }, { 3, 5, 16 }, { 3, 6, 16 }, { 4, 7, 16 },
-   { 2, 8, 16 }, { 3, 9, 16 }, { 3, 10, 16 }, { 4, 11, 16 }, { 3, 12, 16 }, { 4, 13, 16 }, { 4, 14, 16 }, { 5, 15, 16 },
-   { 1, 0, 0 }, { 2, 1, 32 }, { 2, 2, 32 }, { 3, 3, 32 }, { 2, 4, 32 }, { 3, 5, 32 }, { 3, 6, 32 }, { 4, 7, 32 },
-   { 2, 8, 32 }, { 3, 9, 32 }, { 3, 10, 32 }, { 4, 11, 32 }, { 3, 12, 32 }, { 4, 13, 32 }, { 4, 14, 32 }, { 5, 15, 32 },
-   { 2, 16, 32 }, { 3, 17, 32 }, { 3, 18, 32 }, { 4, 19, 32 }, { 3, 20, 32 }, { 4, 21, 32 }, { 4, 22, 32 }, { 5, 23, 32 },
-   { 3, 24, 32 }, { 4, 25, 32 }, { 4, 26, 32 }, { 5, 27, 32 }, { 4, 28, 32 }, { 5, 29, 32 }, { 5, 30, 32 }, { 6, 31, 32 },
-#if FP_LUT > 6
-   { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 },
-   { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 },
-   { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 },
-   { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 },
-   { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 },
-   { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 },
-   { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 },
-   { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 },
-#if FP_LUT > 7
-   { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 },
-   { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 },
-   { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 },
-   { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 },
-   { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 },
-   { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 },
-   { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 },
-   { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 },
-   { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 },
-   { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 },
-   { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 },
-   { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 },
-   { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 },
-   { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 },
-   { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 },
-   { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 },
-#if FP_LUT > 8
-   { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 },
-   { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 },
-   { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 },
-   { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 },
-   { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 },
-   { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 },
-   { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 },
-   { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 },
-   { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 },
-   { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 },
-   { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 },
-   { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 },
-   { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 },
-   { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 },
-   { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 },
-   { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 },
-   { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 },
-   { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 },
-   { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 },
-   { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 },
-   { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 },
-   { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 },
-   { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 },
-   { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 },
-   { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 },
-   { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 },
-   { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 },
-   { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 },
-   { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 },
-   { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 },
-   { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 },
-   { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 },
-#if FP_LUT > 9
-   { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 },
-   { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 },
-   { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 },
-   { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 },
-   { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 },
-   { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 },
-   { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 },
-   { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 },
-   { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 },
-   { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 },
-   { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 },
-   { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 },
-   { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 },
-   { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 },
-   { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 },
-   { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 },
-   { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 },
-   { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 },
-   { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 },
-   { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 },
-   { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 },
-   { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 },
-   { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 },
-   { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 },
-   { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 },
-   { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 },
-   { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 },
-   { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 },
-   { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 },
-   { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 },
-   { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 },
-   { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 },
-   { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 },
-   { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 },
-   { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 },
-   { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 },
-   { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 },
-   { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 },
-   { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 },
-   { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 },
-   { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 },
-   { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 },
-   { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 },
-   { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 },
-   { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 },
-   { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 },
-   { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 },
-   { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 },
-   { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 },
-   { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 },
-   { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 },
-   { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 },
-   { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 },
-   { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 },
-   { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 },
-   { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 },
-   { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 },
-   { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 },
-   { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 },
-   { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 },
-   { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 },
-   { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 },
-   { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 },
-   { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 },
-#if FP_LUT > 10
-   { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 },
-   { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 },
-   { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 },
-   { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 },
-   { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 },
-   { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 },
-   { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 },
-   { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 },
-   { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 },
-   { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 },
-   { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 },
-   { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 },
-   { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 },
-   { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 },
-   { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 },
-   { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 },
-   { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 },
-   { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 },
-   { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 },
-   { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 },
-   { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 },
-   { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 },
-   { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 },
-   { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 },
-   { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 },
-   { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 },
-   { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 },
-   { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 },
-   { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 },
-   { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 },
-   { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 },
-   { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 },
-   { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 },
-   { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 },
-   { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 },
-   { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 },
-   { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 },
-   { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 },
-   { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 },
-   { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 },
-   { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 },
-   { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 },
-   { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 },
-   { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 },
-   { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 },
-   { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 },
-   { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 },
-   { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 },
-   { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 },
-   { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 },
-   { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 },
-   { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 },
-   { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 },
-   { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 },
-   { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 },
-   { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 },
-   { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 },
-   { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 },
-   { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 },
-   { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 },
-   { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 },
-   { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 },
-   { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 },
-   { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 },
-   { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 },
-   { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 },
-   { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 },
-   { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 },
-   { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 },
-   { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 },
-   { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 },
-   { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 },
-   { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 },
-   { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 },
-   { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 },
-   { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 },
-   { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 },
-   { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 },
-   { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 },
-   { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 },
-   { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 },
-   { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 },
-   { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 },
-   { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 },
-   { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 },
-   { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 },
-   { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 },
-   { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 },
-   { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 },
-   { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 },
-   { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 },
-   { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 },
-   { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 },
-   { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 },
-   { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 },
-   { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 },
-   { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 },
-   { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 },
-   { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 },
-   { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 },
-   { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 },
-   { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 },
-   { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 },
-   { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 },
-   { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 },
-   { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 },
-   { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 },
-   { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 },
-   { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 },
-   { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 },
-   { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 },
-   { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 },
-   { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 },
-   { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 },
-   { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 },
-   { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 },
-   { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 },
-   { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 },
-   { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 },
-   { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 },
-   { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 },
-   { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 },
-   { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 },
-   { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 },
-   { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 },
-   { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 },
-   { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 },
-   { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 },
-#if FP_LUT > 11
-   { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 },
-   { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 },
-   { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 },
-   { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 },
-   { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 },
-   { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 },
-   { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 },
-   { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 },
-   { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 },
-   { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 },
-   { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 },
-   { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 },
-   { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 },
-   { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 },
-   { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 },
-   { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 },
-   { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 },
-   { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 },
-   { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 },
-   { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 },
-   { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 },
-   { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 },
-   { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 },
-   { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 },
-   { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 },
-   { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 },
-   { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 },
-   { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 },
-   { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 },
-   { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 },
-   { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 },
-   { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 },
-   { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 },
-   { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 },
-   { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 },
-   { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 },
-   { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 },
-   { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 },
-   { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 },
-   { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 },
-   { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 },
-   { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 },
-   { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 },
-   { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 },
-   { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 },
-   { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 },
-   { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 },
-   { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 },
-   { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 },
-   { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 },
-   { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 },
-   { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 },
-   { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 },
-   { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 },
-   { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 },
-   { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 },
-   { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 },
-   { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 },
-   { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 },
-   { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 },
-   { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 },
-   { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 },
-   { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 },
-   { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 },
-   { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 },
-   { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 },
-   { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 },
-   { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 },
-   { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 },
-   { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 },
-   { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 },
-   { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 },
-   { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 },
-   { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 },
-   { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 },
-   { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 },
-   { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 },
-   { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 },
-   { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 },
-   { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 },
-   { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 },
-   { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 },
-   { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 },
-   { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 },
-   { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 },
-   { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 },
-   { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 },
-   { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 },
-   { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 },
-   { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 },
-   { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 },
-   { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 },
-   { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 },
-   { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 },
-   { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 },
-   { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 },
-   { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 },
-   { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 },
-   { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 },
-   { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 },
-   { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 },
-   { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 },
-   { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 },
-   { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 },
-   { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 },
-   { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 },
-   { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 },
-   { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 },
-   { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 },
-   { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 },
-   { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 },
-   { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 },
-   { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 },
-   { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 },
-   { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 },
-   { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 },
-   { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 },
-   { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 },
-   { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 },
-   { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 },
-   { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 },
-   { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 },
-   { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 },
-   { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 },
-   { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 },
-   { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 },
-   { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 },
-   { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 },
-   { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 },
-   { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 },
-   { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 },
-   { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 },
-   { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 },
-   { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 },
-   { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 },
-   { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 },
-   { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 },
-   { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 },
-   { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 },
-   { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 },
-   { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 },
-   { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 },
-   { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 },
-   { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 },
-   { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 },
-   { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 },
-   { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 },
-   { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 },
-   { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 },
-   { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 },
-   { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 },
-   { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 },
-   { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 },
-   { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 },
-   { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 },
-   { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 },
-   { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 },
-   { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 },
-   { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 },
-   { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 },
-   { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 },
-   { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 },
-   { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 },
-   { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 },
-   { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 },
-   { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 },
-   { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 },
-   { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 },
-   { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 },
-   { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 },
-   { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 },
-   { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 },
-   { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 },
-   { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 },
-   { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 },
-   { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 },
-   { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 },
-   { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 },
-   { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 },
-   { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 },
-   { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 },
-   { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 },
-   { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 },
-   { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 },
-   { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 },
-   { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 },
-   { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 },
-   { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 },
-   { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 },
-   { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 },
-   { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 },
-   { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 },
-   { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 },
-   { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 },
-   { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 },
-   { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 },
-   { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 },
-   { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 },
-   { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 },
-   { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 },
-   { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 },
-   { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 },
-   { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 },
-   { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 },
-   { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 },
-   { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 },
-   { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 },
-   { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 },
-   { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 },
-   { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 },
-   { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 },
-   { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 },
-   { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 },
-   { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 },
-   { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 },
-   { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 },
-   { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 },
-   { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 },
-   { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 },
-   { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 },
-   { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 },
-   { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 },
-   { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 },
-   { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 },
-   { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 },
-   { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 },
-   { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 },
-   { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 },
-   { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 },
-   { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 },
-   { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 },
-   { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 },
-   { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 },
-   { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 },
-   { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 },
-   { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 },
-   { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 },
-   { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 },
-   { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 },
-   { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 },
-   { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 },
-   { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 },
-   { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 },
-   { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 },
-   { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 },
-   { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 },
-   { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 },
-   { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 },
-   { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 },
-   { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 },
-   { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 },
-   { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 },
-   { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 },
-   { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 },
-   { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 },
-   { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 },
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-};
-
-
-/* find a hole and free as required, return -1 if no hole found */
-static int find_hole(void)
-{
-   unsigned x;
-   int      y, z;
-   for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
-       if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
-          z = x;
-          y = fp_cache[x].lru_count;
-       }
-   }
-
-   /* decrease all */
-   for (x = 0; x < FP_ENTRIES; x++) {
-      if (fp_cache[x].lru_count > 3) {
-         --(fp_cache[x].lru_count);
-      }
-   }
-
-   /* free entry z */
-   if (z >= 0 && fp_cache[z].g) {
-      mp_clear(&fp_cache[z].mu);
-      wc_ecc_del_point(fp_cache[z].g);
-      fp_cache[z].g  = NULL;
-      for (x = 0; x < (1U<<FP_LUT); x++) {
-         wc_ecc_del_point(fp_cache[z].LUT[x]);
-         fp_cache[z].LUT[x] = NULL;
-      }
-      fp_cache[z].lru_count = 0;
-   }
-   return z;
-}
-
-/* determine if a base is already in the cache and if so, where */
-static int find_base(ecc_point* g)
-{
-   int x;
-   for (x = 0; x < FP_ENTRIES; x++) {
-      if (fp_cache[x].g != NULL &&
-          mp_cmp(fp_cache[x].g->x, g->x) == MP_EQ &&
-          mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ &&
-          mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) {
-         break;
-      }
-   }
-   if (x == FP_ENTRIES) {
-      x = -1;
-   }
-   return x;
-}
-
-/* add a new base to the cache */
-static int add_entry(int idx, ecc_point *g)
-{
-   unsigned x, y;
-
-   /* allocate base and LUT */
-   fp_cache[idx].g = wc_ecc_new_point();
-   if (fp_cache[idx].g == NULL) {
-      return GEN_MEM_ERR;
-   }
-
-   /* copy x and y */
-   if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) ||
-       (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) ||
-       (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) {
-      wc_ecc_del_point(fp_cache[idx].g);
-      fp_cache[idx].g = NULL;
-      return GEN_MEM_ERR;
-   }
-
-   for (x = 0; x < (1U<<FP_LUT); x++) {
-      fp_cache[idx].LUT[x] = wc_ecc_new_point();
-      if (fp_cache[idx].LUT[x] == NULL) {
-         for (y = 0; y < x; y++) {
-            wc_ecc_del_point(fp_cache[idx].LUT[y]);
-            fp_cache[idx].LUT[y] = NULL;
-         }
-         wc_ecc_del_point(fp_cache[idx].g);
-         fp_cache[idx].g         = NULL;
-         fp_cache[idx].lru_count = 0;
-         return GEN_MEM_ERR;
-      }
-   }
-
-   fp_cache[idx].lru_count = 0;
-
-   return MP_OKAY;
-}
-#endif
-
-#ifndef WOLFSSL_SP_MATH
-/* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart
- *
- * The algorithm builds patterns in increasing bit order by first making all
- * single bit input patterns, then all two bit input patterns and so on
- */
-static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp,
-    mp_int* mu)
-{
-   int err;
-   unsigned x, y, bitlen, lut_gap;
-   mp_int tmp;
-
-   if (mp_init(&tmp) != MP_OKAY)
-       return GEN_MEM_ERR;
-
-   /* sanity check to make sure lut_order table is of correct size,
-      should compile out to a NOP if true */
-   if ((sizeof(lut_orders) / sizeof(lut_orders[0])) < (1U<<FP_LUT)) {
-       err = BAD_FUNC_ARG;
-   }
-   else {
-    /* get bitlen and round up to next multiple of FP_LUT */
-    bitlen  = mp_unsigned_bin_size(modulus) << 3;
-    x       = bitlen % FP_LUT;
-    if (x) {
-      bitlen += FP_LUT - x;
-    }
-    lut_gap = bitlen / FP_LUT;
-
-    /* init the mu */
-    err = mp_init_copy(&fp_cache[idx].mu, mu);
-   }
-
-   /* copy base */
-   if (err == MP_OKAY) {
-     if ((mp_mulmod(fp_cache[idx].g->x, mu, modulus,
-                  fp_cache[idx].LUT[1]->x) != MP_OKAY) ||
-         (mp_mulmod(fp_cache[idx].g->y, mu, modulus,
-                  fp_cache[idx].LUT[1]->y) != MP_OKAY) ||
-         (mp_mulmod(fp_cache[idx].g->z, mu, modulus,
-                  fp_cache[idx].LUT[1]->z) != MP_OKAY)) {
-       err = MP_MULMOD_E;
-     }
-   }
-
-   /* make all single bit entries */
-   for (x = 1; x < FP_LUT; x++) {
-      if (err != MP_OKAY)
-          break;
-      if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x,
-                   fp_cache[idx].LUT[1<<x]->x) != MP_OKAY) ||
-          (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y,
-                   fp_cache[idx].LUT[1<<x]->y) != MP_OKAY) ||
-          (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z,
-                   fp_cache[idx].LUT[1<<x]->z) != MP_OKAY)){
-          err = MP_INIT_E;
-          break;
-      } else {
-
-         /* now double it bitlen/FP_LUT times */
-         for (y = 0; y < lut_gap; y++) {
-             if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<<x],
-                            fp_cache[idx].LUT[1<<x], a, modulus, mp)) != MP_OKAY) {
-                 break;
-             }
-         }
-     }
-  }
-
-   /* now make all entries in increase order of hamming weight */
-   for (x = 2; x <= FP_LUT; x++) {
-       if (err != MP_OKAY)
-           break;
-       for (y = 0; y < (1UL<<FP_LUT); y++) {
-           if (lut_orders[y].ham != (int)x) continue;
-
-           /* perform the add */
-           if ((err = ecc_projective_add_point(
-                           fp_cache[idx].LUT[lut_orders[y].terma],
-                           fp_cache[idx].LUT[lut_orders[y].termb],
-                           fp_cache[idx].LUT[y], a, modulus, mp)) != MP_OKAY) {
-              break;
-           }
-       }
-   }
-
-   /* now map all entries back to affine space to make point addition faster */
-   for (x = 1; x < (1UL<<FP_LUT); x++) {
-       if (err != MP_OKAY)
-           break;
-
-       /* convert z to normal from montgomery */
-       err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, mp);
-
-       /* invert it */
-       if (err == MP_OKAY)
-         err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus,
-                         fp_cache[idx].LUT[x]->z);
-
-       if (err == MP_OKAY)
-         /* now square it */
-         err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp);
-
-       if (err == MP_OKAY)
-         /* fix x */
-         err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus,
-                         fp_cache[idx].LUT[x]->x);
-
-       if (err == MP_OKAY)
-         /* get 1/z^3 */
-         err = mp_mulmod(&tmp, fp_cache[idx].LUT[x]->z, modulus, &tmp);
-
-       if (err == MP_OKAY)
-         /* fix y */
-         err = mp_mulmod(fp_cache[idx].LUT[x]->y, &tmp, modulus,
-                         fp_cache[idx].LUT[x]->y);
-
-       if (err == MP_OKAY)
-         /* free z */
-         mp_clear(fp_cache[idx].LUT[x]->z);
-   }
-
-   mp_clear(&tmp);
-
-   if (err == MP_OKAY)
-     return MP_OKAY;
-
-   /* err cleanup */
-   for (y = 0; y < (1U<<FP_LUT); y++) {
-      wc_ecc_del_point(fp_cache[idx].LUT[y]);
-      fp_cache[idx].LUT[y] = NULL;
-   }
-   wc_ecc_del_point(fp_cache[idx].g);
-   fp_cache[idx].g         = NULL;
-   fp_cache[idx].lru_count = 0;
-   mp_clear(&fp_cache[idx].mu);
-
-   return err;
-}
-
-/* perform a fixed point ECC mulmod */
-static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a,
-                        mp_int* modulus, mp_digit mp, int map)
-{
-#define KB_SIZE 128
-
-#ifdef WOLFSSL_SMALL_STACK
-   unsigned char* kb = NULL;
-#else
-   unsigned char kb[KB_SIZE];
-#endif
-   int      x, err;
-   unsigned y, z = 0, bitlen, bitpos, lut_gap, first;
-   mp_int   tk, order;
-
-   if (mp_init_multi(&tk, &order, NULL, NULL, NULL, NULL) != MP_OKAY)
-       return MP_INIT_E;
-
-   /* if it's smaller than modulus we fine */
-   if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) {
-      /* find order */
-      y = mp_unsigned_bin_size(modulus);
-      for (x = 0; ecc_sets[x].size; x++) {
-         if (y <= (unsigned)ecc_sets[x].size) break;
-      }
-
-      /* back off if we are on the 521 bit curve */
-      if (y == 66) --x;
-
-      if ((err = mp_read_radix(&order, ecc_sets[x].order,
-                                                MP_RADIX_HEX)) != MP_OKAY) {
-         goto done;
-      }
-
-      /* k must be less than modulus */
-      if (mp_cmp(k, &order) != MP_LT) {
-         if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) {
-            goto done;
-         }
-      } else {
-         if ((err = mp_copy(k, &tk)) != MP_OKAY) {
-            goto done;
-         }
-      }
-   } else {
-      if ((err = mp_copy(k, &tk)) != MP_OKAY) {
-         goto done;
-      }
-   }
-
-   /* get bitlen and round up to next multiple of FP_LUT */
-   bitlen  = mp_unsigned_bin_size(modulus) << 3;
-   x       = bitlen % FP_LUT;
-   if (x) {
-      bitlen += FP_LUT - x;
-   }
-   lut_gap = bitlen / FP_LUT;
-
-   /* get the k value */
-   if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
-      err = BUFFER_E; goto done;
-   }
-
-   /* store k */
-#ifdef WOLFSSL_SMALL_STACK
-   kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-   if (kb == NULL) {
-      err = MEMORY_E; goto done;
-   }
-#endif
-
-   XMEMSET(kb, 0, KB_SIZE);
-   if ((err = mp_to_unsigned_bin(&tk, kb)) == MP_OKAY) {
-      /* let's reverse kb so it's little endian */
-      x = 0;
-      y = mp_unsigned_bin_size(&tk);
-      if (y > 0) {
-          y -= 1;
-      }
-
-      while ((unsigned)x < y) {
-         z = kb[x]; kb[x] = kb[y]; kb[y] = (byte)z;
-         ++x; --y;
-      }
-
-      /* at this point we can start, yipee */
-      first = 1;
-      for (x = lut_gap-1; x >= 0; x--) {
-          /* extract FP_LUT bits from kb spread out by lut_gap bits and offset
-             by x bits from the start */
-          bitpos = x;
-          for (y = z = 0; y < FP_LUT; y++) {
-             z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
-             bitpos += lut_gap;  /* it's y*lut_gap + x, but here we can avoid
-                                    the mult in each loop */
-          }
-
-          /* double if not first */
-          if (!first) {
-             if ((err = ecc_projective_dbl_point(R, R, a, modulus,
-                                                             mp)) != MP_OKAY) {
-                break;
-             }
-          }
-
-          /* add if not first, otherwise copy */
-          if (!first && z) {
-             if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
-                                                 a, modulus, mp)) != MP_OKAY) {
-                break;
-             }
-          } else if (z) {
-             if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) ||
-                 (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) ||
-                 (mp_copy(&fp_cache[idx].mu,       R->z) != MP_OKAY)) {
-                 err = GEN_MEM_ERR;
-                 break;
-             }
-                 first = 0;
-          }
-      }
-   }
-
-   if (err == MP_OKAY) {
-      (void) z; /* Acknowledge the unused assignment */
-      ForceZero(kb, KB_SIZE);
-
-      /* map R back from projective space */
-      if (map) {
-         err = ecc_map(R, modulus, mp);
-      } else {
-         err = MP_OKAY;
-      }
-   }
-
-done:
-   /* cleanup */
-   mp_clear(&order);
-   mp_clear(&tk);
-
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-
-#undef KB_SIZE
-
-   return err;
-}
-#endif
-
-#ifdef ECC_SHAMIR
-#ifndef WOLFSSL_SP_MATH
-/* perform a fixed point ECC mulmod */
-static int accel_fp_mul2add(int idx1, int idx2,
-                            mp_int* kA, mp_int* kB,
-                            ecc_point *R, mp_int* a,
-                            mp_int* modulus, mp_digit mp)
-{
-#define KB_SIZE 128
-
-#ifdef WOLFSSL_SMALL_STACK
-   unsigned char* kb[2] = {NULL, NULL};
-#else
-   unsigned char kb[2][KB_SIZE];
-#endif
-   int      x, err;
-   unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB;
-   mp_int tka, tkb, order;
-
-   if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY)
-       return MP_INIT_E;
-
-   /* if it's smaller than modulus we fine */
-   if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
-      /* find order */
-      y = mp_unsigned_bin_size(modulus);
-      for (x = 0; ecc_sets[x].size; x++) {
-         if (y <= (unsigned)ecc_sets[x].size) break;
-      }
-
-      /* back off if we are on the 521 bit curve */
-      if (y == 66) --x;
-
-      if ((err = mp_read_radix(&order, ecc_sets[x].order,
-                                                MP_RADIX_HEX)) != MP_OKAY) {
-         goto done;
-      }
-
-      /* kA must be less than modulus */
-      if (mp_cmp(kA, &order) != MP_LT) {
-         if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) {
-            goto done;
-         }
-      } else {
-         if ((err = mp_copy(kA, &tka)) != MP_OKAY) {
-            goto done;
-         }
-      }
-   } else {
-      if ((err = mp_copy(kA, &tka)) != MP_OKAY) {
-         goto done;
-      }
-   }
-
-   /* if it's smaller than modulus we fine */
-   if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
-      /* find order */
-      y = mp_unsigned_bin_size(modulus);
-      for (x = 0; ecc_sets[x].size; x++) {
-         if (y <= (unsigned)ecc_sets[x].size) break;
-      }
-
-      /* back off if we are on the 521 bit curve */
-      if (y == 66) --x;
-
-      if ((err = mp_read_radix(&order, ecc_sets[x].order,
-                                                MP_RADIX_HEX)) != MP_OKAY) {
-         goto done;
-      }
-
-      /* kB must be less than modulus */
-      if (mp_cmp(kB, &order) != MP_LT) {
-         if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) {
-            goto done;
-         }
-      } else {
-         if ((err = mp_copy(kB, &tkb)) != MP_OKAY) {
-            goto done;
-         }
-      }
-   } else {
-      if ((err = mp_copy(kB, &tkb)) != MP_OKAY) {
-         goto done;
-      }
-   }
-
-   /* get bitlen and round up to next multiple of FP_LUT */
-   bitlen  = mp_unsigned_bin_size(modulus) << 3;
-   x       = bitlen % FP_LUT;
-   if (x) {
-      bitlen += FP_LUT - x;
-   }
-   lut_gap = bitlen / FP_LUT;
-
-   /* get the k value */
-   if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
-       (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2))  ) {
-      err = BUFFER_E; goto done;
-   }
-
-   /* store k */
-#ifdef WOLFSSL_SMALL_STACK
-   kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-   if (kb[0] == NULL) {
-      err = MEMORY_E; goto done;
-   }
-#endif
-
-   XMEMSET(kb[0], 0, KB_SIZE);
-   if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
-      goto done;
-   }
-
-   /* let's reverse kb so it's little endian */
-   x = 0;
-   y = mp_unsigned_bin_size(&tka);
-   if (y > 0) {
-       y -= 1;
-   }
-   mp_clear(&tka);
-   while ((unsigned)x < y) {
-      z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = (byte)z;
-      ++x; --y;
-   }
-
-   /* store b */
-#ifdef WOLFSSL_SMALL_STACK
-   kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-   if (kb[1] == NULL) {
-      err = MEMORY_E; goto done;
-   }
-#endif
-
-   XMEMSET(kb[1], 0, KB_SIZE);
-   if ((err = mp_to_unsigned_bin(&tkb, kb[1])) == MP_OKAY) {
-      x = 0;
-      y = mp_unsigned_bin_size(&tkb);
-      if (y > 0) {
-          y -= 1;
-      }
-
-      while ((unsigned)x < y) {
-         z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = (byte)z;
-         ++x; --y;
-      }
-
-      /* at this point we can start, yipee */
-      first = 1;
-      for (x = lut_gap-1; x >= 0; x--) {
-          /* extract FP_LUT bits from kb spread out by lut_gap bits and
-             offset by x bits from the start */
-          bitpos = x;
-          for (y = zA = zB = 0; y < FP_LUT; y++) {
-             zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
-             zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
-             bitpos += lut_gap;    /* it's y*lut_gap + x, but here we can avoid
-                                      the mult in each loop */
-          }
-
-          /* double if not first */
-          if (!first) {
-             if ((err = ecc_projective_dbl_point(R, R, a, modulus,
-                                                              mp)) != MP_OKAY) {
-                break;
-             }
-          }
-
-          /* add if not first, otherwise copy */
-          if (!first) {
-             if (zA) {
-                if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
-                                                  R, a, modulus, mp)) != MP_OKAY) {
-                   break;
-                }
-             }
-             if (zB) {
-                if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
-                                                  R, a, modulus, mp)) != MP_OKAY) {
-                   break;
-                }
-             }
-          } else {
-             if (zA) {
-                 if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) ||
-                    (mp_copy(fp_cache[idx1].LUT[zA]->y,  R->y) != MP_OKAY) ||
-                    (mp_copy(&fp_cache[idx1].mu,         R->z) != MP_OKAY)) {
-                     err = GEN_MEM_ERR;
-                     break;
-                 }
-                    first = 0;
-             }
-             if (zB && first == 0) {
-                if (zB) {
-                   if ((err = ecc_projective_add_point(R,
-                           fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){
-                      break;
-                   }
-                }
-             } else if (zB && first == 1) {
-                 if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) ||
-                    (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
-                    (mp_copy(&fp_cache[idx2].mu,        R->z) != MP_OKAY)) {
-                     err = GEN_MEM_ERR;
-                     break;
-                 }
-                    first = 0;
-             }
-          }
-      }
-   }
-
-done:
-   /* cleanup */
-   mp_clear(&tkb);
-   mp_clear(&tka);
-   mp_clear(&order);
-
-#ifdef WOLFSSL_SMALL_STACK
-   if (kb[0])
-#endif
-      ForceZero(kb[0], KB_SIZE);
-#ifdef WOLFSSL_SMALL_STACK
-   if (kb[1])
-#endif
-      ForceZero(kb[1], KB_SIZE);
-
-#ifdef WOLFSSL_SMALL_STACK
-   XFREE(kb[0], NULL, DYNAMIC_TYPE_ECC_BUFFER);
-   XFREE(kb[1], NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-
-#undef KB_SIZE
-
-    if (err != MP_OKAY)
-        return err;
-
-   return ecc_map(R, modulus, mp);
-}
-
-
-/** ECC Fixed Point mulmod global with heap hint used
-  Computes kA*A + kB*B = C using Shamir's Trick
-  A        First point to multiply
-  kA       What to multiple A by
-  B        Second point to multiply
-  kB       What to multiple B by
-  C        [out] Destination point (can overlap with A or B)
-  a        ECC curve parameter a
-  modulus  Modulus for curve
-  return MP_OKAY on success
-*/
-int ecc_mul2add(ecc_point* A, mp_int* kA,
-                ecc_point* B, mp_int* kB,
-                ecc_point* C, mp_int* a, mp_int* modulus, void* heap)
-{
-   int  idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0;
-   mp_digit mp;
-   mp_int   mu;
-
-   err = mp_init(&mu);
-   if (err != MP_OKAY)
-       return err;
-
-#ifndef HAVE_THREAD_LS
-   if (initMutex == 0) {
-        wc_InitMutex(&ecc_fp_lock);
-        initMutex = 1;
-   }
-   if (wc_LockMutex(&ecc_fp_lock) != 0)
-      return BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-      /* find point */
-      idx1 = find_base(A);
-
-      /* no entry? */
-      if (idx1 == -1) {
-         /* find hole and add it */
-         if ((idx1 = find_hole()) >= 0) {
-            err = add_entry(idx1, A);
-         }
-      }
-      if (err == MP_OKAY && idx1 != -1) {
-         /* increment LRU */
-         ++(fp_cache[idx1].lru_count);
-      }
-
-      if (err == MP_OKAY)
-        /* find point */
-        idx2 = find_base(B);
-
-      if (err == MP_OKAY) {
-        /* no entry? */
-        if (idx2 == -1) {
-           /* find hole and add it */
-           if ((idx2 = find_hole()) >= 0)
-              err = add_entry(idx2, B);
-         }
-      }
-
-      if (err == MP_OKAY && idx2 != -1) {
-         /* increment LRU */
-         ++(fp_cache[idx2].lru_count);
-      }
-
-      if (err == MP_OKAY) {
-        /* if it's 2 build the LUT, if it's higher just use the LUT */
-        if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
-           /* compute mp */
-           err = mp_montgomery_setup(modulus, &mp);
-
-           if (err == MP_OKAY) {
-             mpInit = 1;
-             err = mp_montgomery_calc_normalization(&mu, modulus);
-           }
-
-           if (err == MP_OKAY)
-             /* build the LUT */
-               err = build_lut(idx1, a, modulus, mp, &mu);
-        }
-      }
-
-      if (err == MP_OKAY) {
-        /* if it's 2 build the LUT, if it's higher just use the LUT */
-        if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
-           if (mpInit == 0) {
-                /* compute mp */
-                err = mp_montgomery_setup(modulus, &mp);
-                if (err == MP_OKAY) {
-                    mpInit = 1;
-                    err = mp_montgomery_calc_normalization(&mu, modulus);
-                }
-            }
-
-            if (err == MP_OKAY)
-            /* build the LUT */
-              err = build_lut(idx2, a, modulus, mp, &mu);
-        }
-      }
-
-
-      if (err == MP_OKAY) {
-        if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 &&
-                                     fp_cache[idx2].lru_count >= 2) {
-           if (mpInit == 0) {
-              /* compute mp */
-              err = mp_montgomery_setup(modulus, &mp);
-           }
-           if (err == MP_OKAY)
-             err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp);
-        } else {
-           err = normal_ecc_mul2add(A, kA, B, kB, C, a, modulus, heap);
-        }
-    }
-
-#ifndef HAVE_THREAD_LS
-    wc_UnLockMutex(&ecc_fp_lock);
-#endif /* HAVE_THREAD_LS */
-    mp_clear(&mu);
-
-    return err;
-}
-#endif
-#endif /* ECC_SHAMIR */
-
-/** ECC Fixed Point mulmod global
-    k        The multiplicand
-    G        Base point to multiply
-    R        [out] Destination of product
-    a        ECC curve parameter a
-    modulus  The modulus for the curve
-    map      [boolean] If non-zero maps the point back to affine co-ordinates,
-             otherwise it's left in jacobian-montgomery form
-    return MP_OKAY if successful
-*/
-int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
-    mp_int* modulus, int map, void* heap)
-{
-#ifndef WOLFSSL_SP_MATH
-   int   idx, err = MP_OKAY;
-   mp_digit mp;
-   mp_int   mu;
-   int      mpSetup = 0;
-
-   if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
-       return ECC_BAD_ARG_E;
-   }
-
-   if (mp_init(&mu) != MP_OKAY)
-       return MP_INIT_E;
-
-#ifndef HAVE_THREAD_LS
-   if (initMutex == 0) {
-        wc_InitMutex(&ecc_fp_lock);
-        initMutex = 1;
-   }
-
-   if (wc_LockMutex(&ecc_fp_lock) != 0)
-      return BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-      /* find point */
-      idx = find_base(G);
-
-      /* no entry? */
-      if (idx == -1) {
-         /* find hole and add it */
-         idx = find_hole();
-
-         if (idx >= 0)
-            err = add_entry(idx, G);
-      }
-      if (err == MP_OKAY && idx >= 0) {
-         /* increment LRU */
-         ++(fp_cache[idx].lru_count);
-      }
-
-
-      if (err == MP_OKAY) {
-        /* if it's 2 build the LUT, if it's higher just use the LUT */
-        if (idx >= 0 && fp_cache[idx].lru_count == 2) {
-           /* compute mp */
-           err = mp_montgomery_setup(modulus, &mp);
-
-           if (err == MP_OKAY) {
-             /* compute mu */
-             mpSetup = 1;
-             err = mp_montgomery_calc_normalization(&mu, modulus);
-           }
-
-           if (err == MP_OKAY)
-             /* build the LUT */
-             err = build_lut(idx, a, modulus, mp, &mu);
-        }
-      }
-
-      if (err == MP_OKAY) {
-        if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
-           if (mpSetup == 0) {
-              /* compute mp */
-              err = mp_montgomery_setup(modulus, &mp);
-           }
-           if (err == MP_OKAY)
-             err = accel_fp_mul(idx, k, R, a, modulus, mp, map);
-        } else {
-           err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap);
-        }
-     }
-
-#ifndef HAVE_THREAD_LS
-    wc_UnLockMutex(&ecc_fp_lock);
-#endif /* HAVE_THREAD_LS */
-    mp_clear(&mu);
-
-    return err;
-#else
-    if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) {
-        return ECC_BAD_ARG_E;
-    }
-
-    return sp_ecc_mulmod_256(k, G, R, map, heap);
-#endif
-}
-
-#ifndef WOLFSSL_SP_MATH
-/* helper function for freeing the cache ...
-   must be called with the cache mutex locked */
-static void wc_ecc_fp_free_cache(void)
-{
-   unsigned x, y;
-   for (x = 0; x < FP_ENTRIES; x++) {
-      if (fp_cache[x].g != NULL) {
-         for (y = 0; y < (1U<<FP_LUT); y++) {
-            wc_ecc_del_point(fp_cache[x].LUT[y]);
-            fp_cache[x].LUT[y] = NULL;
-         }
-         wc_ecc_del_point(fp_cache[x].g);
-         fp_cache[x].g         = NULL;
-         mp_clear(&fp_cache[x].mu);
-         fp_cache[x].lru_count = 0;
-         fp_cache[x].lock = 0;
-      }
-   }
-}
-#endif
-
-/** Free the Fixed Point cache */
-void wc_ecc_fp_free(void)
-{
-#ifndef WOLFSSL_SP_MATH
-#ifndef HAVE_THREAD_LS
-   if (initMutex == 0) {
-        wc_InitMutex(&ecc_fp_lock);
-        initMutex = 1;
-   }
-
-   if (wc_LockMutex(&ecc_fp_lock) == 0) {
-#endif /* HAVE_THREAD_LS */
-
-       wc_ecc_fp_free_cache();
-
-#ifndef HAVE_THREAD_LS
-       wc_UnLockMutex(&ecc_fp_lock);
-       wc_FreeMutex(&ecc_fp_lock);
-       initMutex = 0;
-   }
-#endif /* HAVE_THREAD_LS */
-#endif
-}
-
-
-#endif /* FP_ECC */
-
-#ifdef HAVE_ECC_ENCRYPT
-
-
-enum ecCliState {
-    ecCLI_INIT      = 1,
-    ecCLI_SALT_GET  = 2,
-    ecCLI_SALT_SET  = 3,
-    ecCLI_SENT_REQ  = 4,
-    ecCLI_RECV_RESP = 5,
-    ecCLI_BAD_STATE = 99
-};
-
-enum ecSrvState {
-    ecSRV_INIT      = 1,
-    ecSRV_SALT_GET  = 2,
-    ecSRV_SALT_SET  = 3,
-    ecSRV_RECV_REQ  = 4,
-    ecSRV_SENT_RESP = 5,
-    ecSRV_BAD_STATE = 99
-};
-
-
-struct ecEncCtx {
-    const byte* kdfSalt;   /* optional salt for kdf */
-    const byte* kdfInfo;   /* optional info for kdf */
-    const byte* macSalt;   /* optional salt for mac */
-    word32    kdfSaltSz;   /* size of kdfSalt */
-    word32    kdfInfoSz;   /* size of kdfInfo */
-    word32    macSaltSz;   /* size of macSalt */
-    void*     heap;        /* heap hint for memory used */
-    byte      clientSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
-    byte      serverSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
-    byte      encAlgo;     /* which encryption type */
-    byte      kdfAlgo;     /* which key derivation function type */
-    byte      macAlgo;     /* which mac function type */
-    byte      protocol;    /* are we REQ_RESP client or server ? */
-    byte      cliSt;       /* protocol state, for sanity checks */
-    byte      srvSt;       /* protocol state, for sanity checks */
-};
-
-
-const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx)
-{
-    if (ctx == NULL || ctx->protocol == 0)
-        return NULL;
-
-    if (ctx->protocol == REQ_RESP_CLIENT) {
-        if (ctx->cliSt == ecCLI_INIT) {
-            ctx->cliSt =  ecCLI_SALT_GET;
-            return ctx->clientSalt;
-        }
-        else {
-            ctx->cliSt = ecCLI_BAD_STATE;
-            return NULL;
-        }
-    }
-    else if (ctx->protocol == REQ_RESP_SERVER) {
-        if (ctx->srvSt == ecSRV_INIT) {
-            ctx->srvSt =  ecSRV_SALT_GET;
-            return ctx->serverSalt;
-        }
-        else {
-            ctx->srvSt = ecSRV_BAD_STATE;
-            return NULL;
-        }
-    }
-
-    return NULL;
-}
-
-
-/* optional set info, can be called before or after set_peer_salt */
-int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz)
-{
-    if (ctx == NULL || info == 0 || sz < 0)
-        return BAD_FUNC_ARG;
-
-    ctx->kdfInfo   = info;
-    ctx->kdfInfoSz = sz;
-
-    return 0;
-}
-
-
-static const char* exchange_info = "Secure Message Exchange";
-
-int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
-{
-    byte tmp[EXCHANGE_SALT_SZ/2];
-    int  halfSz = EXCHANGE_SALT_SZ/2;
-
-    if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ctx->protocol == REQ_RESP_CLIENT) {
-        XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
-        if (ctx->cliSt == ecCLI_SALT_GET)
-            ctx->cliSt =  ecCLI_SALT_SET;
-        else {
-            ctx->cliSt =  ecCLI_BAD_STATE;
-            return BAD_STATE_E;
-        }
-    }
-    else {
-        XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
-        if (ctx->srvSt == ecSRV_SALT_GET)
-            ctx->srvSt =  ecSRV_SALT_SET;
-        else {
-            ctx->srvSt =  ecSRV_BAD_STATE;
-            return BAD_STATE_E;
-        }
-    }
-
-    /* mix half and half */
-    /* tmp stores 2nd half of client before overwrite */
-    XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
-    XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
-    XMEMCPY(ctx->serverSalt, tmp, halfSz);
-
-    ctx->kdfSalt   = ctx->clientSalt;
-    ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
-
-    ctx->macSalt   = ctx->serverSalt;
-    ctx->macSaltSz = EXCHANGE_SALT_SZ;
-
-    if (ctx->kdfInfo == NULL) {
-        /* default info */
-        ctx->kdfInfo   = (const byte*)exchange_info;
-        ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
-    }
-
-    return 0;
-}
-
-
-static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, WC_RNG* rng)
-{
-    byte* saltBuffer = NULL;
-
-    if (ctx == NULL || rng == NULL || flags == 0)
-        return BAD_FUNC_ARG;
-
-    saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
-
-    return wc_RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
-}
-
-
-static void ecc_ctx_init(ecEncCtx* ctx, int flags)
-{
-    if (ctx) {
-        XMEMSET(ctx, 0, sizeof(ecEncCtx));
-
-        ctx->encAlgo  = ecAES_128_CBC;
-        ctx->kdfAlgo  = ecHKDF_SHA256;
-        ctx->macAlgo  = ecHMAC_SHA256;
-        ctx->protocol = (byte)flags;
-
-        if (flags == REQ_RESP_CLIENT)
-            ctx->cliSt = ecCLI_INIT;
-        if (flags == REQ_RESP_SERVER)
-            ctx->srvSt = ecSRV_INIT;
-    }
-}
-
-
-/* allow ecc context reset so user doesn't have to init/free for reuse */
-int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng)
-{
-    if (ctx == NULL || rng == NULL)
-        return BAD_FUNC_ARG;
-
-    ecc_ctx_init(ctx, ctx->protocol);
-    return ecc_ctx_set_salt(ctx, ctx->protocol, rng);
-}
-
-
-ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap)
-{
-    int       ret = 0;
-    ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), heap,
-                                                              DYNAMIC_TYPE_ECC);
-
-    if (ctx) {
-        ctx->protocol = (byte)flags;
-        ctx->heap     = heap;
-    }
-
-    ret = wc_ecc_ctx_reset(ctx, rng);
-    if (ret != 0) {
-        wc_ecc_ctx_free(ctx);
-        ctx = NULL;
-    }
-
-    return ctx;
-}
-
-
-/* alloc/init and set defaults, return new Context  */
-ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng)
-{
-    return wc_ecc_ctx_new_ex(flags, rng, NULL);
-}
-
-
-/* free any resources, clear any keys */
-void wc_ecc_ctx_free(ecEncCtx* ctx)
-{
-    if (ctx) {
-        ForceZero(ctx, sizeof(ecEncCtx));
-        XFREE(ctx, ctx->heap, DYNAMIC_TYPE_ECC);
-    }
-}
-
-
-static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
-                             int* keysLen, word32* digestSz, word32* blockSz)
-{
-    if (ctx) {
-        switch (ctx->encAlgo) {
-            case ecAES_128_CBC:
-                *encKeySz = KEY_SIZE_128;
-                *ivSz     = IV_SIZE_128;
-                *blockSz  = AES_BLOCK_SIZE;
-                break;
-            default:
-                return BAD_FUNC_ARG;
-        }
-
-        switch (ctx->macAlgo) {
-            case ecHMAC_SHA256:
-                *digestSz = WC_SHA256_DIGEST_SIZE;
-                break;
-            default:
-                return BAD_FUNC_ARG;
-        }
-    } else
-        return BAD_FUNC_ARG;
-
-    *keysLen  = *encKeySz + *ivSz + *digestSz;
-
-    return 0;
-}
-
-
-/* ecc encrypt with shared secret run through kdf
-   ctx holds non default algos and inputs
-   msgSz should be the right size for encAlgo, i.e., already padded
-   return 0 on success */
-int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
-                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
-{
-    int          ret = 0;
-    word32       blockSz;
-    word32       digestSz;
-    ecEncCtx     localCtx;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*        sharedSecret;
-    byte*        keys;
-#else
-    byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
-    byte         keys[ECC_BUFSIZE];         /* max size */
-#endif
-    word32       sharedSz = ECC_MAXSIZE;
-    int          keysLen;
-    int          encKeySz;
-    int          ivSz;
-    int          offset = 0;         /* keys offset if doing msg exchange */
-    byte*        encKey;
-    byte*        encIv;
-    byte*        macKey;
-
-    if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
-                           outSz  == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ctx == NULL) {  /* use defaults */
-        ecc_ctx_init(&localCtx, 0);
-        ctx = &localCtx;
-    }
-
-    ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
-                            &blockSz);
-    if (ret != 0)
-        return ret;
-
-    if (ctx->protocol == REQ_RESP_SERVER) {
-        offset = keysLen;
-        keysLen *= 2;
-
-        if (ctx->srvSt != ecSRV_RECV_REQ)
-            return BAD_STATE_E;
-
-        ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
-    }
-    else if (ctx->protocol == REQ_RESP_CLIENT) {
-        if (ctx->cliSt != ecCLI_SALT_SET)
-            return BAD_STATE_E;
-
-        ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
-    }
-
-    if (keysLen > ECC_BUFSIZE) /* keys size */
-        return BUFFER_E;
-
-    if ( (msgSz%blockSz) != 0)
-        return BAD_PADDING_E;
-
-    if (*outSz < (msgSz + digestSz))
-        return BUFFER_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (sharedSecret == NULL)
-        return MEMORY_E;
-
-    keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (keys == NULL) {
-        XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    do {
-    #if defined(WOLFSSL_ASYNC_CRYPT)
-        ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-        if (ret != 0)
-            break;
-    #endif
-        ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
-    } while (ret == WC_PENDING_E);
-    if (ret == 0) {
-       switch (ctx->kdfAlgo) {
-           case ecHKDF_SHA256 :
-               ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
-                          ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
-                          keys, keysLen);
-               break;
-
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0) {
-       encKey = keys + offset;
-       encIv  = encKey + encKeySz;
-       macKey = encKey + encKeySz + ivSz;
-
-       switch (ctx->encAlgo) {
-           case ecAES_128_CBC:
-               {
-                   Aes aes;
-                   ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
-                                                                AES_ENCRYPTION);
-                   if (ret != 0)
-                       break;
-                   ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz);
-                #if defined(WOLFSSL_ASYNC_CRYPT)
-                   ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE);
-                #endif
-               }
-               break;
-
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0) {
-       switch (ctx->macAlgo) {
-           case ecHMAC_SHA256:
-               {
-                   Hmac hmac;
-                   ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
-                   if (ret == 0) {
-                       ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE);
-                       if (ret == 0)
-                           ret = wc_HmacUpdate(&hmac, out, msgSz);
-                       if (ret == 0)
-                           ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
-                       if (ret == 0)
-                           ret = wc_HmacFinal(&hmac, out+msgSz);
-                       wc_HmacFree(&hmac);
-                   }
-               }
-               break;
-
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0)
-       *outSz = msgSz + digestSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-/* ecc decrypt with shared secret run through kdf
-   ctx holds non default algos and inputs
-   return 0 on success */
-int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
-                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
-{
-    int          ret = 0;
-    word32       blockSz;
-    word32       digestSz;
-    ecEncCtx     localCtx;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*        sharedSecret;
-    byte*        keys;
-#else
-    byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
-    byte         keys[ECC_BUFSIZE];         /* max size */
-#endif
-    word32       sharedSz = ECC_MAXSIZE;
-    int          keysLen;
-    int          encKeySz;
-    int          ivSz;
-    int          offset = 0;       /* in case using msg exchange */
-    byte*        encKey;
-    byte*        encIv;
-    byte*        macKey;
-
-    if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
-                           outSz  == NULL)
-        return BAD_FUNC_ARG;
-
-    if (ctx == NULL) {  /* use defaults */
-        ecc_ctx_init(&localCtx, 0);
-        ctx = &localCtx;
-    }
-
-    ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
-                            &blockSz);
-    if (ret != 0)
-        return ret;
-
-    if (ctx->protocol == REQ_RESP_CLIENT) {
-        offset = keysLen;
-        keysLen *= 2;
-
-        if (ctx->cliSt != ecCLI_SENT_REQ)
-            return BAD_STATE_E;
-
-        ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
-    }
-    else if (ctx->protocol == REQ_RESP_SERVER) {
-        if (ctx->srvSt != ecSRV_SALT_SET)
-            return BAD_STATE_E;
-
-        ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
-    }
-
-    if (keysLen > ECC_BUFSIZE) /* keys size */
-        return BUFFER_E;
-
-    if ( ((msgSz-digestSz) % blockSz) != 0)
-        return BAD_PADDING_E;
-
-    if (*outSz < (msgSz - digestSz))
-        return BUFFER_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (sharedSecret == NULL)
-        return MEMORY_E;
-
-    keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    if (keys == NULL) {
-        XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    do {
-    #if defined(WOLFSSL_ASYNC_CRYPT)
-        ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
-        if (ret != 0)
-            break;
-    #endif
-        ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
-    } while (ret == WC_PENDING_E);
-    if (ret == 0) {
-       switch (ctx->kdfAlgo) {
-           case ecHKDF_SHA256 :
-               ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
-                          ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
-                          keys, keysLen);
-               break;
-
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0) {
-       encKey = keys + offset;
-       encIv  = encKey + encKeySz;
-       macKey = encKey + encKeySz + ivSz;
-
-       switch (ctx->macAlgo) {
-           case ecHMAC_SHA256:
-           {
-               byte verify[WC_SHA256_DIGEST_SIZE];
-               Hmac hmac;
-
-               ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
-               if (ret == 0) {
-                   ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE);
-                   if (ret == 0)
-                       ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz);
-                   if (ret == 0)
-                       ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
-                   if (ret == 0)
-                       ret = wc_HmacFinal(&hmac, verify);
-                   if (ret == 0) {
-                      if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0)
-                          ret = -1;
-                   }
-
-                   wc_HmacFree(&hmac);
-               }
-               break;
-           }
-
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0) {
-       switch (ctx->encAlgo) {
-    #ifdef HAVE_AES_CBC
-           case ecAES_128_CBC:
-               {
-                   Aes aes;
-                   ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
-                                                                AES_DECRYPTION);
-                   if (ret != 0)
-                       break;
-                   ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
-                #if defined(WOLFSSL_ASYNC_CRYPT)
-                   ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE);
-                #endif
-               }
-               break;
-    #endif
-           default:
-               ret = BAD_FUNC_ARG;
-               break;
-       }
-    }
-
-    if (ret == 0)
-       *outSz = msgSz - digestSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-    XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-#endif /* HAVE_ECC_ENCRYPT */
-
-
-#ifdef HAVE_COMP_KEY
-#ifndef WOLFSSL_ATECC508A
-
-#ifndef WOLFSSL_SP_MATH
-int do_mp_jacobi(mp_int* a, mp_int* n, int* c);
-
-int do_mp_jacobi(mp_int* a, mp_int* n, int* c)
-{
-  int      k, s, res;
-  int      r = 0; /* initialize to help static analysis out */
-  mp_digit residue;
-
-  /* if a < 0 return MP_VAL */
-  if (mp_isneg(a) == MP_YES) {
-     return MP_VAL;
-  }
-
-  /* if n <= 0 return MP_VAL */
-  if (mp_cmp_d(n, 0) != MP_GT) {
-     return MP_VAL;
-  }
-
-  /* step 1. handle case of a == 0 */
-  if (mp_iszero (a) == MP_YES) {
-     /* special case of a == 0 and n == 1 */
-     if (mp_cmp_d (n, 1) == MP_EQ) {
-       *c = 1;
-     } else {
-       *c = 0;
-     }
-     return MP_OKAY;
-  }
-
-  /* step 2.  if a == 1, return 1 */
-  if (mp_cmp_d (a, 1) == MP_EQ) {
-    *c = 1;
-    return MP_OKAY;
-  }
-
-  /* default */
-  s = 0;
-
-  /* divide out larger power of two */
-  k = mp_cnt_lsb(a);
-  res = mp_div_2d(a, k, a, NULL);
-
-  if (res == MP_OKAY) {
-    /* step 4.  if e is even set s=1 */
-    if ((k & 1) == 0) {
-      s = 1;
-    } else {
-      /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
-      residue = n->dp[0] & 7;
-
-      if (residue == 1 || residue == 7) {
-        s = 1;
-      } else if (residue == 3 || residue == 5) {
-        s = -1;
-      }
-    }
-
-    /* step 5.  if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */
-    if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) {
-      s = -s;
-    }
-  }
-
-  if (res == MP_OKAY) {
-    /* if a == 1 we're done */
-    if (mp_cmp_d(a, 1) == MP_EQ) {
-      *c = s;
-    } else {
-      /* n1 = n mod a */
-      res = mp_mod (n, a, n);
-      if (res == MP_OKAY)
-        res = do_mp_jacobi(n, a, &r);
-
-      if (res == MP_OKAY)
-        *c = s * r;
-    }
-  }
-
-  return res;
-}
-
-
-/* computes the jacobi c = (a | n) (or Legendre if n is prime)
- * HAC pp. 73 Algorithm 2.149
- * HAC is wrong here, as the special case of (0 | 1) is not
- * handled correctly.
- */
-int mp_jacobi(mp_int* a, mp_int* n, int* c)
-{
-    mp_int   a1, n1;
-    int      res;
-
-    /* step 3.  write a = a1 * 2**k  */
-    if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-        return res;
-    }
-
-    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
-        goto done;
-    }
-
-    if ((res = mp_copy(n, &n1)) != MP_OKAY) {
-        goto done;
-    }
-
-    res = do_mp_jacobi(&a1, &n1, c);
-
-done:
-  /* cleanup */
-  mp_clear(&n1);
-  mp_clear(&a1);
-
-  return res;
-}
-
-
-/* Solves the modular equation x^2 = n (mod p)
- * where prime number is greater than 2 (odd prime).
- * The result is returned in the third argument x
- * the function returns MP_OKAY on success, MP_VAL or another error on failure
- */
-int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
-{
-#ifdef SQRTMOD_USE_MOD_EXP
-  int res;
-
-  mp_int e;
-
-  res = mp_init(&e);
-  if (res == MP_OKAY)
-      res = mp_add_d(prime, 1, &e);
-  if (res == MP_OKAY)
-      res = mp_div_2d(&e, 2, &e, NULL);
-  if (res == MP_OKAY)
-      res = mp_exptmod(n, &e, prime, ret);
-
-  mp_clear(&e);
-
-  return res;
-#else
-  int res, legendre, done = 0;
-  mp_int t1, C, Q, S, Z, M, T, R, two;
-  mp_digit i;
-
-  /* first handle the simple cases n = 0 or n = 1 */
-  if (mp_cmp_d(n, 0) == MP_EQ) {
-    mp_zero(ret);
-    return MP_OKAY;
-  }
-  if (mp_cmp_d(n, 1) == MP_EQ) {
-    return mp_set(ret, 1);
-  }
-
-  /* prime must be odd */
-  if (mp_cmp_d(prime, 2) == MP_EQ) {
-    return MP_VAL;
-  }
-
-  /* is quadratic non-residue mod prime */
-  if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) {
-    return res;
-  }
-  if (legendre == -1) {
-    return MP_VAL;
-  }
-
-  if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
-    return res;
-
-  if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
-                          != MP_OKAY) {
-    mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
-    mp_clear(&M);
-    return res;
-  }
-
-  /* SPECIAL CASE: if prime mod 4 == 3
-   * compute directly: res = n^(prime+1)/4 mod prime
-   * Handbook of Applied Cryptography algorithm 3.36
-   */
-  res = mp_mod_d(prime, 4, &i);
-  if (res == MP_OKAY && i == 3) {
-    res = mp_add_d(prime, 1, &t1);
-
-    if (res == MP_OKAY)
-      res = mp_div_2(&t1, &t1);
-    if (res == MP_OKAY)
-      res = mp_div_2(&t1, &t1);
-    if (res == MP_OKAY)
-      res = mp_exptmod(n, &t1, prime, ret);
-
-    done = 1;
-  }
-
-  /* NOW: TonelliShanks algorithm */
-  if (res == MP_OKAY && done == 0) {
-
-    /* factor out powers of 2 from prime-1, defining Q and S
-    *                                      as: prime-1 = Q*2^S */
-    /* Q = prime - 1 */
-    res = mp_copy(prime, &Q);
-    if (res == MP_OKAY)
-      res = mp_sub_d(&Q, 1, &Q);
-
-    /* S = 0 */
-    if (res == MP_OKAY)
-      mp_zero(&S);
-
-    while (res == MP_OKAY && mp_iseven(&Q) == MP_YES) {
-      /* Q = Q / 2 */
-      res = mp_div_2(&Q, &Q);
-
-      /* S = S + 1 */
-      if (res == MP_OKAY)
-        res = mp_add_d(&S, 1, &S);
-    }
-
-    /* find a Z such that the Legendre symbol (Z|prime) == -1 */
-    /* Z = 2 */
-    if (res == MP_OKAY)
-      res = mp_set_int(&Z, 2);
-
-    while (res == MP_OKAY) {
-      res = mp_jacobi(&Z, prime, &legendre);
-      if (res == MP_OKAY && legendre == -1)
-        break;
-
-      /* Z = Z + 1 */
-      if (res == MP_OKAY)
-        res = mp_add_d(&Z, 1, &Z);
-    }
-
-    /* C = Z ^ Q mod prime */
-    if (res == MP_OKAY)
-      res = mp_exptmod(&Z, &Q, prime, &C);
-
-    /* t1 = (Q + 1) / 2 */
-    if (res == MP_OKAY)
-      res = mp_add_d(&Q, 1, &t1);
-    if (res == MP_OKAY)
-      res = mp_div_2(&t1, &t1);
-
-    /* R = n ^ ((Q + 1) / 2) mod prime */
-    if (res == MP_OKAY)
-      res = mp_exptmod(n, &t1, prime, &R);
-
-    /* T = n ^ Q mod prime */
-    if (res == MP_OKAY)
-      res = mp_exptmod(n, &Q, prime, &T);
-
-    /* M = S */
-    if (res == MP_OKAY)
-      res = mp_copy(&S, &M);
-
-    if (res == MP_OKAY)
-      res = mp_set_int(&two, 2);
-
-    while (res == MP_OKAY && done == 0) {
-      res = mp_copy(&T, &t1);
-
-      /* reduce to 1 and count */
-      i = 0;
-      while (res == MP_OKAY) {
-        if (mp_cmp_d(&t1, 1) == MP_EQ)
-            break;
-        res = mp_exptmod(&t1, &two, prime, &t1);
-        if (res == MP_OKAY)
-          i++;
-      }
-      if (res == MP_OKAY && i == 0) {
-        res = mp_copy(&R, ret);
-        done = 1;
-      }
-
-      if (done == 0) {
-        /* t1 = 2 ^ (M - i - 1) */
-        if (res == MP_OKAY)
-          res = mp_sub_d(&M, i, &t1);
-        if (res == MP_OKAY)
-          res = mp_sub_d(&t1, 1, &t1);
-        if (res == MP_OKAY)
-          res = mp_exptmod(&two, &t1, prime, &t1);
-
-        /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
-        if (res == MP_OKAY)
-          res = mp_exptmod(&C, &t1, prime, &t1);
-
-        /* C = (t1 * t1) mod prime */
-        if (res == MP_OKAY)
-          res = mp_sqrmod(&t1, prime, &C);
-
-        /* R = (R * t1) mod prime */
-        if (res == MP_OKAY)
-          res = mp_mulmod(&R, &t1, prime, &R);
-
-        /* T = (T * C) mod prime */
-        if (res == MP_OKAY)
-          res = mp_mulmod(&T, &C, prime, &T);
-
-        /* M = i */
-        if (res == MP_OKAY)
-          res = mp_set(&M, i);
-      }
-    }
-  }
-
-  /* done */
-  mp_clear(&t1);
-  mp_clear(&C);
-  mp_clear(&Q);
-  mp_clear(&S);
-  mp_clear(&Z);
-  mp_clear(&M);
-  mp_clear(&T);
-  mp_clear(&R);
-  mp_clear(&two);
-
-  return res;
-#endif
-}
-#endif
-#endif /* !WOLFSSL_ATECC508A */
-
-
-/* export public ECC key in ANSI X9.63 format compressed */
-static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
-{
-   word32 numlen;
-   int    ret = MP_OKAY;
-
-   if (key == NULL || out == NULL || outLen == NULL)
-       return BAD_FUNC_ARG;
-
-   if (wc_ecc_is_valid_idx(key->idx) == 0) {
-      return ECC_BAD_ARG_E;
-   }
-   numlen = key->dp->size;
-
-   if (*outLen < (1 + numlen)) {
-      *outLen = 1 + numlen;
-      return BUFFER_E;
-   }
-
-#ifdef WOLFSSL_ATECC508A
-   /* TODO: Implement equiv call to ATECC508A */
-   ret = BAD_COND_E;
-
-#else
-
-   /* store first byte */
-   out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
-
-   /* pad and store x */
-   XMEMSET(out+1, 0, numlen);
-   ret = mp_to_unsigned_bin(key->pubkey.x,
-                       out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
-   *outLen = 1 + numlen;
-
-#endif /* WOLFSSL_ATECC508A */
-
-   return ret;
-}
-
-#endif /* HAVE_COMP_KEY */
-
-
-int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz)
-{
-    int x;
-
-    if (oidSum == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* find matching OID sum (based on encoded value) */
-    for (x = 0; ecc_sets[x].size != 0; x++) {
-        if (ecc_sets[x].oidSum == oidSum) {
-            int ret = 0;
-        #ifdef HAVE_OID_ENCODING
-            /* check cache */
-            oid_cache_t* o = &ecc_oid_cache[x];
-            if (o->oidSz == 0) {
-                o->oidSz = sizeof(o->oid);
-                ret = EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz,
-                                                            o->oid, &o->oidSz);
-            }
-            if (oidSz) {
-                *oidSz = o->oidSz;
-            }
-            if (oid) {
-                *oid = o->oid;
-            }
-        #else
-            if (oidSz) {
-                *oidSz = ecc_sets[x].oidSz;
-            }
-            if (oid) {
-                *oid = ecc_sets[x].oid;
-            }
-        #endif
-            /* on success return curve id */
-            if (ret == 0) {
-                ret = ecc_sets[x].id;
-            }
-            return ret;
-        }
-    }
-
-    return NOT_COMPILED_IN;
-}
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp)
-{
-    if (key == NULL || dp == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    key->idx = ECC_CUSTOM_IDX;
-    key->dp = dp;
-
-    return 0;
-}
-#endif /* WOLFSSL_CUSTOM_CURVES */
-
-#ifdef HAVE_X963_KDF
-
-static WC_INLINE void IncrementX963KdfCounter(byte* inOutCtr)
-{
-    int i;
-
-    /* in network byte order so start at end and work back */
-    for (i = 3; i >= 0; i--) {
-        if (++inOutCtr[i])  /* we're done unless we overflow */
-            return;
-    }
-}
-
-/* ASN X9.63 Key Derivation Function (SEC1) */
-int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz,
-                const byte* sinfo, word32 sinfoSz, byte* out, word32 outSz)
-{
-    int ret, i;
-    int digestSz, copySz;
-    int remaining = outSz;
-    byte* outIdx;
-    byte  counter[4];
-    byte  tmp[WC_MAX_DIGEST_SIZE];
-
-#ifdef WOLFSSL_SMALL_STACK
-    wc_HashAlg* hash;
-#else
-    wc_HashAlg hash[1];
-#endif
-
-    if (secret == NULL || secretSz == 0 || out == NULL)
-        return BAD_FUNC_ARG;
-
-    /* X9.63 allowed algos only */
-    if (type != WC_HASH_TYPE_SHA    && type != WC_HASH_TYPE_SHA224 &&
-        type != WC_HASH_TYPE_SHA256 && type != WC_HASH_TYPE_SHA384 &&
-        type != WC_HASH_TYPE_SHA512)
-        return BAD_FUNC_ARG;
-
-    digestSz = wc_HashGetDigestSize(type);
-    if (digestSz < 0)
-        return digestSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
-                                DYNAMIC_TYPE_HASHES);
-    if (hash == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_HashInit(hash, type);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-        return ret;
-    }
-
-    outIdx = out;
-    XMEMSET(counter, 0, sizeof(counter));
-
-    for (i = 1; remaining > 0; i++) {
-
-        IncrementX963KdfCounter(counter);
-
-        ret = wc_HashUpdate(hash, type, secret, secretSz);
-        if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
-        }
-
-        ret = wc_HashUpdate(hash, type, counter, sizeof(counter));
-        if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
-        }
-
-        if (sinfo) {
-            ret = wc_HashUpdate(hash, type, sinfo, sinfoSz);
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-                return ret;
-            }
-        }
-
-        ret = wc_HashFinal(hash, type, tmp);
-        if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-            return ret;
-        }
-
-        copySz = min(remaining, digestSz);
-        XMEMCPY(outIdx, tmp, copySz);
-
-        remaining -= copySz;
-        outIdx += copySz;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-     XFREE(hash, NULL, DYNAMIC_TYPE_HASHES);
-#endif
-
-    return 0;
-}
-#endif /* HAVE_X963_KDF */
-
-#endif /* HAVE_ECC */
-
--- a/wolfcrypt/src/ecc_fp.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-/* dummy ecc_fp.c for dist */
-
--- a/wolfcrypt/src/ed25519.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,584 +0,0 @@
-/* ed25519.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-/* in case user set HAVE_ED25519 there */
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_ED25519
-
-#include <wolfssl/wolfcrypt/ed25519.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef FREESCALE_LTC_ECC
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-
-/* generate an ed25519 key pair.
- * returns 0 on success
- */
-int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
-{
-    byte  az[ED25519_PRV_KEY_SIZE];
-    int   ret;
-#if !defined(FREESCALE_LTC_ECC)
-    ge_p3 A;
-#endif
-
-    if (rng == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* ed25519 has 32 byte key sizes */
-    if (keySz != ED25519_KEY_SIZE)
-        return BAD_FUNC_ARG;
-
-    ret  = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
-    if (ret != 0)
-        return ret;
-    ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az);
-    if (ret != 0) {
-        ForceZero(key->k, ED25519_KEY_SIZE);
-        return ret;
-    }
-
-    /* apply clamp */
-    az[0]  &= 248;
-    az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
-    az[31] |= 64;
-
-#ifdef FREESCALE_LTC_ECC
-    ltc_pkha_ecc_point_t publicKey = {0};
-    publicKey.X = key->pointX;
-    publicKey.Y = key->pointY;
-    LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az, ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */);
-    LTC_PKHA_Ed25519_Compress(&publicKey, key->p);
-#else
-    ge_scalarmult_base(&A, az);
-    ge_p3_tobytes(key->p, &A);
-#endif
-    /* put public key after private key, on the same buffer */
-    XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
-
-    key->pubKeySet = 1;
-
-    return ret;
-}
-
-
-#ifdef HAVE_ED25519_SIGN
-/*
-    in     contains the message to sign
-    inlen  is the length of the message to sign
-    out    is the buffer to write the signature
-    outLen [in/out] input size of out buf
-                     output gets set as the final length of out
-    key    is the ed25519 key to use when signing
-    return 0 on success
- */
-int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
-                        word32 *outLen, ed25519_key* key)
-{
-#ifdef FREESCALE_LTC_ECC
-    byte   tempBuf[ED25519_PRV_KEY_SIZE];
-#else
-    ge_p3  R;
-#endif
-    byte   nonce[WC_SHA512_DIGEST_SIZE];
-    byte   hram[WC_SHA512_DIGEST_SIZE];
-    byte   az[ED25519_PRV_KEY_SIZE];
-    wc_Sha512 sha;
-    int    ret;
-
-    /* sanity check on arguments */
-    if (in == NULL || out == NULL || outLen == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-    if (!key->pubKeySet)
-        return BAD_FUNC_ARG;
-
-    /* check and set up out length */
-    if (*outLen < ED25519_SIG_SIZE) {
-        *outLen = ED25519_SIG_SIZE;
-        return BUFFER_E;
-    }
-    *outLen = ED25519_SIG_SIZE;
-
-    /* step 1: create nonce to use where nonce is r in
-       r = H(h_b, ... ,h_2b-1,M) */
-    ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az);
-    if (ret != 0)
-        return ret;
-
-    /* apply clamp */
-    az[0]  &= 248;
-    az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
-    az[31] |= 64;
-
-    ret = wc_InitSha512(&sha);
-    if (ret != 0)
-        return ret;
-    ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE);
-    if (ret == 0)
-        ret = wc_Sha512Update(&sha, in, inlen);
-    if (ret == 0)
-        ret = wc_Sha512Final(&sha, nonce);
-    wc_Sha512Free(&sha);
-    if (ret != 0)
-        return ret;
-
-#ifdef FREESCALE_LTC_ECC
-    ltc_pkha_ecc_point_t ltcPoint = {0};
-    ltcPoint.X = &tempBuf[0];
-    ltcPoint.Y = &tempBuf[32];
-    LTC_PKHA_sc_reduce(nonce);
-    LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, ED25519_KEY_SIZE, &ltcPoint, kLTC_Ed25519 /* result on Ed25519 */);
-    LTC_PKHA_Ed25519_Compress(&ltcPoint, out);
-#else
-    sc_reduce(nonce);
-
-    /* step 2: computing R = rB where rB is the scalar multiplication of
-       r and B */
-    ge_scalarmult_base(&R,nonce);
-    ge_p3_tobytes(out,&R);
-#endif
-
-    /* step 3: hash R + public key + message getting H(R,A,M) then
-       creating S = (r + H(R,A,M)a) mod l */
-    ret = wc_InitSha512(&sha);
-    if (ret != 0)
-        return ret;
-    ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2);
-    if (ret == 0)
-        ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
-    if (ret == 0)
-        ret = wc_Sha512Update(&sha, in, inlen);
-    if (ret == 0)
-        ret = wc_Sha512Final(&sha, hram);
-    wc_Sha512Free(&sha);
-    if (ret != 0)
-        return ret;
-
-#ifdef FREESCALE_LTC_ECC
-    LTC_PKHA_sc_reduce(hram);
-    LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
-#else
-    sc_reduce(hram);
-    sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
-#endif
-
-    return ret;
-}
-
-#endif /* HAVE_ED25519_SIGN */
-
-#ifdef HAVE_ED25519_VERIFY
-
-/*
-   sig     is array of bytes containing the signature
-   siglen  is the length of sig byte array
-   msg     the array of bytes containing the message
-   msglen  length of msg array
-   res     will be 1 on successful verify and 0 on unsuccessful
-   return  0 and res of 1 on success
-*/
-int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
-                          word32 msglen, int* res, ed25519_key* key)
-{
-    byte   rcheck[ED25519_KEY_SIZE];
-    byte   h[WC_SHA512_DIGEST_SIZE];
-#ifndef FREESCALE_LTC_ECC
-    ge_p3  A;
-    ge_p2  R;
-#endif
-    int    ret;
-    wc_Sha512 sha;
-
-    /* sanity check on arguments */
-    if (sig == NULL || msg == NULL || res == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* set verification failed by default */
-    *res = 0;
-
-    /* check on basics needed to verify signature */
-    if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
-        return BAD_FUNC_ARG;
-
-    /* uncompress A (public key), test if valid, and negate it */
-#ifndef FREESCALE_LTC_ECC
-    if (ge_frombytes_negate_vartime(&A, key->p) != 0)
-        return BAD_FUNC_ARG;
-#endif
-
-    /* find H(R,A,M) and store it as h */
-    ret  = wc_InitSha512(&sha);
-    if (ret != 0)
-        return ret;
-    ret = wc_Sha512Update(&sha, sig,    ED25519_SIG_SIZE/2);
-    if (ret == 0)
-        ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
-    if (ret == 0)
-        ret = wc_Sha512Update(&sha, msg,    msglen);
-    if (ret == 0)
-        ret = wc_Sha512Final(&sha,  h);
-    wc_Sha512Free(&sha);
-    if (ret != 0)
-        return ret;
-
-#ifdef FREESCALE_LTC_ECC
-    LTC_PKHA_sc_reduce(h);
-    LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key);
-#else
-    sc_reduce(h);
-
-    /*
-       Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
-       SB - H(R,A,M)A saving decompression of R
-    */
-    ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2));
-    if (ret != 0)
-        return ret;
-
-    ge_tobytes(rcheck, &R);
-#endif /* FREESCALE_LTC_ECC */
-
-    /* comparison of R created to R in sig */
-    ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
-    if (ret != 0)
-        return SIG_VERIFY_E;
-
-    /* set the verification status */
-    *res = 1;
-
-    return ret;
-}
-
-#endif /* HAVE_ED25519_VERIFY */
-
-
-/* initialize information and memory for key */
-int wc_ed25519_init(ed25519_key* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMSET(key, 0, sizeof(ed25519_key));
-
-#ifndef FREESCALE_LTC_ECC
-    fe_init();
-#endif
-
-    return 0;
-}
-
-
-/* clear memory of key */
-void wc_ed25519_free(ed25519_key* key)
-{
-    if (key == NULL)
-        return;
-
-    ForceZero(key, sizeof(ed25519_key));
-}
-
-
-#ifdef HAVE_ED25519_KEY_EXPORT
-
-/*
-    outLen should contain the size of out buffer when input. outLen is than set
-    to the final output length.
-    returns 0 on success
- */
-int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
-{
-    /* sanity check on arguments */
-    if (key == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    if (*outLen < ED25519_PUB_KEY_SIZE) {
-        *outLen = ED25519_PUB_KEY_SIZE;
-        return BUFFER_E;
-    }
-
-    *outLen = ED25519_PUB_KEY_SIZE;
-    XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE);
-
-    return 0;
-}
-
-#endif /* HAVE_ED25519_KEY_EXPORT */
-
-
-#ifdef HAVE_ED25519_KEY_IMPORT
-/*
-    Imports a compressed/uncompressed public key.
-    in    the byte array containing the public key
-    inLen the length of the byte array being passed in
-    key   ed25519 key struct to put the public key in
- */
-int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
-{
-    int    ret;
-
-    /* sanity check on arguments */
-    if (in == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    if (inLen < ED25519_PUB_KEY_SIZE)
-        return BAD_FUNC_ARG;
-
-    /* compressed prefix according to draft
-       http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
-    if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) {
-        /* key is stored in compressed format so just copy in */
-        XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE);
-#ifdef FREESCALE_LTC_ECC
-        /* recover X coordinate */
-        ltc_pkha_ecc_point_t pubKey;
-        pubKey.X = key->pointX;
-        pubKey.Y = key->pointY;
-        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
-#endif
-        key->pubKeySet = 1;
-        return 0;
-    }
-
-    /* importing uncompressed public key */
-    if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) {
-#ifdef FREESCALE_LTC_ECC
-        /* reverse bytes for little endian byte order */
-        for (int i = 0; i < ED25519_KEY_SIZE; i++)
-        {
-            key->pointX[i] = *(in + ED25519_KEY_SIZE - i);
-            key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i);
-        }
-        XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE);
-        ret = 0;
-#else
-        /* pass in (x,y) and store compressed key */
-        ret = ge_compress_key(key->p, in+1,
-                              in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
-#endif /* FREESCALE_LTC_ECC */
-        if (ret == 0)
-            key->pubKeySet = 1;
-        return ret;
-    }
-
-    /* if not specified compressed or uncompressed check key size
-       if key size is equal to compressed key size copy in key */
-    if (inLen == ED25519_PUB_KEY_SIZE) {
-        XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
-#ifdef FREESCALE_LTC_ECC
-        /* recover X coordinate */
-        ltc_pkha_ecc_point_t pubKey;
-        pubKey.X = key->pointX;
-        pubKey.Y = key->pointY;
-        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
-#endif
-        key->pubKeySet = 1;
-        return 0;
-    }
-
-    /* bad public key format */
-    return BAD_FUNC_ARG;
-}
-
-
-/*
-    For importing a private key.
- */
-int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
-                                                               ed25519_key* key)
-{
-    /* sanity check on arguments */
-    if (priv == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* key size check */
-    if (privSz < ED25519_KEY_SIZE)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
-
-    return 0;
-}
-
-/*
-    For importing a private key and its associated public key.
- */
-int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
-                                const byte* pub, word32 pubSz, ed25519_key* key)
-{
-    int    ret;
-
-    /* sanity check on arguments */
-    if (priv == NULL || pub == NULL || key == NULL)
-        return BAD_FUNC_ARG;
-
-    /* key size check */
-    if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE)
-        return BAD_FUNC_ARG;
-
-    /* import public key */
-    ret = wc_ed25519_import_public(pub, pubSz, key);
-    if (ret != 0)
-        return ret;
-
-    /* make the private key (priv + pub) */
-    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
-    XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
-
-    return ret;
-}
-
-#endif /* HAVE_ED25519_KEY_IMPORT */
-
-
-#ifdef HAVE_ED25519_KEY_EXPORT
-
-/*
- export private key only (secret part so 32 bytes)
- outLen should contain the size of out buffer when input. outLen is than set
- to the final output length.
- returns 0 on success
- */
-int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
-{
-    /* sanity checks on arguments */
-    if (key == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    if (*outLen < ED25519_KEY_SIZE) {
-        *outLen = ED25519_KEY_SIZE;
-        return BUFFER_E;
-    }
-
-    *outLen = ED25519_KEY_SIZE;
-    XMEMCPY(out, key->k, ED25519_KEY_SIZE);
-
-    return 0;
-}
-
-/*
- export private key, including public part
- outLen should contain the size of out buffer when input. outLen is than set
- to the final output length.
- returns 0 on success
- */
-int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen)
-{
-    /* sanity checks on arguments */
-    if (key == NULL || out == NULL || outLen == NULL)
-        return BAD_FUNC_ARG;
-
-    if (*outLen < ED25519_PRV_KEY_SIZE) {
-        *outLen = ED25519_PRV_KEY_SIZE;
-        return BUFFER_E;
-    }
-
-    *outLen = ED25519_PRV_KEY_SIZE;
-    XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE);
-
-    return 0;
-}
-
-/* export full private key and public key
-   return 0 on success
- */
-int wc_ed25519_export_key(ed25519_key* key,
-                          byte* priv, word32 *privSz,
-                          byte* pub, word32 *pubSz)
-{
-    int ret;
-
-    /* export 'full' private part */
-    ret = wc_ed25519_export_private(key, priv, privSz);
-    if (ret != 0)
-        return ret;
-
-    /* export public part */
-    ret = wc_ed25519_export_public(key, pub, pubSz);
-
-    return ret;
-}
-
-#endif /* HAVE_ED25519_KEY_EXPORT */
-
-/* check the private and public keys match */
-int wc_ed25519_check_key(ed25519_key* key)
-{
-    /* TODO: Perform check of private and public key */
-    (void)key;
-
-    return 0;
-}
-
-/* returns the private key size (secret only) in bytes */
-int wc_ed25519_size(ed25519_key* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    return ED25519_KEY_SIZE;
-}
-
-/* returns the private key size (secret + public) in bytes */
-int wc_ed25519_priv_size(ed25519_key* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    return ED25519_PRV_KEY_SIZE;
-}
-
-/* returns the compressed key size in bytes (public key) */
-int wc_ed25519_pub_size(ed25519_key* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    return ED25519_PUB_KEY_SIZE;
-}
-
-/* returns the size of signature in bytes */
-int wc_ed25519_sig_size(ed25519_key* key)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    return ED25519_SIG_SIZE;
-}
-
-#endif /* HAVE_ED25519 */
-
-
--- a/wolfcrypt/src/error.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,497 +0,0 @@
-/* error.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifdef _MSC_VER
-    /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
-    #pragma warning(disable: 4996)
-#endif
-
-#ifndef NO_ERROR_STRINGS
-const char* wc_GetErrorString(int error)
-{
-    switch (error) {
-
-    case OPEN_RAN_E :
-        return "opening random device error";
-
-    case READ_RAN_E :
-        return "reading random device error";
-
-    case WINCRYPT_E :
-        return "windows crypt init error";
-
-    case CRYPTGEN_E :
-        return "windows crypt generation error";
-
-    case RAN_BLOCK_E :
-        return "random device read would block error";
-
-    case BAD_MUTEX_E :
-        return "Bad mutex, operation failed";
-
-    case WC_TIMEOUT_E:
-        return "Timeout error";
-
-    case WC_PENDING_E:
-        return "wolfCrypt Operation Pending (would block / eagain) error";
-
-    case WC_NOT_PENDING_E:
-        return "wolfCrypt operation not pending error";
-
-    case MP_INIT_E :
-        return "mp_init error state";
-
-    case MP_READ_E :
-        return "mp_read error state";
-
-    case MP_EXPTMOD_E :
-        return "mp_exptmod error state";
-
-    case MP_TO_E :
-        return "mp_to_xxx error state, can't convert";
-
-    case MP_SUB_E :
-        return "mp_sub error state, can't subtract";
-
-    case MP_ADD_E :
-        return "mp_add error state, can't add";
-
-    case MP_MUL_E :
-        return "mp_mul error state, can't multiply";
-
-    case MP_MULMOD_E :
-        return "mp_mulmod error state, can't multiply mod";
-
-    case MP_MOD_E :
-        return "mp_mod error state, can't mod";
-
-    case MP_INVMOD_E :
-        return "mp_invmod error state, can't inv mod";
-
-    case MP_CMP_E :
-        return "mp_cmp error state";
-
-    case MP_ZERO_E :
-        return "mp zero result, not expected";
-
-    case MEMORY_E :
-        return "out of memory error";
-
-    case VAR_STATE_CHANGE_E :
-        return "Variable state modified by different thread";
-
-    case RSA_WRONG_TYPE_E :
-        return "RSA wrong block type for RSA function";
-
-    case RSA_BUFFER_E :
-        return "RSA buffer error, output too small or input too big";
-
-    case BUFFER_E :
-        return "Buffer error, output too small or input too big";
-
-    case ALGO_ID_E :
-        return "Setting Cert AlgoID error";
-
-    case PUBLIC_KEY_E :
-        return "Setting Cert Public Key error";
-
-    case DATE_E :
-        return "Setting Cert Date validity error";
-
-    case SUBJECT_E :
-        return "Setting Cert Subject name error";
-
-    case ISSUER_E :
-        return "Setting Cert Issuer name error";
-
-    case CA_TRUE_E :
-        return "Setting basic constraint CA true error";
-
-    case EXTENSIONS_E :
-        return "Setting extensions error";
-
-    case ASN_PARSE_E :
-        return "ASN parsing error, invalid input";
-
-    case ASN_VERSION_E :
-        return "ASN version error, invalid number";
-
-    case ASN_GETINT_E :
-        return "ASN get big int error, invalid data";
-
-    case ASN_RSA_KEY_E :
-        return "ASN key init error, invalid input";
-
-    case ASN_OBJECT_ID_E :
-        return "ASN object id error, invalid id";
-
-    case ASN_TAG_NULL_E :
-        return "ASN tag error, not null";
-
-    case ASN_EXPECT_0_E :
-        return "ASN expect error, not zero";
-
-    case ASN_BITSTR_E :
-        return "ASN bit string error, wrong id";
-
-    case ASN_UNKNOWN_OID_E :
-        return "ASN oid error, unknown sum id";
-
-    case ASN_DATE_SZ_E :
-        return "ASN date error, bad size";
-
-    case ASN_BEFORE_DATE_E :
-        return "ASN date error, current date before";
-
-    case ASN_AFTER_DATE_E :
-        return "ASN date error, current date after";
-
-    case ASN_SIG_OID_E :
-        return "ASN signature error, mismatched oid";
-
-    case ASN_TIME_E :
-        return "ASN time error, unknown time type";
-
-    case ASN_INPUT_E :
-        return "ASN input error, not enough data";
-
-    case ASN_SIG_CONFIRM_E :
-        return "ASN sig error, confirm failure";
-
-    case ASN_SIG_HASH_E :
-        return "ASN sig error, unsupported hash type";
-
-    case ASN_SIG_KEY_E :
-        return "ASN sig error, unsupported key type";
-
-    case ASN_DH_KEY_E :
-        return "ASN key init error, invalid input";
-
-    case ASN_NTRU_KEY_E :
-        return "ASN NTRU key decode error, invalid input";
-
-    case ASN_CRIT_EXT_E:
-        return "X.509 Critical extension ignored or invalid";
-
-    case ASN_ALT_NAME_E:
-        return "ASN alternate name error";
-
-    case ECC_BAD_ARG_E :
-        return "ECC input argument wrong type, invalid input";
-
-    case ASN_ECC_KEY_E :
-        return "ECC ASN1 bad key data, invalid input";
-
-    case ECC_CURVE_OID_E :
-        return "ECC curve sum OID unsupported, invalid input";
-
-    case BAD_FUNC_ARG :
-        return "Bad function argument";
-
-    case NOT_COMPILED_IN :
-        return "Feature not compiled in";
-
-    case UNICODE_SIZE_E :
-        return "Unicode password too big";
-
-    case NO_PASSWORD :
-        return "No password provided by user";
-
-    case ALT_NAME_E :
-        return "Alt Name problem, too big";
-
-    case AES_GCM_AUTH_E:
-        return "AES-GCM Authentication check fail";
-
-    case AES_CCM_AUTH_E:
-        return "AES-CCM Authentication check fail";
-
-    case ASYNC_INIT_E:
-        return "Async Init error";
-
-    case COMPRESS_INIT_E:
-        return "Compress Init error";
-
-    case COMPRESS_E:
-        return "Compress error";
-
-    case DECOMPRESS_INIT_E:
-        return "DeCompress Init error";
-
-    case DECOMPRESS_E:
-        return "DeCompress error";
-
-    case BAD_ALIGN_E:
-        return "Bad alignment error, no alloc help";
-
-    case ASN_NO_SIGNER_E :
-        return "ASN no signer error to confirm failure";
-
-    case ASN_CRL_CONFIRM_E :
-        return "ASN CRL sig error, confirm failure";
-
-    case ASN_CRL_NO_SIGNER_E :
-        return "ASN CRL no signer error to confirm failure";
-
-    case ASN_OCSP_CONFIRM_E :
-        return "ASN OCSP sig error, confirm failure";
-
-    case ASN_NO_PEM_HEADER:
-        return "ASN no PEM Header Error";
-
-    case BAD_STATE_E:
-        return "Bad state operation";
-
-    case BAD_PADDING_E:
-        return "Bad padding, message wrong length";
-
-    case REQ_ATTRIBUTE_E:
-        return "Setting cert request attributes error";
-
-    case PKCS7_OID_E:
-        return "PKCS#7 error: mismatched OID value";
-
-    case PKCS7_RECIP_E:
-        return "PKCS#7 error: no matching recipient found";
-
-    case FIPS_NOT_ALLOWED_E:
-        return "FIPS mode not allowed error";
-
-    case ASN_NAME_INVALID_E:
-        return "Name Constraint error";
-
-    case RNG_FAILURE_E:
-        return "Random Number Generator failed";
-
-    case HMAC_MIN_KEYLEN_E:
-        return "FIPS Mode HMAC Minimum Key Length error";
-
-    case RSA_PAD_E:
-        return "Rsa Padding error";
-
-    case LENGTH_ONLY_E:
-        return "Output length only set, not for other use error";
-
-    case IN_CORE_FIPS_E:
-        return "In Core Integrity check FIPS error";
-
-    case AES_KAT_FIPS_E:
-        return "AES Known Answer Test check FIPS error";
-
-    case DES3_KAT_FIPS_E:
-        return "DES3 Known Answer Test check FIPS error";
-
-    case HMAC_KAT_FIPS_E:
-        return "HMAC Known Answer Test check FIPS error";
-
-    case RSA_KAT_FIPS_E:
-        return "RSA Known Answer Test check FIPS error";
-
-    case DRBG_KAT_FIPS_E:
-        return "DRBG Known Answer Test check FIPS error";
-
-    case DRBG_CONT_FIPS_E:
-        return "DRBG Continuous Test FIPS error";
-
-    case AESGCM_KAT_FIPS_E:
-        return "AESGCM Known Answer Test check FIPS error";
-
-    case THREAD_STORE_KEY_E:
-        return "Thread Storage Key Create error";
-
-    case THREAD_STORE_SET_E:
-        return "Thread Storage Set error";
-
-    case MAC_CMP_FAILED_E:
-        return "MAC comparison failed";
-
-    case IS_POINT_E:
-        return "ECC is point on curve failed";
-
-    case ECC_INF_E:
-        return " ECC point at infinity error";
-
-    case ECC_OUT_OF_RANGE_E:
-        return " ECC Qx or Qy out of range error";
-
-    case ECC_PRIV_KEY_E:
-        return " ECC private key is not valid error";
-
-    case SRP_CALL_ORDER_E:
-        return "SRP function called in the wrong order error";
-
-    case SRP_VERIFY_E:
-        return "SRP proof verification error";
-
-    case SRP_BAD_KEY_E:
-        return "SRP bad key values error";
-
-    case ASN_NO_SKID:
-        return "ASN no Subject Key Identifier found error";
-
-    case ASN_NO_AKID:
-        return "ASN no Authority Key Identifier found error";
-
-    case ASN_NO_KEYUSAGE:
-        return "ASN no Key Usage found error";
-
-    case SKID_E:
-        return "Setting Subject Key Identifier error";
-
-    case AKID_E:
-        return "Setting Authority Key Identifier error";
-
-    case KEYUSAGE_E:
-        return "Key Usage value error";
-
-    case EXTKEYUSAGE_E:
-        return "Extended Key Usage value error";
-
-    case CERTPOLICIES_E:
-        return "Setting Certificate Policies error";
-
-    case WC_INIT_E:
-        return "wolfCrypt Initialize Failure error";
-
-    case SIG_VERIFY_E:
-        return "Signature verify error";
-
-    case BAD_COND_E:
-        return "Bad condition variable operation error";
-
-    case SIG_TYPE_E:
-        return "Signature type not enabled/available";
-
-    case HASH_TYPE_E:
-        return "Hash type not enabled/available";
-
-    case WC_KEY_SIZE_E:
-        return "Key size error, either too small or large";
-
-    case ASN_COUNTRY_SIZE_E:
-        return "Country code size error, either too small or large";
-
-    case MISSING_RNG_E:
-        return "RNG required but not provided";
-
-    case ASN_PATHLEN_SIZE_E:
-        return "ASN CA path length value too large error";
-
-    case ASN_PATHLEN_INV_E:
-        return "ASN CA path length larger than signer error";
-
-    case BAD_KEYWRAP_ALG_E:
-        return "Unsupported key wrap algorithm error";
-
-    case BAD_KEYWRAP_IV_E:
-        return "Decrypted AES key wrap IV does not match expected";
-
-    case WC_CLEANUP_E:
-        return "wolfcrypt cleanup failed";
-
-    case ECC_CDH_KAT_FIPS_E:
-        return "wolfcrypt FIPS ECC CDH Known Answer Test Failure";
-
-    case DH_CHECK_PUB_E:
-        return "DH Check Public Key failure";
-
-    case BAD_PATH_ERROR:
-        return "Bad path for opendir error";
-
-    case ASYNC_OP_E:
-        return "Async operation error";
-
-    case BAD_OCSP_RESPONDER:
-        return "Invalid OCSP Responder, missing specific key usage extensions";
-
-    case ECC_PRIVATEONLY_E:
-        return "Invalid use of private only ECC key";
-
-    case WC_HW_E:
-        return "Error with hardware crypto use";
-
-    case WC_HW_WAIT_E:
-        return "Hardware waiting on resource";
-
-    case PSS_SALTLEN_E:
-        return "PSS - Length of salt is too big for hash algorithm";
-
-    case PRIME_GEN_E:
-        return "Unable to find a prime for RSA key";
-
-    case BER_INDEF_E:
-        return "Unable to decode an indefinite length encoded message";
-
-    case RSA_OUT_OF_RANGE_E:
-        return "Ciphertext to decrypt is out of range";
-
-    case RSAPSS_PAT_FIPS_E:
-        return "wolfcrypt FIPS RSA-PSS Pairwise Agreement Test Failure";
-
-    case ECDSA_PAT_FIPS_E:
-        return "wolfcrypt FIPS ECDSA Pairwise Agreement Test Failure";
-
-    case DH_KAT_FIPS_E:
-        return "wolfcrypt FIPS DH Known Answer Test Failure";
-
-    case AESCCM_KAT_FIPS_E:
-        return "AESCCM Known Answer Test check FIPS error";
-
-    case SHA3_KAT_FIPS_E:
-        return "SHA-3 Known Answer Test check FIPS error";
-
-    case ECDHE_KAT_FIPS_E:
-        return "wolfcrypt FIPS ECDHE Known Answer Test Failure";
-
-    case AES_GCM_OVERFLOW_E:
-        return "AES-GCM invocation counter overflow";
-
-    case AES_CCM_OVERFLOW_E:
-        return "AES-CCM invocation counter overflow";
-
-    case RSA_KEY_PAIR_E:
-        return "RSA Key Pair-Wise Consistency check fail";
-
-    case DH_CHECK_PRIV_E:
-        return "DH Check Private Key failure";
-
-    default:
-        return "unknown error number";
-
-    }
-}
-
-void wc_ErrorString(int error, char* buffer)
-{
-    XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ);
-}
-#endif /* !NO_ERROR_STRINGS */
-
-
--- a/wolfcrypt/src/evp.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1319 +0,0 @@
-/* evp.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-#if !defined(WOLFSSL_EVP_INCLUDED)
-    #ifndef WOLFSSL_IGNORE_FILE_WARN
-        #warning evp.c does not need to be compiled seperatly from ssl.c
-    #endif
-#else
-
-static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher);
-
-
-/* Getter function for cipher key length
- *
- * c  WOLFSSL_EVP_CIPHER structure to get key length from
- *
- * NOTE: OpenSSL_add_all_ciphers() should be called first before using this
- *       function
- *
- * Returns size of key in bytes
- */
-int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c)
-{
-    WOLFSSL_ENTER("wolfSSL_EVP_Cipher_key_length");
-
-    if (c == NULL) {
-        return 0;
-    }
-
-    switch (cipherType(c)) {
-    #if !defined(NO_AES) && defined(HAVE_AES_CBC)
-      case AES_128_CBC_TYPE: return 16;
-      case AES_192_CBC_TYPE: return 24;
-      case AES_256_CBC_TYPE: return 32;
-  #endif
-  #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-      case AES_128_CTR_TYPE: return 16;
-      case AES_192_CTR_TYPE: return 24;
-      case AES_256_CTR_TYPE: return 32;
-  #endif
-  #if !defined(NO_AES) && defined(HAVE_AES_ECB)
-      case AES_128_ECB_TYPE: return 16;
-      case AES_192_ECB_TYPE: return 24;
-      case AES_256_ECB_TYPE: return 32;
-  #endif
-  #ifndef NO_DES3
-      case DES_CBC_TYPE:      return 8;
-      case DES_EDE3_CBC_TYPE: return 24;
-      case DES_ECB_TYPE:      return 8;
-      case DES_EDE3_ECB_TYPE: return 24;
-  #endif
-      default:
-          return 0;
-      }
-}
-
-
-WOLFSSL_API int  wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                        const WOLFSSL_EVP_CIPHER* type,
-                                        const unsigned char* key,
-                                        const unsigned char* iv)
-{
-    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1);
-}
-
-WOLFSSL_API int  wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                        const WOLFSSL_EVP_CIPHER* type,
-                                        WOLFSSL_ENGINE *impl,
-                                        const unsigned char* key,
-                                        const unsigned char* iv)
-{
-    (void) impl;
-    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1);
-}
-
-WOLFSSL_API int  wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                        const WOLFSSL_EVP_CIPHER* type,
-                                        const unsigned char* key,
-                                        const unsigned char* iv)
-{
-    WOLFSSL_ENTER("wolfSSL_EVP_CipherInit");
-    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0);
-}
-
-WOLFSSL_API int  wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                        const WOLFSSL_EVP_CIPHER* type,
-                                        WOLFSSL_ENGINE *impl,
-                                        const unsigned char* key,
-                                        const unsigned char* iv)
-{
-    (void) impl;
-    WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit");
-    return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0);
-}
-
-
-WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void)
-{
-	WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx,
-                                                 NULL, DYNAMIC_TYPE_TMP_BUFFER);
-	if (ctx) {
-      WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new");
-		  wolfSSL_EVP_CIPHER_CTX_init(ctx);
-  }
-	return ctx;
-}
-
-WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx)
-{
-    if (ctx) {
-        WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free");
-		    wolfSSL_EVP_CIPHER_CTX_cleanup(ctx);
-		    XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-		}
-}
-
-WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx)
-{
-  if (ctx == NULL) return 0;
-  return ctx->flags & WOLFSSL_EVP_CIPH_MODE;
-}
-
-WOLFSSL_API int  wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl)
-{
-    if (ctx && ctx->enc) {
-        WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal");
-        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
-    }
-    else
-        return WOLFSSL_FAILURE;
-}
-
-
-WOLFSSL_API int  wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx,
-                                    const WOLFSSL_EVP_CIPHER* type,
-                                    WOLFSSL_ENGINE *impl,
-                                    const unsigned char* key,
-                                    const unsigned char* iv,
-                                    int enc)
-{
-    (void)impl;
-    return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc);
-}
-
-WOLFSSL_API int  wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl)
-{
-    if (ctx && ctx->enc) {
-        WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex");
-        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
-    }
-    else
-        return WOLFSSL_FAILURE;
-}
-
-WOLFSSL_API int  wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl)
-{
-  if (ctx && ctx->enc)
-      return WOLFSSL_FAILURE;
-  else {
-      WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal");
-      return wolfSSL_EVP_CipherFinal(ctx, out, outl);
-  }
-}
-
-WOLFSSL_API int  wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl)
-{
-    if (ctx && ctx->enc)
-        return WOLFSSL_FAILURE;
-    else {
-        WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal_ex");
-        return wolfSSL_EVP_CipherFinal(ctx, out, outl);
-    }
-}
-
-
-WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
-                                     const WOLFSSL_EVP_MD* type,
-                                     WOLFSSL_ENGINE *impl)
-{
-    (void) impl;
-    WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex");
-    return wolfSSL_EVP_DigestInit(ctx, type);
-}
-
-#ifdef DEBUG_WOLFSSL_EVP
-#define PRINT_BUF(b, sz) { int _i; for(_i=0; _i<(sz); _i++) { \
-  printf("%02x(%c),", (b)[_i], (b)[_i]); if ((_i+1)%8==0)printf("\n");}}
-#else
-#define PRINT_BUF(b, sz)
-#endif
-
-static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz)
-{
-    int fill;
-
-    if (sz > 0) {
-        if ((sz+ctx->bufUsed) > ctx->block_size) {
-            fill = ctx->block_size - ctx->bufUsed;
-        } else {
-            fill = sz;
-        }
-        XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill);
-        ctx->bufUsed += fill;
-        return fill;
-    } else return 0;
-}
-
-static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out,
-                                   const unsigned char *in, int inl)
-{
-    int ret = 0;
-
-    switch (ctx->cipherType) {
-    #if !defined(NO_AES) && defined(HAVE_AES_CBC)
-        case AES_128_CBC_TYPE:
-        case AES_192_CBC_TYPE:
-        case AES_256_CBC_TYPE:
-            if (ctx->enc)
-                ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl);
-            else
-                ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl);
-            break;
-    #endif
-    #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-        case AES_128_CTR_TYPE:
-        case AES_192_CTR_TYPE:
-        case AES_256_CTR_TYPE:
-            ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl);
-            break;
-    #endif
-    #if !defined(NO_AES) && defined(HAVE_AES_ECB)
-        case AES_128_ECB_TYPE:
-        case AES_192_ECB_TYPE:
-        case AES_256_ECB_TYPE:
-            if (ctx->enc)
-                ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl);
-            else
-                ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl);
-            break;
-    #endif
-    #ifndef NO_DES3
-        case DES_CBC_TYPE:
-            if (ctx->enc)
-                ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl);
-            else
-                ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl);
-            break;
-        case DES_EDE3_CBC_TYPE:
-            if (ctx->enc)
-                ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl);
-            else
-                ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl);
-            break;
-        #if defined(WOLFSSL_DES_ECB)
-        case DES_ECB_TYPE:
-            ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl);
-            break;
-        case DES_EDE3_ECB_TYPE:
-            ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl);
-            break;
-        #endif
-    #endif
-    #ifndef NO_RC4
-        case ARC4_TYPE:
-            wc_Arc4Process(&ctx->cipher.arc4, out, in, inl);
-        break;
-    #endif
-        default:
-            return WOLFSSL_FAILURE;
-    }
-
-    if (ret != 0)
-        return WOLFSSL_FAILURE; /* failure */
-
-    (void)in;
-    (void)inl;
-    (void)out;
-
-    return WOLFSSL_SUCCESS; /* success */
-}
-
-WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl,
-                                   const unsigned char *in, int inl)
-{
-    int blocks;
-    int fill;
-
-    if ((ctx == NULL) || (inl < 0) ||
-        (outl == NULL)|| (out == NULL) || (in == NULL)) return BAD_FUNC_ARG;
-    WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate");
-
-    *outl = 0;
-    if (inl == 0) return WOLFSSL_SUCCESS;
-
-    if (ctx->bufUsed > 0) { /* concatinate them if there is anything */
-        fill = fillBuff(ctx, in, inl);
-        inl -= fill;
-        in  += fill;
-    }
-    if ((ctx->enc == 0)&& (ctx->lastUsed == 1)) {
-        PRINT_BUF(ctx->lastBlock, ctx->block_size);
-        XMEMCPY(out, ctx->lastBlock, ctx->block_size);
-        *outl+= ctx->block_size;
-        out  += ctx->block_size;
-    }
-    if (ctx->bufUsed == ctx->block_size) {
-        /* the buff is full, flash out */
-        PRINT_BUF(ctx->buf, ctx->block_size);
-        if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0)
-            return WOLFSSL_FAILURE;
-        PRINT_BUF(out, ctx->block_size);
-        if (ctx->enc == 0) {
-            ctx->lastUsed = 1;
-            XMEMCPY(ctx->lastBlock, out, ctx->block_size);
-        } else {
-            *outl+= ctx->block_size;
-            out  += ctx->block_size;
-        }
-        ctx->bufUsed = 0;
-    }
-
-    blocks = inl / ctx->block_size;
-    if (blocks > 0) {
-        /* process blocks */
-        if (evpCipherBlock(ctx, out, in, blocks * ctx->block_size) == 0)
-            return WOLFSSL_FAILURE;
-        PRINT_BUF(in, ctx->block_size*blocks);
-        PRINT_BUF(out,ctx->block_size*blocks);
-        inl  -= ctx->block_size * blocks;
-        in   += ctx->block_size * blocks;
-        if (ctx->enc == 0) {
-            if ((ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) ||
-                    (ctx->block_size == 1)) {
-                ctx->lastUsed = 0;
-                XMEMCPY(ctx->lastBlock, &out[ctx->block_size * blocks], ctx->block_size);
-                *outl+= ctx->block_size * blocks;
-            } else {
-                ctx->lastUsed = 1;
-                XMEMCPY(ctx->lastBlock, &out[ctx->block_size * (blocks-1)], ctx->block_size);
-                *outl+= ctx->block_size * (blocks-1);
-            }
-        } else {
-            *outl+= ctx->block_size * blocks;
-        }
-    }
-    if (inl > 0) {
-        /* put fraction into buff */
-        fillBuff(ctx, in, inl);
-        /* no increase of outl */
-    }
-
-    (void)out; /* silence warning in case not read */
-
-    return WOLFSSL_SUCCESS;
-}
-
-static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx)
-{
-    int i;
-    for (i = ctx->bufUsed; i < ctx->block_size; i++)
-        ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed);
-}
-
-static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff)
-{
-    int i;
-    int n;
-    n = buff[ctx->block_size-1];
-    if (n > ctx->block_size) return -1;
-    for (i = 0; i < n; i++) {
-        if (buff[ctx->block_size-i-1] != n)
-            return -1;
-    }
-    return ctx->block_size - n;
-}
-
-WOLFSSL_API int  wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
-                                   unsigned char *out, int *outl)
-{
-    int fl;
-    if (ctx == NULL || out == NULL) return BAD_FUNC_ARG;
-    WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
-    if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
-        if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
-        *outl = 0;
-        return WOLFSSL_SUCCESS;
-    }
-    if (ctx->enc) {
-        if (ctx->block_size == 1) {
-            *outl = 0;
-            return WOLFSSL_SUCCESS;
-        }
-        if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
-            padBlock(ctx);
-            PRINT_BUF(ctx->buf, ctx->block_size);
-            if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0)
-                return WOLFSSL_FAILURE;
-
-            PRINT_BUF(out, ctx->block_size);
-            *outl = ctx->block_size;
-        }
-    } else {
-        if (ctx->block_size == 1) {
-            *outl = 0;
-            return WOLFSSL_SUCCESS;
-        }
-        if (ctx->lastUsed) {
-            PRINT_BUF(ctx->lastBlock, ctx->block_size);
-            if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
-                XMEMCPY(out, ctx->lastBlock, fl);
-                *outl = fl;
-            } else return 0;
-        }
-    }
-    return WOLFSSL_SUCCESS;
-}
-
-WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx)
-{
-    if (ctx == NULL) return BAD_FUNC_ARG;
-    switch (ctx->cipherType) {
-#if !defined(NO_AES) || !defined(NO_DES3)
-#if !defined(NO_AES) && defined(HAVE_AES_CBC)
-    case AES_128_CBC_TYPE:
-    case AES_192_CBC_TYPE:
-    case AES_256_CBC_TYPE:
-#endif
-#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-    case AES_128_CTR_TYPE:
-    case AES_192_CTR_TYPE:
-    case AES_256_CTR_TYPE:
-#endif
-#if !defined(NO_AES)
-    case AES_128_ECB_TYPE:
-    case AES_192_ECB_TYPE:
-    case AES_256_ECB_TYPE:
-#endif
-#ifndef NO_DES3
-    case DES_CBC_TYPE:
-    case DES_ECB_TYPE:
-    case DES_EDE3_CBC_TYPE:
-    case DES_EDE3_ECB_TYPE:
-#endif
-        return ctx->block_size;
-#endif /* !NO_AES || !NO_DES3 */
-    default:
-        return 0;
-    }
-}
-
-static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher)
-{
-    if (cipher == NULL) return 0; /* dummy for #ifdef */
-  #ifndef NO_DES3
-      else if (XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0)
-          return DES_CBC_TYPE;
-      else if (XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)
-          return DES_EDE3_CBC_TYPE;
-  #if !defined(NO_DES3)
-      else if (XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0)
-          return DES_ECB_TYPE;
-      else if (XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)
-          return DES_EDE3_ECB_TYPE;
-  #endif /* NO_DES3 && HAVE_AES_ECB */
-  #endif
-
-  #if !defined(NO_AES) && defined(HAVE_AES_CBC)
-      #ifdef WOLFSSL_AES_128
-      else if (XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)
-          return AES_128_CBC_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_192
-      else if (XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)
-          return AES_192_CBC_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_256
-      else if (XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)
-          return AES_256_CBC_TYPE;
-      #endif
-  #endif /* !NO_AES && HAVE_AES_CBC */
-  #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-      #ifdef WOLFSSL_AES_128
-      else if (XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)
-          return AES_128_CTR_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_192
-      else if (XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)
-          return AES_192_CTR_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_256
-      else if (XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)
-          return AES_256_CTR_TYPE;
-      #endif
-  #endif /* !NO_AES && HAVE_AES_CBC */
-  #if !defined(NO_AES) && defined(HAVE_AES_ECB)
-      #ifdef WOLFSSL_AES_128
-      else if (XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)
-          return AES_128_ECB_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_192
-      else if (XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)
-          return AES_192_ECB_TYPE;
-      #endif
-      #ifdef WOLFSSL_AES_256
-      else if (XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)
-          return AES_256_ECB_TYPE;
-      #endif
-  #endif /* !NO_AES && HAVE_AES_CBC */
-      else return 0;
-}
-
-WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher)
-{
-  if (cipher == NULL) return BAD_FUNC_ARG;
-  switch (cipherType(cipher)) {
-  #if !defined(NO_AES) && defined(HAVE_AES_CBC)
-      case AES_128_CBC_TYPE:
-      case AES_192_CBC_TYPE:
-      case AES_256_CBC_TYPE:
-                             return AES_BLOCK_SIZE;
-  #endif
-  #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-      case AES_128_CTR_TYPE:
-      case AES_192_CTR_TYPE:
-      case AES_256_CTR_TYPE:
-                             return AES_BLOCK_SIZE;
-  #endif
-  #if !defined(NO_AES) && defined(HAVE_AES_ECB)
-      case AES_128_ECB_TYPE:
-      case AES_192_ECB_TYPE:
-      case AES_256_ECB_TYPE:
-                             return AES_BLOCK_SIZE;
-  #endif
-  #ifndef NO_DES3
-      case DES_CBC_TYPE: return 8;
-      case DES_EDE3_CBC_TYPE: return 8;
-      case DES_ECB_TYPE: return 8;
-      case DES_EDE3_ECB_TYPE: return 8;
-  #endif
-      default:
-          return 0;
-      }
-}
-
-unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
-{
-    switch (cipherType(cipher)) {
-    #if !defined(NO_AES) && defined(HAVE_AES_CBC)
-        case AES_128_CBC_TYPE:
-        case AES_192_CBC_TYPE:
-        case AES_256_CBC_TYPE:
-            return WOLFSSL_EVP_CIPH_CBC_MODE;
-    #endif
-    #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
-        case AES_128_CTR_TYPE:
-        case AES_192_CTR_TYPE:
-        case AES_256_CTR_TYPE:
-            return WOLFSSL_EVP_CIPH_CTR_MODE;
-    #endif
-    #if !defined(NO_AES)
-        case AES_128_ECB_TYPE:
-        case AES_192_ECB_TYPE:
-        case AES_256_ECB_TYPE:
-            return WOLFSSL_EVP_CIPH_ECB_MODE;
-    #endif
-    #ifndef NO_DES3
-        case DES_CBC_TYPE:
-        case DES_EDE3_CBC_TYPE:
-            return WOLFSSL_EVP_CIPH_CBC_MODE;
-        case DES_ECB_TYPE:
-        case DES_EDE3_ECB_TYPE:
-            return WOLFSSL_EVP_CIPH_ECB_MODE;
-    #endif
-    #ifndef NO_RC4
-        case ARC4_TYPE:
-            return EVP_CIPH_STREAM_CIPHER;
-    #endif
-        default:
-            return 0;
-        }
-}
-
-WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
-{
-  if (cipher == NULL) return 0;
-  return WOLFSSL_CIPHER_mode(cipher);
-}
-
-WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags)
-{
-    if (ctx != NULL) {
-        ctx->flags = flags;
-    }
-}
-
-WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher)
-{
-  if (cipher == NULL) return 0;
-  return WOLFSSL_CIPHER_mode(cipher);
-}
-
-WOLFSSL_API int  wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding)
-{
-  if (ctx == NULL) return BAD_FUNC_ARG;
-  if (padding) {
-      ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING;
-  }
-  else {
-      ctx->flags |=  WOLFSSL_EVP_CIPH_NO_PADDING;
-  }
-  return 1;
-}
-
-WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest)
-{
-    (void)digest;
-    /* nothing to do */
-    return 0;
-}
-
-
-/* Frees the WOLFSSL_EVP_PKEY_CTX passed in.
- *
- * return WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx)
-{
-    if (ctx == NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_CTX_free");
-    XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Creates a new WOLFSSL_EVP_PKEY_CTX structure.
- *
- * pkey  key structure to use with new WOLFSSL_EVP_PEKY_CTX
- * e     engine to use. It should be NULL at this time.
- *
- * return the new structure on success and NULL if failed.
- */
-WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e)
-{
-    WOLFSSL_EVP_PKEY_CTX* ctx;
-
-    if (pkey == NULL) return 0;
-    if (e != NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_CTX_new");
-
-    ctx = (WOLFSSL_EVP_PKEY_CTX*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY_CTX), NULL,
-            DYNAMIC_TYPE_PUBLIC_KEY);
-    if (ctx == NULL) return NULL;
-    XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX));
-    ctx->pkey = pkey;
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    ctx->padding = RSA_PKCS1_PADDING;
-#endif
-
-    return ctx;
-}
-
-
-/* Sets the type of RSA padding to use.
- *
- * ctx     structure to set padding in.
- * padding RSA padding type
- *
- * returns WOLFSSL_SUCCESS on success.
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding)
-{
-    if (ctx == NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_CTX_set_rsa_padding");
-    ctx->padding = padding;
-    return WOLFSSL_SUCCESS;
-}
-
-
-/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer.
- *
- * ctx    structure to decrypt with
- * out    buffer to hold the results
- * outlen initially holds size of out buffer and gets set to decrypt result size
- * in     buffer decrypt
- * inlen  length of in buffer
- *
- * returns WOLFSSL_SUCCESS on success.
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
-                     unsigned char *out, size_t *outlen,
-                     const unsigned char *in, size_t inlen)
-{
-    int len;
-
-    if (ctx == NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_decrypt");
-
-    (void)out;
-    (void)outlen;
-    (void)in;
-    (void)inlen;
-    (void)len;
-
-    switch (ctx->pkey->type) {
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    case EVP_PKEY_RSA:
-        len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out,
-              ctx->pkey->rsa, ctx->padding);
-        if (len < 0) break;
-        else {
-            *outlen = len;
-            return WOLFSSL_SUCCESS;
-        }
-#endif /* NO_RSA */
-
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Initialize a WOLFSSL_EVP_PKEY_CTX structure for decryption
- *
- * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with decryption
- *
- * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx)
-{
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_PKEY_decrypt_init");
-    switch (ctx->pkey->type) {
-    case EVP_PKEY_RSA:
-        ctx->op = EVP_PKEY_OP_DECRYPT;
-        return WOLFSSL_SUCCESS;
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data
- *
- * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with encryption
- * out    buffer to hold encrypted data
- * outlen length of out buffer
- * in     data to be encrypted
- * inlen  length of in buffer
- *
- * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
-                     unsigned char *out, size_t *outlen,
-                     const unsigned char *in, size_t inlen)
-{
-    int len;
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_PKEY_encrypt");
-    if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE;
-
-    (void)out;
-    (void)outlen;
-    (void)in;
-    (void)inlen;
-    (void)len;
-    switch (ctx->pkey->type) {
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    case EVP_PKEY_RSA:
-        len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out,
-                  ctx->pkey->rsa, ctx->padding);
-        if (len < 0)
-            break;
-        else {
-            *outlen = len;
-            return WOLFSSL_SUCCESS;
-        }
-#endif /* NO_RSA */
-
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Initialize a WOLFSSL_EVP_PKEY_CTX structure to encrypt data
- *
- * ctx    WOLFSSL_EVP_PKEY_CTX structure to use with encryption
- *
- * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx)
-{
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_PKEY_encrypt_init");
-
-    switch (ctx->pkey->type) {
-    case EVP_PKEY_RSA:
-        ctx->op = EVP_PKEY_OP_ENCRYPT;
-        return WOLFSSL_SUCCESS;
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Get the size in bits for WOLFSSL_EVP_PKEY key
- *
- * pkey WOLFSSL_EVP_PKEY structure to get key size of
- *
- * returns the size in bits of key on success
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey)
-{
-    int bytes;
-
-    if (pkey == NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_bits");
-    if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0;
-    return bytes*8;
-}
-
-
-/* Get the size in bytes for WOLFSSL_EVP_PKEY key
- *
- * pkey WOLFSSL_EVP_PKEY structure to get key size of
- *
- * returns the size of a key on success which is the maximum size of a
- *         signature
- */
-WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey)
-{
-    if (pkey == NULL) return 0;
-    WOLFSSL_ENTER("EVP_PKEY_size");
-
-    switch (pkey->type) {
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    case EVP_PKEY_RSA:
-        return (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(pkey->rsa));
-#endif /* NO_RSA */
-
-#ifdef HAVE_ECC
-    case EVP_PKEY_EC:
-        if (pkey->ecc == NULL || pkey->ecc->internal == NULL) {
-            WOLFSSL_MSG("No ECC key has been set");
-            break;
-        }
-        return wc_ecc_size((ecc_key*)(pkey->ecc->internal));
-#endif /* HAVE_ECC */
-
-    default:
-        break;
-    }
-    return 0;
-}
-
-
-/* Initialize structure for signing
- *
- * ctx  WOLFSSL_EVP_MD_CTX structure to initialize
- * type is the type of message digest to use
- *
- * returns WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type)
-{
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_SignInit");
-    return wolfSSL_EVP_DigestInit(ctx,type);
-}
-
-
-/* Update structure with data for signing
- *
- * ctx  WOLFSSL_EVP_MD_CTX structure to update
- * data buffer holding data to update with for sign
- * len  length of data buffer
- *
- * returns WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len)
-{
-    if (ctx == NULL) return 0;
-    WOLFSSL_ENTER("EVP_SignUpdate(");
-    return wolfSSL_EVP_DigestUpdate(ctx, data, len);
-}
-
-/* macro gaurd because currently only used with RSA */
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-/* Helper function for getting the NID value from md
- *
- * returns the NID value associated with md on success */
-static int md2nid(int md)
-{
-    const char * d;
-    d = (const char *)wolfSSL_EVP_get_md((const unsigned char)md);
-    if (XSTRNCMP(d, "SHA", 3) == 0) {
-        if (XSTRLEN(d) > 3) {
-            if (XSTRNCMP(d, "SHA256", 6) == 0) {
-                return NID_sha256;
-            }
-            if (XSTRNCMP(d, "SHA384", 6) == 0) {
-                return NID_sha384;
-            }
-            if (XSTRNCMP(d, "SHA512", 6) == 0) {
-                return NID_sha512;
-            }
-            WOLFSSL_MSG("Unknown SHA type");
-            return 0;
-        }
-        else {
-            return NID_sha1;
-        }
-    }
-    if (XSTRNCMP(d, "MD5", 3) == 0)
-        return NID_md5;
-    return 0;
-}
-#endif /* NO_RSA */
-
-/* Finalize structure for signing
- *
- * ctx    WOLFSSL_EVP_MD_CTX structure to finalize
- * sigret buffer to hold resulting signature
- * siglen length of sigret buffer
- * pkey   key to sign with
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
-WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret,
-                  unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey)
-{
-    unsigned int mdsize;
-    unsigned char md[WC_MAX_DIGEST_SIZE];
-    int ret;
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_SignFinal");
-
-    ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize);
-    if (ret <= 0) return ret;
-
-    (void)sigret;
-    (void)siglen;
-
-    switch (pkey->type) {
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    case EVP_PKEY_RSA: {
-        int nid = md2nid(ctx->macType);
-        if (nid < 0) break;
-        return wolfSSL_RSA_sign(nid, md, mdsize, sigret,
-                                siglen, pkey->rsa);
-    }
-#endif /* NO_RSA */
-
-    case EVP_PKEY_DSA:
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-
-/* Initialize structure for verifying signature
- *
- * ctx  WOLFSSL_EVP_MD_CTX structure to initialize
- * type is the type of message digest to use
- *
- * returns WOLFSSL_SUCCESS on success
- */
-WOLFSSL_API int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type)
-{
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_VerifyInit");
-    return wolfSSL_EVP_DigestInit(ctx,type);
-}
-
-
-/* Update structure for verifying signature
- *
- * ctx  WOLFSSL_EVP_MD_CTX structure to update
- * data buffer holding data to update with for verify
- * len  length of data buffer
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
-WOLFSSL_API int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len)
-{
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_VerifyUpdate");
-    return wolfSSL_EVP_DigestUpdate(ctx, data, len);
-}
-
-
-/* Finalize structure for verifying signature
- *
- * ctx    WOLFSSL_EVP_MD_CTX structure to finalize
- * sig    buffer holding signature
- * siglen length of sig buffer
- * pkey   key to verify with
- *
- * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
- */
-WOLFSSL_API int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
-        unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey)
-{
-    int ret;
-    unsigned char md[WC_MAX_DIGEST_SIZE];
-    unsigned int mdsize;
-
-    if (ctx == NULL) return WOLFSSL_FAILURE;
-    WOLFSSL_ENTER("EVP_VerifyFinal");
-    ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize);
-    if (ret <= 0) return ret;
-
-    (void)sig;
-    (void)siglen;
-
-    switch (pkey->type) {
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
-    case EVP_PKEY_RSA: {
-        int nid = md2nid(ctx->macType);
-        if (nid < 0) break;
-        return wolfSSL_RSA_verify(nid, md, mdsize, sig,
-                (unsigned int)siglen, pkey->rsa);
-    }
-#endif /* NO_RSA */
-
-    case EVP_PKEY_DSA:
-    case EVP_PKEY_EC:
-        WOLFSSL_MSG("not implemented");
-        FALL_THROUGH;
-    default:
-        break;
-    }
-    return WOLFSSL_FAILURE;
-}
-
-WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher)
-{
-    (void)cipher;
-    /* nothing to do */
-    return 0;
-}
-
-
-WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e,
-                                          const unsigned char* key, int keylen)
-{
-    WOLFSSL_EVP_PKEY* pkey;
-
-    (void)e;
-
-    if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0))
-        return NULL;
-
-    pkey = wolfSSL_PKEY_new();
-    if (pkey != NULL) {
-        pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-        if (pkey->pkey.ptr == NULL && keylen > 0) {
-            wolfSSL_EVP_PKEY_free(pkey);
-            pkey = NULL;
-        }
-        else {
-            XMEMCPY(pkey->pkey.ptr, key, keylen);
-            pkey->pkey_sz = keylen;
-            pkey->type = pkey->save_type = type;
-        }
-    }
-
-    return pkey;
-}
-
-
-const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey,
-                                                size_t* len)
-{
-    if (pkey == NULL || len == NULL)
-        return NULL;
-
-    *len = (size_t)pkey->pkey_sz;
-
-    return (const unsigned char*)pkey->pkey.ptr;
-}
-
-
-int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx,
-                               WOLFSSL_EVP_PKEY_CTX **pctx,
-                               const WOLFSSL_EVP_MD *type,
-                               WOLFSSL_ENGINE *e,
-                               WOLFSSL_EVP_PKEY *pkey)
-{
-    int hashType;
-    const unsigned char* key;
-    size_t keySz;
-
-    /* Unused parameters */
-    (void)pctx;
-    (void)e;
-
-    WOLFSSL_ENTER("EVP_DigestSignInit");
-
-    if (ctx == NULL || type == NULL || pkey == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* compile-time validation of ASYNC_CTX_SIZE */
-    typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ?
-                                                                    1 : -1];
-    (void)sizeof(async_test);
-#endif
-
-    if (XSTRNCMP(type, "SHA256", 6) == 0) {
-         hashType = WC_SHA256;
-    }
-#ifdef WOLFSSL_SHA224
-    else if (XSTRNCMP(type, "SHA224", 6) == 0) {
-         hashType = WC_SHA224;
-    }
-#endif
-#ifdef WOLFSSL_SHA384
-    else if (XSTRNCMP(type, "SHA384", 6) == 0) {
-         hashType = WC_SHA384;
-    }
-#endif
-#ifdef WOLFSSL_SHA512
-    else if (XSTRNCMP(type, "SHA512", 6) == 0) {
-         hashType = WC_SHA512;
-    }
-#endif
-#ifndef NO_MD5
-    else if (XSTRNCMP(type, "MD5", 3) == 0) {
-        hashType = WC_MD5;
-    }
-#endif
-#ifndef NO_SHA
-    /* has to be last since would pick or 224, 256, 384, or 512 too */
-    else if (XSTRNCMP(type, "SHA", 3) == 0) {
-         hashType = WC_SHA;
-    }
-#endif /* NO_SHA */
-    else
-         return BAD_FUNC_ARG;
-
-    key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz);
-
-    if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0)
-        return WOLFSSL_FAILURE;
-
-    if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0)
-        return WOLFSSL_FAILURE;
-
-    ctx->macType = NID_hmac & 0xFF;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx,
-                                 const void *d, unsigned int cnt)
-{
-    WOLFSSL_ENTER("EVP_DigestSignFinal");
-
-    if (ctx->macType != (NID_hmac & 0xFF))
-        return WOLFSSL_FAILURE;
-
-    if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0)
-        return WOLFSSL_FAILURE;
-
-    return WOLFSSL_SUCCESS;
-}
-
-
-int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx,
-                                unsigned char *sig, size_t *siglen)
-{
-    unsigned char digest[WC_MAX_DIGEST_SIZE];
-    Hmac hmacCopy;
-    int hashLen, ret;
-
-    WOLFSSL_ENTER("EVP_DigestSignFinal");
-
-    if (ctx == NULL || siglen == NULL)
-        return WOLFSSL_FAILURE;
-
-    if (ctx->macType != (NID_hmac & 0xFF))
-        return WOLFSSL_FAILURE;
-
-    switch (ctx->hash.hmac.macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            hashLen = WC_MD5_DIGEST_SIZE;
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            hashLen = WC_SHA_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            hashLen = WC_SHA224_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            hashLen = WC_SHA256_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA512
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            hashLen = WC_SHA384_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA384 */
-        case WC_SHA512:
-            hashLen = WC_SHA512_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            hashLen = BLAKE2B_OUTBYTES;
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-        default:
-            return 0;
-    }
-
-    if (sig == NULL) {
-        *siglen = hashLen;
-        return WOLFSSL_SUCCESS;
-    }
-
-    if ((int)(*siglen) > hashLen)
-        *siglen = hashLen;
-
-    XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy));
-    ret = wc_HmacFinal(&hmacCopy, digest) == 0;
-    if (ret == 1)
-        XMEMCPY(sig, digest, *siglen);
-
-    ForceZero(&hmacCopy, sizeof(hmacCopy));
-    ForceZero(digest, sizeof(digest));
-    return ret;
-}
-#endif /* WOLFSSL_EVP_INCLUDED */
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_PWDBASED) && !defined(NO_SHA)
-WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
-                                               const unsigned char *salt,
-                                               int saltlen, int iter,
-                                               int keylen, unsigned char *out)
-{
-    const char *nostring = "";
-    int ret = 0;
-
-    if (pass == NULL) {
-        passlen = 0;
-        pass = nostring;
-    } else if (passlen == -1) {
-        passlen = (int)XSTRLEN(pass);
-    }
-
-    ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen,
-                    iter, keylen, WC_SHA);
-    if (ret == 0)
-        return WOLFSSL_SUCCESS;
-    else
-        return WOLFSSL_FAILURE;
-}
-#endif /* OPENSSL_EXTRA && !NO_PWDBASED !NO_SHA*/
-
--- a/wolfcrypt/src/fe_low_mem.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,612 +0,0 @@
-/* fe_low_mem.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* Based from Daniel Beer's public domain work. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519)
-#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) /* use slower code that takes less memory */
-
-#include <wolfssl/wolfcrypt/fe_operations.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-void fprime_copy(byte *x, const byte *a)
-{
-    int i;
-    for (i = 0; i < F25519_SIZE; i++)
-        x[i] = a[i];
-}
-
-
-void lm_copy(byte* x, const byte* a)
-{
-    int i;
-    for (i = 0; i < F25519_SIZE; i++)
-        x[i] = a[i];
-}
-
-#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \
-    (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) &&      \
-    !defined(FREESCALE_LTC_ECC)
-    /* to be Complementary to fe_low_mem.c */
-#else
-void fe_init()
-{
-}
-#endif
-
-#ifdef CURVE25519_SMALL
-
-/* Double an X-coordinate */
-static void xc_double(byte *x3, byte *z3,
-		      const byte *x1, const byte *z1)
-{
-	/* Explicit formulas database: dbl-1987-m
-	 *
-	 * source 1987 Montgomery "Speeding the Pollard and elliptic
-	 *   curve methods of factorization", page 261, fourth display
-	 * compute X3 = (X1^2-Z1^2)^2
-	 * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2)
-	 */
-	byte x1sq[F25519_SIZE];
-	byte z1sq[F25519_SIZE];
-	byte x1z1[F25519_SIZE];
-	byte a[F25519_SIZE];
-
-	fe_mul__distinct(x1sq, x1, x1);
-	fe_mul__distinct(z1sq, z1, z1);
-	fe_mul__distinct(x1z1, x1, z1);
-
-	lm_sub(a, x1sq, z1sq);
-	fe_mul__distinct(x3, a, a);
-
-	fe_mul_c(a, x1z1, 486662);
-	lm_add(a, x1sq, a);
-	lm_add(a, z1sq, a);
-	fe_mul__distinct(x1sq, x1z1, a);
-	fe_mul_c(z3, x1sq, 4);
-}
-
-
-/* Differential addition */
-static void xc_diffadd(byte *x5, byte *z5,
-		       const byte *x1, const byte *z1,
-		       const byte *x2, const byte *z2,
-		       const byte *x3, const byte *z3)
-{
-	/* Explicit formulas database: dbl-1987-m3
-	 *
-	 * source 1987 Montgomery "Speeding the Pollard and elliptic curve
-	 *   methods of factorization", page 261, fifth display, plus
-	 *   common-subexpression elimination
-	 * compute A = X2+Z2
-	 * compute B = X2-Z2
-	 * compute C = X3+Z3
-	 * compute D = X3-Z3
-	 * compute DA = D A
-	 * compute CB = C B
-	 * compute X5 = Z1(DA+CB)^2
-	 * compute Z5 = X1(DA-CB)^2
-	 */
-	byte da[F25519_SIZE];
-	byte cb[F25519_SIZE];
-	byte a[F25519_SIZE];
-	byte b[F25519_SIZE];
-
-	lm_add(a, x2, z2);
-	lm_sub(b, x3, z3); /* D */
-	fe_mul__distinct(da, a, b);
-
-	lm_sub(b, x2, z2);
-	lm_add(a, x3, z3); /* C */
-	fe_mul__distinct(cb, a, b);
-
-	lm_add(a, da, cb);
-	fe_mul__distinct(b, a, a);
-	fe_mul__distinct(x5, z1, b);
-
-	lm_sub(a, da, cb);
-	fe_mul__distinct(b, a, a);
-	fe_mul__distinct(z5, x1, b);
-}
-
-#ifndef FREESCALE_LTC_ECC
-int curve25519(byte *result, byte *e, byte *q)
-{
-	/* Current point: P_m */
-	byte xm[F25519_SIZE];
-	byte zm[F25519_SIZE] = {1};
-
-	/* Predecessor: P_(m-1) */
-	byte xm1[F25519_SIZE] = {1};
-	byte zm1[F25519_SIZE] = {0};
-
-	int i;
-
-	/* Note: bit 254 is assumed to be 1 */
-	lm_copy(xm, q);
-
-	for (i = 253; i >= 0; i--) {
-		const int bit = (e[i >> 3] >> (i & 7)) & 1;
-		byte xms[F25519_SIZE];
-		byte zms[F25519_SIZE];
-
-		/* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */
-		xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1);
-		xc_double(xm, zm, xm, zm);
-
-		/* Compute P_(2m+1) */
-		xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one);
-
-		/* Select:
-		 *   bit = 1 --> (P_(2m+1), P_(2m))
-		 *   bit = 0 --> (P_(2m), P_(2m-1))
-		 */
-		fe_select(xm1, xm1, xm, bit);
-		fe_select(zm1, zm1, zm, bit);
-		fe_select(xm, xm, xms, bit);
-		fe_select(zm, zm, zms, bit);
-	}
-
-	/* Freeze out of projective coordinates */
-	fe_inv__distinct(zm1, zm);
-	fe_mul__distinct(result, zm1, xm);
-	fe_normalize(result);
-    return 0;
-}
-#endif /* !FREESCALE_LTC_ECC */
-#endif /* CURVE25519_SMALL */
-
-
-static void raw_add(byte *x, const byte *p)
-{
-	word16 c = 0;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += ((word16)x[i]) + ((word16)p[i]);
-		x[i] = (byte)c;
-		c >>= 8;
-	}
-}
-
-
-static void raw_try_sub(byte *x, const byte *p)
-{
-	byte minusp[F25519_SIZE];
-	word16 c = 0;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c = ((word16)x[i]) - ((word16)p[i]) - c;
-		minusp[i] = (byte)c;
-		c = (c >> 8) & 1;
-	}
-
-	fprime_select(x, minusp, x, (byte)c);
-}
-
-
-static int prime_msb(const byte *p)
-{
-    int i;
-    byte x;
-    int shift = 1;
-    int z     = F25519_SIZE - 1;
-
-   /*
-       Test for any hot bits.
-       As soon as one instance is encountered set shift to 0.
-    */
-	for (i = F25519_SIZE - 1; i >= 0; i--) {
-        shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1);
-        z -= shift;
-    }
-	x = p[z];
-	z <<= 3;
-    shift = 1;
-    for (i = 0; i < 8; i++) {
-        shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1);
-        z += shift;
-    }
-
-	return z - 1;
-}
-
-
-void fprime_select(byte *dst, const byte *zero, const byte *one, byte condition)
-{
-	const byte mask = -condition;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++)
-		dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
-}
-
-
-void fprime_add(byte *r, const byte *a, const byte *modulus)
-{
-	raw_add(r, a);
-	raw_try_sub(r, modulus);
-}
-
-
-void fprime_sub(byte *r, const byte *a, const byte *modulus)
-{
-	raw_add(r, modulus);
-	raw_try_sub(r, a);
-	raw_try_sub(r, modulus);
-}
-
-
-void fprime_mul(byte *r, const byte *a, const byte *b,
-		const byte *modulus)
-{
-	word16 c = 0;
-	int i,j;
-
-	XMEMSET(r, 0, F25519_SIZE);
-
-	for (i = prime_msb(modulus); i >= 0; i--) {
-		const byte bit = (b[i >> 3] >> (i & 7)) & 1;
-		byte plusa[F25519_SIZE];
-
-	    for (j = 0; j < F25519_SIZE; j++) {
-		    c |= ((word16)r[j]) << 1;
-		    r[j] = (byte)c;
-		    c >>= 8;
-	    }
-		raw_try_sub(r, modulus);
-
-		fprime_copy(plusa, r);
-		fprime_add(plusa, a, modulus);
-
-		fprime_select(r, r, plusa, bit);
-	}
-}
-
-
-void fe_load(byte *x, word32 c)
-{
-	word32 i;
-
-	for (i = 0; i < sizeof(c); i++) {
-		x[i] = c;
-		c >>= 8;
-	}
-
-	for (; i < F25519_SIZE; i++)
-		x[i] = 0;
-}
-
-
-void fe_normalize(byte *x)
-{
-	byte minusp[F25519_SIZE];
-	word16 c;
-	int i;
-
-	/* Reduce using 2^255 = 19 mod p */
-	c = (x[31] >> 7) * 19;
-	x[31] &= 127;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += x[i];
-		x[i] = (byte)c;
-		c >>= 8;
-	}
-
-	/* The number is now less than 2^255 + 18, and therefore less than
-	 * 2p. Try subtracting p, and conditionally load the subtracted
-	 * value if underflow did not occur.
-	 */
-	c = 19;
-
-	for (i = 0; i + 1 < F25519_SIZE; i++) {
-		c += x[i];
-		minusp[i] = (byte)c;
-		c >>= 8;
-	}
-
-	c += ((word16)x[i]) - 128;
-	minusp[31] = (byte)c;
-
-	/* Load x-p if no underflow */
-	fe_select(x, minusp, x, (c >> 15) & 1);
-}
-
-
-void fe_select(byte *dst,
-		   const byte *zero, const byte *one,
-		   byte condition)
-{
-	const byte mask = -condition;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++)
-		dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
-}
-
-
-void lm_add(byte* r, const byte* a, const byte* b)
-{
-	word16 c = 0;
-	int i;
-
-	/* Add */
-	for (i = 0; i < F25519_SIZE; i++) {
-		c >>= 8;
-		c += ((word16)a[i]) + ((word16)b[i]);
-		r[i] = (byte)c;
-	}
-
-	/* Reduce with 2^255 = 19 mod p */
-	r[31] &= 127;
-	c = (c >> 7) * 19;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += r[i];
-		r[i] = (byte)c;
-		c >>= 8;
-	}
-}
-
-
-void lm_sub(byte* r, const byte* a, const byte* b)
-{
-	word32 c = 0;
-	int i;
-
-	/* Calculate a + 2p - b, to avoid underflow */
-	c = 218;
-	for (i = 0; i + 1 < F25519_SIZE; i++) {
-		c += 65280 + ((word32)a[i]) - ((word32)b[i]);
-		r[i] = c;
-		c >>= 8;
-	}
-
-	c += ((word32)a[31]) - ((word32)b[31]);
-	r[31] = c & 127;
-	c = (c >> 7) * 19;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += r[i];
-		r[i] = c;
-		c >>= 8;
-	}
-}
-
-
-void lm_neg(byte* r, const byte* a)
-{
-	word32 c = 0;
-	int i;
-
-	/* Calculate 2p - a, to avoid underflow */
-	c = 218;
-	for (i = 0; i + 1 < F25519_SIZE; i++) {
-		c += 65280 - ((word32)a[i]);
-		r[i] = c;
-		c >>= 8;
-	}
-
-	c -= ((word32)a[31]);
-	r[31] = c & 127;
-	c = (c >> 7) * 19;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += r[i];
-		r[i] = c;
-		c >>= 8;
-	}
-}
-
-
-void fe_mul__distinct(byte *r, const byte *a, const byte *b)
-{
-	word32 c = 0;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		int j;
-
-		c >>= 8;
-		for (j = 0; j <= i; j++)
-			c += ((word32)a[j]) * ((word32)b[i - j]);
-
-		for (; j < F25519_SIZE; j++)
-			c += ((word32)a[j]) *
-			     ((word32)b[i + F25519_SIZE - j]) * 38;
-
-		r[i] = c;
-	}
-
-	r[31] &= 127;
-	c = (c >> 7) * 19;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += r[i];
-		r[i] = c;
-		c >>= 8;
-	}
-}
-
-
-void lm_mul(byte *r, const byte* a, const byte *b)
-{
-	byte tmp[F25519_SIZE];
-
-	fe_mul__distinct(tmp, a, b);
-	lm_copy(r, tmp);
-}
-
-
-void fe_mul_c(byte *r, const byte *a, word32 b)
-{
-	word32 c = 0;
-	int i;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c >>= 8;
-		c += b * ((word32)a[i]);
-		r[i] = c;
-	}
-
-	r[31] &= 127;
-	c >>= 7;
-	c *= 19;
-
-	for (i = 0; i < F25519_SIZE; i++) {
-		c += r[i];
-		r[i] = c;
-		c >>= 8;
-	}
-}
-
-
-void fe_inv__distinct(byte *r, const byte *x)
-{
-	byte s[F25519_SIZE];
-	int i;
-
-	/* This is a prime field, so by Fermat's little theorem:
-	 *
-	 *     x^(p-1) = 1 mod p
-	 *
-	 * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative
-	 * inverse.
-	 *
-	 * This is a 255-bit binary number with the digits:
-	 *
-	 *     11111111... 01011
-	 *
-	 * We compute the result by the usual binary chain, but
-	 * alternate between keeping the accumulator in r and s, so as
-	 * to avoid copying temporaries.
-	 */
-
-	/* 1 1 */
-	fe_mul__distinct(s, x, x);
-	fe_mul__distinct(r, s, x);
-
-	/* 1 x 248 */
-	for (i = 0; i < 248; i++) {
-		fe_mul__distinct(s, r, r);
-		fe_mul__distinct(r, s, x);
-	}
-
-	/* 0 */
-	fe_mul__distinct(s, r, r);
-
-	/* 1 */
-	fe_mul__distinct(r, s, s);
-	fe_mul__distinct(s, r, x);
-
-	/* 0 */
-	fe_mul__distinct(r, s, s);
-
-	/* 1 */
-	fe_mul__distinct(s, r, r);
-	fe_mul__distinct(r, s, x);
-
-	/* 1 */
-	fe_mul__distinct(s, r, r);
-	fe_mul__distinct(r, s, x);
-}
-
-
-void lm_invert(byte *r, const byte *x)
-{
-	byte tmp[F25519_SIZE];
-
-	fe_inv__distinct(tmp, x);
-	lm_copy(r, tmp);
-}
-
-
-/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary
- * storage.
- */
-static void exp2523(byte *r, const byte *x, byte *s)
-{
-	int i;
-
-	/* This number is a 252-bit number with the binary expansion:
-	 *
-	 *     111111... 01
-	 */
-
-	/* 1 1 */
-	fe_mul__distinct(r, x, x);
-	fe_mul__distinct(s, r, x);
-
-	/* 1 x 248 */
-	for (i = 0; i < 248; i++) {
-		fe_mul__distinct(r, s, s);
-		fe_mul__distinct(s, r, x);
-	}
-
-	/* 0 */
-	fe_mul__distinct(r, s, s);
-
-	/* 1 */
-	fe_mul__distinct(s, r, r);
-	fe_mul__distinct(r, s, x);
-}
-
-
-void fe_sqrt(byte *r, const byte *a)
-{
-	byte v[F25519_SIZE];
-	byte i[F25519_SIZE];
-	byte x[F25519_SIZE];
-	byte y[F25519_SIZE];
-
-	/* v = (2a)^((p-5)/8) [x = 2a] */
-	fe_mul_c(x, a, 2);
-	exp2523(v, x, y);
-
-	/* i = 2av^2 - 1 */
-	fe_mul__distinct(y, v, v);
-	fe_mul__distinct(i, x, y);
-	fe_load(y, 1);
-	lm_sub(i, i, y);
-
-	/* r = avi */
-	fe_mul__distinct(x, v, a);
-	fe_mul__distinct(r, x, i);
-}
-
-#endif /* CURVE25519_SMALL || ED25519_SMALL */
-#endif /* HAVE_CURVE25519 || HAVE_ED25519 */
-
--- a/wolfcrypt/src/fe_operations.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1437 +0,0 @@
-/* fe_operations.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519)
-#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) /* run when not defined to use small memory math */
-
-#include <wolfssl/wolfcrypt/fe_operations.h>
-#include <stdint.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef CURVED25519_X64
-#include "fe_x25519_x64.i"
-#elif defined(CURVED25519_128BIT)
-#include "fe_x25519_128.i"
-#else
-
-#if defined(HAVE_CURVE25519) || \
-    (defined(HAVE_ED25519) && !defined(ED25519_SMALL))
-/*
-fe means field element.
-Here the field is \Z/(2^255-19).
-An element t, entries t[0]...t[9], represents the integer
-t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
-Bounds on each t[i] vary depending on context.
-*/
-
-uint64_t load_3(const unsigned char *in)
-{
-  uint64_t result;
-  result = (uint64_t) in[0];
-  result |= ((uint64_t) in[1]) << 8;
-  result |= ((uint64_t) in[2]) << 16;
-  return result;
-}
-
-
-uint64_t load_4(const unsigned char *in)
-{
-  uint64_t result;
-  result = (uint64_t) in[0];
-  result |= ((uint64_t) in[1]) << 8;
-  result |= ((uint64_t) in[2]) << 16;
-  result |= ((uint64_t) in[3]) << 24;
-  return result;
-}
-#endif
-
-/*
-h = 1
-*/
-
-void fe_1(fe h)
-{
-  h[0] = 1;
-  h[1] = 0;
-  h[2] = 0;
-  h[3] = 0;
-  h[4] = 0;
-  h[5] = 0;
-  h[6] = 0;
-  h[7] = 0;
-  h[8] = 0;
-  h[9] = 0;
-}
-
-
-/*
-h = 0
-*/
-
-void fe_0(fe h)
-{
-  h[0] = 0;
-  h[1] = 0;
-  h[2] = 0;
-  h[3] = 0;
-  h[4] = 0;
-  h[5] = 0;
-  h[6] = 0;
-  h[7] = 0;
-  h[8] = 0;
-  h[9] = 0;
-}
-
-
-#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \
-     (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \
-    !defined(FREESCALE_LTC_ECC)
-/* to be Complementary to fe_low_mem.c */
-void fe_init()
-{
-}
-#endif
-
-#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \
-    !defined(FREESCALE_LTC_ECC)
-int curve25519(byte* q, byte* n, byte* p)
-{
-#if 0
-  unsigned char e[32];
-#endif
-  fe x1;
-  fe x2;
-  fe z2;
-  fe x3;
-  fe z3;
-  fe tmp0;
-  fe tmp1;
-  int pos;
-  unsigned int swap;
-  unsigned int b;
-
-  /* Clamp already done during key generation and import */
-#if 0
-  {
-    unsigned int i;
-    for (i = 0;i < 32;++i) e[i] = n[i];
-    e[0] &= 248;
-    e[31] &= 127;
-    e[31] |= 64;
-  }
-#endif
-
-  fe_frombytes(x1,p);
-  fe_1(x2);
-  fe_0(z2);
-  fe_copy(x3,x1);
-  fe_1(z3);
-
-  swap = 0;
-  for (pos = 254;pos >= 0;--pos) {
-#if 0
-    b = e[pos / 8] >> (pos & 7);
-#else
-    b = n[pos / 8] >> (pos & 7);
-#endif
-    b &= 1;
-    swap ^= b;
-    fe_cswap(x2,x3,swap);
-    fe_cswap(z2,z3,swap);
-    swap = b;
-
-    /* montgomery */
-	fe_sub(tmp0,x3,z3);
-	fe_sub(tmp1,x2,z2);
-	fe_add(x2,x2,z2);
-	fe_add(z2,x3,z3);
-	fe_mul(z3,tmp0,x2);
-	fe_mul(z2,z2,tmp1);
-	fe_sq(tmp0,tmp1);
-	fe_sq(tmp1,x2);
-	fe_add(x3,z3,z2);
-	fe_sub(z2,z3,z2);
-	fe_mul(x2,tmp1,tmp0);
-	fe_sub(tmp1,tmp1,tmp0);
-	fe_sq(z2,z2);
-	fe_mul121666(z3,tmp1);
-	fe_sq(x3,x3);
-	fe_add(tmp0,tmp0,z3);
-	fe_mul(z3,x1,z2);
-	fe_mul(z2,tmp1,tmp0);
-  }
-  fe_cswap(x2,x3,swap);
-  fe_cswap(z2,z3,swap);
-
-  fe_invert(z2,z2);
-  fe_mul(x2,x2,z2);
-  fe_tobytes(q,x2);
-
-  return 0;
-}
-#endif /* HAVE_CURVE25519 && !CURVE25519_SMALL && !FREESCALE_LTC_ECC */
-
-
-/*
-h = f * f
-Can overlap h with f.
-
-Preconditions:
-   |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-
-Postconditions:
-   |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
-*/
-
-/*
-See fe_mul.c for discussion of implementation strategy.
-*/
-
-void fe_sq(fe h,const fe f)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t f0_2 = 2 * f0;
-  int32_t f1_2 = 2 * f1;
-  int32_t f2_2 = 2 * f2;
-  int32_t f3_2 = 2 * f3;
-  int32_t f4_2 = 2 * f4;
-  int32_t f5_2 = 2 * f5;
-  int32_t f6_2 = 2 * f6;
-  int32_t f7_2 = 2 * f7;
-  int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
-  int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
-  int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
-  int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
-  int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
-  int64_t f0f0    = f0   * (int64_t) f0;
-  int64_t f0f1_2  = f0_2 * (int64_t) f1;
-  int64_t f0f2_2  = f0_2 * (int64_t) f2;
-  int64_t f0f3_2  = f0_2 * (int64_t) f3;
-  int64_t f0f4_2  = f0_2 * (int64_t) f4;
-  int64_t f0f5_2  = f0_2 * (int64_t) f5;
-  int64_t f0f6_2  = f0_2 * (int64_t) f6;
-  int64_t f0f7_2  = f0_2 * (int64_t) f7;
-  int64_t f0f8_2  = f0_2 * (int64_t) f8;
-  int64_t f0f9_2  = f0_2 * (int64_t) f9;
-  int64_t f1f1_2  = f1_2 * (int64_t) f1;
-  int64_t f1f2_2  = f1_2 * (int64_t) f2;
-  int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
-  int64_t f1f4_2  = f1_2 * (int64_t) f4;
-  int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
-  int64_t f1f6_2  = f1_2 * (int64_t) f6;
-  int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
-  int64_t f1f8_2  = f1_2 * (int64_t) f8;
-  int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
-  int64_t f2f2    = f2   * (int64_t) f2;
-  int64_t f2f3_2  = f2_2 * (int64_t) f3;
-  int64_t f2f4_2  = f2_2 * (int64_t) f4;
-  int64_t f2f5_2  = f2_2 * (int64_t) f5;
-  int64_t f2f6_2  = f2_2 * (int64_t) f6;
-  int64_t f2f7_2  = f2_2 * (int64_t) f7;
-  int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
-  int64_t f2f9_38 = f2   * (int64_t) f9_38;
-  int64_t f3f3_2  = f3_2 * (int64_t) f3;
-  int64_t f3f4_2  = f3_2 * (int64_t) f4;
-  int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
-  int64_t f3f6_2  = f3_2 * (int64_t) f6;
-  int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
-  int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
-  int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
-  int64_t f4f4    = f4   * (int64_t) f4;
-  int64_t f4f5_2  = f4_2 * (int64_t) f5;
-  int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
-  int64_t f4f7_38 = f4   * (int64_t) f7_38;
-  int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
-  int64_t f4f9_38 = f4   * (int64_t) f9_38;
-  int64_t f5f5_38 = f5   * (int64_t) f5_38;
-  int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
-  int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
-  int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
-  int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
-  int64_t f6f6_19 = f6   * (int64_t) f6_19;
-  int64_t f6f7_38 = f6   * (int64_t) f7_38;
-  int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
-  int64_t f6f9_38 = f6   * (int64_t) f9_38;
-  int64_t f7f7_38 = f7   * (int64_t) f7_38;
-  int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
-  int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
-  int64_t f8f8_19 = f8   * (int64_t) f8_19;
-  int64_t f8f9_38 = f8   * (int64_t) f9_38;
-  int64_t f9f9_38 = f9   * (int64_t) f9_38;
-  int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
-  int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
-  int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
-  int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
-  int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
-  int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
-  int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
-  int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
-  int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
-  int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
-  int64_t carry0;
-  int64_t carry1;
-  int64_t carry2;
-  int64_t carry3;
-  int64_t carry4;
-  int64_t carry5;
-  int64_t carry6;
-  int64_t carry7;
-  int64_t carry8;
-  int64_t carry9;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
-
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
-
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-
-  h[0] = (int32_t)h0;
-  h[1] = (int32_t)h1;
-  h[2] = (int32_t)h2;
-  h[3] = (int32_t)h3;
-  h[4] = (int32_t)h4;
-  h[5] = (int32_t)h5;
-  h[6] = (int32_t)h6;
-  h[7] = (int32_t)h7;
-  h[8] = (int32_t)h8;
-  h[9] = (int32_t)h9;
-}
-
-
-/*
-h = f + g
-Can overlap h with f or g.
-
-Preconditions:
-   |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-   |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-
-Postconditions:
-   |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-*/
-
-void fe_add(fe h,const fe f,const fe g)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t g0 = g[0];
-  int32_t g1 = g[1];
-  int32_t g2 = g[2];
-  int32_t g3 = g[3];
-  int32_t g4 = g[4];
-  int32_t g5 = g[5];
-  int32_t g6 = g[6];
-  int32_t g7 = g[7];
-  int32_t g8 = g[8];
-  int32_t g9 = g[9];
-  int32_t h0 = f0 + g0;
-  int32_t h1 = f1 + g1;
-  int32_t h2 = f2 + g2;
-  int32_t h3 = f3 + g3;
-  int32_t h4 = f4 + g4;
-  int32_t h5 = f5 + g5;
-  int32_t h6 = f6 + g6;
-  int32_t h7 = f7 + g7;
-  int32_t h8 = f8 + g8;
-  int32_t h9 = f9 + g9;
-  h[0] = h0;
-  h[1] = h1;
-  h[2] = h2;
-  h[3] = h3;
-  h[4] = h4;
-  h[5] = h5;
-  h[6] = h6;
-  h[7] = h7;
-  h[8] = h8;
-  h[9] = h9;
-}
-
-
-/*
-Preconditions:
-  |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-
-Write p=2^255-19; q=floor(h/p).
-Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
-
-Proof:
-  Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
-  Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
-
-  Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
-  Then 0<y<1.
-
-  Write r=h-pq.
-  Have 0<=r<=p-1=2^255-20.
-  Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
-
-  Write x=r+19(2^-255)r+y.
-  Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
-
-  Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
-  so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
-*/
-
-void fe_tobytes(unsigned char *s,const fe h)
-{
-  int32_t h0 = h[0];
-  int32_t h1 = h[1];
-  int32_t h2 = h[2];
-  int32_t h3 = h[3];
-  int32_t h4 = h[4];
-  int32_t h5 = h[5];
-  int32_t h6 = h[6];
-  int32_t h7 = h[7];
-  int32_t h8 = h[8];
-  int32_t h9 = h[9];
-  int32_t q;
-  int32_t carry0;
-  int32_t carry1;
-  int32_t carry2;
-  int32_t carry3;
-  int32_t carry4;
-  int32_t carry5;
-  int32_t carry6;
-  int32_t carry7;
-  int32_t carry8;
-  int32_t carry9;
-
-  q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
-  q = (h0 + q) >> 26;
-  q = (h1 + q) >> 25;
-  q = (h2 + q) >> 26;
-  q = (h3 + q) >> 25;
-  q = (h4 + q) >> 26;
-  q = (h5 + q) >> 25;
-  q = (h6 + q) >> 26;
-  q = (h7 + q) >> 25;
-  q = (h8 + q) >> 26;
-  q = (h9 + q) >> 25;
-
-  /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
-  h0 += 19 * q;
-  /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
-
-  carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
-  carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
-  carry9 = h9 >> 25;               h9 -= carry9 << 25;
-                  /* h10 = carry9 */
-
-  /*
-  Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
-  Have h0+...+2^230 h9 between 0 and 2^255-1;
-  evidently 2^255 h10-2^255 q = 0.
-  Goal: Output h0+...+2^230 h9.
-  */
-
-  s[0] = (byte)(h0 >> 0);
-  s[1] = (byte)(h0 >> 8);
-  s[2] = (byte)(h0 >> 16);
-  s[3] = (byte)((h0 >> 24) | (h1 << 2));
-  s[4] = (byte)(h1 >> 6);
-  s[5] = (byte)(h1 >> 14);
-  s[6] = (byte)((h1 >> 22) | (h2 << 3));
-  s[7] = (byte)(h2 >> 5);
-  s[8] = (byte)(h2 >> 13);
-  s[9] = (byte)((h2 >> 21) | (h3 << 5));
-  s[10] = (byte)(h3 >> 3);
-  s[11] = (byte)(h3 >> 11);
-  s[12] = (byte)((h3 >> 19) | (h4 << 6));
-  s[13] = (byte)(h4 >> 2);
-  s[14] = (byte)(h4 >> 10);
-  s[15] = (byte)(h4 >> 18);
-  s[16] = (byte)(h5 >> 0);
-  s[17] = (byte)(h5 >> 8);
-  s[18] = (byte)(h5 >> 16);
-  s[19] = (byte)((h5 >> 24) | (h6 << 1));
-  s[20] = (byte)(h6 >> 7);
-  s[21] = (byte)(h6 >> 15);
-  s[22] = (byte)((h6 >> 23) | (h7 << 3));
-  s[23] = (byte)(h7 >> 5);
-  s[24] = (byte)(h7 >> 13);
-  s[25] = (byte)((h7 >> 21) | (h8 << 4));
-  s[26] = (byte)(h8 >> 4);
-  s[27] = (byte)(h8 >> 12);
-  s[28] = (byte)((h8 >> 20) | (h9 << 6));
-  s[29] = (byte)(h9 >> 2);
-  s[30] = (byte)(h9 >> 10);
-  s[31] = (byte)(h9 >> 18);
-}
-
-
-/*
-h = f - g
-Can overlap h with f or g.
-
-Preconditions:
-   |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-   |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-
-Postconditions:
-   |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-*/
-
-void fe_sub(fe h,const fe f,const fe g)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t g0 = g[0];
-  int32_t g1 = g[1];
-  int32_t g2 = g[2];
-  int32_t g3 = g[3];
-  int32_t g4 = g[4];
-  int32_t g5 = g[5];
-  int32_t g6 = g[6];
-  int32_t g7 = g[7];
-  int32_t g8 = g[8];
-  int32_t g9 = g[9];
-  int32_t h0 = f0 - g0;
-  int32_t h1 = f1 - g1;
-  int32_t h2 = f2 - g2;
-  int32_t h3 = f3 - g3;
-  int32_t h4 = f4 - g4;
-  int32_t h5 = f5 - g5;
-  int32_t h6 = f6 - g6;
-  int32_t h7 = f7 - g7;
-  int32_t h8 = f8 - g8;
-  int32_t h9 = f9 - g9;
-  h[0] = h0;
-  h[1] = h1;
-  h[2] = h2;
-  h[3] = h3;
-  h[4] = h4;
-  h[5] = h5;
-  h[6] = h6;
-  h[7] = h7;
-  h[8] = h8;
-  h[9] = h9;
-}
-
-
-#if defined(HAVE_CURVE25519) || \
-    (defined(HAVE_ED25519) && !defined(ED25519_SMALL))
-/*
-Ignores top bit of h.
-*/
-
-void fe_frombytes(fe h,const unsigned char *s)
-{
-  int64_t h0 = load_4(s);
-  int64_t h1 = load_3(s + 4) << 6;
-  int64_t h2 = load_3(s + 7) << 5;
-  int64_t h3 = load_3(s + 10) << 3;
-  int64_t h4 = load_3(s + 13) << 2;
-  int64_t h5 = load_4(s + 16);
-  int64_t h6 = load_3(s + 20) << 7;
-  int64_t h7 = load_3(s + 23) << 5;
-  int64_t h8 = load_3(s + 26) << 4;
-  int64_t h9 = (load_3(s + 29) & 8388607) << 2;
-  int64_t carry0;
-  int64_t carry1;
-  int64_t carry2;
-  int64_t carry3;
-  int64_t carry4;
-  int64_t carry5;
-  int64_t carry6;
-  int64_t carry7;
-  int64_t carry8;
-  int64_t carry9;
-
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
-
-  h[0] = (int32_t)h0;
-  h[1] = (int32_t)h1;
-  h[2] = (int32_t)h2;
-  h[3] = (int32_t)h3;
-  h[4] = (int32_t)h4;
-  h[5] = (int32_t)h5;
-  h[6] = (int32_t)h6;
-  h[7] = (int32_t)h7;
-  h[8] = (int32_t)h8;
-  h[9] = (int32_t)h9;
-}
-#endif
-
-
-void fe_invert(fe out,const fe z)
-{
-  fe t0;
-  fe t1;
-  fe t2;
-  fe t3;
-  int i;
-
-  /* pow225521 */
-  fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
-  fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
-  fe_mul(t1,z,t1);
-  fe_mul(t0,t0,t1);
-  fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2);
-  fe_mul(t1,t1,t2);
-  fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2);
-  fe_mul(t1,t2,t1);
-  fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2);
-  fe_mul(t2,t2,t1);
-  fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3);
-  fe_mul(t2,t3,t2);
-  fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2);
-  fe_mul(t1,t2,t1);
-  fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2);
-  fe_mul(t2,t2,t1);
-  fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3);
-  fe_mul(t2,t3,t2);
-  fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2);
-  fe_mul(t1,t2,t1);
-  fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1);
-  fe_mul(out,t1,t0);
-
-  return;
-}
-
-
-/*
-h = f
-*/
-
-void fe_copy(fe h,const fe f)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  h[0] = f0;
-  h[1] = f1;
-  h[2] = f2;
-  h[3] = f3;
-  h[4] = f4;
-  h[5] = f5;
-  h[6] = f6;
-  h[7] = f7;
-  h[8] = f8;
-  h[9] = f9;
-}
-
-
-/*
-h = f * g
-Can overlap h with f or g.
-
-Preconditions:
-   |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-   |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-
-Postconditions:
-   |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
-*/
-
-/*
-Notes on implementation strategy:
-
-Using schoolbook multiplication.
-Karatsuba would save a little in some cost models.
-
-Most multiplications by 2 and 19 are 32-bit precomputations;
-cheaper than 64-bit postcomputations.
-
-There is one remaining multiplication by 19 in the carry chain;
-one *19 precomputation can be merged into this,
-but the resulting data flow is considerably less clean.
-
-There are 12 carries below.
-10 of them are 2-way parallelizable and vectorizable.
-Can get away with 11 carries, but then data flow is much deeper.
-
-With tighter constraints on inputs can squeeze carries into int32.
-*/
-
-void fe_mul(fe h,const fe f,const fe g)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t g0 = g[0];
-  int32_t g1 = g[1];
-  int32_t g2 = g[2];
-  int32_t g3 = g[3];
-  int32_t g4 = g[4];
-  int32_t g5 = g[5];
-  int32_t g6 = g[6];
-  int32_t g7 = g[7];
-  int32_t g8 = g[8];
-  int32_t g9 = g[9];
-  int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
-  int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
-  int32_t g3_19 = 19 * g3;
-  int32_t g4_19 = 19 * g4;
-  int32_t g5_19 = 19 * g5;
-  int32_t g6_19 = 19 * g6;
-  int32_t g7_19 = 19 * g7;
-  int32_t g8_19 = 19 * g8;
-  int32_t g9_19 = 19 * g9;
-  int32_t f1_2 = 2 * f1;
-  int32_t f3_2 = 2 * f3;
-  int32_t f5_2 = 2 * f5;
-  int32_t f7_2 = 2 * f7;
-  int32_t f9_2 = 2 * f9;
-  int64_t f0g0    = f0   * (int64_t) g0;
-  int64_t f0g1    = f0   * (int64_t) g1;
-  int64_t f0g2    = f0   * (int64_t) g2;
-  int64_t f0g3    = f0   * (int64_t) g3;
-  int64_t f0g4    = f0   * (int64_t) g4;
-  int64_t f0g5    = f0   * (int64_t) g5;
-  int64_t f0g6    = f0   * (int64_t) g6;
-  int64_t f0g7    = f0   * (int64_t) g7;
-  int64_t f0g8    = f0   * (int64_t) g8;
-  int64_t f0g9    = f0   * (int64_t) g9;
-  int64_t f1g0    = f1   * (int64_t) g0;
-  int64_t f1g1_2  = f1_2 * (int64_t) g1;
-  int64_t f1g2    = f1   * (int64_t) g2;
-  int64_t f1g3_2  = f1_2 * (int64_t) g3;
-  int64_t f1g4    = f1   * (int64_t) g4;
-  int64_t f1g5_2  = f1_2 * (int64_t) g5;
-  int64_t f1g6    = f1   * (int64_t) g6;
-  int64_t f1g7_2  = f1_2 * (int64_t) g7;
-  int64_t f1g8    = f1   * (int64_t) g8;
-  int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
-  int64_t f2g0    = f2   * (int64_t) g0;
-  int64_t f2g1    = f2   * (int64_t) g1;
-  int64_t f2g2    = f2   * (int64_t) g2;
-  int64_t f2g3    = f2   * (int64_t) g3;
-  int64_t f2g4    = f2   * (int64_t) g4;
-  int64_t f2g5    = f2   * (int64_t) g5;
-  int64_t f2g6    = f2   * (int64_t) g6;
-  int64_t f2g7    = f2   * (int64_t) g7;
-  int64_t f2g8_19 = f2   * (int64_t) g8_19;
-  int64_t f2g9_19 = f2   * (int64_t) g9_19;
-  int64_t f3g0    = f3   * (int64_t) g0;
-  int64_t f3g1_2  = f3_2 * (int64_t) g1;
-  int64_t f3g2    = f3   * (int64_t) g2;
-  int64_t f3g3_2  = f3_2 * (int64_t) g3;
-  int64_t f3g4    = f3   * (int64_t) g4;
-  int64_t f3g5_2  = f3_2 * (int64_t) g5;
-  int64_t f3g6    = f3   * (int64_t) g6;
-  int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
-  int64_t f3g8_19 = f3   * (int64_t) g8_19;
-  int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
-  int64_t f4g0    = f4   * (int64_t) g0;
-  int64_t f4g1    = f4   * (int64_t) g1;
-  int64_t f4g2    = f4   * (int64_t) g2;
-  int64_t f4g3    = f4   * (int64_t) g3;
-  int64_t f4g4    = f4   * (int64_t) g4;
-  int64_t f4g5    = f4   * (int64_t) g5;
-  int64_t f4g6_19 = f4   * (int64_t) g6_19;
-  int64_t f4g7_19 = f4   * (int64_t) g7_19;
-  int64_t f4g8_19 = f4   * (int64_t) g8_19;
-  int64_t f4g9_19 = f4   * (int64_t) g9_19;
-  int64_t f5g0    = f5   * (int64_t) g0;
-  int64_t f5g1_2  = f5_2 * (int64_t) g1;
-  int64_t f5g2    = f5   * (int64_t) g2;
-  int64_t f5g3_2  = f5_2 * (int64_t) g3;
-  int64_t f5g4    = f5   * (int64_t) g4;
-  int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
-  int64_t f5g6_19 = f5   * (int64_t) g6_19;
-  int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
-  int64_t f5g8_19 = f5   * (int64_t) g8_19;
-  int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
-  int64_t f6g0    = f6   * (int64_t) g0;
-  int64_t f6g1    = f6   * (int64_t) g1;
-  int64_t f6g2    = f6   * (int64_t) g2;
-  int64_t f6g3    = f6   * (int64_t) g3;
-  int64_t f6g4_19 = f6   * (int64_t) g4_19;
-  int64_t f6g5_19 = f6   * (int64_t) g5_19;
-  int64_t f6g6_19 = f6   * (int64_t) g6_19;
-  int64_t f6g7_19 = f6   * (int64_t) g7_19;
-  int64_t f6g8_19 = f6   * (int64_t) g8_19;
-  int64_t f6g9_19 = f6   * (int64_t) g9_19;
-  int64_t f7g0    = f7   * (int64_t) g0;
-  int64_t f7g1_2  = f7_2 * (int64_t) g1;
-  int64_t f7g2    = f7   * (int64_t) g2;
-  int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
-  int64_t f7g4_19 = f7   * (int64_t) g4_19;
-  int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
-  int64_t f7g6_19 = f7   * (int64_t) g6_19;
-  int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
-  int64_t f7g8_19 = f7   * (int64_t) g8_19;
-  int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
-  int64_t f8g0    = f8   * (int64_t) g0;
-  int64_t f8g1    = f8   * (int64_t) g1;
-  int64_t f8g2_19 = f8   * (int64_t) g2_19;
-  int64_t f8g3_19 = f8   * (int64_t) g3_19;
-  int64_t f8g4_19 = f8   * (int64_t) g4_19;
-  int64_t f8g5_19 = f8   * (int64_t) g5_19;
-  int64_t f8g6_19 = f8   * (int64_t) g6_19;
-  int64_t f8g7_19 = f8   * (int64_t) g7_19;
-  int64_t f8g8_19 = f8   * (int64_t) g8_19;
-  int64_t f8g9_19 = f8   * (int64_t) g9_19;
-  int64_t f9g0    = f9   * (int64_t) g0;
-  int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
-  int64_t f9g2_19 = f9   * (int64_t) g2_19;
-  int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
-  int64_t f9g4_19 = f9   * (int64_t) g4_19;
-  int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
-  int64_t f9g6_19 = f9   * (int64_t) g6_19;
-  int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
-  int64_t f9g8_19 = f9   * (int64_t) g8_19;
-  int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
-  int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
-  int64_t h1 = f0g1+f1g0   +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
-  int64_t h2 = f0g2+f1g1_2 +f2g0   +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
-  int64_t h3 = f0g3+f1g2   +f2g1   +f3g0   +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
-  int64_t h4 = f0g4+f1g3_2 +f2g2   +f3g1_2 +f4g0   +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
-  int64_t h5 = f0g5+f1g4   +f2g3   +f3g2   +f4g1   +f5g0   +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
-  int64_t h6 = f0g6+f1g5_2 +f2g4   +f3g3_2 +f4g2   +f5g1_2 +f6g0   +f7g9_38+f8g8_19+f9g7_38;
-  int64_t h7 = f0g7+f1g6   +f2g5   +f3g4   +f4g3   +f5g2   +f6g1   +f7g0   +f8g9_19+f9g8_19;
-  int64_t h8 = f0g8+f1g7_2 +f2g6   +f3g5_2 +f4g4   +f5g3_2 +f6g2   +f7g1_2 +f8g0   +f9g9_38;
-  int64_t h9 = f0g9+f1g8   +f2g7   +f3g6   +f4g5   +f5g4   +f6g3   +f7g2   +f8g1   +f9g0   ;
-  int64_t carry0;
-  int64_t carry1;
-  int64_t carry2;
-  int64_t carry3;
-  int64_t carry4;
-  int64_t carry5;
-  int64_t carry6;
-  int64_t carry7;
-  int64_t carry8;
-  int64_t carry9;
-
-  /*
-  |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
-    i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
-  |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
-    i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
-  */
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  /* |h0| <= 2^25 */
-  /* |h4| <= 2^25 */
-  /* |h1| <= 1.71*2^59 */
-  /* |h5| <= 1.71*2^59 */
-
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-  /* |h1| <= 2^24; from now on fits into int32 */
-  /* |h5| <= 2^24; from now on fits into int32 */
-  /* |h2| <= 1.41*2^60 */
-  /* |h6| <= 1.41*2^60 */
-
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-  /* |h2| <= 2^25; from now on fits into int32 unchanged */
-  /* |h6| <= 2^25; from now on fits into int32 unchanged */
-  /* |h3| <= 1.71*2^59 */
-  /* |h7| <= 1.71*2^59 */
-
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
-  /* |h3| <= 2^24; from now on fits into int32 unchanged */
-  /* |h7| <= 2^24; from now on fits into int32 unchanged */
-  /* |h4| <= 1.72*2^34 */
-  /* |h8| <= 1.41*2^60 */
-
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
-  /* |h4| <= 2^25; from now on fits into int32 unchanged */
-  /* |h8| <= 2^25; from now on fits into int32 unchanged */
-  /* |h5| <= 1.01*2^24 */
-  /* |h9| <= 1.71*2^59 */
-
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-  /* |h9| <= 2^24; from now on fits into int32 unchanged */
-  /* |h0| <= 1.1*2^39 */
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  /* |h0| <= 2^25; from now on fits into int32 unchanged */
-  /* |h1| <= 1.01*2^24 */
-
-  h[0] = (int32_t)h0;
-  h[1] = (int32_t)h1;
-  h[2] = (int32_t)h2;
-  h[3] = (int32_t)h3;
-  h[4] = (int32_t)h4;
-  h[5] = (int32_t)h5;
-  h[6] = (int32_t)h6;
-  h[7] = (int32_t)h7;
-  h[8] = (int32_t)h8;
-  h[9] = (int32_t)h9;
-}
-
-
-/*
-Replace (f,g) with (g,f) if b == 1;
-replace (f,g) with (f,g) if b == 0.
-
-Preconditions: b in {0,1}.
-*/
-
-void fe_cswap(fe f, fe g, int b)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t g0 = g[0];
-  int32_t g1 = g[1];
-  int32_t g2 = g[2];
-  int32_t g3 = g[3];
-  int32_t g4 = g[4];
-  int32_t g5 = g[5];
-  int32_t g6 = g[6];
-  int32_t g7 = g[7];
-  int32_t g8 = g[8];
-  int32_t g9 = g[9];
-  int32_t x0 = f0 ^ g0;
-  int32_t x1 = f1 ^ g1;
-  int32_t x2 = f2 ^ g2;
-  int32_t x3 = f3 ^ g3;
-  int32_t x4 = f4 ^ g4;
-  int32_t x5 = f5 ^ g5;
-  int32_t x6 = f6 ^ g6;
-  int32_t x7 = f7 ^ g7;
-  int32_t x8 = f8 ^ g8;
-  int32_t x9 = f9 ^ g9;
-  b = -b;
-  x0 &= b;
-  x1 &= b;
-  x2 &= b;
-  x3 &= b;
-  x4 &= b;
-  x5 &= b;
-  x6 &= b;
-  x7 &= b;
-  x8 &= b;
-  x9 &= b;
-  f[0] = f0 ^ x0;
-  f[1] = f1 ^ x1;
-  f[2] = f2 ^ x2;
-  f[3] = f3 ^ x3;
-  f[4] = f4 ^ x4;
-  f[5] = f5 ^ x5;
-  f[6] = f6 ^ x6;
-  f[7] = f7 ^ x7;
-  f[8] = f8 ^ x8;
-  f[9] = f9 ^ x9;
-  g[0] = g0 ^ x0;
-  g[1] = g1 ^ x1;
-  g[2] = g2 ^ x2;
-  g[3] = g3 ^ x3;
-  g[4] = g4 ^ x4;
-  g[5] = g5 ^ x5;
-  g[6] = g6 ^ x6;
-  g[7] = g7 ^ x7;
-  g[8] = g8 ^ x8;
-  g[9] = g9 ^ x9;
-}
-
-
-/*
-h = f * 121666
-Can overlap h with f.
-
-Preconditions:
-   |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-
-Postconditions:
-   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-*/
-
-void fe_mul121666(fe h,fe f)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int64_t h0 = f0 * (int64_t) 121666;
-  int64_t h1 = f1 * (int64_t) 121666;
-  int64_t h2 = f2 * (int64_t) 121666;
-  int64_t h3 = f3 * (int64_t) 121666;
-  int64_t h4 = f4 * (int64_t) 121666;
-  int64_t h5 = f5 * (int64_t) 121666;
-  int64_t h6 = f6 * (int64_t) 121666;
-  int64_t h7 = f7 * (int64_t) 121666;
-  int64_t h8 = f8 * (int64_t) 121666;
-  int64_t h9 = f9 * (int64_t) 121666;
-  int64_t carry0;
-  int64_t carry1;
-  int64_t carry2;
-  int64_t carry3;
-  int64_t carry4;
-  int64_t carry5;
-  int64_t carry6;
-  int64_t carry7;
-  int64_t carry8;
-  int64_t carry9;
-
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
-
-  h[0] = (int32_t)h0;
-  h[1] = (int32_t)h1;
-  h[2] = (int32_t)h2;
-  h[3] = (int32_t)h3;
-  h[4] = (int32_t)h4;
-  h[5] = (int32_t)h5;
-  h[6] = (int32_t)h6;
-  h[7] = (int32_t)h7;
-  h[8] = (int32_t)h8;
-  h[9] = (int32_t)h9;
-}
-
-
-/*
-h = 2 * f * f
-Can overlap h with f.
-
-Preconditions:
-   |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
-
-Postconditions:
-   |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
-*/
-
-/*
-See fe_mul.c for discussion of implementation strategy.
-*/
-
-void fe_sq2(fe h,const fe f)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t f0_2 = 2 * f0;
-  int32_t f1_2 = 2 * f1;
-  int32_t f2_2 = 2 * f2;
-  int32_t f3_2 = 2 * f3;
-  int32_t f4_2 = 2 * f4;
-  int32_t f5_2 = 2 * f5;
-  int32_t f6_2 = 2 * f6;
-  int32_t f7_2 = 2 * f7;
-  int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
-  int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
-  int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
-  int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
-  int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
-  int64_t f0f0    = f0   * (int64_t) f0;
-  int64_t f0f1_2  = f0_2 * (int64_t) f1;
-  int64_t f0f2_2  = f0_2 * (int64_t) f2;
-  int64_t f0f3_2  = f0_2 * (int64_t) f3;
-  int64_t f0f4_2  = f0_2 * (int64_t) f4;
-  int64_t f0f5_2  = f0_2 * (int64_t) f5;
-  int64_t f0f6_2  = f0_2 * (int64_t) f6;
-  int64_t f0f7_2  = f0_2 * (int64_t) f7;
-  int64_t f0f8_2  = f0_2 * (int64_t) f8;
-  int64_t f0f9_2  = f0_2 * (int64_t) f9;
-  int64_t f1f1_2  = f1_2 * (int64_t) f1;
-  int64_t f1f2_2  = f1_2 * (int64_t) f2;
-  int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
-  int64_t f1f4_2  = f1_2 * (int64_t) f4;
-  int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
-  int64_t f1f6_2  = f1_2 * (int64_t) f6;
-  int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
-  int64_t f1f8_2  = f1_2 * (int64_t) f8;
-  int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
-  int64_t f2f2    = f2   * (int64_t) f2;
-  int64_t f2f3_2  = f2_2 * (int64_t) f3;
-  int64_t f2f4_2  = f2_2 * (int64_t) f4;
-  int64_t f2f5_2  = f2_2 * (int64_t) f5;
-  int64_t f2f6_2  = f2_2 * (int64_t) f6;
-  int64_t f2f7_2  = f2_2 * (int64_t) f7;
-  int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
-  int64_t f2f9_38 = f2   * (int64_t) f9_38;
-  int64_t f3f3_2  = f3_2 * (int64_t) f3;
-  int64_t f3f4_2  = f3_2 * (int64_t) f4;
-  int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
-  int64_t f3f6_2  = f3_2 * (int64_t) f6;
-  int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
-  int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
-  int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
-  int64_t f4f4    = f4   * (int64_t) f4;
-  int64_t f4f5_2  = f4_2 * (int64_t) f5;
-  int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
-  int64_t f4f7_38 = f4   * (int64_t) f7_38;
-  int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
-  int64_t f4f9_38 = f4   * (int64_t) f9_38;
-  int64_t f5f5_38 = f5   * (int64_t) f5_38;
-  int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
-  int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
-  int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
-  int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
-  int64_t f6f6_19 = f6   * (int64_t) f6_19;
-  int64_t f6f7_38 = f6   * (int64_t) f7_38;
-  int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
-  int64_t f6f9_38 = f6   * (int64_t) f9_38;
-  int64_t f7f7_38 = f7   * (int64_t) f7_38;
-  int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
-  int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
-  int64_t f8f8_19 = f8   * (int64_t) f8_19;
-  int64_t f8f9_38 = f8   * (int64_t) f9_38;
-  int64_t f9f9_38 = f9   * (int64_t) f9_38;
-  int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
-  int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
-  int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
-  int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
-  int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
-  int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
-  int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
-  int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
-  int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
-  int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
-  int64_t carry0;
-  int64_t carry1;
-  int64_t carry2;
-  int64_t carry3;
-  int64_t carry4;
-  int64_t carry5;
-  int64_t carry6;
-  int64_t carry7;
-  int64_t carry8;
-  int64_t carry9;
-
-  h0 += h0;
-  h1 += h1;
-  h2 += h2;
-  h3 += h3;
-  h4 += h4;
-  h5 += h5;
-  h6 += h6;
-  h7 += h7;
-  h8 += h8;
-  h9 += h9;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
-
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
-
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-
-  h[0] = (int32_t)h0;
-  h[1] = (int32_t)h1;
-  h[2] = (int32_t)h2;
-  h[3] = (int32_t)h3;
-  h[4] = (int32_t)h4;
-  h[5] = (int32_t)h5;
-  h[6] = (int32_t)h6;
-  h[7] = (int32_t)h7;
-  h[8] = (int32_t)h8;
-  h[9] = (int32_t)h9;
-}
-
-
-void fe_pow22523(fe out,const fe z)
-{
-  fe t0;
-  fe t1;
-  fe t2;
-  int i;
-
-  fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
-  fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
-  fe_mul(t1,z,t1);
-  fe_mul(t0,t0,t1);
-  fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0);
-  fe_mul(t0,t1,t0);
-  fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1);
-  fe_mul(t0,t1,t0);
-  fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1);
-  fe_mul(t1,t1,t0);
-  fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2);
-  fe_mul(t1,t2,t1);
-  fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1);
-  fe_mul(t0,t1,t0);
-  fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1);
-  fe_mul(t1,t1,t0);
-  fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2);
-  fe_mul(t1,t2,t1);
-  fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1);
-  fe_mul(t0,t1,t0);
-  fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0);
-  fe_mul(out,t0,z);
-
-  return;
-}
-
-
-/*
-h = -f
-
-Preconditions:
-   |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-
-Postconditions:
-   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-*/
-
-void fe_neg(fe h,const fe f)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t h0 = -f0;
-  int32_t h1 = -f1;
-  int32_t h2 = -f2;
-  int32_t h3 = -f3;
-  int32_t h4 = -f4;
-  int32_t h5 = -f5;
-  int32_t h6 = -f6;
-  int32_t h7 = -f7;
-  int32_t h8 = -f8;
-  int32_t h9 = -f9;
-  h[0] = h0;
-  h[1] = h1;
-  h[2] = h2;
-  h[3] = h3;
-  h[4] = h4;
-  h[5] = h5;
-  h[6] = h6;
-  h[7] = h7;
-  h[8] = h8;
-  h[9] = h9;
-}
-
-
-/*
-Preconditions:
-   |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-*/
-
-static const unsigned char zero[32] = {0};
-
-int fe_isnonzero(const fe f)
-{
-  unsigned char s[32];
-  fe_tobytes(s,f);
-  return ConstantCompare(s,zero,32);
-}
-
-
-/*
-return 1 if f is in {1,3,5,...,q-2}
-return 0 if f is in {0,2,4,...,q-1}
-
-Preconditions:
-   |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-*/
-
-int fe_isnegative(const fe f)
-{
-  unsigned char s[32];
-  fe_tobytes(s,f);
-  return s[0] & 1;
-}
-
-
-/*
-Replace (f,g) with (g,g) if b == 1;
-replace (f,g) with (f,g) if b == 0.
-
-Preconditions: b in {0,1}.
-*/
-
-void fe_cmov(fe f, const fe g, int b)
-{
-  int32_t f0 = f[0];
-  int32_t f1 = f[1];
-  int32_t f2 = f[2];
-  int32_t f3 = f[3];
-  int32_t f4 = f[4];
-  int32_t f5 = f[5];
-  int32_t f6 = f[6];
-  int32_t f7 = f[7];
-  int32_t f8 = f[8];
-  int32_t f9 = f[9];
-  int32_t g0 = g[0];
-  int32_t g1 = g[1];
-  int32_t g2 = g[2];
-  int32_t g3 = g[3];
-  int32_t g4 = g[4];
-  int32_t g5 = g[5];
-  int32_t g6 = g[6];
-  int32_t g7 = g[7];
-  int32_t g8 = g[8];
-  int32_t g9 = g[9];
-  int32_t x0 = f0 ^ g0;
-  int32_t x1 = f1 ^ g1;
-  int32_t x2 = f2 ^ g2;
-  int32_t x3 = f3 ^ g3;
-  int32_t x4 = f4 ^ g4;
-  int32_t x5 = f5 ^ g5;
-  int32_t x6 = f6 ^ g6;
-  int32_t x7 = f7 ^ g7;
-  int32_t x8 = f8 ^ g8;
-  int32_t x9 = f9 ^ g9;
-  b = -b;
-  x0 &= b;
-  x1 &= b;
-  x2 &= b;
-  x3 &= b;
-  x4 &= b;
-  x5 &= b;
-  x6 &= b;
-  x7 &= b;
-  x8 &= b;
-  x9 &= b;
-  f[0] = f0 ^ x0;
-  f[1] = f1 ^ x1;
-  f[2] = f2 ^ x2;
-  f[3] = f3 ^ x3;
-  f[4] = f4 ^ x4;
-  f[5] = f5 ^ x5;
-  f[6] = f6 ^ x6;
-  f[7] = f7 ^ x7;
-  f[8] = f8 ^ x8;
-  f[9] = f9 ^ x9;
-}
-#endif
-
-#endif /* !CURVE25519_SMALL || !ED25519_SMALL */
-#endif /* HAVE_CURVE25519 || HAVE_ED25519 */
-
--- a/wolfcrypt/src/ge_low_mem.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,564 +0,0 @@
-/* ge_low_mem.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based from Daniel Beer's public domain work. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_ED25519
-#ifdef ED25519_SMALL /* use slower code that takes less memory */
-
-#include <wolfssl/wolfcrypt/ge_operations.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-void ed25519_smult(ge_p3 *r, const ge_p3 *a, const byte *e);
-void ed25519_add(ge_p3 *r, const ge_p3 *a, const ge_p3 *b);
-void ed25519_double(ge_p3 *r, const ge_p3 *a);
-
-
-static const byte ed25519_order[F25519_SIZE] = {
-    0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
-    0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
-};
-
-/*Arithmetic modulo the group order m = 2^252 +
- 27742317777372353535851937790883648493 =
- 7237005577332262213973186563042994240857116359379907606001950938285454250989 */
-
-static const word32 m[32] = {
-    0xED,0xD3,0xF5,0x5C,0x1A,0x63,0x12,0x58,0xD6,0x9C,0xF7,0xA2,0xDE,0xF9,
-    0xDE,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x10
-};
-
-static const word32 mu[33] = {
-    0x1B,0x13,0x2C,0x0A,0xA3,0xE5,0x9C,0xED,0xA7,0x29,0x63,0x08,0x5D,0x21,
-    0x06,0x21,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0xFF,0xFF,0xFF,0xFF,0x0F
-};
-
-
-int ge_compress_key(byte* out, const byte* xIn, const byte* yIn,
-                        word32 keySz)
-{
-    byte tmp[F25519_SIZE];
-    byte parity;
-    byte pt[32];
-    int     i;
-
-    lm_copy(tmp, xIn);
-    parity = (tmp[0] & 1) << 7;
-
-    lm_copy(pt, yIn);
-    pt[31] |= parity;
-
-    for(i = 0; i < 32; i++) {
-        out[32-i-1] = pt[i];
-    }
-    (void)keySz;
-    return 0;
-}
-
-
-static word32 lt(word32 a,word32 b) /* 16-bit inputs */
-{
-  unsigned int x = a;
-  x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */
-  x >>= 31; /* 0: no; 1: yes */
-  return x;
-}
-
-
-/* Reduce coefficients of r before calling reduce_add_sub */
-static void reduce_add_sub(word32 *r)
-{
-  word32 pb = 0;
-  word32 b;
-  word32 mask;
-  int i;
-  unsigned char t[32];
-
-  for(i=0;i<32;i++)
-  {
-    pb += m[i];
-    b = lt(r[i],pb);
-    t[i] = r[i]-pb+(b<<8);
-    pb = b;
-  }
-  mask = b - 1;
-  for(i=0;i<32;i++)
-    r[i] ^= mask & (r[i] ^ t[i]);
-}
-
-
-/* Reduce coefficients of x before calling barrett_reduce */
-static void barrett_reduce(word32* r, word32 x[64])
-{
-  /* See HAC, Alg. 14.42 */
-  int i,j;
-  word32 q2[66];
-  word32 *q3 = q2 + 33;
-  word32 r1[33];
-  word32 r2[33];
-  word32 carry;
-  word32 pb = 0;
-  word32 b;
-
-  for (i = 0;i < 66;++i) q2[i] = 0;
-  for (i = 0;i < 33;++i) r2[i] = 0;
-
-  for(i=0;i<33;i++)
-    for(j=0;j<33;j++)
-      if(i+j >= 31) q2[i+j] += mu[i]*x[j+31];
-  carry = q2[31] >> 8;
-  q2[32] += carry;
-  carry = q2[32] >> 8;
-  q2[33] += carry;
-
-  for(i=0;i<33;i++)r1[i] = x[i];
-  for(i=0;i<32;i++)
-    for(j=0;j<33;j++)
-      if(i+j < 33) r2[i+j] += m[i]*q3[j];
-
-  for(i=0;i<32;i++)
-  {
-    carry = r2[i] >> 8;
-    r2[i+1] += carry;
-    r2[i] &= 0xff;
-  }
-
-  for(i=0;i<32;i++)
-  {
-    pb += r2[i];
-    b = lt(r1[i],pb);
-    r[i] = r1[i]-pb+(b<<8);
-    pb = b;
-  }
-
-  /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3
-   * r is an unsigned type.
-   * If so: Handle  it here!
-   */
-
-  reduce_add_sub(r);
-  reduce_add_sub(r);
-}
-
-
-void sc_reduce(unsigned char x[64])
-{
-  int i;
-  word32 t[64];
-  word32 r[32];
-  for(i=0;i<64;i++) t[i] = x[i];
-  barrett_reduce(r, t);
-  for(i=0;i<32;i++) x[i] = (r[i] & 0xFF);
-}
-
-
-void sc_muladd(byte* out, const byte* a, const byte* b, const byte* c)
-{
-
-    byte s[32];
-    byte e[64];
-
-    XMEMSET(e, 0, sizeof(e));
-    XMEMCPY(e, b, 32);
-
-    /* Obtain e */
-    sc_reduce(e);
-
-    /* Compute s = ze + k */
-    fprime_mul(s, a, e, ed25519_order);
-    fprime_add(s, c, ed25519_order);
-
-    XMEMCPY(out, s, 32);
-}
-
-
-/* Base point is (numbers wrapped):
- *
- *     x = 151122213495354007725011514095885315114
- *         54012693041857206046113283949847762202
- *     y = 463168356949264781694283940034751631413
- *         07993866256225615783033603165251855960
- *
- * y is derived by transforming the original Montgomery base (u=9). x
- * is the corresponding positive coordinate for the new curve equation.
- * t is x*y.
- */
-const ge_p3 ed25519_base = {
-    {
-        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9,
-        0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69,
-        0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
-        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
-    },
-    {
-        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
-        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66
-    },
-    {1, 0},
-    {
-        0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d,
-        0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20,
-        0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66,
-        0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67
-    },
-
-};
-
-
-const ge_p3 ed25519_neutral = {
-    {0},
-    {1, 0},
-    {1, 0},
-    {0},
-
-};
-
-
-static const byte ed25519_d[F25519_SIZE] = {
-    0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
-    0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
-    0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
-    0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
-};
-
-
-/* k = 2d */
-static const byte ed25519_k[F25519_SIZE] = {
-    0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb,
-    0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00,
-    0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19,
-    0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24
-};
-
-
-void ed25519_add(ge_p3 *r,
-         const ge_p3 *p1, const ge_p3 *p2)
-{
-    /* Explicit formulas database: add-2008-hwcd-3
-     *
-     * source 2008 Hisil--Wong--Carter--Dawson,
-     *     http://eprint.iacr.org/2008/522, Section 3.1
-     * appliesto extended-1
-     * parameter k
-     * assume k = 2 d
-     * compute A = (Y1-X1)(Y2-X2)
-     * compute B = (Y1+X1)(Y2+X2)
-     * compute C = T1 k T2
-     * compute D = Z1 2 Z2
-     * compute E = B - A
-     * compute F = D - C
-     * compute G = D + C
-     * compute H = B + A
-     * compute X3 = E F
-     * compute Y3 = G H
-     * compute T3 = E H
-     * compute Z3 = F G
-     */
-    byte a[F25519_SIZE];
-    byte b[F25519_SIZE];
-    byte c[F25519_SIZE];
-    byte d[F25519_SIZE];
-    byte e[F25519_SIZE];
-    byte f[F25519_SIZE];
-    byte g[F25519_SIZE];
-    byte h[F25519_SIZE];
-
-    /* A = (Y1-X1)(Y2-X2) */
-    lm_sub(c, p1->Y, p1->X);
-    lm_sub(d, p2->Y, p2->X);
-    fe_mul__distinct(a, c, d);
-
-    /* B = (Y1+X1)(Y2+X2) */
-    lm_add(c, p1->Y, p1->X);
-    lm_add(d, p2->Y, p2->X);
-    fe_mul__distinct(b, c, d);
-
-    /* C = T1 k T2 */
-    fe_mul__distinct(d, p1->T, p2->T);
-    fe_mul__distinct(c, d, ed25519_k);
-
-    /* D = Z1 2 Z2 */
-    fe_mul__distinct(d, p1->Z, p2->Z);
-    lm_add(d, d, d);
-
-    /* E = B - A */
-    lm_sub(e, b, a);
-
-    /* F = D - C */
-    lm_sub(f, d, c);
-
-    /* G = D + C */
-    lm_add(g, d, c);
-
-    /* H = B + A */
-    lm_add(h, b, a);
-
-    /* X3 = E F */
-    fe_mul__distinct(r->X, e, f);
-
-    /* Y3 = G H */
-    fe_mul__distinct(r->Y, g, h);
-
-    /* T3 = E H */
-    fe_mul__distinct(r->T, e, h);
-
-    /* Z3 = F G */
-    fe_mul__distinct(r->Z, f, g);
-}
-
-
-void ed25519_double(ge_p3 *r, const ge_p3 *p)
-{
-    /* Explicit formulas database: dbl-2008-hwcd
-     *
-     * source 2008 Hisil--Wong--Carter--Dawson,
-     *     http://eprint.iacr.org/2008/522, Section 3.3
-     * compute A = X1^2
-     * compute B = Y1^2
-     * compute C = 2 Z1^2
-     * compute D = a A
-     * compute E = (X1+Y1)^2-A-B
-     * compute G = D + B
-     * compute F = G - C
-     * compute H = D - B
-     * compute X3 = E F
-     * compute Y3 = G H
-     * compute T3 = E H
-     * compute Z3 = F G
-     */
-    byte a[F25519_SIZE];
-    byte b[F25519_SIZE];
-    byte c[F25519_SIZE];
-    byte e[F25519_SIZE];
-    byte f[F25519_SIZE];
-    byte g[F25519_SIZE];
-    byte h[F25519_SIZE];
-
-    /* A = X1^2 */
-    fe_mul__distinct(a, p->X, p->X);
-
-    /* B = Y1^2 */
-    fe_mul__distinct(b, p->Y, p->Y);
-
-    /* C = 2 Z1^2 */
-    fe_mul__distinct(c, p->Z, p->Z);
-    lm_add(c, c, c);
-
-    /* D = a A (alter sign) */
-    /* E = (X1+Y1)^2-A-B */
-    lm_add(f, p->X, p->Y);
-    fe_mul__distinct(e, f, f);
-    lm_sub(e, e, a);
-    lm_sub(e, e, b);
-
-    /* G = D + B */
-    lm_sub(g, b, a);
-
-    /* F = G - C */
-    lm_sub(f, g, c);
-
-    /* H = D - B */
-    lm_neg(h, b);
-    lm_sub(h, h, a);
-
-    /* X3 = E F */
-    fe_mul__distinct(r->X, e, f);
-
-    /* Y3 = G H */
-    fe_mul__distinct(r->Y, g, h);
-
-    /* T3 = E H */
-    fe_mul__distinct(r->T, e, h);
-
-    /* Z3 = F G */
-    fe_mul__distinct(r->Z, f, g);
-}
-
-
-void ed25519_smult(ge_p3 *r_out, const ge_p3 *p, const byte *e)
-{
-    ge_p3 r;
-    int   i;
-
-    XMEMCPY(&r, &ed25519_neutral, sizeof(r));
-
-    for (i = 255; i >= 0; i--) {
-        const byte bit = (e[i >> 3] >> (i & 7)) & 1;
-        ge_p3 s;
-
-        ed25519_double(&r, &r);
-        ed25519_add(&s, &r, p);
-
-        fe_select(r.X, r.X, s.X, bit);
-        fe_select(r.Y, r.Y, s.Y, bit);
-        fe_select(r.Z, r.Z, s.Z, bit);
-        fe_select(r.T, r.T, s.T, bit);
-    }
-    XMEMCPY(r_out, &r, sizeof(r));
-}
-
-
-void ge_scalarmult_base(ge_p3 *R,const unsigned char *nonce)
-{
-    ed25519_smult(R, &ed25519_base, nonce);
-}
-
-
-/* pack the point h into array s */
-void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
-{
-    byte x[F25519_SIZE];
-    byte y[F25519_SIZE];
-    byte z1[F25519_SIZE];
-    byte parity;
-
-    fe_inv__distinct(z1, h->Z);
-    fe_mul__distinct(x, h->X, z1);
-    fe_mul__distinct(y, h->Y, z1);
-
-    fe_normalize(x);
-    fe_normalize(y);
-
-    parity = (x[0] & 1) << 7;
-    lm_copy(s, y);
-    fe_normalize(s);
-    s[31] |= parity;
-}
-
-
-/* pack the point h into array s */
-void ge_tobytes(unsigned char *s,const ge_p2 *h)
-{
-    byte x[F25519_SIZE];
-    byte y[F25519_SIZE];
-    byte z1[F25519_SIZE];
-    byte parity;
-
-    fe_inv__distinct(z1, h->Z);
-    fe_mul__distinct(x, h->X, z1);
-    fe_mul__distinct(y, h->Y, z1);
-
-    fe_normalize(x);
-    fe_normalize(y);
-
-    parity = (x[0] & 1) << 7;
-    lm_copy(s, y);
-    fe_normalize(s);
-    s[31] |= parity;
-}
-
-
-/*
-   Test if the public key can be uncompressed and negate it (-X,Y,Z,-T)
-   return 0 on success
- */
-int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s)
-{
-
-    byte parity;
-    byte x[F25519_SIZE];
-    byte y[F25519_SIZE];
-    byte a[F25519_SIZE];
-    byte b[F25519_SIZE];
-    byte c[F25519_SIZE];
-    int ret = 0;
-
-    /* unpack the key s */
-    parity = s[31] >> 7;
-    lm_copy(y, s);
-    y[31] &= 127;
-
-    fe_mul__distinct(c, y, y);
-    fe_mul__distinct(b, c, ed25519_d);
-    lm_add(a, b, f25519_one);
-    fe_inv__distinct(b, a);
-    lm_sub(a, c, f25519_one);
-    fe_mul__distinct(c, a, b);
-    fe_sqrt(a, c);
-    lm_neg(b, a);
-    fe_select(x, a, b, (a[0] ^ parity) & 1);
-
-    /* test that x^2 is equal to c */
-    fe_mul__distinct(a, x, x);
-    fe_normalize(a);
-    fe_normalize(c);
-    ret |= ConstantCompare(a, c, F25519_SIZE);
-
-    /* project the key s onto p */
-    lm_copy(p->X, x);
-    lm_copy(p->Y, y);
-    fe_load(p->Z, 1);
-    fe_mul__distinct(p->T, x, y);
-
-    /* negate, the point becomes (-X,Y,Z,-T) */
-    lm_neg(p->X,p->X);
-    lm_neg(p->T,p->T);
-
-    return ret;
-}
-
-
-int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h,
-                                 const ge_p3 *inA,const unsigned char *sig)
-{
-    ge_p3 p, A;
-    int ret = 0;
-
-    XMEMCPY(&A, inA, sizeof(ge_p3));
-
-    /* find SB */
-    ed25519_smult(&p, &ed25519_base, sig);
-
-    /* find H(R,A,M) * -A */
-    ed25519_smult(&A, &A, h);
-
-    /* SB + -H(R,A,M)A */
-    ed25519_add(&A, &p, &A);
-
-    lm_copy(R->X, A.X);
-    lm_copy(R->Y, A.Y);
-    lm_copy(R->Z, A.Z);
-
-    return ret;
-}
-
-#endif /* ED25519_SMALL */
-#endif /* HAVE_ED25519 */
-
--- a/wolfcrypt/src/ge_operations.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7023 +0,0 @@
-/* ge_operations.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_ED25519
-#ifndef ED25519_SMALL /* run when not defined to use small memory math */
-
-#include <wolfssl/wolfcrypt/ge_operations.h>
-#include <wolfssl/wolfcrypt/ed25519.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-static void ge_p2_0(ge_p2 *);
-#ifndef CURVED25519_X64
-static void ge_precomp_0(ge_precomp *);
-#endif
-static void ge_p3_to_p2(ge_p2 *,const ge_p3 *);
-static void ge_p3_to_cached(ge_cached *,const ge_p3 *);
-static void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *);
-static void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *);
-static void ge_p2_dbl(ge_p1p1 *,const ge_p2 *);
-static void ge_p3_dbl(ge_p1p1 *,const ge_p3 *);
-
-static void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
-static void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
-static void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *);
-static void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *);
-
-/*
-ge means group element.
-
-Here the group is the set of pairs (x,y) of field elements (see ge_operations.h)
-satisfying -x^2 + y^2 = 1 + d x^2y^2
-where d = -121665/121666.
-
-Representations:
-  ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
-  ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
-  ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
-  ge_precomp (Duif): (y+x,y-x,2dxy)
-*/
-
-#if !defined(HAVE___UINT128_T) || defined(NO_CURVED25519_128BIT)
-#define MASK_21     0x1fffff
-#define ORDER_0     0x15d3ed
-#define ORDER_1     0x18d2e7
-#define ORDER_2     0x160498
-#define ORDER_3     0xf39ac
-#define ORDER_4     0x1dea2f
-#define ORDER_5     0xa6f7c
-
-/*
-Input:
-  s[0]+256*s[1]+...+256^63*s[63] = s
-
-Output:
-  s[0]+256*s[1]+...+256^31*s[31] = s mod l
-  where l = 2^252 + 27742317777372353535851937790883648493.
-  Overwrites s in place.
-*/
-void sc_reduce(byte* s)
-{
-    int64_t t[24];
-    int64_t carry;
-
-    t[ 0] = MASK_21 & (load_3(s +  0) >> 0);
-    t[ 1] = MASK_21 & (load_4(s +  2) >> 5);
-    t[ 2] = MASK_21 & (load_3(s +  5) >> 2);
-    t[ 3] = MASK_21 & (load_4(s +  7) >> 7);
-    t[ 4] = MASK_21 & (load_4(s + 10) >> 4);
-    t[ 5] = MASK_21 & (load_3(s + 13) >> 1);
-    t[ 6] = MASK_21 & (load_4(s + 15) >> 6);
-    t[ 7] = MASK_21 & (load_3(s + 18) >> 3);
-    t[ 8] = MASK_21 & (load_3(s + 21) >> 0);
-    t[ 9] = MASK_21 & (load_4(s + 23) >> 5);
-    t[10] = MASK_21 & (load_3(s + 26) >> 2);
-    t[11] = MASK_21 & (load_4(s + 28) >> 7);
-    t[12] = MASK_21 & (load_4(s + 31) >> 4);
-    t[13] = MASK_21 & (load_3(s + 34) >> 1);
-    t[14] = MASK_21 & (load_4(s + 36) >> 6);
-    t[15] = MASK_21 & (load_3(s + 39) >> 3);
-    t[16] = MASK_21 & (load_3(s + 42) >> 0);
-    t[17] = MASK_21 & (load_4(s + 44) >> 5);
-    t[18] = MASK_21 & (load_3(s + 47) >> 2);
-    t[19] = MASK_21 & (load_4(s + 49) >> 7);
-    t[20] = MASK_21 & (load_4(s + 52) >> 4);
-    t[21] = MASK_21 & (load_3(s + 55) >> 1);
-    t[22] = MASK_21 & (load_4(s + 57) >> 6);
-    t[23] =           (load_4(s + 60) >> 3);
-
-    t[11] -= t[23] * ORDER_0;
-    t[12] -= t[23] * ORDER_1;
-    t[13] -= t[23] * ORDER_2;
-    t[14] -= t[23] * ORDER_3;
-    t[15] -= t[23] * ORDER_4;
-    t[16] -= t[23] * ORDER_5;
-
-    t[10] -= t[22] * ORDER_0;
-    t[11] -= t[22] * ORDER_1;
-    t[12] -= t[22] * ORDER_2;
-    t[13] -= t[22] * ORDER_3;
-    t[14] -= t[22] * ORDER_4;
-    t[15] -= t[22] * ORDER_5;
-
-    t[ 9] -= t[21] * ORDER_0;
-    t[10] -= t[21] * ORDER_1;
-    t[11] -= t[21] * ORDER_2;
-    t[12] -= t[21] * ORDER_3;
-    t[13] -= t[21] * ORDER_4;
-    t[14] -= t[21] * ORDER_5;
-
-    t[ 8] -= t[20] * ORDER_0;
-    t[ 9] -= t[20] * ORDER_1;
-    t[10] -= t[20] * ORDER_2;
-    t[11] -= t[20] * ORDER_3;
-    t[12] -= t[20] * ORDER_4;
-    t[13] -= t[20] * ORDER_5;
-
-    t[ 7] -= t[19] * ORDER_0;
-    t[ 8] -= t[19] * ORDER_1;
-    t[ 9] -= t[19] * ORDER_2;
-    t[10] -= t[19] * ORDER_3;
-    t[11] -= t[19] * ORDER_4;
-    t[12] -= t[19] * ORDER_5;
-
-    t[ 6] -= t[18] * ORDER_0;
-    t[ 7] -= t[18] * ORDER_1;
-    t[ 8] -= t[18] * ORDER_2;
-    t[ 9] -= t[18] * ORDER_3;
-    t[10] -= t[18] * ORDER_4;
-    t[11] -= t[18] * ORDER_5;
-
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-    carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21;
-    carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21;
-    carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21;
-    carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21;
-    carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21;
-
-    t[ 5] -= t[17] * ORDER_0;
-    t[ 6] -= t[17] * ORDER_1;
-    t[ 7] -= t[17] * ORDER_2;
-    t[ 8] -= t[17] * ORDER_3;
-    t[ 9] -= t[17] * ORDER_4;
-    t[10] -= t[17] * ORDER_5;
-
-    t[ 4] -= t[16] * ORDER_0;
-    t[ 5] -= t[16] * ORDER_1;
-    t[ 6] -= t[16] * ORDER_2;
-    t[ 7] -= t[16] * ORDER_3;
-    t[ 8] -= t[16] * ORDER_4;
-    t[ 9] -= t[16] * ORDER_5;
-
-    t[ 3] -= t[15] * ORDER_0;
-    t[ 4] -= t[15] * ORDER_1;
-    t[ 5] -= t[15] * ORDER_2;
-    t[ 6] -= t[15] * ORDER_3;
-    t[ 7] -= t[15] * ORDER_4;
-    t[ 8] -= t[15] * ORDER_5;
-
-    t[ 2] -= t[14] * ORDER_0;
-    t[ 3] -= t[14] * ORDER_1;
-    t[ 4] -= t[14] * ORDER_2;
-    t[ 5] -= t[14] * ORDER_3;
-    t[ 6] -= t[14] * ORDER_4;
-    t[ 7] -= t[14] * ORDER_5;
-
-    t[ 1] -= t[13] * ORDER_0;
-    t[ 2] -= t[13] * ORDER_1;
-    t[ 3] -= t[13] * ORDER_2;
-    t[ 4] -= t[13] * ORDER_3;
-    t[ 5] -= t[13] * ORDER_4;
-    t[ 6] -= t[13] * ORDER_5;
-
-    t[ 0] -= t[12] * ORDER_0;
-    t[ 1] -= t[12] * ORDER_1;
-    t[ 2] -= t[12] * ORDER_2;
-    t[ 3] -= t[12] * ORDER_3;
-    t[ 4] -= t[12] * ORDER_4;
-    t[ 5] -= t[12] * ORDER_5;
-    t[12]  = 0;
-
-    carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21;
-    carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21;
-    carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21;
-    carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21;
-    carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21;
-    carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21;
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-    carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21;
-
-    t[ 0] -= t[12] * ORDER_0;
-    t[ 1] -= t[12] * ORDER_1;
-    t[ 2] -= t[12] * ORDER_2;
-    t[ 3] -= t[12] * ORDER_3;
-    t[ 4] -= t[12] * ORDER_4;
-    t[ 5] -= t[12] * ORDER_5;
-
-    carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21;
-    carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21;
-    carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21;
-    carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21;
-    carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21;
-    carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21;
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-
-    s[ 0] = (byte)(t[ 0] >>  0);
-    s[ 1] = (byte)(t[ 0] >>  8);
-    s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] <<  5));
-    s[ 3] = (byte)(t[ 1] >>  3);
-    s[ 4] = (byte)(t[ 1] >> 11);
-    s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] <<  2));
-    s[ 6] = (byte)(t[ 2] >>  6);
-    s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] <<  7));
-    s[ 8] = (byte)(t[ 3] >>  1);
-    s[ 9] = (byte)(t[ 3] >>  9);
-    s[10] = (byte)((t[ 3] >> 17) | (t[ 4] <<  4));
-    s[11] = (byte)(t[ 4] >>  4);
-    s[12] = (byte)(t[ 4] >> 12);
-    s[13] = (byte)((t[ 4] >> 20) | (t[ 5] <<  1));
-    s[14] = (byte)(t[ 5] >>  7);
-    s[15] = (byte)((t[ 5] >> 15) | (t[ 6] <<  6));
-    s[16] = (byte)(t[ 6] >>  2);
-    s[17] = (byte)(t[ 6] >> 10);
-    s[18] = (byte)((t[ 6] >> 18) | (t[ 7] <<  3));
-    s[19] = (byte)(t[ 7] >>  5);
-    s[20] = (byte)(t[ 7] >> 13);
-    s[21] = (byte)(t[ 8] >>  0);
-    s[22] = (byte)(t[ 8] >>  8);
-    s[23] = (byte)((t[ 8] >> 16) | (t[ 9] <<  5));
-    s[24] = (byte)(t[ 9] >>  3);
-    s[25] = (byte)(t[ 9] >> 11);
-    s[26] = (byte)((t[ 9] >> 19) | (t[10] <<  2));
-    s[27] = (byte)(t[10] >>  6);
-    s[28] = (byte)((t[10] >> 14) | (t[11] <<  7));
-    s[29] = (byte)(t[11] >>  1);
-    s[30] = (byte)(t[11] >>  9);
-    s[31] = (byte)(t[11] >> 17);
-}
-
-/*
-Input:
-  a[0]+256*a[1]+...+256^31*a[31] = a
-  b[0]+256*b[1]+...+256^31*b[31] = b
-  c[0]+256*c[1]+...+256^31*c[31] = c
-
-Output:
-  s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
-  where l = 2^252 + 27742317777372353535851937790883648493.
-*/
-void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c)
-{
-    uint32_t ad[12], bd[12], cd[12];
-    int64_t t[24];
-    int64_t carry;
-
-    ad[ 0] = MASK_21 & (load_3(a +  0) >> 0);
-    ad[ 1] = MASK_21 & (load_4(a +  2) >> 5);
-    ad[ 2] = MASK_21 & (load_3(a +  5) >> 2);
-    ad[ 3] = MASK_21 & (load_4(a +  7) >> 7);
-    ad[ 4] = MASK_21 & (load_4(a + 10) >> 4);
-    ad[ 5] = MASK_21 & (load_3(a + 13) >> 1);
-    ad[ 6] = MASK_21 & (load_4(a + 15) >> 6);
-    ad[ 7] = MASK_21 & (load_3(a + 18) >> 3);
-    ad[ 8] = MASK_21 & (load_3(a + 21) >> 0);
-    ad[ 9] = MASK_21 & (load_4(a + 23) >> 5);
-    ad[10] = MASK_21 & (load_3(a + 26) >> 2);
-    ad[11] = (uint32_t)(load_4(a + 28) >> 7);
-    bd[ 0] = MASK_21 & (load_3(b +  0) >> 0);
-    bd[ 1] = MASK_21 & (load_4(b +  2) >> 5);
-    bd[ 2] = MASK_21 & (load_3(b +  5) >> 2);
-    bd[ 3] = MASK_21 & (load_4(b +  7) >> 7);
-    bd[ 4] = MASK_21 & (load_4(b + 10) >> 4);
-    bd[ 5] = MASK_21 & (load_3(b + 13) >> 1);
-    bd[ 6] = MASK_21 & (load_4(b + 15) >> 6);
-    bd[ 7] = MASK_21 & (load_3(b + 18) >> 3);
-    bd[ 8] = MASK_21 & (load_3(b + 21) >> 0);
-    bd[ 9] = MASK_21 & (load_4(b + 23) >> 5);
-    bd[10] = MASK_21 & (load_3(b + 26) >> 2);
-    bd[11] = (uint32_t)(load_4(b + 28) >> 7);
-    cd[ 0] = MASK_21 & (load_3(c +  0) >> 0);
-    cd[ 1] = MASK_21 & (load_4(c +  2) >> 5);
-    cd[ 2] = MASK_21 & (load_3(c +  5) >> 2);
-    cd[ 3] = MASK_21 & (load_4(c +  7) >> 7);
-    cd[ 4] = MASK_21 & (load_4(c + 10) >> 4);
-    cd[ 5] = MASK_21 & (load_3(c + 13) >> 1);
-    cd[ 6] = MASK_21 & (load_4(c + 15) >> 6);
-    cd[ 7] = MASK_21 & (load_3(c + 18) >> 3);
-    cd[ 8] = MASK_21 & (load_3(c + 21) >> 0);
-    cd[ 9] = MASK_21 & (load_4(c + 23) >> 5);
-    cd[10] = MASK_21 & (load_3(c + 26) >> 2);
-    cd[11] = (uint32_t)(load_4(c + 28) >> 7);
-
-    t[ 0] = cd[ 0] + (int64_t)ad[ 0] * bd[ 0];
-    t[ 1] = cd[ 1] + (int64_t)ad[ 0] * bd[ 1] + (int64_t)ad[ 1] * bd[ 0];
-    t[ 2] = cd[ 2] + (int64_t)ad[ 0] * bd[ 2] + (int64_t)ad[ 1] * bd[ 1] +
-                     (int64_t)ad[ 2] * bd[ 0];
-    t[ 3] = cd[ 3] + (int64_t)ad[ 0] * bd[ 3] + (int64_t)ad[ 1] * bd[ 2] +
-                     (int64_t)ad[ 2] * bd[ 1] + (int64_t)ad[ 3] * bd[ 0];
-    t[ 4] = cd[ 4] + (int64_t)ad[ 0] * bd[ 4] + (int64_t)ad[ 1] * bd[ 3] +
-                     (int64_t)ad[ 2] * bd[ 2] + (int64_t)ad[ 3] * bd[ 1] +
-                     (int64_t)ad[ 4] * bd[ 0];
-    t[ 5] = cd[ 5] + (int64_t)ad[ 0] * bd[ 5] + (int64_t)ad[ 1] * bd[ 4] +
-                     (int64_t)ad[ 2] * bd[ 3] + (int64_t)ad[ 3] * bd[ 2] +
-                     (int64_t)ad[ 4] * bd[ 1] + (int64_t)ad[ 5] * bd[ 0];
-    t[ 6] = cd[ 6] + (int64_t)ad[ 0] * bd[ 6] + (int64_t)ad[ 1] * bd[ 5] +
-                     (int64_t)ad[ 2] * bd[ 4] + (int64_t)ad[ 3] * bd[ 3] +
-                     (int64_t)ad[ 4] * bd[ 2] + (int64_t)ad[ 5] * bd[ 1] +
-                     (int64_t)ad[ 6] * bd[ 0];
-    t[ 7] = cd[ 7] + (int64_t)ad[ 0] * bd[ 7] + (int64_t)ad[ 1] * bd[ 6] +
-                     (int64_t)ad[ 2] * bd[ 5] + (int64_t)ad[ 3] * bd[ 4] +
-                     (int64_t)ad[ 4] * bd[ 3] + (int64_t)ad[ 5] * bd[ 2] +
-                     (int64_t)ad[ 6] * bd[ 1] + (int64_t)ad[ 7] * bd[ 0];
-    t[ 8] = cd[ 8] + (int64_t)ad[ 0] * bd[ 8] + (int64_t)ad[ 1] * bd[ 7] +
-                     (int64_t)ad[ 2] * bd[ 6] + (int64_t)ad[ 3] * bd[ 5] +
-                     (int64_t)ad[ 4] * bd[ 4] + (int64_t)ad[ 5] * bd[ 3] +
-                     (int64_t)ad[ 6] * bd[ 2] + (int64_t)ad[ 7] * bd[ 1] +
-                     (int64_t)ad[ 8] * bd[ 0];
-    t[ 9] = cd[ 9] + (int64_t)ad[ 0] * bd[ 9] + (int64_t)ad[ 1] * bd[ 8] +
-                     (int64_t)ad[ 2] * bd[ 7] + (int64_t)ad[ 3] * bd[ 6] +
-                     (int64_t)ad[ 4] * bd[ 5] + (int64_t)ad[ 5] * bd[ 4] +
-                     (int64_t)ad[ 6] * bd[ 3] + (int64_t)ad[ 7] * bd[ 2] +
-                     (int64_t)ad[ 8] * bd[ 1] + (int64_t)ad[ 9] * bd[ 0];
-    t[10] = cd[10] + (int64_t)ad[ 0] * bd[10] + (int64_t)ad[ 1] * bd[ 9] +
-                     (int64_t)ad[ 2] * bd[ 8] + (int64_t)ad[ 3] * bd[ 7] +
-                     (int64_t)ad[ 4] * bd[ 6] + (int64_t)ad[ 5] * bd[ 5] +
-                     (int64_t)ad[ 6] * bd[ 4] + (int64_t)ad[ 7] * bd[ 3] +
-                     (int64_t)ad[ 8] * bd[ 2] + (int64_t)ad[ 9] * bd[ 1] +
-                     (int64_t)ad[10] * bd[ 0];
-    t[11] = cd[11] + (int64_t)ad[ 0] * bd[11] + (int64_t)ad[ 1] * bd[10] +
-                     (int64_t)ad[ 2] * bd[ 9] + (int64_t)ad[ 3] * bd[ 8] +
-                     (int64_t)ad[ 4] * bd[ 7] + (int64_t)ad[ 5] * bd[ 6] +
-                     (int64_t)ad[ 6] * bd[ 5] + (int64_t)ad[ 7] * bd[ 4] +
-                     (int64_t)ad[ 8] * bd[ 3] + (int64_t)ad[ 9] * bd[ 2] +
-                     (int64_t)ad[10] * bd[ 1] + (int64_t)ad[11] * bd[ 0];
-    t[12] =          (int64_t)ad[ 1] * bd[11] + (int64_t)ad[ 2] * bd[10] +
-                     (int64_t)ad[ 3] * bd[ 9] + (int64_t)ad[ 4] * bd[ 8] +
-                     (int64_t)ad[ 5] * bd[ 7] + (int64_t)ad[ 6] * bd[ 6] +
-                     (int64_t)ad[ 7] * bd[ 5] + (int64_t)ad[ 8] * bd[ 4] +
-                     (int64_t)ad[ 9] * bd[ 3] + (int64_t)ad[10] * bd[ 2] +
-                     (int64_t)ad[11] * bd[ 1];
-    t[13] =          (int64_t)ad[ 2] * bd[11] + (int64_t)ad[ 3] * bd[10] +
-                     (int64_t)ad[ 4] * bd[ 9] + (int64_t)ad[ 5] * bd[ 8] +
-                     (int64_t)ad[ 6] * bd[ 7] + (int64_t)ad[ 7] * bd[ 6] +
-                     (int64_t)ad[ 8] * bd[ 5] + (int64_t)ad[ 9] * bd[ 4] +
-                     (int64_t)ad[10] * bd[ 3] + (int64_t)ad[11] * bd[ 2];
-    t[14] =          (int64_t)ad[ 3] * bd[11] + (int64_t)ad[ 4] * bd[10] +
-                     (int64_t)ad[ 5] * bd[ 9] + (int64_t)ad[ 6] * bd[ 8] +
-                     (int64_t)ad[ 7] * bd[ 7] + (int64_t)ad[ 8] * bd[ 6] +
-                     (int64_t)ad[ 9] * bd[ 5] + (int64_t)ad[10] * bd[ 4] +
-                     (int64_t)ad[11] * bd[ 3];
-    t[15] =          (int64_t)ad[ 4] * bd[11] + (int64_t)ad[ 5] * bd[10] +
-                     (int64_t)ad[ 6] * bd[ 9] + (int64_t)ad[ 7] * bd[ 8] +
-                     (int64_t)ad[ 8] * bd[ 7] + (int64_t)ad[ 9] * bd[ 6] +
-                     (int64_t)ad[10] * bd[ 5] + (int64_t)ad[11] * bd[ 4];
-    t[16] =          (int64_t)ad[ 5] * bd[11] + (int64_t)ad[ 6] * bd[10] +
-                     (int64_t)ad[ 7] * bd[ 9] + (int64_t)ad[ 8] * bd[ 8] +
-                     (int64_t)ad[ 9] * bd[ 7] + (int64_t)ad[10] * bd[ 6] +
-                     (int64_t)ad[11] * bd[ 5];
-    t[17] =          (int64_t)ad[ 6] * bd[11] + (int64_t)ad[ 7] * bd[10] +
-                     (int64_t)ad[ 8] * bd[ 9] + (int64_t)ad[ 9] * bd[ 8] +
-                     (int64_t)ad[10] * bd[ 7] + (int64_t)ad[11] * bd[ 6];
-    t[18] =          (int64_t)ad[ 7] * bd[11] + (int64_t)ad[ 8] * bd[10] +
-                     (int64_t)ad[ 9] * bd[ 9] + (int64_t)ad[10] * bd[ 8] +
-                     (int64_t)ad[11] * bd[ 7];
-    t[19] =          (int64_t)ad[ 8] * bd[11] + (int64_t)ad[ 9] * bd[10] +
-                     (int64_t)ad[10] * bd[ 9] + (int64_t)ad[11] * bd[ 8];
-    t[20] =          (int64_t)ad[ 9] * bd[11] + (int64_t)ad[10] * bd[10] +
-                     (int64_t)ad[11] * bd[ 9];
-    t[21] =          (int64_t)ad[10] * bd[11] + (int64_t)ad[11] * bd[10];
-    t[22] =          (int64_t)ad[11] * bd[11];
-    t[23] = 0;
-
-    carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21;
-    carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21;
-    carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21;
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-    carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21;
-    carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21;
-    carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21;
-    carry = t[18] >> 21; t[19] += carry; t[18] &= MASK_21;
-    carry = t[20] >> 21; t[21] += carry; t[20] &= MASK_21;
-    carry = t[22] >> 21; t[23] += carry; t[22] &= MASK_21;
-    carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21;
-    carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21;
-    carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21;
-    carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21;
-    carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21;
-    carry = t[17] >> 21; t[18] += carry; t[17] &= MASK_21;
-    carry = t[19] >> 21; t[20] += carry; t[19] &= MASK_21;
-    carry = t[21] >> 21; t[22] += carry; t[21] &= MASK_21;
-
-    t[11] -= t[23] * ORDER_0;
-    t[12] -= t[23] * ORDER_1;
-    t[13] -= t[23] * ORDER_2;
-    t[14] -= t[23] * ORDER_3;
-    t[15] -= t[23] * ORDER_4;
-    t[16] -= t[23] * ORDER_5;
-
-    t[10] -= t[22] * ORDER_0;
-    t[11] -= t[22] * ORDER_1;
-    t[12] -= t[22] * ORDER_2;
-    t[13] -= t[22] * ORDER_3;
-    t[14] -= t[22] * ORDER_4;
-    t[15] -= t[22] * ORDER_5;
-
-    t[ 9] -= t[21] * ORDER_0;
-    t[10] -= t[21] * ORDER_1;
-    t[11] -= t[21] * ORDER_2;
-    t[12] -= t[21] * ORDER_3;
-    t[13] -= t[21] * ORDER_4;
-    t[14] -= t[21] * ORDER_5;
-
-    t[ 8] -= t[20] * ORDER_0;
-    t[ 9] -= t[20] * ORDER_1;
-    t[10] -= t[20] * ORDER_2;
-    t[11] -= t[20] * ORDER_3;
-    t[12] -= t[20] * ORDER_4;
-    t[13] -= t[20] * ORDER_5;
-
-    t[ 7] -= t[19] * ORDER_0;
-    t[ 8] -= t[19] * ORDER_1;
-    t[ 9] -= t[19] * ORDER_2;
-    t[10] -= t[19] * ORDER_3;
-    t[11] -= t[19] * ORDER_4;
-    t[12] -= t[19] * ORDER_5;
-
-    t[ 6] -= t[18] * ORDER_0;
-    t[ 7] -= t[18] * ORDER_1;
-    t[ 8] -= t[18] * ORDER_2;
-    t[ 9] -= t[18] * ORDER_3;
-    t[10] -= t[18] * ORDER_4;
-    t[11] -= t[18] * ORDER_5;
-
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-    carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21;
-    carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21;
-    carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21;
-    carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21;
-    carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21;
-
-    t[ 5] -= t[17] * ORDER_0;
-    t[ 6] -= t[17] * ORDER_1;
-    t[ 7] -= t[17] * ORDER_2;
-    t[ 8] -= t[17] * ORDER_3;
-    t[ 9] -= t[17] * ORDER_4;
-    t[10] -= t[17] * ORDER_5;
-
-    t[ 4] -= t[16] * ORDER_0;
-    t[ 5] -= t[16] * ORDER_1;
-    t[ 6] -= t[16] * ORDER_2;
-    t[ 7] -= t[16] * ORDER_3;
-    t[ 8] -= t[16] * ORDER_4;
-    t[ 9] -= t[16] * ORDER_5;
-
-    t[ 3] -= t[15] * ORDER_0;
-    t[ 4] -= t[15] * ORDER_1;
-    t[ 5] -= t[15] * ORDER_2;
-    t[ 6] -= t[15] * ORDER_3;
-    t[ 7] -= t[15] * ORDER_4;
-    t[ 8] -= t[15] * ORDER_5;
-
-    t[ 2] -= t[14] * ORDER_0;
-    t[ 3] -= t[14] * ORDER_1;
-    t[ 4] -= t[14] * ORDER_2;
-    t[ 5] -= t[14] * ORDER_3;
-    t[ 6] -= t[14] * ORDER_4;
-    t[ 7] -= t[14] * ORDER_5;
-
-    t[ 1] -= t[13] * ORDER_0;
-    t[ 2] -= t[13] * ORDER_1;
-    t[ 3] -= t[13] * ORDER_2;
-    t[ 4] -= t[13] * ORDER_3;
-    t[ 5] -= t[13] * ORDER_4;
-    t[ 6] -= t[13] * ORDER_5;
-
-    t[ 0] -= t[12] * ORDER_0;
-    t[ 1] -= t[12] * ORDER_1;
-    t[ 2] -= t[12] * ORDER_2;
-    t[ 3] -= t[12] * ORDER_3;
-    t[ 4] -= t[12] * ORDER_4;
-    t[ 5] -= t[12] * ORDER_5;
-    t[12]  = 0;
-
-    carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21;
-    carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21;
-    carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21;
-    carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21;
-    carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21;
-    carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21;
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-    carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21;
-
-    t[ 0] -= t[12] * ORDER_0;
-    t[ 1] -= t[12] * ORDER_1;
-    t[ 2] -= t[12] * ORDER_2;
-    t[ 3] -= t[12] * ORDER_3;
-    t[ 4] -= t[12] * ORDER_4;
-    t[ 5] -= t[12] * ORDER_5;
-
-    carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21;
-    carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21;
-    carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21;
-    carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21;
-    carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21;
-    carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21;
-    carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21;
-    carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21;
-    carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21;
-    carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21;
-    carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21;
-
-    s[ 0] = (byte)(t[ 0] >>  0);
-    s[ 1] = (byte)(t[ 0] >>  8);
-    s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] <<  5));
-    s[ 3] = (byte)(t[ 1] >>  3);
-    s[ 4] = (byte)(t[ 1] >> 11);
-    s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] <<  2));
-    s[ 6] = (byte)(t[ 2] >>  6);
-    s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] <<  7));
-    s[ 8] = (byte)(t[ 3] >>  1);
-    s[ 9] = (byte)(t[ 3] >>  9);
-    s[10] = (byte)((t[ 3] >> 17) | (t[ 4] <<  4));
-    s[11] = (byte)(t[ 4] >>  4);
-    s[12] = (byte)(t[ 4] >> 12);
-    s[13] = (byte)((t[ 4] >> 20) | (t[ 5] <<  1));
-    s[14] = (byte)(t[ 5] >>  7);
-    s[15] = (byte)((t[ 5] >> 15) | (t[ 6] <<  6));
-    s[16] = (byte)(t[ 6] >>  2);
-    s[17] = (byte)(t[ 6] >> 10);
-    s[18] = (byte)((t[ 6] >> 18) | (t[ 7] <<  3));
-    s[19] = (byte)(t[ 7] >>  5);
-    s[20] = (byte)(t[ 7] >> 13);
-    s[21] = (byte)(t[ 8] >>  0);
-    s[22] = (byte)(t[ 8] >>  8);
-    s[23] = (byte)((t[ 8] >> 16) | (t[ 9] <<  5));
-    s[24] = (byte)(t[ 9] >>  3);
-    s[25] = (byte)(t[ 9] >> 11);
-    s[26] = (byte)((t[ 9] >> 19) | (t[10] <<  2));
-    s[27] = (byte)(t[10] >>  6);
-    s[28] = (byte)((t[10] >> 14) | (t[11] <<  7));
-    s[29] = (byte)(t[11] >>  1);
-    s[30] = (byte)(t[11] >>  9);
-    s[31] = (byte)(t[11] >> 17);
-}
-#else
-static uint64_t load_6(const byte* a)
-{
-    uint64_t n;
-    n = ((uint64_t)a[0] <<  0) |
-        ((uint64_t)a[1] <<  8) |
-        ((uint64_t)a[2] << 16) |
-        ((uint64_t)a[3] << 24) |
-        ((uint64_t)a[4] << 32) |
-        ((uint64_t)a[5] << 40);
-    return n;
-}
-
-static uint64_t load_7(const byte* a)
-{
-    uint64_t n;
-    n = ((uint64_t)a[0] <<  0) |
-        ((uint64_t)a[1] <<  8) |
-        ((uint64_t)a[2] << 16) |
-        ((uint64_t)a[3] << 24) |
-        ((uint64_t)a[4] << 32) |
-        ((uint64_t)a[5] << 40) |
-        ((uint64_t)a[6] << 48);
-    return n;
-}
-
-#define MASK_42     0x3ffffffffffl
-#define ORDER_0     0x31a5cf5d3edl
-#define ORDER_1     0x1e735960498l
-#define ORDER_2     0x14def9dea2fl
-
-/*
-Input:
-  s[0]+256*s[1]+...+256^63*s[63] = s
-
-Output:
-  s[0]+256*s[1]+...+256^31*s[31] = s mod l
-  where l = 2^252 + 27742317777372353535851937790883648493.
-  Overwrites s in place.
-*/
-void sc_reduce(byte* s)
-{
-    __int128_t t[12];
-    __int128_t carry;
-
-    t[ 0] = MASK_42 & (load_6(s +  0) >> 0);
-    t[ 1] = MASK_42 & (load_6(s +  5) >> 2);
-    t[ 2] = MASK_42 & (load_6(s + 10) >> 4);
-    t[ 3] = MASK_42 & (load_6(s + 15) >> 6);
-    t[ 4] = MASK_42 & (load_6(s + 21) >> 0);
-    t[ 5] = MASK_42 & (load_6(s + 26) >> 2);
-    t[ 6] = MASK_42 & (load_6(s + 31) >> 4);
-    t[ 7] = MASK_42 & (load_6(s + 36) >> 6);
-    t[ 8] = MASK_42 & (load_6(s + 42) >> 0);
-    t[ 9] = MASK_42 & (load_6(s + 47) >> 2);
-    t[10] = MASK_42 & (load_6(s + 52) >> 4);
-    t[11] =           (load_7(s + 57) >> 6);
-
-    t[ 5] -= t[11] * ORDER_0;
-    t[ 6] -= t[11] * ORDER_1;
-    t[ 7] -= t[11] * ORDER_2;
-
-    t[ 4] -= t[10] * ORDER_0;
-    t[ 5] -= t[10] * ORDER_1;
-    t[ 6] -= t[10] * ORDER_2;
-
-    t[ 3] -= t[ 9] * ORDER_0;
-    t[ 4] -= t[ 9] * ORDER_1;
-    t[ 5] -= t[ 9] * ORDER_2;
-
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42;
-    carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-    carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42;
-
-    t[ 2] -= t[ 8] * ORDER_0;
-    t[ 3] -= t[ 8] * ORDER_1;
-    t[ 4] -= t[ 8] * ORDER_2;
-
-    t[ 1] -= t[ 7] * ORDER_0;
-    t[ 2] -= t[ 7] * ORDER_1;
-    t[ 3] -= t[ 7] * ORDER_2;
-
-    t[ 0] -= t[ 6] * ORDER_0;
-    t[ 1] -= t[ 6] * ORDER_1;
-    t[ 2] -= t[ 6] * ORDER_2;
-    t[ 6]  = 0;
-
-    carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42;
-    carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42;
-    carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42;
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-    carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42;
-
-    t[ 0] -= t[ 6] * ORDER_0;
-    t[ 1] -= t[ 6] * ORDER_1;
-    t[ 2] -= t[ 6] * ORDER_2;
-
-    carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42;
-    carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42;
-    carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42;
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-
-    s[ 0] = (t[ 0] >>  0);
-    s[ 1] = (t[ 0] >>  8);
-    s[ 2] = (t[ 0] >> 16);
-    s[ 3] = (t[ 0] >> 24);
-    s[ 4] = (t[ 0] >> 32);
-    s[ 5] = (t[ 0] >> 40) | (t[ 1] <<  2);
-    s[ 6] = (t[ 1] >>  6);
-    s[ 7] = (t[ 1] >> 14);
-    s[ 8] = (t[ 1] >> 22);
-    s[ 9] = (t[ 1] >> 30);
-    s[10] = (t[ 1] >> 38) | (t[ 2] <<  4);
-    s[11] = (t[ 2] >>  4);
-    s[12] = (t[ 2] >> 12);
-    s[13] = (t[ 2] >> 20);
-    s[14] = (t[ 2] >> 28);
-    s[15] = (t[ 2] >> 36) | (t[ 3] <<  6);
-    s[16] = (t[ 3] >>  2);
-    s[17] = (t[ 3] >> 10);
-    s[18] = (t[ 3] >> 18);
-    s[19] = (t[ 3] >> 26);
-    s[20] = (t[ 3] >> 34);
-    s[21] = (t[ 4] >>  0);
-    s[22] = (t[ 4] >>  8);
-    s[23] = (t[ 4] >> 16);
-    s[24] = (t[ 4] >> 24);
-    s[25] = (t[ 4] >> 32);
-    s[26] = (t[ 4] >> 40) | (t[ 5] <<  2);
-    s[27] = (t[ 5] >>  6);
-    s[28] = (t[ 5] >> 14);
-    s[29] = (t[ 5] >> 22);
-    s[30] = (t[ 5] >> 30);
-    s[31] = (t[ 5] >> 38);
-}
-
-/*
-Input:
-  a[0]+256*a[1]+...+256^31*a[31] = a
-  b[0]+256*b[1]+...+256^31*b[31] = b
-  c[0]+256*c[1]+...+256^31*c[31] = c
-
-Output:
-  s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
-  where l = 2^252 + 27742317777372353535851937790883648493.
-*/
-void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c)
-{
-    uint64_t ad[6], bd[6], cd[6];
-    __int128_t t[12];
-    __int128_t carry;
-
-    ad[ 0] = MASK_42 & (load_6(a +  0) >> 0);
-    ad[ 1] = MASK_42 & (load_6(a +  5) >> 2);
-    ad[ 2] = MASK_42 & (load_6(a + 10) >> 4);
-    ad[ 3] = MASK_42 & (load_6(a + 15) >> 6);
-    ad[ 4] = MASK_42 & (load_6(a + 21) >> 0);
-    ad[ 5] =           (load_6(a + 26) >> 2);
-    bd[ 0] = MASK_42 & (load_6(b +  0) >> 0);
-    bd[ 1] = MASK_42 & (load_6(b +  5) >> 2);
-    bd[ 2] = MASK_42 & (load_6(b + 10) >> 4);
-    bd[ 3] = MASK_42 & (load_6(b + 15) >> 6);
-    bd[ 4] = MASK_42 & (load_6(b + 21) >> 0);
-    bd[ 5] =           (load_6(b + 26) >> 2);
-    cd[ 0] = MASK_42 & (load_6(c +  0) >> 0);
-    cd[ 1] = MASK_42 & (load_6(c +  5) >> 2);
-    cd[ 2] = MASK_42 & (load_6(c + 10) >> 4);
-    cd[ 3] = MASK_42 & (load_6(c + 15) >> 6);
-    cd[ 4] = MASK_42 & (load_6(c + 21) >> 0);
-    cd[ 5] =           (load_6(c + 26) >> 2);
-
-    t[ 0] = cd[ 0] + (__int128_t)ad[ 0] * bd[ 0];
-    t[ 1] = cd[ 1] + (__int128_t)ad[ 0] * bd[ 1] + (__int128_t)ad[ 1] * bd[ 0];
-    t[ 2] = cd[ 2] + (__int128_t)ad[ 0] * bd[ 2] + (__int128_t)ad[ 1] * bd[ 1] +
-                     (__int128_t)ad[ 2] * bd[ 0];
-    t[ 3] = cd[ 3] + (__int128_t)ad[ 0] * bd[ 3] + (__int128_t)ad[ 1] * bd[ 2] +
-                     (__int128_t)ad[ 2] * bd[ 1] + (__int128_t)ad[ 3] * bd[ 0];
-    t[ 4] = cd[ 4] + (__int128_t)ad[ 0] * bd[ 4] + (__int128_t)ad[ 1] * bd[ 3] +
-                     (__int128_t)ad[ 2] * bd[ 2] + (__int128_t)ad[ 3] * bd[ 1] +
-                     (__int128_t)ad[ 4] * bd[ 0];
-    t[ 5] = cd[ 5] + (__int128_t)ad[ 0] * bd[ 5] + (__int128_t)ad[ 1] * bd[ 4] +
-                     (__int128_t)ad[ 2] * bd[ 3] + (__int128_t)ad[ 3] * bd[ 2] +
-                     (__int128_t)ad[ 4] * bd[ 1] + (__int128_t)ad[ 5] * bd[ 0];
-    t[ 6] =          (__int128_t)ad[ 1] * bd[ 5] + (__int128_t)ad[ 2] * bd[ 4] +
-                     (__int128_t)ad[ 3] * bd[ 3] + (__int128_t)ad[ 4] * bd[ 2] +
-                     (__int128_t)ad[ 5] * bd[ 1];
-    t[ 7] =          (__int128_t)ad[ 2] * bd[ 5] + (__int128_t)ad[ 3] * bd[ 4] +
-                     (__int128_t)ad[ 4] * bd[ 3] + (__int128_t)ad[ 5] * bd[ 2];
-    t[ 8] =          (__int128_t)ad[ 3] * bd[ 5] + (__int128_t)ad[ 4] * bd[ 4] +
-                     (__int128_t)ad[ 5] * bd[ 3];
-    t[ 9] =          (__int128_t)ad[ 4] * bd[ 5] + (__int128_t)ad[ 5] * bd[ 4];
-    t[10] =          (__int128_t)ad[ 5] * bd[ 5];
-    t[11] = 0;
-
-    carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42;
-    carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-    carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42;
-    carry = t[ 8] >> 42; t[ 9] += carry; t[ 8] &= MASK_42;
-    carry = t[10] >> 42; t[11] += carry; t[10] &= MASK_42;
-    carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42;
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42;
-    carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42;
-    carry = t[ 9] >> 42; t[10] += carry; t[ 9] &= MASK_42;
-
-    t[ 5] -= t[11] * ORDER_0;
-    t[ 6] -= t[11] * ORDER_1;
-    t[ 7] -= t[11] * ORDER_2;
-
-    t[ 4] -= t[10] * ORDER_0;
-    t[ 5] -= t[10] * ORDER_1;
-    t[ 6] -= t[10] * ORDER_2;
-
-    t[ 3] -= t[ 9] * ORDER_0;
-    t[ 4] -= t[ 9] * ORDER_1;
-    t[ 5] -= t[ 9] * ORDER_2;
-
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42;
-    carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-    carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42;
-
-    t[ 2] -= t[ 8] * ORDER_0;
-    t[ 3] -= t[ 8] * ORDER_1;
-    t[ 4] -= t[ 8] * ORDER_2;
-
-    t[ 1] -= t[ 7] * ORDER_0;
-    t[ 2] -= t[ 7] * ORDER_1;
-    t[ 3] -= t[ 7] * ORDER_2;
-
-    t[ 0] -= t[ 6] * ORDER_0;
-    t[ 1] -= t[ 6] * ORDER_1;
-    t[ 2] -= t[ 6] * ORDER_2;
-    t[ 6]  = 0;
-
-    carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42;
-    carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42;
-    carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42;
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-    carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42;
-
-    t[ 0] -= t[ 6] * ORDER_0;
-    t[ 1] -= t[ 6] * ORDER_1;
-    t[ 2] -= t[ 6] * ORDER_2;
-
-    carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42;
-    carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42;
-    carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42;
-    carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42;
-    carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42;
-
-    s[ 0] = (t[ 0] >>  0);
-    s[ 1] = (t[ 0] >>  8);
-    s[ 2] = (t[ 0] >> 16);
-    s[ 3] = (t[ 0] >> 24);
-    s[ 4] = (t[ 0] >> 32);
-    s[ 5] = (t[ 0] >> 40) | (t[ 1] <<  2);
-    s[ 6] = (t[ 1] >>  6);
-    s[ 7] = (t[ 1] >> 14);
-    s[ 8] = (t[ 1] >> 22);
-    s[ 9] = (t[ 1] >> 30);
-    s[10] = (t[ 1] >> 38) | (t[ 2] <<  4);
-    s[11] = (t[ 2] >>  4);
-    s[12] = (t[ 2] >> 12);
-    s[13] = (t[ 2] >> 20);
-    s[14] = (t[ 2] >> 28);
-    s[15] = (t[ 2] >> 36) | (t[ 3] <<  6);
-    s[16] = (t[ 3] >>  2);
-    s[17] = (t[ 3] >> 10);
-    s[18] = (t[ 3] >> 18);
-    s[19] = (t[ 3] >> 26);
-    s[20] = (t[ 3] >> 34);
-    s[21] = (t[ 4] >>  0);
-    s[22] = (t[ 4] >>  8);
-    s[23] = (t[ 4] >> 16);
-    s[24] = (t[ 4] >> 24);
-    s[25] = (t[ 4] >> 32);
-    s[26] = (t[ 4] >> 40) | (t[ 5] <<  2);
-    s[27] = (t[ 5] >>  6);
-    s[28] = (t[ 5] >> 14);
-    s[29] = (t[ 5] >> 22);
-    s[30] = (t[ 5] >> 30);
-    s[31] = (t[ 5] >> 38);
-}
-#endif /* !HAVE___UINT128_T || NO_CURVED25519_128BIT */
-
-int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz)
-{
-    ge     x,y,z;
-    ge_p3  g;
-    byte   bArray[ED25519_KEY_SIZE];
-    word32 i;
-
-    fe_0(x);
-    fe_0(y);
-    fe_1(z);
-    fe_frombytes(x, xIn);
-    fe_frombytes(y, yIn);
-
-    fe_copy(g.X, x);
-    fe_copy(g.Y, y);
-    fe_copy(g.Z, z);
-
-    ge_p3_tobytes(bArray, &g);
-
-    for (i = 0; i < keySz; i++) {
-        out[keySz - 1 - i] = bArray[i];
-    }
-
-    return 0;
-}
-
-
-/*
-r = p + q
-*/
-static WC_INLINE void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
-{
-#ifndef CURVED25519_X64
-    ge t0;
-    fe_add(r->X,p->Y,p->X);
-    fe_sub(r->Y,p->Y,p->X);
-    fe_mul(r->Z,r->X,q->YplusX);
-    fe_mul(r->Y,r->Y,q->YminusX);
-    fe_mul(r->T,q->T2d,p->T);
-    fe_mul(r->X,p->Z,q->Z);
-    fe_add(t0,r->X,r->X);
-    fe_sub(r->X,r->Z,r->Y);
-    fe_add(r->Y,r->Z,r->Y);
-    fe_add(r->Z,t0,r->T);
-    fe_sub(r->T,t0,r->T);
-#else
-    fe_ge_add(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d,
-              q->YplusX, q->YminusX);
-#endif
-}
-
-
-#ifndef CURVED25519_X64
-/* ge_scalar mult base */
-static unsigned char equal(signed char b,signed char c)
-{
-  unsigned char ub = b;
-  unsigned char uc = c;
-  unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
-  uint32_t y = x; /* 0: yes; 1..255: no */
-  y -= 1; /* 4294967295: yes; 0..254: no */
-  y >>= 31; /* 1: yes; 0: no */
-  return (unsigned char)y;
-}
-
-
-static unsigned char negative(signed char b)
-{
-  return ((unsigned char)b) >> 7;
-}
-
-
-static WC_INLINE void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b,
-                        unsigned char n)
-{
-  b = equal(b,n);
-  fe_cmov(t->yplusx,u->yplusx,b);
-  fe_cmov(t->yminusx,u->yminusx,b);
-  fe_cmov(t->xy2d,u->xy2d,b);
-}
-#endif
-
-#ifdef CURVED25519_X64
-static const ge_precomp base[64][8] = {
-{
-    {
-        { 0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65 },
-        { 0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267 },
-        { 0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca }
-    },
-    {
-        { 0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e },
-        { 0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555 },
-        { 0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8 }
-    },
-    {
-        { 0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4 },
-        { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62 },
-        { 0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21 }
-    },
-    {
-        { 0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727 },
-        { 0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a },
-        { 0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18 }
-    },
-    {
-        { 0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb },
-        { 0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3 },
-        { 0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98 }
-    },
-    {
-        { 0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd },
-        { 0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884 },
-        { 0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f }
-    },
-    {
-        { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e },
-        { 0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0 },
-        { 0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37 }
-    },
-    {
-        { 0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f },
-        { 0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3 },
-        { 0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2 }
-    },
-},
-{
-    {
-        { 0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61 },
-        { 0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883 },
-        { 0x9f867c7d968acaab, 0x5f54258e27092729, 0xd0a7d34bea180975, 0x21b546a3374126e1 }
-    },
-    {
-        { 0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965 },
-        { 0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371 },
-        { 0x66b2a496ce5b67f3, 0xff5492d8bd569796, 0x503cec294a592cd0, 0x566943650813acb2 }
-    },
-    {
-        { 0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275 },
-        { 0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4 },
-        { 0xd3a644a6df648437, 0x703b6559880fbfdd, 0xcb852540ad3a1aa5, 0x0900b3f78e4c6468 }
-    },
-    {
-        { 0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c },
-        { 0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714 },
-        { 0xd560005efbf0bcad, 0x8eb70f2ed1870c5e, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670 }
-    },
-    {
-        { 0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181 },
-        { 0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a },
-        { 0x478904d5a04df8f2, 0xfafbae4ab10142d3, 0xf6c8ac63555d0998, 0x5aac4a412f90b104 }
-    },
-    {
-        { 0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235 },
-        { 0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2 },
-        { 0x32e8386475f3d743, 0x365b8baf6ae5d9ef, 0x825238b6385b681e, 0x234929c1167d65e1 }
-    },
-    {
-        { 0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee },
-        { 0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a },
-        { 0xd3add725225ccf62, 0x911a3381b2152c5d, 0xd8b39fad5b08f87d, 0x6f05606b4799fe3b }
-    },
-    {
-        { 0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8 },
-        { 0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8 },
-        { 0xe9ecf2ed0cf86c18, 0xb46d06120735dfd4, 0xbc9da09804b96be7, 0x73e2e62fd96dc26b }
-    },
-},
-{
-    {
-        { 0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39 },
-        { 0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9 },
-        { 0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0 }
-    },
-    {
-        { 0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef },
-        { 0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09 },
-        { 0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c }
-    },
-    {
-        { 0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a },
-        { 0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9 },
-        { 0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c }
-    },
-    {
-        { 0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e },
-        { 0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173 },
-        { 0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04 }
-    },
-    {
-        { 0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c },
-        { 0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999 },
-        { 0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56 }
-    },
-    {
-        { 0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4 },
-        { 0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced },
-        { 0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6 }
-    },
-    {
-        { 0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8 },
-        { 0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f },
-        { 0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151 }
-    },
-    {
-        { 0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a },
-        { 0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3 },
-        { 0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213 }
-    },
-},
-{
-    {
-        { 0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362 },
-        { 0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2 },
-        { 0x2ac519c10d14a954, 0xeaf474b494b5fa90, 0xe6af8382a9f87a5a, 0x0dea6db1879be094 }
-    },
-    {
-        { 0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb },
-        { 0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd },
-        { 0x52151362793408cf, 0xeb0f170319963d94, 0xa833b2fa883d9466, 0x093a7fa775003c78 }
-    },
-    {
-        { 0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e },
-        { 0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403 },
-        { 0x9ed919d5d36990f3, 0x5213aebbdb4eb9f2, 0xc708ea054cb99135, 0x58ded57f72260e56 }
-    },
-    {
-        { 0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143 },
-        { 0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c },
-        { 0x97da2f25b6c88de9, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5 }
-    },
-    {
-        { 0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0 },
-        { 0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96 },
-        { 0x560a2cd687dce6ca, 0x7f3568c48664cf4d, 0x8741e95222803a38, 0x483bdab1595653fc }
-    },
-    {
-        { 0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a },
-        { 0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe },
-        { 0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840 }
-    },
-    {
-        { 0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a },
-        { 0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965 },
-        { 0xe9eb02c4db31f67f, 0xed25fd8910bcfb2b, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce }
-    },
-    {
-        { 0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717 },
-        { 0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9 },
-        { 0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990 }
-    },
-},
-{
-    {
-        { 0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d },
-        { 0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7 },
-        { 0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464 }
-    },
-    {
-        { 0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030 },
-        { 0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2 },
-        { 0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80 }
-    },
-    {
-        { 0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9 },
-        { 0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4 },
-        { 0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b }
-    },
-    {
-        { 0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481 },
-        { 0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5 },
-        { 0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8 }
-    },
-    {
-        { 0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b },
-        { 0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb },
-        { 0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf }
-    },
-    {
-        { 0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b },
-        { 0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74 },
-        { 0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6 }
-    },
-    {
-        { 0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3 },
-        { 0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29 },
-        { 0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc }
-    },
-    {
-        { 0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c },
-        { 0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83 },
-        { 0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2 }
-    },
-},
-{
-    {
-        { 0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47 },
-        { 0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed },
-        { 0xb90829bf7971877a, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5 }
-    },
-    {
-        { 0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282 },
-        { 0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd },
-        { 0xb917c952583c0a58, 0x653ff9b80fe4c6f3, 0x9b0da7d7bcdf3c0c, 0x43a0eeb6ab54d60e }
-    },
-    {
-        { 0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc },
-        { 0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92 },
-        { 0xdd0edc8bd6f2fb3c, 0x54c63aa79cc7b7a0, 0xae0b032b2c8d9f1a, 0x6f9ce107602967fb }
-    },
-    {
-        { 0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9 },
-        { 0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e },
-        { 0x315d5c75b4b27526, 0xcccb842d0236daa5, 0x22f0c8a3345fee8e, 0x73975a617d39dbed }
-    },
-    {
-        { 0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d },
-        { 0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a },
-        { 0x9071d9132b6beb2f, 0x0f26e9ad28418247, 0xeab91ec9bdec925d, 0x4be65bc8f48af2de }
-    },
-    {
-        { 0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e },
-        { 0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b },
-        { 0xdb3ee00943bfb210, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938 }
-    },
-    {
-        { 0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8 },
-        { 0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784 },
-        { 0x65bd1bea70f801de, 0x1befb7c0fe49e28a, 0xa86306cdb1b2ae4a, 0x3b7ac0cd265c2a09 }
-    },
-    {
-        { 0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992 },
-        { 0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b },
-        { 0xdf3d134da980f971, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e }
-    },
-},
-{
-    {
-        { 0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9 },
-        { 0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d },
-        { 0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf }
-    },
-    {
-        { 0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a },
-        { 0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785 },
-        { 0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823 }
-    },
-    {
-        { 0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5 },
-        { 0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee },
-        { 0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790 }
-    },
-    {
-        { 0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068 },
-        { 0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7 },
-        { 0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375 }
-    },
-    {
-        { 0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252 },
-        { 0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a },
-        { 0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76 }
-    },
-    {
-        { 0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b },
-        { 0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21 },
-        { 0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111 }
-    },
-    {
-        { 0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445 },
-        { 0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40 },
-        { 0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c }
-    },
-    {
-        { 0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245 },
-        { 0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4 },
-        { 0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6 }
-    },
-},
-{
-    {
-        { 0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f },
-        { 0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81 },
-        { 0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d }
-    },
-    {
-        { 0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b },
-        { 0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c },
-        { 0xdb20ba0fb8b6b7ff, 0xb732c3b677511fa1, 0xa92b51c099f02d89, 0x4f3875ad489ca5f1 }
-    },
-    {
-        { 0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5 },
-        { 0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081 },
-        { 0xd0959fe9a8cf8819, 0xd0a995508475a99c, 0x6eac173320b09cc5, 0x628ecf04331b1095 }
-    },
-    {
-        { 0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f },
-        { 0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d },
-        { 0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, 0xa17aa1752ff8f5ed, 0x11ded9020e01fdc0 }
-    },
-    {
-        { 0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec },
-        { 0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f },
-        { 0x17d2fb3d86502d7a, 0xb564d84450a69352, 0x7da962c8a60ed75d, 0x00d0f85b318736aa }
-    },
-    {
-        { 0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd },
-        { 0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33 },
-        { 0x81894b4d4a52a9a8, 0xadd93e12f6b8832f, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd }
-    },
-    {
-        { 0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b },
-        { 0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa },
-        { 0x9e630d2c7f191ee4, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5 }
-    },
-    {
-        { 0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4 },
-        { 0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6 },
-        { 0xbbf2b1a072d27ca2, 0xbf393c59fbdec704, 0xe98dbbcee262b81e, 0x02eebd0b3029b589 }
-    },
-},
-{
-    {
-        { 0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c },
-        { 0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0 },
-        { 0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366 }
-    },
-    {
-        { 0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff },
-        { 0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943 },
-        { 0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812 }
-    },
-    {
-        { 0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b },
-        { 0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab },
-        { 0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd }
-    },
-    {
-        { 0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9 },
-        { 0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1 },
-        { 0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e }
-    },
-    {
-        { 0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e },
-        { 0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840 },
-        { 0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272 }
-    },
-    {
-        { 0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4 },
-        { 0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5 },
-        { 0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab }
-    },
-    {
-        { 0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447 },
-        { 0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b },
-        { 0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494 }
-    },
-    {
-        { 0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8 },
-        { 0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3 },
-        { 0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03 }
-    },
-},
-{
-    {
-        { 0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510 },
-        { 0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79 },
-        { 0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5 }
-    },
-    {
-        { 0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb },
-        { 0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9 },
-        { 0xd87823cd319e0780, 0xefc4cfc1897775c5, 0x4854fb129a0ab3f7, 0x12c49d417238c371 }
-    },
-    {
-        { 0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9 },
-        { 0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4 },
-        { 0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, 0xadba5e0c0b3eb9dc, 0x2ab5504448a49ce3 }
-    },
-    {
-        { 0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d },
-        { 0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f },
-        { 0x6409e759d6722c41, 0xa674e1cf72bf729b, 0xbc0a24eb3c21e569, 0x390167d24ebacb23 }
-    },
-    {
-        { 0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69 },
-        { 0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d },
-        { 0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287 }
-    },
-    {
-        { 0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855 },
-        { 0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d },
-        { 0x9444bb31fcfd863a, 0x2fe3690a3e4e48c5, 0xdc29c867d088fa25, 0x13bd1e38d173292e }
-    },
-    {
-        { 0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd },
-        { 0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0 },
-        { 0x3630dfa1b802a6b0, 0x880f874742ad3bd5, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9 }
-    },
-    {
-        { 0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2 },
-        { 0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49 },
-        { 0x8b64b59d83034f45, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b }
-    },
-},
-{
-    {
-        { 0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108 },
-        { 0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1 },
-        { 0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233 }
-    },
-    {
-        { 0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7 },
-        { 0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d },
-        { 0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307 }
-    },
-    {
-        { 0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44 },
-        { 0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53 },
-        { 0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6 }
-    },
-    {
-        { 0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd },
-        { 0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355 },
-        { 0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80 }
-    },
-    {
-        { 0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7 },
-        { 0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304 },
-        { 0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da }
-    },
-    {
-        { 0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784 },
-        { 0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2 },
-        { 0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c }
-    },
-    {
-        { 0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472 },
-        { 0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7 },
-        { 0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17 }
-    },
-    {
-        { 0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5 },
-        { 0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4 },
-        { 0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2 }
-    },
-},
-{
-    {
-        { 0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a },
-        { 0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286 },
-        { 0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5 }
-    },
-    {
-        { 0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68 },
-        { 0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0 },
-        { 0x7d531574028c2705, 0x80317d69db0d75fe, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998 }
-    },
-    {
-        { 0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef },
-        { 0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa },
-        { 0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c }
-    },
-    {
-        { 0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3 },
-        { 0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d },
-        { 0xf9c2414a695aa3eb, 0xdaa42c4c05a68f21, 0x7c6c23987f93963e, 0x210e8cd30c3954e3 }
-    },
-    {
-        { 0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91 },
-        { 0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742 },
-        { 0xfff5fb4bcf535119, 0xf4989d79df1108a0, 0xbdfcea659a3ba325, 0x18a11f1174d1a6f2 }
-    },
-    {
-        { 0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85 },
-        { 0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1 },
-        { 0x24751021cb8ab5e7, 0xfc2344495c5010eb, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5 }
-    },
-    {
-        { 0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae },
-        { 0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f },
-        { 0xe305ca72eb7ef68a, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd }
-    },
-    {
-        { 0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81 },
-        { 0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223 },
-        { 0xa6c5a71349b7d94b, 0xa3f3d15823eb9446, 0x0416fbd277484834, 0x69d45e6f2c70812f }
-    },
-},
-{
-    {
-        { 0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93 },
-        { 0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908 },
-        { 0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3 }
-    },
-    {
-        { 0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c },
-        { 0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e },
-        { 0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808 }
-    },
-    {
-        { 0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8 },
-        { 0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22 },
-        { 0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969 }
-    },
-    {
-        { 0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10 },
-        { 0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea },
-        { 0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba }
-    },
-    {
-        { 0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c },
-        { 0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03 },
-        { 0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92 }
-    },
-    {
-        { 0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9 },
-        { 0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a },
-        { 0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa }
-    },
-    {
-        { 0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9 },
-        { 0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7 },
-        { 0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a }
-    },
-    {
-        { 0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c },
-        { 0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42 },
-        { 0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3 }
-    },
-},
-{
-    {
-        { 0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4 },
-        { 0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72 },
-        { 0xae9ab553bf6aa310, 0x050a50a9806d6e1b, 0x92bb7403adff5139, 0x0394d27645be618b }
-    },
-    {
-        { 0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee },
-        { 0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743 },
-        { 0xcd8a8ea61195dd75, 0xa504d8a81dd9a82f, 0x540dca81a35879b6, 0x60dd16a379c86a8a }
-    },
-    {
-        { 0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a },
-        { 0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685 },
-        { 0xc8d4ac04516ab786, 0x595af3215295b23d, 0xd6edd234db0230c1, 0x0929efe8825b41cc }
-    },
-    {
-        { 0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f },
-        { 0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c },
-        { 0xd2918da78159a59c, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128 }
-    },
-    {
-        { 0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99 },
-        { 0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752 },
-        { 0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, 0xd527bfcfeb778bf2, 0x303337da7012a3be }
-    },
-    {
-        { 0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b },
-        { 0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b },
-        { 0x0c003fbdc08d678d, 0x4d982fa37ead2b17, 0xc07e6bcdb2e582f1, 0x296c7291df412a44 }
-    },
-    {
-        { 0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1 },
-        { 0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0 },
-        { 0x3d0543d3623e7986, 0x679414c2c278a354, 0xae43f0cc726196f6, 0x7836c41f8245eaba }
-    },
-    {
-        { 0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd },
-        { 0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38 },
-        { 0x43eadfcbf4b31d4d, 0xc6503f7411148892, 0xfeee68c5060d3b17, 0x329293b3dd4a0ac8 }
-    },
-},
-{
-    {
-        { 0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35 },
-        { 0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232 },
-        { 0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4 }
-    },
-    {
-        { 0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d },
-        { 0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab },
-        { 0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413 }
-    },
-    {
-        { 0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56 },
-        { 0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84 },
-        { 0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7 }
-    },
-    {
-        { 0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5 },
-        { 0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495 },
-        { 0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41 }
-    },
-    {
-        { 0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286 },
-        { 0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76 },
-        { 0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489 }
-    },
-    {
-        { 0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16 },
-        { 0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008 },
-        { 0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76 }
-    },
-    {
-        { 0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700 },
-        { 0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309 },
-        { 0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb }
-    },
-    {
-        { 0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd },
-        { 0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a },
-        { 0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760 }
-    },
-},
-{
-    {
-        { 0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c },
-        { 0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2 },
-        { 0x7bfec69aab5cad3d, 0xc23e8cd34cb2cfad, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18 }
-    },
-    {
-        { 0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592 },
-        { 0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233 },
-        { 0x405fdd309afcb346, 0xd9723d4428e63f54, 0x94c01df05f65aaae, 0x43e4dc3ae14c0809 }
-    },
-    {
-        { 0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe },
-        { 0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f },
-        { 0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42 }
-    },
-    {
-        { 0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76 },
-        { 0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b },
-        { 0x4a4a5490246a59a2, 0xd63ebddee87fdd90, 0xd9437c670d2371fa, 0x69e87308d30f8ed6 }
-    },
-    {
-        { 0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa },
-        { 0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622 },
-        { 0xd26e5c3e91039f85, 0xc0e9e77df6f33aa9, 0xe8968c5570066a93, 0x3c34d1881faaaddd }
-    },
-    {
-        { 0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a },
-        { 0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d },
-        { 0xb4e856e45a9d1ed2, 0xefe848766c97a9a2, 0xb104cf641e5eee7d, 0x2f50b81c88a71c8f }
-    },
-    {
-        { 0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22 },
-        { 0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd },
-        { 0xd55165883ed28cdf, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74 }
-    },
-    {
-        { 0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc },
-        { 0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28 },
-        { 0x56a8ac24d6d59a9f, 0xc8db753e3096f006, 0x477f41e68f4c5299, 0x588d851cf6c86114 }
-    },
-},
-{
-    {
-        { 0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb },
-        { 0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650 },
-        { 0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba }
-    },
-    {
-        { 0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9 },
-        { 0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650 },
-        { 0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561 }
-    },
-    {
-        { 0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2 },
-        { 0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e },
-        { 0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701 }
-    },
-    {
-        { 0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e },
-        { 0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322 },
-        { 0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0 }
-    },
-    {
-        { 0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839 },
-        { 0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0 },
-        { 0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7 }
-    },
-    {
-        { 0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8 },
-        { 0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9 },
-        { 0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54 }
-    },
-    {
-        { 0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde },
-        { 0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185 },
-        { 0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f }
-    },
-    {
-        { 0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253 },
-        { 0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6 },
-        { 0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d }
-    },
-},
-{
-    {
-        { 0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1 },
-        { 0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07 },
-        { 0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e }
-    },
-    {
-        { 0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148 },
-        { 0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6 },
-        { 0xf1a9990175638698, 0x353dd1beeeaa60d3, 0x849471334c9ba488, 0x63fa6e6843ade311 }
-    },
-    {
-        { 0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67 },
-        { 0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14 },
-        { 0xd03c676c4ce530d4, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9 }
-    },
-    {
-        { 0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a },
-        { 0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c },
-        { 0x0b52b5606dba5ab6, 0xa9134f0fbbb1edab, 0x30a9520d9b04a635, 0x6813b8f37973e5db }
-    },
-    {
-        { 0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed },
-        { 0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900 },
-        { 0xd0ef874daf33da47, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a }
-    },
-    {
-        { 0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634 },
-        { 0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3 },
-        { 0x61943dee6d99c120, 0x86101f2e460b9fe0, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc }
-    },
-    {
-        { 0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f },
-        { 0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9 },
-        { 0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a }
-    },
-    {
-        { 0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a },
-        { 0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8 },
-        { 0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46 }
-    },
-},
-{
-    {
-        { 0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c },
-        { 0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7 },
-        { 0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9 }
-    },
-    {
-        { 0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83 },
-        { 0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877 },
-        { 0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3 }
-    },
-    {
-        { 0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98 },
-        { 0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633 },
-        { 0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016 }
-    },
-    {
-        { 0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1 },
-        { 0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1 },
-        { 0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059 }
-    },
-    {
-        { 0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042 },
-        { 0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b },
-        { 0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a }
-    },
-    {
-        { 0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217 },
-        { 0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0 },
-        { 0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd }
-    },
-    {
-        { 0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05 },
-        { 0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff },
-        { 0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd }
-    },
-    {
-        { 0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295 },
-        { 0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42 },
-        { 0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd }
-    },
-},
-{
-    {
-        { 0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb },
-        { 0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62 },
-        { 0xa617fa9ff53f6139, 0x60f2b5e513e66cb6, 0xd7a8beefb3448aa4, 0x7a2932856f5ea192 }
-    },
-    {
-        { 0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017 },
-        { 0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99 },
-        { 0x437c3b33a650db77, 0x6bafe81dbac52bb2, 0xfe99402d2db7d318, 0x2b5b7eec372ba6ce }
-    },
-    {
-        { 0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee },
-        { 0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9 },
-        { 0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae }
-    },
-    {
-        { 0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850 },
-        { 0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173 },
-        { 0x23d0e0814bccf226, 0x92c745cd8196fb93, 0x8b61796c59541e5b, 0x40a44df0c021f978 }
-    },
-    {
-        { 0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf },
-        { 0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0 },
-        { 0x97506f2f6f87b75c, 0xc624aea0034ae070, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f }
-    },
-    {
-        { 0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac },
-        { 0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25 },
-        { 0x99588e19e4c4912d, 0xefcc3b4e1ca5ce6b, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819 }
-    },
-    {
-        { 0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf },
-        { 0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b },
-        { 0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, 0x81a248776edbb4ca, 0x1a944ee88ecd0563 }
-    },
-    {
-        { 0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a },
-        { 0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995 },
-        { 0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49 }
-    },
-},
-{
-    {
-        { 0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e },
-        { 0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6 },
-        { 0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc }
-    },
-    {
-        { 0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081 },
-        { 0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402 },
-        { 0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006 }
-    },
-    {
-        { 0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5 },
-        { 0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0 },
-        { 0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64 }
-    },
-    {
-        { 0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90 },
-        { 0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c },
-        { 0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18 }
-    },
-    {
-        { 0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355 },
-        { 0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b },
-        { 0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413 }
-    },
-    {
-        { 0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b },
-        { 0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194 },
-        { 0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56 }
-    },
-    {
-        { 0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b },
-        { 0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00 },
-        { 0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38 }
-    },
-    {
-        { 0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57 },
-        { 0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6 },
-        { 0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b }
-    },
-},
-{
-    {
-        { 0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9 },
-        { 0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c },
-        { 0x62f90d65dfde3e34, 0xcf28c592b9fa5fad, 0x99c86ef9c6164510, 0x25d448044a256c84 }
-    },
-    {
-        { 0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26 },
-        { 0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e },
-        { 0xa4ff3e698a48a5db, 0xba6a3806bd95403b, 0x9f7ce1af47d5b65d, 0x15e087e55939d2fb }
-    },
-    {
-        { 0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661 },
-        { 0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9 },
-        { 0x2d45892b17c9e755, 0xd033fd7289308df8, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079 }
-    },
-    {
-        { 0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2 },
-        { 0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6 },
-        { 0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d }
-    },
-    {
-        { 0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4 },
-        { 0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df },
-        { 0x36d9ebc5d485b00c, 0xa2596492e4adb365, 0xc1659480c2119ccd, 0x45306349186e0d5f }
-    },
-    {
-        { 0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f },
-        { 0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f },
-        { 0xecb29fff199801f7, 0x9d361d1fa2a0f72f, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2 }
-    },
-    {
-        { 0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1 },
-        { 0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2 },
-        { 0xce040e9ec04145bc, 0xc71ff4e208f6834c, 0xbd546e8dab8847a3, 0x64666aa0a4d2aba5 }
-    },
-    {
-        { 0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468 },
-        { 0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046 },
-        { 0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e }
-    },
-},
-{
-    {
-        { 0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17 },
-        { 0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e },
-        { 0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa }
-    },
-    {
-        { 0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438 },
-        { 0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c },
-        { 0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543 }
-    },
-    {
-        { 0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452 },
-        { 0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d },
-        { 0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6 }
-    },
-    {
-        { 0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55 },
-        { 0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f },
-        { 0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c }
-    },
-    {
-        { 0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d },
-        { 0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc },
-        { 0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86 }
-    },
-    {
-        { 0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a },
-        { 0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70 },
-        { 0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388 }
-    },
-    {
-        { 0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc },
-        { 0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00 },
-        { 0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4 }
-    },
-    {
-        { 0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d },
-        { 0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8 },
-        { 0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af }
-    },
-},
-{
-    {
-        { 0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2 },
-        { 0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2 },
-        { 0x1d5ad94890bb02c0, 0x50e208b10ec25115, 0xa26a22894ef21702, 0x4dc923343b524805 }
-    },
-    {
-        { 0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847 },
-        { 0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784 },
-        { 0x3c6f9cd1d4a50d56, 0xb6244077c6feab7e, 0x6ff9bf483580972e, 0x00375883b332acfb }
-    },
-    {
-        { 0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7 },
-        { 0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660 },
-        { 0xcb116b73a49bd308, 0x025aad6b2392729e, 0xb4793efa3f55d9b1, 0x72a1056140678bb9 }
-    },
-    {
-        { 0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47 },
-        { 0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00 },
-        { 0xf1c1b5e2de331cb5, 0x5a9f5d8e15fca420, 0x9fa438f17bd932b1, 0x2a381bf01c6146e7 }
-    },
-    {
-        { 0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa },
-        { 0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6 },
-        { 0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242 }
-    },
-    {
-        { 0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab },
-        { 0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192 },
-        { 0x7b48f57414bb3f22, 0x68c7cee4aedccc88, 0xed2f936179ed80be, 0x25d70b885f77bc4b }
-    },
-    {
-        { 0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a },
-        { 0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24 },
-        { 0x87bef4b46a5a7b9c, 0xd2299d1b5fc1d062, 0x82409818dd321648, 0x5c5abeb1e5a2e03d }
-    },
-    {
-        { 0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643 },
-        { 0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f },
-        { 0x6be4404d0ebc52c7, 0xae46233bb1a791f5, 0x2aec170ed25db42b, 0x1d8dfd966645d694 }
-    },
-},
-{
-    {
-        { 0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a },
-        { 0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d },
-        { 0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137 }
-    },
-    {
-        { 0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86 },
-        { 0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007 },
-        { 0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e }
-    },
-    {
-        { 0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c },
-        { 0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07 },
-        { 0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac }
-    },
-    {
-        { 0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754 },
-        { 0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318 },
-        { 0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859 }
-    },
-    {
-        { 0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964 },
-        { 0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2 },
-        { 0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410 }
-    },
-    {
-        { 0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599 },
-        { 0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e },
-        { 0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436 }
-    },
-    {
-        { 0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d },
-        { 0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992 },
-        { 0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf }
-    },
-    {
-        { 0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb },
-        { 0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40 },
-        { 0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716 }
-    },
-},
-{
-    {
-        { 0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad },
-        { 0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365 },
-        { 0x0f196e0d1b826c68, 0xf71ff0e24960e3db, 0x6113167023b7436c, 0x0cf0ea5877da7282 }
-    },
-    {
-        { 0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d },
-        { 0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f },
-        { 0xc4b6664a3a70159f, 0x76194f0f0a904e14, 0xa5614c39a4096c13, 0x6cd0ff50979feced }
-    },
-    {
-        { 0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61 },
-        { 0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c },
-        { 0xc5c6b95aa606a8db, 0x914b7f9eb06825f1, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc }
-    },
-    {
-        { 0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5 },
-        { 0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668 },
-        { 0xab360a7f25563781, 0x2512228a480f7958, 0xc75d05276114b4e3, 0x222d9625d976fe2a }
-    },
-    {
-        { 0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea },
-        { 0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4 },
-        { 0x8155e2521a35ce63, 0xbe100d4df912028e, 0xbff80bf8a57ddcec, 0x57342dc96d6bc6e4 }
-    },
-    {
-        { 0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f },
-        { 0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855 },
-        { 0x272c1f46f9a3902b, 0xc91ba3b799657bcc, 0xae614b304f8a1c0e, 0x7afcaad70b99017b }
-    },
-    {
-        { 0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7 },
-        { 0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb },
-        { 0x9b840f66f1361315, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320 }
-    },
-    {
-        { 0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb },
-        { 0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7 },
-        { 0x4a89e68b82b7abf0, 0xf41cd9279ba6b7b9, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6 }
-    },
-},
-{
-    {
-        { 0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4 },
-        { 0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf },
-        { 0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2 }
-    },
-    {
-        { 0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1 },
-        { 0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d },
-        { 0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317 }
-    },
-    {
-        { 0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133 },
-        { 0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4 },
-        { 0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c }
-    },
-    {
-        { 0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827 },
-        { 0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607 },
-        { 0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae }
-    },
-    {
-        { 0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd },
-        { 0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e },
-        { 0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b }
-    },
-    {
-        { 0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6 },
-        { 0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314 },
-        { 0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389 }
-    },
-    {
-        { 0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea },
-        { 0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7 },
-        { 0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1 }
-    },
-    {
-        { 0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69 },
-        { 0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be },
-        { 0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa }
-    },
-},
-{
-    {
-        { 0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e },
-        { 0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff },
-        { 0xf01cc8f17471cc0c, 0x95242e37579082bb, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb }
-    },
-    {
-        { 0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8 },
-        { 0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58 },
-        { 0x3579f26b0282c4b2, 0x64d592f24fafefae, 0xb7cded7b28c8c7c0, 0x6a927b6b7173a8d7 }
-    },
-    {
-        { 0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d },
-        { 0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592 },
-        { 0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7 }
-    },
-    {
-        { 0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c },
-        { 0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659 },
-        { 0x61ff0640a7862bcc, 0x81cac09a5f11abfe, 0x9047830455d12abb, 0x19a4bde1945ae873 }
-    },
-    {
-        { 0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04 },
-        { 0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1 },
-        { 0xae853c94ab66dc47, 0xeb62343edf762d6e, 0xf08e0e186fb2f7d1, 0x4f0b1c02700ab37a }
-    },
-    {
-        { 0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534 },
-        { 0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54 },
-        { 0xda12c6c407831dcb, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef }
-    },
-    {
-        { 0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f },
-        { 0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331 },
-        { 0x0b886b925fd4d924, 0x60906f7a3626a80d, 0xecd367b4b98abd12, 0x2876beb1def344cf }
-    },
-    {
-        { 0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4 },
-        { 0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3 },
-        { 0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, 0x91bfa43411cce67b, 0x5784481964a831e7 }
-    },
-},
-{
-    {
-        { 0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b },
-        { 0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690 },
-        { 0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b }
-    },
-    {
-        { 0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5 },
-        { 0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149 },
-        { 0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f }
-    },
-    {
-        { 0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668 },
-        { 0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd },
-        { 0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5 }
-    },
-    {
-        { 0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c },
-        { 0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd },
-        { 0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7 }
-    },
-    {
-        { 0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33 },
-        { 0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848 },
-        { 0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51 }
-    },
-    {
-        { 0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37 },
-        { 0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6 },
-        { 0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6 }
-    },
-    {
-        { 0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690 },
-        { 0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788 },
-        { 0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759 }
-    },
-    {
-        { 0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90 },
-        { 0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c },
-        { 0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a }
-    },
-},
-{
-    {
-        { 0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d },
-        { 0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03 },
-        { 0x498fbb795e042e84, 0x7d0dd89a7698b714, 0x8bfb0ba427fe6295, 0x36ba82e721200524 }
-    },
-    {
-        { 0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339 },
-        { 0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4 },
-        { 0x498a6d7064ad94d8, 0xa5b5c8fd9af62263, 0x8ca8ed0545c141f4, 0x2c63bec3662d358c }
-    },
-    {
-        { 0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1 },
-        { 0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf },
-        { 0x8563d19a2066cf6c, 0x401bfd8c4dcc7cd7, 0xd976a6becd0d8f62, 0x67cfd773a278b05e }
-    },
-    {
-        { 0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee },
-        { 0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9 },
-        { 0x93869da3f4e3cb41, 0xbf0392f540f7977e, 0x026204fcd0463b83, 0x3ec91a769eec6eed }
-    },
-    {
-        { 0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896 },
-        { 0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc },
-        { 0x52958faa13cd67a1, 0x965ee0818bdbb517, 0x16e58daa2e8845b3, 0x357d397d5499da8f }
-    },
-    {
-        { 0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1 },
-        { 0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec },
-        { 0x6f58cd5d55aff958, 0xba3eaa5c75567721, 0x75c123999165227d, 0x69be1343c2f2b35e }
-    },
-    {
-        { 0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376 },
-        { 0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696 },
-        { 0x208aed4b4893b32b, 0x3efbf23ebe59b964, 0xd762deb0dba5e507, 0x69607bd681bd9d94 }
-    },
-    {
-        { 0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00 },
-        { 0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0 },
-        { 0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524 }
-    },
-},
-{
-    {
-        { 0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021 },
-        { 0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582 },
-        { 0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6 }
-    },
-    {
-        { 0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369 },
-        { 0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4 },
-        { 0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4 }
-    },
-    {
-        { 0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e },
-        { 0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312 },
-        { 0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4 }
-    },
-    {
-        { 0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f },
-        { 0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc },
-        { 0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537 }
-    },
-    {
-        { 0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390 },
-        { 0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4 },
-        { 0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f }
-    },
-    {
-        { 0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f },
-        { 0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff },
-        { 0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460 }
-    },
-    {
-        { 0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720 },
-        { 0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74 },
-        { 0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7 }
-    },
-    {
-        { 0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d },
-        { 0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730 },
-        { 0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5 }
-    },
-},
-{
-    {
-        { 0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6 },
-        { 0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e },
-        { 0xa7bc970650b9de79, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc }
-    },
-    {
-        { 0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8 },
-        { 0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282 },
-        { 0xf17b483568673205, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599 }
-    },
-    {
-        { 0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b },
-        { 0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87 },
-        { 0xd6863eba37b9e39f, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4 }
-    },
-    {
-        { 0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04 },
-        { 0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9 },
-        { 0x00f565a9f93267de, 0xcecfd78dc0d58e8a, 0xa215e2dcf318e28e, 0x4599ee919b633352 }
-    },
-    {
-        { 0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de },
-        { 0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028 },
-        { 0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc }
-    },
-    {
-        { 0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831 },
-        { 0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006 },
-        { 0x40a3a11ec7910acc, 0x9013dff8f16d27ae, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463 }
-    },
-    {
-        { 0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9 },
-        { 0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9 },
-        { 0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698 }
-    },
-    {
-        { 0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130 },
-        { 0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3 },
-        { 0x925b5ef0670c507c, 0x819bc842b93c33bf, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74 }
-    },
-},
-{
-    {
-        { 0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa },
-        { 0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551 },
-        { 0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693 }
-    },
-    {
-        { 0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352 },
-        { 0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63 },
-        { 0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8 }
-    },
-    {
-        { 0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870 },
-        { 0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36 },
-        { 0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f }
-    },
-    {
-        { 0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51 },
-        { 0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9 },
-        { 0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec }
-    },
-    {
-        { 0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde },
-        { 0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8 },
-        { 0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244 }
-    },
-    {
-        { 0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6 },
-        { 0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a },
-        { 0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4 }
-    },
-    {
-        { 0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6 },
-        { 0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34 },
-        { 0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1 }
-    },
-    {
-        { 0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81 },
-        { 0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab },
-        { 0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7 }
-    },
-},
-{
-    {
-        { 0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef },
-        { 0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75 },
-        { 0xc447901ad61beb59, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26 }
-    },
-    {
-        { 0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f },
-        { 0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e },
-        { 0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b }
-    },
-    {
-        { 0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840 },
-        { 0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908 },
-        { 0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, 0xfed5ac25d3404f9a, 0x72e82d5e5505c229 }
-    },
-    {
-        { 0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861 },
-        { 0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211 },
-        { 0x9f21903f0101689e, 0xd779dfd3bf861005, 0xa122ee5f3deb0f1b, 0x510df84b485a00d4 }
-    },
-    {
-        { 0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e },
-        { 0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a },
-        { 0x6bd47c6598fbee0f, 0x9e4733e2ab55be2d, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4 }
-    },
-    {
-        { 0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8 },
-        { 0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82 },
-        { 0x6da6de8f0e399799, 0x7ad61aa440fda178, 0xb32cd8105e3563dd, 0x15f6beae2ae340ae }
-    },
-    {
-        { 0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda },
-        { 0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281 },
-        { 0x3e4df9655884e2aa, 0xbd62fbdbdbd465a5, 0xd7596caa0de9e524, 0x6e8042ccb2b1b3d7 }
-    },
-    {
-        { 0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0 },
-        { 0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9 },
-        { 0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7 }
-    },
-},
-{
-    {
-        { 0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9 },
-        { 0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e },
-        { 0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7 }
-    },
-    {
-        { 0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0 },
-        { 0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9 },
-        { 0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6 }
-    },
-    {
-        { 0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226 },
-        { 0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3 },
-        { 0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945 }
-    },
-    {
-        { 0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c },
-        { 0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b },
-        { 0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832 }
-    },
-    {
-        { 0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce },
-        { 0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122 },
-        { 0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed }
-    },
-    {
-        { 0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109 },
-        { 0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a },
-        { 0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790 }
-    },
-    {
-        { 0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1 },
-        { 0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99 },
-        { 0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb }
-    },
-    {
-        { 0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08 },
-        { 0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92 },
-        { 0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d }
-    },
-},
-{
-    {
-        { 0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed },
-        { 0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da },
-        { 0x9f97ef2e801ad9f9, 0x83697d5479afda3a, 0xe906b3ffbd596b50, 0x02672b37dd3fb8e0 }
-    },
-    {
-        { 0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8 },
-        { 0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5 },
-        { 0xbf61423d253fcb17, 0x08803ceafa39eb14, 0xf18602df9851c7af, 0x0400f3a049e3414b }
-    },
-    {
-        { 0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3 },
-        { 0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb },
-        { 0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820 }
-    },
-    {
-        { 0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16 },
-        { 0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2 },
-        { 0xc48bab1521a9d733, 0xa6c2eaead61abb25, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67 }
-    },
-    {
-        { 0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11 },
-        { 0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e },
-        { 0x25b5a8e50ef7c48f, 0xeb6034116f2ce532, 0xc5e75173e53de537, 0x73119fa08c12bb03 }
-    },
-    {
-        { 0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212 },
-        { 0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c },
-        { 0x3fecde923aeca999, 0xbdaa5b0062e8c12f, 0x67b99dfc96988ade, 0x3f52c02852661036 }
-    },
-    {
-        { 0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569 },
-        { 0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59 },
-        { 0x051de020de9cbe97, 0xfa07fc56b50bcf74, 0x378cec9f0f11df65, 0x36853c69ab96de4d }
-    },
-    {
-        { 0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8 },
-        { 0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b },
-        { 0xe917fb9e61095301, 0xc102df9402a092f8, 0xbf09e2f5fa66190b, 0x681109bee0dcfe37 }
-    },
-},
-{
-    {
-        { 0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4 },
-        { 0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d },
-        { 0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069 }
-    },
-    {
-        { 0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019 },
-        { 0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f },
-        { 0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012 }
-    },
-    {
-        { 0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6 },
-        { 0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae },
-        { 0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb }
-    },
-    {
-        { 0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c },
-        { 0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877 },
-        { 0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b }
-    },
-    {
-        { 0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5 },
-        { 0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364 },
-        { 0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1 }
-    },
-    {
-        { 0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554 },
-        { 0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9 },
-        { 0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3 }
-    },
-    {
-        { 0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc },
-        { 0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485 },
-        { 0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a }
-    },
-    {
-        { 0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d },
-        { 0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4 },
-        { 0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c }
-    },
-},
-{
-    {
-        { 0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b },
-        { 0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c },
-        { 0xc1fb4177018b9910, 0xa6ea20dc6c0fe140, 0xd661f3e74354c6ff, 0x5ecb72e6f1a3407a }
-    },
-    {
-        { 0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0 },
-        { 0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019 },
-        { 0xf391c51d8ace50a6, 0x3142d0b9ae2d2948, 0xdb4d5a1a7f24ca80, 0x21aeba8b59250ea8 }
-    },
-    {
-        { 0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed },
-        { 0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d },
-        { 0x17e49c17cc947f3d, 0xccc6eda6aac1d27b, 0xdf6092ceb0f08e56, 0x4909b3e22c67c36b }
-    },
-    {
-        { 0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68 },
-        { 0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c },
-        { 0x79d5c62eafc3902b, 0x773a215289e80728, 0xc38ae640e10120b9, 0x09ae23717b2b1a6d }
-    },
-    {
-        { 0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996 },
-        { 0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac },
-        { 0xd27d9afb24997323, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8 }
-    },
-    {
-        { 0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7 },
-        { 0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512 },
-        { 0x4093addc9c07c205, 0xc565be15f532c37e, 0x63dbecfd1583402a, 0x61722b4aef2e032e }
-    },
-    {
-        { 0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59 },
-        { 0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429 },
-        { 0x8d0cb88c1b37cfe1, 0x05b6a5a3053818f3, 0xf2e9bc04b787d959, 0x6beba1249add7f64 }
-    },
-    {
-        { 0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5 },
-        { 0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5 },
-        { 0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, 0xc43eced4a169d097, 0x0a1249fff7e587c3 }
-    },
-},
-{
-    {
-        { 0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c },
-        { 0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792 },
-        { 0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319 }
-    },
-    {
-        { 0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13 },
-        { 0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266 },
-        { 0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e }
-    },
-    {
-        { 0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9 },
-        { 0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868 },
-        { 0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe }
-    },
-    {
-        { 0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241 },
-        { 0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd },
-        { 0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463 }
-    },
-    {
-        { 0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280 },
-        { 0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b },
-        { 0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a }
-    },
-    {
-        { 0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67 },
-        { 0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac },
-        { 0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99 }
-    },
-    {
-        { 0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b },
-        { 0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9 },
-        { 0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db }
-    },
-    {
-        { 0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf },
-        { 0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf },
-        { 0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859 }
-    },
-},
-{
-    {
-        { 0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52 },
-        { 0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c },
-        { 0xb8fd9399e8d19e9d, 0x908191cb962423ff, 0xb2b948d747c742a3, 0x37f33226d7fb44c4 }
-    },
-    {
-        { 0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f },
-        { 0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3 },
-        { 0x8eeb5d076eb55ce0, 0x2fc536bfaa0d925a, 0xbe81830fdcb6c6e8, 0x556c7045827baf52 }
-    },
-    {
-        { 0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3 },
-        { 0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9 },
-        { 0x61af4912c8ef8a6a, 0xe58fa4fe43fb6e5e, 0xb5afcc5d6fd427cf, 0x6a5393281e1e11eb }
-    },
-    {
-        { 0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d },
-        { 0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d },
-        { 0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2 }
-    },
-    {
-        { 0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401 },
-        { 0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd },
-        { 0xc0b73ec6d6b330cd, 0x84e44807132faff1, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2 }
-    },
-    {
-        { 0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438 },
-        { 0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d },
-        { 0xbf56a431ed05b488, 0xa533e66c9c495c7e, 0xe8652baf87f3651a, 0x0241800059d66c33 }
-    },
-    {
-        { 0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0 },
-        { 0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c },
-        { 0xbb537fe0447070de, 0xcba744436dd557df, 0xd3b5a3473600dbcb, 0x4aeabbe6f9ffd7f8 }
-    },
-    {
-        { 0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e },
-        { 0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5 },
-        { 0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c }
-    },
-},
-{
-    {
-        { 0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095 },
-        { 0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6 },
-        { 0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1 }
-    },
-    {
-        { 0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99 },
-        { 0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f },
-        { 0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e }
-    },
-    {
-        { 0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0 },
-        { 0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4 },
-        { 0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c }
-    },
-    {
-        { 0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3 },
-        { 0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c },
-        { 0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d }
-    },
-    {
-        { 0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24 },
-        { 0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca },
-        { 0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34 }
-    },
-    {
-        { 0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e },
-        { 0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354 },
-        { 0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075 }
-    },
-    {
-        { 0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d },
-        { 0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993 },
-        { 0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe }
-    },
-    {
-        { 0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95 },
-        { 0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68 },
-        { 0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d }
-    },
-},
-{
-    {
-        { 0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9 },
-        { 0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9 },
-        { 0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136 }
-    },
-    {
-        { 0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1 },
-        { 0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975 },
-        { 0xf2398e098aa27f82, 0x6d7982bb89a1b024, 0xfa694084214dd24c, 0x71ab966fa32301c3 }
-    },
-    {
-        { 0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed },
-        { 0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22 },
-        { 0x83200a656c340431, 0x9fcd71678ee59c2f, 0x75d4613f71300f8a, 0x7a912faf60f542f9 }
-    },
-    {
-        { 0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a },
-        { 0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be },
-        { 0x597028047f116909, 0x828ac41c1e564467, 0x70417dbde6217387, 0x721627aefbac4384 }
-    },
-    {
-        { 0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902 },
-        { 0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7 },
-        { 0xaedca66978d477f8, 0x1898ba3c29117fe1, 0xcf73f983720cbd58, 0x67da12e6b8b56351 }
-    },
-    {
-        { 0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141 },
-        { 0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a },
-        { 0x3030fc33534c6378, 0xb9635c5ce541e861, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb }
-    },
-    {
-        { 0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c },
-        { 0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51 },
-        { 0x47e241428f83753c, 0x6317bebc866af997, 0xdabb5b433d1a9829, 0x074d8d245287fb2d }
-    },
-    {
-        { 0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9 },
-        { 0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be },
-        { 0xfaa23adeaffe65f7, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395 }
-    },
-},
-{
-    {
-        { 0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060 },
-        { 0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c },
-        { 0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72 }
-    },
-    {
-        { 0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df },
-        { 0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b },
-        { 0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb }
-    },
-    {
-        { 0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64 },
-        { 0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03 },
-        { 0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa }
-    },
-    {
-        { 0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613 },
-        { 0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01 },
-        { 0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb }
-    },
-    {
-        { 0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8 },
-        { 0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c },
-        { 0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75 }
-    },
-    {
-        { 0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13 },
-        { 0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded },
-        { 0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6 }
-    },
-    {
-        { 0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b },
-        { 0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d },
-        { 0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7 }
-    },
-    {
-        { 0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf },
-        { 0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73 },
-        { 0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a }
-    },
-},
-{
-    {
-        { 0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524 },
-        { 0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba },
-        { 0x337788ffca14032c, 0xf3921028447f1ee3, 0x8b14071f231bccad, 0x4c817b4bf2344783 }
-    },
-    {
-        { 0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53 },
-        { 0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b },
-        { 0x6cbdf1703ad0562b, 0x8ecf4830c92521a3, 0xdaebd303fd8424e7, 0x72ad82a42e5ec56f }
-    },
-    {
-        { 0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4 },
-        { 0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d },
-        { 0x8a00aec75532db4d, 0xb869a4e443e31bb1, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08 }
-    },
-    {
-        { 0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53 },
-        { 0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2 },
-        { 0x07bd475b47f796b8, 0xd2c7b013542c8f54, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6 }
-    },
-    {
-        { 0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b },
-        { 0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f },
-        { 0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3 }
-    },
-    {
-        { 0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711 },
-        { 0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2 },
-        { 0x2f07ad636f09a8a2, 0x8697e6ce24205e7d, 0xc0aefc05ee35a139, 0x15e80958b5f9d897 }
-    },
-    {
-        { 0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443 },
-        { 0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39 },
-        { 0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, 0xb323d9f2cda390a7, 0x7be0847b8774d363 }
-    },
-    {
-        { 0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b },
-        { 0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619 },
-        { 0xe77292f373e7ea8a, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966 }
-    },
-},
-{
-    {
-        { 0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d },
-        { 0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d },
-        { 0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0 }
-    },
-    {
-        { 0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba },
-        { 0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956 },
-        { 0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1 }
-    },
-    {
-        { 0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5 },
-        { 0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a },
-        { 0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4 }
-    },
-    {
-        { 0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75 },
-        { 0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5 },
-        { 0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3 }
-    },
-    {
-        { 0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026 },
-        { 0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1 },
-        { 0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066 }
-    },
-    {
-        { 0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2 },
-        { 0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7 },
-        { 0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568 }
-    },
-    {
-        { 0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5 },
-        { 0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5 },
-        { 0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26 }
-    },
-    {
-        { 0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223 },
-        { 0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f },
-        { 0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb }
-    },
-},
-{
-    {
-        { 0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40 },
-        { 0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5 },
-        { 0xa7ab69798d496476, 0x8121aadefcb5abc8, 0xa5dc12ef7b539472, 0x07fd47065e45351a }
-    },
-    {
-        { 0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4 },
-        { 0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23 },
-        { 0xcb3197001bb3666c, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364 }
-    },
-    {
-        { 0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188 },
-        { 0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5 },
-        { 0xe44a23152d096800, 0x5c08c55970866996, 0xdf2db60a46affb6e, 0x579155c1f856fd89 }
-    },
-    {
-        { 0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345 },
-        { 0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a },
-        { 0xd2d41481f1cbafbf, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6 }
-    },
-    {
-        { 0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f },
-        { 0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5 },
-        { 0xe564cfdd5c7d2ceb, 0x82eeafded737ccb9, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb }
-    },
-    {
-        { 0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412 },
-        { 0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501 },
-        { 0x1c74b88dc27e6360, 0x074854268d14850c, 0xa145fb7b3e0dcb30, 0x10843f1b43803b23 }
-    },
-    {
-        { 0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8 },
-        { 0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4 },
-        { 0xb8f4308e7f80be53, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671 }
-    },
-    {
-        { 0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e },
-        { 0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1 },
-        { 0x1bc64631e56bf61f, 0xd379ab106e5382a3, 0x4d58c57e0540168d, 0x566256628442d8e4 }
-    },
-},
-{
-    {
-        { 0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231 },
-        { 0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006 },
-        { 0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc }
-    },
-    {
-        { 0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd },
-        { 0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da },
-        { 0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2 }
-    },
-    {
-        { 0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e },
-        { 0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace },
-        { 0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f }
-    },
-    {
-        { 0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd },
-        { 0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca },
-        { 0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f }
-    },
-    {
-        { 0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616 },
-        { 0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6 },
-        { 0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d }
-    },
-    {
-        { 0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4 },
-        { 0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831 },
-        { 0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214 }
-    },
-    {
-        { 0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde },
-        { 0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6 },
-        { 0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e }
-    },
-    {
-        { 0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074 },
-        { 0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd },
-        { 0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b }
-    },
-},
-{
-    {
-        { 0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa },
-        { 0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d },
-        { 0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71 }
-    },
-    {
-        { 0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7 },
-        { 0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d },
-        { 0xb301bb7c6b1beca3, 0x55393f6dc6eb1375, 0x910d281097b6e4eb, 0x1ad4548d9d479ea3 }
-    },
-    {
-        { 0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258 },
-        { 0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443 },
-        { 0x59ac3bc5d670c022, 0xeae67c109b119406, 0x9798bdf0b3782fda, 0x651e3201fd074092 }
-    },
-    {
-        { 0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278 },
-        { 0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb },
-        { 0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, 0x8320aa0dd6430df9, 0x667282652c4a2fb5 }
-    },
-    {
-        { 0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf },
-        { 0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39 },
-        { 0xd8ee1b18319ea6aa, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14 }
-    },
-    {
-        { 0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e },
-        { 0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1 },
-        { 0x31b6972d98b0bde8, 0x7d920706aca6de5b, 0xe67310f8908a659f, 0x50fac2a6efdf0235 }
-    },
-    {
-        { 0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662 },
-        { 0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4 },
-        { 0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b }
-    },
-    {
-        { 0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e },
-        { 0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408 },
-        { 0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493 }
-    },
-},
-{
-    {
-        { 0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab },
-        { 0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3 },
-        { 0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b }
-    },
-    {
-        { 0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c },
-        { 0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434 },
-        { 0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be }
-    },
-    {
-        { 0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36 },
-        { 0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57 },
-        { 0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179 }
-    },
-    {
-        { 0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3 },
-        { 0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661 },
-        { 0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f }
-    },
-    {
-        { 0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037 },
-        { 0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562 },
-        { 0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e }
-    },
-    {
-        { 0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7 },
-        { 0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc },
-        { 0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a }
-    },
-    {
-        { 0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e },
-        { 0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372 },
-        { 0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97 }
-    },
-    {
-        { 0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6 },
-        { 0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4 },
-        { 0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867 }
-    },
-},
-{
-    {
-        { 0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0 },
-        { 0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287 },
-        { 0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6 }
-    },
-    {
-        { 0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42 },
-        { 0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9 },
-        { 0x9b65c8f17d0752da, 0x881ce338c77ee800, 0xc3b514f05b62f9e3, 0x66ed5dd5bec10d48 }
-    },
-    {
-        { 0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c },
-        { 0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20 },
-        { 0xf235467be5bc1570, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50 }
-    },
-    {
-        { 0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c },
-        { 0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276 },
-        { 0x37d88e68fbe45321, 0x86097548c0d75032, 0x4e9b13ef894a0d35, 0x25a83cac5753d325 }
-    },
-    {
-        { 0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9 },
-        { 0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630 },
-        { 0x1a9615a9b62a345f, 0x22050c564a52fecc, 0xa7a2788528bc0dfe, 0x5e82770a1a1ee71d }
-    },
-    {
-        { 0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee },
-        { 0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102 },
-        { 0xfd2d5d35197dbe6e, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e }
-    },
-    {
-        { 0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64 },
-        { 0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180 },
-        { 0x9e5eee8e33db2710, 0x189854ded6c43ca5, 0xa41c22c592718138, 0x27ad5538a43a5e9b }
-    },
-    {
-        { 0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d },
-        { 0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2 },
-        { 0xdda69d930a3ed3e3, 0x3d386ef1cd60a722, 0xc817ad58bdaa4ee6, 0x23be8d554fe7372a }
-    },
-},
-{
-    {
-        { 0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001 },
-        { 0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797 },
-        { 0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293 }
-    },
-    {
-        { 0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f },
-        { 0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec },
-        { 0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c }
-    },
-    {
-        { 0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332 },
-        { 0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07 },
-        { 0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217 }
-    },
-    {
-        { 0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0 },
-        { 0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714 },
-        { 0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e }
-    },
-    {
-        { 0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e },
-        { 0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13 },
-        { 0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0 }
-    },
-    {
-        { 0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940 },
-        { 0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade },
-        { 0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db }
-    },
-    {
-        { 0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8 },
-        { 0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57 },
-        { 0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408 }
-    },
-    {
-        { 0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98 },
-        { 0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be },
-        { 0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c }
-    },
-},
-{
-    {
-        { 0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c },
-        { 0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40 },
-        { 0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd }
-    },
-    {
-        { 0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e },
-        { 0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb },
-        { 0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0 }
-    },
-    {
-        { 0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972 },
-        { 0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6 },
-        { 0xe9812086fe7eebe0, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9 }
-    },
-    {
-        { 0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b },
-        { 0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b },
-        { 0xcb58c8fe433d8939, 0x89a0cb2e6a8d7e50, 0x79ca955309fbbe5a, 0x0c626616cd7fc106 }
-    },
-    {
-        { 0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192 },
-        { 0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788 },
-        { 0x8fda0f37a0165199, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7 }
-    },
-    {
-        { 0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66 },
-        { 0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959 },
-        { 0x1fadbadba54395a7, 0xb41a02a0ae0da66a, 0xbf19f598bba37c07, 0x6a12b8acde48430d }
-    },
-    {
-        { 0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19 },
-        { 0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7 },
-        { 0x041f7e925830f40e, 0x002d6ca979661c06, 0x86dc9ff92b046a2e, 0x760360928b0493d1 }
-    },
-    {
-        { 0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224 },
-        { 0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68 },
-        { 0xc8b247b65bcaf19c, 0x49779dc3b1b2c652, 0x89a180bbd5ece2e2, 0x13f098a3cec8e039 }
-    },
-},
-{
-    {
-        { 0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9 },
-        { 0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b },
-        { 0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09 }
-    },
-    {
-        { 0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc },
-        { 0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5 },
-        { 0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc }
-    },
-    {
-        { 0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834 },
-        { 0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147 },
-        { 0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2 }
-    },
-    {
-        { 0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65 },
-        { 0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd },
-        { 0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469 }
-    },
-    {
-        { 0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2 },
-        { 0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57 },
-        { 0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63 }
-    },
-    {
-        { 0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0 },
-        { 0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7 },
-        { 0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73 }
-    },
-    {
-        { 0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f },
-        { 0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87 },
-        { 0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65 }
-    },
-    {
-        { 0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620 },
-        { 0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8 },
-        { 0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99 }
-    },
-},
-{
-    {
-        { 0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2 },
-        { 0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9 },
-        { 0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235 }
-    },
-    {
-        { 0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2 },
-        { 0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58 },
-        { 0x8efb23c3328ccb75, 0xaf42a207dd876ee9, 0x20fbdadc5dfae796, 0x241e246b06bf9f51 }
-    },
-    {
-        { 0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee },
-        { 0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097 },
-        { 0xe8d5dc9fa96bad93, 0xe58fb17dde1947dc, 0x681532ea65185fa3, 0x1fdd6c3b034a7830 }
-    },
-    {
-        { 0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5 },
-        { 0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e },
-        { 0xfc415a7c59646445, 0xd224b2d7c128b615, 0x6035c9c905fbb912, 0x42d7a91274429fab }
-    },
-    {
-        { 0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147 },
-        { 0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532 },
-        { 0xdd775d99a8559c6f, 0xf42a2140df003e24, 0x5223e229da928a66, 0x063f46ba6d38f22c }
-    },
-    {
-        { 0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068 },
-        { 0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d },
-        { 0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403 }
-    },
-    {
-        { 0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f },
-        { 0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2 },
-        { 0x8cc154cce9e39904, 0x5b3a040b84de6846, 0xc4d8a61cb1be5d6e, 0x40fb897bd8861f02 }
-    },
-    {
-        { 0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b },
-        { 0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da },
-        { 0xd1c101d50b813381, 0xdee60f1176ee6828, 0x0cb68893383f6409, 0x6183c565f6ff484a }
-    },
-},
-{
-    {
-        { 0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85 },
-        { 0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff },
-        { 0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15 }
-    },
-    {
-        { 0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5 },
-        { 0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33 },
-        { 0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44 }
-    },
-    {
-        { 0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438 },
-        { 0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090 },
-        { 0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955 }
-    },
-    {
-        { 0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe },
-        { 0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f },
-        { 0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50 }
-    },
-    {
-        { 0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577 },
-        { 0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13 },
-        { 0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907 }
-    },
-    {
-        { 0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a },
-        { 0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa },
-        { 0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea }
-    },
-    {
-        { 0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128 },
-        { 0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1 },
-        { 0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4 }
-    },
-    {
-        { 0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1 },
-        { 0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a },
-        { 0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664 }
-    },
-},
-{
-    {
-        { 0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70 },
-        { 0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5 },
-        { 0x8b767a93204ed789, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3 }
-    },
-    {
-        { 0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb },
-        { 0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd },
-        { 0x22b1a58ae9b08183, 0xfd95d071c15c388b, 0xa9812376850a0517, 0x33384cbabb7f335e }
-    },
-    {
-        { 0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059 },
-        { 0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89 },
-        { 0x52e105f61416375a, 0xec97af3685abeba4, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01 }
-    },
-    {
-        { 0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6 },
-        { 0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7 },
-        { 0x8a50777e166f031a, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905 }
-    },
-    {
-        { 0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29 },
-        { 0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d },
-        { 0xda96bbb3aced37ac, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f }
-    },
-    {
-        { 0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00 },
-        { 0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0 },
-        { 0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, 0xa4132cbbe5cf0003, 0x3f93d82354f000ea }
-    },
-    {
-        { 0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff },
-        { 0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a },
-        { 0xf256aceca436df54, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50 }
-    },
-    {
-        { 0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d },
-        { 0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8 },
-        { 0xef5cf100cfb7ea74, 0x22897633a1cb42ac, 0xd4ce0c54cef285e2, 0x30408c048a146a55 }
-    },
-},
-{
-    {
-        { 0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a },
-        { 0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e },
-        { 0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835 }
-    },
-    {
-        { 0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6 },
-        { 0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09 },
-        { 0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d }
-    },
-    {
-        { 0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e },
-        { 0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0 },
-        { 0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1 }
-    },
-    {
-        { 0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138 },
-        { 0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda },
-        { 0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c }
-    },
-    {
-        { 0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9 },
-        { 0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c },
-        { 0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293 }
-    },
-    {
-        { 0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d },
-        { 0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b },
-        { 0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c }
-    },
-    {
-        { 0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03 },
-        { 0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0 },
-        { 0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae }
-    },
-    {
-        { 0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838 },
-        { 0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a },
-        { 0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0 }
-    },
-},
-{
-    {
-        { 0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982 },
-        { 0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87 },
-        { 0xcc802468f7c3568f, 0x9de9ba8219974cb3, 0xabb7229cb5b81360, 0x44e2017a6fbeba62 }
-    },
-    {
-        { 0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d },
-        { 0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea },
-        { 0xdcdfe0a02cc1de60, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606 }
-    },
-    {
-        { 0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75 },
-        { 0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e },
-        { 0x77c8e14577e2189c, 0xa3e46f6aff99c445, 0x3144dfc86d335343, 0x3a96559e7c4216a9 }
-    },
-    {
-        { 0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f },
-        { 0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c },
-        { 0xa54dd074294c0b94, 0xf55d46b8df18ffb6, 0xf06fecc58dae8366, 0x588657668190d165 }
-    },
-    {
-        { 0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93 },
-        { 0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9 },
-        { 0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7 }
-    },
-    {
-        { 0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8 },
-        { 0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a },
-        { 0x183eab7e78a151ab, 0xbbe990c999093763, 0xff717d6e4ac7e335, 0x4c5cddb325f39f88 }
-    },
-    {
-        { 0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b },
-        { 0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21 },
-        { 0x8141e72f2d4dddea, 0xe6eafe9862c607c8, 0x23c28458573cafd0, 0x46b9476f4ff97346 }
-    },
-    {
-        { 0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f },
-        { 0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142 },
-        { 0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7 }
-    },
-},
-{
-    {
-        { 0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17 },
-        { 0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62 },
-        { 0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d }
-    },
-    {
-        { 0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43 },
-        { 0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520 },
-        { 0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80 }
-    },
-    {
-        { 0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d },
-        { 0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d },
-        { 0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe }
-    },
-    {
-        { 0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686 },
-        { 0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc },
-        { 0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4 }
-    },
-    {
-        { 0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a },
-        { 0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51 },
-        { 0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd }
-    },
-    {
-        { 0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472 },
-        { 0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9 },
-        { 0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11 }
-    },
-    {
-        { 0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac },
-        { 0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2 },
-        { 0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5 }
-    },
-    {
-        { 0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb },
-        { 0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb },
-        { 0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d }
-    },
-},
-{
-    {
-        { 0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579 },
-        { 0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad },
-        { 0xd9fa917183075a55, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877 }
-    },
-    {
-        { 0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9 },
-        { 0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8 },
-        { 0xf3678fd0ecc90b54, 0xf001459b12043599, 0x26725fbc3758b89b, 0x4325e4aa73a719ae }
-    },
-    {
-        { 0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d },
-        { 0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947 },
-        { 0xee332d4de3b42b0a, 0xd84e5a2b16a4601c, 0x78243877078ba3e4, 0x77ed1eb4184ee437 }
-    },
-    {
-        { 0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd },
-        { 0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0 },
-        { 0x124079eaa54cf2ba, 0xd72465eb001b26e7, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02 }
-    },
-    {
-        { 0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89 },
-        { 0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45 },
-        { 0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546 }
-    },
-    {
-        { 0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2 },
-        { 0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d },
-        { 0x2323daa74595f8e4, 0xde688c8b857abeb4, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba }
-    },
-    {
-        { 0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7 },
-        { 0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602 },
-        { 0xc1d5285220066a38, 0x95603e523570aef3, 0x832659a7226b8a4d, 0x5dd689091f8eedc9 }
-    },
-    {
-        { 0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748 },
-        { 0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8 },
-        { 0xc704ff4942bdbae6, 0x5e21ade2b2de1f79, 0xe95db3f35652fad8, 0x0822b5378f08ebc1 }
-    },
-},
-{
-    {
-        { 0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f },
-        { 0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6 },
-        { 0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea }
-    },
-    {
-        { 0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5 },
-        { 0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09 },
-        { 0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8 }
-    },
-    {
-        { 0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34 },
-        { 0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486 },
-        { 0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c }
-    },
-    {
-        { 0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80 },
-        { 0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34 },
-        { 0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2 }
-    },
-    {
-        { 0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b },
-        { 0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d },
-        { 0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8 }
-    },
-    {
-        { 0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e },
-        { 0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d },
-        { 0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc }
-    },
-    {
-        { 0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06 },
-        { 0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31 },
-        { 0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094 }
-    },
-    {
-        { 0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071 },
-        { 0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454 },
-        { 0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436 }
-    },
-},
-{
-    {
-        { 0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef },
-        { 0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183 },
-        { 0x32750763b028f48c, 0x06020740556a065f, 0xd53bd812c3495b58, 0x08706c9b865f508d }
-    },
-    {
-        { 0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00 },
-        { 0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9 },
-        { 0x9c49e355c9941ad0, 0xb9734ade74498f84, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3 }
-    },
-    {
-        { 0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435 },
-        { 0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080 },
-        { 0xb22228190d6ef6b2, 0xa94a66b246ce4bfa, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf }
-    },
-    {
-        { 0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1 },
-        { 0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c },
-        { 0x6f203dd5405b4b42, 0x327ec60410b24509, 0x9c347230ac2a8846, 0x77de29fc11ffeb6a }
-    },
-    {
-        { 0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892 },
-        { 0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac },
-        { 0x99803a27c88fcb3a, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2 }
-    },
-    {
-        { 0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51 },
-        { 0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95 },
-        { 0x48329952213fc985, 0x1087cf0d368a1746, 0x8e5261b166c15aa5, 0x2d5b2d842ed24c21 }
-    },
-    {
-        { 0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec },
-        { 0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2 },
-        { 0x79ee6c7223e5b547, 0x6f5f50768330d679, 0xed73e1e96d8adce9, 0x27c3da1e1d8ccc03 }
-    },
-    {
-        { 0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18 },
-        { 0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9 },
-        { 0x232a03c35c258ea5, 0x86f23a2c6bcb0cf1, 0x3dad8d0d2e442166, 0x04a8933cab76862b }
-    },
-},
-{
-    {
-        { 0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140 },
-        { 0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf },
-        { 0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42 }
-    },
-    {
-        { 0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5 },
-        { 0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42 },
-        { 0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b }
-    },
-    {
-        { 0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b },
-        { 0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351 },
-        { 0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4 }
-    },
-    {
-        { 0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e },
-        { 0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217 },
-        { 0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154 }
-    },
-    {
-        { 0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f },
-        { 0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763 },
-        { 0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597 }
-    },
-    {
-        { 0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b },
-        { 0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9 },
-        { 0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f }
-    },
-    {
-        { 0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1 },
-        { 0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858 },
-        { 0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4 }
-    },
-    {
-        { 0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6 },
-        { 0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543 },
-        { 0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f }
-    },
-},
-{
-    {
-        { 0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa },
-        { 0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1 },
-        { 0xecf46e527aba8b57, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5 }
-    },
-    {
-        { 0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe },
-        { 0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9 },
-        { 0xc83ca3e390babd62, 0x80ede3670291c833, 0xc88038ccd37900c4, 0x2c5fc0231ec31fa1 }
-    },
-    {
-        { 0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f },
-        { 0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6 },
-        { 0x5bd9b4763626e81c, 0x89966936bca02edd, 0x0a41193d61f077b3, 0x3097a24200ce5471 }
-    },
-    {
-        { 0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363 },
-        { 0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48 },
-        { 0xaf6c4aa752f912b9, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e }
-    },
-    {
-        { 0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b },
-        { 0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0 },
-        { 0x219ef713d815bac1, 0xf141465d485be25c, 0x6d5447cc4e513c51, 0x174926be5ef44393 }
-    },
-    {
-        { 0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad },
-        { 0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24 },
-        { 0xe276824a1f73371f, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96 }
-    },
-    {
-        { 0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b },
-        { 0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f },
-        { 0xbd4ea9e10f53c4b6, 0x1673dc5f8ac91a14, 0xa8f81a4e2acc1aba, 0x33a92a7924332a25 }
-    },
-    {
-        { 0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54 },
-        { 0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1 },
-        { 0x9d4f270466898d0a, 0x3d0987990aff3f7a, 0xd09ef36267daba45, 0x7761455e7b1c669c }
-    },
-},
-};
-#elif defined(CURVED25519_128BIT)
-static const ge_precomp base[32][8] = {
-{
-    {
-        { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b },
-        { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 },
-        { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 },
-    },
-    {
-        { 0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2 },
-        { 0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92 },
-        { 0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50 },
-    },
-    {
-        { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f },
-        { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd },
-        { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b },
-    },
-    {
-        { 0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58 },
-        { 0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a },
-        { 0x3fbe9c476ff09, 0x0af6b982e4b42, 0x0ad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553 },
-    },
-    {
-        { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 },
-        { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 },
-        { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb },
-    },
-    {
-        { 0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3 },
-        { 0x006b67b7d8ca4, 0x084fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417 },
-        { 0x4326702ea4b71, 0x06834376030b5, 0x0ef0512f9c380, 0x0f1a9f2512584, 0x10b8e91a9f0d6 },
-    },
-    {
-        { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 },
-        { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 },
-        { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 },
-    },
-    {
-        { 0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x0915e76061bce },
-        { 0x75dedf39234d9, 0x01c36ab1f3c54, 0x0f08fee58f5da, 0x0e19613a0d637, 0x3a9024a1320e0 },
-        { 0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4 },
-    },
-},
-{
-    {
-        { 0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee },
-        { 0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31 },
-        { 0x444172106e4c7, 0x01251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864 },
-    },
-    {
-        { 0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x03bf9baf55080 },
-        { 0x3c4277dbe5fde, 0x5a335afd44c92, 0x0c1164099753e, 0x70487006fe423, 0x25e61cabed66f },
-        { 0x3e128cc586604, 0x5968b2e8fc7e2, 0x049a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e },
-    },
-    {
-        { 0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b },
-        { 0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3 },
-        { 0x746166985f7d4, 0x09939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5 },
-    },
-    {
-        { 0x70b2f4e71ecb8, 0x728148efc643c, 0x0753e03995b76, 0x5bf5fb2ab6767, 0x05fc3bc4535d7 },
-        { 0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0x0b9cf062eb09e, 0x2fd9c71e5f758 },
-        { 0x0b3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651 },
-    },
-    {
-        { 0x095cb14246590, 0x002d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907 },
-        { 0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f },
-        { 0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x02521cf67a635 },
-    },
-    {
-        { 0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x001753d9f7cd6 },
-        { 0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382 },
-        { 0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e },
-    },
-    {
-        { 0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c },
-        { 0x0fbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x037e9023930ff, 0x749b76f96fb12 },
-        { 0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0x0a8b0d4045af7, 0x0fcec10f01e02 },
-    },
-    {
-        { 0x2d29dc4244e45, 0x6927b1bc147be, 0x0308534ac0839, 0x4853664033f41, 0x413779166feab },
-        { 0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0x0f981220e2d44, 0x4901aa7183c51 },
-        { 0x1b7548c1af8f0, 0x7848c53368116, 0x01b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1 },
-    },
-},
-{
-    {
-        { 0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0x0a871e070c6a9 },
-        { 0x07d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb },
-        { 0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d },
-    },
-    {
-        { 0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x01850832f0ef1, 0x7d47c6a2cfb89 },
-        { 0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912 },
-        { 0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e },
-    },
-    {
-        { 0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0x0dccfe885b6b4, 0x278febad4eaea },
-        { 0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db },
-        { 0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6 },
-    },
-    {
-        { 0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x0165b5a48efca },
-        { 0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5 },
-        { 0x0a474a0846a76, 0x099a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec },
-    },
-    {
-        { 0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301 },
-        { 0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7 },
-        { 0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb },
-    },
-    {
-        { 0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0x0adc8d1a97b28, 0x06a1a6c288675 },
-        { 0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6 },
-        { 0x0d1d47c1764b6, 0x01c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274 },
-    },
-    {
-        { 0x4278b85eaec2e, 0x0ef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059 },
-        { 0x777fd3a2dcc7f, 0x594a9fb124932, 0x01f8e80ca15f0, 0x714d13cec3269, 0x0403ed1d0ca67 },
-        { 0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303 },
-    },
-    {
-        { 0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f },
-        { 0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a },
-        { 0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x0690c11b03bcd, 0x740dca6d58f0e },
-    },
-},
-{
-    {
-        { 0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0 },
-        { 0x0ee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea },
-        { 0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b },
-    },
-    {
-        { 0x53de66aa91948, 0x045f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2 },
-        { 0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905 },
-        { 0x6134b925112e1, 0x6bb942bb406ed, 0x070c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032 },
-    },
-    {
-        { 0x1fec6f0e7f04c, 0x3cebc692c477d, 0x077986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab },
-        { 0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb },
-        { 0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43 },
-    },
-    {
-        { 0x4431ca596cf14, 0x015da7c801405, 0x03c9b6f8f10b5, 0x0346922934017, 0x201f33139e457 },
-        { 0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd },
-        { 0x27f6b08039d51, 0x4802f8000dfaa, 0x09692a062c525, 0x1baea91075817, 0x397cba8862460 },
-    },
-    {
-        { 0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c },
-        { 0x13093f05959b2, 0x1bd352f2ec618, 0x075789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6 },
-        { 0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971 },
-    },
-    {
-        { 0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a },
-        { 0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf },
-        { 0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x088fe4eb8c225, 0x612436341f08b },
-    },
-    {
-        { 0x349e31a2d2638, 0x0137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90 },
-        { 0x541db874e898d, 0x62d80fb841b33, 0x03e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef },
-        { 0x02f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x036746419c8db, 0x45fe70f505243 },
-    },
-    {
-        { 0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2 },
-        { 0x075a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39 },
-        { 0x74a4401a308fd, 0x06ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3 },
-    },
-},
-{
-    {
-        { 0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8 },
-        { 0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd },
-        { 0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe },
-    },
-    {
-        { 0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd },
-        { 0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0 },
-        { 0x3b0cf4a465030, 0x022b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82 },
-    },
-    {
-        { 0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6 },
-        { 0x004468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0x0bc3d08194a31 },
-        { 0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19 },
-    },
-    {
-        { 0x0c172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x0770c9e824e1a },
-        { 0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de },
-        { 0x1d99a45b5b5fd, 0x523674f2499ec, 0x0f8fa26182613, 0x58f7398048c98, 0x39f264fd41500 },
-    },
-    {
-        { 0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0x0a761e4844a16, 0x65c621272c35f },
-        { 0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889 },
-        { 0x389f8ce3193dd, 0x2d424b8177ce5, 0x073fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce },
-    },
-    {
-        { 0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c },
-        { 0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762 },
-        { 0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0x0d5fde948eed6, 0x508214fa574bd },
-    },
-    {
-        { 0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb },
-        { 0x269153ed6fe4b, 0x72a23aef89840, 0x052be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba },
-        { 0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f },
-    },
-    {
-        { 0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9 },
-        { 0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb },
-        { 0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb },
-    },
-},
-{
-    {
-        { 0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x0844bdee2adf3, 0x4cbad279663ab },
-        { 0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345 },
-        { 0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007 },
-    },
-    {
-        { 0x45dc5f3c29094, 0x3455220b579af, 0x070c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d },
-        { 0x71e6a266b2801, 0x09aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75 },
-        { 0x297d86a7b3768, 0x4835a2f4c6332, 0x070305f434160, 0x183dd014e56ae, 0x7ccdd084387a0 },
-    },
-    {
-        { 0x484186760cc93, 0x7435665533361, 0x02f686336b801, 0x5225446f64331, 0x3593ca848190c },
-        { 0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c },
-        { 0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6 },
-    },
-    {
-        { 0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3 },
-        { 0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3 },
-        { 0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc },
-    },
-    {
-        { 0x615520fbf6363, 0x0b9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1 },
-        { 0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f },
-        { 0x0c938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647 },
-    },
-    {
-        { 0x08bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f },
-        { 0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6 },
-        { 0x6b517a751b13b, 0x0cfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e },
-    },
-    {
-        { 0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0x0fe9877824cde },
-        { 0x3d2e0c30d0cd9, 0x3f597686671bb, 0x0aa587eb63999, 0x0e3c7b592c619, 0x6b2916c05448c },
-        { 0x334d10aba913b, 0x045cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00 },
-    },
-    {
-        { 0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0x0ea89850aafe1, 0x416b151ab706a },
-        { 0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0x0d61b8f78b2ab },
-        { 0x0d7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e },
-    },
-},
-{
-    {
-        { 0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545 },
-        { 0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc },
-        { 0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115 },
-    },
-    {
-        { 0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x00731fbc78f89 },
-        { 0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x021142e9c2b1c },
-        { 0x0c71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15 },
-    },
-    {
-        { 0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9 },
-        { 0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47 },
-        { 0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4 },
-    },
-    {
-        { 0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e },
-        { 0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189 },
-        { 0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x022183510be8d },
-    },
-    {
-        { 0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404 },
-        { 0x766385ead2d14, 0x0194f8b06095e, 0x08478f6823b62, 0x6018689d37308, 0x6a071ce17b806 },
-        { 0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed },
-    },
-    {
-        { 0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424 },
-        { 0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08 },
-        { 0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924 },
-    },
-    {
-        { 0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7 },
-        { 0x28e665ca59cc7, 0x165c715940dd9, 0x0785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84 },
-        { 0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57 },
-    },
-    {
-        { 0x6706efc7c3484, 0x6987839ec366d, 0x0731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6 },
-        { 0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64 },
-        { 0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21 },
-    },
-},
-{
-    {
-        { 0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da },
-        { 0x1214fe194961a, 0x0e1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917 },
-        { 0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a },
-    },
-    {
-        { 0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66 },
-        { 0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc },
-        { 0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f },
-    },
-    {
-        { 0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52 },
-        { 0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0x0d8cc1c48bc16 },
-        { 0x402d36eb419a9, 0x7cef68c14a052, 0x0f1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16 },
-    },
-    {
-        { 0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53 },
-        { 0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948 },
-        { 0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4 },
-    },
-    {
-        { 0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c },
-        { 0x094e7d7dced2a, 0x068fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99 },
-        { 0x26c422e3622f4, 0x0f3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952 },
-    },
-    {
-        { 0x00c2af5f85c6b, 0x0609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0x0d1d2af9ffeb5 },
-        { 0x0ed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x004475ea1a1bb, 0x0fee3e871e188 },
-        { 0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531 },
-    },
-    {
-        { 0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161 },
-        { 0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302 },
-        { 0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f },
-    },
-    {
-        { 0x780f1680c3a94, 0x2a35d3cfcd453, 0x005e5cdc7ddf8, 0x6ee888078ac24, 0x054aa4b316b38 },
-        { 0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1 },
-        { 0x0468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da },
-    },
-},
-{
-    {
-        { 0x265e777d1f515, 0x0f1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc },
-        { 0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d },
-        { 0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0x0ad725db29ecb },
-    },
-    {
-        { 0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399 },
-        { 0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03 },
-        { 0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0x0bccbb72a2a86 },
-    },
-    {
-        { 0x55e4c50fe1296, 0x05fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3 },
-        { 0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b },
-        { 0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4 },
-    },
-    {
-        { 0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423 },
-        { 0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d },
-        { 0x0ba651c5b2b47, 0x5862363701027, 0x0c4d6c219c6db, 0x0f03dff8658de, 0x745d2ffa9c0cf },
-    },
-    {
-        { 0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x06e15be54c1dc },
-        { 0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf },
-        { 0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0x0fbbee20aa4ed, 0x58ded861278ec },
-    },
-    {
-        { 0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x08ba696b531d5 },
-        { 0x73793f266c55c, 0x0b988a9c93b02, 0x09b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f },
-        { 0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf },
-    },
-    {
-        { 0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x07433be3cb393 },
-        { 0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0x0c2b85f39caca, 0x35d30a99b4d59 },
-        { 0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d },
-    },
-    {
-        { 0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x0543618a01600 },
-        { 0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa },
-        { 0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079 },
-    },
-},
-{
-    {
-        { 0x454e91c529ccb, 0x24c98c6bf72cf, 0x0486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66 },
-        { 0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6 },
-        { 0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0x0c2a1c4bcda28 },
-    },
-    {
-        { 0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d },
-        { 0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64 },
-        { 0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x0404a5ca0afba },
-    },
-    {
-        { 0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e },
-        { 0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9 },
-        { 0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0x00b77ea5f78aa, 0x76579a29e822d },
-    },
-    {
-        { 0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x02c514bb2a277 },
-        { 0x68e7e49c02a17, 0x45795346fe8b6, 0x089306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b },
-        { 0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x02c989c8b6bd4, 0x1160920961548 },
-    },
-    {
-        { 0x05616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x0213ee10dfcea, 0x2f637d7491e6e },
-        { 0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698 },
-        { 0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2 },
-    },
-    {
-        { 0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5 },
-        { 0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9 },
-        { 0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0x0dea56e50e364, 0x556d1c8312ad7 },
-    },
-    {
-        { 0x06756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x097abe38cc8c7 },
-        { 0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824 },
-        { 0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8 },
-    },
-    {
-        { 0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009 },
-        { 0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78 },
-        { 0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635 },
-    },
-},
-{
-    {
-        { 0x0aaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7 },
-        { 0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23 },
-        { 0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895 },
-    },
-    {
-        { 0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x0408cc9469953, 0x50af7aed84afa },
-        { 0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313 },
-        { 0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x0033c0102c085, 0x1921a316baebd },
-    },
-    {
-        { 0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c },
-        { 0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a },
-        { 0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950 },
-    },
-    {
-        { 0x6eebe6084034b, 0x6cf01f70a8d7b, 0x0b41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647 },
-        { 0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a },
-        { 0x2b6e7a128b071, 0x5b27511755dcf, 0x08584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b },
-    },
-    {
-        { 0x048dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b },
-        { 0x043c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0 },
-        { 0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x079bfa9b08792 },
-    },
-    {
-        { 0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706 },
-        { 0x03a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0x0ca769e789685, 0x038c77f684817 },
-        { 0x65ee65b167bec, 0x052da19b850a9, 0x0408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf },
-    },
-    {
-        { 0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5 },
-        { 0x080908a182fcf, 0x0532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f },
-        { 0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x050eca52651e4 },
-    },
-    {
-        { 0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a },
-        { 0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f },
-        { 0x55c0dfdf05d96, 0x405569dcf475e, 0x05c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0 },
-    },
-},
-{
-    {
-        { 0x2aff530976b86, 0x0d85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340 },
-        { 0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x09f56900584fd, 0x544d49292fc86 },
-        { 0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316 },
-    },
-    {
-        { 0x3f635d32a7627, 0x0cbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06 },
-        { 0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a },
-        { 0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0x00f94051ee040 },
-    },
-    {
-        { 0x793bb07af9753, 0x1e7b6ecd4fafd, 0x02c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40 },
-        { 0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x086d9b618b637, 0x07d79c7e8beab },
-        { 0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64 },
-    },
-    {
-        { 0x06f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12 },
-        { 0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee },
-        { 0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x0621e2c7d3304 },
-    },
-    {
-        { 0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002 },
-        { 0x060cc8259838d, 0x038d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x0007d6097bd3a },
-        { 0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb },
-    },
-    {
-        { 0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55 },
-        { 0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x02459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8 },
-        { 0x094265066e80d, 0x0a60f918d61a5, 0x0444bf7f30fde, 0x1c40da9ed3c06, 0x079c170bd843b },
-    },
-    {
-        { 0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8 },
-        { 0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f },
-        { 0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5 },
-    },
-    {
-        { 0x147ab2bbea455, 0x1f240f2253126, 0x0c3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd },
-        { 0x02b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929 },
-        { 0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9 },
-    },
-},
-{
-    {
-        { 0x0639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x07a195152e095 },
-        { 0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32 },
-        { 0x68f02389e5fc8, 0x059f1bc877506, 0x504990e410cec, 0x09bd7d0feaee2, 0x3e8fe83d032f0 },
-    },
-    {
-        { 0x04c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258 },
-        { 0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x003ef0e2d70b0, 0x75ba3b797fac4 },
-        { 0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x0904d07b87779 },
-    },
-    {
-        { 0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72 },
-        { 0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd },
-        { 0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40 },
-    },
-    {
-        { 0x0d36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x03aa31507e1e5 },
-        { 0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741 },
-        { 0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4 },
-    },
-    {
-        { 0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x02b4d5e242940 },
-        { 0x31e1988bb79bb, 0x7b82f46b3bcab, 0x0f7a8ce827b41, 0x5e15816177130, 0x326055cf5b276 },
-        { 0x155cb28d18df2, 0x0c30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3 },
-    },
-    {
-        { 0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2 },
-        { 0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0x0bf79176fd18a, 0x2cb67174ff60a },
-        { 0x6cdf9390be1d0, 0x08e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f },
-    },
-    {
-        { 0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x01ed95554468f, 0x68698245d352e },
-        { 0x2f2e0b3b2a224, 0x0c56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5 },
-        { 0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0x0e7a25d714087, 0x46cf4c473daf0 },
-    },
-    {
-        { 0x46ea7f1498140, 0x70725690a8427, 0x0a73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc },
-        { 0x525ed9ec4e5f9, 0x022d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5 },
-        { 0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce },
-    },
-},
-{
-    {
-        { 0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f },
-        { 0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0x0dfcefaa53320, 0x7369e6a92493a },
-        { 0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4 },
-    },
-    {
-        { 0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0x0e0e9d86d24d3, 0x31e83b4161d08 },
-        { 0x0bd1e249dd197, 0x00bcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a },
-        { 0x0c7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550 },
-    },
-    {
-        { 0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x099dec18e71a4, 0x1a56fbaa62ba0 },
-        { 0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0x0ea712017d489, 0x669a656457089 },
-        { 0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58 },
-    },
-    {
-        { 0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b },
-        { 0x25d465ab3e1b9, 0x0f8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b },
-        { 0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd },
-    },
-    {
-        { 0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30 },
-        { 0x47ff83362127d, 0x08e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0x0e645912219f7 },
-        { 0x72f31d8394627, 0x07bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a },
-    },
-    {
-        { 0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950 },
-        { 0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5 },
-        { 0x06edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x05bff02328a11 },
-    },
-    {
-        { 0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a },
-        { 0x2137023cae00b, 0x15a3599eb26c6, 0x0687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4 },
-        { 0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b },
-    },
-    {
-        { 0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c },
-        { 0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96 },
-        { 0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb },
-    },
-},
-{
-    {
-        { 0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x058d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2 },
-        { 0x42b256768d593, 0x2e88459427b4f, 0x02b3876630701, 0x34878d405eae5, 0x29cdd1adc088a },
-        { 0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049 },
-    },
-    {
-        { 0x59a5fd67ff163, 0x3a998ead0352b, 0x083c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072 },
-        { 0x0fd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0x0a4a26e2e2182, 0x5be8cc57092a7 },
-        { 0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791 },
-    },
-    {
-        { 0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018 },
-        { 0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030 },
-        { 0x0172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x0728b6bfe6e91, 0x08420edd5fcdf },
-    },
-    {
-        { 0x0c34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x04d654f321db8 },
-        { 0x720ab8362fa4a, 0x29c4347cdd9bf, 0x0e798ad5f8463, 0x4fef18bcb0bfe, 0x0d9a53efbc176 },
-        { 0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991 },
-    },
-    {
-        { 0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e },
-        { 0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31 },
-        { 0x0274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc },
-    },
-    {
-        { 0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595 },
-        { 0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0x0f3690d04eb8e, 0x73fcdd14b71c0 },
-        { 0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0x0eb26573b10af, 0x389e740c9a9ce },
-    },
-    {
-        { 0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263 },
-        { 0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6 },
-        { 0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484 },
-    },
-    {
-        { 0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0x0f65320ef019b },
-        { 0x21f74c3d2f773, 0x024b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1 },
-        { 0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330 },
-    },
-},
-{
-    {
-        { 0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x010f93bc5fe67, 0x7ee498165acb2 },
-        { 0x69624089c0a2e, 0x0075fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8 },
-        { 0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0x0edf493c85b60 },
-    },
-    {
-        { 0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x04c00c54d1dfa },
-        { 0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4 },
-        { 0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617 },
-    },
-    {
-        { 0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a },
-        { 0x664cc7493bbf4, 0x33d94761874e3, 0x0179e1796f613, 0x1890535e2867d, 0x0f9b8132182ec },
-        { 0x059c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175 },
-    },
-    {
-        { 0x65d50c85066b0, 0x6167453361f7c, 0x06ba3818bb312, 0x6aff29baa7522, 0x08fea02ce8d48 },
-        { 0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0x00b89b8576469 },
-        { 0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d },
-    },
-    {
-        { 0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d },
-        { 0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c },
-        { 0x0cf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4 },
-    },
-    {
-        { 0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3 },
-        { 0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813 },
-        { 0x6a4d400a2509b, 0x041791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6 },
-    },
-    {
-        { 0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a },
-        { 0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879 },
-        { 0x0a0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e },
-    },
-    {
-        { 0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce },
-        { 0x193434934d643, 0x0d4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9 },
-        { 0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9 },
-    },
-},
-{
-    {
-        { 0x304bfacad8ea2, 0x502917d108b07, 0x043176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b },
-        { 0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d },
-        { 0x014d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd },
-    },
-    {
-        { 0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247 },
-        { 0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b },
-        { 0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2 },
-    },
-    {
-        { 0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4 },
-        { 0x6cfab8de73e68, 0x3e6efced4bd21, 0x0056609500dbe, 0x71b7824ad85df, 0x577629c4a7f41 },
-        { 0x0024509c6a888, 0x2696ab12e6644, 0x0cca27f4b80d8, 0x0c7c1f11b119e, 0x701f25bb0caec },
-    },
-    {
-        { 0x0f6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955 },
-        { 0x0b0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40 },
-        { 0x709439b805a35, 0x6ec48557f8187, 0x08a4d1ba13a2c, 0x076348a0bf9ae, 0x0e9b9cbb144ef },
-    },
-    {
-        { 0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3 },
-        { 0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337 },
-        { 0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593 },
-    },
-    {
-        { 0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed },
-        { 0x39d2876f62700, 0x001cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552 },
-        { 0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6 },
-    },
-    {
-        { 0x0e28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690 },
-        { 0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x08fc3a4c677d5 },
-        { 0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x068f1199f11fb, 0x4f2fad0116b90 },
-    },
-    {
-        { 0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e },
-        { 0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef },
-        { 0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289 },
-    },
-},
-{
-    {
-        { 0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4 },
-        { 0x147499718289c, 0x0a48a67e4c7ab, 0x30fbc544bafe3, 0x0c701315fe58a, 0x20b878d577b75 },
-        { 0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c },
-    },
-    {
-        { 0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154 },
-        { 0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c },
-        { 0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0x00ba739e2ae39 },
-    },
-    {
-        { 0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d },
-        { 0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x03283a3e67ad7 },
-        { 0x41dc7be0cb939, 0x1b16c66100904, 0x0a24c20cbc66d, 0x4a2e9efe48681, 0x05e1296846271 },
-    },
-    {
-        { 0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c },
-        { 0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698 },
-        { 0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x006b52076b3ff },
-    },
-    {
-        { 0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7 },
-        { 0x0cfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x0912bef9ce9b8, 0x4d57e3443bc76 },
-        { 0x0d4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602 },
-    },
-    {
-        { 0x3f3245bb2d80a, 0x0e5f720f36efd, 0x3b9cccf60c06d, 0x084e323f37926, 0x465812c8276c2 },
-        { 0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3 },
-        { 0x3beb22a1062d9, 0x6a7063b82c9a8, 0x0a5a35dc197ed, 0x3c80c06a53def, 0x05b32c2b1cb16 },
-    },
-    {
-        { 0x4a42c7ad58195, 0x5c8667e799eff, 0x02e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730 },
-        { 0x05eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471 },
-        { 0x0c524e14dd482, 0x283457496c656, 0x0ad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733 },
-    },
-    {
-        { 0x48b440c86c50d, 0x139929cca3b86, 0x0f8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c },
-        { 0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98 },
-        { 0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x006a573a83075, 0x3f8612966c870 },
-    },
-},
-{
-    {
-        { 0x0fcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1 },
-        { 0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x09ebfb1432d98, 0x504aa77679736 },
-        { 0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x034c2e0ad1a27, 0x4041943d9dba3 },
-    },
-    {
-        { 0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0x00ce58ea7bd01, 0x12d931429800d },
-        { 0x0eeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843 },
-        { 0x67799d337594f, 0x01647548f6018, 0x57fce5578f145, 0x009220c142a71, 0x1b4f92314359a },
-    },
-    {
-        { 0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2 },
-        { 0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132 },
-        { 0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x020c526a758f3 },
-    },
-    {
-        { 0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c },
-        { 0x034f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x02aacc4615313 },
-        { 0x0f7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8 },
-    },
-    {
-        { 0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3 },
-        { 0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075 },
-        { 0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592 },
-    },
-    {
-        { 0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614 },
-        { 0x4a74cb50f9e56, 0x531d1c2640192, 0x0c03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a },
-        { 0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25 },
-    },
-    {
-        { 0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d },
-        { 0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce },
-        { 0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1 },
-    },
-    {
-        { 0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2 },
-        { 0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172 },
-        { 0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d },
-    },
-},
-{
-    {
-        { 0x08d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d },
-        { 0x0071b276d01c9, 0x0b0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db },
-        { 0x00f1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x06e1cd13b19ea },
-    },
-    {
-        { 0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837 },
-        { 0x0ad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16 },
-        { 0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x03f3466bc182c, 0x30d0fded2e513 },
-    },
-    {
-        { 0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58 },
-        { 0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0x0a9214202c099 },
-        { 0x019c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5 },
-    },
-    {
-        { 0x08eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28 },
-        { 0x031bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1 },
-        { 0x5460af1cad202, 0x0b4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca },
-    },
-    {
-        { 0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4 },
-        { 0x090f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d },
-        { 0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf },
-    },
-    {
-        { 0x04a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018 },
-        { 0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x08f338d0c85ee },
-        { 0x3a821991a73bd, 0x03be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078 },
-    },
-    {
-        { 0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0x0db3e7e00cbfb },
-        { 0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x05ce3a41191e6, 0x65ea753f10177 },
-        { 0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0x0ed87df022109, 0x02a4ec1921e1a },
-    },
-    {
-        { 0x06162f1cf795f, 0x324ddcafe5eb9, 0x018d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067 },
-        { 0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780 },
-        { 0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82 },
-    },
-},
-{
-    {
-        { 0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x04af87a96e3a3, 0x57968290bb3a0 },
-        { 0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a },
-        { 0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa },
-    },
-    {
-        { 0x02a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x044fb81d82d50 },
-        { 0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x097e37046fc77, 0x7ef72016758cc },
-        { 0x718c5a907e3d9, 0x3b9c98c6b383b, 0x006ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d },
-    },
-    {
-        { 0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d },
-        { 0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0x0a4e0373d784d },
-        { 0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x071a7d0ace183 },
-    },
-    {
-        { 0x4355220e14431, 0x0e1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775 },
-        { 0x72daac887ba0b, 0x0b7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7 },
-        { 0x0d7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca },
-    },
-    {
-        { 0x1d4eba3d944be, 0x0100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x02ab9680ee8d3 },
-        { 0x1000c2f41c6c5, 0x0219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a },
-        { 0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b },
-    },
-    {
-        { 0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x09f20459f5168, 0x16fb869c03dd3 },
-        { 0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0x0ae333f685277 },
-        { 0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x03aa408fbf684, 0x3f81e38b8f70d },
-    },
-    {
-        { 0x37f355f17c824, 0x07ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0x0ad3e2d34cded },
-        { 0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50 },
-        { 0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1 },
-    },
-    {
-        { 0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d },
-        { 0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4 },
-        { 0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392 },
-    },
-},
-{
-    {
-        { 0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x0302f0cb36a3c, 0x0edc5f5eb426d },
-        { 0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca },
-        { 0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb },
-    },
-    {
-        { 0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122 },
-        { 0x02abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x09d8eddeaa591, 0x2177bfa36dcb7 },
-        { 0x01bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab },
-    },
-    {
-        { 0x17e44985bfb83, 0x54e32c626cc22, 0x096412ff38118, 0x6b241d61a246a, 0x75685abe5ba43 },
-        { 0x3f6aa5344a32e, 0x69683680f11bb, 0x04c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3 },
-        { 0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e },
-    },
-    {
-        { 0x716bce22e83fe, 0x33d0130b83eb8, 0x0952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a },
-        { 0x0dbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3 },
-        { 0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3 },
-    },
-    {
-        { 0x0443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a },
-        { 0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638 },
-        { 0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c },
-    },
-    {
-        { 0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x055dc39b6dea1 },
-        { 0x7937ff7f927c2, 0x0c2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2 },
-        { 0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2 },
-    },
-    {
-        { 0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3 },
-        { 0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e },
-        { 0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a },
-    },
-    {
-        { 0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x0473d308a7639 },
-        { 0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e },
-        { 0x6792603589e05, 0x248db9892595d, 0x006a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043 },
-    },
-},
-{
-    {
-        { 0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x096cc0f9baefa, 0x3f6bd725da4ea },
-        { 0x0b9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x09edb93896d16, 0x36597d25ea5c0 },
-        { 0x58d7b106058ac, 0x3cdf8d20bee69, 0x00a4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d },
-    },
-    {
-        { 0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x03bedc661bf5c },
-        { 0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743 },
-        { 0x0cb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0x0e7ce2b0cdf06 },
-    },
-    {
-        { 0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece },
-        { 0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46 },
-        { 0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d },
-    },
-    {
-        { 0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a },
-        { 0x06ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0x0d1f8dbcf8eed },
-        { 0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x00011b44a31bf },
-    },
-    {
-        { 0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x01308d46ebfcd, 0x63d988a2d2851 },
-        { 0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835 },
-        { 0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x0337c0b34d9c2, 0x33fad52b2368a },
-    },
-    {
-        { 0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0x0f151ff5b7376, 0x3cc355ccb90a7 },
-        { 0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d },
-        { 0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7 },
-    },
-    {
-        { 0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x05aa9b2c79399, 0x431f2c7f665f8 },
-        { 0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91 },
-        { 0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253 },
-    },
-    {
-        { 0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde },
-        { 0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65 },
-        { 0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3 },
-    },
-},
-{
-    {
-        { 0x19cd61ff38640, 0x060c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9 },
-        { 0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x00311d00a9ff4, 0x2cdfdfecd5d05 },
-        { 0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4 },
-    },
-    {
-        { 0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x07eb1f28bbe70, 0x03c935afc4b03 },
-        { 0x65517fd181bae, 0x3e5772c76816d, 0x019189640898a, 0x1ed2a84de7499, 0x578edd74f63c1 },
-        { 0x276c6492b0c3d, 0x09bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c },
-    },
-    {
-        { 0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x07aaca43cae1f, 0x62f05d7526374, 0x0e1bf66c6adba },
-        { 0x0d27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc },
-        { 0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88 },
-    },
-    {
-        { 0x3094ba1d6e334, 0x6e126a7e3300b, 0x089c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784 },
-        { 0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db },
-        { 0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9 },
-    },
-    {
-        { 0x073a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f },
-        { 0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84 },
-        { 0x12f5c6f136c7c, 0x0fedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f },
-    },
-    {
-        { 0x153d8f5e08181, 0x08533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f },
-        { 0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3 },
-        { 0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212 },
-    },
-    {
-        { 0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6 },
-        { 0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38 },
-        { 0x44ead1be8f7d6, 0x5759d4f31f466, 0x0378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6 },
-    },
-    {
-        { 0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x03a134ced89df, 0x7dcf843ce405f },
-        { 0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f },
-        { 0x0d6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271 },
-    },
-},
-{
-    {
-        { 0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7 },
-        { 0x02014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x059a668f5a82e, 0x46115aba1d4dc },
-        { 0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674 },
-    },
-    {
-        { 0x628d3a0a643b9, 0x01cd8640c93d2, 0x0b7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c },
-        { 0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1 },
-        { 0x63f06eda6e133, 0x233342758070f, 0x098e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e },
-    },
-    {
-        { 0x129126699b2e3, 0x0ee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8 },
-        { 0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f },
-        { 0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0x0bcd601a4e930, 0x0eafb03790e52 },
-    },
-    {
-        { 0x0805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435 },
-        { 0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c },
-        { 0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946 },
-    },
-    {
-        { 0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x01bd28338402c, 0x14f29a5383922 },
-        { 0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754 },
-        { 0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0 },
-    },
-    {
-        { 0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734 },
-        { 0x3fc074571217f, 0x3a0d29b2b6aeb, 0x06478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e },
-        { 0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x02522333bc2af, 0x0e34398f4a064 },
-    },
-    {
-        { 0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379 },
-        { 0x522d93ecebde8, 0x024f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362 },
-        { 0x0123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d },
-    },
-    {
-        { 0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58 },
-        { 0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0x0eb28bf671928 },
-        { 0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2 },
-    },
-},
-{
-    {
-        { 0x6f4bd567ae7a9, 0x65ac89317b783, 0x07d3b20fd8932, 0x000f208326916, 0x2ef9c5a5ba384 },
-        { 0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c },
-        { 0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f },
-    },
-    {
-        { 0x0918b1d61dc94, 0x0d350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0x0a738027f639d },
-        { 0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7 },
-        { 0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a },
-    },
-    {
-        { 0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3 },
-        { 0x5318832b0ba78, 0x6f24b9ff17cec, 0x0a47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae },
-        { 0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd },
-    },
-    {
-        { 0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d },
-        { 0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f },
-        { 0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b },
-    },
-    {
-        { 0x190b1829825d5, 0x0e7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2 },
-        { 0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x04321adf49d75 },
-        { 0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70 },
-    },
-    {
-        { 0x64624cfccb1ed, 0x257ab8072b6c1, 0x0120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d },
-        { 0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d },
-        { 0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621 },
-    },
-    {
-        { 0x18e3cc676e542, 0x26079d995a990, 0x04a7c217908b2, 0x1dc7603e6655a, 0x0dedfa10b2444 },
-        { 0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615 },
-        { 0x367d5b82b522a, 0x0d3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9 },
-    },
-    {
-        { 0x72836afb62874, 0x0af3c2094b240, 0x0c285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663 },
-        { 0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d },
-        { 0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05 },
-    },
-},
-{
-    {
-        { 0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320 },
-        { 0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b },
-        { 0x5fdcb41446a8e, 0x5286926ff2a71, 0x0f231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0 },
-    },
-    {
-        { 0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067 },
-        { 0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed },
-        { 0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d },
-    },
-    {
-        { 0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb },
-        { 0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0x0a3b6063214f2, 0x5065f158c9fd2 },
-        { 0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f },
-    },
-    {
-        { 0x5dfa56de66fde, 0x0058809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1 },
-        { 0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x07e9d42d4a28a, 0x38dc083705acd },
-        { 0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2 },
-    },
-    {
-        { 0x1fd11ed0c84a7, 0x021b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64 },
-        { 0x36b15b807cba6, 0x3f78a9e1afed7, 0x0a59c2c608f1f, 0x52bdd8ecb81b7, 0x0b24f48847ed4 },
-        { 0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481 },
-    },
-    {
-        { 0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x0119a3042fb37 },
-        { 0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6 },
-        { 0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20 },
-    },
-    {
-        { 0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x038b7ea483590 },
-        { 0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x09674c6b99108 },
-        { 0x6f82199316ff8, 0x05d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e },
-    },
-    {
-        { 0x4fb0e63066222, 0x130f59747e660, 0x041868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838 },
-        { 0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x08f5114789a8d },
-        { 0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d },
-    },
-},
-{
-    {
-        { 0x68549af3f666e, 0x09e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3 },
-        { 0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x07fea2aba5132, 0x1926e1dc6401e },
-        { 0x74e8aea17cea0, 0x0c743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5 },
-    },
-    {
-        { 0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0x0f2bf89f49f7e, 0x73fced18ee9a0 },
-        { 0x055947d599832, 0x346fe2aa41990, 0x0164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c },
-        { 0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864 },
-    },
-    {
-        { 0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0x0b76bb1b3fa7e },
-        { 0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x0482c3aed35f9, 0x4e1af5271d31b },
-        { 0x0c1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a },
-    },
-    {
-        { 0x0abf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6 },
-        { 0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2 },
-        { 0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61 },
-    },
-    {
-        { 0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30 },
-        { 0x3d16733e248f3, 0x0e2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191 },
-        { 0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd },
-    },
-    {
-        { 0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e },
-        { 0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f },
-        { 0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba },
-    },
-    {
-        { 0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x094707842cf44, 0x7dd73f960725d },
-        { 0x42ddf2845ab2c, 0x6214ffd3276bb, 0x00b8d181a5246, 0x268a6d579eb20, 0x093ff26e58647 },
-        { 0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x05209b3929d5a, 0x2f59bcbc86b47 },
-    },
-    {
-        { 0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082 },
-        { 0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a },
-        { 0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768 },
-    },
-},
-{
-    {
-        { 0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9 },
-        { 0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce },
-        { 0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e },
-    },
-    {
-        { 0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a },
-        { 0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252 },
-        { 0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459 },
-    },
-    {
-        { 0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340 },
-        { 0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f },
-        { 0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0x0f8893f02210c, 0x15596b3ae5710 },
-    },
-    {
-        { 0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x09c1495be913f, 0x3aa4e241afb6d },
-        { 0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0x0d2237687b5f4 },
-        { 0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a },
-    },
-    {
-        { 0x7a4732787ccdf, 0x11e427c7f0640, 0x03659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600 },
-        { 0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6 },
-        { 0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66 },
-    },
-    {
-        { 0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd },
-        { 0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f },
-        { 0x232cda2b4e554, 0x0422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x02c70bf52b68e },
-    },
-    {
-        { 0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43 },
-        { 0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef },
-        { 0x0f04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2 },
-    },
-    {
-        { 0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196 },
-        { 0x7565a5cc7324f, 0x01ca0d5244a11, 0x116b067418713, 0x0a57d8c55edae, 0x6c6809c103803 },
-        { 0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x05911b9f6ef7c },
-    },
-},
-{
-    {
-        { 0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2 },
-        { 0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270 },
-        { 0x770ba3b73bd08, 0x11475f7e186d4, 0x0251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817 },
-    },
-    {
-        { 0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3 },
-        { 0x452036b1782fc, 0x02d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c },
-        { 0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda },
-    },
-    {
-        { 0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b },
-        { 0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db },
-        { 0x2aa650dfa5ce7, 0x54916a8f19415, 0x00dc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091 },
-    },
-    {
-        { 0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a },
-        { 0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x0040f3d945441 },
-        { 0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254 },
-    },
-    {
-        { 0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7 },
-        { 0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78 },
-        { 0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c },
-    },
-    {
-        { 0x6d317e820107c, 0x090815d2ca3ca, 0x03ff1eb1499a1, 0x23960f050e319, 0x5373669c91611 },
-        { 0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78 },
-        { 0x014ab9a0e5257, 0x09939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87 },
-    },
-    {
-        { 0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x02f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6 },
-        { 0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743 },
-        { 0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1 },
-    },
-    {
-        { 0x0bc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5 },
-        { 0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d },
-        { 0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287 },
-    },
-},
-{
-    {
-        { 0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x087ed7e3bc55f, 0x7deb10149c726 },
-        { 0x048478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a },
-        { 0x2af6a8766ee7a, 0x08aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x08e68e9ff62ce },
-    },
-    {
-        { 0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71 },
-        { 0x5500a4bc130ad, 0x127a17a938695, 0x02a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3 },
-        { 0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2 },
-    },
-    {
-        { 0x172cdd596bdbd, 0x0731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a },
-        { 0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3 },
-        { 0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa },
-    },
-    {
-        { 0x55261e293eac6, 0x06426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x0760bb8d195ad },
-        { 0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2 },
-        { 0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac },
-    },
-    {
-        { 0x469656571f2d3, 0x0aa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x01b9c7b62e6dd },
-        { 0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d },
-        { 0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x08af5b784e4ba },
-    },
-    {
-        { 0x314d289cc2c4b, 0x23450e2f1bc4e, 0x0cd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98 },
-        { 0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1 },
-        { 0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2 },
-    },
-    {
-        { 0x14ce442ce221f, 0x18980a72516cc, 0x072f80db86677, 0x703331fda526e, 0x24b31d47691c8 },
-        { 0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b },
-        { 0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x04a7857b309a7, 0x545b585d14dda },
-    },
-    {
-        { 0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x038858667fead, 0x4d22dc3e64c8d },
-        { 0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0x0f62f9c332ba5 },
-        { 0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371 },
-    },
-},
-{
-    {
-        { 0x02b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0x0a037db9f2a62, 0x4005419b1d2bc },
-        { 0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0x0fa3614f3b1ca },
-        { 0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a },
-    },
-    {
-        { 0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0x0eae41ce355cc, 0x6c535d13ff776 },
-        { 0x49448fac8f53e, 0x34f74c6e8356a, 0x0ad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86 },
-        { 0x534e93e8a35af, 0x08b10fd02c997, 0x26ac2acb81e05, 0x09d8c98ce3b79, 0x25e17fe4d50ac },
-    },
-    {
-        { 0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698 },
-        { 0x09bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb },
-        { 0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7 },
-    },
-    {
-        { 0x091e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd },
-        { 0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x01ab12d5807e3 },
-        { 0x5189041e32d96, 0x05b062b090231, 0x0c91766e7b78f, 0x0aa0f55a138ec, 0x4a3961e2c918a },
-    },
-    {
-        { 0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x08fc1dad38b79, 0x68aceead9bd41 },
-        { 0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db },
-        { 0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f },
-    },
-    {
-        { 0x2cbebfd022790, 0x0b8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515 },
-        { 0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0x0d49fc5e044be, 0x709fa43edcb29 },
-        { 0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81 },
-    },
-    {
-        { 0x2afaa5e10b0b9, 0x61de08355254d, 0x0eb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd },
-        { 0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0x0b7d5d8a6c314 },
-        { 0x448327b95d543, 0x0146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de },
-    },
-    {
-        { 0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x053713fe3b7e6, 0x19735fd7f6bc2 },
-        { 0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc },
-        { 0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0x0fef911191df8 },
-    },
-},
-};
-#else
-/* base[i][j] = (j+1)*256^i*B */
-static const ge_precomp base[32][8] = {
-{
- {
-  { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
-  { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
-  { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
- },
- {
-  { -12815894,-12976347,-21581243,11784320,-25355658,-2750717,-11717903,-3814571,-358445,-10211303 },
-  { -21703237,6903825,27185491,6451973,-29577724,-9554005,-15616551,11189268,-26829678,-5319081 },
-  { 26966642,11152617,32442495,15396054,14353839,-12752335,-3128826,-9541118,-15472047,-4166697 },
- },
- {
-  { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
-  { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
-  { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
- },
- {
-  { -17036878,13921892,10945806,-6033431,27105052,-16084379,-28926210,15006023,3284568,-6276540 },
-  { 23599295,-8306047,-11193664,-7687416,13236774,10506355,7464579,9656445,13059162,10374397 },
-  { 7798556,16710257,3033922,2874086,28997861,2835604,32406664,-3839045,-641708,-101325 },
- },
- {
-  { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
-  { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
-  { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
- },
- {
-  { -15371964,-12862754,32573250,4720197,-26436522,5875511,-19188627,-15224819,-9818940,-12085777 },
-  { -8549212,109983,15149363,2178705,22900618,4543417,3044240,-15689887,1762328,14866737 },
-  { -18199695,-15951423,-10473290,1707278,-17185920,3916101,-28236412,3959421,27914454,4383652 },
- },
- {
-  { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
-  { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
-  { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
- },
- {
-  { 14499471,-2729599,-33191113,-4254652,28494862,14271267,30290735,10876454,-33154098,2381726 },
-  { -7195431,-2655363,-14730155,462251,-27724326,3941372,-6236617,3696005,-32300832,15351955 },
-  { 27431194,8222322,16448760,-3907995,-18707002,11938355,-32961401,-2970515,29551813,10109425 },
- },
-},
-{
- {
-  { -13657040,-13155431,-31283750,11777098,21447386,6519384,-2378284,-1627556,10092783,-4764171 },
-  { 27939166,14210322,4677035,16277044,-22964462,-12398139,-32508754,12005538,-17810127,12803510 },
-  { 17228999,-15661624,-1233527,300140,-1224870,-11714777,30364213,-9038194,18016357,4397660 },
- },
- {
-  { -10958843,-7690207,4776341,-14954238,27850028,-15602212,-26619106,14544525,-17477504,982639 },
-  { 29253598,15796703,-2863982,-9908884,10057023,3163536,7332899,-4120128,-21047696,9934963 },
-  { 5793303,16271923,-24131614,-10116404,29188560,1206517,-14747930,4559895,-30123922,-10897950 },
- },
- {
-  { -27643952,-11493006,16282657,-11036493,28414021,-15012264,24191034,4541697,-13338309,5500568 },
-  { 12650548,-1497113,9052871,11355358,-17680037,-8400164,-17430592,12264343,10874051,13524335 },
-  { 25556948,-3045990,714651,2510400,23394682,-10415330,33119038,5080568,-22528059,5376628 },
- },
- {
-  { -26088264,-4011052,-17013699,-3537628,-6726793,1920897,-22321305,-9447443,4535768,1569007 },
-  { -2255422,14606630,-21692440,-8039818,28430649,8775819,-30494562,3044290,31848280,12543772 },
-  { -22028579,2943893,-31857513,6777306,13784462,-4292203,-27377195,-2062731,7718482,14474653 },
- },
- {
-  { 2385315,2454213,-22631320,46603,-4437935,-15680415,656965,-7236665,24316168,-5253567 },
-  { 13741529,10911568,-33233417,-8603737,-20177830,-1033297,33040651,-13424532,-20729456,8321686 },
-  { 21060490,-2212744,15712757,-4336099,1639040,10656336,23845965,-11874838,-9984458,608372 },
- },
- {
-  { -13672732,-15087586,-10889693,-7557059,-6036909,11305547,1123968,-6780577,27229399,23887 },
-  { -23244140,-294205,-11744728,14712571,-29465699,-2029617,12797024,-6440308,-1633405,16678954 },
-  { -29500620,4770662,-16054387,14001338,7830047,9564805,-1508144,-4795045,-17169265,4904953 },
- },
- {
-  { 24059557,14617003,19037157,-15039908,19766093,-14906429,5169211,16191880,2128236,-4326833 },
-  { -16981152,4124966,-8540610,-10653797,30336522,-14105247,-29806336,916033,-6882542,-2986532 },
-  { -22630907,12419372,-7134229,-7473371,-16478904,16739175,285431,2763829,15736322,4143876 },
- },
- {
-  { 2379352,11839345,-4110402,-5988665,11274298,794957,212801,-14594663,23527084,-16458268 },
-  { 33431127,-11130478,-17838966,-15626900,8909499,8376530,-32625340,4087881,-15188911,-14416214 },
-  { 1767683,7197987,-13205226,-2022635,-13091350,448826,5799055,4357868,-4774191,-16323038 },
- },
-},
-{
- {
-  { 6721966,13833823,-23523388,-1551314,26354293,-11863321,23365147,-3949732,7390890,2759800 },
-  { 4409041,2052381,23373853,10530217,7676779,-12885954,21302353,-4264057,1244380,-12919645 },
-  { -4421239,7169619,4982368,-2957590,30256825,-2777540,14086413,9208236,15886429,16489664 },
- },
- {
-  { 1996075,10375649,14346367,13311202,-6874135,-16438411,-13693198,398369,-30606455,-712933 },
-  { -25307465,9795880,-2777414,14878809,-33531835,14780363,13348553,12076947,-30836462,5113182 },
-  { -17770784,11797796,31950843,13929123,-25888302,12288344,-30341101,-7336386,13847711,5387222 },
- },
- {
-  { -18582163,-3416217,17824843,-2340966,22744343,-10442611,8763061,3617786,-19600662,10370991 },
-  { 20246567,-14369378,22358229,-543712,18507283,-10413996,14554437,-8746092,32232924,16763880 },
-  { 9648505,10094563,26416693,14745928,-30374318,-6472621,11094161,15689506,3140038,-16510092 },
- },
- {
-  { -16160072,5472695,31895588,4744994,8823515,10365685,-27224800,9448613,-28774454,366295 },
-  { 19153450,11523972,-11096490,-6503142,-24647631,5420647,28344573,8041113,719605,11671788 },
-  { 8678025,2694440,-6808014,2517372,4964326,11152271,-15432916,-15266516,27000813,-10195553 },
- },
- {
-  { -15157904,7134312,8639287,-2814877,-7235688,10421742,564065,5336097,6750977,-14521026 },
-  { 11836410,-3979488,26297894,16080799,23455045,15735944,1695823,-8819122,8169720,16220347 },
-  { -18115838,8653647,17578566,-6092619,-8025777,-16012763,-11144307,-2627664,-5990708,-14166033 },
- },
- {
-  { -23308498,-10968312,15213228,-10081214,-30853605,-11050004,27884329,2847284,2655861,1738395 },
-  { -27537433,-14253021,-25336301,-8002780,-9370762,8129821,21651608,-3239336,-19087449,-11005278 },
-  { 1533110,3437855,23735889,459276,29970501,11335377,26030092,5821408,10478196,8544890 },
- },
- {
-  { 32173121,-16129311,24896207,3921497,22579056,-3410854,19270449,12217473,17789017,-3395995 },
-  { -30552961,-2228401,-15578829,-10147201,13243889,517024,15479401,-3853233,30460520,1052596 },
-  { -11614875,13323618,32618793,8175907,-15230173,12596687,27491595,-4612359,3179268,-9478891 },
- },
- {
-  { 31947069,-14366651,-4640583,-15339921,-15125977,-6039709,-14756777,-16411740,19072640,-9511060 },
-  { 11685058,11822410,3158003,-13952594,33402194,-4165066,5977896,-5215017,473099,5040608 },
-  { -20290863,8198642,-27410132,11602123,1290375,-2799760,28326862,1721092,-19558642,-3131606 },
- },
-},
-{
- {
-  { 7881532,10687937,7578723,7738378,-18951012,-2553952,21820786,8076149,-27868496,11538389 },
-  { -19935666,3899861,18283497,-6801568,-15728660,-11249211,8754525,7446702,-5676054,5797016 },
-  { -11295600,-3793569,-15782110,-7964573,12708869,-8456199,2014099,-9050574,-2369172,-5877341 },
- },
- {
-  { -22472376,-11568741,-27682020,1146375,18956691,16640559,1192730,-3714199,15123619,10811505 },
-  { 14352098,-3419715,-18942044,10822655,32750596,4699007,-70363,15776356,-28886779,-11974553 },
-  { -28241164,-8072475,-4978962,-5315317,29416931,1847569,-20654173,-16484855,4714547,-9600655 },
- },
- {
-  { 15200332,8368572,19679101,15970074,-31872674,1959451,24611599,-4543832,-11745876,12340220 },
-  { 12876937,-10480056,33134381,6590940,-6307776,14872440,9613953,8241152,15370987,9608631 },
-  { -4143277,-12014408,8446281,-391603,4407738,13629032,-7724868,15866074,-28210621,-8814099 },
- },
- {
-  { 26660628,-15677655,8393734,358047,-7401291,992988,-23904233,858697,20571223,8420556 },
-  { 14620715,13067227,-15447274,8264467,14106269,15080814,33531827,12516406,-21574435,-12476749 },
-  { 236881,10476226,57258,-14677024,6472998,2466984,17258519,7256740,8791136,15069930 },
- },
- {
-  { 1276410,-9371918,22949635,-16322807,-23493039,-5702186,14711875,4874229,-30663140,-2331391 },
-  { 5855666,4990204,-13711848,7294284,-7804282,1924647,-1423175,-7912378,-33069337,9234253 },
-  { 20590503,-9018988,31529744,-7352666,-2706834,10650548,31559055,-11609587,18979186,13396066 },
- },
- {
-  { 24474287,4968103,22267082,4407354,24063882,-8325180,-18816887,13594782,33514650,7021958 },
-  { -11566906,-6565505,-21365085,15928892,-26158305,4315421,-25948728,-3916677,-21480480,12868082 },
-  { -28635013,13504661,19988037,-2132761,21078225,6443208,-21446107,2244500,-12455797,-8089383 },
- },
- {
-  { -30595528,13793479,-5852820,319136,-25723172,-6263899,33086546,8957937,-15233648,5540521 },
-  { -11630176,-11503902,-8119500,-7643073,2620056,1022908,-23710744,-1568984,-16128528,-14962807 },
-  { 23152971,775386,27395463,14006635,-9701118,4649512,1689819,892185,-11513277,-15205948 },
- },
- {
-  { 9770129,9586738,26496094,4324120,1556511,-3550024,27453819,4763127,-19179614,5867134 },
-  { -32765025,1927590,31726409,-4753295,23962434,-16019500,27846559,5931263,-29749703,-16108455 },
-  { 27461885,-2977536,22380810,1815854,-23033753,-3031938,7283490,-15148073,-19526700,7734629 },
- },
-},
-{
- {
-  { -8010264,-9590817,-11120403,6196038,29344158,-13430885,7585295,-3176626,18549497,15302069 },
-  { -32658337,-6171222,-7672793,-11051681,6258878,13504381,10458790,-6418461,-8872242,8424746 },
-  { 24687205,8613276,-30667046,-3233545,1863892,-1830544,19206234,7134917,-11284482,-828919 },
- },
- {
-  { 11334899,-9218022,8025293,12707519,17523892,-10476071,10243738,-14685461,-5066034,16498837 },
-  { 8911542,6887158,-9584260,-6958590,11145641,-9543680,17303925,-14124238,6536641,10543906 },
-  { -28946384,15479763,-17466835,568876,-1497683,11223454,-2669190,-16625574,-27235709,8876771 },
- },
- {
-  { -25742899,-12566864,-15649966,-846607,-33026686,-796288,-33481822,15824474,-604426,-9039817 },
-  { 10330056,70051,7957388,-9002667,9764902,15609756,27698697,-4890037,1657394,3084098 },
-  { 10477963,-7470260,12119566,-13250805,29016247,-5365589,31280319,14396151,-30233575,15272409 },
- },
- {
-  { -12288309,3169463,28813183,16658753,25116432,-5630466,-25173957,-12636138,-25014757,1950504 },
-  { -26180358,9489187,11053416,-14746161,-31053720,5825630,-8384306,-8767532,15341279,8373727 },
-  { 28685821,7759505,-14378516,-12002860,-31971820,4079242,298136,-10232602,-2878207,15190420 },
- },
- {
-  { -32932876,13806336,-14337485,-15794431,-24004620,10940928,8669718,2742393,-26033313,-6875003 },
-  { -1580388,-11729417,-25979658,-11445023,-17411874,-10912854,9291594,-16247779,-12154742,6048605 },
-  { -30305315,14843444,1539301,11864366,20201677,1900163,13934231,5128323,11213262,9168384 },
- },
- {
-  { -26280513,11007847,19408960,-940758,-18592965,-4328580,-5088060,-11105150,20470157,-16398701 },
-  { -23136053,9282192,14855179,-15390078,-7362815,-14408560,-22783952,14461608,14042978,5230683 },
-  { 29969567,-2741594,-16711867,-8552442,9175486,-2468974,21556951,3506042,-5933891,-12449708 },
- },
- {
-  { -3144746,8744661,19704003,4581278,-20430686,6830683,-21284170,8971513,-28539189,15326563 },
-  { -19464629,10110288,-17262528,-3503892,-23500387,1355669,-15523050,15300988,-20514118,9168260 },
-  { -5353335,4488613,-23803248,16314347,7780487,-15638939,-28948358,9601605,33087103,-9011387 },
- },
- {
-  { -19443170,-15512900,-20797467,-12445323,-29824447,10229461,-27444329,-15000531,-5996870,15664672 },
-  { 23294591,-16632613,-22650781,-8470978,27844204,11461195,13099750,-2460356,18151676,13417686 },
-  { -24722913,-4176517,-31150679,5988919,-26858785,6685065,1661597,-12551441,15271676,-15452665 },
- },
-},
-{
- {
-  { 11433042,-13228665,8239631,-5279517,-1985436,-725718,-18698764,2167544,-6921301,-13440182 },
-  { -31436171,15575146,30436815,12192228,-22463353,9395379,-9917708,-8638997,12215110,12028277 },
-  { 14098400,6555944,23007258,5757252,-15427832,-12950502,30123440,4617780,-16900089,-655628 },
- },
- {
-  { -4026201,-15240835,11893168,13718664,-14809462,1847385,-15819999,10154009,23973261,-12684474 },
-  { -26531820,-3695990,-1908898,2534301,-31870557,-16550355,18341390,-11419951,32013174,-10103539 },
-  { -25479301,10876443,-11771086,-14625140,-12369567,1838104,21911214,6354752,4425632,-837822 },
- },
- {
-  { -10433389,-14612966,22229858,-3091047,-13191166,776729,-17415375,-12020462,4725005,14044970 },
-  { 19268650,-7304421,1555349,8692754,-21474059,-9910664,6347390,-1411784,-19522291,-16109756 },
-  { -24864089,12986008,-10898878,-5558584,-11312371,-148526,19541418,8180106,9282262,10282508 },
- },
- {
-  { -26205082,4428547,-8661196,-13194263,4098402,-14165257,15522535,8372215,5542595,-10702683 },
-  { -10562541,14895633,26814552,-16673850,-17480754,-2489360,-2781891,6993761,-18093885,10114655 },
-  { -20107055,-929418,31422704,10427861,-7110749,6150669,-29091755,-11529146,25953725,-106158 },
- },
- {
-  { -4234397,-8039292,-9119125,3046000,2101609,-12607294,19390020,6094296,-3315279,12831125 },
-  { -15998678,7578152,5310217,14408357,-33548620,-224739,31575954,6326196,7381791,-2421839 },
-  { -20902779,3296811,24736065,-16328389,18374254,7318640,6295303,8082724,-15362489,12339664 },
- },
- {
-  { 27724736,2291157,6088201,-14184798,1792727,5857634,13848414,15768922,25091167,14856294 },
-  { -18866652,8331043,24373479,8541013,-701998,-9269457,12927300,-12695493,-22182473,-9012899 },
-  { -11423429,-5421590,11632845,3405020,30536730,-11674039,-27260765,13866390,30146206,9142070 },
- },
- {
-  { 3924129,-15307516,-13817122,-10054960,12291820,-668366,-27702774,9326384,-8237858,4171294 },
-  { -15921940,16037937,6713787,16606682,-21612135,2790944,26396185,3731949,345228,-5462949 },
-  { -21327538,13448259,25284571,1143661,20614966,-8849387,2031539,-12391231,-16253183,-13582083 },
- },
- {
-  { 31016211,-16722429,26371392,-14451233,-5027349,14854137,17477601,3842657,28012650,-16405420 },
-  { -5075835,9368966,-8562079,-4600902,-15249953,6970560,-9189873,16292057,-8867157,3507940 },
-  { 29439664,3537914,23333589,6997794,-17555561,-11018068,-15209202,-15051267,-9164929,6580396 },
- },
-},
-{
- {
-  { -12185861,-7679788,16438269,10826160,-8696817,-6235611,17860444,-9273846,-2095802,9304567 },
-  { 20714564,-4336911,29088195,7406487,11426967,-5095705,14792667,-14608617,5289421,-477127 },
-  { -16665533,-10650790,-6160345,-13305760,9192020,-1802462,17271490,12349094,26939669,-3752294 },
- },
- {
-  { -12889898,9373458,31595848,16374215,21471720,13221525,-27283495,-12348559,-3698806,117887 },
-  { 22263325,-6560050,3984570,-11174646,-15114008,-566785,28311253,5358056,-23319780,541964 },
-  { 16259219,3261970,2309254,-15534474,-16885711,-4581916,24134070,-16705829,-13337066,-13552195 },
- },
- {
-  { 9378160,-13140186,-22845982,-12745264,28198281,-7244098,-2399684,-717351,690426,14876244 },
-  { 24977353,-314384,-8223969,-13465086,28432343,-1176353,-13068804,-12297348,-22380984,6618999 },
-  { -1538174,11685646,12944378,13682314,-24389511,-14413193,8044829,-13817328,32239829,-5652762 },
- },
- {
-  { -18603066,4762990,-926250,8885304,-28412480,-3187315,9781647,-10350059,32779359,5095274 },
-  { -33008130,-5214506,-32264887,-3685216,9460461,-9327423,-24601656,14506724,21639561,-2630236 },
-  { -16400943,-13112215,25239338,15531969,3987758,-4499318,-1289502,-6863535,17874574,558605 },
- },
- {
-  { -13600129,10240081,9171883,16131053,-20869254,9599700,33499487,5080151,2085892,5119761 },
-  { -22205145,-2519528,-16381601,414691,-25019550,2170430,30634760,-8363614,-31999993,-5759884 },
-  { -6845704,15791202,8550074,-1312654,29928809,-12092256,27534430,-7192145,-22351378,12961482 },
- },
- {
-  { -24492060,-9570771,10368194,11582341,-23397293,-2245287,16533930,8206996,-30194652,-5159638 },
-  { -11121496,-3382234,2307366,6362031,-135455,8868177,-16835630,7031275,7589640,8945490 },
-  { -32152748,8917967,6661220,-11677616,-1192060,-15793393,7251489,-11182180,24099109,-14456170 },
- },
- {
-  { 5019558,-7907470,4244127,-14714356,-26933272,6453165,-19118182,-13289025,-6231896,-10280736 },
-  { 10853594,10721687,26480089,5861829,-22995819,1972175,-1866647,-10557898,-3363451,-6441124 },
-  { -17002408,5906790,221599,-6563147,7828208,-13248918,24362661,-2008168,-13866408,7421392 },
- },
- {
-  { 8139927,-6546497,32257646,-5890546,30375719,1886181,-21175108,15441252,28826358,-4123029 },
-  { 6267086,9695052,7709135,-16603597,-32869068,-1886135,14795160,-7840124,13746021,-1742048 },
-  { 28584902,7787108,-6732942,-15050729,22846041,-7571236,-3181936,-363524,4771362,-8419958 },
- },
-},
-{
- {
-  { 24949256,6376279,-27466481,-8174608,-18646154,-9930606,33543569,-12141695,3569627,11342593 },
-  { 26514989,4740088,27912651,3697550,19331575,-11472339,6809886,4608608,7325975,-14801071 },
-  { -11618399,-14554430,-24321212,7655128,-1369274,5214312,-27400540,10258390,-17646694,-8186692 },
- },
- {
-  { 11431204,15823007,26570245,14329124,18029990,4796082,-31446179,15580664,9280358,-3973687 },
-  { -160783,-10326257,-22855316,-4304997,-20861367,-13621002,-32810901,-11181622,-15545091,4387441 },
-  { -20799378,12194512,3937617,-5805892,-27154820,9340370,-24513992,8548137,20617071,-7482001 },
- },
- {
-  { -938825,-3930586,-8714311,16124718,24603125,-6225393,-13775352,-11875822,24345683,10325460 },
-  { -19855277,-1568885,-22202708,8714034,14007766,6928528,16318175,-1010689,4766743,3552007 },
-  { -21751364,-16730916,1351763,-803421,-4009670,3950935,3217514,14481909,10988822,-3994762 },
- },
- {
-  { 15564307,-14311570,3101243,5684148,30446780,-8051356,12677127,-6505343,-8295852,13296005 },
-  { -9442290,6624296,-30298964,-11913677,-4670981,-2057379,31521204,9614054,-30000824,12074674 },
-  { 4771191,-135239,14290749,-13089852,27992298,14998318,-1413936,-1556716,29832613,-16391035 },
- },
- {
-  { 7064884,-7541174,-19161962,-5067537,-18891269,-2912736,25825242,5293297,-27122660,13101590 },
-  { -2298563,2439670,-7466610,1719965,-27267541,-16328445,32512469,-5317593,-30356070,-4190957 },
-  { -30006540,10162316,-33180176,3981723,-16482138,-13070044,14413974,9515896,19568978,9628812 },
- },
- {
-  { 33053803,199357,15894591,1583059,27380243,-4580435,-17838894,-6106839,-6291786,3437740 },
-  { -18978877,3884493,19469877,12726490,15913552,13614290,-22961733,70104,7463304,4176122 },
-  { -27124001,10659917,11482427,-16070381,12771467,-6635117,-32719404,-5322751,24216882,5944158 },
- },
- {
-  { 8894125,7450974,-2664149,-9765752,-28080517,-12389115,19345746,14680796,11632993,5847885 },
-  { 26942781,-2315317,9129564,-4906607,26024105,11769399,-11518837,6367194,-9727230,4782140 },
-  { 19916461,-4828410,-22910704,-11414391,25606324,-5972441,33253853,8220911,6358847,-1873857 },
- },
- {
-  { 801428,-2081702,16569428,11065167,29875704,96627,7908388,-4480480,-13538503,1387155 },
-  { 19646058,5720633,-11416706,12814209,11607948,12749789,14147075,15156355,-21866831,11835260 },
-  { 19299512,1155910,28703737,14890794,2925026,7269399,26121523,15467869,-26560550,5052483 },
- },
-},
-{
- {
-  { -3017432,10058206,1980837,3964243,22160966,12322533,-6431123,-12618185,12228557,-7003677 },
-  { 32944382,14922211,-22844894,5188528,21913450,-8719943,4001465,13238564,-6114803,8653815 },
-  { 22865569,-4652735,27603668,-12545395,14348958,8234005,24808405,5719875,28483275,2841751 },
- },
- {
-  { -16420968,-1113305,-327719,-12107856,21886282,-15552774,-1887966,-315658,19932058,-12739203 },
-  { -11656086,10087521,-8864888,-5536143,-19278573,-3055912,3999228,13239134,-4777469,-13910208 },
-  { 1382174,-11694719,17266790,9194690,-13324356,9720081,20403944,11284705,-14013818,3093230 },
- },
- {
-  { 16650921,-11037932,-1064178,1570629,-8329746,7352753,-302424,16271225,-24049421,-6691850 },
-  { -21911077,-5927941,-4611316,-5560156,-31744103,-10785293,24123614,15193618,-21652117,-16739389 },
-  { -9935934,-4289447,-25279823,4372842,2087473,10399484,31870908,14690798,17361620,11864968 },
- },
- {
-  { -11307610,6210372,13206574,5806320,-29017692,-13967200,-12331205,-7486601,-25578460,-16240689 },
-  { 14668462,-12270235,26039039,15305210,25515617,4542480,10453892,6577524,9145645,-6443880 },
-  { 5974874,3053895,-9433049,-10385191,-31865124,3225009,-7972642,3936128,-5652273,-3050304 },
- },
- {
-  { 30625386,-4729400,-25555961,-12792866,-20484575,7695099,17097188,-16303496,-27999779,1803632 },
-  { -3553091,9865099,-5228566,4272701,-5673832,-16689700,14911344,12196514,-21405489,7047412 },
-  { 20093277,9920966,-11138194,-5343857,13161587,12044805,-32856851,4124601,-32343828,-10257566 },
- },
- {
-  { -20788824,14084654,-13531713,7842147,19119038,-13822605,4752377,-8714640,-21679658,2288038 },
-  { -26819236,-3283715,29965059,3039786,-14473765,2540457,29457502,14625692,-24819617,12570232 },
-  { -1063558,-11551823,16920318,12494842,1278292,-5869109,-21159943,-3498680,-11974704,4724943 },
- },
- {
-  { 17960970,-11775534,-4140968,-9702530,-8876562,-1410617,-12907383,-8659932,-29576300,1903856 },
-  { 23134274,-14279132,-10681997,-1611936,20684485,15770816,-12989750,3190296,26955097,14109738 },
-  { 15308788,5320727,-30113809,-14318877,22902008,7767164,29425325,-11277562,31960942,11934971 },
- },
- {
-  { -27395711,8435796,4109644,12222639,-24627868,14818669,20638173,4875028,10491392,1379718 },
-  { -13159415,9197841,3875503,-8936108,-1383712,-5879801,33518459,16176658,21432314,12180697 },
-  { -11787308,11500838,13787581,-13832590,-22430679,10140205,1465425,12689540,-10301319,-13872883 },
- },
-},
-{
- {
-  { 5414091,-15386041,-21007664,9643570,12834970,1186149,-2622916,-1342231,26128231,6032912 },
-  { -26337395,-13766162,32496025,-13653919,17847801,-12669156,3604025,8316894,-25875034,-10437358 },
-  { 3296484,6223048,24680646,-12246460,-23052020,5903205,-8862297,-4639164,12376617,3188849 },
- },
- {
-  { 29190488,-14659046,27549113,-1183516,3520066,-10697301,32049515,-7309113,-16109234,-9852307 },
-  { -14744486,-9309156,735818,-598978,-20407687,-5057904,25246078,-15795669,18640741,-960977 },
-  { -6928835,-16430795,10361374,5642961,4910474,12345252,-31638386,-494430,10530747,1053335 },
- },
- {
-  { -29265967,-14186805,-13538216,-12117373,-19457059,-10655384,-31462369,-2948985,24018831,15026644 },
-  { -22592535,-3145277,-2289276,5953843,-13440189,9425631,25310643,13003497,-2314791,-15145616 },
-  { -27419985,-603321,-8043984,-1669117,-26092265,13987819,-27297622,187899,-23166419,-2531735 },
- },
- {
-  { -21744398,-13810475,1844840,5021428,-10434399,-15911473,9716667,16266922,-5070217,726099 },
-  { 29370922,-6053998,7334071,-15342259,9385287,2247707,-13661962,-4839461,30007388,-15823341 },
-  { -936379,16086691,23751945,-543318,-1167538,-5189036,9137109,730663,9835848,4555336 },
- },
- {
-  { -23376435,1410446,-22253753,-12899614,30867635,15826977,17693930,544696,-11985298,12422646 },
-  { 31117226,-12215734,-13502838,6561947,-9876867,-12757670,-5118685,-4096706,29120153,13924425 },
-  { -17400879,-14233209,19675799,-2734756,-11006962,-5858820,-9383939,-11317700,7240931,-237388 },
- },
- {
-  { -31361739,-11346780,-15007447,-5856218,-22453340,-12152771,1222336,4389483,3293637,-15551743 },
-  { -16684801,-14444245,11038544,11054958,-13801175,-3338533,-24319580,7733547,12796905,-6335822 },
-  { -8759414,-10817836,-25418864,10783769,-30615557,-9746811,-28253339,3647836,3222231,-11160462 },
- },
- {
-  { 18606113,1693100,-25448386,-15170272,4112353,10045021,23603893,-2048234,-7550776,2484985 },
-  { 9255317,-3131197,-12156162,-1004256,13098013,-9214866,16377220,-2102812,-19802075,-3034702 },
-  { -22729289,7496160,-5742199,11329249,19991973,-3347502,-31718148,9936966,-30097688,-10618797 },
- },
- {
-  { 21878590,-5001297,4338336,13643897,-3036865,13160960,19708896,5415497,-7360503,-4109293 },
-  { 27736861,10103576,12500508,8502413,-3413016,-9633558,10436918,-1550276,-23659143,-8132100 },
-  { 19492550,-12104365,-29681976,-852630,-3208171,12403437,30066266,8367329,13243957,8709688 },
- },
-},
-{
- {
-  { 12015105,2801261,28198131,10151021,24818120,-4743133,-11194191,-5645734,5150968,7274186 },
-  { 2831366,-12492146,1478975,6122054,23825128,-12733586,31097299,6083058,31021603,-9793610 },
-  { -2529932,-2229646,445613,10720828,-13849527,-11505937,-23507731,16354465,15067285,-14147707 },
- },
- {
-  { 7840942,14037873,-33364863,15934016,-728213,-3642706,21403988,1057586,-19379462,-12403220 },
-  { 915865,-16469274,15608285,-8789130,-24357026,6060030,-17371319,8410997,-7220461,16527025 },
-  { 32922597,-556987,20336074,-16184568,10903705,-5384487,16957574,52992,23834301,6588044 },
- },
- {
-  { 32752030,11232950,3381995,-8714866,22652988,-10744103,17159699,16689107,-20314580,-1305992 },
-  { -4689649,9166776,-25710296,-10847306,11576752,12733943,7924251,-2752281,1976123,-7249027 },
-  { 21251222,16309901,-2983015,-6783122,30810597,12967303,156041,-3371252,12331345,-8237197 },
- },
- {
-  { 8651614,-4477032,-16085636,-4996994,13002507,2950805,29054427,-5106970,10008136,-4667901 },
-  { 31486080,15114593,-14261250,12951354,14369431,-7387845,16347321,-13662089,8684155,-10532952 },
-  { 19443825,11385320,24468943,-9659068,-23919258,2187569,-26263207,-6086921,31316348,14219878 },
- },
- {
-  { -28594490,1193785,32245219,11392485,31092169,15722801,27146014,6992409,29126555,9207390 },
-  { 32382935,1110093,18477781,11028262,-27411763,-7548111,-4980517,10843782,-7957600,-14435730 },
-  { 2814918,7836403,27519878,-7868156,-20894015,-11553689,-21494559,8550130,28346258,1994730 },
- },
- {
-  { -19578299,8085545,-14000519,-3948622,2785838,-16231307,-19516951,7174894,22628102,8115180 },
-  { -30405132,955511,-11133838,-15078069,-32447087,-13278079,-25651578,3317160,-9943017,930272 },
-  { -15303681,-6833769,28856490,1357446,23421993,1057177,24091212,-1388970,-22765376,-10650715 },
- },
- {
-  { -22751231,-5303997,-12907607,-12768866,-15811511,-7797053,-14839018,-16554220,-1867018,8398970 },
-  { -31969310,2106403,-4736360,1362501,12813763,16200670,22981545,-6291273,18009408,-15772772 },
-  { -17220923,-9545221,-27784654,14166835,29815394,7444469,29551787,-3727419,19288549,1325865 },
- },
- {
-  { 15100157,-15835752,-23923978,-1005098,-26450192,15509408,12376730,-3479146,33166107,-8042750 },
-  { 20909231,13023121,-9209752,16251778,-5778415,-8094914,12412151,10018715,2213263,-13878373 },
-  { 32529814,-11074689,30361439,-16689753,-9135940,1513226,22922121,6382134,-5766928,8371348 },
- },
-},
-{
- {
-  { 9923462,11271500,12616794,3544722,-29998368,-1721626,12891687,-8193132,-26442943,10486144 },
-  { -22597207,-7012665,8587003,-8257861,4084309,-12970062,361726,2610596,-23921530,-11455195 },
-  { 5408411,-1136691,-4969122,10561668,24145918,14240566,31319731,-4235541,19985175,-3436086 },
- },
- {
-  { -13994457,16616821,14549246,3341099,32155958,13648976,-17577068,8849297,65030,8370684 },
-  { -8320926,-12049626,31204563,5839400,-20627288,-1057277,-19442942,6922164,12743482,-9800518 },
-  { -2361371,12678785,28815050,4759974,-23893047,4884717,23783145,11038569,18800704,255233 },
- },
- {
-  { -5269658,-1773886,13957886,7990715,23132995,728773,13393847,9066957,19258688,-14753793 },
-  { -2936654,-10827535,-10432089,14516793,-3640786,4372541,-31934921,2209390,-1524053,2055794 },
-  { 580882,16705327,5468415,-2683018,-30926419,-14696000,-7203346,-8994389,-30021019,7394435 },
- },
- {
-  { 23838809,1822728,-15738443,15242727,8318092,-3733104,-21672180,-3492205,-4821741,14799921 },
-  { 13345610,9759151,3371034,-16137791,16353039,8577942,31129804,13496856,-9056018,7402518 },
-  { 2286874,-4435931,-20042458,-2008336,-13696227,5038122,11006906,-15760352,8205061,1607563 },
- },
- {
-  { 14414086,-8002132,3331830,-3208217,22249151,-5594188,18364661,-2906958,30019587,-9029278 },
-  { -27688051,1585953,-10775053,931069,-29120221,-11002319,-14410829,12029093,9944378,8024 },
-  { 4368715,-3709630,29874200,-15022983,-20230386,-11410704,-16114594,-999085,-8142388,5640030 },
- },
- {
-  { 10299610,13746483,11661824,16234854,7630238,5998374,9809887,-16694564,15219798,-14327783 },
-  { 27425505,-5719081,3055006,10660664,23458024,595578,-15398605,-1173195,-18342183,9742717 },
-  { 6744077,2427284,26042789,2720740,-847906,1118974,32324614,7406442,12420155,1994844 },
- },
- {
-  { 14012521,-5024720,-18384453,-9578469,-26485342,-3936439,-13033478,-10909803,24319929,-6446333 },
-  { 16412690,-4507367,10772641,15929391,-17068788,-4658621,10555945,-10484049,-30102368,-4739048 },
-  { 22397382,-7767684,-9293161,-12792868,17166287,-9755136,-27333065,6199366,21880021,-12250760 },
- },
- {
-  { -4283307,5368523,-31117018,8163389,-30323063,3209128,16557151,8890729,8840445,4957760 },
-  { -15447727,709327,-6919446,-10870178,-29777922,6522332,-21720181,12130072,-14796503,5005757 },
-  { -2114751,-14308128,23019042,15765735,-25269683,6002752,10183197,-13239326,-16395286,-2176112 },
- },
-},
-{
- {
-  { -19025756,1632005,13466291,-7995100,-23640451,16573537,-32013908,-3057104,22208662,2000468 },
-  { 3065073,-1412761,-25598674,-361432,-17683065,-5703415,-8164212,11248527,-3691214,-7414184 },
-  { 10379208,-6045554,8877319,1473647,-29291284,-12507580,16690915,2553332,-3132688,16400289 },
- },
- {
-  { 15716668,1254266,-18472690,7446274,-8448918,6344164,-22097271,-7285580,26894937,9132066 },
-  { 24158887,12938817,11085297,-8177598,-28063478,-4457083,-30576463,64452,-6817084,-2692882 },
-  { 13488534,7794716,22236231,5989356,25426474,-12578208,2350710,-3418511,-4688006,2364226 },
- },
- {
-  { 16335052,9132434,25640582,6678888,1725628,8517937,-11807024,-11697457,15445875,-7798101 },
-  { 29004207,-7867081,28661402,-640412,-12794003,-7943086,31863255,-4135540,-278050,-15759279 },
-  { -6122061,-14866665,-28614905,14569919,-10857999,-3591829,10343412,-6976290,-29828287,-10815811 },
- },
- {
-  { 27081650,3463984,14099042,-4517604,1616303,-6205604,29542636,15372179,17293797,960709 },
-  { 20263915,11434237,-5765435,11236810,13505955,-10857102,-16111345,6493122,-19384511,7639714 },
-  { -2830798,-14839232,25403038,-8215196,-8317012,-16173699,18006287,-16043750,29994677,-15808121 },
- },
- {
-  { 9769828,5202651,-24157398,-13631392,-28051003,-11561624,-24613141,-13860782,-31184575,709464 },
-  { 12286395,13076066,-21775189,-1176622,-25003198,4057652,-32018128,-8890874,16102007,13205847 },
-  { 13733362,5599946,10557076,3195751,-5557991,8536970,-25540170,8525972,10151379,10394400 },
- },
- {
-  { 4024660,-16137551,22436262,12276534,-9099015,-2686099,19698229,11743039,-33302334,8934414 },
-  { -15879800,-4525240,-8580747,-2934061,14634845,-698278,-9449077,3137094,-11536886,11721158 },
-  { 17555939,-5013938,8268606,2331751,-22738815,9761013,9319229,8835153,-9205489,-1280045 },
- },
- {
-  { -461409,-7830014,20614118,16688288,-7514766,-4807119,22300304,505429,6108462,-6183415 },
-  { -5070281,12367917,-30663534,3234473,32617080,-8422642,29880583,-13483331,-26898490,-7867459 },
-  { -31975283,5726539,26934134,10237677,-3173717,-605053,24199304,3795095,7592688,-14992079 },
- },
- {
-  { 21594432,-14964228,17466408,-4077222,32537084,2739898,6407723,12018833,-28256052,4298412 },
-  { -20650503,-11961496,-27236275,570498,3767144,-1717540,13891942,-1569194,13717174,10805743 },
-  { -14676630,-15644296,15287174,11927123,24177847,-8175568,-796431,14860609,-26938930,-5863836 },
- },
-},
-{
- {
-  { 12962541,5311799,-10060768,11658280,18855286,-7954201,13286263,-12808704,-4381056,9882022 },
-  { 18512079,11319350,-20123124,15090309,18818594,5271736,-22727904,3666879,-23967430,-3299429 },
-  { -6789020,-3146043,16192429,13241070,15898607,-14206114,-10084880,-6661110,-2403099,5276065 },
- },
- {
-  { 30169808,-5317648,26306206,-11750859,27814964,7069267,7152851,3684982,1449224,13082861 },
-  { 10342826,3098505,2119311,193222,25702612,12233820,23697382,15056736,-21016438,-8202000 },
-  { -33150110,3261608,22745853,7948688,19370557,-15177665,-26171976,6482814,-10300080,-11060101 },
- },
- {
-  { 32869458,-5408545,25609743,15678670,-10687769,-15471071,26112421,2521008,-22664288,6904815 },
-  { 29506923,4457497,3377935,-9796444,-30510046,12935080,1561737,3841096,-29003639,-6657642 },
-  { 10340844,-6630377,-18656632,-2278430,12621151,-13339055,30878497,-11824370,-25584551,5181966 },
- },
- {
-  { 25940115,-12658025,17324188,-10307374,-8671468,15029094,24396252,-16450922,-2322852,-12388574 },
-  { -21765684,9916823,-1300409,4079498,-1028346,11909559,1782390,12641087,20603771,-6561742 },
-  { -18882287,-11673380,24849422,11501709,13161720,-4768874,1925523,11914390,4662781,7820689 },
- },
- {
-  { 12241050,-425982,8132691,9393934,32846760,-1599620,29749456,12172924,16136752,15264020 },
-  { -10349955,-14680563,-8211979,2330220,-17662549,-14545780,10658213,6671822,19012087,3772772 },
-  { 3753511,-3421066,10617074,2028709,14841030,-6721664,28718732,-15762884,20527771,12988982 },
- },
- {
-  { -14822485,-5797269,-3707987,12689773,-898983,-10914866,-24183046,-10564943,3299665,-12424953 },
-  { -16777703,-15253301,-9642417,4978983,3308785,8755439,6943197,6461331,-25583147,8991218 },
-  { -17226263,1816362,-1673288,-6086439,31783888,-8175991,-32948145,7417950,-30242287,1507265 },
- },
- {
-  { 29692663,6829891,-10498800,4334896,20945975,-11906496,-28887608,8209391,14606362,-10647073 },
-  { -3481570,8707081,32188102,5672294,22096700,1711240,-33020695,9761487,4170404,-2085325 },
-  { -11587470,14855945,-4127778,-1531857,-26649089,15084046,22186522,16002000,-14276837,-8400798 },
- },
- {
-  { -4811456,13761029,-31703877,-2483919,-3312471,7869047,-7113572,-9620092,13240845,10965870 },
-  { -7742563,-8256762,-14768334,-13656260,-23232383,12387166,4498947,14147411,29514390,4302863 },
-  { -13413405,-12407859,20757302,-13801832,14785143,8976368,-5061276,-2144373,17846988,-13971927 },
- },
-},
-{
- {
-  { -2244452,-754728,-4597030,-1066309,-6247172,1455299,-21647728,-9214789,-5222701,12650267 },
-  { -9906797,-16070310,21134160,12198166,-27064575,708126,387813,13770293,-19134326,10958663 },
-  { 22470984,12369526,23446014,-5441109,-21520802,-9698723,-11772496,-11574455,-25083830,4271862 },
- },
- {
-  { -25169565,-10053642,-19909332,15361595,-5984358,2159192,75375,-4278529,-32526221,8469673 },
-  { 15854970,4148314,-8893890,7259002,11666551,13824734,-30531198,2697372,24154791,-9460943 },
-  { 15446137,-15806644,29759747,14019369,30811221,-9610191,-31582008,12840104,24913809,9815020 },
- },
- {
-  { -4709286,-5614269,-31841498,-12288893,-14443537,10799414,-9103676,13438769,18735128,9466238 },
-  { 11933045,9281483,5081055,-5183824,-2628162,-4905629,-7727821,-10896103,-22728655,16199064 },
-  { 14576810,379472,-26786533,-8317236,-29426508,-10812974,-102766,1876699,30801119,2164795 },
- },
- {
-  { 15995086,3199873,13672555,13712240,-19378835,-4647646,-13081610,-15496269,-13492807,1268052 },
-  { -10290614,-3659039,-3286592,10948818,23037027,3794475,-3470338,-12600221,-17055369,3565904 },
-  { 29210088,-9419337,-5919792,-4952785,10834811,-13327726,-16512102,-10820713,-27162222,-14030531 },
- },
- {
-  { -13161890,15508588,16663704,-8156150,-28349942,9019123,-29183421,-3769423,2244111,-14001979 },
-  { -5152875,-3800936,-9306475,-6071583,16243069,14684434,-25673088,-16180800,13491506,4641841 },
-  { 10813417,643330,-19188515,-728916,30292062,-16600078,27548447,-7721242,14476989,-12767431 },
- },
- {
-  { 10292079,9984945,6481436,8279905,-7251514,7032743,27282937,-1644259,-27912810,12651324 },
-  { -31185513,-813383,22271204,11835308,10201545,15351028,17099662,3988035,21721536,-3148940 },
-  { 10202177,-6545839,-31373232,-9574638,-32150642,-8119683,-12906320,3852694,13216206,14842320 },
- },
- {
-  { -15815640,-10601066,-6538952,-7258995,-6984659,-6581778,-31500847,13765824,-27434397,9900184 },
-  { 14465505,-13833331,-32133984,-14738873,-27443187,12990492,33046193,15796406,-7051866,-8040114 },
-  { 30924417,-8279620,6359016,-12816335,16508377,9071735,-25488601,15413635,9524356,-7018878 },
- },
- {
-  { 12274201,-13175547,32627641,-1785326,6736625,13267305,5237659,-5109483,15663516,4035784 },
-  { -2951309,8903985,17349946,601635,-16432815,-4612556,-13732739,-15889334,-22258478,4659091 },
-  { -16916263,-4952973,-30393711,-15158821,20774812,15897498,5736189,15026997,-2178256,-13455585 },
- },
-},
-{
- {
-  { -8858980,-2219056,28571666,-10155518,-474467,-10105698,-3801496,278095,23440562,-290208 },
-  { 10226241,-5928702,15139956,120818,-14867693,5218603,32937275,11551483,-16571960,-7442864 },
-  { 17932739,-12437276,-24039557,10749060,11316803,7535897,22503767,5561594,-3646624,3898661 },
- },
- {
-  { 7749907,-969567,-16339731,-16464,-25018111,15122143,-1573531,7152530,21831162,1245233 },
-  { 26958459,-14658026,4314586,8346991,-5677764,11960072,-32589295,-620035,-30402091,-16716212 },
-  { -12165896,9166947,33491384,13673479,29787085,13096535,6280834,14587357,-22338025,13987525 },
- },
- {
-  { -24349909,7778775,21116000,15572597,-4833266,-5357778,-4300898,-5124639,-7469781,-2858068 },
-  { 9681908,-6737123,-31951644,13591838,-6883821,386950,31622781,6439245,-14581012,4091397 },
-  { -8426427,1470727,-28109679,-1596990,3978627,-5123623,-19622683,12092163,29077877,-14741988 },
- },
- {
-  { 5269168,-6859726,-13230211,-8020715,25932563,1763552,-5606110,-5505881,-20017847,2357889 },
-  { 32264008,-15407652,-5387735,-1160093,-2091322,-3946900,23104804,-12869908,5727338,189038 },
-  { 14609123,-8954470,-6000566,-16622781,-14577387,-7743898,-26745169,10942115,-25888931,-14884697 },
- },
- {
-  { 20513500,5557931,-15604613,7829531,26413943,-2019404,-21378968,7471781,13913677,-5137875 },
-  { -25574376,11967826,29233242,12948236,-6754465,4713227,-8940970,14059180,12878652,8511905 },
-  { -25656801,3393631,-2955415,-7075526,-2250709,9366908,-30223418,6812974,5568676,-3127656 },
- },
- {
-  { 11630004,12144454,2116339,13606037,27378885,15676917,-17408753,-13504373,-14395196,8070818 },
-  { 27117696,-10007378,-31282771,-5570088,1127282,12772488,-29845906,10483306,-11552749,-1028714 },
-  { 10637467,-5688064,5674781,1072708,-26343588,-6982302,-1683975,9177853,-27493162,15431203 },
- },
- {
-  { 20525145,10892566,-12742472,12779443,-29493034,16150075,-28240519,14943142,-15056790,-7935931 },
-  { -30024462,5626926,-551567,-9981087,753598,11981191,25244767,-3239766,-3356550,9594024 },
-  { -23752644,2636870,-5163910,-10103818,585134,7877383,11345683,-6492290,13352335,-10977084 },
- },
- {
-  { -1931799,-5407458,3304649,-12884869,17015806,-4877091,-29783850,-7752482,-13215537,-319204 },
-  { 20239939,6607058,6203985,3483793,-18386976,-779229,-20723742,15077870,-22750759,14523817 },
-  { 27406042,-6041657,27423596,-4497394,4996214,10002360,-28842031,-4545494,-30172742,-4805667 },
- },
-},
-{
- {
-  { 11374242,12660715,17861383,-12540833,10935568,1099227,-13886076,-9091740,-27727044,11358504 },
-  { -12730809,10311867,1510375,10778093,-2119455,-9145702,32676003,11149336,-26123651,4985768 },
-  { -19096303,341147,-6197485,-239033,15756973,-8796662,-983043,13794114,-19414307,-15621255 },
- },
- {
-  { 6490081,11940286,25495923,-7726360,8668373,-8751316,3367603,6970005,-1691065,-9004790 },
-  { 1656497,13457317,15370807,6364910,13605745,8362338,-19174622,-5475723,-16796596,-5031438 },
-  { -22273315,-13524424,-64685,-4334223,-18605636,-10921968,-20571065,-7007978,-99853,-10237333 },
- },
- {
-  { 17747465,10039260,19368299,-4050591,-20630635,-16041286,31992683,-15857976,-29260363,-5511971 },
-  { 31932027,-4986141,-19612382,16366580,22023614,88450,11371999,-3744247,4882242,-10626905 },
-  { 29796507,37186,19818052,10115756,-11829032,3352736,18551198,3272828,-5190932,-4162409 },
- },
- {
-  { 12501286,4044383,-8612957,-13392385,-32430052,5136599,-19230378,-3529697,330070,-3659409 },
-  { 6384877,2899513,17807477,7663917,-2358888,12363165,25366522,-8573892,-271295,12071499 },
-  { -8365515,-4042521,25133448,-4517355,-6211027,2265927,-32769618,1936675,-5159697,3829363 },
- },
- {
-  { 28425966,-5835433,-577090,-4697198,-14217555,6870930,7921550,-6567787,26333140,14267664 },
-  { -11067219,11871231,27385719,-10559544,-4585914,-11189312,10004786,-8709488,-21761224,8930324 },
-  { -21197785,-16396035,25654216,-1725397,12282012,11008919,1541940,4757911,-26491501,-16408940 },
- },
- {
-  { 13537262,-7759490,-20604840,10961927,-5922820,-13218065,-13156584,6217254,-15943699,13814990 },
-  { -17422573,15157790,18705543,29619,24409717,-260476,27361681,9257833,-1956526,-1776914 },
-  { -25045300,-10191966,15366585,15166509,-13105086,8423556,-29171540,12361135,-18685978,4578290 },
- },
- {
-  { 24579768,3711570,1342322,-11180126,-27005135,14124956,-22544529,14074919,21964432,8235257 },
-  { -6528613,-2411497,9442966,-5925588,12025640,-1487420,-2981514,-1669206,13006806,2355433 },
-  { -16304899,-13605259,-6632427,-5142349,16974359,-10911083,27202044,1719366,1141648,-12796236 },
- },
- {
-  { -12863944,-13219986,-8318266,-11018091,-6810145,-4843894,13475066,-3133972,32674895,13715045 },
-  { 11423335,-5468059,32344216,8962751,24989809,9241752,-13265253,16086212,-28740881,-15642093 },
-  { -1409668,12530728,-6368726,10847387,19531186,-14132160,-11709148,7791794,-27245943,4383347 },
- },
-},
-{
- {
-  { -28970898,5271447,-1266009,-9736989,-12455236,16732599,-4862407,-4906449,27193557,6245191 },
-  { -15193956,5362278,-1783893,2695834,4960227,12840725,23061898,3260492,22510453,8577507 },
-  { -12632451,11257346,-32692994,13548177,-721004,10879011,31168030,13952092,-29571492,-3635906 },
- },
- {
-  { 3877321,-9572739,32416692,5405324,-11004407,-13656635,3759769,11935320,5611860,8164018 },
-  { -16275802,14667797,15906460,12155291,-22111149,-9039718,32003002,-8832289,5773085,-8422109 },
-  { -23788118,-8254300,1950875,8937633,18686727,16459170,-905725,12376320,31632953,190926 },
- },
- {
-  { -24593607,-16138885,-8423991,13378746,14162407,6901328,-8288749,4508564,-25341555,-3627528 },
-  { 8884438,-5884009,6023974,10104341,-6881569,-4941533,18722941,-14786005,-1672488,827625 },
-  { -32720583,-16289296,-32503547,7101210,13354605,2659080,-1800575,-14108036,-24878478,1541286 },
- },
- {
-  { 2901347,-1117687,3880376,-10059388,-17620940,-3612781,-21802117,-3567481,20456845,-1885033 },
-  { 27019610,12299467,-13658288,-1603234,-12861660,-4861471,-19540150,-5016058,29439641,15138866 },
-  { 21536104,-6626420,-32447818,-10690208,-22408077,5175814,-5420040,-16361163,7779328,109896 },
- },
- {
-  { 30279744,14648750,-8044871,6425558,13639621,-743509,28698390,12180118,23177719,-554075 },
-  { 26572847,3405927,-31701700,12890905,-19265668,5335866,-6493768,2378492,4439158,-13279347 },
-  { -22716706,3489070,-9225266,-332753,18875722,-1140095,14819434,-12731527,-17717757,-5461437 },
- },
- {
-  { -5056483,16566551,15953661,3767752,-10436499,15627060,-820954,2177225,8550082,-15114165 },
-  { -18473302,16596775,-381660,15663611,22860960,15585581,-27844109,-3582739,-23260460,-8428588 },
-  { -32480551,15707275,-8205912,-5652081,29464558,2713815,-22725137,15860482,-21902570,1494193 },
- },
- {
-  { -19562091,-14087393,-25583872,-9299552,13127842,759709,21923482,16529112,8742704,12967017 },
-  { -28464899,1553205,32536856,-10473729,-24691605,-406174,-8914625,-2933896,-29903758,15553883 },
-  { 21877909,3230008,9881174,10539357,-4797115,2841332,11543572,14513274,19375923,-12647961 },
- },
- {
-  { 8832269,-14495485,13253511,5137575,5037871,4078777,24880818,-6222716,2862653,9455043 },
-  { 29306751,5123106,20245049,-14149889,9592566,8447059,-2077124,-2990080,15511449,4789663 },
-  { -20679756,7004547,8824831,-9434977,-4045704,-3750736,-5754762,108893,23513200,16652362 },
- },
-},
-{
- {
-  { -33256173,4144782,-4476029,-6579123,10770039,-7155542,-6650416,-12936300,-18319198,10212860 },
-  { 2756081,8598110,7383731,-6859892,22312759,-1105012,21179801,2600940,-9988298,-12506466 },
-  { -24645692,13317462,-30449259,-15653928,21365574,-10869657,11344424,864440,-2499677,-16710063 },
- },
- {
-  { -26432803,6148329,-17184412,-14474154,18782929,-275997,-22561534,211300,2719757,4940997 },
-  { -1323882,3911313,-6948744,14759765,-30027150,7851207,21690126,8518463,26699843,5276295 },
-  { -13149873,-6429067,9396249,365013,24703301,-10488939,1321586,149635,-15452774,7159369 },
- },
- {
-  { 9987780,-3404759,17507962,9505530,9731535,-2165514,22356009,8312176,22477218,-8403385 },
-  { 18155857,-16504990,19744716,9006923,15154154,-10538976,24256460,-4864995,-22548173,9334109 },
-  { 2986088,-4911893,10776628,-3473844,10620590,-7083203,-21413845,14253545,-22587149,536906 },
- },
- {
-  { 4377756,8115836,24567078,15495314,11625074,13064599,7390551,10589625,10838060,-15420424 },
-  { -19342404,867880,9277171,-3218459,-14431572,-1986443,19295826,-15796950,6378260,699185 },
-  { 7895026,4057113,-7081772,-13077756,-17886831,-323126,-716039,15693155,-5045064,-13373962 },
- },
- {
-  { -7737563,-5869402,-14566319,-7406919,11385654,13201616,31730678,-10962840,-3918636,-9669325 },
-  { 10188286,-15770834,-7336361,13427543,22223443,14896287,30743455,7116568,-21786507,5427593 },
-  { 696102,13206899,27047647,-10632082,15285305,-9853179,10798490,-4578720,19236243,12477404 },
- },
- {
-  { -11229439,11243796,-17054270,-8040865,-788228,-8167967,-3897669,11180504,-23169516,7733644 },
-  { 17800790,-14036179,-27000429,-11766671,23887827,3149671,23466177,-10538171,10322027,15313801 },
-  { 26246234,11968874,32263343,-5468728,6830755,-13323031,-15794704,-101982,-24449242,10890804 },
- },
- {
-  { -31365647,10271363,-12660625,-6267268,16690207,-13062544,-14982212,16484931,25180797,-5334884 },
-  { -586574,10376444,-32586414,-11286356,19801893,10997610,2276632,9482883,316878,13820577 },
-  { -9882808,-4510367,-2115506,16457136,-11100081,11674996,30756178,-7515054,30696930,-3712849 },
- },
- {
-  { 32988917,-9603412,12499366,7910787,-10617257,-11931514,-7342816,-9985397,-32349517,7392473 },
-  { -8855661,15927861,9866406,-3649411,-2396914,-16655781,-30409476,-9134995,25112947,-2926644 },
-  { -2504044,-436966,25621774,-5678772,15085042,-5479877,-24884878,-13526194,5537438,-13914319 },
- },
-},
-{
- {
-  { -11225584,2320285,-9584280,10149187,-33444663,5808648,-14876251,-1729667,31234590,6090599 },
-  { -9633316,116426,26083934,2897444,-6364437,-2688086,609721,15878753,-6970405,-9034768 },
-  { -27757857,247744,-15194774,-9002551,23288161,-10011936,-23869595,6503646,20650474,1804084 },
- },
- {
-  { -27589786,15456424,8972517,8469608,15640622,4439847,3121995,-10329713,27842616,-202328 },
-  { -15306973,2839644,22530074,10026331,4602058,5048462,28248656,5031932,-11375082,12714369 },
-  { 20807691,-7270825,29286141,11421711,-27876523,-13868230,-21227475,1035546,-19733229,12796920 },
- },
- {
-  { 12076899,-14301286,-8785001,-11848922,-25012791,16400684,-17591495,-12899438,3480665,-15182815 },
-  { -32361549,5457597,28548107,7833186,7303070,-11953545,-24363064,-15921875,-33374054,2771025 },
-  { -21389266,421932,26597266,6860826,22486084,-6737172,-17137485,-4210226,-24552282,15673397 },
- },
- {
-  { -20184622,2338216,19788685,-9620956,-4001265,-8740893,-20271184,4733254,3727144,-12934448 },
-  { 6120119,814863,-11794402,-622716,6812205,-15747771,2019594,7975683,31123697,-10958981 },
-  { 30069250,-11435332,30434654,2958439,18399564,-976289,12296869,9204260,-16432438,9648165 },
- },
- {
-  { 32705432,-1550977,30705658,7451065,-11805606,9631813,3305266,5248604,-26008332,-11377501 },
-  { 17219865,2375039,-31570947,-5575615,-19459679,9219903,294711,15298639,2662509,-16297073 },
-  { -1172927,-7558695,-4366770,-4287744,-21346413,-8434326,32087529,-1222777,32247248,-14389861 },
- },
- {
-  { 14312628,1221556,17395390,-8700143,-4945741,-8684635,-28197744,-9637817,-16027623,-13378845 },
-  { -1428825,-9678990,-9235681,6549687,-7383069,-468664,23046502,9803137,17597934,2346211 },
-  { 18510800,15337574,26171504,981392,-22241552,7827556,-23491134,-11323352,3059833,-11782870 },
- },
- {
-  { 10141598,6082907,17829293,-1947643,9830092,13613136,-25556636,-5544586,-33502212,3592096 },
-  { 33114168,-15889352,-26525686,-13343397,33076705,8716171,1151462,1521897,-982665,-6837803 },
-  { -32939165,-4255815,23947181,-324178,-33072974,-12305637,-16637686,3891704,26353178,693168 },
- },
- {
-  { 30374239,1595580,-16884039,13186931,4600344,406904,9585294,-400668,31375464,14369965 },
-  { -14370654,-7772529,1510301,6434173,-18784789,-6262728,32732230,-13108839,17901441,16011505 },
-  { 18171223,-11934626,-12500402,15197122,-11038147,-15230035,-19172240,-16046376,8764035,12309598 },
- },
-},
-{
- {
-  { 5975908,-5243188,-19459362,-9681747,-11541277,14015782,-23665757,1228319,17544096,-10593782 },
-  { 5811932,-1715293,3442887,-2269310,-18367348,-8359541,-18044043,-15410127,-5565381,12348900 },
-  { -31399660,11407555,25755363,6891399,-3256938,14872274,-24849353,8141295,-10632534,-585479 },
- },
- {
-  { -12675304,694026,-5076145,13300344,14015258,-14451394,-9698672,-11329050,30944593,1130208 },
-  { 8247766,-6710942,-26562381,-7709309,-14401939,-14648910,4652152,2488540,23550156,-271232 },
-  { 17294316,-3788438,7026748,15626851,22990044,113481,2267737,-5908146,-408818,-137719 },
- },
- {
-  { 16091085,-16253926,18599252,7340678,2137637,-1221657,-3364161,14550936,3260525,-7166271 },
-  { -4910104,-13332887,18550887,10864893,-16459325,-7291596,-23028869,-13204905,-12748722,2701326 },
-  { -8574695,16099415,4629974,-16340524,-20786213,-6005432,-10018363,9276971,11329923,1862132 },
- },
- {
-  { 14763076,-15903608,-30918270,3689867,3511892,10313526,-21951088,12219231,-9037963,-940300 },
-  { 8894987,-3446094,6150753,3013931,301220,15693451,-31981216,-2909717,-15438168,11595570 },
-  { 15214962,3537601,-26238722,-14058872,4418657,-15230761,13947276,10730794,-13489462,-4363670 },
- },
- {
-  { -2538306,7682793,32759013,263109,-29984731,-7955452,-22332124,-10188635,977108,699994 },
-  { -12466472,4195084,-9211532,550904,-15565337,12917920,19118110,-439841,-30534533,-14337913 },
-  { 31788461,-14507657,4799989,7372237,8808585,-14747943,9408237,-10051775,12493932,-5409317 },
- },
- {
-  { -25680606,5260744,-19235809,-6284470,-3695942,16566087,27218280,2607121,29375955,6024730 },
-  { 842132,-2794693,-4763381,-8722815,26332018,-12405641,11831880,6985184,-9940361,2854096 },
-  { -4847262,-7969331,2516242,-5847713,9695691,-7221186,16512645,960770,12121869,16648078 },
- },
- {
-  { -15218652,14667096,-13336229,2013717,30598287,-464137,-31504922,-7882064,20237806,2838411 },
-  { -19288047,4453152,15298546,-16178388,22115043,-15972604,12544294,-13470457,1068881,-12499905 },
-  { -9558883,-16518835,33238498,13506958,30505848,-1114596,-8486907,-2630053,12521378,4845654 },
- },
- {
-  { -28198521,10744108,-2958380,10199664,7759311,-13088600,3409348,-873400,-6482306,-12885870 },
-  { -23561822,6230156,-20382013,10655314,-24040585,-11621172,10477734,-1240216,-3113227,13974498 },
-  { 12966261,15550616,-32038948,-1615346,21025980,-629444,5642325,7188737,18895762,12629579 },
- },
-},
-{
- {
-  { 14741879,-14946887,22177208,-11721237,1279741,8058600,11758140,789443,32195181,3895677 },
-  { 10758205,15755439,-4509950,9243698,-4879422,6879879,-2204575,-3566119,-8982069,4429647 },
-  { -2453894,15725973,-20436342,-10410672,-5803908,-11040220,-7135870,-11642895,18047436,-15281743 },
- },
- {
-  { -25173001,-11307165,29759956,11776784,-22262383,-15820455,10993114,-12850837,-17620701,-9408468 },
-  { 21987233,700364,-24505048,14972008,-7774265,-5718395,32155026,2581431,-29958985,8773375 },
-  { -25568350,454463,-13211935,16126715,25240068,8594567,20656846,12017935,-7874389,-13920155 },
- },
- {
-  { 6028182,6263078,-31011806,-11301710,-818919,2461772,-31841174,-5468042,-1721788,-2776725 },
-  { -12278994,16624277,987579,-5922598,32908203,1248608,7719845,-4166698,28408820,6816612 },
-  { -10358094,-8237829,19549651,-12169222,22082623,16147817,20613181,13982702,-10339570,5067943 },
- },
- {
-  { -30505967,-3821767,12074681,13582412,-19877972,2443951,-19719286,12746132,5331210,-10105944 },
-  { 30528811,3601899,-1957090,4619785,-27361822,-15436388,24180793,-12570394,27679908,-1648928 },
-  { 9402404,-13957065,32834043,10838634,-26580150,-13237195,26653274,-8685565,22611444,-12715406 },
- },
- {
-  { 22190590,1118029,22736441,15130463,-30460692,-5991321,19189625,-4648942,4854859,6622139 },
-  { -8310738,-2953450,-8262579,-3388049,-10401731,-271929,13424426,-3567227,26404409,13001963 },
-  { -31241838,-15415700,-2994250,8939346,11562230,-12840670,-26064365,-11621720,-15405155,11020693 },
- },
- {
-  { 1866042,-7949489,-7898649,-10301010,12483315,13477547,3175636,-12424163,28761762,1406734 },
-  { -448555,-1777666,13018551,3194501,-9580420,-11161737,24760585,-4347088,25577411,-13378680 },
-  { -24290378,4759345,-690653,-1852816,2066747,10693769,-29595790,9884936,-9368926,4745410 },
- },
- {
-  { -9141284,6049714,-19531061,-4341411,-31260798,9944276,-15462008,-11311852,10931924,-11931931 },
-  { -16561513,14112680,-8012645,4817318,-8040464,-11414606,-22853429,10856641,-20470770,13434654 },
-  { 22759489,-10073434,-16766264,-1871422,13637442,-10168091,1765144,-12654326,28445307,-5364710 },
- },
- {
-  { 29875063,12493613,2795536,-3786330,1710620,15181182,-10195717,-8788675,9074234,1167180 },
-  { -26205683,11014233,-9842651,-2635485,-26908120,7532294,-18716888,-9535498,3843903,9367684 },
-  { -10969595,-6403711,9591134,9582310,11349256,108879,16235123,8601684,-139197,4242895 },
- },
-},
-{
- {
-  { 22092954,-13191123,-2042793,-11968512,32186753,-11517388,-6574341,2470660,-27417366,16625501 },
-  { -11057722,3042016,13770083,-9257922,584236,-544855,-7770857,2602725,-27351616,14247413 },
-  { 6314175,-10264892,-32772502,15957557,-10157730,168750,-8618807,14290061,27108877,-1180880 },
- },
- {
-  { -8586597,-7170966,13241782,10960156,-32991015,-13794596,33547976,-11058889,-27148451,981874 },
-  { 22833440,9293594,-32649448,-13618667,-9136966,14756819,-22928859,-13970780,-10479804,-16197962 },
-  { -7768587,3326786,-28111797,10783824,19178761,14905060,22680049,13906969,-15933690,3797899 },
- },
- {
-  { 21721356,-4212746,-12206123,9310182,-3882239,-13653110,23740224,-2709232,20491983,-8042152 },
-  { 9209270,-15135055,-13256557,-6167798,-731016,15289673,25947805,15286587,30997318,-6703063 },
-  { 7392032,16618386,23946583,-8039892,-13265164,-1533858,-14197445,-2321576,17649998,-250080 },
- },
- {
-  { -9301088,-14193827,30609526,-3049543,-25175069,-1283752,-15241566,-9525724,-2233253,7662146 },
-  { -17558673,1763594,-33114336,15908610,-30040870,-12174295,7335080,-8472199,-3174674,3440183 },
-  { -19889700,-5977008,-24111293,-9688870,10799743,-16571957,40450,-4431835,4862400,1133 },
- },
- {
-  { -32856209,-7873957,-5422389,14860950,-16319031,7956142,7258061,311861,-30594991,-7379421 },
-  { -3773428,-1565936,28985340,7499440,24445838,9325937,29727763,16527196,18278453,15405622 },
-  { -4381906,8508652,-19898366,-3674424,-5984453,15149970,-13313598,843523,-21875062,13626197 },
- },
- {
-  { 2281448,-13487055,-10915418,-2609910,1879358,16164207,-10783882,3953792,13340839,15928663 },
-  { 31727126,-7179855,-18437503,-8283652,2875793,-16390330,-25269894,-7014826,-23452306,5964753 },
-  { 4100420,-5959452,-17179337,6017714,-18705837,12227141,-26684835,11344144,2538215,-7570755 },
- },
- {
-  { -9433605,6123113,11159803,-2156608,30016280,14966241,-20474983,1485421,-629256,-15958862 },
-  { -26804558,4260919,11851389,9658551,-32017107,16367492,-20205425,-13191288,11659922,-11115118 },
-  { 26180396,10015009,-30844224,-8581293,5418197,9480663,2231568,-10170080,33100372,-1306171 },
- },
- {
-  { 15121113,-5201871,-10389905,15427821,-27509937,-15992507,21670947,4486675,-5931810,-14466380 },
-  { 16166486,-9483733,-11104130,6023908,-31926798,-1364923,2340060,-16254968,-10735770,-10039824 },
-  { 28042865,-3557089,-12126526,12259706,-3717498,-6945899,6766453,-8689599,18036436,5803270 },
- },
-},
-{
- {
-  { -817581,6763912,11803561,1585585,10958447,-2671165,23855391,4598332,-6159431,-14117438 },
-  { -31031306,-14256194,17332029,-2383520,31312682,-5967183,696309,50292,-20095739,11763584 },
-  { -594563,-2514283,-32234153,12643980,12650761,14811489,665117,-12613632,-19773211,-10713562 },
- },
- {
-  { 30464590,-11262872,-4127476,-12734478,19835327,-7105613,-24396175,2075773,-17020157,992471 },
-  { 18357185,-6994433,7766382,16342475,-29324918,411174,14578841,8080033,-11574335,-10601610 },
-  { 19598397,10334610,12555054,2555664,18821899,-10339780,21873263,16014234,26224780,16452269 },
- },
- {
-  { -30223925,5145196,5944548,16385966,3976735,2009897,-11377804,-7618186,-20533829,3698650 },
-  { 14187449,3448569,-10636236,-10810935,-22663880,-3433596,7268410,-10890444,27394301,12015369 },
-  { 19695761,16087646,28032085,12999827,6817792,11427614,20244189,-1312777,-13259127,-3402461 },
- },
- {
-  { 30860103,12735208,-1888245,-4699734,-16974906,2256940,-8166013,12298312,-8550524,-10393462 },
-  { -5719826,-11245325,-1910649,15569035,26642876,-7587760,-5789354,-15118654,-4976164,12651793 },
-  { -2848395,9953421,11531313,-5282879,26895123,-12697089,-13118820,-16517902,9768698,-2533218 },
- },
- {
-  { -24719459,1894651,-287698,-4704085,15348719,-8156530,32767513,12765450,4940095,10678226 },
-  { 18860224,15980149,-18987240,-1562570,-26233012,-11071856,-7843882,13944024,-24372348,16582019 },
-  { -15504260,4970268,-29893044,4175593,-20993212,-2199756,-11704054,15444560,-11003761,7989037 },
- },
- {
-  { 31490452,5568061,-2412803,2182383,-32336847,4531686,-32078269,6200206,-19686113,-14800171 },
-  { -17308668,-15879940,-31522777,-2831,-32887382,16375549,8680158,-16371713,28550068,-6857132 },
-  { -28126887,-5688091,16837845,-1820458,-6850681,12700016,-30039981,4364038,1155602,5988841 },
- },
- {
-  { 21890435,-13272907,-12624011,12154349,-7831873,15300496,23148983,-4470481,24618407,8283181 },
-  { -33136107,-10512751,9975416,6841041,-31559793,16356536,3070187,-7025928,1466169,10740210 },
-  { -1509399,-15488185,-13503385,-10655916,32799044,909394,-13938903,-5779719,-32164649,-15327040 },
- },
- {
-  { 3960823,-14267803,-28026090,-15918051,-19404858,13146868,15567327,951507,-3260321,-573935 },
-  { 24740841,5052253,-30094131,8961361,25877428,6165135,-24368180,14397372,-7380369,-6144105 },
-  { -28888365,3510803,-28103278,-1158478,-11238128,-10631454,-15441463,-14453128,-1625486,-6494814 },
- },
-},
-{
- {
-  { 793299,-9230478,8836302,-6235707,-27360908,-2369593,33152843,-4885251,-9906200,-621852 },
-  { 5666233,525582,20782575,-8038419,-24538499,14657740,16099374,1468826,-6171428,-15186581 },
-  { -4859255,-3779343,-2917758,-6748019,7778750,11688288,-30404353,-9871238,-1558923,-9863646 },
- },
- {
-  { 10896332,-7719704,824275,472601,-19460308,3009587,25248958,14783338,-30581476,-15757844 },
-  { 10566929,12612572,-31944212,11118703,-12633376,12362879,21752402,8822496,24003793,14264025 },
-  { 27713862,-7355973,-11008240,9227530,27050101,2504721,23886875,-13117525,13958495,-5732453 },
- },
- {
-  { -23481610,4867226,-27247128,3900521,29838369,-8212291,-31889399,-10041781,7340521,-15410068 },
-  { 4646514,-8011124,-22766023,-11532654,23184553,8566613,31366726,-1381061,-15066784,-10375192 },
-  { -17270517,12723032,-16993061,14878794,21619651,-6197576,27584817,3093888,-8843694,3849921 },
- },
- {
-  { -9064912,2103172,25561640,-15125738,-5239824,9582958,32477045,-9017955,5002294,-15550259 },
-  { -12057553,-11177906,21115585,-13365155,8808712,-12030708,16489530,13378448,-25845716,12741426 },
-  { -5946367,10645103,-30911586,15390284,-3286982,-7118677,24306472,15852464,28834118,-7646072 },
- },
- {
-  { -17335748,-9107057,-24531279,9434953,-8472084,-583362,-13090771,455841,20461858,5491305 },
-  { 13669248,-16095482,-12481974,-10203039,-14569770,-11893198,-24995986,11293807,-28588204,-9421832 },
-  { 28497928,6272777,-33022994,14470570,8906179,-1225630,18504674,-14165166,29867745,-8795943 },
- },
- {
-  { -16207023,13517196,-27799630,-13697798,24009064,-6373891,-6367600,-13175392,22853429,-4012011 },
-  { 24191378,16712145,-13931797,15217831,14542237,1646131,18603514,-11037887,12876623,-2112447 },
-  { 17902668,4518229,-411702,-2829247,26878217,5258055,-12860753,608397,16031844,3723494 },
- },
- {
-  { -28632773,12763728,-20446446,7577504,33001348,-13017745,17558842,-7872890,23896954,-4314245 },
-  { -20005381,-12011952,31520464,605201,2543521,5991821,-2945064,7229064,-9919646,-8826859 },
-  { 28816045,298879,-28165016,-15920938,19000928,-1665890,-12680833,-2949325,-18051778,-2082915 },
- },
- {
-  { 16000882,-344896,3493092,-11447198,-29504595,-13159789,12577740,16041268,-19715240,7847707 },
-  { 10151868,10572098,27312476,7922682,14825339,4723128,-32855931,-6519018,-10020567,3852848 },
-  { -11430470,15697596,-21121557,-4420647,5386314,15063598,16514493,-15932110,29330899,-15076224 },
- },
-},
-{
- {
-  { -25499735,-4378794,-15222908,-6901211,16615731,2051784,3303702,15490,-27548796,12314391 },
-  { 15683520,-6003043,18109120,-9980648,15337968,-5997823,-16717435,15921866,16103996,-3731215 },
-  { -23169824,-10781249,13588192,-1628807,-3798557,-1074929,-19273607,5402699,-29815713,-9841101 },
- },
- {
-  { 23190676,2384583,-32714340,3462154,-29903655,-1529132,-11266856,8911517,-25205859,2739713 },
-  { 21374101,-3554250,-33524649,9874411,15377179,11831242,-33529904,6134907,4931255,11987849 },
-  { -7732,-2978858,-16223486,7277597,105524,-322051,-31480539,13861388,-30076310,10117930 },
- },
- {
-  { -29501170,-10744872,-26163768,13051539,-25625564,5089643,-6325503,6704079,12890019,15728940 },
-  { -21972360,-11771379,-951059,-4418840,14704840,2695116,903376,-10428139,12885167,8311031 },
-  { -17516482,5352194,10384213,-13811658,7506451,13453191,26423267,4384730,1888765,-5435404 },
- },
- {
-  { -25817338,-3107312,-13494599,-3182506,30896459,-13921729,-32251644,-12707869,-19464434,-3340243 },
-  { -23607977,-2665774,-526091,4651136,5765089,4618330,6092245,14845197,17151279,-9854116 },
-  { -24830458,-12733720,-15165978,10367250,-29530908,-265356,22825805,-7087279,-16866484,16176525 },
- },
- {
-  { -23583256,6564961,20063689,3798228,-4740178,7359225,2006182,-10363426,-28746253,-10197509 },
-  { -10626600,-4486402,-13320562,-5125317,3432136,-6393229,23632037,-1940610,32808310,1099883 },
-  { 15030977,5768825,-27451236,-2887299,-6427378,-15361371,-15277896,-6809350,2051441,-15225865 },
- },
- {
-  { -3362323,-7239372,7517890,9824992,23555850,295369,5148398,-14154188,-22686354,16633660 },
-  { 4577086,-16752288,13249841,-15304328,19958763,-14537274,18559670,-10759549,8402478,-9864273 },
-  { -28406330,-1051581,-26790155,-907698,-17212414,-11030789,9453451,-14980072,17983010,9967138 },
- },
- {
-  { -25762494,6524722,26585488,9969270,24709298,1220360,-1677990,7806337,17507396,3651560 },
-  { -10420457,-4118111,14584639,15971087,-15768321,8861010,26556809,-5574557,-18553322,-11357135 },
-  { 2839101,14284142,4029895,3472686,14402957,12689363,-26642121,8459447,-5605463,-7621941 },
- },
- {
-  { -4839289,-3535444,9744961,2871048,25113978,3187018,-25110813,-849066,17258084,-7977739 },
-  { 18164541,-10595176,-17154882,-1542417,19237078,-9745295,23357533,-15217008,26908270,12150756 },
-  { -30264870,-7647865,5112249,-7036672,-1499807,-6974257,43168,-5537701,-32302074,16215819 },
- },
-},
-{
- {
-  { -6898905,9824394,-12304779,-4401089,-31397141,-6276835,32574489,12532905,-7503072,-8675347 },
-  { -27343522,-16515468,-27151524,-10722951,946346,16291093,254968,7168080,21676107,-1943028 },
-  { 21260961,-8424752,-16831886,-11920822,-23677961,3968121,-3651949,-6215466,-3556191,-7913075 },
- },
- {
-  { 16544754,13250366,-16804428,15546242,-4583003,12757258,-2462308,-8680336,-18907032,-9662799 },
-  { -2415239,-15577728,18312303,4964443,-15272530,-12653564,26820651,16690659,25459437,-4564609 },
-  { -25144690,11425020,28423002,-11020557,-6144921,-15826224,9142795,-2391602,-6432418,-1644817 },
- },
- {
-  { -23104652,6253476,16964147,-3768872,-25113972,-12296437,-27457225,-16344658,6335692,7249989 },
-  { -30333227,13979675,7503222,-12368314,-11956721,-4621693,-30272269,2682242,25993170,-12478523 },
-  { 4364628,5930691,32304656,-10044554,-8054781,15091131,22857016,-10598955,31820368,15075278 },
- },
- {
-  { 31879134,-8918693,17258761,90626,-8041836,-4917709,24162788,-9650886,-17970238,12833045 },
-  { 19073683,14851414,-24403169,-11860168,7625278,11091125,-19619190,2074449,-9413939,14905377 },
-  { 24483667,-11935567,-2518866,-11547418,-1553130,15355506,-25282080,9253129,27628530,-7555480 },
- },
- {
-  { 17597607,8340603,19355617,552187,26198470,-3176583,4593324,-9157582,-14110875,15297016 },
-  { 510886,14337390,-31785257,16638632,6328095,2713355,-20217417,-11864220,8683221,2921426 },
-  { 18606791,11874196,27155355,-5281482,-24031742,6265446,-25178240,-1278924,4674690,13890525 },
- },
- {
-  { 13609624,13069022,-27372361,-13055908,24360586,9592974,14977157,9835105,4389687,288396 },
-  { 9922506,-519394,13613107,5883594,-18758345,-434263,-12304062,8317628,23388070,16052080 },
-  { 12720016,11937594,-31970060,-5028689,26900120,8561328,-20155687,-11632979,-14754271,-10812892 },
- },
- {
-  { 15961858,14150409,26716931,-665832,-22794328,13603569,11829573,7467844,-28822128,929275 },
-  { 11038231,-11582396,-27310482,-7316562,-10498527,-16307831,-23479533,-9371869,-21393143,2465074 },
-  { 20017163,-4323226,27915242,1529148,12396362,15675764,13817261,-9658066,2463391,-4622140 },
- },
- {
-  { -16358878,-12663911,-12065183,4996454,-1256422,1073572,9583558,12851107,4003896,12673717 },
-  { -1731589,-15155870,-3262930,16143082,19294135,13385325,14741514,-9103726,7903886,2348101 },
-  { 24536016,-16515207,12715592,-3862155,1511293,10047386,-3842346,-7129159,-28377538,10048127 },
- },
-},
-{
- {
-  { -12622226,-6204820,30718825,2591312,-10617028,12192840,18873298,-7297090,-32297756,15221632 },
-  { -26478122,-11103864,11546244,-1852483,9180880,7656409,-21343950,2095755,29769758,6593415 },
-  { -31994208,-2907461,4176912,3264766,12538965,-868111,26312345,-6118678,30958054,8292160 },
- },
- {
-  { 31429822,-13959116,29173532,15632448,12174511,-2760094,32808831,3977186,26143136,-3148876 },
-  { 22648901,1402143,-22799984,13746059,7936347,365344,-8668633,-1674433,-3758243,-2304625 },
-  { -15491917,8012313,-2514730,-12702462,-23965846,-10254029,-1612713,-1535569,-16664475,8194478 },
- },
- {
-  { 27338066,-7507420,-7414224,10140405,-19026427,-6589889,27277191,8855376,28572286,3005164 },
-  { 26287124,4821776,25476601,-4145903,-3764513,-15788984,-18008582,1182479,-26094821,-13079595 },
-  { -7171154,3178080,23970071,6201893,-17195577,-4489192,-21876275,-13982627,32208683,-1198248 },
- },
- {
-  { -16657702,2817643,-10286362,14811298,6024667,13349505,-27315504,-10497842,-27672585,-11539858 },
-  { 15941029,-9405932,-21367050,8062055,31876073,-238629,-15278393,-1444429,15397331,-4130193 },
-  { 8934485,-13485467,-23286397,-13423241,-32446090,14047986,31170398,-1441021,-27505566,15087184 },
- },
- {
-  { -18357243,-2156491,24524913,-16677868,15520427,-6360776,-15502406,11461896,16788528,-5868942 },
-  { -1947386,16013773,21750665,3714552,-17401782,-16055433,-3770287,-10323320,31322514,-11615635 },
-  { 21426655,-5650218,-13648287,-5347537,-28812189,-4920970,-18275391,-14621414,13040862,-12112948 },
- },
- {
-  { 11293895,12478086,-27136401,15083750,-29307421,14748872,14555558,-13417103,1613711,4896935 },
-  { -25894883,15323294,-8489791,-8057900,25967126,-13425460,2825960,-4897045,-23971776,-11267415 },
-  { -15924766,-5229880,-17443532,6410664,3622847,10243618,20615400,12405433,-23753030,-8436416 },
- },
- {
-  { -7091295,12556208,-20191352,9025187,-17072479,4333801,4378436,2432030,23097949,-566018 },
-  { 4565804,-16025654,20084412,-7842817,1724999,189254,24767264,10103221,-18512313,2424778 },
-  { 366633,-11976806,8173090,-6890119,30788634,5745705,-7168678,1344109,-3642553,12412659 },
- },
- {
-  { -24001791,7690286,14929416,-168257,-32210835,-13412986,24162697,-15326504,-3141501,11179385 },
-  { 18289522,-14724954,8056945,16430056,-21729724,7842514,-6001441,-1486897,-18684645,-11443503 },
-  { 476239,6601091,-6152790,-9723375,17503545,-4863900,27672959,13403813,11052904,5219329 },
- },
-},
-{
- {
-  { 20678546,-8375738,-32671898,8849123,-5009758,14574752,31186971,-3973730,9014762,-8579056 },
-  { -13644050,-10350239,-15962508,5075808,-1514661,-11534600,-33102500,9160280,8473550,-3256838 },
-  { 24900749,14435722,17209120,-15292541,-22592275,9878983,-7689309,-16335821,-24568481,11788948 },
- },
- {
-  { -3118155,-11395194,-13802089,14797441,9652448,-6845904,-20037437,10410733,-24568470,-1458691 },
-  { -15659161,16736706,-22467150,10215878,-9097177,7563911,11871841,-12505194,-18513325,8464118 },
-  { -23400612,8348507,-14585951,-861714,-3950205,-6373419,14325289,8628612,33313881,-8370517 },
- },
- {
-  { -20186973,-4967935,22367356,5271547,-1097117,-4788838,-24805667,-10236854,-8940735,-5818269 },
-  { -6948785,-1795212,-32625683,-16021179,32635414,-7374245,15989197,-12838188,28358192,-4253904 },
-  { -23561781,-2799059,-32351682,-1661963,-9147719,10429267,-16637684,4072016,-5351664,5596589 },
- },
- {
-  { -28236598,-3390048,12312896,6213178,3117142,16078565,29266239,2557221,1768301,15373193 },
-  { -7243358,-3246960,-4593467,-7553353,-127927,-912245,-1090902,-4504991,-24660491,3442910 },
-  { -30210571,5124043,14181784,8197961,18964734,-11939093,22597931,7176455,-18585478,13365930 },
- },
- {
-  { -7877390,-1499958,8324673,4690079,6261860,890446,24538107,-8570186,-9689599,-3031667 },
-  { 25008904,-10771599,-4305031,-9638010,16265036,15721635,683793,-11823784,15723479,-15163481 },
-  { -9660625,12374379,-27006999,-7026148,-7724114,-12314514,11879682,5400171,519526,-1235876 },
- },
- {
-  { 22258397,-16332233,-7869817,14613016,-22520255,-2950923,-20353881,7315967,16648397,7605640 },
-  { -8081308,-8464597,-8223311,9719710,19259459,-15348212,23994942,-5281555,-9468848,4763278 },
-  { -21699244,9220969,-15730624,1084137,-25476107,-2852390,31088447,-7764523,-11356529,728112 },
- },
- {
-  { 26047220,-11751471,-6900323,-16521798,24092068,9158119,-4273545,-12555558,-29365436,-5498272 },
-  { 17510331,-322857,5854289,8403524,17133918,-3112612,-28111007,12327945,10750447,10014012 },
-  { -10312768,3936952,9156313,-8897683,16498692,-994647,-27481051,-666732,3424691,7540221 },
- },
- {
-  { 30322361,-6964110,11361005,-4143317,7433304,4989748,-7071422,-16317219,-9244265,15258046 },
-  { 13054562,-2779497,19155474,469045,-12482797,4566042,5631406,2711395,1062915,-5136345 },
-  { -19240248,-11254599,-29509029,-7499965,-5835763,13005411,-6066489,12194497,32960380,1459310 },
- },
-},
-{
- {
-  { 19852034,7027924,23669353,10020366,8586503,-6657907,394197,-6101885,18638003,-11174937 },
-  { 31395534,15098109,26581030,8030562,-16527914,-5007134,9012486,-7584354,-6643087,-5442636 },
-  { -9192165,-2347377,-1997099,4529534,25766844,607986,-13222,9677543,-32294889,-6456008 },
- },
- {
-  { -2444496,-149937,29348902,8186665,1873760,12489863,-30934579,-7839692,-7852844,-8138429 },
-  { -15236356,-15433509,7766470,746860,26346930,-10221762,-27333451,10754588,-9431476,5203576 },
-  { 31834314,14135496,-770007,5159118,20917671,-16768096,-7467973,-7337524,31809243,7347066 },
- },
- {
-  { -9606723,-11874240,20414459,13033986,13716524,-11691881,19797970,-12211255,15192876,-2087490 },
-  { -12663563,-2181719,1168162,-3804809,26747877,-14138091,10609330,12694420,33473243,-13382104 },
-  { 33184999,11180355,15832085,-11385430,-1633671,225884,15089336,-11023903,-6135662,14480053 },
- },
- {
-  { 31308717,-5619998,31030840,-1897099,15674547,-6582883,5496208,13685227,27595050,8737275 },
-  { -20318852,-15150239,10933843,-16178022,8335352,-7546022,-31008351,-12610604,26498114,66511 },
-  { 22644454,-8761729,-16671776,4884562,-3105614,-13559366,30540766,-4286747,-13327787,-7515095 },
- },
- {
-  { -28017847,9834845,18617207,-2681312,-3401956,-13307506,8205540,13585437,-17127465,15115439 },
-  { 23711543,-672915,31206561,-8362711,6164647,-9709987,-33535882,-1426096,8236921,16492939 },
-  { -23910559,-13515526,-26299483,-4503841,25005590,-7687270,19574902,10071562,6708380,-6222424 },
- },
- {
-  { 2101391,-4930054,19702731,2367575,-15427167,1047675,5301017,9328700,29955601,-11678310 },
-  { 3096359,9271816,-21620864,-15521844,-14847996,-7592937,-25892142,-12635595,-9917575,6216608 },
-  { -32615849,338663,-25195611,2510422,-29213566,-13820213,24822830,-6146567,-26767480,7525079 },
- },
- {
-  { -23066649,-13985623,16133487,-7896178,-3389565,778788,-910336,-2782495,-19386633,11994101 },
-  { 21691500,-13624626,-641331,-14367021,3285881,-3483596,-25064666,9718258,-7477437,13381418 },
-  { 18445390,-4202236,14979846,11622458,-1727110,-3582980,23111648,-6375247,28535282,15779576 },
- },
- {
-  { 30098053,3089662,-9234387,16662135,-21306940,11308411,-14068454,12021730,9955285,-16303356 },
-  { 9734894,-14576830,-7473633,-9138735,2060392,11313496,-18426029,9924399,20194861,13380996 },
-  { -26378102,-7965207,-22167821,15789297,-18055342,-6168792,-1984914,15707771,26342023,10146099 },
- },
-},
-{
- {
-  { -26016874,-219943,21339191,-41388,19745256,-2878700,-29637280,2227040,21612326,-545728 },
-  { -13077387,1184228,23562814,-5970442,-20351244,-6348714,25764461,12243797,-20856566,11649658 },
-  { -10031494,11262626,27384172,2271902,26947504,-15997771,39944,6114064,33514190,2333242 },
- },
- {
-  { -21433588,-12421821,8119782,7219913,-21830522,-9016134,-6679750,-12670638,24350578,-13450001 },
-  { -4116307,-11271533,-23886186,4843615,-30088339,690623,-31536088,-10406836,8317860,12352766 },
-  { 18200138,-14475911,-33087759,-2696619,-23702521,-9102511,-23552096,-2287550,20712163,6719373 },
- },
- {
-  { 26656208,6075253,-7858556,1886072,-28344043,4262326,11117530,-3763210,26224235,-3297458 },
-  { -17168938,-14854097,-3395676,-16369877,-19954045,14050420,21728352,9493610,18620611,-16428628 },
-  { -13323321,13325349,11432106,5964811,18609221,6062965,-5269471,-9725556,-30701573,-16479657 },
- },
- {
-  { -23860538,-11233159,26961357,1640861,-32413112,-16737940,12248509,-5240639,13735342,1934062 },
-  { 25089769,6742589,17081145,-13406266,21909293,-16067981,-15136294,-3765346,-21277997,5473616 },
-  { 31883677,-7961101,1083432,-11572403,22828471,13290673,-7125085,12469656,29111212,-5451014 },
- },
- {
-  { 24244947,-15050407,-26262976,2791540,-14997599,16666678,24367466,6388839,-10295587,452383 },
-  { -25640782,-3417841,5217916,16224624,19987036,-4082269,-24236251,-5915248,15766062,8407814 },
-  { -20406999,13990231,15495425,16395525,5377168,15166495,-8917023,-4388953,-8067909,2276718 },
- },
- {
-  { 30157918,12924066,-17712050,9245753,19895028,3368142,-23827587,5096219,22740376,-7303417 },
-  { 2041139,-14256350,7783687,13876377,-25946985,-13352459,24051124,13742383,-15637599,13295222 },
-  { 33338237,-8505733,12532113,7977527,9106186,-1715251,-17720195,-4612972,-4451357,-14669444 },
- },
- {
-  { -20045281,5454097,-14346548,6447146,28862071,1883651,-2469266,-4141880,7770569,9620597 },
-  { 23208068,7979712,33071466,8149229,1758231,-10834995,30945528,-1694323,-33502340,-14767970 },
-  { 1439958,-16270480,-1079989,-793782,4625402,10647766,-5043801,1220118,30494170,-11440799 },
- },
- {
-  { -5037580,-13028295,-2970559,-3061767,15640974,-6701666,-26739026,926050,-1684339,-13333647 },
-  { 13908495,-3549272,30919928,-6273825,-21521863,7989039,9021034,9078865,3353509,4033511 },
-  { -29663431,-15113610,32259991,-344482,24295849,-12912123,23161163,8839127,27485041,7356032 },
- },
-},
-{
- {
-  { 9661027,705443,11980065,-5370154,-1628543,14661173,-6346142,2625015,28431036,-16771834 },
-  { -23839233,-8311415,-25945511,7480958,-17681669,-8354183,-22545972,14150565,15970762,4099461 },
-  { 29262576,16756590,26350592,-8793563,8529671,-11208050,13617293,-9937143,11465739,8317062 },
- },
- {
-  { -25493081,-6962928,32500200,-9419051,-23038724,-2302222,14898637,3848455,20969334,-5157516 },
-  { -20384450,-14347713,-18336405,13884722,-33039454,2842114,-21610826,-3649888,11177095,14989547 },
-  { -24496721,-11716016,16959896,2278463,12066309,10137771,13515641,2581286,-28487508,9930240 },
- },
- {
-  { -17751622,-2097826,16544300,-13009300,-15914807,-14949081,18345767,-13403753,16291481,-5314038 },
-  { -33229194,2553288,32678213,9875984,8534129,6889387,-9676774,6957617,4368891,9788741 },
-  { 16660756,7281060,-10830758,12911820,20108584,-8101676,-21722536,-8613148,16250552,-11111103 },
- },
- {
-  { -19765507,2390526,-16551031,14161980,1905286,6414907,4689584,10604807,-30190403,4782747 },
-  { -1354539,14736941,-7367442,-13292886,7710542,-14155590,-9981571,4383045,22546403,437323 },
-  { 31665577,-12180464,-16186830,1491339,-18368625,3294682,27343084,2786261,-30633590,-14097016 },
- },
- {
-  { -14467279,-683715,-33374107,7448552,19294360,14334329,-19690631,2355319,-19284671,-6114373 },
-  { 15121312,-15796162,6377020,-6031361,-10798111,-12957845,18952177,15496498,-29380133,11754228 },
-  { -2637277,-13483075,8488727,-14303896,12728761,-1622493,7141596,11724556,22761615,-10134141 },
- },
- {
-  { 16918416,11729663,-18083579,3022987,-31015732,-13339659,-28741185,-12227393,32851222,11717399 },
-  { 11166634,7338049,-6722523,4531520,-29468672,-7302055,31474879,3483633,-1193175,-4030831 },
-  { -185635,9921305,31456609,-13536438,-12013818,13348923,33142652,6546660,-19985279,-3948376 },
- },
- {
-  { -32460596,11266712,-11197107,-7899103,31703694,3855903,-8537131,-12833048,-30772034,-15486313 },
-  { -18006477,12709068,3991746,-6479188,-21491523,-10550425,-31135347,-16049879,10928917,3011958 },
-  { -6957757,-15594337,31696059,334240,29576716,14796075,-30831056,-12805180,18008031,10258577 },
- },
- {
-  { -22448644,15655569,7018479,-4410003,-30314266,-1201591,-1853465,1367120,25127874,6671743 },
-  { 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684 },
-  { -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476 },
- },
-},
-} ;
-#endif
-
-
-static void ge_select(ge_precomp *t,int pos,signed char b)
-{
-#ifndef CURVED25519_X64
-  ge_precomp minust;
-  unsigned char bnegative = negative(b);
-  unsigned char babs = b - (((-bnegative) & b) << 1);
-
-  ge_precomp_0(t);
-  cmov(t,&base[pos][0],babs,1);
-  cmov(t,&base[pos][1],babs,2);
-  cmov(t,&base[pos][2],babs,3);
-  cmov(t,&base[pos][3],babs,4);
-  cmov(t,&base[pos][4],babs,5);
-  cmov(t,&base[pos][5],babs,6);
-  cmov(t,&base[pos][6],babs,7);
-  cmov(t,&base[pos][7],babs,8);
-  fe_cswap(t->yminusx, t->yplusx, bnegative);
-  fe_neg(minust.xy2d,t->xy2d);
-  fe_cmov(t->xy2d,minust.xy2d,bnegative);
-#else
-  fe_cmov_table((fe*)t, (fe*)base[pos], b);
-#endif
-}
-
-
-/*
-h = a * B
-where a = a[0]+256*a[1]+...+256^31 a[31]
-B is the Ed25519 base point (x,4/5) with x positive.
-
-Preconditions:
-  a[31] <= 127
-*/
-void ge_scalarmult_base(ge_p3 *h,const unsigned char *a)
-{
-  signed char e[64];
-  signed char carry;
-  ge_p1p1 r;
-#ifndef CURVED25519_X64
-  ge_p2 s;
-#endif
-  ge_precomp t;
-  int i;
-
-  for (i = 0;i < 32;++i) {
-    e[2 * i + 0] = (a[i] >> 0) & 15;
-    e[2 * i + 1] = (a[i] >> 4) & 15;
-  }
-  /* each e[i] is between 0 and 15 */
-  /* e[63] is between 0 and 7 */
-
-  carry = 0;
-  for (i = 0;i < 63;++i) {
-    e[i] += carry;
-    carry = e[i] + 8;
-    carry >>= 4;
-    e[i] -= carry << 4;
-  }
-  e[63] += carry;
-  /* each e[i] is between -8 and 8 */
-
-#ifndef CURVED25519_X64
-  ge_select(&t,0,e[1]);
-  fe_sub(h->X, t.yplusx, t.yminusx);
-  fe_add(h->Y, t.yplusx, t.yminusx);
-  fe_0(h->Z);
-  h->Z[0] = 4;
-  fe_mul(h->T,h->X,h->Y);
-  fe_add(h->X, h->X, h->X);
-  fe_add(h->Y, h->Y, h->Y);
-
-  for (i = 3;i < 64;i += 2) {
-    ge_select(&t,i / 2,e[i]);
-    ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
-  }
-
-  ge_p3_dbl(&r,h);  ge_p1p1_to_p2(&s,&r);
-  ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
-  ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
-  ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
-
-  for (i = 0;i < 64;i += 2) {
-    ge_select(&t,i / 2,e[i]);
-    ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
-  }
-#else
-  ge_select(&t, 0, e[0]);
-  fe_sub(h->X, t.yplusx, t.yminusx);
-  fe_add(h->Y, t.yplusx, t.yminusx);
-  fe_0(h->Z);
-  h->Z[0] = 2;
-  fe_copy(h->T, t.xy2d);
-  for (i = 1; i < 64; i++) {
-    ge_select(&t, i, e[i]);
-    ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
-  }
-#endif
-}
-
-
-/* ge double scalar mult */
-static void slide(signed char *r,const unsigned char *a)
-{
-  int i;
-  int b;
-  int k;
-
-  for (i = 0;i < 256;++i)
-    r[i] = 1 & (a[i >> 3] >> (i & 7));
-
-  for (i = 0;i < 256;++i)
-    if (r[i]) {
-      for (b = 1;b <= 6 && i + b < 256;++b) {
-        if (r[i + b]) {
-          if (r[i] + (r[i + b] << b) <= 15) {
-            r[i] += r[i + b] << b; r[i + b] = 0;
-          } else if (r[i] - (r[i + b] << b) >= -15) {
-            r[i] -= r[i + b] << b;
-            for (k = i + b;k < 256;++k) {
-              if (!r[k]) {
-                r[k] = 1;
-                break;
-              }
-              r[k] = 0;
-            }
-          } else
-            break;
-        }
-      }
-    }
-}
-
-#ifdef CURVED25519_X64
-static const ge_precomp Bi[8] = {
-    {
-        { 0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x7cf9d3a33d4ba65,  },
-        { 0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267,  },
-        { 0xabc91205877aaa68, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8,  },
-    },
-    {
-        { 0xaf25b0a84cee9730, 0x25a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4,  },
-        { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62,  },
-        { 0x14ae933f0dd0d889, 0x589423221c35da62, 0xd170e5458cf2db4c, 0x5a2826af12b9b4c6,  },
-    },
-    {
-        { 0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb,  },
-        { 0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3,  },
-        { 0xbcbbdbf1812a8285, 0x270e0807d0bdd1fc, 0xb41b670b1bbda72d, 0x43aabe696b3bb69a,  },
-    },
-    {
-        { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e,  },
-        { 0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0,  },
-        { 0xf1836dc801b8b3a2, 0xb3035f47053ea49a, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7,  },
-    },
-    {
-        { 0x9b2e678aa6a8632f, 0xa6509e6f51bc46c5, 0xceb233c9c686f5b5, 0x34b9ed338add7f59,  },
-        { 0xf36e217e039d8064, 0x98a081b6f520419b, 0x96cbc608e75eb044, 0x49c05a51fadc9c8f,  },
-        { 0x6b4e8bf9045af1b, 0xe2ff83e8a719d22f, 0xaaf6fc2993d4cf16, 0x73c172021b008b06,  },
-    },
-    {
-        { 0x2fbf00848a802ade, 0xe5d9fecf02302e27, 0x113e847117703406, 0x4275aae2546d8faf,  },
-        { 0x315f5b0249864348, 0x3ed6b36977088381, 0xa3a075556a8deb95, 0x18ab598029d5c77f,  },
-        { 0xd82b2cc5fd6089e9, 0x31eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948,  },
-    },
-    {
-        { 0xbf70c222a2007f6d, 0xbf84b39ab5bcdedb, 0x537a0e12fb07ba07, 0x234fd7eec346f241,  },
-        { 0x506f013b327fbf93, 0xaefcebc99b776f6b, 0x9d12b232aaad5968, 0x267882d176024a7,  },
-        { 0x5360a119732ea378, 0x2437e6b1df8dd471, 0xa2ef37f891a7e533, 0x497ba6fdaa097863,  },
-    },
-    {
-        { 0x24cecc0313cfeaa0, 0x8648c28d189c246d, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b,  },
-        { 0x40bcd86468ccf0b, 0xd3829ba42a9910d6, 0x7508300807b25192, 0x43b5cd4218d05ebf,  },
-        { 0x5d9a762f9bd0b516, 0xeb38af4e373fdeee, 0x32e5a7d93d64270, 0x511d61210ae4d842,  },
-    },
-};
-#elif defined(CURVED25519_128BIT)
-static const ge_precomp Bi[8] = {
-    {
-        { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b },
-        { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 },
-        { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 },
-    },
-    {
-        { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f },
-        { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd },
-        { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b },
-    },
-    {
-        { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 },
-        { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 },
-        { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb },
-    },
-    {
-        { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 },
-        { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 },
-        { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 },
-    },
-    {
-        { 0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7 },
-        { 0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9 },
-        { 0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008 },
-    },
-    {
-        { 0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8 },
-        { 0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c },
-        { 0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df },
-    },
-    {
-        { 0x0c222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f },
-        { 0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x0267882d17602 },
-        { 0x0a119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097 },
-    },
-    {
-        { 0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de },
-        { 0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05 },
-        { 0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d },
-    },
-};
-#else
-static const ge_precomp Bi[8] = {
- {
-  { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
-  { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
-  { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
- },
- {
-  { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
-  { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
-  { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
- },
- {
-  { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
-  { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
-  { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
- },
- {
-  { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
-  { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
-  { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
- },
- {
-  { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
-  { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
-  { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
- },
- {
-  { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
-  { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
-  { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
- },
- {
-  { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
-  { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
-  { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
- },
- {
-  { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
-  { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
-  { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
- },
-} ;
-#endif
-
-
-/*
-r = a * A + b * B
-where a = a[0]+256*a[1]+...+256^31 a[31].
-and b = b[0]+256*b[1]+...+256^31 b[31].
-B is the Ed25519 base point (x,4/5) with x positive.
-*/
-int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a,
-                                 const ge_p3 *A, const unsigned char *b)
-{
-  signed char aslide[256];
-  signed char bslide[256];
-  ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
-  ge_p1p1 t;
-  ge_p3 u;
-  ge_p3 A2;
-  int i;
-
-  slide(aslide,a);
-  slide(bslide,b);
-
-  ge_p3_to_cached(&Ai[0],A);
-  ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
-  ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
-  ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
-  ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
-  ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
-  ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
-  ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
-  ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
-
-  ge_p2_0(r);
-
-  for (i = 255;i >= 0;--i) {
-    if (aslide[i] || bslide[i]) break;
-  }
-
-  for (;i >= 0;--i) {
-    ge_p2_dbl(&t,r);
-
-    if (aslide[i] > 0) {
-      ge_p1p1_to_p3(&u,&t);
-      ge_add(&t,&u,&Ai[aslide[i]/2]);
-    } else if (aslide[i] < 0) {
-      ge_p1p1_to_p3(&u,&t);
-      ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
-    }
-
-    if (bslide[i] > 0) {
-      ge_p1p1_to_p3(&u,&t);
-      ge_madd(&t,&u,&Bi[bslide[i]/2]);
-    } else if (bslide[i] < 0) {
-      ge_p1p1_to_p3(&u,&t);
-      ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
-    }
-
-    ge_p1p1_to_p2(r,&t);
-  }
-
-  return 0;
-}
-
-#ifdef CURVED25519_X64
-static const ge d = {
-    0x75eb4dca135978a3, 0x700a4d4141d8ab, 0x8cc740797779e898, 0x52036cee2b6ffe73,
-    };
-#elif defined(CURVED25519_128BIT)
-static const ge d = {
-    0x34dca135978a3, 0x1a8283b156ebd, 0x5e7a26001c029, 0x739c663a03cbb,
-    0x52036cee2b6ff
-};
-#else
-static const ge d = {
--10913610,13857413,-15372611,6949391,114729,
--8787816,-6275908,-3247719,-18696448,-12055116
-} ;
-#endif
-
-
-#ifdef CURVED25519_X64
-static const ge sqrtm1 = {
-    0xc4ee1b274a0ea0b0, 0x2f431806ad2fe478, 0x2b4d00993dfbd7a7, 0x2b8324804fc1df0b,
-    };
-#elif defined(CURVED25519_128BIT)
-static const ge sqrtm1 = {
-    0x61b274a0ea0b0, 0x0d5a5fc8f189d, 0x7ef5e9cbd0c60, 0x78595a6804c9e,
-    0x2b8324804fc1d
-};
-#else
-static const ge sqrtm1 = {
--32595792,-7943725,9377950,3500415,12389472,
--272473,-25146209,-2005654,326686,11406482
-} ;
-#endif
-
-
-int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s)
-{
-  ge u;
-  ge v;
-  ge v3;
-  ge vxx;
-  ge check;
-
-  fe_frombytes(h->Y,s);
-  fe_1(h->Z);
-  fe_sq(u,h->Y);
-  fe_mul(v,u,d);
-  fe_sub(u,u,h->Z);       /* u = y^2-1 */
-  fe_add(v,v,h->Z);       /* v = dy^2+1 */
-
-
-  fe_sq(v3,v);
-  fe_mul(v3,v3,v);        /* v3 = v^3 */
-  fe_sq(h->X,v3);
-  fe_mul(h->X,h->X,v);
-  fe_mul(h->X,h->X,u);    /* x = uv^7 */
-
-  fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
-  fe_mul(h->X,h->X,v3);
-  fe_mul(h->X,h->X,u);    /* x = uv^3(uv^7)^((q-5)/8) */
-
-  fe_sq(vxx,h->X);
-  fe_mul(vxx,vxx,v);
-  fe_sub(check,vxx,u);    /* vx^2-u */
-  if (fe_isnonzero(check)) {
-    fe_add(check,vxx,u);  /* vx^2+u */
-    if (fe_isnonzero(check)) return -1;
-    fe_mul(h->X,h->X,sqrtm1);
-  }
-
-  if (fe_isnegative(h->X) == (s[31] >> 7))
-    fe_neg(h->X,h->X);
-
-  fe_mul(h->T,h->X,h->Y);
-  return 0;
-}
-
-
-/* ge madd */
-/*
-r = p + q
-*/
-
-static WC_INLINE void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
-{
-#ifndef CURVED25519_X64
-    ge t0;
-    fe_add(r->X,p->Y,p->X);
-    fe_sub(r->Y,p->Y,p->X);
-    fe_mul(r->Z,r->X,q->yplusx);
-    fe_mul(r->Y,r->Y,q->yminusx);
-    fe_mul(r->T,q->xy2d,p->T);
-    fe_add(t0,p->Z,p->Z);
-    fe_sub(r->X,r->Z,r->Y);
-    fe_add(r->Y,r->Z,r->Y);
-    fe_add(r->Z,t0,r->T);
-    fe_sub(r->T,t0,r->T);
-#else
-    fe_ge_madd(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d,
-              q->yplusx, q->yminusx);
-#endif
-}
-
-
-/* ge msub */
-
-/*
-r = p - q
-*/
-
-static WC_INLINE void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
-{
-#ifndef CURVED25519_X64
-    ge t0;
-    fe_add(r->X,p->Y,p->X);
-    fe_sub(r->Y,p->Y,p->X);
-    fe_mul(r->Z,r->X,q->yminusx);
-    fe_mul(r->Y,r->Y,q->yplusx);
-    fe_mul(r->T,q->xy2d,p->T);
-    fe_add(t0,p->Z,p->Z);
-    fe_sub(r->X,r->Z,r->Y);
-    fe_add(r->Y,r->Z,r->Y);
-    fe_sub(r->Z,t0,r->T);
-    fe_add(r->T,t0,r->T);
-#else
-    fe_ge_msub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d,
-              q->yplusx, q->yminusx);
-#endif
-}
-
-
-/* ge p1p1 to p2 */
-/*
-r = p
-*/
-
-static void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p)
-{
-#ifndef CURVED25519_X64
-  fe_mul(r->X,p->X,p->T);
-  fe_mul(r->Y,p->Y,p->Z);
-  fe_mul(r->Z,p->Z,p->T);
-#else
-  fe_ge_to_p2(r->X, r->Y, r->Z, p->X, p->Y, p->Z, p->T);
-#endif
-}
-
-
-/* ge p1p1 to p3 */
-
-/*
-r = p
-*/
-
-static WC_INLINE void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p)
-{
-#ifndef CURVED25519_X64
-  fe_mul(r->X,p->X,p->T);
-  fe_mul(r->Y,p->Y,p->Z);
-  fe_mul(r->Z,p->Z,p->T);
-  fe_mul(r->T,p->X,p->Y);
-#else
-  fe_ge_to_p3(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T);
-#endif
-}
-
-
-/* ge p2 0 */
-
-static void ge_p2_0(ge_p2 *h)
-{
-  fe_0(h->X);
-  fe_1(h->Y);
-  fe_1(h->Z);
-}
-
-
-/* ge p2 dbl */
-
-/*
-r = 2 * p
-*/
-
-static WC_INLINE void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p)
-{
-#ifndef CURVED25519_X64
-    ge t0;
-    fe_sq(r->X,p->X);
-    fe_sq(r->Z,p->Y);
-    fe_sq2(r->T,p->Z);
-    fe_add(r->Y,p->X,p->Y);
-    fe_sq(t0,r->Y);
-    fe_add(r->Y,r->Z,r->X);
-    fe_sub(r->Z,r->Z,r->X);
-    fe_sub(r->X,t0,r->Y);
-    fe_sub(r->T,r->T,r->Z);
-#else
-    fe_ge_dbl(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z);
-#endif
-}
-
-
-/* ge p3 dble */
-
-/*
-r = 2 * p
-*/
-
-static void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p)
-{
-  ge_p2 q;
-  ge_p3_to_p2(&q,p);
-  ge_p2_dbl(r,&q);
-}
-
-
-/* ge p3 to cached */
-
-/*
-r = p
-*/
-
-#ifdef CURVED25519_X64
-static const ge d2 = {
-    0xebd69b9426b2f159, 0xe0149a8283b156, 0x198e80f2eef3d130, 0x2406d9dc56dffce7,
-    };
-#elif defined(CURVED25519_128BIT)
-static const ge d2 = {
-    0x69b9426b2f159, 0x35050762add7a, 0x3cf44c0038052, 0x6738cc7407977,
-    0x2406d9dc56dff
-};
-#else
-static const ge d2 = {
--21827239,-5839606,-30745221,13898782,229458,
-15978800,-12551817,-6495438,29715968,9444199
-} ;
-#endif
-
-
-static WC_INLINE void ge_p3_to_cached(ge_cached *r,const ge_p3 *p)
-{
-  fe_add(r->YplusX,p->Y,p->X);
-  fe_sub(r->YminusX,p->Y,p->X);
-  fe_copy(r->Z,p->Z);
-  fe_mul(r->T2d,p->T,d2);
-}
-
-
-/* ge p3 to p2 */
-/*
-r = p
-*/
-
-static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p)
-{
-  fe_copy(r->X,p->X);
-  fe_copy(r->Y,p->Y);
-  fe_copy(r->Z,p->Z);
-}
-
-
-/* ge p3 tobytes */
-void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
-{
-  ge recip;
-  ge x;
-  ge y;
-
-  fe_invert(recip,h->Z);
-  fe_mul(x,h->X,recip);
-  fe_mul(y,h->Y,recip);
-  fe_tobytes(s,y);
-  s[31] ^= fe_isnegative(x) << 7;
-}
-
-
-#ifndef CURVED25519_X64
-/* ge_precomp_0 */
-static void ge_precomp_0(ge_precomp *h)
-{
-  fe_1(h->yplusx);
-  fe_1(h->yminusx);
-  fe_0(h->xy2d);
-}
-#endif
-
-
-/* ge_sub */
-/*
-r = p - q
-*/
-
-static WC_INLINE void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
-{
-#ifndef CURVED25519_X64
-    ge t0;
-    fe_add(r->X,p->Y,p->X);
-    fe_sub(r->Y,p->Y,p->X);
-    fe_mul(r->Z,r->X,q->YminusX);
-    fe_mul(r->Y,r->Y,q->YplusX);
-    fe_mul(r->T,q->T2d,p->T);
-    fe_mul(r->X,p->Z,q->Z);
-    fe_add(t0,r->X,r->X);
-    fe_sub(r->X,r->Z,r->Y);
-    fe_add(r->Y,r->Z,r->Y);
-    fe_sub(r->Z,t0,r->T);
-    fe_add(r->T,t0,r->T);
-#else
-    fe_ge_sub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d,
-              q->YplusX, q->YminusX);
-#endif
-}
-
-
-/* ge tobytes */
-void ge_tobytes(unsigned char *s,const ge_p2 *h)
-{
-  ge recip;
-  ge x;
-  ge y;
-
-  fe_invert(recip,h->Z);
-  fe_mul(x,h->X,recip);
-  fe_mul(y,h->Y,recip);
-  fe_tobytes(s,y);
-  s[31] ^= fe_isnegative(x) << 7;
-}
-
-#endif /* !ED25519_SMALL */
-#endif /* HAVE_ED25519 */
-
--- a/wolfcrypt/src/hash.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,864 +0,0 @@
-/* hash.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#ifndef NO_ASN
-#include <wolfssl/wolfcrypt/asn.h>
-#endif
-
-#include <wolfssl/wolfcrypt/hash.h>
-
-
-#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
-
-#ifdef NO_ASN
-enum Hash_Sum  {
-    MD2h    = 646,
-    MD5h    = 649,
-    SHAh    =  88,
-    SHA224h = 417,
-    SHA256h = 414,
-    SHA384h = 415,
-    SHA512h = 416
-};
-#endif /* !NO_ASN */
-
-#ifdef HAVE_SELFTEST
-enum {
-    /* CAVP selftest includes these in hmac.h instead of sha3.h,
-       copied here for that build */
-    WC_SHA3_224_BLOCK_SIZE = 144,
-    WC_SHA3_256_BLOCK_SIZE = 136,
-    WC_SHA3_384_BLOCK_SIZE = 104,
-    WC_SHA3_512_BLOCK_SIZE = 72,
-};
-#endif
-
-
-/* function converts int hash type to enum */
-enum wc_HashType wc_HashTypeConvert(int hashType)
-{
-    /* Default to hash type none as error */
-    enum wc_HashType eHashType = WC_HASH_TYPE_NONE;
-#if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
-    /* original FIPSv1  and CAVP selftest require a mapping for unique hash
-       type to wc_HashType */
-    switch (hashType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            eHashType = WC_HASH_TYPE_MD5;
-            break;
-    #endif /* !NO_MD5 */
-    #ifndef NO_SHA
-        case WC_SHA:
-            eHashType = WC_HASH_TYPE_SHA;
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            eHashType = WC_HASH_TYPE_SHA224;
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            eHashType = WC_HASH_TYPE_SHA256;
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            eHashType = WC_HASH_TYPE_SHA384;
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            eHashType = WC_HASH_TYPE_SHA512;
-            break;
-    #endif /* WOLFSSL_SHA512 */
-        default:
-            eHashType = WC_HASH_TYPE_NONE;
-            break;
-    }
-#else
-    /* current master uses same unique types as wc_HashType */
-    if (hashType > 0 && hashType <= WC_HASH_TYPE_MAX) {
-        eHashType = (enum wc_HashType)hashType;
-    }
-#endif
-    return eHashType;
-}
-
-
-int wc_HashGetOID(enum wc_HashType hash_type)
-{
-    int oid = HASH_TYPE_E; /* Default to hash type error */
-    switch(hash_type)
-    {
-        case WC_HASH_TYPE_MD2:
-        #ifdef WOLFSSL_MD2
-            oid = MD2h;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD5_SHA:
-        case WC_HASH_TYPE_MD5:
-        #ifndef NO_MD5
-            oid = MD5h;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA:
-        #ifndef NO_SHA
-            oid = SHAh;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-        #ifdef WOLFSSL_SHA224
-            oid = SHA224h;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-        #ifndef NO_SHA256
-            oid = SHA256h;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-        #ifdef WOLFSSL_SHA384
-            oid = SHA384h;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-        #ifdef WOLFSSL_SHA512
-            oid = SHA512h;
-        #endif
-            break;
-
-        /* Not Supported */
-        case WC_HASH_TYPE_MD4:
-        case WC_HASH_TYPE_SHA3_224:
-        case WC_HASH_TYPE_SHA3_256:
-        case WC_HASH_TYPE_SHA3_384:
-        case WC_HASH_TYPE_SHA3_512:
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            oid = BAD_FUNC_ARG;
-            break;
-    }
-    return oid;
-}
-
-enum wc_HashType wc_OidGetHash(int oid)
-{
-    enum wc_HashType hash_type = WC_HASH_TYPE_NONE;
-    switch (oid)
-    {
-        case MD2h:
-        #ifdef WOLFSSL_MD2
-            hash_type = WC_HASH_TYPE_MD2;
-        #endif
-            break;
-        case MD5h:
-        #ifndef NO_MD5
-            hash_type = WC_HASH_TYPE_MD5;
-        #endif
-            break;
-        case SHAh:
-        #ifndef NO_SHA
-            hash_type = WC_HASH_TYPE_SHA;
-        #endif
-            break;
-        case SHA224h:
-        #ifdef WOLFSSL_SHA224
-            hash_type = WC_HASH_TYPE_SHA224;
-        #endif
-            break;
-        case SHA256h:
-        #ifndef NO_SHA256
-            hash_type = WC_HASH_TYPE_SHA256;
-        #endif
-            break;
-        case SHA384h:
-        #ifdef WOLFSSL_SHA384
-            hash_type = WC_HASH_TYPE_SHA384;
-        #endif
-            break;
-        case SHA512h:
-        #ifdef WOLFSSL_SHA512
-            hash_type = WC_HASH_TYPE_SHA512;
-        #endif
-            break;
-        default:
-            break;
-    }
-    return hash_type;
-}
-#endif /* !NO_ASN || !NO_DH || HAVE_ECC */
-
-
-
-/* Get Hash digest size */
-int wc_HashGetDigestSize(enum wc_HashType hash_type)
-{
-    int dig_size = HASH_TYPE_E; /* Default to hash type error */
-    switch(hash_type)
-    {
-        case WC_HASH_TYPE_MD2:
-        #ifdef WOLFSSL_MD2
-            dig_size = MD2_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD4:
-        #ifndef NO_MD4
-            dig_size = MD4_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD5:
-        #ifndef NO_MD5
-            dig_size = WC_MD5_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA:
-        #ifndef NO_SHA
-            dig_size = WC_SHA_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-        #ifdef WOLFSSL_SHA224
-            dig_size = WC_SHA224_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-        #ifndef NO_SHA256
-            dig_size = WC_SHA256_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-        #ifdef WOLFSSL_SHA384
-            dig_size = WC_SHA384_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-        #ifdef WOLFSSL_SHA512
-            dig_size = WC_SHA512_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */
-        #if !defined(NO_MD5) && !defined(NO_SHA)
-            dig_size = (int)WC_MD5_DIGEST_SIZE + (int)WC_SHA_DIGEST_SIZE;
-        #endif
-            break;
-
-        case WC_HASH_TYPE_SHA3_224:
-        #ifdef WOLFSSL_SHA3
-            dig_size = WC_SHA3_224_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_256:
-        #ifdef WOLFSSL_SHA3
-            dig_size = WC_SHA3_256_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_384:
-        #ifdef WOLFSSL_SHA3
-            dig_size = WC_SHA3_384_DIGEST_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_512:
-        #ifdef WOLFSSL_SHA3
-            dig_size = WC_SHA3_512_DIGEST_SIZE;
-        #endif
-            break;
-
-        /* Not Supported */
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            dig_size = BAD_FUNC_ARG;
-            break;
-    }
-    return dig_size;
-}
-
-
-/* Get Hash block size */
-int wc_HashGetBlockSize(enum wc_HashType hash_type)
-{
-    int block_size = HASH_TYPE_E; /* Default to hash type error */
-    switch (hash_type)
-    {
-        case WC_HASH_TYPE_MD2:
-        #ifdef WOLFSSL_MD2
-            block_size = MD2_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD4:
-        #ifndef NO_MD4
-            block_size = MD4_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD5:
-        #ifndef NO_MD5
-            block_size = WC_MD5_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA:
-        #ifndef NO_SHA
-            block_size = WC_SHA_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-        #ifdef WOLFSSL_SHA224
-            block_size = WC_SHA224_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-        #ifndef NO_SHA256
-            block_size = WC_SHA256_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-        #ifdef WOLFSSL_SHA384
-            block_size = WC_SHA384_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-        #ifdef WOLFSSL_SHA512
-            block_size = WC_SHA512_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */
-        #if !defined(NO_MD5) && !defined(NO_SHA)
-            block_size = (int)WC_MD5_BLOCK_SIZE + (int)WC_SHA_BLOCK_SIZE;
-        #endif
-            break;
-
-        case WC_HASH_TYPE_SHA3_224:
-        #ifdef WOLFSSL_SHA3
-            block_size = WC_SHA3_224_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_256:
-        #ifdef WOLFSSL_SHA3
-            block_size = WC_SHA3_256_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_384:
-        #ifdef WOLFSSL_SHA3
-            block_size = WC_SHA3_384_BLOCK_SIZE;
-        #endif
-            break;
-        case WC_HASH_TYPE_SHA3_512:
-        #ifdef WOLFSSL_SHA3
-            block_size = WC_SHA3_512_BLOCK_SIZE;
-        #endif
-            break;
-
-        /* Not Supported */
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            block_size = BAD_FUNC_ARG;
-            break;
-    }
-    return block_size;
-}
-
-/* Generic Hashing Wrapper */
-int wc_Hash(enum wc_HashType hash_type, const byte* data,
-    word32 data_len, byte* hash, word32 hash_len)
-{
-    int ret = HASH_TYPE_E; /* Default to hash type error */
-    word32 dig_size;
-
-    /* Validate hash buffer size */
-    dig_size = wc_HashGetDigestSize(hash_type);
-    if (hash_len < dig_size) {
-        return BUFFER_E;
-    }
-
-    /* Suppress possible unused arg if all hashing is disabled */
-    (void)data;
-    (void)data_len;
-    (void)hash;
-    (void)hash_len;
-
-    switch(hash_type)
-    {
-        case WC_HASH_TYPE_MD5:
-#ifndef NO_MD5
-            ret = wc_Md5Hash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA:
-#ifndef NO_SHA
-            ret = wc_ShaHash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-#ifdef WOLFSSL_SHA224
-            ret = wc_Sha224Hash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-#ifndef NO_SHA256
-            ret = wc_Sha256Hash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-#ifdef WOLFSSL_SHA384
-            ret = wc_Sha384Hash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-#ifdef WOLFSSL_SHA512
-            ret = wc_Sha512Hash(data, data_len, hash);
-#endif
-            break;
-        case WC_HASH_TYPE_MD5_SHA:
-#if !defined(NO_MD5) && !defined(NO_SHA)
-            ret = wc_Md5Hash(data, data_len, hash);
-            if (ret == 0) {
-                ret = wc_ShaHash(data, data_len, &hash[WC_MD5_DIGEST_SIZE]);
-            }
-#endif
-            break;
-
-        /* Not Supported */
-        case WC_HASH_TYPE_MD2:
-        case WC_HASH_TYPE_MD4:
-        case WC_HASH_TYPE_SHA3_224:
-        case WC_HASH_TYPE_SHA3_256:
-        case WC_HASH_TYPE_SHA3_384:
-        case WC_HASH_TYPE_SHA3_512:
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-    return ret;
-}
-
-int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type)
-{
-    int ret = HASH_TYPE_E; /* Default to hash type error */
-
-    if (hash == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (type) {
-        case WC_HASH_TYPE_MD5:
-#ifndef NO_MD5
-            wc_InitMd5(&hash->md5);
-            ret = 0;
-#endif
-            break;
-        case WC_HASH_TYPE_SHA:
-#ifndef NO_SHA
-            ret = wc_InitSha(&hash->sha);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-#ifdef WOLFSSL_SHA224
-            ret = wc_InitSha224(&hash->sha224);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-#ifndef NO_SHA256
-            ret = wc_InitSha256(&hash->sha256);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-#ifdef WOLFSSL_SHA384
-            ret = wc_InitSha384(&hash->sha384);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-#ifdef WOLFSSL_SHA512
-            ret = wc_InitSha512(&hash->sha512);
-#endif
-            break;
-
-        /* not supported */
-        case WC_HASH_TYPE_MD5_SHA:
-        case WC_HASH_TYPE_MD2:
-        case WC_HASH_TYPE_MD4:
-        case WC_HASH_TYPE_SHA3_224:
-        case WC_HASH_TYPE_SHA3_256:
-        case WC_HASH_TYPE_SHA3_384:
-        case WC_HASH_TYPE_SHA3_512:
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-    };
-
-    return ret;
-}
-
-int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data,
-                  word32 dataSz)
-{
-    int ret = HASH_TYPE_E; /* Default to hash type error */
-
-    if (hash == NULL || data == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (type) {
-        case WC_HASH_TYPE_MD5:
-#ifndef NO_MD5
-            wc_Md5Update(&hash->md5, data, dataSz);
-            ret = 0;
-#endif
-            break;
-        case WC_HASH_TYPE_SHA:
-#ifndef NO_SHA
-            ret = wc_ShaUpdate(&hash->sha, data, dataSz);
-            if (ret != 0)
-                return ret;
-#endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-#ifdef WOLFSSL_SHA224
-            ret = wc_Sha224Update(&hash->sha224, data, dataSz);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-#ifndef NO_SHA256
-            ret = wc_Sha256Update(&hash->sha256, data, dataSz);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-#ifdef WOLFSSL_SHA384
-            ret = wc_Sha384Update(&hash->sha384, data, dataSz);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-#ifdef WOLFSSL_SHA512
-            ret = wc_Sha512Update(&hash->sha512, data, dataSz);
-#endif
-            break;
-
-        /* not supported */
-        case WC_HASH_TYPE_MD5_SHA:
-        case WC_HASH_TYPE_MD2:
-        case WC_HASH_TYPE_MD4:
-        case WC_HASH_TYPE_SHA3_224:
-        case WC_HASH_TYPE_SHA3_256:
-        case WC_HASH_TYPE_SHA3_384:
-        case WC_HASH_TYPE_SHA3_512:
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-    };
-
-    return ret;
-}
-
-int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out)
-{
-    int ret = HASH_TYPE_E; /* Default to hash type error */
-
-    if (hash == NULL || out == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (type) {
-        case WC_HASH_TYPE_MD5:
-#ifndef NO_MD5
-            wc_Md5Final(&hash->md5, out);
-            ret = 0;
-#endif
-            break;
-        case WC_HASH_TYPE_SHA:
-#ifndef NO_SHA
-            ret = wc_ShaFinal(&hash->sha, out);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA224:
-#ifdef WOLFSSL_SHA224
-            ret = wc_Sha224Final(&hash->sha224, out);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA256:
-#ifndef NO_SHA256
-            ret = wc_Sha256Final(&hash->sha256, out);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA384:
-#ifdef WOLFSSL_SHA384
-            ret = wc_Sha384Final(&hash->sha384, out);
-#endif
-            break;
-        case WC_HASH_TYPE_SHA512:
-#ifdef WOLFSSL_SHA512
-            ret = wc_Sha512Final(&hash->sha512, out);
-#endif
-            break;
-
-        /* not supported */
-        case WC_HASH_TYPE_MD5_SHA:
-        case WC_HASH_TYPE_MD2:
-        case WC_HASH_TYPE_MD4:
-        case WC_HASH_TYPE_SHA3_224:
-        case WC_HASH_TYPE_SHA3_256:
-        case WC_HASH_TYPE_SHA3_384:
-        case WC_HASH_TYPE_SHA3_512:
-        case WC_HASH_TYPE_BLAKE2B:
-        case WC_HASH_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-    };
-
-    return ret;
-}
-
-
-#if !defined(WOLFSSL_TI_HASH)
-
-#if !defined(NO_MD5)
-    int wc_Md5Hash(const byte* data, word32 len, byte* hash)
-    {
-        int ret;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Md5* md5;
-    #else
-        wc_Md5  md5[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (md5 == NULL)
-            return MEMORY_E;
-    #endif
-
-        ret = wc_InitMd5(md5);
-        if (ret == 0) {
-            ret = wc_Md5Update(md5, data, len);
-            if (ret == 0) {
-                ret = wc_Md5Final(md5, hash);
-            }
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-        return ret;
-    }
-#endif /* !NO_MD5 */
-
-#if !defined(NO_SHA)
-    int wc_ShaHash(const byte* data, word32 len, byte* hash)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Sha* sha;
-    #else
-        wc_Sha sha[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_InitSha(sha)) != 0) {
-            WOLFSSL_MSG("wc_InitSha failed");
-        }
-        else {
-            wc_ShaUpdate(sha, data, len);
-            wc_ShaFinal(sha, hash);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-        return ret;
-    }
-#endif /* !NO_SHA */
-
-#if defined(WOLFSSL_SHA224)
-    int wc_Sha224Hash(const byte* data, word32 len, byte* hash)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Sha224* sha224;
-    #else
-        wc_Sha224 sha224[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        sha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha224 == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_InitSha224(sha224)) != 0) {
-            WOLFSSL_MSG("InitSha224 failed");
-        }
-        else {
-            if ((ret = wc_Sha224Update(sha224, data, len)) != 0) {
-                WOLFSSL_MSG("Sha224Update failed");
-            }
-            else if ((ret = wc_Sha224Final(sha224, hash)) != 0) {
-                WOLFSSL_MSG("Sha224Final failed");
-            }
-            wc_Sha224Free(sha224);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(sha224, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-    return ret;
-}
-#endif /* WOLFSSL_SHA224 */
-
-#if !defined(NO_SHA256)
-    int wc_Sha256Hash(const byte* data, word32 len, byte* hash)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Sha256* sha256;
-    #else
-        wc_Sha256 sha256[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        sha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha256 == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_InitSha256(sha256)) != 0) {
-            WOLFSSL_MSG("InitSha256 failed");
-        }
-        else {
-            if ((ret = wc_Sha256Update(sha256, data, len)) != 0) {
-                WOLFSSL_MSG("Sha256Update failed");
-            }
-            else if ((ret = wc_Sha256Final(sha256, hash)) != 0) {
-                WOLFSSL_MSG("Sha256Final failed");
-            }
-            wc_Sha256Free(sha256);
-        }
-
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-        return ret;
-    }
-#endif /* !NO_SHA256 */
-
-#endif /* !defined(WOLFSSL_TI_HASH) */
-
-
-#if defined(WOLFSSL_SHA512)
-    int wc_Sha512Hash(const byte* data, word32 len, byte* hash)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Sha512* sha512;
-    #else
-        wc_Sha512 sha512[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        sha512 = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), NULL,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha512 == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_InitSha512(sha512)) != 0) {
-            WOLFSSL_MSG("InitSha512 failed");
-        }
-        else {
-            if ((ret = wc_Sha512Update(sha512, data, len)) != 0) {
-                WOLFSSL_MSG("Sha512Update failed");
-            }
-            else if ((ret = wc_Sha512Final(sha512, hash)) != 0) {
-                WOLFSSL_MSG("Sha512Final failed");
-            }
-            wc_Sha512Free(sha512);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-        return ret;
-    }
-#endif /* WOLFSSL_SHA512 */
-
-#if defined(WOLFSSL_SHA384)
-    int wc_Sha384Hash(const byte* data, word32 len, byte* hash)
-    {
-        int ret = 0;
-    #ifdef WOLFSSL_SMALL_STACK
-        wc_Sha384* sha384;
-    #else
-        wc_Sha384 sha384[1];
-    #endif
-
-    #ifdef WOLFSSL_SMALL_STACK
-        sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), NULL,
-            DYNAMIC_TYPE_TMP_BUFFER);
-        if (sha384 == NULL)
-            return MEMORY_E;
-    #endif
-
-        if ((ret = wc_InitSha384(sha384)) != 0) {
-            WOLFSSL_MSG("InitSha384 failed");
-        }
-        else {
-            if ((ret = wc_Sha384Update(sha384, data, len)) != 0) {
-                WOLFSSL_MSG("Sha384Update failed");
-            }
-            else if ((ret = wc_Sha384Final(sha384, hash)) != 0) {
-                WOLFSSL_MSG("Sha384Final failed");
-            }
-            wc_Sha384Free(sha384);
-        }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-
-        return ret;
-    }
-#endif /* WOLFSSL_SHA384 */
-
--- a/wolfcrypt/src/hc128.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-/* hc128.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_HC128
-
-#include <wolfssl/wolfcrypt/hc128.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/hc128.h>
-		#include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifdef BIG_ENDIAN_ORDER
-    #define LITTLE32(x) ByteReverseWord32(x)
-#else
-    #define LITTLE32(x) (x)
-#endif
-
-
-/*h1 function*/
-#define h1(ctx, x, y) {                         \
-     byte a,c;                                  \
-     a = (byte) (x);                            \
-     c = (byte) ((x) >> 16);                    \
-     y = (ctx->T[512+a])+(ctx->T[512+256+c]);   \
-}
-
-/*h2 function*/
-#define h2(ctx, x, y) {                         \
-     byte a,c;                                  \
-     a = (byte) (x);                            \
-     c = (byte) ((x) >> 16);                    \
-     y = (ctx->T[a])+(ctx->T[256+c]);           \
-}
-
-/*one step of HC-128, update P and generate 32 bits keystream*/
-#define step_P(ctx,u,v,a,b,c,d,n){              \
-     word32 tem0,tem1,tem2,tem3;                \
-     h1((ctx),(ctx->X[(d)]),tem3);              \
-     tem0 = rotrFixed((ctx->T[(v)]),23);        \
-     tem1 = rotrFixed((ctx->X[(c)]),10);        \
-     tem2 = rotrFixed((ctx->X[(b)]),8);         \
-     (ctx->T[(u)]) += tem2+(tem0 ^ tem1);       \
-     (ctx->X[(a)]) = (ctx->T[(u)]);             \
-     (n) = tem3 ^ (ctx->T[(u)]) ;               \
-}
-
-/*one step of HC-128, update Q and generate 32 bits keystream*/
-#define step_Q(ctx,u,v,a,b,c,d,n){              \
-     word32 tem0,tem1,tem2,tem3;                \
-     h2((ctx),(ctx->Y[(d)]),tem3);              \
-     tem0 = rotrFixed((ctx->T[(v)]),(32-23));   \
-     tem1 = rotrFixed((ctx->Y[(c)]),(32-10));   \
-     tem2 = rotrFixed((ctx->Y[(b)]),(32-8));    \
-     (ctx->T[(u)]) += tem2 + (tem0 ^ tem1);     \
-     (ctx->Y[(a)]) = (ctx->T[(u)]);             \
-     (n) = tem3 ^ (ctx->T[(u)]) ;               \
-}
-
-/*16 steps of HC-128, generate 512 bits keystream*/
-static void generate_keystream(HC128* ctx, word32* keystream)
-{
-   word32 cc,dd;
-   cc = ctx->counter1024 & 0x1ff;
-   dd = (cc+16)&0x1ff;
-
-   if (ctx->counter1024 < 512)
-   {
-      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
-      step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]);
-      step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]);
-      step_P(ctx, cc+2, cc+3, 2, 8, 15,6, keystream[2]);
-      step_P(ctx, cc+3, cc+4, 3, 9, 0, 7, keystream[3]);
-      step_P(ctx, cc+4, cc+5, 4, 10,1, 8, keystream[4]);
-      step_P(ctx, cc+5, cc+6, 5, 11,2, 9, keystream[5]);
-      step_P(ctx, cc+6, cc+7, 6, 12,3, 10,keystream[6]);
-      step_P(ctx, cc+7, cc+8, 7, 13,4, 11,keystream[7]);
-      step_P(ctx, cc+8, cc+9, 8, 14,5, 12,keystream[8]);
-      step_P(ctx, cc+9, cc+10,9, 15,6, 13,keystream[9]);
-      step_P(ctx, cc+10,cc+11,10,0, 7, 14,keystream[10]);
-      step_P(ctx, cc+11,cc+12,11,1, 8, 15,keystream[11]);
-      step_P(ctx, cc+12,cc+13,12,2, 9, 0, keystream[12]);
-      step_P(ctx, cc+13,cc+14,13,3, 10,1, keystream[13]);
-      step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]);
-      step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]);
-   }
-   else
-   {
-	  ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
-      step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]);
-      step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]);
-      step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]);
-      step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]);
-      step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]);
-      step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]);
-      step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]);
-      step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]);
-      step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]);
-      step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]);
-      step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]);
-      step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]);
-      step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]);
-      step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]);
-      step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]);
-      step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]);
-   }
-}
-
-
-/* The following defines the initialization functions */
-#define f1(x)  (rotrFixed((x),7)  ^ rotrFixed((x),18) ^ ((x) >> 3))
-#define f2(x)  (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10))
-
-/*update table P*/
-#define update_P(ctx,u,v,a,b,c,d){                  \
-     word32 tem0,tem1,tem2,tem3;                    \
-     tem0 = rotrFixed((ctx->T[(v)]),23);            \
-     tem1 = rotrFixed((ctx->X[(c)]),10);            \
-     tem2 = rotrFixed((ctx->X[(b)]),8);             \
-     h1((ctx),(ctx->X[(d)]),tem3);                  \
-     (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3;     \
-     (ctx->X[(a)]) = (ctx->T[(u)]);                 \
-}
-
-/*update table Q*/
-#define update_Q(ctx,u,v,a,b,c,d){                  \
-     word32 tem0,tem1,tem2,tem3;                    \
-     tem0 = rotrFixed((ctx->T[(v)]),(32-23));       \
-     tem1 = rotrFixed((ctx->Y[(c)]),(32-10));       \
-     tem2 = rotrFixed((ctx->Y[(b)]),(32-8));        \
-     h2((ctx),(ctx->Y[(d)]),tem3);                  \
-     (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3;     \
-     (ctx->Y[(a)]) = (ctx->T[(u)]);                 \
-}
-
-/*16 steps of HC-128, without generating keystream, */
-/*but use the outputs to update P and Q*/
-static void setup_update(HC128* ctx)  /*each time 16 steps*/
-{
-   word32 cc,dd;
-   cc = ctx->counter1024 & 0x1ff;
-   dd = (cc+16)&0x1ff;
-
-   if (ctx->counter1024 < 512)
-   {
-      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
-      update_P(ctx, cc+0, cc+1, 0, 6, 13, 4);
-      update_P(ctx, cc+1, cc+2, 1, 7, 14, 5);
-      update_P(ctx, cc+2, cc+3, 2, 8, 15, 6);
-      update_P(ctx, cc+3, cc+4, 3, 9, 0,  7);
-      update_P(ctx, cc+4, cc+5, 4, 10,1,  8);
-      update_P(ctx, cc+5, cc+6, 5, 11,2,  9);
-      update_P(ctx, cc+6, cc+7, 6, 12,3,  10);
-      update_P(ctx, cc+7, cc+8, 7, 13,4,  11);
-      update_P(ctx, cc+8, cc+9, 8, 14,5,  12);
-      update_P(ctx, cc+9, cc+10,9, 15,6,  13);
-      update_P(ctx, cc+10,cc+11,10,0, 7,  14);
-      update_P(ctx, cc+11,cc+12,11,1, 8,  15);
-      update_P(ctx, cc+12,cc+13,12,2, 9,  0);
-      update_P(ctx, cc+13,cc+14,13,3, 10, 1);
-      update_P(ctx, cc+14,cc+15,14,4, 11, 2);
-      update_P(ctx, cc+15,dd+0, 15,5, 12, 3);
-   }
-   else
-   {
-      ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
-      update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4);
-      update_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14, 5);
-      update_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15, 6);
-      update_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0,  7);
-      update_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1,  8);
-      update_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2,  9);
-      update_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3,  10);
-      update_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4,  11);
-      update_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5,  12);
-      update_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6,  13);
-      update_Q(ctx, 512+cc+10,512+cc+11,10,0, 7,  14);
-      update_Q(ctx, 512+cc+11,512+cc+12,11,1, 8,  15);
-      update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9,  0);
-      update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1);
-      update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2);
-      update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3);
-   }
-}
-
-
-/* for the 128-bit key:  key[0]...key[15]
-*  key[0] is the least significant byte of ctx->key[0] (K_0);
-*  key[3] is the most significant byte of ctx->key[0]  (K_0);
-*  ...
-*  key[12] is the least significant byte of ctx->key[3] (K_3)
-*  key[15] is the most significant byte of ctx->key[3]  (K_3)
-*
-*  for the 128-bit iv:  iv[0]...iv[15]
-*  iv[0] is the least significant byte of ctx->iv[0] (IV_0);
-*  iv[3] is the most significant byte of ctx->iv[0]  (IV_0);
-*  ...
-*  iv[12] is the least significant byte of ctx->iv[3] (IV_3)
-*  iv[15] is the most significant byte of ctx->iv[3]  (IV_3)
-*/
-
-
-
-static void Hc128_SetIV(HC128* ctx, const byte* inIv)
-{
-    word32 i;
-    word32 iv[4];
-
-    if (inIv)
-        XMEMCPY(iv, inIv, sizeof(iv));
-    else
-        XMEMSET(iv,    0, sizeof(iv));
-
-	for (i = 0; i < (128 >> 5); i++)
-        ctx->iv[i] = LITTLE32(iv[i]);
-
-    for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4];
-
-    /* expand the key and IV into the table T */
-    /* (expand the key and IV into the table P and Q) */
-
-	for (i = 0; i < 8;  i++)   ctx->T[i] = ctx->key[i];
-	for (i = 8; i < 16; i++)   ctx->T[i] = ctx->iv[i-8];
-
-    for (i = 16; i < (256+16); i++)
-		ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
-                                                       ctx->T[i-16]+i;
-
-	for (i = 0; i < 16;  i++)  ctx->T[i] = ctx->T[256+i];
-
-	for (i = 16; i < 1024; i++)
-		ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
-                                                       ctx->T[i-16]+256+i;
-
-    /* initialize counter1024, X and Y */
-	ctx->counter1024 = 0;
-	for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i];
-    for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i];
-
-    /* run the cipher 1024 steps before generating the output */
-	for (i = 0; i < 64; i++)  setup_update(ctx);
-}
-
-
-static WC_INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv)
-{
-  word32 i;
-
-  /* Key size in bits 128 */
-  for (i = 0; i < (128 >> 5); i++)
-      ctx->key[i] = LITTLE32(((word32*)key)[i]);
-
-  for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4];
-
-  Hc128_SetIV(ctx, iv);
-
-  return 0;
-}
-
-
-int wc_Hc128_SetHeap(HC128* ctx, void* heap)
-{
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    ctx->heap = heap;
-#endif
-
-    (void)heap;
-    return 0;
-}
-
-/* Key setup */
-int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv)
-{
-    if (ctx == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    /* default heap to NULL or heap test value */
-    #ifdef WOLFSSL_HEAP_TEST
-        ctx->heap = (void*)WOLFSSL_HEAP_TEST;
-    #else
-        ctx->heap = NULL;
-    #endif /* WOLFSSL_HEAP_TEST */
-
-    if ((wolfssl_word)key % 4) {
-        int alignKey[4];
-
-        /* iv gets aligned in SetIV */
-        WOLFSSL_MSG("Hc128SetKey unaligned key");
-
-        XMEMCPY(alignKey, key, sizeof(alignKey));
-
-        return DoKey(ctx, (const byte*)alignKey, iv);
-    }
-#endif /* XSTREAM_ALIGN */
-
-    return DoKey(ctx, key, iv);
-}
-
-
-
-/* The following defines the encryption of data stream */
-static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input,
-                            word32 msglen)
-{
-  word32 i, keystream[16];
-
-  for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64)
-  {
-	  generate_keystream(ctx, keystream);
-
-      /* unroll loop */
-	  ((word32*)output)[0]  = ((word32*)input)[0]  ^ LITTLE32(keystream[0]);
-	  ((word32*)output)[1]  = ((word32*)input)[1]  ^ LITTLE32(keystream[1]);
-	  ((word32*)output)[2]  = ((word32*)input)[2]  ^ LITTLE32(keystream[2]);
-	  ((word32*)output)[3]  = ((word32*)input)[3]  ^ LITTLE32(keystream[3]);
-	  ((word32*)output)[4]  = ((word32*)input)[4]  ^ LITTLE32(keystream[4]);
-	  ((word32*)output)[5]  = ((word32*)input)[5]  ^ LITTLE32(keystream[5]);
-	  ((word32*)output)[6]  = ((word32*)input)[6]  ^ LITTLE32(keystream[6]);
-	  ((word32*)output)[7]  = ((word32*)input)[7]  ^ LITTLE32(keystream[7]);
-	  ((word32*)output)[8]  = ((word32*)input)[8]  ^ LITTLE32(keystream[8]);
-	  ((word32*)output)[9]  = ((word32*)input)[9]  ^ LITTLE32(keystream[9]);
-	  ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]);
-	  ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]);
-	  ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]);
-	  ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]);
-	  ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]);
-	  ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]);
-  }
-
-  if (msglen > 0)
-  {
-      XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */
-      generate_keystream(ctx, keystream);
-
-#ifdef BIG_ENDIAN_ORDER
-      {
-          word32 wordsLeft = msglen / sizeof(word32);
-          if (msglen % sizeof(word32)) wordsLeft++;
-
-          ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32));
-      }
-#endif
-
-      for (i = 0; i < msglen; i++)
-	      output[i] = input[i] ^ ((byte*)keystream)[i];
-  }
-
-  return 0;
-}
-
-
-/* Encrypt/decrypt a message of any size */
-int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen)
-{
-    if (ctx == NULL || output == NULL || input == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) {
-        #ifndef NO_WOLFSSL_ALLOC_ALIGN
-            byte* tmp;
-            WOLFSSL_MSG("Hc128Process unaligned");
-
-            tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            if (tmp == NULL) return MEMORY_E;
-
-            XMEMCPY(tmp, input, msglen);
-            DoProcess(ctx, tmp, tmp, msglen);
-            XMEMCPY(output, tmp, msglen);
-
-            XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-            return 0;
-        #else
-            return BAD_ALIGN_E;
-        #endif
-    }
-#endif /* XSTREAM_ALIGN */
-
-    return DoProcess(ctx, output, input, msglen);
-}
-
-
-#else  /* HAVE_HC128 */
-
-
-#ifdef _MSC_VER
-    /* 4206 warning for blank file */
-    #pragma warning(disable: 4206)
-#endif
-
-
-#endif /* HAVE_HC128 */
-
--- a/wolfcrypt/src/hmac.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1214 +0,0 @@
-/* hmac.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifndef NO_HMAC
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$b")
-        #pragma const_seg(".fipsB$b")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/hmac.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* fips wrapper calls, user can call direct */
-/* If building for old FIPS. */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    /* does init */
-    int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz)
-    {
-        if (hmac == NULL || (key == NULL && keySz != 0) ||
-           !(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 ||
-                type == WC_SHA384 || type == WC_SHA512 ||
-                type == BLAKE2B_ID)) {
-            return BAD_FUNC_ARG;
-        }
-
-        return HmacSetKey_fips(hmac, type, key, keySz);
-    }
-    int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz)
-    {
-        if (hmac == NULL || (in == NULL && sz > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        return HmacUpdate_fips(hmac, in, sz);
-    }
-    int wc_HmacFinal(Hmac* hmac, byte* out)
-    {
-        if (hmac == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        return HmacFinal_fips(hmac, out);
-    }
-    int wolfSSL_GetHmacMaxSize(void)
-    {
-        return CyaSSL_GetHmacMaxSize();
-    }
-
-    int wc_HmacInit(Hmac* hmac, void* heap, int devId)
-    {
-        (void)hmac;
-        (void)heap;
-        (void)devId;
-        /* FIPS doesn't support:
-            return HmacInit(hmac, heap, devId); */
-        return 0;
-    }
-    void wc_HmacFree(Hmac* hmac)
-    {
-        (void)hmac;
-        /* FIPS doesn't support:
-            HmacFree(hmac); */
-    }
-
-    #ifdef HAVE_HKDF
-        int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
-                    const byte* salt, word32 saltSz,
-                    const byte* info, word32 infoSz,
-                    byte* out, word32 outSz)
-        {
-            return HKDF(type, inKey, inKeySz, salt, saltSz,
-                info, infoSz, out, outSz);
-        }
-    #endif /* HAVE_HKDF */
-
-#else /* else build without fips, or for new fips */
-
-
-int wc_HmacSizeByType(int type)
-{
-    int ret;
-
-    if (!(type == WC_MD5 || type == WC_SHA ||
-            type == WC_SHA224 || type == WC_SHA256 ||
-            type == WC_SHA384 || type == WC_SHA512 ||
-            type == WC_SHA3_224 || type == WC_SHA3_256 ||
-            type == WC_SHA3_384 || type == WC_SHA3_512 ||
-            type == BLAKE2B_ID)) {
-        return BAD_FUNC_ARG;
-    }
-
-    switch (type) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = WC_MD5_DIGEST_SIZE;
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = WC_SHA_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            ret = WC_SHA224_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = WC_SHA256_DIGEST_SIZE;
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = WC_SHA384_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = WC_SHA512_DIGEST_SIZE;
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = BLAKE2B_OUTBYTES;
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = WC_SHA3_224_DIGEST_SIZE;
-            break;
-
-        case WC_SHA3_256:
-            ret = WC_SHA3_256_DIGEST_SIZE;
-            break;
-
-        case WC_SHA3_384:
-            ret = WC_SHA3_384_DIGEST_SIZE;
-            break;
-
-        case WC_SHA3_512:
-            ret = WC_SHA3_512_DIGEST_SIZE;
-            break;
-
-    #endif
-
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    return ret;
-}
-
-int _InitHmac(Hmac* hmac, int type, void* heap)
-{
-    int ret = 0;
-
-    switch (type) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = wc_InitMd5(&hmac->hash.md5);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = wc_InitSha(&hmac->hash.sha);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            ret = wc_InitSha224(&hmac->hash.sha224);
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = wc_InitSha256(&hmac->hash.sha256);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = wc_InitSha384(&hmac->hash.sha384);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = wc_InitSha512(&hmac->hash.sha512);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256);
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_256:
-            ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_384:
-            ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-        case WC_SHA3_512:
-            ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
-            break;
-    #endif
-
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    /* default to NULL heap hint or test value */
-#ifdef WOLFSSL_HEAP_TEST
-    hmac->heap = (void)WOLFSSL_HEAP_TEST;
-#else
-    hmac->heap = heap;
-#endif /* WOLFSSL_HEAP_TEST */
-
-    return ret;
-}
-
-
-int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
-{
-    byte*  ip;
-    byte*  op;
-    word32 i, hmac_block_size = 0;
-    int    ret = 0;
-    void*  heap = NULL;
-
-    if (hmac == NULL || (key == NULL && length != 0) ||
-       !(type == WC_MD5 || type == WC_SHA ||
-            type == WC_SHA224 || type == WC_SHA256 ||
-            type == WC_SHA384 || type == WC_SHA512 ||
-            type == WC_SHA3_224 || type == WC_SHA3_256 ||
-            type == WC_SHA3_384 || type == WC_SHA3_512 ||
-            type == BLAKE2B_ID)) {
-        return BAD_FUNC_ARG;
-    }
-
-    hmac->innerHashKeyed = 0;
-    hmac->macType = (byte)type;
-
-    ret = _InitHmac(hmac, type, heap);
-    if (ret != 0)
-        return ret;
-
-#ifdef HAVE_FIPS
-    if (length < HMAC_FIPS_MIN_KEY)
-        return HMAC_MIN_KEYLEN_E;
-#endif
-
-    ip = (byte*)hmac->ipad;
-    op = (byte*)hmac->opad;
-
-    switch (hmac->macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            hmac_block_size = WC_MD5_BLOCK_SIZE;
-            if (length <= WC_MD5_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Md5Update(&hmac->hash.md5, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Md5Final(&hmac->hash.md5, ip);
-                if (ret != 0)
-                    break;
-                length = WC_MD5_DIGEST_SIZE;
-            }
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            hmac_block_size = WC_SHA_BLOCK_SIZE;
-            if (length <= WC_SHA_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_ShaUpdate(&hmac->hash.sha, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_ShaFinal(&hmac->hash.sha, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA_DIGEST_SIZE;
-            }
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-        {
-            hmac_block_size = WC_SHA224_BLOCK_SIZE;
-            if (length <= WC_SHA224_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha224Update(&hmac->hash.sha224, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha224Final(&hmac->hash.sha224, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA224_DIGEST_SIZE;
-            }
-        }
-        break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-    		hmac_block_size = WC_SHA256_BLOCK_SIZE;
-            if (length <= WC_SHA256_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha256Update(&hmac->hash.sha256, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha256Final(&hmac->hash.sha256, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA256_DIGEST_SIZE;
-            }
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            hmac_block_size = WC_SHA384_BLOCK_SIZE;
-            if (length <= WC_SHA384_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha384Update(&hmac->hash.sha384, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha384Final(&hmac->hash.sha384, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA384_DIGEST_SIZE;
-            }
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            hmac_block_size = WC_SHA512_BLOCK_SIZE;
-            if (length <= WC_SHA512_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha512Update(&hmac->hash.sha512, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha512Final(&hmac->hash.sha512, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA512_DIGEST_SIZE;
-            }
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            hmac_block_size = BLAKE2B_BLOCKBYTES;
-            if (length <= BLAKE2B_BLOCKBYTES) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256);
-                if (ret != 0)
-                    break;
-
-                length = BLAKE2B_256;
-            }
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            hmac_block_size = WC_SHA3_224_BLOCK_SIZE;
-            if (length <= WC_SHA3_224_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA3_224_DIGEST_SIZE;
-            }
-            break;
-        case WC_SHA3_256:
-            hmac_block_size = WC_SHA3_256_BLOCK_SIZE;
-            if (length <= WC_SHA3_256_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA3_256_DIGEST_SIZE;
-            }
-            break;
-        case WC_SHA3_384:
-            hmac_block_size = WC_SHA3_384_BLOCK_SIZE;
-            if (length <= WC_SHA3_384_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA3_384_DIGEST_SIZE;
-            }
-            break;
-        case WC_SHA3_512:
-            hmac_block_size = WC_SHA3_512_BLOCK_SIZE;
-            if (length <= WC_SHA3_512_BLOCK_SIZE) {
-                if (key != NULL) {
-                    XMEMCPY(ip, key, length);
-                }
-            }
-            else {
-                ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length);
-                if (ret != 0)
-                    break;
-                ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip);
-                if (ret != 0)
-                    break;
-
-                length = WC_SHA3_512_DIGEST_SIZE;
-            }
-            break;
-    #endif /* WOLFSSL_SHA3 */
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
-    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
-    #if defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM)
-        #ifdef HAVE_INTEL_QA
-        if (IntelQaHmacGetType(hmac->macType, NULL) == 0)
-        #endif
-        {
-            if (length > hmac_block_size)
-                length = hmac_block_size;
-            /* update key length */
-            hmac->keyLen = (word16)length;
-
-            return ret;
-        }
-        /* no need to pad below */
-    #endif
-    }
-#endif
-
-    if (ret == 0) {
-        if (length < hmac_block_size)
-            XMEMSET(ip + length, 0, hmac_block_size - length);
-
-        for(i = 0; i < hmac_block_size; i++) {
-            op[i] = ip[i] ^ OPAD;
-            ip[i] ^= IPAD;
-        }
-    }
-
-    return ret;
-}
-
-
-static int HmacKeyInnerHash(Hmac* hmac)
-{
-    int ret = 0;
-
-    switch (hmac->macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad,
-                                                                WC_MD5_BLOCK_SIZE);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad,
-                                                             WC_SHA_BLOCK_SIZE);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad,
-                                                             WC_SHA224_BLOCK_SIZE);
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad,
-                                                             WC_SHA256_BLOCK_SIZE);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad,
-                                                             WC_SHA384_BLOCK_SIZE);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad,
-                                                             WC_SHA512_BLOCK_SIZE);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad,
-                                                            BLAKE2B_BLOCKBYTES);
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
-                                                       WC_SHA3_224_BLOCK_SIZE);
-            break;
-        case WC_SHA3_256:
-            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
-                                                       WC_SHA3_256_BLOCK_SIZE);
-            break;
-        case WC_SHA3_384:
-            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
-                                                       WC_SHA3_384_BLOCK_SIZE);
-            break;
-        case WC_SHA3_512:
-            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
-                                                       WC_SHA3_512_BLOCK_SIZE);
-            break;
-    #endif /* WOLFSSL_SHA3 */
-
-        default:
-            break;
-    }
-
-    if (ret == 0)
-        hmac->innerHashKeyed = 1;
-
-    return ret;
-}
-
-
-int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
-{
-    int ret = 0;
-
-    if (hmac == NULL || (msg == NULL && length > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
-    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
-    #if defined(HAVE_CAVIUM)
-        return NitroxHmacUpdate(hmac, msg, length);
-    #elif defined(HAVE_INTEL_QA)
-        if (IntelQaHmacGetType(hmac->macType, NULL) == 0) {
-            return IntelQaHmac(&hmac->asyncDev, hmac->macType,
-                (byte*)hmac->ipad, hmac->keyLen, NULL, msg, length);
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    if (!hmac->innerHashKeyed) {
-        ret = HmacKeyInnerHash(hmac);
-        if (ret != 0)
-            return ret;
-    }
-
-    switch (hmac->macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = wc_Md5Update(&hmac->hash.md5, msg, length);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = wc_ShaUpdate(&hmac->hash.sha, msg, length);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            ret = wc_Sha224Update(&hmac->hash.sha224, msg, length);
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = wc_Sha256Update(&hmac->hash.sha256, msg, length);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = wc_Sha384Update(&hmac->hash.sha384, msg, length);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = wc_Sha512Update(&hmac->hash.sha512, msg, length);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length);
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = wc_Sha3_224_Update(&hmac->hash.sha3, msg, length);
-            break;
-        case WC_SHA3_256:
-            ret = wc_Sha3_256_Update(&hmac->hash.sha3, msg, length);
-            break;
-        case WC_SHA3_384:
-            ret = wc_Sha3_384_Update(&hmac->hash.sha3, msg, length);
-            break;
-        case WC_SHA3_512:
-            ret = wc_Sha3_512_Update(&hmac->hash.sha3, msg, length);
-            break;
-    #endif /* WOLFSSL_SHA3 */
-
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-
-int wc_HmacFinal(Hmac* hmac, byte* hash)
-{
-    int ret;
-
-    if (hmac == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
-    if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
-        int hashLen = wc_HmacSizeByType(hmac->macType);
-        if (hashLen <= 0)
-            return hashLen;
-
-    #if defined(HAVE_CAVIUM)
-        return NitroxHmacFinal(hmac, hash, hashLen);
-    #elif defined(HAVE_INTEL_QA)
-        if (IntelQaHmacGetType(hmac->macType, NULL) == 0) {
-            return IntelQaHmac(&hmac->asyncDev, hmac->macType,
-                (byte*)hmac->ipad, hmac->keyLen, hash, NULL, hashLen);
-        }
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    if (!hmac->innerHashKeyed) {
-        ret = HmacKeyInnerHash(hmac);
-        if (ret != 0)
-            return ret;
-    }
-
-    switch (hmac->macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad,
-                                                                WC_MD5_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash,
-                                                               WC_MD5_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Md5Final(&hmac->hash.md5, hash);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad,
-                                                             WC_SHA_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash,
-                                                            WC_SHA_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_ShaFinal(&hmac->hash.sha, hash);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-        {
-            ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad,
-                                                             WC_SHA224_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash,
-                                                            WC_SHA224_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha224Final(&hmac->hash.sha224, hash);
-            if (ret != 0)
-                break;
-        }
-        break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad,
-                                                             WC_SHA256_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash,
-                                                            WC_SHA256_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha256Final(&hmac->hash.sha256, hash);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad,
-                                                             WC_SHA384_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash,
-                                                            WC_SHA384_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha384Final(&hmac->hash.sha384, hash);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad,
-                                                             WC_SHA512_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash,
-                                                            WC_SHA512_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha512Final(&hmac->hash.sha512, hash);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash,
-                                                                   BLAKE2B_256);
-            if (ret != 0)
-                break;
-            ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad,
-                                                            BLAKE2B_BLOCKBYTES);
-            if (ret != 0)
-                break;
-            ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash,
-                                                                   BLAKE2B_256);
-            if (ret != 0)
-                break;
-            ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256);
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            ret = wc_Sha3_224_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->opad,
-                                                       WC_SHA3_224_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
-                                                          WC_SHA3_224_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_224_Final(&hmac->hash.sha3, hash);
-            break;
-        case WC_SHA3_256:
-            ret = wc_Sha3_256_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->opad,
-                                                       WC_SHA3_256_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
-                                                          WC_SHA3_256_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_256_Final(&hmac->hash.sha3, hash);
-            break;
-        case WC_SHA3_384:
-            ret = wc_Sha3_384_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->opad,
-                                                       WC_SHA3_384_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
-                                                          WC_SHA3_384_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_384_Final(&hmac->hash.sha3, hash);
-            break;
-        case WC_SHA3_512:
-            ret = wc_Sha3_512_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->opad,
-                                                       WC_SHA3_512_BLOCK_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
-                                                          WC_SHA3_512_DIGEST_SIZE);
-            if (ret != 0)
-                break;
-            ret = wc_Sha3_512_Final(&hmac->hash.sha3, hash);
-            break;
-    #endif /* WOLFSSL_SHA3 */
-
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    if (ret == 0) {
-        hmac->innerHashKeyed = 0;
-    }
-
-    return ret;
-}
-
-
-/* Initialize Hmac for use with async device */
-int wc_HmacInit(Hmac* hmac, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (hmac == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMSET(hmac, 0, sizeof(Hmac));
-    hmac->heap = heap;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
-    hmac->keyLen = 0;
-
-    ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC,
-                                                         hmac->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-/* Free Hmac from use with async device */
-void wc_HmacFree(Hmac* hmac)
-{
-    if (hmac == NULL)
-        return;
-
-    switch (hmac->macType) {
-    #ifndef NO_MD5
-        case WC_MD5:
-            wc_Md5Free(&hmac->hash.md5);
-            break;
-    #endif /* !NO_MD5 */
-
-    #ifndef NO_SHA
-        case WC_SHA:
-            wc_ShaFree(&hmac->hash.sha);
-            break;
-    #endif /* !NO_SHA */
-
-    #ifdef WOLFSSL_SHA224
-        case WC_SHA224:
-            wc_Sha224Free(&hmac->hash.sha224);
-            break;
-    #endif /* WOLFSSL_SHA224 */
-
-    #ifndef NO_SHA256
-        case WC_SHA256:
-            wc_Sha256Free(&hmac->hash.sha256);
-            break;
-    #endif /* !NO_SHA256 */
-
-    #ifdef WOLFSSL_SHA384
-        case WC_SHA384:
-            wc_Sha384Free(&hmac->hash.sha384);
-            break;
-    #endif /* WOLFSSL_SHA384 */
-    #ifdef WOLFSSL_SHA512
-        case WC_SHA512:
-            wc_Sha512Free(&hmac->hash.sha512);
-            break;
-    #endif /* WOLFSSL_SHA512 */
-
-    #ifdef HAVE_BLAKE2
-        case BLAKE2B_ID:
-            break;
-    #endif /* HAVE_BLAKE2 */
-
-    #ifdef WOLFSSL_SHA3
-        case WC_SHA3_224:
-            wc_Sha3_224_Free(&hmac->hash.sha3);
-            break;
-        case WC_SHA3_256:
-            wc_Sha3_256_Free(&hmac->hash.sha3);
-            break;
-        case WC_SHA3_384:
-            wc_Sha3_384_Free(&hmac->hash.sha3);
-            break;
-        case WC_SHA3_512:
-            wc_Sha3_512_Free(&hmac->hash.sha3);
-            break;
-    #endif /* WOLFSSL_SHA3 */
-
-        default:
-            break;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
-    wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-int wolfSSL_GetHmacMaxSize(void)
-{
-    return WC_MAX_DIGEST_SIZE;
-}
-
-#ifdef HAVE_HKDF
-    /* HMAC-KDF-Extract.
-     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
-     *
-     * type     The hash algorithm type.
-     * salt     The optional salt value.
-     * saltSz   The size of the salt.
-     * inKey    The input keying material.
-     * inKeySz  The size of the input keying material.
-     * out      The pseudorandom key with the length that of the hash.
-     * returns 0 on success, otherwise failure.
-     */
-    int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz,
-                        const byte* inKey, word32 inKeySz, byte* out)
-    {
-        byte   tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */
-        Hmac   myHmac;
-        int    ret;
-        const  byte* localSalt;  /* either points to user input or tmp */
-        int    hashSz;
-
-        ret = wc_HmacSizeByType(type);
-        if (ret < 0)
-            return ret;
-
-        hashSz = ret;
-        localSalt = salt;
-        if (localSalt == NULL) {
-            XMEMSET(tmp, 0, hashSz);
-            localSalt = tmp;
-            saltSz    = hashSz;
-        }
-
-        ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID);
-        if (ret == 0) {
-            ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz);
-            if (ret == 0)
-                ret = wc_HmacUpdate(&myHmac, inKey, inKeySz);
-            if (ret == 0)
-                ret = wc_HmacFinal(&myHmac,  out);
-            wc_HmacFree(&myHmac);
-        }
-
-        return ret;
-    }
-
-    /* HMAC-KDF-Expand.
-     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
-     *
-     * type     The hash algorithm type.
-     * inKey    The input key.
-     * inKeySz  The size of the input key.
-     * info     The application specific information.
-     * infoSz   The size of the application specific information.
-     * out      The output keying material.
-     * returns 0 on success, otherwise failure.
-     */
-    int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz,
-                       const byte* info, word32 infoSz, byte* out, word32 outSz)
-    {
-        byte   tmp[WC_MAX_DIGEST_SIZE];
-        Hmac   myHmac;
-        int    ret = 0;
-        word32 outIdx = 0;
-        word32 hashSz = wc_HmacSizeByType(type);
-        byte   n = 0x1;
-
-        ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID);
-        if (ret != 0)
-            return ret;
-
-        while (outIdx < outSz) {
-            int    tmpSz = (n == 1) ? 0 : hashSz;
-            word32 left = outSz - outIdx;
-
-            ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz);
-            if (ret != 0)
-                break;
-            ret = wc_HmacUpdate(&myHmac, tmp, tmpSz);
-            if (ret != 0)
-                break;
-            ret = wc_HmacUpdate(&myHmac, info, infoSz);
-            if (ret != 0)
-                break;
-            ret = wc_HmacUpdate(&myHmac, &n, 1);
-            if (ret != 0)
-                break;
-            ret = wc_HmacFinal(&myHmac, tmp);
-            if (ret != 0)
-                break;
-
-            left = min(left, hashSz);
-            XMEMCPY(out+outIdx, tmp, left);
-
-            outIdx += hashSz;
-            n++;
-        }
-
-        wc_HmacFree(&myHmac);
-
-        return ret;
-    }
-
-    /* HMAC-KDF.
-     * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
-     *
-     * type     The hash algorithm type.
-     * inKey    The input keying material.
-     * inKeySz  The size of the input keying material.
-     * salt     The optional salt value.
-     * saltSz   The size of the salt.
-     * info     The application specific information.
-     * infoSz   The size of the application specific information.
-     * out      The output keying material.
-     * returns 0 on success, otherwise failure.
-     */
-    int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
-                       const byte* salt,  word32 saltSz,
-                       const byte* info,  word32 infoSz,
-                       byte* out,         word32 outSz)
-    {
-        byte   prk[WC_MAX_DIGEST_SIZE];
-        int    hashSz = wc_HmacSizeByType(type);
-        int    ret;
-
-        if (hashSz < 0)
-            return BAD_FUNC_ARG;
-
-        ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk);
-        if (ret != 0)
-            return ret;
-
-        return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz);
-    }
-
-#endif /* HAVE_HKDF */
-
-#endif /* HAVE_FIPS */
-#endif /* NO_HMAC */
-
--- a/wolfcrypt/src/idea.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-/* idea.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_IDEA
-
-#include <wolfssl/wolfcrypt/idea.h>
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-/* multiplication of x and y modulo 2^16+1
- * IDEA specify a special case when an entry value is 0 ( x or y)
- * then it must be replaced by 2^16
- */
-static WC_INLINE word16 idea_mult(word16 x, word16 y)
-{
-    long mul, res;
-
-    mul = (long)x * (long)y;
-    if (mul) {
-        res = (mul & IDEA_MASK) - ((word32)mul >> 16);
-        if (res <= 0)
-            res += IDEA_MODULO;
-
-        return (word16) (res & IDEA_MASK);
-    }
-
-    if (!x)
-        return ((IDEA_MODULO - y) & IDEA_MASK);
-
-    /* !y */
-    return ((IDEA_MODULO - x) & IDEA_MASK);
-}
-
-/* compute 1/a modulo 2^16+1 using Extended euclidean algorithm
- * adapted from fp_invmod */
-static WC_INLINE word16 idea_invmod(word16 x)
-{
-    int   u, v, b, d;
-
-    if (x <= 1)
-        return x;
-
-    u = IDEA_MODULO;
-    v = x;
-    d = 1;
-    b = 0;
-
-    do {
-        while (!(u & 1)) {
-            u >>= 1;
-            if (b & 1)
-                b -= IDEA_MODULO;
-            b >>= 1;
-        }
-
-        while (!(v & 1)) {
-            v >>= 1;
-            if (d & 1) {
-                d -= IDEA_MODULO;
-            }
-            d >>= 1;
-        }
-
-        if (u >= v) {
-            u -= v;
-            b -= d;
-        } else {
-            v -= u;
-            d -= b;
-        }
-    } while (u != 0);
-
-    /* d is now the inverse, put positive value if required */
-    while (d < 0)
-        d += IDEA_MODULO;
-
-    /* d must be < IDEA_MODULO */
-    while (d >= (int)IDEA_MODULO)
-        d -= IDEA_MODULO;
-
-    return (word16)(d & IDEA_MASK);
-}
-
-/* generate the 52 16-bits key sub-blocks from the 128 key */
-int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz,
-                  const byte *iv, int dir)
-{
-    word16  idx = 0;
-    word32  t;
-    short   i;
-
-    if (idea == NULL || key == NULL || keySz != IDEA_KEY_SIZE ||
-        (dir != IDEA_ENCRYPTION && dir != IDEA_DECRYPTION))
-        return BAD_FUNC_ARG;
-
-    /* initial key schedule for 0 -> 7 */
-    for (i = 0; i < IDEA_ROUNDS; i++) {
-        idea->skey[i]  = (word16)key[idx++] << 8;
-        idea->skey[i] |= (word16)key[idx++];
-    }
-
-    /* shift phase key schedule for 8 -> 51 */
-    for (i = IDEA_ROUNDS; i < IDEA_SK_NUM; i++) {
-        t  = (word32)idea->skey[((i+1) & 7) ? i-7 : i-15] << 9;
-        t |= (word32)idea->skey[((i+2) & 7) < 2 ? i-14 : i-6] >> 7;
-        idea->skey[i] = (word16)(t & IDEA_MASK);
-    }
-
-    /* compute decryption key from encryption key */
-    if (dir == IDEA_DECRYPTION) {
-        word16  enckey[IDEA_SK_NUM];
-
-        /* put encryption key in tmp buffer */
-        XMEMCPY(enckey, idea->skey, sizeof(idea->skey));
-
-        idx = 0;
-
-        idea->skey[6*IDEA_ROUNDS]   = idea_invmod(enckey[idx++]);
-        idea->skey[6*IDEA_ROUNDS+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-        idea->skey[6*IDEA_ROUNDS+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-        idea->skey[6*IDEA_ROUNDS+3] = idea_invmod(enckey[idx++]);
-
-        for (i = 6*(IDEA_ROUNDS-1); i >= 0; i -= 6) {
-            idea->skey[i+4] = enckey[idx++];
-            idea->skey[i+5] = enckey[idx++];
-
-            idea->skey[i] = idea_invmod(enckey[idx++]);
-            if (i) {
-                idea->skey[i+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-                idea->skey[i+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-            }
-            else {
-                idea->skey[1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-                idea->skey[2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK;
-            }
-
-            idea->skey[i+3] = idea_invmod(enckey[idx++]);
-        }
-
-        /* erase temporary buffer */
-        ForceZero(enckey, sizeof(enckey));
-    }
-
-    /* set the iv */
-    return wc_IdeaSetIV(idea, iv);
-}
-
-/* set the IV in the Idea key structure */
-int wc_IdeaSetIV(Idea *idea, const byte* iv)
-{
-    if (idea == NULL)
-        return BAD_FUNC_ARG;
-
-    if (iv != NULL)
-        XMEMCPY(idea->reg, iv, IDEA_BLOCK_SIZE);
-    else
-        XMEMSET(idea->reg, 0, IDEA_BLOCK_SIZE);
-
-    return 0;
-}
-
-/* encryption/decryption for a block (64 bits)
- */
-int wc_IdeaCipher(Idea *idea, byte* out, const byte* in)
-{
-    word32 t1, t2;
-    word16 i, skey_idx = 0, idx = 0;
-    word16 x[4];
-
-    if (idea == NULL || out == NULL || in == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* put input byte block in word16 */
-    for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) {
-        x[i]  = (word16)in[idx++] << 8;
-        x[i] |= (word16)in[idx++];
-    }
-
-    for (i = 0; i < IDEA_ROUNDS; i++) {
-        x[0] = idea_mult(x[0], idea->skey[skey_idx++]);
-        x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK;
-        x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK;
-        x[3] = idea_mult(x[3], idea->skey[skey_idx++]);
-
-        t2 = x[0] ^ x[2];
-        t2 = idea_mult((word16)t2, idea->skey[skey_idx++]);
-        t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK;
-        t1 = idea_mult((word16)t1, idea->skey[skey_idx++]);
-        t2 = (t1 + t2) & IDEA_MASK;
-
-        x[0] ^= t1;
-        x[3] ^= t2;
-
-        t2 ^= x[1];
-        x[1] = x[2] ^ (word16)t1;
-        x[2] = (word16)t2;
-    }
-
-    x[0] = idea_mult(x[0], idea->skey[skey_idx++]);
-    out[0] = (x[0] >> 8) & 0xFF;
-    out[1] = x[0] & 0xFF;
-
-    x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK;
-    out[2] = (x[2] >> 8) & 0xFF;
-    out[3] = x[2] & 0xFF;
-
-    x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK;
-    out[4] = (x[1] >> 8) & 0xFF;
-    out[5] = x[1] & 0xFF;
-
-    x[3] = idea_mult(x[3], idea->skey[skey_idx++]);
-    out[6] = (x[3] >> 8) & 0xFF;
-    out[7] = x[3] & 0xFF;
-
-    return 0;
-}
-
-int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len)
-{
-    int  blocks;
-    int  ret;
-
-    if (idea == NULL || out == NULL || in == NULL)
-        return BAD_FUNC_ARG;
-
-    blocks = len / IDEA_BLOCK_SIZE;
-    while (blocks--) {
-        xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE);
-        ret = wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg);
-        if (ret != 0) {
-            return ret;
-        }
-
-        XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE);
-
-        out += IDEA_BLOCK_SIZE;
-        in  += IDEA_BLOCK_SIZE;
-    }
-
-    return 0;
-}
-
-int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len)
-{
-    int  blocks;
-    int  ret;
-
-    if (idea == NULL || out == NULL || in == NULL)
-        return BAD_FUNC_ARG;
-
-    blocks = len / IDEA_BLOCK_SIZE;
-    while (blocks--) {
-        XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE);
-        ret = wc_IdeaCipher(idea, out, (byte*)idea->tmp);
-        if (ret != 0) {
-            return ret;
-        }
-
-        xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE);
-        XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE);
-
-        out += IDEA_BLOCK_SIZE;
-        in  += IDEA_BLOCK_SIZE;
-    }
-
-    return 0;
-}
-
-#endif /* HAVE_IDEA */
-
--- a/wolfcrypt/src/integer.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4965 +0,0 @@
-/* integer.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-/*
- * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
- * http://math.libtomcrypt.com
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-/* in case user set USE_FAST_MATH there */
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifndef NO_BIG_INT
-
-#ifndef USE_FAST_MATH
-
-#ifndef WOLFSSL_SP_MATH
-
-#include <wolfssl/wolfcrypt/integer.h>
-
-#if defined(FREESCALE_LTC_TFM)
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-#ifdef WOLFSSL_DEBUG_MATH
-    #include <stdio.h>
-#endif
-
-#ifndef NO_WOLFSSL_SMALL_STACK
-    #ifndef WOLFSSL_SMALL_STACK
-        #define WOLFSSL_SMALL_STACK
-    #endif
-#endif
-
-#ifdef SHOW_GEN
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #else
-        #include <stdio.h>
-    #endif
-#endif
-
-/* reverse an array, used for radix code */
-static void
-bn_reverse (unsigned char *s, int len)
-{
-    int     ix, iy;
-    unsigned char t;
-
-    ix = 0;
-    iy = len - 1;
-    while (ix < iy) {
-        t     = s[ix];
-        s[ix] = s[iy];
-        s[iy] = t;
-        ++ix;
-        --iy;
-    }
-}
-
-/* math settings check */
-word32 CheckRunTimeSettings(void)
-{
-    return CTC_SETTINGS;
-}
-
-
-/* handle up to 6 inits */
-int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
-                  mp_int* f)
-{
-    int res = MP_OKAY;
-
-    if (a) XMEMSET(a, 0, sizeof(mp_int));
-    if (b) XMEMSET(b, 0, sizeof(mp_int));
-    if (c) XMEMSET(c, 0, sizeof(mp_int));
-    if (d) XMEMSET(d, 0, sizeof(mp_int));
-    if (e) XMEMSET(e, 0, sizeof(mp_int));
-    if (f) XMEMSET(f, 0, sizeof(mp_int));
-
-    if (a && ((res = mp_init(a)) != MP_OKAY))
-        return res;
-
-    if (b && ((res = mp_init(b)) != MP_OKAY)) {
-        mp_clear(a);
-        return res;
-    }
-
-    if (c && ((res = mp_init(c)) != MP_OKAY)) {
-        mp_clear(a); mp_clear(b);
-        return res;
-    }
-
-    if (d && ((res = mp_init(d)) != MP_OKAY)) {
-        mp_clear(a); mp_clear(b); mp_clear(c);
-        return res;
-    }
-
-    if (e && ((res = mp_init(e)) != MP_OKAY)) {
-        mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d);
-        return res;
-    }
-
-    if (f && ((res = mp_init(f)) != MP_OKAY)) {
-        mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d); mp_clear(e);
-        return res;
-    }
-
-    return res;
-}
-
-
-/* init a new mp_int */
-int mp_init (mp_int * a)
-{
-  /* Safeguard against passing in a null pointer */
-  if (a == NULL)
-    return MP_VAL;
-
-  /* defer allocation until mp_grow */
-  a->dp = NULL;
-
-  /* set the used to zero, allocated digits to the default precision
-   * and sign to positive */
-  a->used  = 0;
-  a->alloc = 0;
-  a->sign  = MP_ZPOS;
-#ifdef HAVE_WOLF_BIGINT
-  wc_bigint_init(&a->raw);
-#endif
-
-  return MP_OKAY;
-}
-
-
-/* clear one (frees)  */
-void mp_clear (mp_int * a)
-{
-  int i;
-
-  if (a == NULL)
-      return;
-
-  /* only do anything if a hasn't been freed previously */
-  if (a->dp != NULL) {
-    /* first zero the digits */
-    for (i = 0; i < a->used; i++) {
-        a->dp[i] = 0;
-    }
-
-    /* free ram */
-    mp_free(a);
-
-    /* reset members to make debugging easier */
-    a->alloc = a->used = 0;
-    a->sign  = MP_ZPOS;
-  }
-}
-
-void mp_free (mp_int * a)
-{
-  /* only do anything if a hasn't been freed previously */
-  if (a->dp != NULL) {
-    /* free ram */
-    XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT);
-    a->dp    = NULL;
-  }
-
-#ifdef HAVE_WOLF_BIGINT
-  wc_bigint_free(&a->raw);
-#endif
-}
-
-void mp_forcezero(mp_int * a)
-{
-    if (a == NULL)
-        return;
-
-    /* only do anything if a hasn't been freed previously */
-    if (a->dp != NULL) {
-      /* force zero the used digits */
-      ForceZero(a->dp, a->used * sizeof(mp_digit));
-#ifdef HAVE_WOLF_BIGINT
-      wc_bigint_zero(&a->raw);
-#endif
-      /* free ram */
-      mp_free(a);
-
-      /* reset members to make debugging easier */
-      a->alloc = a->used = 0;
-      a->sign  = MP_ZPOS;
-    }
-
-    a->sign = MP_ZPOS;
-    a->used = 0;
-}
-
-
-/* get the size for an unsigned equivalent */
-int mp_unsigned_bin_size (mp_int * a)
-{
-  int     size = mp_count_bits (a);
-  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
-}
-
-
-/* returns the number of bits in an int */
-int mp_count_bits (mp_int * a)
-{
-  int     r;
-  mp_digit q;
-
-  /* shortcut */
-  if (a->used == 0) {
-    return 0;
-  }
-
-  /* get number of digits and add that */
-  r = (a->used - 1) * DIGIT_BIT;
-
-  /* take the last digit and count the bits in it */
-  q = a->dp[a->used - 1];
-  while (q > ((mp_digit) 0)) {
-    ++r;
-    q >>= ((mp_digit) 1);
-  }
-  return r;
-}
-
-
-int mp_leading_bit (mp_int * a)
-{
-    int bit = 0;
-    mp_int t;
-
-    if (mp_init_copy(&t, a) != MP_OKAY)
-        return 0;
-
-    while (mp_iszero(&t) == MP_NO) {
-#ifndef MP_8BIT
-        bit = (t.dp[0] & 0x80) != 0;
-#else
-        bit = (t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80 != 0;
-#endif
-        if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY)
-            break;
-    }
-    mp_clear(&t);
-    return bit;
-}
-
-int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b)
-{
-  int res = 0;
-  while (mp_iszero(t) == MP_NO) {
-#ifndef MP_8BIT
-      b[x++] = (unsigned char) (t->dp[0] & 255);
-#else
-      b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7));
-#endif
-    if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) {
-      return res;
-    }
-    res = x;
-  }
-  return res;
-}
-
-/* store in unsigned [big endian] format */
-int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
-{
-  int     x, res;
-  mp_int  t;
-
-  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
-    return res;
-  }
-
-  x = mp_to_unsigned_bin_at_pos(0, &t, b);
-  if (x < 0) {
-    mp_clear(&t);
-    return x;
-  }
-
-  bn_reverse (b, x);
-  mp_clear (&t);
-  return res;
-}
-
-
-/* creates "a" then copies b into it */
-int mp_init_copy (mp_int * a, mp_int * b)
-{
-  int     res;
-
-  if ((res = mp_init_size (a, b->used)) != MP_OKAY) {
-    return res;
-  }
-
-  if((res = mp_copy (b, a)) != MP_OKAY) {
-    mp_clear(a);
-  }
-
-  return res;
-}
-
-
-/* copy, b = a */
-int mp_copy (mp_int * a, mp_int * b)
-{
-  int     res, n;
-
-  /* Safeguard against passing in a null pointer */
-  if (a == NULL || b == NULL)
-    return MP_VAL;
-
-  /* if dst == src do nothing */
-  if (a == b) {
-    return MP_OKAY;
-  }
-
-  /* grow dest */
-  if (b->alloc < a->used || b->alloc == 0) {
-     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
-        return res;
-     }
-  }
-
-  /* zero b and copy the parameters over */
-  {
-    mp_digit *tmpa, *tmpb;
-
-    /* pointer aliases */
-
-    /* source */
-    tmpa = a->dp;
-
-    /* destination */
-    tmpb = b->dp;
-
-    /* copy all the digits */
-    for (n = 0; n < a->used; n++) {
-      *tmpb++ = *tmpa++;
-    }
-
-    /* clear high digits */
-    for (; n < b->used && b->dp; n++) {
-      *tmpb++ = 0;
-    }
-  }
-
-  /* copy used count and sign */
-  b->used = a->used;
-  b->sign = a->sign;
-  return MP_OKAY;
-}
-
-
-/* grow as required */
-int mp_grow (mp_int * a, int size)
-{
-  int     i;
-  mp_digit *tmp;
-
-  /* if the alloc size is smaller alloc more ram */
-  if (a->alloc < size || size == 0) {
-    /* ensure there are always at least MP_PREC digits extra on top */
-    size += (MP_PREC * 2) - (size % MP_PREC);
-
-    /* reallocate the array a->dp
-     *
-     * We store the return in a temporary variable
-     * in case the operation failed we don't want
-     * to overwrite the dp member of a.
-     */
-    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL,
-                                                           DYNAMIC_TYPE_BIGINT);
-    if (tmp == NULL) {
-      /* reallocation failed but "a" is still valid [can be freed] */
-      return MP_MEM;
-    }
-
-    /* reallocation succeeded so set a->dp */
-    a->dp = tmp;
-
-    /* zero excess digits */
-    i        = a->alloc;
-    a->alloc = size;
-    for (; i < a->alloc; i++) {
-      a->dp[i] = 0;
-    }
-  }
-  return MP_OKAY;
-}
-
-
-/* shift right by a certain bit count (store quotient in c, optional
-   remainder in d) */
-int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
-{
-  int     D, res;
-  mp_int  t;
-
-
-  /* if the shift count is <= 0 then we do no work */
-  if (b <= 0) {
-    res = mp_copy (a, c);
-    if (d != NULL) {
-      mp_zero (d);
-    }
-    return res;
-  }
-
-  if ((res = mp_init (&t)) != MP_OKAY) {
-    return res;
-  }
-
-  /* get the remainder */
-  if (d != NULL) {
-    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
-      mp_clear (&t);
-      return res;
-    }
-  }
-
-  /* copy */
-  if ((res = mp_copy (a, c)) != MP_OKAY) {
-    mp_clear (&t);
-    return res;
-  }
-
-  /* shift by as many digits in the bit count */
-  if (b >= (int)DIGIT_BIT) {
-    mp_rshd (c, b / DIGIT_BIT);
-  }
-
-  /* shift any bit count < DIGIT_BIT */
-  D = (b % DIGIT_BIT);
-  if (D != 0) {
-    mp_rshb(c, D);
-  }
-  mp_clamp (c);
-  if (d != NULL) {
-    mp_exch (&t, d);
-  }
-  mp_clear (&t);
-  return MP_OKAY;
-}
-
-
-/* set to zero */
-void mp_zero (mp_int * a)
-{
-  int       n;
-  mp_digit *tmp;
-
-  if (a == NULL)
-      return;
-
-  a->sign = MP_ZPOS;
-  a->used = 0;
-
-  tmp = a->dp;
-  for (n = 0; n < a->alloc; n++) {
-     *tmp++ = 0;
-  }
-}
-
-
-/* trim unused digits
- *
- * This is used to ensure that leading zero digits are
- * trimmed and the leading "used" digit will be non-zero
- * Typically very fast.  Also fixes the sign if there
- * are no more leading digits
- */
-void mp_clamp (mp_int * a)
-{
-  /* decrease used while the most significant digit is
-   * zero.
-   */
-  while (a->used > 0 && a->dp[a->used - 1] == 0) {
-    --(a->used);
-  }
-
-  /* reset the sign flag if used == 0 */
-  if (a->used == 0) {
-    a->sign = MP_ZPOS;
-  }
-}
-
-
-/* swap the elements of two integers, for cases where you can't simply swap the
- * mp_int pointers around
- */
-void mp_exch (mp_int * a, mp_int * b)
-{
-  mp_int  t;
-
-  t  = *a;
-  *a = *b;
-  *b = t;
-}
-
-
-/* shift right a certain number of bits */
-void mp_rshb (mp_int *c, int x)
-{
-    mp_digit *tmpc, mask, shift;
-    mp_digit r, rr;
-    mp_digit D = x;
-
-    /* mask */
-    mask = (((mp_digit)1) << D) - 1;
-
-    /* shift for lsb */
-    shift = DIGIT_BIT - D;
-
-    /* alias */
-    tmpc = c->dp + (c->used - 1);
-
-    /* carry */
-    r = 0;
-    for (x = c->used - 1; x >= 0; x--) {
-      /* get the lower  bits of this word in a temp */
-      rr = *tmpc & mask;
-
-      /* shift the current word and mix in the carry bits from previous word */
-      *tmpc = (*tmpc >> D) | (r << shift);
-      --tmpc;
-
-      /* set the carry to the carry bits of the current word found above */
-      r = rr;
-    }
-    mp_clamp(c);
-}
-
-
-/* shift right a certain amount of digits */
-void mp_rshd (mp_int * a, int b)
-{
-  int     x;
-
-  /* if b <= 0 then ignore it */
-  if (b <= 0) {
-    return;
-  }
-
-  /* if b > used then simply zero it and return */
-  if (a->used <= b) {
-    mp_zero (a);
-    return;
-  }
-
-  {
-    mp_digit *bottom, *top;
-
-    /* shift the digits down */
-
-    /* bottom */
-    bottom = a->dp;
-
-    /* top [offset into digits] */
-    top = a->dp + b;
-
-    /* this is implemented as a sliding window where
-     * the window is b-digits long and digits from
-     * the top of the window are copied to the bottom
-     *
-     * e.g.
-
-     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
-                 /\                   |      ---->
-                  \-------------------/      ---->
-     */
-    for (x = 0; x < (a->used - b); x++) {
-      *bottom++ = *top++;
-    }
-
-    /* zero the top digits */
-    for (; x < a->used; x++) {
-      *bottom++ = 0;
-    }
-  }
-
-  /* remove excess digits */
-  a->used -= b;
-}
-
-
-/* calc a value mod 2**b */
-int mp_mod_2d (mp_int * a, int b, mp_int * c)
-{
-  int     x, res;
-
-  /* if b is <= 0 then zero the int */
-  if (b <= 0) {
-    mp_zero (c);
-    return MP_OKAY;
-  }
-
-  /* if the modulus is larger than the value than return */
-  if (b >= (int) (a->used * DIGIT_BIT)) {
-    res = mp_copy (a, c);
-    return res;
-  }
-
-  /* copy */
-  if ((res = mp_copy (a, c)) != MP_OKAY) {
-    return res;
-  }
-
-  /* zero digits above the last digit of the modulus */
-  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
-    c->dp[x] = 0;
-  }
-  /* clear the digit that is not completely outside/inside the modulus */
-  c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) <<
-              (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
-  mp_clamp (c);
-  return MP_OKAY;
-}
-
-
-/* reads a unsigned char array, assumes the msb is stored first [big endian] */
-int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
-{
-  int     res;
-
-  /* make sure there are at least two digits */
-  if (a->alloc < 2) {
-     if ((res = mp_grow(a, 2)) != MP_OKAY) {
-        return res;
-     }
-  }
-
-  /* zero the int */
-  mp_zero (a);
-
-  /* read the bytes in */
-  while (c-- > 0) {
-    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
-      return res;
-    }
-
-#ifndef MP_8BIT
-      a->dp[0] |= *b++;
-      a->used += 1;
-#else
-      a->dp[0] = (*b & MP_MASK);
-      a->dp[1] |= ((*b++ >> 7U) & 1);
-      a->used += 2;
-#endif
-  }
-  mp_clamp (a);
-  return MP_OKAY;
-}
-
-
-/* shift left by a certain bit count */
-int mp_mul_2d (mp_int * a, int b, mp_int * c)
-{
-  mp_digit d;
-  int      res;
-
-  /* copy */
-  if (a != c) {
-     if ((res = mp_copy (a, c)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
-     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  /* shift by as many digits in the bit count */
-  if (b >= (int)DIGIT_BIT) {
-    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* shift any bit count < DIGIT_BIT */
-  d = (mp_digit) (b % DIGIT_BIT);
-  if (d != 0) {
-    mp_digit *tmpc, shift, mask, r, rr;
-    int x;
-
-    /* bitmask for carries */
-    mask = (((mp_digit)1) << d) - 1;
-
-    /* shift for msbs */
-    shift = DIGIT_BIT - d;
-
-    /* alias */
-    tmpc = c->dp;
-
-    /* carry */
-    r    = 0;
-    for (x = 0; x < c->used; x++) {
-      /* get the higher bits of the current word */
-      rr = (*tmpc >> shift) & mask;
-
-      /* shift the current word and OR in the carry */
-      *tmpc = (mp_digit)(((*tmpc << d) | r) & MP_MASK);
-      ++tmpc;
-
-      /* set the carry to the carry bits of the current word */
-      r = rr;
-    }
-
-    /* set final carry */
-    if (r != 0) {
-       c->dp[(c->used)++] = r;
-    }
-  }
-  mp_clamp (c);
-  return MP_OKAY;
-}
-
-
-/* shift left a certain amount of digits */
-int mp_lshd (mp_int * a, int b)
-{
-  int     x, res;
-
-  /* if its less than zero return */
-  if (b <= 0) {
-    return MP_OKAY;
-  }
-
-  /* grow to fit the new digits */
-  if (a->alloc < a->used + b) {
-     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  {
-    mp_digit *top, *bottom;
-
-    /* increment the used by the shift amount then copy upwards */
-    a->used += b;
-
-    /* top */
-    top = a->dp + a->used - 1;
-
-    /* base */
-    bottom = a->dp + a->used - 1 - b;
-
-    /* much like mp_rshd this is implemented using a sliding window
-     * except the window goes the other way around.  Copying from
-     * the bottom to the top.  see bn_mp_rshd.c for more info.
-     */
-    for (x = a->used - 1; x >= b; x--) {
-      *top-- = *bottom--;
-    }
-
-    /* zero the lower digits */
-    top = a->dp;
-    for (x = 0; x < b; x++) {
-      *top++ = 0;
-    }
-  }
-  return MP_OKAY;
-}
-
-
-/* this is a shell function that calls either the normal or Montgomery
- * exptmod functions.  Originally the call to the montgomery code was
- * embedded in the normal function but that wasted a lot of stack space
- * for nothing (since 99% of the time the Montgomery code would be called)
- */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
-#else
-int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
-#endif
-{
-  int dr;
-
-  /* modulus P must be positive */
-  if (P->sign == MP_NEG) {
-     return MP_VAL;
-  }
-
-  /* if exponent X is negative we have to recurse */
-  if (X->sign == MP_NEG) {
-#ifdef BN_MP_INVMOD_C
-     mp_int tmpG, tmpX;
-     int err;
-
-     /* first compute 1/G mod P */
-     if ((err = mp_init(&tmpG)) != MP_OKAY) {
-        return err;
-     }
-     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
-        mp_clear(&tmpG);
-        return err;
-     }
-
-     /* now get |X| */
-     if ((err = mp_init(&tmpX)) != MP_OKAY) {
-        mp_clear(&tmpG);
-        return err;
-     }
-     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
-        mp_clear(&tmpG);
-        mp_clear(&tmpX);
-        return err;
-     }
-
-     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
-     err = mp_exptmod(&tmpG, &tmpX, P, Y);
-     mp_clear(&tmpG);
-     mp_clear(&tmpX);
-     return err;
-#else
-     /* no invmod */
-     return MP_VAL;
-#endif
-  }
-
-/* modified diminished radix reduction */
-#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && \
-  defined(BN_S_MP_EXPTMOD_C)
-  if (mp_reduce_is_2k_l(P) == MP_YES) {
-     return s_mp_exptmod(G, X, P, Y, 1);
-  }
-#endif
-
-#ifdef BN_MP_DR_IS_MODULUS_C
-  /* is it a DR modulus? */
-  dr = mp_dr_is_modulus(P);
-#else
-  /* default to no */
-  dr = 0;
-#endif
-
-#ifdef BN_MP_REDUCE_IS_2K_C
-  /* if not, is it a unrestricted DR modulus? */
-  if (dr == 0) {
-     dr = mp_reduce_is_2k(P) << 1;
-  }
-#endif
-
-  /* if the modulus is odd or dr != 0 use the montgomery method */
-#ifdef BN_MP_EXPTMOD_FAST_C
-  if (mp_isodd (P) == MP_YES || dr !=  0) {
-    return mp_exptmod_fast (G, X, P, Y, dr);
-  } else {
-#endif
-#ifdef BN_S_MP_EXPTMOD_C
-    /* otherwise use the generic Barrett reduction technique */
-    return s_mp_exptmod (G, X, P, Y, 0);
-#else
-    /* no exptmod for evens */
-    return MP_VAL;
-#endif
-#ifdef BN_MP_EXPTMOD_FAST_C
-  }
-#endif
-}
-
-
-/* b = |a|
- *
- * Simple function copies the input and fixes the sign to positive
- */
-int mp_abs (mp_int * a, mp_int * b)
-{
-  int     res;
-
-  /* copy a to b */
-  if (a != b) {
-     if ((res = mp_copy (a, b)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  /* force the sign of b to positive */
-  b->sign = MP_ZPOS;
-
-  return MP_OKAY;
-}
-
-
-/* hac 14.61, pp608 */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c)
-#else
-int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  /* b cannot be negative */
-  if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) {
-    return MP_VAL;
-  }
-
-#ifdef BN_FAST_MP_INVMOD_C
-  /* if the modulus is odd we can use a faster routine instead */
-  if ((mp_isodd(b) == MP_YES) && (mp_cmp_d(b, 1) != MP_EQ)) {
-    return fast_mp_invmod (a, b, c);
-  }
-#endif
-
-#ifdef BN_MP_INVMOD_SLOW_C
-  return mp_invmod_slow(a, b, c);
-#else
-  return MP_VAL;
-#endif
-}
-
-
-/* computes the modular inverse via binary extended euclidean algorithm,
- * that is c = 1/a mod b
- *
- * Based on slow invmod except this is optimized for the case where b is
- * odd as per HAC Note 14.64 on pp. 610
- */
-int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
-{
-  mp_int  x, y, u, v, B, D;
-  int     res, neg, loop_check = 0;
-
-  /* 2. [modified] b must be odd   */
-  if (mp_iseven (b) == MP_YES) {
-    return MP_VAL;
-  }
-
-  /* init all our temps */
-  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D)) != MP_OKAY) {
-     return res;
-  }
-
-  /* x == modulus, y == value to invert */
-  if ((res = mp_copy (b, &x)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-
-  /* we need y = |a| */
-  if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-
-  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
-  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-  if ((res = mp_set (&D, 1)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-
-top:
-  /* 4.  while u is even do */
-  while (mp_iseven (&u) == MP_YES) {
-    /* 4.1 u = u/2 */
-    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    /* 4.2 if B is odd then */
-    if (mp_isodd (&B) == MP_YES) {
-      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
-        goto LBL_ERR;
-      }
-    }
-    /* B = B/2 */
-    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* 5.  while v is even do */
-  while (mp_iseven (&v) == MP_YES) {
-    /* 5.1 v = v/2 */
-    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    /* 5.2 if D is odd then */
-    if (mp_isodd (&D) == MP_YES) {
-      /* D = (D-x)/2 */
-      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
-        goto LBL_ERR;
-      }
-    }
-    /* D = D/2 */
-    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* 6.  if u >= v then */
-  if (mp_cmp (&u, &v) != MP_LT) {
-    /* u = u - v, B = B - D */
-    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  } else {
-    /* v - v - u, D = D - B */
-    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* if not zero goto step 4 */
-  if (mp_iszero (&u) == MP_NO) {
-    if (++loop_check > MAX_INVMOD_SZ) {
-        res = MP_VAL;
-        goto LBL_ERR;
-    }
-    goto top;
-  }
-
-  /* now a = C, b = D, gcd == g*v */
-
-  /* if v != 1 then there is no inverse */
-  if (mp_cmp_d (&v, 1) != MP_EQ) {
-    res = MP_VAL;
-    goto LBL_ERR;
-  }
-
-  /* b is now the inverse */
-  neg = a->sign;
-  while (D.sign == MP_NEG) {
-    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-  /* too big */
-  while (mp_cmp_mag(&D, b) != MP_LT) {
-      if ((res = mp_sub(&D, b, &D)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-  }
-  mp_exch (&D, c);
-  c->sign = neg;
-  res = MP_OKAY;
-
-LBL_ERR:mp_clear(&x);
-        mp_clear(&y);
-        mp_clear(&u);
-        mp_clear(&v);
-        mp_clear(&B);
-        mp_clear(&D);
-  return res;
-}
-
-
-/* hac 14.61, pp608 */
-int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
-{
-  mp_int  x, y, u, v, A, B, C, D;
-  int     res;
-
-  /* b cannot be negative */
-  if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) {
-    return MP_VAL;
-  }
-
-  /* init temps */
-  if ((res = mp_init_multi(&x, &y, &u, &v,
-                           &A, &B)) != MP_OKAY) {
-     return res;
-  }
-
-  /* init rest of tmps temps */
-  if ((res = mp_init_multi(&C, &D, 0, 0, 0, 0)) != MP_OKAY) {
-     mp_clear(&x);
-     mp_clear(&y);
-     mp_clear(&u);
-     mp_clear(&v);
-     mp_clear(&A);
-     mp_clear(&B);
-     return res;
-  }
-
-  /* x = a, y = b */
-  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
-      goto LBL_ERR;
-  }
-  if ((res = mp_copy (b, &y)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-
-  /* 2. [modified] if x,y are both even then return an error! */
-  if (mp_iseven (&x) == MP_YES && mp_iseven (&y) == MP_YES) {
-    res = MP_VAL;
-    goto LBL_ERR;
-  }
-
-  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
-  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-  if ((res = mp_set (&A, 1)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-  if ((res = mp_set (&D, 1)) != MP_OKAY) {
-    goto LBL_ERR;
-  }
-
-top:
-  /* 4.  while u is even do */
-  while (mp_iseven (&u) == MP_YES) {
-    /* 4.1 u = u/2 */
-    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    /* 4.2 if A or B is odd then */
-    if (mp_isodd (&A) == MP_YES || mp_isodd (&B) == MP_YES) {
-      /* A = (A+y)/2, B = (B-x)/2 */
-      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-    }
-    /* A = A/2, B = B/2 */
-    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* 5.  while v is even do */
-  while (mp_iseven (&v) == MP_YES) {
-    /* 5.1 v = v/2 */
-    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    /* 5.2 if C or D is odd then */
-    if (mp_isodd (&C) == MP_YES || mp_isodd (&D) == MP_YES) {
-      /* C = (C+y)/2, D = (D-x)/2 */
-      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-    }
-    /* C = C/2, D = D/2 */
-    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* 6.  if u >= v then */
-  if (mp_cmp (&u, &v) != MP_LT) {
-    /* u = u - v, A = A - C, B = B - D */
-    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  } else {
-    /* v - v - u, C = C - A, D = D - B */
-    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-
-    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
-      goto LBL_ERR;
-    }
-  }
-
-  /* if not zero goto step 4 */
-  if (mp_iszero (&u) == MP_NO)
-    goto top;
-
-  /* now a = C, b = D, gcd == g*v */
-
-  /* if v != 1 then there is no inverse */
-  if (mp_cmp_d (&v, 1) != MP_EQ) {
-    res = MP_VAL;
-    goto LBL_ERR;
-  }
-
-  /* if its too low */
-  while (mp_cmp_d(&C, 0) == MP_LT) {
-      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-  }
-
-  /* too big */
-  while (mp_cmp_mag(&C, b) != MP_LT) {
-      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
-         goto LBL_ERR;
-      }
-  }
-
-  /* C is now the inverse */
-  mp_exch (&C, c);
-  res = MP_OKAY;
-LBL_ERR:mp_clear(&x);
-        mp_clear(&y);
-        mp_clear(&u);
-        mp_clear(&v);
-        mp_clear(&A);
-        mp_clear(&B);
-        mp_clear(&C);
-        mp_clear(&D);
-  return res;
-}
-
-
-/* compare magnitude of two ints (unsigned) */
-int mp_cmp_mag (mp_int * a, mp_int * b)
-{
-  int     n;
-  mp_digit *tmpa, *tmpb;
-
-  /* compare based on # of non-zero digits */
-  if (a->used > b->used) {
-    return MP_GT;
-  }
-
-  if (a->used < b->used) {
-    return MP_LT;
-  }
-
-  /* alias for a */
-  tmpa = a->dp + (a->used - 1);
-
-  /* alias for b */
-  tmpb = b->dp + (a->used - 1);
-
-  /* compare based on digits  */
-  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
-    if (*tmpa > *tmpb) {
-      return MP_GT;
-    }
-
-    if (*tmpa < *tmpb) {
-      return MP_LT;
-    }
-  }
-  return MP_EQ;
-}
-
-
-/* compare two ints (signed)*/
-int mp_cmp (mp_int * a, mp_int * b)
-{
-  /* compare based on sign */
-  if (a->sign != b->sign) {
-     if (a->sign == MP_NEG) {
-        return MP_LT;
-     } else {
-        return MP_GT;
-     }
-  }
-
-  /* compare digits */
-  if (a->sign == MP_NEG) {
-     /* if negative compare opposite direction */
-     return mp_cmp_mag(b, a);
-  } else {
-     return mp_cmp_mag(a, b);
-  }
-}
-
-
-/* compare a digit */
-int mp_cmp_d(mp_int * a, mp_digit b)
-{
-  /* special case for zero*/
-  if (a->used == 0 && b == 0)
-    return MP_EQ;
-
-  /* compare based on sign */
-  if ((b && a->used == 0) || a->sign == MP_NEG) {
-    return MP_LT;
-  }
-
-  /* compare based on magnitude */
-  if (a->used > 1) {
-    return MP_GT;
-  }
-
-  /* compare the only digit of a to b */
-  if (a->dp[0] > b) {
-    return MP_GT;
-  } else if (a->dp[0] < b) {
-    return MP_LT;
-  } else {
-    return MP_EQ;
-  }
-}
-
-
-/* set to a digit */
-int mp_set (mp_int * a, mp_digit b)
-{
-  int res;
-  mp_zero (a);
-  res = mp_grow (a, 1);
-  if (res == MP_OKAY) {
-    a->dp[0] = (mp_digit)(b & MP_MASK);
-    a->used  = (a->dp[0] != 0) ? 1 : 0;
-  }
-  return res;
-}
-
-/* chek if a bit is set */
-int mp_is_bit_set (mp_int *a, mp_digit b)
-{
-    if ((mp_digit)a->used < b/DIGIT_BIT)
-        return 0;
-
-    return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1);
-}
-
-/* c = a mod b, 0 <= c < b */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c)
-#else
-int mp_mod (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  mp_int  t;
-  int     res;
-
-  if ((res = mp_init_size (&t, b->used)) != MP_OKAY) {
-    return res;
-  }
-
-  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
-    mp_clear (&t);
-    return res;
-  }
-
-  if ((mp_iszero(&t) != MP_NO) || (t.sign == b->sign)) {
-    res = MP_OKAY;
-    mp_exch (&t, c);
-  } else {
-    res = mp_add (b, &t, c);
-  }
-
-  mp_clear (&t);
-  return res;
-}
-
-
-/* slower bit-bang division... also smaller */
-int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
-{
-   mp_int ta, tb, tq, q;
-   int    res, n, n2;
-
-  /* is divisor zero ? */
-  if (mp_iszero (b) == MP_YES) {
-    return MP_VAL;
-  }
-
-  /* if a < b then q=0, r = a */
-  if (mp_cmp_mag (a, b) == MP_LT) {
-    if (d != NULL) {
-      res = mp_copy (a, d);
-    } else {
-      res = MP_OKAY;
-    }
-    if (c != NULL) {
-      mp_zero (c);
-    }
-    return res;
-  }
-
-  /* init our temps */
-  if ((res = mp_init_multi(&ta, &tb, &tq, &q, 0, 0)) != MP_OKAY) {
-     return res;
-  }
-
-  if ((res = mp_set(&tq, 1)) != MP_OKAY) {
-     return res;
-  }
-  n = mp_count_bits(a) - mp_count_bits(b);
-  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
-      ((res = mp_abs(b, &tb)) != MP_OKAY) ||
-      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
-      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
-      goto LBL_ERR;
-  }
-
-  while (n-- >= 0) {
-     if (mp_cmp(&tb, &ta) != MP_GT) {
-        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
-            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
-           goto LBL_ERR;
-        }
-     }
-     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
-         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
-           goto LBL_ERR;
-     }
-  }
-
-  /* now q == quotient and ta == remainder */
-  n  = a->sign;
-  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
-  if (c != NULL) {
-     mp_exch(c, &q);
-     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
-  }
-  if (d != NULL) {
-     mp_exch(d, &ta);
-     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
-  }
-LBL_ERR:
-   mp_clear(&ta);
-   mp_clear(&tb);
-   mp_clear(&tq);
-   mp_clear(&q);
-   return res;
-}
-
-
-/* b = a/2 */
-int mp_div_2(mp_int * a, mp_int * b)
-{
-  int     x, res, oldused;
-
-  /* copy */
-  if (b->alloc < a->used) {
-    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  oldused = b->used;
-  b->used = a->used;
-  {
-    mp_digit r, rr, *tmpa, *tmpb;
-
-    /* source alias */
-    tmpa = a->dp + b->used - 1;
-
-    /* dest alias */
-    tmpb = b->dp + b->used - 1;
-
-    /* carry */
-    r = 0;
-    for (x = b->used - 1; x >= 0; x--) {
-      /* get the carry for the next iteration */
-      rr = *tmpa & 1;
-
-      /* shift the current digit, add in carry and store */
-      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
-
-      /* forward carry to next iteration */
-      r = rr;
-    }
-
-    /* zero excess digits */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-  mp_clamp (b);
-  return MP_OKAY;
-}
-
-
-/* high level addition (handles signs) */
-int mp_add (mp_int * a, mp_int * b, mp_int * c)
-{
-  int sa, sb, res;
-
-  /* get sign of both inputs */
-  sa = a->sign;
-  sb = b->sign;
-
-  /* handle two cases, not four */
-  if (sa == sb) {
-    /* both positive or both negative */
-    /* add their magnitudes, copy the sign */
-    c->sign = sa;
-    res = s_mp_add (a, b, c);
-  } else {
-    /* one positive, the other negative */
-    /* subtract the one with the greater magnitude from */
-    /* the one of the lesser magnitude.  The result gets */
-    /* the sign of the one with the greater magnitude. */
-    if (mp_cmp_mag (a, b) == MP_LT) {
-      c->sign = sb;
-      res = s_mp_sub (b, a, c);
-    } else {
-      c->sign = sa;
-      res = s_mp_sub (a, b, c);
-    }
-  }
-  return res;
-}
-
-
-/* low level addition, based on HAC pp.594, Algorithm 14.7 */
-int s_mp_add (mp_int * a, mp_int * b, mp_int * c)
-{
-  mp_int *x;
-  int     olduse, res, min_ab, max_ab;
-
-  /* find sizes, we let |a| <= |b| which means we have to sort
-   * them.  "x" will point to the input with the most digits
-   */
-  if (a->used > b->used) {
-    min_ab = b->used;
-    max_ab = a->used;
-    x = a;
-  } else {
-    min_ab = a->used;
-    max_ab = b->used;
-    x = b;
-  }
-
-  /* init result */
-  if (c->alloc < max_ab + 1) {
-    if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* get old used digit count and set new one */
-  olduse = c->used;
-  c->used = max_ab + 1;
-
-  {
-    mp_digit u, *tmpa, *tmpb, *tmpc;
-    int i;
-
-    /* alias for digit pointers */
-
-    /* first input */
-    tmpa = a->dp;
-
-    /* second input */
-    tmpb = b->dp;
-
-    /* destination */
-    tmpc = c->dp;
-
-    /* zero the carry */
-    u = 0;
-    for (i = 0; i < min_ab; i++) {
-      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
-      *tmpc = *tmpa++ + *tmpb++ + u;
-
-      /* U = carry bit of T[i] */
-      u = *tmpc >> ((mp_digit)DIGIT_BIT);
-
-      /* take away carry bit from T[i] */
-      *tmpc++ &= MP_MASK;
-    }
-
-    /* now copy higher words if any, that is in A+B
-     * if A or B has more digits add those in
-     */
-    if (min_ab != max_ab) {
-      for (; i < max_ab; i++) {
-        /* T[i] = X[i] + U */
-        *tmpc = x->dp[i] + u;
-
-        /* U = carry bit of T[i] */
-        u = *tmpc >> ((mp_digit)DIGIT_BIT);
-
-        /* take away carry bit from T[i] */
-        *tmpc++ &= MP_MASK;
-      }
-    }
-
-    /* add carry */
-    *tmpc++ = u;
-
-    /* clear digits above olduse */
-    for (i = c->used; i < olduse; i++) {
-      *tmpc++ = 0;
-    }
-  }
-
-  mp_clamp (c);
-  return MP_OKAY;
-}
-
-
-/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
-int s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
-{
-  int     olduse, res, min_b, max_a;
-
-  /* find sizes */
-  min_b = b->used;
-  max_a = a->used;
-
-  /* init result */
-  if (c->alloc < max_a) {
-    if ((res = mp_grow (c, max_a)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* sanity check on destination */
-  if (c->dp == NULL)
-     return MP_VAL;
-
-  olduse = c->used;
-  c->used = max_a;
-
-  {
-    mp_digit u, *tmpa, *tmpb, *tmpc;
-    int i;
-
-    /* alias for digit pointers */
-    tmpa = a->dp;
-    tmpb = b->dp;
-    tmpc = c->dp;
-
-    /* set carry to zero */
-    u = 0;
-    for (i = 0; i < min_b; i++) {
-      /* T[i] = A[i] - B[i] - U */
-      *tmpc = *tmpa++ - *tmpb++ - u;
-
-      /* U = carry bit of T[i]
-       * Note this saves performing an AND operation since
-       * if a carry does occur it will propagate all the way to the
-       * MSB.  As a result a single shift is enough to get the carry
-       */
-      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
-
-      /* Clear carry from T[i] */
-      *tmpc++ &= MP_MASK;
-    }
-
-    /* now copy higher words if any, e.g. if A has more digits than B  */
-    for (; i < max_a; i++) {
-      /* T[i] = A[i] - U */
-      *tmpc = *tmpa++ - u;
-
-      /* U = carry bit of T[i] */
-      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
-
-      /* Clear carry from T[i] */
-      *tmpc++ &= MP_MASK;
-    }
-
-    /* clear digits above used (since we may not have grown result above) */
-    for (i = c->used; i < olduse; i++) {
-      *tmpc++ = 0;
-    }
-  }
-
-  mp_clamp (c);
-  return MP_OKAY;
-}
-
-
-/* high level subtraction (handles signs) */
-int mp_sub (mp_int * a, mp_int * b, mp_int * c)
-{
-  int     sa, sb, res;
-
-  sa = a->sign;
-  sb = b->sign;
-
-  if (sa != sb) {
-    /* subtract a negative from a positive, OR */
-    /* subtract a positive from a negative. */
-    /* In either case, ADD their magnitudes, */
-    /* and use the sign of the first number. */
-    c->sign = sa;
-    res = s_mp_add (a, b, c);
-  } else {
-    /* subtract a positive from a positive, OR */
-    /* subtract a negative from a negative. */
-    /* First, take the difference between their */
-    /* magnitudes, then... */
-    if (mp_cmp_mag (a, b) != MP_LT) {
-      /* Copy the sign from the first */
-      c->sign = sa;
-      /* The first has a larger or equal magnitude */
-      res = s_mp_sub (a, b, c);
-    } else {
-      /* The result has the *opposite* sign from */
-      /* the first number. */
-      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
-      /* The second has a larger magnitude */
-      res = s_mp_sub (b, a, c);
-    }
-  }
-  return res;
-}
-
-
-/* determines if reduce_2k_l can be used */
-int mp_reduce_is_2k_l(mp_int *a)
-{
-   int ix, iy;
-
-   if (a->used == 0) {
-      return MP_NO;
-   } else if (a->used == 1) {
-      return MP_YES;
-   } else if (a->used > 1) {
-      /* if more than half of the digits are -1 we're sold */
-      for (iy = ix = 0; ix < a->used; ix++) {
-          if (a->dp[ix] == MP_MASK) {
-              ++iy;
-          }
-      }
-      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
-
-   }
-   return MP_NO;
-}
-
-
-/* determines if mp_reduce_2k can be used */
-int mp_reduce_is_2k(mp_int *a)
-{
-   int ix, iy, iw;
-   mp_digit iz;
-
-   if (a->used == 0) {
-      return MP_NO;
-   } else if (a->used == 1) {
-      return MP_YES;
-   } else if (a->used > 1) {
-      iy = mp_count_bits(a);
-      iz = 1;
-      iw = 1;
-
-      /* Test every bit from the second digit up, must be 1 */
-      for (ix = DIGIT_BIT; ix < iy; ix++) {
-          if ((a->dp[iw] & iz) == 0) {
-             return MP_NO;
-          }
-          iz <<= 1;
-          if (iz > (mp_digit)MP_MASK) {
-             ++iw;
-             iz = 1;
-          }
-      }
-   }
-   return MP_YES;
-}
-
-
-/* determines if a number is a valid DR modulus */
-int mp_dr_is_modulus(mp_int *a)
-{
-   int ix;
-
-   /* must be at least two digits */
-   if (a->used < 2) {
-      return 0;
-   }
-
-   /* must be of the form b**k - a [a <= b] so all
-    * but the first digit must be equal to -1 (mod b).
-    */
-   for (ix = 1; ix < a->used; ix++) {
-       if (a->dp[ix] != MP_MASK) {
-          return 0;
-       }
-   }
-   return 1;
-}
-
-
-/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
- *
- * Uses a left-to-right k-ary sliding window to compute the modular
- * exponentiation.
- * The value of k changes based on the size of the exponent.
- *
- * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
- */
-
-#ifdef MP_LOW_MEM
-   #define TAB_SIZE 32
-#else
-   #define TAB_SIZE 256
-#endif
-
-int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y,
-                     int redmode)
-{
-  mp_int res;
-  mp_digit buf, mp;
-  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
-#ifdef WOLFSSL_SMALL_STACK
-  mp_int* M = NULL;
-#else
-  mp_int M[TAB_SIZE];
-#endif
-  /* use a pointer to the reduction algorithm.  This allows us to use
-   * one of many reduction algorithms without modding the guts of
-   * the code with if statements everywhere.
-   */
-  int     (*redux)(mp_int*,mp_int*,mp_digit);
-
-#ifdef WOLFSSL_SMALL_STACK
-  M = (mp_int*) XMALLOC(sizeof(mp_int) * TAB_SIZE, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-  if (M == NULL)
-    return MP_MEM;
-#endif
-
-  /* find window size */
-  x = mp_count_bits (X);
-  if (x <= 7) {
-    winsize = 2;
-  } else if (x <= 36) {
-    winsize = 3;
-  } else if (x <= 140) {
-    winsize = 4;
-  } else if (x <= 450) {
-    winsize = 5;
-  } else if (x <= 1303) {
-    winsize = 6;
-  } else if (x <= 3529) {
-    winsize = 7;
-  } else {
-    winsize = 8;
-  }
-
-#ifdef MP_LOW_MEM
-  if (winsize > 5) {
-     winsize = 5;
-  }
-#endif
-
-  /* init M array */
-  /* init first cell */
-  if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) {
-#ifdef WOLFSSL_SMALL_STACK
-     XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-     return err;
-  }
-
-  /* now init the second half of the array */
-  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
-    if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) {
-      for (y = 1<<(winsize-1); y < x; y++) {
-        mp_clear (&M[y]);
-      }
-      mp_clear(&M[1]);
-
-#ifdef WOLFSSL_SMALL_STACK
-      XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-      return err;
-    }
-  }
-
-  /* determine and setup reduction code */
-  if (redmode == 0) {
-#ifdef BN_MP_MONTGOMERY_SETUP_C
-     /* now setup montgomery  */
-     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
-        goto LBL_M;
-     }
-#else
-     err = MP_VAL;
-     goto LBL_M;
-#endif
-
-     /* automatically pick the comba one if available (saves quite a few
-        calls/ifs) */
-#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
-     if (((P->used * 2 + 1) < MP_WARRAY) &&
-          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
-        redux = fast_mp_montgomery_reduce;
-     } else
-#endif
-     {
-#ifdef BN_MP_MONTGOMERY_REDUCE_C
-        /* use slower baseline Montgomery method */
-        redux = mp_montgomery_reduce;
-#else
-        err = MP_VAL;
-        goto LBL_M;
-#endif
-     }
-  } else if (redmode == 1) {
-#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
-     /* setup DR reduction for moduli of the form B**k - b */
-     mp_dr_setup(P, &mp);
-     redux = mp_dr_reduce;
-#else
-     err = MP_VAL;
-     goto LBL_M;
-#endif
-  } else {
-#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
-     /* setup DR reduction for moduli of the form 2**k - b */
-     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
-        goto LBL_M;
-     }
-     redux = mp_reduce_2k;
-#else
-     err = MP_VAL;
-     goto LBL_M;
-#endif
-  }
-
-  /* setup result */
-  if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) {
-    goto LBL_M;
-  }
-
-  /* create M table
-   *
-
-   *
-   * The first half of the table is not computed though accept for M[0] and M[1]
-   */
-
-  if (redmode == 0) {
-#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
-     /* now we need R mod m */
-     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
-       goto LBL_RES;
-     }
-
-     /* now set M[1] to G * R mod m */
-     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
-       goto LBL_RES;
-     }
-#else
-     err = MP_VAL;
-     goto LBL_RES;
-#endif
-  } else {
-     if ((err = mp_set(&res, 1)) != MP_OKAY) {
-        goto LBL_RES;
-     }
-     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
-        goto LBL_RES;
-     }
-  }
-
-  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times*/
-  if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
-    goto LBL_RES;
-  }
-
-  for (x = 0; x < (winsize - 1); x++) {
-    if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))],
-                       &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
-      goto LBL_RES;
-    }
-    if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, mp)) != MP_OKAY) {
-      goto LBL_RES;
-    }
-  }
-
-  /* create upper table */
-  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
-    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
-      goto LBL_RES;
-    }
-    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
-      goto LBL_RES;
-    }
-  }
-
-  /* set initial mode and bit cnt */
-  mode   = 0;
-  bitcnt = 1;
-  buf    = 0;
-  digidx = X->used - 1;
-  bitcpy = 0;
-  bitbuf = 0;
-
-  for (;;) {
-    /* grab next digit as required */
-    if (--bitcnt == 0) {
-      /* if digidx == -1 we are out of digits so break */
-      if (digidx == -1) {
-        break;
-      }
-      /* read next digit and reset bitcnt */
-      buf    = X->dp[digidx--];
-      bitcnt = (int)DIGIT_BIT;
-    }
-
-    /* grab the next msb from the exponent */
-    y     = (int)(buf >> (DIGIT_BIT - 1)) & 1;
-    buf <<= (mp_digit)1;
-
-    /* if the bit is zero and mode == 0 then we ignore it
-     * These represent the leading zero bits before the first 1 bit
-     * in the exponent.  Technically this opt is not required but it
-     * does lower the # of trivial squaring/reductions used
-     */
-    if (mode == 0 && y == 0) {
-      continue;
-    }
-
-    /* if the bit is zero and mode == 1 then we square */
-    if (mode == 1 && y == 0) {
-      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, mp)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      continue;
-    }
-
-    /* else we add it to the window */
-    bitbuf |= (y << (winsize - ++bitcpy));
-    mode    = 2;
-
-    if (bitcpy == winsize) {
-      /* ok window is filled so square as required and multiply  */
-      /* square first */
-      for (x = 0; x < winsize; x++) {
-        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-        if ((err = redux (&res, P, mp)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-      }
-
-      /* then multiply */
-      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, mp)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-
-      /* empty window and reset */
-      bitcpy = 0;
-      bitbuf = 0;
-      mode   = 1;
-    }
-  }
-
-  /* if bits remain then square/multiply */
-  if (mode == 2 && bitcpy > 0) {
-    /* square then multiply if the bit is set */
-    for (x = 0; x < bitcpy; x++) {
-      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, mp)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-
-      /* get next bit of the window */
-      bitbuf <<= 1;
-      if ((bitbuf & (1 << winsize)) != 0) {
-        /* then multiply */
-        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-        if ((err = redux (&res, P, mp)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-      }
-    }
-  }
-
-  if (redmode == 0) {
-     /* fixup result if Montgomery reduction is used
-      * recall that any value in a Montgomery system is
-      * actually multiplied by R mod n.  So we have
-      * to reduce one more time to cancel out the factor
-      * of R.
-      */
-     if ((err = redux(&res, P, mp)) != MP_OKAY) {
-       goto LBL_RES;
-     }
-  }
-
-  /* swap res with Y */
-  mp_exch (&res, Y);
-  err = MP_OKAY;
-LBL_RES:mp_clear (&res);
-LBL_M:
-  mp_clear(&M[1]);
-  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
-    mp_clear (&M[x]);
-  }
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-  return err;
-}
-
-
-/* setups the montgomery reduction stuff */
-int mp_montgomery_setup (mp_int * n, mp_digit * rho)
-{
-  mp_digit x, b;
-
-/* fast inversion mod 2**k
- *
- * Based on the fact that
- *
- * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
- *                    =>  2*X*A - X*X*A*A = 1
- *                    =>  2*(1) - (1)     = 1
- */
-  b = n->dp[0];
-
-  if ((b & 1) == 0) {
-    return MP_VAL;
-  }
-
-  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-#if !defined(MP_8BIT)
-  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-#endif
-#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
-  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-#endif
-#ifdef MP_64BIT
-  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-#endif
-
-  /* rho = -1/m mod b */
-  /* TAO, switched mp_word casts to mp_digit to shut up compiler */
-  *rho = (mp_digit)((((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK);
-
-  return MP_OKAY;
-}
-
-
-/* computes xR**-1 == x (mod N) via Montgomery Reduction
- *
- * This is an optimized implementation of montgomery_reduce
- * which uses the comba method to quickly calculate the columns of the
- * reduction.
- *
- * Based on Algorithm 14.32 on pp.601 of HAC.
-*/
-int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
-{
-  int     ix, res, olduse;
-#ifdef WOLFSSL_SMALL_STACK
-  mp_word* W;    /* uses dynamic memory and slower */
-#else
-  mp_word W[MP_WARRAY];
-#endif
-
-  /* get old used count */
-  olduse = x->used;
-
-  /* grow a as required */
-  if (x->alloc < n->used + 1) {
-    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-#ifdef WOLFSSL_SMALL_STACK
-  W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
-  if (W == NULL)
-    return MP_MEM;
-#endif
-
-  /* first we have to get the digits of the input into
-   * an array of double precision words W[...]
-   */
-  {
-    mp_word *_W;
-    mp_digit *tmpx;
-
-    /* alias for the W[] array */
-    _W   = W;
-
-    /* alias for the digits of  x*/
-    tmpx = x->dp;
-
-    /* copy the digits of a into W[0..a->used-1] */
-    for (ix = 0; ix < x->used; ix++) {
-      *_W++ = *tmpx++;
-    }
-
-    /* zero the high words of W[a->used..m->used*2] */
-    for (; ix < n->used * 2 + 1; ix++) {
-      *_W++ = 0;
-    }
-  }
-
-  /* now we proceed to zero successive digits
-   * from the least significant upwards
-   */
-  for (ix = 0; ix < n->used; ix++) {
-    /* mu = ai * m' mod b
-     *
-     * We avoid a double precision multiplication (which isn't required)
-     * by casting the value down to a mp_digit.  Note this requires
-     * that W[ix-1] have  the carry cleared (see after the inner loop)
-     */
-    mp_digit mu;
-    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
-
-    /* a = a + mu * m * b**i
-     *
-     * This is computed in place and on the fly.  The multiplication
-     * by b**i is handled by offseting which columns the results
-     * are added to.
-     *
-     * Note the comba method normally doesn't handle carries in the
-     * inner loop In this case we fix the carry from the previous
-     * column since the Montgomery reduction requires digits of the
-     * result (so far) [see above] to work.  This is
-     * handled by fixing up one carry after the inner loop.  The
-     * carry fixups are done in order so after these loops the
-     * first m->used words of W[] have the carries fixed
-     */
-    {
-      int iy;
-      mp_digit *tmpn;
-      mp_word *_W;
-
-      /* alias for the digits of the modulus */
-      tmpn = n->dp;
-
-      /* Alias for the columns set by an offset of ix */
-      _W = W + ix;
-
-      /* inner loop */
-      for (iy = 0; iy < n->used; iy++) {
-          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
-      }
-    }
-
-    /* now fix carry for next digit, W[ix+1] */
-    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
-  }
-
-  /* now we have to propagate the carries and
-   * shift the words downward [all those least
-   * significant digits we zeroed].
-   */
-  {
-    mp_digit *tmpx;
-    mp_word *_W, *_W1;
-
-    /* nox fix rest of carries */
-
-    /* alias for current word */
-    _W1 = W + ix;
-
-    /* alias for next word, where the carry goes */
-    _W = W + ++ix;
-
-    for (; ix <= n->used * 2 + 1; ix++) {
-      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
-    }
-
-    /* copy out, A = A/b**n
-     *
-     * The result is A/b**n but instead of converting from an
-     * array of mp_word to mp_digit than calling mp_rshd
-     * we just copy them in the right order
-     */
-
-    /* alias for destination word */
-    tmpx = x->dp;
-
-    /* alias for shifted double precision result */
-    _W = W + n->used;
-
-    for (ix = 0; ix < n->used + 1; ix++) {
-      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
-    }
-
-    /* zero olduse digits, if the input a was larger than
-     * m->used+1 we'll have to clear the digits
-     */
-    for (; ix < olduse; ix++) {
-      *tmpx++ = 0;
-    }
-  }
-
-  /* set the max used and clamp */
-  x->used = n->used + 1;
-  mp_clamp (x);
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
-
-  /* if A >= m then A = A - m */
-  if (mp_cmp_mag (x, n) != MP_LT) {
-    return s_mp_sub (x, n, x);
-  }
-  return MP_OKAY;
-}
-
-
-/* computes xR**-1 == x (mod N) via Montgomery Reduction */
-int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
-{
-  int     ix, res, digs;
-  mp_digit mu;
-
-  /* can the fast reduction [comba] method be used?
-   *
-   * Note that unlike in mul you're safely allowed *less*
-   * than the available columns [255 per default] since carries
-   * are fixed up in the inner loop.
-   */
-  digs = n->used * 2 + 1;
-  if ((digs < MP_WARRAY) &&
-      n->used <
-      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
-    return fast_mp_montgomery_reduce (x, n, rho);
-  }
-
-  /* grow the input as required */
-  if (x->alloc < digs) {
-    if ((res = mp_grow (x, digs)) != MP_OKAY) {
-      return res;
-    }
-  }
-  x->used = digs;
-
-  for (ix = 0; ix < n->used; ix++) {
-    /* mu = ai * rho mod b
-     *
-     * The value of rho must be precalculated via
-     * montgomery_setup() such that
-     * it equals -1/n0 mod b this allows the
-     * following inner loop to reduce the
-     * input one digit at a time
-     */
-    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
-
-    /* a = a + mu * m * b**i */
-    {
-      int iy;
-      mp_digit *tmpn, *tmpx, u;
-      mp_word r;
-
-      /* alias for digits of the modulus */
-      tmpn = n->dp;
-
-      /* alias for the digits of x [the input] */
-      tmpx = x->dp + ix;
-
-      /* set the carry to zero */
-      u = 0;
-
-      /* Multiply and add in place */
-      for (iy = 0; iy < n->used; iy++) {
-        /* compute product and sum */
-        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
-                  ((mp_word) u) + ((mp_word) * tmpx);
-
-        /* get carry */
-        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
-
-        /* fix digit */
-        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
-      }
-      /* At this point the ix'th digit of x should be zero */
-
-
-      /* propagate carries upwards as required*/
-      while (u) {
-        *tmpx   += u;
-        u        = *tmpx >> DIGIT_BIT;
-        *tmpx++ &= MP_MASK;
-      }
-    }
-  }
-
-  /* at this point the n.used'th least
-   * significant digits of x are all zero
-   * which means we can shift x to the
-   * right by n.used digits and the
-   * residue is unchanged.
-   */
-
-  /* x = x/b**n.used */
-  mp_clamp(x);
-  mp_rshd (x, n->used);
-
-  /* if x >= n then x = x - n */
-  if (mp_cmp_mag (x, n) != MP_LT) {
-    return s_mp_sub (x, n, x);
-  }
-
-  return MP_OKAY;
-}
-
-
-/* determines the setup value */
-void mp_dr_setup(mp_int *a, mp_digit *d)
-{
-   /* the casts are required if DIGIT_BIT is one less than
-    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
-    */
-   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
-        ((mp_word)a->dp[0]));
-}
-
-
-/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
- *
- * Based on algorithm from the paper
- *
- * "Generating Efficient Primes for Discrete Log Cryptosystems"
- *                 Chae Hoon Lim, Pil Joong Lee,
- *          POSTECH Information Research Laboratories
- *
- * The modulus must be of a special format [see manual]
- *
- * Has been modified to use algorithm 7.10 from the LTM book instead
- *
- * Input x must be in the range 0 <= x <= (n-1)**2
- */
-int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
-{
-  int      err, i, m;
-  mp_word  r;
-  mp_digit mu, *tmpx1, *tmpx2;
-
-  /* m = digits in modulus */
-  m = n->used;
-
-  /* ensure that "x" has at least 2m digits */
-  if (x->alloc < m + m) {
-    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
-      return err;
-    }
-  }
-
-/* top of loop, this is where the code resumes if
- * another reduction pass is required.
- */
-top:
-  /* aliases for digits */
-  /* alias for lower half of x */
-  tmpx1 = x->dp;
-
-  /* alias for upper half of x, or x/B**m */
-  tmpx2 = x->dp + m;
-
-  /* set carry to zero */
-  mu = 0;
-
-  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
-  for (i = 0; i < m; i++) {
-      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
-      *tmpx1++  = (mp_digit)(r & MP_MASK);
-      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
-  }
-
-  /* set final carry */
-  *tmpx1++ = mu;
-
-  /* zero words above m */
-  for (i = m + 1; i < x->used; i++) {
-      *tmpx1++ = 0;
-  }
-
-  /* clamp, sub and return */
-  mp_clamp (x);
-
-  /* if x >= n then subtract and reduce again
-   * Each successive "recursion" makes the input smaller and smaller.
-   */
-  if (mp_cmp_mag (x, n) != MP_LT) {
-    if ((err = s_mp_sub(x, n, x)) != MP_OKAY) {
-        return err;
-    }
-    goto top;
-  }
-  return MP_OKAY;
-}
-
-
-/* reduces a modulo n where n is of the form 2**p - d */
-int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
-{
-   mp_int q;
-   int    p, res;
-
-   if ((res = mp_init(&q)) != MP_OKAY) {
-      return res;
-   }
-
-   p = mp_count_bits(n);
-top:
-   /* q = a/2**p, a = a mod 2**p */
-   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
-      goto ERR;
-   }
-
-   if (d != 1) {
-      /* q = q * d */
-      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
-         goto ERR;
-      }
-   }
-
-   /* a = a + q */
-   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
-      goto ERR;
-   }
-
-   if (mp_cmp_mag(a, n) != MP_LT) {
-      if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {
-         goto ERR;
-      }
-      goto top;
-   }
-
-ERR:
-   mp_clear(&q);
-   return res;
-}
-
-
-/* determines the setup value */
-int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
-{
-   int res, p;
-   mp_int tmp;
-
-   if ((res = mp_init(&tmp)) != MP_OKAY) {
-      return res;
-   }
-
-   p = mp_count_bits(a);
-   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
-      mp_clear(&tmp);
-      return res;
-   }
-
-   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
-      mp_clear(&tmp);
-      return res;
-   }
-
-   *d = tmp.dp[0];
-   mp_clear(&tmp);
-   return MP_OKAY;
-}
-
-
-/* set the b bit of a */
-int mp_set_bit (mp_int * a, int b)
-{
-    int i = b / DIGIT_BIT, res;
-
-    if (a->used < (int)(i + 1)) {
-        /* grow a to accommodate the single bit */
-        if ((res = mp_grow (a, i + 1)) != MP_OKAY) {
-            return res;
-        }
-
-        /* set the used count of where the bit will go */
-        a->used = (int)(i + 1);
-    }
-
-    /* put the single bit in its place */
-    a->dp[i] |= ((mp_digit)1) << (b % DIGIT_BIT);
-
-    return MP_OKAY;
-}
-
-/* computes a = 2**b
- *
- * Simple algorithm which zeros the int, set the required bit
- */
-int mp_2expt (mp_int * a, int b)
-{
-    /* zero a as per default */
-    mp_zero (a);
-
-    return mp_set_bit(a, b);
-}
-
-/* multiply by a digit */
-int mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
-{
-  mp_digit u, *tmpa, *tmpc;
-  mp_word  r;
-  int      ix, res, olduse;
-
-  /* make sure c is big enough to hold a*b */
-  if (c->alloc < a->used + 1) {
-    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* get the original destinations used count */
-  olduse = c->used;
-
-  /* set the sign */
-  c->sign = a->sign;
-
-  /* alias for a->dp [source] */
-  tmpa = a->dp;
-
-  /* alias for c->dp [dest] */
-  tmpc = c->dp;
-
-  /* zero carry */
-  u = 0;
-
-  /* compute columns */
-  for (ix = 0; ix < a->used; ix++) {
-    /* compute product and carry sum for this term */
-    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
-
-    /* mask off higher bits to get a single digit */
-    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
-
-    /* send carry into next iteration */
-    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
-  }
-
-  /* store final carry [if any] and increment ix offset  */
-  *tmpc++ = u;
-  ++ix;
-
-  /* now zero digits above the top */
-  while (ix++ < olduse) {
-     *tmpc++ = 0;
-  }
-
-  /* set used count */
-  c->used = a->used + 1;
-  mp_clamp(c);
-
-  return MP_OKAY;
-}
-
-
-/* d = a * b (mod c) */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
-#else
-int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
-#endif
-{
-  int     res;
-  mp_int  t;
-
-  if ((res = mp_init_size (&t, c->used)) != MP_OKAY) {
-    return res;
-  }
-
-  res = mp_mul (a, b, &t);
-  if (res == MP_OKAY) {
-      res = mp_mod (&t, c, d);
-  }
-
-  mp_clear (&t);
-  return res;
-}
-
-
-/* d = a - b (mod c) */
-int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
-{
-  int     res;
-  mp_int  t;
-
-  if ((res = mp_init (&t)) != MP_OKAY) {
-    return res;
-  }
-
-  res = mp_sub (a, b, &t);
-  if (res == MP_OKAY) {
-      res = mp_mod (&t, c, d);
-  }
-
-  mp_clear (&t);
-
-  return res;
-}
-
-/* d = a + b (mod c) */
-int mp_addmod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
-{
-   int     res;
-   mp_int  t;
-
-   if ((res = mp_init (&t)) != MP_OKAY) {
-     return res;
-   }
-
-   res = mp_add (a, b, &t);
-   if (res == MP_OKAY) {
-       res = mp_mod (&t, c, d);
-   }
-
-   mp_clear (&t);
-
-   return res;
-}
-
-/* computes b = a*a */
-int mp_sqr (mp_int * a, mp_int * b)
-{
-  int     res;
-
-  {
-#ifdef BN_FAST_S_MP_SQR_C
-    /* can we use the fast comba multiplier? */
-    if ((a->used * 2 + 1) < MP_WARRAY &&
-         a->used <
-         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
-      res = fast_s_mp_sqr (a, b);
-    } else
-#endif
-#ifdef BN_S_MP_SQR_C
-      res = s_mp_sqr (a, b);
-#else
-      res = MP_VAL;
-#endif
-  }
-  b->sign = MP_ZPOS;
-  return res;
-}
-
-
-/* high level multiplication (handles sign) */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c)
-#else
-int mp_mul (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  int     res, neg;
-  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
-
-  {
-    /* can we use the fast multiplier?
-     *
-     * The fast multiplier can be used if the output will
-     * have less than MP_WARRAY digits and the number of
-     * digits won't affect carry propagation
-     */
-    int     digs = a->used + b->used + 1;
-
-#ifdef BN_FAST_S_MP_MUL_DIGS_C
-    if ((digs < MP_WARRAY) &&
-        MIN(a->used, b->used) <=
-        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
-      res = fast_s_mp_mul_digs (a, b, c, digs);
-    } else
-#endif
-#ifdef BN_S_MP_MUL_DIGS_C
-      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
-#else
-      res = MP_VAL;
-#endif
-
-  }
-  c->sign = (c->used > 0) ? neg : MP_ZPOS;
-  return res;
-}
-
-
-/* b = a*2 */
-int mp_mul_2(mp_int * a, mp_int * b)
-{
-  int     x, res, oldused;
-
-  /* grow to accommodate result */
-  if (b->alloc < a->used + 1) {
-    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  oldused = b->used;
-  b->used = a->used;
-
-  {
-    mp_digit r, rr, *tmpa, *tmpb;
-
-    /* alias for source */
-    tmpa = a->dp;
-
-    /* alias for dest */
-    tmpb = b->dp;
-
-    /* carry */
-    r = 0;
-    for (x = 0; x < a->used; x++) {
-
-      /* get what will be the *next* carry bit from the
-       * MSB of the current digit
-       */
-      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
-
-      /* now shift up this digit, add in the carry [from the previous] */
-      *tmpb++ = (mp_digit)(((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK);
-
-      /* copy the carry that would be from the source
-       * digit into the next iteration
-       */
-      r = rr;
-    }
-
-    /* new leading digit? */
-    if (r != 0) {
-      /* add a MSB which is always 1 at this point */
-      *tmpb = 1;
-      ++(b->used);
-    }
-
-    /* now zero any excess digits on the destination
-     * that we didn't write to
-     */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-  return MP_OKAY;
-}
-
-
-/* divide by three (based on routine from MPI and the GMP manual) */
-int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
-{
-  mp_int   q;
-  mp_word  w, t;
-  mp_digit b;
-  int      res, ix;
-
-  /* b = 2**DIGIT_BIT / 3 */
-  b = (mp_digit) ( (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3) );
-
-  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
-     return res;
-  }
-
-  q.used = a->used;
-  q.sign = a->sign;
-  w = 0;
-  for (ix = a->used - 1; ix >= 0; ix--) {
-     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
-
-     if (w >= 3) {
-        /* multiply w by [1/3] */
-        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
-
-        /* now subtract 3 * [w/3] from w, to get the remainder */
-        w -= t+t+t;
-
-        /* fixup the remainder as required since
-         * the optimization is not exact.
-         */
-        while (w >= 3) {
-           t += 1;
-           w -= 3;
-        }
-      } else {
-        t = 0;
-      }
-      q.dp[ix] = (mp_digit)t;
-  }
-
-  /* [optional] store the remainder */
-  if (d != NULL) {
-     *d = (mp_digit)w;
-  }
-
-  /* [optional] store the quotient */
-  if (c != NULL) {
-     mp_clamp(&q);
-     mp_exch(&q, c);
-  }
-  mp_clear(&q);
-
-  return res;
-}
-
-
-/* init an mp_init for a given size */
-int mp_init_size (mp_int * a, int size)
-{
-  int x;
-
-  /* pad size so there are always extra digits */
-  size += (MP_PREC * 2) - (size % MP_PREC);
-
-  /* alloc mem */
-  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL,
-                                      DYNAMIC_TYPE_BIGINT);
-  if (a->dp == NULL) {
-    return MP_MEM;
-  }
-
-  /* set the members */
-  a->used  = 0;
-  a->alloc = size;
-  a->sign  = MP_ZPOS;
-#ifdef HAVE_WOLF_BIGINT
-  wc_bigint_init(&a->raw);
-#endif
-
-  /* zero the digits */
-  for (x = 0; x < size; x++) {
-      a->dp[x] = 0;
-  }
-
-  return MP_OKAY;
-}
-
-
-/* the jist of squaring...
- * you do like mult except the offset of the tmpx [one that
- * starts closer to zero] can't equal the offset of tmpy.
- * So basically you set up iy like before then you min it with
- * (ty-tx) so that it never happens.  You double all those
- * you add in the inner loop
-
-After that loop you do the squares and add them in.
-*/
-
-int fast_s_mp_sqr (mp_int * a, mp_int * b)
-{
-  int       olduse, res, pa, ix, iz;
-#ifdef WOLFSSL_SMALL_STACK
-  mp_digit* W;    /* uses dynamic memory and slower */
-#else
-  mp_digit W[MP_WARRAY];
-#endif
-  mp_digit  *tmpx;
-  mp_word   W1;
-
-  /* grow the destination as required */
-  pa = a->used + a->used;
-  if (b->alloc < pa) {
-    if ((res = mp_grow (b, pa)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  if (pa > MP_WARRAY)
-    return MP_RANGE;  /* TAO range check */
-
-#ifdef WOLFSSL_SMALL_STACK
-  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
-  if (W == NULL)
-    return MP_MEM;
-#endif
-
-  /* number of output digits to produce */
-  W1 = 0;
-  for (ix = 0; ix < pa; ix++) {
-      int      tx, ty, iy;
-      mp_word  _W;
-      mp_digit *tmpy;
-
-      /* clear counter */
-      _W = 0;
-
-      /* get offsets into the two bignums */
-      ty = MIN(a->used-1, ix);
-      tx = ix - ty;
-
-      /* setup temp aliases */
-      tmpx = a->dp + tx;
-      tmpy = a->dp + ty;
-
-      /* this is the number of times the loop will iterate, essentially
-         while (tx++ < a->used && ty-- >= 0) { ... }
-       */
-      iy = MIN(a->used-tx, ty+1);
-
-      /* now for squaring tx can never equal ty
-       * we halve the distance since they approach at a rate of 2x
-       * and we have to round because odd cases need to be executed
-       */
-      iy = MIN(iy, (ty-tx+1)>>1);
-
-      /* execute loop */
-      for (iz = 0; iz < iy; iz++) {
-         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
-      }
-
-      /* double the inner product and add carry */
-      _W = _W + _W + W1;
-
-      /* even columns have the square term in them */
-      if ((ix&1) == 0) {
-         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
-      }
-
-      /* store it */
-      W[ix] = (mp_digit)(_W & MP_MASK);
-
-      /* make next carry */
-      W1 = _W >> ((mp_word)DIGIT_BIT);
-  }
-
-  /* setup dest */
-  olduse  = b->used;
-  b->used = a->used+a->used;
-
-  {
-    mp_digit *tmpb;
-    tmpb = b->dp;
-    for (ix = 0; ix < pa; ix++) {
-      *tmpb++ = (mp_digit)(W[ix] & MP_MASK);
-    }
-
-    /* clear unused digits [that existed in the old copy of c] */
-    for (; ix < olduse; ix++) {
-      *tmpb++ = 0;
-    }
-  }
-  mp_clamp (b);
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
-
-  return MP_OKAY;
-}
-
-
-/* Fast (comba) multiplier
- *
- * This is the fast column-array [comba] multiplier.  It is
- * designed to compute the columns of the product first
- * then handle the carries afterwards.  This has the effect
- * of making the nested loops that compute the columns very
- * simple and schedulable on super-scalar processors.
- *
- * This has been modified to produce a variable number of
- * digits of output so if say only a half-product is required
- * you don't have to compute the upper half (a feature
- * required for fast Barrett reduction).
- *
- * Based on Algorithm 14.12 on pp.595 of HAC.
- *
- */
-int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
-{
-  int     olduse, res, pa, ix, iz;
-#ifdef WOLFSSL_SMALL_STACK
-  mp_digit* W;    /* uses dynamic memory and slower */
-#else
-  mp_digit W[MP_WARRAY];
-#endif
-  mp_word  _W;
-
-  /* grow the destination as required */
-  if (c->alloc < digs) {
-    if ((res = mp_grow (c, digs)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* number of output digits to produce */
-  pa = MIN(digs, a->used + b->used);
-  if (pa > MP_WARRAY)
-    return MP_RANGE;  /* TAO range check */
-
-#ifdef WOLFSSL_SMALL_STACK
-  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
-  if (W == NULL)
-    return MP_MEM;
-#endif
-
-  /* clear the carry */
-  _W = 0;
-  for (ix = 0; ix < pa; ix++) {
-      int      tx, ty;
-      int      iy;
-      mp_digit *tmpx, *tmpy;
-
-      /* get offsets into the two bignums */
-      ty = MIN(b->used-1, ix);
-      tx = ix - ty;
-
-      /* setup temp aliases */
-      tmpx = a->dp + tx;
-      tmpy = b->dp + ty;
-
-      /* this is the number of times the loop will iterate, essentially
-         while (tx++ < a->used && ty-- >= 0) { ... }
-       */
-      iy = MIN(a->used-tx, ty+1);
-
-      /* execute loop */
-      for (iz = 0; iz < iy; ++iz) {
-         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
-
-      }
-
-      /* store term */
-      W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK);
-
-      /* make next carry */
-      _W = _W >> ((mp_word)DIGIT_BIT);
- }
-
-  /* setup dest */
-  olduse  = c->used;
-  c->used = pa;
-
-  {
-    mp_digit *tmpc;
-    tmpc = c->dp;
-    for (ix = 0; ix < pa; ix++) { /* JRB, +1 could read uninitialized data */
-      /* now extract the previous digit [below the carry] */
-      *tmpc++ = W[ix];
-    }
-
-    /* clear unused digits [that existed in the old copy of c] */
-    for (; ix < olduse; ix++) {
-      *tmpc++ = 0;
-    }
-  }
-  mp_clamp (c);
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
-
-  return MP_OKAY;
-}
-
-
-/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
-int s_mp_sqr (mp_int * a, mp_int * b)
-{
-  mp_int  t;
-  int     res, ix, iy, pa;
-  mp_word r;
-  mp_digit u, tmpx, *tmpt;
-
-  pa = a->used;
-  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
-    return res;
-  }
-
-  /* default used is maximum possible size */
-  t.used = 2*pa + 1;
-
-  for (ix = 0; ix < pa; ix++) {
-    /* first calculate the digit at 2*ix */
-    /* calculate double precision result */
-    r = ((mp_word) t.dp[2*ix]) +
-        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
-
-    /* store lower part in result */
-    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
-
-    /* get the carry */
-    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
-
-    /* left hand side of A[ix] * A[iy] */
-    tmpx        = a->dp[ix];
-
-    /* alias for where to store the results */
-    tmpt        = t.dp + (2*ix + 1);
-
-    for (iy = ix + 1; iy < pa; iy++) {
-      /* first calculate the product */
-      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
-
-      /* now calculate the double precision result, note we use
-       * addition instead of *2 since it's easier to optimize
-       */
-      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
-
-      /* store lower part */
-      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
-
-      /* get carry */
-      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
-    }
-    /* propagate upwards */
-    while (u != ((mp_digit) 0)) {
-      r       = ((mp_word) *tmpt) + ((mp_word) u);
-      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
-      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
-    }
-  }
-
-  mp_clamp (&t);
-  mp_exch (&t, b);
-  mp_clear (&t);
-  return MP_OKAY;
-}
-
-
-/* multiplies |a| * |b| and only computes up to digs digits of result
- * HAC pp. 595, Algorithm 14.12  Modified so you can control how
- * many digits of output are created.
- */
-int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
-{
-  mp_int  t;
-  int     res, pa, pb, ix, iy;
-  mp_digit u;
-  mp_word r;
-  mp_digit tmpx, *tmpt, *tmpy;
-
-  /* can we use the fast multiplier? */
-  if (((digs) < MP_WARRAY) &&
-      MIN (a->used, b->used) <
-          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
-    return fast_s_mp_mul_digs (a, b, c, digs);
-  }
-
-  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
-    return res;
-  }
-  t.used = digs;
-
-  /* compute the digits of the product directly */
-  pa = a->used;
-  for (ix = 0; ix < pa; ix++) {
-    /* set the carry to zero */
-    u = 0;
-
-    /* limit ourselves to making digs digits of output */
-    pb = MIN (b->used, digs - ix);
-
-    /* setup some aliases */
-    /* copy of the digit from a used within the nested loop */
-    tmpx = a->dp[ix];
-
-    /* an alias for the destination shifted ix places */
-    tmpt = t.dp + ix;
-
-    /* an alias for the digits of b */
-    tmpy = b->dp;
-
-    /* compute the columns of the output and propagate the carry */
-    for (iy = 0; iy < pb; iy++) {
-      /* compute the column as a mp_word */
-      r       = ((mp_word)*tmpt) +
-                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
-                ((mp_word) u);
-
-      /* the new column is the lower part of the result */
-      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
-
-      /* get the carry word from the result */
-      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
-    }
-    /* set carry if it is placed below digs */
-    if (ix + iy < digs) {
-      *tmpt = u;
-    }
-  }
-
-  mp_clamp (&t);
-  mp_exch (&t, c);
-
-  mp_clear (&t);
-  return MP_OKAY;
-}
-
-
-/*
- * shifts with subtractions when the result is greater than b.
- *
- * The method is slightly modified to shift B unconditionally up to just under
- * the leading bit of b.  This saves a lot of multiple precision shifting.
- */
-int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
-{
-  int     x, bits, res;
-
-  /* how many bits of last digit does b use */
-  bits = mp_count_bits (b) % DIGIT_BIT;
-
-  if (b->used > 1) {
-     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1))
-         != MP_OKAY) {
-        return res;
-     }
-  } else {
-     if ((res = mp_set(a, 1)) != MP_OKAY) {
-        return res;
-     }
-     bits = 1;
-  }
-
-  /* now compute C = A * B mod b */
-  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
-    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
-      return res;
-    }
-    if (mp_cmp_mag (a, b) != MP_LT) {
-      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
-        return res;
-      }
-    }
-  }
-
-  return MP_OKAY;
-}
-
-
-#ifdef MP_LOW_MEM
-   #define TAB_SIZE 32
-#else
-   #define TAB_SIZE 256
-#endif
-
-int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
-{
-  mp_int  M[TAB_SIZE], res, mu;
-  mp_digit buf;
-  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
-  int (*redux)(mp_int*,mp_int*,mp_int*);
-
-  /* find window size */
-  x = mp_count_bits (X);
-  if (x <= 7) {
-    winsize = 2;
-  } else if (x <= 36) {
-    winsize = 3;
-  } else if (x <= 140) {
-    winsize = 4;
-  } else if (x <= 450) {
-    winsize = 5;
-  } else if (x <= 1303) {
-    winsize = 6;
-  } else if (x <= 3529) {
-    winsize = 7;
-  } else {
-    winsize = 8;
-  }
-
-#ifdef MP_LOW_MEM
-    if (winsize > 5) {
-       winsize = 5;
-    }
-#endif
-
-  /* init M array */
-  /* init first cell */
-  if ((err = mp_init(&M[1])) != MP_OKAY) {
-     return err;
-  }
-
-  /* now init the second half of the array */
-  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
-    if ((err = mp_init(&M[x])) != MP_OKAY) {
-      for (y = 1<<(winsize-1); y < x; y++) {
-        mp_clear (&M[y]);
-      }
-      mp_clear(&M[1]);
-      return err;
-    }
-  }
-
-  /* create mu, used for Barrett reduction */
-  if ((err = mp_init (&mu)) != MP_OKAY) {
-    goto LBL_M;
-  }
-
-  if (redmode == 0) {
-     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
-        goto LBL_MU;
-     }
-     redux = mp_reduce;
-  } else {
-     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
-        goto LBL_MU;
-     }
-     redux = mp_reduce_2k_l;
-  }
-
-  /* create M table
-   *
-   * The M table contains powers of the base,
-   * e.g. M[x] = G**x mod P
-   *
-   * The first half of the table is not
-   * computed though accept for M[0] and M[1]
-   */
-  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
-    goto LBL_MU;
-  }
-
-  /* compute the value at M[1<<(winsize-1)] by squaring
-   * M[1] (winsize-1) times
-   */
-  if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
-    goto LBL_MU;
-  }
-
-  for (x = 0; x < (winsize - 1); x++) {
-    /* square it */
-    if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))],
-                       &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) {
-      goto LBL_MU;
-    }
-
-    /* reduce modulo P */
-    if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, &mu)) != MP_OKAY) {
-      goto LBL_MU;
-    }
-  }
-
-  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
-   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
-   */
-  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
-    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
-      goto LBL_MU;
-    }
-    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
-      goto LBL_MU;
-    }
-  }
-
-  /* setup result */
-  if ((err = mp_init (&res)) != MP_OKAY) {
-    goto LBL_MU;
-  }
-  if ((err = mp_set (&res, 1)) != MP_OKAY) {
-    goto LBL_MU;
-  }
-
-  /* set initial mode and bit cnt */
-  mode   = 0;
-  bitcnt = 1;
-  buf    = 0;
-  digidx = X->used - 1;
-  bitcpy = 0;
-  bitbuf = 0;
-
-  for (;;) {
-    /* grab next digit as required */
-    if (--bitcnt == 0) {
-      /* if digidx == -1 we are out of digits */
-      if (digidx == -1) {
-        break;
-      }
-      /* read next digit and reset the bitcnt */
-      buf    = X->dp[digidx--];
-      bitcnt = (int) DIGIT_BIT;
-    }
-
-    /* grab the next msb from the exponent */
-    y     = (int)(buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
-    buf <<= (mp_digit)1;
-
-    /* if the bit is zero and mode == 0 then we ignore it
-     * These represent the leading zero bits before the first 1 bit
-     * in the exponent.  Technically this opt is not required but it
-     * does lower the # of trivial squaring/reductions used
-     */
-    if (mode == 0 && y == 0) {
-      continue;
-    }
-
-    /* if the bit is zero and mode == 1 then we square */
-    if (mode == 1 && y == 0) {
-      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      continue;
-    }
-
-    /* else we add it to the window */
-    bitbuf |= (y << (winsize - ++bitcpy));
-    mode    = 2;
-
-    if (bitcpy == winsize) {
-      /* ok window is filled so square as required and multiply  */
-      /* square first */
-      for (x = 0; x < winsize; x++) {
-        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-      }
-
-      /* then multiply */
-      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-
-      /* empty window and reset */
-      bitcpy = 0;
-      bitbuf = 0;
-      mode   = 1;
-    }
-  }
-
-  /* if bits remain then square/multiply */
-  if (mode == 2 && bitcpy > 0) {
-    /* square then multiply if the bit is set */
-    for (x = 0; x < bitcpy; x++) {
-      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
-        goto LBL_RES;
-      }
-
-      bitbuf <<= 1;
-      if ((bitbuf & (1 << winsize)) != 0) {
-        /* then multiply */
-        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
-          goto LBL_RES;
-        }
-      }
-    }
-  }
-
-  mp_exch (&res, Y);
-  err = MP_OKAY;
-LBL_RES:mp_clear (&res);
-LBL_MU:mp_clear (&mu);
-LBL_M:
-  mp_clear(&M[1]);
-  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
-    mp_clear (&M[x]);
-  }
-  return err;
-}
-
-
-/* pre-calculate the value required for Barrett reduction
- * For a given modulus "b" it calculates the value required in "a"
- */
-int mp_reduce_setup (mp_int * a, mp_int * b)
-{
-  int     res;
-
-  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
-    return res;
-  }
-  return mp_div (a, b, a, NULL);
-}
-
-
-/* reduces x mod m, assumes 0 < x < m**2, mu is
- * precomputed via mp_reduce_setup.
- * From HAC pp.604 Algorithm 14.42
- */
-int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
-{
-  mp_int  q;
-  int     res, um = m->used;
-
-  /* q = x */
-  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
-    return res;
-  }
-
-  /* q1 = x / b**(k-1)  */
-  mp_rshd (&q, um - 1);
-
-  /* according to HAC this optimization is ok */
-  if (((mp_word) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
-    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
-      goto CLEANUP;
-    }
-  } else {
-#ifdef BN_S_MP_MUL_HIGH_DIGS_C
-    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
-      goto CLEANUP;
-    }
-#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
-    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
-      goto CLEANUP;
-    }
-#else
-    {
-      res = MP_VAL;
-      goto CLEANUP;
-    }
-#endif
-  }
-
-  /* q3 = q2 / b**(k+1) */
-  mp_rshd (&q, um + 1);
-
-  /* x = x mod b**(k+1), quick (no division) */
-  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
-    goto CLEANUP;
-  }
-
-  /* q = q * m mod b**(k+1), quick (no division) */
-  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
-    goto CLEANUP;
-  }
-
-  /* x = x - q */
-  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
-    goto CLEANUP;
-  }
-
-  /* If x < 0, add b**(k+1) to it */
-  if (mp_cmp_d (x, 0) == MP_LT) {
-    if ((res = mp_set (&q, 1)) != MP_OKAY)
-        goto CLEANUP;
-    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
-      goto CLEANUP;
-    if ((res = mp_add (x, &q, x)) != MP_OKAY)
-      goto CLEANUP;
-  }
-
-  /* Back off if it's too big */
-  while (mp_cmp (x, m) != MP_LT) {
-    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
-      goto CLEANUP;
-    }
-  }
-
-CLEANUP:
-  mp_clear (&q);
-
-  return res;
-}
-
-
-/* reduces a modulo n where n is of the form 2**p - d
-   This differs from reduce_2k since "d" can be larger
-   than a single digit.
-*/
-int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
-{
-   mp_int q;
-   int    p, res;
-
-   if ((res = mp_init(&q)) != MP_OKAY) {
-      return res;
-   }
-
-   p = mp_count_bits(n);
-top:
-   /* q = a/2**p, a = a mod 2**p */
-   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
-      goto ERR;
-   }
-
-   /* q = q * d */
-   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
-      goto ERR;
-   }
-
-   /* a = a + q */
-   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
-      goto ERR;
-   }
-
-   if (mp_cmp_mag(a, n) != MP_LT) {
-      if ((res = s_mp_sub(a, n, a)) != MP_OKAY) {
-         goto ERR;
-      }
-      goto top;
-   }
-
-ERR:
-   mp_clear(&q);
-   return res;
-}
-
-
-/* determines the setup value */
-int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
-{
-   int    res;
-   mp_int tmp;
-
-   if ((res = mp_init(&tmp)) != MP_OKAY) {
-      return res;
-   }
-
-   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
-      goto ERR;
-   }
-
-   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
-      goto ERR;
-   }
-
-ERR:
-   mp_clear(&tmp);
-   return res;
-}
-
-
-/* multiplies |a| * |b| and does not compute the lower digs digits
- * [meant to get the higher part of the product]
- */
-int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
-{
-  mp_int  t;
-  int     res, pa, pb, ix, iy;
-  mp_digit u;
-  mp_word r;
-  mp_digit tmpx, *tmpt, *tmpy;
-
-  /* can we use the fast multiplier? */
-#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
-  if (((a->used + b->used + 1) < MP_WARRAY)
-      && MIN (a->used, b->used) <
-      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
-    return fast_s_mp_mul_high_digs (a, b, c, digs);
-  }
-#endif
-
-  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
-    return res;
-  }
-  t.used = a->used + b->used + 1;
-
-  pa = a->used;
-  pb = b->used;
-  for (ix = 0; ix < pa && a->dp; ix++) {
-    /* clear the carry */
-    u = 0;
-
-    /* left hand side of A[ix] * B[iy] */
-    tmpx = a->dp[ix];
-
-    /* alias to the address of where the digits will be stored */
-    tmpt = &(t.dp[digs]);
-
-    /* alias for where to read the right hand side from */
-    tmpy = b->dp + (digs - ix);
-
-    for (iy = digs - ix; iy < pb; iy++) {
-      /* calculate the double precision result */
-      r       = ((mp_word)*tmpt) +
-                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
-                ((mp_word) u);
-
-      /* get the lower part */
-      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
-
-      /* carry the carry */
-      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
-    }
-    *tmpt = u;
-  }
-  mp_clamp (&t);
-  mp_exch (&t, c);
-  mp_clear (&t);
-  return MP_OKAY;
-}
-
-
-/* this is a modified version of fast_s_mul_digs that only produces
- * output digits *above* digs.  See the comments for fast_s_mul_digs
- * to see how it works.
- *
- * This is used in the Barrett reduction since for one of the multiplications
- * only the higher digits were needed.  This essentially halves the work.
- *
- * Based on Algorithm 14.12 on pp.595 of HAC.
- */
-int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
-{
-  int     olduse, res, pa, ix, iz;
-#ifdef WOLFSSL_SMALL_STACK
-  mp_digit* W;    /* uses dynamic memory and slower */
-#else
-  mp_digit W[MP_WARRAY];
-#endif
-  mp_word  _W;
-
-  if (a->dp == NULL) { /* JRB, avoid reading uninitialized values */
-      return MP_VAL;
-  }
-
-  /* grow the destination as required */
-  pa = a->used + b->used;
-  if (c->alloc < pa) {
-    if ((res = mp_grow (c, pa)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  if (pa > MP_WARRAY)
-    return MP_RANGE;  /* TAO range check */
-
-#ifdef WOLFSSL_SMALL_STACK
-  W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT);
-  if (W == NULL)
-    return MP_MEM;
-#endif
-
-  /* number of output digits to produce */
-  pa = a->used + b->used;
-  _W = 0;
-  for (ix = digs; ix < pa; ix++) { /* JRB, have a->dp check at top of function*/
-      int      tx, ty, iy;
-      mp_digit *tmpx, *tmpy;
-
-      /* get offsets into the two bignums */
-      ty = MIN(b->used-1, ix);
-      tx = ix - ty;
-
-      /* setup temp aliases */
-      tmpx = a->dp + tx;
-      tmpy = b->dp + ty;
-
-      /* this is the number of times the loop will iterate, essentially its
-         while (tx++ < a->used && ty-- >= 0) { ... }
-       */
-      iy = MIN(a->used-tx, ty+1);
-
-      /* execute loop */
-      for (iz = 0; iz < iy; iz++) {
-         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
-      }
-
-      /* store term */
-      W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK);
-
-      /* make next carry */
-      _W = _W >> ((mp_word)DIGIT_BIT);
-  }
-
-  /* setup dest */
-  olduse  = c->used;
-  c->used = pa;
-
-  {
-    mp_digit *tmpc;
-
-    tmpc = c->dp + digs;
-    for (ix = digs; ix < pa; ix++) {   /* TAO, <= could potentially overwrite */
-      /* now extract the previous digit [below the carry] */
-      *tmpc++ = W[ix];
-    }
-
-    /* clear unused digits [that existed in the old copy of c] */
-    for (; ix < olduse; ix++) {
-      *tmpc++ = 0;
-    }
-  }
-  mp_clamp (c);
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(W, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
-
-  return MP_OKAY;
-}
-
-
-#ifndef MP_SET_CHUNK_BITS
-    #define MP_SET_CHUNK_BITS 4
-#endif
-int mp_set_int (mp_int * a, unsigned long b)
-{
-  int x, res;
-
-  /* use direct mp_set if b is less than mp_digit max */
-  if (b < MP_DIGIT_MAX) {
-    return mp_set (a, (mp_digit)b);
-  }
-
-  mp_zero (a);
-
-  /* set chunk bits at a time */
-  for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) {
-    /* shift the number up chunk bits */
-    if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) {
-      return res;
-    }
-
-    /* OR in the top bits of the source */
-    a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) &
-                                  ((1 << MP_SET_CHUNK_BITS) - 1);
-
-    /* shift the source up to the next chunk bits */
-    b <<= MP_SET_CHUNK_BITS;
-
-    /* ensure that digits are not clamped off */
-    a->used += 1;
-  }
-  mp_clamp (a);
-  return MP_OKAY;
-}
-
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC)
-
-/* c = a * a (mod b) */
-int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
-{
-  int     res;
-  mp_int  t;
-
-  if ((res = mp_init (&t)) != MP_OKAY) {
-    return res;
-  }
-
-  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
-    mp_clear (&t);
-    return res;
-  }
-  res = mp_mod (&t, b, c);
-  mp_clear (&t);
-  return res;
-}
-
-#endif
-
-
-#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(WOLFSSL_SNIFFER) || \
-    defined(WOLFSSL_HAVE_WOLFSCEP) || defined(WOLFSSL_KEY_GEN) || \
-    defined(OPENSSL_EXTRA) || defined(WC_RSA_BLINDING)
-
-/* single digit addition */
-int mp_add_d (mp_int* a, mp_digit b, mp_int* c)
-{
-  int     res, ix, oldused;
-  mp_digit *tmpa, *tmpc, mu;
-
-  /* grow c as required */
-  if (c->alloc < a->used + 1) {
-     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
-        return res;
-     }
-  }
-
-  /* if a is negative and |a| >= b, call c = |a| - b */
-  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
-     /* temporarily fix sign of a */
-     a->sign = MP_ZPOS;
-
-     /* c = |a| - b */
-     res = mp_sub_d(a, b, c);
-
-     /* fix sign  */
-     a->sign = c->sign = MP_NEG;
-
-     /* clamp */
-     mp_clamp(c);
-
-     return res;
-  }
-
-  /* old number of used digits in c */
-  oldused = c->used;
-
-  /* sign always positive */
-  c->sign = MP_ZPOS;
-
-  /* source alias */
-  tmpa    = a->dp;
-
-  /* destination alias */
-  tmpc    = c->dp;
-
-  /* if a is positive */
-  if (a->sign == MP_ZPOS) {
-     /* add digit, after this we're propagating
-      * the carry.
-      */
-     *tmpc   = *tmpa++ + b;
-     mu      = *tmpc >> DIGIT_BIT;
-     *tmpc++ &= MP_MASK;
-
-     /* now handle rest of the digits */
-     for (ix = 1; ix < a->used; ix++) {
-        *tmpc   = *tmpa++ + mu;
-        mu      = *tmpc >> DIGIT_BIT;
-        *tmpc++ &= MP_MASK;
-     }
-     /* set final carry */
-     if (ix < c->alloc) {
-        ix++;
-        *tmpc++  = mu;
-     }
-
-     /* setup size */
-     c->used = a->used + 1;
-  } else {
-     /* a was negative and |a| < b */
-     c->used  = 1;
-
-     /* the result is a single digit */
-     if (a->used == 1) {
-        *tmpc++  =  b - a->dp[0];
-     } else {
-        *tmpc++  =  b;
-     }
-
-     /* setup count so the clearing of oldused
-      * can fall through correctly
-      */
-     ix       = 1;
-  }
-
-  /* now zero to oldused */
-  while (ix++ < oldused) {
-     *tmpc++ = 0;
-  }
-  mp_clamp(c);
-
-  return MP_OKAY;
-}
-
-
-/* single digit subtraction */
-int mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
-{
-  mp_digit *tmpa, *tmpc, mu;
-  int       res, ix, oldused;
-
-  /* grow c as required */
-  if (c->alloc < a->used + 1) {
-     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
-        return res;
-     }
-  }
-
-  /* if a is negative just do an unsigned
-   * addition [with fudged signs]
-   */
-  if (a->sign == MP_NEG) {
-     a->sign = MP_ZPOS;
-     res     = mp_add_d(a, b, c);
-     a->sign = c->sign = MP_NEG;
-
-     /* clamp */
-     mp_clamp(c);
-
-     return res;
-  }
-
-  /* setup regs */
-  oldused = c->used;
-  tmpa    = a->dp;
-  tmpc    = c->dp;
-
-  /* if a <= b simply fix the single digit */
-  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
-     if (a->used == 1) {
-        *tmpc++ = b - *tmpa;
-     } else {
-        *tmpc++ = b;
-     }
-     ix      = 1;
-
-     /* negative/1digit */
-     c->sign = MP_NEG;
-     c->used = 1;
-  } else {
-     /* positive/size */
-     c->sign = MP_ZPOS;
-     c->used = a->used;
-
-     /* subtract first digit */
-     *tmpc    = *tmpa++ - b;
-     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
-     *tmpc++ &= MP_MASK;
-
-     /* handle rest of the digits */
-     for (ix = 1; ix < a->used; ix++) {
-        *tmpc    = *tmpa++ - mu;
-        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
-        *tmpc++ &= MP_MASK;
-     }
-  }
-
-  /* zero excess digits */
-  while (ix++ < oldused) {
-     *tmpc++ = 0;
-  }
-  mp_clamp(c);
-  return MP_OKAY;
-}
-
-#endif /* defined(HAVE_ECC) || !defined(NO_PWDBASED) */
-
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \
-    defined(DEBUG_WOLFSSL)
-
-static const int lnz[16] = {
-   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
-};
-
-/* Counts the number of lsbs which are zero before the first zero bit */
-int mp_cnt_lsb(mp_int *a)
-{
-    int x;
-    mp_digit q = 0, qq;
-
-    /* easy out */
-    if (mp_iszero(a) == MP_YES) {
-        return 0;
-    }
-
-    /* scan lower digits until non-zero */
-    for (x = 0; x < a->used && a->dp[x] == 0; x++) {}
-    if (a->dp)
-        q = a->dp[x];
-    x *= DIGIT_BIT;
-
-    /* now scan this digit until a 1 is found */
-    if ((q & 1) == 0) {
-        do {
-            qq  = q & 15;
-            x  += lnz[qq];
-            q >>= 4;
-        } while (qq == 0);
-    }
-    return x;
-}
-
-
-
-
-static int s_is_power_of_two(mp_digit b, int *p)
-{
-   int x;
-
-   /* fast return if no power of two */
-   if ((b==0) || (b & (b-1))) {
-      return 0;
-   }
-
-   for (x = 0; x < DIGIT_BIT; x++) {
-      if (b == (((mp_digit)1)<<x)) {
-         *p = x;
-         return 1;
-      }
-   }
-   return 0;
-}
-
-/* single digit division (based on routine from MPI) */
-static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
-{
-  mp_int  q;
-  mp_word w;
-  mp_digit t;
-  int     res = MP_OKAY, ix;
-
-  /* cannot divide by zero */
-  if (b == 0) {
-     return MP_VAL;
-  }
-
-  /* quick outs */
-  if (b == 1 || mp_iszero(a) == MP_YES) {
-     if (d != NULL) {
-        *d = 0;
-     }
-     if (c != NULL) {
-        return mp_copy(a, c);
-     }
-     return MP_OKAY;
-  }
-
-  /* power of two ? */
-  if (s_is_power_of_two(b, &ix) == 1) {
-     if (d != NULL) {
-        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
-     }
-     if (c != NULL) {
-        return mp_div_2d(a, ix, c, NULL);
-     }
-     return MP_OKAY;
-  }
-
-#ifdef BN_MP_DIV_3_C
-  /* three? */
-  if (b == 3) {
-     return mp_div_3(a, c, d);
-  }
-#endif
-
-  /* no easy answer [c'est la vie].  Just division */
-  if (c != NULL) {
-      if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
-         return res;
-      }
-
-      q.used = a->used;
-      q.sign = a->sign;
-  }
-  else {
-      if ((res = mp_init(&q)) != MP_OKAY) {
-         return res;
-      }
-  }
-
-
-  w = 0;
-  for (ix = a->used - 1; ix >= 0; ix--) {
-     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
-
-     if (w >= b) {
-        t = (mp_digit)(w / b);
-        w -= ((mp_word)t) * ((mp_word)b);
-      } else {
-        t = 0;
-      }
-      if (c != NULL)
-        q.dp[ix] = (mp_digit)t;
-  }
-
-  if (d != NULL) {
-     *d = (mp_digit)w;
-  }
-
-  if (c != NULL) {
-     mp_clamp(&q);
-     mp_exch(&q, c);
-  }
-  mp_clear(&q);
-
-  return res;
-}
-
-
-int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
-{
-  return mp_div_d(a, b, NULL, c);
-}
-
-#endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */
-
-#ifdef WOLFSSL_KEY_GEN
-
-const mp_digit ltm_prime_tab[PRIME_SIZE] = {
-  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
-  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
-  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
-  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
-#ifndef MP_8BIT
-  0x0083,
-  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
-  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
-  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
-  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
-
-  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
-  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
-  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
-  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
-  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
-  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
-  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
-  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
-
-  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
-  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
-  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
-  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
-  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
-  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
-  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
-  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
-
-  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
-  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
-  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
-  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
-  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
-  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
-  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
-  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
-#endif
-};
-
-
-/* Miller-Rabin test of "a" to the base of "b" as described in
- * HAC pp. 139 Algorithm 4.24
- *
- * Sets result to 0 if definitely composite or 1 if probably prime.
- * Randomly the chance of error is no more than 1/4 and often
- * very much lower.
- */
-static int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
-{
-  mp_int  n1, y, r;
-  int     s, j, err;
-
-  /* default */
-  *result = MP_NO;
-
-  /* ensure b > 1 */
-  if (mp_cmp_d(b, 1) != MP_GT) {
-     return MP_VAL;
-  }
-
-  /* get n1 = a - 1 */
-  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
-    return err;
-  }
-  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
-    goto LBL_N1;
-  }
-
-  /* set 2**s * r = n1 */
-  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
-    goto LBL_N1;
-  }
-
-  /* count the number of least significant bits
-   * which are zero
-   */
-  s = mp_cnt_lsb(&r);
-
-  /* now divide n - 1 by 2**s */
-  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
-    goto LBL_R;
-  }
-
-  /* compute y = b**r mod a */
-  if ((err = mp_init (&y)) != MP_OKAY) {
-    goto LBL_R;
-  }
-  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
-    goto LBL_Y;
-  }
-
-  /* if y != 1 and y != n1 do */
-  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
-    j = 1;
-    /* while j <= s-1 and y != n1 */
-    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
-      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
-         goto LBL_Y;
-      }
-
-      /* if y == 1 then composite */
-      if (mp_cmp_d (&y, 1) == MP_EQ) {
-         goto LBL_Y;
-      }
-
-      ++j;
-    }
-
-    /* if y != n1 then composite */
-    if (mp_cmp (&y, &n1) != MP_EQ) {
-      goto LBL_Y;
-    }
-  }
-
-  /* probably prime now */
-  *result = MP_YES;
-LBL_Y:mp_clear (&y);
-LBL_R:mp_clear (&r);
-LBL_N1:mp_clear (&n1);
-  return err;
-}
-
-
-/* determines if an integers is divisible by one
- * of the first PRIME_SIZE primes or not
- *
- * sets result to 0 if not, 1 if yes
- */
-static int mp_prime_is_divisible (mp_int * a, int *result)
-{
-  int     err, ix;
-  mp_digit res;
-
-  /* default to not */
-  *result = MP_NO;
-
-  for (ix = 0; ix < PRIME_SIZE; ix++) {
-    /* what is a mod LBL_prime_tab[ix] */
-    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
-      return err;
-    }
-
-    /* is the residue zero? */
-    if (res == 0) {
-      *result = MP_YES;
-      return MP_OKAY;
-    }
-  }
-
-  return MP_OKAY;
-}
-
-static const int USE_BBS = 1;
-
-int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap)
-{
-    int   err, res, type;
-    byte* buf;
-
-    if (N == NULL || rng == NULL)
-        return MP_VAL;
-
-    /* get type */
-    if (len < 0) {
-        type = USE_BBS;
-        len = -len;
-    } else {
-        type = 0;
-    }
-
-    /* allow sizes between 2 and 512 bytes for a prime size */
-    if (len < 2 || len > 512) {
-        return MP_VAL;
-    }
-
-    /* allocate buffer to work with */
-    buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA);
-    if (buf == NULL) {
-        return MP_MEM;
-    }
-    XMEMSET(buf, 0, len);
-
-    do {
-#ifdef SHOW_GEN
-        printf(".");
-        fflush(stdout);
-#endif
-        /* generate value */
-        err = wc_RNG_GenerateBlock(rng, buf, len);
-        if (err != 0) {
-            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
-            return err;
-        }
-
-        /* munge bits */
-        buf[0]     |= 0x80 | 0x40;
-        buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
-
-        /* load value */
-        if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
-            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
-            return err;
-        }
-
-        /* test */
-        if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
-            XFREE(buf, heap, DYNAMIC_TYPE_RSA);
-            return err;
-        }
-    } while (res == MP_NO);
-
-    XMEMSET(buf, 0, len);
-    XFREE(buf, heap, DYNAMIC_TYPE_RSA);
-
-    return MP_OKAY;
-}
-
-/*
- * Sets result to 1 if probably prime, 0 otherwise
- */
-int mp_prime_is_prime (mp_int * a, int t, int *result)
-{
-  mp_int  b;
-  int     ix, err, res;
-
-  /* default to no */
-  *result = MP_NO;
-
-  /* valid value of t? */
-  if (t <= 0 || t > PRIME_SIZE) {
-    return MP_VAL;
-  }
-
-  /* is the input equal to one of the primes in the table? */
-  for (ix = 0; ix < PRIME_SIZE; ix++) {
-      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
-         *result = 1;
-         return MP_OKAY;
-      }
-  }
-
-  /* first perform trial division */
-  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
-    return err;
-  }
-
-  /* return if it was trivially divisible */
-  if (res == MP_YES) {
-    return MP_OKAY;
-  }
-
-  /* now perform the miller-rabin rounds */
-  if ((err = mp_init (&b)) != MP_OKAY) {
-    return err;
-  }
-
-  for (ix = 0; ix < t; ix++) {
-    /* set the prime */
-    if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) {
-        goto LBL_B;
-    }
-
-    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
-      goto LBL_B;
-    }
-
-    if (res == MP_NO) {
-      goto LBL_B;
-    }
-  }
-
-  /* passed the test */
-  *result = MP_YES;
-LBL_B:mp_clear (&b);
-  return err;
-}
-
-
-/* computes least common multiple as |a*b|/(a, b) */
-int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
-{
-  int     res;
-  mp_int  t1, t2;
-
-
-  if ((res = mp_init_multi (&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
-    return res;
-  }
-
-  /* t1 = get the GCD of the two inputs */
-  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
-    goto LBL_T;
-  }
-
-  /* divide the smallest by the GCD */
-  if (mp_cmp_mag(a, b) == MP_LT) {
-     /* store quotient in t2 such that t2 * b is the LCM */
-     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
-        goto LBL_T;
-     }
-     res = mp_mul(b, &t2, c);
-  } else {
-     /* store quotient in t2 such that t2 * a is the LCM */
-     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
-        goto LBL_T;
-     }
-     res = mp_mul(a, &t2, c);
-  }
-
-  /* fix the sign to positive */
-  c->sign = MP_ZPOS;
-
-LBL_T:
-  mp_clear(&t1);
-  mp_clear(&t2);
-  return res;
-}
-
-
-
-/* Greatest Common Divisor using the binary method */
-int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
-{
-    mp_int  u, v;
-    int     k, u_lsb, v_lsb, res;
-
-    /* either zero than gcd is the largest */
-    if (mp_iszero (a) == MP_YES) {
-        return mp_abs (b, c);
-    }
-    if (mp_iszero (b) == MP_YES) {
-        return mp_abs (a, c);
-    }
-
-    /* get copies of a and b we can modify */
-    if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
-        return res;
-    }
-
-    if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
-        goto LBL_U;
-    }
-
-    /* must be positive for the remainder of the algorithm */
-    u.sign = v.sign = MP_ZPOS;
-
-    /* B1.  Find the common power of two for u and v */
-    u_lsb = mp_cnt_lsb(&u);
-    v_lsb = mp_cnt_lsb(&v);
-    k     = MIN(u_lsb, v_lsb);
-
-    if (k > 0) {
-        /* divide the power of two out */
-        if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
-            goto LBL_V;
-        }
-
-        if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
-            goto LBL_V;
-        }
-    }
-
-    /* divide any remaining factors of two out */
-    if (u_lsb != k) {
-        if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
-            goto LBL_V;
-        }
-    }
-
-    if (v_lsb != k) {
-        if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
-            goto LBL_V;
-        }
-    }
-
-    while (mp_iszero(&v) == MP_NO) {
-        /* make sure v is the largest */
-        if (mp_cmp_mag(&u, &v) == MP_GT) {
-            /* swap u and v to make sure v is >= u */
-            mp_exch(&u, &v);
-        }
-
-        /* subtract smallest from largest */
-        if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
-            goto LBL_V;
-        }
-
-        /* Divide out all factors of two */
-        if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
-            goto LBL_V;
-        }
-    }
-
-    /* multiply by 2**k which we divided out at the beginning */
-    if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
-        goto LBL_V;
-    }
-    c->sign = MP_ZPOS;
-    res = MP_OKAY;
-LBL_V:mp_clear (&u);
-LBL_U:mp_clear (&v);
-    return res;
-}
-
-#endif /* WOLFSSL_KEY_GEN */
-
-
-#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \
-    defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \
-    defined(DEBUG_WOLFSSL)
-
-/* chars used in radix conversions */
-const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-                         abcdefghijklmnopqrstuvwxyz+/";
-#endif
-
-#if !defined(NO_DSA) || defined(HAVE_ECC)
-/* read a string [ASCII] in a given radix */
-int mp_read_radix (mp_int * a, const char *str, int radix)
-{
-  int     y, res, neg;
-  char    ch;
-
-  /* zero the digit bignum */
-  mp_zero(a);
-
-  /* make sure the radix is ok */
-  if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
-    return MP_VAL;
-  }
-
-  /* if the leading digit is a
-   * minus set the sign to negative.
-   */
-  if (*str == '-') {
-    ++str;
-    neg = MP_NEG;
-  } else {
-    neg = MP_ZPOS;
-  }
-
-  /* set the integer to the default of zero */
-  mp_zero (a);
-
-  /* process each digit of the string */
-  while (*str != '\0') {
-    /* if the radix <= 36 the conversion is case insensitive
-     * this allows numbers like 1AB and 1ab to represent the same  value
-     * [e.g. in hex]
-     */
-    ch = (radix <= 36) ? (char)XTOUPPER((unsigned char)*str) : *str;
-    for (y = 0; y < 64; y++) {
-      if (ch == mp_s_rmap[y]) {
-         break;
-      }
-    }
-
-    /* if the char was found in the map
-     * and is less than the given radix add it
-     * to the number, otherwise exit the loop.
-     */
-    if (y < radix) {
-      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
-         return res;
-      }
-      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
-         return res;
-      }
-    } else {
-      break;
-    }
-    ++str;
-  }
-
-  /* if digit in isn't null term, then invalid character was found */
-  if (*str != '\0') {
-     mp_zero (a);
-     return MP_VAL;
-  }
-
-  /* set the sign only if a != 0 */
-  if (mp_iszero(a) != MP_YES) {
-     a->sign = neg;
-  }
-  return MP_OKAY;
-}
-#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
-    defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
-    defined(WOLFSSL_PUBLIC_MP)
-
-/* returns size of ASCII representation */
-int mp_radix_size (mp_int *a, int radix, int *size)
-{
-    int     res, digs;
-    mp_int  t;
-    mp_digit d;
-
-    *size = 0;
-
-    /* special case for binary */
-    if (radix == MP_RADIX_BIN) {
-        *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
-        return MP_OKAY;
-    }
-
-    /* make sure the radix is in range */
-    if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
-        return MP_VAL;
-    }
-
-    if (mp_iszero(a) == MP_YES) {
-        *size = 2;
-        return MP_OKAY;
-    }
-
-    /* digs is the digit count */
-    digs = 0;
-
-    /* if it's negative add one for the sign */
-    if (a->sign == MP_NEG) {
-        ++digs;
-    }
-
-    /* init a copy of the input */
-    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
-        return res;
-    }
-
-    /* force temp to positive */
-    t.sign = MP_ZPOS;
-
-    /* fetch out all of the digits */
-    while (mp_iszero (&t) == MP_NO) {
-        if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
-            mp_clear (&t);
-            return res;
-        }
-        ++digs;
-    }
-    mp_clear (&t);
-
-    /* return digs + 1, the 1 is for the NULL byte that would be required. */
-    *size = digs + 1;
-    return MP_OKAY;
-}
-
-/* stores a bignum as a ASCII string in a given radix (2..64) */
-int mp_toradix (mp_int *a, char *str, int radix)
-{
-    int     res, digs;
-    mp_int  t;
-    mp_digit d;
-    char   *_s = str;
-
-    /* check range of the radix */
-    if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) {
-        return MP_VAL;
-    }
-
-    /* quick out if its zero */
-    if (mp_iszero(a) == MP_YES) {
-        *str++ = '0';
-        *str = '\0';
-        return MP_OKAY;
-    }
-
-    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
-        return res;
-    }
-
-    /* if it is negative output a - */
-    if (t.sign == MP_NEG) {
-        ++_s;
-        *str++ = '-';
-        t.sign = MP_ZPOS;
-    }
-
-    digs = 0;
-    while (mp_iszero (&t) == MP_NO) {
-        if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
-            mp_clear (&t);
-            return res;
-        }
-        *str++ = mp_s_rmap[d];
-        ++digs;
-    }
-
-    /* reverse the digits of the string.  In this case _s points
-     * to the first digit [excluding the sign] of the number]
-     */
-    bn_reverse ((unsigned char *)_s, digs);
-
-    /* append a NULL so the string is properly terminated */
-    *str = '\0';
-
-    mp_clear (&t);
-    return MP_OKAY;
-}
-
-#ifdef WOLFSSL_DEBUG_MATH
-void mp_dump(const char* desc, mp_int* a, byte verbose)
-{
-  char *buffer;
-  int size = a->alloc;
-
-  buffer = (char*)XMALLOC(size * sizeof(mp_digit) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-  if (buffer == NULL) {
-    return;
-  }
-
-  printf("%s: ptr=%p, used=%d, sign=%d, size=%d, mpd=%d\n",
-    desc, a, a->used, a->sign, size, (int)sizeof(mp_digit));
-
-  mp_tohex(a, buffer);
-  printf("  %s\n  ", buffer);
-
-  if (verbose) {
-    int i;
-    for(i=0; i<a->alloc * (int)sizeof(mp_digit); i++) {
-      printf("%02x ", *(((byte*)a->dp) + i));
-    }
-    printf("\n");
-  }
-
-  XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-}
-#endif /* WOLFSSL_DEBUG_MATH */
-
-#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */
-
-#endif /* WOLFSSL_SP_MATH */
-
-#endif /* USE_FAST_MATH */
-
-#endif /* NO_BIG_INT */
-
-
--- a/wolfcrypt/src/logging.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,747 +0,0 @@
-/* logging.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-/* submitted by eof */
-
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
-/* avoid adding WANT_READ and WANT_WRITE to error queue */
-#include <wolfssl/error-ssl.h>
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */
-
-/* accessing any node from the queue should be wrapped in a lock of
- * debug_mutex */
-static void* wc_error_heap;
-struct wc_error_queue {
-    void*  heap; /* the heap hint used with nodes creation */
-    struct wc_error_queue* next;
-    struct wc_error_queue* prev;
-    char   error[WOLFSSL_MAX_ERROR_SZ];
-    char   file[WOLFSSL_MAX_ERROR_SZ];
-    int    value;
-    int    line;
-};
-volatile struct wc_error_queue* wc_errors;
-static struct wc_error_queue* wc_current_node;
-static struct wc_error_queue* wc_last_node;
-/* pointer to last node in queue to make insertion O(1) */
-#endif
-
-#ifdef WOLFSSL_FUNC_TIME
-/* WARNING: This code is only to be used for debugging performance.
- *          The code is not thread-safe.
- *          Do not use WOLFSSL_FUNC_TIME in production code.
- */
-static double wc_func_start[WC_FUNC_COUNT];
-static double wc_func_time[WC_FUNC_COUNT] = { 0, };
-static const char* wc_func_name[WC_FUNC_COUNT] = {
-    "SendClientHello",
-    "DoClientHello",
-    "SendServerHello",
-    "DoServerHello",
-    "SendEncryptedExtensions",
-    "DoEncryptedExtensions",
-    "SendCertificateRequest",
-    "DoCertificateRequest",
-    "SendCertificate",
-    "DoCertificate",
-    "SendCertificateVerify",
-    "DoCertificateVerify",
-    "SendFinished",
-    "DoFinished",
-    "SendKeyUpdate",
-    "DoKeyUpdate",
-    "SendEarlyData",
-    "DoEarlyData",
-    "SendNewSessionTicket",
-    "DoNewSessionTicket",
-    "SendServerHelloDone",
-    "DoServerHelloDone",
-    "SendTicket",
-    "DoTicket",
-    "SendClientKeyExchange",
-    "DoClientKeyExchange",
-    "SendCertificateStatus",
-    "DoCertificateStatus",
-    "SendServerKeyExchange",
-    "DoServerKeyExchange",
-    "SendEarlyData",
-    "DoEarlyData",
-};
-
-#include <sys/time.h>
-
-/* WARNING: This function is not portable. */
-static WC_INLINE double current_time(int reset)
-{
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    (void)reset;
-
-    return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
-}
-#endif /* WOLFSSL_FUNC_TIME */
-
-#ifdef DEBUG_WOLFSSL
-
-/* Set these to default values initially. */
-static wolfSSL_Logging_cb log_function = NULL;
-static int loggingEnabled = 0;
-
-#endif /* DEBUG_WOLFSSL */
-
-
-/* allow this to be set to NULL, so logs can be redirected to default output */
-int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f)
-{
-#ifdef DEBUG_WOLFSSL
-    log_function = f;
-    return 0;
-#else
-    (void)f;
-    return NOT_COMPILED_IN;
-#endif
-}
-
-
-int wolfSSL_Debugging_ON(void)
-{
-#ifdef DEBUG_WOLFSSL
-    loggingEnabled = 1;
-    return 0;
-#else
-    return NOT_COMPILED_IN;
-#endif
-}
-
-
-void wolfSSL_Debugging_OFF(void)
-{
-#ifdef DEBUG_WOLFSSL
-    loggingEnabled = 0;
-#endif
-}
-
-#ifdef WOLFSSL_FUNC_TIME
-/* WARNING: This code is only to be used for debugging performance.
- *          The code is not thread-safe.
- *          Do not use WOLFSSL_FUNC_TIME in production code.
- */
-void WOLFSSL_START(int funcNum)
-{
-    double now = current_time(0) * 1000.0;
-#ifdef WOLFSSL_FUNC_TIME_LOG
-    fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]);
-#endif
-    wc_func_start[funcNum] = now;
-}
-
-void WOLFSSL_END(int funcNum)
-{
-    double now = current_time(0) * 1000.0;
-    wc_func_time[funcNum] += now - wc_func_start[funcNum];
-#ifdef WOLFSSL_FUNC_TIME_LOG
-    fprintf(stderr, "%17.3f: END   - %s\n", now, wc_func_name[funcNum]);
-#endif
-}
-
-void WOLFSSL_TIME(int count)
-{
-    int i;
-    double avg, total = 0;
-
-    for (i = 0; i < WC_FUNC_COUNT; i++) {
-        if (wc_func_time[i] > 0) {
-            avg = wc_func_time[i] / count;
-            fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]);
-            total += avg;
-        }
-    }
-    fprintf(stderr, "%8.3f ms\n", total);
-}
-#endif
-
-#ifdef DEBUG_WOLFSSL
-
-#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    #if MQX_USE_IO_OLD
-        #include <fio.h>
-    #else
-        #include <nio.h>
-    #endif
-#elif defined(WOLFSSL_SGX)
-    /* Declare sprintf for ocall */
-    int sprintf(char* buf, const char *fmt, ...);
-#elif defined(MICRIUM)
-    #include <bsp_ser.h>
-#elif defined(WOLFSSL_USER_LOG)
-    /* user includes their own headers */
-#else
-    #include <stdio.h>   /* for default printf stuff */
-#endif
-
-#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
-    int dc_log_printf(char*, ...);
-#endif
-
-static void wolfssl_log(const int logLevel, const char *const logMessage)
-{
-    if (log_function)
-        log_function(logLevel, logMessage);
-    else {
-#if defined(WOLFSSL_USER_LOG)
-        WOLFSSL_USER_LOG(logMessage);
-#elif defined(WOLFSSL_LOG_PRINTF)
-        printf("%s\n", logMessage);
-
-#elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
-        dc_log_printf("%s\n", logMessage);
-#elif defined(MICRIUM)
-        BSP_Ser_Printf("%s\r\n", logMessage);
-#elif defined(WOLFSSL_MDK_ARM)
-        fflush(stdout) ;
-        printf("%s\n", logMessage);
-        fflush(stdout) ;
-#elif defined(WOLFSSL_UTASKER)
-        fnDebugMsg((char*)logMessage);
-        fnDebugMsg("\r\n");
-#elif defined(MQX_USE_IO_OLD)
-        fprintf(_mqxio_stderr, "%s\n", logMessage);
-
-#else
-        fprintf(stderr, "%s\n", logMessage);
-#endif
-    }
-}
-
-#ifndef WOLFSSL_DEBUG_ERRORS_ONLY
-void WOLFSSL_MSG(const char* msg)
-{
-    if (loggingEnabled)
-        wolfssl_log(INFO_LOG , msg);
-}
-
-
-void WOLFSSL_BUFFER(const byte* buffer, word32 length)
-{
-    #define LINE_LEN 16
-
-    if (loggingEnabled) {
-        word32 i;
-        char line[80];
-
-        if (!buffer) {
-            wolfssl_log(INFO_LOG, "\tNULL");
-
-            return;
-        }
-
-        sprintf(line, "\t");
-
-        for (i = 0; i < LINE_LEN; i++) {
-            if (i < length)
-                sprintf(line + 1 + i * 3,"%02x ", buffer[i]);
-            else
-                sprintf(line + 1 + i * 3, "   ");
-        }
-
-        sprintf(line + 1 + LINE_LEN * 3, "| ");
-
-        for (i = 0; i < LINE_LEN; i++)
-            if (i < length)
-                sprintf(line + 3 + LINE_LEN * 3 + i,
-                     "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.');
-
-        wolfssl_log(INFO_LOG, line);
-
-        if (length > LINE_LEN)
-            WOLFSSL_BUFFER(buffer + LINE_LEN, length - LINE_LEN);
-    }
-}
-
-
-void WOLFSSL_ENTER(const char* msg)
-{
-    if (loggingEnabled) {
-        char buffer[WOLFSSL_MAX_ERROR_SZ];
-        XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg);
-        wolfssl_log(ENTER_LOG , buffer);
-    }
-}
-
-
-void WOLFSSL_LEAVE(const char* msg, int ret)
-{
-    if (loggingEnabled) {
-        char buffer[WOLFSSL_MAX_ERROR_SZ];
-        XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d",
-                msg, ret);
-        wolfssl_log(LEAVE_LOG , buffer);
-    }
-}
-#endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */
-#endif /* DEBUG_WOLFSSL */
-
-/*
- * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is
- * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function
- * name where WOLFSSL_ERROR is called at.
- */
-#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \
-    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line,
-        const char* file, void* usrCtx)
-#else
-void WOLFSSL_ERROR(int error)
-#endif
-{
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (error != WC_PENDING_E)
-#endif
-    {
-        char buffer[WOLFSSL_MAX_ERROR_SZ];
-
-    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-        (void)usrCtx; /* a user ctx for future flexibility */
-        (void)func;
-
-        if (wc_LockMutex(&debug_mutex) != 0) {
-            WOLFSSL_MSG("Lock debug mutex failed");
-            XSNPRINTF(buffer, sizeof(buffer),
-                    "wolfSSL error occurred, error = %d", error);
-        }
-        else {
-            #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
-            /* If running in compatibility mode do not add want read and
-               want right to error queue */
-            if (error != WANT_READ && error != WANT_WRITE) {
-            #endif
-            if (error < 0)
-                error = error - (2 * error); /* get absolute value */
-            XSNPRINTF(buffer, sizeof(buffer),
-                    "wolfSSL error occurred, error = %d line:%d file:%s",
-                    error, line, file);
-            if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) {
-                WOLFSSL_MSG("Error creating logging node");
-                /* with void function there is no return here, continue on
-                 * to unlock mutex and log what buffer was created. */
-            }
-            #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
-            }
-            else {
-                XSNPRINTF(buffer, sizeof(buffer),
-                    "wolfSSL error occurred, error = %d", error);
-
-            }
-            #endif
-
-            wc_UnLockMutex(&debug_mutex);
-        }
-    #else
-        XSNPRINTF(buffer, sizeof(buffer),
-                "wolfSSL error occurred, error = %d", error);
-    #endif
-
-    #ifdef DEBUG_WOLFSSL
-        if (loggingEnabled)
-            wolfssl_log(ERROR_LOG , buffer);
-    #endif
-    }
-}
-
-void WOLFSSL_ERROR_MSG(const char* msg)
-{
-#ifdef DEBUG_WOLFSSL
-    if (loggingEnabled)
-        wolfssl_log(ERROR_LOG , msg);
-#else
-    (void)msg;
-#endif
-}
-
-#endif  /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-/* Internal function that is called by wolfCrypt_Init() */
-int wc_LoggingInit(void)
-{
-    if (wc_InitMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Bad Init Mutex");
-        return BAD_MUTEX_E;
-    }
-    wc_errors          = NULL;
-    wc_current_node    = NULL;
-    wc_last_node       = NULL;
-
-    return 0;
-}
-
-
-/* internal function that is called by wolfCrypt_Cleanup */
-int wc_LoggingCleanup(void)
-{
-    /* clear logging entries */
-    wc_ClearErrorNodes();
-
-    /* free mutex */
-    if (wc_FreeMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Bad Mutex free");
-        return BAD_MUTEX_E;
-    }
-    return 0;
-}
-
-
-/* peek at an error node
- *
- * idx : if -1 then the most recent node is looked at, otherwise search
- *         through queue for node at the given index
- * file  : pointer to internal file string
- * reason : pointer to internal error reason
- * line  : line number that error happened at
- *
- * Returns a negative value in error case, on success returns the nodes error
- * value which is positve (absolute value)
- */
-int wc_PeekErrorNode(int idx, const char **file, const char **reason,
-        int *line)
-{
-    struct wc_error_queue* err;
-
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return BAD_MUTEX_E;
-    }
-
-    if (idx < 0) {
-        err = wc_last_node;
-        if (err == NULL) {
-            WOLFSSL_MSG("No Errors in queue");
-            wc_UnLockMutex(&debug_mutex);
-            return BAD_STATE_E;
-        }
-    }
-    else {
-        int i;
-
-        err = (struct wc_error_queue*)wc_errors;
-        for (i = 0; i < idx; i++) {
-            if (err == NULL) {
-                WOLFSSL_MSG("Error node not found. Bad index?");
-                wc_UnLockMutex(&debug_mutex);
-                return BAD_FUNC_ARG;
-            }
-            err = err->next;
-        }
-    }
-
-    if (file != NULL) {
-        *file = err->file;
-    }
-
-    if (reason != NULL) {
-        *reason = err->error;
-    }
-
-    if (line != NULL) {
-        *line = err->line;
-    }
-
-    wc_UnLockMutex(&debug_mutex);
-
-    return err->value;
-}
-
-
-/* Pulls the current node from error queue and increments current state.
- * Note: this does not delete nodes because input arguments are pointing to
- *       node buffers.
- *
- * file   pointer to file that error was in. Can be NULL to return no file.
- * reason error string giving reason for error. Can be NULL to return no reason.
- * line   retrun line number of where error happened.
- *
- * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure
- */
-int wc_PullErrorNode(const char **file, const char **reason, int *line)
-{
-    struct wc_error_queue* err;
-    int value;
-
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return BAD_MUTEX_E;
-    }
-
-    err = wc_current_node;
-    if (err == NULL) {
-        WOLFSSL_MSG("No Errors in queue");
-        wc_UnLockMutex(&debug_mutex);
-        return BAD_STATE_E;
-    }
-
-    if (file != NULL) {
-        *file = err->file;
-    }
-
-    if (reason != NULL) {
-        *reason = err->error;
-    }
-
-    if (line != NULL) {
-        *line = err->line;
-    }
-
-    value = err->value;
-    wc_current_node = err->next;
-    wc_UnLockMutex(&debug_mutex);
-
-    return value;
-}
-
-
-/* create new error node and add it to the queue
- * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal
- * function. debug_mutex should be locked before a call to this function. */
-int wc_AddErrorNode(int error, int line, char* buf, char* file)
-{
-
-    struct wc_error_queue* err;
-
-    err = (struct wc_error_queue*)XMALLOC(
-            sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG);
-    if (err == NULL) {
-        WOLFSSL_MSG("Unable to create error node for log");
-        return MEMORY_E;
-    }
-    else {
-        int sz;
-
-        XMEMSET(err, 0, sizeof(struct wc_error_queue));
-        err->heap = wc_error_heap;
-        sz = (int)XSTRLEN(buf);
-        if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
-            sz = WOLFSSL_MAX_ERROR_SZ - 1;
-        }
-        if (sz > 0) {
-            XMEMCPY(err->error, buf, sz);
-        }
-
-        sz = (int)XSTRLEN(file);
-        if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
-            sz = WOLFSSL_MAX_ERROR_SZ - 1;
-        }
-        if (sz > 0) {
-            XMEMCPY(err->file, file, sz);
-        }
-
-        err->value = error;
-        err->line  = line;
-
-        /* make sure is terminated */
-        err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0';
-        err->file[WOLFSSL_MAX_ERROR_SZ - 1]  = '\0';
-
-
-        /* since is queue place new node at last of the list */
-        if (wc_last_node == NULL) {
-            /* case of first node added to queue */
-            if (wc_errors != NULL) {
-                /* check for unexpected case before over writing wc_errors */
-                WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n");
-            }
-            else {
-                wc_errors    = err;
-                wc_last_node = err;
-                wc_current_node = err;
-            }
-        }
-        else {
-            wc_last_node->next = err;
-            err->prev = wc_last_node;
-            wc_last_node = err;
-
-            /* check the case where have read to the end of the queue and the
-             * current node to read needs updated */
-            if (wc_current_node == NULL) {
-                wc_current_node = err;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/* Removes the error node at the specified index.
- * idx : if -1 then the most recent node is looked at, otherwise search
- *         through queue for node at the given index
- */
-void wc_RemoveErrorNode(int idx)
-{
-    struct wc_error_queue* current;
-
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return;
-    }
-
-    if (idx == -1)
-        current = wc_last_node;
-    else {
-        current = (struct wc_error_queue*)wc_errors;
-        for (; current != NULL && idx > 0; idx--)
-             current = current->next;
-    }
-    if (current != NULL) {
-        if (current->prev != NULL)
-            current->prev->next = current->next;
-        if (wc_last_node == current)
-            wc_last_node = current->prev;
-        if (wc_errors == current)
-            wc_errors = current->next;
-        XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
-    }
-
-    wc_UnLockMutex(&debug_mutex);
-}
-
-
-/* Clears out the list of error nodes.
- */
-void wc_ClearErrorNodes(void)
-{
-#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return;
-    }
-
-    /* free all nodes from error queue */
-    {
-        struct wc_error_queue* current;
-        struct wc_error_queue* next;
-
-        current = (struct wc_error_queue*)wc_errors;
-        while (current != NULL) {
-            next = current->next;
-            XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
-            current = next;
-        }
-    }
-
-    wc_errors    = NULL;
-    wc_last_node = NULL;
-    wc_UnLockMutex(&debug_mutex);
-#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */
-}
-
-int wc_SetLoggingHeap(void* h)
-{
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return BAD_MUTEX_E;
-    }
-    wc_error_heap = h;
-    wc_UnLockMutex(&debug_mutex);
-    return 0;
-}
-
-
-/* frees all nodes in the queue
- *
- * id  this is the thread id
- */
-int wc_ERR_remove_state(void)
-{
-    struct wc_error_queue* current;
-    struct wc_error_queue* next;
-
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-        return BAD_MUTEX_E;
-    }
-
-    /* free all nodes from error queue */
-    current = (struct wc_error_queue*)wc_errors;
-    while (current != NULL) {
-        next = current->next;
-        XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
-        current = next;
-    }
-
-    wc_errors          = NULL;
-    wc_last_node       = NULL;
-
-    wc_UnLockMutex(&debug_mutex);
-
-    return 0;
-}
-
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
-/* empties out the error queue into the file */
-void wc_ERR_print_errors_fp(XFILE fp)
-{
-    WOLFSSL_ENTER("wc_ERR_print_errors_fp");
-
-    if (wc_LockMutex(&debug_mutex) != 0) {
-        WOLFSSL_MSG("Lock debug mutex failed");
-    }
-    else {
-        /* free all nodes from error queue and print them to file */
-        {
-            struct wc_error_queue* current;
-            struct wc_error_queue* next;
-
-            current = (struct wc_error_queue*)wc_errors;
-            while (current != NULL) {
-                next = current->next;
-                fprintf(fp, "%s\n", current->error);
-                XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
-                current = next;
-            }
-
-            /* set global pointers to match having been freed */
-            wc_errors    = NULL;
-            wc_last_node = NULL;
-        }
-
-        wc_UnLockMutex(&debug_mutex);
-    }
-}
-#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */
-
-#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */
-
-
--- a/wolfcrypt/src/md2.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/* md2.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef WOLFSSL_MD2
-
-#include <wolfssl/wolfcrypt/md2.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-void wc_InitMd2(Md2* md2)
-{
-    XMEMSET(md2->X, 0, MD2_X_SIZE);
-    XMEMSET(md2->C, 0, MD2_BLOCK_SIZE);
-    XMEMSET(md2->buffer, 0, MD2_BLOCK_SIZE);
-    md2->count = 0;
-}
-
-
-void wc_Md2Update(Md2* md2, const byte* data, word32 len)
-{
-    static const byte S[256] =
-    {
-        41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
-        19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
-        76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
-        138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
-        245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
-        148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
-        39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
-        181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
-        150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
-        112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
-        96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
-        85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
-        234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
-        129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
-        8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
-        203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
-        166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
-        31, 26, 219, 153, 141, 51, 159, 17, 131, 20
-    };
-
-    while (len) {
-        word32 L = (MD2_PAD_SIZE - md2->count) < len ?
-                   (MD2_PAD_SIZE - md2->count) : len;
-        XMEMCPY(md2->buffer + md2->count, data, L);
-        md2->count += L;
-        data += L;
-        len  -= L;
-
-        if (md2->count == MD2_PAD_SIZE) {
-            int  i;
-            byte t;
-
-            md2->count = 0;
-            XMEMCPY(md2->X + MD2_PAD_SIZE, md2->buffer, MD2_PAD_SIZE);
-            t = md2->C[15];
-
-            for(i = 0; i < MD2_PAD_SIZE; i++) {
-                md2->X[32 + i] = md2->X[MD2_PAD_SIZE + i] ^ md2->X[i];
-                t = md2->C[i] ^= S[md2->buffer[i] ^ t];
-            }
-
-            t=0;
-            for(i = 0; i < 18; i++) {
-                int j;
-                for(j = 0; j < MD2_X_SIZE; j += 8) {
-                    t = md2->X[j+0] ^= S[t];
-                    t = md2->X[j+1] ^= S[t];
-                    t = md2->X[j+2] ^= S[t];
-                    t = md2->X[j+3] ^= S[t];
-                    t = md2->X[j+4] ^= S[t];
-                    t = md2->X[j+5] ^= S[t];
-                    t = md2->X[j+6] ^= S[t];
-                    t = md2->X[j+7] ^= S[t];
-                }
-                t = (t + i) & 0xFF;
-            }
-        }
-    }
-}
-
-
-void wc_Md2Final(Md2* md2, byte* hash)
-{
-    byte   padding[MD2_BLOCK_SIZE];
-    word32 padLen = MD2_PAD_SIZE - md2->count;
-    word32 i;
-
-    for (i = 0; i < padLen; i++)
-        padding[i] = (byte)padLen;
-
-    wc_Md2Update(md2, padding, padLen);
-    wc_Md2Update(md2, md2->C, MD2_BLOCK_SIZE);
-
-    XMEMCPY(hash, md2->X, MD2_DIGEST_SIZE);
-
-    wc_InitMd2(md2);
-}
-
-
-int wc_Md2Hash(const byte* data, word32 len, byte* hash)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    Md2* md2;
-#else
-    Md2 md2[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    md2 = (Md2*)XMALLOC(sizeof(Md2), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (md2 == NULL)
-        return MEMORY_E;
-#endif
-
-    wc_InitMd2(md2);
-    wc_Md2Update(md2, data, len);
-    wc_Md2Final(md2, hash);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(md2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-
-#endif /* WOLFSSL_MD2 */
-
-
--- a/wolfcrypt/src/md4.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/* md4.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_MD4
-
-#include <wolfssl/wolfcrypt/md4.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-void wc_InitMd4(Md4* md4)
-{
-    md4->digest[0] = 0x67452301L;
-    md4->digest[1] = 0xefcdab89L;
-    md4->digest[2] = 0x98badcfeL;
-    md4->digest[3] = 0x10325476L;
-
-    md4->buffLen = 0;
-    md4->loLen   = 0;
-    md4->hiLen   = 0;
-}
-
-
-static void Transform(Md4* md4)
-{
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-    /* Copy context->state[] to working vars  */
-    word32 A = md4->digest[0];
-    word32 B = md4->digest[1];
-    word32 C = md4->digest[2];
-    word32 D = md4->digest[3];
-
-#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+md4->buffer[k],s);
-    function(A,B,C,D, 0, 3);
-    function(D,A,B,C, 1, 7);
-    function(C,D,A,B, 2,11);
-    function(B,C,D,A, 3,19);
-    function(A,B,C,D, 4, 3);
-    function(D,A,B,C, 5, 7);
-    function(C,D,A,B, 6,11);
-    function(B,C,D,A, 7,19);
-    function(A,B,C,D, 8, 3);
-    function(D,A,B,C, 9, 7);
-    function(C,D,A,B,10,11);
-    function(B,C,D,A,11,19);
-    function(A,B,C,D,12, 3);
-    function(D,A,B,C,13, 7);
-    function(C,D,A,B,14,11);
-    function(B,C,D,A,15,19);
-
-#undef function
-#define function(a,b,c,d,k,s) \
-    a=rotlFixed(a+G(b,c,d)+md4->buffer[k]+0x5a827999,s);
-
-    function(A,B,C,D, 0, 3);
-    function(D,A,B,C, 4, 5);
-    function(C,D,A,B, 8, 9);
-    function(B,C,D,A,12,13);
-    function(A,B,C,D, 1, 3);
-    function(D,A,B,C, 5, 5);
-    function(C,D,A,B, 9, 9);
-    function(B,C,D,A,13,13);
-    function(A,B,C,D, 2, 3);
-    function(D,A,B,C, 6, 5);
-    function(C,D,A,B,10, 9);
-    function(B,C,D,A,14,13);
-    function(A,B,C,D, 3, 3);
-    function(D,A,B,C, 7, 5);
-    function(C,D,A,B,11, 9);
-    function(B,C,D,A,15,13);
-
-#undef function
-#define function(a,b,c,d,k,s) \
-    a=rotlFixed(a+H(b,c,d)+md4->buffer[k]+0x6ed9eba1,s);
-
-    function(A,B,C,D, 0, 3);
-    function(D,A,B,C, 8, 9);
-    function(C,D,A,B, 4,11);
-    function(B,C,D,A,12,15);
-    function(A,B,C,D, 2, 3);
-    function(D,A,B,C,10, 9);
-    function(C,D,A,B, 6,11);
-    function(B,C,D,A,14,15);
-    function(A,B,C,D, 1, 3);
-    function(D,A,B,C, 9, 9);
-    function(C,D,A,B, 5,11);
-    function(B,C,D,A,13,15);
-    function(A,B,C,D, 3, 3);
-    function(D,A,B,C,11, 9);
-    function(C,D,A,B, 7,11);
-    function(B,C,D,A,15,15);
-
-    /* Add the working vars back into digest state[]  */
-    md4->digest[0] += A;
-    md4->digest[1] += B;
-    md4->digest[2] += C;
-    md4->digest[3] += D;
-}
-
-
-static WC_INLINE void AddLength(Md4* md4, word32 len)
-{
-    word32 tmp = md4->loLen;
-    if ( (md4->loLen += len) < tmp)
-        md4->hiLen++;                       /* carry low to high */
-}
-
-
-void wc_Md4Update(Md4* md4, const byte* data, word32 len)
-{
-    /* do block size increments */
-    byte* local = (byte*)md4->buffer;
-
-    while (len) {
-        word32 add = min(len, MD4_BLOCK_SIZE - md4->buffLen);
-        XMEMCPY(&local[md4->buffLen], data, add);
-
-        md4->buffLen += add;
-        data         += add;
-        len          -= add;
-
-        if (md4->buffLen == MD4_BLOCK_SIZE) {
-            #ifdef BIG_ENDIAN_ORDER
-                ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
-            #endif
-            Transform(md4);
-            AddLength(md4, MD4_BLOCK_SIZE);
-            md4->buffLen = 0;
-        }
-    }
-}
-
-
-void wc_Md4Final(Md4* md4, byte* hash)
-{
-    byte* local = (byte*)md4->buffer;
-
-    AddLength(md4, md4->buffLen);               /* before adding pads */
-
-    local[md4->buffLen++] = 0x80;  /* add 1 */
-
-    /* pad with zeros */
-    if (md4->buffLen > MD4_PAD_SIZE) {
-        XMEMSET(&local[md4->buffLen], 0, MD4_BLOCK_SIZE - md4->buffLen);
-        md4->buffLen += MD4_BLOCK_SIZE - md4->buffLen;
-
-        #ifdef BIG_ENDIAN_ORDER
-            ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
-        #endif
-        Transform(md4);
-        md4->buffLen = 0;
-    }
-    XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen);
-
-    /* put lengths in bits */
-    md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) +
-                 (md4->hiLen << 3);
-    md4->loLen = md4->loLen << 3;
-
-    /* store lengths */
-    #ifdef BIG_ENDIAN_ORDER
-        ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE);
-    #endif
-    /* ! length ordering dependent on digest endian type ! */
-    XMEMCPY(&local[MD4_PAD_SIZE], &md4->loLen, sizeof(word32));
-    XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4->hiLen, sizeof(word32));
-
-    Transform(md4);
-    #ifdef BIG_ENDIAN_ORDER
-        ByteReverseWords(md4->digest, md4->digest, MD4_DIGEST_SIZE);
-    #endif
-    XMEMCPY(hash, md4->digest, MD4_DIGEST_SIZE);
-
-    wc_InitMd4(md4);  /* reset state */
-}
-
-
-#endif /* NO_MD4 */
-
-
--- a/wolfcrypt/src/md5.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,441 +0,0 @@
-/* md5.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if !defined(NO_MD5)
-
-#if defined(WOLFSSL_TI_HASH)
-    /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
-
-#else
-
-#include <wolfssl/wolfcrypt/md5.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* Hardware Acceleration */
-#if defined(STM32_HASH)
-
-    /* Supports CubeMX HAL or Standard Peripheral Library */
-	#define HAVE_MD5_CUST_API
-
-    int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
-    {
-        if (md5 == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        (void)devId;
-        (void)heap;
-
-        wc_Stm32_Hash_Init(&md5->stmCtx);
-
-        return 0;
-    }
-
-    int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
-    {
-        int ret;
-
-        if (md5 == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5,
-                data, len);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-    int wc_Md5Final(wc_Md5* md5, byte* hash)
-    {
-        int ret;
-
-        if (md5 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Final(&md5->stmCtx, HASH_AlgoSelection_MD5,
-                hash, WC_MD5_DIGEST_SIZE);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-
-        (void)wc_InitMd5(md5);  /* reset state */
-
-        return ret;
-    }
-
-#elif defined(FREESCALE_MMCAU_SHA)
-    #include "cau_api.h"
-    #define XTRANSFORM(S,B)  Transform((S), (B))
-
-    static int Transform(wc_Md5* md5, byte* data)
-    {
-        int ret = wolfSSL_CryptHwMutexLock();
-        if(ret == 0) {
-        #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-            cau_md5_hash_n(data, 1, (unsigned char*)md5->digest);
-        #else
-            MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest);
-        #endif
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-#elif defined(WOLFSSL_PIC32MZ_HASH)
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-    #define HAVE_MD5_CUST_API
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */
-    #define HAVE_MD5_CUST_API
-#else
-    #define NEED_SOFT_MD5
-
-#endif /* End Hardware Acceleration */
-
-
-#ifdef NEED_SOFT_MD5
-
-    #define XTRANSFORM(S,B)  Transform((S))
-
-    #define F1(x, y, z) (z ^ (x & (y ^ z)))
-    #define F2(x, y, z) F1(z, x, y)
-    #define F3(x, y, z) (x ^ y ^ z)
-    #define F4(x, y, z) (y ^ (x | ~z))
-
-    #define MD5STEP(f, w, x, y, z, data, s) \
-        w = rotlFixed(w + f(x, y, z) + data, s) + x
-
-    static int Transform(wc_Md5* md5)
-    {
-        /* Copy context->state[] to working vars  */
-        word32 a = md5->digest[0];
-        word32 b = md5->digest[1];
-        word32 c = md5->digest[2];
-        word32 d = md5->digest[3];
-
-        MD5STEP(F1, a, b, c, d, md5->buffer[0]  + 0xd76aa478,  7);
-        MD5STEP(F1, d, a, b, c, md5->buffer[1]  + 0xe8c7b756, 12);
-        MD5STEP(F1, c, d, a, b, md5->buffer[2]  + 0x242070db, 17);
-        MD5STEP(F1, b, c, d, a, md5->buffer[3]  + 0xc1bdceee, 22);
-        MD5STEP(F1, a, b, c, d, md5->buffer[4]  + 0xf57c0faf,  7);
-        MD5STEP(F1, d, a, b, c, md5->buffer[5]  + 0x4787c62a, 12);
-        MD5STEP(F1, c, d, a, b, md5->buffer[6]  + 0xa8304613, 17);
-        MD5STEP(F1, b, c, d, a, md5->buffer[7]  + 0xfd469501, 22);
-        MD5STEP(F1, a, b, c, d, md5->buffer[8]  + 0x698098d8,  7);
-        MD5STEP(F1, d, a, b, c, md5->buffer[9]  + 0x8b44f7af, 12);
-        MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17);
-        MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22);
-        MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122,  7);
-        MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12);
-        MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17);
-        MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22);
-
-        MD5STEP(F2, a, b, c, d, md5->buffer[1]  + 0xf61e2562,  5);
-        MD5STEP(F2, d, a, b, c, md5->buffer[6]  + 0xc040b340,  9);
-        MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14);
-        MD5STEP(F2, b, c, d, a, md5->buffer[0]  + 0xe9b6c7aa, 20);
-        MD5STEP(F2, a, b, c, d, md5->buffer[5]  + 0xd62f105d,  5);
-        MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453,  9);
-        MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14);
-        MD5STEP(F2, b, c, d, a, md5->buffer[4]  + 0xe7d3fbc8, 20);
-        MD5STEP(F2, a, b, c, d, md5->buffer[9]  + 0x21e1cde6,  5);
-        MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6,  9);
-        MD5STEP(F2, c, d, a, b, md5->buffer[3]  + 0xf4d50d87, 14);
-        MD5STEP(F2, b, c, d, a, md5->buffer[8]  + 0x455a14ed, 20);
-        MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905,  5);
-        MD5STEP(F2, d, a, b, c, md5->buffer[2]  + 0xfcefa3f8,  9);
-        MD5STEP(F2, c, d, a, b, md5->buffer[7]  + 0x676f02d9, 14);
-        MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20);
-
-        MD5STEP(F3, a, b, c, d, md5->buffer[5]  + 0xfffa3942,  4);
-        MD5STEP(F3, d, a, b, c, md5->buffer[8]  + 0x8771f681, 11);
-        MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16);
-        MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23);
-        MD5STEP(F3, a, b, c, d, md5->buffer[1]  + 0xa4beea44,  4);
-        MD5STEP(F3, d, a, b, c, md5->buffer[4]  + 0x4bdecfa9, 11);
-        MD5STEP(F3, c, d, a, b, md5->buffer[7]  + 0xf6bb4b60, 16);
-        MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23);
-        MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6,  4);
-        MD5STEP(F3, d, a, b, c, md5->buffer[0]  + 0xeaa127fa, 11);
-        MD5STEP(F3, c, d, a, b, md5->buffer[3]  + 0xd4ef3085, 16);
-        MD5STEP(F3, b, c, d, a, md5->buffer[6]  + 0x04881d05, 23);
-        MD5STEP(F3, a, b, c, d, md5->buffer[9]  + 0xd9d4d039,  4);
-        MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11);
-        MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16);
-        MD5STEP(F3, b, c, d, a, md5->buffer[2]  + 0xc4ac5665, 23);
-
-        MD5STEP(F4, a, b, c, d, md5->buffer[0]  + 0xf4292244,  6);
-        MD5STEP(F4, d, a, b, c, md5->buffer[7]  + 0x432aff97, 10);
-        MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15);
-        MD5STEP(F4, b, c, d, a, md5->buffer[5]  + 0xfc93a039, 21);
-        MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3,  6);
-        MD5STEP(F4, d, a, b, c, md5->buffer[3]  + 0x8f0ccc92, 10);
-        MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15);
-        MD5STEP(F4, b, c, d, a, md5->buffer[1]  + 0x85845dd1, 21);
-        MD5STEP(F4, a, b, c, d, md5->buffer[8]  + 0x6fa87e4f,  6);
-        MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10);
-        MD5STEP(F4, c, d, a, b, md5->buffer[6]  + 0xa3014314, 15);
-        MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21);
-        MD5STEP(F4, a, b, c, d, md5->buffer[4]  + 0xf7537e82,  6);
-        MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10);
-        MD5STEP(F4, c, d, a, b, md5->buffer[2]  + 0x2ad7d2bb, 15);
-        MD5STEP(F4, b, c, d, a, md5->buffer[9]  + 0xeb86d391, 21);
-
-        /* Add the working vars back into digest state[]  */
-        md5->digest[0] += a;
-        md5->digest[1] += b;
-        md5->digest[2] += c;
-        md5->digest[3] += d;
-
-        return 0;
-    }
-#endif /* NEED_SOFT_MD5 */
-
-#ifndef HAVE_MD5_CUST_API
-
-static WC_INLINE void AddLength(wc_Md5* md5, word32 len)
-{
-    word32 tmp = md5->loLen;
-    if ((md5->loLen += len) < tmp) {
-        md5->hiLen++;                       /* carry low to high */
-    }
-}
-
-static int _InitMd5(wc_Md5* md5)
-{
-    int ret = 0;
-
-    md5->digest[0] = 0x67452301L;
-    md5->digest[1] = 0xefcdab89L;
-    md5->digest[2] = 0x98badcfeL;
-    md5->digest[3] = 0x10325476L;
-
-    md5->buffLen = 0;
-    md5->loLen   = 0;
-    md5->hiLen   = 0;
-
-    return ret;
-}
-
-int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (md5 == NULL)
-        return BAD_FUNC_ARG;
-
-    md5->heap = heap;
-
-    ret = _InitMd5(md5);
-    if (ret != 0)
-        return ret;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
-    ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5,
-                                                            md5->heap, devId);
-#else
-    (void)devId;
-#endif
-    return ret;
-}
-
-int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
-{
-    int ret = 0;
-    byte* local;
-
-    if (md5 == NULL || (data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
-    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymMd5(&md5->asyncDev, NULL, data, len);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* do block size increments */
-    local = (byte*)md5->buffer;
-
-    /* check that internal buffLen is valid */
-    if (md5->buffLen >= WC_MD5_BLOCK_SIZE)
-        return BUFFER_E;
-
-    while (len) {
-        word32 add = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen);
-        XMEMCPY(&local[md5->buffLen], data, add);
-
-        md5->buffLen += add;
-        data         += add;
-        len          -= add;
-
-        if (md5->buffLen == WC_MD5_BLOCK_SIZE) {
-        #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-            ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
-        #endif
-            XTRANSFORM(md5, local);
-            AddLength(md5, WC_MD5_BLOCK_SIZE);
-            md5->buffLen = 0;
-        }
-    }
-    return ret;
-}
-
-int wc_Md5Final(wc_Md5* md5, byte* hash)
-{
-    byte* local;
-
-    if (md5 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
-    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymMd5(&md5->asyncDev, hash, NULL, WC_MD5_DIGEST_SIZE);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    local = (byte*)md5->buffer;
-
-    AddLength(md5, md5->buffLen);  /* before adding pads */
-    local[md5->buffLen++] = 0x80;  /* add 1 */
-
-    /* pad with zeros */
-    if (md5->buffLen > WC_MD5_PAD_SIZE) {
-        XMEMSET(&local[md5->buffLen], 0, WC_MD5_BLOCK_SIZE - md5->buffLen);
-        md5->buffLen += WC_MD5_BLOCK_SIZE - md5->buffLen;
-
-    #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-        ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
-    #endif
-        XTRANSFORM(md5, local);
-        md5->buffLen = 0;
-    }
-    XMEMSET(&local[md5->buffLen], 0, WC_MD5_PAD_SIZE - md5->buffLen);
-
-#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-    ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
-#endif
-
-    /* put lengths in bits */
-    md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) +
-                 (md5->hiLen << 3);
-    md5->loLen = md5->loLen << 3;
-
-    /* store lengths */
-    /* ! length ordering dependent on digest endian type ! */
-    XMEMCPY(&local[WC_MD5_PAD_SIZE], &md5->loLen, sizeof(word32));
-    XMEMCPY(&local[WC_MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32));
-
-    /* final transform and result to hash */
-    XTRANSFORM(md5, local);
-#ifdef BIG_ENDIAN_ORDER
-    ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE);
-#endif
-    XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE);
-
-    return _InitMd5(md5); /* reset state */
-}
-#endif /* !HAVE_MD5_CUST_API */
-
-
-int wc_InitMd5(wc_Md5* md5)
-{
-    if (md5 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return wc_InitMd5_ex(md5, NULL, INVALID_DEVID);
-}
-
-void wc_Md5Free(wc_Md5* md5)
-{
-    if (md5 == NULL)
-        return;
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
-    wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-int wc_Md5GetHash(wc_Md5* md5, byte* hash)
-{
-    int ret;
-    wc_Md5 tmpMd5;
-
-    if (md5 == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_Md5Copy(md5, &tmpMd5);
-    if (ret == 0) {
-        ret = wc_Md5Final(&tmpMd5, hash);
-    }
-
-    return ret;
-}
-
-int wc_Md5Copy(wc_Md5* src, wc_Md5* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Md5));
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-#ifdef WOLFSSL_PIC32MZ_HASH
-    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
-#endif
-
-    return ret;
-}
-
-#endif /* WOLFSSL_TI_HASH */
-#endif /* NO_MD5 */
-
--- a/wolfcrypt/src/memory.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,955 +0,0 @@
-/* memory.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-/* check old macros @wc_fips */
-#if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY)
-    #define USE_WOLFSSL_MEMORY
-#endif
-#if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK)
-    #define WOLFSSL_MALLOC_CHECK
-#endif
-
-#ifdef USE_WOLFSSL_MEMORY
-
-#include <wolfssl/wolfcrypt/memory.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL)
-    #include <stdio.h>
-#endif
-
-
-/* Set these to default values initially. */
-static wolfSSL_Malloc_cb  malloc_function = NULL;
-static wolfSSL_Free_cb    free_function = NULL;
-static wolfSSL_Realloc_cb realloc_function = NULL;
-
-int wolfSSL_SetAllocators(wolfSSL_Malloc_cb  mf,
-                          wolfSSL_Free_cb    ff,
-                          wolfSSL_Realloc_cb rf)
-{
-    int res = 0;
-
-    if (mf)
-        malloc_function = mf;
-    else
-        res = BAD_FUNC_ARG;
-
-    if (ff)
-        free_function = ff;
-    else
-        res = BAD_FUNC_ARG;
-
-    if (rf)
-        realloc_function = rf;
-    else
-        res = BAD_FUNC_ARG;
-
-    return res;
-}
-
-int wolfSSL_ResetAllocators(void)
-{
-    /* allow nulls to be set for callbacks to restore defaults */
-    malloc_function = NULL;
-    free_function = NULL;
-    realloc_function = NULL;
-
-    return 0;
-}
-
-int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*  mf,
-                          wolfSSL_Free_cb*    ff,
-                          wolfSSL_Realloc_cb* rf)
-{
-    if (mf) *mf = malloc_function;
-    if (ff) *ff = free_function;
-    if (rf) *rf = realloc_function;
-    return 0;
-}
-
-#ifndef WOLFSSL_STATIC_MEMORY
-#ifdef WOLFSSL_DEBUG_MEMORY
-void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
-#else
-void* wolfSSL_Malloc(size_t size)
-#endif
-{
-    void* res = 0;
-
-    if (malloc_function) {
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        res = malloc_function(size, func, line);
-    #else
-        res = malloc_function(size);
-    #endif
-    }
-    else {
-    #ifndef WOLFSSL_NO_MALLOC
-        res = malloc(size);
-    #else
-        WOLFSSL_MSG("No malloc available");
-    #endif
-    }
-
-    #ifdef WOLFSSL_MALLOC_CHECK
-        if (res == NULL)
-            puts("wolfSSL_malloc failed");
-    #endif
-
-    return res;
-}
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-void wolfSSL_Free(void *ptr, const char* func, unsigned int line)
-#else
-void wolfSSL_Free(void *ptr)
-#endif
-{
-    if (free_function) {
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        free_function(ptr, func, line);
-    #else
-        free_function(ptr);
-    #endif
-    }
-    else {
-    #ifndef WOLFSSL_NO_MALLOC
-        free(ptr);
-    #else
-        WOLFSSL_MSG("No free available");
-    #endif
-    }
-}
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line)
-#else
-void* wolfSSL_Realloc(void *ptr, size_t size)
-#endif
-{
-    void* res = 0;
-
-    if (realloc_function) {
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        res = realloc_function(ptr, size, func, line);
-    #else
-        res = realloc_function(ptr, size);
-    #endif
-    }
-    else {
-    #ifndef WOLFSSL_NO_MALLOC
-        res = realloc(ptr, size);
-    #else
-        WOLFSSL_MSG("No realloc available");
-    #endif
-    }
-
-    return res;
-}
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-#ifdef WOLFSSL_STATIC_MEMORY
-
-struct wc_Memory {
-    byte*  buffer;
-    struct wc_Memory* next;
-    word32 sz;
-};
-
-
-/* returns amount of memory used on success. On error returns negative value
-   wc_Memory** list is the list that new buckets are prepended to
- */
-static int create_memory_buckets(byte* buffer, word32 bufSz,
-                              word32 buckSz, word32 buckNum, wc_Memory** list) {
-    word32 i;
-    byte*  pt  = buffer;
-    int    ret = 0;
-    word32 memSz = (word32)sizeof(wc_Memory);
-    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
-
-    /* if not enough space available for bucket size then do not try */
-    if (buckSz + memSz + padSz > bufSz) {
-        return ret;
-    }
-
-    for (i = 0; i < buckNum; i++) {
-        if ((buckSz + memSz + padSz) <= (bufSz - ret)) {
-            /* create a new struct and set its values */
-            wc_Memory* mem = (struct wc_Memory*)(pt);
-            mem->sz = buckSz;
-            mem->buffer = (byte*)pt + padSz + memSz;
-            mem->next = NULL;
-
-            /* add the newly created struct to front of list */
-            if (*list == NULL) {
-                *list = mem;
-            } else {
-                mem->next = *list;
-                *list = mem;
-            }
-
-            /* advance pointer and keep track of memory used */
-            ret += buckSz + padSz + memSz;
-            pt  += buckSz + padSz + memSz;
-        }
-        else {
-            break; /* not enough space left for more buckets of this size */
-        }
-    }
-
-    return ret;
-}
-
-int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap)
-{
-    word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS };
-    word32 wc_Dist[WOLFMEM_DEF_BUCKETS]  = { WOLFMEM_DIST };
-
-    if (heap == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP));
-
-    XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz));
-    XMEMCPY(heap->distList, wc_Dist,  sizeof(wc_Dist));
-
-    if (wc_InitMutex(&(heap->memory_mutex)) != 0) {
-        WOLFSSL_MSG("Error creating heap memory mutex");
-        return BAD_MUTEX_E;
-    }
-
-    return 0;
-}
-
-int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
-    unsigned char* buf, unsigned int sz, int flag, int max)
-{
-    int ret;
-    WOLFSSL_HEAP*      heap;
-    WOLFSSL_HEAP_HINT* hint;
-    word32 idx = 0;
-
-    if (pHint == NULL || buf == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) {
-        return BUFFER_E; /* not enough memory for structures */
-    }
-
-    /* check if hint has already been assigned */
-    if (*pHint == NULL) {
-        heap = (WOLFSSL_HEAP*)buf;
-        idx += sizeof(WOLFSSL_HEAP);
-        hint = (WOLFSSL_HEAP_HINT*)(buf + idx);
-        idx += sizeof(WOLFSSL_HEAP_HINT);
-
-        ret = wolfSSL_init_memory_heap(heap);
-        if (ret != 0) {
-            return ret;
-        }
-
-        XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT));
-        hint->memory = heap;
-    }
-    else {
-    #ifdef WOLFSSL_HEAP_TEST
-        /* do not load in memory if test has been set */
-        if (heap == (void*)WOLFSSL_HEAP_TEST) {
-            return 0;
-        }
-    #endif
-
-        hint = (WOLFSSL_HEAP_HINT*)(*pHint);
-        heap = hint->memory;
-    }
-
-    ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap);
-    if (ret != 1) {
-        WOLFSSL_MSG("Error partitioning memory");
-        return -1;
-    }
-
-    /* determine what max applies too */
-    if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) {
-        heap->maxIO = max;
-    }
-    else { /* general memory used in handshakes */
-        heap->maxHa = max;
-    }
-
-    heap->flag |= flag;
-    *pHint = hint;
-
-    (void)max;
-
-    return 0;
-}
-
-int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag,
-                                                             WOLFSSL_HEAP* heap)
-{
-    word32 ava = sz;
-    byte*  pt  = buffer;
-    int    ret = 0;
-    word32 memSz = (word32)sizeof(wc_Memory);
-    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
-
-    WOLFSSL_ENTER("wolfSSL_load_static_memory");
-
-    if (buffer == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* align pt */
-    while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
-        *pt = 0x00;
-        pt++;
-        ava--;
-    }
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-    printf("Allocated %d bytes for static memory @ %p\n", ava, pt);
-#endif
-
-    /* devide into chunks of memory and add them to available list */
-    while (ava >= (heap->sizeList[0] + padSz + memSz)) {
-        int i;
-        /* creating only IO buffers from memory passed in, max TLS is 16k */
-        if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
-            if ((ret = create_memory_buckets(pt, ava,
-                                          WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) {
-                WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
-                return ret;
-            }
-
-            /* check if no more room left for creating IO buffers */
-            if (ret == 0) {
-                break;
-            }
-
-            /* advance pointer in buffer for next buckets and keep track
-               of how much memory is left available */
-            pt  += ret;
-            ava -= ret;
-        }
-        else {
-            /* start at largest and move to smaller buckets */
-            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
-                if ((heap->sizeList[i] + padSz + memSz) <= ava) {
-                    if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i],
-                                     heap->distList[i], &(heap->ava[i]))) < 0) {
-                        WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
-                        return ret;
-                    }
-
-                    /* advance pointer in buffer for next buckets and keep track
-                       of how much memory is left available */
-                    pt  += ret;
-                    ava -= ret;
-                }
-            }
-        }
-    }
-
-    return 1;
-}
-
-
-/* returns the size of management memory needed for each bucket.
- * This is memory that is used to keep track of and align memory buckets. */
-int wolfSSL_MemoryPaddingSz(void)
-{
-    word32 memSz = (word32)sizeof(wc_Memory);
-    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
-    return memSz + padSz;
-}
-
-
-/* Used to calculate memory size for optimum use with buckets.
-   returns the suggested size rounded down to the nearest bucket. */
-int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag)
-{
-    word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS};
-    word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST};
-
-    word32 ava = sz;
-    byte*  pt  = buffer;
-    word32 memSz = (word32)sizeof(wc_Memory);
-    word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1);
-
-    WOLFSSL_ENTER("wolfSSL_static_size");
-
-    if (buffer == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* align pt */
-    while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) {
-        pt++;
-        ava--;
-    }
-
-    /* creating only IO buffers from memory passed in, max TLS is 16k */
-    if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
-        if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) {
-            return 0; /* not enough room for even one bucket */
-        }
-
-        ava = ava % (memSz + padSz + WOLFMEM_IO_SZ);
-    }
-    else {
-        int i, k;
-
-        if (ava < (bucketSz[0] + padSz + memSz)) {
-            return 0; /* not enough room for even one bucket */
-        }
-
-        while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) {
-            /* start at largest and move to smaller buckets */
-            for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) {
-                for (k = distList[i]; k > 0; k--) {
-                    if ((bucketSz[i] + padSz + memSz) <= ava) {
-                        ava -= bucketSz[i] + padSz + memSz;
-                    }
-                }
-            }
-        }
-    }
-
-    return sz - ava; /* round down */
-}
-
-
-int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
-{
-    WOLFSSL_MSG("Freeing fixed IO buffer");
-
-    /* check if fixed buffer was set */
-    if (*io == NULL) {
-        return 1;
-    }
-
-    if (heap == NULL) {
-        WOLFSSL_MSG("No heap to return fixed IO too");
-    }
-    else {
-        /* put IO buffer back into IO pool */
-        (*io)->next = heap->io;
-        heap->io    = *io;
-        *io         = NULL;
-    }
-
-    return 1;
-}
-
-
-int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io)
-{
-    WOLFSSL_MSG("Setting fixed IO for SSL");
-    if (heap == NULL) {
-        return MEMORY_E;
-    }
-
-    *io = heap->io;
-
-    if (*io != NULL) {
-        heap->io = (*io)->next;
-        (*io)->next = NULL;
-    }
-    else { /* failed to grab an IO buffer */
-        return 0;
-    }
-
-    return 1;
-}
-
-
-int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats)
-{
-        word32     i;
-        wc_Memory* pt;
-
-        XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS));
-
-        stats->totalAlloc = heap->alloc;
-        stats->totalFr    = heap->frAlc;
-        stats->curAlloc   = stats->totalAlloc - stats->totalFr;
-        stats->maxHa      = heap->maxHa;
-        stats->maxIO      = heap->maxIO;
-        for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
-            stats->blockSz[i] = heap->sizeList[i];
-            for (pt = heap->ava[i]; pt != NULL; pt = pt->next) {
-                stats->avaBlock[i] += 1;
-            }
-        }
-
-        for (pt = heap->io; pt != NULL; pt = pt->next) {
-            stats->avaIO++;
-        }
-
-        stats->flag       = heap->flag; /* flag used */
-
-    return 1;
-}
-
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line)
-#else
-void* wolfSSL_Malloc(size_t size, void* heap, int type)
-#endif
-{
-    void* res = 0;
-    wc_Memory* pt = NULL;
-    int   i;
-
-    /* check for testing heap hint was set */
-#ifdef WOLFSSL_HEAP_TEST
-    if (heap == (void*)WOLFSSL_HEAP_TEST) {
-        return malloc(size);
-    }
-#endif
-
-    /* if no heap hint then use dynamic memory*/
-    if (heap == NULL) {
-        #ifdef WOLFSSL_HEAP_TEST
-            /* allow using malloc for creating ctx and method */
-            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
-                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
-                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
-                res = malloc(size);
-            }
-            else {
-                WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n");
-                res = NULL;
-            }
-        #else
-        #ifndef WOLFSSL_NO_MALLOC
-            #ifdef FREERTOS
-                res = pvPortMalloc(size);
-            #else
-                res = malloc(size);
-            #endif
-        #else
-            WOLFSSL_MSG("No heap hint found to use and no malloc");
-            #ifdef WOLFSSL_DEBUG_MEMORY
-            printf("ERROR: at %s:%d\n", func, line);
-            #endif
-        #endif /* WOLFSSL_NO_MALLOC */
-        #endif /* WOLFSSL_HEAP_TEST */
-    }
-    else {
-        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
-        WOLFSSL_HEAP*      mem  = hint->memory;
-
-        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
-            WOLFSSL_MSG("Bad memory_mutex lock");
-            return NULL;
-        }
-
-        /* case of using fixed IO buffers */
-        if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
-                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
-                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
-            if (type == DYNAMIC_TYPE_OUT_BUFFER) {
-                pt = hint->outBuf;
-            }
-            if (type == DYNAMIC_TYPE_IN_BUFFER) {
-                pt = hint->inBuf;
-            }
-        }
-        else {
-            /* check if using IO pool flag */
-            if (mem->flag & WOLFMEM_IO_POOL &&
-                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
-                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
-                if (mem->io != NULL) {
-                    pt      = mem->io;
-                    mem->io = pt->next;
-                }
-            }
-
-            /* general static memory */
-            if (pt == NULL) {
-                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
-                    if ((word32)size < mem->sizeList[i]) {
-                        if (mem->ava[i] != NULL) {
-                            pt = mem->ava[i];
-                            mem->ava[i] = pt->next;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        if (pt != NULL) {
-            mem->inUse += pt->sz;
-            mem->alloc += 1;
-            res = pt->buffer;
-
-        #ifdef WOLFSSL_DEBUG_MEMORY
-            printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
-        #endif
-
-            /* keep track of connection statistics if flag is set */
-            if (mem->flag & WOLFMEM_TRACK_STATS) {
-                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
-                if (stats != NULL) {
-                    stats->curMem += pt->sz;
-                    if (stats->peakMem < stats->curMem) {
-                        stats->peakMem = stats->curMem;
-                    }
-                    stats->curAlloc++;
-                    if (stats->peakAlloc < stats->curAlloc) {
-                        stats->peakAlloc = stats->curAlloc;
-                    }
-                    stats->totalAlloc++;
-                }
-            }
-        }
-        else {
-            WOLFSSL_MSG("ERROR ran out of static memory");
-            #ifdef WOLFSSL_DEBUG_MEMORY
-            printf("Looking for %lu bytes at %s:%d\n", size, func, line);
-            #endif
-        }
-
-        wc_UnLockMutex(&(mem->memory_mutex));
-    }
-
-    #ifdef WOLFSSL_MALLOC_CHECK
-        if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
-            WOLFSSL_MSG("ERROR memory is not alligned");
-            res = NULL;
-        }
-    #endif
-
-
-    (void)i;
-    (void)pt;
-    (void)type;
-
-    return res;
-}
-
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line)
-#else
-void wolfSSL_Free(void *ptr, void* heap, int type)
-#endif
-{
-    int i;
-    wc_Memory* pt;
-
-    if (ptr) {
-        /* check for testing heap hint was set */
-    #ifdef WOLFSSL_HEAP_TEST
-        if (heap == (void*)WOLFSSL_HEAP_TEST) {
-            return free(ptr);
-        }
-    #endif
-
-        if (heap == NULL) {
-        #ifdef WOLFSSL_HEAP_TEST
-            /* allow using malloc for creating ctx and method */
-            if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD ||
-                                            type == DYNAMIC_TYPE_CERT_MANAGER) {
-                WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n");
-            }
-            else {
-                WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n");
-            }
-        #endif
-        #ifndef WOLFSSL_NO_MALLOC
-            #ifdef FREERTOS
-                vPortFree(ptr);
-            #else
-                free(ptr);
-            #endif
-        #else
-            WOLFSSL_MSG("Error trying to call free when turned off");
-        #endif /* WOLFSSL_NO_MALLOC */
-        }
-        else {
-            WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
-            WOLFSSL_HEAP*      mem  = hint->memory;
-            word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
-
-            /* get memory struct and add it to available list */
-            pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz);
-            if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
-                WOLFSSL_MSG("Bad memory_mutex lock");
-                return;
-            }
-
-            /* case of using fixed IO buffers */
-            if (mem->flag & WOLFMEM_IO_POOL_FIXED &&
-                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
-                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
-                /* fixed IO pools are free'd at the end of SSL lifetime
-                   using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */
-            }
-            else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ &&
-                                             (type == DYNAMIC_TYPE_OUT_BUFFER ||
-                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
-                pt->next = mem->io;
-                mem->io  = pt;
-            }
-            else { /* general memory free */
-                for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
-                    if (pt->sz == mem->sizeList[i]) {
-                        pt->next = mem->ava[i];
-                        mem->ava[i] = pt;
-                        break;
-                    }
-                }
-            }
-            mem->inUse -= pt->sz;
-            mem->frAlc += 1;
-
-        #ifdef WOLFSSL_DEBUG_MEMORY
-            printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line);
-        #endif
-
-            /* keep track of connection statistics if flag is set */
-            if (mem->flag & WOLFMEM_TRACK_STATS) {
-                WOLFSSL_MEM_CONN_STATS* stats = hint->stats;
-                if (stats != NULL) {
-                    /* avoid under flow */
-                    if (stats->curMem > pt->sz) {
-                        stats->curMem -= pt->sz;
-                    }
-                    else {
-                        stats->curMem = 0;
-                    }
-
-                    if (stats->curAlloc > 0) {
-                        stats->curAlloc--;
-                    }
-                    stats->totalFr++;
-                }
-            }
-            wc_UnLockMutex(&(mem->memory_mutex));
-        }
-    }
-
-    (void)i;
-    (void)pt;
-    (void)type;
-}
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line)
-#else
-void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type)
-#endif
-{
-    void* res = 0;
-    wc_Memory* pt = NULL;
-    word32 prvSz;
-    int    i;
-
-    /* check for testing heap hint was set */
-#ifdef WOLFSSL_HEAP_TEST
-    if (heap == (void*)WOLFSSL_HEAP_TEST) {
-        return realloc(ptr, size);
-    }
-#endif
-
-    if (heap == NULL) {
-        #ifdef WOLFSSL_HEAP_TEST
-            WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n");
-        #endif
-        #ifndef WOLFSSL_NO_MALLOC
-            res = realloc(ptr, size);
-        #else
-            WOLFSSL_MSG("NO heap found to use for realloc");
-        #endif /* WOLFSSL_NO_MALLOC */
-    }
-    else {
-        WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
-        WOLFSSL_HEAP*      mem  = hint->memory;
-        word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1);
-
-        if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
-            WOLFSSL_MSG("Bad memory_mutex lock");
-            return NULL;
-        }
-
-        /* case of using fixed IO buffers or IO pool */
-        if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED))
-                                          && (type == DYNAMIC_TYPE_OUT_BUFFER ||
-                                              type == DYNAMIC_TYPE_IN_BUFFER)) {
-            /* no realloc, is fixed size */
-            pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory));
-            if (pt->sz < size) {
-                WOLFSSL_MSG("Error IO memory was not large enough");
-                res = NULL; /* return NULL in error case */
-            }
-            res = pt->buffer;
-        }
-        else {
-        /* general memory */
-            for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) {
-                if ((word32)size < mem->sizeList[i]) {
-                    if (mem->ava[i] != NULL) {
-                        pt = mem->ava[i];
-                        mem->ava[i] = pt->next;
-                        break;
-                    }
-                }
-            }
-
-            if (pt != NULL && res == NULL) {
-                res = pt->buffer;
-
-                /* copy over original information and free ptr */
-                prvSz = ((wc_Memory*)((byte*)ptr - padSz -
-                                               sizeof(wc_Memory)))->sz;
-                prvSz = (prvSz > pt->sz)? pt->sz: prvSz;
-                XMEMCPY(pt->buffer, ptr, prvSz);
-                mem->inUse += pt->sz;
-                mem->alloc += 1;
-
-                /* free memory that was previously being used */
-                wc_UnLockMutex(&(mem->memory_mutex));
-                wolfSSL_Free(ptr, heap, type
-            #ifdef WOLFSSL_DEBUG_MEMORY
-                    , func, line
-            #endif
-                );
-                if (wc_LockMutex(&(mem->memory_mutex)) != 0) {
-                    WOLFSSL_MSG("Bad memory_mutex lock");
-                    return NULL;
-                }
-            }
-        }
-        wc_UnLockMutex(&(mem->memory_mutex));
-    }
-
-    #ifdef WOLFSSL_MALLOC_CHECK
-        if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) {
-            WOLFSSL_MSG("ERROR memory is not alligned");
-            res = NULL;
-        }
-    #endif
-
-    (void)i;
-    (void)pt;
-    (void)type;
-
-    return res;
-}
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-#endif /* USE_WOLFSSL_MEMORY */
-
-
-#ifdef HAVE_IO_POOL
-
-/* Example for user io pool, shared build may need definitions in lib proper */
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <stdlib.h>
-
-#ifndef HAVE_THREAD_LS
-    #error "Oops, simple I/O pool example needs thread local storage"
-#endif
-
-
-/* allow simple per thread in and out pools */
-/* use 17k size since max record size is 16k plus overhead */
-static THREAD_LS_T byte pool_in[17*1024];
-static THREAD_LS_T byte pool_out[17*1024];
-
-
-void* XMALLOC(size_t n, void* heap, int type)
-{
-    (void)heap;
-
-    if (type == DYNAMIC_TYPE_IN_BUFFER) {
-        if (n < sizeof(pool_in))
-            return pool_in;
-        else
-            return NULL;
-    }
-
-    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
-        if (n < sizeof(pool_out))
-            return pool_out;
-        else
-            return NULL;
-    }
-
-    return malloc(n);
-}
-
-void* XREALLOC(void *p, size_t n, void* heap, int type)
-{
-    (void)heap;
-
-    if (type == DYNAMIC_TYPE_IN_BUFFER) {
-        if (n < sizeof(pool_in))
-            return pool_in;
-        else
-            return NULL;
-    }
-
-    if (type == DYNAMIC_TYPE_OUT_BUFFER) {
-        if (n < sizeof(pool_out))
-            return pool_out;
-        else
-            return NULL;
-    }
-
-    return realloc(p, n);
-}
-
-void XFREE(void *p, void* heap, int type)
-{
-    (void)heap;
-
-    if (type == DYNAMIC_TYPE_IN_BUFFER)
-        return;  /* do nothing, static pool */
-
-    if (type == DYNAMIC_TYPE_OUT_BUFFER)
-        return;  /* do nothing, static pool */
-
-    free(p);
-}
-
-#endif /* HAVE_IO_POOL */
-
-
--- a/wolfcrypt/src/misc.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/* misc.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLF_CRYPT_MISC_C
-#define WOLF_CRYPT_MISC_C
-
-#include <wolfssl/wolfcrypt/misc.h>
-
-/* inlining these functions is a huge speed increase and a small size decrease,
-   because the functions are smaller than function call setup/cleanup, e.g.,
-   md5 benchmark is twice as fast with inline.  If you don't want it, then
-   define NO_INLINE and compile this file into wolfssl, otherwise it's used as
-   a source header
- */
-
-#ifdef NO_INLINE
-    #define STATIC
-#else
-    #define STATIC static
-#endif
-
-/* Check for if compiling misc.c when not needed. */
-#if !defined(WOLFSSL_MISC_INCLUDED) && !defined(NO_INLINE)
-    #ifndef WOLFSSL_IGNORE_FILE_WARN
-        #warning misc.c does not need to be compiled when using inline (NO_INLINE not defined)
-    #endif
-
-#else
-
-
-#if defined(__ICCARM__)
-    #include <intrinsics.h>
-#endif
-
-
-#ifdef INTEL_INTRINSICS
-
-    #include <stdlib.h>      /* get intrinsic definitions */
-
-    /* for non visual studio probably need no long version, 32 bit only
-     * i.e., _rotl and _rotr */
-    #pragma intrinsic(_lrotl, _lrotr)
-
-    STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y)
-    {
-        return y ? _lrotl(x, y) : x;
-    }
-
-    STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
-    {
-        return y ? _lrotr(x, y) : x;
-    }
-
-#else /* generic */
-
-    STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y)
-    {
-        return (x << y) | (x >> (sizeof(y) * 8 - y));
-    }
-
-
-    STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
-    {
-        return (x >> y) | (x << (sizeof(y) * 8 - y));
-    }
-
-#endif
-
-
-STATIC WC_INLINE word32 ByteReverseWord32(word32 value)
-{
-#ifdef PPC_INTRINSICS
-    /* PPC: load reverse indexed instruction */
-    return (word32)__lwbrx(&value,0);
-#elif defined(__ICCARM__)
-    return (word32)__REV(value);
-#elif defined(KEIL_INTRINSICS)
-    return (word32)__rev(value);
-#elif defined(WOLF_ALLOW_BUILTIN) && \
-        defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3)
-    return (word32)__builtin_bswap32(value);
-#elif defined(FAST_ROTATE)
-    /* 5 instructions with rotate instruction, 9 without */
-    return (rotrFixed(value, 8U) & 0xff00ff00) |
-           (rotlFixed(value, 8U) & 0x00ff00ff);
-#else
-    /* 6 instructions with rotate instruction, 8 without */
-    value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
-    return rotlFixed(value, 16U);
-#endif
-}
-
-
-STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in,
-                                    word32 byteCount)
-{
-    word32 count = byteCount/(word32)sizeof(word32), i;
-
-    for (i = 0; i < count; i++)
-        out[i] = ByteReverseWord32(in[i]);
-
-}
-
-
-#ifdef WORD64_AVAILABLE
-
-
-STATIC WC_INLINE word64 rotlFixed64(word64 x, word64 y)
-{
-    return (x << y) | (x >> (sizeof(y) * 8 - y));
-}
-
-
-STATIC WC_INLINE word64 rotrFixed64(word64 x, word64 y)
-{
-    return (x >> y) | (x << (sizeof(y) * 8 - y));
-}
-
-
-STATIC WC_INLINE word64 ByteReverseWord64(word64 value)
-{
-#if defined(WOLF_ALLOW_BUILTIN) && defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3)
-    return (word64)__builtin_bswap64(value);
-#elif defined(WOLFCRYPT_SLOW_WORD64)
-	return (word64)((word64)ByteReverseWord32((word32) value)) << 32 |
-                    (word64)ByteReverseWord32((word32)(value   >> 32));
-#else
-	value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) |
-            ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
-	value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) |
-            ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
-	return rotlFixed64(value, 32U);
-#endif
-}
-
-
-STATIC WC_INLINE void ByteReverseWords64(word64* out, const word64* in,
-                                      word32 byteCount)
-{
-    word32 count = byteCount/(word32)sizeof(word64), i;
-
-    for (i = 0; i < count; i++)
-        out[i] = ByteReverseWord64(in[i]);
-
-}
-
-#endif /* WORD64_AVAILABLE */
-
-
-STATIC WC_INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n)
-{
-    word32 i;
-
-    for (i = 0; i < n; i++) r[i] ^= a[i];
-}
-
-
-STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count)
-{
-    if (((wolfssl_word)buf | (wolfssl_word)mask | count) % WOLFSSL_WORD_SIZE == 0)
-        XorWords( (wolfssl_word*)buf,
-                  (const wolfssl_word*)mask, count / WOLFSSL_WORD_SIZE);
-    else {
-        word32 i;
-        byte*       b = (byte*)buf;
-        const byte* m = (const byte*)mask;
-
-        for (i = 0; i < count; i++) b[i] ^= m[i];
-    }
-}
-
-
-/* Make sure compiler doesn't skip */
-STATIC WC_INLINE void ForceZero(const void* mem, word32 len)
-{
-    volatile byte* z = (volatile byte*)mem;
-
-#if defined(WOLFSSL_X86_64_BUILD) && defined(WORD64_AVAILABLE)
-    volatile word64* w;
-    #ifndef WOLFSSL_UNALIGNED_64BIT_ACCESS
-        word32 l = (sizeof(word64) - ((size_t)z & (sizeof(word64)-1))) &
-                                                             (sizeof(word64)-1);
-
-        if (len < l) l = len;
-        len -= l;
-        while (l--) *z++ = 0;
-    #endif
-    for (w = (volatile word64*)z; len >= sizeof(*w); len -= sizeof(*w))
-        *w++ = 0;
-    z = (volatile byte*)w;
-#endif
-
-    while (len--) *z++ = 0;
-}
-
-
-/* check all length bytes for equality, return 0 on success */
-STATIC WC_INLINE int ConstantCompare(const byte* a, const byte* b, int length)
-{
-    int i;
-    int compareSum = 0;
-
-    for (i = 0; i < length; i++) {
-        compareSum |= a[i] ^ b[i];
-    }
-
-    return compareSum;
-}
-
-
-#ifndef WOLFSSL_HAVE_MIN
-    #define WOLFSSL_HAVE_MIN
-    #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */
-        #define min min
-    #endif
-    STATIC WC_INLINE word32 min(word32 a, word32 b)
-    {
-        return a > b ? b : a;
-    }
-#endif /* !WOLFSSL_HAVE_MIN */
-
-#ifndef WOLFSSL_HAVE_MAX
-    #define WOLFSSL_HAVE_MAX
-    #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */
-        #define max max
-    #endif
-    STATIC WC_INLINE word32 max(word32 a, word32 b)
-    {
-        return a > b ? a : b;
-    }
-#endif /* !WOLFSSL_HAVE_MAX */
-
-/* converts a 32 bit integer to 24 bit */
-STATIC WC_INLINE void c32to24(word32 in, word24 out)
-{
-    out[0] = (in >> 16) & 0xff;
-    out[1] = (in >>  8) & 0xff;
-    out[2] =  in & 0xff;
-}
-
-/* convert 16 bit integer to opaque */
-STATIC WC_INLINE void c16toa(word16 wc_u16, byte* c)
-{
-    c[0] = (wc_u16 >> 8) & 0xff;
-    c[1] =  wc_u16 & 0xff;
-}
-
-/* convert 32 bit integer to opaque */
-STATIC WC_INLINE void c32toa(word32 wc_u32, byte* c)
-{
-    c[0] = (wc_u32 >> 24) & 0xff;
-    c[1] = (wc_u32 >> 16) & 0xff;
-    c[2] = (wc_u32 >>  8) & 0xff;
-    c[3] =  wc_u32 & 0xff;
-}
-
-/* convert a 24 bit integer into a 32 bit one */
-STATIC WC_INLINE void c24to32(const word24 wc_u24, word32* wc_u32)
-{
-    *wc_u32 = (wc_u24[0] << 16) | (wc_u24[1] << 8) | wc_u24[2];
-}
-
-
-/* convert opaque to 24 bit integer */
-STATIC WC_INLINE void ato24(const byte* c, word32* wc_u24)
-{
-    *wc_u24 = (c[0] << 16) | (c[1] << 8) | c[2];
-}
-
-/* convert opaque to 16 bit integer */
-STATIC WC_INLINE void ato16(const byte* c, word16* wc_u16)
-{
-    *wc_u16 = (word16) ((c[0] << 8) | (c[1]));
-}
-
-/* convert opaque to 32 bit integer */
-STATIC WC_INLINE void ato32(const byte* c, word32* wc_u32)
-{
-    *wc_u32 = ((word32)c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
-}
-
-
-STATIC WC_INLINE word32 btoi(byte b)
-{
-    return (word32)(b - 0x30);
-}
-
-
-/* Constant time - mask set when a > b. */
-STATIC WC_INLINE byte ctMaskGT(int a, int b)
-{
-    return (((word32)a - b - 1) >> 31) - 1;
-}
-
-/* Constant time - mask set when a >= b. */
-STATIC WC_INLINE byte ctMaskGTE(int a, int b)
-{
-    return (((word32)a - b    ) >> 31) - 1;
-}
-
-/* Constant time - mask set when a < b. */
-STATIC WC_INLINE byte ctMaskLT(int a, int b)
-{
-    return (((word32)b - a - 1) >> 31) - 1;
-}
-
-/* Constant time - mask set when a <= b. */
-STATIC WC_INLINE byte ctMaskLTE(int a, int b)
-{
-    return (((word32)b - a    ) >> 31) - 1;
-}
-
-/* Constant time - mask set when a == b. */
-STATIC WC_INLINE byte ctMaskEq(int a, int b)
-{
-    return 0 - (a == b);
-}
-
-/* Constant time - select b when mask is set and a otherwise. */
-STATIC WC_INLINE byte ctMaskSel(byte m, byte a, byte b)
-{
-    return (a & ((byte)~(word32)m)) | (b & m);
-}
-
-/* Constant time - bit set when a <= b. */
-STATIC WC_INLINE byte ctSetLTE(int a, int b)
-{
-    return ((word32)a - b - 1) >> 31;
-}
-
-
-#undef STATIC
-
-#endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */
-
-#endif /* WOLF_CRYPT_MISC_C */
-
--- a/wolfcrypt/src/pkcs12.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2077 +0,0 @@
-/* pkcs12.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if !defined(NO_ASN) && !defined(NO_PWDBASED)
-
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/asn_public.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/hmac.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-#include <wolfssl/wolfcrypt/pkcs12.h>
-#include <wolfssl/wolfcrypt/pwdbased.h>
-#include <wolfssl/wolfcrypt/hash.h>
-
-
-#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
-
-enum {
-    WC_PKCS12_KeyBag = 667,
-    WC_PKCS12_ShroudedKeyBag = 668,
-    WC_PKCS12_CertBag = 669,
-    WC_PKCS12_CertBag_Type1 = 675,
-    WC_PKCS12_CrlBag = 670,
-    WC_PKCS12_SecretBag = 671,
-    WC_PKCS12_SafeContentsBag = 672,
-    WC_PKCS12_DATA = 651,
-    WC_PKCS12_ENCRYPTED_DATA = 656,
-
-    WC_PKCS12_DATA_OBJ_SZ = 11,
-};
-
-/* static const byte WC_PKCS12_ENCRYPTED_OID[] =
-                         {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; */
-static const byte WC_PKCS12_DATA_OID[] =
-                         {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01};
-static const byte WC_PKCS12_CertBag_Type1_OID[] =
-                   {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01};
-static const byte WC_PKCS12_CertBag_OID[] =
-             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03};
-static const byte WC_PKCS12_KeyBag_OID[] =
-             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01};
-static const byte WC_PKCS12_ShroudedKeyBag_OID[] =
-             {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02};
-
-
-typedef struct ContentInfo {
-    byte* data;
-    struct ContentInfo* next;
-    word32 encC;  /* encryptedContent */
-    word32 dataSz;
-    int type; /* DATA / encrypted / envelpoed */
-} ContentInfo;
-
-
-typedef struct AuthenticatedSafe {
-    ContentInfo* CI;
-    byte* data; /* T contents.... */
-    word32 oid; /* encrypted or not */
-    word32 numCI; /* number of Content Info structs */
-    word32 dataSz;
-} AuthenticatedSafe;
-
-
-typedef struct MacData {
-    byte* digest;
-    byte* salt;
-    word32 oid;
-    word32 digestSz;
-    word32 saltSz;
-    int itt; /* number of itterations when creating HMAC key */
-} MacData;
-
-
-struct WC_PKCS12 {
-    void* heap;
-    AuthenticatedSafe* safe;
-    MacData* signData;
-    word32 oid; /* DATA / Enveloped DATA ... */
-};
-
-
-/* for friendlyName, localKeyId .... */
-typedef struct WC_PKCS12_ATTRIBUTE {
-    byte* data;
-    word32 oid;
-    word32 dataSz;
-} WC_PKCS12_ATTRIBUTE;
-
-
-WC_PKCS12* wc_PKCS12_new(void)
-{
-    WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12),
-                                                      NULL, DYNAMIC_TYPE_PKCS);
-    if (pkcs12 == NULL) {
-        WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct");
-        return NULL;
-    }
-
-    XMEMSET(pkcs12, 0, sizeof(WC_PKCS12));
-
-    return pkcs12;
-}
-
-
-static void freeSafe(AuthenticatedSafe* safe, void* heap)
-{
-    int i;
-
-    if (safe == NULL) {
-        return;
-    }
-
-    /* free content info structs */
-    for (i = safe->numCI; i > 0; i--) {
-        ContentInfo* ci = safe->CI;
-        safe->CI = ci->next;
-        XFREE(ci, heap, DYNAMIC_TYPE_PKCS);
-    }
-    if (safe->data != NULL) {
-        XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS);
-    }
-    XFREE(safe, heap, DYNAMIC_TYPE_PKCS);
-
-    (void)heap;
-}
-
-
-void wc_PKCS12_free(WC_PKCS12* pkcs12)
-{
-    void* heap;
-
-    /* if null pointer is passed in do nothing */
-    if (pkcs12 == NULL) {
-        WOLFSSL_MSG("Trying to free null WC_PKCS12 object");
-        return;
-    }
-
-    heap = pkcs12->heap;
-    if (pkcs12->safe != NULL) {
-    	freeSafe(pkcs12->safe, heap);
-    }
-
-    /* free mac data */
-    if (pkcs12->signData != NULL) {
-        if (pkcs12->signData->digest != NULL) {
-            XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST);
-            pkcs12->signData->digest = NULL;
-        }
-        if (pkcs12->signData->salt != NULL) {
-            XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT);
-            pkcs12->signData->salt = NULL;
-        }
-        XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS);
-        pkcs12->signData = NULL;
-    }
-
-    XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS);
-    pkcs12 = NULL;
-}
-
-
-static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input,
-                          word32* idx, int maxIdx)
-{
-    AuthenticatedSafe* safe;
-    word32 oid;
-    word32 localIdx = *idx;
-    int ret;
-    int size = 0;
-
-    safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap,
-                                       DYNAMIC_TYPE_PKCS);
-    if (safe == NULL) {
-        return MEMORY_E;
-    }
-    XMEMSET(safe, 0, sizeof(AuthenticatedSafe));
-
-    ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx);
-    if (ret < 0) {
-        WOLFSSL_LEAVE("Get object id failed", ret);
-        freeSafe(safe, pkcs12->heap);
-        return ASN_PARSE_E;
-    }
-
-    safe->oid = oid;
-    /* check tag, length */
-    if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-        WOLFSSL_MSG("Unexpected tag in PKCS12 DER");
-        freeSafe(safe, pkcs12->heap);
-        return ASN_PARSE_E;
-    }
-    if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) {
-        freeSafe(safe, pkcs12->heap);
-        return ret;
-    }
-
-    switch (oid) {
-        case WC_PKCS12_ENCRYPTED_DATA:
-            WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n");
-            break;
-
-        case WC_PKCS12_DATA:
-            WOLFSSL_MSG("Found PKCS12 OBJECT: DATA");
-            /* get octets holding contents */
-            if (input[localIdx++] != ASN_OCTET_STRING) {
-                WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA");
-                freeSafe(safe, pkcs12->heap);
-                return ASN_PARSE_E;
-            }
-            if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) {
-                freeSafe(safe, pkcs12->heap);
-                return ret;
-            }
-
-            break;
-    }
-
-    safe->dataSz = size;
-    safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-    if (safe->data == NULL) {
-        freeSafe(safe, pkcs12->heap);
-        return MEMORY_E;
-    }
-    XMEMCPY(safe->data, input + localIdx, size);
-    *idx = localIdx;
-
-    /* an instance of AuthenticatedSafe is created from
-     * ContentInfo's strung together in a SEQUENCE. Here we itterate
-     * through the ContentInfo's and add them to our
-     * AuthenticatedSafe struct */
-    localIdx = 0;
-    input = safe->data;
-    {
-        int CISz;
-        ret = GetSequence(input, &localIdx, &CISz, safe->dataSz);
-        if (ret < 0) {
-            freeSafe(safe, pkcs12->heap);
-            return ASN_PARSE_E;
-        }
-        CISz += localIdx;
-        while ((int)localIdx < CISz) {
-            int curSz = 0;
-            word32 curIdx;
-            ContentInfo* ci = NULL;
-
-        #ifdef WOLFSSL_DEBUG_PKCS12
-            printf("\t\tlooking for Content Info.... ");
-        #endif
-
-            if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz))
-                                                                          < 0) {
-                freeSafe(safe, pkcs12->heap);
-                return ret;
-            }
-
-            if (curSz > CISz) {
-                /* subset should not be larger than universe */
-                freeSafe(safe, pkcs12->heap);
-                return ASN_PARSE_E;
-            }
-
-            curIdx = localIdx;
-            if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType,
-                                                           safe->dataSz)) < 0) {
-                WOLFSSL_LEAVE("Get object id failed", ret);
-                freeSafe(safe, pkcs12->heap);
-                return ret;
-            }
-
-            /* create new content info struct ... possible OID sanity check? */
-            ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap,
-                                       DYNAMIC_TYPE_PKCS);
-            if (ci == NULL) {
-                freeSafe(safe, pkcs12->heap);
-                return MEMORY_E;
-            }
-
-            ci->type   = oid;
-            ci->dataSz = curSz - (localIdx-curIdx);
-            ci->data   = (byte*)input + localIdx;
-            localIdx  += ci->dataSz;
-
-        #ifdef WOLFSSL_DEBUG_PKCS12
-            switch (oid) {
-                case WC_PKCS12_ENCRYPTED_DATA:
-                    printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz);
-                    break;
-
-                case WC_PKCS12_DATA:
-                    printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz);
-                    break;
-                default:
-                    printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz);
-            }
-        #endif
-
-            /* insert to head of list */
-            ci->next = safe->CI;
-            safe->CI = ci;
-            safe->numCI += 1;
-        }
-    }
-
-    pkcs12->safe = safe;
-    *idx += localIdx;
-
-    return ret;
-}
-
-
-/* optional mac data */
-static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx,
-                       word32 totalSz)
-{
-    MacData* mac;
-    word32 curIdx = *idx;
-    word32 oid = 0;
-    int size, ret;
-
-    /* Digest Info : Sequence
-     *      DigestAlgorithmIdentifier
-     *      Digest
-     */
-    if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) {
-        WOLFSSL_MSG("Failed to get PKCS12 sequence");
-        return ret;
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("\t\tSEQUENCE: DigestInfo size = %d\n", size);
-#endif
-
-    mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS);
-    if (mac == NULL) {
-        return MEMORY_E;
-    }
-    XMEMSET(mac, 0, sizeof(MacData));
-
-    /* DigestAlgorithmIdentifier */
-    if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) {
-        WOLFSSL_MSG("Failed to get PKCS12 sequence");
-        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-        return ret;
-    }
-    mac->oid = oid;
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("\t\tALGO ID = %d\n", oid);
-#endif
-
-    /* Digest: should be octet type holding digest */
-    if (mem[curIdx++] != ASN_OCTET_STRING) {
-        WOLFSSL_MSG("Failed to get digest");
-        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-        return ASN_PARSE_E;
-    }
-
-    if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) {
-        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-        return ret;
-    }
-    mac->digestSz = size;
-    mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap,
-                                 DYNAMIC_TYPE_DIGEST);
-    if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) {
-        ERROR_OUT(MEMORY_E, exit_gsd);
-    }
-    XMEMCPY(mac->digest, mem + curIdx, mac->digestSz);
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    {
-        byte* p;
-        for (printf("\t\tDigest = "), p = (byte*)mem+curIdx;
-             p < (byte*)mem + curIdx + mac->digestSz;
-             printf("%02X", *p), p++);
-        printf(" : size = %d\n", mac->digestSz);
-    }
-#endif
-
-    curIdx += mac->digestSz;
-
-    /* get salt, should be octet string */
-    if (mem[curIdx++] != ASN_OCTET_STRING) {
-        WOLFSSL_MSG("Failed to get salt");
-        ERROR_OUT(ASN_PARSE_E, exit_gsd);
-    }
-
-    if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) {
-        goto exit_gsd;
-    }
-    mac->saltSz = size;
-    mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT);
-    if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) {
-        ERROR_OUT(MEMORY_E, exit_gsd);
-    }
-    XMEMCPY(mac->salt, mem + curIdx, mac->saltSz);
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    {
-        byte* p;
-        for (printf("\t\tSalt = "), p = (byte*)mem + curIdx;
-             p < (byte*)mem + curIdx + mac->saltSz;
-             printf("%02X", *p), p++);
-        printf(" : size = %d\n", mac->saltSz);
-    }
-#endif
-
-    curIdx += mac->saltSz;
-
-    /* check for MAC iterations, default to 1 */
-    mac->itt = WC_PKCS12_MAC_DEFAULT;
-    if (curIdx < totalSz) {
-        int number = 0;
-        if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) {
-            /* found a iteration value */
-            mac->itt = number;
-        }
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("\t\tITTERATIONS : %d\n", mac->itt);
-#endif
-
-    *idx = curIdx;
-    pkcs12->signData = mac;
-    ret = 0; /* success */
-
-exit_gsd:
-
-    /* failure cleanup */
-    if (ret != 0) {
-        if (mac) {
-            if (mac->digest)
-                XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST);
-            XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-        }
-    }
-
-    return ret;
-}
-
-
-/* expects PKCS12 signData to be set up with OID
- *
- * returns the size of mac created on success. A negative value will be returned
- *         in the case that an error happened.
- */
-static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
-                         const byte* psw, word32 pswSz, byte* out, word32 outSz)
-{
-    Hmac     hmac;
-    MacData* mac;
-    int ret, kLen;
-    enum wc_HashType hashT;
-    int idx = 0;
-    int id  = 3; /* value from RFC 7292 indicating key is used for MAC */
-    word32 i;
-    byte unicodePasswd[MAX_UNICODE_SZ];
-    byte key[MAX_KEY_SIZE];
-
-    if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL ||
-            out == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    mac = pkcs12->signData;
-
-    /* unicode set up from asn.c */
-    if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
-        WOLFSSL_MSG("PKCS12 max unicode size too small");
-        return UNICODE_SIZE_E;
-    }
-
-    for (i = 0; i < pswSz; i++) {
-        unicodePasswd[idx++] = 0x00;
-        unicodePasswd[idx++] = (byte)psw[i];
-    }
-    /* add trailing NULL */
-    unicodePasswd[idx++] = 0x00;
-    unicodePasswd[idx++] = 0x00;
-
-    /* get hash type used and resulting size of HMAC key */
-    hashT = wc_OidGetHash(mac->oid);
-    if (hashT == WC_HASH_TYPE_NONE) {
-        WOLFSSL_MSG("Unsupported hash used");
-        return BAD_FUNC_ARG;
-    }
-    kLen = wc_HashGetDigestSize(hashT);
-
-    /* check out buffer is large enough */
-    if (kLen < 0 || outSz < (word32)kLen) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* idx contains size of unicodePasswd */
-    if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt,
-              mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) {
-        return ret;
-    }
-
-    /* now that key has been created use it to get HMAC hash on data */
-    if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) {
-        return ret;
-    }
-    ret = wc_HmacSetKey(&hmac, (int)hashT, key, kLen);
-    if (ret == 0)
-        ret = wc_HmacUpdate(&hmac, data, dataSz);
-    if (ret == 0)
-        ret = wc_HmacFinal(&hmac, out);
-    wc_HmacFree(&hmac);
-
-    if (ret != 0)
-        return ret;
-
-    return kLen; /* same as digest size */
-}
-
-
-/* check mac on pkcs12, pkcs12->mac has been sanity checked before entering *
- * returns the result of comparison, success is 0 */
-static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
-                            const byte* psw, word32 pswSz)
-{
-    MacData* mac;
-    int ret;
-    byte digest[WC_MAX_DIGEST_SIZE];
-
-    if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    mac = pkcs12->signData;
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("Verifying MAC with OID = %d\n", mac->oid);
-#endif
-
-    /* check if this builds digest size is too small */
-    if (mac->digestSz > WC_MAX_DIGEST_SIZE) {
-        WOLFSSL_MSG("PKCS12 max digest size too small");
-        return BAD_FUNC_ARG;
-    }
-
-    if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz,
-            digest, WC_MAX_DIGEST_SIZE)) < 0) {
-        return ret;
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    {
-        byte* p;
-        for (printf("\t\tHash = "), p = (byte*)digest;
-             p < (byte*)digest + mac->digestSz;
-             printf("%02X", *p), p++);
-        printf(" : size = %d\n", mac->digestSz);
-    }
-#endif
-
-    return XMEMCMP(digest, mac->digest, mac->digestSz);
-}
-
-
-/* Convert DER format stored in der buffer to WC_PKCS12 struct
- * Puts the raw contents of Content Info into structure without completly
- * parsing or decoding.
- * der    : pointer to der buffer holding PKCS12
- * derSz  : size of der buffer
- * pkcs12 : non-null pkcs12 pointer
- * return 0 on success and negative on failure.
- */
-int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12)
-{
-    word32 idx  = 0;
-    word32 totalSz = 0;
-    int ret;
-    int size    = 0;
-    int version = 0;
-
-    WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
-
-    if (der == NULL || pkcs12 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    totalSz = derSz;
-    if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) {
-        WOLFSSL_MSG("Failed to get PKCS12 sequence");
-        return ret;
-    }
-
-    /* get version */
-    if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) {
-        return ret;
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("\nBEGIN: PKCS12 size = %d\n", totalSz);
-    printf("version = %d\n", version);
-#endif
-
-    if (version != 3) {
-        WOLFSSL_MSG("PKCS12 unsupported version!");
-        return ASN_VERSION_E;
-    }
-
-    if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
-        return ret;
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size);
-#endif
-
-    if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) {
-        WOLFSSL_MSG("GetSafeContent error");
-        return ret;
-    }
-
-    /* if more buffer left check for MAC data */
-    if (idx < totalSz) {
-        if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) {
-            WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer");
-        }
-        else {
-        #ifdef WOLFSSL_DEBUG_PKCS12
-            printf("\tSEQUENCE: Signature size = %d\n", size);
-        #endif
-
-            if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) {
-                return ASN_PARSE_E;
-            }
-        }
-    }
-
-#ifdef WOLFSSL_DEBUG_PKCS12
-    printf("END: PKCS12\n");
-#endif
-
-    return ret;
-}
-
-
-/* helper function to free WC_DerCertList */
-void wc_FreeCertList(WC_DerCertList* list, void* heap)
-{
-    WC_DerCertList* current = list;
-    WC_DerCertList* next;
-
-    if (list == NULL) {
-        return;
-    }
-
-    while (current != NULL) {
-        next = current->next;
-        if (current->buffer != NULL) {
-            XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS);
-        }
-        XFREE(current, heap, DYNAMIC_TYPE_PKCS);
-        current = next;
-    }
-
-    (void)heap;
-}
-
-static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz,
-    byte** cert, word32* certSz, void* heap)
-{
-    WC_DerCertList* current  = *list;
-    WC_DerCertList* previous = NULL;
-    DecodedCert DeCert;
-
-    while (current != NULL) {
-
-        InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap);
-        if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) {
-            if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) {
-                WOLFSSL_MSG("Key Pair found");
-                *cert = current->buffer;
-                *certSz = current->bufferSz;
-
-                if (previous == NULL) {
-                    *list = current->next;
-                }
-                else {
-                    previous->next = current->next;
-                }
-                FreeDecodedCert(&DeCert);
-                XFREE(current, heap, DYNAMIC_TYPE_PKCS);
-                break;
-            }
-        }
-        FreeDecodedCert(&DeCert);
-
-        previous = current;
-        current  = current->next;
-    }
-}
-
-
-/* return 0 on success and negative on failure.
- * By side effect returns private key, cert, and optionally ca.
- * Parses and decodes the parts of PKCS12
- *
- * NOTE: can parse with USER RSA enabled but may return cert that is not the
- *       pair for the key when using RSA key pairs.
- *
- * pkcs12 : non-null WC_PKCS12 struct
- * psw    : password to use for PKCS12 decode
- * pkey   : Private key returned
- * cert   : x509 cert returned
- * ca     : optional ca returned
- */
-int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
-        byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
-        WC_DerCertList** ca)
-{
-    ContentInfo* ci       = NULL;
-    WC_DerCertList* certList = NULL;
-    WC_DerCertList* tailList = NULL;
-    byte* buf             = NULL;
-    word32 i, oid;
-    int ret, pswSz;
-
-    WOLFSSL_ENTER("wc_PKCS12_parse");
-
-    if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL ||
-        pkey == NULL   || pkeySz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    pswSz = (int)XSTRLEN(psw);
-    *cert = NULL;
-    *pkey = NULL;
-    if (ca != NULL)
-        *ca = NULL;
-
-    /* if there is sign data then verify the MAC */
-    if (pkcs12->signData != NULL ) {
-        if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data,
-                               pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) {
-            WOLFSSL_MSG("PKCS12 Bad MAC on verify");
-            WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret);
-            return MAC_CMP_FAILED_E;
-        }
-    }
-
-    if (pkcs12->safe == NULL) {
-        WOLFSSL_MSG("No PKCS12 safes to parse");
-        return BAD_FUNC_ARG;
-    }
-
-    /* Decode content infos */
-    ci = pkcs12->safe->CI;
-    for (i = 0; i < pkcs12->safe->numCI; i++) {
-        byte*  data;
-        word32 idx = 0;
-        int    size, totalSz;
-
-        if (ci->type == WC_PKCS12_ENCRYPTED_DATA) {
-            int number;
-
-            WOLFSSL_MSG("Decrypting PKCS12 Content Info Container");
-            data = ci->data;
-            if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-            }
-            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-            if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-            if (number != 0) {
-                WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12");
-            }
-
-            if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-            ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz);
-            if (ret < 0 || oid != WC_PKCS12_DATA) {
-                WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error");
-                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-            }
-
-            /* decrypted content overwrites input buffer */
-            size = ci->dataSz - idx;
-            buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-            if (buf == NULL) {
-                ERROR_OUT(MEMORY_E, exit_pk12par);
-            }
-            XMEMCPY(buf, data + idx, size);
-
-            if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) {
-                WOLFSSL_MSG("Decryption failed, algorithm not compiled in?");
-                goto exit_pk12par;
-            }
-
-            data = buf;
-            idx = 0;
-
-        #ifdef WOLFSSL_DEBUG_PKCS12
-            {
-                byte* p;
-                for (printf("\tData = "), p = (byte*)buf;
-                    p < (byte*)buf + size;
-                    printf("%02X", *p), p++);
-                printf("\n");
-            }
-        #endif
-        }
-        else { /* type DATA */
-            WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container");
-            data = ci->data;
-            if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-            }
-            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
-                goto exit_pk12par;
-            }
-            if (data[idx++] != ASN_OCTET_STRING) {
-                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-            }
-            if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-        }
-
-        /* parse through bags in ContentInfo */
-        if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) {
-            goto exit_pk12par;
-        }
-        totalSz += idx;
-
-        while ((int)idx < totalSz) {
-            int bagSz;
-            if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-            bagSz += idx;
-
-            if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
-                                                             ci->dataSz)) < 0) {
-                goto exit_pk12par;
-            }
-
-            switch (oid) {
-                case WC_PKCS12_KeyBag: /* 667 */
-                    WOLFSSL_MSG("PKCS12 Key Bag found");
-                    if (data[idx++] !=
-                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-                    }
-                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) {
-                        goto exit_pk12par;
-                    }
-                    if (*pkey == NULL) {
-                        *pkey = (byte*)XMALLOC(size, pkcs12->heap,
-                                                       DYNAMIC_TYPE_PUBLIC_KEY);
-                        if (*pkey == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_pk12par);
-                        }
-                        XMEMCPY(*pkey, data + idx, size);
-                        *pkeySz =  ToTraditional(*pkey, size);
-                    }
-
-                #ifdef WOLFSSL_DEBUG_PKCS12
-                    {
-                        byte* p;
-                        for (printf("\tKey = "), p = (byte*)*pkey;
-                            p < (byte*)*pkey + size;
-                            printf("%02X", *p), p++);
-                        printf("\n");
-                    }
-                #endif
-                    idx += size;
-                    break;
-
-                case WC_PKCS12_ShroudedKeyBag: /* 668 */
-                    {
-                        byte* k;
-
-                        WOLFSSL_MSG("PKCS12 Shrouded Key Bag found");
-                        if (data[idx++] !=
-                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                            ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-                        }
-                        if ((ret = GetLength(data, &idx, &size,
-                                                             ci->dataSz)) < 0) {
-                            goto exit_pk12par;
-                        }
-
-                        k = (byte*)XMALLOC(size, pkcs12->heap,
-                                                       DYNAMIC_TYPE_PUBLIC_KEY);
-                        if (k == NULL) {
-                            ERROR_OUT(MEMORY_E, exit_pk12par);
-                        }
-                        XMEMCPY(k, data + idx, size);
-
-                        /* overwrites input, be warned */
-                        if ((ret = ToTraditionalEnc(k, size, psw, pswSz)) < 0) {
-                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                            goto exit_pk12par;
-                        }
-
-                        if (ret < size) {
-                            /* shrink key buffer */
-                            byte* tmp = (byte*)XMALLOC(ret, pkcs12->heap,
-                                                 DYNAMIC_TYPE_PUBLIC_KEY);
-                            if (tmp == NULL) {
-                                XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                                ERROR_OUT(MEMORY_E, exit_pk12par);
-                            }
-                            XMEMCPY(tmp, k, ret);
-                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                            k = tmp;
-                        }
-                        size = ret;
-
-                        if (*pkey == NULL) {
-                            *pkey = k;
-                            *pkeySz = size;
-                        }
-                        else { /* only expecting one key */
-                            XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-                        }
-                        idx += size;
-
-                    #ifdef WOLFSSL_DEBUG_PKCS12
-                        {
-                            byte* p;
-                            for (printf("\tKey = "), p = (byte*)k;
-                                p < (byte*)k + ret;
-                                printf("%02X", *p), p++);
-                            printf("\n");
-                        }
-                    #endif
-                    }
-                    break;
-
-                case WC_PKCS12_CertBag: /* 669 */
-                {
-                    WC_DerCertList* node;
-                    WOLFSSL_MSG("PKCS12 Cert Bag found");
-                    if (data[idx++] !=
-                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-                    }
-                    if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) {
-                        goto exit_pk12par;
-                    }
-
-                    /* get cert bag type */
-                    if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) {
-                        goto exit_pk12par;
-                    }
-
-                    if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType,
-                                                             ci->dataSz)) < 0) {
-                        goto exit_pk12par;
-                    }
-
-                    switch (oid) {
-                        case WC_PKCS12_CertBag_Type1:  /* 675 */
-                            /* type 1 */
-                            WOLFSSL_MSG("PKCS12 cert bag type 1");
-                            if (data[idx++] !=
-                                     (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) {
-                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-                            }
-                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
-                                                                         <= 0) {
-                                goto exit_pk12par;
-                            }
-                            if (data[idx++] != ASN_OCTET_STRING) {
-                                ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-
-                            }
-                            if ((ret = GetLength(data, &idx, &size, ci->dataSz))
-                                                                          < 0) {
-                                goto exit_pk12par;
-                            }
-                            break;
-                       default:
-                            WOLFSSL_MSG("Unknown PKCS12 cert bag type");
-                    }
-
-                    if (size + idx > (word32)bagSz) {
-                        ERROR_OUT(ASN_PARSE_E, exit_pk12par);
-                    }
-
-                    /* list to hold all certs found */
-                    node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList),
-                                               pkcs12->heap, DYNAMIC_TYPE_PKCS);
-                    if (node == NULL) {
-                        ERROR_OUT(MEMORY_E, exit_pk12par);
-                    }
-                    XMEMSET(node, 0, sizeof(WC_DerCertList));
-
-                    node->buffer = (byte*)XMALLOC(size, pkcs12->heap,
-                                                             DYNAMIC_TYPE_PKCS);
-                    if (node->buffer == NULL) {
-                        XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-                        ERROR_OUT(MEMORY_E, exit_pk12par);
-                    }
-                    XMEMCPY(node->buffer, data + idx, size);
-                    node->bufferSz = size;
-
-                    /* put the new node into the list */
-                    if (certList != NULL) {
-                        WOLFSSL_MSG("Pushing new cert onto queue");
-                        tailList->next = node;
-                        tailList = node;
-                    }
-                    else {
-                        certList = node;
-                        tailList = node;
-                    }
-
-                    /* on to next */
-                    idx += size;
-                }
-                    break;
-
-                case WC_PKCS12_CrlBag: /* 670 */
-                    WOLFSSL_MSG("PKCS12 CRL BAG not yet supported");
-                    break;
-
-                case WC_PKCS12_SecretBag: /* 671 */
-                    WOLFSSL_MSG("PKCS12 Secret BAG not yet supported");
-                    break;
-
-                case WC_PKCS12_SafeContentsBag: /* 672 */
-                    WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported");
-                    break;
-
-                default:
-                    WOLFSSL_MSG("Unknown PKCS12 BAG type found");
-            }
-
-            /* Attribute, unknown bag or unsupported */
-            if ((int)idx < bagSz) {
-                idx = bagSz; /* skip for now */
-            }
-        }
-
-        /* free temporary buffer */
-        if (buf != NULL) {
-            XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-            buf = NULL;
-        }
-
-        ci = ci->next;
-        WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container");
-    }
-
-    /* check if key pair, remove from list */
-    if (*pkey != NULL) {
-        freeDecCertList(&certList, pkey, pkeySz, cert, certSz, pkcs12->heap);
-    }
-
-    /* if ca arg provided return certList, otherwise free it */
-    if (ca != NULL) {
-        *ca = certList;
-    }
-    else {
-        /* free list, not wanted */
-        wc_FreeCertList(certList, pkcs12->heap);
-    }
-
-    ret = 0; /* success */
-
-exit_pk12par:
-
-    if (ret != 0) {
-        /* failure cleanup */
-        if (*pkey) {
-            XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            *pkey = NULL;
-        }
-        if (buf) {
-            XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS);
-            buf = NULL;
-        }
-
-        wc_FreeCertList(certList, pkcs12->heap);
-    }
-
-    return ret;
-}
-
-
-/* Helper function to shroud keys.
- *
- * pkcs12 structure to use with shrouding key
- * rng    random number generator used
- * out    buffer to hold results
- * outSz  size of out buffer
- * key    key that is going to be shrouded
- * keySz  size of key buffer
- * vAlgo  algorithm version
- * pass   password to use
- * passSz size of pass buffer
- * itt    number of iterations
- *
- * returns the size of the shrouded key on success
- */
-static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng,
-        byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo,
-        const char* pass, int passSz, int itt)
-{
-    void* heap;
-    word32 tmpIdx = 0;
-    int vPKCS     = 1; /* PKCS#12 default set to 1 */
-    word32 sz;
-    word32 totalSz = 0;
-    int ret;
-
-
-    if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL ||
-            pass == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    heap = wc_PKCS12_GetHeap(pkcs12);
-
-    /* check if trying to get size */
-    if (out != NULL) {
-        tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */
-        sz = *outSz - tmpIdx;
-    }
-
-    /* case of no encryption */
-    if (vAlgo < 0) {
-        const byte* curveOID = NULL;
-        word32 oidSz = 0;
-        int algoID;
-
-        WOLFSSL_MSG("creating PKCS12 Key Bag");
-
-        /* check key type and get OID if ECC */
-        if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))
-                < 0) {
-            return ret;
-        }
-
-        /* PKCS#8 wrapping around key */
-        ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID,
-                curveOID, oidSz);
-    }
-    else {
-        WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag");
-
-        if (vAlgo == PBE_SHA1_DES) {
-            vPKCS = PKCS5;
-            vAlgo = 10;
-        }
-
-        ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz,
-                vPKCS, vAlgo, NULL, 0, itt, rng, heap);
-    }
-    if (ret == LENGTH_ONLY_E) {
-        *outSz =  sz + MAX_LENGTH_SZ + 1;
-        return LENGTH_ONLY_E;
-    }
-    if (ret < 0) {
-        return ret;
-    }
-
-    totalSz += ret;
-
-    /* out should not be null at this point but check before writing */
-    if (out == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* rewind index and set tag and length */
-    tmpIdx -= MAX_LENGTH_SZ + 1;
-    sz = SetExplicit(0, ret, out + tmpIdx);
-    tmpIdx += sz; totalSz += sz;
-    XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, ret);
-
-    return totalSz;
-}
-
-
-/* Helper function to create key bag.
- *
- * pkcs12 structure to use with key bag
- * rng    random number generator used
- * out    buffer to hold results
- * outSz  size of out buffer
- * key    key that is going into key bag
- * keySz  size of key buffer
- * algo   algorithm version
- * iter   number of iterations
- * pass   password to use
- * passSz size of pass buffer
- *
- * returns the size of the key bag on success
- */
-static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng,
-        byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter,
-        char* pass, int passSz)
-{
-    void* heap;
-    byte* tmp;
-    word32 length  = 0;
-    word32 idx     = 0;
-    word32 totalSz = 0;
-    word32 sz;
-    word32 i;
-    word32 tmpSz;
-    int ret;
-
-    /* get max size for shrouded key */
-    ret =  wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz,
-            algo, pass, passSz, iter);
-    if (ret != LENGTH_ONLY_E && ret < 0) {
-        return ret;
-    }
-
-    if (out == NULL) {
-        *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ +
-            length;
-        return LENGTH_ONLY_E;
-    }
-
-    heap = wc_PKCS12_GetHeap(pkcs12);
-
-    /* leave room for sequence */
-    idx += MAX_SEQ_SZ;
-
-    if (algo < 0) { /* not encrypted */
-        out[idx++] = ASN_OBJECT_ID; totalSz++;
-        sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx);
-        idx += sz; totalSz += sz;
-        for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) {
-            out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++;
-        }
-    }
-    else { /* encrypted */
-        out[idx++] = ASN_OBJECT_ID; totalSz++;
-        sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx);
-        idx += sz; totalSz += sz;
-        for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) {
-            out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++;
-        }
-    }
-
-    /* shroud key */
-    tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (tmp == NULL) {
-        return MEMORY_E;
-    }
-
-    ret =  wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz,
-            algo, pass, passSz, iter);
-    if (ret < 0) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return ret;
-    }
-    length = ret;
-    XMEMCPY(out + idx, tmp, length);
-    XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    totalSz += length;
-
-    /* set begining sequence */
-    tmpSz = SetSequence(totalSz, out);
-    XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
-
-    (void)heap;
-    return totalSz + tmpSz;
-}
-
-
-/* Helper function to create cert bag.
- *
- * pkcs12 structure to use with cert bag
- * out    buffer to hold results
- * outSz  size of out buffer
- * cert   cert that is going into cert bag
- * certSz size of cert buffer
- *
- * returns the size of the cert bag on success
- */
-static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12,
-        byte* out, word32* outSz, byte* cert, word32 certSz)
-{
-    word32 length = 0;
-    word32 idx = 0;
-    word32 totalSz = 0;
-    word32 sz;
-    int WC_CERTBAG_OBJECT_ID  = 13;
-    int WC_CERTBAG1_OBJECT_ID = 12;
-    word32 i;
-    word32 tmpSz;
-
-    if (out == NULL) {
-        *outSz = MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
-            MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
-            MAX_LENGTH_SZ + certSz;
-        return LENGTH_ONLY_E;
-    }
-
-    /* check buffer size able to handle max size */
-    if (*outSz < (MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ +
-            MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 +
-            MAX_LENGTH_SZ + certSz)) {
-        return BUFFER_E;
-    }
-
-    /* save room for sequence */
-    idx += MAX_SEQ_SZ;
-
-    /* objectId WC_PKCS12_CertBag */
-    out[idx++] = ASN_OBJECT_ID; totalSz++;
-    sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx);
-    idx += sz; totalSz += sz;
-    for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) {
-        out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++;
-    }
-
-    /**** Cert Bag type 1 ****/
-    out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++;
-
-    /* save room for length and sequence */
-    idx += MAX_LENGTH_SZ;
-    idx += MAX_SEQ_SZ;
-
-    /* object id WC_PKCS12_CertBag_Type1 */
-    out[idx++] = ASN_OBJECT_ID; length++;
-    sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx);
-    idx += sz; length += sz;
-    for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) {
-        out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++;
-    }
-
-    out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++;
-    sz = 0;
-    idx += MAX_LENGTH_SZ; /* save room for length */
-
-    /* place the cert in the buffer */
-    out[idx++] = ASN_OCTET_STRING; sz++;
-    tmpSz = SetLength(certSz, out + idx);
-    idx += tmpSz; sz += tmpSz;
-    XMEMCPY(out + idx, cert, certSz);
-    idx += certSz; sz += certSz;
-
-    /* rewind idx and place length */
-    idx -= (sz + MAX_LENGTH_SZ);
-    tmpSz = SetLength(sz, out + idx);
-    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz);
-    idx += tmpSz + sz; length += tmpSz + sz;
-
-    /* rewind idx and set sequence */
-    idx -= (length + MAX_SEQ_SZ);
-    tmpSz = SetSequence(length, out + idx);
-    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length);
-    length += tmpSz;
-
-    /* place final length */
-    idx -= MAX_LENGTH_SZ;
-    tmpSz = SetLength(length, out + idx);
-    XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length);
-    length += tmpSz;
-
-    /* place final sequence */
-    totalSz += length;
-    tmpSz = SetSequence(totalSz, out);
-    XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz);
-
-    (void)pkcs12;
-
-    return totalSz + tmpSz;
-}
-
-
-/* Helper function to encrypt content.
- *
- * pkcs12    structure to use with key bag
- * rng       random number generator used
- * out       buffer to hold results
- * outSz     size of out buffer
- * content   content to encrypt
- * contentSz size of content buffer
- * vAlgo     algorithm version
- * pass      password to use
- * passSz    size of pass buffer
- * iter      number of iterations
- * type      content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA
- *
- * returns the size of result on success
- */
-static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng,
-        byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo,
-        const char* pass, int passSz, int iter, int type)
-{
-    void* heap;
-    int vPKCS     = 1; /* PKCS#12 is always set to 1 */
-    int ret;
-    byte*  tmp;
-    word32 idx = 0;
-    word32 totalSz = 0;
-    word32 length = 0;
-    word32 tmpSz;
-    word32 encSz;
-    word32 i;
-
-    WOLFSSL_MSG("encrypting PKCS12 content");
-
-    heap = wc_PKCS12_GetHeap(pkcs12);
-
-    /* ENCRYPTED DATA
-     * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
-     * length
-     * sequence
-     * short int
-     * sequence
-     * get object id */
-    if (type == WC_PKCS12_ENCRYPTED_DATA) {
-        if (out == NULL) {
-            *outSz = 1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ +
-                MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ;
-            ret = EncryptContent(NULL, contentSz + MAX_SEQ_SZ, NULL, &encSz,
-                    pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap);
-            if (ret != LENGTH_ONLY_E) {
-                return ret;
-            }
-
-            *outSz += encSz;
-            return LENGTH_ONLY_E;
-        }
-
-        if (*outSz < (1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ)) {
-            return BUFFER_E;
-        }
-        out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++;
-
-        /* save room for length and sequence */
-        idx += MAX_LENGTH_SZ;
-        idx += MAX_SEQ_SZ;
-
-        tmpSz = SetMyVersion(0, out + idx, 0);
-        idx += tmpSz; length += tmpSz;
-
-        encSz = contentSz;
-        if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz,
-                   pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
-            if (ret != LENGTH_ONLY_E) {
-                return ret;
-            }
-        }
-
-        if (*outSz < (idx + MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + encSz)) {
-            return BUFFER_E;
-        }
-        tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (tmp == NULL) {
-            return MEMORY_E;
-        }
-
-        if ((ret = EncryptContent(content, contentSz, tmp, &encSz,
-                   pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) {
-            XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return ret;
-        }
-        encSz = ret;
-
-        #ifdef WOLFSSL_DEBUG_PKCS12
-        {
-            byte* p;
-            for (printf("(size %u) Encrypted Content = ", encSz),
-                    p = (byte*)tmp;
-                p < (byte*)tmp + encSz;
-                printf("%02X", *p), p++);
-            printf("\n");
-        }
-        #endif
-
-        tmpSz = SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx);
-        idx += tmpSz; length += tmpSz;
-
-        out[idx++] = ASN_OBJECT_ID; length++;
-        tmpSz = SetLength(sizeof(WC_PKCS12_DATA_OID), out + idx);
-        idx += tmpSz; length += tmpSz;
-        for (i = 0; i < sizeof(WC_PKCS12_DATA_OID); i++) {
-            out[idx++] = WC_PKCS12_DATA_OID[i]; length++;
-        }
-
-        /* copy over encrypted data */
-        XMEMCPY(out + idx, tmp, encSz);
-        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        idx += encSz; length += encSz;
-
-        /* rewind and place sequence */
-        idx -= (length + MAX_SEQ_SZ);
-        tmpSz = SetSequence(length, out + idx);
-        XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length);
-        length += tmpSz;
-
-        /* now place length */
-        idx -= MAX_LENGTH_SZ;
-        tmpSz = SetLength(length, out + idx);
-        XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length);
-        totalSz += length + tmpSz;
-
-        return totalSz;
-    }
-
-    /* DATA
-     * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
-     * length
-     * ASN_OCTET_STRING
-     * length
-     * sequence containing all bags */
-    if (type == WC_PKCS12_DATA) {
-        if (out == NULL) {
-            *outSz = 1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz;
-            return LENGTH_ONLY_E;
-        }
-
-        if (*outSz < (1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz)) {
-            return BUFFER_E;
-        }
-
-        out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC);
-        totalSz++;
-
-        /* save room for length */
-        idx += MAX_LENGTH_SZ;
-
-        out[idx++] = ASN_OCTET_STRING; length++;
-        tmpSz = SetLength(contentSz, out + idx);
-        idx += tmpSz; length += tmpSz;
-
-        /* sequence containing all bags */
-        XMEMCPY(out + idx, content, contentSz);
-        idx += contentSz; length += contentSz;
-
-        idx -= (MAX_LENGTH_SZ + length);
-        tmpSz = SetLength(length, out + idx);
-        XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length);
-        totalSz += length + tmpSz;
-
-        return totalSz;
-    }
-
-    WOLFSSL_MSG("Unknown/Unsupported content type");
-    return BAD_FUNC_ARG;
-}
-
-
-/*
- * pass : password to use with encryption
- * passSz : size of the password buffer
- * name : friendlyName to use
- * key  : DER format of key
- * keySz : size of key buffer
- * cert : DER format of certificate
- * certSz : size of the certificate buffer
- * ca   : a list of extra certificates
- * nidKey  : type of encryption to use on the key (-1 means no encryption)
- * nidCert : type of encryption to use on the certificate
- *           (-1 means no encryption)
- * iter    : number of iterations with encryption
- * macIter : number of iterations when creating MAC
- * keyType : flag for signature and/or encryption key
- * heap : pointer to allocate from memory
- *
- * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed
- */
-WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name,
-        byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca,
-        int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap)
-{
-    WC_PKCS12*         pkcs12;
-    AuthenticatedSafe* safe;
-    ContentInfo*       ci;
-    WC_RNG rng;
-    int algo;
-    int ret;
-    int type;
-    word32 idx;
-    word32 sz;
-    word32 tmpSz;
-
-    byte*  certCi = NULL;
-    word32 certCiSz;
-    byte*  keyCi;
-    word32 keyCiSz;
-
-    byte*  certBuf = NULL;
-    word32 certBufSz;
-    byte*  keyBuf;
-    word32 keyBufSz = 0;
-
-    WOLFSSL_ENTER("wc_PKCS12_create()");
-
-    if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) {
-        return NULL;
-    }
-
-    if ((pkcs12 = wc_PKCS12_new()) == NULL) {
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E);
-        return NULL;
-    }
-
-    if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
-        return NULL;
-    }
-
-    if (iter <= 0) {
-        iter = WC_PKCS12_ITT_DEFAULT;
-    }
-
-    /**** add private key bag ****/
-    switch (nidKey) {
-        case PBE_SHA1_RC4_128:
-            algo = 1;
-            break;
-
-        case PBE_SHA1_DES:
-            algo = 2;
-            break;
-
-        case PBE_SHA1_DES3:
-            algo = 3;
-            break;
-
-        /* no encryption */
-        case -1:
-            algo = -1;
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown/Unsupported key encryption");
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-    }
-
-    /* get max size for key bag */
-    ret = wc_PKCS12_create_key_bag(pkcs12, &rng, NULL, &keyBufSz, key, keySz,
-            algo, iter, pass, passSz);
-    if (ret != LENGTH_ONLY_E && ret < 0) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
-        return NULL;
-    }
-
-    /* account for sequence around bag */
-    keyBufSz += MAX_SEQ_SZ;
-
-    keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (keyBuf == NULL) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E);
-        return NULL;
-    }
-
-    ret = wc_PKCS12_create_key_bag(pkcs12, &rng, keyBuf + MAX_SEQ_SZ, &keyBufSz,
-            key, keySz, algo, iter, pass, passSz);
-    if (ret < 0) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
-        return NULL;
-    }
-    keyBufSz = ret;
-
-    tmpSz = SetSequence(keyBufSz, keyBuf);
-    XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz);
-    keyBufSz += tmpSz;
-
-    ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &keyCiSz,
-            NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA);
-    if (ret != LENGTH_ONLY_E) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
-        return NULL;
-    }
-    keyCi = (byte*)XMALLOC(keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (keyCi == NULL) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return NULL;
-    }
-
-    ret = wc_PKCS12_encrypt_content(pkcs12, &rng, keyCi, &keyCiSz,
-            keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA);
-    if (ret < 0 ) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        WOLFSSL_LEAVE("wc_PKCS12_create", ret);
-        return NULL;
-    }
-    keyCiSz = ret;
-    XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    #ifdef WOLFSSL_DEBUG_PKCS12
-    {
-        byte* p;
-        for (printf("(size %u) Key Content Info = ", keyCiSz), p = (byte*)keyCi;
-            p < (byte*)keyCi + keyCiSz;
-            printf("%02X", *p), p++);
-        printf("\n");
-    }
-    #endif
-
-
-    /**** add main certificate bag and extras ****/
-    switch (nidCert) {
-        case PBE_SHA1_RC4_128:
-            type = WC_PKCS12_ENCRYPTED_DATA;
-            algo = 1;
-            break;
-
-        case PBE_SHA1_DES:
-            type = WC_PKCS12_ENCRYPTED_DATA;
-            algo = 2;
-            break;
-
-        case PBE_SHA1_DES3:
-            type = WC_PKCS12_ENCRYPTED_DATA;
-            algo = 3;
-            break;
-
-        case -1:
-            type = WC_PKCS12_DATA;
-            algo = -1;
-            break;
-
-        default:
-            WOLFSSL_MSG("Unknown/Unsupported certificate encryption");
-            XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-    }
-
-    /* get max size of buffer needed */
-    ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz);
-    if (ret != LENGTH_ONLY_E) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-
-    if (ca != NULL) {
-        WC_DerCertList* current = ca;
-        word32 curBufSz = 0;
-
-        /* get max buffer size */
-        while (current != NULL) {
-            ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz,
-                    current->buffer, current->bufferSz);
-            if (ret != LENGTH_ONLY_E) {
-                XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                wc_PKCS12_free(pkcs12);
-                wc_FreeRng(&rng);
-                return NULL;
-            }
-            certBufSz += curBufSz;
-            current    = current->next;
-        }
-    }
-
-    /* account for Sequence that holds all certificate bags */
-    certBufSz += MAX_SEQ_SZ;
-
-    /* completed getting max size, now create buffer and start adding bags */
-    certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (certBuf == NULL) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_MSG("Memory error creating certificate bags");
-        return NULL;
-    }
-
-    idx = 0;
-    idx += MAX_SEQ_SZ;
-
-    sz = certBufSz - idx;
-    if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
-            cert, certSz)) < 0) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-    idx += ret;
-
-    if (ca != NULL) {
-        WC_DerCertList* current = ca;
-
-        while (current != NULL) {
-            sz = certBufSz - idx;
-            if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz,
-               current->buffer, current->bufferSz)) < 0) {
-                XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-                wc_PKCS12_free(pkcs12);
-                wc_FreeRng(&rng);
-                return NULL;
-            }
-            idx    += ret;
-            current = current->next;
-        }
-    }
-
-    /* set sequence and create encrypted content with all certificate bags */
-    tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf);
-    XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ);
-    certBufSz = tmpSz + (idx - MAX_SEQ_SZ);
-
-    /* get buffer size needed for content info */
-    ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &certCiSz,
-            NULL, certBufSz, algo, pass, passSz, iter, type);
-    if (ret != LENGTH_ONLY_E) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
-        return NULL;
-    }
-    certCi = (byte*)XMALLOC(certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (certCi == NULL) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-
-    ret = wc_PKCS12_encrypt_content(pkcs12, &rng, certCi, &certCiSz,
-            certBuf, certBufSz, algo, pass, passSz, iter, type);
-    if (ret < 0) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        WOLFSSL_LEAVE("wc_PKCS12_create()", ret);
-        return NULL;
-    }
-    certCiSz = ret;
-    XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    #ifdef WOLFSSL_DEBUG_PKCS12
-    {
-        byte* p;
-        for (printf("(size %u) Encrypted Certificate Content Info = ",certCiSz),
-                p = (byte*)certCi;
-            p < (byte*)certCi + certCiSz;
-            printf("%02X", *p), p++);
-        printf("\n");
-    }
-    #endif
-
-    /**** create safe and and Content Info ****/
-    safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), heap,
-            DYNAMIC_TYPE_PKCS);
-    if (safe == NULL) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-    pkcs12->safe = safe; /* set so all of safe is free'd with wc_PKCS12_free */
-    XMEMSET(safe, 0, sizeof(AuthenticatedSafe));
-
-    safe->dataSz = certCiSz + keyCiSz;
-    safe->data   = (byte*)XMALLOC(safe->dataSz, heap, DYNAMIC_TYPE_PKCS);
-    if (safe->data == NULL) {
-        XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-    XMEMCPY(safe->data, certCi, certCiSz);
-    XMEMCPY(safe->data + certCiSz, keyCi, keyCiSz);
-    XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(keyCi,  heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    safe->numCI = 2;
-
-    /* add Content Info structs to safe, key first then cert */
-    ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS);
-    if (ci == NULL) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-    XMEMSET(ci, 0, sizeof(ContentInfo));
-    safe->CI = ci;
-    ci->data = safe->data + certCiSz;
-    ci->dataSz = keyCiSz;
-    ci->type = WC_PKCS12_DATA;
-
-    ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS);
-    if (ci == NULL) {
-        wc_PKCS12_free(pkcs12);
-        wc_FreeRng(&rng);
-        return NULL;
-    }
-    XMEMSET(ci, 0, sizeof(ContentInfo));
-    ci->next = safe->CI;
-    safe->CI = ci;
-    ci->data = safe->data;
-    ci->dataSz = certCiSz;
-    if (nidCert < 0) {
-        ci->type = WC_PKCS12_DATA;
-    }
-    else {
-        ci->type = WC_PKCS12_ENCRYPTED_DATA;
-    }
-
-    /* create MAC */
-    if (macIter > 0) {
-        MacData* mac;
-        byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */
-
-        mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS);
-        if (mac == NULL) {
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        }
-        XMEMSET(mac, 0, sizeof(MacData));
-        pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */
-
-        #ifndef NO_SHA256
-            mac->oid = SHA256h;
-        #elif !defined(NO_SHA)
-            mac->oid = SHA;
-        #elif defined(WOLFSSL_SHA384)
-            mac->oid = SHA384;
-        #elif defined(WOLFSSL_SHA512)
-            mac->oid = SHA512;
-        #else
-            WOLFSSL_MSG("No supported hash algorithm compiled in!");
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        #endif
-
-        /* store number of iterations */
-        mac->itt = macIter;
-
-        /* set mac salt */
-        mac->saltSz = 8;
-        mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS);
-        if (mac->salt == NULL) {
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        }
-
-        if ((ret = wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz)) != 0) {
-            WOLFSSL_MSG("Error generating random salt");
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        }
-        ret = wc_PKCS12_create_mac(pkcs12, safe->data, safe->dataSz,
-                         (const byte*)pass, passSz, digest, WC_MAX_DIGEST_SIZE);
-        if (ret < 0) {
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        }
-
-        mac->digestSz = ret;
-        mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS);
-        if (mac->digest == NULL) {
-            wc_PKCS12_free(pkcs12);
-            wc_FreeRng(&rng);
-            return NULL;
-        }
-        XMEMCPY(mac->digest, digest, mac->digestSz);
-    }
-    else {
-        pkcs12->signData = NULL;
-    }
-
-    wc_FreeRng(&rng);
-    (void)name;
-    (void)keyType;
-
-    return pkcs12;
-}
-
-
-/* if using a specific memory heap */
-int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap)
-{
-    if (pkcs12 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    pkcs12->heap = heap;
-
-    return 0;
-}
-
-
-/* getter for heap */
-void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12)
-{
-    if (pkcs12 == NULL) {
-        return NULL;
-    }
-
-    return pkcs12->heap;
-}
-
-#undef ERROR_OUT
-
-#endif /* !NO_ASN && !NO_PWDBASED */
-
--- a/wolfcrypt/src/pkcs7.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5102 +0,0 @@
-/* pkcs7.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_PKCS7
-
-#include <wolfssl/wolfcrypt/pkcs7.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#ifndef NO_RSA
-    #include <wolfssl/wolfcrypt/rsa.h>
-#endif
-#ifdef HAVE_ECC
-    #include <wolfssl/wolfcrypt/ecc.h>
-#endif
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* direction for processing, encoding or decoding */
-typedef enum {
-    WC_PKCS7_ENCODE,
-    WC_PKCS7_DECODE
-} pkcs7Direction;
-
-#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \
-                             MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE)
-
-
-/* placed ASN.1 contentType OID into *output, return idx on success,
- * 0 upon failure */
-static int wc_SetContentType(int pkcs7TypeOID, byte* output)
-{
-    /* PKCS#7 content types, RFC 2315, section 14 */
-    const byte pkcs7[]              = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07 };
-    const byte data[]               = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x01 };
-    const byte signedData[]         = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x02};
-    const byte envelopedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x03 };
-    const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x04 };
-    const byte digestedData[]       = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x05 };
-
-#ifndef NO_PKCS7_ENCRYPTED_DATA
-    const byte encryptedData[]      = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
-                                               0x0D, 0x01, 0x07, 0x06 };
-#endif
-
-    int idSz;
-    int typeSz = 0, idx = 0;
-    const byte* typeName = 0;
-    byte ID_Length[MAX_LENGTH_SZ];
-
-    switch (pkcs7TypeOID) {
-        case PKCS7_MSG:
-            typeSz = sizeof(pkcs7);
-            typeName = pkcs7;
-            break;
-
-        case DATA:
-            typeSz = sizeof(data);
-            typeName = data;
-            break;
-
-        case SIGNED_DATA:
-            typeSz = sizeof(signedData);
-            typeName = signedData;
-            break;
-
-        case ENVELOPED_DATA:
-            typeSz = sizeof(envelopedData);
-            typeName = envelopedData;
-            break;
-
-        case SIGNED_AND_ENVELOPED_DATA:
-            typeSz = sizeof(signedAndEnveloped);
-            typeName = signedAndEnveloped;
-            break;
-
-        case DIGESTED_DATA:
-            typeSz = sizeof(digestedData);
-            typeName = digestedData;
-            break;
-
-#ifndef NO_PKCS7_ENCRYPTED_DATA
-        case ENCRYPTED_DATA:
-            typeSz = sizeof(encryptedData);
-            typeName = encryptedData;
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Unknown PKCS#7 Type");
-            return 0;
-    };
-
-    idSz  = SetLength(typeSz, ID_Length);
-    output[idx++] = ASN_OBJECT_ID;
-    XMEMCPY(output + idx, ID_Length, idSz);
-    idx += idSz;
-    XMEMCPY(output + idx, typeName, typeSz);
-    idx += typeSz;
-
-    return idx;
-}
-
-
-/* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
-static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid,
-                             word32 maxIdx)
-{
-    WOLFSSL_ENTER("wc_GetContentType");
-    if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0)
-        return ASN_PARSE_E;
-
-    return 0;
-}
-
-
-/* return block size for algorithm represented by oid, or <0 on error */
-static int wc_PKCS7_GetOIDBlockSize(int oid)
-{
-    int blockSz;
-
-    switch (oid) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256CBCb:
-    #endif
-            blockSz = AES_BLOCK_SIZE;
-            break;
-#endif
-#ifndef NO_DES3
-        case DESb:
-        case DES3b:
-            blockSz = DES_BLOCK_SIZE;
-            break;
-#endif
-        default:
-            WOLFSSL_MSG("Unsupported content cipher type");
-            return ALGO_ID_E;
-    };
-
-    return blockSz;
-}
-
-
-/* get key size for algorithm represented by oid, or <0 on error */
-static int wc_PKCS7_GetOIDKeySize(int oid)
-{
-    int blockKeySz;
-
-    switch (oid) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128CBCb:
-        case AES128_WRAP:
-            blockKeySz = 16;
-            break;
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192CBCb:
-        case AES192_WRAP:
-            blockKeySz = 24;
-            break;
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256CBCb:
-        case AES256_WRAP:
-            blockKeySz = 32;
-            break;
-    #endif
-#endif
-#ifndef NO_DES3
-        case DESb:
-            blockKeySz = DES_KEYLEN;
-            break;
-
-        case DES3b:
-            blockKeySz = DES3_KEYLEN;
-            break;
-#endif
-        default:
-            WOLFSSL_MSG("Unsupported content cipher type");
-            return ALGO_ID_E;
-    };
-
-    return blockKeySz;
-}
-
-
-PKCS7* wc_PKCS7_New(void* heap, int devId)
-{
-    PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7);
-    if (pkcs7) {
-        XMEMSET(pkcs7, 0, sizeof(PKCS7));
-        if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) {
-            pkcs7->isDynamic = 1;
-        }
-        else {
-            XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7);
-            pkcs7 = NULL;
-        }
-    }
-    return pkcs7;
-}
-
-/* This is to initialize a PKCS7 structure. It sets all values to 0 and can be
- * used to set the heap hint.
- *
- * pkcs7 PKCS7 structure to initialize
- * heap  memory heap hint for PKCS7 structure to use
- * devId currently not used but a place holder for async operations
- *
- * returns 0 on success or a negative value for failure
- */
-int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId)
-{
-    WOLFSSL_ENTER("wc_PKCS7_Init");
-
-    if (pkcs7 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(pkcs7, 0, sizeof(PKCS7));
-#ifdef WOLFSSL_HEAP_TEST
-    pkcs7->heap = (void*)WOLFSSL_HEAP_TEST;
-#else
-    pkcs7->heap = heap;
-#endif
-    pkcs7->devId = devId;
-
-    return 0;
-}
-
-
-/* init PKCS7 struct with recipient cert, decode into DecodedCert
- * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
-int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
-{
-    int ret = 0;
-    void* heap;
-    int devId;
-    word16 isDynamic;
-
-    if (pkcs7 == NULL || (cert == NULL && certSz != 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-    heap = pkcs7->heap;
-    devId = pkcs7->devId;
-    isDynamic = pkcs7->isDynamic;
-    ret = wc_PKCS7_Init(pkcs7, heap, devId);
-    if (ret != 0)
-        return ret;
-    pkcs7->isDynamic = isDynamic;
-
-    if (cert != NULL && certSz > 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        DecodedCert* dCert;
-
-        dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
-                                                       DYNAMIC_TYPE_DCERT);
-        if (dCert == NULL)
-            return MEMORY_E;
-#else
-        DecodedCert stack_dCert;
-        DecodedCert* dCert = &stack_dCert;
-#endif
-
-        pkcs7->singleCert = cert;
-        pkcs7->singleCertSz = certSz;
-        InitDecodedCert(dCert, cert, certSz, pkcs7->heap);
-
-        ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
-        if (ret < 0) {
-            FreeDecodedCert(dCert);
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
-#endif
-            return ret;
-        }
-
-        XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
-        pkcs7->publicKeySz = dCert->pubKeySize;
-        pkcs7->publicKeyOID = dCert->keyOID;
-        XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
-        pkcs7->issuer = dCert->issuerRaw;
-        pkcs7->issuerSz = dCert->issuerRawLen;
-        XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz);
-        pkcs7->issuerSnSz = dCert->serialSz;
-        FreeDecodedCert(dCert);
-
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
-#endif
-    }
-
-    return ret;
-}
-
-
-/* free linked list of PKCS7DecodedAttrib structs */
-static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap)
-{
-    PKCS7DecodedAttrib* current;
-
-    if (attrib == NULL) {
-        return;
-    }
-
-    current = attrib;
-    while (current != NULL) {
-        PKCS7DecodedAttrib* next = current->next;
-        if (current->oid != NULL)  {
-            XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7);
-        }
-        if (current->value != NULL) {
-            XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7);
-        }
-        XFREE(current, heap, DYNAMIC_TYPE_PKCS7);
-        current = next;
-    }
-
-    (void)heap;
-}
-
-
-/* releases any memory allocated by a PKCS7 initializer */
-void wc_PKCS7_Free(PKCS7* pkcs7)
-{
-    if (pkcs7 == NULL)
-        return;
-
-    wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
-
-#ifdef ASN_BER_TO_DER
-    if (pkcs7->der != NULL)
-        XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-
-    if (pkcs7->isDynamic) {
-        pkcs7->isDynamic = 0;
-        XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    }
-}
-
-
-/* helper function for parsing through attributes and finding a specific one.
- * returns PKCS7DecodedAttrib pointer on success */
-static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz)
-{
-    PKCS7DecodedAttrib* list;
-
-    if (pkcs7 == NULL || oid == NULL) {
-        return NULL;
-    }
-
-    /* search attributes for pkiStatus */
-    list = pkcs7->decodedAttrib;
-    while (list != NULL) {
-        word32 sz  = oidSz;
-        word32 idx = 0;
-        int    length = 0;
-
-        if (list->oid[idx++] != ASN_OBJECT_ID) {
-            WOLFSSL_MSG("Bad attribute ASN1 syntax");
-            return NULL;
-        }
-
-        if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) {
-            WOLFSSL_MSG("Bad attribute length");
-            return NULL;
-        }
-
-        sz = (sz < (word32)length)? sz : (word32)length;
-        if (XMEMCMP(oid, list->oid + idx, sz) == 0) {
-            return list;
-        }
-        list = list->next;
-    }
-    return NULL;
-}
-
-
-/* Searches through decoded attributes and returns the value for the first one
- * matching the oid passed in. Note that this value includes the leading ASN1
- * syntax. So for a printable string of "3" this would be something like
- *
- * 0x13, 0x01, 0x33
- *  ID   SIZE  "3"
- *
- * pkcs7  structure to get value from
- * oid    OID value to search for with attributes
- * oidSz  size of oid buffer
- * out    buffer to hold result
- * outSz  size of out buffer (if out is NULL this is set to needed size and
-          LENGTH_ONLY_E is returned)
- *
- * returns size of value on success
- */
-int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz,
-        byte* out, word32* outSz)
-{
-    PKCS7DecodedAttrib* attrib;
-
-    if (pkcs7 == NULL || oid == NULL || outSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    attrib = findAttrib(pkcs7, oid, oidSz);
-    if (attrib == NULL) {
-        return ASN_PARSE_E;
-    }
-
-    if (out == NULL) {
-        *outSz = attrib->valueSz;
-        return LENGTH_ONLY_E;
-    }
-
-    if (*outSz < attrib->valueSz) {
-        return BUFFER_E;
-    }
-
-    XMEMCPY(out, attrib->value, attrib->valueSz);
-    return attrib->valueSz;
-}
-
-
-/* build PKCS#7 data content type */
-int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
-{
-    static const byte oid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
-                         0x07, 0x01 };
-    byte seq[MAX_SEQ_SZ];
-    byte octetStr[MAX_OCTET_STR_SZ];
-    word32 seqSz;
-    word32 octetStrSz;
-    word32 oidSz = (word32)sizeof(oid);
-    int idx = 0;
-
-    if (pkcs7 == NULL || output == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
-    seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
-
-    if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
-        return BUFFER_E;
-
-    XMEMCPY(output, seq, seqSz);
-    idx += seqSz;
-    XMEMCPY(output + idx, oid, oidSz);
-    idx += oidSz;
-    XMEMCPY(output + idx, octetStr, octetStrSz);
-    idx += octetStrSz;
-    XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
-    idx += pkcs7->contentSz;
-
-    return idx;
-}
-
-
-typedef struct EncodedAttrib {
-    byte valueSeq[MAX_SEQ_SZ];
-        const byte* oid;
-        byte valueSet[MAX_SET_SZ];
-        const byte* value;
-    word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
-} EncodedAttrib;
-
-
-typedef struct ESD {
-    wc_HashAlg  hash;
-    enum wc_HashType hashType;
-    byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
-    byte contentAttribsDigest[WC_MAX_DIGEST_SIZE];
-    byte encContentDigest[MAX_ENCRYPTED_KEY_SZ];
-
-    byte outerSeq[MAX_SEQ_SZ];
-        byte outerContent[MAX_EXP_SZ];
-            byte innerSeq[MAX_SEQ_SZ];
-                byte version[MAX_VERSION_SZ];
-                byte digAlgoIdSet[MAX_SET_SZ];
-                    byte singleDigAlgoId[MAX_ALGO_SZ];
-
-                byte contentInfoSeq[MAX_SEQ_SZ];
-                    byte innerContSeq[MAX_EXP_SZ];
-                        byte innerOctets[MAX_OCTET_STR_SZ];
-
-                byte certsSet[MAX_SET_SZ];
-
-                byte signerInfoSet[MAX_SET_SZ];
-                    byte signerInfoSeq[MAX_SEQ_SZ];
-                        byte signerVersion[MAX_VERSION_SZ];
-                        byte issuerSnSeq[MAX_SEQ_SZ];
-                            byte issuerName[MAX_SEQ_SZ];
-                            byte issuerSn[MAX_SN_SZ];
-                        byte signerDigAlgoId[MAX_ALGO_SZ];
-                        byte digEncAlgoId[MAX_ALGO_SZ];
-                        byte signedAttribSet[MAX_SET_SZ];
-                            EncodedAttrib signedAttribs[6];
-                        byte signerDigest[MAX_OCTET_STR_SZ];
-    word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
-    word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
-           singleDigAlgoIdSz, certsSetSz;
-    word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
-           issuerSnSeqSz, issuerNameSz, issuerSnSz,
-           signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
-    word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
-           signedAttribSetSz;
-} ESD;
-
-
-static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
-                                            PKCS7Attrib* attribs, int attribsSz)
-{
-    int i;
-    int maxSz = min(eaSz, attribsSz);
-    int allAttribsSz = 0;
-
-    for (i = 0; i < maxSz; i++)
-    {
-        int attribSz = 0;
-
-        ea[i].value = attribs[i].value;
-        ea[i].valueSz = attribs[i].valueSz;
-        attribSz += ea[i].valueSz;
-        ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
-        attribSz += ea[i].valueSetSz;
-        ea[i].oid = attribs[i].oid;
-        ea[i].oidSz = attribs[i].oidSz;
-        attribSz += ea[i].oidSz;
-        ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
-        attribSz += ea[i].valueSeqSz;
-        ea[i].totalSz = attribSz;
-
-        allAttribsSz += attribSz;
-    }
-    return allAttribsSz;
-}
-
-
-static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
-{
-    int i, idx;
-
-    idx = 0;
-    for (i = 0; i < eaSz; i++) {
-        XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
-        idx += ea[i].valueSeqSz;
-        XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
-        idx += ea[i].oidSz;
-        XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
-        idx += ea[i].valueSetSz;
-        XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
-        idx += ea[i].valueSz;
-    }
-    return 0;
-}
-
-
-#ifndef NO_RSA
-
-/* returns size of signature put into out, negative on error */
-static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
-{
-    int ret;
-    word32 idx;
-#ifdef WOLFSSL_SMALL_STACK
-    RsaKey* privKey;
-#else
-    RsaKey  stack_privKey;
-    RsaKey* privKey = &stack_privKey;
-#endif
-
-    if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
-        DYNAMIC_TYPE_TMP_BUFFER);
-    if (privKey == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
-    if (ret == 0) {
-        if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
-            idx = 0;
-            ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
-                                         pkcs7->privateKeySz);
-        }
-        else if (pkcs7->devId == INVALID_DEVID) {
-            ret = BAD_FUNC_ARG;
-        }
-    }
-    if (ret == 0) {
-        ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest,
-                             sizeof(esd->encContentDigest),
-                             privKey, pkcs7->rng);
-    }
-
-    wc_FreeRsaKey(privKey);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* NO_RSA */
-
-
-#ifdef HAVE_ECC
-
-/* returns size of signature put into out, negative on error */
-static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
-{
-    int ret;
-    word32 outSz, idx;
-#ifdef WOLFSSL_SMALL_STACK
-    ecc_key* privKey;
-#else
-    ecc_key  stack_privKey;
-    ecc_key* privKey = &stack_privKey;
-#endif
-
-    if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
-        DYNAMIC_TYPE_TMP_BUFFER);
-    if (privKey == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId);
-    if (ret == 0) {
-        if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
-            idx = 0;
-            ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
-                                         pkcs7->privateKeySz);
-        }
-        else if (pkcs7->devId == INVALID_DEVID) {
-            ret = BAD_FUNC_ARG;
-        }
-    }
-    if (ret == 0) {
-        outSz = sizeof(esd->encContentDigest);
-        ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest,
-                               &outSz, pkcs7->rng, privKey);
-        if (ret == 0)
-            ret = (int)outSz;
-    }
-
-    wc_ecc_free(privKey);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* HAVE_ECC */
-
-
-/* builds up SignedData signed attributes, including default ones.
- *
- * pkcs7 - pointer to initialized PKCS7 structure
- * esd   - pointer to initialized ESD structure, used for output
- *
- * return 0 on success, negative on error */
-static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd,
-                    byte* contentTypeOid, word32 contentTypeOidSz,
-                    byte* contentType, word32 contentTypeSz,
-                    byte* messageDigestOid, word32 messageDigestOidSz)
-{
-    int hashSz;
-
-    PKCS7Attrib cannedAttribs[2];
-    word32 cannedAttribsCount;
-
-    if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL ||
-        contentType == NULL || messageDigestOid == NULL)
-        return BAD_FUNC_ARG;
-
-    hashSz = wc_HashGetDigestSize(esd->hashType);
-    if (hashSz < 0)
-        return hashSz;
-
-    cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
-
-    cannedAttribs[0].oid     = contentTypeOid;
-    cannedAttribs[0].oidSz   = contentTypeOidSz;
-    cannedAttribs[0].value   = contentType;
-    cannedAttribs[0].valueSz = contentTypeSz;
-    cannedAttribs[1].oid     = messageDigestOid;
-    cannedAttribs[1].oidSz   = messageDigestOidSz;
-    cannedAttribs[1].value   = esd->contentDigest;
-    cannedAttribs[1].valueSz = hashSz + 2;  /* ASN.1 heading */
-
-    esd->signedAttribsCount += cannedAttribsCount;
-    esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
-                                         cannedAttribs, cannedAttribsCount);
-
-    esd->signedAttribsCount += pkcs7->signedAttribsSz;
-    esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4,
-                              pkcs7->signedAttribs, pkcs7->signedAttribsSz);
-
-    return 0;
-}
-
-
-/* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or
- * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID.
- *
- * pkcs7          - pointer to PKCS7 structure
- * digEncAlgoId   - [OUT] output int to store correct algo ID in
- * digEncAlgoType - [OUT] output for algo ID type
- *
- * return 0 on success, negative on error */
-static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId,
-                                           int* digEncAlgoType)
-{
-    int algoId   = 0;
-    int algoType = 0;
-
-    if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL)
-        return BAD_FUNC_ARG;
-
-    if (pkcs7->publicKeyOID == RSAk) {
-
-        algoType = oidSigType;
-
-        switch (pkcs7->hashOID) {
-        #ifndef NO_SHA
-            case SHAh:
-                algoId = CTC_SHAwRSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA224
-            case SHA224h:
-                algoId = CTC_SHA224wRSA;
-                break;
-        #endif
-        #ifndef NO_SHA256
-            case SHA256h:
-                algoId = CTC_SHA256wRSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            case SHA384h:
-                algoId = CTC_SHA384wRSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA512
-            case SHA512h:
-                algoId = CTC_SHA512wRSA;
-                break;
-        #endif
-        }
-
-    }
-#ifdef HAVE_ECC
-    else if (pkcs7->publicKeyOID == ECDSAk) {
-
-        algoType = oidSigType;
-
-        switch (pkcs7->hashOID) {
-        #ifndef NO_SHA
-            case SHAh:
-                algoId = CTC_SHAwECDSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA224
-            case SHA224h:
-                algoId = CTC_SHA224wECDSA;
-                break;
-        #endif
-        #ifndef NO_SHA256
-            case SHA256h:
-                algoId = CTC_SHA256wECDSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            case SHA384h:
-                algoId = CTC_SHA384wECDSA;
-                break;
-        #endif
-        #ifdef WOLFSSL_SHA512
-            case SHA512h:
-                algoId = CTC_SHA512wECDSA;
-                break;
-        #endif
-        }
-    }
-#endif /* HAVE_ECC */
-
-    if (algoId == 0) {
-        WOLFSSL_MSG("Invalid signature algorithm type");
-        return BAD_FUNC_ARG;
-    }
-
-    *digEncAlgoId = algoId;
-    *digEncAlgoType = algoType;
-
-    return 0;
-}
-
-
-/* build SignedData DigestInfo for use with PKCS#7/RSA
- *
- * pkcs7 - pointer to initialized PKCS7 struct
- * flatSignedAttribs - flattened, signed attributes
- * flatSignedAttrbsSz - size of flatSignedAttribs, octets
- * esd - pointer to initialized ESD struct
- * digestInfo - [OUT] output array for DigestInfo
- * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo
- *
- * return 0 on success, negative on error */
-static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs,
-                                    word32 flatSignedAttribsSz, ESD* esd,
-                                    byte* digestInfo, word32* digestInfoSz)
-{
-    int ret, hashSz, digIdx = 0;
-    byte digestInfoSeq[MAX_SEQ_SZ];
-    byte digestStr[MAX_OCTET_STR_SZ];
-    byte attribSet[MAX_SET_SZ];
-    byte algoId[MAX_ALGO_SZ];
-    word32 digestInfoSeqSz, digestStrSz, algoIdSz;
-    word32 attribSetSz;
-
-    if (pkcs7 == NULL || esd == NULL || digestInfo == NULL ||
-        digestInfoSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    hashSz = wc_HashGetDigestSize(esd->hashType);
-    if (hashSz < 0)
-        return hashSz;
-
-    if (pkcs7->signedAttribsSz != 0) {
-
-        if (flatSignedAttribs == NULL)
-            return BAD_FUNC_ARG;
-
-        attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
-
-        ret = wc_HashInit(&esd->hash, esd->hashType);
-        if (ret < 0)
-            return ret;
-
-        ret = wc_HashUpdate(&esd->hash, esd->hashType,
-                            attribSet, attribSetSz);
-        if (ret < 0)
-            return ret;
-
-        ret = wc_HashUpdate(&esd->hash, esd->hashType,
-                            flatSignedAttribs, flatSignedAttribsSz);
-        if (ret < 0)
-            return ret;
-
-        ret = wc_HashFinal(&esd->hash, esd->hashType,
-                           esd->contentAttribsDigest);
-        if (ret < 0)
-            return ret;
-
-    } else {
-        /* when no attrs, digest is contentDigest without tag and length */
-        XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz);
-    }
-
-    /* set algoID, with NULL attributes */
-    algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
-
-    digestStrSz = SetOctetString(hashSz, digestStr);
-    digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
-                                  digestInfoSeq);
-
-    if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) {
-        return BUFFER_E;
-    }
-
-    XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
-    digIdx += digestInfoSeqSz;
-    XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
-    digIdx += algoIdSz;
-    XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
-    digIdx += digestStrSz;
-    XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz);
-    digIdx += hashSz;
-
-    *digestInfoSz = digIdx;
-
-    return 0;
-}
-
-
-/* build SignedData signature over DigestInfo or content digest
- *
- * pkcs7 - pointer to initizlied PKCS7 struct
- * flatSignedAttribs - flattened, signed attributes
- * flatSignedAttribsSz - size of flatSignedAttribs, octets
- * esd - pointer to initialized ESD struct
- *
- * returns length of signature on success, negative on error */
-static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
-                                             byte* flatSignedAttribs,
-                                             word32 flatSignedAttribsSz,
-                                             ESD* esd)
-{
-    int ret;
-#ifdef HAVE_ECC
-    int hashSz;
-#endif
-    word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* digestInfo;
-#else
-    byte digestInfo[MAX_PKCS7_DIGEST_SZ];
-#endif
-
-    if (pkcs7 == NULL || esd == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap,
-        DYNAMIC_TYPE_TMP_BUFFER);
-    if (digestInfo == NULL) {
-        return MEMORY_E;
-    }
-#endif
-
-    ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs,
-                                   flatSignedAttribsSz, esd, digestInfo,
-                                   &digestInfoSz);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* sign digestInfo */
-    switch (pkcs7->publicKeyOID) {
-
-#ifndef NO_RSA
-        case RSAk:
-            ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd);
-            break;
-#endif
-
-#ifdef HAVE_ECC
-        case ECDSAk:
-            /* CMS with ECDSA does not sign DigestInfo structure
-             * like PKCS#7 with RSA does */
-            hashSz = wc_HashGetDigestSize(esd->hashType);
-            if (hashSz < 0) {
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            #endif
-                return hashSz;
-            }
-
-            ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest,
-                                     hashSz, esd);
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Unsupported public key type");
-            ret = BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (ret >= 0) {
-        esd->encContentDigestSz = (word32)ret;
-    }
-
-    return ret;
-}
-
-/* build PKCS#7 signedData content type */
-int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
-{
-    static const byte outerOid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
-                         0x07, 0x02 };
-    static const byte innerOid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
-                         0x07, 0x01 };
-
-    byte contentTypeOid[] =
-            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
-                             0x09, 0x03 };
-    byte contentType[] =
-            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-                             0x07, 0x01 };
-    byte messageDigestOid[] =
-            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-                             0x09, 0x04 };
-
-#ifdef WOLFSSL_SMALL_STACK
-    ESD* esd = NULL;
-#else
-    ESD stack_esd;
-    ESD* esd = &stack_esd;
-#endif
-
-    word32 signerInfoSz = 0;
-    word32 totalSz = 0;
-    int idx = 0, ret = 0;
-    int digEncAlgoId, digEncAlgoType, hashSz;
-    byte* flatSignedAttribs = NULL;
-    word32 flatSignedAttribsSz = 0;
-    word32 innerOidSz = sizeof(innerOid);
-    word32 outerOidSz = sizeof(outerOid);
-
-    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
-        pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
-        pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
-        output == NULL || outputSz == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (esd == NULL)
-        return MEMORY_E;
-#endif
-
-    XMEMSET(esd, 0, sizeof(ESD));
-
-    esd->hashType = wc_OidGetHash(pkcs7->hashOID);
-    ret = wc_HashGetDigestSize(esd->hashType);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-    hashSz = ret;
-
-    ret = wc_HashInit(&esd->hash, esd->hashType);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (pkcs7->contentSz != 0)
-    {
-        ret = wc_HashUpdate(&esd->hash, esd->hashType,
-                            pkcs7->content, pkcs7->contentSz);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-        }
-        esd->contentDigest[0] = ASN_OCTET_STRING;
-        esd->contentDigest[1] = (byte)hashSz;
-        ret = wc_HashFinal(&esd->hash, esd->hashType,
-                           &esd->contentDigest[2]);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-        }
-    }
-
-    esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets);
-    esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz,
-                                esd->innerContSeq);
-    esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz +
-                                    innerOidSz + esd->innerContSeqSz,
-                                    esd->contentInfoSeq);
-
-    esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
-                                     esd->issuerSn, MAX_SN_SZ);
-    signerInfoSz += esd->issuerSnSz;
-    esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
-    signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
-    esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
-    signerInfoSz += esd->issuerSnSeqSz;
-    esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0);
-    signerInfoSz += esd->signerVersionSz;
-    esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId,
-                                      oidHashType, 0);
-    signerInfoSz += esd->signerDigAlgoIdSz;
-
-    /* set signatureAlgorithm */
-    ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId,
-                                          &digEncAlgoType);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-    esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId,
-                                    digEncAlgoType, 0);
-    signerInfoSz += esd->digEncAlgoIdSz;
-
-    if (pkcs7->signedAttribsSz != 0) {
-
-        /* build up signed attributes */
-        ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd,
-                                    contentTypeOid, sizeof(contentTypeOid),
-                                    contentType, sizeof(contentType),
-                                    messageDigestOid, sizeof(messageDigestOid));
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return MEMORY_E;
-        }
-
-        flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap,
-                                                         DYNAMIC_TYPE_PKCS7);
-        flatSignedAttribsSz = esd->signedAttribsSz;
-        if (flatSignedAttribs == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return MEMORY_E;
-        }
-
-        FlattenAttributes(flatSignedAttribs,
-                                   esd->signedAttribs, esd->signedAttribsCount);
-        esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
-                                                          esd->signedAttribSet);
-    }
-
-    /* Calculate the final hash and encrypt it. */
-    ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs,
-                                            flatSignedAttribsSz, esd);
-    if (ret < 0) {
-        if (pkcs7->signedAttribsSz != 0)
-            XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
-
-    esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
-                                                             esd->signerDigest);
-    signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
-
-    esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
-    signerInfoSz += esd->signerInfoSeqSz;
-    esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
-    signerInfoSz += esd->signerInfoSetSz;
-
-    esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz,
-                                                                 esd->certsSet);
-
-    esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId,
-                                      oidHashType, 0);
-    esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
-
-
-    esd->versionSz = SetMyVersion(1, esd->version, 0);
-
-    totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
-              esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz +
-              esd->innerOctetsSz + esd->innerContSeqSz +
-              innerOidSz + pkcs7->contentSz +
-              signerInfoSz;
-    esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq);
-    totalSz += esd->innerSeqSz;
-    esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent);
-    totalSz += esd->outerContentSz + outerOidSz;
-    esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq);
-    totalSz += esd->outerSeqSz;
-
-    if (outputSz < totalSz) {
-        if (pkcs7->signedAttribsSz != 0)
-            XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BUFFER_E;
-    }
-
-    idx = 0;
-    XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz);
-    idx += esd->outerSeqSz;
-    XMEMCPY(output + idx, outerOid, outerOidSz);
-    idx += outerOidSz;
-    XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz);
-    idx += esd->outerContentSz;
-    XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz);
-    idx += esd->innerSeqSz;
-    XMEMCPY(output + idx, esd->version, esd->versionSz);
-    idx += esd->versionSz;
-    XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz);
-    idx += esd->digAlgoIdSetSz;
-    XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
-    idx += esd->singleDigAlgoIdSz;
-    XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz);
-    idx += esd->contentInfoSeqSz;
-    XMEMCPY(output + idx, innerOid, innerOidSz);
-    idx += innerOidSz;
-    XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz);
-    idx += esd->innerContSeqSz;
-    XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz);
-    idx += esd->innerOctetsSz;
-    XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
-    idx += pkcs7->contentSz;
-    XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz);
-    idx += esd->certsSetSz;
-    XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
-    idx += pkcs7->singleCertSz;
-    XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz);
-    idx += esd->signerInfoSetSz;
-    XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz);
-    idx += esd->signerInfoSeqSz;
-    XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz);
-    idx += esd->signerVersionSz;
-    XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz);
-    idx += esd->issuerSnSeqSz;
-    XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz);
-    idx += esd->issuerNameSz;
-    XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
-    idx += pkcs7->issuerSz;
-    XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz);
-    idx += esd->issuerSnSz;
-    XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
-    idx += esd->signerDigAlgoIdSz;
-
-    /* SignerInfo:Attributes */
-    if (flatSignedAttribsSz > 0) {
-        XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz);
-        idx += esd->signedAttribSetSz;
-        XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
-        idx += flatSignedAttribsSz;
-        XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    }
-
-    XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz);
-    idx += esd->digEncAlgoIdSz;
-    XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz);
-    idx += esd->signerDigestSz;
-    XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz);
-    idx += esd->encContentDigestSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return idx;
-}
-
-
-#ifndef NO_RSA
-
-/* returns size of signature put into out, negative on error */
-static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
-                              byte* hash, word32 hashSz)
-{
-    int ret = 0;
-    word32 scratch = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* digest;
-    RsaKey* key;
-#else
-    byte digest[MAX_PKCS7_DIGEST_SZ];
-    RsaKey stack_key;
-    RsaKey* key = &stack_key;
-#endif
-
-    if (pkcs7 == NULL || sig == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (digest == NULL)
-        return MEMORY_E;
-
-    key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (key == NULL) {
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
-
-    ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key,
-                              pkcs7->publicKeySz) < 0) {
-        WOLFSSL_MSG("ASN RSA key decode error");
-        wc_FreeRsaKey(key);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return PUBLIC_KEY_E;
-    }
-
-    ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key);
-
-    wc_FreeRsaKey(key);
-
-    if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) {
-        ret = SIG_VERIFY_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* NO_RSA */
-
-
-#ifdef HAVE_ECC
-
-/* returns size of signature put into out, negative on error */
-static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
-                                byte* hash, word32 hashSz)
-{
-    int ret = 0;
-    int res = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* digest;
-    ecc_key* key;
-#else
-    byte digest[MAX_PKCS7_DIGEST_SZ];
-    ecc_key stack_key;
-    ecc_key* key = &stack_key;
-#endif
-    word32 idx = 0;
-
-    if (pkcs7 == NULL || sig == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (digest == NULL)
-        return MEMORY_E;
-
-    key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (key == NULL) {
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
-
-    ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key,
-                                                      pkcs7->publicKeySz) < 0) {
-        WOLFSSL_MSG("ASN ECDSA key decode error");
-        wc_ecc_free(key);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return PUBLIC_KEY_E;
-    }
-
-    ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key);
-
-    wc_ecc_free(key);
-
-    if (ret == 0 && res != 1) {
-        ret = SIG_VERIFY_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* HAVE_ECC */
-
-
-/* build SignedData digest, both in PKCS#7 DigestInfo format and
- * as plain digest for CMS.
- *
- * pkcs7          - pointer to initialized PKCS7 struct
- * signedAttrib   - signed attributes
- * signedAttribSz - size of signedAttrib, octets
- * pkcs7Digest    - [OUT] PKCS#7 DigestInfo
- * pkcs7DigestSz  - [IN/OUT] size of pkcs7Digest
- * plainDigest    - [OUT] pointer to plain digest, offset into pkcs7Digest
- * plainDigestSz  - [OUT] size of digest at plainDigest
- *
- * returns 0 on success, negative on error */
-static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib,
-                                      word32 signedAttribSz, byte* pkcs7Digest,
-                                      word32* pkcs7DigestSz, byte** plainDigest,
-                                      word32* plainDigestSz)
-{
-    int ret = 0, digIdx = 0, hashSz;
-    word32 attribSetSz;
-    byte attribSet[MAX_SET_SZ];
-    byte digest[WC_MAX_DIGEST_SIZE];
-    byte digestInfoSeq[MAX_SEQ_SZ];
-    byte digestStr[MAX_OCTET_STR_SZ];
-    byte algoId[MAX_ALGO_SZ];
-    word32 digestInfoSeqSz, digestStrSz, algoIdSz;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* digestInfo;
-#else
-    byte digestInfo[MAX_PKCS7_DIGEST_SZ];
-#endif
-
-    wc_HashAlg hash;
-    enum wc_HashType hashType;
-
-    if (pkcs7 == NULL || pkcs7Digest == NULL ||
-        pkcs7DigestSz == NULL || plainDigest == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
-        DYNAMIC_TYPE_TMP_BUFFER);
-    if (digestInfo == NULL)
-        return MEMORY_E;
-#endif
-
-    XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz);
-    XMEMSET(digest,      0, WC_MAX_DIGEST_SIZE);
-    XMEMSET(digestInfo,  0, MAX_PKCS7_DIGEST_SZ);
-
-    hashType = wc_OidGetHash(pkcs7->hashOID);
-    ret = wc_HashGetDigestSize(hashType);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-    hashSz = ret;
-
-    /* calculate digest */
-    ret = wc_HashInit(&hash, hashType);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (signedAttribSz > 0) {
-
-        if (signedAttrib == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return BAD_FUNC_ARG;
-        }
-
-        attribSetSz = SetSet(signedAttribSz, attribSet);
-        ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return ret;
-        }
-
-        ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return ret;
-        }
-
-        ret = wc_HashFinal(&hash, hashType, digest);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return ret;
-        }
-
-    } else {
-
-        if (pkcs7->content == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return ret;
-        }
-
-        ret = wc_HashFinal(&hash, hashType, digest);
-        if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return ret;
-        }
-    }
-
-    /* Set algoID, with NULL attributes */
-    algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
-
-    digestStrSz = SetOctetString(hashSz, digestStr);
-    digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
-                                  digestInfoSeq);
-
-    XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
-    digIdx += digestInfoSeqSz;
-    XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
-    digIdx += algoIdSz;
-    XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
-    digIdx += digestStrSz;
-    XMEMCPY(digestInfo + digIdx, digest, hashSz);
-    digIdx += hashSz;
-
-    XMEMCPY(pkcs7Digest, digestInfo, digIdx);
-    *pkcs7DigestSz = digIdx;
-
-    /* set plain digest pointer */
-    *plainDigest = pkcs7Digest + digIdx - hashSz;
-    *plainDigestSz = hashSz;
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-    return 0;
-}
-
-
-/* verifies SignedData signature, over either PKCS#7 DigestInfo or
- * content digest.
- *
- * pkcs7          - pointer to initialized PKCS7 struct
- * sig            - signature to verify
- * sigSz          - size of sig
- * signedAttrib   - signed attributes, or null if empty
- * signedAttribSz - size of signedAttributes
- *
- * return 0 on success, negative on error */
-static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig,
-                                              word32 sigSz, byte* signedAttrib,
-                                              word32 signedAttribSz)
-{
-    int ret = 0;
-    word32 plainDigestSz = 0, pkcs7DigestSz;
-    byte* plainDigest = NULL; /* offset into pkcs7Digest */
-#ifdef WOLFSSL_SMALL_STACK
-    byte* pkcs7Digest;
-#else
-    byte  pkcs7Digest[MAX_PKCS7_DIGEST_SZ];
-#endif
-
-    if (pkcs7 == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
-                                 DYNAMIC_TYPE_TMP_BUFFER);
-    if (pkcs7Digest == NULL)
-        return MEMORY_E;
-#endif
-
-    /* build hash to verify against */
-    pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ;
-    ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib,
-                                         signedAttribSz, pkcs7Digest,
-                                         &pkcs7DigestSz, &plainDigest,
-                                         &plainDigestSz);
-    if (ret < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    switch (pkcs7->publicKeyOID) {
-
-#ifndef NO_RSA
-        case RSAk:
-            ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest,
-                                     pkcs7DigestSz);
-            if (ret < 0) {
-                WOLFSSL_MSG("PKCS#7 verification failed, trying CMS");
-                ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest,
-                                         plainDigestSz);
-            }
-            break;
-#endif
-
-#ifdef HAVE_ECC
-        case ECDSAk:
-            ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest,
-                                       plainDigestSz);
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Unsupported public key type");
-            ret = BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-     XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-    return ret;
-}
-
-
-/* set correct public key OID based on signature OID, stores in
- * pkcs7->publicKeyOID and returns same value */
-static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID)
-{
-    if (pkcs7 == NULL)
-        return BAD_FUNC_ARG;
-
-    pkcs7->publicKeyOID = 0;
-
-    switch (sigOID) {
-
-    #ifndef NO_RSA
-        /* RSA signature types */
-        case CTC_MD2wRSA:
-        case CTC_MD5wRSA:
-        case CTC_SHAwRSA:
-        case CTC_SHA224wRSA:
-        case CTC_SHA256wRSA:
-        case CTC_SHA384wRSA:
-        case CTC_SHA512wRSA:
-            pkcs7->publicKeyOID = RSAk;
-            break;
-
-        /* if sigOID is already RSAk */
-        case RSAk:
-            pkcs7->publicKeyOID = sigOID;
-            break;
-    #endif
-
-    #ifndef NO_DSA
-        /* DSA signature types */
-        case CTC_SHAwDSA:
-            pkcs7->publicKeyOID = DSAk;
-            break;
-
-        /* if sigOID is already DSAk */
-        case DSAk:
-            pkcs7->publicKeyOID = sigOID;
-            break;
-    #endif
-
-    #ifdef HAVE_ECC
-        /* ECDSA signature types */
-        case CTC_SHAwECDSA:
-        case CTC_SHA224wECDSA:
-        case CTC_SHA256wECDSA:
-        case CTC_SHA384wECDSA:
-        case CTC_SHA512wECDSA:
-            pkcs7->publicKeyOID = ECDSAk;
-            break;
-
-        /* if sigOID is already ECDSAk */
-        case ECDSAk:
-            pkcs7->publicKeyOID = sigOID;
-            break;
-    #endif
-
-        default:
-            WOLFSSL_MSG("Unsupported public key algorithm");
-            return ASN_SIG_KEY_E;
-    }
-
-    return pkcs7->publicKeyOID;
-}
-
-
-/* Parses through the attributes and adds them to the PKCS7 structure
- * Creates dynamic attribute structures that are free'd with calling
- * wc_PKCS7_Free()
- *
- * NOTE: An attribute has the ASN1 format of
- ** Sequence
- ****** Object ID
- ****** Set
- ********** {PritnableString, UTCTime, OCTET STRING ...}
- *
- * pkcs7  the PKCS7 structure to put the parsed attributes into
- * in     buffer holding all attributes
- * inSz   size of in buffer
- *
- * returns the number of attributes parsed on success
- */
-static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz)
-{
-    int    found = 0;
-    word32 idx   = 0;
-    word32 oid;
-
-    if (pkcs7 == NULL || in == NULL || inSz < 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    while (idx < (word32)inSz) {
-        int length  = 0;
-        int oidIdx;
-        PKCS7DecodedAttrib* attrib;
-
-        if (GetSequence(in, &idx, &length, inSz) < 0)
-            return ASN_PARSE_E;
-
-        attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
-                pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (attrib == NULL) {
-            return MEMORY_E;
-        }
-        XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
-
-        oidIdx = idx;
-        if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz)
-                < 0) {
-            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return ASN_PARSE_E;
-        }
-        attrib->oidSz = idx - oidIdx;
-        attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
-                                     DYNAMIC_TYPE_PKCS7);
-        if (attrib->oid == NULL) {
-            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return MEMORY_E;
-        }
-        XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz);
-
-
-        /* Get Set that contains the printable string value */
-        if (GetSet(in, &idx, &length, inSz) < 0) {
-            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return ASN_PARSE_E;
-        }
-
-        if ((inSz - idx) < (word32)length) {
-            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return ASN_PARSE_E;
-        }
-
-        attrib->valueSz = (word32)length;
-        attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
-                                       DYNAMIC_TYPE_PKCS7);
-        if (attrib->value == NULL) {
-            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return MEMORY_E;
-        }
-        XMEMCPY(attrib->value, in + idx, attrib->valueSz);
-        idx += length;
-
-        /* store attribute in linked list */
-        if (pkcs7->decodedAttrib != NULL) {
-            attrib->next = pkcs7->decodedAttrib;
-            pkcs7->decodedAttrib = attrib;
-        } else {
-            pkcs7->decodedAttrib = attrib;
-        }
-        found++;
-    }
-
-    return found;
-}
-
-
-/* Finds the certificates in the message and saves it. */
-int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
-{
-    word32 idx, contentType, hashOID, sigOID;
-    int length, version, ret;
-    byte* content = NULL;
-    byte* sig = NULL;
-    byte* cert = NULL;
-    byte* signedAttrib = NULL;
-    int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
-    byte degenerate;
-#ifdef ASN_BER_TO_DER
-    byte* der;
-#endif
-
-    if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
-        return BAD_FUNC_ARG;
-
-    idx = 0;
-
-    /* Get the contentInfo sequence */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length == 0 && pkiMsg[idx-1] == 0x80) {
-#ifdef ASN_BER_TO_DER
-        word32 len = 0;
-
-        ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
-        if (ret != LENGTH_ONLY_E)
-            return ret;
-        pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (pkcs7->der == NULL)
-            return MEMORY_E;
-        ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
-        if (ret < 0)
-            return ret;
-
-        pkiMsg = pkcs7->der;
-        pkiMsgSz = len;
-        idx = 0;
-        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-#else
-        return BER_INDEF_E;
-#endif
-    }
-
-    /* Get the contentInfo contentType */
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (contentType != SIGNED_DATA) {
-        WOLFSSL_MSG("PKCS#7 input not of type SignedData");
-        return PKCS7_OID_E;
-    }
-
-    /* get the ContentInfo content */
-    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* Get the signedData sequence */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* Get the version */
-    if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (version != 1) {
-        WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1");
-        return ASN_VERSION_E;
-    }
-
-    /* Get the set of DigestAlgorithmIdentifiers */
-    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* Skip the set. */
-    idx += length;
-    degenerate = (length == 0)? 1 : 0;
-
-    /* Get the inner ContentInfo sequence */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* Get the inner ContentInfo contentType */
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (contentType != DATA) {
-        WOLFSSL_MSG("PKCS#7 inner input not of type Data");
-        return PKCS7_OID_E;
-    }
-
-    /* Check for content info, it could be omitted when degenerate */
-    {
-        word32 localIdx = idx;
-        ret = 0;
-        if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
-            ret = ASN_PARSE_E;
-
-        if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) <= 0)
-            ret = ASN_PARSE_E;
-
-        if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
-            ret = ASN_PARSE_E;
-
-        if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
-            ret = ASN_PARSE_E;
-
-        /* Save the inner data as the content. */
-        if (length > 0) {
-            /* Local pointer for calculating hashes later */
-            content   = &pkiMsg[localIdx];
-            contentSz = length;
-            localIdx += length;
-        }
-
-        /* update idx if successful */
-        if (ret == 0) {
-            idx = localIdx;
-        }
-    }
-
-    /* If getting the content info failed with non degenerate then return the
-     * error case. Otherwise with a degenerate it is ok if the content
-     * info was omitted */
-    if (!degenerate && ret != 0) {
-        return ret;
-    }
-
-    /* Get the implicit[0] set of certificates */
-    if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
-        idx++;
-        if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-        if (length > 0) {
-            /* At this point, idx is at the first certificate in
-             * a set of certificates. There may be more than one,
-             * or none, or they may be a PKCS 6 extended
-             * certificate. We want to save the first cert if it
-             * is X.509. */
-
-            word32 certIdx = idx;
-
-            if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
-                if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
-                    return ASN_PARSE_E;
-
-                cert = &pkiMsg[idx];
-                certSz += (certIdx - idx);
-            }
-
-#ifdef ASN_BER_TO_DER
-            der = pkcs7->der;
-#endif
-            /* This will reset PKCS7 structure and then set the certificate */
-            wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
-#ifdef ASN_BER_TO_DER
-            pkcs7->der = der;
-#endif
-
-            /* iterate through any additional certificates */
-            if (MAX_PKCS7_CERTS > 0) {
-                word32 localIdx;
-                int sz = 0;
-                int i;
-
-                pkcs7->cert[0]   = cert;
-                pkcs7->certSz[0] = certSz;
-                certIdx = idx + certSz;
-
-                for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsgSz; i++) {
-                    localIdx = certIdx;
-
-                    if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
-                        if (GetLength(pkiMsg, &certIdx, &sz, pkiMsgSz) < 0)
-                            return ASN_PARSE_E;
-
-                        pkcs7->cert[i]   = &pkiMsg[localIdx];
-                        pkcs7->certSz[i] = sz + (certIdx - localIdx);
-                        certIdx += sz;
-                    }
-                }
-            }
-        }
-        idx += length;
-    }
-
-    /* set content and size after init of PKCS7 structure */
-    pkcs7->content   = content;
-    pkcs7->contentSz = contentSz;
-
-    /* Get the implicit[1] set of crls */
-    if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
-        idx++;
-        if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-        /* Skip the set */
-        idx += length;
-    }
-
-    /* Get the set of signerInfos */
-    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length > 0) {
-        /* Get the sequence of the first signerInfo */
-        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-        /* Get the version */
-        if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-        if (version != 1) {
-            WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1");
-            return ASN_VERSION_E;
-        }
-
-        /* Get the sequence of IssuerAndSerialNumber */
-        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-        /* Skip it */
-        idx += length;
-
-        /* Get the sequence of digestAlgorithm */
-        if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) {
-            return ASN_PARSE_E;
-        }
-        pkcs7->hashOID = (int)hashOID;
-
-        /* Get the IMPLICIT[0] SET OF signedAttributes */
-        if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
-            idx++;
-
-            if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-                return ASN_PARSE_E;
-
-            /* save pointer and length */
-            signedAttrib = &pkiMsg[idx];
-            signedAttribSz = length;
-
-            if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) {
-                WOLFSSL_MSG("Error parsing signed attributes");
-                return ASN_PARSE_E;
-            }
-
-            idx += length;
-        }
-
-        /* Get digestEncryptionAlgorithm */
-        if (GetAlgoId(pkiMsg, &idx, &sigOID, oidSigType, pkiMsgSz) < 0) {
-            return ASN_PARSE_E;
-        }
-
-        /* store public key type based on digestEncryptionAlgorithm */
-        ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID);
-        if (ret <= 0) {
-            WOLFSSL_MSG("Failed to set public key OID from signature");
-            return ret;
-        }
-
-        /* Get the signature */
-        if (pkiMsg[idx] == ASN_OCTET_STRING) {
-            idx++;
-
-            if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-                return ASN_PARSE_E;
-
-            /* save pointer and length */
-            sig = &pkiMsg[idx];
-            sigSz = length;
-
-            idx += length;
-        }
-
-        pkcs7->content = content;
-        pkcs7->contentSz = contentSz;
-
-        ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
-                                                 signedAttrib, signedAttribSz);
-        if (ret < 0)
-            return ret;
-    }
-
-    return 0;
-}
-
-
-#ifdef HAVE_ECC
-
-/* KARI == KeyAgreeRecipientInfo (key agreement) */
-typedef struct WC_PKCS7_KARI {
-    DecodedCert* decoded;          /* decoded recip cert */
-    void*    heap;                 /* user heap, points to PKCS7->heap */
-    int      devId;                /* device ID for HW based private key */
-    ecc_key* recipKey;             /* recip key  (pub | priv) */
-    ecc_key* senderKey;            /* sender key (pub | priv) */
-    byte*    senderKeyExport;      /* sender ephemeral key DER */
-    byte*    kek;                  /* key encryption key */
-    byte*    ukm;                  /* OPTIONAL user keying material */
-    byte*    sharedInfo;           /* ECC-CMS-SharedInfo ASN.1 encoded blob */
-    word32   senderKeyExportSz;    /* size of sender ephemeral key DER */
-    word32   kekSz;                /* size of key encryption key */
-    word32   ukmSz;                /* size of user keying material */
-    word32   sharedInfoSz;         /* size of ECC-CMS-SharedInfo encoded */
-    byte     ukmOwner;             /* do we own ukm buffer? 1:yes, 0:no */
-    byte     direction;            /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */
-    byte     decodedInit : 1;      /* indicates decoded was initialized */
-    byte     recipKeyInit : 1;     /* indicates recipKey was initialized */
-    byte     senderKeyInit : 1;    /* indicates senderKey was initialized */
-} WC_PKCS7_KARI;
-
-
-/* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */
-static int wc_PKCS7_KariKeyWrap(byte* cek, word32 cekSz, byte* kek,
-                                word32 kekSz, byte* out, word32 outSz,
-                                int keyWrapAlgo, int direction)
-{
-    int ret;
-
-    if (cek == NULL || kek == NULL || out == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (keyWrapAlgo) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256_WRAP:
-    #endif
-
-            if (direction == AES_ENCRYPTION) {
-
-                ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
-                                    out, outSz, NULL);
-
-            } else if (direction == AES_DECRYPTION) {
-
-                ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
-                                      out, outSz, NULL);
-            } else {
-                WOLFSSL_MSG("Bad key un/wrap direction");
-                return BAD_FUNC_ARG;
-            }
-
-            if (ret <= 0)
-                return ret;
-
-            break;
-#endif /* NO_AES */
-
-        default:
-            WOLFSSL_MSG("Unsupported key wrap algorithm");
-            return BAD_KEYWRAP_ALG_E;
-    };
-
-    (void)cekSz;
-    (void)kekSz;
-    (void)outSz;
-    (void)direction;
-    return ret;
-}
-
-
-/* allocate and create new WC_PKCS7_KARI struct,
- * returns struct pointer on success, NULL on failure */
-static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction)
-{
-    WC_PKCS7_KARI* kari = NULL;
-
-    if (pkcs7 == NULL)
-        return NULL;
-
-    kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap,
-                                   DYNAMIC_TYPE_PKCS7);
-    if (kari == NULL) {
-        WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI");
-        return NULL;
-    }
-
-    kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
-                                          DYNAMIC_TYPE_PKCS7);
-    if (kari->decoded == NULL) {
-        WOLFSSL_MSG("Failed to allocate DecodedCert");
-        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return NULL;
-    }
-
-    kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
-                                       DYNAMIC_TYPE_PKCS7);
-    if (kari->recipKey == NULL) {
-        WOLFSSL_MSG("Failed to allocate recipient ecc_key");
-        XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return NULL;
-    }
-
-    kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
-                                        DYNAMIC_TYPE_PKCS7);
-    if (kari->senderKey == NULL) {
-        WOLFSSL_MSG("Failed to allocate sender ecc_key");
-        XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return NULL;
-    }
-
-    kari->senderKeyExport = NULL;
-    kari->senderKeyExportSz = 0;
-    kari->kek = NULL;
-    kari->kekSz = 0;
-    kari->ukm = NULL;
-    kari->ukmSz = 0;
-    kari->ukmOwner = 0;
-    kari->sharedInfo = NULL;
-    kari->sharedInfoSz = 0;
-    kari->direction = direction;
-    kari->decodedInit = 0;
-    kari->recipKeyInit = 0;
-    kari->senderKeyInit = 0;
-
-    kari->heap = pkcs7->heap;
-    kari->devId = pkcs7->devId;
-
-    return kari;
-}
-
-
-/* free WC_PKCS7_KARI struct, return 0 on success */
-static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari)
-{
-    void* heap;
-
-    if (kari) {
-        heap = kari->heap;
-
-        if (kari->decoded) {
-            if (kari->decodedInit)
-                FreeDecodedCert(kari->decoded);
-            XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7);
-        }
-        if (kari->senderKey) {
-            if (kari->senderKeyInit)
-                wc_ecc_free(kari->senderKey);
-            XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7);
-        }
-        if (kari->recipKey) {
-            if (kari->recipKeyInit)
-                wc_ecc_free(kari->recipKey);
-            XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7);
-        }
-        if (kari->senderKeyExport) {
-            ForceZero(kari->senderKeyExport, kari->senderKeyExportSz);
-            XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7);
-            kari->senderKeyExportSz = 0;
-        }
-        if (kari->kek) {
-            ForceZero(kari->kek, kari->kekSz);
-            XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7);
-            kari->kekSz = 0;
-        }
-        if (kari->ukm) {
-            if (kari->ukmOwner == 1) {
-                XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7);
-            }
-            kari->ukmSz = 0;
-        }
-        if (kari->sharedInfo) {
-            ForceZero(kari->sharedInfo, kari->sharedInfoSz);
-            XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7);
-            kari->sharedInfoSz = 0;
-        }
-        XFREE(kari, heap, DYNAMIC_TYPE_PKCS7);
-    }
-
-    (void)heap;
-
-    return 0;
-}
-
-
-/* parse recipient cert/key, return 0 on success, negative on error
- * key/keySz only needed during decoding (WC_PKCS7_DECODE) */
-static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
-                                       word32 certSz, const byte* key,
-                                       word32 keySz)
-{
-    int ret;
-    word32 idx;
-
-    if (kari == NULL || kari->decoded == NULL ||
-        cert == NULL || certSz == 0)
-        return BAD_FUNC_ARG;
-
-    /* decode certificate */
-    InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap);
-    kari->decodedInit = 1;
-    ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0);
-    if (ret < 0)
-        return ret;
-
-    /* make sure subject key id was read from cert */
-    if (kari->decoded->extSubjKeyIdSet == 0) {
-        WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
-        return BAD_FUNC_ARG;
-    }
-
-    ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId);
-    if (ret != 0)
-        return ret;
-
-    kari->recipKeyInit = 1;
-
-    /* get recip public key */
-    if (kari->direction == WC_PKCS7_ENCODE) {
-
-        idx = 0;
-        ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx,
-                                    kari->recipKey, kari->decoded->pubKeySize);
-        if (ret != 0)
-            return ret;
-    }
-    /* get recip private key */
-    else if (kari->direction == WC_PKCS7_DECODE) {
-        if (key != NULL && keySz > 0) {
-            idx = 0;
-            ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz);
-        }
-        else if (kari->devId == INVALID_DEVID) {
-            ret = BAD_FUNC_ARG;
-        }
-        if (ret != 0)
-            return ret;
-
-    } else {
-        /* bad direction */
-        return BAD_FUNC_ARG;
-    }
-
-    (void)idx;
-
-    return 0;
-}
-
-
-/* create ephemeral ECC key, places ecc_key in kari->senderKey,
- * DER encoded in kari->senderKeyExport. return 0 on success,
- * negative on error */
-static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng)
-{
-    int ret;
-
-    if (kari == NULL || kari->decoded == NULL ||
-        kari->recipKey == NULL || kari->recipKey->dp == NULL ||
-        rng == NULL)
-        return BAD_FUNC_ARG;
-
-    kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize,
-                                           kari->heap, DYNAMIC_TYPE_PKCS7);
-    if (kari->senderKeyExport == NULL)
-        return MEMORY_E;
-
-    kari->senderKeyExportSz = kari->decoded->pubKeySize;
-
-    ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
-    if (ret != 0)
-        return ret;
-
-    kari->senderKeyInit = 1;
-
-    ret = wc_ecc_make_key_ex(rng, kari->recipKey->dp->size,
-                             kari->senderKey, kari->recipKey->dp->id);
-    if (ret != 0)
-        return ret;
-
-    /* dump generated key to X.963 DER for output in CMS bundle */
-    ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport,
-                             &kari->senderKeyExportSz);
-    if (ret != 0)
-        return ret;
-
-    return 0;
-}
-
-
-/* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm,
- * place in kari->sharedInfo. returns 0 on success, negative on error */
-static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
-{
-    int idx = 0;
-    int sharedInfoSeqSz = 0;
-    int keyInfoSz = 0;
-    int suppPubInfoSeqSz = 0;
-    int entityUInfoOctetSz = 0;
-    int entityUInfoExplicitSz = 0;
-    int kekOctetSz = 0;
-    int sharedInfoSz = 0;
-
-    word32 kekBitSz = 0;
-
-    byte sharedInfoSeq[MAX_SEQ_SZ];
-    byte keyInfo[MAX_ALGO_SZ];
-    byte suppPubInfoSeq[MAX_SEQ_SZ];
-    byte entityUInfoOctet[MAX_OCTET_STR_SZ];
-    byte entityUInfoExplicitSeq[MAX_SEQ_SZ];
-    byte kekOctet[MAX_OCTET_STR_SZ];
-
-    if (kari == NULL)
-        return BAD_FUNC_ARG;
-
-    if ((kari->ukmSz > 0) && (kari->ukm == NULL))
-        return BAD_FUNC_ARG;
-
-    /* kekOctet */
-    kekOctetSz = SetOctetString(sizeof(word32), kekOctet);
-    sharedInfoSz += (kekOctetSz + sizeof(word32));
-
-    /* suppPubInfo */
-    suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2,
-                                   kekOctetSz + sizeof(word32),
-                                   suppPubInfoSeq);
-    sharedInfoSz += suppPubInfoSeqSz;
-
-    /* optional ukm/entityInfo */
-    if (kari->ukmSz > 0) {
-        entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet);
-        sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz);
-
-        entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz +
-                                            kari->ukmSz,
-                                            entityUInfoExplicitSeq);
-        sharedInfoSz += entityUInfoExplicitSz;
-    }
-
-    /* keyInfo */
-    keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0);
-    sharedInfoSz += keyInfoSz;
-
-    /* sharedInfo */
-    sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq);
-    sharedInfoSz += sharedInfoSeqSz;
-
-    kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap,
-                                      DYNAMIC_TYPE_PKCS7);
-    if (kari->sharedInfo == NULL)
-        return MEMORY_E;
-
-    kari->sharedInfoSz = sharedInfoSz;
-
-    XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz);
-    idx += sharedInfoSeqSz;
-    XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz);
-    idx += keyInfoSz;
-    if (kari->ukmSz > 0) {
-        XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq,
-                entityUInfoExplicitSz);
-        idx += entityUInfoExplicitSz;
-        XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz);
-        idx += entityUInfoOctetSz;
-        XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz);
-        idx += kari->ukmSz;
-    }
-    XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz);
-    idx += suppPubInfoSeqSz;
-    XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz);
-    idx += kekOctetSz;
-
-    kekBitSz = (kari->kekSz) * 8;              /* convert to bits */
-#ifdef LITTLE_ENDIAN_ORDER
-    kekBitSz = ByteReverseWord32(kekBitSz);    /* network byte order */
-#endif
-    XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz));
-
-    return 0;
-}
-
-
-/* create key encryption key (KEK) using key wrap algorithm and key encryption
- * algorithm, place in kari->kek. return 0 on success, <0 on error. */
-static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari,
-                                    int keyWrapOID, int keyEncOID)
-{
-    int ret;
-    int kSz;
-    enum wc_HashType kdfType;
-    byte*  secret;
-    word32 secretSz;
-
-    if (kari == NULL || kari->recipKey == NULL ||
-        kari->senderKey == NULL || kari->senderKey->dp == NULL)
-        return BAD_FUNC_ARG;
-
-    /* get KEK size, allocate buff */
-    kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID);
-    if (kSz < 0)
-        return kSz;
-
-    kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7);
-    if (kari->kek == NULL)
-        return MEMORY_E;
-
-    kari->kekSz = (word32)kSz;
-
-    /* generate ECC-CMS-SharedInfo */
-    ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID);
-    if (ret != 0)
-        return ret;
-
-    /* generate shared secret */
-    secretSz = kari->senderKey->dp->size;
-    secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7);
-    if (secret == NULL)
-        return MEMORY_E;
-
-    if (kari->direction == WC_PKCS7_ENCODE) {
-
-        ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey,
-                                   secret, &secretSz);
-
-    } else if (kari->direction == WC_PKCS7_DECODE) {
-
-        ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey,
-                                   secret, &secretSz);
-
-    } else {
-        /* bad direction */
-        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
-        return BAD_FUNC_ARG;
-    }
-
-    if (ret != 0) {
-        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    /* run through KDF */
-    switch (keyEncOID) {
-
-    #ifndef NO_SHA
-        case dhSinglePass_stdDH_sha1kdf_scheme:
-            kdfType = WC_HASH_TYPE_SHA;
-            break;
-    #endif
-    #ifndef WOLFSSL_SHA224
-        case dhSinglePass_stdDH_sha224kdf_scheme:
-            kdfType = WC_HASH_TYPE_SHA224;
-            break;
-    #endif
-    #ifndef NO_SHA256
-        case dhSinglePass_stdDH_sha256kdf_scheme:
-            kdfType = WC_HASH_TYPE_SHA256;
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case dhSinglePass_stdDH_sha384kdf_scheme:
-            kdfType = WC_HASH_TYPE_SHA384;
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        case dhSinglePass_stdDH_sha512kdf_scheme:
-            kdfType = WC_HASH_TYPE_SHA512;
-            break;
-    #endif
-        default:
-            WOLFSSL_MSG("Unsupported key agreement algorithm");
-            XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
-            return BAD_FUNC_ARG;
-    };
-
-    ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo,
-                      kari->sharedInfoSz, kari->kek, kari->kekSz);
-    if (ret != 0) {
-        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
-
-    return 0;
-}
-
-
-/* create ASN.1 formatted KeyAgreeRecipientInfo (kari) for use with ECDH,
- * return sequence size or negative on error */
-static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert,
-                            word32 certSz, int keyAgreeAlgo, int blockKeySz,
-                            int keyWrapAlgo, int keyEncAlgo, WC_RNG* rng,
-                            byte* contentKeyPlain, byte* contentKeyEnc,
-                            int* keyEncSz, byte* out, word32 outSz)
-{
-    int ret = 0, idx = 0;
-    int keySz, direction = 0;
-
-    /* ASN.1 layout */
-    int totalSz = 0;
-    int kariSeqSz = 0;
-    byte kariSeq[MAX_SEQ_SZ];           /* IMPLICIT [1] */
-    int verSz = 0;
-    byte ver[MAX_VERSION_SZ];
-
-    int origIdOrKeySeqSz = 0;
-    byte origIdOrKeySeq[MAX_SEQ_SZ];    /* IMPLICIT [0] */
-    int origPubKeySeqSz = 0;
-    byte origPubKeySeq[MAX_SEQ_SZ];     /* IMPLICIT [1] */
-    int origAlgIdSz = 0;
-    byte origAlgId[MAX_ALGO_SZ];
-    int origPubKeyStrSz = 0;
-    byte origPubKeyStr[MAX_OCTET_STR_SZ];
-
-    /* optional user keying material */
-    int ukmOctetSz = 0;
-    byte ukmOctetStr[MAX_OCTET_STR_SZ];
-    int ukmExplicitSz = 0;
-    byte ukmExplicitSeq[MAX_SEQ_SZ];
-
-    int keyEncryptAlgoIdSz = 0;
-    byte keyEncryptAlgoId[MAX_ALGO_SZ];
-    int keyWrapAlgSz = 0;
-    byte keyWrapAlg[MAX_ALGO_SZ];
-
-    int recipEncKeysSeqSz = 0;
-    byte recipEncKeysSeq[MAX_SEQ_SZ];
-    int recipEncKeySeqSz = 0;
-    byte recipEncKeySeq[MAX_SEQ_SZ];
-    int recipKeyIdSeqSz = 0;
-    byte recipKeyIdSeq[MAX_SEQ_SZ];     /* IMPLICIT [0] */
-    int subjKeyIdOctetSz = 0;
-    byte subjKeyIdOctet[MAX_OCTET_STR_SZ];
-    int encryptedKeyOctetSz = 0;
-    byte encryptedKeyOctet[MAX_OCTET_STR_SZ];
-
-    WC_PKCS7_KARI* kari;
-
-    /* only supports ECDSA for now */
-    if (keyAgreeAlgo != ECDSAk)
-        return BAD_FUNC_ARG;
-
-    /* set direction based on keyWrapAlgo */
-    switch (keyWrapAlgo) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256_WRAP:
-    #endif
-            direction = AES_ENCRYPTION;
-            break;
-#endif
-        default:
-            WOLFSSL_MSG("Unsupported key wrap algorithm");
-            return BAD_KEYWRAP_ALG_E;
-    }
-
-    kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE);
-    if (kari == NULL)
-        return MEMORY_E;
-
-    /* set user keying material if available */
-    if ((pkcs7->ukmSz > 0) && (pkcs7->ukm != NULL)) {
-        kari->ukm = pkcs7->ukm;
-        kari->ukmSz = pkcs7->ukmSz;
-        kari->ukmOwner = 0;
-    }
-
-    /* parse recipient cert, get public key */
-    ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        return ret;
-    }
-
-    /* generate sender ephemeral ECC key */
-    ret = wc_PKCS7_KariGenerateEphemeralKey(kari, rng);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        return ret;
-    }
-
-    /* generate KEK (key encryption key) */
-    ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapAlgo, keyEncAlgo);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        return ret;
-    }
-
-    /* encrypt CEK with KEK */
-    keySz = wc_PKCS7_KariKeyWrap(contentKeyPlain, blockKeySz, kari->kek,
-                        kari->kekSz, contentKeyEnc, *keyEncSz, keyWrapAlgo,
-                        direction);
-    if (keySz <= 0) {
-        wc_PKCS7_KariFree(kari);
-        return ret;
-    }
-    *keyEncSz = (word32)keySz;
-
-    /* Start of RecipientEncryptedKeys */
-
-    /* EncryptedKey */
-    encryptedKeyOctetSz = SetOctetString(*keyEncSz, encryptedKeyOctet);
-    totalSz += (encryptedKeyOctetSz + *keyEncSz);
-
-    /* SubjectKeyIdentifier */
-    subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet);
-    totalSz += (subjKeyIdOctetSz + KEYID_SIZE);
-
-    /* RecipientKeyIdentifier IMPLICIT [0] */
-    recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz +
-                                  KEYID_SIZE, recipKeyIdSeq);
-    totalSz += recipKeyIdSeqSz;
-
-    /* RecipientEncryptedKey */
-    recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq);
-    totalSz += recipEncKeySeqSz;
-
-    /* RecipientEncryptedKeys */
-    recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq);
-    totalSz += recipEncKeysSeqSz;
-
-    /* Start of optional UserKeyingMaterial */
-
-    if (kari->ukmSz > 0) {
-        ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr);
-        totalSz += (ukmOctetSz + kari->ukmSz);
-
-        ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz,
-                                    ukmExplicitSeq);
-        totalSz += ukmExplicitSz;
-    }
-
-    /* Start of KeyEncryptionAlgorithmIdentifier */
-
-    /* KeyWrapAlgorithm */
-    keyWrapAlgSz = SetAlgoID(keyWrapAlgo, keyWrapAlg, oidKeyWrapType, 0);
-    totalSz += keyWrapAlgSz;
-
-    /* KeyEncryptionAlgorithmIdentifier */
-    keyEncryptAlgoIdSz = SetAlgoID(keyEncAlgo, keyEncryptAlgoId,
-                                   oidCmsKeyAgreeType, keyWrapAlgSz);
-    totalSz += keyEncryptAlgoIdSz;
-
-    /* Start of OriginatorIdentifierOrKey */
-
-    /* recipient ECPoint, public key */
-    XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */
-    origPubKeyStr[0] = ASN_BIT_STRING;
-    origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1,
-                                origPubKeyStr + 1) + 2;
-    totalSz += (origPubKeyStrSz + kari->senderKeyExportSz);
-
-    /* Originator AlgorithmIdentifier */
-    origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 0);
-    totalSz += origAlgIdSz;
-
-    /* outer OriginatorPublicKey IMPLICIT [1] */
-    origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1,
-                                  origAlgIdSz + origPubKeyStrSz +
-                                  kari->senderKeyExportSz, origPubKeySeq);
-    totalSz += origPubKeySeqSz;
-
-    /* outer OriginatorIdentiferOrKey IMPLICIT [0] */
-    origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0,
-                                   origPubKeySeqSz + origAlgIdSz +
-                                   origPubKeyStrSz + kari->senderKeyExportSz,
-                                   origIdOrKeySeq);
-    totalSz += origIdOrKeySeqSz;
-
-    /* version, always 3 */
-    verSz = SetMyVersion(3, ver, 0);
-    totalSz += verSz;
-
-    /* outer IMPLICIT [1] kari */
-    kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
-    totalSz += kariSeqSz;
-
-    if ((word32)totalSz > outSz) {
-        WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small");
-        wc_PKCS7_KariFree(kari);
-
-        return BUFFER_E;
-    }
-
-    XMEMCPY(out + idx, kariSeq, kariSeqSz);
-    idx += kariSeqSz;
-    XMEMCPY(out + idx, ver, verSz);
-    idx += verSz;
-
-    XMEMCPY(out + idx, origIdOrKeySeq, origIdOrKeySeqSz);
-    idx += origIdOrKeySeqSz;
-    XMEMCPY(out + idx, origPubKeySeq, origPubKeySeqSz);
-    idx += origPubKeySeqSz;
-    XMEMCPY(out + idx, origAlgId, origAlgIdSz);
-    idx += origAlgIdSz;
-    XMEMCPY(out + idx, origPubKeyStr, origPubKeyStrSz);
-    idx += origPubKeyStrSz;
-    /* ephemeral public key */
-    XMEMCPY(out + idx, kari->senderKeyExport, kari->senderKeyExportSz);
-    idx += kari->senderKeyExportSz;
-
-    if (kari->ukmSz > 0) {
-        XMEMCPY(out + idx, ukmExplicitSeq, ukmExplicitSz);
-        idx += ukmExplicitSz;
-        XMEMCPY(out + idx, ukmOctetStr, ukmOctetSz);
-        idx += ukmOctetSz;
-        XMEMCPY(out + idx, kari->ukm, kari->ukmSz);
-        idx += kari->ukmSz;
-    }
-
-    XMEMCPY(out + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz);
-    idx += keyEncryptAlgoIdSz;
-    XMEMCPY(out + idx, keyWrapAlg, keyWrapAlgSz);
-    idx += keyWrapAlgSz;
-
-    XMEMCPY(out + idx, recipEncKeysSeq, recipEncKeysSeqSz);
-    idx += recipEncKeysSeqSz;
-    XMEMCPY(out + idx, recipEncKeySeq, recipEncKeySeqSz);
-    idx += recipEncKeySeqSz;
-    XMEMCPY(out + idx, recipKeyIdSeq, recipKeyIdSeqSz);
-    idx += recipKeyIdSeqSz;
-    XMEMCPY(out + idx, subjKeyIdOctet, subjKeyIdOctetSz);
-    idx += subjKeyIdOctetSz;
-    /* subject key id */
-    XMEMCPY(out + idx, kari->decoded->extSubjKeyId, KEYID_SIZE);
-    idx += KEYID_SIZE;
-    XMEMCPY(out + idx, encryptedKeyOctet, encryptedKeyOctetSz);
-    idx += encryptedKeyOctetSz;
-    /* encrypted CEK */
-    XMEMCPY(out + idx, contentKeyEnc, *keyEncSz);
-    idx += *keyEncSz;
-
-    wc_PKCS7_KariFree(kari);
-
-    return idx;
-}
-
-#endif /* HAVE_ECC */
-
-#ifndef NO_RSA
-
-/* create ASN.1 formatted RecipientInfo structure, returns sequence size */
-static int wc_CreateRecipientInfo(const byte* cert, word32 certSz,
-                                  int keyEncAlgo, int blockKeySz,
-                                  WC_RNG* rng, byte* contentKeyPlain,
-                                  byte* contentKeyEnc, int* keyEncSz,
-                                  byte* out, word32 outSz, void* heap)
-{
-    word32 idx = 0;
-    int ret = 0, totalSz = 0;
-    int verSz, issuerSz, snSz, keyEncAlgSz;
-    int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
-    int encKeyOctetStrSz;
-
-    byte ver[MAX_VERSION_SZ];
-    byte issuerSerialSeq[MAX_SEQ_SZ];
-    byte recipSeq[MAX_SEQ_SZ];
-    byte issuerSeq[MAX_SEQ_SZ];
-    byte encKeyOctetStr[MAX_OCTET_STR_SZ];
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte *serial;
-    byte *keyAlgArray;
-
-    RsaKey* pubKey;
-    DecodedCert* decoded;
-
-    serial = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (decoded == NULL || serial == NULL || keyAlgArray == NULL) {
-        if (serial)      XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (keyAlgArray) XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        if (decoded)     XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-
-#else
-    byte serial[MAX_SN_SZ];
-    byte keyAlgArray[MAX_ALGO_SZ];
-
-    RsaKey stack_pubKey;
-    RsaKey* pubKey = &stack_pubKey;
-    DecodedCert stack_decoded;
-    DecodedCert* decoded = &stack_decoded;
-#endif
-
-    InitDecodedCert(decoded, (byte*)cert, certSz, heap);
-    ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
-    if (ret < 0) {
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* version */
-    verSz = SetMyVersion(0, ver, 0);
-
-    /* IssuerAndSerialNumber */
-    if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
-        WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length");
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return -1;
-    }
-    issuerSz    = decoded->issuerRawLen;
-    issuerSeqSz = SetSequence(issuerSz, issuerSeq);
-
-    if (decoded->serialSz == 0) {
-        WOLFSSL_MSG("DecodedCert missing serial number");
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return -1;
-    }
-    snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, MAX_SN_SZ);
-
-    issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
-                                    issuerSerialSeq);
-
-    /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
-    if (keyEncAlgo != RSAk) {
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ALGO_ID_E;
-    }
-
-    keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, oidKeyType, 0);
-    if (keyEncAlgSz == 0) {
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pubKey == NULL) {
-        FreeDecodedCert(decoded);
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    /* EncryptedKey */
-    ret = wc_InitRsaKey_ex(pubKey, heap, INVALID_DEVID);
-    if (ret != 0) {
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(pubKey,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
-                           decoded->pubKeySize) < 0) {
-        WOLFSSL_MSG("ASN RSA key decode error");
-        wc_FreeRsaKey(pubKey);
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(pubKey,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return PUBLIC_KEY_E;
-    }
-
-    *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
-                                 MAX_ENCRYPTED_KEY_SZ, pubKey, rng);
-    wc_FreeRsaKey(pubKey);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (*keyEncSz < 0) {
-        WOLFSSL_MSG("RSA Public Encrypt failed");
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return *keyEncSz;
-    }
-
-    encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
-
-    /* RecipientInfo */
-    recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
-                             issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
-                             *keyEncSz, recipSeq);
-
-    if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
-        keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
-        WOLFSSL_MSG("RecipientInfo output buffer too small");
-        FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BUFFER_E;
-    }
-
-    XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
-    totalSz += recipSeqSz;
-    XMEMCPY(out + totalSz, ver, verSz);
-    totalSz += verSz;
-    XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
-    totalSz += issuerSerialSeqSz;
-    XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
-    totalSz += issuerSeqSz;
-    XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz);
-    totalSz += issuerSz;
-    XMEMCPY(out + totalSz, serial, snSz);
-    totalSz += snSz;
-    XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
-    totalSz += keyEncAlgSz;
-    XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
-    totalSz += encKeyOctetStrSz;
-    XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
-    totalSz += *keyEncSz;
-
-    FreeDecodedCert(decoded);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(serial,      heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(decoded,     heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return totalSz;
-}
-#endif /* !NO_RSA */
-
-
-/* encrypt content using encryptOID algo */
-static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz,
-                                   byte* iv, int ivSz, byte* in, int inSz,
-                                   byte* out)
-{
-    int ret;
-#ifndef NO_AES
-    Aes  aes;
-#endif
-#ifndef NO_DES3
-    Des  des;
-    Des3 des3;
-#endif
-
-    if (key == NULL || iv == NULL || in == NULL || out == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (encryptOID) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256CBCb:
-    #endif
-            if (
-                #ifdef WOLFSSL_AES_128
-                    (encryptOID == AES128CBCb && keySz != 16 ) ||
-                #endif
-                #ifdef WOLFSSL_AES_192
-                    (encryptOID == AES192CBCb && keySz != 24 ) ||
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    (encryptOID == AES256CBCb && keySz != 32 ) ||
-                #endif
-                    (ivSz  != AES_BLOCK_SIZE) )
-                return BAD_FUNC_ARG;
-
-            ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION);
-            if (ret == 0)
-                ret = wc_AesCbcEncrypt(&aes, out, in, inSz);
-
-            break;
-#endif
-#ifndef NO_DES3
-        case DESb:
-            if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
-                return BAD_FUNC_ARG;
-
-            ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION);
-            if (ret == 0)
-                ret = wc_Des_CbcEncrypt(&des, out, in, inSz);
-
-            break;
-
-        case DES3b:
-            if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
-                return BAD_FUNC_ARG;
-
-            ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION);
-            if (ret == 0)
-                ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz);
-
-            break;
-#endif
-        default:
-            WOLFSSL_MSG("Unsupported content cipher type");
-            return ALGO_ID_E;
-    };
-
-    return ret;
-}
-
-
-/* decrypt content using encryptOID algo */
-static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz,
-                                   byte* iv, int ivSz, byte* in, int inSz,
-                                   byte* out)
-{
-    int ret;
-#ifndef NO_AES
-    Aes  aes;
-#endif
-#ifndef NO_DES3
-    Des  des;
-    Des3 des3;
-#endif
-
-    if (key == NULL || iv == NULL || in == NULL || out == NULL)
-        return BAD_FUNC_ARG;
-
-    switch (encryptOID) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192CBCb:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256CBCb:
-    #endif
-            if (
-                #ifdef WOLFSSL_AES_128
-                    (encryptOID == AES128CBCb && keySz != 16 ) ||
-                #endif
-                #ifdef WOLFSSL_AES_192
-                    (encryptOID == AES192CBCb && keySz != 24 ) ||
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    (encryptOID == AES256CBCb && keySz != 32 ) ||
-                #endif
-                    (ivSz  != AES_BLOCK_SIZE) )
-                return BAD_FUNC_ARG;
-
-            ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION);
-            if (ret == 0)
-                ret = wc_AesCbcDecrypt(&aes, out, in, inSz);
-
-            break;
-#endif
-#ifndef NO_DES3
-        case DESb:
-            if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
-                return BAD_FUNC_ARG;
-
-            ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION);
-            if (ret == 0)
-                ret = wc_Des_CbcDecrypt(&des, out, in, inSz);
-
-            break;
-        case DES3b:
-            if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
-                return BAD_FUNC_ARG;
-
-            ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION);
-            if (ret == 0)
-                ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz);
-
-            break;
-#endif
-        default:
-            WOLFSSL_MSG("Unsupported content cipher type");
-            return ALGO_ID_E;
-    };
-
-    return ret;
-}
-
-
-/* generate random IV, place in iv, return 0 on success negative on error */
-static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz)
-{
-    int ret;
-    WC_RNG* rnd = NULL;
-
-    if (iv == NULL || ivSz == 0)
-        return BAD_FUNC_ARG;
-
-    /* input RNG is optional, init local one if input rng is NULL */
-    if (rng == NULL) {
-        rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG);
-        if (rnd == NULL)
-            return MEMORY_E;
-
-        ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId);
-        if (ret != 0) {
-            XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
-            return ret;
-        }
-
-    } else {
-        rnd = rng;
-    }
-
-    ret = wc_RNG_GenerateBlock(rnd, iv, ivSz);
-
-    if (rng == NULL) {
-        wc_FreeRng(rnd);
-        XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
-    }
-
-    return ret;
-}
-
-
-/* return size of padded data, padded to blockSz chunks, or negative on error */
-int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
-{
-    int padSz;
-
-    if (blockSz == 0)
-        return BAD_FUNC_ARG;
-
-    padSz = blockSz - (inputSz % blockSz);
-
-    return padSz;
-}
-
-
-/* pad input data to blockSz chunk, place in outSz. out must be big enough
- * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */
-int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
-                     word32 blockSz)
-{
-    int i, padSz;
-
-    if (in == NULL  || inSz == 0 ||
-        out == NULL || outSz == 0)
-        return BAD_FUNC_ARG;
-
-    padSz = wc_PKCS7_GetPadSize(inSz, blockSz);
-
-    if (outSz < (inSz + padSz))
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(out, in, inSz);
-
-    for (i = 0; i < padSz; i++) {
-        out[inSz + i] = (byte)padSz;
-    }
-
-    return inSz + padSz;
-}
-
-
-/* build PKCS#7 envelopedData content type, return enveloped size */
-int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
-{
-    int ret, idx = 0;
-    int totalSz, padSz, encryptedOutSz;
-
-    int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
-    byte contentInfoSeq[MAX_SEQ_SZ];
-    byte outerContentType[MAX_ALGO_SZ];
-    byte outerContent[MAX_SEQ_SZ];
-
-    int envDataSeqSz, verSz;
-    byte envDataSeq[MAX_SEQ_SZ];
-    byte ver[MAX_VERSION_SZ];
-
-    WC_RNG rng;
-    int contentKeyEncSz, blockSz, blockKeySz;
-    byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
-#ifdef WOLFSSL_SMALL_STACK
-    byte* contentKeyEnc;
-#else
-    byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
-#endif
-    byte* plain;
-    byte* encryptedContent;
-
-    int recipSz, recipSetSz;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* recip;
-#else
-    byte recip[MAX_RECIP_SZ];
-#endif
-    byte recipSet[MAX_SET_SZ];
-
-    int encContentOctetSz, encContentSeqSz, contentTypeSz;
-    int contentEncAlgoSz, ivOctetStringSz;
-    byte encContentSeq[MAX_SEQ_SZ];
-    byte contentType[MAX_ALGO_SZ];
-    byte contentEncAlgo[MAX_ALGO_SZ];
-    byte tmpIv[MAX_CONTENT_IV_SIZE];
-    byte ivOctetString[MAX_OCTET_STR_SZ];
-    byte encContentOctet[MAX_OCTET_STR_SZ];
-
-    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
-        pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL ||
-        pkcs7->publicKeyOID == 0)
-        return BAD_FUNC_ARG;
-
-    if (output == NULL || outputSz == 0)
-        return BAD_FUNC_ARG;
-
-    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
-    if (blockKeySz < 0)
-        return blockKeySz;
-
-    blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
-    if (blockSz < 0)
-        return blockSz;
-
-    /* outer content type */
-    outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType);
-
-    /* version, defined as 0 in RFC 2315 */
-#ifdef HAVE_ECC
-    if (pkcs7->publicKeyOID == ECDSAk) {
-        verSz = SetMyVersion(2, ver, 0);
-    } else
-#endif
-    {
-        verSz = SetMyVersion(0, ver, 0);
-    }
-
-    /* generate random content encryption key */
-    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
-    if (ret != 0)
-        return ret;
-
-    ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
-    if (ret != 0) {
-        wc_FreeRng(&rng);
-        return ret;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    recip         = (byte*)XMALLOC(MAX_RECIP_SZ, pkcs7->heap,
-                                                       DYNAMIC_TYPE_PKCS7);
-    contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
-                                                       DYNAMIC_TYPE_PKCS7);
-    if (contentKeyEnc == NULL || recip == NULL) {
-        if (recip)         XFREE(recip,         pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (contentKeyEnc) XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        wc_FreeRng(&rng);
-        return MEMORY_E;
-    }
-#endif
-    contentKeyEncSz = MAX_ENCRYPTED_KEY_SZ;
-
-    /* build RecipientInfo, only handle 1 for now */
-    switch (pkcs7->publicKeyOID) {
-#ifndef NO_RSA
-        case RSAk:
-            recipSz = wc_CreateRecipientInfo(pkcs7->singleCert,
-                                    pkcs7->singleCertSz,
-                                    pkcs7->publicKeyOID,
-                                    blockKeySz, &rng, contentKeyPlain,
-                                    contentKeyEnc, &contentKeyEncSz, recip,
-                                    MAX_RECIP_SZ, pkcs7->heap);
-            break;
-#endif
-#ifdef HAVE_ECC
-        case ECDSAk:
-            recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert,
-                                    pkcs7->singleCertSz,
-                                    pkcs7->publicKeyOID,
-                                    blockKeySz, pkcs7->keyWrapOID,
-                                    pkcs7->keyAgreeOID, &rng,
-                                    contentKeyPlain, contentKeyEnc,
-                                    &contentKeyEncSz, recip, MAX_RECIP_SZ);
-            break;
-#endif
-
-        default:
-            WOLFSSL_MSG("Unsupported RecipientInfo public key type");
-            return BAD_FUNC_ARG;
-    };
-
-    ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-
-    if (recipSz < 0) {
-        WOLFSSL_MSG("Failed to create RecipientInfo");
-        wc_FreeRng(&rng);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return recipSz;
-    }
-    recipSetSz = SetSet(recipSz, recipSet);
-
-    /* generate IV for block cipher */
-    ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz);
-    wc_FreeRng(&rng);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* EncryptedContentInfo */
-    contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
-    if (contentTypeSz == 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BAD_FUNC_ARG;
-    }
-
-    /* allocate encrypted content buffer and PKCS#7 padding */
-    padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
-    if (padSz < 0)
-        return padSz;
-
-    encryptedOutSz = pkcs7->contentSz + padSz;
-
-    plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
-                           DYNAMIC_TYPE_PKCS7);
-    if (plain == NULL)
-        return MEMORY_E;
-
-    ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
-                           encryptedOutSz, blockSz);
-    if (ret < 0) {
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
-                                      DYNAMIC_TYPE_PKCS7);
-    if (encryptedContent == NULL) {
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return MEMORY_E;
-    }
-
-    /* put together IV OCTET STRING */
-    ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
-
-    /* build up our ContentEncryptionAlgorithmIdentifier sequence,
-     * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
-    contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
-                                 oidBlkType, ivOctetStringSz + blockSz);
-
-    if (contentEncAlgoSz == 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return BAD_FUNC_ARG;
-    }
-
-    /* encrypt content */
-    ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, contentKeyPlain,
-            blockKeySz, tmpIv, blockSz, plain, encryptedOutSz,
-            encryptedContent);
-
-    if (ret != 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ret;
-    }
-
-    encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz,
-                                    encContentOctet);
-
-    encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
-                                  ivOctetStringSz + blockSz +
-                                  encContentOctetSz + encryptedOutSz,
-                                  encContentSeq);
-
-    /* keep track of sizes for outer wrapper layering */
-    totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
-              contentEncAlgoSz + ivOctetStringSz + blockSz +
-              encContentOctetSz + encryptedOutSz;
-
-    /* EnvelopedData */
-    envDataSeqSz = SetSequence(totalSz, envDataSeq);
-    totalSz += envDataSeqSz;
-
-    /* outer content */
-    outerContentSz = SetExplicit(0, totalSz, outerContent);
-    totalSz += outerContentTypeSz;
-    totalSz += outerContentSz;
-
-    /* ContentInfo */
-    contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
-    totalSz += contentInfoSeqSz;
-
-    if (totalSz > (int)outputSz) {
-        WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return BUFFER_E;
-    }
-
-    XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
-    idx += contentInfoSeqSz;
-    XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
-    idx += outerContentTypeSz;
-    XMEMCPY(output + idx, outerContent, outerContentSz);
-    idx += outerContentSz;
-    XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
-    idx += envDataSeqSz;
-    XMEMCPY(output + idx, ver, verSz);
-    idx += verSz;
-    XMEMCPY(output + idx, recipSet, recipSetSz);
-    idx += recipSetSz;
-    XMEMCPY(output + idx, recip, recipSz);
-    idx += recipSz;
-    XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
-    idx += encContentSeqSz;
-    XMEMCPY(output + idx, contentType, contentTypeSz);
-    idx += contentTypeSz;
-    XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
-    idx += contentEncAlgoSz;
-    XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
-    idx += ivOctetStringSz;
-    XMEMCPY(output + idx, tmpIv, blockSz);
-    idx += blockSz;
-    XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
-    idx += encContentOctetSz;
-    XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
-    idx += encryptedOutSz;
-
-    ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN);
-
-    XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return idx;
-}
-
-#ifndef NO_RSA
-/* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */
-static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
-                               word32* idx, byte* decryptedKey,
-                               word32* decryptedKeySz, int* recipFound)
-{
-    int length, encryptedKeySz, ret;
-    int keySz;
-    word32 encOID;
-    word32 keyIdx;
-    byte   issuerHash[KEYID_SIZE];
-    byte*  outKey = NULL;
-
-#ifdef WC_RSA_BLINDING
-    WC_RNG rng;
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* serialNum;
-    byte* encryptedKey;
-    RsaKey* privKey;
-#else
-    mp_int stack_serialNum;
-    mp_int* serialNum = &stack_serialNum;
-    byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
-
-    RsaKey stack_privKey;
-    RsaKey* privKey = &stack_privKey;
-#endif
-
-    /* remove IssuerAndSerialNumber */
-    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* if we found correct recipient, issuer hashes will match */
-    if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) {
-        *recipFound = 1;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap,
-                                 DYNAMIC_TYPE_TMP_BUFFER);
-    if (serialNum == NULL)
-        return MEMORY_E;
-#endif
-
-    if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    mp_clear(serialNum);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* key encryption algorithm must be RSA for now */
-    if (encOID != RSAk)
-        return ALGO_ID_E;
-
-    /* read encryptedKey */
-#ifdef WOLFSSL_SMALL_STACK
-    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
-                                  DYNAMIC_TYPE_TMP_BUFFER);
-    if (encryptedKey == NULL)
-        return MEMORY_E;
-#endif
-
-    if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (*recipFound == 1)
-        XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz);
-    *idx += encryptedKeySz;
-
-    /* load private key */
-#ifdef WOLFSSL_SMALL_STACK
-    privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
-        DYNAMIC_TYPE_TMP_BUFFER);
-    if (privKey == NULL) {
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
-        keyIdx = 0;
-        ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey,
-                                     pkcs7->privateKeySz);
-    }
-    else if (pkcs7->devId == INVALID_DEVID) {
-        ret = BAD_FUNC_ARG;
-    }
-    if (ret != 0) {
-        WOLFSSL_MSG("Failed to decode RSA private key");
-        wc_FreeRsaKey(privKey);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    /* decrypt encryptedKey */
-    #ifdef WC_RSA_BLINDING
-    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
-    if (ret == 0) {
-        ret = wc_RsaSetRNG(privKey, &rng);
-    }
-    #endif
-    if (ret == 0) {
-        keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
-                                           &outKey, privKey);
-        #ifdef WC_RSA_BLINDING
-            wc_FreeRng(&rng);
-        #endif
-    } else {
-        keySz = ret;
-    }
-    wc_FreeRsaKey(privKey);
-
-    if (keySz <= 0 || outKey == NULL) {
-        ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return keySz;
-    } else {
-        *decryptedKeySz = keySz;
-        XMEMCPY(decryptedKey, outKey, keySz);
-        ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-
-/* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */
-static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx)
-{
-    int ret, length;
-    word32 keyOID;
-
-    if (kari == NULL || pkiMsg == NULL || idx == NULL)
-        return BAD_FUNC_ARG;
-
-    /* remove OriginatorIdentifierOrKey */
-    if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
-        (*idx)++;
-        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-    } else {
-        return ASN_PARSE_E;
-    }
-
-    /* remove OriginatorPublicKey */
-    if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
-        (*idx)++;
-        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-    } else {
-        return ASN_PARSE_E;
-    }
-
-    /* remove AlgorithmIdentifier */
-    if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (keyOID != ECDSAk)
-        return ASN_PARSE_E;
-
-    /* remove ECPoint BIT STRING */
-    if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING))
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if ((pkiMsgSz < (*idx + 1)) || (pkiMsg[(*idx)++] != 0x00))
-        return ASN_EXPECT_0_E;
-
-    /* get sender ephemeral public ECDSA key */
-    ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
-    if (ret != 0)
-        return ret;
-
-    kari->senderKeyInit = 1;
-
-    /* length-1 for unused bits counter */
-    ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey);
-    if (ret != 0)
-        return ret;
-
-    (*idx) += length - 1;
-
-    return 0;
-}
-
-
-/* remove optional UserKeyingMaterial if available, return 0 on success,
- * < 0 on error */
-static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx)
-{
-    int length;
-    word32 savedIdx;
-
-    if (kari == NULL || pkiMsg == NULL || idx == NULL)
-        return BAD_FUNC_ARG;
-
-    savedIdx = *idx;
-
-    /* starts with EXPLICIT [1] */
-    if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
-        *idx = savedIdx;
-        return 0;
-    }
-
-    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
-        *idx = savedIdx;
-        return 0;
-    }
-
-    /* get OCTET STRING */
-    if ( (pkiMsgSz > ((*idx) + 1)) &&
-         (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) {
-        *idx = savedIdx;
-        return 0;
-    }
-
-    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
-        *idx = savedIdx;
-        return 0;
-    }
-
-    kari->ukm = NULL;
-    if (length > 0) {
-        kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7);
-        if (kari->ukm == NULL)
-            return MEMORY_E;
-
-        XMEMCPY(kari->ukm, pkiMsg + (*idx), length);
-        kari->ukmOwner = 1;
-    }
-
-    (*idx) += length;
-    kari->ukmSz = length;
-
-    return 0;
-}
-
-
-/* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success,
- * < 0 on error */
-static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
-                        word32* keyAgreeOID, word32* keyWrapOID)
-{
-    if (kari == NULL || pkiMsg == NULL || idx == NULL ||
-        keyAgreeOID == NULL || keyWrapOID == NULL)
-        return BAD_FUNC_ARG;
-
-    /* remove KeyEncryptionAlgorithmIdentifier */
-    if (GetAlgoId(pkiMsg, idx, keyAgreeOID, oidCmsKeyAgreeType,
-                  pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */
-    if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    return 0;
-}
-
-
-/* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error
- * if subject key ID matches, recipFound is set to 1 */
-static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
-                        int* recipFound)
-{
-    int length;
-    byte subjKeyId[KEYID_SIZE];
-
-    if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL)
-        return BAD_FUNC_ARG;
-
-    /* remove RecipientKeyIdentifier IMPLICIT [0] */
-    if ( (pkiMsgSz > (*idx + 1)) &&
-         (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) {
-
-        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-
-    } else {
-        return ASN_PARSE_E;
-    }
-
-    /* remove SubjectKeyIdentifier */
-    if ( (pkiMsgSz > (*idx + 1)) &&
-         (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length != KEYID_SIZE)
-        return ASN_PARSE_E;
-
-    XMEMCPY(subjKeyId, pkiMsg + (*idx), KEYID_SIZE);
-    (*idx) += length;
-
-    /* subject key id should match if recipient found */
-    if (XMEMCMP(subjKeyId, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) {
-        *recipFound = 1;
-    }
-
-    return 0;
-}
-
-
-/* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error
- * if issuer and serial number match, recipFound is set to 1 */
-static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
-                        int* recipFound)
-{
-    int length, ret;
-    byte issuerHash[KEYID_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* serial;
-    mp_int* recipSerial;
-#else
-    mp_int  stack_serial;
-    mp_int* serial = &stack_serial;
-
-    mp_int  stack_recipSerial;
-    mp_int* recipSerial = &stack_recipSerial;
-#endif
-
-    /* remove IssuerAndSerialNumber */
-    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* if we found correct recipient, issuer hashes will match */
-    if (XMEMCMP(issuerHash, kari->decoded->issuerHash, KEYID_SIZE) == 0) {
-        *recipFound = 1;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
-                              DYNAMIC_TYPE_TMP_BUFFER);
-    if (serial == NULL)
-        return MEMORY_E;
-
-    recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
-                                   DYNAMIC_TYPE_TMP_BUFFER);
-    if (recipSerial == NULL) {
-        XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial,
-                             kari->decoded->serialSz);
-    if (ret != MP_OKAY) {
-        mp_clear(serial);
-        WOLFSSL_MSG("Failed to parse CMS recipient serial number");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    if (mp_cmp(recipSerial, serial) != MP_EQ) {
-        mp_clear(serial);
-        mp_clear(recipSerial);
-        WOLFSSL_MSG("CMS serial number does not match recipient");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return PKCS7_RECIP_E;
-    }
-
-    mp_clear(serial);
-    mp_clear(recipSerial);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(serial,      kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-
-/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */
-static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari,
-                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
-                        int* recipFound, byte* encryptedKey,
-                        int* encryptedKeySz)
-{
-    int length;
-    int ret = 0;
-
-    if (kari == NULL || pkiMsg == NULL || idx == NULL ||
-        recipFound == NULL || encryptedKey == NULL)
-        return BAD_FUNC_ARG;
-
-    /* remove RecipientEncryptedKeys */
-    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* remove RecipientEncryptedKeys */
-    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber
-     * or [0] IMMPLICIT RecipientKeyIdentifier */
-    if ( (pkiMsgSz > (*idx + 1)) &&
-         (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) {
-
-        /* try to get RecipientKeyIdentifier */
-        ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz,
-                                                   idx, recipFound);
-    } else {
-        /* try to get IssuerAndSerialNumber */
-        ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz,
-                                                    idx, recipFound);
-    }
-
-    /* if we don't have either option, malformed CMS */
-    if (ret != 0)
-        return ret;
-
-    /* remove EncryptedKey */
-    if ( (pkiMsgSz > (*idx + 1)) &&
-         (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* put encrypted CEK in decryptedKey buffer for now, decrypt later */
-    if (length > *encryptedKeySz)
-        return BUFFER_E;
-
-    XMEMCPY(encryptedKey, pkiMsg + (*idx), length);
-    *encryptedKeySz = length;
-    (*idx) += length;
-
-    return 0;
-}
-
-#endif /* HAVE_ECC */
-
-
-/* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success,
- * < 0 on error */
-static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
-                               word32* idx, byte* decryptedKey,
-                               word32* decryptedKeySz, int* recipFound)
-{
-#ifdef HAVE_ECC
-    int ret, keySz;
-    int encryptedKeySz;
-    int direction = 0;
-    word32 keyAgreeOID, keyWrapOID;
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte* encryptedKey;
-#else
-    byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
-#endif
-
-    WC_PKCS7_KARI* kari;
-
-    if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
-        pkcs7->singleCertSz == 0 || pkiMsg == NULL ||
-        idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE);
-    if (kari == NULL)
-        return MEMORY_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
-                                  DYNAMIC_TYPE_PKCS7);
-    if (encryptedKey == NULL) {
-        wc_PKCS7_KariFree(kari);
-        return MEMORY_E;
-    }
-#endif
-    encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
-
-    /* parse cert and key */
-    ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert,
-                                      pkcs7->singleCertSz, pkcs7->privateKey,
-                                      pkcs7->privateKeySz);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* remove OriginatorIdentifierOrKey */
-    ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg,
-                                                    pkiMsgSz, idx);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* try and remove optional UserKeyingMaterial */
-    ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* remove KeyEncryptionAlgorithmIdentifier */
-    ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, pkiMsgSz,
-                                                   idx, &keyAgreeOID,
-                                                   &keyWrapOID);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* if user has not explicitly set keyAgreeOID, set from one in bundle */
-    if (pkcs7->keyAgreeOID == 0)
-        pkcs7->keyAgreeOID = keyAgreeOID;
-
-    /* set direction based on key wrap algorithm */
-    switch (keyWrapOID) {
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_128
-        case AES128_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_192
-        case AES192_WRAP:
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case AES256_WRAP:
-    #endif
-            direction = AES_DECRYPTION;
-            break;
-#endif
-        default:
-            wc_PKCS7_KariFree(kari);
-            #ifdef WOLFSSL_SMALL_STACK
-                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            #endif
-            WOLFSSL_MSG("AES key wrap algorithm unsupported");
-            return BAD_KEYWRAP_ALG_E;
-    }
-
-    /* remove RecipientEncryptedKeys */
-    ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz,
-                               idx, recipFound, encryptedKey, &encryptedKeySz);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* create KEK */
-    ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID);
-    if (ret != 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return ret;
-    }
-
-    /* decrypt CEK with KEK */
-    keySz = wc_PKCS7_KariKeyWrap(encryptedKey, encryptedKeySz, kari->kek,
-                                 kari->kekSz, decryptedKey, *decryptedKeySz,
-                                 keyWrapOID, direction);
-    if (keySz <= 0) {
-        wc_PKCS7_KariFree(kari);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        #endif
-        return keySz;
-    }
-    *decryptedKeySz = (word32)keySz;
-
-    wc_PKCS7_KariFree(kari);
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    #endif
-
-    return 0;
-#else
-    (void)pkcs7;
-    (void)pkiMsg;
-    (void)pkiMsgSz;
-    (void)idx;
-    (void)decryptedKey;
-    (void)decryptedKeySz;
-    (void)recipFound;
-
-    return NOT_COMPILED_IN;
-#endif /* HAVE_ECC */
-}
-
-
-/* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */
-static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg,
-                            word32 pkiMsgSz, word32* idx, byte* decryptedKey,
-                            word32* decryptedKeySz, int* recipFound)
-{
-    word32 savedIdx;
-    int version, ret, length;
-
-    if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL ||
-        decryptedKey == NULL || decryptedKeySz == NULL ||
-        recipFound == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    savedIdx = *idx;
-
-    /* when looking for next recipient, use first sequence and version to
-     * indicate there is another, if not, move on */
-    while(*recipFound == 0) {
-
-        /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
-         * last good saved one */
-        if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) {
-
-            if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
-                *idx = savedIdx;
-                break;
-            }
-
-            if (version != 0)
-                return ASN_VERSION_E;
-
-        #ifndef NO_RSA
-            /* found ktri */
-            ret = wc_PKCS7_DecodeKtri(pkcs7, pkiMsg, pkiMsgSz, idx,
-                                      decryptedKey, decryptedKeySz,
-                                      recipFound);
-            if (ret != 0)
-                return ret;
-        #else
-            return NOT_COMPILED_IN;
-        #endif
-        }
-        else {
-            /* kari is IMPLICIT[1] */
-            *idx = savedIdx;
-            if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
-                (*idx)++;
-
-                if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
-                    return ASN_PARSE_E;
-
-                if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
-                    *idx = savedIdx;
-                    break;
-                }
-
-                if (version != 3)
-                    return ASN_VERSION_E;
-
-                /* found kari */
-                ret = wc_PKCS7_DecodeKari(pkcs7, pkiMsg, pkiMsgSz, idx,
-                                          decryptedKey, decryptedKeySz,
-                                          recipFound);
-                if (ret != 0)
-                    return ret;
-            }
-            else {
-                /* failed to find RecipientInfo, restore idx and continue */
-                *idx = savedIdx;
-                break;
-            }
-        }
-
-        /* update good idx */
-        savedIdx = *idx;
-    }
-
-    return 0;
-}
-
-
-/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
-WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
-                                         word32 pkiMsgSz, byte* output,
-                                         word32 outputSz)
-{
-    int recipFound = 0;
-    int ret, version, length;
-    word32 idx = 0;
-    word32 contentType, encOID;
-    word32 decryptedKeySz;
-
-    int expBlockSz, blockKeySz;
-    byte tmpIv[MAX_CONTENT_IV_SIZE];
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte* decryptedKey;
-#else
-    byte decryptedKey[MAX_ENCRYPTED_KEY_SZ];
-#endif
-    int encryptedContentSz;
-    byte padLen;
-    byte* encryptedContent = NULL;
-    int explicitOctet;
-
-    if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
-        pkcs7->singleCertSz == 0)
-        return BAD_FUNC_ARG;
-
-    if (pkiMsg == NULL || pkiMsgSz == 0 ||
-        output == NULL || outputSz == 0)
-        return BAD_FUNC_ARG;
-
-    /* read past ContentInfo, verify type is envelopedData */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length == 0 && pkiMsg[idx-1] == 0x80) {
-#ifdef ASN_BER_TO_DER
-        word32 len = 0;
-
-        ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
-        if (ret != LENGTH_ONLY_E)
-            return ret;
-        pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (pkcs7->der == NULL)
-            return MEMORY_E;
-        ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
-        if (ret < 0)
-            return ret;
-
-        pkiMsg = pkcs7->der;
-        pkiMsgSz = len;
-        idx = 0;
-        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-            return ASN_PARSE_E;
-#else
-        return BER_INDEF_E;
-#endif
-    }
-
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (contentType != ENVELOPED_DATA) {
-        WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
-        return PKCS7_OID_E;
-    }
-
-    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* remove EnvelopedData and version */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* TODO :: make this more accurate */
-    if ((pkcs7->publicKeyOID == RSAk && version != 0)
-    #ifdef HAVE_ECC
-            || (pkcs7->publicKeyOID == ECDSAk && version != 2)
-    #endif
-            ) {
-        WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0");
-        return ASN_VERSION_E;
-    }
-
-    /* walk through RecipientInfo set, find correct recipient */
-    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
-                                                       DYNAMIC_TYPE_PKCS7);
-    if (decryptedKey == NULL)
-        return MEMORY_E;
-#endif
-    decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
-
-    ret = wc_PKCS7_DecodeRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx,
-                                        decryptedKey, &decryptedKeySz,
-                                        &recipFound);
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ret;
-    }
-
-    if (recipFound == 0) {
-        WOLFSSL_MSG("No recipient found in envelopedData that matches input");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return PKCS7_RECIP_E;
-    }
-
-    /* remove EncryptedContentInfo */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    blockKeySz = wc_PKCS7_GetOIDKeySize(encOID);
-    if (blockKeySz < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return blockKeySz;
-    }
-
-    expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
-    if (expBlockSz < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return expBlockSz;
-    }
-
-    /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
-    if (pkiMsg[idx++] != ASN_OCTET_STRING) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (length != expBlockSz) {
-        WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    XMEMCPY(tmpIv, &pkiMsg[idx], length);
-    idx += length;
-
-    explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0);
-
-    /* read encryptedContent, cont[0] */
-    if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) &&
-        pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-    idx++;
-
-    if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ASN_PARSE_E;
-    }
-
-    if (explicitOctet) {
-        if (pkiMsg[idx++] != ASN_OCTET_STRING) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-            return ASN_PARSE_E;
-        }
-
-        if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-            return ASN_PARSE_E;
-        }
-    }
-
-    encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
-                                                       DYNAMIC_TYPE_PKCS7);
-    if (encryptedContent == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return MEMORY_E;
-    }
-
-    XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
-
-    /* decrypt encryptedContent */
-    ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz,
-                                  tmpIv, expBlockSz, encryptedContent,
-                                  encryptedContentSz, encryptedContent);
-    if (ret != 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-        return ret;
-    }
-
-    padLen = encryptedContent[encryptedContentSz-1];
-
-    /* copy plaintext to output */
-    XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
-
-    /* free memory, zero out keys */
-    ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
-    ForceZero(encryptedContent, encryptedContentSz);
-    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-#endif
-
-    return encryptedContentSz - padLen;
-}
-
-
-#ifndef NO_PKCS7_ENCRYPTED_DATA
-
-/* build PKCS#7 encryptedData content type, return encrypted size */
-int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
-{
-    int ret, idx = 0;
-    int totalSz, padSz, encryptedOutSz;
-
-    int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
-    byte contentInfoSeq[MAX_SEQ_SZ];
-    byte outerContentType[MAX_ALGO_SZ];
-    byte outerContent[MAX_SEQ_SZ];
-
-    int encDataSeqSz, verSz, blockSz;
-    byte encDataSeq[MAX_SEQ_SZ];
-    byte ver[MAX_VERSION_SZ];
-
-    byte* plain = NULL;
-    byte* encryptedContent = NULL;
-
-    int encContentOctetSz, encContentSeqSz, contentTypeSz;
-    int contentEncAlgoSz, ivOctetStringSz;
-    byte encContentSeq[MAX_SEQ_SZ];
-    byte contentType[MAX_ALGO_SZ];
-    byte contentEncAlgo[MAX_ALGO_SZ];
-    byte tmpIv[MAX_CONTENT_IV_SIZE];
-    byte ivOctetString[MAX_OCTET_STR_SZ];
-    byte encContentOctet[MAX_OCTET_STR_SZ];
-
-    byte attribSet[MAX_SET_SZ];
-    EncodedAttrib* attribs = NULL;
-    word32 attribsSz;
-    word32 attribsCount;
-    word32 attribsSetSz;
-
-    byte* flatAttribs = NULL;
-
-    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
-        pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
-        pkcs7->encryptionKeySz == 0)
-        return BAD_FUNC_ARG;
-
-    if (output == NULL || outputSz == 0)
-        return BAD_FUNC_ARG;
-
-    /* outer content type */
-    outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType);
-
-    /* version, 2 if unprotectedAttrs present, 0 if absent */
-    if (pkcs7->unprotectedAttribsSz > 0) {
-        verSz = SetMyVersion(2, ver, 0);
-    } else {
-        verSz = SetMyVersion(0, ver, 0);
-    }
-
-    /* EncryptedContentInfo */
-    contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
-    if (contentTypeSz == 0)
-        return BAD_FUNC_ARG;
-
-    /* allocate encrypted content buffer, do PKCS#7 padding */
-    blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
-    if (blockSz < 0)
-        return blockSz;
-
-    padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz);
-    if (padSz < 0)
-        return padSz;
-
-    encryptedOutSz = pkcs7->contentSz + padSz;
-
-    plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
-                           DYNAMIC_TYPE_PKCS7);
-    if (plain == NULL)
-        return MEMORY_E;
-
-    ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
-                           encryptedOutSz, blockSz);
-    if (ret < 0) {
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
-                                      DYNAMIC_TYPE_PKCS7);
-    if (encryptedContent == NULL) {
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return MEMORY_E;
-    }
-
-    /* put together IV OCTET STRING */
-    ivOctetStringSz = SetOctetString(blockSz, ivOctetString);
-
-    /* build up ContentEncryptionAlgorithmIdentifier sequence,
-       adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
-    contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
-                                 oidBlkType, ivOctetStringSz + blockSz);
-    if (contentEncAlgoSz == 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return BAD_FUNC_ARG;
-    }
-
-    /* encrypt content */
-    ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockSz);
-    if (ret != 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey,
-            pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz,
-            encryptedContent);
-    if (ret != 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0,
-                                    encryptedOutSz, encContentOctet);
-
-    encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
-                                  ivOctetStringSz + blockSz +
-                                  encContentOctetSz + encryptedOutSz,
-                                  encContentSeq);
-
-    /* optional UnprotectedAttributes */
-    if (pkcs7->unprotectedAttribsSz != 0) {
-
-        if (pkcs7->unprotectedAttribs == NULL) {
-            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return BAD_FUNC_ARG;
-        }
-
-        attribs = (EncodedAttrib*)XMALLOC(
-                sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz,
-                pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (attribs == NULL) {
-            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return MEMORY_E;
-        }
-
-        attribsCount = pkcs7->unprotectedAttribsSz;
-        attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz,
-                                     pkcs7->unprotectedAttribs,
-                                     pkcs7->unprotectedAttribsSz);
-
-        flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        if (flatAttribs == NULL) {
-            XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return MEMORY_E;
-        }
-
-        FlattenAttributes(flatAttribs, attribs, attribsCount);
-        attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet);
-
-    } else {
-        attribsSz = 0;
-        attribsSetSz = 0;
-    }
-
-    /* keep track of sizes for outer wrapper layering */
-    totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
-              ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz +
-              attribsSz + attribsSetSz;;
-
-    /* EncryptedData */
-    encDataSeqSz = SetSequence(totalSz, encDataSeq);
-    totalSz += encDataSeqSz;
-
-    /* outer content */
-    outerContentSz = SetExplicit(0, totalSz, outerContent);
-    totalSz += outerContentTypeSz;
-    totalSz += outerContentSz;
-
-    /* ContentInfo */
-    contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
-    totalSz += contentInfoSeqSz;
-
-    if (totalSz > (int)outputSz) {
-        WOLFSSL_MSG("PKCS#7 output buffer too small");
-        if (pkcs7->unprotectedAttribsSz != 0) {
-            XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        }
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return BUFFER_E;
-    }
-
-    XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
-    idx += contentInfoSeqSz;
-    XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
-    idx += outerContentTypeSz;
-    XMEMCPY(output + idx, outerContent, outerContentSz);
-    idx += outerContentSz;
-    XMEMCPY(output + idx, encDataSeq, encDataSeqSz);
-    idx += encDataSeqSz;
-    XMEMCPY(output + idx, ver, verSz);
-    idx += verSz;
-    XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
-    idx += encContentSeqSz;
-    XMEMCPY(output + idx, contentType, contentTypeSz);
-    idx += contentTypeSz;
-    XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
-    idx += contentEncAlgoSz;
-    XMEMCPY(output + idx, ivOctetString, ivOctetStringSz);
-    idx += ivOctetStringSz;
-    XMEMCPY(output + idx, tmpIv, blockSz);
-    idx += blockSz;
-    XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
-    idx += encContentOctetSz;
-    XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
-    idx += encryptedOutSz;
-
-    if (pkcs7->unprotectedAttribsSz != 0) {
-        XMEMCPY(output + idx, attribSet, attribsSetSz);
-        idx += attribsSetSz;
-        XMEMCPY(output + idx, flatAttribs, attribsSz);
-        idx += attribsSz;
-        XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    }
-
-    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-    XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-
-    return idx;
-}
-
-
-/* decode and store unprotected attributes in PKCS7->decodedAttrib. Return
- * 0 on success, negative on error. User must call wc_PKCS7_Free(). */
-static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
-                                             word32 pkiMsgSz, word32* inOutIdx)
-{
-    int ret, attribLen;
-    word32 idx;
-
-    if (pkcs7 == NULL || pkiMsg == NULL ||
-        pkiMsgSz == 0 || inOutIdx == NULL)
-        return BAD_FUNC_ARG;
-
-    idx = *inOutIdx;
-
-    if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
-        return ASN_PARSE_E;
-    idx++;
-
-    if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* loop through attributes */
-    if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) {
-        return ret;
-    }
-
-    *inOutIdx = idx;
-
-    return 0;
-}
-
-
-/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
-int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
-                                 byte* output, word32 outputSz)
-{
-    int ret, version, length, haveAttribs;
-    word32 idx = 0;
-    word32 contentType, encOID;
-
-    int expBlockSz;
-    byte tmpIv[MAX_CONTENT_IV_SIZE];
-
-    int encryptedContentSz;
-    byte padLen;
-    byte* encryptedContent = NULL;
-
-    if (pkcs7 == NULL || pkcs7->encryptionKey == NULL ||
-        pkcs7->encryptionKeySz == 0)
-        return BAD_FUNC_ARG;
-
-    if (pkiMsg == NULL || pkiMsgSz == 0 ||
-        output == NULL || outputSz == 0)
-        return BAD_FUNC_ARG;
-    /* read past ContentInfo, verify type is encrypted-data */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (contentType != ENCRYPTED_DATA) {
-        WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
-        return PKCS7_OID_E;
-    }
-
-    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* remove EncryptedData and version */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* get version, check later */
-    haveAttribs = 0;
-    if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    /* remove EncryptedContentInfo */
-    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID);
-    if (expBlockSz < 0)
-        return expBlockSz;
-
-    /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
-    if (pkiMsg[idx++] != ASN_OCTET_STRING)
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
-        return ASN_PARSE_E;
-
-    if (length != expBlockSz) {
-        WOLFSSL_MSG("Incorrect IV length, must be of content alg block size");
-        return ASN_PARSE_E;
-    }
-
-    XMEMCPY(tmpIv, &pkiMsg[idx], length);
-    idx += length;
-
-    /* read encryptedContent, cont[0] */
-    if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
-        return ASN_PARSE_E;
-
-    if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0)
-        return ASN_PARSE_E;
-
-    encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
-                                      DYNAMIC_TYPE_PKCS7);
-    if (encryptedContent == NULL)
-        return MEMORY_E;
-
-    XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
-    idx += encryptedContentSz;
-
-    /* decrypt encryptedContent */
-    ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
-                                  pkcs7->encryptionKeySz, tmpIv, expBlockSz,
-                                  encryptedContent, encryptedContentSz,
-                                  encryptedContent);
-    if (ret != 0) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        return ret;
-    }
-
-    padLen = encryptedContent[encryptedContentSz-1];
-
-    /* copy plaintext to output */
-    XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
-
-    /* get implicit[1] unprotected attributes, optional */
-    pkcs7->decodedAttrib = NULL;
-    if (idx < pkiMsgSz) {
-
-        haveAttribs = 1;
-
-        ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
-                                                   pkiMsgSz, &idx);
-        if (ret != 0) {
-            ForceZero(encryptedContent, encryptedContentSz);
-            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-            return ASN_PARSE_E;
-        }
-    }
-
-    /* go back and check the version now that attribs have been processed */
-    if ((haveAttribs == 0 && version != 0) ||
-        (haveAttribs == 1 && version != 2) ) {
-        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-        WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
-        return ASN_VERSION_E;
-    }
-
-    ForceZero(encryptedContent, encryptedContentSz);
-    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
-
-    return encryptedContentSz - padLen;
-}
-
-#endif /* NO_PKCS7_ENCRYPTED_DATA */
-
-#else  /* HAVE_PKCS7 */
-
-
-#ifdef _MSC_VER
-    /* 4206 warning for blank file */
-    #pragma warning(disable: 4206)
-#endif
-
-
-#endif /* HAVE_PKCS7 */
-
-
--- a/wolfcrypt/src/poly1305.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1648 +0,0 @@
-/* poly1305.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*
- * Based off the public domain implementations by Andrew Moon
- * and Daniel J. Bernstein
- */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_POLY1305
-#include <wolfssl/wolfcrypt/poly1305.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-#ifdef CHACHA_AEAD_TEST
-    #include <stdio.h>
-#endif
-
-#ifdef _MSC_VER
-    /* 4127 warning constant while(1)  */
-    #pragma warning(disable: 4127)
-#endif
-
-#ifdef USE_INTEL_SPEEDUP
-    #include <emmintrin.h>
-    #include <immintrin.h>
-
-    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
-                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
-        #define NO_AVX2_SUPPORT
-    #endif
-    #if defined(__clang__) && ((__clang_major__ < 3) || \
-                               (__clang_major__ == 3 && __clang_minor__ <= 5))
-        #define NO_AVX2_SUPPORT
-    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
-        #undef NO_AVX2_SUPPORT
-    #endif
-
-    #define HAVE_INTEL_AVX1
-    #ifndef NO_AVX2_SUPPORT
-        #define HAVE_INTEL_AVX2
-    #endif
-#endif
-
-#ifdef USE_INTEL_SPEEDUP
-static word32 intel_flags = 0;
-static word32 cpu_flags_set = 0;
-#endif
-
-#if defined(USE_INTEL_SPEEDUP) || defined(POLY130564)
-    #if defined(_MSC_VER)
-        #define POLY1305_NOINLINE __declspec(noinline)
-    #elif defined(__GNUC__)
-        #define POLY1305_NOINLINE __attribute__((noinline))
-    #else
-        #define POLY1305_NOINLINE
-    #endif
-
-    #if defined(_MSC_VER)
-        #include <intrin.h>
-
-        typedef struct word128 {
-            word64 lo;
-            word64 hi;
-        } word128;
-
-        #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
-        #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; \
-                               out.hi += (out.lo < t) + in.hi; }
-        #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; \
-                                 out.hi += (out.lo < t); }
-        #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
-        #define LO(in) (in.lo)
-
-    #elif defined(__GNUC__)
-        #if defined(__SIZEOF_INT128__)
-            typedef unsigned __int128 word128;
-        #else
-            typedef unsigned word128 __attribute__((mode(TI)));
-        #endif
-
-        #define MUL(out, x, y) out = ((word128)x * y)
-        #define ADD(out, in) out += in
-        #define ADDLO(out, in) out += in
-        #define SHR(in, shift) (word64)(in >> (shift))
-        #define LO(in) (word64)(in)
-    #endif
-#endif
-
-#ifdef USE_INTEL_SPEEDUP
-#ifdef HAVE_INTEL_AVX1
-/* Process one block (16 bytes) of data.
- *
- * ctx  Poly1305 context.
- * m    One block of message data.
- */
-static void poly1305_block_avx(Poly1305* ctx, const unsigned char *m)
-{
-        __asm__ __volatile__ (
-            "movq	(%[ctx]), %%r15\n\t"
-            "movq	24(%[ctx]), %%r8\n\t"
-            "movq	32(%[ctx]), %%r9\n\t"
-            "movq	40(%[ctx]), %%r10\n\t"
-            "xorq	%%rbx, %%rbx\n\t"
-            "movb	%[nfin], %%bl\n\t"
-            "# h += m\n\t"
-            "movq	 (%[m]), %%r11\n\t"
-            "movq	8(%[m]), %%r12\n\t"
-            "addq	%%r11, %%r8\n\t"
-            "adcq	%%r12, %%r9\n\t"
-            "movq	8(%[ctx]), %%rax\n\t"
-            "adcq	%%rbx, %%r10\n\t"
-            "# r[1] * h[0] => rdx, rax ==> t2, t1\n\t"
-            "mulq	%%r8\n\t"
-            "movq	%%rax, %%r12\n\t"
-            "movq	%%rdx, %%r13\n\t"
-            "# r[0] * h[1] => rdx, rax ++> t2, t1\n\t"
-            "movq	%%r15, %%rax\n\t"
-            "mulq	%%r9\n\t"
-            "addq	%%rax, %%r12\n\t"
-            "movq	%%r15, %%rax\n\t"
-            "adcq	%%rdx, %%r13\n\t"
-            "# r[0] * h[0] => rdx, rax ==> t4, t0\n\t"
-            "mulq	%%r8\n\t"
-            "movq	%%rax, %%r11\n\t"
-            "movq	%%rdx, %%r8\n\t"
-            "# r[1] * h[1] => rdx, rax =+> t3, t2\n\t"
-            "movq	8(%[ctx]), %%rax\n\t"
-            "mulq	%%r9\n\t"
-            "#   r[0] * h[2] +> t2\n\t"
-            "addq	352(%[ctx],%%r10,8), %%r13\n\t"
-            "movq	%%rdx, %%r14\n\t"
-            "addq	%%r8, %%r12\n\t"
-            "adcq	%%rax, %%r13\n\t"
-            "#   r[1] * h[2] +> t3\n\t"
-            "adcq	408(%[ctx],%%r10,8), %%r14\n\t"
-            "# r * h in r14, r13, r12, r11 \n\t"
-            "# h = (r * h) mod 2^130 - 5\n\t"
-            "movq	%%r13, %%r10\n\t"
-            "andq	  $-4, %%r13\n\t"
-            "andq	   $3, %%r10\n\t"
-            "addq	%%r13, %%r11\n\t"
-            "movq	%%r13, %%r8\n\t"
-            "adcq	%%r14, %%r12\n\t"
-            "adcq	   $0, %%r10\n\t"
-            "shrdq	   $2, %%r14, %%r8\n\t"
-            "shrq	   $2, %%r14\n\t"
-            "addq	%%r11, %%r8\n\t"
-            "adcq	%%r14, %%r12\n\t"
-            "movq	%%r12, %%r9\n\t"
-            "adcq	   $0, %%r10\n\t"
-            "# h in r10, r9, r8 \n\t"
-            "# Store h to ctx\n\t"
-            "movq       %%r8, 24(%[ctx])\n\t"
-            "movq       %%r9, 32(%[ctx])\n\t"
-            "movq       %%r10, 40(%[ctx])\n\t"
-            :
-            : [m] "r" (m), [ctx] "r" (ctx), [nfin] "m" (ctx->finished)
-            : "rax", "rdx", "r11", "r12", "r13", "r14", "r15", "rbx",
-              "r8", "r9", "r10", "memory"
-        );
-}
-
-/* Process multiple blocks (n * 16 bytes) of data.
- *
- * ctx    Poly1305 context.
- * m      Blocks of message data.
- * bytes  The number of bytes to process.
- */
-POLY1305_NOINLINE static void poly1305_blocks_avx(Poly1305* ctx,
-                                           const unsigned char* m, size_t bytes)
-{
-        __asm__ __volatile__ (
-            "movq	(%[ctx]), %%r15\n\t"
-            "movq	24(%[ctx]), %%r8\n\t"
-            "movq	32(%[ctx]), %%r9\n\t"
-            "movq	40(%[ctx]), %%r10\n"
-        "L_avx_start:\n\t"
-            "# h += m\n\t"
-            "movq	 (%[m]), %%r11\n\t"
-            "movq	8(%[m]), %%r12\n\t"
-            "addq	%%r11, %%r8\n\t"
-            "adcq	%%r12, %%r9\n\t"
-            "movq	8(%[ctx]), %%rax\n\t"
-            "adcq	$0, %%r10\n\t"
-            "# r[1] * h[0] => rdx, rax ==> t2, t1\n\t"
-            "mulq	%%r8\n\t"
-            "movq	%%rax, %%r12\n\t"
-            "movq	%%rdx, %%r13\n\t"
-            "# r[0] * h[1] => rdx, rax ++> t2, t1\n\t"
-            "movq	%%r15, %%rax\n\t"
-            "mulq	%%r9\n\t"
-            "addq	%%rax, %%r12\n\t"
-            "movq	%%r15, %%rax\n\t"
-            "adcq	%%rdx, %%r13\n\t"
-            "# r[0] * h[0] => rdx, rax ==> t4, t0\n\t"
-            "mulq	%%r8\n\t"
-            "movq	%%rax, %%r11\n\t"
-            "movq	%%rdx, %%r8\n\t"
-            "# r[1] * h[1] => rdx, rax =+> t3, t2\n\t"
-            "movq	8(%[ctx]), %%rax\n\t"
-            "mulq	%%r9\n\t"
-            "#   r[0] * h[2] +> t2\n\t"
-            "addq	360(%[ctx],%%r10,8), %%r13\n\t"
-            "movq	%%rdx, %%r14\n\t"
-            "addq	%%r8, %%r12\n\t"
-            "adcq	%%rax, %%r13\n\t"
-            "#   r[1] * h[2] +> t3\n\t"
-            "adcq	416(%[ctx],%%r10,8), %%r14\n\t"
-            "# r * h in r14, r13, r12, r11 \n\t"
-            "# h = (r * h) mod 2^130 - 5\n\t"
-            "movq	%%r13, %%r10\n\t"
-            "andq	  $-4, %%r13\n\t"
-            "andq	   $3, %%r10\n\t"
-            "addq	%%r13, %%r11\n\t"
-            "movq	%%r13, %%r8\n\t"
-            "adcq	%%r14, %%r12\n\t"
-            "adcq	   $0, %%r10\n\t"
-            "shrdq	   $2, %%r14, %%r8\n\t"
-            "shrq	   $2, %%r14\n\t"
-            "addq	%%r11, %%r8\n\t"
-            "adcq	%%r14, %%r12\n\t"
-            "movq	%%r12, %%r9\n\t"
-            "adcq	   $0, %%r10\n\t"
-            "# h in r10, r9, r8 \n\t"
-            "# Next block from message\n\t"
-            "addq	$16, %[m]\n\t"
-            "subq	$16, %[bytes]\n\t"
-            "cmp        $16, %[bytes]\n\t"
-            "jge	L_avx_start\n\t"
-            "# Store h to ctx\n\t"
-            "movq	%%r8, 24(%[ctx])\n\t"
-            "movq	%%r9, 32(%[ctx])\n\t"
-            "movq	%%r10, 40(%[ctx])\n\t"
-            : [m] "+r" (m), [bytes] "+r" (bytes)
-            : [ctx] "r" (ctx)
-            : "rax", "rdx", "r11", "r12", "r13", "r14", "r15",
-              "r8", "r9", "r10", "memory"
-        );
-}
-
-/* Set the key to use when processing data.
- * Initialize the context.
- *
- * ctx  Poly1305 context.
- * key  The key data (16 bytes).
- */
-static void poly1305_setkey_avx(Poly1305* ctx, const byte* key)
-{
-    int i;
-
-    ctx->r[0] = *(word64*)(key + 0) & 0x0ffffffc0fffffffL;
-    ctx->r[1] = *(word64*)(key + 8) & 0x0ffffffc0ffffffcL;
-
-    for (i=0; i<7; i++) {
-        ctx->hm[i + 0] = ctx->r[0] * i;
-        ctx->hm[i + 7] = ctx->r[1] * i;
-    }
-
-    /* h (accumulator) = 0 */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-
-    /* save pad for later */
-    ctx->pad[0] = *(word64*)(key + 16);
-    ctx->pad[1] = *(word64*)(key + 24);
-
-    ctx->leftover = 0;
-    ctx->finished = 1;
-}
-
-/* Calculate the final result - authentication data.
- * Zeros out the private data in the context.
- *
- * ctx  Poly1305 context.
- * mac  Buffer to hold 16 bytes.
- */
-static void poly1305_final_avx(Poly1305* ctx, byte* mac)
-{
-    word64 h0, h1, h2;
-
-    /* process the remaining block */
-    if (ctx->leftover) {
-        size_t i = ctx->leftover;
-        ctx->buffer[i] = 1;
-        for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
-            ctx->buffer[i] = 0;
-        ctx->finished = 0;
-        poly1305_block_avx(ctx, ctx->buffer);
-    }
-
-    h0 = ctx->h[0];
-    h1 = ctx->h[1];
-    h2 = ctx->h[2];
-
-    /* h %= p */
-    /* h = (h + pad) */
-    __asm__ __volatile__ (
-        "# mod 2^130 - 5\n\t"
-        "movq	%[h2],  %%r13\n\t"
-        "andq	 $0x3, %[h2]\n\t"
-        "shrq	 $0x2, %%r13\n\t"
-        "leaq	(%%r13, %%r13, 4), %%r13\n\t"
-        "add	 %%r13, %[h0]\n\t"
-        "adc	   $0, %[h1]\n\t"
-        "adc	   $0, %[h2]\n\t"
-        "# Fixup when between (1 << 130) - 1 and (1 << 130) - 5\n\t"
-        "movq	%[h0], %%r13\n\t"
-        "movq	%[h1], %%r14\n\t"
-        "movq	%[h2], %%r15\n\t"
-        "addq	$5, %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "andq	$3, %%r15\n\t"
-        "cmpq   $4, %%r12\n\t"
-        "cmove	%%r13, %[h0]\n\t"
-        "cmove	%%r14, %[h1]\n\t"
-        "cmove	%%r15, %[h2]\n\t"
-        "# h += pad\n\t"
-        "add	%[p0], %[h0]\n\t"
-        "adc	%[p1], %[h1]\n\t"
-        "movq	%[h0], (%[m])\n\t"
-        "movq	%[h1], 8(%[m])\n\t"
-        : [h0] "+r" (h0), [h1] "+r" (h1), [h2] "+r" (h2),
-          [p0] "+r" (ctx->pad[0]), [p1] "+r" (ctx->pad[1])
-        : [m] "r" (mac)
-        : "memory", "r15", "r14", "r13", "r12"
-    );
-
-    /* zero out the state */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-    ctx->r[0] = 0;
-    ctx->r[1] = 0;
-    ctx->pad[0] = 0;
-    ctx->pad[1] = 0;
-}
-#endif
-
-#ifdef HAVE_INTEL_AVX2
-#if defined(_MSC_VER)
-    #define POLY1305_NOINLINE __declspec(noinline)
-#elif defined(__GNUC__)
-    #define POLY1305_NOINLINE __attribute__((noinline))
-#else
-    #define POLY1305_NOINLINE
-#endif
-
-/* Load H into five 256-bit registers.
- *
- * h is the memory location of the data - 26 of 32 bits.
- * h0-h4 the 4 H values with 26 bits stored in 64 for multiply.
- */
-#define LOAD_H(h, h0, h1, h2, h3, h4)  \
-    "vmovdqu	   ("#h"), "#h0"\n\t"  \
-    "vmovdqu	 32("#h"), "#h1"\n\t"  \
-    "vmovdqu	 64("#h"), "#h2"\n\t"  \
-    "vmovdqu	 96("#h"), "#h3"\n\t"  \
-    "vmovdqu	128("#h"), "#h4"\n\t"
-
-/* Store H, five 256-bit registers, packed.
- *
- * h is the memory location of the data - 26 bits in 32.
- * h0-h4 the 4 H values with 26 bits stored in 64.
- * x4 is the xmm register of h4.
- */
-#define STORE_H(h, h0, h1, h2, h3, h4, x4)      \
-    "vmovdqu	 "#h0",    ("#h")\n\t"          \
-    "vmovdqu	 "#h1",  32("#h")\n\t"          \
-    "vmovdqu	 "#h2",  64("#h")\n\t"          \
-    "vmovdqu	 "#h3",  96("#h")\n\t"          \
-    "vmovdqu	 "#h4", 128("#h")\n\t"
-
-/* Load four powers of r into position to be multiplied by the 4 H values.
- *
- * r0-r4 holds the loaded values with 26 bits stored in 64 for multiply.
- * t0-t3 are temporary registers.
- */
-#define LOAD_Rx4(r0, r1, r2, r3, r4,                     \
-                 t0, t1, t2, t3)                         \
-    "vmovdqu		224(%[ctx]), "#r3"\n\t"          \
-    "vmovdqu		256(%[ctx]), "#r2"\n\t"          \
-    "vmovdqu		288(%[ctx]), "#r1"\n\t"          \
-    "vmovdqu		320(%[ctx]), "#r0"\n\t"          \
-    "vpermq		$0xd8, "#r0", "#r0"\n\t"         \
-    "vpermq		$0xd8, "#r1", "#r1"\n\t"         \
-    "vpermq		$0xd8, "#r2", "#r2"\n\t"         \
-    "vpermq		$0xd8, "#r3", "#r3"\n\t"         \
-    "vpunpcklqdq	"#r1", "#r0", "#t0"\n\t"         \
-    "vpunpckhqdq	"#r1", "#r0", "#t1"\n\t"         \
-    "vpunpcklqdq	"#r3", "#r2", "#t2"\n\t"         \
-    "vpunpckhqdq	"#r3", "#r2", "#t3"\n\t"         \
-    "vperm2i128		$0x20, "#t2", "#t0", "#r0"\n\t"  \
-    "vperm2i128		$0x31, "#t2", "#t0", "#r2"\n\t"  \
-    "vperm2i128		$0x20, "#t3", "#t1", "#r4"\n\t"  \
-    "vpsrlq		  $32, "#r0", "#r1"\n\t"         \
-    "vpsrlq		  $32, "#r2", "#r3"\n\t"
-
-/* Load the r^4 value into position to be multiplied by all 4 H values.
- *
- * r4 holds r^4 as five 26 bits each in 32.
- * r0-r4 holds the loaded values with 26 bits stored in 64 for multiply.
- * t0-t1 are temporary registers.
- */
-#define LOAD_R4(r4, r40, r41, r42, r43, r44, \
-                t0, t1)                      \
-    "vmovdqu	"#r4", "#t0"\n\t"            \
-    "vpermq	 $0x0, "#t0", "#r40"\n\t"    \
-    "vpsrlq	  $32, "#t0", "#t1"\n\t"     \
-    "vpermq	$0x55, "#t0", "#r42"\n\t"    \
-    "vpermq	$0xaa, "#t0", "#r44"\n\t"    \
-    "vpermq	 $0x0, "#t1", "#r41"\n\t"    \
-    "vpermq	$0x55, "#t1", "#r43"\n\t"
-
-/* Multiply the top 4 26-bit values in 64 bits of each H by 5 for reduction in
- * multiply.
- *
- * s1-s4 are each 64 bit value in r1-r4 multiplied by 5.
- * r1-r4 are the top 4
- */
-#define MUL5(s1, s2, s3, s4, r1, r2, r3, r4) \
-    "vpslld	   $2, "#r1", "#s1"\n\t"     \
-    "vpslld	   $2, "#r2", "#s2"\n\t"     \
-    "vpslld	   $2, "#r3", "#s3"\n\t"     \
-    "vpslld	   $2, "#r4", "#s4"\n\t"     \
-    "vpaddq	"#s1", "#r1", "#s1"\n\t"     \
-    "vpaddq	"#s2", "#r2", "#s2"\n\t"     \
-    "vpaddq	"#s3", "#r3", "#s3"\n\t"     \
-    "vpaddq	"#s4", "#r4", "#s4"\n\t"
-
-/* Add the 4 H values together.
- * Each 64 bits in a register is 26 bits of one of the H values.
- *
- * h0-h4 contains the 4 H values.
- * t1-t4 are temporary registers.
- */
-#define FINALIZE_H(h0, h1, h2, h3, h4,    \
-                   t0, t1, t2, t3, t4)    \
-    "vpsrldq	$8, "#h0", "#t0"\n\t"     \
-    "vpsrldq	$8, "#h1", "#t1"\n\t"     \
-    "vpsrldq	$8, "#h2", "#t2"\n\t"     \
-    "vpsrldq	$8, "#h3", "#t3"\n\t"     \
-    "vpsrldq	$8, "#h4", "#t4"\n\t"     \
-    "vpaddq	"#h0", "#t0", "#h0"\n\t"  \
-    "vpaddq	"#h1", "#t1", "#h1"\n\t"  \
-    "vpaddq	"#h2", "#t2", "#h2"\n\t"  \
-    "vpaddq	"#h3", "#t3", "#h3"\n\t"  \
-    "vpaddq	"#h4", "#t4", "#h4"\n\t"  \
-    "vpermq	$0x02, "#h0", "#t0"\n\t"  \
-    "vpermq	$0x02, "#h1", "#t1"\n\t"  \
-    "vpermq	$0x02, "#h2", "#t2"\n\t"  \
-    "vpermq	$0x02, "#h3", "#t3"\n\t"  \
-    "vpermq	$0x02, "#h4", "#t4"\n\t"  \
-    "vpaddq	"#h0", "#t0", "#h0"\n\t"  \
-    "vpaddq	"#h1", "#t1", "#h1"\n\t"  \
-    "vpaddq	"#h2", "#t2", "#h2"\n\t"  \
-    "vpaddq	"#h3", "#t3", "#h3"\n\t"  \
-    "vpaddq	"#h4", "#t4", "#h4"\n\t"
-
-/* Move 32 bits from each xmm register to a 32 bit register.
- *
- * x0-x4 are the xmm version of the ymm registers used.
- * t0-t4 are the 32-bit registers to store data in.
- */
-#define MOVE_TO_32(x0, x1, x2, x3, x4,  \
-                   t0, t1, t2, t3, t4)  \
-    "vmovd	"#x0", "#t0"\n\t"       \
-    "vmovd	"#x1", "#t1"\n\t"       \
-    "vmovd	"#x2", "#t2"\n\t"       \
-    "vmovd	"#x3", "#t3"\n\t"       \
-    "vmovd	"#x4", "#t4"\n\t"
-
-/* Multiply using AVX2 instructions.
- * Each register contains up to 32 bits of data in 64 bits.
- * This is a 4 way parallel multiply.
- *
- * h0-h4 contain 4 H values with the 32 bits of each per register.
- * r0-r4 contain the 4 powers of r.
- * s1-s4 contain r1-r4 times 5.
- * t0-t4 and v0-v3 are temporary registers.
- */
-#define MUL_AVX2(h0, h1, h2, h3, h4,        \
-                 r0, r1, r2, r3, r4,        \
-                 s1, s2, s3, s4,            \
-                 t0, t1, t2, t3, t4,        \
-                 v0, v1, v2, v3)            \
-    "vpmuludq	"#s1", "#h4", "#t0"\n\t"    \
-    "vpmuludq	"#s2", "#h3", "#v0"\n\t"    \
-    "vpmuludq	"#s2", "#h4", "#t1"\n\t"    \
-    "vpmuludq	"#s3", "#h3", "#v1"\n\t"    \
-    "vpmuludq	"#s3", "#h4", "#t2"\n\t"    \
-    "vpaddq	"#t0", "#v0", "#t0"\n\t"    \
-    "vpmuludq	"#s3", "#h2", "#v2"\n\t"    \
-    "vpmuludq	"#s4", "#h4", "#t3"\n\t"    \
-    "vpaddq	"#t1", "#v1", "#t1"\n\t"    \
-    "vpmuludq	"#s4", "#h1", "#v3"\n\t"    \
-    "vpmuludq	"#s4", "#h2", "#v0"\n\t"    \
-    "vpaddq	"#t0", "#v2", "#t0"\n\t"    \
-    "vpmuludq	"#s4", "#h3", "#v1"\n\t"    \
-    "vpmuludq	"#r0", "#h3", "#v2"\n\t"    \
-    "vpaddq	"#t0", "#v3", "#t0"\n\t"    \
-    "vpmuludq	"#r0", "#h4", "#t4"\n\t"    \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"    \
-    "vpmuludq	"#r0", "#h0", "#v3"\n\t"    \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"    \
-    "vpmuludq	"#r0", "#h1", "#v0"\n\t"    \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"    \
-    "vpmuludq	"#r0", "#h2", "#v1"\n\t"    \
-    "vpmuludq	"#r1", "#h2", "#v2"\n\t"    \
-    "vpaddq	"#t0", "#v3", "#t0"\n\t"    \
-    "vpmuludq	"#r1", "#h3", "#v3"\n\t"    \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"    \
-    "vpmuludq	"#r1", "#h0", "#v0"\n\t"    \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"    \
-    "vpmuludq	"#r1", "#h1", "#v1"\n\t"    \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"    \
-    "vpmuludq	"#r2", "#h1", "#v2"\n\t"    \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"    \
-    "vpmuludq	"#r2", "#h2", "#v3"\n\t"    \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"    \
-    "vpmuludq	"#r2", "#h0", "#v0"\n\t"    \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"    \
-    "vpmuludq	"#r3", "#h0", "#v1"\n\t"    \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"    \
-    "vpmuludq	"#r3", "#h1", "#v2"\n\t"    \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"    \
-    "vpmuludq	"#r4", "#h0", "#v3"\n\t"    \
-    "vpaddq	"#t2", "#v0", "#t2"\n\t"    \
-    "vpaddq	"#t3", "#v1", "#t3"\n\t"    \
-    "vpaddq	"#t4", "#v2", "#t4"\n\t"    \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"
-
-/* Load the 4 blocks of the message.
- *
- * m the address of the message to load.
- * m0-m4 is the loaded message with 32 bits in 64. Loaded so data is parallel.
- * hi is the high bits of the 4 m (1 << 128 as not final block).
- * z is zero.
- */
-#define LOAD_M(m, m0, m1, m2, m3, m4, hi, z)     \
-    "vmovdqu      (%[m]), "#m0"\n\t"             \
-    "vmovdqu    32(%[m]), "#m1"\n\t"             \
-    "vperm2i128	$0x20, "#m1", "#m0", "#m2"\n\t"  \
-    "vperm2i128	$0x31, "#m1", "#m0", "#m0"\n\t"  \
-    "vpunpckldq	"#m0", "#m2", "#m1"\n\t"         \
-    "vpunpckhdq	"#m0", "#m2", "#m3"\n\t"         \
-    "vpunpckldq	 "#z", "#m1", "#m0"\n\t"         \
-    "vpunpckhdq	 "#z", "#m1", "#m1"\n\t"         \
-    "vpunpckldq	 "#z", "#m3", "#m2"\n\t"         \
-    "vpunpckhdq	 "#z", "#m3", "#m3"\n\t"         \
-    "vmovdqu	"#hi", "#m4"\n\t"                \
-    "vpsllq	   $6, "#m1", "#m1"\n\t"         \
-    "vpsllq	  $12, "#m2", "#m2"\n\t"         \
-    "vpsllq	  $18, "#m3", "#m3"\n\t"
-
-
-/* Multiply using AVX2 instructions - adding with message.
- * Each register contains up to 32 bits of data in 64 bits.
- * This is a 4 way parallel multiply.
- * The message data is loaded first and the multiplication adds into it.
- *
- * h0-h4 contain 4 H values with the 32 bits of each per register.
- * r0-r4 contain the 4 powers of r.
- * s1-s4 contain r1-r4 times 5.
- * t0-t4 and v0-v3 are temporary registers.
- * hi is the high bits of the 4 m (1 << 128 as not final block).
- * z is zero.
- */
-#define MUL_ADD_AVX2(h0, h1, h2, h3, h4,         \
-                     r0, r1, r2, r3, r4,         \
-                     s1, s2, s3, s4,             \
-                     t0, t1, t2, t3, t4,         \
-                     v0, v1, v2, v3,             \
-                     hi, z)                      \
-    "vmovdqu      (%[m]), "#t0"\n\t"             \
-    "vmovdqu    32(%[m]), "#t1"\n\t"             \
-    "vperm2i128	$0x20, "#t1", "#t0", "#t2"\n\t"  \
-    "vperm2i128	$0x31, "#t1", "#t0", "#t0"\n\t"  \
-    "vpunpckldq	"#t0", "#t2", "#t1"\n\t"         \
-    "vpunpckhdq	"#t0", "#t2", "#t3"\n\t"         \
-    "vpunpckldq	 "#z", "#t1", "#t0"\n\t"         \
-    "vpunpckhdq	 "#z", "#t1", "#t1"\n\t"         \
-    "vpunpckldq	 "#z", "#t3", "#t2"\n\t"         \
-    "vpunpckhdq	 "#z", "#t3", "#t3"\n\t"         \
-    "vmovdqu	"#hi", "#t4"\n\t"                \
-    "vpsllq	   $6, "#t1", "#t1"\n\t"         \
-    "vpsllq	  $12, "#t2", "#t2"\n\t"         \
-    "vpsllq	  $18, "#t3", "#t3"\n\t"         \
-    "vpmuludq	"#s1", "#h4", "#v0"\n\t"         \
-    "vpaddq     "#t0", "#v0", "#t0"\n\t"         \
-    "vpmuludq	"#s2", "#h3", "#v0"\n\t"         \
-    "vpmuludq	"#s2", "#h4", "#v1"\n\t"         \
-    "vpaddq     "#t1", "#v1", "#t1"\n\t"         \
-    "vpmuludq	"#s3", "#h3", "#v1"\n\t"         \
-    "vpmuludq	"#s3", "#h4", "#v2"\n\t"         \
-    "vpaddq     "#t2", "#v2", "#t2"\n\t"         \
-    "vpaddq	"#t0", "#v0", "#t0"\n\t"         \
-    "vpmuludq	"#s3", "#h2", "#v2"\n\t"         \
-    "vpmuludq	"#s4", "#h4", "#v3"\n\t"         \
-    "vpaddq     "#t3", "#v3", "#t3"\n\t"         \
-    "vpaddq	"#t1", "#v1", "#t1"\n\t"         \
-    "vpmuludq	"#s4", "#h1", "#v3"\n\t"         \
-    "vpmuludq	"#s4", "#h2", "#v0"\n\t"         \
-    "vpaddq	"#t0", "#v2", "#t0"\n\t"         \
-    "vpmuludq	"#s4", "#h3", "#v1"\n\t"         \
-    "vpmuludq	"#r0", "#h3", "#v2"\n\t"         \
-    "vpaddq	"#t0", "#v3", "#t0"\n\t"         \
-    "vpmuludq	"#r0", "#h4", "#v3"\n\t"         \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"         \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"         \
-    "vpmuludq	"#r0", "#h0", "#v3"\n\t"         \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"         \
-    "vpmuludq	"#r0", "#h1", "#v0"\n\t"         \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"         \
-    "vpmuludq	"#r0", "#h2", "#v1"\n\t"         \
-    "vpmuludq	"#r1", "#h2", "#v2"\n\t"         \
-    "vpaddq	"#t0", "#v3", "#t0"\n\t"         \
-    "vpmuludq	"#r1", "#h3", "#v3"\n\t"         \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"         \
-    "vpmuludq	"#r1", "#h0", "#v0"\n\t"         \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"         \
-    "vpmuludq	"#r1", "#h1", "#v1"\n\t"         \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"         \
-    "vpmuludq	"#r2", "#h1", "#v2"\n\t"         \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"         \
-    "vpmuludq	"#r2", "#h2", "#v3"\n\t"         \
-    "vpaddq	"#t1", "#v0", "#t1"\n\t"         \
-    "vpmuludq	"#r2", "#h0", "#v0"\n\t"         \
-    "vpaddq	"#t2", "#v1", "#t2"\n\t"         \
-    "vpmuludq	"#r3", "#h0", "#v1"\n\t"         \
-    "vpaddq	"#t3", "#v2", "#t3"\n\t"         \
-    "vpmuludq	"#r3", "#h1", "#v2"\n\t"         \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"         \
-    "vpmuludq	"#r4", "#h0", "#v3"\n\t"         \
-    "vpaddq	"#t2", "#v0", "#t2"\n\t"         \
-    "vpaddq	"#t3", "#v1", "#t3"\n\t"         \
-    "vpaddq	"#t4", "#v2", "#t4"\n\t"         \
-    "vpaddq	"#t4", "#v3", "#t4"\n\t"
-
-/* Reduce the 64 bits of data to 26 bits.
- *
- * h0-h4 contain the reduced H values.
- * m0-m4 contain the 4 H values to reduce.
- * t0-t2 are temporaries.
- * mask contains the 26-bit mask for each 64 bit value in the 256 bit register.
- */
-#define REDUCE(h0, h1, h2, h3, h4,          \
-               m0, m1, m2, m3, m4,          \
-               t0, t1, t2, mask)            \
-    "vpsrlq	    $26, "#m0", "#t0"\n\t"  \
-    "vpsrlq	    $26, "#m3", "#t1"\n\t"  \
-    "vpand	"#mask", "#m0", "#m0"\n\t"  \
-    "vpand	"#mask", "#m3", "#m3"\n\t"  \
-    "vpaddq	  "#m1", "#t0", "#m1"\n\t"  \
-    "vpaddq	  "#m4", "#t1", "#m4"\n\t"  \
-                                            \
-    "vpsrlq	    $26, "#m1", "#t0"\n\t"  \
-    "vpsrlq	    $26, "#m4", "#t1"\n\t"  \
-    "vpand	"#mask", "#m1", "#h1"\n\t"  \
-    "vpand	"#mask", "#m4", "#h4"\n\t"  \
-    "vpaddq	  "#m2", "#t0", "#m2"\n\t"  \
-    "vpslld	     $2, "#t1", "#t2"\n\t"  \
-    "vpaddd	  "#t2", "#t1", "#t2"\n\t"  \
-                                            \
-    "vpsrlq	    $26, "#m2", "#t0"\n\t"  \
-    "vpaddq	  "#m0", "#t2", "#m0"\n\t"  \
-    "vpsrlq	    $26, "#m0", "#t1"\n\t"  \
-    "vpand	"#mask", "#m2", "#h2"\n\t"  \
-    "vpand	"#mask", "#m0", "#h0"\n\t"  \
-    "vpaddq	  "#m3", "#t0", "#m3"\n\t"  \
-    "vpaddq	  "#h1", "#t1", "#h1"\n\t"  \
-                                            \
-    "vpsrlq	    $26, "#m3", "#t0"\n\t"  \
-    "vpand	"#mask", "#m3", "#h3"\n\t"  \
-    "vpaddq	  "#h4", "#t0", "#h4"\n\t"  \
-
-
-/* Process multiple blocks (n * 16 bytes) of data.
- *
- * ctx    Poly1305 context.
- * m      Blocks of message data.
- * bytes  The number of bytes to process.
- */
-POLY1305_NOINLINE static void poly1305_blocks_avx2(Poly1305* ctx,
-                                           const unsigned char* m, size_t bytes)
-{
-    ALIGN256 word64 r4[5][4];
-    ALIGN256 word64 s[4][4];
-    register word32 t0 asm("r8") = 0;
-    register word32 t1 asm("r9") = 0;
-    register word32 t2 asm("r10") = 0;
-    register word32 t3 asm("r11") = 0;
-    register word32 t4 asm("r12") = 0;
-    static const word64 mask[4] = { 0x0000000003ffffff, 0x0000000003ffffff,
-                                    0x0000000003ffffff, 0x0000000003ffffff };
-    static const word64 hibit[4] = { 0x1000000, 0x1000000,
-                                     0x1000000, 0x1000000 };
-
-    __asm__ __volatile__ (
-        "vpxor		%%ymm15, %%ymm15, %%ymm15\n\t"
-        "cmpb		$1, %[started]\n\t"
-        "je		L_begin\n\t"
-        "cmpb		$1, %[fin]\n\t"
-        "je		L_begin\n\t"
-        "# Load the message data\n\t"
-        LOAD_M(m, %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, %[hibit], %%ymm15)
-        "vmovdqu	%[mask], %%ymm14\n\t"
-        "# Reduce, in place, the message data\n\t"
-        REDUCE(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-               %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-               %%ymm10, %%ymm11, %%ymm12, %%ymm14)
-        "addq		$64, %[m]\n\t"
-        "subq		$64, %[bytes]\n\t"
-        "jz		L_store\n\t"
-        "jmp		L_load_r4\n\t"
-        "\n"
-    "L_begin:\n\t"
-        "# Load the H values.\n\t"
-        LOAD_H(%[h], %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4)
-        "# Check if there is a power of r to load - otherwise use r^4.\n\t"
-        "cmpb		$0, %[fin]\n\t"
-        "je		L_load_r4\n\t"
-        "\n\t"
-        "# Load the 4 powers of r - r^4, r^3, r^2, r^1.\n\t"
-        LOAD_Rx4(%%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-                 %%ymm10, %%ymm11, %%ymm12, %%ymm13)
-        "jmp		L_mul_5\n\t"
-        "\n"
-     "L_load_r4:\n\t"
-        "# Load r^4 into all four positions.\n\t"
-        LOAD_R4(320(%[ctx]), %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-                %%ymm13, %%ymm14)
-        "\n"
-    "L_mul_5:\n\t"
-        "# Multiply top 4 26-bit values of all four H by 5\n\t"
-        MUL5(%%ymm10, %%ymm11, %%ymm12, %%ymm13, %%ymm6, %%ymm7, %%ymm8, %%ymm9)
-        "# Store powers of r and multiple of 5 for use in multiply.\n\t"
-        "vmovdqa	%%ymm10,    (%[s])\n\t"
-        "vmovdqa	%%ymm11,  32(%[s])\n\t"
-        "vmovdqa	%%ymm12,  64(%[s])\n\t"
-        "vmovdqa	%%ymm13,  96(%[s])\n\t"
-        "vmovdqa	%%ymm5 ,    (%[r4])\n\t"
-        "vmovdqa	%%ymm6 ,  32(%[r4])\n\t"
-        "vmovdqa	%%ymm7 ,  64(%[r4])\n\t"
-        "vmovdqa	%%ymm8 ,  96(%[r4])\n\t"
-        "vmovdqa	%%ymm9 , 128(%[r4])\n\t"
-        "vmovdqu	%[mask], %%ymm14\n\t"
-        "\n"
-        "# If not finished then loop over data\n\t"
-        "cmpb		$0x1, %[fin]\n\t"
-        "jne		L_start\n\t"
-        "# Do last multiply, reduce, add the four H together and move to\n\t"
-        "# 32-bit registers\n\t"
-        MUL_AVX2(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-                 (%[r4]), 32(%[r4]), 64(%[r4]), 96(%[r4]), 128(%[r4]),
-                 (%[s]), 32(%[s]), 64(%[s]), 96(%[s]),
-                 %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-                 %%ymm10, %%ymm11, %%ymm12, %%ymm13)
-        REDUCE(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-               %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-               %%ymm10, %%ymm11, %%ymm12, %%ymm14)
-        FINALIZE_H(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-                   %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9)
-        MOVE_TO_32(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4,
-                   %[t0], %[t1], %[t2], %[t3], %[t4])
-        "jmp		L_end\n\t"
-        "\n"
-    "L_start:\n\t"
-        MUL_ADD_AVX2(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-                     (%[r4]), 32(%[r4]), 64(%[r4]), 96(%[r4]), 128(%[r4]),
-                     (%[s]), 32(%[s]), 64(%[s]), 96(%[s]),
-                     %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-                     %%ymm10, %%ymm11, %%ymm12, %%ymm13,
-                     %[hibit], %%ymm15)
-        REDUCE(%%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4,
-               %%ymm5, %%ymm6, %%ymm7, %%ymm8, %%ymm9,
-               %%ymm10, %%ymm11, %%ymm12, %%ymm14)
-        "addq		$64, %[m]\n\t"
-        "subq		$64, %[bytes]\n\t"
-        "jnz		L_start\n\t"
-        "\n"
-    "L_store:\n\t"
-        "# Store four H values - state\n\t"
-        STORE_H(%[h], %%ymm0, %%ymm1, %%ymm2, %%ymm3, %%ymm4, %%xmm4)
-        "\n"
-    "L_end:\n\t"
-        : [m] "+r" (m), [bytes] "+r" (bytes),
-          [t0] "+r" (t0), [t1] "+r" (t1), [t2] "+r" (t2),
-          [t3] "+r" (t3), [t4] "+r" (t4)
-        : [ctx] "r" (ctx), [h] "r" (ctx->hh),
-          [r4] "r" (r4), [s] "r" (s),
-          [fin] "m" (ctx->finished), [started] "m" (ctx->started),
-          [mask] "m" (mask), [hibit] "m" (hibit)
-        : "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7",
-          "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15",
-          "memory"
-    );
-
-    if (ctx->finished)
-    {
-        word64 h0, h1, h2, c;
-
-        /* Convert to 64-bit form. */
-        h0 = (((word64)(t1 & 0x3FFFF)) << 26) +  t0;
-        h1 = (((word64)(t3 &   0x3FF)) << 34) +
-             (((word64) t2           ) <<  8) + (t1 >> 18);
-        h2 = (((word64) t4           ) << 16) + (t3 >> 10);
-
-        /* Perform modulur reduction. */
-                     c = (h1 >> 44); h1 &= 0xfffffffffff;
-        h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-        h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-        h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
-        h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-        h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-        h1 += c;
-
-        /* Convert from 42/44/44 to 2/64/64 bits used and store result. */
-        ctx->h[0] =  h0        | (h1 << 44);
-        ctx->h[1] = (h1 >> 20) | (h2 << 24);
-        ctx->h[2] =  h2 >> 40;
-    }
-
-    ctx->started = 1;
-}
-
-/* Multiply two 130-bit numbers in 64-bit registers and reduce.
- * 44 + 44 + 42 = 130 bits
- *
- * r0-r2 are the first operand and the result.
- * a0-a2 are the second operand.
- */
-#define MUL_64(r0, r1, r2, a0, a1, a2)                                       \
-    s1 = a1 * (5 << 2);                                                      \
-    s2 = a2 * (5 << 2);                                                      \
-    MUL(d0, r0, a0); MUL(d, r1, s2); ADD(d0, d); MUL(d, r2, s1); ADD(d0, d); \
-    MUL(d1, r0, a1); MUL(d, r1, a0); ADD(d1, d); MUL(d, r2, s2); ADD(d1, d); \
-    MUL(d2, r0, a2); MUL(d, r1, a1); ADD(d2, d); MUL(d, r2, a0); ADD(d2, d); \
-                                                                             \
-                  c = SHR(d0, 44); r0 = LO(d0) & 0xfffffffffff;              \
-    ADDLO(d1, c); c = SHR(d1, 44); r1 = LO(d1) & 0xfffffffffff;              \
-    ADDLO(d2, c); c = SHR(d2, 42); r2 = LO(d2) & 0x3ffffffffff;              \
-    r0  += c * 5; c = (r0 >> 44);  r0 =    r0  & 0xfffffffffff;              \
-    r1  += c
-
-#define SQR_64(r0, r1, r2)                                      \
-    s2 = r2 * (5 << 2);                                         \
-    MUL(d0, r1, s2); ADD(d0, d0); MUL(d, r0, r0); ADD(d0, d);   \
-    MUL(d1, r0, r1); ADD(d1, d1); MUL(d, r2, s2); ADD(d1, d);   \
-    MUL(d2, r0, r2); ADD(d2, d2); MUL(d, r1, r1); ADD(d2, d);   \
-                                                                \
-                  c = SHR(d0, 44); r0 = LO(d0) & 0xfffffffffff; \
-    ADDLO(d1, c); c = SHR(d1, 44); r1 = LO(d1) & 0xfffffffffff; \
-    ADDLO(d2, c); c = SHR(d2, 42); r2 = LO(d2) & 0x3ffffffffff; \
-    r0  += c * 5; c = (r0 >> 44);  r0 =    r0  & 0xfffffffffff; \
-    r1  += c
-
-/* Store the 130-bit number in 64-bit registers as 26-bit values in 32 bits.
- *
- * r0-r2 contains the 130-bit number in 64-bit registers.
- * r is the address of where to store the 26 of 32 bits result.
- */
-#define CONV_64_TO_32(r0, r1, r2, r)                      \
-    r[0] = (word32)( r0                    ) & 0x3ffffff; \
-    r[1] = (word32)((r0 >> 26) | (r1 << 18)) & 0x3ffffff; \
-    r[2] = (word32)( r1 >> 8               ) & 0x3ffffff; \
-    r[3] = (word32)((r1 >> 34) | (r2 << 10)) & 0x3ffffff; \
-    r[4] = (word32)( r2 >> 16              )
-
-/* Calculate R^1, R^2, R^3 and R^4 and store them in the context.
- *
- * ctx    Poly1305 context.
- */
-static void poly1305_calc_powers(Poly1305* ctx)
-{
-    word64 r0, r1, r2, t0, t1, c;
-    word64 r20, r21, r22;
-    word64 r30, r31, r32;
-    word64 r40, r41, r42;
-    word64 s1, s2;
-    word128 d0, d1, d2, d;
-
-    t0 = ctx->r[0];
-    t1 = ctx->r[1];
-    r0 = ( t0                    ) & 0xfffffffffff;
-    r1 = ((t0 >> 44) | (t1 << 20)) & 0xfffffffffff;
-    r2 = ((t1 >> 24)             ) & 0x00fffffffff;
-
-    /* Store r^1 */
-    CONV_64_TO_32(r0, r1, r2, ctx->r1);
-
-    /* Calc and store r^2 */
-    r20 = r0; r21 = r1; r22 = r2;
-    SQR_64(r20, r21, r22);
-    CONV_64_TO_32(r20, r21, r22, ctx->r2);
-
-    /* Calc and store r^3 */
-    r30 = r20; r31 = r21; r32 = r22;
-    MUL_64(r30, r31, r32, r0, r1, r2);
-    CONV_64_TO_32(r30, r31, r32, ctx->r3);
-
-    /* Calc and store r^4 */
-    r40 = r20; r41 = r21; r42 = r22;
-    SQR_64(r40, r41, r42);
-    CONV_64_TO_32(r40, r41, r42, ctx->r4);
-
-}
-
-/* Set the key to use when processing data.
- * Initialize the context.
- * Calls AVX set key function as final function calls AVX code.
- *
- * ctx  Poly1305 context.
- * key  The key data (16 bytes).
- */
-static void poly1305_setkey_avx2(Poly1305* ctx, const byte* key)
-{
-    poly1305_setkey_avx(ctx, key);
-
-    __asm__ __volatile__ (
-        "vpxor		%%ymm0, %%ymm0, %%ymm0\n\t"
-        "vmovdqu	%%ymm0,    (%[hh])\n\t"
-        "vmovdqu	%%ymm0,  32(%[hh])\n\t"
-        "vmovdqu	%%ymm0,  64(%[hh])\n\t"
-        "vmovdqu	%%ymm0,  96(%[hh])\n\t"
-        "vmovdqu	%%ymm0, 128(%[hh])\n\t"
-        :
-        : [hh] "r" (ctx->hh)
-        : "memory", "ymm0"
-    );
-
-    ctx->leftover = 0;
-    ctx->finished = 0;
-    ctx->started = 0;
-}
-
-/* Calculate the final result - authentication data.
- * Zeros out the private data in the context.
- * Calls AVX final function to quickly process last blocks.
- *
- * ctx  Poly1305 context.
- * mac  Buffer to hold 16 bytes - authentication data.
- */
-static void poly1305_final_avx2(Poly1305* ctx, byte* mac)
-{
-    int i, j;
-    int l = (int)ctx->leftover;
-
-    ctx->finished = 1;
-    if (ctx->started)
-        poly1305_blocks_avx2(ctx, ctx->buffer, POLY1305_BLOCK_SIZE * 4);
-
-    i = l & ~(POLY1305_BLOCK_SIZE - 1);
-    if (i > 0)
-        poly1305_blocks_avx(ctx, ctx->buffer, i);
-    ctx->leftover -= i;
-    for (j = 0; i < l; i++, j++)
-        ctx->buffer[j] = ctx->buffer[i];
-
-    poly1305_final_avx(ctx, mac);
-
-    /* zero out the state */
-    __asm__ __volatile__ (
-        "vpxor		%%ymm0, %%ymm0, %%ymm0\n\t"
-        "vmovdqu	%%ymm0,    (%[hh])\n\t"
-        "vmovdqu	%%ymm0,  32(%[hh])\n\t"
-        "vmovdqu	%%ymm0,  64(%[hh])\n\t"
-        "vmovdqu	%%ymm0,  96(%[hh])\n\t"
-        "vmovdqu	%%ymm0, 128(%[hh])\n\t"
-        "vmovdqu	%%ymm0,    (%[r1])\n\t"
-        "vmovdqu	%%ymm0,    (%[r2])\n\t"
-        "vmovdqu	%%ymm0,    (%[r3])\n\t"
-        "vmovdqu	%%ymm0,    (%[r4])\n\t"
-        :
-        : [hh] "r" (ctx->hh), [r1] "r" (ctx->r1), [r2] "r" (ctx->r2),
-          [r3] "r" (ctx->r3), [r4] "r" (ctx->r4)
-        : "memory", "ymm0"
-    );
-
-    ctx->leftover = 0;
-    ctx->finished = 0;
-    ctx->started = 0;
-}
-#endif
-
-#elif defined(POLY130564)
-
-    static word64 U8TO64(const byte* p)
-    {
-        return
-            (((word64)(p[0] & 0xff)      ) |
-             ((word64)(p[1] & 0xff) <<  8) |
-             ((word64)(p[2] & 0xff) << 16) |
-             ((word64)(p[3] & 0xff) << 24) |
-             ((word64)(p[4] & 0xff) << 32) |
-             ((word64)(p[5] & 0xff) << 40) |
-             ((word64)(p[6] & 0xff) << 48) |
-             ((word64)(p[7] & 0xff) << 56));
-    }
-
-    static void U64TO8(byte* p, word64 v) {
-        p[0] = (v      ) & 0xff;
-        p[1] = (v >>  8) & 0xff;
-        p[2] = (v >> 16) & 0xff;
-        p[3] = (v >> 24) & 0xff;
-        p[4] = (v >> 32) & 0xff;
-        p[5] = (v >> 40) & 0xff;
-        p[6] = (v >> 48) & 0xff;
-        p[7] = (v >> 56) & 0xff;
-    }
-
-#else /* if not 64 bit then use 32 bit */
-
-    static word32 U8TO32(const byte *p)
-    {
-        return
-            (((word32)(p[0] & 0xff)      ) |
-             ((word32)(p[1] & 0xff) <<  8) |
-             ((word32)(p[2] & 0xff) << 16) |
-             ((word32)(p[3] & 0xff) << 24));
-    }
-
-    static void U32TO8(byte *p, word32 v) {
-        p[0] = (v      ) & 0xff;
-        p[1] = (v >>  8) & 0xff;
-        p[2] = (v >> 16) & 0xff;
-        p[3] = (v >> 24) & 0xff;
-    }
-#endif
-
-
-static void U32TO64(word32 v, byte* p)
-{
-    XMEMSET(p, 0, 8);
-    p[0] = (v & 0xFF);
-    p[1] = (v >>  8) & 0xFF;
-    p[2] = (v >> 16) & 0xFF;
-    p[3] = (v >> 24) & 0xFF;
-}
-
-static void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
-                            size_t bytes)
-{
-#ifdef USE_INTEL_SPEEDUP
-    /* AVX2 is handled in wc_Poly1305Update. */
-    poly1305_blocks_avx(ctx, m, bytes);
-#elif defined(POLY130564)
-    const word64 hibit = (ctx->finished) ? 0 : ((word64)1 << 40); /* 1 << 128 */
-    word64 r0,r1,r2;
-    word64 s1,s2;
-    word64 h0,h1,h2;
-    word64 c;
-    word128 d0,d1,d2,d;
-
-    r0 = ctx->r[0];
-    r1 = ctx->r[1];
-    r2 = ctx->r[2];
-
-    h0 = ctx->h[0];
-    h1 = ctx->h[1];
-    h2 = ctx->h[2];
-
-    s1 = r1 * (5 << 2);
-    s2 = r2 * (5 << 2);
-
-    while (bytes >= POLY1305_BLOCK_SIZE) {
-        word64 t0,t1;
-
-        /* h += m[i] */
-        t0 = U8TO64(&m[0]);
-        t1 = U8TO64(&m[8]);
-
-        h0 += (( t0                    ) & 0xfffffffffff);
-        h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
-        h2 += (((t1 >> 24)             ) & 0x3ffffffffff) | hibit;
-
-        /* h *= r */
-        MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
-        MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
-        MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
-
-        /* (partial) h %= p */
-                      c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
-        ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
-        ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
-        h0  += c * 5; c = (h0 >> 44);  h0 =    h0  & 0xfffffffffff;
-        h1  += c;
-
-        m += POLY1305_BLOCK_SIZE;
-        bytes -= POLY1305_BLOCK_SIZE;
-    }
-
-    ctx->h[0] = h0;
-    ctx->h[1] = h1;
-    ctx->h[2] = h2;
-
-#else /* if not 64 bit then use 32 bit */
-    const word32 hibit = (ctx->finished) ? 0 : (1 << 24); /* 1 << 128 */
-    word32 r0,r1,r2,r3,r4;
-    word32 s1,s2,s3,s4;
-    word32 h0,h1,h2,h3,h4;
-    word64 d0,d1,d2,d3,d4;
-    word32 c;
-
-
-    r0 = ctx->r[0];
-    r1 = ctx->r[1];
-    r2 = ctx->r[2];
-    r3 = ctx->r[3];
-    r4 = ctx->r[4];
-
-    s1 = r1 * 5;
-    s2 = r2 * 5;
-    s3 = r3 * 5;
-    s4 = r4 * 5;
-
-    h0 = ctx->h[0];
-    h1 = ctx->h[1];
-    h2 = ctx->h[2];
-    h3 = ctx->h[3];
-    h4 = ctx->h[4];
-
-    while (bytes >= POLY1305_BLOCK_SIZE) {
-        /* h += m[i] */
-        h0 += (U8TO32(m+ 0)     ) & 0x3ffffff;
-        h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
-        h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
-        h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
-        h4 += (U8TO32(m+12) >> 8) | hibit;
-
-        /* h *= r */
-        d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) +
-             ((word64)h3 * s2) + ((word64)h4 * s1);
-        d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) +
-             ((word64)h3 * s3) + ((word64)h4 * s2);
-        d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) +
-             ((word64)h3 * s4) + ((word64)h4 * s3);
-        d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) +
-             ((word64)h3 * r0) + ((word64)h4 * s4);
-        d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) +
-             ((word64)h3 * r1) + ((word64)h4 * r0);
-
-        /* (partial) h %= p */
-                      c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff;
-        d1 += c;      c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff;
-        d2 += c;      c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff;
-        d3 += c;      c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff;
-        d4 += c;      c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff;
-        h0 += c * 5;  c =  (h0 >> 26); h0 =                h0 & 0x3ffffff;
-        h1 += c;
-
-        m += POLY1305_BLOCK_SIZE;
-        bytes -= POLY1305_BLOCK_SIZE;
-    }
-
-    ctx->h[0] = h0;
-    ctx->h[1] = h1;
-    ctx->h[2] = h2;
-    ctx->h[3] = h3;
-    ctx->h[4] = h4;
-
-#endif /* end of 64 bit cpu blocks or 32 bit cpu */
-}
-
-static void poly1305_block(Poly1305* ctx, const unsigned char *m)
-{
-#ifdef USE_INTEL_SPEEDUP
-    /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */
-    poly1305_block_avx(ctx, m);
-#else
-    poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE);
-#endif
-}
-
-
-int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz)
-{
-#if defined(POLY130564)
-    word64 t0,t1;
-#endif
-
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef CHACHA_AEAD_TEST
-    word32 k;
-    printf("Poly key used:\n");
-    for (k = 0; k < keySz; k++) {
-        printf("%02x", key[k]);
-        if ((k+1) % 8 == 0)
-            printf("\n");
-    }
-    printf("\n");
-#endif
-
-    if (keySz != 32 || ctx == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef USE_INTEL_SPEEDUP
-    if (!cpu_flags_set) {
-        intel_flags = cpuid_get_flags();
-        cpu_flags_set = 1;
-    }
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(intel_flags))
-        poly1305_setkey_avx2(ctx, key);
-    else
-    #endif
-        poly1305_setkey_avx(ctx, key);
-#elif defined(POLY130564)
-
-    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-    t0 = U8TO64(key + 0);
-    t1 = U8TO64(key + 8);
-
-    ctx->r[0] = ( t0                    ) & 0xffc0fffffff;
-    ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
-    ctx->r[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;
-
-    /* h (accumulator) = 0 */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-
-    /* save pad for later */
-    ctx->pad[0] = U8TO64(key + 16);
-    ctx->pad[1] = U8TO64(key + 24);
-
-    ctx->leftover = 0;
-    ctx->finished = 0;
-
-#else /* if not 64 bit then use 32 bit */
-
-    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-    ctx->r[0] = (U8TO32(key +  0)     ) & 0x3ffffff;
-    ctx->r[1] = (U8TO32(key +  3) >> 2) & 0x3ffff03;
-    ctx->r[2] = (U8TO32(key +  6) >> 4) & 0x3ffc0ff;
-    ctx->r[3] = (U8TO32(key +  9) >> 6) & 0x3f03fff;
-    ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff;
-
-    /* h = 0 */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-    ctx->h[3] = 0;
-    ctx->h[4] = 0;
-
-    /* save pad for later */
-    ctx->pad[0] = U8TO32(key + 16);
-    ctx->pad[1] = U8TO32(key + 20);
-    ctx->pad[2] = U8TO32(key + 24);
-    ctx->pad[3] = U8TO32(key + 28);
-
-    ctx->leftover = 0;
-    ctx->finished = 0;
-
-#endif
-
-    return 0;
-}
-
-
-int wc_Poly1305Final(Poly1305* ctx, byte* mac)
-{
-#ifdef USE_INTEL_SPEEDUP
-#elif defined(POLY130564)
-
-    word64 h0,h1,h2,c;
-    word64 g0,g1,g2;
-    word64 t0,t1;
-
-#else
-
-    word32 h0,h1,h2,h3,h4,c;
-    word32 g0,g1,g2,g3,g4;
-    word64 f;
-    word32 mask;
-
-#endif
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef USE_INTEL_SPEEDUP
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(intel_flags))
-        poly1305_final_avx2(ctx, mac);
-    else
-    #endif
-        poly1305_final_avx(ctx, mac);
-#elif defined(POLY130564)
-
-    /* process the remaining block */
-    if (ctx->leftover) {
-        size_t i = ctx->leftover;
-        ctx->buffer[i] = 1;
-        for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
-            ctx->buffer[i] = 0;
-        ctx->finished = 1;
-        poly1305_block(ctx, ctx->buffer);
-    }
-
-    /* fully carry h */
-    h0 = ctx->h[0];
-    h1 = ctx->h[1];
-    h2 = ctx->h[2];
-
-                 c = (h1 >> 44); h1 &= 0xfffffffffff;
-    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-    h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
-    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
-    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
-    h1 += c;
-
-    /* compute h + -p */
-    g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
-    g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
-    g2 = h2 + c - ((word64)1 << 42);
-
-    /* select h if h < p, or h + -p if h >= p */
-    c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1;
-    g0 &= c;
-    g1 &= c;
-    g2 &= c;
-    c = ~c;
-    h0 = (h0 & c) | g0;
-    h1 = (h1 & c) | g1;
-    h2 = (h2 & c) | g2;
-
-    /* h = (h + pad) */
-    t0 = ctx->pad[0];
-    t1 = ctx->pad[1];
-
-    h0 += (( t0                    ) & 0xfffffffffff)    ;
-    c = (h0 >> 44); h0 &= 0xfffffffffff;
-    h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
-    c = (h1 >> 44); h1 &= 0xfffffffffff;
-    h2 += (((t1 >> 24)             ) & 0x3ffffffffff) + c;
-    h2 &= 0x3ffffffffff;
-
-    /* mac = h % (2^128) */
-    h0 = ((h0      ) | (h1 << 44));
-    h1 = ((h1 >> 20) | (h2 << 24));
-
-    U64TO8(mac + 0, h0);
-    U64TO8(mac + 8, h1);
-
-    /* zero out the state */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-    ctx->r[0] = 0;
-    ctx->r[1] = 0;
-    ctx->r[2] = 0;
-    ctx->pad[0] = 0;
-    ctx->pad[1] = 0;
-
-#else /* if not 64 bit then use 32 bit */
-
-    /* process the remaining block */
-    if (ctx->leftover) {
-        size_t i = ctx->leftover;
-        ctx->buffer[i++] = 1;
-        for (; i < POLY1305_BLOCK_SIZE; i++)
-            ctx->buffer[i] = 0;
-        ctx->finished = 1;
-        poly1305_block(ctx, ctx->buffer);
-    }
-
-    /* fully carry h */
-    h0 = ctx->h[0];
-    h1 = ctx->h[1];
-    h2 = ctx->h[2];
-    h3 = ctx->h[3];
-    h4 = ctx->h[4];
-
-                 c = h1 >> 26; h1 = h1 & 0x3ffffff;
-    h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
-    h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
-    h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
-    h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
-    h1 +=     c;
-
-    /* compute h + -p */
-    g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
-    g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
-    g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
-    g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
-    g4 = h4 + c - (1 << 26);
-
-    /* select h if h < p, or h + -p if h >= p */
-    mask = (g4 >> ((sizeof(word32) * 8) - 1)) - 1;
-    g0 &= mask;
-    g1 &= mask;
-    g2 &= mask;
-    g3 &= mask;
-    g4 &= mask;
-    mask = ~mask;
-    h0 = (h0 & mask) | g0;
-    h1 = (h1 & mask) | g1;
-    h2 = (h2 & mask) | g2;
-    h3 = (h3 & mask) | g3;
-    h4 = (h4 & mask) | g4;
-
-    /* h = h % (2^128) */
-    h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
-    h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
-    h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
-    h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
-
-    /* mac = (h + pad) % (2^128) */
-    f = (word64)h0 + ctx->pad[0]            ; h0 = (word32)f;
-    f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f;
-    f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f;
-    f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f;
-
-    U32TO8(mac + 0, h0);
-    U32TO8(mac + 4, h1);
-    U32TO8(mac + 8, h2);
-    U32TO8(mac + 12, h3);
-
-    /* zero out the state */
-    ctx->h[0] = 0;
-    ctx->h[1] = 0;
-    ctx->h[2] = 0;
-    ctx->h[3] = 0;
-    ctx->h[4] = 0;
-    ctx->r[0] = 0;
-    ctx->r[1] = 0;
-    ctx->r[2] = 0;
-    ctx->r[3] = 0;
-    ctx->r[4] = 0;
-    ctx->pad[0] = 0;
-    ctx->pad[1] = 0;
-    ctx->pad[2] = 0;
-    ctx->pad[3] = 0;
-
-#endif
-
-    return 0;
-}
-
-
-int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes)
-{
-    size_t i;
-
-#ifdef CHACHA_AEAD_TEST
-    word32 k;
-    printf("Raw input to poly:\n");
-    for (k = 0; k < bytes; k++) {
-        printf("%02x", m[k]);
-        if ((k+1) % 16 == 0)
-            printf("\n");
-    }
-    printf("\n");
-#endif
-
-    if (ctx == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef USE_INTEL_SPEEDUP
-    #ifdef HAVE_INTEL_AVX2
-    if (IS_INTEL_AVX2(intel_flags)) {
-        /* handle leftover */
-        if (ctx->leftover) {
-            size_t want = sizeof(ctx->buffer) - ctx->leftover;
-            if (want > bytes)
-                want = bytes;
-
-            for (i = 0; i < want; i++)
-                ctx->buffer[ctx->leftover + i] = m[i];
-            bytes -= (word32)want;
-            m += want;
-            ctx->leftover += want;
-            if (ctx->leftover < sizeof(ctx->buffer))
-                return 0;
-
-            if (!ctx->started)
-                poly1305_calc_powers(ctx);
-            poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer));
-            ctx->leftover = 0;
-        }
-
-        /* process full blocks */
-        if (bytes >= sizeof(ctx->buffer)) {
-            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
-
-            if (!ctx->started)
-                poly1305_calc_powers(ctx);
-            poly1305_blocks_avx2(ctx, m, want);
-            m += want;
-            bytes -= (word32)want;
-        }
-
-        /* store leftover */
-        if (bytes) {
-            for (i = 0; i < bytes; i++)
-                ctx->buffer[ctx->leftover + i] = m[i];
-            ctx->leftover += bytes;
-        }
-    }
-    else
-    #endif
-#endif
-    {
-        /* handle leftover */
-        if (ctx->leftover) {
-            size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover);
-            if (want > bytes)
-                want = bytes;
-            for (i = 0; i < want; i++)
-                ctx->buffer[ctx->leftover + i] = m[i];
-            bytes -= (word32)want;
-            m += want;
-            ctx->leftover += want;
-            if (ctx->leftover < POLY1305_BLOCK_SIZE)
-                return 0;
-            poly1305_block(ctx, ctx->buffer);
-            ctx->leftover = 0;
-        }
-
-        /* process full blocks */
-        if (bytes >= POLY1305_BLOCK_SIZE) {
-            size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1));
-            poly1305_blocks(ctx, m, want);
-            m += want;
-            bytes -= (word32)want;
-        }
-
-        /* store leftover */
-        if (bytes) {
-            for (i = 0; i < bytes; i++)
-                ctx->buffer[ctx->leftover + i] = m[i];
-            ctx->leftover += bytes;
-        }
-    }
-
-    return 0;
-}
-
-
-/*  Takes in an initialized Poly1305 struct that has a key loaded and creates
-    a MAC (tag) using recent TLS AEAD padding scheme.
-    ctx        : Initialized Poly1305 struct to use
-    additional : Additional data to use
-    addSz      : Size of additional buffer
-    input      : Input buffer to create tag from
-    sz         : Size of input buffer
-    tag        : Buffer to hold created tag
-    tagSz      : Size of input tag buffer (must be at least
-                 WC_POLY1305_MAC_SZ(16))
- */
-int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
-                    byte* input, word32 sz, byte* tag, word32 tagSz)
-{
-    int ret;
-    byte padding[WC_POLY1305_PAD_SZ - 1];
-    word32 paddingLen;
-    byte little64[16];
-
-    XMEMSET(padding, 0, sizeof(padding));
-
-    /* sanity check on arguments */
-    if (ctx == NULL || input == NULL || tag == NULL ||
-                                                   tagSz < WC_POLY1305_MAC_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* additional allowed to be 0 */
-    if (addSz > 0) {
-        if (additional == NULL)
-            return BAD_FUNC_ARG;
-
-        /* additional data plus padding */
-        if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
-            return ret;
-        }
-        paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1);
-        if (paddingLen) {
-            if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
-                return ret;
-            }
-        }
-    }
-
-    /* input plus padding */
-    if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
-        return ret;
-    }
-    paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1);
-    if (paddingLen) {
-        if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
-            return ret;
-        }
-    }
-
-    /* size of additional data and input as little endian 64 bit types */
-    U32TO64(addSz, little64);
-    U32TO64(sz, little64 + 8);
-    ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
-    if (ret)
-    {
-        return ret;
-    }
-
-    /* Finalize the auth tag */
-    ret = wc_Poly1305Final(ctx, tag);
-
-    return ret;
-
-}
-#endif /* HAVE_POLY1305 */
-
-
--- a/wolfcrypt/src/pwdbased.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,740 +0,0 @@
-/* pwdbased.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_PWDBASED
-
-#include <wolfssl/wolfcrypt/pwdbased.h>
-#include <wolfssl/wolfcrypt/hmac.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
-int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
-    const byte* passwd, int passwdLen, const byte* salt, int saltLen,
-    int iterations, int hashType, void* heap)
-{
-    int  err;
-    int  keyLeft, ivLeft, i;
-    int  digestLeft, store;
-    int  keyOutput = 0;
-    int  diestLen;
-    byte digest[WC_MAX_DIGEST_SIZE];
-#ifdef WOLFSSL_SMALL_STACK
-    wc_HashAlg* hash = NULL;
-#else
-    wc_HashAlg  hash[1];
-#endif
-    enum wc_HashType hashT;
-
-    (void)heap;
-
-    if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){
-        return BAD_FUNC_ARG;
-    }
-
-    if (iterations <= 0)
-        iterations = 1;
-
-    hashT = wc_HashTypeConvert(hashType);
-    err = wc_HashGetDigestSize(hashT);
-    if (err < 0)
-        return err;
-    diestLen = err;
-
-    /* initialize hash */
-#ifdef WOLFSSL_SMALL_STACK
-    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap,
-                                DYNAMIC_TYPE_HASHCTX);
-    if (hash == NULL)
-        return MEMORY_E;
-#endif
-
-    err = wc_HashInit(hash, hashT);
-    if (err != 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
-    #endif
-        return err;
-    }
-
-    keyLeft = keyLen;
-    ivLeft  = ivLen;
-    while (keyOutput < (keyLen + ivLen)) {
-        digestLeft = diestLen;
-        /* D_(i - 1) */
-        if (keyOutput) { /* first time D_0 is empty */
-            err = wc_HashUpdate(hash, hashT, digest, diestLen);
-            if (err != 0) break;
-        }
-
-        /* data */
-        err = wc_HashUpdate(hash, hashT, passwd, passwdLen);
-        if (err != 0) break;
-
-        /* salt */
-        if (salt) {
-            err = wc_HashUpdate(hash, hashT, salt, saltLen);
-            if (err != 0) break;
-        }
-
-        err = wc_HashFinal(hash, hashT, digest);
-        if (err != 0) break;
-
-        /* count */
-        for (i = 1; i < iterations; i++) {
-            err = wc_HashUpdate(hash, hashT, digest, diestLen);
-            if (err != 0) break;
-
-            err = wc_HashFinal(hash, hashT, digest);
-            if (err != 0) break;
-        }
-
-        if (keyLeft) {
-            store = min(keyLeft, diestLen);
-            XMEMCPY(&key[keyLen - keyLeft], digest, store);
-
-            keyOutput  += store;
-            keyLeft    -= store;
-            digestLeft -= store;
-        }
-
-        if (ivLeft && digestLeft) {
-            store = min(ivLeft, digestLeft);
-            if (iv != NULL)
-                XMEMCPY(&iv[ivLen - ivLeft],
-                        &digest[diestLen - digestLeft], store);
-            keyOutput += store;
-            ivLeft    -= store;
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    if (err != 0)
-        return err;
-
-    if (keyOutput != (keyLen + ivLen))
-        return BUFFER_E;
-
-    return err;
-}
-
-/* PKCS#5 v1.5 */
-int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
-           int sLen, int iterations, int kLen, int hashType)
-{
-    return wc_PBKDF1_ex(output, kLen, NULL, 0,
-        passwd, pLen, salt, sLen, iterations, hashType, NULL);
-}
-
-
-int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
-           int sLen, int iterations, int kLen, int hashType)
-{
-    word32 i = 1;
-    int    hLen;
-    int    j, ret;
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  buffer;
-    Hmac*  hmac;
-#else
-    byte   buffer[WC_MAX_DIGEST_SIZE];
-    Hmac   hmac[1];
-#endif
-    enum wc_HashType hashT;
-
-    if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (iterations <= 0)
-        iterations = 1;
-
-    hashT = wc_HashTypeConvert(hashType);
-    hLen = wc_HashGetDigestSize(hashT);
-    if (hLen < 0)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_SMALL_STACK
-    buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buffer == NULL)
-        return MEMORY_E;
-    hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC);
-    if (buffer == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_HmacInit(hmac, NULL, INVALID_DEVID);
-    if (ret == 0) {
-        /* use int hashType here, since HMAC FIPS uses the old unique value */
-        ret = wc_HmacSetKey(hmac, hashType, passwd, pLen);
-
-        while (ret == 0 && kLen) {
-            int currentLen;
-
-            ret = wc_HmacUpdate(hmac, salt, sLen);
-            if (ret != 0)
-                break;
-
-            /* encode i */
-            for (j = 0; j < 4; j++) {
-                byte b = (byte)(i >> ((3-j) * 8));
-
-                ret = wc_HmacUpdate(hmac, &b, 1);
-                if (ret != 0)
-                    break;
-            }
-
-            /* check ret from inside for loop */
-            if (ret != 0)
-                break;
-
-            ret = wc_HmacFinal(hmac, buffer);
-            if (ret != 0)
-                break;
-
-            currentLen = min(kLen, hLen);
-            XMEMCPY(output, buffer, currentLen);
-
-            for (j = 1; j < iterations; j++) {
-                ret = wc_HmacUpdate(hmac, buffer, hLen);
-                if (ret != 0)
-                    break;
-                ret = wc_HmacFinal(hmac, buffer);
-                if (ret != 0)
-                    break;
-                xorbuf(output, buffer, currentLen);
-            }
-
-            /* check ret from inside for loop */
-            if (ret != 0)
-                break;
-
-            output += currentLen;
-            kLen   -= currentLen;
-            i++;
-        }
-        wc_HmacFree(hmac);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC);
-#endif
-
-    return ret;
-}
-
-/* helper for PKCS12_PBKDF(), does hash operation */
-static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
-                 byte* Ai, word32 u, int iterations)
-{
-    int i;
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    wc_HashAlg* hash = NULL;
-#else
-    wc_HashAlg  hash[1];
-#endif
-    enum wc_HashType hashT;
-
-    if (buffer == NULL || Ai == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    hashT = wc_HashTypeConvert(hashType);
-
-    /* initialize hash */
-#ifdef WOLFSSL_SMALL_STACK
-    hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
-                                DYNAMIC_TYPE_HASHCTX);
-    if (hash == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_HashInit(hash, hashT);
-    if (ret != 0) {
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
-    #endif
-        return ret;
-    }
-
-    ret = wc_HashUpdate(hash, hashT, buffer, totalLen);
-
-    if (ret == 0)
-        ret = wc_HashFinal(hash, hashT, Ai);
-
-    for (i = 1; i < iterations; i++) {
-        if (ret == 0)
-            ret = wc_HashUpdate(hash, hashT, Ai, u);
-        if (ret == 0)
-            ret = wc_HashFinal(hash, hashT, Ai);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
-#endif
-
-    return ret;
-}
-
-
-int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
-    const byte* salt, int saltLen, int iterations, int kLen, int hashType,
-    int id)
-{
-    return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
-                              iterations, kLen, hashType, id, NULL);
-}
-
-
-/* extended API that allows a heap hint to be used */
-int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
-                       const byte* salt, int saltLen, int iterations, int kLen,
-                       int hashType, int id, void* heap)
-{
-    /* all in bytes instead of bits */
-    word32 u, v, dLen, pLen, iLen, sLen, totalLen;
-    int    dynamic = 0;
-    int    ret = 0;
-    int    i;
-    byte   *D, *S, *P, *I;
-#ifdef WOLFSSL_SMALL_STACK
-    byte   staticBuffer[1]; /* force dynamic usage */
-#else
-    byte   staticBuffer[1024];
-#endif
-    byte*  buffer = staticBuffer;
-
-#ifdef WOLFSSL_SMALL_STACK
-    byte*  Ai;
-    byte*  B;
-#else
-    byte   Ai[WC_MAX_DIGEST_SIZE];
-    byte   B[WC_MAX_BLOCK_SIZE];
-#endif
-    enum wc_HashType hashT;
-
-    (void)heap;
-
-    if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (iterations <= 0)
-        iterations = 1;
-
-    hashT = wc_HashTypeConvert(hashType);
-    ret = wc_HashGetDigestSize(hashT);
-    if (ret < 0)
-        return ret;
-    u = ret;
-
-    ret = wc_HashGetBlockSize(hashT);
-    if (ret < 0)
-        return ret;
-    v = ret;
-
-#ifdef WOLFSSL_SMALL_STACK
-    Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (Ai == NULL)
-        return MEMORY_E;
-
-    B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (B == NULL) {
-        XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
-#endif
-
-    XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE);
-    XMEMSET(B,  0, WC_MAX_BLOCK_SIZE);
-
-    dLen = v;
-    sLen = v * ((saltLen + v - 1) / v);
-    if (passLen)
-        pLen = v * ((passLen + v - 1) / v);
-    else
-        pLen = 0;
-    iLen = sLen + pLen;
-
-    totalLen = dLen + sLen + pLen;
-
-    if (totalLen > sizeof(staticBuffer)) {
-        buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
-        if (buffer == NULL) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            XFREE(B,  heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return MEMORY_E;
-        }
-        dynamic = 1;
-    }
-
-    D = buffer;
-    S = D + dLen;
-    P = S + sLen;
-    I = S;
-
-    XMEMSET(D, id, dLen);
-
-    for (i = 0; i < (int)sLen; i++)
-        S[i] = salt[i % saltLen];
-    for (i = 0; i < (int)pLen; i++)
-        P[i] = passwd[i % passLen];
-
-    while (kLen > 0) {
-        word32 currentLen;
-        mp_int B1;
-
-        ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
-        if (ret < 0)
-            break;
-
-        for (i = 0; i < (int)v; i++)
-            B[i] = Ai[i % u];
-
-        if (mp_init(&B1) != MP_OKAY)
-            ret = MP_INIT_E;
-        else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
-            ret = MP_READ_E;
-        else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
-            ret = MP_ADD_E;
-
-        if (ret != 0) {
-            mp_clear(&B1);
-            break;
-        }
-
-        for (i = 0; i < (int)iLen; i += v) {
-            int    outSz;
-            mp_int i1;
-            mp_int res;
-
-            if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
-                ret = MP_INIT_E;
-                break;
-            }
-            if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
-                ret = MP_READ_E;
-            else if (mp_add(&i1, &B1, &res) != MP_OKAY)
-                ret = MP_ADD_E;
-            else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
-                ret = MP_TO_E;
-            else {
-                if (outSz > (int)v) {
-                    /* take off MSB */
-                    byte  tmp[129];
-                    ret = mp_to_unsigned_bin(&res, tmp);
-                    XMEMCPY(I + i, tmp + 1, v);
-                }
-                else if (outSz < (int)v) {
-                    XMEMSET(I + i, 0, v - outSz);
-                    ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
-                }
-                else
-                    ret = mp_to_unsigned_bin(&res, I + i);
-            }
-
-            mp_clear(&i1);
-            mp_clear(&res);
-            if (ret < 0) break;
-        }
-
-        currentLen = min(kLen, (int)u);
-        XMEMCPY(output, Ai, currentLen);
-        output += currentLen;
-        kLen   -= currentLen;
-        mp_clear(&B1);
-    }
-
-    if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(B,  heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#ifdef HAVE_SCRYPT
-/* Rotate the 32-bit value a by b bits to the left.
- *
- * a  32-bit value.
- * b  Number of bits to rotate.
- * returns rotated value.
- */
-#define R(a, b) rotlFixed(a, b)
-
-/* One round of Salsa20/8.
- * Code taken from RFC 7914: scrypt PBKDF.
- *
- * out  Output buffer.
- * in   Input data to hash.
- */
-static void scryptSalsa(word32* out, word32* in)
-{
-    int    i;
-    word32 x[16];
-
-#ifdef LITTLE_ENDIAN_ORDER
-    for (i = 0; i < 16; ++i)
-        x[i] = in[i];
-#else
-    for (i = 0; i < 16; i++)
-        x[i] = ByteReverseWord32(in[i]);
-#endif
-    for (i = 8; i > 0; i -= 2) {
-        x[ 4] ^= R(x[ 0] + x[12],  7);  x[ 8] ^= R(x[ 4] + x[ 0],  9);
-        x[12] ^= R(x[ 8] + x[ 4], 13);  x[ 0] ^= R(x[12] + x[ 8], 18);
-        x[ 9] ^= R(x[ 5] + x[ 1],  7);  x[13] ^= R(x[ 9] + x[ 5],  9);
-        x[ 1] ^= R(x[13] + x[ 9], 13);  x[ 5] ^= R(x[ 1] + x[13], 18);
-        x[14] ^= R(x[10] + x[ 6],  7);  x[ 2] ^= R(x[14] + x[10],  9);
-        x[ 6] ^= R(x[ 2] + x[14], 13);  x[10] ^= R(x[ 6] + x[ 2], 18);
-        x[ 3] ^= R(x[15] + x[11],  7);  x[ 7] ^= R(x[ 3] + x[15],  9);
-        x[11] ^= R(x[ 7] + x[ 3], 13);  x[15] ^= R(x[11] + x[ 7], 18);
-        x[ 1] ^= R(x[ 0] + x[ 3],  7);  x[ 2] ^= R(x[ 1] + x[ 0],  9);
-        x[ 3] ^= R(x[ 2] + x[ 1], 13);  x[ 0] ^= R(x[ 3] + x[ 2], 18);
-        x[ 6] ^= R(x[ 5] + x[ 4],  7);  x[ 7] ^= R(x[ 6] + x[ 5],  9);
-        x[ 4] ^= R(x[ 7] + x[ 6], 13);  x[ 5] ^= R(x[ 4] + x[ 7], 18);
-        x[11] ^= R(x[10] + x[ 9],  7);  x[ 8] ^= R(x[11] + x[10],  9);
-        x[ 9] ^= R(x[ 8] + x[11], 13);  x[10] ^= R(x[ 9] + x[ 8], 18);
-        x[12] ^= R(x[15] + x[14],  7);  x[13] ^= R(x[12] + x[15],  9);
-        x[14] ^= R(x[13] + x[12], 13);  x[15] ^= R(x[14] + x[13], 18);
-    }
-#ifdef LITTLE_ENDIAN_ORDER
-    for (i = 0; i < 16; ++i)
-        out[i] = in[i] + x[i];
-#else
-    for (i = 0; i < 16; i++)
-        out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
-#endif
-}
-
-/* Mix a block using Salsa20/8.
- * Based on RFC 7914: scrypt PBKDF.
- *
- * b  Blocks to mix.
- * y  Temporary storage.
- * r  Size of the block.
- */
-static void scryptBlockMix(byte* b, byte* y, int r)
-{
-    byte x[64];
-#ifdef WORD64_AVAILABLE
-    word64* b64 = (word64*)b;
-    word64* y64 = (word64*)y;
-    word64* x64 = (word64*)x;
-#else
-    word32* b32 = (word32*)b;
-    word32* y32 = (word32*)y;
-    word32* x32 = (word32*)x;
-#endif
-    int  i;
-    int  j;
-
-    /* Step 1. */
-    XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
-    /* Step 2. */
-    for (i = 0; i < 2 * r; i++)
-    {
-#ifdef WORD64_AVAILABLE
-        for (j = 0; j < 8; j++)
-            x64[j] ^= b64[i * 8 + j];
-#else
-        for (j = 0; j < 16; j++)
-            x32[j] ^= b32[i * 16 + j];
-#endif
-        scryptSalsa((word32*)x, (word32*)x);
-        XMEMCPY(y + i * 64, x, sizeof(x));
-    }
-    /* Step 3. */
-    for (i = 0; i < r; i++) {
-#ifdef WORD64_AVAILABLE
-        for (j = 0; j < 8; j++) {
-            b64[i * 8 + j] = y64[2 * i * 8 + j];
-            b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
-        }
-#else
-        for (j = 0; j < 16; j++) {
-            b32[i * 16 + j] = y32[2 * i * 16 + j];
-            b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
-        }
-#endif
-    }
-}
-
-/* Random oracles mix.
- * Based on RFC 7914: scrypt PBKDF.
- *
- * x  Data to mix.
- * v  Temporary buffer.
- * y  Temporary buffer for the block mix.
- * r  Block size parameter.
- * n  CPU/Memory cost parameter.
- */
-static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
-{
-    word32 i;
-    word32 j;
-    word32 k;
-    word32 bSz = 128 * r;
-#ifdef WORD64_AVAILABLE
-    word64* x64 = (word64*)x;
-    word64* v64 = (word64*)v;
-#else
-    word32* x32 = (word32*)x;
-    word32* v32 = (word32*)v;
-#endif
-
-    /* Step 1. X = B (B not needed therefore not implemented) */
-    /* Step 2. */
-    for (i = 0; i < n; i++)
-    {
-        XMEMCPY(v + i * bSz, x, bSz);
-        scryptBlockMix(x, y, r);
-    }
-
-    /* Step 3. */
-    for (i = 0; i < n; i++)
-    {
-#ifdef LITTLE_ENDIAN_ORDER
-#ifdef WORD64_AVAILABLE
-        j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
-#else
-        j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
-#endif
-#else
-        byte* t = x + (2*r - 1) * 64;
-        j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1);
-#endif
-#ifdef WORD64_AVAILABLE
-        for (k = 0; k < bSz / 8; k++)
-            x64[k] ^= v64[j * bSz / 8 + k];
-#else
-        for (k = 0; k < bSz / 4; k++)
-            x32[k] ^= v32[j * bSz / 4 + k];
-#endif
-        scryptBlockMix(x, y, r);
-    }
-    /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
-}
-
-/* Generates an key derived from a password and salt using a memory hard
- * algorithm.
- * Implements RFC 7914: scrypt PBKDF.
- *
- * output     The derived key.
- * passwd     The password to derive key from.
- * passLen    The length of the password.
- * salt       The key specific data.
- * saltLen    The length of the salt data.
- * cost       The CPU/memory cost parameter. Range: 1..(128*r/8-1)
- *            (Iterations = 2^cost)
- * blockSize  The number of 128 byte octets in a working block.
- * parallel   The number of parallel mix operations to perform.
- *            (Note: this implementation does not use threads.)
- * dkLen      The length of the derived key in bytes.
- * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost.
- */
-int wc_scrypt(byte* output, const byte* passwd, int passLen,
-              const byte* salt, int saltLen, int cost, int blockSize,
-              int parallel, int dkLen)
-{
-    int    ret = 0;
-    int    i;
-    byte*  v = NULL;
-    byte*  y = NULL;
-    byte*  blocks = NULL;
-    word32 blocksSz;
-    word32 bSz;
-
-    if (blockSize > 8)
-        return BAD_FUNC_ARG;
-
-    if (cost < 1 || cost >= 128 * blockSize / 8)
-        return BAD_FUNC_ARG;
-
-    bSz = 128 * blockSize;
-    blocksSz = bSz * parallel;
-    blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (blocks == NULL)
-        goto end;
-    /* Temporary for scryptROMix. */
-    v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (v == NULL)
-        goto end;
-    /* Temporary for scryptBlockMix. */
-    y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (y == NULL)
-        goto end;
-
-    /* Step 1. */
-    ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz,
-                    WC_SHA256);
-    if (ret != 0)
-        goto end;
-
-    /* Step 2. */
-    for (i = 0; i < parallel; i++)
-        scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost);
-
-    /* Step 3. */
-    ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen,
-                    WC_SHA256);
-end:
-    if (blocks != NULL)
-        XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (v != NULL)
-        XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (y != NULL)
-        XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return ret;
-}
-#endif
-
-#undef WC_MAX_DIGEST_SIZE
-
-#endif /* NO_PWDBASED */
-
-
--- a/wolfcrypt/src/rabbit.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,343 +0,0 @@
-/* rabbit.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef NO_RABBIT
-
-#include <wolfssl/wolfcrypt/rabbit.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifdef BIG_ENDIAN_ORDER
-    #define LITTLE32(x) ByteReverseWord32(x)
-#else
-    #define LITTLE32(x) (x)
-#endif
-
-#define U32V(x) ((word32)(x) & 0xFFFFFFFFU)
-
-
-/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */
-/* the upper 32 bits XOR the lower 32 bits */
-static word32 RABBIT_g_func(word32 x)
-{
-    /* Temporary variables */
-    word32 a, b, h, l;
-
-    /* Construct high and low argument for squaring */
-    a = x&0xFFFF;
-    b = x>>16;
-
-    /* Calculate high and low result of squaring */
-    h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b;
-    l = x*x;
-
-    /* Return high XOR low */
-    return U32V(h^l);
-}
-
-
-/* Calculate the next internal state */
-static void RABBIT_next_state(RabbitCtx* ctx)
-{
-    /* Temporary variables */
-    word32 g[8], c_old[8], i;
-
-    /* Save old counter values */
-    for (i=0; i<8; i++)
-        c_old[i] = ctx->c[i];
-
-    /* Calculate new counter values */
-    ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry);
-    ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0]));
-    ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1]));
-    ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2]));
-    ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3]));
-    ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4]));
-    ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5]));
-    ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6]));
-    ctx->carry = (ctx->c[7] < c_old[7]);
-
-    /* Calculate the g-values */
-    for (i=0;i<8;i++)
-        g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i]));
-
-    /* Calculate new state values */
-    ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16));
-    ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]);
-    ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16));
-    ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]);
-    ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16));
-    ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]);
-    ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16));
-    ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]);
-}
-
-
-/* IV setup */
-static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv)
-{
-    /* Temporary variables */
-    word32 i0, i1, i2, i3, i;
-    word32 iv[2];
-
-    if (inIv)
-        XMEMCPY(iv, inIv, sizeof(iv));
-    else
-        XMEMSET(iv,    0, sizeof(iv));
-
-    /* Generate four subvectors */
-    i0 = LITTLE32(iv[0]);
-    i2 = LITTLE32(iv[1]);
-    i1 = (i0>>16) | (i2&0xFFFF0000);
-    i3 = (i2<<16) | (i0&0x0000FFFF);
-
-    /* Modify counter values */
-    ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0;
-    ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1;
-    ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2;
-    ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3;
-    ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0;
-    ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1;
-    ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2;
-    ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3;
-
-    /* Copy state variables */
-    for (i=0; i<8; i++)
-        ctx->workCtx.x[i] = ctx->masterCtx.x[i];
-    ctx->workCtx.carry = ctx->masterCtx.carry;
-
-    /* Iterate the system four times */
-    for (i=0; i<4; i++)
-        RABBIT_next_state(&(ctx->workCtx));
-}
-
-
-/* Key setup */
-static WC_INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv)
-{
-    /* Temporary variables */
-    word32 k0, k1, k2, k3, i;
-
-    /* Generate four subkeys */
-    k0 = LITTLE32(*(word32*)(key+ 0));
-    k1 = LITTLE32(*(word32*)(key+ 4));
-    k2 = LITTLE32(*(word32*)(key+ 8));
-    k3 = LITTLE32(*(word32*)(key+12));
-
-    /* Generate initial state variables */
-    ctx->masterCtx.x[0] = k0;
-    ctx->masterCtx.x[2] = k1;
-    ctx->masterCtx.x[4] = k2;
-    ctx->masterCtx.x[6] = k3;
-    ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16);
-    ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16);
-    ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16);
-    ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16);
-
-    /* Generate initial counter values */
-    ctx->masterCtx.c[0] = rotlFixed(k2, 16);
-    ctx->masterCtx.c[2] = rotlFixed(k3, 16);
-    ctx->masterCtx.c[4] = rotlFixed(k0, 16);
-    ctx->masterCtx.c[6] = rotlFixed(k1, 16);
-    ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF);
-    ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF);
-    ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF);
-    ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF);
-
-    /* Clear carry bit */
-    ctx->masterCtx.carry = 0;
-
-    /* Iterate the system four times */
-    for (i=0; i<4; i++)
-        RABBIT_next_state(&(ctx->masterCtx));
-
-    /* Modify the counters */
-    for (i=0; i<8; i++)
-        ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7];
-
-    /* Copy master instance to work instance */
-    for (i=0; i<8; i++) {
-        ctx->workCtx.x[i] = ctx->masterCtx.x[i];
-        ctx->workCtx.c[i] = ctx->masterCtx.c[i];
-    }
-    ctx->workCtx.carry = ctx->masterCtx.carry;
-
-    wc_RabbitSetIV(ctx, iv);
-
-    return 0;
-}
-
-
-int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap)
-{
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    ctx->heap = heap;
-#endif
-
-    (void)heap;
-    return 0;
-}
-
-
-/* Key setup */
-int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv)
-{
-    if (ctx == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    /* default heap to NULL or heap test value */
-    #ifdef WOLFSSL_HEAP_TEST
-        ctx->heap = (void*)WOLFSSL_HEAP_TEST;
-    #else
-        ctx->heap = NULL;
-    #endif /* WOLFSSL_HEAP_TEST */
-
-    if ((wolfssl_word)key % 4) {
-        int alignKey[4];
-
-        /* iv aligned in SetIV */
-        WOLFSSL_MSG("wc_RabbitSetKey unaligned key");
-
-        XMEMCPY(alignKey, key, sizeof(alignKey));
-
-        return DoKey(ctx, (const byte*)alignKey, iv);
-    }
-#endif /* XSTREAM_ALIGN */
-
-    return DoKey(ctx, key, iv);
-}
-
-
-/* Encrypt/decrypt a message of any size */
-static WC_INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input,
-                            word32 msglen)
-{
-    /* Encrypt/decrypt all full blocks */
-    while (msglen >= 16) {
-        /* Iterate the system */
-        RABBIT_next_state(&(ctx->workCtx));
-
-        /* Encrypt/decrypt 16 bytes of data */
-        *(word32*)(output+ 0) = *(word32*)(input+ 0) ^
-                   LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^
-                   U32V(ctx->workCtx.x[3]<<16));
-        *(word32*)(output+ 4) = *(word32*)(input+ 4) ^
-                   LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^
-                   U32V(ctx->workCtx.x[5]<<16));
-        *(word32*)(output+ 8) = *(word32*)(input+ 8) ^
-                   LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^
-                   U32V(ctx->workCtx.x[7]<<16));
-        *(word32*)(output+12) = *(word32*)(input+12) ^
-                   LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^
-                   U32V(ctx->workCtx.x[1]<<16));
-
-        /* Increment pointers and decrement length */
-        input  += 16;
-        output += 16;
-        msglen -= 16;
-    }
-
-    /* Encrypt/decrypt remaining data */
-    if (msglen) {
-
-        word32 i;
-        word32 tmp[4];
-        byte*  buffer = (byte*)tmp;
-
-        XMEMSET(tmp, 0, sizeof(tmp));   /* help static analysis */
-
-        /* Iterate the system */
-        RABBIT_next_state(&(ctx->workCtx));
-
-        /* Generate 16 bytes of pseudo-random data */
-        tmp[0] = LITTLE32(ctx->workCtx.x[0] ^
-                  (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16));
-        tmp[1] = LITTLE32(ctx->workCtx.x[2] ^
-                  (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16));
-        tmp[2] = LITTLE32(ctx->workCtx.x[4] ^
-                  (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16));
-        tmp[3] = LITTLE32(ctx->workCtx.x[6] ^
-                  (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16));
-
-        /* Encrypt/decrypt the data */
-        for (i=0; i<msglen; i++)
-            output[i] = input[i] ^ buffer[i];
-    }
-
-    return 0;
-}
-
-
-/* Encrypt/decrypt a message of any size */
-int wc_RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen)
-{
-    if (ctx == NULL || output == NULL || input == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef XSTREAM_ALIGN
-    if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) {
-        #ifndef NO_WOLFSSL_ALLOC_ALIGN
-            byte* tmp;
-            WOLFSSL_MSG("wc_RabbitProcess unaligned");
-
-            tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-            if (tmp == NULL) return MEMORY_E;
-
-            XMEMCPY(tmp, input, msglen);
-            DoProcess(ctx, tmp, tmp, msglen);
-            XMEMCPY(output, tmp, msglen);
-
-            XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-            return 0;
-        #else
-            return BAD_ALIGN_E;
-        #endif
-    }
-#endif /* XSTREAM_ALIGN */
-
-    return DoProcess(ctx, output, input, msglen);
-}
-
-
-#endif /* NO_RABBIT */
-
--- a/wolfcrypt/src/random.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2023 +0,0 @@
-/* random.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-/* on HPUX 11 you may need to install /dev/random see
-   http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
-
-*/
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$c")
-        #pragma const_seg(".fipsB$c")
-    #endif
-#endif
-
-
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-
-
-/* If building for old FIPS. */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz)
-{
-    return GenerateSeed(os, seed, sz);
-}
-
-int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
-{
-    (void)heap;
-    (void)devId;
-    return InitRng_fips(rng);
-}
-
-int wc_InitRng(WC_RNG* rng)
-{
-    return InitRng_fips(rng);
-}
-
-
-int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz)
-{
-    return RNG_GenerateBlock_fips(rng, b, sz);
-}
-
-
-int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
-{
-    return RNG_GenerateByte(rng, b);
-}
-
-#ifdef HAVE_HASHDRBG
-
-    int wc_FreeRng(WC_RNG* rng)
-    {
-        return FreeRng_fips(rng);
-    }
-
-    int wc_RNG_HealthTest(int reseed,
-                                        const byte* entropyA, word32 entropyASz,
-                                        const byte* entropyB, word32 entropyBSz,
-                                        byte* output, word32 outputSz)
-    {
-        return RNG_HealthTest_fips(reseed, entropyA, entropyASz,
-                              entropyB, entropyBSz, output, outputSz);
-   }
-#endif /* HAVE_HASHDRBG */
-
-#else /* else build without fips, or for new fips */
-
-#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
-
-#include <wolfssl/wolfcrypt/sha256.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_SGX)
-    #include <sgx_trts.h>
-#elif defined(USE_WINDOWS_API)
-    #ifndef _WIN32_WINNT
-        #define _WIN32_WINNT 0x0400
-    #endif
-    #include <windows.h>
-    #include <wincrypt.h>
-#elif defined(HAVE_WNR)
-    #include <wnr.h>
-    #include <wolfssl/wolfcrypt/logging.h>
-    wolfSSL_Mutex wnr_mutex;    /* global netRandom mutex */
-    int wnr_timeout     = 0;    /* entropy timeout, mililseconds */
-    int wnr_mutex_init  = 0;    /* flag for mutex init */
-    wnr_context*  wnr_ctx;      /* global netRandom context */
-#elif defined(FREESCALE_KSDK_2_0_TRNG)
-    #include "fsl_trng.h"
-#elif defined(FREESCALE_KSDK_2_0_RNGA)
-    #include "fsl_rnga.h"
-
-#elif defined(NO_DEV_RANDOM)
-#elif defined(CUSTOM_RAND_GENERATE)
-#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
-#elif defined(CUSTOM_RAND_GENERATE_SEED)
-#elif defined(WOLFSSL_GENSEED_FORTEST)
-#elif defined(WOLFSSL_MDK_ARM)
-#elif defined(WOLFSSL_IAR_ARM)
-#elif defined(WOLFSSL_ROWLEY_ARM)
-#elif defined(WOLFSSL_EMBOS)
-#elif defined(MICRIUM)
-#elif defined(WOLFSSL_NUCLEUS)
-#elif defined(WOLFSSL_PB)
-#else
-    /* include headers that may be needed to get good seed */
-    #include <fcntl.h>
-    #ifndef EBSNET
-        #include <unistd.h>
-    #endif
-#endif
-
-
-#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
-    static word32 intel_flags = 0;
-    static void wc_InitRng_IntelRD(void)
-    {
-        intel_flags = cpuid_get_flags();
-    }
-    #ifdef HAVE_INTEL_RDSEED
-    static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
-    #endif
-    #ifdef HAVE_INTEL_RDRAND
-    static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
-    #endif
-
-#ifdef USE_WINDOWS_API
-    #include <immintrin.h>
-#endif /* USE_WINDOWS_API */
-#endif
-
-/* Start NIST DRBG code */
-#ifdef HAVE_HASHDRBG
-
-#define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
-#define MAX_REQUEST_LEN   (0x10000)
-#define RESEED_INTERVAL   WC_RESEED_INTERVAL
-#define SECURITY_STRENGTH (2048)
-#define ENTROPY_SZ        (SECURITY_STRENGTH/8)
-#define MAX_ENTROPY_SZ    (ENTROPY_SZ + ENTROPY_SZ/2)
-
-/* Internal return codes */
-#define DRBG_SUCCESS      0
-#define DRBG_FAILURE      1
-#define DRBG_NEED_RESEED  2
-#define DRBG_CONT_FAILURE 3
-
-/* RNG health states */
-#define DRBG_NOT_INIT     0
-#define DRBG_OK           1
-#define DRBG_FAILED       2
-#define DRBG_CONT_FAILED  3
-
-#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
-
-/* Verify max gen block len */
-#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
-    #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
-#endif
-
-enum {
-    drbgInitC     = 0,
-    drbgReseed    = 1,
-    drbgGenerateW = 2,
-    drbgGenerateH = 3,
-    drbgInitV
-};
-
-
-typedef struct DRBG {
-    word32 reseedCtr;
-    word32 lastBlock;
-    byte V[DRBG_SEED_LEN];
-    byte C[DRBG_SEED_LEN];
-#ifdef WOLFSSL_ASYNC_CRYPT
-    void* heap;
-    int devId;
-#endif
-    byte   matchCount;
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    wc_Sha256 sha256;
-#endif
-} DRBG;
-
-
-static int wc_RNG_HealthTestLocal(int reseed);
-
-/* Hash Derivation Function */
-/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
-static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
-                                                  const byte* inA, word32 inASz,
-                                                  const byte* inB, word32 inBSz)
-{
-    int ret = DRBG_FAILURE;
-    byte ctr;
-    int i;
-    int len;
-    word32 bits = (outSz * 8); /* reverse byte order */
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    wc_Sha256* sha = &drbg->sha256;
-#else
-    wc_Sha256 sha[1];
-#endif
-    DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
-
-    (void)drbg;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (digest == NULL)
-        return DRBG_FAILURE;
-#endif
-
-#ifdef LITTLE_ENDIAN_ORDER
-    bits = ByteReverseWord32(bits);
-#endif
-    len = (outSz / OUTPUT_BLOCK_LEN)
-        + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
-
-    for (i = 0, ctr = 1; i < len; i++, ctr++) {
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
-    #else
-        ret = wc_InitSha256(sha);
-    #endif
-        if (ret != 0)
-            break;
-
-        if (ret == 0)
-#endif
-            ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
-        if (ret == 0)
-            ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
-
-        if (ret == 0) {
-            /* churning V is the only string that doesn't have the type added */
-            if (type != drbgInitV)
-                ret = wc_Sha256Update(sha, &type, sizeof(type));
-        }
-        if (ret == 0)
-            ret = wc_Sha256Update(sha, inA, inASz);
-        if (ret == 0) {
-            if (inB != NULL && inBSz > 0)
-                ret = wc_Sha256Update(sha, inB, inBSz);
-        }
-        if (ret == 0)
-            ret = wc_Sha256Final(sha, digest);
-
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-        wc_Sha256Free(sha);
-#endif
-        if (ret == 0) {
-            if (outSz > OUTPUT_BLOCK_LEN) {
-                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
-                outSz -= OUTPUT_BLOCK_LEN;
-                out += OUTPUT_BLOCK_LEN;
-            }
-            else {
-                XMEMCPY(out, digest, outSz);
-            }
-        }
-    }
-
-    ForceZero(digest, WC_SHA256_DIGEST_SIZE);
-
-    FREE_VAR(digest, drbg->heap);
-
-    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
-}
-
-/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
-static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz)
-{
-    byte seed[DRBG_SEED_LEN];
-
-    if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V),
-                                          entropy, entropySz) != DRBG_SUCCESS) {
-        return DRBG_FAILURE;
-    }
-
-    XMEMCPY(drbg->V, seed, sizeof(drbg->V));
-    ForceZero(seed, sizeof(seed));
-
-    if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
-                                    sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
-        return DRBG_FAILURE;
-    }
-
-    drbg->reseedCtr = 1;
-    drbg->lastBlock = 0;
-    drbg->matchCount = 0;
-    return DRBG_SUCCESS;
-}
-
-/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
-int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, word32 entropySz)
-{
-    if (rng == NULL || entropy == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    return Hash_DRBG_Reseed(rng->drbg, entropy, entropySz);
-}
-
-static WC_INLINE void array_add_one(byte* data, word32 dataSz)
-{
-    int i;
-
-    for (i = dataSz - 1; i >= 0; i--)
-    {
-        data[i]++;
-        if (data[i] != 0) break;
-    }
-}
-
-/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
-static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
-{
-    int ret = DRBG_FAILURE;
-    byte data[DRBG_SEED_LEN];
-    int i;
-    int len;
-    word32 checkBlock;
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    wc_Sha256* sha = &drbg->sha256;
-#else
-    wc_Sha256 sha[1];
-#endif
-    DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
-
-    /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
-     * the continuous test. */
-
-    if (outSz == 0) outSz = 1;
-
-    len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
-
-    XMEMCPY(data, V, sizeof(data));
-    for (i = 0; i < len; i++) {
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
-    #else
-        ret = wc_InitSha256(sha);
-    #endif
-        if (ret == 0)
-#endif
-            ret = wc_Sha256Update(sha, data, sizeof(data));
-        if (ret == 0)
-            ret = wc_Sha256Final(sha, digest);
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-        wc_Sha256Free(sha);
-#endif
-
-        if (ret == 0) {
-            XMEMCPY(&checkBlock, digest, sizeof(word32));
-            if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
-                if (drbg->matchCount == 1) {
-                    return DRBG_CONT_FAILURE;
-                }
-                else {
-                    if (i == len) {
-                        len++;
-                    }
-                    drbg->matchCount = 1;
-                }
-            }
-            else {
-                drbg->matchCount = 0;
-                drbg->lastBlock = checkBlock;
-            }
-
-            if (out != NULL && outSz != 0) {
-                if (outSz >= OUTPUT_BLOCK_LEN) {
-                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
-                    outSz -= OUTPUT_BLOCK_LEN;
-                    out += OUTPUT_BLOCK_LEN;
-                    array_add_one(data, DRBG_SEED_LEN);
-                }
-                else {
-                    XMEMCPY(out, digest, outSz);
-                    outSz = 0;
-                }
-            }
-        }
-    }
-    ForceZero(data, sizeof(data));
-
-    FREE_VAR(digest, drbg->heap);
-
-    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
-}
-
-static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
-{
-    word16 carry = 0;
-
-    if (dLen > 0 && sLen > 0 && dLen >= sLen) {
-        int sIdx, dIdx;
-
-        for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
-        {
-            carry += d[dIdx] + s[sIdx];
-            d[dIdx] = (byte)carry;
-            carry >>= 8;
-        }
-
-        for (; carry != 0 && dIdx >= 0; dIdx--) {
-            carry += d[dIdx];
-            d[dIdx] = (byte)carry;
-            carry >>= 8;
-        }
-    }
-}
-
-/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
-static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
-{
-    int ret;
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    wc_Sha256* sha = &drbg->sha256;
-#else
-    wc_Sha256 sha[1];
-#endif
-    byte type;
-    word32 reseedCtr;
-
-    if (drbg->reseedCtr == RESEED_INTERVAL) {
-        return DRBG_NEED_RESEED;
-    } else {
-        DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
-        type = drbgGenerateH;
-        reseedCtr = drbg->reseedCtr;
-
-        ret = Hash_gen(drbg, out, outSz, drbg->V);
-        if (ret == DRBG_SUCCESS) {
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-        #ifdef WOLFSSL_ASYNC_CRYPT
-            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
-        #else
-            ret = wc_InitSha256(sha);
-        #endif
-            if (ret == 0)
-#endif
-                ret = wc_Sha256Update(sha, &type, sizeof(type));
-            if (ret == 0)
-                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
-            if (ret == 0)
-                ret = wc_Sha256Final(sha, digest);
-
-#ifndef WOLFSSL_SMALL_STACK_CACHE
-            wc_Sha256Free(sha);
-#endif
-
-            if (ret == 0) {
-                array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
-                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
-            #ifdef LITTLE_ENDIAN_ORDER
-                reseedCtr = ByteReverseWord32(reseedCtr);
-            #endif
-                array_add(drbg->V, sizeof(drbg->V),
-                                          (byte*)&reseedCtr, sizeof(reseedCtr));
-                ret = DRBG_SUCCESS;
-            }
-            drbg->reseedCtr++;
-        }
-        ForceZero(digest, WC_SHA256_DIGEST_SIZE);
-        FREE_VAR(digest, drbg->heap);
-    }
-
-    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
-}
-
-/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
-static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz,
-                                             const byte* nonce, word32 nonceSz,
-                                             void* heap, int devId)
-{
-    int ret = DRBG_FAILURE;
-
-    XMEMSET(drbg, 0, sizeof(DRBG));
-#ifdef WOLFSSL_ASYNC_CRYPT
-    drbg->heap = heap;
-    drbg->devId = devId;
-#else
-    (void)heap;
-    (void)devId;
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
-    #else
-        ret = wc_InitSha256(&drbg->sha256);
-    #endif
-    if (ret != 0)
-        return ret;
-#endif
-
-    if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
-                                              nonce, nonceSz) == DRBG_SUCCESS &&
-        Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
-                                    sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
-
-        drbg->reseedCtr = 1;
-        drbg->lastBlock = 0;
-        drbg->matchCount = 0;
-        ret = DRBG_SUCCESS;
-    }
-
-    return ret;
-}
-
-/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
-static int Hash_DRBG_Uninstantiate(DRBG* drbg)
-{
-    word32 i;
-    int    compareSum = 0;
-    byte*  compareDrbg = (byte*)drbg;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    wc_Sha256Free(&drbg->sha256);
-#endif
-
-    ForceZero(drbg, sizeof(DRBG));
-
-    for (i = 0; i < sizeof(DRBG); i++)
-        compareSum |= compareDrbg[i] ^ 0;
-
-    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
-}
-#endif /* HAVE_HASHDRBG */
-/* End NIST DRBG Code */
-
-
-static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
-                    void* heap, int devId)
-{
-    int ret = RNG_FAILURE_E;
-#ifdef HAVE_HASHDRBG
-    word32 entropySz = ENTROPY_SZ;
-#endif
-
-    (void)nonce;
-    (void)nonceSz;
-
-    if (rng == NULL)
-        return BAD_FUNC_ARG;
-    if (nonce == NULL && nonceSz != 0)
-        return BAD_FUNC_ARG;
-
-#ifdef WOLFSSL_HEAP_TEST
-    rng->heap = (void*)WOLFSSL_HEAP_TEST;
-    (void)heap;
-#else
-    rng->heap = heap;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    rng->devId = devId;
-#else
-    (void)devId;
-#endif
-
-#ifdef HAVE_HASHDRBG
-    /* init the DBRG to known values */
-    rng->drbg = NULL;
-    rng->status = DRBG_NOT_INIT;
-#endif
-
-#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
-    /* init the intel RD seed and/or rand */
-    wc_InitRng_IntelRD();
-#endif
-
-    /* configure async RNG source if available */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
-                                                        rng->heap, rng->devId);
-    if (ret != 0)
-        return ret;
-#endif
-
-#ifdef HAVE_INTEL_RDRAND
-    /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
-    if (IS_INTEL_RDRAND(intel_flags))
-        return 0;
-#endif
-
-#ifdef CUSTOM_RAND_GENERATE_BLOCK
-	ret = 0; /* success */
-#else
-#ifdef HAVE_HASHDRBG
-    if (nonceSz == 0)
-        entropySz = MAX_ENTROPY_SZ;
-
-    if (wc_RNG_HealthTestLocal(0) == 0) {
-        DECLARE_VAR(entropy, byte, MAX_ENTROPY_SZ, rng->heap);
-
-        rng->drbg =
-                (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap,
-                                                          DYNAMIC_TYPE_RNG);
-        if (rng->drbg == NULL) {
-            ret = MEMORY_E;
-        }
-        else if (wc_GenerateSeed(&rng->seed, entropy, entropySz) == 0 &&
-                 Hash_DRBG_Instantiate(rng->drbg, entropy, entropySz,
-                            nonce, nonceSz, rng->heap, devId) == DRBG_SUCCESS) {
-            ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
-        }
-        else
-            ret = DRBG_FAILURE;
-
-        ForceZero(entropy, entropySz);
-        FREE_VAR(entropy, rng->heap);
-    }
-    else
-        ret = DRBG_CONT_FAILURE;
-
-    if (ret == DRBG_SUCCESS) {
-        rng->status = DRBG_OK;
-        ret = 0;
-    }
-    else if (ret == DRBG_CONT_FAILURE) {
-        rng->status = DRBG_CONT_FAILED;
-        ret = DRBG_CONT_FIPS_E;
-    }
-    else if (ret == DRBG_FAILURE) {
-        rng->status = DRBG_FAILED;
-        ret = RNG_FAILURE_E;
-    }
-    else {
-        rng->status = DRBG_FAILED;
-    }
-#endif /* HAVE_HASHDRBG */
-#endif /* CUSTOM_RAND_GENERATE_BLOCK */
-
-    return ret;
-}
-
-
-int wc_InitRng(WC_RNG* rng)
-{
-    return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
-}
-
-
-int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
-{
-    return _InitRng(rng, NULL, 0, heap, devId);
-}
-
-
-int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
-{
-    return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
-}
-
-
-int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
-                       void* heap, int devId)
-{
-    return _InitRng(rng, nonce, nonceSz, heap, devId);
-}
-
-
-/* place a generated block in output */
-int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
-{
-    int ret;
-
-    if (rng == NULL || output == NULL)
-        return BAD_FUNC_ARG;
-
-#ifdef HAVE_INTEL_RDRAND
-    if (IS_INTEL_RDRAND(intel_flags))
-        return wc_GenerateRand_IntelRD(NULL, output, sz);
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT)
-    if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
-        /* these are blocking */
-    #ifdef HAVE_CAVIUM
-        return NitroxRngGenerateBlock(rng, output, sz);
-    #elif defined(HAVE_INTEL_QA)
-        return IntelQaDrbg(&rng->asyncDev, output, sz);
-    #else
-        /* simulator not supported */
-    #endif
-    }
-#endif
-
-#ifdef CUSTOM_RAND_GENERATE_BLOCK
-    XMEMSET(output, 0, sz);
-    ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz);
-#else
-
-#ifdef HAVE_HASHDRBG
-    if (sz > RNG_MAX_BLOCK_LEN)
-        return BAD_FUNC_ARG;
-
-    if (rng->status != DRBG_OK)
-        return RNG_FAILURE_E;
-
-    ret = Hash_DRBG_Generate(rng->drbg, output, sz);
-    if (ret == DRBG_NEED_RESEED) {
-        if (wc_RNG_HealthTestLocal(1) == 0) {
-            byte entropy[ENTROPY_SZ];
-
-            if (wc_GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 &&
-                Hash_DRBG_Reseed(rng->drbg, entropy, ENTROPY_SZ)
-                                                              == DRBG_SUCCESS) {
-
-                ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
-                if (ret == DRBG_SUCCESS)
-                    ret = Hash_DRBG_Generate(rng->drbg, output, sz);
-            }
-            else
-                ret = DRBG_FAILURE;
-
-            ForceZero(entropy, ENTROPY_SZ);
-        }
-        else
-            ret = DRBG_CONT_FAILURE;
-    }
-
-    if (ret == DRBG_SUCCESS) {
-        ret = 0;
-    }
-    else if (ret == DRBG_CONT_FAILURE) {
-        ret = DRBG_CONT_FIPS_E;
-        rng->status = DRBG_CONT_FAILED;
-    }
-    else {
-        ret = RNG_FAILURE_E;
-        rng->status = DRBG_FAILED;
-    }
-#else
-
-    /* if we get here then there is an RNG configuration error */
-    ret = RNG_FAILURE_E;
-
-#endif /* HAVE_HASHDRBG */
-#endif /* CUSTOM_RAND_GENERATE_BLOCK */
-
-    return ret;
-}
-
-
-int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
-{
-    return wc_RNG_GenerateBlock(rng, b, 1);
-}
-
-
-int wc_FreeRng(WC_RNG* rng)
-{
-    int ret = 0;
-
-    if (rng == NULL)
-        return BAD_FUNC_ARG;
-
-#if defined(WOLFSSL_ASYNC_CRYPT)
-    wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
-#endif
-
-#ifdef HAVE_HASHDRBG
-    if (rng->drbg != NULL) {
-        if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS)
-            ret = RNG_FAILURE_E;
-
-        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
-        rng->drbg = NULL;
-    }
-
-    rng->status = DRBG_NOT_INIT;
-#endif /* HAVE_HASHDRBG */
-
-    return ret;
-}
-
-#ifdef HAVE_HASHDRBG
-int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz,
-                                  const byte* entropyB, word32 entropyBSz,
-                                  byte* output, word32 outputSz)
-{
-    return wc_RNG_HealthTest_ex(reseed, NULL, 0,
-                                entropyA, entropyASz,
-                                entropyB, entropyBSz,
-                                output, outputSz,
-                                NULL, INVALID_DEVID);
-}
-
-
-int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
-                                  const byte* entropyA, word32 entropyASz,
-                                  const byte* entropyB, word32 entropyBSz,
-                                  byte* output, word32 outputSz,
-                                  void* heap, int devId)
-{
-    int ret = -1;
-    DRBG* drbg;
-#ifndef WOLFSSL_SMALL_STACK
-    DRBG  drbg_var;
-#endif
-
-    if (entropyA == NULL || output == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (reseed != 0 && entropyB == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
-        return ret;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    drbg = (struct DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG);
-    if (drbg == NULL) {
-        return MEMORY_E;
-    }
-#else
-    drbg = &drbg_var;
-#endif
-
-    if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
-                              heap, devId) != 0) {
-        goto exit_rng_ht;
-    }
-
-    if (reseed) {
-        if (Hash_DRBG_Reseed(drbg, entropyB, entropyBSz) != 0) {
-            goto exit_rng_ht;
-        }
-    }
-
-    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
-        goto exit_rng_ht;
-    }
-
-    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
-        goto exit_rng_ht;
-    }
-
-    /* Mark success */
-    ret = 0;
-
-exit_rng_ht:
-
-    /* This is safe to call even if Hash_DRBG_Instantiate fails */
-    if (Hash_DRBG_Uninstantiate(drbg) != 0) {
-        ret = -1;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(drbg, NULL, DYNAMIC_TYPE_RNG);
-#endif
-
-    return ret;
-}
-
-
-const byte entropyA[] = {
-    0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
-    0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
-    0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
-    0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
-};
-
-const byte reseedEntropyA[] = {
-    0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
-    0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
-    0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
-};
-
-const byte outputA[] = {
-    0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
-    0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
-    0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
-    0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
-    0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
-    0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
-    0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
-    0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
-    0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
-    0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
-    0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
-};
-
-const byte entropyB[] = {
-    0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
-    0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
-    0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
-    0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
-    0xdb, 0xcb, 0xcc, 0x2e
-};
-
-const byte outputB[] = {
-    0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
-    0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
-    0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
-    0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
-    0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
-    0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
-    0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
-    0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
-    0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
-    0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
-    0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
-};
-
-
-static int wc_RNG_HealthTestLocal(int reseed)
-{
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* check;
-#else
-    byte  check[RNG_HEALTH_TEST_CHECK_SIZE];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
-                           DYNAMIC_TYPE_TMP_BUFFER);
-    if (check == NULL) {
-        return MEMORY_E;
-    }
-#endif
-
-    if (reseed) {
-        ret = wc_RNG_HealthTest(1, entropyA, sizeof(entropyA),
-                                reseedEntropyA, sizeof(reseedEntropyA),
-                                check, RNG_HEALTH_TEST_CHECK_SIZE);
-        if (ret == 0) {
-            if (ConstantCompare(check, outputA,
-                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
-                ret = -1;
-        }
-    }
-    else {
-        ret = wc_RNG_HealthTest(0, entropyB, sizeof(entropyB),
-                                NULL, 0,
-                                check, RNG_HEALTH_TEST_CHECK_SIZE);
-        if (ret == 0) {
-            if (ConstantCompare(check, outputB,
-                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
-                ret = -1;
-        }
-
-        /* The previous test cases use a large seed instead of a seed and nonce.
-         * entropyB is actually from a test case with a seed and nonce, and
-         * just concatenates them. The pivot point between seed and nonce is
-         * byte 32, feed them into the health test separately. */
-        if (ret == 0) {
-            ret = wc_RNG_HealthTest_ex(0,
-                                    entropyB + 32, sizeof(entropyB) - 32,
-                                    entropyB, 32,
-                                    NULL, 0,
-                                    check, RNG_HEALTH_TEST_CHECK_SIZE,
-                                    NULL, INVALID_DEVID);
-            if (ret == 0) {
-                if (ConstantCompare(check, outputB, sizeof(outputB)) != 0)
-                    ret = -1;
-            }
-        }
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* HAVE_HASHDRBG */
-
-
-#ifdef HAVE_WNR
-
-/*
- * Init global Whitewood netRandom context
- * Returns 0 on success, negative on error
- */
-int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
-{
-    if (configFile == NULL || timeout < 0)
-        return BAD_FUNC_ARG;
-
-    if (wnr_mutex_init > 0) {
-        WOLFSSL_MSG("netRandom context already created, skipping");
-        return 0;
-    }
-
-    if (wc_InitMutex(&wnr_mutex) != 0) {
-        WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
-        return BAD_MUTEX_E;
-    }
-    wnr_mutex_init = 1;
-
-    if (wc_LockMutex(&wnr_mutex) != 0) {
-        WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
-        return BAD_MUTEX_E;
-    }
-
-    /* store entropy timeout */
-    wnr_timeout = timeout;
-
-    /* create global wnr_context struct */
-    if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
-        WOLFSSL_MSG("Error creating global netRandom context");
-        return RNG_FAILURE_E;
-    }
-
-    /* load config file */
-    if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
-        WOLFSSL_MSG("Error loading config file into netRandom context");
-        wnr_destroy(wnr_ctx);
-        wnr_ctx = NULL;
-        return RNG_FAILURE_E;
-    }
-
-    /* create/init polling mechanism */
-    if (wnr_poll_create() != WNR_ERROR_NONE) {
-        printf("ERROR: wnr_poll_create() failed\n");
-        WOLFSSL_MSG("Error initializing netRandom polling mechanism");
-        wnr_destroy(wnr_ctx);
-        wnr_ctx = NULL;
-        return RNG_FAILURE_E;
-    }
-
-    /* validate config, set HMAC callback (optional) */
-    if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
-        WOLFSSL_MSG("Error setting up netRandom context");
-        wnr_destroy(wnr_ctx);
-        wnr_ctx = NULL;
-        wnr_poll_destroy();
-        return RNG_FAILURE_E;
-    }
-
-    wc_UnLockMutex(&wnr_mutex);
-
-    return 0;
-}
-
-/*
- * Free global Whitewood netRandom context
- * Returns 0 on success, negative on error
- */
-int wc_FreeNetRandom(void)
-{
-    if (wnr_mutex_init > 0) {
-
-        if (wc_LockMutex(&wnr_mutex) != 0) {
-            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
-            return BAD_MUTEX_E;
-        }
-
-        if (wnr_ctx != NULL) {
-            wnr_destroy(wnr_ctx);
-            wnr_ctx = NULL;
-        }
-        wnr_poll_destroy();
-
-        wc_UnLockMutex(&wnr_mutex);
-
-        wc_FreeMutex(&wnr_mutex);
-        wnr_mutex_init = 0;
-    }
-
-    return 0;
-}
-
-#endif /* HAVE_WNR */
-
-
-#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* need more retries if multiple cores */
-    #define INTELRD_RETRY (32 * 8)
-#else
-    #define INTELRD_RETRY 32
-#endif
-
-#ifdef HAVE_INTEL_RDSEED
-
-#ifndef USE_WINDOWS_API
-
-    /* return 0 on success */
-    static WC_INLINE int IntelRDseed64(word64* seed)
-    {
-        unsigned char ok;
-
-        __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
-        return (ok) ? 0 : -1;
-    }
-
-#else /* USE_WINDOWS_API */
-    /* The compiler Visual Studio uses does not allow inline assembly.
-     * It does allow for Intel intrinsic functions. */
-
-    /* return 0 on success */
-    static WC_INLINE int IntelRDseed64(word64* seed)
-    {
-        int ok;
-
-        ok = _rdseed64_step(seed);
-        return (ok) ? 0 : -1;
-    }
-
-#endif /* USE_WINDOWS_API */
-
-/* return 0 on success */
-static WC_INLINE int IntelRDseed64_r(word64* rnd)
-{
-    int i;
-    for (i = 0; i < INTELRD_RETRY; i++) {
-        if (IntelRDseed64(rnd) == 0)
-            return 0;
-    }
-    return -1;
-}
-
-/* return 0 on success */
-static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
-{
-    int ret;
-    word64 rndTmp;
-
-    (void)os;
-
-    if (!IS_INTEL_RDSEED(intel_flags))
-        return -1;
-
-    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
-                                                    output += sizeof(word64)) {
-        ret = IntelRDseed64_r((word64*)output);
-        if (ret != 0)
-            return ret;
-    }
-    if (sz == 0)
-        return 0;
-
-    /* handle unaligned remainder */
-    ret = IntelRDseed64_r(&rndTmp);
-    if (ret != 0)
-        return ret;
-
-    XMEMCPY(output, &rndTmp, sz);
-    ForceZero(&rndTmp, sizeof(rndTmp));
-
-    return 0;
-}
-
-#endif /* HAVE_INTEL_RDSEED */
-
-#ifdef HAVE_INTEL_RDRAND
-
-#ifndef USE_WINDOWS_API
-
-/* return 0 on success */
-static WC_INLINE int IntelRDrand64(word64 *rnd)
-{
-    unsigned char ok;
-
-    __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
-
-    return (ok) ? 0 : -1;
-}
-
-#else /* USE_WINDOWS_API */
-    /* The compiler Visual Studio uses does not allow inline assembly.
-     * It does allow for Intel intrinsic functions. */
-
-/* return 0 on success */
-static WC_INLINE int IntelRDrand64(word64 *rnd)
-{
-    int ok;
-
-    ok = _rdrand64_step(rnd);
-
-    return (ok) ? 0 : -1;
-}
-
-#endif /* USE_WINDOWS_API */
-
-/* return 0 on success */
-static WC_INLINE int IntelRDrand64_r(word64 *rnd)
-{
-    int i;
-    for (i = 0; i < INTELRD_RETRY; i++) {
-        if (IntelRDrand64(rnd) == 0)
-            return 0;
-    }
-    return -1;
-}
-
-/* return 0 on success */
-static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
-{
-    int ret;
-    word64 rndTmp;
-
-    (void)os;
-
-    if (!IS_INTEL_RDRAND(intel_flags))
-        return -1;
-
-    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
-                                                    output += sizeof(word64)) {
-        ret = IntelRDrand64_r((word64 *)output);
-        if (ret != 0)
-            return ret;
-    }
-    if (sz == 0)
-        return 0;
-
-    /* handle unaligned remainder */
-    ret = IntelRDrand64_r(&rndTmp);
-    if (ret != 0)
-        return ret;
-
-    XMEMCPY(output, &rndTmp, sz);
-
-    return 0;
-}
-
-#endif /* HAVE_INTEL_RDRAND */
-#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */
-
-
-/* Begin wc_GenerateSeed Implementations */
-#if defined(CUSTOM_RAND_GENERATE_SEED)
-
-    /* Implement your own random generation function
-     * Return 0 to indicate success
-     * int rand_gen_seed(byte* output, word32 sz);
-     * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        (void)os; /* Suppress unused arg warning */
-        return CUSTOM_RAND_GENERATE_SEED(output, sz);
-    }
-
-#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
-
-    /* Implement your own random generation function,
-     *  which includes OS_Seed.
-     * Return 0 to indicate success
-     * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
-     * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
-    }
-
-#elif defined(CUSTOM_RAND_GENERATE)
-
-   /* Implement your own random generation function
-    * word32 rand_gen(void);
-    * #define CUSTOM_RAND_GENERATE  rand_gen  */
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        word32 i = 0;
-
-        (void)os;
-
-        while (i < sz)
-        {
-            /* If not aligned or there is odd/remainder */
-            if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
-                ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
-            ) {
-                /* Single byte at a time */
-                output[i++] = (byte)CUSTOM_RAND_GENERATE();
-            }
-            else {
-                /* Use native 8, 16, 32 or 64 copy instruction */
-                *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
-                i += sizeof(CUSTOM_RAND_TYPE);
-            }
-        }
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_SGX)
-
-int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-{
-	int ret = !SGX_SUCCESS;
-	int i, read_max = 10;
-
-	for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
-		ret = sgx_read_rand(output, sz);
-	}
-
-	(void)os;
-	return (ret == SGX_SUCCESS) ? 0 : 1;
-}
-
-#elif defined(USE_WINDOWS_API)
-
-int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-{
-    if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
-                            CRYPT_VERIFYCONTEXT))
-        return WINCRYPT_E;
-
-    if (!CryptGenRandom(os->handle, sz, output))
-        return CRYPTGEN_E;
-
-    CryptReleaseContext(os->handle, 0);
-
-    return 0;
-}
-
-
-#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
-
-#include "rtprand.h"   /* rtp_rand () */
-#include "rtptime.h"   /* rtp_get_system_msec() */
-
-
-int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-{
-    int i;
-    rtp_srand(rtp_get_system_msec());
-
-    for (i = 0; i < sz; i++ ) {
-        output[i] = rtp_rand() % 256;
-        if ( (i % 8) == 7)
-            rtp_srand(rtp_get_system_msec());
-    }
-
-    return 0;
-}
-
-
-#elif defined(MICROCHIP_PIC32)
-
-    #ifdef MICROCHIP_MPLAB_HARMONY
-        #define PIC32_SEED_COUNT _CP0_GET_COUNT
-    #else
-        #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
-            #include <peripheral/timer.h>
-        #endif
-        extern word32 ReadCoreTimer(void);
-        #define PIC32_SEED_COUNT ReadCoreTimer
-    #endif
-
-    #ifdef WOLFSSL_PIC32MZ_RNG
-        #include "xc.h"
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            int i;
-            byte rnd[8];
-            word32 *rnd32 = (word32 *)rnd;
-            word32 size = sz;
-            byte* op = output;
-
-#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
-            RNGNUMGEN1 = _CP0_GET_COUNT();
-            RNGPOLY1 = _CP0_GET_COUNT();
-            RNGPOLY2 = _CP0_GET_COUNT();
-            RNGNUMGEN2 = _CP0_GET_COUNT();
-#else
-            // All others can be seeded from the TRNG
-            RNGCONbits.TRNGMODE = 1;
-            RNGCONbits.TRNGEN = 1;
-            while (RNGCNT < 64);
-            RNGCONbits.LOAD = 1;
-            while (RNGCONbits.LOAD == 1);
-            while (RNGCNT < 64);
-            RNGPOLY2 = RNGSEED2;
-            RNGPOLY1 = RNGSEED1;
-#endif
-
-            RNGCONbits.PLEN = 0x40;
-            RNGCONbits.PRNGEN = 1;
-            for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
-                volatile int x;
-                x = RNGNUMGEN1;
-                x = RNGNUMGEN2;
-                (void)x;
-            }
-            do {
-                rnd32[0] = RNGNUMGEN1;
-                rnd32[1] = RNGNUMGEN2;
-
-                for(i=0; i<8; i++, op++) {
-                    *op = rnd[i];
-                    size --;
-                    if(size==0)break;
-                }
-            } while(size);
-            return 0;
-        }
-    #else  /* WOLFSSL_PIC32MZ_RNG */
-        /* uses the core timer, in nanoseconds to seed srand */
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            int i;
-            srand(PIC32_SEED_COUNT() * 25);
-
-            for (i = 0; i < sz; i++ ) {
-                output[i] = rand() % 256;
-                if ( (i % 8) == 7)
-                    srand(PIC32_SEED_COUNT() * 25);
-            }
-            return 0;
-        }
-    #endif /* WOLFSSL_PIC32MZ_RNG */
-
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
-      defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
-
-    #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
-        /*
-         * wc_Generates a RNG seed using the Random Number Generator Accelerator
-         * on the Kinetis K70. Documentation located in Chapter 37 of
-         * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
-         */
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            word32 i;
-
-            /* turn on RNGA module */
-            #if defined(SIM_SCGC3_RNGA_MASK)
-                SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
-            #endif
-            #if defined(SIM_SCGC6_RNGA_MASK)
-                /* additionally needed for at least K64F */
-                SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
-            #endif
-
-            /* set SLP bit to 0 - "RNGA is not in sleep mode" */
-            RNG_CR &= ~RNG_CR_SLP_MASK;
-
-            /* set HA bit to 1 - "security violations masked" */
-            RNG_CR |= RNG_CR_HA_MASK;
-
-            /* set GO bit to 1 - "output register loaded with data" */
-            RNG_CR |= RNG_CR_GO_MASK;
-
-            for (i = 0; i < sz; i++) {
-
-                /* wait for RNG FIFO to be full */
-                while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
-
-                /* get value */
-                output[i] = RNG_OR;
-            }
-
-            return 0;
-        }
-
-    #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
-        /*
-         * wc_Generates a RNG seed using the Random Number Generator (RNGB)
-         * on the Kinetis K53. Documentation located in Chapter 33 of
-         * K53 Sub-Family Reference Manual (see note in the README for link).
-         */
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            int i;
-
-            /* turn on RNGB module */
-            SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
-
-            /* reset RNGB */
-            RNG_CMD |= RNG_CMD_SR_MASK;
-
-            /* FIFO generate interrupt, return all zeros on underflow,
-             * set auto reseed */
-            RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
-
-            /* gen seed, clear interrupts, clear errors */
-            RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
-
-            /* wait for seeding to complete */
-            while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
-
-            for (i = 0; i < sz; i++) {
-
-                /* wait for a word to be available from FIFO */
-                while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
-
-                /* get value */
-                output[i] = RNG_OUT;
-            }
-
-            return 0;
-        }
-
-    #elif defined(FREESCALE_KSDK_2_0_TRNG)
-
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            status_t status;
-            status = TRNG_GetRandomData(TRNG0, output, sz);
-            if (status == kStatus_Success)
-            {
-                return(0);
-            }
-            else
-            {
-                return RAN_BLOCK_E;
-            }
-        }
-
-    #elif defined(FREESCALE_KSDK_2_0_RNGA)
-
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            status_t status;
-            status = RNGA_GetRandomData(RNG, output, sz);
-            if (status == kStatus_Success)
-            {
-                return(0);
-            }
-            else
-            {
-                return RAN_BLOCK_E;
-            }
-        }
-
-
-    #elif defined(FREESCALE_RNGA)
-
-        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-        {
-            RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz);
-            return 0;
-        }
-
-    #else
-        #define USE_TEST_GENSEED
-    #endif /* FREESCALE_K70_RNGA */
-
-#elif defined(STM32_RNG)
-     /* Generate a RNG seed using the hardware random number generator
-      * on the STM32F2/F4/F7. */
-
-    #ifdef WOLFSSL_STM32_CUBEMX
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        RNG_HandleTypeDef hrng;
-        int i;
-        (void)os;
-
-        /* enable RNG clock source */
-        __HAL_RCC_RNG_CLK_ENABLE();
-
-        /* enable RNG peripheral */
-        hrng.Instance = RNG;
-        HAL_RNG_Init(&hrng);
-
-        for (i = 0; i < (int)sz; i++) {
-            /* get value */
-            output[i] = (byte)HAL_RNG_GetRandomNumber(&hrng);
-        }
-
-        return 0;
-    }
-    #elif defined(WOLFSSL_STM32F427_RNG)
-
-    /* Generate a RNG seed using the hardware RNG on the STM32F427
-     * directly, following steps outlined in STM32F4 Reference
-     * Manual (Chapter 24) for STM32F4xx family. */
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int i;
-        (void)os;
-
-        /* enable RNG interrupt, set IE bit in RNG->CR register */
-        RNG->CR |= RNG_CR_IE;
-
-        /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
-         * RNG_LFSR, and error detector */
-        RNG->CR |= RNG_CR_RNGEN;
-
-        /* verify no errors, make sure SEIS and CEIS bits are 0
-         * in RNG->SR register */
-        if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS))
-            return RNG_FAILURE_E;
-
-        for (i = 0; i < (int)sz; i++) {
-            /* wait until RNG number is ready */
-            while ((RNG->SR & RNG_SR_DRDY) == 0) { }
-
-            /* get value */
-            output[i] = RNG->DR;
-        }
-
-        return 0;
-    }
-
-    #else
-
-    /* Generate a RNG seed using the STM32 Standard Peripheral Library */
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int i;
-        (void)os;
-
-        /* enable RNG clock source */
-        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
-
-        /* reset RNG */
-        RNG_DeInit();
-
-        /* enable RNG peripheral */
-        RNG_Cmd(ENABLE);
-
-        /* verify no errors with RNG_CLK or Seed */
-        if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET)
-        	return RNG_FAILURE_E;
-
-        for (i = 0; i < (int)sz; i++) {
-            /* wait until RNG number is ready */
-            while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
-
-            /* get value */
-            output[i] = RNG_GetRandomNumber();
-        }
-
-        return 0;
-    }
-    #endif /* WOLFSSL_STM32_CUBEMX */
-
-#elif defined(WOLFSSL_TIRTOS)
-
-    #include <xdc/runtime/Timestamp.h>
-    #include <stdlib.h>
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int i;
-        srand(xdc_runtime_Timestamp_get32());
-
-        for (i = 0; i < sz; i++ ) {
-            output[i] = rand() % 256;
-            if ((i % 8) == 7) {
-                srand(xdc_runtime_Timestamp_get32());
-            }
-        }
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_PB)
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        word32 i;
-        for (i = 0; i < sz; i++)
-            output[i] = UTL_Rand();
-
-        (void)os;
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_NUCLEUS)
-#include "nucleus.h"
-#include "kernel/plus_common.h"
-
-#warning "potential for not enough entropy, currently being used for testing"
-int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-{
-    int i;
-    srand(NU_Get_Time_Stamp());
-
-    for (i = 0; i < sz; i++ ) {
-        output[i] = rand() % 256;
-        if ((i % 8) == 7) {
-            srand(NU_Get_Time_Stamp());
-        }
-    }
-
-    return 0;
-}
-#elif defined(WOLFSSL_VXWORKS)
-
-    #include <randomNumGen.h>
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
-        STATUS        status;
-
-        #ifdef VXWORKS_SIM
-            /* cannot generate true entropy with VxWorks simulator */
-            #warning "not enough entropy, simulator for testing only"
-            int i = 0;
-
-            for (i = 0; i < 1000; i++) {
-                randomAddTimeStamp();
-            }
-        #endif
-
-        status = randBytes (output, sz);
-        if (status == ERROR) {
-            return RNG_FAILURE_E;
-        }
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_NRF51)
-    #include "app_error.h"
-    #include "nrf_drv_rng.h"
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int remaining = sz, length, pos = 0;
-        uint8_t available;
-        uint32_t err_code;
-
-        (void)os;
-
-        /* Make sure RNG is running */
-        err_code = nrf_drv_rng_init(NULL);
-        if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
-            return -1;
-        }
-
-        while (remaining > 0) {
-            err_code = nrf_drv_rng_bytes_available(&available);
-            if (err_code == NRF_SUCCESS) {
-                length = (remaining < available) ? remaining : available;
-                if (length > 0) {
-                    err_code = nrf_drv_rng_rand(&output[pos], length);
-                    remaining -= length;
-                    pos += length;
-                }
-            }
-
-            if (err_code != NRF_SUCCESS) {
-                break;
-            }
-        }
-
-        return (err_code == NRF_SUCCESS) ? 0 : -1;
-    }
-
-#elif defined(HAVE_WNR)
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        if (os == NULL || output == NULL || wnr_ctx == NULL ||
-                wnr_timeout < 0) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (wnr_mutex_init == 0) {
-            WOLFSSL_MSG("netRandom context must be created before use");
-            return RNG_FAILURE_E;
-        }
-
-        if (wc_LockMutex(&wnr_mutex) != 0) {
-            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n");
-            return BAD_MUTEX_E;
-        }
-
-        if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
-                WNR_ERROR_NONE)
-            return RNG_FAILURE_E;
-
-        wc_UnLockMutex(&wnr_mutex);
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_ATMEL)
-    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-    	int ret = 0;
-
-        (void)os;
-    	if (output == NULL) {
-    		return BUFFER_E;
-    	}
-
-    	ret = atmel_get_random_number(sz, output);
-
-    	return ret;
-    }
-
-#elif defined(INTIME_RTOS)
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int ret = 0;
-
-        (void)os;
-
-        if (output == NULL) {
-            return BUFFER_E;
-        }
-
-        /* Note: Investigate better solution */
-        /* no return to check */
-        arc4random_buf(output, sz);
-
-        return ret;
-    }
-
-#elif defined(IDIRECT_DEV_RANDOM)
-
-    extern int getRandom( int sz, unsigned char *output );
-
-    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int num_bytes_returned = 0;
-
-        num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
-
-        return 0;
-    }
-
-#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
-
-    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
-    #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        Buffer buf[1];
-        int ret  = 0;
-        int times = 1000, i;
-
-        (void)os;
-
-        if (output == NULL) {
-            return BUFFER_E;
-        }
-
-        buf[0].BufferType = DataBuffer | LastBuffer;
-        buf[0].TheAddress = (Address)output;
-        buf[0].Length     = sz;
-
-        /* Check Waiting to make sure entropy is ready */
-        for (i = 0; i < times; i++) {
-            ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
-            if (ret == Success) {
-                break;
-            }
-
-            /* driver could be waiting for entropy */
-            if (ret != RAN_BLOCK_E) {
-                return ret;
-            }
-            usleep(100);
-        }
-
-        if (i == times && ret != Success) {
-             return RNG_FAILURE_E;
-        }
-        else { /* Success case */
-            ret = 0;
-        }
-
-        return ret;
-    }
-
-#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
-    /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
-     * extern int myRngFunc(byte* output, word32 sz);
-     */
-
-#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
-      defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
-      defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
-      defined(WOLFSSL_LPC43xx)  || defined(WOLFSSL_STM32F2xx) || \
-      defined(MBED)             || defined(WOLFSSL_EMBOS) || \
-      defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS)
-
-    /* these platforms do not have a default random seed and
-       you'll need to implement your own wc_GenerateSeed or define via
-       CUSTOM_RAND_GENERATE_BLOCK */
-
-    #define USE_TEST_GENSEED
-
-#elif defined(NO_DEV_RANDOM)
-
-    //#error "you need to write an os specific wc_GenerateSeed() here"
-
-    
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        return 0;
-    }
-    
-
-#else
-
-    /* may block */
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        int ret = 0;
-
-    #ifdef HAVE_INTEL_RDSEED
-        if (IS_INTEL_RDSEED(intel_flags)) {
-             ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
-             if (ret == 0) {
-                 /* success, we're done */
-                 return ret;
-             }
-        #ifdef FORCE_FAILURE_RDSEED
-             /* don't fallback to /dev/urandom */
-             return ret;
-        #else
-             /* reset error and fallback to using /dev/urandom */
-             ret = 0;
-        #endif
-        }
-    #endif /* HAVE_INTEL_RDSEED */
-
-    #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
-        os->fd = open("/dev/urandom", O_RDONLY);
-        if (os->fd == -1)
-    #endif
-        {
-            /* may still have /dev/random */
-            os->fd = open("/dev/random", O_RDONLY);
-            if (os->fd == -1)
-                return OPEN_RAN_E;
-        }
-
-        while (sz) {
-            int len = (int)read(os->fd, output, sz);
-            if (len == -1) {
-                ret = READ_RAN_E;
-                break;
-            }
-
-            sz     -= len;
-            output += len;
-
-            if (sz) {
-    #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
-                sleep(0);             /* context switch */
-    #else
-                ret = RAN_BLOCK_E;
-                break;
-    #endif
-            }
-        }
-        close(os->fd);
-
-        return ret;
-    }
-
-#endif
-
-#ifdef USE_TEST_GENSEED
-    #ifndef _MSC_VER
-        #warning "write a real random seed!!!!, just for testing now"
-    #else
-        #pragma message("Warning: write a real random seed!!!!, just for testing now")
-    #endif
-
-    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
-    {
-        word32 i;
-        for (i = 0; i < sz; i++ )
-            output[i] = i;
-
-        (void)os;
-
-        return 0;
-    }
-#endif
-
-/* End wc_GenerateSeed */
-
-#endif /* WC_NO_RNG */
-#endif /* HAVE_FIPS */
-
--- a/wolfcrypt/src/ripemd.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-/* ripemd.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef WOLFSSL_RIPEMD
-
-#include <wolfssl/wolfcrypt/ripemd.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-int wc_InitRipeMd(RipeMd* ripemd)
-{
-    if (ripemd == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ripemd->digest[0] = 0x67452301L;
-    ripemd->digest[1] = 0xEFCDAB89L;
-    ripemd->digest[2] = 0x98BADCFEL;
-    ripemd->digest[3] = 0x10325476L;
-    ripemd->digest[4] = 0xC3D2E1F0L;
-
-    ripemd->buffLen = 0;
-    ripemd->loLen   = 0;
-    ripemd->hiLen   = 0;
-
-    return 0;
-}
-
-
-/* for all */
-#define F(x, y, z)    (x ^ y ^ z)
-#define G(x, y, z)    (z ^ (x & (y^z)))
-#define H(x, y, z)    (z ^ (x | ~y))
-#define I(x, y, z)    (y ^ (z & (x^y)))
-#define J(x, y, z)    (x ^ (y | ~z))
-
-#define k0 0
-#define k1 0x5a827999
-#define k2 0x6ed9eba1
-#define k3 0x8f1bbcdc
-#define k4 0xa953fd4e
-#define k5 0x50a28be6
-#define k6 0x5c4dd124
-#define k7 0x6d703ef3
-#define k8 0x7a6d76e9
-#define k9 0
-
-/* for 160 and 320 */
-#define Subround(f, a, b, c, d, e, x, s, k) \
-    a += f(b, c, d) + x + k;\
-    a = rotlFixed((word32)a, s) + e;\
-    c = rotlFixed((word32)c, 10U)
-
-static void Transform(RipeMd* ripemd)
-{
-    word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
-    a1 = a2 = ripemd->digest[0];
-    b1 = b2 = ripemd->digest[1];
-    c1 = c2 = ripemd->digest[2];
-    d1 = d2 = ripemd->digest[3];
-    e1 = e2 = ripemd->digest[4];
-
-    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 11, k0);
-    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 1], 14, k0);
-    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 2], 15, k0);
-    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 12, k0);
-    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 4],  5, k0);
-    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 5],  8, k0);
-    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 6],  7, k0);
-    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 7],  9, k0);
-    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 11, k0);
-    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 13, k0);
-    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[10], 14, k0);
-    Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[11], 15, k0);
-    Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[12],  6, k0);
-    Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[13],  7, k0);
-    Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[14],  9, k0);
-    Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[15],  8, k0);
-
-    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 7],  7, k1);
-    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 4],  6, k1);
-    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[13],  8, k1);
-    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 13, k1);
-    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[10], 11, k1);
-    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 6],  9, k1);
-    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[15],  7, k1);
-    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 15, k1);
-    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[12],  7, k1);
-    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 12, k1);
-    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 15, k1);
-    Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 5],  9, k1);
-    Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 11, k1);
-    Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[14],  7, k1);
-    Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[11], 13, k1);
-    Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 8], 12, k1);
-
-    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 11, k2);
-    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[10], 13, k2);
-    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[14],  6, k2);
-    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 4],  7, k2);
-    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 14, k2);
-    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[15],  9, k2);
-    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 13, k2);
-    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 15, k2);
-    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 14, k2);
-    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 7],  8, k2);
-    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 13, k2);
-    Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 6],  6, k2);
-    Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[13],  5, k2);
-    Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[11], 12, k2);
-    Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  7, k2);
-    Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[12],  5, k2);
-
-    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 11, k3);
-    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 12, k3);
-    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[11], 14, k3);
-    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[10], 15, k3);
-    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 14, k3);
-    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 15, k3);
-    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[12],  9, k3);
-    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[ 4],  8, k3);
-    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[13],  9, k3);
-    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 14, k3);
-    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 7],  5, k3);
-    Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[15],  6, k3);
-    Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[14],  8, k3);
-    Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  6, k3);
-    Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 6],  5, k3);
-    Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 12, k3);
-
-    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 4],  9, k4);
-    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 15, k4);
-    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[ 5],  5, k4);
-    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 9], 11, k4);
-    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 7],  6, k4);
-    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[12],  8, k4);
-    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 13, k4);
-    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[10], 12, k4);
-    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[14],  5, k4);
-    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 12, k4);
-    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 3], 13, k4);
-    Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 8], 14, k4);
-    Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[11], 11, k4);
-    Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 6],  8, k4);
-    Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[15],  5, k4);
-    Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[13],  6, k4);
-
-    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 5],  8, k5);
-    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[14],  9, k5);
-    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 7],  9, k5);
-    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[ 0], 11, k5);
-    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 13, k5);
-    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 2], 15, k5);
-    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[11], 15, k5);
-    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 4],  5, k5);
-    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[13],  7, k5);
-    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 6],  7, k5);
-    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[15],  8, k5);
-    Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 11, k5);
-    Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 1], 14, k5);
-    Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[10], 14, k5);
-    Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 3], 12, k5);
-    Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[12],  6, k5);
-
-    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 6],  9, k6);
-    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[11], 13, k6);
-    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 3], 15, k6);
-    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 7],  7, k6);
-    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 12, k6);
-    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[13],  8, k6);
-    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[ 5],  9, k6);
-    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[10], 11, k6);
-    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[14],  7, k6);
-    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[15],  7, k6);
-    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 12, k6);
-    Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[12],  7, k6);
-    Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 4],  6, k6);
-    Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 15, k6);
-    Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 1], 13, k6);
-    Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 2], 11, k6);
-
-    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[15],  9, k7);
-    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 5],  7, k7);
-    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 1], 15, k7);
-    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 3], 11, k7);
-    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  8, k7);
-    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[14],  6, k7);
-    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 6],  6, k7);
-    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 14, k7);
-    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[11], 12, k7);
-    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 13, k7);
-    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[12],  5, k7);
-    Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 14, k7);
-    Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[10], 13, k7);
-    Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 13, k7);
-    Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 4],  7, k7);
-    Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[13],  5, k7);
-
-    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 8], 15, k8);
-    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[ 6],  5, k8);
-    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 4],  8, k8);
-    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 1], 11, k8);
-    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 14, k8);
-    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[11], 14, k8);
-    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[15],  6, k8);
-    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 14, k8);
-    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 5],  6, k8);
-    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[12],  9, k8);
-    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 12, k8);
-    Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[13],  9, k8);
-    Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 9], 12, k8);
-    Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  5, k8);
-    Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[10], 15, k8);
-    Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[14],  8, k8);
-
-    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[12],  8, k9);
-    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[15],  5, k9);
-    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[10], 12, k9);
-    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 4],  9, k9);
-    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 1], 12, k9);
-    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[ 5],  5, k9);
-    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[ 8], 14, k9);
-    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 7],  6, k9);
-    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 6],  8, k9);
-    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 13, k9);
-    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[13],  6, k9);
-    Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[14],  5, k9);
-    Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 0], 15, k9);
-    Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 13, k9);
-    Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 9], 11, k9);
-    Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[11], 11, k9);
-
-    c1                = ripemd->digest[1] + c1 + d2;
-    ripemd->digest[1] = ripemd->digest[2] + d1 + e2;
-    ripemd->digest[2] = ripemd->digest[3] + e1 + a2;
-    ripemd->digest[3] = ripemd->digest[4] + a1 + b2;
-    ripemd->digest[4] = ripemd->digest[0] + b1 + c2;
-    ripemd->digest[0] = c1;
-}
-
-
-static WC_INLINE void AddLength(RipeMd* ripemd, word32 len)
-{
-    word32 tmp = ripemd->loLen;
-    if ( (ripemd->loLen += len) < tmp)
-        ripemd->hiLen++;                       /* carry low to high */
-}
-
-
-int wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len)
-{
-    /* do block size increments */
-    byte* local;
-
-    if (ripemd == NULL || (data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-    local = (byte*)ripemd->buffer;
-
-    while (len) {
-        word32 add = min(len, RIPEMD_BLOCK_SIZE - ripemd->buffLen);
-        XMEMCPY(&local[ripemd->buffLen], data, add);
-
-        ripemd->buffLen += add;
-        data         += add;
-        len          -= add;
-
-        if (ripemd->buffLen == RIPEMD_BLOCK_SIZE) {
-            #ifdef BIG_ENDIAN_ORDER
-                ByteReverseWords(ripemd->buffer, ripemd->buffer,
-                                 RIPEMD_BLOCK_SIZE);
-            #endif
-            Transform(ripemd);
-            AddLength(ripemd, RIPEMD_BLOCK_SIZE);
-            ripemd->buffLen = 0;
-        }
-    }
-    return 0;
-}
-
-
-int wc_RipeMdFinal(RipeMd* ripemd, byte* hash)
-{
-    byte* local;
-
-    if (ripemd == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    local = (byte*)ripemd->buffer;
-
-    AddLength(ripemd, ripemd->buffLen);               /* before adding pads */
-
-    local[ripemd->buffLen++] = 0x80;  /* add 1 */
-
-    /* pad with zeros */
-    if (ripemd->buffLen > RIPEMD_PAD_SIZE) {
-        XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_BLOCK_SIZE - ripemd->buffLen);
-        ripemd->buffLen += RIPEMD_BLOCK_SIZE - ripemd->buffLen;
-
-        #ifdef BIG_ENDIAN_ORDER
-            ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE);
-        #endif
-        Transform(ripemd);
-        ripemd->buffLen = 0;
-    }
-    XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_PAD_SIZE - ripemd->buffLen);
-
-    /* put lengths in bits */
-    ripemd->loLen = ripemd->loLen << 3;
-    ripemd->hiLen = (ripemd->loLen >> (8*sizeof(ripemd->loLen) - 3)) +
-                 (ripemd->hiLen << 3);
-
-    /* store lengths */
-    #ifdef BIG_ENDIAN_ORDER
-        ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE);
-    #endif
-    /* ! length ordering dependent on digest endian type ! */
-    XMEMCPY(&local[RIPEMD_PAD_SIZE], &ripemd->loLen, sizeof(word32));
-    XMEMCPY(&local[RIPEMD_PAD_SIZE + sizeof(word32)], &ripemd->hiLen,
-           sizeof(word32));
-
-    Transform(ripemd);
-    #ifdef BIG_ENDIAN_ORDER
-        ByteReverseWords(ripemd->digest, ripemd->digest, RIPEMD_DIGEST_SIZE);
-    #endif
-    XMEMCPY(hash, ripemd->digest, RIPEMD_DIGEST_SIZE);
-
-    return wc_InitRipeMd(ripemd);  /* reset state */
-}
-
-
-#endif /* WOLFSSL_RIPEMD */
-
--- a/wolfcrypt/src/rsa.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3096 +0,0 @@
-/* rsa.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifndef NO_RSA
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-       #ifdef USE_WINDOWS_API
-               #pragma code_seg(".fipsA$e")
-               #pragma const_seg(".fipsB$e")
-       #endif
-#endif
-
-#include <wolfssl/wolfcrypt/rsa.h>
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-#include <wolfssl/wolfcrypt/sp.h>
-#endif
-
-/*
-Possible RSA enable options:
- * NO_RSA:              Overall control of RSA                      default: on (not defined)
- * WC_RSA_BLINDING:     Uses Blinding w/ Private Ops                default: off
-                        Note: slower by ~20%
- * WOLFSSL_KEY_GEN:     Allows Private Key Generation               default: off
- * RSA_LOW_MEM:         NON CRT Private Operations, less memory     default: off
- * WC_NO_RSA_OAEP:      Disables RSA OAEP padding                   default: on (not defined)
-
-*/
-
-/*
-RSA Key Size Configuration:
- * FP_MAX_BITS:         With USE_FAST_MATH only                     default: 4096
-    If USE_FAST_MATH then use this to override default.
-    Value is key size * 2. Example: RSA 3072 = 6144
-*/
-
-
-/* If building for old FIPS. */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-int  wc_InitRsaKey(RsaKey* key, void* ptr)
-{
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    return InitRsaKey_fips(key, ptr);
-}
-
-
-int  wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId)
-{
-    (void)devId;
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return InitRsaKey_fips(key, ptr);
-}
-
-
-int  wc_FreeRsaKey(RsaKey* key)
-{
-    return FreeRsaKey_fips(key);
-}
-
-
-int  wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
-                                 word32 outLen, RsaKey* key, WC_RNG* rng)
-{
-    if (in == NULL || out == NULL || key == NULL || rng == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng);
-}
-
-
-int  wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
-                                        RsaKey* key)
-{
-    if (in == NULL || out == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaPrivateDecryptInline_fips(in, inLen, out, key);
-}
-
-
-int  wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
-                                  word32 outLen, RsaKey* key)
-{
-    if (in == NULL || out == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key);
-}
-
-
-int  wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
-                            word32 outLen, RsaKey* key, WC_RNG* rng)
-{
-    if (in == NULL || out == NULL || key == NULL || inLen == 0) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng);
-}
-
-
-int  wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
-{
-    if (in == NULL || out == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaSSL_VerifyInline_fips(in, inLen, out, key);
-}
-
-
-int  wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
-                              word32 outLen, RsaKey* key)
-{
-    if (in == NULL || out == NULL || key == NULL || inLen == 0) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaSSL_Verify_fips(in, inLen, out, outLen, key);
-}
-
-
-int  wc_RsaEncryptSize(RsaKey* key)
-{
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-    return RsaEncryptSize_fips(key);
-}
-
-
-int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b,
-                           word32* bSz)
-{
-
-    /* not specified as fips so not needing _fips */
-    return RsaFlattenPublicKey(key, a, aSz, b, bSz);
-}
-
-
-#ifdef WOLFSSL_KEY_GEN
-    int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
-    {
-        return MakeRsaKey(key, size, e, rng);
-    }
-#endif
-
-
-/* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c
-* wc_RsaPrivateKeyDecode
-* wc_RsaPublicKeyDecode
-*/
-
-#else /* else build without fips, or for new fips */
-
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef WOLF_CRYPTO_DEV
-    #include <wolfssl/wolfcrypt/cryptodev.h>
-#endif
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#define ERROR_OUT(x) { ret = (x); goto done;}
-
-
-enum {
-    RSA_STATE_NONE = 0,
-
-    RSA_STATE_ENCRYPT_PAD,
-    RSA_STATE_ENCRYPT_EXPTMOD,
-    RSA_STATE_ENCRYPT_RES,
-
-    RSA_STATE_DECRYPT_EXPTMOD,
-    RSA_STATE_DECRYPT_UNPAD,
-    RSA_STATE_DECRYPT_RES,
-};
-
-static void wc_RsaCleanup(RsaKey* key)
-{
-    if (key && key->data) {
-        /* make sure any allocated memory is free'd */
-        if (key->dataIsAlloc) {
-            if (key->type == RSA_PRIVATE_DECRYPT ||
-                key->type == RSA_PRIVATE_ENCRYPT) {
-                ForceZero(key->data, key->dataLen);
-            }
-            XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT);
-            key->dataIsAlloc = 0;
-        }
-        key->data = NULL;
-        key->dataLen = 0;
-    }
-}
-
-int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(key, 0, sizeof(RsaKey));
-
-    key->type = RSA_TYPE_UNKNOWN;
-    key->state = RSA_STATE_NONE;
-    key->heap = heap;
-    key->data = NULL;
-    key->dataLen = 0;
-    key->dataIsAlloc = 0;
-#ifdef WC_RSA_BLINDING
-    key->rng = NULL;
-#endif
-
-#ifdef WOLF_CRYPTO_DEV
-    key->devId = devId;
-#else
-    (void)devId;
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #ifdef WOLFSSL_CERT_GEN
-        XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx));
-    #endif
-
-    #ifdef WC_ASYNC_ENABLE_RSA
-        /* handle as async */
-        ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA,
-                                                            key->heap, devId);
-        if (ret != 0)
-            return ret;
-    #endif /* WC_ASYNC_ENABLE_RSA */
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL);
-    if (ret != MP_OKAY)
-        return ret;
-
-#if !defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)
-    ret = mp_init_multi(&key->d, &key->p, &key->q, NULL, NULL, NULL);
-#else
-    ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u);
-#endif
-    if (ret != MP_OKAY) {
-        mp_clear(&key->n);
-        mp_clear(&key->e);
-        return ret;
-    }
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    key->pubExp = 0;
-    key->mod    = NULL;
-#endif
-
-    return ret;
-}
-
-int wc_InitRsaKey(RsaKey* key, void* heap)
-{
-    return wc_InitRsaKey_ex(key, heap, INVALID_DEVID);
-}
-
-
-#ifdef WOLFSSL_XILINX_CRYPT
-#define MAX_E_SIZE 4
-/* Used to setup hardware state
- *
- * key  the RSA key to setup
- *
- * returns 0 on success
- */
-int wc_InitRsaHw(RsaKey* key)
-{
-    unsigned char* m; /* RSA modulous */
-    word32 e = 0;     /* RSA public exponent */
-    int mSz;
-    int eSz;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    mSz = mp_unsigned_bin_size(&(key->n));
-    m = (unsigned char*)XMALLOC(mSz, key->heap, DYNAMIC_TYPE_KEY);
-    if (m == 0) {
-        return MEMORY_E;
-    }
-
-    if (mp_to_unsigned_bin(&(key->n), m) != MP_OKAY) {
-        WOLFSSL_MSG("Unable to get RSA key modulus");
-        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
-        return MP_READ_E;
-    }
-
-    eSz = mp_unsigned_bin_size(&(key->e));
-    if (eSz > MAX_E_SIZE) {
-        WOLFSSL_MSG("Exponent of size 4 bytes expected");
-        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
-        return BAD_FUNC_ARG;
-    }
-
-    if (mp_to_unsigned_bin(&(key->e), (byte*)&e + (MAX_E_SIZE - eSz))
-                != MP_OKAY) {
-        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
-        WOLFSSL_MSG("Unable to get RSA key exponent");
-        return MP_READ_E;
-    }
-
-    /* check for existing mod buffer to avoid memory leak */
-    if (key->mod != NULL) {
-        XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY);
-    }
-
-    key->pubExp = e;
-    key->mod    = m;
-
-    if (XSecure_RsaInitialize(&(key->xRsa), key->mod, NULL,
-                (byte*)&(key->pubExp)) != XST_SUCCESS) {
-        WOLFSSL_MSG("Unable to initialize RSA on hardware");
-        XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
-        return BAD_STATE_E;
-    }
-
-#ifdef WOLFSSL_XILINX_PATCH
-   /* currently a patch of xsecure_rsa.c for 2048 bit keys */
-   if (wc_RsaEncryptSize(key) == 256) {
-       if (XSecure_RsaSetSize(&(key->xRsa), 2048) != XST_SUCCESS) {
-           WOLFSSL_MSG("Unable to set RSA key size on hardware");
-           XFREE(m, key->heap, DYNAMIC_TYPE_KEY);
-           return BAD_STATE_E;
-       }
-   }
-#endif
-
-    return 0;
-}
-#endif /* WOLFSSL_XILINX_CRYPT */
-
-int wc_FreeRsaKey(RsaKey* key)
-{
-    int ret = 0;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    wc_RsaCleanup(key);
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
-    wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA);
-#endif
-
-    if (key->type == RSA_PRIVATE) {
-#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
-        mp_forcezero(&key->u);
-        mp_forcezero(&key->dQ);
-        mp_forcezero(&key->dP);
-#endif
-        mp_forcezero(&key->q);
-        mp_forcezero(&key->p);
-        mp_forcezero(&key->d);
-    }
-    /* private part */
-#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
-    mp_clear(&key->u);
-    mp_clear(&key->dQ);
-    mp_clear(&key->dP);
-#endif
-    mp_clear(&key->q);
-    mp_clear(&key->p);
-    mp_clear(&key->d);
-
-    /* public part */
-    mp_clear(&key->e);
-    mp_clear(&key->n);
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY);
-    key->mod = NULL;
-#endif
-
-    return ret;
-}
-
-
-/* Check the pair-wise consistency of the RSA key.
- * From NIST SP 800-56B, section 6.4.1.1.
- * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */
-int wc_CheckRsaKey(RsaKey* key)
-{
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int *k = NULL, *tmp = NULL;
-#else
-    mp_int k[1], tmp[1];
-#endif
-    int ret = 0;
-
-#ifdef WOLFSSL_SMALL_STACK
-    k = (mp_int*)XMALLOC(sizeof(mp_int) * 2, NULL, DYNAMIC_TYPE_RSA);
-    if (k == NULL)
-        return MEMORY_E;
-    tmp = k + 1;
-#endif
-
-    if (mp_init_multi(k, tmp, NULL, NULL, NULL, NULL) != MP_OKAY)
-        ret = MP_INIT_E;
-
-    if (ret == 0) {
-        if (key == NULL)
-            ret = BAD_FUNC_ARG;
-    }
-
-    if (ret == 0) {
-        if (mp_set_int(k, 0x2342) != MP_OKAY)
-            ret = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SP_RSA
-#ifndef WOLFSSL_SP_NO_2048
-    if (mp_count_bits(&key->n) == 2048) {
-        ret = sp_ModExp_2048(k, &key->e, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-        ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-    }
-    else
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-    if (mp_count_bits(&key->n) == 3072) {
-        ret = sp_ModExp_3072(k, &key->e, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-        ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp);
-        if (ret != 0)
-            ret = MP_EXPTMOD_E;
-    }
-    else
-#endif
-#endif
-#ifdef WOLFSSL_SP_MATH
-    {
-        ret = WC_KEY_SIZE_E;
-    }
-#else
-    {
-        if (ret == 0) {
-            if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        }
-
-        if (ret == 0) {
-            if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        }
-    }
-#endif
-
-    if (ret == 0) {
-        if (mp_cmp(k, tmp) != MP_EQ)
-            ret = RSA_KEY_PAIR_E;
-    }
-
-    mp_forcezero(tmp);
-    mp_clear(tmp);
-    mp_clear(k);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(k, NULL, DYNAMIC_TYPE_RSA);
-#endif
-
-    return ret;
-}
-
-
-#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS)
-/* Uses MGF1 standard as a mask generation function
-   hType: hash type used
-   seed:  seed to use for generating mask
-   seedSz: size of seed buffer
-   out:   mask output after generation
-   outSz: size of output buffer
- */
-static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz,
-                                        byte* out, word32 outSz, void* heap)
-{
-    byte* tmp;
-    /* needs to be large enough for seed size plus counter(4) */
-    byte  tmpA[WC_MAX_DIGEST_SIZE + 4];
-    byte   tmpF;     /* 1 if dynamic memory needs freed */
-    word32 tmpSz;
-    int hLen;
-    int ret;
-    word32 counter;
-    word32 idx;
-    hLen    = wc_HashGetDigestSize(hType);
-    counter = 0;
-    idx     = 0;
-
-    (void)heap;
-
-    /* check error return of wc_HashGetDigestSize */
-    if (hLen < 0) {
-        return hLen;
-    }
-
-    /* if tmp is not large enough than use some dynamic memory */
-    if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) {
-        /* find largest amount of memory needed which will be the max of
-         * hLen and (seedSz + 4) since tmp is used to store the hash digest */
-        tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen;
-        tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        if (tmp == NULL) {
-            return MEMORY_E;
-        }
-        tmpF = 1; /* make sure to free memory when done */
-    }
-    else {
-        /* use array on the stack */
-        tmpSz = sizeof(tmpA);
-        tmp  = tmpA;
-        tmpF = 0; /* no need to free memory at end */
-    }
-
-    do {
-        int i = 0;
-        XMEMCPY(tmp, seed, seedSz);
-
-        /* counter to byte array appended to tmp */
-        tmp[seedSz]     = (counter >> 24) & 0xFF;
-        tmp[seedSz + 1] = (counter >> 16) & 0xFF;
-        tmp[seedSz + 2] = (counter >>  8) & 0xFF;
-        tmp[seedSz + 3] = (counter)       & 0xFF;
-
-        /* hash and append to existing output */
-        if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) {
-            /* check for if dynamic memory was needed, then free */
-            if (tmpF) {
-                XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            }
-            return ret;
-        }
-
-        for (i = 0; i < hLen && idx < outSz; i++) {
-            out[idx++] = tmp[i];
-        }
-        counter++;
-    } while (idx < outSz);
-
-    /* check for if dynamic memory was needed, then free */
-    if (tmpF) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-    }
-
-    return 0;
-}
-
-/* helper function to direct which mask generation function is used
-   switeched on type input
- */
-static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out,
-                                                    word32 outSz, void* heap)
-{
-    int ret;
-
-    switch(type) {
-    #ifndef NO_SHA
-        case WC_MGF1SHA1:
-            ret = RsaMGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap);
-            break;
-    #endif
-    #ifndef NO_SHA256
-    #ifdef WOLFSSL_SHA224
-        case WC_MGF1SHA224:
-            ret = RsaMGF1(WC_HASH_TYPE_SHA224, seed, seedSz, out, outSz, heap);
-            break;
-    #endif
-        case WC_MGF1SHA256:
-            ret = RsaMGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz, heap);
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        case WC_MGF1SHA384:
-            ret = RsaMGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz, heap);
-            break;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        case WC_MGF1SHA512:
-            ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap);
-            break;
-    #endif
-        default:
-            WOLFSSL_MSG("Unknown MGF type: check build options");
-            ret = BAD_FUNC_ARG;
-    }
-
-    /* in case of default avoid unused warning */
-    (void)seed;
-    (void)seedSz;
-    (void)out;
-    (void)outSz;
-    (void)heap;
-
-    return ret;
-}
-#endif /* !WC_NO_RSA_OAEP */
-
-
-/* Padding */
-#ifndef WC_NO_RSA_OAEP
-static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock,
-        word32 pkcsBlockLen, byte padValue, WC_RNG* rng,
-        enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen,
-        void* heap)
-{
-    int ret;
-    int hLen;
-    int psLen;
-    int i;
-    word32 idx;
-
-    byte* dbMask;
-
-    #ifdef WOLFSSL_SMALL_STACK
-        byte* lHash = NULL;
-        byte* seed  = NULL;
-    #else
-        /* must be large enough to contain largest hash */
-        byte lHash[WC_MAX_DIGEST_SIZE];
-        byte seed[ WC_MAX_DIGEST_SIZE];
-    #endif
-
-    /* no label is allowed, but catch if no label provided and length > 0 */
-    if (optLabel == NULL && labelLen > 0) {
-        return BUFFER_E;
-    }
-
-    /* limit of label is the same as limit of hash function which is massive */
-    hLen = wc_HashGetDigestSize(hType);
-    if (hLen < 0) {
-        return hLen;
-    }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        if (lHash == NULL) {
-            return MEMORY_E;
-        }
-        seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        if (seed == NULL) {
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            return MEMORY_E;
-        }
-    #else
-        /* hLen should never be larger than lHash since size is max digest size,
-           but check before blindly calling wc_Hash */
-        if ((word32)hLen > sizeof(lHash)) {
-            WOLFSSL_MSG("OAEP lHash to small for digest!!");
-            return MEMORY_E;
-        }
-    #endif
-
-    if ((ret = wc_Hash(hType, optLabel, labelLen, lHash, hLen)) != 0) {
-        WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small");
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return ret;
-    }
-
-    /* handles check of location for idx as well as psLen, cast to int to check
-       for pkcsBlockLen(k) - 2 * hLen - 2 being negative
-       This check is similar to decryption where k > 2 * hLen + 2 as msg
-       size approaches 0. In decryption if k is less than or equal -- then there
-       is no possible room for msg.
-       k = RSA key size
-       hLen = hash digest size -- will always be >= 0 at this point
-     */
-    if ((word32)(2 * hLen + 2) > pkcsBlockLen) {
-        WOLFSSL_MSG("OAEP pad error hash to big for RSA key size");
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return BAD_FUNC_ARG;
-    }
-
-    if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) {
-        WOLFSSL_MSG("OAEP pad error message too long");
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return BAD_FUNC_ARG;
-    }
-
-    /* concatenate lHash || PS || 0x01 || msg */
-    idx = pkcsBlockLen - 1 - inputLen;
-    psLen = pkcsBlockLen - inputLen - 2 * hLen - 2;
-    if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return BUFFER_E;
-    }
-    XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen);
-    pkcsBlock[idx--] = 0x01; /* PS and M separator */
-    while (psLen > 0 && idx > 0) {
-        pkcsBlock[idx--] = 0x00;
-        psLen--;
-    }
-
-    idx = idx - hLen + 1;
-    XMEMCPY(pkcsBlock + idx, lHash, hLen);
-
-    /* generate random seed */
-    if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) {
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return ret;
-    }
-
-    /* create maskedDB from dbMask */
-    dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA);
-    if (dbMask == NULL) {
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return MEMORY_E;
-    }
-    XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */
-
-    ret = RsaMGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap);
-    if (ret != 0) {
-        XFREE(dbMask, heap, DYNAMIC_TYPE_RSA);
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return ret;
-    }
-
-    i = 0;
-    idx = hLen + 1;
-    while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) {
-        pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx];
-        idx++;
-    }
-    XFREE(dbMask, heap, DYNAMIC_TYPE_RSA);
-
-
-    /* create maskedSeed from seedMask */
-    idx = 0;
-    pkcsBlock[idx++] = 0x00;
-    /* create seedMask inline */
-    if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1,
-                                           pkcsBlock + 1, hLen, heap)) != 0) {
-        #ifdef WOLFSSL_SMALL_STACK
-            XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-        #endif
-        return ret;
-    }
-
-    /* xor created seedMask with seed to make maskedSeed */
-    i = 0;
-    while (idx < (word32)(hLen + 1) && i < hLen) {
-        pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++];
-        idx++;
-    }
-
-    #ifdef WOLFSSL_SMALL_STACK
-        XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        XFREE(seed,  heap, DYNAMIC_TYPE_RSA_BUFFER);
-    #endif
-    (void)padValue;
-
-    return 0;
-}
-#endif /* !WC_NO_RSA_OAEP */
-
-#ifdef WC_RSA_PSS
-
-/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc
- * XOR MGF over all bytes down to end of Salt
- * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt)
- *
- * input         Digest of the message.
- * inputLen      Length of digest.
- * pkcsBlock     Buffer to write to.
- * pkcsBlockLen  Length of buffer to write to.
- * rng           Random number generator (for salt).
- * htype         Hash function to use.
- * mgf           Mask generation function.
- * saltLen       Length of salt to put in padding.
- * bits          Length of key in bits.
- * heap          Used for dynamic memory allocation.
- * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid
- * and other negative values on error.
- */
-static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock,
-        word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf,
-        int saltLen, int bits, void* heap)
-{
-    int   ret;
-    int   hLen, i;
-    byte* s;
-    byte* m;
-    byte* h;
-    byte  salt[WC_MAX_DIGEST_SIZE];
-
-    hLen = wc_HashGetDigestSize(hType);
-    if (hLen < 0)
-        return hLen;
-
-    if (saltLen == -1) {
-        saltLen = hLen;
-        #ifdef WOLFSSL_SHA512
-            /* See FIPS 186-4 section 5.5 item (e). */
-            if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
-                saltLen = RSA_PSS_SALT_MAX_SZ;
-        #endif
-    }
-    else if (saltLen > hLen || saltLen < -1)
-        return PSS_SALTLEN_E;
-    if ((int)pkcsBlockLen - hLen < saltLen + 2)
-        return PSS_SALTLEN_E;
-
-    s = m = pkcsBlock;
-    XMEMSET(m, 0, RSA_PSS_PAD_SZ);
-    m += RSA_PSS_PAD_SZ;
-    XMEMCPY(m, input, inputLen);
-    m += inputLen;
-    if ((ret = wc_RNG_GenerateBlock(rng, salt, saltLen)) != 0)
-        return ret;
-    XMEMCPY(m, salt, saltLen);
-    m += saltLen;
-
-    h = pkcsBlock + pkcsBlockLen - 1 - hLen;
-    if ((ret = wc_Hash(hType, s, (word32)(m - s), h, hLen)) != 0)
-        return ret;
-    pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM;
-
-    ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap);
-    if (ret != 0)
-        return ret;
-    pkcsBlock[0] &= (1 << ((bits - 1) & 0x7)) - 1;
-
-    m = pkcsBlock + pkcsBlockLen - 1 - saltLen - hLen - 1;
-    *(m++) ^= 0x01;
-    for (i = 0; i < saltLen; i++)
-        m[i] ^= salt[i];
-
-    return 0;
-}
-#endif
-
-static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
-                           word32 pkcsBlockLen, byte padValue, WC_RNG* rng)
-{
-    if (input == NULL || inputLen == 0 || pkcsBlock == NULL ||
-                                                        pkcsBlockLen == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
-    pkcsBlock++; pkcsBlockLen--;
-    pkcsBlock[0] = padValue;  /* insert padValue */
-
-    if (padValue == RSA_BLOCK_TYPE_1) {
-        if (pkcsBlockLen < inputLen + 2) {
-            WOLFSSL_MSG("RsaPad error, invalid length");
-            return RSA_PAD_E;
-        }
-
-        /* pad with 0xff bytes */
-        XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
-    }
-    else {
-        /* pad with non-zero random bytes */
-        word32 padLen, i;
-        int    ret;
-
-        if (pkcsBlockLen < inputLen + 1) {
-            WOLFSSL_MSG("RsaPad error, invalid length");
-            return RSA_PAD_E;
-        }
-
-        padLen = pkcsBlockLen - inputLen - 1;
-        ret    = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
-        if (ret != 0) {
-            return ret;
-        }
-
-        /* remove zeros */
-        for (i = 1; i < padLen; i++) {
-            if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
-        }
-    }
-
-    pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
-    XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
-
-    return 0;
-}
-
-/* helper function to direct which padding is used */
-static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
-    word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType,
-    enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen,
-    int saltLen, int bits, void* heap)
-{
-    int ret;
-
-    switch (padType)
-    {
-        case WC_RSA_PKCSV15_PAD:
-            /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/
-            ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen,
-                                                                 padValue, rng);
-            break;
-
-    #ifndef WC_NO_RSA_OAEP
-        case WC_RSA_OAEP_PAD:
-            WOLFSSL_MSG("wolfSSL Using RSA OAEP padding");
-            ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen,
-                           padValue, rng, hType, mgf, optLabel, labelLen, heap);
-            break;
-    #endif
-
-    #ifdef WC_RSA_PSS
-        case WC_RSA_PSS_PAD:
-            WOLFSSL_MSG("wolfSSL Using RSA PSS padding");
-            ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, rng,
-                                               hType, mgf, saltLen, bits, heap);
-            break;
-    #endif
-
-    #ifdef WC_RSA_NO_PADDING
-        case WC_RSA_NO_PAD:
-            WOLFSSL_MSG("wolfSSL Using NO padding");
-
-            /* In the case of no padding being used check that input is exactly
-             * the RSA key length */
-            if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
-                WOLFSSL_MSG("Bad input size");
-                ret = RSA_PAD_E;
-            }
-            else {
-                XMEMCPY(pkcsBlock, input, inputLen);
-                ret = 0;
-            }
-            break;
-    #endif
-
-        default:
-            WOLFSSL_MSG("Unknown RSA Pad Type");
-            ret = RSA_PAD_E;
-    }
-
-    /* silence warning if not used with padding scheme */
-    (void)hType;
-    (void)mgf;
-    (void)optLabel;
-    (void)labelLen;
-    (void)saltLen;
-    (void)bits;
-    (void)heap;
-
-    return ret;
-}
-
-
-/* UnPadding */
-#ifndef WC_NO_RSA_OAEP
-/* UnPad plaintext, set start to *output, return length of plaintext,
- * < 0 on error */
-static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen,
-                            byte **output, enum wc_HashType hType, int mgf,
-                            byte* optLabel, word32 labelLen, void* heap)
-{
-    int hLen;
-    int ret;
-    byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */
-    byte* tmp;
-    word32 idx;
-
-    /* no label is allowed, but catch if no label provided and length > 0 */
-    if (optLabel == NULL && labelLen > 0) {
-        return BUFFER_E;
-    }
-
-    hLen = wc_HashGetDigestSize(hType);
-    if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) {
-        return BAD_FUNC_ARG;
-    }
-
-    tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
-    if (tmp == NULL) {
-        return MEMORY_E;
-    }
-    XMEMSET(tmp, 0, pkcsBlockLen);
-
-    /* find seedMask value */
-    if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)),
-                            pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        return ret;
-    }
-
-    /* xor seedMask value with maskedSeed to get seed value */
-    for (idx = 0; idx < (word32)hLen; idx++) {
-        tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx];
-    }
-
-    /* get dbMask value */
-    if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen,
-                                       pkcsBlockLen - hLen - 1, heap)) != 0) {
-        XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER);
-        return ret;
-    }
-
-    /* get DB value by doing maskedDB xor dbMask */
-    for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) {
-        pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen];
-    }
-
-    /* done with use of tmp buffer */
-    XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-
-    /* advance idx to index of PS and msg separator, account for PS size of 0*/
-    idx = hLen + 1 + hLen;
-    while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;}
-
-    /* create hash of label for comparison with hash sent */
-    if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) {
-        return ret;
-    }
-
-    /* say no to chosen ciphertext attack.
-       Comparison of lHash, Y, and separator value needs to all happen in
-       constant time.
-       Attackers should not be able to get error condition from the timing of
-       these checks.
-     */
-    ret = 0;
-    ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen);
-    ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */
-    ret += pkcsBlock[0]     ^ 0x00; /* Y, the first value, should be 0 */
-
-    if (ret != 0) {
-        WOLFSSL_MSG("RsaUnPad_OAEP: Padding Error");
-        return BAD_PADDING_E;
-    }
-
-    /* adjust pointer to correct location in array and return size of M */
-    *output = (byte*)(pkcsBlock + idx);
-    return pkcsBlockLen - idx;
-}
-#endif /* WC_NO_RSA_OAEP */
-
-#ifdef WC_RSA_PSS
-/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc
- * MGF over all bytes down to end of Salt
- *
- * pkcsBlock     Buffer holding decrypted data.
- * pkcsBlockLen  Length of buffer.
- * htype         Hash function to use.
- * mgf           Mask generation function.
- * saltLen       Length of salt to put in padding.
- * bits          Length of key in bits.
- * heap          Used for dynamic memory allocation.
- * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid,
- * BAD_PADDING_E when the padding is not valid, MEMORY_E when allocation fails
- * and other negative values on error.
- */
-static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen,
-                        byte **output, enum wc_HashType hType, int mgf,
-                        int saltLen, int bits, void* heap)
-{
-    int   ret;
-    byte* tmp;
-    int   hLen, i;
-
-    hLen = wc_HashGetDigestSize(hType);
-    if (hLen < 0)
-        return hLen;
-
-    if (saltLen == -1) {
-        saltLen = hLen;
-        #ifdef WOLFSSL_SHA512
-            /* See FIPS 186-4 section 5.5 item (e). */
-            if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
-                saltLen = RSA_PSS_SALT_MAX_SZ;
-        #endif
-    }
-    else if (saltLen > hLen || saltLen < -1)
-        return PSS_SALTLEN_E;
-    if ((int)pkcsBlockLen - hLen < saltLen + 2)
-        return PSS_SALTLEN_E;
-
-    if (pkcsBlock[pkcsBlockLen - 1] != RSA_PSS_PAD_TERM) {
-        WOLFSSL_MSG("RsaUnPad_PSS: Padding Term Error");
-        return BAD_PADDING_E;
-    }
-
-    tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER);
-    if (tmp == NULL)
-        return MEMORY_E;
-
-    if ((ret = RsaMGF(mgf, pkcsBlock + pkcsBlockLen - 1 - hLen, hLen,
-                                    tmp, pkcsBlockLen - 1 - hLen, heap)) != 0) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        return ret;
-    }
-
-    tmp[0] &= (1 << ((bits - 1) & 0x7)) - 1;
-    for (i = 0; i < (int)(pkcsBlockLen - 1 - saltLen - hLen - 1); i++) {
-        if (tmp[i] != pkcsBlock[i]) {
-            XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-            WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match");
-            return BAD_PADDING_E;
-        }
-    }
-    if (tmp[i] != (pkcsBlock[i] ^ 0x01)) {
-        XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-        WOLFSSL_MSG("RsaUnPad_PSS: Padding Error End");
-        return BAD_PADDING_E;
-    }
-    for (i++; i < (int)(pkcsBlockLen - 1 - hLen); i++)
-        pkcsBlock[i] ^= tmp[i];
-
-    XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER);
-
-    *output = pkcsBlock + pkcsBlockLen - (hLen + saltLen + 1);
-    return saltLen + hLen;
-}
-#endif
-
-/* UnPad plaintext, set start to *output, return length of plaintext,
- * < 0 on error */
-static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
-                                               byte **output, byte padValue)
-{
-    word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0;
-    word32 invalid = 0;
-    word32 i = 1;
-    word32 outputLen;
-
-    if (output == NULL || pkcsBlockLen == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (pkcsBlock[0] != 0x0) { /* skip past zero */
-        invalid = 1;
-    }
-    pkcsBlock++; pkcsBlockLen--;
-
-    /* Require block type padValue */
-    invalid = (pkcsBlock[0] != padValue) || invalid;
-
-    /* verify the padding until we find the separator */
-    if (padValue == RSA_BLOCK_TYPE_1) {
-        while (i<pkcsBlockLen && pkcsBlock[i++] == 0xFF) {/* Null body */}
-    }
-    else {
-        while (i<pkcsBlockLen && pkcsBlock[i++]) {/* Null body */}
-    }
-
-    if (!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
-        WOLFSSL_MSG("RsaUnPad error, bad formatting");
-        return RSA_PAD_E;
-    }
-
-    outputLen = pkcsBlockLen - i;
-    invalid = (outputLen > maxOutputLen) || invalid;
-
-    if (invalid) {
-        WOLFSSL_MSG("RsaUnPad error, invalid formatting");
-        return RSA_PAD_E;
-    }
-
-    *output = (byte *)(pkcsBlock + i);
-    return outputLen;
-}
-
-/* helper function to direct unpadding
- *
- * bits is the key modulus size in bits
- */
-static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
-                          byte padValue, int padType, enum wc_HashType hType,
-                          int mgf, byte* optLabel, word32 labelLen, int saltLen,
-                          int bits, void* heap)
-{
-    int ret;
-
-    switch (padType) {
-        case WC_RSA_PKCSV15_PAD:
-            /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/
-            ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue);
-            break;
-
-    #ifndef WC_NO_RSA_OAEP
-        case WC_RSA_OAEP_PAD:
-            WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding");
-            ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out,
-                                        hType, mgf, optLabel, labelLen, heap);
-            break;
-    #endif
-
-    #ifdef WC_RSA_PSS
-        case WC_RSA_PSS_PAD:
-            WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding");
-            ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf,
-                                                           saltLen, bits, heap);
-            break;
-    #endif
-
-    #ifdef WC_RSA_NO_PADDING
-        case WC_RSA_NO_PAD:
-            WOLFSSL_MSG("wolfSSL Using NO un-padding");
-
-            /* In the case of no padding being used check that input is exactly
-             * the RSA key length */
-            if (bits <= 0 || pkcsBlockLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
-                WOLFSSL_MSG("Bad input size");
-                ret = RSA_PAD_E;
-            }
-            else {
-                if (out != NULL) {
-                    *out = pkcsBlock;
-                }
-                ret = pkcsBlockLen;
-            }
-            break;
-    #endif /* WC_RSA_NO_PADDING */
-
-        default:
-            WOLFSSL_MSG("Unknown RSA UnPad Type");
-            ret = RSA_PAD_E;
-    }
-
-    /* silence warning if not used with padding scheme */
-    (void)hType;
-    (void)mgf;
-    (void)optLabel;
-    (void)labelLen;
-    (void)saltLen;
-    (void)bits;
-    (void)heap;
-
-    return ret;
-}
-
-#if defined(WOLFSSL_XILINX_CRYPT)
-/*
- * Xilinx hardened crypto acceleration.
- *
- * Returns 0 on success and negative values on error.
- */
-static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out,
-                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-    int    ret = 0;
-    word32 keyLen, len;
-    (void)rng;
-
-    keyLen = wc_RsaEncryptSize(key);
-    if (keyLen > *outLen) {
-        WOLFSSL_MSG("Output buffer is not big enough");
-        return BAD_FUNC_ARG;
-    }
-
-    if (inLen != keyLen) {
-        WOLFSSL_MSG("Expected that inLen equals RSA key length");
-        return BAD_FUNC_ARG;
-    }
-
-    switch(type) {
-    case RSA_PRIVATE_DECRYPT:
-    case RSA_PRIVATE_ENCRYPT:
-        /* Currently public exponent is loaded by default.
-         * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes
-         * leading to private key operations with Xsecure_RsaDecrypt not being
-         * supported */
-        ret = RSA_WRONG_TYPE_E;
-        break;
-    case RSA_PUBLIC_ENCRYPT:
-    case RSA_PUBLIC_DECRYPT:
-        if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) {
-            ret = BAD_STATE_E;
-        }
-        break;
-    default:
-        ret = RSA_WRONG_TYPE_E;
-    }
-
-    *outLen = keyLen;
-
-    return ret;
-}
-#endif /* WOLFSSL_XILINX_CRYPT */
-
-static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out,
-                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-#ifndef WOLFSSL_SP_MATH
-#ifdef WOLFSSL_SMALL_STACK
-    mp_int* tmp = NULL;
-#ifdef WC_RSA_BLINDING
-    mp_int* rnd = NULL;
-    mp_int* rndi = NULL;
-#endif
-#else
-    mp_int tmp[1];
-#ifdef WC_RSA_BLINDING
-    mp_int rnd[1], rndi[1];
-#endif
-#endif
-    int    ret = 0;
-    word32 keyLen, len;
-#endif
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-#ifndef WOLFSSL_SP_NO_2048
-    if (mp_count_bits(&key->n) == 2048) {
-        switch(type) {
-        case RSA_PRIVATE_DECRYPT:
-        case RSA_PRIVATE_ENCRYPT:
-    #ifdef WC_RSA_BLINDING
-            if (rng == NULL)
-                return MISSING_RNG_E;
-    #endif
-    #ifndef RSA_LOW_MEM
-            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
-                                      &key->dP, &key->dQ, &key->u, &key->n,
-                                      out, outLen);
-    #else
-            return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q,
-                                      NULL, NULL, NULL, &key->n, out, outLen);
-    #endif
-        case RSA_PUBLIC_ENCRYPT:
-        case RSA_PUBLIC_DECRYPT:
-            return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen);
-        }
-    }
-#endif
-#ifndef WOLFSSL_SP_NO_3072
-    if (mp_count_bits(&key->n) == 3072) {
-        switch(type) {
-        case RSA_PRIVATE_DECRYPT:
-        case RSA_PRIVATE_ENCRYPT:
-    #ifdef WC_RSA_BLINDING
-            if (rng == NULL)
-                return MISSING_RNG_E;
-    #endif
-    #ifndef RSA_LOW_MEM
-            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
-                                      &key->dP, &key->dQ, &key->u, &key->n,
-                                      out, outLen);
-    #else
-            return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q,
-                                      NULL, NULL, NULL, &key->n, out, outLen);
-    #endif
-        case RSA_PUBLIC_ENCRYPT:
-        case RSA_PUBLIC_DECRYPT:
-            return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen);
-        }
-    }
-#endif
-#endif /* WOLFSSL_HAVE_SP_RSA */
-
-#ifdef WOLFSSL_SP_MATH
-    return WC_KEY_SIZE_E;
-#else
-    (void)rng;
-
-#ifdef WOLFSSL_SMALL_STACK
-    tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA);
-    if (tmp == NULL)
-        return MEMORY_E;
-#ifdef WC_RSA_BLINDING
-    rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA);
-    if (rnd == NULL) {
-        XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
-        return MEMORY_E;
-    }
-    rndi = rnd + 1;
-#endif /* WC_RSA_BLINDING */
-#endif /* WOLFSSL_SMALL_STACK */
-
-    if (mp_init(tmp) != MP_OKAY)
-        ret = MP_INIT_E;
-
-#ifdef WC_RSA_BLINDING
-    if (ret == 0) {
-        if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
-            if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) {
-                mp_clear(tmp);
-                ret = MP_INIT_E;
-            }
-        }
-    }
-#endif
-
-    if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY)
-        ret = MP_READ_E;
-
-    if (ret == 0) {
-        switch(type) {
-        case RSA_PRIVATE_DECRYPT:
-        case RSA_PRIVATE_ENCRYPT:
-        {
-        #ifdef WC_RSA_BLINDING
-            /* blind */
-            ret = mp_rand(rnd, get_digit_count(&key->n), rng);
-
-            /* rndi = 1/rnd mod n */
-            if (ret == 0 && mp_invmod(rnd, &key->n, rndi) != MP_OKAY)
-                ret = MP_INVMOD_E;
-
-            /* rnd = rnd^e */
-            if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-
-            /* tmp = tmp*rnd mod n */
-            if (ret == 0 && mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY)
-                ret = MP_MULMOD_E;
-        #endif /* WC_RSA_BLINDING */
-
-        #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
-            if (ret == 0 && mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-        #else
-            if (ret == 0) {
-            #ifdef WOLFSSL_SMALL_STACK
-                mp_int* tmpa = NULL;
-                mp_int* tmpb = NULL;
-            #else
-                mp_int tmpa[1], tmpb[1];
-            #endif
-                int cleara = 0, clearb = 0;
-
-            #ifdef WOLFSSL_SMALL_STACK
-                tmpa = XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA);
-                if (tmpa != NULL)
-                    tmpb = tmpa + 1;
-                else
-                    ret = MEMORY_E;
-            #endif
-
-                if (ret == 0) {
-                    if (mp_init(tmpa) != MP_OKAY)
-                        ret = MP_INIT_E;
-                    else
-                        cleara = 1;
-                }
-
-                if (ret == 0) {
-                    if (mp_init(tmpb) != MP_OKAY)
-                        ret = MP_INIT_E;
-                    else
-                        clearb = 1;
-                }
-
-                /* tmpa = tmp^dP mod p */
-                if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p,
-                                                               tmpa) != MP_OKAY)
-                    ret = MP_EXPTMOD_E;
-    
-                /* tmpb = tmp^dQ mod q */
-                if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q,
-                                                               tmpb) != MP_OKAY)
-                    ret = MP_EXPTMOD_E;
-
-                /* tmp = (tmpa - tmpb) * qInv (mod p) */
-                if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY)
-                    ret = MP_SUB_E;
-
-                if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p,
-                                                                tmp) != MP_OKAY)
-                    ret = MP_MULMOD_E;
-
-                /* tmp = tmpb + q * tmp */
-                if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY)
-                    ret = MP_MUL_E;
-
-                if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY)
-                    ret = MP_ADD_E;
-
-            #ifdef WOLFSSL_SMALL_STACK
-                if (tmpa != NULL)
-            #endif
-                {
-                    if (cleara)
-                        mp_clear(tmpa);
-                    if (clearb)
-                        mp_clear(tmpb);
-            #ifdef WOLFSSL_SMALL_STACK
-                    XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA);
-            #endif
-                }
-            } /* tmpa/b scope */
-        #endif   /* RSA_LOW_MEM */
-
-        #ifdef WC_RSA_BLINDING
-            /* unblind */
-            if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY)
-                ret = MP_MULMOD_E;
-        #endif   /* WC_RSA_BLINDING */
-
-            break;
-        }
-        case RSA_PUBLIC_ENCRYPT:
-        case RSA_PUBLIC_DECRYPT:
-        #ifdef WOLFSSL_XILINX_CRYPT
-            ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng);
-        #else
-            if (mp_exptmod(tmp, &key->e, &key->n, tmp) != MP_OKAY)
-                ret = MP_EXPTMOD_E;
-            break;
-        #endif
-        default:
-            ret = RSA_WRONG_TYPE_E;
-            break;
-        }
-    }
-
-    if (ret == 0) {
-        keyLen = wc_RsaEncryptSize(key);
-        if (keyLen > *outLen)
-            ret = RSA_BUFFER_E;
-    }
-    if (ret == 0) {
-        len = mp_unsigned_bin_size(tmp);
-
-        /* pad front w/ zeros to match key length */
-        while (len < keyLen) {
-            *out++ = 0x00;
-            len++;
-        }
-
-        *outLen = keyLen;
-
-        /* convert */
-        if (mp_to_unsigned_bin(tmp, out) != MP_OKAY)
-             ret = MP_TO_E;
-    }
-
-    mp_clear(tmp);
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
-#endif
-#ifdef WC_RSA_BLINDING
-    if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
-        mp_clear(rndi);
-        mp_clear(rnd);
-    }
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA);
-#endif
-#endif /* WC_RSA_BLINDING */
-    return ret;
-#endif /* WOLFSSL_SP_MATH */
-}
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
-static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out,
-                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-    int ret = 0;
-
-    (void)rng;
-
-#ifdef WOLFSSL_ASYNC_CRYPT_TEST
-    if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_FUNC)) {
-        WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-        testDev->rsaFunc.in = in;
-        testDev->rsaFunc.inSz = inLen;
-        testDev->rsaFunc.out = out;
-        testDev->rsaFunc.outSz = outLen;
-        testDev->rsaFunc.type = type;
-        testDev->rsaFunc.key = key;
-        testDev->rsaFunc.rng = rng;
-        return WC_PENDING_E;
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT_TEST */
-
-    switch(type) {
-    case RSA_PRIVATE_DECRYPT:
-    case RSA_PRIVATE_ENCRYPT:
-    #ifdef HAVE_CAVIUM
-        key->dataLen = key->n.raw.len;
-        ret = NitroxRsaExptMod(in, inLen,
-                               key->d.raw.buf, key->d.raw.len,
-                               key->n.raw.buf, key->n.raw.len,
-                               out, outLen, key);
-    #elif defined(HAVE_INTEL_QA)
-        #ifdef RSA_LOW_MEM
-            ret = IntelQaRsaPrivate(&key->asyncDev, in, inLen,
-                                    &key->d.raw, &key->n.raw,
-                                    out, outLen);
-        #else
-            ret = IntelQaRsaCrtPrivate(&key->asyncDev, in, inLen,
-                                &key->p.raw, &key->q.raw,
-                                &key->dP.raw, &key->dQ.raw,
-                                &key->u.raw,
-                                out, outLen);
-        #endif
-    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
-    #endif
-        break;
-
-    case RSA_PUBLIC_ENCRYPT:
-    case RSA_PUBLIC_DECRYPT:
-    #ifdef HAVE_CAVIUM
-        key->dataLen = key->n.raw.len;
-        ret = NitroxRsaExptMod(in, inLen,
-                               key->e.raw.buf, key->e.raw.len,
-                               key->n.raw.buf, key->n.raw.len,
-                               out, outLen, key);
-    #elif defined(HAVE_INTEL_QA)
-        ret = IntelQaRsaPublic(&key->asyncDev, in, inLen,
-                               &key->e.raw, &key->n.raw,
-                               out, outLen);
-    #else /* WOLFSSL_ASYNC_CRYPT_TEST */
-        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
-    #endif
-        break;
-
-    default:
-        ret = RSA_WRONG_TYPE_E;
-    }
-
-    return ret;
-}
-#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */
-
-#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING)
-/* Function that does the RSA operation directly with no padding.
- *
- * in       buffer to do operation on
- * inLen    length of input buffer
- * out      buffer to hold results
- * outSz    gets set to size of result buffer. Should be passed in as length
- *          of out buffer. If the pointer "out" is null then outSz gets set to
- *          the expected buffer size needed and LENGTH_ONLY_E gets returned.
- * key      RSA key to use for encrypt/decrypt
- * type     if using private or public key {RSA_PUBLIC_ENCRYPT,
- *          RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT}
- * rng      wolfSSL RNG to use if needed
- *
- * returns size of result on success
- */
-int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
-        RsaKey* key, int type, WC_RNG* rng)
-{
-    int ret;
-
-    if (in == NULL || outSz == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* sanity check on type of RSA operation */
-    switch (type) {
-        case RSA_PUBLIC_ENCRYPT:
-        case RSA_PUBLIC_DECRYPT:
-        case RSA_PRIVATE_ENCRYPT:
-        case RSA_PRIVATE_DECRYPT:
-            break;
-        default:
-            WOLFSSL_MSG("Bad RSA type");
-            return BAD_FUNC_ARG;
-    }
-
-    if ((ret = wc_RsaEncryptSize(key)) < 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (inLen != (word32)ret) {
-        WOLFSSL_MSG("Bad input length. Should be RSA key size");
-        return BAD_FUNC_ARG;
-    }
-
-    if (out == NULL) {
-        *outSz = inLen;
-        return LENGTH_ONLY_E;
-    }
-
-    switch (key->state) {
-        case RSA_STATE_NONE:
-        case RSA_STATE_ENCRYPT_PAD:
-        case RSA_STATE_ENCRYPT_EXPTMOD:
-        case RSA_STATE_DECRYPT_EXPTMOD:
-        case RSA_STATE_DECRYPT_UNPAD:
-            key->state = (type == RSA_PRIVATE_ENCRYPT ||
-                    type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD:
-                                                  RSA_STATE_DECRYPT_EXPTMOD;
-
-            key->dataLen = *outSz;
-
-            ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng);
-            if (ret >= 0 || ret == WC_PENDING_E) {
-                key->state = (type == RSA_PRIVATE_ENCRYPT ||
-                    type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES:
-                                                  RSA_STATE_DECRYPT_RES;
-            }
-            if (ret < 0) {
-                break;
-            }
-
-            FALL_THROUGH;
-
-        case RSA_STATE_ENCRYPT_RES:
-        case RSA_STATE_DECRYPT_RES:
-            ret = key->dataLen;
-            break;
-
-        default:
-            ret = BAD_STATE_E;
-    }
-
-    /* if async pending then skip cleanup*/
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-
-    key->state = RSA_STATE_NONE;
-    wc_RsaCleanup(key);
-
-    return ret;
-}
-#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING */
-
-
-int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
-                          word32* outLen, int type, RsaKey* key, WC_RNG* rng)
-{
-    int ret = 0;
-
-    if (key == NULL || in == NULL || inLen == 0 || out == NULL ||
-            outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLF_CRYPTO_DEV
-    if (key->devId != INVALID_DEVID) {
-        ret = wc_CryptoDev_Rsa(in, inLen, out, outLen, type, key, rng);
-        if (ret != NOT_COMPILED_IN)
-            return ret;
-        ret = 0; /* reset error code and try using software */
-    }
-#endif
-
-#ifndef NO_RSA_BOUNDS_CHECK
-    if (type == RSA_PRIVATE_DECRYPT &&
-        key->state == RSA_STATE_DECRYPT_EXPTMOD) {
-
-        /* Check that 1 < in < n-1. (Requirement of 800-56B.) */
-#ifdef WOLFSSL_SMALL_STACK
-        mp_int* c = NULL;
-#else
-        mp_int c[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-        c = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA);
-        if (c == NULL)
-            ret = MEMORY_E;
-#endif
-
-        if (mp_init(c) != MP_OKAY)
-            ret = MEMORY_E;
-        if (ret == 0) {
-            if (mp_read_unsigned_bin(c, in, inLen) != 0)
-                ret = MP_READ_E;
-        }
-        if (ret == 0) {
-            /* check c > 1 */
-            if (mp_cmp_d(c, 1) != MP_GT)
-                ret = RSA_OUT_OF_RANGE_E;
-        }
-        if (ret == 0) {
-            /* add c+1 */
-            if (mp_add_d(c, 1, c) != MP_OKAY)
-                ret = MP_ADD_E;
-        }
-        if (ret == 0) {
-            /* check c+1 < n */
-            if (mp_cmp(c, &key->n) != MP_LT)
-                ret = RSA_OUT_OF_RANGE_E;
-        }
-        mp_clear(c);
-
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(c, key->heap, DYNAMIC_TYPE_RSA);
-#endif
-
-        if (ret != 0)
-            return ret;
-    }
-#endif /* NO_RSA_BOUNDS_CHECK */
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
-                                                        key->n.raw.len > 0) {
-        ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng);
-    }
-    else
-#endif
-    {
-        ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng);
-    }
-
-    /* handle error */
-    if (ret < 0 && ret != WC_PENDING_E) {
-        if (ret == MP_EXPTMOD_E) {
-            /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */
-            WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem");
-        }
-
-        key->state = RSA_STATE_NONE;
-        wc_RsaCleanup(key);
-    }
-
-    return ret;
-}
-
-
-/* Internal Wrappers */
-/* Gives the option of choosing padding type
-   in : input to be encrypted
-   inLen: length of input buffer
-   out: encrypted output
-   outLen: length of encrypted output buffer
-   key   : wolfSSL initialized RSA key struct
-   rng   : wolfSSL initialized random number struct
-   rsa_type  : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
-        RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
-   pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
-   pad_type  : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
-        WC_RSA_NO_PAD or WC_RSA_PSS_PAD
-   hash  : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
-   mgf   : type of mask generation function to use
-   label : optional label
-   labelSz : size of optional label buffer
-   saltLen : Length of salt used in PSS
-   rng : random number generator */
-static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
-                            word32 outLen, RsaKey* key, int rsa_type,
-                            byte pad_value, int pad_type,
-                            enum wc_HashType hash, int mgf,
-                            byte* label, word32 labelSz, int saltLen,
-                            WC_RNG* rng)
-{
-    int ret, sz;
-
-    if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    sz = wc_RsaEncryptSize(key);
-    if (sz > (int)outLen) {
-        return RSA_BUFFER_E;
-    }
-
-    if (sz < RSA_MIN_PAD_SZ) {
-        return WC_KEY_SIZE_E;
-    }
-
-    if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) {
-#ifdef WC_RSA_NO_PADDING
-        /* In the case that no padding is used the input length can and should
-         * be the same size as the RSA key. */
-        if (pad_type != WC_RSA_NO_PAD)
-#endif
-        return RSA_BUFFER_E;
-    }
-
-    switch (key->state) {
-    case RSA_STATE_NONE:
-    case RSA_STATE_ENCRYPT_PAD:
-        key->state = RSA_STATE_ENCRYPT_PAD;
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
-            defined(HAVE_CAVIUM)
-        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
-                                 pad_type != WC_RSA_PSS_PAD && key->n.raw.buf) {
-            /* Async operations that include padding */
-            if (rsa_type == RSA_PUBLIC_ENCRYPT &&
-                                                pad_value == RSA_BLOCK_TYPE_2) {
-                key->state = RSA_STATE_ENCRYPT_RES;
-                key->dataLen = key->n.raw.len;
-                return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key);
-            }
-            else if (rsa_type == RSA_PRIVATE_ENCRYPT &&
-                                                pad_value == RSA_BLOCK_TYPE_1) {
-                key->state = RSA_STATE_ENCRYPT_RES;
-                key->dataLen = key->n.raw.len;
-                return NitroxRsaSSL_Sign(in, inLen, out, outLen, key);
-            }
-        }
-    #endif
-
-        ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash,
-                           mgf, label, labelSz, saltLen, mp_count_bits(&key->n),
-                           key->heap);
-        if (ret < 0) {
-            break;
-        }
-
-        key->state = RSA_STATE_ENCRYPT_EXPTMOD;
-
-        FALL_THROUGH;
-
-    case RSA_STATE_ENCRYPT_EXPTMOD:
-
-        key->dataLen = outLen;
-        ret = wc_RsaFunction(out, sz, out, &key->dataLen, rsa_type, key, rng);
-
-        if (ret >= 0 || ret == WC_PENDING_E) {
-            key->state = RSA_STATE_ENCRYPT_RES;
-        }
-        if (ret < 0) {
-            break;
-        }
-
-        FALL_THROUGH;
-
-    case RSA_STATE_ENCRYPT_RES:
-        ret = key->dataLen;
-        break;
-
-    default:
-        ret = BAD_STATE_E;
-        break;
-    }
-
-    /* if async pending then return and skip done cleanup below */
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-
-    key->state = RSA_STATE_NONE;
-    wc_RsaCleanup(key);
-
-    return ret;
-}
-
-/* Gives the option of choosing padding type
-   in : input to be decrypted
-   inLen: length of input buffer
-   out:  decrypted message
-   outLen: length of decrypted message in bytes
-   outPtr: optional inline output pointer (if provided doing inline)
-   key   : wolfSSL initialized RSA key struct
-   rsa_type  : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
-        RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
-   pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
-   pad_type  : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
-        WC_RSA_NO_PAD, WC_RSA_PSS_PAD
-   hash  : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
-   mgf   : type of mask generation function to use
-   label : optional label
-   labelSz : size of optional label buffer
-   saltLen : Length of salt used in PSS
-   rng : random number generator */
-static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out,
-                            word32 outLen, byte** outPtr, RsaKey* key,
-                            int rsa_type, byte pad_value, int pad_type,
-                            enum wc_HashType hash, int mgf,
-                            byte* label, word32 labelSz, int saltLen,
-                            WC_RNG* rng)
-{
-    int ret = RSA_WRONG_TYPE_E;
-
-    if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    switch (key->state) {
-    case RSA_STATE_NONE:
-    case RSA_STATE_DECRYPT_EXPTMOD:
-        key->state = RSA_STATE_DECRYPT_EXPTMOD;
-        key->dataLen = inLen;
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
-            defined(HAVE_CAVIUM)
-        /* Async operations that include padding */
-        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
-                                                   pad_type != WC_RSA_PSS_PAD) {
-            if (rsa_type == RSA_PRIVATE_DECRYPT &&
-                                                pad_value == RSA_BLOCK_TYPE_2) {
-                key->state = RSA_STATE_DECRYPT_RES;
-                key->data = NULL;
-                return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen,
-                                               key);
-            }
-            else if (rsa_type == RSA_PUBLIC_DECRYPT &&
-                                                pad_value == RSA_BLOCK_TYPE_1) {
-                key->state = RSA_STATE_DECRYPT_RES;
-                key->data = NULL;
-                return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, key);
-            }
-        }
-    #endif
-
-        /* verify the tmp ptr is NULL, otherwise indicates bad state */
-        if (key->data != NULL) {
-            ret = BAD_STATE_E;
-            break;
-        }
-
-        /* if not doing this inline then allocate a buffer for it */
-        if (outPtr == NULL) {
-            key->data = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_WOLF_BIGINT);
-            key->dataIsAlloc = 1;
-            if (key->data == NULL) {
-                ret = MEMORY_E;
-                break;
-            }
-            XMEMCPY(key->data, in, inLen);
-        }
-        else {
-            key->data = out;
-        }
-        ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, rsa_type,
-                                                                      key, rng);
-
-        if (ret >= 0 || ret == WC_PENDING_E) {
-            key->state = RSA_STATE_DECRYPT_UNPAD;
-        }
-        if (ret < 0) {
-            break;
-        }
-
-        FALL_THROUGH;
-
-    case RSA_STATE_DECRYPT_UNPAD:
-    {
-        byte* pad = NULL;
-        ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type,
-                             hash, mgf, label, labelSz, saltLen,
-                             mp_count_bits(&key->n), key->heap);
-        if (ret > 0 && ret <= (int)outLen && pad != NULL) {
-            /* only copy output if not inline */
-            if (outPtr == NULL) {
-                XMEMCPY(out, pad, ret);
-            }
-            else {
-                *outPtr = pad;
-            }
-        }
-        else if (ret >= 0) {
-            ret = RSA_BUFFER_E;
-        }
-        if (ret < 0) {
-            break;
-        }
-
-        key->state = RSA_STATE_DECRYPT_RES;
-
-        FALL_THROUGH;
-    }
-    case RSA_STATE_DECRYPT_RES:
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \
-            defined(HAVE_CAVIUM)
-        if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
-                                                   pad_type != WC_RSA_PSS_PAD) {
-            /* convert result */
-            byte* dataLen = (byte*)&key->dataLen;
-            ret = (dataLen[0] << 8) | (dataLen[1]);
-
-            if (outPtr)
-                *outPtr = in;
-        }
-    #endif
-        break;
-
-    default:
-        ret = BAD_STATE_E;
-        break;
-    }
-
-    /* if async pending then return and skip done cleanup below */
-    if (ret == WC_PENDING_E) {
-        return ret;
-    }
-
-    key->state = RSA_STATE_NONE;
-    wc_RsaCleanup(key);
-
-    return ret;
-}
-
-
-/* Public RSA Functions */
-int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
-                                                     RsaKey* key, WC_RNG* rng)
-{
-    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
-        RSA_PUBLIC_ENCRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-
-#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
-int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
-                    word32 outLen, RsaKey* key, WC_RNG* rng, int type,
-                    enum wc_HashType hash, int mgf, byte* label,
-                    word32 labelSz)
-{
-    return RsaPublicEncryptEx(in, inLen, out, outLen, key, RSA_PUBLIC_ENCRYPT,
-        RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, 0, rng);
-}
-#endif /* WC_NO_RSA_OAEP */
-
-
-int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
-        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-
-#ifndef WC_NO_RSA_OAEP
-int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out,
-                                  RsaKey* key, int type, enum wc_HashType hash,
-                                  int mgf, byte* label, word32 labelSz)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
-        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash,
-        mgf, label, labelSz, 0, rng);
-}
-#endif /* WC_NO_RSA_OAEP */
-
-
-int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
-                                                 word32 outLen, RsaKey* key)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
-        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
-int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
-                            word32 outLen, RsaKey* key, int type,
-                            enum wc_HashType hash, int mgf, byte* label,
-                            word32 labelSz)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
-        RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label,
-        labelSz, 0, rng);
-}
-#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */
-
-
-int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
-        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
-                                                                 RsaKey* key)
-{
-    WC_RNG* rng;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key,
-        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-#ifdef WC_RSA_PSS
-/* Verify the message signed with RSA-PSS.
- * The input buffer is reused for the ouput buffer.
- * Salt length is equal to hash length.
- *
- * in     Buffer holding encrypted data.
- * inLen  Length of data in buffer.
- * out    Pointer to address containing the PSS data.
- * hash   Hash algorithm.
- * mgf    Mask generation function.
- * key    Public RSA key.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
-                           enum wc_HashType hash, int mgf, RsaKey* key)
-{
-    return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, -1, key);
-}
-
-/* Verify the message signed with RSA-PSS.
- * The input buffer is reused for the ouput buffer.
- *
- * in       Buffer holding encrypted data.
- * inLen    Length of data in buffer.
- * out      Pointer to address containing the PSS data.
- * hash     Hash algorithm.
- * mgf      Mask generation function.
- * key      Public RSA key.
- * saltLen  Length of salt used. -1 indicates salt length is the same as the
- *          hash length.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out,
-                              enum wc_HashType hash, int mgf, int saltLen,
-                              RsaKey* key)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key,
-        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
-        hash, mgf, NULL, 0, saltLen, rng);
-}
-
-/* Verify the message signed with RSA-PSS.
- * Salt length is equal to hash length.
- *
- * in     Buffer holding encrypted data.
- * inLen  Length of data in buffer.
- * out    Pointer to address containing the PSS data.
- * hash   Hash algorithm.
- * mgf    Mask generation function.
- * key    Public RSA key.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, word32 outLen,
-                     enum wc_HashType hash, int mgf, RsaKey* key)
-{
-    return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf, -1, key);
-}
-
-/* Verify the message signed with RSA-PSS.
- *
- * in       Buffer holding encrypted data.
- * inLen    Length of data in buffer.
- * out      Pointer to address containing the PSS data.
- * hash     Hash algorithm.
- * mgf      Mask generation function.
- * key      Public RSA key.
- * saltLen  Length of salt used. -1 indicates salt length is the same as the
- *          hash length.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, word32 outLen,
-                        enum wc_HashType hash, int mgf, int saltLen,
-                        RsaKey* key)
-{
-    WC_RNG* rng = NULL;
-#ifdef WC_RSA_BLINDING
-    rng = key->rng;
-#endif
-    return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key,
-        RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
-        hash, mgf, NULL, 0, saltLen, rng);
-}
-
-
-/* Checks the PSS data to ensure that the signature matches.
- * Salt length is equal to hash length.
- *
- * in        Hash of the data that is being verified.
- * inSz      Length of hash.
- * sig       Buffer holding PSS data.
- * sigSz     Size of PSS data.
- * hashType  Hash algorithm.
- * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when
- * NULL is passed in to in or sig or inSz is not the same as the hash
- * algorithm length and 0 on success.
- */
-int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig,
-                           word32 sigSz, enum wc_HashType hashType)
-{
-    return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, inSz, 0);
-}
-
-/* Checks the PSS data to ensure that the signature matches.
- *
- * in        Hash of the data that is being verified.
- * inSz      Length of hash.
- * sig       Buffer holding PSS data.
- * sigSz     Size of PSS data.
- * hashType  Hash algorithm.
- * saltLen   Length of salt used. -1 indicates salt length is the same as the
- *           hash length.
- * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when
- * NULL is passed in to in or sig or inSz is not the same as the hash
- * algorithm length and 0 on success.
- */
-int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, byte* sig,
-                              word32 sigSz, enum wc_HashType hashType,
-                              int saltLen, int bits)
-{
-    int ret = 0;
-    byte sigCheck[WC_MAX_DIGEST_SIZE*2 + RSA_PSS_PAD_SZ];
-
-    (void)bits;
-
-    if (in == NULL || sig == NULL ||
-                      inSz != (word32)wc_HashGetDigestSize(hashType))
-        ret = BAD_FUNC_ARG;
-
-    if (ret == 0) {
-        if (saltLen == -1) {
-            saltLen = inSz;
-            #ifdef WOLFSSL_SHA512
-                /* See FIPS 186-4 section 5.5 item (e). */
-                if (bits == 1024 && inSz == WC_SHA512_DIGEST_SIZE)
-                    saltLen = RSA_PSS_SALT_MAX_SZ;
-            #endif
-        }
-        else if (saltLen < -1 || (word32)saltLen > inSz)
-            ret = PSS_SALTLEN_E;
-    }
-
-    /* Sig = Salt | Exp Hash */
-    if (ret == 0) {
-        if (sigSz != inSz + saltLen)
-            ret = BAD_PADDING_E;
-    }
-
-    /* Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) */
-    if (ret == 0) {
-        XMEMSET(sigCheck, 0, RSA_PSS_PAD_SZ);
-        XMEMCPY(sigCheck + RSA_PSS_PAD_SZ, in, inSz);
-        XMEMCPY(sigCheck + RSA_PSS_PAD_SZ + inSz, sig, saltLen);
-        ret = wc_Hash(hashType, sigCheck, RSA_PSS_PAD_SZ + inSz + saltLen,
-                      sigCheck, inSz);
-    }
-    if (ret == 0) {
-        if (XMEMCMP(sigCheck, sig + saltLen, inSz) != 0) {
-            WOLFSSL_MSG("RsaPSS_CheckPadding: Padding Error");
-            ret = BAD_PADDING_E;
-        }
-    }
-
-    return ret;
-}
-
-
-/* Verify the message signed with RSA-PSS.
- * The input buffer is reused for the ouput buffer.
- * Salt length is equal to hash length.
- *
- * in     Buffer holding encrypted data.
- * inLen  Length of data in buffer.
- * out    Pointer to address containing the PSS data.
- * digest Hash of the data that is being verified.
- * digestLen Length of hash.
- * hash   Hash algorithm.
- * mgf    Mask generation function.
- * key    Public RSA key.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
-                           const byte* digest, word32 digestLen,
-                           enum wc_HashType hash, int mgf, RsaKey* key)
-{
-    int ret = 0, verify, saltLen, hLen, bits = 0;
-
-    hLen = wc_HashGetDigestSize(hash);
-    if (hLen < 0)
-        return hLen;
-    if ((word32)hLen != digestLen)
-        return BAD_FUNC_ARG;
-
-    saltLen = hLen;
-    #ifdef WOLFSSL_SHA512
-        /* See FIPS 186-4 section 5.5 item (e). */
-        bits = mp_count_bits(&key->n);
-        if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
-            saltLen = RSA_PSS_SALT_MAX_SZ;
-    #endif
-
-    verify = wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, saltLen, key);
-    if (verify > 0)
-        ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, *out, verify,
-                                        hash, saltLen, bits);
-    if (ret == 0)
-        ret = verify;
-
-    return ret;
-}
-
-
-/* Verify the message signed with RSA-PSS.
- * Salt length is equal to hash length.
- *
- * in     Buffer holding encrypted data.
- * inLen  Length of data in buffer.
- * out    Pointer to address containing the PSS data.
- * outLen Length of the output.
- * digest Hash of the data that is being verified.
- * digestLen Length of hash.
- * hash   Hash algorithm.
- * mgf    Mask generation function.
- * key    Public RSA key.
- * returns the length of the PSS data on success and negative indicates failure.
- */
-int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, byte* out, word32 outLen,
-                          const byte* digest, word32 digestLen,
-                          enum wc_HashType hash, int mgf,
-                          RsaKey* key)
-{
-    int ret = 0, verify, saltLen, hLen, bits = 0;
-
-    hLen = wc_HashGetDigestSize(hash);
-    if (hLen < 0)
-        return hLen;
-    if ((word32)hLen != digestLen)
-        return BAD_FUNC_ARG;
-
-    saltLen = hLen;
-    #ifdef WOLFSSL_SHA512
-        /* See FIPS 186-4 section 5.5 item (e). */
-        bits = mp_count_bits(&key->n);
-        if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE)
-            saltLen = RSA_PSS_SALT_MAX_SZ;
-    #endif
-
-    verify = wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash,
-                                 mgf, saltLen, key);
-    if (verify > 0)
-        ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, out, verify,
-                                        hash, saltLen, bits);
-    if (ret == 0)
-        ret = verify;
-
-    return ret;
-}
-
-#endif
-
-int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
-                                                   RsaKey* key, WC_RNG* rng)
-{
-    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
-        RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD,
-        WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
-}
-
-#ifdef WC_RSA_PSS
-/* Sign the hash of a message using RSA-PSS.
- * Salt length is equal to hash length.
- *
- * in      Buffer holding hash of message.
- * inLen   Length of data in buffer (hash length).
- * out     Buffer to write encrypted signature into.
- * outLen  Size of buffer to write to.
- * hash    Hash algorithm.
- * mgf     Mask generation function.
- * key     Public RSA key.
- * rng     Random number generator.
- * returns the length of the encrypted signature on success, a negative value
- * indicates failure.
- */
-int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
-                       enum wc_HashType hash, int mgf, RsaKey* key, WC_RNG* rng)
-{
-    return wc_RsaPSS_Sign_ex(in, inLen, out, outLen, hash, mgf, -1, key, rng);
-}
-
-/* Sign the hash of a message using RSA-PSS.
- *
- * in       Buffer holding hash of message.
- * inLen    Length of data in buffer (hash length).
- * out      Buffer to write encrypted signature into.
- * outLen   Size of buffer to write to.
- * hash     Hash algorithm.
- * mgf      Mask generation function.
- * saltLen  Length of salt used. -1 indicates salt length is the same as the
- *          hash length.
- * key      Public RSA key.
- * rng      Random number generator.
- * returns the length of the encrypted signature on success, a negative value
- * indicates failure.
- */
-int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen,
-                      enum wc_HashType hash, int mgf, int saltLen, RsaKey* key,
-                      WC_RNG* rng)
-{
-    return RsaPublicEncryptEx(in, inLen, out, outLen, key,
-        RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD,
-        hash, mgf, NULL, 0, saltLen, rng);
-}
-#endif
-
-int wc_RsaEncryptSize(RsaKey* key)
-{
-    int ret;
-
-    if (key == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    ret =  mp_unsigned_bin_size(&key->n);
-
-#ifdef WOLF_CRYPTO_DEV
-    if (ret == 0 && key->devId != INVALID_DEVID) {
-        ret = 2048/8; /* hardware handles, use 2048-bit as default */
-    }
-#endif
-
-    return ret;
-}
-
-
-/* flatten RsaKey structure into individual elements (e, n) */
-int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n,
-                                                                   word32* nSz)
-{
-    int sz, ret;
-
-    if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    sz = mp_unsigned_bin_size(&key->e);
-    if ((word32)sz > *eSz)
-        return RSA_BUFFER_E;
-    ret = mp_to_unsigned_bin(&key->e, e);
-    if (ret != MP_OKAY)
-        return ret;
-    *eSz = (word32)sz;
-
-    sz = wc_RsaEncryptSize(key);
-    if ((word32)sz > *nSz)
-        return RSA_BUFFER_E;
-    ret = mp_to_unsigned_bin(&key->n, n);
-    if (ret != MP_OKAY)
-        return ret;
-    *nSz = (word32)sz;
-
-    return 0;
-}
-
-
-static int RsaGetValue(mp_int* in, byte* out, word32* outSz)
-{
-    word32 sz;
-    int ret = 0;
-
-    /* Parameters ensured by calling function. */
-
-    sz = (word32)mp_unsigned_bin_size(in);
-    if (sz > *outSz)
-        ret = RSA_BUFFER_E;
-
-    if (ret == 0)
-        ret = mp_to_unsigned_bin(in, out);
-
-    if (ret == MP_OKAY)
-        *outSz = sz;
-
-    return ret;
-}
-
-
-int wc_RsaExportKey(RsaKey* key,
-                    byte* e, word32* eSz, byte* n, word32* nSz,
-                    byte* d, word32* dSz, byte* p, word32* pSz,
-                    byte* q, word32* qSz)
-{
-    int ret = BAD_FUNC_ARG;
-
-    if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz)
-        ret = 0;
-
-    if (ret == 0)
-        ret = RsaGetValue(&key->e, e, eSz);
-    if (ret == 0)
-        ret = RsaGetValue(&key->n, n, nSz);
-    if (ret == 0)
-        ret = RsaGetValue(&key->d, d, dSz);
-    if (ret == 0)
-        ret = RsaGetValue(&key->p, p, pSz);
-    if (ret == 0)
-        ret = RsaGetValue(&key->q, q, qSz);
-
-    return ret;
-}
-
-
-#ifdef WOLFSSL_KEY_GEN
-
-/* Check that |p-q| > 2^((size/2)-100) */
-static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size)
-{
-    mp_int c, d;
-    int ret;
-
-    if (p == NULL || q == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = mp_init_multi(&c, &d, NULL, NULL, NULL, NULL);
-
-    /* c = 2^((size/2)-100) */
-    if (ret == 0)
-        ret = mp_2expt(&c, (size/2)-100);
-
-    /* d = |p-q| */
-    if (ret == 0)
-        ret = mp_sub(p, q, &d);
-
-    if (ret == 0)
-        ret = mp_abs(&d, &d);
-
-    /* compare */
-    if (ret == 0)
-        ret = mp_cmp(&d, &c);
-
-    if (ret == MP_GT)
-        ret = MP_OKAY;
-
-    mp_clear(&d);
-    mp_clear(&c);
-
-    return ret;
-}
-
-
-/* The lower_bound value is floor(2^(0.5) * 2^((nlen/2)-1)) where nlen is 4096.
- * This number was calculated using a small test tool written with a common
- * large number math library. Other values of nlen may be checked with a subset
- * of lower_bound. */
-static const byte lower_bound[] = {
-    0xB5, 0x04, 0xF3, 0x33, 0xF9, 0xDE, 0x64, 0x84,
-    0x59, 0x7D, 0x89, 0xB3, 0x75, 0x4A, 0xBE, 0x9F,
-    0x1D, 0x6F, 0x60, 0xBA, 0x89, 0x3B, 0xA8, 0x4C,
-    0xED, 0x17, 0xAC, 0x85, 0x83, 0x33, 0x99, 0x15,
-/* 512 */
-    0x4A, 0xFC, 0x83, 0x04, 0x3A, 0xB8, 0xA2, 0xC3,
-    0xA8, 0xB1, 0xFE, 0x6F, 0xDC, 0x83, 0xDB, 0x39,
-    0x0F, 0x74, 0xA8, 0x5E, 0x43, 0x9C, 0x7B, 0x4A,
-    0x78, 0x04, 0x87, 0x36, 0x3D, 0xFA, 0x27, 0x68,
-/* 1024 */
-    0xD2, 0x20, 0x2E, 0x87, 0x42, 0xAF, 0x1F, 0x4E,
-    0x53, 0x05, 0x9C, 0x60, 0x11, 0xBC, 0x33, 0x7B,
-    0xCA, 0xB1, 0xBC, 0x91, 0x16, 0x88, 0x45, 0x8A,
-    0x46, 0x0A, 0xBC, 0x72, 0x2F, 0x7C, 0x4E, 0x33,
-    0xC6, 0xD5, 0xA8, 0xA3, 0x8B, 0xB7, 0xE9, 0xDC,
-    0xCB, 0x2A, 0x63, 0x43, 0x31, 0xF3, 0xC8, 0x4D,
-    0xF5, 0x2F, 0x12, 0x0F, 0x83, 0x6E, 0x58, 0x2E,
-    0xEA, 0xA4, 0xA0, 0x89, 0x90, 0x40, 0xCA, 0x4A,
-/* 2048 */
-    0x81, 0x39, 0x4A, 0xB6, 0xD8, 0xFD, 0x0E, 0xFD,
-    0xF4, 0xD3, 0xA0, 0x2C, 0xEB, 0xC9, 0x3E, 0x0C,
-    0x42, 0x64, 0xDA, 0xBC, 0xD5, 0x28, 0xB6, 0x51,
-    0xB8, 0xCF, 0x34, 0x1B, 0x6F, 0x82, 0x36, 0xC7,
-    0x01, 0x04, 0xDC, 0x01, 0xFE, 0x32, 0x35, 0x2F,
-    0x33, 0x2A, 0x5E, 0x9F, 0x7B, 0xDA, 0x1E, 0xBF,
-    0xF6, 0xA1, 0xBE, 0x3F, 0xCA, 0x22, 0x13, 0x07,
-    0xDE, 0xA0, 0x62, 0x41, 0xF7, 0xAA, 0x81, 0xC2,
-/* 3072 */
-    0xC1, 0xFC, 0xBD, 0xDE, 0xA2, 0xF7, 0xDC, 0x33,
-    0x18, 0x83, 0x8A, 0x2E, 0xAF, 0xF5, 0xF3, 0xB2,
-    0xD2, 0x4F, 0x4A, 0x76, 0x3F, 0xAC, 0xB8, 0x82,
-    0xFD, 0xFE, 0x17, 0x0F, 0xD3, 0xB1, 0xF7, 0x80,
-    0xF9, 0xAC, 0xCE, 0x41, 0x79, 0x7F, 0x28, 0x05,
-    0xC2, 0x46, 0x78, 0x5E, 0x92, 0x95, 0x70, 0x23,
-    0x5F, 0xCF, 0x8F, 0x7B, 0xCA, 0x3E, 0xA3, 0x3B,
-    0x4D, 0x7C, 0x60, 0xA5, 0xE6, 0x33, 0xE3, 0xE1
-/* 4096 */
-};
-
-
-/* returns 1 on key size ok and 0 if not ok */
-static WC_INLINE int RsaSizeCheck(int size)
-{
-    if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) {
-        return 0;
-    }
-
-#ifdef HAVE_FIPS
-    /* Key size requirements for CAVP */
-    switch (size) {
-        case 1024:
-        case 2048:
-        case 3072:
-        case 4096:
-            return 1;
-    }
-
-    return 0;
-#else
-    return 1; /* allow unusual key sizes in non FIPS mode */
-#endif /* HAVE_FIPS */
-}
-
-
-static int wc_CheckProbablePrime_ex(mp_int* p, mp_int* q, mp_int* e, int nlen,
-                                    int* isPrime)
-{
-    int ret;
-    mp_int tmp1, tmp2;
-    mp_int* prime;
-
-    if (p == NULL || e == NULL || isPrime == NULL)
-        return BAD_FUNC_ARG;
-
-    if (!RsaSizeCheck(nlen))
-        return BAD_FUNC_ARG;
-
-    *isPrime = MP_NO;
-
-    if (q != NULL) {
-        /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */
-        ret = wc_CompareDiffPQ(p, q, nlen);
-        if (ret != MP_OKAY) goto notOkay;
-        prime = q;
-    }
-    else
-        prime = p;
-
-    ret = mp_init_multi(&tmp1, &tmp2, NULL, NULL, NULL, NULL);
-    if (ret != MP_OKAY) goto notOkay;
-
-    /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1))
-     *           This is a comparison against lowerBound */
-    ret = mp_read_unsigned_bin(&tmp1, lower_bound, nlen/16);
-    if (ret != MP_OKAY) goto notOkay;
-    ret = mp_cmp(prime, &tmp1);
-    if (ret == MP_LT) goto exit;
-
-    /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */
-    ret = mp_sub_d(prime, 1, &tmp1);  /* tmp1 = prime-1 */
-    if (ret != MP_OKAY) goto notOkay;
-    ret = mp_gcd(&tmp1, e, &tmp2);  /* tmp2 = gcd(prime-1, e) */
-    if (ret != MP_OKAY) goto notOkay;
-    ret = mp_cmp_d(&tmp2, 1);
-    if (ret != MP_EQ) goto exit; /* e divides p-1 */
-
-    /* 4.5.1,5.6.1 - Check primality of p with 8 iterations */
-    ret = mp_prime_is_prime(prime, 8, isPrime);
-        /* Performs some divides by a table of primes, and then does M-R,
-         * it sets isPrime as a side-effect. */
-    if (ret != MP_OKAY) goto notOkay;
-
-exit:
-    ret = MP_OKAY;
-notOkay:
-    mp_clear(&tmp1);
-    mp_clear(&tmp2);
-    return ret;
-}
-
-
-
-int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz,
-                          const byte* qRaw, word32 qRawSz,
-                          const byte* eRaw, word32 eRawSz,
-                          int nlen, int* isPrime)
-{
-    mp_int p, q, e;
-    mp_int* Q = NULL;
-    int ret;
-
-    if (pRaw == NULL || pRawSz == 0 ||
-        eRaw == NULL || eRawSz == 0 ||
-        isPrime == NULL) {
-
-        return BAD_FUNC_ARG;
-    }
-
-    if ((qRaw != NULL && qRawSz == 0) || (qRaw == NULL && qRawSz != 0))
-        return BAD_FUNC_ARG;
-
-    ret = mp_init_multi(&p, &q, &e, NULL, NULL, NULL);
-
-    if (ret == MP_OKAY)
-        ret = mp_read_unsigned_bin(&p, pRaw, pRawSz);
-
-    if (ret == MP_OKAY) {
-        if (qRaw != NULL) {
-            ret = mp_read_unsigned_bin(&q, qRaw, qRawSz);
-            if (ret == MP_OKAY)
-                Q = &q;
-        }
-    }
-
-    if (ret == MP_OKAY)
-        ret = mp_read_unsigned_bin(&e, eRaw, eRawSz);
-
-    if (ret == MP_OKAY)
-        ret = wc_CheckProbablePrime_ex(&p, Q, &e, nlen, isPrime);
-
-    ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E;
-
-    mp_clear(&p);
-    mp_clear(&q);
-    mp_clear(&e);
-
-    return ret;
-}
-
-
-/* Make an RSA key for size bits, with e specified, 65537 is a good e */
-int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng)
-{
-    mp_int p, q, tmp1, tmp2, tmp3;
-    int err, i, failCount, primeSz, isPrime = 0;
-    byte* buf = NULL;
-
-    if (key == NULL || rng == NULL)
-        return BAD_FUNC_ARG;
-
-    if (!RsaSizeCheck(size))
-        return BAD_FUNC_ARG;
-
-    if (e < 3 || (e & 1) == 0)
-        return BAD_FUNC_ARG;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
-    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) {
-    #ifdef HAVE_CAVIUM
-        /* TODO: Not implemented */
-    #elif defined(HAVE_INTEL_QA)
-        /* TODO: Not implemented */
-    #else
-        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_MAKE)) {
-            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
-            testDev->rsaMake.rng = rng;
-            testDev->rsaMake.key = key;
-            testDev->rsaMake.size = size;
-            testDev->rsaMake.e = e;
-            return WC_PENDING_E;
-        }
-    #endif
-    }
-#endif
-
-    err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL);
-
-    if (err == MP_OKAY)
-        err = mp_set_int(&tmp3, e);
-
-    /* The failCount value comes from NIST FIPS 186-4, section B.3.3,
-     * process steps 4.7 and 5.8. */
-    failCount = 5 * (size / 2);
-    primeSz = size / 16; /* size is the size of n in bits.
-                            primeSz is in bytes. */
-
-    /* allocate buffer to work with */
-    if (err == MP_OKAY) {
-        buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA);
-        if (buf == NULL)
-            err = MEMORY_E;
-    }
-
-    /* make p */
-    if (err == MP_OKAY) {
-        isPrime = 0;
-        i = 0;
-        do {
-#ifdef SHOW_GEN
-            printf(".");
-            fflush(stdout);
-#endif
-            /* generate value */
-            err = wc_RNG_GenerateBlock(rng, buf, primeSz);
-
-            if (err == 0) {
-                /* prime lower bound has the MSB set, set it in candidate */
-                buf[0] |= 0x80;
-                /* make candidate odd */
-                buf[primeSz-1] |= 0x01;
-                /* load value */
-                err = mp_read_unsigned_bin(&p, buf, primeSz);
-            }
-
-            if (err == MP_OKAY)
-                err = wc_CheckProbablePrime_ex(&p, NULL, &tmp3, size, &isPrime);
-
-#ifdef WOLFSSL_FIPS
-            i++;
-#else
-            /* Keep the old retry behavior in non-FIPS build. */
-            (void)i;
-#endif
-        } while (err == MP_OKAY && !isPrime && i < failCount);
-    }
-
-    if (err == MP_OKAY && !isPrime)
-        err = PRIME_GEN_E;
-
-    /* make q */
-    if (err == MP_OKAY) {
-        isPrime = 0;
-        i = 0;
-        do {
-#ifdef SHOW_GEN
-            printf(".");
-            fflush(stdout);
-#endif
-            /* generate value */
-            err = wc_RNG_GenerateBlock(rng, buf, primeSz);
-
-            if (err == 0) {
-                /* prime lower bound has the MSB set, set it in candidate */
-                buf[0] |= 0x80;
-                /* make candidate odd */
-                buf[primeSz-1] |= 0x01;
-                /* load value */
-                err = mp_read_unsigned_bin(&q, buf, primeSz);
-            }
-
-            if (err == MP_OKAY)
-                err = wc_CheckProbablePrime_ex(&p, &q, &tmp3, size, &isPrime);
-
-#ifdef WOLFSSL_FIPS
-            i++;
-#else
-            /* Keep the old retry behavior in non-FIPS build. */
-            (void)i;
-#endif
-        } while (err == MP_OKAY && !isPrime && i < failCount);
-    }
-
-    if (err == MP_OKAY && !isPrime)
-        err = PRIME_GEN_E;
-
-    if (buf) {
-        ForceZero(buf, primeSz);
-        XFREE(buf, key->heap, DYNAMIC_TYPE_RSA);
-    }
-
-    if (err == MP_OKAY)
-        err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
-
-    if (err == MP_OKAY)
-        err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL);
-
-    if (err == MP_OKAY)
-        err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
-
-    if (err == MP_OKAY)
-        err = mp_sub_d(&q, 1, &tmp2);  /* tmp2 = q-1 */
-
-    if (err == MP_OKAY)
-        err = mp_lcm(&tmp1, &tmp2, &tmp3);  /* tmp3 = lcm(p-1, q-1),last loop */
-
-    /* make key */
-    if (err == MP_OKAY)
-        err = mp_set_int(&key->e, (mp_digit)e);  /* key->e = e */
-
-    if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
-        err = mp_invmod(&key->e, &tmp3, &key->d);
-
-    if (err == MP_OKAY)
-        err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
-
-    if (err == MP_OKAY)
-        err = mp_mod(&key->d, &tmp1, &key->dP); /* key->dP = d mod(p-1) */
-
-    if (err == MP_OKAY)
-        err = mp_mod(&key->d, &tmp2, &key->dQ); /* key->dQ = d mod(q-1) */
-
-    if (err == MP_OKAY)
-        err = mp_invmod(&q, &p, &key->u); /* key->u = 1/q mod p */
-
-    if (err == MP_OKAY)
-        err = mp_copy(&p, &key->p);
-
-    if (err == MP_OKAY)
-        err = mp_copy(&q, &key->q);
-
-    if (err == MP_OKAY)
-        key->type = RSA_PRIVATE;
-
-    mp_clear(&tmp1);
-    mp_clear(&tmp2);
-    mp_clear(&tmp3);
-    mp_clear(&p);
-    mp_clear(&q);
-
-    /* Perform the pair-wise consistency test on the new key. */
-    if (err == 0)
-        err = wc_CheckRsaKey(key);
-
-    if (err != 0) {
-        wc_FreeRsaKey(key);
-        return err;
-    }
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    if (wc_InitRsaHw(key) != 0) {
-        return BAD_STATE_E;
-    }
-#endif
-
-    return 0;
-}
-#endif /* WOLFSSL_KEY_GEN */
-
-
-#ifdef WC_RSA_BLINDING
-
-int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng)
-{
-    if (key == NULL)
-        return BAD_FUNC_ARG;
-
-    key->rng = rng;
-
-    return 0;
-}
-
-#endif /* WC_RSA_BLINDING */
-
-
-#undef ERROR_OUT
-
-#endif /* HAVE_FIPS */
-#endif /* NO_RSA */
-
--- a/wolfcrypt/src/selftest.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfcrypt/src/sha.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,598 +0,0 @@
-/* sha.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if !defined(NO_SHA)
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$j")
-        #pragma const_seg(".fipsB$j")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/sha.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-/* fips wrapper calls, user can call direct */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    int wc_InitSha(wc_Sha* sha)
-    {
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return InitSha_fips(sha);
-    }
-    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
-    {
-        (void)heap;
-        (void)devId;
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return InitSha_fips(sha);
-    }
-
-    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
-    {
-        if (sha == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-        return ShaUpdate_fips(sha, data, len);
-    }
-
-    int wc_ShaFinal(wc_Sha* sha, byte* out)
-    {
-        if (sha == NULL || out == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return ShaFinal_fips(sha,out);
-    }
-    void wc_ShaFree(wc_Sha* sha)
-    {
-        (void)sha;
-        /* Not supported in FIPS */
-    }
-
-#else /* else build without fips, or for FIPS v2 */
-
-
-#if defined(WOLFSSL_TI_HASH)
-    /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
-
-#else
-
-#include <wolfssl/wolfcrypt/logging.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-/* Hardware Acceleration */
-#if defined(WOLFSSL_PIC32MZ_HASH)
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-
-#elif defined(STM32_HASH)
-
-    /* Supports CubeMX HAL or Standard Peripheral Library */
-    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
-    {
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        (void)devId;
-        (void)heap;
-
-        wc_Stm32_Hash_Init(&sha->stmCtx);
-
-        return 0;
-    }
-
-    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
-    {
-        int ret;
-
-        if (sha == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1,
-                data, len);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-    int wc_ShaFinal(wc_Sha* sha, byte* hash)
-    {
-        int ret;
-
-        if (sha == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Final(&sha->stmCtx, HASH_AlgoSelection_SHA1,
-                hash, WC_SHA_DIGEST_SIZE);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-
-        (void)wc_InitSha(sha);  /* reset state */
-
-        return ret;
-    }
-
-
-#elif defined(FREESCALE_LTC_SHA)
-
-    #include "fsl_ltc.h"
-    int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
-    {
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        (void)devId;
-        (void)heap;
-
-        LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0);
-        return 0;
-    }
-
-    int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
-    {
-        LTC_HASH_Update(&sha->ctx, data, len);
-        return 0;
-    }
-
-    int wc_ShaFinal(wc_Sha* sha, byte* hash)
-    {
-        uint32_t hashlen = WC_SHA_DIGEST_SIZE;
-        LTC_HASH_Finish(&sha->ctx, hash, &hashlen);
-        return wc_InitSha(sha);  /* reset state */
-    }
-
-
-#elif defined(FREESCALE_MMCAU_SHA)
-
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-        #include "cau_api.h"
-    #else
-        #include "fsl_mmcau.h"
-    #endif
-
-    #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */
-    #define XTRANSFORM(S,B)   Transform((S),(B))
-
-    static int InitSha(wc_Sha* sha)
-    {
-        int ret = 0;
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret != 0) {
-            return ret;
-        }
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-        cau_sha1_initialize_output(sha->digest);
-    #else
-        MMCAU_SHA1_InitializeOutput((uint32_t*)sha->digest);
-    #endif
-        wolfSSL_CryptHwMutexUnLock();
-
-        sha->buffLen = 0;
-        sha->loLen   = 0;
-        sha->hiLen   = 0;
-
-        return ret;
-    }
-
-    static int Transform(wc_Sha* sha, byte* data)
-    {
-        int ret = wolfSSL_CryptHwMutexLock();
-        if(ret == 0) {
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-            cau_sha1_hash_n(data, 1, sha->digest);
-    #else
-            MMCAU_SHA1_HashN(data, 1, (uint32_t*)sha->digest);
-    #endif
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* wolfcrypt/src/port/caam/caam_sha.c */
-#else
-
-    /* Software implementation */
-    #define USE_SHA_SOFTWARE_IMPL
-
-    static int InitSha(wc_Sha* sha)
-    {
-        int ret = 0;
-
-        sha->digest[0] = 0x67452301L;
-        sha->digest[1] = 0xEFCDAB89L;
-        sha->digest[2] = 0x98BADCFEL;
-        sha->digest[3] = 0x10325476L;
-        sha->digest[4] = 0xC3D2E1F0L;
-
-        sha->buffLen = 0;
-        sha->loLen   = 0;
-        sha->hiLen   = 0;
-
-        return ret;
-    }
-
-#endif /* End Hardware Acceleration */
-
-
-/* Software implementation */
-#ifdef USE_SHA_SOFTWARE_IMPL
-
-static WC_INLINE void AddLength(wc_Sha* sha, word32 len)
-{
-    word32 tmp = sha->loLen;
-    if ((sha->loLen += len) < tmp)
-        sha->hiLen++;                       /* carry low to high */
-}
-
-/* Check if custom wc_Sha transform is used */
-#ifndef XTRANSFORM
-    #define XTRANSFORM(S,B)   Transform((S),(B))
-
-    #define blk0(i) (W[i] = sha->buffer[i])
-    #define blk1(i) (W[(i)&15] = \
-        rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1))
-
-    #define f1(x,y,z) ((z)^((x) &((y)^(z))))
-    #define f2(x,y,z) ((x)^(y)^(z))
-    #define f3(x,y,z) (((x)&(y))|((z)&((x)|(y))))
-    #define f4(x,y,z) ((x)^(y)^(z))
-
-    #ifdef WOLFSSL_NUCLEUS_1_2
-        /* nucleus.h also defines R1-R4 */
-        #undef R1
-        #undef R2
-        #undef R3
-        #undef R4
-    #endif
-
-    /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-    #define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \
-        rotlFixed((v),5); (w) = rotlFixed((w),30);
-    #define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \
-        rotlFixed((v),5); (w) = rotlFixed((w),30);
-    #define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \
-        rotlFixed((v),5); (w) = rotlFixed((w),30);
-    #define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \
-        rotlFixed((v),5); (w) = rotlFixed((w),30);
-    #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \
-        rotlFixed((v),5); (w) = rotlFixed((w),30);
-
-    static void Transform(wc_Sha* sha, byte* data)
-    {
-        word32 W[WC_SHA_BLOCK_SIZE / sizeof(word32)];
-
-        /* Copy context->state[] to working vars */
-        word32 a = sha->digest[0];
-        word32 b = sha->digest[1];
-        word32 c = sha->digest[2];
-        word32 d = sha->digest[3];
-        word32 e = sha->digest[4];
-
-    #ifdef USE_SLOW_SHA
-        word32 t, i;
-
-        for (i = 0; i < 16; i++) {
-            R0(a, b, c, d, e, i);
-            t = e; e = d; d = c; c = b; b = a; a = t;
-        }
-
-        for (; i < 20; i++) {
-            R1(a, b, c, d, e, i);
-            t = e; e = d; d = c; c = b; b = a; a = t;
-        }
-
-        for (; i < 40; i++) {
-            R2(a, b, c, d, e, i);
-            t = e; e = d; d = c; c = b; b = a; a = t;
-        }
-
-        for (; i < 60; i++) {
-            R3(a, b, c, d, e, i);
-            t = e; e = d; d = c; c = b; b = a; a = t;
-        }
-
-        for (; i < 80; i++) {
-            R4(a, b, c, d, e, i);
-            t = e; e = d; d = c; c = b; b = a; a = t;
-        }
-    #else
-        /* nearly 1 K bigger in code size but 25% faster */
-        /* 4 rounds of 20 operations each. Loop unrolled. */
-        R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-        R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-        R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-        R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-
-        R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-
-        R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-        R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-        R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-        R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-        R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-
-        R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-        R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-        R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-        R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-        R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-
-        R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-        R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-        R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-        R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-        R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-    #endif
-
-        /* Add the working vars back into digest state[] */
-        sha->digest[0] += a;
-        sha->digest[1] += b;
-        sha->digest[2] += c;
-        sha->digest[3] += d;
-        sha->digest[4] += e;
-
-        (void)data; /* Not used */
-    }
-#endif /* !USE_CUSTOM_SHA_TRANSFORM */
-
-
-int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (sha == NULL)
-        return BAD_FUNC_ARG;
-
-    sha->heap = heap;
-
-    ret = InitSha(sha);
-    if (ret != 0)
-        return ret;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
-    ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA,
-                                                            sha->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
-{
-    byte* local;
-
-    if (sha == NULL ||(data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* do block size increments */
-    local = (byte*)sha->buffer;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
-    if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha(&sha->asyncDev, NULL, data, len);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    /* check that internal buffLen is valid */
-    if (sha->buffLen >= WC_SHA_BLOCK_SIZE)
-        return BUFFER_E;
-
-    while (len) {
-        word32 add = min(len, WC_SHA_BLOCK_SIZE - sha->buffLen);
-        XMEMCPY(&local[sha->buffLen], data, add);
-
-        sha->buffLen += add;
-        data         += add;
-        len          -= add;
-
-        if (sha->buffLen == WC_SHA_BLOCK_SIZE) {
-#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-            ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
-#endif
-            XTRANSFORM(sha, local);
-            AddLength(sha, WC_SHA_BLOCK_SIZE);
-            sha->buffLen = 0;
-        }
-    }
-
-    return 0;
-}
-
-int wc_ShaFinalRaw(wc_Sha* sha, byte* hash)
-{
-#ifdef LITTLE_ENDIAN_ORDER
-    word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)];
-#endif
-
-    if (sha == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef LITTLE_ENDIAN_ORDER
-    ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE);
-    XMEMCPY(hash, digest, WC_SHA_DIGEST_SIZE);
-#else
-    XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE);
-#endif
-
-    return 0;
-}
-
-int wc_ShaFinal(wc_Sha* sha, byte* hash)
-{
-    byte* local;
-
-    if (sha == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    local = (byte*)sha->buffer;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
-    if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha(&sha->asyncDev, hash, NULL, WC_SHA_DIGEST_SIZE);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    AddLength(sha, sha->buffLen);  /* before adding pads */
-
-    local[sha->buffLen++] = 0x80;  /* add 1 */
-
-    /* pad with zeros */
-    if (sha->buffLen > WC_SHA_PAD_SIZE) {
-        XMEMSET(&local[sha->buffLen], 0, WC_SHA_BLOCK_SIZE - sha->buffLen);
-        sha->buffLen += WC_SHA_BLOCK_SIZE - sha->buffLen;
-
-#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-        ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
-#endif
-        XTRANSFORM(sha, local);
-        sha->buffLen = 0;
-    }
-    XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen);
-
-#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-    ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
-#endif
-
-    /* store lengths */
-    /* put lengths in bits */
-    sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + (sha->hiLen << 3);
-    sha->loLen = sha->loLen << 3;
-
-    /* ! length ordering dependent on digest endian type ! */
-    XMEMCPY(&local[WC_SHA_PAD_SIZE], &sha->hiLen, sizeof(word32));
-    XMEMCPY(&local[WC_SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32));
-
-#if defined(FREESCALE_MMCAU_SHA)
-    /* Kinetis requires only these bytes reversed */
-    ByteReverseWords(&sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)],
-                     &sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)],
-                     2 * sizeof(word32));
-#endif
-
-    XTRANSFORM(sha, local);
-#ifdef LITTLE_ENDIAN_ORDER
-    ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE);
-#endif
-    XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE);
-
-    return InitSha(sha); /* reset state */
-}
-
-#endif /* USE_SHA_SOFTWARE_IMPL */
-
-
-int wc_InitSha(wc_Sha* sha)
-{
-    return wc_InitSha_ex(sha, NULL, INVALID_DEVID);
-}
-
-void wc_ShaFree(wc_Sha* sha)
-{
-    if (sha == NULL)
-        return;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
-    wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-#endif /* !WOLFSSL_TI_HASH */
-#endif /* HAVE_FIPS */
-
-#ifndef WOLFSSL_TI_HASH
-int wc_ShaGetHash(wc_Sha* sha, byte* hash)
-{
-    int ret;
-    wc_Sha tmpSha;
-
-    if (sha == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_ShaCopy(sha, &tmpSha);
-    if (ret == 0) {
-        ret = wc_ShaFinal(&tmpSha, hash);
-    }
-    return ret;
-}
-
-int wc_ShaCopy(wc_Sha* src, wc_Sha* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Sha));
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-#ifdef WOLFSSL_PIC32MZ_HASH
-    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
-#endif
-
-    return ret;
-}
-#endif /* !WOLFSSL_TI_HASH */
-
-#endif /* !NO_SHA */
-
--- a/wolfcrypt/src/sha256.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2816 +0,0 @@
-/* sha256.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* code submitted by raphael.huck@efixo.com */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if !defined(NO_SHA256) && !defined(WOLFSSL_ARMASM)
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$d")
-        #pragma const_seg(".fipsB$d")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/sha256.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-
-/* fips wrapper calls, user can call direct */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    int wc_InitSha256(wc_Sha256* sha)
-    {
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return InitSha256_fips(sha);
-    }
-    int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
-    {
-        (void)heap;
-        (void)devId;
-        if (sha == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return InitSha256_fips(sha);
-    }
-    int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len)
-    {
-        if (sha == NULL ||  (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (data == NULL && len == 0) {
-            /* valid, but do nothing */
-            return 0;
-        }
-
-        return Sha256Update_fips(sha, data, len);
-    }
-    int wc_Sha256Final(wc_Sha256* sha, byte* out)
-    {
-        if (sha == NULL || out == NULL) {
-            return BAD_FUNC_ARG;
-        }
-        return Sha256Final_fips(sha, out);
-    }
-    void wc_Sha256Free(wc_Sha256* sha)
-    {
-        (void)sha;
-        /* Not supported in FIPS */
-    }
-
-#else /* else build without fips, or for FIPS v2 */
-
-
-#if defined(WOLFSSL_TI_HASH)
-    /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
-#else
-
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#if defined(USE_INTEL_SPEEDUP)
-    #define HAVE_INTEL_AVX1
-
-    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
-                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
-        #define NO_AVX2_SUPPORT
-    #endif
-    #if defined(__clang__) && ((__clang_major__ < 3) || \
-                               (__clang_major__ == 3 && __clang_minor__ <= 5))
-        #define NO_AVX2_SUPPORT
-    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
-        #undef NO_AVX2_SUPPORT
-    #endif
-
-    #define HAVE_INTEL_AVX1
-    #ifndef NO_AVX2_SUPPORT
-        #define HAVE_INTEL_AVX2
-    #endif
-#endif /* USE_INTEL_SPEEDUP */
-
-#if defined(HAVE_INTEL_AVX2)
-    #define HAVE_INTEL_RORX
-#endif
-
-
-#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
-    (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH))
-static int InitSha256(wc_Sha256* sha256)
-{
-    int ret = 0;
-
-    if (sha256 == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
-    sha256->digest[0] = 0x6A09E667L;
-    sha256->digest[1] = 0xBB67AE85L;
-    sha256->digest[2] = 0x3C6EF372L;
-    sha256->digest[3] = 0xA54FF53AL;
-    sha256->digest[4] = 0x510E527FL;
-    sha256->digest[5] = 0x9B05688CL;
-    sha256->digest[6] = 0x1F83D9ABL;
-    sha256->digest[7] = 0x5BE0CD19L;
-
-    sha256->buffLen = 0;
-    sha256->loLen   = 0;
-    sha256->hiLen   = 0;
-
-    return ret;
-}
-#endif
-
-
-/* Hardware Acceleration */
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-
-    /* in case intel instructions aren't available, plus we need the K[] global */
-    #define NEED_SOFT_SHA256
-
-    /*****
-    Intel AVX1/AVX2 Macro Control Structure
-
-    #define HAVE_INTEL_AVX1
-    #define HAVE_INTEL_AVX2
-
-    #define HAVE_INTEL_RORX
-
-
-    int InitSha256(wc_Sha256* sha256) {
-         Save/Recover XMM, YMM
-         ...
-    }
-
-    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
-      Transform_Sha256(); Function prototype
-    #else
-      Transform_Sha256() {   }
-      int Sha256Final() {
-         Save/Recover XMM, YMM
-         ...
-      }
-    #endif
-
-    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
-        #if defined(HAVE_INTEL_RORX
-             #define RND with rorx instuction
-        #else
-            #define RND
-        #endif
-    #endif
-
-    #if defined(HAVE_INTEL_AVX1)
-
-       #define XMM Instructions/inline asm
-
-       int Transform_Sha256() {
-           Stitched Message Sched/Round
-        }
-
-    #elif defined(HAVE_INTEL_AVX2)
-
-      #define YMM Instructions/inline asm
-
-      int Transform_Sha256() {
-          More granural Stitched Message Sched/Round
-      }
-
-    #endif
-
-    */
-
-    /* Each platform needs to query info type 1 from cpuid to see if aesni is
-     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
-     */
-
-    /* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */
-    static int Transform_Sha256(wc_Sha256* sha256);
-    #if defined(HAVE_INTEL_AVX1)
-        static int Transform_Sha256_AVX1(wc_Sha256 *sha256);
-        static int Transform_Sha256_AVX1_Len(wc_Sha256* sha256, word32 len);
-    #endif
-    #if defined(HAVE_INTEL_AVX2)
-        static int Transform_Sha256_AVX2(wc_Sha256 *sha256);
-        static int Transform_Sha256_AVX2_Len(wc_Sha256* sha256, word32 len);
-        #ifdef HAVE_INTEL_RORX
-        static int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256);
-        static int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256, word32 len);
-        static int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256);
-        static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, word32 len);
-        #endif
-    #endif
-    static int (*Transform_Sha256_p)(wc_Sha256* sha256);
-                                                       /* = _Transform_Sha256 */
-    static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, word32 len);
-                                                                    /* = NULL */
-    static int transform_check = 0;
-    static word32 intel_flags;
-    #define XTRANSFORM(S)         (*Transform_Sha256_p)((S))
-    #define XTRANSFORM_LEN(S, L)  (*Transform_Sha256_Len_p)((S),(L))
-
-    static void Sha256_SetTransform(void)
-    {
-
-        if (transform_check)
-            return;
-
-        intel_flags = cpuid_get_flags();
-
-    #ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_AVX2(intel_flags)) {
-        #ifdef HAVE_INTEL_RORX
-            if (IS_INTEL_BMI2(intel_flags)) {
-                Transform_Sha256_p = Transform_Sha256_AVX2_RORX;
-                Transform_Sha256_Len_p = Transform_Sha256_AVX2_RORX_Len;
-            }
-            else
-        #endif
-            if (1)
-            {
-                Transform_Sha256_p = Transform_Sha256_AVX2;
-                Transform_Sha256_Len_p = Transform_Sha256_AVX2_Len;
-            }
-        #ifdef HAVE_INTEL_RORX
-            else {
-                Transform_Sha256_p = Transform_Sha256_AVX1_RORX;
-                Transform_Sha256_Len_p = Transform_Sha256_AVX1_RORX_Len;
-            }
-        #endif
-        }
-        else
-    #endif
-    #ifdef HAVE_INTEL_AVX1
-        if (IS_INTEL_AVX1(intel_flags)) {
-            Transform_Sha256_p = Transform_Sha256_AVX1;
-            Transform_Sha256_Len_p = Transform_Sha256_AVX1_Len;
-        }
-        else
-    #endif
-        {
-            Transform_Sha256_p = Transform_Sha256;
-            Transform_Sha256_Len_p = NULL;
-        }
-
-        transform_check = 1;
-    }
-
-    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
-    {
-        int ret = 0;
-        if (sha256 == NULL)
-            return BAD_FUNC_ARG;
-
-        sha256->heap = heap;
-
-        ret = InitSha256(sha256);
-        if (ret != 0)
-            return ret;
-
-        /* choose best Transform function under this runtime environment */
-        Sha256_SetTransform();
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
-        ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
-                            WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
-    #else
-        (void)devId;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        return ret;
-    }
-
-#elif defined(FREESCALE_LTC_SHA)
-    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
-    {
-        (void)heap;
-        (void)devId;
-
-        LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0);
-
-        return 0;
-    }
-
-#elif defined(FREESCALE_MMCAU_SHA)
-
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-        #include "cau_api.h"
-    #else
-        #include "fsl_mmcau.h"
-    #endif
-
-    #define XTRANSFORM(S)        Transform_Sha256((S))
-    #define XTRANSFORM_LEN(S,L)  Transform_Sha256_Len((S),(L))
-
-    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
-    {
-        int ret = 0;
-
-        (void)heap;
-        (void)devId;
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret != 0) {
-            return ret;
-        }
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-        cau_sha256_initialize_output(sha256->digest);
-    #else
-        MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest);
-    #endif
-        wolfSSL_CryptHwMutexUnLock();
-
-        sha256->buffLen = 0;
-        sha256->loLen   = 0;
-        sha256->hiLen   = 0;
-
-        return ret;
-    }
-
-    static int Transform_Sha256(wc_Sha256* sha256)
-    {
-        int ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-    #ifdef FREESCALE_MMCAU_CLASSIC_SHA
-            cau_sha256_hash_n((byte*)sha256->buffer, 1, sha256->digest);
-    #else
-            MMCAU_SHA256_HashN((byte*)sha256->buffer, 1, sha256->digest);
-    #endif
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-#elif defined(WOLFSSL_PIC32MZ_HASH)
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-
-#elif defined(STM32_HASH_SHA2)
-
-    /* Supports CubeMX HAL or Standard Peripheral Library */
-
-    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
-    {
-        if (sha256 == NULL)
-            return BAD_FUNC_ARG;
-
-        (void)devId;
-        (void)heap;
-
-        wc_Stm32_Hash_Init(&sha256->stmCtx);
-        return 0;
-    }
-
-    int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
-    {
-        int ret = 0;
-
-        if (sha256 == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Update(&sha256->stmCtx,
-                HASH_AlgoSelection_SHA256, data, len);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-    int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
-    {
-        int ret = 0;
-
-        if (sha256 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Final(&sha256->stmCtx,
-                HASH_AlgoSelection_SHA256, hash, WC_SHA256_DIGEST_SIZE);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-
-        (void)wc_InitSha256(sha256); /* reset state */
-
-        return ret;
-    }
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
-#else
-    #define NEED_SOFT_SHA256
-
-    int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
-    {
-        int ret = 0;
-        if (sha256 == NULL)
-            return BAD_FUNC_ARG;
-
-        sha256->heap = heap;
-
-        ret = InitSha256(sha256);
-        if (ret != 0)
-            return ret;
-
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-        sha256->W = NULL;
-    #endif
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
-        ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
-                            WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
-    #else
-        (void)devId;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        return ret;
-    }
-#endif /* End Hardware Acceleration */
-
-#ifdef NEED_SOFT_SHA256
-
-    static const ALIGN32 word32 K[64] = {
-        0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
-        0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
-        0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
-        0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
-        0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
-        0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
-        0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
-        0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
-        0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
-        0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
-        0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
-        0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
-        0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
-    };
-
-    #define Ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))
-    #define Maj(x,y,z)      ((((x) | (y)) & (z)) | ((x) & (y)))
-    #define R(x, n)         (((x) & 0xFFFFFFFFU) >> (n))
-
-    #define S(x, n)         rotrFixed(x, n)
-    #define Sigma0(x)       (S(x, 2)  ^ S(x, 13) ^ S(x, 22))
-    #define Sigma1(x)       (S(x, 6)  ^ S(x, 11) ^ S(x, 25))
-    #define Gamma0(x)       (S(x, 7)  ^ S(x, 18) ^ R(x, 3))
-    #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-
-    #define a(i) S[(0-i) & 7]
-    #define b(i) S[(1-i) & 7]
-    #define c(i) S[(2-i) & 7]
-    #define d(i) S[(3-i) & 7]
-    #define e(i) S[(4-i) & 7]
-    #define f(i) S[(5-i) & 7]
-    #define g(i) S[(6-i) & 7]
-    #define h(i) S[(7-i) & 7]
-
-    #define RND(j) \
-         t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + W[i+j]; \
-         t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
-         d(j) += t0; \
-         h(j)  = t0 + t1
-
-    #ifndef XTRANSFORM
-         #define XTRANSFORM(S)        Transform_Sha256((S))
-         #define XTRANSFORM_LEN(S,L)  Transform_Sha256_Len((S),(L))
-    #endif
-
-    static int Transform_Sha256(wc_Sha256* sha256)
-    {
-        word32 S[8], t0, t1;
-        int i;
-
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-        word32* W = sha256->W;
-        if (W == NULL) {
-            W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
-                                                              DYNAMIC_TYPE_RNG);
-            if (W == NULL)
-                return MEMORY_E;
-            sha256->W = W;
-        }
-    #elif defined(WOLFSSL_SMALL_STACK)
-        word32* W;
-        W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-        if (W == NULL)
-            return MEMORY_E;
-    #else
-        word32 W[WC_SHA256_BLOCK_SIZE];
-    #endif
-
-        /* Copy context->state[] to working vars */
-        for (i = 0; i < 8; i++)
-            S[i] = sha256->digest[i];
-
-        for (i = 0; i < 16; i++)
-            W[i] = sha256->buffer[i];
-
-        for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++)
-            W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
-
-    #ifdef USE_SLOW_SHA256
-        /* not unrolled - ~2k smaller and ~25% slower */
-        for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
-            int j;
-            for (j = 0; j < 8; j++) { /* braces needed here for macros {} */
-                RND(j);
-            }
-        }
-    #else
-        /* partially loop unrolled */
-        for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
-            RND(0); RND(1); RND(2); RND(3);
-            RND(4); RND(5); RND(6); RND(7);
-        }
-    #endif /* USE_SLOW_SHA256 */
-
-        /* Add the working vars back into digest state[] */
-        for (i = 0; i < 8; i++) {
-            sha256->digest[i] += S[i];
-        }
-
-    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
-        XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    #endif
-        return 0;
-    }
-#endif
-/* End wc_ software implementation */
-
-
-#ifdef XTRANSFORM
-
-    static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len)
-    {
-        word32 tmp = sha256->loLen;
-        if ((sha256->loLen += len) < tmp)
-            sha256->hiLen++;                       /* carry low to high */
-    }
-
-    static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
-    {
-        int ret = 0;
-        byte* local;
-
-        if (sha256 == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        if (data == NULL && len == 0) {
-            /* valid, but do nothing */
-            return 0;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
-        if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
-        #if defined(HAVE_INTEL_QA)
-            return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len);
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        /* do block size increments */
-        local = (byte*)sha256->buffer;
-
-        /* check that internal buffLen is valid */
-        if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE)
-            return BUFFER_E;
-
-        if (sha256->buffLen > 0) {
-            word32 add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen);
-            XMEMCPY(&local[sha256->buffLen], data, add);
-
-            sha256->buffLen += add;
-            data            += add;
-            len             -= add;
-
-            if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) {
-        #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-            #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-                if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-            #endif
-                {
-                    ByteReverseWords(sha256->buffer, sha256->buffer,
-                                                          WC_SHA256_BLOCK_SIZE);
-                }
-        #endif
-                ret = XTRANSFORM(sha256);
-                if (ret == 0) {
-                    AddLength(sha256, WC_SHA256_BLOCK_SIZE);
-                    sha256->buffLen = 0;
-                }
-                else
-                    len = 0;
-            }
-        }
-
-    #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-        if (Transform_Sha256_Len_p != NULL) {
-            word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1);
-
-            if (blocksLen > 0) {
-                AddLength(sha256, blocksLen);
-                sha256->data = data;
-                /* Byte reversal performed in function if required. */
-                XTRANSFORM_LEN(sha256, blocksLen);
-                data += blocksLen;
-                len  -= blocksLen;
-            }
-        }
-        else
-    #endif
-    #if !defined(LITTLE_ENDIAN_ORDER) || defined(FREESCALE_MMCAU_SHA) || \
-                            defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-        {
-            word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1);
-
-            AddLength(sha256, blocksLen);
-            while (len >= WC_SHA256_BLOCK_SIZE) {
-                XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE);
-
-                data += WC_SHA256_BLOCK_SIZE;
-                len  -= WC_SHA256_BLOCK_SIZE;
-
-                /* Byte reversal performed in function if required. */
-                ret = XTRANSFORM(sha256);
-                if (ret != 0)
-                    break;
-            }
-        }
-    #else
-        {
-            word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1);
-
-            AddLength(sha256, blocksLen);
-            while (len >= WC_SHA256_BLOCK_SIZE) {
-                XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE);
-
-                data += WC_SHA256_BLOCK_SIZE;
-                len  -= WC_SHA256_BLOCK_SIZE;
-
-                ByteReverseWords(sha256->buffer, sha256->buffer,
-                                                          WC_SHA256_BLOCK_SIZE);
-                ret = XTRANSFORM(sha256);
-                if (ret != 0)
-                    break;
-            }
-        }
-    #endif
-
-        if (len > 0) {
-            XMEMCPY(local, data, len);
-            sha256->buffLen = len;
-        }
-
-        return ret;
-    }
-
-    int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
-    {
-        return Sha256Update(sha256, data, len);
-    }
-
-    static WC_INLINE int Sha256Final(wc_Sha256* sha256)
-    {
-
-        int ret;
-        byte* local = (byte*)sha256->buffer;
-
-        if (sha256 == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        AddLength(sha256, sha256->buffLen);  /* before adding pads */
-        local[sha256->buffLen++] = 0x80;     /* add 1 */
-
-        /* pad with zeros */
-        if (sha256->buffLen > WC_SHA256_PAD_SIZE) {
-            XMEMSET(&local[sha256->buffLen], 0,
-                WC_SHA256_BLOCK_SIZE - sha256->buffLen);
-            sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen;
-
-            {
-        #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-            #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-                if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-            #endif
-                {
-                    ByteReverseWords(sha256->buffer, sha256->buffer,
-                                                          WC_SHA256_BLOCK_SIZE);
-                }
-        #endif
-            }
-
-            ret = XTRANSFORM(sha256);
-            if (ret != 0)
-                return ret;
-
-            sha256->buffLen = 0;
-        }
-        XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen);
-
-        /* put lengths in bits */
-        sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) +
-                                                         (sha256->hiLen << 3);
-        sha256->loLen = sha256->loLen << 3;
-
-        /* store lengths */
-    #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
-        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-            if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-        #endif
-            {
-                ByteReverseWords(sha256->buffer, sha256->buffer,
-                    WC_SHA256_BLOCK_SIZE);
-            }
-    #endif
-        /* ! length ordering dependent on digest endian type ! */
-        XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
-        XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
-                sizeof(word32));
-
-    #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || \
-        defined(HAVE_INTEL_AVX2)
-        /* Kinetis requires only these bytes reversed */
-        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-            if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
-        #endif
-            {
-                ByteReverseWords(
-                    &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
-                    &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
-                    2 * sizeof(word32));
-            }
-    #endif
-
-        return XTRANSFORM(sha256);
-    }
-
-    int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
-    {
-    #ifdef LITTLE_ENDIAN_ORDER
-        word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
-    #endif
-
-        if (sha256 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords((word32*)digest, (word32*)sha256->digest,
-                                                         WC_SHA256_DIGEST_SIZE);
-        XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE);
-    #else
-        XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
-    #endif
-
-        return 0;
-    }
-
-    int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
-    {
-        int ret;
-
-        if (sha256 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
-        if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
-        #if defined(HAVE_INTEL_QA)
-            return IntelQaSymSha256(&sha256->asyncDev, hash, NULL,
-                                            WC_SHA256_DIGEST_SIZE);
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        ret = Sha256Final(sha256);
-        if (ret != 0)
-            return ret;
-
-    #if defined(LITTLE_ENDIAN_ORDER)
-        ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE);
-    #endif
-        XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
-
-        return InitSha256(sha256);  /* reset state */
-    }
-
-#endif /* XTRANSFORM */
-
-
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-
-#define _LOAD_DIGEST()                     \
-    "movl	  (%[sha256]), %%r8d \n\t" \
-    "movl	 4(%[sha256]), %%r9d \n\t" \
-    "movl	 8(%[sha256]), %%r10d\n\t" \
-    "movl	12(%[sha256]), %%r11d\n\t" \
-    "movl	16(%[sha256]), %%r12d\n\t" \
-    "movl	20(%[sha256]), %%r13d\n\t" \
-    "movl	24(%[sha256]), %%r14d\n\t" \
-    "movl	28(%[sha256]), %%r15d\n\t"
-
-#define _STORE_ADD_DIGEST()                \
-    "addl	%%r8d ,   (%[sha256])\n\t" \
-    "addl	%%r9d ,  4(%[sha256])\n\t" \
-    "addl	%%r10d,  8(%[sha256])\n\t" \
-    "addl	%%r11d, 12(%[sha256])\n\t" \
-    "addl	%%r12d, 16(%[sha256])\n\t" \
-    "addl	%%r13d, 20(%[sha256])\n\t" \
-    "addl	%%r14d, 24(%[sha256])\n\t" \
-    "addl	%%r15d, 28(%[sha256])\n\t"
-
-#define _ADD_DIGEST()                      \
-    "addl	  (%[sha256]), %%r8d \n\t" \
-    "addl	 4(%[sha256]), %%r9d \n\t" \
-    "addl	 8(%[sha256]), %%r10d\n\t" \
-    "addl	12(%[sha256]), %%r11d\n\t" \
-    "addl	16(%[sha256]), %%r12d\n\t" \
-    "addl	20(%[sha256]), %%r13d\n\t" \
-    "addl	24(%[sha256]), %%r14d\n\t" \
-    "addl	28(%[sha256]), %%r15d\n\t"
-
-#define _STORE_DIGEST()                    \
-    "movl	%%r8d ,   (%[sha256])\n\t" \
-    "movl	%%r9d ,  4(%[sha256])\n\t" \
-    "movl	%%r10d,  8(%[sha256])\n\t" \
-    "movl	%%r11d, 12(%[sha256])\n\t" \
-    "movl	%%r12d, 16(%[sha256])\n\t" \
-    "movl	%%r13d, 20(%[sha256])\n\t" \
-    "movl	%%r14d, 24(%[sha256])\n\t" \
-    "movl	%%r15d, 28(%[sha256])\n\t"
-
-#define LOAD_DIGEST() \
-    _LOAD_DIGEST()
-
-#define STORE_ADD_DIGEST() \
-    _STORE_ADD_DIGEST()
-
-#define ADD_DIGEST() \
-    _ADD_DIGEST()
-
-#define STORE_DIGEST() \
-    _STORE_DIGEST()
-
-
-#define S_0 %r8d
-#define S_1 %r9d
-#define S_2 %r10d
-#define S_3 %r11d
-#define S_4 %r12d
-#define S_5 %r13d
-#define S_6 %r14d
-#define S_7 %r15d
-
-#define L1  "%%edx"
-#define L2  "%%ecx"
-#define L3  "%%eax"
-#define L4  "%%ebx"
-#define WK  "%%rsp"
-
-#define WORK_REGS  "eax", "ebx", "ecx", "edx"
-#define STATE_REGS "r8","r9","r10","r11","r12","r13","r14","r15"
-#define XMM_REGS   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6",    \
-                   "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13"
-
-#if defined(HAVE_INTEL_RORX)
-#define RND_STEP_RORX_0_1(a, b, c, d, e, f, g, h, i) \
-    /* L3 = f */                                     \
-    "movl	%" #f ", " L3 "\n\t"                 \
-    /* L2 = e>>>11 */                                \
-    "rorx	$11, %" #e ", " L2 "\n\t"            \
-    /* h += w_k */                                   \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"     \
-
-#define RND_STEP_RORX_0_2(a, b, c, d, e, f, g, h, i) \
-    /* L2 = (e>>>6) ^ (e>>>11) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L3 = f ^ g */                                 \
-    "xorl	%" #g ", " L3 "\n\t"                 \
-    /* L1 = e>>>25 */                                \
-    "rorx	$25, %" #e ", " L1 "\n\t"            \
-
-#define RND_STEP_RORX_0_3(a, b, c, d, e, f, g, h, i) \
-    /* L3 = (f ^ g) & e */                           \
-    "andl	%" #e ", " L3 "\n\t"                 \
-    /* L1 = Sigma1(e) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L2 = a>>>13 */                                \
-    "rorx	$13, %" #a ", " L2 "\n\t"            \
-
-#define RND_STEP_RORX_0_4(a, b, c, d, e, f, g, h, i) \
-    /* h += Sigma1(e) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L1 = a>>>2 */                                 \
-    "rorx	$2, %" #a ", " L1 "\n\t"             \
-    /* L3 = Ch(e,f,g) */                             \
-    "xorl	%" #g ", " L3 "\n\t"                 \
-
-#define RND_STEP_RORX_0_5(a, b, c, d, e, f, g, h, i) \
-    /* L2 = (a>>>2) ^ (a>>>13) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L1 = a>>>22 */                                \
-    "rorx	$22, %" #a ", " L1 "\n\t"            \
-    /* h += Ch(e,f,g) */                             \
-    "addl	" L3 ", %" #h "\n\t"                 \
-
-#define RND_STEP_RORX_0_6(a, b, c, d, e, f, g, h, i) \
-    /* L1 = Sigma0(a) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L3 = b */                                     \
-    "movl	%" #b ", " L3 "\n\t"                 \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */       \
-    "addl	%" #h ", %" #d "\n\t"                \
-
-#define RND_STEP_RORX_0_7(a, b, c, d, e, f, g, h, i) \
-    /* L3 = a ^ b */                                 \
-    "xorl	%" #a ", " L3 "\n\t"                 \
-    /* h += Sigma0(a) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L4 = (a ^ b) & (b ^ c) */                     \
-    "andl	" L3 ", " L4 "\n\t"                  \
-
-#define RND_STEP_RORX_0_8(a, b, c, d, e, f, g, h, i) \
-    /* L4 = Maj(a,b,c) */                            \
-    "xorl	%" #b ", " L4 "\n\t"                 \
-    /* L1 = d>>>6 (= e>>>6 next RND) */              \
-    "rorx	$6, %" #d ", " L1 "\n\t"             \
-    /* h += Maj(a,b,c) */                            \
-    "addl	" L4 ", %" #h "\n\t"                 \
-
-#define RND_STEP_RORX_1_1(a, b, c, d, e, f, g, h, i) \
-    /* L4 = f */                                     \
-    "movl	%" #f ", " L4 "\n\t"                 \
-    /* L2 = e>>>11 */                                \
-    "rorx	$11, %" #e ", " L2 "\n\t"            \
-    /* h += w_k */                                   \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"     \
-
-#define RND_STEP_RORX_1_2(a, b, c, d, e, f, g, h, i) \
-    /* L2 = (e>>>6) ^ (e>>>11) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L4 = f ^ g */                                 \
-    "xorl	%" #g ", " L4 "\n\t"                 \
-    /* L1 = e>>>25 */                                \
-    "rorx	$25, %" #e ", " L1 "\n\t"            \
-
-#define RND_STEP_RORX_1_3(a, b, c, d, e, f, g, h, i) \
-    /* L4 = (f ^ g) & e */                           \
-    "andl	%" #e ", " L4 "\n\t"                 \
-    /* L1 = Sigma1(e) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L2 = a>>>13 */                                \
-    "rorx	$13, %" #a ", " L2 "\n\t"            \
-
-#define RND_STEP_RORX_1_4(a, b, c, d, e, f, g, h, i) \
-    /* h += Sigma1(e) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L1 = a>>>2 */                                 \
-    "rorx	$2, %" #a ", " L1 "\n\t"             \
-    /* L4 = Ch(e,f,g) */                             \
-    "xorl	%" #g ", " L4 "\n\t"                 \
-
-#define RND_STEP_RORX_1_5(a, b, c, d, e, f, g, h, i) \
-    /* L2 = (a>>>2) ^ (a>>>13) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L1 = a>>>22 */                                \
-    "rorx	$22, %" #a ", " L1 "\n\t"            \
-    /* h += Ch(e,f,g) */                             \
-    "addl	" L4 ", %" #h "\n\t"                 \
-
-#define RND_STEP_RORX_1_6(a, b, c, d, e, f, g, h, i) \
-    /* L1 = Sigma0(a) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L4 = b */                                     \
-    "movl	%" #b ", " L4 "\n\t"                 \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */       \
-    "addl	%" #h ", %" #d "\n\t"                \
-
-#define RND_STEP_RORX_1_7(a, b, c, d, e, f, g, h, i) \
-    /* L4 = a ^ b */                                 \
-    "xorl	%" #a ", " L4 "\n\t"                 \
-    /* h += Sigma0(a) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L3 = (a ^ b) & (b ^ c) */                     \
-    "andl	" L4 ", " L3 "\n\t"                  \
-
-#define RND_STEP_RORX_1_8(a, b, c, d, e, f, g, h, i) \
-    /* L3 = Maj(a,b,c) */                            \
-    "xorl	%" #b ", " L3 "\n\t"                 \
-    /* L1 = d>>>6 (= e>>>6 next RND) */              \
-    "rorx	$6, %" #d ", " L1 "\n\t"             \
-    /* h += Maj(a,b,c) */                            \
-    "addl	" L3 ", %" #h "\n\t"                 \
-
-#define _RND_RORX_X_0(a, b, c, d, e, f, g, h, i)     \
-    /* L1 = e>>>6 */                                 \
-    "rorx	$6, %" #e ", " L1 "\n\t"             \
-    /* L2 = e>>>11 */                                \
-    "rorx	$11, %" #e ", " L2 "\n\t"            \
-    /* Prev RND: h += Maj(a,b,c) */                  \
-    "addl	" L3 ", %" #a "\n\t"                 \
-    /* h += w_k */                                   \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"     \
-    /* L3 = f */                                     \
-    "movl	%" #f ", " L3 "\n\t"                 \
-    /* L2 = (e>>>6) ^ (e>>>11) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L3 = f ^ g */                                 \
-    "xorl	%" #g ", " L3 "\n\t"                 \
-    /* L1 = e>>>25 */                                \
-    "rorx	$25, %" #e ", " L1 "\n\t"            \
-    /* L1 = Sigma1(e) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L3 = (f ^ g) & e */                           \
-    "andl	%" #e ", " L3 "\n\t"                 \
-    /* h += Sigma1(e) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L1 = a>>>2 */                                 \
-    "rorx	$2, %" #a ", " L1 "\n\t"             \
-    /* L2 = a>>>13 */                                \
-    "rorx	$13, %" #a ", " L2 "\n\t"            \
-    /* L3 = Ch(e,f,g) */                             \
-    "xorl	%" #g ", " L3 "\n\t"                 \
-    /* L2 = (a>>>2) ^ (a>>>13) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L1 = a>>>22 */                                \
-    "rorx	$22, %" #a ", " L1 "\n\t"            \
-    /* h += Ch(e,f,g) */                             \
-    "addl	" L3 ", %" #h "\n\t"                 \
-    /* L1 = Sigma0(a) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L3 = b */                                     \
-    "movl	%" #b ", " L3 "\n\t"                 \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */       \
-    "addl	%" #h ", %" #d "\n\t"                \
-    /* L3 = a ^ b */                                 \
-    "xorl	%" #a ", " L3 "\n\t"                 \
-    /* L4 = (a ^ b) & (b ^ c) */                     \
-    "andl	" L3 ", " L4 "\n\t"                  \
-    /* h += Sigma0(a) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L4 = Maj(a,b,c) */                            \
-    "xorl	%" #b ", " L4 "\n\t"                 \
-
-#define _RND_RORX_X_1(a, b, c, d, e, f, g, h, i)     \
-    /* L1 = e>>>6 */                                 \
-    "rorx	$6, %" #e ", " L1 "\n\t"             \
-    /* L2 = e>>>11 */                                \
-    "rorx	$11, %" #e ", " L2 "\n\t"            \
-    /* Prev RND: h += Maj(a,b,c) */                  \
-    "addl	" L4 ", %" #a "\n\t"                 \
-    /* h += w_k */                                   \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"     \
-    /* L4 = f */                                     \
-    "movl	%" #f ", " L4 "\n\t"                 \
-    /* L2 = (e>>>6) ^ (e>>>11) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L4 = f ^ g */                                 \
-    "xorl	%" #g ", " L4 "\n\t"                 \
-    /* L1 = e>>>25 */                                \
-    "rorx	$25, %" #e ", " L1 "\n\t"            \
-    /* L1 = Sigma1(e) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L4 = (f ^ g) & e */                           \
-    "andl	%" #e ", " L4 "\n\t"                 \
-    /* h += Sigma1(e) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L1 = a>>>2 */                                 \
-    "rorx	$2, %" #a ", " L1 "\n\t"             \
-    /* L2 = a>>>13 */                                \
-    "rorx	$13, %" #a ", " L2 "\n\t"            \
-    /* L4 = Ch(e,f,g) */                             \
-    "xorl	%" #g ", " L4 "\n\t"                 \
-    /* L2 = (a>>>2) ^ (a>>>13) */                    \
-    "xorl	" L1 ", " L2 "\n\t"                  \
-    /* L1 = a>>>22 */                                \
-    "rorx	$22, %" #a ", " L1 "\n\t"            \
-    /* h += Ch(e,f,g) */                             \
-    "addl	" L4 ", %" #h "\n\t"                 \
-    /* L1 = Sigma0(a) */                             \
-    "xorl	" L2 ", " L1 "\n\t"                  \
-    /* L4 = b */                                     \
-    "movl	%" #b ", " L4 "\n\t"                 \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */       \
-    "addl	%" #h ", %" #d "\n\t"                \
-    /* L4 = a ^ b */                                 \
-    "xorl	%" #a ", " L4 "\n\t"                 \
-    /* L2 = (a ^ b) & (b ^ c) */                     \
-    "andl	" L4 ", " L3 "\n\t"                  \
-    /* h += Sigma0(a) */                             \
-    "addl	" L1 ", %" #h "\n\t"                 \
-    /* L3 = Maj(a,b,c) */                            \
-    "xorl	%" #b ", " L3 "\n\t"                 \
-
-
-#define RND_RORX_X_0(a,b,c,d,e,f,g,h,i) \
-       _RND_RORX_X_0(a,b,c,d,e,f,g,h,i)
-#define RND_RORX_X_1(a,b,c,d,e,f,g,h,i) \
-       _RND_RORX_X_1(a,b,c,d,e,f,g,h,i)
-
-#define RND_RORX_X4(a,b,c,d,e,f,g,h,i)    \
-        RND_RORX_X_0(a,b,c,d,e,f,g,h,i+0) \
-        RND_RORX_X_1(h,a,b,c,d,e,f,g,i+1) \
-        RND_RORX_X_0(g,h,a,b,c,d,e,f,i+2) \
-        RND_RORX_X_1(f,g,h,a,b,c,d,e,i+3)
-
-#endif /* HAVE_INTEL_RORX */
-
-#define RND_STEP_0_1(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = e>>>14 */                                                 \
-    "rorl	$14, " L1 "\n\t"                                      \
-
-#define RND_STEP_0_2(a,b,c,d,e,f,g,h,i)                               \
-    /* L3 = b */                                                      \
-    "movl	%" #b ", " L3 "\n\t"                                  \
-    /* L2 = f */                                                      \
-    "movl	%" #f ", " L2 "\n\t"                                  \
-    /* h += w_k */                                                    \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"                      \
-    /* L2 = f ^ g */                                                  \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-
-#define RND_STEP_0_3(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = (e>>>14) ^ e */                                           \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L2 = (f ^ g) & e */                                            \
-    "andl	%" #e ", " L2 "\n\t"                                  \
- 
-#define RND_STEP_0_4(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = ((e>>>14) ^ e) >>> 5 */                                   \
-    "rorl	$5, " L1 "\n\t"                                       \
-    /* L2 = Ch(e,f,g) */                                              \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */                             \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* h += Ch(e,f,g) */                                              \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-#define RND_STEP_0_5(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */                     \
-    "rorl	$6, " L1 "\n\t"                                       \
-    /* L3 = a ^ b (= b ^ c of next RND) */                            \
-    "xorl	%" #a ", " L3 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) */                                     \
-    "addl	" L1 ", %" #h "\n\t"                                  \
-    /* L2 = a */                                                      \
-    "movl	%" #a ", " L2 "\n\t"                                  \
-
-#define RND_STEP_0_6(a,b,c,d,e,f,g,h,i)                               \
-    /* L3 = (a ^ b) & (b ^ c) */                                      \
-    "andl	" L3 ", " L4 "\n\t"                                   \
-    /* L2 = a>>>9 */                                                  \
-    "rorl	$9, " L2 "\n\t"                                       \
-    /* L2 = (a>>>9) ^ a */                                            \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* L1 = Maj(a,b,c) */                                             \
-    "xorl	%" #b ", " L4 "\n\t"                                  \
-
-#define RND_STEP_0_7(a,b,c,d,e,f,g,h,i)                               \
-    /* L2 = ((a>>>9) ^ a) >>> 11 */                                   \
-    "rorl	$11, " L2 "\n\t"                                      \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */                        \
-    "addl	%" #h ", %" #d "\n\t"                                 \
-    /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */                             \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */            \
-    "addl	" L4 ", %" #h "\n\t"                                  \
-
-#define RND_STEP_0_8(a,b,c,d,e,f,g,h,i)                               \
-    /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */                     \
-    "rorl	$2, " L2 "\n\t"                                       \
-    /* L1 = d (e of next RND) */                                      \
-    "movl	%" #d ", " L1 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */  \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-#define RND_STEP_1_1(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = e>>>14 */                                                 \
-    "rorl	$14, " L1 "\n\t"                                      \
- 
-#define RND_STEP_1_2(a,b,c,d,e,f,g,h,i)                               \
-    /* L3 = b */                                                      \
-    "movl	%" #b ", " L4 "\n\t"                                  \
-    /* L2 = f */                                                      \
-    "movl	%" #f ", " L2 "\n\t"                                  \
-    /* h += w_k */                                                    \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"                      \
-    /* L2 = f ^ g */                                                  \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
- 
-#define RND_STEP_1_3(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = (e>>>14) ^ e */                                           \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L2 = (f ^ g) & e */                                            \
-    "andl	%" #e ", " L2 "\n\t"                                  \
- 
-#define RND_STEP_1_4(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = ((e>>>14) ^ e) >>> 5 */                                   \
-    "rorl	$5, " L1 "\n\t"                                       \
-    /* L2 = Ch(e,f,g) */                                              \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */                             \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* h += Ch(e,f,g) */                                              \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-#define RND_STEP_1_5(a,b,c,d,e,f,g,h,i)                               \
-    /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */                     \
-    "rorl	$6, " L1 "\n\t"                                       \
-    /* L4 = a ^ b (= b ^ c of next RND) */                            \
-    "xorl	%" #a ", " L4 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) */                                     \
-    "addl	" L1 ", %" #h "\n\t"                                  \
-    /* L2 = a */                                                      \
-    "movl	%" #a ", " L2 "\n\t"                                  \
-
-#define RND_STEP_1_6(a,b,c,d,e,f,g,h,i)                               \
-    /* L3 = (a ^ b) & (b ^ c)  */                                     \
-    "andl	" L4 ", " L3 "\n\t"                                   \
-    /* L2 = a>>>9 */                                                  \
-    "rorl	$9, " L2 "\n\t"                                       \
-    /* L2 = (a>>>9) ^ a */                                            \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* L1 = Maj(a,b,c) */                                             \
-    "xorl	%" #b ", " L3 "\n\t"                                  \
-
-#define RND_STEP_1_7(a,b,c,d,e,f,g,h,i)                               \
-    /* L2 = ((a>>>9) ^ a) >>> 11 */                                   \
-    "rorl	$11, " L2 "\n\t"                                      \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */                        \
-    "addl	%" #h ", %" #d "\n\t"                                 \
-    /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */                             \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */            \
-    "addl	" L3 ", %" #h "\n\t"                                  \
-
-#define RND_STEP_1_8(a,b,c,d,e,f,g,h,i)                               \
-    /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */                     \
-    "rorl	$2, " L2 "\n\t"                                       \
-    /* L1 = d (e of next RND) */                                      \
-    "movl	%" #d ", " L1 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */  \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-#define _RND_ALL_0(a,b,c,d,e,f,g,h,i)                                 \
-    /* h += w_k */                                                    \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"                      \
-    /* L2 = f */                                                      \
-    "movl	%" #f ", " L2 "\n\t"                                  \
-    /* L3 = b */                                                      \
-    "movl	%" #b ", " L3 "\n\t"                                  \
-    /* L2 = f ^ g */                                                  \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = e>>>14 */                                                 \
-    "rorl	$14, " L1 "\n\t"                                      \
-    /* L2 = (f ^ g) & e */                                            \
-    "andl	%" #e ", " L2 "\n\t"                                  \
-    /* L1 = (e>>>14) ^ e */                                           \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L2 = Ch(e,f,g) */                                              \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = ((e>>>14) ^ e) >>> 5 */                                   \
-    "rorl	$5, " L1 "\n\t"                                       \
-    /* h += Ch(e,f,g) */                                              \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-    /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */                             \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L3 = a ^ b */                                                  \
-    "xorl	%" #a ", " L3 "\n\t"                                  \
-    /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */                     \
-    "rorl	$6, " L1 "\n\t"                                       \
-    /* L2 = a */                                                      \
-    "movl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) */                                     \
-    "addl	" L1 ", %" #h "\n\t"                                  \
-    /* L2 = a>>>9 */                                                  \
-    "rorl	$9, " L2 "\n\t"                                       \
-    /* L3 = (a ^ b) & (b ^ c) */                                      \
-    "andl	" L3 ", " L4 "\n\t"                                   \
-    /* L2 = (a>>>9) ^ a */                                            \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* L1 = Maj(a,b,c) */                                             \
-    "xorl	%" #b ", " L4 "\n\t"                                  \
-    /* L2 = ((a>>>9) ^ a) >>> 11 */                                   \
-    "rorl	$11, " L2 "\n\t"                                      \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */                        \
-    "addl	%" #h ", %" #d "\n\t"                                 \
-    /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */                             \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */            \
-    "addl	" L4 ", %" #h "\n\t"                                  \
-    /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */                     \
-    "rorl	$2, " L2 "\n\t"                                       \
-    /* L1 = d (e of next RND) */                                      \
-    "movl	%" #d ", " L1 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */  \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-#define _RND_ALL_1(a,b,c,d,e,f,g,h,i)                                 \
-    /* h += w_k */                                                    \
-    "addl	(" #i ")*4(" WK "), %" #h "\n\t"                      \
-    /* L2 = f */                                                      \
-    "movl	%" #f ", " L2 "\n\t"                                  \
-    /* L3 = b */                                                      \
-    "movl	%" #b ", " L4 "\n\t"                                  \
-    /* L2 = f ^ g */                                                  \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = e>>>14 */                                                 \
-    "rorl	$14, " L1 "\n\t"                                      \
-    /* L2 = (f ^ g) & e */                                            \
-    "andl	%" #e ", " L2 "\n\t"                                  \
-    /* L1 = (e>>>14) ^ e */                                           \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L2 = Ch(e,f,g) */                                              \
-    "xorl	%" #g ", " L2 "\n\t"                                  \
-    /* L1 = ((e>>>14) ^ e) >>> 5 */                                   \
-    "rorl	$5, " L1 "\n\t"                                       \
-    /* h += Ch(e,f,g) */                                              \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-    /* L1 = (((e>>>14) ^ e) >>> 5) ^ e */                             \
-    "xorl	%" #e ", " L1 "\n\t"                                  \
-    /* L3 = a ^ b */                                                  \
-    "xorl	%" #a ", " L4 "\n\t"                                  \
-    /* L1 = ((((e>>>14) ^ e) >>> 5) ^ e) >>> 6 */                     \
-    "rorl	$6, " L1 "\n\t"                                       \
-    /* L2 = a */                                                      \
-    "movl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) */                                     \
-    "addl	" L1 ", %" #h "\n\t"                                  \
-    /* L2 = a>>>9 */                                                  \
-    "rorl	$9, " L2 "\n\t"                                       \
-    /* L3 = (a ^ b) & (b ^ c)  */                                     \
-    "andl	" L4 ", " L3 "\n\t"                                   \
-    /* L2 = (a>>>9) ^ a */                                            \
-    "xorl	%" #a", " L2 "\n\t"                                   \
-    /* L1 = Maj(a,b,c) */                                             \
-    "xorl	%" #b ", " L3 "\n\t"                                  \
-    /* L2 = ((a>>>9) ^ a) >>> 11 */                                   \
-    "rorl	$11, " L2 "\n\t"                                      \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */                        \
-    "addl	%" #h ", %" #d "\n\t"                                 \
-    /* L2 = (((a>>>9) ^ a) >>> 11) ^ a */                             \
-    "xorl	%" #a ", " L2 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) + Ch(e,f,g) + Maj(a,b,c) */            \
-    "addl	" L3 ", %" #h "\n\t"                                  \
-    /* L2 = ((((a>>>9) ^ a) >>> 11) ^ a) >>> 2 */                     \
-    "rorl	$2, " L2 "\n\t"                                       \
-    /* L1 = d (e of next RND) */                                      \
-    "movl	%" #d ", " L1 "\n\t"                                  \
-    /* h = h + w_k + Sigma1(e) Sigma0(a) + Ch(e,f,g) + Maj(a,b,c) */  \
-    "addl	" L2 ", %" #h "\n\t"                                  \
-
-
-#define RND_ALL_0(a, b, c, d, e, f, g, h, i) \
-       _RND_ALL_0(a, b, c, d, e, f, g, h, i)
-#define RND_ALL_1(a, b, c, d, e, f, g, h, i) \
-       _RND_ALL_1(a, b, c, d, e, f, g, h, i)
-
-#define RND_ALL_4(a, b, c, d, e, f, g, h, i)   \
-        RND_ALL_0(a, b, c, d, e, f, g, h, i+0) \
-        RND_ALL_1(h, a, b, c, d, e, f, g, i+1) \
-        RND_ALL_0(g, h, a, b, c, d, e, f, i+2) \
-        RND_ALL_1(f, g, h, a, b, c, d, e, i+3)
-
-#endif  /* defined(HAVE_INTEL_AVX1) ||  defined(HAVE_INTEL_AVX2) */
-
-#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */
-
-#define _VPALIGNR(op1, op2, op3, op4)                    \
-    "vpalignr	$" #op4", %" #op3", %" #op2", %" #op1"\n\t"
-#define VPALIGNR(op1, op2, op3, op4)                     \
-        _VPALIGNR(op1, op2, op3, op4)
-#define _VPADDD(op1, op2, op3)                           \
-    "vpaddd	%" #op3", %" #op2", %" #op1"\n\t"
-#define VPADDD(op1, op2, op3)                            \
-       _VPADDD(op1, op2, op3)
-#define _VPSRLD(op1, op2, op3)                           \
-    "vpsrld	$" #op3", %" #op2", %" #op1"\n\t"
-#define VPSRLD(op1, op2, op3)        \
-       _VPSRLD(op1, op2, op3)
-#define _VPSRLQ(op1, op2, op3)                           \
-    "vpsrlq	$" #op3", %" #op2", %" #op1"\n\t"
-#define VPSRLQ(op1,op2,op3)        \
-       _VPSRLQ(op1,op2,op3)
-#define _VPSLLD(op1,op2,op3)                             \
-    "vpslld	$" #op3", %" #op2", %" #op1"\n\t"
-#define VPSLLD(op1,op2,op3)        \
-       _VPSLLD(op1,op2,op3)
-#define _VPOR(op1,op2,op3)                               \
-    "vpor	%" #op3", %" #op2", %" #op1"\n\t"
-#define VPOR(op1,op2,op3)          \
-       _VPOR(op1,op2,op3)
-#define _VPXOR(op1,op2,op3)                              \
-    "vpxor	%" #op3", %" #op2", %" #op1"\n\t"
-#define VPXOR(op1,op2,op3)         \
-       _VPXOR(op1,op2,op3)
-#define _VPSHUFD(op1,op2,op3)                            \
-    "vpshufd	$" #op3", %" #op2", %" #op1"\n\t"
-#define VPSHUFD(op1,op2,op3)       \
-       _VPSHUFD(op1,op2,op3)
-#define _VPSHUFB(op1,op2,op3)                            \
-    "vpshufb	%" #op3", %" #op2", %" #op1"\n\t"
-#define VPSHUFB(op1,op2,op3)       \
-       _VPSHUFB(op1,op2,op3)
-#define _VPSLLDQ(op1,op2,op3)                            \
-    "vpslldq	$" #op3", %" #op2", %" #op1"\n\t"
-#define VPSLLDQ(op1,op2,op3)       \
-       _VPSLLDQ(op1,op2,op3)
-
-#define MsgSched(X0,X1,X2,X3,a,b,c,d,e,f,g,h,_i)                           \
-            RND_STEP_0_1(a,b,c,d,e,f,g,h,_i)                               \
-    VPALIGNR (XTMP1, X1, X0, 4)    /* XTMP1 = W[-15] */                    \
-    VPALIGNR (XTMP0, X3, X2, 4)    /* XTMP0 = W[-7] */                     \
-            RND_STEP_0_2(a,b,c,d,e,f,g,h,_i)                               \
-            RND_STEP_0_3(a,b,c,d,e,f,g,h,_i)                               \
-    VPSRLD   (XTMP2, XTMP1, 7)     /* XTMP2 = W[-15] >> 7 */               \
-    VPSLLD   (XTMP3, XTMP1, 25)    /* XTEMP3 = W[-15] << (32-7) */         \
-            RND_STEP_0_4(a,b,c,d,e,f,g,h,_i)                               \
-            RND_STEP_0_5(a,b,c,d,e,f,g,h,_i)                               \
-    VPSRLD   (XTMP4, XTMP1, 18)    /* XTEMP4 = W[-15] >> 18 */             \
-    VPSLLD   (XTMP5, XTMP1, 14)    /* XTEMP5 = W[-15] << (32-18) */        \
-            RND_STEP_0_6(a,b,c,d,e,f,g,h,_i)                               \
-            RND_STEP_0_7(a,b,c,d,e,f,g,h,_i)                               \
-    VPOR     (XTMP2, XTMP3, XTMP2) /* XTMP2 = W[-15] >>> 7 */              \
-    VPOR     (XTMP4, XTMP5, XTMP4) /* XTMP4 = W[-15] >>> 18 */             \
-            RND_STEP_0_8(a,b,c,d,e,f,g,h,_i)                               \
-            RND_STEP_1_1(h,a,b,c,d,e,f,g,_i+1)                             \
-            RND_STEP_1_2(h,a,b,c,d,e,f,g,_i+1)                             \
-    VPSRLD   (XTMP5, XTMP1, 3)     /* XTMP4 = W[-15] >> 3 */               \
-    VPXOR    (XTMP2, XTMP4, XTMP2)                                         \
-                          /* XTMP2 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */ \
-            RND_STEP_1_3(h,a,b,c,d,e,f,g,_i+1)                             \
-            RND_STEP_1_4(h,a,b,c,d,e,f,g,_i+1)                             \
-    VPXOR    (XTMP1, XTMP5, XTMP2)  /* XTMP1 = s0 */                       \
-    VPSHUFD  (XTMP2, X3, 0b11111010)  /* XTMP2 = W[-2] {BBAA}*/            \
-            RND_STEP_1_5(h,a,b,c,d,e,f,g,_i+1)                             \
-            RND_STEP_1_6(h,a,b,c,d,e,f,g,_i+1)                             \
-    VPSRLD   (XTMP4, XTMP2, 10)      /* XTMP4 = W[-2] >> 10 {BBAA} */      \
-    VPSRLQ   (XTMP3, XTMP2, 19)      /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */  \
-            RND_STEP_1_7(h,a,b,c,d,e,f,g,_i+1)                             \
-            RND_STEP_1_8(h,a,b,c,d,e,f,g,_i+1)                             \
-            RND_STEP_0_1(g,h,a,b,c,d,e,f,_i+2)                             \
-    VPSRLQ   (XTMP2, XTMP2, 17)      /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */  \
-    VPADDD   (XTMP0, XTMP0, X0)                                            \
-            RND_STEP_0_2(g,h,a,b,c,d,e,f,_i+2)                             \
-            RND_STEP_0_3(g,h,a,b,c,d,e,f,_i+2)                             \
-            RND_STEP_0_4(g,h,a,b,c,d,e,f,_i+2)                             \
-    VPXOR    (XTMP2, XTMP3, XTMP2)                                         \
-    VPADDD   (XTMP0, XTMP0, XTMP1)  /* XTMP0 = W[-16] + W[-7] + s0 */      \
-            RND_STEP_0_5(g,h,a,b,c,d,e,f,_i+2)                             \
-    VPXOR    (XTMP4, XTMP4, XTMP2)   /* XTMP4 = s1 {xBxA} */               \
-            RND_STEP_0_6(g,h,a,b,c,d,e,f,_i+2)                             \
-    VPSHUFB  (XTMP4, XTMP4, SHUF_00BA)  /* XTMP4 = s1 {00BA} */            \
-            RND_STEP_0_7(g,h,a,b,c,d,e,f,_i+2)                             \
-    VPADDD   (XTMP0, XTMP0, XTMP4)  /* XTMP0 = {..., ..., W[1], W[0]} */   \
-            RND_STEP_0_8(g,h,a,b,c,d,e,f,_i+2)                             \
-            RND_STEP_1_1(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPSHUFD  (XTMP2, XTMP0, 0b01010000) /* XTMP2 = W[-2] {DDCC} */         \
-            RND_STEP_1_2(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPSRLQ   (XTMP4, XTMP2, 17)      /* XTMP4 = W[-2] MY_ROR 17 {xDxC} */  \
-    VPSRLQ   (XTMP3, XTMP2, 19)       /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */ \
-            RND_STEP_1_3(f,g,h,a,b,c,d,e,_i+3)                             \
-            RND_STEP_1_4(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPSRLD   (XTMP5, XTMP2, 10)       /* XTMP5 = W[-2] >> 10 {DDCC} */     \
-    VPXOR    (XTMP4, XTMP3, XTMP4)                                         \
-            RND_STEP_1_5(f,g,h,a,b,c,d,e,_i+3)                             \
-            RND_STEP_1_6(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPXOR    (XTMP5, XTMP4, XTMP5)   /* XTMP5 = s1 {xDxC} */               \
-            RND_STEP_1_7(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPSHUFB  (XTMP5, XTMP5, SHUF_DC00) /* XTMP5 = s1 {DC00} */             \
-            RND_STEP_1_8(f,g,h,a,b,c,d,e,_i+3)                             \
-    VPADDD   (X0, XTMP5, XTMP0)      /* X0 = {W[3], W[2], W[1], W[0]} */
-
-#if defined(HAVE_INTEL_RORX)
-
-#define MsgSched_RORX(X0,X1,X2,X3,a,b,c,d,e,f,g,h,_i)                      \
-            RND_STEP_RORX_0_1(a,b,c,d,e,f,g,h,_i)                          \
-    VPALIGNR (XTMP0, X3, X2, 4)                                            \
-    VPALIGNR (XTMP1, X1, X0, 4)   /* XTMP1 = W[-15] */                     \
-            RND_STEP_RORX_0_2(a,b,c,d,e,f,g,h,_i)                          \
-            RND_STEP_RORX_0_3(a,b,c,d,e,f,g,h,_i)                          \
-    VPSRLD   (XTMP2, XTMP1, 7)                                             \
-    VPSLLD   (XTMP3, XTMP1, 25) /* VPSLLD   (XTMP3, XTMP1, (32-7)) */      \
-            RND_STEP_RORX_0_4(a,b,c,d,e,f,g,h,_i)                          \
-            RND_STEP_RORX_0_5(a,b,c,d,e,f,g,h,_i)                          \
-    VPSRLD   (XTMP4, XTMP1, 3)  /* XTMP4 = W[-15] >> 3 */                  \
-    VPOR     (XTMP3, XTMP3, XTMP2)  /* XTMP1 = W[-15] MY_ROR 7 */          \
-            RND_STEP_RORX_0_6(a,b,c,d,e,f,g,h,_i)                          \
-            RND_STEP_RORX_0_7(a,b,c,d,e,f,g,h,_i)                          \
-            RND_STEP_RORX_0_8(a,b,c,d,e,f,g,h,_i)                          \
-                                                                           \
-            RND_STEP_RORX_1_1(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPSRLD   (XTMP2, XTMP1,18)                                             \
-            RND_STEP_RORX_1_2(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPSLLD   (XTMP1, XTMP1, 14) /* VPSLLD   (XTMP1, XTMP1, (32-18)) */     \
-            RND_STEP_RORX_1_3(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPXOR    (XTMP3, XTMP3, XTMP1)                                         \
-            RND_STEP_RORX_1_4(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPXOR    (XTMP3, XTMP3, XTMP2)                                         \
-                          /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */ \
-            RND_STEP_RORX_1_5(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPSHUFD  (XTMP2, X3, 0b11111010)  /* XTMP2 = W[-2] {BBAA}*/            \
-            RND_STEP_RORX_1_6(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPXOR    (XTMP1, XTMP3, XTMP4)  /* XTMP1 = s0 */                       \
-            RND_STEP_RORX_1_7(h,a,b,c,d,e,f,g,_i+1)                        \
-    VPSRLD   (XTMP4, XTMP2, 10)      /* XTMP4 = W[-2] >> 10 {BBAA} */      \
-            RND_STEP_RORX_1_8(h,a,b,c,d,e,f,g,_i+1)                        \
-                                                                           \
-            RND_STEP_RORX_0_1(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPSRLQ   (XTMP3, XTMP2, 19)      /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */  \
-            RND_STEP_RORX_0_2(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPSRLQ   (XTMP2, XTMP2, 17)      /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */  \
-    VPADDD   (XTMP0, XTMP0, X0)                                            \
-            RND_STEP_RORX_0_3(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPADDD   (XTMP0, XTMP0, XTMP1)  /* XTMP0 = W[-16] + W[-7] + s0 */      \
-            RND_STEP_RORX_0_4(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPXOR    (XTMP2, XTMP2, XTMP3)                                         \
-            RND_STEP_RORX_0_5(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPXOR    (XTMP4, XTMP4, XTMP2)   /* XTMP4 = s1 {xBxA} */               \
-            RND_STEP_RORX_0_6(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPSHUFB  (XTMP4, XTMP4, SHUF_00BA)  /* XTMP4 = s1 {00BA} */            \
-            RND_STEP_RORX_0_7(g,h,a,b,c,d,e,f,_i+2)                        \
-    VPADDD   (XTMP0, XTMP0, XTMP4)  /* XTMP0 = {..., ..., W[1], W[0]} */   \
-            RND_STEP_RORX_0_8(g,h,a,b,c,d,e,f,_i+2)                        \
-                                                                           \
-            RND_STEP_RORX_1_1(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPSHUFD  (XTMP2, XTMP0, 0b01010000) /* XTMP2 = W[-2] {DDCC} */         \
-            RND_STEP_RORX_1_2(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPSRLD   (XTMP5, XTMP2, 10)       /* XTMP5 = W[-2] >> 10 {DDCC} */     \
-            RND_STEP_RORX_1_3(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPSRLQ   (XTMP3, XTMP2, 19)       /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */ \
-            RND_STEP_RORX_1_4(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPSRLQ   (XTMP2, XTMP2, 17)      /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */  \
-            RND_STEP_RORX_1_5(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPXOR    (XTMP2, XTMP2, XTMP3)                                         \
-            RND_STEP_RORX_1_6(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPXOR    (XTMP5, XTMP5, XTMP2)   /* XTMP5 = s1 {xDxC} */               \
-            RND_STEP_RORX_1_7(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPSHUFB  (XTMP5, XTMP5, SHUF_DC00) /* XTMP5 = s1 {DC00} */             \
-            RND_STEP_RORX_1_8(f,g,h,a,b,c,d,e,_i+3)                        \
-    VPADDD   (X0, XTMP5, XTMP0)      /* X0 = {W[3], W[2], W[1], W[0]} */
-
-#endif /* HAVE_INTEL_RORX */
-
-
-#define _W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) \
-    "# X0, X1, X2, X3 = W[0..15]\n\t"                  \
-    "vmovdqu	  (%%rax), %" #X0 "\n\t"               \
-    "vmovdqu	16(%%rax), %" #X1 "\n\t"               \
-    VPSHUFB(X0, X0, BYTE_FLIP_MASK)                    \
-    VPSHUFB(X1, X1, BYTE_FLIP_MASK)                    \
-    "vmovdqu	32(%%rax), %" #X2 "\n\t"               \
-    "vmovdqu	48(%%rax), %" #X3 "\n\t"               \
-    VPSHUFB(X2, X2, BYTE_FLIP_MASK)                    \
-    VPSHUFB(X3, X3, BYTE_FLIP_MASK)
-
-#define W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK) \
-       _W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK)
-
-
-#define _SET_W_K_XFER_4(i) \
-    "vpaddd	(" #i "*4)+ 0+%[K], %%xmm0, %%xmm4\n\t"  \
-    "vpaddd	(" #i "*4)+16+%[K], %%xmm1, %%xmm5\n\t"  \
-    "vmovdqu	%%xmm4,   (" WK ")\n\t"                  \
-    "vmovdqu	%%xmm5, 16(" WK ")\n\t"                  \
-    "vpaddd	(" #i "*4)+32+%[K], %%xmm2, %%xmm6\n\t"  \
-    "vpaddd	(" #i "*4)+48+%[K], %%xmm3, %%xmm7\n\t"  \
-    "vmovdqu	%%xmm6, 32(" WK ")\n\t"                  \
-    "vmovdqu	%%xmm7, 48(" WK ")\n\t"
-
-#define SET_W_K_XFER_4(i) \
-       _SET_W_K_XFER_4(i)
-
-
-static const ALIGN32 word64 mSHUF_00BA[] =
-    { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF }; /* shuffle xBxA -> 00BA */
-static const ALIGN32 word64 mSHUF_DC00[] =
-    { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 }; /* shuffle xDxC -> DC00 */
-static const ALIGN32 word64 mBYTE_FLIP_MASK[] =
-    { 0x0405060700010203, 0x0c0d0e0f08090a0b };
-
-#define _Init_Masks(mask1, mask2, mask3)       \
-    "vmovdqa	%[FLIP], %" #mask1 "\n\t"      \
-    "vmovdqa	%[SHUF00BA], %" #mask2 "\n\t"  \
-    "vmovdqa	%[SHUFDC00], %" #mask3 "\n\t"
-
-#define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \
-       _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-
-#define X0 %xmm0
-#define X1 %xmm1
-#define X2 %xmm2
-#define X3 %xmm3
-
-#define XTMP0 %xmm4
-#define XTMP1 %xmm5
-#define XTMP2 %xmm6
-#define XTMP3 %xmm7
-#define XTMP4 %xmm8
-#define XTMP5 %xmm9
-#define XFER  %xmm10
-
-#define SHUF_00BA   %xmm11 /* shuffle xBxA -> 00BA */
-#define SHUF_DC00   %xmm12 /* shuffle xDxC -> DC00 */
-#define BYTE_FLIP_MASK  %xmm13
-
-
-SHA256_NOINLINE static int Transform_Sha256_AVX1(wc_Sha256* sha256)
-{
-    __asm__ __volatile__ (
-
-        "subq	$64, %%rsp\n\t"
-
-        "leaq	32(%[sha256]), %%rax\n\t"
-    Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-    LOAD_DIGEST()
-
-    W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK)
-
-        "movl	%%r9d, " L4 "\n\t"
-        "movl	%%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_K_XFER_4(0)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(16)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(32)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(48)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    STORE_ADD_DIGEST()
-
-        "addq	$64, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_DC00[0]),
-          [sha256]   "r" (sha256),
-          [K]        "m" (K)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory"
-    );
-
-    return 0;
-}
-
-SHA256_NOINLINE static int Transform_Sha256_AVX1_Len(wc_Sha256* sha256,
-                                                     word32 len)
-{
-    __asm__ __volatile__ (
-
-        "subq	$64, %%rsp\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-    LOAD_DIGEST()
-
-        "# Start of loop processing a block\n"
-        "1:\n\t"
-
-    W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK)
-
-        "movl	%%r9d, " L4 "\n\t"
-        "movl	%%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_K_XFER_4(0)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(16)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(32)
-    MsgSched(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(48)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    ADD_DIGEST()
-
-        "addq	$64, %%rax\n\t"
-        "subl	$64, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "movq	%%rax, 120(%[sha256])\n\t"
-        "jnz	1b\n\t"
-
-        "addq	$64, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_DC00[0]),
-          [sha256]   "r" (sha256),
-          [len]      "r" (len),
-          [K]        "m" (K)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory"
-    );
-
-    return 0;
-}
-#endif  /* HAVE_INTEL_AVX1 */
-
-#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX)
-SHA256_NOINLINE static int Transform_Sha256_AVX1_RORX(wc_Sha256* sha256)
-{
-    __asm__ __volatile__ (
-
-        "subq	$64, %%rsp\n\t"
-
-    Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-        "leaq	32(%[sha256]), %%rax\n\t"
-    W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK)
-
-    LOAD_DIGEST()
-
-    SET_W_K_XFER_4(0)
-        "movl	%%r9d, " L4 "\n\t"
-        "rorx	$6, %%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(16)
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(32)
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(48)
-        "xorl	" L3 ", " L3 "\n\t"
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addl	" L3 ", %%r8d\n\t"
-
-    STORE_ADD_DIGEST()
-
-        "addq	$64, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_DC00[0]),
-          [sha256]   "r" (sha256),
-          [K]        "m" (K)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory"
-    );
-
-    return 0;
-}
-
-SHA256_NOINLINE static int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256,
-                                                          word32 len)
-{
-    __asm__ __volatile__ (
-
-        "subq	$64, %%rsp\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-    LOAD_DIGEST()
-
-        "# Start of loop processing a block\n"
-        "1:\n\t"
-
-    W_K_from_buff(X0, X1, X2, X3, BYTE_FLIP_MASK)
-
-    SET_W_K_XFER_4(0)
-        "movl	%%r9d, " L4 "\n\t"
-        "rorx	$6, %%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(16)
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(32)
-    MsgSched_RORX(X0, X1, X2, X3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_RORX(X1, X2, X3, X0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    MsgSched_RORX(X2, X3, X0, X1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    MsgSched_RORX(X3, X0, X1, X2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-
-    SET_W_K_XFER_4(48)
-        "xorl	" L3 ", " L3 "\n\t"
-        "xorl	" L2 ", " L2 "\n\t"
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  4)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  8)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 12)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addl	" L3 ", %%r8d\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    ADD_DIGEST()
-
-        "addq	$64, %%rax\n\t"
-        "subl	$64, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "movq	%%rax, 120(%[sha256])\n\t"
-        "jnz	1b\n\t"
-
-        "addq	$64, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_DC00[0]),
-          [sha256]   "r" (sha256),
-          [len]      "r" (len),
-          [K]        "m" (K)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory"
-    );
-
-    return 0;
-}
-#endif /* HAVE_INTEL_AVX2 && HAVE_INTEL_RORX */
-
-
-#if defined(HAVE_INTEL_AVX2)
-#define Y0 %ymm0
-#define Y1 %ymm1
-#define Y2 %ymm2
-#define Y3 %ymm3
-
-#define YTMP0 %ymm4
-#define YTMP1 %ymm5
-#define YTMP2 %ymm6
-#define YTMP3 %ymm7
-#define YTMP4 %ymm8
-#define YTMP5 %ymm9
-#define YXFER %ymm10
-
-#define SHUF_Y_00BA       %ymm11 /* shuffle xBxA -> 00BA */
-#define SHUF_Y_DC00       %ymm12 /* shuffle xDxC -> DC00 */
-#define BYTE_FLIP_Y_MASK  %ymm13
-
-#define YMM_REGS "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", \
-                 "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13"
-
-#define MsgSched_Y(Y0,Y1,Y2,Y3,a,b,c,d,e,f,g,h,_i)                            \
-            RND_STEP_0_1(a,b,c,d,e,f,g,h,_i)                                  \
-    VPALIGNR (YTMP1, Y1, Y0, 4)    /* YTMP1 = W[-15] */                       \
-    VPALIGNR (YTMP0, Y3, Y2, 4)    /* YTMP0 = W[-7] */                        \
-            RND_STEP_0_2(a,b,c,d,e,f,g,h,_i)                                  \
-            RND_STEP_0_3(a,b,c,d,e,f,g,h,_i)                                  \
-    VPSRLD   (YTMP2, YTMP1, 7)     /* YTMP2 = W[-15] >> 7 */                  \
-    VPSLLD   (YTMP3, YTMP1, 25)    /* YTEMP3 = W[-15] << (32-7) */            \
-            RND_STEP_0_4(a,b,c,d,e,f,g,h,_i)                                  \
-            RND_STEP_0_5(a,b,c,d,e,f,g,h,_i)                                  \
-    VPSRLD   (YTMP4, YTMP1, 18)    /* YTEMP4 = W[-15] >> 18 */                \
-    VPSLLD   (YTMP5, YTMP1, 14)    /* YTEMP5 = W[-15] << (32-18) */           \
-            RND_STEP_0_6(a,b,c,d,e,f,g,h,_i)                                  \
-            RND_STEP_0_7(a,b,c,d,e,f,g,h,_i)                                  \
-    VPOR     (YTMP2, YTMP3, YTMP2) /* YTMP2 = W[-15] >>> 7 */                 \
-    VPOR     (YTMP4, YTMP5, YTMP4) /* YTMP4 = W[-15] >>> 18 */                \
-            RND_STEP_0_8(a,b,c,d,e,f,g,h,_i)                                  \
-            RND_STEP_1_1(h,a,b,c,d,e,f,g,_i+1)                                \
-            RND_STEP_1_2(h,a,b,c,d,e,f,g,_i+1)                                \
-    VPSRLD   (YTMP5, YTMP1, 3)     /* YTMP4 = W[-15] >> 3 */                  \
-    VPXOR    (YTMP2, YTMP4, YTMP2) /* YTMP2 = W[-15] >>> 7 ^ W[-15] >>> 18 */ \
-            RND_STEP_1_3(h,a,b,c,d,e,f,g,_i+1)                                \
-            RND_STEP_1_4(h,a,b,c,d,e,f,g,_i+1)                                \
-    VPXOR    (YTMP1, YTMP5, YTMP2)  /* YTMP1 = s0 */                          \
-    VPSHUFD  (YTMP2, Y3, 0b11111010)  /* YTMP2 = W[-2] {BBAA}*/               \
-            RND_STEP_1_5(h,a,b,c,d,e,f,g,_i+1)                                \
-            RND_STEP_1_6(h,a,b,c,d,e,f,g,_i+1)                                \
-    VPSRLD   (YTMP4, YTMP2, 10)      /* YTMP4 = W[-2] >> 10 {BBAA} */         \
-    VPSRLQ   (YTMP3, YTMP2, 19)      /* YTMP3 = W[-2] MY_ROR 19 {xBxA} */     \
-            RND_STEP_1_7(h,a,b,c,d,e,f,g,_i+1)                                \
-            RND_STEP_1_8(h,a,b,c,d,e,f,g,_i+1)                                \
-            RND_STEP_0_1(g,h,a,b,c,d,e,f,_i+2)                                \
-    VPSRLQ   (YTMP2, YTMP2, 17)      /* YTMP2 = W[-2] MY_ROR 17 {xBxA} */     \
-    VPADDD   (YTMP0, YTMP0, Y0)                                               \
-            RND_STEP_0_2(g,h,a,b,c,d,e,f,_i+2)                                \
-            RND_STEP_0_3(g,h,a,b,c,d,e,f,_i+2)                                \
-            RND_STEP_0_4(g,h,a,b,c,d,e,f,_i+2)                                \
-    VPXOR    (YTMP2, YTMP3, YTMP2)                                            \
-    VPADDD   (YTMP0, YTMP0, YTMP1)  /* YTMP0 = W[-16] + W[-7] + s0 */         \
-            RND_STEP_0_5(g,h,a,b,c,d,e,f,_i+2)                                \
-    VPXOR    (YTMP4, YTMP4, YTMP2)   /* YTMP4 = s1 {xBxA} */                  \
-            RND_STEP_0_6(g,h,a,b,c,d,e,f,_i+2)                                \
-    VPSHUFB  (YTMP4, YTMP4, SHUF_Y_00BA)  /* YTMP4 = s1 {00BA} */             \
-            RND_STEP_0_7(g,h,a,b,c,d,e,f,_i+2)                                \
-    VPADDD   (YTMP0, YTMP0, YTMP4)  /* YTMP0 = {..., ..., W[1], W[0]} */      \
-            RND_STEP_0_8(g,h,a,b,c,d,e,f,_i+2)                                \
-            RND_STEP_1_1(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPSHUFD  (YTMP2, YTMP0, 0b01010000) /* YTMP2 = W[-2] {DDCC} */            \
-            RND_STEP_1_2(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPSRLQ   (YTMP4, YTMP2, 17)      /* YTMP4 = W[-2] MY_ROR 17 {xDxC} */     \
-    VPSRLQ   (YTMP3, YTMP2, 19)       /* YTMP3 = W[-2] MY_ROR 19 {xDxC} */    \
-            RND_STEP_1_3(f,g,h,a,b,c,d,e,_i+3)                                \
-            RND_STEP_1_4(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPSRLD   (YTMP5, YTMP2, 10)       /* YTMP5 = W[-2] >> 10 {DDCC} */        \
-    VPXOR    (YTMP4, YTMP3, YTMP4)                                            \
-            RND_STEP_1_5(f,g,h,a,b,c,d,e,_i+3)                                \
-            RND_STEP_1_6(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPXOR    (YTMP5, YTMP4, YTMP5)   /* YTMP5 = s1 {xDxC} */                  \
-            RND_STEP_1_7(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPSHUFB  (YTMP5, YTMP5, SHUF_Y_DC00) /* YTMP5 = s1 {DC00} */              \
-            RND_STEP_1_8(f,g,h,a,b,c,d,e,_i+3)                                \
-    VPADDD   (Y0, YTMP5, YTMP0)      /* Y0 = {W[3], W[2], W[1], W[0]} */
-
-#if defined(HAVE_INTEL_RORX)
-
-#define MsgSched_Y_RORX(Y0,Y1,Y2,Y3,a,b,c,d,e,f,g,h,_i)                       \
-            RND_STEP_RORX_0_1(a,b,c,d,e,f,g,h,_i)                             \
-    VPALIGNR (YTMP1, Y1, Y0, 4)    /* YTMP1 = W[-15] */                       \
-            RND_STEP_RORX_0_2(a,b,c,d,e,f,g,h,_i)                             \
-    VPALIGNR (YTMP0, Y3, Y2, 4)    /* YTMP0 = W[-7] */                        \
-            RND_STEP_RORX_0_3(a,b,c,d,e,f,g,h,_i)                             \
-    VPSRLD   (YTMP2, YTMP1, 7)     /* YTMP2 = W[-15] >> 7 */                  \
-            RND_STEP_RORX_0_4(a,b,c,d,e,f,g,h,_i)                             \
-    VPSLLD   (YTMP3, YTMP1, 25)    /* YTEMP3 = W[-15] << (32-7) */            \
-            RND_STEP_RORX_0_5(a,b,c,d,e,f,g,h,_i)                             \
-    VPSRLD   (YTMP4, YTMP1, 18)    /* YTEMP4 = W[-15] >> 18 */                \
-            RND_STEP_RORX_0_6(a,b,c,d,e,f,g,h,_i)                             \
-    VPSLLD   (YTMP5, YTMP1, 14)    /* YTEMP5 = W[-15] << (32-18) */           \
-            RND_STEP_RORX_0_7(a,b,c,d,e,f,g,h,_i)                             \
-    VPOR     (YTMP2, YTMP2, YTMP3) /* YTMP2 = W[-15] >>> 7 */                 \
-            RND_STEP_RORX_0_8(a,b,c,d,e,f,g,h,_i)                             \
-    VPOR     (YTMP4, YTMP4, YTMP5) /* YTMP4 = W[-15] >>> 18 */                \
-            RND_STEP_RORX_1_1(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPSRLD   (YTMP5, YTMP1, 3)     /* YTMP4 = W[-15] >> 3 */                  \
-            RND_STEP_RORX_1_2(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPXOR    (YTMP2, YTMP2, YTMP4) /* YTMP2 = W[-15] >>> 7 ^ W[-15] >>> 18 */ \
-            RND_STEP_RORX_1_3(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPSHUFD  (YTMP3, Y3, 0b11111010)  /* YTMP2 = W[-2] {BBAA}*/               \
-            RND_STEP_RORX_1_4(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPXOR    (YTMP1, YTMP5, YTMP2)  /* YTMP1 = s0 */                          \
-            RND_STEP_RORX_1_5(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPSRLD   (YTMP4, YTMP3, 10)      /* YTMP4 = W[-2] >> 10 {BBAA} */         \
-            RND_STEP_RORX_1_6(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPSRLQ   (YTMP2, YTMP3, 19)      /* YTMP3 = W[-2] MY_ROR 19 {xBxA} */     \
-            RND_STEP_RORX_1_7(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPSRLQ   (YTMP3, YTMP3, 17)      /* YTMP2 = W[-2] MY_ROR 17 {xBxA} */     \
-            RND_STEP_RORX_1_8(h,a,b,c,d,e,f,g,_i+1)                           \
-    VPADDD   (YTMP0, YTMP0, Y0)                                               \
-            RND_STEP_RORX_0_1(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPXOR    (YTMP2, YTMP2, YTMP3)                                            \
-            RND_STEP_RORX_0_2(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPXOR    (YTMP4, YTMP4, YTMP2)   /* YTMP4 = s1 {xBxA} */                  \
-            RND_STEP_RORX_0_3(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPADDD   (YTMP0, YTMP0, YTMP1)  /* YTMP0 = W[-16] + W[-7] + s0 */         \
-            RND_STEP_RORX_0_4(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPSHUFB  (YTMP4, YTMP4, SHUF_Y_00BA)  /* YTMP4 = s1 {00BA} */             \
-            RND_STEP_RORX_0_5(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPADDD   (YTMP0, YTMP0, YTMP4)  /* YTMP0 = {..., ..., W[1], W[0]} */      \
-            RND_STEP_RORX_0_6(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPSHUFD  (YTMP2, YTMP0, 0b01010000) /* YTMP2 = W[-2] {DDCC} */            \
-            RND_STEP_RORX_0_7(g,h,a,b,c,d,e,f,_i+2)                           \
-            RND_STEP_RORX_0_8(g,h,a,b,c,d,e,f,_i+2)                           \
-    VPSRLQ   (YTMP4, YTMP2, 17)      /* YTMP4 = W[-2] MY_ROR 17 {xDxC} */     \
-            RND_STEP_RORX_1_1(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPSRLQ   (YTMP3, YTMP2, 19)       /* YTMP3 = W[-2] MY_ROR 19 {xDxC} */    \
-            RND_STEP_RORX_1_2(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPSRLD   (YTMP5, YTMP2, 10)       /* YTMP5 = W[-2] >> 10 {DDCC} */        \
-            RND_STEP_RORX_1_3(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPXOR    (YTMP4, YTMP4, YTMP3)                                            \
-            RND_STEP_RORX_1_4(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPXOR    (YTMP5, YTMP5, YTMP4)   /* YTMP5 = s1 {xDxC} */                  \
-            RND_STEP_RORX_1_5(f,g,h,a,b,c,d,e,_i+3)                           \
-            RND_STEP_RORX_1_6(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPSHUFB  (YTMP5, YTMP5, SHUF_Y_DC00) /* YTMP5 = s1 {DC00} */              \
-            RND_STEP_RORX_1_7(f,g,h,a,b,c,d,e,_i+3)                           \
-            RND_STEP_RORX_1_8(f,g,h,a,b,c,d,e,_i+3)                           \
-    VPADDD   (Y0, YTMP5, YTMP0)      /* Y0 = {W[3], W[2], W[1], W[0]} */      \
-
-#endif /* HAVE_INTEL_RORX */
-
-#define _VINSERTI128(op1,op2,op3,op4) \
-    "vinserti128	$" #op4 ", %" #op3 ", %" #op2 ", %" #op1 "\n\t"
-#define VINSERTI128(op1,op2,op3,op4)  \
-       _VINSERTI128(op1,op2,op3,op4)
-
-
-#define _LOAD_W_K_LOW(BYTE_FLIP_MASK, reg)   \
-    "# X0, X1, X2, X3 = W[0..15]\n\t"        \
-    "vmovdqu	  (%%" #reg "), %%xmm0\n\t"  \
-    "vmovdqu	16(%%" #reg "), %%xmm1\n\t"  \
-    VPSHUFB(X0, X0, BYTE_FLIP_MASK)          \
-    VPSHUFB(X1, X1, BYTE_FLIP_MASK)          \
-    "vmovdqu	32(%%" #reg "), %%xmm2\n\t"  \
-    "vmovdqu	48(%%" #reg "), %%xmm3\n\t"  \
-    VPSHUFB(X2, X2, BYTE_FLIP_MASK)          \
-    VPSHUFB(X3, X3, BYTE_FLIP_MASK)
-
-#define LOAD_W_K_LOW(BYTE_FLIP_MASK, reg) \
-       _LOAD_W_K_LOW(BYTE_FLIP_MASK, reg)
-
-
-#define _LOAD_W_K(BYTE_FLIP_Y_MASK, reg)      \
-    "# X0, X1, X2, X3 = W[0..15]\n\t"         \
-    "vmovdqu	   (%%" #reg "), %%xmm0\n\t"  \
-    "vmovdqu	 16(%%" #reg "), %%xmm1\n\t"  \
-    "vmovdqu	 64(%%" #reg "), %%xmm4\n\t"  \
-    "vmovdqu	 80(%%" #reg "), %%xmm5\n\t"  \
-    VINSERTI128(Y0, Y0, XTMP0, 1)             \
-    VINSERTI128(Y1, Y1, XTMP1, 1)             \
-    VPSHUFB(Y0, Y0, BYTE_FLIP_Y_MASK)         \
-    VPSHUFB(Y1, Y1, BYTE_FLIP_Y_MASK)         \
-    "vmovdqu	 32(%%" #reg "), %%xmm2\n\t"  \
-    "vmovdqu	 48(%%" #reg "), %%xmm3\n\t"  \
-    "vmovdqu	 96(%%" #reg "), %%xmm6\n\t"  \
-    "vmovdqu	112(%%" #reg "), %%xmm7\n\t"  \
-    VINSERTI128(Y2, Y2, XTMP2, 1)             \
-    VINSERTI128(Y3, Y3, XTMP3, 1)             \
-    VPSHUFB(Y2, Y2, BYTE_FLIP_Y_MASK)         \
-    VPSHUFB(Y3, Y3, BYTE_FLIP_Y_MASK)
-
-#define LOAD_W_K(BYTE_FLIP_Y_MASK, reg) \
-       _LOAD_W_K(BYTE_FLIP_Y_MASK, reg)
-
-
-#define _SET_W_Y_4(i)  \
-    "vpaddd	(" #i "*8)+ 0+%[K], %%ymm0, %%ymm4\n\t" \
-    "vpaddd	(" #i "*8)+32+%[K], %%ymm1, %%ymm5\n\t" \
-    "vmovdqu	%%ymm4, (" #i "*8)+ 0(" WK ")\n\t"      \
-    "vmovdqu	%%ymm5, (" #i "*8)+32(" WK ")\n\t"      \
-    "vpaddd	(" #i "*8)+64+%[K], %%ymm2, %%ymm4\n\t" \
-    "vpaddd	(" #i "*8)+96+%[K], %%ymm3, %%ymm5\n\t" \
-    "vmovdqu	%%ymm4, (" #i "*8)+64(" WK ")\n\t"      \
-    "vmovdqu	%%ymm5, (" #i "*8)+96(" WK ")\n\t"
-
-#define SET_W_Y_4(i) \
-       _SET_W_Y_4(i)
-
-
-static const ALIGN32 word64 mSHUF_Y_00BA[] =
-    { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF,
-      0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF }; /* shuffle xBxA -> 00BA */
-static const ALIGN32 word64 mSHUF_Y_DC00[] =
-    { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100,
-      0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 }; /* shuffle xDxC -> DC00 */
-static const ALIGN32 word64 mBYTE_FLIP_Y_MASK[] =
-    { 0x0405060700010203, 0x0c0d0e0f08090a0b,
-      0x0405060700010203, 0x0c0d0e0f08090a0b };
-
-#define _INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \
-    "vmovdqa	%[FLIP], %" #BYTE_FLIP_MASK "\n\t"          \
-    "vmovdqa	%[SHUF00BA], %" #SHUF_00BA "\n\t"           \
-    "vmovdqa	%[SHUFDC00], %" #SHUF_DC00 "\n\t"
-
-#define INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) \
-       _INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)
-
-static const ALIGN32 word32 K256[128] = {
-    0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L,
-    0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L,
-    0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L,
-    0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L,
-    0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L,
-    0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L,
-    0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, 0xC19BF174L,
-    0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, 0xC19BF174L,
-    0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
-    0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
-    0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL,
-    0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL,
-    0x983E5152L, 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L,
-    0x983E5152L, 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L,
-    0xC6E00BF3L, 0xD5A79147L, 0x06CA6351L, 0x14292967L,
-    0xC6E00BF3L, 0xD5A79147L, 0x06CA6351L, 0x14292967L,
-    0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, 0x53380D13L,
-    0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, 0x53380D13L,
-    0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
-    0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
-    0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L,
-    0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L,
-    0xD192E819L, 0xD6990624L, 0xF40E3585L, 0x106AA070L,
-    0xD192E819L, 0xD6990624L, 0xF40E3585L, 0x106AA070L,
-    0x19A4C116L, 0x1E376C08L, 0x2748774CL, 0x34B0BCB5L,
-    0x19A4C116L, 0x1E376C08L, 0x2748774CL, 0x34B0BCB5L,
-    0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, 0x682E6FF3L,
-    0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, 0x682E6FF3L,
-    0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
-    0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
-    0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L,
-    0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
-};
-
-SHA256_NOINLINE static int Transform_Sha256_AVX2(wc_Sha256* sha256)
-{
-    __asm__ __volatile__ (
-
-        "subq	$512, %%rsp\n\t"
-        "leaq	32(%[sha256]), %%rax\n\t"
-
-    INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_Y_00BA, SHUF_Y_DC00)
-    LOAD_DIGEST()
-
-    LOAD_W_K_LOW(BYTE_FLIP_MASK, rax)
-
-        "movl	%%r9d, " L4 "\n\t"
-        "movl	%%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_Y_4(0)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  8)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24)
-
-    SET_W_Y_4(16)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56)
-
-    SET_W_Y_4(32)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88)
-
-    SET_W_Y_4(48)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  96)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120)
-
-    STORE_ADD_DIGEST()
-
-        "addq	$512, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_Y_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_Y_DC00[0]),
-          [sha256]   "r" (sha256),
-          [K]        "m" (K256)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory"
-    );
-
-    return 0;
-}
-
-SHA256_NOINLINE static int Transform_Sha256_AVX2_Len(wc_Sha256* sha256,
-                                                     word32 len)
-{
-    if ((len & WC_SHA256_BLOCK_SIZE) != 0) {
-        XMEMCPY(sha256->buffer, sha256->data, WC_SHA256_BLOCK_SIZE);
-        Transform_Sha256_AVX2(sha256);
-        sha256->data += WC_SHA256_BLOCK_SIZE;
-        len -= WC_SHA256_BLOCK_SIZE;
-        if (len == 0)
-            return 0;
-    }
-
-    __asm__ __volatile__ (
-
-        "subq	$512, %%rsp\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    INIT_MASKS_Y(BYTE_FLIP_Y_MASK, SHUF_Y_00BA, SHUF_Y_DC00)
-    LOAD_DIGEST()
-
-        "# Start of loop processing two blocks\n"
-        "1:\n\t"
-
-    LOAD_W_K(BYTE_FLIP_Y_MASK, rax)
-
-        "movl	%%r9d, " L4 "\n\t"
-        "movl	%%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_Y_4(0)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  8)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24)
-
-    SET_W_Y_4(16)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56)
-
-    SET_W_Y_4(32)
-    MsgSched_Y(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64)
-    MsgSched_Y(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72)
-    MsgSched_Y(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80)
-    MsgSched_Y(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88)
-
-    SET_W_Y_4(48)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  96)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120)
-
-    ADD_DIGEST()
-    STORE_DIGEST()
-
-        "movl	%%r9d, " L4 "\n\t"
-        "movl	%%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,   4)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  12)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  20)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  28)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  36)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  44)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  52)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  60)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  68)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  76)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  84)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  92)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 100)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 108)
-    RND_ALL_4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 116)
-    RND_ALL_4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 124)
-
-    ADD_DIGEST()
-
-        "movq	120(%[sha256]), %%rax\n\t"
-        "addq	$128, %%rax\n\t"
-        "subl	$128, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "movq	%%rax, 120(%[sha256])\n\t"
-        "jnz	1b\n\t"
-
-        "addq	$512, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_Y_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_Y_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_Y_DC00[0]),
-          [sha256]   "r" (sha256),
-          [len]      "r" (len),
-          [K]        "m" (K256)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory"
-    );
-
-    return 0;
-}
-
-#if defined(HAVE_INTEL_RORX)
-SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX(wc_Sha256* sha256)
-{
-    __asm__ __volatile__ (
-
-        "subq	$512, %%rsp\n\t"
-        "leaq	32(%[sha256]), %%rax\n\t"
-
-    INIT_MASKS_Y(BYTE_FLIP_MASK, SHUF_Y_00BA, SHUF_Y_DC00)
-    LOAD_W_K_LOW(BYTE_FLIP_MASK, rax)
-
-    LOAD_DIGEST()
-
-        "movl	%%r9d, " L4 "\n\t"
-        "rorx	$6, %%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_Y_4(0)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  8)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24)
-
-    SET_W_Y_4(16)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56)
-
-    SET_W_Y_4(32)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88)
-
-    SET_W_Y_4(48)
-        "xorl	" L3 ", " L3 "\n\t"
-        "xorl	" L2 ", " L2 "\n\t"
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  96)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addl	" L3 ", %%r8d\n\t"
-
-    STORE_ADD_DIGEST()
-
-        "addq	$512, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_Y_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_Y_DC00[0]),
-          [sha256]   "r" (sha256),
-          [K]        "m" (K256)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory"
-    );
-
-    return 0;
-}
-
-SHA256_NOINLINE static int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
-                                                          word32 len)
-{
-    if ((len & WC_SHA256_BLOCK_SIZE) != 0) {
-        XMEMCPY(sha256->buffer, sha256->data, WC_SHA256_BLOCK_SIZE);
-        Transform_Sha256_AVX2_RORX(sha256);
-        sha256->data += WC_SHA256_BLOCK_SIZE;
-        len -= WC_SHA256_BLOCK_SIZE;
-        if (len == 0)
-            return 0;
-    }
-
-    __asm__ __volatile__ (
-
-        "subq	$512, %%rsp\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    INIT_MASKS_Y(BYTE_FLIP_Y_MASK, SHUF_Y_00BA, SHUF_Y_DC00)
-    LOAD_DIGEST()
-
-        "# Start of loop processing two blocks\n"
-        "1:\n\t"
-
-    LOAD_W_K(BYTE_FLIP_Y_MASK, rax)
-
-        "movl	%%r9d, " L4 "\n\t"
-        "rorx	$6, %%r12d, " L1 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    SET_W_Y_4(0)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  0)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  8)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 16)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 24)
-
-    SET_W_Y_4(16)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 32)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 40)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 48)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 56)
-
-    SET_W_Y_4(32)
-    MsgSched_Y_RORX(Y0, Y1, Y2, Y3, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 64)
-    MsgSched_Y_RORX(Y1, Y2, Y3, Y0, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 72)
-    MsgSched_Y_RORX(Y2, Y3, Y0, Y1, S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 80)
-    MsgSched_Y_RORX(Y3, Y0, Y1, Y2, S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 88)
-
-    SET_W_Y_4(48)
-        "xorl	" L3 ", " L3 "\n\t"
-        "xorl	" L2 ", " L2 "\n\t"
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  96)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 104)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 112)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 120)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addl	" L3 ", %%r8d\n\t"
-        "xorl	" L2 ", " L2 "\n\t"
-
-    ADD_DIGEST()
-    STORE_DIGEST()
-
-        "movl	%%r9d, " L4 "\n\t"
-        "xorl	" L3 ", " L3 "\n\t"
-        "xorl	%%r10d, " L4 "\n\t"
-
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,   4)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  12)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  20)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  28)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  36)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  44)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  52)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  60)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  68)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  76)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,  84)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3,  92)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 100)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 108)
-    RND_RORX_X4(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7, 116)
-    RND_RORX_X4(S_4, S_5, S_6, S_7, S_0, S_1, S_2, S_3, 124)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addl	" L3 ", %%r8d\n\t"
-        "movq	120(%[sha256]), %%rax\n\t"
-
-    ADD_DIGEST()
-
-        "addq	$128, %%rax\n\t"
-        "subl	$128, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "movq	%%rax, 120(%[sha256])\n\t"
-        "jnz	1b\n\t"
-
-        "addq	$512, %%rsp\n\t"
-
-        :
-        : [FLIP]     "m" (mBYTE_FLIP_Y_MASK[0]),
-          [SHUF00BA] "m" (mSHUF_Y_00BA[0]),
-          [SHUFDC00] "m" (mSHUF_Y_DC00[0]),
-          [sha256]   "r" (sha256),
-          [len]      "r" (len),
-          [K]        "m" (K256)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory"
-    );
-
-    return 0;
-}
-#endif  /* HAVE_INTEL_RORX */
-#endif  /* HAVE_INTEL_AVX2 */
-
-
-#ifdef WOLFSSL_SHA224
-
-#ifdef STM32_HASH_SHA2
-
-    /* Supports CubeMX HAL or Standard Peripheral Library */
-
-    int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
-    {
-        if (sha224 == NULL)
-            return BAD_FUNC_ARG;
-
-        (void)devId;
-        (void)heap;
-
-        wc_Stm32_Hash_Init(&sha224->stmCtx);
-        return 0;
-    }
-
-    int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
-    {
-        int ret = 0;
-
-        if (sha224 == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Update(&sha224->stmCtx,
-                HASH_AlgoSelection_SHA224, data, len);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-        return ret;
-    }
-
-    int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
-    {
-        int ret = 0;
-
-        if (sha224 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        ret = wolfSSL_CryptHwMutexLock();
-        if (ret == 0) {
-            ret = wc_Stm32_Hash_Final(&sha224->stmCtx,
-                HASH_AlgoSelection_SHA224, hash, WC_SHA224_DIGEST_SIZE);
-            wolfSSL_CryptHwMutexUnLock();
-        }
-
-        (void)wc_InitSha224(sha224); /* reset state */
-
-        return ret;
-    }
-
-#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
-#else
-
-    #define NEED_SOFT_SHA224
-
-
-    static int InitSha224(wc_Sha224* sha224)
-    {
-        int ret = 0;
-
-        if (sha224 == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-        sha224->digest[0] = 0xc1059ed8;
-        sha224->digest[1] = 0x367cd507;
-        sha224->digest[2] = 0x3070dd17;
-        sha224->digest[3] = 0xf70e5939;
-        sha224->digest[4] = 0xffc00b31;
-        sha224->digest[5] = 0x68581511;
-        sha224->digest[6] = 0x64f98fa7;
-        sha224->digest[7] = 0xbefa4fa4;
-
-        sha224->buffLen = 0;
-        sha224->loLen   = 0;
-        sha224->hiLen   = 0;
-
-    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
-        /* choose best Transform function under this runtime environment */
-        Sha256_SetTransform();
-    #endif
-
-        return ret;
-    }
-
-#endif
-
-#ifdef NEED_SOFT_SHA224
-    int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
-    {
-        int ret = 0;
-
-        if (sha224 == NULL)
-            return BAD_FUNC_ARG;
-
-        sha224->heap = heap;
-
-        ret = InitSha224(sha224);
-        if (ret != 0)
-            return ret;
-
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-        sha224->W = NULL;
-    #endif
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
-        ret = wolfAsync_DevCtxInit(&sha224->asyncDev,
-                            WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId);
-    #else
-        (void)devId;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        return ret;
-    }
-
-    int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
-    {
-        int ret;
-
-        if (sha224 == NULL || (data == NULL && len > 0)) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
-        if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
-        #if defined(HAVE_INTEL_QA)
-            return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len);
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        ret = Sha256Update((wc_Sha256*)sha224, data, len);
-
-        return ret;
-    }
-
-    int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
-    {
-        int ret;
-
-        if (sha224 == NULL || hash == NULL) {
-            return BAD_FUNC_ARG;
-        }
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
-        if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
-        #if defined(HAVE_INTEL_QA)
-            return IntelQaSymSha224(&sha224->asyncDev, hash, NULL,
-                                            WC_SHA224_DIGEST_SIZE);
-        #endif
-        }
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        ret = Sha256Final((wc_Sha256*)sha224);
-        if (ret != 0)
-            return ret;
-
-    #if defined(LITTLE_ENDIAN_ORDER)
-        ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE);
-    #endif
-        XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE);
-
-        return InitSha224(sha224);  /* reset state */
-    }
-#endif /* end of SHA224 software implementation */
-
-    int wc_InitSha224(wc_Sha224* sha224)
-    {
-        return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
-    }
-
-    void wc_Sha224Free(wc_Sha224* sha224)
-    {
-        if (sha224 == NULL)
-            return;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    if (sha224->W != NULL) {
-        XFREE(sha224->W, NULL, DYNAMIC_TYPE_RNG);
-        sha224->W = NULL;
-    }
-#endif
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
-        wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224);
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-    }
-#endif /* WOLFSSL_SHA224 */
-
-
-int wc_InitSha256(wc_Sha256* sha256)
-{
-    return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
-}
-
-void wc_Sha256Free(wc_Sha256* sha256)
-{
-    if (sha256 == NULL)
-        return;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    if (sha256->W != NULL) {
-        XFREE(sha256->W, NULL, DYNAMIC_TYPE_RNG);
-        sha256->W = NULL;
-    }
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
-    wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-#endif /* !WOLFSSL_TI_HASH */
-#endif /* HAVE_FIPS */
-
-
-#ifndef WOLFSSL_TI_HASH
-#ifdef WOLFSSL_SHA224
-    int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash)
-    {
-        int ret;
-        wc_Sha224 tmpSha224;
-
-        if (sha224 == NULL || hash == NULL)
-            return BAD_FUNC_ARG;
-
-        ret = wc_Sha224Copy(sha224, &tmpSha224);
-        if (ret == 0) {
-            ret = wc_Sha224Final(&tmpSha224, hash);
-            wc_Sha224Free(&tmpSha224);
-        }
-        return ret;
-    }
-    int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
-    {
-        int ret = 0;
-
-        if (src == NULL || dst == NULL)
-            return BAD_FUNC_ARG;
-
-        XMEMCPY(dst, src, sizeof(wc_Sha224));
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-        dst->W = NULL;
-    #endif
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-    #endif
-
-        return ret;
-    }
-#endif /* WOLFSSL_SHA224 */
-
-int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
-{
-    int ret;
-    wc_Sha256 tmpSha256;
-
-    if (sha256 == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_Sha256Copy(sha256, &tmpSha256);
-    if (ret == 0) {
-        ret = wc_Sha256Final(&tmpSha256, hash);
-        wc_Sha256Free(&tmpSha256);
-    }
-    return ret;
-}
-int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Sha256));
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    dst->W = NULL;
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-#ifdef WOLFSSL_PIC32MZ_HASH
-    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
-#endif
-
-    return ret;
-}
-#endif /* !WOLFSSL_TI_HASH */
-
-#endif /* NO_SHA256 */
-
--- a/wolfcrypt/src/sha3.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1101 +0,0 @@
-/* sha3.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_XILINX_CRYPT)
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$l")
-        #pragma const_seg(".fipsB$l")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/sha3.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifdef WOLFSSL_SHA3_SMALL
-/* Rotate a 64-bit value left.
- *
- * a  Number to rotate left.
- * r  Number od bits to rotate left.
- * returns the rotated number.
- */
-#define ROTL64(a, n)    (((a)<<(n))|((a)>>(64-(n))))
-
-/* An array of values to XOR for block operation. */
-static const word64 hash_keccak_r[24] =
-{
-    0x0000000000000001UL, 0x0000000000008082UL,
-    0x800000000000808aUL, 0x8000000080008000UL,
-    0x000000000000808bUL, 0x0000000080000001UL,
-    0x8000000080008081UL, 0x8000000000008009UL,
-    0x000000000000008aUL, 0x0000000000000088UL,
-    0x0000000080008009UL, 0x000000008000000aUL,
-    0x000000008000808bUL, 0x800000000000008bUL,
-    0x8000000000008089UL, 0x8000000000008003UL,
-    0x8000000000008002UL, 0x8000000000000080UL,
-    0x000000000000800aUL, 0x800000008000000aUL,
-    0x8000000080008081UL, 0x8000000000008080UL,
-    0x0000000080000001UL, 0x8000000080008008UL
-};
-
-/* Indeces used in swap and rotate operation. */
-#define K_I_0   10
-#define K_I_1    7
-#define K_I_2   11
-#define K_I_3   17
-#define K_I_4   18
-#define K_I_5    3
-#define K_I_6    5
-#define K_I_7   16
-#define K_I_8    8
-#define K_I_9   21
-#define K_I_10  24
-#define K_I_11   4
-#define K_I_12  15
-#define K_I_13  23
-#define K_I_14  19
-#define K_I_15  13
-#define K_I_16  12
-#define K_I_17   2
-#define K_I_18  20
-#define K_I_19  14
-#define K_I_20  22
-#define K_I_21   9
-#define K_I_22   6
-#define K_I_23   1
-
-/* Number of bits to rotate in swap and rotate operation. */
-#define K_R_0    1
-#define K_R_1    3
-#define K_R_2    6
-#define K_R_3   10
-#define K_R_4   15
-#define K_R_5   21
-#define K_R_6   28
-#define K_R_7   36
-#define K_R_8   45
-#define K_R_9   55
-#define K_R_10   2
-#define K_R_11  14
-#define K_R_12  27
-#define K_R_13  41
-#define K_R_14  56
-#define K_R_15   8
-#define K_R_16  25
-#define K_R_17  43
-#define K_R_18  62
-#define K_R_19  18
-#define K_R_20  39
-#define K_R_21  61
-#define K_R_22  20
-#define K_R_23  44
-
-/* Swap and rotate left operation.
- *
- * s   The state.
- * t1  Temporary value.
- * t2  Second temporary value.
- * i   The index of the loop.
- */
-#define SWAP_ROTL(s, t1, t2, i)                                         \
-do                                                                      \
-{                                                                       \
-    t2 = s[K_I_##i]; s[K_I_##i] = ROTL64(t1, K_R_##i);                  \
-}                                                                       \
-while (0)
-
-/* Mix the XOR of the column's values into each number by column.
- *
- * s  The state.
- * b  Temporary array of XORed column values.
- * x  The index of the column.
- * t  Temporary variable.
- */
-#define COL_MIX(s, b, x, t)                                             \
-do                                                                      \
-{                                                                       \
-    for (x = 0; x < 5; x++)                                             \
-        b[x] = s[x + 0] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; \
-    for (x = 0; x < 5; x++)                                             \
-    {                                                                   \
-        t = b[(x + 4) % 5] ^ ROTL64(b[(x + 1) % 5], 1);                 \
-        s[x +  0] ^= t;                                                 \
-        s[x +  5] ^= t;                                                 \
-        s[x + 10] ^= t;                                                 \
-        s[x + 15] ^= t;                                                 \
-        s[x + 20] ^= t;                                                 \
-    }                                                                   \
-}                                                                       \
-while (0)
-
-#ifdef SHA3_BY_SPEC
-/* Mix the row values.
- * BMI1 has ANDN instruction ((~a) & b) - Haswell and above.
- *
- * s   The state.
- * b   Temporary array of XORed row values.
- * y   The index of the row to work on.
- * x   The index of the column.
- * t0  Temporary variable.
- * t1  Temporary variable.
- */
-#define ROW_MIX(s, b, y, x, t0, t1)                                     \
-do                                                                      \
-{                                                                       \
-    for (y = 0; y < 5; y++)                                             \
-    {                                                                   \
-        for (x = 0; x < 5; x++)                                         \
-            b[x] = s[y * 5 + x];                                        \
-        for (x = 0; x < 5; x++)                                         \
-           s[y * 5 + x] = b[x] ^ (~b[(x + 1) % 5] & b[(x + 2) % 5]);    \
-    }                                                                   \
-}                                                                       \
-while (0)
-#else
-/* Mix the row values.
- * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c)
- *
- * s   The state.
- * b   Temporary array of XORed row values.
- * y   The index of the row to work on.
- * x   The index of the column.
- * t0  Temporary variable.
- * t1  Temporary variable.
- */
-#define ROW_MIX(s, b, y, x, t12, t34)                                   \
-do                                                                      \
-{                                                                       \
-    for (y = 0; y < 5; y++)                                             \
-    {                                                                   \
-        for (x = 0; x < 5; x++)                                         \
-            b[x] = s[y * 5 + x];                                        \
-        t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]);                       \
-        s[y * 5 + 0] = b[0] ^ (b[2] &  t12);                            \
-        s[y * 5 + 1] =  t12 ^ (b[2] | b[3]);                            \
-        s[y * 5 + 2] = b[2] ^ (b[4] &  t34);                            \
-        s[y * 5 + 3] =  t34 ^ (b[4] | b[0]);                            \
-        s[y * 5 + 4] = b[4] ^ (b[1] & (b[0] ^ b[1]));                   \
-    }                                                                   \
-}                                                                       \
-while (0)
-#endif /* SHA3_BY_SPEC */
-
-/* The block operation performed on the state.
- *
- * s  The state.
- */
-static void BlockSha3(word64 *s)
-{
-    byte i, x, y;
-    word64 t0, t1;
-    word64 b[5];
-
-    for (i = 0; i < 24; i++)
-    {
-        COL_MIX(s, b, x, t0);
-
-        t0 = s[1];
-        SWAP_ROTL(s, t0, t1,  0);
-        SWAP_ROTL(s, t1, t0,  1);
-        SWAP_ROTL(s, t0, t1,  2);
-        SWAP_ROTL(s, t1, t0,  3);
-        SWAP_ROTL(s, t0, t1,  4);
-        SWAP_ROTL(s, t1, t0,  5);
-        SWAP_ROTL(s, t0, t1,  6);
-        SWAP_ROTL(s, t1, t0,  7);
-        SWAP_ROTL(s, t0, t1,  8);
-        SWAP_ROTL(s, t1, t0,  9);
-        SWAP_ROTL(s, t0, t1, 10);
-        SWAP_ROTL(s, t1, t0, 11);
-        SWAP_ROTL(s, t0, t1, 12);
-        SWAP_ROTL(s, t1, t0, 13);
-        SWAP_ROTL(s, t0, t1, 14);
-        SWAP_ROTL(s, t1, t0, 15);
-        SWAP_ROTL(s, t0, t1, 16);
-        SWAP_ROTL(s, t1, t0, 17);
-        SWAP_ROTL(s, t0, t1, 18);
-        SWAP_ROTL(s, t1, t0, 19);
-        SWAP_ROTL(s, t0, t1, 20);
-        SWAP_ROTL(s, t1, t0, 21);
-        SWAP_ROTL(s, t0, t1, 22);
-        SWAP_ROTL(s, t1, t0, 23);
-
-        ROW_MIX(s, b, y, x, t0, t1);
-
-        s[0] ^= hash_keccak_r[i];
-    }
-}
-#else
-/* Rotate a 64-bit value left.
- *
- * a  Number to rotate left.
- * r  Number od bits to rotate left.
- * returns the rotated number.
- */
-#define ROTL64(a, n)    (((a)<<(n))|((a)>>(64-(n))))
-
-/* An array of values to XOR for block operation. */
-static const word64 hash_keccak_r[24] =
-{
-    0x0000000000000001UL, 0x0000000000008082UL,
-    0x800000000000808aUL, 0x8000000080008000UL,
-    0x000000000000808bUL, 0x0000000080000001UL,
-    0x8000000080008081UL, 0x8000000000008009UL,
-    0x000000000000008aUL, 0x0000000000000088UL,
-    0x0000000080008009UL, 0x000000008000000aUL,
-    0x000000008000808bUL, 0x800000000000008bUL,
-    0x8000000000008089UL, 0x8000000000008003UL,
-    0x8000000000008002UL, 0x8000000000000080UL,
-    0x000000000000800aUL, 0x800000008000000aUL,
-    0x8000000080008081UL, 0x8000000000008080UL,
-    0x0000000080000001UL, 0x8000000080008008UL
-};
-
-/* Indeces used in swap and rotate operation. */
-#define KI_0     6
-#define KI_1    12
-#define KI_2    18
-#define KI_3    24
-#define KI_4     3
-#define KI_5     9
-#define KI_6    10
-#define KI_7    16
-#define KI_8    22
-#define KI_9     1
-#define KI_10    7
-#define KI_11   13
-#define KI_12   19
-#define KI_13   20
-#define KI_14    4
-#define KI_15    5
-#define KI_16   11
-#define KI_17   17
-#define KI_18   23
-#define KI_19    2
-#define KI_20    8
-#define KI_21   14
-#define KI_22   15
-#define KI_23   21
-
-/* Number of bits to rotate in swap and rotate operation. */
-#define KR_0    44
-#define KR_1    43
-#define KR_2    21
-#define KR_3    14
-#define KR_4    28
-#define KR_5    20
-#define KR_6     3
-#define KR_7    45
-#define KR_8    61
-#define KR_9     1
-#define KR_10    6
-#define KR_11   25
-#define KR_12    8
-#define KR_13   18
-#define KR_14   27
-#define KR_15   36
-#define KR_16   10
-#define KR_17   15
-#define KR_18   56
-#define KR_19   62
-#define KR_20   55
-#define KR_21   39
-#define KR_22   41
-#define KR_23    2
-
-/* Mix the XOR of the column's values into each number by column.
- *
- * s  The state.
- * b  Temporary array of XORed column values.
- * x  The index of the column.
- * t  Temporary variable.
- */
-#define COL_MIX(s, b, x, t)                                     \
-do                                                              \
-{                                                               \
-    b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];                 \
-    b[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];                 \
-    b[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];                 \
-    b[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];                 \
-    b[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];                 \
-    t = b[(0 + 4) % 5] ^ ROTL64(b[(0 + 1) % 5], 1);             \
-    s[ 0] ^= t; s[ 5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; \
-    t = b[(1 + 4) % 5] ^ ROTL64(b[(1 + 1) % 5], 1);             \
-    s[ 1] ^= t; s[ 6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; \
-    t = b[(2 + 4) % 5] ^ ROTL64(b[(2 + 1) % 5], 1);             \
-    s[ 2] ^= t; s[ 7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; \
-    t = b[(3 + 4) % 5] ^ ROTL64(b[(3 + 1) % 5], 1);             \
-    s[ 3] ^= t; s[ 8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; \
-    t = b[(4 + 4) % 5] ^ ROTL64(b[(4 + 1) % 5], 1);             \
-    s[ 4] ^= t; s[ 9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; \
-}                                                               \
-while (0)
-
-#define S(s1, i) ROTL64(s1[KI_##i], KR_##i)
-
-#ifdef SHA3_BY_SPEC
-/* Mix the row values.
- * BMI1 has ANDN instruction ((~a) & b) - Haswell and above.
- *
- * s2  The new state.
- * s1  The current state.
- * b   Temporary array of XORed row values.
- * t0  Temporary variable. (Unused)
- * t1  Temporary variable. (Unused)
- */
-#define ROW_MIX(s2, s1, b, t0, t1)            \
-do                                            \
-{                                             \
-    b[0] = s1[0];                             \
-    b[1] = S(s1, 0);                          \
-    b[2] = S(s1, 1);                          \
-    b[3] = S(s1, 2);                          \
-    b[4] = S(s1, 3);                          \
-    s2[0] = b[0] ^ (~b[1] & b[2]);            \
-    s2[1] = b[1] ^ (~b[2] & b[3]);            \
-    s2[2] = b[2] ^ (~b[3] & b[4]);            \
-    s2[3] = b[3] ^ (~b[4] & b[0]);            \
-    s2[4] = b[4] ^ (~b[0] & b[1]);            \
-    b[0] = S(s1, 4);                          \
-    b[1] = S(s1, 5);                          \
-    b[2] = S(s1, 6);                          \
-    b[3] = S(s1, 7);                          \
-    b[4] = S(s1, 8);                          \
-    s2[5] = b[0] ^ (~b[1] & b[2]);            \
-    s2[6] = b[1] ^ (~b[2] & b[3]);            \
-    s2[7] = b[2] ^ (~b[3] & b[4]);            \
-    s2[8] = b[3] ^ (~b[4] & b[0]);            \
-    s2[9] = b[4] ^ (~b[0] & b[1]);            \
-    b[0] = S(s1, 9);                          \
-    b[1] = S(s1, 10);                         \
-    b[2] = S(s1, 11);                         \
-    b[3] = S(s1, 12);                         \
-    b[4] = S(s1, 13);                         \
-    s2[10] = b[0] ^ (~b[1] & b[2]);           \
-    s2[11] = b[1] ^ (~b[2] & b[3]);           \
-    s2[12] = b[2] ^ (~b[3] & b[4]);           \
-    s2[13] = b[3] ^ (~b[4] & b[0]);           \
-    s2[14] = b[4] ^ (~b[0] & b[1]);           \
-    b[0] = S(s1, 14);                         \
-    b[1] = S(s1, 15);                         \
-    b[2] = S(s1, 16);                         \
-    b[3] = S(s1, 17);                         \
-    b[4] = S(s1, 18);                         \
-    s2[15] = b[0] ^ (~b[1] & b[2]);           \
-    s2[16] = b[1] ^ (~b[2] & b[3]);           \
-    s2[17] = b[2] ^ (~b[3] & b[4]);           \
-    s2[18] = b[3] ^ (~b[4] & b[0]);           \
-    s2[19] = b[4] ^ (~b[0] & b[1]);           \
-    b[0] = S(s1, 19);                         \
-    b[1] = S(s1, 20);                         \
-    b[2] = S(s1, 21);                         \
-    b[3] = S(s1, 22);                         \
-    b[4] = S(s1, 23);                         \
-    s2[20] = b[0] ^ (~b[1] & b[2]);           \
-    s2[21] = b[1] ^ (~b[2] & b[3]);           \
-    s2[22] = b[2] ^ (~b[3] & b[4]);           \
-    s2[23] = b[3] ^ (~b[4] & b[0]);           \
-    s2[24] = b[4] ^ (~b[0] & b[1]);           \
-}                                             \
-while (0)
-#else
-/* Mix the row values.
- * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c)
- *
- * s2  The new state.
- * s1  The current state.
- * b   Temporary array of XORed row values.
- * t12 Temporary variable.
- * t34 Temporary variable.
- */
-#define ROW_MIX(s2, s1, b, t12, t34)          \
-do                                            \
-{                                             \
-    b[0] = s1[0];                             \
-    b[1] = S(s1, 0);                          \
-    b[2] = S(s1, 1);                          \
-    b[3] = S(s1, 2);                          \
-    b[4] = S(s1, 3);                          \
-    t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \
-    s2[0] = b[0] ^ (b[2] &  t12);             \
-    s2[1] =  t12 ^ (b[2] | b[3]);             \
-    s2[2] = b[2] ^ (b[4] &  t34);             \
-    s2[3] =  t34 ^ (b[4] | b[0]);             \
-    s2[4] = b[4] ^ (b[1] & (b[0] ^ b[1]));    \
-    b[0] = S(s1, 4);                          \
-    b[1] = S(s1, 5);                          \
-    b[2] = S(s1, 6);                          \
-    b[3] = S(s1, 7);                          \
-    b[4] = S(s1, 8);                          \
-    t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \
-    s2[5] = b[0] ^ (b[2] &  t12);             \
-    s2[6] =  t12 ^ (b[2] | b[3]);             \
-    s2[7] = b[2] ^ (b[4] &  t34);             \
-    s2[8] =  t34 ^ (b[4] | b[0]);             \
-    s2[9] = b[4] ^ (b[1] & (b[0] ^ b[1]));    \
-    b[0] = S(s1, 9);                          \
-    b[1] = S(s1, 10);                         \
-    b[2] = S(s1, 11);                         \
-    b[3] = S(s1, 12);                         \
-    b[4] = S(s1, 13);                         \
-    t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \
-    s2[10] = b[0] ^ (b[2] &  t12);            \
-    s2[11] =  t12 ^ (b[2] | b[3]);            \
-    s2[12] = b[2] ^ (b[4] &  t34);            \
-    s2[13] =  t34 ^ (b[4] | b[0]);            \
-    s2[14] = b[4] ^ (b[1] & (b[0] ^ b[1]));   \
-    b[0] = S(s1, 14);                         \
-    b[1] = S(s1, 15);                         \
-    b[2] = S(s1, 16);                         \
-    b[3] = S(s1, 17);                         \
-    b[4] = S(s1, 18);                         \
-    t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \
-    s2[15] = b[0] ^ (b[2] &  t12);            \
-    s2[16] =  t12 ^ (b[2] | b[3]);            \
-    s2[17] = b[2] ^ (b[4] &  t34);            \
-    s2[18] =  t34 ^ (b[4] | b[0]);            \
-    s2[19] = b[4] ^ (b[1] & (b[0] ^ b[1]));   \
-    b[0] = S(s1, 19);                         \
-    b[1] = S(s1, 20);                         \
-    b[2] = S(s1, 21);                         \
-    b[3] = S(s1, 22);                         \
-    b[4] = S(s1, 23);                         \
-    t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \
-    s2[20] = b[0] ^ (b[2] &  t12);            \
-    s2[21] =  t12 ^ (b[2] | b[3]);            \
-    s2[22] = b[2] ^ (b[4] &  t34);            \
-    s2[23] =  t34 ^ (b[4] | b[0]);            \
-    s2[24] = b[4] ^ (b[1] & (b[0] ^ b[1]));   \
-}                                             \
-while (0)
-#endif /* SHA3_BY_SPEC */
-
-/* The block operation performed on the state.
- *
- * s  The state.
- */
-static void BlockSha3(word64 *s)
-{
-    word64 n[25];
-    word64 b[5];
-    word64 t0;
-#ifndef SHA3_BY_SPEC
-    word64 t1;
-#endif
-    byte i;
-
-    for (i = 0; i < 24; i += 2)
-    {
-        COL_MIX(s, b, x, t0);
-        ROW_MIX(n, s, b, t0, t1);
-        n[0] ^= hash_keccak_r[i];
-
-        COL_MIX(n, b, x, t0);
-        ROW_MIX(s, n, b, t0, t1);
-        s[0] ^= hash_keccak_r[i+1];
-    }
-}
-#endif /* WOLFSSL_SHA3_SMALL */
-
-/* Convert the array of bytes, in little-endian order, to a 64-bit integer.
- *
- * a  Array of bytes.
- * returns a 64-bit integer.
- */
-static word64 Load64BitBigEndian(const byte* a)
-{
-#ifdef BIG_ENDIAN_ORDER
-    word64 n = 0;
-    int i;
-
-    for (i = 0; i < 8; i++)
-        n |= (word64)a[i] << (8 * i);
-
-    return n;
-#else
-    return *(word64*)a;
-#endif
-}
-
-/* Initialize the state for a SHA3-224 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * returns 0 on success.
- */
-static int InitSha3(wc_Sha3* sha3)
-{
-    int i;
-
-    for (i = 0; i < 25; i++)
-        sha3->s[i] = 0;
-    sha3->i = 0;
-
-    return 0;
-}
-
-/* Update the SHA-3 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * p     Number of 64-bit numbers in a block of data to process.
- * returns 0 on success.
- */
-static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
-{
-    byte i;
-    byte l;
-    byte *t;
-
-    if (sha3->i > 0)
-    {
-        l = p * 8 - sha3->i;
-        if (l > len) {
-            l = (byte)len;
-        }
-
-        t = &sha3->t[sha3->i];
-        for (i = 0; i < l; i++)
-            t[i] = data[i];
-        data += i;
-        len -= i;
-        sha3->i += i;
-
-        if (sha3->i == p * 8)
-        {
-            for (i = 0; i < p; i++)
-                sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
-            BlockSha3(sha3->s);
-            sha3->i = 0;
-        }
-    }
-    while (len >= ((word32)(p * 8)))
-    {
-        for (i = 0; i < p; i++)
-            sha3->s[i] ^= Load64BitBigEndian(data + 8 * i);
-        BlockSha3(sha3->s);
-        len -= p * 8;
-        data += p * 8;
-    }
-    for (i = 0; i < len; i++)
-        sha3->t[i] = data[i];
-    sha3->i += i;
-
-    return 0;
-}
-
-/* Calculate the SHA-3 hash based on all the message data seen.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result.
- * p     Number of 64-bit numbers in a block of data to process.
- * len   Number of bytes in output.
- * returns 0 on success.
- */
-static int Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte l)
-{
-    byte i;
-    byte *s8 = (byte *)sha3->s;
-
-    sha3->t[p * 8 - 1]  = 0x00;
-    sha3->t[  sha3->i]  = 0x06;
-    sha3->t[p * 8 - 1] |= 0x80;
-    for (i=sha3->i + 1; i < p * 8 - 1; i++)
-        sha3->t[i] = 0;
-    for (i = 0; i < p; i++)
-        sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i);
-    BlockSha3(sha3->s);
-#if defined(BIG_ENDIAN_ORDER)
-    ByteReverseWords64(sha3->s, sha3->s, ((l+7)/8)*8);
-#endif
-    for (i = 0; i < l; i++)
-        hash[i] = s8[i];
-
-    return 0;
-}
-
-/* Initialize the state for a SHA-3 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * heap   Heap reference for dynamic memory allocation. (Used in async ops.)
- * devId  Device identifier for asynchronous operation.
- * returns 0 on success.
- */
-static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
-{
-    int ret = 0;
-
-    if (sha3 == NULL)
-        return BAD_FUNC_ARG;
-
-    sha3->heap = heap;
-    ret = InitSha3(sha3);
-    if (ret != 0)
-        return ret;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3)
-    ret = wolfAsync_DevCtxInit(&sha3->asyncDev,
-                        WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-/* Update the SHA-3 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * p     Number of 64-bit numbers in a block of data to process.
- * returns 0 on success.
- */
-static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
-{
-    int ret = 0;
-
-    if (sha3 == NULL || (data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3)
-    if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha3(&sha3->asyncDev, NULL, data, len);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    Sha3Update(sha3, data, len, p);
-
-    return ret;
-}
-
-/* Calculate the SHA-3 hash based on all the message data seen.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result.
- * p     Number of 64-bit numbers in a block of data to process.
- * len   Number of bytes in output.
- * returns 0 on success.
- */
-static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
-{
-    int ret;
-
-    if (sha3 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3)
-    if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha3(&sha3->asyncDev, hash, NULL,
-                              SHA3_DIGEST_SIZE);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    ret = Sha3Final(sha3, hash, p, len);
-    if (ret != 0)
-        return ret;
-
-    return InitSha3(sha3);  /* reset state */
-}
-
-/* Dispose of any dynamically allocated data from the SHA3-384 operation.
- * (Required for async ops.)
- *
- * sha3  wc_Sha3 object holding state.
- * returns 0 on success.
- */
-static void wc_Sha3Free(wc_Sha3* sha3)
-{
-    (void)sha3;
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3)
-    if (sha3 == NULL)
-        return;
-
-    wolfAsync_DevCtxFree(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-
-/* Copy the state of the SHA3 operation.
- *
- * src  wc_Sha3 object holding state top copy.
- * dst  wc_Sha3 object to copy into.
- * returns 0 on success.
- */
-static int wc_Sha3Copy(wc_Sha3* src, wc_Sha3* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Sha3));
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-
-    return ret;
-}
-
-/* Calculate the SHA3-224 hash based on all the message data so far.
- * More message data can be added, after this operation, using the current
- * state.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 28 bytes.
- * p     Number of 64-bit numbers in a block of data to process.
- * len   Number of bytes in output.
- * returns 0 on success.
- */
-static int wc_Sha3GetHash(wc_Sha3* sha3, byte* hash, byte p, byte len)
-{
-    int ret;
-    wc_Sha3 tmpSha3;
-
-    if (sha3 == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_Sha3Copy(sha3, &tmpSha3);
-    if (ret == 0) {
-        ret = wc_Sha3Final(&tmpSha3, hash, p, len);
-    }
-    return ret;
-}
-
-
-/* Initialize the state for a SHA3-224 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * heap   Heap reference for dynamic memory allocation. (Used in async ops.)
- * devId  Device identifier for asynchronous operation.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_InitSha3_224(wc_Sha3* sha3, void* heap, int devId)
-{
-    return wc_InitSha3(sha3, heap, devId);
-}
-
-/* Update the SHA3-224 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_224_Update(wc_Sha3* sha3, const byte* data, word32 len)
-{
-    return wc_Sha3Update(sha3, data, len, WC_SHA3_224_COUNT);
-}
-
-/* Calculate the SHA3-224 hash based on all the message data seen.
- * The state is initialized ready for a new message to hash.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 28 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_224_Final(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3Final(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE);
-}
-
-/* Dispose of any dynamically allocated data from the SHA3-224 operation.
- * (Required for async ops.)
- *
- * sha3  wc_Sha3 object holding state.
- * returns 0 on success.
- */
-WOLFSSL_API void wc_Sha3_224_Free(wc_Sha3* sha3)
-{
-    wc_Sha3Free(sha3);
-}
-
-/* Calculate the SHA3-224 hash based on all the message data so far.
- * More message data can be added, after this operation, using the current
- * state.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 28 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_224_GetHash(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3GetHash(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE);
-}
-
-/* Copy the state of the SHA3-224 operation.
- *
- * src  wc_Sha3 object holding state top copy.
- * dst  wc_Sha3 object to copy into.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst)
-{
-    return wc_Sha3Copy(src, dst);
-}
-
-
-/* Initialize the state for a SHA3-256 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * heap   Heap reference for dynamic memory allocation. (Used in async ops.)
- * devId  Device identifier for asynchronous operation.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_InitSha3_256(wc_Sha3* sha3, void* heap, int devId)
-{
-    return wc_InitSha3(sha3, heap, devId);
-}
-
-/* Update the SHA3-256 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_256_Update(wc_Sha3* sha3, const byte* data, word32 len)
-{
-    return wc_Sha3Update(sha3, data, len, WC_SHA3_256_COUNT);
-}
-
-/* Calculate the SHA3-256 hash based on all the message data seen.
- * The state is initialized ready for a new message to hash.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 32 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_256_Final(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3Final(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE);
-}
-
-/* Dispose of any dynamically allocated data from the SHA3-256 operation.
- * (Required for async ops.)
- *
- * sha3  wc_Sha3 object holding state.
- * returns 0 on success.
- */
-WOLFSSL_API void wc_Sha3_256_Free(wc_Sha3* sha3)
-{
-    wc_Sha3Free(sha3);
-}
-
-/* Calculate the SHA3-256 hash based on all the message data so far.
- * More message data can be added, after this operation, using the current
- * state.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 32 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_256_GetHash(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3GetHash(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE);
-}
-
-/* Copy the state of the SHA3-256 operation.
- *
- * src  wc_Sha3 object holding state top copy.
- * dst  wc_Sha3 object to copy into.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst)
-{
-    return wc_Sha3Copy(src, dst);
-}
-
-
-/* Initialize the state for a SHA3-384 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * heap   Heap reference for dynamic memory allocation. (Used in async ops.)
- * devId  Device identifier for asynchronous operation.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_InitSha3_384(wc_Sha3* sha3, void* heap, int devId)
-{
-    return wc_InitSha3(sha3, heap, devId);
-}
-
-/* Update the SHA3-384 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_384_Update(wc_Sha3* sha3, const byte* data, word32 len)
-{
-    return wc_Sha3Update(sha3, data, len, WC_SHA3_384_COUNT);
-}
-
-/* Calculate the SHA3-384 hash based on all the message data seen.
- * The state is initialized ready for a new message to hash.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 48 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_384_Final(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3Final(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE);
-}
-
-/* Dispose of any dynamically allocated data from the SHA3-384 operation.
- * (Required for async ops.)
- *
- * sha3  wc_Sha3 object holding state.
- * returns 0 on success.
- */
-WOLFSSL_API void wc_Sha3_384_Free(wc_Sha3* sha3)
-{
-    wc_Sha3Free(sha3);
-}
-
-/* Calculate the SHA3-384 hash based on all the message data so far.
- * More message data can be added, after this operation, using the current
- * state.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 48 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_384_GetHash(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3GetHash(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE);
-}
-
-/* Copy the state of the SHA3-384 operation.
- *
- * src  wc_Sha3 object holding state top copy.
- * dst  wc_Sha3 object to copy into.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst)
-{
-    return wc_Sha3Copy(src, dst);
-}
-
-
-/* Initialize the state for a SHA3-512 hash operation.
- *
- * sha3   wc_Sha3 object holding state.
- * heap   Heap reference for dynamic memory allocation. (Used in async ops.)
- * devId  Device identifier for asynchronous operation.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_InitSha3_512(wc_Sha3* sha3, void* heap, int devId)
-{
-    return wc_InitSha3(sha3, heap, devId);
-}
-
-/* Update the SHA3-512 hash state with message data.
- *
- * sha3  wc_Sha3 object holding state.
- * data  Message data to be hashed.
- * len   Length of the message data.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_512_Update(wc_Sha3* sha3, const byte* data, word32 len)
-{
-    return wc_Sha3Update(sha3, data, len, WC_SHA3_512_COUNT);
-}
-
-/* Calculate the SHA3-512 hash based on all the message data seen.
- * The state is initialized ready for a new message to hash.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 64 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_512_Final(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3Final(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE);
-}
-
-/* Dispose of any dynamically allocated data from the SHA3-512 operation.
- * (Required for async ops.)
- *
- * sha3  wc_Sha3 object holding state.
- * returns 0 on success.
- */
-WOLFSSL_API void wc_Sha3_512_Free(wc_Sha3* sha3)
-{
-    wc_Sha3Free(sha3);
-}
-
-/* Calculate the SHA3-512 hash based on all the message data so far.
- * More message data can be added, after this operation, using the current
- * state.
- *
- * sha3  wc_Sha3 object holding state.
- * hash  Buffer to hold the hash result. Must be at least 64 bytes.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_512_GetHash(wc_Sha3* sha3, byte* hash)
-{
-    return wc_Sha3GetHash(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE);
-}
-
-/* Copy the state of the SHA3-512 operation.
- *
- * src  wc_Sha3 object holding state top copy.
- * dst  wc_Sha3 object to copy into.
- * returns 0 on success.
- */
-WOLFSSL_API int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst)
-{
-    return wc_Sha3Copy(src, dst);
-}
-
-#endif /* WOLFSSL_SHA3 */
-
--- a/wolfcrypt/src/sha512.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2866 +0,0 @@
-/* sha512.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-
-    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
-    #define FIPS_NO_WRAPPERS
-
-    #ifdef USE_WINDOWS_API
-        #pragma code_seg(".fipsA$k")
-        #pragma const_seg(".fipsB$k")
-    #endif
-#endif
-
-#include <wolfssl/wolfcrypt/sha512.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-
-/* deprecated USE_SLOW_SHA2 (replaced with USE_SLOW_SHA512) */
-#if defined(USE_SLOW_SHA2) && !defined(USE_SLOW_SHA512)
-    #define USE_SLOW_SHA512
-#endif
-
-/* fips wrapper calls, user can call direct */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-
-    #ifdef WOLFSSL_SHA512
-
-        int wc_InitSha512(wc_Sha512* sha)
-        {
-            if (sha == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            return InitSha512_fips(sha);
-        }
-        int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId)
-        {
-            (void)heap;
-            (void)devId;
-            if (sha == NULL) {
-                return BAD_FUNC_ARG;
-            }
-            return InitSha512_fips(sha);
-        }
-        int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len)
-        {
-            if (sha == NULL || (data == NULL && len > 0)) {
-                return BAD_FUNC_ARG;
-            }
-
-            return Sha512Update_fips(sha, data, len);
-        }
-        int wc_Sha512Final(wc_Sha512* sha, byte* out)
-        {
-            if (sha == NULL || out == NULL) {
-                return BAD_FUNC_ARG;
-            }
-
-            return Sha512Final_fips(sha, out);
-        }
-        void wc_Sha512Free(wc_Sha512* sha)
-        {
-            (void)sha;
-            /* Not supported in FIPS */
-        }
-    #endif
-
-    #if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM)
-        int wc_InitSha384(wc_Sha384* sha)
-        {
-            if (sha == NULL) {
-                return BAD_FUNC_ARG;
-            }
-            return InitSha384_fips(sha);
-        }
-        int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId)
-        {
-            (void)heap;
-            (void)devId;
-            if (sha == NULL) {
-                return BAD_FUNC_ARG;
-            }
-            return InitSha384_fips(sha);
-        }
-        int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len)
-        {
-            if (sha == NULL || (data == NULL && len > 0)) {
-                return BAD_FUNC_ARG;
-            }
-            return Sha384Update_fips(sha, data, len);
-        }
-        int wc_Sha384Final(wc_Sha384* sha, byte* out)
-        {
-            if (sha == NULL || out == NULL) {
-                return BAD_FUNC_ARG;
-            }
-            return Sha384Final_fips(sha, out);
-        }
-        void wc_Sha384Free(wc_Sha384* sha)
-        {
-            (void)sha;
-            /* Not supported in FIPS */
-        }
-    #endif /* WOLFSSL_SHA384 || HAVE_AESGCM */
-
-#else /* else build without fips, or for FIPS v2 */
-
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#if defined(USE_INTEL_SPEEDUP)
-    #define HAVE_INTEL_AVX1
-
-    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
-                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
-        #define NO_AVX2_SUPPORT
-    #endif
-    #if defined(__clang__) && ((__clang_major__ < 3) || \
-                               (__clang_major__ == 3 && __clang_minor__ <= 5))
-        #define NO_AVX2_SUPPORT
-    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
-        #undef NO_AVX2_SUPPORT
-    #endif
-
-    #define HAVE_INTEL_AVX1
-    #ifndef NO_AVX2_SUPPORT
-        #define HAVE_INTEL_AVX2
-    #endif
-#endif
-
-#if defined(HAVE_INTEL_AVX1)
-    /* #define DEBUG_XMM  */
-#endif
-
-#if defined(HAVE_INTEL_AVX2)
-    #define HAVE_INTEL_RORX
-    /* #define DEBUG_YMM  */
-#endif
-
-#if defined(HAVE_BYTEREVERSE64) && \
-        !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2)
-    #define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size)
-    #define ByteReverseWords64_1(buf, size) \
-        { unsigned int i ;\
-            for(i=0; i< size/sizeof(word64); i++){\
-                __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\
-            }\
-        }
-#endif
-
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
-#else
-
-#ifdef WOLFSSL_SHA512
-
-static int InitSha512(wc_Sha512* sha512)
-{
-    if (sha512 == NULL)
-        return BAD_FUNC_ARG;
-
-    sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
-    sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
-    sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
-    sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
-    sha512->digest[4] = W64LIT(0x510e527fade682d1);
-    sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
-    sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
-    sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
-
-    sha512->buffLen = 0;
-    sha512->loLen   = 0;
-    sha512->hiLen   = 0;
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SHA512 */
-
-/* Hardware Acceleration */
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-
-#ifdef WOLFSSL_SHA512
-
-    /*****
-    Intel AVX1/AVX2 Macro Control Structure
-
-    #if defined(HAVE_INteL_SPEEDUP)
-        #define HAVE_INTEL_AVX1
-        #define HAVE_INTEL_AVX2
-    #endif
-
-    int InitSha512(wc_Sha512* sha512) {
-         Save/Recover XMM, YMM
-         ...
-
-         Check Intel AVX cpuid flags
-    }
-
-    #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
-      Transform_Sha512_AVX1(); # Function prototype
-      Transform_Sha512_AVX2(); #
-    #endif
-
-      _Transform_Sha512() {     # Native Transform Function body
-
-      }
-
-      int Sha512Update() {
-         Save/Recover XMM, YMM
-         ...
-      }
-
-      int Sha512Final() {
-         Save/Recover XMM, YMM
-         ...
-      }
-
-
-    #if defined(HAVE_INTEL_AVX1)
-
-       XMM Instructions/INLINE asm Definitions
-
-    #endif
-
-    #if defined(HAVE_INTEL_AVX2)
-
-       YMM Instructions/INLINE asm Definitions
-
-    #endif
-
-    #if defnied(HAVE_INTEL_AVX1)
-
-      int Transform_Sha512_AVX1() {
-          Stitched Message Sched/Round
-      }
-
-    #endif
-
-    #if defnied(HAVE_INTEL_AVX2)
-
-      int Transform_Sha512_AVX2() {
-          Stitched Message Sched/Round
-      }
-    #endif
-
-    */
-
-
-    /* Each platform needs to query info type 1 from cpuid to see if aesni is
-     * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
-     */
-
-    #if defined(HAVE_INTEL_AVX1)
-        static int Transform_Sha512_AVX1(wc_Sha512 *sha512);
-        static int Transform_Sha512_AVX1_Len(wc_Sha512 *sha512, word32 len);
-    #endif
-    #if defined(HAVE_INTEL_AVX2)
-        static int Transform_Sha512_AVX2(wc_Sha512 *sha512);
-        static int Transform_Sha512_AVX2_Len(wc_Sha512 *sha512, word32 len);
-        #if defined(HAVE_INTEL_RORX)
-            static int Transform_Sha512_AVX1_RORX(wc_Sha512 *sha512);
-            static int Transform_Sha512_AVX1_RORX_Len(wc_Sha512 *sha512,
-                                                      word32 len);
-            static int Transform_Sha512_AVX2_RORX(wc_Sha512 *sha512);
-            static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512 *sha512,
-                                                      word32 len);
-        #endif
-    #endif
-    static int _Transform_Sha512(wc_Sha512 *sha512);
-    static int (*Transform_Sha512_p)(wc_Sha512* sha512) = _Transform_Sha512;
-    static int (*Transform_Sha512_Len_p)(wc_Sha512* sha512, word32 len) = NULL;
-    static int transform_check = 0;
-    static int intel_flags;
-    #define Transform_Sha512(sha512)     (*Transform_Sha512_p)(sha512)
-    #define Transform_Sha512_Len(sha512, len) \
-        (*Transform_Sha512_Len_p)(sha512, len)
-
-    static void Sha512_SetTransform()
-    {
-        if (transform_check)
-            return;
-
-        intel_flags = cpuid_get_flags();
-
-    #if defined(HAVE_INTEL_AVX2)
-        if (IS_INTEL_AVX2(intel_flags)) {
-        #ifdef HAVE_INTEL_RORX
-            if (IS_INTEL_BMI2(intel_flags)) {
-                Transform_Sha512_p = Transform_Sha512_AVX2_RORX;
-                Transform_Sha512_Len_p = Transform_Sha512_AVX2_RORX_Len;
-            }
-            else
-        #endif
-            if (1) {
-                Transform_Sha512_p = Transform_Sha512_AVX2;
-                Transform_Sha512_Len_p = Transform_Sha512_AVX2_Len;
-            }
-        #ifdef HAVE_INTEL_RORX
-            else {
-                Transform_Sha512_p = Transform_Sha512_AVX1_RORX;
-                Transform_Sha512_Len_p = Transform_Sha512_AVX1_RORX_Len;
-            }
-        #endif
-        }
-        else
-    #endif
-    #if defined(HAVE_INTEL_AVX1)
-        if (IS_INTEL_AVX1(intel_flags)) {
-            Transform_Sha512_p = Transform_Sha512_AVX1;
-            Transform_Sha512_Len_p = Transform_Sha512_AVX1_Len;
-        }
-        else
-    #endif
-            Transform_Sha512_p = _Transform_Sha512;
-
-        transform_check = 1;
-    }
-
-    int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
-    {
-        int ret = InitSha512(sha512);
-
-        (void)heap;
-        (void)devId;
-
-        Sha512_SetTransform();
-
-        return ret;
-    }
-
-#endif /* WOLFSSL_SHA512 */
-
-#else
-    #define Transform_Sha512(sha512) _Transform_Sha512(sha512)
-
-    #ifdef WOLFSSL_SHA512
-
-    int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
-    {
-        int ret = 0;
-
-        if (sha512 == NULL)
-            return BAD_FUNC_ARG;
-
-        sha512->heap = heap;
-
-        ret = InitSha512(sha512);
-        if (ret != 0)
-            return ret;
-
-    #ifdef WOLFSSL_SMALL_STACK_CACHE
-        sha512->W = NULL;
-    #endif
-
-    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
-        ret = wolfAsync_DevCtxInit(&sha512->asyncDev,
-                            WOLFSSL_ASYNC_MARKER_SHA512, sha512->heap, devId);
-    #else
-        (void)devId;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-
-        return ret;
-    }
-
-    #endif /* WOLFSSL_SHA512 */
-
-#endif /* Hardware Acceleration */
-
-static const word64 K512[80] = {
-    W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
-    W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
-    W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
-    W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
-    W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
-    W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
-    W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
-    W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
-    W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
-    W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
-    W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
-    W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
-    W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
-    W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
-    W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
-    W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
-    W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
-    W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
-    W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
-    W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
-    W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
-    W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
-    W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
-    W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
-    W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
-    W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
-    W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
-    W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
-    W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
-    W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
-    W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
-    W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
-    W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
-    W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
-    W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
-    W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
-    W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
-    W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
-    W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
-    W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
-};
-
-#define blk0(i) (W[i] = sha512->buffer[i])
-
-#define blk2(i) (\
-               W[ i     & 15] += \
-            s1(W[(i-2)  & 15])+ \
-               W[(i-7)  & 15] + \
-            s0(W[(i-15) & 15])  \
-        )
-
-#define Ch(x,y,z)  (z ^ (x & (y ^ z)))
-#define Maj(x,y,z) ((x & y) | (z & (x | y)))
-
-#define a(i) T[(0-i) & 7]
-#define b(i) T[(1-i) & 7]
-#define c(i) T[(2-i) & 7]
-#define d(i) T[(3-i) & 7]
-#define e(i) T[(4-i) & 7]
-#define f(i) T[(5-i) & 7]
-#define g(i) T[(6-i) & 7]
-#define h(i) T[(7-i) & 7]
-
-#define S0(x) (rotrFixed64(x,28) ^ rotrFixed64(x,34) ^ rotrFixed64(x,39))
-#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41))
-#define s0(x) (rotrFixed64(x,1)  ^ rotrFixed64(x,8)  ^ (x>>7))
-#define s1(x) (rotrFixed64(x,19) ^ rotrFixed64(x,61) ^ (x>>6))
-
-#define R(i) \
-    h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j ? blk2(i) : blk0(i)); \
-    d(i) += h(i); \
-    h(i) += S0(a(i)) + Maj(a(i),b(i),c(i))
-
-static int _Transform_Sha512(wc_Sha512* sha512)
-{
-    const word64* K = K512;
-    word32 j;
-    word64 T[8];
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    word64* W = sha512->W;
-    if (W == NULL) {
-        W = (word64*) XMALLOC(sizeof(word64) * 16, NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-        if (W == NULL)
-            return MEMORY_E;
-        sha512->W = W;
-    }
-#elif defined(WOLFSSL_SMALL_STACK)
-    word64* W;
-    W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (W == NULL)
-        return MEMORY_E;
-#else
-    word64 W[16];
-#endif
-
-    /* Copy digest to working vars */
-    XMEMCPY(T, sha512->digest, sizeof(T));
-
-#ifdef USE_SLOW_SHA512
-    /* over twice as small, but 50% slower */
-    /* 80 operations, not unrolled */
-    for (j = 0; j < 80; j += 16) {
-        int m;
-        for (m = 0; m < 16; m++) { /* braces needed here for macros {} */
-            R(m);
-        }
-    }
-#else
-    /* 80 operations, partially loop unrolled */
-    for (j = 0; j < 80; j += 16) {
-        R( 0); R( 1); R( 2); R( 3);
-        R( 4); R( 5); R( 6); R( 7);
-        R( 8); R( 9); R(10); R(11);
-        R(12); R(13); R(14); R(15);
-    }
-#endif /* USE_SLOW_SHA512 */
-
-    /* Add the working vars back into digest */
-    sha512->digest[0] += a(0);
-    sha512->digest[1] += b(0);
-    sha512->digest[2] += c(0);
-    sha512->digest[3] += d(0);
-    sha512->digest[4] += e(0);
-    sha512->digest[5] += f(0);
-    sha512->digest[6] += g(0);
-    sha512->digest[7] += h(0);
-
-    /* Wipe variables */
-    ForceZero(W, sizeof(word64) * 16);
-    ForceZero(T, sizeof(T));
-
-#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
-    XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return 0;
-}
-
-
-static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len)
-{
-    word64 tmp = sha512->loLen;
-    if ( (sha512->loLen += len) < tmp)
-        sha512->hiLen++;                       /* carry low to high */
-}
-
-static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
-{
-    int ret = 0;
-    /* do block size increments */
-    byte* local = (byte*)sha512->buffer;
-
-    /* check that internal buffLen is valid */
-    if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE)
-        return BUFFER_E;
-
-    if (sha512->buffLen > 0) {
-        word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen);
-        if (add > 0) {
-            XMEMCPY(&local[sha512->buffLen], data, add);
-
-            sha512->buffLen += add;
-            data            += add;
-            len             -= add;
-        }
-
-        if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) {
-    #if defined(LITTLE_ENDIAN_ORDER)
-        #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-            if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-        #endif
-            {
-                ByteReverseWords64(sha512->buffer, sha512->buffer,
-                                                          WC_SHA512_BLOCK_SIZE);
-            }
-    #endif
-            ret = Transform_Sha512(sha512);
-            if (ret == 0) {
-                AddLength(sha512, WC_SHA512_BLOCK_SIZE);
-                sha512->buffLen = 0;
-            }
-            else
-                len = 0;
-        }
-    }
-
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-    if (Transform_Sha512_Len_p != NULL) {
-        word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1);
-
-        if (blocksLen > 0) {
-            AddLength(sha512, blocksLen);
-            sha512->data = data;
-            /* Byte reversal performed in function if required. */
-            Transform_Sha512_Len(sha512, blocksLen);
-            data += blocksLen;
-            len  -= blocksLen;
-        }
-    }
-    else
-#endif
-#if !defined(LITTLE_ENDIAN_ORDER) || defined(FREESCALE_MMCAU_SHA) || \
-                            defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-    {
-        word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1);
-
-        AddLength(sha512, blocksLen);
-        while (len >= WC_SHA512_BLOCK_SIZE) {
-            XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE);
-
-            data += WC_SHA512_BLOCK_SIZE;
-            len  -= WC_SHA512_BLOCK_SIZE;
-
-            /* Byte reversal performed in function if required. */
-            ret = Transform_Sha512(sha512);
-            if (ret != 0)
-                break;
-        }
-    }
-#else
-    {
-        word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1);
-
-        AddLength(sha512, blocksLen);
-        while (len >= WC_SHA512_BLOCK_SIZE) {
-            XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE);
-
-            data += WC_SHA512_BLOCK_SIZE;
-            len  -= WC_SHA512_BLOCK_SIZE;
-
-            ByteReverseWords64(sha512->buffer, sha512->buffer,
-                                                          WC_SHA512_BLOCK_SIZE);
-            ret = Transform_Sha512(sha512);
-            if (ret != 0)
-                break;
-        }
-    }
-#endif
-
-    if (len > 0) {
-        XMEMCPY(local, data, len);
-        sha512->buffLen = len;
-    }
-
-    return ret;
-}
-
-#ifdef WOLFSSL_SHA512
-
-int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
-{
-    if (sha512 == NULL || (data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
-    if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha512(&sha512->asyncDev, NULL, data, len);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return Sha512Update(sha512, data, len);
-}
-
-#endif /* WOLFSSL_SHA512 */
-
-#endif /* WOLFSSL_IMX6_CAAM */
-
-static WC_INLINE int Sha512Final(wc_Sha512* sha512)
-{
-    byte* local = (byte*)sha512->buffer;
-    int ret;
-
-    if (sha512 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    AddLength(sha512, sha512->buffLen);               /* before adding pads */
-
-    local[sha512->buffLen++] = 0x80;  /* add 1 */
-
-    /* pad with zeros */
-    if (sha512->buffLen > WC_SHA512_PAD_SIZE) {
-        XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_BLOCK_SIZE - sha512->buffLen);
-        sha512->buffLen += WC_SHA512_BLOCK_SIZE - sha512->buffLen;
-#if defined(LITTLE_ENDIAN_ORDER)
-    #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-        if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-    #endif
-        {
-            ByteReverseWords64(sha512->buffer,sha512->buffer,
-                                                             WC_SHA512_BLOCK_SIZE);
-        }
-#endif /* LITTLE_ENDIAN_ORDER */
-        ret = Transform_Sha512(sha512);
-        if (ret != 0)
-            return ret;
-
-        sha512->buffLen = 0;
-    }
-    XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen);
-
-    /* put lengths in bits */
-    sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) +
-                                                         (sha512->hiLen << 3);
-    sha512->loLen = sha512->loLen << 3;
-
-    /* store lengths */
-#if defined(LITTLE_ENDIAN_ORDER)
-    #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-        if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
-    #endif
-            ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE);
-#endif
-    /* ! length ordering dependent on digest endian type ! */
-
-    sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
-    sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-    if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
-        ByteReverseWords64(&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
-                           &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
-                           WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE);
-#endif
-    ret = Transform_Sha512(sha512);
-    if (ret != 0)
-        return ret;
-
-    #ifdef LITTLE_ENDIAN_ORDER
-        ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE);
-    #endif
-
-    return 0;
-}
-
-#ifdef WOLFSSL_SHA512
-
-int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash)
-{
-#ifdef LITTLE_ENDIAN_ORDER
-    word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
-#endif
-
-    if (sha512 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef LITTLE_ENDIAN_ORDER
-    ByteReverseWords64((word64*)digest, (word64*)sha512->digest,
-                                                         WC_SHA512_DIGEST_SIZE);
-    XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE);
-#else
-    XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
-#endif
-
-    return 0;
-}
-
-int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
-{
-    int ret;
-
-    if (sha512 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
-    if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha512(&sha512->asyncDev, hash, NULL,
-                                            WC_SHA512_DIGEST_SIZE);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    ret = Sha512Final(sha512);
-    if (ret != 0)
-        return ret;
-
-    XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
-
-    return InitSha512(sha512);  /* reset state */
-}
-
-
-int wc_InitSha512(wc_Sha512* sha512)
-{
-    return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID);
-}
-
-void wc_Sha512Free(wc_Sha512* sha512)
-{
-    if (sha512 == NULL)
-        return;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    if (sha512->W != NULL) {
-        XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        sha512->W = NULL;
-    }
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
-    wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-
-#if defined(HAVE_INTEL_AVX1)
-
-static word64 mBYTE_FLIP_MASK[] =  { 0x0001020304050607, 0x08090a0b0c0d0e0f };
-
-#define W_0     xmm0
-#define W_2     xmm1
-#define W_4     xmm2
-#define W_6     xmm3
-#define W_8     xmm4
-#define W_10    xmm5
-#define W_12    xmm6
-#define W_14    xmm7
-
-#define W_M15   xmm12
-#define W_M7    xmm13
-#define MASK    xmm14
-
-#define XTMP1   xmm8
-#define XTMP2   xmm9
-#define XTMP3   xmm10
-#define XTMP4   xmm11
-
-#define XMM_REGS \
-    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",       \
-    "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
-
-#define _VPALIGNR(dest, src1, src2, bits)                               \
-    "vpalignr	$" #bits ", %%" #src2 ", %%" #src1 ", %%" #dest "\n\t"
-#define VPALIGNR(dest, src1, src2, bits) \
-       _VPALIGNR(dest, src1, src2, bits)
-
-#define _V_SHIFT_R(dest, src, bits)                             \
-    "vpsrlq	$" #bits ", %%" #src ", %%" #dest "\n\t"
-#define V_SHIFT_R(dest, src, bits) \
-       _V_SHIFT_R(dest, src, bits)
-
-#define _V_SHIFT_L(dest, src, bits)                             \
-    "vpsllq	$" #bits ", %%" #src ", %%" #dest "\n\t"
-#define V_SHIFT_L(dest, src, bits) \
-       _V_SHIFT_L(dest, src, bits)
-
-#define _V_ADD(dest, src1, src2)                                \
-    "vpaddq	%%" #src1 ", %%" #src2 ", %%" #dest "\n\t"
-#define V_ADD(dest, src1, src2) \
-       _V_ADD(dest, src1, src2)
-
-#define _V_XOR(dest, src1, src2)                                \
-    "vpxor	%%" #src1 ", %%" #src2 ", %%" #dest "\n\t"
-#define V_XOR(dest, src1, src2) \
-       _V_XOR(dest, src1, src2)
-
-#define _V_OR(dest, src1, src2)                                 \
-    "vpor	%%" #src1 ", %%" #src2 ", %%" #dest "\n\t"
-#define V_OR(dest, src1, src2) \
-       _V_OR(dest, src1, src2)
-
-#define RA  %%r8
-#define RB  %%r9
-#define RC  %%r10
-#define RD  %%r11
-#define RE  %%r12
-#define RF  %%r13
-#define RG  %%r14
-#define RH  %%r15
-
-#define STATE_REGS "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-
-#define L1  "%%rax"
-#define L2  "%%rcx"
-#define L3  "%%rdx"
-#define L4  "%%rbx"
-#define WX  "%%rsp"
-
-#define WORK_REGS "rax", "rbx", "rcx", "rdx"
-
-#define RND_0_1(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = e >>> 23 */                              \
-    "rorq	 $23, " L1 "\n\t"                    \
-
-#define RND_0_2(a,b,c,d,e,f,g,h,i)                   \
-    /* L3 = a */                                     \
-    "movq	"#a", " L3 "\n\t"                    \
-    /* L2 = f */                                     \
-    "movq	"#f", " L2 "\n\t"                    \
-    /* h += W_X[i] */                                \
-    "addq	("#i")*8(" WX "), "#h"\n\t"          \
-    /* L2 = f ^ g */                                 \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_0_2_A(a,b,c,d,e,f,g,h,i)                 \
-    /* L3 = a */                                     \
-    "movq	"#a", " L3 "\n\t"                    \
-    /* L2 = f */                                     \
-    "movq	"#f", " L2 "\n\t"                    \
-
-#define RND_0_2_B(a,b,c,d,e,f,g,h,i)                 \
-    /* h += W_X[i] */                                \
-    "addq	("#i")*8(" WX "), "#h"\n\t"          \
-    /* L2 = f ^ g */                                 \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_0_3(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = (e >>> 23) ^ e */                        \
-    "xorq	"#e", " L1 "\n\t"                    \
-    /* L2 = (f ^ g) & e */                           \
-    "andq	"#e", " L2 "\n\t"                    \
-
-#define RND_0_4(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = ((e >>> 23) ^ e) >>> 4 */                \
-    "rorq	 $4, " L1 "\n\t"                     \
-    /* L2 = ((f ^ g) & e) ^ g */                     \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_0_5(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = (((e >>> 23) ^ e) >>> 4) ^ e */          \
-    "xorq	"#e", " L1 "\n\t"                    \
-    /* h += Ch(e,f,g) */                             \
-    "addq	" L2 ", "#h"\n\t"                    \
-
-#define RND_0_6(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = ((((e >>> 23) ^ e) >>> 4) ^ e) >>> 14 */ \
-    "rorq	$14, " L1 "\n\t"                     \
-    /* L3 = a ^ b */                                 \
-    "xorq	"#b", " L3 "\n\t"                    \
-
-#define RND_0_7(a,b,c,d,e,f,g,h,i)                   \
-    /* h += Sigma1(e) */                             \
-    "addq	" L1 ", "#h"\n\t"                    \
-    /* L2 = a */                                     \
-    "movq	"#a", " L2 "\n\t"                    \
-
-#define RND_0_8(a,b,c,d,e,f,g,h,i)                   \
-    /* L4 = (a ^ b) & (b ^ c) */                     \
-    "andq	" L3 ", " L4 "\n\t"                  \
-    /* L2 = a >>> 5 */                               \
-    "rorq	$5, " L2 "\n\t"                      \
-
-#define RND_0_9(a,b,c,d,e,f,g,h,i)                   \
-    /* L2 = (a >>> 5) ^ a */                         \
-    "xorq	"#a", " L2 "\n\t"                    \
-    /* L4 = ((a ^ b) & (b ^ c) ^ b */                \
-    "xorq	"#b", " L4 "\n\t"                    \
-
-#define RND_0_10(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = ((a >>> 5) ^ a) >>> 6 */                 \
-    "rorq	 $6, " L2 "\n\t"                     \
-    /* d += h */                                     \
-    "addq	"#h", "#d"\n\t"                      \
-
-#define RND_0_11(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = (((a >>> 5) ^ a) >>> 6) ^ a */           \
-    "xorq	"#a", " L2 "\n\t"                    \
-    /* h += Sigma0(a) */                             \
-    "addq	" L4 ", "#h"\n\t"                    \
-
-#define RND_0_12(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = ((((a >>> 5) ^ a) >>> 6) ^ a) >>> 28 */  \
-    "rorq	$28, " L2 "\n\t"                     \
-    /* d (= e next RND) */                           \
-    "movq	"#d", " L1 "\n\t"                    \
-    /* h += Maj(a,b,c) */                            \
-    "addq	" L2 ", "#h"\n\t"                    \
-
-#define RND_1_1(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = e >>> 23 */                              \
-    "rorq	 $23, " L1 "\n\t"                    \
-
-#define RND_1_2(a,b,c,d,e,f,g,h,i)                   \
-    /* L4 = a */                                     \
-    "movq	"#a", " L4 "\n\t"                    \
-    /* L2 = f */                                     \
-    "movq	"#f", " L2 "\n\t"                    \
-    /* h += W_X[i] */                                \
-    "addq	("#i")*8(" WX "), "#h"\n\t"          \
-    /* L2 = f ^ g */                                 \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_1_2_A(a,b,c,d,e,f,g,h,i)                 \
-    /* L4 = a */                                     \
-    "movq	"#a", " L4 "\n\t"                    \
-    /* L2 = f */                                     \
-    "movq	"#f", " L2 "\n\t"                    \
-
-#define RND_1_2_B(a,b,c,d,e,f,g,h,i)                 \
-    /* h += W_X[i] */                                \
-    "addq	("#i")*8(" WX "), "#h"\n\t"          \
-    /* L2 = f ^ g */                                 \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_1_3(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = (e >>> 23) ^ e */                        \
-    "xorq	"#e", " L1 "\n\t"                    \
-    /* L2 = (f ^ g) & e */                           \
-    "andq	"#e", " L2 "\n\t"                    \
-
-#define RND_1_4(a,b,c,d,e,f,g,h,i)                   \
-    /* ((e >>> 23) ^ e) >>> 4 */                     \
-    "rorq	 $4, " L1 "\n\t"                     \
-    /* ((f ^ g) & e) ^ g */                          \
-    "xorq	"#g", " L2 "\n\t"                    \
-
-#define RND_1_5(a,b,c,d,e,f,g,h,i)                   \
-    /* (((e >>> 23) ^ e) >>> 4) ^ e */               \
-    "xorq	"#e", " L1 "\n\t"                    \
-    /* h += Ch(e,f,g) */                             \
-    "addq	" L2 ", "#h"\n\t"                    \
-
-#define RND_1_6(a,b,c,d,e,f,g,h,i)                   \
-    /* L1 = ((((e >>> 23) ^ e) >>> 4) ^ e) >>> 14 */ \
-    "rorq	$14, " L1 "\n\t"                     \
-    /* L4 = a ^ b */                                 \
-    "xorq	"#b", " L4 "\n\t"                    \
-
-#define RND_1_7(a,b,c,d,e,f,g,h,i)                   \
-    /* h += Sigma1(e) */                             \
-    "addq	" L1 ", "#h"\n\t"                    \
-    /* L2 = a */                                     \
-    "movq	"#a", " L2 "\n\t"                    \
- 
-#define RND_1_8(a,b,c,d,e,f,g,h,i)                   \
-    /* L3 = (a ^ b) & (b ^ c) */                     \
-    "andq	" L4 ", " L3 "\n\t"                  \
-    /* L2 = a >>> 5 */                               \
-    "rorq	$5, " L2 "\n\t"                      \
-
-#define RND_1_9(a,b,c,d,e,f,g,h,i)                   \
-    /* L2 = (a >>> 5) ^ a */                         \
-    "xorq	"#a", " L2 "\n\t"                    \
-    /* L3 = ((a ^ b) & (b ^ c) ^ b */                \
-    "xorq	"#b", " L3 "\n\t"                    \
-
-#define RND_1_10(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = ((a >>> 5) ^ a) >>> 6 */                 \
-    "rorq	 $6, " L2 "\n\t"                     \
-    /* d += h */                                     \
-    "addq	"#h", "#d"\n\t"                      \
-
-#define RND_1_11(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = (((a >>> 5) ^ a) >>> 6) ^ a */           \
-    "xorq	"#a", " L2 "\n\t"                    \
-    /* h += Sigma0(a) */                             \
-    "addq	" L3 ", "#h"\n\t"                    \
-
-#define RND_1_12(a,b,c,d,e,f,g,h,i)                  \
-    /* L2 = ((((a >>> 5) ^ a) >>> 6) ^ a) >>> 28 */  \
-    "rorq	$28, " L2 "\n\t"                     \
-    /* d (= e next RND) */                           \
-    "movq	"#d", " L1 "\n\t"                    \
-    /* h += Maj(a,b,c) */                            \
-    "addq	" L2 ", "#h"\n\t"                    \
-
-
-#define MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \
-            RND_0_1(a,b,c,d,e,f,g,h,i)                                  \
-    VPALIGNR(W_M15, W_2, W_0, 8)                                        \
-    VPALIGNR(W_M7, W_10, W_8, 8)                                        \
-            RND_0_2(a,b,c,d,e,f,g,h,i)                                  \
-    V_SHIFT_R(XTMP1, W_M15, 1)                                          \
-    V_SHIFT_L(XTMP2, W_M15, 63)                                         \
-            RND_0_3(a,b,c,d,e,f,g,h,i)                                  \
-            RND_0_4(a,b,c,d,e,f,g,h,i)                                  \
-    V_SHIFT_R(XTMP3, W_M15, 8)                                          \
-    V_SHIFT_L(XTMP4, W_M15, 56)                                         \
-            RND_0_5(a,b,c,d,e,f,g,h,i)                                  \
-            RND_0_6(a,b,c,d,e,f,g,h,i)                                  \
-    V_OR(XTMP1, XTMP2, XTMP1)                                           \
-    V_OR(XTMP3, XTMP4, XTMP3)                                           \
-            RND_0_7(a,b,c,d,e,f,g,h,i)                                  \
-            RND_0_8(a,b,c,d,e,f,g,h,i)                                  \
-    V_SHIFT_R(XTMP4, W_M15, 7)                                          \
-    V_XOR(XTMP1, XTMP3, XTMP1)                                          \
-            RND_0_9(a,b,c,d,e,f,g,h,i)                                  \
-            RND_0_10(a,b,c,d,e,f,g,h,i)                                 \
-    V_XOR(XTMP1, XTMP4, XTMP1)                                          \
-    V_ADD(W_0, W_0, W_M7)                                               \
-            RND_0_11(a,b,c,d,e,f,g,h,i)                                 \
-            RND_0_12(a,b,c,d,e,f,g,h,i)                                 \
-            RND_1_1(h,a,b,c,d,e,f,g,i+1)                                \
-    V_ADD(W_0, W_0, XTMP1)                                              \
-            RND_1_2(h,a,b,c,d,e,f,g,i+1)                                \
-    V_SHIFT_R(XTMP1, W_14, 19)                                          \
-    V_SHIFT_L(XTMP2, W_14, 45)                                          \
-            RND_1_3(h,a,b,c,d,e,f,g,i+1)                                \
-            RND_1_4(h,a,b,c,d,e,f,g,i+1)                                \
-    V_SHIFT_R(XTMP3, W_14, 61)                                          \
-    V_SHIFT_L(XTMP4, W_14, 3)                                           \
-            RND_1_5(h,a,b,c,d,e,f,g,i+1)                                \
-            RND_1_6(h,a,b,c,d,e,f,g,i+1)                                \
-            RND_1_7(h,a,b,c,d,e,f,g,i+1)                                \
-    V_OR(XTMP1, XTMP2, XTMP1)                                           \
-    V_OR(XTMP3, XTMP4, XTMP3)                                           \
-            RND_1_8(h,a,b,c,d,e,f,g,i+1)                                \
-            RND_1_9(h,a,b,c,d,e,f,g,i+1)                                \
-    V_XOR(XTMP1, XTMP3, XTMP1)                                          \
-    V_SHIFT_R(XTMP4, W_14, 6)                                           \
-            RND_1_10(h,a,b,c,d,e,f,g,i+1)                               \
-            RND_1_11(h,a,b,c,d,e,f,g,i+1)                               \
-    V_XOR(XTMP1, XTMP4, XTMP1)                                          \
-            RND_1_12(h,a,b,c,d,e,f,g,i+1)                               \
-    V_ADD(W_0, W_0, XTMP1)                                              \
-
-#define RND_ALL_2(a, b, c, d, e, f, g, h, i) \
-    RND_0_1 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_2 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_3 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_4 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_5 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_6 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_7 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_8 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_9 (a, b, c, d, e, f, g, h, i )     \
-    RND_0_10(a, b, c, d, e, f, g, h, i )     \
-    RND_0_11(a, b, c, d, e, f, g, h, i )     \
-    RND_0_12(a, b, c, d, e, f, g, h, i )     \
-    RND_1_1 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_2 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_3 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_4 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_5 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_6 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_7 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_8 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_9 (h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_10(h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_11(h, a, b, c, d, e, f, g, i+1)    \
-    RND_1_12(h, a, b, c, d, e, f, g, i+1)
-
-
-#if defined(HAVE_INTEL_RORX)
-
-#define RND_RORX_0_1(a, b, c, d, e, f, g, h, i) \
-    /* L1 = e>>>14 */                           \
-    "rorxq	$14, "#e", " L1 "\n\t"          \
-    /* L2 = e>>>18 */                           \
-    "rorxq	$18, "#e", " L2 "\n\t"          \
-    /* Prev RND: h += Maj(a,b,c) */             \
-    "addq	" L3 ", "#a"\n\t"               \
-
-#define RND_RORX_0_2(a, b, c, d, e, f, g, h, i) \
-    /* h += w_k */                              \
-    "addq	("#i")*8(" WX "), "#h"\n\t"     \
-    /* L3 = f */                                \
-    "movq	"#f", " L3 "\n\t"               \
-    /* L2 = (e>>>14) ^ (e>>>18) */              \
-    "xorq	" L1 ", " L2 "\n\t"             \
-
-#define RND_RORX_0_3(a, b, c, d, e, f, g, h, i) \
-    /* L3 = f ^ g */                            \
-    "xorq	"#g", " L3 "\n\t"               \
-    /* L1 = e>>>41 */                           \
-    "rorxq	$41, "#e", " L1 "\n\t"          \
-    /* L1 = Sigma1(e) */                        \
-    "xorq	" L2 ", " L1 "\n\t"             \
-
-#define RND_RORX_0_4(a, b, c, d, e, f, g, h, i) \
-    /* L3 = (f ^ g) & e */                      \
-    "andq	"#e", " L3 "\n\t"               \
-    /* h += Sigma1(e) */                        \
-    "addq	" L1 ", "#h"\n\t"               \
-    /* L1 = a>>>28 */                           \
-    "rorxq	$28, "#a", " L1 "\n\t"          \
-
-#define RND_RORX_0_5(a, b, c, d, e, f, g, h, i) \
-    /* L2 = a>>>34 */                           \
-    "rorxq	$34, "#a", " L2 "\n\t"          \
-    /* L3 = Ch(e,f,g) */                        \
-    "xorq	"#g", " L3 "\n\t"               \
-    /* L2 = (a>>>28) ^ (a>>>34) */              \
-    "xorq	" L1 ", " L2 "\n\t"             \
-
-#define RND_RORX_0_6(a, b, c, d, e, f, g, h, i) \
-    /* L1 = a>>>39 */                           \
-    "rorxq	$39, "#a", " L1 "\n\t"          \
-    /* h += Ch(e,f,g) */                        \
-    "addq	" L3 ", "#h"\n\t"               \
-    /* L1 = Sigma0(a) */                        \
-    "xorq	" L2 ", " L1 "\n\t"             \
-
-#define RND_RORX_0_7(a, b, c, d, e, f, g, h, i) \
-    /* L3 = b */                                \
-    "movq	"#b", " L3 "\n\t"               \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */  \
-    "addq	"#h", "#d"\n\t"                 \
-    /* L3 = a ^ b */                            \
-    "xorq	"#a", " L3 "\n\t"               \
-
-#define RND_RORX_0_8(a, b, c, d, e, f, g, h, i) \
-    /* L4 = (a ^ b) & (b ^ c) */                \
-    "andq	" L3 ", " L4 "\n\t"             \
-    /* h += Sigma0(a) */                        \
-    "addq	" L1 ", "#h"\n\t"               \
-    /* L4 = Maj(a,b,c) */                       \
-    "xorq	"#b", " L4 "\n\t"               \
-
-#define RND_RORX_1_1(a, b, c, d, e, f, g, h, i) \
-    /* L1 = e>>>14 */                           \
-    "rorxq	$14, "#e", " L1 "\n\t"          \
-    /* L2 = e>>>18 */                           \
-    "rorxq	$18, "#e", " L2 "\n\t"          \
-    /* Prev RND: h += Maj(a,b,c) */             \
-    "addq	" L4 ", "#a"\n\t"               \
-
-#define RND_RORX_1_2(a, b, c, d, e, f, g, h, i) \
-    /* h += w_k */                              \
-    "addq	("#i")*8(" WX "), "#h"\n\t"     \
-    /* L4 = f */                                \
-    "movq	"#f", " L4 "\n\t"               \
-    /* L2 = (e>>>14) ^ (e>>>18) */              \
-    "xorq	" L1 ", " L2 "\n\t"             \
-
-#define RND_RORX_1_3(a, b, c, d, e, f, g, h, i) \
-    /* L4 = f ^ g */                            \
-    "xorq	"#g", " L4 "\n\t"               \
-    /* L1 = e>>>41 */                           \
-    "rorxq	$41, "#e", " L1 "\n\t"          \
-    /* L1 = Sigma1(e) */                        \
-    "xorq	" L2 ", " L1 "\n\t"             \
-
-#define RND_RORX_1_4(a, b, c, d, e, f, g, h, i) \
-    /* L4 = (f ^ g) & e */                      \
-    "andq	"#e", " L4 "\n\t"               \
-    /* h += Sigma1(e) */                        \
-    "addq	" L1 ", "#h"\n\t"               \
-    /* L1 = a>>>28 */                           \
-    "rorxq	$28, "#a", " L1 "\n\t"          \
-
-#define RND_RORX_1_5(a, b, c, d, e, f, g, h, i) \
-    /* L2 = a>>>34 */                           \
-    "rorxq	$34, "#a", " L2 "\n\t"          \
-    /* L4 = Ch(e,f,g) */                        \
-    "xorq	"#g", " L4 "\n\t"               \
-    /* L2 = (a>>>28) ^ (a>>>34) */              \
-    "xorq	" L1 ", " L2 "\n\t"             \
-
-#define RND_RORX_1_6(a, b, c, d, e, f, g, h, i) \
-    /* L1 = a>>>39 */                           \
-    "rorxq	$39, "#a", " L1 "\n\t"          \
-    /* h += Ch(e,f,g) */                        \
-    "addq	" L4 ", "#h"\n\t"               \
-    /* L1 = Sigma0(a) */                        \
-    "xorq	" L2 ", " L1 "\n\t"             \
-
-#define RND_RORX_1_7(a, b, c, d, e, f, g, h, i) \
-    /* L4 = b */                                \
-    "movq	"#b", " L4 "\n\t"               \
-    /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */  \
-    "addq	"#h", "#d"\n\t"                 \
-    /* L4 = a ^ b */                            \
-    "xorq	"#a", " L4 "\n\t"               \
-
-#define RND_RORX_1_8(a, b, c, d, e, f, g, h, i) \
-    /* L2 = (a ^ b) & (b ^ c) */                \
-    "andq	" L4 ", " L3 "\n\t"             \
-    /* h += Sigma0(a) */                        \
-    "addq	" L1 ", "#h"\n\t"               \
-    /* L3 = Maj(a,b,c) */                       \
-    "xorq	"#b", " L3 "\n\t"               \
-
-#define RND_RORX_ALL_2(a, b, c, d, e, f, g, h, i) \
-    RND_RORX_0_1(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_2(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_3(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_4(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_5(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_6(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_7(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_0_8(a, b, c, d, e, f, g, h, i+0)     \
-    RND_RORX_1_1(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_2(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_3(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_4(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_5(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_6(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_7(h, a, b, c, d, e, f, g, i+1)     \
-    RND_RORX_1_8(h, a, b, c, d, e, f, g, i+1)     \
-
-#define RND_RORX_ALL_4(a, b, c, d, e, f, g, h, i) \
-    RND_RORX_ALL_2(a, b, c, d, e, f, g, h, i+0)   \
-    RND_RORX_ALL_2(g, h, a, b, c, d, e, f, i+2)
-
-#define MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \
-            RND_RORX_0_1(a,b,c,d,e,f,g,h,i)                                 \
-    VPALIGNR(W_M15, W_2, W_0, 8)                                            \
-    VPALIGNR(W_M7, W_10, W_8, 8)                                            \
-            RND_RORX_0_2(a,b,c,d,e,f,g,h,i)                                 \
-    V_SHIFT_R(XTMP1, W_M15, 1)                                              \
-    V_SHIFT_L(XTMP2, W_M15, 63)                                             \
-            RND_RORX_0_3(a,b,c,d,e,f,g,h,i)                                 \
-    V_SHIFT_R(XTMP3, W_M15, 8)                                              \
-    V_SHIFT_L(XTMP4, W_M15, 56)                                             \
-            RND_RORX_0_4(a,b,c,d,e,f,g,h,i)                                 \
-    V_OR(XTMP1, XTMP2, XTMP1)                                               \
-    V_OR(XTMP3, XTMP4, XTMP3)                                               \
-            RND_RORX_0_5(a,b,c,d,e,f,g,h,i)                                 \
-    V_SHIFT_R(XTMP4, W_M15, 7)                                              \
-    V_XOR(XTMP1, XTMP3, XTMP1)                                              \
-            RND_RORX_0_6(a,b,c,d,e,f,g,h,i)                                 \
-    V_XOR(XTMP1, XTMP4, XTMP1)                                              \
-    V_ADD(W_0, W_0, W_M7)                                                   \
-            RND_RORX_0_7(a,b,c,d,e,f,g,h,i)                                 \
-            RND_RORX_0_8(a,b,c,d,e,f,g,h,i)                                 \
-    V_ADD(W_0, W_0, XTMP1)                                                  \
-            RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1)                               \
-    V_SHIFT_R(XTMP1, W_14, 19)                                              \
-    V_SHIFT_L(XTMP2, W_14, 45)                                              \
-            RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1)                               \
-    V_SHIFT_R(XTMP3, W_14, 61)                                              \
-    V_SHIFT_L(XTMP4, W_14, 3)                                               \
-            RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1)                               \
-    V_OR(XTMP1, XTMP2, XTMP1)                                               \
-    V_OR(XTMP3, XTMP4, XTMP3)                                               \
-            RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1)                               \
-            RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1)                               \
-    V_XOR(XTMP1, XTMP3, XTMP1)                                              \
-    V_SHIFT_R(XTMP4, W_14, 6)                                               \
-            RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1)                               \
-            RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1)                               \
-    V_XOR(XTMP1, XTMP4, XTMP1)                                              \
-            RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1)                               \
-    V_ADD(W_0, W_0, XTMP1)                                                  \
-
-#endif
-
-#define _INIT_MASK(mask) \
-    "vmovdqu %[mask], %%" #mask "\n\t"
-#define INIT_MASK(mask) \
-       _INIT_MASK(mask)
-
-#define _LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg)           \
-    "vmovdqu	" #i1 "*16(%%" #reg "), %%" #xmm1 "\n\t"   \
-    "vmovdqu	" #i2 "*16(%%" #reg "), %%" #xmm2 "\n\t"   \
-    "vpshufb	%%" #mask ", %%" #xmm1 ", %%" #xmm1 "\n\t" \
-    "vpshufb	%%" #mask ", %%" #xmm2 ", %%" #xmm2 "\n\t"
-#define LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg) \
-       _LOAD_W_2(i1, i2, xmm1, xmm2, mask, reg)
-
-#define LOAD_W(mask, reg)                           \
-    /* X0..3(xmm4..7), W[0..15] = buffer[0.15];  */ \
-    LOAD_W_2(0, 1, W_0 , W_2 , mask, reg)           \
-    LOAD_W_2(2, 3, W_4 , W_6 , mask, reg)           \
-    LOAD_W_2(4, 5, W_8 , W_10, mask, reg)           \
-    LOAD_W_2(6, 7, W_12, W_14, mask, reg)
-
-#define _SET_W_X_2(xmm0, xmm1, reg, i)                          \
-    "vpaddq	" #i "+ 0(%%" #reg "), %%" #xmm0 ", %%xmm8\n\t" \
-    "vpaddq	" #i "+16(%%" #reg "), %%" #xmm1 ", %%xmm9\n\t" \
-    "vmovdqu	%%xmm8, " #i "+ 0(" WX ")\n\t"                  \
-    "vmovdqu	%%xmm9, " #i "+16(" WX ")\n\t"                  \
-
-#define SET_W_X_2(xmm0, xmm1, reg, i) \
-       _SET_W_X_2(xmm0, xmm1, reg, i)
-
-#define SET_W_X(reg)                \
-    SET_W_X_2(W_0 , W_2 , reg,  0)  \
-    SET_W_X_2(W_4 , W_6 , reg, 32)  \
-    SET_W_X_2(W_8 , W_10, reg, 64)  \
-    SET_W_X_2(W_12, W_14, reg, 96)
-
-#define LOAD_DIGEST()                     \
-    "movq	  (%[sha512]), %%r8 \n\t" \
-    "movq	 8(%[sha512]), %%r9 \n\t" \
-    "movq	16(%[sha512]), %%r10\n\t" \
-    "movq	24(%[sha512]), %%r11\n\t" \
-    "movq	32(%[sha512]), %%r12\n\t" \
-    "movq	40(%[sha512]), %%r13\n\t" \
-    "movq	48(%[sha512]), %%r14\n\t" \
-    "movq	56(%[sha512]), %%r15\n\t"
-
-#define STORE_ADD_DIGEST()                \
-    "addq	 %%r8,   (%[sha512])\n\t" \
-    "addq	 %%r9,  8(%[sha512])\n\t" \
-    "addq	%%r10, 16(%[sha512])\n\t" \
-    "addq	%%r11, 24(%[sha512])\n\t" \
-    "addq	%%r12, 32(%[sha512])\n\t" \
-    "addq	%%r13, 40(%[sha512])\n\t" \
-    "addq	%%r14, 48(%[sha512])\n\t" \
-    "addq	%%r15, 56(%[sha512])\n\t"
-
-#define ADD_DIGEST()                      \
-    "addq	  (%[sha512]), %%r8 \n\t" \
-    "addq	 8(%[sha512]), %%r9 \n\t" \
-    "addq	16(%[sha512]), %%r10\n\t" \
-    "addq	24(%[sha512]), %%r11\n\t" \
-    "addq	32(%[sha512]), %%r12\n\t" \
-    "addq	40(%[sha512]), %%r13\n\t" \
-    "addq	48(%[sha512]), %%r14\n\t" \
-    "addq	56(%[sha512]), %%r15\n\t"
-
-#define STORE_DIGEST()                    \
-    "movq	 %%r8,   (%[sha512])\n\t" \
-    "movq	 %%r9,  8(%[sha512])\n\t" \
-    "movq	%%r10, 16(%[sha512])\n\t" \
-    "movq	%%r11, 24(%[sha512])\n\t" \
-    "movq	%%r12, 32(%[sha512])\n\t" \
-    "movq	%%r13, 40(%[sha512])\n\t" \
-    "movq	%%r14, 48(%[sha512])\n\t" \
-    "movq	%%r15, 56(%[sha512])\n\t"
-
-#endif /* HAVE_INTEL_AVX1 */
-
-
-/***  Transform Body ***/
-#if defined(HAVE_INTEL_AVX1)
-static int Transform_Sha512_AVX1(wc_Sha512* sha512)
-{
-    __asm__ __volatile__ (
-
-        /* 16 Ws plus loop counter. */
-        "subq	$136, %%rsp\n\t"
-        "leaq	64(%[sha512]), %%rax\n\t"
-
-    INIT_MASK(MASK)
-    LOAD_DIGEST()
-
-    LOAD_W(MASK, rax)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-        /* b */
-        "movq	%%r9, " L4 "\n\t"
-        /* e */
-        "movq	%%r12, " L1 "\n\t"
-        /* b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-    SET_W_X(rsi)
-
-        "addq	$128, %%rsi\n\t"
-
-    MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched2(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    MsgSched2(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched2(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6)
-    MsgSched2(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched2(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10)
-    MsgSched2(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12)
-    MsgSched2(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-        "subl	$1, 16*8(" WX ")\n\t"
-        "jne	1b\n\t"
-
-    SET_W_X(rsi)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    STORE_ADD_DIGEST()
-
-        "addq	$136, %%rsp\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-
-static int Transform_Sha512_AVX1_Len(wc_Sha512* sha512, word32 len)
-{
-    __asm__ __volatile__ (
-
-        "movq	224(%[sha512]), %%rsi\n\t"
-        "leaq	%[K512], %%rdx\n\t"
-
-    INIT_MASK(MASK)
-    LOAD_DIGEST()
-
-        "# Start of processing a block\n"
-        "2:\n\t"
-
-        /* 16 Ws plus loop counter and K512. len goes into -4(%rsp).
-         * Debug needs more stack space. */
-        "subq	$256, %%rsp\n\t"
-
-    LOAD_W(MASK, rsi)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        /* b */
-        "movq	%%r9, " L4 "\n\t"
-        /* e */
-        "movq	%%r12, " L1 "\n\t"
-        /* b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-    SET_W_X(rdx)
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-        "addq	$128, %%rdx\n\t"
-        "movq	%%rdx, 17*8(%%rsp)\n\t"
-
-    MsgSched2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched2(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    MsgSched2(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched2(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6)
-    MsgSched2(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched2(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10)
-    MsgSched2(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12)
-    MsgSched2(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-        "movq	17*8(%%rsp), %%rdx\n\t"
-
-    SET_W_X(rdx)
-
-        "subl	$1, 16*8(" WX ")\n\t"
-        "jne	1b\n\t"
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    ADD_DIGEST()
-
-        "addq	$256, %%rsp\n\t"
-        "leaq	%[K512], %%rdx\n\t"
-        "addq	$128, %%rsi\n\t"
-        "subl	$128, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "jnz	2b\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK),
-          [len]    "m" (len),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-#endif /* HAVE_INTEL_AVX1 */
-
-#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX)
-static int Transform_Sha512_AVX1_RORX(wc_Sha512* sha512)
-{
-    __asm__ __volatile__ (
-
-        /* 16 Ws plus loop counter and K512. */
-        "subq	$144, %%rsp\n\t"
-        "leaq	64(%[sha512]), %%rax\n\t"
-
-    INIT_MASK(MASK)
-    LOAD_DIGEST()
-
-    LOAD_W(MASK, rax)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* L3 = 0 (add to prev h) */
-        "xorq	" L3 ", " L3 "\n\t"
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-    SET_W_X(rsi)
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-        "addq	$128, %%rsi\n\t"
-
-    MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched_RORX(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    MsgSched_RORX(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched_RORX(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6)
-    MsgSched_RORX(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched_RORX(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10)
-    MsgSched_RORX(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12)
-    MsgSched_RORX(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    SET_W_X(rsi)
-
-        "subl	$1, 16*8(" WX ")\n\t"
-        "jne	1b\n\t"
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6)
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-        /* Prev RND: h += Maj(a,b,c) */
-        "addq	" L3 ", %%r8\n\t"
-        "addq	$144, %%rsp\n\t"
-
-    STORE_ADD_DIGEST()
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-
-static int Transform_Sha512_AVX1_RORX_Len(wc_Sha512* sha512, word32 len)
-{
-    __asm__ __volatile__ (
-
-        "movq	224(%[sha512]), %%rsi\n\t"
-        "leaq	%[K512], %%rcx\n\t"
-
-    INIT_MASK(MASK)
-    LOAD_DIGEST()
-
-        "# Start of processing a block\n"
-        "2:\n\t"
-
-        /* 16 Ws plus loop counter and K512. len goes into -4(%rsp).
-         * Debug needs more stack space. */
-        "subq	$256, %%rsp\n\t"
-
-    LOAD_W(MASK, rsi)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* L3 = 0 (add to prev h) */
-        "xorq	" L3 ", " L3 "\n\t"
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-    SET_W_X(rcx)
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-        "addq	$128, %%rcx\n\t"
-        "movq	%%rcx, 17*8(%%rsp)\n\t"
-
-    MsgSched_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched_RORX(W_2,W_4,W_6,W_8,W_10,W_12,W_14,W_0,RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    MsgSched_RORX(W_4,W_6,W_8,W_10,W_12,W_14,W_0,W_2,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched_RORX(W_6,W_8,W_10,W_12,W_14,W_0,W_2,W_4,RC,RD,RE,RF,RG,RH,RA,RB, 6)
-    MsgSched_RORX(W_8,W_10,W_12,W_14,W_0,W_2,W_4,W_6,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched_RORX(W_10,W_12,W_14,W_0,W_2,W_4,W_6,W_8,RG,RH,RA,RB,RC,RD,RE,RF,10)
-    MsgSched_RORX(W_12,W_14,W_0,W_2,W_4,W_6,W_8,W_10,RE,RF,RG,RH,RA,RB,RC,RD,12)
-    MsgSched_RORX(W_14,W_0,W_2,W_4,W_6,W_8,W_10,W_12,RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-        "movq	17*8(%%rsp), %%rcx\n\t"
-
-    SET_W_X(rcx)
-
-        "subl	$1, 16*8(" WX ")\n\t"
-        "jne	1b\n\t"
-
-    SET_W_X(rcx)
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6)
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-        /* Prev RND: h += Maj(a,b,c) */
-        "addq	" L3 ", %%r8\n\t"
-        "addq	$256, %%rsp\n\t"
-
-    ADD_DIGEST()
-
-        "leaq	%[K512], %%rcx\n\t"
-        "addq	$128, %%rsi\n\t"
-        "subl	$128, %[len]\n\t"
-
-    STORE_DIGEST()
-
-        "jnz	2b\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK),
-          [len]    "m" (len),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, XMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-#endif /* HAVE_INTEL_AVX2 && HAVE_INTEL_RORX */
-
-#if defined(HAVE_INTEL_AVX2)
-static const unsigned long mBYTE_FLIP_MASK_Y[] =
-   { 0x0001020304050607, 0x08090a0b0c0d0e0f,
-     0x0001020304050607, 0x08090a0b0c0d0e0f };
-
-#define W_Y_0       ymm0
-#define W_Y_4       ymm1
-#define W_Y_8       ymm2
-#define W_Y_12      ymm3
-
-#define X0       xmm0
-#define X1       xmm1
-#define X2       xmm2
-#define X3       xmm3
-#define X4       xmm4
-#define X5       xmm5
-#define X6       xmm6
-#define X7       xmm7
-#define X8       xmm8
-#define X9       xmm9
-#define Y0       ymm0
-#define Y1       ymm1
-#define Y2       ymm2
-#define Y3       ymm3
-#define Y4       ymm4
-#define Y5       ymm5
-#define Y6       ymm6
-#define Y7       ymm7
-
-#define W_Y_M15     ymm12
-#define W_Y_M7      ymm13
-#define W_Y_M2      ymm14
-#define MASK_Y      ymm15
-
-#define YTMP1       ymm8
-#define YTMP2       ymm9
-#define YTMP3       ymm10
-#define YTMP4       ymm11
-
-#define YMM_REGS \
-    "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7",       \
-    "xmm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"
-
-#define _VPERM2I128(dest, src1, src2, sel)                             \
-    "vperm2I128	$" #sel ", %%" #src2 ", %%" #src1 ", %%" #dest "\n\t"
-#define VPERM2I128(dest, src1, src2, sel) \
-       _VPERM2I128(dest, src1, src2, sel)
-
-#define _VPERMQ(dest, src, sel)                                        \
-    "vpermq	$" #sel ", %%" #src ", %%" #dest "\n\t"
-#define VPERMQ(dest, src, sel) \
-       _VPERMQ(dest, src, sel)
-
-#define _VPBLENDD(dest, src1, src2, sel)                               \
-    "vpblendd	$" #sel ", %%" #src2 ", %%" #src1 ", %%" #dest "\n\t"
-#define VPBLENDD(dest, src1, src2, sel) \
-       _VPBLENDD(dest, src1, src2, sel)
-
-#define _V_ADD_I(dest, src1, addr, i)                                  \
-    "vpaddq	 "#i"*8(%%" #addr "), %%" #src1 ", %%" #dest "\n\t"
-#define V_ADD_I(dest, src1, addr, i) \
-       _V_ADD_I(dest, src1, addr, i)
-
-#define _VMOVDQU_I(addr, i, src)                                       \
-    "vmovdqu	 %%" #src ", " #i "*8(%%" #addr ")\n\t"
-#define VMOVDQU_I(addr, i, src) \
-       _VMOVDQU_I(addr, i, src)
-
-#define MsgSched4_AVX2(W_Y_0,W_Y_4,W_Y_8,W_Y_12,a,b,c,d,e,f,g,h,i) \
-            RND_0_1(a,b,c,d,e,f,g,h,i)                             \
-    /* W[-13]..W[-15], W[-12] */                                   \
-    VPBLENDD(W_Y_M15, W_Y_0, W_Y_4, 0x03)                          \
-    /* W[-5]..W[-7], W[-4] */                                      \
-    VPBLENDD(W_Y_M7, W_Y_8, W_Y_12, 0x03)                          \
-            RND_0_2(a,b,c,d,e,f,g,h,i)                             \
-            RND_0_3(a,b,c,d,e,f,g,h,i)                             \
-    /* W_Y_M15 = W[-12]..W[-15] */                                 \
-    VPERMQ(W_Y_M15, W_Y_M15, 0x39)                                 \
-            RND_0_4(a,b,c,d,e,f,g,h,i)                             \
-    /* W_Y_M7 = W[-4]..W[-7] */                                    \
-    VPERMQ(W_Y_M7, W_Y_M7, 0x39)                                   \
-            RND_0_5(a,b,c,d,e,f,g,h,i)                             \
-            RND_0_6(a,b,c,d,e,f,g,h,i)                             \
-    /* W[-15] >>  1 */                                             \
-    V_SHIFT_R(YTMP1, W_Y_M15, 1)                                   \
-            RND_0_7(a,b,c,d,e,f,g,h,i)                             \
-    /* W[-15] << 63 */                                             \
-    V_SHIFT_L(YTMP2, W_Y_M15, 63)                                  \
-            RND_0_8(a,b,c,d,e,f,g,h,i)                             \
-    /* W[-15] >>  8 */                                             \
-    V_SHIFT_R(YTMP3, W_Y_M15, 8)                                   \
-            RND_0_9(a,b,c,d,e,f,g,h,i)                             \
-    /* W[-15] << 56 */                                             \
-    V_SHIFT_L(YTMP4, W_Y_M15, 56)                                  \
-            RND_0_10(a,b,c,d,e,f,g,h,i)                            \
-    /* W[-15] >>> 1 */                                             \
-    V_OR(YTMP1, YTMP2, YTMP1)                                      \
-            RND_0_11(a,b,c,d,e,f,g,h,i)                            \
-    /* W[-15] >>> 8 */                                             \
-    V_OR(YTMP3, YTMP4, YTMP3)                                      \
-            RND_0_12(a,b,c,d,e,f,g,h,i)                            \
-            RND_1_1(h,a,b,c,d,e,f,g,i+1)                           \
-    /* W[-15] >> 7 */                                              \
-    V_SHIFT_R(YTMP4, W_Y_M15, 7)                                   \
-            RND_1_2_A(h,a,b,c,d,e,f,g,i+1)                         \
-    /* (W[-15] >>> 1) ^ (W[-15] >>> 8) */                          \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                     \
-            RND_1_2_B(h,a,b,c,d,e,f,g,i+1)                         \
-    /* (W[-15] >>> 1) ^ (W[-15] >>> 8) ^ (W[-15] >> 7) */          \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                     \
-            RND_1_3(h,a,b,c,d,e,f,g,i+1)                           \
-    /* W[0] = W[-16] + W[-7] */                                    \
-    V_ADD(W_Y_0, W_Y_0, W_Y_M7)                                    \
-            RND_1_4(h,a,b,c,d,e,f,g,i+1)                           \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) */                       \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                     \
-            RND_1_5(h,a,b,c,d,e,f,g,i+1)                           \
-    /* 0, 0, W[-1], W[-2] */                                       \
-    VPERM2I128(W_Y_M2, W_Y_12, W_Y_12, 0x81)                       \
-            RND_1_6(h,a,b,c,d,e,f,g,i+1)                           \
-            RND_1_7(h,a,b,c,d,e,f,g,i+1)                           \
-            RND_1_8(h,a,b,c,d,e,f,g,i+1)                           \
-    /* W[-2] >> 19 */                                              \
-    V_SHIFT_R(YTMP1, W_Y_M2, 19)                                   \
-            RND_1_9(h,a,b,c,d,e,f,g,i+1)                           \
-    /* W[-2] << 45 */                                              \
-    V_SHIFT_L(YTMP2, W_Y_M2, 45)                                   \
-            RND_1_10(h,a,b,c,d,e,f,g,i+1)                          \
-    /* W[-2] >> 61 */                                              \
-    V_SHIFT_R(YTMP3, W_Y_M2, 61)                                   \
-            RND_1_11(h,a,b,c,d,e,f,g,i+1)                          \
-    /* W[-2] <<  3 */                                              \
-    V_SHIFT_L(YTMP4, W_Y_M2, 3)                                    \
-            RND_1_12(h,a,b,c,d,e,f,g,i+1)                          \
-            RND_0_1(g,h,a,b,c,d,e,f,i+2)                           \
-    /* W[-2] >>> 19 */                                             \
-    V_OR(YTMP1, YTMP2, YTMP1)                                      \
-            RND_0_2(g,h,a,b,c,d,e,f,i+2)                           \
-    /* W[-2] >>> 61 */                                             \
-    V_OR(YTMP3, YTMP4, YTMP3)                                      \
-            RND_0_3(g,h,a,b,c,d,e,f,i+2)                           \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */                          \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                     \
-            RND_0_4(g,h,a,b,c,d,e,f,i+2)                           \
-    /* W[-2] >>  6 */                                              \
-    V_SHIFT_R(YTMP4, W_Y_M2, 6)                                    \
-            RND_0_5(g,h,a,b,c,d,e,f,i+2)                           \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */           \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                     \
-            RND_0_6(g,h,a,b,c,d,e,f,i+2)                           \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */           \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                     \
-            RND_0_7(g,h,a,b,c,d,e,f,i+2)                           \
-            RND_0_8(g,h,a,b,c,d,e,f,i+2)                           \
-    /* W[1], W[0], 0, 0 */                                         \
-    VPERM2I128(W_Y_M2, W_Y_0, W_Y_0, 0x08)                         \
-            RND_0_9(g,h,a,b,c,d,e,f,i+2)                           \
-            RND_0_10(g,h,a,b,c,d,e,f,i+2)                          \
-    /* W[-2] >> 19 */                                              \
-    V_SHIFT_R(YTMP1, W_Y_M2, 19)                                   \
-            RND_0_11(g,h,a,b,c,d,e,f,i+2)                          \
-    /* W[-2] << 45 */                                              \
-    V_SHIFT_L(YTMP2, W_Y_M2, 45)                                   \
-            RND_0_12(g,h,a,b,c,d,e,f,i+2)                          \
-            RND_1_1(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[-2] >> 61 */                                              \
-    V_SHIFT_R(YTMP3, W_Y_M2, 61)                                   \
-            RND_1_2(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[-2] <<  3 */                                              \
-    V_SHIFT_L(YTMP4, W_Y_M2, 3)                                    \
-            RND_1_3(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[-2] >>> 19 */                                             \
-    V_OR(YTMP1, YTMP2, YTMP1)                                      \
-            RND_1_4(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[-2] >>> 61 */                                             \
-    V_OR(YTMP3, YTMP4, YTMP3)                                      \
-            RND_1_5(f,g,h,a,b,c,d,e,i+3)                           \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */                          \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                     \
-            RND_1_6(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[-2] >>  6 */                                              \
-    V_SHIFT_R(YTMP4, W_Y_M2, 6)                                    \
-            RND_1_7(f,g,h,a,b,c,d,e,i+3)                           \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */           \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                     \
-            RND_1_8(f,g,h,a,b,c,d,e,i+3)                           \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */           \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                     \
-            RND_1_9(f,g,h,a,b,c,d,e,i+3)                           \
-            RND_1_10(f,g,h,a,b,c,d,e,i+3)                          \
-            RND_1_11(f,g,h,a,b,c,d,e,i+3)                          \
-            RND_1_12(f,g,h,a,b,c,d,e,i+3)                          \
-
-#define MsgSched2_AVX2(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,f,g,h,i) \
-            RND_0_1(a,b,c,d,e,f,g,h,i)                                       \
-    VPALIGNR(W_Y_M15, W_2, W_0, 8)                                           \
-    VPALIGNR(W_Y_M7, W_10, W_8, 8)                                           \
-            RND_0_2(a,b,c,d,e,f,g,h,i)                                       \
-    V_SHIFT_R(YTMP1, W_Y_M15, 1)                                             \
-    V_SHIFT_L(YTMP2, W_Y_M15, 63)                                            \
-            RND_0_3(a,b,c,d,e,f,g,h,i)                                       \
-            RND_0_4(a,b,c,d,e,f,g,h,i)                                       \
-    V_SHIFT_R(YTMP3, W_Y_M15, 8)                                             \
-    V_SHIFT_L(YTMP4, W_Y_M15, 56)                                            \
-            RND_0_5(a,b,c,d,e,f,g,h,i)                                       \
-            RND_0_6(a,b,c,d,e,f,g,h,i)                                       \
-    V_OR(YTMP1, YTMP2, YTMP1)                                                \
-    V_OR(YTMP3, YTMP4, YTMP3)                                                \
-            RND_0_7(a,b,c,d,e,f,g,h,i)                                       \
-            RND_0_8(a,b,c,d,e,f,g,h,i)                                       \
-    V_SHIFT_R(YTMP4, W_Y_M15, 7)                                             \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                               \
-            RND_0_9(a,b,c,d,e,f,g,h,i)                                       \
-            RND_0_10(a,b,c,d,e,f,g,h,i)                                      \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                               \
-    V_ADD(W_0, W_0, W_Y_M7)                                                  \
-            RND_0_11(a,b,c,d,e,f,g,h,i)                                      \
-            RND_0_12(a,b,c,d,e,f,g,h,i)                                      \
-            RND_1_1(h,a,b,c,d,e,f,g,i+1)                                     \
-    V_ADD(W_0, W_0, YTMP1)                                                   \
-            RND_1_2(h,a,b,c,d,e,f,g,i+1)                                     \
-    V_SHIFT_R(YTMP1, W_14, 19)                                               \
-    V_SHIFT_L(YTMP2, W_14, 45)                                               \
-            RND_1_3(h,a,b,c,d,e,f,g,i+1)                                     \
-            RND_1_4(h,a,b,c,d,e,f,g,i+1)                                     \
-    V_SHIFT_R(YTMP3, W_14, 61)                                               \
-    V_SHIFT_L(YTMP4, W_14, 3)                                                \
-            RND_1_5(h,a,b,c,d,e,f,g,i+1)                                     \
-            RND_1_6(h,a,b,c,d,e,f,g,i+1)                                     \
-            RND_1_7(h,a,b,c,d,e,f,g,i+1)                                     \
-    V_OR(YTMP1, YTMP2, YTMP1)                                                \
-    V_OR(YTMP3, YTMP4, YTMP3)                                                \
-            RND_1_8(h,a,b,c,d,e,f,g,i+1)                                     \
-            RND_1_9(h,a,b,c,d,e,f,g,i+1)                                     \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                               \
-    V_SHIFT_R(YTMP4, W_14, 6)                                                \
-            RND_1_10(h,a,b,c,d,e,f,g,i+1)                                    \
-            RND_1_11(h,a,b,c,d,e,f,g,i+1)                                    \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                               \
-            RND_1_12(h,a,b,c,d,e,f,g,i+1)                                    \
-    V_ADD(W_0, W_0, YTMP1)                                                   \
-
-#define MsgSched4_AVX2_RORX_SET(W_Y_0,W_Y_4,W_Y_8,W_Y_12,a,b,c,d,e,f,g,h,i) \
-            RND_RORX_0_1(a,b,c,d,e,f,g,h,i)                                 \
-    /* W[-13]..W[-15], W[-12] */                                            \
-    VPBLENDD(W_Y_M15, W_Y_0, W_Y_4, 0x03)                                   \
-    /* W[-5]..W[-7], W[-4] */                                               \
-    VPBLENDD(W_Y_M7, W_Y_8, W_Y_12, 0x03)                                   \
-            RND_RORX_0_2(a,b,c,d,e,f,g,h,i)                                 \
-    /* W_Y_M15 = W[-12]..W[-15] */                                          \
-    VPERMQ(W_Y_M15, W_Y_M15, 0x39)                                          \
-            RND_RORX_0_3(a,b,c,d,e,f,g,h,i)                                 \
-    /* W_Y_M7 = W[-4]..W[-7] */                                             \
-    VPERMQ(W_Y_M7, W_Y_M7, 0x39)                                            \
-            RND_RORX_0_4(a,b,c,d,e,f,g,h,i)                                 \
-    /* W[-15] >>  1 */                                                      \
-    V_SHIFT_R(YTMP1, W_Y_M15, 1)                                            \
-    /* W[-15] << 63 */                                                      \
-    V_SHIFT_L(YTMP2, W_Y_M15, 63)                                           \
-            RND_RORX_0_5(a,b,c,d,e,f,g,h,i)                                 \
-    /* W[-15] >>  8 */                                                      \
-    V_SHIFT_R(YTMP3, W_Y_M15, 8)                                            \
-    /* W[-15] << 56 */                                                      \
-    V_SHIFT_L(YTMP4, W_Y_M15, 56)                                           \
-    /* W[-15] >>> 1 */                                                      \
-    V_OR(YTMP1, YTMP2, YTMP1)                                               \
-    /* W[-15] >>> 8 */                                                      \
-    V_OR(YTMP3, YTMP4, YTMP3)                                               \
-            RND_RORX_0_6(a,b,c,d,e,f,g,h,i)                                 \
-    /* W[-15] >> 7 */                                                       \
-    V_SHIFT_R(YTMP4, W_Y_M15, 7)                                            \
-            RND_RORX_0_7(a,b,c,d,e,f,g,h,i)                                 \
-    /* 0, 0, W[-1], W[-2] */                                                \
-    VPERM2I128(W_Y_M2, W_Y_12, W_Y_12, 0x81)                                \
-            RND_RORX_0_8(a,b,c,d,e,f,g,h,i)                                 \
-            RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1)                               \
-    /* (W[-15] >>> 1) ^ (W[-15] >>> 8) */                                   \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                              \
-            RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1)                               \
-    /* (W[-15] >>> 1) ^ (W[-15] >>> 8) ^ (W[-15] >> 7) */                   \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                              \
-            RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1)                               \
-    /* W[0] = W[-16] + W[-7] */                                             \
-    V_ADD(W_Y_0, W_Y_0, W_Y_M7)                                             \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) */                                \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                              \
-            RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1)                               \
-    /* W[-2] >> 19 */                                                       \
-    V_SHIFT_R(YTMP1, W_Y_M2, 19)                                            \
-    /* W[-2] << 45 */                                                       \
-    V_SHIFT_L(YTMP2, W_Y_M2, 45)                                            \
-            RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1)                               \
-    /* W[-2] >> 61 */                                                       \
-    V_SHIFT_R(YTMP3, W_Y_M2, 61)                                            \
-    /* W[-2] <<  3 */                                                       \
-    V_SHIFT_L(YTMP4, W_Y_M2, 3)                                             \
-    /* W[-2] >>> 19 */                                                      \
-    V_OR(YTMP1, YTMP2, YTMP1)                                               \
-            RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1)                               \
-    /* W[-2] >>> 61 */                                                      \
-    V_OR(YTMP3, YTMP4, YTMP3)                                               \
-            RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1)                               \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */                                   \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                              \
-            RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1)                               \
-    /* W[-2] >>  6 */                                                       \
-    V_SHIFT_R(YTMP4, W_Y_M2, 6)                                             \
-            RND_RORX_0_1(g,h,a,b,c,d,e,f,i+2)                               \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */                    \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                              \
-            RND_RORX_0_2(g,h,a,b,c,d,e,f,i+2)                               \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */                    \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                              \
-            RND_RORX_0_3(g,h,a,b,c,d,e,f,i+2)                               \
-    /* W[1], W[0], 0, 0 */                                                  \
-    VPERM2I128(W_Y_M2, W_Y_0, W_Y_0, 0x08)                                  \
-            RND_RORX_0_4(g,h,a,b,c,d,e,f,i+2)                               \
-            RND_RORX_0_5(g,h,a,b,c,d,e,f,i+2)                               \
-    /* W[-2] >> 19 */                                                       \
-    V_SHIFT_R(YTMP1, W_Y_M2, 19)                                            \
-    /* W[-2] << 45 */                                                       \
-    V_SHIFT_L(YTMP2, W_Y_M2, 45)                                            \
-            RND_RORX_0_6(g,h,a,b,c,d,e,f,i+2)                               \
-    /* W[-2] >> 61 */                                                       \
-    V_SHIFT_R(YTMP3, W_Y_M2, 61)                                            \
-    /* W[-2] <<  3 */                                                       \
-    V_SHIFT_L(YTMP4, W_Y_M2, 3)                                             \
-    /* W[-2] >>> 19 */                                                      \
-    V_OR(YTMP1, YTMP2, YTMP1)                                               \
-            RND_RORX_0_7(g,h,a,b,c,d,e,f,i+2)                               \
-    /* W[-2] >>> 61 */                                                      \
-    V_OR(YTMP3, YTMP4, YTMP3)                                               \
-            RND_RORX_0_8(g,h,a,b,c,d,e,f,i+2)                               \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) */                                   \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                              \
-            RND_RORX_1_1(f,g,h,a,b,c,d,e,i+3)                               \
-    /* W[-2] >>  6 */                                                       \
-    V_SHIFT_R(YTMP4, W_Y_M2, 6)                                             \
-            RND_RORX_1_2(f,g,h,a,b,c,d,e,i+3)                               \
-            RND_RORX_1_3(f,g,h,a,b,c,d,e,i+3)                               \
-    /* (W[-2] >>> 19) ^ (W[-2] >>> 61) ^ (W[-2] >> 6) */                    \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                              \
-            RND_RORX_1_4(f,g,h,a,b,c,d,e,i+3)                               \
-            RND_RORX_1_5(f,g,h,a,b,c,d,e,i+3)                               \
-    /* W[0] = W[-16] + W[-7] + s0(W[-15]) + s1(W[-2]) */                    \
-    V_ADD(W_Y_0, W_Y_0, YTMP1)                                              \
-            RND_RORX_1_6(f,g,h,a,b,c,d,e,i+3)                               \
-    V_ADD_I(YTMP1, W_Y_0, rsi, i)                                           \
-            RND_RORX_1_7(f,g,h,a,b,c,d,e,i+3)                               \
-            RND_RORX_1_8(f,g,h,a,b,c,d,e,i+3)                               \
-    VMOVDQU_I(rsp, i, YTMP1)                                                \
-
-#define MsgSched2_AVX2_RORX(W_0,W_2,W_4,W_6,W_8,W_10,W_12,W_14,a,b,c,d,e,  \
-                            f,g,h,i)                                       \
-            RND_RORX_0_1(a,b,c,d,e,f,g,h,i)                                \
-    VPALIGNR(W_Y_M15, W_2, W_0, 8)                                         \
-    VPALIGNR(W_Y_M7, W_10, W_8, 8)                                         \
-            RND_RORX_0_2(a,b,c,d,e,f,g,h,i)                                \
-    V_SHIFT_R(YTMP1, W_Y_M15, 1)                                           \
-    V_SHIFT_L(YTMP2, W_Y_M15, 63)                                          \
-            RND_RORX_0_3(a,b,c,d,e,f,g,h,i)                                \
-    V_SHIFT_R(YTMP3, W_Y_M15, 8)                                           \
-    V_SHIFT_L(YTMP4, W_Y_M15, 56)                                          \
-            RND_RORX_0_4(a,b,c,d,e,f,g,h,i)                                \
-    V_OR(YTMP1, YTMP2, YTMP1)                                              \
-    V_OR(YTMP3, YTMP4, YTMP3)                                              \
-            RND_RORX_0_5(a,b,c,d,e,f,g,h,i)                                \
-    V_SHIFT_R(YTMP4, W_Y_M15, 7)                                           \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                             \
-            RND_RORX_0_6(a,b,c,d,e,f,g,h,i)                                \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                             \
-    V_ADD(W_0, W_0, W_Y_M7)                                                \
-            RND_RORX_0_7(a,b,c,d,e,f,g,h,i)                                \
-            RND_RORX_0_8(a,b,c,d,e,f,g,h,i)                                \
-    V_ADD(W_0, W_0, YTMP1)                                                 \
-            RND_RORX_1_1(h,a,b,c,d,e,f,g,i+1)                              \
-    V_SHIFT_R(YTMP1, W_14, 19)                                             \
-    V_SHIFT_L(YTMP2, W_14, 45)                                             \
-            RND_RORX_1_2(h,a,b,c,d,e,f,g,i+1)                              \
-    V_SHIFT_R(YTMP3, W_14, 61)                                             \
-    V_SHIFT_L(YTMP4, W_14, 3)                                              \
-            RND_RORX_1_3(h,a,b,c,d,e,f,g,i+1)                              \
-    V_OR(YTMP1, YTMP2, YTMP1)                                              \
-    V_OR(YTMP3, YTMP4, YTMP3)                                              \
-            RND_RORX_1_4(h,a,b,c,d,e,f,g,i+1)                              \
-            RND_RORX_1_5(h,a,b,c,d,e,f,g,i+1)                              \
-    V_XOR(YTMP1, YTMP3, YTMP1)                                             \
-    V_SHIFT_R(YTMP4, W_14, 6)                                              \
-            RND_RORX_1_6(h,a,b,c,d,e,f,g,i+1)                              \
-            RND_RORX_1_7(h,a,b,c,d,e,f,g,i+1)                              \
-    V_XOR(YTMP1, YTMP4, YTMP1)                                             \
-            RND_RORX_1_8(h,a,b,c,d,e,f,g,i+1)                              \
-    V_ADD(W_0, W_0, YTMP1)                                                 \
-
-
-#define _INIT_MASK_Y(mask)            \
-    "vmovdqu %[mask], %%"#mask"\n\t"
-#define INIT_MASK_Y(mask) \
-       _INIT_MASK_Y(mask)
-
-/* Load into YMM registers and swap endian. */
-#define _LOAD_BLOCK_W_Y_2(mask, ymm0, ymm1, reg, i)           \
-    /* buffer[0..15] => ymm0..ymm3;  */                       \
-    "vmovdqu	" #i "+ 0(%%" #reg "), %%" #ymm0 "\n\t"       \
-    "vmovdqu	" #i "+32(%%" #reg "), %%" #ymm1 "\n\t"       \
-    "vpshufb	%%" #mask ", %%" #ymm0 ", %%" #ymm0 "\n\t"    \
-    "vpshufb	%%" #mask ", %%" #ymm1 ", %%" #ymm1 "\n\t"
-
-#define LOAD_BLOCK_W_Y_2(mask, ymm1, ymm2, reg, i) \
-       _LOAD_BLOCK_W_Y_2(mask, ymm1, ymm2, reg, i)
-
-#define LOAD_BLOCK_W_Y(mask, reg)                  \
-    LOAD_BLOCK_W_Y_2(mask, W_Y_0, W_Y_4 , reg,  0) \
-    LOAD_BLOCK_W_Y_2(mask, W_Y_8, W_Y_12, reg, 64)
-
-#define _SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i)                    \
-    "vpaddq	" #i "+ 0(%%" #reg "), %%" #ymm0 ", %%" #ymm2 "\n\t"  \
-    "vpaddq	" #i "+32(%%" #reg "), %%" #ymm1 ", %%" #ymm3 "\n\t"  \
-    "vmovdqu	%%" #ymm2 ", " #i "+ 0(" WX ")\n\t"                   \
-    "vmovdqu	%%" #ymm3 ", " #i "+32(" WX ")\n\t"
-
-#define SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i) \
-       _SET_W_Y_2(ymm0, ymm1, ymm2, ymm3, reg, i)
-
-#define SET_BLOCK_W_Y(reg)                          \
-    SET_W_Y_2(W_Y_0, W_Y_4 , YTMP1, YTMP2, reg,  0) \
-    SET_W_Y_2(W_Y_8, W_Y_12, YTMP1, YTMP2, reg, 64)
-
-/* Load into YMM registers and swap endian. */
-#define _LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i)   \
-    "vmovdqu	" #i "+  0(%%" #reg "), %%" #X0 "\n\t"                   \
-    "vmovdqu	" #i "+ 16(%%" #reg "), %%" #X1 "\n\t"                   \
-    "vmovdqu	" #i "+128(%%" #reg "), %%" #X8 "\n\t"                   \
-    "vmovdqu	" #i "+144(%%" #reg "), %%" #X9 "\n\t"                   \
-    "vinserti128	$1, %%" #X8 ", %%" #Y0 ", %%" #Y0 "\n\t"         \
-    "vinserti128	$1, %%" #X9 ", %%" #Y1 ", %%" #Y1 "\n\t"         \
-    "vpshufb	%%" #mask ", %%" #Y0 ", %%" #Y0 "\n\t"                   \
-    "vpshufb	%%" #mask ", %%" #Y1 ", %%" #Y1 "\n\t"
-
-#define LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i) \
-       _LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg, i)
-
-#define LOAD_BLOCK2_W_Y(mask, reg)                           \
-    LOAD_BLOCK2_W_Y_2(mask, Y0, Y1, X0, X1, X8, X9, reg,  0) \
-    LOAD_BLOCK2_W_Y_2(mask, Y2, Y3, X2, X3, X8, X9, reg, 32) \
-    LOAD_BLOCK2_W_Y_2(mask, Y4, Y5, X4, X5, X8, X9, reg, 64) \
-    LOAD_BLOCK2_W_Y_2(mask, Y6, Y7, X6, X7, X8, X9, reg, 96) \
-
-#define SET_BLOCK2_W_Y(reg)                   \
-    SET_W_Y_2(Y0, Y1, YTMP1, YTMP2, reg,   0) \
-    SET_W_Y_2(Y2, Y3, YTMP1, YTMP2, reg,  64) \
-    SET_W_Y_2(Y4, Y5, YTMP1, YTMP2, reg, 128) \
-    SET_W_Y_2(Y6, Y7, YTMP1, YTMP2, reg, 192)
-
-static const word64 K512_AVX2[160] = {
-    W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
-    W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
-    W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
-    W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
-    W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
-    W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
-    W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
-    W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
-    W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
-    W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
-    W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
-    W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
-    W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
-    W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
-    W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
-    W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
-    W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
-    W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
-    W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
-    W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
-    W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
-    W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
-    W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
-    W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
-    W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
-    W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
-    W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
-    W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
-    W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
-    W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
-    W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
-    W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
-    W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
-    W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
-    W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
-    W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
-    W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
-    W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
-    W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
-    W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
-    W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
-    W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
-    W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
-    W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
-    W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
-    W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
-    W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
-    W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
-    W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
-    W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
-    W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
-    W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
-    W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
-    W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
-    W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
-    W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
-    W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
-    W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
-    W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
-    W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
-    W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
-    W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
-    W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
-    W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
-    W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
-    W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
-    W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
-    W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
-    W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
-    W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
-    W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
-    W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
-    W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
-    W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
-    W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
-    W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
-    W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
-    W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
-    W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817),
-    W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
-};
-static const word64* K512_AVX2_END = &K512_AVX2[128];
-
-static int Transform_Sha512_AVX2(wc_Sha512* sha512)
-{
-    __asm__ __volatile__ (
-
-        /* 16 Ws plus loop counter and K512. */
-        "subq	$136, %%rsp\n\t"
-        "leaq	64(%[sha512]), %%rax\n\t"
-
-    INIT_MASK(MASK_Y)
-    LOAD_DIGEST()
-
-    LOAD_BLOCK_W_Y(MASK_Y, rax)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-        /* b */
-        "movq	%%r9, " L4 "\n\t"
-        /* e */
-        "movq	%%r12, " L1 "\n\t"
-        /* b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-    SET_BLOCK_W_Y(rsi)
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-        "addq	$128, %%rsi\n\t"
-
-    MsgSched4_AVX2(W_Y_0,W_Y_4,W_Y_8,W_Y_12,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched4_AVX2(W_Y_4,W_Y_8,W_Y_12,W_Y_0,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched4_AVX2(W_Y_8,W_Y_12,W_Y_0,W_Y_4,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched4_AVX2(W_Y_12,W_Y_0,W_Y_4,W_Y_8,RE,RF,RG,RH,RA,RB,RC,RD,12)
-
-    SET_BLOCK_W_Y(rsi)
-
-        "subl	$1, 16*8(" WX ")\n\t"
-        "jne	1b\n\t"
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 2)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB, 6)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,10)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,12)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    STORE_ADD_DIGEST()
-
-        "addq	$136, %%rsp\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK_Y),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-
-static int Transform_Sha512_AVX2_Len(wc_Sha512* sha512, word32 len)
-{
-    if ((len & WC_SHA512_BLOCK_SIZE) != 0) {
-        XMEMCPY(sha512->buffer, sha512->data, WC_SHA512_BLOCK_SIZE);
-        Transform_Sha512_AVX2(sha512);
-        sha512->data += WC_SHA512_BLOCK_SIZE;
-        len -= WC_SHA512_BLOCK_SIZE;
-        if (len == 0)
-            return 0;
-    }
-
-    __asm__ __volatile__ (
-
-        "movq	224(%[sha512]), %%rcx\n\t"
-
-    INIT_MASK(MASK_Y)
-    LOAD_DIGEST()
-
-        "# Start of processing two blocks\n"
-        "2:\n\t"
-
-        "subq	$1344, %%rsp\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* e */
-        "movq	%%r12, " L1 "\n\t"
-
-    LOAD_BLOCK2_W_Y(MASK_Y, rcx)
-
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-        "\n"
-        "1:\n\t"
-    SET_BLOCK2_W_Y(rsi)
-    MsgSched2_AVX2(Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched2_AVX2(Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y0,RG,RH,RA,RB,RC,RD,RE,RF, 4)
-    MsgSched2_AVX2(Y2,Y3,Y4,Y5,Y6,Y7,Y0,Y1,RE,RF,RG,RH,RA,RB,RC,RD, 8)
-    MsgSched2_AVX2(Y3,Y4,Y5,Y6,Y7,Y0,Y1,Y2,RC,RD,RE,RF,RG,RH,RA,RB,12)
-    MsgSched2_AVX2(Y4,Y5,Y6,Y7,Y0,Y1,Y2,Y3,RA,RB,RC,RD,RE,RF,RG,RH,16)
-    MsgSched2_AVX2(Y5,Y6,Y7,Y0,Y1,Y2,Y3,Y4,RG,RH,RA,RB,RC,RD,RE,RF,20)
-    MsgSched2_AVX2(Y6,Y7,Y0,Y1,Y2,Y3,Y4,Y5,RE,RF,RG,RH,RA,RB,RC,RD,24)
-    MsgSched2_AVX2(Y7,Y0,Y1,Y2,Y3,Y4,Y5,Y6,RC,RD,RE,RF,RG,RH,RA,RB,28)
-        "addq	$256, %%rsi\n\t"
-        "addq	$256, %%rsp\n\t"
-        "cmpq	%[K512_END], %%rsi\n\t"
-        "jne	1b\n\t"
-
-    SET_BLOCK2_W_Y(rsi)
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 4)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 8)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,12)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,16)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,20)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,24)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,28)
-        "subq	$1024, %%rsp\n\t"
-
-    ADD_DIGEST()
-    STORE_DIGEST()
-
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* e */
-        "movq	%%r12, " L1 "\n\t"
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-        "movq	$5, %%rsi\n\t"
-        "\n"
-        "3:\n\t"
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 2)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 6)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,10)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    RND_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,18)
-    RND_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,22)
-    RND_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,26)
-    RND_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,30)
-        "addq	$256, %%rsp\n\t"
-        "subq	$1, %%rsi\n\t"
-        "jnz	3b\n\t"
-
-    ADD_DIGEST()
-
-        "movq	224(%[sha512]), %%rcx\n\t"
-        "addq	$64, %%rsp\n\t"
-        "addq	$256, %%rcx\n\t"
-        "subl	$256, %[len]\n\t"
-        "movq	%%rcx, 224(%[sha512])\n\t"
-
-    STORE_DIGEST()
-
-        "jnz	2b\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK_Y),
-          [len]    "m" (len),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512_AVX2),
-          [K512_END]   "m" (K512_AVX2_END)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-
-#ifdef HAVE_INTEL_RORX
-static int Transform_Sha512_AVX2_RORX(wc_Sha512* sha512)
-{
-    __asm__ __volatile__ (
-
-        /* 16 Ws plus loop counter. */
-        "subq	$136, %%rsp\n\t"
-        "leaq	64(%[sha512]), " L2 "\n\t"
-
-    INIT_MASK(MASK_Y)
-    LOAD_DIGEST()
-
-    LOAD_BLOCK_W_Y(MASK_Y, rcx)
-
-        "movl	$4, 16*8(" WX ")\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-        /* b */
-        "movq	%%r9, " L4 "\n\t"
-        /* L3 = 0 (add to prev h) */
-        "xorq	" L3 ", " L3 "\n\t"
-        /* b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-    SET_BLOCK_W_Y(rsi)
-
-        "# Start of 16 rounds\n"
-        "1:\n\t"
-
-        "addq	$128, %%rsi\n\t"
-
-    MsgSched4_AVX2_RORX_SET(W_Y_0,W_Y_4,W_Y_8,W_Y_12,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched4_AVX2_RORX_SET(W_Y_4,W_Y_8,W_Y_12,W_Y_0,RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    MsgSched4_AVX2_RORX_SET(W_Y_8,W_Y_12,W_Y_0,W_Y_4,RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    MsgSched4_AVX2_RORX_SET(W_Y_12,W_Y_0,W_Y_4,W_Y_8,RE,RF,RG,RH,RA,RB,RC,RD,12)
-
-        "subl	$1, 16*8(%%rsp)\n\t"
-        "jnz	1b\n\t"
-
-    RND_RORX_ALL_4(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_RORX_ALL_4(RE,RF,RG,RH,RA,RB,RC,RD, 4)
-    RND_RORX_ALL_4(RA,RB,RC,RD,RE,RF,RG,RH, 8)
-    RND_RORX_ALL_4(RE,RF,RG,RH,RA,RB,RC,RD,12)
-        /* Prev RND: h += Maj(a,b,c) */
-        "addq	" L3 ", %%r8\n\t"
-        "addq	$136, %%rsp\n\t"
-
-    STORE_ADD_DIGEST()
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK_Y),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-
-static int Transform_Sha512_AVX2_RORX_Len(wc_Sha512* sha512, word32 len)
-{
-    if ((len & WC_SHA512_BLOCK_SIZE) != 0) {
-        XMEMCPY(sha512->buffer, sha512->data, WC_SHA512_BLOCK_SIZE);
-        Transform_Sha512_AVX2_RORX(sha512);
-        sha512->data += WC_SHA512_BLOCK_SIZE;
-        len -= WC_SHA512_BLOCK_SIZE;
-        if (len == 0)
-            return 0;
-    }
-
-    __asm__ __volatile__ (
-
-        "movq	224(%[sha512]), %%rax\n\t"
-
-    INIT_MASK(MASK_Y)
-    LOAD_DIGEST()
-
-        "# Start of processing two blocks\n"
-        "2:\n\t"
-
-        "subq	$1344, %%rsp\n\t"
-        "leaq	%[K512], %%rsi\n\t"
-
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* L3 = 0 (add to prev h) */
-        "xorq	" L3 ", " L3 "\n\t"
-
-    LOAD_BLOCK2_W_Y(MASK_Y, rax)
-
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-        "\n"
-        "1:\n\t"
-    SET_BLOCK2_W_Y(rsi)
-    MsgSched2_AVX2_RORX(Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    MsgSched2_AVX2_RORX(Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y0,RG,RH,RA,RB,RC,RD,RE,RF, 4)
-    MsgSched2_AVX2_RORX(Y2,Y3,Y4,Y5,Y6,Y7,Y0,Y1,RE,RF,RG,RH,RA,RB,RC,RD, 8)
-    MsgSched2_AVX2_RORX(Y3,Y4,Y5,Y6,Y7,Y0,Y1,Y2,RC,RD,RE,RF,RG,RH,RA,RB,12)
-    MsgSched2_AVX2_RORX(Y4,Y5,Y6,Y7,Y0,Y1,Y2,Y3,RA,RB,RC,RD,RE,RF,RG,RH,16)
-    MsgSched2_AVX2_RORX(Y5,Y6,Y7,Y0,Y1,Y2,Y3,Y4,RG,RH,RA,RB,RC,RD,RE,RF,20)
-    MsgSched2_AVX2_RORX(Y6,Y7,Y0,Y1,Y2,Y3,Y4,Y5,RE,RF,RG,RH,RA,RB,RC,RD,24)
-    MsgSched2_AVX2_RORX(Y7,Y0,Y1,Y2,Y3,Y4,Y5,Y6,RC,RD,RE,RF,RG,RH,RA,RB,28)
-        "addq	$256, %%rsi\n\t"
-        "addq	$256, %%rsp\n\t"
-        "cmpq	%[K512_END], %%rsi\n\t"
-        "jne	1b\n\t"
-
-    SET_BLOCK2_W_Y(rsi)
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 0)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 4)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD, 8)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,12)
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,16)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,20)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,24)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,28)
-        "addq	" L3 ", %%r8\n\t"
-        "subq	$1024, %%rsp\n\t"
-
-    ADD_DIGEST()
-    STORE_DIGEST()
-
-        /* L4 = b */
-        "movq	%%r9, " L4 "\n\t"
-        /* L3 = 0 (add to prev h) */
-        "xorq	" L3 ", " L3 "\n\t"
-        /* L4 = b ^ c */
-        "xorq	%%r10, " L4 "\n\t"
-
-        "movq	$5, %%rsi\n\t"
-        "\n"
-        "3:\n\t"
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH, 2)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF, 6)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,10)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,14)
-
-    RND_RORX_ALL_2(RA,RB,RC,RD,RE,RF,RG,RH,18)
-    RND_RORX_ALL_2(RG,RH,RA,RB,RC,RD,RE,RF,22)
-    RND_RORX_ALL_2(RE,RF,RG,RH,RA,RB,RC,RD,26)
-    RND_RORX_ALL_2(RC,RD,RE,RF,RG,RH,RA,RB,30)
-        "addq	$256, %%rsp\n\t"
-        "subq	$1, %%rsi\n\t"
-        "jnz	3b\n\t"
-
-        "addq	" L3 ", %%r8\n\t"
-
-    ADD_DIGEST()
-
-        "movq	224(%[sha512]), %%rax\n\t"
-        "addq	$64, %%rsp\n\t"
-        "addq	$256, %%rax\n\t"
-        "subl	$256, %[len]\n\t"
-        "movq	%%rax, 224(%[sha512])\n\t"
-
-    STORE_DIGEST()
-
-        "jnz	2b\n\t"
-
-        :
-        : [mask]   "m" (mBYTE_FLIP_MASK_Y),
-          [len]    "m" (len),
-          [sha512] "r" (sha512),
-          [K512]   "m" (K512_AVX2),
-          [K512_END]   "m" (K512_AVX2_END)
-        : WORK_REGS, STATE_REGS, YMM_REGS, "memory", "rsi"
-    );
-
-    return 0;
-}
-#endif /* HAVE_INTEL_RORX */
-#endif /* HAVE_INTEL_AVX2 */
-
-#endif /* WOLFSSL_SHA512 */
-
-
-/* -------------------------------------------------------------------------- */
-/* SHA384 */
-/* -------------------------------------------------------------------------- */
-#ifdef WOLFSSL_SHA384
-
-#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
-    /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */
-#else
-
-static int InitSha384(wc_Sha384* sha384)
-{
-    if (sha384 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
-    sha384->digest[1] = W64LIT(0x629a292a367cd507);
-    sha384->digest[2] = W64LIT(0x9159015a3070dd17);
-    sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
-    sha384->digest[4] = W64LIT(0x67332667ffc00b31);
-    sha384->digest[5] = W64LIT(0x8eb44a8768581511);
-    sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
-    sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
-
-    sha384->buffLen = 0;
-    sha384->loLen   = 0;
-    sha384->hiLen   = 0;
-
-    return 0;
-}
-
-int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len)
-{
-    if (sha384 == NULL || (data == NULL && len > 0)) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
-    if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha384(&sha384->asyncDev, NULL, data, len);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return Sha512Update((wc_Sha512*)sha384, data, len);
-}
-
-
-int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash)
-{
-#ifdef LITTLE_ENDIAN_ORDER
-    word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)];
-#endif
-
-    if (sha384 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef LITTLE_ENDIAN_ORDER
-    ByteReverseWords64((word64*)digest, (word64*)sha384->digest,
-                                                         WC_SHA384_DIGEST_SIZE);
-    XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE);
-#else
-    XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
-#endif
-
-    return 0;
-}
-
-int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
-{
-    int ret;
-
-    if (sha384 == NULL || hash == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
-    if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) {
-    #if defined(HAVE_INTEL_QA)
-        return IntelQaSymSha384(&sha384->asyncDev, hash, NULL,
-                                            WC_SHA384_DIGEST_SIZE);
-    #endif
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    ret = Sha512Final((wc_Sha512*)sha384);
-    if (ret != 0)
-        return ret;
-
-    XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
-
-    return InitSha384(sha384);  /* reset state */
-}
-
-
-/* Hardware Acceleration */
-#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)
-    int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
-    {
-        int ret = InitSha384(sha384);
-
-        (void)heap;
-        (void)devId;
-
-        Sha512_SetTransform();
-
-        return ret;
-    }
-#else
-int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
-{
-    int ret;
-
-    if (sha384 == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    sha384->heap = heap;
-    ret = InitSha384(sha384);
-    if (ret != 0)
-        return ret;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    sha384->W = NULL;
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
-    ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384,
-                                                           sha384->heap, devId);
-#else
-    (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-#endif
-#endif /* WOLFSSL_IMX6_CAAM */
-
-int wc_InitSha384(wc_Sha384* sha384)
-{
-    return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID);
-}
-
-void wc_Sha384Free(wc_Sha384* sha384)
-{
-    if (sha384 == NULL)
-        return;
-
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    if (sha384->W != NULL) {
-        XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        sha384->W = NULL;
-    }
-#endif
-
-#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
-    wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-}
-
-#endif /* WOLFSSL_SHA384 */
-
-#endif /* HAVE_FIPS */
-
-#ifdef WOLFSSL_SHA512
-
-int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash)
-{
-    int ret;
-    wc_Sha512 tmpSha512;
-
-    if (sha512 == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_Sha512Copy(sha512, &tmpSha512);
-    if (ret == 0) {
-        ret = wc_Sha512Final(&tmpSha512, hash);
-        wc_Sha512Free(&tmpSha512);
-    }
-    return ret;
-}
-
-int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Sha512));
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    dst->W = NULL;
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-
-    return ret;
-}
-
-#endif /* WOLFSSL_SHA512 */
-
-#ifdef WOLFSSL_SHA384
-
-int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash)
-{
-    int ret;
-    wc_Sha384 tmpSha384;
-
-    if (sha384 == NULL || hash == NULL)
-        return BAD_FUNC_ARG;
-
-    ret = wc_Sha384Copy(sha384, &tmpSha384);
-    if (ret == 0) {
-        ret = wc_Sha384Final(&tmpSha384, hash);
-        wc_Sha384Free(&tmpSha384);
-    }
-    return ret;
-}
-int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
-{
-    int ret = 0;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    XMEMCPY(dst, src, sizeof(wc_Sha384));
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    dst->W = NULL;
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
-#endif
-
-    return ret;
-}
-
-#endif /* WOLFSSL_SHA384 */
-
-#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
-
--- a/wolfcrypt/src/signature.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,450 +0,0 @@
-/* signature.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/signature.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#ifndef NO_ASN
-#include <wolfssl/wolfcrypt/asn.h>
-#endif
-#ifdef HAVE_ECC
-#include <wolfssl/wolfcrypt/ecc.h>
-#endif
-#ifndef NO_RSA
-#include <wolfssl/wolfcrypt/rsa.h>
-#endif
-
-/* If ECC and RSA are disabled then disable signature wrapper */
-#if (!defined(HAVE_ECC) || (defined(HAVE_ECC) && !defined(HAVE_ECC_SIGN) \
-    && !defined(HAVE_ECC_VERIFY))) && defined(NO_RSA)
-    #undef NO_SIG_WRAPPER
-    #define NO_SIG_WRAPPER
-#endif
-
-/* Signature wrapper disabled check */
-#ifndef NO_SIG_WRAPPER
-
-#if !defined(NO_RSA) && !defined(NO_ASN)
-static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte** hash_data,
-    word32* hash_len)
-{
-    int ret = wc_HashGetOID(hash_type);
-    if (ret > 0) {
-        int oid = ret;
-
-        /* Allocate buffer for hash and max DER encoded */
-        word32 digest_len = *hash_len + MAX_DER_DIGEST_SZ;
-        byte *digest_buf = (byte*)XMALLOC(digest_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (digest_buf) {
-            ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid);
-            if (ret > 0) {
-                digest_len = ret;
-                ret = 0;
-
-                /* Replace hash with digest (DER encoding + hash) */
-                XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-                *hash_data = digest_buf;
-                *hash_len = digest_len;
-            }
-            else {
-                XFREE(digest_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            }
-        }
-        else {
-            ret = MEMORY_E;
-        }
-    }
-    return ret;
-}
-#endif /* !NO_RSA && !NO_ASN */
-
-int wc_SignatureGetSize(enum wc_SignatureType sig_type,
-    const void* key, word32 key_len)
-{
-    int sig_len = BAD_FUNC_ARG;
-
-    /* Suppress possible unused args if all signature types are disabled */
-    (void)key;
-    (void)key_len;
-
-    switch(sig_type) {
-        case WC_SIGNATURE_TYPE_ECC:
-#ifdef HAVE_ECC
-            /* Sanity check that void* key is at least ecc_key in size */
-            if (key_len >= sizeof(ecc_key)) {
-                sig_len = wc_ecc_sig_size((ecc_key*)key);
-            }
-            else {
-                WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size");
-            }
-#else
-            sig_len = SIG_TYPE_E;
-#endif
-            break;
-
-        case WC_SIGNATURE_TYPE_RSA_W_ENC:
-        case WC_SIGNATURE_TYPE_RSA:
-#ifndef NO_RSA
-            /* Sanity check that void* key is at least RsaKey in size */
-            if (key_len >= sizeof(RsaKey)) {
-                sig_len = wc_RsaEncryptSize((RsaKey*)key);
-            }
-            else {
-                WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size");
-            }
-#else
-            sig_len = SIG_TYPE_E;
-#endif
-            break;
-
-        case WC_SIGNATURE_TYPE_NONE:
-        default:
-            sig_len = BAD_FUNC_ARG;
-            break;
-    }
-    return sig_len;
-}
-
-int wc_SignatureVerifyHash(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* hash_data, word32 hash_len,
-    const byte* sig, word32 sig_len,
-    const void* key, word32 key_len)
-{
-    int ret;
-
-    /* Check arguments */
-    if (hash_data == NULL || hash_len <= 0 ||
-        sig == NULL || sig_len <= 0 ||
-        key == NULL || key_len <= 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate signature len (1 to max is okay) */
-    if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) {
-        WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len");
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate hash size */
-    ret = wc_HashGetDigestSize(hash_type);
-    if (ret < 0) {
-        WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
-        return ret;
-    }
-    ret = 0;
-
-    /* Verify signature using hash */
-    switch (sig_type) {
-        case WC_SIGNATURE_TYPE_ECC:
-        {
-#if defined(HAVE_ECC) && defined(HAVE_ECC_VERIFY)
-            int is_valid_sig = 0;
-
-            /* Perform verification of signature using provided ECC key */
-            do {
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev,
-                    WC_ASYNC_FLAG_CALL_AGAIN);
-            #endif
-            if (ret >= 0)
-                ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len,
-                    &is_valid_sig, (ecc_key*)key);
-            } while (ret == WC_PENDING_E);
-            if (ret != 0 || is_valid_sig != 1) {
-                ret = SIG_VERIFY_E;
-            }
-#else
-            ret = SIG_TYPE_E;
-#endif
-            break;
-        }
-
-        case WC_SIGNATURE_TYPE_RSA_W_ENC:
-        case WC_SIGNATURE_TYPE_RSA:
-        {
-#ifndef NO_RSA
-            word32 plain_len = hash_len;
-            byte *plain_data;
-
-            /* Make sure the plain text output is at least key size */
-            if (plain_len < sig_len) {
-                plain_len = sig_len;
-            }
-            plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            if (plain_data) {
-                /* Perform verification of signature using provided RSA key */
-                do {
-                #ifdef WOLFSSL_ASYNC_CRYPT
-                    ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev,
-                        WC_ASYNC_FLAG_CALL_AGAIN);
-                #endif
-                if (ret >= 0)
-                    ret = wc_RsaSSL_Verify(sig, sig_len, plain_data,
-                        plain_len, (RsaKey*)key);
-                } while (ret == WC_PENDING_E);
-                if (ret >= 0) {
-                    if ((word32)ret == hash_len &&
-                            XMEMCMP(plain_data, hash_data, hash_len) == 0) {
-                        ret = 0; /* Success */
-                    }
-                    else {
-                        WOLFSSL_MSG("RSA Signature Verify difference!");
-                        ret = SIG_VERIFY_E;
-                    }
-                }
-                XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-            }
-            else {
-                ret = MEMORY_E;
-            }
-#else
-            ret = SIG_TYPE_E;
-#endif
-            break;
-        }
-
-        case WC_SIGNATURE_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    return ret;
-}
-
-int wc_SignatureVerify(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* data, word32 data_len,
-    const byte* sig, word32 sig_len,
-    const void* key, word32 key_len)
-{
-    int ret;
-    word32 hash_len;
-    byte *hash_data = NULL;
-
-    /* Check arguments */
-    if (data == NULL || data_len <= 0 ||
-        sig == NULL || sig_len <= 0 ||
-        key == NULL || key_len <= 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate signature len (1 to max is okay) */
-    if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) {
-        WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len");
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate hash size */
-    ret = wc_HashGetDigestSize(hash_type);
-    if (ret < 0) {
-        WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
-        return ret;
-    }
-    hash_len = ret;
-
-    /* Allocate temporary buffer for hash data */
-    hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (hash_data == NULL) {
-        return MEMORY_E;
-    }
-
-    /* Perform hash of data */
-    ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
-    if (ret == 0) {
-        /* Handle RSA with DER encoding */
-        if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
-        #if defined(NO_RSA) || defined(NO_ASN)
-            ret = SIG_TYPE_E;
-        #else
-            ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
-        #endif
-        }
-
-        if (ret == 0) {
-            /* Verify signature using hash */
-            ret = wc_SignatureVerifyHash(hash_type, sig_type,
-                hash_data, hash_len, sig, sig_len, key, key_len);
-        }
-    }
-
-    if (hash_data) {
-        XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return ret;
-}
-
-
-int wc_SignatureGenerateHash(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* hash_data, word32 hash_len,
-    byte* sig, word32 *sig_len,
-    const void* key, word32 key_len, WC_RNG* rng)
-{
-    int ret;
-
-    /* Suppress possible unused arg if all signature types are disabled */
-    (void)rng;
-
-    /* Check arguments */
-    if (hash_data == NULL || hash_len <= 0 ||
-        sig == NULL || sig_len == NULL || *sig_len <= 0 ||
-        key == NULL || key_len <= 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate signature len (needs to be at least max) */
-    if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) {
-        WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len");
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate hash size */
-    ret = wc_HashGetDigestSize(hash_type);
-    if (ret < 0) {
-        WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
-        return ret;
-    }
-    ret = 0;
-
-    /* Create signature using hash as data */
-    switch (sig_type) {
-        case WC_SIGNATURE_TYPE_ECC:
-#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)
-            /* Create signature using provided ECC key */
-            do {
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev,
-                    WC_ASYNC_FLAG_CALL_AGAIN);
-            #endif
-            if (ret >= 0)
-                ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len,
-                    rng, (ecc_key*)key);
-            } while (ret == WC_PENDING_E);
-#else
-            ret = SIG_TYPE_E;
-#endif
-            break;
-
-        case WC_SIGNATURE_TYPE_RSA_W_ENC:
-        case WC_SIGNATURE_TYPE_RSA:
-#ifndef NO_RSA
-            /* Create signature using provided RSA key */
-            do {
-            #ifdef WOLFSSL_ASYNC_CRYPT
-                ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev,
-                    WC_ASYNC_FLAG_CALL_AGAIN);
-            #endif
-                if (ret >= 0)
-                    ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len,
-                        (RsaKey*)key, rng);
-            } while (ret == WC_PENDING_E);
-            if (ret >= 0) {
-                *sig_len = ret;
-                ret = 0; /* Success */
-            }
-#else
-            ret = SIG_TYPE_E;
-#endif
-            break;
-
-        case WC_SIGNATURE_TYPE_NONE:
-        default:
-            ret = BAD_FUNC_ARG;
-            break;
-    }
-
-    return ret;
-}
-
-int wc_SignatureGenerate(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* data, word32 data_len,
-    byte* sig, word32 *sig_len,
-    const void* key, word32 key_len, WC_RNG* rng)
-{
-    int ret;
-    word32 hash_len;
-    byte *hash_data = NULL;
-
-    /* Check arguments */
-    if (data == NULL || data_len <= 0 ||
-        sig == NULL || sig_len == NULL || *sig_len <= 0 ||
-        key == NULL || key_len <= 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate signature len (needs to be at least max) */
-    if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) {
-        WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len");
-        return BAD_FUNC_ARG;
-    }
-
-    /* Validate hash size */
-    ret = wc_HashGetDigestSize(hash_type);
-    if (ret < 0) {
-        WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
-        return ret;
-    }
-    hash_len = ret;
-
-    /* Allocate temporary buffer for hash data */
-    hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (hash_data == NULL) {
-        return MEMORY_E;
-    }
-
-    /* Perform hash of data */
-    ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
-    if (ret == 0) {
-        /* Handle RSA with DER encoding */
-        if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
-        #if defined(NO_RSA) || defined(NO_ASN)
-            ret = SIG_TYPE_E;
-        #else
-            ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
-        #endif
-        }
-
-        if (ret == 0) {
-            /* Generate signature using hash */
-            ret = wc_SignatureGenerateHash(hash_type, sig_type,
-                hash_data, hash_len, sig, sig_len, key, key_len, rng);
-        }
-    }
-
-    if (hash_data) {
-        XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return ret;
-}
-
-#endif /* NO_SIG_WRAPPER */
-
--- a/wolfcrypt/src/sp_arm32.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24911 +0,0 @@
-/* sp.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#ifdef RSA_LOW_MEM
-#define SP_RSA_PRIVATE_EXP_D
-
-#ifndef WOLFSSL_SP_SMALL
-#define WOLFSSL_SP_SMALL
-#endif
-#endif
-
-#include <wolfssl/wolfcrypt/sp.h>
-
-#ifdef WOLFSSL_SP_ARM32_ASM
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
-#ifndef WOLFSSL_SP_NO_2048
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 24) {
-            r[j] &= 0xffffffff;
-            s = 32 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 32
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 32
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffff;
-        s = 32 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 32 <= DIGIT_BIT) {
-            s += 32;
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 32) {
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            s = 32 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 256
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_2048_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 2048 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<64 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 32) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 32);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "#  A[0] * B[0]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r3, r4, r8, r9\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[0]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #4]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[1]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[0]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #8]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[2]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[1]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[0]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #12]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[3]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[2]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[0]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #16]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[4]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[3]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[2]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[1]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[0]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #20]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[5]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[4]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[3]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[2]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[1]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[0]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #24]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[6]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[5]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[4]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[3]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[2]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[1]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[0]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #28]\n\t"
-        "#  A[1] * B[7]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[2] * B[6]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[5]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[4]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[3]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[2]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[1]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "#  A[2] * B[7]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[3] * B[6]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[5]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[4]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[3]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[2]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "#  A[3] * B[7]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[4] * B[6]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[5]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[4]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[3]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "#  A[4] * B[7]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[5] * B[6]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[5]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[4]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "#  A[5] * B[7]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[6] * B[6]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[5]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "#  A[6] * B[7]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[7] * B[6]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "#  A[7] * B[7]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "#  A[0] * A[0]\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "umull	r8, r3, r10, r10\n\t"
-        "mov	r4, #0\n\t"
-        "str	r8, [%[tmp]]\n\t"
-        "#  A[0] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #4]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[1] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[tmp], #8]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[1] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[tmp], #12]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[1] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[2] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #16]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[tmp], #20]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[tmp], #24]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r2, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adcs	r4, r4, r6\n\t"
-        "adc	r2, r2, r7\n\t"
-        "str	r3, [%[tmp], #28]\n\t"
-        "#  A[1] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[2] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "#  A[2] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[3] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[r], #36]\n\t"
-        "#  A[3] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[4] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[5] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #40]\n\t"
-        "#  A[4] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[5] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[r], #44]\n\t"
-        "#  A[5] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[6] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[r], #48]\n\t"
-        "#  A[6] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #52]\n\t"
-        "#  A[7] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adc	r2, r2, r9\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r2, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<8; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-    r[4] = a[4] & m;
-    r[5] = a[5] & m;
-    r[6] = a[6] & m;
-    r[7] = a[7] & m;
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit b1[8];
-    sp_digit z2[16];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_8(a1, a, &a[8]);
-    cb = sp_2048_add_8(b1, b, &b[8]);
-    u  = ca & cb;
-    sp_2048_mul_8(z1, a1, b1);
-    sp_2048_mul_8(z2, &a[8], &b[8]);
-    sp_2048_mul_8(z0, a, b);
-    sp_2048_mask_8(r + 16, a1, 0 - cb);
-    sp_2048_mask_8(b1, b1, 0 - ca);
-    u += sp_2048_add_8(r + 16, r + 16, b1);
-    u += sp_2048_sub_in_place_16(z1, z2);
-    u += sp_2048_sub_in_place_16(z1, z0);
-    u += sp_2048_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_2048_add_16(r + 16, r + 16, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[16];
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit u;
-
-    u = sp_2048_add_8(a1, a, &a[8]);
-    sp_2048_sqr_8(z1, a1);
-    sp_2048_sqr_8(z2, &a[8]);
-    sp_2048_sqr_8(z0, a);
-    sp_2048_mask_8(r + 16, a1, 0 - u);
-    u += sp_2048_add_8(r + 16, r + 16, r + 16);
-    u += sp_2048_sub_in_place_16(z1, z2);
-    u += sp_2048_sub_in_place_16(z1, z0);
-    u += sp_2048_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_2048_add_16(r + 16, r + 16, z2);
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "ldr	r2, [%[a], #64]\n\t"
-        "ldr	r3, [%[a], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r5, [%[a], #76]\n\t"
-        "ldr	r6, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "ldr	r8, [%[b], #72]\n\t"
-        "ldr	r9, [%[b], #76]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #64]\n\t"
-        "str	r3, [%[a], #68]\n\t"
-        "str	r4, [%[a], #72]\n\t"
-        "str	r5, [%[a], #76]\n\t"
-        "ldr	r2, [%[a], #80]\n\t"
-        "ldr	r3, [%[a], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r5, [%[a], #92]\n\t"
-        "ldr	r6, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "ldr	r8, [%[b], #88]\n\t"
-        "ldr	r9, [%[b], #92]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #80]\n\t"
-        "str	r3, [%[a], #84]\n\t"
-        "str	r4, [%[a], #88]\n\t"
-        "str	r5, [%[a], #92]\n\t"
-        "ldr	r2, [%[a], #96]\n\t"
-        "ldr	r3, [%[a], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r5, [%[a], #108]\n\t"
-        "ldr	r6, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "ldr	r8, [%[b], #104]\n\t"
-        "ldr	r9, [%[b], #108]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #96]\n\t"
-        "str	r3, [%[a], #100]\n\t"
-        "str	r4, [%[a], #104]\n\t"
-        "str	r5, [%[a], #108]\n\t"
-        "ldr	r2, [%[a], #112]\n\t"
-        "ldr	r3, [%[a], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r5, [%[a], #124]\n\t"
-        "ldr	r6, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "ldr	r8, [%[b], #120]\n\t"
-        "ldr	r9, [%[b], #124]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #112]\n\t"
-        "str	r3, [%[a], #116]\n\t"
-        "str	r4, [%[a], #120]\n\t"
-        "str	r5, [%[a], #124]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r5, [%[a], #68]\n\t"
-        "ldr	r6, [%[a], #72]\n\t"
-        "ldr	r7, [%[a], #76]\n\t"
-        "ldr	r8, [%[b], #64]\n\t"
-        "ldr	r9, [%[b], #68]\n\t"
-        "ldr	r10, [%[b], #72]\n\t"
-        "ldr	r14, [%[b], #76]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "str	r6, [%[r], #72]\n\t"
-        "str	r7, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r5, [%[a], #84]\n\t"
-        "ldr	r6, [%[a], #88]\n\t"
-        "ldr	r7, [%[a], #92]\n\t"
-        "ldr	r8, [%[b], #80]\n\t"
-        "ldr	r9, [%[b], #84]\n\t"
-        "ldr	r10, [%[b], #88]\n\t"
-        "ldr	r14, [%[b], #92]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r5, [%[r], #84]\n\t"
-        "str	r6, [%[r], #88]\n\t"
-        "str	r7, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r5, [%[a], #100]\n\t"
-        "ldr	r6, [%[a], #104]\n\t"
-        "ldr	r7, [%[a], #108]\n\t"
-        "ldr	r8, [%[b], #96]\n\t"
-        "ldr	r9, [%[b], #100]\n\t"
-        "ldr	r10, [%[b], #104]\n\t"
-        "ldr	r14, [%[b], #108]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r5, [%[r], #100]\n\t"
-        "str	r6, [%[r], #104]\n\t"
-        "str	r7, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r5, [%[a], #116]\n\t"
-        "ldr	r6, [%[a], #120]\n\t"
-        "ldr	r7, [%[a], #124]\n\t"
-        "ldr	r8, [%[b], #112]\n\t"
-        "ldr	r9, [%[b], #116]\n\t"
-        "ldr	r10, [%[b], #120]\n\t"
-        "ldr	r14, [%[b], #124]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "str	r6, [%[r], #120]\n\t"
-        "str	r7, [%[r], #124]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<16; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit b1[16];
-    sp_digit z2[32];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_16(a1, a, &a[16]);
-    cb = sp_2048_add_16(b1, b, &b[16]);
-    u  = ca & cb;
-    sp_2048_mul_16(z1, a1, b1);
-    sp_2048_mul_16(z2, &a[16], &b[16]);
-    sp_2048_mul_16(z0, a, b);
-    sp_2048_mask_16(r + 32, a1, 0 - cb);
-    sp_2048_mask_16(b1, b1, 0 - ca);
-    u += sp_2048_add_16(r + 32, r + 32, b1);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[32];
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit u;
-
-    u = sp_2048_add_16(a1, a, &a[16]);
-    sp_2048_sqr_16(z1, a1);
-    sp_2048_sqr_16(z2, &a[16]);
-    sp_2048_sqr_16(z0, a);
-    sp_2048_mask_16(r + 32, a1, 0 - u);
-    u += sp_2048_add_16(r + 32, r + 32, r + 32);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "ldr	r2, [%[a], #64]\n\t"
-        "ldr	r3, [%[a], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r5, [%[a], #76]\n\t"
-        "ldr	r6, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "ldr	r8, [%[b], #72]\n\t"
-        "ldr	r9, [%[b], #76]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #64]\n\t"
-        "str	r3, [%[a], #68]\n\t"
-        "str	r4, [%[a], #72]\n\t"
-        "str	r5, [%[a], #76]\n\t"
-        "ldr	r2, [%[a], #80]\n\t"
-        "ldr	r3, [%[a], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r5, [%[a], #92]\n\t"
-        "ldr	r6, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "ldr	r8, [%[b], #88]\n\t"
-        "ldr	r9, [%[b], #92]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #80]\n\t"
-        "str	r3, [%[a], #84]\n\t"
-        "str	r4, [%[a], #88]\n\t"
-        "str	r5, [%[a], #92]\n\t"
-        "ldr	r2, [%[a], #96]\n\t"
-        "ldr	r3, [%[a], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r5, [%[a], #108]\n\t"
-        "ldr	r6, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "ldr	r8, [%[b], #104]\n\t"
-        "ldr	r9, [%[b], #108]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #96]\n\t"
-        "str	r3, [%[a], #100]\n\t"
-        "str	r4, [%[a], #104]\n\t"
-        "str	r5, [%[a], #108]\n\t"
-        "ldr	r2, [%[a], #112]\n\t"
-        "ldr	r3, [%[a], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r5, [%[a], #124]\n\t"
-        "ldr	r6, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "ldr	r8, [%[b], #120]\n\t"
-        "ldr	r9, [%[b], #124]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #112]\n\t"
-        "str	r3, [%[a], #116]\n\t"
-        "str	r4, [%[a], #120]\n\t"
-        "str	r5, [%[a], #124]\n\t"
-        "ldr	r2, [%[a], #128]\n\t"
-        "ldr	r3, [%[a], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r5, [%[a], #140]\n\t"
-        "ldr	r6, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "ldr	r8, [%[b], #136]\n\t"
-        "ldr	r9, [%[b], #140]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #128]\n\t"
-        "str	r3, [%[a], #132]\n\t"
-        "str	r4, [%[a], #136]\n\t"
-        "str	r5, [%[a], #140]\n\t"
-        "ldr	r2, [%[a], #144]\n\t"
-        "ldr	r3, [%[a], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r5, [%[a], #156]\n\t"
-        "ldr	r6, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "ldr	r8, [%[b], #152]\n\t"
-        "ldr	r9, [%[b], #156]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #144]\n\t"
-        "str	r3, [%[a], #148]\n\t"
-        "str	r4, [%[a], #152]\n\t"
-        "str	r5, [%[a], #156]\n\t"
-        "ldr	r2, [%[a], #160]\n\t"
-        "ldr	r3, [%[a], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r5, [%[a], #172]\n\t"
-        "ldr	r6, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "ldr	r8, [%[b], #168]\n\t"
-        "ldr	r9, [%[b], #172]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #160]\n\t"
-        "str	r3, [%[a], #164]\n\t"
-        "str	r4, [%[a], #168]\n\t"
-        "str	r5, [%[a], #172]\n\t"
-        "ldr	r2, [%[a], #176]\n\t"
-        "ldr	r3, [%[a], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r5, [%[a], #188]\n\t"
-        "ldr	r6, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "ldr	r8, [%[b], #184]\n\t"
-        "ldr	r9, [%[b], #188]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #176]\n\t"
-        "str	r3, [%[a], #180]\n\t"
-        "str	r4, [%[a], #184]\n\t"
-        "str	r5, [%[a], #188]\n\t"
-        "ldr	r2, [%[a], #192]\n\t"
-        "ldr	r3, [%[a], #196]\n\t"
-        "ldr	r4, [%[a], #200]\n\t"
-        "ldr	r5, [%[a], #204]\n\t"
-        "ldr	r6, [%[b], #192]\n\t"
-        "ldr	r7, [%[b], #196]\n\t"
-        "ldr	r8, [%[b], #200]\n\t"
-        "ldr	r9, [%[b], #204]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #192]\n\t"
-        "str	r3, [%[a], #196]\n\t"
-        "str	r4, [%[a], #200]\n\t"
-        "str	r5, [%[a], #204]\n\t"
-        "ldr	r2, [%[a], #208]\n\t"
-        "ldr	r3, [%[a], #212]\n\t"
-        "ldr	r4, [%[a], #216]\n\t"
-        "ldr	r5, [%[a], #220]\n\t"
-        "ldr	r6, [%[b], #208]\n\t"
-        "ldr	r7, [%[b], #212]\n\t"
-        "ldr	r8, [%[b], #216]\n\t"
-        "ldr	r9, [%[b], #220]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #208]\n\t"
-        "str	r3, [%[a], #212]\n\t"
-        "str	r4, [%[a], #216]\n\t"
-        "str	r5, [%[a], #220]\n\t"
-        "ldr	r2, [%[a], #224]\n\t"
-        "ldr	r3, [%[a], #228]\n\t"
-        "ldr	r4, [%[a], #232]\n\t"
-        "ldr	r5, [%[a], #236]\n\t"
-        "ldr	r6, [%[b], #224]\n\t"
-        "ldr	r7, [%[b], #228]\n\t"
-        "ldr	r8, [%[b], #232]\n\t"
-        "ldr	r9, [%[b], #236]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #224]\n\t"
-        "str	r3, [%[a], #228]\n\t"
-        "str	r4, [%[a], #232]\n\t"
-        "str	r5, [%[a], #236]\n\t"
-        "ldr	r2, [%[a], #240]\n\t"
-        "ldr	r3, [%[a], #244]\n\t"
-        "ldr	r4, [%[a], #248]\n\t"
-        "ldr	r5, [%[a], #252]\n\t"
-        "ldr	r6, [%[b], #240]\n\t"
-        "ldr	r7, [%[b], #244]\n\t"
-        "ldr	r8, [%[b], #248]\n\t"
-        "ldr	r9, [%[b], #252]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #240]\n\t"
-        "str	r3, [%[a], #244]\n\t"
-        "str	r4, [%[a], #248]\n\t"
-        "str	r5, [%[a], #252]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r5, [%[a], #68]\n\t"
-        "ldr	r6, [%[a], #72]\n\t"
-        "ldr	r7, [%[a], #76]\n\t"
-        "ldr	r8, [%[b], #64]\n\t"
-        "ldr	r9, [%[b], #68]\n\t"
-        "ldr	r10, [%[b], #72]\n\t"
-        "ldr	r14, [%[b], #76]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "str	r6, [%[r], #72]\n\t"
-        "str	r7, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r5, [%[a], #84]\n\t"
-        "ldr	r6, [%[a], #88]\n\t"
-        "ldr	r7, [%[a], #92]\n\t"
-        "ldr	r8, [%[b], #80]\n\t"
-        "ldr	r9, [%[b], #84]\n\t"
-        "ldr	r10, [%[b], #88]\n\t"
-        "ldr	r14, [%[b], #92]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r5, [%[r], #84]\n\t"
-        "str	r6, [%[r], #88]\n\t"
-        "str	r7, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r5, [%[a], #100]\n\t"
-        "ldr	r6, [%[a], #104]\n\t"
-        "ldr	r7, [%[a], #108]\n\t"
-        "ldr	r8, [%[b], #96]\n\t"
-        "ldr	r9, [%[b], #100]\n\t"
-        "ldr	r10, [%[b], #104]\n\t"
-        "ldr	r14, [%[b], #108]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r5, [%[r], #100]\n\t"
-        "str	r6, [%[r], #104]\n\t"
-        "str	r7, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r5, [%[a], #116]\n\t"
-        "ldr	r6, [%[a], #120]\n\t"
-        "ldr	r7, [%[a], #124]\n\t"
-        "ldr	r8, [%[b], #112]\n\t"
-        "ldr	r9, [%[b], #116]\n\t"
-        "ldr	r10, [%[b], #120]\n\t"
-        "ldr	r14, [%[b], #124]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "str	r6, [%[r], #120]\n\t"
-        "str	r7, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r5, [%[a], #132]\n\t"
-        "ldr	r6, [%[a], #136]\n\t"
-        "ldr	r7, [%[a], #140]\n\t"
-        "ldr	r8, [%[b], #128]\n\t"
-        "ldr	r9, [%[b], #132]\n\t"
-        "ldr	r10, [%[b], #136]\n\t"
-        "ldr	r14, [%[b], #140]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r5, [%[r], #132]\n\t"
-        "str	r6, [%[r], #136]\n\t"
-        "str	r7, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r5, [%[a], #148]\n\t"
-        "ldr	r6, [%[a], #152]\n\t"
-        "ldr	r7, [%[a], #156]\n\t"
-        "ldr	r8, [%[b], #144]\n\t"
-        "ldr	r9, [%[b], #148]\n\t"
-        "ldr	r10, [%[b], #152]\n\t"
-        "ldr	r14, [%[b], #156]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r5, [%[r], #148]\n\t"
-        "str	r6, [%[r], #152]\n\t"
-        "str	r7, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r5, [%[a], #164]\n\t"
-        "ldr	r6, [%[a], #168]\n\t"
-        "ldr	r7, [%[a], #172]\n\t"
-        "ldr	r8, [%[b], #160]\n\t"
-        "ldr	r9, [%[b], #164]\n\t"
-        "ldr	r10, [%[b], #168]\n\t"
-        "ldr	r14, [%[b], #172]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "str	r6, [%[r], #168]\n\t"
-        "str	r7, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r5, [%[a], #180]\n\t"
-        "ldr	r6, [%[a], #184]\n\t"
-        "ldr	r7, [%[a], #188]\n\t"
-        "ldr	r8, [%[b], #176]\n\t"
-        "ldr	r9, [%[b], #180]\n\t"
-        "ldr	r10, [%[b], #184]\n\t"
-        "ldr	r14, [%[b], #188]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r5, [%[r], #180]\n\t"
-        "str	r6, [%[r], #184]\n\t"
-        "str	r7, [%[r], #188]\n\t"
-        "ldr	r4, [%[a], #192]\n\t"
-        "ldr	r5, [%[a], #196]\n\t"
-        "ldr	r6, [%[a], #200]\n\t"
-        "ldr	r7, [%[a], #204]\n\t"
-        "ldr	r8, [%[b], #192]\n\t"
-        "ldr	r9, [%[b], #196]\n\t"
-        "ldr	r10, [%[b], #200]\n\t"
-        "ldr	r14, [%[b], #204]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #192]\n\t"
-        "str	r5, [%[r], #196]\n\t"
-        "str	r6, [%[r], #200]\n\t"
-        "str	r7, [%[r], #204]\n\t"
-        "ldr	r4, [%[a], #208]\n\t"
-        "ldr	r5, [%[a], #212]\n\t"
-        "ldr	r6, [%[a], #216]\n\t"
-        "ldr	r7, [%[a], #220]\n\t"
-        "ldr	r8, [%[b], #208]\n\t"
-        "ldr	r9, [%[b], #212]\n\t"
-        "ldr	r10, [%[b], #216]\n\t"
-        "ldr	r14, [%[b], #220]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "str	r5, [%[r], #212]\n\t"
-        "str	r6, [%[r], #216]\n\t"
-        "str	r7, [%[r], #220]\n\t"
-        "ldr	r4, [%[a], #224]\n\t"
-        "ldr	r5, [%[a], #228]\n\t"
-        "ldr	r6, [%[a], #232]\n\t"
-        "ldr	r7, [%[a], #236]\n\t"
-        "ldr	r8, [%[b], #224]\n\t"
-        "ldr	r9, [%[b], #228]\n\t"
-        "ldr	r10, [%[b], #232]\n\t"
-        "ldr	r14, [%[b], #236]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #224]\n\t"
-        "str	r5, [%[r], #228]\n\t"
-        "str	r6, [%[r], #232]\n\t"
-        "str	r7, [%[r], #236]\n\t"
-        "ldr	r4, [%[a], #240]\n\t"
-        "ldr	r5, [%[a], #244]\n\t"
-        "ldr	r6, [%[a], #248]\n\t"
-        "ldr	r7, [%[a], #252]\n\t"
-        "ldr	r8, [%[b], #240]\n\t"
-        "ldr	r9, [%[b], #244]\n\t"
-        "ldr	r10, [%[b], #248]\n\t"
-        "ldr	r14, [%[b], #252]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #240]\n\t"
-        "str	r5, [%[r], #244]\n\t"
-        "str	r6, [%[r], #248]\n\t"
-        "str	r7, [%[r], #252]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<32; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_64(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[64];
-    sp_digit a1[32];
-    sp_digit b1[32];
-    sp_digit z2[64];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_32(a1, a, &a[32]);
-    cb = sp_2048_add_32(b1, b, &b[32]);
-    u  = ca & cb;
-    sp_2048_mul_32(z1, a1, b1);
-    sp_2048_mul_32(z2, &a[32], &b[32]);
-    sp_2048_mul_32(z0, a, b);
-    sp_2048_mask_32(r + 64, a1, 0 - cb);
-    sp_2048_mask_32(b1, b1, 0 - ca);
-    u += sp_2048_add_32(r + 64, r + 64, b1);
-    u += sp_2048_sub_in_place_64(z1, z2);
-    u += sp_2048_sub_in_place_64(z1, z0);
-    u += sp_2048_add_64(r + 32, r + 32, z1);
-    r[96] = u;
-    XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1));
-    sp_2048_add_64(r + 64, r + 64, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[64];
-    sp_digit z1[64];
-    sp_digit a1[32];
-    sp_digit u;
-
-    u = sp_2048_add_32(a1, a, &a[32]);
-    sp_2048_sqr_32(z1, a1);
-    sp_2048_sqr_32(z2, &a[32]);
-    sp_2048_sqr_32(z0, a);
-    sp_2048_mask_32(r + 64, a1, 0 - u);
-    u += sp_2048_add_32(r + 64, r + 64, r + 64);
-    u += sp_2048_sub_in_place_64(z1, z2);
-    u += sp_2048_sub_in_place_64(z1, z0);
-    u += sp_2048_add_64(r + 32, r + 32, z1);
-    r[96] = u;
-    XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1));
-    sp_2048_add_64(r + 64, r + 64, z2);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #256\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "mov	r4, #0\n\t"
-        "adc	%[c], r4, #0\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "add	r12, %[a], #256\n\t"
-        "\n1:\n\t"
-        "subs	%[c], r14, %[c]\n\t"
-        "ldr	r3, [%[a]]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[a]], #4\n\t"
-        "str	r4, [%[a]], #4\n\t"
-        "str	r5, [%[a]], #4\n\t"
-        "str	r6, [%[a]], #4\n\t"
-        "sbc	%[c], r14, r14\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[128];
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #252\n\t"
-        "movcc	r3, #0\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r12, [%[b], r4]\n\t"
-        "umull	r9, r10, r14, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, #0\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #256\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #504\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[128];
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "mov	r5, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #252\n\t"
-        "movcc	r3, r12\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "cmp	r4, r3\n\t"
-        "beq	4f\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r9, [%[a], r4]\n\t"
-        "umull	r9, r10, r14, r9\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "bal	5f\n\t"
-        "\n4:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "umull	r9, r10, r14, r14\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "\n5:\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #256\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r4\n\t"
-        "bgt	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #504\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m)
-{
-    int i;
-
-    for (i=0; i<32; i++)
-        r[i] = a[i] & m;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #128\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "mov	r4, #0\n\t"
-        "adc	%[c], r4, #0\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "add	r12, %[a], #128\n\t"
-        "\n1:\n\t"
-        "subs	%[c], r14, %[c]\n\t"
-        "ldr	r3, [%[a]]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[a]], #4\n\t"
-        "str	r4, [%[a]], #4\n\t"
-        "str	r5, [%[a]], #4\n\t"
-        "str	r6, [%[a]], #4\n\t"
-        "sbc	%[c], r14, r14\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[64];
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #124\n\t"
-        "movcc	r3, #0\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r12, [%[b], r4]\n\t"
-        "umull	r9, r10, r14, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, #0\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #128\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #248\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[64];
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "mov	r5, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #124\n\t"
-        "movcc	r3, r12\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "cmp	r4, r3\n\t"
-        "beq	4f\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r9, [%[a], r4]\n\t"
-        "umull	r9, r10, r14, r9\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "bal	5f\n\t"
-        "\n4:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "umull	r9, r10, r14, r14\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "\n5:\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #128\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r4\n\t"
-        "bgt	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #248\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 32);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_32(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r9, #0\n\t"
-        "mov	r8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], r9, %[c]\n\t"
-        "ldr	r4, [%[a], r8]\n\t"
-        "ldr	r5, [%[b], r8]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        "str	r4, [%[r], r8]\n\t"
-        "add	r8, r8, #4\n\t"
-        "cmp	r8, #128\n\t"
-        "blt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "mov	r9, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r5, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "subs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r6, [%[r], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r5, [%[b], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r5, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r6, [%[r], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r5, [%[b], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r6, [%[a], #36]\n\t"
-        "ldr	r5, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r6, [%[r], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r6, [%[a], #44]\n\t"
-        "ldr	r5, [%[b], #40]\n\t"
-        "ldr	r7, [%[b], #44]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "str	r6, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r6, [%[a], #52]\n\t"
-        "ldr	r5, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r6, [%[r], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r6, [%[a], #60]\n\t"
-        "ldr	r5, [%[b], #56]\n\t"
-        "ldr	r7, [%[b], #60]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r6, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r6, [%[a], #68]\n\t"
-        "ldr	r5, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r6, [%[r], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r6, [%[a], #76]\n\t"
-        "ldr	r5, [%[b], #72]\n\t"
-        "ldr	r7, [%[b], #76]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #72]\n\t"
-        "str	r6, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r6, [%[a], #84]\n\t"
-        "ldr	r5, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r6, [%[r], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r6, [%[a], #92]\n\t"
-        "ldr	r5, [%[b], #88]\n\t"
-        "ldr	r7, [%[b], #92]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "str	r6, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r6, [%[a], #100]\n\t"
-        "ldr	r5, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r6, [%[r], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r6, [%[a], #108]\n\t"
-        "ldr	r5, [%[b], #104]\n\t"
-        "ldr	r7, [%[b], #108]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #104]\n\t"
-        "str	r6, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r6, [%[a], #116]\n\t"
-        "ldr	r5, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r6, [%[r], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r6, [%[a], #124]\n\t"
-        "ldr	r5, [%[b], #120]\n\t"
-        "ldr	r7, [%[b], #124]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #120]\n\t"
-        "str	r6, [%[r], #124]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "ldr	r14, [%[a], #4]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	r8, %[mp], r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	r7, [%[m], #0]\n\t"
-        "ldr	r9, [%[a], #0]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r10, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	r7, [%[m], #4]\n\t"
-        "ldr	r9, [%[a], #4]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r14, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r10, r10, r5\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	r7, [%[m], #8]\n\t"
-        "ldr	r14, [%[a], #8]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r14, r14, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r14, r14, r4\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	r7, [%[m], #12]\n\t"
-        "ldr	r9, [%[a], #12]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #12]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	r7, [%[m], #16]\n\t"
-        "ldr	r9, [%[a], #16]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #16]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	r7, [%[m], #20]\n\t"
-        "ldr	r9, [%[a], #20]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #20]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	r7, [%[m], #24]\n\t"
-        "ldr	r9, [%[a], #24]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #24]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	r7, [%[m], #28]\n\t"
-        "ldr	r9, [%[a], #28]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #28]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	r7, [%[m], #32]\n\t"
-        "ldr	r9, [%[a], #32]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #32]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	r7, [%[m], #36]\n\t"
-        "ldr	r9, [%[a], #36]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #36]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	r7, [%[m], #40]\n\t"
-        "ldr	r9, [%[a], #40]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #40]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	r7, [%[m], #44]\n\t"
-        "ldr	r9, [%[a], #44]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #44]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	r7, [%[m], #48]\n\t"
-        "ldr	r9, [%[a], #48]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #48]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	r7, [%[m], #52]\n\t"
-        "ldr	r9, [%[a], #52]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #52]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	r7, [%[m], #56]\n\t"
-        "ldr	r9, [%[a], #56]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #56]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	r7, [%[m], #60]\n\t"
-        "ldr	r9, [%[a], #60]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #60]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr	r7, [%[m], #64]\n\t"
-        "ldr	r9, [%[a], #64]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #64]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr	r7, [%[m], #68]\n\t"
-        "ldr	r9, [%[a], #68]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #68]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr	r7, [%[m], #72]\n\t"
-        "ldr	r9, [%[a], #72]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #72]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr	r7, [%[m], #76]\n\t"
-        "ldr	r9, [%[a], #76]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #76]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr	r7, [%[m], #80]\n\t"
-        "ldr	r9, [%[a], #80]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #80]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr	r7, [%[m], #84]\n\t"
-        "ldr	r9, [%[a], #84]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #84]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr	r7, [%[m], #88]\n\t"
-        "ldr	r9, [%[a], #88]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #88]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr	r7, [%[m], #92]\n\t"
-        "ldr	r9, [%[a], #92]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #92]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr	r7, [%[m], #96]\n\t"
-        "ldr	r9, [%[a], #96]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #96]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr	r7, [%[m], #100]\n\t"
-        "ldr	r9, [%[a], #100]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #100]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr	r7, [%[m], #104]\n\t"
-        "ldr	r9, [%[a], #104]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #104]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr	r7, [%[m], #108]\n\t"
-        "ldr	r9, [%[a], #108]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #108]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr	r7, [%[m], #112]\n\t"
-        "ldr	r9, [%[a], #112]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #112]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr	r7, [%[m], #116]\n\t"
-        "ldr	r9, [%[a], #116]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #116]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr	r7, [%[m], #120]\n\t"
-        "ldr	r9, [%[a], #120]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #120]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr	r7, [%[m], #124]\n\t"
-        "ldr   r9, [%[a], #124]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r7, r7, %[ca]\n\t"
-        "mov	%[ca], #0\n\t"
-        "adc	%[ca], %[ca], %[ca]\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #124]\n\t"
-        "ldr	r9, [%[a], #128]\n\t"
-        "adcs	r9, r9, r7\n\t"
-        "str	r9, [%[a], #128]\n\t"
-        "adc	%[ca], %[ca], #0\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], #4\n\t"
-        "add	r12, r12, #4\n\t"
-        "cmp	r12, #128\n\t"
-        "blt	1b\n\t"
-        "str	r10, [%[a], #0]\n\t"
-        "str	r14, [%[a], #4]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_32(r, a, b);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_32(r, a);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r5, r3, %[b], r8\n\t"
-        "mov	r4, #0\n\t"
-        "str	r5, [%[r]]\n\t"
-        "mov	r5, #0\n\t"
-        "mov	r9, #4\n\t"
-        "1:\n\t"
-        "ldr	r8, [%[a], r9]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], r9]\n\t"
-        "mov	r3, r4\n\t"
-        "mov	r4, r5\n\t"
-        "mov	r5, #0\n\t"
-        "add	r9, r9, #4\n\t"
-        "cmp	r9, #128\n\t"
-        "blt	1b\n\t"
-        "str	r3, [%[r], #128]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r3, r4, %[b], r8\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "# A[2] * B\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "# A[4] * B\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "# A[5] * B\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "# A[6] * B\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #24]\n\t"
-        "# A[7] * B\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #28]\n\t"
-        "# A[8] * B\n\t"
-        "ldr	r8, [%[a], #32]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "# A[9] * B\n\t"
-        "ldr	r8, [%[a], #36]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "# A[10] * B\n\t"
-        "ldr	r8, [%[a], #40]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "# A[11] * B\n\t"
-        "ldr	r8, [%[a], #44]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "# A[12] * B\n\t"
-        "ldr	r8, [%[a], #48]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "# A[13] * B\n\t"
-        "ldr	r8, [%[a], #52]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "# A[14] * B\n\t"
-        "ldr	r8, [%[a], #56]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "# A[15] * B\n\t"
-        "ldr	r8, [%[a], #60]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        "# A[16] * B\n\t"
-        "ldr	r8, [%[a], #64]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "# A[17] * B\n\t"
-        "ldr	r8, [%[a], #68]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "# A[18] * B\n\t"
-        "ldr	r8, [%[a], #72]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #72]\n\t"
-        "# A[19] * B\n\t"
-        "ldr	r8, [%[a], #76]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #76]\n\t"
-        "# A[20] * B\n\t"
-        "ldr	r8, [%[a], #80]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #80]\n\t"
-        "# A[21] * B\n\t"
-        "ldr	r8, [%[a], #84]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #84]\n\t"
-        "# A[22] * B\n\t"
-        "ldr	r8, [%[a], #88]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "# A[23] * B\n\t"
-        "ldr	r8, [%[a], #92]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #92]\n\t"
-        "# A[24] * B\n\t"
-        "ldr	r8, [%[a], #96]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #96]\n\t"
-        "# A[25] * B\n\t"
-        "ldr	r8, [%[a], #100]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #100]\n\t"
-        "# A[26] * B\n\t"
-        "ldr	r8, [%[a], #104]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #104]\n\t"
-        "# A[27] * B\n\t"
-        "ldr	r8, [%[a], #108]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #108]\n\t"
-        "# A[28] * B\n\t"
-        "ldr	r8, [%[a], #112]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "# A[29] * B\n\t"
-        "ldr	r8, [%[a], #116]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "# A[30] * B\n\t"
-        "ldr	r8, [%[a], #120]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #120]\n\t"
-        "# A[31] * B\n\t"
-        "ldr	r8, [%[a], #124]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adc	r5, r5, r7\n\t"
-        "str	r4, [%[r], #124]\n\t"
-        "str	r5, [%[r], #128]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
-static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r = 0;
-
-    __asm__ __volatile__ (
-        "lsr	r5, %[div], #1\n\t"
-        "add	r5, r5, #1\n\t"
-        "mov	r6, %[d0]\n\t"
-        "mov	r7, %[d1]\n\t"
-        "# Do top 32\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "# Next 30 bits\n\t"
-        "mov	r4, #29\n\t"
-        "1:\n\t"
-        "movs	r6, r6, lsl #1\n\t"
-        "adc	r7, r7, r7\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "subs	r4, r4, #1\n\t"
-        "bpl	1b\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "add	%[r], %[r], #1\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "subs	r8, %[div], r4\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        : [r] "+r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "r4", "r5", "r6", "r7", "r8"
-    );
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int32_t sp_2048_cmp_32(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "mov	r6, #124\n\t"
-        "1:\n\t"
-        "ldr	r4, [%[a], r6]\n\t"
-        "ldr	r5, [%[b], r6]\n\t"
-        "and	r4, r4, r3\n\t"
-        "and	r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "sub	r6, r6, #4\n\t"
-        "bcc	1b\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "ldr		r4, [%[a], #124]\n\t"
-        "ldr		r5, [%[b], #124]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #120]\n\t"
-        "ldr		r5, [%[b], #120]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #116]\n\t"
-        "ldr		r5, [%[b], #116]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #112]\n\t"
-        "ldr		r5, [%[b], #112]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #108]\n\t"
-        "ldr		r5, [%[b], #108]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #104]\n\t"
-        "ldr		r5, [%[b], #104]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #100]\n\t"
-        "ldr		r5, [%[b], #100]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #96]\n\t"
-        "ldr		r5, [%[b], #96]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #92]\n\t"
-        "ldr		r5, [%[b], #92]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #88]\n\t"
-        "ldr		r5, [%[b], #88]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #84]\n\t"
-        "ldr		r5, [%[b], #84]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #80]\n\t"
-        "ldr		r5, [%[b], #80]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #76]\n\t"
-        "ldr		r5, [%[b], #76]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #72]\n\t"
-        "ldr		r5, [%[b], #72]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #68]\n\t"
-        "ldr		r5, [%[b], #68]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #64]\n\t"
-        "ldr		r5, [%[b], #64]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #60]\n\t"
-        "ldr		r5, [%[b], #60]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #56]\n\t"
-        "ldr		r5, [%[b], #56]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #52]\n\t"
-        "ldr		r5, [%[b], #52]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #48]\n\t"
-        "ldr		r5, [%[b], #48]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #44]\n\t"
-        "ldr		r5, [%[b], #44]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #40]\n\t"
-        "ldr		r5, [%[b], #40]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #36]\n\t"
-        "ldr		r5, [%[b], #36]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #32]\n\t"
-        "ldr		r5, [%[b], #32]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #28]\n\t"
-        "ldr		r5, [%[b], #28]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #24]\n\t"
-        "ldr		r5, [%[b], #24]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #20]\n\t"
-        "ldr		r5, [%[b], #20]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #16]\n\t"
-        "ldr		r5, [%[b], #16]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #12]\n\t"
-        "ldr		r5, [%[b], #12]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #8]\n\t"
-        "ldr		r5, [%[b], #8]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #4]\n\t"
-        "ldr		r5, [%[b], #4]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #0]\n\t"
-        "ldr		r5, [%[b], #0]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[64], t2[33];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[31];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
-    for (i=31; i>=0; i--) {
-        r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
-
-        sp_2048_mul_d_32(t2, d, r1);
-        t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
-        t1[32 + i] -= t2[32];
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_32(t1, d) >= 0;
-    sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_32(a, m, NULL, r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][64];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 28;
-        n <<= 4;
-        c = 28;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 28;
-                n <<= 4;
-                c = 28;
-            }
-            else if (c < 4) {
-                y = n >> 28;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 28) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-
-            sp_2048_mont_mul_32(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][64];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_32(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_32(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_32(t[20], t[10], m, mp);
-        sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_32(t[22], t[11], m, mp);
-        sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_32(t[24], t[12], m, mp);
-        sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_32(t[26], t[13], m, mp);
-        sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_32(t[28], t[14], m, mp);
-        sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_32(t[30], t[15], m, mp);
-        sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 27;
-        n <<= 5;
-        c = 27;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 27;
-                n <<= 5;
-                c = 27;
-            }
-            else if (c < 5) {
-                y = n >> 27;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 27) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-
-            sp_2048_mont_mul_32(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0xf;
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_mul_32(r, r, t[y], m, mp);
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_64(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 64);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_64(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_64(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r9, #0\n\t"
-        "mov	r8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], r9, %[c]\n\t"
-        "ldr	r4, [%[a], r8]\n\t"
-        "ldr	r5, [%[b], r8]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        "str	r4, [%[r], r8]\n\t"
-        "add	r8, r8, #4\n\t"
-        "cmp	r8, #256\n\t"
-        "blt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "mov	r9, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r5, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "subs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r6, [%[r], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r5, [%[b], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r5, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r6, [%[r], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r5, [%[b], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r6, [%[a], #36]\n\t"
-        "ldr	r5, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r6, [%[r], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r6, [%[a], #44]\n\t"
-        "ldr	r5, [%[b], #40]\n\t"
-        "ldr	r7, [%[b], #44]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "str	r6, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r6, [%[a], #52]\n\t"
-        "ldr	r5, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r6, [%[r], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r6, [%[a], #60]\n\t"
-        "ldr	r5, [%[b], #56]\n\t"
-        "ldr	r7, [%[b], #60]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r6, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r6, [%[a], #68]\n\t"
-        "ldr	r5, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r6, [%[r], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r6, [%[a], #76]\n\t"
-        "ldr	r5, [%[b], #72]\n\t"
-        "ldr	r7, [%[b], #76]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #72]\n\t"
-        "str	r6, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r6, [%[a], #84]\n\t"
-        "ldr	r5, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r6, [%[r], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r6, [%[a], #92]\n\t"
-        "ldr	r5, [%[b], #88]\n\t"
-        "ldr	r7, [%[b], #92]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "str	r6, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r6, [%[a], #100]\n\t"
-        "ldr	r5, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r6, [%[r], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r6, [%[a], #108]\n\t"
-        "ldr	r5, [%[b], #104]\n\t"
-        "ldr	r7, [%[b], #108]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #104]\n\t"
-        "str	r6, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r6, [%[a], #116]\n\t"
-        "ldr	r5, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r6, [%[r], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r6, [%[a], #124]\n\t"
-        "ldr	r5, [%[b], #120]\n\t"
-        "ldr	r7, [%[b], #124]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #120]\n\t"
-        "str	r6, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r6, [%[a], #132]\n\t"
-        "ldr	r5, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r6, [%[r], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r6, [%[a], #140]\n\t"
-        "ldr	r5, [%[b], #136]\n\t"
-        "ldr	r7, [%[b], #140]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "str	r6, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r6, [%[a], #148]\n\t"
-        "ldr	r5, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r6, [%[r], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r6, [%[a], #156]\n\t"
-        "ldr	r5, [%[b], #152]\n\t"
-        "ldr	r7, [%[b], #156]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #152]\n\t"
-        "str	r6, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r6, [%[a], #164]\n\t"
-        "ldr	r5, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r6, [%[r], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r6, [%[a], #172]\n\t"
-        "ldr	r5, [%[b], #168]\n\t"
-        "ldr	r7, [%[b], #172]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #168]\n\t"
-        "str	r6, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r6, [%[a], #180]\n\t"
-        "ldr	r5, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r6, [%[r], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r6, [%[a], #188]\n\t"
-        "ldr	r5, [%[b], #184]\n\t"
-        "ldr	r7, [%[b], #188]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "str	r6, [%[r], #188]\n\t"
-        "ldr	r4, [%[a], #192]\n\t"
-        "ldr	r6, [%[a], #196]\n\t"
-        "ldr	r5, [%[b], #192]\n\t"
-        "ldr	r7, [%[b], #196]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #192]\n\t"
-        "str	r6, [%[r], #196]\n\t"
-        "ldr	r4, [%[a], #200]\n\t"
-        "ldr	r6, [%[a], #204]\n\t"
-        "ldr	r5, [%[b], #200]\n\t"
-        "ldr	r7, [%[b], #204]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #200]\n\t"
-        "str	r6, [%[r], #204]\n\t"
-        "ldr	r4, [%[a], #208]\n\t"
-        "ldr	r6, [%[a], #212]\n\t"
-        "ldr	r5, [%[b], #208]\n\t"
-        "ldr	r7, [%[b], #212]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "str	r6, [%[r], #212]\n\t"
-        "ldr	r4, [%[a], #216]\n\t"
-        "ldr	r6, [%[a], #220]\n\t"
-        "ldr	r5, [%[b], #216]\n\t"
-        "ldr	r7, [%[b], #220]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #216]\n\t"
-        "str	r6, [%[r], #220]\n\t"
-        "ldr	r4, [%[a], #224]\n\t"
-        "ldr	r6, [%[a], #228]\n\t"
-        "ldr	r5, [%[b], #224]\n\t"
-        "ldr	r7, [%[b], #228]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #224]\n\t"
-        "str	r6, [%[r], #228]\n\t"
-        "ldr	r4, [%[a], #232]\n\t"
-        "ldr	r6, [%[a], #236]\n\t"
-        "ldr	r5, [%[b], #232]\n\t"
-        "ldr	r7, [%[b], #236]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #232]\n\t"
-        "str	r6, [%[r], #236]\n\t"
-        "ldr	r4, [%[a], #240]\n\t"
-        "ldr	r6, [%[a], #244]\n\t"
-        "ldr	r5, [%[b], #240]\n\t"
-        "ldr	r7, [%[b], #244]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #240]\n\t"
-        "str	r6, [%[r], #244]\n\t"
-        "ldr	r4, [%[a], #248]\n\t"
-        "ldr	r6, [%[a], #252]\n\t"
-        "ldr	r5, [%[b], #248]\n\t"
-        "ldr	r7, [%[b], #252]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #248]\n\t"
-        "str	r6, [%[r], #252]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "ldr	r14, [%[a], #4]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	r8, %[mp], r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	r7, [%[m], #0]\n\t"
-        "ldr	r9, [%[a], #0]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r10, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	r7, [%[m], #4]\n\t"
-        "ldr	r9, [%[a], #4]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r14, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r10, r10, r5\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	r7, [%[m], #8]\n\t"
-        "ldr	r14, [%[a], #8]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r14, r14, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r14, r14, r4\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	r7, [%[m], #12]\n\t"
-        "ldr	r9, [%[a], #12]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #12]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	r7, [%[m], #16]\n\t"
-        "ldr	r9, [%[a], #16]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #16]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	r7, [%[m], #20]\n\t"
-        "ldr	r9, [%[a], #20]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #20]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	r7, [%[m], #24]\n\t"
-        "ldr	r9, [%[a], #24]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #24]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	r7, [%[m], #28]\n\t"
-        "ldr	r9, [%[a], #28]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #28]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	r7, [%[m], #32]\n\t"
-        "ldr	r9, [%[a], #32]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #32]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	r7, [%[m], #36]\n\t"
-        "ldr	r9, [%[a], #36]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #36]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	r7, [%[m], #40]\n\t"
-        "ldr	r9, [%[a], #40]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #40]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	r7, [%[m], #44]\n\t"
-        "ldr	r9, [%[a], #44]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #44]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	r7, [%[m], #48]\n\t"
-        "ldr	r9, [%[a], #48]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #48]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	r7, [%[m], #52]\n\t"
-        "ldr	r9, [%[a], #52]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #52]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	r7, [%[m], #56]\n\t"
-        "ldr	r9, [%[a], #56]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #56]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	r7, [%[m], #60]\n\t"
-        "ldr	r9, [%[a], #60]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #60]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr	r7, [%[m], #64]\n\t"
-        "ldr	r9, [%[a], #64]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #64]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr	r7, [%[m], #68]\n\t"
-        "ldr	r9, [%[a], #68]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #68]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr	r7, [%[m], #72]\n\t"
-        "ldr	r9, [%[a], #72]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #72]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr	r7, [%[m], #76]\n\t"
-        "ldr	r9, [%[a], #76]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #76]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr	r7, [%[m], #80]\n\t"
-        "ldr	r9, [%[a], #80]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #80]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr	r7, [%[m], #84]\n\t"
-        "ldr	r9, [%[a], #84]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #84]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr	r7, [%[m], #88]\n\t"
-        "ldr	r9, [%[a], #88]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #88]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr	r7, [%[m], #92]\n\t"
-        "ldr	r9, [%[a], #92]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #92]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr	r7, [%[m], #96]\n\t"
-        "ldr	r9, [%[a], #96]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #96]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr	r7, [%[m], #100]\n\t"
-        "ldr	r9, [%[a], #100]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #100]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr	r7, [%[m], #104]\n\t"
-        "ldr	r9, [%[a], #104]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #104]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr	r7, [%[m], #108]\n\t"
-        "ldr	r9, [%[a], #108]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #108]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr	r7, [%[m], #112]\n\t"
-        "ldr	r9, [%[a], #112]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #112]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr	r7, [%[m], #116]\n\t"
-        "ldr	r9, [%[a], #116]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #116]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr	r7, [%[m], #120]\n\t"
-        "ldr	r9, [%[a], #120]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #120]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr	r7, [%[m], #124]\n\t"
-        "ldr	r9, [%[a], #124]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #124]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "ldr	r7, [%[m], #128]\n\t"
-        "ldr	r9, [%[a], #128]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #128]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "ldr	r7, [%[m], #132]\n\t"
-        "ldr	r9, [%[a], #132]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #132]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "ldr	r7, [%[m], #136]\n\t"
-        "ldr	r9, [%[a], #136]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #136]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "ldr	r7, [%[m], #140]\n\t"
-        "ldr	r9, [%[a], #140]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #140]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "ldr	r7, [%[m], #144]\n\t"
-        "ldr	r9, [%[a], #144]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #144]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "ldr	r7, [%[m], #148]\n\t"
-        "ldr	r9, [%[a], #148]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #148]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "ldr	r7, [%[m], #152]\n\t"
-        "ldr	r9, [%[a], #152]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #152]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "ldr	r7, [%[m], #156]\n\t"
-        "ldr	r9, [%[a], #156]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #156]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "ldr	r7, [%[m], #160]\n\t"
-        "ldr	r9, [%[a], #160]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #160]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "ldr	r7, [%[m], #164]\n\t"
-        "ldr	r9, [%[a], #164]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #164]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "ldr	r7, [%[m], #168]\n\t"
-        "ldr	r9, [%[a], #168]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #168]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "ldr	r7, [%[m], #172]\n\t"
-        "ldr	r9, [%[a], #172]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #172]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "ldr	r7, [%[m], #176]\n\t"
-        "ldr	r9, [%[a], #176]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #176]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "ldr	r7, [%[m], #180]\n\t"
-        "ldr	r9, [%[a], #180]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #180]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "ldr	r7, [%[m], #184]\n\t"
-        "ldr	r9, [%[a], #184]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #184]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "ldr	r7, [%[m], #188]\n\t"
-        "ldr	r9, [%[a], #188]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #188]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+48] += m[48] * mu\n\t"
-        "ldr	r7, [%[m], #192]\n\t"
-        "ldr	r9, [%[a], #192]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #192]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+49] += m[49] * mu\n\t"
-        "ldr	r7, [%[m], #196]\n\t"
-        "ldr	r9, [%[a], #196]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #196]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+50] += m[50] * mu\n\t"
-        "ldr	r7, [%[m], #200]\n\t"
-        "ldr	r9, [%[a], #200]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #200]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+51] += m[51] * mu\n\t"
-        "ldr	r7, [%[m], #204]\n\t"
-        "ldr	r9, [%[a], #204]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #204]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+52] += m[52] * mu\n\t"
-        "ldr	r7, [%[m], #208]\n\t"
-        "ldr	r9, [%[a], #208]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #208]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+53] += m[53] * mu\n\t"
-        "ldr	r7, [%[m], #212]\n\t"
-        "ldr	r9, [%[a], #212]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #212]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+54] += m[54] * mu\n\t"
-        "ldr	r7, [%[m], #216]\n\t"
-        "ldr	r9, [%[a], #216]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #216]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+55] += m[55] * mu\n\t"
-        "ldr	r7, [%[m], #220]\n\t"
-        "ldr	r9, [%[a], #220]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #220]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+56] += m[56] * mu\n\t"
-        "ldr	r7, [%[m], #224]\n\t"
-        "ldr	r9, [%[a], #224]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #224]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+57] += m[57] * mu\n\t"
-        "ldr	r7, [%[m], #228]\n\t"
-        "ldr	r9, [%[a], #228]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #228]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+58] += m[58] * mu\n\t"
-        "ldr	r7, [%[m], #232]\n\t"
-        "ldr	r9, [%[a], #232]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #232]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+59] += m[59] * mu\n\t"
-        "ldr	r7, [%[m], #236]\n\t"
-        "ldr	r9, [%[a], #236]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #236]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+60] += m[60] * mu\n\t"
-        "ldr	r7, [%[m], #240]\n\t"
-        "ldr	r9, [%[a], #240]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #240]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+61] += m[61] * mu\n\t"
-        "ldr	r7, [%[m], #244]\n\t"
-        "ldr	r9, [%[a], #244]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #244]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+62] += m[62] * mu\n\t"
-        "ldr	r7, [%[m], #248]\n\t"
-        "ldr	r9, [%[a], #248]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #248]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+63] += m[63] * mu\n\t"
-        "ldr	r7, [%[m], #252]\n\t"
-        "ldr   r9, [%[a], #252]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r7, r7, %[ca]\n\t"
-        "mov	%[ca], #0\n\t"
-        "adc	%[ca], %[ca], %[ca]\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #252]\n\t"
-        "ldr	r9, [%[a], #256]\n\t"
-        "adcs	r9, r9, r7\n\t"
-        "str	r9, [%[a], #256]\n\t"
-        "adc	%[ca], %[ca], #0\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], #4\n\t"
-        "add	r12, r12, #4\n\t"
-        "cmp	r12, #256\n\t"
-        "blt	1b\n\t"
-        "str	r10, [%[a], #0]\n\t"
-        "str	r14, [%[a], #4]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_64(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_64(r, a, b);
-    sp_2048_mont_reduce_64(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_64(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_64(r, a);
-    sp_2048_mont_reduce_64(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r5, r3, %[b], r8\n\t"
-        "mov	r4, #0\n\t"
-        "str	r5, [%[r]]\n\t"
-        "mov	r5, #0\n\t"
-        "mov	r9, #4\n\t"
-        "1:\n\t"
-        "ldr	r8, [%[a], r9]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], r9]\n\t"
-        "mov	r3, r4\n\t"
-        "mov	r4, r5\n\t"
-        "mov	r5, #0\n\t"
-        "add	r9, r9, #4\n\t"
-        "cmp	r9, #256\n\t"
-        "blt	1b\n\t"
-        "str	r3, [%[r], #256]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r3, r4, %[b], r8\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "# A[2] * B\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "# A[4] * B\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "# A[5] * B\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "# A[6] * B\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #24]\n\t"
-        "# A[7] * B\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #28]\n\t"
-        "# A[8] * B\n\t"
-        "ldr	r8, [%[a], #32]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "# A[9] * B\n\t"
-        "ldr	r8, [%[a], #36]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "# A[10] * B\n\t"
-        "ldr	r8, [%[a], #40]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "# A[11] * B\n\t"
-        "ldr	r8, [%[a], #44]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "# A[12] * B\n\t"
-        "ldr	r8, [%[a], #48]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "# A[13] * B\n\t"
-        "ldr	r8, [%[a], #52]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "# A[14] * B\n\t"
-        "ldr	r8, [%[a], #56]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "# A[15] * B\n\t"
-        "ldr	r8, [%[a], #60]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        "# A[16] * B\n\t"
-        "ldr	r8, [%[a], #64]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "# A[17] * B\n\t"
-        "ldr	r8, [%[a], #68]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "# A[18] * B\n\t"
-        "ldr	r8, [%[a], #72]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #72]\n\t"
-        "# A[19] * B\n\t"
-        "ldr	r8, [%[a], #76]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #76]\n\t"
-        "# A[20] * B\n\t"
-        "ldr	r8, [%[a], #80]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #80]\n\t"
-        "# A[21] * B\n\t"
-        "ldr	r8, [%[a], #84]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #84]\n\t"
-        "# A[22] * B\n\t"
-        "ldr	r8, [%[a], #88]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "# A[23] * B\n\t"
-        "ldr	r8, [%[a], #92]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #92]\n\t"
-        "# A[24] * B\n\t"
-        "ldr	r8, [%[a], #96]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #96]\n\t"
-        "# A[25] * B\n\t"
-        "ldr	r8, [%[a], #100]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #100]\n\t"
-        "# A[26] * B\n\t"
-        "ldr	r8, [%[a], #104]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #104]\n\t"
-        "# A[27] * B\n\t"
-        "ldr	r8, [%[a], #108]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #108]\n\t"
-        "# A[28] * B\n\t"
-        "ldr	r8, [%[a], #112]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "# A[29] * B\n\t"
-        "ldr	r8, [%[a], #116]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "# A[30] * B\n\t"
-        "ldr	r8, [%[a], #120]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #120]\n\t"
-        "# A[31] * B\n\t"
-        "ldr	r8, [%[a], #124]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #124]\n\t"
-        "# A[32] * B\n\t"
-        "ldr	r8, [%[a], #128]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #128]\n\t"
-        "# A[33] * B\n\t"
-        "ldr	r8, [%[a], #132]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #132]\n\t"
-        "# A[34] * B\n\t"
-        "ldr	r8, [%[a], #136]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "# A[35] * B\n\t"
-        "ldr	r8, [%[a], #140]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #140]\n\t"
-        "# A[36] * B\n\t"
-        "ldr	r8, [%[a], #144]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #144]\n\t"
-        "# A[37] * B\n\t"
-        "ldr	r8, [%[a], #148]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #148]\n\t"
-        "# A[38] * B\n\t"
-        "ldr	r8, [%[a], #152]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #152]\n\t"
-        "# A[39] * B\n\t"
-        "ldr	r8, [%[a], #156]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #156]\n\t"
-        "# A[40] * B\n\t"
-        "ldr	r8, [%[a], #160]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "# A[41] * B\n\t"
-        "ldr	r8, [%[a], #164]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "# A[42] * B\n\t"
-        "ldr	r8, [%[a], #168]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #168]\n\t"
-        "# A[43] * B\n\t"
-        "ldr	r8, [%[a], #172]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #172]\n\t"
-        "# A[44] * B\n\t"
-        "ldr	r8, [%[a], #176]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #176]\n\t"
-        "# A[45] * B\n\t"
-        "ldr	r8, [%[a], #180]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #180]\n\t"
-        "# A[46] * B\n\t"
-        "ldr	r8, [%[a], #184]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "# A[47] * B\n\t"
-        "ldr	r8, [%[a], #188]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #188]\n\t"
-        "# A[48] * B\n\t"
-        "ldr	r8, [%[a], #192]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #192]\n\t"
-        "# A[49] * B\n\t"
-        "ldr	r8, [%[a], #196]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #196]\n\t"
-        "# A[50] * B\n\t"
-        "ldr	r8, [%[a], #200]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #200]\n\t"
-        "# A[51] * B\n\t"
-        "ldr	r8, [%[a], #204]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #204]\n\t"
-        "# A[52] * B\n\t"
-        "ldr	r8, [%[a], #208]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "# A[53] * B\n\t"
-        "ldr	r8, [%[a], #212]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #212]\n\t"
-        "# A[54] * B\n\t"
-        "ldr	r8, [%[a], #216]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #216]\n\t"
-        "# A[55] * B\n\t"
-        "ldr	r8, [%[a], #220]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #220]\n\t"
-        "# A[56] * B\n\t"
-        "ldr	r8, [%[a], #224]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #224]\n\t"
-        "# A[57] * B\n\t"
-        "ldr	r8, [%[a], #228]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #228]\n\t"
-        "# A[58] * B\n\t"
-        "ldr	r8, [%[a], #232]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #232]\n\t"
-        "# A[59] * B\n\t"
-        "ldr	r8, [%[a], #236]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #236]\n\t"
-        "# A[60] * B\n\t"
-        "ldr	r8, [%[a], #240]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #240]\n\t"
-        "# A[61] * B\n\t"
-        "ldr	r8, [%[a], #244]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #244]\n\t"
-        "# A[62] * B\n\t"
-        "ldr	r8, [%[a], #248]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #248]\n\t"
-        "# A[63] * B\n\t"
-        "ldr	r8, [%[a], #252]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r3, [%[r], #252]\n\t"
-        "str	r4, [%[r], #256]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
-static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r = 0;
-
-    __asm__ __volatile__ (
-        "lsr	r5, %[div], #1\n\t"
-        "add	r5, r5, #1\n\t"
-        "mov	r6, %[d0]\n\t"
-        "mov	r7, %[d1]\n\t"
-        "# Do top 32\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "# Next 30 bits\n\t"
-        "mov	r4, #29\n\t"
-        "1:\n\t"
-        "movs	r6, r6, lsl #1\n\t"
-        "adc	r7, r7, r7\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "subs	r4, r4, #1\n\t"
-        "bpl	1b\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "add	%[r], %[r], #1\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "subs	r8, %[div], r4\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        : [r] "+r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "r4", "r5", "r6", "r7", "r8"
-    );
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_64(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<64; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int32_t sp_2048_cmp_64(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "mov	r6, #252\n\t"
-        "1:\n\t"
-        "ldr	r4, [%[a], r6]\n\t"
-        "ldr	r5, [%[b], r6]\n\t"
-        "and	r4, r4, r3\n\t"
-        "and	r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "sub	r6, r6, #4\n\t"
-        "bcc	1b\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "ldr		r4, [%[a], #252]\n\t"
-        "ldr		r5, [%[b], #252]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #248]\n\t"
-        "ldr		r5, [%[b], #248]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #244]\n\t"
-        "ldr		r5, [%[b], #244]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #240]\n\t"
-        "ldr		r5, [%[b], #240]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #236]\n\t"
-        "ldr		r5, [%[b], #236]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #232]\n\t"
-        "ldr		r5, [%[b], #232]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #228]\n\t"
-        "ldr		r5, [%[b], #228]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #224]\n\t"
-        "ldr		r5, [%[b], #224]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #220]\n\t"
-        "ldr		r5, [%[b], #220]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #216]\n\t"
-        "ldr		r5, [%[b], #216]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #212]\n\t"
-        "ldr		r5, [%[b], #212]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #208]\n\t"
-        "ldr		r5, [%[b], #208]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #204]\n\t"
-        "ldr		r5, [%[b], #204]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #200]\n\t"
-        "ldr		r5, [%[b], #200]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #196]\n\t"
-        "ldr		r5, [%[b], #196]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #192]\n\t"
-        "ldr		r5, [%[b], #192]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #188]\n\t"
-        "ldr		r5, [%[b], #188]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #184]\n\t"
-        "ldr		r5, [%[b], #184]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #180]\n\t"
-        "ldr		r5, [%[b], #180]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #176]\n\t"
-        "ldr		r5, [%[b], #176]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #172]\n\t"
-        "ldr		r5, [%[b], #172]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #168]\n\t"
-        "ldr		r5, [%[b], #168]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #164]\n\t"
-        "ldr		r5, [%[b], #164]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #160]\n\t"
-        "ldr		r5, [%[b], #160]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #156]\n\t"
-        "ldr		r5, [%[b], #156]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #152]\n\t"
-        "ldr		r5, [%[b], #152]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #148]\n\t"
-        "ldr		r5, [%[b], #148]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #144]\n\t"
-        "ldr		r5, [%[b], #144]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #140]\n\t"
-        "ldr		r5, [%[b], #140]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #136]\n\t"
-        "ldr		r5, [%[b], #136]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #132]\n\t"
-        "ldr		r5, [%[b], #132]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #128]\n\t"
-        "ldr		r5, [%[b], #128]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #124]\n\t"
-        "ldr		r5, [%[b], #124]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #120]\n\t"
-        "ldr		r5, [%[b], #120]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #116]\n\t"
-        "ldr		r5, [%[b], #116]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #112]\n\t"
-        "ldr		r5, [%[b], #112]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #108]\n\t"
-        "ldr		r5, [%[b], #108]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #104]\n\t"
-        "ldr		r5, [%[b], #104]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #100]\n\t"
-        "ldr		r5, [%[b], #100]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #96]\n\t"
-        "ldr		r5, [%[b], #96]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #92]\n\t"
-        "ldr		r5, [%[b], #92]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #88]\n\t"
-        "ldr		r5, [%[b], #88]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #84]\n\t"
-        "ldr		r5, [%[b], #84]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #80]\n\t"
-        "ldr		r5, [%[b], #80]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #76]\n\t"
-        "ldr		r5, [%[b], #76]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #72]\n\t"
-        "ldr		r5, [%[b], #72]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #68]\n\t"
-        "ldr		r5, [%[b], #68]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #64]\n\t"
-        "ldr		r5, [%[b], #64]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #60]\n\t"
-        "ldr		r5, [%[b], #60]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #56]\n\t"
-        "ldr		r5, [%[b], #56]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #52]\n\t"
-        "ldr		r5, [%[b], #52]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #48]\n\t"
-        "ldr		r5, [%[b], #48]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #44]\n\t"
-        "ldr		r5, [%[b], #44]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #40]\n\t"
-        "ldr		r5, [%[b], #40]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #36]\n\t"
-        "ldr		r5, [%[b], #36]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #32]\n\t"
-        "ldr		r5, [%[b], #32]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #28]\n\t"
-        "ldr		r5, [%[b], #28]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #24]\n\t"
-        "ldr		r5, [%[b], #24]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #20]\n\t"
-        "ldr		r5, [%[b], #20]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #16]\n\t"
-        "ldr		r5, [%[b], #16]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #12]\n\t"
-        "ldr		r5, [%[b], #12]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #8]\n\t"
-        "ldr		r5, [%[b], #8]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #4]\n\t"
-        "ldr		r5, [%[b], #4]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #0]\n\t"
-        "ldr		r5, [%[b], #0]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_64(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[128], t2[65];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[63];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
-    for (i=63; i>=0; i--) {
-        r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div);
-
-        sp_2048_mul_d_64(t2, d, r1);
-        t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
-        t1[64 + i] -= t2[64];
-        sp_2048_mask_64(t2, d, t1[64 + i]);
-        t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
-        sp_2048_mask_64(t2, d, t1[64 + i]);
-        t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_64(t1, d) >= 0;
-    sp_2048_cond_sub_64(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_64(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_64(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_64_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[128], t2[65];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[63];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 64);
-    for (i=63; i>=0; i--) {
-        r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div);
-
-        sp_2048_mul_d_64(t2, d, r1);
-        t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2);
-        t1[64 + i] -= t2[64];
-        if (t1[64 + i] != 0) {
-            t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
-            if (t1[64 + i] != 0)
-                t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_2048_cmp_64(t1, d) >= 0;
-    sp_2048_cond_sub_64(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_64_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][128];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 128, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 128;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_64(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 64);
-        if (reduceA) {
-            err = sp_2048_mod_64(t[1] + 64, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_64(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
-            err = sp_2048_mod_64(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_64(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_64(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_64(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 28;
-        n <<= 4;
-        c = 28;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 28;
-                n <<= 4;
-                c = 28;
-            }
-            else if (c < 4) {
-                y = n >> 28;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 28) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-
-            sp_2048_mont_mul_64(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[64], 0, sizeof(sp_digit) * 64);
-        sp_2048_mont_reduce_64(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
-        sp_2048_cond_sub_64(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][128];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 128, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 128;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_64(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 64);
-        if (reduceA) {
-            err = sp_2048_mod_64(t[1] + 64, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_64(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64);
-            err = sp_2048_mod_64(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_64(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_64(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_64(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_64(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_64(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_64(t[20], t[10], m, mp);
-        sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_64(t[22], t[11], m, mp);
-        sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_64(t[24], t[12], m, mp);
-        sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_64(t[26], t[13], m, mp);
-        sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_64(t[28], t[14], m, mp);
-        sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_64(t[30], t[15], m, mp);
-        sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 27;
-        n <<= 5;
-        c = 27;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 64);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 27;
-                n <<= 5;
-                c = 27;
-            }
-            else if (c < 5) {
-                y = n >> 27;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 27) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-            sp_2048_mont_sqr_64(r, r, m, mp);
-
-            sp_2048_mont_mul_64(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x7;
-        sp_2048_mont_sqr_64(r, r, m, mp);
-        sp_2048_mont_sqr_64(r, r, m, mp);
-        sp_2048_mont_sqr_64(r, r, m, mp);
-        sp_2048_mont_mul_64(r, r, t[y], m, mp);
-
-        XMEMSET(&r[64], 0, sizeof(sp_digit) * 64);
-        sp_2048_mont_reduce_64(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_64(r, m) >= 0);
-        sp_2048_cond_sub_64(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[128], md[64], rd[128];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 64 * 2;
-        m = r + 64 * 2;
-        ah = a + 64;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 64;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(ah, 64, in, inLen);
-#if DIGIT_BIT >= 32
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 64, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_2048_sqr_64(r, ah);
-                err = sp_2048_mod_64_cond(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_2048_mul_64(r, ah, r);
-                err = sp_2048_mod_64_cond(r, r, m);
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_2048_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 64);
-            err = sp_2048_mod_64_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=31; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 64);
-                for (i--; i>=0; i--) {
-                    sp_2048_mont_sqr_64(r, r, m, mp);
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_2048_mont_mul_64(r, r, a, m, mp);
-                }
-                XMEMSET(&r[64], 0, sizeof(sp_digit) * 64);
-                sp_2048_mont_reduce_64(r, m, mp);
-
-                for (i = 63; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_2048_sub_in_place_64(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[64 * 2];
-    sp_digit pd[32], qd[32], dpd[32];
-    sp_digit tmpad[64], tmpbd[64];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 64 * 2;
-        q = p + 32;
-        qi = dq = dp = q + 32;
-        tmpa = qi + 32;
-        tmpb = tmpa + 64;
-
-        tmp = t;
-        r = tmp + 64;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 64;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 64, in, inLen);
-        sp_2048_from_mp(p, 32, pm);
-        sp_2048_from_mp(q, 32, qm);
-        sp_2048_from_mp(dp, 32, dpm);
-
-        err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(dq, 32, dqm);
-        err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_2048_sub_in_place_32(tmpa, tmpb);
-        sp_2048_mask_32(tmp, p, c);
-        sp_2048_add_32(tmpa, tmpa, tmp);
-
-        sp_2048_from_mp(qi, 32, qim);
-        sp_2048_mul_32(tmpa, tmpa, qi);
-        err = sp_2048_mod_32(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_32(tmpa, q, tmpa);
-        XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_add_64(r, tmpb, tmpa);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_2048_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 32
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 64);
-        r->used = 64;
-        mp_clamp(r);
-#elif DIGIT_BIT < 32
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 64; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 32) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 32 - s;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 64; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 32 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 32 - s;
-            }
-            else
-                s += 32;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[128], e[64], m[64];
-    sp_digit* r = b;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 64, base);
-        sp_2048_from_mp(e, 64, exp);
-        sp_2048_from_mp(m, 64, mod);
-
-        err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 256 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[128], e[64], m[64];
-    sp_digit* r = b;
-    word32 i;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 64, base);
-        sp_2048_from_bin(e, 64, exp, expLen);
-        sp_2048_from_mp(m, 64, mod);
-
-        err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_2048 */
-
-#ifndef WOLFSSL_SP_NO_3072
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 24) {
-            r[j] &= 0xffffffff;
-            s = 32 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 32
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 32
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffff;
-        s = 32 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 32 <= DIGIT_BIT) {
-            s += 32;
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 32) {
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            s = 32 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 384
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_3072_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 3072 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<96 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 32) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 32);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "#  A[0] * B[0]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r3, r4, r8, r9\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[0]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #4]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[1]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[0]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #8]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[2]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[1]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[0]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #12]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[3]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[2]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[0]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #16]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[4]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[3]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[2]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[1]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[0]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #20]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[5]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[4]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[3]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[2]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[1]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[0]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #24]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[6]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[5]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[4]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[3]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[2]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[1]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[0]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #28]\n\t"
-        "#  A[1] * B[7]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[2] * B[6]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[5]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[4]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[3]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[2]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[1]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "#  A[2] * B[7]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[3] * B[6]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[5]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[4]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[3]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[2]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "#  A[3] * B[7]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[4] * B[6]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[5]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[4]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[3]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "#  A[4] * B[7]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[5] * B[6]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[5]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[4]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "#  A[5] * B[7]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[6] * B[6]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[5]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "#  A[6] * B[7]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[7] * B[6]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "#  A[7] * B[7]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_8(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "#  A[0] * A[0]\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "umull	r8, r3, r10, r10\n\t"
-        "mov	r4, #0\n\t"
-        "str	r8, [%[tmp]]\n\t"
-        "#  A[0] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #4]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[1] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[tmp], #8]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[1] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[tmp], #12]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[1] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[2] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #16]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[tmp], #20]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[tmp], #24]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r2, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adcs	r4, r4, r6\n\t"
-        "adc	r2, r2, r7\n\t"
-        "str	r3, [%[tmp], #28]\n\t"
-        "#  A[1] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[2] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "#  A[2] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[3] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[r], #36]\n\t"
-        "#  A[3] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[4] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[5] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #40]\n\t"
-        "#  A[4] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[5] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[r], #44]\n\t"
-        "#  A[5] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[6] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[r], #48]\n\t"
-        "#  A[6] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #52]\n\t"
-        "#  A[7] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adc	r2, r2, r9\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r2, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_16(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_8(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<8; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-    r[4] = a[4] & m;
-    r[5] = a[5] & m;
-    r[6] = a[6] & m;
-    r[7] = a[7] & m;
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit b1[8];
-    sp_digit z2[16];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_8(a1, a, &a[8]);
-    cb = sp_3072_add_8(b1, b, &b[8]);
-    u  = ca & cb;
-    sp_3072_mul_8(z1, a1, b1);
-    sp_3072_mul_8(z2, &a[8], &b[8]);
-    sp_3072_mul_8(z0, a, b);
-    sp_3072_mask_8(r + 16, a1, 0 - cb);
-    sp_3072_mask_8(b1, b1, 0 - ca);
-    u += sp_3072_add_8(r + 16, r + 16, b1);
-    u += sp_3072_sub_in_place_16(z1, z2);
-    u += sp_3072_sub_in_place_16(z1, z0);
-    u += sp_3072_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_3072_add_16(r + 16, r + 16, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[16];
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit u;
-
-    u = sp_3072_add_8(a1, a, &a[8]);
-    sp_3072_sqr_8(z1, a1);
-    sp_3072_sqr_8(z2, &a[8]);
-    sp_3072_sqr_8(z0, a);
-    sp_3072_mask_8(r + 16, a1, 0 - u);
-    u += sp_3072_add_8(r + 16, r + 16, r + 16);
-    u += sp_3072_sub_in_place_16(z1, z2);
-    u += sp_3072_sub_in_place_16(z1, z0);
-    u += sp_3072_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_3072_add_16(r + 16, r + 16, z2);
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r3, [%[a], #0]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "ldr	r8, [%[b], #4]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "ldr	r10, [%[b], #12]\n\t"
-        "subs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r3, [%[a], #16]\n\t"
-        "ldr	r4, [%[a], #20]\n\t"
-        "ldr	r5, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "ldr	r8, [%[b], #20]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "ldr	r10, [%[b], #28]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #16]\n\t"
-        "str	r4, [%[r], #20]\n\t"
-        "str	r5, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "ldr	r3, [%[a], #32]\n\t"
-        "ldr	r4, [%[a], #36]\n\t"
-        "ldr	r5, [%[a], #40]\n\t"
-        "ldr	r6, [%[a], #44]\n\t"
-        "ldr	r7, [%[b], #32]\n\t"
-        "ldr	r8, [%[b], #36]\n\t"
-        "ldr	r9, [%[b], #40]\n\t"
-        "ldr	r10, [%[b], #44]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #32]\n\t"
-        "str	r4, [%[r], #36]\n\t"
-        "str	r5, [%[r], #40]\n\t"
-        "str	r6, [%[r], #44]\n\t"
-        "ldr	r3, [%[a], #48]\n\t"
-        "ldr	r4, [%[a], #52]\n\t"
-        "ldr	r5, [%[a], #56]\n\t"
-        "ldr	r6, [%[a], #60]\n\t"
-        "ldr	r7, [%[b], #48]\n\t"
-        "ldr	r8, [%[b], #52]\n\t"
-        "ldr	r9, [%[b], #56]\n\t"
-        "ldr	r10, [%[b], #60]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "str	r6, [%[r], #60]\n\t"
-        "ldr	r3, [%[a], #64]\n\t"
-        "ldr	r4, [%[a], #68]\n\t"
-        "ldr	r5, [%[a], #72]\n\t"
-        "ldr	r6, [%[a], #76]\n\t"
-        "ldr	r7, [%[b], #64]\n\t"
-        "ldr	r8, [%[b], #68]\n\t"
-        "ldr	r9, [%[b], #72]\n\t"
-        "ldr	r10, [%[b], #76]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #64]\n\t"
-        "str	r4, [%[r], #68]\n\t"
-        "str	r5, [%[r], #72]\n\t"
-        "str	r6, [%[r], #76]\n\t"
-        "ldr	r3, [%[a], #80]\n\t"
-        "ldr	r4, [%[a], #84]\n\t"
-        "ldr	r5, [%[a], #88]\n\t"
-        "ldr	r6, [%[a], #92]\n\t"
-        "ldr	r7, [%[b], #80]\n\t"
-        "ldr	r8, [%[b], #84]\n\t"
-        "ldr	r9, [%[b], #88]\n\t"
-        "ldr	r10, [%[b], #92]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #80]\n\t"
-        "str	r4, [%[r], #84]\n\t"
-        "str	r5, [%[r], #88]\n\t"
-        "str	r6, [%[r], #92]\n\t"
-        "ldr	r3, [%[a], #96]\n\t"
-        "ldr	r4, [%[a], #100]\n\t"
-        "ldr	r5, [%[a], #104]\n\t"
-        "ldr	r6, [%[a], #108]\n\t"
-        "ldr	r7, [%[b], #96]\n\t"
-        "ldr	r8, [%[b], #100]\n\t"
-        "ldr	r9, [%[b], #104]\n\t"
-        "ldr	r10, [%[b], #108]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #96]\n\t"
-        "str	r4, [%[r], #100]\n\t"
-        "str	r5, [%[r], #104]\n\t"
-        "str	r6, [%[r], #108]\n\t"
-        "ldr	r3, [%[a], #112]\n\t"
-        "ldr	r4, [%[a], #116]\n\t"
-        "ldr	r5, [%[a], #120]\n\t"
-        "ldr	r6, [%[a], #124]\n\t"
-        "ldr	r7, [%[b], #112]\n\t"
-        "ldr	r8, [%[b], #116]\n\t"
-        "ldr	r9, [%[b], #120]\n\t"
-        "ldr	r10, [%[b], #124]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #112]\n\t"
-        "str	r4, [%[r], #116]\n\t"
-        "str	r5, [%[r], #120]\n\t"
-        "str	r6, [%[r], #124]\n\t"
-        "sbc	%[c], %[c], #0\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r5, [%[a], #68]\n\t"
-        "ldr	r6, [%[a], #72]\n\t"
-        "ldr	r7, [%[a], #76]\n\t"
-        "ldr	r8, [%[b], #64]\n\t"
-        "ldr	r9, [%[b], #68]\n\t"
-        "ldr	r10, [%[b], #72]\n\t"
-        "ldr	r14, [%[b], #76]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "str	r6, [%[r], #72]\n\t"
-        "str	r7, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r5, [%[a], #84]\n\t"
-        "ldr	r6, [%[a], #88]\n\t"
-        "ldr	r7, [%[a], #92]\n\t"
-        "ldr	r8, [%[b], #80]\n\t"
-        "ldr	r9, [%[b], #84]\n\t"
-        "ldr	r10, [%[b], #88]\n\t"
-        "ldr	r14, [%[b], #92]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r5, [%[r], #84]\n\t"
-        "str	r6, [%[r], #88]\n\t"
-        "str	r7, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r5, [%[a], #100]\n\t"
-        "ldr	r6, [%[a], #104]\n\t"
-        "ldr	r7, [%[a], #108]\n\t"
-        "ldr	r8, [%[b], #96]\n\t"
-        "ldr	r9, [%[b], #100]\n\t"
-        "ldr	r10, [%[b], #104]\n\t"
-        "ldr	r14, [%[b], #108]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r5, [%[r], #100]\n\t"
-        "str	r6, [%[r], #104]\n\t"
-        "str	r7, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r5, [%[a], #116]\n\t"
-        "ldr	r6, [%[a], #120]\n\t"
-        "ldr	r7, [%[a], #124]\n\t"
-        "ldr	r8, [%[b], #112]\n\t"
-        "ldr	r9, [%[b], #116]\n\t"
-        "ldr	r10, [%[b], #120]\n\t"
-        "ldr	r14, [%[b], #124]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "str	r6, [%[r], #120]\n\t"
-        "str	r7, [%[r], #124]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit p0[32];
-    sp_digit p1[32];
-    sp_digit p2[32];
-    sp_digit p3[32];
-    sp_digit p4[32];
-    sp_digit p5[32];
-    sp_digit t0[32];
-    sp_digit t1[32];
-    sp_digit t2[32];
-    sp_digit a0[16];
-    sp_digit a1[16];
-    sp_digit a2[16];
-    sp_digit b0[16];
-    sp_digit b1[16];
-    sp_digit b2[16];
-    sp_3072_add_16(a0, a, &a[16]);
-    sp_3072_add_16(b0, b, &b[16]);
-    sp_3072_add_16(a1, &a[16], &a[32]);
-    sp_3072_add_16(b1, &b[16], &b[32]);
-    sp_3072_add_16(a2, a0, &a[32]);
-    sp_3072_add_16(b2, b0, &b[32]);
-    sp_3072_mul_16(p0, a, b);
-    sp_3072_mul_16(p2, &a[16], &b[16]);
-    sp_3072_mul_16(p4, &a[32], &b[32]);
-    sp_3072_mul_16(p1, a0, b0);
-    sp_3072_mul_16(p3, a1, b1);
-    sp_3072_mul_16(p5, a2, b2);
-    XMEMSET(r, 0, sizeof(*r)*2*48);
-    sp_3072_sub_32(t0, p3, p2);
-    sp_3072_sub_32(t1, p1, p2);
-    sp_3072_sub_32(t2, p5, t0);
-    sp_3072_sub_32(t2, t2, t1);
-    sp_3072_sub_32(t0, t0, p4);
-    sp_3072_sub_32(t1, t1, p0);
-    sp_3072_add_32(r, r, p0);
-    sp_3072_add_32(&r[16], &r[16], t1);
-    sp_3072_add_32(&r[32], &r[32], t2);
-    sp_3072_add_32(&r[48], &r[48], t0);
-    sp_3072_add_32(&r[64], &r[64], p4);
-}
-
-/* Square a into r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit p0[32];
-    sp_digit p1[32];
-    sp_digit p2[32];
-    sp_digit p3[32];
-    sp_digit p4[32];
-    sp_digit p5[32];
-    sp_digit t0[32];
-    sp_digit t1[32];
-    sp_digit t2[32];
-    sp_digit a0[16];
-    sp_digit a1[16];
-    sp_digit a2[16];
-    sp_3072_add_16(a0, a, &a[16]);
-    sp_3072_add_16(a1, &a[16], &a[32]);
-    sp_3072_add_16(a2, a0, &a[32]);
-    sp_3072_sqr_16(p0, a);
-    sp_3072_sqr_16(p2, &a[16]);
-    sp_3072_sqr_16(p4, &a[32]);
-    sp_3072_sqr_16(p1, a0);
-    sp_3072_sqr_16(p3, a1);
-    sp_3072_sqr_16(p5, a2);
-    XMEMSET(r, 0, sizeof(*r)*2*48);
-    sp_3072_sub_32(t0, p3, p2);
-    sp_3072_sub_32(t1, p1, p2);
-    sp_3072_sub_32(t2, p5, t0);
-    sp_3072_sub_32(t2, t2, t1);
-    sp_3072_sub_32(t0, t0, p4);
-    sp_3072_sub_32(t1, t1, p0);
-    sp_3072_add_32(r, r, p0);
-    sp_3072_add_32(&r[16], &r[16], t1);
-    sp_3072_add_32(&r[32], &r[32], t2);
-    sp_3072_add_32(&r[48], &r[48], t0);
-    sp_3072_add_32(&r[64], &r[64], p4);
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r5, [%[a], #68]\n\t"
-        "ldr	r6, [%[a], #72]\n\t"
-        "ldr	r7, [%[a], #76]\n\t"
-        "ldr	r8, [%[b], #64]\n\t"
-        "ldr	r9, [%[b], #68]\n\t"
-        "ldr	r10, [%[b], #72]\n\t"
-        "ldr	r14, [%[b], #76]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "str	r6, [%[r], #72]\n\t"
-        "str	r7, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r5, [%[a], #84]\n\t"
-        "ldr	r6, [%[a], #88]\n\t"
-        "ldr	r7, [%[a], #92]\n\t"
-        "ldr	r8, [%[b], #80]\n\t"
-        "ldr	r9, [%[b], #84]\n\t"
-        "ldr	r10, [%[b], #88]\n\t"
-        "ldr	r14, [%[b], #92]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r5, [%[r], #84]\n\t"
-        "str	r6, [%[r], #88]\n\t"
-        "str	r7, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r5, [%[a], #100]\n\t"
-        "ldr	r6, [%[a], #104]\n\t"
-        "ldr	r7, [%[a], #108]\n\t"
-        "ldr	r8, [%[b], #96]\n\t"
-        "ldr	r9, [%[b], #100]\n\t"
-        "ldr	r10, [%[b], #104]\n\t"
-        "ldr	r14, [%[b], #108]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r5, [%[r], #100]\n\t"
-        "str	r6, [%[r], #104]\n\t"
-        "str	r7, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r5, [%[a], #116]\n\t"
-        "ldr	r6, [%[a], #120]\n\t"
-        "ldr	r7, [%[a], #124]\n\t"
-        "ldr	r8, [%[b], #112]\n\t"
-        "ldr	r9, [%[b], #116]\n\t"
-        "ldr	r10, [%[b], #120]\n\t"
-        "ldr	r14, [%[b], #124]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "str	r6, [%[r], #120]\n\t"
-        "str	r7, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r5, [%[a], #132]\n\t"
-        "ldr	r6, [%[a], #136]\n\t"
-        "ldr	r7, [%[a], #140]\n\t"
-        "ldr	r8, [%[b], #128]\n\t"
-        "ldr	r9, [%[b], #132]\n\t"
-        "ldr	r10, [%[b], #136]\n\t"
-        "ldr	r14, [%[b], #140]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r5, [%[r], #132]\n\t"
-        "str	r6, [%[r], #136]\n\t"
-        "str	r7, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r5, [%[a], #148]\n\t"
-        "ldr	r6, [%[a], #152]\n\t"
-        "ldr	r7, [%[a], #156]\n\t"
-        "ldr	r8, [%[b], #144]\n\t"
-        "ldr	r9, [%[b], #148]\n\t"
-        "ldr	r10, [%[b], #152]\n\t"
-        "ldr	r14, [%[b], #156]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r5, [%[r], #148]\n\t"
-        "str	r6, [%[r], #152]\n\t"
-        "str	r7, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r5, [%[a], #164]\n\t"
-        "ldr	r6, [%[a], #168]\n\t"
-        "ldr	r7, [%[a], #172]\n\t"
-        "ldr	r8, [%[b], #160]\n\t"
-        "ldr	r9, [%[b], #164]\n\t"
-        "ldr	r10, [%[b], #168]\n\t"
-        "ldr	r14, [%[b], #172]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "str	r6, [%[r], #168]\n\t"
-        "str	r7, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r5, [%[a], #180]\n\t"
-        "ldr	r6, [%[a], #184]\n\t"
-        "ldr	r7, [%[a], #188]\n\t"
-        "ldr	r8, [%[b], #176]\n\t"
-        "ldr	r9, [%[b], #180]\n\t"
-        "ldr	r10, [%[b], #184]\n\t"
-        "ldr	r14, [%[b], #188]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r5, [%[r], #180]\n\t"
-        "str	r6, [%[r], #184]\n\t"
-        "str	r7, [%[r], #188]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "ldr	r2, [%[a], #64]\n\t"
-        "ldr	r3, [%[a], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r5, [%[a], #76]\n\t"
-        "ldr	r6, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "ldr	r8, [%[b], #72]\n\t"
-        "ldr	r9, [%[b], #76]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #64]\n\t"
-        "str	r3, [%[a], #68]\n\t"
-        "str	r4, [%[a], #72]\n\t"
-        "str	r5, [%[a], #76]\n\t"
-        "ldr	r2, [%[a], #80]\n\t"
-        "ldr	r3, [%[a], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r5, [%[a], #92]\n\t"
-        "ldr	r6, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "ldr	r8, [%[b], #88]\n\t"
-        "ldr	r9, [%[b], #92]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #80]\n\t"
-        "str	r3, [%[a], #84]\n\t"
-        "str	r4, [%[a], #88]\n\t"
-        "str	r5, [%[a], #92]\n\t"
-        "ldr	r2, [%[a], #96]\n\t"
-        "ldr	r3, [%[a], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r5, [%[a], #108]\n\t"
-        "ldr	r6, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "ldr	r8, [%[b], #104]\n\t"
-        "ldr	r9, [%[b], #108]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #96]\n\t"
-        "str	r3, [%[a], #100]\n\t"
-        "str	r4, [%[a], #104]\n\t"
-        "str	r5, [%[a], #108]\n\t"
-        "ldr	r2, [%[a], #112]\n\t"
-        "ldr	r3, [%[a], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r5, [%[a], #124]\n\t"
-        "ldr	r6, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "ldr	r8, [%[b], #120]\n\t"
-        "ldr	r9, [%[b], #124]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #112]\n\t"
-        "str	r3, [%[a], #116]\n\t"
-        "str	r4, [%[a], #120]\n\t"
-        "str	r5, [%[a], #124]\n\t"
-        "ldr	r2, [%[a], #128]\n\t"
-        "ldr	r3, [%[a], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r5, [%[a], #140]\n\t"
-        "ldr	r6, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "ldr	r8, [%[b], #136]\n\t"
-        "ldr	r9, [%[b], #140]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #128]\n\t"
-        "str	r3, [%[a], #132]\n\t"
-        "str	r4, [%[a], #136]\n\t"
-        "str	r5, [%[a], #140]\n\t"
-        "ldr	r2, [%[a], #144]\n\t"
-        "ldr	r3, [%[a], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r5, [%[a], #156]\n\t"
-        "ldr	r6, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "ldr	r8, [%[b], #152]\n\t"
-        "ldr	r9, [%[b], #156]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #144]\n\t"
-        "str	r3, [%[a], #148]\n\t"
-        "str	r4, [%[a], #152]\n\t"
-        "str	r5, [%[a], #156]\n\t"
-        "ldr	r2, [%[a], #160]\n\t"
-        "ldr	r3, [%[a], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r5, [%[a], #172]\n\t"
-        "ldr	r6, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "ldr	r8, [%[b], #168]\n\t"
-        "ldr	r9, [%[b], #172]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #160]\n\t"
-        "str	r3, [%[a], #164]\n\t"
-        "str	r4, [%[a], #168]\n\t"
-        "str	r5, [%[a], #172]\n\t"
-        "ldr	r2, [%[a], #176]\n\t"
-        "ldr	r3, [%[a], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r5, [%[a], #188]\n\t"
-        "ldr	r6, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "ldr	r8, [%[b], #184]\n\t"
-        "ldr	r9, [%[b], #188]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #176]\n\t"
-        "str	r3, [%[a], #180]\n\t"
-        "str	r4, [%[a], #184]\n\t"
-        "str	r5, [%[a], #188]\n\t"
-        "ldr	r2, [%[a], #192]\n\t"
-        "ldr	r3, [%[a], #196]\n\t"
-        "ldr	r4, [%[a], #200]\n\t"
-        "ldr	r5, [%[a], #204]\n\t"
-        "ldr	r6, [%[b], #192]\n\t"
-        "ldr	r7, [%[b], #196]\n\t"
-        "ldr	r8, [%[b], #200]\n\t"
-        "ldr	r9, [%[b], #204]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #192]\n\t"
-        "str	r3, [%[a], #196]\n\t"
-        "str	r4, [%[a], #200]\n\t"
-        "str	r5, [%[a], #204]\n\t"
-        "ldr	r2, [%[a], #208]\n\t"
-        "ldr	r3, [%[a], #212]\n\t"
-        "ldr	r4, [%[a], #216]\n\t"
-        "ldr	r5, [%[a], #220]\n\t"
-        "ldr	r6, [%[b], #208]\n\t"
-        "ldr	r7, [%[b], #212]\n\t"
-        "ldr	r8, [%[b], #216]\n\t"
-        "ldr	r9, [%[b], #220]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #208]\n\t"
-        "str	r3, [%[a], #212]\n\t"
-        "str	r4, [%[a], #216]\n\t"
-        "str	r5, [%[a], #220]\n\t"
-        "ldr	r2, [%[a], #224]\n\t"
-        "ldr	r3, [%[a], #228]\n\t"
-        "ldr	r4, [%[a], #232]\n\t"
-        "ldr	r5, [%[a], #236]\n\t"
-        "ldr	r6, [%[b], #224]\n\t"
-        "ldr	r7, [%[b], #228]\n\t"
-        "ldr	r8, [%[b], #232]\n\t"
-        "ldr	r9, [%[b], #236]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #224]\n\t"
-        "str	r3, [%[a], #228]\n\t"
-        "str	r4, [%[a], #232]\n\t"
-        "str	r5, [%[a], #236]\n\t"
-        "ldr	r2, [%[a], #240]\n\t"
-        "ldr	r3, [%[a], #244]\n\t"
-        "ldr	r4, [%[a], #248]\n\t"
-        "ldr	r5, [%[a], #252]\n\t"
-        "ldr	r6, [%[b], #240]\n\t"
-        "ldr	r7, [%[b], #244]\n\t"
-        "ldr	r8, [%[b], #248]\n\t"
-        "ldr	r9, [%[b], #252]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #240]\n\t"
-        "str	r3, [%[a], #244]\n\t"
-        "str	r4, [%[a], #248]\n\t"
-        "str	r5, [%[a], #252]\n\t"
-        "ldr	r2, [%[a], #256]\n\t"
-        "ldr	r3, [%[a], #260]\n\t"
-        "ldr	r4, [%[a], #264]\n\t"
-        "ldr	r5, [%[a], #268]\n\t"
-        "ldr	r6, [%[b], #256]\n\t"
-        "ldr	r7, [%[b], #260]\n\t"
-        "ldr	r8, [%[b], #264]\n\t"
-        "ldr	r9, [%[b], #268]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #256]\n\t"
-        "str	r3, [%[a], #260]\n\t"
-        "str	r4, [%[a], #264]\n\t"
-        "str	r5, [%[a], #268]\n\t"
-        "ldr	r2, [%[a], #272]\n\t"
-        "ldr	r3, [%[a], #276]\n\t"
-        "ldr	r4, [%[a], #280]\n\t"
-        "ldr	r5, [%[a], #284]\n\t"
-        "ldr	r6, [%[b], #272]\n\t"
-        "ldr	r7, [%[b], #276]\n\t"
-        "ldr	r8, [%[b], #280]\n\t"
-        "ldr	r9, [%[b], #284]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #272]\n\t"
-        "str	r3, [%[a], #276]\n\t"
-        "str	r4, [%[a], #280]\n\t"
-        "str	r5, [%[a], #284]\n\t"
-        "ldr	r2, [%[a], #288]\n\t"
-        "ldr	r3, [%[a], #292]\n\t"
-        "ldr	r4, [%[a], #296]\n\t"
-        "ldr	r5, [%[a], #300]\n\t"
-        "ldr	r6, [%[b], #288]\n\t"
-        "ldr	r7, [%[b], #292]\n\t"
-        "ldr	r8, [%[b], #296]\n\t"
-        "ldr	r9, [%[b], #300]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #288]\n\t"
-        "str	r3, [%[a], #292]\n\t"
-        "str	r4, [%[a], #296]\n\t"
-        "str	r5, [%[a], #300]\n\t"
-        "ldr	r2, [%[a], #304]\n\t"
-        "ldr	r3, [%[a], #308]\n\t"
-        "ldr	r4, [%[a], #312]\n\t"
-        "ldr	r5, [%[a], #316]\n\t"
-        "ldr	r6, [%[b], #304]\n\t"
-        "ldr	r7, [%[b], #308]\n\t"
-        "ldr	r8, [%[b], #312]\n\t"
-        "ldr	r9, [%[b], #316]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #304]\n\t"
-        "str	r3, [%[a], #308]\n\t"
-        "str	r4, [%[a], #312]\n\t"
-        "str	r5, [%[a], #316]\n\t"
-        "ldr	r2, [%[a], #320]\n\t"
-        "ldr	r3, [%[a], #324]\n\t"
-        "ldr	r4, [%[a], #328]\n\t"
-        "ldr	r5, [%[a], #332]\n\t"
-        "ldr	r6, [%[b], #320]\n\t"
-        "ldr	r7, [%[b], #324]\n\t"
-        "ldr	r8, [%[b], #328]\n\t"
-        "ldr	r9, [%[b], #332]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #320]\n\t"
-        "str	r3, [%[a], #324]\n\t"
-        "str	r4, [%[a], #328]\n\t"
-        "str	r5, [%[a], #332]\n\t"
-        "ldr	r2, [%[a], #336]\n\t"
-        "ldr	r3, [%[a], #340]\n\t"
-        "ldr	r4, [%[a], #344]\n\t"
-        "ldr	r5, [%[a], #348]\n\t"
-        "ldr	r6, [%[b], #336]\n\t"
-        "ldr	r7, [%[b], #340]\n\t"
-        "ldr	r8, [%[b], #344]\n\t"
-        "ldr	r9, [%[b], #348]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #336]\n\t"
-        "str	r3, [%[a], #340]\n\t"
-        "str	r4, [%[a], #344]\n\t"
-        "str	r5, [%[a], #348]\n\t"
-        "ldr	r2, [%[a], #352]\n\t"
-        "ldr	r3, [%[a], #356]\n\t"
-        "ldr	r4, [%[a], #360]\n\t"
-        "ldr	r5, [%[a], #364]\n\t"
-        "ldr	r6, [%[b], #352]\n\t"
-        "ldr	r7, [%[b], #356]\n\t"
-        "ldr	r8, [%[b], #360]\n\t"
-        "ldr	r9, [%[b], #364]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #352]\n\t"
-        "str	r3, [%[a], #356]\n\t"
-        "str	r4, [%[a], #360]\n\t"
-        "str	r5, [%[a], #364]\n\t"
-        "ldr	r2, [%[a], #368]\n\t"
-        "ldr	r3, [%[a], #372]\n\t"
-        "ldr	r4, [%[a], #376]\n\t"
-        "ldr	r5, [%[a], #380]\n\t"
-        "ldr	r6, [%[b], #368]\n\t"
-        "ldr	r7, [%[b], #372]\n\t"
-        "ldr	r8, [%[b], #376]\n\t"
-        "ldr	r9, [%[b], #380]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #368]\n\t"
-        "str	r3, [%[a], #372]\n\t"
-        "str	r4, [%[a], #376]\n\t"
-        "str	r5, [%[a], #380]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r5, [%[a], #36]\n\t"
-        "ldr	r6, [%[a], #40]\n\t"
-        "ldr	r7, [%[a], #44]\n\t"
-        "ldr	r8, [%[b], #32]\n\t"
-        "ldr	r9, [%[b], #36]\n\t"
-        "ldr	r10, [%[b], #40]\n\t"
-        "ldr	r14, [%[b], #44]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r5, [%[r], #36]\n\t"
-        "str	r6, [%[r], #40]\n\t"
-        "str	r7, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r5, [%[a], #52]\n\t"
-        "ldr	r6, [%[a], #56]\n\t"
-        "ldr	r7, [%[a], #60]\n\t"
-        "ldr	r8, [%[b], #48]\n\t"
-        "ldr	r9, [%[b], #52]\n\t"
-        "ldr	r10, [%[b], #56]\n\t"
-        "ldr	r14, [%[b], #60]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r5, [%[r], #52]\n\t"
-        "str	r6, [%[r], #56]\n\t"
-        "str	r7, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r5, [%[a], #68]\n\t"
-        "ldr	r6, [%[a], #72]\n\t"
-        "ldr	r7, [%[a], #76]\n\t"
-        "ldr	r8, [%[b], #64]\n\t"
-        "ldr	r9, [%[b], #68]\n\t"
-        "ldr	r10, [%[b], #72]\n\t"
-        "ldr	r14, [%[b], #76]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "str	r6, [%[r], #72]\n\t"
-        "str	r7, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r5, [%[a], #84]\n\t"
-        "ldr	r6, [%[a], #88]\n\t"
-        "ldr	r7, [%[a], #92]\n\t"
-        "ldr	r8, [%[b], #80]\n\t"
-        "ldr	r9, [%[b], #84]\n\t"
-        "ldr	r10, [%[b], #88]\n\t"
-        "ldr	r14, [%[b], #92]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r5, [%[r], #84]\n\t"
-        "str	r6, [%[r], #88]\n\t"
-        "str	r7, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r5, [%[a], #100]\n\t"
-        "ldr	r6, [%[a], #104]\n\t"
-        "ldr	r7, [%[a], #108]\n\t"
-        "ldr	r8, [%[b], #96]\n\t"
-        "ldr	r9, [%[b], #100]\n\t"
-        "ldr	r10, [%[b], #104]\n\t"
-        "ldr	r14, [%[b], #108]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r5, [%[r], #100]\n\t"
-        "str	r6, [%[r], #104]\n\t"
-        "str	r7, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r5, [%[a], #116]\n\t"
-        "ldr	r6, [%[a], #120]\n\t"
-        "ldr	r7, [%[a], #124]\n\t"
-        "ldr	r8, [%[b], #112]\n\t"
-        "ldr	r9, [%[b], #116]\n\t"
-        "ldr	r10, [%[b], #120]\n\t"
-        "ldr	r14, [%[b], #124]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "str	r6, [%[r], #120]\n\t"
-        "str	r7, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r5, [%[a], #132]\n\t"
-        "ldr	r6, [%[a], #136]\n\t"
-        "ldr	r7, [%[a], #140]\n\t"
-        "ldr	r8, [%[b], #128]\n\t"
-        "ldr	r9, [%[b], #132]\n\t"
-        "ldr	r10, [%[b], #136]\n\t"
-        "ldr	r14, [%[b], #140]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r5, [%[r], #132]\n\t"
-        "str	r6, [%[r], #136]\n\t"
-        "str	r7, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r5, [%[a], #148]\n\t"
-        "ldr	r6, [%[a], #152]\n\t"
-        "ldr	r7, [%[a], #156]\n\t"
-        "ldr	r8, [%[b], #144]\n\t"
-        "ldr	r9, [%[b], #148]\n\t"
-        "ldr	r10, [%[b], #152]\n\t"
-        "ldr	r14, [%[b], #156]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r5, [%[r], #148]\n\t"
-        "str	r6, [%[r], #152]\n\t"
-        "str	r7, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r5, [%[a], #164]\n\t"
-        "ldr	r6, [%[a], #168]\n\t"
-        "ldr	r7, [%[a], #172]\n\t"
-        "ldr	r8, [%[b], #160]\n\t"
-        "ldr	r9, [%[b], #164]\n\t"
-        "ldr	r10, [%[b], #168]\n\t"
-        "ldr	r14, [%[b], #172]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "str	r6, [%[r], #168]\n\t"
-        "str	r7, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r5, [%[a], #180]\n\t"
-        "ldr	r6, [%[a], #184]\n\t"
-        "ldr	r7, [%[a], #188]\n\t"
-        "ldr	r8, [%[b], #176]\n\t"
-        "ldr	r9, [%[b], #180]\n\t"
-        "ldr	r10, [%[b], #184]\n\t"
-        "ldr	r14, [%[b], #188]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r5, [%[r], #180]\n\t"
-        "str	r6, [%[r], #184]\n\t"
-        "str	r7, [%[r], #188]\n\t"
-        "ldr	r4, [%[a], #192]\n\t"
-        "ldr	r5, [%[a], #196]\n\t"
-        "ldr	r6, [%[a], #200]\n\t"
-        "ldr	r7, [%[a], #204]\n\t"
-        "ldr	r8, [%[b], #192]\n\t"
-        "ldr	r9, [%[b], #196]\n\t"
-        "ldr	r10, [%[b], #200]\n\t"
-        "ldr	r14, [%[b], #204]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #192]\n\t"
-        "str	r5, [%[r], #196]\n\t"
-        "str	r6, [%[r], #200]\n\t"
-        "str	r7, [%[r], #204]\n\t"
-        "ldr	r4, [%[a], #208]\n\t"
-        "ldr	r5, [%[a], #212]\n\t"
-        "ldr	r6, [%[a], #216]\n\t"
-        "ldr	r7, [%[a], #220]\n\t"
-        "ldr	r8, [%[b], #208]\n\t"
-        "ldr	r9, [%[b], #212]\n\t"
-        "ldr	r10, [%[b], #216]\n\t"
-        "ldr	r14, [%[b], #220]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "str	r5, [%[r], #212]\n\t"
-        "str	r6, [%[r], #216]\n\t"
-        "str	r7, [%[r], #220]\n\t"
-        "ldr	r4, [%[a], #224]\n\t"
-        "ldr	r5, [%[a], #228]\n\t"
-        "ldr	r6, [%[a], #232]\n\t"
-        "ldr	r7, [%[a], #236]\n\t"
-        "ldr	r8, [%[b], #224]\n\t"
-        "ldr	r9, [%[b], #228]\n\t"
-        "ldr	r10, [%[b], #232]\n\t"
-        "ldr	r14, [%[b], #236]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #224]\n\t"
-        "str	r5, [%[r], #228]\n\t"
-        "str	r6, [%[r], #232]\n\t"
-        "str	r7, [%[r], #236]\n\t"
-        "ldr	r4, [%[a], #240]\n\t"
-        "ldr	r5, [%[a], #244]\n\t"
-        "ldr	r6, [%[a], #248]\n\t"
-        "ldr	r7, [%[a], #252]\n\t"
-        "ldr	r8, [%[b], #240]\n\t"
-        "ldr	r9, [%[b], #244]\n\t"
-        "ldr	r10, [%[b], #248]\n\t"
-        "ldr	r14, [%[b], #252]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #240]\n\t"
-        "str	r5, [%[r], #244]\n\t"
-        "str	r6, [%[r], #248]\n\t"
-        "str	r7, [%[r], #252]\n\t"
-        "ldr	r4, [%[a], #256]\n\t"
-        "ldr	r5, [%[a], #260]\n\t"
-        "ldr	r6, [%[a], #264]\n\t"
-        "ldr	r7, [%[a], #268]\n\t"
-        "ldr	r8, [%[b], #256]\n\t"
-        "ldr	r9, [%[b], #260]\n\t"
-        "ldr	r10, [%[b], #264]\n\t"
-        "ldr	r14, [%[b], #268]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #256]\n\t"
-        "str	r5, [%[r], #260]\n\t"
-        "str	r6, [%[r], #264]\n\t"
-        "str	r7, [%[r], #268]\n\t"
-        "ldr	r4, [%[a], #272]\n\t"
-        "ldr	r5, [%[a], #276]\n\t"
-        "ldr	r6, [%[a], #280]\n\t"
-        "ldr	r7, [%[a], #284]\n\t"
-        "ldr	r8, [%[b], #272]\n\t"
-        "ldr	r9, [%[b], #276]\n\t"
-        "ldr	r10, [%[b], #280]\n\t"
-        "ldr	r14, [%[b], #284]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #272]\n\t"
-        "str	r5, [%[r], #276]\n\t"
-        "str	r6, [%[r], #280]\n\t"
-        "str	r7, [%[r], #284]\n\t"
-        "ldr	r4, [%[a], #288]\n\t"
-        "ldr	r5, [%[a], #292]\n\t"
-        "ldr	r6, [%[a], #296]\n\t"
-        "ldr	r7, [%[a], #300]\n\t"
-        "ldr	r8, [%[b], #288]\n\t"
-        "ldr	r9, [%[b], #292]\n\t"
-        "ldr	r10, [%[b], #296]\n\t"
-        "ldr	r14, [%[b], #300]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #288]\n\t"
-        "str	r5, [%[r], #292]\n\t"
-        "str	r6, [%[r], #296]\n\t"
-        "str	r7, [%[r], #300]\n\t"
-        "ldr	r4, [%[a], #304]\n\t"
-        "ldr	r5, [%[a], #308]\n\t"
-        "ldr	r6, [%[a], #312]\n\t"
-        "ldr	r7, [%[a], #316]\n\t"
-        "ldr	r8, [%[b], #304]\n\t"
-        "ldr	r9, [%[b], #308]\n\t"
-        "ldr	r10, [%[b], #312]\n\t"
-        "ldr	r14, [%[b], #316]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #304]\n\t"
-        "str	r5, [%[r], #308]\n\t"
-        "str	r6, [%[r], #312]\n\t"
-        "str	r7, [%[r], #316]\n\t"
-        "ldr	r4, [%[a], #320]\n\t"
-        "ldr	r5, [%[a], #324]\n\t"
-        "ldr	r6, [%[a], #328]\n\t"
-        "ldr	r7, [%[a], #332]\n\t"
-        "ldr	r8, [%[b], #320]\n\t"
-        "ldr	r9, [%[b], #324]\n\t"
-        "ldr	r10, [%[b], #328]\n\t"
-        "ldr	r14, [%[b], #332]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #320]\n\t"
-        "str	r5, [%[r], #324]\n\t"
-        "str	r6, [%[r], #328]\n\t"
-        "str	r7, [%[r], #332]\n\t"
-        "ldr	r4, [%[a], #336]\n\t"
-        "ldr	r5, [%[a], #340]\n\t"
-        "ldr	r6, [%[a], #344]\n\t"
-        "ldr	r7, [%[a], #348]\n\t"
-        "ldr	r8, [%[b], #336]\n\t"
-        "ldr	r9, [%[b], #340]\n\t"
-        "ldr	r10, [%[b], #344]\n\t"
-        "ldr	r14, [%[b], #348]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #336]\n\t"
-        "str	r5, [%[r], #340]\n\t"
-        "str	r6, [%[r], #344]\n\t"
-        "str	r7, [%[r], #348]\n\t"
-        "ldr	r4, [%[a], #352]\n\t"
-        "ldr	r5, [%[a], #356]\n\t"
-        "ldr	r6, [%[a], #360]\n\t"
-        "ldr	r7, [%[a], #364]\n\t"
-        "ldr	r8, [%[b], #352]\n\t"
-        "ldr	r9, [%[b], #356]\n\t"
-        "ldr	r10, [%[b], #360]\n\t"
-        "ldr	r14, [%[b], #364]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #352]\n\t"
-        "str	r5, [%[r], #356]\n\t"
-        "str	r6, [%[r], #360]\n\t"
-        "str	r7, [%[r], #364]\n\t"
-        "ldr	r4, [%[a], #368]\n\t"
-        "ldr	r5, [%[a], #372]\n\t"
-        "ldr	r6, [%[a], #376]\n\t"
-        "ldr	r7, [%[a], #380]\n\t"
-        "ldr	r8, [%[b], #368]\n\t"
-        "ldr	r9, [%[b], #372]\n\t"
-        "ldr	r10, [%[b], #376]\n\t"
-        "ldr	r14, [%[b], #380]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #368]\n\t"
-        "str	r5, [%[r], #372]\n\t"
-        "str	r6, [%[r], #376]\n\t"
-        "str	r7, [%[r], #380]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<48; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_96(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[96];
-    sp_digit a1[48];
-    sp_digit b1[48];
-    sp_digit z2[96];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_48(a1, a, &a[48]);
-    cb = sp_3072_add_48(b1, b, &b[48]);
-    u  = ca & cb;
-    sp_3072_mul_48(z1, a1, b1);
-    sp_3072_mul_48(z2, &a[48], &b[48]);
-    sp_3072_mul_48(z0, a, b);
-    sp_3072_mask_48(r + 96, a1, 0 - cb);
-    sp_3072_mask_48(b1, b1, 0 - ca);
-    u += sp_3072_add_48(r + 96, r + 96, b1);
-    u += sp_3072_sub_in_place_96(z1, z2);
-    u += sp_3072_sub_in_place_96(z1, z0);
-    u += sp_3072_add_96(r + 48, r + 48, z1);
-    r[144] = u;
-    XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1));
-    sp_3072_add_96(r + 96, r + 96, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[96];
-    sp_digit z1[96];
-    sp_digit a1[48];
-    sp_digit u;
-
-    u = sp_3072_add_48(a1, a, &a[48]);
-    sp_3072_sqr_48(z1, a1);
-    sp_3072_sqr_48(z2, &a[48]);
-    sp_3072_sqr_48(z0, a);
-    sp_3072_mask_48(r + 96, a1, 0 - u);
-    u += sp_3072_add_48(r + 96, r + 96, r + 96);
-    u += sp_3072_sub_in_place_96(z1, z2);
-    u += sp_3072_sub_in_place_96(z1, z0);
-    u += sp_3072_add_96(r + 48, r + 48, z1);
-    r[144] = u;
-    XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1));
-    sp_3072_add_96(r + 96, r + 96, z2);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #384\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "mov	r4, #0\n\t"
-        "adc	%[c], r4, #0\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "add	r12, %[a], #384\n\t"
-        "\n1:\n\t"
-        "subs	%[c], r14, %[c]\n\t"
-        "ldr	r3, [%[a]]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[a]], #4\n\t"
-        "str	r4, [%[a]], #4\n\t"
-        "str	r5, [%[a]], #4\n\t"
-        "str	r6, [%[a]], #4\n\t"
-        "sbc	%[c], r14, r14\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[192];
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #380\n\t"
-        "movcc	r3, #0\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r12, [%[b], r4]\n\t"
-        "umull	r9, r10, r14, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, #0\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #384\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #760\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[192];
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "mov	r5, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #380\n\t"
-        "movcc	r3, r12\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "cmp	r4, r3\n\t"
-        "beq	4f\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r9, [%[a], r4]\n\t"
-        "umull	r9, r10, r14, r9\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "bal	5f\n\t"
-        "\n4:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "umull	r9, r10, r14, r14\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "\n5:\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #384\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r4\n\t"
-        "bgt	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #760\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m)
-{
-    int i;
-
-    for (i=0; i<48; i++)
-        r[i] = a[i] & m;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #192\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "mov	r4, #0\n\t"
-        "adc	%[c], r4, #0\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[96];
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #188\n\t"
-        "movcc	r3, #0\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r12, [%[b], r4]\n\t"
-        "umull	r9, r10, r14, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, #0\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #192\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #376\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[96];
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "mov	r5, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #188\n\t"
-        "movcc	r3, r12\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "cmp	r4, r3\n\t"
-        "beq	4f\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r9, [%[a], r4]\n\t"
-        "umull	r9, r10, r14, r9\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "bal	5f\n\t"
-        "\n4:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "umull	r9, r10, r14, r14\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "\n5:\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #192\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r4\n\t"
-        "bgt	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #376\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "add	r12, %[a], #192\n\t"
-        "\n1:\n\t"
-        "subs	%[c], r14, %[c]\n\t"
-        "ldr	r3, [%[a]]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[a]], #4\n\t"
-        "str	r4, [%[a]], #4\n\t"
-        "str	r5, [%[a]], #4\n\t"
-        "str	r6, [%[a]], #4\n\t"
-        "sbc	%[c], r14, r14\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
-    );
-
-    return c;
-}
-
-#else
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "ldr	r2, [%[a], #32]\n\t"
-        "ldr	r3, [%[a], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r5, [%[a], #44]\n\t"
-        "ldr	r6, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "ldr	r8, [%[b], #40]\n\t"
-        "ldr	r9, [%[b], #44]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #32]\n\t"
-        "str	r3, [%[a], #36]\n\t"
-        "str	r4, [%[a], #40]\n\t"
-        "str	r5, [%[a], #44]\n\t"
-        "ldr	r2, [%[a], #48]\n\t"
-        "ldr	r3, [%[a], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r5, [%[a], #60]\n\t"
-        "ldr	r6, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "ldr	r8, [%[b], #56]\n\t"
-        "ldr	r9, [%[b], #60]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #48]\n\t"
-        "str	r3, [%[a], #52]\n\t"
-        "str	r4, [%[a], #56]\n\t"
-        "str	r5, [%[a], #60]\n\t"
-        "ldr	r2, [%[a], #64]\n\t"
-        "ldr	r3, [%[a], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r5, [%[a], #76]\n\t"
-        "ldr	r6, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "ldr	r8, [%[b], #72]\n\t"
-        "ldr	r9, [%[b], #76]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #64]\n\t"
-        "str	r3, [%[a], #68]\n\t"
-        "str	r4, [%[a], #72]\n\t"
-        "str	r5, [%[a], #76]\n\t"
-        "ldr	r2, [%[a], #80]\n\t"
-        "ldr	r3, [%[a], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r5, [%[a], #92]\n\t"
-        "ldr	r6, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "ldr	r8, [%[b], #88]\n\t"
-        "ldr	r9, [%[b], #92]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #80]\n\t"
-        "str	r3, [%[a], #84]\n\t"
-        "str	r4, [%[a], #88]\n\t"
-        "str	r5, [%[a], #92]\n\t"
-        "ldr	r2, [%[a], #96]\n\t"
-        "ldr	r3, [%[a], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r5, [%[a], #108]\n\t"
-        "ldr	r6, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "ldr	r8, [%[b], #104]\n\t"
-        "ldr	r9, [%[b], #108]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #96]\n\t"
-        "str	r3, [%[a], #100]\n\t"
-        "str	r4, [%[a], #104]\n\t"
-        "str	r5, [%[a], #108]\n\t"
-        "ldr	r2, [%[a], #112]\n\t"
-        "ldr	r3, [%[a], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r5, [%[a], #124]\n\t"
-        "ldr	r6, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "ldr	r8, [%[b], #120]\n\t"
-        "ldr	r9, [%[b], #124]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #112]\n\t"
-        "str	r3, [%[a], #116]\n\t"
-        "str	r4, [%[a], #120]\n\t"
-        "str	r5, [%[a], #124]\n\t"
-        "ldr	r2, [%[a], #128]\n\t"
-        "ldr	r3, [%[a], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r5, [%[a], #140]\n\t"
-        "ldr	r6, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "ldr	r8, [%[b], #136]\n\t"
-        "ldr	r9, [%[b], #140]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #128]\n\t"
-        "str	r3, [%[a], #132]\n\t"
-        "str	r4, [%[a], #136]\n\t"
-        "str	r5, [%[a], #140]\n\t"
-        "ldr	r2, [%[a], #144]\n\t"
-        "ldr	r3, [%[a], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r5, [%[a], #156]\n\t"
-        "ldr	r6, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "ldr	r8, [%[b], #152]\n\t"
-        "ldr	r9, [%[b], #156]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #144]\n\t"
-        "str	r3, [%[a], #148]\n\t"
-        "str	r4, [%[a], #152]\n\t"
-        "str	r5, [%[a], #156]\n\t"
-        "ldr	r2, [%[a], #160]\n\t"
-        "ldr	r3, [%[a], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r5, [%[a], #172]\n\t"
-        "ldr	r6, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "ldr	r8, [%[b], #168]\n\t"
-        "ldr	r9, [%[b], #172]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #160]\n\t"
-        "str	r3, [%[a], #164]\n\t"
-        "str	r4, [%[a], #168]\n\t"
-        "str	r5, [%[a], #172]\n\t"
-        "ldr	r2, [%[a], #176]\n\t"
-        "ldr	r3, [%[a], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r5, [%[a], #188]\n\t"
-        "ldr	r6, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "ldr	r8, [%[b], #184]\n\t"
-        "ldr	r9, [%[b], #188]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #176]\n\t"
-        "str	r3, [%[a], #180]\n\t"
-        "str	r4, [%[a], #184]\n\t"
-        "str	r5, [%[a], #188]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 48);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_48(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r9, #0\n\t"
-        "mov	r8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], r9, %[c]\n\t"
-        "ldr	r4, [%[a], r8]\n\t"
-        "ldr	r5, [%[b], r8]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        "str	r4, [%[r], r8]\n\t"
-        "add	r8, r8, #4\n\t"
-        "cmp	r8, #192\n\t"
-        "blt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "mov	r9, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r5, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "subs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r6, [%[r], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r5, [%[b], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r5, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r6, [%[r], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r5, [%[b], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r6, [%[a], #36]\n\t"
-        "ldr	r5, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r6, [%[r], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r6, [%[a], #44]\n\t"
-        "ldr	r5, [%[b], #40]\n\t"
-        "ldr	r7, [%[b], #44]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "str	r6, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r6, [%[a], #52]\n\t"
-        "ldr	r5, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r6, [%[r], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r6, [%[a], #60]\n\t"
-        "ldr	r5, [%[b], #56]\n\t"
-        "ldr	r7, [%[b], #60]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r6, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r6, [%[a], #68]\n\t"
-        "ldr	r5, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r6, [%[r], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r6, [%[a], #76]\n\t"
-        "ldr	r5, [%[b], #72]\n\t"
-        "ldr	r7, [%[b], #76]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #72]\n\t"
-        "str	r6, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r6, [%[a], #84]\n\t"
-        "ldr	r5, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r6, [%[r], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r6, [%[a], #92]\n\t"
-        "ldr	r5, [%[b], #88]\n\t"
-        "ldr	r7, [%[b], #92]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "str	r6, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r6, [%[a], #100]\n\t"
-        "ldr	r5, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r6, [%[r], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r6, [%[a], #108]\n\t"
-        "ldr	r5, [%[b], #104]\n\t"
-        "ldr	r7, [%[b], #108]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #104]\n\t"
-        "str	r6, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r6, [%[a], #116]\n\t"
-        "ldr	r5, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r6, [%[r], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r6, [%[a], #124]\n\t"
-        "ldr	r5, [%[b], #120]\n\t"
-        "ldr	r7, [%[b], #124]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #120]\n\t"
-        "str	r6, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r6, [%[a], #132]\n\t"
-        "ldr	r5, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r6, [%[r], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r6, [%[a], #140]\n\t"
-        "ldr	r5, [%[b], #136]\n\t"
-        "ldr	r7, [%[b], #140]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "str	r6, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r6, [%[a], #148]\n\t"
-        "ldr	r5, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r6, [%[r], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r6, [%[a], #156]\n\t"
-        "ldr	r5, [%[b], #152]\n\t"
-        "ldr	r7, [%[b], #156]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #152]\n\t"
-        "str	r6, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r6, [%[a], #164]\n\t"
-        "ldr	r5, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r6, [%[r], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r6, [%[a], #172]\n\t"
-        "ldr	r5, [%[b], #168]\n\t"
-        "ldr	r7, [%[b], #172]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #168]\n\t"
-        "str	r6, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r6, [%[a], #180]\n\t"
-        "ldr	r5, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r6, [%[r], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r6, [%[a], #188]\n\t"
-        "ldr	r5, [%[b], #184]\n\t"
-        "ldr	r7, [%[b], #188]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "str	r6, [%[r], #188]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "ldr	r14, [%[a], #4]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	r8, %[mp], r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	r7, [%[m], #0]\n\t"
-        "ldr	r9, [%[a], #0]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r10, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	r7, [%[m], #4]\n\t"
-        "ldr	r9, [%[a], #4]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r14, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r10, r10, r5\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	r7, [%[m], #8]\n\t"
-        "ldr	r14, [%[a], #8]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r14, r14, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r14, r14, r4\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	r7, [%[m], #12]\n\t"
-        "ldr	r9, [%[a], #12]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #12]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	r7, [%[m], #16]\n\t"
-        "ldr	r9, [%[a], #16]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #16]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	r7, [%[m], #20]\n\t"
-        "ldr	r9, [%[a], #20]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #20]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	r7, [%[m], #24]\n\t"
-        "ldr	r9, [%[a], #24]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #24]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	r7, [%[m], #28]\n\t"
-        "ldr	r9, [%[a], #28]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #28]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	r7, [%[m], #32]\n\t"
-        "ldr	r9, [%[a], #32]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #32]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	r7, [%[m], #36]\n\t"
-        "ldr	r9, [%[a], #36]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #36]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	r7, [%[m], #40]\n\t"
-        "ldr	r9, [%[a], #40]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #40]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	r7, [%[m], #44]\n\t"
-        "ldr	r9, [%[a], #44]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #44]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	r7, [%[m], #48]\n\t"
-        "ldr	r9, [%[a], #48]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #48]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	r7, [%[m], #52]\n\t"
-        "ldr	r9, [%[a], #52]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #52]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	r7, [%[m], #56]\n\t"
-        "ldr	r9, [%[a], #56]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #56]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	r7, [%[m], #60]\n\t"
-        "ldr	r9, [%[a], #60]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #60]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr	r7, [%[m], #64]\n\t"
-        "ldr	r9, [%[a], #64]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #64]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr	r7, [%[m], #68]\n\t"
-        "ldr	r9, [%[a], #68]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #68]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr	r7, [%[m], #72]\n\t"
-        "ldr	r9, [%[a], #72]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #72]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr	r7, [%[m], #76]\n\t"
-        "ldr	r9, [%[a], #76]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #76]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr	r7, [%[m], #80]\n\t"
-        "ldr	r9, [%[a], #80]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #80]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr	r7, [%[m], #84]\n\t"
-        "ldr	r9, [%[a], #84]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #84]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr	r7, [%[m], #88]\n\t"
-        "ldr	r9, [%[a], #88]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #88]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr	r7, [%[m], #92]\n\t"
-        "ldr	r9, [%[a], #92]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #92]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr	r7, [%[m], #96]\n\t"
-        "ldr	r9, [%[a], #96]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #96]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr	r7, [%[m], #100]\n\t"
-        "ldr	r9, [%[a], #100]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #100]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr	r7, [%[m], #104]\n\t"
-        "ldr	r9, [%[a], #104]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #104]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr	r7, [%[m], #108]\n\t"
-        "ldr	r9, [%[a], #108]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #108]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr	r7, [%[m], #112]\n\t"
-        "ldr	r9, [%[a], #112]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #112]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr	r7, [%[m], #116]\n\t"
-        "ldr	r9, [%[a], #116]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #116]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr	r7, [%[m], #120]\n\t"
-        "ldr	r9, [%[a], #120]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #120]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr	r7, [%[m], #124]\n\t"
-        "ldr	r9, [%[a], #124]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #124]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "ldr	r7, [%[m], #128]\n\t"
-        "ldr	r9, [%[a], #128]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #128]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "ldr	r7, [%[m], #132]\n\t"
-        "ldr	r9, [%[a], #132]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #132]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "ldr	r7, [%[m], #136]\n\t"
-        "ldr	r9, [%[a], #136]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #136]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "ldr	r7, [%[m], #140]\n\t"
-        "ldr	r9, [%[a], #140]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #140]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "ldr	r7, [%[m], #144]\n\t"
-        "ldr	r9, [%[a], #144]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #144]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "ldr	r7, [%[m], #148]\n\t"
-        "ldr	r9, [%[a], #148]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #148]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "ldr	r7, [%[m], #152]\n\t"
-        "ldr	r9, [%[a], #152]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #152]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "ldr	r7, [%[m], #156]\n\t"
-        "ldr	r9, [%[a], #156]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #156]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "ldr	r7, [%[m], #160]\n\t"
-        "ldr	r9, [%[a], #160]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #160]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "ldr	r7, [%[m], #164]\n\t"
-        "ldr	r9, [%[a], #164]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #164]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "ldr	r7, [%[m], #168]\n\t"
-        "ldr	r9, [%[a], #168]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #168]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "ldr	r7, [%[m], #172]\n\t"
-        "ldr	r9, [%[a], #172]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #172]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "ldr	r7, [%[m], #176]\n\t"
-        "ldr	r9, [%[a], #176]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #176]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "ldr	r7, [%[m], #180]\n\t"
-        "ldr	r9, [%[a], #180]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #180]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "ldr	r7, [%[m], #184]\n\t"
-        "ldr	r9, [%[a], #184]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #184]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "ldr	r7, [%[m], #188]\n\t"
-        "ldr   r9, [%[a], #188]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r7, r7, %[ca]\n\t"
-        "mov	%[ca], #0\n\t"
-        "adc	%[ca], %[ca], %[ca]\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #188]\n\t"
-        "ldr	r9, [%[a], #192]\n\t"
-        "adcs	r9, r9, r7\n\t"
-        "str	r9, [%[a], #192]\n\t"
-        "adc	%[ca], %[ca], #0\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], #4\n\t"
-        "add	r12, r12, #4\n\t"
-        "cmp	r12, #192\n\t"
-        "blt	1b\n\t"
-        "str	r10, [%[a], #0]\n\t"
-        "str	r14, [%[a], #4]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_48(r, a, b);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_48(r, a);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r5, r3, %[b], r8\n\t"
-        "mov	r4, #0\n\t"
-        "str	r5, [%[r]]\n\t"
-        "mov	r5, #0\n\t"
-        "mov	r9, #4\n\t"
-        "1:\n\t"
-        "ldr	r8, [%[a], r9]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], r9]\n\t"
-        "mov	r3, r4\n\t"
-        "mov	r4, r5\n\t"
-        "mov	r5, #0\n\t"
-        "add	r9, r9, #4\n\t"
-        "cmp	r9, #192\n\t"
-        "blt	1b\n\t"
-        "str	r3, [%[r], #192]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r3, r4, %[b], r8\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "# A[2] * B\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "# A[4] * B\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "# A[5] * B\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "# A[6] * B\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #24]\n\t"
-        "# A[7] * B\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #28]\n\t"
-        "# A[8] * B\n\t"
-        "ldr	r8, [%[a], #32]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "# A[9] * B\n\t"
-        "ldr	r8, [%[a], #36]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "# A[10] * B\n\t"
-        "ldr	r8, [%[a], #40]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "# A[11] * B\n\t"
-        "ldr	r8, [%[a], #44]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "# A[12] * B\n\t"
-        "ldr	r8, [%[a], #48]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "# A[13] * B\n\t"
-        "ldr	r8, [%[a], #52]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "# A[14] * B\n\t"
-        "ldr	r8, [%[a], #56]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "# A[15] * B\n\t"
-        "ldr	r8, [%[a], #60]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        "# A[16] * B\n\t"
-        "ldr	r8, [%[a], #64]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "# A[17] * B\n\t"
-        "ldr	r8, [%[a], #68]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "# A[18] * B\n\t"
-        "ldr	r8, [%[a], #72]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #72]\n\t"
-        "# A[19] * B\n\t"
-        "ldr	r8, [%[a], #76]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #76]\n\t"
-        "# A[20] * B\n\t"
-        "ldr	r8, [%[a], #80]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #80]\n\t"
-        "# A[21] * B\n\t"
-        "ldr	r8, [%[a], #84]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #84]\n\t"
-        "# A[22] * B\n\t"
-        "ldr	r8, [%[a], #88]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "# A[23] * B\n\t"
-        "ldr	r8, [%[a], #92]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #92]\n\t"
-        "# A[24] * B\n\t"
-        "ldr	r8, [%[a], #96]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #96]\n\t"
-        "# A[25] * B\n\t"
-        "ldr	r8, [%[a], #100]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #100]\n\t"
-        "# A[26] * B\n\t"
-        "ldr	r8, [%[a], #104]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #104]\n\t"
-        "# A[27] * B\n\t"
-        "ldr	r8, [%[a], #108]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #108]\n\t"
-        "# A[28] * B\n\t"
-        "ldr	r8, [%[a], #112]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "# A[29] * B\n\t"
-        "ldr	r8, [%[a], #116]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "# A[30] * B\n\t"
-        "ldr	r8, [%[a], #120]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #120]\n\t"
-        "# A[31] * B\n\t"
-        "ldr	r8, [%[a], #124]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #124]\n\t"
-        "# A[32] * B\n\t"
-        "ldr	r8, [%[a], #128]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #128]\n\t"
-        "# A[33] * B\n\t"
-        "ldr	r8, [%[a], #132]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #132]\n\t"
-        "# A[34] * B\n\t"
-        "ldr	r8, [%[a], #136]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "# A[35] * B\n\t"
-        "ldr	r8, [%[a], #140]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #140]\n\t"
-        "# A[36] * B\n\t"
-        "ldr	r8, [%[a], #144]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #144]\n\t"
-        "# A[37] * B\n\t"
-        "ldr	r8, [%[a], #148]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #148]\n\t"
-        "# A[38] * B\n\t"
-        "ldr	r8, [%[a], #152]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #152]\n\t"
-        "# A[39] * B\n\t"
-        "ldr	r8, [%[a], #156]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #156]\n\t"
-        "# A[40] * B\n\t"
-        "ldr	r8, [%[a], #160]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "# A[41] * B\n\t"
-        "ldr	r8, [%[a], #164]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "# A[42] * B\n\t"
-        "ldr	r8, [%[a], #168]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #168]\n\t"
-        "# A[43] * B\n\t"
-        "ldr	r8, [%[a], #172]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #172]\n\t"
-        "# A[44] * B\n\t"
-        "ldr	r8, [%[a], #176]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #176]\n\t"
-        "# A[45] * B\n\t"
-        "ldr	r8, [%[a], #180]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #180]\n\t"
-        "# A[46] * B\n\t"
-        "ldr	r8, [%[a], #184]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "# A[47] * B\n\t"
-        "ldr	r8, [%[a], #188]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r5, [%[r], #188]\n\t"
-        "str	r3, [%[r], #192]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
-static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r = 0;
-
-    __asm__ __volatile__ (
-        "lsr	r5, %[div], #1\n\t"
-        "add	r5, r5, #1\n\t"
-        "mov	r6, %[d0]\n\t"
-        "mov	r7, %[d1]\n\t"
-        "# Do top 32\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "# Next 30 bits\n\t"
-        "mov	r4, #29\n\t"
-        "1:\n\t"
-        "movs	r6, r6, lsl #1\n\t"
-        "adc	r7, r7, r7\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "subs	r4, r4, #1\n\t"
-        "bpl	1b\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "add	%[r], %[r], #1\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "subs	r8, %[div], r4\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        : [r] "+r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "r4", "r5", "r6", "r7", "r8"
-    );
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int32_t sp_3072_cmp_48(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "mov	r6, #188\n\t"
-        "1:\n\t"
-        "ldr	r4, [%[a], r6]\n\t"
-        "ldr	r5, [%[b], r6]\n\t"
-        "and	r4, r4, r3\n\t"
-        "and	r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "sub	r6, r6, #4\n\t"
-        "bcc	1b\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "ldr		r4, [%[a], #188]\n\t"
-        "ldr		r5, [%[b], #188]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #184]\n\t"
-        "ldr		r5, [%[b], #184]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #180]\n\t"
-        "ldr		r5, [%[b], #180]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #176]\n\t"
-        "ldr		r5, [%[b], #176]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #172]\n\t"
-        "ldr		r5, [%[b], #172]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #168]\n\t"
-        "ldr		r5, [%[b], #168]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #164]\n\t"
-        "ldr		r5, [%[b], #164]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #160]\n\t"
-        "ldr		r5, [%[b], #160]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #156]\n\t"
-        "ldr		r5, [%[b], #156]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #152]\n\t"
-        "ldr		r5, [%[b], #152]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #148]\n\t"
-        "ldr		r5, [%[b], #148]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #144]\n\t"
-        "ldr		r5, [%[b], #144]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #140]\n\t"
-        "ldr		r5, [%[b], #140]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #136]\n\t"
-        "ldr		r5, [%[b], #136]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #132]\n\t"
-        "ldr		r5, [%[b], #132]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #128]\n\t"
-        "ldr		r5, [%[b], #128]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #124]\n\t"
-        "ldr		r5, [%[b], #124]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #120]\n\t"
-        "ldr		r5, [%[b], #120]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #116]\n\t"
-        "ldr		r5, [%[b], #116]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #112]\n\t"
-        "ldr		r5, [%[b], #112]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #108]\n\t"
-        "ldr		r5, [%[b], #108]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #104]\n\t"
-        "ldr		r5, [%[b], #104]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #100]\n\t"
-        "ldr		r5, [%[b], #100]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #96]\n\t"
-        "ldr		r5, [%[b], #96]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #92]\n\t"
-        "ldr		r5, [%[b], #92]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #88]\n\t"
-        "ldr		r5, [%[b], #88]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #84]\n\t"
-        "ldr		r5, [%[b], #84]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #80]\n\t"
-        "ldr		r5, [%[b], #80]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #76]\n\t"
-        "ldr		r5, [%[b], #76]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #72]\n\t"
-        "ldr		r5, [%[b], #72]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #68]\n\t"
-        "ldr		r5, [%[b], #68]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #64]\n\t"
-        "ldr		r5, [%[b], #64]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #60]\n\t"
-        "ldr		r5, [%[b], #60]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #56]\n\t"
-        "ldr		r5, [%[b], #56]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #52]\n\t"
-        "ldr		r5, [%[b], #52]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #48]\n\t"
-        "ldr		r5, [%[b], #48]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #44]\n\t"
-        "ldr		r5, [%[b], #44]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #40]\n\t"
-        "ldr		r5, [%[b], #40]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #36]\n\t"
-        "ldr		r5, [%[b], #36]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #32]\n\t"
-        "ldr		r5, [%[b], #32]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #28]\n\t"
-        "ldr		r5, [%[b], #28]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #24]\n\t"
-        "ldr		r5, [%[b], #24]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #20]\n\t"
-        "ldr		r5, [%[b], #20]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #16]\n\t"
-        "ldr		r5, [%[b], #16]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #12]\n\t"
-        "ldr		r5, [%[b], #12]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #8]\n\t"
-        "ldr		r5, [%[b], #8]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #4]\n\t"
-        "ldr		r5, [%[b], #4]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #0]\n\t"
-        "ldr		r5, [%[b], #0]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[96], t2[49];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[47];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
-    for (i=47; i>=0; i--) {
-        r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
-
-        sp_3072_mul_d_48(t2, d, r1);
-        t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
-        t1[48 + i] -= t2[48];
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_48(t1, d) >= 0;
-    sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_48(a, m, NULL, r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][96];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 28;
-        n <<= 4;
-        c = 28;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 28;
-                n <<= 4;
-                c = 28;
-            }
-            else if (c < 4) {
-                y = n >> 28;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 28) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-
-            sp_3072_mont_mul_48(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][96];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_48(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_48(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_48(t[20], t[10], m, mp);
-        sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_48(t[22], t[11], m, mp);
-        sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_48(t[24], t[12], m, mp);
-        sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_48(t[26], t[13], m, mp);
-        sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_48(t[28], t[14], m, mp);
-        sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_48(t[30], t[15], m, mp);
-        sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 27;
-        n <<= 5;
-        c = 27;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 27;
-                n <<= 5;
-                c = 27;
-            }
-            else if (c < 5) {
-                y = n >> 27;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 27) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-
-            sp_3072_mont_mul_48(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x1;
-        sp_3072_mont_sqr_48(r, r, m, mp);
-        sp_3072_mont_mul_48(r, r, t[y], m, mp);
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_96(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 96);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_96(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_96(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r9, #0\n\t"
-        "mov	r8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], r9, %[c]\n\t"
-        "ldr	r4, [%[a], r8]\n\t"
-        "ldr	r5, [%[b], r8]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        "str	r4, [%[r], r8]\n\t"
-        "add	r8, r8, #4\n\t"
-        "cmp	r8, #384\n\t"
-        "blt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "mov	r9, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r5, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "subs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r6, [%[r], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r5, [%[b], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r5, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r6, [%[r], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r5, [%[b], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "ldr	r4, [%[a], #32]\n\t"
-        "ldr	r6, [%[a], #36]\n\t"
-        "ldr	r5, [%[b], #32]\n\t"
-        "ldr	r7, [%[b], #36]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "str	r6, [%[r], #36]\n\t"
-        "ldr	r4, [%[a], #40]\n\t"
-        "ldr	r6, [%[a], #44]\n\t"
-        "ldr	r5, [%[b], #40]\n\t"
-        "ldr	r7, [%[b], #44]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "str	r6, [%[r], #44]\n\t"
-        "ldr	r4, [%[a], #48]\n\t"
-        "ldr	r6, [%[a], #52]\n\t"
-        "ldr	r5, [%[b], #48]\n\t"
-        "ldr	r7, [%[b], #52]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #48]\n\t"
-        "str	r6, [%[r], #52]\n\t"
-        "ldr	r4, [%[a], #56]\n\t"
-        "ldr	r6, [%[a], #60]\n\t"
-        "ldr	r5, [%[b], #56]\n\t"
-        "ldr	r7, [%[b], #60]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r6, [%[r], #60]\n\t"
-        "ldr	r4, [%[a], #64]\n\t"
-        "ldr	r6, [%[a], #68]\n\t"
-        "ldr	r5, [%[b], #64]\n\t"
-        "ldr	r7, [%[b], #68]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "str	r6, [%[r], #68]\n\t"
-        "ldr	r4, [%[a], #72]\n\t"
-        "ldr	r6, [%[a], #76]\n\t"
-        "ldr	r5, [%[b], #72]\n\t"
-        "ldr	r7, [%[b], #76]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #72]\n\t"
-        "str	r6, [%[r], #76]\n\t"
-        "ldr	r4, [%[a], #80]\n\t"
-        "ldr	r6, [%[a], #84]\n\t"
-        "ldr	r5, [%[b], #80]\n\t"
-        "ldr	r7, [%[b], #84]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #80]\n\t"
-        "str	r6, [%[r], #84]\n\t"
-        "ldr	r4, [%[a], #88]\n\t"
-        "ldr	r6, [%[a], #92]\n\t"
-        "ldr	r5, [%[b], #88]\n\t"
-        "ldr	r7, [%[b], #92]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "str	r6, [%[r], #92]\n\t"
-        "ldr	r4, [%[a], #96]\n\t"
-        "ldr	r6, [%[a], #100]\n\t"
-        "ldr	r5, [%[b], #96]\n\t"
-        "ldr	r7, [%[b], #100]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #96]\n\t"
-        "str	r6, [%[r], #100]\n\t"
-        "ldr	r4, [%[a], #104]\n\t"
-        "ldr	r6, [%[a], #108]\n\t"
-        "ldr	r5, [%[b], #104]\n\t"
-        "ldr	r7, [%[b], #108]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #104]\n\t"
-        "str	r6, [%[r], #108]\n\t"
-        "ldr	r4, [%[a], #112]\n\t"
-        "ldr	r6, [%[a], #116]\n\t"
-        "ldr	r5, [%[b], #112]\n\t"
-        "ldr	r7, [%[b], #116]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "str	r6, [%[r], #116]\n\t"
-        "ldr	r4, [%[a], #120]\n\t"
-        "ldr	r6, [%[a], #124]\n\t"
-        "ldr	r5, [%[b], #120]\n\t"
-        "ldr	r7, [%[b], #124]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #120]\n\t"
-        "str	r6, [%[r], #124]\n\t"
-        "ldr	r4, [%[a], #128]\n\t"
-        "ldr	r6, [%[a], #132]\n\t"
-        "ldr	r5, [%[b], #128]\n\t"
-        "ldr	r7, [%[b], #132]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #128]\n\t"
-        "str	r6, [%[r], #132]\n\t"
-        "ldr	r4, [%[a], #136]\n\t"
-        "ldr	r6, [%[a], #140]\n\t"
-        "ldr	r5, [%[b], #136]\n\t"
-        "ldr	r7, [%[b], #140]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "str	r6, [%[r], #140]\n\t"
-        "ldr	r4, [%[a], #144]\n\t"
-        "ldr	r6, [%[a], #148]\n\t"
-        "ldr	r5, [%[b], #144]\n\t"
-        "ldr	r7, [%[b], #148]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #144]\n\t"
-        "str	r6, [%[r], #148]\n\t"
-        "ldr	r4, [%[a], #152]\n\t"
-        "ldr	r6, [%[a], #156]\n\t"
-        "ldr	r5, [%[b], #152]\n\t"
-        "ldr	r7, [%[b], #156]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #152]\n\t"
-        "str	r6, [%[r], #156]\n\t"
-        "ldr	r4, [%[a], #160]\n\t"
-        "ldr	r6, [%[a], #164]\n\t"
-        "ldr	r5, [%[b], #160]\n\t"
-        "ldr	r7, [%[b], #164]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "str	r6, [%[r], #164]\n\t"
-        "ldr	r4, [%[a], #168]\n\t"
-        "ldr	r6, [%[a], #172]\n\t"
-        "ldr	r5, [%[b], #168]\n\t"
-        "ldr	r7, [%[b], #172]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #168]\n\t"
-        "str	r6, [%[r], #172]\n\t"
-        "ldr	r4, [%[a], #176]\n\t"
-        "ldr	r6, [%[a], #180]\n\t"
-        "ldr	r5, [%[b], #176]\n\t"
-        "ldr	r7, [%[b], #180]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #176]\n\t"
-        "str	r6, [%[r], #180]\n\t"
-        "ldr	r4, [%[a], #184]\n\t"
-        "ldr	r6, [%[a], #188]\n\t"
-        "ldr	r5, [%[b], #184]\n\t"
-        "ldr	r7, [%[b], #188]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "str	r6, [%[r], #188]\n\t"
-        "ldr	r4, [%[a], #192]\n\t"
-        "ldr	r6, [%[a], #196]\n\t"
-        "ldr	r5, [%[b], #192]\n\t"
-        "ldr	r7, [%[b], #196]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #192]\n\t"
-        "str	r6, [%[r], #196]\n\t"
-        "ldr	r4, [%[a], #200]\n\t"
-        "ldr	r6, [%[a], #204]\n\t"
-        "ldr	r5, [%[b], #200]\n\t"
-        "ldr	r7, [%[b], #204]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #200]\n\t"
-        "str	r6, [%[r], #204]\n\t"
-        "ldr	r4, [%[a], #208]\n\t"
-        "ldr	r6, [%[a], #212]\n\t"
-        "ldr	r5, [%[b], #208]\n\t"
-        "ldr	r7, [%[b], #212]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "str	r6, [%[r], #212]\n\t"
-        "ldr	r4, [%[a], #216]\n\t"
-        "ldr	r6, [%[a], #220]\n\t"
-        "ldr	r5, [%[b], #216]\n\t"
-        "ldr	r7, [%[b], #220]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #216]\n\t"
-        "str	r6, [%[r], #220]\n\t"
-        "ldr	r4, [%[a], #224]\n\t"
-        "ldr	r6, [%[a], #228]\n\t"
-        "ldr	r5, [%[b], #224]\n\t"
-        "ldr	r7, [%[b], #228]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #224]\n\t"
-        "str	r6, [%[r], #228]\n\t"
-        "ldr	r4, [%[a], #232]\n\t"
-        "ldr	r6, [%[a], #236]\n\t"
-        "ldr	r5, [%[b], #232]\n\t"
-        "ldr	r7, [%[b], #236]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #232]\n\t"
-        "str	r6, [%[r], #236]\n\t"
-        "ldr	r4, [%[a], #240]\n\t"
-        "ldr	r6, [%[a], #244]\n\t"
-        "ldr	r5, [%[b], #240]\n\t"
-        "ldr	r7, [%[b], #244]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #240]\n\t"
-        "str	r6, [%[r], #244]\n\t"
-        "ldr	r4, [%[a], #248]\n\t"
-        "ldr	r6, [%[a], #252]\n\t"
-        "ldr	r5, [%[b], #248]\n\t"
-        "ldr	r7, [%[b], #252]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #248]\n\t"
-        "str	r6, [%[r], #252]\n\t"
-        "ldr	r4, [%[a], #256]\n\t"
-        "ldr	r6, [%[a], #260]\n\t"
-        "ldr	r5, [%[b], #256]\n\t"
-        "ldr	r7, [%[b], #260]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #256]\n\t"
-        "str	r6, [%[r], #260]\n\t"
-        "ldr	r4, [%[a], #264]\n\t"
-        "ldr	r6, [%[a], #268]\n\t"
-        "ldr	r5, [%[b], #264]\n\t"
-        "ldr	r7, [%[b], #268]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #264]\n\t"
-        "str	r6, [%[r], #268]\n\t"
-        "ldr	r4, [%[a], #272]\n\t"
-        "ldr	r6, [%[a], #276]\n\t"
-        "ldr	r5, [%[b], #272]\n\t"
-        "ldr	r7, [%[b], #276]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #272]\n\t"
-        "str	r6, [%[r], #276]\n\t"
-        "ldr	r4, [%[a], #280]\n\t"
-        "ldr	r6, [%[a], #284]\n\t"
-        "ldr	r5, [%[b], #280]\n\t"
-        "ldr	r7, [%[b], #284]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #280]\n\t"
-        "str	r6, [%[r], #284]\n\t"
-        "ldr	r4, [%[a], #288]\n\t"
-        "ldr	r6, [%[a], #292]\n\t"
-        "ldr	r5, [%[b], #288]\n\t"
-        "ldr	r7, [%[b], #292]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #288]\n\t"
-        "str	r6, [%[r], #292]\n\t"
-        "ldr	r4, [%[a], #296]\n\t"
-        "ldr	r6, [%[a], #300]\n\t"
-        "ldr	r5, [%[b], #296]\n\t"
-        "ldr	r7, [%[b], #300]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #296]\n\t"
-        "str	r6, [%[r], #300]\n\t"
-        "ldr	r4, [%[a], #304]\n\t"
-        "ldr	r6, [%[a], #308]\n\t"
-        "ldr	r5, [%[b], #304]\n\t"
-        "ldr	r7, [%[b], #308]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #304]\n\t"
-        "str	r6, [%[r], #308]\n\t"
-        "ldr	r4, [%[a], #312]\n\t"
-        "ldr	r6, [%[a], #316]\n\t"
-        "ldr	r5, [%[b], #312]\n\t"
-        "ldr	r7, [%[b], #316]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #312]\n\t"
-        "str	r6, [%[r], #316]\n\t"
-        "ldr	r4, [%[a], #320]\n\t"
-        "ldr	r6, [%[a], #324]\n\t"
-        "ldr	r5, [%[b], #320]\n\t"
-        "ldr	r7, [%[b], #324]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #320]\n\t"
-        "str	r6, [%[r], #324]\n\t"
-        "ldr	r4, [%[a], #328]\n\t"
-        "ldr	r6, [%[a], #332]\n\t"
-        "ldr	r5, [%[b], #328]\n\t"
-        "ldr	r7, [%[b], #332]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #328]\n\t"
-        "str	r6, [%[r], #332]\n\t"
-        "ldr	r4, [%[a], #336]\n\t"
-        "ldr	r6, [%[a], #340]\n\t"
-        "ldr	r5, [%[b], #336]\n\t"
-        "ldr	r7, [%[b], #340]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #336]\n\t"
-        "str	r6, [%[r], #340]\n\t"
-        "ldr	r4, [%[a], #344]\n\t"
-        "ldr	r6, [%[a], #348]\n\t"
-        "ldr	r5, [%[b], #344]\n\t"
-        "ldr	r7, [%[b], #348]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #344]\n\t"
-        "str	r6, [%[r], #348]\n\t"
-        "ldr	r4, [%[a], #352]\n\t"
-        "ldr	r6, [%[a], #356]\n\t"
-        "ldr	r5, [%[b], #352]\n\t"
-        "ldr	r7, [%[b], #356]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #352]\n\t"
-        "str	r6, [%[r], #356]\n\t"
-        "ldr	r4, [%[a], #360]\n\t"
-        "ldr	r6, [%[a], #364]\n\t"
-        "ldr	r5, [%[b], #360]\n\t"
-        "ldr	r7, [%[b], #364]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #360]\n\t"
-        "str	r6, [%[r], #364]\n\t"
-        "ldr	r4, [%[a], #368]\n\t"
-        "ldr	r6, [%[a], #372]\n\t"
-        "ldr	r5, [%[b], #368]\n\t"
-        "ldr	r7, [%[b], #372]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #368]\n\t"
-        "str	r6, [%[r], #372]\n\t"
-        "ldr	r4, [%[a], #376]\n\t"
-        "ldr	r6, [%[a], #380]\n\t"
-        "ldr	r5, [%[b], #376]\n\t"
-        "ldr	r7, [%[b], #380]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #376]\n\t"
-        "str	r6, [%[r], #380]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "ldr	r14, [%[a], #4]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	r8, %[mp], r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	r7, [%[m], #0]\n\t"
-        "ldr	r9, [%[a], #0]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r10, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	r7, [%[m], #4]\n\t"
-        "ldr	r9, [%[a], #4]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r14, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r10, r10, r5\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	r7, [%[m], #8]\n\t"
-        "ldr	r14, [%[a], #8]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r14, r14, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r14, r14, r4\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	r7, [%[m], #12]\n\t"
-        "ldr	r9, [%[a], #12]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #12]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	r7, [%[m], #16]\n\t"
-        "ldr	r9, [%[a], #16]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #16]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	r7, [%[m], #20]\n\t"
-        "ldr	r9, [%[a], #20]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #20]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	r7, [%[m], #24]\n\t"
-        "ldr	r9, [%[a], #24]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #24]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	r7, [%[m], #28]\n\t"
-        "ldr	r9, [%[a], #28]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #28]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	r7, [%[m], #32]\n\t"
-        "ldr	r9, [%[a], #32]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #32]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	r7, [%[m], #36]\n\t"
-        "ldr	r9, [%[a], #36]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #36]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	r7, [%[m], #40]\n\t"
-        "ldr	r9, [%[a], #40]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #40]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	r7, [%[m], #44]\n\t"
-        "ldr	r9, [%[a], #44]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #44]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	r7, [%[m], #48]\n\t"
-        "ldr	r9, [%[a], #48]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #48]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	r7, [%[m], #52]\n\t"
-        "ldr	r9, [%[a], #52]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #52]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	r7, [%[m], #56]\n\t"
-        "ldr	r9, [%[a], #56]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #56]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	r7, [%[m], #60]\n\t"
-        "ldr	r9, [%[a], #60]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #60]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr	r7, [%[m], #64]\n\t"
-        "ldr	r9, [%[a], #64]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #64]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr	r7, [%[m], #68]\n\t"
-        "ldr	r9, [%[a], #68]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #68]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr	r7, [%[m], #72]\n\t"
-        "ldr	r9, [%[a], #72]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #72]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr	r7, [%[m], #76]\n\t"
-        "ldr	r9, [%[a], #76]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #76]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr	r7, [%[m], #80]\n\t"
-        "ldr	r9, [%[a], #80]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #80]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr	r7, [%[m], #84]\n\t"
-        "ldr	r9, [%[a], #84]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #84]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr	r7, [%[m], #88]\n\t"
-        "ldr	r9, [%[a], #88]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #88]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr	r7, [%[m], #92]\n\t"
-        "ldr	r9, [%[a], #92]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #92]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr	r7, [%[m], #96]\n\t"
-        "ldr	r9, [%[a], #96]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #96]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr	r7, [%[m], #100]\n\t"
-        "ldr	r9, [%[a], #100]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #100]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr	r7, [%[m], #104]\n\t"
-        "ldr	r9, [%[a], #104]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #104]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr	r7, [%[m], #108]\n\t"
-        "ldr	r9, [%[a], #108]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #108]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr	r7, [%[m], #112]\n\t"
-        "ldr	r9, [%[a], #112]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #112]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr	r7, [%[m], #116]\n\t"
-        "ldr	r9, [%[a], #116]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #116]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr	r7, [%[m], #120]\n\t"
-        "ldr	r9, [%[a], #120]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #120]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr	r7, [%[m], #124]\n\t"
-        "ldr	r9, [%[a], #124]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #124]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "ldr	r7, [%[m], #128]\n\t"
-        "ldr	r9, [%[a], #128]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #128]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "ldr	r7, [%[m], #132]\n\t"
-        "ldr	r9, [%[a], #132]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #132]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "ldr	r7, [%[m], #136]\n\t"
-        "ldr	r9, [%[a], #136]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #136]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "ldr	r7, [%[m], #140]\n\t"
-        "ldr	r9, [%[a], #140]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #140]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "ldr	r7, [%[m], #144]\n\t"
-        "ldr	r9, [%[a], #144]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #144]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "ldr	r7, [%[m], #148]\n\t"
-        "ldr	r9, [%[a], #148]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #148]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "ldr	r7, [%[m], #152]\n\t"
-        "ldr	r9, [%[a], #152]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #152]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "ldr	r7, [%[m], #156]\n\t"
-        "ldr	r9, [%[a], #156]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #156]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "ldr	r7, [%[m], #160]\n\t"
-        "ldr	r9, [%[a], #160]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #160]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "ldr	r7, [%[m], #164]\n\t"
-        "ldr	r9, [%[a], #164]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #164]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "ldr	r7, [%[m], #168]\n\t"
-        "ldr	r9, [%[a], #168]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #168]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "ldr	r7, [%[m], #172]\n\t"
-        "ldr	r9, [%[a], #172]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #172]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "ldr	r7, [%[m], #176]\n\t"
-        "ldr	r9, [%[a], #176]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #176]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "ldr	r7, [%[m], #180]\n\t"
-        "ldr	r9, [%[a], #180]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #180]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "ldr	r7, [%[m], #184]\n\t"
-        "ldr	r9, [%[a], #184]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #184]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "ldr	r7, [%[m], #188]\n\t"
-        "ldr	r9, [%[a], #188]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #188]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+48] += m[48] * mu\n\t"
-        "ldr	r7, [%[m], #192]\n\t"
-        "ldr	r9, [%[a], #192]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #192]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+49] += m[49] * mu\n\t"
-        "ldr	r7, [%[m], #196]\n\t"
-        "ldr	r9, [%[a], #196]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #196]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+50] += m[50] * mu\n\t"
-        "ldr	r7, [%[m], #200]\n\t"
-        "ldr	r9, [%[a], #200]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #200]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+51] += m[51] * mu\n\t"
-        "ldr	r7, [%[m], #204]\n\t"
-        "ldr	r9, [%[a], #204]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #204]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+52] += m[52] * mu\n\t"
-        "ldr	r7, [%[m], #208]\n\t"
-        "ldr	r9, [%[a], #208]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #208]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+53] += m[53] * mu\n\t"
-        "ldr	r7, [%[m], #212]\n\t"
-        "ldr	r9, [%[a], #212]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #212]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+54] += m[54] * mu\n\t"
-        "ldr	r7, [%[m], #216]\n\t"
-        "ldr	r9, [%[a], #216]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #216]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+55] += m[55] * mu\n\t"
-        "ldr	r7, [%[m], #220]\n\t"
-        "ldr	r9, [%[a], #220]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #220]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+56] += m[56] * mu\n\t"
-        "ldr	r7, [%[m], #224]\n\t"
-        "ldr	r9, [%[a], #224]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #224]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+57] += m[57] * mu\n\t"
-        "ldr	r7, [%[m], #228]\n\t"
-        "ldr	r9, [%[a], #228]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #228]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+58] += m[58] * mu\n\t"
-        "ldr	r7, [%[m], #232]\n\t"
-        "ldr	r9, [%[a], #232]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #232]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+59] += m[59] * mu\n\t"
-        "ldr	r7, [%[m], #236]\n\t"
-        "ldr	r9, [%[a], #236]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #236]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+60] += m[60] * mu\n\t"
-        "ldr	r7, [%[m], #240]\n\t"
-        "ldr	r9, [%[a], #240]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #240]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+61] += m[61] * mu\n\t"
-        "ldr	r7, [%[m], #244]\n\t"
-        "ldr	r9, [%[a], #244]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #244]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+62] += m[62] * mu\n\t"
-        "ldr	r7, [%[m], #248]\n\t"
-        "ldr	r9, [%[a], #248]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #248]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+63] += m[63] * mu\n\t"
-        "ldr	r7, [%[m], #252]\n\t"
-        "ldr	r9, [%[a], #252]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #252]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+64] += m[64] * mu\n\t"
-        "ldr	r7, [%[m], #256]\n\t"
-        "ldr	r9, [%[a], #256]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #256]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+65] += m[65] * mu\n\t"
-        "ldr	r7, [%[m], #260]\n\t"
-        "ldr	r9, [%[a], #260]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #260]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+66] += m[66] * mu\n\t"
-        "ldr	r7, [%[m], #264]\n\t"
-        "ldr	r9, [%[a], #264]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #264]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+67] += m[67] * mu\n\t"
-        "ldr	r7, [%[m], #268]\n\t"
-        "ldr	r9, [%[a], #268]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #268]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+68] += m[68] * mu\n\t"
-        "ldr	r7, [%[m], #272]\n\t"
-        "ldr	r9, [%[a], #272]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #272]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+69] += m[69] * mu\n\t"
-        "ldr	r7, [%[m], #276]\n\t"
-        "ldr	r9, [%[a], #276]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #276]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+70] += m[70] * mu\n\t"
-        "ldr	r7, [%[m], #280]\n\t"
-        "ldr	r9, [%[a], #280]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #280]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+71] += m[71] * mu\n\t"
-        "ldr	r7, [%[m], #284]\n\t"
-        "ldr	r9, [%[a], #284]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #284]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+72] += m[72] * mu\n\t"
-        "ldr	r7, [%[m], #288]\n\t"
-        "ldr	r9, [%[a], #288]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #288]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+73] += m[73] * mu\n\t"
-        "ldr	r7, [%[m], #292]\n\t"
-        "ldr	r9, [%[a], #292]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #292]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+74] += m[74] * mu\n\t"
-        "ldr	r7, [%[m], #296]\n\t"
-        "ldr	r9, [%[a], #296]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #296]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+75] += m[75] * mu\n\t"
-        "ldr	r7, [%[m], #300]\n\t"
-        "ldr	r9, [%[a], #300]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #300]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+76] += m[76] * mu\n\t"
-        "ldr	r7, [%[m], #304]\n\t"
-        "ldr	r9, [%[a], #304]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #304]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+77] += m[77] * mu\n\t"
-        "ldr	r7, [%[m], #308]\n\t"
-        "ldr	r9, [%[a], #308]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #308]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+78] += m[78] * mu\n\t"
-        "ldr	r7, [%[m], #312]\n\t"
-        "ldr	r9, [%[a], #312]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #312]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+79] += m[79] * mu\n\t"
-        "ldr	r7, [%[m], #316]\n\t"
-        "ldr	r9, [%[a], #316]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #316]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+80] += m[80] * mu\n\t"
-        "ldr	r7, [%[m], #320]\n\t"
-        "ldr	r9, [%[a], #320]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #320]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+81] += m[81] * mu\n\t"
-        "ldr	r7, [%[m], #324]\n\t"
-        "ldr	r9, [%[a], #324]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #324]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+82] += m[82] * mu\n\t"
-        "ldr	r7, [%[m], #328]\n\t"
-        "ldr	r9, [%[a], #328]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #328]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+83] += m[83] * mu\n\t"
-        "ldr	r7, [%[m], #332]\n\t"
-        "ldr	r9, [%[a], #332]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #332]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+84] += m[84] * mu\n\t"
-        "ldr	r7, [%[m], #336]\n\t"
-        "ldr	r9, [%[a], #336]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #336]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+85] += m[85] * mu\n\t"
-        "ldr	r7, [%[m], #340]\n\t"
-        "ldr	r9, [%[a], #340]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #340]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+86] += m[86] * mu\n\t"
-        "ldr	r7, [%[m], #344]\n\t"
-        "ldr	r9, [%[a], #344]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #344]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+87] += m[87] * mu\n\t"
-        "ldr	r7, [%[m], #348]\n\t"
-        "ldr	r9, [%[a], #348]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #348]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+88] += m[88] * mu\n\t"
-        "ldr	r7, [%[m], #352]\n\t"
-        "ldr	r9, [%[a], #352]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #352]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+89] += m[89] * mu\n\t"
-        "ldr	r7, [%[m], #356]\n\t"
-        "ldr	r9, [%[a], #356]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #356]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+90] += m[90] * mu\n\t"
-        "ldr	r7, [%[m], #360]\n\t"
-        "ldr	r9, [%[a], #360]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #360]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+91] += m[91] * mu\n\t"
-        "ldr	r7, [%[m], #364]\n\t"
-        "ldr	r9, [%[a], #364]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #364]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+92] += m[92] * mu\n\t"
-        "ldr	r7, [%[m], #368]\n\t"
-        "ldr	r9, [%[a], #368]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #368]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+93] += m[93] * mu\n\t"
-        "ldr	r7, [%[m], #372]\n\t"
-        "ldr	r9, [%[a], #372]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #372]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+94] += m[94] * mu\n\t"
-        "ldr	r7, [%[m], #376]\n\t"
-        "ldr	r9, [%[a], #376]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #376]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+95] += m[95] * mu\n\t"
-        "ldr	r7, [%[m], #380]\n\t"
-        "ldr   r9, [%[a], #380]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r7, r7, %[ca]\n\t"
-        "mov	%[ca], #0\n\t"
-        "adc	%[ca], %[ca], %[ca]\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #380]\n\t"
-        "ldr	r9, [%[a], #384]\n\t"
-        "adcs	r9, r9, r7\n\t"
-        "str	r9, [%[a], #384]\n\t"
-        "adc	%[ca], %[ca], #0\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], #4\n\t"
-        "add	r12, r12, #4\n\t"
-        "cmp	r12, #384\n\t"
-        "blt	1b\n\t"
-        "str	r10, [%[a], #0]\n\t"
-        "str	r14, [%[a], #4]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_96(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_96(r, a, b);
-    sp_3072_mont_reduce_96(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_96(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_96(r, a);
-    sp_3072_mont_reduce_96(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r5, r3, %[b], r8\n\t"
-        "mov	r4, #0\n\t"
-        "str	r5, [%[r]]\n\t"
-        "mov	r5, #0\n\t"
-        "mov	r9, #4\n\t"
-        "1:\n\t"
-        "ldr	r8, [%[a], r9]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], r9]\n\t"
-        "mov	r3, r4\n\t"
-        "mov	r4, r5\n\t"
-        "mov	r5, #0\n\t"
-        "add	r9, r9, #4\n\t"
-        "cmp	r9, #384\n\t"
-        "blt	1b\n\t"
-        "str	r3, [%[r], #384]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r3, r4, %[b], r8\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "# A[2] * B\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "# A[4] * B\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "# A[5] * B\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "# A[6] * B\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #24]\n\t"
-        "# A[7] * B\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #28]\n\t"
-        "# A[8] * B\n\t"
-        "ldr	r8, [%[a], #32]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "# A[9] * B\n\t"
-        "ldr	r8, [%[a], #36]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "# A[10] * B\n\t"
-        "ldr	r8, [%[a], #40]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "# A[11] * B\n\t"
-        "ldr	r8, [%[a], #44]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "# A[12] * B\n\t"
-        "ldr	r8, [%[a], #48]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "# A[13] * B\n\t"
-        "ldr	r8, [%[a], #52]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "# A[14] * B\n\t"
-        "ldr	r8, [%[a], #56]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "# A[15] * B\n\t"
-        "ldr	r8, [%[a], #60]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        "# A[16] * B\n\t"
-        "ldr	r8, [%[a], #64]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #64]\n\t"
-        "# A[17] * B\n\t"
-        "ldr	r8, [%[a], #68]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #68]\n\t"
-        "# A[18] * B\n\t"
-        "ldr	r8, [%[a], #72]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #72]\n\t"
-        "# A[19] * B\n\t"
-        "ldr	r8, [%[a], #76]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #76]\n\t"
-        "# A[20] * B\n\t"
-        "ldr	r8, [%[a], #80]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #80]\n\t"
-        "# A[21] * B\n\t"
-        "ldr	r8, [%[a], #84]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #84]\n\t"
-        "# A[22] * B\n\t"
-        "ldr	r8, [%[a], #88]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #88]\n\t"
-        "# A[23] * B\n\t"
-        "ldr	r8, [%[a], #92]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #92]\n\t"
-        "# A[24] * B\n\t"
-        "ldr	r8, [%[a], #96]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #96]\n\t"
-        "# A[25] * B\n\t"
-        "ldr	r8, [%[a], #100]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #100]\n\t"
-        "# A[26] * B\n\t"
-        "ldr	r8, [%[a], #104]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #104]\n\t"
-        "# A[27] * B\n\t"
-        "ldr	r8, [%[a], #108]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #108]\n\t"
-        "# A[28] * B\n\t"
-        "ldr	r8, [%[a], #112]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #112]\n\t"
-        "# A[29] * B\n\t"
-        "ldr	r8, [%[a], #116]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #116]\n\t"
-        "# A[30] * B\n\t"
-        "ldr	r8, [%[a], #120]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #120]\n\t"
-        "# A[31] * B\n\t"
-        "ldr	r8, [%[a], #124]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #124]\n\t"
-        "# A[32] * B\n\t"
-        "ldr	r8, [%[a], #128]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #128]\n\t"
-        "# A[33] * B\n\t"
-        "ldr	r8, [%[a], #132]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #132]\n\t"
-        "# A[34] * B\n\t"
-        "ldr	r8, [%[a], #136]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #136]\n\t"
-        "# A[35] * B\n\t"
-        "ldr	r8, [%[a], #140]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #140]\n\t"
-        "# A[36] * B\n\t"
-        "ldr	r8, [%[a], #144]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #144]\n\t"
-        "# A[37] * B\n\t"
-        "ldr	r8, [%[a], #148]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #148]\n\t"
-        "# A[38] * B\n\t"
-        "ldr	r8, [%[a], #152]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #152]\n\t"
-        "# A[39] * B\n\t"
-        "ldr	r8, [%[a], #156]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #156]\n\t"
-        "# A[40] * B\n\t"
-        "ldr	r8, [%[a], #160]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #160]\n\t"
-        "# A[41] * B\n\t"
-        "ldr	r8, [%[a], #164]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #164]\n\t"
-        "# A[42] * B\n\t"
-        "ldr	r8, [%[a], #168]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #168]\n\t"
-        "# A[43] * B\n\t"
-        "ldr	r8, [%[a], #172]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #172]\n\t"
-        "# A[44] * B\n\t"
-        "ldr	r8, [%[a], #176]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #176]\n\t"
-        "# A[45] * B\n\t"
-        "ldr	r8, [%[a], #180]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #180]\n\t"
-        "# A[46] * B\n\t"
-        "ldr	r8, [%[a], #184]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #184]\n\t"
-        "# A[47] * B\n\t"
-        "ldr	r8, [%[a], #188]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #188]\n\t"
-        "# A[48] * B\n\t"
-        "ldr	r8, [%[a], #192]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #192]\n\t"
-        "# A[49] * B\n\t"
-        "ldr	r8, [%[a], #196]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #196]\n\t"
-        "# A[50] * B\n\t"
-        "ldr	r8, [%[a], #200]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #200]\n\t"
-        "# A[51] * B\n\t"
-        "ldr	r8, [%[a], #204]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #204]\n\t"
-        "# A[52] * B\n\t"
-        "ldr	r8, [%[a], #208]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #208]\n\t"
-        "# A[53] * B\n\t"
-        "ldr	r8, [%[a], #212]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #212]\n\t"
-        "# A[54] * B\n\t"
-        "ldr	r8, [%[a], #216]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #216]\n\t"
-        "# A[55] * B\n\t"
-        "ldr	r8, [%[a], #220]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #220]\n\t"
-        "# A[56] * B\n\t"
-        "ldr	r8, [%[a], #224]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #224]\n\t"
-        "# A[57] * B\n\t"
-        "ldr	r8, [%[a], #228]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #228]\n\t"
-        "# A[58] * B\n\t"
-        "ldr	r8, [%[a], #232]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #232]\n\t"
-        "# A[59] * B\n\t"
-        "ldr	r8, [%[a], #236]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #236]\n\t"
-        "# A[60] * B\n\t"
-        "ldr	r8, [%[a], #240]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #240]\n\t"
-        "# A[61] * B\n\t"
-        "ldr	r8, [%[a], #244]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #244]\n\t"
-        "# A[62] * B\n\t"
-        "ldr	r8, [%[a], #248]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #248]\n\t"
-        "# A[63] * B\n\t"
-        "ldr	r8, [%[a], #252]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #252]\n\t"
-        "# A[64] * B\n\t"
-        "ldr	r8, [%[a], #256]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #256]\n\t"
-        "# A[65] * B\n\t"
-        "ldr	r8, [%[a], #260]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #260]\n\t"
-        "# A[66] * B\n\t"
-        "ldr	r8, [%[a], #264]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #264]\n\t"
-        "# A[67] * B\n\t"
-        "ldr	r8, [%[a], #268]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #268]\n\t"
-        "# A[68] * B\n\t"
-        "ldr	r8, [%[a], #272]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #272]\n\t"
-        "# A[69] * B\n\t"
-        "ldr	r8, [%[a], #276]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #276]\n\t"
-        "# A[70] * B\n\t"
-        "ldr	r8, [%[a], #280]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #280]\n\t"
-        "# A[71] * B\n\t"
-        "ldr	r8, [%[a], #284]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #284]\n\t"
-        "# A[72] * B\n\t"
-        "ldr	r8, [%[a], #288]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #288]\n\t"
-        "# A[73] * B\n\t"
-        "ldr	r8, [%[a], #292]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #292]\n\t"
-        "# A[74] * B\n\t"
-        "ldr	r8, [%[a], #296]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #296]\n\t"
-        "# A[75] * B\n\t"
-        "ldr	r8, [%[a], #300]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #300]\n\t"
-        "# A[76] * B\n\t"
-        "ldr	r8, [%[a], #304]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #304]\n\t"
-        "# A[77] * B\n\t"
-        "ldr	r8, [%[a], #308]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #308]\n\t"
-        "# A[78] * B\n\t"
-        "ldr	r8, [%[a], #312]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #312]\n\t"
-        "# A[79] * B\n\t"
-        "ldr	r8, [%[a], #316]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #316]\n\t"
-        "# A[80] * B\n\t"
-        "ldr	r8, [%[a], #320]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #320]\n\t"
-        "# A[81] * B\n\t"
-        "ldr	r8, [%[a], #324]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #324]\n\t"
-        "# A[82] * B\n\t"
-        "ldr	r8, [%[a], #328]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #328]\n\t"
-        "# A[83] * B\n\t"
-        "ldr	r8, [%[a], #332]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #332]\n\t"
-        "# A[84] * B\n\t"
-        "ldr	r8, [%[a], #336]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #336]\n\t"
-        "# A[85] * B\n\t"
-        "ldr	r8, [%[a], #340]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #340]\n\t"
-        "# A[86] * B\n\t"
-        "ldr	r8, [%[a], #344]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #344]\n\t"
-        "# A[87] * B\n\t"
-        "ldr	r8, [%[a], #348]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #348]\n\t"
-        "# A[88] * B\n\t"
-        "ldr	r8, [%[a], #352]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #352]\n\t"
-        "# A[89] * B\n\t"
-        "ldr	r8, [%[a], #356]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #356]\n\t"
-        "# A[90] * B\n\t"
-        "ldr	r8, [%[a], #360]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #360]\n\t"
-        "# A[91] * B\n\t"
-        "ldr	r8, [%[a], #364]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #364]\n\t"
-        "# A[92] * B\n\t"
-        "ldr	r8, [%[a], #368]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #368]\n\t"
-        "# A[93] * B\n\t"
-        "ldr	r8, [%[a], #372]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #372]\n\t"
-        "# A[94] * B\n\t"
-        "ldr	r8, [%[a], #376]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #376]\n\t"
-        "# A[95] * B\n\t"
-        "ldr	r8, [%[a], #380]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r5, [%[r], #380]\n\t"
-        "str	r3, [%[r], #384]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
-static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r = 0;
-
-    __asm__ __volatile__ (
-        "lsr	r5, %[div], #1\n\t"
-        "add	r5, r5, #1\n\t"
-        "mov	r6, %[d0]\n\t"
-        "mov	r7, %[d1]\n\t"
-        "# Do top 32\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "# Next 30 bits\n\t"
-        "mov	r4, #29\n\t"
-        "1:\n\t"
-        "movs	r6, r6, lsl #1\n\t"
-        "adc	r7, r7, r7\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "subs	r4, r4, #1\n\t"
-        "bpl	1b\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "add	%[r], %[r], #1\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "subs	r8, %[div], r4\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        : [r] "+r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "r4", "r5", "r6", "r7", "r8"
-    );
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_96(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<96; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 96; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int32_t sp_3072_cmp_96(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "mov	r6, #380\n\t"
-        "1:\n\t"
-        "ldr	r4, [%[a], r6]\n\t"
-        "ldr	r5, [%[b], r6]\n\t"
-        "and	r4, r4, r3\n\t"
-        "and	r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "sub	r6, r6, #4\n\t"
-        "bcc	1b\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "ldr		r4, [%[a], #380]\n\t"
-        "ldr		r5, [%[b], #380]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #376]\n\t"
-        "ldr		r5, [%[b], #376]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #372]\n\t"
-        "ldr		r5, [%[b], #372]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #368]\n\t"
-        "ldr		r5, [%[b], #368]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #364]\n\t"
-        "ldr		r5, [%[b], #364]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #360]\n\t"
-        "ldr		r5, [%[b], #360]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #356]\n\t"
-        "ldr		r5, [%[b], #356]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #352]\n\t"
-        "ldr		r5, [%[b], #352]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #348]\n\t"
-        "ldr		r5, [%[b], #348]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #344]\n\t"
-        "ldr		r5, [%[b], #344]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #340]\n\t"
-        "ldr		r5, [%[b], #340]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #336]\n\t"
-        "ldr		r5, [%[b], #336]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #332]\n\t"
-        "ldr		r5, [%[b], #332]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #328]\n\t"
-        "ldr		r5, [%[b], #328]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #324]\n\t"
-        "ldr		r5, [%[b], #324]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #320]\n\t"
-        "ldr		r5, [%[b], #320]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #316]\n\t"
-        "ldr		r5, [%[b], #316]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #312]\n\t"
-        "ldr		r5, [%[b], #312]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #308]\n\t"
-        "ldr		r5, [%[b], #308]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #304]\n\t"
-        "ldr		r5, [%[b], #304]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #300]\n\t"
-        "ldr		r5, [%[b], #300]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #296]\n\t"
-        "ldr		r5, [%[b], #296]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #292]\n\t"
-        "ldr		r5, [%[b], #292]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #288]\n\t"
-        "ldr		r5, [%[b], #288]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #284]\n\t"
-        "ldr		r5, [%[b], #284]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #280]\n\t"
-        "ldr		r5, [%[b], #280]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #276]\n\t"
-        "ldr		r5, [%[b], #276]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #272]\n\t"
-        "ldr		r5, [%[b], #272]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #268]\n\t"
-        "ldr		r5, [%[b], #268]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #264]\n\t"
-        "ldr		r5, [%[b], #264]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #260]\n\t"
-        "ldr		r5, [%[b], #260]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #256]\n\t"
-        "ldr		r5, [%[b], #256]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #252]\n\t"
-        "ldr		r5, [%[b], #252]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #248]\n\t"
-        "ldr		r5, [%[b], #248]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #244]\n\t"
-        "ldr		r5, [%[b], #244]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #240]\n\t"
-        "ldr		r5, [%[b], #240]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #236]\n\t"
-        "ldr		r5, [%[b], #236]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #232]\n\t"
-        "ldr		r5, [%[b], #232]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #228]\n\t"
-        "ldr		r5, [%[b], #228]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #224]\n\t"
-        "ldr		r5, [%[b], #224]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #220]\n\t"
-        "ldr		r5, [%[b], #220]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #216]\n\t"
-        "ldr		r5, [%[b], #216]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #212]\n\t"
-        "ldr		r5, [%[b], #212]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #208]\n\t"
-        "ldr		r5, [%[b], #208]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #204]\n\t"
-        "ldr		r5, [%[b], #204]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #200]\n\t"
-        "ldr		r5, [%[b], #200]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #196]\n\t"
-        "ldr		r5, [%[b], #196]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #192]\n\t"
-        "ldr		r5, [%[b], #192]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #188]\n\t"
-        "ldr		r5, [%[b], #188]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #184]\n\t"
-        "ldr		r5, [%[b], #184]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #180]\n\t"
-        "ldr		r5, [%[b], #180]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #176]\n\t"
-        "ldr		r5, [%[b], #176]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #172]\n\t"
-        "ldr		r5, [%[b], #172]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #168]\n\t"
-        "ldr		r5, [%[b], #168]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #164]\n\t"
-        "ldr		r5, [%[b], #164]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #160]\n\t"
-        "ldr		r5, [%[b], #160]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #156]\n\t"
-        "ldr		r5, [%[b], #156]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #152]\n\t"
-        "ldr		r5, [%[b], #152]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #148]\n\t"
-        "ldr		r5, [%[b], #148]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #144]\n\t"
-        "ldr		r5, [%[b], #144]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #140]\n\t"
-        "ldr		r5, [%[b], #140]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #136]\n\t"
-        "ldr		r5, [%[b], #136]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #132]\n\t"
-        "ldr		r5, [%[b], #132]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #128]\n\t"
-        "ldr		r5, [%[b], #128]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #124]\n\t"
-        "ldr		r5, [%[b], #124]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #120]\n\t"
-        "ldr		r5, [%[b], #120]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #116]\n\t"
-        "ldr		r5, [%[b], #116]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #112]\n\t"
-        "ldr		r5, [%[b], #112]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #108]\n\t"
-        "ldr		r5, [%[b], #108]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #104]\n\t"
-        "ldr		r5, [%[b], #104]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #100]\n\t"
-        "ldr		r5, [%[b], #100]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #96]\n\t"
-        "ldr		r5, [%[b], #96]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #92]\n\t"
-        "ldr		r5, [%[b], #92]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #88]\n\t"
-        "ldr		r5, [%[b], #88]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #84]\n\t"
-        "ldr		r5, [%[b], #84]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #80]\n\t"
-        "ldr		r5, [%[b], #80]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #76]\n\t"
-        "ldr		r5, [%[b], #76]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #72]\n\t"
-        "ldr		r5, [%[b], #72]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #68]\n\t"
-        "ldr		r5, [%[b], #68]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #64]\n\t"
-        "ldr		r5, [%[b], #64]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #60]\n\t"
-        "ldr		r5, [%[b], #60]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #56]\n\t"
-        "ldr		r5, [%[b], #56]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #52]\n\t"
-        "ldr		r5, [%[b], #52]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #48]\n\t"
-        "ldr		r5, [%[b], #48]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #44]\n\t"
-        "ldr		r5, [%[b], #44]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #40]\n\t"
-        "ldr		r5, [%[b], #40]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #36]\n\t"
-        "ldr		r5, [%[b], #36]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #32]\n\t"
-        "ldr		r5, [%[b], #32]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #28]\n\t"
-        "ldr		r5, [%[b], #28]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #24]\n\t"
-        "ldr		r5, [%[b], #24]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #20]\n\t"
-        "ldr		r5, [%[b], #20]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #16]\n\t"
-        "ldr		r5, [%[b], #16]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #12]\n\t"
-        "ldr		r5, [%[b], #12]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #8]\n\t"
-        "ldr		r5, [%[b], #8]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #4]\n\t"
-        "ldr		r5, [%[b], #4]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #0]\n\t"
-        "ldr		r5, [%[b], #0]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_96(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[192], t2[97];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[95];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
-    for (i=95; i>=0; i--) {
-        r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div);
-
-        sp_3072_mul_d_96(t2, d, r1);
-        t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
-        t1[96 + i] -= t2[96];
-        sp_3072_mask_96(t2, d, t1[96 + i]);
-        t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
-        sp_3072_mask_96(t2, d, t1[96 + i]);
-        t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_96(t1, d) >= 0;
-    sp_3072_cond_sub_96(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_96(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_96(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_96_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[192], t2[97];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[95];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 96);
-    for (i=95; i>=0; i--) {
-        r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div);
-
-        sp_3072_mul_d_96(t2, d, r1);
-        t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2);
-        t1[96 + i] -= t2[96];
-        if (t1[96 + i] != 0) {
-            t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
-            if (t1[96 + i] != 0)
-                t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_3072_cmp_96(t1, d) >= 0;
-    sp_3072_cond_sub_96(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_96_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][192];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 192, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 192;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_96(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 96);
-        if (reduceA) {
-            err = sp_3072_mod_96(t[1] + 96, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_96(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
-            err = sp_3072_mod_96(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_96(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_96(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_96(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 28;
-        n <<= 4;
-        c = 28;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 28;
-                n <<= 4;
-                c = 28;
-            }
-            else if (c < 4) {
-                y = n >> 28;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 28) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-
-            sp_3072_mont_mul_96(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[96], 0, sizeof(sp_digit) * 96);
-        sp_3072_mont_reduce_96(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
-        sp_3072_cond_sub_96(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][192];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 192, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 192;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_96(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 96);
-        if (reduceA) {
-            err = sp_3072_mod_96(t[1] + 96, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_96(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96);
-            err = sp_3072_mod_96(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_96(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_96(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_96(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_96(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_96(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_96(t[20], t[10], m, mp);
-        sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_96(t[22], t[11], m, mp);
-        sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_96(t[24], t[12], m, mp);
-        sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_96(t[26], t[13], m, mp);
-        sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_96(t[28], t[14], m, mp);
-        sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_96(t[30], t[15], m, mp);
-        sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 32;
-        n = e[i--];
-        y = n >> 27;
-        n <<= 5;
-        c = 27;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 96);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 27;
-                n <<= 5;
-                c = 27;
-            }
-            else if (c < 5) {
-                y = n >> 27;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (32 - c);
-                n <<= c;
-                c = 32 - c;
-            }
-            else {
-                y = (n >> 27) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-            sp_3072_mont_sqr_96(r, r, m, mp);
-
-            sp_3072_mont_mul_96(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x3;
-        sp_3072_mont_sqr_96(r, r, m, mp);
-        sp_3072_mont_sqr_96(r, r, m, mp);
-        sp_3072_mont_mul_96(r, r, t[y], m, mp);
-
-        XMEMSET(&r[96], 0, sizeof(sp_digit) * 96);
-        sp_3072_mont_reduce_96(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_96(r, m) >= 0);
-        sp_3072_cond_sub_96(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[192], md[96], rd[192];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 96 * 2;
-        m = r + 96 * 2;
-        ah = a + 96;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 96;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(ah, 96, in, inLen);
-#if DIGIT_BIT >= 32
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 96, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_3072_sqr_96(r, ah);
-                err = sp_3072_mod_96_cond(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_3072_mul_96(r, ah, r);
-                err = sp_3072_mod_96_cond(r, r, m);
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_3072_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 96);
-            err = sp_3072_mod_96_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=31; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 96);
-                for (i--; i>=0; i--) {
-                    sp_3072_mont_sqr_96(r, r, m, mp);
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_3072_mont_mul_96(r, r, a, m, mp);
-                }
-                XMEMSET(&r[96], 0, sizeof(sp_digit) * 96);
-                sp_3072_mont_reduce_96(r, m, mp);
-
-                for (i = 95; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_3072_sub_in_place_96(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[96 * 2];
-    sp_digit pd[48], qd[48], dpd[48];
-    sp_digit tmpad[96], tmpbd[96];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 96 * 2;
-        q = p + 48;
-        qi = dq = dp = q + 48;
-        tmpa = qi + 48;
-        tmpb = tmpa + 96;
-
-        tmp = t;
-        r = tmp + 96;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 96;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 96, in, inLen);
-        sp_3072_from_mp(p, 48, pm);
-        sp_3072_from_mp(q, 48, qm);
-        sp_3072_from_mp(dp, 48, dpm);
-
-        err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(dq, 48, dqm);
-        err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_3072_sub_in_place_48(tmpa, tmpb);
-        sp_3072_mask_48(tmp, p, c);
-        sp_3072_add_48(tmpa, tmpa, tmp);
-
-        sp_3072_from_mp(qi, 48, qim);
-        sp_3072_mul_48(tmpa, tmpa, qi);
-        err = sp_3072_mod_48(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_48(tmpa, q, tmpa);
-        XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_add_96(r, tmpb, tmpa);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_3072_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 32
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 96);
-        r->used = 96;
-        mp_clamp(r);
-#elif DIGIT_BIT < 32
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 96; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 32) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 32 - s;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 96; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 32 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 32 - s;
-            }
-            else
-                s += 32;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[192], e[96], m[96];
-    sp_digit* r = b;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 96, base);
-        sp_3072_from_mp(e, 96, exp);
-        sp_3072_from_mp(m, 96, mod);
-
-        err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 384 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[192], e[96], m[96];
-    sp_digit* r = b;
-    word32 i;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 96, base);
-        sp_3072_from_bin(e, 96, exp, expLen);
-        sp_3072_from_mp(m, 96, mod);
-
-        err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_3072 */
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-
-/* Point structure to use. */
-typedef struct sp_point {
-    sp_digit x[2 * 8];
-    sp_digit y[2 * 8];
-    sp_digit z[2 * 8];
-    int infinity;
-} sp_point;
-
-/* The modulus (prime) of the curve P256. */
-static sp_digit p256_mod[8] = {
-    0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,
-    0x00000001,0xffffffff
-};
-/* The Montogmery normalizer for modulus of the curve P256. */
-static sp_digit p256_norm_mod[8] = {
-    0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff,
-    0xfffffffe,0x00000000
-};
-/* The Montogmery multiplier for modulus of the curve P256. */
-static sp_digit p256_mp_mod = 0x00000001;
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
-                                            defined(HAVE_ECC_VERIFY)
-/* The order of the curve P256. */
-static sp_digit p256_order[8] = {
-    0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
-    0x00000000,0xffffffff
-};
-#endif
-/* The order of the curve P256 minus 2. */
-static sp_digit p256_order2[8] = {
-    0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
-    0x00000000,0xffffffff
-};
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery normalizer for order of the curve P256. */
-static sp_digit p256_norm_order[8] = {
-    0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000,
-    0xffffffff,0x00000000
-};
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery multiplier for order of the curve P256. */
-static sp_digit p256_mp_order = 0xee00bc4f;
-#endif
-/* The base point of curve P256. */
-static sp_point p256_base = {
-    /* X ordinate */
-    {
-        0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5,
-        0xe12c4247,0x6b17d1f2
-    },
-    /* Y ordinate */
-    {
-        0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a,
-        0xfe1a7f9b,0x4fe342e2
-    },
-    /* Z ordinate */
-    {
-        0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
-        0x00000000,0x00000000
-    },
-    /* infinity */
-    0
-};
-#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
-static sp_digit p256_b[8] = {
-    0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55,
-    0xaa3a93e7,0x5ac635d8
-};
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* Allocate memory for point and return error. */
-#define sp_ecc_point_new(heap, sp, p)                                   \
-    ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \
-        MEMORY_E : MP_OKAY
-#else
-/* Set pointer to data and return no error. */
-#define sp_ecc_point_new(heap, sp, p)   ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* If valid pointer then clear point data if requested and free data. */
-#define sp_ecc_point_free(p, clear, heap)     \
-    do {                                      \
-        if (p != NULL) {                      \
-            if (clear)                        \
-                XMEMSET(p, 0, sizeof(*p));    \
-            XFREE(p, heap, DYNAMIC_TYPE_ECC); \
-        }                                     \
-    }                                         \
-    while (0)
-#else
-/* Clear point data if requested. */
-#define sp_ecc_point_free(p, clear, heap) \
-    do {                                  \
-        if (clear)                        \
-            XMEMSET(p, 0, sizeof(*p));    \
-    }                                     \
-    while (0)
-#endif
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r  The resulting Montgomery form number.
- * a  The number to convert.
- * m  The modulus (prime).
- */
-static int sp_256_mod_mul_norm_8(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    int64_t t[8];
-    int64_t a64[8];
-    int64_t o;
-
-    (void)m;
-
-    a64[0] = a[0];
-    a64[1] = a[1];
-    a64[2] = a[2];
-    a64[3] = a[3];
-    a64[4] = a[4];
-    a64[5] = a[5];
-    a64[6] = a[6];
-    a64[7] = a[7];
-
-    /*  1  1  0 -1 -1 -1 -1  0 */
-    t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6];
-    /*  0  1  1  0 -1 -1 -1 -1 */
-    t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7];
-    /*  0  0  1  1  0 -1 -1 -1 */
-    t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7];
-    /* -1 -1  0  2  2  1  0 -1 */
-    t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7];
-    /*  0 -1 -1  0  2  2  1  0 */
-    t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6];
-    /*  0  0 -1 -1  0  2  2  1 */
-    t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7];
-    /* -1 -1  0  0  0  1  3  2 */
-    t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7];
-    /*  1  0 -1 -1 -1 -1  0  3 */
-    t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7];
-
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    o     = t[7] >> 32; t[7] &= 0xffffffff;
-    t[0] += o;
-    t[3] -= o;
-    t[6] -= o;
-    t[7] += o;
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    r[0] = t[0];
-    r[1] = t[1];
-    r[2] = t[2];
-    r[3] = t[3];
-    r[4] = t[4];
-    r[5] = t[5];
-    r[6] = t[6];
-    r[7] = t[7];
-
-    return MP_OKAY;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 32
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 32
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffff;
-        s = 32 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 32 <= DIGIT_BIT) {
-            s += 32;
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 32) {
-            r[j] &= 0xffffffff;
-            if (j + 1 >= max)
-                break;
-            s = 32 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point.
- *
- * p   Point of type sp_point (result).
- * pm  Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_8(sp_point* p, ecc_point* pm)
-{
-    XMEMSET(p->x, 0, sizeof(p->x));
-    XMEMSET(p->y, 0, sizeof(p->y));
-    XMEMSET(p->z, 0, sizeof(p->z));
-    sp_256_from_mp(p->x, 8, pm->x);
-    sp_256_from_mp(p->y, 8, pm->y);
-    sp_256_from_mp(p->z, 8, pm->z);
-    p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_256_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 32
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 8);
-        r->used = 8;
-        mp_clamp(r);
-#elif DIGIT_BIT < 32
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 8; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 32) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 32 - s;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 8; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 32 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 32 - s;
-            }
-            else
-                s += 32;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Convert a point of type sp_point to type ecc_point.
- *
- * p   Point of type sp_point.
- * pm  Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_8(sp_point* p, ecc_point* pm)
-{
-    int err;
-
-    err = sp_256_to_mp(p->x, pm->x);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pm->y);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pm->z);
-
-    return err;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int32_t sp_256_cmp_8(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "mov	r6, #28\n\t"
-        "1:\n\t"
-        "ldr	r4, [%[a], r6]\n\t"
-        "ldr	r5, [%[b], r6]\n\t"
-        "and	r4, r4, r3\n\t"
-        "and	r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "sub	r6, r6, #4\n\t"
-        "bcc	1b\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r7, #0\n\t"
-        "mov	r3, #-1\n\t"
-        "ldr		r4, [%[a], #28]\n\t"
-        "ldr		r5, [%[b], #28]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #24]\n\t"
-        "ldr		r5, [%[b], #24]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #20]\n\t"
-        "ldr		r5, [%[b], #20]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #16]\n\t"
-        "ldr		r5, [%[b], #16]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #12]\n\t"
-        "ldr		r5, [%[b], #12]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #8]\n\t"
-        "ldr		r5, [%[b], #8]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #4]\n\t"
-        "ldr		r5, [%[b], #4]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "ldr		r4, [%[a], #0]\n\t"
-        "ldr		r5, [%[b], #0]\n\t"
-        "and		r4, r4, r3\n\t"
-        "and		r5, r5, r3\n\t"
-        "subs	r4, r4, r5\n\t"
-        "movhi	%[r], %[one]\n\t"
-        "movlo	%[r], r3\n\t"
-        "movne	r3, r7\n\t"
-        "eor	%[r], %[r], r3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "r2", "r3", "r4", "r5", "r6", "r7"
-    );
-#endif
-
-    return r;
-}
-
-/* Normalize the values in each word to 32.
- *
- * a  Array of sp_digit to normalize.
- */
-#define sp_256_norm_8(a)
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_256_cond_sub_8(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r9, #0\n\t"
-        "mov	r8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], r9, %[c]\n\t"
-        "ldr	r4, [%[a], r8]\n\t"
-        "ldr	r5, [%[b], r8]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        "str	r4, [%[r], r8]\n\t"
-        "add	r8, r8, #4\n\t"
-        "cmp	r8, #32\n\t"
-        "blt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "mov	r9, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r5, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "subs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r6, [%[r], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r5, [%[b], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r5, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r6, [%[r], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r5, [%[b], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "and	r5, r5, %[m]\n\t"
-        "and	r7, r7, %[m]\n\t"
-        "sbcs	r4, r4, r5\n\t"
-        "sbcs	r6, r6, r7\n\t"
-        "str	r4, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "r4", "r6", "r5", "r7", "r8", "r9"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "ldr	r14, [%[a], #4]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	r8, %[mp], r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	r7, [%[m], #0]\n\t"
-        "ldr	r9, [%[a], #0]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r10, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	r7, [%[m], #4]\n\t"
-        "ldr	r9, [%[a], #4]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r10, r14, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r10, r10, r5\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	r7, [%[m], #8]\n\t"
-        "ldr	r14, [%[a], #8]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r14, r14, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r14, r14, r4\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	r7, [%[m], #12]\n\t"
-        "ldr	r9, [%[a], #12]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #12]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	r7, [%[m], #16]\n\t"
-        "ldr	r9, [%[a], #16]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #16]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	r7, [%[m], #20]\n\t"
-        "ldr	r9, [%[a], #20]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r4, r7, #0\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #20]\n\t"
-        "adc	r4, r4, #0\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	r7, [%[m], #24]\n\t"
-        "ldr	r9, [%[a], #24]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r9, r9, r6\n\t"
-        "adc	r5, r7, #0\n\t"
-        "adds	r9, r9, r4\n\t"
-        "str	r9, [%[a], #24]\n\t"
-        "adc	r5, r5, #0\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	r7, [%[m], #28]\n\t"
-        "ldr   r9, [%[a], #28]\n\t"
-        "umull	r6, r7, r8, r7\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r7, r7, %[ca]\n\t"
-        "mov	%[ca], #0\n\t"
-        "adc	%[ca], %[ca], %[ca]\n\t"
-        "adds	r9, r9, r5\n\t"
-        "str	r9, [%[a], #28]\n\t"
-        "ldr	r9, [%[a], #32]\n\t"
-        "adcs	r9, r9, r7\n\t"
-        "str	r9, [%[a], #32]\n\t"
-        "adc	%[ca], %[ca], #0\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], #4\n\t"
-        "add	r12, r12, #4\n\t"
-        "cmp	r12, #32\n\t"
-        "blt	1b\n\t"
-        "str	r10, [%[a], #0]\n\t"
-        "str	r14, [%[a], #4]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_mul_8(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_digit tmp[9];
-
-    (void)mp;
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "#  A[0] * B[0]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r8, r9, r6, r7\n\t"
-        "str	r8, [%[tmp], #0]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adc	r10, r4, #0\n\t"
-        "#  A[1] * B[0]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "str	r9, [%[tmp], #4]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adc	r14, r4, r14\n\t"
-        "#  A[1] * B[1]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, #0\n\t"
-        "#  A[2] * B[0]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "str	r10, [%[tmp], #8]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "#  A[1] * B[2]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[2] * B[1]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[3] * B[0]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "str	r14, [%[tmp], #12]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "#  A[1] * B[3]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[2] * B[2]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[4] * B[0]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "#  A[1] * B[4]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[2] * B[3]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[3] * B[2]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[4] * B[1]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[5] * B[0]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, #0\n\t"
-        "#  A[1] * B[5]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[2] * B[4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[3] * B[3]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[4] * B[2]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[5] * B[1]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[6] * B[0]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "#  A[1] * B[6]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[2] * B[5]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[3] * B[4]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[4] * B[3]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[5] * B[2]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[6] * B[1]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[7] * B[0]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "#  A[1] * B[7]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "#  A[2] * B[6]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[3] * B[5]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[4] * B[4]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[5] * B[3]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[6] * B[2]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[7] * B[1]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "str	r8, [%[r], #0]\n\t"
-        "#  A[2] * B[7]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "#  A[3] * B[6]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[4] * B[5]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[5] * B[4]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[6] * B[3]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[7] * B[2]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "str	r9, [%[r], #4]\n\t"
-        "#  A[3] * B[7]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, #0\n\t"
-        "#  A[4] * B[6]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[5] * B[5]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[6] * B[4]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[7] * B[3]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "str	r10, [%[r], #8]\n\t"
-        "#  A[4] * B[7]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "#  A[5] * B[6]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[6] * B[5]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[7] * B[4]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "str	r14, [%[r], #12]\n\t"
-        "#  A[5] * B[7]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "#  A[6] * B[6]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[7] * B[5]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[6] * B[7]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "#  A[7] * B[6]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[7] * B[7]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adc	r14, r4, r14\n\t"
-        "str	r8, [%[r], #16]\n\t"
-        "str	r9, [%[r], #20]\n\t"
-        "str	r10, [%[r], #24]\n\t"
-        "str	r14, [%[r], #28]\n\t"
-        "# Start Reduction\n\t"
-        "ldr	r4, [%[tmp], #0]\n\t"
-        "ldr	r5, [%[tmp], #4]\n\t"
-        "ldr	r6, [%[tmp], #8]\n\t"
-        "ldr	r7, [%[tmp], #12]\n\t"
-        "ldr	r8, [%[tmp], #16]\n\t"
-        "ldr	r9, [%[tmp], #20]\n\t"
-        "ldr	r10, [%[tmp], #24]\n\t"
-        "ldr	r14, [%[tmp], #28]\n\t"
-        "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t"
-        "#    - a[0] << 224\n\t"
-        "#   + (a[0]-a[1] * 2) << (6 * 32)\n\t"
-        "adds	r10, r10, r4\n\t"
-        "adc	r14, r14, r5\n\t"
-        "adds	r10, r10, r4\n\t"
-        "adc	r14, r14, r5\n\t"
-        "#   - a[0] << (7 * 32)\n\t"
-        "sub	r14, r14, r4\n\t"
-        "#   + a[0]-a[4] << (3 * 32)\n\t"
-        "mov	%[a], r7\n\t"
-        "mov	%[b], r8\n\t"
-        "adds	r7, r7, r4\n\t"
-        "adcs	r8, r8, r5\n\t"
-        "adcs	r9, r9, r6\n\t"
-        "adcs	r10, r10, %[a]\n\t"
-        "adc	r14, r14, %[b]\n\t"
-        "str	r4, [%[tmp], #0]\n\t"
-        "str	r5, [%[tmp], #4]\n\t"
-        "str	r6, [%[tmp], #8]\n\t"
-        "str	r7, [%[tmp], #12]\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "# a += mu * m\n\t"
-        "#   += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t"
-        "mov	%[a], #0\n\t"
-        "# a[6] +=        t[0] + t[3]\n\t"
-        "ldr	r3, [%[tmp], #24]\n\t"
-        "adds	r3, r3, r4\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "# a[7] +=        t[1] + t[4]\n\t"
-        "ldr	r3, [%[tmp], #28]\n\t"
-        "adds	r3, r3, %[b]\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "str	r3, [%[tmp], #32]\n\t"
-        "# a[8] += t[0] + t[2] + t[5]\n\t"
-        "ldr	r3, [%[r], #0]\n\t"
-        "adds	r3, r3, %[b]\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r4\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r9\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "# a[9]  += t[1] + t[3] + t[6]\n\t"
-        "# a[10] += t[2] + t[4] + t[7]\n\t"
-        "ldr	r3, [%[r], #4]\n\t"
-        "ldr	r4, [%[r], #8]\n\t"
-        "adds	r3, r3, %[b]\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adcs	r4, r4, r6\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r10\n\t"
-        "adcs	r4, r4, r14\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r3, [%[r], #4]\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "# a[11] += t[3] + t[5]\n\t"
-        "# a[12] += t[4] + t[6]\n\t"
-        "# a[13] += t[5] + t[7]\n\t"
-        "# a[14] += t[6]\n\t"
-        "ldr	r3, [%[r], #12]\n\t"
-        "ldr	r4, [%[r], #16]\n\t"
-        "ldr	r5, [%[r], #20]\n\t"
-        "ldr	r6, [%[r], #24]\n\t"
-        "adds	r3, r3, %[b]\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "adcs	r5, r5, #0\n\t"
-        "adcs	r6, r6, #0\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "adds	r3, r3, r9\n\t"
-        "adcs	r4, r4, r10\n\t"
-        "adcs	r5, r5, r14\n\t"
-        "adcs	r6, r6, #0\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "# a[15] += t[7]\n\t"
-        "ldr	r3, [%[r], #28]\n\t"
-        "adds	r3, r3, %[b]\n\t"
-        "adc	%[b], %[a], #0\n\t"
-        "adds	r3, r3, r14\n\t"
-        "adc	%[b], %[b], #0\n\t"
-        "str	r3, [%[r], #28]\n\t"
-        "ldr	r3, [%[tmp], #32]\n\t"
-        "ldr	r4, [%[r], #0]\n\t"
-        "ldr	r5, [%[r], #4]\n\t"
-        "ldr	r6, [%[r], #8]\n\t"
-        "ldr	r8, [%[tmp], #0]\n\t"
-        "ldr	r9, [%[tmp], #4]\n\t"
-        "ldr	r10, [%[tmp], #8]\n\t"
-        "ldr	r14, [%[tmp], #12]\n\t"
-        "subs	r3, r3, r8\n\t"
-        "sbcs	r4, r4, r9\n\t"
-        "sbcs	r5, r5, r10\n\t"
-        "sbcs	r6, r6, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "ldr	r3, [%[r], #12]\n\t"
-        "ldr	r4, [%[r], #16]\n\t"
-        "ldr	r5, [%[r], #20]\n\t"
-        "ldr	r6, [%[r], #24]\n\t"
-        "ldr	r7, [%[r], #28]\n\t"
-        "ldr	r8, [%[tmp], #16]\n\t"
-        "ldr	r9, [%[tmp], #20]\n\t"
-        "ldr	r10, [%[tmp], #24]\n\t"
-        "ldr	r14, [%[tmp], #28]\n\t"
-        "sbcs	r3, r3, r8\n\t"
-        "sbcs	r4, r4, r9\n\t"
-        "sbcs	r5, r5, r10\n\t"
-        "sbcs	r6, r6, r14\n\t"
-        "sbc	r7, r7, #0\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "sub	%[b], %[a], %[b]\n\t"
-        "and	%[a], %[b], #1\n\t"
-        "ldr	r3, [%[r], #0]\n\t"
-        "ldr	r4, [%[r], #4]\n\t"
-        "ldr	r5, [%[r], #8]\n\t"
-        "ldr	r6, [%[r], #12]\n\t"
-        "ldr	r7, [%[r], #16]\n\t"
-        "ldr	r8, [%[r], #20]\n\t"
-        "ldr	r9, [%[r], #24]\n\t"
-        "ldr	r10, [%[r], #28]\n\t"
-        "subs	r3, r3, %[b]\n\t"
-        "sbcs	r4, r4, %[b]\n\t"
-        "sbcs	r5, r5, %[b]\n\t"
-        "sbcs	r6, r6, #0\n\t"
-        "sbcs	r7, r7, #0\n\t"
-        "sbcs	r8, r8, #0\n\t"
-        "sbcs	r9, r9, %[a]\n\t"
-        "sbc	r10, r10, %[b]\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "str	r7, [%[r], #16]\n\t"
-        "str	r8, [%[r], #20]\n\t"
-        "str	r9, [%[r], #24]\n\t"
-        "str	r10, [%[r], #28]\n\t"
-        : [a] "+r" (a), [b] "+r" (b)
-        : [r] "r" (r), [tmp] "r" (tmp)
-        : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7"
-    );
-}
-
-/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit tmp[16];
-
-    (void)mp;
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "#  A[0] * A[1]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #4]\n\t"
-        "umull	r9, r10, r6, r7\n\t"
-        "str	r9, [%[tmp], #4]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adc	r14, r4, #0\n\t"
-        "str	r10, [%[tmp], #8]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adc	r8, r4, #0\n\t"
-        "#  A[1] * A[2]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #8]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "str	r14, [%[tmp], #12]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adc	r9, r4, r9\n\t"
-        "#  A[1] * A[3]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adc	r10, r4, r10\n\t"
-        "#  A[1] * A[4]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "#  A[2] * A[3]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, #0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "#  A[2] * A[4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[2] * A[5]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "#  A[3] * A[4]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[a], #16]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "#  A[1] * A[7]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "#  A[2] * A[6]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "#  A[3] * A[5]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[a], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, r10\n\t"
-        "str	r8, [%[tmp], #32]\n\t"
-        "#  A[2] * A[7]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, #0\n\t"
-        "#  A[3] * A[6]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "#  A[4] * A[5]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[a], #20]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adcs	r10, r4, r10\n\t"
-        "adc	r14, r5, r14\n\t"
-        "str	r9, [%[tmp], #36]\n\t"
-        "#  A[3] * A[7]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, #0\n\t"
-        "#  A[4] * A[6]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r10, r3, r10\n\t"
-        "adcs	r14, r4, r14\n\t"
-        "adc	r8, r5, r8\n\t"
-        "str	r10, [%[tmp], #40]\n\t"
-        "#  A[4] * A[7]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, #0\n\t"
-        "#  A[5] * A[6]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[a], #24]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r14, r3, r14\n\t"
-        "adcs	r8, r4, r8\n\t"
-        "adc	r9, r5, r9\n\t"
-        "str	r14, [%[tmp], #44]\n\t"
-        "#  A[5] * A[7]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r8, r3, r8\n\t"
-        "adcs	r9, r4, r9\n\t"
-        "adc	r10, r5, #0\n\t"
-        "str	r8, [%[tmp], #48]\n\t"
-        "#  A[6] * A[7]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "umull	r3, r4, r6, r7\n\t"
-        "adds	r9, r3, r9\n\t"
-        "adc	r10, r4, r10\n\t"
-        "str	r9, [%[tmp], #52]\n\t"
-        "str	r10, [%[tmp], #56]\n\t"
-        "# Double\n\t"
-        "ldr	r4, [%[tmp], #4]\n\t"
-        "ldr	r6, [%[tmp], #8]\n\t"
-        "ldr	r7, [%[tmp], #12]\n\t"
-        "ldr	r8, [%[tmp], #16]\n\t"
-        "ldr	r9, [%[tmp], #20]\n\t"
-        "ldr	r10, [%[tmp], #24]\n\t"
-        "ldr	r14, [%[tmp], #28]\n\t"
-        "ldr	r12, [%[tmp], #32]\n\t"
-        "ldr	r3, [%[tmp], #36]\n\t"
-        "adds	r4, r4, r4\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adcs	r7, r7, r7\n\t"
-        "adcs	r8, r8, r8\n\t"
-        "adcs	r9, r9, r9\n\t"
-        "adcs	r10, r10, r10\n\t"
-        "adcs	r14, r14, r14\n\t"
-        "adcs	r12, r12, r12\n\t"
-        "adcs	r3, r3, r3\n\t"
-        "str	r4, [%[tmp], #4]\n\t"
-        "str	r6, [%[tmp], #8]\n\t"
-        "str	r7, [%[tmp], #12]\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "str	r12, [%[tmp], #32]\n\t"
-        "str	r3, [%[tmp], #36]\n\t"
-        "ldr	r4, [%[tmp], #40]\n\t"
-        "ldr	r6, [%[tmp], #44]\n\t"
-        "ldr	r7, [%[tmp], #48]\n\t"
-        "ldr	r8, [%[tmp], #52]\n\t"
-        "ldr	r9, [%[tmp], #56]\n\t"
-        "adcs	r4, r4, r4\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adcs	r7, r7, r7\n\t"
-        "adcs	r8, r8, r8\n\t"
-        "adcs	r9, r9, r9\n\t"
-        "str	r4, [%[tmp], #40]\n\t"
-        "str	r6, [%[tmp], #44]\n\t"
-        "str	r7, [%[tmp], #48]\n\t"
-        "str	r8, [%[tmp], #52]\n\t"
-        "str	r9, [%[tmp], #56]\n\t"
-        "adc	r10, r5, #0\n\t"
-        "str	r10, [%[tmp], #60]\n\t"
-        "ldr	r4, [%[tmp], #4]\n\t"
-        "ldr	r5, [%[tmp], #8]\n\t"
-        "ldr	r12, [%[tmp], #12]\n\t"
-        "#  A[0] * A[0]\n\t"
-        "ldr	r6, [%[a], #0]\n\t"
-        "umull	r8, r9, r6, r6\n\t"
-        "#  A[1] * A[1]\n\t"
-        "ldr	r6, [%[a], #4]\n\t"
-        "umull	r10, r14, r6, r6\n\t"
-        "adds	r9, r9, r4\n\t"
-        "adcs	r10, r10, r5\n\t"
-        "adcs	r14, r14, r12\n\t"
-        "str	r8, [%[tmp], #0]\n\t"
-        "str	r9, [%[tmp], #4]\n\t"
-        "str	r10, [%[tmp], #8]\n\t"
-        "str	r14, [%[tmp], #12]\n\t"
-        "ldr	r3, [%[tmp], #16]\n\t"
-        "ldr	r4, [%[tmp], #20]\n\t"
-        "ldr	r5, [%[tmp], #24]\n\t"
-        "ldr	r12, [%[tmp], #28]\n\t"
-        "#  A[2] * A[2]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "umull	r8, r9, r6, r6\n\t"
-        "#  A[3] * A[3]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "umull	r10, r14, r6, r6\n\t"
-        "adcs	r8, r8, r3\n\t"
-        "adcs	r9, r9, r4\n\t"
-        "adcs	r10, r10, r5\n\t"
-        "adcs	r14, r14, r12\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "ldr	r3, [%[tmp], #32]\n\t"
-        "ldr	r4, [%[tmp], #36]\n\t"
-        "ldr	r5, [%[tmp], #40]\n\t"
-        "ldr	r12, [%[tmp], #44]\n\t"
-        "#  A[4] * A[4]\n\t"
-        "ldr	r6, [%[a], #16]\n\t"
-        "umull	r8, r9, r6, r6\n\t"
-        "#  A[5] * A[5]\n\t"
-        "ldr	r6, [%[a], #20]\n\t"
-        "umull	r10, r14, r6, r6\n\t"
-        "adcs	r8, r8, r3\n\t"
-        "adcs	r9, r9, r4\n\t"
-        "adcs	r10, r10, r5\n\t"
-        "adcs	r14, r14, r12\n\t"
-        "str	r8, [%[r], #0]\n\t"
-        "str	r9, [%[r], #4]\n\t"
-        "str	r10, [%[r], #8]\n\t"
-        "str	r14, [%[r], #12]\n\t"
-        "ldr	r3, [%[tmp], #48]\n\t"
-        "ldr	r4, [%[tmp], #52]\n\t"
-        "ldr	r5, [%[tmp], #56]\n\t"
-        "ldr	r12, [%[tmp], #60]\n\t"
-        "#  A[6] * A[6]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "umull	r8, r9, r6, r6\n\t"
-        "#  A[7] * A[7]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "umull	r10, r14, r6, r6\n\t"
-        "adcs	r8, r8, r3\n\t"
-        "adcs	r9, r9, r4\n\t"
-        "adcs	r10, r10, r5\n\t"
-        "adc	r14, r14, r12\n\t"
-        "str	r8, [%[r], #16]\n\t"
-        "str	r9, [%[r], #20]\n\t"
-        "str	r10, [%[r], #24]\n\t"
-        "str	r14, [%[r], #28]\n\t"
-        "# Start Reduction\n\t"
-        "ldr	r4, [%[tmp], #0]\n\t"
-        "ldr	r5, [%[tmp], #4]\n\t"
-        "ldr	r6, [%[tmp], #8]\n\t"
-        "ldr	r7, [%[tmp], #12]\n\t"
-        "ldr	r8, [%[tmp], #16]\n\t"
-        "ldr	r9, [%[tmp], #20]\n\t"
-        "ldr	r10, [%[tmp], #24]\n\t"
-        "ldr	r14, [%[tmp], #28]\n\t"
-        "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t"
-        "#    - a[0] << 224\n\t"
-        "#   + (a[0]-a[1] * 2) << (6 * 32)\n\t"
-        "adds	r10, r10, r4\n\t"
-        "adc	r14, r14, r5\n\t"
-        "adds	r10, r10, r4\n\t"
-        "adc	r14, r14, r5\n\t"
-        "#   - a[0] << (7 * 32)\n\t"
-        "sub	r14, r14, r4\n\t"
-        "#   + a[0]-a[4] << (3 * 32)\n\t"
-        "mov	%[a], r7\n\t"
-        "mov	r12, r8\n\t"
-        "adds	r7, r7, r4\n\t"
-        "adcs	r8, r8, r5\n\t"
-        "adcs	r9, r9, r6\n\t"
-        "adcs	r10, r10, %[a]\n\t"
-        "adc	r14, r14, r12\n\t"
-        "str	r4, [%[tmp], #0]\n\t"
-        "str	r5, [%[tmp], #4]\n\t"
-        "str	r6, [%[tmp], #8]\n\t"
-        "str	r7, [%[tmp], #12]\n\t"
-        "str	r8, [%[tmp], #16]\n\t"
-        "str	r9, [%[tmp], #20]\n\t"
-        "# a += mu * m\n\t"
-        "#   += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t"
-        "mov	%[a], #0\n\t"
-        "# a[6] +=        t[0] + t[3]\n\t"
-        "ldr	r3, [%[tmp], #24]\n\t"
-        "adds	r3, r3, r4\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r10, [%[tmp], #24]\n\t"
-        "# a[7] +=        t[1] + t[4]\n\t"
-        "ldr	r3, [%[tmp], #28]\n\t"
-        "adds	r3, r3, r12\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r14, [%[tmp], #28]\n\t"
-        "str	r3, [%[tmp], #32]\n\t"
-        "# a[8] += t[0] + t[2] + t[5]\n\t"
-        "ldr	r3, [%[r], #0]\n\t"
-        "adds	r3, r3, r12\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r4\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r9\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "# a[9]  += t[1] + t[3] + t[6]\n\t"
-        "# a[10] += t[2] + t[4] + t[7]\n\t"
-        "ldr	r3, [%[r], #4]\n\t"
-        "ldr	r4, [%[r], #8]\n\t"
-        "adds	r3, r3, r12\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adcs	r4, r4, r6\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r10\n\t"
-        "adcs	r4, r4, r14\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r3, [%[r], #4]\n\t"
-        "str	r4, [%[r], #8]\n\t"
-        "# a[11] += t[3] + t[5]\n\t"
-        "# a[12] += t[4] + t[6]\n\t"
-        "# a[13] += t[5] + t[7]\n\t"
-        "# a[14] += t[6]\n\t"
-        "ldr	r3, [%[r], #12]\n\t"
-        "ldr	r4, [%[r], #16]\n\t"
-        "ldr	r5, [%[r], #20]\n\t"
-        "ldr	r6, [%[r], #24]\n\t"
-        "adds	r3, r3, r12\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "adcs	r5, r5, #0\n\t"
-        "adcs	r6, r6, #0\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adc	r12, r12, #0\n\t"
-        "adds	r3, r3, r9\n\t"
-        "adcs	r4, r4, r10\n\t"
-        "adcs	r5, r5, r14\n\t"
-        "adcs	r6, r6, #0\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "# a[15] += t[7]\n\t"
-        "ldr	r3, [%[r], #28]\n\t"
-        "adds	r3, r3, r12\n\t"
-        "adc	r12, %[a], #0\n\t"
-        "adds	r3, r3, r14\n\t"
-        "adc	r12, r12, #0\n\t"
-        "str	r3, [%[r], #28]\n\t"
-        "ldr	r3, [%[tmp], #32]\n\t"
-        "ldr	r4, [%[r], #0]\n\t"
-        "ldr	r5, [%[r], #4]\n\t"
-        "ldr	r6, [%[r], #8]\n\t"
-        "ldr	r8, [%[tmp], #0]\n\t"
-        "ldr	r9, [%[tmp], #4]\n\t"
-        "ldr	r10, [%[tmp], #8]\n\t"
-        "ldr	r14, [%[tmp], #12]\n\t"
-        "subs	r3, r3, r8\n\t"
-        "sbcs	r4, r4, r9\n\t"
-        "sbcs	r5, r5, r10\n\t"
-        "sbcs	r6, r6, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "ldr	r3, [%[r], #12]\n\t"
-        "ldr	r4, [%[r], #16]\n\t"
-        "ldr	r5, [%[r], #20]\n\t"
-        "ldr	r6, [%[r], #24]\n\t"
-        "ldr	r7, [%[r], #28]\n\t"
-        "ldr	r8, [%[tmp], #16]\n\t"
-        "ldr	r9, [%[tmp], #20]\n\t"
-        "ldr	r10, [%[tmp], #24]\n\t"
-        "ldr	r14, [%[tmp], #28]\n\t"
-        "sbcs	r3, r3, r8\n\t"
-        "sbcs	r4, r4, r9\n\t"
-        "sbcs	r5, r5, r10\n\t"
-        "sbcs	r6, r6, r14\n\t"
-        "sbc	r7, r7, #0\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "sub	r12, %[a], r12\n\t"
-        "and	%[a], r12, #1\n\t"
-        "ldr	r3, [%[r], #0]\n\t"
-        "ldr	r4, [%[r], #4]\n\t"
-        "ldr	r5, [%[r], #8]\n\t"
-        "ldr	r6, [%[r], #12]\n\t"
-        "ldr	r7, [%[r], #16]\n\t"
-        "ldr	r8, [%[r], #20]\n\t"
-        "ldr	r9, [%[r], #24]\n\t"
-        "ldr	r10, [%[r], #28]\n\t"
-        "subs	r3, r3, r12\n\t"
-        "sbcs	r4, r4, r12\n\t"
-        "sbcs	r5, r5, r12\n\t"
-        "sbcs	r6, r6, #0\n\t"
-        "sbcs	r7, r7, #0\n\t"
-        "sbcs	r8, r8, #0\n\t"
-        "sbcs	r9, r9, %[a]\n\t"
-        "sbc	r10, r10, r12\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "str	r7, [%[r], #16]\n\t"
-        "str	r8, [%[r], #20]\n\t"
-        "str	r9, [%[r], #24]\n\t"
-        "str	r10, [%[r], #28]\n\t"
-        : [a] "+r" (a)
-        : [r] "r" (r), [tmp] "r" (tmp)
-        : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7", "r12"
-    );
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_8(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_8(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_8(r, r, m, mp);
-}
-
-#else
-/* Mod-2 for the P256 curve. */
-static const uint32_t p256_mod_2[8] = {
-    0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,
-    0x00000001,0xffffffff
-};
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 8);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 8);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 8;
-    sp_digit* t3 = td + 4 * 8;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_8(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_8(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_8(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_8(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_8(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_8(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_8(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_8(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_8(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_8(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_8(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_8(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_8(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*8;
-    int32_t n;
-
-    sp_256_mont_inv_8(t1, p->z, t + 2*8);
-
-    sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 8, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_8(r->x, p256_mod);
-    sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_8(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 8, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_8(r->y, p256_mod);
-    sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_8(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #32\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "mov	r4, #0\n\t"
-        "adc	%[c], r4, #0\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a], #0]\n\t"
-        "ldr	r5, [%[a], #4]\n\t"
-        "ldr	r6, [%[a], #8]\n\t"
-        "ldr	r7, [%[a], #12]\n\t"
-        "ldr	r8, [%[b], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "ldr	r10, [%[b], #8]\n\t"
-        "ldr	r14, [%[b], #12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #0]\n\t"
-        "str	r5, [%[r], #4]\n\t"
-        "str	r6, [%[r], #8]\n\t"
-        "str	r7, [%[r], #12]\n\t"
-        "ldr	r4, [%[a], #16]\n\t"
-        "ldr	r5, [%[a], #20]\n\t"
-        "ldr	r6, [%[a], #24]\n\t"
-        "ldr	r7, [%[a], #28]\n\t"
-        "ldr	r8, [%[b], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "ldr	r10, [%[b], #24]\n\t"
-        "ldr	r14, [%[b], #28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "str	r6, [%[r], #24]\n\t"
-        "str	r7, [%[r], #28]\n\t"
-        "adc	%[c], r12, r12\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Add two Montgomery form numbers (r = a + b % m).
- *
- * r   Result of addition.
- * a   First number to add in Montogmery form.
- * b   Second number to add in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_add_8(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a],#0]\n\t"
-        "ldr	r5, [%[a],#4]\n\t"
-        "ldr	r6, [%[a],#8]\n\t"
-        "ldr	r7, [%[a],#12]\n\t"
-        "ldr	r8, [%[b],#0]\n\t"
-        "ldr	r9, [%[b],#4]\n\t"
-        "ldr	r10, [%[b],#8]\n\t"
-        "ldr	r14, [%[b],#12]\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "str	r4, [%[r],#0]\n\t"
-        "str	r5, [%[r],#4]\n\t"
-        "str	r6, [%[r],#8]\n\t"
-        "str	r7, [%[r],#12]\n\t"
-        "ldr	r4, [%[a],#16]\n\t"
-        "ldr	r5, [%[a],#20]\n\t"
-        "ldr	r6, [%[a],#24]\n\t"
-        "ldr	r7, [%[a],#28]\n\t"
-        "ldr	r8, [%[b],#16]\n\t"
-        "ldr	r9, [%[b],#20]\n\t"
-        "ldr	r10, [%[b],#24]\n\t"
-        "ldr	r14, [%[b],#28]\n\t"
-        "adcs	r4, r4, r8\n\t"
-        "adcs	r5, r5, r9\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "adcs	r7, r7, r14\n\t"
-        "adc	r3, r12, #0\n\t"
-        "sub	r3, r12, r3\n\t"
-        "and	r12, r3, #1\n\t"
-        "ldr	r8, [%[r],#0]\n\t"
-        "ldr	r9, [%[r],#4]\n\t"
-        "ldr	r10, [%[r],#8]\n\t"
-        "ldr	r14, [%[r],#12]\n\t"
-        "subs	r8, r8, r3\n\t"
-        "sbcs	r9, r9, r3\n\t"
-        "sbcs	r10, r10, r3\n\t"
-        "sbcs	r14, r14, #0\n\t"
-        "sbcs	r4, r4, #0\n\t"
-        "sbcs	r5, r5, #0\n\t"
-        "sbcs	r6, r6, r12\n\t"
-        "sbc	r7, r7, r3\n\t"
-        "str	r8, [%[r],#0]\n\t"
-        "str	r9, [%[r],#4]\n\t"
-        "str	r10, [%[r],#8]\n\t"
-        "str	r14, [%[r],#12]\n\t"
-        "str	r4, [%[r],#16]\n\t"
-        "str	r5, [%[r],#20]\n\t"
-        "str	r6, [%[r],#24]\n\t"
-        "str	r7, [%[r],#28]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12"
-    );
-}
-
-/* Double a Montgomery form number (r = a + a % m).
- *
- * r   Result of doubling.
- * a   Number to double in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_dbl_8(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a],#0]\n\t"
-        "ldr	r5, [%[a],#4]\n\t"
-        "ldr	r6, [%[a],#8]\n\t"
-        "ldr	r7, [%[a],#12]\n\t"
-        "ldr	r8, [%[a],#16]\n\t"
-        "ldr	r9, [%[a],#20]\n\t"
-        "ldr	r10, [%[a],#24]\n\t"
-        "ldr	r14, [%[a],#28]\n\t"
-        "adds	r4, r4, r4\n\t"
-        "adcs	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adcs	r7, r7, r7\n\t"
-        "adcs	r8, r8, r8\n\t"
-        "adcs	r9, r9, r9\n\t"
-        "adcs	r10, r10, r10\n\t"
-        "adcs	r14, r14, r14\n\t"
-        "adc	r3, r12, #0\n\t"
-        "sub	r3, r12, r3\n\t"
-        "and	r12, r3, #1\n\t"
-        "subs	r4, r4, r3\n\t"
-        "sbcs	r5, r5, r3\n\t"
-        "sbcs	r6, r6, r3\n\t"
-        "sbcs	r7, r7, #0\n\t"
-        "sbcs	r8, r8, #0\n\t"
-        "sbcs	r9, r9, #0\n\t"
-        "sbcs	r10, r10, r12\n\t"
-        "sbc	r14, r14, r3\n\t"
-        "str	r4, [%[r],#0]\n\t"
-        "str	r5, [%[r],#4]\n\t"
-        "str	r6, [%[r],#8]\n\t"
-        "str	r7, [%[r],#12]\n\t"
-        "str	r8, [%[r],#16]\n\t"
-        "str	r9, [%[r],#20]\n\t"
-        "str	r10, [%[r],#24]\n\t"
-        "str	r14, [%[r],#28]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12"
-    );
-}
-
-/* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r   Result of Tripling.
- * a   Number to triple in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_tpl_8(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a],#0]\n\t"
-        "ldr	r5, [%[a],#4]\n\t"
-        "ldr	r6, [%[a],#8]\n\t"
-        "ldr	r7, [%[a],#12]\n\t"
-        "ldr	r8, [%[a],#16]\n\t"
-        "ldr	r9, [%[a],#20]\n\t"
-        "ldr	r10, [%[a],#24]\n\t"
-        "ldr	r14, [%[a],#28]\n\t"
-        "adds	r4, r4, r4\n\t"
-        "adcs	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adcs	r7, r7, r7\n\t"
-        "adcs	r8, r8, r8\n\t"
-        "adcs	r9, r9, r9\n\t"
-        "adcs	r10, r10, r10\n\t"
-        "adcs	r14, r14, r14\n\t"
-        "adc	r3, r12, #0\n\t"
-        "sub	r3, r12, r3\n\t"
-        "and	r12, r3, #1\n\t"
-        "subs	r4, r4, r3\n\t"
-        "sbcs	r5, r5, r3\n\t"
-        "sbcs	r6, r6, r3\n\t"
-        "sbcs	r7, r7, #0\n\t"
-        "sbcs	r8, r8, #0\n\t"
-        "sbcs	r9, r9, #0\n\t"
-        "sbcs	r10, r10, r12\n\t"
-        "sbc	r14, r14, r3\n\t"
-        "str	r8, [%[r],#16]\n\t"
-        "str	r9, [%[r],#20]\n\t"
-        "str	r10, [%[r],#24]\n\t"
-        "str	r14, [%[r],#28]\n\t"
-        "mov	r12, #0\n\t"
-        "ldr	r8, [%[a],#0]\n\t"
-        "ldr	r9, [%[a],#4]\n\t"
-        "ldr	r10, [%[a],#8]\n\t"
-        "ldr	r14, [%[a],#12]\n\t"
-        "adds	r8, r8, r4\n\t"
-        "adcs	r9, r9, r5\n\t"
-        "adcs	r10, r10, r6\n\t"
-        "adcs	r14, r14, r7\n\t"
-        "str	r8, [%[r],#0]\n\t"
-        "str	r9, [%[r],#4]\n\t"
-        "str	r10, [%[r],#8]\n\t"
-        "str	r14, [%[r],#12]\n\t"
-        "ldr	r8, [%[a],#16]\n\t"
-        "ldr	r9, [%[a],#20]\n\t"
-        "ldr	r10, [%[a],#24]\n\t"
-        "ldr	r14, [%[a],#28]\n\t"
-        "ldr	r4, [%[r],#16]\n\t"
-        "ldr	r5, [%[r],#20]\n\t"
-        "ldr	r6, [%[r],#24]\n\t"
-        "ldr	r7, [%[r],#28]\n\t"
-        "adcs	r8, r8, r4\n\t"
-        "adcs	r9, r9, r5\n\t"
-        "adcs	r10, r10, r6\n\t"
-        "adcs	r14, r14, r7\n\t"
-        "adc	r3, r12, #0\n\t"
-        "sub	r3, r12, r3\n\t"
-        "and	r12, r3, #1\n\t"
-        "ldr	r4, [%[r],#0]\n\t"
-        "ldr	r5, [%[r],#4]\n\t"
-        "ldr	r6, [%[r],#8]\n\t"
-        "ldr	r7, [%[r],#12]\n\t"
-        "subs	r4, r4, r3\n\t"
-        "sbcs	r5, r5, r3\n\t"
-        "sbcs	r6, r6, r3\n\t"
-        "sbcs	r7, r7, #0\n\t"
-        "sbcs	r8, r8, #0\n\t"
-        "sbcs	r9, r9, #0\n\t"
-        "sbcs	r10, r10, r12\n\t"
-        "sbc	r14, r14, r3\n\t"
-        "str	r4, [%[r],#0]\n\t"
-        "str	r5, [%[r],#4]\n\t"
-        "str	r6, [%[r],#8]\n\t"
-        "str	r7, [%[r],#12]\n\t"
-        "str	r8, [%[r],#16]\n\t"
-        "str	r9, [%[r],#20]\n\t"
-        "str	r10, [%[r],#24]\n\t"
-        "str	r14, [%[r],#28]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12"
-    );
-}
-
-/* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r   Result of subtration.
- * a   Number to subtract from in Montogmery form.
- * b   Number to subtract with in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_sub_8(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    (void)m;
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "ldr	r4, [%[a],#0]\n\t"
-        "ldr	r5, [%[a],#4]\n\t"
-        "ldr	r6, [%[a],#8]\n\t"
-        "ldr	r7, [%[a],#12]\n\t"
-        "ldr	r8, [%[b],#0]\n\t"
-        "ldr	r9, [%[b],#4]\n\t"
-        "ldr	r10, [%[b],#8]\n\t"
-        "ldr	r14, [%[b],#12]\n\t"
-        "subs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "sbcs	r7, r7, r14\n\t"
-        "str	r4, [%[r],#0]\n\t"
-        "str	r5, [%[r],#4]\n\t"
-        "str	r6, [%[r],#8]\n\t"
-        "str	r7, [%[r],#12]\n\t"
-        "ldr	r4, [%[a],#16]\n\t"
-        "ldr	r5, [%[a],#20]\n\t"
-        "ldr	r6, [%[a],#24]\n\t"
-        "ldr	r7, [%[a],#28]\n\t"
-        "ldr	r8, [%[b],#16]\n\t"
-        "ldr	r9, [%[b],#20]\n\t"
-        "ldr	r10, [%[b],#24]\n\t"
-        "ldr	r14, [%[b],#28]\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "sbcs	r7, r7, r14\n\t"
-        "sbc	r3, r12, #0\n\t"
-        "and	r12, r3, #1\n\t"
-        "ldr	r8, [%[r],#0]\n\t"
-        "ldr	r9, [%[r],#4]\n\t"
-        "ldr	r10, [%[r],#8]\n\t"
-        "ldr	r14, [%[r],#12]\n\t"
-        "adds	r8, r8, r3\n\t"
-        "adcs	r9, r9, r3\n\t"
-        "adcs	r10, r10, r3\n\t"
-        "adcs	r14, r14, #0\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "adcs	r5, r5, #0\n\t"
-        "adcs	r6, r6, r12\n\t"
-        "adc	r7, r7, r3\n\t"
-        "str	r8, [%[r],#0]\n\t"
-        "str	r9, [%[r],#4]\n\t"
-        "str	r10, [%[r],#8]\n\t"
-        "str	r14, [%[r],#12]\n\t"
-        "str	r4, [%[r],#16]\n\t"
-        "str	r5, [%[r],#20]\n\t"
-        "str	r6, [%[r],#24]\n\t"
-        "str	r7, [%[r],#28]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12"
-    );
-}
-
-/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r  Result of division by 2.
- * a  Number to divide.
- * m  Modulus (prime).
- */
-static void sp_256_div2_8(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "ldr	r3, [%[a], #0]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "and	r9, r3, #1\n\t"
-        "sub	r7, r10, r9\n\t"
-        "and	r8, r7, #1\n\t"
-        "adds	r3, r3, r7\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r3, [%[a], #16]\n\t"
-        "ldr	r4, [%[a], #20]\n\t"
-        "ldr	r5, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "adcs	r3, r3, r10\n\t"
-        "adcs	r4, r4, r10\n\t"
-        "adcs	r5, r5, r8\n\t"
-        "adcs	r6, r6, r7\n\t"
-        "adc	r9, r10, r10\n\t"
-        "lsr	r7, r3, #1\n\t"
-        "and	r3, r3, #1\n\t"
-        "lsr	r8, r4, #1\n\t"
-        "lsr	r10, r5, #1\n\t"
-        "lsr	r14, r6, #1\n\t"
-        "orr	r7, r7, r4, lsl #31\n\t"
-        "orr	r8, r8, r5, lsl #31\n\t"
-        "orr	r10, r10, r6, lsl #31\n\t"
-        "orr	r14, r14, r9, lsl #31\n\t"
-        "mov	r9, r3\n\t"
-        "str	r7, [%[r], #16]\n\t"
-        "str	r8, [%[r], #20]\n\t"
-        "str	r10, [%[r], #24]\n\t"
-        "str	r14, [%[r], #28]\n\t"
-        "ldr	r3, [%[r], #0]\n\t"
-        "ldr	r4, [%[r], #4]\n\t"
-        "ldr	r5, [%[r], #8]\n\t"
-        "ldr	r6, [%[r], #12]\n\t"
-        "lsr	r7, r3, #1\n\t"
-        "lsr	r8, r4, #1\n\t"
-        "lsr	r10, r5, #1\n\t"
-        "lsr	r14, r6, #1\n\t"
-        "orr	r7, r7, r4, lsl #31\n\t"
-        "orr	r8, r8, r5, lsl #31\n\t"
-        "orr	r10, r10, r6, lsl #31\n\t"
-        "orr	r14, r14, r9, lsl #31\n\t"
-        "str	r7, [%[r], #0]\n\t"
-        "str	r8, [%[r], #4]\n\t"
-        "str	r10, [%[r], #8]\n\t"
-        "str	r14, [%[r], #12]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [m] "r" (m)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r10", "r14", "r9"
-    );
-
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*8;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<8; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<8; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<8; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_8(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_8(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_8(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_8(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_8(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_8(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_8(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_8(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_8(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_8(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_8(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_8(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_8(y, y, t2, p256_mod);
-
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	r12, %[a], #32\n\t"
-        "\n1:\n\t"
-        "rsbs	%[c], %[c], #0\n\t"
-        "ldr	r4, [%[a]], #4\n\t"
-        "ldr	r5, [%[a]], #4\n\t"
-        "ldr	r6, [%[a]], #4\n\t"
-        "ldr	r7, [%[a]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "ldr	r14, [%[b]], #4\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "sbcs	r7, r7, r14\n\t"
-        "str	r4, [%[r]], #4\n\t"
-        "str	r5, [%[r]], #4\n\t"
-        "str	r6, [%[r]], #4\n\t"
-        "str	r7, [%[r]], #4\n\t"
-        "sbc	%[c], r4, r4\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    return c;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r3, [%[a], #0]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b], #0]\n\t"
-        "ldr	r8, [%[b], #4]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "ldr	r10, [%[b], #12]\n\t"
-        "subs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #0]\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "str	r6, [%[r], #12]\n\t"
-        "ldr	r3, [%[a], #16]\n\t"
-        "ldr	r4, [%[a], #20]\n\t"
-        "ldr	r5, [%[a], #24]\n\t"
-        "ldr	r6, [%[a], #28]\n\t"
-        "ldr	r7, [%[b], #16]\n\t"
-        "ldr	r8, [%[b], #20]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "ldr	r10, [%[b], #28]\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[r], #16]\n\t"
-        "str	r4, [%[r], #20]\n\t"
-        "str	r5, [%[r], #24]\n\t"
-        "str	r6, [%[r], #28]\n\t"
-        "sbc	%[c], %[c], #0\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a  First number to compare.
- * b  Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
-static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b)
-{
-    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
-            (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0;
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*8;
-    sp_digit* t3 = t + 4*8;
-    sp_digit* t4 = t + 6*8;
-    sp_digit* t5 = t + 8*8;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_8(t1, p256_mod, q->y);
-    sp_256_norm_8(t1);
-    if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) &
-        (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) {
-        sp_256_proj_point_dbl_8(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<8; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<8; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<8; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_8(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_8(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_8(x, x, t5, p256_mod);
-        sp_256_mont_dbl_8(t1, y, p256_mod);
-        sp_256_mont_sub_8(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_8(y, y, x, p256_mod);
-        sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_8(y, y, t5, p256_mod);
-    }
-}
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_fast_8(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[16];
-    sp_point rtd;
-    sp_digit tmpd[2 * 8 * 5];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod);
-        sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod);
-        sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod);
-        t[1].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp);
-        t[ 2].infinity = 0;
-        sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp);
-        t[ 3].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp);
-        t[ 4].infinity = 0;
-        sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp);
-        t[ 5].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp);
-        t[ 6].infinity = 0;
-        sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp);
-        t[ 7].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp);
-        t[ 8].infinity = 0;
-        sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp);
-        t[ 9].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp);
-        t[10].infinity = 0;
-        sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp);
-        t[11].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp);
-        t[12].infinity = 0;
-        sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp);
-        t[13].infinity = 0;
-        sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp);
-        t[14].infinity = 0;
-        sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp);
-        t[15].infinity = 0;
-
-        i = 6;
-        n = k[i+1] << 0;
-        c = 28;
-        y = n >> 28;
-        XMEMCPY(rt, &t[y], sizeof(sp_point));
-        n <<= 4;
-        for (; i>=0 || c>=4; ) {
-            if (c < 4) {
-                n |= k[i--] << (0 - c);
-                c += 32;
-            }
-            y = (n >> 28) & 0xf;
-            n <<= 4;
-            c -= 4;
-
-            sp_256_proj_point_dbl_8(rt, rt, tmp);
-            sp_256_proj_point_dbl_8(rt, rt, tmp);
-            sp_256_proj_point_dbl_8(rt, rt, tmp);
-            sp_256_proj_point_dbl_8(rt, rt, tmp);
-
-            sp_256_proj_point_add_8(rt, rt, &t[y], tmp);
-        }
-
-        if (map)
-            sp_256_map_8(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 16);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(rt, 1, heap);
-
-    return err;
-}
-
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry {
-    sp_digit x[8];
-    sp_digit y[8];
-    byte infinity;
-} sp_table_entry;
-
-#ifdef FP_ECC
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_8(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*8;
-    sp_digit* b = t + 4*8;
-    sp_digit* t1 = t + 6*8;
-    sp_digit* t2 = t + 8*8;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<8; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<8; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<8; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_8(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_8(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_8(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_8(t1, b, p256_mod);
-        sp_256_mont_sub_8(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_8(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_8(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_8(y, b, x, p256_mod);
-        sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_8(y, y, p256_mod);
-        sp_256_mont_sub_8(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_8(y, y, p256_mod);
-}
-
-#endif /* FP_ECC */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_8(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*8;
-    sp_digit* t3 = t + 4*8;
-    sp_digit* t4 = t + 6*8;
-    sp_digit* t5 = t + 8*8;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_8(t1, p256_mod, q->y);
-    sp_256_norm_8(t1);
-    if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) &
-        (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) {
-        sp_256_proj_point_dbl_8(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<8; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<8; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<8; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_8(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_8(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_8(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_8(t1, t3, p256_mod);
-        sp_256_mont_sub_8(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_8(t3, t3, x, p256_mod);
-        sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_8(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef WOLFSSL_SP_SMALL
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_8(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 8;
-    sp_digit* tmp = t + 4 * 8;
-
-    sp_256_mont_inv_8(t1, a->z, tmp);
-
-    sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_8(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_8(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<4; i++) {
-            sp_256_proj_point_dbl_n_8(t, t, 64, tmp);
-            sp_256_proj_to_affine_8(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<4; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
-                sp_256_proj_to_affine_8(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 8 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=63; j<4; j++,x+=32)
-            y |= ((k[x / 32] >> (x % 32)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=62; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<4; j++,x+=64)
-                y |= ((k[x / 32] >> (x % 32)) & 1) << j;
-
-            sp_256_proj_point_dbl_8(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_8(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_8(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[8];
-    sp_digit y[8];
-    sp_table_entry table[16];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_8(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_8(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 8 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#else
-#ifdef FP_ECC
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_8(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_8(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_8(t, t, 32, tmp);
-            sp_256_proj_to_affine_8(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_8(t, s1, s2, tmp);
-                sp_256_proj_to_affine_8(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 8 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 32] >> (x % 32)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 32] >> (x % 32)) & 1) << j;
-
-            sp_256_proj_point_dbl_8(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_8(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_8(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[8];
-    sp_digit y[8];
-    sp_table_entry table[256];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_8(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_8(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 8 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_8(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * p     Point to multiply.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[8];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 8, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 8, km);
-        sp_256_point_from_ecc_point_8(point, gm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_8(point, point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_8(point, point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_8(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#ifdef WOLFSSL_SP_SMALL
-static sp_table_entry p256_table[16] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
-        0xa53755c6,0x18905f76 },
-      { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
-        0x25885d85,0x8571ff18 },
-      0 },
-    /* 2 */
-    { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
-        0xfd1b667f,0x2f5e6961 },
-      { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
-        0x8d6f0f7b,0xf648f916 },
-      0 },
-    /* 3 */
-    { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
-        0x133d0015,0x5abe0285 },
-      { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
-        0x6b6f7383,0x94bb725b },
-      0 },
-    /* 4 */
-    { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
-        0x21d324f6,0x61d587d4 },
-      { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
-        0x4621efbe,0xfa11fe12 },
-      0 },
-    /* 5 */
-    { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
-        0x1f13bedc,0x586eb04c },
-      { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
-        0x70864f11,0x19d5ac08 },
-      0 },
-    /* 6 */
-    { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
-        0xc3b266b1,0xbb6de651 },
-      { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
-        0x5d18b99b,0x60b4619a },
-      0 },
-    /* 7 */
-    { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
-        0xaeebffcd,0x9d0f27b2 },
-      { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
-        0x356ec48d,0x244a566d },
-      0 },
-    /* 8 */
-    { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
-        0xcd42ab1b,0x803f3e02 },
-      { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
-        0x5067adc1,0xc097440e },
-      0 },
-    /* 9 */
-    { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
-        0x915f1f30,0xf1af32d5 },
-      { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
-        0xe2d41c8b,0x23d0f130 },
-      0 },
-    /* 10 */
-    { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
-        0x7990216a,0x50bbb4d9 },
-      { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
-        0x01fe49c3,0x2b100118 },
-      0 },
-    /* 11 */
-    { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
-        0x83fbae0c,0xdd558999 },
-      { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
-        0x149d6041,0xe6e4c551 },
-      0 },
-    /* 12 */
-    { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
-        0xdb7e63af,0xfad27148 },
-      { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
-        0x9f0e1a84,0x77387de3 },
-      0 },
-    /* 13 */
-    { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
-        0xbef0c47e,0xb37b85c0 },
-      { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
-        0xf9f628d5,0x9c135ac8 },
-      0 },
-    /* 14 */
-    { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
-        0x91ece900,0xc109f9cb },
-      { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
-        0x2eee1ee1,0x9bc3344f },
-      0 },
-    /* 15 */
-    { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
-        0x5f1a4cc1,0x29591d52 },
-      { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
-        0x18ef332c,0x6376551f },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#else
-static sp_table_entry p256_table[256] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b,
-        0xa53755c6,0x18905f76 },
-      { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688,
-        0x25885d85,0x8571ff18 },
-      0 },
-    /* 2 */
-    { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca,
-        0xdbdf58e9,0xd953c50d },
-      { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110,
-        0x9eb288f3,0x863ebb7e },
-      0 },
-    /* 3 */
-    { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954,
-        0xb5ff80a0,0x00076055 },
-      { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39,
-        0x34373ee0,0x83087761 },
-      0 },
-    /* 4 */
-    { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a,
-        0xfd1b667f,0x2f5e6961 },
-      { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37,
-        0x8d6f0f7b,0xf648f916 },
-      0 },
-    /* 5 */
-    { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761,
-        0x133d0015,0x5abe0285 },
-      { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562,
-        0x6b6f7383,0x94bb725b },
-      0 },
-    /* 6 */
-    { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129,
-        0x2f7dc4ef,0xcdd6bbcb },
-      { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792,
-        0x4bdae5f6,0xa361bebd },
-      0 },
-    /* 7 */
-    { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec,
-        0xc4b5292c,0xba12ca09 },
-      { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089,
-        0x701fef4b,0x53ebb99d },
-      0 },
-    /* 8 */
-    { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334,
-        0x06d54831,0x8589fb92 },
-      { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507,
-        0x02541c4f,0xebb0696d },
-      0 },
-    /* 9 */
-    { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3,
-        0xd1b27da3,0xeb2820cb },
-      { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42,
-        0x55a7da1d,0x1f28289b },
-      0 },
-    /* 10 */
-    { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862,
-        0x05e54d63,0x337a4b59 },
-      { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781,
-        0xf4c2fbd6,0x0d65e0d5 },
-      0 },
-    /* 11 */
-    { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4,
-        0x52f4a232,0xc23da242 },
-      { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86,
-        0xc790cff1,0x19de3b8c },
-      0 },
-    /* 12 */
-    { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586,
-        0x91fccbfd,0xe34dcbd4 },
-      { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127,
-        0x7b4e0f7f,0xe7641f44 },
-      0 },
-    /* 13 */
-    { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6,
-        0x052a57bf,0x4a12df57 },
-      { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa,
-        0xbb5bea46,0x6af5aa93 },
-      0 },
-    /* 14 */
-    { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4,
-        0x66a44013,0x5fe3475a },
-      { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae,
-        0xecfea916,0xb544e308 },
-      0 },
-    /* 15 */
-    { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76,
-        0xa6b0c20b,0xe0b6b2bd },
-      { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad,
-        0x25a63774,0x71c023de },
-      0 },
-    /* 16 */
-    { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5,
-        0x21d324f6,0x61d587d4 },
-      { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e,
-        0x4621efbe,0xfa11fe12 },
-      0 },
-    /* 17 */
-    { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67,
-        0x1f13bedc,0x586eb04c },
-      { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0,
-        0x70864f11,0x19d5ac08 },
-      0 },
-    /* 18 */
-    { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b,
-        0x7f9c563f,0xe7c0073f },
-      { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a,
-        0xc65b3c0a,0xe08504fe },
-      0 },
-    /* 19 */
-    { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa,
-        0x5b0996b4,0x78f01882 },
-      { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877,
-        0x7e94747a,0x43a773b8 },
-      0 },
-    /* 20 */
-    { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a,
-        0xc3b266b1,0xbb6de651 },
-      { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1,
-        0x5d18b99b,0x60b4619a },
-      0 },
-    /* 21 */
-    { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014,
-        0xaeebffcd,0x9d0f27b2 },
-      { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0,
-        0x356ec48d,0x244a566d },
-      0 },
-    /* 22 */
-    { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b,
-        0x3581ef69,0x45e58c87 },
-      { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2,
-        0xc1e4b7a4,0xc040e21c },
-      0 },
-    /* 23 */
-    { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576,
-        0x682c6ec7,0x1cdf5c97 },
-      { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1,
-        0xa92dff3d,0x046755f8 },
-      0 },
-    /* 24 */
-    { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172,
-        0x3b83a5f3,0x046e5e11 },
-      { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6,
-        0x303d005b,0x6e0106c3 },
-      0 },
-    /* 25 */
-    { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8,
-        0xe901cf1f,0x442594ed },
-      { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1,
-        0x4c2ee68e,0xa796fa51 },
-      0 },
-    /* 26 */
-    { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e,
-        0xc69766e9,0xe4ad2da9 },
-      { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4,
-        0xc37b5143,0xc5e94046 },
-      0 },
-    /* 27 */
-    { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0,
-        0xdb464747,0x63283daf },
-      { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad,
-        0x1981a938,0x68bd19ab },
-      0 },
-    /* 28 */
-    { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981,
-        0x3c6fdfd6,0x495292f5 },
-      { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2,
-        0x26036837,0x0ec7530d },
-      0 },
-    /* 29 */
-    { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5,
-        0x64863f0b,0x0f6207a6 },
-      { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407,
-        0x08ed6dcf,0xff0db072 },
-      0 },
-    /* 30 */
-    { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317,
-        0x88740ea3,0x313b513c },
-      { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd,
-        0x86f19f81,0x2d3abcf9 },
-      0 },
-    /* 31 */
-    { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f,
-        0xded98cdf,0xc036fa10 },
-      { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277,
-        0xb6d40194,0xa6b2a2c4 },
-      0 },
-    /* 32 */
-    { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac,
-        0xaf7c9860,0x810ee252 },
-      { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74,
-        0x92731745,0xd485717a },
-      0 },
-    /* 33 */
-    { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb,
-        0x2f9a604e,0x6a6045a7 },
-      { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73,
-        0xf9e15790,0xd3e45cfa },
-      0 },
-    /* 34 */
-    { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54,
-        0xe3c2c19c,0x207755de },
-      { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6,
-        0x7154b00d,0x48dc5ee5 },
-      0 },
-    /* 35 */
-    { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe,
-        0xdff6f445,0xf2fb0aed },
-      { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad,
-        0xdb28d525,0xa13e9015 },
-      0 },
-    /* 36 */
-    { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241,
-        0x1497526f,0x2bf0d6b0 },
-      { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f,
-        0x162fe89f,0x42a94a5a },
-      0 },
-    /* 37 */
-    { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050,
-        0xc65ede3d,0x2c2dd969 },
-      { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706,
-        0x42c56dbc,0xf437fa1f },
-      0 },
-    /* 38 */
-    { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050,
-        0x54707aa8,0xaaf45b33 },
-      { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681,
-        0xf4f272bc,0xcdf6310d },
-      0 },
-    /* 39 */
-    { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772,
-        0xda9e2ff2,0xf0d008ba },
-      { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d,
-        0xca887b8b,0x5bd5c2f5 },
-      0 },
-    /* 40 */
-    { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e,
-        0xa09e4719,0xaa12dfc8 },
-      { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73,
-        0xe48ca901,0x6c036e73 },
-      0 },
-    /* 41 */
-    { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b,
-        0x96afbe24,0x292ff658 },
-      { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f,
-        0x311b7276,0x644e0c90 },
-      0 },
-    /* 42 */
-    { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87,
-        0xcab79a77,0xf25ae793 },
-      { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3,
-        0x13db0a3e,0x39b8e653 },
-      0 },
-    /* 43 */
-    { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a,
-        0x0f19db06,0x39122f2f },
-      { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2,
-        0xce80ff8d,0x8de80af8 },
-      0 },
-    /* 44 */
-    { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b,
-        0x2e368c04,0x87194906 },
-      { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a,
-        0x5b74fde1,0xfc315e6a },
-      0 },
-    /* 45 */
-    { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b,
-        0xee389088,0xe6d4a7ad },
-      { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93,
-        0x9be2ae57,0x35dfaf9a },
-      0 },
-    /* 46 */
-    { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41,
-        0x1c830d2b,0x1da5c7d7 },
-      { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7,
-        0xdbf4b9d6,0x7077c0fd },
-      0 },
-    /* 47 */
-    { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140,
-        0xe50efe44,0x53a8632e },
-      { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3,
-        0x34e1fcc1,0x028ca76d },
-      0 },
-    /* 48 */
-    { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117,
-        0x6962f046,0x04c17cd8 },
-      { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6,
-        0xfed97474,0xf7ba4de9 },
-      0 },
-    /* 49 */
-    { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553,
-        0x52131c41,0xe31f9600 },
-      { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac,
-        0xce34d47b,0xaa3a6259 },
-      0 },
-    /* 50 */
-    { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa,
-        0x7e79daee,0x2398dd62 },
-      { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377,
-        0x1c046210,0x5717f5b2 },
-      0 },
-    /* 51 */
-    { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239,
-        0x0e3c28de,0x660a2c56 },
-      { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481,
-        0x4f522453,0x624ee54c },
-      0 },
-    /* 52 */
-    { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423,
-        0x92bdfbc0,0x4f392afb },
-      { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803,
-        0xccdb399c,0x8a3e7977 },
-      0 },
-    /* 53 */
-    { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de,
-        0x70c24404,0x3888d023 },
-      { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8,
-        0x18102336,0xa5e62e47 },
-      0 },
-    /* 54 */
-    { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7,
-        0x466a5adc,0x2c4768e6 },
-      { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064,
-        0xf9e652a0,0x7b5e6441 },
-      0 },
-    /* 55 */
-    { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5,
-        0x0c8d744a,0xb8af73cb },
-      { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f,
-        0x7f3f0895,0xa036395f },
-      0 },
-    /* 56 */
-    { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682,
-        0x875fb533,0x4be36b01 },
-      { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05,
-        0x1bdc00c0,0x8cbc9a87 },
-      0 },
-    /* 57 */
-    { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c,
-        0x0c0835f8,0x44e7553e },
-      { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276,
-        0x5eb8fc18,0x470a683a },
-      0 },
-    /* 58 */
-    { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee,
-        0xc63dc6ef,0x16410690 },
-      { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72,
-        0x7abcbb4f,0xd73479fd },
-      0 },
-    /* 59 */
-    { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1,
-        0x0771666b,0x816469e3 },
-      { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb,
-        0xf0dd3f9c,0x0a36dd23 },
-      0 },
-    /* 60 */
-    { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad,
-        0xfdbab118,0xe331dfd6 },
-      { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7,
-        0x492e3389,0xd3b4782a },
-      0 },
-    /* 61 */
-    { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953,
-        0x4c86a5bd,0x7281275a },
-      { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a,
-        0xce145059,0x2c062e7e },
-      0 },
-    /* 62 */
-    { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288,
-        0x2c4e7ef1,0x282a35f9 },
-      { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38,
-        0x554d2abd,0xc71cd513 },
-      0 },
-    /* 63 */
-    { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7,
-        0xcf47f3a3,0xc50f6740 },
-      { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222,
-        0x212958dc,0xb9ecb3a7 },
-      0 },
-    /* 64 */
-    { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e,
-        0xcd42ab1b,0x803f3e02 },
-      { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273,
-        0x5067adc1,0xc097440e },
-      0 },
-    /* 65 */
-    { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459,
-        0x915f1f30,0xf1af32d5 },
-      { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418,
-        0xe2d41c8b,0x23d0f130 },
-      0 },
-    /* 66 */
-    { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648,
-        0xc0a3fadd,0xb0288dd6 },
-      { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7,
-        0xf408c8d2,0xffd3724f },
-      0 },
-    /* 67 */
-    { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b,
-        0xd78c26df,0xf5590f4a },
-      { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f,
-        0xf6f74a20,0x18d6da54 },
-      0 },
-    /* 68 */
-    { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926,
-        0x7990216a,0x50bbb4d9 },
-      { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b,
-        0x01fe49c3,0x2b100118 },
-      0 },
-    /* 69 */
-    { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa,
-        0x83fbae0c,0xdd558999 },
-      { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf,
-        0x149d6041,0xe6e4c551 },
-      0 },
-    /* 70 */
-    { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b,
-        0x07ed56ff,0x51e00db1 },
-      { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5,
-        0x49829177,0xe22f4241 },
-      0 },
-    /* 71 */
-    { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f,
-        0x52dc48c9,0xf709373d },
-      { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a,
-        0xe7275b11,0xbd52d288 },
-      0 },
-    /* 72 */
-    { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e,
-        0xc8aa77a6,0xa0d0f8e4 },
-      { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8,
-        0x946d6a00,0xa56c78c7 },
-      0 },
-    /* 73 */
-    { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f,
-        0x731a367a,0xd8befdf8 },
-      { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40,
-        0xce9f6478,0x854a68a5 },
-      0 },
-    /* 74 */
-    { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b,
-        0x98846a95,0x5cacea0b },
-      { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8,
-        0x35e4efa9,0xe4982d12 },
-      0 },
-    /* 75 */
-    { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa,
-        0x16b20499,0x8046b7f6 },
-      { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea,
-        0x9082af55,0xeb17ca7b },
-      0 },
-    /* 76 */
-    { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565,
-        0xfab5e131,0x097b00ba },
-      { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11,
-        0xafdbcc9e,0xf95c747b },
-      0 },
-    /* 77 */
-    { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1,
-        0x566ed837,0x3512601e },
-      { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2,
-        0x6068ab6b,0x0ef97123 },
-      0 },
-    /* 78 */
-    { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74,
-        0x3b4fbc95,0xfc16d933 },
-      { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497,
-        0xb95d7a17,0x14ca4af1 },
-      0 },
-    /* 79 */
-    { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7,
-        0xf59c231d,0x4057b063 },
-      { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae,
-        0xf1330b13,0x1c3b5d64 },
-      0 },
-    /* 80 */
-    { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07,
-        0xdb7e63af,0xfad27148 },
-      { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875,
-        0x9f0e1a84,0x77387de3 },
-      0 },
-    /* 81 */
-    { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408,
-        0xbef0c47e,0xb37b85c0 },
-      { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa,
-        0xf9f628d5,0x9c135ac8 },
-      0 },
-    /* 82 */
-    { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176,
-        0xc433851f,0x5721361f },
-      { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e,
-        0xe6bb11bd,0xdcbac3c9 },
-      0 },
-    /* 83 */
-    { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7,
-        0x2d626862,0xb8c1c89e },
-      { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9,
-        0x2f9422d4,0x5d23bbda },
-      0 },
-    /* 84 */
-    { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403,
-        0x91ece900,0xc109f9cb },
-      { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d,
-        0x2eee1ee1,0x9bc3344f },
-      0 },
-    /* 85 */
-    { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665,
-        0x5f1a4cc1,0x29591d52 },
-      { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496,
-        0x18ef332c,0x6376551f },
-      0 },
-    /* 86 */
-    { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064,
-        0x08e2987a,0xbdb79dc8 },
-      { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022,
-        0xadd3c14a,0x8ee86001 },
-      0 },
-    /* 87 */
-    { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899,
-        0x6f77aa4b,0x92e51d7a },
-      { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3,
-        0x0a56aaaa,0x5182f86f },
-      0 },
-    /* 88 */
-    { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb,
-        0x4073a6f2,0x91dcab5d },
-      { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c,
-        0x97974f2b,0x17a0cedb },
-      0 },
-    /* 89 */
-    { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4,
-        0x7f4cdf41,0x2e8ce36c },
-      { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388,
-        0x34f668f3,0xf4ccc6cb },
-      0 },
-    /* 90 */
-    { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741,
-        0x9a0df3c9,0xac0db488 },
-      { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f,
-        0x94c974a2,0x95a64a61 },
-      0 },
-    /* 91 */
-    { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c,
-        0x29210677,0x231e54ba },
-      { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b,
-        0xd8a731e1,0xab0be032 },
-      0 },
-    /* 92 */
-    { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196,
-        0x2cf6a679,0xf1bcc880 },
-      { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc,
-        0x5aebb271,0x85169469 },
-      0 },
-    /* 93 */
-    { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2,
-        0xdaad55d8,0x8f67d9d2 },
-      { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4,
-        0xc0728b5d,0xf84572b9 },
-      0 },
-    /* 94 */
-    { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07,
-        0x616b2c19,0xedee2710 },
-      { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3,
-        0x44ebd7f4,0x9fd27e9b },
-      0 },
-    /* 95 */
-    { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816,
-        0x958ff387,0xa40c2fb6 },
-      { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704,
-        0x7dc6decf,0x99bc9bb8 },
-      0 },
-    /* 96 */
-    { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0,
-        0xa16d7e64,0x9abe210b },
-      { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987,
-        0x87f344b0,0x7881c257 },
-      0 },
-    /* 97 */
-    { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2,
-        0xa30e8940,0x15e6e319 },
-      { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1,
-        0x191172ce,0x0e55facf },
-      0 },
-    /* 98 */
-    { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca,
-        0x6fe96577,0xd73d0976 },
-      { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859,
-        0x8f15a50b,0x9250a374 },
-      0 },
-    /* 99 */
-    { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289,
-        0xc1cc8c0b,0x77414082 },
-      { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7,
-        0x12eb20b9,0x8cb04f4d },
-      0 },
-    /* 100 */
-    { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f,
-        0x47123b51,0xe4e429ef },
-      { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07,
-        0x3c6e6552,0x37bca2ff },
-      0 },
-    /* 101 */
-    { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9,
-        0x3002b22a,0x59913edc },
-      { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375,
-        0xb013e226,0x43786e4a },
-      0 },
-    /* 102 */
-    { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845,
-        0xb7e79e7a,0x8638ca98 },
-      { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0,
-        0x7b3aa6f0,0x1ecdd36a },
-      0 },
-    /* 103 */
-    { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa,
-        0xd459f32d,0xd85d0f85 },
-      { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4,
-        0xb4ed3c62,0xa04f19c3 },
-      0 },
-    /* 104 */
-    { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a,
-        0x5c0950b0,0x92b2eeea },
-      { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3,
-        0x5834276c,0x1ee78221 },
-      0 },
-    /* 105 */
-    { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a,
-        0x57a6e150,0xf3f2ced8 },
-      { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7,
-        0x3da3e210,0x0f56a454 },
-      0 },
-    /* 106 */
-    { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0,
-        0x1969e263,0xbd8f1741 },
-      { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7,
-        0x30ccfa09,0x2d1a1c35 },
-      0 },
-    /* 107 */
-    { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949,
-        0xb91fba46,0xa107a65e },
-      { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584,
-        0xf87a9af2,0x183d760a },
-      0 },
-    /* 108 */
-    { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963,
-        0xc269d754,0x1d44179d },
-      { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5,
-        0x9606d262,0x771f9cc2 },
-      0 },
-    /* 109 */
-    { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2,
-        0x0362718e,0x64427a31 },
-      { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d,
-        0x6ae90d6d,0x49d9b749 },
-      0 },
-    /* 110 */
-    { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0,
-        0x3f605445,0x9037d81b },
-      { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96,
-        0x7cc0639c,0x08c3de6a },
-      0 },
-    /* 111 */
-    { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e,
-        0x45796b2f,0xc6909442 },
-      { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab,
-        0xcafe3ac0,0x3fa3db02 },
-      0 },
-    /* 112 */
-    { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c,
-        0xfdb808ff,0xc5c4bdb0 },
-      { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d,
-        0x46c2b6b5,0x2d56db94 },
-      0 },
-    /* 113 */
-    { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4,
-        0xe503ba42,0x0f56bd9d },
-      { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a,
-        0x1173b5f1,0x4003bb9d },
-      0 },
-    /* 114 */
-    { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d,
-        0xa07f2f9e,0x53765522 },
-      { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e,
-        0x6c5d4549,0x7a056f58 },
-      0 },
-    /* 115 */
-    { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e,
-        0x7a1a2675,0x77d482f1 },
-      { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057,
-        0x2b38b0e4,0x4115012b },
-      0 },
-    /* 116 */
-    { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e,
-        0xfbea0946,0xcdf04572 },
-      { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1,
-        0x97383109,0xee703dda },
-      0 },
-    /* 117 */
-    { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff,
-        0xa162ce21,0x2a0ad89d },
-      { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c,
-        0xac2b4659,0xd62d0b67 },
-      0 },
-    /* 118 */
-    { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3,
-        0x991c2426,0xb39a23f2 },
-      { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137,
-        0xc0674cc5,0x04ed0092 },
-      0 },
-    /* 119 */
-    { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6,
-        0x0177c387,0xa0a91fc1 },
-      { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1,
-        0x9ed20c41,0x084cf988 },
-      0 },
-    /* 120 */
-    { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4,
-        0x73abf77e,0xd57955b2 },
-      { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089,
-        0x02d141f1,0x8e14ea42 },
-      0 },
-    /* 121 */
-    { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194,
-        0x2aa4d158,0x597e1a37 },
-      { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a,
-        0x199b4dea,0xca3f0236 },
-      0 },
-    /* 122 */
-    { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1,
-        0x309c07e4,0xbde7fd7e },
-      { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f,
-        0x0a7dd198,0xb623ad0e },
-      0 },
-    /* 123 */
-    { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0,
-        0x58ec137b,0xd6aa2e46 },
-      { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b,
-        0x2dcc513a,0x111662e0 },
-      0 },
-    /* 124 */
-    { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7,
-        0x94b750f8,0xdb3ee1cb },
-      { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93,
-        0x52206a59,0x886a6442 },
-      0 },
-    /* 125 */
-    { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d,
-        0x018a17bc,0xa70cf4eb },
-      { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e,
-        0xd1747b77,0xaa4772ab },
-      0 },
-    /* 126 */
-    { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4,
-        0x30faf974,0x611a6ddc },
-      { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf,
-        0x16429c88,0x5cfffaf8 },
-      0 },
-    /* 127 */
-    { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f,
-        0x7dc1994c,0x6e5a6b23 },
-      { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6,
-        0x242dabcc,0x481a238d },
-      0 },
-    /* 128 */
-    { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d,
-        0xe0cdf943,0x2c41114c },
-      { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2,
-        0x42ff9297,0x20477abf },
-      0 },
-    /* 129 */
-    { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b,
-        0xc77396b6,0xac66409a },
-      { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba,
-        0xcc122f85,0xce8e6975 },
-      0 },
-    /* 130 */
-    { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d,
-        0x250bb4a8,0x08fde365 },
-      { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc,
-        0x565d6cd7,0x2f7e2fd2 },
-      0 },
-    /* 131 */
-    { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d,
-        0x907702ae,0xc65be92e },
-      { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585,
-        0xd1193b3a,0x4bff8e47 },
-      0 },
-    /* 132 */
-    { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef,
-        0x5772967d,0x3e4e4ae6 },
-      { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26,
-        0x58ec6028,0x5388aefd },
-      0 },
-    /* 133 */
-    { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f,
-        0x4f75be0e,0x5cf908d1 },
-      { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f,
-        0x60f00ce2,0xa698ba40 },
-      0 },
-    /* 134 */
-    { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544,
-        0x7aebad8d,0xb142ef8a },
-      { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b,
-        0x58515075,0xd1896a96 },
-      0 },
-    /* 135 */
-    { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73,
-        0x7981da39,0x267b0e0b },
-      { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0,
-        0xa1119393,0xb54e287a },
-      0 },
-    /* 136 */
-    { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab,
-        0x5f87d4e6,0x84abb28b },
-      { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b,
-        0x17655640,0xe5436f67 },
-      0 },
-    /* 137 */
-    { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd,
-        0x5b9ce99e,0x0404f68b },
-      { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960,
-        0x0ac1c701,0x3a4263df },
-      0 },
-    /* 138 */
-    { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6,
-        0x905ea367,0x0ca8fd3f },
-      { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be,
-        0x4ddb0c33,0x96dca264 },
-      0 },
-    /* 139 */
-    { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770,
-        0x3aad59dc,0x4363e212 },
-      { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604,
-        0xd8bb98c4,0x840e115c },
-      0 },
-    /* 140 */
-    { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272,
-        0x30ded6d4,0x5e0d6abd },
-      { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9,
-        0x2945a25a,0x7dea48f4 },
-      0 },
-    /* 141 */
-    { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54,
-        0xebfd16d1,0xabc2a2be },
-      { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377,
-        0x6c7eefc1,0x4ea35394 },
-      0 },
-    /* 142 */
-    { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a,
-        0x1c94ffc3,0x3a76e689 },
-      { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72,
-        0x465e6464,0x8212a10a },
-      0 },
-    /* 143 */
-    { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67,
-        0x599cb164,0xaa7cab71 },
-      { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292,
-        0xfe0617c3,0x40e38073 },
-      0 },
-    /* 144 */
-    { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320,
-        0xb3055526,0xe3604700 },
-      { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434,
-        0xa3dee15f,0x6542d677 },
-      0 },
-    /* 145 */
-    { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8,
-        0x09bb6f21,0xa6534aee },
-      { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1,
-        0xdc9aef22,0xf3cb672f },
-      0 },
-    /* 146 */
-    { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9,
-        0xaae870e7,0x7cafaa2e },
-      { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108,
-        0xb9bd522e,0x0aab13c1 },
-      0 },
-    /* 147 */
-    { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173,
-        0x847012e9,0x4b91a602 },
-      { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a,
-        0x72321cab,0x49534c53 },
-      0 },
-    /* 148 */
-    { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b,
-        0xd65ac5ee,0xcaf46c4f },
-      { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168,
-        0x04c6770f,0x14ce9e57 },
-      0 },
-    /* 149 */
-    { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f,
-        0x3e4c9a71,0x1bb708a5 },
-      { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71,
-        0xda300102,0xf9d126f2 },
-      0 },
-    /* 150 */
-    { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311,
-        0x729ecc69,0x807afcb9 },
-      { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59,
-        0x6568cd8c,0x751adcd1 },
-      0 },
-    /* 151 */
-    { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14,
-        0x2537743f,0x29ec4468 },
-      { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a,
-        0x92a4077d,0xff9370e3 },
-      0 },
-    /* 152 */
-    { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e,
-        0xa2a9d01a,0x9776478b },
-      { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5,
-        0xac2f82fa,0x74a6313f },
-      0 },
-    /* 153 */
-    { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0,
-        0x0ff4863d,0xab75be15 },
-      { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03,
-        0x0b4459f6,0x4ebeac2e },
-      0 },
-    /* 154 */
-    { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633,
-        0x2c1baffc,0xdf99887b },
-      { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511,
-        0x779f4058,0x27b040a7 },
-      0 },
-    /* 155 */
-    { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152,
-        0xe4cfa3f5,0xb393dd37 },
-      { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be,
-        0xd0463419,0x09588c12 },
-      0 },
-    /* 156 */
-    { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280,
-        0xdb9f648b,0x81c879a9 },
-      { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41,
-        0x5fc11bc4,0xfa0d48f5 },
-      0 },
-    /* 157 */
-    { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1,
-        0xb6a367d6,0x8ea0e156 },
-      { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b,
-        0xfa00b5ac,0x3f5ab924 },
-      0 },
-    /* 158 */
-    { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6,
-        0x2b74256e,0x8bc76887 },
-      { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168,
-        0x60fcf34f,0xb386f190 },
-      0 },
-    /* 159 */
-    { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea,
-        0x1b069c4d,0x4cb460f7 },
-      { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66,
-        0x95ef5223,0x52c0d508 },
-      0 },
-    /* 160 */
-    { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661,
-        0x2bb09c0b,0x4ac3c938 },
-      { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765,
-        0xe39705f4,0x380d94c7 },
-      0 },
-    /* 161 */
-    { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977,
-        0xde2637af,0x2ce3e171 },
-      { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f,
-        0x0b624e4d,0x2e6cd852 },
-      0 },
-    /* 162 */
-    { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e,
-        0x42c69d54,0xca177547 },
-      { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793,
-        0x9cab2ce6,0xa976a713 },
-      0 },
-    /* 163 */
-    { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7,
-        0x0a1f4999,0x8720a717 },
-      { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a,
-        0xc769893c,0x9719ef29 },
-      0 },
-    /* 164 */
-    { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0,
-        0xe15704c1,0xa5072976 },
-      { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18,
-        0xf7b77725,0x99389c9d },
-      0 },
-    /* 165 */
-    { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89,
-        0x202c82e4,0xa88806aa },
-      { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0,
-        0x4738dcfe,0x0043bffb },
-      0 },
-    /* 166 */
-    { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a,
-        0xba6c4866,0x52f3ef01 },
-      { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa,
-        0x9ef27e75,0x3296bd89 },
-      0 },
-    /* 167 */
-    { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd,
-        0xaee571e9,0x3b90febf },
-      { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48,
-        0x9f810b18,0x6e88069d },
-      0 },
-    /* 168 */
-    { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221,
-        0xdefaad13,0xa7222bea },
-      { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5,
-        0xbc2ac690,0xbe94d523 },
-      0 },
-    /* 169 */
-    { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1,
-        0x9be8c766,0x7782defe },
-      { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc,
-        0xa2892e4b,0x03838567 },
-      0 },
-    /* 170 */
-    { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc,
-        0xadf7b420,0xdbd986c4 },
-      { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d,
-        0x6860bbd0,0x8e24d3c4 },
-      0 },
-    /* 171 */
-    { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4,
-        0x407bafc8,0x541a99c4 },
-      { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4,
-        0xf57d35d1,0xc0092c49 },
-      0 },
-    /* 172 */
-    { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1,
-        0x7286944d,0x75e40634 },
-      { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16,
-        0xc7848586,0x5b7cb658 },
-      0 },
-    /* 173 */
-    { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1,
-        0x8df097a1,0x7ae13eba },
-      { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878,
-        0xe2a8e3fd,0x787d8074 },
-      0 },
-    /* 174 */
-    { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3,
-        0x9ef28484,0x5c222819 },
-      { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1,
-        0xbaf0f2b0,0xe45d37ab },
-      0 },
-    /* 175 */
-    { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7,
-        0x84dfb9d3,0xed7bc122 },
-      { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140,
-        0x45ca6d27,0xaac97cc9 },
-      0 },
-    /* 176 */
-    { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1,
-        0x1163dc4e,0x318f97b3 },
-      { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f,
-        0x9a84ff4d,0xfa41faa1 },
-      0 },
-    /* 177 */
-    { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4,
-        0x1d26e9e2,0x38bb6b2c },
-      { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf,
-        0xce7601a5,0x94dd0905 },
-      0 },
-    /* 178 */
-    { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9,
-        0xd25c2ae9,0x92077867 },
-      { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3,
-        0xd29beb51,0x81e8428b },
-      0 },
-    /* 179 */
-    { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f,
-        0xdbbfa4b1,0x1b94ab62 },
-      { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f,
-        0x055590ee,0x06a38e28 },
-      0 },
-    /* 180 */
-    { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b,
-        0x83d9d4f8,0xa7b36c20 },
-      { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2,
-        0xa2822a20,0xbe54c6b4 },
-      0 },
-    /* 181 */
-    { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f,
-        0xeae022bb,0xbf30a5ab },
-      { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb,
-        0x2732d13a,0xd1c820de },
-      0 },
-    /* 182 */
-    { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe,
-        0x68a18da3,0xb7d17bed },
-      { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af,
-        0x6412cc64,0x3997fd5e },
-      0 },
-    /* 183 */
-    { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0,
-        0x3c6c13e8,0x0eeb8929 },
-      { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6,
-        0xc922b6ef,0x228916f8 },
-      0 },
-    /* 184 */
-    { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e,
-        0x6e93097e,0xec05ad1d },
-      { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237,
-        0x7ff11b37,0x7d314156 },
-      0 },
-    /* 185 */
-    { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97,
-        0x9bc1d7a3,0xe9ce66fc },
-      { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34,
-        0x72280651,0xd9650b01 },
-      0 },
-    /* 186 */
-    { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208,
-        0x804eb7a2,0x14d6699a },
-      { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90,
-        0x0d43598a,0x6f4c6841 },
-      0 },
-    /* 187 */
-    { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2,
-        0x61189abb,0x4c4350fd },
-      { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413,
-        0x5a3118b5,0xa726d242 },
-      0 },
-    /* 188 */
-    { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f,
-        0xcc6cf392,0x13639e82 },
-      { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e,
-        0xc1a335a3,0xca9365e1 },
-      0 },
-    /* 189 */
-    { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4,
-        0x970b72a5,0x9ce29c34 },
-      { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a,
-        0xab42af98,0x48c4abd7 },
-      0 },
-    /* 190 */
-    { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698,
-        0xf67b33cb,0x78017c32 },
-      { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55,
-        0xde5c1c04,0x53cd0454 },
-      0 },
-    /* 191 */
-    { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1,
-        0xd3d7fa8f,0xeea465c1 },
-      { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770,
-        0x7ae69193,0x1b6e42a4 },
-      0 },
-    /* 192 */
-    { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887,
-        0x187fbd3d,0x0224da14 },
-      { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf,
-        0x42bfff33,0x60838ef0 },
-      0 },
-    /* 193 */
-    { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a,
-        0x2d331643,0x636eb202 },
-      { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2,
-        0x39218bac,0x8844eeb6 },
-      0 },
-    /* 194 */
-    { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f,
-        0x51fb789e,0x27ba83dc },
-      { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35,
-        0x87f3a4ab,0xadb62d34 },
-      0 },
-    /* 195 */
-    { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7,
-        0x75e7c8b2,0xb990fd76 },
-      { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a,
-        0x4d10d18d,0x81707ef9 },
-      0 },
-    /* 196 */
-    { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4,
-        0xd5a8aa5c,0x3792daea },
-      { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527,
-        0x94b001ba,0x5abd635e },
-      0 },
-    /* 197 */
-    { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea,
-        0x846ab610,0x5995bf21 },
-      { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44,
-        0xd483411e,0x44c32ca2 },
-      0 },
-    /* 198 */
-    { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b,
-        0x8082a54c,0x1f2162fb },
-      { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e,
-        0xc3e907c9,0x8f1d402b },
-      0 },
-    /* 199 */
-    { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37,
-        0x926edbf9,0xb1980f43 },
-      { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4,
-        0x37448e45,0x2828ad9b },
-      0 },
-    /* 200 */
-    { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2,
-        0x5a14b390,0x4973f127 },
-      { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f,
-        0xdb168ac7,0x6dac8ed0 },
-      0 },
-    /* 201 */
-    { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0,
-        0x20b9de4c,0x4b23ef59 },
-      { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863,
-        0xddf49a4e,0x4dd71534 },
-      0 },
-    /* 202 */
-    { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8,
-        0x2f4a4dbb,0xfd317000 },
-      { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976,
-        0x9569f365,0x14fac58c },
-      0 },
-    /* 203 */
-    { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240,
-        0x36abda50,0xed7c7651 },
-      { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075,
-        0x4d2e9f53,0xfefcb7f7 },
-      0 },
-    /* 204 */
-    { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de,
-        0x87e0d80b,0x1801a57e },
-      { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b,
-        0x1ead1064,0x9f8fc11e },
-      0 },
-    /* 205 */
-    { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd,
-        0x3d3a69a9,0xa9d3809d },
-      { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e,
-        0xe1178ef7,0x3006b9ae },
-      0 },
-    /* 206 */
-    { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd,
-        0x45f8f761,0x0ab85fd7 },
-      { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274,
-        0x11e942c2,0xb122d675 },
-      0 },
-    /* 207 */
-    { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301,
-        0x097dbaec,0x9f599dc1 },
-      { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4,
-        0x8a294b78,0x7d5528e0 },
-      0 },
-    /* 208 */
-    { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b,
-        0x303f1730,0x28ccea01 },
-      { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc,
-        0xa1d013bf,0xc18baf48 },
-      0 },
-    /* 209 */
-    { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171,
-        0xb7a9596b,0x9def809d },
-      { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d,
-        0x68808ce5,0x0357f8b0 },
-      0 },
-    /* 210 */
-    { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874,
-        0x1b489887,0xe4a01add },
-      { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71,
-        0xce10cc30,0x466d7d79 },
-      0 },
-    /* 211 */
-    { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28,
-        0x451ead1a,0xc672a522 },
-      { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680,
-        0xf2a67513,0x5e3d64fa },
-      0 },
-    /* 212 */
-    { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a,
-        0xeb8e42fc,0x6c8a7a95 },
-      { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738,
-        0xad82ca91,0x348ae422 },
-      0 },
-    /* 213 */
-    { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782,
-        0xd9ef2d2e,0xc1074de0 },
-      { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50,
-        0xc9e54ffc,0xfbadfbdb },
-      0 },
-    /* 214 */
-    { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd,
-        0x83716fcd,0xb7f976b4 },
-      { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760,
-        0xcafcc805,0xf4d41b2e },
-      0 },
-    /* 215 */
-    { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974,
-        0xe0160f10,0x180824ea },
-      { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34,
-        0x83cf6d25,0x67e5f639 },
-      0 },
-    /* 216 */
-    { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276,
-        0x04c11fc6,0x9fef789a },
-      { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0,
-        0xa99c4e20,0xbc80c181 },
-      0 },
-    /* 217 */
-    { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171,
-        0x9f8cdf10,0x49270e62 },
-      { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17,
-        0x61372f7f,0xd2ee52f9 },
-      0 },
-    /* 218 */
-    { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5,
-        0xe5abb733,0xdfb478be },
-      { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf,
-        0x08df473a,0xd9a140b4 },
-      0 },
-    /* 219 */
-    { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391,
-        0x623f4b1a,0x760c058d },
-      { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110,
-        0x8f190409,0x7141982d },
-      0 },
-    /* 220 */
-    { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6,
-        0x89d54e47,0x3af9d1ce },
-      { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc,
-        0x73957dd6,0xb1f815c3 },
-      0 },
-    /* 221 */
-    { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d,
-        0x1543f052,0xa41aed14 },
-      { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be,
-        0x86fb60ef,0xd6e9c1dd },
-      0 },
-    /* 222 */
-    { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7,
-        0xae9bf8c2,0x9c9c6e10 },
-      { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23,
-        0x40fa61b6,0x566bd596 },
-      0 },
-    /* 223 */
-    { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0,
-        0xf525345e,0xcf2c7390 },
-      { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a,
-        0x8aa20979,0x02f51755 },
-      0 },
-    /* 224 */
-    { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac,
-        0xe8d4d97d,0x14e9ada5 },
-      { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d,
-        0x8e9d9ae8,0xa0ad4fab },
-      0 },
-    /* 225 */
-    { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737,
-        0x6e56ed1e,0xbcd530b8 },
-      { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761,
-        0x6979341d,0x909283cf },
-      0 },
-    /* 226 */
-    { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b,
-        0xace1549a,0x35eeb7c9 },
-      { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c,
-        0x448ae864,0x9a8b2cf4 },
-      0 },
-    /* 227 */
-    { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168,
-        0xd4491379,0x6bdb60f4 },
-      { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741,
-        0x94ba08a9,0x01ec3cfd },
-      0 },
-    /* 228 */
-    { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f,
-        0x475464f6,0xd1acb1c0 },
-      { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813,
-        0x405626c2,0x7dcd079d },
-      0 },
-    /* 229 */
-    { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971,
-        0x377d19b8,0x0bf53589 },
-      { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6,
-        0xe16686fc,0xd28be4d9 },
-      0 },
-    /* 230 */
-    { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa,
-        0x510f88ce,0xd76007aa },
-      { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082,
-        0xb303bb01,0xf2b52f68 },
-      0 },
-    /* 231 */
-    { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680,
-        0xcc5aed3a,0xd8dbe98e },
-      { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd,
-        0xee559705,0xe01593a3 },
-      0 },
-    /* 232 */
-    { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f,
-        0xaeb8ef06,0xafec07b1 },
-      { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a,
-        0x6e2dbfdd,0xa71b9354 },
-      0 },
-    /* 233 */
-    { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db,
-        0x628523d9,0x53a2005c },
-      { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7,
-        0x3d588e3d,0xbf47d19b },
-      0 },
-    /* 234 */
-    { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae,
-        0x39c9a1b6,0x001c2c7f },
-      { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b,
-        0x86ffb99b,0xfdadf8e7 },
-      0 },
-    /* 235 */
-    { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055,
-        0x5aa43c94,0x3a838e4d },
-      { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6,
-        0x873e1da3,0x3cdb8257 },
-      0 },
-    /* 236 */
-    { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2,
-        0xf1f57fba,0x5a60cc89 },
-      { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8,
-        0xdbfd8fc0,0x922ff56f },
-      0 },
-    /* 237 */
-    { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46,
-        0xf6c5cd62,0x72919a7d },
-      { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77,
-        0x3624089a,0x5e791780 },
-      0 },
-    /* 238 */
-    { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea,
-        0xe24c2fab,0x4e0a5371 },
-      { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae,
-        0xd56604ee,0xf5ff7818 },
-      0 },
-    /* 239 */
-    { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a,
-        0x533f5e64,0xe41df0e9 },
-      { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192,
-        0xac4f155f,0x8edd7d6e },
-      0 },
-    /* 240 */
-    { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c,
-        0xed8aee96,0x1432c1ca },
-      { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5,
-        0x5ac8d2c6,0xcaef480b },
-      0 },
-    /* 241 */
-    { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0,
-        0x8efae236,0xd0ba177e },
-      { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605,
-        0x1c54ae16,0xf31c957c },
-      0 },
-    /* 242 */
-    { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55,
-        0x96e17c3a,0x013404cb },
-      { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682,
-        0x91933e6c,0x6f377c4b },
-      0 },
-    /* 243 */
-    { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037,
-        0xd2d09506,0x6dba3e4e },
-      { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752,
-        0x3becf4a7,0xf13cf342 },
-      0 },
-    /* 244 */
-    { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6,
-        0x274bbad3,0xc83fa9a9 },
-      { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e,
-        0x5d702683,0xb49d70f4 },
-      0 },
-    /* 245 */
-    { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418,
-        0x0c30f1cf,0x59cfadbb },
-      { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c,
-        0x354a4b67,0x5babf362 },
-      0 },
-    /* 246 */
-    { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1,
-        0x9026c8f0,0x6188c6a7 },
-      { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b,
-        0xdf50b9d9,0x993fe475 },
-      0 },
-    /* 247 */
-    { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a,
-        0x4c80616b,0x81f76466 },
-      { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04,
-        0x5fe9060d,0x564a812a },
-      0 },
-    /* 248 */
-    { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f,
-        0x00e51d6c,0x226bf3cf },
-      { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49,
-        0xff257836,0x68779f47 },
-      0 },
-    /* 249 */
-    { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28,
-        0xeb092e0b,0x97bcb0d1 },
-      { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3,
-        0x0a784655,0xa872ffe8 },
-      0 },
-    /* 250 */
-    { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91,
-        0xb732a36a,0x02812bfc },
-      { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398,
-        0xfe5396af,0x07391cc9 },
-      0 },
-    /* 251 */
-    { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8,
-        0x7e6d2a08,0x355d2adc },
-      { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd,
-        0x7c2a3a79,0x3dc2b1e3 },
-      0 },
-    /* 252 */
-    { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590,
-        0x3ccd846b,0xc4786910 },
-      { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5,
-        0xd5bb4d32,0xccc42968 },
-      0 },
-    /* 253 */
-    { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640,
-        0xaa4871cf,0xe147eb42 },
-      { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47,
-        0x080e96e3,0x239ac047 },
-      0 },
-    /* 254 */
-    { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e,
-        0xf5f7e59d,0xc55fa1a3 },
-      { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998,
-        0xd4f4b699,0x094cd99c },
-      0 },
-    /* 255 */
-    { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9,
-        0x42abad33,0xb90a30b6 },
-      { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc,
-        0x1b7924f7,0x019f8b9a },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#endif
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[8];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 8, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 8, km);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_8(point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_8(point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_8(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN)
-/* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a  Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
-static int sp_256_iszero_8(const sp_digit* a)
-{
-    return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */
-/* Add 1 to a. (a = a + 1)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_add_one_8(sp_digit* a)
-{
-    __asm__ __volatile__ (
-        "ldr	r1, [%[a], #0]\n\t"
-        "ldr	r2, [%[a], #4]\n\t"
-        "ldr	r3, [%[a], #8]\n\t"
-        "ldr	r4, [%[a], #12]\n\t"
-        "adds	r1, r1, #1\n\t"
-        "adcs	r2, r2, #0\n\t"
-        "adcs	r3, r3, #0\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "str	r1, [%[a], #0]\n\t"
-        "str	r2, [%[a], #4]\n\t"
-        "str	r3, [%[a], #8]\n\t"
-        "str	r4, [%[a], #12]\n\t"
-        "ldr	r1, [%[a], #16]\n\t"
-        "ldr	r2, [%[a], #20]\n\t"
-        "ldr	r3, [%[a], #24]\n\t"
-        "ldr	r4, [%[a], #28]\n\t"
-        "adcs	r1, r1, #0\n\t"
-        "adcs	r2, r2, #0\n\t"
-        "adcs	r3, r3, #0\n\t"
-        "adcs	r4, r4, #0\n\t"
-        "str	r1, [%[a], #16]\n\t"
-        "str	r2, [%[a], #20]\n\t"
-        "str	r3, [%[a], #24]\n\t"
-        "str	r4, [%[a], #28]\n\t"
-        :
-        : [a] "r" (a)
-        : "memory", "r1", "r2", "r3", "r4"
-    );
-}
-
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 24) {
-            r[j] &= 0xffffffff;
-            s = 32 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Generates a scalar that is in the range 1..order-1.
- *
- * rng  Random number generator.
- * k    Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k)
-{
-    int err;
-    byte buf[32];
-
-    do {
-        err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
-        if (err == 0) {
-            sp_256_from_bin(k, 8, buf, sizeof(buf));
-            if (sp_256_cmp_8(k, p256_order2) < 0) {
-                sp_256_add_one_8(k);
-                break;
-            }
-        }
-    }
-    while (err == 0);
-
-    return err;
-}
-
-/* Makes a random EC key pair.
- *
- * rng   Random number generator.
- * priv  Generated private value.
- * pub   Generated public point.
- * heap  Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[8];
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point inf;
-#endif
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point* infinity;
-#endif
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, inf, infinity);
-#endif
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 8, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_ecc_gen_k_8(rng, k);
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_8(point, k, 1, NULL);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            err = sp_256_ecc_mulmod_avx2_8(infinity, point, p256_order, 1,
-                                                                          NULL);
-        }
-        else
-#endif
-            err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL);
-    }
-    if (err == MP_OKAY) {
-        if (!sp_256_iszero_8(point->x) || !sp_256_iszero_8(point->y))
-            err = ECC_INF_E;
-    }
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(k, priv);
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_8(point, pub);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_ecc_point_free(infinity, 1, heap);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-
-#ifdef HAVE_ECC_DHE
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 32
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_256_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 256 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<8 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 32) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 32);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv    Scalar to multiply the point by.
- * pub     Point to multiply.
- * out     Buffer to hold X ordinate.
- * outLen  On entry, size of the buffer in bytes.
- *         On exit, length of data in buffer in bytes.
- * heap    Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outLen, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[8];
-#endif
-    sp_point* point = NULL;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 32)
-        err = BUFFER_E;
-
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 8, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 8, priv);
-        sp_256_point_from_ecc_point_8(point, pub);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_8(point, point, k, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_8(point, point, k, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        sp_256_to_bin(point->x, out);
-        *outLen = 32;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_DHE */
-
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[16];
-
-    __asm__ __volatile__ (
-        "mov	r5, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #28\n\t"
-        "movcc	r3, #0\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r12, [%[b], r4]\n\t"
-        "umull	r9, r10, r14, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, #0\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #32\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #56\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "#  A[0] * B[0]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r3, r4, r8, r9\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[0]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #4]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[1]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[0]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #8]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[2]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[1]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[0]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #12]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[3]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[2]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[0]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #16]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[1] * B[4]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[2] * B[3]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[2]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[1]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[0]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[tmp], #20]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[1] * B[5]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[2] * B[4]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[3] * B[3]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[2]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[1]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[0]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[tmp], #24]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[1] * B[6]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[2] * B[5]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[3] * B[4]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[4] * B[3]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[2]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[1]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[0]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #0]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[tmp], #28]\n\t"
-        "#  A[1] * B[7]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[2] * B[6]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[3] * B[5]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[4] * B[4]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[5] * B[3]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[2]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[1]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #4]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        "#  A[2] * B[7]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[3] * B[6]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[4] * B[5]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[5] * B[4]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[6] * B[3]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[2]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #8]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #36]\n\t"
-        "#  A[3] * B[7]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[4] * B[6]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[5] * B[5]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[6] * B[4]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "#  A[7] * B[3]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #40]\n\t"
-        "#  A[4] * B[7]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "#  A[5] * B[6]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[6] * B[5]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "#  A[7] * B[4]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #16]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r4, r10\n\t"
-        "str	r5, [%[r], #44]\n\t"
-        "#  A[5] * B[7]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "#  A[6] * B[6]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "#  A[7] * B[5]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #20]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r5, r10\n\t"
-        "str	r3, [%[r], #48]\n\t"
-        "#  A[6] * B[7]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "#  A[7] * B[6]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #24]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r3, r10\n\t"
-        "str	r4, [%[r], #52]\n\t"
-        "#  A[7] * B[7]\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "umull	r6, r7, r8, r9\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r5, [%[r], #56]\n\t"
-        "str	r3, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef HAVE_INTEL_AVX2
-#endif /* HAVE_INTEL_AVX2 */
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "add	r12, %[a], #32\n\t"
-        "\n1:\n\t"
-        "subs	%[c], r14, %[c]\n\t"
-        "ldr	r3, [%[a]]\n\t"
-        "ldr	r4, [%[a], #4]\n\t"
-        "ldr	r5, [%[a], #8]\n\t"
-        "ldr	r6, [%[a], #12]\n\t"
-        "ldr	r7, [%[b]], #4\n\t"
-        "ldr	r8, [%[b]], #4\n\t"
-        "ldr	r9, [%[b]], #4\n\t"
-        "ldr	r10, [%[b]], #4\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "sbcs	r6, r6, r10\n\t"
-        "str	r3, [%[a]], #4\n\t"
-        "str	r4, [%[a]], #4\n\t"
-        "str	r5, [%[a]], #4\n\t"
-        "str	r6, [%[a]], #4\n\t"
-        "sbc	%[c], r14, r14\n\t"
-        "cmp	%[a], r12\n\t"
-        "bne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
-    );
-
-    return c;
-}
-
-#else
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldr	r2, [%[a], #0]\n\t"
-        "ldr	r3, [%[a], #4]\n\t"
-        "ldr	r4, [%[a], #8]\n\t"
-        "ldr	r5, [%[a], #12]\n\t"
-        "ldr	r6, [%[b], #0]\n\t"
-        "ldr	r7, [%[b], #4]\n\t"
-        "ldr	r8, [%[b], #8]\n\t"
-        "ldr	r9, [%[b], #12]\n\t"
-        "subs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #0]\n\t"
-        "str	r3, [%[a], #4]\n\t"
-        "str	r4, [%[a], #8]\n\t"
-        "str	r5, [%[a], #12]\n\t"
-        "ldr	r2, [%[a], #16]\n\t"
-        "ldr	r3, [%[a], #20]\n\t"
-        "ldr	r4, [%[a], #24]\n\t"
-        "ldr	r5, [%[a], #28]\n\t"
-        "ldr	r6, [%[b], #16]\n\t"
-        "ldr	r7, [%[b], #20]\n\t"
-        "ldr	r8, [%[b], #24]\n\t"
-        "ldr	r9, [%[b], #28]\n\t"
-        "sbcs	r2, r2, r6\n\t"
-        "sbcs	r3, r3, r7\n\t"
-        "sbcs	r4, r4, r8\n\t"
-        "sbcs	r5, r5, r9\n\t"
-        "str	r2, [%[a], #16]\n\t"
-        "str	r3, [%[a], #20]\n\t"
-        "str	r4, [%[a], #24]\n\t"
-        "str	r5, [%[a], #28]\n\t"
-        "sbc	%[c], r9, r9\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r5, r3, %[b], r8\n\t"
-        "mov	r4, #0\n\t"
-        "str	r5, [%[r]]\n\t"
-        "mov	r5, #0\n\t"
-        "mov	r9, #4\n\t"
-        "1:\n\t"
-        "ldr	r8, [%[a], r9]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], r9]\n\t"
-        "mov	r3, r4\n\t"
-        "mov	r4, r5\n\t"
-        "mov	r5, #0\n\t"
-        "add	r9, r9, #4\n\t"
-        "cmp	r9, #32\n\t"
-        "blt	1b\n\t"
-        "str	r3, [%[r], #32]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	r10, #0\n\t"
-        "# A[0] * B\n\t"
-        "ldr	r8, [%[a]]\n\t"
-        "umull	r3, r4, %[b], r8\n\t"
-        "mov	r5, #0\n\t"
-        "str	r3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #4]\n\t"
-        "# A[2] * B\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #8]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #12]\n\t"
-        "# A[4] * B\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "mov	r3, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adcs	r5, r5, r7\n\t"
-        "adc	r3, r10, r10\n\t"
-        "str	r4, [%[r], #16]\n\t"
-        "# A[5] * B\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "mov	r4, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r5, r5, r6\n\t"
-        "adcs	r3, r3, r7\n\t"
-        "adc	r4, r10, r10\n\t"
-        "str	r5, [%[r], #20]\n\t"
-        "# A[6] * B\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "mov	r5, #0\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r3, r3, r6\n\t"
-        "adcs	r4, r4, r7\n\t"
-        "adc	r5, r10, r10\n\t"
-        "str	r3, [%[r], #24]\n\t"
-        "# A[7] * B\n\t"
-        "ldr	r8, [%[a], #28]\n\t"
-        "umull	r6, r7, %[b], r8\n\t"
-        "adds	r4, r4, r6\n\t"
-        "adc	r5, r5, r7\n\t"
-        "str	r4, [%[r], #28]\n\t"
-        "str	r5, [%[r], #32]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- *
- * Note that this is an approximate div. It may give an answer 1 larger.
- */
-static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r = 0;
-
-    __asm__ __volatile__ (
-        "lsr	r5, %[div], #1\n\t"
-        "add	r5, r5, #1\n\t"
-        "mov	r6, %[d0]\n\t"
-        "mov	r7, %[d1]\n\t"
-        "# Do top 32\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "# Next 30 bits\n\t"
-        "mov	r4, #29\n\t"
-        "1:\n\t"
-        "movs	r6, r6, lsl #1\n\t"
-        "adc	r7, r7, r7\n\t"
-        "subs	r8, r5, r7\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        "and	r8, r8, r5\n\t"
-        "subs	r7, r7, r8\n\t"
-        "subs	r4, r4, #1\n\t"
-        "bpl	1b\n\t"
-        "add	%[r], %[r], %[r]\n\t"
-        "add	%[r], %[r], #1\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "umull	r4, r5, %[r], %[div]\n\t"
-        "subs	r4, %[d0], r4\n\t"
-        "sbc	r5, %[d1], r5\n\t"
-        "add	%[r], %[r], r5\n\t"
-        "subs	r8, %[div], r4\n\t"
-        "sbc	r8, r8, r8\n\t"
-        "sub	%[r], %[r], r8\n\t"
-        : [r] "+r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "r4", "r5", "r6", "r7", "r8"
-    );
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_256_mask_8(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<8; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-    r[4] = a[4] & m;
-    r[5] = a[5] & m;
-    r[6] = a[6] & m;
-    r[7] = a[7] & m;
-#endif
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_div_8(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[16], t2[9];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[7];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 8);
-    for (i=7; i>=0; i--) {
-        r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div);
-
-        sp_256_mul_d_8(t2, d, r1);
-        t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2);
-        t1[8 + i] -= t2[8];
-        sp_256_mask_8(t2, d, t1[8 + i]);
-        t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
-        sp_256_mask_8(t2, d, t1[8 + i]);
-        t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_256_cmp_8(t1, d) >= 0;
-    sp_256_cond_sub_8(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_mod_8(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_256_div_8(a, m, NULL, r);
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[16];
-
-    __asm__ __volatile__ (
-        "mov	r12, #0\n\t"
-        "mov	r6, #0\n\t"
-        "mov	r7, #0\n\t"
-        "mov	r8, #0\n\t"
-        "mov	r5, #0\n\t"
-        "\n1:\n\t"
-        "subs	r3, r5, #28\n\t"
-        "movcc	r3, r12\n\t"
-        "sub	r4, r5, r3\n\t"
-        "\n2:\n\t"
-        "cmp	r4, r3\n\t"
-        "beq	4f\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "ldr	r9, [%[a], r4]\n\t"
-        "umull	r9, r10, r14, r9\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "bal	5f\n\t"
-        "\n4:\n\t"
-        "ldr	r14, [%[a], r3]\n\t"
-        "umull	r9, r10, r14, r14\n\t"
-        "adds	r6, r6, r9\n\t"
-        "adcs	r7, r7, r10\n\t"
-        "adc	r8, r8, r12\n\t"
-        "\n5:\n\t"
-        "add	r3, r3, #4\n\t"
-        "sub	r4, r4, #4\n\t"
-        "cmp	r3, #32\n\t"
-        "beq	3f\n\t"
-        "cmp	r3, r4\n\t"
-        "bgt	3f\n\t"
-        "cmp	r3, r5\n\t"
-        "ble	2b\n\t"
-        "\n3:\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        "mov	r6, r7\n\t"
-        "mov	r7, r8\n\t"
-        "mov	r8, #0\n\t"
-        "add	r5, r5, #4\n\t"
-        "cmp	r5, #56\n\t"
-        "ble	1b\n\t"
-        "str	r6, [%[r], r5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_sqr_8(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	r14, #0\n\t"
-        "#  A[0] * A[0]\n\t"
-        "ldr	r10, [%[a], #0]\n\t"
-        "umull	r8, r3, r10, r10\n\t"
-        "mov	r4, #0\n\t"
-        "str	r8, [%[tmp]]\n\t"
-        "#  A[0] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #4]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[1] * A[1]\n\t"
-        "ldr	r10, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[tmp], #8]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[1] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[tmp], #12]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[1] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[2] * A[2]\n\t"
-        "ldr	r10, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[tmp], #16]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[tmp], #20]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[3]\n\t"
-        "ldr	r10, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[tmp], #24]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #0]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r2, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[2] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r3, r3, r5\n\t"
-        "adcs	r4, r4, r6\n\t"
-        "adc	r2, r2, r7\n\t"
-        "str	r3, [%[tmp], #28]\n\t"
-        "#  A[1] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #4]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r3, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[2] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[3] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[4]\n\t"
-        "ldr	r10, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r4, r4, r5\n\t"
-        "adcs	r2, r2, r6\n\t"
-        "adc	r3, r3, r7\n\t"
-        "str	r4, [%[r], #32]\n\t"
-        "#  A[2] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #8]\n\t"
-        "umull	r5, r6, r10, r8\n\t"
-        "mov	r4, #0\n\t"
-        "mov	r7, #0\n\t"
-        "#  A[3] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "#  A[4] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r5, r5, r8\n\t"
-        "adcs	r6, r6, r9\n\t"
-        "adc	r7, r7, r14\n\t"
-        "adds	r5, r5, r5\n\t"
-        "adcs	r6, r6, r6\n\t"
-        "adc	r7, r7, r7\n\t"
-        "adds	r2, r2, r5\n\t"
-        "adcs	r3, r3, r6\n\t"
-        "adc	r4, r4, r7\n\t"
-        "str	r2, [%[r], #36]\n\t"
-        "#  A[3] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #12]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[4] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "#  A[5] * A[5]\n\t"
-        "ldr	r10, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #40]\n\t"
-        "#  A[4] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #16]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r14, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "#  A[5] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adcs	r2, r2, r9\n\t"
-        "adc	r3, r3, r14\n\t"
-        "str	r4, [%[r], #44]\n\t"
-        "#  A[5] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #20]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r14, r14\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "#  A[6] * A[6]\n\t"
-        "ldr	r10, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r2, r2, r8\n\t"
-        "adcs	r3, r3, r9\n\t"
-        "adc	r4, r4, r14\n\t"
-        "str	r2, [%[r], #48]\n\t"
-        "#  A[6] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "ldr	r8, [%[a], #24]\n\t"
-        "umull	r8, r9, r10, r8\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r14, r14\n\t"
-        "adds	r3, r3, r8\n\t"
-        "adcs	r4, r4, r9\n\t"
-        "adc	r2, r2, r14\n\t"
-        "str	r3, [%[r], #52]\n\t"
-        "#  A[7] * A[7]\n\t"
-        "ldr	r10, [%[a], #28]\n\t"
-        "umull	r8, r9, r10, r10\n\t"
-        "adds	r4, r4, r8\n\t"
-        "adc	r2, r2, r9\n\t"
-        "str	r4, [%[r], #56]\n\t"
-        "str	r2, [%[r], #60]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Order-2 for the P256 curve. */
-static const uint32_t p256_order_2[8] = {
-    0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
-    0x00000000,0xffffffff
-};
-#else
-/* The low half of the order-2 of the P256 curve. */
-static const uint32_t p256_order_low[4] = {
-    0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad
-};
-#endif /* WOLFSSL_SP_SMALL */
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_8(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_8(r, a, b);
-    sp_256_mont_reduce_8(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_8(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_8(r, a);
-    sp_256_mont_reduce_8(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_8(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_8(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_8(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_8(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 8);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_8(t, t);
-        if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_8(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 8);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 8;
-    sp_digit* t3 = td + 4 * 8;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_8(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_8(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_8(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_8(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_8(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_8(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_8(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_8(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_8(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_8(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_8(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_8(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_8(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_8(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_8(t2, t2, 4);
-    sp_256_mont_mul_order_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_8(t2, t2, 4);
-    sp_256_mont_mul_order_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_8(t2, t2, 4);
-    sp_256_mont_mul_order_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_8(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_8(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_avx2_8(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_avx2_8(r, a, b);
-    sp_256_mont_reduce_avx2_8(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_avx2_8(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_avx2_8(r, a);
-    sp_256_mont_reduce_avx2_8(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_avx2_8(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_avx2_8(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_avx2_8(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_avx2_8(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 8);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_8(t, t);
-        if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_8(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 8);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 8;
-    sp_digit* t3 = td + 4 * 8;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_avx2_8(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_avx2_8(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_avx2_8(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_avx2_8(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_avx2_8(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_8(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_8(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_8(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_avx2_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_avx2_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_avx2_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_8(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_8(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_8(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_avx2_8(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_avx2_8(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
-#ifdef HAVE_ECC_SIGN
-#ifndef SP_ECC_MAX_SIG_GEN
-#define SP_ECC_MAX_SIG_GEN  64
-#endif
-
-/* Sign the hash using the private key.
- *   e = [hash, 256 bits] from binary
- *   r = (k.G)->x mod order
- *   s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit ed[2*8];
-    sp_digit xd[2*8];
-    sp_digit kd[2*8];
-    sp_digit rd[2*8];
-    sp_digit td[3 * 2*8];
-    sp_point p;
-#endif
-    sp_digit* e = NULL;
-    sp_digit* x = NULL;
-    sp_digit* k = NULL;
-    sp_digit* r = NULL;
-    sp_digit* tmp = NULL;
-    sp_point* point = NULL;
-    sp_digit carry;
-    sp_digit* s;
-    sp_digit* kInv;
-    int err = MP_OKAY;
-    int32_t c;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            e = d + 0 * 8;
-            x = d + 2 * 8;
-            k = d + 4 * 8;
-            r = d + 6 * 8;
-            tmp = d + 8 * 8;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    e = ed;
-    x = xd;
-    k = kd;
-    r = rd;
-    tmp = td;
-#endif
-    s = e;
-    kInv = k;
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(e, 8, hash, hashLen);
-        sp_256_from_mp(x, 8, priv);
-    }
-
-    for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
-        /* New random point. */
-        err = sp_256_ecc_gen_k_8(rng, k);
-        if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                err = sp_256_ecc_mulmod_base_avx2_8(point, k, 1, heap);
-            else
-#endif
-                err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
-        }
-
-        if (err == MP_OKAY) {
-            /* r = point->x mod order */
-            XMEMCPY(r, point->x, sizeof(sp_digit) * 8);
-            sp_256_norm_8(r);
-            c = sp_256_cmp_8(r, p256_order);
-            sp_256_cond_sub_8(r, r, p256_order, 0 - (c >= 0));
-            sp_256_norm_8(r);
-
-            /* Conv k to Montgomery form (mod order) */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_8(k, k, p256_norm_order);
-            else
-#endif
-                sp_256_mul_8(k, k, p256_norm_order);
-            err = sp_256_mod_8(k, k, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_8(k);
-            /* kInv = 1/k mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_inv_order_avx2_8(kInv, k, tmp);
-            else
-#endif
-                sp_256_mont_inv_order_8(kInv, k, tmp);
-            sp_256_norm_8(kInv);
-
-            /* s = r * x + e */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_8(x, x, r);
-            else
-#endif
-                sp_256_mul_8(x, x, r);
-            err = sp_256_mod_8(x, x, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_8(x);
-            carry = sp_256_add_8(s, e, x);
-            sp_256_cond_sub_8(s, s, p256_order, 0 - carry);
-            sp_256_norm_8(s);
-            c = sp_256_cmp_8(s, p256_order);
-            sp_256_cond_sub_8(s, s, p256_order, 0 - (c >= 0));
-            sp_256_norm_8(s);
-
-            /* s = s * k^-1 mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_mul_order_avx2_8(s, s, kInv);
-            else
-#endif
-                sp_256_mont_mul_order_8(s, s, kInv);
-            sp_256_norm_8(s);
-
-            /* Check that signature is usable. */
-            if (!sp_256_iszero_8(s))
-                break;
-        }
-    }
-
-    if (i == 0)
-        err = RNG_FAILURE_E;
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(r, rm);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(s, sm);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8);
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    XMEMSET(e, 0, sizeof(sp_digit) * 2 * 8);
-    XMEMSET(x, 0, sizeof(sp_digit) * 2 * 8);
-    XMEMSET(k, 0, sizeof(sp_digit) * 2 * 8);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8);
-    XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*8);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-/* Verify the signature values with the hash and public key.
- *   e = Truncate(hash, 256)
- *   u1 = e/s mod order
- *   u2 = r/s mod order
- *   r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- *   (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- *   (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
-    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit u1d[2*8];
-    sp_digit u2d[2*8];
-    sp_digit sd[2*8];
-    sp_digit tmpd[2*8 * 5];
-    sp_point p1d;
-    sp_point p2d;
-#endif
-    sp_digit* u1;
-    sp_digit* u2;
-    sp_digit* s;
-    sp_digit* tmp;
-    sp_point* p1;
-    sp_point* p2 = NULL;
-    sp_digit carry;
-    int32_t c;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p1d, p1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p2d, p2);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 16 * 8, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            u1  = d + 0 * 8;
-            u2  = d + 2 * 8;
-            s   = d + 4 * 8;
-            tmp = d + 6 * 8;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    u1 = u1d;
-    u2 = u2d;
-    s  = sd;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(u1, 8, hash, hashLen);
-        sp_256_from_mp(u2, 8, r);
-        sp_256_from_mp(s, 8, sm);
-        sp_256_from_mp(p2->x, 8, pX);
-        sp_256_from_mp(p2->y, 8, pY);
-        sp_256_from_mp(p2->z, 8, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_avx2_8(s, s, p256_norm_order);
-        else
-#endif
-            sp_256_mul_8(s, s, p256_norm_order);
-        err = sp_256_mod_8(s, s, p256_order);
-    }
-    if (err == MP_OKAY) {
-        sp_256_norm_8(s);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_inv_order_avx2_8(s, s, tmp);
-            sp_256_mont_mul_order_avx2_8(u1, u1, s);
-            sp_256_mont_mul_order_avx2_8(u2, u2, s);
-        }
-        else
-#endif
-        {
-            sp_256_mont_inv_order_8(s, s, tmp);
-            sp_256_mont_mul_order_8(u1, u1, s);
-            sp_256_mont_mul_order_8(u2, u2, s);
-        }
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_8(p1, u1, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap);
-    }
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_8(p2, p2, u2, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_8(p1, p1, p2, tmp);
-        else
-#endif
-            sp_256_proj_point_add_8(p1, p1, p2, tmp);
-
-        /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
-        /* Reload r and convert to Montgomery form. */
-        sp_256_from_mp(u2, 8, r);
-        err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* u1 = r.z'.z' mod prime */
-        sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod);
-        *res = sp_256_cmp_8(p1->x, u1) == 0;
-        if (*res == 0) {
-            /* Reload r and add order. */
-            sp_256_from_mp(u2, 8, r);
-            carry = sp_256_add_8(u2, u2, p256_order);
-            /* Carry means result is greater than mod and is not valid. */
-            if (!carry) {
-                sp_256_norm_8(u2);
-
-                /* Compare with mod and if greater or equal then not valid. */
-                c = sp_256_cmp_8(u2, p256_mod);
-                if (c < 0) {
-                    /* Convert to Montogomery form */
-                    err = sp_256_mod_mul_norm_8(u2, u2, p256_mod);
-                    if (err == MP_OKAY) {
-                        /* u1 = (r + 1*order).z'.z' mod prime */
-                        sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
-                                                                  p256_mp_mod);
-                        *res = sp_256_cmp_8(p1->x, u2) == 0;
-                    }
-                }
-            }
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p1, 0, heap);
-    sp_ecc_point_free(p2, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_CHECK_KEY
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * point  EC point.
- * heap   Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-static int sp_256_ecc_is_point_8(sp_point* point, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit t1d[2*8];
-    sp_digit t2d[2*8];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 8;
-        t2 = d + 2 * 8;
-    }
-    else
-        err = MEMORY_E;
-#else
-    (void)heap;
-
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_sqr_8(t1, point->y);
-        sp_256_mod_8(t1, t1, p256_mod);
-        sp_256_sqr_8(t2, point->x);
-        sp_256_mod_8(t2, t2, p256_mod);
-        sp_256_mul_8(t2, t2, point->x);
-        sp_256_mod_8(t2, t2, p256_mod);
-	sp_256_sub_8(t2, p256_mod, t2);
-        sp_256_mont_add_8(t1, t1, t2, p256_mod);
-
-        sp_256_mont_add_8(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_8(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_8(t1, t1, point->x, p256_mod);
-
-        if (sp_256_cmp_8(t1, p256_b) != 0)
-            err = MP_VAL;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX  X ordinate of EC point.
- * pY  Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point pubd;
-#endif
-    sp_point* pub;
-    byte one[1] = { 1 };
-    int err;
-
-    err = sp_ecc_point_new(NULL, pubd, pub);
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 8, pX);
-        sp_256_from_mp(pub->y, 8, pY);
-        sp_256_from_bin(pub->z, 8, one, sizeof(one));
-
-        err = sp_256_ecc_is_point_8(pub, NULL);
-    }
-
-    sp_ecc_point_free(pub, 0, NULL);
-
-    return err;
-}
-
-/* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX     X ordinate of EC point.
- * pY     Y ordinate of EC point.
- * privm  Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit privd[8];
-    sp_point pubd;
-    sp_point pd;
-#endif
-    sp_digit* priv = NULL;
-    sp_point* pub;
-    sp_point* p = NULL;
-    byte one[1] = { 1 };
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, pubd, pub);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        priv = XMALLOC(sizeof(sp_digit) * 8, heap, DYNAMIC_TYPE_ECC);
-        if (priv == NULL)
-            err = MEMORY_E;
-    }
-#else
-    priv = privd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 8, pX);
-        sp_256_from_mp(pub->y, 8, pY);
-        sp_256_from_bin(pub->z, 8, one, sizeof(one));
-        sp_256_from_mp(priv, 8, privm);
-
-        /* Check point at infinitiy. */
-        if (sp_256_iszero_8(pub->x) &&
-            sp_256_iszero_8(pub->y))
-            err = ECC_INF_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check range of X and Y */
-        if (sp_256_cmp_8(pub->x, p256_mod) >= 0 ||
-            sp_256_cmp_8(pub->y, p256_mod) >= 0)
-            err = ECC_OUT_OF_RANGE_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check point is on curve */
-        err = sp_256_ecc_is_point_8(pub, heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* Point * order = infinity */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_8(p, pub, p256_order, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is infinity */
-        if (!sp_256_iszero_8(p->x) ||
-            !sp_256_iszero_8(p->y)) {
-            err = ECC_INF_E;
-        }
-    }
-
-    if (err == MP_OKAY) {
-        /* Base * private = point */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_8(p, priv, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is public key */
-        if (sp_256_cmp_8(p->x, pub->x) != 0 ||
-            sp_256_cmp_8(p->y, pub->y) != 0) {
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (priv != NULL)
-        XFREE(priv, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(pub, 0, heap);
-
-    return err;
-}
-#endif
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-/* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX   First EC point's X ordinate.
- * pY   First EC point's Y ordinate.
- * pZ   First EC point's Z ordinate.
- * qX   Second EC point's X ordinate.
- * qY   Second EC point's Y ordinate.
- * qZ   Second EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 8 * 5];
-    sp_point pd;
-    sp_point qd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    sp_point* q = NULL;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(NULL, qd, q);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 8, pX);
-        sp_256_from_mp(p->y, 8, pY);
-        sp_256_from_mp(p->z, 8, pZ);
-        sp_256_from_mp(q->x, 8, qX);
-        sp_256_from_mp(q->y, 8, qY);
-        sp_256_from_mp(q->z, 8, qZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_8(p, p, q, tmp);
-        else
-#endif
-            sp_256_proj_point_add_8(p, p, q, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(q, 0, NULL);
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 8 * 2];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 8, pX);
-        sp_256_from_mp(p->y, 8, pY);
-        sp_256_from_mp(p->z, 8, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_dbl_avx2_8(p, p, tmp);
-        else
-#endif
-            sp_256_proj_point_dbl_8(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 8 * 4];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 8, pX);
-        sp_256_from_mp(p->y, 8, pY);
-        sp_256_from_mp(p->z, 8, pZ);
-
-        sp_256_map_8(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, pX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
-#ifdef HAVE_COMP_KEY
-/* Find the square root of a number mod the prime of the curve.
- *
- * y  The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mont_sqrt_8(sp_digit* y)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit t1d[2 * 8];
-    sp_digit t2d[2 * 8];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 8;
-        t2 = d + 2 * 8;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_avx2_8(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_avx2_8(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_avx2_8(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_avx2_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_avx2_8(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_avx2_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_avx2_8(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_avx2_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_avx2_8(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_avx2_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_avx2_8(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_avx2_8(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_avx2_8(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_avx2_8(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_avx2_8(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Uncompress the point given the X ordinate.
- *
- * xm    X ordinate.
- * odd   Whether the Y ordinate is odd.
- * ym    Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit xd[2 * 8];
-    sp_digit yd[2 * 8];
-#endif
-    sp_digit* x;
-    sp_digit* y;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        x = d + 0 * 8;
-        y = d + 2 * 8;
-    }
-    else
-        err = MEMORY_E;
-#else
-    x = xd;
-    y = yd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(x, 8, xm);
-
-        err = sp_256_mod_mul_norm_8(x, x, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* y = x^3 */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_sqr_avx2_8(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_avx2_8(y, y, x, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod);
-        }
-        /* y = x^3 - 3x */
-        sp_256_mont_sub_8(y, y, x, p256_mod);
-        sp_256_mont_sub_8(y, y, x, p256_mod);
-        sp_256_mont_sub_8(y, y, x, p256_mod);
-        /* y = x^3 - 3x + b */
-        err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod);
-    }
-    if (err == MP_OKAY) {
-        sp_256_mont_add_8(y, y, x, p256_mod);
-        /* y = sqrt(x^3 - 3x + b) */
-        err = sp_256_mont_sqrt_8(y);
-    }
-    if (err == MP_OKAY) {
-        XMEMSET(y + 8, 0, 8 * sizeof(sp_digit));
-        sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod);
-        if (((y[0] ^ odd) & 1) != 0)
-            sp_256_mont_sub_8(y, p256_mod, y, p256_mod);
-
-        err = sp_256_to_mp(y, ym);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-#endif /* WOLFSSL_SP_ARM32_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
--- a/wolfcrypt/src/sp_arm64.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29842 +0,0 @@
-/* sp.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#ifdef RSA_LOW_MEM
-#define SP_RSA_PRIVATE_EXP_D
-
-#ifndef WOLFSSL_SP_SMALL
-#define WOLFSSL_SP_SMALL
-#endif
-#endif
-
-#include <wolfssl/wolfcrypt/sp.h>
-
-#ifdef WOLFSSL_SP_ARM64_ASM
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
-#ifndef WOLFSSL_SP_NO_2048
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 256
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_2048_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 2048 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<32 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "ldp	x8, x9, [%[a], 0]\n\t"
-        "ldp	x10, x11, [%[a], 16]\n\t"
-        "ldp	x12, x13, [%[a], 32]\n\t"
-        "ldp	x14, x15, [%[a], 48]\n\t"
-        "ldp	x16, x17, [%[b], 0]\n\t"
-        "ldp	x18, x19, [%[b], 16]\n\t"
-        "ldp	x20, x21, [%[b], 32]\n\t"
-        "ldp	x22, x23, [%[b], 48]\n\t"
-        "#  A[0] * B[0]\n\t"
-        "mul	x3, x8, x16\n\t"
-        "umulh	x4, x8, x16\n\t"
-        "str	x3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "mul	x6, x8, x17\n\t"
-        "umulh	x7, x8, x17\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adc	x5, xzr, x7\n\t"
-        "#  A[1] * B[0]\n\t"
-        "mul	x6, x9, x16\n\t"
-        "umulh	x7, x9, x16\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "str	x4, [%[tmp], 8]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "mul	x6, x8, x18\n\t"
-        "umulh	x7, x8, x18\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[1]\n\t"
-        "mul	x6, x9, x17\n\t"
-        "umulh	x7, x9, x17\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[0]\n\t"
-        "mul	x6, x10, x16\n\t"
-        "umulh	x7, x10, x16\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 16]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "mul	x6, x8, x19\n\t"
-        "umulh	x7, x8, x19\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[2]\n\t"
-        "mul	x6, x9, x18\n\t"
-        "umulh	x7, x9, x18\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[1]\n\t"
-        "mul	x6, x10, x17\n\t"
-        "umulh	x7, x10, x17\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[0]\n\t"
-        "mul	x6, x11, x16\n\t"
-        "umulh	x7, x11, x16\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 24]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "mul	x6, x8, x20\n\t"
-        "umulh	x7, x8, x20\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[3]\n\t"
-        "mul	x6, x9, x19\n\t"
-        "umulh	x7, x9, x19\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[2] * B[2]\n\t"
-        "mul	x6, x10, x18\n\t"
-        "umulh	x7, x10, x18\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[1]\n\t"
-        "mul	x6, x11, x17\n\t"
-        "umulh	x7, x11, x17\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[0]\n\t"
-        "mul	x6, x12, x16\n\t"
-        "umulh	x7, x12, x16\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 32]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "mul	x6, x8, x21\n\t"
-        "umulh	x7, x8, x21\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[4]\n\t"
-        "mul	x6, x9, x20\n\t"
-        "umulh	x7, x9, x20\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[3]\n\t"
-        "mul	x6, x10, x19\n\t"
-        "umulh	x7, x10, x19\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[3] * B[2]\n\t"
-        "mul	x6, x11, x18\n\t"
-        "umulh	x7, x11, x18\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[4] * B[1]\n\t"
-        "mul	x6, x12, x17\n\t"
-        "umulh	x7, x12, x17\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[0]\n\t"
-        "mul	x6, x13, x16\n\t"
-        "umulh	x7, x13, x16\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 40]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "mul	x6, x8, x22\n\t"
-        "umulh	x7, x8, x22\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[5]\n\t"
-        "mul	x6, x9, x21\n\t"
-        "umulh	x7, x9, x21\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[4]\n\t"
-        "mul	x6, x10, x20\n\t"
-        "umulh	x7, x10, x20\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[3]\n\t"
-        "mul	x6, x11, x19\n\t"
-        "umulh	x7, x11, x19\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[4] * B[2]\n\t"
-        "mul	x6, x12, x18\n\t"
-        "umulh	x7, x12, x18\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[5] * B[1]\n\t"
-        "mul	x6, x13, x17\n\t"
-        "umulh	x7, x13, x17\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[0]\n\t"
-        "mul	x6, x14, x16\n\t"
-        "umulh	x7, x14, x16\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 48]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "mul	x6, x8, x23\n\t"
-        "umulh	x7, x8, x23\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[6]\n\t"
-        "mul	x6, x9, x22\n\t"
-        "umulh	x7, x9, x22\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[2] * B[5]\n\t"
-        "mul	x6, x10, x21\n\t"
-        "umulh	x7, x10, x21\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[4]\n\t"
-        "mul	x6, x11, x20\n\t"
-        "umulh	x7, x11, x20\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[3]\n\t"
-        "mul	x6, x12, x19\n\t"
-        "umulh	x7, x12, x19\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * B[2]\n\t"
-        "mul	x6, x13, x18\n\t"
-        "umulh	x7, x13, x18\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[6] * B[1]\n\t"
-        "mul	x6, x14, x17\n\t"
-        "umulh	x7, x14, x17\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[0]\n\t"
-        "mul	x6, x15, x16\n\t"
-        "umulh	x7, x15, x16\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 56]\n\t"
-        "#  A[1] * B[7]\n\t"
-        "mul	x6, x9, x23\n\t"
-        "umulh	x7, x9, x23\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[2] * B[6]\n\t"
-        "mul	x6, x10, x22\n\t"
-        "umulh	x7, x10, x22\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[3] * B[5]\n\t"
-        "mul	x6, x11, x21\n\t"
-        "umulh	x7, x11, x21\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[4] * B[4]\n\t"
-        "mul	x6, x12, x20\n\t"
-        "umulh	x7, x12, x20\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[3]\n\t"
-        "mul	x6, x13, x19\n\t"
-        "umulh	x7, x13, x19\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * B[2]\n\t"
-        "mul	x6, x14, x18\n\t"
-        "umulh	x7, x14, x18\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[7] * B[1]\n\t"
-        "mul	x6, x15, x17\n\t"
-        "umulh	x7, x15, x17\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 64]\n\t"
-        "#  A[2] * B[7]\n\t"
-        "mul	x6, x10, x23\n\t"
-        "umulh	x7, x10, x23\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[3] * B[6]\n\t"
-        "mul	x6, x11, x22\n\t"
-        "umulh	x7, x11, x22\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[4] * B[5]\n\t"
-        "mul	x6, x12, x21\n\t"
-        "umulh	x7, x12, x21\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[5] * B[4]\n\t"
-        "mul	x6, x13, x20\n\t"
-        "umulh	x7, x13, x20\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[3]\n\t"
-        "mul	x6, x14, x19\n\t"
-        "umulh	x7, x14, x19\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[7] * B[2]\n\t"
-        "mul	x6, x15, x18\n\t"
-        "umulh	x7, x15, x18\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 72]\n\t"
-        "#  A[3] * B[7]\n\t"
-        "mul	x6, x11, x23\n\t"
-        "umulh	x7, x11, x23\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[4] * B[6]\n\t"
-        "mul	x6, x12, x22\n\t"
-        "umulh	x7, x12, x22\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * B[5]\n\t"
-        "mul	x6, x13, x21\n\t"
-        "umulh	x7, x13, x21\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[6] * B[4]\n\t"
-        "mul	x6, x14, x20\n\t"
-        "umulh	x7, x14, x20\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[3]\n\t"
-        "mul	x6, x15, x19\n\t"
-        "umulh	x7, x15, x19\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 80]\n\t"
-        "#  A[4] * B[7]\n\t"
-        "mul	x6, x12, x23\n\t"
-        "umulh	x7, x12, x23\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[5] * B[6]\n\t"
-        "mul	x6, x13, x22\n\t"
-        "umulh	x7, x13, x22\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * B[5]\n\t"
-        "mul	x6, x14, x21\n\t"
-        "umulh	x7, x14, x21\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[7] * B[4]\n\t"
-        "mul	x6, x15, x20\n\t"
-        "umulh	x7, x15, x20\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 88]\n\t"
-        "#  A[5] * B[7]\n\t"
-        "mul	x6, x13, x23\n\t"
-        "umulh	x7, x13, x23\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[6] * B[6]\n\t"
-        "mul	x6, x14, x22\n\t"
-        "umulh	x7, x14, x22\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[7] * B[5]\n\t"
-        "mul	x6, x15, x21\n\t"
-        "umulh	x7, x15, x21\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 96]\n\t"
-        "#  A[6] * B[7]\n\t"
-        "mul	x6, x14, x23\n\t"
-        "umulh	x7, x14, x23\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[7] * B[6]\n\t"
-        "mul	x6, x15, x22\n\t"
-        "umulh	x7, x15, x22\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 104]\n\t"
-        "#  A[7] * B[7]\n\t"
-        "mul	x6, x15, x23\n\t"
-        "umulh	x7, x15, x23\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "stp	x5, x3, [%[r], 112]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "ldp	x12, x13, [%[a], 16]\n\t"
-        "ldp	x14, x15, [%[a], 32]\n\t"
-        "ldp	x16, x17, [%[a], 48]\n\t"
-        "#  A[0] * A[0]\n\t"
-        "mul	x2, x10, x10\n\t"
-        "umulh	x3, x10, x10\n\t"
-        "str	x2, [%[tmp]]\n\t"
-        "mov	x4, 0\n\t"
-        "#  A[0] * A[1]\n\t"
-        "mul	x8, x10, x11\n\t"
-        "umulh	x9, x10, x11\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[tmp], 8]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "mul	x8, x10, x12\n\t"
-        "umulh	x9, x10, x12\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[1] * A[1]\n\t"
-        "mul	x8, x11, x11\n\t"
-        "umulh	x9, x11, x11\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 16]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "mul	x8, x10, x13\n\t"
-        "umulh	x9, x10, x13\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[1] * A[2]\n\t"
-        "mul	x8, x11, x12\n\t"
-        "umulh	x9, x11, x12\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[tmp], 24]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "mul	x8, x10, x14\n\t"
-        "umulh	x9, x10, x14\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[1] * A[3]\n\t"
-        "mul	x8, x11, x13\n\t"
-        "umulh	x9, x11, x13\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[2] * A[2]\n\t"
-        "mul	x8, x12, x12\n\t"
-        "umulh	x9, x12, x12\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[tmp], 32]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "mul	x5, x10, x15\n\t"
-        "umulh	x6, x10, x15\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[4]\n\t"
-        "mul	x8, x11, x14\n\t"
-        "umulh	x9, x11, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[3]\n\t"
-        "mul	x8, x12, x13\n\t"
-        "umulh	x9, x12, x13\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[tmp], 40]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "mul	x5, x10, x16\n\t"
-        "umulh	x6, x10, x16\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "mul	x8, x11, x15\n\t"
-        "umulh	x9, x11, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[4]\n\t"
-        "mul	x8, x12, x14\n\t"
-        "umulh	x9, x12, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[3]\n\t"
-        "mul	x8, x13, x13\n\t"
-        "umulh	x9, x13, x13\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[tmp], 48]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "mul	x5, x10, x17\n\t"
-        "umulh	x6, x10, x17\n\t"
-        "mov	x2, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "mul	x8, x11, x16\n\t"
-        "umulh	x9, x11, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[5]\n\t"
-        "mul	x8, x12, x15\n\t"
-        "umulh	x9, x12, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[4]\n\t"
-        "mul	x8, x13, x14\n\t"
-        "umulh	x9, x13, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x3, x3, x5\n\t"
-        "adcs	x4, x4, x6\n\t"
-        "adc	x2, x2, x7\n\t"
-        "str	x3, [%[tmp], 56]\n\t"
-        "#  A[1] * A[7]\n\t"
-        "mul	x5, x11, x17\n\t"
-        "umulh	x6, x11, x17\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[2] * A[6]\n\t"
-        "mul	x8, x12, x16\n\t"
-        "umulh	x9, x12, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[5]\n\t"
-        "mul	x8, x13, x15\n\t"
-        "umulh	x9, x13, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[4]\n\t"
-        "mul	x8, x14, x14\n\t"
-        "umulh	x9, x14, x14\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[r], 64]\n\t"
-        "#  A[2] * A[7]\n\t"
-        "mul	x5, x12, x17\n\t"
-        "umulh	x6, x12, x17\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[3] * A[6]\n\t"
-        "mul	x8, x13, x16\n\t"
-        "umulh	x9, x13, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[5]\n\t"
-        "mul	x8, x14, x15\n\t"
-        "umulh	x9, x14, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[r], 72]\n\t"
-        "#  A[3] * A[7]\n\t"
-        "mul	x8, x13, x17\n\t"
-        "umulh	x9, x13, x17\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[4] * A[6]\n\t"
-        "mul	x8, x14, x16\n\t"
-        "umulh	x9, x14, x16\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[5] * A[5]\n\t"
-        "mul	x8, x15, x15\n\t"
-        "umulh	x9, x15, x15\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[r], 80]\n\t"
-        "#  A[4] * A[7]\n\t"
-        "mul	x8, x14, x17\n\t"
-        "umulh	x9, x14, x17\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * A[6]\n\t"
-        "mul	x8, x15, x16\n\t"
-        "umulh	x9, x15, x16\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 88]\n\t"
-        "#  A[5] * A[7]\n\t"
-        "mul	x8, x15, x17\n\t"
-        "umulh	x9, x15, x17\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * A[6]\n\t"
-        "mul	x8, x16, x16\n\t"
-        "umulh	x9, x16, x16\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[r], 96]\n\t"
-        "#  A[6] * A[7]\n\t"
-        "mul	x8, x16, x17\n\t"
-        "umulh	x9, x16, x17\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[r], 104]\n\t"
-        "#  A[7] * A[7]\n\t"
-        "mul	x8, x17, x17\n\t"
-        "umulh	x9, x17, x17\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adc	x2, x2, x9\n\t"
-        "stp	x4, x2, [%[r], 112]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x2, x3, [%[a], 0]\n\t"
-        "ldp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x6, x7, [%[b], 0]\n\t"
-        "ldp	x8, x9, [%[b], 16]\n\t"
-        "subs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 0]\n\t"
-        "stp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x2, x3, [%[a], 32]\n\t"
-        "ldp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x6, x7, [%[b], 32]\n\t"
-        "ldp	x8, x9, [%[b], 48]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 32]\n\t"
-        "stp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x2, x3, [%[a], 64]\n\t"
-        "ldp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x6, x7, [%[b], 64]\n\t"
-        "ldp	x8, x9, [%[b], 80]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 64]\n\t"
-        "stp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x2, x3, [%[a], 96]\n\t"
-        "ldp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x6, x7, [%[b], 96]\n\t"
-        "ldp	x8, x9, [%[b], 112]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 96]\n\t"
-        "stp	x4, x5, [%[a], 112]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "ldp	x3, x4, [%[a], 64]\n\t"
-        "ldp	x5, x6, [%[a], 80]\n\t"
-        "ldp	x7, x8, [%[b], 64]\n\t"
-        "ldp	x9, x10, [%[b], 80]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 64]\n\t"
-        "stp	x5, x6, [%[r], 80]\n\t"
-        "ldp	x3, x4, [%[a], 96]\n\t"
-        "ldp	x5, x6, [%[a], 112]\n\t"
-        "ldp	x7, x8, [%[b], 96]\n\t"
-        "ldp	x9, x10, [%[b], 112]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 96]\n\t"
-        "stp	x5, x6, [%[r], 112]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<8; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-    r[4] = a[4] & m;
-    r[5] = a[5] & m;
-    r[6] = a[6] & m;
-    r[7] = a[7] & m;
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit b1[8];
-    sp_digit z2[16];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_8(a1, a, &a[8]);
-    cb = sp_2048_add_8(b1, b, &b[8]);
-    u  = ca & cb;
-    sp_2048_mul_8(z1, a1, b1);
-    sp_2048_mul_8(z2, &a[8], &b[8]);
-    sp_2048_mul_8(z0, a, b);
-    sp_2048_mask_8(r + 16, a1, 0 - cb);
-    sp_2048_mask_8(b1, b1, 0 - ca);
-    u += sp_2048_add_8(r + 16, r + 16, b1);
-    u += sp_2048_sub_in_place_16(z1, z2);
-    u += sp_2048_sub_in_place_16(z1, z0);
-    u += sp_2048_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_2048_add_16(r + 16, r + 16, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[16];
-    sp_digit z1[16];
-    sp_digit a1[8];
-    sp_digit u;
-
-    u = sp_2048_add_8(a1, a, &a[8]);
-    sp_2048_sqr_8(z1, a1);
-    sp_2048_sqr_8(z2, &a[8]);
-    sp_2048_sqr_8(z0, a);
-    sp_2048_mask_8(r + 16, a1, 0 - u);
-    u += sp_2048_add_8(r + 16, r + 16, r + 16);
-    u += sp_2048_sub_in_place_16(z1, z2);
-    u += sp_2048_sub_in_place_16(z1, z0);
-    u += sp_2048_add_16(r + 8, r + 8, z1);
-    r[24] = u;
-    XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1));
-    sp_2048_add_16(r + 16, r + 16, z2);
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x2, x3, [%[a], 0]\n\t"
-        "ldp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x6, x7, [%[b], 0]\n\t"
-        "ldp	x8, x9, [%[b], 16]\n\t"
-        "subs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 0]\n\t"
-        "stp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x2, x3, [%[a], 32]\n\t"
-        "ldp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x6, x7, [%[b], 32]\n\t"
-        "ldp	x8, x9, [%[b], 48]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 32]\n\t"
-        "stp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x2, x3, [%[a], 64]\n\t"
-        "ldp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x6, x7, [%[b], 64]\n\t"
-        "ldp	x8, x9, [%[b], 80]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 64]\n\t"
-        "stp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x2, x3, [%[a], 96]\n\t"
-        "ldp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x6, x7, [%[b], 96]\n\t"
-        "ldp	x8, x9, [%[b], 112]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 96]\n\t"
-        "stp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x2, x3, [%[a], 128]\n\t"
-        "ldp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x6, x7, [%[b], 128]\n\t"
-        "ldp	x8, x9, [%[b], 144]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 128]\n\t"
-        "stp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x2, x3, [%[a], 160]\n\t"
-        "ldp	x4, x5, [%[a], 176]\n\t"
-        "ldp	x6, x7, [%[b], 160]\n\t"
-        "ldp	x8, x9, [%[b], 176]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 160]\n\t"
-        "stp	x4, x5, [%[a], 176]\n\t"
-        "ldp	x2, x3, [%[a], 192]\n\t"
-        "ldp	x4, x5, [%[a], 208]\n\t"
-        "ldp	x6, x7, [%[b], 192]\n\t"
-        "ldp	x8, x9, [%[b], 208]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 192]\n\t"
-        "stp	x4, x5, [%[a], 208]\n\t"
-        "ldp	x2, x3, [%[a], 224]\n\t"
-        "ldp	x4, x5, [%[a], 240]\n\t"
-        "ldp	x6, x7, [%[b], 224]\n\t"
-        "ldp	x8, x9, [%[b], 240]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 224]\n\t"
-        "stp	x4, x5, [%[a], 240]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "ldp	x3, x4, [%[a], 64]\n\t"
-        "ldp	x5, x6, [%[a], 80]\n\t"
-        "ldp	x7, x8, [%[b], 64]\n\t"
-        "ldp	x9, x10, [%[b], 80]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 64]\n\t"
-        "stp	x5, x6, [%[r], 80]\n\t"
-        "ldp	x3, x4, [%[a], 96]\n\t"
-        "ldp	x5, x6, [%[a], 112]\n\t"
-        "ldp	x7, x8, [%[b], 96]\n\t"
-        "ldp	x9, x10, [%[b], 112]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 96]\n\t"
-        "stp	x5, x6, [%[r], 112]\n\t"
-        "ldp	x3, x4, [%[a], 128]\n\t"
-        "ldp	x5, x6, [%[a], 144]\n\t"
-        "ldp	x7, x8, [%[b], 128]\n\t"
-        "ldp	x9, x10, [%[b], 144]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 128]\n\t"
-        "stp	x5, x6, [%[r], 144]\n\t"
-        "ldp	x3, x4, [%[a], 160]\n\t"
-        "ldp	x5, x6, [%[a], 176]\n\t"
-        "ldp	x7, x8, [%[b], 160]\n\t"
-        "ldp	x9, x10, [%[b], 176]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 160]\n\t"
-        "stp	x5, x6, [%[r], 176]\n\t"
-        "ldp	x3, x4, [%[a], 192]\n\t"
-        "ldp	x5, x6, [%[a], 208]\n\t"
-        "ldp	x7, x8, [%[b], 192]\n\t"
-        "ldp	x9, x10, [%[b], 208]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 192]\n\t"
-        "stp	x5, x6, [%[r], 208]\n\t"
-        "ldp	x3, x4, [%[a], 224]\n\t"
-        "ldp	x5, x6, [%[a], 240]\n\t"
-        "ldp	x7, x8, [%[b], 224]\n\t"
-        "ldp	x9, x10, [%[b], 240]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 224]\n\t"
-        "stp	x5, x6, [%[r], 240]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<16; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit b1[16];
-    sp_digit z2[32];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_16(a1, a, &a[16]);
-    cb = sp_2048_add_16(b1, b, &b[16]);
-    u  = ca & cb;
-    sp_2048_mul_16(z1, a1, b1);
-    sp_2048_mul_16(z2, &a[16], &b[16]);
-    sp_2048_mul_16(z0, a, b);
-    sp_2048_mask_16(r + 32, a1, 0 - cb);
-    sp_2048_mask_16(b1, b1, 0 - ca);
-    u += sp_2048_add_16(r + 32, r + 32, b1);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[32];
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit u;
-
-    u = sp_2048_add_16(a1, a, &a[16]);
-    sp_2048_sqr_16(z1, a1);
-    sp_2048_sqr_16(z2, &a[16]);
-    sp_2048_sqr_16(z0, a);
-    sp_2048_mask_16(r + 32, a1, 0 - u);
-    u += sp_2048_add_16(r + 32, r + 32, r + 32);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x11, %[a], 256\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldp	x3, x4, [%[a]], #16\n\t"
-        "ldp	x5, x6, [%[a]], #16\n\t"
-        "ldp	x7, x8, [%[b]], #16\n\t"
-        "ldp	x9, x10, [%[b]], #16\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r]], #16\n\t"
-        "stp	x5, x6, [%[r]], #16\n\t"
-        "cset	%[c], cs\n\t"
-        "cmp	%[a], x11\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x10, %[a], 256\n\t"
-        "\n1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldp	x2, x3, [%[a]]\n\t"
-        "ldp	x4, x5, [%[a], #16]\n\t"
-        "ldp	x6, x7, [%[b]], #16\n\t"
-        "ldp	x8, x9, [%[b]], #16\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a]], #16\n\t"
-        "stp	x4, x5, [%[a]], #16\n\t"
-        "csetm	%[c], cc\n\t"
-        "cmp	%[a], x10\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[64];
-
-    __asm__ __volatile__ (
-        "mov	x5, 0\n\t"
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 248\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[b], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 256\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 496\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[64];
-
-    __asm__ __volatile__ (
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "mov	x5, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 248\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "cmp	x4, x3\n\t"
-        "b.eq	4f\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[a], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "b.al	5f\n\t"
-        "\n4:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "mul	x9, x10, x10\n\t"
-        "umulh	x10, x10, x10\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "\n5:\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 256\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x4\n\t"
-        "b.gt	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 496\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m)
-{
-    int i;
-
-    for (i=0; i<16; i++)
-        r[i] = a[i] & m;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x11, %[a], 128\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldp	x3, x4, [%[a]], #16\n\t"
-        "ldp	x5, x6, [%[a]], #16\n\t"
-        "ldp	x7, x8, [%[b]], #16\n\t"
-        "ldp	x9, x10, [%[b]], #16\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r]], #16\n\t"
-        "stp	x5, x6, [%[r]], #16\n\t"
-        "cset	%[c], cs\n\t"
-        "cmp	%[a], x11\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x10, %[a], 128\n\t"
-        "\n1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldp	x2, x3, [%[a]]\n\t"
-        "ldp	x4, x5, [%[a], #16]\n\t"
-        "ldp	x6, x7, [%[b]], #16\n\t"
-        "ldp	x8, x9, [%[b]], #16\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a]], #16\n\t"
-        "stp	x4, x5, [%[a]], #16\n\t"
-        "csetm	%[c], cc\n\t"
-        "cmp	%[a], x10\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[32];
-
-    __asm__ __volatile__ (
-        "mov	x5, 0\n\t"
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 120\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[b], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 128\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 240\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[32];
-
-    __asm__ __volatile__ (
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "mov	x5, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 120\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "cmp	x4, x3\n\t"
-        "b.eq	4f\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[a], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "b.al	5f\n\t"
-        "\n4:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "mul	x9, x10, x10\n\t"
-        "umulh	x10, x10, x10\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "\n5:\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 128\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x4\n\t"
-        "b.gt	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 240\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_16(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 16);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_16(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_16(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldr	x4, [%[a], x8]\n\t"
-        "ldr	x5, [%[b], x8]\n\t"
-        "and	x5, x5, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "csetm	%[c], cc\n\t"
-        "str	x4, [%[r], x8]\n\t"
-        "add	x8, x8, #8\n\t"
-        "cmp	x8, 128\n\t"
-        "b.lt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x6, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "ldr		x7, [%[b], 8]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "subs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 0]\n\t"
-        "str		x6, [%[r], 8]\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x6, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "ldr		x7, [%[b], 24]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 16]\n\t"
-        "str		x6, [%[r], 24]\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x6, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "ldr		x7, [%[b], 40]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "str		x6, [%[r], 40]\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x6, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "ldr		x7, [%[b], 56]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 48]\n\t"
-        "str		x6, [%[r], 56]\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x6, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "ldr		x7, [%[b], 72]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 64]\n\t"
-        "str		x6, [%[r], 72]\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x6, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "ldr		x7, [%[b], 88]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "str		x6, [%[r], 88]\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x6, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "ldr		x7, [%[b], 104]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 96]\n\t"
-        "str		x6, [%[r], 104]\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x6, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "ldr		x7, [%[b], 120]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 112]\n\t"
-        "str		x6, [%[r], 120]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "ldp       x12, x13, [%[m], 0]\n\t"
-        "ldp       x14, x15, [%[m], 16]\n\t"
-        "ldp       x16, x17, [%[m], 32]\n\t"
-        "ldp       x18, x19, [%[m], 48]\n\t"
-        "ldp       x20, x21, [%[m], 64]\n\t"
-        "ldp       x22, x23, [%[m], 80]\n\t"
-        "ldp       x24, x25, [%[m], 96]\n\t"
-        "ldp       x26, x27, [%[m], 112]\n\t"
-        "# i = 0\n\t"
-        "mov	x3, 0\n\t"
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	x8, %[mp], x10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	x9, [%[a], 0]\n\t"
-        "mul		x6, x12, x8\n\t"
-        "umulh	x7, x12, x8\n\t"
-        "adds	x10, x10, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	x9, [%[a], 8]\n\t"
-        "mul		x6, x13, x8\n\t"
-        "umulh	x7, x13, x8\n\t"
-        "adds	x10, x11, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x10, x10, x5\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	x11, [%[a], 16]\n\t"
-        "mul		x6, x14, x8\n\t"
-        "umulh	x7, x14, x8\n\t"
-        "adds	x11, x11, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x11, x11, x4\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	x9, [%[a], 24]\n\t"
-        "mul		x6, x15, x8\n\t"
-        "umulh	x7, x15, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 24]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	x9, [%[a], 32]\n\t"
-        "mul		x6, x16, x8\n\t"
-        "umulh	x7, x16, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 32]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	x9, [%[a], 40]\n\t"
-        "mul		x6, x17, x8\n\t"
-        "umulh	x7, x17, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 40]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	x9, [%[a], 48]\n\t"
-        "mul		x6, x18, x8\n\t"
-        "umulh	x7, x18, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 48]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	x9, [%[a], 56]\n\t"
-        "mul		x6, x19, x8\n\t"
-        "umulh	x7, x19, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 56]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	x9, [%[a], 64]\n\t"
-        "mul		x6, x20, x8\n\t"
-        "umulh	x7, x20, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 64]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	x9, [%[a], 72]\n\t"
-        "mul		x6, x21, x8\n\t"
-        "umulh	x7, x21, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 72]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	x9, [%[a], 80]\n\t"
-        "mul		x6, x22, x8\n\t"
-        "umulh	x7, x22, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 80]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	x9, [%[a], 88]\n\t"
-        "mul		x6, x23, x8\n\t"
-        "umulh	x7, x23, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 88]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	x9, [%[a], 96]\n\t"
-        "mul		x6, x24, x8\n\t"
-        "umulh	x7, x24, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 96]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	x9, [%[a], 104]\n\t"
-        "mul		x6, x25, x8\n\t"
-        "umulh	x7, x25, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 104]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	x9, [%[a], 112]\n\t"
-        "mul		x6, x26, x8\n\t"
-        "umulh	x7, x26, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 112]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	x9, [%[a], 120]\n\t"
-        "mul	x6, x27, x8\n\t"
-        "umulh	x7, x27, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x7, x7, %[ca]\n\t"
-        "cset  %[ca], cs\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 120]\n\t"
-        "ldr	x9, [%[a], 128]\n\t"
-        "adcs	x9, x9, x7\n\t"
-        "str	x9, [%[a], 128]\n\t"
-        "adc	%[ca], %[ca], xzr\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], 8\n\t"
-        "add	x3, x3, 8\n\t"
-        "cmp	x3, 128\n\t"
-        "blt	1b\n\t"
-        "str	x10, [%[a], 0]\n\t"
-        "str	x11, [%[a], 8]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27"
-    );
-
-    sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_16(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_16(r, a, b);
-    sp_2048_mont_reduce_16(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_16(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_16(r, a);
-    sp_2048_mont_reduce_16(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x5, %[b], x8\n\t"
-        "umulh	x3, %[b], x8\n\t"
-        "mov	x4, 0\n\t"
-        "str	x5, [%[r]]\n\t"
-        "mov	x5, 0\n\t"
-        "mov	x9, #8\n\t"
-        "1:\n\t"
-        "ldr	x8, [%[a], x9]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "str	x3, [%[r], x9]\n\t"
-        "mov	x3, x4\n\t"
-        "mov	x4, x5\n\t"
-        "mov	x5, #0\n\t"
-        "add	x9, x9, #8\n\t"
-        "cmp	x9, 128\n\t"
-        "b.lt	1b\n\t"
-        "str	x3, [%[r], 128]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x3, %[b], x8\n\t"
-        "umulh	x4, %[b], x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr		x8, [%[a], 8]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 8]\n\t"
-        "# A[2] * B\n\t"
-        "ldr		x8, [%[a], 16]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 16]\n\t"
-        "# A[3] * B\n\t"
-        "ldr		x8, [%[a], 24]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 24]\n\t"
-        "# A[4] * B\n\t"
-        "ldr		x8, [%[a], 32]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "# A[5] * B\n\t"
-        "ldr		x8, [%[a], 40]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 40]\n\t"
-        "# A[6] * B\n\t"
-        "ldr		x8, [%[a], 48]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 48]\n\t"
-        "# A[7] * B\n\t"
-        "ldr		x8, [%[a], 56]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 56]\n\t"
-        "# A[8] * B\n\t"
-        "ldr		x8, [%[a], 64]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 64]\n\t"
-        "# A[9] * B\n\t"
-        "ldr		x8, [%[a], 72]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 72]\n\t"
-        "# A[10] * B\n\t"
-        "ldr		x8, [%[a], 80]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "# A[11] * B\n\t"
-        "ldr		x8, [%[a], 88]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 88]\n\t"
-        "# A[12] * B\n\t"
-        "ldr		x8, [%[a], 96]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 96]\n\t"
-        "# A[13] * B\n\t"
-        "ldr		x8, [%[a], 104]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 104]\n\t"
-        "# A[14] * B\n\t"
-        "ldr		x8, [%[a], 112]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 112]\n\t"
-        "# A[15] * B\n\t"
-        "ldr	x8, [%[a], 120]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x3, [%[r], 120]\n\t"
-        "str	x4, [%[r], 128]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "lsr	x5, %[div], 32\n\t"
-        "add	x5, x5, 1\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x6, x3, 32\n\t"
-        "mul	x4, %[div], x6\n\t"
-        "umulh	x3, %[div], x6\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x3, x3, 32\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d0], %[div]\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x3, %[div], x3\n\t"
-        "sub	%[d0], %[d0], x3\n\t"
-        "mov	%[r], x6\n\t"
-
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "x3", "x4", "x5", "x6"
-    );
-
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_2048_cmp_16(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "mov	x6, 120\n\t"
-        "1:\n\t"
-        "ldr	x4, [%[a], x6]\n\t"
-        "ldr	x5, [%[b], x6]\n\t"
-        "and	x4, x4, x3\n\t"
-        "and	x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "sub	x6, x6, #8\n\t"
-        "b.cc	1b\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "ldr		x4, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 120]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 104]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 88]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 72]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 56]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 40]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 24]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 8]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_16(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[32], t2[17];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[15];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 16);
-    for (i=15; i>=0; i--) {
-        r1 = div_2048_word_16(t1[16 + i], t1[16 + i - 1], div);
-
-        sp_2048_mul_d_16(t2, d, r1);
-        t1[16 + i] += sp_2048_sub_in_place_16(&t1[i], t2);
-        t1[16 + i] -= t2[16];
-        sp_2048_mask_16(t2, d, t1[16 + i]);
-        t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2);
-        sp_2048_mask_16(t2, d, t1[16 + i]);
-        t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_16(t1, d) >= 0;
-    sp_2048_cond_sub_16(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_16(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_16(a, m, NULL, r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][32];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 32, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 32;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_16(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 16);
-        if (reduceA) {
-            err = sp_2048_mod_16(t[1] + 16, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_16(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16);
-            err = sp_2048_mod_16(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_16(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_16(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_16(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 60;
-        n <<= 4;
-        c = 60;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 60;
-                n <<= 4;
-                c = 60;
-            }
-            else if (c < 4) {
-                y = n >> 60;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 60) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-
-            sp_2048_mont_mul_16(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_mont_reduce_16(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_16(r, m) >= 0);
-        sp_2048_cond_sub_16(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][32];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 32;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_16(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 16);
-        if (reduceA) {
-            err = sp_2048_mod_16(t[1] + 16, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_16(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16);
-            err = sp_2048_mod_16(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_16(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_16(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_16(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_16(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_16(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_16(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_16(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_16(t[20], t[10], m, mp);
-        sp_2048_mont_mul_16(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_16(t[22], t[11], m, mp);
-        sp_2048_mont_mul_16(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_16(t[24], t[12], m, mp);
-        sp_2048_mont_mul_16(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_16(t[26], t[13], m, mp);
-        sp_2048_mont_mul_16(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_16(t[28], t[14], m, mp);
-        sp_2048_mont_mul_16(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_16(t[30], t[15], m, mp);
-        sp_2048_mont_mul_16(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-
-            sp_2048_mont_mul_16(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0xf;
-        sp_2048_mont_sqr_16(r, r, m, mp);
-        sp_2048_mont_sqr_16(r, r, m, mp);
-        sp_2048_mont_sqr_16(r, r, m, mp);
-        sp_2048_mont_sqr_16(r, r, m, mp);
-        sp_2048_mont_mul_16(r, r, t[y], m, mp);
-
-        XMEMSET(&r[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_mont_reduce_16(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_16(r, m) >= 0);
-        sp_2048_cond_sub_16(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 32);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_32(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldr	x4, [%[a], x8]\n\t"
-        "ldr	x5, [%[b], x8]\n\t"
-        "and	x5, x5, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "csetm	%[c], cc\n\t"
-        "str	x4, [%[r], x8]\n\t"
-        "add	x8, x8, #8\n\t"
-        "cmp	x8, 256\n\t"
-        "b.lt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x6, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "ldr		x7, [%[b], 8]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "subs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 0]\n\t"
-        "str		x6, [%[r], 8]\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x6, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "ldr		x7, [%[b], 24]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 16]\n\t"
-        "str		x6, [%[r], 24]\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x6, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "ldr		x7, [%[b], 40]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "str		x6, [%[r], 40]\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x6, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "ldr		x7, [%[b], 56]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 48]\n\t"
-        "str		x6, [%[r], 56]\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x6, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "ldr		x7, [%[b], 72]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 64]\n\t"
-        "str		x6, [%[r], 72]\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x6, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "ldr		x7, [%[b], 88]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "str		x6, [%[r], 88]\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x6, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "ldr		x7, [%[b], 104]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 96]\n\t"
-        "str		x6, [%[r], 104]\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x6, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "ldr		x7, [%[b], 120]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 112]\n\t"
-        "str		x6, [%[r], 120]\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x6, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "ldr		x7, [%[b], 136]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "str		x6, [%[r], 136]\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x6, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "ldr		x7, [%[b], 152]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 144]\n\t"
-        "str		x6, [%[r], 152]\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x6, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "ldr		x7, [%[b], 168]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 160]\n\t"
-        "str		x6, [%[r], 168]\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x6, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "ldr		x7, [%[b], 184]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "str		x6, [%[r], 184]\n\t"
-        "ldr		x4, [%[a], 192]\n\t"
-        "ldr		x6, [%[a], 200]\n\t"
-        "ldr		x5, [%[b], 192]\n\t"
-        "ldr		x7, [%[b], 200]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 192]\n\t"
-        "str		x6, [%[r], 200]\n\t"
-        "ldr		x4, [%[a], 208]\n\t"
-        "ldr		x6, [%[a], 216]\n\t"
-        "ldr		x5, [%[b], 208]\n\t"
-        "ldr		x7, [%[b], 216]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 208]\n\t"
-        "str		x6, [%[r], 216]\n\t"
-        "ldr		x4, [%[a], 224]\n\t"
-        "ldr		x6, [%[a], 232]\n\t"
-        "ldr		x5, [%[b], 224]\n\t"
-        "ldr		x7, [%[b], 232]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 224]\n\t"
-        "str		x6, [%[r], 232]\n\t"
-        "ldr		x4, [%[a], 240]\n\t"
-        "ldr		x6, [%[a], 248]\n\t"
-        "ldr		x5, [%[b], 240]\n\t"
-        "ldr		x7, [%[b], 248]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 240]\n\t"
-        "str		x6, [%[r], 248]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "ldp       x12, x13, [%[m], 0]\n\t"
-        "ldp       x14, x15, [%[m], 16]\n\t"
-        "ldp       x16, x17, [%[m], 32]\n\t"
-        "ldp       x18, x19, [%[m], 48]\n\t"
-        "ldp       x20, x21, [%[m], 64]\n\t"
-        "ldp       x22, x23, [%[m], 80]\n\t"
-        "ldp       x24, x25, [%[m], 96]\n\t"
-        "ldp       x26, x27, [%[m], 112]\n\t"
-        "# i = 0\n\t"
-        "mov	x3, 0\n\t"
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	x8, %[mp], x10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	x9, [%[a], 0]\n\t"
-        "mul		x6, x12, x8\n\t"
-        "umulh	x7, x12, x8\n\t"
-        "adds	x10, x10, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	x9, [%[a], 8]\n\t"
-        "mul		x6, x13, x8\n\t"
-        "umulh	x7, x13, x8\n\t"
-        "adds	x10, x11, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x10, x10, x5\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	x11, [%[a], 16]\n\t"
-        "mul		x6, x14, x8\n\t"
-        "umulh	x7, x14, x8\n\t"
-        "adds	x11, x11, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x11, x11, x4\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	x9, [%[a], 24]\n\t"
-        "mul		x6, x15, x8\n\t"
-        "umulh	x7, x15, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 24]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	x9, [%[a], 32]\n\t"
-        "mul		x6, x16, x8\n\t"
-        "umulh	x7, x16, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 32]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	x9, [%[a], 40]\n\t"
-        "mul		x6, x17, x8\n\t"
-        "umulh	x7, x17, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 40]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	x9, [%[a], 48]\n\t"
-        "mul		x6, x18, x8\n\t"
-        "umulh	x7, x18, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 48]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	x9, [%[a], 56]\n\t"
-        "mul		x6, x19, x8\n\t"
-        "umulh	x7, x19, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 56]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	x9, [%[a], 64]\n\t"
-        "mul		x6, x20, x8\n\t"
-        "umulh	x7, x20, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 64]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	x9, [%[a], 72]\n\t"
-        "mul		x6, x21, x8\n\t"
-        "umulh	x7, x21, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 72]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	x9, [%[a], 80]\n\t"
-        "mul		x6, x22, x8\n\t"
-        "umulh	x7, x22, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 80]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	x9, [%[a], 88]\n\t"
-        "mul		x6, x23, x8\n\t"
-        "umulh	x7, x23, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 88]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	x9, [%[a], 96]\n\t"
-        "mul		x6, x24, x8\n\t"
-        "umulh	x7, x24, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 96]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	x9, [%[a], 104]\n\t"
-        "mul		x6, x25, x8\n\t"
-        "umulh	x7, x25, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 104]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	x9, [%[a], 112]\n\t"
-        "mul		x6, x26, x8\n\t"
-        "umulh	x7, x26, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 112]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	x9, [%[a], 120]\n\t"
-        "mul		x6, x27, x8\n\t"
-        "umulh	x7, x27, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 120]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr		x7, [%[m], 128]\n\t"
-        "ldr	x9, [%[a], 128]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 128]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr		x7, [%[m], 136]\n\t"
-        "ldr	x9, [%[a], 136]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 136]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr		x7, [%[m], 144]\n\t"
-        "ldr	x9, [%[a], 144]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 144]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr		x7, [%[m], 152]\n\t"
-        "ldr	x9, [%[a], 152]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 152]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr		x7, [%[m], 160]\n\t"
-        "ldr	x9, [%[a], 160]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 160]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr		x7, [%[m], 168]\n\t"
-        "ldr	x9, [%[a], 168]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 168]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr		x7, [%[m], 176]\n\t"
-        "ldr	x9, [%[a], 176]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 176]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr		x7, [%[m], 184]\n\t"
-        "ldr	x9, [%[a], 184]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 184]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr		x7, [%[m], 192]\n\t"
-        "ldr	x9, [%[a], 192]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 192]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr		x7, [%[m], 200]\n\t"
-        "ldr	x9, [%[a], 200]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 200]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr		x7, [%[m], 208]\n\t"
-        "ldr	x9, [%[a], 208]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 208]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr		x7, [%[m], 216]\n\t"
-        "ldr	x9, [%[a], 216]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 216]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr		x7, [%[m], 224]\n\t"
-        "ldr	x9, [%[a], 224]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 224]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr		x7, [%[m], 232]\n\t"
-        "ldr	x9, [%[a], 232]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 232]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr		x7, [%[m], 240]\n\t"
-        "ldr	x9, [%[a], 240]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 240]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr	x7, [%[m], 248]\n\t"
-        "ldr	x9, [%[a], 248]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x7, x7, %[ca]\n\t"
-        "cset  %[ca], cs\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 248]\n\t"
-        "ldr	x9, [%[a], 256]\n\t"
-        "adcs	x9, x9, x7\n\t"
-        "str	x9, [%[a], 256]\n\t"
-        "adc	%[ca], %[ca], xzr\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], 8\n\t"
-        "add	x3, x3, 8\n\t"
-        "cmp	x3, 256\n\t"
-        "blt	1b\n\t"
-        "str	x10, [%[a], 0]\n\t"
-        "str	x11, [%[a], 8]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27"
-    );
-
-    sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_32(r, a, b);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_32(r, a);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x5, %[b], x8\n\t"
-        "umulh	x3, %[b], x8\n\t"
-        "mov	x4, 0\n\t"
-        "str	x5, [%[r]]\n\t"
-        "mov	x5, 0\n\t"
-        "mov	x9, #8\n\t"
-        "1:\n\t"
-        "ldr	x8, [%[a], x9]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "str	x3, [%[r], x9]\n\t"
-        "mov	x3, x4\n\t"
-        "mov	x4, x5\n\t"
-        "mov	x5, #0\n\t"
-        "add	x9, x9, #8\n\t"
-        "cmp	x9, 256\n\t"
-        "b.lt	1b\n\t"
-        "str	x3, [%[r], 256]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x3, %[b], x8\n\t"
-        "umulh	x4, %[b], x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr		x8, [%[a], 8]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 8]\n\t"
-        "# A[2] * B\n\t"
-        "ldr		x8, [%[a], 16]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 16]\n\t"
-        "# A[3] * B\n\t"
-        "ldr		x8, [%[a], 24]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 24]\n\t"
-        "# A[4] * B\n\t"
-        "ldr		x8, [%[a], 32]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "# A[5] * B\n\t"
-        "ldr		x8, [%[a], 40]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 40]\n\t"
-        "# A[6] * B\n\t"
-        "ldr		x8, [%[a], 48]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 48]\n\t"
-        "# A[7] * B\n\t"
-        "ldr		x8, [%[a], 56]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 56]\n\t"
-        "# A[8] * B\n\t"
-        "ldr		x8, [%[a], 64]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 64]\n\t"
-        "# A[9] * B\n\t"
-        "ldr		x8, [%[a], 72]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 72]\n\t"
-        "# A[10] * B\n\t"
-        "ldr		x8, [%[a], 80]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "# A[11] * B\n\t"
-        "ldr		x8, [%[a], 88]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 88]\n\t"
-        "# A[12] * B\n\t"
-        "ldr		x8, [%[a], 96]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 96]\n\t"
-        "# A[13] * B\n\t"
-        "ldr		x8, [%[a], 104]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 104]\n\t"
-        "# A[14] * B\n\t"
-        "ldr		x8, [%[a], 112]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 112]\n\t"
-        "# A[15] * B\n\t"
-        "ldr		x8, [%[a], 120]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 120]\n\t"
-        "# A[16] * B\n\t"
-        "ldr		x8, [%[a], 128]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "# A[17] * B\n\t"
-        "ldr		x8, [%[a], 136]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 136]\n\t"
-        "# A[18] * B\n\t"
-        "ldr		x8, [%[a], 144]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 144]\n\t"
-        "# A[19] * B\n\t"
-        "ldr		x8, [%[a], 152]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 152]\n\t"
-        "# A[20] * B\n\t"
-        "ldr		x8, [%[a], 160]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 160]\n\t"
-        "# A[21] * B\n\t"
-        "ldr		x8, [%[a], 168]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 168]\n\t"
-        "# A[22] * B\n\t"
-        "ldr		x8, [%[a], 176]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "# A[23] * B\n\t"
-        "ldr		x8, [%[a], 184]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 184]\n\t"
-        "# A[24] * B\n\t"
-        "ldr		x8, [%[a], 192]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 192]\n\t"
-        "# A[25] * B\n\t"
-        "ldr		x8, [%[a], 200]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 200]\n\t"
-        "# A[26] * B\n\t"
-        "ldr		x8, [%[a], 208]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 208]\n\t"
-        "# A[27] * B\n\t"
-        "ldr		x8, [%[a], 216]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 216]\n\t"
-        "# A[28] * B\n\t"
-        "ldr		x8, [%[a], 224]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 224]\n\t"
-        "# A[29] * B\n\t"
-        "ldr		x8, [%[a], 232]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 232]\n\t"
-        "# A[30] * B\n\t"
-        "ldr		x8, [%[a], 240]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 240]\n\t"
-        "# A[31] * B\n\t"
-        "ldr	x8, [%[a], 248]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adc	x5, x5, x7\n\t"
-        "str	x4, [%[r], 248]\n\t"
-        "str	x5, [%[r], 256]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "lsr	x5, %[div], 32\n\t"
-        "add	x5, x5, 1\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x6, x3, 32\n\t"
-        "mul	x4, %[div], x6\n\t"
-        "umulh	x3, %[div], x6\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x3, x3, 32\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d0], %[div]\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x3, %[div], x3\n\t"
-        "sub	%[d0], %[d0], x3\n\t"
-        "mov	%[r], x6\n\t"
-
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "x3", "x4", "x5", "x6"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<32; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_2048_cmp_32(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "mov	x6, 248\n\t"
-        "1:\n\t"
-        "ldr	x4, [%[a], x6]\n\t"
-        "ldr	x5, [%[b], x6]\n\t"
-        "and	x4, x4, x3\n\t"
-        "and	x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "sub	x6, x6, #8\n\t"
-        "b.cc	1b\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "ldr		x4, [%[a], 248]\n\t"
-        "ldr		x5, [%[b], 248]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 240]\n\t"
-        "ldr		x5, [%[b], 240]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 232]\n\t"
-        "ldr		x5, [%[b], 232]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 224]\n\t"
-        "ldr		x5, [%[b], 224]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 216]\n\t"
-        "ldr		x5, [%[b], 216]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 208]\n\t"
-        "ldr		x5, [%[b], 208]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 200]\n\t"
-        "ldr		x5, [%[b], 200]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 192]\n\t"
-        "ldr		x5, [%[b], 192]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 184]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 168]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 152]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 136]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 120]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 104]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 88]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 72]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 56]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 40]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 24]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 8]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[64], t2[33];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[31];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
-    for (i=31; i>=0; i--) {
-        r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
-
-        sp_2048_mul_d_32(t2, d, r1);
-        t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
-        t1[32 + i] -= t2[32];
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_32(t1, d) >= 0;
-    sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_32(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_32_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[64], t2[33];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[31];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
-    for (i=31; i>=0; i--) {
-        r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
-
-        sp_2048_mul_d_32(t2, d, r1);
-        t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
-        t1[32 + i] -= t2[32];
-        if (t1[32 + i] != 0) {
-            t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d);
-            if (t1[32 + i] != 0)
-                t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_2048_cmp_32(t1, d) >= 0;
-    sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_32_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][64];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 60;
-        n <<= 4;
-        c = 60;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 60;
-                n <<= 4;
-                c = 60;
-            }
-            else if (c < 4) {
-                y = n >> 60;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 60) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-
-            sp_2048_mont_mul_32(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][64];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_32(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_32(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_32(t[20], t[10], m, mp);
-        sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_32(t[22], t[11], m, mp);
-        sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_32(t[24], t[12], m, mp);
-        sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_32(t[26], t[13], m, mp);
-        sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_32(t[28], t[14], m, mp);
-        sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_32(t[30], t[15], m, mp);
-        sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-
-            sp_2048_mont_mul_32(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x7;
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_mul_32(r, r, t[y], m, mp);
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[64], md[32], rd[64];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 32 * 2;
-        m = r + 32 * 2;
-        ah = a + 32;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 32;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(ah, 32, in, inLen);
-#if DIGIT_BIT >= 64
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 32, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_2048_sqr_32(r, ah);
-                err = sp_2048_mod_32_cond(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_2048_mul_32(r, ah, r);
-                err = sp_2048_mod_32_cond(r, r, m);
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_2048_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=63; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 32);
-                for (i--; i>=0; i--) {
-                    sp_2048_mont_sqr_32(r, r, m, mp);
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_2048_mont_mul_32(r, r, a, m, mp);
-                }
-                XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-                sp_2048_mont_reduce_32(r, m, mp);
-
-                for (i = 31; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_2048_sub_in_place_32(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[32 * 2];
-    sp_digit pd[16], qd[16], dpd[16];
-    sp_digit tmpad[32], tmpbd[32];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 32 * 2;
-        q = p + 16;
-        qi = dq = dp = q + 16;
-        tmpa = qi + 16;
-        tmpb = tmpa + 32;
-
-        tmp = t;
-        r = tmp + 32;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 32;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 32, in, inLen);
-        sp_2048_from_mp(p, 16, pm);
-        sp_2048_from_mp(q, 16, qm);
-        sp_2048_from_mp(dp, 16, dpm);
-
-        err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(dq, 16, dqm);
-        err = sp_2048_mod_exp_16(tmpb, a, dq, 1024, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_2048_sub_in_place_16(tmpa, tmpb);
-        sp_2048_mask_16(tmp, p, c);
-        sp_2048_add_16(tmpa, tmpa, tmp);
-
-        sp_2048_from_mp(qi, 16, qim);
-        sp_2048_mul_16(tmpa, tmpa, qi);
-        err = sp_2048_mod_16(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_16(tmpa, q, tmpa);
-        XMEMSET(&tmpb[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_add_32(r, tmpb, tmpa);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_2048_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
-        r->used = 32;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 32; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 32; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[64], e[32], m[32];
-    sp_digit* r = b;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 32, base);
-        sp_2048_from_mp(e, 32, exp);
-        sp_2048_from_mp(m, 32, mod);
-
-        err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 256 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[64], e[32], m[32];
-    sp_digit* r = b;
-    word32 i;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 32, base);
-        sp_2048_from_bin(e, 32, exp, expLen);
-        sp_2048_from_mp(m, 32, mod);
-
-        err = sp_2048_mod_exp_32(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_2048 */
-
-#ifndef WOLFSSL_SP_NO_3072
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 384
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_3072_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 3072 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<48 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[12];
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x3, x7, x8\n\t"
-        "umulh	x4, x7, x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[0]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 8]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[1]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[0]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 16]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[2]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[1]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[0]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 24]\n\t"
-        "#  A[0] * B[4]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[3]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[2] * B[2]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[1]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[0]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 32]\n\t"
-        "#  A[0] * B[5]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[4]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[3]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[3] * B[2]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[4] * B[1]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[0]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 40]\n\t"
-        "#  A[0] * B[6]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[5]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[4]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[3]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[4] * B[2]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[5] * B[1]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[0]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 48]\n\t"
-        "#  A[0] * B[7]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[6]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[2] * B[5]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[4]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[3]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * B[2]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[6] * B[1]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[0]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 56]\n\t"
-        "#  A[0] * B[8]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[7]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[6]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[3] * B[5]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[4] * B[4]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[3]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * B[2]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[7] * B[1]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[8] * B[0]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 64]\n\t"
-        "#  A[0] * B[9]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[8]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[7]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[6]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[4] * B[5]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[5] * B[4]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[3]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[7] * B[2]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[8] * B[1]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[9] * B[0]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 72]\n\t"
-        "#  A[0] * B[10]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[1] * B[9]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[2] * B[8]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[7]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[6]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * B[5]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[6] * B[4]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[3]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[8] * B[2]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[9] * B[1]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[10] * B[0]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 80]\n\t"
-        "#  A[0] * B[11]\n\t"
-        "ldr	x7, [%[a], 0]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[10]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[9]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[3] * B[8]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[4] * B[7]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[6]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * B[5]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[7] * B[4]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[8] * B[3]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[9] * B[2]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[10] * B[1]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[11] * B[0]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 0]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 88]\n\t"
-        "#  A[1] * B[11]\n\t"
-        "ldr	x7, [%[a], 8]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[2] * B[10]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[9]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[4] * B[8]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[5] * B[7]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[6]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[7] * B[5]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[8] * B[4]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[9] * B[3]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[10] * B[2]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[11] * B[1]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 8]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 96]\n\t"
-        "#  A[2] * B[11]\n\t"
-        "ldr	x7, [%[a], 16]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[3] * B[10]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[4] * B[9]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[5] * B[8]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[6] * B[7]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[6]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[8] * B[5]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[9] * B[4]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[10] * B[3]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[11] * B[2]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 16]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 104]\n\t"
-        "#  A[3] * B[11]\n\t"
-        "ldr	x7, [%[a], 24]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[4] * B[10]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[5] * B[9]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[6] * B[8]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[7] * B[7]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[8] * B[6]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[9] * B[5]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[10] * B[4]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[11] * B[3]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 24]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 112]\n\t"
-        "#  A[4] * B[11]\n\t"
-        "ldr	x7, [%[a], 32]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[5] * B[10]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[6] * B[9]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[7] * B[8]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[8] * B[7]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[9] * B[6]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[10] * B[5]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[11] * B[4]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 32]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 120]\n\t"
-        "#  A[5] * B[11]\n\t"
-        "ldr	x7, [%[a], 40]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[6] * B[10]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[7] * B[9]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[8] * B[8]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[9] * B[7]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[10] * B[6]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[11] * B[5]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 40]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 128]\n\t"
-        "#  A[6] * B[11]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[7] * B[10]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[8] * B[9]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[9] * B[8]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[10] * B[7]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[11] * B[6]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 48]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 136]\n\t"
-        "#  A[7] * B[11]\n\t"
-        "ldr	x7, [%[a], 56]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[8] * B[10]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[9] * B[9]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[10] * B[8]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[11] * B[7]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 56]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 144]\n\t"
-        "#  A[8] * B[11]\n\t"
-        "ldr	x7, [%[a], 64]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[9] * B[10]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[10] * B[9]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[11] * B[8]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 64]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 152]\n\t"
-        "#  A[9] * B[11]\n\t"
-        "ldr	x7, [%[a], 72]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[10] * B[10]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[11] * B[9]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 72]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 160]\n\t"
-        "#  A[10] * B[11]\n\t"
-        "ldr	x7, [%[a], 80]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[11] * B[10]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 80]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[r], 168]\n\t"
-        "#  A[11] * B[11]\n\t"
-        "ldr	x7, [%[a], 88]\n\t"
-        "ldr	x8, [%[b], 88]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adc	x5, x5, x7\n\t"
-        "stp	x4, x5, [%[r], 176]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[12];
-
-    __asm__ __volatile__ (
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "ldp	x12, x13, [%[a], 16]\n\t"
-        "ldp	x14, x15, [%[a], 32]\n\t"
-        "ldp	x16, x17, [%[a], 48]\n\t"
-        "ldp	x18, x19, [%[a], 64]\n\t"
-        "ldp	x20, x21, [%[a], 80]\n\t"
-        "#  A[0] * A[0]\n\t"
-        "mul	x2, x10, x10\n\t"
-        "umulh	x3, x10, x10\n\t"
-        "str	x2, [%[tmp]]\n\t"
-        "mov	x4, 0\n\t"
-        "#  A[0] * A[1]\n\t"
-        "mul	x8, x10, x11\n\t"
-        "umulh	x9, x10, x11\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[tmp], 8]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "mul	x8, x10, x12\n\t"
-        "umulh	x9, x10, x12\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[1] * A[1]\n\t"
-        "mul	x8, x11, x11\n\t"
-        "umulh	x9, x11, x11\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 16]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "mul	x8, x10, x13\n\t"
-        "umulh	x9, x10, x13\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[1] * A[2]\n\t"
-        "mul	x8, x11, x12\n\t"
-        "umulh	x9, x11, x12\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[tmp], 24]\n\t"
-        "#  A[0] * A[4]\n\t"
-        "mul	x8, x10, x14\n\t"
-        "umulh	x9, x10, x14\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[1] * A[3]\n\t"
-        "mul	x8, x11, x13\n\t"
-        "umulh	x9, x11, x13\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[2] * A[2]\n\t"
-        "mul	x8, x12, x12\n\t"
-        "umulh	x9, x12, x12\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[tmp], 32]\n\t"
-        "#  A[0] * A[5]\n\t"
-        "mul	x5, x10, x15\n\t"
-        "umulh	x6, x10, x15\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[4]\n\t"
-        "mul	x8, x11, x14\n\t"
-        "umulh	x9, x11, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[3]\n\t"
-        "mul	x8, x12, x13\n\t"
-        "umulh	x9, x12, x13\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[tmp], 40]\n\t"
-        "#  A[0] * A[6]\n\t"
-        "mul	x5, x10, x16\n\t"
-        "umulh	x6, x10, x16\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[5]\n\t"
-        "mul	x8, x11, x15\n\t"
-        "umulh	x9, x11, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[4]\n\t"
-        "mul	x8, x12, x14\n\t"
-        "umulh	x9, x12, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[3]\n\t"
-        "mul	x8, x13, x13\n\t"
-        "umulh	x9, x13, x13\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[tmp], 48]\n\t"
-        "#  A[0] * A[7]\n\t"
-        "mul	x5, x10, x17\n\t"
-        "umulh	x6, x10, x17\n\t"
-        "mov	x2, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[6]\n\t"
-        "mul	x8, x11, x16\n\t"
-        "umulh	x9, x11, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[5]\n\t"
-        "mul	x8, x12, x15\n\t"
-        "umulh	x9, x12, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[4]\n\t"
-        "mul	x8, x13, x14\n\t"
-        "umulh	x9, x13, x14\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x3, x3, x5\n\t"
-        "adcs	x4, x4, x6\n\t"
-        "adc	x2, x2, x7\n\t"
-        "str	x3, [%[tmp], 56]\n\t"
-        "#  A[0] * A[8]\n\t"
-        "mul	x5, x10, x18\n\t"
-        "umulh	x6, x10, x18\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[7]\n\t"
-        "mul	x8, x11, x17\n\t"
-        "umulh	x9, x11, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[6]\n\t"
-        "mul	x8, x12, x16\n\t"
-        "umulh	x9, x12, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[5]\n\t"
-        "mul	x8, x13, x15\n\t"
-        "umulh	x9, x13, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[4]\n\t"
-        "mul	x8, x14, x14\n\t"
-        "umulh	x9, x14, x14\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[tmp], 64]\n\t"
-        "#  A[0] * A[9]\n\t"
-        "mul	x5, x10, x19\n\t"
-        "umulh	x6, x10, x19\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[8]\n\t"
-        "mul	x8, x11, x18\n\t"
-        "umulh	x9, x11, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[7]\n\t"
-        "mul	x8, x12, x17\n\t"
-        "umulh	x9, x12, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[6]\n\t"
-        "mul	x8, x13, x16\n\t"
-        "umulh	x9, x13, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[5]\n\t"
-        "mul	x8, x14, x15\n\t"
-        "umulh	x9, x14, x15\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[tmp], 72]\n\t"
-        "#  A[0] * A[10]\n\t"
-        "mul	x5, x10, x20\n\t"
-        "umulh	x6, x10, x20\n\t"
-        "mov	x2, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[9]\n\t"
-        "mul	x8, x11, x19\n\t"
-        "umulh	x9, x11, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[8]\n\t"
-        "mul	x8, x12, x18\n\t"
-        "umulh	x9, x12, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[7]\n\t"
-        "mul	x8, x13, x17\n\t"
-        "umulh	x9, x13, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[6]\n\t"
-        "mul	x8, x14, x16\n\t"
-        "umulh	x9, x14, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[5] * A[5]\n\t"
-        "mul	x8, x15, x15\n\t"
-        "umulh	x9, x15, x15\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x3, x3, x5\n\t"
-        "adcs	x4, x4, x6\n\t"
-        "adc	x2, x2, x7\n\t"
-        "str	x3, [%[tmp], 80]\n\t"
-        "#  A[0] * A[11]\n\t"
-        "mul	x5, x10, x21\n\t"
-        "umulh	x6, x10, x21\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[1] * A[10]\n\t"
-        "mul	x8, x11, x20\n\t"
-        "umulh	x9, x11, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[2] * A[9]\n\t"
-        "mul	x8, x12, x19\n\t"
-        "umulh	x9, x12, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[8]\n\t"
-        "mul	x8, x13, x18\n\t"
-        "umulh	x9, x13, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[7]\n\t"
-        "mul	x8, x14, x17\n\t"
-        "umulh	x9, x14, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[5] * A[6]\n\t"
-        "mul	x8, x15, x16\n\t"
-        "umulh	x9, x15, x16\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[tmp], 88]\n\t"
-        "#  A[1] * A[11]\n\t"
-        "mul	x5, x11, x21\n\t"
-        "umulh	x6, x11, x21\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[2] * A[10]\n\t"
-        "mul	x8, x12, x20\n\t"
-        "umulh	x9, x12, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[3] * A[9]\n\t"
-        "mul	x8, x13, x19\n\t"
-        "umulh	x9, x13, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[8]\n\t"
-        "mul	x8, x14, x18\n\t"
-        "umulh	x9, x14, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[5] * A[7]\n\t"
-        "mul	x8, x15, x17\n\t"
-        "umulh	x9, x15, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[6] * A[6]\n\t"
-        "mul	x8, x16, x16\n\t"
-        "umulh	x9, x16, x16\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[r], 96]\n\t"
-        "#  A[2] * A[11]\n\t"
-        "mul	x5, x12, x21\n\t"
-        "umulh	x6, x12, x21\n\t"
-        "mov	x2, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[3] * A[10]\n\t"
-        "mul	x8, x13, x20\n\t"
-        "umulh	x9, x13, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[4] * A[9]\n\t"
-        "mul	x8, x14, x19\n\t"
-        "umulh	x9, x14, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[5] * A[8]\n\t"
-        "mul	x8, x15, x18\n\t"
-        "umulh	x9, x15, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[6] * A[7]\n\t"
-        "mul	x8, x16, x17\n\t"
-        "umulh	x9, x16, x17\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x3, x3, x5\n\t"
-        "adcs	x4, x4, x6\n\t"
-        "adc	x2, x2, x7\n\t"
-        "str	x3, [%[r], 104]\n\t"
-        "#  A[3] * A[11]\n\t"
-        "mul	x5, x13, x21\n\t"
-        "umulh	x6, x13, x21\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[4] * A[10]\n\t"
-        "mul	x8, x14, x20\n\t"
-        "umulh	x9, x14, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[5] * A[9]\n\t"
-        "mul	x8, x15, x19\n\t"
-        "umulh	x9, x15, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[6] * A[8]\n\t"
-        "mul	x8, x16, x18\n\t"
-        "umulh	x9, x16, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[7] * A[7]\n\t"
-        "mul	x8, x17, x17\n\t"
-        "umulh	x9, x17, x17\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[r], 112]\n\t"
-        "#  A[4] * A[11]\n\t"
-        "mul	x5, x14, x21\n\t"
-        "umulh	x6, x14, x21\n\t"
-        "mov	x4, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[5] * A[10]\n\t"
-        "mul	x8, x15, x20\n\t"
-        "umulh	x9, x15, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[6] * A[9]\n\t"
-        "mul	x8, x16, x19\n\t"
-        "umulh	x9, x16, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[7] * A[8]\n\t"
-        "mul	x8, x17, x18\n\t"
-        "umulh	x9, x17, x18\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x2, x2, x5\n\t"
-        "adcs	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x2, [%[r], 120]\n\t"
-        "#  A[5] * A[11]\n\t"
-        "mul	x5, x15, x21\n\t"
-        "umulh	x6, x15, x21\n\t"
-        "mov	x2, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[6] * A[10]\n\t"
-        "mul	x8, x16, x20\n\t"
-        "umulh	x9, x16, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[7] * A[9]\n\t"
-        "mul	x8, x17, x19\n\t"
-        "umulh	x9, x17, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[8] * A[8]\n\t"
-        "mul	x8, x18, x18\n\t"
-        "umulh	x9, x18, x18\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x3, x3, x5\n\t"
-        "adcs	x4, x4, x6\n\t"
-        "adc	x2, x2, x7\n\t"
-        "str	x3, [%[r], 128]\n\t"
-        "#  A[6] * A[11]\n\t"
-        "mul	x5, x16, x21\n\t"
-        "umulh	x6, x16, x21\n\t"
-        "mov	x3, 0\n\t"
-        "mov	x7, 0\n\t"
-        "#  A[7] * A[10]\n\t"
-        "mul	x8, x17, x20\n\t"
-        "umulh	x9, x17, x20\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "#  A[8] * A[9]\n\t"
-        "mul	x8, x18, x19\n\t"
-        "umulh	x9, x18, x19\n\t"
-        "adds	x5, x5, x8\n\t"
-        "adcs	x6, x6, x9\n\t"
-        "adc	x7, x7, xzr\n\t"
-        "adds	x5, x5, x5\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "adc	x7, x7, x7\n\t"
-        "adds	x4, x4, x5\n\t"
-        "adcs	x2, x2, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x4, [%[r], 136]\n\t"
-        "#  A[7] * A[11]\n\t"
-        "mul	x8, x17, x21\n\t"
-        "umulh	x9, x17, x21\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[8] * A[10]\n\t"
-        "mul	x8, x18, x20\n\t"
-        "umulh	x9, x18, x20\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[9] * A[9]\n\t"
-        "mul	x8, x19, x19\n\t"
-        "umulh	x9, x19, x19\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[r], 144]\n\t"
-        "#  A[8] * A[11]\n\t"
-        "mul	x8, x18, x21\n\t"
-        "umulh	x9, x18, x21\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[9] * A[10]\n\t"
-        "mul	x8, x19, x20\n\t"
-        "umulh	x9, x19, x20\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[r], 152]\n\t"
-        "#  A[9] * A[11]\n\t"
-        "mul	x8, x19, x21\n\t"
-        "umulh	x9, x19, x21\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[10] * A[10]\n\t"
-        "mul	x8, x20, x20\n\t"
-        "umulh	x9, x20, x20\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 160]\n\t"
-        "#  A[10] * A[11]\n\t"
-        "mul	x8, x20, x21\n\t"
-        "umulh	x9, x20, x21\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[r], 168]\n\t"
-        "#  A[11] * A[11]\n\t"
-        "mul	x8, x21, x21\n\t"
-        "umulh	x9, x21, x21\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adc	x4, x4, x9\n\t"
-        "stp	x3, x4, [%[r], 176]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "ldp	x3, x4, [%[a], 64]\n\t"
-        "ldp	x5, x6, [%[a], 80]\n\t"
-        "ldp	x7, x8, [%[b], 64]\n\t"
-        "ldp	x9, x10, [%[b], 80]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 64]\n\t"
-        "stp	x5, x6, [%[r], 80]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x2, x3, [%[a], 0]\n\t"
-        "ldp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x6, x7, [%[b], 0]\n\t"
-        "ldp	x8, x9, [%[b], 16]\n\t"
-        "subs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 0]\n\t"
-        "stp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x2, x3, [%[a], 32]\n\t"
-        "ldp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x6, x7, [%[b], 32]\n\t"
-        "ldp	x8, x9, [%[b], 48]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 32]\n\t"
-        "stp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x2, x3, [%[a], 64]\n\t"
-        "ldp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x6, x7, [%[b], 64]\n\t"
-        "ldp	x8, x9, [%[b], 80]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 64]\n\t"
-        "stp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x2, x3, [%[a], 96]\n\t"
-        "ldp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x6, x7, [%[b], 96]\n\t"
-        "ldp	x8, x9, [%[b], 112]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 96]\n\t"
-        "stp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x2, x3, [%[a], 128]\n\t"
-        "ldp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x6, x7, [%[b], 128]\n\t"
-        "ldp	x8, x9, [%[b], 144]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 128]\n\t"
-        "stp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x2, x3, [%[a], 160]\n\t"
-        "ldp	x4, x5, [%[a], 176]\n\t"
-        "ldp	x6, x7, [%[b], 160]\n\t"
-        "ldp	x8, x9, [%[b], 176]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 160]\n\t"
-        "stp	x4, x5, [%[a], 176]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "ldp	x3, x4, [%[a], 64]\n\t"
-        "ldp	x5, x6, [%[a], 80]\n\t"
-        "ldp	x7, x8, [%[b], 64]\n\t"
-        "ldp	x9, x10, [%[b], 80]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 64]\n\t"
-        "stp	x5, x6, [%[r], 80]\n\t"
-        "ldp	x3, x4, [%[a], 96]\n\t"
-        "ldp	x5, x6, [%[a], 112]\n\t"
-        "ldp	x7, x8, [%[b], 96]\n\t"
-        "ldp	x9, x10, [%[b], 112]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 96]\n\t"
-        "stp	x5, x6, [%[r], 112]\n\t"
-        "ldp	x3, x4, [%[a], 128]\n\t"
-        "ldp	x5, x6, [%[a], 144]\n\t"
-        "ldp	x7, x8, [%[b], 128]\n\t"
-        "ldp	x9, x10, [%[b], 144]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 128]\n\t"
-        "stp	x5, x6, [%[r], 144]\n\t"
-        "ldp	x3, x4, [%[a], 160]\n\t"
-        "ldp	x5, x6, [%[a], 176]\n\t"
-        "ldp	x7, x8, [%[b], 160]\n\t"
-        "ldp	x9, x10, [%[b], 176]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 160]\n\t"
-        "stp	x5, x6, [%[r], 176]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_12(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<12; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-    r[4] = a[4] & m;
-    r[5] = a[5] & m;
-    r[6] = a[6] & m;
-    r[7] = a[7] & m;
-    r[8] = a[8] & m;
-    r[9] = a[9] & m;
-    r[10] = a[10] & m;
-    r[11] = a[11] & m;
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[24];
-    sp_digit a1[12];
-    sp_digit b1[12];
-    sp_digit z2[24];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_12(a1, a, &a[12]);
-    cb = sp_3072_add_12(b1, b, &b[12]);
-    u  = ca & cb;
-    sp_3072_mul_12(z1, a1, b1);
-    sp_3072_mul_12(z2, &a[12], &b[12]);
-    sp_3072_mul_12(z0, a, b);
-    sp_3072_mask_12(r + 24, a1, 0 - cb);
-    sp_3072_mask_12(b1, b1, 0 - ca);
-    u += sp_3072_add_12(r + 24, r + 24, b1);
-    u += sp_3072_sub_in_place_24(z1, z2);
-    u += sp_3072_sub_in_place_24(z1, z0);
-    u += sp_3072_add_24(r + 12, r + 12, z1);
-    r[36] = u;
-    XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1));
-    sp_3072_add_24(r + 24, r + 24, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[24];
-    sp_digit z1[24];
-    sp_digit a1[12];
-    sp_digit u;
-
-    u = sp_3072_add_12(a1, a, &a[12]);
-    sp_3072_sqr_12(z1, a1);
-    sp_3072_sqr_12(z2, &a[12]);
-    sp_3072_sqr_12(z0, a);
-    sp_3072_mask_12(r + 24, a1, 0 - u);
-    u += sp_3072_add_12(r + 24, r + 24, r + 24);
-    u += sp_3072_sub_in_place_24(z1, z2);
-    u += sp_3072_sub_in_place_24(z1, z0);
-    u += sp_3072_add_24(r + 12, r + 12, z1);
-    r[36] = u;
-    XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1));
-    sp_3072_add_24(r + 24, r + 24, z2);
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x2, x3, [%[a], 0]\n\t"
-        "ldp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x6, x7, [%[b], 0]\n\t"
-        "ldp	x8, x9, [%[b], 16]\n\t"
-        "subs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 0]\n\t"
-        "stp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x2, x3, [%[a], 32]\n\t"
-        "ldp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x6, x7, [%[b], 32]\n\t"
-        "ldp	x8, x9, [%[b], 48]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 32]\n\t"
-        "stp	x4, x5, [%[a], 48]\n\t"
-        "ldp	x2, x3, [%[a], 64]\n\t"
-        "ldp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x6, x7, [%[b], 64]\n\t"
-        "ldp	x8, x9, [%[b], 80]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 64]\n\t"
-        "stp	x4, x5, [%[a], 80]\n\t"
-        "ldp	x2, x3, [%[a], 96]\n\t"
-        "ldp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x6, x7, [%[b], 96]\n\t"
-        "ldp	x8, x9, [%[b], 112]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 96]\n\t"
-        "stp	x4, x5, [%[a], 112]\n\t"
-        "ldp	x2, x3, [%[a], 128]\n\t"
-        "ldp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x6, x7, [%[b], 128]\n\t"
-        "ldp	x8, x9, [%[b], 144]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 128]\n\t"
-        "stp	x4, x5, [%[a], 144]\n\t"
-        "ldp	x2, x3, [%[a], 160]\n\t"
-        "ldp	x4, x5, [%[a], 176]\n\t"
-        "ldp	x6, x7, [%[b], 160]\n\t"
-        "ldp	x8, x9, [%[b], 176]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 160]\n\t"
-        "stp	x4, x5, [%[a], 176]\n\t"
-        "ldp	x2, x3, [%[a], 192]\n\t"
-        "ldp	x4, x5, [%[a], 208]\n\t"
-        "ldp	x6, x7, [%[b], 192]\n\t"
-        "ldp	x8, x9, [%[b], 208]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 192]\n\t"
-        "stp	x4, x5, [%[a], 208]\n\t"
-        "ldp	x2, x3, [%[a], 224]\n\t"
-        "ldp	x4, x5, [%[a], 240]\n\t"
-        "ldp	x6, x7, [%[b], 224]\n\t"
-        "ldp	x8, x9, [%[b], 240]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 224]\n\t"
-        "stp	x4, x5, [%[a], 240]\n\t"
-        "ldp	x2, x3, [%[a], 256]\n\t"
-        "ldp	x4, x5, [%[a], 272]\n\t"
-        "ldp	x6, x7, [%[b], 256]\n\t"
-        "ldp	x8, x9, [%[b], 272]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 256]\n\t"
-        "stp	x4, x5, [%[a], 272]\n\t"
-        "ldp	x2, x3, [%[a], 288]\n\t"
-        "ldp	x4, x5, [%[a], 304]\n\t"
-        "ldp	x6, x7, [%[b], 288]\n\t"
-        "ldp	x8, x9, [%[b], 304]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 288]\n\t"
-        "stp	x4, x5, [%[a], 304]\n\t"
-        "ldp	x2, x3, [%[a], 320]\n\t"
-        "ldp	x4, x5, [%[a], 336]\n\t"
-        "ldp	x6, x7, [%[b], 320]\n\t"
-        "ldp	x8, x9, [%[b], 336]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 320]\n\t"
-        "stp	x4, x5, [%[a], 336]\n\t"
-        "ldp	x2, x3, [%[a], 352]\n\t"
-        "ldp	x4, x5, [%[a], 368]\n\t"
-        "ldp	x6, x7, [%[b], 352]\n\t"
-        "ldp	x8, x9, [%[b], 368]\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 352]\n\t"
-        "stp	x4, x5, [%[a], 368]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x3, x4, [%[a], 32]\n\t"
-        "ldp	x5, x6, [%[a], 48]\n\t"
-        "ldp	x7, x8, [%[b], 32]\n\t"
-        "ldp	x9, x10, [%[b], 48]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 32]\n\t"
-        "stp	x5, x6, [%[r], 48]\n\t"
-        "ldp	x3, x4, [%[a], 64]\n\t"
-        "ldp	x5, x6, [%[a], 80]\n\t"
-        "ldp	x7, x8, [%[b], 64]\n\t"
-        "ldp	x9, x10, [%[b], 80]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 64]\n\t"
-        "stp	x5, x6, [%[r], 80]\n\t"
-        "ldp	x3, x4, [%[a], 96]\n\t"
-        "ldp	x5, x6, [%[a], 112]\n\t"
-        "ldp	x7, x8, [%[b], 96]\n\t"
-        "ldp	x9, x10, [%[b], 112]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 96]\n\t"
-        "stp	x5, x6, [%[r], 112]\n\t"
-        "ldp	x3, x4, [%[a], 128]\n\t"
-        "ldp	x5, x6, [%[a], 144]\n\t"
-        "ldp	x7, x8, [%[b], 128]\n\t"
-        "ldp	x9, x10, [%[b], 144]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 128]\n\t"
-        "stp	x5, x6, [%[r], 144]\n\t"
-        "ldp	x3, x4, [%[a], 160]\n\t"
-        "ldp	x5, x6, [%[a], 176]\n\t"
-        "ldp	x7, x8, [%[b], 160]\n\t"
-        "ldp	x9, x10, [%[b], 176]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 160]\n\t"
-        "stp	x5, x6, [%[r], 176]\n\t"
-        "ldp	x3, x4, [%[a], 192]\n\t"
-        "ldp	x5, x6, [%[a], 208]\n\t"
-        "ldp	x7, x8, [%[b], 192]\n\t"
-        "ldp	x9, x10, [%[b], 208]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 192]\n\t"
-        "stp	x5, x6, [%[r], 208]\n\t"
-        "ldp	x3, x4, [%[a], 224]\n\t"
-        "ldp	x5, x6, [%[a], 240]\n\t"
-        "ldp	x7, x8, [%[b], 224]\n\t"
-        "ldp	x9, x10, [%[b], 240]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 224]\n\t"
-        "stp	x5, x6, [%[r], 240]\n\t"
-        "ldp	x3, x4, [%[a], 256]\n\t"
-        "ldp	x5, x6, [%[a], 272]\n\t"
-        "ldp	x7, x8, [%[b], 256]\n\t"
-        "ldp	x9, x10, [%[b], 272]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 256]\n\t"
-        "stp	x5, x6, [%[r], 272]\n\t"
-        "ldp	x3, x4, [%[a], 288]\n\t"
-        "ldp	x5, x6, [%[a], 304]\n\t"
-        "ldp	x7, x8, [%[b], 288]\n\t"
-        "ldp	x9, x10, [%[b], 304]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 288]\n\t"
-        "stp	x5, x6, [%[r], 304]\n\t"
-        "ldp	x3, x4, [%[a], 320]\n\t"
-        "ldp	x5, x6, [%[a], 336]\n\t"
-        "ldp	x7, x8, [%[b], 320]\n\t"
-        "ldp	x9, x10, [%[b], 336]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 320]\n\t"
-        "stp	x5, x6, [%[r], 336]\n\t"
-        "ldp	x3, x4, [%[a], 352]\n\t"
-        "ldp	x5, x6, [%[a], 368]\n\t"
-        "ldp	x7, x8, [%[b], 352]\n\t"
-        "ldp	x9, x10, [%[b], 368]\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 352]\n\t"
-        "stp	x5, x6, [%[r], 368]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<24; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit b1[24];
-    sp_digit z2[48];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_24(a1, a, &a[24]);
-    cb = sp_3072_add_24(b1, b, &b[24]);
-    u  = ca & cb;
-    sp_3072_mul_24(z1, a1, b1);
-    sp_3072_mul_24(z2, &a[24], &b[24]);
-    sp_3072_mul_24(z0, a, b);
-    sp_3072_mask_24(r + 48, a1, 0 - cb);
-    sp_3072_mask_24(b1, b1, 0 - ca);
-    u += sp_3072_add_24(r + 48, r + 48, b1);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[48];
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit u;
-
-    u = sp_3072_add_24(a1, a, &a[24]);
-    sp_3072_sqr_24(z1, a1);
-    sp_3072_sqr_24(z2, &a[24]);
-    sp_3072_sqr_24(z0, a);
-    sp_3072_mask_24(r + 48, a1, 0 - u);
-    u += sp_3072_add_24(r + 48, r + 48, r + 48);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x11, %[a], 384\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldp	x3, x4, [%[a]], #16\n\t"
-        "ldp	x5, x6, [%[a]], #16\n\t"
-        "ldp	x7, x8, [%[b]], #16\n\t"
-        "ldp	x9, x10, [%[b]], #16\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r]], #16\n\t"
-        "stp	x5, x6, [%[r]], #16\n\t"
-        "cset	%[c], cs\n\t"
-        "cmp	%[a], x11\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x10, %[a], 384\n\t"
-        "\n1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldp	x2, x3, [%[a]]\n\t"
-        "ldp	x4, x5, [%[a], #16]\n\t"
-        "ldp	x6, x7, [%[b]], #16\n\t"
-        "ldp	x8, x9, [%[b]], #16\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a]], #16\n\t"
-        "stp	x4, x5, [%[a]], #16\n\t"
-        "csetm	%[c], cc\n\t"
-        "cmp	%[a], x10\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[96];
-
-    __asm__ __volatile__ (
-        "mov	x5, 0\n\t"
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 376\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[b], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 384\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 752\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[96];
-
-    __asm__ __volatile__ (
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "mov	x5, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 376\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "cmp	x4, x3\n\t"
-        "b.eq	4f\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[a], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "b.al	5f\n\t"
-        "\n4:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "mul	x9, x10, x10\n\t"
-        "umulh	x10, x10, x10\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "\n5:\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 384\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x4\n\t"
-        "b.gt	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 752\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m)
-{
-    int i;
-
-    for (i=0; i<24; i++)
-        r[i] = a[i] & m;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x11, %[a], 192\n\t"
-        "\n1:\n\t"
-        "adds	%[c], %[c], #-1\n\t"
-        "ldp	x3, x4, [%[a]], #16\n\t"
-        "ldp	x5, x6, [%[a]], #16\n\t"
-        "ldp	x7, x8, [%[b]], #16\n\t"
-        "ldp	x9, x10, [%[b]], #16\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r]], #16\n\t"
-        "stp	x5, x6, [%[r]], #16\n\t"
-        "cset	%[c], cs\n\t"
-        "cmp	%[a], x11\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "add	x10, %[a], 192\n\t"
-        "\n1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldp	x2, x3, [%[a]]\n\t"
-        "ldp	x4, x5, [%[a], #16]\n\t"
-        "ldp	x6, x7, [%[b]], #16\n\t"
-        "ldp	x8, x9, [%[b]], #16\n\t"
-        "sbcs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a]], #16\n\t"
-        "stp	x4, x5, [%[a]], #16\n\t"
-        "csetm	%[c], cc\n\t"
-        "cmp	%[a], x10\n\t"
-        "b.ne	1b\n\t"
-        : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b)
-        :
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[48];
-
-    __asm__ __volatile__ (
-        "mov	x5, 0\n\t"
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 184\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[b], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 192\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 368\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[48];
-
-    __asm__ __volatile__ (
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "mov	x5, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 184\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "cmp	x4, x3\n\t"
-        "b.eq	4f\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[a], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "b.al	5f\n\t"
-        "\n4:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "mul	x9, x10, x10\n\t"
-        "umulh	x10, x10, x10\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "\n5:\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 192\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x4\n\t"
-        "b.gt	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 368\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_24(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 24);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_24(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_24(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldr	x4, [%[a], x8]\n\t"
-        "ldr	x5, [%[b], x8]\n\t"
-        "and	x5, x5, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "csetm	%[c], cc\n\t"
-        "str	x4, [%[r], x8]\n\t"
-        "add	x8, x8, #8\n\t"
-        "cmp	x8, 192\n\t"
-        "b.lt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x6, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "ldr		x7, [%[b], 8]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "subs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 0]\n\t"
-        "str		x6, [%[r], 8]\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x6, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "ldr		x7, [%[b], 24]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 16]\n\t"
-        "str		x6, [%[r], 24]\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x6, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "ldr		x7, [%[b], 40]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "str		x6, [%[r], 40]\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x6, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "ldr		x7, [%[b], 56]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 48]\n\t"
-        "str		x6, [%[r], 56]\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x6, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "ldr		x7, [%[b], 72]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 64]\n\t"
-        "str		x6, [%[r], 72]\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x6, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "ldr		x7, [%[b], 88]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "str		x6, [%[r], 88]\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x6, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "ldr		x7, [%[b], 104]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 96]\n\t"
-        "str		x6, [%[r], 104]\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x6, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "ldr		x7, [%[b], 120]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 112]\n\t"
-        "str		x6, [%[r], 120]\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x6, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "ldr		x7, [%[b], 136]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "str		x6, [%[r], 136]\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x6, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "ldr		x7, [%[b], 152]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 144]\n\t"
-        "str		x6, [%[r], 152]\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x6, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "ldr		x7, [%[b], 168]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 160]\n\t"
-        "str		x6, [%[r], 168]\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x6, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "ldr		x7, [%[b], 184]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "str		x6, [%[r], 184]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "ldp       x12, x13, [%[m], 0]\n\t"
-        "ldp       x14, x15, [%[m], 16]\n\t"
-        "ldp       x16, x17, [%[m], 32]\n\t"
-        "ldp       x18, x19, [%[m], 48]\n\t"
-        "ldp       x20, x21, [%[m], 64]\n\t"
-        "ldp       x22, x23, [%[m], 80]\n\t"
-        "ldp       x24, x25, [%[m], 96]\n\t"
-        "ldp       x26, x27, [%[m], 112]\n\t"
-        "# i = 0\n\t"
-        "mov	x3, 0\n\t"
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	x8, %[mp], x10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	x9, [%[a], 0]\n\t"
-        "mul		x6, x12, x8\n\t"
-        "umulh	x7, x12, x8\n\t"
-        "adds	x10, x10, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	x9, [%[a], 8]\n\t"
-        "mul		x6, x13, x8\n\t"
-        "umulh	x7, x13, x8\n\t"
-        "adds	x10, x11, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x10, x10, x5\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	x11, [%[a], 16]\n\t"
-        "mul		x6, x14, x8\n\t"
-        "umulh	x7, x14, x8\n\t"
-        "adds	x11, x11, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x11, x11, x4\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	x9, [%[a], 24]\n\t"
-        "mul		x6, x15, x8\n\t"
-        "umulh	x7, x15, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 24]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	x9, [%[a], 32]\n\t"
-        "mul		x6, x16, x8\n\t"
-        "umulh	x7, x16, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 32]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	x9, [%[a], 40]\n\t"
-        "mul		x6, x17, x8\n\t"
-        "umulh	x7, x17, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 40]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	x9, [%[a], 48]\n\t"
-        "mul		x6, x18, x8\n\t"
-        "umulh	x7, x18, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 48]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	x9, [%[a], 56]\n\t"
-        "mul		x6, x19, x8\n\t"
-        "umulh	x7, x19, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 56]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	x9, [%[a], 64]\n\t"
-        "mul		x6, x20, x8\n\t"
-        "umulh	x7, x20, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 64]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	x9, [%[a], 72]\n\t"
-        "mul		x6, x21, x8\n\t"
-        "umulh	x7, x21, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 72]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	x9, [%[a], 80]\n\t"
-        "mul		x6, x22, x8\n\t"
-        "umulh	x7, x22, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 80]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	x9, [%[a], 88]\n\t"
-        "mul		x6, x23, x8\n\t"
-        "umulh	x7, x23, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 88]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	x9, [%[a], 96]\n\t"
-        "mul		x6, x24, x8\n\t"
-        "umulh	x7, x24, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 96]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	x9, [%[a], 104]\n\t"
-        "mul		x6, x25, x8\n\t"
-        "umulh	x7, x25, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 104]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	x9, [%[a], 112]\n\t"
-        "mul		x6, x26, x8\n\t"
-        "umulh	x7, x26, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 112]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	x9, [%[a], 120]\n\t"
-        "mul		x6, x27, x8\n\t"
-        "umulh	x7, x27, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 120]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr		x7, [%[m], 128]\n\t"
-        "ldr	x9, [%[a], 128]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 128]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr		x7, [%[m], 136]\n\t"
-        "ldr	x9, [%[a], 136]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 136]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr		x7, [%[m], 144]\n\t"
-        "ldr	x9, [%[a], 144]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 144]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr		x7, [%[m], 152]\n\t"
-        "ldr	x9, [%[a], 152]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 152]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr		x7, [%[m], 160]\n\t"
-        "ldr	x9, [%[a], 160]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 160]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr		x7, [%[m], 168]\n\t"
-        "ldr	x9, [%[a], 168]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 168]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr		x7, [%[m], 176]\n\t"
-        "ldr	x9, [%[a], 176]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 176]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr	x7, [%[m], 184]\n\t"
-        "ldr	x9, [%[a], 184]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x7, x7, %[ca]\n\t"
-        "cset  %[ca], cs\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 184]\n\t"
-        "ldr	x9, [%[a], 192]\n\t"
-        "adcs	x9, x9, x7\n\t"
-        "str	x9, [%[a], 192]\n\t"
-        "adc	%[ca], %[ca], xzr\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], 8\n\t"
-        "add	x3, x3, 8\n\t"
-        "cmp	x3, 192\n\t"
-        "blt	1b\n\t"
-        "str	x10, [%[a], 0]\n\t"
-        "str	x11, [%[a], 8]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27"
-    );
-
-    sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_24(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_24(r, a, b);
-    sp_3072_mont_reduce_24(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_24(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_24(r, a);
-    sp_3072_mont_reduce_24(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x5, %[b], x8\n\t"
-        "umulh	x3, %[b], x8\n\t"
-        "mov	x4, 0\n\t"
-        "str	x5, [%[r]]\n\t"
-        "mov	x5, 0\n\t"
-        "mov	x9, #8\n\t"
-        "1:\n\t"
-        "ldr	x8, [%[a], x9]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "str	x3, [%[r], x9]\n\t"
-        "mov	x3, x4\n\t"
-        "mov	x4, x5\n\t"
-        "mov	x5, #0\n\t"
-        "add	x9, x9, #8\n\t"
-        "cmp	x9, 192\n\t"
-        "b.lt	1b\n\t"
-        "str	x3, [%[r], 192]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x3, %[b], x8\n\t"
-        "umulh	x4, %[b], x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr		x8, [%[a], 8]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 8]\n\t"
-        "# A[2] * B\n\t"
-        "ldr		x8, [%[a], 16]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 16]\n\t"
-        "# A[3] * B\n\t"
-        "ldr		x8, [%[a], 24]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 24]\n\t"
-        "# A[4] * B\n\t"
-        "ldr		x8, [%[a], 32]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "# A[5] * B\n\t"
-        "ldr		x8, [%[a], 40]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 40]\n\t"
-        "# A[6] * B\n\t"
-        "ldr		x8, [%[a], 48]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 48]\n\t"
-        "# A[7] * B\n\t"
-        "ldr		x8, [%[a], 56]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 56]\n\t"
-        "# A[8] * B\n\t"
-        "ldr		x8, [%[a], 64]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 64]\n\t"
-        "# A[9] * B\n\t"
-        "ldr		x8, [%[a], 72]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 72]\n\t"
-        "# A[10] * B\n\t"
-        "ldr		x8, [%[a], 80]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "# A[11] * B\n\t"
-        "ldr		x8, [%[a], 88]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 88]\n\t"
-        "# A[12] * B\n\t"
-        "ldr		x8, [%[a], 96]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 96]\n\t"
-        "# A[13] * B\n\t"
-        "ldr		x8, [%[a], 104]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 104]\n\t"
-        "# A[14] * B\n\t"
-        "ldr		x8, [%[a], 112]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 112]\n\t"
-        "# A[15] * B\n\t"
-        "ldr		x8, [%[a], 120]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 120]\n\t"
-        "# A[16] * B\n\t"
-        "ldr		x8, [%[a], 128]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "# A[17] * B\n\t"
-        "ldr		x8, [%[a], 136]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 136]\n\t"
-        "# A[18] * B\n\t"
-        "ldr		x8, [%[a], 144]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 144]\n\t"
-        "# A[19] * B\n\t"
-        "ldr		x8, [%[a], 152]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 152]\n\t"
-        "# A[20] * B\n\t"
-        "ldr		x8, [%[a], 160]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 160]\n\t"
-        "# A[21] * B\n\t"
-        "ldr		x8, [%[a], 168]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 168]\n\t"
-        "# A[22] * B\n\t"
-        "ldr		x8, [%[a], 176]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "# A[23] * B\n\t"
-        "ldr	x8, [%[a], 184]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x5, [%[r], 184]\n\t"
-        "str	x3, [%[r], 192]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "lsr	x5, %[div], 32\n\t"
-        "add	x5, x5, 1\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x6, x3, 32\n\t"
-        "mul	x4, %[div], x6\n\t"
-        "umulh	x3, %[div], x6\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x3, x3, 32\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d0], %[div]\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x3, %[div], x3\n\t"
-        "sub	%[d0], %[d0], x3\n\t"
-        "mov	%[r], x6\n\t"
-
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "x3", "x4", "x5", "x6"
-    );
-
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_3072_cmp_24(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "mov	x6, 184\n\t"
-        "1:\n\t"
-        "ldr	x4, [%[a], x6]\n\t"
-        "ldr	x5, [%[b], x6]\n\t"
-        "and	x4, x4, x3\n\t"
-        "and	x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "sub	x6, x6, #8\n\t"
-        "b.cc	1b\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "ldr		x4, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 184]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 168]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 152]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 136]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 120]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 104]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 88]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 72]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 56]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 40]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 24]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 8]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_24(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[48], t2[25];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[23];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 24);
-    for (i=23; i>=0; i--) {
-        r1 = div_3072_word_24(t1[24 + i], t1[24 + i - 1], div);
-
-        sp_3072_mul_d_24(t2, d, r1);
-        t1[24 + i] += sp_3072_sub_in_place_24(&t1[i], t2);
-        t1[24 + i] -= t2[24];
-        sp_3072_mask_24(t2, d, t1[24 + i]);
-        t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2);
-        sp_3072_mask_24(t2, d, t1[24 + i]);
-        t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_24(t1, d) >= 0;
-    sp_3072_cond_sub_24(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_24(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_24(a, m, NULL, r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][48];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 48, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 48;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_24(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 24);
-        if (reduceA) {
-            err = sp_3072_mod_24(t[1] + 24, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_24(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24);
-            err = sp_3072_mod_24(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_24(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_24(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_24(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 60;
-        n <<= 4;
-        c = 60;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 60;
-                n <<= 4;
-                c = 60;
-            }
-            else if (c < 4) {
-                y = n >> 60;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 60) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-
-            sp_3072_mont_mul_24(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_mont_reduce_24(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_24(r, m) >= 0);
-        sp_3072_cond_sub_24(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][48];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 48;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_24(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 24);
-        if (reduceA) {
-            err = sp_3072_mod_24(t[1] + 24, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_24(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24);
-            err = sp_3072_mod_24(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_24(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_24(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_24(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_24(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_24(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_24(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_24(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_24(t[20], t[10], m, mp);
-        sp_3072_mont_mul_24(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_24(t[22], t[11], m, mp);
-        sp_3072_mont_mul_24(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_24(t[24], t[12], m, mp);
-        sp_3072_mont_mul_24(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_24(t[26], t[13], m, mp);
-        sp_3072_mont_mul_24(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_24(t[28], t[14], m, mp);
-        sp_3072_mont_mul_24(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_24(t[30], t[15], m, mp);
-        sp_3072_mont_mul_24(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-
-            sp_3072_mont_mul_24(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x1;
-        sp_3072_mont_sqr_24(r, r, m, mp);
-        sp_3072_mont_mul_24(r, r, t[y], m, mp);
-
-        XMEMSET(&r[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_mont_reduce_24(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_24(r, m) >= 0);
-        sp_3072_cond_sub_24(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 48);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_48(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x8, #0\n\t"
-        "1:\n\t"
-        "subs	%[c], xzr, %[c]\n\t"
-        "ldr	x4, [%[a], x8]\n\t"
-        "ldr	x5, [%[b], x8]\n\t"
-        "and	x5, x5, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "csetm	%[c], cc\n\t"
-        "str	x4, [%[r], x8]\n\t"
-        "add	x8, x8, #8\n\t"
-        "cmp	x8, 384\n\t"
-        "b.lt	1b\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x6, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "ldr		x7, [%[b], 8]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "subs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 0]\n\t"
-        "str		x6, [%[r], 8]\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x6, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "ldr		x7, [%[b], 24]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 16]\n\t"
-        "str		x6, [%[r], 24]\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x6, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "ldr		x7, [%[b], 40]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "str		x6, [%[r], 40]\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x6, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "ldr		x7, [%[b], 56]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 48]\n\t"
-        "str		x6, [%[r], 56]\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x6, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "ldr		x7, [%[b], 72]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 64]\n\t"
-        "str		x6, [%[r], 72]\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x6, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "ldr		x7, [%[b], 88]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "str		x6, [%[r], 88]\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x6, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "ldr		x7, [%[b], 104]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 96]\n\t"
-        "str		x6, [%[r], 104]\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x6, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "ldr		x7, [%[b], 120]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 112]\n\t"
-        "str		x6, [%[r], 120]\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x6, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "ldr		x7, [%[b], 136]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "str		x6, [%[r], 136]\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x6, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "ldr		x7, [%[b], 152]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 144]\n\t"
-        "str		x6, [%[r], 152]\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x6, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "ldr		x7, [%[b], 168]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 160]\n\t"
-        "str		x6, [%[r], 168]\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x6, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "ldr		x7, [%[b], 184]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "str		x6, [%[r], 184]\n\t"
-        "ldr		x4, [%[a], 192]\n\t"
-        "ldr		x6, [%[a], 200]\n\t"
-        "ldr		x5, [%[b], 192]\n\t"
-        "ldr		x7, [%[b], 200]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 192]\n\t"
-        "str		x6, [%[r], 200]\n\t"
-        "ldr		x4, [%[a], 208]\n\t"
-        "ldr		x6, [%[a], 216]\n\t"
-        "ldr		x5, [%[b], 208]\n\t"
-        "ldr		x7, [%[b], 216]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 208]\n\t"
-        "str		x6, [%[r], 216]\n\t"
-        "ldr		x4, [%[a], 224]\n\t"
-        "ldr		x6, [%[a], 232]\n\t"
-        "ldr		x5, [%[b], 224]\n\t"
-        "ldr		x7, [%[b], 232]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 224]\n\t"
-        "str		x6, [%[r], 232]\n\t"
-        "ldr		x4, [%[a], 240]\n\t"
-        "ldr		x6, [%[a], 248]\n\t"
-        "ldr		x5, [%[b], 240]\n\t"
-        "ldr		x7, [%[b], 248]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 240]\n\t"
-        "str		x6, [%[r], 248]\n\t"
-        "ldr		x4, [%[a], 256]\n\t"
-        "ldr		x6, [%[a], 264]\n\t"
-        "ldr		x5, [%[b], 256]\n\t"
-        "ldr		x7, [%[b], 264]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 256]\n\t"
-        "str		x6, [%[r], 264]\n\t"
-        "ldr		x4, [%[a], 272]\n\t"
-        "ldr		x6, [%[a], 280]\n\t"
-        "ldr		x5, [%[b], 272]\n\t"
-        "ldr		x7, [%[b], 280]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 272]\n\t"
-        "str		x6, [%[r], 280]\n\t"
-        "ldr		x4, [%[a], 288]\n\t"
-        "ldr		x6, [%[a], 296]\n\t"
-        "ldr		x5, [%[b], 288]\n\t"
-        "ldr		x7, [%[b], 296]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 288]\n\t"
-        "str		x6, [%[r], 296]\n\t"
-        "ldr		x4, [%[a], 304]\n\t"
-        "ldr		x6, [%[a], 312]\n\t"
-        "ldr		x5, [%[b], 304]\n\t"
-        "ldr		x7, [%[b], 312]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 304]\n\t"
-        "str		x6, [%[r], 312]\n\t"
-        "ldr		x4, [%[a], 320]\n\t"
-        "ldr		x6, [%[a], 328]\n\t"
-        "ldr		x5, [%[b], 320]\n\t"
-        "ldr		x7, [%[b], 328]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 320]\n\t"
-        "str		x6, [%[r], 328]\n\t"
-        "ldr		x4, [%[a], 336]\n\t"
-        "ldr		x6, [%[a], 344]\n\t"
-        "ldr		x5, [%[b], 336]\n\t"
-        "ldr		x7, [%[b], 344]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 336]\n\t"
-        "str		x6, [%[r], 344]\n\t"
-        "ldr		x4, [%[a], 352]\n\t"
-        "ldr		x6, [%[a], 360]\n\t"
-        "ldr		x5, [%[b], 352]\n\t"
-        "ldr		x7, [%[b], 360]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 352]\n\t"
-        "str		x6, [%[r], 360]\n\t"
-        "ldr		x4, [%[a], 368]\n\t"
-        "ldr		x6, [%[a], 376]\n\t"
-        "ldr		x5, [%[b], 368]\n\t"
-        "ldr		x7, [%[b], 376]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 368]\n\t"
-        "str		x6, [%[r], 376]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-#endif /* WOLFSSL_SP_SMALL */
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "ldp       x12, x13, [%[m], 0]\n\t"
-        "ldp       x14, x15, [%[m], 16]\n\t"
-        "ldp       x16, x17, [%[m], 32]\n\t"
-        "ldp       x18, x19, [%[m], 48]\n\t"
-        "ldp       x20, x21, [%[m], 64]\n\t"
-        "ldp       x22, x23, [%[m], 80]\n\t"
-        "ldp       x24, x25, [%[m], 96]\n\t"
-        "ldp       x26, x27, [%[m], 112]\n\t"
-        "# i = 0\n\t"
-        "mov	x3, 0\n\t"
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "mul	x8, %[mp], x10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	x9, [%[a], 0]\n\t"
-        "mul		x6, x12, x8\n\t"
-        "umulh	x7, x12, x8\n\t"
-        "adds	x10, x10, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "ldr	x9, [%[a], 8]\n\t"
-        "mul		x6, x13, x8\n\t"
-        "umulh	x7, x13, x8\n\t"
-        "adds	x10, x11, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x10, x10, x5\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "ldr	x11, [%[a], 16]\n\t"
-        "mul		x6, x14, x8\n\t"
-        "umulh	x7, x14, x8\n\t"
-        "adds	x11, x11, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x11, x11, x4\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "ldr	x9, [%[a], 24]\n\t"
-        "mul		x6, x15, x8\n\t"
-        "umulh	x7, x15, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 24]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "ldr	x9, [%[a], 32]\n\t"
-        "mul		x6, x16, x8\n\t"
-        "umulh	x7, x16, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 32]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "ldr	x9, [%[a], 40]\n\t"
-        "mul		x6, x17, x8\n\t"
-        "umulh	x7, x17, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 40]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "ldr	x9, [%[a], 48]\n\t"
-        "mul		x6, x18, x8\n\t"
-        "umulh	x7, x18, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 48]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "ldr	x9, [%[a], 56]\n\t"
-        "mul		x6, x19, x8\n\t"
-        "umulh	x7, x19, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 56]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "ldr	x9, [%[a], 64]\n\t"
-        "mul		x6, x20, x8\n\t"
-        "umulh	x7, x20, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 64]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "ldr	x9, [%[a], 72]\n\t"
-        "mul		x6, x21, x8\n\t"
-        "umulh	x7, x21, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 72]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "ldr	x9, [%[a], 80]\n\t"
-        "mul		x6, x22, x8\n\t"
-        "umulh	x7, x22, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 80]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "ldr	x9, [%[a], 88]\n\t"
-        "mul		x6, x23, x8\n\t"
-        "umulh	x7, x23, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 88]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "ldr	x9, [%[a], 96]\n\t"
-        "mul		x6, x24, x8\n\t"
-        "umulh	x7, x24, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 96]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "ldr	x9, [%[a], 104]\n\t"
-        "mul		x6, x25, x8\n\t"
-        "umulh	x7, x25, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 104]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "ldr	x9, [%[a], 112]\n\t"
-        "mul		x6, x26, x8\n\t"
-        "umulh	x7, x26, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 112]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "ldr	x9, [%[a], 120]\n\t"
-        "mul		x6, x27, x8\n\t"
-        "umulh	x7, x27, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 120]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "ldr		x7, [%[m], 128]\n\t"
-        "ldr	x9, [%[a], 128]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 128]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "ldr		x7, [%[m], 136]\n\t"
-        "ldr	x9, [%[a], 136]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 136]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "ldr		x7, [%[m], 144]\n\t"
-        "ldr	x9, [%[a], 144]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 144]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "ldr		x7, [%[m], 152]\n\t"
-        "ldr	x9, [%[a], 152]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 152]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "ldr		x7, [%[m], 160]\n\t"
-        "ldr	x9, [%[a], 160]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 160]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "ldr		x7, [%[m], 168]\n\t"
-        "ldr	x9, [%[a], 168]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 168]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "ldr		x7, [%[m], 176]\n\t"
-        "ldr	x9, [%[a], 176]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 176]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "ldr		x7, [%[m], 184]\n\t"
-        "ldr	x9, [%[a], 184]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 184]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "ldr		x7, [%[m], 192]\n\t"
-        "ldr	x9, [%[a], 192]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 192]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "ldr		x7, [%[m], 200]\n\t"
-        "ldr	x9, [%[a], 200]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 200]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "ldr		x7, [%[m], 208]\n\t"
-        "ldr	x9, [%[a], 208]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 208]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "ldr		x7, [%[m], 216]\n\t"
-        "ldr	x9, [%[a], 216]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 216]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "ldr		x7, [%[m], 224]\n\t"
-        "ldr	x9, [%[a], 224]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 224]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "ldr		x7, [%[m], 232]\n\t"
-        "ldr	x9, [%[a], 232]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 232]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "ldr		x7, [%[m], 240]\n\t"
-        "ldr	x9, [%[a], 240]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 240]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "ldr		x7, [%[m], 248]\n\t"
-        "ldr	x9, [%[a], 248]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 248]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "ldr		x7, [%[m], 256]\n\t"
-        "ldr	x9, [%[a], 256]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 256]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "ldr		x7, [%[m], 264]\n\t"
-        "ldr	x9, [%[a], 264]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 264]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "ldr		x7, [%[m], 272]\n\t"
-        "ldr	x9, [%[a], 272]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 272]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "ldr		x7, [%[m], 280]\n\t"
-        "ldr	x9, [%[a], 280]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 280]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "ldr		x7, [%[m], 288]\n\t"
-        "ldr	x9, [%[a], 288]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 288]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "ldr		x7, [%[m], 296]\n\t"
-        "ldr	x9, [%[a], 296]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 296]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "ldr		x7, [%[m], 304]\n\t"
-        "ldr	x9, [%[a], 304]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 304]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "ldr		x7, [%[m], 312]\n\t"
-        "ldr	x9, [%[a], 312]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 312]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "ldr		x7, [%[m], 320]\n\t"
-        "ldr	x9, [%[a], 320]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 320]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "ldr		x7, [%[m], 328]\n\t"
-        "ldr	x9, [%[a], 328]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 328]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "ldr		x7, [%[m], 336]\n\t"
-        "ldr	x9, [%[a], 336]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 336]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "ldr		x7, [%[m], 344]\n\t"
-        "ldr	x9, [%[a], 344]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 344]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "ldr		x7, [%[m], 352]\n\t"
-        "ldr	x9, [%[a], 352]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 352]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "ldr		x7, [%[m], 360]\n\t"
-        "ldr	x9, [%[a], 360]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x4, x7, xzr\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 360]\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "ldr		x7, [%[m], 368]\n\t"
-        "ldr	x9, [%[a], 368]\n\t"
-        "mul		x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x9, x9, x6\n\t"
-        "adc	x5, x7, xzr\n\t"
-        "adds	x9, x9, x4\n\t"
-        "str	x9, [%[a], 368]\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "ldr	x7, [%[m], 376]\n\t"
-        "ldr	x9, [%[a], 376]\n\t"
-        "mul	x6, x7, x8\n\t"
-        "umulh	x7, x7, x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x7, x7, %[ca]\n\t"
-        "cset  %[ca], cs\n\t"
-        "adds	x9, x9, x5\n\t"
-        "str	x9, [%[a], 376]\n\t"
-        "ldr	x9, [%[a], 384]\n\t"
-        "adcs	x9, x9, x7\n\t"
-        "str	x9, [%[a], 384]\n\t"
-        "adc	%[ca], %[ca], xzr\n\t"
-        "# i += 1\n\t"
-        "add	%[a], %[a], 8\n\t"
-        "add	x3, x3, 8\n\t"
-        "cmp	x3, 384\n\t"
-        "blt	1b\n\t"
-        "str	x10, [%[a], 0]\n\t"
-        "str	x11, [%[a], 8]\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27"
-    );
-
-    sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_48(r, a, b);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_48(r, a);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x5, %[b], x8\n\t"
-        "umulh	x3, %[b], x8\n\t"
-        "mov	x4, 0\n\t"
-        "str	x5, [%[r]]\n\t"
-        "mov	x5, 0\n\t"
-        "mov	x9, #8\n\t"
-        "1:\n\t"
-        "ldr	x8, [%[a], x9]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "str	x3, [%[r], x9]\n\t"
-        "mov	x3, x4\n\t"
-        "mov	x4, x5\n\t"
-        "mov	x5, #0\n\t"
-        "add	x9, x9, #8\n\t"
-        "cmp	x9, 384\n\t"
-        "b.lt	1b\n\t"
-        "str	x3, [%[r], 384]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#else
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x3, %[b], x8\n\t"
-        "umulh	x4, %[b], x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr		x8, [%[a], 8]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 8]\n\t"
-        "# A[2] * B\n\t"
-        "ldr		x8, [%[a], 16]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 16]\n\t"
-        "# A[3] * B\n\t"
-        "ldr		x8, [%[a], 24]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 24]\n\t"
-        "# A[4] * B\n\t"
-        "ldr		x8, [%[a], 32]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 32]\n\t"
-        "# A[5] * B\n\t"
-        "ldr		x8, [%[a], 40]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 40]\n\t"
-        "# A[6] * B\n\t"
-        "ldr		x8, [%[a], 48]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 48]\n\t"
-        "# A[7] * B\n\t"
-        "ldr		x8, [%[a], 56]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 56]\n\t"
-        "# A[8] * B\n\t"
-        "ldr		x8, [%[a], 64]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 64]\n\t"
-        "# A[9] * B\n\t"
-        "ldr		x8, [%[a], 72]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 72]\n\t"
-        "# A[10] * B\n\t"
-        "ldr		x8, [%[a], 80]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 80]\n\t"
-        "# A[11] * B\n\t"
-        "ldr		x8, [%[a], 88]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 88]\n\t"
-        "# A[12] * B\n\t"
-        "ldr		x8, [%[a], 96]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 96]\n\t"
-        "# A[13] * B\n\t"
-        "ldr		x8, [%[a], 104]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 104]\n\t"
-        "# A[14] * B\n\t"
-        "ldr		x8, [%[a], 112]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 112]\n\t"
-        "# A[15] * B\n\t"
-        "ldr		x8, [%[a], 120]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 120]\n\t"
-        "# A[16] * B\n\t"
-        "ldr		x8, [%[a], 128]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 128]\n\t"
-        "# A[17] * B\n\t"
-        "ldr		x8, [%[a], 136]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 136]\n\t"
-        "# A[18] * B\n\t"
-        "ldr		x8, [%[a], 144]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 144]\n\t"
-        "# A[19] * B\n\t"
-        "ldr		x8, [%[a], 152]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 152]\n\t"
-        "# A[20] * B\n\t"
-        "ldr		x8, [%[a], 160]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 160]\n\t"
-        "# A[21] * B\n\t"
-        "ldr		x8, [%[a], 168]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 168]\n\t"
-        "# A[22] * B\n\t"
-        "ldr		x8, [%[a], 176]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 176]\n\t"
-        "# A[23] * B\n\t"
-        "ldr		x8, [%[a], 184]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 184]\n\t"
-        "# A[24] * B\n\t"
-        "ldr		x8, [%[a], 192]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 192]\n\t"
-        "# A[25] * B\n\t"
-        "ldr		x8, [%[a], 200]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 200]\n\t"
-        "# A[26] * B\n\t"
-        "ldr		x8, [%[a], 208]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 208]\n\t"
-        "# A[27] * B\n\t"
-        "ldr		x8, [%[a], 216]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 216]\n\t"
-        "# A[28] * B\n\t"
-        "ldr		x8, [%[a], 224]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 224]\n\t"
-        "# A[29] * B\n\t"
-        "ldr		x8, [%[a], 232]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 232]\n\t"
-        "# A[30] * B\n\t"
-        "ldr		x8, [%[a], 240]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 240]\n\t"
-        "# A[31] * B\n\t"
-        "ldr		x8, [%[a], 248]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 248]\n\t"
-        "# A[32] * B\n\t"
-        "ldr		x8, [%[a], 256]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 256]\n\t"
-        "# A[33] * B\n\t"
-        "ldr		x8, [%[a], 264]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 264]\n\t"
-        "# A[34] * B\n\t"
-        "ldr		x8, [%[a], 272]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 272]\n\t"
-        "# A[35] * B\n\t"
-        "ldr		x8, [%[a], 280]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 280]\n\t"
-        "# A[36] * B\n\t"
-        "ldr		x8, [%[a], 288]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 288]\n\t"
-        "# A[37] * B\n\t"
-        "ldr		x8, [%[a], 296]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 296]\n\t"
-        "# A[38] * B\n\t"
-        "ldr		x8, [%[a], 304]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 304]\n\t"
-        "# A[39] * B\n\t"
-        "ldr		x8, [%[a], 312]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 312]\n\t"
-        "# A[40] * B\n\t"
-        "ldr		x8, [%[a], 320]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 320]\n\t"
-        "# A[41] * B\n\t"
-        "ldr		x8, [%[a], 328]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 328]\n\t"
-        "# A[42] * B\n\t"
-        "ldr		x8, [%[a], 336]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 336]\n\t"
-        "# A[43] * B\n\t"
-        "ldr		x8, [%[a], 344]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 344]\n\t"
-        "# A[44] * B\n\t"
-        "ldr		x8, [%[a], 352]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 352]\n\t"
-        "# A[45] * B\n\t"
-        "ldr		x8, [%[a], 360]\n\t"
-        "mov		x5, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc		x5, xzr, xzr\n\t"
-        "str		x3, [%[r], 360]\n\t"
-        "# A[46] * B\n\t"
-        "ldr		x8, [%[a], 368]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 368]\n\t"
-        "# A[47] * B\n\t"
-        "ldr	x8, [%[a], 376]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adc	x3, x3, x7\n\t"
-        "str	x5, [%[r], 376]\n\t"
-        "str	x3, [%[r], 384]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-#endif
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "lsr	x5, %[div], 32\n\t"
-        "add	x5, x5, 1\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x6, x3, 32\n\t"
-        "mul	x4, %[div], x6\n\t"
-        "umulh	x3, %[div], x6\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x3, x3, 32\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d0], %[div]\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x3, %[div], x3\n\t"
-        "sub	%[d0], %[d0], x3\n\t"
-        "mov	%[r], x6\n\t"
-
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "x3", "x4", "x5", "x6"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<48; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_3072_cmp_48(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "mov	x6, 376\n\t"
-        "1:\n\t"
-        "ldr	x4, [%[a], x6]\n\t"
-        "ldr	x5, [%[b], x6]\n\t"
-        "and	x4, x4, x3\n\t"
-        "and	x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "sub	x6, x6, #8\n\t"
-        "b.cc	1b\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "ldr		x4, [%[a], 376]\n\t"
-        "ldr		x5, [%[b], 376]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 368]\n\t"
-        "ldr		x5, [%[b], 368]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 360]\n\t"
-        "ldr		x5, [%[b], 360]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 352]\n\t"
-        "ldr		x5, [%[b], 352]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 344]\n\t"
-        "ldr		x5, [%[b], 344]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 336]\n\t"
-        "ldr		x5, [%[b], 336]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 328]\n\t"
-        "ldr		x5, [%[b], 328]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 320]\n\t"
-        "ldr		x5, [%[b], 320]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 312]\n\t"
-        "ldr		x5, [%[b], 312]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 304]\n\t"
-        "ldr		x5, [%[b], 304]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 296]\n\t"
-        "ldr		x5, [%[b], 296]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 288]\n\t"
-        "ldr		x5, [%[b], 288]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 280]\n\t"
-        "ldr		x5, [%[b], 280]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 272]\n\t"
-        "ldr		x5, [%[b], 272]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 264]\n\t"
-        "ldr		x5, [%[b], 264]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 256]\n\t"
-        "ldr		x5, [%[b], 256]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 248]\n\t"
-        "ldr		x5, [%[b], 248]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 240]\n\t"
-        "ldr		x5, [%[b], 240]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 232]\n\t"
-        "ldr		x5, [%[b], 232]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 224]\n\t"
-        "ldr		x5, [%[b], 224]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 216]\n\t"
-        "ldr		x5, [%[b], 216]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 208]\n\t"
-        "ldr		x5, [%[b], 208]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 200]\n\t"
-        "ldr		x5, [%[b], 200]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 192]\n\t"
-        "ldr		x5, [%[b], 192]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 184]\n\t"
-        "ldr		x5, [%[b], 184]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 176]\n\t"
-        "ldr		x5, [%[b], 176]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 168]\n\t"
-        "ldr		x5, [%[b], 168]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 160]\n\t"
-        "ldr		x5, [%[b], 160]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 152]\n\t"
-        "ldr		x5, [%[b], 152]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 144]\n\t"
-        "ldr		x5, [%[b], 144]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 136]\n\t"
-        "ldr		x5, [%[b], 136]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 128]\n\t"
-        "ldr		x5, [%[b], 128]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 120]\n\t"
-        "ldr		x5, [%[b], 120]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 112]\n\t"
-        "ldr		x5, [%[b], 112]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 104]\n\t"
-        "ldr		x5, [%[b], 104]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 96]\n\t"
-        "ldr		x5, [%[b], 96]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 88]\n\t"
-        "ldr		x5, [%[b], 88]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 80]\n\t"
-        "ldr		x5, [%[b], 80]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 72]\n\t"
-        "ldr		x5, [%[b], 72]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 64]\n\t"
-        "ldr		x5, [%[b], 64]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 56]\n\t"
-        "ldr		x5, [%[b], 56]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 48]\n\t"
-        "ldr		x5, [%[b], 48]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 40]\n\t"
-        "ldr		x5, [%[b], 40]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 32]\n\t"
-        "ldr		x5, [%[b], 32]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 24]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 8]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#endif
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[96], t2[49];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[47];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
-    for (i=47; i>=0; i--) {
-        r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
-
-        sp_3072_mul_d_48(t2, d, r1);
-        t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
-        t1[48 + i] -= t2[48];
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_48(t1, d) >= 0;
-    sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_48(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_48_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[96], t2[49];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[47];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
-    for (i=47; i>=0; i--) {
-        r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
-
-        sp_3072_mul_d_48(t2, d, r1);
-        t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
-        t1[48 + i] -= t2[48];
-        if (t1[48 + i] != 0) {
-            t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d);
-            if (t1[48 + i] != 0)
-                t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_3072_cmp_48(t1, d) >= 0;
-    sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_48_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef WOLFSSL_SP_SMALL
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[16][96];
-#else
-    sp_digit* t[16];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<16; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 60;
-        n <<= 4;
-        c = 60;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=4; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 60;
-                n <<= 4;
-                c = 60;
-            }
-            else if (c < 4) {
-                y = n >> 60;
-                n = e[i--];
-                c = 4 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 60) & 0xf;
-                n <<= 4;
-                c -= 4;
-            }
-
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-
-            sp_3072_mont_mul_48(r, r, t[y], m, mp);
-        }
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#else
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][96];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_48(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_48(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_48(t[20], t[10], m, mp);
-        sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_48(t[22], t[11], m, mp);
-        sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_48(t[24], t[12], m, mp);
-        sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_48(t[26], t[13], m, mp);
-        sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_48(t[28], t[14], m, mp);
-        sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_48(t[30], t[15], m, mp);
-        sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-
-            sp_3072_mont_mul_48(r, r, t[y], m, mp);
-        }
-        y = e[0] & 0x3;
-        sp_3072_mont_sqr_48(r, r, m, mp);
-        sp_3072_mont_sqr_48(r, r, m, mp);
-        sp_3072_mont_mul_48(r, r, t[y], m, mp);
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[96], md[48], rd[96];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 48 * 2;
-        m = r + 48 * 2;
-        ah = a + 48;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 48;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(ah, 48, in, inLen);
-#if DIGIT_BIT >= 64
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 48, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_3072_sqr_48(r, ah);
-                err = sp_3072_mod_48_cond(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_3072_mul_48(r, ah, r);
-                err = sp_3072_mod_48_cond(r, r, m);
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_3072_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=63; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 48);
-                for (i--; i>=0; i--) {
-                    sp_3072_mont_sqr_48(r, r, m, mp);
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_3072_mont_mul_48(r, r, a, m, mp);
-                }
-                XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-                sp_3072_mont_reduce_48(r, m, mp);
-
-                for (i = 47; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_3072_sub_in_place_48(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[48 * 2];
-    sp_digit pd[24], qd[24], dpd[24];
-    sp_digit tmpad[48], tmpbd[48];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 48 * 2;
-        q = p + 24;
-        qi = dq = dp = q + 24;
-        tmpa = qi + 24;
-        tmpb = tmpa + 48;
-
-        tmp = t;
-        r = tmp + 48;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 48;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 48, in, inLen);
-        sp_3072_from_mp(p, 24, pm);
-        sp_3072_from_mp(q, 24, qm);
-        sp_3072_from_mp(dp, 24, dpm);
-
-        err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(dq, 24, dqm);
-        err = sp_3072_mod_exp_24(tmpb, a, dq, 1536, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_3072_sub_in_place_24(tmpa, tmpb);
-        sp_3072_mask_24(tmp, p, c);
-        sp_3072_add_24(tmpa, tmpa, tmp);
-
-        sp_3072_from_mp(qi, 24, qim);
-        sp_3072_mul_24(tmpa, tmpa, qi);
-        err = sp_3072_mod_24(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_24(tmpa, q, tmpa);
-        XMEMSET(&tmpb[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_add_48(r, tmpb, tmpa);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_3072_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 48);
-        r->used = 48;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 48; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 48; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[96], e[48], m[48];
-    sp_digit* r = b;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 48, base);
-        sp_3072_from_mp(e, 48, exp);
-        sp_3072_from_mp(m, 48, mod);
-
-        err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 384 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[96], e[48], m[48];
-    sp_digit* r = b;
-    word32 i;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 48, base);
-        sp_3072_from_bin(e, 48, exp, expLen);
-        sp_3072_from_mp(m, 48, mod);
-
-        err = sp_3072_mod_exp_48(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_3072 */
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-
-/* Point structure to use. */
-typedef struct sp_point {
-    sp_digit x[2 * 4];
-    sp_digit y[2 * 4];
-    sp_digit z[2 * 4];
-    int infinity;
-} sp_point;
-
-/* The modulus (prime) of the curve P256. */
-static sp_digit p256_mod[4] = {
-    0xffffffffffffffffl,0x00000000ffffffffl,0x0000000000000000l,
-    0xffffffff00000001l
-};
-/* The Montogmery normalizer for modulus of the curve P256. */
-static sp_digit p256_norm_mod[4] = {
-    0x0000000000000001l,0xffffffff00000000l,0xffffffffffffffffl,
-    0x00000000fffffffel
-};
-/* The Montogmery multiplier for modulus of the curve P256. */
-static sp_digit p256_mp_mod = 0x0000000000000001;
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
-                                            defined(HAVE_ECC_VERIFY)
-/* The order of the curve P256. */
-static sp_digit p256_order[4] = {
-    0xf3b9cac2fc632551l,0xbce6faada7179e84l,0xffffffffffffffffl,
-    0xffffffff00000000l
-};
-#endif
-/* The order of the curve P256 minus 2. */
-static sp_digit p256_order2[4] = {
-    0xf3b9cac2fc63254fl,0xbce6faada7179e84l,0xffffffffffffffffl,
-    0xffffffff00000000l
-};
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery normalizer for order of the curve P256. */
-static sp_digit p256_norm_order[4] = {
-    0x0c46353d039cdaafl,0x4319055258e8617bl,0x0000000000000000l,
-    0x00000000ffffffffl
-};
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery multiplier for order of the curve P256. */
-static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl;
-#endif
-#ifdef WOLFSSL_SP_SMALL
-/* The base point of curve P256. */
-static sp_point p256_base = {
-    /* X ordinate */
-    {
-        0xf4a13945d898c296l,0x77037d812deb33a0l,0xf8bce6e563a440f2l,
-        0x6b17d1f2e12c4247l
-    },
-    /* Y ordinate */
-    {
-        0xcbb6406837bf51f5l,0x2bce33576b315ecel,0x8ee7eb4a7c0f9e16l,
-        0x4fe342e2fe1a7f9bl
-    },
-    /* Z ordinate */
-    {
-        0x0000000000000001l,0x0000000000000000l,0x0000000000000000l,
-        0x0000000000000000l
-    },
-    /* infinity */
-    0
-};
-#endif /* WOLFSSL_SP_SMALL */
-#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
-static sp_digit p256_b[4] = {
-    0x3bce3c3e27d2604bl,0x651d06b0cc53b0f6l,0xb3ebbd55769886bcl,
-    0x5ac635d8aa3a93e7l
-};
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* Allocate memory for point and return error. */
-#define sp_ecc_point_new(heap, sp, p)                                   \
-    ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \
-        MEMORY_E : MP_OKAY
-#else
-/* Set pointer to data and return no error. */
-#define sp_ecc_point_new(heap, sp, p)   ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* If valid pointer then clear point data if requested and free data. */
-#define sp_ecc_point_free(p, clear, heap)     \
-    do {                                      \
-        if (p != NULL) {                      \
-            if (clear)                        \
-                XMEMSET(p, 0, sizeof(*p));    \
-            XFREE(p, heap, DYNAMIC_TYPE_ECC); \
-        }                                     \
-    }                                         \
-    while (0)
-#else
-/* Clear point data if requested. */
-#define sp_ecc_point_free(p, clear, heap) \
-    do {                                  \
-        if (clear)                        \
-            XMEMSET(p, 0, sizeof(*p));    \
-    }                                     \
-    while (0)
-#endif
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r  The resulting Montgomery form number.
- * a  The number to convert.
- * m  The modulus (prime).
- */
-static int sp_256_mod_mul_norm_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    int64_t t[8];
-    int64_t a32[8];
-    int64_t o;
-
-    (void)m;
-
-    a32[0] = a[0] & 0xffffffff;
-    a32[1] = a[0] >> 32;
-    a32[2] = a[1] & 0xffffffff;
-    a32[3] = a[1] >> 32;
-    a32[4] = a[2] & 0xffffffff;
-    a32[5] = a[2] >> 32;
-    a32[6] = a[3] & 0xffffffff;
-    a32[7] = a[3] >> 32;
-
-    /*  1  1  0 -1 -1 -1 -1  0 */
-    t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
-    /*  0  1  1  0 -1 -1 -1 -1 */
-    t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
-    /*  0  0  1  1  0 -1 -1 -1 */
-    t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
-    /* -1 -1  0  2  2  1  0 -1 */
-    t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
-    /*  0 -1 -1  0  2  2  1  0 */
-    t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
-    /*  0  0 -1 -1  0  2  2  1 */
-    t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
-    /* -1 -1  0  0  0  1  3  2 */
-    t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
-    /*  1  0 -1 -1 -1 -1  0  3 */
-    t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    o     = t[7] >> 32; t[7] &= 0xffffffff;
-    t[0] += o;
-    t[3] -= o;
-    t[6] -= o;
-    t[7] += o;
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    r[0] = (t[1] << 32) | t[0];
-    r[1] = (t[3] << 32) | t[2];
-    r[2] = (t[5] << 32) | t[4];
-    r[3] = (t[7] << 32) | t[6];
-
-    return MP_OKAY;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point.
- *
- * p   Point of type sp_point (result).
- * pm  Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_4(sp_point* p, ecc_point* pm)
-{
-    XMEMSET(p->x, 0, sizeof(p->x));
-    XMEMSET(p->y, 0, sizeof(p->y));
-    XMEMSET(p->z, 0, sizeof(p->z));
-    sp_256_from_mp(p->x, 4, pm->x);
-    sp_256_from_mp(p->y, 4, pm->y);
-    sp_256_from_mp(p->z, 4, pm->z);
-    p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_256_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 4);
-        r->used = 4;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 4; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 4; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Convert a point of type sp_point to type ecc_point.
- *
- * p   Point of type sp_point.
- * pm  Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_4(sp_point* p, ecc_point* pm)
-{
-    int err;
-
-    err = sp_256_to_mp(p->x, pm->x);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pm->y);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pm->z);
-
-    return err;
-}
-
-/* Conditionally copy a into r using the mask m.
- * m is -1 to copy and 0 when not.
- *
- * r  A single precision number to copy over.
- * a  A single precision number to copy.
- * m  Mask value to apply.
- */
-static void sp_256_cond_copy_4(sp_digit* r, const sp_digit* a, const sp_digit m)
-{
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[r], 0]\n\t"
-        "ldp	x5, x6, [%[r], 16]\n\t"
-        "ldp	x7, x8, [%[a], 0]\n\t"
-        "ldp	x9, x10, [%[a], 16]\n\t"
-        "eor	x7, x7, x3\n\t"
-        "eor	x8, x8, x4\n\t"
-        "eor	x9, x9, x5\n\t"
-        "eor	x10, x10, x6\n\t"
-        "and	x7, x7, %[m]\n\t"
-        "and	x8, x8, %[m]\n\t"
-        "and	x9, x9, %[m]\n\t"
-        "and	x10, x10, %[m]\n\t"
-        "eor	x3, x3, x7\n\t"
-        "eor	x4, x4, x8\n\t"
-        "eor	x5, x5, x9\n\t"
-        "eor	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [m] "r" (m)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_256_cmp_4(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-#ifdef WOLFSSL_SP_SMALL
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "mov	x6, 24\n\t"
-        "1:\n\t"
-        "ldr	x4, [%[a], x6]\n\t"
-        "ldr	x5, [%[b], x6]\n\t"
-        "and	x4, x4, x3\n\t"
-        "and	x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "sub	x6, x6, #8\n\t"
-        "b.cc	1b\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#else
-    __asm__ __volatile__ (
-        "mov	x3, -1\n\t"
-        "ldr		x4, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 24]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 8]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "and		x4, x4, x3\n\t"
-        "and		x5, x5, x3\n\t"
-        "subs	x4, x4, x5\n\t"
-        "csel	%[r], %[one], %[r], hi\n\t"
-        "csel	%[r], x3, %[r], lo\n\t"
-        "csel	x3, x3, xzr, eq\n\t"
-        "eor	%[r], %[r], x3\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "x2", "x3", "x4", "x5", "x6"
-    );
-#endif
-
-    return r;
-}
-
-/* Normalize the values in each word to 64.
- *
- * a  Array of sp_digit to normalize.
- */
-#define sp_256_norm_4(a)
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_256_cond_sub_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-
-        "ldr		x4, [%[a], 0]\n\t"
-        "ldr		x6, [%[a], 8]\n\t"
-        "ldr		x5, [%[b], 0]\n\t"
-        "ldr		x7, [%[b], 8]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "subs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 0]\n\t"
-        "str		x6, [%[r], 8]\n\t"
-        "ldr		x4, [%[a], 16]\n\t"
-        "ldr		x6, [%[a], 24]\n\t"
-        "ldr		x5, [%[b], 16]\n\t"
-        "ldr		x7, [%[b], 24]\n\t"
-        "and		x5, x5, %[m]\n\t"
-        "and		x7, x7, %[m]\n\t"
-        "sbcs	x4, x4, x5\n\t"
-        "sbcs	x6, x6, x7\n\t"
-        "str		x4, [%[r], 16]\n\t"
-        "str		x6, [%[r], 24]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x6", "x5", "x7", "x8"
-    );
-
-    return c;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "subs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "sbcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "mov	x9, xzr\n\t"
-        "mov	x8, xzr\n\t"
-        "mov	x6, %[a]\n\t"
-        "\n1:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "ldr	x5, [x6, 0]\n\t"
-        "mov	x7, x5\n\t"
-        "mul	x5, %[mp], x5\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "ldr	x4, [%[m], 0]\n\t"
-        "ldr	x11, [%[m], 8]\n\t"
-        "mul	x3, x4, x5\n\t"
-        "umulh	x10, x4, x5\n\t"
-        "adds	x7, x7, x3\n\t"
-        "str	x7, [x6, 0]\n\t"
-        "adc	x10, x10, xzr\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "mul	x3, x11, x5\n\t"
-        "umulh	x12, x11, x5\n\t"
-        "ldr	x11, [%[m], 16]\n\t"
-        "ldr	x7, [x6, 8]\n\t"
-        "adds	x3, x3, x10\n\t"
-        "adc	x12, x12, xzr\n\t"
-        "adds	x7, x7, x3\n\t"
-        "str	x7, [x6, 8]\n\t"
-        "adc	x12, x12, xzr\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "mul	x3, x11, x5\n\t"
-        "umulh	x10, x11, x5\n\t"
-        "ldr	x11, [%[m], 24]\n\t"
-        "ldr	x7, [x6, 16]\n\t"
-        "adds	x3, x3, x12\n\t"
-        "adc	x10, x10, xzr\n\t"
-        "adds	x7, x7, x3\n\t"
-        "str	x7, [x6, 16]\n\t"
-        "adc	x10, x10, xzr\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "mul	x3, x11, x5\n\t"
-        "umulh	x4, x11, x5\n\t"
-        "ldr	x7, [x6, 24]\n\t"
-        "ldr	x12, [x6, 32]\n\t"
-        "adds	x3, x3, x10\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "cset	x9, cs\n\t"
-        "adds	x7, x7, x3\n\t"
-        "str	x7, [x6, 24]\n\t"
-        "adcs	x12, x12, x4\n\t"
-        "str	x12, [x6, 32]\n\t"
-        "adc	x9, x9, xzr\n\t"
-        "# i += 1\n\t"
-        "add	x6, x6, 8\n\t"
-        "add	x8, x8, 8\n\t"
-        "cmp	x8, 32\n\t"
-        "b.lt	1b\n\t"
-        "ldr	x5, [%[a], 32]\n\t"
-        "ldr	x6, [%[a], 40]\n\t"
-        "ldr	x7, [%[a], 48]\n\t"
-        "ldr	x8, [%[a], 56]\n\t"
-        "sub	x3, xzr, x9\n\t"
-        "ldr	x9, [%[m], 0]\n\t"
-        "ldr	x10, [%[m], 8]\n\t"
-        "ldr	x11, [%[m], 16]\n\t"
-        "ldr	x12, [%[m], 24]\n\t"
-        "and	x9, x9, x3\n\t"
-        "and	x10, x10, x3\n\t"
-        "and	x11, x11, x3\n\t"
-        "and	x12, x12, x3\n\t"
-        "subs	x5, x5, x9\n\t"
-        "sbcs	x6, x6, x10\n\t"
-        "sbcs	x7, x7, x11\n\t"
-        "sbc	x8, x8, x12\n\t"
-        "str	x5, [%[a], 0]\n\t"
-        "str	x6, [%[a], 8]\n\t"
-        "str	x7, [%[a], 16]\n\t"
-        "str	x8, [%[a], 24]\n\t"
-        :
-        : [a] "r" (a), [m] "r" (m), [mp] "r" (mp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
-          "x12"
-    );
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_mul_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    (void)mp;
-
-    __asm__ __volatile__ (
-        "ldr	x18, [%[a], 0]\n\t"
-        "ldr	x19, [%[a], 8]\n\t"
-        "ldr	x20, [%[a], 16]\n\t"
-        "ldr	x21, [%[a], 24]\n\t"
-        "ldr	x22, [%[b], 0]\n\t"
-        "ldr	x23, [%[b], 8]\n\t"
-        "ldr	x24, [%[b], 16]\n\t"
-        "ldr	x25, [%[b], 24]\n\t"
-        "#  A[0] * B[0]\n\t"
-        "mul	x10, x18, x22\n\t"
-        "umulh	x11, x18, x22\n\t"
-        "#  A[0] * B[1]\n\t"
-        "mul	x5, x18, x23\n\t"
-        "umulh	x6, x18, x23\n\t"
-        "adds	x11, x11, x5\n\t"
-        "adc	x12, xzr, x6\n\t"
-        "#  A[1] * B[0]\n\t"
-        "mul	x5, x19, x22\n\t"
-        "umulh	x6, x19, x22\n\t"
-        "adds	x11, x11, x5\n\t"
-        "adcs	x12, x12, x6\n\t"
-        "adc	x13, xzr, xzr\n\t"
-        "#  A[0] * B[2]\n\t"
-        "mul	x5, x18, x24\n\t"
-        "umulh	x6, x18, x24\n\t"
-        "adds	x12, x12, x5\n\t"
-        "adc	x13, x13, x6\n\t"
-        "#  A[1] * B[1]\n\t"
-        "mul	x5, x19, x23\n\t"
-        "umulh	x6, x19, x23\n\t"
-        "adds	x12, x12, x5\n\t"
-        "adcs	x13, x13, x6\n\t"
-        "adc	x14, xzr, xzr\n\t"
-        "#  A[2] * B[0]\n\t"
-        "mul	x5, x20, x22\n\t"
-        "umulh	x6, x20, x22\n\t"
-        "adds	x12, x12, x5\n\t"
-        "adcs	x13, x13, x6\n\t"
-        "adc	x14, x14, xzr\n\t"
-        "#  A[0] * B[3]\n\t"
-        "mul	x5, x18, x25\n\t"
-        "umulh	x6, x18, x25\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adc	x15, xzr, xzr\n\t"
-        "#  A[1] * B[2]\n\t"
-        "mul	x5, x19, x24\n\t"
-        "umulh	x6, x19, x24\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adc	x15, x15, xzr\n\t"
-        "#  A[2] * B[1]\n\t"
-        "mul	x5, x20, x23\n\t"
-        "umulh	x6, x20, x23\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adc	x15, x15, xzr\n\t"
-        "#  A[3] * B[0]\n\t"
-        "mul	x5, x21, x22\n\t"
-        "umulh	x6, x21, x22\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adc	x15, x15, xzr\n\t"
-        "#  A[1] * B[3]\n\t"
-        "mul	x5, x19, x25\n\t"
-        "umulh	x6, x19, x25\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adcs	x15, x15, x6\n\t"
-        "adc	x16, xzr, xzr\n\t"
-        "#  A[2] * B[2]\n\t"
-        "mul	x5, x20, x24\n\t"
-        "umulh	x6, x20, x24\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adcs	x15, x15, x6\n\t"
-        "adc	x16, x16, xzr\n\t"
-        "#  A[3] * B[1]\n\t"
-        "mul	x5, x21, x23\n\t"
-        "umulh	x6, x21, x23\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adcs	x15, x15, x6\n\t"
-        "adc	x16, x16, xzr\n\t"
-        "#  A[2] * B[3]\n\t"
-        "mul	x5, x20, x25\n\t"
-        "umulh	x6, x20, x25\n\t"
-        "adds	x15, x15, x5\n\t"
-        "adcs	x16, x16, x6\n\t"
-        "adc	x17, xzr, xzr\n\t"
-        "#  A[3] * B[2]\n\t"
-        "mul	x5, x21, x24\n\t"
-        "umulh	x6, x21, x24\n\t"
-        "adds	x15, x15, x5\n\t"
-        "adcs	x16, x16, x6\n\t"
-        "adc	x17, x17, xzr\n\t"
-        "#  A[3] * B[3]\n\t"
-        "mul	x5, x21, x25\n\t"
-        "umulh	x6, x21, x25\n\t"
-        "adds	x16, x16, x5\n\t"
-        "adc	x17, x17, x6\n\t"
-        "# Start Reduction\n\t"
-        "mov	x5, x10\n\t"
-        "mov	x6, x11\n\t"
-        "mov	x7, x12\n\t"
-        "mov	x8, x13\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "add	x8, x8, x10\n\t"
-        "add	x8, x8, x10\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "lsl	x10, x10, 32\n\t"
-        "lsr	x18, x5, 32\n\t"
-        "lsl	x11, x6, 32\n\t"
-        "lsr	x19, x6, 32\n\t"
-        "lsl	x12, x7, 32\n\t"
-        "eor	x11, x11, x18\n\t"
-        "eor	x12, x12, x19\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "sub	x8, x8, x10\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "adds	x6, x6, x10\n\t"
-        "adcs	x7, x7, x11\n\t"
-        "adc	x8, x8, x12\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adcs	x15, x15, x6\n\t"
-        "adcs	x16, x16, x7\n\t"
-        "adcs	x17, x17, x8\n\t"
-        "csetm	x10, cs\n\t"
-        "#   a += mu << 192\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adcs	x15, x15, x7\n\t"
-        "adcs	x16, x16, x8\n\t"
-        "adcs	x17, x17, xzr\n\t"
-        "csetm	x20, cs\n\t"
-        "add	x10, x10, x20\n\t"
-        "# mu <<= 32\n\t"
-        "lsr	x9, x8, 32\n\t"
-        "lsr	x18, x5, 32\n\t"
-        "lsl	x5, x5, 32\n\t"
-        "lsr	x19, x6, 32\n\t"
-        "lsl	x6, x6, 32\n\t"
-        "lsr	x20, x7, 32\n\t"
-        "lsl	x7, x7, 32\n\t"
-        "lsl	x8, x8, 32\n\t"
-        "eor	x6, x6, x18\n\t"
-        "eor	x7, x7, x19\n\t"
-        "eor	x8, x8, x20\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "adds	x13, x13, x7\n\t"
-        "adcs	x14, x14, x8\n\t"
-        "adcs	x15, x15, x9\n\t"
-        "adcs	x16, x16, xzr\n\t"
-        "adcs	x17, x17, xzr\n\t"
-        "csetm	x20, cs\n\t"
-        "add	x10, x10, x20\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subs	x13, x13, x5\n\t"
-        "mov	x18, 0xffffffff\n\t"
-        "sbcs	x14, x14, x6\n\t"
-        "mov	x19, 0xffffffff00000001\n\t"
-        "sbcs	x15, x15, x7\n\t"
-        "sbcs	x16, x16, x8\n\t"
-        "sbcs	x17, x17, x9\n\t"
-        "cset	x20, cc\n\t"
-        "add	x10, x10, x20\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "and	x18, x18, x10\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "and	x19, x19, x10\n\t"
-        "subs	x14, x14, x10\n\t"
-        "sbcs	x15, x15, x18\n\t"
-        "sbcs	x16, x16, xzr\n\t"
-        "sbc	x17, x17, x19\n\t"
-        "str	x14, [%[r], 0]\n\t"
-        "str	x15, [%[r], 8]\n\t"
-        "str	x16, [%[r], 16]\n\t"
-        "str	x17, [%[r], 24]\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b)
-        : [r] "r" (r)
-        : "memory", "x5", "x6", "x7", "x8", "x9",
-          "x18", "x19", "x20", "x21",
-          "x22", "x23", "x24", "x25",
-          "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"
-    );
-}
-
-/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_sqr_4(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "ldr	x18, [%[a], 0]\n\t"
-        "ldr	x19, [%[a], 8]\n\t"
-        "ldr	x20, [%[a], 16]\n\t"
-        "ldr	x21, [%[a], 24]\n\t"
-        "#  A[0] * A[1]\n\t"
-        "mul	x11, x18, x19\n\t"
-        "umulh	x12, x18, x19\n\t"
-        "#  A[0] * A[2]\n\t"
-        "mul	x5, x18, x20\n\t"
-        "umulh	x6, x18, x20\n\t"
-        "adds	x12, x12, x5\n\t"
-        "adc	x13, xzr, x6\n\t"
-        "#  A[0] * A[3]\n\t"
-        "mul	x5, x18, x21\n\t"
-        "umulh	x6, x18, x21\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adc	x14, xzr, x6\n\t"
-        "#  A[1] * A[2]\n\t"
-        "mul	x5, x19, x20\n\t"
-        "umulh	x6, x19, x20\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adc	x15, xzr, xzr\n\t"
-        "#  A[1] * A[3]\n\t"
-        "mul	x5, x19, x21\n\t"
-        "umulh	x6, x19, x21\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adc	x15, x15, x6\n\t"
-        "#  A[2] * A[3]\n\t"
-        "mul	x5, x20, x21\n\t"
-        "umulh	x6, x20, x21\n\t"
-        "adds	x15, x15, x5\n\t"
-        "adc	x16, xzr, x6\n\t"
-        "# Double\n\t"
-        "adds	x11, x11, x11\n\t"
-        "adcs	x12, x12, x12\n\t"
-        "adcs	x13, x13, x13\n\t"
-        "adcs	x14, x14, x14\n\t"
-        "adcs	x15, x15, x15\n\t"
-        "adcs	x16, x16, x16\n\t"
-        "cset	x17, cs\n\t"
-        "#  A[0] * A[0]\n\t"
-        "mul	x10, x18, x18\n\t"
-        "umulh	x4, x18, x18\n\t"
-        "#  A[1] * A[1]\n\t"
-        "mul	x5, x19, x19\n\t"
-        "umulh	x6, x19, x19\n\t"
-        "#  A[2] * A[2]\n\t"
-        "mul	x7, x20, x20\n\t"
-        "umulh	x8, x20, x20\n\t"
-        "#  A[3] * A[3]\n\t"
-        "mul	x9, x21, x21\n\t"
-        "umulh	x18, x21, x21\n\t"
-        "adds	x11, x11, x4\n\t"
-        "adcs	x12, x12, x5\n\t"
-        "adcs	x13, x13, x6\n\t"
-        "adcs	x14, x14, x7\n\t"
-        "adcs	x15, x15, x8\n\t"
-        "adcs	x16, x16, x9\n\t"
-        "adc	x17, x17, x18\n\t"
-        "# Start Reduction\n\t"
-        "mov	x5, x10\n\t"
-        "mov	x6, x11\n\t"
-        "mov	x7, x12\n\t"
-        "mov	x8, x13\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "add	x8, x8, x10\n\t"
-        "add	x8, x8, x10\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "lsl	x10, x10, 32\n\t"
-        "lsr	x18, x5, 32\n\t"
-        "lsl	x11, x6, 32\n\t"
-        "lsr	x19, x6, 32\n\t"
-        "lsl	x12, x7, 32\n\t"
-        "eor	x11, x11, x18\n\t"
-        "eor	x12, x12, x19\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "sub	x8, x8, x10\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "adds	x6, x6, x10\n\t"
-        "adcs	x7, x7, x11\n\t"
-        "adc	x8, x8, x12\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "adds	x14, x14, x5\n\t"
-        "adcs	x15, x15, x6\n\t"
-        "adcs	x16, x16, x7\n\t"
-        "adcs	x17, x17, x8\n\t"
-        "csetm	x10, cs\n\t"
-        "#   a += mu << 192\n\t"
-        "adds	x13, x13, x5\n\t"
-        "adcs	x14, x14, x6\n\t"
-        "adcs	x15, x15, x7\n\t"
-        "adcs	x16, x16, x8\n\t"
-        "adcs	x17, x17, xzr\n\t"
-        "csetm	x20, cs\n\t"
-        "add	x10, x10, x20\n\t"
-        "# mu <<= 32\n\t"
-        "lsr	x9, x8, 32\n\t"
-        "lsr	x18, x5, 32\n\t"
-        "lsl	x5, x5, 32\n\t"
-        "lsr	x19, x6, 32\n\t"
-        "lsl	x6, x6, 32\n\t"
-        "lsr	x20, x7, 32\n\t"
-        "lsl	x7, x7, 32\n\t"
-        "lsl	x8, x8, 32\n\t"
-        "eor	x6, x6, x18\n\t"
-        "eor	x7, x7, x19\n\t"
-        "eor	x8, x8, x20\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "adds	x13, x13, x7\n\t"
-        "adcs	x14, x14, x8\n\t"
-        "adcs	x15, x15, x9\n\t"
-        "adcs	x16, x16, xzr\n\t"
-        "adcs	x17, x17, xzr\n\t"
-        "csetm	x20, cs\n\t"
-        "add	x10, x10, x20\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subs	x13, x13, x5\n\t"
-        "mov	x18, 0xffffffff\n\t"
-        "sbcs	x14, x14, x6\n\t"
-        "mov	x19, 0xffffffff00000001\n\t"
-        "sbcs	x15, x15, x7\n\t"
-        "sbcs	x16, x16, x8\n\t"
-        "sbcs	x17, x17, x9\n\t"
-        "cset	x20, cc\n\t"
-        "add	x10, x10, x20\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "and	x18, x18, x10\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "and	x19, x19, x10\n\t"
-        "subs	x14, x14, x10\n\t"
-        "sbcs	x15, x15, x18\n\t"
-        "sbcs	x16, x16, xzr\n\t"
-        "sbc	x17, x17, x19\n\t"
-        "str	x14, [%[r], 0]\n\t"
-        "str	x15, [%[r], 8]\n\t"
-        "str	x16, [%[r], 16]\n\t"
-        "str	x17, [%[r], 24]\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp)
-        : [r] "r" (r)
-        : "memory", "x4", "x5", "x6", "x7", "x8", "x9",
-          "x18", "x19", "x20", "x21",
-          "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"
-    );
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_4(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_4(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_4(r, r, m, mp);
-}
-
-#else
-/* Mod-2 for the P256 curve. */
-static const uint64_t p256_mod_2[4] = {
-    0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000,
-    0xffffffff00000001
-};
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_4(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_4(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_4(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_4(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_4(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_4(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_4(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_4(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_4(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_4(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_4(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_4(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_4(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_4(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    int64_t n;
-
-    sp_256_mont_inv_4(t1, p->z, t + 2*4);
-
-    sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_4(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 4, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_4(r->x, p256_mod);
-    sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_4(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 4, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_4(r->y, p256_mod);
-    sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-/* Add two Montgomery form numbers (r = a + b % m).
- *
- * r   Result of addition.
- * a   First number to add in Montogmery form.
- * b   Second number to add in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_add_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "ldr	x4, [%[a],0]\n\t"
-        "ldr	x5, [%[a],8]\n\t"
-        "ldr	x6, [%[a],16]\n\t"
-        "ldr	x7, [%[a],24]\n\t"
-        "ldr	x8, [%[b],0]\n\t"
-        "ldr	x9, [%[b],8]\n\t"
-        "ldr	x10, [%[b],16]\n\t"
-        "ldr	x11, [%[b],24]\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "mov	x12, 0xffffffff\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "adcs	x7, x7, x11\n\t"
-        "mov	x13, 0xffffffff00000001\n\t"
-        "csetm	x14, cs\n\t"
-        "and	x12, x12, x14\n\t"
-        "and	x13, x13, x14\n\t"
-        "subs	x4, x4, x14\n\t"
-        "sbcs	x5, x5, x12\n\t"
-        "str	x4, [%[r],0]\n\t"
-        "sbcs	x6, x6, xzr\n\t"
-        "str	x5, [%[r],8]\n\t"
-        "sbc	x7, x7, x13\n\t"
-        "str	x6, [%[r],16]\n\t"
-        "str	x7, [%[r],24]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14"
-    );
-}
-
-/* Double a Montgomery form number (r = a + a % m).
- *
- * r   Result of doubling.
- * a   Number to double in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_dbl_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "ldr	x3, [%[a]]\n\t"
-        "ldr	x4, [%[a],8]\n\t"
-        "ldr	x5, [%[a],16]\n\t"
-        "ldr	x6, [%[a],24]\n\t"
-        "adds	x3, x3, x3\n\t"
-        "adcs	x4, x4, x4\n\t"
-        "mov	x7, 0xffffffff\n\t"
-        "adcs	x5, x5, x5\n\t"
-        "mov	x8, 0xffffffff00000001\n\t"
-        "adcs	x6, x6, x6\n\t"
-        "csetm	x9, cs\n\t"
-        "and	x7, x7, x9\n\t"
-        "and	x8, x8, x9\n\t"
-        "subs	x3, x3, x9\n\t"
-        "sbcs	x4, x4, x7\n\t"
-        "str	x3, [%[r],0]\n\t"
-        "sbcs	x5, x5, xzr\n\t"
-        "str	x4, [%[r],8]\n\t"
-        "sbc	x6, x6, x8\n\t"
-        "str	x5, [%[r],16]\n\t"
-        "str	x6, [%[r],24]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    (void)m;
-}
-
-/* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r   Result of Tripling.
- * a   Number to triple in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_tpl_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "ldr	x10, [%[a]]\n\t"
-        "ldr	x11, [%[a],8]\n\t"
-        "ldr	x12, [%[a],16]\n\t"
-        "ldr	x13, [%[a],24]\n\t"
-        "adds	x3, x10, x10\n\t"
-        "adcs	x4, x11, x11\n\t"
-        "mov	x7, 0xffffffff\n\t"
-        "adcs	x5, x12, x12\n\t"
-        "mov	x8, 0xffffffff00000001\n\t"
-        "adcs	x6, x13, x13\n\t"
-        "csetm	x9, cs\n\t"
-        "and	x7, x7, x9\n\t"
-        "and	x8, x8, x9\n\t"
-        "subs	x3, x3, x9\n\t"
-        "sbcs	x4, x4, x7\n\t"
-        "sbcs	x5, x5, xzr\n\t"
-        "sbc	x6, x6, x8\n\t"
-        "adds	x3, x3, x10\n\t"
-        "adcs	x4, x4, x11\n\t"
-        "mov	x7, 0xffffffff\n\t"
-        "adcs	x5, x5, x12\n\t"
-        "mov	x8, 0xffffffff00000001\n\t"
-        "adcs	x6, x6, x13\n\t"
-        "csetm	x9, cs\n\t"
-        "and	x7, x7, x9\n\t"
-        "and	x8, x8, x9\n\t"
-        "subs	x3, x3, x9\n\t"
-        "sbcs	x4, x4, x7\n\t"
-        "sbcs	x5, x5, xzr\n\t"
-        "sbc	x6, x6, x8\n\t"
-        "str	x3, [%[r], 0]\n\t"
-        "str	x4, [%[r], 8]\n\t"
-        "str	x5, [%[r], 16]\n\t"
-        "str	x6, [%[r], 24]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "x10", "x11", "x12", "x13", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    (void)m;
-}
-
-/* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r   Result of subtration.
- * a   Number to subtract from in Montogmery form.
- * b   Number to subtract with in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_sub_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "ldr	x4, [%[a],0]\n\t"
-        "ldr	x5, [%[a],8]\n\t"
-        "ldr	x6, [%[a],16]\n\t"
-        "ldr	x7, [%[a],24]\n\t"
-        "ldr	x8, [%[b],0]\n\t"
-        "ldr	x9, [%[b],8]\n\t"
-        "ldr	x10, [%[b],16]\n\t"
-        "ldr	x11, [%[b],24]\n\t"
-        "subs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "mov	x12, 0xffffffff\n\t"
-        "sbcs	x6, x6, x10\n\t"
-        "sbcs	x7, x7, x11\n\t"
-        "mov	x13, 0xffffffff00000001\n\t"
-        "csetm	x14, cc\n\t"
-        "and	x12, x12, x14\n\t"
-        "and	x13, x13, x14\n\t"
-        "adds	x4, x4, x14\n\t"
-        "adcs	x5, x5, x12\n\t"
-        "str	x4, [%[r],0]\n\t"
-        "adcs	x6, x6, xzr\n\t"
-        "str	x5, [%[r],8]\n\t"
-        "adc	x7, x7, x13\n\t"
-        "str	x6, [%[r],16]\n\t"
-        "str	x7, [%[r],24]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14"
-    );
-}
-
-/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r  Result of division by 2.
- * a  Number to divide.
- * m  Modulus (prime).
- */
-static void sp_256_div2_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "ldr	x3, [%[a], 0]\n\t"
-        "ldr	x4, [%[a], 8]\n\t"
-        "ldr	x5, [%[a], 16]\n\t"
-        "ldr	x6, [%[a], 24]\n\t"
-        "and	x9, x3, 1\n\t"
-        "sub	x10, xzr, x9\n\t"
-        "and	x7, x10, 0xffffffff\n\t"
-        "and	x8, x10, 0xffffffff00000001\n\t"
-        "adds	x3, x3, x10\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adcs	x5, x5, xzr\n\t"
-        "adcs	x6, x6, x8\n\t"
-        "cset	x9, cs\n\t"
-        "lsr	x3, x3, 1\n\t"
-        "lsr	x7, x4, 1\n\t"
-        "lsr	x8, x5, 1\n\t"
-        "lsr	x10, x6, 1\n\t"
-        "orr	x3, x3, x4, lsl 63\n\t"
-        "orr	x4, x7, x5, lsl 63\n\t"
-        "orr	x5, x8, x6, lsl 63\n\t"
-        "orr	x6, x10, x9, lsl 63\n\t"
-        "str	x3, [%[r], 0]\n\t"
-        "str	x4, [%[r], 8]\n\t"
-        "str	x5, [%[r], 16]\n\t"
-        "str	x6, [%[r], 24]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [m] "r" (m)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_4(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_4(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_4(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_4(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_4(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_4(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_4(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_4(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_4(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_4(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_4(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_4(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_4(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_4(y, y, p256_mod);
-}
-
-/* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a  First number to compare.
- * b  Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
-static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b)
-{
-    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0;
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_4(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, x, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, y, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, y, t5, p256_mod);
-    }
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_store_4(sp_point* r, sp_point* p,
-        int n, int m, sp_digit* t)
-{
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x = r[2*m].x;
-    sp_digit* y = r[(1<<n)*m].y;
-    sp_digit* z = r[2*m].z;
-    int i;
-
-    for (i=0; i<4; i++)
-        x[i] = p->x[i];
-    for (i=0; i<4; i++)
-        y[i] = p->y[i];
-    for (i=0; i<4; i++)
-        z[i] = p->z[i];
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod);
-    for (i=1; i<=n; i++) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod);
-        x = r[(1<<i)*m].x;
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_4(r[(1<<i)*m].z, z, y, p256_mod, p256_mp_mod);
-        z = r[(1<<i)*m].z;
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod);
-        if (i != n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-        /* Y = Y/2 */
-        sp_256_div2_4(r[(1<<i)*m].y, y, p256_mod);
-        r[(1<<i)*m].infinity = 0;
-    }
-}
-
-/* Add two Montgomery form projective points.
- *
- * ra  Result of addition.
- * rs  Result of subtraction.
- * p   Frist point to add.
- * q   Second point to add.
- * t   Temporary ordinate data.
- */
-static void sp_256_proj_point_add_sub_4(sp_point* ra, sp_point* rs,
-        sp_point* p, sp_point* q, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* t6 = t + 10*4;
-    sp_digit* x = ra->x;
-    sp_digit* y = ra->y;
-    sp_digit* z = ra->z;
-    sp_digit* xs = rs->x;
-    sp_digit* ys = rs->y;
-    sp_digit* zs = rs->z;
-
-
-    XMEMCPY(x, p->x, sizeof(p->x) / 2);
-    XMEMCPY(y, p->y, sizeof(p->y) / 2);
-    XMEMCPY(z, p->z, sizeof(p->z) / 2);
-    ra->infinity = 0;
-    rs->infinity = 0;
-
-    /* U1 = X1*Z2^2 */
-    sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod);
-    /* U2 = X2*Z1^2 */
-    sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-    /* S1 = Y1*Z2^3 */
-    sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod);
-    /* S2 = Y2*Z1^3 */
-    sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-    /* H = U2 - U1 */
-    sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-    /* RS = S2 + S1 */
-    sp_256_mont_add_4(t6, t4, t3, p256_mod);
-    /* R = S2 - S1 */
-    sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-    /* Z3 = H*Z1*Z2 */
-    /* ZS = H*Z1*Z2 */
-    sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-    XMEMCPY(zs, z, sizeof(p->z)/2);
-    /* X3 = R^2 - H^3 - 2*U1*H^2 */
-    /* XS = RS^2 - H^3 - 2*U1*H^2 */
-    sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(xs, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(x, x, t5, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t5, p256_mod);
-    sp_256_mont_dbl_4(t1, y, p256_mod);
-    sp_256_mont_sub_4(x, x, t1, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t1, p256_mod);
-    /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-    /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
-    sp_256_mont_sub_4(ys, y, xs, p256_mod);
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod);
-    sp_256_sub_4(t6, p256_mod, t6);
-    sp_256_mont_mul_4(ys, ys, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(y, y, t5, p256_mod);
-    sp_256_mont_sub_4(ys, ys, t5, p256_mod);
-}
-
-/* Structure used to describe recoding of scalar multiplication. */
-typedef struct ecc_recode {
-    /* Index into pre-computation table. */
-    uint8_t i;
-    /* Use the negative of the point. */
-    uint8_t neg;
-} ecc_recode;
-
-/* The index into pre-computation table to use. */
-static uint8_t recode_index_4_6[66] = {
-     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
-    16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,
-     0,  1,
-};
-
-/* Whether to negate y-ordinate. */
-static uint8_t recode_neg_4_6[66] = {
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     0,  0,
-};
-
-/* Recode the scalar for multiplication using pre-computed values and
- * subtraction.
- *
- * k  Scalar to multiply by.
- * v  Vector of operations to peform.
- */
-static void sp_256_ecc_recode_6_4(sp_digit* k, ecc_recode* v)
-{
-    int i, j;
-    uint8_t y;
-    int carry = 0;
-    int o;
-    sp_digit n;
-
-    j = 0;
-    n = k[j];
-    o = 0;
-    for (i=0; i<43; i++) {
-        y = n;
-        if (o + 6 < 64) {
-            y &= 0x3f;
-            n >>= 6;
-            o += 6;
-        }
-        else if (o + 6 == 64) {
-            n >>= 6;
-            if (++j < 4)
-                n = k[j];
-            o = 0;
-        }
-        else if (++j < 4) {
-            n = k[j];
-            y |= (n << (64 - o)) & 0x3f;
-            o -= 58;
-            n >>= o;
-        }
-
-        y += carry;
-        v[i].i = recode_index_4_6[y];
-        v[i].neg = recode_neg_4_6[y];
-        carry = (y >> 6) + v[i].neg;
-    }
-}
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_win_add_sub_4(sp_point* r, sp_point* g,
-        sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[33];
-    sp_point rtd, pd;
-    sp_digit tmpd[2 * 4 * 6];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode v[43];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        t[1].infinity = 0;
-        /* t[2] ... t[32]  */
-    sp_256_proj_point_dbl_n_store_4(t, &t[ 1], 5, 1, tmp);
-    sp_256_proj_point_add_4(&t[ 3], &t[ 2], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[ 6], &t[ 3], tmp);
-    sp_256_proj_point_add_sub_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[10], &t[ 5], tmp);
-    sp_256_proj_point_add_sub_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[12], &t[ 6], tmp);
-    sp_256_proj_point_dbl_4(&t[14], &t[ 7], tmp);
-    sp_256_proj_point_add_sub_4(&t[15], &t[13], &t[14], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[18], &t[ 9], tmp);
-    sp_256_proj_point_add_sub_4(&t[19], &t[17], &t[18], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[20], &t[10], tmp);
-    sp_256_proj_point_dbl_4(&t[22], &t[11], tmp);
-    sp_256_proj_point_add_sub_4(&t[23], &t[21], &t[22], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[24], &t[12], tmp);
-    sp_256_proj_point_dbl_4(&t[26], &t[13], tmp);
-    sp_256_proj_point_add_sub_4(&t[27], &t[25], &t[26], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[28], &t[14], tmp);
-    sp_256_proj_point_dbl_4(&t[30], &t[15], tmp);
-    sp_256_proj_point_add_sub_4(&t[31], &t[29], &t[30], &t[ 1], tmp);
-
-        negy = t[0].y;
-
-        sp_256_ecc_recode_6_4(k, v);
-
-        i = 42;
-        XMEMCPY(rt, &t[v[i].i], sizeof(sp_point));
-        for (--i; i>=0; i--) {
-            sp_256_proj_point_dbl_n_4(rt, rt, 6, tmp);
-
-            XMEMCPY(p, &t[v[i].i], sizeof(sp_point));
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_4(rt, rt, p, tmp);
-        }
-
-        if (map)
-            sp_256_map_4(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    if (tmp != NULL)
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry {
-    sp_digit x[4];
-    sp_digit y[4];
-    byte infinity;
-} sp_table_entry;
-
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_4(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_4(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_4(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_4(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, t3, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_4(t3, t3, x, p256_mod);
-        sp_256_mont_mul_4(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_4(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 4;
-    sp_digit* tmp = t + 4 * 4;
-
-    sp_256_mont_inv_4(t1, a->z, tmp);
-
-    sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_4(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_4(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_4(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_4(t, t, 32, tmp);
-            sp_256_proj_to_affine_4(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_4(t, s1, s2, tmp);
-                sp_256_proj_to_affine_4(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_4(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 4 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-
-            sp_256_proj_point_dbl_4(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_4(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_4(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[4];
-    sp_digit y[4];
-    sp_table_entry table[256];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_4(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_4(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_4(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 4 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_4(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_4(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * p     Point to multiply.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, km);
-        sp_256_point_from_ecc_point_4(point, gm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(point, point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(point, point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#ifdef WOLFSSL_SP_SMALL
-static sp_table_entry p256_table[256] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l,
-        0x18905f76a53755c6l },
-      { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l,
-        0x8571ff1825885d85l },
-      0 },
-    /* 2 */
-    { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l,
-        0xd953c50ddbdf58e9l },
-      { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl,
-        0x863ebb7e9eb288f3l },
-      0 },
-    /* 3 */
-    { { 0x7856b6235cdb6485l,0x808f0ea22f0a2f97l,0x3e68d9544f7e300bl,
-        0x00076055b5ff80a0l },
-      { 0x7634eb9b838d2010l,0x54014fbb3243708al,0xe0e47d39842a6606l,
-        0x8308776134373ee0l },
-      0 },
-    /* 4 */
-    { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl,
-        0x2f5e6961fd1b667fl },
-      { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l,
-        0xf648f9168d6f0f7bl },
-      0 },
-    /* 5 */
-    { { 0x9e566847e137bbbcl,0xe434469e8a6a0becl,0xb1c4276179d73463l,
-        0x5abe0285133d0015l },
-      { 0x92aa837cc04c7dabl,0x573d9f4c43260c07l,0x0c93156278e6cc37l,
-        0x94bb725b6b6f7383l },
-      0 },
-    /* 6 */
-    { { 0xbbf9b48f720f141cl,0x6199b3cd2df5bc74l,0xdc3f6129411045c4l,
-        0xcdd6bbcb2f7dc4efl },
-      { 0xcca6700beaf436fdl,0x6f647f6db99326bel,0x0c0fa792014f2522l,
-        0xa361bebd4bdae5f6l },
-      0 },
-    /* 7 */
-    { { 0x28aa2558597c13c7l,0xc38d635f50b7c3e1l,0x07039aecf3c09d1dl,
-        0xba12ca09c4b5292cl },
-      { 0x9e408fa459f91dfdl,0x3af43b66ceea07fbl,0x1eceb0899d780b29l,
-        0x53ebb99d701fef4bl },
-      0 },
-    /* 8 */
-    { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l,
-        0x8589fb9206d54831l },
-      { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l,
-        0xebb0696d02541c4fl },
-      0 },
-    /* 9 */
-    { { 0x4616ca15ac1647c5l,0xb8127d47c4cf5799l,0xdc666aa3764dfbacl,
-        0xeb2820cbd1b27da3l },
-      { 0x9406f8d86a87e008l,0xd87dfa9d922378f3l,0x56ed2e4280ccecb2l,
-        0x1f28289b55a7da1dl },
-      0 },
-    /* 10 */
-    { { 0xabbaa0c03b89da99l,0xa6f2d79eb8284022l,0x27847862b81c05e8l,
-        0x337a4b5905e54d63l },
-      { 0x3c67500d21f7794al,0x207005b77d6d7f61l,0x0a5a378104cfd6e8l,
-        0x0d65e0d5f4c2fbd6l },
-      0 },
-    /* 11 */
-    { { 0xd9d09bbeb5275d38l,0x4268a7450be0a358l,0xf0762ff4973eb265l,
-        0xc23da24252f4a232l },
-      { 0x5da1b84f0b94520cl,0x09666763b05bd78el,0x3a4dcb8694d29ea1l,
-        0x19de3b8cc790cff1l },
-      0 },
-    /* 12 */
-    { { 0x183a716c26c5fe04l,0x3b28de0b3bba1bdbl,0x7432c586a4cb712cl,
-        0xe34dcbd491fccbfdl },
-      { 0xb408d46baaa58403l,0x9a69748682e97a53l,0x9e39012736aaa8afl,
-        0xe7641f447b4e0f7fl },
-      0 },
-    /* 13 */
-    { { 0x7d753941df64ba59l,0xd33f10ec0b0242fcl,0x4f06dfc6a1581859l,
-        0x4a12df57052a57bfl },
-      { 0xbfa6338f9439dbd0l,0xd3c24bd4bde53e1fl,0xfd5e4ffa21f1b314l,
-        0x6af5aa93bb5bea46l },
-      0 },
-    /* 14 */
-    { { 0xda10b69910c91999l,0x0a24b4402a580491l,0x3e0094b4b8cc2090l,
-        0x5fe3475a66a44013l },
-      { 0xb0f8cabdf93e7b4bl,0x292b501a7c23f91al,0x42e889aecd1e6263l,
-        0xb544e308ecfea916l },
-      0 },
-    /* 15 */
-    { { 0x6478c6e916ddfdcel,0x2c329166f89179e6l,0x4e8d6e764d4e67e1l,
-        0xe0b6b2bda6b0c20bl },
-      { 0x0d312df2bb7efb57l,0x1aac0dde790c4007l,0xf90336ad679bc944l,
-        0x71c023de25a63774l },
-      0 },
-    /* 16 */
-    { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l,
-        0x61d587d421d324f6l },
-      { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el,
-        0xfa11fe124621efbel },
-      0 },
-    /* 17 */
-    { { 0x1c891f2b2cb19ffdl,0x01ba8d5bb1923c23l,0xb6d03d678ac5ca8el,
-        0x586eb04c1f13bedcl },
-      { 0x0c35c6e527e8ed09l,0x1e81a33c1819ede2l,0x278fd6c056c652fal,
-        0x19d5ac0870864f11l },
-      0 },
-    /* 18 */
-    { { 0x1e99f581309a4e1fl,0xab7de71be9270074l,0x26a5ef0befd28d20l,
-        0xe7c0073f7f9c563fl },
-      { 0x1f6d663a0ef59f76l,0x669b3b5420fcb050l,0xc08c1f7a7a6602d4l,
-        0xe08504fec65b3c0al },
-      0 },
-    /* 19 */
-    { { 0xf098f68da031b3cal,0x6d1cab9ee6da6d66l,0x5bfd81fa94f246e8l,
-        0x78f018825b0996b4l },
-      { 0xb7eefde43a25787fl,0x8016f80d1dccac9bl,0x0cea4877b35bfc36l,
-        0x43a773b87e94747al },
-      0 },
-    /* 20 */
-    { { 0x62577734d2b533d5l,0x673b8af6a1bdddc0l,0x577e7c9aa79ec293l,
-        0xbb6de651c3b266b1l },
-      { 0xe7e9303ab65259b3l,0xd6a0afd3d03a7480l,0xc5ac83d19b3cfc27l,
-        0x60b4619a5d18b99bl },
-      0 },
-    /* 21 */
-    { { 0xbd6a38e11ae5aa1cl,0xb8b7652b49e73658l,0x0b130014ee5f87edl,
-        0x9d0f27b2aeebffcdl },
-      { 0xca9246317a730a55l,0x9c955b2fddbbc83al,0x07c1dfe0ac019a71l,
-        0x244a566d356ec48dl },
-      0 },
-    /* 22 */
-    { { 0x6db0394aeacf1f96l,0x9f2122a9024c271cl,0x2626ac1b82cbd3b9l,
-        0x45e58c873581ef69l },
-      { 0xd3ff479da38f9dbcl,0xa8aaf146e888a040l,0x945adfb246e0bed7l,
-        0xc040e21cc1e4b7a4l },
-      0 },
-    /* 23 */
-    { { 0x847af0006f8117b6l,0x651969ff73a35433l,0x482b35761d9475ebl,
-        0x1cdf5c97682c6ec7l },
-      { 0x7db775b411f04839l,0x7dbeacf448de1698l,0xb2921dd1b70b3219l,
-        0x046755f8a92dff3dl },
-      0 },
-    /* 24 */
-    { { 0xcc8ac5d2bce8ffcdl,0x0d53c48b2fe61a82l,0xf6f161727202d6c7l,
-        0x046e5e113b83a5f3l },
-      { 0xe7b8ff64d8007f01l,0x7fb1ef125af43183l,0x045c5ea635e1a03cl,
-        0x6e0106c3303d005bl },
-      0 },
-    /* 25 */
-    { { 0x48c7358488dd73b1l,0x7670708f995ed0d9l,0x38385ea8c56a2ab7l,
-        0x442594ede901cf1fl },
-      { 0xf8faa2c912d4b65bl,0x94c2343b96c90c37l,0xd326e4a15e978d1fl,
-        0xa796fa514c2ee68el },
-      0 },
-    /* 26 */
-    { { 0x359fb604823addd7l,0x9e2a6183e56693b3l,0xf885b78e3cbf3c80l,
-        0xe4ad2da9c69766e9l },
-      { 0x357f7f428e048a61l,0x082d198cc092d9a0l,0xfc3a1af4c03ed8efl,
-        0xc5e94046c37b5143l },
-      0 },
-    /* 27 */
-    { { 0x476a538c2be75f9el,0x6fd1a9e8cb123a78l,0xd85e4df0b109c04bl,
-        0x63283dafdb464747l },
-      { 0xce728cf7baf2df15l,0xe592c4550ad9a7f4l,0xfab226ade834bcc3l,
-        0x68bd19ab1981a938l },
-      0 },
-    /* 28 */
-    { { 0xc08ead511887d659l,0x3374d5f4b359305al,0x96986981cfe74fe3l,
-        0x495292f53c6fdfd6l },
-      { 0x4a878c9e1acec896l,0xd964b210ec5b4484l,0x6696f7e2664d60a7l,
-        0x0ec7530d26036837l },
-      0 },
-    /* 29 */
-    { { 0x2da13a05ad2687bbl,0xa1f83b6af32e21fal,0x390f5ef51dd4607bl,
-        0x0f6207a664863f0bl },
-      { 0xbd67e3bb0f138233l,0xdd66b96c272aa718l,0x8ed0040726ec88ael,
-        0xff0db07208ed6dcfl },
-      0 },
-    /* 30 */
-    { { 0x749fa1014c95d553l,0xa44052fd5d680a8al,0x183b4317ff3b566fl,
-        0x313b513c88740ea3l },
-      { 0xb402e2ac08d11549l,0x071ee10bb4dee21cl,0x26b987dd47f2320el,
-        0x2d3abcf986f19f81l },
-      0 },
-    /* 31 */
-    { { 0x4c288501815581a2l,0x9a0a6d56632211afl,0x19ba7a0f0cab2e99l,
-        0xc036fa10ded98cdfl },
-      { 0x29ae08bac1fbd009l,0x0b68b19006d15816l,0xc2eb32779b9e0d8fl,
-        0xa6b2a2c4b6d40194l },
-      0 },
-    /* 32 */
-    { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l,
-        0x810ee252af7c9860l },
-      { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l,
-        0xd485717a92731745l },
-      0 },
-    /* 33 */
-    { { 0x11741a8af0cb5a98l,0xd3da8f931f3110bfl,0x1994e2cbab382adfl,
-        0x6a6045a72f9a604el },
-      { 0x170c0d3fa2b2411dl,0xbe0eb83e510e96e0l,0x3bcc9f738865b3ccl,
-        0xd3e45cfaf9e15790l },
-      0 },
-    /* 34 */
-    { { 0xce1f69bbe83f7669l,0x09f8ae8272877d6bl,0x9548ae543244278dl,
-        0x207755dee3c2c19cl },
-      { 0x87bd61d96fef1945l,0x18813cefb12d28c3l,0x9fbcd1d672df64aal,
-        0x48dc5ee57154b00dl },
-      0 },
-    /* 35 */
-    { { 0x123790bff7e5a199l,0xe0efb8cf989ccbb7l,0xc27a2bfe0a519c79l,
-        0xf2fb0aeddff6f445l },
-      { 0x41c09575f0b5025fl,0x550543d740fa9f22l,0x8fa3c8ad380bfbd0l,
-        0xa13e9015db28d525l },
-      0 },
-    /* 36 */
-    { { 0xf9f7a350a2b65cbcl,0x0b04b9722a464226l,0x265ce241e23f07a1l,
-        0x2bf0d6b01497526fl },
-      { 0xd3d4dd3f4b216fb7l,0xf7d7b867fbdda26al,0xaeb7b83f6708505cl,
-        0x42a94a5a162fe89fl },
-      0 },
-    /* 37 */
-    { { 0x5846ad0beaadf191l,0x0f8a489025a268d7l,0xe8603050494dc1f6l,
-        0x2c2dd969c65ede3dl },
-      { 0x6d02171d93849c17l,0x460488ba1da250ddl,0x4810c7063c3a5485l,
-        0xf437fa1f42c56dbcl },
-      0 },
-    /* 38 */
-    { { 0x6aa0d7144a0f7dabl,0x0f0497931776e9acl,0x52c0a050f5f39786l,
-        0xaaf45b3354707aa8l },
-      { 0x85e37c33c18d364al,0xd40b9b063e497165l,0xf417168115ec5444l,
-        0xcdf6310df4f272bcl },
-      0 },
-    /* 39 */
-    { { 0x7473c6238ea8b7efl,0x08e9351885bc2287l,0x419567722bda8e34l,
-        0xf0d008bada9e2ff2l },
-      { 0x2912671d2414d3b1l,0xb3754985b019ea76l,0x5c61b96d453bcbdbl,
-        0x5bd5c2f5ca887b8bl },
-      0 },
-    /* 40 */
-    { { 0xef0f469ef49a3154l,0x3e85a5956e2b2e9al,0x45aaec1eaa924a9cl,
-        0xaa12dfc8a09e4719l },
-      { 0x26f272274df69f1dl,0xe0e4c82ca2ff5e73l,0xb9d8ce73b7a9dd44l,
-        0x6c036e73e48ca901l },
-      0 },
-    /* 41 */
-    { { 0x5cfae12a0f6e3138l,0x6966ef0025ad345al,0x8993c64b45672bc5l,
-        0x292ff65896afbe24l },
-      { 0xd5250d445e213402l,0xf6580e274392c9fel,0x097b397fda1c72e8l,
-        0x644e0c90311b7276l },
-      0 },
-    /* 42 */
-    { { 0xe1e421e1a47153f0l,0xb86c3b79920418c9l,0x93bdce87705d7672l,
-        0xf25ae793cab79a77l },
-      { 0x1f3194a36d869d0cl,0x9d55c8824986c264l,0x49fb5ea3096e945el,
-        0x39b8e65313db0a3el },
-      0 },
-    /* 43 */
-    { { 0x37754200b6fd2e59l,0x35e2c0669255c98fl,0xd9dab21a0e2a5739l,
-        0x39122f2f0f19db06l },
-      { 0xcfbce1e003cad53cl,0x225b2c0fe65c17e3l,0x72baf1d29aa13877l,
-        0x8de80af8ce80ff8dl },
-      0 },
-    /* 44 */
-    { { 0xafbea8d9207bbb76l,0x921c7e7c21782758l,0xdfa2b74b1c0436b1l,
-        0x871949062e368c04l },
-      { 0xb5f928bba3993df5l,0x639d75b5f3b3d26al,0x011aa78a85b55050l,
-        0xfc315e6a5b74fde1l },
-      0 },
-    /* 45 */
-    { { 0x561fd41ae8d6ecfal,0x5f8c44f61aec7f86l,0x98452a7b4924741dl,
-        0xe6d4a7adee389088l },
-      { 0x60552ed14593c75dl,0x70a70da4dd271162l,0xd2aede937ba2c7dbl,
-        0x35dfaf9a9be2ae57l },
-      0 },
-    /* 46 */
-    { { 0x6b956fcdaa736636l,0x09f51d97ae2cab7el,0xfb10bf410f349966l,
-        0x1da5c7d71c830d2bl },
-      { 0x5c41e4833cce6825l,0x15ad118ff9573c3bl,0xa28552c7f23036b8l,
-        0x7077c0fddbf4b9d6l },
-      0 },
-    /* 47 */
-    { { 0xbf63ff8d46b9661cl,0xa1dfd36b0d2cfd71l,0x0373e140a847f8f7l,
-        0x53a8632ee50efe44l },
-      { 0x0976ff68696d8051l,0xdaec0c95c74f468al,0x62994dc35e4e26bdl,
-        0x028ca76d34e1fcc1l },
-      0 },
-    /* 48 */
-    { { 0xd11d47dcfc9877eel,0xc8b36210801d0002l,0xd002c11754c260b6l,
-        0x04c17cd86962f046l },
-      { 0x6d9bd094b0daddf5l,0xbea2357524ce55c0l,0x663356e672da03b5l,
-        0xf7ba4de9fed97474l },
-      0 },
-    /* 49 */
-    { { 0xd0dbfa34ebe1263fl,0x5576373571ae7ce6l,0xd244055382a6f523l,
-        0xe31f960052131c41l },
-      { 0xd1bb9216ea6b6ec6l,0x37a1d12e73c2fc44l,0xc10e7eac89d0a294l,
-        0xaa3a6259ce34d47bl },
-      0 },
-    /* 50 */
-    { { 0xfbcf9df536f3dcd3l,0x6ceded50d2bf7360l,0x491710fadf504f5bl,
-        0x2398dd627e79daeel },
-      { 0xcf4705a36d09569el,0xea0619bb5149f769l,0xff9c037735f6034cl,
-        0x5717f5b21c046210l },
-      0 },
-    /* 51 */
-    { { 0x9fe229c921dd895el,0x8e51850040c28451l,0xfa13d2391d637ecdl,
-        0x660a2c560e3c28del },
-      { 0x9cca88aed67fcbd0l,0xc84724780ea9f096l,0x32b2f48172e92b4dl,
-        0x624ee54c4f522453l },
-      0 },
-    /* 52 */
-    { { 0x09549ce4d897ecccl,0x4d49d1d93f9880aal,0x723c2423043a7c20l,
-        0x4f392afb92bdfbc0l },
-      { 0x6969f8fa7de44fd9l,0xb66cfbe457b32156l,0xdb2fa803368ebc3cl,
-        0x8a3e7977ccdb399cl },
-      0 },
-    /* 53 */
-    { { 0xdde1881f06c4b125l,0xae34e300f6e3ca8cl,0xef6999de5c7a13e9l,
-        0x3888d02370c24404l },
-      { 0x7628035644f91081l,0x3d9fcf615f015504l,0x1827edc8632cd36el,
-        0xa5e62e4718102336l },
-      0 },
-    /* 54 */
-    { { 0x1a825ee32facd6c8l,0x699c635454bcbc66l,0x0ce3edf798df9931l,
-        0x2c4768e6466a5adcl },
-      { 0xb346ff8c90a64bc9l,0x630a6020e4779f5cl,0xd949d064bc05e884l,
-        0x7b5e6441f9e652a0l },
-      0 },
-    /* 55 */
-    { { 0x2169422c1d28444al,0xe996c5d8be136a39l,0x2387afe5fb0c7fcel,
-        0xb8af73cb0c8d744al },
-      { 0x5fde83aa338b86fdl,0xfee3f158a58a5cffl,0xc9ee8f6f20ac9433l,
-        0xa036395f7f3f0895l },
-      0 },
-    /* 56 */
-    { { 0x8c73c6bba10f7770l,0xa6f16d81a12a0e24l,0x100df68251bc2b9fl,
-        0x4be36b01875fb533l },
-      { 0x9226086e9fb56dbbl,0x306fef8b07e7a4f8l,0xeeaccc0566d52f20l,
-        0x8cbc9a871bdc00c0l },
-      0 },
-    /* 57 */
-    { { 0xe131895cc0dac4abl,0xa874a440712ff112l,0x6332ae7c6a1cee57l,
-        0x44e7553e0c0835f8l },
-      { 0x6d503fff7734002dl,0x9d35cb8b0b34425cl,0x95f702760e8738b5l,
-        0x470a683a5eb8fc18l },
-      0 },
-    /* 58 */
-    { { 0x81b761dc90513482l,0x0287202a01e9276al,0xcda441ee0ce73083l,
-        0x16410690c63dc6efl },
-      { 0xf5034a066d06a2edl,0xdd4d7745189b100bl,0xd914ae72ab8218c9l,
-        0xd73479fd7abcbb4fl },
-      0 },
-    /* 59 */
-    { { 0x7edefb165ad4c6e5l,0x262cf08f5b06d04dl,0x12ed5bb18575cb14l,
-        0x816469e30771666bl },
-      { 0xd7ab9d79561e291el,0xeb9daf22c1de1661l,0xf49827eb135e0513l,
-        0x0a36dd23f0dd3f9cl },
-      0 },
-    /* 60 */
-    { { 0x098d32c741d5533cl,0x7c5f5a9e8684628fl,0x39a228ade349bd11l,
-        0xe331dfd6fdbab118l },
-      { 0x5100ab686bcc6ed8l,0x7160c3bdef7a260el,0x9063d9a7bce850d7l,
-        0xd3b4782a492e3389l },
-      0 },
-    /* 61 */
-    { { 0xa149b6e8f3821f90l,0x92edd9ed66eb7aadl,0x0bb669531a013116l,
-        0x7281275a4c86a5bdl },
-      { 0x503858f7d3ff47e5l,0x5e1616bc61016441l,0x62b0f11a7dfd9bb1l,
-        0x2c062e7ece145059l },
-      0 },
-    /* 62 */
-    { { 0xa76f996f0159ac2el,0x281e7736cbdb2713l,0x2ad6d28808e46047l,
-        0x282a35f92c4e7ef1l },
-      { 0x9c354b1ec0ce5cd2l,0xcf99efc91379c229l,0x992caf383e82c11el,
-        0xc71cd513554d2abdl },
-      0 },
-    /* 63 */
-    { { 0x4885de9c09b578f4l,0x1884e258e3affa7al,0x8f76b1b759182f1fl,
-        0xc50f6740cf47f3a3l },
-      { 0xa9c4adf3374b68eal,0xa406f32369965fe2l,0x2f86a22285a53050l,
-        0xb9ecb3a7212958dcl },
-      0 },
-    /* 64 */
-    { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l,
-        0x803f3e02cd42ab1bl },
-      { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl,
-        0xc097440e5067adc1l },
-      0 },
-    /* 65 */
-    { { 0x846a56f2c379ab34l,0xa8ee068b841df8d1l,0x20314459176c68efl,
-        0xf1af32d5915f1f30l },
-      { 0x99c375315d75bd50l,0x837cffbaf72f67bcl,0x0613a41848d7723fl,
-        0x23d0f130e2d41c8bl },
-      0 },
-    /* 66 */
-    { { 0x857ab6edf41500d9l,0x0d890ae5fcbeada8l,0x52fe864889725951l,
-        0xb0288dd6c0a3faddl },
-      { 0x85320f30650bcb08l,0x71af6313695d6e16l,0x31f520a7b989aa76l,
-        0xffd3724ff408c8d2l },
-      0 },
-    /* 67 */
-    { { 0x53968e64b458e6cbl,0x992dad20317a5d28l,0x3814ae0b7aa75f56l,
-        0xf5590f4ad78c26dfl },
-      { 0x0fc24bd3cf0ba55al,0x0fc4724a0c778bael,0x1ce9864f683b674al,
-        0x18d6da54f6f74a20l },
-      0 },
-    /* 68 */
-    { { 0xed93e225d5be5a2bl,0x6fe799835934f3c6l,0x4314092622626ffcl,
-        0x50bbb4d97990216al },
-      { 0x378191c6e57ec63el,0x65422c40181dcdb2l,0x41a8099b0236e0f6l,
-        0x2b10011801fe49c3l },
-      0 },
-    /* 69 */
-    { { 0xfc68b5c59b391593l,0xc385f5a2598270fcl,0x7144f3aad19adcbbl,
-        0xdd55899983fbae0cl },
-      { 0x93b88b8e74b82ff4l,0xd2e03c4071e734c9l,0x9a7a9eaf43c0322al,
-        0xe6e4c551149d6041l },
-      0 },
-    /* 70 */
-    { { 0x55f655bb1e9af288l,0x647e1a64f7ada931l,0x43697e4bcb2820e5l,
-        0x51e00db107ed56ffl },
-      { 0x43d169b8771c327el,0x29cdb20b4a96c2adl,0xc07d51f53deb4779l,
-        0xe22f424149829177l },
-      0 },
-    /* 71 */
-    { { 0xcd45e8f4635f1abbl,0x7edc0cb568538874l,0xc9472c1fb5a8034dl,
-        0xf709373d52dc48c9l },
-      { 0x401966bba8af30d6l,0x95bf5f4af137b69cl,0x3966162a9361c47el,
-        0xbd52d288e7275b11l },
-      0 },
-    /* 72 */
-    { { 0xab155c7a9c5fa877l,0x17dad6727d3a3d48l,0x43f43f9e73d189d8l,
-        0xa0d0f8e4c8aa77a6l },
-      { 0x0bbeafd8cc94f92dl,0xd818c8be0c4ddb3al,0x22cc65f8b82eba14l,
-        0xa56c78c7946d6a00l },
-      0 },
-    /* 73 */
-    { { 0x2962391b0dd09529l,0x803e0ea63daddfcfl,0x2c77351f5b5bf481l,
-        0xd8befdf8731a367al },
-      { 0xab919d42fc0157f4l,0xf51caed7fec8e650l,0xcdf9cb4002d48b0al,
-        0x854a68a5ce9f6478l },
-      0 },
-    /* 74 */
-    { { 0xdc35f67b63506ea5l,0x9286c489a4fe0d66l,0x3f101d3bfe95cd4dl,
-        0x5cacea0b98846a95l },
-      { 0xa90df60c9ceac44dl,0x3db29af4354d1c3al,0x08dd3de8ad5dbabel,
-        0xe4982d1235e4efa9l },
-      0 },
-    /* 75 */
-    { { 0x23104a22c34cd55el,0x58695bb32680d132l,0xfb345afa1fa1d943l,
-        0x8046b7f616b20499l },
-      { 0xb533581e38e7d098l,0xd7f61e8df46f0b70l,0x30dea9ea44cb78c4l,
-        0xeb17ca7b9082af55l },
-      0 },
-    /* 76 */
-    { { 0x1751b59876a145b9l,0xa5cf6b0fc1bc71ecl,0xd3e03565392715bbl,
-        0x097b00bafab5e131l },
-      { 0xaa66c8e9565f69e1l,0x77e8f75ab5be5199l,0x6033ba11da4fd984l,
-        0xf95c747bafdbcc9el },
-      0 },
-    /* 77 */
-    { { 0x558f01d3bebae45el,0xa8ebe9f0c4bc6955l,0xaeb705b1dbc64fc6l,
-        0x3512601e566ed837l },
-      { 0x9336f1e1fa1161cdl,0x328ab8d54c65ef87l,0x4757eee2724f21e5l,
-        0x0ef971236068ab6bl },
-      0 },
-    /* 78 */
-    { { 0x02598cf754ca4226l,0x5eede138f8642c8el,0x48963f74468e1790l,
-        0xfc16d9333b4fbc95l },
-      { 0xbe96fb31e7c800cal,0x138063312678adaal,0x3d6244976ff3e8b5l,
-        0x14ca4af1b95d7a17l },
-      0 },
-    /* 79 */
-    { { 0x7a4771babd2f81d5l,0x1a5f9d6901f7d196l,0xd898bef7cad9c907l,
-        0x4057b063f59c231dl },
-      { 0xbffd82fe89c05c0al,0xe4911c6f1dc0df85l,0x3befccaea35a16dbl,
-        0x1c3b5d64f1330b13l },
-      0 },
-    /* 80 */
-    { { 0x5fe14bfe80ec21fel,0xf6ce116ac255be82l,0x98bc5a072f4a5d67l,
-        0xfad27148db7e63afl },
-      { 0x90c0b6ac29ab05b3l,0x37a9a83c4e251ae6l,0x0a7dc875c2aade7dl,
-        0x77387de39f0e1a84l },
-      0 },
-    /* 81 */
-    { { 0x1e9ecc49a56c0dd7l,0xa5cffcd846086c74l,0x8f7a1408f505aecel,
-        0xb37b85c0bef0c47el },
-      { 0x3596b6e4cc0e6a8fl,0xfd6d4bbf6b388f23l,0xaba453fac39cef4el,
-        0x9c135ac8f9f628d5l },
-      0 },
-    /* 82 */
-    { { 0x32aa320284e35743l,0x320d6ab185a3cdefl,0xb821b1761df19819l,
-        0x5721361fc433851fl },
-      { 0x1f0db36a71fc9168l,0x5f98ba735e5c403cl,0xf64ca87e37bcd8f5l,
-        0xdcbac3c9e6bb11bdl },
-      0 },
-    /* 83 */
-    { { 0xf01d99684518cbe2l,0xd242fc189c9eb04el,0x727663c7e47feebfl,
-        0xb8c1c89e2d626862l },
-      { 0x51a58bddc8e1d569l,0x563809c8b7d88cd0l,0x26c27fd9f11f31ebl,
-        0x5d23bbda2f9422d4l },
-      0 },
-    /* 84 */
-    { { 0x0a1c729495c8f8bel,0x2961c4803bf362bfl,0x9e418403df63d4acl,
-        0xc109f9cb91ece900l },
-      { 0xc2d095d058945705l,0xb9083d96ddeb85c0l,0x84692b8d7a40449bl,
-        0x9bc3344f2eee1ee1l },
-      0 },
-    /* 85 */
-    { { 0x0d5ae35642913074l,0x55491b2748a542b1l,0x469ca665b310732al,
-        0x29591d525f1a4cc1l },
-      { 0xe76f5b6bb84f983fl,0xbe7eef419f5f84e1l,0x1200d49680baa189l,
-        0x6376551f18ef332cl },
-      0 },
-    /* 86 */
-    { { 0xbda5f14e562976ccl,0x22bca3e60ef12c38l,0xbbfa30646cca9852l,
-        0xbdb79dc808e2987al },
-      { 0xfd2cb5c9cb06a772l,0x38f475aafe536dcel,0xc2a3e0227c2b5db8l,
-        0x8ee86001add3c14al },
-      0 },
-    /* 87 */
-    { { 0xcbe96981a4ade873l,0x7ee9aa4dc4fba48cl,0x2cee28995a054ba5l,
-        0x92e51d7a6f77aa4bl },
-      { 0x948bafa87190a34dl,0xd698f75bf6bd1ed1l,0xd00ee6e30caf1144l,
-        0x5182f86f0a56aaaal },
-      0 },
-    /* 88 */
-    { { 0xfba6212c7a4cc99cl,0xff609b683e6d9ca1l,0x5dbb27cb5ac98c5al,
-        0x91dcab5d4073a6f2l },
-      { 0x01b6cc3d5f575a70l,0x0cb361396f8d87fal,0x165d4e8c89981736l,
-        0x17a0cedb97974f2bl },
-      0 },
-    /* 89 */
-    { { 0x38861e2a076c8d3al,0x701aad39210f924bl,0x94d0eae413a835d9l,
-        0x2e8ce36c7f4cdf41l },
-      { 0x91273dab037a862bl,0x01ba9bb760e4c8fal,0xf964538833baf2ddl,
-        0xf4ccc6cb34f668f3l },
-      0 },
-    /* 90 */
-    { { 0x44ef525cf1f79687l,0x7c59549592efa815l,0xe1231741a5c78d29l,
-        0xac0db4889a0df3c9l },
-      { 0x86bfc711df01747fl,0x592b9358ef17df13l,0xe5880e4f5ccb6bb5l,
-        0x95a64a6194c974a2l },
-      0 },
-    /* 91 */
-    { { 0x72c1efdac15a4c93l,0x40269b7382585141l,0x6a8dfb1c16cb0badl,
-        0x231e54ba29210677l },
-      { 0xa70df9178ae6d2dcl,0x4d6aa63f39112918l,0xf627726b5e5b7223l,
-        0xab0be032d8a731e1l },
-      0 },
-    /* 92 */
-    { { 0x097ad0e98d131f2dl,0x637f09e33b04f101l,0x1ac86196d5e9a748l,
-        0xf1bcc8802cf6a679l },
-      { 0x25c69140e8daacb4l,0x3c4e405560f65009l,0x591cc8fc477937a6l,
-        0x851694695aebb271l },
-      0 },
-    /* 93 */
-    { { 0xde35c143f1dcf593l,0x78202b29b018be3bl,0xe9cdadc29bdd9d3dl,
-        0x8f67d9d2daad55d8l },
-      { 0x841116567481ea5fl,0xe7d2dde9e34c590cl,0xffdd43f405053fa8l,
-        0xf84572b9c0728b5dl },
-      0 },
-    /* 94 */
-    { { 0x5e1a7a7197af71c9l,0xa14494447a736565l,0xa1b4ae070e1d5063l,
-        0xedee2710616b2c19l },
-      { 0xb2f034f511734121l,0x1cac6e554a25e9f0l,0x8dc148f3a40c2ecfl,
-        0x9fd27e9b44ebd7f4l },
-      0 },
-    /* 95 */
-    { { 0x3cc7658af6e2cb16l,0xe3eb7d2cfe5919b6l,0x5a8c5816168d5583l,
-        0xa40c2fb6958ff387l },
-      { 0x8c9ec560fedcc158l,0x7ad804c655f23056l,0xd93967049a307e12l,
-        0x99bc9bb87dc6decfl },
-      0 },
-    /* 96 */
-    { { 0x84a9521d927dafc6l,0x52c1fb695c09cd19l,0x9d9581a0f9366ddel,
-        0x9abe210ba16d7e64l },
-      { 0x480af84a48915220l,0xfa73176a4dd816c6l,0xc7d539871681ca5al,
-        0x7881c25787f344b0l },
-      0 },
-    /* 97 */
-    { { 0x93399b51e0bcf3ffl,0x0d02cbc5127f74f6l,0x8fb465a2dd01d968l,
-        0x15e6e319a30e8940l },
-      { 0x646d6e0d3e0e05f4l,0xfad7bddc43588404l,0xbe61c7d1c4f850d3l,
-        0x0e55facf191172cel },
-      0 },
-    /* 98 */
-    { { 0x7e9d9806f8787564l,0x1a33172131e85ce6l,0x6b0158cab819e8d6l,
-        0xd73d09766fe96577l },
-      { 0x424834251eb7206el,0xa519290fc618bb42l,0x5dcbb8595e30a520l,
-        0x9250a3748f15a50bl },
-      0 },
-    /* 99 */
-    { { 0xcaff08f8be577410l,0xfd408a035077a8c6l,0xf1f63289ec0a63a4l,
-        0x77414082c1cc8c0bl },
-      { 0x05a40fa6eb0991cdl,0xc1ca086649fdc296l,0x3a68a3c7b324fd40l,
-        0x8cb04f4d12eb20b9l },
-      0 },
-    /* 100 */
-    { { 0xb1c2d0556906171cl,0x9073e9cdb0240c3fl,0xdb8e6b4fd8906841l,
-        0xe4e429ef47123b51l },
-      { 0x0b8dd53c38ec36f4l,0xf9d2dc01ff4b6a27l,0x5d066e07879a9a48l,
-        0x37bca2ff3c6e6552l },
-      0 },
-    /* 101 */
-    { { 0x4cd2e3c7df562470l,0x44f272a2c0964ac9l,0x7c6d5df980c793bel,
-        0x59913edc3002b22al },
-      { 0x7a139a835750592al,0x99e01d80e783de02l,0xcf8c0375ea05d64fl,
-        0x43786e4ab013e226l },
-      0 },
-    /* 102 */
-    { { 0xff32b0ed9e56b5a6l,0x0750d9a6d9fc68f9l,0xec15e845597846a7l,
-        0x8638ca98b7e79e7al },
-      { 0x2f5ae0960afc24b2l,0x05398eaf4dace8f2l,0x3b765dd0aecba78fl,
-        0x1ecdd36a7b3aa6f0l },
-      0 },
-    /* 103 */
-    { { 0x5d3acd626c5ff2f3l,0xa2d516c02873a978l,0xad94c9fad2110d54l,
-        0xd85d0f85d459f32dl },
-      { 0x9f700b8d10b11da3l,0xd2c22c30a78318c4l,0x556988f49208decdl,
-        0xa04f19c3b4ed3c62l },
-      0 },
-    /* 104 */
-    { { 0x087924c8ed7f93bdl,0xcb64ac5d392f51f6l,0x7cae330a821b71afl,
-        0x92b2eeea5c0950b0l },
-      { 0x85ac4c9485b6e235l,0xab2ca4a92936c0f0l,0x80faa6b3e0508891l,
-        0x1ee782215834276cl },
-      0 },
-    /* 105 */
-    { { 0xa60a2e00e63e79f7l,0xf590e7b2f399d906l,0x9021054a6607c09dl,
-        0xf3f2ced857a6e150l },
-      { 0x200510f3f10d9b55l,0x9d2fcfacd8642648l,0xe5631aa7e8bd0e7cl,
-        0x0f56a4543da3e210l },
-      0 },
-    /* 106 */
-    { { 0x5b21bffa1043e0dfl,0x6c74b6cc9c007e6dl,0x1a656ec0d4a8517al,
-        0xbd8f17411969e263l },
-      { 0x8a9bbb86beb7494al,0x1567d46f45f3b838l,0xdf7a12a7a4e5a79al,
-        0x2d1a1c3530ccfa09l },
-      0 },
-    /* 107 */
-    { { 0x192e3813506508dal,0x336180c4a1d795a7l,0xcddb59497a9944b3l,
-        0xa107a65eb91fba46l },
-      { 0xe6d1d1c50f94d639l,0x8b4af3758a58b7d7l,0x1a7c5584bd37ca1cl,
-        0x183d760af87a9af2l },
-      0 },
-    /* 108 */
-    { { 0x29d697110dde59a4l,0xf1ad8d070e8bef87l,0x229b49634f2ebe78l,
-        0x1d44179dc269d754l },
-      { 0xb32dc0cf8390d30el,0x0a3b27530de8110cl,0x31af1dc52bc0339al,
-        0x771f9cc29606d262l },
-      0 },
-    /* 109 */
-    { { 0x99993e7785040739l,0x44539db98026a939l,0xcf40f6f2f5f8fc26l,
-        0x64427a310362718el },
-      { 0x4f4f2d8785428aa8l,0x7b7adc3febfb49a8l,0x201b2c6df23d01acl,
-        0x49d9b7496ae90d6dl },
-      0 },
-    /* 110 */
-    { { 0xcc78d8bc435d1099l,0x2adbcd4e8e8d1a08l,0x02c2e2a02cb68a41l,
-        0x9037d81b3f605445l },
-      { 0x7cdbac27074c7b61l,0xfe2031ab57bfd72el,0x61ccec96596d5352l,
-        0x08c3de6a7cc0639cl },
-      0 },
-    /* 111 */
-    { { 0x20fdd020f6d552abl,0x56baff9805cd81f1l,0x06fb7c3e91351291l,
-        0xc690944245796b2fl },
-      { 0x17b3ae9c41231bd1l,0x1eac6e875cc58205l,0x208837abf9d6a122l,
-        0x3fa3db02cafe3ac0l },
-      0 },
-    /* 112 */
-    { { 0xd75a3e6505058880l,0x7da365ef643943f2l,0x4147861cfab24925l,
-        0xc5c4bdb0fdb808ffl },
-      { 0x73513e34b272b56bl,0xc8327e9511b9043al,0xfd8ce37df8844969l,
-        0x2d56db9446c2b6b5l },
-      0 },
-    /* 113 */
-    { { 0x2461782fff46ac6bl,0xd19f792607a2e425l,0xfafea3c409a48de1l,
-        0x0f56bd9de503ba42l },
-      { 0x137d4ed1345cda49l,0x821158fc816f299dl,0xe7c6a54aaeb43402l,
-        0x4003bb9d1173b5f1l },
-      0 },
-    /* 114 */
-    { { 0x3b8e8189a0803387l,0xece115f539cbd404l,0x4297208dd2877f21l,
-        0x53765522a07f2f9el },
-      { 0xa4980a21a8a4182dl,0xa2bbd07a3219df79l,0x674d0a2e1a19a2d4l,
-        0x7a056f586c5d4549l },
-      0 },
-    /* 115 */
-    { { 0x646b25589d8a2a47l,0x5b582948c3df2773l,0x51ec000eabf0d539l,
-        0x77d482f17a1a2675l },
-      { 0xb8a1bd9587853948l,0xa6f817bd6cfbffeel,0xab6ec05780681e47l,
-        0x4115012b2b38b0e4l },
-      0 },
-    /* 116 */
-    { { 0x3c73f0f46de28cedl,0x1d5da7609b13ec47l,0x61b8ce9e6e5c6392l,
-        0xcdf04572fbea0946l },
-      { 0x1cb3c58b6c53c3b0l,0x97fe3c10447b843cl,0xfb2b8ae12cb9780el,
-        0xee703dda97383109l },
-      0 },
-    /* 117 */
-    { { 0x34515140ff57e43al,0xd44660d3b1b811b8l,0x2b3b5dff8f42b986l,
-        0x2a0ad89da162ce21l },
-      { 0x64e4a6946bc277bal,0xc788c954c141c276l,0x141aa64ccabf6274l,
-        0xd62d0b67ac2b4659l },
-      0 },
-    /* 118 */
-    { { 0x39c5d87b2c054ac4l,0x57005859f27df788l,0xedf7cbf3b18128d6l,
-        0xb39a23f2991c2426l },
-      { 0x95284a15f0b16ae5l,0x0c6a05b1a136f51bl,0x1d63c137f2700783l,
-        0x04ed0092c0674cc5l },
-      0 },
-    /* 119 */
-    { { 0x1f4185d19ae90393l,0x3047b4294a3d64e6l,0xae0001a69854fc14l,
-        0xa0a91fc10177c387l },
-      { 0xff0a3f01ae2c831el,0xbb76ae822b727e16l,0x8f12c8a15a3075b4l,
-        0x084cf9889ed20c41l },
-      0 },
-    /* 120 */
-    { { 0xd98509defca6becfl,0x2fceae807dffb328l,0x5d8a15c44778e8b9l,
-        0xd57955b273abf77el },
-      { 0x210da79e31b5d4f1l,0xaa52f04b3cfa7a1cl,0xd4d12089dc27c20bl,
-        0x8e14ea4202d141f1l },
-      0 },
-    /* 121 */
-    { { 0xeed50345f2897042l,0x8d05331f43402c4al,0xc8d9c194c8bdfb21l,
-        0x597e1a372aa4d158l },
-      { 0x0327ec1acf0bd68cl,0x6d4be0dcab024945l,0x5b9c8d7ac9fe3e84l,
-        0xca3f0236199b4deal },
-      0 },
-    /* 122 */
-    { { 0x592a10b56170bd20l,0x0ea897f16d3f5de7l,0xa3363ff144b2ade2l,
-        0xbde7fd7e309c07e4l },
-      { 0x516bb6d2b8f5432cl,0x210dc1cbe043444bl,0x3db01e6ff8f95b5al,
-        0xb623ad0e0a7dd198l },
-      0 },
-    /* 123 */
-    { { 0xa75bd67560c7b65bl,0xab8c559023a4a289l,0xf8220fd0d7b26795l,
-        0xd6aa2e4658ec137bl },
-      { 0x10abc00b5138bb85l,0x8c31d121d833a95cl,0xb24ff00b1702a32el,
-        0x111662e02dcc513al },
-      0 },
-    /* 124 */
-    { { 0x78114015efb42b87l,0xbd9f5d701b6c4dffl,0x66ecccd7a7d7c129l,
-        0xdb3ee1cb94b750f8l },
-      { 0xb26f3db0f34837cfl,0xe7eed18bb9578d4fl,0x5d2cdf937c56657dl,
-        0x886a644252206a59l },
-      0 },
-    /* 125 */
-    { { 0x3c234cfb65b569eal,0x20011141f72119c1l,0x8badc85da15a619el,
-        0xa70cf4eb018a17bcl },
-      { 0x224f97ae8c4a6a65l,0x36e5cf270134378fl,0xbe3a609e4f7e0960l,
-        0xaa4772abd1747b77l },
-      0 },
-    /* 126 */
-    { { 0x676761317aa60cc0l,0xc79163610368115fl,0xded98bb4bbc1bb5al,
-        0x611a6ddc30faf974l },
-      { 0x30e78cbcc15ee47al,0x2e8962824e0d96a5l,0x36f35adf3dd9ed88l,
-        0x5cfffaf816429c88l },
-      0 },
-    /* 127 */
-    { { 0xc0d54cff9b7a99cdl,0x7bf3b99d843c45a1l,0x038a908f62c739e1l,
-        0x6e5a6b237dc1994cl },
-      { 0xef8b454e0ba5db77l,0xb7b8807facf60d63l,0xe591c0c676608378l,
-        0x481a238d242dabccl },
-      0 },
-    /* 128 */
-    { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l,
-        0x2c41114ce0cdf943l },
-      { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l,
-        0x20477abf42ff9297l },
-      0 },
-    /* 129 */
-    { { 0x2f75173c18d65dbfl,0x77bf940e339edad8l,0x7022d26bdcf1001cl,
-        0xac66409ac77396b6l },
-      { 0x8b0bb36fc6261cc3l,0x213f7bc9190e7e90l,0x6541cebaa45e6c10l,
-        0xce8e6975cc122f85l },
-      0 },
-    /* 130 */
-    { { 0x0f121b41bc0a67d2l,0x62d4760a444d248al,0x0e044f1d659b4737l,
-        0x08fde365250bb4a8l },
-      { 0xaceec3da848bf287l,0xc2a62182d3369d6el,0x3582dfdc92449482l,
-        0x2f7e2fd2565d6cd7l },
-      0 },
-    /* 131 */
-    { { 0xae4b92dbc3770fa7l,0x095e8d5c379043f9l,0x54f34e9d17761171l,
-        0xc65be92e907702ael },
-      { 0x2758a303f6fd0a40l,0xe7d822e3bcce784bl,0x7ae4f5854f9767bfl,
-        0x4bff8e47d1193b3al },
-      0 },
-    /* 132 */
-    { { 0xcd41d21f00ff1480l,0x2ab8fb7d0754db16l,0xac81d2efbbe0f3eal,
-        0x3e4e4ae65772967dl },
-      { 0x7e18f36d3c5303e6l,0x3bd9994b92262397l,0x9ed70e261324c3c0l,
-        0x5388aefd58ec6028l },
-      0 },
-    /* 133 */
-    { { 0xad1317eb5e5d7713l,0x09b985ee75de49dal,0x32f5bc4fc74fb261l,
-        0x5cf908d14f75be0el },
-      { 0x760435108e657b12l,0xbfd421a5b96ed9e6l,0x0e29f51f8970ccc2l,
-        0xa698ba4060f00ce2l },
-      0 },
-    /* 134 */
-    { { 0x73db1686ef748fecl,0xe6e755a27e9d2cf9l,0x630b6544ce265effl,
-        0xb142ef8a7aebad8dl },
-      { 0xad31af9f17d5770al,0x66af3b672cb3412fl,0x6bd60d1bdf3359del,
-        0xd1896a9658515075l },
-      0 },
-    /* 135 */
-    { { 0xec5957ab33c41c08l,0x87de94ac5468e2e1l,0x18816b73ac472f6cl,
-        0x267b0e0b7981da39l },
-      { 0x6e554e5d8e62b988l,0xd8ddc755116d21e7l,0x4610faf03d2a6f99l,
-        0xb54e287aa1119393l },
-      0 },
-    /* 136 */
-    { { 0x0a0122b5178a876bl,0x51ff96ff085104b4l,0x050b31ab14f29f76l,
-        0x84abb28b5f87d4e6l },
-      { 0xd5ed439f8270790al,0x2d6cb59d85e3f46bl,0x75f55c1b6c1e2212l,
-        0xe5436f6717655640l },
-      0 },
-    /* 137 */
-    { { 0x53f9025e2286e8d5l,0x353c95b4864453bel,0xd832f5bde408e3a0l,
-        0x0404f68b5b9ce99el },
-      { 0xcad33bdea781e8e5l,0x3cdf5018163c2f5bl,0x575769600119caa3l,
-        0x3a4263df0ac1c701l },
-      0 },
-    /* 138 */
-    { { 0xc2965ecc9aeb596dl,0x01ea03e7023c92b4l,0x4704b4b62e013961l,
-        0x0ca8fd3f905ea367l },
-      { 0x92523a42551b2b61l,0x1eb7a89c390fcd06l,0xe7f1d2be0392a63el,
-        0x96dca2644ddb0c33l },
-      0 },
-    /* 139 */
-    { { 0x203bb43a387510afl,0x846feaa8a9a36a01l,0xd23a57702f950378l,
-        0x4363e2123aad59dcl },
-      { 0xca43a1c740246a47l,0xb362b8d2e55dd24dl,0xf9b086045d8faf96l,
-        0x840e115cd8bb98c4l },
-      0 },
-    /* 140 */
-    { { 0xf12205e21023e8a7l,0xc808a8cdd8dc7a0bl,0xe292a272163a5ddfl,
-        0x5e0d6abd30ded6d4l },
-      { 0x07a721c27cfc0f64l,0x42eec01d0e55ed88l,0x26a7bef91d1f9db2l,
-        0x7dea48f42945a25al },
-      0 },
-    /* 141 */
-    { { 0xabdf6f1ce5060a81l,0xe79f9c72f8f95615l,0xcfd36c5406ac268bl,
-        0xabc2a2beebfd16d1l },
-      { 0x8ac66f91d3e2eac7l,0x6f10ba63d2dd0466l,0x6790e3770282d31bl,
-        0x4ea353946c7eefc1l },
-      0 },
-    /* 142 */
-    { { 0xed8a2f8d5266309dl,0x0a51c6c081945a3el,0xcecaf45a578c5dc1l,
-        0x3a76e6891c94ffc3l },
-      { 0x9aace8a47d7b0d0fl,0x963ace968f584a5fl,0x51a30c724e697fbel,
-        0x8212a10a465e6464l },
-      0 },
-    /* 143 */
-    { { 0xef7c61c3cfab8caal,0x18eb8e840e142390l,0xcd1dff677e9733cal,
-        0xaa7cab71599cb164l },
-      { 0x02fc9273bc837bd1l,0xc06407d0c36af5d7l,0x17621292f423da49l,
-        0x40e38073fe0617c3l },
-      0 },
-    /* 144 */
-    { { 0xf4f80824a7bf9b7cl,0x365d23203fbe30d0l,0xbfbe532097cf9ce3l,
-        0xe3604700b3055526l },
-      { 0x4dcb99116cc6c2c7l,0x72683708ba4cbee6l,0xdcded434637ad9ecl,
-        0x6542d677a3dee15fl },
-      0 },
-    /* 145 */
-    { { 0x3f32b6d07b6c377al,0x6cb03847903448bel,0xd6fdd3a820da8af7l,
-        0xa6534aee09bb6f21l },
-      { 0x30a1780d1035facfl,0x35e55a339dcb47e6l,0x6ea50fe1c447f393l,
-        0xf3cb672fdc9aef22l },
-      0 },
-    /* 146 */
-    { { 0xeb3719fe3b55fd83l,0xe0d7a46c875ddd10l,0x33ac9fa905cea784l,
-        0x7cafaa2eaae870e7l },
-      { 0x9b814d041d53b338l,0xe0acc0a0ef87e6c6l,0xfb93d10811672b0fl,
-        0x0aab13c1b9bd522el },
-      0 },
-    /* 147 */
-    { { 0xddcce278d2681297l,0xcb350eb1b509546al,0x2dc431737661aaf2l,
-        0x4b91a602847012e9l },
-      { 0xdcff109572f8ddcfl,0x08ebf61e9a911af4l,0x48f4360ac372430el,
-        0x49534c5372321cabl },
-      0 },
-    /* 148 */
-    { { 0x83df7d71f07b7e9dl,0xa478efa313cd516fl,0x78ef264b6c047ee3l,
-        0xcaf46c4fd65ac5eel },
-      { 0xa04d0c7792aa8266l,0xedf45466913684bbl,0x56e65168ae4b16b0l,
-        0x14ce9e5704c6770fl },
-      0 },
-    /* 149 */
-    { { 0x99445e3e965e8f91l,0xd3aca1bacb0f2492l,0xd31cc70f90c8a0a0l,
-        0x1bb708a53e4c9a71l },
-      { 0xd5ca9e69558bdd7al,0x734a0508018a26b1l,0xb093aa714c9cf1ecl,
-        0xf9d126f2da300102l },
-      0 },
-    /* 150 */
-    { { 0x749bca7aaff9563el,0xdd077afeb49914a0l,0xe27a0311bf5f1671l,
-        0x807afcb9729ecc69l },
-      { 0x7f8a9337c9b08b77l,0x86c3a785443c7e38l,0x85fafa59476fd8bal,
-        0x751adcd16568cd8cl },
-      0 },
-    /* 151 */
-    { { 0x8aea38b410715c0dl,0xd113ea718f7697f7l,0x665eab1493fbf06dl,
-        0x29ec44682537743fl },
-      { 0x3d94719cb50bebbcl,0x399ee5bfe4505422l,0x90cd5b3a8d2dedb1l,
-        0xff9370e392a4077dl },
-      0 },
-    /* 152 */
-    { { 0x59a2d69bc6b75b65l,0x4188f8d5266651c5l,0x28a9f33e3de9d7d2l,
-        0x9776478ba2a9d01al },
-      { 0x8852622d929af2c7l,0x334f5d6d4e690923l,0xce6cc7e5a89a51e9l,
-        0x74a6313fac2f82fal },
-      0 },
-    /* 153 */
-    { { 0xb2f4dfddb75f079cl,0x85b07c9518e36fbbl,0x1b6cfcf0e7cd36ddl,
-        0xab75be150ff4863dl },
-      { 0x81b367c0173fc9b7l,0xb90a7420d2594fd0l,0x15fdbf03c4091236l,
-        0x4ebeac2e0b4459f6l },
-      0 },
-    /* 154 */
-    { { 0xeb6c5fe75c9f2c53l,0xd25220118eae9411l,0xc8887633f95ac5d8l,
-        0xdf99887b2c1baffcl },
-      { 0xbb78eed2850aaecbl,0x9d49181b01d6a272l,0x978dd511b1cdbcacl,
-        0x27b040a7779f4058l },
-      0 },
-    /* 155 */
-    { { 0x90405db7f73b2eb2l,0xe0df85088e1b2118l,0x501b71525962327el,
-        0xb393dd37e4cfa3f5l },
-      { 0xa1230e7b3fd75165l,0xd66344c2bcd33554l,0x6c36f1be0f7b5022l,
-        0x09588c12d0463419l },
-      0 },
-    /* 156 */
-    { { 0xe086093f02601c3bl,0xfb0252f8cf5c335fl,0x955cf280894aff28l,
-        0x81c879a9db9f648bl },
-      { 0x040e687cc6f56c51l,0xfed471693f17618cl,0x44f88a419059353bl,
-        0xfa0d48f55fc11bc4l },
-      0 },
-    /* 157 */
-    { { 0xbc6e1c9de1608e4dl,0x010dda113582822cl,0xf6b7ddc1157ec2d7l,
-        0x8ea0e156b6a367d6l },
-      { 0xa354e02f2383b3b4l,0x69966b943f01f53cl,0x4ff6632b2de03ca5l,
-        0x3f5ab924fa00b5acl },
-      0 },
-    /* 158 */
-    { { 0x337bb0d959739efbl,0xc751b0f4e7ebec0dl,0x2da52dd6411a67d1l,
-        0x8bc768872b74256el },
-      { 0xa5be3b7282d3d253l,0xa9f679a1f58d779fl,0xa1cac168e16767bbl,
-        0xb386f19060fcf34fl },
-      0 },
-    /* 159 */
-    { { 0x31f3c1352fedcfc2l,0x5396bf6262f8af0dl,0x9a02b4eae57288c2l,
-        0x4cb460f71b069c4dl },
-      { 0xae67b4d35b8095eal,0x92bbf8596fc07603l,0xe1475f66b614a165l,
-        0x52c0d50895ef5223l },
-      0 },
-    /* 160 */
-    { { 0x231c210e15339848l,0xe87a28e870778c8dl,0x9d1de6616956e170l,
-        0x4ac3c9382bb09c0bl },
-      { 0x19be05516998987dl,0x8b2376c4ae09f4d6l,0x1de0b7651a3f933dl,
-        0x380d94c7e39705f4l },
-      0 },
-    /* 161 */
-    { { 0x01a355aa81542e75l,0x96c724a1ee01b9b7l,0x6b3a2977624d7087l,
-        0x2ce3e171de2637afl },
-      { 0xcfefeb49f5d5bc1al,0xa655607e2777e2b5l,0x4feaac2f9513756cl,
-        0x2e6cd8520b624e4dl },
-      0 },
-    /* 162 */
-    { { 0x3685954b8c31c31dl,0x68533d005bf21a0cl,0x0bd7626e75c79ec9l,
-        0xca17754742c69d54l },
-      { 0xcc6edafff6d2dbb2l,0xfd0d8cbd174a9d18l,0x875e8793aa4578e8l,
-        0xa976a7139cab2ce6l },
-      0 },
-    /* 163 */
-    { { 0x0a651f1b93fb353dl,0xd75cab8b57fcfa72l,0xaa88cfa731b15281l,
-        0x8720a7170a1f4999l },
-      { 0x8c3e8d37693e1b90l,0xd345dc0b16f6dfc3l,0x8ea8d00ab52a8742l,
-        0x9719ef29c769893cl },
-      0 },
-    /* 164 */
-    { { 0x820eed8d58e35909l,0x9366d8dc33ddc116l,0xd7f999d06e205026l,
-        0xa5072976e15704c1l },
-      { 0x002a37eac4e70b2el,0x84dcf6576890aa8al,0xcd71bf18645b2a5cl,
-        0x99389c9df7b77725l },
-      0 },
-    /* 165 */
-    { { 0x238c08f27ada7a4bl,0x3abe9d03fd389366l,0x6b672e89766f512cl,
-        0xa88806aa202c82e4l },
-      { 0x6602044ad380184el,0xa8cb78c4126a8b85l,0x79d670c0ad844f17l,
-        0x0043bffb4738dcfel },
-      0 },
-    /* 166 */
-    { { 0x8d59b5dc36d5192el,0xacf885d34590b2afl,0x83566d0a11601781l,
-        0x52f3ef01ba6c4866l },
-      { 0x3986732a0edcb64dl,0x0a482c238068379fl,0x16cbe5fa7040f309l,
-        0x3296bd899ef27e75l },
-      0 },
-    /* 167 */
-    { { 0x476aba89454d81d7l,0x9eade7ef51eb9b3cl,0x619a21cd81c57986l,
-        0x3b90febfaee571e9l },
-      { 0x9393023e5496f7cbl,0x55be41d87fb51bc4l,0x03f1dd4899beb5cel,
-        0x6e88069d9f810b18l },
-      0 },
-    /* 168 */
-    { { 0xce37ab11b43ea1dbl,0x0a7ff1a95259d292l,0x851b02218f84f186l,
-        0xa7222beadefaad13l },
-      { 0xa2ac78ec2b0a9144l,0x5a024051f2fa59c5l,0x91d1eca56147ce38l,
-        0xbe94d523bc2ac690l },
-      0 },
-    /* 169 */
-    { { 0x72f4945e0b226ce7l,0xb8afd747967e8b70l,0xedea46f185a6c63el,
-        0x7782defe9be8c766l },
-      { 0x760d2aa43db38626l,0x460ae78776f67ad1l,0x341b86fc54499cdbl,
-        0x03838567a2892e4bl },
-      0 },
-    /* 170 */
-    { { 0x2d8daefd79ec1a0fl,0x3bbcd6fdceb39c97l,0xf5575ffc58f61a95l,
-        0xdbd986c4adf7b420l },
-      { 0x81aa881415f39eb7l,0x6ee2fcf5b98d976cl,0x5465475dcf2f717dl,
-        0x8e24d3c46860bbd0l },
-      0 },
-    /* 171 */
-    { { 0x749d8e549a587390l,0x12bb194f0cbec588l,0x46e07da4b25983c6l,
-        0x541a99c4407bafc8l },
-      { 0xdb241692624c8842l,0x6044c12ad86c05ffl,0xc59d14b44f7fcf62l,
-        0xc0092c49f57d35d1l },
-      0 },
-    /* 172 */
-    { { 0xd3cc75c3df2e61efl,0x7e8841c82e1b35cal,0xc62d30d1909f29f4l,
-        0x75e406347286944dl },
-      { 0xe7d41fc5bbc237d0l,0xc9537bf0ec4f01c9l,0x91c51a16282bd534l,
-        0x5b7cb658c7848586l },
-      0 },
-    /* 173 */
-    { { 0x964a70848a28ead1l,0x802dc508fd3b47f6l,0x9ae4bfd1767e5b39l,
-        0x7ae13eba8df097a1l },
-      { 0xfd216ef8eadd384el,0x0361a2d9b6b2ff06l,0x204b98784bcdb5f3l,
-        0x787d8074e2a8e3fdl },
-      0 },
-    /* 174 */
-    { { 0xc5e25d6b757fbb1cl,0xe47bddb2ca201debl,0x4a55e9a36d2233ffl,
-        0x5c2228199ef28484l },
-      { 0x773d4a8588315250l,0x21b21a2b827097c1l,0xab7c4ea1def5d33fl,
-        0xe45d37abbaf0f2b0l },
-      0 },
-    /* 175 */
-    { { 0xd2df1e3428511c8al,0xebb229c8bdca6cd3l,0x578a71a7627c39a7l,
-        0xed7bc12284dfb9d3l },
-      { 0xcf22a6df93dea561l,0x5443f18dd48f0ed1l,0xd8b861405bad23e8l,
-        0xaac97cc945ca6d27l },
-      0 },
-    /* 176 */
-    { { 0xeb54ea74a16bd00al,0xd839e9adf5c0bcc1l,0x092bb7f11f9bfc06l,
-        0x318f97b31163dc4el },
-      { 0xecc0c5bec30d7138l,0x44e8df23abc30220l,0x2bb7972fb0223606l,
-        0xfa41faa19a84ff4dl },
-      0 },
-    /* 177 */
-    { { 0x4402d974a6642269l,0xc81814ce9bb783bdl,0x398d38e47941e60bl,
-        0x38bb6b2c1d26e9e2l },
-      { 0xc64e4a256a577f87l,0x8b52d253dc11fe1cl,0xff336abf62280728l,
-        0x94dd0905ce7601a5l },
-      0 },
-    /* 178 */
-    { { 0x156cf7dcde93f92al,0xa01333cb89b5f315l,0x02404df9c995e750l,
-        0x92077867d25c2ae9l },
-      { 0xe2471e010bf39d44l,0x5f2c902096bb53d7l,0x4c44b7b35c9c3d8fl,
-        0x81e8428bd29beb51l },
-      0 },
-    /* 179 */
-    { { 0x6dd9c2bac477199fl,0x8cb8eeee6b5ecdd9l,0x8af7db3fee40fd0el,
-        0x1b94ab62dbbfa4b1l },
-      { 0x44f0d8b3ce47f143l,0x51e623fc63f46163l,0xf18f270fcc599383l,
-        0x06a38e28055590eel },
-      0 },
-    /* 180 */
-    { { 0x2e5b0139b3355b49l,0x20e26560b4ebf99bl,0xc08ffa6bd269f3dcl,
-        0xa7b36c2083d9d4f8l },
-      { 0x64d15c3a1b3e8830l,0xd5fceae1a89f9c0bl,0xcfeee4a2e2d16930l,
-        0xbe54c6b4a2822a20l },
-      0 },
-    /* 181 */
-    { { 0xd6cdb3df8d91167cl,0x517c3f79e7a6625el,0x7105648f346ac7f4l,
-        0xbf30a5abeae022bbl },
-      { 0x8e7785be93828a68l,0x5161c3327f3ef036l,0xe11b5feb592146b2l,
-        0xd1c820de2732d13al },
-      0 },
-    /* 182 */
-    { { 0x043e13479038b363l,0x58c11f546b05e519l,0x4fe57abe6026cad1l,
-        0xb7d17bed68a18da3l },
-      { 0x44ca5891e29c2559l,0x4f7a03765bfffd84l,0x498de4af74e46948l,
-        0x3997fd5e6412cc64l },
-      0 },
-    /* 183 */
-    { { 0xf20746828bd61507l,0x29e132d534a64d2al,0xffeddfb08a8a15e3l,
-        0x0eeb89293c6c13e8l },
-      { 0xe9b69a3ea7e259f8l,0xce1db7e6d13e7e67l,0x277318f6ad1fa685l,
-        0x228916f8c922b6efl },
-      0 },
-    /* 184 */
-    { { 0x959ae25b0a12ab5bl,0xcc11171f957bc136l,0x8058429ed16e2b0cl,
-        0xec05ad1d6e93097el },
-      { 0x157ba5beac3f3708l,0x31baf93530b59d77l,0x47b55237118234e5l,
-        0x7d3141567ff11b37l },
-      0 },
-    /* 185 */
-    { { 0x7bd9c05cf6dfefabl,0xbe2f2268dcb37707l,0xe53ead973a38bb95l,
-        0xe9ce66fc9bc1d7a3l },
-      { 0x75aa15766f6a02a1l,0x38c087df60e600edl,0xf8947f3468cdc1b9l,
-        0xd9650b0172280651l },
-      0 },
-    /* 186 */
-    { { 0x504b4c4a5a057e60l,0xcbccc3be8def25e4l,0xa635320817c1ccbdl,
-        0x14d6699a804eb7a2l },
-      { 0x2c8a8415db1f411al,0x09fbaf0bf80d769cl,0xb4deef901c2f77adl,
-        0x6f4c68410d43598al },
-      0 },
-    /* 187 */
-    { { 0x8726df4e96c24a96l,0x534dbc85fcbd99a3l,0x3c466ef28b2ae30al,
-        0x4c4350fd61189abbl },
-      { 0x2967f716f855b8dal,0x41a42394463c38a1l,0xc37e1413eae93343l,
-        0xa726d2425a3118b5l },
-      0 },
-    /* 188 */
-    { { 0xdae6b3ee948c1086l,0xf1de503dcbd3a2e1l,0x3f35ed3f03d022f3l,
-        0x13639e82cc6cf392l },
-      { 0x9ac938fbcdafaa86l,0xf45bc5fb2654a258l,0x1963b26e45051329l,
-        0xca9365e1c1a335a3l },
-      0 },
-    /* 189 */
-    { { 0x3615ac754c3b2d20l,0x742a5417904e241bl,0xb08521c4cc9d071dl,
-        0x9ce29c34970b72a5l },
-      { 0x8cc81f736d3e0ad6l,0x8060da9ef2f8434cl,0x35ed1d1a6ce862d9l,
-        0x48c4abd7ab42af98l },
-      0 },
-    /* 190 */
-    { { 0xd221b0cc40c7485al,0xead455bbe5274dbfl,0x493c76989263d2e8l,
-        0x78017c32f67b33cbl },
-      { 0xb9d35769930cb5eel,0xc0d14e940c408ed2l,0xf8b7bf55272f1a4dl,
-        0x53cd0454de5c1c04l },
-      0 },
-    /* 191 */
-    { { 0xbcd585fa5d28ccacl,0x5f823e56005b746el,0x7c79f0a1cd0123aal,
-        0xeea465c1d3d7fa8fl },
-      { 0x7810659f0551803bl,0x6c0b599f7ce6af70l,0x4195a77029288e70l,
-        0x1b6e42a47ae69193l },
-      0 },
-    /* 192 */
-    { { 0x2e80937cf67d04c3l,0x1e312be289eeb811l,0x56b5d88792594d60l,
-        0x0224da14187fbd3dl },
-      { 0x87abb8630c5fe36fl,0x580f3c604ef51f5fl,0x964fb1bfb3b429ecl,
-        0x60838ef042bfff33l },
-      0 },
-    /* 193 */
-    { { 0x432cb2f27e0bbe99l,0x7bda44f304aa39eel,0x5f497c7a9fa93903l,
-        0x636eb2022d331643l },
-      { 0xfcfd0e6193ae00aal,0x875a00fe31ae6d2fl,0xf43658a29f93901cl,
-        0x8844eeb639218bacl },
-      0 },
-    /* 194 */
-    { { 0x114171d26b3bae58l,0x7db3df7117e39f3el,0xcd37bc7f81a8eadal,
-        0x27ba83dc51fb789el },
-      { 0xa7df439ffbf54de5l,0x7277030bb5fe1a71l,0x42ee8e35db297a48l,
-        0xadb62d3487f3a4abl },
-      0 },
-    /* 195 */
-    { { 0x9b1168a2a175df2al,0x082aa04f618c32e9l,0xc9e4f2e7146b0916l,
-        0xb990fd7675e7c8b2l },
-      { 0x0829d96b4df37313l,0x1c205579d0b40789l,0x66c9ae4a78087711l,
-        0x81707ef94d10d18dl },
-      0 },
-    /* 196 */
-    { { 0x97d7cab203d6ff96l,0x5b851bfc0d843360l,0x268823c4d042db4bl,
-        0x3792daead5a8aa5cl },
-      { 0x52818865941afa0bl,0xf3e9e74142d83671l,0x17c825275be4e0a7l,
-        0x5abd635e94b001bal },
-      0 },
-    /* 197 */
-    { { 0x727fa84e0ac4927cl,0xe3886035a7c8cf23l,0xa4bcd5ea4adca0dfl,
-        0x5995bf21846ab610l },
-      { 0xe90f860b829dfa33l,0xcaafe2ae958fc18bl,0x9b3baf4478630366l,
-        0x44c32ca2d483411el },
-      0 },
-    /* 198 */
-    { { 0xa74a97f1e40ed80cl,0x5f938cb131d2ca82l,0x53f2124b7c2d6ad9l,
-        0x1f2162fb8082a54cl },
-      { 0x7e467cc5720b173el,0x40e8a666085f12f9l,0x8cebc20e4c9d65dcl,
-        0x8f1d402bc3e907c9l },
-      0 },
-    /* 199 */
-    { { 0x4f592f9cfbc4058al,0xb15e14b6292f5670l,0xc55cfe37bc1d8c57l,
-        0xb1980f43926edbf9l },
-      { 0x98c33e0932c76b09l,0x1df5279d33b07f78l,0x6f08ead4863bb461l,
-        0x2828ad9b37448e45l },
-      0 },
-    /* 200 */
-    { { 0x696722c4c4cf4ac5l,0xf5ac1a3fdde64afbl,0x0551baa2e0890832l,
-        0x4973f1275a14b390l },
-      { 0xe59d8335322eac5dl,0x5e07eef50bd9b568l,0xab36720fa2588393l,
-        0x6dac8ed0db168ac7l },
-      0 },
-    /* 201 */
-    { { 0xf7b545aeeda835efl,0x4aa113d21d10ed51l,0x035a65e013741b09l,
-        0x4b23ef5920b9de4cl },
-      { 0xe82bb6803c4c7341l,0xd457706d3f58bc37l,0x73527863a51e3ee8l,
-        0x4dd71534ddf49a4el },
-      0 },
-    /* 202 */
-    { { 0xbf94467295476cd9l,0x648d072fe31a725bl,0x1441c8b8fc4b67e0l,
-        0xfd3170002f4a4dbbl },
-      { 0x1cb43ff48995d0e1l,0x76e695d10ef729aal,0xe0d5f97641798982l,
-        0x14fac58c9569f365l },
-      0 },
-    /* 203 */
-    { { 0xad9a0065f312ae18l,0x51958dc0fcc93fc9l,0xd9a142408a7d2846l,
-        0xed7c765136abda50l },
-      { 0x46270f1a25d4abbcl,0x9b5dd8f3f1a113eal,0xc609b0755b51952fl,
-        0xfefcb7f74d2e9f53l },
-      0 },
-    /* 204 */
-    { { 0xbd09497aba119185l,0xd54e8c30aac45ba4l,0x492479deaa521179l,
-        0x1801a57e87e0d80bl },
-      { 0x073d3f8dfcafffb0l,0x6cf33c0bae255240l,0x781d763b5b5fdfbcl,
-        0x9f8fc11e1ead1064l },
-      0 },
-    /* 205 */
-    { { 0x1583a1715e69544cl,0x0eaf8567f04b7813l,0x1e22a8fd278a4c32l,
-        0xa9d3809d3d3a69a9l },
-      { 0x936c2c2c59a2da3bl,0x38ccbcf61895c847l,0x5e65244e63d50869l,
-        0x3006b9aee1178ef7l },
-      0 },
-    /* 206 */
-    { { 0x0bb1f2b0c9eead28l,0x7eef635d89f4dfbcl,0x074757fdb2ce8939l,
-        0x0ab85fd745f8f761l },
-      { 0xecda7c933e5b4549l,0x4be2bb5c97922f21l,0x261a1274b43b8040l,
-        0xb122d67511e942c2l },
-      0 },
-    /* 207 */
-    { { 0x3be607be66a5ae7al,0x01e703fa76adcbe3l,0xaf9043014eb6e5c5l,
-        0x9f599dc1097dbaecl },
-      { 0x6d75b7180ff250edl,0x8eb91574349a20dcl,0x425605a410b227a3l,
-        0x7d5528e08a294b78l },
-      0 },
-    /* 208 */
-    { { 0xf0f58f6620c26defl,0x025585ea582b2d1el,0xfbe7d79b01ce3881l,
-        0x28ccea01303f1730l },
-      { 0xd1dabcd179644ba5l,0x1fc643e806fff0b8l,0xa60a76fc66b3e17bl,
-        0xc18baf48a1d013bfl },
-      0 },
-    /* 209 */
-    { { 0x34e638c85dc4216dl,0x00c01067206142acl,0xd453a17195f5064al,
-        0x9def809db7a9596bl },
-      { 0x41e8642e67ab8d2cl,0xb42404336237a2b6l,0x7d506a6d64c4218bl,
-        0x0357f8b068808ce5l },
-      0 },
-    /* 210 */
-    { { 0x8e9dbe644cd2cc88l,0xcc61c28df0b8f39dl,0x4a309874cd30a0c8l,
-        0xe4a01add1b489887l },
-      { 0x2ed1eeacf57cd8f9l,0x1b767d3ebd594c48l,0xa7295c717bd2f787l,
-        0x466d7d79ce10cc30l },
-      0 },
-    /* 211 */
-    { { 0x47d318929dada2c7l,0x4fa0a6c38f9aa27dl,0x90e4fd28820a59e1l,
-        0xc672a522451ead1al },
-      { 0x30607cc85d86b655l,0xf0235d3bf9ad4af1l,0x99a08680571172a6l,
-        0x5e3d64faf2a67513l },
-      0 },
-    /* 212 */
-    { { 0xaa6410c79b3b4416l,0xcd8fcf85eab26d99l,0x5ebff74adb656a74l,
-        0x6c8a7a95eb8e42fcl },
-      { 0x10c60ba7b02a63bdl,0x6b2f23038b8f0047l,0x8c6c3738312d90b0l,
-        0x348ae422ad82ca91l },
-      0 },
-    /* 213 */
-    { { 0x7f4746635ccda2fbl,0x22accaa18e0726d2l,0x85adf782492b1f20l,
-        0xc1074de0d9ef2d2el },
-      { 0xfcf3ce44ae9a65b3l,0xfd71e4ac05d7151bl,0xd4711f50ce6a9788l,
-        0xfbadfbdbc9e54ffcl },
-      0 },
-    /* 214 */
-    { { 0x1713f1cd20a99363l,0xb915658f6cf22775l,0x968175cd24d359b2l,
-        0xb7f976b483716fcdl },
-      { 0x5758e24d5d6dbf74l,0x8d23bafd71c3af36l,0x48f477600243dfe3l,
-        0xf4d41b2ecafcc805l },
-      0 },
-    /* 215 */
-    { { 0x51f1cf28fdabd48dl,0xce81be3632c078a4l,0x6ace2974117146e9l,
-        0x180824eae0160f10l },
-      { 0x0387698b66e58358l,0x63568752ce6ca358l,0x82380e345e41e6c5l,
-        0x67e5f63983cf6d25l },
-      0 },
-    /* 216 */
-    { { 0xf89ccb8dcf4899efl,0x949015f09ebb44c0l,0x546f9276b2598ec9l,
-        0x9fef789a04c11fc6l },
-      { 0x6d367ecf53d2a071l,0xb10e1a7fa4519b09l,0xca6b3fb0611e2eefl,
-        0xbc80c181a99c4e20l },
-      0 },
-    /* 217 */
-    { { 0x972536f8e5eb82e6l,0x1a484fc7f56cb920l,0xc78e217150b5da5el,
-        0x49270e629f8cdf10l },
-      { 0x1a39b7bbea6b50adl,0x9a0284c1a2388ffcl,0x5403eb178107197bl,
-        0xd2ee52f961372f7fl },
-      0 },
-    /* 218 */
-    { { 0xd37cd28588e0362al,0x442fa8a78fa5d94dl,0xaff836e5a434a526l,
-        0xdfb478bee5abb733l },
-      { 0xa91f1ce7673eede6l,0xa5390ad42b5b2f04l,0x5e66f7bf5530da2fl,
-        0xd9a140b408df473al },
-      0 },
-    /* 219 */
-    { { 0x0e0221b56e8ea498l,0x623478293563ee09l,0xe06b8391335d2adel,
-        0x760c058d623f4b1al },
-      { 0x0b89b58cc198aa79l,0xf74890d2f07aba7fl,0x4e204110fde2556al,
-        0x7141982d8f190409l },
-      0 },
-    /* 220 */
-    { { 0x6f0a0e334d4b0f45l,0xd9280b38392a94e1l,0x3af324c6b3c61d5el,
-        0x3af9d1ce89d54e47l },
-      { 0xfd8f798120930371l,0xeda2664c21c17097l,0x0e9545dcdc42309bl,
-        0xb1f815c373957dd6l },
-      0 },
-    /* 221 */
-    { { 0x84faa78e89fec44al,0xc8c2ae473caa4cafl,0x691c807dc1b6a624l,
-        0xa41aed141543f052l },
-      { 0x424353997d5ffe04l,0x8bacb2df625b6e20l,0x85d660be87817775l,
-        0xd6e9c1dd86fb60efl },
-      0 },
-    /* 222 */
-    { { 0x3aa2e97ec6853264l,0x771533b7e2304a0bl,0x1b912bb7b8eae9bel,
-        0x9c9c6e10ae9bf8c2l },
-      { 0xa2309a59e030b74cl,0x4ed7494d6a631e90l,0x89f44b23a49b79f2l,
-        0x566bd59640fa61b6l },
-      0 },
-    /* 223 */
-    { { 0x066c0118c18061f3l,0x190b25d37c83fc70l,0xf05fc8e027273245l,
-        0xcf2c7390f525345el },
-      { 0xa09bceb410eb30cfl,0xcfd2ebba0d77703al,0xe842c43a150ff255l,
-        0x02f517558aa20979l },
-      0 },
-    /* 224 */
-    { { 0x396ef794addb7d07l,0x0b4fc74224455500l,0xfaff8eacc78aa3cel,
-        0x14e9ada5e8d4d97dl },
-      { 0xdaa480a12f7079e2l,0x45baa3cde4b0800el,0x01765e2d7838157dl,
-        0xa0ad4fab8e9d9ae8l },
-      0 },
-    /* 225 */
-    { { 0x0bfb76214a653618l,0x1872813c31eaaa5fl,0x1553e73744949d5el,
-        0xbcd530b86e56ed1el },
-      { 0x169be85332e9c47bl,0xdc2776feb50059abl,0xcdba9761192bfbb4l,
-        0x909283cf6979341dl },
-      0 },
-    /* 226 */
-    { { 0x67b0032476e81a13l,0x9bee1a9962171239l,0x08ed361bd32e19d6l,
-        0x35eeb7c9ace1549al },
-      { 0x1280ae5a7e4e5bdcl,0x2dcd2cd3b6ceec6el,0x52e4224c6e266bc1l,
-        0x9a8b2cf4448ae864l },
-      0 },
-    /* 227 */
-    { { 0xf6471bf209d03b59l,0xc90e62a3b65af2abl,0xff7ff168ebd5eec9l,
-        0x6bdb60f4d4491379l },
-      { 0xdadafebc8a55bc30l,0xc79ead1610097fe0l,0x42e197414c1e3bddl,
-        0x01ec3cfd94ba08a9l },
-      0 },
-    /* 228 */
-    { { 0xba6277ebdc9485c2l,0x48cc9a7922fb10c7l,0x4f61d60f70a28d8al,
-        0xd1acb1c0475464f6l },
-      { 0xd26902b126f36612l,0x59c3a44ee0618d8bl,0x4df8a813308357eel,
-        0x7dcd079d405626c2l },
-      0 },
-    /* 229 */
-    { { 0x5ce7d4d3f05a4b48l,0xadcd295237230772l,0xd18f7971812a915al,
-        0x0bf53589377d19b8l },
-      { 0x35ecd95a6c68ea73l,0xc7f3bbca823a584dl,0x9fb674c6f473a723l,
-        0xd28be4d9e16686fcl },
-      0 },
-    /* 230 */
-    { { 0x5d2b990638fa8e4bl,0x559f186e893fd8fcl,0x3a6de2aa436fb6fcl,
-        0xd76007aa510f88cel },
-      { 0x2d10aab6523a4988l,0xb455cf4474dd0273l,0x7f467082a3407278l,
-        0xf2b52f68b303bb01l },
-      0 },
-    /* 231 */
-    { { 0x0d57eafa9835b4cal,0x2d2232fcbb669cbcl,0x8eeeb680c6643198l,
-        0xd8dbe98ecc5aed3al },
-      { 0xcba9be3fc5a02709l,0x30be68e5f5ba1fa8l,0xfebd43cdf10ea852l,
-        0xe01593a3ee559705l },
-      0 },
-    /* 232 */
-    { { 0xd3e5af50ea75a0a6l,0x512226ac57858033l,0x6fe6d50fd0176406l,
-        0xafec07b1aeb8ef06l },
-      { 0x7fb9956780bb0a31l,0x6f1af3cc37309aael,0x9153a15a01abf389l,
-        0xa71b93546e2dbfddl },
-      0 },
-    /* 233 */
-    { { 0xbf8e12e018f593d2l,0xd1a90428a078122bl,0x150505db0ba4f2adl,
-        0x53a2005c628523d9l },
-      { 0x07c8b639e7f2b935l,0x2bff975ac182961al,0x86bceea77518ca2cl,
-        0xbf47d19b3d588e3dl },
-      0 },
-    /* 234 */
-    { { 0x672967a7dd7665d5l,0x4e3030572f2f4de5l,0x144005ae80d4903fl,
-        0x001c2c7f39c9a1b6l },
-      { 0x143a801469efc6d6l,0xc810bdaa7bc7a724l,0x5f65670ba78150a4l,
-        0xfdadf8e786ffb99bl },
-      0 },
-    /* 235 */
-    { { 0xfd38cb88ffc00785l,0x77fa75913b48eb67l,0x0454d055bf368fbcl,
-        0x3a838e4d5aa43c94l },
-      { 0x561663293e97bb9al,0x9eb93363441d94d9l,0x515591a60adb2a83l,
-        0x3cdb8257873e1da3l },
-      0 },
-    /* 236 */
-    { { 0x137140a97de77eabl,0xf7e1c50d41648109l,0x762dcad2ceb1d0dfl,
-        0x5a60cc89f1f57fbal },
-      { 0x80b3638240d45673l,0x1b82be195913c655l,0x057284b8dd64b741l,
-        0x922ff56fdbfd8fc0l },
-      0 },
-    /* 237 */
-    { { 0x1b265deec9a129a1l,0xa5b1ce57cc284e04l,0x04380c46cebfbe3cl,
-        0x72919a7df6c5cd62l },
-      { 0x298f453a8fb90f9al,0xd719c00b88e4031bl,0xe32c0e77796f1856l,
-        0x5e7917803624089al },
-      0 },
-    /* 238 */
-    { { 0x5c16ec557f63cdfbl,0x8e6a3571f1cae4fdl,0xfce26bea560597cal,
-        0x4e0a5371e24c2fabl },
-      { 0x276a40d3a5765357l,0x3c89af440d73a2b4l,0xb8f370ae41d11a32l,
-        0xf5ff7818d56604eel },
-      0 },
-    /* 239 */
-    { { 0xfbf3e3fe1a09df21l,0x26d5d28ee66e8e47l,0x2096bd0a29c89015l,
-        0xe41df0e9533f5e64l },
-      { 0x305fda40b3ba9e3fl,0xf2340ceb2604d895l,0x0866e1927f0367c7l,
-        0x8edd7d6eac4f155fl },
-      0 },
-    /* 240 */
-    { { 0xc9a1dc0e0bfc8ff3l,0x14efd82be936f42fl,0x67016f7ccca381efl,
-        0x1432c1caed8aee96l },
-      { 0xec68482970b23c26l,0xa64fe8730735b273l,0xe389f6e5eaef0f5al,
-        0xcaef480b5ac8d2c6l },
-      0 },
-    /* 241 */
-    { { 0x5245c97875315922l,0xd82951713063cca5l,0xf3ce60d0b64ef2cbl,
-        0xd0ba177e8efae236l },
-      { 0x53a9ae8fb1b3af60l,0x1a796ae53d2da20el,0x01d63605df9eef28l,
-        0xf31c957c1c54ae16l },
-      0 },
-    /* 242 */
-    { { 0xc0f58d5249cc4597l,0xdc5015b0bae0a028l,0xefc5fc55734a814al,
-        0x013404cb96e17c3al },
-      { 0xb29e2585c9a824bfl,0xd593185e001eaed7l,0x8d6ee68261ef68acl,
-        0x6f377c4b91933e6cl },
-      0 },
-    /* 243 */
-    { { 0x9f93bad1a8333fd2l,0xa89302025a2a95b8l,0x211e5037eaf75acel,
-        0x6dba3e4ed2d09506l },
-      { 0xa48ef98cd04399cdl,0x1811c66ee6b73adel,0x72f60752c17ecaf3l,
-        0xf13cf3423becf4a7l },
-      0 },
-    /* 244 */
-    { { 0xceeb9ec0a919e2ebl,0x83a9a195f62c0f68l,0xcfba3bb67aba2299l,
-        0xc83fa9a9274bbad3l },
-      { 0x0d7d1b0b62fa1ce0l,0xe58b60f53418efbfl,0xbfa8ef9e52706f04l,
-        0xb49d70f45d702683l },
-      0 },
-    /* 245 */
-    { { 0x914c7510fad5513bl,0x05f32eecb1751e2dl,0x6d850418d9fb9d59l,
-        0x59cfadbb0c30f1cfl },
-      { 0xe167ac2355cb7fd6l,0x249367b8820426a3l,0xeaeec58c90a78864l,
-        0x5babf362354a4b67l },
-      0 },
-    /* 246 */
-    { { 0x37c981d1ee424865l,0x8b002878f2e5577fl,0x702970f1b9e0c058l,
-        0x6188c6a79026c8f0l },
-      { 0x06f9a19bd0f244dal,0x1ecced5cfb080873l,0x35470f9b9f213637l,
-        0x993fe475df50b9d9l },
-      0 },
-    /* 247 */
-    { { 0x68e31cdf9b2c3609l,0x84eb19c02c46d4eal,0x7ac9ec1a9a775101l,
-        0x81f764664c80616bl },
-      { 0x1d7c2a5a75fbe978l,0x6743fed3f183b356l,0x838d1f04501dd2bfl,
-        0x564a812a5fe9060dl },
-      0 },
-    /* 248 */
-    { { 0x7a5a64f4fa817d1dl,0x55f96844bea82e0fl,0xb5ff5a0fcd57f9aal,
-        0x226bf3cf00e51d6cl },
-      { 0xd6d1a9f92f2833cfl,0x20a0a35a4f4f89a8l,0x11536c498f3f7f77l,
-        0x68779f47ff257836l },
-      0 },
-    /* 249 */
-    { { 0x79b0c1c173043d08l,0xa54467741fc020fal,0xd3767e289a6d26d0l,
-        0x97bcb0d1eb092e0bl },
-      { 0x2ab6eaa8f32ed3c3l,0xc8a4f151b281bc48l,0x4d1bf4f3bfa178f3l,
-        0xa872ffe80a784655l },
-      0 },
-    /* 250 */
-    { { 0xb1ab7935a32b2086l,0xe1eb710e8160f486l,0x9bd0cd913b6ae6bel,
-        0x02812bfcb732a36al },
-      { 0xa63fd7cacf605318l,0x646e5d50fdfd6d1dl,0xa1d683982102d619l,
-        0x07391cc9fe5396afl },
-      0 },
-    /* 251 */
-    { { 0xc50157f08b80d02bl,0x6b8333d162877f7fl,0x7aca1af878d542ael,
-        0x355d2adc7e6d2a08l },
-      { 0xb41f335a287386e1l,0xfd272a94f8e43275l,0x286ca2cde79989eal,
-        0x3dc2b1e37c2a3a79l },
-      0 },
-    /* 252 */
-    { { 0xd689d21c04581352l,0x0a00c825376782bel,0x203bd5909fed701fl,
-        0xc47869103ccd846bl },
-      { 0x5dba770824c768edl,0x72feea026841f657l,0x73313ed56accce0el,
-        0xccc42968d5bb4d32l },
-      0 },
-    /* 253 */
-    { { 0x94e50de13d7620b9l,0xd89a5c8a5992a56al,0xdc007640675487c9l,
-        0xe147eb42aa4871cfl },
-      { 0x274ab4eeacf3ae46l,0xfd4936fb50350fbel,0xdf2afe4748c840eal,
-        0x239ac047080e96e3l },
-      0 },
-    /* 254 */
-    { { 0x481d1f352bfee8d4l,0xce80b5cffa7b0fecl,0x105c4c9e2ce9af3cl,
-        0xc55fa1a3f5f7e59dl },
-      { 0x3186f14e8257c227l,0xc5b1653f342be00bl,0x09afc998aa904fb2l,
-        0x094cd99cd4f4b699l },
-      0 },
-    /* 255 */
-    { { 0x8a981c84d703bebal,0x8631d15032ceb291l,0xa445f2c9e3bd49ecl,
-        0xb90a30b642abad33l },
-      { 0xb465404fb4a5abf9l,0x004750c375db7603l,0x6f9a42ccca35d89fl,
-        0x019f8b9a1b7924f7l },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#else
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_sum {
-    sp_digit x[4];
-    sp_digit y[4];
-    byte infinity;
-} sp_table_entry_sum;
-
-/* Table of pre-computed values for P256 with 3 multiples and width of 8 bits.
- */
-static sp_table_entry_sum p256_table[33][58] = {
-    {
-        /* 0 << 0 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 0 */
-        { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l,
-            0x18905f76a53755c6l },
-          { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l,
-            0x8571ff1825885d85l },
-          0 },
-        /* 3 << 0 */
-        { { 0xffac3f904eebc127l,0xb027f84a087d81fbl,0x66ad77dd87cbbc98l,
-            0x26936a3fb6ff747el },
-          { 0xb04c5c1fc983a7ebl,0x583e47ad0861fe1al,0x788208311a2ee98el,
-            0xd5f06a29e587cc07l },
-          0 },
-        /* 4 << 0 */
-        { { 0x74b0b50d46918dccl,0x4650a6edc623c173l,0x0cdaacace8100af2l,
-            0x577362f541b0176bl },
-          { 0x2d96f24ce4cbaba6l,0x17628471fad6f447l,0x6b6c36dee5ddd22el,
-            0x84b14c394c5ab863l },
-          0 },
-        /* 5 << 0 */
-        { { 0xbe1b8aaec45c61f5l,0x90ec649a94b9537dl,0x941cb5aad076c20cl,
-            0xc9079605890523c8l },
-          { 0xeb309b4ae7ba4f10l,0x73c568efe5eb882bl,0x3540a9877e7a1f68l,
-            0x73a076bb2dd1e916l },
-          0 },
-        /* 7 << 0 */
-        { { 0x0746354ea0173b4fl,0x2bd20213d23c00f7l,0xf43eaab50c23bb08l,
-            0x13ba5119c3123e03l },
-          { 0x2847d0303f5b9d4dl,0x6742f2f25da67bddl,0xef933bdc77c94195l,
-            0xeaedd9156e240867l },
-          0 },
-        /* 9 << 0 */
-        { { 0x75c96e8f264e20e8l,0xabe6bfed59a7a841l,0x2cc09c0444c8eb00l,
-            0xe05b3080f0c4e16bl },
-          { 0x1eb7777aa45f3314l,0x56af7bedce5d45e3l,0x2b6e019a88b12f1al,
-            0x086659cdfd835f9bl },
-          0 },
-        /* 10 << 0 */
-        { { 0x2c18dbd19dc21ec8l,0x98f9868a0fcf8139l,0x737d2cd648250b49l,
-            0xcc61c94724b3428fl },
-          { 0x0c2b407880dd9e76l,0xc43a8991383fbe08l,0x5f7d2d65779be5d2l,
-            0x78719a54eb3b4ab5l },
-          0 },
-        /* 11 << 0 */
-        { { 0xea7d260a6245e404l,0x9de407956e7fdfe0l,0x1ff3a4158dac1ab5l,
-            0x3e7090f1649c9073l },
-          { 0x1a7685612b944e88l,0x250f939ee57f61c8l,0x0c0daa891ead643dl,
-            0x68930023e125b88el },
-          0 },
-        /* 13 << 0 */
-        { { 0xccc425634b2ed709l,0x0e356769856fd30dl,0xbcbcd43f559e9811l,
-            0x738477ac5395b759l },
-          { 0x35752b90c00ee17fl,0x68748390742ed2e3l,0x7cd06422bd1f5bc1l,
-            0xfbc08769c9e7b797l },
-          0 },
-        /* 15 << 0 */
-        { { 0x72bcd8b7bc60055bl,0x03cc23ee56e27e4bl,0xee337424e4819370l,
-            0xe2aa0e430ad3da09l },
-          { 0x40b8524f6383c45dl,0xd766355442a41b25l,0x64efa6de778a4797l,
-            0x2042170a7079adf4l },
-          0 },
-        /* 16 << 0 */
-        { { 0x808b0b650bc6fb80l,0x5882e0753ffe2e6bl,0xd5ef2f7c2c83f549l,
-            0x54d63c809103b723l },
-          { 0xf2f11bd652a23f9bl,0x3670c3194b0b6587l,0x55c4623bb1580e9el,
-            0x64edf7b201efe220l },
-          0 },
-        /* 17 << 0 */
-        { { 0x97091dcbd53c5c9dl,0xf17624b6ac0a177bl,0xb0f139752cfe2dffl,
-            0xc1a35c0a6c7a574el },
-          { 0x227d314693e79987l,0x0575bf30e89cb80el,0x2f4e247f0d1883bbl,
-            0xebd512263274c3d0l },
-          0 },
-        /* 19 << 0 */
-        { { 0xfea912baa5659ae8l,0x68363aba25e1a16el,0xb8842277752c41acl,
-            0xfe545c282897c3fcl },
-          { 0x2d36e9e7dc4c696bl,0x5806244afba977c5l,0x85665e9be39508c1l,
-            0xf720ee256d12597bl },
-          0 },
-        /* 21 << 0 */
-        { { 0x562e4cecc135b208l,0x74e1b2654783f47dl,0x6d2a506c5a3f3b30l,
-            0xecead9f4c16762fcl },
-          { 0xf29dd4b2e286e5b9l,0x1b0fadc083bb3c61l,0x7a75023e7fac29a4l,
-            0xc086d5f1c9477fa3l },
-          0 },
-        /* 23 << 0 */
-        { { 0xf4f876532de45068l,0x37c7a7e89e2e1f6el,0xd0825fa2a3584069l,
-            0xaf2cea7c1727bf42l },
-          { 0x0360a4fb9e4785a9l,0xe5fda49c27299f4al,0x48068e1371ac2f71l,
-            0x83d0687b9077666fl },
-          0 },
-        /* 25 << 0 */
-        { { 0xa4a319acd837879fl,0x6fc1b49eed6b67b0l,0xe395993332f1f3afl,
-            0x966742eb65432a2el },
-          { 0x4b8dc9feb4966228l,0x96cc631243f43950l,0x12068859c9b731eel,
-            0x7b948dc356f79968l },
-          0 },
-        /* 27 << 0 */
-        { { 0x042c2af497e2feb4l,0xd36a42d7aebf7313l,0x49d2c9eb084ffdd7l,
-            0x9f8aa54b2ef7c76al },
-          { 0x9200b7ba09895e70l,0x3bd0c66fddb7fb58l,0x2d97d10878eb4cbbl,
-            0x2d431068d84bde31l },
-          0 },
-        /* 28 << 0 */
-        { { 0x4b523eb7172ccd1fl,0x7323cb2830a6a892l,0x97082ec0cfe153ebl,
-            0xe97f6b6af2aadb97l },
-          { 0x1d3d393ed1a83da1l,0xa6a7f9c7804b2a68l,0x4a688b482d0cb71el,
-            0xa9b4cc5f40585278l },
-          0 },
-        /* 29 << 0 */
-        { { 0x5e5db46acb66e132l,0xf1be963a0d925880l,0x944a70270317b9e2l,
-            0xe266f95948603d48l },
-          { 0x98db66735c208899l,0x90472447a2fb18a3l,0x8a966939777c619fl,
-            0x3798142a2a3be21bl },
-          0 },
-        /* 31 << 0 */
-        { { 0xe2f73c696755ff89l,0xdd3cf7e7473017e6l,0x8ef5689d3cf7600dl,
-            0x948dc4f8b1fc87b4l },
-          { 0xd9e9fe814ea53299l,0x2d921ca298eb6028l,0xfaecedfd0c9803fcl,
-            0xf38ae8914d7b4745l },
-          0 },
-        /* 33 << 0 */
-        { { 0x871514560f664534l,0x85ceae7c4b68f103l,0xac09c4ae65578ab9l,
-            0x33ec6868f044b10cl },
-          { 0x6ac4832b3a8ec1f1l,0x5509d1285847d5efl,0xf909604f763f1574l,
-            0xb16c4303c32f63c4l },
-          0 },
-        /* 34 << 0 */
-        { { 0xb6ab20147ca23cd3l,0xcaa7a5c6a391849dl,0x5b0673a375678d94l,
-            0xc982ddd4dd303e64l },
-          { 0xfd7b000b5db6f971l,0xbba2cb1f6f876f92l,0xc77332a33c569426l,
-            0xa159100c570d74f8l },
-          0 },
-        /* 35 << 0 */
-        { { 0xfd16847fdec67ef5l,0x742ee464233e76b7l,0x0b8e4134efc2b4c8l,
-            0xca640b8642a3e521l },
-          { 0x653a01908ceb6aa9l,0x313c300c547852d5l,0x24e4ab126b237af7l,
-            0x2ba901628bb47af8l },
-          0 },
-        /* 36 << 0 */
-        { { 0x3d5e58d6a8219bb7l,0xc691d0bd1b06c57fl,0x0ae4cb10d257576el,
-            0x3569656cd54a3dc3l },
-          { 0xe5ebaebd94cda03al,0x934e82d3162bfe13l,0x450ac0bae251a0c6l,
-            0x480b9e11dd6da526l },
-          0 },
-        /* 37 << 0 */
-        { { 0x00467bc58cce08b5l,0xb636458c7f178d55l,0xc5748baea677d806l,
-            0x2763a387dfa394ebl },
-          { 0xa12b448a7d3cebb6l,0xe7adda3e6f20d850l,0xf63ebce51558462cl,
-            0x58b36143620088a8l },
-          0 },
-        /* 39 << 0 */
-        { { 0xa9d89488a059c142l,0x6f5ae714ff0b9346l,0x068f237d16fb3664l,
-            0x5853e4c4363186acl },
-          { 0xe2d87d2363c52f98l,0x2ec4a76681828876l,0x47b864fae14e7b1cl,
-            0x0c0bc0e569192408l },
-          0 },
-        /* 40 << 0 */
-        { { 0xe4d7681db82e9f3el,0x83200f0bdf25e13cl,0x8909984c66f27280l,
-            0x462d7b0075f73227l },
-          { 0xd90ba188f2651798l,0x74c6e18c36ab1c34l,0xab256ea35ef54359l,
-            0x03466612d1aa702fl },
-          0 },
-        /* 41 << 0 */
-        { { 0x624d60492ed22e91l,0x6fdfe0b56f072822l,0xeeca111539ce2271l,
-            0x98100a4fdb01614fl },
-          { 0xb6b0daa2a35c628fl,0xb6f94d2ec87e9a47l,0xc67732591d57d9cel,
-            0xf70bfeec03884a7bl },
-          0 },
-        /* 43 << 0 */
-        { { 0x4ff23ffd248a7d06l,0x80c5bfb4878873fal,0xb7d9ad9005745981l,
-            0x179c85db3db01994l },
-          { 0xba41b06261a6966cl,0x4d82d052eadce5a8l,0x9e91cd3ba5e6a318l,
-            0x47795f4f95b2dda0l },
-          0 },
-        /* 44 << 0 */
-        { { 0xecfd7c1fd55a897cl,0x009194abb29110fbl,0x5f0e2046e381d3b0l,
-            0x5f3425f6a98dd291l },
-          { 0xbfa06687730d50dal,0x0423446c4b083b7fl,0x397a247dd69d3417l,
-            0xeb629f90387ba42al },
-          0 },
-        /* 45 << 0 */
-        { { 0x1ee426ccd5cd79bfl,0x0032940b946c6e18l,0x1b1e8ae057477f58l,
-            0xe94f7d346d823278l },
-          { 0xc747cb96782ba21al,0xc5254469f72b33a5l,0x772ef6dec7f80c81l,
-            0xd73acbfe2cd9e6b5l },
-          0 },
-        /* 46 << 0 */
-        { { 0x4075b5b149ee90d9l,0x785c339aa06e9ebal,0xa1030d5babf825e0l,
-            0xcec684c3a42931dcl },
-          { 0x42ab62c9c1586e63l,0x45431d665ab43f2bl,0x57c8b2c055f7835dl,
-            0x033da338c1b7f865l },
-          0 },
-        /* 47 << 0 */
-        { { 0x283c7513caa76097l,0x0a624fa936c83906l,0x6b20afec715af2c7l,
-            0x4b969974eba78bfdl },
-          { 0x220755ccd921d60el,0x9b944e107baeca13l,0x04819d515ded93d4l,
-            0x9bbff86e6dddfd27l },
-          0 },
-        /* 48 << 0 */
-        { { 0x6b34413077adc612l,0xa7496529bbd803a0l,0x1a1baaa76d8805bdl,
-            0xc8403902470343adl },
-          { 0x39f59f66175adff1l,0x0b26d7fbb7d8c5b7l,0xa875f5ce529d75e3l,
-            0x85efc7e941325cc2l },
-          0 },
-        /* 49 << 0 */
-        { { 0x21950b421ff6acd3l,0xffe7048453dc6909l,0xff4cd0b228766127l,
-            0xabdbe6084fb7db2bl },
-          { 0x837c92285e1109e8l,0x26147d27f4645b5al,0x4d78f592f7818ed8l,
-            0xd394077ef247fa36l },
-          0 },
-        /* 51 << 0 */
-        { { 0x508cec1c3b3f64c9l,0xe20bc0ba1e5edf3fl,0xda1deb852f4318d4l,
-            0xd20ebe0d5c3fa443l },
-          { 0x370b4ea773241ea3l,0x61f1511c5e1a5f65l,0x99a5e23d82681c62l,
-            0xd731e383a2f54c2dl },
-          0 },
-        /* 52 << 0 */
-        { { 0x2692f36e83445904l,0x2e0ec469af45f9c0l,0x905a3201c67528b7l,
-            0x88f77f34d0e5e542l },
-          { 0xf67a8d295864687cl,0x23b92eae22df3562l,0x5c27014b9bbec39el,
-            0x7ef2f2269c0f0f8dl },
-          0 },
-        /* 53 << 0 */
-        { { 0x97359638546c4d8dl,0x5f9c3fc492f24679l,0x912e8beda8c8acd9l,
-            0xec3a318d306634b0l },
-          { 0x80167f41c31cb264l,0x3db82f6f522113f2l,0xb155bcd2dcafe197l,
-            0xfba1da5943465283l },
-          0 },
-        /* 55 << 0 */
-        { { 0x258bbbf9e7305683l,0x31eea5bf07ef5be6l,0x0deb0e4a46c814c1l,
-            0x5cee8449a7b730ddl },
-          { 0xeab495c5a0182bdel,0xee759f879e27a6b4l,0xc2cf6a6880e518cal,
-            0x25e8013ff14cf3f4l },
-          0 },
-        /* 57 << 0 */
-        { { 0x3ec832e77acaca28l,0x1bfeea57c7385b29l,0x068212e3fd1eaf38l,
-            0xc13298306acf8cccl },
-          { 0xb909f2db2aac9e59l,0x5748060db661782al,0xc5ab2632c79b7a01l,
-            0xda44c6c600017626l },
-          0 },
-        /* 59 << 0 */
-        { { 0x69d44ed65c46aa8el,0x2100d5d3a8d063d1l,0xcb9727eaa2d17c36l,
-            0x4c2bab1b8add53b7l },
-          { 0xa084e90c15426704l,0x778afcd3a837ebeal,0x6651f7017ce477f8l,
-            0xa062499846fb7a8bl },
-          0 },
-        /* 60 << 0 */
-        { { 0xdc1e6828ed8a6e19l,0x33fc23364189d9c7l,0x026f8fe2671c39bcl,
-            0xd40c4ccdbc6f9915l },
-          { 0xafa135bbf80e75cal,0x12c651a022adff2cl,0xc40a04bd4f51ad96l,
-            0x04820109bbe4e832l },
-          0 },
-        /* 61 << 0 */
-        { { 0x3667eb1a7f4c04ccl,0x59556621a9404f84l,0x71cdf6537eceb50al,
-            0x994a44a69b8335fal },
-          { 0xd7faf819dbeb9b69l,0x473c5680eed4350dl,0xb6658466da44bba2l,
-            0x0d1bc780872bdbf3l },
-          0 },
-        /* 63 << 0 */
-        { { 0xb8d3d9319ff91fe5l,0x039c4800f0518eedl,0x95c376329182cb26l,
-            0x0763a43482fc568dl },
-          { 0x707c04d5383e76bal,0xac98b930824e8197l,0x92bf7c8f91230de0l,
-            0x90876a0140959b70l },
-          0 },
-        /* 64 << 0 */
-        { { 0xdb6d96f305968b80l,0x380a0913089f73b9l,0x7da70b83c2c61e01l,
-            0x95fb8394569b38c7l },
-          { 0x9a3c651280edfe2fl,0x8f726bb98faeaf82l,0x8010a4a078424bf8l,
-            0x296720440e844970l },
-          0 },
-        /* 65 << 0 */
-        { { 0xdc2306ebfcdbb2b2l,0x79527db7ba66f4b9l,0xbf639ed67765765el,
-            0x01628c4706b6090al },
-          { 0x66eb62f1b957b4a1l,0x33cb7691ba659f46l,0x2c90d98cf3e055d6l,
-            0x7d096ac42f174750l },
-          0 },
-        /* 71 << 0 */
-        { { 0xf19f382e92aa7864l,0x49c7cb94fc05804bl,0xf94aa89b40750d01l,
-            0xdd421b5d4a210364l },
-          { 0x56cd001e39df3672l,0x030a119fdd4af1ecl,0x11f947e696cd0572l,
-            0x574cc7b293786791l },
-          0 },
-        /* 77 << 0 */
-        { { 0x0a2193bfc266f85cl,0x719a87be5a0ec9cel,0x9c30c6422b2f9c49l,
-            0xdb15e4963d5baeb1l },
-          { 0x83c3139be0d37321l,0x4788522b2e9fdbb2l,0x2b4f0c7877eb94eal,
-            0x854dc9d595105f9el },
-          0 },
-        /* 83 << 0 */
-        { { 0x2c9ee62dc3363a22l,0x125d4714ec67199al,0xf87abebf2ab80485l,
-            0xcf3086e87a243ca4l },
-          { 0x5c52b051c64e09ddl,0x5e9b16125625aad7l,0x0536a39db19c6126l,
-            0x97f0013247b64be5l },
-          0 },
-        /* 89 << 0 */
-        { { 0xc1ee6264a7eabe67l,0x62d51e29fd54487dl,0x3ea123446310eb5al,
-            0xbd88aca74765b805l },
-          { 0xb7b284be14fb691al,0x640388f83b9fffefl,0x7ab49dd209f98f9al,
-            0x7150f87e7211e445l },
-          0 },
-        /* 95 << 0 */
-        { { 0x263e039bb308cc40l,0x6684ad762b346fd2l,0x9a127f2bcaa12d0dl,
-            0x76a8f9fea974291fl },
-          { 0xc802049b68aa19e4l,0x65499c990c5dbba0l,0xee1b1cb5344455a1l,
-            0x3f293fda2cd6f439l },
-          0 },
-        /* 101 << 0 */
-        { { 0xb7a96e0a4ea6fdf7l,0xbbe914d3b99cd026l,0x6a610374c569a602l,
-            0xe9b1c23914da499el },
-          { 0xb5f6f0feadc19a99l,0x731251826f21687cl,0x5a8a14644be77793l,
-            0x94ce9e0adba8bfc7l },
-          0 },
-        /* 107 << 0 */
-        { { 0x2ca0ba9c3796f4c7l,0x3571e4d1592ce334l,0x28f9cdebe9f6e877l,
-            0xee206023efce1a70l },
-          { 0xb2159e08b76369dcl,0x2754e4260a7f687cl,0xe008039e02de2ff1l,
-            0xccd7e9418ea700c1l },
-          0 },
-        /* 113 << 0 */
-        { { 0xa125e6c1b7ebcb88l,0x3289e86e10ec0d40l,0xcc3a5ecb98353869l,
-            0x734e0d078a2b0d3al },
-          { 0xe0d92e9a51933360l,0xfa6bcdb1786076b9l,0xd13cca90747f19ecl,
-            0x61d8209d49f3a53dl },
-          0 },
-        /* 116 << 0 */
-        { { 0x87f9793bc9826344l,0x4b3de89bb2f5f79cl,0xc9f08a5659cb1b6el,
-            0xd8f1fc5f6a92b9aal },
-          { 0x86357f9eb412595el,0x53c30bbe65b80f16l,0xf06c2c8c70549a57l,
-            0xa9c8a4b42b9157dal },
-          0 },
-        /* 119 << 0 */
-        { { 0x87af199e6cc47305l,0x062afb7c1e314ddel,0x2be22ba0f3a49fb4l,
-            0x6ed0b988157b7f56l },
-          { 0x8162cf502d653fd9l,0x17d29c64877b7497l,0xd7e814380f67b514l,
-            0xfedf1014fe6ee703l },
-          0 },
-        /* 125 << 0 */
-        { { 0xaab54cfc93740130l,0xf72dab6d225733fal,0x04b76d2d1ed32559l,
-            0xa9fe2396bb85b9cbl },
-          { 0x128b0d24bf2219f0l,0x2292393b579f3ce2l,0x51dc5fac145ff0d5l,
-            0xb16d6af8c3febbc1l },
-          0 },
-    },
-    {
-        /* 0 << 8 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 8 */
-        { { 0x486d8ffa696946fcl,0x50fbc6d8b9cba56dl,0x7e3d423e90f35a15l,
-            0x7c3da195c0dd962cl },
-          { 0xe673fdb03cfd5d8bl,0x0704b7c2889dfca5l,0xf6ce581ff52305aal,
-            0x399d49eb914d5e53l },
-          0 },
-        /* 3 << 8 */
-        { { 0x35d6a53eed4c3717l,0x9f8240cf3d0ed2a3l,0x8c0d4d05e5543aa5l,
-            0x45d5bbfbdd33b4b4l },
-          { 0xfa04cc73137fd28el,0x862ac6efc73b3ffdl,0x403ff9f531f51ef2l,
-            0x34d5e0fcbc73f5a2l },
-          0 },
-        /* 4 << 8 */
-        { { 0x4f7081e144cc3addl,0xd5ffa1d687be82cfl,0x89890b6c0edd6472l,
-            0xada26e1a3ed17863l },
-          { 0x276f271563483caal,0xe6924cd92f6077fdl,0x05a7fe980a466e3cl,
-            0xf1c794b0b1902d1fl },
-          0 },
-        /* 5 << 8 */
-        { { 0x33b2385c08369a90l,0x2990c59b190eb4f8l,0x819a6145c68eac80l,
-            0x7a786d622ec4a014l },
-          { 0x33faadbe20ac3a8dl,0x31a217815aba2d30l,0x209d2742dba4f565l,
-            0xdb2ce9e355aa0fbbl },
-          0 },
-        /* 7 << 8 */
-        { { 0x0c4a58d474a86108l,0xf8048a8fee4c5d90l,0xe3c7c924e86d4c80l,
-            0x28c889de056a1e60l },
-          { 0x57e2662eb214a040l,0xe8c48e9837e10347l,0x8774286280ac748al,
-            0xf1c24022186b06f2l },
-          0 },
-        /* 9 << 8 */
-        { { 0xe8cbf1e5d5923359l,0xdb0cea9d539b9fb0l,0x0c5b34cf49859b98l,
-            0x5e583c56a4403cc6l },
-          { 0x11fc1a2dd48185b7l,0xc93fbc7e6e521787l,0x47e7a05805105b8bl,
-            0x7b4d4d58db8260c8l },
-          0 },
-        /* 10 << 8 */
-        { { 0xb31bd6136339c083l,0x39ff8155dfb64701l,0x7c3388d2e29604abl,
-            0x1e19084ba6b10442l },
-          { 0x17cf54c0eccd47efl,0x896933854a5dfb30l,0x69d023fb47daf9f6l,
-            0x9222840b7d91d959l },
-          0 },
-        /* 11 << 8 */
-        { { 0xc510610939842194l,0xb7e2353e49d05295l,0xfc8c1d5cefb42ee0l,
-            0xe04884eb08ce811cl },
-          { 0xf1f75d817419f40el,0x5b0ac162a995c241l,0x120921bbc4c55646l,
-            0x713520c28d33cf97l },
-          0 },
-        /* 13 << 8 */
-        { { 0x41d04ee21726931al,0x0bbbb2c83660ecfdl,0xa6ef6de524818e18l,
-            0xe421cc51e7d57887l },
-          { 0xf127d208bea87be6l,0x16a475d3b1cdd682l,0x9db1b684439b63f7l,
-            0x5359b3dbf0f113b6l },
-          0 },
-        /* 15 << 8 */
-        { { 0x3a5c752edcc18770l,0x4baf1f2f8825c3a5l,0xebd63f7421b153edl,
-            0xa2383e47b2f64723l },
-          { 0xe7bf620a2646d19al,0x56cb44ec03c83ffdl,0xaf7267c94f6be9f1l,
-            0x8b2dfd7bc06bb5e9l },
-          0 },
-        /* 16 << 8 */
-        { { 0x6772b0e5ab4b35a2l,0x1d8b6001f5eeaacfl,0x728f7ce4795b9580l,
-            0x4a20ed2a41fb81dal },
-          { 0x9f685cd44fec01e6l,0x3ed7ddcca7ff50adl,0x460fd2640c2d97fdl,
-            0x3a241426eb82f4f9l },
-          0 },
-        /* 17 << 8 */
-        { { 0xc503cd33bccd9617l,0x365dede4ba7730a3l,0x798c63555ddb0786l,
-            0xa6c3200efc9cd3bcl },
-          { 0x060ffb2ce5e35efdl,0x99a4e25b5555a1c1l,0x11d95375f70b3751l,
-            0x0a57354a160e1bf6l },
-          0 },
-        /* 19 << 8 */
-        { { 0xc033bdc719803511l,0xa9f97b3b8888c3bel,0x3d68aebc85c6d05el,
-            0xc3b88a9d193919ebl },
-          { 0x2d300748c48b0ee3l,0x7506bc7c07a746c1l,0xfc48437c6e6d57f3l,
-            0x5bd71587cfeaa91al },
-          0 },
-        /* 21 << 8 */
-        { { 0xe40736d3df61bc76l,0x13a619c03f778cdbl,0x6dd921a4c56ea28fl,
-            0x76a524332fa647b4l },
-          { 0x23591891ac5bdc5dl,0xff4a1a72bac7dc01l,0x9905e26162df8453l,
-            0x3ac045dfe63b265fl },
-          0 },
-        /* 23 << 8 */
-        { { 0x8435bd6994b03ed1l,0xd9ad1de3634cc546l,0x2cf423fc00e420cal,
-            0xeed26d80a03096ddl },
-          { 0xd7f60be7a4db09d2l,0xf47f569d960622f7l,0xe5925fd77296c729l,
-            0xeff2db2626ca2715l },
-          0 },
-        /* 25 << 8 */
-        { { 0x5dfee80f83774bddl,0x6313160285734485l,0xa1b524ae914a69a9l,
-            0xebc2ffafd4e300d7l },
-          { 0x52c93db77cfa46a5l,0x71e6161f21653b50l,0x3574fc57a4bc580al,
-            0xc09015dde1bc1253l },
-          0 },
-        /* 27 << 8 */
-        { { 0x9c38ddcceb5b76c1l,0x746f528526fc0ab4l,0x52a63a50d62c269fl,
-            0x60049c5599458621l },
-          { 0xe7f48f823c2f7c9el,0x6bd99043917d5cf3l,0xeb1317a88701f469l,
-            0xbd3fe2ed9a449fe0l },
-          0 },
-        /* 28 << 8 */
-        { { 0xe652533b3cef0d7dl,0xd94f7b182bbb4381l,0x838752be0e80f500l,
-            0x8e6e24889e9c9bfbl },
-          { 0xc975169716caca6al,0x866c49d838531ad9l,0xc917e2397151ade1l,
-            0x2d016ec16037c407l },
-          0 },
-        /* 29 << 8 */
-        { { 0x202f6a9c31c71f7bl,0x01f95aa3296ffe5cl,0x5fc0601453cec3a3l,
-            0xeb9912375f498a45l },
-          { 0xae9a935e5d91ba87l,0xc6ac62810b564a19l,0x8a8fe81c3bd44e69l,
-            0x7c8b467f9dd11d45l },
-          0 },
-        /* 31 << 8 */
-        { { 0x21d3634d39eedbbal,0x35cd2e680455a46dl,0xc8cafe65f9d7eb0cl,
-            0xbda3ce9e00cefb3el },
-          { 0xddc17a602c9cf7a4l,0x01572ee47bcb8773l,0xa92b2b018c7548dfl,
-            0x732fd309a84600e3l },
-          0 },
-        /* 33 << 8 */
-        { { 0x65cf89a2e0600afal,0xcf51482f753c5ceal,0x4f2b2d25a5c2bfc5l,
-            0x9381f57187098256l },
-          { 0x89210f676e976e4bl,0xe2cf12f489f47a7bl,0xc21a1658e8484050l,
-            0xa224dbf82f0fff01l },
-          0 },
-        /* 34 << 8 */
-        { { 0xc28961087282513dl,0x9a78c4296a3f8fb8l,0xddfa56f9a31e24b7l,
-            0xb1e14f84fb72611fl },
-          { 0x1d0f70ab45078d65l,0xb247aef3819924d8l,0x8d519f9dbb9877c1l,
-            0x495c2ece8368c7c9l },
-          0 },
-        /* 35 << 8 */
-        { { 0xca9129a0bdb69d12l,0xbe3e319978f39adfl,0xa88506df5fe49438l,
-            0x17ddb7a7aafe894cl },
-          { 0x28d1456f6d1d742fl,0xeec09651917d1268l,0xdecb1c700fd5b4c0l,
-            0x32d14f6acf2861dbl },
-          0 },
-        /* 36 << 8 */
-        { { 0x903f6e3960e913afl,0xb2b58bee98bf140dl,0x9deff025354890b8l,
-            0x155810068d2e924el },
-          { 0xb5755db493c95e5bl,0x3fac42f0dae20eb8l,0x9377c8c109b6d8e0l,
-            0xa43e2b46ab47ceffl },
-          0 },
-        /* 37 << 8 */
-        { { 0x6c3f5a51cb61e7e7l,0x264aebc80d9c73b2l,0xc404b2114a0d9288l,
-            0x5178d3cf8b3a79e9l },
-          { 0x4080be5372a420d7l,0xa39396adef026429l,0x22fbb92e8dde4728l,
-            0x19e42d8874d949fcl },
-          0 },
-        /* 39 << 8 */
-        { { 0xde352d78387f5557l,0x6770149969367413l,0x255bb8c00b0cc102l,
-            0x63cad1be1f4d262el },
-          { 0xf34f9a8a3f8f4fb6l,0x32bc13aae03a969fl,0xb29d4336218371cdl,
-            0x799d76ab285bd210l },
-          0 },
-        /* 40 << 8 */
-        { { 0x5f57b2fbfacfa459l,0x874b1498c1b5aa6bl,0xb9e89acac4db2092l,
-            0x1362bf8ddf4381dal },
-          { 0x25d76830b76328a0l,0x38188b7098572ae4l,0xb43e941429132f7dl,
-            0x7895a29f22dd42c9l },
-          0 },
-        /* 41 << 8 */
-        { { 0x85bded619e808c05l,0x6e0fc2bcc7ef83bbl,0xed70e0b499bedf77l,
-            0x300e777dc1aaffc0l },
-          { 0xe2da2359c43e6d2cl,0xacf6d60a275226e0l,0x18ca38f7f82558bdl,
-            0xd7b017d475ae2591l },
-          0 },
-        /* 43 << 8 */
-        { { 0xed299e2d7cd92ee2l,0x2c08eb37ad847153l,0x7b372aa712acfd81l,
-            0x574d27f5fabda29cl },
-          { 0xbd8247f0f2ee6ebcl,0x8bf76710d06be261l,0x26e95b4bcb186d4cl,
-            0x4fa3ac1d1ebb4a46l },
-          0 },
-        /* 44 << 8 */
-        { { 0xcbde78dd5e22cbb2l,0xf449c85b76bb4391l,0x4289f357b6a4273bl,
-            0x9fce23fd48e84a19l },
-          { 0xcfc32730939eb3b4l,0x8b3d982c16c32280l,0x5ac234bad5f1346cl,
-            0x781954b470769fc9l },
-          0 },
-        /* 45 << 8 */
-        { { 0xff0d4d30062c7dbdl,0x2c483081e6f9fcf0l,0x22f96316d67e070fl,
-            0xdd9be459c0e68c44l },
-          { 0xb9c1edffce2edd4dl,0x1a54782021fc538cl,0x93849be49979aee1l,
-            0x3f313629a590949el },
-          0 },
-        /* 46 << 8 */
-        { { 0x160b836b266be332l,0x49de38215f340575l,0x782e8f6701edce66l,
-            0x83ae008b5df1a93el },
-          { 0x85d33a263ed9ffebl,0xae2f9f961e79db97l,0xf64f209b95ae9e34l,
-            0x2b6b03455e957d49l },
-          0 },
-        /* 47 << 8 */
-        { { 0x7a24a21a331d6bdal,0xfdba302f6328f742l,0x37a36dd47744dca4l,
-            0xda2832ce6fef500fl },
-          { 0x23da304a7b49d73al,0xeede2cebc6ad834fl,0xf21a81248dec3c78l,
-            0x4bc9469b19b721e3l },
-          0 },
-        /* 48 << 8 */
-        { { 0x6faf68feaae6ee70l,0x78f4cc155602b0c9l,0x7e3321a86e94052al,
-            0x2fb3a0d6734d5d80l },
-          { 0xf3b98f3bb25a43bal,0x30bf803119ee2951l,0x7ffee43321b0612al,
-            0x12f775e42eb821d0l },
-          0 },
-        /* 49 << 8 */
-        { { 0x31cc342913e5c1d6l,0x05deaa3cee54e334l,0x21ea2b61cd5087d8l,
-            0x73a1841e70d1b8bcl },
-          { 0xd44e2b41b078bf14l,0xc295732fcea2a30el,0x30cdab42954939f7l,
-            0xc1b4e43a2dba0b7cl },
-          0 },
-        /* 51 << 8 */
-        { { 0x5f33f618b6a20132l,0xc8d73e3cfbbf3022l,0xf3b9844d47ed4320l,
-            0xab5868aa927f00cal },
-          { 0x06cb1113077f6e1cl,0x1417b43a5c94faaal,0x7666cb90cf4cd1e9l,
-            0x99e009f210900566l },
-          0 },
-        /* 52 << 8 */
-        { { 0x4fdff805f57209b5l,0x9bd65ac3f952ac8dl,0x02a3abd3c7969a6fl,
-            0x1359927ef523775fl },
-          { 0xe09b463f88d2e861l,0x661d2199623287c3l,0x821e64495a70eb7al,
-            0x0afbbb1dd67dc684l },
-          0 },
-        /* 53 << 8 */
-        { { 0x2c5a2b2d55750eb2l,0x54d756c29dc28d9fl,0x798c8d113af97f71l,
-            0x54e21ee21f6d1853l },
-          { 0x34e0c8bceffc3f8al,0xed3cc4dda96f193fl,0x86436a84fad97110l,
-            0x8530ca522c97205el },
-          0 },
-        /* 55 << 8 */
-        { { 0x9b6c8452f7236867l,0x21cf260c777b44fdl,0x659fc99dceb00c52l,
-            0xda97098e2439e8dbl },
-          { 0x647efe510ed6e14fl,0x37c8ca122a6600f3l,0x53e89b0badf6f4a7l,
-            0xd9fc8c716645618al },
-          0 },
-        /* 57 << 8 */
-        { { 0x9cecfb8eee6ebd31l,0x4603994b1ff25529l,0x707bc80af4b141c4l,
-            0x3a83d56c07524d3al },
-          { 0x7035c746613a3020l,0x7aa766b286626a1cl,0x3af656095ac76c78l,
-            0x4039c655171e47d6l },
-          0 },
-        /* 59 << 8 */
-        { { 0x79cb147f0ce33b63l,0xa1328a622d160c61l,0xf99538f3cf7eb87el,
-            0x0334d4958e2241d5l },
-          { 0x3ad97e02f3e49e48l,0xdcfcc754037c3679l,0x76078ba61a8ff67cl,
-            0x8054aa55c2a64964l },
-          0 },
-        /* 60 << 8 */
-        { { 0x5852104b87453b28l,0x073e8128b387344dl,0x300e78e4817cfc08l,
-            0x3a82ed4799362088l },
-          { 0xe222304c88de46a4l,0x666c94fd57fadf4al,0x40b2d08ea0c8e108l,
-            0x4b2955b909e050fal },
-          0 },
-        /* 61 << 8 */
-        { { 0x656078565f814881l,0x0fc3d1ce58466117l,0x0ae377d3c6c1e68al,
-            0xe3dd8d5cba566c48l },
-          { 0x9404849ec4b63be6l,0x1e22b03ba5be9c92l,0x08145122a8b03e63l,
-            0x71248243771fe153l },
-          0 },
-        /* 63 << 8 */
-        { { 0xa80a0e83b41ac541l,0xa77570ea533e5f9bl,0x416a14c0216dc452l,
-            0x2a8d728a19f7ee59l },
-          { 0x58494c8cd6552eaal,0x4d635acd60145722l,0xa8e9b127327b1cbcl,
-            0xb429a62e9f8235f0l },
-          0 },
-        /* 64 << 8 */
-        { { 0xf8d112e76e6485b3l,0x4d3e24db771c52f8l,0x48e3ee41684a2f6dl,
-            0x7161957d21d95551l },
-          { 0x19631283cdb12a6cl,0xbf3fa8822e50e164l,0xf6254b633166cc73l,
-            0x3aefa7aeaee8cc38l },
-          0 },
-        /* 65 << 8 */
-        { { 0xd52d2cb746ef1c7el,0xebd4f7c4d8fb6e07l,0x16f77a48cf6dd2b4l,
-            0x6e8f0431e77e4d51l },
-          { 0x59d94cc4e9177bf2l,0xb58a578f7a7181a1l,0xeefbc4cde8f6d330l,
-            0xa66c85560fe05490l },
-          0 },
-        /* 71 << 8 */
-        { { 0x0e6db7a35d9649dal,0x4d2f25193be3d362l,0xcd891fd5a6b137b5l,
-            0xa4b7e4ddacd377a9l },
-          { 0x20ccd6f24355f258l,0x842c08673aafb413l,0xdd55db99d6873b88l,
-            0x04d15f4fea5a2a55l },
-          0 },
-        /* 77 << 8 */
-        { { 0x679cd93dfae289c2l,0x84cadd61ff92ba1bl,0x548b5a6f2cd734aal,
-            0x1827507db8267082l },
-          { 0xa903a6010c6d5b4cl,0xde0d96befdfb952bl,0x2fc9419c6a2e24f9l,
-            0x27333e3936bb3203l },
-          0 },
-        /* 83 << 8 */
-        { { 0x3eb7f062dde4aa6al,0x40effae07f354cc0l,0xe9a14bc2a066c05el,
-            0x7817b11356afc543l },
-          { 0x5f0ed1f28bdda262l,0x001e23d2e007ec13l,0x435878a59c57de6al,
-            0x84d0e20895ac263cl },
-          0 },
-        /* 89 << 8 */
-        { { 0xedf24aec97a66678l,0xd1f93cf8ccf55671l,0x4ed2ce8a9379a49dl,
-            0x64991862c39b0ac9l },
-          { 0xc15b24e31ff67e04l,0x4ee8fc76c3c084fel,0x262012b4f64bcd46l,
-            0x3b5086732425c622l },
-          0 },
-        /* 95 << 8 */
-        { { 0xaa3e451fe65002f7l,0xf5ff2617eb46d253l,0x918d146e572afca2l,
-            0x0a9333b7e56a8553l },
-          { 0x9b7e232d94127dc0l,0xcd0687d6831014e6l,0x725ce5baf08e1c71l,
-            0x56e26f48cde0e4edl },
-          0 },
-        /* 101 << 8 */
-        { { 0xae78dde8db833460l,0xaf1736fe762cb78al,0x5cd85742eae5ac60l,
-            0x7b6c52fe955e981al },
-          { 0x9f823e8555599f97l,0xb9ce70d21a4b46b3l,0xb6076175d7d09829l,
-            0x21e77d22abf390a4l },
-          0 },
-        /* 107 << 8 */
-        { { 0xf704f09da142ad7el,0xb60ec2e1bab9f5d2l,0x4180314681e54d0dl,
-            0x0de50506309335e6l },
-          { 0x4135374e05aec64fl,0xb5d31041b556808al,0x0092eb86049033a8l,
-            0x5b7a2fa0bde0d737l },
-          0 },
-        /* 113 << 8 */
-        { { 0xc0dfa6bbefb40cfal,0x86a6fe279c5037f3l,0xf153cd37f71155f4l,
-            0xf16d6029767664f9l },
-          { 0x7441aa54c635aa57l,0x547f82e9e8186b2el,0x330b464bfbf7c7fel,
-            0xb5556770a1f6fddel },
-          0 },
-        /* 116 << 8 */
-        { { 0xa0a9c5d1e8f9edf1l,0x9814c26b6946cea3l,0xcbb47a37d8e6a08dl,
-            0x517a3d9b2cba11b1l },
-          { 0x94edc73dab43c540l,0x4fd0b82a753e552cl,0x419aab8bd14ae853l,
-            0x94955f9ca68abad8l },
-          0 },
-        /* 119 << 8 */
-        { { 0x3a162e06ed169150l,0x8c9683a6ba1194a8l,0x53fead66ccc28d04l,
-            0xdbb2a85bef09809al },
-          { 0x58e677439d3ab018l,0xff9a2046b6e56bd0l,0xf4b8215eb28061e9l,
-            0xcf16d9f7b10e358fl },
-          0 },
-        /* 125 << 8 */
-        { { 0x265ceae9a55abe39l,0x9e3783f796a98f84l,0xb799628af0757d99l,
-            0xebb5f12665472fb3l },
-          { 0xd83619f52ba517d8l,0x5672105f50382bdfl,0x32c5681c4a12ee9fl,
-            0x31e6f60d834a9fedl },
-          0 },
-    },
-    {
-        /* 0 << 16 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 16 */
-        { { 0x0f0165fce3779ee3l,0xe00e7f9dbd495d9el,0x1fa4efa220284e7al,
-            0x4564bade47ac6219l },
-          { 0x90e6312ac4708e8el,0x4f5725fba71e9adfl,0xe95f55ae3d684b9fl,
-            0x47f7ccb11e94b415l },
-          0 },
-        /* 3 << 16 */
-        { { 0xbd9b8b1dbe7a2af3l,0xec51caa94fb74a72l,0xb9937a4b63879697l,
-            0x7c9a9d20ec2687d5l },
-          { 0x1773e44f6ef5f014l,0x8abcf412e90c6900l,0x387bd0228142161el,
-            0x50393755fcb6ff2al },
-          0 },
-        /* 4 << 16 */
-        { { 0xfabf770977f7195al,0x8ec86167adeb838fl,0xea1285a8bb4f012dl,
-            0xd68835039a3eab3fl },
-          { 0xee5d24f8309004c2l,0xa96e4b7613ffe95el,0x0cdffe12bd223ea4l,
-            0x8f5c2ee5b6739a53l },
-          0 },
-        /* 5 << 16 */
-        { { 0x3d61333959145a65l,0xcd9bc368fa406337l,0x82d11be32d8a52a0l,
-            0xf6877b2797a1c590l },
-          { 0x837a819bf5cbdb25l,0x2a4fd1d8de090249l,0x622a7de774990e5fl,
-            0x840fa5a07945511bl },
-          0 },
-        /* 7 << 16 */
-        { { 0x26e08c07e3533d77l,0xd7222e6a2e341c99l,0x9d60ec3d8d2dc4edl,
-            0xbdfe0d8f7c476cf8l },
-          { 0x1fe59ab61d056605l,0xa9ea9df686a8551fl,0x8489941e47fb8d8cl,
-            0xfeb874eb4a7f1b10l },
-          0 },
-        /* 9 << 16 */
-        { { 0x9164088d977eab40l,0x51f4c5b62760b390l,0xd238238f340dd553l,
-            0x358566c3db1d31c9l },
-          { 0x3a5ad69e5068f5ffl,0xf31435fcdaff6b06l,0xae549a5bd6debff0l,
-            0x59e5f0b775e01331l },
-          0 },
-        /* 10 << 16 */
-        { { 0x2cc5226138634818l,0x501814f4b44c2e0bl,0xf7e181aa54dfdba3l,
-            0xcfd58ff0e759718cl },
-          { 0xf90cdb14d3b507a8l,0x57bd478ec50bdad8l,0x29c197e250e5f9aal,
-            0x4db6eef8e40bc855l },
-          0 },
-        /* 11 << 16 */
-        { { 0xd5d5cdd35958cd79l,0x3580a1b51d373114l,0xa36e4c91fa935726l,
-            0xa38c534def20d760l },
-          { 0x7088e40a2ff5845bl,0xe5bb40bdbd78177fl,0x4f06a7a8857f9920l,
-            0xe3cc3e50e968f05dl },
-          0 },
-        /* 13 << 16 */
-        { { 0x10595b5696a71cbal,0x944938b2fdcadeb7l,0xa282da4cfccd8471l,
-            0x98ec05f30d37bfe1l },
-          { 0xe171ce1b0698304al,0x2d69144421bdf79bl,0xd0cd3b741b21dec1l,
-            0x712ecd8b16a15f71l },
-          0 },
-        /* 15 << 16 */
-        { { 0xe89f48c85963a46el,0x658ab875a99e61c7l,0x6e296f874b8517b4l,
-            0x36c4fcdcfc1bc656l },
-          { 0xde5227a1a3906defl,0x9fe95f5762418945l,0x20c91e81fdd96cdel,
-            0x5adbe47eda4480del },
-          0 },
-        /* 16 << 16 */
-        { { 0xa7a8746a584c5e20l,0x267e4ea1b9dc7035l,0x593a15cfb9548c9bl,
-            0x5e6e21354bd012f3l },
-          { 0xdf31cc6a8c8f936el,0x8af84d04b5c241dcl,0x63990a6f345efb86l,
-            0x6fef4e61b9b962cbl },
-          0 },
-        /* 17 << 16 */
-        { { 0xaa35809ddfe6e2a0l,0xebb4d7d4356a2222l,0x7d500a6a319f33b7l,
-            0x4895a47d4ac99011l },
-          { 0x300ab40bdf3812b2l,0xd0764ec88aec8b9fl,0x86b61d95e591b2a7l,
-            0xc1b2a0b72ed74603l },
-          0 },
-        /* 19 << 16 */
-        { { 0x6001bf5d3849c680l,0xd7a1a4e4c1d3faccl,0xa0f2776418c5e351l,
-            0x0849c0736c29c623l },
-          { 0x3317e143ac751c0cl,0x9bcb1f3eda06200bl,0x40a63a75541419b5l,
-            0x8fad9c983f62c513l },
-          0 },
-        /* 21 << 16 */
-        { { 0xacff0828d03b2242l,0x5a9375c43abb7389l,0x41b1a318d0192baal,
-            0x105bd3100458e97bl },
-          { 0x71582dc7ed496315l,0x8ab2884a4d4bda18l,0xb8b638b494bc5bb8l,
-            0xb42ed1309500bb04l },
-          0 },
-        /* 23 << 16 */
-        { { 0x73e04f02ad1ed952l,0x680051cadfa5bdb7l,0xbe0bef3c0c7437b9l,
-            0x45d6f3a40e65e627l },
-          { 0x5295e060c9436a75l,0xbe84ba78d289ba9el,0x350887fd69c09364l,
-            0xf27bfd17671c64a7l },
-          0 },
-        /* 25 << 16 */
-        { { 0xc8afbdc3adf6ffc5l,0x4a4fb35876385891l,0xc7fa86424d41453fl,
-            0x19490b7672eedd06l },
-          { 0xc883e45337d22d6al,0x8e6e38e4a9009f96l,0x44e2811eb1c560c6l,
-            0x8a0021bf4439cfcfl },
-          0 },
-        /* 27 << 16 */
-        { { 0xba768f8b7615a327l,0x6c8b320d7b15bbe7l,0x5d8d5bcbaaa9ca64l,
-            0x19a2b99f3d13cdfdl },
-          { 0x858288a26f172e10l,0x2412a4da37a00f94l,0xfc67fd2edaa7f6c6l,
-            0x4aea0eadafa2a5c5l },
-          0 },
-        /* 28 << 16 */
-        { { 0x5c80ccef6cd77b30l,0x49978299ec99b6d0l,0x6bf4485eb939d335l,
-            0xc53e61ab86d7c147l },
-          { 0xdd948052fb601dddl,0x34c5eb393511dd48l,0x91f5c67600e6f61cl,
-            0x33f1b525b1e71f34l },
-          0 },
-        /* 29 << 16 */
-        { { 0xb4cb4a151d2dad36l,0x709a61631e60b60dl,0x2f18f3bd932ece4fl,
-            0x70f495a8e92368bel },
-          { 0x6e88be2bb7aeaa6fl,0x4efebd9ae1bf1d6el,0x49925e6e44e94993l,
-            0x33b7aba0ef0517dcl },
-          0 },
-        /* 31 << 16 */
-        { { 0x69ce1f207afe6c37l,0xe1148ba984f68db5l,0x32668bdc2c594a8al,
-            0x2cb60d3063ac4fb3l },
-          { 0x5e6efe1dd9e036f8l,0x917cb2a27db4739fl,0x70ea601ded4e0b5el,
-            0x5928f068ae7ac8a6l },
-          0 },
-        /* 33 << 16 */
-        { { 0x9e4ad0073f2d96abl,0x51a9697f2d058c03l,0xcd5c0a7522d1e795l,
-            0xaa1a121c2ac4f019l },
-          { 0xa837c14c3e3631f4l,0x6a997381236a5576l,0xb305e7db2753782bl,
-            0xae561b0237243afbl },
-          0 },
-        /* 34 << 16 */
-        { { 0x20176baca787897bl,0x057b8b979a9f67d9l,0xe7d5c4f761e14e09l,
-            0x8e4856901e6cd6d0l },
-          { 0x3eeffbba9b925d52l,0xe651a5383046927bl,0x02326d1fe92d4352l,
-            0xad2d6493d697369fl },
-          0 },
-        /* 35 << 16 */
-        { { 0xe9de299c548c4ca5l,0x66f64ef54be3bde3l,0xcf6d39ebf2d5ebc9l,
-            0x665ca727898953e1l },
-          { 0x521ec435e33ac1b4l,0x8418fa7534ab2b82l,0x94d6c0c4771a3a87l,
-            0x21feb6054859ee22l },
-          0 },
-        /* 36 << 16 */
-        { { 0xde7153f8eed9dd1dl,0xba09ad1152ebcb2el,0xaa41b015e1843fb6l,
-            0xf933a2abdd4ce6f0l },
-          { 0x777f834313f6b83fl,0x28df7da4db113a75l,0x6d7d1b3c72a5d143l,
-            0x6f789698966c6ddfl },
-          0 },
-        /* 37 << 16 */
-        { { 0x57d11ed7a95e704el,0x7d5ac6dc380ad582l,0xb175421d5ab6e377l,
-            0x4e383b0ba760dd4dl },
-          { 0xde07b81a352b6cb3l,0x342abe825c2e1704l,0x90988de20dd48537l,
-            0x4a7fec0544821591l },
-          0 },
-        /* 39 << 16 */
-        { { 0xb0e4d17c90a94eb7l,0x27555067aceb0176l,0x587576e15c38c4e2l,
-            0xe647d9dd445f2880l },
-          { 0x00beb2f5ca502f83l,0x4e89e638c44767c7l,0xbef361da154a5757l,
-            0x2dc632a2dc0675f2l },
-          0 },
-        /* 40 << 16 */
-        { { 0xed439a33a72ba054l,0xa3170a15ead265bal,0xcf7eb903fe99a58el,
-            0xcf6db0c633d80c26l },
-          { 0xd031255ef613e71al,0x12ccbe5718ca255cl,0xdd21d0537808c40dl,
-            0xf5488ebc3af2be6bl },
-          0 },
-        /* 41 << 16 */
-        { { 0x589a125ac10f8157l,0x3c8a15bde1353e49l,0x7d9bbd0c22ce2dd0l,
-            0xdfcd019211ac7bb1l },
-          { 0x0e1d67151193c5b1l,0xd4de115ab0e8c285l,0x0b3e94c2272c29fel,
-            0xea640843c8213581l },
-          0 },
-        /* 43 << 16 */
-        { { 0x7a01aeed6aca2231l,0x8135cf2ace80abbel,0xdc1a41b2ae5fdec9l,
-            0xde34ea4da0174364l },
-          { 0xa5104e453cf8b845l,0x4b6fd986675ba557l,0x4bc750af29c8cb4al,
-            0x8bebb266583f9391l },
-          0 },
-        /* 44 << 16 */
-        { { 0x47110d7c1be3f9c5l,0x12b9e4485eadb4ddl,0x6e8c09870b713d41l,
-            0xe1e20356733d56ael },
-          { 0xe68d6bab445ea727l,0x9ef4f6eac934a1a4l,0xe0155547f8cef1c3l,
-            0xdb5c3909159bdcbfl },
-          0 },
-        /* 45 << 16 */
-        { { 0xef0449cb32fa8a37l,0x95071f5dcd246405l,0x1c56ad776c598891l,
-            0x981781de0fa9cd42l },
-          { 0x0f93d456d29c0500l,0x43aa7bc1483f52c4l,0xd7c8736666c8abadl,
-            0x47552530ea5050efl },
-          0 },
-        /* 46 << 16 */
-        { { 0x40dd9ca9fa9b8d3dl,0xf27b7bc056da41d9l,0x87967f4b66db8845l,
-            0xf6918c9444de6bc7l },
-          { 0x4d76d51135568d4dl,0x7ab18f9a40e7fa5al,0x069a44bba5bbbdc6l,
-            0x19e6c04bb4c8f808l },
-          0 },
-        /* 47 << 16 */
-        { { 0x5fd2501108b2b6c7l,0xcce85a3ec41cad21l,0x90857daffdd70387l,
-            0x7a679062c63789f4l },
-          { 0x9c462134ef8666e2l,0xcb7dba108c8505bdl,0x7c4a7e2fc610f2e7l,
-            0x22906f65d68315f9l },
-          0 },
-        /* 48 << 16 */
-        { { 0xf2efe23d442a8ad1l,0xc3816a7d06b9c164l,0xa9df2d8bdc0aa5e5l,
-            0x191ae46f120a8e65l },
-          { 0x83667f8700611c5bl,0x83171ed7ff109948l,0x33a2ecf8ca695952l,
-            0xfa4a73eef48d1a13l },
-          0 },
-        /* 49 << 16 */
-        { { 0x41dd38c1118de9a0l,0x3485cb3be2d8f6f5l,0xd4bac751b1dcc577l,
-            0x2148d93fed12ea6bl },
-          { 0xde3504729da8cb18l,0x6046daf89eb85925l,0xddbc357b942b1044l,
-            0x248e7afe815b8b7cl },
-          0 },
-        /* 51 << 16 */
-        { { 0xd4bb77b3acb21004l,0xe9f236cf83392035l,0xa9894c5c52133743l,
-            0x4d6112749a7b054al },
-          { 0xa61675ea4ba2a553l,0x59c199681da6aa78l,0x3988c36590f474del,
-            0x73e751bbd001be43l },
-          0 },
-        /* 52 << 16 */
-        { { 0x97cacf846604007dl,0x1e92b4b22d47a9f1l,0x858ae0d6374ed165l,
-            0x4c973e6f307aefb8l },
-          { 0x6f524a238a10eb72l,0x7b4a92a9eb2849d6l,0x3678bda42fe91eddl,
-            0x56092acd7c0fc35cl },
-          0 },
-        /* 53 << 16 */
-        { { 0x93bea99b1b9b43c4l,0x2f6af6f3e145fda2l,0x862f0607278adf0dl,
-            0x647be08398456ccal },
-          { 0xce79ba1487250c28l,0x1c1c4fc8efedab42l,0x966f612af90caa8dl,
-            0xb1a2cf6e72c440f8l },
-          0 },
-        /* 55 << 16 */
-        { { 0x2fca1be45b3b7dd5l,0x453c19853c211bcal,0x313cb21969a46484l,
-            0x66082837414bd5dfl },
-          { 0xab7a97bf2ac1cdf7l,0x45cd1792676d778fl,0x42fb6c4f6a5b560al,
-            0x45747fe30b8f17e9l },
-          0 },
-        /* 57 << 16 */
-        { { 0x38b6db6235db6218l,0xa10cdfe1bb54bacal,0x56fd4a1d610f7f6bl,
-            0xc4bea78b76d183d7l },
-          { 0xc0e6ca9fbf730d26l,0x1b1e271aed6cf535l,0x6fef275faadbe375l,
-            0xfa2e8da903e489bal },
-          0 },
-        /* 59 << 16 */
-        { { 0x6f79d25c7c4626ecl,0xfe27690232d55d6cl,0x3f5c5768afa19ce3l,
-            0xa1373777f8834739l },
-          { 0x761d67a8a4ce960al,0xb34de1ea459e656al,0x8725b0f09db6f269l,
-            0x75316f250dbfe22el },
-          0 },
-        /* 60 << 16 */
-        { { 0x091d5b631a093b40l,0xb85c1c075862f24al,0xc5d74eb53e8f85bfl,
-            0xf51c7746cab22456l },
-          { 0xc25cb8d9e761da89l,0x2670ec2fc0f028b5l,0x873fd30d2db9af5cl,
-            0x3d0f1ea18262565el },
-          0 },
-        /* 61 << 16 */
-        { { 0x8f9492c261c23b3cl,0xd366baeb631688a4l,0x55e759e78093bb07l,
-            0xf6d0eaf47218f765l },
-          { 0xb8a174ff54ca583bl,0x790f10e0b23d14cel,0xfebe7333be83cbbal,
-            0xfeb6dcc5eed67536l },
-          0 },
-        /* 63 << 16 */
-        { { 0x175b3bacce027e5bl,0xe0728a99c48252c4l,0x0be25d4507a39c7cl,
-            0xcb9c2d3aba8e8c72l },
-          { 0x6185a48d1abd459al,0x27207feadff9a27bl,0xfd92e8231d34393fl,
-            0x738511534351d965l },
-          0 },
-        /* 64 << 16 */
-        { { 0xfcde7cc8f43a730fl,0xe89b6f3c33ab590el,0xc823f529ad03240bl,
-            0x82b79afe98bea5dbl },
-          { 0x568f2856962fe5del,0x0c590adb60c591f3l,0x1fc74a144a28a858l,
-            0x3b662498b3203f4cl },
-          0 },
-        /* 65 << 16 */
-        { { 0x8ede0fcdc11682eel,0x41e3faa1b2ab5664l,0x58b2a7dc26a35ff5l,
-            0x939bcd6b701b89e9l },
-          { 0x55f66fd188e0838fl,0x99d1a77b4ff1f975l,0x103abbf72e060cc5l,
-            0x91c77beb6bc4bdbbl },
-          0 },
-        /* 71 << 16 */
-        { { 0xcd048abca380cc72l,0x91cab1bbd0e13662l,0x68115b18686de4cel,
-            0x484724e63deccbf5l },
-          { 0xf164ba54f176137el,0x5189793662ab2728l,0x6afdecf9b60a5458l,
-            0xca40472d0aabafd2l },
-          0 },
-        /* 77 << 16 */
-        { { 0x7a9439183b98d725l,0x1c1763e8ece1ea3cl,0x45c44ef639840476l,
-            0x689271e69c009133l },
-          { 0xa017405f56a51fe1l,0xd54cc7253e0d0970l,0x212ad075cfe09e8bl,
-            0x999f21c37af7bf30l },
-          0 },
-        /* 83 << 16 */
-        { { 0xdc2a2af12bf95f73l,0xb88b4ca76de82cbel,0xa31a21aaecb8e84el,
-            0x86d19a601b74f5bel },
-          { 0xc68bf64406008019l,0xe52ab50e9431c694l,0x6375463d627ab11cl,
-            0xdd3eeaa03c0ef241l },
-          0 },
-        /* 89 << 16 */
-        { { 0x608d9cb323f1caf8l,0x95069450b1700741l,0xe3132bd2bc2fa7aal,
-            0xc4f363e7f64e4f06l },
-          { 0xb059c4191ca888c2l,0x1004cb1f8d17bf5dl,0x6b6ba6f934ea5711l,
-            0x071d94abd79b2c8al },
-          0 },
-        /* 95 << 16 */
-        { { 0xc7ef9b42d147a39dl,0x36dd5d770a10cd5bl,0x3bf6cc77d0eea34bl,
-            0x60c84591197479c7l },
-          { 0xf95860ac50ba50edl,0xe1c94a8dc4cdc8fal,0x780818d685e24a23l,
-            0x1950e3c0c8abbd27l },
-          0 },
-        /* 101 << 16 */
-        { { 0x9908c694ae04778el,0x2e37a6790a0d36ffl,0x212a340f52b067bdl,
-            0xec89c9fad080b914l },
-          { 0x920dc2f005ab8a23l,0xecff5c78655e8984l,0x80eedd34f66211acl,
-            0xa7a56366ef58d4d8l },
-          0 },
-        /* 107 << 16 */
-        { { 0x4f95debe2bca42f0l,0xf0346307844334d2l,0x7003a60521d600aal,
-            0x1eb98c6365c5248al },
-          { 0x6757b3822fa202cal,0x32765d399fb12f36l,0xe851b476d7b44c9al,
-            0x27cd7d1b4e0bab4cl },
-          0 },
-        /* 113 << 16 */
-        { { 0xd0c1f7c9c43ea1a3l,0x73d944f49f42907dl,0xd113f34619352c92l,
-            0x86a1ad53b149cdc1l },
-          { 0x32c34e8f848d1be4l,0xba8afda7c3d9360bl,0x17e8bc32eea8bf96l,
-            0x3174cae499c87febl },
-          0 },
-        /* 116 << 16 */
-        { { 0x4b215f016671b47el,0xb67633ca4a8dae2al,0x2915120f79fd3cdbl,
-            0xc1f8a06fb064e6del },
-          { 0xf4d5368cc1d57420l,0x6ada51a8e18de475l,0xa0f0d47cc749d4b0l,
-            0xabfa2c0074526aa5l },
-          0 },
-        /* 119 << 16 */
-        { { 0xf752f6659e5ce44fl,0x7b97ebfa189d35ecl,0x9540cbb90fc609abl,
-            0x19c1dc6999632cc8l },
-          { 0x0a957700e08ca9a8l,0xb0cd0ab7a3246a4el,0xca687cfcc8d6a544l,
-            0xb6281f0035f82a77l },
-          0 },
-        /* 125 << 16 */
-        { { 0x547027012b818036l,0xf72315f729c8f14cl,0x95f1bc15230e74bel,
-            0x2e7c492f1abe20d4l },
-          { 0xe1ea8b1cd7e78ab1l,0xc3f6ba59043585adl,0xac404ea9477ac053l,
-            0xaa6872914ec6d0e3l },
-          0 },
-    },
-    {
-        /* 0 << 24 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 24 */
-        { { 0xd9d0c8c4868af75dl,0xd7325cff45c8c7eal,0xab471996cc81ecb0l,
-            0xff5d55f3611824edl },
-          { 0xbe3145411977a0eel,0x5085c4c5722038c6l,0x2d5335bff94bb495l,
-            0x894ad8a6c8e2a082l },
-          0 },
-        /* 3 << 24 */
-        { { 0xd1e059b21994ef20l,0x2a653b69638ae318l,0x70d5eb582f699010l,
-            0x279739f709f5f84al },
-          { 0x5da4663c8b799336l,0xfdfdf14d203c37ebl,0x32d8a9dca1dbfb2dl,
-            0xab40cff077d48f9bl },
-          0 },
-        /* 4 << 24 */
-        { { 0xf2369f0b879fbbedl,0x0ff0ae86da9d1869l,0x5251d75956766f45l,
-            0x4984d8c02be8d0fcl },
-          { 0x7ecc95a6d21008f0l,0x29bd54a03a1a1c49l,0xab9828c5d26c50f3l,
-            0x32c0087c51d0d251l },
-          0 },
-        /* 5 << 24 */
-        { { 0xf61790abfbaf50a5l,0xdf55e76b684e0750l,0xec516da7f176b005l,
-            0x575553bb7a2dddc7l },
-          { 0x37c87ca3553afa73l,0x315f3ffc4d55c251l,0xe846442aaf3e5d35l,
-            0x61b911496495ff28l },
-          0 },
-        /* 7 << 24 */
-        { { 0x4bdf3a4956f90823l,0xba0f5080741d777bl,0x091d71c3f38bf760l,
-            0x9633d50f9b625b02l },
-          { 0x03ecb743b8c9de61l,0xb47512545de74720l,0x9f9defc974ce1cb2l,
-            0x774a4f6a00bd32efl },
-          0 },
-        /* 9 << 24 */
-        { { 0x327bc002b0131e5bl,0x1739e6d5cb2514d9l,0xc8cbdafe55a81543l,
-            0x5bb1a36ce1137243l },
-          { 0x205da3c517325327l,0xc35c1a36515a057el,0xf00f64c942925f9bl,
-            0xbd14633cb7d59f7al },
-          0 },
-        /* 10 << 24 */
-        { { 0xae2ad171656e8c3al,0xc0e2a4631acd0705l,0x006f6a8aa0b6055cl,
-            0xaf4513d72b65a26el },
-          { 0x3f549e14d616d5bcl,0x64ee395571253b1fl,0xe8b10bc1b8ce243al,
-            0xbcbeace5913a4e77l },
-          0 },
-        /* 11 << 24 */
-        { { 0x47c1004341f37dbdl,0x96eccae36168ecf6l,0x65bde59d1ca46aa3l,
-            0x38a7027ab8698ffal },
-          { 0xa2b89dc86dc34437l,0x5a0a118d43a4153fl,0x9e330a861ce22fd8l,
-            0x28382af6b3bbd3bcl },
-          0 },
-        /* 13 << 24 */
-        { { 0x0b2e27c0d81e0271l,0xa67a7596117a317cl,0x17f08928a6723d99l,
-            0x71a75681485310a3l },
-          { 0x90465462afb66ca9l,0x185e97ccfbbe229dl,0x6a1a606addad8fc2l,
-            0x2431f316b3c797cfl },
-          0 },
-        /* 15 << 24 */
-        { { 0x4703401193529432l,0x1f106bdd30743462l,0xabfb9964cd66d8cal,
-            0x934d9d5ae9bdadd5l },
-          { 0x5976d815908e3d22l,0x344a362f28e057bdl,0xf92cdadc5443dfb3l,
-            0x001297adf089603bl },
-          0 },
-        /* 16 << 24 */
-        { { 0x7f99824f20151427l,0x206828b692430206l,0xaa9097d7e1112357l,
-            0xacf9a2f209e414ecl },
-          { 0xdbdac9da27915356l,0x7e0734b7001efee3l,0x54fab5bbd2b288e2l,
-            0x4c630fc4f62dd09cl },
-          0 },
-        /* 17 << 24 */
-        { { 0x4a2fce605044066bl,0x904a019cfa3a47f4l,0xba81ea9c0c5c0a60l,
-            0xd7e4ea0d96c098bdl },
-          { 0xefe700419cd50a02l,0xc0c839d42d7f048cl,0xe2daf264e09b561fl,
-            0x0cbc13185034b18bl },
-          0 },
-        /* 19 << 24 */
-        { { 0x11e5f2e388323f7al,0xe07a74c2927584cdl,0x1e774b3495613d2dl,
-            0x9c9b52c52c787488l },
-          { 0x3cdd3c3ebe421f08l,0x5ff7819e223e3d5fl,0xba8739b2c1da09b9l,
-            0x6b7263164e8b491bl },
-          0 },
-        /* 21 << 24 */
-        { { 0xb5afd13ca0943befl,0xd651772957abb1ccl,0x9d5a52dc9b61b5bcl,
-            0x85cefaa6806e31cdl },
-          { 0xab84257a720a1deal,0x6a60261bced70d35l,0xc023f94db9d6da61l,
-            0x947f7eec54a0ae0el },
-          0 },
-        /* 23 << 24 */
-        { { 0xc3b787569f83b787l,0xd6d249263694ddd7l,0x58d248945d70a02el,
-            0xac16670e8c278c6al },
-          { 0x71a94d58e370b6e6l,0xe4d763840253db05l,0x99b1c98814b32cfel,
-            0x4e6bd870cc78cc95l },
-          0 },
-        /* 25 << 24 */
-        { { 0xf5f7ca79c8b63614l,0xf3bfb2158af4903cl,0x2bdb9f5496d47bd3l,
-            0xd6e715300e8a63bal },
-          { 0x67e90a497a93bec4l,0x8613478b8c1e63eel,0xe36bd9c8f2dde561l,
-            0x681486518a768689l },
-          0 },
-        /* 27 << 24 */
-        { { 0xef617a9494aa531cl,0x9ac35e2fd6f4ad87l,0xbcd2a047122468fbl,
-            0xbd7a423fef7c5ca6l },
-          { 0xab58cb52064c8040l,0x93ef4ed54a644716l,0xf7d17097c32cd48dl,
-            0xb249a173d17fcf42l },
-          0 },
-        /* 28 << 24 */
-        { { 0x66fe0fffe298cdf5l,0x3f61bea47b2e51b6l,0x7d372117bad3afa4l,
-            0x6521a09cef656e2fl },
-          { 0xb3b8c966e8a58fe7l,0x25203a115a47ebc7l,0xfe81588d5c4be573l,
-            0x6132e2f31f49a03cl },
-          0 },
-        /* 29 << 24 */
-        { { 0xbbe5c108b7a7ecc4l,0x62a5a78ebfd22e4cl,0xb7974033df188bd2l,
-            0xcf11deea4df7d1ael },
-          { 0x99cc774a53ace3eal,0xe0373a71105cc1f6l,0xd751987f133d7a20l,
-            0xab86ee04ae215871l },
-          0 },
-        /* 31 << 24 */
-        { { 0x2094f9a280cd10e6l,0x045232aa7b8a0da7l,0x969a81b69c03244el,
-            0x1293b4ca7e98d955l },
-          { 0x1631421dd68f3ab0l,0xa0106422c3738c82l,0xc5f43845f82c4ff9l,
-            0xb479acbe1aa0f58fl },
-          0 },
-        /* 33 << 24 */
-        { { 0xf1db0267f67683cfl,0xa6b13c9e44ce009dl,0x04b4eed505884a69l,
-            0xf2ff9c16d9087a0bl },
-          { 0x2c53699b3e35b4a6l,0x5020c0142369afb8l,0xf83bfe0095be37f1l,
-            0xd300d8c553b29d80l },
-          0 },
-        /* 34 << 24 */
-        { { 0x16893055811cf4bbl,0x580dd1e55aeb5027l,0xcaf47fba5ae3c71cl,
-            0xde79698129ebbb07l },
-          { 0xbed1db33d262cdd3l,0x78315e3748c7313bl,0xfc9561f02fe1368dl,
-            0xe0209698ccacacc7l },
-          0 },
-        /* 35 << 24 */
-        { { 0xd61af89a781ece24l,0xf3b90626008f41e9l,0xd715dbf7c5693191l,
-            0x8d6c05de6f299edel },
-          { 0xf18d62637ca50aacl,0x7987bf5cb0dd5fdcl,0x424136bd2cfa702bl,
-            0xaa7e237ded859db2l },
-          0 },
-        /* 36 << 24 */
-        { { 0xde7169e4e5d41796l,0x6700333e33c0a380l,0xe20b95780343a994l,
-            0xa745455e1fb3a1c3l },
-          { 0x97e0ff88ce029a7fl,0x3b3481c976e384bcl,0x028b339dddad5951l,
-            0xa1fdcdbae4b95cfcl },
-          0 },
-        /* 37 << 24 */
-        { { 0xcc9221baed20c6adl,0xf2619a51fa9c73aal,0xfc2cff847d7f55a5l,
-            0xd56c23d65f01d4dal },
-          { 0x6d20f88cb3d84d5fl,0x048825f75dcc615dl,0x73634d3f85631a6el,
-            0xa57a02e3ad7b2e2dl },
-          0 },
-        /* 39 << 24 */
-        { { 0x067a8dcf08aa81ffl,0x62948258c23f3d16l,0xb61bd04316f2fe7bl,
-            0xf250f769b6a766b1l },
-          { 0x32df97246d0b241el,0xb736e4bb714e5f88l,0x50da15022c1d40d7l,
-            0x013e0edebdd285a4l },
-          0 },
-        /* 40 << 24 */
-        { { 0x1b92c3a0181a5d8fl,0x6429531d9adb77c7l,0x629152b53af710eel,
-            0x4e3f27370bd5647el },
-          { 0xfb7c392b77553c7dl,0xa930abacefe78c87l,0xf80c8cd6a05a6991l,
-            0x751469b71be5f6f5l },
-          0 },
-        /* 41 << 24 */
-        { { 0xf89f2b0b3e2f2af0l,0x52f634099eefc39al,0x505005c679906cb6l,
-            0x820c2216b2de0b1el },
-          { 0x96f0f2831f20ad7al,0xcd33125c718ffcb0l,0xf6130ef278f0c578l,
-            0x4cda2471d0b76b95l },
-          0 },
-        /* 43 << 24 */
-        { { 0x611dd83f39485581l,0x96c47051803e1b20l,0xefacc736830f44c7l,
-            0x5588d8ce688b12bal },
-          { 0x44f4edf3eee70fadl,0x1026dfd8869539f7l,0xa4c146ee8ddb0e00l,
-            0x9f4f55816efb41c8l },
-          0 },
-        /* 44 << 24 */
-        { { 0x6036ed0236cbace7l,0x5a70e4abada837ddl,0xf06918aff10b2fefl,
-            0x08a8a9f69fd31590l },
-          { 0x6c4a1ba6916af88dl,0x4868bc1466016037l,0x06d345af164228a9l,
-            0x2c1961d19b550dd9l },
-          0 },
-        /* 45 << 24 */
-        { { 0x8b72775c6851f0acl,0x7827242bd70f5975l,0x2de91f1e34db4a6fl,
-            0x586bf3d58538f5eel },
-          { 0xf0a15aed25d9a09bl,0x43018e56f74deb46l,0xc2af1ad0f50e0e67l,
-            0x49cc9528b10cff6fl },
-          0 },
-        /* 46 << 24 */
-        { { 0x05eb146c9d55c425l,0xe2b557ccbc62261fl,0x2a716301bd077089l,
-            0x83a63c81e0527d02l },
-          { 0x055ff7f8a0d9203bl,0x05d09f0525bf5a04l,0x2e44545fb3eb0b30l,
-            0xed7c57c4d279a1adl },
-          0 },
-        /* 47 << 24 */
-        { { 0x6928f6e45e0ebdd5l,0xd7e44ddf092d233bl,0xe7148066d1b7026fl,
-            0xf645a2e53d5f25c3l },
-          { 0x6eeb25ee58ff9eb4l,0x60f1fcf737f87ebfl,0x9eaaf1e5c4679c70l,
-            0x4609fb13b7b7dc7el },
-          0 },
-        /* 48 << 24 */
-        { { 0xae915f5d5fa067d1l,0x4134b57f9668960cl,0xbd3656d6a48edaacl,
-            0xdac1e3e4fc1d7436l },
-          { 0x674ff869d81fbb26l,0x449ed3ecb26c33d4l,0x85138705d94203e8l,
-            0xccde538bbeeb6f4al },
-          0 },
-        /* 49 << 24 */
-        { { 0x27f317af2b33987fl,0xd2d3cf5d51e59588l,0x333999bd031f27c9l,
-            0x6ddfa3f22e0a3306l },
-          { 0x23e0e651990041b0l,0xf028aba1585837acl,0x1c6ad72b25226f53l,
-            0xf243c991d1fca64al },
-          0 },
-        /* 51 << 24 */
-        { { 0x72b8a13272cbae1fl,0xfe0b1c4fbfdbd64al,0x98bc7876c5e76921l,
-            0x51c726bfdb1f5af7l },
-          { 0x97e88a842c186e8bl,0x9ed99516ed8eb7b4l,0x3e54a17dafc818ebl,
-            0xfcfbf25a1e8f77d8l },
-          0 },
-        /* 52 << 24 */
-        { { 0x7780d7d68f7d5c6el,0x6725b49a454101e6l,0xceddc26586b0770cl,
-            0xc26624615666f504l },
-          { 0x16b77477ce040f75l,0x13f9113c293f8b45l,0xff0cfa07e2dcc91el,
-            0x1948d8bd41c202f5l },
-          0 },
-        /* 53 << 24 */
-        { { 0x4c6ae39a1dfbe13al,0xafb1e5c46be9c200l,0x39e728d168bb08c3l,
-            0xc794b905acc9166fl },
-          { 0x1cb0dec2d9c7c3e4l,0xc4c3053289f14d65l,0x4af80801a6a9d609l,
-            0x79d7e82de0d6ab24l },
-          0 },
-        /* 55 << 24 */
-        { { 0xb905c6af8ad4cf6el,0x785590b0f6d1be13l,0x78f402c2a0ef76bel,
-            0x739b22ea5c19a40bl },
-          { 0xd4d3262553d596b6l,0x01598eb4d571666bl,0xf8dc150b8173486al,
-            0xd8aa43af15e94f09l },
-          0 },
-        /* 57 << 24 */
-        { { 0xcfa387cd984393b5l,0x1645659e21a1bf92l,0xb4ab3966dd46c7eel,
-            0xcf8c296d89482623l },
-          { 0x72e4d01cf976b4c0l,0x44ad07e8fa0fa5ebl,0xd6c82681b486fdd2l,
-            0x2d9074f89b8845b4l },
-          0 },
-        /* 59 << 24 */
-        { { 0x96e4fc08d96862dbl,0xf9e29bb6c50c14b2l,0xfedaad64f8f9be75l,
-            0xab6b2d79ae9e1274l },
-          { 0x033e3eb58d84dec0l,0xc136904ccbd113e7l,0xb82b0aed6061f289l,
-            0x3476d9247b699e25l },
-          0 },
-        /* 60 << 24 */
-        { { 0x8fb5ceeb969231dcl,0xaed13be1686ff6cdl,0x71d7c67bdd69db87l,
-            0x49613e08fb53f33al },
-          { 0x2899729ead8e802fl,0x83bfde49d1982a1dl,0x675c45ea878239d2l,
-            0xb7bf59cd0d8240d3l },
-          0 },
-        /* 61 << 24 */
-        { { 0x853d8cd1baf53b8bl,0x9c73d04cff95fc18l,0xae8a94412d1d6aacl,
-            0xd8a15ce901500b70l },
-          { 0xaef813499aacba59l,0x2cd2ba0ac493cd8dl,0x01c37ee1f398f034l,
-            0xed72d51d0f7299fcl },
-          0 },
-        /* 63 << 24 */
-        { { 0x2c204940e7592fb1l,0xcc1bb19b49366f08l,0x31855e8a7c927935l,
-            0x16f7e9a2c590b81dl },
-          { 0xa5fbb7c1ed8df240l,0x7b5204122de2d7f5l,0x7eb1eb989a637588l,
-            0x5ef4eca89540d2e8l },
-          0 },
-        /* 64 << 24 */
-        { { 0x55d5c68da61a76fal,0x598b441dca1554dcl,0xd39923b9773b279cl,
-            0x33331d3c36bf9efcl },
-          { 0x2d4c848e298de399l,0xcfdb8e77a1a27f56l,0x94c855ea57b8ab70l,
-            0xdcdb9dae6f7879bal },
-          0 },
-        /* 65 << 24 */
-        { { 0x811e14dd9594afb8l,0xaf6c1b10d349124al,0x8488021b6528a642l,
-            0xecf6834341cf1447l },
-          { 0x7a40acb756924446l,0xd9c11bbed98ec4cfl,0x0cef00bfb2bff163l,
-            0xfaaad8015432803bl },
-          0 },
-        /* 71 << 24 */
-        { { 0x5a217d5e6b075cbel,0x7ef88d1dc89b513bl,0xb6d015da0531c93bl,
-            0x477b502a6333834al },
-          { 0x4655e48b2fb458d5l,0x93f21a7cb7674ca8l,0xa0616786502d1f3al,
-            0x82d16d17f26bb6ccl },
-          0 },
-        /* 77 << 24 */
-        { { 0x3d995aa9183c1688l,0xa125906c3766d2e8l,0x23ed7871c5f10d5bl,
-            0xdfe1e1cc6df80368l },
-          { 0x8bfcb54271eaae2cl,0xe94e6f910945a7bbl,0xd543ef90862f650al,
-            0x0dc043b803eed66bl },
-          0 },
-        /* 83 << 24 */
-        { { 0x0c6a5620060d2ccdl,0xcd8200e37a8a03a4l,0x6018d304793867e6l,
-            0xad23dd61a74d054dl },
-          { 0x5a856faeebc21eb4l,0x66be16714b5cd7dbl,0xe0d0441ec75f8c9dl,
-            0xb80ca9ecf90dbc6dl },
-          0 },
-        /* 89 << 24 */
-        { { 0xbd6902ccd24692cbl,0xbcce6bbc21920408l,0x40f120ca55dec4c5l,
-            0xd9f1f5ef5361c8b3l },
-          { 0x535d368226935dffl,0x9635447b01a9998al,0x8c4ec40d99e36d12l,
-            0xbaeef8912b793369l },
-          0 },
-        /* 95 << 24 */
-        { { 0xded3a51c1cd887ebl,0xd43225568376515cl,0xdaf3a2271ca7c097l,
-            0x089156fdecd4d90cl },
-          { 0x2b354810ca0727c9l,0xb7257c1966c19d8cl,0x5e68a379432d5072l,
-            0x75c04c2443e585c7l },
-          0 },
-        /* 101 << 24 */
-        { { 0xb5ba2a8fe5e0952fl,0x2c2d086811040b4el,0x27448bd5f818e253l,
-            0x720f677987a92c85l },
-          { 0x2c9b2367b9d035fal,0xf18ad8ce16c15ab9l,0xd65a360841bd57eel,
-            0xeb4b07c9ff6ae897l },
-          0 },
-        /* 107 << 24 */
-        { { 0xcffb6d71d38589acl,0x812372920fa509d3l,0x94db5ba6e54725e8l,
-            0x1ad2b4206cfbb825l },
-          { 0x8592c1f238cfb9f2l,0xbe8e917e0eec6a27l,0x53921bfe9d93d42fl,
-            0x1aa95e6269454a35l },
-          0 },
-        /* 113 << 24 */
-        { { 0xc25e8934d898049dl,0xeeaf4e6d3bb3d459l,0xc3ac44447d29ad10l,
-            0xccdf9fcbcef8fa04l },
-          { 0x1d995a3fb9679cb9l,0x3d6c5eab46fabc14l,0xd3849ff066385d4dl,
-            0xc0eb21bacff08be2l },
-          0 },
-        /* 116 << 24 */
-        { { 0x8213c71e90d13fd6l,0x114321149bb6b733l,0xaaf8037880ac4902l,
-            0xb24e046b555f7557l },
-          { 0x5f6ed2881db79832l,0xd493a758ac760e5dl,0xbc30a2a7a1c0f570l,
-            0xa5009807161174e3l },
-          0 },
-        /* 119 << 24 */
-        { { 0x9e9b864a6889e952l,0xee908932f352f31al,0xe421f2423166b932l,
-            0x6dd4aa3b7ddbdb35l },
-          { 0x553cc5639e8b88a4l,0x05457f171f04704dl,0x1dcc3004c9554e6bl,
-            0x3a4a3a253f1b61e7l },
-          0 },
-        /* 125 << 24 */
-        { { 0x7ac0a5e7c56e303al,0x7c7bab64037b0a19l,0x11f103fcc8d29a2bl,
-            0x7d99dc46cf0b1340l },
-          { 0x0481588ceffba92el,0x8a817356b04e77bcl,0x19edf4dbce1b708dl,
-            0xa2a1f7a6e6f9d52cl },
-          0 },
-    },
-    {
-        /* 0 << 32 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 32 */
-        { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l,
-            0xd953c50ddbdf58e9l },
-          { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl,
-            0x863ebb7e9eb288f3l },
-          0 },
-        /* 3 << 32 */
-        { { 0xa18f07e0e90fb21el,0x00fd2b80bba7fca1l,0x20387f2795cd67b5l,
-            0x5b89a4e7d39707f7l },
-          { 0x8f83ad3f894407cel,0xa0025b946c226132l,0xc79563c7f906c13bl,
-            0x5f548f314e7bb025l },
-          0 },
-        /* 4 << 32 */
-        { { 0x0ee6d3a7c35d8794l,0x042e65580356bae5l,0x9f59698d643322fdl,
-            0x9379ae1550a61967l },
-          { 0x64b9ae62fcc9981el,0xaed3d6316d2934c6l,0x2454b3025e4e65ebl,
-            0xab09f647f9950428l },
-          0 },
-        /* 5 << 32 */
-        { { 0xc1b3d3d331b85f09l,0x0f45354aa88ae64al,0xa8b626d32fec50fdl,
-            0x1bdcfbd4e828834fl },
-          { 0xe45a2866cd522539l,0xfa9d4732810f7ab3l,0xd8c1d6b4c905f293l,
-            0x10ac80473461b597l },
-          0 },
-        /* 7 << 32 */
-        { { 0xbbb175146fc627e2l,0xa0569bc591573a51l,0xa7016d9e358243d5l,
-            0x0dac0c56ac1d6692l },
-          { 0x993833b5da590d5fl,0xa8067803de817491l,0x65b4f2124dbf75d0l,
-            0xcc960232ccf80cfbl },
-          0 },
-        /* 9 << 32 */
-        { { 0x35d742806cf3d65bl,0x4b7c790678b28dd9l,0xc4fcdd2f95e1f85fl,
-            0xcf6fb7ba591350b6l },
-          { 0x9f8e3287edfc26afl,0xe2dd9e73c2d0ed9al,0xeab5d67f24cbb703l,
-            0x60c293999a759a5al },
-          0 },
-        /* 10 << 32 */
-        { { 0xcf8625d7708f97cdl,0xfb6c5119ea419de4l,0xe8cb234dc03f9b06l,
-            0x5a7822c335e23972l },
-          { 0x9b876319a284ff10l,0xefcc49977093fdcel,0xdddfd62a878fe39al,
-            0x44bfbe53910aa059l },
-          0 },
-        /* 11 << 32 */
-        { { 0xfb93ca3d7ca53d5fl,0x432649f004379cbfl,0xf506113acba2ff75l,
-            0x4594ae2103718b35l },
-          { 0x1aa6cee50d044627l,0xc0e0d2b7f5c94aa2l,0x0bf33d3dee4dd3f5l,
-            0xaca96e288477c97al },
-          0 },
-        /* 13 << 32 */
-        { { 0x995c068e6861a713l,0xa9ba339463de88dcl,0xab954344689a964fl,
-            0x58195aec0f5a0d6cl },
-          { 0xc5f207d5c98f8b50l,0x6600cd280c98ccf6l,0x1a680fe339c3e6c2l,
-            0xa23f3931660e87c0l },
-          0 },
-        /* 15 << 32 */
-        { { 0x43bc1b42c78440a1l,0x9a07e22632ac6c3fl,0xaf3d7ba10f4bcd15l,
-            0x3ad43c9da36814c6l },
-          { 0xca11f742a0c9c162l,0xd3e06fc6c90b96ecl,0xeace6e766bf2d03fl,
-            0x8bcd98e8f8032795l },
-          0 },
-        /* 16 << 32 */
-        { { 0xe27a6dbe305406ddl,0x8eb7dc7fdd5d1957l,0xf54a6876387d4d8fl,
-            0x9c479409c7762de4l },
-          { 0xbe4d5b5d99b30778l,0x25380c566e793682l,0x602d37f3dac740e3l,
-            0x140deabe1566e4ael },
-          0 },
-        /* 17 << 32 */
-        { { 0x7be3ddb77099ae96l,0x83d6157306e0da6al,0x31bcac5f74bf9870l,
-            0x7f7aa3b422b256f1l },
-          { 0xff84d63caa212e20l,0x7d636556decdc8b5l,0x8fed824dbf909d62l,
-            0x62d70186e5fb1445l },
-          0 },
-        /* 19 << 32 */
-        { { 0x8796989f67d8ab8al,0xa46282253700b772l,0xa353cadf05f799abl,
-            0x7a8be2741eeb06bbl },
-          { 0xf74a367e4653b134l,0x4e43449660c70340l,0xc99b6d6b72e10b18l,
-            0xcf1adf0f1ba636e1l },
-          0 },
-        /* 21 << 32 */
-        { { 0xb0260fb57c6a0958l,0xae791b9c2fc2731el,0xb339f2bf8ce6e575l,
-            0x769214a816e2639fl },
-          { 0xbaf422e1346da10el,0xc7805fdf7a56f463l,0xf47b6b766f845428l,
-            0x8f21369e38492948l },
-          0 },
-        /* 23 << 32 */
-        { { 0x2bac716a17931a90l,0x42a5e27cc8267236l,0xfd4b367c0bafeb78l,
-            0x5856e69c6173db02l },
-          { 0xfaac7358973d73c4l,0xbfbffcc36768d285l,0x05444ff2be3eb243l,
-            0x9f8d3692f3c323fel },
-          0 },
-        /* 25 << 32 */
-        { { 0xac296863221c31a9l,0x46f3a24ef1ca99a9l,0xd927648a7535a864l,
-            0xd7e3c47d5848e497l },
-          { 0xc19595b782a98ac7l,0x9a9bf627273ff554l,0xe29aa48fb62298a1l,
-            0xed3f068ee797e9e3l },
-          0 },
-        /* 27 << 32 */
-        { { 0x8d16a1660eb9227bl,0xe04c6bc58c37c74bl,0xd1be9585cc1ef78cl,
-            0xa5cfe1962e929d9bl },
-          { 0xc9b0ea21417c1cc6l,0x316352d345b79599l,0xc1502c4dc2d54af7l,
-            0xe7f4412990f83445l },
-          0 },
-        /* 28 << 32 */
-        { { 0x0f6704abd95917e8l,0x168dafaeaec6e899l,0xd2833e8cde710027l,
-            0x34ea277e68ee3c59l },
-          { 0x3689e2350054d4e5l,0x6f3a568d11013943l,0xb5ce1ff69bc2b144l,
-            0x705bfe7e72b33a59l },
-          0 },
-        /* 29 << 32 */
-        { { 0x1baa4f02c8e93284l,0xec6b93ea3c97d3e8l,0xb656c149034f8b32l,
-            0x3cab9063cd4cc69fl },
-          { 0xd8de5989d61031ccl,0xcf85329fc1b1de1dl,0xf18b78b323d8cb9al,
-            0x6dc04bc61a6b69eal },
-          0 },
-        /* 31 << 32 */
-        { { 0x79cf86314a1d4f8fl,0xda5ba331aa47394el,0x36f9c0be8ff20527l,
-            0xccdc719bbc7097f6l },
-          { 0x2304a3ba5cb052bbl,0xab80cdea392f0ab5l,0x0ac1858bf38de03bl,
-            0xd6e2119878a8f55dl },
-          0 },
-        /* 33 << 32 */
-        { { 0x6bdebc26584bc618l,0x499f0f1894591499l,0xd35ed50bf4a573dal,
-            0x5a622e73ff2792d0l },
-          { 0x8510cbce68d41a3bl,0x6610f43c94e919afl,0x4527373dc163c8a1l,
-            0x50afb46f280a8a7dl },
-          0 },
-        /* 34 << 32 */
-        { { 0x33e779cd8de7707al,0xf94bbd94438f535bl,0x61159864be144878l,
-            0xb6623235f098ce4al },
-          { 0x6813b71ba65568d8l,0x6603dd4c2f796451l,0x9a97d88c8b9ee5b2l,
-            0xaaa4593549d5926cl },
-          0 },
-        /* 35 << 32 */
-        { { 0x2e01fc75ebe75bf2l,0x8270318d6cbdd09cl,0x534e4f21d3f1a196l,
-            0x6c9eaeca9459173el },
-          { 0xda454fe0b642a1d4l,0xe45b69bfc4664c4al,0x4724bd423e078dc8l,
-            0x39ac8fe603336b81l },
-          0 },
-        /* 36 << 32 */
-        { { 0x0a2e53dd302e9485l,0x75882a19deaa9ff4l,0xe283242eac8de4ddl,
-            0x2742105cc678dba7l },
-          { 0x9f6f0a88cdb3a8a2l,0x5c9d3338f722e894l,0xf1fa3143c38c31c1l,
-            0x22137e2db18c77acl },
-          0 },
-        /* 37 << 32 */
-        { { 0xd821665e368d7835l,0x3300c012b596c6ecl,0xb60da7353557b2ddl,
-            0x6c3d9db6fb8cf9ael },
-          { 0x092d8b0b8b4b0d34l,0x900a0bf4b3d4107dl,0x75371a245e813ec3l,
-            0x91125a17f2ad56d5l },
-          0 },
-        /* 39 << 32 */
-        { { 0x5e6594e2fe0073e6l,0x908a93778be13cb7l,0xa2c3d5c8ac26617cl,
-            0xa0bab085c317c6b9l },
-          { 0x0bdc183b83664109l,0x6bbba2b468f9dcd9l,0x697a50785814be41l,
-            0x12a59b183a5e5f98l },
-          0 },
-        /* 40 << 32 */
-        { { 0xbd9802e6c30fa92bl,0x5a70d96d9a552784l,0x9085c4ea3f83169bl,
-            0xfa9423bb06908228l },
-          { 0x2ffebe12fe97a5b9l,0x85da604971b99118l,0x9cbc2f7f63178846l,
-            0xfd96bc709153218el },
-          0 },
-        /* 41 << 32 */
-        { { 0xb5a85c61bfa70ca6l,0x4edc7f2d4c1f745fl,0x05aea9aa3ded1eb5l,
-            0x750385efb82e5918l },
-          { 0xdcbc53221fdc5164l,0x32a5721f6794184el,0x5c5b2269ff09c90bl,
-            0x96d009115323ca42l },
-          0 },
-        /* 43 << 32 */
-        { { 0x12c73403f43f1440l,0xc94813eb66cc1f50l,0x04d5957b9b035151l,
-            0x76011bca4bfaafa8l },
-          { 0x56806c13574f1f0al,0x98f63a4697652a62l,0x17c63ef4a3178de9l,
-            0xf7ce961a65009a52l },
-          0 },
-        /* 44 << 32 */
-        { { 0x58f92aebe4173516l,0xdc37d99275e42d44l,0x76dcec5b4d48e1bal,
-            0x07e0608e25676448l },
-          { 0xa1877bcd1d4af36al,0x38b62b3c5a8ccf0cl,0x60522e88aeab7f75l,
-            0xbef213ed5e03547al },
-          0 },
-        /* 45 << 32 */
-        { { 0x8acd5ba4e6ed0282l,0x792328f06a04531dl,0xe95de8aa80297e50l,
-            0x79d33ce07d60e05cl },
-          { 0xcb84646dd827d602l,0xd3421521302a608cl,0x867970a4524f9751l,
-            0x05e2f7e347a75734l },
-          0 },
-        /* 46 << 32 */
-        { { 0x64e4de4a01c66263l,0xbcfe16a4d0033d4cl,0x359e23d4817de1dcl,
-            0xb01e812ec259449cl },
-          { 0x90c9ade2df53499fl,0xabbeaa27288c6862l,0x5a655db4cd1b896fl,
-            0x416f10a5a022a3d6l },
-          0 },
-        /* 47 << 32 */
-        { { 0x0d17e1ef98601fd5l,0x9a3f85e0eab76a6fl,0x0b9eaed1510b80a1l,
-            0x3282fd747ec30422l },
-          { 0xaca5815a70a4a402l,0xfad3121cf2439cb2l,0xba251af81fccabd6l,
-            0xb382843fa5c127d5l },
-          0 },
-        /* 48 << 32 */
-        { { 0x958381db1782269bl,0xae34bf792597e550l,0xbb5c60645f385153l,
-            0x6f0e96afe3088048l },
-          { 0xbf6a021577884456l,0xb3b5688c69310ea7l,0x17c9429504fad2del,
-            0xe020f0e517896d4dl },
-          0 },
-        /* 49 << 32 */
-        { { 0x442fdfe920cd1ebel,0xa8317dfa6a250d62l,0x5214576d082d5a2dl,
-            0xc1a5d31930803c33l },
-          { 0x33eee5b25e4a2cd0l,0x7df181b3b4db8011l,0x249285145b5c6b0bl,
-            0x464c1c5828bf8837l },
-          0 },
-        /* 51 << 32 */
-        { { 0x5464da65d55babd1l,0x50eaad2a0048d80fl,0x782ca3dd2b9bce90l,
-            0x41107164ab526844l },
-          { 0xad3f0602d56e0a5fl,0xc1f0248018455114l,0xe05d8dcab1527931l,
-            0x87818cf5bb1295d7l },
-          0 },
-        /* 52 << 32 */
-        { { 0x95aeb5bd483e333al,0x003af31effeaededl,0xfc5532e87efb1e4fl,
-            0xb37e0fb52dfa24a5l },
-          { 0x485d4cecdc140b08l,0xb81a0d23983bd787l,0xd19928dae8d489fdl,
-            0x3fa0312c177b9dbdl },
-          0 },
-        /* 53 << 32 */
-        { { 0xade391470c6d7e88l,0x4fd1e8cd47072c45l,0x145760fed5a65c56l,
-            0x198960c7be4887del },
-          { 0xfe7974a82640257al,0xf838a19b774febefl,0xb2aecad11b6e988el,
-            0x643f44fa448e4a8fl },
-          0 },
-        /* 55 << 32 */
-        { { 0xc35ceffdee756e71l,0x2c1364d88ea932c4l,0xbd594d8d837d2d9fl,
-            0x5b334bdac9d74d48l },
-          { 0x72dc3e03b8fac08bl,0x38f01de006fdf70fl,0x4bde74b31d298ba4l,
-            0x2598d183ad5f42a9l },
-          0 },
-        /* 57 << 32 */
-        { { 0x02c6ba15f62befa2l,0x6399ceb55c8ccee9l,0x3638bd6e08d3473el,
-            0xb8f1f13d2f8f4a9cl },
-          { 0x50d7560655827a74l,0x8d6e65f33fb4f32cl,0x40a5d21189ee621al,
-            0x6d3f9e11c4474716l },
-          0 },
-        /* 59 << 32 */
-        { { 0xcb633a4ce9b2bb8fl,0x0475703f8c529253l,0x61e007b5a8878873l,
-            0x342d77ba14504159l },
-          { 0x2925175c313578dfl,0x4e631897b6b097f1l,0xe64d138929350e41l,
-            0x2fb20608ec7adccdl },
-          0 },
-        /* 60 << 32 */
-        { { 0xa560c234d5c0f5d1l,0x74f84bf62bdef0efl,0x61ed00005cbd3d0bl,
-            0xc74262d087fb408bl },
-          { 0xad30a6496cc64128l,0x708e3a31a4a8b154l,0xaf21ce2637f82074l,
-            0x31d33b38204c9a74l },
-          0 },
-        /* 61 << 32 */
-        { { 0x8f609fe04cc2f575l,0xe44f9784b35488c4l,0x0d464bb6180fa375l,
-            0x4f44d5d2de2247b8l },
-          { 0xf538eb38141ef077l,0x781f8f6e8fa456a4l,0x67e9a46429b4f39dl,
-            0x245d21e8b704c3e9l },
-          0 },
-        /* 63 << 32 */
-        { { 0x45a94ee858ffa7cdl,0x4d38bc6818053549l,0x0b4bc65a499d79f3l,
-            0xa81e3ab09159cab7l },
-          { 0xf13716efb47898cel,0xb7ee597c2e2d9044l,0x09396b90e6158276l,
-            0x5c644dc36a533fcel },
-          0 },
-        /* 64 << 32 */
-        { { 0xcca4428dbbe5a1a9l,0x8187fd5f3126bd67l,0x0036973a48105826l,
-            0xa39b6663b8bd61a0l },
-          { 0x6d42deef2d65a808l,0x4969044f94636b19l,0xf611ee47dd5d564cl,
-            0x7b2f3a49d2873077l },
-          0 },
-        /* 65 << 32 */
-        { { 0xbe4c16c3bf429668l,0xd32f56f0ef35db3bl,0xae8355de9ea4e3f1l,
-            0x8f66c4a2a450944el },
-          { 0xafab94c8b798fbe2l,0x18c57baff7f3d5cfl,0x692d191c5cfa5c7dl,
-            0xc0c25f69a689daebl },
-          0 },
-        /* 71 << 32 */
-        { { 0x15fb3ae398340d4cl,0xa8b9233a7de82134l,0x44971a545fc0dbc6l,
-            0xb2b4f0f3a1d3f094l },
-          { 0x8d9eaba1b6242bd4l,0xd8aad777787cc557l,0xb1ab8b7870d1a2bbl,
-            0x5d20f48cead3bfe3l },
-          0 },
-        /* 77 << 32 */
-        { { 0x4dacbf09a2bf9772l,0x969a4c4357aa8457l,0xadbe673b273ebfc5l,
-            0xb85582bb927778c9l },
-          { 0x748371855c03752cl,0xc337bc6bc2f60d11l,0x2c3838e4ad456a09l,
-            0xaf479c897e381842l },
-          0 },
-        /* 83 << 32 */
-        { { 0x8530ae751b1aea77l,0xf43b923ba8310cb9l,0x9c1a60c6bf4dd6c5l,
-            0x11885b863e3aaaa5l },
-          { 0x594a8fa90f69821el,0x1eece3d66bc37998l,0x1fd718f518df32bfl,
-            0x1c00c7d461d84082l },
-          0 },
-        /* 89 << 32 */
-        { { 0xd67ee3a4c763c3cfl,0x760b128305969234l,0x1a5ff331ec17f2d1l,
-            0x25f0392a84fecfefl },
-          { 0xb1bc004a3a80d47el,0xf450bf08182fee3bl,0xf11117681e19751el,
-            0x5b4127dae28ed23fl },
-          0 },
-        /* 95 << 32 */
-        { { 0x91e00defdaf08f09l,0x7ef41724f4738a07l,0x990fbbceaf1263fcl,
-            0x779121e3e6eeb5aal },
-          { 0x3e162c7a5a3ecf52l,0x73ae568a51be5faal,0x8bea1bfa451be8a9l,
-            0x3e8cd5db90e11097l },
-          0 },
-        /* 101 << 32 */
-        { { 0x90390f7224d27159l,0x685c139efd07e5d4l,0x4e21e44a3bc234a8l,
-            0x61b50f34eeb14dacl },
-          { 0x7beb0aa087555d58l,0x781326bcc806f0d2l,0xc289537a1eb7199fl,
-            0x44a31a037b42766el },
-          0 },
-        /* 107 << 32 */
-        { { 0x7d778206edde4b40l,0x34539fa18eb92fcdl,0x5a0bdd79bf52a552l,
-            0x066d3672fdcca75el },
-          { 0xd73fa893e28b5a5bl,0xb495135876c38698l,0x44469b0114ae16cfl,
-            0xb428c763691d6618l },
-          0 },
-        /* 113 << 32 */
-        { { 0x9022db8b69196353l,0x152ebb7dd7a4afd0l,0xea36fae57fcf1765l,
-            0xa8fc00ba0decea8al },
-          { 0x1047206a0c0b0414l,0x6607d8ade076df28l,0xf343e19966b8aba1l,
-            0x7f03c1ad311e208dl },
-          0 },
-        /* 116 << 32 */
-        { { 0xe6b4c96e888f3870l,0xa21bb618fe544042l,0x7122ee88bd817699l,
-            0xcb38ecebfa66e173l },
-          { 0x6ed5b3482c9cc05fl,0x591affc84ae0fd9el,0x7cf325ac6e7aaac0l,
-            0x2397c053d05e5be0l },
-          0 },
-        /* 119 << 32 */
-        { { 0x95363f61eaa96552l,0xe03bc6b38fb15b73l,0xa5c5808f2c389053l,
-            0xcd021e6c11b2030cl },
-          { 0x349ca9bdc038e30al,0x0a3368d4165afa2cl,0x043630debbfa1cc6l,
-            0xb8c4456ba7cdbf69l },
-          0 },
-        /* 125 << 32 */
-        { { 0x63aa3315fd7d2983l,0xaf4c96afa6a04bedl,0x3a5c0b5410814a74l,
-            0x9906f5e30f9b0770l },
-          { 0x622be6523676986fl,0x09ac5bc0173e7cb5l,0x1c40e56a502c8b3cl,
-            0xabb9a0f7253ce8f6l },
-          0 },
-    },
-    {
-        /* 0 << 40 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 40 */
-        { { 0x889f6d65533ef217l,0x7158c7e4c3ca2e87l,0xfb670dfbdc2b4167l,
-            0x75910a01844c257fl },
-          { 0xf336bf07cf88577dl,0x22245250e45e2acel,0x2ed92e8d7ca23d85l,
-            0x29f8be4c2b812f58l },
-          0 },
-        /* 3 << 40 */
-        { { 0xc51e414351facc61l,0xbaf2647de68a25bcl,0x8f5271a00ff872edl,
-            0x8f32ef993d2d9659l },
-          { 0xca12488c7593cbd4l,0xed266c5d02b82fabl,0x0a2f78ad14eb3f16l,
-            0xc34049484d47afe3l },
-          0 },
-        /* 4 << 40 */
-        { { 0xa6f3d574c005979dl,0xc2072b426a40e350l,0xfca5c1568de2ecf9l,
-            0xa8c8bf5ba515344el },
-          { 0x97aee555114df14al,0xd4374a4dfdc5ec6bl,0x754cc28f2ca85418l,
-            0x71cb9e27d3c41f78l },
-          0 },
-        /* 5 << 40 */
-        { { 0x09c1670209470496l,0xa489a5edebd23815l,0xc4dde4648edd4398l,
-            0x3ca7b94a80111696l },
-          { 0x3c385d682ad636a4l,0x6702702508dc5f1el,0x0c1965deafa21943l,
-            0x18666e16610be69el },
-          0 },
-        /* 7 << 40 */
-        { { 0x45beb4ca2a604b3bl,0x56f651843a616762l,0xf52f5a70978b806el,
-            0x7aa3978711dc4480l },
-          { 0xe13fac2a0e01fabcl,0x7c6ee8a5237d99f9l,0x251384ee05211ffel,
-            0x4ff6976d1bc9d3ebl },
-          0 },
-        /* 9 << 40 */
-        { { 0xdde0492316e043a2l,0x98a452611dd3d209l,0xeaf9f61bd431ebe8l,
-            0x00919f4dbaf56abdl },
-          { 0xe42417db6d8774b1l,0x5fc5279c58e0e309l,0x64aa40613adf81eal,
-            0xef419edabc627c7fl },
-          0 },
-        /* 10 << 40 */
-        { { 0x3919759239ef620fl,0x9d47284074fa29c4l,0x4e428fa39d416d83l,
-            0xd1a7c25129f30269l },
-          { 0x46076e1cd746218fl,0xf3ad6ee8110d967el,0xfbb5f434a00ae61fl,
-            0x3cd2c01980d4c929l },
-          0 },
-        /* 11 << 40 */
-        { { 0xfa24d0537a4af00fl,0x3f938926ca294614l,0x0d700c183982182el,
-            0x801334434cc59947l },
-          { 0xf0397106ec87c925l,0x62bd59fc0ed6665cl,0xe8414348c7cca8b5l,
-            0x574c76209f9f0a30l },
-          0 },
-        /* 13 << 40 */
-        { { 0x95be42e2bb8b6a07l,0x64be74eeca23f86al,0xa73d74fd154ce470l,
-            0x1c2d2857d8dc076al },
-          { 0xb1fa1c575a887868l,0x38df8e0b3de64818l,0xd88e52f9c34e8967l,
-            0x274b4f018b4cc76cl },
-          0 },
-        /* 15 << 40 */
-        { { 0x3f5c05b4f8b7559dl,0x0be4c7acfae29200l,0xdd6d3ef756532accl,
-            0xf6c3ed87eea7a285l },
-          { 0xe463b0a8f46ec59bl,0x531d9b14ecea6c83l,0x3d6bdbafc2dc836bl,
-            0x3ee501e92ab27f0bl },
-          0 },
-        /* 16 << 40 */
-        { { 0x8df275455922ac1cl,0xa7b3ef5ca52b3f63l,0x8e77b21471de57c4l,
-            0x31682c10834c008bl },
-          { 0xc76824f04bd55d31l,0xb6d1c08617b61c71l,0x31db0903c2a5089dl,
-            0x9c092172184e5d3fl },
-          0 },
-        /* 17 << 40 */
-        { { 0x7b1a921ea6b3340bl,0x6d7c4d7d7438a53el,0x2b9ef73c5bf71d8fl,
-            0xb5f6e0182b167a7cl },
-          { 0x5ada98ab0ce536a3l,0xee0f16f9e1fea850l,0xf6424e9d74f1c0c5l,
-            0x4d00de0cd3d10b41l },
-          0 },
-        /* 19 << 40 */
-        { { 0xd542f522a6533610l,0xfdde15a734ec439al,0x696560fedc87dd0dl,
-            0x69eab421e01fd05fl },
-          { 0xca4febdc95cc5988l,0x839be396c44d92fbl,0x7bedff6daffe543bl,
-            0xd2bb97296f6da43al },
-          0 },
-        /* 21 << 40 */
-        { { 0x5bc6dea80b8d0077l,0xb2adf5d1ea9c49efl,0x7104c20eaafe8659l,
-            0x1e3604f37866ee7el },
-          { 0x0cfc7e7b3075c8c5l,0x5281d9bb639c5a2bl,0xcbdf42494bc44ee3l,
-            0x835ab066655e9209l },
-          0 },
-        /* 23 << 40 */
-        { { 0x78fbda4b90b94ffal,0x447e52eb7beb993cl,0x920011bc92620d15l,
-            0x7bad6ecf481fd396l },
-          { 0xad3bd28ba989a09el,0x20491784a3e62b78l,0xcdcd7096b07bd9efl,
-            0x9bf5bb7337d780adl },
-          0 },
-        /* 25 << 40 */
-        { { 0xbe911a71a976c8d4l,0xba0346743fdd778el,0x2359e7434cf87ea1l,
-            0x8dccf65f07ebb691l },
-          { 0x6c2c18eb09746d87l,0x6a19945fd2ecc8fal,0xc67121ff2ffa0339l,
-            0x408c95ba9bd9fc31l },
-          0 },
-        /* 27 << 40 */
-        { { 0xa317204bcaa5da39l,0xd390df7468bf53d7l,0x56de18b2dbd71c0dl,
-            0xcb4d3bee75184779l },
-          { 0x815a219499d920a5l,0x9e10fb4ecf3d3a64l,0x7fd4901dfe92e1eel,
-            0x5d86d10d3ab87b2el },
-          0 },
-        /* 28 << 40 */
-        { { 0x24f2a692840bb336l,0x7c353bdca669fa7bl,0xda20d6fcdec9c300l,
-            0x625fbe2fa13a4f17l },
-          { 0xa2b1b61adbc17328l,0x008965bfa9515621l,0x49690939c620ff46l,
-            0x182dd27d8717e91cl },
-          0 },
-        /* 29 << 40 */
-        { { 0x98e9136c878303e4l,0x2769e74fd1e65efdl,0x6154c545809da56el,
-            0x8c5d50a04301638cl },
-          { 0x10f3d2068214b763l,0x2da9a2fc44df0644l,0xca912bab588a6fcdl,
-            0xe9e82d9b227e1932l },
-          0 },
-        /* 31 << 40 */
-        { { 0xcbdc4d66d080e55bl,0xad3f11e5b8f98d6bl,0x31bea68e18a32480l,
-            0xdf1c6fd52c1bcf6el },
-          { 0xadcda7ee118a3f39l,0xbd02f857ac060d5fl,0xd2d0265d86631997l,
-            0xb866a7d33818f2d4l },
-          0 },
-        /* 33 << 40 */
-        { { 0xfbcce2d31892d98dl,0x2e34bc9507de73dcl,0x3a48d1a94891eec1l,
-            0xe64499c24d31060bl },
-          { 0xe9674b7149745520l,0xf126ccaca6594a2cl,0x33e5c1a079945342l,
-            0x02aa0629066e061fl },
-          0 },
-        /* 34 << 40 */
-        { { 0xdfd7c0ae7af3191el,0x923ec111d68c70d9l,0xb6f1380bb675f013l,
-            0x9192a224f23d45bal },
-          { 0xbe7890f9524891e3l,0x45b24c47eba996bbl,0x59331e48320447e9l,
-            0x0e4d8753ac9afad4l },
-          0 },
-        /* 35 << 40 */
-        { { 0x49e49c38c9f5a6c3l,0x3f5eea44d8ee2a65l,0x02bf3e761c74bbb4l,
-            0x50d291cdef565571l },
-          { 0xf4edc290a36dd5fal,0x3015df9556dd6b85l,0x4494926aa5549a16l,
-            0x5de6c59390399e4al },
-          0 },
-        /* 36 << 40 */
-        { { 0x29be11c6ce800998l,0x72bb1752b90360d9l,0x2c1931975a4ad590l,
-            0x2ba2f5489fc1dbc0l },
-          { 0x7fe4eebbe490ebe0l,0x12a0a4cd7fae11c0l,0x7197cf81e903ba37l,
-            0xcf7d4aa8de1c6dd8l },
-          0 },
-        /* 37 << 40 */
-        { { 0x961fa6317e249e7bl,0x5c4f707796caed50l,0x6b176e62d7e50885l,
-            0x4dd5de72f390cbecl },
-          { 0x91fa29954b2bd762l,0x80427e6395b8dadel,0xd565bf1de2c34743l,
-            0x911da39d16e6c841l },
-          0 },
-        /* 39 << 40 */
-        { { 0x48365465802ff016l,0x6d2a561f71beece6l,0xdd299ce6f9707052l,
-            0x62a32698a23407bbl },
-          { 0x1d55bdb147004afbl,0xfadec124369b1084l,0x1ce78adf291c89f7l,
-            0x9f2eaf03278bc529l },
-          0 },
-        /* 40 << 40 */
-        { { 0x92af6bf43fd5684cl,0x2b26eecf80360aa1l,0xbd960f3000546a82l,
-            0x407b3c43f59ad8fel },
-          { 0x86cae5fe249c82bal,0x9e0faec72463744cl,0x87f551e894916272l,
-            0x033f93446ceb0615l },
-          0 },
-        /* 41 << 40 */
-        { { 0x04658ad212dba0cel,0x9e600624068822f0l,0x84661f11b26d368bl,
-            0xbca867d894ebb87al },
-          { 0x79506dc42f1bad89l,0x1a8322d3ebcbe7a1l,0xb4f1e102ac197178l,
-            0x29a950b779f7198cl },
-          0 },
-        /* 43 << 40 */
-        { { 0x19a6fb0984a3d1d5l,0x6c75c3a2ba5f5307l,0x7983485bf9698447l,
-            0x689f41b88b1cdc1el },
-          { 0x18f6fbd74c1979d0l,0x3e6be9a27a0b6708l,0x06acb615f63d5a8al,
-            0x8a817c098d0f64b1l },
-          0 },
-        /* 44 << 40 */
-        { { 0x1e5eb0d18be82e84l,0x89967f0e7a582fefl,0xbcf687d5a6e921fal,
-            0xdfee4cf3d37a09bal },
-          { 0x94f06965b493c465l,0x638b9a1c7635c030l,0x7666786466f05e9fl,
-            0xccaf6808c04da725l },
-          0 },
-        /* 45 << 40 */
-        { { 0xa9b3479b1b53a173l,0xc041eda3392eddc0l,0xdb8f804755edd7eel,
-            0xaf1f7a37ab60683cl },
-          { 0x9318603a72c0accbl,0xab1bb9fe401cbf3cl,0xc40e991e88afe245l,
-            0x9298a4580d06ac35l },
-          0 },
-        /* 46 << 40 */
-        { { 0x58e127d5036c2fe7l,0x5fe5020555b93361l,0xc1373d850f74a045l,
-            0x28cd79dbe8228e4bl },
-          { 0x0ae82320c2018d9al,0xf6d0049c78f8016al,0x381b6fe2149b31fbl,
-            0x33a0e8adec3cfbcfl },
-          0 },
-        /* 47 << 40 */
-        { { 0x23a6612e9eab5da7l,0xb645fe29d94d6431l,0xe3d74594ca1210c4l,
-            0xdc1376bceeca0674l },
-          { 0xfd40dfef657f0154l,0x7952a548d52cbac5l,0x0ee189583685ad28l,
-            0xd13639409ba9ca46l },
-          0 },
-        /* 48 << 40 */
-        { { 0xca2eb690768fccfcl,0xf402d37db835b362l,0x0efac0d0e2fdfccel,
-            0xefc9cdefb638d990l },
-          { 0x2af12b72d1669a8bl,0x33c536bc5774ccbdl,0x30b21909fb34870el,
-            0xc38fa2f77df25acal },
-          0 },
-        /* 49 << 40 */
-        { { 0x1337902f1c982cd6l,0x222e08fe14ec53eal,0x6c8abd0d330ef3e5l,
-            0xeb59e01531f6fd9dl },
-          { 0xd74ae554a8532df4l,0xbc010db1ab44c83el,0xe98016561b8f9285l,
-            0x65a9612783acc546l },
-          0 },
-        /* 51 << 40 */
-        { { 0x36a8b0a76770cfb1l,0x3338d52f9bb578fcl,0x5136c785f5ed12a4l,
-            0x652d47ed87bf129el },
-          { 0x9c6c827e6067c2d0l,0x61fc2f410345533al,0x2d7fb182130cea19l,
-            0x71a0186330b3ef85l },
-          0 },
-        /* 52 << 40 */
-        { { 0x74c5f02bbf81f3f5l,0x0525a5aeaf7e4581l,0x88d2aaba433c54ael,
-            0xed9775db806a56c5l },
-          { 0xd320738ac0edb37dl,0x25fdb6ee66cc1f51l,0xac661d1710600d76l,
-            0x931ec1f3bdd1ed76l },
-          0 },
-        /* 53 << 40 */
-        { { 0xb81e239161faa569l,0xb379f759bb40eebfl,0x9f2fd1b2a2c54549l,
-            0x0a968f4b0d6ba0ael },
-          { 0xaa869e6eedfe8c75l,0x0e36b298645ab173l,0x5a76282b0bcdefd7l,
-            0x9e949331d05293f2l },
-          0 },
-        /* 55 << 40 */
-        { { 0xc1cfa9a1c59fac6el,0x2648bffcb72747cel,0x5f8a39805f2e2637l,
-            0x8bd3a8eb73e65758l },
-          { 0xd9c43f1df14381a7l,0xecc1c3b0d6a86c10l,0xffcf4fa8a4a6dc74l,
-            0x7304fa834cea0a46l },
-          0 },
-        /* 57 << 40 */
-        { { 0x4460760c34dca952l,0xeac9cf2444c70444l,0xb879297b8493c87el,
-            0x295941a54b2dccb7l },
-          { 0x1e5cecede58721cdl,0xc8b58db74ca0d12bl,0x1927965c6da1d034l,
-            0x7220b02839ed1369l },
-          0 },
-        /* 59 << 40 */
-        { { 0xc38746c83c2e34b6l,0x9f27362e38a51042l,0x26febec02067afebl,
-            0xd9c4e15544e7371fl },
-          { 0x6035f469f92930d1l,0xe6ed7c08b4431b8bl,0xa25bf5903e16410dl,
-            0x147d83368adf4c18l },
-          0 },
-        /* 60 << 40 */
-        { { 0x7f01c9ecaa80ba59l,0x3083411a68538e51l,0x970370f1e88128afl,
-            0x625cc3db91dec14bl },
-          { 0xfef9666c01ac3107l,0xb2a8d577d5057ac3l,0xb0f2629992be5df7l,
-            0xf579c8e500353924l },
-          0 },
-        /* 61 << 40 */
-        { { 0xbd9398d6ca02669fl,0x896e053bf9ad11a1l,0xe024b699a3556f9fl,
-            0x23b4b96ad53cbca3l },
-          { 0x549d2d6c89733dd6l,0x3dae193f394f3179l,0x8bf7ec1cdfeda825l,
-            0xf6a1db7a8a4844b4l },
-          0 },
-        /* 63 << 40 */
-        { { 0x3b5403d56437a027l,0xda32bbd233ed30aal,0xd2ad3baa906de0cal,
-            0x3b6df514533f736el },
-          { 0x986f1cab5df9b9c4l,0x41cd2088970d330el,0xaae7c2238c20a923l,
-            0x52760a6e1e951dc0l },
-          0 },
-        /* 64 << 40 */
-        { { 0xb8fa3d931341ed7al,0x4223272ca7b59d49l,0x3dcb194783b8c4a4l,
-            0x4e413c01ed1302e4l },
-          { 0x6d999127e17e44cel,0xee86bf7533b3adfbl,0xf6902fe625aa96cal,
-            0xb73540e4e5aae47dl },
-          0 },
-        /* 65 << 40 */
-        { { 0x55318a525e34036cl,0xc3acafaaf9884e3fl,0xe5ba15cea042ba04l,
-            0x56a1d8960ada550el },
-          { 0xa5198cae87b76764l,0xd079d1f0b6fd84fbl,0xb22b637bcbe363edl,
-            0xbe8ab7d64499deaal },
-          0 },
-        /* 71 << 40 */
-        { { 0xbe8eba5eb4925f25l,0x00f8bf582e3159d6l,0xb1aa24fa18856070l,
-            0x22ea8b74e4c30b22l },
-          { 0x512f633e55bbe4e8l,0x82ba62318678aee9l,0xea05da90fdf72b7el,
-            0x616b9bc7a4fc65eel },
-          0 },
-        /* 77 << 40 */
-        { { 0xe31ee3b3b7c221e7l,0x10353824e353fa43l,0x9d2f3df69dd2a86fl,
-            0x8a12ab9322ccffecl },
-          { 0x25c8e326d666f9e5l,0x33ea98a0598da7fbl,0x2fc1de0917f74e17l,
-            0x0d0b6c7a35efb211l },
-          0 },
-        /* 83 << 40 */
-        { { 0x22a82c6c804e6ecel,0x824a170b1d8fce9el,0x621802becee65ed0l,
-            0x4a4e9e7895ec4285l },
-          { 0x8da0988fa8940b7al,0xaff89c5b86445aa5l,0x386fdbdad689cde9l,
-            0x3aeaae7d9f5caaccl },
-          0 },
-        /* 89 << 40 */
-        { { 0xe9cb9e68a7b62f4cl,0x515cae0ec3b7092el,0xb8abec354b491f52l,
-            0x672673fd01eeabc1l },
-          { 0x65e5739f7ad6e8a1l,0xc2da8e003d91b2f9l,0xcc43229cced84319l,
-            0x0f8cbf9574ccf2d1l },
-          0 },
-        /* 95 << 40 */
-        { { 0xb03d1cfb1b2f872al,0x88aef4670872b6f7l,0xaafe55e48ea9170cl,
-            0xd5cc4875f24aa689l },
-          { 0x7e5732908458ce84l,0xef4e143d58bfc16dl,0xc58626efaa222836l,
-            0x01c60ec0ca5e0cb8l },
-          0 },
-        /* 101 << 40 */
-        { { 0x123901aa36337c09l,0x1697acadd2f5e675l,0xc0a1ddd022fe2bael,
-            0xf68ea88cff0210ddl },
-          { 0x665d11e014168709l,0x912a575f45f25321l,0x7e7ed38070c78934l,
-            0x663d692cb0a46322l },
-          0 },
-        /* 107 << 40 */
-        { { 0x912ab8bd8642cba4l,0x97fab1a3b6b50b73l,0x76666b3cb86ef354l,
-            0x16d41330fa5ecce9l },
-          { 0x77c7c138c7da404bl,0xc6508cb78c983fb0l,0xe5881733f9004984l,
-            0x76dea7794182c7abl },
-          0 },
-        /* 113 << 40 */
-        { { 0x16db18583556b765l,0x39c18c200263755al,0x7b6691f591c15201l,
-            0x4e4c17b168514ea9l },
-          { 0xacbe449e06f5f20al,0xeb9119d2541ddfb6l,0x2f6e687bf2eac86fl,
-            0xb161471ec14ac508l },
-          0 },
-        /* 116 << 40 */
-        { { 0x58846d32c4744733l,0x40517c71379f9e34l,0x2f65655f130ef6cal,
-            0x526e4488f1f3503fl },
-          { 0x8467bd177ee4a976l,0x1d9dc913921363d1l,0xd8d24c33b069e041l,
-            0x5eb5da0a2cdf7f51l },
-          0 },
-        /* 119 << 40 */
-        { { 0x81c2cc32951ab3e7l,0xc86d9a109b0c7e87l,0x0b7a18bd606ef408l,
-            0x099b5bbfe6c2251el },
-          { 0x46d627d0bfce880fl,0xbfaddcbbe1c6865al,0xa9ab6183d2bb9a00l,
-            0x23cb9a2720ad9789l },
-          0 },
-        /* 125 << 40 */
-        { { 0x1592d0630c25fbebl,0x13869ec24995a3fal,0x6413f494861d0a73l,
-            0xa3b782342f9f1b89l },
-          { 0x113689e2b6cad351l,0x53be2014a873dcc1l,0xccf405e0c6bb1be7l,
-            0x4fff7b4ca9061ca9l },
-          0 },
-    },
-    {
-        /* 0 << 48 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 48 */
-        { { 0xcc7a64880a750c0fl,0x39bacfe34e548e83l,0x3d418c760c110f05l,
-            0x3e4daa4cb1f11588l },
-          { 0x2733e7b55ffc69ffl,0x46f147bc92053127l,0x885b2434d722df94l,
-            0x6a444f65e6fc6b7cl },
-          0 },
-        /* 3 << 48 */
-        { { 0x6d0b16f4bdaedfbdl,0x23fd326086746cedl,0x8bfb1d2fff4b3e17l,
-            0xc7f2ec2d019c14c8l },
-          { 0x3e0832f245104b0dl,0x5f00dafbadea2b7el,0x29e5cf6699fbfb0fl,
-            0x264f972361827cdal },
-          0 },
-        /* 4 << 48 */
-        { { 0x97b14f7ea90567e6l,0x513257b7b6ae5cb7l,0x85454a3c9f10903dl,
-            0xd8d2c9ad69bc3724l },
-          { 0x38da93246b29cb44l,0xb540a21d77c8cbacl,0x9bbfe43501918e42l,
-            0xfffa707a56c3614el },
-          0 },
-        /* 5 << 48 */
-        { { 0x6eb1a2f3e30bc27fl,0xe5f0c05ab0836511l,0x4d741bbf4965ab0el,
-            0xfeec41ca83464bbdl },
-          { 0x1aca705f99d0b09fl,0xc5d6cc56f42da5fal,0x49964eddcc52b931l,
-            0x8ae59615c884d8d8l },
-          0 },
-        /* 7 << 48 */
-        { { 0xf634b57b39f8868al,0xe27f4fd475cc69afl,0xa47e58cbd0d5496el,
-            0x8a26793fd323e07fl },
-          { 0xc61a9b72fa30f349l,0x94c9d9c9b696d134l,0x792beca85880a6d1l,
-            0xbdcc4645af039995l },
-          0 },
-        /* 9 << 48 */
-        { { 0xce7ef8e58c796c3cl,0x9adaae84dd66e57al,0x784ae13e45227f33l,
-            0xb046c5b82a85e757l },
-          { 0xb7aa50aeec37631fl,0xbedc4fca3b300758l,0x0f82567e0ac9700bl,
-            0x1071d9d44ff5f8d2l },
-          0 },
-        /* 10 << 48 */
-        { { 0x61360ee99e240d18l,0x057cdcacb4b94466l,0xe7667cd12fe5325cl,
-            0x1fa297b521974e3bl },
-          { 0xfa4081e7db083d76l,0x31993be6f206bd15l,0x8949269b14c19f8cl,
-            0x21468d72a9d92357l },
-          0 },
-        /* 11 << 48 */
-        { { 0xd09ef6c4e51a2811l,0x39f6862bb8fb66b9l,0x64e77f8d22dfaa99l,
-            0x7b10504461b08aacl },
-          { 0x71704e4c4a7df332l,0xd09734342ffe015bl,0xab0eaf4408d3020el,
-            0x28b1909eed63b97al },
-          0 },
-        /* 13 << 48 */
-        { { 0x2f3fa882cdadcd4fl,0xa4ef68595f631995l,0xe52ca2f9e531766fl,
-            0x20af5c3057e2c1d3l },
-          { 0x1e4828f6e51e94b8l,0xf900a1751a2f5d4fl,0xe831adb3392c58a0l,
-            0x4c5a90ca1b6e5866l },
-          0 },
-        /* 15 << 48 */
-        { { 0x5f3dcba86182827cl,0xd1a448ddbd7e7252l,0x2d8f96fcf493b815l,
-            0xba0a4c263b0aa95fl },
-          { 0x88a1514063a0007fl,0x9564c25e6a9c5846l,0x5a4d7b0fdc0fcbcal,
-            0x2275daa33f8a740el },
-          0 },
-        /* 16 << 48 */
-        { { 0x83f49167ceca9754l,0x426d2cf64b7939a0l,0x2555e355723fd0bfl,
-            0xa96e6d06c4f144e2l },
-          { 0x4768a8dd87880e61l,0x15543815e508e4d5l,0x09d7e772b1b65e15l,
-            0x63439dd6ac302fa0l },
-          0 },
-        /* 17 << 48 */
-        { { 0x159591cc0461086bl,0xb695aa9495e66e51l,0x2d4c946779ded531l,
-            0xbd2482ba89c2be79l },
-          { 0x8ee2658aa20bbf19l,0xc000528a32247917l,0xd924be4affeae845l,
-            0x51312bebed992c8bl },
-          0 },
-        /* 19 << 48 */
-        { { 0x3a01b958dc752bd9l,0x2babdbc20c215d45l,0xe689d79a131641c1l,
-            0x48e8f0da80e05ed4l },
-          { 0x4b505feb77bb70c4l,0xefbd3e2bb6057ef7l,0x7583e22dce603ca5l,
-            0xfbe3b1f22c5c70c7l },
-          0 },
-        /* 21 << 48 */
-        { { 0x8ec1ecf029e5e35al,0x2f3168e58645c2b3l,0xe9297362c7f94cb2l,
-            0x4fbf1466d1c90b39l },
-          { 0x3e4f7656920bae2al,0x805d04b9f1beb172l,0x729a7208dbdbd4b4l,
-            0x1aade45687aeca53l },
-          0 },
-        /* 23 << 48 */
-        { { 0xb0ff1f541934a508l,0x19e1397604bbf31al,0xb2a8e6033717a6b4l,
-            0xd601e45d0ef12cb9l },
-          { 0x563f0af5b515e98el,0x9b129db633984f9bl,0xe34aba2fa47e4a65l,
-            0xb56f82d19e3f9d82l },
-          0 },
-        /* 25 << 48 */
-        { { 0x0203effdb1209b86l,0x21f063edb19d6cbfl,0x59f53476980f275bl,
-            0x202456d7b7ac5e80l },
-          { 0xe5a8c05f4900edc9l,0x04c08eb470f01e86l,0xf74ac2241dcd98cel,
-            0x7e77cc0ce2e830dbl },
-          0 },
-        /* 27 << 48 */
-        { { 0x74e37234a9747edel,0x4fc9fbb1361b1013l,0xe7b533733cf357efl,
-            0x6aa2dd2c991c4193l },
-          { 0x7887e4d2a770917al,0xdd1809b4c20d24cbl,0x004cd7c38e9c2d3el,
-            0xc77c5baba9970abel },
-          0 },
-        /* 28 << 48 */
-        { { 0x20ac0351d598d710l,0x272c4166cb3a4da4l,0xdb82fe1aca71de1fl,
-            0x746e79f2d8f54b0fl },
-          { 0x6e7fc7364b573e9bl,0x75d03f46fd4b5040l,0x5c1cc36d0b98d87bl,
-            0x513ba3f11f472da1l },
-          0 },
-        /* 29 << 48 */
-        { { 0x52927eaac3af237fl,0xfaa06065d7398767l,0x042e72b497c6ce0bl,
-            0xdaed0cc40a9f2361l },
-          { 0xddc2e11c2fc1bb4al,0x631da5770c1a9ef8l,0x8a4cfe44680272bfl,
-            0xc76b9f7262fb5cc3l },
-          0 },
-        /* 31 << 48 */
-        { { 0x248f814538b3aae3l,0xb5345864bc204334l,0x66d6b5bc1d127524l,
-            0xe312080d14f572d3l },
-          { 0x13ed15a716abafebl,0x6f18ce27dba967bel,0x96c9e826ef08552dl,
-            0x2c191b06be2b63e0l },
-          0 },
-        /* 33 << 48 */
-        { { 0xde4be45dc115ca51l,0xa028cafe934dabd6l,0x7e875663d1c0f8c5l,
-            0xa8e32ab063d17473l },
-          { 0x33f55bd5543199aal,0x79d2c937a2071d6el,0xa6a6758ceff16f28l,
-            0x9c5f93ef87d85201l },
-          0 },
-        /* 34 << 48 */
-        { { 0x7f2e440381e9ede3l,0x243c3894caf6df0al,0x7c605bb11c073b11l,
-            0xcd06a541ba6a4a62l },
-          { 0x2916894949d4e2e5l,0x33649d074af66880l,0xbfc0c885e9a85035l,
-            0xb4e52113fc410f4bl },
-          0 },
-        /* 35 << 48 */
-        { { 0xe86f21bc3ad4c81el,0x53b408403a37dcebl,0xaa606087383402cdl,
-            0xc248caf185452b1dl },
-          { 0x38853772576b57cdl,0xe2798e5441b7a6edl,0x7c2f1eed95ef4a33l,
-            0xccd7e776adb1873cl },
-          0 },
-        /* 36 << 48 */
-        { { 0xdca3b70678a6513bl,0x92ea4a2a9edb1943l,0x02642216db6e2dd8l,
-            0x9b45d0b49fd57894l },
-          { 0x114e70dbc69d11ael,0x1477dd194c57595fl,0xbc2208b4ec77c272l,
-            0x95c5b4d7db68f59cl },
-          0 },
-        /* 37 << 48 */
-        { { 0xd978bb791c61030al,0xa47325d2218222f3l,0x65ad4d4832e67d97l,
-            0x31e4ed632e0d162al },
-          { 0x7308ea317f76da37l,0xcfdffe87d93f35d8l,0xf4b2d60ee6f96cc4l,
-            0x8028f3bd0117c421l },
-          0 },
-        /* 39 << 48 */
-        { { 0x7df80cbb9543edb6l,0xa07a54df40b0b3bcl,0xacbd067cc1888488l,
-            0x61ad61318a00c721l },
-          { 0x67e7599ebe2e6fe6l,0x8349d568f7270e06l,0x5630aabc307bc0c7l,
-            0x97210b3f71af442fl },
-          0 },
-        /* 40 << 48 */
-        { { 0xfe541fa47ea67c77l,0x952bd2afe3ea810cl,0x791fef568d01d374l,
-            0xa3a1c6210f11336el },
-          { 0x5ad0d5a9c7ec6d79l,0xff7038af3225c342l,0x003c6689bc69601bl,
-            0x25059bc745e8747dl },
-          0 },
-        /* 41 << 48 */
-        { { 0x58bdabb7ef701b5fl,0x64f987aee00c3a96l,0x533b391e2d585679l,
-            0x30ad79d97a862e03l },
-          { 0xd941471e8177b261l,0x33f65cb856a9018el,0x985ce9f607759fc4l,
-            0x9b085f33aefdbd9el },
-          0 },
-        /* 43 << 48 */
-        { { 0xab2fa51a9c43ee15l,0x457f338263f30575l,0xce8dcd863e75a6e0l,
-            0x67a03ab86e70421al },
-          { 0xe72c37893e174230l,0x45ffff6c066f4816l,0x3a3dd84879a2d4a7l,
-            0xefa4b7e68b76c24cl },
-          0 },
-        /* 44 << 48 */
-        { { 0x9a75c80676cb2566l,0x8f76acb1b24892d9l,0x7ae7b9cc1f08fe45l,
-            0x19ef73296a4907d8l },
-          { 0x2db4ab715f228bf0l,0xf3cdea39817032d7l,0x0b1f482edcabe3c0l,
-            0x3baf76b4bb86325cl },
-          0 },
-        /* 45 << 48 */
-        { { 0xd6be8f00e39e056al,0xb58f87a6232fa3bcl,0xd5cb09dc6b18c772l,
-            0x3177256da8e7e17bl },
-          { 0x1877fd34230bf92cl,0x6f9031175a36f632l,0x526a288728e2c9d9l,
-            0xc373fc94415ec45cl },
-          0 },
-        /* 46 << 48 */
-        { { 0xd49065e010089465l,0x3bab5d298e77c596l,0x7636c3a6193dbd95l,
-            0xdef5d294b246e499l },
-          { 0xb22c58b9286b2475l,0xa0b93939cd80862bl,0x3002c83af0992388l,
-            0x6de01f9beacbe14cl },
-          0 },
-        /* 47 << 48 */
-        { { 0x70fa6e2a2bf5e373l,0x501691739271694cl,0xd6ebb98c5d2ed9f1l,
-            0x11fd0b3f225bf92dl },
-          { 0x51ffbcea1e3d5520l,0xa7c549875513ad47l,0xe9689750b431d46dl,
-            0x6e69fecbb620cb9al },
-          0 },
-        /* 48 << 48 */
-        { { 0x6aac688eadd70482l,0x708de92a7b4a4e8al,0x75b6dd73758a6eefl,
-            0xea4bf352725b3c43l },
-          { 0x10041f2c87912868l,0xb1b1be95ef09297al,0x19ae23c5a9f3860al,
-            0xc4f0f839515dcf4bl },
-          0 },
-        /* 49 << 48 */
-        { { 0xf3c22398e04b5734l,0x4fba59b275f2579dl,0xbf95182d691901b3l,
-            0x4c139534eb599496l },
-          { 0xf3f821de33b77e8bl,0x66e580743785d42fl,0xe3ba3d5abdc89c2dl,
-            0x7ee988bdd19f37b9l },
-          0 },
-        /* 51 << 48 */
-        { { 0xe9ba62ca2ee53eb0l,0x64295ae23401d7dal,0x70ed8be24e493580l,
-            0x702caa624502732fl },
-          { 0xb1f4e21278d0cedfl,0x130b114bdc97057bl,0x9c5d0bd3c38c77b5l,
-            0xd9d641e18bad68e7l },
-          0 },
-        /* 52 << 48 */
-        { { 0xc71e27bf8538a5c6l,0x195c63dd89abff17l,0xfd3152851b71e3dal,
-            0x9cbdfda7fa680fa0l },
-          { 0x9db876ca849d7eabl,0xebe2764b3c273271l,0x663357e3f208dceal,
-            0x8c5bd833565b1b70l },
-          0 },
-        /* 53 << 48 */
-        { { 0x7c2dea1d122aebd4l,0x090bee4a138c1e4dl,0x94a9ffe59e4aca6cl,
-            0x8f3212ba5d405c7fl },
-          { 0x6618185f180b5e85l,0x76298d46f455ab9fl,0x0c804076476b2d88l,
-            0x45ea9d03d5a40b39l },
-          0 },
-        /* 55 << 48 */
-        { { 0xdf325ac76a2ed772l,0x35da47ccb0da2765l,0x94ce6f460bc9b166l,
-            0xe0fc82fb5f7f3628l },
-          { 0x2b26d588c055f576l,0xb9d37c97ec2bae98l,0xffbbead856908806l,
-            0xa8c2df87437f4c84l },
-          0 },
-        /* 57 << 48 */
-        { { 0x47d11c3528430994l,0x0183df71cf13d9d3l,0x98604c89aa138fe5l,
-            0xb1432e1c32c09aa1l },
-          { 0xf19bc45d99bd5e34l,0xb198be72108e9b89l,0xee500ae9dacde648l,
-            0x5936cf98746870a9l },
-          0 },
-        /* 59 << 48 */
-        { { 0x6d8efb98ed1d5a9bl,0x2e0b08e697f778fal,0xda728454dc5e0835l,
-            0x2c28a45f8e3651c4l },
-          { 0x667fab6f7ee77088l,0xd94429c8f29a94b4l,0xd83d594d9deea5b2l,
-            0x2dc08ccbbea58080l },
-          0 },
-        /* 60 << 48 */
-        { { 0xba5514df3fd165e8l,0x499fd6a9061f8811l,0x72cd1fe0bfef9f00l,
-            0x120a4bb979ad7e8al },
-          { 0xf2ffd0955f4a5ac5l,0xcfd174f195a7a2f0l,0xd42301ba9d17baf1l,
-            0xd2fa487a77f22089l },
-          0 },
-        /* 61 << 48 */
-        { { 0xfb5f53ba20a9a01el,0x3adb174fd20d6a9cl,0x6db8bb6d80e0f64fl,
-            0x596e428df6a26f76l },
-          { 0xbab1f846e6a4e362l,0x8bdb22af9b1becbdl,0x62b48335f31352adl,
-            0xd72c26409634f727l },
-          0 },
-        /* 63 << 48 */
-        { { 0xaaa61cb22b1ec1c3l,0x3b5156722cb6f00el,0x67d1be0a8bf83f60l,
-            0x88f1627aa4b804bcl },
-          { 0xc52b11a7cdade2abl,0xa6a8b71a606a4e9dl,0x04e0e6697b900551l,
-            0x35cfa33c8d5ad0d2l },
-          0 },
-        /* 64 << 48 */
-        { { 0xb93452381d531696l,0x57201c0088cdde69l,0xdde922519a86afc7l,
-            0xe3043895bd35cea8l },
-          { 0x7608c1e18555970dl,0x8267dfa92535935el,0xd4c60a57322ea38bl,
-            0xe0bf7977804ef8b5l },
-          0 },
-        /* 65 << 48 */
-        { { 0x375ca189b60f0d5al,0xc9458cf949a78362l,0x61c1c5024262c03al,
-            0x299353db4363d5bel },
-          { 0xe3565124dac407fel,0x16ea66cd5b93c532l,0xe5c6aec2749df8e3l,
-            0x59181317ce3ee4bfl },
-          0 },
-        /* 71 << 48 */
-        { { 0xd46ea34af41c2a3cl,0x9936184916545c98l,0xd7cb800ccf2498b4l,
-            0xe71d088d9353fe87l },
-          { 0x43443cbeae2e172cl,0x77131656ca905cb3l,0x76471fd1dce63594l,
-            0x346b1d1738f5e264l },
-          0 },
-        /* 77 << 48 */
-        { { 0x22b1e639f6d0a419l,0x8bbb1fad7cea278cl,0xf07f6c01370cc86al,
-            0x661bd027d39b837fl },
-          { 0x042c7a69de606098l,0x93433b154e44eb12l,0x20f44ada88d8bfe8l,
-            0xb44f66e64ccbfab6l },
-          0 },
-        /* 83 << 48 */
-        { { 0x1cc32158583d9745l,0x9306223cad1c2201l,0x76aa8d0995748039l,
-            0x29425391707e9b59l },
-          { 0x8501c0d4487cdf9el,0xbe08e89c205c5611l,0xa950400b04ccc48bl,
-            0xb614b69b637e966bl },
-          0 },
-        /* 89 << 48 */
-        { { 0xd9c3c1238ffa5c4bl,0xc65765f7f3593988l,0x9a7e5d2728242119l,
-            0x0ad27b5097ad7620l },
-          { 0x154cc5eb413a8b23l,0xae93d8de7afa8254l,0x9ce5116cab9907b5l,
-            0x9a163d78063103b9l },
-          0 },
-        /* 95 << 48 */
-        { { 0x5c4c299291086d2al,0x42c6ca9de8e2d951l,0xe67ecf93dd353f30l,
-            0xba54557fe7167c2el },
-          { 0x04a7eb2db734c779l,0x8f345605e300711al,0x4811c1ad67b27de6l,
-            0xb7ac8e842731d5f0l },
-          0 },
-        /* 101 << 48 */
-        { { 0xee33a1d8e449ac46l,0x2500ba0aaaebfa2dl,0x8fb914ebc424eff4l,
-            0x3a36545d3989255el },
-          { 0xd24f2484761235e6l,0x2fc5d5ddd9b2c04bl,0x73660f86070ab0dbl,
-            0x2e266d0479d20c7bl },
-          0 },
-        /* 107 << 48 */
-        { { 0x143752d5316d19a3l,0x56a55e01915497b8l,0x44ba4b2609a5fd15l,
-            0xe4fc3e7fd9bee4eel },
-          { 0x6f9d8609878a9f26l,0xdf36b5bd2ede7a20l,0x8e03e712a9a3e435l,
-            0x4ced555b56546d33l },
-          0 },
-        /* 113 << 48 */
-        { { 0x89a6aaab0882717el,0x56a9736b43fa5153l,0xdb07dcc9d0e1fb1al,
-            0xe7c986d34145e227l },
-          { 0x57be66abb10dad51l,0xa47b964e4aa01ea7l,0xd851d9f36bb837cbl,
-            0x9851ab3d652e13f7l },
-          0 },
-        /* 116 << 48 */
-        { { 0x22b88a805616ee30l,0xfb09548fe7ab1083l,0x8ad6ab0d511270cdl,
-            0x61f6c57a6924d9abl },
-          { 0xa0f7bf7290aecb08l,0x849f87c90df784a4l,0x27c79c15cfaf1d03l,
-            0xbbf9f675c463facel },
-          0 },
-        /* 119 << 48 */
-        { { 0x65512fb716dd6ce1l,0xfa76ebc960d53b35l,0x31e5322e19ada3bel,
-            0x7e259b75d0ccc3cdl },
-          { 0xd36d03f0e025fd69l,0xbefab782eea9e5f3l,0x1569969dd09ce6a7l,
-            0x2df5396178c385b0l },
-          0 },
-        /* 125 << 48 */
-        { { 0x4201652fce0ccac7l,0x12f8e93df1d29d2dl,0x6c2ac9b2220f00c1l,
-            0x4ee6a685a850baa9l },
-          { 0x2c2371f163ee8829l,0xddff16488f464433l,0xeab6cd8869a2c413l,
-            0xcae34beb85e4c2a8l },
-          0 },
-    },
-    {
-        /* 0 << 56 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 56 */
-        { { 0xc7913e91991724f3l,0x5eda799c39cbd686l,0xddb595c763d4fc1el,
-            0x6b63b80bac4fed54l },
-          { 0x6ea0fc697e5fb516l,0x737708bad0f1c964l,0x9628745f11a92ca5l,
-            0x61f379589a86967al },
-          0 },
-        /* 3 << 56 */
-        { { 0x46a8c4180d738dedl,0x6f1a5bb0e0de5729l,0xf10230b98ba81675l,
-            0x32c6f30c112b33d4l },
-          { 0x7559129dd8fffb62l,0x6a281b47b459bf05l,0x77c1bd3afa3b6776l,
-            0x0709b3807829973al },
-          0 },
-        /* 4 << 56 */
-        { { 0x8c26b232a3326505l,0x38d69272ee1d41bfl,0x0459453effe32afal,
-            0xce8143ad7cb3ea87l },
-          { 0x932ec1fa7e6ab666l,0x6cd2d23022286264l,0x459a46fe6736f8edl,
-            0x50bf0d009eca85bbl },
-          0 },
-        /* 5 << 56 */
-        { { 0x0b825852877a21ecl,0x300414a70f537a94l,0x3f1cba4021a9a6a2l,
-            0x50824eee76943c00l },
-          { 0xa0dbfcecf83cba5dl,0xf953814893b4f3c0l,0x6174416248f24dd7l,
-            0x5322d64de4fb09ddl },
-          0 },
-        /* 7 << 56 */
-        { { 0xa337c447f1f0ced1l,0x800cc7939492dd2bl,0x4b93151dbea08efal,
-            0x820cf3f8de0a741el },
-          { 0xff1982dc1c0f7d13l,0xef92196084dde6cal,0x1ad7d97245f96ee3l,
-            0x319c8dbe29dea0c7l },
-          0 },
-        /* 9 << 56 */
-        { { 0x0ae1d63b0eb919b0l,0xd74ee51da74b9620l,0x395458d0a674290cl,
-            0x324c930f4620a510l },
-          { 0x2d1f4d19fbac27d4l,0x4086e8ca9bedeeacl,0x0cdd211b9b679ab8l,
-            0x5970167d7090fec4l },
-          0 },
-        /* 10 << 56 */
-        { { 0x3420f2c9faf1fc63l,0x616d333a328c8bb4l,0x7d65364c57f1fe4al,
-            0x9343e87755e5c73al },
-          { 0x5795176be970e78cl,0xa36ccebf60533627l,0xfc7c738009cdfc1bl,
-            0xb39a2afeb3fec326l },
-          0 },
-        /* 11 << 56 */
-        { { 0xb7ff1ba16224408al,0xcc856e92247cfc5el,0x01f102e7c18bc493l,
-            0x4613ab742091c727l },
-          { 0xaa25e89cc420bf2bl,0x00a5317690337ec2l,0xd2be9f437d025fc7l,
-            0x3316fb856e6fe3dcl },
-          0 },
-        /* 13 << 56 */
-        { { 0x67332cfc2064cfd1l,0x339c31deb0651934l,0x719b28d52a3bcbeal,
-            0xee74c82b9d6ae5c6l },
-          { 0x0927d05ebaf28ee6l,0x82cecf2c9d719028l,0x0b0d353eddb30289l,
-            0xfe4bb977fddb2e29l },
-          0 },
-        /* 15 << 56 */
-        { { 0xe10b2ab817a91cael,0xb89aab6508e27f63l,0x7b3074a7dba3ddf9l,
-            0x1c20ce09330c2972l },
-          { 0x6b9917b45fcf7e33l,0xe6793743945ceb42l,0x18fc22155c633d19l,
-            0xad1adb3cc7485474l },
-          0 },
-        /* 16 << 56 */
-        { { 0x646f96796424c49bl,0xf888dfe867c241c9l,0xe12d4b9324f68b49l,
-            0x9a6b62d8a571df20l },
-          { 0x81b4b26d179483cbl,0x666f96329511fae2l,0xd281b3e4d53aa51fl,
-            0x7f96a7657f3dbd16l },
-          0 },
-        /* 17 << 56 */
-        { { 0xa7f8b5bf074a30cel,0xd7f52107005a32e6l,0x6f9e090750237ed4l,
-            0x2f21da478096fa2bl },
-          { 0xf3e19cb4eec863a0l,0xd18f77fd9527620al,0x9505c81c407c1cf8l,
-            0x9998db4e1b6ec284l },
-          0 },
-        /* 19 << 56 */
-        { { 0x794e2d5984ac066cl,0xf5954a92e68c69a0l,0x28c524584fd99dccl,
-            0x60e639fcb1012517l },
-          { 0xc2e601257de79248l,0xe9ef6404f12fc6d7l,0x4c4f28082a3b5d32l,
-            0x865ad32ec768eb8al },
-          0 },
-        /* 21 << 56 */
-        { { 0x4f4ddf91b2f1ac7al,0xf99eaabb760fee27l,0x57f4008a49c228e5l,
-            0x090be4401cf713bbl },
-          { 0xac91fbe45004f022l,0xd838c2c2569e1af6l,0xd6c7d20b0f1daaa5l,
-            0xaa063ac11bbb02c0l },
-          0 },
-        /* 23 << 56 */
-        { { 0x54935fcb81d73c9el,0x6d07e9790a5e97abl,0x4dc7b30acf3a6babl,
-            0x147ab1f3170bee11l },
-          { 0x0aaf8e3d9fafdee4l,0xfab3dbcb538a8b95l,0x405df4b36ef13871l,
-            0xf1f4e9cb088d5a49l },
-          0 },
-        /* 25 << 56 */
-        { { 0x43c01b87459afccdl,0x6bd45143b7432652l,0x8473453055b5d78el,
-            0x81088fdb1554ba7dl },
-          { 0xada0a52c1e269375l,0xf9f037c42dc5ec10l,0xc066060794bfbc11l,
-            0xc0a630bbc9c40d2fl },
-          0 },
-        /* 27 << 56 */
-        { { 0x9a730ed44763eb50l,0x24a0e221c1ab0d66l,0x643b6393648748f3l,
-            0x1982daa16d3c6291l },
-          { 0x6f00a9f78bbc5549l,0x7a1783e17f36384el,0xe8346323de977f50l,
-            0x91ab688db245502al },
-          0 },
-        /* 28 << 56 */
-        { { 0x331ab6b56d0bdd66l,0x0a6ef32e64b71229l,0x1028150efe7c352fl,
-            0x27e04350ce7b39d3l },
-          { 0x2a3c8acdc1070c82l,0xfb2034d380c9feefl,0x2d729621709f3729l,
-            0x8df290bf62cb4549l },
-          0 },
-        /* 29 << 56 */
-        { { 0x02f99f33fc2e4326l,0x3b30076d5eddf032l,0xbb21f8cf0c652fb5l,
-            0x314fb49eed91cf7bl },
-          { 0xa013eca52f700750l,0x2b9e3c23712a4575l,0xe5355557af30fbb0l,
-            0x1ada35167c77e771l },
-          0 },
-        /* 31 << 56 */
-        { { 0xdc9f46fc609e4a74l,0x2a44a143ba667f91l,0xbc3d8b95b4d83436l,
-            0xa01e4bd0c7bd2958l },
-          { 0x7b18293273483c90l,0xa79c6aa1a7c7b598l,0xbf3983c6eaaac07el,
-            0x8f18181e96e0d4e6l },
-          0 },
-        /* 33 << 56 */
-        { { 0x0bfc27eeacee5043l,0xae419e732eb10f02l,0x19c028d18943fb05l,
-            0x71f01cf7ff13aa2al },
-          { 0x7790737e8887a132l,0x6751330966318410l,0x9819e8a37ddb795el,
-            0xfecb8ef5dad100b2l },
-          0 },
-        /* 34 << 56 */
-        { { 0x59f74a223021926al,0xb7c28a496f9b4c1cl,0xed1a733f912ad0abl,
-            0x42a910af01a5659cl },
-          { 0x3842c6e07bd68cabl,0x2b57fa3876d70ac8l,0x8a6707a83c53aaebl,
-            0x62c1c51065b4db18l },
-          0 },
-        /* 35 << 56 */
-        { { 0x8de2c1fbb2d09dc7l,0xc3dfed12266bd23bl,0x927d039bd5b27db6l,
-            0x2fb2f0f1103243dal },
-          { 0xf855a07b80be7399l,0xed9327ce1f9f27a8l,0xa0bd99c7729bdef7l,
-            0x2b67125e28250d88l },
-          0 },
-        /* 36 << 56 */
-        { { 0x784b26e88670ced7l,0xe3dfe41fc31bd3b4l,0x9e353a06bcc85cbcl,
-            0x302e290960178a9dl },
-          { 0x860abf11a6eac16el,0x76447000aa2b3aacl,0x46ff9d19850afdabl,
-            0x35bdd6a5fdb2d4c1l },
-          0 },
-        /* 37 << 56 */
-        { { 0xe82594b07e5c9ce9l,0x0f379e5320af346el,0x608b31e3bc65ad4al,
-            0x710c6b12267c4826l },
-          { 0x51c966f971954cf1l,0xb1cec7930d0aa215l,0x1f15598986bd23a8l,
-            0xae2ff99cf9452e86l },
-          0 },
-        /* 39 << 56 */
-        { { 0xb5a741a76b2515cfl,0x71c416019585c749l,0x78350d4fe683de97l,
-            0x31d6152463d0b5f5l },
-          { 0x7a0cc5e1fbce090bl,0xaac927edfbcb2a5bl,0xe920de4920d84c35l,
-            0x8c06a0b622b4de26l },
-          0 },
-        /* 40 << 56 */
-        { { 0xd34dd58bafe7ddf3l,0x55851fedc1e6e55bl,0xd1395616960696e7l,
-            0x940304b25f22705fl },
-          { 0x6f43f861b0a2a860l,0xcf1212820e7cc981l,0x121862120ab64a96l,
-            0x09215b9ab789383cl },
-          0 },
-        /* 41 << 56 */
-        { { 0x311eb30537387c09l,0xc5832fcef03ee760l,0x30358f5832f7ea19l,
-            0xe01d3c3491d53551l },
-          { 0x1ca5ee41da48ea80l,0x34e71e8ecf4fa4c1l,0x312abd257af1e1c7l,
-            0xe3afcdeb2153f4a5l },
-          0 },
-        /* 43 << 56 */
-        { { 0x2a17747fa6d74081l,0x60ea4c0555a26214l,0x53514bb41f88c5fel,
-            0xedd645677e83426cl },
-          { 0xd5d6cbec96460b25l,0xa12fd0ce68dc115el,0xc5bc3ed2697840eal,
-            0x969876a8a6331e31l },
-          0 },
-        /* 44 << 56 */
-        { { 0x60c36217472ff580l,0xf42297054ad41393l,0x4bd99ef0a03b8b92l,
-            0x501c7317c144f4f6l },
-          { 0x159009b318464945l,0x6d5e594c74c5c6bel,0x2d587011321a3660l,
-            0xd1e184b13898d022l },
-          0 },
-        /* 45 << 56 */
-        { { 0x5ba047524c6a7e04l,0x47fa1e2b45550b65l,0x9419daf048c0a9a5l,
-            0x663629537c243236l },
-          { 0xcd0744b15cb12a88l,0x561b6f9a2b646188l,0x599415a566c2c0c0l,
-            0xbe3f08590f83f09al },
-          0 },
-        /* 46 << 56 */
-        { { 0x9141c5beb92041b8l,0x01ae38c726477d0dl,0xca8b71f3d12c7a94l,
-            0xfab5b31f765c70dbl },
-          { 0x76ae7492487443e9l,0x8595a310990d1349l,0xf8dbeda87d460a37l,
-            0x7f7ad0821e45a38fl },
-          0 },
-        /* 47 << 56 */
-        { { 0xed1d4db61059705al,0xa3dd492ae6b9c697l,0x4b92ee3a6eb38bd5l,
-            0xbab2609d67cc0bb7l },
-          { 0x7fc4fe896e70ee82l,0xeff2c56e13e6b7e3l,0x9b18959e34d26fcal,
-            0x2517ab66889d6b45l },
-          0 },
-        /* 48 << 56 */
-        { { 0xf167b4e0bdefdd4fl,0x69958465f366e401l,0x5aa368aba73bbec0l,
-            0x121487097b240c21l },
-          { 0x378c323318969006l,0xcb4d73cee1fe53d1l,0x5f50a80e130c4361l,
-            0xd67f59517ef5212bl },
-          0 },
-        /* 49 << 56 */
-        { { 0xf145e21e9e70c72el,0xb2e52e295566d2fbl,0x44eaba4a032397f5l,
-            0x5e56937b7e31a7del },
-          { 0x68dcf517456c61e1l,0xbc2e954aa8b0a388l,0xe3552fa760a8b755l,
-            0x03442dae73ad0cdel },
-          0 },
-        /* 51 << 56 */
-        { { 0x3fcbdbce478e2135l,0x7547b5cfbda35342l,0xa97e81f18a677af6l,
-            0xc8c2bf8328817987l },
-          { 0xdf07eaaf45580985l,0xc68d1f05c93b45cbl,0x106aa2fec77b4cacl,
-            0x4c1d8afc04a7ae86l },
-          0 },
-        /* 52 << 56 */
-        { { 0xdb41c3fd9eb45ab2l,0x5b234b5bd4b22e74l,0xda253decf215958al,
-            0x67e0606ea04edfa0l },
-          { 0xabbbf070ef751b11l,0xf352f175f6f06dcel,0xdfc4b6af6839f6b4l,
-            0x53ddf9a89959848el },
-          0 },
-        /* 53 << 56 */
-        { { 0xda49c379c21520b0l,0x90864ff0dbd5d1b6l,0x2f055d235f49c7f7l,
-            0xe51e4e6aa796b2d8l },
-          { 0xc361a67f5c9dc340l,0x5ad53c37bca7c620l,0xda1d658832c756d0l,
-            0xad60d9118bb67e13l },
-          0 },
-        /* 55 << 56 */
-        { { 0xd1183316fd6f7140l,0xf9fadb5bbd8e81f7l,0x701d5e0c5a02d962l,
-            0xfdee4dbf1b601324l },
-          { 0xbed1740735d7620el,0x04e3c2c3f48c0012l,0x9ee29da73455449al,
-            0x562cdef491a836c4l },
-          0 },
-        /* 57 << 56 */
-        { { 0x147ebf01fad097a5l,0x49883ea8610e815dl,0xe44d60ba8a11de56l,
-            0xa970de6e827a7a6dl },
-          { 0x2be414245e17fc19l,0xd833c65701214057l,0x1375813b363e723fl,
-            0x6820bb88e6a52e9bl },
-          0 },
-        /* 59 << 56 */
-        { { 0xe1b6f60c08191224l,0xc4126ebbde4ec091l,0xe1dff4dc4ae38d84l,
-            0xde3f57db4f2ef985l },
-          { 0x34964337d446a1ddl,0x7bf217a0859e77f6l,0x8ff105278e1d13f5l,
-            0xa304ef0374eeae27l },
-          0 },
-        /* 60 << 56 */
-        { { 0xfc6f5e47d19dfa5al,0xdb007de37fad982bl,0x28205ad1613715f5l,
-            0x251e67297889529el },
-          { 0x727051841ae98e78l,0xf818537d271cac32l,0xc8a15b7eb7f410f5l,
-            0xc474356f81f62393l },
-          0 },
-        /* 61 << 56 */
-        { { 0x92dbdc5ac242316bl,0xabe060acdbf4aff5l,0x6e8c38fe909a8ec6l,
-            0x43e514e56116cb94l },
-          { 0x2078fa3807d784f9l,0x1161a880f4b5b357l,0x5283ce7913adea3dl,
-            0x0756c3e6cc6a910bl },
-          0 },
-        /* 63 << 56 */
-        { { 0xa573a4966d17fbc7l,0x0cd1a70a73d2b24el,0x34e2c5cab2676937l,
-            0xe7050b06bf669f21l },
-          { 0xfbe948b61ede9046l,0xa053005197662659l,0x58cbd4edf10124c5l,
-            0xde2646e4dd6c06c8l },
-          0 },
-        /* 64 << 56 */
-        { { 0x332f81088cad38c0l,0x471b7e906bd68ae2l,0x56ac3fb20d8e27a3l,
-            0xb54660db136b4b0dl },
-          { 0x123a1e11a6fd8de4l,0x44dbffeaa37799efl,0x4540b977ce6ac17cl,
-            0x495173a8af60acefl },
-          0 },
-        /* 65 << 56 */
-        { { 0xc48b1478db447d0bl,0xe1b85f5d46104fbbl,0x4ab31e7d991c60b9l,
-            0xaa674a9258a0cfd0l },
-          { 0x179fc2cd316f4297l,0x90c18642dcccbc82l,0x65d4309e56a4c163l,
-            0xf211a9c7145a33ecl },
-          0 },
-        /* 71 << 56 */
-        { { 0x9669170cdc32717fl,0x52d69b5138133e34l,0xaed24e5fb079c3b2l,
-            0xaba44a91a21ea3d2l },
-          { 0xd6814f1938d40105l,0x38289fe463462e7al,0x1793eefa3a80cbf5l,
-            0x05816a0795f29bacl },
-          0 },
-        /* 77 << 56 */
-        { { 0xdca88ad98f850641l,0x8c1152c447999b0dl,0x509f654e654aff33l,
-            0x2228550f08a12f14l },
-          { 0x60fe99dbb6a0ccdbl,0x80d6829bfc2cddccl,0x190f454dd5617aa4l,
-            0x0aea05fe36295d2dl },
-          0 },
-        /* 83 << 56 */
-        { { 0x1de06c8af9bef9a5l,0xe24d85d3fb2d3164l,0x3dbe455e8d203d3el,
-            0x439bee4735ea47a9l },
-          { 0xcc143432784893d7l,0x9b71073bd9bebd00l,0x6c106b343aa2fe88l,
-            0x9df2a42734746f7al },
-          0 },
-        /* 89 << 56 */
-        { { 0x1ad0b3725a8c2168l,0x64e52d6d143f0402l,0xd933c783e320f31fl,
-            0x1ccf90a80ff14f52l },
-          { 0xd3a3133ee1e6d0c0l,0xfd75a2d5b4acc8cal,0x62659b8e5559d171l,
-            0x5087d6e9f13ad52al },
-          0 },
-        /* 95 << 56 */
-        { { 0xb4d647a5deef31a4l,0x95bf4ab180975ea9l,0x2f92d15adf57b03el,
-            0x5ee808ab746b26d6l },
-          { 0x4341597c1082f261l,0x027795eb40c45e95l,0xcb77744b3b690c30l,
-            0xdd87c084af3f88d1l },
-          0 },
-        /* 101 << 56 */
-        { { 0x469f177572109785l,0xf365e55123f84d6cl,0x8006a9c28a046dbbl,
-            0x1b9fbe892fa09f52l },
-          { 0xac18a88016075e9el,0x4a3069bc1e3fd628l,0x20c61eaa60c61c14l,
-            0x315b59daf61f004bl },
-          0 },
-        /* 107 << 56 */
-        { { 0x0a94387f26d04857l,0x952a4ebc43d6de95l,0xb422e15cf14abdfal,
-            0x5b7a0153324ef90cl },
-          { 0x6aefa20e9826ec5bl,0x0e529886ad2fe161l,0xb710a74ec0d416e8l,
-            0x6cf4b0a5fb6c90bcl },
-          0 },
-        /* 113 << 56 */
-        { { 0x822aea4031979d3bl,0xb504eafde215a109l,0xa8761ead84bf2377l,
-            0xb55c1e55efb3d942l },
-          { 0xd01f9b0212b7f17bl,0x41b62c2a891bfbbfl,0x50800e6b08938149l,
-            0x527b50a9b0a55d82l },
-          0 },
-        /* 116 << 56 */
-        { { 0x6bc84d8d1d9ce3c4l,0x53b465072a308df0l,0x6c3da9bfca79c88al,
-            0x9636ad9c36372acfl },
-          { 0x8840e92c425ef14cl,0x863191f96af3225bl,0xd56d82d0d369b857l,
-            0x2053a2527a4c41f9l },
-          0 },
-        /* 119 << 56 */
-        { { 0x20aecd6609ca8805l,0x945d9b31dc818ee6l,0x1424647c2119b44bl,
-            0xbe934d7e5a6641f9l },
-          { 0xe91d53184559e55el,0xc2fb8e0b4dfbc3d4l,0x9e92e20676cb937fl,
-            0x0f5582e4f2932429l },
-          0 },
-        /* 125 << 56 */
-        { { 0xb5fc22a42d31809fl,0x6d582d2b0e35b7b4l,0x5fac415158c5f576l,
-            0xdff239371e4cd7c9l },
-          { 0x0f62b329ed4d1925l,0x00994a2e6010fb16l,0xb4b91076bd754837l,
-            0xfde219463345103al },
-          0 },
-    },
-    {
-        /* 0 << 64 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 64 */
-        { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl,
-            0x2f5e6961fd1b667fl },
-          { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l,
-            0xf648f9168d6f0f7bl },
-          0 },
-        /* 3 << 64 */
-        { { 0x4090914bb5def996l,0x1cb69c83233dd1e7l,0xc1e9c1d39b3d5e76l,
-            0x1f3338edfccf6012l },
-          { 0xb1e95d0d2f5378a8l,0xacf4c2c72f00cd21l,0x6e984240eb5fe290l,
-            0xd66c038d248088ael },
-          0 },
-        /* 4 << 64 */
-        { { 0x9ad5462bb4d8bc50l,0x181c0b16a9195770l,0xebd4fe1c78412a68l,
-            0xae0341bcc0dff48cl },
-          { 0xb6bc45cf7003e866l,0xf11a6dea8a24a41bl,0x5407151ad04c24c2l,
-            0x62c9d27dda5b7b68l },
-          0 },
-        /* 5 << 64 */
-        { { 0xd4992b30614c0900l,0xda98d121bd00c24bl,0x7f534dc87ec4bfa1l,
-            0x4a5ff67437dc34bcl },
-          { 0x68c196b81d7ea1d7l,0x38cf289380a6d208l,0xfd56cd09e3cbbd6el,
-            0xec72e27e4205a5b6l },
-          0 },
-        /* 7 << 64 */
-        { { 0xe8b97932b88756ddl,0xed4e8652f17e3e61l,0xc2dd14993ee1c4a4l,
-            0xc0aaee17597f8c0el },
-          { 0x15c4edb96c168af3l,0x6563c7bfb39ae875l,0xadfadb6f20adb436l,
-            0xad55e8c99a042ac0l },
-          0 },
-        /* 9 << 64 */
-        { { 0x65c29219909523c8l,0xa62f648fa3a1c741l,0x88598d4f60c9e55al,
-            0xbce9141b0e4f347al },
-          { 0x9af97d8435f9b988l,0x0210da62320475b6l,0x3c076e229191476cl,
-            0x7520dbd944fc7834l },
-          0 },
-        /* 10 << 64 */
-        { { 0x87a7ebd1e0a1b12al,0x1e4ef88d770ba95fl,0x8c33345cdc2ae9cbl,
-            0xcecf127601cc8403l },
-          { 0x687c012e1b39b80fl,0xfd90d0ad35c33ba4l,0xa3ef5a675c9661c2l,
-            0x368fc88ee017429el },
-          0 },
-        /* 11 << 64 */
-        { { 0x664300b07850ec06l,0xac5a38b97d3a10cfl,0x9233188de34ab39dl,
-            0xe77057e45072cbb9l },
-          { 0xbcf0c042b59e78dfl,0x4cfc91e81d97de52l,0x4661a26c3ee0ca4al,
-            0x5620a4c1fb8507bcl },
-          0 },
-        /* 13 << 64 */
-        { { 0x84b9ca1504b6c5a0l,0x35216f3918f0e3a3l,0x3ec2d2bcbd986c00l,
-            0x8bf546d9d19228fel },
-          { 0xd1c655a44cd623c3l,0x366ce718502b8e5al,0x2cfc84b4eea0bfe7l,
-            0xe01d5ceecf443e8el },
-          0 },
-        /* 15 << 64 */
-        { { 0xa75feacabe063f64l,0x9b392f43bce47a09l,0xd42415091ad07acal,
-            0x4b0c591b8d26cd0fl },
-          { 0x2d42ddfd92f1169al,0x63aeb1ac4cbf2392l,0x1de9e8770691a2afl,
-            0xebe79af7d98021dal },
-          0 },
-        /* 16 << 64 */
-        { { 0x58af2010f5b343bcl,0x0f2e400af2f142fel,0x3483bfdea85f4bdfl,
-            0xf0b1d09303bfeaa9l },
-          { 0x2ea01b95c7081603l,0xe943e4c93dba1097l,0x47be92adb438f3a6l,
-            0x00bb7742e5bf6636l },
-          0 },
-        /* 17 << 64 */
-        { { 0x66917ce63b5f1cc4l,0x37ae52eace872e62l,0xbb087b722905f244l,
-            0x120770861e6af74fl },
-          { 0x4b644e491058edeal,0x827510e3b638ca1dl,0x8cf2b7046038591cl,
-            0xffc8b47afe635063l },
-          0 },
-        /* 19 << 64 */
-        { { 0x7677408d6dfafed3l,0x33a0165339661588l,0x3c9c15ec0b726fa0l,
-            0x090cfd936c9b56dal },
-          { 0xe34f4baea3c40af5l,0x3469eadbd21129f1l,0xcc51674a1e207ce8l,
-            0x1e293b24c83b1ef9l },
-          0 },
-        /* 21 << 64 */
-        { { 0x796d3a85825808bdl,0x51dc3cb73fd6e902l,0x643c768a916219d1l,
-            0x36cd7685a2ad7d32l },
-          { 0xe3db9d05b22922a4l,0x6494c87edba29660l,0xf0ac91dfbcd2ebc7l,
-            0x4deb57a045107f8dl },
-          0 },
-        /* 23 << 64 */
-        { { 0xb6c69ac82094cec3l,0x9976fb88403b770cl,0x1dea026c4859590dl,
-            0xb6acbb468562d1fdl },
-          { 0x7cd6c46144569d85l,0xc3190a3697f0891dl,0xc6f5319548d5a17dl,
-            0x7d919966d749abc8l },
-          0 },
-        /* 25 << 64 */
-        { { 0xb53b7de561906373l,0x858dbadeeb999595l,0x8cbb47b2a59e5c36l,
-            0x660318b3dcf4e842l },
-          { 0xbd161ccd12ba4b7al,0xf399daabf8c8282al,0x1587633aeeb2130dl,
-            0xa465311ada38dd7dl },
-          0 },
-        /* 27 << 64 */
-        { { 0x2dae9082be7cf3a6l,0xcc86ba92bc967274l,0xf28a2ce8aea0a8a9l,
-            0x404ca6d96ee988b3l },
-          { 0xfd7e9c5d005921b8l,0xf56297f144e79bf9l,0xa163b4600d75ddc2l,
-            0x30b23616a1f2be87l },
-          0 },
-        /* 28 << 64 */
-        { { 0x19e6125dec3f1decl,0x07b1f040911178dal,0xd93ededa904a6738l,
-            0x55187a5a0bebedcdl },
-          { 0xf7d04722eb329d41l,0xf449099ef170b391l,0xfd317a69ca99f828l,
-            0x50c3db2b34a4976dl },
-          0 },
-        /* 29 << 64 */
-        { { 0x0064d8585499fb32l,0x7b67bad977a8aeb7l,0x1d3eb9772d08eec5l,
-            0x5fc047a6cbabae1dl },
-          { 0x0577d159e54a64bbl,0x8862201bc43497e4l,0xad6b4e282ce0608dl,
-            0x8b687b7d0b167aacl },
-          0 },
-        /* 31 << 64 */
-        { { 0xe9f9669cda94951el,0x4b6af58d66b8d418l,0xfa32107417d426a4l,
-            0xc78e66a99dde6027l },
-          { 0x0516c0834a53b964l,0xfc659d38ff602330l,0x0ab55e5c58c5c897l,
-            0x985099b2838bc5dfl },
-          0 },
-        /* 33 << 64 */
-        { { 0xe7a935fa1684cb3bl,0x571650b5a7d7e69dl,0x6ba9ffa40328c168l,
-            0xac43f6bc7e46f358l },
-          { 0x54f75e567cb6a779l,0x4e4e2cc8c61320del,0xb94258bc2b8903d0l,
-            0xc7f32d57ceecabe0l },
-          0 },
-        /* 34 << 64 */
-        { { 0x34739f16cd7d9d89l,0x6daab4267ca080b5l,0x772086ff40e19f45l,
-            0x43caa56118c61b42l },
-          { 0x0ba3d4a8dbf365f1l,0xa0db435ee760ad97l,0xfd6f30d56916c59bl,
-            0xab34cb5dafe12f5dl },
-          0 },
-        /* 35 << 64 */
-        { { 0x445b86ea02a3260al,0x8c51d6428d689babl,0x183334d65588904cl,
-            0xf8a3b84d479d6422l },
-          { 0x581acfa0f0833d00l,0xc50827bc3b567d2dl,0x2c935e6daddcf73el,
-            0x2a645f7704dd19f2l },
-          0 },
-        /* 36 << 64 */
-        { { 0x78d2e8dfcb564473l,0x4349a97357d5621al,0x9d835d89218f8b24l,
-            0x01fe7bc5079b6ee2l },
-          { 0xe57f2a2b5b3b5dcel,0x5a8637b75fe55565l,0x83ff34aea41dbae7l,
-            0xfce1199c950a7a8fl },
-          0 },
-        /* 37 << 64 */
-        { { 0x0ca5d25bf8e71ce2l,0x204edc4a062685dal,0x06fe407d87678ec2l,
-            0xd16936a07defa39al },
-          { 0x3b108d84af3d16d0l,0xf2e9616d0305cad0l,0xbc9537e6f27bed97l,
-            0x71c2d699ebc9f45cl },
-          0 },
-        /* 39 << 64 */
-        { { 0x203bdd84cdcd3a85l,0x1107b901ade3ccfal,0xa7da89e95533159dl,
-            0x8d834005860e8c64l },
-          { 0x914bc0eb2a7638f7l,0xc66ce0a6620e8606l,0x11ef98c2e6c12dc0l,
-            0x25666b1d7780fc0el },
-          0 },
-        /* 40 << 64 */
-        { { 0x374f541f3e707706l,0x9a4d3638a831d0cfl,0x4ab4f4831518ca04l,
-            0x54e3ee5dfe38c318l },
-          { 0x383ae36403c8819bl,0xa9d1daa12e17864cl,0x245a97b350eeaa5bl,
-            0x5362d00999bf4e83l },
-          0 },
-        /* 41 << 64 */
-        { { 0x6667e89f4ded8a4fl,0xa59161abc36a7795l,0x1c96f6f9331ccf94l,
-            0xf2727e879a686d49l },
-          { 0x0f94894bb841295fl,0xb0fe8f744a0503d1l,0x60c581c7ef407926l,
-            0x1980c8e13edb7e1cl },
-          0 },
-        /* 43 << 64 */
-        { { 0x47948c84c5de1a41l,0xd595d14a48959688l,0x3bfca4be86ff21c9l,
-            0xb5ff59b86a4191cal },
-          { 0xced1dd1d65094c86l,0xd57b86559dc9d001l,0xbcac6fa3486e51d7l,
-            0x8e97e2637b774c1bl },
-          0 },
-        /* 44 << 64 */
-        { { 0xfc0313c29bd43980l,0x9c954b70f172db29l,0x679bdcb7f954a21al,
-            0x6b48170954e2e4fcl },
-          { 0x318af5f530baf1d0l,0x26ea8a3ccbf92060l,0xc3c69d7ccd5ae258l,
-            0xa73ba0470ead07c9l },
-          0 },
-        /* 45 << 64 */
-        { { 0xe82eb003e35dca85l,0xfd0000fa31e39180l,0xbca90f746735f378l,
-            0xe6aa783158c943edl },
-          { 0x0e94ecd5b6a438d7l,0xc02b60faf9a5f114l,0x4063568b8b1611ebl,
-            0x1398bdc1272509ecl },
-          0 },
-        /* 46 << 64 */
-        { { 0xc2ef6a01be3e92d1l,0x1bce9c27282bd5ddl,0xf7e488f3adda0568l,
-            0xd4f15fdb1af9bb8bl },
-          { 0x8c490ade4da846efl,0x76229da17f0b825el,0xc8b812082a6711c6l,
-            0x511f5e23b4c523aal },
-          0 },
-        /* 47 << 64 */
-        { { 0xbdf4e7049970f46el,0x70e220288dadbd1al,0x2b86c97fb1223d26l,
-            0x042ad22ecf62f51al },
-          { 0x72944339ba2ed2e9l,0x0ba0d10ef94fa61dl,0x3f86164194e68f15l,
-            0x1312a74acb86c545l },
-          0 },
-        /* 48 << 64 */
-        { { 0x3a63c39731815e69l,0x6df9cbd6dcdd2802l,0x4c47ed4a15b4f6afl,
-            0x62009d826ac0f978l },
-          { 0x664d80d28b898fc7l,0x72f1eeda2c17c91fl,0x9e84d3bc7aae6609l,
-            0x58c7c19528376895l },
-          0 },
-        /* 49 << 64 */
-        { { 0x640ebf5d5b8d354al,0xa5f3a8fdb396ff64l,0xd53f041d8378ed81l,
-            0x1969d61bc1234ad2l },
-          { 0x16d7acffeb68bde2l,0x63767a68f23e9368l,0x937a533c38928d95l,
-            0xee2190bbbeb0f1f2l },
-          0 },
-        /* 51 << 64 */
-        { { 0xb6860c9a73a4aafbl,0xb2f996290488870dl,0x16ef6232572d9e25l,
-            0x5b9eb1bad1383389l },
-          { 0xabf713a7ed8d77f8l,0xd2b4a2e9e2b69e64l,0xa1a22cfd6d6f17c2l,
-            0x4bfd6f992d604511l },
-          0 },
-        /* 52 << 64 */
-        { { 0xdcff7630d9294f07l,0x89b765d68dba8fd0l,0x553e55de8dbcaccdl,
-            0x9b4a009eed702bf8l },
-          { 0xf6e534dd27b8ca0dl,0xc4496b346177fd52l,0x378ce6f6c87bb7b7l,
-            0x68633d4844cc19f0l },
-          0 },
-        /* 53 << 64 */
-        { { 0xfe550021bc84c625l,0x8d7169986d45e4a3l,0xa09c6ded4c0c66b7l,
-            0xe32313aeb9e1d547l },
-          { 0x8ce775b4d1e8e0b9l,0xa899f9102654dd15l,0x7c38aa066cc8b2a9l,
-            0xe6ebb291d6ce6cc0l },
-          0 },
-        /* 55 << 64 */
-        { { 0x5963df62a6991216l,0x4c17f72246996010l,0x131dc2b840477722l,
-            0x78bf50b0d1765a75l },
-          { 0x360afd587ceaca12l,0xebc55dbb139cd470l,0x9083e27e4c05541cl,
-            0xc10057a3b873d757l },
-          0 },
-        /* 57 << 64 */
-        { { 0x440009c3deed7769l,0xde2fa58a14fd8a44l,0x509e7df35b627596l,
-            0x3d76a87cc3bb07a7l },
-          { 0x8018fee5b8ef000al,0x71ce33e9823fd4b6l,0x3a1cac37469c0bb1l,
-            0x92fe7aeaf3eec8eel },
-          0 },
-        /* 59 << 64 */
-        { { 0x37ad0eb8de64e568l,0x4ac669bca1e3e20el,0x240d0ac22ce944edl,
-            0xd532039a3c1b28fbl },
-          { 0xa2bb899a23acba6cl,0xd472af671af937e1l,0x04478f7b8851e753l,
-            0x74030eef5ea05307l },
-          0 },
-        /* 60 << 64 */
-        { { 0x3559e7b67dc17874l,0xd0caf0ef8195cc2al,0x07c067880cd24dd9l,
-            0x01a99ea002857c41l },
-          { 0xd86579e490f82f63l,0xb1e0658ae41c9237l,0x075ffafd93fd1e79l,
-            0x6e70403547f60b8fl },
-          0 },
-        /* 61 << 64 */
-        { { 0x2246ad76c1d68c31l,0x9126202b0d5c4677l,0x5f40de81638882dcl,
-            0xb131988ca3253a7fl },
-          { 0x766f1897ba9ae0a8l,0xf0e01dd41d8b5fefl,0x03e28ce3ed7b12c8l,
-            0x44b3a2be1fd20e1el },
-          0 },
-        /* 63 << 64 */
-        { { 0xd4c8e8e5f2a5f247l,0x42ffd816c2c7c979l,0x89e1485211093d1al,
-            0x98f44a4613871ebbl },
-          { 0x374849964b032e2dl,0x28a430f445995a61l,0xf2f9acbad5be16b6l,
-            0xac98a5402d8e02aal },
-          0 },
-        /* 64 << 64 */
-        { { 0x0d53f5c7a3e6fcedl,0xe8cbbdd5f45fbdebl,0xf85c01df13339a70l,
-            0x0ff71880142ceb81l },
-          { 0x4c4e8774bd70437al,0x5fb32891ba0bda6al,0x1cdbebd2f18bd26el,
-            0x2f9526f103a9d522l },
-          0 },
-        /* 65 << 64 */
-        { { 0x48334fdcc20b8d30l,0x25f887d749414fddl,0x9ccd513311a2cf0dl,
-            0x7e7799e4d08975a4l },
-          { 0xb5993a53729b951cl,0x0cf14a5a62dbc6a8l,0xb39ed36efe4d16eel,
-            0xb75f3fb681bda63al },
-          0 },
-        /* 71 << 64 */
-        { { 0xac7db8706d4f68b5l,0x819a13c7be49b3a4l,0x646ae2b1418bf1e9l,
-            0x25b53a5f69b3a5ccl },
-          { 0xd23d94d37de26578l,0x8bb581caecdd138al,0x9e053f67f857b0dal,
-            0xe679cc7a255ff474l },
-          0 },
-        /* 77 << 64 */
-        { { 0x4a4b8d990df097f9l,0x0ae1227a0b4173cal,0x0d401778adb72178l,
-            0xd29848b43f421e0cl },
-          { 0xc5eec6096eb0722dl,0x527d72877e12c028l,0xed12a9e71b5dcc0cl,
-            0x26b27344dcf4b4dal },
-          0 },
-        /* 83 << 64 */
-        { { 0x695c502565e4408al,0x2d23768fcbce94e6l,0x1505fa1e5080b88dl,
-            0x5c8fbab6855f7cc1l },
-          { 0x70d876f275fb125dl,0x456421330a252007l,0xfe99249a8ee05be1l,
-            0x0893b620f4bf5490l },
-          0 },
-        /* 89 << 64 */
-        { { 0x2a59df1ed9fe6bdfl,0x96a9c791785e057fl,0x4b0d795f86a1d751l,
-            0x196c8e0aec642886l },
-          { 0x6df67899bc0e055cl,0x4173204a63007433l,0xb5ee4efec21c9245l,
-            0x2f7d4c75c1451bael },
-          0 },
-        /* 95 << 64 */
-        { { 0x2ad7f836b1047b7fl,0x368d431a71f6bfe1l,0xfcd933b103db4667l,
-            0xfff77ed3ecb81330l },
-          { 0x3677935b44958bd4l,0xa6cfcda8a1d5a9e7l,0xb2b73bc699ff9fael,
-            0x1c2cd628f866d3c4l },
-          0 },
-        /* 101 << 64 */
-        { { 0x2756873495031ceel,0xebed373d51091c1bl,0x398fef0819aa2f27l,
-            0x2f26174e2c0a9feal },
-          { 0xedca72b6b219be3fl,0x001a8fdc80503df8l,0x9a2fadbb6b93f643l,
-            0xd48e552cd44cebc3l },
-          0 },
-        /* 107 << 64 */
-        { { 0x6c0dbb68667a7ab6l,0x00490ce757630e91l,0x04976cd57eb2f382l,
-            0x9ee486b655dda4a3l },
-          { 0x4ea5c9c9cca0d01cl,0xa6e054b639f69c6dl,0xb3b7ac992ecab239l,
-            0x80c9f6d17597512el },
-          0 },
-        /* 113 << 64 */
-        { { 0x64dfdd68b942fad9l,0xe7d8e88da5eb3d14l,0xb7281dc2382f6301l,
-            0xcfa2ee6dbfe00a7fl },
-          { 0x6e617657dc7be39fl,0x22d58dd6591c6e3al,0xd3a4003918318c13l,
-            0xcac6c830981b6b72l },
-          0 },
-        /* 116 << 64 */
-        { { 0x009690ffb4fbfaa0l,0x8bbbdab73619c6dbl,0xc6d44273728356e8l,
-            0xfd76f0d8e453ec35l },
-          { 0x775c2554aac28a29l,0x28f7af9d5c55e4f0l,0xbacf54a688e8ad4dl,
-            0x85b018e80aa76ddfl },
-          0 },
-        /* 119 << 64 */
-        { { 0x27893f7983ce88e4l,0x9556c9977785f13dl,0x83d3c38d3a35831el,
-            0x3856c829d12f0a1dl },
-          { 0xb308d84c93259c1al,0x4ef87ab4691ffd28l,0x76a18d5321a88c58l,
-            0xf13cd5d53503cb4dl },
-          0 },
-        /* 125 << 64 */
-        { { 0x669d93dba8cc0db3l,0x403cb9200dfcfcf4l,0x5def4a03e77c3979l,
-            0x2a05c9423e2e2522l },
-          { 0xd86dca52b5f48bf0l,0x174766de5828a135l,0x116290b40d3a96d0l,
-            0xe1999457aeea1193l },
-          0 },
-    },
-    {
-        /* 0 << 72 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 72 */
-        { { 0x0db2fb5ed005832al,0x5f5efd3b91042e4fl,0x8c4ffdc6ed70f8cal,
-            0xe4645d0bb52da9ccl },
-          { 0x9596f58bc9001d1fl,0x52c8f0bc4e117205l,0xfd4aa0d2e398a084l,
-            0x815bfe3a104f49del },
-          0 },
-        /* 3 << 72 */
-        { { 0x524d226ad7ab9a2dl,0x9c00090d7dfae958l,0x0ba5f5398751d8c2l,
-            0x8afcbcdd3ab8262dl },
-          { 0x57392729e99d043bl,0xef51263baebc943al,0x9feace9320862935l,
-            0x639efc03b06c817bl },
-          0 },
-        /* 4 << 72 */
-        { { 0xe839be7d341d81dcl,0xcddb688932148379l,0xda6211a1f7026eadl,
-            0xf3b2575ff4d1cc5el },
-          { 0x40cfc8f6a7a73ae6l,0x83879a5e61d5b483l,0xc5acb1ed41a50ebcl,
-            0x59a60cc83c07d8fal },
-          0 },
-        /* 5 << 72 */
-        { { 0xdec98d4ac3b81990l,0x1cb837229e0cc8fel,0xfe0b0491d2b427b9l,
-            0x0f2386ace983a66cl },
-          { 0x930c4d1eb3291213l,0xa2f82b2e59a62ae4l,0x77233853f93e89e3l,
-            0x7f8063ac11777c7fl },
-          0 },
-        /* 7 << 72 */
-        { { 0x36e607cf02ff6072l,0xa47d2ca98ad98cdcl,0xbf471d1ef5f56609l,
-            0xbcf86623f264ada0l },
-          { 0xb70c0687aa9e5cb6l,0xc98124f217401c6cl,0x8189635fd4a61435l,
-            0xd28fb8afa9d98ea6l },
-          0 },
-        /* 9 << 72 */
-        { { 0x3d4da8c3017025f3l,0xefcf628cfb9579b4l,0x5c4d00161f3716ecl,
-            0x9c27ebc46801116el },
-          { 0x5eba0ea11da1767el,0xfe15145247004c57l,0x3ace6df68c2373b7l,
-            0x75c3dffe5dbc37acl },
-          0 },
-        /* 10 << 72 */
-        { { 0xa2a147dba28a0749l,0x246c20d6ee519165l,0x5068d1b1d3810715l,
-            0xb1e7018c748160b9l },
-          { 0x03f5b1faf380ff62l,0xef7fb1ddf3cb2c1el,0xeab539a8fc91a7dal,
-            0x83ddb707f3f9b561l },
-          0 },
-        /* 11 << 72 */
-        { { 0xb57276d980101b98l,0x760883fdb82f0f66l,0x89d7de754bc3eff3l,
-            0x03b606435dc2ab40l },
-          { 0xcd6e53dfe05beeacl,0xf2f1e862bc3325cdl,0xdd0f7921774f03c3l,
-            0x97ca72214552cc1bl },
-          0 },
-        /* 13 << 72 */
-        { { 0x760cb3b5e224c5d7l,0xfa3baf8c68616919l,0x9fbca1138d142552l,
-            0x1ab18bf17669ebf5l },
-          { 0x55e6f53e9bdf25ddl,0x04cc0bf3cb6cd154l,0x595bef4995e89080l,
-            0xfe9459a8104a9ac1l },
-          0 },
-        /* 15 << 72 */
-        { { 0x694b64c5abb020e8l,0x3d18c18419c4eec7l,0x9c4673ef1c4793e5l,
-            0xc7b8aeb5056092e6l },
-          { 0x3aa1ca43f0f8c16bl,0x224ed5ecd679b2f6l,0x0d56eeaf55a205c9l,
-            0xbfe115ba4b8e028bl },
-          0 },
-        /* 16 << 72 */
-        { { 0x3e22a7b397acf4ecl,0x0426c4005ea8b640l,0x5e3295a64e969285l,
-            0x22aabc59a6a45670l },
-          { 0xb929714c5f5942bcl,0x9a6168bdfa3182edl,0x2216a665104152bal,
-            0x46908d03b6926368l },
-          0 },
-        /* 17 << 72 */
-        { { 0x9b8be0247fcba850l,0x81eb5797820a181el,0xa0f2812230a01211l,
-            0x7e9cdc3cae7b8821l },
-          { 0x202332cc72ce15e7l,0xcd3cb2bbcb8238d7l,0xe4ab63dfc6e82c43l,
-            0x58bd00283183d717l },
-          0 },
-        /* 19 << 72 */
-        { { 0x02d57b7e717ed7b5l,0xd22e5b244dbce1a2l,0x174bd7712a4cdcf5l,
-            0xa6fdb801408205bbl },
-          { 0x67b4b0695e1387e9l,0x332b19a10591a442l,0x24edd916ccacf366l,
-            0xbe34cc4534958a50l },
-          0 },
-        /* 21 << 72 */
-        { { 0xa3f46e1e3e66d391l,0xb4a732cd7d6369b2l,0x99c3b85d402c1022l,
-            0x7dccfcbe2b54932el },
-          { 0xa6ddaa7b56b1dfe2l,0x31dc78a5e34a82c9l,0x8abeb3da704f3941l,
-            0xdf11a36cca55fa98l },
-          0 },
-        /* 23 << 72 */
-        { { 0x6c01f77a16e00c1bl,0x82515490839eaaacl,0x62f3a4ef3470d334l,
-            0x5a29a6491c1dcd6cl },
-          { 0x46b6782ece997a25l,0x9978fb35d3579953l,0x98f5a9df0960e0cel,
-            0x547dc8391f527a4cl },
-          0 },
-        /* 25 << 72 */
-        { { 0x395b15835d9dc24fl,0xa4256932c73ae680l,0x0542960efaa2c8e9l,
-            0x2bb3adee71068c6al },
-          { 0xa706099b570b4554l,0x85d12bb5f4e278d6l,0xd78af6f664296843l,
-            0xc7d3b3888428c633l },
-          0 },
-        /* 27 << 72 */
-        { { 0x34d44f9343b7e597l,0xdde440a7c2530f42l,0x7270a0817856bdb9l,
-            0x86a945eb5353032fl },
-          { 0x6c2f8e9966d39810l,0x0642a31b9b8b4b6bl,0x51679e62d1509d82l,
-            0x0120001c90f8ff16l },
-          0 },
-        /* 28 << 72 */
-        { { 0x50a1c1062e36e34al,0x74e8f58ce024ed1al,0x3f0f1dfa1300d726l,
-            0x6680df267b4a2d18l },
-          { 0x12b5979d8235b3b7l,0x1d2fafcb8a611493l,0x73ebda968848ece5l,
-            0xe996c275a413e399l },
-          0 },
-        /* 29 << 72 */
-        { { 0x46b7d7c7495ff000l,0xe60ed097baed95d1l,0xaa8804ac6e38f9c0l,
-            0x92990c0645c6f9bbl },
-          { 0xcae6a439c0919851l,0x713dff151bf5e1f2l,0x5d262c302eb38cdbl,
-            0xb73d505190df31dfl },
-          0 },
-        /* 31 << 72 */
-        { { 0x921e7b1c32d9268cl,0x34db2b964276fad4l,0x0ec56d34cc44e730l,
-            0x59be3a46096545b7l },
-          { 0xe9fdbc9766cf3a6al,0x7b2f83edd04e9b53l,0x6d99b3cc8fbae3e7l,
-            0x8eb5646c7ada3a40l },
-          0 },
-        /* 33 << 72 */
-        { { 0xa69ab906fc3302bfl,0x49ae6ba7d0872e90l,0xc9e2d6d1f3a1bfc3l,
-            0x11dfe85f1a033500l },
-          { 0x45189c2998666dbdl,0xba6aab88bbfd13cel,0xcf9c8b43dbd38cd4l,
-            0xa0cb581b68009236l },
-          0 },
-        /* 34 << 72 */
-        { { 0xff18c42a16288a7al,0x6363ace430699163l,0x8546d6332a2ce353l,
-            0x5e0379ef7b6b3418l },
-          { 0x2df2bb463e941bb2l,0xae7c091888e1aacel,0x6bc0982d83f5a37al,
-            0x8521bd02676d09e0l },
-          0 },
-        /* 35 << 72 */
-        { { 0x6531dff33d361aacl,0x59b954477c8cac2el,0xcc104df6c5cb7363l,
-            0x68b571c519364acdl },
-          { 0x7521e962979c3bc0l,0xbe0544c9c4aa1f92l,0x59127fe92a31eabbl,
-            0x760ac28593d8b55bl },
-          0 },
-        /* 36 << 72 */
-        { { 0x62ed534c6115164bl,0xaebe9e4cdce84ceal,0xd81c91a1c83f64c3l,
-            0x325a8ca8ecacd09al },
-          { 0x7ea57ad968b45df1l,0xa555636fd530c5d2l,0x23aff510591cfe32l,
-            0x46ff147637bedab9l },
-          0 },
-        /* 37 << 72 */
-        { { 0xa5a7e81ecb2edb3bl,0x9b0dc5f4f8fbe238l,0xc6f258087c66dd34l,
-            0xb4a57503a3f8f38al },
-          { 0x195b433513571b5bl,0xa32840763ccbc30bl,0x64ae1ffccf99ddd5l,
-            0x0dfc8772aa844e76l },
-          0 },
-        /* 39 << 72 */
-        { { 0x8b471afbfb22341dl,0xbf448b43397afdd2l,0x4cb08409682c37edl,
-            0xc3acfae6a948f1f6l },
-          { 0xf58462549e634707l,0x50161a78bd949f52l,0xf0529e752fe73566l,
-            0xe7e3fdef6fda53e0l },
-          0 },
-        /* 40 << 72 */
-        { { 0x56dab1c8321a518cl,0xfd4439a68bce226fl,0xe0b30d194facb9fal,
-            0xb5052f307583571bl },
-          { 0x1442641012afd476l,0xd02e417203fe624al,0xfc394f65531c92e6l,
-            0x16d4bf5ad4bc0b52l },
-          0 },
-        /* 41 << 72 */
-        { { 0xa38ac25eb4ec4f0fl,0x5399c024de72b27dl,0x08318aafd81a3d65l,
-            0x1af227a70c20e5d9l },
-          { 0x6389cc9a26c54e25l,0x438298bba47dc27fl,0x75386cca1a63fa0el,
-            0xc941e84cdf7bc1b0l },
-          0 },
-        /* 43 << 72 */
-        { { 0x81cad748fdfe3faal,0x752107b453ff1988l,0x8d8bb7001a8fd829l,
-            0x69838e15ca821d8el },
-          { 0x24371ede3b9f6b34l,0x19b4bb24d91e1495l,0x90899ca1e598ded1l,
-            0xbbb78b167c14e9e3l },
-          0 },
-        /* 44 << 72 */
-        { { 0xa577e84cbef239aal,0x656d2b6f8904b4d4l,0x2f6defe6ca4007edl,
-            0xca6e517737770796l },
-          { 0x4c62fcba298b6448l,0x046849660f62e00dl,0x806c2f0390b07d82l,
-            0x730855795e8d1e60l },
-          0 },
-        /* 45 << 72 */
-        { { 0x24488802f4703b78l,0x6c9323bee9eaa1e0l,0x242990e2aa94c170l,
-            0x3292bc42a15b5886l },
-          { 0x60ccb5bc908af203l,0x8fd63583713b09bdl,0x40791ecad693fa28l,
-            0xea80abf2941af8a1l },
-          0 },
-        /* 46 << 72 */
-        { { 0xf9c0315071145fe3l,0x80a71b55d7873a7dl,0xd134244b5e10bac7l,
-            0x303f7e12ded3a4b4l },
-          { 0x58e6f17e803b7a3bl,0xcd6f64130b1ca6b4l,0x25e744ce2ce65aa2l,
-            0xf2bbc66b952efa51l },
-          0 },
-        /* 47 << 72 */
-        { { 0xc8b212e75913e1f3l,0xf018ab208d416886l,0x28249e15b617cac4l,
-            0x837fcba1693ed09al },
-          { 0x9c457e511c15a1bcl,0x9354758756c7f3f1l,0x1afd80348be18306l,
-            0xa43d56982256ab14l },
-          0 },
-        /* 48 << 72 */
-        { { 0xce06b88210395755l,0x117ce6345ec1df80l,0xfefae513eff55e96l,
-            0xcf36cba6fd7fed1el },
-          { 0x7340eca9a40ebf88l,0xe6ec1bcfb3d37e12l,0xca51b64e86bbf9ffl,
-            0x4e0dbb588b40e05el },
-          0 },
-        /* 49 << 72 */
-        { { 0xf9c063f62f2be34bl,0x9ca32fa99c20f16bl,0xe02e350d0125a01al,
-            0x62d66c54e6516c25l },
-          { 0x21b154ad5120bedbl,0xb1077f4e8d6ff9d8l,0xd01a46c300bb4941l,
-            0x9d381847d1460588l },
-          0 },
-        /* 51 << 72 */
-        { { 0xf3a9b311581cb57bl,0x65fb3fb649727d13l,0xb8496e3d35131142l,
-            0xf7642f554d0cdab9l },
-          { 0xe2f66f0e9f6d7e45l,0xbae14cedaa22fcd4l,0x1f769f0e49b2e05al,
-            0x08c4d7784ac5191el },
-          0 },
-        /* 52 << 72 */
-        { { 0x86f9108ece4aa825l,0xbe5b2f317e5a5fbfl,0x2772c1b49254bb78l,
-            0xae6cdf5f4ff8ac5cl },
-          { 0x106cd94bf6b7a12el,0xbe0915d6d1c7a1a5l,0x8bf6bc8d3b40ac5el,
-            0xbb89180423ee3acal },
-          0 },
-        /* 53 << 72 */
-        { { 0x76f15eaa618b5ea1l,0xec1ea62e6d4ad0c8l,0x301b60c8168d57fal,
-            0x454d5f771edbfb05l },
-          { 0xea888e29a936031al,0x01303d3f0174dd17l,0x8b5e06b4244254e7l,
-            0x00ebf03509724acfl },
-          0 },
-        /* 55 << 72 */
-        { { 0x66ce3ded8e66d509l,0x368e38d05a488586l,0x7b9ae220c7eedf5el,
-            0x67e9ea52bfbf9d62l },
-          { 0xe9cbf53d99b7ecb3l,0xfde3e8c0908bf072l,0x288400ab1107e21fl,
-            0x24c8856256532667l },
-          0 },
-        /* 57 << 72 */
-        { { 0x0d5f9955ca9d3ad1l,0x545feba13a1daec0l,0xd22972016cb30f23l,
-            0x9660175ccef6cf6el },
-          { 0xbf3e341a395738dcl,0x74a5efbc80f7cca4l,0xc4f9a07bbebc6a60l,
-            0x2f1e3dad4b1f915al },
-          0 },
-        /* 59 << 72 */
-        { { 0xada4423f0d5e2e34l,0x2d31f4920b372358l,0xd7f469370e2d6a8cl,
-            0xf5e7ccfe0028e4ael },
-          { 0x20fcb1f3928854b2l,0x2a8973c507271bf6l,0xe87de33e5fa88fe1l,
-            0xe9af2dce7bd3c2a6l },
-          0 },
-        /* 60 << 72 */
-        { { 0x185a19d959d097b2l,0xb1c72a3a0dea2875l,0x3b371628f9021f08l,
-            0x45f1255bfa9d6ac1l },
-          { 0x9ff36a90cfd72c0dl,0x8c7315db24fe2376l,0x9aebcde04b34d42cl,
-            0x2129ab16923025f3l },
-          0 },
-        /* 61 << 72 */
-        { { 0x341b9dd714b4cf50l,0x7c6e4634d619d00el,0x571d6e2fdf2165ael,
-            0xdedf9cd18dbe9db5l },
-          { 0x52a152777c5f3dc3l,0x7d27c97ef2901cf7l,0x5e098b54d02a85dfl,
-            0x6fce3e13088e3640l },
-          0 },
-        /* 63 << 72 */
-        { { 0xfa95be147a939904l,0xdfcf5b9bb56365ccl,0xdbb546bdd2d66922l,
-            0xf26a8b9cda03ca7fl },
-          { 0x96a8042d16821c0cl,0xe6729970e88ede60l,0xd028130d1285e303l,
-            0x1678b01688b7de75l },
-          0 },
-        /* 64 << 72 */
-        { { 0x96649933aed1d1f7l,0x566eaff350563090l,0x345057f0ad2e39cfl,
-            0x148ff65b1f832124l },
-          { 0x042e89d4cf94cf0dl,0x319bec84520c58b3l,0x2a2676265361aa0dl,
-            0xc86fa3028fbc87adl },
-          0 },
-        /* 65 << 72 */
-        { { 0x5db4884124627d04l,0xf92740766f7e3febl,0xd09eb11773496240l,
-            0xd48e51419a6b9ec9l },
-          { 0xcbb2ac97b7336e27l,0xe794fb760640bf6cl,0xc0b7f78dc7c7fa3fl,
-            0x1355d071fd2edbb9l },
-          0 },
-        /* 71 << 72 */
-        { { 0x575d9724e84e25a3l,0x068690a13d4d8708l,0x8a7b1c6c54dd62d0l,
-            0x8c45e1b37f88e231l },
-          { 0x38c665466d85afe2l,0x65231642e1d69f1bl,0xb71c53a090687ec1l,
-            0xdf8469d777fb5981l },
-          0 },
-        /* 77 << 72 */
-        { { 0xb920b503144fe6bcl,0x54b0f0593914c130l,0x63188d5a8269b650l,
-            0x8d7780962fc7064dl },
-          { 0xbf7b0eec5e50839al,0xaf8a7ddbe242cd06l,0x93df850809cecdb9l,
-            0x4db58a72410659e9l },
-          0 },
-        /* 83 << 72 */
-        { { 0x460d9b383baba3cdl,0x52386e4d2cf860b8l,0xd224fe5da3924b9al,
-            0xe4a4be7bcf14d813l },
-          { 0xb0759e82ed3774fdl,0x57c064b38d9b6c59l,0x301ab902aee183d0l,
-            0xf1c873495ba207c3l },
-          0 },
-        /* 89 << 72 */
-        { { 0xe8245b0a6dd58696l,0x0714eedb61091043l,0x7d9874459101129bl,
-            0x4a7f1f03a0b27a21l },
-          { 0x282e5cff71ee2045l,0x25c694a3da5c6b41l,0xb3d8e21f5542ca55l,
-            0x57d64170e3601af0l },
-          0 },
-        /* 95 << 72 */
-        { { 0x9c8e86c6c6c4fee6l,0x70194db5a596119bl,0xfc6271d30e06050cl,
-            0x17d94c89b15f18d2l },
-          { 0x76c9e9bd49817224l,0x42621638b989c5bcl,0x1e9c4cbeb769d70cl,
-            0x85e227c3b87f2783l },
-          0 },
-        /* 101 << 72 */
-        { { 0x146185d2117e73c5l,0xbf6214696dc38116l,0x9af9d9b5459e72cbl,
-            0x7512882fb3930b85l },
-          { 0xfe935379d36583b8l,0xb83ad35e7c7fdcdel,0x093ca0ab2658ae4bl,
-            0xc9b16d60a756681bl },
-          0 },
-        /* 107 << 72 */
-        { { 0x12c24d9195d3519bl,0x1fc6db1bdb43fd06l,0x1ae49fed25bbde51l,
-            0x27072e0b76d2827bl },
-          { 0xdcb92e05aeb8c47fl,0x601d414056145f67l,0xcb7002652a39e8f7l,
-            0x6ce9facc35620d8cl },
-          0 },
-        /* 113 << 72 */
-        { { 0x5c428a5ebd702c22l,0xcb6863291616129dl,0xe6278994eabcb9a1l,
-            0xb409a10b9327e540l },
-          { 0x6899f7cb66cf96aal,0xa9225f051c64b545l,0x00c5522ee3feec21l,
-            0x35503728e083315cl },
-          0 },
-        /* 116 << 72 */
-        { { 0x1916d88cf1600077l,0x1ac9c238e3a58b2bl,0x3080df8535f3508dl,
-            0x86cc18712744912bl },
-          { 0x56aec9d5ccd15044l,0x8dd9061a5db0ab17l,0x84d6bc4e2c84171dl,
-            0xd569c7d70989a5bdl },
-          0 },
-        /* 119 << 72 */
-        { { 0x24446b2702af35abl,0x071710478eea4565l,0xba4989db728306e6l,
-            0x2cd692a85954a558l },
-          { 0x644e02763576b32el,0x7efdb65c1f9fe65dl,0x04b2828e8796c048l,
-            0xcfd22481187b979bl },
-          0 },
-        /* 125 << 72 */
-        { { 0xa10d104084ea9701l,0x27dd0dcb415e187dl,0xf667c5e939bfe45cl,
-            0x3995e4ae55b67506l },
-          { 0xb25117d9b5a14801l,0xeee58525fe142e92l,0x100b856a6dbae9f1l,
-            0xada7057629586658l },
-          0 },
-    },
-    {
-        /* 0 << 80 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 80 */
-        { { 0xe4050f1cf1c367cal,0x9bc85a9bc90fbc7dl,0xa373c4a2e1a11032l,
-            0xb64232b7ad0393a9l },
-          { 0xf5577eb0167dad29l,0x1604f30194b78ab2l,0x0baa94afe829348bl,
-            0x77fbd8dd41654342l },
-          0 },
-        /* 3 << 80 */
-        { { 0xa2f7932c68af43eel,0x5502468e703d00bdl,0xe5dc978f2fb061f5l,
-            0xc9a1904a28c815adl },
-          { 0xd3af538d470c56a4l,0x159abc5f193d8cedl,0x2a37245f20108ef3l,
-            0xfa17081e223f7178l },
-          0 },
-        /* 4 << 80 */
-        { { 0x1fe2a9b2b4b4b67cl,0xc1d10df0e8020604l,0x9d64abfcbc8058d8l,
-            0x8943b9b2712a0fbbl },
-          { 0x90eed9143b3def04l,0x85ab3aa24ce775ffl,0x605fd4ca7bbc9040l,
-            0x8b34a564e2c75dfbl },
-          0 },
-        /* 5 << 80 */
-        { { 0x5c18acf88e2f7d90l,0xfdbf33d777be32cdl,0x0a085cd7d2eb5ee9l,
-            0x2d702cfbb3201115l },
-          { 0xb6e0ebdb85c88ce8l,0x23a3ce3c1e01d617l,0x3041618e567333acl,
-            0x9dd0fd8f157edb6bl },
-          0 },
-        /* 7 << 80 */
-        { { 0x516ff3a36fa6110cl,0x74fb1eb1fb93561fl,0x6c0c90478457522bl,
-            0xcfd321046bb8bdc6l },
-          { 0x2d6884a2cc80ad57l,0x7c27fc3586a9b637l,0x3461baedadf4e8cdl,
-            0x1d56251a617242f0l },
-          0 },
-        /* 9 << 80 */
-        { { 0x892c81a321175ec1l,0x9159a505ee018109l,0xc70130532d8be316l,
-            0x76060c21426fa2e5l },
-          { 0x074d2dfc6b6f0f22l,0x9725fc64ca01a671l,0x3f6679b92770bd8el,
-            0x8fe6604fd7c9b3fel },
-          0 },
-        /* 10 << 80 */
-        { { 0xce711154b6e00a84l,0xd9fe7e4224890e60l,0xd10bc6c34560988fl,
-            0xbdc2ef526859b004l },
-          { 0xdcf0d868d5c890eel,0x893115e6119c47dcl,0xe97966fbee714567l,
-            0x117813355c85aa53l },
-          0 },
-        /* 11 << 80 */
-        { { 0x71d530cc73204349l,0xc9df473d94a0679cl,0xc572f0014261e031l,
-            0x9786b71f22f135fel },
-          { 0xed6505fa6b64e56fl,0xe2fb48e905219c46l,0x0dbec45bedf53d71l,
-            0xd7d782f2c589f406l },
-          0 },
-        /* 13 << 80 */
-        { { 0x06513c8a446cd7f4l,0x158c423b906d52a6l,0x71503261c423866cl,
-            0x4b96f57093c148eel },
-          { 0x5daf9cc7239a8523l,0x611b597695ac4b8bl,0xde3981db724bf7f6l,
-            0x7e7d0f7867afc443l },
-          0 },
-        /* 15 << 80 */
-        { { 0x3d1ab80c8ce59954l,0x742c5a9478222ac0l,0x3ddacbf894f878ddl,
-            0xfc085117e7d54a99l },
-          { 0xfb0f1dfa21e38ec2l,0x1c7b59cb16f4ff7fl,0x988752397ea888fel,
-            0x705d270cb10dc889l },
-          0 },
-        /* 16 << 80 */
-        { { 0xe5aa692a87dec0e1l,0x010ded8df7b39d00l,0x7b1b80c854cfa0b5l,
-            0x66beb876a0f8ea28l },
-          { 0x50d7f5313476cd0el,0xa63d0e65b08d3949l,0x1a09eea953479fc6l,
-            0x82ae9891f499e742l },
-          0 },
-        /* 17 << 80 */
-        { { 0xd7c89ba1e7d1cefdl,0xcb33553a9a91e03dl,0xa01caaff59f01e54l,
-            0x4a71c141de07def7l },
-          { 0xe1616a4034d467d1l,0x6f395ab2e8ba8817l,0xf781ea64e45869abl,
-            0x8b9513bb7134f484l },
-          0 },
-        /* 19 << 80 */
-        { { 0x0b0ec9035948c135l,0xaee219539a990127l,0x9d15ba0eb185dda1l,
-            0xd87bc2fb2c7d6802l },
-          { 0x05a480307a82d7f8l,0x7b591ce4e7e11ec3l,0x14d4cc22a0e15fdbl,
-            0xf2d4213576def955l },
-          0 },
-        /* 21 << 80 */
-        { { 0xd56d69e4117a5f59l,0xcae6008a01286e97l,0x716a0a282dab13b0l,
-            0xc821da99b3a8d2d0l },
-          { 0x6898b66239c305e6l,0xe42d3394c8b61142l,0x54c1d2b253b16712l,
-            0x3cec3953a01f4be6l },
-          0 },
-        /* 23 << 80 */
-        { { 0x5bd1e3036951b85el,0x1a73f1fb164d79a4l,0x6e77abd39fb22bc3l,
-            0x8ae4c181b3d18dfdl },
-          { 0xdd4226f5a6a14ed1l,0x620e111feb4e1d92l,0xffce6e59edca4fe8l,
-            0x39f5fc053d0a717dl },
-          0 },
-        /* 25 << 80 */
-        { { 0xef8fa78cd91aff44l,0x6f3f9749bdc03be7l,0x171545f8b8596075l,
-            0xbe31a73e2af132cel },
-          { 0x5b4e174123884e1dl,0x4373357ea9fa75f0l,0x8dba2731bc06f49el,
-            0xa09aebc877fa6de8l },
-          0 },
-        /* 27 << 80 */
-        { { 0xd4974e518293e18cl,0x1e4cfc5331ec0e8fl,0x80b4258325d40b1el,
-            0x5cfb73a2a85f7588l },
-          { 0xe553efd204c0e00bl,0xdaa6750e9a48ac39l,0xf20936b00abda06al,
-            0xbfd3c7e4bf85771cl },
-          0 },
-        /* 28 << 80 */
-        { { 0x72669c3c7292495cl,0xa627e2dd82786572l,0xbdbfce5cd39c3e3dl,
-            0xba6164927feed3d6l },
-          { 0x4eb5f513e77b7318l,0x133f2e834337c2e0l,0xdea20f07f408bec6l,
-            0x848a8396e3c87655l },
-          0 },
-        /* 29 << 80 */
-        { { 0x3086643551138f2bl,0x1176d8e6108a36bal,0xd78b3b400d4d4b66l,
-            0x99ddd9bd956dbff1l },
-          { 0x91dfe72822f08e5fl,0x7fd8cfe6a081ac4el,0x8ebb278ed75285c2l,
-            0x2335fe00ef457ac0l },
-          0 },
-        /* 31 << 80 */
-        { { 0xe9d79c50f058191al,0x6749c3b05d3183f8l,0x5edc2708dbfeb1ecl,
-            0x2c18f93621275986l },
-          { 0x3a093e1f0703389fl,0xdf065e4a3ef60f44l,0x6860e4df87e7c458l,
-            0xdb22d96e8bfe4c7dl },
-          0 },
-        /* 33 << 80 */
-        { { 0xb7193811b48dad42l,0x23b9dca320ad0f0cl,0x55511ffb54efb61bl,
-            0xac8ed94626f9ce42l },
-          { 0xa42b4bc73fc4cbd9l,0x2a4670905c6f8e39l,0xb50040f87eb592del,
-            0x6633f81bdc2541f3l },
-          0 },
-        /* 34 << 80 */
-        { { 0xc104e02ed2d6d9c2l,0xa4876e870302517al,0x0263c9b2912f5005l,
-            0x902f364a3d89d268l },
-          { 0x76070565bb20a5a8l,0xa3a8977452109e98l,0x51fbffec463aa476l,
-            0xfa8519625daa1503l },
-          0 },
-        /* 35 << 80 */
-        { { 0xe449dd8f82a9a4f3l,0xa1a2f405797e6b36l,0x76913537787785e8l,
-            0x0315a3cfe064481el },
-          { 0xc02291ee83df11e2l,0x5b59a0e9bcd178f0l,0xd5e8d10ce6b4c63al,
-            0x9eee599f3fc60a82l },
-          0 },
-        /* 36 << 80 */
-        { { 0x051e589759621468l,0xb92c06327293621el,0xee17ea647762e4f2l,
-            0x412107a771abd28cl },
-          { 0xa083d87bf02d65ebl,0xbd4a3f165594395el,0x1d5694337c8882f3l,
-            0xc5eb10c55f9c63cfl },
-          0 },
-        /* 37 << 80 */
-        { { 0x4b196728c8e62c4el,0x03dbd04cb74a757cl,0xe960a65b8520f044l,
-            0x9eda0f33f7937337l },
-          { 0x06ff0b86b6dc7dfbl,0x3bd276c11fc1ac35l,0x0e67055b1b255c27l,
-            0xe43ae552eff899f8l },
-          0 },
-        /* 39 << 80 */
-        { { 0xc64c914d3b156d76l,0x784c1f61d794345dl,0xcda0c77c365d7a50l,
-            0xcc5a1e205b32dbd0l },
-          { 0x2f4e78bff90b6ac0l,0xbead62f9a2d4862dl,0xa8f67e7dcc346b53l,
-            0xa38d7ae947e59dbdl },
-          0 },
-        /* 40 << 80 */
-        { { 0x7dc1605d480aca4dl,0x08c37750ef263aabl,0xd5c6b7c93f166725l,
-            0xf99982f30ff2853bl },
-          { 0xc61b9583a8ecb64al,0x041211a91b771741l,0x50ba64154e156f97l,
-            0xb6595ea871b8954el },
-          0 },
-        /* 41 << 80 */
-        { { 0x4ae760845eb3b4eel,0xcafefdc6c62ed274l,0x4eabeacf113f790bl,
-            0x10c2cc88a5ff64c9l },
-          { 0xe7b59f8a49965d80l,0xd04884b50df07712l,0x6316ac5ba5f7bab1l,
-            0x388111d99e78a075l },
-          0 },
-        /* 43 << 80 */
-        { { 0x8d437128f24804efl,0x12a687dd7b71dd53l,0x8b8f71d96139a60el,
-            0xb047fed42a095ec7l },
-          { 0xef238041fba59ee8l,0x61b17fac64045514l,0x45b1cf4857afa184l,
-            0x8592c50a4bff5fc5l },
-          0 },
-        /* 44 << 80 */
-        { { 0x2830592394b745dcl,0x53e9ec16b09cb993l,0x59d0b57f9a134ed1l,
-            0x89d7b439c56ee0ebl },
-          { 0xc3656539991e22a2l,0xd27a89372a345043l,0x55dd5341064038eel,
-            0xc9ee3f0348cb42efl },
-          0 },
-        /* 45 << 80 */
-        { { 0x08518c631d56c1cbl,0x5650f79f31235521l,0x33fc08d648911017l,
-            0xbb8b58538a0a33c8l },
-          { 0xb54554f2f869a62al,0x67f8cf48222457e5l,0x46e13911f276cc0dl,
-            0x4b3a2ad6943b389el },
-          0 },
-        /* 46 << 80 */
-        { { 0x0e72b816b11a4c9dl,0x919b2738e9028fa4l,0xab80e1117698a5d6l,
-            0xcd7950f56cd49adal },
-          { 0x0db75c908dfb13a5l,0x2178578770f12cebl,0xfab72d5243486ff6l,
-            0x66d55d726a0673ebl },
-          0 },
-        /* 47 << 80 */
-        { { 0xe98014b922667519l,0x7fcab2b3a95da9c0l,0x9bdbccd8438d5060l,
-            0xa72fff5455a726b6l },
-          { 0x7ae032943a5e769bl,0xf7291e9b559a0734l,0x18ae4f182ce18eeel,
-            0x88e49f7328b7b4f0l },
-          0 },
-        /* 48 << 80 */
-        { { 0x90fe7a1d214aeb18l,0x1506af3c741432f7l,0xbb5565f9e591a0c4l,
-            0x10d41a77b44f1bc3l },
-          { 0xa09d65e4a84bde96l,0x42f060d8f20a6a1cl,0x652a3bfdf27f9ce7l,
-            0xb6bdb65c3b3d739fl },
-          0 },
-        /* 49 << 80 */
-        { { 0xc6a2923e60ef9d87l,0xac66cdd8c3a64f1cl,0x069292d26e0bb0ccl,
-            0x9e491414451e52a0l },
-          { 0x2e76cedf0e0d35b3l,0x311b7ae9af682b84l,0xaa1017a02f90b176l,
-            0xac0b43a794feb6e8l },
-          0 },
-        /* 51 << 80 */
-        { { 0x7ddb42f9214e82f5l,0x91c88566f67269d7l,0x1763ed8cdd0ff422l,
-            0x045dd690ad284ddfl },
-          { 0x5713bbb141e48fe7l,0xdc5bef28f8eb580fl,0x4bd0b288ed2992c2l,
-            0x436587faaf5ef2b3l },
-          0 },
-        /* 52 << 80 */
-        { { 0xbbc1a48d6e5822c4l,0x16c3135daacebd02l,0xd0c6c543b56157dfl,
-            0xae249a0ef49f44a1l },
-          { 0x1f2c23ce72c47341l,0x8f52dc2a25974313l,0x2c99bc0a958e0e6bl,
-            0xe57eab6b950cd492l },
-          0 },
-        /* 53 << 80 */
-        { { 0xea66db638934efc0l,0x7bfe479193c6f7c7l,0x78438d535ef90d99l,
-            0xe63b87c9c665736dl },
-          { 0x6de32d82db49e1bbl,0xbfa877dcd0ad1648l,0xdb2e85de1197806dl,
-            0x74e9dbd3cfee7854l },
-          0 },
-        /* 55 << 80 */
-        { { 0xd2c26e2edb6d7e0al,0x9103119a531009cdl,0xb5dc49869a8b9d54l,
-            0x4781b83bb408b427l },
-          { 0x70d98b2ccb4ba2f7l,0x112ed5d7fa8a36b8l,0x97257bc6fdde1675l,
-            0xd2a9c711db211cb7l },
-          0 },
-        /* 57 << 80 */
-        { { 0xe4aa6a06ee79fe8cl,0x06e210233dff8a54l,0x63e11ac5bf50731al,
-            0xb8b9944f544125b8l },
-          { 0xcba92c41d359aeb0l,0xd201c893249bca36l,0xfe79bd77cb501216l,
-            0x694b21488d525ba4l },
-          0 },
-        /* 59 << 80 */
-        { { 0x60c90e11ee3dde2al,0x7df08e17bb36c4a2l,0xb6c3210dcc5b3c17l,
-            0xa814180955cec91cl },
-          { 0xf4ecbc05a8193dffl,0xf43cdef8da5744fal,0x4895a6c6f12f8a2el,
-            0x44282692eb7b910al },
-          0 },
-        /* 60 << 80 */
-        { { 0x1a405e1886d6e13al,0x6a18c91827a7c67cl,0xc34877ebe127bfd7l,
-            0x3c9fab08c098e692l },
-          { 0xfe2dc65bc2066586l,0xb107603a8f68a0a9l,0x74ef0ef8127cd340l,
-            0xfe577b5b86788d87l },
-          0 },
-        /* 61 << 80 */
-        { { 0xdc7ff83c71234c81l,0xee48d9c6d868c82fl,0xb80bac5e37e4f365l,
-            0x2bfbe94efcb951c2l },
-          { 0x55829049a374d0b0l,0x2a502cada87a5fb4l,0x0742ac9d9ee840bal,
-            0x7689bf53eecd05b1l },
-          0 },
-        /* 63 << 80 */
-        { { 0x0e7f459320059c22l,0x47c273e0e49368a2l,0x5ccb960ac6946ee2l,
-            0xd8209ec48b3271b6l },
-          { 0x7fd5142cdfb9e947l,0x46a89c83ff737ab1l,0xa45f6b0282d875ecl,
-            0x19a16e0e34c296d6l },
-          0 },
-        /* 64 << 80 */
-        { { 0xeb5ddcb6ec7fae9fl,0x995f2714efb66e5al,0xdee95d8e69445d52l,
-            0x1b6c2d4609e27620l },
-          { 0x32621c318129d716l,0xb03909f10958c1aal,0x8c468ef91af4af63l,
-            0x162c429ffba5cdf6l },
-          0 },
-        /* 65 << 80 */
-        { { 0x65c93be33607927bl,0x86feaaecdae5411dl,0x4a1686c6dd2e2c3dl,
-            0xf78200068acdf51dl },
-          { 0xf82c4d0239ed3e50l,0x5ac04047b4c3a4a4l,0xbdd14d7ec34b07a7l,
-            0x9911d7027cc12db5l },
-          0 },
-        /* 71 << 80 */
-        { { 0x4ed5dbbd1751abc9l,0xaf374229a23cc54al,0x9b5fa66ea4ed3f9al,
-            0xc56dd9613d380643l },
-          { 0x7d77897144b38021l,0xdf4712d0d3584508l,0x0018e2eecd7ab168l,
-            0xc8a3a166293d29a7l },
-          0 },
-        /* 77 << 80 */
-        { { 0x34681bdb3a5a0214l,0xe188d6f1f718797el,0xaa751de7db761c5fl,
-            0x347c50324959a5cel },
-          { 0x108705fc338be49cl,0x1dc5eada95abf7a8l,0xb863808f0fc3f0b7l,
-            0x529c27c1a05c4d43l },
-          0 },
-        /* 83 << 80 */
-        { { 0xa75f90677f699f79l,0xd01cf9c866356f99l,0xf90f9b73fdfbaae7l,
-            0xe0b5f4412c304d2fl },
-          { 0x17cbfb11807f3f57l,0xe902d542af8a9eb4l,0x3335285461f89b4al,
-            0x3a51c54d3628c0ael },
-          0 },
-        /* 89 << 80 */
-        { { 0xae5fd487c704212dl,0x82dd07a565e2e32cl,0x46d4c9646c19c199l,
-            0xe7f428593778eedcl },
-          { 0x084a4e9b6dcc5ec9l,0x757e04ba2d0538b7l,0x4ec0a573a3fba4cdl,
-            0x2432a4e5c627c2fcl },
-          0 },
-        /* 95 << 80 */
-        { { 0xfde00b3094c8a424l,0x20a57d8cd224c232l,0xd6ace1a170019992l,
-            0x1a648d40697e67a3l },
-          { 0xed1fb10691338d84l,0x828004a08372bfc8l,0xb93030fefad3bfedl,
-            0x883dea23f27369ecl },
-          0 },
-        /* 101 << 80 */
-        { { 0xfbbf36a62a710d73l,0x8db834024b3cc6bbl,0xa60c47cf16d7b1fcl,
-            0xf9778fa6cd16ce8fl },
-          { 0xd77023086d14a1a6l,0x01f139cb06e8247cl,0xd89af2979770b9c1l,
-            0x94bf1ca97d9fb550l },
-          0 },
-        /* 107 << 80 */
-        { { 0xe17e2e6dc2d45f34l,0x5969d8ee26efc6cbl,0x6f175231b9219cfbl,
-            0x027f333c189f1175l },
-          { 0x5bc60fad54f6da49l,0xc52e09af8ae5c3f3l,0x6c0e3927ed07f46dl,
-            0xbfd9e598f39cf16bl },
-          0 },
-        /* 113 << 80 */
-        { { 0x9dffd95b090aefb9l,0x26db7b73637224fel,0xb78a679e92e2aa0cl,
-            0xfc7c824ffc8f895dl },
-          { 0xdc8287e8e636b3a8l,0x6b3ccc0f28b7a639l,0x38e6e2cc653de56al,
-            0x998cf6985392c3cal },
-          0 },
-        /* 116 << 80 */
-        { { 0xe68de79e57f0d6fal,0xe707b252ff9c06f7l,0x5613698a4a061697l,
-            0xd83d6453b5390352l },
-          { 0x59b007599867c708l,0xcfe24fd7b41ea7adl,0x4692abf3da5b7de6l,
-            0xd99a6f3bf0c54e8fl },
-          0 },
-        /* 119 << 80 */
-        { { 0xe8ee870dea4addc3l,0x0d1fb29559841f3el,0xdc05b5581dba2f14l,
-            0xb8bf38324e3f4600l },
-          { 0x1a909e66fd57c48al,0xb65ca4c24e2d76dfl,0x0b27755ae7c60d89l,
-            0x9fcfa75acb9003f6l },
-          0 },
-        /* 125 << 80 */
-        { { 0xbbbdf4c49e5325aal,0x6879fe11d0d1f281l,0x7a400f890633002el,
-            0xc3633c779bb79ac9l },
-          { 0x15a4cfae93ab9bc3l,0x379bbdea42594603l,0x7c61dfa257d2af3fl,
-            0x20190537b51bfb62l },
-          0 },
-    },
-    {
-        /* 0 << 88 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 88 */
-        { { 0xa80d1db6f79588c0l,0xfa52fc69b55768ccl,0x0b4df1ae7f54438al,
-            0x0cadd1a7f9b46a4fl },
-          { 0xb40ea6b31803dd6fl,0x488e4fa555eaae35l,0x9f047d55382e4e16l,
-            0xc9b5b7e02f6e0c98l },
-          0 },
-        /* 3 << 88 */
-        { { 0x4b7d0e0683a7337bl,0x1e3416d4ffecf249l,0x24840eff66a2b71fl,
-            0xd0d9a50ab37cc26dl },
-          { 0xe21981506fe28ef7l,0x3cc5ef1623324c7fl,0x220f3455769b5263l,
-            0xe2ade2f1a10bf475l },
-          0 },
-        /* 4 << 88 */
-        { { 0x9894344f3a29467al,0xde81e949c51eba6dl,0xdaea066ba5e5c2f2l,
-            0x3fc8a61408c8c7b3l },
-          { 0x7adff88f06d0de9fl,0xbbc11cf53b75ce0al,0x9fbb7accfbbc87d5l,
-            0xa1458e267badfde2l },
-          0 },
-        /* 5 << 88 */
-        { { 0x03b6c8c7dacddb7dl,0x92ed50047e1edcadl,0xa0e46c2f54080633l,
-            0xcd37663d46dec1cel },
-          { 0x396984c5f365b7ccl,0x294e3a2ae79bb95dl,0x9aa17d7727b1d3c1l,
-            0x3ffd3cfae49440f5l },
-          0 },
-        /* 7 << 88 */
-        { { 0x26679d11399f9cf3l,0x78e7a48e1e3c4394l,0x08722dea0d98daf1l,
-            0x37e7ed5880030ea3l },
-          { 0xf3731ad43c8aae72l,0x7878be95ac729695l,0x6a643affbbc28352l,
-            0xef8b801b78759b61l },
-          0 },
-        /* 9 << 88 */
-        { { 0xdcdd3709b63afe75l,0xad9d7f0b3f1af8ffl,0xdd6a8045194f4beel,
-            0x867724cc2f7d998cl },
-          { 0xd51d0aa5837751bel,0x21d6754a959a0658l,0xd2212611695f7e58l,
-            0xec4b93c2297363efl },
-          0 },
-        /* 10 << 88 */
-        { { 0x0ac1c5fab6ef26cfl,0xcd8ba0c5a39de8eel,0x11ba7537dd7796e0l,
-            0x1215933476d58d6dl },
-          { 0xf51eb76f529fda4cl,0x2fd9209ddedaa8a3l,0x555a675615efac65l,
-            0xb784c9ca7fd42fe9l },
-          0 },
-        /* 11 << 88 */
-        { { 0x8165ec11b9d1a70fl,0x01347efc384f6cael,0xe95c01a0ab7aeca9l,
-            0x459ba1c5c6c99530l },
-          { 0x38967a635cf3416bl,0x5c3761fd1e5457e2l,0x43e6077af03e9df6l,
-            0xb15d34628bd1c7f6l },
-          0 },
-        /* 13 << 88 */
-        { { 0xad87d3db35a75c49l,0xc69d800961af03c5l,0x31aef61a3a6a6c4cl,
-            0xb3292640aa10a993l },
-          { 0x959aae80aaee340fl,0xf900528e7f381a3bl,0x44ecf76e853691a3l,
-            0xa081663ce749e68el },
-          0 },
-        /* 15 << 88 */
-        { { 0x4f2782136283e34al,0x6f9fcf60fbfa315fl,0x224a2ab99b701364l,
-            0xb4b1b418f9fecadcl },
-          { 0xbf7280fe50ba1b9al,0x7e68259c33f36db9l,0x8ccb754e154c9fb0l,
-            0xf281adb1db2328f1l },
-          0 },
-        /* 16 << 88 */
-        { { 0xf92dda31be24319al,0x03f7d28be095a8e7l,0xa52fe84098782185l,
-            0x276ddafe29c24dbcl },
-          { 0x80cd54961d7a64ebl,0xe43608897f1dbe42l,0x2f81a8778438d2d5l,
-            0x7e4d52a885169036l },
-          0 },
-        /* 17 << 88 */
-        { { 0xc2a950ad2d6608bel,0xab415e2a51c3c2b6l,0xffbd2a65f5c803e7l,
-            0x3f81dc3eca908532l },
-          { 0x0ec47397c28c04f4l,0xf6c632e8153f58e8l,0xccac35f8efb4a6d8l,
-            0x22a1b677ee6d7407l },
-          0 },
-        /* 19 << 88 */
-        { { 0x276662435243c119l,0x79cb8580e707363el,0x5bf5ebf4d01682d6l,
-            0x8a980173762811e0l },
-          { 0xe2f2be1fc7547d77l,0x21a50fffb925fec6l,0x5e6cf2ef40115509l,
-            0xb69beae18faa0fc0l },
-          0 },
-        /* 21 << 88 */
-        { { 0xfa147da8cec36e75l,0xba184e5a42860484l,0xe8ec25df222fb1e6l,
-            0xce91dcb18ff8403cl },
-          { 0xf1b0e27ead7faa32l,0x097d881d42a3a205l,0xa8865dd43f8f56d4l,
-            0x624d7a451aef929dl },
-          0 },
-        /* 23 << 88 */
-        { { 0x3db0238ad01698e8l,0xbb7186dc00306082l,0x542f4377250f830el,
-            0x34b8a67dae438c50l },
-          { 0xada528a0858d8048l,0x561aa3336b57afc1l,0x8d9188e0fda35f7al,
-            0x5838d1211dcad0c5l },
-          0 },
-        /* 25 << 88 */
-        { { 0x4f97d1529f17511dl,0x8b9f012776fdb9ebl,0x53a0a72d4056e6a7l,
-            0x5ff937d64e262eeel },
-          { 0xaa64a8dc489fbe6dl,0xc19947dfea02bc69l,0x76f0bbb91492c9bel,
-            0xe53881098d89cd01l },
-          0 },
-        /* 27 << 88 */
-        { { 0x16083309456057b7l,0x2810c08040a331f6l,0x0561656c3c166929l,
-            0x16f0d8d6ed1c3999l },
-          { 0x37b6da7294697927l,0xd821c2cc23ca6c9cl,0x42ef1bdb8ca4351cl,
-            0x7ca32bad5edfa682l },
-          0 },
-        /* 28 << 88 */
-        { { 0xdc1de17d98119f10l,0x74353c5d488c36a6l,0x14aaf33a3d8e23dfl,
-            0x31e075c078baf593l },
-          { 0x0f7ca03a46d1ca3cl,0x99c5e3ac47b660c7l,0x70d0241388fe2e59l,
-            0x2e9a6be12a7ec005l },
-          0 },
-        /* 29 << 88 */
-        { { 0x4d1f087f184252b1l,0xfd3ace273f5b49c6l,0x6e874447bbb04da2l,
-            0x2347e3a1b3767ff0l },
-          { 0x990d4010f868966al,0x35320090dd658b5el,0x1105bfb974fe972al,
-            0x3961f7dc8e7ad2c6l },
-          0 },
-        /* 31 << 88 */
-        { { 0x100d8b54741e3286l,0x65d9108ef3abc7afl,0x172b450620ef8fbcl,
-            0x11bd7db2d81b8a2el },
-          { 0xf89210e1e8e41de5l,0x910613f3d98a868bl,0xbfc85241849aa909l,
-            0x68a43e21c7d3a7cal },
-          0 },
-        /* 33 << 88 */
-        { { 0x68f891479a4f8293l,0x48262328a5eb9101l,0x7eca2a178fe218b5l,
-            0xde6c22dbc733f768l },
-          { 0xde7171d108d6084dl,0xd153827a0f0f8092l,0xc7b52d8f85a9252fl,
-            0xfa29ca3a5708b31fl },
-          0 },
-        /* 34 << 88 */
-        { { 0x20518ddf9e0ad7e7l,0x33d5d079e8d28b9bl,0x1149b393d13058b0l,
-            0x708cc65586d4651dl },
-          { 0xd7fefaa694207435l,0xce882c0d96312f8fl,0x2fd5cb2059d091a7l,
-            0x4533a88a0e1ece94l },
-          0 },
-        /* 35 << 88 */
-        { { 0xceddd9b5a59c28bcl,0xaa4808f9572e2a5dl,0x38bc191999014a1el,
-            0x1aacefdaa6d85686l },
-          { 0xa59283d42a573fddl,0x84359db29c387594l,0x79994773dca3acc8l,
-            0xe4323e7654cf7653l },
-          0 },
-        /* 36 << 88 */
-        { { 0xac449695241fbd6fl,0x67c9b170081c1223l,0x16868f21b56aac6fl,
-            0x34bd8fa3f8bcb721l },
-          { 0x06b6bd33b6691c76l,0x6c924766381a7973l,0x6a12444ca54078dbl,
-            0xd02e91a96d1051ccl },
-          0 },
-        /* 37 << 88 */
-        { { 0x512f5fb35f30b344l,0xb13ade169d516885l,0x18812e9b2b468802l,
-            0xf15d730e6b28979al },
-          { 0x5015616f6889348bl,0xe0b02a0a96af0401l,0x3b02007b61204c89l,
-            0x9ece2aa7432742a4l },
-          0 },
-        /* 39 << 88 */
-        { { 0xd5f7e09c7c1cc4a1l,0x313ac04218b2d854l,0xbc4fe2a04c253b10l,
-            0x25a696a3c7080b5cl },
-          { 0x6de3cb6aef811877l,0x4d242fecd15f9644l,0xb9bfa2480ee6a136l,
-            0x8122679e9c8d181el },
-          0 },
-        /* 40 << 88 */
-        { { 0x37e5684744ddfa35l,0x9ccfc5c5dab3f747l,0x9ac1df3f1ee96cf4l,
-            0x0c0571a13b480b8fl },
-          { 0x2fbeb3d54b3a7b3cl,0x35c036695dcdbb99l,0x52a0f5dcb2415b3al,
-            0xd57759b44413ed9al },
-          0 },
-        /* 41 << 88 */
-        { { 0xc2c7daec96a8d727l,0x8a11631a17f3abf9l,0x06aba65c0ae8940al,
-            0xfca280c7873d3635l },
-          { 0x57496889ddb72b87l,0xaa9a3359320793d4l,0x11b6864d43120741l,
-            0x1877cd4e51527639l },
-          0 },
-        /* 43 << 88 */
-        { { 0x8b35ce4e6f43dfc6l,0x4114b2fe9a19f3bfl,0x8c4af8024ffa45cal,
-            0xa3ab5f869328b847l },
-          { 0x0986de3e555f30f0l,0xaae6e3eac8cb84c4l,0x2a7dcdbaa4ba01f7l,
-            0xfa32efa729f5dc6cl },
-          0 },
-        /* 44 << 88 */
-        { { 0x077379c00b33d3f8l,0x421883c67064e409l,0x2d0873d76c29c8f6l,
-            0xbfa433a3d274c0c8l },
-          { 0x56dc778f23a5891el,0xd663bf6535e2de04l,0x488fdb485db517cel,
-            0x00bba55e19b226c2l },
-          0 },
-        /* 45 << 88 */
-        { { 0x879b30ead7260d78l,0x04954ba2eac5201fl,0x3210c0e3ff2529d1l,
-            0x0743823488b470b3l },
-          { 0x8b618de48854cc0dl,0x98270d5e35b795eel,0x0e47d651aa33ca37l,
-            0x77d75fda1e87d0cfl },
-          0 },
-        /* 46 << 88 */
-        { { 0x789dbe987803fbf9l,0x940589aa17ede316l,0x032902bd85a1988cl,
-            0x43cbc0031c47f7f0l },
-          { 0xc6ff73714709148fl,0x769957122d9b8a5el,0xb4520e462597b70el,
-            0x00d19f39f67ff3b8l },
-          0 },
-        /* 47 << 88 */
-        { { 0xe2dfcef9b159f403l,0xe8e9e8d8855644afl,0x2796247163fa1068l,
-            0x400e992a968a5400l },
-          { 0xe2b9d29f56e563c1l,0xed66759c2885fabfl,0x788b6263750abdffl,
-            0x30adb00d6cbbdcacl },
-          0 },
-        /* 48 << 88 */
-        { { 0x1fe647d83d30a2c5l,0x0857f77ef78a81dcl,0x11d5a334131a4a9bl,
-            0xc0a94af929d393f5l },
-          { 0xbc3a5c0bdaa6ec1al,0xba9fe49388d2d7edl,0xbb4335b4bb614797l,
-            0x991c4d6872f83533l },
-          0 },
-        /* 49 << 88 */
-        { { 0x5548d3423fa17b28l,0x38587952823ee731l,0x8ee9b90a0a28bcd1l,
-            0xcfc029bf6676917el },
-          { 0x7e08306d2a212358l,0x66a9488dc88a66bcl,0x7a09db327d7c9e65l,
-            0x20eaf4e72cbc1790l },
-          0 },
-        /* 51 << 88 */
-        { { 0xb3095b491f2a9605l,0x7cfc4205f72691c7l,0x1544bf964d889b90l,
-            0xdc44d20ba0bbae7al },
-          { 0xee369b670b1f0b23l,0xf3ec25e818a7bdcbl,0xf614ab5df47ecf65l,
-            0x4869762f80a4a09dl },
-          0 },
-        /* 52 << 88 */
-        { { 0xedbbeee78a058fb6l,0xb9d19ddcfb09121al,0xa41bb45bd34dddcel,
-            0x2dbc80b900964bc4l },
-          { 0x4ed9137d1d6cb654l,0x1b9016db483d01c5l,0x5fc501bc6528e22el,
-            0xb2d2f8816cad646bl },
-          0 },
-        /* 53 << 88 */
-        { { 0xb57aa72a89043e56l,0x8fbca2435c5319fdl,0xe66aef43b13ce900l,
-            0x2c7c3927c3382934l },
-          { 0x434d9104a835fdf5l,0x419470b81b3b85bel,0xeaec374abeb4d448l,
-            0x26a53b51f33cda51l },
-          0 },
-        /* 55 << 88 */
-        { { 0x421f1725bb1db793l,0x20214d4f558c94a9l,0x3371233b7696092cl,
-            0x774d3fcb1902ab0el },
-          { 0x4ce223ded149aecel,0x174b260e33057bc7l,0xdf70cfa3f6effee4l,
-            0x3d8cd01f80880678l },
-          0 },
-        /* 57 << 88 */
-        { { 0x32db21862e59985cl,0x448865abaa1b39e1l,0x250ce79cd89fe98dl,
-            0x962710e763e3fb10l },
-          { 0xa8fc70561ac10e3el,0x9eed208fa3b132fbl,0xf499d638937051f5l,
-            0x27acf7ec21a9f78fl },
-          0 },
-        /* 59 << 88 */
-        { { 0x148e572a4c7b445el,0xdc10a0214dc95a4fl,0xe60e9c2e02237869l,
-            0xbfdfcb3aa393c3a4l },
-          { 0x8b799db211a64cf0l,0x1ca865ea2e16f59fl,0x865441fbd3a17e46l,
-            0x23315b9753409692l },
-          0 },
-        /* 60 << 88 */
-        { { 0x5e76fb2f286bad39l,0xbad9efe39dcad1e2l,0x60e75190edc7e904l,
-            0x6a6f063e0fecb5a5l },
-          { 0x5150ed85aed8acc3l,0xb56ccfbc6d20af6cl,0x7e0d1e982c69dbfal,
-            0xabf5628a7c7e10a9l },
-          0 },
-        /* 61 << 88 */
-        { { 0xb84af2c00df6d61fl,0x02c651c52acbaf4bl,0xfb605754afaaa0bfl,
-            0xa03f5257dff61017l },
-          { 0x9e3ffb1672762093l,0x4f9a5da0c4f40bd3l,0x37dce5220d26f8e1l,
-            0x260f736fc06a1a07l },
-          0 },
-        /* 63 << 88 */
-        { { 0xb92aba79b1077d55l,0xc52f81081a42f5f5l,0x9913f04f86e5aa99l,
-            0x6814b0b1f3c7f504l },
-          { 0xb7d61fd34d354bdal,0xf27926e39581d25el,0x97724001c2dc21adl,
-            0x835778231d5c4788l },
-          0 },
-        /* 64 << 88 */
-        { { 0x77b868cee978a1d3l,0xe3a68b337ab92d04l,0x5102979487a5b862l,
-            0x5f0606c33a61d41dl },
-          { 0x2814be276f9326f1l,0x2f521c14c6fe3c2el,0x17464d7dacdf7351l,
-            0x10f5f9d3777f7e44l },
-          0 },
-        /* 65 << 88 */
-        { { 0x53857462ff9727a2l,0xe6870e7dc68488e7l,0x276da72808c79656l,
-            0x1308eb61d86c24ebl },
-          { 0x34c43a84db0a3e56l,0x03961b5525335a59l,0xf9bc2d5805689d86l,
-            0xfa4d3c01eb29d6d6l },
-          0 },
-        /* 71 << 88 */
-        { { 0xd07dac3037d10ffal,0xb2b0a0fd8bef0a79l,0xa2e804510ec02505l,
-            0xf256c18962f55f5fl },
-          { 0x0ca3f9b10b39f4f0l,0x7bf4e1cf3bb7c8e9l,0x7a8a43f8ee11f227l,
-            0x2ad8431a3e4056ebl },
-          0 },
-        /* 77 << 88 */
-        { { 0xb8cf71ed031c1871l,0x702431806f703102l,0x9a87e1c24ec6f1b0l,
-            0xf7e6e5b4664f275dl },
-          { 0xc70a8b4e8c76b505l,0x6ba69bf2a002e9cfl,0x33ed74f7a0d8c9bfl,
-            0x17f5f4b18d9989del },
-          0 },
-        /* 83 << 88 */
-        { { 0xcd116dcb1b13a4a1l,0x591adb831c369877l,0x697be1aca6b8e80bl,
-            0xb2d4baa1b975d781l },
-          { 0xd4a9a496b16b48e7l,0x64de2d7af293997dl,0x039ae039af09a492l,
-            0x66e31a2665f3a485l },
-          0 },
-        /* 89 << 88 */
-        { { 0x110a8a42fec01a53l,0x1f5fcc1b38affab8l,0x757310ca9941a19el,
-            0x11ef95f76c29d6cbl },
-          { 0x0756bdb22dd427bal,0x8de8d44af3e16c33l,0xf9d28355e25aec52l,
-            0xeb761efc02f36465l },
-          0 },
-        /* 95 << 88 */
-        { { 0xfc83bf7454bfcd7al,0x51d861794837b6bel,0x8165b3f9801a324dl,
-            0x3a5972bc634cfd61l },
-          { 0xeecfe6d825258ed6l,0x51d968df1451ced0l,0x3010cdb8316aa0ael,
-            0xc295b8522900eaf2l },
-          0 },
-        /* 101 << 88 */
-        { { 0x5ad434a3890cc798l,0x4c17ff5e1531bce4l,0x825b5b5a5ea8e26fl,
-            0xacca9d5dd66fd7b3l },
-          { 0xb647dbde37ae6f92l,0xa5594868f3600416l,0x7b90ac53ab0c5d63l,
-            0x4b66ad7ceb43e1d0l },
-          0 },
-        /* 107 << 88 */
-        { { 0x04a211fac09ccbffl,0x9c96ad9ee873d898l,0x9eb1deb69c481f86l,
-            0xb3616ce8b2d70298l },
-          { 0x67a6fe9b9073726dl,0x5b8aa37d4c9bf744l,0xf558603ebb6aa0efl,
-            0x72767f5103d304fbl },
-          0 },
-        /* 113 << 88 */
-        { { 0x787cb8b8d6e9b7e3l,0x8bb30222e079fc68l,0x651a2ea6e3145a0bl,
-            0x0254c5da9ab18fa8l },
-          { 0x83722ffc12e1611fl,0xb0ddf1ffa7cc61bel,0x7c9c7e10ac0ac8d7l,
-            0x8241a8191da12218l },
-          0 },
-        /* 116 << 88 */
-        { { 0x70bb7719bc407e6el,0x231328efd84ceb41l,0x8bca6a1fc104bb20l,
-            0xd6f4e425280b9071l },
-          { 0xb41b95a292896a82l,0x735cf435fa34df67l,0xbc331a08d9d6d769l,
-            0x579786052682747el },
-          0 },
-        /* 119 << 88 */
-        { { 0x048ba499eb3af9a9l,0x43a8c367d50b82cel,0xedf9e2b21e0724d9l,
-            0x3098aab3d607140bl },
-          { 0xd1f18f1e5ed49eb9l,0xf9c6bb6ae0bb02a2l,0x204f96aa0cd245ddl,
-            0xdaadaf4afb011ed5l },
-          0 },
-        /* 125 << 88 */
-        { { 0xb298ce2de50404b1l,0x04dd38c45bf9b581l,0x229deabdfada51e8l,
-            0x74bd233f8788a132l },
-          { 0x951ba5ecf03e6c30l,0x9da2f5aa45bf1a41l,0x6bec7fea7e52b860l,
-            0x76e3778964b0a9ddl },
-          0 },
-    },
-    {
-        /* 0 << 96 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 96 */
-        { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l,
-            0x8589fb9206d54831l },
-          { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l,
-            0xebb0696d02541c4fl },
-          0 },
-        /* 3 << 96 */
-        { { 0xb99f0e0399375235l,0x7614c847b9917970l,0xfec93ce9524ec067l,
-            0xe40e7bf89b122520l },
-          { 0xb5670631ee4c4774l,0x6f03847a3b04914cl,0xc96e9429dc9dd226l,
-            0x43489b6c8c57c1f8l },
-          0 },
-        /* 4 << 96 */
-        { { 0x0e299d23fe67ba66l,0x9145076093cf2f34l,0xf45b5ea997fcf913l,
-            0x5be008438bd7dddal },
-          { 0x358c3e05d53ff04dl,0xbf7ccdc35de91ef7l,0xad684dbfb69ec1a0l,
-            0x367e7cf2801fd997l },
-          0 },
-        /* 5 << 96 */
-        { { 0x46ffd227cc2338fbl,0x89ff6fa990e26153l,0xbe570779331a0076l,
-            0x43d241c506e1f3afl },
-          { 0xfdcdb97dde9b62a3l,0x6a06e984a0ae30eal,0xc9bf16804fbddf7dl,
-            0x170471a2d36163c4l },
-          0 },
-        /* 7 << 96 */
-        { { 0x361619e455950cc3l,0xc71d665c56b66bb8l,0xea034b34afac6d84l,
-            0xa987f832e5e4c7e3l },
-          { 0xa07427727a79a6a7l,0x56e5d017e26d6c23l,0x7e50b97638167e10l,
-            0xaa6c81efe88aa84el },
-          0 },
-        /* 9 << 96 */
-        { { 0x473959d74d325bbfl,0x2a61beec8d6114b9l,0x25672a94924be2eel,
-            0xa48595dbf2c23d0cl },
-          { 0xe476848b6a221838l,0xe743e69a35c1b673l,0x2ab42499d8468503l,
-            0x62aa0054e9e90ba7l },
-          0 },
-        /* 10 << 96 */
-        { { 0x358d13f1bc482911l,0x685d1971b7fa7f26l,0x3e67a51d2be1aee4l,
-            0xe041850998d114a9l },
-          { 0x59639f604e052561l,0x32075c49155d0818l,0x2aa2343b67b64b1cl,
-            0x1b445e2967f53e6al },
-          0 },
-        /* 11 << 96 */
-        { { 0xbdfb271773a904e0l,0x7ce1e40b28888d73l,0x2e7e35f6eaa97d1bl,
-            0xd061772aa9afa097l },
-          { 0x434ac7c47a1f7c59l,0x6e21124ae79b7b9al,0x055acff3bb22ecc7l,
-            0x8bfd7ac984c858d3l },
-          0 },
-        /* 13 << 96 */
-        { { 0x2fd57df59f1f68adl,0x5ddcc6dbb06470c8l,0x801b6451a9b47307l,
-            0x6b51c8e376551bf4l },
-          { 0xef0bd1f7d44e1da9l,0x714bcb1d4d4e600cl,0xc57bb9e40c6540c7l,
-            0x71bd1ec2327cc644l },
-          0 },
-        /* 15 << 96 */
-        { { 0x9a52cf7e7f4dd81fl,0xa0132be15e69c05el,0x90dab7472a0f4d72l,
-            0xc142f911312d6706l },
-          { 0xe8d3631f8261998bl,0xf0f42fae615c1c94l,0x2f4e948caec3fa5dl,
-            0x242ae7a8a374101el },
-          0 },
-        /* 16 << 96 */
-        { { 0x0f893a5dc8de610bl,0xe8c515fb67e223cel,0x7774bfa64ead6dc5l,
-            0x89d20f95925c728fl },
-          { 0x7a1e0966098583cel,0xa2eedb9493f2a7d7l,0x1b2820974c304d4al,
-            0x0842e3dac077282dl },
-          0 },
-        /* 17 << 96 */
-        { { 0x1fa878cad088be52l,0x89c2cb07a9e1e656l,0x385bc5c3219d62dbl,
-            0xd82b676b5fda2752l },
-          { 0x2449dc9ee304eafcl,0x1e9e7991632f4ea2l,0x3036e061cdd5e0b9l,
-            0x75a6f6ff830825bcl },
-          0 },
-        /* 19 << 96 */
-        { { 0xb10fcddc449dedb4l,0x2c890042d1244acfl,0x9b3072cac7fc7017l,
-            0x1acda6859ce8063fl },
-          { 0xd243313c7f51e2f5l,0x52a3f1a4d73d9578l,0xda785b7a64f0ce6el,
-            0x2e766315442a4c2dl },
-          0 },
-        /* 21 << 96 */
-        { { 0x94f9b004151f111al,0xc7a5035b07dbc5fal,0x53958ea7609e49d7l,
-            0x0526b4d79013f4c0l },
-          { 0x66de5ebb593e2fbdl,0x6e7cf8b44c2e0c37l,0x6f72fc8b8c983e78l,
-            0x6fab9b632348f9d7l },
-          0 },
-        /* 23 << 96 */
-        { { 0xc748a3526a3d8468l,0x3fab479927e38032l,0x91ad3629fa430ce7l,
-            0xc5af0b2c71614c44l },
-          { 0xcede3fa50c211611l,0x6e6889ba02338083l,0xee0a195977f0fe32l,
-            0x01ea905d0f4bbc5al },
-          0 },
-        /* 25 << 96 */
-        { { 0x12cfb25e8193db48l,0xddb4ae633bea708cl,0xdaae102ef181f821l,
-            0x9d9d923024a089d9l },
-          { 0x71c4122da0876aeal,0x1a63ea3bbbe19c09l,0x3b898076016f8d0cl,
-            0xa5cccc5daea6b713l },
-          0 },
-        /* 27 << 96 */
-        { { 0xc3f22baf4a8e2f61l,0x77d29ede176da6a6l,0x40a55f211607da63l,
-            0x858b38561452e391l },
-          { 0x0dd3c267fe1b3c56l,0x66c04bdd7d55227al,0xfbd2fe55e6404e09l,
-            0x5981cf49ea9cfcbcl },
-          0 },
-        /* 28 << 96 */
-        { { 0xe549237f78890732l,0xc443bef953fcb4d9l,0x9884d8a6eb3480d6l,
-            0x8a35b6a13048b186l },
-          { 0xb4e4471665e9a90al,0x45bf380d653006c0l,0x8f3f820d4fe9ae3bl,
-            0x244a35a0979a3b71l },
-          0 },
-        /* 29 << 96 */
-        { { 0xae46a902aea870afl,0xa9b9fcf57cbedc99l,0x74f2ca3f79b7e793l,
-            0xadb8f2231dbeeb28l },
-          { 0x6302060e6764df85l,0x363320d257ebd554l,0xd9fd573e798d22e1l,
-            0x285f85f5ebb67dedl },
-          0 },
-        /* 31 << 96 */
-        { { 0xd86b329211caa2b5l,0x2a26258e39337bd1l,0x4dc5a9b579c8c291l,
-            0x16443d87741942e6l },
-          { 0x6bc9a2f8f811400cl,0x819c69359eeb4e0el,0xe1be7273ce0c214bl,
-            0x429afb8184b61581l },
-          0 },
-        /* 33 << 96 */
-        { { 0xb37e188756af5812l,0xd662bdb485aff83el,0xc89742d07bc63de7l,
-            0xea103f9d0279f487l },
-          { 0x4d26916a3a6cc639l,0x4eea3a3c7c743b94l,0x6a3e0dc7007376d9l,
-            0xdb6ef3cf573f904el },
-          0 },
-        /* 34 << 96 */
-        { { 0x9b1058ecb0b0fb53l,0x8955f5f75f8a9a9fl,0xf5f92e7f9f6f9e6dl,
-            0x03f5df6c50ec198bl },
-          { 0x6c8741f2b8aedbcel,0x8f4e60cfed8018f7l,0x6ca5297c9fa01f89l,
-            0x8591cf7a864995dbl },
-          0 },
-        /* 35 << 96 */
-        { { 0xa126147eb0a11b9bl,0xeedcc9e198900232l,0x15d94f8c2bead119l,
-            0x042423cfefc38691l },
-          { 0x6ce86fbe77165d91l,0xa07732126b3fd565l,0x8cdc409150b1f9c7l,
-            0x7f5ad1af064595acl },
-          0 },
-        /* 36 << 96 */
-        { { 0xed374a6658926dddl,0x138b2d49908015b8l,0x886c6579de1f7ab8l,
-            0x888b9aa0c3020b7al },
-          { 0xd3ec034e3a96e355l,0xba65b0b8f30fbe9al,0x064c8e50ff21367al,
-            0x1f508ea40b04b46el },
-          0 },
-        /* 37 << 96 */
-        { { 0x73644c158f8402a0l,0x0d9b5354f4730eb9l,0x78542af4e94cc278l,
-            0xf4dbede3e395f33al },
-          { 0x8fe8cbc590c70b00l,0x9c35bb2d7db197f6l,0x229b4973e6599746l,
-            0x0817d04e1a84b986l },
-          0 },
-        /* 39 << 96 */
-        { { 0x8ffe34e95ecd09b3l,0x6a7c3de4153b7cael,0xf02713e4a81044b7l,
-            0x85ca6158c70545c8l },
-          { 0xd3ff392845d88bffl,0x3a251a07f0bafe89l,0x61290e1287cea7f4l,
-            0xa360a17efa4808adl },
-          0 },
-        /* 40 << 96 */
-        { { 0x98561a49747c866cl,0xbbb1e5fe0518a062l,0x20ff4e8becdc3608l,
-            0x7f55cded20184027l },
-          { 0x8d73ec95f38c85f0l,0x5b589fdf8bc3b8c3l,0xbe95dd980f12b66fl,
-            0xf5bd1a090e338e01l },
-          0 },
-        /* 41 << 96 */
-        { { 0x2d1751083edf4e2bl,0x30e6e90fa29c10d0l,0xfee1eb14c9c6ccd2l,
-            0x244670c756a81453l },
-          { 0x90b33eefc5185c22l,0xd77ae4b63db82d28l,0xce5ee034f228f940l,
-            0x5d7660847bb47be5l },
-          0 },
-        /* 43 << 96 */
-        { { 0x88b7eec499b9a8c6l,0x56048d9e14e8ef0cl,0xa18f93215c89cf78l,
-            0xbd2087616d327e66l },
-          { 0x5b187225d9e53e27l,0xa57ca6c7bf4d0317l,0x187731d2e9557736l,
-            0xd4ce2f78a874982el },
-          0 },
-        /* 44 << 96 */
-        { { 0x65163ae55e915918l,0x6158d6d986f8a46bl,0x8466b538eeebf99cl,
-            0xca8761f6bca477efl },
-          { 0xaf3449c29ebbc601l,0xef3b0f41e0c3ae2fl,0xaa6c577d5de63752l,
-            0xe916660164682a51l },
-          0 },
-        /* 45 << 96 */
-        { { 0xf5b602bb29f47deal,0x42853c9659ddd679l,0x5c25be4041d7c001l,
-            0x8e069399d4a3b307l },
-          { 0x1782152e736ce467l,0x2e264109c9cb4f08l,0xf900cb11ab124698l,
-            0x1bbed1d02d6e05b1l },
-          0 },
-        /* 46 << 96 */
-        { { 0x9cc3fedc7da08b1fl,0x0f44949361d5ed38l,0xc8cbc4209b991b6bl,
-            0xee62a342891c42e1l },
-          { 0x11c496bb1a179139l,0x94ece2892eac4d8el,0x35f303a5a98d5570l,
-            0x69d4340514a31552l },
-          0 },
-        /* 47 << 96 */
-        { { 0x29d45e50892dfcbal,0x653e613e5c30cee3l,0x7b8c1ae61868a348l,
-            0x40ab51654f2c612al },
-          { 0x56e977f9891cdc8cl,0xee1ca12a34ca7cd1l,0xa4e283ee17b5ddf8l,
-            0x4e36f2fb6f536205l },
-          0 },
-        /* 48 << 96 */
-        { { 0x5a3097befc15aa1el,0x40d12548b54b0745l,0x5bad4706519a5f12l,
-            0xed03f717a439dee6l },
-          { 0x0794bb6c4a02c499l,0xf725083dcffe71d2l,0x2cad75190f3adcafl,
-            0x7f68ea1c43729310l },
-          0 },
-        /* 49 << 96 */
-        { { 0xa3834d85e89ea13fl,0x2ca00f942db803bbl,0x0f378681400ed3dal,
-            0x1028af6b54854da3l },
-          { 0x3928c2da06400c7fl,0x21119785d82aac92l,0x06618c17724e4af0l,
-            0x22b42b161470736bl },
-          0 },
-        /* 51 << 96 */
-        { { 0x7d0cfd48f7f2ac65l,0x46e1ac705f641b60l,0x0ab9566a0fcf0137l,
-            0xbd4380e0db460fb8l },
-          { 0x4550efbf6db99b55l,0x33846e669764b744l,0xacffa0cae34ca007l,
-            0xce642d6a077e646cl },
-          0 },
-        /* 52 << 96 */
-        { { 0xe747c8c7b7ffd977l,0xec104c3580761a22l,0x8395ebaf5a3ffb83l,
-            0xfb3261f4e4b63db7l },
-          { 0x53544960d883e544l,0x13520d708cc2eeb8l,0x08f6337bd3d65f99l,
-            0x83997db2781cf95bl },
-          0 },
-        /* 53 << 96 */
-        { { 0xd89112c47d8037a3l,0xcba48ad3464c2025l,0x3afea8399814a09dl,
-            0x69e52260269030b5l },
-          { 0x5b7067365c674805l,0x8c3fd33d87343f56l,0xc572c858b1c61edfl,
-            0x43d8f4ded06749cbl },
-          0 },
-        /* 55 << 96 */
-        { { 0x04da1f06b4066003l,0xf7d4e52f372749e8l,0x56cd667114b38747l,
-            0x1943a22a22eb6d9el },
-          { 0xc2c5391990714b0al,0xb6e3abb7d13cf3ael,0xfcd8d671676115cbl,
-            0x178ce1a0c06a0d3al },
-          0 },
-        /* 57 << 96 */
-        { { 0x94485b36913508f8l,0x92f87fe36de83b42l,0xedd476f0ed77e666l,
-            0xee90fbc68da2cf53l },
-          { 0x6f4afc53fc6cf3d9l,0x231bceb9f21f6ecfl,0x6504a11d494c6e9cl,
-            0xd3728f032c211461l },
-          0 },
-        /* 59 << 96 */
-        { { 0x09a9b93799562ca2l,0xb7d5c5cf6a5a5aa8l,0x52f5d7b9987b219dl,
-            0x33849f9ec38014d4l },
-          { 0x299adaf628f23880l,0x738ecc8874875588l,0x39d707adca2af665l,
-            0xc8c11f688f4c5f73l },
-          0 },
-        /* 60 << 96 */
-        { { 0x68e4f15e9afdfb3cl,0x49a561435bdfb6dfl,0xa9bc1bd45f823d97l,
-            0xbceb5970ea111c2al },
-          { 0x366b455fb269bbc4l,0x7cd85e1ee9bc5d62l,0xc743c41c4f18b086l,
-            0xa4b4099095294fb9l },
-          0 },
-        /* 61 << 96 */
-        { { 0x2ae046d66aa34757l,0x34db1addaa6d7e9dl,0x2b4b7e017ccf432bl,
-            0xfbe0bfa590d319c6l },
-          { 0xfb2981687ec7a7f2l,0x346cc46004f5132el,0x782b2e53b40aceddl,
-            0x402e1d64e3f0b8b9l },
-          0 },
-        /* 63 << 96 */
-        { { 0x2aa3b21d25a56088l,0xae6ee57543d08962l,0x669e42bff1e22297l,
-            0x7b4c635732e3a47al },
-          { 0x22b16260ea464a25l,0xad8ca59072d5cd7al,0x7c244266104eb96al,
-            0x1def95e28e7c11d2l },
-          0 },
-        /* 64 << 96 */
-        { { 0x9c7c581d26ee8382l,0xcf17dcc5359d638el,0xee8273abb728ae3dl,
-            0x1d112926f821f047l },
-          { 0x1149847750491a74l,0x687fa761fde0dfb9l,0x2c2580227ea435abl,
-            0x6b8bdb9491ce7e3fl },
-          0 },
-        /* 65 << 96 */
-        { { 0x1f04524cdc27e1f7l,0xa0c74f61572eab14l,0xdd5d0cfced272074l,
-            0x95533c1d5bfe4f65l },
-          { 0x3039d57ecce817cal,0x029967d73b822082l,0x9fca43866c4a10d3l,
-            0xf8b2a7f0bb4968ebl },
-          0 },
-        /* 71 << 96 */
-        { { 0x933cd6dcbfbf6407l,0xd08f21504be673f8l,0x0e1c4d0db1140a2el,
-            0x0502a092431b270al },
-          { 0x5d99f9508768c00al,0xda3ce5079b3ff3c7l,0x1c648b75031c11abl,
-            0x5e3de47bf2776305l },
-          0 },
-        /* 77 << 96 */
-        { { 0xe22af9274d2b9de4l,0xf3690f55a69609ecl,0x20260a6e453fbe18l,
-            0x8edcb46b42d0b085l },
-          { 0xd4ef250b7d9c7f58l,0x5e8578dfc83c3433l,0x9751d9b9e46e320al,
-            0xb02bd03cf3c58af6l },
-          0 },
-        /* 83 << 96 */
-        { { 0x0ab299ede1b4d1ccl,0x22e7301cec4d18d2l,0xf2380f2a7b86d4ffl,
-            0xca19ef9e40753713l },
-          { 0x52bb0d24678c38a1l,0xcc9d6fd499001c02l,0xa2dd6b00bc5876e4l,
-            0xfe04b402409fe2b3l },
-          0 },
-        /* 89 << 96 */
-        { { 0x7db986b1ff69f8d3l,0x648865e59d6266b9l,0x7ccfe96183f7dae5l,
-            0x0f59a8bd6828379bl },
-          { 0xad97e5ef0ac7c4e8l,0xa75914be784e9c18l,0x053e015bb18c1bb8l,
-            0x18f6cefcb347043el },
-          0 },
-        /* 95 << 96 */
-        { { 0xb4d641bdf257c38al,0xadcea4d0c1372574l,0x7f8d20be71c8f0d0l,
-            0x14a1d24c41dc6344l },
-          { 0xe446054e41f35526l,0x4664213823c952ddl,0xfbde483401f6b0acl,
-            0xc89eee66d75b6318l },
-          0 },
-        /* 101 << 96 */
-        { { 0x700242937a087392l,0xd42bd3aad5da04del,0xee64cb5b1f803414l,
-            0xd6341ecbbab52988l },
-          { 0x7ad522f343170a74l,0x5fba22536d61d9del,0x230304c1e845a6e5l,
-            0xd69feabfbc9e326bl },
-          0 },
-        /* 107 << 96 */
-        { { 0xef7e49412e8a11d7l,0x4cb8963662c8bae1l,0xecc741198aad5816l,
-            0x13490782c7af5175l },
-          { 0x10c701f73e91a604l,0xcb8c6c7124cc30c1l,0xce0d479c071eb382l,
-            0xa3dc71fb058087d4l },
-          0 },
-        /* 113 << 96 */
-        { { 0xec368492541eb6d1l,0x567735d6e09a94abl,0xb8039ec172350329l,
-            0x3bd83a8f4894ddafl },
-          { 0x740ef2a39c07063dl,0xba25e72277da7b59l,0xb09e248e3bf42e82l,
-            0x7ff36da0b017d037l },
-          0 },
-        /* 116 << 96 */
-        { { 0xca80416651b8d9a3l,0x42531bc90ffb0db1l,0x72ce4718aa82e7cel,
-            0x6e199913df574741l },
-          { 0xd5f1b13dd5d36946l,0x8255dc65f68f0194l,0xdc9df4cd8710d230l,
-            0x3453c20f138c1988l },
-          0 },
-        /* 119 << 96 */
-        { { 0x913f23b9ed08ac04l,0x18e336643590d098l,0xd3f72934e67536dcl,
-            0xf949a757ec7ecde9l },
-          { 0x37fc6583cf9cbd37l,0xcbe62cc043b1228el,0x777124948a743274l,
-            0x3ea3668c716ce6f1l },
-          0 },
-        /* 125 << 96 */
-        { { 0xc89ce010a90d375bl,0x39ac669340503fe3l,0x9036f782d33ecb0el,
-            0x5190656841fdc7d1l },
-          { 0xbefd136e917d94cdl,0x05fea2f22a511b24l,0x80e62d76f9076e0cl,
-            0x8c57635e418ba653l },
-          0 },
-    },
-    {
-        /* 0 << 104 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 104 */
-        { { 0x20d3c982cf7d62d2l,0x1f36e29d23ba8150l,0x48ae0bf092763f9el,
-            0x7a527e6b1d3a7007l },
-          { 0xb4a89097581a85e3l,0x1f1a520fdc158be5l,0xf98db37d167d726el,
-            0x8802786e1113e862l },
-          0 },
-        /* 3 << 104 */
-        { { 0xf6e894d1f4c6b6ecl,0x526b082718b3cd9bl,0x73f952a812117fbfl,
-            0x2be864b011945bf5l },
-          { 0x86f18ea542099b64l,0x2770b28a07548ce2l,0x97390f28295c1c9cl,
-            0x672e6a43cb5206c3l },
-          0 },
-        /* 4 << 104 */
-        { { 0xc37c7dd0c55c4496l,0xa6a9635725bbabd2l,0x5b7e63f2add7f363l,
-            0x9dce37822e73f1dfl },
-          { 0xe1e5a16ab2b91f71l,0xe44898235ba0163cl,0xf2759c32f6e515adl,
-            0xa5e2f1f88615eecfl },
-          0 },
-        /* 5 << 104 */
-        { { 0xcacce2c847c64367l,0x6a496b9f45af4ec0l,0x2a0836f36034042cl,
-            0x14a1f3900b6c62eal },
-          { 0xe7fa93633ef1f540l,0xd323b30a72a76d93l,0xffeec8b50feae451l,
-            0x4eafc172bd04ef87l },
-          0 },
-        /* 7 << 104 */
-        { { 0xe4435a51b3e59b89l,0x136139554133a1c9l,0x87f46973440bee59l,
-            0x714710f800c401e4l },
-          { 0xc0cf4bced6c446c9l,0xe0aa7fd66c4d5368l,0xde5d811afc68fc37l,
-            0x61febd72b7c2a057l },
-          0 },
-        /* 9 << 104 */
-        { { 0x27375fe665f837e2l,0x93f8c68bd882179fl,0x584feadc59b16187l,
-            0xe5b50be9483bc162l },
-          { 0x7ad9d6f1a2776625l,0xe9d1008004ff457bl,0x5b56d322677618a6l,
-            0x036694eae3e68673l },
-          0 },
-        /* 10 << 104 */
-        { { 0x6ca4f87e822e37bel,0x73f237b4253bda4el,0xf747f3a241190aebl,
-            0xf06fa36f804cf284l },
-          { 0x0a6bbb6efc621c12l,0x5d624b6440b80ec6l,0x4b0724257ba556f3l,
-            0x7fa0c3543e2d20a8l },
-          0 },
-        /* 11 << 104 */
-        { { 0x6feaffc51d8a4fd1l,0x59663b205f1ad208l,0xefc93cef24acb46al,
-            0x54929de05967118cl },
-          { 0x885708009acffb1cl,0x492bbf2b145639ecl,0x71f495a638f0018el,
-            0xe24365dbc2792847l },
-          0 },
-        /* 13 << 104 */
-        { { 0x4bedae86a6f29002l,0x7abedb56e034457al,0x8bf3eec6179bff2al,
-            0x9d626d57390f4e6bl },
-          { 0x653fe0e914dd6ea3l,0x7483715989bd6d08l,0x85fb05b4ebd9b03dl,
-            0x7dc3f2214a768bbcl },
-          0 },
-        /* 15 << 104 */
-        { { 0xaacc63f132b0ed8fl,0x041237242bafefd2l,0x0df9a7987e2d2a13l,
-            0x09bd13cf9c27591fl },
-          { 0xaa5f5e476e1afb50l,0xcd146a42b66eb646l,0x3f07561d1442ec3cl,
-            0x7e5471738ae8ec47l },
-          0 },
-        /* 16 << 104 */
-        { { 0x8de2b7bc453cadd6l,0x203900a7bc0bc1f8l,0xbcd86e47a6abd3afl,
-            0x911cac128502effbl },
-          { 0x2d550242ec965469l,0x0e9f769229e0017el,0x633f078f65979885l,
-            0xfb87d4494cf751efl },
-          0 },
-        /* 17 << 104 */
-        { { 0x2c3e61196c0c6cd5l,0x5e01a49a99f4aac8l,0xfa518fc92ef1565el,
-            0xf64ff8714f772366l },
-          { 0x52fcbc2b726420d0l,0x30fbf6eb76cfa9eel,0x0bd17139fa618268l,
-            0x23ed6e122087535dl },
-          0 },
-        /* 19 << 104 */
-        { { 0x76098e38bb4ccb2cl,0x44e88aeeafbad6d1l,0x5c4d286771928778l,
-            0xb1df868138534c94l },
-          { 0x67eb8f4d77ce9debl,0x2a86d0461a77c55dl,0xc327181e46a6a3e7l,
-            0x68fd611b8710e206l },
-          0 },
-        /* 21 << 104 */
-        { { 0xc093f3fc0c82bdf1l,0x21db25894f76c4a6l,0xf3dcb22ee410a7ael,
-            0x1db37114f3c22ffel },
-          { 0x9bd0a1fb58f6801dl,0x2cab103bd1b55cc8l,0x2ae1a7f5077ba4b2l,
-            0x82b46642ce5ab2b3l },
-          0 },
-        /* 23 << 104 */
-        { { 0xc8477ec52546684cl,0xe3f9387702ff02b5l,0xefb72133ae5d04cdl,
-            0x644905c339f10d02l },
-          { 0x1750c87c13d8d356l,0x0e9b8063b41e7640l,0xc7ece04f5647b05bl,
-            0x89a43da7ca9df9c4l },
-          0 },
-        /* 25 << 104 */
-        { { 0x02610ef1920eb7d9l,0x34bd2fc2e1ea1dc0l,0xcb89da255170b890l,
-            0xaaa2796461cff827l },
-          { 0xc308c9d37103ed6al,0xe82d63d5a467564al,0x94c897c4a0fa7732l,
-            0x75eb52fa64c7aa5fl },
-          0 },
-        /* 27 << 104 */
-        { { 0x52582f9cb985fcb6l,0xaaef8d9f8508a691l,0x494c2c346e505131l,
-            0x6d062362d55f30f6l },
-          { 0x70059e9122e1e32fl,0x1507c3fe9e51abb0l,0xd8aba31b2b7bda72l,
-            0x5acbc5f77b753f13l },
-          0 },
-        /* 28 << 104 */
-        { { 0x15bfb8bf5116f937l,0x7c64a586c1268943l,0x71e25cc38419a2c8l,
-            0x9fd6b0c48335f463l },
-          { 0x4bf0ba3ce8ee0e0el,0x6f6fba60298c21fal,0x57d57b39ae66bee0l,
-            0x292d513022672544l },
-          0 },
-        /* 29 << 104 */
-        { { 0x075dc81953952ff6l,0xd4d9eeda20b7384dl,0x8a81c1bfd2d6c6a5l,
-            0x319368a0db050f3bl },
-          { 0x91f476de31f1cee2l,0x1b38604500d0e17fl,0xed2081889a820384l,
-            0x8d00c411a0f1a637l },
-          0 },
-        /* 31 << 104 */
-        { { 0xb029b687a47fd8f0l,0xa531360696371a05l,0x7b84e88c5ab09140l,
-            0x87dad7c85eeb1d14l },
-          { 0xef0749b9d0edf6f3l,0x29fc7310e2ef198bl,0x01e05df5069ed399l,
-            0x121db4ecdf4e2fcal },
-          0 },
-        /* 33 << 104 */
-        { { 0xe730f3f62826bee0l,0xb9bdbe3fce332a8fl,0x1ecad11766ec00aal,
-            0x7503d835617a62d1l },
-          { 0x9f34e161b862b139l,0xde42194cf30f6a67l,0x5037a953c1e879fel,
-            0x62f321f89bda45dbl },
-          0 },
-        /* 34 << 104 */
-        { { 0xe87771d8033f2876l,0xb0186ec67d5cc3dbl,0x58e8bb803bc9bc1dl,
-            0x4d1395cc6f6ef60el },
-          { 0xa73c62d6186244a0l,0x918e5f23110a5b53l,0xed4878ca741b7eabl,
-            0x3038d71adbe03e51l },
-          0 },
-        /* 35 << 104 */
-        { { 0xcbdba27c40234d55l,0x24352b6cb3eb56c9l,0xae681b85a8e9295al,
-            0x2a6cfba1f1171664l },
-          { 0x49f045838ca40c3cl,0xe56da25c6eb0f8eal,0x8e62f86fc4341a4el,
-            0x7f68bdc64c3f947fl },
-          0 },
-        /* 36 << 104 */
-        { { 0x840204b7a93c3246l,0x21ab6069a0b9b4cdl,0xf5fa6e2bb1d64218l,
-            0x1de6ad0ef3d56191l },
-          { 0x570aaa88ff1929c7l,0xc6df4c6b640e87b5l,0xde8a74f2c65f0cccl,
-            0x8b972fd5e6f6cc01l },
-          0 },
-        /* 37 << 104 */
-        { { 0x862013c00bf22173l,0xfd004c834acd8e23l,0x50e422ca310b1649l,
-            0xe6d04de65bbe1854l },
-          { 0x651f646385761ef3l,0x3b17d38652cf85c9l,0xbdce284a5f54ecc7l,
-            0x72efcd3ec7c2106cl },
-          0 },
-        /* 39 << 104 */
-        { { 0x34324b182ff07e3el,0x29938f38f50bcb71l,0xd0e3d7b977e2bcc3l,
-            0x8e78f007c0a3292bl },
-          { 0xfa28c530005c2c00l,0x6f9c21d51faa0c5al,0x3df01abd7b9c78f3l,
-            0x0e5618c1ccaaeb7el },
-          0 },
-        /* 40 << 104 */
-        { { 0xaa6778fce7560b90l,0xb4073e61a7e824cel,0xff0d693cd642eba8l,
-            0x7ce2e57a5dccef38l },
-          { 0x89c2c7891df1ad46l,0x83a06922098346fdl,0x2d715d72da2fc177l,
-            0x7b6dd71d85b6cf1dl },
-          0 },
-        /* 41 << 104 */
-        { { 0x4601a6a492ad3889l,0xdc8e3364d9a0709fl,0x0c687f2b2c260327l,
-            0xe882af62e1a79573l },
-          { 0x0cfd00ab945d9017l,0xe6df7505d0e3c188l,0xb389a66dbde825a2l,
-            0x126d77b6bcd8e14fl },
-          0 },
-        /* 43 << 104 */
-        { { 0xc800acc7db18ec73l,0x0ebecc78d86e99efl,0x675796cdbd05bc5fl,
-            0x254498126afd7c7fl },
-          { 0x96293b695969b165l,0xd8514d83c162c8dal,0xe174f8b674a15a5cl,
-            0x880d687389a2f73cl },
-          0 },
-        /* 44 << 104 */
-        { { 0x53703a328300129fl,0x1f63766268c43bfdl,0xbcbd191300e54051l,
-            0x812fcc627bf5a8c5l },
-          { 0x3f969d5f29fb85dal,0x72f4e00a694759e8l,0x426b6e52790726b7l,
-            0x617bbc873bdbb209l },
-          0 },
-        /* 45 << 104 */
-        { { 0xf536f07cad1deb2el,0x2a13a11ea87a710el,0x0ce2ccab64f4dc96l,
-            0x16178694f5a55464l },
-          { 0x1496168da2cb3986l,0xb079a5b9d56a93a9l,0x97005e99092893d3l,
-            0x55df5ed6e8fcc6c3l },
-          0 },
-        /* 46 << 104 */
-        { { 0x511f8bb997aee317l,0x812a4096e81536a8l,0x137dfe593ac09b9bl,
-            0x0682238fba8c9a7al },
-          { 0x7072ead6aeccb4bdl,0x6a34e9aa692ba633l,0xc82eaec26fff9d33l,
-            0xfb7535121d4d2b62l },
-          0 },
-        /* 47 << 104 */
-        { { 0x821dca8bbf328b1cl,0x24596ddd5a3d6830l,0x061c4c15635b5b4cl,
-            0x0e2b3bef4fa3560al },
-          { 0xffced37498906c43l,0x10ebd174e26b3784l,0x7cd068c470039bb5l,
-            0xc47dda0f88404e59l },
-          0 },
-        /* 48 << 104 */
-        { { 0x1a0445ff1d7aadabl,0x65d38260d5f6a67cl,0x6e62fb0891cfb26fl,
-            0xef1e0fa55c7d91d6l },
-          { 0x47e7c7ba33db72cdl,0x017cbc09fa7c74b2l,0x3c931590f50a503cl,
-            0xcac54f60616baa42l },
-          0 },
-        /* 49 << 104 */
-        { { 0x7ad7d13569185235l,0x19771949fb69e030l,0xd4de9717bc45fb4fl,
-            0x5657b076167e5739l },
-          { 0x9503a71fdd27449el,0xfa2fabf73cc01347l,0xf8ecef24c83fb301l,
-            0x527012bd5a8d5078l },
-          0 },
-        /* 51 << 104 */
-        { { 0x70a550d7e6fc3a32l,0x8e5875841951fe57l,0x5e6d43eaaab9788bl,
-            0x1e406fed80599794l },
-          { 0xd8164ace9ed2557cl,0xf9648f30ff593e10l,0x53af2fd80c2ff879l,
-            0x6705993cc9409bf4l },
-          0 },
-        /* 52 << 104 */
-        { { 0x04b005b6c6458293l,0x36bb5276e8d10af7l,0xacf2dc138ee617b8l,
-            0x470d2d35b004b3d4l },
-          { 0x06790832feeb1b77l,0x2bb75c3985657f9cl,0xd70bd4edc0f60004l,
-            0xfe797ecc219b018bl },
-          0 },
-        /* 53 << 104 */
-        { { 0xeca02ebf0ef19ceel,0xac691fbe2de090a4l,0x1f3866641b374547l,
-            0xbd8018c6a12ee85fl },
-          { 0x3e851318ee63e0f1l,0x45b0c37a161987d3l,0x67fe36056eb567c4l,
-            0x07c291b563200c5bl },
-          0 },
-        /* 55 << 104 */
-        { { 0xc85535ac1a956a8al,0x7bf4d70bc0ade321l,0xaf2efc48237bc56fl,
-            0xf9bfe13e31ba97e7l },
-          { 0x2ca5fac4cf7c6c65l,0xc23b14ff03ec3e35l,0xc5109923217bcfd2l,
-            0xf02f96a1c58f32f3l },
-          0 },
-        /* 57 << 104 */
-        { { 0x3b1f715b0d0aeff4l,0xbe406d62f0d44536l,0xe413843d567bcb38l,
-            0x75b7fb43791e705al },
-          { 0x5b831d4b224f85e5l,0x3fea6659d9a35eael,0xd6f8bd097c85480bl,
-            0x2a9561a34a959267l },
-          0 },
-        /* 59 << 104 */
-        { { 0x4a96a3535a303c10l,0x9aa3ad71c37c8d7el,0x4e2d077fde52014fl,
-            0x4d8bec5df8e3964dl },
-          { 0xda88ab94e865e142l,0x52df506d10a88091l,0x9aebff0092fc38a2l,
-            0xdfc034395608b0a2l },
-          0 },
-        /* 60 << 104 */
-        { { 0xee23fa819966e7eel,0x64ec4aa805b7920dl,0x2d44462d2d90aad4l,
-            0xf44dd195df277ad5l },
-          { 0x8d6471f1bb46b6a1l,0x1e65d313fd885090l,0x33a800f513a977b4l,
-            0xaca9d7210797e1efl },
-          0 },
-        /* 61 << 104 */
-        { { 0xb1557be2a4ea787el,0x59324973019f667fl,0x262ceced5595367cl,
-            0x8a676897ec598640l },
-          { 0x2df6cebfc7f06f4fl,0xb255723138078f9al,0xad553c46524a0dd1l,
-            0xe20bb20a5a68d62al },
-          0 },
-        /* 63 << 104 */
-        { { 0x6f47e3779589e263l,0x7cb83e3d35106bb8l,0x2642d87bcc632fc2l,
-            0x4d18f34d8b77eb36l },
-          { 0x7de6bf6d19ca4d1cl,0x438e8f02f7e926aal,0xb539021250ac930al,
-            0xe34ddfc15b219a9fl },
-          0 },
-        /* 64 << 104 */
-        { { 0x98857ceb1bf4581cl,0xe635e186aca7b166l,0x278ddd22659722acl,
-            0xa0903c4c1db68007l },
-          { 0x366e458948f21402l,0x31b49c14b96abda2l,0x329c4b09e0403190l,
-            0x97197ca3d29f43fel },
-          0 },
-        /* 65 << 104 */
-        { { 0xfe4de13781479db4l,0x307331f012f08ea5l,0x7f59a64758c04c13l,
-            0x6b41189abdc9b3c9l },
-          { 0xb10f11e5a6f8c5edl,0x757fb7a3f5b0579el,0x456d0a873c90d027l,
-            0x7e8bb6bf32361796l },
-          0 },
-        /* 71 << 104 */
-        { { 0x6aa1dc6c9e689d8dl,0xaa5fa015479cdd09l,0x7eb4dbb582fc000al,
-            0x4a57b689eff4e701l },
-          { 0x7bfe8d2a8e15cd8cl,0xab109b1cc9074e1al,0x5716715fee1619a5l,
-            0xf29a51eccdcb40bcl },
-          0 },
-        /* 77 << 104 */
-        { { 0x14c76234ddf03c6el,0xdfb5d388baeb2eddl,0x4bd85da26d413d2dl,
-            0x5b0dd9be3ae38469l },
-          { 0xe4d8a9d89ab3ae61l,0xb9e37b880ee63951l,0x17f08e9b21a7f30fl,
-            0x173db1e8119af788l },
-          0 },
-        /* 83 << 104 */
-        { { 0x2352ad4a170d43f6l,0x098d74f65a0ae4b0l,0x290f5236c3a46c2al,
-            0xea9266102dd87e7fl },
-          { 0xd7ee90f6848e6911l,0xebe8f4cce0d8886fl,0xa2038320558ff6a0l,
-            0x1f716534f37c38cfl },
-          0 },
-        /* 89 << 104 */
-        { { 0x9754209439a4a159l,0xe6135412fed24278l,0xbba62254d70e2cabl,
-            0x4ac6a8ac85895130l },
-          { 0xc01614fee1a45363l,0x720ad3f8b67294f2l,0x724ea95cb420ea51l,
-            0x1f40ab2d712b856cl },
-          0 },
-        /* 95 << 104 */
-        { { 0x708e1c7975f3d30cl,0x423f1535e2172da3l,0x7a29be342a06a0b1l,
-            0x9de5c9eb32c68ba2l },
-          { 0x70217b0232d48793l,0x3cf3855bac1471cfl,0x6762d03f8321e179l,
-            0x06ee12ea236fa7cfl },
-          0 },
-        /* 101 << 104 */
-        { { 0x1718e7428779109bl,0x6188008d0aca350bl,0xbbe227e00594bc15l,
-            0x4a7b6423ddbdea35l },
-          { 0x06ad632dfa44e1bfl,0xaf9c163d1e97b409l,0x64dafec3c61f2b2fl,
-            0xc6759d905525c0c9l },
-          0 },
-        /* 107 << 104 */
-        { { 0x76d6294787517149l,0x2bda339baa77d325l,0x04b1bec067ad1fd1l,
-            0x49f63fcc0aec7c73l },
-          { 0x005cb459ec1bf494l,0x8fa99c1b1ec6f8bbl,0x70a4e6d78b59dd43l,
-            0xfd70bcb313d6594dl },
-          0 },
-        /* 113 << 104 */
-        { { 0x2987a7cb13966c11l,0x74ad0a26a783f283l,0xf011200ae54d27f0l,
-            0xbd8632963fb38396l },
-          { 0x7ec7fe8c9b86d059l,0xfa94ca76d0cd33a7l,0xf6ad741cdc646993l,
-            0x83054a427ebc34e9l },
-          0 },
-        /* 116 << 104 */
-        { { 0xadef8c5a192ef710l,0x88afbd4b3b7431f9l,0x7e1f740764250c9el,
-            0x6e31318db58bec07l },
-          { 0xfd4fc4b824f89b4el,0x65a5dd8848c36a2al,0x4f1eccfff024baa7l,
-            0x22a21cf2cba94650l },
-          0 },
-        /* 119 << 104 */
-        { { 0x7b45865478f39754l,0xcbb8b96c4564e003l,0xb492d2bf69b35752l,
-            0x4e6287e065ee5ad3l },
-          { 0x07906c14eb1ffe62l,0xf350390c681fcdf8l,0xc351386f6be3eec3l,
-            0x8480d00ee5df919dl },
-          0 },
-        /* 125 << 104 */
-        { { 0x399861ecf8a2d5aal,0xb179adeb046f78cbl,0x056a6cd88792f647l,
-            0xd3dfc91c3d411820l },
-          { 0x4ccf92d179693be1l,0x12ecd9a3f65cb250l,0x58e5d2102538b9e7l,
-            0x4e655882ff977ccal },
-          0 },
-    },
-    {
-        /* 0 << 112 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 112 */
-        { { 0x8ce9b6bfc360e25al,0xe6425195075a1a78l,0x9dc756a8481732f4l,
-            0x83c0440f5432b57al },
-          { 0xc670b3f1d720281fl,0x2205910ed135e051l,0xded14b0edb052be7l,
-            0x697b3d27c568ea39l },
-          0 },
-        /* 3 << 112 */
-        { { 0x0b89de9314092ebbl,0xf17256bd428e240cl,0xcf89a7f393d2f064l,
-            0x4f57841ee1ed3b14l },
-          { 0x4ee14405e708d855l,0x856aae7203f1c3d0l,0xc8e5424fbdd7eed5l,
-            0x3333e4ef73ab4270l },
-          0 },
-        /* 4 << 112 */
-        { { 0x3bc77adedda492f8l,0xc11a3aea78297205l,0x5e89a3e734931b4cl,
-            0x17512e2e9f5694bbl },
-          { 0x5dc349f3177bf8b6l,0x232ea4ba08c7ff3el,0x9c4f9d16f511145dl,
-            0xccf109a333b379c3l },
-          0 },
-        /* 5 << 112 */
-        { { 0xe75e7a88a1f25897l,0x7ac6961fa1b5d4d8l,0xe3e1077308f3ed5cl,
-            0x208a54ec0a892dfbl },
-          { 0xbe826e1978660710l,0x0cf70a97237df2c8l,0x418a7340ed704da5l,
-            0xa3eeb9a908ca33fdl },
-          0 },
-        /* 7 << 112 */
-        { { 0xb4323d588434a920l,0xc0af8e93622103c5l,0x667518ef938dbf9al,
-            0xa184307383a9cdf2l },
-          { 0x350a94aa5447ab80l,0xe5e5a325c75a3d61l,0x74ba507f68411a9el,
-            0x10581fc1594f70c5l },
-          0 },
-        /* 9 << 112 */
-        { { 0x5aaa98a7cb0c9c8cl,0x75105f3081c4375cl,0xceee50575ef1c90fl,
-            0xb31e065fc23a17bfl },
-          { 0x5364d275d4b6d45al,0xd363f3ad62ec8996l,0xb5d212394391c65bl,
-            0x84564765ebb41b47l },
-          0 },
-        /* 10 << 112 */
-        { { 0x20d18ecc37107c78l,0xacff3b6b570c2a66l,0x22f975d99bd0d845l,
-            0xef0a0c46ba178fa0l },
-          { 0x1a41965176b6028el,0xc49ec674248612d4l,0x5b6ac4f27338af55l,
-            0x06145e627bee5a36l },
-          0 },
-        /* 11 << 112 */
-        { { 0x33e95d07e75746b5l,0x1c1e1f6dc40c78bel,0x967833ef222ff8e2l,
-            0x4bedcf6ab49180adl },
-          { 0x6b37e9c13d7a4c8al,0x2748887c6ddfe760l,0xf7055123aa3a5bbcl,
-            0x954ff2257bbb8e74l },
-          0 },
-        /* 13 << 112 */
-        { { 0x4e23ca446d3fea55l,0xb4ae9c86f4810568l,0x47bfb91b2a62f27dl,
-            0x60deb4c9d9bac28cl },
-          { 0xa892d8947de6c34cl,0x4ee682594494587dl,0x914ee14e1a3f8a5bl,
-            0xbb113eaa28700385l },
-          0 },
-        /* 15 << 112 */
-        { { 0xef9dc899a7b56eafl,0x00c0e52c34ef7316l,0x5b1e4e24fe818a86l,
-            0x9d31e20dc538be47l },
-          { 0x22eb932d3ed68974l,0xe44bbc087c4e87c4l,0x4121086e0dde9aefl,
-            0x8e6b9cff134f4345l },
-          0 },
-        /* 16 << 112 */
-        { { 0x96892c1f711b0eb9l,0xb905f2c8780ab954l,0xace26309a20792dbl,
-            0xec8ac9b30684e126l },
-          { 0x486ad8b6b40a2447l,0x60121fc19fe3fb24l,0x5626fccf1a8e3b3fl,
-            0x4e5686226ad1f394l },
-          0 },
-        /* 17 << 112 */
-        { { 0xda7aae0d196aa5a1l,0xe0df8c771041b5fbl,0x451465d926b318b7l,
-            0xc29b6e557ab136e9l },
-          { 0x2c2ab48b71148463l,0xb5738de364454a76l,0x54ccf9a05a03abe4l,
-            0x377c02960427d58el },
-          0 },
-        /* 19 << 112 */
-        { { 0x90e4f7c92d7d1413l,0x67e2d6b59834f597l,0x4fd4f4f9a808c3e8l,
-            0xaf8237e0d5281ec1l },
-          { 0x25ab5fdc84687ceel,0xc5ded6b1a5b26c09l,0x8e4a5aecc8ea7650l,
-            0x23b73e5c14cc417fl },
-          0 },
-        /* 21 << 112 */
-        { { 0xb4293fdcf50225f9l,0xc52e175cb0e12b03l,0xf649c3bad0a8bf64l,
-            0x745a8fefeb8ae3c6l },
-          { 0x30d7e5a358321bc3l,0xb1732be70bc4df48l,0x1f217993e9ea5058l,
-            0xf7a71cde3e4fd745l },
-          0 },
-        /* 23 << 112 */
-        { { 0xa188b2502d0f39aal,0x622118bb15a85947l,0x2ebf520ffde0f4fal,
-            0xa40e9f294860e539l },
-          { 0x7b6a51eb22b57f0fl,0x849a33b97e80644al,0x50e5d16f1cf095fel,
-            0xd754b54eec55f002l },
-          0 },
-        /* 25 << 112 */
-        { { 0xcd821dfb988baf01l,0xe6331a7ddbb16647l,0x1eb8ad33094cb960l,
-            0x593cca38c91bbca5l },
-          { 0x384aac8d26567456l,0x40fa0309c04b6490l,0x97834cd6dab6c8f6l,
-            0x68a7318d3f91e55fl },
-          0 },
-        /* 27 << 112 */
-        { { 0xc7bfd486605daaa6l,0x46fd72b7bb9a6c9el,0xe4847fb1a124fb89l,
-            0x75959cbda2d8ffbcl },
-          { 0x42579f65c8a588eel,0x368c92e6b80b499dl,0xea4ef6cd999a5df1l,
-            0xaa73bb7f936fe604l },
-          0 },
-        /* 28 << 112 */
-        { { 0xf347a70d6457d188l,0x86eda86b8b7a388bl,0xb7cdff060ccd6013l,
-            0xbeb1b6c7d0053fb2l },
-          { 0x0b02238799240a9fl,0x1bbb384f776189b2l,0x8695e71e9066193al,
-            0x2eb5009706ffac7el },
-          0 },
-        /* 29 << 112 */
-        { { 0x0654a9c04a7d2caal,0x6f3fb3d1a5aaa290l,0x835db041ff476e8fl,
-            0x540b8b0bc42295e4l },
-          { 0xa5c73ac905e214f5l,0x9a74075a56a0b638l,0x2e4b1090ce9e680bl,
-            0x57a5b4796b8d9afal },
-          0 },
-        /* 31 << 112 */
-        { { 0x2a2bfa7f650006f0l,0xdfd7dad350c0fbb2l,0x92452495ccf9ad96l,
-            0x183bf494d95635f9l },
-          { 0x02d5df434a7bd989l,0x505385cca5431095l,0xdd98e67dfd43f53el,
-            0xd61e1a6c500c34a9l },
-          0 },
-        /* 33 << 112 */
-        { { 0x41d85ea1ef74c45bl,0x2cfbfa66ae328506l,0x98b078f53ada7da9l,
-            0xd985fe37ec752fbbl },
-          { 0xeece68fe5a0148b4l,0x6f9a55c72d78136dl,0x232dccc4d2b729cel,
-            0xa27e0dfd90aafbc4l },
-          0 },
-        /* 34 << 112 */
-        { { 0x9647445212b4603el,0xa876c5516b706d14l,0xdf145fcf69a9d412l,
-            0xe2ab75b72d479c34l },
-          { 0x12df9a761a23ff97l,0xc61389925d359d10l,0x6e51c7aefa835f22l,
-            0x69a79cb1c0fcc4d9l },
-          0 },
-        /* 35 << 112 */
-        { { 0xf57f350d594cc7e1l,0x3079ca633350ab79l,0x226fb6149aff594al,
-            0x35afec026d59a62bl },
-          { 0x9bee46f406ed2c6el,0x58da17357d939a57l,0x44c504028fd1797el,
-            0xd8853e7c5ccea6cal },
-          0 },
-        /* 36 << 112 */
-        { { 0x4065508da35fcd5fl,0x8965df8c495ccaebl,0x0f2da85012e1a962l,
-            0xee471b94c1cf1cc4l },
-          { 0xcef19bc80a08fb75l,0x704958f581de3591l,0x2867f8b23aef4f88l,
-            0x8d749384ea9f9a5fl },
-          0 },
-        /* 37 << 112 */
-        { { 0x1b3855378c9049f4l,0x5be948f37b92d8b6l,0xd96f725db6e2bd6bl,
-            0x37a222bc958c454dl },
-          { 0xe7c61abb8809bf61l,0x46f07fbc1346f18dl,0xfb567a7ae87c0d1cl,
-            0x84a461c87ef3d07al },
-          0 },
-        /* 39 << 112 */
-        { { 0x3ab3d5afbd76e195l,0x478dd1ad6938a810l,0x6ffab3936ee3d5cbl,
-            0xdfb693db22b361e4l },
-          { 0xf969449651dbf1a7l,0xcab4b4ef08a2e762l,0xe8c92f25d39bba9al,
-            0x850e61bcf1464d96l },
-          0 },
-        /* 40 << 112 */
-        { { 0xb7e830e3dc09508bl,0xfaf6d2cf74317655l,0x72606cebdf690355l,
-            0x48bb92b3d0c3ded6l },
-          { 0x65b754845c7cf892l,0xf6cd7ac9d5d5f01fl,0xc2c30a5996401d69l,
-            0x91268650ed921878l },
-          0 },
-        /* 41 << 112 */
-        { { 0x380bf913b78c558fl,0x43c0baebc8afdaa9l,0x377f61d554f169d3l,
-            0xf8da07e3ae5ff20bl },
-          { 0xb676c49da8a90ea8l,0x81c1ff2b83a29b21l,0x383297ac2ad8d276l,
-            0x3001122fba89f982l },
-          0 },
-        /* 43 << 112 */
-        { { 0xbbe1e6a6c93f72d6l,0xd5f75d12cad800eal,0xfa40a09fe7acf117l,
-            0x32c8cdd57581a355l },
-          { 0x742219927023c499l,0xa8afe5d738ec3901l,0x5691afcba90e83f0l,
-            0x41bcaa030b8f8eacl },
-          0 },
-        /* 44 << 112 */
-        { { 0xe38b5ff98d2668d5l,0x0715281a7ad81965l,0x1bc8fc7c03c6ce11l,
-            0xcbbee6e28b650436l },
-          { 0x06b00fe80cdb9808l,0x17d6e066fe3ed315l,0x2e9d38c64d0b5018l,
-            0xab8bfd56844dcaefl },
-          0 },
-        /* 45 << 112 */
-        { { 0x42894a59513aed8bl,0xf77f3b6d314bd07al,0xbbdecb8f8e42b582l,
-            0xf10e2fa8d2390fe6l },
-          { 0xefb9502262a2f201l,0x4d59ea5050ee32b0l,0xd87f77286da789a8l,
-            0xcf98a2cff79492c4l },
-          0 },
-        /* 46 << 112 */
-        { { 0xf9577239720943c2l,0xba044cf53990b9d0l,0x5aa8e82395f2884al,
-            0x834de6ed0278a0afl },
-          { 0xc8e1ee9a5f25bd12l,0x9259ceaa6f7ab271l,0x7e6d97a277d00b76l,
-            0x5c0c6eeaa437832al },
-          0 },
-        /* 47 << 112 */
-        { { 0x5232c20f5606b81dl,0xabd7b3750d991ee5l,0x4d2bfe358632d951l,
-            0x78f8514698ed9364l },
-          { 0x951873f0f30c3282l,0x0da8ac80a789230bl,0x3ac7789c5398967fl,
-            0xa69b8f7fbdda0fb5l },
-          0 },
-        /* 48 << 112 */
-        { { 0xe5db77176add8545l,0x1b71cb6672c49b66l,0xd856073968421d77l,
-            0x03840fe883e3afeal },
-          { 0xb391dad51ec69977l,0xae243fb9307f6726l,0xc88ac87be8ca160cl,
-            0x5174cced4ce355f4l },
-          0 },
-        /* 49 << 112 */
-        { { 0x98a35966e58ba37dl,0xfdcc8da27817335dl,0x5b75283083fbc7bfl,
-            0x68e419d4d9c96984l },
-          { 0x409a39f402a40380l,0x88940faf1fe977bcl,0xc640a94b8f8edea6l,
-            0x1e22cd17ed11547dl },
-          0 },
-        /* 51 << 112 */
-        { { 0x17ba93b1a20ef103l,0xad8591306ba6577bl,0x65c91cf66fa214a0l,
-            0xd7d49c6c27990da5l },
-          { 0xecd9ec8d20bb569dl,0xbd4b2502eeffbc33l,0x2056ca5a6bed0467l,
-            0x7916a1f75b63728cl },
-          0 },
-        /* 52 << 112 */
-        { { 0xd4f9497d53a4f566l,0x8973466497b56810l,0xf8e1da740494a621l,
-            0x82546a938d011c68l },
-          { 0x1f3acb19c61ac162l,0x52f8fa9cabad0d3el,0x15356523b4b7ea43l,
-            0x5a16ad61ae608125l },
-          0 },
-        /* 53 << 112 */
-        { { 0xb0bcb87f4faed184l,0x5f236b1d5029f45fl,0xd42c76070bc6b1fcl,
-            0xc644324e68aefce3l },
-          { 0x8e191d595c5d8446l,0xc020807713ae1979l,0xadcaee553ba59cc7l,
-            0x20ed6d6ba2cb81bal },
-          0 },
-        /* 55 << 112 */
-        { { 0x7392b41a530ccbbdl,0x87c82146ea823525l,0xa52f984c05d98d0cl,
-            0x2ae57d735ef6974cl },
-          { 0x9377f7bf3042a6ddl,0xb1a007c019647a64l,0xfaa9079a0cca9767l,
-            0x3d81a25bf68f72d5l },
-          0 },
-        /* 57 << 112 */
-        { { 0xc110d830b0f2ac95l,0x48d0995aab20e64el,0x0f3e00e17729cd9al,
-            0x2a570c20dd556946l },
-          { 0x912dbcfd4e86214dl,0x2d014ee2cf615498l,0x55e2b1e63530d76el,
-            0xc5135ae4fd0fd6d1l },
-          0 },
-        /* 59 << 112 */
-        { { 0x1854daa5061f1658l,0xc0016df1df0cd2b3l,0xc2a3f23e833d50del,
-            0x73b681d2bbbd3017l },
-          { 0x2f046dc43ac343c0l,0x9c847e7d85716421l,0xe1e13c910917eed4l,
-            0x3fc9eebd63a1b9c6l },
-          0 },
-        /* 60 << 112 */
-        { { 0x0f816a727fe02299l,0x6335ccc2294f3319l,0x3820179f4745c5bel,
-            0xe647b782922f066el },
-          { 0xc22e49de02cafb8al,0x299bc2fffcc2ecccl,0x9a8feea26e0e8282l,
-            0xa627278bfe893205l },
-          0 },
-        /* 61 << 112 */
-        { { 0xa7e197337933e47bl,0xf4ff6b132e766402l,0xa4d8be0a98440d9fl,
-            0x658f5c2f38938808l },
-          { 0x90b75677c95b3b3el,0xfa0442693137b6ffl,0x077b039b43c47c29l,
-            0xcca95dd38a6445b2l },
-          0 },
-        /* 63 << 112 */
-        { { 0x583f3703f9374ab6l,0x864f91956e564145l,0x33bc3f4822526d50l,
-            0x9f323c801262a496l },
-          { 0xaa97a7ae3f046a9al,0x70da183edf8a039al,0x5b68f71c52aa0ba6l,
-            0x9be0fe5121459c2dl },
-          0 },
-        /* 64 << 112 */
-        { { 0xc1e17eb6cbc613e5l,0x33131d55497ea61cl,0x2f69d39eaf7eded5l,
-            0x73c2f434de6af11bl },
-          { 0x4ca52493a4a375fal,0x5f06787cb833c5c2l,0x814e091f3e6e71cfl,
-            0x76451f578b746666l },
-          0 },
-        /* 65 << 112 */
-        { { 0xa700767eabd0cc76l,0xa14ae98015889273l,0x5acf2cc466ea6380l,
-            0xb942cc40d08d18b9l },
-          { 0x9b5daa763ae45782l,0x61a25e0fb72f0ce0l,0xf94c0e80435fefe3l,
-            0x73d552cf1620e1c9l },
-          0 },
-        /* 71 << 112 */
-        { { 0x57130582727185c1l,0x8f2b8ebc163897ecl,0x4a059cc7a04e4a6bl,
-            0x4b1de9fe0908a366l },
-          { 0xa4f7738688d0fef0l,0x55e3bb1d9ebfc138l,0x9022bbef005ae362l,
-            0xf5669edc8741d349l },
-          0 },
-        /* 77 << 112 */
-        { { 0xf192c0f7ede937a4l,0xd2e91d62810c1b1el,0xf2b40b64dcc39c69l,
-            0xe125fbd028f03b0el },
-          { 0x52966dd78da708f9l,0x92d400a3cc0e7f32l,0x4e35aae36b0842b8l,
-            0x0b4fe66ded3ad3cfl },
-          0 },
-        /* 83 << 112 */
-        { { 0x14b81d951f1ff6b5l,0x1d82f132ed9b03b8l,0x52f6f029b4fa4047l,
-            0xea653682601e5913l },
-          { 0x4e900375edeee046l,0xd22ed267f9428714l,0xb004fb3b1753e873l,
-            0xfef061ba245b2c09l },
-          0 },
-        /* 89 << 112 */
-        { { 0x5e2376eaf9deba2bl,0x1ed1e9e5269a18cfl,0x8dffd66dcb1cada8l,
-            0xb13239f068369c77l },
-          { 0x2fede3a67f25426fl,0xc885cf0c6f90a2a6l,0xd950162d4eeac543l,
-            0x53011aa09abc201bl },
-          0 },
-        /* 95 << 112 */
-        { { 0x7a63925d432b798al,0x92e762cfc9bd6da9l,0xf22fb9706a190382l,
-            0x19919b847b18a9b3l },
-          { 0x16793b803adfde86l,0xf9ce15ace8b1d44cl,0x4bf74144c0a140b8l,
-            0x680468616f853f6cl },
-          0 },
-        /* 101 << 112 */
-        { { 0xd4e0d8460db84ba2l,0x9a162a3a360b68bbl,0x7297f3939233146cl,
-            0xbc93c2f4ec77412dl },
-          { 0x13ddf0a7e07e1065l,0x000a8d45fb5e5131l,0xb4373078cf61d467l,
-            0xa4a1fd67bf3bb6f9l },
-          0 },
-        /* 107 << 112 */
-        { { 0x6f2473f9d7585098l,0x45a29448d4f23c1al,0x47fe40f1c22bdc25l,
-            0x4e46ed1f31347673l },
-          { 0x5e43a8624148898cl,0x4a02ededa993954el,0x83d830b52f8a1847l,
-            0x007e3156a7f6a378l },
-          0 },
-        /* 113 << 112 */
-        { { 0x01a39fe7e847ca18l,0xaf2722418fed2772l,0x3104ef891fbb1748l,
-            0x5b55331b2b9dd5ffl },
-          { 0xe7806e31cec6a787l,0x9f49ed881e9c0af2l,0xf5a66373a3905b36l,
-            0x77b5bca9efab75f3l },
-          0 },
-        /* 116 << 112 */
-        { { 0xd4d75f4bf0831932l,0x5e770ac477fe8cc9l,0x52b5e748862e72a2l,
-            0xe9a45482501d35fel },
-          { 0x8a93e7424a9ab187l,0x5a72506de88ca017l,0xe680dcb201eb2defl,
-            0xdc5aa4e6ba68209dl },
-          0 },
-        /* 119 << 112 */
-        { { 0x2defa3dc3d01a344l,0x11fd939b162e459al,0x928453b97313d720l,
-            0x08696dc053184a65l },
-          { 0xd9f8a69c721f7415l,0x304eb0e079539019l,0xc9b0ca6dbb0c6313l,
-            0xa10133eba93dc74el },
-          0 },
-        /* 125 << 112 */
-        { { 0xee0b164004393f1el,0x511547dfe1301979l,0xc00dfc3516d26d87l,
-            0x06227c8aab847494l },
-          { 0x178ca86748b2fdc7l,0xb51296f01a8ba1dcl,0xf252787731e1dd14l,
-            0x7ecb5456c0ba2a1fl },
-          0 },
-    },
-    {
-        /* 0 << 120 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 120 */
-        { { 0x3e0e5c9dd111f8ecl,0xbcc33f8db7c4e760l,0x702f9a91bd392a51l,
-            0x7da4a795c132e92dl },
-          { 0x1a0b0ae30bb1151bl,0x54febac802e32251l,0xea3a5082694e9e78l,
-            0xe58ffec1e4fe40b8l },
-          0 },
-        /* 3 << 120 */
-        { { 0x7b23c513516e19e4l,0x56e2e847c5c4d593l,0x9f727d735ce71ef6l,
-            0x5b6304a6f79a44c5l },
-          { 0x6638a7363ab7e433l,0x1adea470fe742f83l,0xe054b8545b7fc19fl,
-            0xf935381aba1d0698l },
-          0 },
-        /* 4 << 120 */
-        { { 0xb5504f9d918e4936l,0x65035ef6b2513982l,0x0553a0c26f4d9cb9l,
-            0x6cb10d56bea85509l },
-          { 0x48d957b7a242da11l,0x16a4d3dd672b7268l,0x3d7e637c8502a96bl,
-            0x27c7032b730d463bl },
-          0 },
-        /* 5 << 120 */
-        { { 0x55366b7d5846426fl,0xe7d09e89247d441dl,0x510b404d736fbf48l,
-            0x7fa003d0e784bd7dl },
-          { 0x25f7614f17fd9596l,0x49e0e0a135cb98dbl,0x2c65957b2e83a76al,
-            0x5d40da8dcddbe0f8l },
-          0 },
-        /* 7 << 120 */
-        { { 0x9fb3bba354530bb2l,0xbde3ef77cb0869eal,0x89bc90460b431163l,
-            0x4d03d7d2e4819a35l },
-          { 0x33ae4f9e43b6a782l,0x216db3079c88a686l,0x91dd88e000ffedd9l,
-            0xb280da9f12bd4840l },
-          0 },
-        /* 9 << 120 */
-        { { 0xa37f3573f37f5937l,0xeb0f6c7dd1e4fca5l,0x2965a554ac8ab0fcl,
-            0x17fbf56c274676acl },
-          { 0x2e2f6bd9acf7d720l,0x41fc8f8810224766l,0x517a14b385d53befl,
-            0xdae327a57d76a7d1l },
-          0 },
-        /* 10 << 120 */
-        { { 0x515d5c891f5f82dcl,0x9a7f67d76361079el,0xa8da81e311a35330l,
-            0xe44990c44b18be1bl },
-          { 0xc7d5ed95af103e59l,0xece8aba78dac9261l,0xbe82b0999394b8d3l,
-            0x6830f09a16adfe83l },
-          0 },
-        /* 11 << 120 */
-        { { 0x43c41ac194d7d9b1l,0x5bafdd82c82e7f17l,0xdf0614c15fda0fcal,
-            0x74b043a7a8ae37adl },
-          { 0x3ba6afa19e71734cl,0x15d5437e9c450f2el,0x4a5883fe67e242b1l,
-            0x5143bdc22c1953c2l },
-          0 },
-        /* 13 << 120 */
-        { { 0xc676d7f2b1f3390bl,0x9f7a1b8ca5b61272l,0x4ebebfc9c2e127a9l,
-            0x4602500c5dd997bfl },
-          { 0x7f09771c4711230fl,0x058eb37c020f09c1l,0xab693d4bfee5e38bl,
-            0x9289eb1f4653cbc0l },
-          0 },
-        /* 15 << 120 */
-        { { 0x54da9dc7ab952578l,0xb5423df226e84d0bl,0xa8b64eeb9b872042l,
-            0xac2057825990f6dfl },
-          { 0x4ff696eb21f4c77al,0x1a79c3e4aab273afl,0x29bc922e9436b3f1l,
-            0xff807ef8d6d9a27al },
-          0 },
-        /* 16 << 120 */
-        { { 0xc7f3a8f833f6746cl,0x21e46f65fea990cal,0x915fd5c5caddb0a9l,
-            0xbd41f01678614555l },
-          { 0x346f4434426ffb58l,0x8055943614dbc204l,0xf3dd20fe5a969b7fl,
-            0x9d59e956e899a39al },
-          0 },
-        /* 17 << 120 */
-        { { 0xe4ca688fd06f56c0l,0xa48af70ddf027972l,0x691f0f045e9a609dl,
-            0xa9dd82cdee61270el },
-          { 0x8903ca63a0ef18d3l,0x9fb7ee353d6ca3bdl,0xa7b4a09cabf47d03l,
-            0x4cdada011c67de8el },
-          0 },
-        /* 19 << 120 */
-        { { 0xac127dc1e038a675l,0x729deff38c5c6320l,0xb7df8fd4a90d2c53l,
-            0x9b74b0ec681e7cd3l },
-          { 0x5cb5a623dab407e5l,0xcdbd361576b340c6l,0xa184415a7d28392cl,
-            0xc184c1d8e96f7830l },
-          0 },
-        /* 21 << 120 */
-        { { 0x86a9303b2f7e85c3l,0x5fce462171988f9bl,0x5b935bf6c138acb5l,
-            0x30ea7d6725661212l },
-          { 0xef1eb5f4e51ab9a2l,0x0587c98aae067c78l,0xb3ce1b3c77ca9ca6l,
-            0x2a553d4d54b5f057l },
-          0 },
-        /* 23 << 120 */
-        { { 0x2c7156e10b1894a0l,0x92034001d81c68c0l,0xed225d00c8b115b5l,
-            0x237f9c2283b907f2l },
-          { 0x0ea2f32f4470e2c0l,0xb725f7c158be4e95l,0x0f1dcafab1ae5463l,
-            0x59ed51871ba2fc04l },
-          0 },
-        /* 25 << 120 */
-        { { 0xd1b0ccdec9520711l,0x55a9e4ed3c8b84bfl,0x9426bd39a1fef314l,
-            0x4f5f638e6eb93f2bl },
-          { 0xba2a1ed32bf9341bl,0xd63c13214d42d5a9l,0xd2964a89316dc7c5l,
-            0xd1759606ca511851l },
-          0 },
-        /* 27 << 120 */
-        { { 0xedf69feaf8c51187l,0x05bb67ec741e4da7l,0x47df0f3208114345l,
-            0x56facb07bb9792b1l },
-          { 0xf3e007e98f6229e4l,0x62d103f4526fba0fl,0x4f33bef7b0339d79l,
-            0x9841357bb59bfec1l },
-          0 },
-        /* 28 << 120 */
-        { { 0xae1e0b67e28ef5bal,0x2c9a4699cb18e169l,0x0ecd0e331e6bbd20l,
-            0x571b360eaf5e81d2l },
-          { 0xcd9fea58101c1d45l,0x6651788e18880452l,0xa99726351f8dd446l,
-            0x44bed022e37281d0l },
-          0 },
-        /* 29 << 120 */
-        { { 0x830e6eea60dbac1fl,0x23d8c484da06a2f7l,0x896714b050ca535bl,
-            0xdc8d3644ebd97a9bl },
-          { 0x106ef9fab12177b4l,0xf79bf464534d5d9cl,0x2537a349a6ab360bl,
-            0xc7c54253a00c744fl },
-          0 },
-        /* 31 << 120 */
-        { { 0x24d661d168754ab0l,0x801fce1d6f429a76l,0xc068a85fa58ce769l,
-            0xedc35c545d5eca2bl },
-          { 0xea31276fa3f660d1l,0xa0184ebeb8fc7167l,0x0f20f21a1d8db0ael,
-            0xd96d095f56c35e12l },
-          0 },
-        /* 33 << 120 */
-        { { 0x57d2046b59da06ebl,0x3c076d5fa49f6d74l,0x6b4c96e616f82ea0l,
-            0xaf7b0f1f90536c0bl },
-          { 0x7999f86d204a9b2dl,0x7e420264126c9f87l,0x4c967a1f262ac4e5l,
-            0xe8174a09900e79adl },
-          0 },
-        /* 34 << 120 */
-        { { 0xd51687f2cb82516bl,0x8a440cfc040e4670l,0xeafd2bcfe7738d32l,
-            0x7071e9162a1e911al },
-          { 0xbd3abd44cfea57bbl,0x9c3add16085b19e2l,0xb194c01d6baa5aa6l,
-            0x6f3d3faf92f85c64l },
-          0 },
-        /* 35 << 120 */
-        { { 0xe23e0769488a280el,0x8e55a728e63a5904l,0x01690716ab84cccfl,
-            0xfe796130b78b3c98l },
-          { 0x15cc475b9117f211l,0xbdc178761d1b9d56l,0x8df5594a3e37b9b9l,
-            0x97747e341e37e494l },
-          0 },
-        /* 36 << 120 */
-        { { 0xf2a6370ed2f896e1l,0x27100e63802987afl,0xb4db1cff4678ebc7l,
-            0x6e5f28d937b4b263l },
-          { 0xd29030009711ebc4l,0xf14dcb9ff8712484l,0x7a46ec3eea449146l,
-            0x200155e9c1c51179l },
-          0 },
-        /* 37 << 120 */
-        { { 0x8130f007f1968d55l,0x18823e7097ed9803l,0xdc9fec559402762dl,
-            0x9e0bd57e278f5abbl },
-          { 0xaa41b913c9ebf303l,0x1105ec43a76b9353l,0xf8e4ee4cf4e6c6b5l,
-            0x3a630972bd7be696l },
-          0 },
-        /* 39 << 120 */
-        { { 0x5c7da7e16356b3eel,0x951bfe458ccf9b48l,0x6f2c6e91d0555d0cl,
-            0x47d7f7b58efd38eel },
-          { 0x957256c8af6fd630l,0xa690c65bdc01774cl,0xad52b27c7c8dafdal,
-            0x81fbc16af44a145fl },
-          0 },
-        /* 40 << 120 */
-        { { 0x497c3a3481b0493al,0x2b3ab20d71bc8408l,0x0c60226aa03769d1l,
-            0x4ac89c7ad10708b0l },
-          { 0x62398ea5092f7e6al,0x7f408f54de96d526l,0x025bde6f85bf102cl,
-            0xcc2f85120a4aa72el },
-          0 },
-        /* 41 << 120 */
-        { { 0x8a65e0386884a9c3l,0xd2e6ac047bf8c794l,0xc9c5d3d3f7bcdfb9l,
-            0x0000ce42a33f2c12l },
-          { 0xea1c0a9a7dd13b2bl,0xbfd97d7f0c35c3b1l,0x0ba75cf3347fcefel,
-            0xc3c5f28f1333460dl },
-          0 },
-        /* 43 << 120 */
-        { { 0x7810ebf575baa708l,0xe7fa7a0dd7440549l,0x25b813baf0667e4al,
-            0x30a46740d15838a8l },
-          { 0x13207b1ad04b22f7l,0x09e601ffd1419699l,0xb1038fc77f687b27l,
-            0xa4547dc9a127f95bl },
-          0 },
-        /* 44 << 120 */
-        { { 0x83b2e3b3056ecd2cl,0xd17dcdaaf03dfd36l,0xee24a5f81dcef956l,
-            0xb6746cd0b7239f16l },
-          { 0xed6cb311c8458c48l,0xe8c0fc9805d27da4l,0x4610e9a0a1bf0970l,
-            0x1947f01d9906c19el },
-          0 },
-        /* 45 << 120 */
-        { { 0x8b979126217c7cd7l,0x65c57a378050067el,0x6a50c6383f34838cl,
-            0x3de617c29b7bc81fl },
-          { 0x58488d24253a0ac7l,0x3fe53ec75520ba0bl,0x9156dca763f0607el,
-            0xdd08c5705d1fe134l },
-          0 },
-        /* 46 << 120 */
-        { { 0xbfb1d9e1e33ba77fl,0x0985311ccaef6c01l,0xc8b59e9accca8948l,
-            0x1256280945416f25l },
-          { 0xc90edbc257f53218l,0xcaa08c05125d8fb5l,0x33ea3fd49a1aad3bl,
-            0x2aa8bd83d005e8bel },
-          0 },
-        /* 47 << 120 */
-        { { 0xcbd2f1a3c2b22963l,0x0f7bd29c0c8ac2b3l,0xddb932432d405bfdl,
-            0xeabd4805328413b5l },
-          { 0xcc79d31748ebb6b9l,0x09604f831f521aael,0xd3487fdf4c7d188cl,
-            0xd219c318d1552ea9l },
-          0 },
-        /* 48 << 120 */
-        { { 0xef4f115c775d6ecel,0x69d2e3bbe8c0e78dl,0xb0264ef1145cfc81l,
-            0x0a41e9fa1b69788bl },
-          { 0x0d9233be909a1f0bl,0x150a84520ae76b30l,0xea3375370632bb69l,
-            0x15f7b3cfaa25584al },
-          0 },
-        /* 49 << 120 */
-        { { 0xfc4c623e321f7b11l,0xd36c1066f9cbc693l,0x8165235835dc0c0al,
-            0xa3ce2e18c824e97el },
-          { 0x59ea7cbcc6ff405el,0xced5a94a1e56a1e2l,0x88d744c53ab64b39l,
-            0x8963d029073a36e7l },
-          0 },
-        /* 51 << 120 */
-        { { 0x97aa902cb19f3edbl,0x8e605ff9bbf2975bl,0x0536fa8ba6eb299bl,
-            0xfd96da4f7cd03ac0l },
-          { 0x29c5b5b578f9a265l,0x1f025a6d5fd0bc1bl,0x440486ee58e0f8e1l,
-            0x8f191f7d593e49e9l },
-          0 },
-        /* 52 << 120 */
-        { { 0xbddf656baea9c13fl,0x083c5d514c678b37l,0x975431b630878ed4l,
-            0x6de13d4608d9cf1cl },
-          { 0xfbb639cc02427c45l,0x6190ca0c5a6cd989l,0x35a6aa26c53f11b7l,
-            0x73f9e17dddfd86f6l },
-          0 },
-        /* 53 << 120 */
-        { { 0xd30478a317be7689l,0x6fc3f634e358f7a7l,0x4057ece515688d9fl,
-            0xb5397495d3d91eefl },
-          { 0x62fac49e2f49bde4l,0xeb4a3e1860125c73l,0x15f38be8dabdac55l,
-            0x18bf29f7d334d52al },
-          0 },
-        /* 55 << 120 */
-        { { 0xf684162b68777538l,0x3e2a770bbb3381f4l,0x1b7562c1b374577cl,
-            0x9eec22dc5cf21688l },
-          { 0xc35014b1d472be2cl,0xafe2317035f086fbl,0xb9c9c4c9a1491ce1l,
-            0x2df1e669b56792ddl },
-          0 },
-        /* 57 << 120 */
-        { { 0xcf7d36fe1830f624l,0x176c3c12ed0474bdl,0x25b802c8f82b493dl,
-            0x683c2a744c78147el },
-          { 0x0db99444f8f3e446l,0x437bcac6800a56c7l,0xb4e592264d08b25fl,
-            0xcaf1b4142e691ca7l },
-          0 },
-        /* 59 << 120 */
-        { { 0x378bd47b9d231cafl,0xde3aa2f01f4db832l,0xf609d16ab29bd7d5l,
-            0x13feab54bdfb54dfl },
-          { 0x274abbbc22fc1a12l,0x267febb47d30ef1bl,0xeffa996d80717cd8l,
-            0x065a86d1118d0812l },
-          0 },
-        /* 60 << 120 */
-        { { 0xc681a8656a3cb3afl,0x528f25a981751414l,0x6669f07cc7eac946l,
-            0x9fb3a53f3cc6cc6bl },
-          { 0x2919d92a11ae224al,0xa59141110b170a19l,0xdc16c611e2042f16l,
-            0x58ace12decd4180bl },
-          0 },
-        /* 61 << 120 */
-        { { 0x689bb1ec107bb59fl,0x8129702adad2b385l,0x10bd3baeb1630603l,
-            0xaadec5d15f23e7cfl },
-          { 0x572f234f4586f7fbl,0x13abdec95ec11b32l,0xa462a7ec6191c26al,
-            0x4a7d92a06685c8d3l },
-          0 },
-        /* 63 << 120 */
-        { { 0xdd4e2b63b16628eal,0xdf0c8fc8eefa5e86l,0xb0ec710205662720l,
-            0x3f4c6956fe81e9dal },
-          { 0x5732ad8f52e356f7l,0x045a103968a658f0l,0x9c40b0b6506ba33al,
-            0x0a426010cb54258dl },
-          0 },
-        /* 64 << 120 */
-        { { 0x09891641d4c5105fl,0x1ae80f8e6d7fbd65l,0x9d67225fbee6bdb0l,
-            0x3b433b597fc4d860l },
-          { 0x44e66db693e85638l,0xf7b59252e3e9862fl,0xdb785157665c32ecl,
-            0x702fefd7ae362f50l },
-          0 },
-        /* 65 << 120 */
-        { { 0x3902ab14c3254641l,0xa63cfd9fd8c001c8l,0x597d155c52d0af3cl,
-            0xc5a2cbc4a0dbe688l },
-          { 0xac8a841b249195aal,0xc98f01aaed14426fl,0xeb4a8ce8353905f1l,
-            0x4d6668171ecee1b7l },
-          0 },
-        /* 71 << 120 */
-        { { 0xbd66e7d9a94da8cdl,0x7bc04735801ef314l,0x90f3eba1c5cc2904l,
-            0x3c7dfed6f71bb36dl },
-          { 0x89a50c8da75e3086l,0x88b8b4746f8e3418l,0x26fe17f4a44a5dbdl,
-            0x98bf74c16a1e24fel },
-          0 },
-        /* 77 << 120 */
-        { { 0xca7b470679e0db85l,0x7f46c7716fc897fdl,0x9537e7918edfc0f3l,
-            0xa46d4b4405e91ddfl },
-          { 0x97d21061ee5575e7l,0x1f4f32da59650429l,0x2d1d6af878995129l,
-            0x41d6fc228a0e4260l },
-          0 },
-        /* 83 << 120 */
-        { { 0xb30a1a89107d2282l,0x5433d7673a5e1323l,0xb9eeab822abdfeafl,
-            0x9579cb46df3e0dbfl },
-          { 0x6fc3ff2c7e088e79l,0x94b32360d7314326l,0xd2e82b59e5ad82e4l,
-            0x7372dc4a55bc24e3l },
-          0 },
-        /* 89 << 120 */
-        { { 0x355697215f3c03cbl,0x4150adf2a146edcdl,0x16ec1a421a252e1cl,
-            0xdf4d0f94424984eal },
-          { 0x15142b5f5fabe961l,0xe6a73c29567ec13al,0xe6d370795d12070al,
-            0x437743d0206fd7c6l },
-          0 },
-        /* 95 << 120 */
-        { { 0x483b7a95d66bc594l,0xf6a7064e8a6113bbl,0x373ce20f4ed34f72l,
-            0x6aa876ab24f429b2l },
-          { 0x378d5c25412c3102l,0xe4219a97b493199cl,0x01c7cafaa0b37332l,
-            0x9305cc85f7633f7dl },
-          0 },
-        /* 101 << 120 */
-        { { 0x0259b43aaadf2273l,0x869c5bd3cf9dc1c2l,0x4f18a6e4068d6628l,
-            0xd110637fec2d4547l },
-          { 0x1ae88a791e94aaddl,0xe8b4be39de64f5f9l,0x85cbd9b24dc6b2bbl,
-            0xb65091fa1bc352b2l },
-          0 },
-        /* 107 << 120 */
-        { { 0x7c5cea5d20f6a354l,0xe936ff1582f3ed39l,0x54e7a775b779368el,
-            0x8ca8a46e3cb17c9el },
-          { 0x753ca1fa0138974dl,0x9ce311eba72902ffl,0xcb727e56973f72b6l,
-            0xde72538d91685710l },
-          0 },
-        /* 113 << 120 */
-        { { 0xf423569f1bec8f85l,0x23376da5ca844ac4l,0xce7b407a111523f4l,
-            0x736fb92dde7aa46dl },
-          { 0xd9139edcc7662640l,0x520fbf0656a85e24l,0x14e3b5857e5284b5l,
-            0xcbae4e8321d56ef3l },
-          0 },
-        /* 116 << 120 */
-        { { 0x69830a05564470a1l,0x1a1e26cf5b702e8el,0xe5fdf7d9d8fae645l,
-            0xe4774f74a9950c66l },
-          { 0x18bdda7cd1466825l,0xe6ab4ce6d115218al,0xfcb8c50064528629l,
-            0xd705f429e70deed9l },
-          0 },
-        /* 119 << 120 */
-        { { 0x3f992d7ba99df096l,0x08993b4125e78725l,0x79eaad13117c4cafl,
-            0x7230594c9fa87285l },
-          { 0xac23d7edf2673e27l,0xc9d76fb53b9eb111l,0x7a0a036a9e9db78al,
-            0x7c6ec39df9565cffl },
-          0 },
-        /* 125 << 120 */
-        { { 0x956ad1441fd4f7a1l,0x6c511ffecb7546cal,0x11becdaef5ae6ddbl,
-            0x67587741946168b2l },
-          { 0x99cd45edf54379a7l,0x687f8462e2748decl,0x2b2be1e1837bd066l,
-            0x3862659c0c45a5a9l },
-          0 },
-    },
-    {
-        /* 0 << 128 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 128 */
-        { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l,
-            0x61d587d421d324f6l },
-          { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el,
-            0xfa11fe124621efbel },
-          0 },
-        /* 3 << 128 */
-        { { 0xc0f734a3b2335834l,0x9526205a90ef6860l,0xcb8be71704e2bb0dl,
-            0x2418871e02f383fal },
-          { 0xd71776814082c157l,0xcc914ad029c20073l,0xf186c1ebe587e728l,
-            0x6fdb3c2261bcd5fdl },
-          0 },
-        /* 4 << 128 */
-        { { 0xb4480f0441c23fa3l,0xb4712eb0c1989a2el,0x3ccbba0f93a29ca7l,
-            0x6e205c14d619428cl },
-          { 0x90db7957b3641686l,0x0432691d45ac8b4el,0x07a759acf64e0350l,
-            0x0514d89c9c972517l },
-          0 },
-        /* 5 << 128 */
-        { { 0xcc7c4c1c2cf9d7c1l,0x1320886aee95e5abl,0xbb7b9056beae170cl,
-            0xc8a5b250dbc0d662l },
-          { 0x4ed81432c11d2303l,0x7da669121f03769fl,0x3ac7a5fd84539828l,
-            0x14dada943bccdd02l },
-          0 },
-        /* 7 << 128 */
-        { { 0x51b90651cbae2f70l,0xefc4bc0593aaa8ebl,0x8ecd8689dd1df499l,
-            0x1aee99a822f367a5l },
-          { 0x95d485b9ae8274c5l,0x6c14d4457d30b39cl,0xbafea90bbcc1ef81l,
-            0x7c5f317aa459a2edl },
-          0 },
-        /* 9 << 128 */
-        { { 0x410dc6a90deeaf52l,0xb003fb024c641c15l,0x1384978c5bc504c4l,
-            0x37640487864a6a77l },
-          { 0x05991bc6222a77dal,0x62260a575e47eb11l,0xc7af6613f21b432cl,
-            0x22f3acc9ab4953e9l },
-          0 },
-        /* 10 << 128 */
-        { { 0x27c8919240be34e8l,0xc7162b3791907f35l,0x90188ec1a956702bl,
-            0xca132f7ddf93769cl },
-          { 0x3ece44f90e2025b4l,0x67aaec690c62f14cl,0xad74141822e3cc11l,
-            0xcf9b75c37ff9a50el },
-          0 },
-        /* 11 << 128 */
-        { { 0x0d0942770c24efc8l,0x0349fd04bef737a4l,0x6d1c9dd2514cdd28l,
-            0x29c135ff30da9521l },
-          { 0xea6e4508f78b0b6fl,0x176f5dd2678c143cl,0x081484184be21e65l,
-            0x27f7525ce7df38c4l },
-          0 },
-        /* 13 << 128 */
-        { { 0x9faaccf5e4652f1dl,0xbd6fdd2ad56157b2l,0xa4f4fb1f6261ec50l,
-            0x244e55ad476bcd52l },
-          { 0x881c9305047d320bl,0x1ca983d56181263fl,0x354e9a44278fb8eel,
-            0xad2dbc0f396e4964l },
-          0 },
-        /* 15 << 128 */
-        { { 0xfce0176788a2ffe4l,0xdc506a3528e169a5l,0x0ea108617af9c93al,
-            0x1ed2436103fa0e08l },
-          { 0x96eaaa92a3d694e7l,0xc0f43b4def50bc74l,0xce6aa58c64114db4l,
-            0x8218e8ea7c000fd4l },
-          0 },
-        /* 16 << 128 */
-        { { 0x6a7091c2e48fb889l,0x26882c137b8a9d06l,0xa24986631b82a0e2l,
-            0x844ed7363518152dl },
-          { 0x282f476fd86e27c7l,0xa04edaca04afefdcl,0x8b256ebc6119e34dl,
-            0x56a413e90787d78bl },
-          0 },
-        /* 17 << 128 */
-        { { 0xd1ffd160deb58b9bl,0x78492428c007273cl,0x47c908048ef06073l,
-            0x746cd0dfe48c659el },
-          { 0xbd7e8e109d47055bl,0xe070967e39711c04l,0x3d8869c99c9444f6l,
-            0x6c67ccc834ac85fcl },
-          0 },
-        /* 19 << 128 */
-        { { 0x8a42d8b087b05be1l,0xef00df8d3e4e1456l,0x148cc8e8fbfc8cd2l,
-            0x0288ae4c4878804fl },
-          { 0x44e669a73b4f6872l,0xa4a8dbd4aab53c5bl,0x843fa963c9660052l,
-            0x128e2d2571c05dd2l },
-          0 },
-        /* 21 << 128 */
-        { { 0x3ea86174a9f1b59bl,0xc747ea076a9a8845l,0x733710b5ab242123l,
-            0x6381b546d386a60cl },
-          { 0xba0e286366a44904l,0x770f618de9db556cl,0x39e567f828fb198dl,
-            0xb5f1bef040147ee8l },
-          0 },
-        /* 23 << 128 */
-        { { 0x1adee1d516391617l,0x962d9184a3315fd9l,0x91c229750c805d59l,
-            0x4575eaf2cd9a1877l },
-          { 0x83fef163451831b9l,0x829d6bdd6f09e30fl,0x9379272dcc6b4e6al,
-            0xd7a049bd95fbee4al },
-          0 },
-        /* 25 << 128 */
-        { { 0x695f70da44ae09c6l,0x79793892bb99de1dl,0xde269352f696b429l,
-            0xe37ea97f8104c825l },
-          { 0x3166cac6b0e72e63l,0xa82e633ca03ba670l,0x1106e3843e505667l,
-            0xc2994f3dffb788b6l },
-          0 },
-        /* 27 << 128 */
-        { { 0xd36a5ab37c53073bl,0xc44a9940ebdc7e35l,0x7dd86c8bf3ded136l,
-            0x9fe9879fd5a0eb14l },
-          { 0xa210726c9b99bf9cl,0x3faf4456861036afl,0x1661f1c9615d091al,
-            0x2c63f630911551bcl },
-          0 },
-        /* 28 << 128 */
-        { { 0x1554d46da670ff1dl,0x24833d88cb97a1ccl,0x8fa6ab3cded97493l,
-            0x215e037189926498l },
-          { 0x549bd592e56d74ffl,0x58a8caf543b5e1ecl,0x3c6087a323e93cb9l,
-            0x8b0549875648b83cl },
-          0 },
-        /* 29 << 128 */
-        { { 0x232974230554f94fl,0x4f445a380f3a7618l,0xb9fb40bee4abefd6l,
-            0xfbf3eaf9c15eb07cl },
-          { 0xed469c23aca0c8b3l,0xc5209f68846e3f8fl,0x33d51d13d75da468l,
-            0x9406e10a3d5c6e29l },
-          0 },
-        /* 31 << 128 */
-        { { 0xb9a44b1f5c6cad21l,0xaa9947751ee60a83l,0xc89af3858c390401l,
-            0xef1e450b8dd51056l },
-          { 0x5f5f069879ac84d1l,0x68d82982ef57b1afl,0x31f1d90f50849555l,
-            0xff9577e57d9fc8f6l },
-          0 },
-        /* 33 << 128 */
-        { { 0xaeebc5c0b430d6a1l,0x39b87a13dc3a9c04l,0xf0c445252db4a631l,
-            0xe32d95482c66fcf6l },
-          { 0x16f11bafb17849c4l,0xdd1c76615eca71f7l,0x4389ad2e32e6c944l,
-            0x727c11a5889a06bbl },
-          0 },
-        /* 34 << 128 */
-        { { 0x38dd1ac021e5781al,0x578318dbfd019ee2l,0x096b677d5f88e574l,
-            0xdbec82b216ad9f4fl },
-          { 0x348debe23260e8d9l,0x9334126064dfcda1l,0xdc5fb34cefc8faael,
-            0x5fa048beb4a6fc25l },
-          0 },
-        /* 35 << 128 */
-        { { 0xe18806fd60b3258cl,0xb7d2926b1364df47l,0xe208300fa107ce99l,
-            0x8d2f29fe7918df0el },
-          { 0x0b012d77a1244f4cl,0xf01076f4213a11cfl,0x8e623223181c559dl,
-            0x9df196ee995a281dl },
-          0 },
-        /* 36 << 128 */
-        { { 0xc431a238013ff83bl,0x7c0018b2fad69d08l,0x99aeb52a4c9589eal,
-            0x121f41ab9b1cf19fl },
-          { 0x0cfbbcbaef0f5958l,0x8deb3aeb7be8fbdcl,0x12b954081f15aa31l,
-            0x5acc09b34c0c06fdl },
-          0 },
-        /* 37 << 128 */
-        { { 0xfaa821383a721940l,0xdd70f54dd0008b83l,0x00decb507d32a52dl,
-            0x04563529cdd87deal },
-          { 0xb0e7e2a2db81643dl,0x445f4c383a6fef50l,0x5c0ef211df694ae1l,
-            0xa5a8fead923d0f1cl },
-          0 },
-        /* 39 << 128 */
-        { { 0xbc0e08b0325b2601l,0xae9e4c6105815b7al,0x07f664faf944a4a1l,
-            0x0ad19d29288f83b3l },
-          { 0x8615cd677232c458l,0x98edff6e9038e7d1l,0x082e0c4395a4dfccl,
-            0x336267afeceee00el },
-          0 },
-        /* 40 << 128 */
-        { { 0x775cbfa86d518ffbl,0xdecee1f6930f124bl,0x9a402804f5e81d0fl,
-            0x0e8225c52a0eeb2fl },
-          { 0x884a5d39fee9e867l,0x9540428ffb505454l,0xb2bf2e20107a70d1l,
-            0xd9917c3ba010b2aal },
-          0 },
-        /* 41 << 128 */
-        { { 0xc88ad4452a29bfdel,0x3072ebfa998368b7l,0xa754cbf7f5384692l,
-            0x85f7e16906b13146l },
-          { 0x42a7095f6a549fbel,0xef44edf91f7f1f42l,0xbea2989737b0c863l,
-            0x13b096d87a1e7fc3l },
-          0 },
-        /* 43 << 128 */
-        { { 0x51add77ce2a3a251l,0x840ca1384d8476adl,0x08d01d26f6096478l,
-            0x10d501a532f1662bl },
-          { 0xc8d63f811165a955l,0x587aa2e34095046al,0x759506c617af9000l,
-            0xd6201fe4a32ab8d2l },
-          0 },
-        /* 44 << 128 */
-        { { 0xa98f42fa3d843d53l,0x33777cc613ef927al,0xc440cdbecb84ca74l,
-            0x8c22f9631dc7c5ddl },
-          { 0x4bc82b70c8d94708l,0x7e0b43fcc814364fl,0x286d4e2486f59b7el,
-            0x1abc895e4d6bf4c4l },
-          0 },
-        /* 45 << 128 */
-        { { 0x7c52500cfc8c9bbdl,0x635563381534d9f7l,0xf55f38cbfd52c990l,
-            0xc585ae85058f52e7l },
-          { 0xb710a28bf9f19a01l,0x891861bdf0273ca4l,0x38a7aa2b034b0b7cl,
-            0xa2ecead52a809fb1l },
-          0 },
-        /* 46 << 128 */
-        { { 0x3df614f1ec3ca8eal,0x6bb24e9f9505bc08l,0x23ba1afbf37ace22l,
-            0x2e51b03b3463c261l },
-          { 0x59a0fca9c39e6558l,0x819f271ca342ccd9l,0x0c913d54df7ac033l,
-            0xba0f83de573257d3l },
-          0 },
-        /* 47 << 128 */
-        { { 0xdf62817ab3b32fbcl,0x616d74b0964670d4l,0xa37bc6270e26020bl,
-            0xda46d655b7d40bdal },
-          { 0x2840f155b5773f84l,0xbb633777897774b6l,0x59ff1df79a1ed3fal,
-            0xf7011ee2bac571f9l },
-          0 },
-        /* 48 << 128 */
-        { { 0x38151e274d559d96l,0x4f18c0d3b8db6c01l,0x49a3aa836f9921afl,
-            0xdbeab27b8c046029l },
-          { 0x242b9eaa7040bf3bl,0x39c479e51614b091l,0x338ede2b0e4baf5dl,
-            0x5bb192b7f0a53945l },
-          0 },
-        /* 49 << 128 */
-        { { 0xd612951861535bb0l,0xbf14364016f6a954l,0x3e0931eedde18024l,
-            0x79d791c8139441c0l },
-          { 0xba4fe7ecb67b8269l,0x7f30d848224b96c1l,0xa7e0a6abf0341068l,
-            0x78db42c37198ea2dl },
-          0 },
-        /* 51 << 128 */
-        { { 0x13354044185ce776l,0x109a6e059ff0100cl,0xafa3b61b03144cb1l,
-            0x4e4c814585265586l },
-          { 0xa8dafd33edb35364l,0x6691781bfd2606bel,0x2e06a9786182f5ccl,
-            0x588784ebe77faeecl },
-          0 },
-        /* 52 << 128 */
-        { { 0x896d572337e440d7l,0x685c5fd9ade23f68l,0xb5b1a26dc2c64918l,
-            0xb9390e30dad6580cl },
-          { 0x87911c4e7dee5b9bl,0xb90c5053deb04f6el,0x37b942a18f065aa6l,
-            0x34acdf2a1ca0928dl },
-          0 },
-        /* 53 << 128 */
-        { { 0xc773f525606f8f04l,0x75ae4a4b41b0a5bbl,0xb2aa058eaf7df93cl,
-            0xf15bea4feafed676l },
-          { 0xd2967b236a3c4fd7l,0xa698628090e30e7fl,0xf1b5166d316418bdl,
-            0x5748682e1c13cb29l },
-          0 },
-        /* 55 << 128 */
-        { { 0xe7b11babfff3605bl,0xdbce1b74cbac080fl,0xa0be39bd6535f082l,
-            0x2b6501805f826684l },
-          { 0xf90cea2400f5244fl,0xe279f2fadd244a1cl,0xd3fca77c9421c3ael,
-            0xe66bc7ee81a5210al },
-          0 },
-        /* 57 << 128 */
-        { { 0x114085dac40c6461l,0xaf78cb47f47d41b8l,0x7a9ae851755b0adbl,
-            0x8d2e8c66a0600b6dl },
-          { 0x5fb19045389758c0l,0xfa6e2cdabe7c91b2l,0x6472a432663983a2l,
-            0xc9370829e0e19363l },
-          0 },
-        /* 59 << 128 */
-        { { 0xd335856ec50bf2ffl,0x89b42295dfa708c2l,0x5dfb42241b201b4el,
-            0x6c94d6b94eecbf9cl },
-          { 0xabe5a47a7a634097l,0xf3d53b1643febecfl,0xff18619faca9846el,
-            0x80ad8629a4066177l },
-          0 },
-        /* 60 << 128 */
-        { { 0x7872e34b3390ff23l,0x968ce4abde7d18efl,0x9b4a745e627fe7b1l,
-            0x9607b0a0caff3e2al },
-          { 0x1b05818eeb40e3a5l,0x6ac62204c0fa8d7al,0xb5b9058571ed4809l,
-            0xb2432ef0f7cb65f2l },
-          0 },
-        /* 61 << 128 */
-        { { 0xc1203418f8a144b7l,0xb3413f808378f901l,0xf6badea161857095l,
-            0xcd2816c2b2e93efel },
-          { 0x6a8303ea174a0ee6l,0x98b62f29150b28b6l,0x68071bbc9c2a05b6l,
-            0xcfcf41a39f00e36el },
-          0 },
-        /* 63 << 128 */
-        { { 0xcaf564f234d6bc29l,0x9e9a6507f3c8edb0l,0x2fb889edd4e5502el,
-            0xb70d4ceb6cc9d8edl },
-          { 0x0de25356b020f740l,0xa68d9263d11fe5e6l,0xe86400679d85dd77l,
-            0xa95dfa7dec2c8c8dl },
-          0 },
-        /* 64 << 128 */
-        { { 0x715c9f973112795fl,0xe8244437984e6ee1l,0x55cb4858ecb66bcdl,
-            0x7c136735abaffbeel },
-          { 0x546615955dbec38el,0x51c0782c388ad153l,0x9ba4c53ac6e0952fl,
-            0x27e6782a1b21dfa8l },
-          0 },
-        /* 65 << 128 */
-        { { 0x3f9bc63ece59397dl,0x3f0f98a93eaa6104l,0x2f82c37c002d9271l,
-            0x6ac0495d4985353cl },
-          { 0xbde52f629191527bl,0xa3a13fce475aa640l,0x1d71ae17ce673f89l,
-            0x2b5cc61529120ec1l },
-          0 },
-        /* 71 << 128 */
-        { { 0xa0ab0f9924318c1cl,0x0cc5ca7da80ca60bl,0x24e27598abb965bal,
-            0xc4863198b44d1351l },
-          { 0x4d913783a28f04bel,0x404e78088cce8960l,0x2973b4e46286873el,
-            0x7b6e0f3219f42b50l },
-          0 },
-        /* 77 << 128 */
-        { { 0x0091a786306a6349l,0x4640ceab2098622dl,0x9928022be8182233l,
-            0xf261bee4514d0bedl },
-          { 0x70cdcc44c5f64fedl,0x4e19fec4f9eb2dfel,0xd05bdc09058b0b69l,
-            0x16f3007ed3bc6190l },
-          0 },
-        /* 83 << 128 */
-        { { 0x8f7f16957f136df1l,0x6d7547019b4f4215l,0xfb22d55eb4cc46a6l,
-            0x0b53ef53a8563034l },
-          { 0x8b105acc42bc9353l,0xe44c0a396079d59dl,0x78441fee35ee38ddl,
-            0x87ad93e43dcc0119l },
-          0 },
-        /* 89 << 128 */
-        { { 0x98a1c55358d9f73al,0xaa0843f0540e2b91l,0x701f8831d0647459l,
-            0xc4ae9d0484673005l },
-          { 0x9c37bc9f30b3ea20l,0x24cb4e2dbcbfb2b2l,0x8513e6f313cbf070l,
-            0x0c4db4334e76c79el },
-          0 },
-        /* 95 << 128 */
-        { { 0x882a2b9cbc8320b8l,0x16e9c11e3ad9e222l,0x24399ac19b23cb1dl,
-            0x334c5496799a89c7l },
-          { 0x72b6f9b8df3d774cl,0x42955bcbb11b6704l,0x3c4d6021ad2d4eafl,
-            0x5416b309afe2b671l },
-          0 },
-        /* 101 << 128 */
-        { { 0x1bbe9e662bf7c2a6l,0x22a3a10ca4acfddbl,0x2424eaab46bae581l,
-            0xebec1bbf40d6bdadl },
-          { 0xd7e3fa1a5b012aedl,0xc0f82c23f1dc6204l,0x42787c82e319477dl,
-            0xca1ae7a14cf57573l },
-          0 },
-        /* 107 << 128 */
-        { { 0x44b7d589d51bbde9l,0x15de755fd6a4cc98l,0x9b6ea8e582fb8e2el,
-            0x9d9294f04332bc22l },
-          { 0x53c6b2b7d1fa239al,0x286bf536693ca4f1l,0xc3fa754603c00f65l,
-            0xc046713af49cdb48l },
-          0 },
-        /* 113 << 128 */
-        { { 0xe356f5f11d82d5d6l,0xa0346a73d035ca0cl,0x14c76adee1884448l,
-            0xd8369bdd1c23dde9l },
-          { 0x13017862fe025eafl,0x6b5ac5e9a76be1d7l,0x52d621a94933bb6el,
-            0xb045b53baa8c1d3fl },
-          0 },
-        /* 116 << 128 */
-        { { 0x242da39e4e40466al,0xc03cb184ac322b07l,0x776b744f9aaa10bfl,
-            0xb80d9f14fe7d4beal },
-          { 0x75cd14308f9c4908l,0xa4e59ce9087b3d7al,0x3bbdce598cdca614l,
-            0x58c57113bc1a5df1l },
-          0 },
-        /* 119 << 128 */
-        { { 0x2a70af1abd79d467l,0x68dc4f23f63e2b73l,0x4345572f1f67b23dl,
-            0xc012b08f3a340718l },
-          { 0x9458585cc963dbe2l,0x21d84032223a495cl,0x0d54a4ea0dc28159l,
-            0xd9549e2c9b927dafl },
-          0 },
-        /* 125 << 128 */
-        { { 0xcd54ebd2d43c8cd2l,0x5ff4ded6a817b9f9l,0x6f59bc31245386d3l,
-            0x65b67cb0a2077821l },
-          { 0x36407956405ffa07l,0x723e0252d589f27al,0x052004b888e1239el,
-            0x8e6d188d69fdf94dl },
-          0 },
-    },
-    {
-        /* 0 << 136 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 136 */
-        { { 0xc16c236e846e364fl,0x7f33527cdea50ca0l,0xc48107750926b86dl,
-            0x6c2a36090598e70cl },
-          { 0xa6755e52f024e924l,0xe0fa07a49db4afcal,0x15c3ce7d66831790l,
-            0x5b4ef350a6cbb0d6l },
-          0 },
-        /* 3 << 136 */
-        { { 0xe2a37598a9d82abfl,0x5f188ccbe6c170f5l,0x816822005066b087l,
-            0xda22c212c7155adal },
-          { 0x151e5d3afbddb479l,0x4b606b846d715b99l,0x4a73b54bf997cb2el,
-            0x9a1bfe433ecd8b66l },
-          0 },
-        /* 4 << 136 */
-        { { 0xe13122f3dbfb894el,0xbe9b79f6ce274b18l,0x85a49de5ca58aadfl,
-            0x2495775811487351l },
-          { 0x111def61bb939099l,0x1d6a974a26d13694l,0x4474b4ced3fc253bl,
-            0x3a1485e64c5db15el },
-          0 },
-        /* 5 << 136 */
-        { { 0x5afddab61430c9abl,0x0bdd41d32238e997l,0xf0947430418042ael,
-            0x71f9addacdddc4cbl },
-          { 0x7090c016c52dd907l,0xd9bdf44d29e2047fl,0xe6f1fe801b1011a6l,
-            0xb63accbcd9acdc78l },
-          0 },
-        /* 7 << 136 */
-        { { 0x0ad7337ac0b7eff3l,0x8552225ec5e48b3cl,0xe6f78b0c73f13a5fl,
-            0x5e70062e82349cbel },
-          { 0x6b8d5048e7073969l,0x392d2a29c33cb3d2l,0xee4f727c4ecaa20fl,
-            0xa068c99e2ccde707l },
-          0 },
-        /* 9 << 136 */
-        { { 0x5b826fcb1b3ec67bl,0xece1b4b041356616l,0x7d5ce77e56a3ab4fl,
-            0xf6087f13aa212da0l },
-          { 0xe63015054db92129l,0xb8ae4c9940407d11l,0x2b6de222dfab8385l,
-            0x9b323022b7d6c3b4l },
-          0 },
-        /* 10 << 136 */
-        { { 0x057ef17a5ae6ad84l,0x9feae00b293a6ae0l,0xd18bb6c154266408l,
-            0xd3d3e1209c8e8e48l },
-          { 0xba8d4ca80e94fc8fl,0x80262ffc8a8ea0fel,0xac5b2855f71655fdl,
-            0xa348f8fae9aced89l },
-          0 },
-        /* 11 << 136 */
-        { { 0x60684b69a5660af3l,0x69aad23b9066d14bl,0x4d9f9b49fa4d020al,
-            0xafb54ec1b5cd6a4al },
-          { 0x2b25fe1832fd864dl,0xee6945062b6b64d0l,0x954a2a515001d8aal,
-            0x5e1008557082b5b3l },
-          0 },
-        /* 13 << 136 */
-        { { 0x20ecf71cbc90eb1bl,0x4234facf651c1df4l,0xc720fce9e681f678l,
-            0x680becdda7c007f4l },
-          { 0x7c08dc063181afeal,0x75c1b050a34eca91l,0x7d3479d54b9e2333l,
-            0xed16640af3951aa3l },
-          0 },
-        /* 15 << 136 */
-        { { 0x911b596264723e54l,0x34384f8c004b327cl,0x06ca5c61b85435f2l,
-            0x12e0cd25e2c1075cl },
-          { 0xa4b84cb8ac727394l,0x50bd720492b352c1l,0xe85524a49cbd0fb4l,
-            0x10b9274be7876024l },
-          0 },
-        /* 16 << 136 */
-        { { 0xef0a3fecfa181e69l,0x9ea02f8130d69a98l,0xb2e9cf8e66eab95dl,
-            0x520f2beb24720021l },
-          { 0x621c540a1df84361l,0x1203772171fa6d5dl,0x6e3c7b510ff5f6ffl,
-            0x817a069babb2bef3l },
-          0 },
-        /* 17 << 136 */
-        { { 0xb7cf93c3aace2c6al,0x017a96e658ff1bbfl,0x3b401301624a8250l,
-            0xf5ef158529266518l },
-          { 0x3c968bef7585838dl,0x8e97d023853191abl,0x175022e4f6823389l,
-            0xb6a3bfc2f6a9b4c1l },
-          0 },
-        /* 19 << 136 */
-        { { 0x515acf174591d77el,0xb393c89e3c3b25b6l,0x291e068e9c95abd7l,
-            0x256b72c046c02544l },
-          { 0x8172af03915ea92fl,0xc1b324ae4fcd0f03l,0x8abc779215108993l,
-            0xe05fe6867ab815ael },
-          0 },
-        /* 21 << 136 */
-        { { 0xca08d4095bc42740l,0xdd2c19d3e26e2e60l,0x27afdeded7c091fal,
-            0x3b943b0faf25cb22l },
-          { 0x400af8be026047e9l,0x3149b35f772b8ff9l,0x3ddb2c06f17229d9l,
-            0xcd604aeadac152fcl },
-          0 },
-        /* 23 << 136 */
-        { { 0xea2275311c0f6803l,0x9ae82d5ea394cc08l,0xc107a2cfbe32080cl,
-            0x550f35a76429f6d7l },
-          { 0x483c94dacfb70c0cl,0xf26f8e5d90190c94l,0x8574b3cf86bf2620l,
-            0xe7258e45df9f482fl },
-          0 },
-        /* 25 << 136 */
-        { { 0x8f8dc582da46f1cfl,0x61d76cf91e1e7427l,0x8aceb48b306c84aal,
-            0xecaa142f28ebff98l },
-          { 0xac5bd940401d80fel,0x0caacb8fe800cf9el,0x99068da9b3359af5l,
-            0x92fdd5795225b8c0l },
-          0 },
-        /* 27 << 136 */
-        { { 0x5a29d1c5ab56a3fbl,0x4e46ffc0a9aab4afl,0xa210472624d83080l,
-            0xb5820998007f08b6l },
-          { 0x9ce1188e4bc07b3el,0xbf6d0dbe32a19898l,0x5d5c68ea5b2350bal,
-            0xd6c794eb3aa20b45l },
-          0 },
-        /* 28 << 136 */
-        { { 0x3de605ba9ec598cfl,0x1933d3ae4d3029ael,0x6bf2fabd9b140516l,
-            0x712dfc5559a7d01cl },
-          { 0xff3eaae0d2576366l,0x36e407f948701cf8l,0xede21d89b41f4bd4l,
-            0xc5292f5c666eefa9l },
-          0 },
-        /* 29 << 136 */
-        { { 0x30045782c3ebcd77l,0xaa0cf3c73fdbe72el,0x719ec58ef8f43b39l,
-            0x9716fb9972574d3al },
-          { 0x300afc2b0d03ccd6l,0xb60016a34f3fac41l,0x8898910ea3a439f6l,
-            0xdc00a99707ca11f5l },
-          0 },
-        /* 31 << 136 */
-        { { 0x291b15ee8ed34662l,0xb780d54b2ee422a7l,0x5b9e3788fcfe4ccbl,
-            0x4554cb8cbe8b7c3al },
-          { 0xfdaccc2209a85a7fl,0x51f4a8ec555497edl,0x07dc69037da33505l,
-            0xa3bc8bfcbc1fc1dbl },
-          0 },
-        /* 33 << 136 */
-        { { 0x661638c151e25257l,0x0a6fd99c53304974l,0x29d8ae165078eec6l,
-            0xed7512ad447b73del },
-          { 0x0e21de607a4d0e9bl,0x842abd422462be01l,0x3be82afa5cddc709l,
-            0x25bb9da99b52797dl },
-          0 },
-        /* 34 << 136 */
-        { { 0x80613af28adc986al,0x4602284935776a41l,0x17d33e0f4665d03cl,
-            0xeb12eb6c0df12b50l },
-          { 0x0f0effa0ee41527fl,0x8ca2edb680531563l,0x4c354679f28c52c3l,
-            0x67f1ba5c2f6df66dl },
-          0 },
-        /* 35 << 136 */
-        { { 0x9c27207a2479fb3fl,0xef6e0f13515fb902l,0x3f7ad9e9d0d9436el,
-            0x36eb4ea5893bbcf5l },
-          { 0x5c53a2ac02b316b7l,0x10c75ee1f54f7585l,0x29e5879c3c7a4c1bl,
-            0x77da3c82f29c67d6l },
-          0 },
-        /* 36 << 136 */
-        { { 0xf2b75d21ef78a852l,0xba38cd34dd31a900l,0x72b3a68658ffe18al,
-            0x7464190cbfd95745l },
-          { 0x406e532177ed6e81l,0x1af0975bde535eabl,0x66ba22c760c54c82l,
-            0x88e3b1ceb00a2fe0l },
-          0 },
-        /* 37 << 136 */
-        { { 0xb6099b7df7e5c69bl,0x84aa1e26ba34ee2fl,0x5952600405c338bbl,
-            0xe9a134374951a539l },
-          { 0xb12276526ec196bdl,0x26a7be264b6dce36l,0x052e10a4e2a68458l,
-            0x475fc74c1f38898bl },
-          0 },
-        /* 39 << 136 */
-        { { 0x120167fc0a3eb4e1l,0xaa94bc70c0c21204l,0x313cd835e1243b75l,
-            0x3bb63fb20bfd6a4al },
-          { 0xa615dcae21ef05cfl,0x63774c2ec23c3ee5l,0x39365b1fed0dfd65l,
-            0xb610e6ff5d2a2d7dl },
-          0 },
-        /* 40 << 136 */
-        { { 0x55b7f977f0337b15l,0x3bc872a30e94973al,0x624ad983770deea0l,
-            0xcaab336413a5efdbl },
-          { 0x391dd0027a0d4247l,0x39590d5df312aed5l,0x532802c9351365acl,
-            0xdd2e824578a2e22al },
-          0 },
-        /* 41 << 136 */
-        { { 0x81b0d7be7f774fb8l,0x62f32bb3aa412425l,0xbe7afe26bbcd2162l,
-            0xa6ce167c53c7fa7dl },
-          { 0x8deca64fc5c4fc5bl,0x70e546aba6efd2fel,0xf2d8495987ff672al,
-            0x2ca551f249c3059el },
-          0 },
-        /* 43 << 136 */
-        { { 0x40b62d528eb99155l,0xe6b048947420a7e0l,0x9ebecb2bc685e58al,
-            0x3ea642d8d3c8d2cbl },
-          { 0x5340ac6ed489d0dfl,0xf3846d08c2b7588el,0x4cecd8a0611c289bl,
-            0xdddc39c50dd71421l },
-          0 },
-        /* 44 << 136 */
-        { { 0x98c6a6a52ebee687l,0xcdf65bfa56c1c731l,0x48e8132772def210l,
-            0x4ea119418083b5a5l },
-          { 0x3fdcea4fffebb525l,0x55aaea19fb50bf72l,0x5fbedc0a2a85b40cl,
-            0x0d6fd954bf44f29fl },
-          0 },
-        /* 45 << 136 */
-        { { 0x83a8302a9db4071el,0x52f104436f8ae934l,0x96de829d175b800al,
-            0x20ff5035373e97cel },
-          { 0xf58660185f65356al,0x992c15054c8cd782l,0x0b962c8eb57d727fl,
-            0xe8a9abc92bba8bc7l },
-          0 },
-        /* 46 << 136 */
-        { { 0x81a85ddd7cf2b565l,0x5e51e6afc34a0305l,0xa8d94ccefbc89faal,
-            0x2bfd97c1e68cd288l },
-          { 0x16d79c21af2958b8l,0x5e5d989defda7df8l,0x6d2f0ca6ff734c8al,
-            0xfa5b8dd32cc9bafel },
-          0 },
-        /* 47 << 136 */
-        { { 0x5787a9934e6ed688l,0x6815f3b5aab42f46l,0x7960f45b093c6c66l,
-            0xb2b9829728be10cfl },
-          { 0x1d4c7790296568cdl,0xa279a877f048e194l,0xcf7c20f4c6a58b4el,
-            0xf0c717afa1f9c00fl },
-          0 },
-        /* 48 << 136 */
-        { { 0x8a10b53189e800cal,0x50fe0c17145208fdl,0x9e43c0d3b714ba37l,
-            0x427d200e34189accl },
-          { 0x05dee24fe616e2c0l,0x9c25f4c8ee1854c1l,0x4d3222a58f342a73l,
-            0x0807804fa027c952l },
-          0 },
-        /* 49 << 136 */
-        { { 0x79730084ba196afcl,0x17d38e98054bd539l,0xc5cfff3918583239l,
-            0x4b0db5a2d9adbee6l },
-          { 0x9bc9f1e3c2a304e8l,0xbaa61de7de406fa8l,0x8e921ca9e4bec498l,
-            0xd9f4e5ae6604ab02l },
-          0 },
-        /* 51 << 136 */
-        { { 0xdf6b97b5b37f2097l,0x7576c3f9b4a5d2b9l,0x6eb697ed3588cabbl,
-            0x4d75b38622598d8fl },
-          { 0x4e6d93b522ff55e8l,0x4620ec635b8f7edal,0xd5006209f97b7749l,
-            0x9e22e3a84da8b464l },
-          0 },
-        /* 52 << 136 */
-        { { 0xbabfb7f82e8f326fl,0xed9cac225625a519l,0xf1109c1a0edae0a9l,
-            0x45f80a9858521259l },
-          { 0x37a44b075ab71f44l,0x21699eb64a21161bl,0xb523fddf56fe67eel,
-            0x9f5c3a2120b9f72el },
-          0 },
-        /* 53 << 136 */
-        { { 0x12c1131508b75673l,0xfa20121823b096d6l,0x839f01aeeacd6537l,
-            0x0e592be787df32cal },
-          { 0xfe3f65ff8b7dd0fcl,0xed09b4875c1d9a80l,0x8c09dd97b79786d8l,
-            0x74eba2806c5bc983l },
-          0 },
-        /* 55 << 136 */
-        { { 0xf917704862987b50l,0xcc84cdc6bc4ac456l,0x8bd2c922ae08fe12l,
-            0x09d5f661fc2d06c7l },
-          { 0xd10ac6dd9457d47fl,0x65aa30a23668060cl,0x33cddac6745161fcl,
-            0xf4c18b5ea51e540fl },
-          0 },
-        /* 57 << 136 */
-        { { 0x591c064ede723c1fl,0x92e5d4e601a4adael,0x3d7ee8a3145716ecl,
-            0x0ef4c62061727816l },
-          { 0x0e17c576f1bf6d6el,0x173104015ae18045l,0xdad620aae9589b75l,
-            0xb10c7e2d0eda4905l },
-          0 },
-        /* 59 << 136 */
-        { { 0xb8020f16aa08df6fl,0x03cf58ffd67054e9l,0x302e003c11fe3d1al,
-            0x9c194bc1c638a3ecl },
-          { 0x8ed3cb3adefd3f1el,0xc4115e079bf39de4l,0x8dece48bdf46fdf6l,
-            0xebd1dbcf30eafeafl },
-          0 },
-        /* 60 << 136 */
-        { { 0x058eb276fba319c5l,0xd33a91127f7fa54al,0xf060c1b4932a2dabl,
-            0xce3a224e79c7d9bfl },
-          { 0x6fb0388c0ba92823l,0x8d31738a69787881l,0x2d86eb0203cd00b7l,
-            0x4e6e44512b69911bl },
-          0 },
-        /* 61 << 136 */
-        { { 0xff2efe1cfdcca1cfl,0x08f22c69b5bb71e3l,0xc63f4a9f7023076el,
-            0x88fb2aa0ce0c490el },
-          { 0xcc7c97f91f77783cl,0x360026d942ab36b7l,0x547c34ecefd68f70l,
-            0xebe7f99efbabfdabl },
-          0 },
-        /* 63 << 136 */
-        { { 0xe7c1c1788613e87al,0xb035d65e60b82654l,0x055a82d03583a254l,
-            0x27ce1ffc9b3b22fal },
-          { 0x0cf904917ec83cd5l,0xfc6c21805604aa40l,0x1330604099357428l,
-            0x9b0982f9ad4818b7l },
-          0 },
-        /* 64 << 136 */
-        { { 0xc222653a4f0d56f3l,0x961e4047ca28b805l,0x2c03f8b04a73434bl,
-            0x4c966787ab712a19l },
-          { 0xcc196c42864fee42l,0xc1be93da5b0ece5cl,0xa87d9f22c131c159l,
-            0x2bb6d593dce45655l },
-          0 },
-        /* 65 << 136 */
-        { { 0x3a6080d9fb56bc3al,0xf1552dcad6212d7el,0x977ac5b59420f4f6l,
-            0xef914d370e3cd97fl },
-          { 0x807bd6e69c04f768l,0x743a7b552bb803f6l,0x7f5c20804215f4b0l,
-            0x41e331288fc6ce42l },
-          0 },
-        /* 71 << 136 */
-        { { 0x5a31c9ac61e6a460l,0x55102e4093e7eeddl,0x969fe0612da6adcel,
-            0xe8cddc2f3ffea1d9l },
-          { 0xaa26c6b1f0f327c5l,0x9e5b63743544f5e1l,0x5159fa1ddbaa685bl,
-            0x9892d03aa7f44b99l },
-          0 },
-        /* 77 << 136 */
-        { { 0x4dfcbf12e2c6fc1fl,0x703f2f5b7535ac29l,0x78f8617e82f7dc0fl,
-            0x54b835ff853e792dl },
-          { 0x3cc7f000df9f7353l,0x0d7ffd68db5a157al,0x2c1c33691672b21cl,
-            0x694b4904ac970ef8l },
-          0 },
-        /* 83 << 136 */
-        { { 0xd655bc42c1d2c45cl,0x572f603cbd22b05fl,0xa7fbf09388e4531al,
-            0x8d38bbd91fdde98dl },
-          { 0x16cc2aaa73b0fa01l,0x515019a25e8ffb04l,0xb075990611e792ccl,
-            0x89df06f399112c90l },
-          0 },
-        /* 89 << 136 */
-        { { 0x26d435c2481b46dal,0x73ab7e96266e9b3al,0x22d5b1db3c613c40l,
-            0x9de4021c6727e399l },
-          { 0x451ebba56051f8c9l,0xa37f6ec52c281a58l,0x3d7a28fe0e9f4cc5l,
-            0x0f45bcd655b64df7l },
-          0 },
-        /* 95 << 136 */
-        { { 0xba2a718c66616fbel,0x4b27810b3369a9acl,0x50b8391a2b426d5fl,
-            0x420c88efa626fa05l },
-          { 0xe39cef97b9c39a30l,0xcae7cde85e67e5d0l,0x3821f8319a58e521l,
-            0xbf474d1941479509l },
-          0 },
-        /* 101 << 136 */
-        { { 0x401bbab58fb15118l,0xb0376892dbf38b39l,0x10e4b9dd3a3ca42al,
-            0xa69c2693f8063ffel },
-          { 0xe10facdde07cb761l,0x96f4dde831d7759al,0xd702fdecc2cc7f9fl,
-            0x9e87e46e1ac0162cl },
-          0 },
-        /* 107 << 136 */
-        { { 0xb6cd60518479ca8fl,0xcca345e60968f6c7l,0x7b57248a64a9afe7l,
-            0x5552e3511d0d4db9l },
-          { 0x8f749b199dc68aabl,0x0fb86f06db1f7819l,0x23b300963143ac09l,
-            0x61c166d8abfbcb9bl },
-          0 },
-        /* 113 << 136 */
-        { { 0x4c96e85a43101165l,0x393a882fcf39bd19l,0xef9e1d42c2df6f33l,
-            0xe1775c990278f088l },
-          { 0xb1581929a9250d4al,0x582b0608c4168873l,0x0b3ffba3a1e68cd8l,
-            0x3f78147ef9490897l },
-          0 },
-        /* 116 << 136 */
-        { { 0x277b5177eb18ff20l,0x48002e9828f06d62l,0xece8d6c30e506d8dl,
-            0x5cde0a58cd9ff963l },
-          { 0x3b97cdb74e3baa0el,0x50560c0b631238f9l,0xe1c31b35cf79793dl,
-            0x95d12f14355e2178l },
-          0 },
-        /* 119 << 136 */
-        { { 0x0143f695bcc31b77l,0x3627aed14c49b65al,0x6e4f7a9ce441c183l,
-            0xb708c79de1bfa0a3l },
-          { 0xdbf0fc313a0726b8l,0xe04d82a8852d78bbl,0xb859001e3be5d398l,
-            0x92dcc20c8e89bd11l },
-          0 },
-        /* 125 << 136 */
-        { { 0x5f2416a3df9026b4l,0xffc01f3afcb29a1bl,0x18d02c9f1d94b20fl,
-            0xd93b0f2f81cfdef3l },
-          { 0xe6b0fd4713adf5f2l,0xcc9067b7ba06dff3l,0xb48c0cbb2256f842l,
-            0xc2ae741dfd34df2fl },
-          0 },
-    },
-    {
-        /* 0 << 144 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 144 */
-        { { 0x80531fe1c63c4962l,0x50541e89981fdb25l,0xdc1291a1fd4c2b6bl,
-            0xc0693a17a6df4fcal },
-          { 0xb2c4604e0117f203l,0x245f19630a99b8d0l,0xaedc20aac6212c44l,
-            0xb1ed4e56520f52a8l },
-          0 },
-        /* 3 << 144 */
-        { { 0x18f37a9c6bdf22dal,0xefbc432f90dc82dfl,0xc52cef8e5d703651l,
-            0x82887ba0d99881a5l },
-          { 0x7cec9ddab920ec1dl,0xd0d7e8c3ec3e8d3bl,0x445bc3954ca88747l,
-            0xedeaa2e09fd53535l },
-          0 },
-        /* 4 << 144 */
-        { { 0xa12b384ece53c2d0l,0x779d897d5e4606dal,0xa53e47b073ec12b0l,
-            0x462dbbba5756f1adl },
-          { 0x69fe09f2cafe37b6l,0x273d1ebfecce2e17l,0x8ac1d5383cf607fdl,
-            0x8035f7ff12e10c25l },
-          0 },
-        /* 5 << 144 */
-        { { 0xb7d4cc0f296c9005l,0x4b9094fa7b0aebdbl,0xe1bf10f1c00ec8d4l,
-            0xd807b1c4d667c101l },
-          { 0xa9412cdfbe713383l,0x435e063e81142ba1l,0x984c15ecaf0a6bdcl,
-            0x592c246092a3dab9l },
-          0 },
-        /* 7 << 144 */
-        { { 0x9365690016e23e9dl,0xcb220c6ba7cc41e1l,0xb36b20c369d6245cl,
-            0x2d63c348b62e9a6al },
-          { 0xa3473e19cdc0bcb5l,0x70f18b3f8f601b98l,0x8ad7a2c7cde346e4l,
-            0xae9f6ec3bd3aaa64l },
-          0 },
-        /* 9 << 144 */
-        { { 0x030223503274c7e1l,0x61ee8c934c4b6c26l,0x3c4397e3199389cel,
-            0xe0082600488757cel },
-          { 0xaac3a2df06b4dafbl,0x45af0700ddff5b6al,0x0a5974248c1d9fa0l,
-            0x1640087d391fc68bl },
-          0 },
-        /* 10 << 144 */
-        { { 0x26a43e41d07fa53dl,0x3154a78a74e35bc5l,0x7b768924e0da2f8cl,
-            0xba964a2b23613f9al },
-          { 0x5a548d35ba1d16c4l,0x2e1bfed1fb54d057l,0xff992136bc640205l,
-            0xf39cb9148156df29l },
-          0 },
-        /* 11 << 144 */
-        { { 0xf4873fcf4e5548bdl,0x8725da3f03ce57f0l,0xd82f5c95ca953258l,
-            0xac647f127cf0747el },
-          { 0xff2038b02d570bd5l,0xb0c2a767a13ae03fl,0xebaa27cde9932d16l,
-            0xa686e3fc1234e901l },
-          0 },
-        /* 13 << 144 */
-        { { 0x9f80435e63261eccl,0x6302a62e4337d6c9l,0x91916a49ca4958a0l,
-            0x554958993149d5d3l },
-          { 0x378d020b9f91de3cl,0x47b839a34dd25170l,0x2825854138b7f258l,
-            0xea5b14f7437e7decl },
-          0 },
-        /* 15 << 144 */
-        { { 0x74f08736b0018f44l,0xf4a03417b446d0f5l,0x66a4aa2fa40ca6b2l,
-            0x215679f0badb60edl },
-          { 0x3871195a323e4eefl,0x8f0940c320952b16l,0xfe8dac62879d5f7dl,
-            0x649cb623c1a6e875l },
-          0 },
-        /* 16 << 144 */
-        { { 0xecaff541338d6e43l,0x56f7dd734541d5ccl,0xb5d426de96bc88cal,
-            0x48d94f6b9ed3a2c3l },
-          { 0x6354a3bb2ef8279cl,0xd575465b0b1867f2l,0xef99b0ff95225151l,
-            0xf3e19d88f94500d8l },
-          0 },
-        /* 17 << 144 */
-        { { 0xa26a9087133ec108l,0x5dc5699f2712bdc0l,0x96903f4dd14224a9l,
-            0x3da5992429e47b80l },
-          { 0xb717712ff9dbba5al,0x9e52004b756391c9l,0xe669a11dcc9d219cl,
-            0x3b6e6b84d1d6c07dl },
-          0 },
-        /* 19 << 144 */
-        { { 0x5feec06a676feadbl,0xfc449bc59d69f322l,0x1d8d7b5e7cda8895l,
-            0x5ed54dc11a3314a7l },
-          { 0x1a11d2ae6de889c0l,0xb2a979724ced2bd9l,0x6ecf6989306a5ef6l,
-            0x1611d57b8cc8a249l },
-          0 },
-        /* 21 << 144 */
-        { { 0x2d9942ba007cbf87l,0x4e62bce6df3fc926l,0xe7eee5b0e4560affl,
-            0xe51963bb7cb009b7l },
-          { 0xaa5118cee29b37ddl,0x5cd84a4747263903l,0x3050caa6620055d8l,
-            0x7ef576a76c4b1e3dl },
-          0 },
-        /* 23 << 144 */
-        { { 0x9026a4dde6008ff1l,0x49e995ad1c8cd96cl,0x80722e73503e589bl,
-            0x05bcbce184c2bc26l },
-          { 0x255f9abbd4682c2cl,0xc42bcfc2f084d456l,0xa0eae9b0641c0767l,
-            0x1b45632d864c9a2dl },
-          0 },
-        /* 25 << 144 */
-        { { 0xcf25793b6ae024e0l,0x1b6607b484b5c4b0l,0x9579fa903f1624c8l,
-            0x37fb65be68bd57e8l },
-          { 0xd693a55efc39c203l,0x4e267ac4c87252e9l,0xb8d78bb09f899413l,
-            0xe4c014070b3b8508l },
-          0 },
-        /* 27 << 144 */
-        { { 0x662906e5bc3f3553l,0xde38d53531459684l,0x8f46a8c634f7280dl,
-            0xaaf91b873d24198el },
-          { 0xecd5ee115f9b117el,0xce00ffbe50ae8ddal,0x263a3d4e7710a9ael,
-            0x0ff3f721f26ba74fl },
-          0 },
-        /* 28 << 144 */
-        { { 0x4a8a4f47f0cefa69l,0xdc8e4cbaa4546866l,0x359ba69b23f603c1l,
-            0xdab4d601187b7ac5l },
-          { 0xa6ca4337c1ebc8d9l,0x9fa6585452b4074bl,0x1a4b4f81902fb733l,
-            0xd2bb5d7aa525deaal },
-          0 },
-        /* 29 << 144 */
-        { { 0xcc287ac2e6b3577al,0xd7528ca7f612003bl,0x8afdb6f12c1400b8l,
-            0x103a2ed346a2dd8dl },
-          { 0xc8f8c54d2ee21339l,0x8f011b92355a2d20l,0x81c6fc9f1346f2acl,
-            0xdb6042f005a6d24bl },
-          0 },
-        /* 31 << 144 */
-        { { 0xfc90e3630da4f996l,0x8ceca49daa6d6fe4l,0x1084affdbdfc619bl,
-            0x2029f672c1140b04l },
-          { 0x606ec25f136f3e5el,0x6d24149b02224c4al,0xabb0f142cfdfcf4cl,
-            0xe40d0419fab1a0edl },
-          0 },
-        /* 33 << 144 */
-        { { 0xcfdd08265cbccb84l,0x2258a16e88ad93c4l,0xb3ac365e728c5ad3l,
-            0x0bbf97808560df1fl },
-          { 0x42d08a39bad8c7b8l,0x1e3960106d3e8b91l,0xc332b39910274f58l,
-            0xe0a84dacce2ea778l },
-          0 },
-        /* 34 << 144 */
-        { { 0x113e1189ff432945l,0x4a0d2c3d04e1106cl,0xcde487744f3597b1l,
-            0x853b029174fa26eal },
-          { 0x2149e0ff02662e26l,0xb3181eaa5e6a030fl,0x086fc2159b006340l,
-            0xa1df84a694a4e0bbl },
-          0 },
-        /* 35 << 144 */
-        { { 0xc2cbd80ac99f8d3dl,0xe24b9d8f50ecf4f4l,0xf18d34728ecb126al,
-            0x83966662e1670aael },
-          { 0x1cece80fda5f594el,0x545e94ae65f391e0l,0xf3286dff93f98bb7l,
-            0xf945e6cdf5abf176l },
-          0 },
-        /* 36 << 144 */
-        { { 0x00ba5995dd95ac33l,0xa4957a40738f3bf4l,0x073539f599438a85l,
-            0xcc9c43acc2eb1411l },
-          { 0xe27501b5be2ec3d2l,0xa88d4ed057a85458l,0x870ae236755c8777l,
-            0x0933c5af89216cbal },
-          0 },
-        /* 37 << 144 */
-        { { 0xb5feea219e40e37fl,0x8c5ccb159e20fd60l,0xaeddc502ce8209a1l,
-            0xbdf873cc11e793b3l },
-          { 0xbc938103f0de8db5l,0x619fb72fb0e9d3d5l,0x800147cb588ed2adl,
-            0x260f92bb7901ced8l },
-          0 },
-        /* 39 << 144 */
-        { { 0x72dd9b089848c699l,0xc6086381185dacc1l,0x9489f11ff7d5a4c8l,
-            0xedb41d5628dee90fl },
-          { 0x1091db6b09af693cl,0xc7587551ae4b6413l,0x806aefb0768227adl,
-            0x4214b83eafb3c88el },
-          0 },
-        /* 40 << 144 */
-        { { 0xddfb02c4c753c45fl,0x18ca81b6f9c840fel,0x846fd09ab0f8a3e6l,
-            0xb1162adde7733dbcl },
-          { 0x7070ad20236e3ab6l,0xf88cdaf5b2a56326l,0x05fc8719997cbc7al,
-            0x442cd4524b665272l },
-          0 },
-        /* 41 << 144 */
-        { { 0x748819f9aa9c0ef5l,0xd7227d8ba458ad48l,0x8d67399f27aef626l,
-            0xc6241a1859bf0a4cl },
-          { 0xed9b0bfcc31cb9bbl,0x591254f896142555l,0x80e4bab461134151l,
-            0x7c5e680243efbd83l },
-          0 },
-        /* 43 << 144 */
-        { { 0x7f3f5a1706b9b7ddl,0x392132e75faeb417l,0x508ac4788fae38a2l,
-            0x2b854ead0d3499c3l },
-          { 0x26a687d8ef18bf0fl,0x62ff0c4a8ae00b61l,0x84111011f48578f2l,
-            0xa879f383cd0fcd3al },
-          0 },
-        /* 44 << 144 */
-        { { 0xeb7615aa202992f0l,0xde0562b38361d0b3l,0x789a302862027ee0l,
-            0xe3e3e9921048f899l },
-          { 0x07945c246deadab4l,0xeb06a15ec77d894el,0xb825af36bab1416bl,
-            0x99083c4df4b4e04fl },
-          0 },
-        /* 45 << 144 */
-        { { 0x4684a8f27b3ad6c3l,0x58238dbd928d9b6bl,0x31865b998da2c495l,
-            0xc1ca784fb8e7cda1l },
-          { 0xc9605dc71e081572l,0x8f560bcdef8ed104l,0x51f73981bd3feaedl,
-            0xc778aa4e4251c88dl },
-          0 },
-        /* 46 << 144 */
-        { { 0x9c0daa63aa502800l,0x73c7959a1e15b9bdl,0xd0447bcb7ab10f6cl,
-            0x05b8fbc8b8311bdel },
-          { 0xa8a74be1915d5c4el,0x38d41c1e0b7c0351l,0x5bb2d49ff52d6568l,
-            0x6c48d8eed5e43593l },
-          0 },
-        /* 47 << 144 */
-        { { 0x387b26d554159498l,0x92e92fad1ec34eb4l,0x0f88705e7a51b635l,
-            0x66bcbf4dedca735fl },
-          { 0x0a4c6112dcb896ccl,0x148e1dfe6fc72ad9l,0x3de977fd2b4c9585l,
-            0x0cd6e65f741e62cal },
-          0 },
-        /* 48 << 144 */
-        { { 0x7807f364b71698f5l,0x6ba418d29f7b605el,0xfd20b00fa03b2cbbl,
-            0x883eca37da54386fl },
-          { 0xff0be43ff3437f24l,0xe910b432a48bb33cl,0x4963a128329df765l,
-            0xac1dd556be2fe6f7l },
-          0 },
-        /* 49 << 144 */
-        { { 0x98ae40d53ce533bal,0x10342e1931fdd9c2l,0x54a255c8abf8b2bfl,
-            0x8facc41b15f6fef7l },
-          { 0x2e195565bc65b38bl,0xb9f3abaaeaea63cbl,0xede2ab9bf2b7518bl,
-            0x5e84102ce9ea3d81l },
-          0 },
-        /* 51 << 144 */
-        { { 0x162abc35113bc262l,0x8012f06829eb3fd4l,0x0e2727eb2c1ccf9cl,
-            0x89561ff44b455b20l },
-          { 0xc48db835ee3b1fd4l,0x4075ca86095bbfa7l,0x0c498d7d98745182l,
-            0x828fb93c5dfb5205l },
-          0 },
-        /* 52 << 144 */
-        { { 0xf95c7a5f0a76333bl,0x07603929cd607927l,0xabde328591028d3el,
-            0x55765e8fa032a400l },
-          { 0x3041f2cabed17cd7l,0x018a5b7b9a9e5923l,0xca4867975bb9bae3l,
-            0x741c802ecc382cb5l },
-          0 },
-        /* 53 << 144 */
-        { { 0x182a10311e5a3d8el,0xc352b8c8986c4d10l,0x7c50a172434c02ebl,
-            0x121d728c4420c41cl },
-          { 0x0f8eca2a8a51812fl,0xdb6c4a4ea5158430l,0x67944e0b8d8f4144l,
-            0x387cc2052405c77al },
-          0 },
-        /* 55 << 144 */
-        { { 0x98b36eb47e95ad76l,0x1973fa7d5f7e5ff7l,0xc4827abc6cc8a25cl,
-            0x4263a0d3ec822ae4l },
-          { 0x49f113f35217a6f4l,0xf27cc9bb81748aa6l,0x9cb81d97d822e08el,
-            0x698d2826b5c360bcl },
-          0 },
-        /* 57 << 144 */
-        { { 0x895f81514eb6d0b8l,0x32ef71df9f786536l,0x032a449430379a79l,
-            0xa8c1076218bdb83fl },
-          { 0x7a3b0b8fe53a4064l,0x0e724a54e2ce89b7l,0x565baeba7a31f6bcl,
-            0x12b9fa6387d18a7bl },
-          0 },
-        /* 59 << 144 */
-        { { 0x027231a3585bcfbdl,0x8690e977dca24269l,0x229c021afc6f1422l,
-            0xd98050d044084cabl },
-          { 0x6add95d79d4fd09al,0x12484c68c15b24ddl,0xa79a8f4facf4f551l,
-            0xf53204e27a83cbecl },
-          0 },
-        /* 60 << 144 */
-        { { 0xbc006413a906f7aal,0x9c8cd648bbeaf464l,0xaf5c7c64fb78cdf2l,
-            0xe45839eafabc2375l },
-          { 0x1eb89bd150012172l,0x9d0d76194488518cl,0xd55a7238bd534d32l,
-            0x48f35d5e95b4fe55l },
-          0 },
-        /* 61 << 144 */
-        { { 0xa6c5574f3e70a35al,0x35c11b5a8df97d97l,0x8f629f6cda85dd27l,
-            0x94dab294c218452el },
-          { 0xa2e1882e8916c731l,0xc02ce77c8929e350l,0xa7ed351fe4eff8afl,
-            0xeb76ef0654c3e1c1l },
-          0 },
-        /* 63 << 144 */
-        { { 0xc31d7cf87e3f5be5l,0x1472af0d3ce7f3a0l,0x226414f8f962e1afl,
-            0xd318e3df16f54295l },
-          { 0x9a3f6aaf41477cd3l,0x7034172f66ec6b2el,0xbea54eb537413a62l,
-            0x79f81262dc515e73l },
-          0 },
-        /* 64 << 144 */
-        { { 0x994f523a626332d5l,0x7bc388335561bb44l,0x005ed4b03d845ea2l,
-            0xd39d3ee1c2a1f08al },
-          { 0x6561fdd3e7676b0dl,0x620e35fffb706017l,0x36ce424ff264f9a8l,
-            0xc4c3419fda2681f7l },
-          0 },
-        /* 65 << 144 */
-        { { 0xb71a52b8b6bf8719l,0x0c7701f73196db36l,0xff1b936f53141cf4l,
-            0x684d8a3c1b94a31cl },
-          { 0xe555633ab52386e1l,0x9353a2af91450578l,0xc53db6fab99b14bcl,
-            0x1f2d42adcf619d36l },
-          0 },
-        /* 71 << 144 */
-        { { 0xbeb535ef3851c573l,0x3105fff585589843l,0xbe9f62a1d47aaf06l,
-            0x6bb2ee5d107e1131l },
-          { 0x82530247a4a7699fl,0x3fb475e144872afbl,0x8ad43fd73c4c49f2l,
-            0x3f7632882e045fc4l },
-          0 },
-        /* 77 << 144 */
-        { { 0x48440beb2924d7b2l,0x234163809c88fc57l,0xdc1d23d54ab08c2bl,
-            0x576400b6e70feab0l },
-          { 0x3b8afb8ba66da779l,0x7a7e3bf445468f16l,0x1976ddf3231f79dfl,
-            0xbe61c170b8531a9el },
-          0 },
-        /* 83 << 144 */
-        { { 0xf8d2dc768bf191b2l,0x3269e68813a39eb9l,0x104bb84be755eccfl,
-            0xb8d1330f2868f807l },
-          { 0x2b29c74cb06c6059l,0x3648baa1a6440a26l,0x5dfae323f1e6b2c9l,
-            0x9d0319b79330ac0al },
-          0 },
-        /* 89 << 144 */
-        { { 0x526ba3770e708bb2l,0x95c21ba327565dd9l,0x7071f46d48a0a873l,
-            0xe4b9959efed6cc74l },
-          { 0x1b16bfd1e08a5afal,0xc87fec98d1789782l,0x200186e946cfd068l,
-            0x88ea35a7280bf3ebl },
-          0 },
-        /* 95 << 144 */
-        { { 0x9e31943d42ac0e6cl,0xe61374cf1db8e40fl,0xbe27ea35a27db609l,
-            0x7c5b91d67bf192e9l },
-          { 0xc2af846defd0a24bl,0x1b2efc37669b647al,0xbfc3c38e5e58ef8al,
-            0xb6afb167e13ab5a2l },
-          0 },
-        /* 101 << 144 */
-        { { 0x08612d29b9f2aad4l,0x43c41330ad09dd17l,0xa45cb84a9f740519l,
-            0x0a9ea9a7512ec031l },
-          { 0x6e90dccaee747f35l,0xe4388bd1f0a1479bl,0x966140c4e20a9029l,
-            0x1bb1f65d7dd956abl },
-          0 },
-        /* 107 << 144 */
-        { { 0x066d206ea8f12bb3l,0xc9023b1b4325ec13l,0x1f56c72c96ead8ddl,
-            0x454050fd8003e4c2l },
-          { 0x9ca258a58917aa9dl,0xfe24b282d94593cfl,0xea66c203752741cfl,
-            0x5714268c295a895el },
-          0 },
-        /* 113 << 144 */
-        { { 0x72a9fbecc177d694l,0x38bb9387d68454d3l,0xa3d347bf590bc7d2l,
-            0xcb6e292605ccc234l },
-          { 0x588abfcf0d393c01l,0xf053dadf539e5568l,0xad7480fef2a8b157l,
-            0xff28c8bb018cac8fl },
-          0 },
-        /* 116 << 144 */
-        { { 0x12f1a00e7f5b8821l,0x0afa44e489b4b0cel,0x2dcaad8f6006338el,
-            0x79c022cdba41242bl },
-          { 0x7f6ef7e17871d350l,0x946c2a91674253adl,0xf686d137a9cbbdd9l,
-            0xa47ce2eaf7d4f9f2l },
-          0 },
-        /* 119 << 144 */
-        { { 0x1824991b205d40d6l,0x49cca1c085046a90l,0x7e23c1acd005e3c2l,
-            0x093a9ae6d102c8ffl },
-          { 0xf4791082d2f40843l,0xe456021811645483l,0x8a59c3b0fd3a6b39l,
-            0x39130e7f820de158l },
-          0 },
-        /* 125 << 144 */
-        { { 0xf7eef88d83b90783l,0xff60762af336d581l,0xf64f2d5dd801f5a0l,
-            0x672b6ee7d6b3b8b9l },
-          { 0xa2a2dceb08034d69l,0x3eca27f635638218l,0xe7065986fa17fefdl,
-            0xf1b74445f5803af1l },
-          0 },
-    },
-    {
-        /* 0 << 152 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 152 */
-        { { 0x32670d2f7189e71fl,0xc64387485ecf91e7l,0x15758e57db757a21l,
-            0x427d09f8290a9ce5l },
-          { 0x846a308f38384a7al,0xaac3acb4b0732b99l,0x9e94100917845819l,
-            0x95cba111a7ce5e03l },
-          0 },
-        /* 3 << 152 */
-        { { 0x37a01e48a105fc8el,0x769d754a289ba48cl,0xc08c6fe1d51c2180l,
-            0xb032dd33b7bd1387l },
-          { 0x953826db020b0aa6l,0x05137e800664c73cl,0xc66302c4660cf95dl,
-            0x99004e11b2cef28al },
-          0 },
-        /* 4 << 152 */
-        { { 0x214bc9a7d298c241l,0xe3b697ba56807cfdl,0xef1c78024564eadbl,
-            0xdde8cdcfb48149c5l },
-          { 0x946bf0a75a4d2604l,0x27154d7f6c1538afl,0x95cc9230de5b1fccl,
-            0xd88519e966864f82l },
-          0 },
-        /* 5 << 152 */
-        { { 0x1013e4f796ea6ca1l,0x567cdc2a1f792871l,0xadb728705c658d45l,
-            0xf7c1ff4ace600e98l },
-          { 0xa1ba86574b6cad39l,0x3d58d634ba20b428l,0xc0011cdea2e6fdfbl,
-            0xa832367a7b18960dl },
-          0 },
-        /* 7 << 152 */
-        { { 0x1ecc032af416448dl,0x4a7e8c10ec76d971l,0x854f9805b90b6eael,
-            0xfd0b15324bed0594l },
-          { 0x89f71848d98b5ca3l,0xd01fe5fcf039b3efl,0x4481332e627bda2el,
-            0xe67cecd7a5073e41l },
-          0 },
-        /* 9 << 152 */
-        { { 0x2ab0bce94595a859l,0x4d8c2da082084ee7l,0x21ff8be5acca3d3cl,
-            0xd8b805337827f633l },
-          { 0xf74e8c026becabbfl,0x9fae4dbefede4828l,0xd3885a5b3cc46bcfl,
-            0x2d535e2b6e6ad144l },
-          0 },
-        /* 10 << 152 */
-        { { 0x63d3444507d9e240l,0x6fbadf4338cff7e6l,0x8717624a959c9461l,
-            0xd7d951c411fb775bl },
-          { 0x4049161af6fc3a2bl,0x0dfa2547a1a8e98dl,0xeca780d439c2139cl,
-            0xd8c2d8cbd73ea8efl },
-          0 },
-        /* 11 << 152 */
-        { { 0x3aa1974f07605b28l,0x4f3d82a71e296255l,0xbbe5ea03b4e23f16l,
-            0x8f5c6c6b4e654193l },
-          { 0x27181182d3e8ab01l,0xc68bb231f3ba6bc2l,0x90a244d820af1fd7l,
-            0x605abc055b713f4fl },
-          0 },
-        /* 13 << 152 */
-        { { 0xca5fe19bd221991al,0x271ff066f05f400el,0x9d46ec4c9cf09896l,
-            0xdcaa8dfdec4febc3l },
-          { 0xaa3995a0adf19d04l,0xc98634239da573a6l,0x378058b2f2465b2bl,
-            0x20d389f9b4c31612l },
-          0 },
-        /* 15 << 152 */
-        { { 0xd7d199c7b7631c9dl,0x1322c2b8bb123942l,0xe662b68fbe8b6848l,
-            0xc970faf2cde99b14l },
-          { 0x61b27134b06655e5l,0xadcef8f781365d89l,0x917b5ab521b851aal,
-            0x4f4472121cf694a7l },
-          0 },
-        /* 16 << 152 */
-        { { 0x488f1185ca8d9d1al,0xadf2c77dd987ded2l,0x5f3039f060c46124l,
-            0xe5d70b7571e095f4l },
-          { 0x82d586506260e70fl,0x39d75ea7f750d105l,0x8cf3d0b175bac364l,
-            0xf3a7564d21d01329l },
-          0 },
-        /* 17 << 152 */
-        { { 0x241e3907fe44e547l,0x42d464c36b992187l,0xeaa8fa989ba72f28l,
-            0x965a8b8f6afbb81fl },
-          { 0x69356a7a8b375ea5l,0x22501ec741bdcc83l,0xf80f4e1445fb180cl,
-            0xc0b12e95f5e1b822l },
-          0 },
-        /* 19 << 152 */
-        { { 0x977234e05483dc02l,0x0167430c13d8dcb2l,0xa9971278049912edl,
-            0xab044b18ca40fa39l },
-          { 0xac9587449ff3896cl,0x75bb32eb860d1240l,0xf807071f6b958654l,
-            0x67d2d3dc7121b4b6l },
-          0 },
-        /* 21 << 152 */
-        { { 0x3b61e67722f9f017l,0x9c593eb1a8541696l,0xbeba950050eda653l,
-            0x07b5a48f5e673f6al },
-          { 0x748dca0013257aa3l,0x6bbddf9a7372e942l,0xc012f4badde83977l,
-            0x6e59b327392ddb53l },
-          0 },
-        /* 23 << 152 */
-        { { 0xb2f3fff641356603l,0x50e63537545f042bl,0x55e5149770eb530dl,
-            0x5a7383c310860c3bl },
-          { 0x7be30382ea669a09l,0xfdf735d289cc1c7fl,0x6e51ed844e0607cfl,
-            0xdab566df4893795el },
-          0 },
-        /* 25 << 152 */
-        { { 0x20e3be0f8920690dl,0x98db80eaac279c05l,0x4cd5c60a44b8a4f8l,
-            0xeda7e91c7b0335f4l },
-          { 0x45c1302a41ee5713l,0x1f6455fe588508d0l,0x82cb7311163d2fc3l,
-            0xe866b90322f10b71l },
-          0 },
-        /* 27 << 152 */
-        { { 0xc217a2e259b4041el,0x85b96ce274526cbfl,0xcbfc4f5473f12687l,
-            0x097caa5fd40225e7l },
-          { 0x0871ad406e91293fl,0x5f2ea207033b98ecl,0x0b3b8fac1f27d37al,
-            0x7d72dd4c7f03876cl },
-          0 },
-        /* 28 << 152 */
-        { { 0xb51a40a51e6a75c1l,0x24327c760ea7d817l,0x0663018207774597l,
-            0xd6fdbec397fa7164l },
-          { 0x20c99dfb13c90f48l,0xd6ac5273686ef263l,0xc6a50bdcfef64eebl,
-            0xcd87b28186fdfc32l },
-          0 },
-        /* 29 << 152 */
-        { { 0x2f0c49ac95861439l,0xcdcb051b2e36e38al,0x459474080ae20c0cl,
-            0x374baad2dddf0aabl },
-          { 0x291abc85d5d104a4l,0x0758001958a0657cl,0xd0f428e1a905ea13l,
-            0x12599ddcf7241dbfl },
-          0 },
-        /* 31 << 152 */
-        { { 0x16222ce81bc3c403l,0xbacc1508fc13ca02l,0xfa98db4d920ee8e9l,
-            0xe5fc39c4df12a359l },
-          { 0x4e8c9b90188733e8l,0x04283dd81394936cl,0x93b3db51cd130432l,
-            0x33bfe3163c93ce31l },
-          0 },
-        /* 33 << 152 */
-        { { 0xb48591e9840b1724l,0x1009559f5885ec6fl,0x45ee51121b077620l,
-            0x848f9800f1f4cc8al },
-          { 0x6ec1e0f74e97bceal,0x953bc23a98e80642l,0x9f0d1e8194ce7181l,
-            0xeb3e6b9700eec596l },
-          0 },
-        /* 34 << 152 */
-        { { 0x6d34b39bff7514dal,0x29ffe49825be3634l,0x63e56598f28c8b82l,
-            0x78b99133aab41bcel },
-          { 0x11febd5a52563180l,0xa3be94c5c356a8c0l,0x5e9b422e0d61f864l,
-            0x2bf4ca1278fd259el },
-          0 },
-        /* 35 << 152 */
-        { { 0x8f60e40266914514l,0x6d9e280fef178167l,0x2ff7aec9e2949a48l,
-            0x422389ce72d37511l },
-          { 0xe9b156f3307ac1d2l,0x1cb581a78518e79fl,0x56d43f302185cf82l,
-            0x8d46c5aade59562cl },
-          0 },
-        /* 36 << 152 */
-        { { 0x50fc0711745edc11l,0x9dd9ad7d3dc87558l,0xce6931fbb49d1e64l,
-            0x6c77a0a2c98bd0f9l },
-          { 0x62b9a6296baf7cb1l,0xcf065f91ccf72d22l,0x7203cce979639071l,
-            0x09ae4885f9cb732fl },
-          0 },
-        /* 37 << 152 */
-        { { 0xd007d682e4b35428l,0x80c162315bcdc0d6l,0xe55a86bd36fce9b2l,
-            0x16772edb969a87cfl },
-          { 0xff323a2d3f370c94l,0x8d3c8028bf3c1afcl,0x4e1591e73b0c3fafl,
-            0xfbd6475cb981ce83l },
-          0 },
-        /* 39 << 152 */
-        { { 0xcf414ae3315b2471l,0xf54abf8033168de6l,0x6883efc5df5cdb24l,
-            0x3eca788c8efe81acl },
-          { 0xdb58c6c778eeccadl,0x3c77939082fecfb7l,0x5736cdd9c9b513f3l,
-            0xab7e6ea57b02aaf2l },
-          0 },
-        /* 40 << 152 */
-        { { 0x5e7c3becee8314f3l,0x1c068aeddbea298fl,0x08d381f17c80acecl,
-            0x03b56be8e330495bl },
-          { 0xaeffb8f29222882dl,0x95ff38f6c4af8bf7l,0x50e32d351fc57d8cl,
-            0x6635be5217b444f0l },
-          0 },
-        /* 41 << 152 */
-        { { 0x2cec7ba64805d895l,0x4c8399870ac78e7cl,0x031ad6c7f79416c5l,
-            0x1b2f2621f1838d2fl },
-          { 0x60835eac91447f90l,0x59147af1f9bab5d9l,0x7a3005d6f393f175l,
-            0x8cf3c468c4120ba2l },
-          0 },
-        /* 43 << 152 */
-        { { 0xeccffc7d8a2c1f08l,0x308916d37e384bd4l,0x6b8c2ff55e366384l,
-            0xf4b2850d03e4747cl },
-          { 0xe839c569e96c1488l,0xa46ff7f956c9cb10l,0xd968c74c362fd172l,
-            0x2aa7fe4cad6bb601l },
-          0 },
-        /* 44 << 152 */
-        { { 0x04d15276a5177900l,0x4e1dbb47f6858752l,0x5b475622c615796cl,
-            0xa6fa0387691867bfl },
-          { 0xed7f5d562844c6d0l,0xc633cf9b03a2477dl,0xf6be5c402d3721d6l,
-            0xaf312eb7e9fd68e6l },
-          0 },
-        /* 45 << 152 */
-        { { 0xf3b8164eec04c847l,0xa305ca93fe65816cl,0xa65f9963c7e2ce52l,
-            0xc448005198882cfcl },
-          { 0x46a998df05c165bbl,0xc38f4edf9dfe1e98l,0xb96ec43f8739f77al,
-            0x10a23af9313b40bfl },
-          0 },
-        /* 46 << 152 */
-        { { 0xe476c3e3ee668e0cl,0xcec6a984478197c2l,0xc9fa1d68897147c1l,
-            0x4e6aec0ea6465793l },
-          { 0xedca9db76b219c3bl,0xa2cd57942e508d3bl,0x38b384663936e02al,
-            0x0b8d3b4ca54ce90fl },
-          0 },
-        /* 47 << 152 */
-        { { 0x66e06537af08e0fcl,0x70fe0f2a907f1a93l,0x8c25245285ec1647l,
-            0x0b8b2964d5560eddl },
-          { 0xda45a326f3ef8e14l,0xf3adf9a6abc3494bl,0xbbdd93c11eda0d92l,
-            0x1b5e12c609912773l },
-          0 },
-        /* 48 << 152 */
-        { { 0x242792d2e7417ce1l,0xff42bc71970ee7f5l,0x1ff4dc6d5c67a41el,
-            0x77709b7b20882a58l },
-          { 0x3554731dbe217f2cl,0x2af2a8cd5bb72177l,0x58eee769591dd059l,
-            0xbb2930c94bba6477l },
-          0 },
-        /* 49 << 152 */
-        { { 0x5d9d507551d01848l,0x53dadb405b600d1el,0x7ba5b4dc5cb0a9a3l,
-            0xdb85b04c6795e547l },
-          { 0x480e7443f0354843l,0xc7efe6e813012322l,0x479b674a2aeee1e6l,
-            0xf5481f19704f4ea3l },
-          0 },
-        /* 51 << 152 */
-        { { 0x76a38d6978c7816el,0xe020c87df84ec554l,0x99af2f78f9818010l,
-            0x31cf103d988136eal },
-          { 0x6b095a114816a5aal,0x5a4cd2a4eff0a4afl,0x543041a5892e5e04l,
-            0x460f94c30aab9ee1l },
-          0 },
-        /* 52 << 152 */
-        { { 0x863ee0477d930cfcl,0x4c262ad1396fd1f4l,0xf4765bc8039af7e1l,
-            0x2519834b5ba104f6l },
-          { 0x7cd61b4cd105f961l,0xa5415da5d63bca54l,0x778280a088a1f17cl,
-            0xc49689492329512cl },
-          0 },
-        /* 53 << 152 */
-        { { 0x282d92b48cd3948al,0x95d219dfe168205bl,0xf6111a6f87bf3abcl,
-            0x910f8ce655fee9f2l },
-          { 0xb6c806f74f71ac89l,0xd0cc300fb7235f73l,0xfe37ccb47d0d45bbl,
-            0x5b2445f6952f0eaal },
-          0 },
-        /* 55 << 152 */
-        { { 0x03870be447141962l,0x8b79033f4a2b3f7fl,0xb6983b5ed2e5e274l,
-            0x2a2f8018501ed99cl },
-          { 0x07a92eb9feb49656l,0x063f0a9e482e2972l,0x413be27a57435832l,
-            0x56363c5f6f9d3de1l },
-          0 },
-        /* 57 << 152 */
-        { { 0xd247153163b50214l,0x32b435eeb2b897del,0xc49f0b01b05df4del,
-            0x97b6aa40b7df9b91l },
-          { 0x58ff34ec8ec39d78l,0xab0889005e0114a3l,0x6872b4de4822b7b8l,
-            0x7614c0d0ab239073l },
-          0 },
-        /* 59 << 152 */
-        { { 0x81891d378aa5d80al,0xf48ca24292e45f2cl,0xba711b6c0d04904cl,
-            0x5992cda349f16ed6l },
-          { 0x18b9a739790593eel,0x8b98e84dc4ba16d1l,0xac55701cb7b81615l,
-            0xadb4533b15822291l },
-          0 },
-        /* 60 << 152 */
-        { { 0x6210db7181236c97l,0x74f7685b3ee0781fl,0x4df7da7ba3e41372l,
-            0x2aae38b1b1a1553el },
-          { 0x1688e222f6dd9d1bl,0x576954485b8b6487l,0x478d21274b2edeaal,
-            0xb2818fa51e85956al },
-          0 },
-        /* 61 << 152 */
-        { { 0xc0677533f255ba8el,0x2bdae2a1efa2aabel,0xf7aebbd4b086c8a6l,
-            0x148455d992cb1147l },
-          { 0xa084e8d715402565l,0x33f111a8fa41bf23l,0x4bc990d627ac189bl,
-            0x48dbe6569d505f76l },
-          0 },
-        /* 63 << 152 */
-        { { 0x59df7fab596766f3l,0x4cadcbfe604f26e4l,0x0cf199338a6af592l,
-            0x3af1ace287b826c1l },
-          { 0xf09a5b38ee60684el,0xa04cbeda4ed7c711l,0xdb28c42eb1731040l,
-            0x75fcc0ec2e6e6523l },
-          0 },
-        /* 64 << 152 */
-        { { 0x1e6adddaf176f2c0l,0x01ca4604e2572658l,0x0a404ded85342ffbl,
-            0x8cf60f96441838d6l },
-          { 0x9bbc691cc9071c4al,0xfd58874434442803l,0x97101c85809c0d81l,
-            0xa7fb754c8c456f7fl },
-          0 },
-        /* 65 << 152 */
-        { { 0x4374020072196f30l,0x59ed0dc0dcd6c935l,0x17d4ed8e5034161bl,
-            0x8abe3e13009e7170l },
-          { 0xe51c41c96c791456l,0xc671807704d72bb6l,0xd4309cf56bba424al,
-            0x6122b951d0ca4ceal },
-          0 },
-        /* 71 << 152 */
-        { { 0xdfdb2e9c4278982bl,0xf3a282b32d6a2a61l,0x5611650cd2f2b03cl,
-            0xa62c177f43f7f83al },
-          { 0x372310ab4c593d32l,0x2bb6903a2b570f9cl,0x2930da3df43af904l,
-            0x2bbd04aa2c8a5a7dl },
-          0 },
-        /* 77 << 152 */
-        { { 0x10c324c007e536del,0xc456836d377be1b4l,0x9a627d75d785af3fl,
-            0xde74559118b58b31l },
-          { 0xeac83ea60c47239al,0x35da24abbc02f670l,0x2d4abde0c3af6e63l,
-            0xac53acba5a7ebf1bl },
-          0 },
-        /* 83 << 152 */
-        { { 0x2b03ec2efd9a9f3el,0xc967cd2b9d898a09l,0xb24bcba8039dc4f6l,
-            0x0ea1d297061ada1el },
-          { 0x3a7a25fbc134b8bcl,0x846282d6f61cd312l,0xfa1de0d2e0d778d9l,
-            0xf75fad4ef09be264l },
-          0 },
-        /* 89 << 152 */
-        { { 0x7d35695bcf74afb3l,0x34d43d9f15bb36fbl,0x15f0b43960b45fbel,
-            0xb15db8d84f38ec06l },
-          { 0x93ce7d50f7da1406l,0x2db97edd9f076aaal,0x27ebb9aa354429dcl,
-            0xf97eb5c446ace469l },
-          0 },
-        /* 95 << 152 */
-        { { 0x758fa2312dcf498fl,0xaa8c14d15cf3853al,0x416f5dab097d786al,
-            0xceec00ef38f242a0l },
-          { 0x2f8b10b9d8b75ef2l,0xee64912b2281be6al,0xa883481aa382a51el,
-            0x9442300f61b16b8al },
-          0 },
-        /* 101 << 152 */
-        { { 0x80e7fbc4f4b171e1l,0xdd2246f5661564a4l,0xcf08d73cd00d4e54l,
-            0xf725f5389fca9a30l },
-          { 0xd9607358af20debel,0xa97c81e16f7d1cf2l,0x72794ae70dedfb2al,
-            0xc328cb93159ff29dl },
-          0 },
-        /* 107 << 152 */
-        { { 0xaf9491d6252f6d59l,0x6744d7518feda60dl,0xa485f8aa34c5c048l,
-            0x2ed794b4b50ea53bl },
-          { 0x0da82650db26c289l,0xed3ab4c50904af55l,0x425eda1176544463l,
-            0x917be5f48939b29bl },
-          0 },
-        /* 113 << 152 */
-        { { 0xa2e72d0f8e208e5dl,0x5a5e4344234a5fedl,0x6dcc56535005bee8l,
-            0x09d0c254854e2e04l },
-          { 0xade4bcdba82f0789l,0x5a3e3cd4ec460a91l,0x6b1a867be76695b2l,
-            0xd1eb9df0a28b9331l },
-          0 },
-        /* 116 << 152 */
-        { { 0x3f5cf5f678e62ddcl,0x2267c45407fd752bl,0x5e361b6b5e437bbel,
-            0x95c595018354e075l },
-          { 0xec725f85f2b254d9l,0x844b617d2cb52b4el,0xed8554f5cf425fb5l,
-            0xab67703e2af9f312l },
-          0 },
-        /* 119 << 152 */
-        { { 0x8dcc920005fb96bbl,0x29d2442470f84705l,0x540bb6e63f09628fl,
-            0x07f8b4de2a9c2359l },
-          { 0xb8e002d1957e41dcl,0x9a0fe82b9e683a3fl,0x996b1a5250e633fdl,
-            0x748a11e500c669cal },
-          0 },
-        /* 125 << 152 */
-        { { 0x0593a788581dfd6el,0x99f1164f64e1b329l,0x1142c44b1defddbbl,
-            0xbc95c9c7660b9036l },
-          { 0xf24b5a47079179ccl,0x6175b52c21f7033bl,0x8b5d84183bc2eec0l,
-            0xc1332c8272d12670l },
-          0 },
-    },
-    {
-        /* 0 << 160 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 160 */
-        { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l,
-            0x810ee252af7c9860l },
-          { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l,
-            0xd485717a92731745l },
-          0 },
-        /* 3 << 160 */
-        { { 0x6c8d0aa9b898fd52l,0x2fb38a57be9af1a7l,0xe1f2b9a93b4f03f8l,
-            0x2b1aad44c3f0cc6fl },
-          { 0x58b5332e7cf2c084l,0x1c57d96f0367d26dl,0x2297eabdfa6e4a8dl,
-            0x65a947ee4a0e2b6al },
-          0 },
-        /* 4 << 160 */
-        { { 0xaaafafb0285b9491l,0x01a0be881e4c705el,0xff1d4f5d2ad9caabl,
-            0x6e349a4ac37a233fl },
-          { 0xcf1c12464a1c6a16l,0xd99e6b6629383260l,0xea3d43665f6d5471l,
-            0x36974d04ff8cc89bl },
-          0 },
-        /* 5 << 160 */
-        { { 0xf535b616fdd5b854l,0x592549c85728719fl,0xe231468606921cadl,
-            0x98c8ce34311b1ef8l },
-          { 0x28b937e7e9090b36l,0x67fc3ab90bf7bbb7l,0x12337097a9d87974l,
-            0x3e5adca1f970e3fel },
-          0 },
-        /* 7 << 160 */
-        { { 0xcdcc68a7b3f85ff0l,0xacd21cdd1a888044l,0xb6719b2e05dbe894l,
-            0xfae1d3d88b8260d4l },
-          { 0xedfedece8a1c5d92l,0xbca01a94dc52077el,0xc085549c16dd13edl,
-            0xdc5c3bae495ebaadl },
-          0 },
-        /* 9 << 160 */
-        { { 0xcc17063fbe7b643al,0x7872e1c846085760l,0x86b0fffbb4214c9el,
-            0xb18bbc0e72bf3638l },
-          { 0x8b17de0c722591c9l,0x1edeab1948c29e0cl,0x9fbfd98ef4304f20l,
-            0x2d1dbb6b9c77ffb6l },
-          0 },
-        /* 10 << 160 */
-        { { 0xf53f2c658ead09f7l,0x1335e1d59780d14dl,0x69cc20e0cd1b66bcl,
-            0x9b670a37bbe0bfc8l },
-          { 0xce53dc8128efbeedl,0x0c74e77c8326a6e5l,0x3604e0d2b88e9a63l,
-            0xbab38fca13dc2248l },
-          0 },
-        /* 11 << 160 */
-        { { 0x255616d3c7141771l,0xa86691ab2f226b66l,0xda19fea4b3ca63a9l,
-            0xfc05dc42ae672f2bl },
-          { 0xa9c6e786718ba28fl,0x07b7995b9c66b984l,0x0f434f551b3702f2l,
-            0xd6f6212fda84eeffl },
-          0 },
-        /* 13 << 160 */
-        { { 0x4b0e7987b5b41d78l,0xea7df9074bf0c4f8l,0xb4d03560fab80ecdl,
-            0x6cf306f6fb1db7e5l },
-          { 0x0d59fb5689fd4773l,0xab254f4000f9be33l,0x18a09a9277352da4l,
-            0xf81862f5641ea3efl },
-          0 },
-        /* 15 << 160 */
-        { { 0xb59b01579f759d01l,0xa2923d2f7eae4fdel,0x18327757690ba8c0l,
-            0x4bf7e38b44f51443l },
-          { 0xb6812563b413fc26l,0xedb7d36379e53b36l,0x4fa585c4c389f66dl,
-            0x8e1adc3154bd3416l },
-          0 },
-        /* 16 << 160 */
-        { { 0xd3b3a13f1402b9d0l,0x573441c32c7bc863l,0x4b301ec4578c3e6el,
-            0xc26fc9c40adaf57el },
-          { 0x96e71bfd7493cea3l,0xd05d4b3f1af81456l,0xdaca2a8a6a8c608fl,
-            0x53ef07f60725b276l },
-          0 },
-        /* 17 << 160 */
-        { { 0x971e9eedd5098497l,0x97692be63077d8a7l,0xb57e02ad79625a8al,
-            0x5e3d20f6a688ecd5l },
-          { 0xa4431a28188f964dl,0xd4eb23bd5a11c1dbl,0xfcda853eadc7446fl,
-            0x9e2e98b593c94046l },
-          0 },
-        /* 19 << 160 */
-        { { 0x4a649b66eddaa4f1l,0x35a04f185e690c50l,0x1639bdcff908bc53l,
-            0xce6d525c121726e8l },
-          { 0x70f34948902b402cl,0x3a40c6950e290579l,0x7b0ed90f469a0085l,
-            0xecb979c60189c501l },
-          0 },
-        /* 21 << 160 */
-        { { 0x847e2bde5cee8d07l,0x1bed198cd3340037l,0x439ffb3ce41586e3l,
-            0x594980f1856f15b0l },
-          { 0x22c3b86c6e9307c6l,0xf8b3ee08876382dbl,0x850c628e628f3f30l,
-            0x22ec0acb51ee3659l },
-          0 },
-        /* 23 << 160 */
-        { { 0xa4052591efcef5a0l,0x82692a47106d55afl,0xdac3ea88e6ead453l,
-            0xaa1368fcf3dfd875l },
-          { 0x87bc688aa0c539eal,0x905e206040b1de3el,0x072240b8f1d52452l,
-            0x3ebf0644d57b6580l },
-          0 },
-        /* 25 << 160 */
-        { { 0x12109bcc07a0b2f8l,0x336f87d2ca23f14cl,0xb39ae282452a2ea2l,
-            0x8e085f5bab59a500l },
-          { 0xf7daeb69b63f015cl,0x44c555bcacb47b38l,0x96190454b623910al,
-            0x4b666e2255b41b70l },
-          0 },
-        /* 27 << 160 */
-        { { 0xf146914eb53419fdl,0xd2109b07493e88bfl,0x30bf9cbccc54bcd5l,
-            0xcf9ea59750e34a1fl },
-          { 0x70ade8a59588591dl,0xf668be676b41c269l,0x3497c58f78df2e6bl,
-            0x0fad05cc71042b56l },
-          0 },
-        /* 28 << 160 */
-        { { 0x27f536e049ce89e7l,0x18908539cc890cb5l,0x308909abd83c2aa1l,
-            0xecd3142b1ab73bd3l },
-          { 0x6a85bf59b3f5ab84l,0x3c320a68f2bea4c6l,0xad8dc5386da4541fl,
-            0xeaf34eb0b7c41186l },
-          0 },
-        /* 29 << 160 */
-        { { 0x709da836093aa5f6l,0x567a9becb4644edel,0xae02a46044466b0cl,
-            0xc80b237a407f1b3bl },
-          { 0x451df45ab4168a98l,0xdc9b40ef24a3f7c9l,0x23593ef32671341dl,
-            0x40f4533190b90faal },
-          0 },
-        /* 31 << 160 */
-        { { 0x7f97768e922f36e3l,0x936943f8491034a2l,0x72f6c17f21483753l,
-            0x5489fa0cb2918619l },
-          { 0x55b31aa59cc21a46l,0xde4cc71a8e54ab14l,0x942cb8be9eaff8b0l,
-            0xe38f6116d1755231l },
-          0 },
-        /* 33 << 160 */
-        { { 0xf0c0606a395b39abl,0x0efcbc699b5166a5l,0x85995e6895453d85l,
-            0xadc9a2920806ee5cl },
-          { 0xc3662e804928fe09l,0x2a2ddcc6969c87e7l,0xa02d7947111d319dl,
-            0xde23bcf12d20f66dl },
-          0 },
-        /* 34 << 160 */
-        { { 0xc47cb3395f6d4a09l,0x6b4f355cee52b826l,0x3d100f5df51b930al,
-            0xf4512fac9f668f69l },
-          { 0x546781d5206c4c74l,0xd021d4d4cb4d2e48l,0x494a54c2ca085c2dl,
-            0xf1dbaca4520850a8l },
-          0 },
-        /* 35 << 160 */
-        { { 0xb2d15b14a911cc2bl,0xab2dfaf7643e28eal,0xfccc9ed1f52c4c2dl,
-            0xfb4b1d4a09d8faa3l },
-          { 0x6fd72a9b7f5ce767l,0x0233c856a287e2b5l,0xd42135e05775ebb9l,
-            0xb3c9dada7376568bl },
-          0 },
-        /* 36 << 160 */
-        { { 0x63c79326490a1acal,0xcb64dd9c41526b02l,0xbb772591a2979258l,
-            0x3f58297048d97846l },
-          { 0xd66b70d17c213ba7l,0xc28febb5e8a0ced4l,0x6b911831c10338c1l,
-            0x0d54e389bf0126f3l },
-          0 },
-        /* 37 << 160 */
-        { { 0x5952996b5306af1bl,0x99f444f4354b67bel,0x6f670181633a2928l,
-            0x289023f0e9bdc4a6l },
-          { 0xcbed12148f7455a2l,0x501ace2f659a4858l,0x83ee678d5f8e1784l,
-            0x95c984587335c5bdl },
-          0 },
-        /* 39 << 160 */
-        { { 0x2e25a1f3e0233000l,0xed0028cd44fe8ba9l,0x447501a6021d43b3l,
-            0x4ec203906b4dffccl },
-          { 0x50642f9ad0169740l,0x9360003373cc58adl,0x825f1a82fe9cf9acl,
-            0x456194c653242bd6l },
-          0 },
-        /* 40 << 160 */
-        { { 0x40242efeb483689bl,0x2575d3f6513ac262l,0xf30037c80ca6db72l,
-            0xc9fcce8298864be2l },
-          { 0x84a112ff0149362dl,0x95e575821c4ae971l,0x1fa4b1a8945cf86cl,
-            0x4525a7340b024a2fl },
-          0 },
-        /* 41 << 160 */
-        { { 0x83205e8f5db5e2b1l,0x94e7a2621e311c12l,0xe1cac7333e37068fl,
-            0xe3f43f6d39965acfl },
-          { 0xd28db9e854d905bal,0x686f372a101f2162l,0x409cfe5d3d1b46d4l,
-            0x17648f1cbd0bb63al },
-          0 },
-        /* 43 << 160 */
-        { { 0xef83315b821f4ee4l,0xb90766998ba78b4dl,0xee6a15880fce5260l,
-            0x828f4a72d754affbl },
-          { 0x4650ec7daaae54d2l,0x3174301f1057efe9l,0x174e0683eb7704cel,
-            0xb7e6aeb357eb0b14l },
-          0 },
-        /* 44 << 160 */
-        { { 0xcaead1c2c905d85fl,0xe9d7f7900733ae57l,0x24c9a65cf07cdd94l,
-            0x7389359ca4b55931l },
-          { 0xf58709b7367e45f7l,0x1f203067cb7e7adcl,0x82444bffc7b72818l,
-            0x07303b35baac8033l },
-          0 },
-        /* 45 << 160 */
-        { { 0xd59528fb38a0dc96l,0x8179dc9088d0e857l,0x55e9ba039ed4b1afl,
-            0x8a2c0dc787b74cacl },
-          { 0xe8ca91aeef1c0006l,0x67f59ab2de0e15d4l,0xba0cddf86e6634d2l,
-            0x352803657b7ba591l },
-          0 },
-        /* 46 << 160 */
-        { { 0x1e1ee4e4d13b7ea1l,0xe6489b24e0e74180l,0xa5f2c6107e70ef70l,
-            0xa1655412bdd10894l },
-          { 0x555ebefb7af4194el,0x533c1c3c8e89bd9cl,0x735b9b5789895856l,
-            0x15fb3cd2567f5c15l },
-          0 },
-        /* 47 << 160 */
-        { { 0xef07bfedfb0986c7l,0xde138afe47c1659al,0x8b79c159a555e907l,
-            0x21d572f1125518bbl },
-          { 0x2005999ad320410cl,0x4167dc469484414bl,0x0cd965c34c6aaefdl,
-            0x2a1abc9a0e1d5e9dl },
-          0 },
-        /* 48 << 160 */
-        { { 0x057fed45526f09fdl,0xe8a4f10c8128240al,0x9332efc4ff2bfd8dl,
-            0x214e77a0bd35aa31l },
-          { 0x32896d7314faa40el,0x767867ec01e5f186l,0xc9adf8f117a1813el,
-            0xcb6cda7854741795l },
-          0 },
-        /* 49 << 160 */
-        { { 0xadfaf39b888dedf1l,0x4f8b178aab1750b9l,0x26418617ffe6b0eal,
-            0x01d1be82af04a59fl },
-          { 0x41584147e652db64l,0xf7775ac5727f9ea7l,0x58052a20e72ad8bbl,
-            0x5badf0dc6021160el },
-          0 },
-        /* 51 << 160 */
-        { { 0x8490ea99183de59dl,0xc95f72146f5c6f8cl,0x89b55d15df00c334l,
-            0x84386ad8a0ec36f7l },
-          { 0x24dadaefe4dc1ed1l,0xc606ba4c1e717227l,0x7e4756c0bbfa62eal,
-            0x3916cf14afc29cf3l },
-          0 },
-        /* 52 << 160 */
-        { { 0xb7b4d00101dae185l,0x45434e0b9b7a94bcl,0xf54339affbd8cb0bl,
-            0xdcc4569ee98ef49el },
-          { 0x7789318a09a51299l,0x81b4d206b2b025d8l,0xf64aa418fae85792l,
-            0x3e50258facd7baf7l },
-          0 },
-        /* 53 << 160 */
-        { { 0x4152c508492d91f3l,0x59d6cf9c678f9db4l,0xb0a8c966404608d1l,
-            0xdced55d0e3fed558l },
-          { 0x0914a3cb33a76188l,0x79df212423d35d46l,0x2322507fca13b364l,
-            0x0aed41d60078ab93l },
-          0 },
-        /* 55 << 160 */
-        { { 0x7acdaa7f6b2ebfc2l,0xb5ab1a9a80d9f67fl,0x53ba8173ff8aa8b0l,
-            0x9cd85cf874ca56a6l },
-          { 0xabac57f49c4fad81l,0x2325bb8521078995l,0xbac5e3a1b928a054l,
-            0x7219047a2394cc2al },
-          0 },
-        /* 57 << 160 */
-        { { 0xa33410d2aa75fd37l,0x821093affc0f1192l,0xe45e85ed155e39a9l,
-            0xd0e87cd12de67188l },
-          { 0xdeca97d965d43d87l,0x8c73826f9d2c99ecl,0x1bfe111e33237ddbl,
-            0xda32e865587bfb28l },
-          0 },
-        /* 59 << 160 */
-        { { 0xde456d92c89e9e4el,0xe45688a98e47f3cdl,0x3deacfca3bacbde0l,
-            0xdf9b32efc9683a70l },
-          { 0x749bc007e1691106l,0x788a05342a5154d7l,0x1a06baecf7c7b70dl,
-            0xb5b608eeae6ffc4cl },
-          0 },
-        /* 60 << 160 */
-        { { 0x4cd296df5579bea4l,0x10e35ac85ceedaf1l,0x04c4c5fde3bcc5b1l,
-            0x95f9ee8a89412cf9l },
-          { 0x2c9459ee82b6eb0fl,0x2e84576595c2aaddl,0x774a84aed327fcfel,
-            0xd8c937220368d476l },
-          0 },
-        /* 61 << 160 */
-        { { 0x39ebf947ccd25abbl,0x74e7a868cb49ebael,0x576ea108332e6147l,
-            0xcf3ba166150c1e5dl },
-          { 0xb5411fc3515c0e93l,0x51b15761f15c8a34l,0x362a4a3a0d213f38l,
-            0xf6f63c2e24e93aeal },
-          0 },
-        /* 63 << 160 */
-        { { 0x0cb3a2dcb78528d5l,0xa1888c18d585bb41l,0x210cca40de402a6el,
-            0x10c6339d9ed7c381l },
-          { 0xcd3558d561fe2a0cl,0xc97db05dad5140b1l,0x3366b028b21f8d11l,
-            0x878b09033e38be13l },
-          0 },
-        /* 64 << 160 */
-        { { 0x211cde10296c36efl,0x7ee8967282c4da77l,0xb617d270a57836dal,
-            0xf0cd9c319cb7560bl },
-          { 0x01fdcbf7e455fe90l,0x3fb53cbb7e7334f3l,0x781e2ea44e7de4ecl,
-            0x8adab3ad0b384fd0l },
-          0 },
-        /* 65 << 160 */
-        { { 0x081e505aa353ba05l,0x244ab34a288b86b1l,0x1155f06214e3a829l,
-            0x383300daf2118a6bl },
-          { 0xe8fc17cef27032b9l,0xed7f05c9c7bd2389l,0x78f70d14202f8a88l,
-            0x8a8310c0647b3f20l },
-          0 },
-        /* 71 << 160 */
-        { { 0xc80786e1a3633369l,0x496d55de9073f5b9l,0x10deeb6a89ae93cel,
-            0x6a2dd5c8b12e00c6l },
-          { 0xc25cd2f90c68e26dl,0x29d7ad8b53f0bb64l,0x2dd0d027d7fc9b00l,
-            0xad21e1f7ca9c4d5dl },
-          0 },
-        /* 77 << 160 */
-        { { 0xd45cb932d83465f3l,0x95830c0faf22fdbdl,0x41d830e007cd2a0al,
-            0x4a08500e3616e716l },
-          { 0x5931fc9f277755a5l,0x7d11680731006764l,0xa409a0ad1b3999aal,
-            0xec70368c9939d566l },
-          0 },
-        /* 83 << 160 */
-        { { 0x3905cb59f2030370l,0x7e9bdee56dcc8fd7l,0xb1b7b04e9806e06fl,
-            0xfbdadce22c73eb57l },
-          { 0xfb1ab2e98d5b2eb3l,0x58fbf2df7699338bl,0x81b1c54a63b5a032l,
-            0xefd1a1896a5d7ff4l },
-          0 },
-        /* 89 << 160 */
-        { { 0x0265189da1f769eal,0x22fa0bbbfdb5a502l,0xf69f0d1b21027534l,
-            0x64302b81f6066b99l },
-          { 0xdef85fc98a717e80l,0xe066166386879a3bl,0xe5489b347f95b22cl,
-            0x106dca9aa054a563l },
-          0 },
-        /* 95 << 160 */
-        { { 0xd624b4f4b4be9a77l,0x21a11ed77d50acb1l,0x707181f43d406e11l,
-            0x3f324d203ef158bcl },
-          { 0xb29a2a34aa8cc8del,0x482f4a15315db969l,0x42ce4fc7d9af272el,
-            0x784665b1f8f4cdc4l },
-          0 },
-        /* 101 << 160 */
-        { { 0x66ff7f73ab43a863l,0xa90be2cba77fd07el,0x84843997f76e5288l,
-            0x288c197f3cee129bl },
-          { 0x39acc080c0a060a6l,0x4c8e574bd24e27cal,0x1dd6170ffcd3d5e9l,
-            0x9736bb51f75e5150l },
-          0 },
-        /* 107 << 160 */
-        { { 0x2133810e6ba75716l,0x4debf728712886a8l,0x351e46a1f527d1f3l,
-            0x29709ae8e9591564l },
-          { 0x696163d3a3dc1780l,0xd5b7825ae02aadf3l,0x23579d7cd565ae68l,
-            0x105380124fa42cecl },
-          0 },
-        /* 113 << 160 */
-        { { 0x04eb554d13ffa704l,0x7441a62f2ed33d20l,0xaa926fa0b5b81324l,
-            0xb981bcb829836f61l },
-          { 0x313a78d4cc9a7a15l,0xff1242d11b3921d2l,0xc0053fd36a209d4dl,
-            0x95ac85caf7e92ca9l },
-          0 },
-        /* 116 << 160 */
-        { { 0x6d2a483d6f73c51el,0xa4cb2412ea0dc2ddl,0x50663c411eb917ffl,
-            0x3d3a74cfeade299el },
-          { 0x29b3990f4a7a9202l,0xa9bccf59a7b15c3dl,0x66a3ccdca5df9208l,
-            0x48027c1443f2f929l },
-          0 },
-        /* 119 << 160 */
-        { { 0xdf8a6f9673c3f6fbl,0xe4b1f0d98cc03220l,0x5ddacd618350480cl,
-            0x485c4fababdfb016l },
-          { 0xdc840628b4d424b7l,0x07d3a99c215b2359l,0xad3dc5af56dff52el,
-            0x5a3a6754973b6825l },
-          0 },
-        /* 125 << 160 */
-        { { 0xcfe231b83539a06dl,0xb36d1f72f46770ddl,0x126049747bb900d6l,
-            0x8d0990973fc31661l },
-          { 0x03b2749c920bc39el,0xf933d510b0486e23l,0x09cc958f0e9b0bb5l,
-            0x0b254dd1aa1e23abl },
-          0 },
-    },
-    {
-        /* 0 << 168 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 168 */
-        { { 0x263a2cfb9db3b381l,0x9c3a2deed4df0a4bl,0x728d06e97d04e61fl,
-            0x8b1adfbc42449325l },
-          { 0x6ec1d9397e053a1bl,0xee2be5c766daf707l,0x80ba1e14810ac7abl,
-            0xdd2ae778f530f174l },
-          0 },
-        /* 3 << 168 */
-        { { 0xadbaeb79b6828f36l,0x9d7a025801bd5b9el,0xeda01e0d1e844b0cl,
-            0x4b625175887edfc9l },
-          { 0x14109fdd9669b621l,0x88a2ca56f6f87b98l,0xfe2eb788170df6bcl,
-            0x0cea06f4ffa473f9l },
-          0 },
-        /* 4 << 168 */
-        { { 0x43ed81b5c4e83d33l,0xd9f358795efd488bl,0x164a620f9deb4d0fl,
-            0xc6927bdbac6a7394l },
-          { 0x45c28df79f9e0f03l,0x2868661efcd7e1a9l,0x7cf4e8d0ffa348f1l,
-            0x6bd4c284398538e0l },
-          0 },
-        /* 5 << 168 */
-        { { 0x2618a091289a8619l,0xef796e606671b173l,0x664e46e59090c632l,
-            0xa38062d41e66f8fbl },
-          { 0x6c744a200573274el,0xd07b67e4a9271394l,0x391223b26bdc0e20l,
-            0xbe2d93f1eb0a05a7l },
-          0 },
-        /* 7 << 168 */
-        { { 0x7efa14b84444896bl,0x64974d2ff94027fbl,0xefdcd0e8de84487dl,
-            0x8c45b2602b48989bl },
-          { 0xa8fcbbc2d8463487l,0xd1b2b3f73fbc476cl,0x21d005b7c8f443c0l,
-            0x518f2e6740c0139cl },
-          0 },
-        /* 9 << 168 */
-        { { 0xae51dca2a91f6791l,0x2abe41909baa9efcl,0xd9d2e2f4559c7ac1l,
-            0xe82f4b51fc9f773al },
-          { 0xa77130274073e81cl,0xc0276facfbb596fcl,0x1d819fc9a684f70cl,
-            0x29b47fddc9f7b1e0l },
-          0 },
-        /* 10 << 168 */
-        { { 0x358de103459b1940l,0xec881c595b013e93l,0x51574c9349532ad3l,
-            0x2db1d445b37b46del },
-          { 0xc6445b87df239fd8l,0xc718af75151d24eel,0xaea1c4a4f43c6259l,
-            0x40c0e5d770be02f7l },
-          0 },
-        /* 11 << 168 */
-        { { 0x6a4590f4721b33f2l,0x2124f1fbfedf04eal,0xf8e53cde9745efe7l,
-            0xe7e1043265f046d9l },
-          { 0xc3fca28ee4d0c7e6l,0x847e339a87253b1bl,0x9b5953483743e643l,
-            0xcb6a0a0b4fd12fc5l },
-          0 },
-        /* 13 << 168 */
-        { { 0xec1214eda714181dl,0x609ac13b6067b341l,0xff4b4c97a545df1fl,
-            0xa124050134d2076bl },
-          { 0x6efa0c231409ca97l,0x254cc1a820638c43l,0xd4e363afdcfb46cdl,
-            0x62c2adc303942a27l },
-          0 },
-        /* 15 << 168 */
-        { { 0x27b6a8ab3fd40e09l,0xe455842e77313ea9l,0x8b51d1e21f55988bl,
-            0x5716dd73062bbbfcl },
-          { 0x633c11e54e8bf3del,0x9a0e77b61b85be3bl,0x565107290911cca6l,
-            0x27e76495efa6590fl },
-          0 },
-        /* 16 << 168 */
-        { { 0xe4ac8b33070d3aabl,0x2643672b9a2cd5e5l,0x52eff79b1cfc9173l,
-            0x665ca49b90a7c13fl },
-          { 0x5a8dda59b3efb998l,0x8a5b922d052f1341l,0xae9ebbab3cf9a530l,
-            0x35986e7bf56da4d7l },
-          0 },
-        /* 17 << 168 */
-        { { 0x3a636b5cff3513ccl,0xbb0cf8ba3198f7ddl,0xb8d4052241f16f86l,
-            0x760575d8de13a7bfl },
-          { 0x36f74e169f7aa181l,0x163a3ecff509ed1cl,0x6aead61f3c40a491l,
-            0x158c95fcdfe8fcaal },
-          0 },
-        /* 19 << 168 */
-        { { 0x6b47accdd9eee96cl,0x0ca277fbe58cec37l,0x113fe413e702c42al,
-            0xdd1764eec47cbe51l },
-          { 0x041e7cde7b3ed739l,0x50cb74595ce9e1c0l,0x355685132925b212l,
-            0x7cff95c4001b081cl },
-          0 },
-        /* 21 << 168 */
-        { { 0x726f0973da50c991l,0x48afcd5b822d6ee2l,0xe5fc718b20fd7771l,
-            0xb9e8e77dfd0807a1l },
-          { 0x7f5e0f4499a7703dl,0x6972930e618e36f3l,0x2b7c77b823807bbel,
-            0xe5b82405cb27ff50l },
-          0 },
-        /* 23 << 168 */
-        { { 0x98cb1ae9255c0980l,0x4bd863812b4a739fl,0x5a5c31e11e4a45a1l,
-            0x1e5d55fe9cb0db2fl },
-          { 0x74661b068ff5cc29l,0x026b389f0eb8a4f4l,0x536b21a458848c24l,
-            0x2e5bf8ec81dc72b0l },
-          0 },
-        /* 25 << 168 */
-        { { 0x9f0af483d309cbe6l,0x5b020d8ae0bced4fl,0x606e986db38023e3l,
-            0xad8f2c9d1abc6933l },
-          { 0x19292e1de7400e93l,0xfe3e18a952be5e4dl,0xe8e9771d2e0680bfl,
-            0x8c5bec98c54db063l },
-          0 },
-        /* 27 << 168 */
-        { { 0x4c23f62a2c160dcdl,0x34e6c5e38f90eaefl,0x35865519a9a65d5al,
-            0x07c48aae8fd38a3dl },
-          { 0xb7e7aeda50068527l,0x2c09ef231c90936al,0x31ecfeb6e879324cl,
-            0xa0871f6bfb0ec938l },
-          0 },
-        /* 28 << 168 */
-        { { 0xb1f0fb68d84d835dl,0xc90caf39861dc1e6l,0x12e5b0467594f8d7l,
-            0x26897ae265012b92l },
-          { 0xbcf68a08a4d6755dl,0x403ee41c0991fbdal,0x733e343e3bbf17e8l,
-            0xd2c7980d679b3d65l },
-          0 },
-        /* 29 << 168 */
-        { { 0x33056232d2e11305l,0x966be492f3c07a6fl,0x6a8878ffbb15509dl,
-            0xff2211010a9b59a4l },
-          { 0x6c9f564aabe30129l,0xc6f2c940336e64cfl,0x0fe752628b0c8022l,
-            0xbe0267e96ae8db87l },
-          0 },
-        /* 31 << 168 */
-        { { 0x9d031369a5e829e5l,0xcbb4c6fc1607aa41l,0x75ac59a6241d84c1l,
-            0xc043f2bf8829e0eel },
-          { 0x82a38f758ea5e185l,0x8bda40b9d87cbd9fl,0x9e65e75e2d8fc601l,
-            0x3d515f74a35690b3l },
-          0 },
-        /* 33 << 168 */
-        { { 0xf6b5b2d0bc8fa5bcl,0x8a5ead67500c277bl,0x214625e6dfa08a5dl,
-            0x51fdfedc959cf047l },
-          { 0x6bc9430b289fca32l,0xe36ff0cf9d9bdc3fl,0x2fe187cb58ea0edel,
-            0xed66af205a900b3fl },
-          0 },
-        /* 34 << 168 */
-        { { 0x00e0968b5fa9f4d6l,0x2d4066ce37a362e7l,0xa99a9748bd07e772l,
-            0x710989c006a4f1d0l },
-          { 0xd5dedf35ce40cbd8l,0xab55c5f01743293dl,0x766f11448aa24e2cl,
-            0x94d874f8605fbcb4l },
-          0 },
-        /* 35 << 168 */
-        { { 0xa365f0e8a518001bl,0xee605eb69d04ef0fl,0x5a3915cdba8d4d25l,
-            0x44c0e1b8b5113472l },
-          { 0xcbb024e88b6740dcl,0x89087a53ee1d4f0cl,0xa88fa05c1fc4e372l,
-            0x8bf395cbaf8b3af2l },
-          0 },
-        /* 36 << 168 */
-        { { 0x1e71c9a1deb8568bl,0xa35daea080fb3d32l,0xe8b6f2662cf8fb81l,
-            0x6d51afe89490696al },
-          { 0x81beac6e51803a19l,0xe3d24b7f86219080l,0x727cfd9ddf6f463cl,
-            0x8c6865ca72284ee8l },
-          0 },
-        /* 37 << 168 */
-        { { 0x32c88b7db743f4efl,0x3793909be7d11dcel,0xd398f9222ff2ebe8l,
-            0x2c70ca44e5e49796l },
-          { 0xdf4d9929cb1131b1l,0x7826f29825888e79l,0x4d3a112cf1d8740al,
-            0x00384cb6270afa8bl },
-          0 },
-        /* 39 << 168 */
-        { { 0xbe7e990ff0d796a0l,0x5fc62478df0e8b02l,0x8aae8bf4030c00adl,
-            0x3d2db93b9004ba0fl },
-          { 0xe48c8a79d85d5ddcl,0xe907caa76bb07f34l,0x58db343aa39eaed5l,
-            0x0ea6e007adaf5724l },
-          0 },
-        /* 40 << 168 */
-        { { 0xe00df169d23233f3l,0x3e32279677cb637fl,0x1f897c0e1da0cf6cl,
-            0xa651f5d831d6bbddl },
-          { 0xdd61af191a230c76l,0xbd527272cdaa5e4al,0xca753636d0abcd7el,
-            0x78bdd37c370bd8dcl },
-          0 },
-        /* 41 << 168 */
-        { { 0xc23916c217cd93fel,0x65b97a4ddadce6e2l,0xe04ed4eb174e42f8l,
-            0x1491ccaabb21480al },
-          { 0x145a828023196332l,0x3c3862d7587b479al,0x9f4a88a301dcd0edl,
-            0x4da2b7ef3ea12f1fl },
-          0 },
-        /* 43 << 168 */
-        { { 0x71965cbfc3dd9b4dl,0xce23edbffc068a87l,0xb78d4725745b029bl,
-            0x74610713cefdd9bdl },
-          { 0x7116f75f1266bf52l,0x0204672218e49bb6l,0xdf43df9f3d6f19e3l,
-            0xef1bc7d0e685cb2fl },
-          0 },
-        /* 44 << 168 */
-        { { 0xcddb27c17078c432l,0xe1961b9cb77fedb7l,0x1edc2f5cc2290570l,
-            0x2c3fefca19cbd886l },
-          { 0xcf880a36c2af389al,0x96c610fdbda71ceal,0xf03977a932aa8463l,
-            0x8eb7763f8586d90al },
-          0 },
-        /* 45 << 168 */
-        { { 0x3f3424542a296e77l,0xc871868342837a35l,0x7dc710906a09c731l,
-            0x54778ffb51b816dbl },
-          { 0x6b33bfecaf06defdl,0xfe3c105f8592b70bl,0xf937fda461da6114l,
-            0x3c13e6514c266ad7l },
-          0 },
-        /* 46 << 168 */
-        { { 0xe363a829855938e8l,0x2eeb5d9e9de54b72l,0xbeb93b0e20ccfab9l,
-            0x3dffbb5f25e61a25l },
-          { 0x7f655e431acc093dl,0x0cb6cc3d3964ce61l,0x6ab283a1e5e9b460l,
-            0x55d787c5a1c7e72dl },
-          0 },
-        /* 47 << 168 */
-        { { 0x4d2efd47deadbf02l,0x11e80219ac459068l,0x810c762671f311f0l,
-            0xfa17ef8d4ab6ef53l },
-          { 0xaf47fd2593e43bffl,0x5cb5ff3f0be40632l,0x546871068ee61da3l,
-            0x7764196eb08afd0fl },
-          0 },
-        /* 48 << 168 */
-        { { 0x831ab3edf0290a8fl,0xcae81966cb47c387l,0xaad7dece184efb4fl,
-            0xdcfc53b34749110el },
-          { 0x6698f23c4cb632f9l,0xc42a1ad6b91f8067l,0xb116a81d6284180al,
-            0xebedf5f8e901326fl },
-          0 },
-        /* 49 << 168 */
-        { { 0xf2274c9f97e3e044l,0x4201852011d09fc9l,0x56a65f17d18e6e23l,
-            0x2ea61e2a352b683cl },
-          { 0x27d291bc575eaa94l,0x9e7bc721b8ff522dl,0x5f7268bfa7f04d6fl,
-            0x5868c73faba41748l },
-          0 },
-        /* 51 << 168 */
-        { { 0x1c52e63596e78cc4l,0x5385c8b20c06b4a8l,0xd84ddfdbb0e87d03l,
-            0xc49dfb66934bafadl },
-          { 0x7071e17059f70772l,0x3a073a843a1db56bl,0x034949033b8af190l,
-            0x7d882de3d32920f0l },
-          0 },
-        /* 52 << 168 */
-        { { 0x91633f0ab2cf8940l,0x72b0b1786f948f51l,0x2d28dc30782653c8l,
-            0x88829849db903a05l },
-          { 0xb8095d0c6a19d2bbl,0x4b9e7f0c86f782cbl,0x7af739882d907064l,
-            0xd12be0fe8b32643cl },
-          0 },
-        /* 53 << 168 */
-        { { 0x358ed23d0e165dc3l,0x3d47ce624e2378cel,0x7e2bb0b9feb8a087l,
-            0x3246e8aee29e10b9l },
-          { 0x459f4ec703ce2b4dl,0xe9b4ca1bbbc077cfl,0x2613b4f20e9940c1l,
-            0xfc598bb9047d1eb1l },
-          0 },
-        /* 55 << 168 */
-        { { 0x52fb0c9d7fc63668l,0x6886c9dd0c039cdel,0x602bd59955b22351l,
-            0xb00cab02360c7c13l },
-          { 0x8cb616bc81b69442l,0x41486700b55c3ceel,0x71093281f49ba278l,
-            0xad956d9c64a50710l },
-          0 },
-        /* 57 << 168 */
-        { { 0xbaca6591d4b66947l,0xb452ce9804460a8cl,0x6830d24643768f55l,
-            0xf4197ed87dff12dfl },
-          { 0x6521b472400dd0f7l,0x59f5ca8f4b1e7093l,0x6feff11b080338ael,
-            0x0ada31f6a29ca3c6l },
-          0 },
-        /* 59 << 168 */
-        { { 0x04e5dfe0d809c7bdl,0xd7b2580c8f1050abl,0x6d91ad78d8a4176fl,
-            0x0af556ee4e2e897cl },
-          { 0x162a8b73921de0acl,0x52ac9c227ea78400l,0xee2a4eeaefce2174l,
-            0xbe61844e6d637f79l },
-          0 },
-        /* 60 << 168 */
-        { { 0x0491f1bc789a283bl,0x72d3ac3d880836f4l,0xaa1c5ea388e5402dl,
-            0x1b192421d5cc473dl },
-          { 0x5c0b99989dc84cacl,0xb0a8482d9c6e75b8l,0x639961d03a191ce2l,
-            0xda3bc8656d837930l },
-          0 },
-        /* 61 << 168 */
-        { { 0xca990653056e6f8fl,0x84861c4164d133a7l,0x8b403276746abe40l,
-            0xb7b4d51aebf8e303l },
-          { 0x05b43211220a255dl,0xc997152c02419e6el,0x76ff47b6630c2feal,
-            0x50518677281fdadel },
-          0 },
-        /* 63 << 168 */
-        { { 0x6d2d99b7ea7b979bl,0xcd78cd74e6fb3bcdl,0x11e45a9e86cffbfel,
-            0x78a61cf4637024f6l },
-          { 0xd06bc8723d502295l,0xf1376854458cb288l,0xb9db26a1342f8586l,
-            0xf33effcf4beee09el },
-          0 },
-        /* 64 << 168 */
-        { { 0xd7e0c4cdb30cfb3al,0x6d09b8c16c9db4c8l,0x40ba1a4207c8d9dfl,
-            0x6fd495f71c52c66dl },
-          { 0xfb0e169f275264dal,0x80c2b746e57d8362l,0xedd987f749ad7222l,
-            0xfdc229af4398ec7bl },
-          0 },
-        /* 65 << 168 */
-        { { 0xfe81af4609418a51l,0xdbb60b836f18e3a5l,0x5e7a86ea4566ec9cl,
-            0xb76ff40f25093925l },
-          { 0x5fe6662c429c5554l,0xfc9ec35384e478cfl,0x73dbb5f3e8cfa761l,
-            0x031e506592f82709l },
-          0 },
-        /* 71 << 168 */
-        { { 0x108c736abd49f2e0l,0xe230f2417487dcc8l,0x073fc4f8f74d939cl,
-            0x98532487e9745bbel },
-          { 0x5208eb981714b10bl,0xec35d0510458725dl,0x35dbb60bf203f4b6l,
-            0x064299b27781ab38l },
-          0 },
-        /* 77 << 168 */
-        { { 0x43cc7bbc02d26929l,0xeb00a683162d9607l,0x2af152b8ed9fa224l,
-            0xf24e8bee12257f0cl },
-          { 0xdf065dd5d004b1cbl,0x6aa20bcf9f9908c6l,0x8e5e86b6941c593dl,
-            0x0e0034b398969717l },
-          0 },
-        /* 83 << 168 */
-        { { 0x5be62e155c43b8fcl,0xd9e0adfc3c445636l,0xc5141df0e0d78f48l,
-            0xd134bbed2c277716l },
-          { 0x79033a84598fe069l,0x6c704367b081614cl,0x55c45d66bf5bf772l,
-            0xf08744c57a444730l },
-          0 },
-        /* 89 << 168 */
-        { { 0x866752091422b528l,0xdb297411c3e028eel,0x1f5575b040e1c3ccl,
-            0x85367b84d333b04fl },
-          { 0x57864c86e9804aa9l,0xf13fa8e3439156dfl,0xa3b337e0464e0aecl,
-            0x0018dfd7f2ae382bl },
-          0 },
-        /* 95 << 168 */
-        { { 0xe93cece9cea132fcl,0x985542d8f74e867al,0x2a3d18a5cc8fcf87l,
-            0xa0561055479d0039l },
-          { 0x3513c7eaac4b3f9dl,0xc095967256477606l,0xa63960f330df8ad6l,
-            0x59ca8d53cc9ddcb3l },
-          0 },
-        /* 101 << 168 */
-        { { 0x6d8e942b2f208191l,0xd49a6d9453fe5457l,0x2b55e391003010bal,
-            0x3dd1fd9fdf4605ebl },
-          { 0xdc006a3358682886l,0x60a5e86c1bd9ac88l,0xc4bd320ed0cab8f2l,
-            0x7281e7cb7751855bl },
-          0 },
-        /* 107 << 168 */
-        { { 0x7d564222e1881e7al,0x59061a89db0673c2l,0x1f9d607213f27313l,
-            0x5b3b29368ff3aeb7l },
-          { 0x6cf2304ccf969f43l,0x8eff4a25e7f69ae5l,0xbaeb6411d17da4ffl,
-            0x666af0af9eea17ecl },
-          0 },
-        /* 113 << 168 */
-        { { 0x6c0b811697f4cd0bl,0xcd7825d40e4ea852l,0x80158fb0677fef3dl,
-            0x5bb1a3aaa10ee693l },
-          { 0xc5df66678066fc9bl,0x3200dc11f404d4a6l,0x58868950a8686d8el,
-            0xbdaaffb53770fabal },
-          0 },
-        /* 116 << 168 */
-        { { 0xba6a9f84660326f5l,0x61c1e44161bc3e88l,0xfbf992a0bde85cf8l,
-            0xe704dd1e6f8c8f5fl },
-          { 0x231caa0ab1d7d486l,0xd10616d8891cd571l,0x2ddada75c008833cl,
-            0x44337d6dad514c94l },
-          0 },
-        /* 119 << 168 */
-        { { 0xd48678b8f6933cf0l,0x7b4d623e0b739471l,0x4ad620287b216238l,
-            0xb4d4918959c4fabel },
-          { 0x8c2a1bdc296d42d5l,0x9235d0ec2fd3eb96l,0xfe271972f81c135bl,
-            0x82b5181741471e16l },
-          0 },
-        /* 125 << 168 */
-        { { 0xe9aa8ce4051f8e81l,0x14484af67cd1391fl,0x53a361dcafb1656el,
-            0x6ad8ba02f4d9d0cbl },
-          { 0xfb4385466c50a722l,0x2f1c5bbc7edb37f4l,0x8dc90ccb16e4b795l,
-            0xbcb32e1508127094l },
-          0 },
-    },
-    {
-        /* 0 << 176 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 176 */
-        { { 0xb81d783e979f3925l,0x1efd130aaf4c89a7l,0x525c2144fd1bf7fal,
-            0x4b2969041b265a9el },
-          { 0xed8e9634b9db65b6l,0x35c82e3203599d8al,0xdaa7a54f403563f3l,
-            0x9df088ad022c38abl },
-          0 },
-        /* 3 << 176 */
-        { { 0x9e93ba24f111661el,0xedced484b105eb04l,0x96dc9ba1f424b578l,
-            0xbf8f66b7e83e9069l },
-          { 0x872d4df4d7ed8216l,0xbf07f3778e2cbecfl,0x4281d89998e73754l,
-            0xfec85fbb8aab8708l },
-          0 },
-        /* 4 << 176 */
-        { { 0x13b5bf22765fa7d0l,0x59805bf01d6a5370l,0x67a5e29d4280db98l,
-            0x4f53916f776b1ce3l },
-          { 0x714ff61f33ddf626l,0x4206238ea085d103l,0x1c50d4b7e5809ee3l,
-            0x999f450d85f8eb1dl },
-          0 },
-        /* 5 << 176 */
-        { { 0x82eebe731a3a93bcl,0x42bbf465a21adc1al,0xc10b6fa4ef030efdl,
-            0x247aa4c787b097bbl },
-          { 0x8b8dc632f60c77dal,0x6ffbc26ac223523el,0xa4f6ff11344579cfl,
-            0x5825653c980250f6l },
-          0 },
-        /* 7 << 176 */
-        { { 0xeda6c595d314e7bcl,0x2ee7464b467899edl,0x1cef423c0a1ed5d3l,
-            0x217e76ea69cc7613l },
-          { 0x27ccce1fe7cda917l,0x12d8016b8a893f16l,0xbcd6de849fc74f6bl,
-            0xfa5817e2f3144e61l },
-          0 },
-        /* 9 << 176 */
-        { { 0xc0b48d4e49ccd6d7l,0xff8fb02c88bd5580l,0xc75235e907d473b2l,
-            0x4fab1ac5a2188af3l },
-          { 0x030fa3bc97576ec0l,0xe8c946e80b7e7d2fl,0x40a5c9cc70305600l,
-            0x6d8260a9c8b013b4l },
-          0 },
-        /* 10 << 176 */
-        { { 0xe6c51073615cd9e4l,0x498ec047f1243c06l,0x3e5a8809b17b3d8cl,
-            0x5cd99e610cc565f1l },
-          { 0x81e312df7851dafel,0xf156f5baa79061e2l,0x80d62b71880c590el,
-            0xbec9746f0a39faa1l },
-          0 },
-        /* 11 << 176 */
-        { { 0x2b09d2c3cfdcf7ddl,0x41a9fce3723fcab4l,0x73d905f707f57ca3l,
-            0x080f9fb1ac8e1555l },
-          { 0x7c088e849ba7a531l,0x07d35586ed9a147fl,0x602846abaf48c336l,
-            0x7320fd320ccf0e79l },
-          0 },
-        /* 13 << 176 */
-        { { 0x92eb40907f8f875dl,0x9c9d754e56c26bbfl,0x158cea618110bbe7l,
-            0x62a6b802745f91eal },
-          { 0xa79c41aac6e7394bl,0x445b6a83ad57ef10l,0x0c5277eb6ea6f40cl,
-            0x319fe96b88633365l },
-          0 },
-        /* 15 << 176 */
-        { { 0x77f84203d39b8c34l,0xed8b1be63125eddbl,0x5bbf2441f6e39dc5l,
-            0xb00f6ee66a5d678al },
-          { 0xba456ecf57d0ea99l,0xdcae0f5817e06c43l,0x01643de40f5b4baal,
-            0x2c324341d161b9bel },
-          0 },
-        /* 16 << 176 */
-        { { 0x949c9976e1337c26l,0x6faadebdd73d68e5l,0x9e158614f1b768d9l,
-            0x22dfa5579cc4f069l },
-          { 0xccd6da17be93c6d6l,0x24866c61a504f5b9l,0x2121353c8d694da1l,
-            0x1c6ca5800140b8c6l },
-          0 },
-        /* 17 << 176 */
-        { { 0x4e77c5575b45afb4l,0xe9ded649efb8912dl,0x7ec9bbf542f6e557l,
-            0x2570dfff62671f00l },
-          { 0x2b3bfb7888e084bdl,0xa024b238f37fe5b4l,0x44e7dc0495649aeel,
-            0x498ca2555e7ec1d8l },
-          0 },
-        /* 19 << 176 */
-        { { 0x2e44d22526a1fc90l,0x0d6d10d24d70705dl,0xd94b6b10d70c45f4l,
-            0x0f201022b216c079l },
-          { 0xcec966c5658fde41l,0xa8d2bc7d7e27601dl,0xbfcce3e1ff230be7l,
-            0x3394ff6b0033ffb5l },
-          0 },
-        /* 21 << 176 */
-        { { 0x05d99be8b9c20cdal,0x89f7aad5d5cd0c98l,0x7ef936fe5bb94183l,
-            0x92ca0753b05cd7f2l },
-          { 0x9d65db1174a1e035l,0x02628cc813eaea92l,0xf2d9e24249e4fbf2l,
-            0x94fdfd9be384f8b7l },
-          0 },
-        /* 23 << 176 */
-        { { 0x29882d7c98379d44l,0xd000bdfb509edc8al,0xc6f95979e66fe464l,
-            0x504a6115fa61bde0l },
-          { 0x56b3b871effea31al,0x2d3de26df0c21a54l,0x21dbff31834753bfl,
-            0xe67ecf4969269d86l },
-          0 },
-        /* 25 << 176 */
-        { { 0xed29a56da16d4b34l,0x7fba9d09dca21c4fl,0x66d7ac006d8de486l,
-            0x6006198773a2a5e1l },
-          { 0x8b400f869da28ff0l,0x3133f70843c4599cl,0x9911c9b8ee28cb0dl,
-            0xcd7e28748e0af61dl },
-          0 },
-        /* 27 << 176 */
-        { { 0x6a7bb6a93b5bdb83l,0x08da65c0a4a72318l,0xc58d22aa63eb065fl,
-            0x1717596c1b15d685l },
-          { 0x112df0d0b266d88bl,0xf688ae975941945al,0x487386e37c292cacl,
-            0x42f3b50d57d6985cl },
-          0 },
-        /* 28 << 176 */
-        { { 0x69e3be0427596893l,0xb6bb02a645bf452bl,0x0875c11af4c698c8l,
-            0x6652b5c7bece3794l },
-          { 0x7b3755fd4f5c0499l,0x6ea16558b5532b38l,0xd1c69889a2e96ef7l,
-            0x9c773c3a61ed8f48l },
-          0 },
-        /* 29 << 176 */
-        { { 0x5a304ada8545d185l,0x82ae44ea738bb8cbl,0x628a35e3df87e10el,
-            0xd3624f3da15b9fe3l },
-          { 0xcc44209b14be4254l,0x7d0efcbcbdbc2ea5l,0x1f60336204c37bbel,
-            0x21f363f556a5852cl },
-          0 },
-        /* 31 << 176 */
-        { { 0x81262e4225346689l,0x716da290b07c7004l,0x35f911eab7950ee3l,
-            0x6fd72969261d21b5l },
-          { 0x5238980308b640d3l,0x5b0026ee887f12a1l,0x20e21660742e9311l,
-            0x0ef6d5415ff77ff7l },
-          0 },
-        /* 33 << 176 */
-        { { 0x64aa0874925dd0b0l,0x5ffd503851c474c6l,0x4478c72c8ebd4157l,
-            0xb98694cb8c8375e2l },
-          { 0xeda4edeecd8e208cl,0xf98a053d2c0670a6l,0x564bd3057f346b9dl,
-            0xafbbf3e94c318fddl },
-          0 },
-        /* 34 << 176 */
-        { { 0x8a03410aa96c4685l,0xef1b6b16a978a31bl,0x44738a3b629df6cfl,
-            0xa1dc65da807713e9l },
-          { 0x569cc7884c373442l,0x1f30a2464965fb52l,0x56822f1677ff5e2el,
-            0x63f18812e303748bl },
-          0 },
-        /* 35 << 176 */
-        { { 0x2abdc403dd0983ecl,0xec0c08c7f365c6f5l,0xe555083fbdb66b8bl,
-            0x593685bc4e8973ffl },
-          { 0x737df3f920e9c705l,0x00c7bcc309c31a5al,0x5f1d23e2efdcb34dl,
-            0x79d9b382470f7949l },
-          0 },
-        /* 36 << 176 */
-        { { 0x44a315645fd2eb1dl,0x4e7397263fdd1356l,0x9b96735463200efel,
-            0xcb70402e520bbb6al },
-          { 0xcbc90d7e693d2642l,0x6fb00064bc9b4002l,0x95f2eab3d96f7150l,
-            0xb1619e3fe035f47al },
-          0 },
-        /* 37 << 176 */
-        { { 0xd22d6073d1561bb7l,0x40666e4ba9928683l,0x90654dab8ab3f9b1l,
-            0x7625c507b8773421l },
-          { 0x288f28220ca88cd2l,0xbb88114ed8d005c1l,0xbeec2b0af603a11bl,
-            0x8fdda60325f7949el },
-          0 },
-        /* 39 << 176 */
-        { { 0x6503632d6ee4f1d0l,0xd5449747ea394840l,0xd696167a8abe13a1l,
-            0xc080f76e609ebaa9l },
-          { 0x181acf0c10aa70d6l,0x70614461291e5e50l,0x7ade8e84b9f0c0a3l,
-            0xef1de9f2cb11b41el },
-          0 },
-        /* 40 << 176 */
-        { { 0x2d5c3c848e592413l,0x727022961832ba2cl,0x22979b51596c6321l,
-            0x738f31cb5a04db64l },
-          { 0x0bdaa6ca98f84ee5l,0x4e9e827c15e21eeel,0x4c59dbcc3ea632e0l,
-            0xed3404db5bc6f027l },
-          0 },
-        /* 41 << 176 */
-        { { 0x2841f05cfbaf8b26l,0xac9830db5b243770l,0xde3ab1707787f324l,
-            0x1ee12efe079209bcl },
-          { 0x2d3fd62d5bcf6e3cl,0x8a680655d60b0582l,0xdafc5061bc2b64a1l,
-            0xe0d91e7526a88788l },
-          0 },
-        /* 43 << 176 */
-        { { 0x2d49c685426b1b1el,0x6c2149caeabb02f7l,0xa4697d7fde11984fl,
-            0xa0e32fb3ed3c8707l },
-          { 0xb783e825f4ca12dal,0xb2666e2448770a50l,0x82d47f478660e923l,
-            0x6e36cd71fb4a984fl },
-          0 },
-        /* 44 << 176 */
-        { { 0x3295a8ea43c66b92l,0x99387af6ac5d19d4l,0x545f9b1b8e9d2090l,
-            0x138b1c4c2660f530l },
-          { 0xbfb05fd2ff872627l,0xb6614b0f4c3bc45cl,0x13defece62ca0fb0l,
-            0x82ddae134fededd8l },
-          0 },
-        /* 45 << 176 */
-        { { 0x5a34499b871c4cbbl,0x3ab0e69a2eb6084bl,0xa8d0160025ef7755l,
-            0x5db8f611d9e70f5dl },
-          { 0x63f9eb9a7afa95d7l,0x328b97f9706d7964l,0x8bcf9a0f4b71dfcal,
-            0x53d4c3042a5c7934l },
-          0 },
-        /* 46 << 176 */
-        { { 0x0c87dd3a8768d9aal,0x201ce5a082f6a55fl,0xa3de6f3049ca4602l,
-            0x36f421422aeb5f17l },
-          { 0x5c9962399817b77al,0x2584a10ae8d165acl,0x80f683d0c726f4aal,
-            0x524307502dcdfa48l },
-          0 },
-        /* 47 << 176 */
-        { { 0x0c04399f94683df2l,0x0978e9d4e954838dl,0x01faa5e8cf4a7a7bl,
-            0x92f6e6a90dae61cfl },
-          { 0x0c0f1293373dc957l,0x8320178fd8cc6b67l,0x4af977ed4b6444f2l,
-            0xd8c9a401ad8e5f84l },
-          0 },
-        /* 48 << 176 */
-        { { 0xbd5660ed9aed9f40l,0x70ca6ad1532a8c99l,0xc4978bfb95c371eal,
-            0xe5464d0d7003109dl },
-          { 0x1af32fdfd9e535efl,0xabf57ea798c9185bl,0xed7a741712b42488l,
-            0x8e0296a7e97286fal },
-          0 },
-        /* 49 << 176 */
-        { { 0x79ee35ac16fca804l,0x8f16e6165f59782el,0x8fbef1011737694el,
-            0xb34b7625462be08bl },
-          { 0x7e63e1b016e75c91l,0xb6a18edd2d23728dl,0xcf761a1e7f299ab6l,
-            0x796dcdebf16c770el },
-          0 },
-        /* 51 << 176 */
-        { { 0x47354f22308ee4afl,0x96959a538ecd6f4bl,0xf60b5f104055cbd2l,
-            0x04b1c9599bd86095l },
-          { 0x26accd8486008564l,0x46b2fe0478f31ea7l,0x5500dbf72dd76f23l,
-            0x36bcdf584c496c6fl },
-          0 },
-        /* 52 << 176 */
-        { { 0x8836cd431527d7cel,0x1f236623187a50eal,0x6470c0ae847221f0l,
-            0xc61f86b47e449110l },
-          { 0x7cc9cc20fa9fcec1l,0xa394903019134349l,0xafe5a08ff53ab467l,
-            0x9caba02301ed2919l },
-          0 },
-        /* 53 << 176 */
-        { { 0xffecbdce406abf1el,0x0ef4bcd73ae340d4l,0x7e37bae0e19d5613l,
-            0xe191669be4c6e97al },
-          { 0x9fafe59797292db7l,0xab7ef3713172d716l,0x9f0fff330ce3b533l,
-            0xca94ff8f932dd8cfl },
-          0 },
-        /* 55 << 176 */
-        { { 0x659c8b5d78aea69el,0xdde7ab46476a8fb9l,0x26bfe303bd01b5e6l,
-            0xf3dfb08a726a937cl },
-          { 0xe7a591fa0a263670l,0xe872c3f8f97434a0l,0x4881a82e2e0f2c21l,
-            0x17624e48788ef958l },
-          0 },
-        /* 57 << 176 */
-        { { 0xd526d66da7222e5bl,0xd33bb78efeb00e25l,0x9a7d670b932c8d08l,
-            0xea31e5273cee093fl },
-          { 0x55cc091bd04b7a43l,0x12b08d6dd01a123dl,0x1d98a6467fb0e7bal,
-            0xdabb09483535fd0dl },
-          0 },
-        /* 59 << 176 */
-        { { 0x2862314d08b69b19l,0x9cf302e191effcfal,0x43bdc8462ead917al,
-            0x21b238bbf94b3d8fl },
-          { 0xa3736160e2f465d3l,0x4d7fb6818541e255l,0x46fa089a23551edcl,
-            0xf7c41d17c1fefa8cl },
-          0 },
-        /* 60 << 176 */
-        { { 0x8ed0807fed113000l,0x8e1672d04c691484l,0x33a13ab31ee86ca0l,
-            0x9df0d9573bcaee4fl },
-          { 0x0cf0c638ef0dfb71l,0x1e0fe22ac2c9510al,0x43f506716fcc6a21l,
-            0xccb58404cec03a94l },
-          0 },
-        /* 61 << 176 */
-        { { 0x59547e37fd0936c1l,0x81e0517df45140b1l,0xcc6ccd89ed49e3fcl,
-            0xc2fa23eff3b897del },
-          { 0x149511ef2050c80al,0xf66bea6b3140b833l,0xbbe1401e2786d723l,
-            0x0aeb549c887509bcl },
-          0 },
-        /* 63 << 176 */
-        { { 0xf938e85060f5867al,0x806e1fff72429adcl,0x5ff7962a45f43b52l,
-            0xd8375ab6b2bbb403l },
-          { 0x00d5819b21b287fcl,0x15c7190ebae37d58l,0x075ce5ce05fcfb07l,
-            0x76368d06dbc003cbl },
-          0 },
-        /* 64 << 176 */
-        { { 0x01079383171b445fl,0x9bcf21e38131ad4cl,0x8cdfe205c93987e8l,
-            0xe63f4152c92e8c8fl },
-          { 0x729462a930add43dl,0x62ebb143c980f05al,0x4f3954e53b06e968l,
-            0xfe1d75ad242cf6b1l },
-          0 },
-        /* 65 << 176 */
-        { { 0x1cf508197630655el,0x9b4685c408d417f5l,0x6ea942619b049259l,
-            0x31c29b54fe73b755l },
-          { 0x3d2872a1f1f2af17l,0xbcd1139956bcbc4bl,0x4d14f59890d7a85cl,
-            0xd2c46040dbcbe998l },
-          0 },
-        /* 71 << 176 */
-        { { 0x3c8a06ca9792c42al,0x92535628602460ddl,0xa95e13f2ddd4c676l,
-            0xe823841d3b20d463l },
-          { 0x0248605bbfad6051l,0x82985dd61af51233l,0x3d243a5cdef7d742l,
-            0x0a88ce55ff6aa911l },
-          0 },
-        /* 77 << 176 */
-        { { 0xcf5b5962449aec98l,0x40322a6531a41389l,0xcd15606fd72c0527l,
-            0xfe91eac7b90d65a0l },
-          { 0xcd32415487636360l,0x82f2c7bdfc653a6fl,0xd04d138ae315ce7cl,
-            0x40ebfd5e78118dbcl },
-          0 },
-        /* 83 << 176 */
-        { { 0x0f9ea6ae4144660fl,0x02345c6513279b25l,0x139497b65c7671cbl,
-            0x7259f14b2ebed1d5l },
-          { 0xa1e5d98ce9b29988l,0xaed0efcd8df73ac8l,0x88339f073b81a77cl,
-            0x28f2bbca7109c8a6l },
-          0 },
-        /* 89 << 176 */
-        { { 0xa264f99d811472ddl,0x0e7eae0afc07a80cl,0x77f264d4a683cdc6l,
-            0x0512df49d053c668l },
-          { 0x2b4dfbade61dea15l,0x83de61acfd74890al,0xd2552bab32d41182l,
-            0x1fb9411435924e6al },
-          0 },
-        /* 95 << 176 */
-        { { 0x85efe53ade23c988l,0x89d41dbbf897f91bl,0x1357f91e7873fa8dl,
-            0x7a6ec2e3718d911cl },
-          { 0xf9e4f92e8f209a01l,0x4ffb96a70fdd67f3l,0x4c81a787f83dde1cl,
-            0x0d68fce15e163b60l },
-          0 },
-        /* 101 << 176 */
-        { { 0xbc79b4b26ab6da9dl,0xb4be5c278bb005f1l,0x63624530cd3b280bl,
-            0x543142f04e880026l },
-          { 0xbf7fb14cad90ddbfl,0xfe456e8a3966732dl,0x85499fb987ce35e9l,
-            0x8af09e6b24f1305dl },
-          0 },
-        /* 107 << 176 */
-        { { 0x5fc563ec16dc2b4bl,0xfe5631b25d0e535fl,0xbf4c489f9a93e36cl,
-            0x56badff1da2a07c4l },
-          { 0x72ac6b77fb7c5595l,0x4b25b9428e6645d9l,0xeeae127251f0657el,
-            0x30779ca51abeb76bl },
-          0 },
-        /* 113 << 176 */
-        { { 0x3d602ef5d909f43dl,0x2b2951a6bb347c79l,0x44903bfaa0d88896l,
-            0xd4ab20e8684c104fl },
-          { 0x55f70b4dd9b7e626l,0x084b3ee646a5f9ecl,0x1799cbe3da4ae81al,
-            0xc7cfac937fd6b80fl },
-          0 },
-        /* 116 << 176 */
-        { { 0x45647911ca20c525l,0x78f83186004706abl,0x5596377d97510538l,
-            0x047863defe041f8cl },
-          { 0xaea784896ec82367l,0x9d4eac2601eee8fcl,0xb32728f19b57d9dbl,
-            0x60a158f5313c0f65l },
-          0 },
-        /* 119 << 176 */
-        { { 0xf78caf129754377bl,0xa7fce16b6966f0c4l,0xfea937555a54a2b7l,
-            0x52d7f79b7cdfe951l },
-          { 0x3e14b92e94b1dac0l,0x363f2e5af168b73bl,0xcc0e9dcb6436a8c2l,
-            0x2dbece4bb52cbd27l },
-          0 },
-        /* 125 << 176 */
-        { { 0x7e7907ed8df38ffel,0xa68ec827e24e8a24l,0x5093a97e5f168732l,
-            0xa9ffea2f39ebb6dbl },
-          { 0x89e02c12284276d4l,0xc1179e3b3f9502d6l,0x01becb51d8f69eb6l,
-            0x86eee2935eb1c73cl },
-          0 },
-    },
-    {
-        /* 0 << 184 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 184 */
-        { { 0xf3b7963f4c830320l,0x842c7aa0903203e3l,0xaf22ca0ae7327afbl,
-            0x38e13092967609b6l },
-          { 0x73b8fb62757558f1l,0x3cc3e831f7eca8c1l,0xe4174474f6331627l,
-            0xa77989cac3c40234l },
-          0 },
-        /* 3 << 184 */
-        { { 0xb32cb8b0b796d219l,0xc3e95f4f34741dd9l,0x8721212568edf6f5l,
-            0x7a03aee4a2b9cb8el },
-          { 0x0cd3c376f53a89aal,0x0d8af9b1948a28dcl,0xcf86a3f4902ab04fl,
-            0x8aacb62a7f42002dl },
-          0 },
-        /* 4 << 184 */
-        { { 0xfd8e139f8f5fcda8l,0xf3e558c4bdee5bfdl,0xd76cbaf4e33f9f77l,
-            0x3a4c97a471771969l },
-          { 0xda27e84bf6dce6a7l,0xff373d9613e6c2d1l,0xf115193cd759a6e9l,
-            0x3f9b702563d2262cl },
-          0 },
-        /* 5 << 184 */
-        { { 0x9cb0ae6c252bd479l,0x05e0f88a12b5848fl,0x78f6d2b2a5c97663l,
-            0x6f6e149bc162225cl },
-          { 0xe602235cde601a89l,0xd17bbe98f373be1fl,0xcaf49a5ba8471827l,
-            0x7e1a0a8518aaa116l },
-          0 },
-        /* 7 << 184 */
-        { { 0x8b1e572235e6fc06l,0x3477728f0b3e13d5l,0x150c294daa8a7372l,
-            0xc0291d433bfa528al },
-          { 0xc6c8bc67cec5a196l,0xdeeb31e45c2e8a7cl,0xba93e244fb6e1c51l,
-            0xb9f8b71b2e28e156l },
-          0 },
-        /* 9 << 184 */
-        { { 0x343ac0a3ee9523f0l,0xbb75eab2975ea978l,0x1bccf332107387f4l,
-            0x790f92599ab0062el },
-          { 0xf1a363ad1e4f6a5fl,0x06e08b8462519a50l,0x609151877265f1eel,
-            0x6a80ca3493ae985el },
-          0 },
-        /* 10 << 184 */
-        { { 0xa3f4f521e447f2c4l,0x81b8da7a604291f0l,0xd680bc467d5926del,
-            0x84f21fd534a1202fl },
-          { 0x1d1e31814e9df3d8l,0x1ca4861a39ab8d34l,0x809ddeec5b19aa4al,
-            0x59f72f7e4d329366l },
-          0 },
-        /* 11 << 184 */
-        { { 0x2dfb9e08be0f4492l,0x3ff0da03e9d5e517l,0x03dbe9a1f79466a8l,
-            0x0b87bcd015ea9932l },
-          { 0xeb64fc83ab1f58abl,0x6d9598da817edc8al,0x699cff661d3b67e5l,
-            0x645c0f2992635853l },
-          0 },
-        /* 13 << 184 */
-        { { 0xd50e57c7d7fe71f3l,0x15342190bc97ce38l,0x51bda2de4df07b63l,
-            0xba12aeae200eb87dl },
-          { 0xabe135d2a9b4f8f6l,0x04619d65fad6d99cl,0x4a6683a77994937cl,
-            0x7a778c8b6f94f09al },
-          0 },
-        /* 15 << 184 */
-        { { 0x8dd1fb83425c6559l,0x7fc00ee60af06fdal,0xe98c922533d956dfl,
-            0x0f1ef3354fbdc8a2l },
-          { 0x2abb5145b79b8ea2l,0x40fd2945bdbff288l,0x6a814ac4d7185db7l,
-            0xc4329d6fc084609al },
-          0 },
-        /* 16 << 184 */
-        { { 0x511053e453544774l,0x834d0ecc3adba2bcl,0x4215d7f7bae371f5l,
-            0xfcfd57bf6c8663bcl },
-          { 0xded2383dd6901b1dl,0x3b49fbb4b5587dc3l,0xfd44a08d07625f62l,
-            0x3ee4d65b9de9b762l },
-          0 },
-        /* 17 << 184 */
-        { { 0x55ef9d3dcc26e8b0l,0xf869c827729b707al,0xdbbf450d8c47e00cl,
-            0x73d546ea60972ed7l },
-          { 0x9563e11f0dcd6821l,0xe48e1af57d80de7fl,0xbe7139b49057838dl,
-            0xf3f0ad4d7e5ca535l },
-          0 },
-        /* 19 << 184 */
-        { { 0xac66d1d49f8f8cc2l,0x43fe5c154ef18941l,0xbae77b6ddc30fcbfl,
-            0xdb95ea7d945723b7l },
-          { 0x43298e2bda8097e2l,0x8004167baf22ea9bl,0x9cf5974196a83d57l,
-            0xb35c9aba3cf67d5el },
-          0 },
-        /* 21 << 184 */
-        { { 0x0569a48df766f793l,0x6b4c7b16706b3442l,0xcc97754416ff41e0l,
-            0x800c56e31fee2e86l },
-          { 0xce0c3d0fcdf93450l,0x6ec3703582f35916l,0x902520d5bbc11e68l,
-            0x7e2b988505078223l },
-          0 },
-        /* 23 << 184 */
-        { { 0xb30d1769101da00bl,0xb26872d5113cfdb6l,0x7b0491da44e48db5l,
-            0x810e73bb2013f8c9l },
-          { 0xc86e579a570f0b59l,0xf34107e37a918f34l,0x49286d00277473f1l,
-            0x74423f5abc85905dl },
-          0 },
-        /* 25 << 184 */
-        { { 0x90d7417879de6b48l,0xe762caf0d14fa75bl,0xa309dcf3bd91ec5dl,
-            0x7aafe1ddf526d04fl },
-          { 0x76911342d39e36ffl,0xe28994d2fabb34b8l,0xac23a92c863110cbl,
-            0x9f0f69673aabd166l },
-          0 },
-        /* 27 << 184 */
-        { { 0x7436bdf47e333f98l,0x879cf31f2455af64l,0x07933a9cf6cfde92l,
-            0xfcac38a5b6e3203fl },
-          { 0xa39b6a8098e5a6e0l,0x1d600b5da4837528l,0x54718de7c32d412bl,
-            0x02870f46317937ccl },
-          0 },
-        /* 28 << 184 */
-        { { 0x1f13756db1761ec8l,0xe53c8b98a4b97e55l,0xb2aee3f84096cc28l,
-            0x48c361a0920f1a8dl },
-          { 0xa98b672d8c31190al,0x7bc1e7d1001855d4l,0x242cfb07bf3f4b2al,
-            0x9bf44a3f32a28bc4l },
-          0 },
-        /* 29 << 184 */
-        { { 0x96d4b271e36eeccdl,0x2d8c01b859237e23l,0x24f7a6eb8adf2653l,
-            0xc08ac4ab41183d80l },
-          { 0xc35e5bb7036367c3l,0xd8c97cbc0ba59f61l,0x296b1f4c5aafe986l,
-            0xa519c7a17d179c37l },
-          0 },
-        /* 31 << 184 */
-        { { 0x4043490790ae5f49l,0x8ac8f73649556b81l,0xb57a89b0f4e77a16l,
-            0xe1a1565d071020eal },
-          { 0x4a27f34d3dda8450l,0x65af18b9bc395814l,0xaf21939f9ff49991l,
-            0x47e00639b4af7691l },
-          0 },
-        /* 33 << 184 */
-        { { 0x4b3e263246b1f9b2l,0x6457d838efde99d3l,0x77d5142325e56171l,
-            0xb45de3df7d54996cl },
-          { 0x1ee2dd3194098d98l,0x986896141f3ebdc5l,0x2704a107997efb47l,
-            0x96b502eecb11e520l },
-          0 },
-        /* 34 << 184 */
-        { { 0x58c8039ec19f866el,0xc84c053e386c2644l,0xb3708ab049435704l,
-            0x1b70c3c86fc47b24l },
-          { 0x235582a27f095649l,0x0d344b66673c9a9el,0x777c9e71e2b00efdl,
-            0x91691d6e5b877856l },
-          0 },
-        /* 35 << 184 */
-        { { 0x11c663c49cd31e22l,0x46ae0bd95fb943d7l,0x6e36bca6a392fc01l,
-            0x4f8cc3a77948716fl },
-          { 0x10ae9d6b3aa4bbb0l,0xcc9b6cb5d8001a86l,0x012c8e3aa0a4ceedl,
-            0xe462971e52274942l },
-          0 },
-        /* 36 << 184 */
-        { { 0x9982e2ac42e176a5l,0x324eba46e2782b64l,0x3d8caaafe18350f5l,
-            0xf3d82af2f5d674cal },
-          { 0xc2090fed56600d1el,0x4548e0ef5950de07l,0xb2f0023f765a4febl,
-            0xb303103339f16790l },
-          0 },
-        /* 37 << 184 */
-        { { 0xb94095dc7bdacf7al,0x0e73db39509b310al,0x76e99a6b41b5f772l,
-            0xef40e9c596f3dbd7l },
-          { 0xd0d644f980f2179el,0xe0db831d5a89807el,0xa0188493c2a2d6c6l,
-            0xf2d9a85e5ba9faa9l },
-          0 },
-        /* 39 << 184 */
-        { { 0x598b7876cdd95b93l,0x5f7cc827336966e8l,0x01887109e797f102l,
-            0x665671c446c7c296l },
-          { 0xb314793c6e019c72l,0x5a6c81580e0329acl,0x4faf2f1b44281b98l,
-            0x825884072e1fc97el },
-          0 },
-        /* 40 << 184 */
-        { { 0xa692781d61a3c8b3l,0x08bc385432876d0el,0xbecf05fb28027b03l,
-            0x636c687da4b1e12fl },
-          { 0x00e3003d07217c58l,0x613ba9375e01b2a3l,0xa58c8405881de16el,
-            0xc653c43014f8f48bl },
-          0 },
-        /* 41 << 184 */
-        { { 0x68e53c7c89c0c7c2l,0xf2e680b23c423272l,0xacd47fae60f50133l,
-            0x4c484c6534f05605l },
-          { 0x663bdcf9ebffbb7dl,0xb49cff3be42421c6l,0x0549f7b13f53f261l,
-            0xc516aeda7c374766l },
-          0 },
-        /* 43 << 184 */
-        { { 0xa515fe0f76a0ec26l,0xf727c0797b0b8b21l,0xaeed4c671993651el,
-            0x1465a7f828ac7c87l },
-          { 0x776bd5131f0ef90bl,0x57515d2cd9773e61l,0x235455e95564c50bl,
-            0xf44daef80bf06a24l },
-          0 },
-        /* 44 << 184 */
-        { { 0xbc1c6897d6a0d0f9l,0xd8e0ea0e3b0d7f55l,0xb35baa92b85b7aadl,
-            0x2becd1b7674e48f4l },
-          { 0xe2d7f78d6d7a9ac2l,0xf5074262f99c95d0l,0x4852470a89f611e9l,
-            0xf7aa911992869decl },
-          0 },
-        /* 45 << 184 */
-        { { 0x0bd1755b0ac4840fl,0x0f4c6c2aa22eef10l,0x3f72fe2d78d16dd9l,
-            0xb2d49200ff7096a4l },
-          { 0xa5dead555ffca031l,0x1d013c320b65f4cfl,0x67e498582a23f441l,
-            0x55bae166d02412c0l },
-          0 },
-        /* 46 << 184 */
-        { { 0x546dd4545739a62al,0x353dc1422a30b836l,0x1462449d99cbd704l,
-            0xda02d0772da69411l },
-          { 0xcb115fe565b1a1adl,0x395235f501230a22l,0x8ae630eed164d970l,
-            0x60b679f0074e3a7el },
-          0 },
-        /* 47 << 184 */
-        { { 0x2e64695245d231e1l,0xc96663ac00d8a0fbl,0xc1fbaa0cd07e1f41l,
-            0x4b31484488758781l },
-          { 0xd6971a835183e72el,0xd1d01f174cbe99b7l,0xe90b438c5a2f7512l,
-            0xf858fa452957c620l },
-          0 },
-        /* 48 << 184 */
-        { { 0xed7f2e774e6daae2l,0x7b3ae0e39e0a19bcl,0xd3293f8a91ae677el,
-            0xd363b0cb45c8611fl },
-          { 0xbe1d1ccf309ae93bl,0xa3f80be73920cae1l,0xaaacba74498edf01l,
-            0x1e6d2a4ab2f5ac90l },
-          0 },
-        /* 49 << 184 */
-        { { 0xb5c5bb67b972a778l,0xc2423a4a190f9b5al,0x4e693cf365247948l,
-            0xc37d129ea94a65a3l },
-          { 0xbea4736b6e9cd47bl,0xf3d1bd212338f524l,0xa2a0278e067a45dal,
-            0xc86d631b5b5dce9bl },
-          0 },
-        /* 51 << 184 */
-        { { 0xc2d75f46116952cel,0xd2b66269b75e40dal,0x024f670f921c4111l,
-            0x37ffd854c91fd490l },
-          { 0x6be44d0385b2f613l,0x040cd7d9ba11c4f9l,0x04c1cb762c0efb1fl,
-            0xd905ff4f505e4698l },
-          0 },
-        /* 52 << 184 */
-        { { 0x60c5f03f233550f1l,0xd4d09411925afd2el,0xa95b65c3d258e5a6l,
-            0x1a19cfb59f902c6al },
-          { 0xb486013af5ad5c68l,0xa2506776979638f3l,0x1232b4d0a38e0b28l,
-            0xa64784b8d36a7b4fl },
-          0 },
-        /* 53 << 184 */
-        { { 0x22c75830a13dcb47l,0xd6e81258efd7a08fl,0x6db703b6e4fc49b8l,
-            0x8a5ac636f01817e9l },
-          { 0x8d27b6e1b3f24514l,0x40edc3bc708c51d7l,0x9a1eec7765bb086dl,
-            0x812ccb42b10800f8l },
-          0 },
-        /* 55 << 184 */
-        { { 0x1a39c6acd4338453l,0x3d93822954b1295dl,0x7bf0bf45e0d81165l,
-            0x83d58ca5972804d2l },
-          { 0x105d3ddb00524b94l,0x65d516e7920378ecl,0x1d28f5f1aea33926l,
-            0xa0b354313901c906l },
-          0 },
-        /* 57 << 184 */
-        { { 0x000442a1e4f354del,0x165b44d9d1d112f5l,0x67fd9ced0d05c0a9l,
-            0xd6ce074360bd5d60l },
-          { 0x9ac80c931522af2al,0x8232d522fa07d449l,0x287b5534c3fdb652l,
-            0x9f0548b3abd2ab98l },
-          0 },
-        /* 59 << 184 */
-        { { 0xde8d7086b9aea1d4l,0x692180d98a7dc3fcl,0xd64ffb53bad3e6f3l,
-            0x84628acf36ce3f91l },
-          { 0xf76e470b6d498ac5l,0xa16945547abad602l,0x5b8fd6a5a255c1f6l,
-            0xffe24e4a8576ae2al },
-          0 },
-        /* 60 << 184 */
-        { { 0x5655179de7d70e03l,0x3e780c5c72a84570l,0xc102b4cb1d50029cl,
-            0x3e71bdd5f075e839l },
-          { 0x6460f4f0b498b822l,0x2682e06c6d4b8da5l,0x4eae53c996a740d4l,
-            0xc19d8bef6389702cl },
-          0 },
-        /* 61 << 184 */
-        { { 0x711be2081025fe1dl,0x2e562c89f0bc6a99l,0xcfd2be3a28bf4150l,
-            0x33037b4a38e5bc91l },
-          { 0x10c6da9df52fea02l,0x511f62444f0ea410l,0x19d37ca81a294c3fl,
-            0x7e40f444618e6fd3l },
-          0 },
-        /* 63 << 184 */
-        { { 0x4095f5ddbedb8734l,0x9c16027c4432f51al,0xced8179d873d0f11l,
-            0x70c2bc9f6ebe6e61l },
-          { 0x5c31035d616cf2f4l,0xf92e0fbd00a4af3dl,0xe6048a03511893c4l,
-            0x639a804b52e2f462l },
-          0 },
-        /* 64 << 184 */
-        { { 0x8735728dc2c6ff70l,0x79d6122fc5dc2235l,0x23f5d00319e277f9l,
-            0x7ee84e25dded8cc7l },
-          { 0x91a8afb063cd880al,0x3f3ea7c63574af60l,0x0cfcdc8402de7f42l,
-            0x62d0792fb31aa152l },
-          0 },
-        /* 65 << 184 */
-        { { 0x0f4bcefd9da373e4l,0x7278f44d119271a3l,0xb2dff94449e111c0l,
-            0xb0a3abf8e5d2b2d4l },
-          { 0x01baabb48ea80631l,0x27517ed3da305f85l,0x0a1ca6fc3f56aa86l,
-            0x183d9c7694c22839l },
-          0 },
-        /* 71 << 184 */
-        { { 0xe9a0dfbf22e238d7l,0x8690dfd97e8d8d31l,0xb3cb2a0d4006c59cl,
-            0xe4d297caa1850d74l },
-          { 0x066f10517842d14cl,0x68dd32737d43602bl,0x1f9f5cf931345f39l,
-            0x44f18c2b10593890l },
-          0 },
-        /* 77 << 184 */
-        { { 0x8d8c0233a7c3f60bl,0xfb59fe2d2bcbbd4cl,0xfa311680dc3e5b44l,
-            0xb3cba9f3fbea5eedl },
-          { 0xcb353b2f61e0e690l,0x06edf0c1b6e0efe0l,0xa29578cb1d0c02a2l,
-            0xaeb2d677937fec07l },
-          0 },
-        /* 83 << 184 */
-        { { 0xa19a81c5cdd0cac9l,0x5c10b942ec9cf85bl,0x0843ef4639e8c298l,
-            0xcfd45d0e6c043258l },
-          { 0x1011bcb9fb7e4b58l,0xae6362a544402bbdl,0x9ecc8c68ec15d751l,
-            0xbc05998869d1a00bl },
-          0 },
-        /* 89 << 184 */
-        { { 0xe9a43619460147e3l,0x881a6af423067448l,0x94f93ae6cee17a6bl,
-            0x469e692f10782558l },
-          { 0x01e244a1289bdb32l,0x240645779dddf970l,0x664cbd92d8f521ecl,
-            0xadaf8ffb600222d0l },
-          0 },
-        /* 95 << 184 */
-        { { 0x68314c740dbec437l,0x2095e1295ec75e2cl,0x8e88a3ddf0e6c606l,
-            0x40ac647d1230f6b2l },
-          { 0x09d124aaa2e6b991l,0xa22f9e2bcc81037cl,0xc842b64d15c3a1c2l,
-            0x4d822becce808c65l },
-          0 },
-        /* 101 << 184 */
-        { { 0xb02204d06ffb396bl,0x82eb6ecc881bead6l,0xf58432cebd6896c8l,
-            0xc243468da38f4b9dl },
-          { 0x8486402df8e628bdl,0x5dd338a1a4df2401l,0x748a41ab0daac953l,
-            0xaa121d13e51e6235l },
-          0 },
-        /* 107 << 184 */
-        { { 0x6daa0a4e50abc6aal,0x99fcc5bdeafb7cf2l,0xc705f64c4b8dbd2al,
-            0x7deff836e7b51e90l },
-          { 0xd92f42b859a8180fl,0x3bb298f8618d24acl,0x2433aa7357a56438l,
-            0xcf29895b48a6a238l },
-          0 },
-        /* 113 << 184 */
-        { { 0x74079dc59ed25aafl,0x7988245c023d5143l,0x7edfc6a6feb79c24l,
-            0x7ed03c50a6baa70fl },
-          { 0x71d3413596a753b4l,0x59efbafcef976246l,0xed050260a4a6947fl,
-            0xabbc1f8066254247l },
-          0 },
-        /* 116 << 184 */
-        { { 0x1f804e00caa4646fl,0x8643dc8870944924l,0xa37f1ca273f86de9l,
-            0xa3199f9228889898l },
-          { 0xc273ba580c1e4adfl,0x0f0d38af65bc82f0l,0xd8b28ab5f8a6cd3bl,
-            0xeea6e08575894d8el },
-          0 },
-        /* 119 << 184 */
-        { { 0x398f39132c1620f7l,0x9046d2dea921f3a3l,0x40a25a2785b50bb0l,
-            0xb9adeca0d32e95f3l },
-          { 0xa4199b1bdede5cbfl,0x9068aee084f5410bl,0x6665e4f5730f0397l,
-            0x2e9ba18c8ae20659l },
-          0 },
-        /* 125 << 184 */
-        { { 0xd76e9b2351835897l,0x72a0e000012deda6l,0x5bf08922bfec23e4l,
-            0x8c2fcf1385cf2b7bl },
-          { 0x6c42f935c63332c6l,0x8736c58395eccce9l,0x2d2abbb10721afc8l,
-            0x1f7a76cc42d4e029l },
-          0 },
-    },
-    {
-        /* 0 << 192 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 192 */
-        { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l,
-            0x803f3e02cd42ab1bl },
-          { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl,
-            0xc097440e5067adc1l },
-          0 },
-        /* 3 << 192 */
-        { { 0x266344a43794f8dcl,0xdcca923a483c5c36l,0x2d6b6bbf3f9d10a0l,
-            0xb320c5ca81d9bdf3l },
-          { 0x620e28ff47b50a95l,0x933e3b01cef03371l,0xf081bf8599100153l,
-            0x183be9a0c3a8c8d6l },
-          0 },
-        /* 4 << 192 */
-        { { 0xb6c185c341dca566l,0x7de7fedad8622aa3l,0x99e84d92901b6dfbl,
-            0x30a02b0e7c4ad288l },
-          { 0xc7c81daa2fd3cf36l,0xd1319547df89e59fl,0xb2be8184cd496733l,
-            0xd5f449eb93d3412bl },
-          0 },
-        /* 5 << 192 */
-        { { 0x25470fabe085116bl,0x04a4337587285310l,0x4e39187ee2bfd52fl,
-            0x36166b447d9ebc74l },
-          { 0x92ad433cfd4b322cl,0x726aa817ba79ab51l,0xf96eacd8c1db15ebl,
-            0xfaf71e910476be63l },
-          0 },
-        /* 7 << 192 */
-        { { 0x72cfd2e949dee168l,0x1ae052233e2af239l,0x009e75be1d94066al,
-            0x6cca31c738abf413l },
-          { 0xb50bd61d9bc49908l,0x4a9b4a8cf5e2bc1el,0xeb6cc5f7946f83acl,
-            0x27da93fcebffab28l },
-          0 },
-        /* 9 << 192 */
-        { { 0x3ce519ef76257c51l,0x6f5818d318d477e7l,0xab022e037963edc0l,
-            0xf0403a898bd1f5f3l },
-          { 0xe43b8da0496033cal,0x0994e10ea1cfdd72l,0xb1ec6d20ba73c0e2l,
-            0x0329c9ecb6bcfad1l },
-          0 },
-        /* 10 << 192 */
-        { { 0xf1ff42a12c84bd9dl,0x751f3ec4390c674al,0x27bb36f701e5e0cal,
-            0x65dfff515caf6692l },
-          { 0x5df579c4cd7bbd3fl,0xef8fb29785591205l,0x1ded7203e47ac732l,
-            0xa93dc45ccd1c331al },
-          0 },
-        /* 11 << 192 */
-        { { 0xbdec338e3318d2d4l,0x733dd7bbbe8de963l,0x61bcc3baa2c47ebdl,
-            0xa821ad1935efcbdel },
-          { 0x91ac668c024cdd5cl,0x7ba558e4c1cdfa49l,0x491d4ce0908fb4dal,
-            0x7ba869f9f685bde8l },
-          0 },
-        /* 13 << 192 */
-        { { 0xed1b5ec279f464bal,0x2d65e42c47d72e26l,0x8198e5749e67f926l,
-            0x4106673834747e44l },
-          { 0x4637acc1e37e5447l,0x02cbc9ecf3e15822l,0x58a8e98e805aa83cl,
-            0x73facd6e5595e800l },
-          0 },
-        /* 15 << 192 */
-        { { 0x468ff80338330507l,0x06f34ddf4037a53el,0x70cd1a408d6993a4l,
-            0xf85a159743e5c022l },
-          { 0x396fc9c2c125a67dl,0x03b7bebf1064bfcbl,0x7c444592a9806dcbl,
-            0x1b02614b4487cd54l },
-          0 },
-        /* 16 << 192 */
-        { { 0x8303604f692ac542l,0xf079ffe1227b91d3l,0x19f63e6315aaf9bdl,
-            0xf99ee565f1f344fbl },
-          { 0x8a1d661fd6219199l,0x8c883bc6d48ce41cl,0x1065118f3c74d904l,
-            0x713889ee0faf8b1bl },
-          0 },
-        /* 17 << 192 */
-        { { 0xb47b60f70de21bb6l,0x64acae4fdcd836cal,0x3375ea6dc744ce63l,
-            0xb764265fb047955bl },
-          { 0xc68a5d4c9841c2c3l,0x60e98fd7cf454f60l,0xc701fbe2756aea0cl,
-            0x09c8885eaab21c79l },
-          0 },
-        /* 19 << 192 */
-        { { 0x45bb810869d2d46cl,0xe47c8b3968c8365al,0xf3b87663267551bdl,
-            0x1590768f5b67547al },
-          { 0x371c1db2fb2ed3ffl,0xe316691917a59440l,0x03c0d178df242c14l,
-            0x40c93fceed862ac1l },
-          0 },
-        /* 21 << 192 */
-        { { 0x1286da692bc982d6l,0x5f6d80f27bdae7e3l,0x3d9c5647a6f064fbl,
-            0xfdc8e6a1d74c1540l },
-          { 0x97da48c6d68b135al,0xc2097979d66dbfffl,0x0296adb9ea20531dl,
-            0xa333730d4ab2c8f0l },
-          0 },
-        /* 23 << 192 */
-        { { 0x0eb3565429847fedl,0xfdc142860a673dd0l,0x721b36278b62dd0bl,
-            0x105a293e711a5771l },
-          { 0xdf001cce7f761927l,0xf7b681b011d04c7dl,0x16dff792a3ac1996l,
-            0x580c120b0fc4ae30l },
-          0 },
-        /* 25 << 192 */
-        { { 0x31ea3d4f7ee8d0bcl,0x3832f22a0f42c3dcl,0xc661061a1a87a2f4l,
-            0x0978c9f64b45576bl },
-          { 0xb7abac3c6dfb5fd2l,0x27f36a00b7e01b90l,0x68f733cde9429e36l,
-            0x953a4681dcbfe8cbl },
-          0 },
-        /* 27 << 192 */
-        { { 0xbfb7c41067fe1eafl,0xa2073c6a6929a785l,0x6f2536f4a75fdb79l,
-            0x859ad26d809bca69l },
-          { 0x06f2c0693b197e7bl,0x656ad9f48ec0a573l,0xe7c7901f9a4d0262l,
-            0xbec29443b938602bl },
-          0 },
-        /* 28 << 192 */
-        { { 0xd00397fc0f0073a4l,0x5b668fa46f8d675fl,0x14374ac91522108cl,
-            0x92efa7d10283e42el },
-          { 0x673e6df90b6d024al,0x05f914d457581f26l,0xf5c8516267df8c12l,
-            0x1197f1b4e06c2462l },
-          0 },
-        /* 29 << 192 */
-        { { 0x6e2d1cb3dd9c90c1l,0x28f82d5a7990579el,0x90e189cd06226195l,
-            0xbd2939df19b0dc74l },
-          { 0x18b18505c0917177l,0xeed5470d3117d9c4l,0x39ef92eb6c893ca0l,
-            0x4533ef8244a41940l },
-          0 },
-        /* 31 << 192 */
-        { { 0xcaee9dec34943ddal,0x8e50e98e8b4b6782l,0x24358ea591ea3a1fl,
-            0x71c4c827a9e1c194l },
-          { 0xa38baa5d09bb7a94l,0xfb4ab4c057b58f9cl,0x4a01065e24e0ee19l,
-            0xb9cf805107b877bfl },
-          0 },
-        /* 33 << 192 */
-        { { 0xd38c1ce0a2980d5el,0x8b84cca4541face7l,0x93298136dbd8d05dl,
-            0x582708d03f85c85al },
-          { 0x6545eec7282960e4l,0x92e184aebaadec07l,0x05452564fd27a20fl,
-            0x79d4668abddce6ebl },
-          0 },
-        /* 34 << 192 */
-        { { 0xf5cc5cccf5191707l,0xe800328bd5d01f67l,0x0572012ebd9b1599l,
-            0xf5be11a6863d0125l },
-          { 0x4da7ca876ea441e0l,0x47dbf83b321b134al,0x5cbadcdac1acfb4al,
-            0x19ac798a734f8e25l },
-          0 },
-        /* 35 << 192 */
-        { { 0xe312623a7002114fl,0xb888b637e047686bl,0x23b2c270cbac91bdl,
-            0xb50b31884dbfe02dl },
-          { 0x8335ce43de97eef6l,0x6a4e65502bac193al,0xf2b35aac3101f720l,
-            0x5b2c88d5379a2015l },
-          0 },
-        /* 36 << 192 */
-        { { 0xf445e77131547128l,0x22761665e27811cal,0x9b944e91a37c6681l,
-            0xc0aa06a536899860l },
-          { 0x8c2b5816cfcd557el,0xf2734a19945aa357l,0x536ca07ca55a0049l,
-            0x8328fdccc636d967l },
-          0 },
-        /* 37 << 192 */
-        { { 0x52b513616aca06bdl,0x8d19b893cdf16560l,0x06b28179c3b438cdl,
-            0xde1ef747cd1819e4l },
-          { 0xbc6cc43b5f557985l,0xa277e11f61e0142al,0x58890f1e429cc392l,
-            0x28d17dbfe5fc8f5el },
-          0 },
-        /* 39 << 192 */
-        { { 0x556df61a29a8f7cbl,0x5cf554dfd14ab27al,0x243f933ba755b886l,
-            0xa4d0b06ff2d4ce87l },
-          { 0xa745eb8d2c0f1d39l,0xc228747aea3047a5l,0xced774c41d2cecc0l,
-            0x54a55c3a774fb01al },
-          0 },
-        /* 40 << 192 */
-        { { 0xa691398a4a9eb3f0l,0x56c1dbff3b99a48fl,0x9a87e1b91b4b5b32l,
-            0xad6396145378b5fel },
-          { 0x437a243ec26b5302l,0x0275878c3ccb4c10l,0x0e81e4a21de07015l,
-            0x0c6265c9850df3c0l },
-          0 },
-        /* 41 << 192 */
-        { { 0x182c3f0e6be95db0l,0x8c5ab38cae065c62l,0xcce8294ebe23abacl,
-            0xed5b65c47d0add6dl },
-          { 0xbce57d78cc9494cal,0x76f75c717f435877l,0xb3084b2eb06560a9l,
-            0x67216bc850b55981l },
-          0 },
-        /* 43 << 192 */
-        { { 0x49c9fd92557de68bl,0x357aa44fc3151b7al,0xd36286d11e4aebd0l,
-            0x84562cd736a51203l },
-          { 0x42a57e7c3cacc002l,0x794a47751b1e25a3l,0x2c2ab68cac0d4356l,
-            0xececb6addb31afdcl },
-          0 },
-        /* 44 << 192 */
-        { { 0x47a5f010b4c21bfel,0x45c5610f0ac3dc20l,0x20e689fcea3bf4dcl,
-            0xf244ea49fb5f46e4l },
-          { 0xd918e59e8ca38e45l,0x7d6c601d96189a6fl,0x1a40f03854138471l,
-            0xfe867d7308a9d034l },
-          0 },
-        /* 45 << 192 */
-        { { 0x3b49e489100c0410l,0x8831d3992adc2b29l,0xb6726cd1247a8116l,
-            0x83a71a59d1d56d8el },
-          { 0x82ade2fe5cd333e9l,0x3b087ef83ea11f1al,0x17b96ca66ce879cel,
-            0xc2f74a971871dc43l },
-          0 },
-        /* 46 << 192 */
-        { { 0xa11a1e3680b576cel,0xf91278bbce2683e8l,0xc3bab95fbae8bc5bl,
-            0x642ca26397351715l },
-          { 0x5ffc14726fecbbc1l,0x2465e996a23f36d4l,0x06fc53bf5187d428l,
-            0x54b4014351fbce91l },
-          0 },
-        /* 47 << 192 */
-        { { 0x081ca6f0eafc7b2cl,0x1ba047a38c48703fl,0xe84865046663accfl,
-            0xde1f97568d43689cl },
-          { 0xf5373e1d5bc19f75l,0x4e48c493d64b0a54l,0x0c43f4e25807dbf6l,
-            0x73bef15167778c36l },
-          0 },
-        /* 48 << 192 */
-        { { 0xca6c0937b1b76ba6l,0x1a2eab854d2026dcl,0xb1715e1519d9ae0al,
-            0xf1ad9199bac4a026l },
-          { 0x35b3dfb807ea7b0el,0xedf5496f3ed9eb89l,0x8932e5ff2d6d08abl,
-            0xf314874e25bd2731l },
-          0 },
-        /* 49 << 192 */
-        { { 0x9d5322e89e9bba53l,0xdd7c9ceb989ff350l,0xd76147eadab0d7b3l,
-            0x8e45b1c6d7a9a9a1l },
-          { 0x8f896a91d4f10c10l,0x999a73c54068de06l,0x84a9d0839cf0a779l,
-            0x4d7cc7689f608ab2l },
-          0 },
-        /* 51 << 192 */
-        { { 0x1833ccddaee93c82l,0x6a05ef7b9f35f20fl,0xc538dac9ae413bc2l,
-            0x1e74f4658b4784bdl },
-          { 0xccb2bc4a49ffd544l,0x9b88183d2b17ae88l,0x96037a136e43824fl,
-            0xbbb61441480bf3dfl },
-          0 },
-        /* 52 << 192 */
-        { { 0x13319d20e090ad42l,0x4ff3186e12cbb719l,0xf38e504913fc0a46l,
-            0x83185a1254e60378l },
-          { 0x08c4057797ea8935l,0x7b2212a946b614f9l,0xedcdfa520634cfb3l,
-            0xdbc60eed9e7d5726l },
-          0 },
-        /* 53 << 192 */
-        { { 0x9b0785c6c7e1070fl,0xec112f53cbf561e5l,0xc93511e37fab3464l,
-            0x9e6dc4da9de8e0c2l },
-          { 0x7733c425e206b4eel,0xb8b254ef50cedf29l,0xfaee4bbbd50ad285l,
-            0x216e76d58c4eb6cfl },
-          0 },
-        /* 55 << 192 */
-        { { 0x9d6a28641d51f254l,0x26c5062a0c2822c3l,0xd74ebba8334bf4eel,
-            0x6e5446eb0b8f7305l },
-          { 0x5988ae8eb629beccl,0x71e576d0a1de7d1dl,0x15e39592a8873970l,
-            0x2b1f9a9342ecc74el },
-          0 },
-        /* 57 << 192 */
-        { { 0xcbdb70727c519bf9l,0x112986bbcaaf48e6l,0x64d4c6d1a13baf3cl,
-            0x85ccf6f7a065e77el },
-          { 0x183be337749beaedl,0xb3703096cba6c9b1l,0x1edf81f0e42b8afel,
-            0xf04ed594ccb73ad7l },
-          0 },
-        /* 59 << 192 */
-        { { 0xfa954ebc38491e9fl,0xf75a5808d32f0b03l,0x196d4a828083b9d3l,
-            0x92d5a0be5e8dc9fel },
-          { 0x4a507ae9aea628bal,0xeea5861e11a02fb5l,0xa033b84fd23ec8f7l,
-            0x1a68c36ec60f11d5l },
-          0 },
-        /* 60 << 192 */
-        { { 0x3dfb55bdab920ef2l,0xe0090971e6244484l,0xdc39fd08f7c6e1a3l,
-            0x1ca765356ee79e72l },
-          { 0x472c8985287d590cl,0x67635e35ad6daeb4l,0x06ec4e7980f9fee3l,
-            0x0aceb39921dc5fdbl },
-          0 },
-        /* 61 << 192 */
-        { { 0xdb2478fd9410a756l,0xd106aefe3a53a1e6l,0x1f4c940d14286333l,
-            0x6a98659d04950958l },
-          { 0x3232a1c6a6bbe060l,0x19ad132ca5e7ca9bl,0x3c9c13ef800fae29l,
-            0x9b0d9068b8660f49l },
-          0 },
-        /* 63 << 192 */
-        { { 0x1e7f043795c53027l,0x5221e5c0da9a3806l,0xf297d8e379d9385fl,
-            0x4d69e95f78ba697el },
-          { 0xdda936cee76d13c1l,0xd9a5790a485b12f5l,0xeab84add51efbfd0l,
-            0xc9a3ee9ca9f44aa4l },
-          0 },
-        /* 64 << 192 */
-        { { 0xefb26a753f73f449l,0x1d1c94f88d44fc79l,0x49f0fbc53bc0dc4dl,
-            0xb747ea0b3698a0d0l },
-          { 0x5218c3fe228d291el,0x35b804b543c129d6l,0xfac859b8d1acc516l,
-            0x6c10697d95d6e668l },
-          0 },
-        /* 65 << 192 */
-        { { 0x8c12e87a15454db4l,0xbc1fc546908e8fbcl,0xc35d83c7e4cf1636l,
-            0xcb2f5ac820641524l },
-          { 0x2400aae2e644ecd0l,0x9b01e2d14be37119l,0x6cffd52831b54857l,
-            0xb3fd5d864b5cbf81l },
-          0 },
-        /* 71 << 192 */
-        { { 0x2e999a4739709fb9l,0x4cb4bbdb62c2b30fl,0x4c7259ac09de0c92l,
-            0x73c1e34f8c59a0ffl },
-          { 0x0a9e5f2e48cb0a12l,0x5e07449fcf499bb0l,0x0527a8b4b02c4a54l,
-            0x7381287159da01e4l },
-          0 },
-        /* 77 << 192 */
-        { { 0xe0b876ca0548ff87l,0x74b5a9b25e03bae3l,0xd5564cc5dd0642d2l,
-            0x29ed211b668c4977l },
-          { 0xf29d3b7aa7422b11l,0x17f2d3586d29b8bal,0x2e35cdda2bb887del,
-            0x650f148078e4444bl },
-          0 },
-        /* 83 << 192 */
-        { { 0x8c75532fb47435ebl,0x2234e2c5a113f905l,0x27b75fea31508ae9l,
-            0x09733e40d489ad0bl },
-          { 0x73b38464a1b06da1l,0x0aed522dc5b7ccf2l,0xcc04783e78d7e5afl,
-            0xa81c8a8ff23eaab7l },
-          0 },
-        /* 89 << 192 */
-        { { 0x6bb5eca73c149ffal,0x4593d851c536487al,0x3675daaad85eb9edl,
-            0xbf65d0f9b8a58ffbl },
-          { 0x1dc6ddddc22e83eel,0xb673397ee10d3c17l,0x6bdc20600ca62c93l,
-            0x260389c30b821f6dl },
-          0 },
-        /* 95 << 192 */
-        { { 0x45f5cf07b417be10l,0x0acb1a44e5d561d8l,0x54b7baeafb1dfbe9l,
-            0x0e6e66219044672el },
-          { 0xa9b6db6d9a793601l,0xd70eadb8a4a0ba4al,0xaedace846098b89el,
-            0x970f2c23ac39d40fl },
-          0 },
-        /* 101 << 192 */
-        { { 0x9dff8d289c7eaaa8l,0x38bcd076db0cc361l,0x25760147cdea9db8l,
-            0x44c89dd40163f343l },
-          { 0x18815d7544db8365l,0xa186d57b37f3e4b3l,0xa71de7806e84a7fal,
-            0xf1c08989e56646b3l },
-          0 },
-        /* 107 << 192 */
-        { { 0xad73e1448fb56a43l,0x078c14fb715543c9l,0xa57770fd64b92d54l,
-            0xf0420a9277e9b919l },
-          { 0xc660d0cb588ccc1dl,0x069baa1471415c2el,0x747438dc32982740l,
-            0x4782ce08767381eel },
-          0 },
-        /* 113 << 192 */
-        { { 0xc2a1ee5fdb3b6b5dl,0x08ce544820e1339fl,0x3cb954b77073955fl,
-            0xb9ed2ee7f32d0832l },
-          { 0xc0a998b1b4aac98el,0x4912273dbca4bac7l,0xac0f5014c3f92c4al,
-            0xbf3dc27f9e916e78l },
-          0 },
-        /* 116 << 192 */
-        { { 0x222c7bae28833944l,0xbb78a867f5e3cf67l,0x590cbd96faf6cfd6l,
-            0x1c50aecb3b0d842el },
-          { 0x8f2c5df1dbade9a5l,0x60923fb7e3840cecl,0xe8f2db6b03a67512l,
-            0x90af187be0d7c628l },
-          0 },
-        /* 119 << 192 */
-        { { 0xb4162b615fee3ccbl,0xe9786e7d7327e651l,0x6c85bd938812d9c1l,
-            0xfe4905083dc9e838l },
-          { 0xe66f25178a6765dfl,0x72fd294edeee184cl,0x07608bd27b6ec227l,
-            0x9df7b664dfdaa5e6l },
-          0 },
-        /* 125 << 192 */
-        { { 0x4aea16602d53a155l,0x7285069a32ab07fdl,0xf6f3000d8b6fcd19l,
-            0x010b1f246e98953fl },
-          { 0xe180bc559f9aa221l,0x7717ee383cba4534l,0x5997f3aa36cbda06l,
-            0x54c6090064a04b05l },
-          0 },
-    },
-    {
-        /* 0 << 200 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 200 */
-        { { 0x25914f7881fdad90l,0xcf638f560d2cf6abl,0xb90bc03fcc054de5l,
-            0x932811a718b06350l },
-          { 0x2f00b3309bbd11ffl,0x76108a6fb4044974l,0x801bb9e0a851d266l,
-            0x0dd099bebf8990c1l },
-          0 },
-        /* 3 << 200 */
-        { { 0xebd6a6777b0ac93dl,0xa6e37b0d78f5e0d7l,0x2516c09676f5492bl,
-            0x1e4bf8889ac05f3al },
-          { 0xcdb42ce04df0ba2bl,0x935d5cfd5062341bl,0x8a30333382acac20l,
-            0x429438c45198b00el },
-          0 },
-        /* 4 << 200 */
-        { { 0xfb2838be67e573e0l,0x05891db94084c44bl,0x9131137396c1c2c5l,
-            0x6aebfa3fd958444bl },
-          { 0xac9cdce9e56e55c1l,0x7148ced32caa46d0l,0x2e10c7efb61fe8ebl,
-            0x9fd835daff97cf4dl },
-          0 },
-        /* 5 << 200 */
-        { { 0x6c626f56c1770616l,0x5351909e09da9a2dl,0xe58e6825a3730e45l,
-            0x9d8c8bc003ef0a79l },
-          { 0x543f78b6056becfdl,0x33f13253a090b36dl,0x82ad4997794432f9l,
-            0x1386493c4721f502l },
-          0 },
-        /* 7 << 200 */
-        { { 0xe566f400b008733al,0xcba0697d512e1f57l,0x9537c2b240509cd0l,
-            0x5f989c6957353d8cl },
-          { 0x7dbec9724c3c2b2fl,0x90e02fa8ff031fa8l,0xf4d15c53cfd5d11fl,
-            0xb3404fae48314dfcl },
-          0 },
-        /* 9 << 200 */
-        { { 0xf02cc3a9f327a07fl,0xefb27a9b4490937dl,0x81451e96b1b3afa5l,
-            0x67e24de891883be4l },
-          { 0x1ad65d4770869e54l,0xd36291a464a3856al,0x070a1abf7132e880l,
-            0x9511d0a30e28dfdfl },
-          0 },
-        /* 10 << 200 */
-        { { 0xfdeed650f8d1cac4l,0xeb99194b6d16bda5l,0xb53b19f71cabbe46l,
-            0x5f45af5039b9276cl },
-          { 0xd0784c6126ee9d77l,0xf7a1558b0c02ca5dl,0xb61d6c59f032e720l,
-            0xae3ffb95470cf3f7l },
-          0 },
-        /* 11 << 200 */
-        { { 0x9b185facc72a4be5l,0xf66de2364d848089l,0xba14d07c717afea9l,
-            0x25bfbfc02d551c1cl },
-          { 0x2cef0ecd4cdf3d88l,0x8cee2aa3647f73c4l,0xc10a7d3d722d67f7l,
-            0x090037a294564a21l },
-          0 },
-        /* 13 << 200 */
-        { { 0x6ac07bb84f3815c4l,0xddb9f6241aa9017el,0x31e30228ca85720al,
-            0xe59d63f57cb75838l },
-          { 0x69e18e777baad2d0l,0x2cfdb784d42f5d73l,0x025dd53df5774983l,
-            0x2f80e7cee042cd52l },
-          0 },
-        /* 15 << 200 */
-        { { 0x43f18d7f4d6ee4abl,0xd3ac8cde9570c3dcl,0x527e49070b8c9b2al,
-            0x716709a7c5a4c0f1l },
-          { 0x930852b0916a26b1l,0x3cc17fcf4e071177l,0x34f5e3d459694868l,
-            0xee0341aba28f655dl },
-          0 },
-        /* 16 << 200 */
-        { { 0xf431f462060b5f61l,0xa56f46b47bd057c2l,0x348dca6c47e1bf65l,
-            0x9a38783e41bcf1ffl },
-          { 0x7a5d33a9da710718l,0x5a7799872e0aeaf6l,0xca87314d2d29d187l,
-            0xfa0edc3ec687d733l },
-          0 },
-        /* 17 << 200 */
-        { { 0x4b764317aa365220l,0x7a24affe68cc0355l,0x76732ed0ceb3df5el,
-            0x2ce1332aae096ed0l },
-          { 0x89ce70a7b8adac9dl,0xfdddcf05b3fc85c8l,0xbd7b29c6f2ee8bfel,
-            0xa1effcb9457d50f3l },
-          0 },
-        /* 19 << 200 */
-        { { 0x6053972dac953207l,0xc2ca9a8408ad12f6l,0x9ed6cd386ba36190l,
-            0xa5b50a48539d18a4l },
-          { 0xd9491347dbf18c2al,0x2cdce4662e9697cfl,0x4e97db5ca9e31819l,
-            0x0fb02e2d4c044b74l },
-          0 },
-        /* 21 << 200 */
-        { { 0x66a4dd414aa5e9ddl,0x6ec7576e64f6aeb9l,0x3f08ce06c7e980b5l,
-            0x52fe9fd6c1a2aa7el },
-          { 0xfe46e6d95074326al,0xd570ed734c126c1dl,0x86c7ec257217d55al,
-            0x3cb434057c3de2b2l },
-          0 },
-        /* 23 << 200 */
-        { { 0x48e0295dcc9e79bfl,0x2419485693eb403dl,0x9386fb7709dd8194l,
-            0xb6e89bb101a242f6l },
-          { 0xc7994f3924d308d7l,0xf0fbc392de673d88l,0x43eed52ea11abb62l,
-            0xc900f9d0c83e7fbel },
-          0 },
-        /* 25 << 200 */
-        { { 0x214a10dca8152891l,0xe6787b4c64f1abb2l,0x276333d9fa1a10edl,
-            0xc0e1c88e47dbccbcl },
-          { 0x8a3c37c4849dd12el,0x2144a8c8d86e109fl,0xbb6891f7286c140cl,
-            0xb0b8c5e29cce5e6fl },
-          0 },
-        /* 27 << 200 */
-        { { 0x3f9e0e3499753288l,0x6b26f1ebe559d93al,0x647fe21d9841faf1l,
-            0x48a4b6efa786ea02l },
-          { 0x6e09cd22665a882dl,0x95390d81b63ccda6l,0x5b014db4b026a44al,
-            0x5b96efb22ad30ff1l },
-          0 },
-        /* 28 << 200 */
-        { { 0x64c50c8b4a3b99e9l,0x2489a675d0a26f4fl,0xe2aacaeed85bc6fdl,
-            0x556882038a6019bal },
-          { 0x7ceb9da645cfac07l,0xe1ad3d25652dbd09l,0x086adf348d3b5d2bl,
-            0xf9256d8aec3654a0l },
-          0 },
-        /* 29 << 200 */
-        { { 0x571c246bf009a690l,0x8fe54231ccd90d3al,0x8adde6adfe173b79l,
-            0x75d9a392b05a5e3bl },
-          { 0x607f47b0d1bb3a84l,0xe4e3b472058e691al,0xfc0f793bf3d956e3l,
-            0x6a6730b605de54dal },
-          0 },
-        /* 31 << 200 */
-        { { 0x4daf7f540d80aaa1l,0xc571d04c229c4574l,0x469e2da5fffca53dl,
-            0x9fffe29513ff7f59l },
-          { 0x2075da5a33a254f7l,0x769f33acd35e575dl,0x7b940d2c3d35001al,
-            0x2d606b57e34c95b7l },
-          0 },
-        /* 33 << 200 */
-        { { 0xc7e4f8b899365f86l,0x8f6f959faae69527l,0x749ffedffdfaeeeal,
-            0x2b91f0221b54c2a0l },
-          { 0xe75c2352addbdf83l,0xe7329922fff2694cl,0xbb65ae06badadeacl,
-            0x16cbb9d1f56be3b5l },
-          0 },
-        /* 34 << 200 */
-        { { 0xb100a4c67a07bd70l,0x222fee7634787efel,0xa4dafc14f1e79d1bl,
-            0x0d3a82dad18b8be4l },
-          { 0xe0181445fc06922fl,0x0873d99b714a90b6l,0xdf43082fa5087a0el,
-            0x195e49367399e0dbl },
-          0 },
-        /* 35 << 200 */
-        { { 0x7e83545aae6fcc9cl,0x1a24fce819e15ce2l,0x4a3465c536d8c6a8l,
-            0xd1e5f24109436ae0l },
-          { 0xed334bfc6be463d5l,0xc46a600b934fbdcfl,0xbd2fd65b920321ffl,
-            0x953fa91767fa154el },
-          0 },
-        /* 36 << 200 */
-        { { 0x5dca4995f93ddad1l,0x061efcabf72470c2l,0xad78d54d5e7e0741l,
-            0xa91f4e839c4e0ab4l },
-          { 0xdd4403af5c75aa0dl,0x4308c8ee13c69113l,0x3a3b66f51ebc36adl,
-            0xc07cc3f0f4bf777al },
-          0 },
-        /* 37 << 200 */
-        { { 0x3fd1963e37a86b32l,0x22e236d60bd0880el,0xb87467cf89f0fa5cl,
-            0x85b9c6c0310e0265l },
-          { 0x82979a96783459ael,0xd19b0919bd529ed3l,0xa21f771808434f94l,
-            0x3dd130a9195369c6l },
-          0 },
-        /* 39 << 200 */
-        { { 0xc61e62767915d157l,0xc48244279e07fb0el,0x8980c1cc8420ea49l,
-            0x10d82e4a588d4e2bl },
-          { 0xdddecd52b17eff2dl,0xe44c7b2ded8492a4l,0x96ca89ebb9bea6afl,
-            0x724166fe1b03ed03l },
-          0 },
-        /* 40 << 200 */
-        { { 0xfc87975f8fb54738l,0x3516078827c3ead3l,0x834116d2b74a085al,
-            0x53c99a73a62fe996l },
-          { 0x87585be05b81c51bl,0x925bafa8be0852b7l,0x76a4fafda84d19a7l,
-            0x39a45982585206d4l },
-          0 },
-        /* 41 << 200 */
-        { { 0x8bbc484ed551f3e1l,0x6e058a90b7eb06d2l,0xfaccd9a0e5cd281al,
-            0xe7661b78d5b44900l },
-          { 0x03afe115725fde22l,0xbe929230c7229fd1l,0x5cd0d16a0000035el,
-            0x1f6a9df0c8f5a910l },
-          0 },
-        /* 43 << 200 */
-        { { 0xe54bbcfd535dfc82l,0x89be0b89a9012196l,0xa67831ee71011beal,
-            0x2ea7a8292db43878l },
-          { 0xff7c144378ffe871l,0xa67dc3d4c63f65eal,0xbbfc7fc2a1527419l,
-            0x6440380bf6c36b8fl },
-          0 },
-        /* 44 << 200 */
-        { { 0x71ab9f69d812d7e6l,0x2847c5516e142126l,0x9e27755bb31e7753l,
-            0xb89533e2943b8c7fl },
-          { 0xbe7f0c6e14fa7dc6l,0x782a06388cee1f7al,0x7069292938e13a6bl,
-            0x1e1221f0c63f4d28l },
-          0 },
-        /* 45 << 200 */
-        { { 0x9030aa9a63a431f4l,0x0fa7b5d45039a318l,0x6a0cf40af083687dl,
-            0x46689cec659fa752l },
-          { 0x8259727a456fa97el,0x4f618a355b08d7fcl,0x2c44217b72028d15l,
-            0x8083b09935111e32l },
-          0 },
-        /* 46 << 200 */
-        { { 0xaa5976523b5b29f1l,0xb07f10ab37432a54l,0x16e3e2236e36556fl,
-            0xf1c7c9bd47cd4586l },
-          { 0xa4eef99d3f87216dl,0x4e54d3c52e1eaa79l,0x534c5901d2540d91l,
-            0x718df7c9b6f0fcfcl },
-          0 },
-        /* 47 << 200 */
-        { { 0x99497f8a2eb0ee3bl,0x87e550c1caeb3a20l,0xd23e053dfb91627cl,
-            0xb971c043873124e6l },
-          { 0x3581ab853b16e467l,0x24541c926145187bl,0x4423ec5c010c2527l,
-            0x775f13029fa82a68l },
-          0 },
-        /* 48 << 200 */
-        { { 0x499b6ab65eb03c0el,0xf19b795472bc3fdel,0xa86b5b9c6e3a80d2l,
-            0xe43775086d42819fl },
-          { 0xc1663650bb3ee8a3l,0x75eb14fcb132075fl,0xa8ccc9067ad834f6l,
-            0xea6a2474e6e92ffdl },
-          0 },
-        /* 49 << 200 */
-        { { 0xbaebdd8a0c40aec4l,0x5eccafb563e8cfd0l,0x1c204c0eb5159938l,
-            0x607109d34b996aa9l },
-          { 0x024c6c4b9cef59fel,0xbc846e216ed4b6f1l,0xf6a50ff3ff652c0al,
-            0x368af2c72d95220cl },
-          0 },
-        /* 51 << 200 */
-        { { 0xec9c2e35cbd3ccafl,0xb9eeff3ddcda8f30l,0x82012e191062d02el,
-            0xed964cc94efc6b6el },
-          { 0x8853ea0a6bf54c22l,0xea40fcc0f3cbe264l,0x21f9c01ddecf114el,
-            0x05e754c63da71e59l },
-          0 },
-        /* 52 << 200 */
-        { { 0xe6a26d38046dfc72l,0x70409579c2175175l,0x2a575ac5d44e0c1dl,
-            0xb35395e01479ab5al },
-          { 0x1550a5d4f7bfbd8el,0x01daeb680778807bl,0xe0aa940321294dbal,
-            0x84bcdc8c5b5a93b7l },
-          0 },
-        /* 53 << 200 */
-        { { 0x876cc4d2520f04abl,0x6e320f5da85ff6a8l,0x7c504720ce17bc80l,
-            0xe7907079a62089f9l },
-          { 0xa45c4ac7bca45feel,0xd8f3facd5bd54b0cl,0xc0b036277b3e4a24l,
-            0xaabe96dfe4cd4b57l },
-          0 },
-        /* 55 << 200 */
-        { { 0xdc85a54773862ce4l,0x169051a3cc6f5d85l,0x8e3d3be0355f4df7l,
-            0xa139d6fac72bac76l },
-          { 0xddc95d0dfeb0a6f0l,0xd53f70e545cd6955l,0x18eede5e47e54112l,
-            0x4a135dc9cbc6a52el },
-          0 },
-        /* 57 << 200 */
-        { { 0x705a08ba90a58fb4l,0x10eef880fb3f8a64l,0x4ced9ba2f8e585ffl,
-            0xb4f0f955fc6ebef5l },
-          { 0x152c1a338d8b739el,0xb2be701db495bee5l,0xd27141a8d3540a74l,
-            0x20c8a00247f9e9d7l },
-          0 },
-        /* 59 << 200 */
-        { { 0x6d5ae921f5adcb3fl,0xaed1047003a3b610l,0x7c75e36f22256df9l,
-            0xe664b36fb97dae99l },
-          { 0x138b5eca91e746ael,0xb3e01ef5648674a7l,0xa3f256da9e375c74l,
-            0xa00e82bc6a82d6f3l },
-          0 },
-        /* 60 << 200 */
-        { { 0xe7a01eae6e28b4a8l,0xb3bf8224782166c9l,0x0b7ba2a06a244510l,
-            0x9751a69c2abbb4dbl },
-          { 0xb611adc1b3f9fcbcl,0x1d08eb3b436c4675l,0x1c71e98a20f96a64l,
-            0x33d9b58c7ffd3f08l },
-          0 },
-        /* 61 << 200 */
-        { { 0x7c7b03c1affa2d6cl,0x5f189bb9aec6e624l,0xe77a1eedadeff5e7l,
-            0xfc58b90f4280b467l },
-          { 0x561e5d579b71cb4el,0x8ed767aa36d6a17el,0x38d8671e8aa9e188l,
-            0x7bc68f07a95350c0l },
-          0 },
-        /* 63 << 200 */
-        { { 0xe0cd38cf98c01384l,0xc6741123a4226d9fl,0xdd1d42dbf877a0b8l,
-            0xc5986ef0110b3cbal },
-          { 0xeba949f809c8cebel,0x96b47bc4bd39f1dcl,0xbad140b6e07a2a3cl,
-            0x2a8d80999ac5ca8al },
-          0 },
-        /* 64 << 200 */
-        { { 0x39d934abd3c095f1l,0x04b261bee4b76d71l,0x1d2e6970e73e6984l,
-            0x879fb23b5e5fcb11l },
-          { 0x11506c72dfd75490l,0x3a97d08561bcf1c1l,0x43201d82bf5e7007l,
-            0x7f0ac52f798232a7l },
-          0 },
-        /* 65 << 200 */
-        { { 0x8cf27618590ca850l,0x58134f6f44bb94f2l,0x0a147562b78b4eecl,
-            0x2e5986e39f1ed647l },
-          { 0x9becf893348393b0l,0xaea21b92c31c2a86l,0x3d69859e5ff1b9a6l,
-            0x6fcd19f4cd805691l },
-          0 },
-        /* 71 << 200 */
-        { { 0x81619bd4841f43c3l,0x3a3325538e5c61f0l,0x2b68921eda862151l,
-            0x97f5c8a741a491f8l },
-          { 0x8b452094d3b9afa0l,0x93b2b7b4f2124dbcl,0x53285e7d26e0e26dl,
-            0x3f003fc5c8a24edel },
-          0 },
-        /* 77 << 200 */
-        { { 0x4cdabb586c025824l,0x5935ad1586bfcd7dl,0x8ce2c3101b7c5533l,
-            0x761c9fe96cae8808l },
-          { 0x8a0723f5d9e66d70l,0xb640b323dcced11dl,0x5768528051ae548cl,
-            0x83576f75d53f3f2cl },
-          0 },
-        /* 83 << 200 */
-        { { 0xc715edc47b532ec3l,0x159765e6c4a6e14bl,0x4a74f15228cd2d45l,
-            0xbfd309edae8c753bl },
-          { 0xf56bb5315d6d5245l,0x2c89c21833b30a55l,0xe436141acd4ed5fal,
-            0x7eb7a5c707868ee6l },
-          0 },
-        /* 89 << 200 */
-        { { 0x9a3ad3ffb0c7c48cl,0x25e8d977738e3638l,0xbb6c6c9d1c024074l,
-            0xeda1ac0f8cfdf416l },
-          { 0x93059ba538de49e2l,0xdb199cfc1b9ce741l,0x49b05e9446f3b494l,
-            0x717cafc606480902l },
-          0 },
-        /* 95 << 200 */
-        { { 0x8d27421052885708l,0x9d2297fd74e5b9b5l,0xe7cb6a68dc4d7318l,
-            0x0b60b0d276357b31l },
-          { 0x57301994532c2095l,0xfbae2ba203373452l,0xe8020b20ba700583l,
-            0x1ca7772c2988919cl },
-          0 },
-        /* 101 << 200 */
-        { { 0x723296eb918f3eecl,0x358c9ff0b79901c6l,0x64a1934c8d5e814cl,
-            0x7e5a9afced165177l },
-          { 0xd783840168733e7al,0xfcf3c0b6f61ede6dl,0x94ec0bf08434e804l,
-            0xa5a70153c192c1cdl },
-          0 },
-        /* 107 << 200 */
-        { { 0x03cdf976c23e49d4l,0x51e5cfa5a2ae72d5l,0x7716faa3100f7a51l,
-            0xc53153a2c14dc015l },
-          { 0xe7c69b052b47ec18l,0xff4756907ea93b01l,0x55fde3c540a2f205l,
-            0x0263d0b12f85aed6l },
-          0 },
-        /* 113 << 200 */
-        { { 0x668c56619686fe30l,0x382a8ccd8f73a476l,0xda012cbfb40a85e7l,
-            0x55ea1e72e9e88b91l },
-          { 0x8312556088cc5afcl,0x44ae54cbc45b19c7l,0xc91fffa8f86a02cdl,
-            0xc79f573752d7e89bl },
-          0 },
-        /* 116 << 200 */
-        { { 0x652b50523e357579l,0x08ce7d3a2afe5746l,0x9dc1cca6f71a12efl,
-            0x80a221c24f6c4196l },
-          { 0xdde40eff0f49f508l,0x7995bb46913b0dc3l,0x4adbdeb385e44f6el,
-            0x6816bb3ab222e4bbl },
-          0 },
-        /* 119 << 200 */
-        { { 0xce1ee518579a1a4dl,0x5d86e8912bc3870al,0x230878d18da907c4l,
-            0xc648392777ae7ea8l },
-          { 0x64319653016c0ad7l,0x7cbfa0b0b71f20dal,0xbf087dc3395ed4d8l,
-            0x59512add307d218dl },
-          0 },
-        /* 125 << 200 */
-        { { 0x7378a969d8ae335el,0x11c69965506d3a42l,0x212539769949468al,
-            0x570cf87e64995050l },
-          { 0xf300ad2e30b94e22l,0xbc159cf8f36dad32l,0xdff3b3767ca8aa6al,
-            0xa5de93b5627fb9e7l },
-          0 },
-    },
-    {
-        /* 0 << 208 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 208 */
-        { { 0x75d9bc15adf7cccfl,0x81a3e5d6dfa1e1b0l,0x8c39e444249bc17el,
-            0xf37dccb28ea7fd43l },
-          { 0xda654873907fba12l,0x35daa6da4a372904l,0x0564cfc66283a6c5l,
-            0xd09fa4f64a9395bfl },
-          0 },
-        /* 3 << 208 */
-        { { 0xc51aa29e5cfe5c48l,0x82c020ae815ee096l,0x7848ad827549a68al,
-            0x7933d48960471355l },
-          { 0x04998d2e67c51e57l,0x0f64020ad9944afcl,0x7a299fe1a7fadac6l,
-            0x40c73ff45aefe92cl },
-          0 },
-        /* 4 << 208 */
-        { { 0xe5f649be9d8e68fdl,0xdb0f05331b044320l,0xf6fde9b3e0c33398l,
-            0x92f4209b66c8cfael },
-          { 0xe9d1afcc1a739d4bl,0x09aea75fa28ab8del,0x14375fb5eac6f1d0l,
-            0x6420b560708f7aa5l },
-          0 },
-        /* 5 << 208 */
-        { { 0xbf44ffc75488771al,0xcb76e3f17f2f2191l,0x4197bde394f86a42l,
-            0x45c25bb970641d9al },
-          { 0xd8a29e31f88ce6dcl,0xbe2becfd4bb7ac7dl,0x13094214b5670cc7l,
-            0xe90a8fd560af8433l },
-          0 },
-        /* 7 << 208 */
-        { { 0x0ecf9b8b4ebd3f02l,0xa47acd9d86b770eal,0x93b84a6a2da213cel,
-            0xd760871b53e7c8cfl },
-          { 0x7a5f58e536e530d7l,0x7abc52a51912ad51l,0x7ad43db02ea0252al,
-            0x498b00ecc176b742l },
-          0 },
-        /* 9 << 208 */
-        { { 0x9ff713ef888ae17fl,0x6007f68fb34b7bebl,0x5d2b18983b653d64l,
-            0xcbf73e91d3ca4b1bl },
-          { 0x4b050ad56cdfb3a1l,0x41bd3ec3d1f833a4l,0x78d7e2ee719d7bf5l,
-            0xea4604672a27412el },
-          0 },
-        /* 10 << 208 */
-        { { 0x7dad6d1b42cd7900l,0xb6e6b439e058f8a4l,0x8836f1e662aa3bbcl,
-            0xd45bf2c811142b0al },
-          { 0xae324bac3c045ed1l,0x372be24d270a8333l,0xeeda7a3a6b7c73b6l,
-            0xf6675402db49562al },
-          0 },
-        /* 11 << 208 */
-        { { 0xc312ba68441e760dl,0x84d0d061a50e512el,0xfe764f4e4bbdd849l,
-            0xa924adcf9dadd5c0l },
-          { 0x08685961debfe976l,0xd3d846c529fba601l,0x43bf8227dc3f4040l,
-            0x05e767b8a49e9ff5l },
-          0 },
-        /* 13 << 208 */
-        { { 0xc4689c309953e453l,0x5e355a2e1712dca5l,0x1ff83c81f1cd96f7l,
-            0xb06b89fb44cf56dbl },
-          { 0x1827705365f16e0dl,0x6403b91de5618672l,0xba3f9475be384bc6l,
-            0x7f691cbe303ce5f3l },
-          0 },
-        /* 15 << 208 */
-        { { 0x4589ba03210f4045l,0xd5e7366301e8012al,0x1c26052d74462ffal,
-            0xe78f600c4f989519l },
-          { 0xc63ca0c97cee0b2fl,0xbe588573af760b5fl,0x05906fc4593773cdl,
-            0xd5970fb0e322d5afl },
-          0 },
-        /* 16 << 208 */
-        { { 0x103c46e60ebcf726l,0x4482b8316231470el,0x6f6dfaca487c2109l,
-            0x2e0ace9762e666efl },
-          { 0x3246a9d31f8d1f42l,0x1b1e83f1574944d2l,0x13dfa63aa57f334bl,
-            0x0cf8daed9f025d81l },
-          0 },
-        /* 17 << 208 */
-        { { 0xf67c098aae0690aal,0x1a4656422b7bc62bl,0xaffc6b917220dea2l,
-            0xd97ac543d2552deel },
-          { 0x1f84514a7e816b8el,0xe9887e81a8f38552l,0x2e6358e6847ad46bl,
-            0x1f67871e6bc9895el },
-          0 },
-        /* 19 << 208 */
-        { { 0x2462b6e0d47f43fal,0x71db3610d8a245e5l,0x0c26b0e734208974l,
-            0x0cd6d49d2029bd2el },
-          { 0xf207c9f6091922b8l,0x0c476c5c7f0fbf66l,0x6de7efb2295d6da8l,
-            0xea054ee10ced6cfel },
-          0 },
-        /* 21 << 208 */
-        { { 0xd21496e3e9bd795cl,0xf293f617c6a557del,0x9d041b7239a45642l,
-            0xe8353dab4ac87f80l },
-          { 0x21e9f35620d8d019l,0x1f4adca9d2fb2668l,0xe5f68227dfecd64al,
-            0x10d71b79d7f09ec0l },
-          0 },
-        /* 23 << 208 */
-        { { 0xca3f068999f87118l,0x99a933911b2417f0l,0xa383481a3d1f70e5l,
-            0x7a31a6c833b14414l },
-          { 0x9d60f4368b2a9931l,0xd4c97ded80588534l,0x7cb29e82ab6a8bdal,
-            0x3799bdad97b4c45al },
-          0 },
-        /* 25 << 208 */
-        { { 0x51da0ff629011af3l,0xcbb03c809a4f0855l,0xea3536725555b10bl,
-            0x4bf94e025c7da97el },
-          { 0x384352f5ff713300l,0xb2c2b675192d41e6l,0x4ff66861625ca046l,
-            0xf0f5e472013dddc4l },
-          0 },
-        /* 27 << 208 */
-        { { 0x38c44cdc59987914l,0xad7f2829757fb853l,0x9aabf1c8688e3342l,
-            0xbe0f1e4ef534c850l },
-          { 0x732cac652ec24ecal,0x9328b657933bb5e4l,0xe2747ff60bb31033l,
-            0xdbaab72cfcdc36acl },
-          0 },
-        /* 28 << 208 */
-        { { 0x0e5e3049a639fc6bl,0xe75c35d986003625l,0x0cf35bd85dcc1646l,
-            0x8bcaced26c26273al },
-          { 0xe22ecf1db5536742l,0x013dd8971a9e068bl,0x17f411cb8a7909c5l,
-            0x5757ac98861dd506l },
-          0 },
-        /* 29 << 208 */
-        { { 0xaf410d5aac66a3e8l,0x39fcbffb2031f658l,0xd29e58c947ce11fbl,
-            0x7f0b874965f73e49l },
-          { 0xedc30f4b27fea6c6l,0xe03b9103d2baa340l,0xa7bb3f17ae680612l,
-            0xe06656a8197af6f0l },
-          0 },
-        /* 31 << 208 */
-        { { 0x84562095bff86165l,0x994194e916bc7589l,0xb1320c7ec14c6710l,
-            0x508a8d7f766e978fl },
-          { 0xd04adc9ec7e1f6fel,0x7bafaff68398cecfl,0x906df2fccef3b934l,
-            0xc65afe18f3008c38l },
-          0 },
-        /* 33 << 208 */
-        { { 0x477ffeeeab983130l,0x5426363a96e83d55l,0xcf0370a15204af42l,
-            0x99834414b5a6ea8fl },
-          { 0xf475ba711ab4ee8al,0x8486da5d0102d8f2l,0x55082e713839c821l,
-            0xa57e58395b65defal },
-          0 },
-        /* 34 << 208 */
-        { { 0x34b2185bbbb33a76l,0x189038b7d48158c2l,0xfa32eb90e9e90217l,
-            0x79271771730e74dfl },
-          { 0x315ed8c2a5d01ffdl,0x9799dae723e6a95el,0x40070aa016f5715al,
-            0x40e6c0ca5ea51f8cl },
-          0 },
-        /* 35 << 208 */
-        { { 0x099c0570d8132163l,0xcd5508a3023dbbf3l,0x18162ff526bfe6a6l,
-            0xf39e071144bbb455l },
-          { 0x49664996eaa3cf96l,0x1c6442d5e2649be9l,0x6199f740c01d269dl,
-            0x4be605ee37542c11l },
-          0 },
-        /* 36 << 208 */
-        { { 0xc7313e9cf36658f0l,0xc433ef1c71f8057el,0x853262461b6a835al,
-            0xc8f053987c86394cl },
-          { 0xff398cdfe983c4a1l,0xbf5e816203b7b931l,0x93193c46b7b9045bl,
-            0x1e4ebf5da4a6e46bl },
-          0 },
-        /* 37 << 208 */
-        { { 0xd032fbfd0dbf82b4l,0x707181f668e58969l,0xef434381e7be2d5el,
-            0x290669176f2c64ddl },
-          { 0xf66cffc3772769abl,0x68d8a76a17aad01cl,0xdd3991c590f6e078l,
-            0xdb74db06ea4ac7dcl },
-          0 },
-        /* 39 << 208 */
-        { { 0x9f34a7c11c78be71l,0x7bf2f2d149ca6987l,0xb528a514dcd34afcl,
-            0x4dddb3f1183a68b1l },
-          { 0x54d2626660b83883l,0x9073e4e0e0cd8dadl,0xbd2b837d9eb818b2l,
-            0x5fa5f9086ae2e32dl },
-          0 },
-        /* 40 << 208 */
-        { { 0xf9942a6043a24fe7l,0x29c1191effb3492bl,0x9f662449902fde05l,
-            0xc792a7ac6713c32dl },
-          { 0x2fd88ad8b737982cl,0x7e3a0319a21e60e3l,0x09b0de447383591al,
-            0x6df141ee8310a456l },
-          0 },
-        /* 41 << 208 */
-        { { 0xcd02ba1e0df98a64l,0x301b6bfa03f5676el,0x41e1a8d4a2fe4090l,
-            0x489c1cbf47f0e1dcl },
-          { 0x4171a98c20760847l,0xdcb21cee77af4796l,0x5fb0f0c9d0b7e981l,
-            0x4c2791dff33b9f8dl },
-          0 },
-        /* 43 << 208 */
-        { { 0x95d7ec0c50420a50l,0x5794665c2a6756d5l,0x73558c6e9101e7f5l,
-            0xa3fa0f8c1642af0el },
-          { 0xa11b309b4ee43551l,0x3939de30cb8fc712l,0x9710f2320fde8921l,
-            0x2a4db2d5cae8b41cl },
-          0 },
-        /* 44 << 208 */
-        { { 0xaec1a039e6d6f471l,0x14b2ba0f1198d12el,0xebc1a1603aeee5acl,
-            0x401f4836e0b964cel },
-          { 0x2ee437964fd03f66l,0x3fdb4e49dd8f3f12l,0x6ef267f629380f18l,
-            0x3e8e96708da64d16l },
-          0 },
-        /* 45 << 208 */
-        { { 0xdf6cdac0bc4c78adl,0xbe9e32182e97376el,0xa37f9d8b1a139274l,
-            0x7640c3982807128el },
-          { 0xe9735166c05b5f85l,0xbccd3675100e5716l,0x51376a293e5c9682l,
-            0x95efe088848f6aeal },
-          0 },
-        /* 46 << 208 */
-        { { 0xfac2d7dd23d14105l,0xdda17149a9136f52l,0xb9f3a9c672d1a99bl,
-            0x2fcf532a142c3b20l },
-          { 0xc2731f1e61190c1bl,0x26dbe810a76509e4l,0xc96cc431908bb92fl,
-            0x5661a84d80e3e694l },
-          0 },
-        /* 47 << 208 */
-        { { 0x5194d144150ba121l,0x8de57c48b6b11561l,0x803228da96c156d9l,
-            0x2112e4250a8f6376l },
-          { 0x15436294643449ffl,0xfc3880add4118cd0l,0x16ed90731e3f7413l,
-            0xa400699901d38d6dl },
-          0 },
-        /* 48 << 208 */
-        { { 0xbc19180c207674f1l,0x112e09a733ae8fdbl,0x996675546aaeb71el,
-            0x79432af1e101b1c7l },
-          { 0xd5eb558fde2ddec6l,0x81392d1f5357753fl,0xa7a76b973ae1158al,
-            0x416fbbff4a899991l },
-          0 },
-        /* 49 << 208 */
-        { { 0xf84c9147c52d7384l,0x86391accec01efa6l,0xffd68616f9c6f3f4l,
-            0xc7536461b17c2de6l },
-          { 0xa81f4ba10121abdfl,0xa068a2e26f6eae27l,0xe0ee90350eb159f0l,
-            0x4c48f761fd8c4b9cl },
-          0 },
-        /* 51 << 208 */
-        { { 0x4b6d71e87790000cl,0xced195744ce9293el,0xc25626a3747585e8l,
-            0xb8307d22d7044270l },
-          { 0xf08e7ef6117c24cbl,0xae6403162f660d04l,0xbc3ffdcff224a2fdl,
-            0x1ebc0328d0586c7el },
-          0 },
-        /* 52 << 208 */
-        { { 0x9e65fdfd0d4a9dcfl,0x7bc29e48944ddf12l,0xbc1a92d93c856866l,
-            0x273c69056e98dfe2l },
-          { 0x69fce418cdfaa6b8l,0x606bd8235061c69fl,0x42d495a06af75e27l,
-            0x8ed3d5056d873a1fl },
-          0 },
-        /* 53 << 208 */
-        { { 0x46b160e5a6022278l,0x86b1d50cc30a51fcl,0xe898ac0e684b81b7l,
-            0x04d591e277b93597l },
-          { 0xd20cac347626e18al,0xb49c941f0a968733l,0x054e6e7e21631627l,
-            0xd6d33db9d4c716b1l },
-          0 },
-        /* 55 << 208 */
-        { { 0xaa79ab4bf91e9b75l,0x7df3235bd34d961dl,0x9f3954e6534a40e1l,
-            0x80f88d2c790b4456l },
-          { 0x98f7711b21e9fb2al,0x0a04c318877d27e6l,0x499b7c2412338848l,
-            0x0b1dbe9ccd5e7ec3l },
-          0 },
-        /* 57 << 208 */
-        { { 0xb430ff44e04715ffl,0x671358d565d076d0l,0x3946d38f22c3aa06l,
-            0x80919ea363b2d627l },
-          { 0x14ffa219e8790922l,0xfe1d895ae8d89c48l,0x717e9e51748e806el,
-            0xb91e1ddf550d711dl },
-          0 },
-        /* 59 << 208 */
-        { { 0x8aac26225f540127l,0x57cd5d7cba25f742l,0x87006a6b1df7a0fcl,
-            0x88e9ab863ecbf26cl },
-          { 0xe1b8155f9143b314l,0xc00196130b679bddl,0x819e7b61a1871d07l,
-            0xc36e7892cc2c9cc9l },
-          0 },
-        /* 60 << 208 */
-        { { 0x4b03c55b8e33787fl,0xef42f975a6384673l,0xff7304f75051b9f0l,
-            0x18aca1dc741c87c2l },
-          { 0x56f120a72d4bfe80l,0xfd823b3d053e732cl,0x11bccfe47537ca16l,
-            0xdf6c9c741b5a996bl },
-          0 },
-        /* 61 << 208 */
-        { { 0x65729b05301ee370l,0x3ed09a2a24c2824cl,0x781ef66a33481977l,
-            0xf2ccdeec193506d0l },
-          { 0x92b4f70d703422d6l,0x7f004a43f80a1b99l,0x47db23607a856445l,
-            0x783a8dd1ce5b0622l },
-          0 },
-        /* 63 << 208 */
-        { { 0x7febefd34e9aac5al,0x601c89e2bdd6173el,0x79b08930c257431el,
-            0x915d601d399ee099l },
-          { 0xfa48347eca02acd2l,0xc33249baeeb7ccedl,0xd76e408755704722l,
-            0xd3709c600dcf4878l },
-          0 },
-        /* 64 << 208 */
-        { { 0xee7332c7904fc3fal,0x14a23f45c7e3636al,0xc38659c3f091d9aal,
-            0x4a995e5db12d8540l },
-          { 0x20a53becf3a5598al,0x56534b17b1eaa995l,0x9ed3dca4bf04e03cl,
-            0x716c563ad8d56268l },
-          0 },
-        /* 65 << 208 */
-        { { 0x963353201580f3adl,0x6c495304b0cd50d4l,0xd035cdc7555ff981l,
-            0xe65cd063c6b6bdfbl },
-          { 0x7deb3cbb437e749cl,0xa9de9f3db5dc24a1l,0xe2e76a2b35c29ffal,
-            0x4d35e261323ba650l },
-          0 },
-        /* 71 << 208 */
-        { { 0x52c46fc8c89e2766l,0x7330b02bb945e5f2l,0xc77ef75c2673ebbcl,
-            0x1740e72657c33783l },
-          { 0xf0312d29623565fbl,0xff9f707af0ca1ed9l,0xb98609ca5ea51a4al,
-            0xde86b9a87b5cc91fl },
-          0 },
-        /* 77 << 208 */
-        { { 0x0dece4badca158b7l,0x5e39baf6a3e9f837l,0xcf14e6dc4d57b640l,
-            0x0548aaa4b67bcbe7l },
-          { 0xb6cf5b393c90e434l,0xf8b3c5645006f3abl,0xa74e92859bf04bd9l,
-            0xf59a3a6bf99c8977l },
-          0 },
-        /* 83 << 208 */
-        { { 0x652ca66ac5b072d5l,0x2102b55993ad4928l,0x1b5f192d88210f9bl,
-            0xb18710144c6ad7e5l },
-          { 0x3979fde3bc0abf13l,0xb5cb4c7dac3fd631l,0x4aedffa6c200ec7bl,
-            0x8aed81ceaddf3610l },
-          0 },
-        /* 89 << 208 */
-        { { 0x72b48105abeefbael,0x0e9e6e41827bb22bl,0xf45ada151e52a848l,
-            0xb8e94579534867a2l },
-          { 0x3a08773b7adb0fdcl,0xe7133a28b83316dfl,0xc8b7b08c5bb41470l,
-            0x28719eb4aaf140c7l },
-          0 },
-        /* 95 << 208 */
-        { { 0x398996cd430007cel,0x20d8c0e07642d616l,0x81566639a7eb2397l,
-            0x74aa0b692e133732l },
-          { 0x326745907ba80aa7l,0x56a491c39bd69d64l,0xc8c8b040e54dcce0l,
-            0x3f991872d571d037l },
-          0 },
-        /* 101 << 208 */
-        { { 0x70e681fa4fb595c9l,0xf0635d6386b4d97bl,0xfc029284c1347081l,
-            0x5a4e9cbe4fee0303l },
-          { 0xd43da8609c31094fl,0x0412cfed6515b4aal,0x10fc06da8d53be86l,
-            0x4b7b380b4bccc94dl },
-          0 },
-        /* 107 << 208 */
-        { { 0x560d57408e7d6738l,0xa82268a8937f12a2l,0x87787b2d3d95b463l,
-            0xb36539b2030e23bfl },
-          { 0x60d16b8fd61e761dl,0x96ba2949fe8efccdl,0x8c170eda667fa7ebl,
-            0xc880d74cf800d7c3l },
-          0 },
-        /* 113 << 208 */
-        { { 0x7c05d6c1efcbfea0l,0xae7ba3291a2f6dd8l,0x521598ed5bd42ecfl,
-            0x58e07842ef0ab40cl },
-          { 0xae65105f66c752a5l,0x4910fba45f99d499l,0xbfdaf5fce9e44357l,
-            0x6aaf4053796ee5b6l },
-          0 },
-        /* 116 << 208 */
-        { { 0xf58fecb16f640f62l,0xe274b92b39f51946l,0x7f4dfc046288af44l,
-            0x0a91f32aeac329e5l },
-          { 0x43ad274bd6aaba31l,0x719a16400f6884f9l,0x685d29f6daf91e20l,
-            0x5ec1cc3327e49d52l },
-          0 },
-        /* 119 << 208 */
-        { { 0x615ac02527ba93edl,0x0d43915d3556ef47l,0x8c739fd1cb0cda89l,
-            0xa2318169625f7a16l },
-          { 0x17d486113e0479cel,0x814beb6038ee541el,0x09c9807fb98ef355l,
-            0x4ad3668752d07af6l },
-          0 },
-        /* 125 << 208 */
-        { { 0x5c1f42e444f3f568l,0xd743b7c078fb409bl,0xe09edccb6224362cl,
-            0x7f13d140c5fe872cl },
-          { 0x85e8cb88f403c0ebl,0x918a231b688d20a0l,0xc65b7ab9f246c73fl,
-            0xda743fbf76dbd6adl },
-          0 },
-    },
-    {
-        /* 0 << 216 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 216 */
-        { { 0xa0158eeae457a477l,0xd19857dbee6ddc05l,0xb326522418c41671l,
-            0x3ffdfc7e3c2c0d58l },
-          { 0x3a3a525426ee7cdal,0x341b0869df02c3a8l,0xa023bf42723bbfc8l,
-            0x3d15002a14452691l },
-          0 },
-        /* 3 << 216 */
-        { { 0xf3cae7e9262a3539l,0x78a49d1d6670d59el,0x37de0f63c1c5e1b9l,
-            0x3072c30c69cb7c1cl },
-          { 0x1d278a5277c850e6l,0x84f15f8f1f6a3de6l,0x46a8bb45592ca7adl,
-            0x1912e3eee4d424b8l },
-          0 },
-        /* 4 << 216 */
-        { { 0x6ba7a92079e5fb67l,0xe1331feb70aa725el,0x5080ccf57df5d837l,
-            0xe4cae01d7ff72e21l },
-          { 0xd9243ee60412a77dl,0x06ff7cacdf449025l,0xbe75f7cd23ef5a31l,
-            0xbc9578220ddef7a8l },
-          0 },
-        /* 5 << 216 */
-        { { 0xdc988086365e668bl,0xada8dcdaaabda5fbl,0xbc146b4c255f1fbel,
-            0x9cfcde29cf34cfc3l },
-          { 0xacbb453e7e85d1e4l,0x9ca09679f92358b5l,0x15fc2d96240823ffl,
-            0x8d65adf70c11d11el },
-          0 },
-        /* 7 << 216 */
-        { { 0x775557f10296f4fdl,0x1dca76a3ea51b436l,0xf3e98f60fb950805l,
-            0x31ff32ea831cf7f1l },
-          { 0x643e7bf18d2c714bl,0x64b5c3392e9d2acal,0xa9fd9ccc6adc2d23l,
-            0xfc2397eccc721b9bl },
-          0 },
-        /* 9 << 216 */
-        { { 0xf031182db48ec57dl,0x515d32f804b233b9l,0x06bbb1d4093aad26l,
-            0x88a142fe0d83d1ecl },
-          { 0x3b95c099245c73f8l,0xb126d4af52edcd32l,0xf8022c1e8fcb52e6l,
-            0x5a51ac4c0106d339l },
-          0 },
-        /* 10 << 216 */
-        { { 0xc589e1ce44ace150l,0xe0f8d3d94381e97cl,0x59e99b1162c5a4b8l,
-            0x90d262f7fd0ec9f9l },
-          { 0xfbc854c9283e13c9l,0x2d04fde7aedc7085l,0x057d776547dcbecbl,
-            0x8dbdf5919a76fa5fl },
-          0 },
-        /* 11 << 216 */
-        { { 0xb7f70a1a7c64a054l,0x0dc1c0df9db43e79l,0x6d0a4ae251fe63d6l,
-            0xe0d5e3327f0c8abfl },
-          { 0xff5500362b7ecee8l,0x3ea0e6f75d055008l,0x30deb62ff24ac84fl,
-            0x936969fd5d7116b7l },
-          0 },
-        /* 13 << 216 */
-        { { 0x02da76122617cf7fl,0xd6e25d4eeee35260l,0xb2fa5b0afd3533e9l,
-            0xe76bb7b0b9126f88l },
-          { 0x692e6a9988856866l,0x3fdf394f49db65cal,0x2529699122d8d606l,
-            0xe815bfbf3dd7c4cfl },
-          0 },
-        /* 15 << 216 */
-        { { 0x69c984ed4d844e7fl,0xd354b2174a2e8a82l,0x25bd4addfb2c4136l,
-            0xf72df4de144b26e1l },
-          { 0xd0aa9db0e6101afdl,0x4445efaae49bd1b8l,0x5dc54eee331593b2l,
-            0xfa35e3b9094bf10bl },
-          0 },
-        /* 16 << 216 */
-        { { 0xdb567d6ac42bd6d2l,0x6df86468bb1f96ael,0x0efe5b1a4843b28el,
-            0x961bbb056379b240l },
-          { 0xb6caf5f070a6a26bl,0x70686c0d328e6e39l,0x80da06cf895fc8d3l,
-            0x804d8810b363fdc9l },
-          0 },
-        /* 17 << 216 */
-        { { 0x660a0f893ea089c3l,0xa25823aac9009b09l,0xb2262d7ba681f5e5l,
-            0x4fc30c8c3413863al },
-          { 0x691544b7c32059f7l,0xf65cf276b21c6134l,0xe3a96b2a5104dabal,
-            0xbb08d109a43ee42fl },
-          0 },
-        /* 19 << 216 */
-        { { 0x85a52d69f9916861l,0x595469a4da4fa813l,0x1dd7786e3338502fl,
-            0x34b8ef2853963ac5l },
-          { 0xc0f019f81a891b25l,0xb619970c4f4bd775l,0x8c2a5af3be19f681l,
-            0x9463db0498ec1728l },
-          0 },
-        /* 21 << 216 */
-        { { 0xeb62c27801f39eabl,0x27de39340ab3a4aal,0xfbd17520a982ca8dl,
-            0x58817ec2e4bdc6edl },
-          { 0x312d78de31c6ac13l,0x9483bf7609202ea6l,0xf64ab8b622c6d8e1l,
-            0xdddf589ce580de74l },
-          0 },
-        /* 23 << 216 */
-        { { 0xe0fa3336ee98a92al,0x7d80eeef66a4d745l,0xb612531bba0119d3l,
-            0x86e770c1b351fe15l },
-          { 0xafbad6f882d5a397l,0x1e5f1cb80dbf0110l,0x25138ac09f79063dl,
-            0x089ed22f2746a156l },
-          0 },
-        /* 25 << 216 */
-        { { 0x198d1b5d7d8b8ddel,0xf32c11078dab37fbl,0xf15fcb6d42b93874l,
-            0x91ddb74f41f94f84l },
-          { 0x6a64540a271524b2l,0x950a0c12758b5a64l,0xf9f237933dce9580l,
-            0xc8edd0ab2cf8ce32l },
-          0 },
-        /* 27 << 216 */
-        { { 0xefc6357eae1046b7l,0xe6704929612932e4l,0xa20305d4b1355b17l,
-            0x88a9136a58b4a156l },
-          { 0xbc379985b4d275ecl,0x718b91316eaf338bl,0x61229a7ad152a509l,
-            0x1109f7c445157ae9l },
-          0 },
-        /* 28 << 216 */
-        { { 0xcf197ca7fb8088fal,0x014272474ddc96c5l,0xa2d2550a30777176l,
-            0x534698984d0cf71dl },
-          { 0x6ce937b83a2aaac6l,0xe9f91dc35af38d9bl,0x2598ad83c8bf2899l,
-            0x8e706ac9b5536c16l },
-          0 },
-        /* 29 << 216 */
-        { { 0x2bde42140df85c2cl,0x4fb839f4058a7a63l,0x7c10572a47f51231l,
-            0x878826231989824el },
-          { 0xa8293d2016e1564al,0xcb11c0f818c04576l,0x83b91e7d9740c631l,
-            0xbdcb23d0cbffcea0l },
-          0 },
-        /* 31 << 216 */
-        { { 0x64bdfd2a9094bfc8l,0x8558acc60fc54d1el,0x3992848faf27721el,
-            0x7a8fcbdaa14cd009l },
-          { 0x6de6120900a4b9c2l,0xbd192b1b20cf8f28l,0x2356b90168d9be83l,
-            0xce1e7a944a49a48al },
-          0 },
-        /* 33 << 216 */
-        { { 0x7630103b6ac189b9l,0x15d35edc6f1f5549l,0x9051799d31cb58edl,
-            0xb4f32694a7a8579el },
-          { 0x6f037435f2abe306l,0xf0595696410fb2f7l,0x2a0d347a5cc98f59l,
-            0x9c19a9a87e3bbd69l },
-          0 },
-        /* 34 << 216 */
-        { { 0x87f8df7c0e58d493l,0xb1ae5ed058b73f12l,0xc368f784dea0c34dl,
-            0x9bd0a120859a91a0l },
-          { 0xb00d88b7cc863c68l,0x3a1cc11e3d1f4d65l,0xea38e0e70aa85593l,
-            0x37f13e987dc4aee8l },
-          0 },
-        /* 35 << 216 */
-        { { 0x91dbe00e49430cd2l,0xcc67c0b17aa8ef6bl,0x769985b8a273f1a5l,
-            0x358371dc360e5dafl },
-          { 0xbf9b9127d6d8b5e8l,0x748ae12cb45588c1l,0x9c609eb556076c58l,
-            0xf287489109733e89l },
-          0 },
-        /* 36 << 216 */
-        { { 0x10d38667bc947badl,0x738e07ce2a36ee2el,0xc93470cdc577fcacl,
-            0xdee1b6162782470dl },
-          { 0x36a25e672e793d12l,0xd6aa6caee0f186dal,0x474d0fd980e07af7l,
-            0xf7cdc47dba8a5cd4l },
-          0 },
-        /* 37 << 216 */
-        { { 0xceb6aa80f8a08fddl,0xd98fc56f46fead7bl,0xe26bd3f8b07b3f1fl,
-            0x3547e9b99d361c3el },
-          { 0x1a89f802e94b8eccl,0x2210a590c0a40ef2l,0xe7e5b965afc01bf2l,
-            0xca3d57fe234b936bl },
-          0 },
-        /* 39 << 216 */
-        { { 0x9230a70db9f9e8cdl,0xa63cebfcb81ba2ecl,0x8482ca87a8f664d6l,
-            0xa8ae78e00b137064l },
-          { 0xb787bd558384c687l,0xfde1d1bdb29ae830l,0xc4a9b2e39f0b7535l,
-            0x7e6c9a15efde2d01l },
-          0 },
-        /* 40 << 216 */
-        { { 0x7d2e5c054f7269b1l,0xfcf30777e287c385l,0x10edc84ff2a46f21l,
-            0x354417574f43fa36l },
-          { 0xf1327899fd703431l,0xa438d7a616dd587al,0x65c34c57e9c8352dl,
-            0xa728edab5cc5a24el },
-          0 },
-        /* 41 << 216 */
-        { { 0xcd6e6db872896d4fl,0x324afa99896c4640l,0x37d18c3d33a292bdl,
-            0x98dba3b44143421fl },
-          { 0x2406f3c949c61b84l,0x402d974754899588l,0xc73b7fd634a485e5l,
-            0x75c9bae08587f0c3l },
-          0 },
-        /* 43 << 216 */
-        { { 0x6c32fa8cb0b4a04dl,0xeb58d0d875fda587l,0x61d8a157c4b86563l,
-            0x92191bf01006b8afl },
-          { 0xd04d3eff32d3478bl,0x3cc52eab2a684fc8l,0xb19a0f1625de54ccl,
-            0x5c5295973620db2dl },
-          0 },
-        /* 44 << 216 */
-        { { 0xa97b51265c3427b0l,0x6401405cd282c9bdl,0x3629f8d7222c5c45l,
-            0xb1c02c16e8d50aedl },
-          { 0xbea2ed75d9635bc9l,0x226790c76e24552fl,0x3c33f2a365f1d066l,
-            0x2a43463e6dfccc2el },
-          0 },
-        /* 45 << 216 */
-        { { 0x09b2e0d3b8da1e01l,0xa3a1a8fee9c0eb04l,0x59af5afe8bf653bal,
-            0xba979f8bd0a54836l },
-          { 0xa0d8194b51ee6ffbl,0x451c29e2f4b0586cl,0x7eb5fddb7471ee3dl,
-            0x84b627d4bcb3afd8l },
-          0 },
-        /* 46 << 216 */
-        { { 0x8cc3453adb483761l,0xe7cc608565d5672bl,0x277ed6cbde3efc87l,
-            0x19f2f36869234eafl },
-          { 0x9aaf43175c0b800bl,0x1f1e7c898b6da6e2l,0x6cfb4715b94ec75el,
-            0xd590dd5f453118c2l },
-          0 },
-        /* 47 << 216 */
-        { { 0xa70e9b0afb54e812l,0x092a0d7d8d86819bl,0x5421ff042e669090l,
-            0x8af770c6b133c952l },
-          { 0xc8e8dd596c8b1426l,0x1c92eb0e9523b483l,0x5a7c88f2cf3d40edl,
-            0x4cc0c04bf5dd98f8l },
-          0 },
-        /* 48 << 216 */
-        { { 0x14e49da11f17a34cl,0x5420ab39235a1456l,0xb76372412f50363bl,
-            0x7b15d623c3fabb6el },
-          { 0xa0ef40b1e274e49cl,0x5cf5074496b1860al,0xd6583fbf66afe5a4l,
-            0x44240510f47e3e9al },
-          0 },
-        /* 49 << 216 */
-        { { 0xb3939a8ffd617288l,0x3d37e5c2d68c2636l,0x4a595fac9d666c0el,
-            0xfebcad9edb3a4978l },
-          { 0x6d284a49c125016fl,0x05a7b9c80ee246a2l,0xe8b351739436c6e9l,
-            0xffb89032d4be40b7l },
-          0 },
-        /* 51 << 216 */
-        { { 0xba1387a5436ebf33l,0xc351a400e8d05267l,0x18645dde4259dbe8l,
-            0x5fc32895c10fd676l },
-          { 0x1ef7a944807f040el,0x9486b5c625738e5fl,0xc9e56cf4a7e3e96cl,
-            0x34c7dc87a20be832l },
-          0 },
-        /* 52 << 216 */
-        { { 0xe10d49996fe8393fl,0x0f809a3fe91f3a32l,0x61096d1c802f63c8l,
-            0x289e146257750d3dl },
-          { 0xed06167e9889feeal,0xd5c9c0e2e0993909l,0x46fca0d856508ac6l,
-            0x918260474f1b8e83l },
-          0 },
-        /* 53 << 216 */
-        { { 0x1d5f2ad7a9bf79cbl,0x228fb24fca9c2f98l,0x5f7c3883701c4b71l,
-            0x18cf76c4ec42d686l },
-          { 0x3680d2e94dcdec8dl,0x6d58e87ba0d60cb6l,0x72fbf086a0e513cfl,
-            0xb922d3c5346ed99al },
-          0 },
-        /* 55 << 216 */
-        { { 0x1678d658c2b9b874l,0x0e0b2c47f6360d4dl,0x01a45c02a0c9b9acl,
-            0x05e82e9d0da69afbl },
-          { 0x50be4001f28b8018l,0x503d967b667d8241l,0x6cd816534981da04l,
-            0x9b18c3117f09c35fl },
-          0 },
-        /* 57 << 216 */
-        { { 0xdfdfd5b409d22331l,0xf445126817f0c6a2l,0xe51d1aa8a5cde27bl,
-            0xb61a12a37aaf9513l },
-          { 0xe43a241d3b3ea114l,0x5c62b624366ae28dl,0x085a530db5f237eal,
-            0x7c4ed375651205afl },
-          0 },
-        /* 59 << 216 */
-        { { 0xf9de879dce842decl,0xe505320a94cedb89l,0xee55dae7f05ad888l,
-            0x44ffbfa7f028b4efl },
-          { 0xa3c1b32e63b2cd31l,0x201a058910c5ab29l,0x20f930afcd4085d6l,
-            0xda79ed169f6ff24bl },
-          0 },
-        /* 60 << 216 */
-        { { 0x7e8cfbcf704e23c6l,0xc71b7d2228aaa65bl,0xa041b2bd245e3c83l,
-            0x69b98834d21854ffl },
-          { 0x89d227a3963bfeecl,0x99947aaade7da7cbl,0x1d9ee9dbee68a9b1l,
-            0x0a08f003698ec368l },
-          0 },
-        /* 61 << 216 */
-        { { 0x04c64f33b0959be5l,0x182332ba396a7fe2l,0x4c5401e302e15b97l,
-            0x92880f9877db104bl },
-          { 0x0bf0b9cc21726a33l,0x780264741acc7b6dl,0x9721f621a26f08e3l,
-            0xe3935b434197fed1l },
-          0 },
-        /* 63 << 216 */
-        { { 0x0bffae503652be69l,0x395a9c6afb3fd5d8l,0x17f66adaa4fadfbfl,
-            0x1ee92a35f9268f8cl },
-          { 0x40ded34d6827781al,0xcd36224e34e63dccl,0xec90cf571cd1ef7al,
-            0xf6067d578f72a3bfl },
-          0 },
-        /* 64 << 216 */
-        { { 0x142b55021a93507al,0xb4cd11878d3c06cfl,0xdf70e76a91ec3f40l,
-            0x484e81ad4e7553c2l },
-          { 0x830f87b5272e9d6el,0xea1c93e5c6ff514al,0x67cc2adcc4192a8el,
-            0xc77e27e242f4535al },
-          0 },
-        /* 65 << 216 */
-        { { 0x537388d299e2f9d2l,0x15ead88612cd6d08l,0x33dfe3a769082d86l,
-            0x0ef25f4266d79d40l },
-          { 0x8035b4e546ba5cf1l,0x4e48f53711eec591l,0x40b56cda122a7aael,
-            0x78e270211dbb79a7l },
-          0 },
-        /* 71 << 216 */
-        { { 0x520b655355b4a5b1l,0xeee835cafb4f5fdel,0xb2ae86e59a823d7fl,
-            0x24325f4fc084497fl },
-          { 0x542bed4e6f0eefa4l,0x2909233b141792fdl,0x74bfc3bfc847a946l,
-            0x8ec1d009e212cb44l },
-          0 },
-        /* 77 << 216 */
-        { { 0xc2082b6d5cedd516l,0xaf148eadeafa3a10l,0x104cd5855ad63aa6l,
-            0xe3fdbf8c78c11e1el },
-          { 0x78651c493c25c24el,0x8064c4f37b7cce0el,0xa55441d4a6d8a928l,
-            0x4525c40eb0db3adcl },
-          0 },
-        /* 83 << 216 */
-        { { 0x5f69e49cfde6001el,0xc61e753aee59b47el,0xd0d4559971b0db5bl,
-            0x7f76f7b45ad4acc3l },
-          { 0xb0318a9c39830897l,0x2b15da22feef3822l,0x34049400acfb0753l,
-            0x16f4fb51a5114ed4l },
-          0 },
-        /* 89 << 216 */
-        { { 0x0b5c76928defbf10l,0xb9f1795cb79cdb6el,0xba17e7759a90317cl,
-            0x3cb69cf950cf514bl },
-          { 0x076cc4c1e5b892ffl,0x75724e8fb548b73cl,0x2ebcdb33248ff2e6l,
-            0x1f12967be109b08fl },
-          0 },
-        /* 95 << 216 */
-        { { 0x3f514c63461b7bb3l,0x3bdca5aa70afbad7l,0x368ce251eab3e38bl,
-            0xdc0fb3300d101049l },
-          { 0x7ce09abdff5013eel,0x926dd7dd7d10729dl,0xe6fe47ab6f486197l,
-            0xd23964eaa6eb6903l },
-          0 },
-        /* 101 << 216 */
-        { { 0x537ceb74eca30797l,0xf171bba557b0f338l,0x220a31fee831f1f8l,
-            0xabbc2c7c5ae6bbbcl },
-          { 0xaf7609f27eadfb60l,0x22cff1d58f28b51bl,0x63c3d76d6d1863bdl,
-            0x3a6a2fb489e8a4c8l },
-          0 },
-        /* 107 << 216 */
-        { { 0x9e74f8beb26e38f0l,0xc4c73fc4ea8bd55bl,0x086f688e1429e1fcl,
-            0x91438ff40f78159fl },
-          { 0x3571ae5f20810acbl,0x305edafe7451eb00l,0x8443c96d5704385cl,
-            0xc03b234e542605b5l },
-          0 },
-        /* 113 << 216 */
-        { { 0x2e5ff4fed85567c2l,0x136f49c7e4abd0c6l,0x5a68730cfb8a62d1l,
-            0x101ebfd030bcb848l },
-          { 0x634b0618fee950bbl,0xfa748d21c8aa65bal,0xc1d67c3e699f5560l,
-            0x6fb0546cb22889d2l },
-          0 },
-        /* 116 << 216 */
-        { { 0xa9784ebd9c95f0f9l,0x5ed9deb224640771l,0x31244af7035561c4l,
-            0x87332f3a7ee857del },
-          { 0x09e16e9e2b9e0d88l,0x52d910f456a06049l,0x507ed477a9592f48l,
-            0x85cb917b2365d678l },
-          0 },
-        /* 119 << 216 */
-        { { 0x6108f2b458a9d40dl,0xb036034838e15a52l,0xcc5610a3fd5625d6l,
-            0x79825dd083b0418el },
-          { 0xf83a95fc6324b6e5l,0x2463114deedfc4ebl,0x58b177e32250707fl,
-            0x778dcd454af8d942l },
-          0 },
-        /* 125 << 216 */
-        { { 0x1ecf2670eb816bf8l,0xa2d6e73aaa6d59c6l,0xf9a11434156852ebl,
-            0x9bc9bb70f6f82c83l },
-          { 0xd23a018d9c874836l,0xd26bf8bc6db5a8b5l,0x1d648846bec0c624l,
-            0x39f15d97ef90302fl },
-          0 },
-    },
-    {
-        /* 0 << 224 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 224 */
-        { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l,
-            0x2c41114ce0cdf943l },
-          { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l,
-            0x20477abf42ff9297l },
-          0 },
-        /* 3 << 224 */
-        { { 0x126f35b51e706ad9l,0xb99cebb4c3a9ebdfl,0xa75389afbf608d90l,
-            0x76113c4fc6c89858l },
-          { 0x80de8eb097e2b5aal,0x7e1022cc63b91304l,0x3bdab6056ccc066cl,
-            0x33cbb144b2edf900l },
-          0 },
-        /* 4 << 224 */
-        { { 0xc41764717af715d2l,0xe2f7f594d0134a96l,0x2c1873efa41ec956l,
-            0xe4e7b4f677821304l },
-          { 0xe5c8ff9788d5374al,0x2b915e6380823d5bl,0xea6bc755b2ee8fe2l,
-            0x6657624ce7112651l },
-          0 },
-        /* 5 << 224 */
-        { { 0x157af101dace5acal,0xc4fdbcf211a6a267l,0xdaddf340c49c8609l,
-            0x97e49f52e9604a65l },
-          { 0x9be8e790937e2ad5l,0x846e2508326e17f1l,0x3f38007a0bbbc0dcl,
-            0xcf03603fb11e16d6l },
-          0 },
-        /* 7 << 224 */
-        { { 0x5ed0c007f8ae7c38l,0x6db07a5c3d740192l,0xbe5e9c2a5fe36db3l,
-            0xd5b9d57a76e95046l },
-          { 0x54ac32e78eba20f2l,0xef11ca8f71b9a352l,0x305e373eff98a658l,
-            0xffe5a100823eb667l },
-          0 },
-        /* 9 << 224 */
-        { { 0x5c8ed8d5da64309dl,0x61a6de5691b30704l,0xd6b52f6a2f9b5808l,
-            0x0eee419498c958a7l },
-          { 0xcddd9aab771e4caal,0x83965dfd78bc21bel,0x02affce3b3b504f5l,
-            0x30847a21561c8291l },
-          0 },
-        /* 10 << 224 */
-        { { 0xd2eb2cf152bfda05l,0xe0e4c4e96197b98cl,0x1d35076cf8a1726fl,
-            0x6c06085b2db11e3dl },
-          { 0x15c0c4d74463ba14l,0x9d292f830030238cl,0x1311ee8b3727536dl,
-            0xfeea86efbeaedc1el },
-          0 },
-        /* 11 << 224 */
-        { { 0xb9d18cd366131e2el,0xf31d974f80fe2682l,0xb6e49e0fe4160289l,
-            0x7c48ec0b08e92799l },
-          { 0x818111d8d1989aa7l,0xb34fa0aaebf926f9l,0xdb5fe2f5a245474al,
-            0xf80a6ebb3c7ca756l },
-          0 },
-        /* 13 << 224 */
-        { { 0x8ea610593de9abe3l,0x404348819cdc03bel,0x9b261245cfedce8cl,
-            0x78c318b4cf5234a1l },
-          { 0x510bcf16fde24c99l,0x2a77cb75a2c2ff5dl,0x9c895c2b27960fb4l,
-            0xd30ce975b0eda42bl },
-          0 },
-        /* 15 << 224 */
-        { { 0x09521177ff57d051l,0x2ff38037fb6a1961l,0xfc0aba74a3d76ad4l,
-            0x7c76480325a7ec17l },
-          { 0x7532d75f48879bc8l,0xea7eacc058ce6bc1l,0xc82176b48e896c16l,
-            0x9a30e0b22c750fedl },
-          0 },
-        /* 16 << 224 */
-        { { 0xc37e2c2e421d3aa4l,0xf926407ce84fa840l,0x18abc03d1454e41cl,
-            0x26605ecd3f7af644l },
-          { 0x242341a6d6a5eabfl,0x1edb84f4216b668el,0xd836edb804010102l,
-            0x5b337ce7945e1d8cl },
-          0 },
-        /* 17 << 224 */
-        { { 0xd2075c77c055dc14l,0x2a0ffa2581d89cdfl,0x8ce815ea6ffdcbafl,
-            0xa3428878fb648867l },
-          { 0x277699cf884655fbl,0xfa5b5bd6364d3e41l,0x01f680c6441e1cb7l,
-            0x3fd61e66b70a7d67l },
-          0 },
-        /* 19 << 224 */
-        { { 0xfd5bb657b1fa70fbl,0xfa07f50fd8073a00l,0xf72e3aa7bca02500l,
-            0xf68f895d9975740dl },
-          { 0x301120605cae2a6al,0x01bd721802874842l,0x3d4238917ce47bd3l,
-            0xa66663c1789544f6l },
-          0 },
-        /* 21 << 224 */
-        { { 0xb4b9a39b36194d40l,0xe857a7c577612601l,0xf4209dd24ecf2f58l,
-            0x82b9e66d5a033487l },
-          { 0xc1e36934e4e8b9ddl,0xd2372c9da42377d7l,0x51dc94c70e3ae43bl,
-            0x4c57761e04474f6fl },
-          0 },
-        /* 23 << 224 */
-        { { 0xa39114e24415503bl,0xc08ff7c64cbb17e9l,0x1eff674dd7dec966l,
-            0x6d4690af53376f63l },
-          { 0xff6fe32eea74237bl,0xc436d17ecd57508el,0x15aa28e1edcc40fel,
-            0x0d769c04581bbb44l },
-          0 },
-        /* 25 << 224 */
-        { { 0xfe51d0296ae55043l,0x8931e98f44a87de1l,0xe57f1cc609e4fee2l,
-            0x0d063b674e072d92l },
-          { 0x70a998b9ed0e4316l,0xe74a736b306aca46l,0xecf0fbf24fda97c7l,
-            0xa40f65cb3e178d93l },
-          0 },
-        /* 27 << 224 */
-        { { 0x8667e981c27253c9l,0x05a6aefb92b36a45l,0xa62c4b369cb7bb46l,
-            0x8394f37511f7027bl },
-          { 0x747bc79c5f109d0fl,0xcad88a765b8cc60al,0x80c5a66b58f09e68l,
-            0xe753d451f6127eacl },
-          0 },
-        /* 28 << 224 */
-        { { 0xc44b74a15b0ec6f5l,0x47989fe45289b2b8l,0x745f848458d6fc73l,
-            0xec362a6ff61c70abl },
-          { 0x070c98a7b3a8ad41l,0x73a20fc07b63db51l,0xed2c2173f44c35f4l,
-            0x8a56149d9acc9dcal },
-          0 },
-        /* 29 << 224 */
-        { { 0x98f178819ac6e0f4l,0x360fdeafa413b5edl,0x0625b8f4a300b0fdl,
-            0xf1f4d76a5b3222d3l },
-          { 0x9d6f5109587f76b8l,0x8b4ee08d2317fdb5l,0x88089bb78c68b095l,
-            0x95570e9a5808d9b9l },
-          0 },
-        /* 31 << 224 */
-        { { 0x2e1284943fb42622l,0x3b2700ac500907d5l,0xf370fb091a95ec63l,
-            0xf8f30be231b6dfbdl },
-          { 0xf2b2f8d269e55f15l,0x1fead851cc1323e9l,0xfa366010d9e5eef6l,
-            0x64d487b0e316107el },
-          0 },
-        /* 33 << 224 */
-        { { 0xc9a9513929607745l,0x0ca07420a26f2b28l,0xcb2790e74bc6f9ddl,
-            0x345bbb58adcaffc0l },
-          { 0xc65ea38cbe0f27a2l,0x67c24d7c641fcb56l,0x2c25f0a7a9e2c757l,
-            0x93f5cdb016f16c49l },
-          0 },
-        /* 34 << 224 */
-        { { 0x2ca5a9d7c5ee30a1l,0xd1593635b909b729l,0x804ce9f3dadeff48l,
-            0xec464751b07c30c3l },
-          { 0x89d65ff39e49af6al,0xf2d6238a6f3d01bcl,0x1095561e0bced843l,
-            0x51789e12c8a13fd8l },
-          0 },
-        /* 35 << 224 */
-        { { 0xd633f929763231dfl,0x46df9f7de7cbddefl,0x01c889c0cb265da8l,
-            0xfce1ad10af4336d2l },
-          { 0x8d110df6fc6a0a7el,0xdd431b986da425dcl,0xcdc4aeab1834aabel,
-            0x84deb1248439b7fcl },
-          0 },
-        /* 36 << 224 */
-        { { 0x8796f1693c2a5998l,0x9b9247b47947190dl,0x55b9d9a511597014l,
-            0x7e9dd70d7b1566eel },
-          { 0x94ad78f7cbcd5e64l,0x0359ac179bd4c032l,0x3b11baaf7cc222ael,
-            0xa6a6e284ba78e812l },
-          0 },
-        /* 37 << 224 */
-        { { 0x8392053f24cea1a0l,0xc97bce4a33621491l,0x7eb1db3435399ee9l,
-            0x473f78efece81ad1l },
-          { 0x41d72fe0f63d3d0dl,0xe620b880afab62fcl,0x92096bc993158383l,
-            0x41a213578f896f6cl },
-          0 },
-        /* 39 << 224 */
-        { { 0x6fb4d4e42bad4d5fl,0xfa4c3590fef0059bl,0x6a10218af5122294l,
-            0x9a78a81aa85751d1l },
-          { 0x04f20579a98e84e7l,0xfe1242c04997e5b5l,0xe77a273bca21e1e4l,
-            0xfcc8b1ef9411939dl },
-          0 },
-        /* 40 << 224 */
-        { { 0xe20ea30292d0487al,0x1442dbec294b91fel,0x1f7a4afebb6b0e8fl,
-            0x1700ef746889c318l },
-          { 0xf5bbffc370f1fc62l,0x3b31d4b669c79ccal,0xe8bc2aaba7f6340dl,
-            0xb0b08ab4a725e10al },
-          0 },
-        /* 41 << 224 */
-        { { 0x44f05701ae340050l,0xba4b30161cf0c569l,0x5aa29f83fbe19a51l,
-            0x1b9ed428b71d752el },
-          { 0x1666e54eeb4819f5l,0x616cdfed9e18b75bl,0x112ed5be3ee27b0bl,
-            0xfbf2831944c7de4dl },
-          0 },
-        /* 43 << 224 */
-        { { 0x722eb104e2b4e075l,0x49987295437c4926l,0xb1e4c0e446a9b82dl,
-            0xd0cb319757a006f5l },
-          { 0xf3de0f7dd7808c56l,0xb5c54d8f51f89772l,0x500a114aadbd31aal,
-            0x9afaaaa6295f6cabl },
-          0 },
-        /* 44 << 224 */
-        { { 0x94705e2104cf667al,0xfc2a811b9d3935d7l,0x560b02806d09267cl,
-            0xf19ed119f780e53bl },
-          { 0xf0227c09067b6269l,0x967b85335caef599l,0x155b924368efeebcl,
-            0xcd6d34f5c497bae6l },
-          0 },
-        /* 45 << 224 */
-        { { 0x1dd8d5d36cceb370l,0x2aeac579a78d7bf9l,0x5d65017d70b67a62l,
-            0x70c8e44f17c53f67l },
-          { 0xd1fc095086a34d09l,0xe0fca256e7134907l,0xe24fa29c80fdd315l,
-            0x2c4acd03d87499adl },
-          0 },
-        /* 46 << 224 */
-        { { 0xbaaf75173b5a9ba6l,0xb9cbe1f612e51a51l,0xd88edae35e154897l,
-            0xe4309c3c77b66ca0l },
-          { 0xf5555805f67f3746l,0x85fc37baa36401ffl,0xdf86e2cad9499a53l,
-            0x6270b2a3ecbc955bl },
-          0 },
-        /* 47 << 224 */
-        { { 0xafae64f5974ad33bl,0x04d85977fe7b2df1l,0x2a3db3ff4ab03f73l,
-            0x0b87878a8702740al },
-          { 0x6d263f015a061732l,0xc25430cea32a1901l,0xf7ebab3ddb155018l,
-            0x3a86f69363a9b78el },
-          0 },
-        /* 48 << 224 */
-        { { 0x349ae368da9f3804l,0x470f07fea164349cl,0xd52f4cc98562baa5l,
-            0xc74a9e862b290df3l },
-          { 0xd3a1aa3543471a24l,0x239446beb8194511l,0xbec2dd0081dcd44dl,
-            0xca3d7f0fc42ac82dl },
-          0 },
-        /* 49 << 224 */
-        { { 0x1f3db085fdaf4520l,0xbb6d3e804549daf2l,0xf5969d8a19ad5c42l,
-            0x7052b13ddbfd1511l },
-          { 0x11890d1b682b9060l,0xa71d3883ac34452cl,0xa438055b783805b4l,
-            0x432412774725b23el },
-          0 },
-        /* 51 << 224 */
-        { { 0x40b08f7443b30ca8l,0xe10b5bbad9934583l,0xe8a546d6b51110adl,
-            0x1dd50e6628e0b6c5l },
-          { 0x292e9d54cff2b821l,0x3882555d47281760l,0x134838f83724d6e3l,
-            0xf2c679e022ddcda1l },
-          0 },
-        /* 52 << 224 */
-        { { 0x40ee88156d2a5768l,0x7f227bd21c1e7e2dl,0x487ba134d04ff443l,
-            0x76e2ff3dc614e54bl },
-          { 0x36b88d6fa3177ec7l,0xbf731d512328fff5l,0x758caea249ba158el,
-            0x5ab8ff4c02938188l },
-          0 },
-        /* 53 << 224 */
-        { { 0x33e1605635edc56dl,0x5a69d3497e940d79l,0x6c4fd00103866dcbl,
-            0x20a38f574893cdefl },
-          { 0xfbf3e790fac3a15bl,0x6ed7ea2e7a4f8e6bl,0xa663eb4fbc3aca86l,
-            0x22061ea5080d53f7l },
-          0 },
-        /* 55 << 224 */
-        { { 0x635a8e5ec3a0ee43l,0x70aaebca679898ffl,0x9ee9f5475dc63d56l,
-            0xce987966ffb34d00l },
-          { 0xf9f86b195e26310al,0x9e435484382a8ca8l,0x253bcb81c2352fe4l,
-            0xa4eac8b04474b571l },
-          0 },
-        /* 57 << 224 */
-        { { 0x2617f91c93aa96b8l,0x0fc8716b7fca2e13l,0xa7106f5e95328723l,
-            0xd1c9c40b262e6522l },
-          { 0xb9bafe8642b7c094l,0x1873439d1543c021l,0xe1baa5de5cbefd5dl,
-            0xa363fc5e521e8affl },
-          0 },
-        /* 59 << 224 */
-        { { 0xbc00fc2f2f8ba2c7l,0x0966eb2f7c67aa28l,0x13f7b5165a786972l,
-            0x3bfb75578a2fbba0l },
-          { 0x131c4f235a2b9620l,0xbff3ed276faf46bel,0x9b4473d17e172323l,
-            0x421e8878339f6246l },
-          0 },
-        /* 60 << 224 */
-        { { 0x0fa8587a25a41632l,0xc0814124a35b6c93l,0x2b18a9f559ebb8dbl,
-            0x264e335776edb29cl },
-          { 0xaf245ccdc87c51e2l,0x16b3015b501e6214l,0xbb31c5600a3882cel,
-            0x6961bb94fec11e04l },
-          0 },
-        /* 61 << 224 */
-        { { 0x3b825b8deff7a3a0l,0xbec33738b1df7326l,0x68ad747c99604a1fl,
-            0xd154c9349a3bd499l },
-          { 0xac33506f1cc7a906l,0x73bb53926c560e8fl,0x6428fcbe263e3944l,
-            0xc11828d51c387434l },
-          0 },
-        /* 63 << 224 */
-        { { 0x659b17c8d8ceb147l,0x9b649eeeb70a5554l,0x6b7fa0b5ac6bc634l,
-            0xd99fe2c71d6e732fl },
-          { 0x30e6e7628d3abba2l,0x18fee6e7a797b799l,0x5c9d360dc696464dl,
-            0xe3baeb4827bfde12l },
-          0 },
-        /* 64 << 224 */
-        { { 0x2bf5db47f23206d5l,0x2f6d34201d260152l,0x17b876533f8ff89al,
-            0x5157c30c378fa458l },
-          { 0x7517c5c52d4fb936l,0xef22f7ace6518cdcl,0xdeb483e6bf847a64l,
-            0xf508455892e0fa89l },
-          0 },
-        /* 65 << 224 */
-        { { 0xf77bb113a74ed3bel,0x89e4eb8f074f2637l,0x7fbfa84df7ce2aebl,
-            0xe7c6ecd5baaefe4cl },
-          { 0x176bba7df6319542l,0x70098120f6080799l,0x2e2118339054d9aal,
-            0x1be4c6a78295a912l },
-          0 },
-        /* 71 << 224 */
-        { { 0x6bb4d8c35df1455fl,0xb839f08f0384b033l,0x718868af11f95d50l,
-            0xae256a92e07a8801l },
-          { 0xa5bafaf24d71a273l,0x18ff04ea2a30e68fl,0x364c193287ba727el,
-            0x4bb8cf99befcaf73l },
-          0 },
-        /* 77 << 224 */
-        { { 0xc79f5b1f4e9fb3d7l,0x52854970a51cccddl,0xa4e27e97f00054a3l,
-            0x26a79792240e1232l },
-          { 0xb15579fecb5ff465l,0x6ef54c3bd1722a84l,0xee211bfa5239a4d8l,
-            0x36c7db27270b7059l },
-          0 },
-        /* 83 << 224 */
-        { { 0x5e7da0a9f9858cd3l,0x67459de5b633de49l,0x2db0d54b2e73892el,
-            0x37f50877adae399al },
-          { 0x83c28b83b65e6179l,0xae5a915ca39faf17l,0x6ab8f3fbe841b53cl,
-            0x7c30997b0df7d004l },
-          0 },
-        /* 89 << 224 */
-        { { 0x87904ca7b3b862bdl,0x7593db93cf9ea671l,0x8a2670f8739aa783l,
-            0x3921d779f5154ca6l },
-          { 0xe81ca56468f65ebbl,0x0c600603bc4e64d4l,0xdf170049cb83b2d1l,
-            0x373893b863487064l },
-          0 },
-        /* 95 << 224 */
-        { { 0x7c3c52b9c0c4e88el,0x0f0484d06f0c2446l,0xeb876827000fe87bl,
-            0xa749b3136d20f94al },
-          { 0x0876dae9d55abda6l,0xe6e4367620726911l,0xf85e8a8c4a2676b4l,
-            0x4e8c97f1b4a890ebl },
-          0 },
-        /* 101 << 224 */
-        { { 0xa992f482a3c0a4f4l,0xe1536f3f7a8d961al,0x26fc79ae000752b0l,
-            0xdbfb706b76ad8508l },
-          { 0x2642b2ed6f4cf9e4l,0xa013db54557fa7e2l,0x2ef711821d326116l,
-            0x8dc3f5bcbafc83ecl },
-          0 },
-        /* 107 << 224 */
-        { { 0x9671258578e5a201l,0xc71aca1de9125569l,0x360c45c0e2231379l,
-            0x2d71783512e82369l },
-          { 0x392432d3d84b2153l,0x502fd3f6d6939ffel,0x33c440ae6e766cacl,
-            0x99f1fbee28062416l },
-          0 },
-        /* 113 << 224 */
-        { { 0xe51ad841861604cbl,0x1ec9c54f630283a7l,0xcc42cad582a39473l,
-            0xa2eb053709929c4al },
-          { 0xe374459767f655a3l,0x9f54c2451d7f2674l,0xd85e9163fbc8aba5l,
-            0x12fd0b55866bc892l },
-          0 },
-        /* 116 << 224 */
-        { { 0x4f2c3063d7bd4661l,0xe533798d57a974ccl,0x44860d503ea02d85l,
-            0xf2a7f4e5acaa0521l },
-          { 0x05593061abb108f0l,0x56d1056044528309l,0x1f674df9c88b6d1el,
-            0x19fdc4cbd8744c4dl },
-          0 },
-        /* 119 << 224 */
-        { { 0xfd1488ec00f2f1d5l,0x24fcc67b44a825ddl,0xc7bfae2ea925a0f4l,
-            0x5e03249cad59cf48l },
-          { 0x1dc5a8e11af4844cl,0x89b2fbc58a598c20l,0xb0f56afff2078121l,
-            0x8194012d4878bb0dl },
-          0 },
-        /* 125 << 224 */
-        { { 0xc1cbe9d3a5ae1031l,0x38da74435706b987l,0x01844b55b353f188l,
-            0x390c59ca87a807c5l },
-          { 0x55ac7b1fb13b780cl,0x060970bff375c1cbl,0x8dd1f378c7ab4e5cl,
-            0xcca782e5cf726645l },
-          0 },
-    },
-    {
-        /* 0 << 232 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 232 */
-        { { 0x91213462f23f2d92l,0x6cab71bd60b94078l,0x6bdd0a63176cde20l,
-            0x54c9b20cee4d54bcl },
-          { 0x3cd2d8aa9f2ac02fl,0x03f8e617206eedb0l,0xc7f68e1693086434l,
-            0x831469c592dd3db9l },
-          0 },
-        /* 3 << 232 */
-        { { 0x4a9090cde36d0757l,0xf722d7b1d9a29382l,0xfb7fb04c04b48ddfl,
-            0x628ad2a7ebe16f43l },
-          { 0xcd3fbfb520226040l,0x6c34ecb15104b6c4l,0x30c0754ec903c188l,
-            0xec336b082d23cab0l },
-          0 },
-        /* 4 << 232 */
-        { { 0x9f51439e558df019l,0x230da4baac712b27l,0x518919e355185a24l,
-            0x4dcefcdd84b78f50l },
-          { 0xa7d90fb2a47d4c5al,0x55ac9abfb30e009el,0xfd2fc35974eed273l,
-            0xb72d824cdbea8fafl },
-          0 },
-        /* 5 << 232 */
-        { { 0xd213f923cbb13d1bl,0x98799f425bfb9bfel,0x1ae8ddc9701144a9l,
-            0x0b8b3bb64c5595eel },
-          { 0x0ea9ef2e3ecebb21l,0x17cb6c4b3671f9a7l,0x47ef464f726f1d1fl,
-            0x171b94846943a276l },
-          0 },
-        /* 7 << 232 */
-        { { 0xc9941109a607419dl,0xfaa71e62bb6bca80l,0x34158c1307c431f3l,
-            0x594abebc992bc47al },
-          { 0x6dfea691eb78399fl,0x48aafb353f42cba4l,0xedcd65af077c04f0l,
-            0x1a29a366e884491al },
-          0 },
-        /* 9 << 232 */
-        { { 0x7bf6a5c1f7ea25aal,0xd165e6bffbb07d5fl,0xe353936189e78671l,
-            0xa3fcac892bac4219l },
-          { 0xdfab6fd4f0baa8abl,0x5a4adac1e2c1c2e5l,0x6cd75e3140d85849l,
-            0xce263fea19b39181l },
-          0 },
-        /* 10 << 232 */
-        { { 0xb8d804a3315980cdl,0x693bc492fa3bebf7l,0x3578aeee2253c504l,
-            0x158de498cd2474a2l },
-          { 0x1331f5c7cfda8368l,0xd2d7bbb378d7177el,0xdf61133af3c1e46el,
-            0x5836ce7dd30e7be8l },
-          0 },
-        /* 11 << 232 */
-        { { 0xe042ece59a29a5c5l,0xb19b3c073b6c8402l,0xc97667c719d92684l,
-            0xb5624622ebc66372l },
-          { 0x0cb96e653c04fa02l,0x83a7176c8eaa39aal,0x2033561deaa1633fl,
-            0x45a9d0864533df73l },
-          0 },
-        /* 13 << 232 */
-        { { 0xa29ae9df5ece6e7cl,0x0603ac8f0facfb55l,0xcfe85b7adda233a5l,
-            0xe618919fbd75f0b8l },
-          { 0xf555a3d299bf1603l,0x1f43afc9f184255al,0xdcdaf341319a3e02l,
-            0xd3b117ef03903a39l },
-          0 },
-        /* 15 << 232 */
-        { { 0xb6b82fa74d82f4c2l,0x90725a606804efb3l,0xbc82ec46adc3425el,
-            0xb7b805812787843el },
-          { 0xdf46d91cdd1fc74cl,0xdc1c62cbe783a6c4l,0x59d1b9f31a04cbbal,
-            0xd87f6f7295e40764l },
-          0 },
-        /* 16 << 232 */
-        { { 0x196860411e84e0e5l,0xa5db84d3aea34c93l,0xf9d5bb197073a732l,
-            0xb8d2fe566bcfd7c0l },
-          { 0x45775f36f3eb82fal,0x8cb20cccfdff8b58l,0x1659b65f8374c110l,
-            0xb8b4a422330c789al },
-          0 },
-        /* 17 << 232 */
-        { { 0xa6312c9e8977d99bl,0xbe94433183f531e7l,0x8232c0c218d3b1d4l,
-            0x617aae8be1247b73l },
-          { 0x40153fc4282aec3bl,0xc6063d2ff7b8f823l,0x68f10e583304f94cl,
-            0x31efae74ee676346l },
-          0 },
-        /* 19 << 232 */
-        { { 0xd98bf2a43734e520l,0x5e3abbe3209bdcbal,0x77c76553bc945b35l,
-            0x5331c093c6ef14aal },
-          { 0x518ffe2976b60c80l,0x2285593b7ace16f8l,0xab1f64ccbe2b9784l,
-            0xe8f2c0d9ab2421b6l },
-          0 },
-        /* 21 << 232 */
-        { { 0x481dae5fd5ecfefcl,0x07084fd8c2bff8fcl,0x8040a01aea324596l,
-            0x4c646980d4de4036l },
-          { 0x9eb8ab4ed65abfc3l,0xe01cb91f13541ec7l,0x8f029adbfd695012l,
-            0x9ae284833c7569ecl },
-          0 },
-        /* 23 << 232 */
-        { { 0xc83605f6f10ff927l,0xd387145123739fc6l,0x6d163450cac1c2ccl,
-            0x6b521296a2ec1ac5l },
-          { 0x0606c4f96e3cb4a5l,0xe47d3f41778abff7l,0x425a8d5ebe8e3a45l,
-            0x53ea9e97a6102160l },
-          0 },
-        /* 25 << 232 */
-        { { 0x6b72fab526bc2797l,0x13670d1699f16771l,0x001700521e3e48d1l,
-            0x978fe401b7adf678l },
-          { 0x55ecfb92d41c5dd4l,0x5ff8e247c7b27da5l,0xe7518272013fb606l,
-            0x5768d7e52f547a3cl },
-          0 },
-        /* 27 << 232 */
-        { { 0x0e966e64c73b2383l,0x49eb3447d17d8762l,0xde1078218da05dabl,
-            0x443d8baa016b7236l },
-          { 0x163b63a5ea7610d6l,0xe47e4185ce1ca979l,0xae648b6580baa132l,
-            0xebf53de20e0d5b64l },
-          0 },
-        /* 28 << 232 */
-        { { 0x6ba535da9a85788bl,0xd21f03aebd0626d4l,0x099f8c47e873dc64l,
-            0xcda8564d018ec97el },
-          { 0x3e8d7a5cde92c68cl,0x78e035a173323cc4l,0x3ef26275f880ff7cl,
-            0xa4ee3dff273eedaal },
-          0 },
-        /* 29 << 232 */
-        { { 0x8bbaec49571d92acl,0x569e85fe4692517fl,0x8333b014a14ea4afl,
-            0x32f2a62f12e5c5adl },
-          { 0x98c2ce3a06d89b85l,0xb90741aa2ff77a08l,0x2530defc01f795a2l,
-            0xd6e5ba0b84b3c199l },
-          0 },
-        /* 31 << 232 */
-        { { 0x3d1b24cb28c682c6l,0x27f252288612575bl,0xb587c779e8e66e98l,
-            0x7b0c03e9405eb1fel },
-          { 0xfdf0d03015b548e7l,0xa8be76e038b36af7l,0x4cdab04a4f310c40l,
-            0x6287223ef47ecaecl },
-          0 },
-        /* 33 << 232 */
-        { { 0x0a4c6f3670ad54aal,0xc24cfd0d2a543909l,0xe1b0bc5b745c1a97l,
-            0xb8431cfd68f0ddbfl },
-          { 0x326357989ed8cb06l,0xa00a80ff759d2b7dl,0x81f335c190570e02l,
-            0xbfccd89849c4e4d9l },
-          0 },
-        /* 34 << 232 */
-        { { 0x4dcb646bfd16d8c4l,0x76a6b640e38ba57bl,0xd92de1f79d8ae7e2l,
-            0x126f48f13f77f23bl },
-          { 0xb7b53ca977e8abc2l,0x3faa17112c0787ffl,0xf8f9308c8e5762f8l,
-            0x600a8a7f6b83aea8l },
-          0 },
-        /* 35 << 232 */
-        { { 0xa2aed4a799aa03c0l,0x1f93b93da18b79c5l,0x7b4550b7314192c3l,
-            0x9da00676272bb08el },
-          { 0xe42f0d7e23e072edl,0x7ce76494888b5783l,0x4c7900203680b63bl,
-            0x6040c83f662a8718l },
-          0 },
-        /* 36 << 232 */
-        { { 0xba9e5c88a56d73edl,0x6c24f7712ca054d3l,0x4a37c235083beae1l,
-            0x04a883b26483e9fdl },
-          { 0x0c63f3aee27c2c5dl,0x0e1da88dae4671f1l,0xa577e8e25995e1dbl,
-            0xbfc4b1b16ed6066al },
-          0 },
-        /* 37 << 232 */
-        { { 0x8b398541f53d9e63l,0x4ab045bb019395cbl,0x69a1b90371dd70c7l,
-            0xdedf284b38aaa431l },
-          { 0xb45e245aaed3efe7l,0x49460905079f2facl,0xde4dee470845bd78l,
-            0x0540524039d02ec3l },
-          0 },
-        /* 39 << 232 */
-        { { 0x300cf051675cc986l,0x758afea99324219fl,0xf524c3fad5a93b5fl,
-            0xb73385abc3864a8al },
-          { 0xbde19289f6be9050l,0xbb9018558205a3f3l,0x99a9d14d229f6b89l,
-            0x4c3a802f4336e68fl },
-          0 },
-        /* 40 << 232 */
-        { { 0xdd4a12d8e12b31f8l,0x577e29bc177736e6l,0x2353722ba88935e8l,
-            0xca1d3729015f286dl },
-          { 0x86c7b6a239a3e035l,0x6e5250bfd3b03a9fl,0x79d98930fd0d536el,
-            0x8c4cbbabfa0c3832l },
-          0 },
-        /* 41 << 232 */
-        { { 0x92ecff374f8e6163l,0x171cc8830f35faeal,0xc5434242bcd36142l,
-            0x707049adb28b63bbl },
-          { 0xa1f4d1dbf6443da9l,0x002bb062dabc108bl,0x17287f171a272b08l,
-            0x2a3aac8c884cf6bbl },
-          0 },
-        /* 43 << 232 */
-        { { 0x55524645651c0a5al,0x14624a9703cf0d12l,0xca9315a8f884a9e2l,
-            0x9840c6e2df7c9d59l },
-          { 0xd96bd10a7438e8d5l,0x12be73d2b2f887del,0x5e47445dca2493efl,
-            0x85aef555e9fff03el },
-          0 },
-        /* 44 << 232 */
-        { { 0x169b38c9a43b2339l,0x884308d91732bfabl,0xe4b593a28ff202ddl,
-            0xaf51d11f1e65376cl },
-          { 0x6ec648de741525ffl,0xf93cbd369ff4c628l,0xc76df9efb1129c79l,
-            0x31a5f2e2b7a67294l },
-          0 },
-        /* 45 << 232 */
-        { { 0x0661bc02801d0e38l,0x4a37dc0e71fc46b7l,0x0b224cfc80c3e311l,
-            0x2dd3d2779646a957l },
-          { 0xfa45aa18ef524012l,0x5d2a2d0916185a09l,0x34d5c630b5313dcel,
-            0xd9581ed151e4cf84l },
-          0 },
-        /* 46 << 232 */
-        { { 0x5845aa4a8ebd2af8l,0x141404ecd3df43ccl,0xff3fc7681ffd48d9l,
-            0x8a096e72e0cefb65l },
-          { 0xc9c81cfdffc3a5cdl,0x7550aa3029b27cf9l,0x34dca72b65fa0380l,
-            0xe8c5f6059ddd032bl },
-          0 },
-        /* 47 << 232 */
-        { { 0xe53da8a46bfbadb3l,0x4a9dfa55afaeeb5el,0x076245ea6644b1d4l,
-            0xc19be4012307bbcbl },
-          { 0x097774c19d77318bl,0xacc8a1519cfd51c4l,0x736ef6b3ecaa7b08l,
-            0x107479132d643a80l },
-          0 },
-        /* 48 << 232 */
-        { { 0x2d500910cab91f1el,0xbedd9e444d1cd216l,0xd634b74fedd02252l,
-            0xbd60f8e11258617al },
-          { 0xd8c7537b9e05614al,0xfd26c766e7af5fc5l,0x0660b581582bd926l,
-            0x87019244acf07fc8l },
-          0 },
-        /* 49 << 232 */
-        { { 0xd4889fdf6220ae8el,0x745d67ec1abf1549l,0x957b2e3d2fb89c36l,
-            0x9768c90edc62ada9l },
-          { 0x90332fd748e6c46el,0x5aa5a4e54e90ef0dl,0x58838fd3ddcc8571l,
-            0xd12f6c6f9a721126l },
-          0 },
-        /* 51 << 232 */
-        { { 0x2f0fd0b2cec757bal,0x46a7a9c63032cd1dl,0x9af3a600547d7a77l,
-            0x828e16eca43da1bal },
-          { 0x0b303a66092a8d92l,0x78ba0389c23d08bal,0x52aed08d4616bd29l,
-            0x4c0ff1210539c9fal },
-          0 },
-        /* 52 << 232 */
-        { { 0x2c3b7322badcfe8el,0x6e0616fac5e25a04l,0x0a3c12753da6e4a2l,
-            0xe46c957e077bca01l },
-          { 0xb46ca4e3da4be64bl,0xa59bda668e75ee78l,0x41835184a4de98f2l,
-            0x6efb1f924ed6a568l },
-          0 },
-        /* 53 << 232 */
-        { { 0xbb8cdc094af1dd72l,0x93c0aa38a2460633l,0xf66f5d238a7ebc93l,
-            0x43ecda843e8e37a6l },
-          { 0x399da8265fd5139el,0x8b39930fd446f38el,0x114414135d2b68efl,
-            0x8be163b8d1637c38l },
-          0 },
-        /* 55 << 232 */
-        { { 0x488e2a35b70ddbd3l,0xb4aa5f718da50077l,0xb38b74b1d8752bbdl,
-            0x7007f328416106a3l },
-          { 0xe6a62e4fcec4ea68l,0x9fdfb79741ef920bl,0x1a19d7dfe3c337a6l,
-            0x08f643558be0f586l },
-          0 },
-        /* 57 << 232 */
-        { { 0x91a5d8ff60343a1fl,0x921e442173ef8cdfl,0x4358f27b975138cdl,
-            0x36fd8577a4992b08l },
-          { 0xc07c8ca1f8d044c6l,0xcf42903687747b6bl,0x0932ffb0867c8632l,
-            0x7e565213250e5a89l },
-          0 },
-        /* 59 << 232 */
-        { { 0xae7c3b9b06255feal,0x2eb1d9a78a6fe229l,0xf81548e77601e6f8l,
-            0x777394eb7bd96d6cl },
-          { 0x54734187000a3509l,0xaeec146492d43c04l,0xc9b7f0d7c428b4acl,
-            0x9d4bcedccd7f7018l },
-          0 },
-        /* 60 << 232 */
-        { { 0x4741b9b311370605l,0x47fa72f75d09b355l,0x391a71ac7a144c6al,
-            0x0808c0f498b6e3cal },
-          { 0x7eaed9ef7fe53900l,0xf157a2a5e5a830bal,0xd13ec09127974afcl,
-            0x78d710a70b87997dl },
-          0 },
-        /* 61 << 232 */
-        { { 0xcbb96ecb4e263f81l,0x093e0d1509084351l,0x7af3232629220a81l,
-            0xd721b415c60f36dcl },
-          { 0xe3340a87fe9387a1l,0x6088bf482ff2b126l,0xd31028f1d2bc982cl,
-            0x9794e106630d52cbl },
-          0 },
-        /* 63 << 232 */
-        { { 0x1dac76780b11e972l,0x46e814c62698dafel,0x553f7370c37640d6l,
-            0xdcf588cc51cede93l },
-          { 0x4d6b56d3c3f6215bl,0x07edc6621b8f8f03l,0xdfef9d60b9a5dfbcl,
-            0x377edf4d10af7a5bl },
-          0 },
-        /* 64 << 232 */
-        { { 0x8928e99aeeaf8c49l,0xee7aa73d6e24d728l,0x4c5007c2e72b156cl,
-            0x5fcf57c5ed408a1dl },
-          { 0x9f719e39b6057604l,0x7d343c01c2868bbfl,0x2cca254b7e103e2dl,
-            0xe6eb38a9f131bea2l },
-          0 },
-        /* 65 << 232 */
-        { { 0x26ae28bede7a4b7el,0xd2f07569d2664163l,0x798690d4ff69266al,
-            0x77093d356ef3695dl },
-          { 0xaca9903d567dd3dfl,0x259c59a3a274c67bl,0x9f34bc0bfc1198b0l,
-            0x51a7726290b1521cl },
-          0 },
-        /* 71 << 232 */
-        { { 0xa20644bc80ca5391l,0xf9cdb4f7e5b36ea3l,0xe7936c0641426e22l,
-            0x39bc23033eef8a52l },
-          { 0x31253f43e5d8f896l,0xb0e5a588dc3df499l,0x1d03519a2d7e66d5l,
-            0x923de91f6d7da5e3l },
-          0 },
-        /* 77 << 232 */
-        { { 0x17a833ffedf861e4l,0x0ee3d0af4ebec965l,0xd0fac1c1ea66870el,
-            0x325756d0ae810cf4l },
-          { 0x4ed78d2c78e9a415l,0x6cc65685192046e4l,0x03e4243d8498a91el,
-            0x56a02dd25ab97794l },
-          0 },
-        /* 83 << 232 */
-        { { 0xc2fd373748e2b156l,0x259e9a98139645bel,0xe90106fb9877b4f1l,
-            0x49e5bac5889ce002l },
-          { 0x936a7dd18cf14e0bl,0x70bf6d304e3a8a01l,0x99d3e8bfeb748b62l,
-            0xa52a27c99b31c55cl },
-          0 },
-        /* 89 << 232 */
-        { { 0x9db1d41d300637d5l,0xe38744397c2dd836l,0x36179baf0d04ceb3l,
-            0xe9ccd17b251b3f2dl },
-          { 0xd8228073442b6d1dl,0x59a038363eed2971l,0xb443732046979f5cl,
-            0x54ad4113ae63937cl },
-          0 },
-        /* 95 << 232 */
-        { { 0x092c34e6d9246e9fl,0xb4b3b63d3eeb18a7l,0x8b3778beed9d1383l,
-            0xe4cb7be9d70d5d80l },
-          { 0xcff12e9b3d059203l,0x277af117ba86699fl,0x9bd4e8e363603585l,
-            0x0750b0f28e89c8d5l },
-          0 },
-        /* 101 << 232 */
-        { { 0x38b77e5958f7187bl,0x31c7068de0cb618el,0xa0f8e0d6c11ebe62l,
-            0x07adc8010473d7ebl },
-          { 0x36161a2c5c3e9510l,0xb2ec90d64ad04815l,0x01e2dd1f917d8166l,
-            0x549bcbdd6aa0f794l },
-          0 },
-        /* 107 << 232 */
-        { { 0x4ab27c3a8e4e45e5l,0xf6bd9d82f2bb99e7l,0xcab48c735e9da59fl,
-            0xdeb09eb2b9727353l },
-          { 0xc4a7954bafb8fa3el,0x34af2a49abf6803dl,0xc1ee1416d63e13bbl,
-            0xd49bf42d7a949193l },
-          0 },
-        /* 113 << 232 */
-        { { 0x504823ea9c9c07c6l,0x9dbec902bee2288cl,0x018d7875f0ceb6bbl,
-            0x678b997304f7022cl },
-          { 0x74d658238c5fb369l,0x7d4e1f114ca89ee8l,0x148316399905abc0l,
-            0xc107324e2c4deff4l },
-          0 },
-        /* 116 << 232 */
-        { { 0x1bc4fa8bdadc4404l,0x0edb9534daa12ee3l,0x084481b6a5f7289cl,
-            0x7f42461d9d8fb3d2l },
-          { 0xf93f1d3212293c70l,0xc14706596bb73ea3l,0xf80834afde339cadl,
-            0x99dcfc0081f22953l },
-          0 },
-        /* 119 << 232 */
-        { { 0x497e544f9fca737el,0x7f6342210e91e1afl,0x638e500c78d7b20bl,
-            0xb1ffed3f7ebaa947l },
-          { 0x751aa54871086f83l,0x8100bb703cf97848l,0xc32f91ace19ad68fl,
-            0x7dffb6851fb9157el },
-          0 },
-        /* 125 << 232 */
-        { { 0x5108589778e25060l,0x33e3cb7316cfe6cbl,0x0884cb8d410c0822l,
-            0xaa806ecc0be3fc94l },
-          { 0x9f9121f5f692353el,0xb9ab0310f8ee3349l,0x390032ce2561973el,
-            0xc07b6c6c8856b766l },
-          0 },
-    },
-    {
-        /* 0 << 240 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 240 */
-        { { 0x1083e2ea1f095615l,0x0a28ad7714e68c33l,0x6bfc02523d8818bel,
-            0xb585113af35850cdl },
-          { 0x7d935f0b30df8aa1l,0xaddda07c4ab7e3acl,0x92c34299552f00cbl,
-            0xc33ed1de2909df6cl },
-          0 },
-        /* 3 << 240 */
-        { { 0xabe7905a83cdd60el,0x50602fb5a1170184l,0x689886cdb023642al,
-            0xd568d090a6e1fb00l },
-          { 0x5b1922c70259217fl,0x93831cd9c43141e4l,0xdfca35870c95f86el,
-            0xdec2057a568ae828l },
-          0 },
-        /* 4 << 240 */
-        { { 0x568f8925913cc16dl,0x18bc5b6de1a26f5al,0xdfa413bef5f499ael,
-            0xf8835decc3f0ae84l },
-          { 0xb6e60bd865a40ab0l,0x65596439194b377el,0xbcd8562592084a69l,
-            0x5ce433b94f23ede0l },
-          0 },
-        /* 5 << 240 */
-        { { 0x860d523d42e06189l,0xbf0779414e3aff13l,0x0b616dcac1b20650l,
-            0xe66dd6d12131300dl },
-          { 0xd4a0fd67ff99abdel,0xc9903550c7aac50dl,0x022ecf8b7c46b2d7l,
-            0x3333b1e83abf92afl },
-          0 },
-        /* 7 << 240 */
-        { { 0xefecdef7be42a582l,0xd3fc608065046be6l,0xc9af13c809e8dba9l,
-            0x1e6c9847641491ffl },
-          { 0x3b574925d30c31f7l,0xb7eb72baac2a2122l,0x776a0dacef0859e7l,
-            0x06fec31421900942l },
-          0 },
-        /* 9 << 240 */
-        { { 0x7ec62fbbf4737f21l,0xd8dba5ab6209f5acl,0x24b5d7a9a5f9adbel,
-            0x707d28f7a61dc768l },
-          { 0x7711460bcaa999eal,0xba7b174d1c92e4ccl,0x3c4bab6618d4bf2dl,
-            0xb8f0c980eb8bd279l },
-          0 },
-        /* 10 << 240 */
-        { { 0x9d658932790691bfl,0xed61058906b736ael,0x712c2f04c0d63b6el,
-            0x5cf06fd5c63d488fl },
-          { 0x97363facd9588e41l,0x1f9bf7622b93257el,0xa9d1ffc4667acacel,
-            0x1cf4a1aa0a061ecfl },
-          0 },
-        /* 11 << 240 */
-        { { 0x28d675b2c0519a23l,0x9ebf94fe4f6952e3l,0xf28bb767a2294a8al,
-            0x85512b4dfe0af3f5l },
-          { 0x18958ba899b16a0dl,0x95c2430cba7548a7l,0xb30d1b10a16be615l,
-            0xe3ebbb9785bfb74cl },
-          0 },
-        /* 13 << 240 */
-        { { 0x81eeb865d2fdca23l,0x5a15ee08cc8ef895l,0x768fa10a01905614l,
-            0xeff5b8ef880ee19bl },
-          { 0xf0c0cabbcb1c8a0el,0x2e1ee9cdb8c838f9l,0x0587d8b88a4a14c0l,
-            0xf6f278962ff698e5l },
-          0 },
-        /* 15 << 240 */
-        { { 0x9c4b646e9e2fce99l,0x68a210811e80857fl,0x06d54e443643b52al,
-            0xde8d6d630d8eb843l },
-          { 0x7032156342146a0al,0x8ba826f25eaa3622l,0x227a58bd86138787l,
-            0x43b6c03c10281d37l },
-          0 },
-        /* 16 << 240 */
-        { { 0x02b37a952f41deffl,0x0e44a59ae63b89b7l,0x673257dc143ff951l,
-            0x19c02205d752baf4l },
-          { 0x46c23069c4b7d692l,0x2e6392c3fd1502acl,0x6057b1a21b220846l,
-            0xe51ff9460c1b5b63l },
-          0 },
-        /* 17 << 240 */
-        { { 0x7aca2632f02fc0f0l,0xb92b337dc7f01c86l,0x624bc4bf5afbdc7dl,
-            0x812b07bc4de21a5el },
-          { 0x29d137240b2090ccl,0x0403c5095a1b2132l,0x1dca34d50e35e015l,
-            0xf085ed7d3bbbb66fl },
-          0 },
-        /* 19 << 240 */
-        { { 0xc27b98f9f781e865l,0x51e1f692994e1345l,0x0807d516e19361eel,
-            0x13885ceffb998aefl },
-          { 0xd223d5e92f0f8a17l,0x48672010e8d20280l,0x6f02fd60237eac98l,
-            0xcc51bfad9ada7ee7l },
-          0 },
-        /* 21 << 240 */
-        { { 0x2756bcdd1e09701dl,0x94e31db990d45c80l,0xb9e856a98566e584l,
-            0x4f87d9deab10e3f3l },
-          { 0x166ecb373ded9cb2l,0xfd14c7073f653d3el,0x105d049b92aec425l,
-            0x7f657e4909a42e11l },
-          0 },
-        /* 23 << 240 */
-        { { 0xea6490076a159594l,0x3e424d6b1f97ce52l,0xac6df30a185e8ccbl,
-            0xad56ec80517747bfl },
-          { 0xf0935ccf4391fe93l,0x866b260f03811d40l,0x792047b99f7b9abel,
-            0xb1600bc88ee42d84l },
-          0 },
-        /* 25 << 240 */
-        { { 0x2d97b3db7768a85fl,0x2b78f6334287e038l,0x86c947676f892bb1l,
-            0x920bfb1ac0a9c200l },
-          { 0x4292f6ec332041b2l,0xa30bb937c9989d54l,0x39f941ebc6d5879el,
-            0x76a450fcdfdbb187l },
-          0 },
-        /* 27 << 240 */
-        { { 0x31256089ee430db6l,0xaece9bd8f6836f56l,0x484cfc4bfb85a046l,
-            0xee1e3e2c1599b2b9l },
-          { 0x7e3c38903d122eafl,0xaa940ce0c770556cl,0x4802d6631b08fae8l,
-            0xb08a85807f69f8bal },
-          0 },
-        /* 28 << 240 */
-        { { 0x70ed0a0405411eael,0x60deb08f16494c66l,0x8cf20fc6133797bbl,
-            0x3e30f4f50c6bc310l },
-          { 0x1a677c29749c46c7l,0xfe1d93f4f11e981cl,0x937303d82e3e688bl,
-            0x01aef5a7a6aa9e85l },
-          0 },
-        /* 29 << 240 */
-        { { 0x4902f495b959b920l,0x13b0fdbdfca2d885l,0x41cbd9e7b6a2f0fal,
-            0xf9bdf11056430b87l },
-          { 0xd705a223954d19b9l,0x74d0fc5c972a4fdel,0xcbcbfed6912977eal,
-            0x870611fdcc59a5afl },
-          0 },
-        /* 31 << 240 */
-        { { 0xf4f19bd04089236al,0x3b206c12313d0e0bl,0x73e70df303feaeb2l,
-            0x09dba0eb9bd1efe0l },
-          { 0x4c7fd532fc4e5305l,0xd792ffede93d787al,0xc72dc4e2e4245010l,
-            0xe7e0d47d0466bbbdl },
-          0 },
-        /* 33 << 240 */
-        { { 0x549c861983e4f8bbl,0xf70133fbd8e06829l,0xc962b8e28c64e849l,
-            0xad87f5b1901e4c25l },
-          { 0xd005bde568a1cab5l,0x6a591acf0d2a95bal,0x728f14ce30ebcae4l,
-            0x303cec99a3459b0fl },
-          0 },
-        /* 34 << 240 */
-        { { 0x62e62f258350e6bcl,0x5a5ea94d96adba1fl,0x36c2a2844a23c7b3l,
-            0x32f50a72992f5c8bl },
-          { 0x55d685204136c6afl,0x1aafd32992794f20l,0x69f5d820b59aa9bfl,
-            0x218966a8570e209al },
-          0 },
-        /* 35 << 240 */
-        { { 0xf3204feb2f9a31fcl,0x77f33a360429f463l,0xfb9f3a5a59a1d6a7l,
-            0x4445a2e93b1a78e0l },
-          { 0xc77a9b6fd58e32d3l,0xa44e23c8302e6390l,0x7d8e00b4c0f7bcb0l,
-            0xd2e2237b0ffa46f4l },
-          0 },
-        /* 36 << 240 */
-        { { 0xb3046cb13c8ea6d3l,0xf0151b5efce2f445l,0xa968e60b55e5715el,
-            0x39e52662587dce61l },
-          { 0xfde176e0b7de2862l,0x298d83e68e8db497l,0x1042136773641bfbl,
-            0xd72ac78d36e0bb0dl },
-          0 },
-        /* 37 << 240 */
-        { { 0x2cabb94fff6b8340l,0xf425a35a21771acbl,0x564fec3d12c4a758l,
-            0x57a61af39ba8f281l },
-          { 0x5807e78c97e9a71dl,0x991d9be75b8314e6l,0x1cd90b16ec4133b9l,
-            0xff043efa0f1ac621l },
-          0 },
-        /* 39 << 240 */
-        { { 0xea6e5527d7e58321l,0xfb95c13c04056ff1l,0x9447361f2fc4e732l,
-            0x63cbc655786d0154l },
-          { 0x302c0d668610fb71l,0xbf692d6920d06613l,0x8465b74b4be8355al,
-            0xcc883c95c31356b7l },
-          0 },
-        /* 40 << 240 */
-        { { 0x4ab6e919b33eabcal,0xb58f0998a1acacbfl,0xa747e5782ddbc28fl,
-            0xf9dd04ca59866cbcl },
-          { 0x084c062ff7a0073fl,0x6d22acdfb577fc38l,0x0870ee08eacd907cl,
-            0x710b4b266c9fcf95l },
-          0 },
-        /* 41 << 240 */
-        { { 0xa99546faf1c835a7l,0x1514a5a30d59f933l,0x1f6ad0f81bedd730l,
-            0x24de76287b528aaal },
-          { 0x4d9e7845c02fff87l,0xba74f8a942c79e67l,0x5bf5015f476e285bl,
-            0x0b1a5d8b1b93b364l },
-          0 },
-        /* 43 << 240 */
-        { { 0x8c7c0d7ff839819fl,0xc82b819827a95965l,0xce7294d377270519l,
-            0xfb508d6cad47aff7l },
-          { 0xf6de15431035076al,0x697d60ac5dd465c6l,0x88d771b8a76dcd26l,
-            0x8c7ce11ab10c9c44l },
-          0 },
-        /* 44 << 240 */
-        { { 0x215ea44a08216060l,0xccfa18a187996cf6l,0xccfb2483f7eccdd2l,
-            0x07aa601ad453c66al },
-          { 0xd43cf263cffee9e2l,0x230bc099718f69bfl,0xc43de21300c193e8l,
-            0x94cf251799c8746fl },
-          0 },
-        /* 45 << 240 */
-        { { 0x4785d7f87d1320c5l,0x84bed8c3d0771dcbl,0xff28044d22254edbl,
-            0x2e5992a445f71504l },
-          { 0xcb92695b72bbf5cdl,0x9bcbde35c42422e5l,0x856594fd1d07ed86l,
-            0x3aaf0b717716b4ffl },
-          0 },
-        /* 46 << 240 */
-        { { 0x3edf24f9eebed405l,0x9e3141360eccb503l,0xf7704c25b85c2bc2l,
-            0x4cb7c1de9a3247eel },
-          { 0x798ac8f2f0b507c5l,0x6e6217206851bbf1l,0xc0b89398c0d9ed16l,
-            0xf7d5d2a09f20728fl },
-          0 },
-        /* 47 << 240 */
-        { { 0x7358a94a19f0ededl,0x5e08c4c3e32ccfbbl,0x84a8eeeb0089f071l,
-            0xdaf0514c41fc436el },
-          { 0x30fe216f310309afl,0xe72f77bd564e6fc9l,0xe7ef3bddfdc59fd5l,
-            0xd199b1c9a8e1169cl },
-          0 },
-        /* 48 << 240 */
-        { { 0xb9dc857c5b0f7bd4l,0x6990c2c9108ea1cdl,0x84730b83b984c7a9l,
-            0x552723d2eab18a78l },
-          { 0x9752c2e2919ba0f9l,0x075a3bd94bf40890l,0x71e52a04a6d98212l,
-            0x3fb6607a9f18a4c8l },
-          0 },
-        /* 49 << 240 */
-        { { 0xa0305d01e8c3214dl,0x025b3cae8d51cea3l,0xeeaf7ab239923274l,
-            0x51179407c876b72cl },
-          { 0xcf0241c7d4549a68l,0xffae7f4c793dab3dl,0xdfb5917b4bdf2280l,
-            0xcf25c870a652e391l },
-          0 },
-        /* 51 << 240 */
-        { { 0xb1345466b922e1c8l,0xae42f46ab5bf8a34l,0x1e1ab6053310e604l,
-            0x64093cd9b4d7a658l },
-          { 0x5d3b385ab3d9242cl,0x2225b99ae56f8ec7l,0x19a8cbfc9a916e11l,
-            0x11c5df831f957c03l },
-          0 },
-        /* 52 << 240 */
-        { { 0x09f1d04af381147bl,0x7be13628b26b345fl,0xd8371966d1c60b78l,
-            0xf1743c2c5d91808fl },
-          { 0x8a2966acafc71cc3l,0x0ba9702efdfc24c3l,0x60c80158e6fbb539l,
-            0x58eaee49812c32f4l },
-          0 },
-        /* 53 << 240 */
-        { { 0x31af7f5ee89d0b84l,0xa776dada6caa110bl,0xd67b7891df6d54ddl,
-            0x831613cab82b8a5cl },
-          { 0x7a4eb86ef020af6dl,0x2914fd11bd795a7bl,0xc038a273fcb54a17l,
-            0x6b2dc8e18219cc75l },
-          0 },
-        /* 55 << 240 */
-        { { 0x031fc875464ba9b5l,0xe268cf45bd812dd3l,0x443f57defbfb664al,
-            0xfd1a38544e28c2fal },
-          { 0xb8799782cb96515bl,0xa12d3e3f1138c95dl,0x0cc5ee117748ee57l,
-            0x6ab167cf955a7dfcl },
-          0 },
-        /* 57 << 240 */
-        { { 0x0d54aaca4dc1c74fl,0x74af1807bf2e0d61l,0x151254f87aebe0f1l,
-            0x4072f38bf6376095l },
-          { 0x31ebe17a26646abfl,0xdc8cb6b40ecc1282l,0x4f6326bbbc095a66l,
-            0x37dad65a0363636dl },
-          0 },
-        /* 59 << 240 */
-        { { 0xc851860a70f8c15al,0xb2d4555488368381l,0xbfd46e197019c7b6l,
-            0xa1a9b12f6bb6f33bl },
-          { 0xecfd5fe6f170c82bl,0x6d58bb52d601afc3l,0xb8b3de15fe6eb102l,
-            0xad07336886a47964l },
-          0 },
-        /* 60 << 240 */
-        { { 0x89f514c91911840fl,0xc9fa6b504cc106bcl,0x70a97f0dfe55b4f1l,
-            0xada6306be5888609l },
-          { 0xa9437881c6dc8d15l,0x0fc0f5368411f3dfl,0xd26162087a913dd2l,
-            0x4fe1c7c4e92848cdl },
-          0 },
-        /* 61 << 240 */
-        { { 0xaa18eb262e07383dl,0xb948c35c34e90f3dl,0x95e97f81d3653565l,
-            0x4a821a2687b5b75dl },
-          { 0x87b4d81c892db882l,0xa69e65d689f3bfadl,0xe475f532eb371cacl,
-            0xd8cc23fa17194d5dl },
-          0 },
-        /* 63 << 240 */
-        { { 0x3fc0052ad789d484l,0xe8c67aac29324323l,0x133fd07cf54c43d3l,
-            0xd4a0848fb91d4faal },
-          { 0xf683ce065ea5098fl,0xe84348f9887c8a76l,0x38f8c2cf79b224b6l,
-            0x327e4c534a818cb1l },
-          0 },
-        /* 64 << 240 */
-        { { 0xb6d92a7f3e5f9f11l,0x9afe153ad6cb3b8el,0x4d1a6dd7ddf800bdl,
-            0xf6c13cc0caf17e19l },
-          { 0x15f6c58e325fc3eel,0x71095400a31dc3b2l,0x168e7c07afa3d3e7l,
-            0x3f8417a194c7ae2dl },
-          0 },
-        /* 65 << 240 */
-        { { 0x0c9e9237d5f812bcl,0xdae5b7e9595f02e5l,0x5ec1dece42b1e9a8l,
-            0x506a6ef8e527a685l },
-          { 0xe3049290236af251l,0x6322dd1bf81970acl,0x1459d39c516d5e61l,
-            0x672f502d9455b694l },
-          0 },
-        /* 71 << 240 */
-        { { 0xf83788e06b228af2l,0xaafc823911f596fal,0x6d47fa592f0fcb13l,
-            0x0b7af65f1c99c5d4l },
-          { 0xbc4c185dca961e6fl,0xec02b09f158481a4l,0x4bbfd9f31423fdd4l,
-            0x0ff44a53b619644bl },
-          0 },
-        /* 77 << 240 */
-        { { 0x23e255a3ea3f59d8l,0x1f4a47a8261ac30bl,0x346bf409c8faf0b3l,
-            0xd13e73fbc03a226bl },
-          { 0x670ddc792fe8a79bl,0x335fa172f1aac412l,0xe2347de1a5ceff20l,
-            0x66e02c73381130f2l },
-          0 },
-        /* 83 << 240 */
-        { { 0xa6b874c51db717cdl,0x027d318ab00f160bl,0x578f89f49be791afl,
-            0x659ef2f01f3b5e9bl },
-          { 0xa0c593033835d84cl,0xb71e261fdb6f9a60l,0x65837c7f44b7813fl,
-            0xea776163ea4bcc96l },
-          0 },
-        /* 89 << 240 */
-        { { 0x208234118df3f15fl,0xe0514d4694f341acl,0xdc66282d6486d704l,
-            0xd5fb354ad2548389l },
-          { 0xf3e98d72df273295l,0x27ded7fa50cd09fcl,0x4f486af3c5c1c169l,
-            0xe51044150aa41ba3l },
-          0 },
-        /* 95 << 240 */
-        { { 0x66b14d296fce0aecl,0x35fe5e60c8915ceal,0x06a023b736c5da39l,
-            0x0977c9f0404e932fl },
-          { 0x1dd6f95db54866del,0xe5ec79359387430cl,0x98dee57b5ef42e67l,
-            0x1707f01912ed3ad0l },
-          0 },
-        /* 101 << 240 */
-        { { 0xeb3abdedeec82495l,0x587a696e764a41c7l,0x13fdcce2add1a6a3l,
-            0x299a0d43286b2162l },
-          { 0x2c4e71e18131f1b4l,0x48f0e806ada3d04fl,0x91d2de80c57491b2l,
-            0x1b1266236cc355cbl },
-          0 },
-        /* 107 << 240 */
-        { { 0xdc28afe5a6d44444l,0xb5ad8d3cfe0b947bl,0x50c6126c96ce9fb9l,
-            0x5384a998d1fc7d39l },
-          { 0xa43ff8898788f51cl,0x30359593a6bc7b87l,0x3e1691dccc0d019al,
-            0xda0ef5ad7943abcdl },
-          0 },
-        /* 113 << 240 */
-        { { 0x5bc58b6f020b5cd7l,0x9098e202e103ff4el,0xc1f1a3d9f6fce7c7l,
-            0xf9dc32a856090ccel },
-          { 0x4c7d2520a9cc3b09l,0x98d47b5dd8c4dfcel,0xdcee788297e689b4l,
-            0xe5eec71815f982b9l },
-          0 },
-        /* 116 << 240 */
-        { { 0xff154bb8a1e1538cl,0xb9883276f7dcfae9l,0x1ac0a4d2c1c8cba4l,
-            0x511a54cc76e6b284l },
-          { 0xe2da436f00011f6dl,0x4d357a190f43a8adl,0xf36899c95458655bl,
-            0xe5f75c768d613ed9l },
-          0 },
-        /* 119 << 240 */
-        { { 0x15b4af1d93f12ef8l,0x3f4c5868fd032f88l,0x39f67a08f27d86bdl,
-            0x2f551820da32db6bl },
-          { 0x72fe295ac2c16214l,0x39927c381a2cf9afl,0x8dda23d6b1dc1ae7l,
-            0x1209ff3ed32071d4l },
-          0 },
-        /* 125 << 240 */
-        { { 0x861fdceb9a3c6c6fl,0x76d7a01386778453l,0xbf8d147cd5e422cbl,
-            0xd16f532e51772d19l },
-          { 0x72025ee2570d02cdl,0xe8e7737be80c7664l,0x81b7d56c334a8d8fl,
-            0x42477a0ff1b79308l },
-          0 },
-    },
-    {
-        /* 0 << 248 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 248 */
-        { { 0xf306a3c8ee3c76cbl,0x3cf11623d32a1f6el,0xe6d5ab646863e956l,
-            0x3b8a4cbe5c005c26l },
-          { 0xdcd529a59ce6bb27l,0xc4afaa5204d4b16fl,0xb0624a267923798dl,
-            0x85e56df66b307fabl },
-          0 },
-        /* 3 << 248 */
-        { { 0x896895959884aaf7l,0xb1959be307b348a6l,0x96250e573c147c87l,
-            0xae0efb3add0c61f8l },
-          { 0xed00745eca8c325el,0x3c911696ecff3f70l,0x73acbc65319ad41dl,
-            0x7b01a020f0b1c7efl },
-          0 },
-        /* 4 << 248 */
-        { { 0x9910ba6b23a5d896l,0x1fe19e357fe4364el,0x6e1da8c39a33c677l,
-            0x15b4488b29fd9fd0l },
-          { 0x1f4392541a1f22bfl,0x920a8a70ab8163e8l,0x3fd1b24907e5658el,
-            0xf2c4f79cb6ec839bl },
-          0 },
-        /* 5 << 248 */
-        { { 0x262143b5224c08dcl,0x2bbb09b481b50c91l,0xc16ed709aca8c84fl,
-            0xa6210d9db2850ca8l },
-          { 0x6d8df67a09cb54d6l,0x91eef6e0500919a4l,0x90f613810f132857l,
-            0x9acede47f8d5028bl },
-          0 },
-        /* 7 << 248 */
-        { { 0x45e21446de673629l,0x57f7aa1e703c2d21l,0xa0e99b7f98c868c7l,
-            0x4e42f66d8b641676l },
-          { 0x602884dc91077896l,0xa0d690cfc2c9885bl,0xfeb4da333b9a5187l,
-            0x5f789598153c87eel },
-          0 },
-        /* 9 << 248 */
-        { { 0xb19b1c4fca66eca8l,0xf04a20b55663de54l,0x42a29a33c223b617l,
-            0x86c68d0d44827e11l },
-          { 0x71f90ddeadba1206l,0xeeffb4167a6ceeeal,0x9e302fbac543e8afl,
-            0xcf07f7471aa77b96l },
-          0 },
-        /* 10 << 248 */
-        { { 0xcf57fca29849e95bl,0x96e9793ed510053cl,0x89fa443d07d3e75el,
-            0xfe2bc235e52800a0l },
-          { 0x1c208b8c0ac7e740l,0xb5852a49e7222263l,0x217e4005e541e592l,
-            0xee52747dc960b0e1l },
-          0 },
-        /* 11 << 248 */
-        { { 0x5fd7cafb475952afl,0x23a6d71954a43337l,0xa83a7523b1617941l,
-            0x0b7f35d412b37dd4l },
-          { 0x81ec51292ae27eafl,0x7ca92fb3318169dfl,0xc01bfd6078d0875al,
-            0xcc6074e3c99c436el },
-          0 },
-        /* 13 << 248 */
-        { { 0x4ca6bdebf57912b8l,0x9a17577e98507b5al,0x8ed4ab7759e51dfcl,
-            0x103b7b2a470f5a36l },
-          { 0x0c8545ac12553321l,0xab5861a760482817l,0xf4b5f602b9b856cfl,
-            0x609955787adf2e5fl },
-          0 },
-        /* 15 << 248 */
-        { { 0x60ce25b1ee5cb44fl,0xddcc7d182c2d7598l,0x1765a1b301847b5cl,
-            0xf5d9c3635d0d23b7l },
-          { 0x42ff1ba7928b65d0l,0x587ac69d6148e043l,0x3099be0dd320390bl,
-            0xa7b88dfc4278329fl },
-          0 },
-        /* 16 << 248 */
-        { { 0x80802dc91ec34f9el,0xd8772d3533810603l,0x3f06d66c530cb4f3l,
-            0x7be5ed0dc475c129l },
-          { 0xcb9e3c1931e82b10l,0xc63d2857c9ff6b4cl,0xb92118c692a1b45el,
-            0x0aec44147285bbcal },
-          0 },
-        /* 17 << 248 */
-        { { 0x7685bb9e0ba4e0b7l,0x330a7ebc5e58c29bl,0xbc1d9173e8a3797al,
-            0x7c506a16ea60f86cl },
-          { 0x9defb9248c099445l,0xcf1ddcc0256df210l,0x4844ce293d07e990l,
-            0x92318e37e2628503l },
-          0 },
-        /* 19 << 248 */
-        { { 0x61acd597fdf968d7l,0x7321a8b26598c381l,0xcb86a2809f448a0cl,
-            0x38534a01855df66al },
-          { 0xc119ec141e29037fl,0xe23c20ad0b42ba67l,0xefb1c4e033fb4f22l,
-            0xf088358f445a5032l },
-          0 },
-        /* 21 << 248 */
-        { { 0x2d73f5d1b8475744l,0xcc297e0a9d399b06l,0xa8c61d4038d3df06l,
-            0xacc6e8651a2d27a0l },
-          { 0x63dd6f6230153bf2l,0x6b23ad7bd73b83b7l,0x25382bf767ff7dcdl,
-            0x7e268c8fcf7ce2d1l },
-          0 },
-        /* 23 << 248 */
-        { { 0x4b9161c3cb2ebef1l,0x6009716b669ed801l,0x97c65219aacefe44l,
-            0xde13597d71aae4b5l },
-          { 0x3a077a816141d651l,0xe1b4e80129f876eal,0x729aed6d5c00c96cl,
-            0x0c6f404374cc645el },
-          0 },
-        /* 25 << 248 */
-        { { 0x22c51812df5a66e1l,0x1c8069c9ae7dedeal,0xcff9d86f0eea5180l,
-            0x676dbd6f44235ddal },
-          { 0xa53f01383db1ad42l,0xd079e571bcf19029l,0x1e37b9ecfab0cf82l,
-            0x93ae35ed4844e9c4l },
-          0 },
-        /* 27 << 248 */
-        { { 0xdaee55a543756358l,0x0ace18d41b2d3f89l,0x3391fa36824dd7d4l,
-            0x7b9963d1770e5f3fl },
-          { 0xc1fb9a78c94f724dl,0x94ff86fe76c4da6bl,0xb5d928c64170609bl,
-            0xc9372becfb015a9fl },
-          0 },
-        /* 28 << 248 */
-        { { 0x9c34b650e16e05e9l,0x965a774094e74640l,0xa3fd22fbcea3f029l,
-            0x1eb6a9688f95277cl },
-          { 0x2520a63d7bad84f6l,0xad917201f58f2feel,0xea92c1669b840d48l,
-            0x12109c4aacef5cbdl },
-          0 },
-        /* 29 << 248 */
-        { { 0xd85850d0d407a252l,0x6fa3b14de63909d4l,0x2ff9f6593e0fba69l,
-            0x7f9fd2a2d1b2cd0bl },
-          { 0x611233d745ad896al,0xfe4211648df850f9l,0x7808832399e32983l,
-            0x4b040859dee6741dl },
-          0 },
-        /* 31 << 248 */
-        { { 0x7dd2afd456e1ed5cl,0xd48429ec41ba4992l,0x97a02188968bab27l,
-            0x09ecf813e63c4168l },
-          { 0xf4ac65e77288b10cl,0x10630ab2afac7410l,0x4e3e59c3bb049e56l,
-            0x25972fff40fea0b1l },
-          0 },
-        /* 33 << 248 */
-        { { 0xfd8363da98365c18l,0x8aa57b1a8d47bf91l,0x423dce57695f4dd6l,
-            0xfccf54d4cc17f034l },
-          { 0x8fdba27c3610ea51l,0xcc0a06d654306b06l,0xb97a121c389b9dfdl,
-            0x7dbb90eb1ed0ca42l },
-          0 },
-        /* 34 << 248 */
-        { { 0xd32d7cec0094e84cl,0x862ae25e2ece8f72l,0x8644ef1cdfceb8abl,
-            0x68a9969c8e225628l },
-          { 0xdf209e27b3117876l,0x308a6e1882ba242bl,0xcbd09a659bf0cdb6l,
-            0x79f2826cc85b9705l },
-          0 },
-        /* 35 << 248 */
-        { { 0x3b36b6bf8f011496l,0xea6acc1a9bcf6ef8l,0x6db132263b101f12l,
-            0x4fc4e35e3b7585c3l },
-          { 0x641de27556eb64c6l,0x9b2834d3f3b08519l,0xebb76a2ba1f44b40l,
-            0x1b545ccd3cd31677l },
-          0 },
-        /* 36 << 248 */
-        { { 0xab293027aad991c1l,0x598d0bf8849be4b7l,0x8c94a21ab972da90l,
-            0xada4cfdd7ecfa840l },
-          { 0x93d4b9c0fbcec63al,0x7ca617a203219a34l,0x900424eb6a652a55l,
-            0xaf9346e9eb8562e0l },
-          0 },
-        /* 37 << 248 */
-        { { 0x9681a73d2d8bc904l,0x8b5f9b317b1553bel,0xfb03b874f6bc852fl,
-            0x8e658fb8cbbec8b0l },
-          { 0x9b2ff17bb9e9f9d1l,0xf46e9bf3e8679854l,0x7fbb1323618ed3aal,
-            0x064a1c5d714ebc3dl },
-          0 },
-        /* 39 << 248 */
-        { { 0xac0bdfc39f0e69dcl,0x71957386ae12f132l,0xa263ef2e6aa90b5bl,
-            0xa94b152390d42976l },
-          { 0xfb2d17741bcdbf7bl,0xba77b77c3a04f72fl,0xa6818ed8ec3e25a1l,
-            0x2e0e01743733e251l },
-          0 },
-        /* 40 << 248 */
-        { { 0xc3e04d7902381461l,0xb1643ab5911bc478l,0xc92becfa390b3ef2l,
-            0x54476778acd2f1b6l },
-          { 0x8daa0c4d66bf3aafl,0x2bc1287b2c21c65al,0xee182910b5a13ac3l,
-            0xbb04730090b0790al },
-          0 },
-        /* 41 << 248 */
-        { { 0x8bdd6f35a8540489l,0x788c03e5ee390d4el,0x203323c18f653017l,
-            0x39953308c4bc0094l },
-          { 0x6ee0857118308d0bl,0x70e9f90b450b0002l,0x191662aa8139f145l,
-            0xd7c5415b62d71124l },
-          0 },
-        /* 43 << 248 */
-        { { 0x41b37d72b927231cl,0xca17b5429e4de13al,0x7bc03469cded2ce3l,
-            0x961b0ecb4f4560f9l },
-          { 0x7c5bd41b43d31fa1l,0x3ed047f643f44dc3l,0x5b02083efe1a4d14l,
-            0xcc2c66ac18b330bcl },
-          0 },
-        /* 44 << 248 */
-        { { 0x83766947d17d4e0bl,0xc5772beefdc3a47bl,0x765a50db1a6fd0ffl,
-            0x17f904ba45b0995el },
-          { 0xcee643832883487el,0xf56db7f3c270aaedl,0x6738d94f46cb1fd9l,
-            0xc8fa426a142fd4d5l },
-          0 },
-        /* 45 << 248 */
-        { { 0xc85bef5b5a78efcel,0xaf380c6b0580e41el,0x6c093256a43b8d9bl,
-            0xed9d07bbea670933l },
-          { 0xfdb9a295f1682c6el,0x4cc29a63532b6bb7l,0x21a918f9f8e42dd0l,
-            0x9ac935ce0edacca0l },
-          0 },
-        /* 46 << 248 */
-        { { 0xbfe48a8ff43daf9dl,0xd7799b31b313c052l,0x46d480d77119c60el,
-            0x5090d91f0b80bcb9l },
-          { 0xc94c4c1e873bd7bfl,0x16e69b4f9915aa0al,0x769be02bb1d5928cl,
-            0x3fdaf62162e1d85al },
-          0 },
-        /* 47 << 248 */
-        { { 0x03497a57371c1b5cl,0x11e4c0b3552ab6abl,0xf857061f0a169ee7l,
-            0xc21c6c43e6d1bc66l },
-          { 0x706283a82832be7al,0xd35b143299aba62cl,0x7f4da83de9aef62dl,
-            0x2b7e5fc8723fa4e5l },
-          0 },
-        /* 48 << 248 */
-        { { 0xae485bb72b724759l,0x945353e1b2d4c63al,0x82159d07de7d6f2cl,
-            0x389caef34ec5b109l },
-          { 0x4a8ebb53db65ef14l,0x2dc2cb7edd99de43l,0x816fa3ed83f2405fl,
-            0x73429bb9c14208a3l },
-          0 },
-        /* 49 << 248 */
-        { { 0xc086e737eb4cfa54l,0x9400e1ad3c44aad9l,0x210bba94336959b4l,
-            0x08621a809106f0cal },
-          { 0x2ae66096c510ee9cl,0x2ba21617fc76a895l,0xc0707f8b0c186f1el,
-            0x1fe170a3ed0bfe25l },
-          0 },
-        /* 51 << 248 */
-        { { 0x3780fe2084759c5cl,0x716ec626b7050aa7l,0x6a43fb8b84b63bd1l,
-            0xb01098a039bc449fl },
-          { 0x96b3ff8ebb7daa4dl,0x2d146882654a7f01l,0x2500f701dcae6143l,
-            0xc13d51d01626fd3bl },
-          0 },
-        /* 52 << 248 */
-        { { 0x08ed8febd56daf06l,0x8d98277b4a837f69l,0x9947c636a9b6e05al,
-            0x58c8a77ac0d58abdl },
-          { 0xf45496a45f121e4fl,0x16cd67c71076d3d3l,0xecbd1958e3fb0c5dl,
-            0xfbe185ec38e1eb47l },
-          0 },
-        /* 53 << 248 */
-        { { 0x65b067eb740216e3l,0x1e19a71479db8760l,0x8d30dca18878de5al,
-            0x627d03e8aa47c005l },
-          { 0x096d58c0d2536c96l,0x232e6a4d69b12c2al,0x850eb8c0e7044bcel,
-            0xd9cf923bef2ee9a1l },
-          0 },
-        /* 55 << 248 */
-        { { 0x8b301094c8eaee90l,0x9a96950b8330928fl,0x472ba105faccc3bal,
-            0x00f8620e9153172al },
-          { 0x019b8164303fcdf5l,0x614d5c3c41fb4c73l,0x632d98f2c5992f89l,
-            0xfbeb29d790e2dea5l },
-          0 },
-        /* 57 << 248 */
-        { { 0xefd48b577f91d6e0l,0x8575605595bcf5d4l,0x7677b4a7bb9d891bl,
-            0xdc9931e9685912c9l },
-          { 0x69bca306f31a07c8l,0x3dd729534962a7f0l,0xdcea49cc9d366c2al,
-            0xce664ba7dc79a57dl },
-          0 },
-        /* 59 << 248 */
-        { { 0x7842d547013ec3b5l,0xa2785ceb433cf990l,0x9d667e5f700ab14al,
-            0x4b46f362a0f46d55l },
-          { 0x152c0e80cc7a3487l,0x7f3a88cef86f5e68l,0x6f950a73f1b2a75fl,
-            0x9be5b1aa51d24f3bl },
-          0 },
-        /* 60 << 248 */
-        { { 0xaea68626dc4ad4f4l,0x5dc516824ddbc0b6l,0xa76697bd602e9065l,
-            0xbeeb3ea58c37888el },
-          { 0x1ec4a2f214569113l,0xe48b820ca35f4484l,0x9fb560949ae44df2l,
-            0x6ca1346292cc09fdl },
-          0 },
-        /* 61 << 248 */
-        { { 0x887e0b87bcdc3a36l,0x6b0d617d503dee65l,0x96bda1f6cebcb893l,
-            0xdc0dd17341e20b3el },
-          { 0x812fbacfa6657c11l,0x32492fcbc94a6f4bl,0x854a0bcb6a772123l,
-            0x1ed573f65d463f31l },
-          0 },
-        /* 63 << 248 */
-        { { 0x22c7ef7bd022cc4dl,0xeec383d61e63b4bcl,0x52e0aaa06502b46fl,
-            0x9224187ded5e41bfl },
-          { 0x3a01f53dd26faf1cl,0x9bc4ee2e4e591d10l,0x10b7a98eea7e4c88l,
-            0xe521c150e2c1beccl },
-          0 },
-        /* 64 << 248 */
-        { { 0xb618d590b01e6e27l,0x047e2ccde180b2dcl,0xd1b299b504aea4a9l,
-            0x412c9e1e9fa403a4l },
-          { 0x88d28a3679407552l,0x49c50136f332b8e3l,0x3a1b6fcce668de19l,
-            0x178851bc75122b97l },
-          0 },
-        /* 65 << 248 */
-        { { 0x26f9b9322ed53a71l,0x0bac7348c72ef2e0l,0x7e96001da5c6faf1l,
-            0x5d43f76dea00eb2dl },
-          { 0x1327370f44f1c478l,0x1c83a9ac6bb964c8l,0xa3a9769f76ffbd25l,
-            0xdf045fb6b04f1bddl },
-          0 },
-        /* 71 << 248 */
-        { { 0x4283898d556b975el,0x6e2301ffe3880361l,0xc6d3b2bbe9198077l,
-            0xc4799578d21cac02l },
-          { 0x11448ff8f784eb7cl,0xb775973fbb81898dl,0x4e51f061519c76b9l,
-            0xaba1f3ef3cad0393l },
-          0 },
-        /* 77 << 248 */
-        { { 0x59d60c1c9b339830l,0x5af60a44ac32746dl,0x5ac006bc9dea8d80l,
-            0x4a2a56d97f2b1180l },
-          { 0x2032845a46946fc4l,0xe25b911226a3b503l,0xfed89db9a28827d3l,
-            0xdd2d7e90c6b74593l },
-          0 },
-        /* 83 << 248 */
-        { { 0x9b047a26cda38ecfl,0x6889284f5f6cb442l,0x4d128bcb14753820l,
-            0x8f9937c160eedd78l },
-          { 0xe333bad751ab9127l,0xd31b01c67ace3b19l,0x0732de39d7c0b4bel,
-            0xad04fa4c649e2b9bl },
-          0 },
-        /* 89 << 248 */
-        { { 0x02e042689d1495bal,0x95dca5a85591b5f8l,0xb10488d856f46c71l,
-            0x97829baf3590000al },
-          { 0xaeda5cb378c9e78al,0x3615873a7ba1c71cl,0x7c9f9f4d4333aa12l,
-            0x893fab42cea8e6d3l },
-          0 },
-        /* 95 << 248 */
-        { { 0x9eb09fff69aaa09fl,0xf36678a926731322l,0x8be61ee1cafcabafl,
-            0x77a172f558ddb763l },
-          { 0x7e09dfc66471130el,0x7f8909791039771el,0x0e44071d37800b9bl,
-            0x09123d27fe762d10l },
-          0 },
-        /* 101 << 248 */
-        { { 0xffd455a7a1b7fdd6l,0xb6162cb4dabdffael,0xf859519ec89c0e56l,
-            0x07406c1b421f2846l },
-          { 0x42db24ed9e96ddbbl,0x03bcae092dc5da85l,0x75099cd217aa7493l,
-            0x8cd1aa4266b8740dl },
-          0 },
-        /* 107 << 248 */
-        { { 0xe94333d5dde7fec3l,0x894fd673745a9be3l,0xaf3d97c725683748l,
-            0xeaa469a2c9ec165fl },
-          { 0xc9a18decdc7abd3bl,0xf059008082717b02l,0x9816374a4fdf4300l,
-            0x449d3eb74fb5a6cel },
-          0 },
-        /* 113 << 248 */
-        { { 0x7fc983ebd28001a6l,0xeabf5276dae74b6bl,0x50adb67d742ed0a5l,
-            0x1d2ad363650e1446l },
-          { 0x5a564253d122f5d0l,0x7e5aefc7e30471del,0xdc64cbb3e5dc2f2cl,
-            0xe645b9fa9437be4el },
-          0 },
-        /* 116 << 248 */
-        { { 0x0f58cec54e27d357l,0x08dcf2b70004539el,0xb1ead64104f96709l,
-            0x350fed185a914c72l },
-          { 0x44f43523c5147854l,0x45f8b46f46d04ac7l,0x62c306869a449d51l,
-            0xaacc0f0d9e66d9a3l },
-          0 },
-        /* 119 << 248 */
-        { { 0x94cb62e5bdd61b63l,0xe6ce5b5104a0ec57l,0x0461cb95f0bda8a4l,
-            0xca2d6220cbadfe8fl },
-          { 0x6c19bdf03c1ad65el,0x774a49bae04239d5l,0xf78cb7404a2fd59dl,
-            0xaebf90ed66a09130l },
-          0 },
-        /* 125 << 248 */
-        { { 0x10e4074857cc8d54l,0x29985831918e3cf9l,0x3d87def9f2e344eel,
-            0x8899992c68977860l },
-          { 0xbdc8d73b210f3c50l,0x98aa042fa9857f46l,0x76a34daf6c71357fl,
-            0x086289d3200bcb6dl },
-          0 },
-    },
-    {
-        /* 0 << 256 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 256 */
-        { { 0xb4e370af3aeac968l,0xe4f7fee9c4b63266l,0xb4acd4c2e3ac5664l,
-            0xf8910bd2ceb38cbfl },
-          { 0x1c3ae50cc9c0726el,0x15309569d97b40bfl,0x70884b7ffd5a5a1bl,
-            0x3890896aef8314cdl },
-          0 },
-        /* 3 << 256 */
-        { { 0x996884f5903fa271l,0xe6da0fd2b9da921el,0xa6f2f2695db01e54l,
-            0x1ee3e9bd6876214el },
-          { 0xa26e181ce27a9497l,0x36d254e48e215e04l,0x42f32a6c252cabcal,
-            0x9948148780b57614l },
-          0 },
-        /* 4 << 256 */
-        { { 0xab41b43a43228d83l,0x24ae1c304ad63f99l,0x8e525f1a46a51229l,
-            0x14af860fcd26d2b4l },
-          { 0xd6baef613f714aa1l,0xf51865adeb78795el,0xd3e21fcee6a9d694l,
-            0x82ceb1dd8a37b527l },
-          0 },
-        /* 5 << 256 */
-        { { 0x4a665bfd2f9fd51al,0x7f2f1fe2481b97f7l,0xcad05d69ad36ce50l,
-            0x314fc2a4844f4dedl },
-          { 0xd5593d8cb55fc5c6l,0xe3510ce8bfb1e23dl,0xf9b7be6937453ccel,
-            0xd3541b7969fae631l },
-          0 },
-        /* 7 << 256 */
-        { { 0x711b8a4176a9f05dl,0x06ca4e4b9011d488l,0x543bc62ba248a65el,
-            0x017535ffc9290894l },
-          { 0x840b84ce406851d7l,0xafa3acdf90e960b4l,0xac3394af7128fd34l,
-            0x54eb4d5b2ac0f92cl },
-          0 },
-        /* 9 << 256 */
-        { { 0x3549a0f14df48fecl,0x6ae7b1eec239f83al,0x001dcf253eb90ff3l,
-            0x02ff0f02581e90edl },
-          { 0x72921d8ca103dcefl,0x2c513c3c5876293el,0xc07064ca6b68875el,
-            0x7198d44653b9537cl },
-          0 },
-        /* 10 << 256 */
-        { { 0x58349b77685e089bl,0x1c678441219b7b8cl,0xba8da91f61e2e20dl,
-            0xf9c50b8c309fd4e6l },
-          { 0x99b0164996d0ef64l,0xac334ded60cdb63al,0x6b9ada19fb0bce4fl,
-            0x39dc9375c7896377l },
-          0 },
-        /* 11 << 256 */
-        { { 0x068dda8b7e1bc126l,0x77c7c58176243a21l,0xcc8ba55c875f9dael,
-            0xdde7afe2ce469f95l },
-          { 0xde2a15f5e9523b85l,0x447512c6d85674ael,0x5691f89e12c6c20cl,
-            0xd64ef40e0fae4513l },
-          0 },
-        /* 13 << 256 */
-        { { 0x10db2041c4d9eb40l,0x420eccb724f03f8al,0x64470fd17d29080el,
-            0xf66c5b4416e52414l },
-          { 0xa32cc70e4ca94031l,0xa67931592c8401bal,0x34f2dc29abfcc58dl,
-            0x6f340f9a07325d7dl },
-          0 },
-        /* 15 << 256 */
-        { { 0xf55d446b060a52bbl,0x2f33cb9f02939f24l,0x0f27a01bc8953718l,
-            0x362882917fcd3932l },
-          { 0x7485613488ed4436l,0xcfe69e27195f089el,0xd6ab040a8ff10bd8l,
-            0x9741c5472e4a1623l },
-          0 },
-        /* 16 << 256 */
-        { { 0xc52d8d8b6d55d6a4l,0xc4130fb3be58e8f9l,0x5f55c345e1275627l,
-            0xb881a03c117042d3l },
-          { 0x00a970a53238d301l,0x40d7cf2412a2c4f1l,0xace4a2f5d770ea74l,
-            0x36a2e587e96940b2l },
-          0 },
-        /* 17 << 256 */
-        { { 0x84793d9fef12d4c8l,0x04b89b152d8a163cl,0x0fdb566fb4a87740l,
-            0xf7e6e5cf9e595680l },
-          { 0xbcb973e41c5cd74el,0xafcb439fe4ed49d8l,0xd5c0820aebbae8eel,
-            0x23483d836f56e2a2l },
-          0 },
-        /* 19 << 256 */
-        { { 0x91f9b8be5e8ad115l,0xf1fd6a2e225db496l,0xf362d2cf4a444085l,
-            0x033d9201eea043ebl },
-          { 0x1e50c0989951a150l,0x4814fca5cfcf1f94l,0xaf3e8ef41bf82de5l,
-            0xba0e2991038cff53l },
-          0 },
-        /* 21 << 256 */
-        { { 0x904a41ae5fc373fal,0x235556d61a6a3fc4l,0xe44eb3ea36eeb570l,
-            0xa4e1b34a26ba5ca6l },
-          { 0x210e7c9131180257l,0x2c28669622158b0cl,0xc78b69c783ddd341l,
-            0xfc05941b294e1750l },
-          0 },
-        /* 23 << 256 */
-        { { 0x70666f51fc167dedl,0x47e9e289fe75b8d1l,0x8a5f59739605a03el,
-            0x19876a58dd579094l },
-          { 0x69a5c8cca964e426l,0xed74a652ccf20306l,0x5c93ae3cf06d31d5l,
-            0x51922fa2127a8a12l },
-          0 },
-        /* 25 << 256 */
-        { { 0xa18e26f99e3d509el,0xbc296dd2c10814fal,0x5dadd6eeaa24e147l,
-            0xdba2121a8340f12el },
-          { 0xd348e7f3e245ca21l,0x1e45a42978e3eb5bl,0x252bf89c169677bbl,
-            0xfb33a2564021ac55l },
-          0 },
-        /* 27 << 256 */
-        { { 0x30dc46586e7d72b8l,0x38df46fb0d81c3d6l,0x901bab6e10e84162l,
-            0x25d7303ff7932801l },
-          { 0xe781d5f37500be42l,0x9a7104c3380ff208l,0xfa801181652121a1l,
-            0xef89f4f18d3bed43l },
-          0 },
-        /* 28 << 256 */
-        { { 0xbe4ae5683594917al,0xef7c1c47a04bf81el,0xa1dc3612046d91a0l,
-            0x3eee37affb11b338l },
-          { 0x7e90278fd03d8f51l,0x3045a6da4fa183c6l,0xb39e573391cd16a9l,
-            0xc748a504e54e9411l },
-          0 },
-        /* 29 << 256 */
-        { { 0x07804331a1c6ec56l,0x25358e795b347123l,0x1ab9b39acf9432a4l,
-            0x9628501d0a7881cel },
-          { 0x749d58988a46d98el,0x01ea43346a17c321l,0xe2b197f9b1f9160fl,
-            0x2052c7c07815f2a2l },
-          0 },
-        /* 31 << 256 */
-        { { 0xaa691bfbc57a1a6dl,0x06cae127d737d525l,0x5be04b2f963c7c98l,
-            0x936b1f5bfc00bc4al },
-          { 0x3fed4ac77eda6a34l,0xba6ca7aa2500a438l,0x1e979fa6786c2a75l,
-            0xa3db26bec13f37d4l },
-          0 },
-        /* 33 << 256 */
-        { { 0x20afae333d7006d1l,0xdcbca6fbbda467d1l,0x2714b3827df4006cl,
-            0x9abc0510c8e94549l },
-          { 0x5b30a6d464c14915l,0xba91d0c35752b44fl,0x7ad9b19bbb389f1fl,
-            0xe4c7aa04ef7c6e13l },
-          0 },
-        /* 34 << 256 */
-        { { 0x1e24a3f23d12e2b6l,0xf99df403febd6db3l,0x61e580a6b0c8e12fl,
-            0x819341b7c2bfe085l },
-          { 0xd53002d640828921l,0x31e1eb65cea010efl,0xc48d0cfe85b3279fl,
-            0xb90de69089f35fa5l },
-          0 },
-        /* 35 << 256 */
-        { { 0xa3f6fd3c88ed748fl,0x6d72613af48127b9l,0xe85ed703d1e6f7e5l,
-            0xbb563db449636f40l },
-          { 0x23bae3c9708497bal,0x89dbff163aa65cf4l,0x70861847e6c0850al,
-            0x5ef19d5d48b2e90cl },
-          0 },
-        /* 36 << 256 */
-        { { 0xab6a1e13107f7bacl,0x83a8bc57972091f5l,0x3c65b454f6dcba41l,
-            0xd7606ff96abc431dl },
-          { 0xa3af9c189bd09971l,0x6ddd3bbf276bad63l,0xd2aba9beab4f0816l,
-            0x8f13063c151581edl },
-          0 },
-        /* 37 << 256 */
-        { { 0xf9c02364f5761b15l,0x3cfa250afd478139l,0x67d51e7416e26191l,
-            0x0281bbf65eda396cl },
-          { 0xbd38d4d70d1f4510l,0x2032a930edff593el,0x0ab74a0cf2ea4ad7l,
-            0xb95aa9c3302498d6l },
-          0 },
-        /* 39 << 256 */
-        { { 0x2995495dd7da3c7cl,0x28d579d0a0bb703el,0xabec6afec8288837l,
-            0x93c34dfd05ab989bl },
-          { 0xcc94f05dde5ea3dfl,0xc3e3d4ef90f436e6l,0x32b3dee1cf59dc4el,
-            0x5eab01635447d9d9l },
-          0 },
-        /* 40 << 256 */
-        { { 0xd31c5e8e2c23464el,0x5bcc382f50cfbde7l,0x6cee3d8da93c3d9bl,
-            0xbee2948909ee62acl },
-          { 0x4848d59c10742b84l,0x2486796fe35e9c84l,0x1a1d9570cd8f391al,
-            0x839aa0913eedb743l },
-          0 },
-        /* 41 << 256 */
-        { { 0xae02a7ce0f83f369l,0x3b67c56097994835l,0x715def441ae4bbeal,
-            0x11e764ee59f6b9eel },
-          { 0x70c775051c962c3al,0x42811507d937a258l,0x06dbdceed03e6e86l,
-            0x39a3a7ed48cae79el },
-          0 },
-        /* 43 << 256 */
-        { { 0xa32e729fb220eef8l,0x12d876baf37ac5d7l,0x9376ab45105a7f34l,
-            0xb422331a4deb7275l },
-          { 0x6ea07fb7686dea5el,0xba67ed3e1d8e32c9l,0x5ae52632bbc6bb9cl,
-            0xdca55b86d1397575l },
-          0 },
-        /* 44 << 256 */
-        { { 0xd9183f74378200b1l,0xe5ea1645762f5605l,0x78b42e2f7bd6290fl,
-            0xa0bdfccc07fa0899l },
-          { 0x2f92ea52dacda629l,0x810b4e6c48de27e2l,0x013d8587d9d1250dl,
-            0xc153d519dd5141d5l },
-          0 },
-        /* 45 << 256 */
-        { { 0x8f1f6cb5b8f1d719l,0xa9abc27b04e15a4el,0xc0d944a92ad42296l,
-            0x69ecc877f3d2b0e5l },
-          { 0xec60dbea16a5581al,0x2a0ead5fb85130d6l,0x7b3d2ebb6fddac23l,
-            0x06213269ac448663l },
-          0 },
-        /* 46 << 256 */
-        { { 0xe1074008ac11e180l,0xdff3339c14b8f830l,0x136e22be636504f3l,
-            0xb07ae98aa09c5c4cl },
-          { 0x9b0a0517192168e9l,0x39e09fac86ad0865l,0x24f90705adb08d41l,
-            0x9c699cc759d3be24l },
-          0 },
-        /* 47 << 256 */
-        { { 0xd9e16551907e36b0l,0x57f24b6caf91cb5al,0xbdb7dfdb062edae4l,
-            0x99e3bffe4b85f424l },
-          { 0x250774f4b2961ba7l,0xe7c0f2386d993c51l,0xcd0aae29f559b4bdl,
-            0x3b12893a09a6859bl },
-          0 },
-        /* 48 << 256 */
-        { { 0xac177eb985ae12c3l,0x8e6cb5cc6cf76537l,0x134abb19f265f9e3l,
-            0xc37309b71ba3f55dl },
-          { 0x570833b4392d564bl,0xaa273a27d8c22f00l,0x9ba6b6276006773al,
-            0x2156c94f0a16c092l },
-          0 },
-        /* 49 << 256 */
-        { { 0x2be0436b408e1258l,0xb179a2e34f47f121l,0x140b948fa42d3cfcl,
-            0x96649c6700d2b4e6l },
-          { 0x2bf934c7d08a4b34l,0x371c770136b472ddl,0x36297876e06adc73l,
-            0x59e0d8251c3e6558l },
-          0 },
-        /* 51 << 256 */
-        { { 0x9368cfd304a8bc81l,0x145249d4c49e58c7l,0x8c7ac1891392be01l,
-            0x58cbcb5fbc7b0903l },
-          { 0x502218a1a0377b0al,0x5c17eb8afb625836l,0x845c09ef349f4d26l,
-            0x15fdeb2554ddce85l },
-          0 },
-        /* 52 << 256 */
-        { { 0xf773535a64e8344dl,0xb8486a33d0dbabe6l,0x43c2df99b578862dl,
-            0xcead29a11a39820el },
-          { 0x3e5466fe63134d63l,0xc37ea88fdf43a104l,0x3b34ac34bbaacb5al,
-            0x8281c240bc20be5al },
-          0 },
-        /* 53 << 256 */
-        { { 0x55113d5e0f8dec77l,0xdfe59f251d7e1543l,0x3b2837e0a63a849al,
-            0xdfbdb8b67a5691afl },
-          { 0x8dd6faf0bd4cf444l,0x28b2bdfaab128b6cl,0x44af3ee24b1098ebl,
-            0xbbf328ebe50b2d02l },
-          0 },
-        /* 55 << 256 */
-        { { 0xf231b1f4e4e6151al,0x6ac7130413258c6al,0x6f9cb1c1a09b9f86l,
-            0xbfc9291ee52ed880l },
-          { 0x2a7d8230bea258a2l,0xd52a0da6baf386acl,0x5166764b3af00b7el,
-            0x84792b043c985be2l },
-          0 },
-        /* 57 << 256 */
-        { { 0x914ca588a906d9e4l,0xb4e4e86abc27a876l,0x97e6ed27724324f2l,
-            0xda7e9aa5c0b87d2cl },
-          { 0xafccbe6b33a56f84l,0x69e8fd4ac892d90al,0xb47512910bb5457fl,
-            0xad65e4d05cb136fal },
-          0 },
-        /* 59 << 256 */
-        { { 0xb09974d2fd679a1bl,0x17abc2a54578faf0l,0xe7da92828c830388l,
-            0x7e455d8b0edf6146l },
-          { 0xdff3b2f0c324bdb6l,0xe7a1718769f4a4f9l,0xfb4e0b3129c500a4l,
-            0x1ed50799a09c5a07l },
-          0 },
-        /* 60 << 256 */
-        { { 0x6b669496c679d9f9l,0x3b741f36e78f0830l,0xf99d4857eb3f9e53l,
-            0x41be594276f7d4ael },
-          { 0x75f44d57c09a112bl,0xa5139fd68475eeb7l,0xa4560cd5c6bc9df6l,
-            0x8ce2c4cf50845434l },
-          0 },
-        /* 61 << 256 */
-        { { 0x96b515c32b3cb0a6l,0x65836de3930d5344l,0xfb032d5b00e6d403l,
-            0x2648301843c93bd1l },
-          { 0xfc4525dd4b572363l,0x12b7923e7b28ab5cl,0xf376b633e22ac5e6l,
-            0xd6ff6582e30b4707l },
-          0 },
-        /* 63 << 256 */
-        { { 0x8bdce75c83b09e07l,0x64228b19227717c4l,0xeae8f8a2dc6a1f02l,
-            0x1081031be72f3b6dl },
-          { 0xba0f876072c3f736l,0xde38a0c5246a28adl,0x0b116fe08596c412l,
-            0xb9e37be3fa135d11l },
-          0 },
-        /* 64 << 256 */
-        { { 0x09800dc1b48d4168l,0xa740b282bfee87a2l,0x80c6b75dc94a547al,
-            0x8cb622f0099c1985l },
-          { 0xe6c789631467e05dl,0x027b658822fd3064l,0xe14735e2c2fdb68cl,
-            0xfd2869947d853158l },
-          0 },
-        /* 65 << 256 */
-        { { 0x301916a5bbd7caf1l,0xef563fda4e2076c2l,0xccbc56088467f279l,
-            0xd7de3088b8d0f1bfl },
-          { 0x3d9adcce8586910dl,0x3fa3b8b9d775e0e9l,0x4b7a4a1d88136503l,
-            0xc748656de4994fcel },
-          0 },
-        /* 71 << 256 */
-        { { 0x18cc605c2d9f8646l,0x3764f1c29e441b64l,0xb0ea7f7fc4b64ee3l,
-            0xb5c22d0c042f8678l },
-          { 0x3761f7f89b3057fdl,0xc85b8de64a207ce4l,0x11da715bc5c04cf7l,
-            0x0cb1fa77c8e99c1fl },
-          0 },
-        /* 77 << 256 */
-        { { 0x35f9cfc8045dab4el,0x08a65c6771a7d720l,0xf076767b8eef1351l,
-            0x5351dbff8638fbe5l },
-          { 0x5aead6f7772ad54cl,0x5f6b441fafe93e69l,0xb7b83d1aeeb876b5l,
-            0xbe1ba4a7cdc094d9l },
-          0 },
-        /* 83 << 256 */
-        { { 0x005d8f04ec0377bal,0x036b8e1ace58f05dl,0xdd6ffc6f1b28cf58l,
-            0xc3d95a58e206189fl },
-          { 0xcb2873c1f52e8b8cl,0xcffdb18d80142af1l,0x7cf88eb64c77ed78l,
-            0xb3a3141981ef2c12l },
-          0 },
-        /* 89 << 256 */
-        { { 0xbb17e6f957c175b1l,0xf33abc63260a6f6dl,0x9435f2de620ddd6bl,
-            0x90bdde59ff3e99eal },
-          { 0x3d7875e0567b520fl,0xdd6954aa813b4978l,0x1af3dc24de7b631cl,
-            0x82ddcd08934d3c97l },
-          0 },
-        /* 95 << 256 */
-        { { 0x7a9d60affc5ce598l,0xc6f507597c37abfdl,0xaa1b32f3a79355d0l,
-            0xac581b94d7e4fcf3l },
-          { 0x2669cefd139f6466l,0x560a98bb26f97570l,0x32e1c1db2837b908l,
-            0x7823d7922d252781l },
-          0 },
-        /* 101 << 256 */
-        { { 0xea018b4cdedf9af0l,0x4b64c0a380c1d2f9l,0x527a0b1c36992c44l,
-            0x72a2408142b7adffl },
-          { 0x0023d10f97a502eel,0xc0f9ed067b401ac4l,0xabd1bd03d6d3b516l,
-            0xc320e3e478c5d0bel },
-          0 },
-        /* 107 << 256 */
-        { { 0x9f5d2a6a37dd009cl,0x88c0f42ac2c3cbacl,0x3155636977552a1el,
-            0xe78ec89d02f8098fl },
-          { 0x276c2ad71b6eeff9l,0xf4c49a28f7f91856l,0x698a2368dc795124l,
-            0x5502810de92a6c0fl },
-          0 },
-        /* 113 << 256 */
-        { { 0x82a5042e9f5e5192l,0x64da65fac0965a88l,0xf4c80dd56668399el,
-            0x635323757e33c233l },
-          { 0x5e5339b1a0048616l,0x4a17b1931c91741fl,0x65fdc7c213dcf3d0l,
-            0x230181426d10c410l },
-          0 },
-        /* 116 << 256 */
-        { { 0x090a04220f46c635l,0xc7eac842a04de3f5l,0x45b69d4c8990d4b2l,
-            0x032aeb50b8e0cdc6l },
-          { 0x02ce332a4ee3f307l,0x3c80c1545043980fl,0xc774838bcbd5287cl,
-            0x052661074a37d0ael },
-          0 },
-        /* 119 << 256 */
-        { { 0xc401b9c0f4d70fbfl,0xf82bbfde98ee47fel,0x94965118c84d91afl,
-            0xdd9a67c4d3b6ad1dl },
-          { 0x85c9cf1eb66a3ad4l,0x05580a0fbf5f514cl,0xf3ef0fd00218536el,
-            0x1dc2cf2bd14a7ca9l },
-          0 },
-        /* 125 << 256 */
-        { { 0x18c83e337c1e24d4l,0x30911165563657c6l,0xf9be1af679e53083l,
-            0x9b058059637753cel },
-          { 0x6a37fa24e54522b9l,0xc11d38b426dbf4c4l,0xbc6738655ebd4d9al,
-            0x2b40e9427fd4e2ecl },
-          0 },
-    },
-};
-
-/* Structure used to describe recoding of scalar multiplication. */
-typedef struct ecc_recode_sum {
-    /* Index into pre-computation table. */
-    uint8_t i;
-    /* Multiplier to add point into. */
-    uint8_t mul;
-    /* Use the negative of the point. */
-    uint8_t neg;
-} ecc_recode_sum;
-
-/* The index into pre-computation table to use. */
-static uint8_t recode_index_4_8[258] = {
-     0,  1,  1,  1,  3,  4,  2,  5,  3,  2,  4,  8,  3,  9,  5,  4,
-    11, 12,  6, 13,  7,  5,  8, 15, 55, 16,  9,  6, 18, 19,  7, 20,
-    11,  8, 12, 23, 24, 25, 13,  9, 27, 28, 14, 29, 30, 10, 15, 33,
-    11, 35, 16, 12, 37, 38, 17, 39, 18, 13, 19, 41, 42, 43, 20, 14,
-    45, 46, 21, 44, 22, 15, 23, 47, 24, 43, 25, 16, 42, 48, 26, 41,
-    27, 17, 28, 49, 18, 40, 29, 19, 30, 50, 31, 39, 32, 20, 33, 51,
-    34, 38, 35, 21, 37, 52, 22, 36, 37, 23, 38, 53, 24, 35, 39, 25,
-    34, 54, 40, 33, 55, 26, 32, 56, 27, 31, 43, 28, 30, 57, 44, 29,
-    45, 29, 44, 57, 30, 28, 43, 31, 27, 56, 32, 26, 55, 33, 40, 54,
-    34, 25, 39, 35, 24, 53, 38, 23, 37, 36, 22, 52, 37, 21, 35, 38,
-    34, 51, 33, 20, 32, 39, 31, 50, 30, 19, 29, 40, 18, 49, 28, 17,
-    27, 41, 26, 48, 42, 16, 25, 43, 24, 47, 23, 15, 22, 44, 21, 46,
-    45, 14, 20, 43, 42, 41, 19, 13, 18, 39, 17, 38, 37, 12, 16, 35,
-    11, 33, 15, 10, 30, 29, 14, 28, 27,  9, 13, 25, 24, 23, 12,  8,
-    11, 20,  7, 19, 18,  6,  9, 16, 55, 15,  8,  5,  7, 13,  6, 12,
-    11,  4,  5,  9,  3,  8,  4,  2,  3,  5,  2,  4,  3,  1,  1,  1,
-     0,  1,
-};
-
-/* Multiple to add point into. */
-static uint8_t recode_mul_4_8[258] = {
-     0,  1,  2,  3,  1,  1,  2,  1,  2,  3,  2,  1,  3,  1,  2,  3,
-     1,  1,  2,  1,  2,  3,  2,  1,  2,  1,  2,  3,  1,  1,  3,  1,
-     2,  3,  2,  1,  1,  1,  2,  3,  1,  1,  2,  1,  1,  3,  2,  1,
-     3,  1,  2,  3,  1,  1,  2,  1,  2,  3,  2,  1,  1,  1,  2,  3,
-     1,  1,  2,  3,  2,  3,  2,  1,  2,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  2,  1,  2,  3,  2,  3,  2,  1,
-     2,  3,  2,  3,  3,  1,  3,  3,  2,  3,  2,  1,  3,  3,  2,  3,
-     3,  1,  2,  3,  1,  3,  3,  1,  3,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  3,  1,  3,  3,  1,  3,  2,  1,
-     3,  3,  2,  3,  3,  1,  2,  3,  2,  3,  3,  1,  3,  3,  2,  3,
-     2,  1,  2,  3,  2,  3,  2,  1,  2,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  2,  1,  2,  3,  2,  3,  2,  1,
-     1,  3,  2,  1,  1,  1,  2,  3,  2,  1,  2,  1,  1,  3,  2,  1,
-     3,  1,  2,  3,  1,  1,  2,  1,  1,  3,  2,  1,  1,  1,  2,  3,
-     2,  1,  3,  1,  1,  3,  2,  1,  2,  1,  2,  3,  2,  1,  2,  1,
-     1,  3,  2,  1,  3,  1,  2,  3,  2,  1,  2,  1,  1,  3,  2,  1,
-     0,  1,
-};
-
-/* Whether to negate y-ordinate. */
-static uint8_t recode_neg_4_8[258] = {
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  1,  0,  0,  1,
-     0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-     0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,
-     1,  0,  0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  1,
-     0,  0,  1,  1,  0,  1,  1,  0,  1,  1,  0,  1,  1,  0,  1,  1,
-     0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,  1,  1,  0,
-     1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,
-     1,  0,  1,  1,  0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     0,  0,
-};
-
-/* Recode the scalar for multiplication using pre-computed values, multipliers
- * and subtraction.
- *
- * k  Scalar to multiply by.
- * v  Vector of operations to peform.
- */
-static void sp_256_ecc_recode_sum_8_4(sp_digit* k, ecc_recode_sum* v)
-{
-    int i, j;
-    uint16_t y;
-    int carry = 0;
-    int o;
-    sp_digit n;
-
-    j = 0;
-    n = k[j];
-    o = 0;
-    for (i=0; i<33; i++) {
-        y = n;
-        if (o + 8 < 64) {
-            y &= 0xff;
-            n >>= 8;
-            o += 8;
-        }
-        else if (o + 8 == 64) {
-            n >>= 8;
-            if (++j < 4)
-                n = k[j];
-            o = 0;
-        }
-        else if (++j < 4) {
-            n = k[j];
-            y |= (n << (64 - o)) & 0xff;
-            o -= 56;
-            n >>= o;
-        }
-
-        y += carry;
-        v[i].i = recode_index_4_8[y];
-        v[i].mul = recode_mul_4_8[y];
-        v[i].neg = recode_neg_4_8[y];
-        carry = (y >> 8) + v[i].neg;
-    }
-}
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[4];
-    sp_point pd;
-    sp_digit tmpd[2 * 4 * 5];
-#endif
-    sp_point* t;
-    sp_point* p;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode_sum v[33];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-    negy = tmp;
-
-    if (err == MP_OKAY) {
-        sp_256_ecc_recode_sum_8_4(k, v);
-
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        for (i=0; i<4; i++) {
-            XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod));
-            t[i].infinity = 1;
-        }
-
-        i = 32;
-        XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-        XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-        t[v[i].mul].infinity = p256_table[i][v[i].i].infinity;
-        for (--i; i>=0; i--) {
-            XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-            XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-            p->infinity = p256_table[i][v[i].i].infinity;
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_qz1_4(&t[v[i].mul], &t[v[i].mul], p, tmp);
-        }
-        sp_256_proj_point_add_4(&t[2], &t[2], &t[3], tmp);
-        sp_256_proj_point_add_4(&t[1], &t[1], &t[3], tmp);
-        sp_256_proj_point_dbl_4(&t[2], &t[2], tmp);
-        sp_256_proj_point_add_4(&t[1], &t[1], &t[2], tmp);
-
-        if (map)
-            sp_256_map_4(r, &t[1], tmp);
-        else
-            XMEMCPY(r, &t[1], sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(p, 0, heap);
-
-    return MP_OKAY;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, km);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN)
-/* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a  Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
-static int sp_256_iszero_4(const sp_digit* a)
-{
-    return (a[0] | a[1] | a[2] | a[3]) == 0;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */
-/* Add 1 to a. (a = a + 1)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_add_one_4(sp_digit* a)
-{
-    __asm__ __volatile__ (
-        "ldp	x1, x2,  [%[a], 0]\n\t"
-        "ldp	x3, x4,  [%[a], 16]\n\t"
-        "adds	x1, x1, #1\n\t"
-        "adcs	x2, x2, xzr\n\t"
-        "adcs	x3, x3, xzr\n\t"
-        "adcs	x4, x4, xzr\n\t"
-        "stp	x1, x2, [%[a], 0]\n\t"
-        "stp	x3, x4, [%[a], 16]\n\t"
-        :
-        : [a] "r" (a)
-        : "memory", "x1", "x2", "x3", "x4"
-    );
-}
-
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Generates a scalar that is in the range 1..order-1.
- *
- * rng  Random number generator.
- * k    Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k)
-{
-    int err;
-    byte buf[32];
-
-    do {
-        err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
-        if (err == 0) {
-            sp_256_from_bin(k, 4, buf, sizeof(buf));
-            if (sp_256_cmp_4(k, p256_order2) < 0) {
-                sp_256_add_one_4(k);
-                break;
-            }
-        }
-    }
-    while (err == 0);
-
-    return err;
-}
-
-/* Makes a random EC key pair.
- *
- * rng   Random number generator.
- * priv  Generated private value.
- * pub   Generated public point.
- * heap  Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point inf;
-#endif
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point* infinity;
-#endif
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, inf, infinity);
-#endif
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_ecc_gen_k_4(rng, k);
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, NULL);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL);
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            err = sp_256_ecc_mulmod_avx2_4(infinity, point, p256_order, 1,
-                                                                          NULL);
-        }
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL);
-    }
-    if (err == MP_OKAY) {
-        if (!sp_256_iszero_4(point->x) || !sp_256_iszero_4(point->y))
-            err = ECC_INF_E;
-    }
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(k, priv);
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, pub);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_ecc_point_free(infinity, 1, heap);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-
-#ifdef HAVE_ECC_DHE
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 32
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_256_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 256 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<4 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv    Scalar to multiply the point by.
- * pub     Point to multiply.
- * out     Buffer to hold X ordinate.
- * outLen  On entry, size of the buffer in bytes.
- *         On exit, length of data in buffer in bytes.
- * heap    Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outLen, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point = NULL;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 32)
-        err = BUFFER_E;
-
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, priv);
-        sp_256_point_from_ecc_point_4(point, pub);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(point, point, k, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(point, point, k, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        sp_256_to_bin(point->x, out);
-        *outLen = 32;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_DHE */
-
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x3, x4, [%[a], 0]\n\t"
-        "ldp	x5, x6, [%[a], 16]\n\t"
-        "ldp	x7, x8, [%[b], 0]\n\t"
-        "ldp	x9, x10, [%[b], 16]\n\t"
-        "adds	x3, x3, x7\n\t"
-        "adcs	x4, x4, x8\n\t"
-        "adcs	x5, x5, x9\n\t"
-        "adcs	x6, x6, x10\n\t"
-        "stp	x3, x4, [%[r], 0]\n\t"
-        "stp	x5, x6, [%[r], 16]\n\t"
-        "cset	%[c], cs\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"
-    );
-
-    return c;
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	x5, 0\n\t"
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 24\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[b], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 32\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 48\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b)
-{
-    sp_digit tmp[4];
-
-    __asm__ __volatile__ (
-        "ldp	x8, x9, [%[a], 0]\n\t"
-        "ldp	x10, x11, [%[a], 16]\n\t"
-        "ldp	x12, x13, [%[b], 0]\n\t"
-        "ldp	x14, x15, [%[b], 16]\n\t"
-        "#  A[0] * B[0]\n\t"
-        "mul	x3, x8, x12\n\t"
-        "umulh	x4, x8, x12\n\t"
-        "str	x3, [%[tmp]]\n\t"
-        "#  A[0] * B[1]\n\t"
-        "mul	x6, x8, x13\n\t"
-        "umulh	x7, x8, x13\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adc	x5, xzr, x7\n\t"
-        "#  A[1] * B[0]\n\t"
-        "mul	x6, x9, x12\n\t"
-        "umulh	x7, x9, x12\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "str	x4, [%[tmp], 8]\n\t"
-        "#  A[0] * B[2]\n\t"
-        "mul	x6, x8, x14\n\t"
-        "umulh	x7, x8, x14\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[1] * B[1]\n\t"
-        "mul	x6, x9, x13\n\t"
-        "umulh	x7, x9, x13\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[2] * B[0]\n\t"
-        "mul	x6, x10, x12\n\t"
-        "umulh	x7, x10, x12\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[tmp], 16]\n\t"
-        "#  A[0] * B[3]\n\t"
-        "mul	x6, x8, x15\n\t"
-        "umulh	x7, x8, x15\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, xzr, xzr\n\t"
-        "#  A[1] * B[2]\n\t"
-        "mul	x6, x9, x14\n\t"
-        "umulh	x7, x9, x14\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[2] * B[1]\n\t"
-        "mul	x6, x10, x13\n\t"
-        "umulh	x7, x10, x13\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "#  A[3] * B[0]\n\t"
-        "mul	x6, x11, x12\n\t"
-        "umulh	x7, x11, x12\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adcs	x4, x4, x7\n\t"
-        "adc	x5, x5, xzr\n\t"
-        "str	x3, [%[tmp], 24]\n\t"
-        "#  A[1] * B[3]\n\t"
-        "mul	x6, x9, x15\n\t"
-        "umulh	x7, x9, x15\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "#  A[2] * B[2]\n\t"
-        "mul	x6, x10, x14\n\t"
-        "umulh	x7, x10, x14\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[3] * B[1]\n\t"
-        "mul	x6, x11, x13\n\t"
-        "umulh	x7, x11, x13\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 32]\n\t"
-        "#  A[2] * B[3]\n\t"
-        "mul	x6, x10, x15\n\t"
-        "umulh	x7, x10, x15\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "#  A[3] * B[2]\n\t"
-        "mul	x6, x11, x14\n\t"
-        "umulh	x7, x11, x14\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x5, [%[r], 40]\n\t"
-        "#  A[3] * B[3]\n\t"
-        "mul	x6, x11, x15\n\t"
-        "umulh	x7, x11, x15\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "stp	x3, x4, [%[r], 48]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef HAVE_INTEL_AVX2
-#endif /* HAVE_INTEL_AVX2 */
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-static sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "ldp	x2, x3, [%[a], 0]\n\t"
-        "ldp	x4, x5, [%[a], 16]\n\t"
-        "ldp	x6, x7, [%[b], 0]\n\t"
-        "ldp	x8, x9, [%[b], 16]\n\t"
-        "subs	x2, x2, x6\n\t"
-        "sbcs	x3, x3, x7\n\t"
-        "sbcs	x4, x4, x8\n\t"
-        "sbcs	x5, x5, x9\n\t"
-        "stp	x2, x3, [%[a], 0]\n\t"
-        "stp	x4, x5, [%[a], 16]\n\t"
-        "csetm	%[c], cc\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
-    );
-
-    return c;
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-static void sp_256_mul_d_4(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "ldr	x8, [%[a]]\n\t"
-        "mul	x3, %[b], x8\n\t"
-        "umulh	x4, %[b], x8\n\t"
-        "mov	x5, 0\n\t"
-        "str	x3, [%[r]]\n\t"
-        "# A[1] * B\n\t"
-        "ldr		x8, [%[a], 8]\n\t"
-        "mov		x3, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x4, x4, x6\n\t"
-        "adcs	x5, x5, x7\n\t"
-        "adc		x3, xzr, xzr\n\t"
-        "str		x4, [%[r], 8]\n\t"
-        "# A[2] * B\n\t"
-        "ldr		x8, [%[a], 16]\n\t"
-        "mov		x4, 0\n\t"
-        "mul		x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x5, x5, x6\n\t"
-        "adcs	x3, x3, x7\n\t"
-        "adc		x4, xzr, xzr\n\t"
-        "str		x5, [%[r], 16]\n\t"
-        "# A[3] * B\n\t"
-        "ldr	x8, [%[a], 24]\n\t"
-        "mul	x6, %[b], x8\n\t"
-        "umulh	x7, %[b], x8\n\t"
-        "adds	x3, x3, x6\n\t"
-        "adc	x4, x4, x7\n\t"
-        "str	x3, [%[r], 24]\n\t"
-        "str	x4, [%[r], 32]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8"
-    );
-}
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_256_word_4(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "lsr	x5, %[div], 32\n\t"
-        "add	x5, x5, 1\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x6, x3, 32\n\t"
-        "mul	x4, %[div], x6\n\t"
-        "umulh	x3, %[div], x6\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d1], x5\n\t"
-        "lsl	x3, x3, 32\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "lsl	x3, %[d1], 32\n\t"
-        "orr	x3, x3, %[d0], lsr 32\n\t"
-
-        "udiv	x3, x3, x5\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x4, %[div], x3\n\t"
-        "umulh	x3, %[div], x3\n\t"
-        "subs	%[d0], %[d0], x4\n\t"
-        "sbc	%[d1], %[d1], x3\n\t"
-
-        "udiv	x3, %[d0], %[div]\n\t"
-        "add	x6, x6, x3\n\t"
-        "mul	x3, %[div], x3\n\t"
-        "sub	%[d0], %[d0], x3\n\t"
-        "mov	%[r], x6\n\t"
-
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "x3", "x4", "x5", "x6"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_256_mask_4(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<4; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-#endif
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_div_4(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[8], t2[5];
-    sp_digit div, r1;
-    int i;
-
-    (void)m;
-
-    div = d[3];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 4);
-    for (i=3; i>=0; i--) {
-        r1 = div_256_word_4(t1[4 + i], t1[4 + i - 1], div);
-
-        sp_256_mul_d_4(t2, d, r1);
-        t1[4 + i] += sp_256_sub_in_place_4(&t1[i], t2);
-        t1[4 + i] -= t2[4];
-        sp_256_mask_4(t2, d, t1[4 + i]);
-        t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2);
-        sp_256_mask_4(t2, d, t1[4 + i]);
-        t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_256_cmp_4(t1, d) >= 0;
-    sp_256_cond_sub_4(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_mod_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_256_div_4(a, m, NULL, r);
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_sqr_4(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[8];
-
-    __asm__ __volatile__ (
-        "mov	x6, 0\n\t"
-        "mov	x7, 0\n\t"
-        "mov	x8, 0\n\t"
-        "mov	x5, 0\n\t"
-        "\n1:\n\t"
-        "subs	x3, x5, 24\n\t"
-        "csel	x3, xzr, x3, cc\n\t"
-        "sub	x4, x5, x3\n\t"
-        "\n2:\n\t"
-        "cmp	x4, x3\n\t"
-        "b.eq	4f\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "ldr	x11, [%[a], x4]\n\t"
-        "mul	x9, x10, x11\n\t"
-        "umulh	x10, x10, x11\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "b.al	5f\n\t"
-        "\n4:\n\t"
-        "ldr	x10, [%[a], x3]\n\t"
-        "mul	x9, x10, x10\n\t"
-        "umulh	x10, x10, x10\n\t"
-        "adds	x6, x6, x9\n\t"
-        "adcs	x7, x7, x10\n\t"
-        "adc	x8, x8, xzr\n\t"
-        "\n5:\n\t"
-        "add	x3, x3, #8\n\t"
-        "sub	x4, x4, #8\n\t"
-        "cmp	x3, 32\n\t"
-        "b.eq	3f\n\t"
-        "cmp	x3, x4\n\t"
-        "b.gt	3f\n\t"
-        "cmp	x3, x5\n\t"
-        "b.le	2b\n\t"
-        "\n3:\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        "mov	x6, x7\n\t"
-        "mov	x7, x8\n\t"
-        "mov	x8, #0\n\t"
-        "add	x5, x5, #8\n\t"
-        "cmp	x5, 48\n\t"
-        "b.le	1b\n\t"
-        "str	x6, [%[r], x5]\n\t"
-        :
-        : [r] "r" (tmp), [a] "r" (a)
-        : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_sqr_4(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[4];
-
-    __asm__ __volatile__ (
-        "ldp	x10, x11, [%[a], 0]\n\t"
-        "ldp	x12, x13, [%[a], 16]\n\t"
-        "#  A[0] * A[0]\n\t"
-        "mul	x2, x10, x10\n\t"
-        "umulh	x3, x10, x10\n\t"
-        "str	x2, [%[tmp]]\n\t"
-        "mov	x4, 0\n\t"
-        "#  A[0] * A[1]\n\t"
-        "mul	x8, x10, x11\n\t"
-        "umulh	x9, x10, x11\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[tmp], 8]\n\t"
-        "#  A[0] * A[2]\n\t"
-        "mul	x8, x10, x12\n\t"
-        "umulh	x9, x10, x12\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "#  A[1] * A[1]\n\t"
-        "mul	x8, x11, x11\n\t"
-        "umulh	x9, x11, x11\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[tmp], 16]\n\t"
-        "#  A[0] * A[3]\n\t"
-        "mul	x8, x10, x13\n\t"
-        "umulh	x9, x10, x13\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, xzr, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "#  A[1] * A[2]\n\t"
-        "mul	x8, x11, x12\n\t"
-        "umulh	x9, x11, x12\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adcs	x3, x3, x9\n\t"
-        "adc	x4, x4, xzr\n\t"
-        "str	x2, [%[tmp], 24]\n\t"
-        "#  A[1] * A[3]\n\t"
-        "mul	x8, x11, x13\n\t"
-        "umulh	x9, x11, x13\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, xzr, xzr\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "#  A[2] * A[2]\n\t"
-        "mul	x8, x12, x12\n\t"
-        "umulh	x9, x12, x12\n\t"
-        "adds	x3, x3, x8\n\t"
-        "adcs	x4, x4, x9\n\t"
-        "adc	x2, x2, xzr\n\t"
-        "str	x3, [%[r], 32]\n\t"
-        "#  A[2] * A[3]\n\t"
-        "mul	x8, x12, x13\n\t"
-        "umulh	x9, x12, x13\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, xzr, xzr\n\t"
-        "adds	x4, x4, x8\n\t"
-        "adcs	x2, x2, x9\n\t"
-        "adc	x3, x3, xzr\n\t"
-        "str	x4, [%[r], 40]\n\t"
-        "#  A[3] * A[3]\n\t"
-        "mul	x8, x13, x13\n\t"
-        "umulh	x9, x13, x13\n\t"
-        "adds	x2, x2, x8\n\t"
-        "adc	x3, x3, x9\n\t"
-        "stp	x2, x3, [%[r], 48]\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Order-2 for the P256 curve. */
-static const uint64_t p256_order_2[4] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff,
-    0xffffffff00000000
-};
-#else
-/* The low half of the order-2 of the P256 curve. */
-static const uint64_t p256_order_low[2] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84
-};
-#endif /* WOLFSSL_SP_SMALL */
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_4(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_4(r, a, b);
-    sp_256_mont_reduce_4(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_4(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_4(r, a);
-    sp_256_mont_reduce_4(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_4(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_4(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_4(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_4(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_4(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_4(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_4(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_4(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_4(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_4(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_4(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_4(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_4(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_4(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_4(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_4(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_4(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_avx2_4(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_avx2_4(r, a, b);
-    sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_avx2_4(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_avx2_4(r, a);
-    sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_avx2_4(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_avx2_4(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_avx2_4(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_4(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_avx2_4(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_avx2_4(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_avx2_4(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_avx2_4(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
-#ifdef HAVE_ECC_SIGN
-#ifndef SP_ECC_MAX_SIG_GEN
-#define SP_ECC_MAX_SIG_GEN  64
-#endif
-
-/* Sign the hash using the private key.
- *   e = [hash, 256 bits] from binary
- *   r = (k.G)->x mod order
- *   s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit ed[2*4];
-    sp_digit xd[2*4];
-    sp_digit kd[2*4];
-    sp_digit rd[2*4];
-    sp_digit td[3 * 2*4];
-    sp_point p;
-#endif
-    sp_digit* e = NULL;
-    sp_digit* x = NULL;
-    sp_digit* k = NULL;
-    sp_digit* r = NULL;
-    sp_digit* tmp = NULL;
-    sp_point* point = NULL;
-    sp_digit carry;
-    sp_digit* s;
-    sp_digit* kInv;
-    int err = MP_OKAY;
-    int64_t c;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            e = d + 0 * 4;
-            x = d + 2 * 4;
-            k = d + 4 * 4;
-            r = d + 6 * 4;
-            tmp = d + 8 * 4;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    e = ed;
-    x = xd;
-    k = kd;
-    r = rd;
-    tmp = td;
-#endif
-    s = e;
-    kInv = k;
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(e, 4, hash, hashLen);
-        sp_256_from_mp(x, 4, priv);
-    }
-
-    for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
-        /* New random point. */
-        err = sp_256_ecc_gen_k_4(rng, k);
-        if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, heap);
-            else
-#endif
-                err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL);
-        }
-
-        if (err == MP_OKAY) {
-            /* r = point->x mod order */
-            XMEMCPY(r, point->x, sizeof(sp_digit) * 4);
-            sp_256_norm_4(r);
-            c = sp_256_cmp_4(r, p256_order);
-            sp_256_cond_sub_4(r, r, p256_order, 0 - (c >= 0));
-            sp_256_norm_4(r);
-
-            /* Conv k to Montgomery form (mod order) */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_4(k, k, p256_norm_order);
-            else
-#endif
-                sp_256_mul_4(k, k, p256_norm_order);
-            err = sp_256_mod_4(k, k, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_4(k);
-            /* kInv = 1/k mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_inv_order_avx2_4(kInv, k, tmp);
-            else
-#endif
-                sp_256_mont_inv_order_4(kInv, k, tmp);
-            sp_256_norm_4(kInv);
-
-            /* s = r * x + e */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_4(x, x, r);
-            else
-#endif
-                sp_256_mul_4(x, x, r);
-            err = sp_256_mod_4(x, x, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_4(x);
-            carry = sp_256_add_4(s, e, x);
-            sp_256_cond_sub_4(s, s, p256_order, 0 - carry);
-            sp_256_norm_4(s);
-            c = sp_256_cmp_4(s, p256_order);
-            sp_256_cond_sub_4(s, s, p256_order, 0 - (c >= 0));
-            sp_256_norm_4(s);
-
-            /* s = s * k^-1 mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_mul_order_avx2_4(s, s, kInv);
-            else
-#endif
-                sp_256_mont_mul_order_4(s, s, kInv);
-            sp_256_norm_4(s);
-
-            /* Check that signature is usable. */
-            if (!sp_256_iszero_4(s))
-                break;
-        }
-    }
-
-    if (i == 0)
-        err = RNG_FAILURE_E;
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(r, rm);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(s, sm);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4);
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    XMEMSET(e, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(x, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(k, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*4);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-/* Verify the signature values with the hash and public key.
- *   e = Truncate(hash, 256)
- *   u1 = e/s mod order
- *   u2 = r/s mod order
- *   r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- *   (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- *   (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
-    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit u1d[2*4];
-    sp_digit u2d[2*4];
-    sp_digit sd[2*4];
-    sp_digit tmpd[2*4 * 5];
-    sp_point p1d;
-    sp_point p2d;
-#endif
-    sp_digit* u1;
-    sp_digit* u2;
-    sp_digit* s;
-    sp_digit* tmp;
-    sp_point* p1;
-    sp_point* p2 = NULL;
-    sp_digit carry;
-    int64_t c;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p1d, p1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p2d, p2);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            u1  = d + 0 * 4;
-            u2  = d + 2 * 4;
-            s   = d + 4 * 4;
-            tmp = d + 6 * 4;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    u1 = u1d;
-    u2 = u2d;
-    s  = sd;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(u1, 4, hash, hashLen);
-        sp_256_from_mp(u2, 4, r);
-        sp_256_from_mp(s, 4, sm);
-        sp_256_from_mp(p2->x, 4, pX);
-        sp_256_from_mp(p2->y, 4, pY);
-        sp_256_from_mp(p2->z, 4, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_avx2_4(s, s, p256_norm_order);
-        else
-#endif
-            sp_256_mul_4(s, s, p256_norm_order);
-        err = sp_256_mod_4(s, s, p256_order);
-    }
-    if (err == MP_OKAY) {
-        sp_256_norm_4(s);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_inv_order_avx2_4(s, s, tmp);
-            sp_256_mont_mul_order_avx2_4(u1, u1, s);
-            sp_256_mont_mul_order_avx2_4(u2, u2, s);
-        }
-        else
-#endif
-        {
-            sp_256_mont_inv_order_4(s, s, tmp);
-            sp_256_mont_mul_order_4(u1, u1, s);
-            sp_256_mont_mul_order_4(u2, u2, s);
-        }
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap);
-    }
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp);
-        else
-#endif
-            sp_256_proj_point_add_4(p1, p1, p2, tmp);
-
-        /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
-        /* Reload r and convert to Montgomery form. */
-        sp_256_from_mp(u2, 4, r);
-        err = sp_256_mod_mul_norm_4(u2, u2, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* u1 = r.z'.z' mod prime */
-        sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod);
-        *res = sp_256_cmp_4(p1->x, u1) == 0;
-        if (*res == 0) {
-            /* Reload r and add order. */
-            sp_256_from_mp(u2, 4, r);
-            carry = sp_256_add_4(u2, u2, p256_order);
-            /* Carry means result is greater than mod and is not valid. */
-            if (!carry) {
-                sp_256_norm_4(u2);
-
-                /* Compare with mod and if greater or equal then not valid. */
-                c = sp_256_cmp_4(u2, p256_mod);
-                if (c < 0) {
-                    /* Convert to Montogomery form */
-                    err = sp_256_mod_mul_norm_4(u2, u2, p256_mod);
-                    if (err == MP_OKAY) {
-                        /* u1 = (r + 1*order).z'.z' mod prime */
-                        sp_256_mont_mul_4(u1, u2, p1->z, p256_mod,
-                                                                  p256_mp_mod);
-                        *res = sp_256_cmp_4(p1->x, u2) == 0;
-                    }
-                }
-            }
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p1, 0, heap);
-    sp_ecc_point_free(p2, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_CHECK_KEY
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * point  EC point.
- * heap   Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-static int sp_256_ecc_is_point_4(sp_point* point, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit t1d[2*4];
-    sp_digit t2d[2*4];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 4;
-        t2 = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    (void)heap;
-
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_sqr_4(t1, point->y);
-        sp_256_mod_4(t1, t1, p256_mod);
-        sp_256_sqr_4(t2, point->x);
-        sp_256_mod_4(t2, t2, p256_mod);
-        sp_256_mul_4(t2, t2, point->x);
-        sp_256_mod_4(t2, t2, p256_mod);
-	sp_256_sub_4(t2, p256_mod, t2);
-        sp_256_mont_add_4(t1, t1, t2, p256_mod);
-
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-
-        if (sp_256_cmp_4(t1, p256_b) != 0)
-            err = MP_VAL;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX  X ordinate of EC point.
- * pY  Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point pubd;
-#endif
-    sp_point* pub;
-    byte one[1] = { 1 };
-    int err;
-
-    err = sp_ecc_point_new(NULL, pubd, pub);
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 4, pX);
-        sp_256_from_mp(pub->y, 4, pY);
-        sp_256_from_bin(pub->z, 4, one, sizeof(one));
-
-        err = sp_256_ecc_is_point_4(pub, NULL);
-    }
-
-    sp_ecc_point_free(pub, 0, NULL);
-
-    return err;
-}
-
-/* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX     X ordinate of EC point.
- * pY     Y ordinate of EC point.
- * privm  Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit privd[4];
-    sp_point pubd;
-    sp_point pd;
-#endif
-    sp_digit* priv = NULL;
-    sp_point* pub;
-    sp_point* p = NULL;
-    byte one[1] = { 1 };
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, pubd, pub);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        priv = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (priv == NULL)
-            err = MEMORY_E;
-    }
-#else
-    priv = privd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 4, pX);
-        sp_256_from_mp(pub->y, 4, pY);
-        sp_256_from_bin(pub->z, 4, one, sizeof(one));
-        sp_256_from_mp(priv, 4, privm);
-
-        /* Check point at infinitiy. */
-        if (sp_256_iszero_4(pub->x) &&
-            sp_256_iszero_4(pub->y))
-            err = ECC_INF_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check range of X and Y */
-        if (sp_256_cmp_4(pub->x, p256_mod) >= 0 ||
-            sp_256_cmp_4(pub->y, p256_mod) >= 0)
-            err = ECC_OUT_OF_RANGE_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check point is on curve */
-        err = sp_256_ecc_is_point_4(pub, heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* Point * order = infinity */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(p, pub, p256_order, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is infinity */
-        if (!sp_256_iszero_4(p->x) ||
-            !sp_256_iszero_4(p->y)) {
-            err = ECC_INF_E;
-        }
-    }
-
-    if (err == MP_OKAY) {
-        /* Base * private = point */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(p, priv, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is public key */
-        if (sp_256_cmp_4(p->x, pub->x) != 0 ||
-            sp_256_cmp_4(p->y, pub->y) != 0) {
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (priv != NULL)
-        XFREE(priv, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(pub, 0, heap);
-
-    return err;
-}
-#endif
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-/* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX   First EC point's X ordinate.
- * pY   First EC point's Y ordinate.
- * pZ   First EC point's Z ordinate.
- * qX   Second EC point's X ordinate.
- * qY   Second EC point's Y ordinate.
- * qZ   Second EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 5];
-    sp_point pd;
-    sp_point qd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    sp_point* q = NULL;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(NULL, qd, q);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-        sp_256_from_mp(q->x, 4, qX);
-        sp_256_from_mp(q->y, 4, qY);
-        sp_256_from_mp(q->z, 4, qZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_4(p, p, q, tmp);
-        else
-#endif
-            sp_256_proj_point_add_4(p, p, q, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(q, 0, NULL);
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 2];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_dbl_avx2_4(p, p, tmp);
-        else
-#endif
-            sp_256_proj_point_dbl_4(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 4];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-
-        sp_256_map_4(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, pX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
-#ifdef HAVE_COMP_KEY
-/* Find the square root of a number mod the prime of the curve.
- *
- * y  The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mont_sqrt_4(sp_digit* y)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit t1d[2 * 4];
-    sp_digit t2d[2 * 4];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 4;
-        t2 = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_avx2_4(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_avx2_4(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_avx2_4(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_avx2_4(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Uncompress the point given the X ordinate.
- *
- * xm    X ordinate.
- * odd   Whether the Y ordinate is odd.
- * ym    Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit xd[2 * 4];
-    sp_digit yd[2 * 4];
-#endif
-    sp_digit* x;
-    sp_digit* y;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        x = d + 0 * 4;
-        y = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    x = xd;
-    y = yd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(x, 4, xm);
-
-        err = sp_256_mod_mul_norm_4(x, x, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* y = x^3 */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_sqr_avx2_4(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod);
-        }
-        /* y = x^3 - 3x */
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        /* y = x^3 - 3x + b */
-        err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod);
-    }
-    if (err == MP_OKAY) {
-        sp_256_mont_add_4(y, y, x, p256_mod);
-        /* y = sqrt(x^3 - 3x + b) */
-        err = sp_256_mont_sqrt_4(y);
-    }
-    if (err == MP_OKAY) {
-        XMEMSET(y + 4, 0, 4 * sizeof(sp_digit));
-        sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod);
-        if (((y[0] ^ odd) & 1) != 0)
-            sp_256_mont_sub_4(y, p256_mod, y, p256_mod);
-
-        err = sp_256_to_mp(y, ym);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-#endif /* WOLFSSL_SP_ARM64_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
--- a/wolfcrypt/src/sp_c32.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12824 +0,0 @@
-/* sp.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#ifdef RSA_LOW_MEM
-#define SP_RSA_PRIVATE_EXP_D
-
-#ifndef WOLFSSL_SP_SMALL
-#define WOLFSSL_SP_SMALL
-#endif
-#endif
-
-#include <wolfssl/wolfcrypt/sp.h>
-
-#ifndef WOLFSSL_SP_ASM
-#if SP_WORD_SIZE == 32
-#if defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)
-/* Mask for address to obfuscate which of the two address will be used. */
-static const size_t addr_mask[2] = { 0, (size_t)-1 };
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
-#ifndef WOLFSSL_SP_NO_2048
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 15) {
-            r[j] &= 0x7fffff;
-            s = 23 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 23
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 23
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0x7fffff;
-        s = 23 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 23 <= DIGIT_BIT) {
-            s += 23;
-            r[j] &= 0x7fffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 23) {
-            r[j] &= 0x7fffff;
-            if (j + 1 >= max)
-                break;
-            s = 23 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 256
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_2048_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<89; i++) {
-        r[i+1] += r[i] >> 23;
-        r[i] &= 0x7fffff;
-    }
-    j = 2048 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<90 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 23) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 23);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_15(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int64_t t0   = ((int64_t)a[ 0]) * b[ 0];
-    int64_t t1   = ((int64_t)a[ 0]) * b[ 1]
-                 + ((int64_t)a[ 1]) * b[ 0];
-    int64_t t2   = ((int64_t)a[ 0]) * b[ 2]
-                 + ((int64_t)a[ 1]) * b[ 1]
-                 + ((int64_t)a[ 2]) * b[ 0];
-    int64_t t3   = ((int64_t)a[ 0]) * b[ 3]
-                 + ((int64_t)a[ 1]) * b[ 2]
-                 + ((int64_t)a[ 2]) * b[ 1]
-                 + ((int64_t)a[ 3]) * b[ 0];
-    int64_t t4   = ((int64_t)a[ 0]) * b[ 4]
-                 + ((int64_t)a[ 1]) * b[ 3]
-                 + ((int64_t)a[ 2]) * b[ 2]
-                 + ((int64_t)a[ 3]) * b[ 1]
-                 + ((int64_t)a[ 4]) * b[ 0];
-    int64_t t5   = ((int64_t)a[ 0]) * b[ 5]
-                 + ((int64_t)a[ 1]) * b[ 4]
-                 + ((int64_t)a[ 2]) * b[ 3]
-                 + ((int64_t)a[ 3]) * b[ 2]
-                 + ((int64_t)a[ 4]) * b[ 1]
-                 + ((int64_t)a[ 5]) * b[ 0];
-    int64_t t6   = ((int64_t)a[ 0]) * b[ 6]
-                 + ((int64_t)a[ 1]) * b[ 5]
-                 + ((int64_t)a[ 2]) * b[ 4]
-                 + ((int64_t)a[ 3]) * b[ 3]
-                 + ((int64_t)a[ 4]) * b[ 2]
-                 + ((int64_t)a[ 5]) * b[ 1]
-                 + ((int64_t)a[ 6]) * b[ 0];
-    int64_t t7   = ((int64_t)a[ 0]) * b[ 7]
-                 + ((int64_t)a[ 1]) * b[ 6]
-                 + ((int64_t)a[ 2]) * b[ 5]
-                 + ((int64_t)a[ 3]) * b[ 4]
-                 + ((int64_t)a[ 4]) * b[ 3]
-                 + ((int64_t)a[ 5]) * b[ 2]
-                 + ((int64_t)a[ 6]) * b[ 1]
-                 + ((int64_t)a[ 7]) * b[ 0];
-    int64_t t8   = ((int64_t)a[ 0]) * b[ 8]
-                 + ((int64_t)a[ 1]) * b[ 7]
-                 + ((int64_t)a[ 2]) * b[ 6]
-                 + ((int64_t)a[ 3]) * b[ 5]
-                 + ((int64_t)a[ 4]) * b[ 4]
-                 + ((int64_t)a[ 5]) * b[ 3]
-                 + ((int64_t)a[ 6]) * b[ 2]
-                 + ((int64_t)a[ 7]) * b[ 1]
-                 + ((int64_t)a[ 8]) * b[ 0];
-    int64_t t9   = ((int64_t)a[ 0]) * b[ 9]
-                 + ((int64_t)a[ 1]) * b[ 8]
-                 + ((int64_t)a[ 2]) * b[ 7]
-                 + ((int64_t)a[ 3]) * b[ 6]
-                 + ((int64_t)a[ 4]) * b[ 5]
-                 + ((int64_t)a[ 5]) * b[ 4]
-                 + ((int64_t)a[ 6]) * b[ 3]
-                 + ((int64_t)a[ 7]) * b[ 2]
-                 + ((int64_t)a[ 8]) * b[ 1]
-                 + ((int64_t)a[ 9]) * b[ 0];
-    int64_t t10  = ((int64_t)a[ 0]) * b[10]
-                 + ((int64_t)a[ 1]) * b[ 9]
-                 + ((int64_t)a[ 2]) * b[ 8]
-                 + ((int64_t)a[ 3]) * b[ 7]
-                 + ((int64_t)a[ 4]) * b[ 6]
-                 + ((int64_t)a[ 5]) * b[ 5]
-                 + ((int64_t)a[ 6]) * b[ 4]
-                 + ((int64_t)a[ 7]) * b[ 3]
-                 + ((int64_t)a[ 8]) * b[ 2]
-                 + ((int64_t)a[ 9]) * b[ 1]
-                 + ((int64_t)a[10]) * b[ 0];
-    int64_t t11  = ((int64_t)a[ 0]) * b[11]
-                 + ((int64_t)a[ 1]) * b[10]
-                 + ((int64_t)a[ 2]) * b[ 9]
-                 + ((int64_t)a[ 3]) * b[ 8]
-                 + ((int64_t)a[ 4]) * b[ 7]
-                 + ((int64_t)a[ 5]) * b[ 6]
-                 + ((int64_t)a[ 6]) * b[ 5]
-                 + ((int64_t)a[ 7]) * b[ 4]
-                 + ((int64_t)a[ 8]) * b[ 3]
-                 + ((int64_t)a[ 9]) * b[ 2]
-                 + ((int64_t)a[10]) * b[ 1]
-                 + ((int64_t)a[11]) * b[ 0];
-    int64_t t12  = ((int64_t)a[ 0]) * b[12]
-                 + ((int64_t)a[ 1]) * b[11]
-                 + ((int64_t)a[ 2]) * b[10]
-                 + ((int64_t)a[ 3]) * b[ 9]
-                 + ((int64_t)a[ 4]) * b[ 8]
-                 + ((int64_t)a[ 5]) * b[ 7]
-                 + ((int64_t)a[ 6]) * b[ 6]
-                 + ((int64_t)a[ 7]) * b[ 5]
-                 + ((int64_t)a[ 8]) * b[ 4]
-                 + ((int64_t)a[ 9]) * b[ 3]
-                 + ((int64_t)a[10]) * b[ 2]
-                 + ((int64_t)a[11]) * b[ 1]
-                 + ((int64_t)a[12]) * b[ 0];
-    int64_t t13  = ((int64_t)a[ 0]) * b[13]
-                 + ((int64_t)a[ 1]) * b[12]
-                 + ((int64_t)a[ 2]) * b[11]
-                 + ((int64_t)a[ 3]) * b[10]
-                 + ((int64_t)a[ 4]) * b[ 9]
-                 + ((int64_t)a[ 5]) * b[ 8]
-                 + ((int64_t)a[ 6]) * b[ 7]
-                 + ((int64_t)a[ 7]) * b[ 6]
-                 + ((int64_t)a[ 8]) * b[ 5]
-                 + ((int64_t)a[ 9]) * b[ 4]
-                 + ((int64_t)a[10]) * b[ 3]
-                 + ((int64_t)a[11]) * b[ 2]
-                 + ((int64_t)a[12]) * b[ 1]
-                 + ((int64_t)a[13]) * b[ 0];
-    int64_t t14  = ((int64_t)a[ 0]) * b[14]
-                 + ((int64_t)a[ 1]) * b[13]
-                 + ((int64_t)a[ 2]) * b[12]
-                 + ((int64_t)a[ 3]) * b[11]
-                 + ((int64_t)a[ 4]) * b[10]
-                 + ((int64_t)a[ 5]) * b[ 9]
-                 + ((int64_t)a[ 6]) * b[ 8]
-                 + ((int64_t)a[ 7]) * b[ 7]
-                 + ((int64_t)a[ 8]) * b[ 6]
-                 + ((int64_t)a[ 9]) * b[ 5]
-                 + ((int64_t)a[10]) * b[ 4]
-                 + ((int64_t)a[11]) * b[ 3]
-                 + ((int64_t)a[12]) * b[ 2]
-                 + ((int64_t)a[13]) * b[ 1]
-                 + ((int64_t)a[14]) * b[ 0];
-    int64_t t15  = ((int64_t)a[ 1]) * b[14]
-                 + ((int64_t)a[ 2]) * b[13]
-                 + ((int64_t)a[ 3]) * b[12]
-                 + ((int64_t)a[ 4]) * b[11]
-                 + ((int64_t)a[ 5]) * b[10]
-                 + ((int64_t)a[ 6]) * b[ 9]
-                 + ((int64_t)a[ 7]) * b[ 8]
-                 + ((int64_t)a[ 8]) * b[ 7]
-                 + ((int64_t)a[ 9]) * b[ 6]
-                 + ((int64_t)a[10]) * b[ 5]
-                 + ((int64_t)a[11]) * b[ 4]
-                 + ((int64_t)a[12]) * b[ 3]
-                 + ((int64_t)a[13]) * b[ 2]
-                 + ((int64_t)a[14]) * b[ 1];
-    int64_t t16  = ((int64_t)a[ 2]) * b[14]
-                 + ((int64_t)a[ 3]) * b[13]
-                 + ((int64_t)a[ 4]) * b[12]
-                 + ((int64_t)a[ 5]) * b[11]
-                 + ((int64_t)a[ 6]) * b[10]
-                 + ((int64_t)a[ 7]) * b[ 9]
-                 + ((int64_t)a[ 8]) * b[ 8]
-                 + ((int64_t)a[ 9]) * b[ 7]
-                 + ((int64_t)a[10]) * b[ 6]
-                 + ((int64_t)a[11]) * b[ 5]
-                 + ((int64_t)a[12]) * b[ 4]
-                 + ((int64_t)a[13]) * b[ 3]
-                 + ((int64_t)a[14]) * b[ 2];
-    int64_t t17  = ((int64_t)a[ 3]) * b[14]
-                 + ((int64_t)a[ 4]) * b[13]
-                 + ((int64_t)a[ 5]) * b[12]
-                 + ((int64_t)a[ 6]) * b[11]
-                 + ((int64_t)a[ 7]) * b[10]
-                 + ((int64_t)a[ 8]) * b[ 9]
-                 + ((int64_t)a[ 9]) * b[ 8]
-                 + ((int64_t)a[10]) * b[ 7]
-                 + ((int64_t)a[11]) * b[ 6]
-                 + ((int64_t)a[12]) * b[ 5]
-                 + ((int64_t)a[13]) * b[ 4]
-                 + ((int64_t)a[14]) * b[ 3];
-    int64_t t18  = ((int64_t)a[ 4]) * b[14]
-                 + ((int64_t)a[ 5]) * b[13]
-                 + ((int64_t)a[ 6]) * b[12]
-                 + ((int64_t)a[ 7]) * b[11]
-                 + ((int64_t)a[ 8]) * b[10]
-                 + ((int64_t)a[ 9]) * b[ 9]
-                 + ((int64_t)a[10]) * b[ 8]
-                 + ((int64_t)a[11]) * b[ 7]
-                 + ((int64_t)a[12]) * b[ 6]
-                 + ((int64_t)a[13]) * b[ 5]
-                 + ((int64_t)a[14]) * b[ 4];
-    int64_t t19  = ((int64_t)a[ 5]) * b[14]
-                 + ((int64_t)a[ 6]) * b[13]
-                 + ((int64_t)a[ 7]) * b[12]
-                 + ((int64_t)a[ 8]) * b[11]
-                 + ((int64_t)a[ 9]) * b[10]
-                 + ((int64_t)a[10]) * b[ 9]
-                 + ((int64_t)a[11]) * b[ 8]
-                 + ((int64_t)a[12]) * b[ 7]
-                 + ((int64_t)a[13]) * b[ 6]
-                 + ((int64_t)a[14]) * b[ 5];
-    int64_t t20  = ((int64_t)a[ 6]) * b[14]
-                 + ((int64_t)a[ 7]) * b[13]
-                 + ((int64_t)a[ 8]) * b[12]
-                 + ((int64_t)a[ 9]) * b[11]
-                 + ((int64_t)a[10]) * b[10]
-                 + ((int64_t)a[11]) * b[ 9]
-                 + ((int64_t)a[12]) * b[ 8]
-                 + ((int64_t)a[13]) * b[ 7]
-                 + ((int64_t)a[14]) * b[ 6];
-    int64_t t21  = ((int64_t)a[ 7]) * b[14]
-                 + ((int64_t)a[ 8]) * b[13]
-                 + ((int64_t)a[ 9]) * b[12]
-                 + ((int64_t)a[10]) * b[11]
-                 + ((int64_t)a[11]) * b[10]
-                 + ((int64_t)a[12]) * b[ 9]
-                 + ((int64_t)a[13]) * b[ 8]
-                 + ((int64_t)a[14]) * b[ 7];
-    int64_t t22  = ((int64_t)a[ 8]) * b[14]
-                 + ((int64_t)a[ 9]) * b[13]
-                 + ((int64_t)a[10]) * b[12]
-                 + ((int64_t)a[11]) * b[11]
-                 + ((int64_t)a[12]) * b[10]
-                 + ((int64_t)a[13]) * b[ 9]
-                 + ((int64_t)a[14]) * b[ 8];
-    int64_t t23  = ((int64_t)a[ 9]) * b[14]
-                 + ((int64_t)a[10]) * b[13]
-                 + ((int64_t)a[11]) * b[12]
-                 + ((int64_t)a[12]) * b[11]
-                 + ((int64_t)a[13]) * b[10]
-                 + ((int64_t)a[14]) * b[ 9];
-    int64_t t24  = ((int64_t)a[10]) * b[14]
-                 + ((int64_t)a[11]) * b[13]
-                 + ((int64_t)a[12]) * b[12]
-                 + ((int64_t)a[13]) * b[11]
-                 + ((int64_t)a[14]) * b[10];
-    int64_t t25  = ((int64_t)a[11]) * b[14]
-                 + ((int64_t)a[12]) * b[13]
-                 + ((int64_t)a[13]) * b[12]
-                 + ((int64_t)a[14]) * b[11];
-    int64_t t26  = ((int64_t)a[12]) * b[14]
-                 + ((int64_t)a[13]) * b[13]
-                 + ((int64_t)a[14]) * b[12];
-    int64_t t27  = ((int64_t)a[13]) * b[14]
-                 + ((int64_t)a[14]) * b[13];
-    int64_t t28  = ((int64_t)a[14]) * b[14];
-
-    t1   += t0  >> 23; r[ 0] = t0  & 0x7fffff;
-    t2   += t1  >> 23; r[ 1] = t1  & 0x7fffff;
-    t3   += t2  >> 23; r[ 2] = t2  & 0x7fffff;
-    t4   += t3  >> 23; r[ 3] = t3  & 0x7fffff;
-    t5   += t4  >> 23; r[ 4] = t4  & 0x7fffff;
-    t6   += t5  >> 23; r[ 5] = t5  & 0x7fffff;
-    t7   += t6  >> 23; r[ 6] = t6  & 0x7fffff;
-    t8   += t7  >> 23; r[ 7] = t7  & 0x7fffff;
-    t9   += t8  >> 23; r[ 8] = t8  & 0x7fffff;
-    t10  += t9  >> 23; r[ 9] = t9  & 0x7fffff;
-    t11  += t10 >> 23; r[10] = t10 & 0x7fffff;
-    t12  += t11 >> 23; r[11] = t11 & 0x7fffff;
-    t13  += t12 >> 23; r[12] = t12 & 0x7fffff;
-    t14  += t13 >> 23; r[13] = t13 & 0x7fffff;
-    t15  += t14 >> 23; r[14] = t14 & 0x7fffff;
-    t16  += t15 >> 23; r[15] = t15 & 0x7fffff;
-    t17  += t16 >> 23; r[16] = t16 & 0x7fffff;
-    t18  += t17 >> 23; r[17] = t17 & 0x7fffff;
-    t19  += t18 >> 23; r[18] = t18 & 0x7fffff;
-    t20  += t19 >> 23; r[19] = t19 & 0x7fffff;
-    t21  += t20 >> 23; r[20] = t20 & 0x7fffff;
-    t22  += t21 >> 23; r[21] = t21 & 0x7fffff;
-    t23  += t22 >> 23; r[22] = t22 & 0x7fffff;
-    t24  += t23 >> 23; r[23] = t23 & 0x7fffff;
-    t25  += t24 >> 23; r[24] = t24 & 0x7fffff;
-    t26  += t25 >> 23; r[25] = t25 & 0x7fffff;
-    t27  += t26 >> 23; r[26] = t26 & 0x7fffff;
-    t28  += t27 >> 23; r[27] = t27 & 0x7fffff;
-    r[29] = (sp_digit)(t28 >> 23);
-                       r[28] = t28 & 0x7fffff;
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_15(sp_digit* r, const sp_digit* a)
-{
-    int64_t t0   =  ((int64_t)a[ 0]) * a[ 0];
-    int64_t t1   = (((int64_t)a[ 0]) * a[ 1]) * 2;
-    int64_t t2   = (((int64_t)a[ 0]) * a[ 2]) * 2
-                 +  ((int64_t)a[ 1]) * a[ 1];
-    int64_t t3   = (((int64_t)a[ 0]) * a[ 3]
-                 +  ((int64_t)a[ 1]) * a[ 2]) * 2;
-    int64_t t4   = (((int64_t)a[ 0]) * a[ 4]
-                 +  ((int64_t)a[ 1]) * a[ 3]) * 2
-                 +  ((int64_t)a[ 2]) * a[ 2];
-    int64_t t5   = (((int64_t)a[ 0]) * a[ 5]
-                 +  ((int64_t)a[ 1]) * a[ 4]
-                 +  ((int64_t)a[ 2]) * a[ 3]) * 2;
-    int64_t t6   = (((int64_t)a[ 0]) * a[ 6]
-                 +  ((int64_t)a[ 1]) * a[ 5]
-                 +  ((int64_t)a[ 2]) * a[ 4]) * 2
-                 +  ((int64_t)a[ 3]) * a[ 3];
-    int64_t t7   = (((int64_t)a[ 0]) * a[ 7]
-                 +  ((int64_t)a[ 1]) * a[ 6]
-                 +  ((int64_t)a[ 2]) * a[ 5]
-                 +  ((int64_t)a[ 3]) * a[ 4]) * 2;
-    int64_t t8   = (((int64_t)a[ 0]) * a[ 8]
-                 +  ((int64_t)a[ 1]) * a[ 7]
-                 +  ((int64_t)a[ 2]) * a[ 6]
-                 +  ((int64_t)a[ 3]) * a[ 5]) * 2
-                 +  ((int64_t)a[ 4]) * a[ 4];
-    int64_t t9   = (((int64_t)a[ 0]) * a[ 9]
-                 +  ((int64_t)a[ 1]) * a[ 8]
-                 +  ((int64_t)a[ 2]) * a[ 7]
-                 +  ((int64_t)a[ 3]) * a[ 6]
-                 +  ((int64_t)a[ 4]) * a[ 5]) * 2;
-    int64_t t10  = (((int64_t)a[ 0]) * a[10]
-                 +  ((int64_t)a[ 1]) * a[ 9]
-                 +  ((int64_t)a[ 2]) * a[ 8]
-                 +  ((int64_t)a[ 3]) * a[ 7]
-                 +  ((int64_t)a[ 4]) * a[ 6]) * 2
-                 +  ((int64_t)a[ 5]) * a[ 5];
-    int64_t t11  = (((int64_t)a[ 0]) * a[11]
-                 +  ((int64_t)a[ 1]) * a[10]
-                 +  ((int64_t)a[ 2]) * a[ 9]
-                 +  ((int64_t)a[ 3]) * a[ 8]
-                 +  ((int64_t)a[ 4]) * a[ 7]
-                 +  ((int64_t)a[ 5]) * a[ 6]) * 2;
-    int64_t t12  = (((int64_t)a[ 0]) * a[12]
-                 +  ((int64_t)a[ 1]) * a[11]
-                 +  ((int64_t)a[ 2]) * a[10]
-                 +  ((int64_t)a[ 3]) * a[ 9]
-                 +  ((int64_t)a[ 4]) * a[ 8]
-                 +  ((int64_t)a[ 5]) * a[ 7]) * 2
-                 +  ((int64_t)a[ 6]) * a[ 6];
-    int64_t t13  = (((int64_t)a[ 0]) * a[13]
-                 +  ((int64_t)a[ 1]) * a[12]
-                 +  ((int64_t)a[ 2]) * a[11]
-                 +  ((int64_t)a[ 3]) * a[10]
-                 +  ((int64_t)a[ 4]) * a[ 9]
-                 +  ((int64_t)a[ 5]) * a[ 8]
-                 +  ((int64_t)a[ 6]) * a[ 7]) * 2;
-    int64_t t14  = (((int64_t)a[ 0]) * a[14]
-                 +  ((int64_t)a[ 1]) * a[13]
-                 +  ((int64_t)a[ 2]) * a[12]
-                 +  ((int64_t)a[ 3]) * a[11]
-                 +  ((int64_t)a[ 4]) * a[10]
-                 +  ((int64_t)a[ 5]) * a[ 9]
-                 +  ((int64_t)a[ 6]) * a[ 8]) * 2
-                 +  ((int64_t)a[ 7]) * a[ 7];
-    int64_t t15  = (((int64_t)a[ 1]) * a[14]
-                 +  ((int64_t)a[ 2]) * a[13]
-                 +  ((int64_t)a[ 3]) * a[12]
-                 +  ((int64_t)a[ 4]) * a[11]
-                 +  ((int64_t)a[ 5]) * a[10]
-                 +  ((int64_t)a[ 6]) * a[ 9]
-                 +  ((int64_t)a[ 7]) * a[ 8]) * 2;
-    int64_t t16  = (((int64_t)a[ 2]) * a[14]
-                 +  ((int64_t)a[ 3]) * a[13]
-                 +  ((int64_t)a[ 4]) * a[12]
-                 +  ((int64_t)a[ 5]) * a[11]
-                 +  ((int64_t)a[ 6]) * a[10]
-                 +  ((int64_t)a[ 7]) * a[ 9]) * 2
-                 +  ((int64_t)a[ 8]) * a[ 8];
-    int64_t t17  = (((int64_t)a[ 3]) * a[14]
-                 +  ((int64_t)a[ 4]) * a[13]
-                 +  ((int64_t)a[ 5]) * a[12]
-                 +  ((int64_t)a[ 6]) * a[11]
-                 +  ((int64_t)a[ 7]) * a[10]
-                 +  ((int64_t)a[ 8]) * a[ 9]) * 2;
-    int64_t t18  = (((int64_t)a[ 4]) * a[14]
-                 +  ((int64_t)a[ 5]) * a[13]
-                 +  ((int64_t)a[ 6]) * a[12]
-                 +  ((int64_t)a[ 7]) * a[11]
-                 +  ((int64_t)a[ 8]) * a[10]) * 2
-                 +  ((int64_t)a[ 9]) * a[ 9];
-    int64_t t19  = (((int64_t)a[ 5]) * a[14]
-                 +  ((int64_t)a[ 6]) * a[13]
-                 +  ((int64_t)a[ 7]) * a[12]
-                 +  ((int64_t)a[ 8]) * a[11]
-                 +  ((int64_t)a[ 9]) * a[10]) * 2;
-    int64_t t20  = (((int64_t)a[ 6]) * a[14]
-                 +  ((int64_t)a[ 7]) * a[13]
-                 +  ((int64_t)a[ 8]) * a[12]
-                 +  ((int64_t)a[ 9]) * a[11]) * 2
-                 +  ((int64_t)a[10]) * a[10];
-    int64_t t21  = (((int64_t)a[ 7]) * a[14]
-                 +  ((int64_t)a[ 8]) * a[13]
-                 +  ((int64_t)a[ 9]) * a[12]
-                 +  ((int64_t)a[10]) * a[11]) * 2;
-    int64_t t22  = (((int64_t)a[ 8]) * a[14]
-                 +  ((int64_t)a[ 9]) * a[13]
-                 +  ((int64_t)a[10]) * a[12]) * 2
-                 +  ((int64_t)a[11]) * a[11];
-    int64_t t23  = (((int64_t)a[ 9]) * a[14]
-                 +  ((int64_t)a[10]) * a[13]
-                 +  ((int64_t)a[11]) * a[12]) * 2;
-    int64_t t24  = (((int64_t)a[10]) * a[14]
-                 +  ((int64_t)a[11]) * a[13]) * 2
-                 +  ((int64_t)a[12]) * a[12];
-    int64_t t25  = (((int64_t)a[11]) * a[14]
-                 +  ((int64_t)a[12]) * a[13]) * 2;
-    int64_t t26  = (((int64_t)a[12]) * a[14]) * 2
-                 +  ((int64_t)a[13]) * a[13];
-    int64_t t27  = (((int64_t)a[13]) * a[14]) * 2;
-    int64_t t28  =  ((int64_t)a[14]) * a[14];
-
-    t1   += t0  >> 23; r[ 0] = t0  & 0x7fffff;
-    t2   += t1  >> 23; r[ 1] = t1  & 0x7fffff;
-    t3   += t2  >> 23; r[ 2] = t2  & 0x7fffff;
-    t4   += t3  >> 23; r[ 3] = t3  & 0x7fffff;
-    t5   += t4  >> 23; r[ 4] = t4  & 0x7fffff;
-    t6   += t5  >> 23; r[ 5] = t5  & 0x7fffff;
-    t7   += t6  >> 23; r[ 6] = t6  & 0x7fffff;
-    t8   += t7  >> 23; r[ 7] = t7  & 0x7fffff;
-    t9   += t8  >> 23; r[ 8] = t8  & 0x7fffff;
-    t10  += t9  >> 23; r[ 9] = t9  & 0x7fffff;
-    t11  += t10 >> 23; r[10] = t10 & 0x7fffff;
-    t12  += t11 >> 23; r[11] = t11 & 0x7fffff;
-    t13  += t12 >> 23; r[12] = t12 & 0x7fffff;
-    t14  += t13 >> 23; r[13] = t13 & 0x7fffff;
-    t15  += t14 >> 23; r[14] = t14 & 0x7fffff;
-    t16  += t15 >> 23; r[15] = t15 & 0x7fffff;
-    t17  += t16 >> 23; r[16] = t16 & 0x7fffff;
-    t18  += t17 >> 23; r[17] = t17 & 0x7fffff;
-    t19  += t18 >> 23; r[18] = t18 & 0x7fffff;
-    t20  += t19 >> 23; r[19] = t19 & 0x7fffff;
-    t21  += t20 >> 23; r[20] = t20 & 0x7fffff;
-    t22  += t21 >> 23; r[21] = t21 & 0x7fffff;
-    t23  += t22 >> 23; r[22] = t22 & 0x7fffff;
-    t24  += t23 >> 23; r[23] = t23 & 0x7fffff;
-    t25  += t24 >> 23; r[24] = t24 & 0x7fffff;
-    t26  += t25 >> 23; r[25] = t25 & 0x7fffff;
-    t27  += t26 >> 23; r[26] = t26 & 0x7fffff;
-    t28  += t27 >> 23; r[27] = t27 & 0x7fffff;
-    r[29] = (sp_digit)(t28 >> 23);
-                       r[28] = t28 & 0x7fffff;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_15(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] + b[ 0];
-    r[ 1] = a[ 1] + b[ 1];
-    r[ 2] = a[ 2] + b[ 2];
-    r[ 3] = a[ 3] + b[ 3];
-    r[ 4] = a[ 4] + b[ 4];
-    r[ 5] = a[ 5] + b[ 5];
-    r[ 6] = a[ 6] + b[ 6];
-    r[ 7] = a[ 7] + b[ 7];
-    r[ 8] = a[ 8] + b[ 8];
-    r[ 9] = a[ 9] + b[ 9];
-    r[10] = a[10] + b[10];
-    r[11] = a[11] + b[11];
-    r[12] = a[12] + b[12];
-    r[13] = a[13] + b[13];
-    r[14] = a[14] + b[14];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_30(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[24] = a[24] - b[24];
-    r[25] = a[25] - b[25];
-    r[26] = a[26] - b[26];
-    r[27] = a[27] - b[27];
-    r[28] = a[28] - b[28];
-    r[29] = a[29] - b[29];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_30(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[24] = a[24] + b[24];
-    r[25] = a[25] + b[25];
-    r[26] = a[26] + b[26];
-    r[27] = a[27] + b[27];
-    r[28] = a[28] + b[28];
-    r[29] = a[29] + b[29];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit p0[30];
-    sp_digit p1[30];
-    sp_digit p2[30];
-    sp_digit p3[30];
-    sp_digit p4[30];
-    sp_digit p5[30];
-    sp_digit t0[30];
-    sp_digit t1[30];
-    sp_digit t2[30];
-    sp_digit a0[15];
-    sp_digit a1[15];
-    sp_digit a2[15];
-    sp_digit b0[15];
-    sp_digit b1[15];
-    sp_digit b2[15];
-    sp_2048_add_15(a0, a, &a[15]);
-    sp_2048_add_15(b0, b, &b[15]);
-    sp_2048_add_15(a1, &a[15], &a[30]);
-    sp_2048_add_15(b1, &b[15], &b[30]);
-    sp_2048_add_15(a2, a0, &a[30]);
-    sp_2048_add_15(b2, b0, &b[30]);
-    sp_2048_mul_15(p0, a, b);
-    sp_2048_mul_15(p2, &a[15], &b[15]);
-    sp_2048_mul_15(p4, &a[30], &b[30]);
-    sp_2048_mul_15(p1, a0, b0);
-    sp_2048_mul_15(p3, a1, b1);
-    sp_2048_mul_15(p5, a2, b2);
-    XMEMSET(r, 0, sizeof(*r)*2*45);
-    sp_2048_sub_30(t0, p3, p2);
-    sp_2048_sub_30(t1, p1, p2);
-    sp_2048_sub_30(t2, p5, t0);
-    sp_2048_sub_30(t2, t2, t1);
-    sp_2048_sub_30(t0, t0, p4);
-    sp_2048_sub_30(t1, t1, p0);
-    sp_2048_add_30(r, r, p0);
-    sp_2048_add_30(&r[15], &r[15], t1);
-    sp_2048_add_30(&r[30], &r[30], t2);
-    sp_2048_add_30(&r[45], &r[45], t0);
-    sp_2048_add_30(&r[60], &r[60], p4);
-}
-
-/* Square a into r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a)
-{
-    sp_digit p0[30];
-    sp_digit p1[30];
-    sp_digit p2[30];
-    sp_digit p3[30];
-    sp_digit p4[30];
-    sp_digit p5[30];
-    sp_digit t0[30];
-    sp_digit t1[30];
-    sp_digit t2[30];
-    sp_digit a0[15];
-    sp_digit a1[15];
-    sp_digit a2[15];
-    sp_2048_add_15(a0, a, &a[15]);
-    sp_2048_add_15(a1, &a[15], &a[30]);
-    sp_2048_add_15(a2, a0, &a[30]);
-    sp_2048_sqr_15(p0, a);
-    sp_2048_sqr_15(p2, &a[15]);
-    sp_2048_sqr_15(p4, &a[30]);
-    sp_2048_sqr_15(p1, a0);
-    sp_2048_sqr_15(p3, a1);
-    sp_2048_sqr_15(p5, a2);
-    XMEMSET(r, 0, sizeof(*r)*2*45);
-    sp_2048_sub_30(t0, p3, p2);
-    sp_2048_sub_30(t1, p1, p2);
-    sp_2048_sub_30(t2, p5, t0);
-    sp_2048_sub_30(t2, t2, t1);
-    sp_2048_sub_30(t0, t0, p4);
-    sp_2048_sub_30(t1, t1, p0);
-    sp_2048_add_30(r, r, p0);
-    sp_2048_add_30(&r[15], &r[15], t1);
-    sp_2048_add_30(&r[30], &r[30], t2);
-    sp_2048_add_30(&r[45], &r[45], t0);
-    sp_2048_add_30(&r[60], &r[60], p4);
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[40] = a[40] + b[40];
-    r[41] = a[41] + b[41];
-    r[42] = a[42] + b[42];
-    r[43] = a[43] + b[43];
-    r[44] = a[44] + b[44];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[88] = a[88] + b[88];
-    r[89] = a[89] + b[89];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[88] = a[88] - b[88];
-    r[89] = a[89] - b[89];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[90];
-    sp_digit* a1 = z1;
-    sp_digit b1[45];
-    sp_digit* z2 = r + 90;
-    sp_2048_add_45(a1, a, &a[45]);
-    sp_2048_add_45(b1, b, &b[45]);
-    sp_2048_mul_45(z2, &a[45], &b[45]);
-    sp_2048_mul_45(z0, a, b);
-    sp_2048_mul_45(z1, a1, b1);
-    sp_2048_sub_90(z1, z1, z2);
-    sp_2048_sub_90(z1, z1, z0);
-    sp_2048_add_90(r + 45, r + 45, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[90];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 90;
-    sp_2048_add_45(a1, a, &a[45]);
-    sp_2048_sqr_45(z2, &a[45]);
-    sp_2048_sqr_45(z0, a);
-    sp_2048_sqr_45(z1, a1);
-    sp_2048_sub_90(z1, z1, z2);
-    sp_2048_sub_90(z1, z1, z0);
-    sp_2048_add_90(r + 45, r + 45, z1);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[89]) * b[89];
-    r[179] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 177; k >= 0; k--) {
-        for (i = 89; i >= 0; i--) {
-            j = k - i;
-            if (j >= 90)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[89]) * a[89];
-    r[179] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 177; k >= 0; k--) {
-        for (i = 89; i >= 0; i--) {
-            j = k - i;
-            if (j >= 90 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int64_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 45; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 45; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[40] = a[40] - b[40];
-    r[41] = a[41] - b[41];
-    r[42] = a[42] - b[42];
-    r[43] = a[43] - b[43];
-    r[44] = a[44] - b[44];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[44]) * b[44];
-    r[89] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 87; k >= 0; k--) {
-        for (i = 44; i >= 0; i--) {
-            j = k - i;
-            if (j >= 45)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[44]) * a[44];
-    r[89] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 87; k >= 0; k--) {
-        for (i = 44; i >= 0; i--) {
-            j = k - i;
-            if (j >= 45 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int64_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x &= 0x7fffff;
-
-    /* rho = -1/m mod b */
-    *rho = (1L << 23) - x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_45(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<44; i++)
-        r[i] = 0x7fffff;
-#else
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = 0x7fffff;
-        r[i + 1] = 0x7fffff;
-        r[i + 2] = 0x7fffff;
-        r[i + 3] = 0x7fffff;
-        r[i + 4] = 0x7fffff;
-        r[i + 5] = 0x7fffff;
-        r[i + 6] = 0x7fffff;
-        r[i + 7] = 0x7fffff;
-    }
-    r[40] = 0x7fffff;
-    r[41] = 0x7fffff;
-    r[42] = 0x7fffff;
-    r[43] = 0x7fffff;
-#endif
-    r[44] = 0xfffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_2048_sub_45(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_2048_cmp_45(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=44; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[44] - b[44]) & (0 - !r);
-    r |= (a[43] - b[43]) & (0 - !r);
-    r |= (a[42] - b[42]) & (0 - !r);
-    r |= (a[41] - b[41]) & (0 - !r);
-    r |= (a[40] - b[40]) & (0 - !r);
-    for (i = 32; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_sub_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 45; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[40] = a[40] - (b[40] & m);
-    r[41] = a[41] - (b[41] & m);
-    r[42] = a[42] - (b[42] & m);
-    r[43] = a[43] - (b[43] & m);
-    r[44] = a[44] - (b[44] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_add_45(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 45; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[45] += t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff;
-    for (i = 0; i < 40; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[41]; r[41] += (t[0] >> 23) + (t[1] & 0x7fffff);
-    t[2] = tb * a[42]; r[42] += (t[1] >> 23) + (t[2] & 0x7fffff);
-    t[3] = tb * a[43]; r[43] += (t[2] >> 23) + (t[3] & 0x7fffff);
-    t[4] = tb * a[44]; r[44] += (t[3] >> 23) + (t[4] & 0x7fffff);
-    r[45] +=  t[4] >> 23;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 23.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_2048_norm_45(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 44; i++) {
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-#else
-    int i;
-    for (i = 0; i < 40; i += 8) {
-        a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff;
-        a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff;
-        a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff;
-        a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff;
-        a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff;
-        a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff;
-        a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff;
-        a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff;
-        a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff;
-    }
-    a[40+1] += a[40] >> 23;
-    a[40] &= 0x7fffff;
-    a[41+1] += a[41] >> 23;
-    a[41] &= 0x7fffff;
-    a[42+1] += a[42] >> 23;
-    a[42] &= 0x7fffff;
-    a[43+1] += a[43] >> 23;
-    a[43] &= 0x7fffff;
-#endif
-}
-
-/* Shift the result in the high 1024 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_2048_mont_shift_45(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    int64_t n = a[44] >> 12;
-    n += ((int64_t)a[45]) << 11;
-
-    for (i = 0; i < 44; i++) {
-        r[i] = n & 0x7fffff;
-        n >>= 23;
-        n += ((int64_t)a[46 + i]) << 11;
-    }
-    r[44] = (sp_digit)n;
-#else
-    int i;
-    int64_t n = a[44] >> 12;
-    n += ((int64_t)a[45]) << 11;
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 46]) << 11;
-        r[i + 1] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 47]) << 11;
-        r[i + 2] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 48]) << 11;
-        r[i + 3] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 49]) << 11;
-        r[i + 4] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 50]) << 11;
-        r[i + 5] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 51]) << 11;
-        r[i + 6] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 52]) << 11;
-        r[i + 7] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 53]) << 11;
-    }
-    r[40] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[86]) << 11;
-    r[41] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[87]) << 11;
-    r[42] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[88]) << 11;
-    r[43] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[89]) << 11;
-    r[44] = (sp_digit)n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[45], 0, sizeof(*r) * 45);
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_2048_mont_reduce_45(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    for (i=0; i<44; i++) {
-        mu = (a[i] * mp) & 0x7fffff;
-        sp_2048_mul_add_45(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-    }
-    mu = (a[i] * mp) & 0xfffl;
-    sp_2048_mul_add_45(a+i, m, mu);
-    a[i+1] += a[i] >> 23;
-    a[i] &= 0x7fffff;
-
-    sp_2048_mont_shift_45(a, a);
-    sp_2048_cond_sub_45(a, a, m, 0 - ((a[44] >> 12) > 0));
-    sp_2048_norm_45(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_45(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_45(r, a, b);
-    sp_2048_mont_reduce_45(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_45(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_45(r, a);
-    sp_2048_mont_reduce_45(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_d_45(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 45; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[45] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 40; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[41];
-    r[41] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-    t[2] = tb * a[42];
-    r[42] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-    t[3] = tb * a[43];
-    r[43] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-    t[4] = tb * a[44];
-    r[44] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-    r[45] =  (sp_digit)(t[4] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_d_90(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 90; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[90] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 88; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[89];
-    r[89] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-    r[90] =  (sp_digit)(t[1] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_add_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 45; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[40] = a[40] + (b[40] & m);
-    r[41] = a[41] + (b[41] & m);
-    r[42] = a[42] + (b[42] & m);
-    r[43] = a[43] + (b[43] & m);
-    r[44] = a[44] + (b[44] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 45; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<44; i++)
-        r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff;
-#else
-    r[0] = ((a[0] >> n) | (a[1] << (23 - n))) & 0x7fffff;
-    r[1] = ((a[1] >> n) | (a[2] << (23 - n))) & 0x7fffff;
-    r[2] = ((a[2] >> n) | (a[3] << (23 - n))) & 0x7fffff;
-    r[3] = ((a[3] >> n) | (a[4] << (23 - n))) & 0x7fffff;
-    r[4] = ((a[4] >> n) | (a[5] << (23 - n))) & 0x7fffff;
-    r[5] = ((a[5] >> n) | (a[6] << (23 - n))) & 0x7fffff;
-    r[6] = ((a[6] >> n) | (a[7] << (23 - n))) & 0x7fffff;
-    r[7] = ((a[7] >> n) | (a[8] << (23 - n))) & 0x7fffff;
-    r[8] = ((a[8] >> n) | (a[9] << (23 - n))) & 0x7fffff;
-    r[9] = ((a[9] >> n) | (a[10] << (23 - n))) & 0x7fffff;
-    r[10] = ((a[10] >> n) | (a[11] << (23 - n))) & 0x7fffff;
-    r[11] = ((a[11] >> n) | (a[12] << (23 - n))) & 0x7fffff;
-    r[12] = ((a[12] >> n) | (a[13] << (23 - n))) & 0x7fffff;
-    r[13] = ((a[13] >> n) | (a[14] << (23 - n))) & 0x7fffff;
-    r[14] = ((a[14] >> n) | (a[15] << (23 - n))) & 0x7fffff;
-    r[15] = ((a[15] >> n) | (a[16] << (23 - n))) & 0x7fffff;
-    r[16] = ((a[16] >> n) | (a[17] << (23 - n))) & 0x7fffff;
-    r[17] = ((a[17] >> n) | (a[18] << (23 - n))) & 0x7fffff;
-    r[18] = ((a[18] >> n) | (a[19] << (23 - n))) & 0x7fffff;
-    r[19] = ((a[19] >> n) | (a[20] << (23 - n))) & 0x7fffff;
-    r[20] = ((a[20] >> n) | (a[21] << (23 - n))) & 0x7fffff;
-    r[21] = ((a[21] >> n) | (a[22] << (23 - n))) & 0x7fffff;
-    r[22] = ((a[22] >> n) | (a[23] << (23 - n))) & 0x7fffff;
-    r[23] = ((a[23] >> n) | (a[24] << (23 - n))) & 0x7fffff;
-    r[24] = ((a[24] >> n) | (a[25] << (23 - n))) & 0x7fffff;
-    r[25] = ((a[25] >> n) | (a[26] << (23 - n))) & 0x7fffff;
-    r[26] = ((a[26] >> n) | (a[27] << (23 - n))) & 0x7fffff;
-    r[27] = ((a[27] >> n) | (a[28] << (23 - n))) & 0x7fffff;
-    r[28] = ((a[28] >> n) | (a[29] << (23 - n))) & 0x7fffff;
-    r[29] = ((a[29] >> n) | (a[30] << (23 - n))) & 0x7fffff;
-    r[30] = ((a[30] >> n) | (a[31] << (23 - n))) & 0x7fffff;
-    r[31] = ((a[31] >> n) | (a[32] << (23 - n))) & 0x7fffff;
-    r[32] = ((a[32] >> n) | (a[33] << (23 - n))) & 0x7fffff;
-    r[33] = ((a[33] >> n) | (a[34] << (23 - n))) & 0x7fffff;
-    r[34] = ((a[34] >> n) | (a[35] << (23 - n))) & 0x7fffff;
-    r[35] = ((a[35] >> n) | (a[36] << (23 - n))) & 0x7fffff;
-    r[36] = ((a[36] >> n) | (a[37] << (23 - n))) & 0x7fffff;
-    r[37] = ((a[37] >> n) | (a[38] << (23 - n))) & 0x7fffff;
-    r[38] = ((a[38] >> n) | (a[39] << (23 - n))) & 0x7fffff;
-    r[39] = ((a[39] >> n) | (a[40] << (23 - n))) & 0x7fffff;
-    r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff;
-    r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff;
-    r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff;
-    r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff;
-#endif
-    r[44] = a[44] >> n;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_div_45(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int64_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[90 + 1], t2d[45 + 1], sdd[45 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    sp_digit* sd;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (4 * 45 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 90 + 1;
-        sd = t2 + 45 + 1;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-    sd = sdd;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_d_45(sd, d, 1 << 11);
-        sp_2048_mul_d_90(t1, a, 1 << 11);
-        div = sd[44];
-        for (i=45; i>=0; i--) {
-            t1[45 + i] += t1[45 + i - 1] >> 23;
-            t1[45 + i - 1] &= 0x7fffff;
-            d1 = t1[45 + i];
-            d1 <<= 23;
-            d1 += t1[45 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_2048_mul_d_45(t2, sd, r1);
-            sp_2048_sub_45(&t1[i], &t1[i], t2);
-            t1[45 + i] -= t2[45];
-            t1[45 + i] += t1[45 + i - 1] >> 23;
-            t1[45 + i - 1] &= 0x7fffff;
-            r1 = (((-t1[45 + i]) << 23) - t1[45 + i - 1]) / div;
-            r1 -= t1[45 + i];
-            sp_2048_mul_d_45(t2, sd, r1);
-            sp_2048_add_45(&t1[i], &t1[i], t2);
-            t1[45 + i] += t1[45 + i - 1] >> 23;
-            t1[45 + i - 1] &= 0x7fffff;
-        }
-        t1[45 - 1] += t1[45 - 2] >> 23;
-        t1[45 - 2] &= 0x7fffff;
-        d1 = t1[45 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_2048_mul_d_45(t2, sd, r1);
-        sp_2048_sub_45(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 45);
-        for (i=0; i<43; i++) {
-            r[i+1] += r[i] >> 23;
-            r[i] &= 0x7fffff;
-        }
-        sp_2048_cond_add_45(r, r, sd, 0 - (r[44] < 0));
-    }
-
-    sp_2048_rshift_45(r, r, 11);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_mod_45(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_45(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_45(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 45 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 45 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[45 * 2];
-        t[2] = &td[2 * 45 * 2];
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_45(norm, m);
-
-        if (reduceA)
-            err = sp_2048_mod_45(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 45);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_45(t[1], t[1], norm);
-        err = sp_2048_mod_45(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_45(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 45 * 2);
-            sp_2048_mont_sqr_45(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 45 * 2);
-        }
-
-        sp_2048_mont_reduce_45(t[0], m, mp);
-        n = sp_2048_cmp_45(t[0], m);
-        sp_2048_cond_sub_45(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 45 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][90];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 45 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[45 * 2];
-        t[2] = &td[2 * 45 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_45(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_45(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_45(t[1], t[1], norm);
-                err = sp_2048_mod_45(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_45(t[1], a, norm);
-            err = sp_2048_mod_45(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_45(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_2048_mont_sqr_45(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_2048_mont_reduce_45(t[0], m, mp);
-        n = sp_2048_cmp_45(t[0], m);
-        sp_2048_cond_sub_45(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][90];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[90];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 90, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 90;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_45(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_45(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_45(t[1], t[1], norm);
-                err = sp_2048_mod_45(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_45(t[1], a, norm);
-            err = sp_2048_mod_45(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_45(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_45(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_45(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_45(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_45(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_45(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_45(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_45(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_45(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_45(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_45(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_45(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_45(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_45(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_45(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_45(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_45(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_45(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_45(t[20], t[10], m, mp);
-        sp_2048_mont_mul_45(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_45(t[22], t[11], m, mp);
-        sp_2048_mont_mul_45(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_45(t[24], t[12], m, mp);
-        sp_2048_mont_mul_45(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_45(t[26], t[13], m, mp);
-        sp_2048_mont_mul_45(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_45(t[28], t[14], m, mp);
-        sp_2048_mont_mul_45(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_45(t[30], t[15], m, mp);
-        sp_2048_mont_mul_45(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 22) / 23) - 1;
-        c = bits % 23;
-        if (c == 0)
-            c = 23;
-        if (i < 45)
-            n = e[i--] << (32 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (9 - c);
-            c += 23;
-        }
-        y = n >> 27;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (9 - c);
-                c += 23;
-            }
-            y = (n >> 27) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_2048_mont_sqr_45(rt, rt, m, mp);
-            sp_2048_mont_sqr_45(rt, rt, m, mp);
-            sp_2048_mont_sqr_45(rt, rt, m, mp);
-            sp_2048_mont_sqr_45(rt, rt, m, mp);
-            sp_2048_mont_sqr_45(rt, rt, m, mp);
-
-            sp_2048_mont_mul_45(rt, rt, t[y], m, mp);
-        }
-
-        sp_2048_mont_reduce_45(rt, m, mp);
-        n = sp_2048_cmp_45(rt, m);
-        sp_2048_cond_sub_45(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_90(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<89; i++)
-        r[i] = 0x7fffff;
-#else
-    int i;
-
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = 0x7fffff;
-        r[i + 1] = 0x7fffff;
-        r[i + 2] = 0x7fffff;
-        r[i + 3] = 0x7fffff;
-        r[i + 4] = 0x7fffff;
-        r[i + 5] = 0x7fffff;
-        r[i + 6] = 0x7fffff;
-        r[i + 7] = 0x7fffff;
-    }
-    r[88] = 0x7fffff;
-#endif
-    r[89] = 0x1l;
-
-    /* r = (2^n - 1) mod n */
-    sp_2048_sub_90(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_2048_cmp_90(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=89; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[89] - b[89]) & (0 - !r);
-    r |= (a[88] - b[88]) & (0 - !r);
-    for (i = 80; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_sub_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[88] = a[88] - (b[88] & m);
-    r[89] = a[89] - (b[89] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_add_90(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 90; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[90] += t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff;
-    for (i = 0; i < 88; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[89]; r[89] += (t[0] >> 23) + (t[1] & 0x7fffff);
-    r[90] +=  t[1] >> 23;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 23.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_2048_norm_90(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 89; i++) {
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-#else
-    int i;
-    for (i = 0; i < 88; i += 8) {
-        a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff;
-        a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff;
-        a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff;
-        a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff;
-        a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff;
-        a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff;
-        a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff;
-        a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff;
-        a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff;
-    }
-    a[88+1] += a[88] >> 23;
-    a[88] &= 0x7fffff;
-#endif
-}
-
-/* Shift the result in the high 2048 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_2048_mont_shift_90(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    int64_t n = a[89] >> 1;
-    n += ((int64_t)a[90]) << 22;
-
-    for (i = 0; i < 89; i++) {
-        r[i] = n & 0x7fffff;
-        n >>= 23;
-        n += ((int64_t)a[91 + i]) << 22;
-    }
-    r[89] = (sp_digit)n;
-#else
-    int i;
-    int64_t n = a[89] >> 1;
-    n += ((int64_t)a[90]) << 22;
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 91]) << 22;
-        r[i + 1] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 92]) << 22;
-        r[i + 2] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 93]) << 22;
-        r[i + 3] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 94]) << 22;
-        r[i + 4] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 95]) << 22;
-        r[i + 5] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 96]) << 22;
-        r[i + 6] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 97]) << 22;
-        r[i + 7] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 98]) << 22;
-    }
-    r[88] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[179]) << 22;
-    r[89] = (sp_digit)n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[90], 0, sizeof(*r) * 90);
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_2048_mont_reduce_90(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<89; i++) {
-            mu = (a[i] * mp) & 0x7fffff;
-            sp_2048_mul_add_90(a+i, m, mu);
-            a[i+1] += a[i] >> 23;
-        }
-        mu = (a[i] * mp) & 0x1l;
-        sp_2048_mul_add_90(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-    else {
-        for (i=0; i<89; i++) {
-            mu = a[i] & 0x7fffff;
-            sp_2048_mul_add_90(a+i, m, mu);
-            a[i+1] += a[i] >> 23;
-        }
-        mu = a[i] & 0x1l;
-        sp_2048_mul_add_90(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-
-    sp_2048_mont_shift_90(a, a);
-    sp_2048_cond_sub_90(a, a, m, 0 - ((a[89] >> 1) > 0));
-    sp_2048_norm_90(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_90(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_90(r, a, b);
-    sp_2048_mont_reduce_90(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_90(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_90(r, a);
-    sp_2048_mont_reduce_90(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_d_180(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 180; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[180] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 176; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[177];
-    r[177] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-    t[2] = tb * a[178];
-    r[178] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-    t[3] = tb * a[179];
-    r[179] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-    r[180] =  (sp_digit)(t[3] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_add_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 88; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[88] = a[88] + (b[88] & m);
-    r[89] = a[89] + (b[89] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 90; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<89; i++)
-        r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff;
-#else
-    r[0] = ((a[0] >> n) | (a[1] << (23 - n))) & 0x7fffff;
-    r[1] = ((a[1] >> n) | (a[2] << (23 - n))) & 0x7fffff;
-    r[2] = ((a[2] >> n) | (a[3] << (23 - n))) & 0x7fffff;
-    r[3] = ((a[3] >> n) | (a[4] << (23 - n))) & 0x7fffff;
-    r[4] = ((a[4] >> n) | (a[5] << (23 - n))) & 0x7fffff;
-    r[5] = ((a[5] >> n) | (a[6] << (23 - n))) & 0x7fffff;
-    r[6] = ((a[6] >> n) | (a[7] << (23 - n))) & 0x7fffff;
-    r[7] = ((a[7] >> n) | (a[8] << (23 - n))) & 0x7fffff;
-    r[8] = ((a[8] >> n) | (a[9] << (23 - n))) & 0x7fffff;
-    r[9] = ((a[9] >> n) | (a[10] << (23 - n))) & 0x7fffff;
-    r[10] = ((a[10] >> n) | (a[11] << (23 - n))) & 0x7fffff;
-    r[11] = ((a[11] >> n) | (a[12] << (23 - n))) & 0x7fffff;
-    r[12] = ((a[12] >> n) | (a[13] << (23 - n))) & 0x7fffff;
-    r[13] = ((a[13] >> n) | (a[14] << (23 - n))) & 0x7fffff;
-    r[14] = ((a[14] >> n) | (a[15] << (23 - n))) & 0x7fffff;
-    r[15] = ((a[15] >> n) | (a[16] << (23 - n))) & 0x7fffff;
-    r[16] = ((a[16] >> n) | (a[17] << (23 - n))) & 0x7fffff;
-    r[17] = ((a[17] >> n) | (a[18] << (23 - n))) & 0x7fffff;
-    r[18] = ((a[18] >> n) | (a[19] << (23 - n))) & 0x7fffff;
-    r[19] = ((a[19] >> n) | (a[20] << (23 - n))) & 0x7fffff;
-    r[20] = ((a[20] >> n) | (a[21] << (23 - n))) & 0x7fffff;
-    r[21] = ((a[21] >> n) | (a[22] << (23 - n))) & 0x7fffff;
-    r[22] = ((a[22] >> n) | (a[23] << (23 - n))) & 0x7fffff;
-    r[23] = ((a[23] >> n) | (a[24] << (23 - n))) & 0x7fffff;
-    r[24] = ((a[24] >> n) | (a[25] << (23 - n))) & 0x7fffff;
-    r[25] = ((a[25] >> n) | (a[26] << (23 - n))) & 0x7fffff;
-    r[26] = ((a[26] >> n) | (a[27] << (23 - n))) & 0x7fffff;
-    r[27] = ((a[27] >> n) | (a[28] << (23 - n))) & 0x7fffff;
-    r[28] = ((a[28] >> n) | (a[29] << (23 - n))) & 0x7fffff;
-    r[29] = ((a[29] >> n) | (a[30] << (23 - n))) & 0x7fffff;
-    r[30] = ((a[30] >> n) | (a[31] << (23 - n))) & 0x7fffff;
-    r[31] = ((a[31] >> n) | (a[32] << (23 - n))) & 0x7fffff;
-    r[32] = ((a[32] >> n) | (a[33] << (23 - n))) & 0x7fffff;
-    r[33] = ((a[33] >> n) | (a[34] << (23 - n))) & 0x7fffff;
-    r[34] = ((a[34] >> n) | (a[35] << (23 - n))) & 0x7fffff;
-    r[35] = ((a[35] >> n) | (a[36] << (23 - n))) & 0x7fffff;
-    r[36] = ((a[36] >> n) | (a[37] << (23 - n))) & 0x7fffff;
-    r[37] = ((a[37] >> n) | (a[38] << (23 - n))) & 0x7fffff;
-    r[38] = ((a[38] >> n) | (a[39] << (23 - n))) & 0x7fffff;
-    r[39] = ((a[39] >> n) | (a[40] << (23 - n))) & 0x7fffff;
-    r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff;
-    r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff;
-    r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff;
-    r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff;
-    r[44] = ((a[44] >> n) | (a[45] << (23 - n))) & 0x7fffff;
-    r[45] = ((a[45] >> n) | (a[46] << (23 - n))) & 0x7fffff;
-    r[46] = ((a[46] >> n) | (a[47] << (23 - n))) & 0x7fffff;
-    r[47] = ((a[47] >> n) | (a[48] << (23 - n))) & 0x7fffff;
-    r[48] = ((a[48] >> n) | (a[49] << (23 - n))) & 0x7fffff;
-    r[49] = ((a[49] >> n) | (a[50] << (23 - n))) & 0x7fffff;
-    r[50] = ((a[50] >> n) | (a[51] << (23 - n))) & 0x7fffff;
-    r[51] = ((a[51] >> n) | (a[52] << (23 - n))) & 0x7fffff;
-    r[52] = ((a[52] >> n) | (a[53] << (23 - n))) & 0x7fffff;
-    r[53] = ((a[53] >> n) | (a[54] << (23 - n))) & 0x7fffff;
-    r[54] = ((a[54] >> n) | (a[55] << (23 - n))) & 0x7fffff;
-    r[55] = ((a[55] >> n) | (a[56] << (23 - n))) & 0x7fffff;
-    r[56] = ((a[56] >> n) | (a[57] << (23 - n))) & 0x7fffff;
-    r[57] = ((a[57] >> n) | (a[58] << (23 - n))) & 0x7fffff;
-    r[58] = ((a[58] >> n) | (a[59] << (23 - n))) & 0x7fffff;
-    r[59] = ((a[59] >> n) | (a[60] << (23 - n))) & 0x7fffff;
-    r[60] = ((a[60] >> n) | (a[61] << (23 - n))) & 0x7fffff;
-    r[61] = ((a[61] >> n) | (a[62] << (23 - n))) & 0x7fffff;
-    r[62] = ((a[62] >> n) | (a[63] << (23 - n))) & 0x7fffff;
-    r[63] = ((a[63] >> n) | (a[64] << (23 - n))) & 0x7fffff;
-    r[64] = ((a[64] >> n) | (a[65] << (23 - n))) & 0x7fffff;
-    r[65] = ((a[65] >> n) | (a[66] << (23 - n))) & 0x7fffff;
-    r[66] = ((a[66] >> n) | (a[67] << (23 - n))) & 0x7fffff;
-    r[67] = ((a[67] >> n) | (a[68] << (23 - n))) & 0x7fffff;
-    r[68] = ((a[68] >> n) | (a[69] << (23 - n))) & 0x7fffff;
-    r[69] = ((a[69] >> n) | (a[70] << (23 - n))) & 0x7fffff;
-    r[70] = ((a[70] >> n) | (a[71] << (23 - n))) & 0x7fffff;
-    r[71] = ((a[71] >> n) | (a[72] << (23 - n))) & 0x7fffff;
-    r[72] = ((a[72] >> n) | (a[73] << (23 - n))) & 0x7fffff;
-    r[73] = ((a[73] >> n) | (a[74] << (23 - n))) & 0x7fffff;
-    r[74] = ((a[74] >> n) | (a[75] << (23 - n))) & 0x7fffff;
-    r[75] = ((a[75] >> n) | (a[76] << (23 - n))) & 0x7fffff;
-    r[76] = ((a[76] >> n) | (a[77] << (23 - n))) & 0x7fffff;
-    r[77] = ((a[77] >> n) | (a[78] << (23 - n))) & 0x7fffff;
-    r[78] = ((a[78] >> n) | (a[79] << (23 - n))) & 0x7fffff;
-    r[79] = ((a[79] >> n) | (a[80] << (23 - n))) & 0x7fffff;
-    r[80] = ((a[80] >> n) | (a[81] << (23 - n))) & 0x7fffff;
-    r[81] = ((a[81] >> n) | (a[82] << (23 - n))) & 0x7fffff;
-    r[82] = ((a[82] >> n) | (a[83] << (23 - n))) & 0x7fffff;
-    r[83] = ((a[83] >> n) | (a[84] << (23 - n))) & 0x7fffff;
-    r[84] = ((a[84] >> n) | (a[85] << (23 - n))) & 0x7fffff;
-    r[85] = ((a[85] >> n) | (a[86] << (23 - n))) & 0x7fffff;
-    r[86] = ((a[86] >> n) | (a[87] << (23 - n))) & 0x7fffff;
-    r[87] = ((a[87] >> n) | (a[88] << (23 - n))) & 0x7fffff;
-    r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff;
-#endif
-    r[89] = a[89] >> n;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_div_90(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int64_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[180 + 1], t2d[90 + 1], sdd[90 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    sp_digit* sd;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (4 * 90 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 180 + 1;
-        sd = t2 + 90 + 1;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-    sd = sdd;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_d_90(sd, d, 1 << 22);
-        sp_2048_mul_d_180(t1, a, 1 << 22);
-        div = sd[89];
-        for (i=90; i>=0; i--) {
-            t1[90 + i] += t1[90 + i - 1] >> 23;
-            t1[90 + i - 1] &= 0x7fffff;
-            d1 = t1[90 + i];
-            d1 <<= 23;
-            d1 += t1[90 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_2048_mul_d_90(t2, sd, r1);
-            sp_2048_sub_90(&t1[i], &t1[i], t2);
-            t1[90 + i] -= t2[90];
-            t1[90 + i] += t1[90 + i - 1] >> 23;
-            t1[90 + i - 1] &= 0x7fffff;
-            r1 = (((-t1[90 + i]) << 23) - t1[90 + i - 1]) / div;
-            r1 -= t1[90 + i];
-            sp_2048_mul_d_90(t2, sd, r1);
-            sp_2048_add_90(&t1[i], &t1[i], t2);
-            t1[90 + i] += t1[90 + i - 1] >> 23;
-            t1[90 + i - 1] &= 0x7fffff;
-        }
-        t1[90 - 1] += t1[90 - 2] >> 23;
-        t1[90 - 2] &= 0x7fffff;
-        d1 = t1[90 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_2048_mul_d_90(t2, sd, r1);
-        sp_2048_sub_90(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 90);
-        for (i=0; i<88; i++) {
-            r[i+1] += r[i] >> 23;
-            r[i] &= 0x7fffff;
-        }
-        sp_2048_cond_add_90(r, r, sd, 0 - (r[89] < 0));
-    }
-
-    sp_2048_rshift_90(r, r, 22);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_mod_90(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_90(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_90(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 90 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 90 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[90 * 2];
-        t[2] = &td[2 * 90 * 2];
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_90(norm, m);
-
-        if (reduceA)
-            err = sp_2048_mod_90(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 90);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_90(t[1], t[1], norm);
-        err = sp_2048_mod_90(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_90(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 90 * 2);
-            sp_2048_mont_sqr_90(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 90 * 2);
-        }
-
-        sp_2048_mont_reduce_90(t[0], m, mp);
-        n = sp_2048_cmp_90(t[0], m);
-        sp_2048_cond_sub_90(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 90 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][180];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 90 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[90 * 2];
-        t[2] = &td[2 * 90 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_90(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_90(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_90(t[1], t[1], norm);
-                err = sp_2048_mod_90(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_90(t[1], a, norm);
-            err = sp_2048_mod_90(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_90(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_2048_mont_sqr_90(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_2048_mont_reduce_90(t[0], m, mp);
-        n = sp_2048_cmp_90(t[0], m);
-        sp_2048_cond_sub_90(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][180];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[180];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 180, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 180;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_90(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_90(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_90(t[1], t[1], norm);
-                err = sp_2048_mod_90(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_90(t[1], a, norm);
-            err = sp_2048_mod_90(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_90(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_90(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_90(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_90(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_90(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_90(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_90(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_90(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_90(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_90(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_90(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_90(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_90(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_90(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_90(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_90(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_90(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_90(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_90(t[20], t[10], m, mp);
-        sp_2048_mont_mul_90(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_90(t[22], t[11], m, mp);
-        sp_2048_mont_mul_90(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_90(t[24], t[12], m, mp);
-        sp_2048_mont_mul_90(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_90(t[26], t[13], m, mp);
-        sp_2048_mont_mul_90(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_90(t[28], t[14], m, mp);
-        sp_2048_mont_mul_90(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_90(t[30], t[15], m, mp);
-        sp_2048_mont_mul_90(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 22) / 23) - 1;
-        c = bits % 23;
-        if (c == 0)
-            c = 23;
-        if (i < 90)
-            n = e[i--] << (32 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (9 - c);
-            c += 23;
-        }
-        y = n >> 27;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (9 - c);
-                c += 23;
-            }
-            y = (n >> 27) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_2048_mont_sqr_90(rt, rt, m, mp);
-            sp_2048_mont_sqr_90(rt, rt, m, mp);
-            sp_2048_mont_sqr_90(rt, rt, m, mp);
-            sp_2048_mont_sqr_90(rt, rt, m, mp);
-            sp_2048_mont_sqr_90(rt, rt, m, mp);
-
-            sp_2048_mont_mul_90(rt, rt, t[y], m, mp);
-        }
-
-        sp_2048_mont_reduce_90(rt, m, mp);
-        n = sp_2048_cmp_90(rt, m);
-        sp_2048_cond_sub_90(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \
-                                    !defined(RSA_LOW_MEM)
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_45(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<45; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 40; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-    r[40] = a[40] & m;
-    r[41] = a[41] & m;
-    r[42] = a[42] & m;
-    r[43] = a[43] & m;
-    r[44] = a[44] & m;
-#endif
-}
-
-#endif
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* d = NULL;
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit* norm;
-    sp_digit e[1];
-    sp_digit mp;
-    int i;
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 90 * 2;
-        m = r + 90 * 2;
-        norm = r;
-
-        sp_2048_from_bin(a, 90, in, inLen);
-#if DIGIT_BIT >= 23
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 90, mm);
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_90(norm, m);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_90(a, a, norm);
-        err = sp_2048_mod_90(a, a, m);
-    }
-    if (err == MP_OKAY) {
-        for (i=22; i>=0; i--)
-            if (e[0] >> i)
-                break;
-
-        XMEMCPY(r, a, sizeof(sp_digit) * 90 * 2);
-        for (i--; i>=0; i--) {
-            sp_2048_mont_sqr_90(r, r, m, mp);
-
-            if (((e[0] >> i) & 1) == 1)
-                sp_2048_mont_mul_90(r, r, a, m, mp);
-        }
-        sp_2048_mont_reduce_90(r, m, mp);
-        mp = sp_2048_cmp_90(r, m);
-        sp_2048_cond_sub_90(r, r, m, (mp < 0) - 1);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#else
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[180], md[90], rd[180];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 90 * 2;
-        m = r + 90 * 2;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 90, in, inLen);
-#if DIGIT_BIT >= 23
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 90, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_2048_sqr_90(r, a);
-                err = sp_2048_mod_90(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_2048_mul_90(r, a, r);
-                err = sp_2048_mod_90(r, r, m);
-            }
-        }
-        else {
-            sp_digit* norm = r;
-            int i;
-            sp_digit mp;
-
-            sp_2048_mont_setup(m, &mp);
-            sp_2048_mont_norm_90(norm, m);
-
-            if (err == MP_OKAY) {
-                sp_2048_mul_90(a, a, norm);
-                err = sp_2048_mod_90(a, a, m);
-            }
-
-            if (err == MP_OKAY) {
-                for (i=22; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 180);
-                for (i--; i>=0; i--) {
-                    sp_2048_mont_sqr_90(r, r, m, mp);
-
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_2048_mont_mul_90(r, r, a, m, mp);
-                }
-                sp_2048_mont_reduce_90(r, m, mp);
-                mp = sp_2048_cmp_90(r, m);
-                sp_2048_cond_sub_90(r, r, m, (mp < 0) - 1);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* a;
-    sp_digit* d = NULL;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = d + 90;
-        m = a + 90;
-        r = a;
-
-        sp_2048_from_bin(a, 90, in, inLen);
-        sp_2048_from_mp(d, 90, dm);
-        sp_2048_from_mp(m, 90, mm);
-        err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 90);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[180], d[90], m[90];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 90, in, inLen);
-        sp_2048_from_mp(d, 90, dm);
-        sp_2048_from_mp(m, 90, mm);
-        err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    XMEMSET(d, 0, sizeof(sp_digit) * 90);
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#else
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* t = NULL;
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 90 * 2;
-        q = p + 45;
-        qi = dq = dp = q + 45;
-        tmpa = qi + 45;
-        tmpb = tmpa + 90;
-
-        tmp = t;
-        r = tmp + 90;
-
-        sp_2048_from_bin(a, 90, in, inLen);
-        sp_2048_from_mp(p, 45, pm);
-        sp_2048_from_mp(q, 45, qm);
-        sp_2048_from_mp(dp, 45, dpm);
-        err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(dq, 45, dqm);
-        err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_sub_45(tmpa, tmpa, tmpb);
-        sp_2048_mask_45(tmp, p, tmpa[44] >> 31);
-        sp_2048_add_45(tmpa, tmpa, tmp);
-
-        sp_2048_from_mp(qi, 45, qim);
-        sp_2048_mul_45(tmpa, tmpa, qi);
-        err = sp_2048_mod_45(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_45(tmpa, q, tmpa);
-        sp_2048_add_90(r, tmpb, tmpa);
-        sp_2048_norm_90(r);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 45 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[90 * 2];
-    sp_digit p[45], q[45], dp[45], dq[45], qi[45];
-    sp_digit tmp[90], tmpa[90], tmpb[90];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 90, in, inLen);
-        sp_2048_from_mp(p, 45, pm);
-        sp_2048_from_mp(q, 45, qm);
-        sp_2048_from_mp(dp, 45, dpm);
-        sp_2048_from_mp(dq, 45, dqm);
-        sp_2048_from_mp(qi, 45, qim);
-
-        err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY)
-        err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1);
-
-    if (err == MP_OKAY) {
-        sp_2048_sub_45(tmpa, tmpa, tmpb);
-        sp_2048_mask_45(tmp, p, tmpa[44] >> 31);
-        sp_2048_add_45(tmpa, tmpa, tmp);
-        sp_2048_mul_45(tmpa, tmpa, qi);
-        err = sp_2048_mod_45(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_45(tmpa, tmpa, q);
-        sp_2048_add_90(r, tmpb, tmpa);
-        sp_2048_norm_90(r);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    XMEMSET(tmpa, 0, sizeof(tmpa));
-    XMEMSET(tmpb, 0, sizeof(tmpb));
-    XMEMSET(p, 0, sizeof(p));
-    XMEMSET(q, 0, sizeof(q));
-    XMEMSET(dp, 0, sizeof(dp));
-    XMEMSET(dq, 0, sizeof(dq));
-    XMEMSET(qi, 0, sizeof(qi));
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
-}
-
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_2048_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 23
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 90);
-        r->used = 90;
-        mp_clamp(r);
-#elif DIGIT_BIT < 23
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 90; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 23) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 23 - s;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 90; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 23 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 23 - s;
-            }
-            else
-                s += 23;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 90 * 2;
-        m = e + 90;
-        r = b;
-
-        sp_2048_from_mp(b, 90, base);
-        sp_2048_from_mp(e, 90, exp);
-        sp_2048_from_mp(m, 90, mod);
-
-        err = sp_2048_mod_exp_90(r, b, e, mp_count_bits(exp), m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 90);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[180], ed[90], md[90];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 90 * 2;
-        m = e + 90;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 90, base);
-        sp_2048_from_mp(e, 90, exp);
-        sp_2048_from_mp(m, 90, mod);
-
-        err = sp_2048_mod_exp_90(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 90);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 256 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 90 * 2;
-        m = e + 90;
-        r = b;
-
-        sp_2048_from_mp(b, 90, base);
-        sp_2048_from_bin(e, 90, exp, expLen);
-        sp_2048_from_mp(m, 90, mod);
-
-        err = sp_2048_mod_exp_90(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 90);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[180], ed[90], md[90];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-    int err = MP_OKAY;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 90 * 2;
-        m = e + 90;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 90, base);
-        sp_2048_from_bin(e, 90, exp, expLen);
-        sp_2048_from_mp(m, 90, mod);
-
-        err = sp_2048_mod_exp_90(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 90);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_2048 */
-
-#ifndef WOLFSSL_SP_NO_3072
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 15) {
-            r[j] &= 0x7fffff;
-            s = 23 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 23
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 23
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0x7fffff;
-        s = 23 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 23 <= DIGIT_BIT) {
-            s += 23;
-            r[j] &= 0x7fffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 23) {
-            r[j] &= 0x7fffff;
-            if (j + 1 >= max)
-                break;
-            s = 23 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 384
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_3072_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<135; i++) {
-        r[i+1] += r[i] >> 23;
-        r[i] &= 0x7fffff;
-    }
-    j = 3072 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<136 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 23) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 23);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_17(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j;
-    int64_t t[34];
-
-    XMEMSET(t, 0, sizeof(t));
-    for (i=0; i<17; i++) {
-        for (j=0; j<17; j++)
-            t[i+j] += ((int64_t)a[i]) * b[j];
-    }
-    for (i=0; i<33; i++) {
-        r[i] = t[i] & 0x7fffff;
-        t[i+1] += t[i] >> 23;
-    }
-    r[33] = (sp_digit)t[33];
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_17(sp_digit* r, const sp_digit* a)
-{
-    int i, j;
-    int64_t t[34];
-
-    XMEMSET(t, 0, sizeof(t));
-    for (i=0; i<17; i++) {
-        for (j=0; j<i; j++)
-            t[i+j] += (((int64_t)a[i]) * a[j]) * 2;
-        t[i+i] += ((int64_t)a[i]) * a[i];
-    }
-    for (i=0; i<33; i++) {
-        r[i] = t[i] & 0x7fffff;
-        t[i+1] += t[i] >> 23;
-    }
-    r[33] = (sp_digit)t[33];
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_17(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[16] = a[16] + b[16];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_34(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[32] = a[32] + b[32];
-    r[33] = a[33] + b[33];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_34(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[32] = a[32] - b[32];
-    r[33] = a[33] - b[33];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_34(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[34];
-    sp_digit* a1 = z1;
-    sp_digit b1[17];
-    sp_digit* z2 = r + 34;
-    sp_3072_add_17(a1, a, &a[17]);
-    sp_3072_add_17(b1, b, &b[17]);
-    sp_3072_mul_17(z2, &a[17], &b[17]);
-    sp_3072_mul_17(z0, a, b);
-    sp_3072_mul_17(z1, a1, b1);
-    sp_3072_sub_34(z1, z1, z2);
-    sp_3072_sub_34(z1, z1, z0);
-    sp_3072_add_34(r + 17, r + 17, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_34(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[34];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 34;
-    sp_3072_add_17(a1, a, &a[17]);
-    sp_3072_sqr_17(z2, &a[17]);
-    sp_3072_sqr_17(z0, a);
-    sp_3072_sqr_17(z1, a1);
-    sp_3072_sub_34(z1, z1, z2);
-    sp_3072_sub_34(z1, z1, z0);
-    sp_3072_add_34(r + 17, r + 17, z1);
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[64] = a[64] + b[64];
-    r[65] = a[65] + b[65];
-    r[66] = a[66] + b[66];
-    r[67] = a[67] + b[67];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[64] = a[64] - b[64];
-    r[65] = a[65] - b[65];
-    r[66] = a[66] - b[66];
-    r[67] = a[67] - b[67];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_68(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[68];
-    sp_digit* a1 = z1;
-    sp_digit b1[34];
-    sp_digit* z2 = r + 68;
-    sp_3072_add_34(a1, a, &a[34]);
-    sp_3072_add_34(b1, b, &b[34]);
-    sp_3072_mul_34(z2, &a[34], &b[34]);
-    sp_3072_mul_34(z0, a, b);
-    sp_3072_mul_34(z1, a1, b1);
-    sp_3072_sub_68(z1, z1, z2);
-    sp_3072_sub_68(z1, z1, z0);
-    sp_3072_add_68(r + 34, r + 34, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_68(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[68];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 68;
-    sp_3072_add_34(a1, a, &a[34]);
-    sp_3072_sqr_34(z2, &a[34]);
-    sp_3072_sqr_34(z0, a);
-    sp_3072_sqr_34(z1, a1);
-    sp_3072_sub_68(z1, z1, z2);
-    sp_3072_sub_68(z1, z1, z0);
-    sp_3072_add_68(r + 34, r + 34, z1);
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_136(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[136];
-    sp_digit* a1 = z1;
-    sp_digit b1[68];
-    sp_digit* z2 = r + 136;
-    sp_3072_add_68(a1, a, &a[68]);
-    sp_3072_add_68(b1, b, &b[68]);
-    sp_3072_mul_68(z2, &a[68], &b[68]);
-    sp_3072_mul_68(z0, a, b);
-    sp_3072_mul_68(z1, a1, b1);
-    sp_3072_sub_136(z1, z1, z2);
-    sp_3072_sub_136(z1, z1, z0);
-    sp_3072_add_136(r + 68, r + 68, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_136(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[136];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 136;
-    sp_3072_add_68(a1, a, &a[68]);
-    sp_3072_sqr_68(z2, &a[68]);
-    sp_3072_sqr_68(z0, a);
-    sp_3072_sqr_68(z1, a1);
-    sp_3072_sub_136(z1, z1, z2);
-    sp_3072_sub_136(z1, z1, z0);
-    sp_3072_add_136(r + 68, r + 68, z1);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_136(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[135]) * b[135];
-    r[271] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 269; k >= 0; k--) {
-        for (i = 135; i >= 0; i--) {
-            j = k - i;
-            if (j >= 136)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_136(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[135]) * a[135];
-    r[271] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 269; k >= 0; k--) {
-        for (i = 135; i >= 0; i--) {
-            j = k - i;
-            if (j >= 136 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int64_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_68(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[67]) * b[67];
-    r[135] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 133; k >= 0; k--) {
-        for (i = 67; i >= 0; i--) {
-            j = k - i;
-            if (j >= 68)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_68(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[67]) * a[67];
-    r[135] = (sp_digit)(c >> 23);
-    c = (c & 0x7fffff) << 23;
-    for (k = 133; k >= 0; k--) {
-        for (i = 67; i >= 0; i--) {
-            j = k - i;
-            if (j >= 68 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int64_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 46;
-        r[k + 1] = (c >> 23) & 0x7fffff;
-        c = (c & 0x7fffff) << 23;
-    }
-    r[0] = (sp_digit)(c >> 23);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x &= 0x7fffff;
-
-    /* rho = -1/m mod b */
-    *rho = (1L << 23) - x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_68(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<67; i++)
-        r[i] = 0x7fffff;
-#else
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i + 0] = 0x7fffff;
-        r[i + 1] = 0x7fffff;
-        r[i + 2] = 0x7fffff;
-        r[i + 3] = 0x7fffff;
-        r[i + 4] = 0x7fffff;
-        r[i + 5] = 0x7fffff;
-        r[i + 6] = 0x7fffff;
-        r[i + 7] = 0x7fffff;
-    }
-    r[64] = 0x7fffff;
-    r[65] = 0x7fffff;
-    r[66] = 0x7fffff;
-#endif
-    r[67] = 0x3ffffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_3072_sub_68(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_3072_cmp_68(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=67; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[67] - b[67]) & (0 - !r);
-    r |= (a[66] - b[66]) & (0 - !r);
-    r |= (a[65] - b[65]) & (0 - !r);
-    r |= (a[64] - b[64]) & (0 - !r);
-    for (i = 56; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_sub_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[64] = a[64] - (b[64] & m);
-    r[65] = a[65] - (b[65] & m);
-    r[66] = a[66] - (b[66] & m);
-    r[67] = a[67] - (b[67] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_add_68(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 68; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[68] += t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff;
-    for (i = 0; i < 64; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[65]; r[65] += (t[0] >> 23) + (t[1] & 0x7fffff);
-    t[2] = tb * a[66]; r[66] += (t[1] >> 23) + (t[2] & 0x7fffff);
-    t[3] = tb * a[67]; r[67] += (t[2] >> 23) + (t[3] & 0x7fffff);
-    r[68] +=  t[3] >> 23;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 23.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_3072_norm_68(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 67; i++) {
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-#else
-    int i;
-    for (i = 0; i < 64; i += 8) {
-        a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff;
-        a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff;
-        a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff;
-        a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff;
-        a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff;
-        a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff;
-        a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff;
-        a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff;
-        a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff;
-    }
-    a[64+1] += a[64] >> 23;
-    a[64] &= 0x7fffff;
-    a[65+1] += a[65] >> 23;
-    a[65] &= 0x7fffff;
-    a[66+1] += a[66] >> 23;
-    a[66] &= 0x7fffff;
-#endif
-}
-
-/* Shift the result in the high 1536 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_3072_mont_shift_68(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    sp_digit n, s;
-
-    s = a[68];
-    n = a[67] >> 18;
-    for (i = 0; i < 67; i++) {
-        n += (s & 0x7fffff) << 5;
-        r[i] = n & 0x7fffff;
-        n >>= 23;
-        s = a[69 + i] + (s >> 23);
-    }
-    n += s << 5;
-    r[67] = n;
-#else
-    sp_digit n, s;
-    int i;
-
-    s = a[68]; n = a[67] >> 18;
-    for (i = 0; i < 64; i += 8) {
-        n += (s & 0x7fffff) << 5; r[i+0] = n & 0x7fffff;
-        n >>= 23; s = a[i+69] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+1] = n & 0x7fffff;
-        n >>= 23; s = a[i+70] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+2] = n & 0x7fffff;
-        n >>= 23; s = a[i+71] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+3] = n & 0x7fffff;
-        n >>= 23; s = a[i+72] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+4] = n & 0x7fffff;
-        n >>= 23; s = a[i+73] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+5] = n & 0x7fffff;
-        n >>= 23; s = a[i+74] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+6] = n & 0x7fffff;
-        n >>= 23; s = a[i+75] + (s >> 23);
-        n += (s & 0x7fffff) << 5; r[i+7] = n & 0x7fffff;
-        n >>= 23; s = a[i+76] + (s >> 23);
-    }
-    n += (s & 0x7fffff) << 5; r[64] = n & 0x7fffff;
-    n >>= 23; s = a[133] + (s >> 23);
-    n += (s & 0x7fffff) << 5; r[65] = n & 0x7fffff;
-    n >>= 23; s = a[134] + (s >> 23);
-    n += (s & 0x7fffff) << 5; r[66] = n & 0x7fffff;
-    n >>= 23; s = a[135] + (s >> 23);
-    n += s << 5;              r[67] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[68], 0, sizeof(*r) * 68);
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_3072_mont_reduce_68(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    for (i=0; i<67; i++) {
-        mu = (a[i] * mp) & 0x7fffff;
-        sp_3072_mul_add_68(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-    }
-    mu = (a[i] * mp) & 0x3ffffl;
-    sp_3072_mul_add_68(a+i, m, mu);
-    a[i+1] += a[i] >> 23;
-    a[i] &= 0x7fffff;
-
-    sp_3072_mont_shift_68(a, a);
-    sp_3072_cond_sub_68(a, a, m, 0 - ((a[67] >> 18) > 0));
-    sp_3072_norm_68(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_68(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_68(r, a, b);
-    sp_3072_mont_reduce_68(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_68(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_68(r, a);
-    sp_3072_mont_reduce_68(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_d_68(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 68; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[68] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 64; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    t[1] = tb * a[65];
-    r[65] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-    t[2] = tb * a[66];
-    r[66] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-    t[3] = tb * a[67];
-    r[67] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-    r[68] =  (sp_digit)(t[3] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_add_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[64] = a[64] + (b[64] & m);
-    r[65] = a[65] + (b[65] & m);
-    r[66] = a[66] + (b[66] & m);
-    r[67] = a[67] + (b[67] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_68(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 68; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_div_68(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int64_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[136], t2d[68 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 68 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 68;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[67];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 68);
-        for (i=67; i>=0; i--) {
-            t1[68 + i] += t1[68 + i - 1] >> 23;
-            t1[68 + i - 1] &= 0x7fffff;
-            d1 = t1[68 + i];
-            d1 <<= 23;
-            d1 += t1[68 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_3072_mul_d_68(t2, d, r1);
-            sp_3072_sub_68(&t1[i], &t1[i], t2);
-            t1[68 + i] -= t2[68];
-            t1[68 + i] += t1[68 + i - 1] >> 23;
-            t1[68 + i - 1] &= 0x7fffff;
-            r1 = (((-t1[68 + i]) << 23) - t1[68 + i - 1]) / div;
-            r1++;
-            sp_3072_mul_d_68(t2, d, r1);
-            sp_3072_add_68(&t1[i], &t1[i], t2);
-            t1[68 + i] += t1[68 + i - 1] >> 23;
-            t1[68 + i - 1] &= 0x7fffff;
-        }
-        t1[68 - 1] += t1[68 - 2] >> 23;
-        t1[68 - 2] &= 0x7fffff;
-        d1 = t1[68 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_3072_mul_d_68(t2, d, r1);
-        sp_3072_sub_68(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 68);
-        for (i=0; i<66; i++) {
-            r[i+1] += r[i] >> 23;
-            r[i] &= 0x7fffff;
-        }
-        sp_3072_cond_add_68(r, r, d, 0 - (r[67] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_mod_68(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_68(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_68(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 68 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 68 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[68 * 2];
-        t[2] = &td[2 * 68 * 2];
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_68(norm, m);
-
-        if (reduceA)
-            err = sp_3072_mod_68(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 68);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_68(t[1], t[1], norm);
-        err = sp_3072_mod_68(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_68(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 68 * 2);
-            sp_3072_mont_sqr_68(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 68 * 2);
-        }
-
-        sp_3072_mont_reduce_68(t[0], m, mp);
-        n = sp_3072_cmp_68(t[0], m);
-        sp_3072_cond_sub_68(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 68 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][136];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 68 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[68 * 2];
-        t[2] = &td[2 * 68 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_68(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_68(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_68(t[1], t[1], norm);
-                err = sp_3072_mod_68(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_68(t[1], a, norm);
-            err = sp_3072_mod_68(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_68(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_3072_mont_sqr_68(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_3072_mont_reduce_68(t[0], m, mp);
-        n = sp_3072_cmp_68(t[0], m);
-        sp_3072_cond_sub_68(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][136];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[136];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 136, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 136;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_68(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_68(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_68(t[1], t[1], norm);
-                err = sp_3072_mod_68(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_68(t[1], a, norm);
-            err = sp_3072_mod_68(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_68(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_68(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_68(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_68(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_68(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_68(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_68(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_68(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_68(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_68(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_68(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_68(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_68(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_68(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_68(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_68(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_68(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_68(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_68(t[20], t[10], m, mp);
-        sp_3072_mont_mul_68(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_68(t[22], t[11], m, mp);
-        sp_3072_mont_mul_68(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_68(t[24], t[12], m, mp);
-        sp_3072_mont_mul_68(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_68(t[26], t[13], m, mp);
-        sp_3072_mont_mul_68(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_68(t[28], t[14], m, mp);
-        sp_3072_mont_mul_68(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_68(t[30], t[15], m, mp);
-        sp_3072_mont_mul_68(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 22) / 23) - 1;
-        c = bits % 23;
-        if (c == 0)
-            c = 23;
-        if (i < 68)
-            n = e[i--] << (32 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (9 - c);
-            c += 23;
-        }
-        y = n >> 27;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (9 - c);
-                c += 23;
-            }
-            y = (n >> 27) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_3072_mont_sqr_68(rt, rt, m, mp);
-            sp_3072_mont_sqr_68(rt, rt, m, mp);
-            sp_3072_mont_sqr_68(rt, rt, m, mp);
-            sp_3072_mont_sqr_68(rt, rt, m, mp);
-            sp_3072_mont_sqr_68(rt, rt, m, mp);
-
-            sp_3072_mont_mul_68(rt, rt, t[y], m, mp);
-        }
-
-        sp_3072_mont_reduce_68(rt, m, mp);
-        n = sp_3072_cmp_68(rt, m);
-        sp_3072_cond_sub_68(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_136(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<135; i++)
-        r[i] = 0x7fffff;
-#else
-    int i;
-
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = 0x7fffff;
-        r[i + 1] = 0x7fffff;
-        r[i + 2] = 0x7fffff;
-        r[i + 3] = 0x7fffff;
-        r[i + 4] = 0x7fffff;
-        r[i + 5] = 0x7fffff;
-        r[i + 6] = 0x7fffff;
-        r[i + 7] = 0x7fffff;
-    }
-#endif
-    r[135] = 0x1fffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_3072_sub_136(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_3072_cmp_136(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=135; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    for (i = 128; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_sub_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_add_136(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 136; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[136] += t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff;
-    for (i = 0; i < 136; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    r[136] +=  t[7] >> 23;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 23.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_3072_norm_136(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 135; i++) {
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-#else
-    int i;
-    for (i = 0; i < 128; i += 8) {
-        a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff;
-        a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff;
-        a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff;
-        a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff;
-        a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff;
-        a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff;
-        a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff;
-        a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff;
-        a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff;
-    }
-    a[128+1] += a[128] >> 23;
-    a[128] &= 0x7fffff;
-    a[129+1] += a[129] >> 23;
-    a[129] &= 0x7fffff;
-    a[130+1] += a[130] >> 23;
-    a[130] &= 0x7fffff;
-    a[131+1] += a[131] >> 23;
-    a[131] &= 0x7fffff;
-    a[132+1] += a[132] >> 23;
-    a[132] &= 0x7fffff;
-    a[133+1] += a[133] >> 23;
-    a[133] &= 0x7fffff;
-    a[134+1] += a[134] >> 23;
-    a[134] &= 0x7fffff;
-#endif
-}
-
-/* Shift the result in the high 3072 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_3072_mont_shift_136(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    int64_t n = a[135] >> 13;
-    n += ((int64_t)a[136]) << 10;
-
-    for (i = 0; i < 135; i++) {
-        r[i] = n & 0x7fffff;
-        n >>= 23;
-        n += ((int64_t)a[137 + i]) << 10;
-    }
-    r[135] = (sp_digit)n;
-#else
-    int i;
-    int64_t n = a[135] >> 13;
-    n += ((int64_t)a[136]) << 10;
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 137]) << 10;
-        r[i + 1] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 138]) << 10;
-        r[i + 2] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 139]) << 10;
-        r[i + 3] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 140]) << 10;
-        r[i + 4] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 141]) << 10;
-        r[i + 5] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 142]) << 10;
-        r[i + 6] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 143]) << 10;
-        r[i + 7] = n & 0x7fffff;
-        n >>= 23; n += ((int64_t)a[i + 144]) << 10;
-    }
-    r[135] = (sp_digit)n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[136], 0, sizeof(*r) * 136);
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_3072_mont_reduce_136(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<135; i++) {
-            mu = (a[i] * mp) & 0x7fffff;
-            sp_3072_mul_add_136(a+i, m, mu);
-            a[i+1] += a[i] >> 23;
-        }
-        mu = (a[i] * mp) & 0x1fffl;
-        sp_3072_mul_add_136(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-    else {
-        for (i=0; i<135; i++) {
-            mu = a[i] & 0x7fffff;
-            sp_3072_mul_add_136(a+i, m, mu);
-            a[i+1] += a[i] >> 23;
-        }
-        mu = a[i] & 0x1fffl;
-        sp_3072_mul_add_136(a+i, m, mu);
-        a[i+1] += a[i] >> 23;
-        a[i] &= 0x7fffff;
-    }
-
-    sp_3072_mont_shift_136(a, a);
-    sp_3072_cond_sub_136(a, a, m, 0 - ((a[135] >> 13) > 0));
-    sp_3072_norm_136(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_136(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_136(r, a, b);
-    sp_3072_mont_reduce_136(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_136(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_136(r, a);
-    sp_3072_mont_reduce_136(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_d_136(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 136; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[136] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 136; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    r[136] =  (sp_digit)(t[7] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_d_272(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 272; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x7fffff;
-        t >>= 23;
-    }
-    r[272] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff;
-    for (i = 0; i < 272; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff);
-    }
-    r[272] =  (sp_digit)(t[7] >> 23);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_add_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 136; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_136(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 136; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-SP_NOINLINE static void sp_3072_rshift_136(sp_digit* r, sp_digit* a, byte n)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<135; i++)
-        r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff;
-#else
-    r[0] = ((a[0] >> n) | (a[1] << (23 - n))) & 0x7fffff;
-    r[1] = ((a[1] >> n) | (a[2] << (23 - n))) & 0x7fffff;
-    r[2] = ((a[2] >> n) | (a[3] << (23 - n))) & 0x7fffff;
-    r[3] = ((a[3] >> n) | (a[4] << (23 - n))) & 0x7fffff;
-    r[4] = ((a[4] >> n) | (a[5] << (23 - n))) & 0x7fffff;
-    r[5] = ((a[5] >> n) | (a[6] << (23 - n))) & 0x7fffff;
-    r[6] = ((a[6] >> n) | (a[7] << (23 - n))) & 0x7fffff;
-    r[7] = ((a[7] >> n) | (a[8] << (23 - n))) & 0x7fffff;
-    r[8] = ((a[8] >> n) | (a[9] << (23 - n))) & 0x7fffff;
-    r[9] = ((a[9] >> n) | (a[10] << (23 - n))) & 0x7fffff;
-    r[10] = ((a[10] >> n) | (a[11] << (23 - n))) & 0x7fffff;
-    r[11] = ((a[11] >> n) | (a[12] << (23 - n))) & 0x7fffff;
-    r[12] = ((a[12] >> n) | (a[13] << (23 - n))) & 0x7fffff;
-    r[13] = ((a[13] >> n) | (a[14] << (23 - n))) & 0x7fffff;
-    r[14] = ((a[14] >> n) | (a[15] << (23 - n))) & 0x7fffff;
-    r[15] = ((a[15] >> n) | (a[16] << (23 - n))) & 0x7fffff;
-    r[16] = ((a[16] >> n) | (a[17] << (23 - n))) & 0x7fffff;
-    r[17] = ((a[17] >> n) | (a[18] << (23 - n))) & 0x7fffff;
-    r[18] = ((a[18] >> n) | (a[19] << (23 - n))) & 0x7fffff;
-    r[19] = ((a[19] >> n) | (a[20] << (23 - n))) & 0x7fffff;
-    r[20] = ((a[20] >> n) | (a[21] << (23 - n))) & 0x7fffff;
-    r[21] = ((a[21] >> n) | (a[22] << (23 - n))) & 0x7fffff;
-    r[22] = ((a[22] >> n) | (a[23] << (23 - n))) & 0x7fffff;
-    r[23] = ((a[23] >> n) | (a[24] << (23 - n))) & 0x7fffff;
-    r[24] = ((a[24] >> n) | (a[25] << (23 - n))) & 0x7fffff;
-    r[25] = ((a[25] >> n) | (a[26] << (23 - n))) & 0x7fffff;
-    r[26] = ((a[26] >> n) | (a[27] << (23 - n))) & 0x7fffff;
-    r[27] = ((a[27] >> n) | (a[28] << (23 - n))) & 0x7fffff;
-    r[28] = ((a[28] >> n) | (a[29] << (23 - n))) & 0x7fffff;
-    r[29] = ((a[29] >> n) | (a[30] << (23 - n))) & 0x7fffff;
-    r[30] = ((a[30] >> n) | (a[31] << (23 - n))) & 0x7fffff;
-    r[31] = ((a[31] >> n) | (a[32] << (23 - n))) & 0x7fffff;
-    r[32] = ((a[32] >> n) | (a[33] << (23 - n))) & 0x7fffff;
-    r[33] = ((a[33] >> n) | (a[34] << (23 - n))) & 0x7fffff;
-    r[34] = ((a[34] >> n) | (a[35] << (23 - n))) & 0x7fffff;
-    r[35] = ((a[35] >> n) | (a[36] << (23 - n))) & 0x7fffff;
-    r[36] = ((a[36] >> n) | (a[37] << (23 - n))) & 0x7fffff;
-    r[37] = ((a[37] >> n) | (a[38] << (23 - n))) & 0x7fffff;
-    r[38] = ((a[38] >> n) | (a[39] << (23 - n))) & 0x7fffff;
-    r[39] = ((a[39] >> n) | (a[40] << (23 - n))) & 0x7fffff;
-    r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff;
-    r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff;
-    r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff;
-    r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff;
-    r[44] = ((a[44] >> n) | (a[45] << (23 - n))) & 0x7fffff;
-    r[45] = ((a[45] >> n) | (a[46] << (23 - n))) & 0x7fffff;
-    r[46] = ((a[46] >> n) | (a[47] << (23 - n))) & 0x7fffff;
-    r[47] = ((a[47] >> n) | (a[48] << (23 - n))) & 0x7fffff;
-    r[48] = ((a[48] >> n) | (a[49] << (23 - n))) & 0x7fffff;
-    r[49] = ((a[49] >> n) | (a[50] << (23 - n))) & 0x7fffff;
-    r[50] = ((a[50] >> n) | (a[51] << (23 - n))) & 0x7fffff;
-    r[51] = ((a[51] >> n) | (a[52] << (23 - n))) & 0x7fffff;
-    r[52] = ((a[52] >> n) | (a[53] << (23 - n))) & 0x7fffff;
-    r[53] = ((a[53] >> n) | (a[54] << (23 - n))) & 0x7fffff;
-    r[54] = ((a[54] >> n) | (a[55] << (23 - n))) & 0x7fffff;
-    r[55] = ((a[55] >> n) | (a[56] << (23 - n))) & 0x7fffff;
-    r[56] = ((a[56] >> n) | (a[57] << (23 - n))) & 0x7fffff;
-    r[57] = ((a[57] >> n) | (a[58] << (23 - n))) & 0x7fffff;
-    r[58] = ((a[58] >> n) | (a[59] << (23 - n))) & 0x7fffff;
-    r[59] = ((a[59] >> n) | (a[60] << (23 - n))) & 0x7fffff;
-    r[60] = ((a[60] >> n) | (a[61] << (23 - n))) & 0x7fffff;
-    r[61] = ((a[61] >> n) | (a[62] << (23 - n))) & 0x7fffff;
-    r[62] = ((a[62] >> n) | (a[63] << (23 - n))) & 0x7fffff;
-    r[63] = ((a[63] >> n) | (a[64] << (23 - n))) & 0x7fffff;
-    r[64] = ((a[64] >> n) | (a[65] << (23 - n))) & 0x7fffff;
-    r[65] = ((a[65] >> n) | (a[66] << (23 - n))) & 0x7fffff;
-    r[66] = ((a[66] >> n) | (a[67] << (23 - n))) & 0x7fffff;
-    r[67] = ((a[67] >> n) | (a[68] << (23 - n))) & 0x7fffff;
-    r[68] = ((a[68] >> n) | (a[69] << (23 - n))) & 0x7fffff;
-    r[69] = ((a[69] >> n) | (a[70] << (23 - n))) & 0x7fffff;
-    r[70] = ((a[70] >> n) | (a[71] << (23 - n))) & 0x7fffff;
-    r[71] = ((a[71] >> n) | (a[72] << (23 - n))) & 0x7fffff;
-    r[72] = ((a[72] >> n) | (a[73] << (23 - n))) & 0x7fffff;
-    r[73] = ((a[73] >> n) | (a[74] << (23 - n))) & 0x7fffff;
-    r[74] = ((a[74] >> n) | (a[75] << (23 - n))) & 0x7fffff;
-    r[75] = ((a[75] >> n) | (a[76] << (23 - n))) & 0x7fffff;
-    r[76] = ((a[76] >> n) | (a[77] << (23 - n))) & 0x7fffff;
-    r[77] = ((a[77] >> n) | (a[78] << (23 - n))) & 0x7fffff;
-    r[78] = ((a[78] >> n) | (a[79] << (23 - n))) & 0x7fffff;
-    r[79] = ((a[79] >> n) | (a[80] << (23 - n))) & 0x7fffff;
-    r[80] = ((a[80] >> n) | (a[81] << (23 - n))) & 0x7fffff;
-    r[81] = ((a[81] >> n) | (a[82] << (23 - n))) & 0x7fffff;
-    r[82] = ((a[82] >> n) | (a[83] << (23 - n))) & 0x7fffff;
-    r[83] = ((a[83] >> n) | (a[84] << (23 - n))) & 0x7fffff;
-    r[84] = ((a[84] >> n) | (a[85] << (23 - n))) & 0x7fffff;
-    r[85] = ((a[85] >> n) | (a[86] << (23 - n))) & 0x7fffff;
-    r[86] = ((a[86] >> n) | (a[87] << (23 - n))) & 0x7fffff;
-    r[87] = ((a[87] >> n) | (a[88] << (23 - n))) & 0x7fffff;
-    r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff;
-    r[89] = ((a[89] >> n) | (a[90] << (23 - n))) & 0x7fffff;
-    r[90] = ((a[90] >> n) | (a[91] << (23 - n))) & 0x7fffff;
-    r[91] = ((a[91] >> n) | (a[92] << (23 - n))) & 0x7fffff;
-    r[92] = ((a[92] >> n) | (a[93] << (23 - n))) & 0x7fffff;
-    r[93] = ((a[93] >> n) | (a[94] << (23 - n))) & 0x7fffff;
-    r[94] = ((a[94] >> n) | (a[95] << (23 - n))) & 0x7fffff;
-    r[95] = ((a[95] >> n) | (a[96] << (23 - n))) & 0x7fffff;
-    r[96] = ((a[96] >> n) | (a[97] << (23 - n))) & 0x7fffff;
-    r[97] = ((a[97] >> n) | (a[98] << (23 - n))) & 0x7fffff;
-    r[98] = ((a[98] >> n) | (a[99] << (23 - n))) & 0x7fffff;
-    r[99] = ((a[99] >> n) | (a[100] << (23 - n))) & 0x7fffff;
-    r[100] = ((a[100] >> n) | (a[101] << (23 - n))) & 0x7fffff;
-    r[101] = ((a[101] >> n) | (a[102] << (23 - n))) & 0x7fffff;
-    r[102] = ((a[102] >> n) | (a[103] << (23 - n))) & 0x7fffff;
-    r[103] = ((a[103] >> n) | (a[104] << (23 - n))) & 0x7fffff;
-    r[104] = ((a[104] >> n) | (a[105] << (23 - n))) & 0x7fffff;
-    r[105] = ((a[105] >> n) | (a[106] << (23 - n))) & 0x7fffff;
-    r[106] = ((a[106] >> n) | (a[107] << (23 - n))) & 0x7fffff;
-    r[107] = ((a[107] >> n) | (a[108] << (23 - n))) & 0x7fffff;
-    r[108] = ((a[108] >> n) | (a[109] << (23 - n))) & 0x7fffff;
-    r[109] = ((a[109] >> n) | (a[110] << (23 - n))) & 0x7fffff;
-    r[110] = ((a[110] >> n) | (a[111] << (23 - n))) & 0x7fffff;
-    r[111] = ((a[111] >> n) | (a[112] << (23 - n))) & 0x7fffff;
-    r[112] = ((a[112] >> n) | (a[113] << (23 - n))) & 0x7fffff;
-    r[113] = ((a[113] >> n) | (a[114] << (23 - n))) & 0x7fffff;
-    r[114] = ((a[114] >> n) | (a[115] << (23 - n))) & 0x7fffff;
-    r[115] = ((a[115] >> n) | (a[116] << (23 - n))) & 0x7fffff;
-    r[116] = ((a[116] >> n) | (a[117] << (23 - n))) & 0x7fffff;
-    r[117] = ((a[117] >> n) | (a[118] << (23 - n))) & 0x7fffff;
-    r[118] = ((a[118] >> n) | (a[119] << (23 - n))) & 0x7fffff;
-    r[119] = ((a[119] >> n) | (a[120] << (23 - n))) & 0x7fffff;
-    r[120] = ((a[120] >> n) | (a[121] << (23 - n))) & 0x7fffff;
-    r[121] = ((a[121] >> n) | (a[122] << (23 - n))) & 0x7fffff;
-    r[122] = ((a[122] >> n) | (a[123] << (23 - n))) & 0x7fffff;
-    r[123] = ((a[123] >> n) | (a[124] << (23 - n))) & 0x7fffff;
-    r[124] = ((a[124] >> n) | (a[125] << (23 - n))) & 0x7fffff;
-    r[125] = ((a[125] >> n) | (a[126] << (23 - n))) & 0x7fffff;
-    r[126] = ((a[126] >> n) | (a[127] << (23 - n))) & 0x7fffff;
-    r[127] = ((a[127] >> n) | (a[128] << (23 - n))) & 0x7fffff;
-    r[128] = ((a[128] >> n) | (a[129] << (23 - n))) & 0x7fffff;
-    r[129] = ((a[129] >> n) | (a[130] << (23 - n))) & 0x7fffff;
-    r[130] = ((a[130] >> n) | (a[131] << (23 - n))) & 0x7fffff;
-    r[131] = ((a[131] >> n) | (a[132] << (23 - n))) & 0x7fffff;
-    r[132] = ((a[132] >> n) | (a[133] << (23 - n))) & 0x7fffff;
-    r[133] = ((a[133] >> n) | (a[134] << (23 - n))) & 0x7fffff;
-    r[134] = ((a[134] >> n) | (a[135] << (23 - n))) & 0x7fffff;
-#endif
-    r[135] = a[135] >> n;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_div_136(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int64_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[272 + 1], t2d[136 + 1], sdd[136 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    sp_digit* sd;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (4 * 136 + 3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 272 + 1;
-        sd = t2 + 136 + 1;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-    sd = sdd;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_d_136(sd, d, 1 << 10);
-        sp_3072_mul_d_272(t1, a, 1 << 10);
-        div = sd[135];
-        for (i=136; i>=0; i--) {
-            t1[136 + i] += t1[136 + i - 1] >> 23;
-            t1[136 + i - 1] &= 0x7fffff;
-            d1 = t1[136 + i];
-            d1 <<= 23;
-            d1 += t1[136 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_3072_mul_d_136(t2, sd, r1);
-            sp_3072_sub_136(&t1[i], &t1[i], t2);
-            t1[136 + i] -= t2[136];
-            t1[136 + i] += t1[136 + i - 1] >> 23;
-            t1[136 + i - 1] &= 0x7fffff;
-            r1 = (((-t1[136 + i]) << 23) - t1[136 + i - 1]) / div;
-            r1 -= t1[136 + i];
-            sp_3072_mul_d_136(t2, sd, r1);
-            sp_3072_add_136(&t1[i], &t1[i], t2);
-            t1[136 + i] += t1[136 + i - 1] >> 23;
-            t1[136 + i - 1] &= 0x7fffff;
-        }
-        t1[136 - 1] += t1[136 - 2] >> 23;
-        t1[136 - 2] &= 0x7fffff;
-        d1 = t1[136 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_3072_mul_d_136(t2, sd, r1);
-        sp_3072_sub_136(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 136);
-        for (i=0; i<134; i++) {
-            r[i+1] += r[i] >> 23;
-            r[i] &= 0x7fffff;
-        }
-        sp_3072_cond_add_136(r, r, sd, 0 - (r[135] < 0));
-    }
-
-    sp_3072_rshift_136(r, r, 10);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_mod_136(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_136(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_136(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 136 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 136 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[136 * 2];
-        t[2] = &td[2 * 136 * 2];
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_136(norm, m);
-
-        if (reduceA)
-            err = sp_3072_mod_136(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 136);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_136(t[1], t[1], norm);
-        err = sp_3072_mod_136(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_136(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 136 * 2);
-            sp_3072_mont_sqr_136(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 136 * 2);
-        }
-
-        sp_3072_mont_reduce_136(t[0], m, mp);
-        n = sp_3072_cmp_136(t[0], m);
-        sp_3072_cond_sub_136(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 136 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][272];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 136 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[136 * 2];
-        t[2] = &td[2 * 136 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_136(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_136(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_136(t[1], t[1], norm);
-                err = sp_3072_mod_136(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_136(t[1], a, norm);
-            err = sp_3072_mod_136(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 23;
-        c = bits % 23;
-        n = e[i--] << (23 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 23;
-            }
-
-            y = (n >> 22) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_136(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_3072_mont_sqr_136(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_3072_mont_reduce_136(t[0], m, mp);
-        n = sp_3072_cmp_136(t[0], m);
-        sp_3072_cond_sub_136(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][272];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[272];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 272, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 272;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_136(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_136(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_136(t[1], t[1], norm);
-                err = sp_3072_mod_136(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_136(t[1], a, norm);
-            err = sp_3072_mod_136(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_136(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_136(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_136(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_136(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_136(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_136(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_136(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_136(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_136(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_136(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_136(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_136(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_136(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_136(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_136(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_136(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_136(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_136(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_136(t[20], t[10], m, mp);
-        sp_3072_mont_mul_136(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_136(t[22], t[11], m, mp);
-        sp_3072_mont_mul_136(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_136(t[24], t[12], m, mp);
-        sp_3072_mont_mul_136(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_136(t[26], t[13], m, mp);
-        sp_3072_mont_mul_136(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_136(t[28], t[14], m, mp);
-        sp_3072_mont_mul_136(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_136(t[30], t[15], m, mp);
-        sp_3072_mont_mul_136(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 22) / 23) - 1;
-        c = bits % 23;
-        if (c == 0)
-            c = 23;
-        if (i < 136)
-            n = e[i--] << (32 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (9 - c);
-            c += 23;
-        }
-        y = n >> 27;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (9 - c);
-                c += 23;
-            }
-            y = (n >> 27) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_3072_mont_sqr_136(rt, rt, m, mp);
-            sp_3072_mont_sqr_136(rt, rt, m, mp);
-            sp_3072_mont_sqr_136(rt, rt, m, mp);
-            sp_3072_mont_sqr_136(rt, rt, m, mp);
-            sp_3072_mont_sqr_136(rt, rt, m, mp);
-
-            sp_3072_mont_mul_136(rt, rt, t[y], m, mp);
-        }
-
-        sp_3072_mont_reduce_136(rt, m, mp);
-        n = sp_3072_cmp_136(rt, m);
-        sp_3072_cond_sub_136(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \
-                                    !defined(RSA_LOW_MEM)
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_68(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<68; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 64; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-    r[64] = a[64] & m;
-    r[65] = a[65] & m;
-    r[66] = a[66] & m;
-    r[67] = a[67] & m;
-#endif
-}
-
-#endif
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* d = NULL;
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit* norm;
-    sp_digit e[1];
-    sp_digit mp;
-    int i;
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 136 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 136 * 2;
-        m = r + 136 * 2;
-        norm = r;
-
-        sp_3072_from_bin(a, 136, in, inLen);
-#if DIGIT_BIT >= 23
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 136, mm);
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_136(norm, m);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_136(a, a, norm);
-        err = sp_3072_mod_136(a, a, m);
-    }
-    if (err == MP_OKAY) {
-        for (i=22; i>=0; i--)
-            if (e[0] >> i)
-                break;
-
-        XMEMCPY(r, a, sizeof(sp_digit) * 136 * 2);
-        for (i--; i>=0; i--) {
-            sp_3072_mont_sqr_136(r, r, m, mp);
-
-            if (((e[0] >> i) & 1) == 1)
-                sp_3072_mont_mul_136(r, r, a, m, mp);
-        }
-        sp_3072_mont_reduce_136(r, m, mp);
-        mp = sp_3072_cmp_136(r, m);
-        sp_3072_cond_sub_136(r, r, m, (mp < 0) - 1);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#else
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[272], md[136], rd[272];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 136 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 136 * 2;
-        m = r + 136 * 2;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 136, in, inLen);
-#if DIGIT_BIT >= 23
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 136, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_3072_sqr_136(r, a);
-                err = sp_3072_mod_136(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_3072_mul_136(r, a, r);
-                err = sp_3072_mod_136(r, r, m);
-            }
-        }
-        else {
-            sp_digit* norm = r;
-            int i;
-            sp_digit mp;
-
-            sp_3072_mont_setup(m, &mp);
-            sp_3072_mont_norm_136(norm, m);
-
-            if (err == MP_OKAY) {
-                sp_3072_mul_136(a, a, norm);
-                err = sp_3072_mod_136(a, a, m);
-            }
-
-            if (err == MP_OKAY) {
-                for (i=22; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 272);
-                for (i--; i>=0; i--) {
-                    sp_3072_mont_sqr_136(r, r, m, mp);
-
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_3072_mont_mul_136(r, r, a, m, mp);
-                }
-                sp_3072_mont_reduce_136(r, m, mp);
-                mp = sp_3072_cmp_136(r, m);
-                sp_3072_cond_sub_136(r, r, m, (mp < 0) - 1);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* a;
-    sp_digit* d = NULL;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 136 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = d + 136;
-        m = a + 136;
-        r = a;
-
-        sp_3072_from_bin(a, 136, in, inLen);
-        sp_3072_from_mp(d, 136, dm);
-        sp_3072_from_mp(m, 136, mm);
-        err = sp_3072_mod_exp_136(r, a, d, 3072, m, 0);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 136);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[272], d[136], m[136];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 136, in, inLen);
-        sp_3072_from_mp(d, 136, dm);
-        sp_3072_from_mp(m, 136, mm);
-        err = sp_3072_mod_exp_136(r, a, d, 3072, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    XMEMSET(d, 0, sizeof(sp_digit) * 136);
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#else
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* t = NULL;
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 68 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 136 * 2;
-        q = p + 68;
-        qi = dq = dp = q + 68;
-        tmpa = qi + 68;
-        tmpb = tmpa + 136;
-
-        tmp = t;
-        r = tmp + 136;
-
-        sp_3072_from_bin(a, 136, in, inLen);
-        sp_3072_from_mp(p, 68, pm);
-        sp_3072_from_mp(q, 68, qm);
-        sp_3072_from_mp(dp, 68, dpm);
-        err = sp_3072_mod_exp_68(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(dq, 68, dqm);
-        err = sp_3072_mod_exp_68(tmpb, a, dq, 1536, q, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_sub_68(tmpa, tmpa, tmpb);
-        sp_3072_mask_68(tmp, p, tmpa[67] >> 31);
-        sp_3072_add_68(tmpa, tmpa, tmp);
-
-        sp_3072_from_mp(qi, 68, qim);
-        sp_3072_mul_68(tmpa, tmpa, qi);
-        err = sp_3072_mod_68(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_68(tmpa, q, tmpa);
-        sp_3072_add_136(r, tmpb, tmpa);
-        sp_3072_norm_136(r);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 68 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[136 * 2];
-    sp_digit p[68], q[68], dp[68], dq[68], qi[68];
-    sp_digit tmp[136], tmpa[136], tmpb[136];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 136, in, inLen);
-        sp_3072_from_mp(p, 68, pm);
-        sp_3072_from_mp(q, 68, qm);
-        sp_3072_from_mp(dp, 68, dpm);
-        sp_3072_from_mp(dq, 68, dqm);
-        sp_3072_from_mp(qi, 68, qim);
-
-        err = sp_3072_mod_exp_68(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY)
-        err = sp_3072_mod_exp_68(tmpb, a, dq, 1536, q, 1);
-
-    if (err == MP_OKAY) {
-        sp_3072_sub_68(tmpa, tmpa, tmpb);
-        sp_3072_mask_68(tmp, p, tmpa[67] >> 31);
-        sp_3072_add_68(tmpa, tmpa, tmp);
-        sp_3072_mul_68(tmpa, tmpa, qi);
-        err = sp_3072_mod_68(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_68(tmpa, tmpa, q);
-        sp_3072_add_136(r, tmpb, tmpa);
-        sp_3072_norm_136(r);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    XMEMSET(tmpa, 0, sizeof(tmpa));
-    XMEMSET(tmpb, 0, sizeof(tmpb));
-    XMEMSET(p, 0, sizeof(p));
-    XMEMSET(q, 0, sizeof(q));
-    XMEMSET(dp, 0, sizeof(dp));
-    XMEMSET(dq, 0, sizeof(dq));
-    XMEMSET(qi, 0, sizeof(qi));
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
-}
-
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_3072_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 23
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 136);
-        r->used = 136;
-        mp_clamp(r);
-#elif DIGIT_BIT < 23
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 136; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 23) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 23 - s;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 136; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 23 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 23 - s;
-            }
-            else
-                s += 23;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 136 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 136 * 2;
-        m = e + 136;
-        r = b;
-
-        sp_3072_from_mp(b, 136, base);
-        sp_3072_from_mp(e, 136, exp);
-        sp_3072_from_mp(m, 136, mod);
-
-        err = sp_3072_mod_exp_136(r, b, e, mp_count_bits(exp), m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 136);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[272], ed[136], md[136];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 136 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 136 * 2;
-        m = e + 136;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 136, base);
-        sp_3072_from_mp(e, 136, exp);
-        sp_3072_from_mp(m, 136, mod);
-
-        err = sp_3072_mod_exp_136(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 136);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 384 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 136 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 136 * 2;
-        m = e + 136;
-        r = b;
-
-        sp_3072_from_mp(b, 136, base);
-        sp_3072_from_bin(e, 136, exp, expLen);
-        sp_3072_from_mp(m, 136, mod);
-
-        err = sp_3072_mod_exp_136(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 136);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[272], ed[136], md[136];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-    int err = MP_OKAY;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 136 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 136 * 2;
-        m = e + 136;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 136, base);
-        sp_3072_from_bin(e, 136, exp, expLen);
-        sp_3072_from_mp(m, 136, mod);
-
-        err = sp_3072_mod_exp_136(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 136);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_3072 */
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-
-/* Point structure to use. */
-typedef struct sp_point {
-    sp_digit x[2 * 10];
-    sp_digit y[2 * 10];
-    sp_digit z[2 * 10];
-    int infinity;
-} sp_point;
-
-/* The modulus (prime) of the curve P256. */
-static sp_digit p256_mod[10] = {
-    0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000,
-    0x0000400,0x3ff0000,0x03fffff
-};
-#ifndef WOLFSSL_SP_SMALL
-/* The Montogmery normalizer for modulus of the curve P256. */
-static sp_digit p256_norm_mod[10] = {
-    0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff,
-    0x3fffbff,0x000ffff,0x0000000
-};
-#endif /* WOLFSSL_SP_SMALL */
-/* The Montogmery multiplier for modulus of the curve P256. */
-static sp_digit p256_mp_mod = 0x000001;
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
-                                            defined(HAVE_ECC_VERIFY)
-/* The order of the curve P256. */
-static sp_digit p256_order[10] = {
-    0x0632551,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff,
-    0x00003ff,0x3ff0000,0x03fffff
-};
-#endif
-/* The order of the curve P256 minus 2. */
-static sp_digit p256_order2[10] = {
-    0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff,
-    0x00003ff,0x3ff0000,0x03fffff
-};
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery normalizer for order of the curve P256. */
-static sp_digit p256_norm_order[10] = {
-    0x39cdaaf,0x18d4f40,0x217b0c4,0x14963a1,0x0431905,0x0000000,0x0000000,
-    0x3fffc00,0x000ffff,0x0000000
-};
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery multiplier for order of the curve P256. */
-static sp_digit p256_mp_order = 0x200bc4f;
-#endif
-/* The base point of curve P256. */
-static sp_point p256_base = {
-    /* X ordinate */
-    {
-        0x098c296,0x04e5176,0x33a0f4a,0x204b7ac,0x277037d,0x0e9103c,0x3ce6e56,
-        0x1091fe2,0x1f2e12c,0x01ac5f4
-    },
-    /* Y ordinate */
-    {
-        0x3bf51f5,0x1901a0d,0x1ececbb,0x15dacc5,0x22bce33,0x303e785,0x27eb4a7,
-        0x1fe6e3b,0x2e2fe1a,0x013f8d0
-    },
-    /* Z ordinate */
-    {
-        0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
-        0x0000000,0x0000000,0x0000000
-    },
-    /* infinity */
-    0
-};
-#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
-static sp_digit p256_b[10] = {
-    0x3d2604b,0x38f0f89,0x30f63bc,0x2c3314e,0x0651d06,0x1a621af,0x2bbd557,
-    0x24f9ecf,0x1d8aa3a,0x016b18d
-};
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* Allocate memory for point and return error. */
-#define sp_ecc_point_new(heap, sp, p)                                   \
-    ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \
-        MEMORY_E : MP_OKAY
-#else
-/* Set pointer to data and return no error. */
-#define sp_ecc_point_new(heap, sp, p)   ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* If valid pointer then clear point data if requested and free data. */
-#define sp_ecc_point_free(p, clear, heap)     \
-    do {                                      \
-        if (p != NULL) {                      \
-            if (clear)                        \
-                XMEMSET(p, 0, sizeof(*p));    \
-            XFREE(p, heap, DYNAMIC_TYPE_ECC); \
-        }                                     \
-    }                                         \
-    while (0)
-#else
-/* Clear point data if requested. */
-#define sp_ecc_point_free(p, clear, heap) \
-    do {                                  \
-        if (clear)                        \
-            XMEMSET(p, 0, sizeof(*p));    \
-    }                                     \
-    while (0)
-#endif
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r  The resulting Montgomery form number.
- * a  The number to convert.
- * m  The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mod_mul_norm_10(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    int64_t* td;
-#else
-    int64_t td[8];
-    int64_t a32d[8];
-#endif
-    int64_t* t;
-    int64_t* a32;
-    int64_t o;
-    int err = MP_OKAY;
-
-    (void)m;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
-    if (td != NULL) {
-        t = td;
-        a32 = td + 8;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t = td;
-    a32 = a32d;
-#endif
-
-    if (err == MP_OKAY) {
-        a32[0] = a[0];
-        a32[0] |= a[1] << 26;
-        a32[0] &= 0xffffffff;
-        a32[1] = (sp_digit)(a[1] >> 6);
-        a32[1] |= a[2] << 20;
-        a32[1] &= 0xffffffff;
-        a32[2] = (sp_digit)(a[2] >> 12);
-        a32[2] |= a[3] << 14;
-        a32[2] &= 0xffffffff;
-        a32[3] = (sp_digit)(a[3] >> 18);
-        a32[3] |= a[4] << 8;
-        a32[3] &= 0xffffffff;
-        a32[4] = (sp_digit)(a[4] >> 24);
-        a32[4] |= a[5] << 2;
-        a32[4] |= a[6] << 28;
-        a32[4] &= 0xffffffff;
-        a32[5] = (sp_digit)(a[6] >> 4);
-        a32[5] |= a[7] << 22;
-        a32[5] &= 0xffffffff;
-        a32[6] = (sp_digit)(a[7] >> 10);
-        a32[6] |= a[8] << 16;
-        a32[6] &= 0xffffffff;
-        a32[7] = (sp_digit)(a[8] >> 16);
-        a32[7] |= a[9] << 10;
-        a32[7] &= 0xffffffff;
-
-        /*  1  1  0 -1 -1 -1 -1  0 */
-        t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
-        /*  0  1  1  0 -1 -1 -1 -1 */
-        t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
-        /*  0  0  1  1  0 -1 -1 -1 */
-        t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
-        /* -1 -1  0  2  2  1  0 -1 */
-        t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
-        /*  0 -1 -1  0  2  2  1  0 */
-        t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
-        /*  0  0 -1 -1  0  2  2  1 */
-        t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
-        /* -1 -1  0  0  0  1  3  2 */
-        t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
-        /*  1  0 -1 -1 -1 -1  0  3 */
-        t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
-        t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-        t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-        t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-        t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-        t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-        t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-        t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-        o     = t[7] >> 32; t[7] &= 0xffffffff;
-        t[0] += o;
-        t[3] -= o;
-        t[6] -= o;
-        t[7] += o;
-        t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-        t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-        t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-        t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-        t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-        t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-        t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-
-        r[0] = (sp_digit)(t[0]) & 0x3ffffff;
-        r[1] = (sp_digit)(t[0] >> 26);
-        r[1] |= t[1] << 6;
-        r[1] &= 0x3ffffff;
-        r[2] = (sp_digit)(t[1] >> 20);
-        r[2] |= t[2] << 12;
-        r[2] &= 0x3ffffff;
-        r[3] = (sp_digit)(t[2] >> 14);
-        r[3] |= t[3] << 18;
-        r[3] &= 0x3ffffff;
-        r[4] = (sp_digit)(t[3] >> 8);
-        r[4] |= t[4] << 24;
-        r[4] &= 0x3ffffff;
-        r[5] = (sp_digit)(t[4] >> 2) & 0x3ffffff;
-        r[6] = (sp_digit)(t[4] >> 28);
-        r[6] |= t[5] << 4;
-        r[6] &= 0x3ffffff;
-        r[7] = (sp_digit)(t[5] >> 22);
-        r[7] |= t[6] << 10;
-        r[7] &= 0x3ffffff;
-        r[8] = (sp_digit)(t[6] >> 16);
-        r[8] |= t[7] << 16;
-        r[8] &= 0x3ffffff;
-        r[9] = (sp_digit)(t[7] >> 10);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 26
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 26
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0x3ffffff;
-        s = 26 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 26 <= DIGIT_BIT) {
-            s += 26;
-            r[j] &= 0x3ffffff;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 26) {
-            r[j] &= 0x3ffffff;
-            if (j + 1 >= max)
-                break;
-            s = 26 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point.
- *
- * p   Point of type sp_point (result).
- * pm  Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_10(sp_point* p, ecc_point* pm)
-{
-    XMEMSET(p->x, 0, sizeof(p->x));
-    XMEMSET(p->y, 0, sizeof(p->y));
-    XMEMSET(p->z, 0, sizeof(p->z));
-    sp_256_from_mp(p->x, 10, pm->x);
-    sp_256_from_mp(p->y, 10, pm->y);
-    sp_256_from_mp(p->z, 10, pm->z);
-    p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_256_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 26
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 10);
-        r->used = 10;
-        mp_clamp(r);
-#elif DIGIT_BIT < 26
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 10; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 26) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 26 - s;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 10; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 26 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 32
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 26 - s;
-            }
-            else
-                s += 26;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Convert a point of type sp_point to type ecc_point.
- *
- * p   Point of type sp_point.
- * pm  Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_10(sp_point* p, ecc_point* pm)
-{
-    int err;
-
-    err = sp_256_to_mp(p->x, pm->x);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pm->y);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pm->z);
-
-    return err;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=9; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    r |= (a[ 9] - b[ 9]) & (0 - !r);
-    r |= (a[ 8] - b[ 8]) & (0 - !r);
-    r |= (a[ 7] - b[ 7]) & (0 - !r);
-    r |= (a[ 6] - b[ 6]) & (0 - !r);
-    r |= (a[ 5] - b[ 5]) & (0 - !r);
-    r |= (a[ 4] - b[ 4]) & (0 - !r);
-    r |= (a[ 3] - b[ 3]) & (0 - !r);
-    r |= (a[ 2] - b[ 2]) & (0 - !r);
-    r |= (a[ 1] - b[ 1]) & (0 - !r);
-    r |= (a[ 0] - b[ 0]) & (0 - !r);
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Normalize the values in each word to 26.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_256_norm_10(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 9; i++) {
-        a[i+1] += a[i] >> 26;
-        a[i] &= 0x3ffffff;
-    }
-#else
-    a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
-    a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
-    a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
-    a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
-    a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
-    a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
-    a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
-    a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
-    a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
-#endif
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_256_cond_sub_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 10; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    r[ 0] = a[ 0] - (b[ 0] & m);
-    r[ 1] = a[ 1] - (b[ 1] & m);
-    r[ 2] = a[ 2] - (b[ 2] & m);
-    r[ 3] = a[ 3] - (b[ 3] & m);
-    r[ 4] = a[ 4] - (b[ 4] & m);
-    r[ 5] = a[ 5] - (b[ 5] & m);
-    r[ 6] = a[ 6] - (b[ 6] & m);
-    r[ 7] = a[ 7] - (b[ 7] & m);
-    r[ 8] = a[ 8] - (b[ 8] & m);
-    r[ 9] = a[ 9] - (b[ 9] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 10; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x3ffffff;
-        t >>= 26;
-    }
-    r[10] += t;
-#else
-    int64_t tb = b;
-    int64_t t[10];
-
-    t[ 0] = tb * a[ 0];
-    t[ 1] = tb * a[ 1];
-    t[ 2] = tb * a[ 2];
-    t[ 3] = tb * a[ 3];
-    t[ 4] = tb * a[ 4];
-    t[ 5] = tb * a[ 5];
-    t[ 6] = tb * a[ 6];
-    t[ 7] = tb * a[ 7];
-    t[ 8] = tb * a[ 8];
-    t[ 9] = tb * a[ 9];
-    r[ 0] +=                 (t[ 0] & 0x3ffffff);
-    r[ 1] += (t[ 0] >> 26) + (t[ 1] & 0x3ffffff);
-    r[ 2] += (t[ 1] >> 26) + (t[ 2] & 0x3ffffff);
-    r[ 3] += (t[ 2] >> 26) + (t[ 3] & 0x3ffffff);
-    r[ 4] += (t[ 3] >> 26) + (t[ 4] & 0x3ffffff);
-    r[ 5] += (t[ 4] >> 26) + (t[ 5] & 0x3ffffff);
-    r[ 6] += (t[ 5] >> 26) + (t[ 6] & 0x3ffffff);
-    r[ 7] += (t[ 6] >> 26) + (t[ 7] & 0x3ffffff);
-    r[ 8] += (t[ 7] >> 26) + (t[ 8] & 0x3ffffff);
-    r[ 9] += (t[ 8] >> 26) + (t[ 9] & 0x3ffffff);
-    r[10] +=  t[ 9] >> 26;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Shift the result in the high 256 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    sp_digit n, s;
-
-    s = a[10];
-    n = a[9] >> 22;
-    for (i = 0; i < 9; i++) {
-        n += (s & 0x3ffffff) << 4;
-        r[i] = n & 0x3ffffff;
-        n >>= 26;
-        s = a[11 + i] + (s >> 26);
-    }
-    n += s << 4;
-    r[9] = n;
-#else
-    sp_digit n, s;
-
-    s = a[10]; n = a[9] >> 22;
-    n += (s & 0x3ffffff) << 4; r[ 0] = n & 0x3ffffff;
-    n >>= 26; s = a[11] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 1] = n & 0x3ffffff;
-    n >>= 26; s = a[12] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 2] = n & 0x3ffffff;
-    n >>= 26; s = a[13] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 3] = n & 0x3ffffff;
-    n >>= 26; s = a[14] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 4] = n & 0x3ffffff;
-    n >>= 26; s = a[15] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 5] = n & 0x3ffffff;
-    n >>= 26; s = a[16] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 6] = n & 0x3ffffff;
-    n >>= 26; s = a[17] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 7] = n & 0x3ffffff;
-    n >>= 26; s = a[18] + (s >> 26);
-    n += (s & 0x3ffffff) << 4; r[ 8] = n & 0x3ffffff;
-    n >>= 26; s = a[19] + (s >> 26);
-    n += s << 4;              r[ 9] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[10], 0, sizeof(*r) * 10);
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_256_mont_reduce_10(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<9; i++) {
-            mu = (a[i] * mp) & 0x3ffffff;
-            sp_256_mul_add_10(a+i, m, mu);
-            a[i+1] += a[i] >> 26;
-        }
-        mu = (a[i] * mp) & 0x3fffffl;
-        sp_256_mul_add_10(a+i, m, mu);
-        a[i+1] += a[i] >> 26;
-        a[i] &= 0x3ffffff;
-    }
-    else {
-        for (i=0; i<9; i++) {
-            mu = a[i] & 0x3ffffff;
-            sp_256_mul_add_10(a+i, p256_mod, mu);
-            a[i+1] += a[i] >> 26;
-        }
-        mu = a[i] & 0x3fffffl;
-        sp_256_mul_add_10(a+i, p256_mod, mu);
-        a[i+1] += a[i] >> 26;
-        a[i] &= 0x3ffffff;
-    }
-
-    sp_256_mont_shift_10(a, a);
-    sp_256_cond_sub_10(a, a, m, 0 - ((a[9] >> 22) > 0));
-    sp_256_norm_10(a);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[9]) * b[9];
-    r[19] = (sp_digit)(c >> 26);
-    c = (c & 0x3ffffff) << 26;
-    for (k = 17; k >= 0; k--) {
-        for (i = 9; i >= 0; i--) {
-            j = k - i;
-            if (j >= 10)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 52;
-        r[k + 1] = (c >> 26) & 0x3ffffff;
-        c = (c & 0x3ffffff) << 26;
-    }
-    r[0] = (sp_digit)(c >> 26);
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int64_t t0   = ((int64_t)a[ 0]) * b[ 0];
-    int64_t t1   = ((int64_t)a[ 0]) * b[ 1]
-                 + ((int64_t)a[ 1]) * b[ 0];
-    int64_t t2   = ((int64_t)a[ 0]) * b[ 2]
-                 + ((int64_t)a[ 1]) * b[ 1]
-                 + ((int64_t)a[ 2]) * b[ 0];
-    int64_t t3   = ((int64_t)a[ 0]) * b[ 3]
-                 + ((int64_t)a[ 1]) * b[ 2]
-                 + ((int64_t)a[ 2]) * b[ 1]
-                 + ((int64_t)a[ 3]) * b[ 0];
-    int64_t t4   = ((int64_t)a[ 0]) * b[ 4]
-                 + ((int64_t)a[ 1]) * b[ 3]
-                 + ((int64_t)a[ 2]) * b[ 2]
-                 + ((int64_t)a[ 3]) * b[ 1]
-                 + ((int64_t)a[ 4]) * b[ 0];
-    int64_t t5   = ((int64_t)a[ 0]) * b[ 5]
-                 + ((int64_t)a[ 1]) * b[ 4]
-                 + ((int64_t)a[ 2]) * b[ 3]
-                 + ((int64_t)a[ 3]) * b[ 2]
-                 + ((int64_t)a[ 4]) * b[ 1]
-                 + ((int64_t)a[ 5]) * b[ 0];
-    int64_t t6   = ((int64_t)a[ 0]) * b[ 6]
-                 + ((int64_t)a[ 1]) * b[ 5]
-                 + ((int64_t)a[ 2]) * b[ 4]
-                 + ((int64_t)a[ 3]) * b[ 3]
-                 + ((int64_t)a[ 4]) * b[ 2]
-                 + ((int64_t)a[ 5]) * b[ 1]
-                 + ((int64_t)a[ 6]) * b[ 0];
-    int64_t t7   = ((int64_t)a[ 0]) * b[ 7]
-                 + ((int64_t)a[ 1]) * b[ 6]
-                 + ((int64_t)a[ 2]) * b[ 5]
-                 + ((int64_t)a[ 3]) * b[ 4]
-                 + ((int64_t)a[ 4]) * b[ 3]
-                 + ((int64_t)a[ 5]) * b[ 2]
-                 + ((int64_t)a[ 6]) * b[ 1]
-                 + ((int64_t)a[ 7]) * b[ 0];
-    int64_t t8   = ((int64_t)a[ 0]) * b[ 8]
-                 + ((int64_t)a[ 1]) * b[ 7]
-                 + ((int64_t)a[ 2]) * b[ 6]
-                 + ((int64_t)a[ 3]) * b[ 5]
-                 + ((int64_t)a[ 4]) * b[ 4]
-                 + ((int64_t)a[ 5]) * b[ 3]
-                 + ((int64_t)a[ 6]) * b[ 2]
-                 + ((int64_t)a[ 7]) * b[ 1]
-                 + ((int64_t)a[ 8]) * b[ 0];
-    int64_t t9   = ((int64_t)a[ 0]) * b[ 9]
-                 + ((int64_t)a[ 1]) * b[ 8]
-                 + ((int64_t)a[ 2]) * b[ 7]
-                 + ((int64_t)a[ 3]) * b[ 6]
-                 + ((int64_t)a[ 4]) * b[ 5]
-                 + ((int64_t)a[ 5]) * b[ 4]
-                 + ((int64_t)a[ 6]) * b[ 3]
-                 + ((int64_t)a[ 7]) * b[ 2]
-                 + ((int64_t)a[ 8]) * b[ 1]
-                 + ((int64_t)a[ 9]) * b[ 0];
-    int64_t t10  = ((int64_t)a[ 1]) * b[ 9]
-                 + ((int64_t)a[ 2]) * b[ 8]
-                 + ((int64_t)a[ 3]) * b[ 7]
-                 + ((int64_t)a[ 4]) * b[ 6]
-                 + ((int64_t)a[ 5]) * b[ 5]
-                 + ((int64_t)a[ 6]) * b[ 4]
-                 + ((int64_t)a[ 7]) * b[ 3]
-                 + ((int64_t)a[ 8]) * b[ 2]
-                 + ((int64_t)a[ 9]) * b[ 1];
-    int64_t t11  = ((int64_t)a[ 2]) * b[ 9]
-                 + ((int64_t)a[ 3]) * b[ 8]
-                 + ((int64_t)a[ 4]) * b[ 7]
-                 + ((int64_t)a[ 5]) * b[ 6]
-                 + ((int64_t)a[ 6]) * b[ 5]
-                 + ((int64_t)a[ 7]) * b[ 4]
-                 + ((int64_t)a[ 8]) * b[ 3]
-                 + ((int64_t)a[ 9]) * b[ 2];
-    int64_t t12  = ((int64_t)a[ 3]) * b[ 9]
-                 + ((int64_t)a[ 4]) * b[ 8]
-                 + ((int64_t)a[ 5]) * b[ 7]
-                 + ((int64_t)a[ 6]) * b[ 6]
-                 + ((int64_t)a[ 7]) * b[ 5]
-                 + ((int64_t)a[ 8]) * b[ 4]
-                 + ((int64_t)a[ 9]) * b[ 3];
-    int64_t t13  = ((int64_t)a[ 4]) * b[ 9]
-                 + ((int64_t)a[ 5]) * b[ 8]
-                 + ((int64_t)a[ 6]) * b[ 7]
-                 + ((int64_t)a[ 7]) * b[ 6]
-                 + ((int64_t)a[ 8]) * b[ 5]
-                 + ((int64_t)a[ 9]) * b[ 4];
-    int64_t t14  = ((int64_t)a[ 5]) * b[ 9]
-                 + ((int64_t)a[ 6]) * b[ 8]
-                 + ((int64_t)a[ 7]) * b[ 7]
-                 + ((int64_t)a[ 8]) * b[ 6]
-                 + ((int64_t)a[ 9]) * b[ 5];
-    int64_t t15  = ((int64_t)a[ 6]) * b[ 9]
-                 + ((int64_t)a[ 7]) * b[ 8]
-                 + ((int64_t)a[ 8]) * b[ 7]
-                 + ((int64_t)a[ 9]) * b[ 6];
-    int64_t t16  = ((int64_t)a[ 7]) * b[ 9]
-                 + ((int64_t)a[ 8]) * b[ 8]
-                 + ((int64_t)a[ 9]) * b[ 7];
-    int64_t t17  = ((int64_t)a[ 8]) * b[ 9]
-                 + ((int64_t)a[ 9]) * b[ 8];
-    int64_t t18  = ((int64_t)a[ 9]) * b[ 9];
-
-    t1   += t0  >> 26; r[ 0] = t0  & 0x3ffffff;
-    t2   += t1  >> 26; r[ 1] = t1  & 0x3ffffff;
-    t3   += t2  >> 26; r[ 2] = t2  & 0x3ffffff;
-    t4   += t3  >> 26; r[ 3] = t3  & 0x3ffffff;
-    t5   += t4  >> 26; r[ 4] = t4  & 0x3ffffff;
-    t6   += t5  >> 26; r[ 5] = t5  & 0x3ffffff;
-    t7   += t6  >> 26; r[ 6] = t6  & 0x3ffffff;
-    t8   += t7  >> 26; r[ 7] = t7  & 0x3ffffff;
-    t9   += t8  >> 26; r[ 8] = t8  & 0x3ffffff;
-    t10  += t9  >> 26; r[ 9] = t9  & 0x3ffffff;
-    t11  += t10 >> 26; r[10] = t10 & 0x3ffffff;
-    t12  += t11 >> 26; r[11] = t11 & 0x3ffffff;
-    t13  += t12 >> 26; r[12] = t12 & 0x3ffffff;
-    t14  += t13 >> 26; r[13] = t13 & 0x3ffffff;
-    t15  += t14 >> 26; r[14] = t14 & 0x3ffffff;
-    t16  += t15 >> 26; r[15] = t15 & 0x3ffffff;
-    t17  += t16 >> 26; r[16] = t16 & 0x3ffffff;
-    t18  += t17 >> 26; r[17] = t17 & 0x3ffffff;
-    r[19] = (sp_digit)(t18 >> 26);
-                       r[18] = t18 & 0x3ffffff;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_mul_10(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mul_10(r, a, b);
-    sp_256_mont_reduce_10(r, m, mp);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int64_t c;
-
-    c = ((int64_t)a[9]) * a[9];
-    r[19] = (sp_digit)(c >> 26);
-    c = (c & 0x3ffffff) << 26;
-    for (k = 17; k >= 0; k--) {
-        for (i = 9; i >= 0; i--) {
-            j = k - i;
-            if (j >= 10 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int64_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int64_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 52;
-        r[k + 1] = (c >> 26) & 0x3ffffff;
-        c = (c & 0x3ffffff) << 26;
-    }
-    r[0] = (sp_digit)(c >> 26);
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a)
-{
-    int64_t t0   =  ((int64_t)a[ 0]) * a[ 0];
-    int64_t t1   = (((int64_t)a[ 0]) * a[ 1]) * 2;
-    int64_t t2   = (((int64_t)a[ 0]) * a[ 2]) * 2
-                 +  ((int64_t)a[ 1]) * a[ 1];
-    int64_t t3   = (((int64_t)a[ 0]) * a[ 3]
-                 +  ((int64_t)a[ 1]) * a[ 2]) * 2;
-    int64_t t4   = (((int64_t)a[ 0]) * a[ 4]
-                 +  ((int64_t)a[ 1]) * a[ 3]) * 2
-                 +  ((int64_t)a[ 2]) * a[ 2];
-    int64_t t5   = (((int64_t)a[ 0]) * a[ 5]
-                 +  ((int64_t)a[ 1]) * a[ 4]
-                 +  ((int64_t)a[ 2]) * a[ 3]) * 2;
-    int64_t t6   = (((int64_t)a[ 0]) * a[ 6]
-                 +  ((int64_t)a[ 1]) * a[ 5]
-                 +  ((int64_t)a[ 2]) * a[ 4]) * 2
-                 +  ((int64_t)a[ 3]) * a[ 3];
-    int64_t t7   = (((int64_t)a[ 0]) * a[ 7]
-                 +  ((int64_t)a[ 1]) * a[ 6]
-                 +  ((int64_t)a[ 2]) * a[ 5]
-                 +  ((int64_t)a[ 3]) * a[ 4]) * 2;
-    int64_t t8   = (((int64_t)a[ 0]) * a[ 8]
-                 +  ((int64_t)a[ 1]) * a[ 7]
-                 +  ((int64_t)a[ 2]) * a[ 6]
-                 +  ((int64_t)a[ 3]) * a[ 5]) * 2
-                 +  ((int64_t)a[ 4]) * a[ 4];
-    int64_t t9   = (((int64_t)a[ 0]) * a[ 9]
-                 +  ((int64_t)a[ 1]) * a[ 8]
-                 +  ((int64_t)a[ 2]) * a[ 7]
-                 +  ((int64_t)a[ 3]) * a[ 6]
-                 +  ((int64_t)a[ 4]) * a[ 5]) * 2;
-    int64_t t10  = (((int64_t)a[ 1]) * a[ 9]
-                 +  ((int64_t)a[ 2]) * a[ 8]
-                 +  ((int64_t)a[ 3]) * a[ 7]
-                 +  ((int64_t)a[ 4]) * a[ 6]) * 2
-                 +  ((int64_t)a[ 5]) * a[ 5];
-    int64_t t11  = (((int64_t)a[ 2]) * a[ 9]
-                 +  ((int64_t)a[ 3]) * a[ 8]
-                 +  ((int64_t)a[ 4]) * a[ 7]
-                 +  ((int64_t)a[ 5]) * a[ 6]) * 2;
-    int64_t t12  = (((int64_t)a[ 3]) * a[ 9]
-                 +  ((int64_t)a[ 4]) * a[ 8]
-                 +  ((int64_t)a[ 5]) * a[ 7]) * 2
-                 +  ((int64_t)a[ 6]) * a[ 6];
-    int64_t t13  = (((int64_t)a[ 4]) * a[ 9]
-                 +  ((int64_t)a[ 5]) * a[ 8]
-                 +  ((int64_t)a[ 6]) * a[ 7]) * 2;
-    int64_t t14  = (((int64_t)a[ 5]) * a[ 9]
-                 +  ((int64_t)a[ 6]) * a[ 8]) * 2
-                 +  ((int64_t)a[ 7]) * a[ 7];
-    int64_t t15  = (((int64_t)a[ 6]) * a[ 9]
-                 +  ((int64_t)a[ 7]) * a[ 8]) * 2;
-    int64_t t16  = (((int64_t)a[ 7]) * a[ 9]) * 2
-                 +  ((int64_t)a[ 8]) * a[ 8];
-    int64_t t17  = (((int64_t)a[ 8]) * a[ 9]) * 2;
-    int64_t t18  =  ((int64_t)a[ 9]) * a[ 9];
-
-    t1   += t0  >> 26; r[ 0] = t0  & 0x3ffffff;
-    t2   += t1  >> 26; r[ 1] = t1  & 0x3ffffff;
-    t3   += t2  >> 26; r[ 2] = t2  & 0x3ffffff;
-    t4   += t3  >> 26; r[ 3] = t3  & 0x3ffffff;
-    t5   += t4  >> 26; r[ 4] = t4  & 0x3ffffff;
-    t6   += t5  >> 26; r[ 5] = t5  & 0x3ffffff;
-    t7   += t6  >> 26; r[ 6] = t6  & 0x3ffffff;
-    t8   += t7  >> 26; r[ 7] = t7  & 0x3ffffff;
-    t9   += t8  >> 26; r[ 8] = t8  & 0x3ffffff;
-    t10  += t9  >> 26; r[ 9] = t9  & 0x3ffffff;
-    t11  += t10 >> 26; r[10] = t10 & 0x3ffffff;
-    t12  += t11 >> 26; r[11] = t11 & 0x3ffffff;
-    t13  += t12 >> 26; r[12] = t12 & 0x3ffffff;
-    t14  += t13 >> 26; r[13] = t13 & 0x3ffffff;
-    t15  += t14 >> 26; r[14] = t14 & 0x3ffffff;
-    t16  += t15 >> 26; r[15] = t15 & 0x3ffffff;
-    t17  += t16 >> 26; r[16] = t16 & 0x3ffffff;
-    t18  += t17 >> 26; r[17] = t17 & 0x3ffffff;
-    r[19] = (sp_digit)(t18 >> 26);
-                       r[18] = t18 & 0x3ffffff;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_10(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_256_sqr_10(r, a);
-    sp_256_mont_reduce_10(r, m, mp);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_10(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_10(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_10(r, r, m, mp);
-}
-
-#else
-/* Mod-2 for the P256 curve. */
-static const uint32_t p256_mod_2[8] = {
-    0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,
-    0x00000001,0xffffffff
-};
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 10);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 10);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 10;
-    sp_digit* t3 = td + 4 * 10;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_10(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_10(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_10(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_10(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_10(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_10(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_10(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_10(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_10(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_10(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_10(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_10(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_10(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*10;
-    int32_t n;
-
-    sp_256_mont_inv_10(t1, p->z, t + 2*10);
-
-    sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 10, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_10(r->x, p256_mod);
-    sp_256_cond_sub_10(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_10(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 10, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_10(r->y, p256_mod);
-    sp_256_cond_sub_10(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_10(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 10; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] + b[ 0];
-    r[ 1] = a[ 1] + b[ 1];
-    r[ 2] = a[ 2] + b[ 2];
-    r[ 3] = a[ 3] + b[ 3];
-    r[ 4] = a[ 4] + b[ 4];
-    r[ 5] = a[ 5] + b[ 5];
-    r[ 6] = a[ 6] + b[ 6];
-    r[ 7] = a[ 7] + b[ 7];
-    r[ 8] = a[ 8] + b[ 8];
-    r[ 9] = a[ 9] + b[ 9];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Add two Montgomery form numbers (r = a + b % m).
- *
- * r   Result of addition.
- * a   First number to add in Montogmery form.
- * b   Second number to add in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_add_10(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    sp_256_add_10(r, a, b);
-    sp_256_norm_10(r);
-    sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0));
-    sp_256_norm_10(r);
-}
-
-/* Double a Montgomery form number (r = a + a % m).
- *
- * r   Result of doubling.
- * a   Number to double in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_dbl_10(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_add_10(r, a, a);
-    sp_256_norm_10(r);
-    sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0));
-    sp_256_norm_10(r);
-}
-
-/* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r   Result of Tripling.
- * a   Number to triple in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_tpl_10(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_add_10(r, a, a);
-    sp_256_norm_10(r);
-    sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0));
-    sp_256_norm_10(r);
-    sp_256_add_10(r, r, a);
-    sp_256_norm_10(r);
-    sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0));
-    sp_256_norm_10(r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 10; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] - b[ 0];
-    r[ 1] = a[ 1] - b[ 1];
-    r[ 2] = a[ 2] - b[ 2];
-    r[ 3] = a[ 3] - b[ 3];
-    r[ 4] = a[ 4] - b[ 4];
-    r[ 5] = a[ 5] - b[ 5];
-    r[ 6] = a[ 6] - b[ 6];
-    r[ 7] = a[ 7] - b[ 7];
-    r[ 8] = a[ 8] - b[ 8];
-    r[ 9] = a[ 9] - b[ 9];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_256_cond_add_10(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 10; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    r[ 0] = a[ 0] + (b[ 0] & m);
-    r[ 1] = a[ 1] + (b[ 1] & m);
-    r[ 2] = a[ 2] + (b[ 2] & m);
-    r[ 3] = a[ 3] + (b[ 3] & m);
-    r[ 4] = a[ 4] + (b[ 4] & m);
-    r[ 5] = a[ 5] + (b[ 5] & m);
-    r[ 6] = a[ 6] + (b[ 6] & m);
-    r[ 7] = a[ 7] + (b[ 7] & m);
-    r[ 8] = a[ 8] + (b[ 8] & m);
-    r[ 9] = a[ 9] + (b[ 9] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r   Result of subtration.
- * a   Number to subtract from in Montogmery form.
- * b   Number to subtract with in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_sub_10(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    sp_256_sub_10(r, a, b);
-    sp_256_cond_add_10(r, r, m, r[9] >> 22);
-    sp_256_norm_10(r);
-}
-
-/* Shift number left one bit.
- * Bottom bit is lost.
- *
- * r  Result of shift.
- * a  Number to shift.
- */
-SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<9; i++)
-        r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff;
-#else
-    r[0] = ((a[0] >> 1) | (a[1] << 25)) & 0x3ffffff;
-    r[1] = ((a[1] >> 1) | (a[2] << 25)) & 0x3ffffff;
-    r[2] = ((a[2] >> 1) | (a[3] << 25)) & 0x3ffffff;
-    r[3] = ((a[3] >> 1) | (a[4] << 25)) & 0x3ffffff;
-    r[4] = ((a[4] >> 1) | (a[5] << 25)) & 0x3ffffff;
-    r[5] = ((a[5] >> 1) | (a[6] << 25)) & 0x3ffffff;
-    r[6] = ((a[6] >> 1) | (a[7] << 25)) & 0x3ffffff;
-    r[7] = ((a[7] >> 1) | (a[8] << 25)) & 0x3ffffff;
-    r[8] = ((a[8] >> 1) | (a[9] << 25)) & 0x3ffffff;
-#endif
-    r[9] = a[9] >> 1;
-}
-
-/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r  Result of division by 2.
- * a  Number to divide.
- * m  Modulus (prime).
- */
-static void sp_256_div2_10(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_cond_add_10(r, a, m, 0 - (a[0] & 1));
-    sp_256_norm_10(r);
-    sp_256_rshift1_10(r, r);
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*10;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<10; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<10; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<10; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_10(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_10(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_10(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_10(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_10(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_10(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_10(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_10(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_10(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_10(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_10(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_10(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_10(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_10(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_10(y, y, t2, p256_mod);
-
-}
-
-/* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a  First number to compare.
- * b  Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
-static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b)
-{
-    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
-            (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) |
-            (a[8] ^ b[8]) | (a[9] ^ b[9])) == 0;
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*10;
-    sp_digit* t3 = t + 4*10;
-    sp_digit* t4 = t + 6*10;
-    sp_digit* t5 = t + 8*10;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_10(t1, p256_mod, q->y);
-    sp_256_norm_10(t1);
-    if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) &
-        (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) {
-        sp_256_proj_point_dbl_10(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<10; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<10; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<10; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_10(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_10(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_10(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_10(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_10(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_10(x, x, t5, p256_mod);
-        sp_256_mont_dbl_10(t1, y, p256_mod);
-        sp_256_mont_sub_10(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_10(y, y, x, p256_mod);
-        sp_256_mont_mul_10(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_10(y, y, t5, p256_mod);
-    }
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-    sp_point* td;
-    sp_point* t[3];
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    (void)heap;
-
-    td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC);
-    if (td == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3);
-
-        t[0] = &td[0];
-        t[1] = &td[1];
-        t[2] = &td[2];
-
-        /* t[0] = {0, 0, 1} * norm */
-        t[0]->infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_10(t[1]->x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t[1]->y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t[1]->z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        i = 9;
-        c = 22;
-        n = k[i--] << (26 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = k[i--];
-                c = 26;
-            }
-
-            y = (n >> 25) & 1;
-            n <<= 1;
-
-            sp_256_proj_point_add_10(t[y^1], t[0], t[1], tmp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(sp_point));
-            sp_256_proj_point_dbl_10(t[2], t[2], tmp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(sp_point));
-        }
-
-        if (map)
-            sp_256_map_10(r, t[0], tmp);
-        else
-            XMEMCPY(r, t[0], sizeof(sp_point));
-    }
-
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    if (td != NULL) {
-        XMEMSET(td, 0, sizeof(sp_point) * 3);
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-}
-
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[3];
-    sp_digit tmpd[2 * 10 * 5];
-#endif
-    sp_point* t;
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    (void)heap;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_point td[3];
-    t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        t[0] = &td[0];
-        t[1] = &td[1];
-        t[2] = &td[2];
-
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        i = 9;
-        c = 22;
-        n = k[i--] << (26 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = k[i--];
-                c = 26;
-            }
-
-            y = (n >> 25) & 1;
-            n <<= 1;
-
-            sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1], tmp);
-
-            XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
-                                 ((size_t)&t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_256_proj_point_dbl_10(&t[2], &t[2], tmp);
-            XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
-                           ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2]));
-        }
-
-        if (map)
-            sp_256_map_10(r, &t[0], tmp);
-        else
-            XMEMCPY(r, &t[0], sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 3);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-
-    return err;
-}
-
-#else
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry {
-    sp_digit x[10];
-    sp_digit y[10];
-    byte infinity;
-} sp_table_entry;
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_fast_10(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[16];
-    sp_point rtd;
-    sp_digit tmpd[2 * 10 * 5];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod);
-        sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod);
-        sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod);
-        t[1].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[ 2], &t[ 1], tmp);
-        t[ 2].infinity = 0;
-        sp_256_proj_point_add_10(&t[ 3], &t[ 2], &t[ 1], tmp);
-        t[ 3].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[ 4], &t[ 2], tmp);
-        t[ 4].infinity = 0;
-        sp_256_proj_point_add_10(&t[ 5], &t[ 3], &t[ 2], tmp);
-        t[ 5].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[ 6], &t[ 3], tmp);
-        t[ 6].infinity = 0;
-        sp_256_proj_point_add_10(&t[ 7], &t[ 4], &t[ 3], tmp);
-        t[ 7].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[ 8], &t[ 4], tmp);
-        t[ 8].infinity = 0;
-        sp_256_proj_point_add_10(&t[ 9], &t[ 5], &t[ 4], tmp);
-        t[ 9].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[10], &t[ 5], tmp);
-        t[10].infinity = 0;
-        sp_256_proj_point_add_10(&t[11], &t[ 6], &t[ 5], tmp);
-        t[11].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[12], &t[ 6], tmp);
-        t[12].infinity = 0;
-        sp_256_proj_point_add_10(&t[13], &t[ 7], &t[ 6], tmp);
-        t[13].infinity = 0;
-        sp_256_proj_point_dbl_10(&t[14], &t[ 7], tmp);
-        t[14].infinity = 0;
-        sp_256_proj_point_add_10(&t[15], &t[ 8], &t[ 7], tmp);
-        t[15].infinity = 0;
-
-        i = 8;
-        n = k[i+1] << 6;
-        c = 18;
-        y = n >> 24;
-        XMEMCPY(rt, &t[y], sizeof(sp_point));
-        n <<= 8;
-        for (; i>=0 || c>=4; ) {
-            if (c < 4) {
-                n |= k[i--] << (6 - c);
-                c += 26;
-            }
-            y = (n >> 28) & 0xf;
-            n <<= 4;
-            c -= 4;
-
-            sp_256_proj_point_dbl_10(rt, rt, tmp);
-            sp_256_proj_point_dbl_10(rt, rt, tmp);
-            sp_256_proj_point_dbl_10(rt, rt, tmp);
-            sp_256_proj_point_dbl_10(rt, rt, tmp);
-
-            sp_256_proj_point_add_10(rt, rt, &t[y], tmp);
-        }
-
-        if (map)
-            sp_256_map_10(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 16);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(rt, 1, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_10(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*10;
-    sp_digit* b = t + 4*10;
-    sp_digit* t1 = t + 6*10;
-    sp_digit* t2 = t + 8*10;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<10; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<10; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<10; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_10(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_10(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_10(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_10(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_10(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_10(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_10(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_10(t1, b, p256_mod);
-        sp_256_mont_sub_10(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_10(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_10(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_10(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_10(y, b, x, p256_mod);
-        sp_256_mont_mul_10(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_10(y, y, p256_mod);
-        sp_256_mont_sub_10(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_10(y, y, p256_mod);
-}
-
-#endif /* FP_ECC */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_10(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*10;
-    sp_digit* t3 = t + 4*10;
-    sp_digit* t4 = t + 6*10;
-    sp_digit* t5 = t + 8*10;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_10(t1, p256_mod, q->y);
-    sp_256_norm_10(t1);
-    if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) &
-        (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) {
-        sp_256_proj_point_dbl_10(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<10; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<10; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<10; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_10(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_10(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_10(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_10(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_10(t1, t3, p256_mod);
-        sp_256_mont_sub_10(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_10(t3, t3, x, p256_mod);
-        sp_256_mont_mul_10(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_10(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_10(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 10;
-    sp_digit* tmp = t + 4 * 10;
-
-    sp_256_mont_inv_10(t1, a->z, tmp);
-
-    sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_10(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_10(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_10(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_10(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_10(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_10(t, t, 32, tmp);
-            sp_256_proj_to_affine_10(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_10(t, s1, s2, tmp);
-                sp_256_proj_to_affine_10(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_10(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 10 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 26] >> (x % 26)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 26] >> (x % 26)) & 1) << j;
-
-            sp_256_proj_point_dbl_10(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_10(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_10(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[10];
-    sp_digit y[10];
-    sp_table_entry table[256];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_10(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_10(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_fast_10(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 10 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_10(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_fast_10(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_10(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#endif
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * p     Point to multiply.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[10];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 10, km);
-        sp_256_point_from_ecc_point_10(point, gm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_10(point, point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_10(point, point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_10(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    /* No pre-computed values. */
-    return sp_256_ecc_mulmod_10(r, &p256_base, k, map, heap);
-}
-
-#else
-static sp_table_entry p256_table[256] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x0a9143c,0x1cc3506,0x360179e,0x3f17fb6,0x075ba95,0x1d88944,
-        0x3b732b7,0x15719e7,0x376a537,0x0062417 },
-      { 0x295560a,0x094d5f3,0x245cddf,0x392e867,0x18b4ab8,0x3487cc9,
-        0x288688d,0x176174b,0x3182588,0x0215c7f },
-      0 },
-    /* 2 */
-    { { 0x147519a,0x2218090,0x32f0202,0x2b09acd,0x0d0981e,0x1e17af2,
-        0x14a7caa,0x163a6a7,0x10ddbdf,0x03654f1 },
-      { 0x1590f8f,0x0d8733f,0x09179d6,0x1ad139b,0x372e962,0x0bad933,
-        0x1961102,0x223cdff,0x37e9eb2,0x0218fae },
-      0 },
-    /* 3 */
-    { { 0x0db6485,0x1ad88d7,0x2f97785,0x288bc28,0x3808f0e,0x3df8c02,
-        0x28d9544,0x20280f9,0x055b5ff,0x00001d8 },
-      { 0x38d2010,0x13ae6e0,0x308a763,0x2ecc90d,0x254014f,0x10a9981,
-        0x247d398,0x0fb8383,0x3613437,0x020c21d },
-      0 },
-    /* 4 */
-    { { 0x2a0d2bb,0x08bf145,0x34994f9,0x1b06988,0x30d5cc1,0x1f18b22,
-        0x01cf3a5,0x199fe49,0x161fd1b,0x00bd79a },
-      { 0x1a01797,0x171c2fd,0x21925c1,0x1358255,0x23d20b4,0x1c7f6d4,
-        0x111b370,0x03dec12,0x1168d6f,0x03d923e },
-      0 },
-    /* 5 */
-    { { 0x137bbbc,0x19a11f8,0x0bec9e5,0x27a29a8,0x3e43446,0x275cd18,
-        0x0427617,0x00056c7,0x285133d,0x016af80 },
-      { 0x04c7dab,0x2a0df30,0x0c0792a,0x1310c98,0x3573d9f,0x239b30d,
-        0x1315627,0x1ce0c32,0x25b6b6f,0x0252edc },
-      0 },
-    /* 6 */
-    { { 0x20f141c,0x26d23dc,0x3c74bbf,0x334b7d6,0x06199b3,0x0441171,
-        0x3f61294,0x313bf70,0x3cb2f7d,0x03375ae },
-      { 0x2f436fd,0x19c02fa,0x26becca,0x1b6e64c,0x26f647f,0x053c948,
-        0x0fa7920,0x397d830,0x2bd4bda,0x028d86f },
-      0 },
-    /* 7 */
-    { { 0x17c13c7,0x2895616,0x03e128a,0x17d42df,0x1c38d63,0x0f02747,
-        0x039aecf,0x0a4b01c,0x209c4b5,0x02e84b2 },
-      { 0x1f91dfd,0x023e916,0x07fb9e4,0x19b3ba8,0x13af43b,0x35e02ca,
-        0x0eb0899,0x3bd2c7b,0x19d701f,0x014faee },
-      0 },
-    /* 8 */
-    { { 0x0e63d34,0x1fb8c6c,0x0fab4fe,0x1caa795,0x0f46005,0x179ed69,
-        0x093334d,0x120c701,0x39206d5,0x021627e },
-      { 0x183553a,0x03d7319,0x09e5aa7,0x12b8959,0x2087909,0x0011194,
-        0x1045071,0x0713f32,0x16d0254,0x03aec1a },
-      0 },
-    /* 9 */
-    { { 0x01647c5,0x1b2856b,0x1799461,0x11f133d,0x0b8127d,0x1937eeb,
-        0x266aa37,0x1f68f71,0x0cbd1b2,0x03aca08 },
-      { 0x287e008,0x1be361a,0x38f3940,0x276488d,0x2d87dfa,0x0333b2c,
-        0x2d2e428,0x368755b,0x09b55a7,0x007ca0a },
-      0 },
-    /* 10 */
-    { { 0x389da99,0x2a8300e,0x0022abb,0x27ae0a1,0x0a6f2d7,0x207017a,
-        0x047862b,0x1358c9e,0x35905e5,0x00cde92 },
-      { 0x1f7794a,0x1d40348,0x3f613c6,0x2ddf5b5,0x0207005,0x133f5ba,
-        0x1a37810,0x3ef5829,0x0d5f4c2,0x0035978 },
-      0 },
-    /* 11 */
-    { { 0x1275d38,0x026efad,0x2358d9d,0x1142f82,0x14268a7,0x1cfac99,
-        0x362ff49,0x288cbc1,0x24252f4,0x0308f68 },
-      { 0x394520c,0x06e13c2,0x178e5da,0x18ec16f,0x1096667,0x134a7a8,
-        0x0dcb869,0x33fc4e9,0x38cc790,0x006778e },
-      0 },
-    /* 12 */
-    { { 0x2c5fe04,0x29c5b09,0x1bdb183,0x02ceee8,0x03b28de,0x132dc4b,
-        0x32c586a,0x32ff5d0,0x3d491fc,0x038d372 },
-      { 0x2a58403,0x2351aea,0x3a53b40,0x21a0ba5,0x39a6974,0x1aaaa2b,
-        0x3901273,0x03dfe78,0x3447b4e,0x039d907 },
-      0 },
-    /* 13 */
-    { { 0x364ba59,0x14e5077,0x02fc7d7,0x3b02c09,0x1d33f10,0x0560616,
-        0x06dfc6a,0x15efd3c,0x357052a,0x01284b7 },
-      { 0x039dbd0,0x18ce3e5,0x3e1fbfa,0x352f794,0x0d3c24b,0x07c6cc5,
-        0x1e4ffa2,0x3a91bf5,0x293bb5b,0x01abd6a },
-      0 },
-    /* 14 */
-    { { 0x0c91999,0x02da644,0x0491da1,0x100a960,0x00a24b4,0x2330824,
-        0x0094b4b,0x1004cf8,0x35a66a4,0x017f8d1 },
-      { 0x13e7b4b,0x232af7e,0x391ab0f,0x069f08f,0x3292b50,0x3479898,
-        0x2889aec,0x2a4590b,0x308ecfe,0x02d5138 },
-      0 },
-    /* 15 */
-    { { 0x2ddfdce,0x231ba45,0x39e6647,0x19be245,0x12c3291,0x35399f8,
-        0x0d6e764,0x3082d3a,0x2bda6b0,0x0382dac },
-      { 0x37efb57,0x04b7cae,0x00070d3,0x379e431,0x01aac0d,0x1e6f251,
-        0x0336ad6,0x0ddd3e4,0x3de25a6,0x01c7008 },
-      0 },
-    /* 16 */
-    { { 0x3e20925,0x230912f,0x286762a,0x30e3f73,0x391c19a,0x34e1c18,
-        0x16a5d5d,0x093d96a,0x3d421d3,0x0187561 },
-      { 0x37173ea,0x19ce8a8,0x0b65e87,0x0214dde,0x2238480,0x16ead0f,
-        0x38441e0,0x3bef843,0x2124621,0x03e847f },
-      0 },
-    /* 17 */
-    { { 0x0b19ffd,0x247cacb,0x3c231c8,0x16ec648,0x201ba8d,0x2b172a3,
-        0x103d678,0x2fb72db,0x04c1f13,0x0161bac },
-      { 0x3e8ed09,0x171b949,0x2de20c3,0x0f06067,0x21e81a3,0x1b194be,
-        0x0fd6c05,0x13c449e,0x0087086,0x006756b },
-      0 },
-    /* 18 */
-    { { 0x09a4e1f,0x27d604c,0x00741e9,0x06fa49c,0x0ab7de7,0x3f4a348,
-        0x25ef0be,0x158fc9a,0x33f7f9c,0x039f001 },
-      { 0x2f59f76,0x3598e83,0x30501f6,0x15083f2,0x0669b3b,0x29980b5,
-        0x0c1f7a7,0x0f02b02,0x0fec65b,0x0382141 },
-      0 },
-    /* 19 */
-    { { 0x031b3ca,0x23da368,0x2d66f09,0x27b9b69,0x06d1cab,0x13c91ba,
-        0x3d81fa9,0x25ad16f,0x0825b09,0x01e3c06 },
-      { 0x225787f,0x3bf790e,0x2c9bb7e,0x0347732,0x28016f8,0x0d6ff0d,
-        0x2a4877b,0x1d1e833,0x3b87e94,0x010e9dc },
-      0 },
-    /* 20 */
-    { { 0x2b533d5,0x1ddcd34,0x1dc0625,0x3da86f7,0x3673b8a,0x1e7b0a4,
-        0x3e7c9aa,0x19ac55d,0x251c3b2,0x02edb79 },
-      { 0x25259b3,0x24c0ead,0x3480e7e,0x34f40e9,0x3d6a0af,0x2cf3f09,
-        0x2c83d19,0x2e66f16,0x19a5d18,0x0182d18 },
-      0 },
-    /* 21 */
-    { { 0x2e5aa1c,0x28e3846,0x3658bd6,0x0ad279c,0x1b8b765,0x397e1fb,
-        0x130014e,0x3ff342c,0x3b2aeeb,0x02743c9 },
-      { 0x2730a55,0x0918c5e,0x083aca9,0x0bf76ef,0x19c955b,0x300669c,
-        0x01dfe0a,0x312341f,0x26d356e,0x0091295 },
-      0 },
-    /* 22 */
-    { { 0x2cf1f96,0x00e52ba,0x271c6db,0x2a40930,0x19f2122,0x0b2f4ee,
-        0x26ac1b8,0x3bda498,0x0873581,0x0117963 },
-      { 0x38f9dbc,0x3d1e768,0x2040d3f,0x11ba222,0x3a8aaf1,0x1b82fb5,
-        0x1adfb24,0x2de9251,0x21cc1e4,0x0301038 },
-      0 },
-    /* 23 */
-    { { 0x38117b6,0x2bc001b,0x1433847,0x3fdce8d,0x3651969,0x3651d7a,
-        0x2b35761,0x1bb1d20,0x097682c,0x00737d7 },
-      { 0x1f04839,0x1dd6d04,0x16987db,0x3d12378,0x17dbeac,0x1c2cc86,
-        0x121dd1b,0x3fcf6ca,0x1f8a92d,0x00119d5 },
-      0 },
-    /* 24 */
-    { { 0x0e8ffcd,0x2b174af,0x1a82cc8,0x22cbf98,0x30d53c4,0x080b5b1,
-        0x3161727,0x297cfdb,0x2113b83,0x0011b97 },
-      { 0x0007f01,0x23fd936,0x3183e7b,0x0496bd0,0x07fb1ef,0x178680f,
-        0x1c5ea63,0x0016c11,0x2c3303d,0x01b8041 },
-      0 },
-    /* 25 */
-    { { 0x0dd73b1,0x1cd6122,0x10d948c,0x23e657b,0x3767070,0x15a8aad,
-        0x385ea8c,0x33c7ce0,0x0ede901,0x0110965 },
-      { 0x2d4b65b,0x2a8b244,0x0c37f8f,0x0ee5b24,0x394c234,0x3a5e347,
-        0x26e4a15,0x39a3b4c,0x2514c2e,0x029e5be },
-      0 },
-    /* 26 */
-    { { 0x23addd7,0x3ed8120,0x13b3359,0x20f959a,0x09e2a61,0x32fcf20,
-        0x05b78e3,0x19ba7e2,0x1a9c697,0x0392b4b },
-      { 0x2048a61,0x3dfd0a3,0x19a0357,0x233024b,0x3082d19,0x00fb63b,
-        0x3a1af4c,0x1450ff0,0x046c37b,0x0317a50 },
-      0 },
-    /* 27 */
-    { { 0x3e75f9e,0x294e30a,0x3a78476,0x3a32c48,0x36fd1a9,0x0427012,
-        0x1e4df0b,0x11d1f61,0x1afdb46,0x018ca0f },
-      { 0x2f2df15,0x0a33dee,0x27f4ce7,0x1542b66,0x3e592c4,0x20d2f30,
-        0x3226ade,0x2a4e3ea,0x1ab1981,0x01a2f46 },
-      0 },
-    /* 28 */
-    { { 0x087d659,0x3ab5446,0x305ac08,0x3d2cd64,0x33374d5,0x3f9d3f8,
-        0x186981c,0x37f5a5a,0x2f53c6f,0x01254a4 },
-      { 0x2cec896,0x1e32786,0x04844a8,0x043b16d,0x3d964b2,0x1935829,
-        0x16f7e26,0x1a0dd9a,0x30d2603,0x003b1d4 },
-      0 },
-    /* 29 */
-    { { 0x12687bb,0x04e816b,0x21fa2da,0x1abccb8,0x3a1f83b,0x375181e,
-        0x0f5ef51,0x0fc2ce4,0x3a66486,0x003d881 },
-      { 0x3138233,0x1f8eec3,0x2718bd6,0x1b09caa,0x2dd66b9,0x1bb222b,
-        0x1004072,0x1b73e3b,0x07208ed,0x03fc36c },
-      0 },
-    /* 30 */
-    { { 0x095d553,0x3e84053,0x0a8a749,0x3f575a0,0x3a44052,0x3ced59b,
-        0x3b4317f,0x03a8c60,0x13c8874,0x00c4ed4 },
-      { 0x0d11549,0x0b8ab02,0x221cb40,0x02ed37b,0x2071ee1,0x1fc8c83,
-        0x3987dd4,0x27e049a,0x0f986f1,0x00b4eaf },
-      0 },
-    /* 31 */
-    { { 0x15581a2,0x2214060,0x11af4c2,0x1598c88,0x19a0a6d,0x32acba6,
-        0x3a7a0f0,0x2337c66,0x210ded9,0x0300dbe },
-      { 0x1fbd009,0x3822eb0,0x181629a,0x2401b45,0x30b68b1,0x2e78363,
-        0x2b32779,0x006530b,0x2c4b6d4,0x029aca8 },
-      0 },
-    /* 32 */
-    { { 0x13549cf,0x0f943db,0x265ed43,0x1bfeb35,0x06f3369,0x3847f2d,
-        0x1bfdacc,0x26181a5,0x252af7c,0x02043b8 },
-      { 0x159bb2c,0x143f85c,0x357b654,0x2f9d62c,0x2f7dfbe,0x1a7fa9c,
-        0x057e74d,0x05d14ac,0x17a9273,0x035215c },
-      0 },
-    /* 33 */
-    { { 0x0cb5a98,0x106a2bc,0x10bf117,0x24c7cc4,0x3d3da8f,0x2ce0ab7,
-        0x14e2cba,0x1813866,0x1a72f9a,0x01a9811 },
-      { 0x2b2411d,0x3034fe8,0x16e0170,0x0f9443a,0x0be0eb8,0x2196cf3,
-        0x0c9f738,0x15e40ef,0x0faf9e1,0x034f917 },
-      0 },
-    /* 34 */
-    { { 0x03f7669,0x3da6efa,0x3d6bce1,0x209ca1d,0x109f8ae,0x09109e3,
-        0x08ae543,0x3067255,0x1dee3c2,0x0081dd5 },
-      { 0x3ef1945,0x358765b,0x28c387b,0x3bec4b4,0x218813c,0x0b7d92a,
-        0x3cd1d67,0x2c0367e,0x2e57154,0x0123717 },
-      0 },
-    /* 35 */
-    { { 0x3e5a199,0x1e42ffd,0x0bb7123,0x33e6273,0x1e0efb8,0x294671e,
-        0x3a2bfe0,0x3d11709,0x2eddff6,0x03cbec2 },
-      { 0x0b5025f,0x0255d7c,0x1f2241c,0x35d03ea,0x0550543,0x202fef4,
-        0x23c8ad3,0x354963e,0x015db28,0x0284fa4 },
-      0 },
-    /* 36 */
-    { { 0x2b65cbc,0x1e8d428,0x0226f9f,0x1c8a919,0x10b04b9,0x08fc1e8,
-        0x1ce241e,0x149bc99,0x2b01497,0x00afc35 },
-      { 0x3216fb7,0x1374fd2,0x226ad3d,0x19fef76,0x0f7d7b8,0x1c21417,
-        0x37b83f6,0x3a27eba,0x25a162f,0x010aa52 },
-      0 },
-    /* 37 */
-    { { 0x2adf191,0x1ab42fa,0x28d7584,0x2409689,0x20f8a48,0x253707d,
-        0x2030504,0x378f7a1,0x169c65e,0x00b0b76 },
-      { 0x3849c17,0x085c764,0x10dd6d0,0x2e87689,0x1460488,0x30e9521,
-        0x10c7063,0x1b6f120,0x21f42c5,0x03d0dfe },
-      0 },
-    /* 38 */
-    { { 0x20f7dab,0x035c512,0x29ac6aa,0x24c5ddb,0x20f0497,0x17ce5e1,
-        0x00a050f,0x1eaa14b,0x3335470,0x02abd16 },
-      { 0x18d364a,0x0df0cf0,0x316585e,0x018f925,0x0d40b9b,0x17b1511,
-        0x1716811,0x1caf3d0,0x10df4f2,0x0337d8c },
-      0 },
-    /* 39 */
-    { { 0x2a8b7ef,0x0f188e3,0x2287747,0x06216f0,0x008e935,0x2f6a38d,
-        0x1567722,0x0bfc906,0x0bada9e,0x03c3402 },
-      { 0x014d3b1,0x099c749,0x2a76291,0x216c067,0x3b37549,0x14ef2f6,
-        0x21b96d4,0x1ee2d71,0x2f5ca88,0x016f570 },
-      0 },
-    /* 40 */
-    { { 0x09a3154,0x3d1a7bd,0x2e9aef0,0x255b8ac,0x03e85a5,0x2a492a7,
-        0x2aec1ea,0x11c6516,0x3c8a09e,0x02a84b7 },
-      { 0x1f69f1d,0x09c89d3,0x1e7326f,0x0b28bfd,0x0e0e4c8,0x1ea7751,
-        0x18ce73b,0x2a406e7,0x273e48c,0x01b00db },
-      0 },
-    /* 41 */
-    { { 0x36e3138,0x2b84a83,0x345a5cf,0x00096b4,0x16966ef,0x159caf1,
-        0x13c64b4,0x2f89226,0x25896af,0x00a4bfd },
-      { 0x2213402,0x1435117,0x09fed52,0x09d0e4b,0x0f6580e,0x2871cba,
-        0x3b397fd,0x1c9d825,0x090311b,0x0191383 },
-      0 },
-    /* 42 */
-    { { 0x07153f0,0x1087869,0x18c9e1e,0x1e64810,0x2b86c3b,0x0175d9c,
-        0x3dce877,0x269de4e,0x393cab7,0x03c96b9 },
-      { 0x1869d0c,0x06528db,0x02641f3,0x209261b,0x29d55c8,0x25ba517,
-        0x3b5ea30,0x028f927,0x25313db,0x00e6e39 },
-      0 },
-    /* 43 */
-    { { 0x2fd2e59,0x150802d,0x098f377,0x19a4957,0x135e2c0,0x38a95ce,
-        0x1ab21a0,0x36c1b67,0x32f0f19,0x00e448b },
-      { 0x3cad53c,0x3387800,0x17e3cfb,0x03f9970,0x3225b2c,0x2a84e1d,
-        0x3af1d29,0x3fe35ca,0x2f8ce80,0x0237a02 },
-      0 },
-    /* 44 */
-    { { 0x07bbb76,0x3aa3648,0x2758afb,0x1f085e0,0x1921c7e,0x3010dac,
-        0x22b74b1,0x230137e,0x1062e36,0x021c652 },
-      { 0x3993df5,0x24a2ee8,0x126ab5f,0x2d7cecf,0x0639d75,0x16d5414,
-        0x1aa78a8,0x3f78404,0x26a5b74,0x03f0c57 },
-      0 },
-    /* 45 */
-    { { 0x0d6ecfa,0x3f506ba,0x3f86561,0x3d86bb1,0x15f8c44,0x2491d07,
-        0x052a7b4,0x2422261,0x3adee38,0x039b529 },
-      { 0x193c75d,0x14bb451,0x1162605,0x293749c,0x370a70d,0x2e8b1f6,
-        0x2ede937,0x2b95f4a,0x39a9be2,0x00d77eb },
-      0 },
-    /* 46 */
-    { { 0x2736636,0x15bf36a,0x2b7e6b9,0x25eb8b2,0x209f51d,0x3cd2659,
-        0x10bf410,0x034afec,0x3d71c83,0x0076971 },
-      { 0x0ce6825,0x07920cf,0x3c3b5c4,0x23fe55c,0x015ad11,0x08c0dae,
-        0x0552c7f,0x2e75a8a,0x0fddbf4,0x01c1df0 },
-      0 },
-    /* 47 */
-    { { 0x2b9661c,0x0ffe351,0x3d71bf6,0x1ac34b3,0x3a1dfd3,0x211fe3d,
-        0x33e140a,0x3f9100d,0x32ee50e,0x014ea18 },
-      { 0x16d8051,0x1bfda1a,0x068a097,0x2571d3d,0x1daec0c,0x39389af,
-        0x194dc35,0x3f3058a,0x36d34e1,0x000a329 },
-      0 },
-    /* 48 */
-    { { 0x09877ee,0x351f73f,0x0002d11,0x0420074,0x2c8b362,0x130982d,
-        0x02c1175,0x3c11b40,0x0d86962,0x001305f },
-      { 0x0daddf5,0x2f4252c,0x15c06d9,0x1d49339,0x1bea235,0x0b680ed,
-        0x3356e67,0x1d1d198,0x1e9fed9,0x03dee93 },
-      0 },
-    /* 49 */
-    { { 0x3e1263f,0x2fe8d3a,0x3ce6d0d,0x0d5c6b9,0x3557637,0x0a9bd48,
-        0x0405538,0x0710749,0x2005213,0x038c7e5 },
-      { 0x26b6ec6,0x2e485ba,0x3c44d1b,0x0b9cf0b,0x037a1d1,0x27428a5,
-        0x0e7eac8,0x351ef04,0x259ce34,0x02a8e98 },
-      0 },
-    /* 50 */
-    { { 0x2f3dcd3,0x3e77d4d,0x3360fbc,0x1434afd,0x36ceded,0x3d413d6,
-        0x1710fad,0x36bb924,0x1627e79,0x008e637 },
-      { 0x109569e,0x1c168db,0x3769cf4,0x2ed4527,0x0ea0619,0x17d80d3,
-        0x1c03773,0x18843fe,0x1b21c04,0x015c5fd },
-      0 },
-    /* 51 */
-    { { 0x1dd895e,0x08a7248,0x04519fe,0x001030a,0x18e5185,0x358dfb3,
-        0x13d2391,0x0a37be8,0x0560e3c,0x019828b },
-      { 0x27fcbd0,0x2a22bb5,0x30969cc,0x1e03aa7,0x1c84724,0x0ba4ad3,
-        0x32f4817,0x0914cca,0x14c4f52,0x01893b9 },
-      0 },
-    /* 52 */
-    { { 0x097eccc,0x1273936,0x00aa095,0x364fe62,0x04d49d1,0x10e9f08,
-        0x3c24230,0x3ef01c8,0x2fb92bd,0x013ce4a },
-      { 0x1e44fd9,0x27e3e9f,0x2156696,0x3915ecc,0x0b66cfb,0x1a3af0f,
-        0x2fa8033,0x0e6736c,0x177ccdb,0x0228f9e },
-      0 },
-    /* 53 */
-    { { 0x2c4b125,0x06207c1,0x0a8cdde,0x003db8f,0x1ae34e3,0x31e84fa,
-        0x2999de5,0x11013bd,0x02370c2,0x00e2234 },
-      { 0x0f91081,0x200d591,0x1504762,0x1857c05,0x23d9fcf,0x0cb34db,
-        0x27edc86,0x08cd860,0x2471810,0x029798b },
-      0 },
-    /* 54 */
-    { { 0x3acd6c8,0x097b8cb,0x3c661a8,0x15152f2,0x1699c63,0x237e64c,
-        0x23edf79,0x16b7033,0x0e6466a,0x00b11da },
-      { 0x0a64bc9,0x1bfe324,0x1f5cb34,0x08391de,0x0630a60,0x3017a21,
-        0x09d064b,0x14a8365,0x041f9e6,0x01ed799 },
-      0 },
-    /* 55 */
-    { { 0x128444a,0x2508b07,0x2a39216,0x362f84d,0x2e996c5,0x2c31ff3,
-        0x07afe5f,0x1d1288e,0x3cb0c8d,0x02e2bdc },
-      { 0x38b86fd,0x3a0ea8c,0x1cff5fd,0x1629629,0x3fee3f1,0x02b250c,
-        0x2e8f6f2,0x0225727,0x15f7f3f,0x0280d8e },
-      0 },
-    /* 56 */
-    { { 0x10f7770,0x0f1aee8,0x0e248c7,0x20684a8,0x3a6f16d,0x06f0ae7,
-        0x0df6825,0x2d4cc40,0x301875f,0x012f8da },
-      { 0x3b56dbb,0x1821ba7,0x24f8922,0x22c1f9e,0x0306fef,0x1b54bc8,
-        0x2ccc056,0x00303ba,0x2871bdc,0x0232f26 },
-      0 },
-    /* 57 */
-    { { 0x0dac4ab,0x0625730,0x3112e13,0x101c4bf,0x3a874a4,0x2873b95,
-        0x32ae7c6,0x0d7e18c,0x13e0c08,0x01139d5 },
-      { 0x334002d,0x00fffdd,0x025c6d5,0x22c2cd1,0x19d35cb,0x3a1ce2d,
-        0x3702760,0x3f06257,0x03a5eb8,0x011c29a },
-      0 },
-    /* 58 */
-    { { 0x0513482,0x1d87724,0x276a81b,0x0a807a4,0x3028720,0x339cc20,
-        0x2441ee0,0x31bbf36,0x290c63d,0x0059041 },
-      { 0x106a2ed,0x0d2819b,0x100bf50,0x114626c,0x1dd4d77,0x2e08632,
-        0x14ae72a,0x2ed3f64,0x1fd7abc,0x035cd1e },
-      0 },
-    /* 59 */
-    { { 0x2d4c6e5,0x3bec596,0x104d7ed,0x23d6c1b,0x0262cf0,0x15d72c5,
-        0x2d5bb18,0x199ac4b,0x1e30771,0x020591a },
-      { 0x21e291e,0x2e75e55,0x1661d7a,0x08b0778,0x3eb9daf,0x0d78144,
-        0x1827eb1,0x0fe73d2,0x123f0dd,0x0028db7 },
-      0 },
-    /* 60 */
-    { { 0x1d5533c,0x34cb1d0,0x228f098,0x27a1a11,0x17c5f5a,0x0d26f44,
-        0x2228ade,0x2c460e6,0x3d6fdba,0x038cc77 },
-      { 0x3cc6ed8,0x02ada1a,0x260e510,0x2f7bde8,0x37160c3,0x33a1435,
-        0x23d9a7b,0x0ce2641,0x02a492e,0x034ed1e },
-      0 },
-    /* 61 */
-    { { 0x3821f90,0x26dba3c,0x3aada14,0x3b59bad,0x292edd9,0x2804c45,
-        0x3669531,0x296f42e,0x35a4c86,0x01ca049 },
-      { 0x3ff47e5,0x2163df4,0x2441503,0x2f18405,0x15e1616,0x37f66ec,
-        0x30f11a7,0x141658a,0x27ece14,0x00b018b },
-      0 },
-    /* 62 */
-    { { 0x159ac2e,0x3e65bc0,0x2713a76,0x0db2f6c,0x3281e77,0x2391811,
-        0x16d2880,0x1fbc4ab,0x1f92c4e,0x00a0a8d },
-      { 0x0ce5cd2,0x152c7b0,0x02299c3,0x3244de7,0x2cf99ef,0x3a0b047,
-        0x2caf383,0x0aaf664,0x113554d,0x031c735 },
-      0 },
-    /* 63 */
-    { { 0x1b578f4,0x177a702,0x3a7a488,0x1638ebf,0x31884e2,0x2460bc7,
-        0x36b1b75,0x3ce8e3d,0x340cf47,0x03143d9 },
-      { 0x34b68ea,0x12b7ccd,0x1fe2a9c,0x08da659,0x0a406f3,0x1694c14,
-        0x06a2228,0x16370be,0x3a72129,0x02e7b2c },
-      0 },
-    /* 64 */
-    { { 0x0f8b16a,0x21043bd,0x266a56f,0x3fb11ec,0x197241a,0x36721f0,
-        0x006b8e6,0x2ac6c29,0x202cd42,0x0200fcf },
-      { 0x0dbec69,0x0c26a01,0x105f7f0,0x3dceeeb,0x3a83b85,0x363865f,
-        0x097273a,0x2b70718,0x00e5067,0x03025d1 },
-      0 },
-    /* 65 */
-    { { 0x379ab34,0x295bcb0,0x38d1846,0x22e1077,0x3a8ee06,0x1db1a3b,
-        0x3144591,0x07cc080,0x2d5915f,0x03c6bcc },
-      { 0x175bd50,0x0dd4c57,0x27bc99c,0x2ebdcbd,0x3837cff,0x235dc8f,
-        0x13a4184,0x0722c18,0x130e2d4,0x008f43c },
-      0 },
-    /* 66 */
-    { { 0x01500d9,0x2adbb7d,0x2da8857,0x397f2fa,0x10d890a,0x25c9654,
-        0x3e86488,0x3eb754b,0x1d6c0a3,0x02c0a23 },
-      { 0x10bcb08,0x083cc19,0x2e16853,0x04da575,0x271af63,0x2626a9d,
-        0x3520a7b,0x32348c7,0x24ff408,0x03ff4dc },
-      0 },
-    /* 67 */
-    { { 0x058e6cb,0x1a3992d,0x1d28539,0x080c5e9,0x2992dad,0x2a9d7d5,
-        0x14ae0b7,0x09b7ce0,0x34ad78c,0x03d5643 },
-      { 0x30ba55a,0x092f4f3,0x0bae0fc,0x12831de,0x20fc472,0x20ed9d2,
-        0x29864f6,0x1288073,0x254f6f7,0x00635b6 },
-      0 },
-    /* 68 */
-    { { 0x1be5a2b,0x0f88975,0x33c6ed9,0x20d64d3,0x06fe799,0x0989bff,
-        0x1409262,0x085a90c,0x0d97990,0x0142eed },
-      { 0x17ec63e,0x06471b9,0x0db2378,0x1006077,0x265422c,0x08db83d,
-        0x28099b0,0x1270d06,0x11801fe,0x00ac400 },
-      0 },
-    /* 69 */
-    { { 0x3391593,0x22d7166,0x30fcfc6,0x2896609,0x3c385f5,0x066b72e,
-        0x04f3aad,0x2b831c5,0x19983fb,0x0375562 },
-      { 0x0b82ff4,0x222e39d,0x34c993b,0x101c79c,0x2d2e03c,0x0f00c8a,
-        0x3a9eaf4,0x1810669,0x151149d,0x039b931 },
-      0 },
-    /* 70 */
-    { { 0x29af288,0x1956ec7,0x293155f,0x193deb6,0x1647e1a,0x2ca0839,
-        0x297e4bc,0x15bfd0d,0x1b107ed,0x0147803 },
-      { 0x31c327e,0x05a6e1d,0x02ad43d,0x02d2a5b,0x129cdb2,0x37ad1de,
-        0x3d51f53,0x245df01,0x2414982,0x0388bd0 },
-      0 },
-    /* 71 */
-    { { 0x35f1abb,0x17a3d18,0x0874cd4,0x2d5a14e,0x17edc0c,0x16a00d3,
-        0x072c1fb,0x1232725,0x33d52dc,0x03dc24d },
-      { 0x0af30d6,0x259aeea,0x369c401,0x12bc4de,0x295bf5f,0x0d8711f,
-        0x26162a9,0x16c44e5,0x288e727,0x02f54b4 },
-      0 },
-    /* 72 */
-    { { 0x05fa877,0x1571ea7,0x3d48ab1,0x1c9f4e8,0x017dad6,0x0f46276,
-        0x343f9e7,0x1de990f,0x0e4c8aa,0x028343e },
-      { 0x094f92d,0x3abf633,0x1b3a0bb,0x2f83137,0x0d818c8,0x20bae85,
-        0x0c65f8b,0x1a8008b,0x0c7946d,0x0295b1e },
-      0 },
-    /* 73 */
-    { { 0x1d09529,0x08e46c3,0x1fcf296,0x298f6b7,0x1803e0e,0x2d6fd20,
-        0x37351f5,0x0d9e8b1,0x1f8731a,0x0362fbf },
-      { 0x00157f4,0x06750bf,0x2650ab9,0x35ffb23,0x2f51cae,0x0b522c2,
-        0x39cb400,0x191e337,0x0a5ce9f,0x021529a },
-      0 },
-    /* 74 */
-    { { 0x3506ea5,0x17d9ed8,0x0d66dc3,0x22693f8,0x19286c4,0x3a57353,
-        0x101d3bf,0x1aa54fc,0x20b9884,0x0172b3a },
-      { 0x0eac44d,0x37d8327,0x1c3aa90,0x3d0d534,0x23db29a,0x3576eaf,
-        0x1d3de8a,0x3bea423,0x11235e4,0x039260b },
-      0 },
-    /* 75 */
-    { { 0x34cd55e,0x01288b0,0x1132231,0x2cc9a03,0x358695b,0x3e87650,
-        0x345afa1,0x01267ec,0x3f616b2,0x02011ad },
-      { 0x0e7d098,0x0d6078e,0x0b70b53,0x237d1bc,0x0d7f61e,0x132de31,
-        0x1ea9ea4,0x2bd54c3,0x27b9082,0x03ac5f2 },
-      0 },
-    /* 76 */
-    { { 0x2a145b9,0x06d661d,0x31ec175,0x03f06f1,0x3a5cf6b,0x249c56e,
-        0x2035653,0x384c74f,0x0bafab5,0x0025ec0 },
-      { 0x25f69e1,0x1b23a55,0x1199aa6,0x16ad6f9,0x077e8f7,0x293f661,
-        0x33ba11d,0x3327980,0x07bafdb,0x03e571d },
-      0 },
-    /* 77 */
-    { { 0x2bae45e,0x3c074ef,0x2955558,0x3c312f1,0x2a8ebe9,0x2f193f1,
-        0x3705b1d,0x360deba,0x01e566e,0x00d4498 },
-      { 0x21161cd,0x1bc787e,0x2f87933,0x3553197,0x1328ab8,0x093c879,
-        0x17eee27,0x2adad1d,0x1236068,0x003be5c },
-      0 },
-    /* 78 */
-    { { 0x0ca4226,0x2633dd5,0x2c8e025,0x0e3e190,0x05eede1,0x1a385e4,
-        0x163f744,0x2f25522,0x1333b4f,0x03f05b6 },
-      { 0x3c800ca,0x1becc79,0x2daabe9,0x0c499e2,0x1138063,0x3fcfa2d,
-        0x2244976,0x1e85cf5,0x2f1b95d,0x0053292 },
-      0 },
-    /* 79 */
-    { { 0x12f81d5,0x1dc6eaf,0x11967a4,0x1a407df,0x31a5f9d,0x2b67241,
-        0x18bef7c,0x08c7762,0x063f59c,0x01015ec },
-      { 0x1c05c0a,0x360bfa2,0x1f85bff,0x1bc7703,0x3e4911c,0x0d685b6,
-        0x2fccaea,0x02c4cef,0x164f133,0x0070ed7 },
-      0 },
-    /* 80 */
-    { { 0x0ec21fe,0x052ffa0,0x3e825fe,0x1ab0956,0x3f6ce11,0x3d29759,
-        0x3c5a072,0x18ebe62,0x148db7e,0x03eb49c },
-      { 0x1ab05b3,0x02dab0a,0x1ae690c,0x0f13894,0x137a9a8,0x0aab79f,
-        0x3dc875c,0x06a1029,0x1e39f0e,0x01dce1f },
-      0 },
-    /* 81 */
-    { { 0x16c0dd7,0x3b31269,0x2c741e9,0x3611821,0x2a5cffc,0x1416bb3,
-        0x3a1408f,0x311fa3d,0x1c0bef0,0x02cdee1 },
-      { 0x00e6a8f,0x1adb933,0x0f23359,0x2fdace2,0x2fd6d4b,0x0e73bd3,
-        0x2453fac,0x0a356ae,0x2c8f9f6,0x02704d6 },
-      0 },
-    /* 82 */
-    { { 0x0e35743,0x28c80a1,0x0def32a,0x2c6168f,0x1320d6a,0x37c6606,
-        0x21b1761,0x2147ee0,0x21fc433,0x015c84d },
-      { 0x1fc9168,0x36cda9c,0x003c1f0,0x1cd7971,0x15f98ba,0x1ef363d,
-        0x0ca87e3,0x046f7d9,0x3c9e6bb,0x0372eb0 },
-      0 },
-    /* 83 */
-    { { 0x118cbe2,0x3665a11,0x304ef01,0x062727a,0x3d242fc,0x11ffbaf,
-        0x3663c7e,0x1a189c9,0x09e2d62,0x02e3072 },
-      { 0x0e1d569,0x162f772,0x0cd051a,0x322df62,0x3563809,0x047cc7a,
-        0x027fd9f,0x08b509b,0x3da2f94,0x01748ee },
-      0 },
-    /* 84 */
-    { { 0x1c8f8be,0x31ca525,0x22bf0a1,0x200efcd,0x02961c4,0x3d8f52b,
-        0x018403d,0x3a40279,0x1cb91ec,0x030427e },
-      { 0x0945705,0x0257416,0x05c0c2d,0x25b77ae,0x3b9083d,0x2901126,
-        0x292b8d7,0x07b8611,0x04f2eee,0x026f0cd },
-      0 },
-    /* 85 */
-    { { 0x2913074,0x2b8d590,0x02b10d5,0x09d2295,0x255491b,0x0c41cca,
-        0x1ca665b,0x133051a,0x1525f1a,0x00a5647 },
-      { 0x04f983f,0x3d6daee,0x04e1e76,0x1067d7e,0x1be7eef,0x02ea862,
-        0x00d4968,0x0ccb048,0x11f18ef,0x018dd95 },
-      0 },
-    /* 86 */
-    { { 0x22976cc,0x17c5395,0x2c38bda,0x3983bc4,0x222bca3,0x332a614,
-        0x3a30646,0x261eaef,0x1c808e2,0x02f6de7 },
-      { 0x306a772,0x32d7272,0x2dcefd2,0x2abf94d,0x038f475,0x30ad76e,
-        0x23e0227,0x3052b0a,0x001add3,0x023ba18 },
-      0 },
-    /* 87 */
-    { { 0x0ade873,0x25a6069,0x248ccbe,0x13713ee,0x17ee9aa,0x28152e9,
-        0x2e28995,0x2a92cb3,0x17a6f77,0x024b947 },
-      { 0x190a34d,0x2ebea1c,0x1ed1948,0x16fdaf4,0x0d698f7,0x32bc451,
-        0x0ee6e30,0x2aaab40,0x06f0a56,0x01460be },
-      0 },
-    /* 88 */
-    { { 0x24cc99c,0x1884b1e,0x1ca1fba,0x1a0f9b6,0x2ff609b,0x2b26316,
-        0x3b27cb5,0x29bc976,0x35d4073,0x024772a },
-      { 0x3575a70,0x1b30f57,0x07fa01b,0x0e5be36,0x20cb361,0x26605cd,
-        0x1d4e8c8,0x13cac59,0x2db9797,0x005e833 },
-      0 },
-    /* 89 */
-    { { 0x36c8d3a,0x1878a81,0x124b388,0x0e4843e,0x1701aad,0x0ea0d76,
-        0x10eae41,0x37d0653,0x36c7f4c,0x00ba338 },
-      { 0x37a862b,0x1cf6ac0,0x08fa912,0x2dd8393,0x101ba9b,0x0eebcb7,
-        0x2453883,0x1a3cfe5,0x2cb34f6,0x03d3331 },
-      0 },
-    /* 90 */
-    { { 0x1f79687,0x3d4973c,0x281544e,0x2564bbe,0x17c5954,0x171e34a,
-        0x231741a,0x3cf2784,0x0889a0d,0x02b036d },
-      { 0x301747f,0x3f1c477,0x1f1386b,0x163bc5f,0x1592b93,0x332daed,
-        0x080e4f5,0x1d28b96,0x26194c9,0x0256992 },
-      0 },
-    /* 91 */
-    { { 0x15a4c93,0x07bf6b0,0x114172c,0x1ce0961,0x140269b,0x1b2c2eb,
-        0x0dfb1c1,0x019ddaa,0x0ba2921,0x008c795 },
-      { 0x2e6d2dc,0x37e45e2,0x2918a70,0x0fce444,0x34d6aa6,0x396dc88,
-        0x27726b5,0x0c787d8,0x032d8a7,0x02ac2f8 },
-      0 },
-    /* 92 */
-    { { 0x1131f2d,0x2b43a63,0x3101097,0x38cec13,0x0637f09,0x17a69d2,
-        0x086196d,0x299e46b,0x0802cf6,0x03c6f32 },
-      { 0x0daacb4,0x1a4503a,0x100925c,0x15583d9,0x23c4e40,0x1de4de9,
-        0x1cc8fc4,0x2c9c564,0x0695aeb,0x02145a5 },
-      0 },
-    /* 93 */
-    { { 0x1dcf593,0x17050fc,0x3e3bde3,0x0a6c062,0x178202b,0x2f7674f,
-        0x0dadc29,0x15763a7,0x1d2daad,0x023d9f6 },
-      { 0x081ea5f,0x045959d,0x190c841,0x3a78d31,0x0e7d2dd,0x1414fea,
-        0x1d43f40,0x22d77ff,0x2b9c072,0x03e115c },
-      0 },
-    /* 94 */
-    { { 0x3af71c9,0x29e9c65,0x25655e1,0x111e9cd,0x3a14494,0x3875418,
-        0x34ae070,0x0b06686,0x310616b,0x03b7b89 },
-      { 0x1734121,0x00d3d44,0x29f0b2f,0x1552897,0x31cac6e,0x1030bb3,
-        0x0148f3a,0x35fd237,0x29b44eb,0x027f49f },
-      0 },
-    /* 95 */
-    { { 0x2e2cb16,0x1d962bd,0x19b63cc,0x0b3f964,0x3e3eb7d,0x1a35560,
-        0x0c58161,0x3ce1d6a,0x3b6958f,0x029030b },
-      { 0x2dcc158,0x3b1583f,0x30568c9,0x31957c8,0x27ad804,0x28c1f84,
-        0x3967049,0x37b3f64,0x3b87dc6,0x0266f26 },
-      0 },
-    /* 96 */
-    { { 0x27dafc6,0x2548764,0x0d1984a,0x1a57027,0x252c1fb,0x24d9b77,
-        0x1581a0f,0x1f99276,0x10ba16d,0x026af88 },
-      { 0x0915220,0x2be1292,0x16c6480,0x1a93760,0x2fa7317,0x1a07296,
-        0x1539871,0x112c31f,0x25787f3,0x01e2070 },
-      0 },
-    /* 97 */
-    { { 0x0bcf3ff,0x266d478,0x34f6933,0x31449fd,0x00d02cb,0x340765a,
-        0x3465a2d,0x225023e,0x319a30e,0x00579b8 },
-      { 0x20e05f4,0x35b834f,0x0404646,0x3710d62,0x3fad7bd,0x13e1434,
-        0x21c7d1c,0x1cb3af9,0x2cf1911,0x003957e },
-      0 },
-    /* 98 */
-    { { 0x0787564,0x36601be,0x1ce67e9,0x084c7a1,0x21a3317,0x2067a35,
-        0x0158cab,0x195ddac,0x1766fe9,0x035cf42 },
-      { 0x2b7206e,0x20d0947,0x3b42424,0x03f1862,0x0a51929,0x38c2948,
-        0x0bb8595,0x2942d77,0x3748f15,0x0249428 },
-      0 },
-    /* 99 */
-    { { 0x2577410,0x3c23e2f,0x28c6caf,0x00d41de,0x0fd408a,0x30298e9,
-        0x363289e,0x2302fc7,0x082c1cc,0x01dd050 },
-      { 0x30991cd,0x103e9ba,0x029605a,0x19927f7,0x0c1ca08,0x0c93f50,
-        0x28a3c7b,0x082e4e9,0x34d12eb,0x0232c13 },
-      0 },
-    /* 100 */
-    { { 0x106171c,0x0b4155a,0x0c3fb1c,0x336c090,0x19073e9,0x2241a10,
-        0x0e6b4fd,0x0ed476e,0x1ef4712,0x039390a },
-      { 0x0ec36f4,0x3754f0e,0x2a270b8,0x007fd2d,0x0f9d2dc,0x1e6a692,
-        0x066e078,0x1954974,0x2ff3c6e,0x00def28 },
-      0 },
-    /* 101 */
-    { { 0x3562470,0x0b8f1f7,0x0ac94cd,0x28b0259,0x244f272,0x031e4ef,
-        0x2d5df98,0x2c8a9f1,0x2dc3002,0x016644f },
-      { 0x350592a,0x0e6a0d5,0x1e027a1,0x2039e0f,0x399e01d,0x2817593,
-        0x0c0375e,0x3889b3e,0x24ab013,0x010de1b },
-      0 },
-    /* 102 */
-    { { 0x256b5a6,0x0ac3b67,0x28f9ff3,0x29b67f1,0x30750d9,0x25e11a9,
-        0x15e8455,0x279ebb0,0x298b7e7,0x0218e32 },
-      { 0x2fc24b2,0x2b82582,0x28f22f5,0x2bd36b3,0x305398e,0x3b2e9e3,
-        0x365dd0a,0x29bc0ed,0x36a7b3a,0x007b374 },
-      0 },
-    /* 103 */
-    { { 0x05ff2f3,0x2b3589b,0x29785d3,0x300a1ce,0x0a2d516,0x0844355,
-        0x14c9fad,0x3ccb6b6,0x385d459,0x0361743 },
-      { 0x0b11da3,0x002e344,0x18c49f7,0x0c29e0c,0x1d2c22c,0x08237b3,
-        0x2988f49,0x0f18955,0x1c3b4ed,0x02813c6 },
-      0 },
-    /* 104 */
-    { { 0x17f93bd,0x249323b,0x11f6087,0x174e4bd,0x3cb64ac,0x086dc6b,
-        0x2e330a8,0x142c1f2,0x2ea5c09,0x024acbb },
-      { 0x1b6e235,0x3132521,0x00f085a,0x2a4a4db,0x1ab2ca4,0x0142224,
-        0x3aa6b3e,0x09db203,0x2215834,0x007b9e0 },
-      0 },
-    /* 105 */
-    { { 0x23e79f7,0x28b8039,0x1906a60,0x2cbce67,0x1f590e7,0x181f027,
-        0x21054a6,0x3854240,0x2d857a6,0x03cfcb3 },
-      { 0x10d9b55,0x1443cfc,0x2648200,0x2b36190,0x09d2fcf,0x22f439f,
-        0x231aa7e,0x3884395,0x0543da3,0x003d5a9 },
-      0 },
-    /* 106 */
-    { { 0x043e0df,0x06ffe84,0x3e6d5b2,0x3327001,0x26c74b6,0x12a145e,
-        0x256ec0d,0x3898c69,0x3411969,0x02f63c5 },
-      { 0x2b7494a,0x2eee1af,0x38388a9,0x1bd17ce,0x21567d4,0x13969e6,
-        0x3a12a7a,0x3e8277d,0x03530cc,0x00b4687 },
-      0 },
-    /* 107 */
-    { { 0x06508da,0x38e04d4,0x15a7192,0x312875e,0x3336180,0x2a6512c,
-        0x1b59497,0x2e91b37,0x25eb91f,0x02841e9 },
-      { 0x394d639,0x0747143,0x37d7e6d,0x1d62962,0x08b4af3,0x34df287,
-        0x3c5584b,0x26bc869,0x20af87a,0x0060f5d },
-      0 },
-    /* 108 */
-    { { 0x1de59a4,0x1a5c443,0x2f8729d,0x01c3a2f,0x0f1ad8d,0x3cbaf9e,
-        0x1b49634,0x35d508a,0x39dc269,0x0075105 },
-      { 0x390d30e,0x37033e0,0x110cb32,0x14c37a0,0x20a3b27,0x2f00ce6,
-        0x2f1dc52,0x34988c6,0x0c29606,0x01dc7e7 },
-      0 },
-    /* 109 */
-    { { 0x1040739,0x24f9de1,0x2939999,0x2e6009a,0x244539d,0x17e3f09,
-        0x00f6f2f,0x1c63b3d,0x2310362,0x019109e },
-      { 0x1428aa8,0x3cb61e1,0x09a84f4,0x0ffafed,0x07b7adc,0x08f406b,
-        0x1b2c6df,0x035b480,0x3496ae9,0x012766d },
-      0 },
-    /* 110 */
-    { { 0x35d1099,0x2362f10,0x1a08cc7,0x13a3a34,0x12adbcd,0x32da290,
-        0x02e2a02,0x151140b,0x01b3f60,0x0240df6 },
-      { 0x34c7b61,0x2eb09c1,0x172e7cd,0x2ad5eff,0x2fe2031,0x25b54d4,
-        0x0cec965,0x18e7187,0x26a7cc0,0x00230f7 },
-      0 },
-    /* 111 */
-    { { 0x2d552ab,0x374083d,0x01f120f,0x2601736,0x156baff,0x04d44a4,
-        0x3b7c3e9,0x1acbc1b,0x0424579,0x031a425 },
-      { 0x1231bd1,0x0eba710,0x020517b,0x21d7316,0x21eac6e,0x275a848,
-        0x0837abf,0x0eb0082,0x302cafe,0x00fe8f6 },
-      0 },
-    /* 112 */
-    { { 0x1058880,0x28f9941,0x03f2d75,0x3bd90e5,0x17da365,0x2ac9249,
-        0x07861cf,0x023fd05,0x1b0fdb8,0x031712f },
-      { 0x272b56b,0x04f8d2c,0x043a735,0x25446e4,0x1c8327e,0x221125a,
-        0x0ce37df,0x2dad7f6,0x39446c2,0x00b55b6 },
-      0 },
-    /* 113 */
-    { { 0x346ac6b,0x05e0bff,0x2425246,0x0981e8b,0x1d19f79,0x2692378,
-        0x3ea3c40,0x2e90beb,0x19de503,0x003d5af },
-      { 0x05cda49,0x353b44d,0x299d137,0x3f205bc,0x2821158,0x3ad0d00,
-        0x06a54aa,0x2d7c79f,0x39d1173,0x01000ee },
-      0 },
-    /* 114 */
-    { { 0x0803387,0x3a06268,0x14043b8,0x3d4e72f,0x1ece115,0x0a1dfc8,
-        0x17208dd,0x0be790a,0x122a07f,0x014dd95 },
-      { 0x0a4182d,0x202886a,0x1f79a49,0x1e8c867,0x0a2bbd0,0x28668b5,
-        0x0d0a2e1,0x115259d,0x3586c5d,0x01e815b },
-      0 },
-    /* 115 */
-    { { 0x18a2a47,0x2c95627,0x2773646,0x1230f7c,0x15b5829,0x2fc354e,
-        0x2c000ea,0x099d547,0x2f17a1a,0x01df520 },
-      { 0x3853948,0x06f6561,0x3feeb8a,0x2f5b3ef,0x3a6f817,0x01a0791,
-        0x2ec0578,0x2c392ad,0x12b2b38,0x0104540 },
-      0 },
-    /* 116 */
-    { { 0x1e28ced,0x0fc3d1b,0x2c473c7,0x1826c4f,0x21d5da7,0x39718e4,
-        0x38ce9e6,0x0251986,0x172fbea,0x0337c11 },
-      { 0x053c3b0,0x0f162db,0x043c1cb,0x04111ee,0x297fe3c,0x32e5e03,
-        0x2b8ae12,0x0c427ec,0x1da9738,0x03b9c0f },
-      0 },
-    /* 117 */
-    { { 0x357e43a,0x054503f,0x11b8345,0x34ec6e0,0x2d44660,0x3d0ae61,
-        0x3b5dff8,0x33884ac,0x09da162,0x00a82b6 },
-      { 0x3c277ba,0x129a51a,0x027664e,0x1530507,0x0c788c9,0x2afd89d,
-        0x1aa64cc,0x1196450,0x367ac2b,0x0358b42 },
-      0 },
-    /* 118 */
-    { { 0x0054ac4,0x1761ecb,0x378839c,0x167c9f7,0x2570058,0x0604a35,
-        0x37cbf3b,0x0909bb7,0x3f2991c,0x02ce688 },
-      { 0x0b16ae5,0x212857c,0x351b952,0x2c684db,0x30c6a05,0x09c01e0,
-        0x23c137f,0x1331475,0x092c067,0x0013b40 },
-      0 },
-    /* 119 */
-    { { 0x2e90393,0x0617466,0x24e61f4,0x0a528f5,0x03047b4,0x2153f05,
-        0x0001a69,0x30e1eb8,0x3c10177,0x0282a47 },
-      { 0x22c831e,0x28fc06b,0x3e16ff0,0x208adc9,0x0bb76ae,0x28c1d6d,
-        0x12c8a15,0x031063c,0x1889ed2,0x002133e },
-      0 },
-    /* 120 */
-    { { 0x0a6becf,0x14277bf,0x3328d98,0x201f7fe,0x12fceae,0x1de3a2e,
-        0x0a15c44,0x3ddf976,0x1b273ab,0x0355e55 },
-      { 0x1b5d4f1,0x369e78c,0x3a1c210,0x12cf3e9,0x3aa52f0,0x309f082,
-        0x112089d,0x107c753,0x24202d1,0x023853a },
-      0 },
-    /* 121 */
-    { { 0x2897042,0x140d17c,0x2c4aeed,0x07d0d00,0x18d0533,0x22f7ec8,
-        0x19c194c,0x3456323,0x2372aa4,0x0165f86 },
-      { 0x30bd68c,0x1fb06b3,0x0945032,0x372ac09,0x06d4be0,0x27f8fa1,
-        0x1c8d7ac,0x137a96e,0x236199b,0x0328fc0 },
-      0 },
-    /* 122 */
-    { { 0x170bd20,0x2842d58,0x1de7592,0x3c5b4fd,0x20ea897,0x12cab78,
-        0x363ff14,0x01f928c,0x17e309c,0x02f79ff },
-      { 0x0f5432c,0x2edb4ae,0x044b516,0x32f810d,0x2210dc1,0x23e56d6,
-        0x301e6ff,0x34660f6,0x10e0a7d,0x02d88eb },
-      0 },
-    /* 123 */
-    { { 0x0c7b65b,0x2f59d58,0x2289a75,0x2408e92,0x1ab8c55,0x1ec99e5,
-        0x220fd0d,0x04defe0,0x24658ec,0x035aa8b },
-      { 0x138bb85,0x2f002d4,0x295c10a,0x08760ce,0x28c31d1,0x1c0a8cb,
-        0x0ff00b1,0x144eac9,0x2e02dcc,0x0044598 },
-      0 },
-    /* 124 */
-    { { 0x3b42b87,0x050057b,0x0dff781,0x1c06db1,0x1bd9f5d,0x1f5f04a,
-        0x2cccd7a,0x143e19b,0x1cb94b7,0x036cfb8 },
-      { 0x34837cf,0x3cf6c3c,0x0d4fb26,0x22ee55e,0x1e7eed1,0x315995f,
-        0x2cdf937,0x1a96574,0x0425220,0x0221a99 },
-      0 },
-    /* 125 */
-    { { 0x1b569ea,0x0d33ed9,0x19c13c2,0x107dc84,0x2200111,0x0569867,
-        0x2dc85da,0x05ef22e,0x0eb018a,0x029c33d },
-      { 0x04a6a65,0x3e5eba3,0x378f224,0x09c04d0,0x036e5cf,0x3df8258,
-        0x3a609e4,0x1eddef8,0x2abd174,0x02a91dc },
-      0 },
-    /* 126 */
-    { { 0x2a60cc0,0x1d84c5e,0x115f676,0x1840da0,0x2c79163,0x2f06ed6,
-        0x198bb4b,0x3e5d37b,0x1dc30fa,0x018469b },
-      { 0x15ee47a,0x1e32f30,0x16a530e,0x2093836,0x02e8962,0x3767b62,
-        0x335adf3,0x27220db,0x2f81642,0x0173ffe },
-      0 },
-    /* 127 */
-    { { 0x37a99cd,0x1533fe6,0x05a1c0d,0x27610f1,0x17bf3b9,0x0b1ce78,
-        0x0a908f6,0x265300e,0x3237dc1,0x01b969a },
-      { 0x3a5db77,0x2d15382,0x0d63ef8,0x1feb3d8,0x0b7b880,0x19820de,
-        0x11c0c67,0x2af3396,0x38d242d,0x0120688 },
-      0 },
-    /* 128 */
-    { { 0x1d0b34a,0x05ef00d,0x00a7e34,0x1ae0c9f,0x1440b38,0x300d8b4,
-        0x37262da,0x3e50e3e,0x14ce0cd,0x00b1044 },
-      { 0x195a0b1,0x173bc6b,0x03622ba,0x2a19f55,0x1c09b37,0x07921b2,
-        0x16cdd20,0x24a5c9b,0x2bf42ff,0x00811de },
-      0 },
-    /* 129 */
-    { { 0x0d65dbf,0x145cf06,0x1ad82f7,0x038ce7b,0x077bf94,0x33c4007,
-        0x22d26bd,0x25ad9c0,0x09ac773,0x02b1990 },
-      { 0x2261cc3,0x2ecdbf1,0x3e908b0,0x3246439,0x0213f7b,0x1179b04,
-        0x01cebaa,0x0be1595,0x175cc12,0x033a39a },
-      0 },
-    /* 130 */
-    { { 0x00a67d2,0x086d06f,0x248a0f1,0x0291134,0x362d476,0x166d1cd,
-        0x044f1d6,0x2d2a038,0x365250b,0x0023f78 },
-      { 0x08bf287,0x3b0f6a1,0x1d6eace,0x20b4cda,0x2c2a621,0x0912520,
-        0x02dfdc9,0x1b35cd6,0x3d2565d,0x00bdf8b },
-      0 },
-    /* 131 */
-    { { 0x3770fa7,0x2e4b6f0,0x03f9ae4,0x170de41,0x1095e8d,0x1dd845c,
-        0x334e9d1,0x00ab953,0x12e9077,0x03196fa },
-      { 0x2fd0a40,0x228c0fd,0x384b275,0x38ef339,0x3e7d822,0x3e5d9ef,
-        0x24f5854,0x0ece9eb,0x247d119,0x012ffe3 },
-      0 },
-    /* 132 */
-    { { 0x0ff1480,0x07487c0,0x1b16cd4,0x1f41d53,0x22ab8fb,0x2f83cfa,
-        0x01d2efb,0x259f6b2,0x2e65772,0x00f9392 },
-      { 0x05303e6,0x23cdb4f,0x23977e1,0x12e4898,0x03bd999,0x0c930f0,
-        0x170e261,0x180a27b,0x2fd58ec,0x014e22b },
-      0 },
-    /* 133 */
-    { { 0x25d7713,0x0c5fad7,0x09daad1,0x3b9d779,0x109b985,0x1d3ec98,
-        0x35bc4fc,0x2f838cb,0x0d14f75,0x0173e42 },
-      { 0x2657b12,0x10d4423,0x19e6760,0x296e5bb,0x2bfd421,0x25c3330,
-        0x29f51f8,0x0338838,0x24060f0,0x029a62e },
-      0 },
-    /* 134 */
-    { { 0x3748fec,0x2c5a1bb,0x2cf973d,0x289fa74,0x3e6e755,0x38997bf,
-        0x0b6544c,0x2b6358c,0x38a7aeb,0x02c50bb },
-      { 0x3d5770a,0x06be7c5,0x012fad3,0x19cb2cd,0x266af3b,0x3ccd677,
-        0x160d1bd,0x141d5af,0x2965851,0x034625a },
-      0 },
-    /* 135 */
-    { { 0x3c41c08,0x255eacc,0x22e1ec5,0x2b151a3,0x087de94,0x311cbdb,
-        0x016b73a,0x368e462,0x20b7981,0x0099ec3 },
-      { 0x262b988,0x1539763,0x21e76e5,0x15445b4,0x1d8ddc7,0x34a9be6,
-        0x10faf03,0x24e4d18,0x07aa111,0x02d538a },
-      0 },
-    /* 136 */
-    { { 0x38a876b,0x048ad45,0x04b40a0,0x3fc2144,0x251ff96,0x13ca7dd,
-        0x0b31ab1,0x3539814,0x28b5f87,0x0212aec },
-      { 0x270790a,0x350e7e0,0x346bd5e,0x276178f,0x22d6cb5,0x3078884,
-        0x355c1b6,0x15901d7,0x3671765,0x03950db },
-      0 },
-    /* 137 */
-    { { 0x286e8d5,0x2409788,0x13be53f,0x2d21911,0x0353c95,0x10238e8,
-        0x32f5bde,0x3a67b60,0x28b5b9c,0x001013d },
-      { 0x381e8e5,0x0cef7a9,0x2f5bcad,0x06058f0,0x33cdf50,0x04672a8,
-        0x1769600,0x31c055d,0x3df0ac1,0x00e9098 },
-      0 },
-    /* 138 */
-    { { 0x2eb596d,0x197b326,0x12b4c29,0x39c08f2,0x101ea03,0x3804e58,
-        0x04b4b62,0x28d9d1c,0x13f905e,0x0032a3f },
-      { 0x11b2b61,0x08e9095,0x0d06925,0x270e43f,0x21eb7a8,0x0e4a98f,
-        0x31d2be0,0x030cf9f,0x2644ddb,0x025b728 },
-      0 },
-    /* 139 */
-    { { 0x07510af,0x2ed0e8e,0x2a01203,0x2a2a68d,0x0846fea,0x3e540de,
-        0x3a57702,0x1677348,0x2123aad,0x010d8f8 },
-      { 0x0246a47,0x0e871d0,0x124dca4,0x34b9577,0x2b362b8,0x363ebe5,
-        0x3086045,0x26313e6,0x15cd8bb,0x0210384 },
-      0 },
-    /* 140 */
-    { { 0x023e8a7,0x0817884,0x3a0bf12,0x3376371,0x3c808a8,0x18e9777,
-        0x12a2721,0x35b538a,0x2bd30de,0x017835a },
-      { 0x0fc0f64,0x1c8709f,0x2d8807a,0x0743957,0x242eec0,0x347e76c,
-        0x27bef91,0x289689a,0x0f42945,0x01f7a92 },
-      0 },
-    /* 141 */
-    { { 0x1060a81,0x3dbc739,0x1615abd,0x1cbe3e5,0x3e79f9c,0x1ab09a2,
-        0x136c540,0x05b473f,0x2beebfd,0x02af0a8 },
-      { 0x3e2eac7,0x19be474,0x04668ac,0x18f4b74,0x36f10ba,0x0a0b4c6,
-        0x10e3770,0x3bf059e,0x3946c7e,0x013a8d4 },
-      0 },
-    /* 142 */
-    { { 0x266309d,0x28be354,0x1a3eed8,0x3020651,0x10a51c6,0x1e31770,
-        0x0af45a5,0x3ff0f3b,0x2891c94,0x00e9db9 },
-      { 0x17b0d0f,0x33a291f,0x0a5f9aa,0x25a3d61,0x2963ace,0x39a5fef,
-        0x230c724,0x1919146,0x10a465e,0x02084a8 },
-      0 },
-    /* 143 */
-    { { 0x3ab8caa,0x31870f3,0x2390ef7,0x2103850,0x218eb8e,0x3a5ccf2,
-        0x1dff677,0x2c59334,0x371599c,0x02a9f2a },
-      { 0x0837bd1,0x3249cef,0x35d702f,0x3430dab,0x1c06407,0x108f692,
-        0x221292f,0x05f0c5d,0x073fe06,0x01038e0 },
-      0 },
-    /* 144 */
-    { { 0x3bf9b7c,0x2020929,0x30d0f4f,0x080fef8,0x3365d23,0x1f3e738,
-        0x3e53209,0x1549afe,0x300b305,0x038d811 },
-      { 0x0c6c2c7,0x2e6445b,0x3ee64dc,0x022e932,0x0726837,0x0deb67b,
-        0x1ed4346,0x3857f73,0x277a3de,0x01950b5 },
-      0 },
-    /* 145 */
-    { { 0x36c377a,0x0adb41e,0x08be3f3,0x11e40d1,0x36cb038,0x036a2bd,
-        0x3dd3a82,0x1bc875b,0x2ee09bb,0x02994d2 },
-      { 0x035facf,0x05e0344,0x07e630a,0x0ce772d,0x335e55a,0x111fce4,
-        0x250fe1c,0x3bc89ba,0x32fdc9a,0x03cf2d9 },
-      0 },
-    /* 146 */
-    { { 0x355fd83,0x1c67f8e,0x1d10eb3,0x1b21d77,0x0e0d7a4,0x173a9e1,
-        0x2c9fa90,0x1c39cce,0x22eaae8,0x01f2bea },
-      { 0x153b338,0x0534107,0x26c69b8,0x283be1f,0x3e0acc0,0x059cac3,
-        0x13d1081,0x148bbee,0x3c1b9bd,0x002aac4 },
-      0 },
-    /* 147 */
-    { { 0x2681297,0x3389e34,0x146addc,0x2c6d425,0x2cb350e,0x1986abc,
-        0x0431737,0x04ba4b7,0x2028470,0x012e469 },
-      { 0x2f8ddcf,0x3c4255c,0x1af4dcf,0x07a6a44,0x208ebf6,0x0dc90c3,
-        0x34360ac,0x072ad23,0x0537232,0x01254d3 },
-      0 },
-    /* 148 */
-    { { 0x07b7e9d,0x3df5c7c,0x116f83d,0x28c4f35,0x3a478ef,0x3011fb8,
-        0x2f264b6,0x317b9e3,0x04fd65a,0x032bd1b },
-      { 0x2aa8266,0x3431de4,0x04bba04,0x19a44da,0x0edf454,0x392c5ac,
-        0x265168a,0x1dc3d5b,0x25704c6,0x00533a7 },
-      0 },
-    /* 149 */
-    { { 0x25e8f91,0x1178fa5,0x2492994,0x2eb2c3c,0x0d3aca1,0x0322828,
-        0x1cc70f9,0x269c74c,0x0a53e4c,0x006edc2 },
-      { 0x18bdd7a,0x2a79a55,0x26b1d5c,0x0200628,0x0734a05,0x3273c7b,
-        0x13aa714,0x0040ac2,0x2f2da30,0x03e7449 },
-      0 },
-    /* 150 */
-    { { 0x3f9563e,0x2f29eab,0x14a0749,0x3fad264,0x1dd077a,0x3d7c59c,
-        0x3a0311b,0x331a789,0x0b9729e,0x0201ebf },
-      { 0x1b08b77,0x2a4cdf2,0x3e387f8,0x21510f1,0x286c3a7,0x1dbf62e,
-        0x3afa594,0x3363217,0x0d16568,0x01d46b7 },
-      0 },
-    /* 151 */
-    { { 0x0715c0d,0x28e2d04,0x17f78ae,0x1c63dda,0x1d113ea,0x0fefc1b,
-        0x1eab149,0x1d0fd99,0x0682537,0x00a7b11 },
-      { 0x10bebbc,0x11c672d,0x14223d9,0x2ff9141,0x1399ee5,0x34b7b6c,
-        0x0d5b3a8,0x01df643,0x0e392a4,0x03fe4dc },
-      0 },
-    /* 152 */
-    { { 0x2b75b65,0x0b5a6f1,0x11c559a,0x3549999,0x24188f8,0x37a75f4,
-        0x29f33e3,0x34068a2,0x38ba2a9,0x025dd91 },
-      { 0x29af2c7,0x0988b64,0x0923885,0x1b539a4,0x1334f5d,0x226947a,
-        0x2cc7e5a,0x20beb39,0x13fac2f,0x01d298c },
-      0 },
-    /* 153 */
-    { { 0x35f079c,0x137f76d,0x2fbbb2f,0x254638d,0x185b07c,0x1f34db7,
-        0x2cfcf0e,0x218f46d,0x2150ff4,0x02add6f },
-      { 0x33fc9b7,0x0d9f005,0x0fd081b,0x0834965,0x2b90a74,0x102448d,
-        0x3dbf03c,0x167d857,0x02e0b44,0x013afab },
-      0 },
-    /* 154 */
-    { { 0x09f2c53,0x317f9d7,0x1411eb6,0x0463aba,0x0d25220,0x256b176,
-        0x087633f,0x2bff322,0x07b2c1b,0x037e662 },
-      { 0x10aaecb,0x23bb4a1,0x2272bb7,0x06c075a,0x09d4918,0x0736f2b,
-        0x0dd511b,0x101625e,0x0a7779f,0x009ec10 },
-      0 },
-    /* 155 */
-    { { 0x33b2eb2,0x0176dfd,0x2118904,0x022386c,0x2e0df85,0x2588c9f,
-        0x1b71525,0x28fd540,0x137e4cf,0x02ce4f7 },
-      { 0x3d75165,0x0c39ecf,0x3554a12,0x30af34c,0x2d66344,0x3ded408,
-        0x36f1be0,0x0d065b0,0x012d046,0x0025623 },
-      0 },
-    /* 156 */
-    { { 0x2601c3b,0x1824fc0,0x335fe08,0x3e33d70,0x0fb0252,0x252bfca,
-        0x1cf2808,0x1922e55,0x1a9db9f,0x020721e },
-      { 0x2f56c51,0x39a1f31,0x218c040,0x1a4fc5d,0x3fed471,0x0164d4e,
-        0x388a419,0x06f1113,0x0f55fc1,0x03e8352 },
-      0 },
-    /* 157 */
-    { { 0x1608e4d,0x3872778,0x022cbc6,0x044d60a,0x3010dda,0x15fb0b5,
-        0x37ddc11,0x19f5bda,0x156b6a3,0x023a838 },
-      { 0x383b3b4,0x1380bc8,0x353ca35,0x250fc07,0x169966b,0x3780f29,
-        0x36632b2,0x2d6b13f,0x124fa00,0x00fd6ae },
-      0 },
-    /* 158 */
-    { { 0x1739efb,0x2ec3656,0x2c0d337,0x3d39faf,0x1c751b0,0x04699f4,
-        0x252dd64,0x095b8b6,0x0872b74,0x022f1da },
-      { 0x2d3d253,0x38edca0,0x379fa5b,0x287d635,0x3a9f679,0x059d9ee,
-        0x0ac168e,0x3cd3e87,0x19060fc,0x02ce1bc },
-      0 },
-    /* 159 */
-    { { 0x3edcfc2,0x0f04d4b,0x2f0d31f,0x1898be2,0x25396bf,0x15ca230,
-        0x02b4eae,0x2713668,0x0f71b06,0x0132d18 },
-      { 0x38095ea,0x1ed34d6,0x3603ae6,0x165bf01,0x192bbf8,0x1852859,
-        0x075f66b,0x1488f85,0x10895ef,0x014b035 },
-      0 },
-    /* 160 */
-    { { 0x1339848,0x3084385,0x0c8d231,0x3a1c1de,0x0e87a28,0x255b85c,
-        0x1de6616,0x2702e74,0x1382bb0,0x012b0f2 },
-      { 0x198987d,0x381545a,0x34d619b,0x312b827,0x18b2376,0x28fe4cf,
-        0x20b7651,0x017d077,0x0c7e397,0x00e0365 },
-      0 },
-    /* 161 */
-    { { 0x1542e75,0x0d56aa0,0x39b701a,0x287b806,0x396c724,0x0935c21,
-        0x3a29776,0x0debdac,0x171de26,0x00b38f8 },
-      { 0x1d5bc1a,0x3fad27d,0x22b5cfe,0x1f89ddf,0x0a65560,0x144dd5b,
-        0x2aac2f9,0x139353f,0x0520b62,0x00b9b36 },
-      0 },
-    /* 162 */
-    { { 0x031c31d,0x16552e3,0x1a0c368,0x0016fc8,0x168533d,0x171e7b2,
-        0x17626e7,0x275502f,0x14742c6,0x03285dd },
-      { 0x2d2dbb2,0x3b6bffd,0x1d18cc6,0x2f45d2a,0x0fd0d8c,0x2915e3a,
-        0x1e8793a,0x0b39a1d,0x3139cab,0x02a5da9 },
-      0 },
-    /* 163 */
-    { { 0x3fb353d,0x147c6e4,0x3a720a6,0x22d5ff3,0x1d75cab,0x06c54a0,
-        0x08cfa73,0x12666aa,0x3170a1f,0x021c829 },
-      { 0x13e1b90,0x3a34dda,0x1fc38c3,0x02c5bdb,0x2d345dc,0x14aa1d0,
-        0x28d00ab,0x224f23a,0x329c769,0x025c67b },
-      0 },
-    /* 164 */
-    { { 0x0e35909,0x3bb6356,0x0116820,0x370cf77,0x29366d8,0x3881409,
-        0x3999d06,0x013075f,0x176e157,0x02941ca },
-      { 0x0e70b2e,0x28dfab1,0x2a8a002,0x15da242,0x084dcf6,0x116ca97,
-        0x31bf186,0x1dc9735,0x09df7b7,0x0264e27 },
-      0 },
-    /* 165 */
-    { { 0x2da7a4b,0x3023c9e,0x1366238,0x00ff4e2,0x03abe9d,0x19bd44b,
-        0x272e897,0x20b91ad,0x2aa202c,0x02a2201 },
-      { 0x380184e,0x08112b4,0x0b85660,0x31049aa,0x3a8cb78,0x36113c5,
-        0x1670c0a,0x373f9e7,0x3fb4738,0x00010ef },
-      0 },
-    /* 166 */
-    { { 0x2d5192e,0x26d770d,0x32af8d5,0x34d1642,0x1acf885,0x05805e0,
-        0x166d0a1,0x1219a0d,0x301ba6c,0x014bcfb },
-      { 0x2dcb64d,0x19cca83,0x379f398,0x08e01a0,0x10a482c,0x0103cc2,
-        0x0be5fa7,0x1f9d45b,0x1899ef2,0x00ca5af },
-      0 },
-    /* 167 */
-    { { 0x14d81d7,0x2aea251,0x1b3c476,0x3bd47ae,0x29eade7,0x0715e61,
-        0x1a21cd8,0x1c7a586,0x2bfaee5,0x00ee43f },
-      { 0x096f7cb,0x0c08f95,0x1bc4939,0x361fed4,0x255be41,0x26fad73,
-        0x31dd489,0x02c600f,0x29d9f81,0x01ba201 },
-      0 },
-    /* 168 */
-    { { 0x03ea1db,0x1eac46d,0x1292ce3,0x2a54967,0x20a7ff1,0x3e13c61,
-        0x1b02218,0x2b44e14,0x3eadefa,0x029c88a },
-      { 0x30a9144,0x31e3b0a,0x19c5a2a,0x147cbe9,0x05a0240,0x051f38e,
-        0x11eca56,0x31a4247,0x123bc2a,0x02fa535 },
-      0 },
-    /* 169 */
-    { { 0x3226ce7,0x1251782,0x0b7072f,0x11e59fa,0x2b8afd7,0x169b18f,
-        0x2a46f18,0x31d9bb7,0x2fe9be8,0x01de0b7 },
-      { 0x1b38626,0x34aa90f,0x3ad1760,0x21ddbd9,0x3460ae7,0x1126736,
-        0x1b86fc5,0x0b92cd0,0x167a289,0x000e0e1 },
-      0 },
-    /* 170 */
-    { { 0x1ec1a0f,0x36bbf5e,0x1c972d8,0x3f73ace,0x13bbcd6,0x23d86a5,
-        0x175ffc5,0x2d083d5,0x2c4adf7,0x036f661 },
-      { 0x1f39eb7,0x2a20505,0x176c81a,0x3d6e636,0x16ee2fc,0x3cbdc5f,
-        0x25475dc,0x2ef4151,0x3c46860,0x0238934 },
-      0 },
-    /* 171 */
-    { { 0x2587390,0x3639526,0x0588749,0x13c32fb,0x212bb19,0x09660f1,
-        0x207da4b,0x2bf211b,0x1c4407b,0x01506a6 },
-      { 0x24c8842,0x105a498,0x05ffdb2,0x0ab61b0,0x26044c1,0x3dff3d8,
-        0x1d14b44,0x0d74716,0x049f57d,0x030024b },
-      0 },
-    /* 172 */
-    { { 0x32e61ef,0x31d70f7,0x35cad3c,0x320b86c,0x07e8841,0x027ca7d,
-        0x2d30d19,0x2513718,0x2347286,0x01d7901 },
-      { 0x3c237d0,0x107f16e,0x01c9e7d,0x3c3b13c,0x0c9537b,0x20af54d,
-        0x051a162,0x2161a47,0x258c784,0x016df2d },
-      0 },
-    /* 173 */
-    { { 0x228ead1,0x29c2122,0x07f6964,0x023f4ed,0x1802dc5,0x19f96ce,
-        0x24bfd17,0x25e866b,0x2ba8df0,0x01eb84f },
-      { 0x2dd384e,0x05bbe3a,0x3f06fd2,0x366dacb,0x30361a2,0x2f36d7c,
-        0x0b98784,0x38ff481,0x074e2a8,0x01e1f60 },
-      0 },
-    /* 174 */
-    { { 0x17fbb1c,0x0975add,0x1debc5e,0x2cb2880,0x3e47bdd,0x3488cff,
-        0x15e9a36,0x2121129,0x0199ef2,0x017088a },
-      { 0x0315250,0x352a162,0x17c1773,0x0ae09c2,0x321b21a,0x3bd74cf,
-        0x3c4ea1d,0x3cac2ad,0x3abbaf0,0x039174d },
-      0 },
-    /* 175 */
-    { { 0x0511c8a,0x3c78d0a,0x2cd3d2d,0x322f729,0x3ebb229,0x09f0e69,
-        0x0a71a76,0x2e74d5e,0x12284df,0x03b5ef0 },
-      { 0x3dea561,0x0a9b7e4,0x0ed1cf2,0x237523c,0x05443f1,0x2eb48fa,
-        0x3861405,0x1b49f62,0x0c945ca,0x02ab25f },
-      0 },
-    /* 176 */
-    { { 0x16bd00a,0x13a9d28,0x3cc1eb5,0x2b7d702,0x2d839e9,0x3e6ff01,
-        0x2bb7f11,0x3713824,0x3b31163,0x00c63e5 },
-      { 0x30d7138,0x0316fb0,0x0220ecc,0x08eaf0c,0x244e8df,0x0088d81,
-        0x37972fb,0x3fd34ae,0x2a19a84,0x03e907e },
-      0 },
-    /* 177 */
-    { { 0x2642269,0x0b65d29,0x03bd440,0x33a6ede,0x3c81814,0x2507982,
-        0x0d38e47,0x3a788e6,0x32c1d26,0x00e2eda },
-      { 0x2577f87,0x392895a,0x3e1cc64,0x14f7047,0x08b52d2,0x08a01ca,
-        0x336abf6,0x00697fc,0x105ce76,0x0253742 },
-      0 },
-    /* 178 */
-    { { 0x293f92a,0x33df737,0x3315156,0x32e26d7,0x0a01333,0x26579d4,
-        0x004df9c,0x0aba409,0x067d25c,0x02481de },
-      { 0x3f39d44,0x1c78042,0x13d7e24,0x0825aed,0x35f2c90,0x3270f63,
-        0x04b7b35,0x3ad4531,0x28bd29b,0x0207a10 },
-      0 },
-    /* 179 */
-    { { 0x077199f,0x270aeb1,0x0dd96dd,0x3b9ad7b,0x28cb8ee,0x3903f43,
-        0x37db3fe,0x292c62b,0x362dbbf,0x006e52a },
-      { 0x247f143,0x0362cf3,0x216344f,0x3f18fd1,0x351e623,0x31664e0,
-        0x0f270fc,0x243bbc6,0x2280555,0x001a8e3 },
-      0 },
-    /* 180 */
-    { { 0x3355b49,0x2c04e6c,0x399b2e5,0x182d3af,0x020e265,0x09a7cf7,
-        0x0ffa6bd,0x353e302,0x02083d9,0x029ecdb },
-      { 0x33e8830,0x0570e86,0x1c0b64d,0x386a27e,0x0d5fcea,0x0b45a4c,
-        0x2ee4a2e,0x0a8833f,0x2b4a282,0x02f9531 },
-      0 },
-    /* 181 */
-    { { 0x191167c,0x36cf7e3,0x225ed6c,0x1e79e99,0x0517c3f,0x11ab1fd,
-        0x05648f3,0x08aedc4,0x1abeae0,0x02fcc29 },
-      { 0x3828a68,0x1e16fa4,0x30368e7,0x0c9fcfb,0x25161c3,0x24851ac,
-        0x1b5feb5,0x344eb84,0x0de2732,0x0347208 },
-      0 },
-    /* 182 */
-    { { 0x038b363,0x384d1e4,0x2519043,0x151ac17,0x158c11f,0x009b2b4,
-        0x257abe6,0x2368d3f,0x3ed68a1,0x02df45e },
-      { 0x29c2559,0x2962478,0x3d8444c,0x1d96fff,0x04f7a03,0x1391a52,
-        0x0de4af7,0x3319126,0x15e6412,0x00e65ff },
-      0 },
-    /* 183 */
-    { { 0x3d61507,0x1d1a0a2,0x0d2af20,0x354d299,0x329e132,0x2a28578,
-        0x2ddfb08,0x04fa3ff,0x1293c6c,0x003bae2 },
-      { 0x3e259f8,0x1a68fa9,0x3e67e9b,0x39b44f9,0x1ce1db7,0x347e9a1,
-        0x3318f6a,0x2dbbc9d,0x2f8c922,0x008a245 },
-      0 },
-    /* 184 */
-    { { 0x212ab5b,0x2b896c2,0x0136959,0x07e55ef,0x0cc1117,0x05b8ac3,
-        0x18429ed,0x025fa01,0x11d6e93,0x03b016b },
-      { 0x03f3708,0x2e96fab,0x1d77157,0x0d4c2d6,0x131baf9,0x0608d39,
-        0x3552371,0x06cdd1e,0x1567ff1,0x01f4c50 },
-      0 },
-    /* 185 */
-    { { 0x2dfefab,0x270173d,0x37077bd,0x1a372cd,0x1be2f22,0x28e2ee5,
-        0x3ead973,0x35e8f94,0x2fc9bc1,0x03a7399 },
-      { 0x36a02a1,0x2855d9b,0x00ed75a,0x37d8398,0x138c087,0x233706e,
-        0x147f346,0x01947e2,0x3017228,0x0365942 },
-      0 },
-    /* 186 */
-    { { 0x2057e60,0x2d31296,0x25e4504,0x2fa37bc,0x1cbccc3,0x1f0732f,
-        0x3532081,0x2de8a98,0x19a804e,0x005359a },
-      { 0x31f411a,0x2a10576,0x369c2c8,0x02fe035,0x109fbaf,0x30bddeb,
-        0x1eef901,0x1662ad3,0x0410d43,0x01bd31a },
-      0 },
-    /* 187 */
-    { { 0x2c24a96,0x1b7d3a5,0x19a3872,0x217f2f6,0x2534dbc,0x2cab8c2,
-        0x066ef28,0x26aecf1,0x0fd6118,0x01310d4 },
-      { 0x055b8da,0x1fdc5be,0x38a1296,0x25118f0,0x341a423,0x2ba4cd0,
-        0x3e1413e,0x062d70d,0x2425a31,0x029c9b4 },
-      0 },
-    /* 188 */
-    { { 0x08c1086,0x1acfba5,0x22e1dae,0x0f72f4e,0x3f1de50,0x0f408bc,
-        0x35ed3f0,0x3ce48fc,0x282cc6c,0x004d8e7 },
-      { 0x1afaa86,0x24e3ef3,0x22589ac,0x3ec9952,0x1f45bc5,0x14144ca,
-        0x23b26e4,0x0d68c65,0x1e1c1a3,0x032a4d9 },
-      0 },
-    /* 189 */
-    { { 0x03b2d20,0x16b1d53,0x241b361,0x05e4138,0x1742a54,0x32741c7,
-        0x0521c4c,0x1ca96c2,0x034970b,0x02738a7 },
-      { 0x13e0ad6,0x207dcdb,0x034c8cc,0x27bcbe1,0x18060da,0x33a18b6,
-        0x2d1d1a6,0x2be60d7,0x3d7ab42,0x012312a },
-      0 },
-    /* 190 */
-    { { 0x0c7485a,0x06c3310,0x0dbfd22,0x2ef949d,0x0ead455,0x098f4ba,
-        0x3c76989,0x0cf2d24,0x032f67b,0x01e005f },
-      { 0x30cb5ee,0x0d5da64,0x0ed2b9d,0x2503102,0x1c0d14e,0x1cbc693,
-        0x37bf552,0x07013e2,0x054de5c,0x014f341 },
-      0 },
-    /* 191 */
-    { { 0x128ccac,0x1617e97,0x346ebcd,0x158016d,0x25f823e,0x34048ea,
-        0x39f0a1c,0x3ea3df1,0x1c1d3d7,0x03ba919 },
-      { 0x151803b,0x01967c1,0x2f70781,0x27df39a,0x06c0b59,0x24a239c,
-        0x15a7702,0x2464d06,0x2a47ae6,0x006db90 },
-      0 },
-    /* 192 */
-    { { 0x27d04c3,0x024df3d,0x38112e8,0x38a27ba,0x01e312b,0x0965358,
-        0x35d8879,0x2f4f55a,0x214187f,0x0008936 },
-      { 0x05fe36f,0x2ee18c3,0x1f5f87a,0x1813bd4,0x0580f3c,0x0ed0a7b,
-        0x0fb1bfb,0x3fcce59,0x2f042bf,0x01820e3 },
-      0 },
-    /* 193 */
-    { { 0x20bbe99,0x32cbc9f,0x39ee432,0x3cc12a8,0x37bda44,0x3ea4e40,
-        0x097c7a9,0x0590d7d,0x2022d33,0x018dbac },
-      { 0x3ae00aa,0x3439864,0x2d2ffcf,0x3f8c6b9,0x0875a00,0x3e4e407,
-        0x3658a29,0x22eb3d0,0x2b63921,0x022113b },
-      0 },
-    /* 194 */
-    { { 0x33bae58,0x05c749a,0x1f3e114,0x1c45f8e,0x27db3df,0x06a3ab6,
-        0x37bc7f8,0x1e27b34,0x3dc51fb,0x009eea0 },
-      { 0x3f54de5,0x3d0e7fe,0x1a71a7d,0x02ed7f8,0x0727703,0x2ca5e92,
-        0x2e8e35d,0x292ad0b,0x13487f3,0x02b6d8b },
-      0 },
-    /* 195 */
-    { { 0x175df2a,0x05a28a8,0x32e99b1,0x13d8630,0x2082aa0,0x11ac245,
-        0x24f2e71,0x322cb27,0x17675e7,0x02e643f },
-      { 0x1f37313,0x2765ad3,0x0789082,0x1e742d0,0x11c2055,0x2021dc4,
-        0x09ae4a7,0x346359b,0x2f94d10,0x0205c1f },
-      0 },
-    /* 196 */
-    { { 0x3d6ff96,0x1f2ac80,0x336097d,0x3f03610,0x35b851b,0x010b6d2,
-        0x0823c4d,0x2a9709a,0x2ead5a8,0x00de4b6 },
-      { 0x01afa0b,0x0621965,0x3671528,0x1050b60,0x3f3e9e7,0x2f93829,
-        0x0825275,0x006e85f,0x35e94b0,0x016af58 },
-      0 },
-    /* 197 */
-    { { 0x2c4927c,0x3ea1382,0x0f23727,0x0d69f23,0x3e38860,0x2b72837,
-        0x3cd5ea4,0x2d84292,0x321846a,0x016656f },
-      { 0x29dfa33,0x3e182e0,0x018be90,0x2ba563f,0x2caafe2,0x218c0d9,
-        0x3baf447,0x1047a6c,0x0a2d483,0x01130cb },
-      0 },
-    /* 198 */
-    { { 0x00ed80c,0x2a5fc79,0x0a82a74,0x2c4c74b,0x15f938c,0x30b5ab6,
-        0x32124b7,0x295314f,0x2fb8082,0x007c858 },
-      { 0x20b173e,0x19f315c,0x12f97e4,0x198217c,0x040e8a6,0x3275977,
-        0x2bc20e4,0x01f2633,0x02bc3e9,0x023c750 },
-      0 },
-    /* 199 */
-    { { 0x3c4058a,0x24be73e,0x16704f5,0x2d8a4bd,0x3b15e14,0x3076315,
-        0x1cfe37b,0x36fe715,0x343926e,0x02c6603 },
-      { 0x2c76b09,0x0cf824c,0x3f7898c,0x274cec1,0x11df527,0x18eed18,
-        0x08ead48,0x23915bc,0x19b3744,0x00a0a2b },
-      0 },
-    /* 200 */
-    { { 0x0cf4ac5,0x1c8b131,0x0afb696,0x0ff7799,0x2f5ac1a,0x022420c,
-        0x11baa2e,0x2ce4015,0x1275a14,0x0125cfc },
-      { 0x22eac5d,0x360cd4c,0x3568e59,0x3d42f66,0x35e07ee,0x09620e4,
-        0x36720fa,0x22b1eac,0x2d0db16,0x01b6b23 },
-      0 },
-    /* 201 */
-    { { 0x1a835ef,0x1516bbb,0x2d51f7b,0x3487443,0x14aa113,0x0dd06c2,
-        0x1a65e01,0x379300d,0x35920b9,0x012c8fb },
-      { 0x04c7341,0x2eda00f,0x3c37e82,0x1b4fd62,0x0d45770,0x1478fba,
-        0x127863a,0x26939cd,0x134ddf4,0x01375c5 },
-      0 },
-    /* 202 */
-    { { 0x1476cd9,0x1119ca5,0x325bbf9,0x0bf8c69,0x0648d07,0x312d9f8,
-        0x01c8b8f,0x136ec51,0x0002f4a,0x03f4c5c },
-      { 0x195d0e1,0x10ffd22,0x29aa1cb,0x3443bdc,0x276e695,0x05e6260,
-        0x15f9764,0x3cd9783,0x18c9569,0x0053eb1 },
-      0 },
-    /* 203 */
-    { { 0x312ae18,0x280197c,0x3fc9ad9,0x303f324,0x251958d,0x29f4a11,
-        0x2142408,0x3694366,0x25136ab,0x03b5f1d },
-      { 0x1d4abbc,0x1c3c689,0x13ea462,0x3cfc684,0x39b5dd8,0x2d4654b,
-        0x09b0755,0x27d4f18,0x3f74d2e,0x03fbf2d },
-      0 },
-    /* 204 */
-    { { 0x2119185,0x2525eae,0x1ba4bd0,0x0c2ab11,0x1d54e8c,0x294845e,
-        0x2479dea,0x3602d24,0x17e87e0,0x0060069 },
-      { 0x0afffb0,0x34fe37f,0x1240073,0x02eb895,0x06cf33c,0x2d7f7ef,
-        0x1d763b5,0x04191e0,0x11e1ead,0x027e3f0 },
-      0 },
-    /* 205 */
-    { { 0x269544c,0x0e85c57,0x3813158,0x19fc12d,0x20eaf85,0x1e2930c,
-        0x22a8fd2,0x1a6a478,0x09d3d3a,0x02a74e0 },
-      { 0x1a2da3b,0x30b0b16,0x0847936,0x3d86257,0x138ccbc,0x0f5421a,
-        0x25244e6,0x23bdd79,0x1aee117,0x00c01ae },
-      0 },
-    /* 206 */
-    { { 0x1eead28,0x07cac32,0x1fbc0bb,0x17627d3,0x17eef63,0x0b3a24e,
-        0x0757fdb,0x3dd841d,0x3d745f8,0x002ae17 },
-      { 0x25b4549,0x29f24cf,0x2f21ecd,0x1725e48,0x04be2bb,0x10ee010,
-        0x1a1274b,0x10b0898,0x27511e9,0x02c48b5 },
-      0 },
-    /* 207 */
-    { { 0x2a5ae7a,0x181ef99,0x0be33be,0x3e9dab7,0x101e703,0x3adb971,
-        0x1043014,0x2ebb2be,0x1c1097d,0x027d667 },
-      { 0x3f250ed,0x16dc603,0x20dc6d7,0x1d0d268,0x38eb915,0x02c89e8,
-        0x1605a41,0x12de109,0x0e08a29,0x01f554a },
-      0 },
-    /* 208 */
-    { { 0x0c26def,0x163d988,0x2d1ef0f,0x3a960ac,0x1025585,0x0738e20,
-        0x27d79b0,0x05cc3ef,0x201303f,0x00a333a },
-      { 0x1644ba5,0x2af345e,0x30b8d1d,0x3a01bff,0x31fc643,0x1acf85e,
-        0x0a76fc6,0x04efe98,0x348a1d0,0x03062eb },
-      0 },
-    /* 209 */
-    { { 0x1c4216d,0x18e3217,0x02ac34e,0x19c8185,0x200c010,0x17d4192,
-        0x13a1719,0x165af51,0x09db7a9,0x0277be0 },
-      { 0x3ab8d2c,0x2190b99,0x22b641e,0x0cd88de,0x3b42404,0x1310862,
-        0x106a6d6,0x23395f5,0x0b06880,0x000d5fe },
-      0 },
-    /* 210 */
-    { { 0x0d2cc88,0x36f9913,0x339d8e9,0x237c2e3,0x0cc61c2,0x34c2832,
-        0x309874c,0x2621d28,0x2dd1b48,0x0392806 },
-      { 0x17cd8f9,0x07bab3d,0x0c482ed,0x0faf565,0x31b767d,0x2f4bde1,
-        0x295c717,0x330c29c,0x179ce10,0x0119b5f },
-      0 },
-    /* 211 */
-    { { 0x1ada2c7,0x0c624a7,0x227d47d,0x30e3e6a,0x14fa0a6,0x0829678,
-        0x24fd288,0x2b46a43,0x122451e,0x0319ca9 },
-      { 0x186b655,0x01f3217,0x0af1306,0x0efe6b5,0x2f0235d,0x1c45ca9,
-        0x2086805,0x1d44e66,0x0faf2a6,0x0178f59 },
-      0 },
-    /* 212 */
-    { { 0x33b4416,0x10431e6,0x2d99aa6,0x217aac9,0x0cd8fcf,0x2d95a9d,
-        0x3ff74ad,0x10bf17a,0x295eb8e,0x01b229e },
-      { 0x02a63bd,0x182e9ec,0x004710c,0x00e2e3c,0x06b2f23,0x04b642c,
-        0x2c37383,0x32a4631,0x022ad82,0x00d22b9 },
-      0 },
-    /* 213 */
-    { { 0x0cda2fb,0x1d198d7,0x26d27f4,0x286381c,0x022acca,0x24ac7c8,
-        0x2df7824,0x0b4ba16,0x1e0d9ef,0x03041d3 },
-      { 0x29a65b3,0x0f3912b,0x151bfcf,0x2b0175c,0x0fd71e4,0x39aa5e2,
-        0x311f50c,0x13ff351,0x3dbc9e5,0x03eeb7e },
-      0 },
-    /* 214 */
-    { { 0x0a99363,0x0fc7348,0x2775171,0x23db3c8,0x2b91565,0x134d66c,
-        0x0175cd2,0x1bf365a,0x2b48371,0x02dfe5d },
-      { 0x16dbf74,0x2389357,0x2f36575,0x3f5c70e,0x38d23ba,0x090f7f8,
-        0x3477600,0x3201523,0x32ecafc,0x03d3506 },
-      0 },
-    /* 215 */
-    { { 0x1abd48d,0x073ca3f,0x38a451f,0x0d8cb01,0x1ce81be,0x05c51ba,
-        0x0e29741,0x03c41ab,0x0eae016,0x0060209 },
-      { 0x2e58358,0x1da62d9,0x2358038,0x14b39b2,0x1635687,0x39079b1,
-        0x380e345,0x1b49608,0x23983cf,0x019f97d },
-      0 },
-    /* 216 */
-    { { 0x34899ef,0x332e373,0x04c0f89,0x3c27aed,0x1949015,0x09663b2,
-        0x2f9276b,0x07f1951,0x09a04c1,0x027fbde },
-      { 0x3d2a071,0x19fb3d4,0x1b096d3,0x1fe9146,0x3b10e1a,0x0478bbb,
-        0x2b3fb06,0x1388329,0x181a99c,0x02f2030 },
-      0 },
-    /* 217 */
-    { { 0x1eb82e6,0x14dbe39,0x3920972,0x31fd5b2,0x21a484f,0x02d7697,
-        0x0e21715,0x37c431e,0x2629f8c,0x01249c3 },
-      { 0x26b50ad,0x26deefa,0x0ffc1a3,0x30688e2,0x39a0284,0x041c65e,
-        0x03eb178,0x0bdfd50,0x2f96137,0x034bb94 },
-      0 },
-    /* 218 */
-    { { 0x0e0362a,0x334a162,0x194dd37,0x29e3e97,0x2442fa8,0x10d2949,
-        0x3836e5a,0x2dccebf,0x0bee5ab,0x037ed1e },
-      { 0x33eede6,0x3c739d9,0x2f04a91,0x350ad6c,0x3a5390a,0x14c368b,
-        0x26f7bf5,0x11ce979,0x0b408df,0x0366850 },
-      0 },
-    /* 219 */
-    { { 0x28ea498,0x0886d5b,0x2e090e0,0x0a4d58f,0x2623478,0x0d74ab7,
-        0x2b83913,0x12c6b81,0x18d623f,0x01d8301 },
-      { 0x198aa79,0x26d6330,0x3a7f0b8,0x34bc1ea,0x2f74890,0x378955a,
-        0x204110f,0x0102538,0x02d8f19,0x01c5066 },
-      0 },
-    /* 220 */
-    { { 0x14b0f45,0x2838cd3,0x14e16f0,0x0e0e4aa,0x2d9280b,0x0f18757,
-        0x3324c6b,0x1391ceb,0x1ce89d5,0x00ebe74 },
-      { 0x0930371,0x3de6048,0x3097fd8,0x1308705,0x3eda266,0x3108c26,
-        0x1545dcd,0x1f7583a,0x1c37395,0x02c7e05 },
-      0 },
-    /* 221 */
-    { { 0x1fec44a,0x2a9e3a2,0x0caf84f,0x11cf2a9,0x0c8c2ae,0x06da989,
-        0x1c807dc,0x3c149a4,0x1141543,0x02906bb },
-      { 0x15ffe04,0x0d4e65f,0x2e20424,0x37d896d,0x18bacb2,0x1e05ddd,
-        0x1660be8,0x183be17,0x1dd86fb,0x035ba70 },
-      0 },
-    /* 222 */
-    { { 0x2853264,0x0ba5fb1,0x0a0b3aa,0x2df88c1,0x2771533,0x23aba6f,
-        0x112bb7b,0x3e3086e,0x210ae9b,0x027271b },
-      { 0x030b74c,0x0269678,0x1e90a23,0x135a98c,0x24ed749,0x126de7c,
-        0x344b23a,0x186da27,0x19640fa,0x0159af5 },
-      0 },
-    /* 223 */
-    { { 0x18061f3,0x3004630,0x3c70066,0x34df20f,0x1190b25,0x1c9cc91,
-        0x1fc8e02,0x0d17bc1,0x390f525,0x033cb1c },
-      { 0x0eb30cf,0x2f3ad04,0x303aa09,0x2e835dd,0x1cfd2eb,0x143fc95,
-        0x02c43a1,0x025e7a1,0x3558aa2,0x000bd45 },
-      0 },
-    /* 224 */
-    { { 0x1db7d07,0x3bde52b,0x1500396,0x1089115,0x20b4fc7,0x1e2a8f3,
-        0x3f8eacc,0x365f7eb,0x1a5e8d4,0x0053a6b },
-      { 0x37079e2,0x120284b,0x000edaa,0x33792c2,0x145baa3,0x20e055f,
-        0x365e2d7,0x26ba005,0x3ab8e9d,0x0282b53 },
-      0 },
-    /* 225 */
-    { { 0x2653618,0x2dd8852,0x2a5f0bf,0x0f0c7aa,0x2187281,0x1252757,
-        0x13e7374,0x3b47855,0x0b86e56,0x02f354c },
-      { 0x2e9c47b,0x2fa14cc,0x19ab169,0x3fad401,0x0dc2776,0x24afeed,
-        0x3a97611,0x0d07736,0x3cf6979,0x02424a0 },
-      0 },
-    /* 226 */
-    { { 0x2e81a13,0x000c91d,0x123967b,0x265885c,0x29bee1a,0x0cb8675,
-        0x2d361bd,0x1526823,0x3c9ace1,0x00d7bad },
-      { 0x24e5bdc,0x02b969f,0x2c6e128,0x34edb3b,0x12dcd2c,0x3899af0,
-        0x24224c6,0x3a1914b,0x0f4448a,0x026a2cb },
-      0 },
-    /* 227 */
-    { { 0x1d03b59,0x1c6fc82,0x32abf64,0x28ed96b,0x1c90e62,0x2f57bb2,
-        0x3ff168e,0x04de7fd,0x0f4d449,0x01af6d8 },
-      { 0x255bc30,0x2bfaf22,0x3fe0dad,0x0584025,0x1c79ead,0x3078ef7,
-        0x2197414,0x022a50b,0x0fd94ba,0x0007b0f },
-      0 },
-    /* 228 */
-    { { 0x09485c2,0x09dfaf7,0x10c7ba6,0x1e48bec,0x248cc9a,0x028a362,
-        0x21d60f7,0x193d93d,0x1c04754,0x0346b2c },
-      { 0x2f36612,0x240ac49,0x0d8bd26,0x13b8186,0x259c3a4,0x020d5fb,
-        0x38a8133,0x09b0937,0x39d4056,0x01f7341 },
-      0 },
-    /* 229 */
-    { { 0x05a4b48,0x1f534fc,0x07725ce,0x148dc8c,0x2adcd29,0x04aa456,
-        0x0f79718,0x066e346,0x189377d,0x002fd4d },
-      { 0x068ea73,0x336569b,0x184d35e,0x32a08e9,0x3c7f3bb,0x11ce9c8,
-        0x3674c6f,0x21bf27e,0x0d9e166,0x034a2f9 },
-      0 },
-    /* 230 */
-    { { 0x0fa8e4b,0x2e6418e,0x18fc5d2,0x1ba24ff,0x0559f18,0x0dbedbf,
-        0x2de2aa4,0x22338e9,0x3aa510f,0x035d801 },
-      { 0x23a4988,0x02aad94,0x02732d1,0x111d374,0x0b455cf,0x0d01c9e,
-        0x067082a,0x2ec05fd,0x368b303,0x03cad4b },
-      0 },
-    /* 231 */
-    { { 0x035b4ca,0x1fabea6,0x1cbc0d5,0x3f2ed9a,0x02d2232,0x1990c66,
-        0x2eb680c,0x3b4ea3b,0x18ecc5a,0x03636fa },
-      { 0x1a02709,0x26f8ff1,0x1fa8cba,0x397d6e8,0x230be68,0x043aa14,
-        0x3d43cdf,0x25c17fa,0x3a3ee55,0x0380564 },
-      0 },
-    /* 232 */
-    { { 0x275a0a6,0x16bd43a,0x0033d3e,0x2b15e16,0x2512226,0x005d901,
-        0x26d50fd,0x3bc19bf,0x3b1aeb8,0x02bfb01 },
-      { 0x0bb0a31,0x26559e0,0x1aae7fb,0x330dcc2,0x16f1af3,0x06afce2,
-        0x13a15a0,0x2ff7645,0x3546e2d,0x029c6e4 },
-      0 },
-    /* 233 */
-    { { 0x0f593d2,0x384b806,0x122bbf8,0x0a281e0,0x1d1a904,0x2e93cab,
-        0x0505db0,0x08f6454,0x05c6285,0x014e880 },
-      { 0x3f2b935,0x22d8e79,0x161a07c,0x16b060a,0x02bff97,0x146328b,
-        0x3ceea77,0x238f61a,0x19b3d58,0x02fd1f4 },
-      0 },
-    /* 234 */
-    { { 0x17665d5,0x259e9f7,0x0de5672,0x15cbcbd,0x34e3030,0x035240f,
-        0x0005ae8,0x286d851,0x07f39c9,0x000070b },
-      { 0x1efc6d6,0x2a0051a,0x2724143,0x2a9ef1e,0x0c810bd,0x1e05429,
-        0x25670ba,0x2e66d7d,0x0e786ff,0x03f6b7e },
-      0 },
-    /* 235 */
-    { { 0x3c00785,0x232e23f,0x2b67fd3,0x244ed23,0x077fa75,0x3cda3ef,
-        0x14d055b,0x0f25011,0x24d5aa4,0x00ea0e3 },
-      { 0x297bb9a,0x198ca4f,0x14d9561,0x18d1076,0x39eb933,0x2b6caa0,
-        0x1591a60,0x0768d45,0x257873e,0x00f36e0 },
-      0 },
-    /* 236 */
-    { { 0x1e77eab,0x0502a5f,0x0109137,0x0350592,0x3f7e1c5,0x3ac7437,
-        0x2dcad2c,0x1fee9d8,0x089f1f5,0x0169833 },
-      { 0x0d45673,0x0d8e090,0x065580b,0x065644f,0x11b82be,0x3592dd0,
-        0x3284b8d,0x23f0015,0x16fdbfd,0x0248bfd },
-      0 },
-    /* 237 */
-    { { 0x1a129a1,0x1977bb2,0x0e041b2,0x15f30a1,0x0a5b1ce,0x3afef8f,
-        0x380c46c,0x3358810,0x27df6c5,0x01ca466 },
-      { 0x3b90f9a,0x3d14ea3,0x031b298,0x02e2390,0x2d719c0,0x25bc615,
-        0x2c0e777,0x0226b8c,0x3803624,0x0179e45 },
-      0 },
-    /* 238 */
-    { { 0x363cdfb,0x1bb155f,0x24fd5c1,0x1c7c72b,0x28e6a35,0x18165f2,
-        0x226bea5,0x0beaff3,0x371e24c,0x0138294 },
-      { 0x1765357,0x29034e9,0x22b4276,0x11035ce,0x23c89af,0x074468c,
-        0x3370ae4,0x013bae3,0x018d566,0x03d7fde },
-      0 },
-    /* 239 */
-    { { 0x209df21,0x0f8ff86,0x0e47fbf,0x23b99ba,0x126d5d2,0x2722405,
-        0x16bd0a2,0x1799082,0x0e9533f,0x039077c },
-      { 0x3ba9e3f,0x3f6902c,0x1895305,0x3ac9813,0x3f2340c,0x3c0d9f1,
-        0x26e1927,0x0557c21,0x16eac4f,0x023b75f },
-      0 },
-    /* 240 */
-    { { 0x3fc8ff3,0x0770382,0x342fc9a,0x0afa4db,0x314efd8,0x328e07b,
-        0x016f7cc,0x3ba599c,0x1caed8a,0x0050cb0 },
-      { 0x0b23c26,0x2120a5c,0x3273ec6,0x1cc1cd6,0x2a64fe8,0x2bbc3d6,
-        0x09f6e5e,0x34b1b8e,0x00b5ac8,0x032bbd2 },
-      0 },
-    /* 241 */
-    { { 0x1315922,0x1725e1d,0x0ca5524,0x1c4c18f,0x3d82951,0x193bcb2,
-        0x0e60d0b,0x388dbcf,0x37e8efa,0x0342e85 },
-      { 0x1b3af60,0x26ba3ec,0x220e53a,0x394f4b6,0x01a796a,0x3e7bbca,
-        0x163605d,0x2b85807,0x17c1c54,0x03cc725 },
-      0 },
-    /* 242 */
-    { { 0x1cc4597,0x1635492,0x2028c0f,0x2c2eb82,0x2dc5015,0x0d2a052,
-        0x05fc557,0x1f0ebbf,0x0cb96e1,0x0004d01 },
-      { 0x1a824bf,0x3896172,0x2ed7b29,0x178007a,0x0d59318,0x07bda2b,
-        0x2ee6826,0x0f9b235,0x04b9193,0x01bcddf },
-      0 },
-    /* 243 */
-    { { 0x0333fd2,0x0eeb46a,0x15b89f9,0x00968aa,0x2a89302,0x2bdd6b3,
-        0x1e5037e,0x2541884,0x24ed2d0,0x01b6e8f },
-      { 0x04399cd,0x3be6334,0x3adea48,0x1bb9adc,0x31811c6,0x05fb2bc,
-        0x360752c,0x3d29dcb,0x3423bec,0x03c4f3c },
-      0 },
-    /* 244 */
-    { { 0x119e2eb,0x2e7b02a,0x0f68cee,0x257d8b0,0x183a9a1,0x2ae88a6,
-        0x3a3bb67,0x2eb4f3e,0x1a9274b,0x0320fea },
-      { 0x2fa1ce0,0x346c2d8,0x2fbf0d7,0x3d4d063,0x0e58b60,0x09c1bc1,
-        0x28ef9e5,0x09a0efe,0x0f45d70,0x02d275c },
-      0 },
-    /* 245 */
-    { { 0x2d5513b,0x31d443e,0x1e2d914,0x3b2c5d4,0x105f32e,0x27ee756,
-        0x050418d,0x3c73db6,0x1bb0c30,0x01673eb },
-      { 0x1cb7fd6,0x1eb08d5,0x26a3e16,0x2e20810,0x0249367,0x029e219,
-        0x2ec58c9,0x12d9fab,0x362354a,0x016eafc },
-      0 },
-    /* 246 */
-    { { 0x2424865,0x260747b,0x177f37c,0x1e3cb95,0x08b0028,0x2783016,
-        0x2970f1b,0x323c1c0,0x2a79026,0x0186231 },
-      { 0x0f244da,0x26866f4,0x087306f,0x173ec20,0x31ecced,0x3c84d8d,
-        0x070f9b9,0x2e764d5,0x075df50,0x0264ff9 },
-      0 },
-    /* 247 */
-    { { 0x32c3609,0x0c737e6,0x14ea68e,0x300b11b,0x184eb19,0x29dd440,
-        0x09ec1a9,0x185adeb,0x0664c80,0x0207dd9 },
-      { 0x1fbe978,0x30a969d,0x33561d7,0x34fc60e,0x36743fe,0x00774af,
-        0x0d1f045,0x018360e,0x12a5fe9,0x01592a0 },
-      0 },
-    /* 248 */
-    { { 0x2817d1d,0x2993d3e,0x2e0f7a5,0x112faa0,0x255f968,0x355fe6a,
-        0x3f5a0fc,0x075b2d7,0x3cf00e5,0x0089afc },
-      { 0x32833cf,0x06a7e4b,0x09a8d6d,0x1693d3e,0x320a0a3,0x3cfdfdd,
-        0x136c498,0x1e0d845,0x347ff25,0x01a1de7 },
-      0 },
-    /* 249 */
-    { { 0x3043d08,0x030705c,0x20fa79b,0x1d07f00,0x0a54467,0x29b49b4,
-        0x367e289,0x0b82f4d,0x0d1eb09,0x025ef2c },
-      { 0x32ed3c3,0x1baaa3c,0x3c482ab,0x146ca06,0x3c8a4f1,0x3e85e3c,
-        0x1bf4f3b,0x1195534,0x3e80a78,0x02a1cbf },
-      0 },
-    /* 250 */
-    { { 0x32b2086,0x2de4d68,0x3486b1a,0x03a0583,0x2e1eb71,0x2dab9af,
-        0x10cd913,0x28daa6f,0x3fcb732,0x000a04a },
-      { 0x3605318,0x3f5f2b3,0x2d1da63,0x143f7f5,0x1646e5d,0x040b586,
-        0x1683982,0x25abe87,0x0c9fe53,0x001ce47 },
-      0 },
-    /* 251 */
-    { { 0x380d02b,0x055fc22,0x3f7fc50,0x3458a1d,0x26b8333,0x23550ab,
-        0x0a1af87,0x0a821eb,0x2dc7e6d,0x00d574a },
-      { 0x07386e1,0x3ccd68a,0x3275b41,0x253e390,0x2fd272a,0x1e6627a,
-        0x2ca2cde,0x0e9e4a1,0x1e37c2a,0x00f70ac },
-      0 },
-    /* 252 */
-    { { 0x0581352,0x2748701,0x02bed68,0x094dd9e,0x30a00c8,0x3fb5c07,
-        0x3bd5909,0x211ac80,0x1103ccd,0x0311e1a },
-      { 0x0c768ed,0x29dc209,0x36575db,0x009a107,0x272feea,0x2b33383,
-        0x313ed56,0x134c9cc,0x168d5bb,0x033310a },
-      0 },
-    /* 253 */
-    { { 0x17620b9,0x143784f,0x256a94e,0x229664a,0x1d89a5c,0x1d521f2,
-        0x0076406,0x1c73f70,0x342aa48,0x03851fa },
-      { 0x0f3ae46,0x2ad3bab,0x0fbe274,0x3ed40d4,0x2fd4936,0x232103a,
-        0x2afe474,0x25b8f7c,0x047080e,0x008e6b0 },
-      0 },
-    /* 254 */
-    { { 0x3fee8d4,0x347cd4a,0x0fec481,0x33fe9ec,0x0ce80b5,0x33a6bcf,
-        0x1c4c9e2,0x3967441,0x1a3f5f7,0x03157e8 },
-      { 0x257c227,0x1bc53a0,0x200b318,0x0fcd0af,0x2c5b165,0x2a413ec,
-        0x2fc998a,0x2da6426,0x19cd4f4,0x0025336 },
-      0 },
-    /* 255 */
-    { { 0x303beba,0x2072135,0x32918a9,0x140cb3a,0x08631d1,0x0ef527b,
-        0x05f2c9e,0x2b4ce91,0x0b642ab,0x02e428c },
-      { 0x0a5abf9,0x15013ed,0x3603b46,0x30dd76d,0x3004750,0x28d7627,
-        0x1a42ccc,0x093ddbe,0x39a1b79,0x00067e2 },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_10(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#endif
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[10];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 10, km);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_10(point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_10(point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_10(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN)
-/* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a  Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
-static int sp_256_iszero_10(const sp_digit* a)
-{
-    return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
-            a[8] | a[9]) == 0;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */
-/* Add 1 to a. (a = a + 1)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_add_one_10(sp_digit* a)
-{
-    a[0]++;
-    sp_256_norm_10(a);
-}
-
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 18) {
-            r[j] &= 0x3ffffff;
-            s = 26 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Generates a scalar that is in the range 1..order-1.
- *
- * rng  Random number generator.
- * k    Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-static int sp_256_ecc_gen_k_10(WC_RNG* rng, sp_digit* k)
-{
-    int err;
-    byte buf[32];
-
-    do {
-        err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
-        if (err == 0) {
-            sp_256_from_bin(k, 10, buf, sizeof(buf));
-            if (sp_256_cmp_10(k, p256_order2) < 0) {
-                sp_256_add_one_10(k);
-                break;
-            }
-        }
-    }
-    while (err == 0);
-
-    return err;
-}
-
-/* Makes a random EC key pair.
- *
- * rng   Random number generator.
- * priv  Generated private value.
- * pub   Generated public point.
- * heap  Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[10];
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point inf;
-#endif
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point* infinity;
-#endif
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, inf, infinity);
-#endif
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_ecc_gen_k_10(rng, k);
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_10(point, k, 1, NULL);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL);
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            err = sp_256_ecc_mulmod_avx2_10(infinity, point, p256_order, 1,
-                                                                          NULL);
-        }
-        else
-#endif
-            err = sp_256_ecc_mulmod_10(infinity, point, p256_order, 1, NULL);
-    }
-    if (err == MP_OKAY) {
-        if (!sp_256_iszero_10(point->x) || !sp_256_iszero_10(point->y))
-            err = ECC_INF_E;
-    }
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(k, priv);
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_10(point, pub);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_ecc_point_free(infinity, 1, heap);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-
-#ifdef HAVE_ECC_DHE
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 32
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_256_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<9; i++) {
-        r[i+1] += r[i] >> 26;
-        r[i] &= 0x3ffffff;
-    }
-    j = 256 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<10 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 26) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 26);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv    Scalar to multiply the point by.
- * pub     Point to multiply.
- * out     Buffer to hold X ordinate.
- * outLen  On entry, size of the buffer in bytes.
- *         On exit, length of data in buffer in bytes.
- * heap    Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outLen, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[10];
-#endif
-    sp_point* point = NULL;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 32)
-        err = BUFFER_E;
-
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 10, priv);
-        sp_256_point_from_ecc_point_10(point, pub);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_10(point, point, k, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_10(point, point, k, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        sp_256_to_bin(point->x, out);
-        *outLen = 32;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_DHE */
-
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef HAVE_INTEL_AVX2
-#endif /* HAVE_INTEL_AVX2 */
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int64_t tb = b;
-    int64_t t = 0;
-    int i;
-
-    for (i = 0; i < 10; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x3ffffff;
-        t >>= 26;
-    }
-    r[10] = (sp_digit)t;
-#else
-    int64_t tb = b;
-    int64_t t[10];
-
-    t[ 0] = tb * a[ 0];
-    t[ 1] = tb * a[ 1];
-    t[ 2] = tb * a[ 2];
-    t[ 3] = tb * a[ 3];
-    t[ 4] = tb * a[ 4];
-    t[ 5] = tb * a[ 5];
-    t[ 6] = tb * a[ 6];
-    t[ 7] = tb * a[ 7];
-    t[ 8] = tb * a[ 8];
-    t[ 9] = tb * a[ 9];
-    r[ 0] =                           (t[ 0] & 0x3ffffff);
-    r[ 1] = (sp_digit)(t[ 0] >> 26) + (t[ 1] & 0x3ffffff);
-    r[ 2] = (sp_digit)(t[ 1] >> 26) + (t[ 2] & 0x3ffffff);
-    r[ 3] = (sp_digit)(t[ 2] >> 26) + (t[ 3] & 0x3ffffff);
-    r[ 4] = (sp_digit)(t[ 3] >> 26) + (t[ 4] & 0x3ffffff);
-    r[ 5] = (sp_digit)(t[ 4] >> 26) + (t[ 5] & 0x3ffffff);
-    r[ 6] = (sp_digit)(t[ 5] >> 26) + (t[ 6] & 0x3ffffff);
-    r[ 7] = (sp_digit)(t[ 6] >> 26) + (t[ 7] & 0x3ffffff);
-    r[ 8] = (sp_digit)(t[ 7] >> 26) + (t[ 8] & 0x3ffffff);
-    r[ 9] = (sp_digit)(t[ 8] >> 26) + (t[ 9] & 0x3ffffff);
-    r[10] = (sp_digit)(t[ 9] >> 26);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_256_div_10(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int64_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[20], t2d[10 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 10;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[9];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 10);
-        for (i=9; i>=0; i--) {
-            t1[10 + i] += t1[10 + i - 1] >> 26;
-            t1[10 + i - 1] &= 0x3ffffff;
-            d1 = t1[10 + i];
-            d1 <<= 26;
-            d1 += t1[10 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_256_mul_d_10(t2, d, r1);
-            sp_256_sub_10(&t1[i], &t1[i], t2);
-            t1[10 + i] -= t2[10];
-            t1[10 + i] += t1[10 + i - 1] >> 26;
-            t1[10 + i - 1] &= 0x3ffffff;
-            r1 = (((-t1[10 + i]) << 26) - t1[10 + i - 1]) / div;
-            r1++;
-            sp_256_mul_d_10(t2, d, r1);
-            sp_256_add_10(&t1[i], &t1[i], t2);
-            t1[10 + i] += t1[10 + i - 1] >> 26;
-            t1[10 + i - 1] &= 0x3ffffff;
-        }
-        t1[10 - 1] += t1[10 - 2] >> 26;
-        t1[10 - 2] &= 0x3ffffff;
-        d1 = t1[10 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_256_mul_d_10(t2, d, r1);
-        sp_256_sub_10(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 10);
-        for (i=0; i<8; i++) {
-            r[i+1] += r[i] >> 26;
-            r[i] &= 0x3ffffff;
-        }
-        sp_256_cond_add_10(r, r, d, 0 - (r[9] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_256_mod_10(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_256_div_10(a, m, NULL, r);
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Order-2 for the P256 curve. */
-static const uint32_t p256_order_2[8] = {
-    0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff,
-    0x00000000,0xffffffff
-};
-#else
-/* The low half of the order-2 of the P256 curve. */
-static const uint32_t p256_order_low[4] = {
-    0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad
-};
-#endif /* WOLFSSL_SP_SMALL */
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_10(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_10(r, a, b);
-    sp_256_mont_reduce_10(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_10(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_10(r, a);
-    sp_256_mont_reduce_10(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_10(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_10(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_10(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_10(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 10);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_10(t, t);
-        if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_10(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 10);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 10;
-    sp_digit* t3 = td + 4 * 10;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_10(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_10(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_10(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_10(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_10(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_10(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_10(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_10(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_10(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_10(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_10(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_10(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_10(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_10(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_10(t2, t2, 4);
-    sp_256_mont_mul_order_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_10(t2, t2, 4);
-    sp_256_mont_mul_order_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_10(t2, t2, 4);
-    sp_256_mont_mul_order_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_10(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_10(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_avx2_10(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_avx2_10(r, a, b);
-    sp_256_mont_reduce_avx2_10(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_avx2_10(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_avx2_10(r, a);
-    sp_256_mont_reduce_avx2_10(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_avx2_10(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_avx2_10(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_avx2_10(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_avx2_10(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 10);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_10(t, t);
-        if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_10(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 10);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 10;
-    sp_digit* t3 = td + 4 * 10;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_avx2_10(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_avx2_10(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_avx2_10(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_avx2_10(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_avx2_10(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_10(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_10(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_10(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_avx2_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_avx2_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_avx2_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_10(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_10(t2, t2);
-        if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32)))
-            sp_256_mont_mul_order_avx2_10(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_avx2_10(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_avx2_10(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
-#ifdef HAVE_ECC_SIGN
-#ifndef SP_ECC_MAX_SIG_GEN
-#define SP_ECC_MAX_SIG_GEN  64
-#endif
-
-/* Sign the hash using the private key.
- *   e = [hash, 256 bits] from binary
- *   r = (k.G)->x mod order
- *   s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit ed[2*10];
-    sp_digit xd[2*10];
-    sp_digit kd[2*10];
-    sp_digit rd[2*10];
-    sp_digit td[3 * 2*10];
-    sp_point p;
-#endif
-    sp_digit* e = NULL;
-    sp_digit* x = NULL;
-    sp_digit* k = NULL;
-    sp_digit* r = NULL;
-    sp_digit* tmp = NULL;
-    sp_point* point = NULL;
-    sp_digit carry;
-    sp_digit* s;
-    sp_digit* kInv;
-    int err = MP_OKAY;
-    int32_t c;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            e = d + 0 * 10;
-            x = d + 2 * 10;
-            k = d + 4 * 10;
-            r = d + 6 * 10;
-            tmp = d + 8 * 10;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    e = ed;
-    x = xd;
-    k = kd;
-    r = rd;
-    tmp = td;
-#endif
-    s = e;
-    kInv = k;
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(e, 10, hash, hashLen);
-        sp_256_from_mp(x, 10, priv);
-    }
-
-    for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
-        /* New random point. */
-        err = sp_256_ecc_gen_k_10(rng, k);
-        if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                err = sp_256_ecc_mulmod_base_avx2_10(point, k, 1, heap);
-            else
-#endif
-                err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL);
-        }
-
-        if (err == MP_OKAY) {
-            /* r = point->x mod order */
-            XMEMCPY(r, point->x, sizeof(sp_digit) * 10);
-            sp_256_norm_10(r);
-            c = sp_256_cmp_10(r, p256_order);
-            sp_256_cond_sub_10(r, r, p256_order, 0 - (c >= 0));
-            sp_256_norm_10(r);
-
-            /* Conv k to Montgomery form (mod order) */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_10(k, k, p256_norm_order);
-            else
-#endif
-                sp_256_mul_10(k, k, p256_norm_order);
-            err = sp_256_mod_10(k, k, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_10(k);
-            /* kInv = 1/k mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_inv_order_avx2_10(kInv, k, tmp);
-            else
-#endif
-                sp_256_mont_inv_order_10(kInv, k, tmp);
-            sp_256_norm_10(kInv);
-
-            /* s = r * x + e */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_10(x, x, r);
-            else
-#endif
-                sp_256_mul_10(x, x, r);
-            err = sp_256_mod_10(x, x, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_10(x);
-            carry = sp_256_add_10(s, e, x);
-            sp_256_cond_sub_10(s, s, p256_order, 0 - carry);
-            sp_256_norm_10(s);
-            c = sp_256_cmp_10(s, p256_order);
-            sp_256_cond_sub_10(s, s, p256_order, 0 - (c >= 0));
-            sp_256_norm_10(s);
-
-            /* s = s * k^-1 mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_mul_order_avx2_10(s, s, kInv);
-            else
-#endif
-                sp_256_mont_mul_order_10(s, s, kInv);
-            sp_256_norm_10(s);
-
-            /* Check that signature is usable. */
-            if (!sp_256_iszero_10(s))
-                break;
-        }
-    }
-
-    if (i == 0)
-        err = RNG_FAILURE_E;
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(r, rm);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(s, sm);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 8 * 10);
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    XMEMSET(e, 0, sizeof(sp_digit) * 2 * 10);
-    XMEMSET(x, 0, sizeof(sp_digit) * 2 * 10);
-    XMEMSET(k, 0, sizeof(sp_digit) * 2 * 10);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10);
-    XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*10);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-/* Verify the signature values with the hash and public key.
- *   e = Truncate(hash, 256)
- *   u1 = e/s mod order
- *   u2 = r/s mod order
- *   r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- *   (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- *   (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
-    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit u1d[2*10];
-    sp_digit u2d[2*10];
-    sp_digit sd[2*10];
-    sp_digit tmpd[2*10 * 5];
-    sp_point p1d;
-    sp_point p2d;
-#endif
-    sp_digit* u1;
-    sp_digit* u2;
-    sp_digit* s;
-    sp_digit* tmp;
-    sp_point* p1;
-    sp_point* p2 = NULL;
-    sp_digit carry;
-    int32_t c;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p1d, p1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p2d, p2);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 16 * 10, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            u1  = d + 0 * 10;
-            u2  = d + 2 * 10;
-            s   = d + 4 * 10;
-            tmp = d + 6 * 10;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    u1 = u1d;
-    u2 = u2d;
-    s  = sd;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(u1, 10, hash, hashLen);
-        sp_256_from_mp(u2, 10, r);
-        sp_256_from_mp(s, 10, sm);
-        sp_256_from_mp(p2->x, 10, pX);
-        sp_256_from_mp(p2->y, 10, pY);
-        sp_256_from_mp(p2->z, 10, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_avx2_10(s, s, p256_norm_order);
-        else
-#endif
-            sp_256_mul_10(s, s, p256_norm_order);
-        err = sp_256_mod_10(s, s, p256_order);
-    }
-    if (err == MP_OKAY) {
-        sp_256_norm_10(s);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_inv_order_avx2_10(s, s, tmp);
-            sp_256_mont_mul_order_avx2_10(u1, u1, s);
-            sp_256_mont_mul_order_avx2_10(u2, u2, s);
-        }
-        else
-#endif
-        {
-            sp_256_mont_inv_order_10(s, s, tmp);
-            sp_256_mont_mul_order_10(u1, u1, s);
-            sp_256_mont_mul_order_10(u2, u2, s);
-        }
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_10(p1, u1, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_10(p1, u1, 0, heap);
-    }
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_10(p2, p2, u2, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, heap);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_10(p1, p1, p2, tmp);
-        else
-#endif
-            sp_256_proj_point_add_10(p1, p1, p2, tmp);
-
-        /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
-        /* Reload r and convert to Montgomery form. */
-        sp_256_from_mp(u2, 10, r);
-        err = sp_256_mod_mul_norm_10(u2, u2, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* u1 = r.z'.z' mod prime */
-        sp_256_mont_sqr_10(p1->z, p1->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, p256_mp_mod);
-        *res = sp_256_cmp_10(p1->x, u1) == 0;
-        if (*res == 0) {
-            /* Reload r and add order. */
-            sp_256_from_mp(u2, 10, r);
-            carry = sp_256_add_10(u2, u2, p256_order);
-            /* Carry means result is greater than mod and is not valid. */
-            if (!carry) {
-                sp_256_norm_10(u2);
-
-                /* Compare with mod and if greater or equal then not valid. */
-                c = sp_256_cmp_10(u2, p256_mod);
-                if (c < 0) {
-                    /* Convert to Montogomery form */
-                    err = sp_256_mod_mul_norm_10(u2, u2, p256_mod);
-                    if (err == MP_OKAY) {
-                        /* u1 = (r + 1*order).z'.z' mod prime */
-                        sp_256_mont_mul_10(u1, u2, p1->z, p256_mod,
-                                                                  p256_mp_mod);
-                        *res = sp_256_cmp_10(p1->x, u2) == 0;
-                    }
-                }
-            }
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p1, 0, heap);
-    sp_ecc_point_free(p2, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_CHECK_KEY
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * point  EC point.
- * heap   Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-static int sp_256_ecc_is_point_10(sp_point* point, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit t1d[2*10];
-    sp_digit t2d[2*10];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 10 * 4, heap, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 10;
-        t2 = d + 2 * 10;
-    }
-    else
-        err = MEMORY_E;
-#else
-    (void)heap;
-
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_sqr_10(t1, point->y);
-        sp_256_mod_10(t1, t1, p256_mod);
-        sp_256_sqr_10(t2, point->x);
-        sp_256_mod_10(t2, t2, p256_mod);
-        sp_256_mul_10(t2, t2, point->x);
-        sp_256_mod_10(t2, t2, p256_mod);
-	sp_256_sub_10(t2, p256_mod, t2);
-        sp_256_mont_add_10(t1, t1, t2, p256_mod);
-
-        sp_256_mont_add_10(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_10(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_10(t1, t1, point->x, p256_mod);
-
-        if (sp_256_cmp_10(t1, p256_b) != 0)
-            err = MP_VAL;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX  X ordinate of EC point.
- * pY  Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point pubd;
-#endif
-    sp_point* pub;
-    byte one[1] = { 1 };
-    int err;
-
-    err = sp_ecc_point_new(NULL, pubd, pub);
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 10, pX);
-        sp_256_from_mp(pub->y, 10, pY);
-        sp_256_from_bin(pub->z, 10, one, sizeof(one));
-
-        err = sp_256_ecc_is_point_10(pub, NULL);
-    }
-
-    sp_ecc_point_free(pub, 0, NULL);
-
-    return err;
-}
-
-/* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX     X ordinate of EC point.
- * pY     Y ordinate of EC point.
- * privm  Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit privd[10];
-    sp_point pubd;
-    sp_point pd;
-#endif
-    sp_digit* priv = NULL;
-    sp_point* pub;
-    sp_point* p = NULL;
-    byte one[1] = { 1 };
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, pubd, pub);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        priv = XMALLOC(sizeof(sp_digit) * 10, heap, DYNAMIC_TYPE_ECC);
-        if (priv == NULL)
-            err = MEMORY_E;
-    }
-#else
-    priv = privd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 10, pX);
-        sp_256_from_mp(pub->y, 10, pY);
-        sp_256_from_bin(pub->z, 10, one, sizeof(one));
-        sp_256_from_mp(priv, 10, privm);
-
-        /* Check point at infinitiy. */
-        if (sp_256_iszero_10(pub->x) &&
-            sp_256_iszero_10(pub->y))
-            err = ECC_INF_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check range of X and Y */
-        if (sp_256_cmp_10(pub->x, p256_mod) >= 0 ||
-            sp_256_cmp_10(pub->y, p256_mod) >= 0)
-            err = ECC_OUT_OF_RANGE_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check point is on curve */
-        err = sp_256_ecc_is_point_10(pub, heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* Point * order = infinity */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_10(p, pub, p256_order, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_10(p, pub, p256_order, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is infinity */
-        if (!sp_256_iszero_10(p->x) ||
-            !sp_256_iszero_10(p->y)) {
-            err = ECC_INF_E;
-        }
-    }
-
-    if (err == MP_OKAY) {
-        /* Base * private = point */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_10(p, priv, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_10(p, priv, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is public key */
-        if (sp_256_cmp_10(p->x, pub->x) != 0 ||
-            sp_256_cmp_10(p->y, pub->y) != 0) {
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (priv != NULL)
-        XFREE(priv, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(pub, 0, heap);
-
-    return err;
-}
-#endif
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-/* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX   First EC point's X ordinate.
- * pY   First EC point's Y ordinate.
- * pZ   First EC point's Z ordinate.
- * qX   Second EC point's X ordinate.
- * qY   Second EC point's Y ordinate.
- * qZ   Second EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 10 * 5];
-    sp_point pd;
-    sp_point qd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    sp_point* q = NULL;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(NULL, qd, q);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 10, pX);
-        sp_256_from_mp(p->y, 10, pY);
-        sp_256_from_mp(p->z, 10, pZ);
-        sp_256_from_mp(q->x, 10, qX);
-        sp_256_from_mp(q->y, 10, qY);
-        sp_256_from_mp(q->z, 10, qZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_10(p, p, q, tmp);
-        else
-#endif
-            sp_256_proj_point_add_10(p, p, q, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(q, 0, NULL);
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 10 * 2];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 10, pX);
-        sp_256_from_mp(p->y, 10, pY);
-        sp_256_from_mp(p->z, 10, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_dbl_avx2_10(p, p, tmp);
-        else
-#endif
-            sp_256_proj_point_dbl_10(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 10 * 4];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 10, pX);
-        sp_256_from_mp(p->y, 10, pY);
-        sp_256_from_mp(p->z, 10, pZ);
-
-        sp_256_map_10(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, pX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
-#ifdef HAVE_COMP_KEY
-/* Find the square root of a number mod the prime of the curve.
- *
- * y  The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mont_sqrt_10(sp_digit* y)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit t1d[2 * 10];
-    sp_digit t2d[2 * 10];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 10;
-        t2 = d + 2 * 10;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_avx2_10(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_avx2_10(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_avx2_10(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_avx2_10(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_avx2_10(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_avx2_10(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_avx2_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_avx2_10(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_avx2_10(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_avx2_10(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_avx2_10(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_avx2_10(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_10(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_10(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_10(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_10(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_10(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_10(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_10(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_10(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Uncompress the point given the X ordinate.
- *
- * xm    X ordinate.
- * odd   Whether the Y ordinate is odd.
- * ym    Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit xd[2 * 10];
-    sp_digit yd[2 * 10];
-#endif
-    sp_digit* x;
-    sp_digit* y;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        x = d + 0 * 10;
-        y = d + 2 * 10;
-    }
-    else
-        err = MEMORY_E;
-#else
-    x = xd;
-    y = yd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(x, 10, xm);
-
-        err = sp_256_mod_mul_norm_10(x, x, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* y = x^3 */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_sqr_avx2_10(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_avx2_10(y, y, x, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            sp_256_mont_sqr_10(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod);
-        }
-        /* y = x^3 - 3x */
-        sp_256_mont_sub_10(y, y, x, p256_mod);
-        sp_256_mont_sub_10(y, y, x, p256_mod);
-        sp_256_mont_sub_10(y, y, x, p256_mod);
-        /* y = x^3 - 3x + b */
-        err = sp_256_mod_mul_norm_10(x, p256_b, p256_mod);
-    }
-    if (err == MP_OKAY) {
-        sp_256_mont_add_10(y, y, x, p256_mod);
-        /* y = sqrt(x^3 - 3x + b) */
-        err = sp_256_mont_sqrt_10(y);
-    }
-    if (err == MP_OKAY) {
-        XMEMSET(y + 10, 0, 10 * sizeof(sp_digit));
-        sp_256_mont_reduce_10(y, p256_mod, p256_mp_mod);
-        if (((y[0] ^ odd) & 1) != 0)
-            sp_256_mont_sub_10(y, p256_mod, y, p256_mod);
-
-        err = sp_256_to_mp(y, ym);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* SP_WORD_SIZE == 32 */
-#endif /* !WOLFSSL_SP_ASM */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
--- a/wolfcrypt/src/sp_c64.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12035 +0,0 @@
-/* sp.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#ifdef RSA_LOW_MEM
-#define SP_RSA_PRIVATE_EXP_D
-
-#ifndef WOLFSSL_SP_SMALL
-#define WOLFSSL_SP_SMALL
-#endif
-#endif
-
-#include <wolfssl/wolfcrypt/sp.h>
-
-#ifndef WOLFSSL_SP_ASM
-#if SP_WORD_SIZE == 64
-#if defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)
-/* Mask for address to obfuscate which of the two address will be used. */
-static const size_t addr_mask[2] = { 0, (size_t)-1 };
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
-#ifndef WOLFSSL_SP_NO_2048
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 49) {
-            r[j] &= 0x1ffffffffffffffl;
-            s = 57 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 57
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 57
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0x1ffffffffffffffl;
-        s = 57 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 57 <= DIGIT_BIT) {
-            s += 57;
-            r[j] &= 0x1ffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 57) {
-            r[j] &= 0x1ffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 57 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 256
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_2048_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<35; i++) {
-        r[i+1] += r[i] >> 57;
-        r[i] &= 0x1ffffffffffffffl;
-    }
-    j = 2048 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<36 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 57) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 57);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_9(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int128_t t0   = ((int128_t)a[ 0]) * b[ 0];
-    int128_t t1   = ((int128_t)a[ 0]) * b[ 1]
-                 + ((int128_t)a[ 1]) * b[ 0];
-    int128_t t2   = ((int128_t)a[ 0]) * b[ 2]
-                 + ((int128_t)a[ 1]) * b[ 1]
-                 + ((int128_t)a[ 2]) * b[ 0];
-    int128_t t3   = ((int128_t)a[ 0]) * b[ 3]
-                 + ((int128_t)a[ 1]) * b[ 2]
-                 + ((int128_t)a[ 2]) * b[ 1]
-                 + ((int128_t)a[ 3]) * b[ 0];
-    int128_t t4   = ((int128_t)a[ 0]) * b[ 4]
-                 + ((int128_t)a[ 1]) * b[ 3]
-                 + ((int128_t)a[ 2]) * b[ 2]
-                 + ((int128_t)a[ 3]) * b[ 1]
-                 + ((int128_t)a[ 4]) * b[ 0];
-    int128_t t5   = ((int128_t)a[ 0]) * b[ 5]
-                 + ((int128_t)a[ 1]) * b[ 4]
-                 + ((int128_t)a[ 2]) * b[ 3]
-                 + ((int128_t)a[ 3]) * b[ 2]
-                 + ((int128_t)a[ 4]) * b[ 1]
-                 + ((int128_t)a[ 5]) * b[ 0];
-    int128_t t6   = ((int128_t)a[ 0]) * b[ 6]
-                 + ((int128_t)a[ 1]) * b[ 5]
-                 + ((int128_t)a[ 2]) * b[ 4]
-                 + ((int128_t)a[ 3]) * b[ 3]
-                 + ((int128_t)a[ 4]) * b[ 2]
-                 + ((int128_t)a[ 5]) * b[ 1]
-                 + ((int128_t)a[ 6]) * b[ 0];
-    int128_t t7   = ((int128_t)a[ 0]) * b[ 7]
-                 + ((int128_t)a[ 1]) * b[ 6]
-                 + ((int128_t)a[ 2]) * b[ 5]
-                 + ((int128_t)a[ 3]) * b[ 4]
-                 + ((int128_t)a[ 4]) * b[ 3]
-                 + ((int128_t)a[ 5]) * b[ 2]
-                 + ((int128_t)a[ 6]) * b[ 1]
-                 + ((int128_t)a[ 7]) * b[ 0];
-    int128_t t8   = ((int128_t)a[ 0]) * b[ 8]
-                 + ((int128_t)a[ 1]) * b[ 7]
-                 + ((int128_t)a[ 2]) * b[ 6]
-                 + ((int128_t)a[ 3]) * b[ 5]
-                 + ((int128_t)a[ 4]) * b[ 4]
-                 + ((int128_t)a[ 5]) * b[ 3]
-                 + ((int128_t)a[ 6]) * b[ 2]
-                 + ((int128_t)a[ 7]) * b[ 1]
-                 + ((int128_t)a[ 8]) * b[ 0];
-    int128_t t9   = ((int128_t)a[ 1]) * b[ 8]
-                 + ((int128_t)a[ 2]) * b[ 7]
-                 + ((int128_t)a[ 3]) * b[ 6]
-                 + ((int128_t)a[ 4]) * b[ 5]
-                 + ((int128_t)a[ 5]) * b[ 4]
-                 + ((int128_t)a[ 6]) * b[ 3]
-                 + ((int128_t)a[ 7]) * b[ 2]
-                 + ((int128_t)a[ 8]) * b[ 1];
-    int128_t t10  = ((int128_t)a[ 2]) * b[ 8]
-                 + ((int128_t)a[ 3]) * b[ 7]
-                 + ((int128_t)a[ 4]) * b[ 6]
-                 + ((int128_t)a[ 5]) * b[ 5]
-                 + ((int128_t)a[ 6]) * b[ 4]
-                 + ((int128_t)a[ 7]) * b[ 3]
-                 + ((int128_t)a[ 8]) * b[ 2];
-    int128_t t11  = ((int128_t)a[ 3]) * b[ 8]
-                 + ((int128_t)a[ 4]) * b[ 7]
-                 + ((int128_t)a[ 5]) * b[ 6]
-                 + ((int128_t)a[ 6]) * b[ 5]
-                 + ((int128_t)a[ 7]) * b[ 4]
-                 + ((int128_t)a[ 8]) * b[ 3];
-    int128_t t12  = ((int128_t)a[ 4]) * b[ 8]
-                 + ((int128_t)a[ 5]) * b[ 7]
-                 + ((int128_t)a[ 6]) * b[ 6]
-                 + ((int128_t)a[ 7]) * b[ 5]
-                 + ((int128_t)a[ 8]) * b[ 4];
-    int128_t t13  = ((int128_t)a[ 5]) * b[ 8]
-                 + ((int128_t)a[ 6]) * b[ 7]
-                 + ((int128_t)a[ 7]) * b[ 6]
-                 + ((int128_t)a[ 8]) * b[ 5];
-    int128_t t14  = ((int128_t)a[ 6]) * b[ 8]
-                 + ((int128_t)a[ 7]) * b[ 7]
-                 + ((int128_t)a[ 8]) * b[ 6];
-    int128_t t15  = ((int128_t)a[ 7]) * b[ 8]
-                 + ((int128_t)a[ 8]) * b[ 7];
-    int128_t t16  = ((int128_t)a[ 8]) * b[ 8];
-
-    t1   += t0  >> 57; r[ 0] = t0  & 0x1ffffffffffffffl;
-    t2   += t1  >> 57; r[ 1] = t1  & 0x1ffffffffffffffl;
-    t3   += t2  >> 57; r[ 2] = t2  & 0x1ffffffffffffffl;
-    t4   += t3  >> 57; r[ 3] = t3  & 0x1ffffffffffffffl;
-    t5   += t4  >> 57; r[ 4] = t4  & 0x1ffffffffffffffl;
-    t6   += t5  >> 57; r[ 5] = t5  & 0x1ffffffffffffffl;
-    t7   += t6  >> 57; r[ 6] = t6  & 0x1ffffffffffffffl;
-    t8   += t7  >> 57; r[ 7] = t7  & 0x1ffffffffffffffl;
-    t9   += t8  >> 57; r[ 8] = t8  & 0x1ffffffffffffffl;
-    t10  += t9  >> 57; r[ 9] = t9  & 0x1ffffffffffffffl;
-    t11  += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl;
-    t12  += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl;
-    t13  += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl;
-    t14  += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl;
-    t15  += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl;
-    t16  += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl;
-    r[17] = (sp_digit)(t16 >> 57);
-                       r[16] = t16 & 0x1ffffffffffffffl;
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_9(sp_digit* r, const sp_digit* a)
-{
-    int128_t t0   =  ((int128_t)a[ 0]) * a[ 0];
-    int128_t t1   = (((int128_t)a[ 0]) * a[ 1]) * 2;
-    int128_t t2   = (((int128_t)a[ 0]) * a[ 2]) * 2
-                 +  ((int128_t)a[ 1]) * a[ 1];
-    int128_t t3   = (((int128_t)a[ 0]) * a[ 3]
-                 +  ((int128_t)a[ 1]) * a[ 2]) * 2;
-    int128_t t4   = (((int128_t)a[ 0]) * a[ 4]
-                 +  ((int128_t)a[ 1]) * a[ 3]) * 2
-                 +  ((int128_t)a[ 2]) * a[ 2];
-    int128_t t5   = (((int128_t)a[ 0]) * a[ 5]
-                 +  ((int128_t)a[ 1]) * a[ 4]
-                 +  ((int128_t)a[ 2]) * a[ 3]) * 2;
-    int128_t t6   = (((int128_t)a[ 0]) * a[ 6]
-                 +  ((int128_t)a[ 1]) * a[ 5]
-                 +  ((int128_t)a[ 2]) * a[ 4]) * 2
-                 +  ((int128_t)a[ 3]) * a[ 3];
-    int128_t t7   = (((int128_t)a[ 0]) * a[ 7]
-                 +  ((int128_t)a[ 1]) * a[ 6]
-                 +  ((int128_t)a[ 2]) * a[ 5]
-                 +  ((int128_t)a[ 3]) * a[ 4]) * 2;
-    int128_t t8   = (((int128_t)a[ 0]) * a[ 8]
-                 +  ((int128_t)a[ 1]) * a[ 7]
-                 +  ((int128_t)a[ 2]) * a[ 6]
-                 +  ((int128_t)a[ 3]) * a[ 5]) * 2
-                 +  ((int128_t)a[ 4]) * a[ 4];
-    int128_t t9   = (((int128_t)a[ 1]) * a[ 8]
-                 +  ((int128_t)a[ 2]) * a[ 7]
-                 +  ((int128_t)a[ 3]) * a[ 6]
-                 +  ((int128_t)a[ 4]) * a[ 5]) * 2;
-    int128_t t10  = (((int128_t)a[ 2]) * a[ 8]
-                 +  ((int128_t)a[ 3]) * a[ 7]
-                 +  ((int128_t)a[ 4]) * a[ 6]) * 2
-                 +  ((int128_t)a[ 5]) * a[ 5];
-    int128_t t11  = (((int128_t)a[ 3]) * a[ 8]
-                 +  ((int128_t)a[ 4]) * a[ 7]
-                 +  ((int128_t)a[ 5]) * a[ 6]) * 2;
-    int128_t t12  = (((int128_t)a[ 4]) * a[ 8]
-                 +  ((int128_t)a[ 5]) * a[ 7]) * 2
-                 +  ((int128_t)a[ 6]) * a[ 6];
-    int128_t t13  = (((int128_t)a[ 5]) * a[ 8]
-                 +  ((int128_t)a[ 6]) * a[ 7]) * 2;
-    int128_t t14  = (((int128_t)a[ 6]) * a[ 8]) * 2
-                 +  ((int128_t)a[ 7]) * a[ 7];
-    int128_t t15  = (((int128_t)a[ 7]) * a[ 8]) * 2;
-    int128_t t16  =  ((int128_t)a[ 8]) * a[ 8];
-
-    t1   += t0  >> 57; r[ 0] = t0  & 0x1ffffffffffffffl;
-    t2   += t1  >> 57; r[ 1] = t1  & 0x1ffffffffffffffl;
-    t3   += t2  >> 57; r[ 2] = t2  & 0x1ffffffffffffffl;
-    t4   += t3  >> 57; r[ 3] = t3  & 0x1ffffffffffffffl;
-    t5   += t4  >> 57; r[ 4] = t4  & 0x1ffffffffffffffl;
-    t6   += t5  >> 57; r[ 5] = t5  & 0x1ffffffffffffffl;
-    t7   += t6  >> 57; r[ 6] = t6  & 0x1ffffffffffffffl;
-    t8   += t7  >> 57; r[ 7] = t7  & 0x1ffffffffffffffl;
-    t9   += t8  >> 57; r[ 8] = t8  & 0x1ffffffffffffffl;
-    t10  += t9  >> 57; r[ 9] = t9  & 0x1ffffffffffffffl;
-    t11  += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl;
-    t12  += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl;
-    t13  += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl;
-    t14  += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl;
-    t15  += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl;
-    t16  += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl;
-    r[17] = (sp_digit)(t16 >> 57);
-                       r[16] = t16 & 0x1ffffffffffffffl;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_9(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] + b[ 0];
-    r[ 1] = a[ 1] + b[ 1];
-    r[ 2] = a[ 2] + b[ 2];
-    r[ 3] = a[ 3] + b[ 3];
-    r[ 4] = a[ 4] + b[ 4];
-    r[ 5] = a[ 5] + b[ 5];
-    r[ 6] = a[ 6] + b[ 6];
-    r[ 7] = a[ 7] + b[ 7];
-    r[ 8] = a[ 8] + b[ 8];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[16] = a[16] + b[16];
-    r[17] = a[17] + b[17];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[16] = a[16] - b[16];
-    r[17] = a[17] - b[17];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[18];
-    sp_digit* a1 = z1;
-    sp_digit b1[9];
-    sp_digit* z2 = r + 18;
-    sp_2048_add_9(a1, a, &a[9]);
-    sp_2048_add_9(b1, b, &b[9]);
-    sp_2048_mul_9(z2, &a[9], &b[9]);
-    sp_2048_mul_9(z0, a, b);
-    sp_2048_mul_9(z1, a1, b1);
-    sp_2048_sub_18(z1, z1, z2);
-    sp_2048_sub_18(z1, z1, z0);
-    sp_2048_add_18(r + 9, r + 9, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[18];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 18;
-    sp_2048_add_9(a1, a, &a[9]);
-    sp_2048_sqr_9(z2, &a[9]);
-    sp_2048_sqr_9(z0, a);
-    sp_2048_sqr_9(z1, a1);
-    sp_2048_sub_18(z1, z1, z2);
-    sp_2048_sub_18(z1, z1, z0);
-    sp_2048_add_18(r + 9, r + 9, z1);
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[32] = a[32] + b[32];
-    r[33] = a[33] + b[33];
-    r[34] = a[34] + b[34];
-    r[35] = a[35] + b[35];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[32] = a[32] - b[32];
-    r[33] = a[33] - b[33];
-    r[34] = a[34] - b[34];
-    r[35] = a[35] - b[35];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[36];
-    sp_digit* a1 = z1;
-    sp_digit b1[18];
-    sp_digit* z2 = r + 36;
-    sp_2048_add_18(a1, a, &a[18]);
-    sp_2048_add_18(b1, b, &b[18]);
-    sp_2048_mul_18(z2, &a[18], &b[18]);
-    sp_2048_mul_18(z0, a, b);
-    sp_2048_mul_18(z1, a1, b1);
-    sp_2048_sub_36(z1, z1, z2);
-    sp_2048_sub_36(z1, z1, z0);
-    sp_2048_add_36(r + 18, r + 18, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[36];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 36;
-    sp_2048_add_18(a1, a, &a[18]);
-    sp_2048_sqr_18(z2, &a[18]);
-    sp_2048_sqr_18(z0, a);
-    sp_2048_sqr_18(z1, a1);
-    sp_2048_sub_36(z1, z1, z2);
-    sp_2048_sub_36(z1, z1, z0);
-    sp_2048_add_36(r + 18, r + 18, z1);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[35]) * b[35];
-    r[71] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 69; k >= 0; k--) {
-        for (i = 35; i >= 0; i--) {
-            j = k - i;
-            if (j >= 36)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[35]) * a[35];
-    r[71] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 69; k >= 0; k--) {
-        for (i = 35; i >= 0; i--) {
-            j = k - i;
-            if (j >= 36 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int128_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[17]) * b[17];
-    r[35] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 33; k >= 0; k--) {
-        for (i = 17; i >= 0; i--) {
-            j = k - i;
-            if (j >= 18)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[17]) * a[17];
-    r[35] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 33; k >= 0; k--) {
-        for (i = 17; i >= 0; i--) {
-            j = k - i;
-            if (j >= 18 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int128_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-    x &= 0x1ffffffffffffffl;
-
-    /* rho = -1/m mod b */
-    *rho = (1L << 57) - x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_18(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<17; i++)
-        r[i] = 0x1ffffffffffffffl;
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = 0x1ffffffffffffffl;
-        r[i + 1] = 0x1ffffffffffffffl;
-        r[i + 2] = 0x1ffffffffffffffl;
-        r[i + 3] = 0x1ffffffffffffffl;
-        r[i + 4] = 0x1ffffffffffffffl;
-        r[i + 5] = 0x1ffffffffffffffl;
-        r[i + 6] = 0x1ffffffffffffffl;
-        r[i + 7] = 0x1ffffffffffffffl;
-    }
-    r[16] = 0x1ffffffffffffffl;
-#endif
-    r[17] = 0x7fffffffffffffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_2048_sub_18(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_2048_cmp_18(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=17; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[17] - b[17]) & (0 - !r);
-    r |= (a[16] - b[16]) & (0 - !r);
-    for (i = 8; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_sub_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[16] = a[16] - (b[16] & m);
-    r[17] = a[17] - (b[17] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 18; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[18] += t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 16; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[17]; r[17] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    r[18] +=  t[1] >> 57;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 57.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_2048_norm_18(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 17; i++) {
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-#else
-    int i;
-    for (i = 0; i < 16; i += 8) {
-        a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl;
-        a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl;
-        a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl;
-        a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl;
-        a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl;
-        a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl;
-        a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl;
-        a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl;
-        a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl;
-    }
-    a[16+1] += a[16] >> 57;
-    a[16] &= 0x1ffffffffffffffl;
-#endif
-}
-
-/* Shift the result in the high 1024 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_2048_mont_shift_18(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    word64 n;
-
-    n = a[17] >> 55;
-    for (i = 0; i < 17; i++) {
-        n += a[18 + i] << 2;
-        r[i] = n & 0x1ffffffffffffffl;
-        n >>= 57;
-    }
-    n += a[35] << 2;
-    r[17] = n;
-#else
-    word64 n;
-    int i;
-
-    n  = a[17] >> 55;
-    for (i = 0; i < 16; i += 8) {
-        n += a[i+18] << 2; r[i+0] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+19] << 2; r[i+1] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+20] << 2; r[i+2] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+21] << 2; r[i+3] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+22] << 2; r[i+4] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+23] << 2; r[i+5] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+24] << 2; r[i+6] = n & 0x1ffffffffffffffl; n >>= 57;
-        n += a[i+25] << 2; r[i+7] = n & 0x1ffffffffffffffl; n >>= 57;
-    }
-    n += a[34] << 2; r[16] = n & 0x1ffffffffffffffl; n >>= 57;
-    n += a[35] << 2; r[17] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[18], 0, sizeof(*r) * 18);
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_2048_mont_reduce_18(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    for (i=0; i<17; i++) {
-        mu = (a[i] * mp) & 0x1ffffffffffffffl;
-        sp_2048_mul_add_18(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-    }
-    mu = (a[i] * mp) & 0x7fffffffffffffl;
-    sp_2048_mul_add_18(a+i, m, mu);
-    a[i+1] += a[i] >> 57;
-    a[i] &= 0x1ffffffffffffffl;
-
-    sp_2048_mont_shift_18(a, a);
-    sp_2048_cond_sub_18(a, a, m, 0 - ((a[17] >> 55) > 0));
-    sp_2048_norm_18(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_18(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_18(r, a, b);
-    sp_2048_mont_reduce_18(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_18(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_18(r, a);
-    sp_2048_mont_reduce_18(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_d_18(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 18; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[18] = (sp_digit)t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 16; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[17];
-    r[17] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    r[18] =  (sp_digit)(t[1] >> 57);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[16] = a[16] + (b[16] & m);
-    r[17] = a[17] + (b[17] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 18; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_div_18(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int128_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[36], t2d[18 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 18;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[17];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 18);
-        for (i=17; i>=0; i--) {
-            t1[18 + i] += t1[18 + i - 1] >> 57;
-            t1[18 + i - 1] &= 0x1ffffffffffffffl;
-            d1 = t1[18 + i];
-            d1 <<= 57;
-            d1 += t1[18 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_2048_mul_d_18(t2, d, r1);
-            sp_2048_sub_18(&t1[i], &t1[i], t2);
-            t1[18 + i] -= t2[18];
-            t1[18 + i] += t1[18 + i - 1] >> 57;
-            t1[18 + i - 1] &= 0x1ffffffffffffffl;
-            r1 = (((-t1[18 + i]) << 57) - t1[18 + i - 1]) / div;
-            r1++;
-            sp_2048_mul_d_18(t2, d, r1);
-            sp_2048_add_18(&t1[i], &t1[i], t2);
-            t1[18 + i] += t1[18 + i - 1] >> 57;
-            t1[18 + i - 1] &= 0x1ffffffffffffffl;
-        }
-        t1[18 - 1] += t1[18 - 2] >> 57;
-        t1[18 - 2] &= 0x1ffffffffffffffl;
-        d1 = t1[18 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_2048_mul_d_18(t2, d, r1);
-        sp_2048_sub_18(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 18);
-        for (i=0; i<16; i++) {
-            r[i+1] += r[i] >> 57;
-            r[i] &= 0x1ffffffffffffffl;
-        }
-        sp_2048_cond_add_18(r, r, d, 0 - (r[17] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_mod_18(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_18(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_18(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 18 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[18 * 2];
-        t[2] = &td[2 * 18 * 2];
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_18(norm, m);
-
-        if (reduceA)
-            err = sp_2048_mod_18(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 18);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_18(t[1], t[1], norm);
-        err = sp_2048_mod_18(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 18 * 2);
-            sp_2048_mont_sqr_18(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 18 * 2);
-        }
-
-        sp_2048_mont_reduce_18(t[0], m, mp);
-        n = sp_2048_cmp_18(t[0], m);
-        sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 18 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][36];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[18 * 2];
-        t[2] = &td[2 * 18 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_18(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_18(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_18(t[1], t[1], norm);
-                err = sp_2048_mod_18(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_18(t[1], a, norm);
-            err = sp_2048_mod_18(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_2048_mont_sqr_18(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_2048_mont_reduce_18(t[0], m, mp);
-        n = sp_2048_cmp_18(t[0], m);
-        sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][36];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[36];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 36, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 36;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_18(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_18(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_18(t[1], t[1], norm);
-                err = sp_2048_mod_18(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_18(t[1], a, norm);
-            err = sp_2048_mod_18(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_18(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_18(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_18(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_18(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_18(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_18(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_18(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_18(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_18(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_18(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_18(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_18(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_18(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_18(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_18(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_18(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_18(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_18(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_18(t[20], t[10], m, mp);
-        sp_2048_mont_mul_18(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_18(t[22], t[11], m, mp);
-        sp_2048_mont_mul_18(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_18(t[24], t[12], m, mp);
-        sp_2048_mont_mul_18(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_18(t[26], t[13], m, mp);
-        sp_2048_mont_mul_18(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_18(t[28], t[14], m, mp);
-        sp_2048_mont_mul_18(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_18(t[30], t[15], m, mp);
-        sp_2048_mont_mul_18(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 56) / 57) - 1;
-        c = bits % 57;
-        if (c == 0)
-            c = 57;
-        if (i < 18)
-            n = e[i--] << (64 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (7 - c);
-            c += 57;
-        }
-        y = n >> 59;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (7 - c);
-                c += 57;
-            }
-            y = (n >> 59) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_2048_mont_sqr_18(rt, rt, m, mp);
-            sp_2048_mont_sqr_18(rt, rt, m, mp);
-            sp_2048_mont_sqr_18(rt, rt, m, mp);
-            sp_2048_mont_sqr_18(rt, rt, m, mp);
-            sp_2048_mont_sqr_18(rt, rt, m, mp);
-
-            sp_2048_mont_mul_18(rt, rt, t[y], m, mp);
-        }
-
-        sp_2048_mont_reduce_18(rt, m, mp);
-        n = sp_2048_cmp_18(rt, m);
-        sp_2048_cond_sub_18(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_36(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<35; i++)
-        r[i] = 0x1ffffffffffffffl;
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = 0x1ffffffffffffffl;
-        r[i + 1] = 0x1ffffffffffffffl;
-        r[i + 2] = 0x1ffffffffffffffl;
-        r[i + 3] = 0x1ffffffffffffffl;
-        r[i + 4] = 0x1ffffffffffffffl;
-        r[i + 5] = 0x1ffffffffffffffl;
-        r[i + 6] = 0x1ffffffffffffffl;
-        r[i + 7] = 0x1ffffffffffffffl;
-    }
-    r[32] = 0x1ffffffffffffffl;
-    r[33] = 0x1ffffffffffffffl;
-    r[34] = 0x1ffffffffffffffl;
-#endif
-    r[35] = 0x1fffffffffffffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_2048_sub_36(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_2048_cmp_36(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=35; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[35] - b[35]) & (0 - !r);
-    r |= (a[34] - b[34]) & (0 - !r);
-    r |= (a[33] - b[33]) & (0 - !r);
-    r |= (a[32] - b[32]) & (0 - !r);
-    for (i = 24; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_sub_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[32] = a[32] - (b[32] & m);
-    r[33] = a[33] - (b[33] & m);
-    r[34] = a[34] - (b[34] & m);
-    r[35] = a[35] - (b[35] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 36; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[36] += t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 32; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[33]; r[33] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[34]; r[34] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    t[3] = tb * a[35]; r[35] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-    r[36] +=  t[3] >> 57;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 57.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_2048_norm_36(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 35; i++) {
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-#else
-    int i;
-    for (i = 0; i < 32; i += 8) {
-        a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl;
-        a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl;
-        a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl;
-        a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl;
-        a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl;
-        a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl;
-        a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl;
-        a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl;
-        a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl;
-    }
-    a[32+1] += a[32] >> 57;
-    a[32] &= 0x1ffffffffffffffl;
-    a[33+1] += a[33] >> 57;
-    a[33] &= 0x1ffffffffffffffl;
-    a[34+1] += a[34] >> 57;
-    a[34] &= 0x1ffffffffffffffl;
-#endif
-}
-
-/* Shift the result in the high 2048 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    sp_digit n, s;
-
-    s = a[36];
-    n = a[35] >> 53;
-    for (i = 0; i < 35; i++) {
-        n += (s & 0x1ffffffffffffffl) << 4;
-        r[i] = n & 0x1ffffffffffffffl;
-        n >>= 57;
-        s = a[37 + i] + (s >> 57);
-    }
-    n += s << 4;
-    r[35] = n;
-#else
-    sp_digit n, s;
-    int i;
-
-    s = a[36]; n = a[35] >> 53;
-    for (i = 0; i < 32; i += 8) {
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+0] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+37] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+1] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+38] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+2] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+39] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+3] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+40] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+4] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+41] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+5] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+42] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+6] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+43] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 4; r[i+7] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+44] + (s >> 57);
-    }
-    n += (s & 0x1ffffffffffffffl) << 4; r[32] = n & 0x1ffffffffffffffl;
-    n >>= 57; s = a[69] + (s >> 57);
-    n += (s & 0x1ffffffffffffffl) << 4; r[33] = n & 0x1ffffffffffffffl;
-    n >>= 57; s = a[70] + (s >> 57);
-    n += (s & 0x1ffffffffffffffl) << 4; r[34] = n & 0x1ffffffffffffffl;
-    n >>= 57; s = a[71] + (s >> 57);
-    n += s << 4;              r[35] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[36], 0, sizeof(*r) * 36);
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_2048_mont_reduce_36(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<35; i++) {
-            mu = (a[i] * mp) & 0x1ffffffffffffffl;
-            sp_2048_mul_add_36(a+i, m, mu);
-            a[i+1] += a[i] >> 57;
-        }
-        mu = (a[i] * mp) & 0x1fffffffffffffl;
-        sp_2048_mul_add_36(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-    else {
-        for (i=0; i<35; i++) {
-            mu = a[i] & 0x1ffffffffffffffl;
-            sp_2048_mul_add_36(a+i, m, mu);
-            a[i+1] += a[i] >> 57;
-        }
-        mu = a[i] & 0x1fffffffffffffl;
-        sp_2048_mul_add_36(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-
-    sp_2048_mont_shift_36(a, a);
-    sp_2048_cond_sub_36(a, a, m, 0 - ((a[35] >> 53) > 0));
-    sp_2048_norm_36(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_36(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_36(r, a, b);
-    sp_2048_mont_reduce_36(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_36(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_36(r, a);
-    sp_2048_mont_reduce_36(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 36; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[36] = (sp_digit)t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 32; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[33];
-    r[33] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[34];
-    r[34] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    t[3] = tb * a[35];
-    r[35] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-    r[36] =  (sp_digit)(t[3] >> 57);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[32] = a[32] + (b[32] & m);
-    r[33] = a[33] + (b[33] & m);
-    r[34] = a[34] + (b[34] & m);
-    r[35] = a[35] + (b[35] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef WOLFSSL_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#endif
-#ifdef WOLFSSL_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 36; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#endif
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_div_36(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int128_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[72], t2d[36 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 36 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 36;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[35];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 36);
-        for (i=35; i>=0; i--) {
-            t1[36 + i] += t1[36 + i - 1] >> 57;
-            t1[36 + i - 1] &= 0x1ffffffffffffffl;
-            d1 = t1[36 + i];
-            d1 <<= 57;
-            d1 += t1[36 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_2048_mul_d_36(t2, d, r1);
-            sp_2048_sub_36(&t1[i], &t1[i], t2);
-            t1[36 + i] -= t2[36];
-            t1[36 + i] += t1[36 + i - 1] >> 57;
-            t1[36 + i - 1] &= 0x1ffffffffffffffl;
-            r1 = (((-t1[36 + i]) << 57) - t1[36 + i - 1]) / div;
-            r1++;
-            sp_2048_mul_d_36(t2, d, r1);
-            sp_2048_add_36(&t1[i], &t1[i], t2);
-            t1[36 + i] += t1[36 + i - 1] >> 57;
-            t1[36 + i - 1] &= 0x1ffffffffffffffl;
-        }
-        t1[36 - 1] += t1[36 - 2] >> 57;
-        t1[36 - 2] &= 0x1ffffffffffffffl;
-        d1 = t1[36 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_2048_mul_d_36(t2, d, r1);
-        sp_2048_sub_36(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 36);
-        for (i=0; i<34; i++) {
-            r[i+1] += r[i] >> 57;
-            r[i] &= 0x1ffffffffffffffl;
-        }
-        sp_2048_cond_add_36(r, r, d, 0 - (r[35] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_2048_mod_36(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_36(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_36(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 36 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[36 * 2];
-        t[2] = &td[2 * 36 * 2];
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_36(norm, m);
-
-        if (reduceA)
-            err = sp_2048_mod_36(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 36);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_36(t[1], t[1], norm);
-        err = sp_2048_mod_36(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 36 * 2);
-            sp_2048_mont_sqr_36(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 36 * 2);
-        }
-
-        sp_2048_mont_reduce_36(t[0], m, mp);
-        n = sp_2048_cmp_36(t[0], m);
-        sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 36 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][72];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[36 * 2];
-        t[2] = &td[2 * 36 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_36(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_36(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_36(t[1], t[1], norm);
-                err = sp_2048_mod_36(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_36(t[1], a, norm);
-            err = sp_2048_mod_36(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_2048_mont_sqr_36(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_2048_mont_reduce_36(t[0], m, mp);
-        n = sp_2048_cmp_36(t[0], m);
-        sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][72];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[72];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 72, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 72;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_36(norm, m);
-
-        if (reduceA) {
-            err = sp_2048_mod_36(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_2048_mul_36(t[1], t[1], norm);
-                err = sp_2048_mod_36(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_2048_mul_36(t[1], a, norm);
-            err = sp_2048_mod_36(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_36(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_36(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_36(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_36(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_36(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_36(t[20], t[10], m, mp);
-        sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_36(t[22], t[11], m, mp);
-        sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_36(t[24], t[12], m, mp);
-        sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_36(t[26], t[13], m, mp);
-        sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_36(t[28], t[14], m, mp);
-        sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_36(t[30], t[15], m, mp);
-        sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 56) / 57) - 1;
-        c = bits % 57;
-        if (c == 0)
-            c = 57;
-        if (i < 36)
-            n = e[i--] << (64 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (7 - c);
-            c += 57;
-        }
-        y = n >> 59;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (7 - c);
-                c += 57;
-            }
-            y = (n >> 59) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_2048_mont_sqr_36(rt, rt, m, mp);
-            sp_2048_mont_sqr_36(rt, rt, m, mp);
-            sp_2048_mont_sqr_36(rt, rt, m, mp);
-            sp_2048_mont_sqr_36(rt, rt, m, mp);
-            sp_2048_mont_sqr_36(rt, rt, m, mp);
-
-            sp_2048_mont_mul_36(rt, rt, t[y], m, mp);
-        }
-
-        sp_2048_mont_reduce_36(rt, m, mp);
-        n = sp_2048_cmp_36(rt, m);
-        sp_2048_cond_sub_36(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \
-                                    !defined(RSA_LOW_MEM)
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_18(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<18; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-    r[16] = a[16] & m;
-    r[17] = a[17] & m;
-#endif
-}
-
-#endif
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* d = NULL;
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit* norm;
-    sp_digit e[1];
-    sp_digit mp;
-    int i;
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 36 * 2;
-        m = r + 36 * 2;
-        norm = r;
-
-        sp_2048_from_bin(a, 36, in, inLen);
-#if DIGIT_BIT >= 57
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 36, mm);
-
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_36(norm, m);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_mul_36(a, a, norm);
-        err = sp_2048_mod_36(a, a, m);
-    }
-    if (err == MP_OKAY) {
-        for (i=56; i>=0; i--)
-            if (e[0] >> i)
-                break;
-
-        XMEMCPY(r, a, sizeof(sp_digit) * 36 * 2);
-        for (i--; i>=0; i--) {
-            sp_2048_mont_sqr_36(r, r, m, mp);
-
-            if (((e[0] >> i) & 1) == 1)
-                sp_2048_mont_mul_36(r, r, a, m, mp);
-        }
-        sp_2048_mont_reduce_36(r, m, mp);
-        mp = sp_2048_cmp_36(r, m);
-        sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#else
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[72], md[36], rd[72];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 36 * 2;
-        m = r + 36 * 2;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 36, in, inLen);
-#if DIGIT_BIT >= 57
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 36, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_2048_sqr_36(r, a);
-                err = sp_2048_mod_36(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_2048_mul_36(r, a, r);
-                err = sp_2048_mod_36(r, r, m);
-            }
-        }
-        else {
-            sp_digit* norm = r;
-            int i;
-            sp_digit mp;
-
-            sp_2048_mont_setup(m, &mp);
-            sp_2048_mont_norm_36(norm, m);
-
-            if (err == MP_OKAY) {
-                sp_2048_mul_36(a, a, norm);
-                err = sp_2048_mod_36(a, a, m);
-            }
-
-            if (err == MP_OKAY) {
-                for (i=56; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 72);
-                for (i--; i>=0; i--) {
-                    sp_2048_mont_sqr_36(r, r, m, mp);
-
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_2048_mont_mul_36(r, r, a, m, mp);
-                }
-                sp_2048_mont_reduce_36(r, m, mp);
-                mp = sp_2048_cmp_36(r, m);
-                sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* a;
-    sp_digit* d = NULL;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = d + 36;
-        m = a + 36;
-        r = a;
-
-        sp_2048_from_bin(a, 36, in, inLen);
-        sp_2048_from_mp(d, 36, dm);
-        sp_2048_from_mp(m, 36, mm);
-        err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 36);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[72], d[36], m[36];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 36, in, inLen);
-        sp_2048_from_mp(d, 36, dm);
-        sp_2048_from_mp(m, 36, mm);
-        err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    XMEMSET(d, 0, sizeof(sp_digit) * 36);
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#else
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* t = NULL;
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 36 * 2;
-        q = p + 18;
-        qi = dq = dp = q + 18;
-        tmpa = qi + 18;
-        tmpb = tmpa + 36;
-
-        tmp = t;
-        r = tmp + 36;
-
-        sp_2048_from_bin(a, 36, in, inLen);
-        sp_2048_from_mp(p, 18, pm);
-        sp_2048_from_mp(q, 18, qm);
-        sp_2048_from_mp(dp, 18, dpm);
-        err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(dq, 18, dqm);
-        err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_sub_18(tmpa, tmpa, tmpb);
-        sp_2048_mask_18(tmp, p, tmpa[17] >> 63);
-        sp_2048_add_18(tmpa, tmpa, tmp);
-
-        sp_2048_from_mp(qi, 18, qim);
-        sp_2048_mul_18(tmpa, tmpa, qi);
-        err = sp_2048_mod_18(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_18(tmpa, q, tmpa);
-        sp_2048_add_36(r, tmpb, tmpa);
-        sp_2048_norm_36(r);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 18 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[36 * 2];
-    sp_digit p[18], q[18], dp[18], dq[18], qi[18];
-    sp_digit tmp[36], tmpa[36], tmpb[36];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 36, in, inLen);
-        sp_2048_from_mp(p, 18, pm);
-        sp_2048_from_mp(q, 18, qm);
-        sp_2048_from_mp(dp, 18, dpm);
-        sp_2048_from_mp(dq, 18, dqm);
-        sp_2048_from_mp(qi, 18, qim);
-
-        err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY)
-        err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1);
-
-    if (err == MP_OKAY) {
-        sp_2048_sub_18(tmpa, tmpa, tmpb);
-        sp_2048_mask_18(tmp, p, tmpa[17] >> 63);
-        sp_2048_add_18(tmpa, tmpa, tmp);
-        sp_2048_mul_18(tmpa, tmpa, qi);
-        err = sp_2048_mod_18(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mul_18(tmpa, tmpa, q);
-        sp_2048_add_36(r, tmpb, tmpa);
-        sp_2048_norm_36(r);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-    XMEMSET(tmpa, 0, sizeof(tmpa));
-    XMEMSET(tmpb, 0, sizeof(tmpb));
-    XMEMSET(p, 0, sizeof(p));
-    XMEMSET(q, 0, sizeof(q));
-    XMEMSET(dp, 0, sizeof(dp));
-    XMEMSET(dq, 0, sizeof(dq));
-    XMEMSET(qi, 0, sizeof(qi));
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
-}
-
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_2048_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 57
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 36);
-        r->used = 36;
-        mp_clamp(r);
-#elif DIGIT_BIT < 57
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 36; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 57) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 57 - s;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 36; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 57 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 57 - s;
-            }
-            else
-                s += 57;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 36 * 2;
-        m = e + 36;
-        r = b;
-
-        sp_2048_from_mp(b, 36, base);
-        sp_2048_from_mp(e, 36, exp);
-        sp_2048_from_mp(m, 36, mod);
-
-        err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 36);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[72], ed[36], md[36];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 36 * 2;
-        m = e + 36;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 36, base);
-        sp_2048_from_mp(e, 36, exp);
-        sp_2048_from_mp(m, 36, mod);
-
-        err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 36);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 256 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 36 * 2;
-        m = e + 36;
-        r = b;
-
-        sp_2048_from_mp(b, 36, base);
-        sp_2048_from_bin(e, 36, exp, expLen);
-        sp_2048_from_mp(m, 36, mod);
-
-        err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 36);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[72], ed[36], md[36];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-    int err = MP_OKAY;
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 36 * 2;
-        m = e + 36;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 36, base);
-        sp_2048_from_bin(e, 36, exp, expLen);
-        sp_2048_from_mp(m, 36, mod);
-
-        err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 36);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_2048 */
-
-#ifndef WOLFSSL_SP_NO_3072
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 49) {
-            r[j] &= 0x1ffffffffffffffl;
-            s = 57 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 57
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 57
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0x1ffffffffffffffl;
-        s = 57 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 57 <= DIGIT_BIT) {
-            s += 57;
-            r[j] &= 0x1ffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 57) {
-            r[j] &= 0x1ffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 57 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 384
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_3072_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<53; i++) {
-        r[i+1] += r[i] >> 57;
-        r[i] &= 0x1ffffffffffffffl;
-    }
-    j = 3072 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<54 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 57) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 57);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_9(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int128_t t0   = ((int128_t)a[ 0]) * b[ 0];
-    int128_t t1   = ((int128_t)a[ 0]) * b[ 1]
-                 + ((int128_t)a[ 1]) * b[ 0];
-    int128_t t2   = ((int128_t)a[ 0]) * b[ 2]
-                 + ((int128_t)a[ 1]) * b[ 1]
-                 + ((int128_t)a[ 2]) * b[ 0];
-    int128_t t3   = ((int128_t)a[ 0]) * b[ 3]
-                 + ((int128_t)a[ 1]) * b[ 2]
-                 + ((int128_t)a[ 2]) * b[ 1]
-                 + ((int128_t)a[ 3]) * b[ 0];
-    int128_t t4   = ((int128_t)a[ 0]) * b[ 4]
-                 + ((int128_t)a[ 1]) * b[ 3]
-                 + ((int128_t)a[ 2]) * b[ 2]
-                 + ((int128_t)a[ 3]) * b[ 1]
-                 + ((int128_t)a[ 4]) * b[ 0];
-    int128_t t5   = ((int128_t)a[ 0]) * b[ 5]
-                 + ((int128_t)a[ 1]) * b[ 4]
-                 + ((int128_t)a[ 2]) * b[ 3]
-                 + ((int128_t)a[ 3]) * b[ 2]
-                 + ((int128_t)a[ 4]) * b[ 1]
-                 + ((int128_t)a[ 5]) * b[ 0];
-    int128_t t6   = ((int128_t)a[ 0]) * b[ 6]
-                 + ((int128_t)a[ 1]) * b[ 5]
-                 + ((int128_t)a[ 2]) * b[ 4]
-                 + ((int128_t)a[ 3]) * b[ 3]
-                 + ((int128_t)a[ 4]) * b[ 2]
-                 + ((int128_t)a[ 5]) * b[ 1]
-                 + ((int128_t)a[ 6]) * b[ 0];
-    int128_t t7   = ((int128_t)a[ 0]) * b[ 7]
-                 + ((int128_t)a[ 1]) * b[ 6]
-                 + ((int128_t)a[ 2]) * b[ 5]
-                 + ((int128_t)a[ 3]) * b[ 4]
-                 + ((int128_t)a[ 4]) * b[ 3]
-                 + ((int128_t)a[ 5]) * b[ 2]
-                 + ((int128_t)a[ 6]) * b[ 1]
-                 + ((int128_t)a[ 7]) * b[ 0];
-    int128_t t8   = ((int128_t)a[ 0]) * b[ 8]
-                 + ((int128_t)a[ 1]) * b[ 7]
-                 + ((int128_t)a[ 2]) * b[ 6]
-                 + ((int128_t)a[ 3]) * b[ 5]
-                 + ((int128_t)a[ 4]) * b[ 4]
-                 + ((int128_t)a[ 5]) * b[ 3]
-                 + ((int128_t)a[ 6]) * b[ 2]
-                 + ((int128_t)a[ 7]) * b[ 1]
-                 + ((int128_t)a[ 8]) * b[ 0];
-    int128_t t9   = ((int128_t)a[ 1]) * b[ 8]
-                 + ((int128_t)a[ 2]) * b[ 7]
-                 + ((int128_t)a[ 3]) * b[ 6]
-                 + ((int128_t)a[ 4]) * b[ 5]
-                 + ((int128_t)a[ 5]) * b[ 4]
-                 + ((int128_t)a[ 6]) * b[ 3]
-                 + ((int128_t)a[ 7]) * b[ 2]
-                 + ((int128_t)a[ 8]) * b[ 1];
-    int128_t t10  = ((int128_t)a[ 2]) * b[ 8]
-                 + ((int128_t)a[ 3]) * b[ 7]
-                 + ((int128_t)a[ 4]) * b[ 6]
-                 + ((int128_t)a[ 5]) * b[ 5]
-                 + ((int128_t)a[ 6]) * b[ 4]
-                 + ((int128_t)a[ 7]) * b[ 3]
-                 + ((int128_t)a[ 8]) * b[ 2];
-    int128_t t11  = ((int128_t)a[ 3]) * b[ 8]
-                 + ((int128_t)a[ 4]) * b[ 7]
-                 + ((int128_t)a[ 5]) * b[ 6]
-                 + ((int128_t)a[ 6]) * b[ 5]
-                 + ((int128_t)a[ 7]) * b[ 4]
-                 + ((int128_t)a[ 8]) * b[ 3];
-    int128_t t12  = ((int128_t)a[ 4]) * b[ 8]
-                 + ((int128_t)a[ 5]) * b[ 7]
-                 + ((int128_t)a[ 6]) * b[ 6]
-                 + ((int128_t)a[ 7]) * b[ 5]
-                 + ((int128_t)a[ 8]) * b[ 4];
-    int128_t t13  = ((int128_t)a[ 5]) * b[ 8]
-                 + ((int128_t)a[ 6]) * b[ 7]
-                 + ((int128_t)a[ 7]) * b[ 6]
-                 + ((int128_t)a[ 8]) * b[ 5];
-    int128_t t14  = ((int128_t)a[ 6]) * b[ 8]
-                 + ((int128_t)a[ 7]) * b[ 7]
-                 + ((int128_t)a[ 8]) * b[ 6];
-    int128_t t15  = ((int128_t)a[ 7]) * b[ 8]
-                 + ((int128_t)a[ 8]) * b[ 7];
-    int128_t t16  = ((int128_t)a[ 8]) * b[ 8];
-
-    t1   += t0  >> 57; r[ 0] = t0  & 0x1ffffffffffffffl;
-    t2   += t1  >> 57; r[ 1] = t1  & 0x1ffffffffffffffl;
-    t3   += t2  >> 57; r[ 2] = t2  & 0x1ffffffffffffffl;
-    t4   += t3  >> 57; r[ 3] = t3  & 0x1ffffffffffffffl;
-    t5   += t4  >> 57; r[ 4] = t4  & 0x1ffffffffffffffl;
-    t6   += t5  >> 57; r[ 5] = t5  & 0x1ffffffffffffffl;
-    t7   += t6  >> 57; r[ 6] = t6  & 0x1ffffffffffffffl;
-    t8   += t7  >> 57; r[ 7] = t7  & 0x1ffffffffffffffl;
-    t9   += t8  >> 57; r[ 8] = t8  & 0x1ffffffffffffffl;
-    t10  += t9  >> 57; r[ 9] = t9  & 0x1ffffffffffffffl;
-    t11  += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl;
-    t12  += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl;
-    t13  += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl;
-    t14  += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl;
-    t15  += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl;
-    t16  += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl;
-    r[17] = (sp_digit)(t16 >> 57);
-                       r[16] = t16 & 0x1ffffffffffffffl;
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_9(sp_digit* r, const sp_digit* a)
-{
-    int128_t t0   =  ((int128_t)a[ 0]) * a[ 0];
-    int128_t t1   = (((int128_t)a[ 0]) * a[ 1]) * 2;
-    int128_t t2   = (((int128_t)a[ 0]) * a[ 2]) * 2
-                 +  ((int128_t)a[ 1]) * a[ 1];
-    int128_t t3   = (((int128_t)a[ 0]) * a[ 3]
-                 +  ((int128_t)a[ 1]) * a[ 2]) * 2;
-    int128_t t4   = (((int128_t)a[ 0]) * a[ 4]
-                 +  ((int128_t)a[ 1]) * a[ 3]) * 2
-                 +  ((int128_t)a[ 2]) * a[ 2];
-    int128_t t5   = (((int128_t)a[ 0]) * a[ 5]
-                 +  ((int128_t)a[ 1]) * a[ 4]
-                 +  ((int128_t)a[ 2]) * a[ 3]) * 2;
-    int128_t t6   = (((int128_t)a[ 0]) * a[ 6]
-                 +  ((int128_t)a[ 1]) * a[ 5]
-                 +  ((int128_t)a[ 2]) * a[ 4]) * 2
-                 +  ((int128_t)a[ 3]) * a[ 3];
-    int128_t t7   = (((int128_t)a[ 0]) * a[ 7]
-                 +  ((int128_t)a[ 1]) * a[ 6]
-                 +  ((int128_t)a[ 2]) * a[ 5]
-                 +  ((int128_t)a[ 3]) * a[ 4]) * 2;
-    int128_t t8   = (((int128_t)a[ 0]) * a[ 8]
-                 +  ((int128_t)a[ 1]) * a[ 7]
-                 +  ((int128_t)a[ 2]) * a[ 6]
-                 +  ((int128_t)a[ 3]) * a[ 5]) * 2
-                 +  ((int128_t)a[ 4]) * a[ 4];
-    int128_t t9   = (((int128_t)a[ 1]) * a[ 8]
-                 +  ((int128_t)a[ 2]) * a[ 7]
-                 +  ((int128_t)a[ 3]) * a[ 6]
-                 +  ((int128_t)a[ 4]) * a[ 5]) * 2;
-    int128_t t10  = (((int128_t)a[ 2]) * a[ 8]
-                 +  ((int128_t)a[ 3]) * a[ 7]
-                 +  ((int128_t)a[ 4]) * a[ 6]) * 2
-                 +  ((int128_t)a[ 5]) * a[ 5];
-    int128_t t11  = (((int128_t)a[ 3]) * a[ 8]
-                 +  ((int128_t)a[ 4]) * a[ 7]
-                 +  ((int128_t)a[ 5]) * a[ 6]) * 2;
-    int128_t t12  = (((int128_t)a[ 4]) * a[ 8]
-                 +  ((int128_t)a[ 5]) * a[ 7]) * 2
-                 +  ((int128_t)a[ 6]) * a[ 6];
-    int128_t t13  = (((int128_t)a[ 5]) * a[ 8]
-                 +  ((int128_t)a[ 6]) * a[ 7]) * 2;
-    int128_t t14  = (((int128_t)a[ 6]) * a[ 8]) * 2
-                 +  ((int128_t)a[ 7]) * a[ 7];
-    int128_t t15  = (((int128_t)a[ 7]) * a[ 8]) * 2;
-    int128_t t16  =  ((int128_t)a[ 8]) * a[ 8];
-
-    t1   += t0  >> 57; r[ 0] = t0  & 0x1ffffffffffffffl;
-    t2   += t1  >> 57; r[ 1] = t1  & 0x1ffffffffffffffl;
-    t3   += t2  >> 57; r[ 2] = t2  & 0x1ffffffffffffffl;
-    t4   += t3  >> 57; r[ 3] = t3  & 0x1ffffffffffffffl;
-    t5   += t4  >> 57; r[ 4] = t4  & 0x1ffffffffffffffl;
-    t6   += t5  >> 57; r[ 5] = t5  & 0x1ffffffffffffffl;
-    t7   += t6  >> 57; r[ 6] = t6  & 0x1ffffffffffffffl;
-    t8   += t7  >> 57; r[ 7] = t7  & 0x1ffffffffffffffl;
-    t9   += t8  >> 57; r[ 8] = t8  & 0x1ffffffffffffffl;
-    t10  += t9  >> 57; r[ 9] = t9  & 0x1ffffffffffffffl;
-    t11  += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl;
-    t12  += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl;
-    t13  += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl;
-    t14  += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl;
-    t15  += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl;
-    t16  += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl;
-    r[17] = (sp_digit)(t16 >> 57);
-                       r[16] = t16 & 0x1ffffffffffffffl;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_9(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] + b[ 0];
-    r[ 1] = a[ 1] + b[ 1];
-    r[ 2] = a[ 2] + b[ 2];
-    r[ 3] = a[ 3] + b[ 3];
-    r[ 4] = a[ 4] + b[ 4];
-    r[ 5] = a[ 5] + b[ 5];
-    r[ 6] = a[ 6] + b[ 6];
-    r[ 7] = a[ 7] + b[ 7];
-    r[ 8] = a[ 8] + b[ 8];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[16] = a[16] + b[16];
-    r[17] = a[17] + b[17];
-
-    return 0;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_18(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[16] = a[16] - b[16];
-    r[17] = a[17] - b[17];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_18(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[18];
-    sp_digit* a1 = z1;
-    sp_digit b1[9];
-    sp_digit* z2 = r + 18;
-    sp_3072_add_9(a1, a, &a[9]);
-    sp_3072_add_9(b1, b, &b[9]);
-    sp_3072_mul_9(z2, &a[9], &b[9]);
-    sp_3072_mul_9(z0, a, b);
-    sp_3072_mul_9(z1, a1, b1);
-    sp_3072_sub_18(z1, z1, z2);
-    sp_3072_sub_18(z1, z1, z0);
-    sp_3072_add_18(r + 9, r + 9, z1);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_18(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[18];
-    sp_digit* a1 = z1;
-    sp_digit* z2 = r + 18;
-    sp_3072_add_9(a1, a, &a[9]);
-    sp_3072_sqr_9(z2, &a[9]);
-    sp_3072_sqr_9(z0, a);
-    sp_3072_sqr_9(z1, a1);
-    sp_3072_sub_18(z1, z1, z2);
-    sp_3072_sub_18(z1, z1, z0);
-    sp_3072_add_18(r + 9, r + 9, z1);
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[32] = a[32] - b[32];
-    r[33] = a[33] - b[33];
-    r[34] = a[34] - b[34];
-    r[35] = a[35] - b[35];
-
-    return 0;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_36(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[32] = a[32] + b[32];
-    r[33] = a[33] + b[33];
-    r[34] = a[34] + b[34];
-    r[35] = a[35] + b[35];
-
-    return 0;
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit p0[36];
-    sp_digit p1[36];
-    sp_digit p2[36];
-    sp_digit p3[36];
-    sp_digit p4[36];
-    sp_digit p5[36];
-    sp_digit t0[36];
-    sp_digit t1[36];
-    sp_digit t2[36];
-    sp_digit a0[18];
-    sp_digit a1[18];
-    sp_digit a2[18];
-    sp_digit b0[18];
-    sp_digit b1[18];
-    sp_digit b2[18];
-    sp_3072_add_18(a0, a, &a[18]);
-    sp_3072_add_18(b0, b, &b[18]);
-    sp_3072_add_18(a1, &a[18], &a[36]);
-    sp_3072_add_18(b1, &b[18], &b[36]);
-    sp_3072_add_18(a2, a0, &a[36]);
-    sp_3072_add_18(b2, b0, &b[36]);
-    sp_3072_mul_18(p0, a, b);
-    sp_3072_mul_18(p2, &a[18], &b[18]);
-    sp_3072_mul_18(p4, &a[36], &b[36]);
-    sp_3072_mul_18(p1, a0, b0);
-    sp_3072_mul_18(p3, a1, b1);
-    sp_3072_mul_18(p5, a2, b2);
-    XMEMSET(r, 0, sizeof(*r)*2*54);
-    sp_3072_sub_36(t0, p3, p2);
-    sp_3072_sub_36(t1, p1, p2);
-    sp_3072_sub_36(t2, p5, t0);
-    sp_3072_sub_36(t2, t2, t1);
-    sp_3072_sub_36(t0, t0, p4);
-    sp_3072_sub_36(t1, t1, p0);
-    sp_3072_add_36(r, r, p0);
-    sp_3072_add_36(&r[18], &r[18], t1);
-    sp_3072_add_36(&r[36], &r[36], t2);
-    sp_3072_add_36(&r[54], &r[54], t0);
-    sp_3072_add_36(&r[72], &r[72], p4);
-}
-
-/* Square a into r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a)
-{
-    sp_digit p0[36];
-    sp_digit p1[36];
-    sp_digit p2[36];
-    sp_digit p3[36];
-    sp_digit p4[36];
-    sp_digit p5[36];
-    sp_digit t0[36];
-    sp_digit t1[36];
-    sp_digit t2[36];
-    sp_digit a0[18];
-    sp_digit a1[18];
-    sp_digit a2[18];
-    sp_3072_add_18(a0, a, &a[18]);
-    sp_3072_add_18(a1, &a[18], &a[36]);
-    sp_3072_add_18(a2, a0, &a[36]);
-    sp_3072_sqr_18(p0, a);
-    sp_3072_sqr_18(p2, &a[18]);
-    sp_3072_sqr_18(p4, &a[36]);
-    sp_3072_sqr_18(p1, a0);
-    sp_3072_sqr_18(p3, a1);
-    sp_3072_sqr_18(p5, a2);
-    XMEMSET(r, 0, sizeof(*r)*2*54);
-    sp_3072_sub_36(t0, p3, p2);
-    sp_3072_sub_36(t1, p1, p2);
-    sp_3072_sub_36(t2, p5, t0);
-    sp_3072_sub_36(t2, t2, t1);
-    sp_3072_sub_36(t0, t0, p4);
-    sp_3072_sub_36(t1, t1, p0);
-    sp_3072_add_36(r, r, p0);
-    sp_3072_add_36(&r[18], &r[18], t1);
-    sp_3072_add_36(&r[36], &r[36], t2);
-    sp_3072_add_36(&r[54], &r[54], t0);
-    sp_3072_add_36(&r[72], &r[72], p4);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 54; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[48] = a[48] + b[48];
-    r[49] = a[49] + b[49];
-    r[50] = a[50] + b[50];
-    r[51] = a[51] + b[51];
-    r[52] = a[52] + b[52];
-    r[53] = a[53] + b[53];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 54; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[48] = a[48] - b[48];
-    r[49] = a[49] - b[49];
-    r[50] = a[50] - b[50];
-    r[51] = a[51] - b[51];
-    r[52] = a[52] - b[52];
-    r[53] = a[53] - b[53];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[53]) * b[53];
-    r[107] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 105; k >= 0; k--) {
-        for (i = 53; i >= 0; i--) {
-            j = k - i;
-            if (j >= 54)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[53]) * a[53];
-    r[107] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 105; k >= 0; k--) {
-        for (i = 53; i >= 0; i--) {
-            j = k - i;
-            if (j >= 54 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int128_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 27; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_add_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] + b[i + 0];
-        r[i + 1] = a[i + 1] + b[i + 1];
-        r[i + 2] = a[i + 2] + b[i + 2];
-        r[i + 3] = a[i + 3] + b[i + 3];
-        r[i + 4] = a[i + 4] + b[i + 4];
-        r[i + 5] = a[i + 5] + b[i + 5];
-        r[i + 6] = a[i + 6] + b[i + 6];
-        r[i + 7] = a[i + 7] + b[i + 7];
-    }
-    r[24] = a[24] + b[24];
-    r[25] = a[25] + b[25];
-    r[26] = a[26] + b[26];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 27; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] - b[i + 0];
-        r[i + 1] = a[i + 1] - b[i + 1];
-        r[i + 2] = a[i + 2] - b[i + 2];
-        r[i + 3] = a[i + 3] - b[i + 3];
-        r[i + 4] = a[i + 4] - b[i + 4];
-        r[i + 5] = a[i + 5] - b[i + 5];
-        r[i + 6] = a[i + 6] - b[i + 6];
-        r[i + 7] = a[i + 7] - b[i + 7];
-    }
-    r[24] = a[24] - b[24];
-    r[25] = a[25] - b[25];
-    r[26] = a[26] - b[26];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[26]) * b[26];
-    r[53] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 51; k >= 0; k--) {
-        for (i = 26; i >= 0; i--) {
-            j = k - i;
-            if (j >= 27)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j;
-    int128_t t[54];
-
-    XMEMSET(t, 0, sizeof(t));
-    for (i=0; i<27; i++) {
-        for (j=0; j<27; j++)
-            t[i+j] += ((int128_t)a[i]) * b[j];
-    }
-    for (i=0; i<53; i++) {
-        r[i] = t[i] & 0x1ffffffffffffffl;
-        t[i+1] += t[i] >> 57;
-    }
-    r[53] = (sp_digit)t[53];
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[26]) * a[26];
-    r[53] = (sp_digit)(c >> 57);
-    c = (c & 0x1ffffffffffffffl) << 57;
-    for (k = 51; k >= 0; k--) {
-        for (i = 26; i >= 0; i--) {
-            j = k - i;
-            if (j >= 27 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int128_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 114;
-        r[k + 1] = (c >> 57) & 0x1ffffffffffffffl;
-        c = (c & 0x1ffffffffffffffl) << 57;
-    }
-    r[0] = (sp_digit)(c >> 57);
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a)
-{
-    int i, j;
-    int128_t t[54];
-
-    XMEMSET(t, 0, sizeof(t));
-    for (i=0; i<27; i++) {
-        for (j=0; j<i; j++)
-            t[i+j] += (((int128_t)a[i]) * a[j]) * 2;
-        t[i+i] += ((int128_t)a[i]) * a[i];
-    }
-    for (i=0; i<53; i++) {
-        r[i] = t[i] & 0x1ffffffffffffffl;
-        t[i+1] += t[i] >> 57;
-    }
-    r[53] = (sp_digit)t[53];
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-    x &= 0x1ffffffffffffffl;
-
-    /* rho = -1/m mod b */
-    *rho = (1L << 57) - x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_27(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<26; i++)
-        r[i] = 0x1ffffffffffffffl;
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = 0x1ffffffffffffffl;
-        r[i + 1] = 0x1ffffffffffffffl;
-        r[i + 2] = 0x1ffffffffffffffl;
-        r[i + 3] = 0x1ffffffffffffffl;
-        r[i + 4] = 0x1ffffffffffffffl;
-        r[i + 5] = 0x1ffffffffffffffl;
-        r[i + 6] = 0x1ffffffffffffffl;
-        r[i + 7] = 0x1ffffffffffffffl;
-    }
-    r[24] = 0x1ffffffffffffffl;
-    r[25] = 0x1ffffffffffffffl;
-#endif
-    r[26] = 0x3fffffffffffffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_3072_sub_27(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_3072_cmp_27(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=26; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[26] - b[26]) & (0 - !r);
-    r |= (a[25] - b[25]) & (0 - !r);
-    r |= (a[24] - b[24]) & (0 - !r);
-    for (i = 16; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_sub_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 27; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[24] = a[24] - (b[24] & m);
-    r[25] = a[25] - (b[25] & m);
-    r[26] = a[26] - (b[26] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_add_27(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 27; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[27] += t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 24; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[25]; r[25] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[26]; r[26] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    r[27] +=  t[2] >> 57;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 57.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_3072_norm_27(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 26; i++) {
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-#else
-    int i;
-    for (i = 0; i < 24; i += 8) {
-        a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl;
-        a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl;
-        a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl;
-        a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl;
-        a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl;
-        a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl;
-        a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl;
-        a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl;
-        a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl;
-    }
-    a[24+1] += a[24] >> 57;
-    a[24] &= 0x1ffffffffffffffl;
-    a[25+1] += a[25] >> 57;
-    a[25] &= 0x1ffffffffffffffl;
-#endif
-}
-
-/* Shift the result in the high 1536 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    sp_digit n, s;
-
-    s = a[27];
-    n = a[26] >> 54;
-    for (i = 0; i < 26; i++) {
-        n += (s & 0x1ffffffffffffffl) << 3;
-        r[i] = n & 0x1ffffffffffffffl;
-        n >>= 57;
-        s = a[28 + i] + (s >> 57);
-    }
-    n += s << 3;
-    r[26] = n;
-#else
-    sp_digit n, s;
-    int i;
-
-    s = a[27]; n = a[26] >> 54;
-    for (i = 0; i < 24; i += 8) {
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+0] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+28] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+1] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+29] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+2] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+30] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+3] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+31] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+4] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+32] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+5] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+33] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+6] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+34] + (s >> 57);
-        n += (s & 0x1ffffffffffffffl) << 3; r[i+7] = n & 0x1ffffffffffffffl;
-        n >>= 57; s = a[i+35] + (s >> 57);
-    }
-    n += (s & 0x1ffffffffffffffl) << 3; r[24] = n & 0x1ffffffffffffffl;
-    n >>= 57; s = a[52] + (s >> 57);
-    n += (s & 0x1ffffffffffffffl) << 3; r[25] = n & 0x1ffffffffffffffl;
-    n >>= 57; s = a[53] + (s >> 57);
-    n += s << 3;              r[26] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[27], 0, sizeof(*r) * 27);
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_3072_mont_reduce_27(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    for (i=0; i<26; i++) {
-        mu = (a[i] * mp) & 0x1ffffffffffffffl;
-        sp_3072_mul_add_27(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-    }
-    mu = (a[i] * mp) & 0x3fffffffffffffl;
-    sp_3072_mul_add_27(a+i, m, mu);
-    a[i+1] += a[i] >> 57;
-    a[i] &= 0x1ffffffffffffffl;
-
-    sp_3072_mont_shift_27(a, a);
-    sp_3072_cond_sub_27(a, a, m, 0 - ((a[26] >> 54) > 0));
-    sp_3072_norm_27(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_27(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_27(r, a, b);
-    sp_3072_mont_reduce_27(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_27(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_27(r, a);
-    sp_3072_mont_reduce_27(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_d_27(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 27; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[27] = (sp_digit)t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 24; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[25];
-    r[25] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[26];
-    r[26] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    r[27] =  (sp_digit)(t[2] >> 57);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_add_27(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 27; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[24] = a[24] + (b[24] & m);
-    r[25] = a[25] + (b[25] & m);
-    r[26] = a[26] + (b[26] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_div_27(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int128_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[54], t2d[27 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 27 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 27;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[26];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 27);
-        for (i=26; i>=0; i--) {
-            t1[27 + i] += t1[27 + i - 1] >> 57;
-            t1[27 + i - 1] &= 0x1ffffffffffffffl;
-            d1 = t1[27 + i];
-            d1 <<= 57;
-            d1 += t1[27 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_3072_mul_d_27(t2, d, r1);
-            sp_3072_sub_27(&t1[i], &t1[i], t2);
-            t1[27 + i] -= t2[27];
-            t1[27 + i] += t1[27 + i - 1] >> 57;
-            t1[27 + i - 1] &= 0x1ffffffffffffffl;
-            r1 = (((-t1[27 + i]) << 57) - t1[27 + i - 1]) / div;
-            r1++;
-            sp_3072_mul_d_27(t2, d, r1);
-            sp_3072_add_27(&t1[i], &t1[i], t2);
-            t1[27 + i] += t1[27 + i - 1] >> 57;
-            t1[27 + i - 1] &= 0x1ffffffffffffffl;
-        }
-        t1[27 - 1] += t1[27 - 2] >> 57;
-        t1[27 - 2] &= 0x1ffffffffffffffl;
-        d1 = t1[27 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_3072_mul_d_27(t2, d, r1);
-        sp_3072_sub_27(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 27);
-        for (i=0; i<25; i++) {
-            r[i+1] += r[i] >> 57;
-            r[i] &= 0x1ffffffffffffffl;
-        }
-        sp_3072_cond_add_27(r, r, d, 0 - (r[26] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_mod_27(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_27(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_27(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 27 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[27 * 2];
-        t[2] = &td[2 * 27 * 2];
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_27(norm, m);
-
-        if (reduceA)
-            err = sp_3072_mod_27(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 27);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_27(t[1], t[1], norm);
-        err = sp_3072_mod_27(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 27 * 2);
-            sp_3072_mont_sqr_27(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 27 * 2);
-        }
-
-        sp_3072_mont_reduce_27(t[0], m, mp);
-        n = sp_3072_cmp_27(t[0], m);
-        sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 27 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][54];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[27 * 2];
-        t[2] = &td[2 * 27 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_27(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_27(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_27(t[1], t[1], norm);
-                err = sp_3072_mod_27(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_27(t[1], a, norm);
-            err = sp_3072_mod_27(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_3072_mont_sqr_27(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_3072_mont_reduce_27(t[0], m, mp);
-        n = sp_3072_cmp_27(t[0], m);
-        sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][54];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[54];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 54, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 54;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_27(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_27(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_27(t[1], t[1], norm);
-                err = sp_3072_mod_27(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_27(t[1], a, norm);
-            err = sp_3072_mod_27(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_27(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_27(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_27(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_27(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_27(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_27(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_27(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_27(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_27(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_27(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_27(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_27(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_27(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_27(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_27(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_27(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_27(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_27(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_27(t[20], t[10], m, mp);
-        sp_3072_mont_mul_27(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_27(t[22], t[11], m, mp);
-        sp_3072_mont_mul_27(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_27(t[24], t[12], m, mp);
-        sp_3072_mont_mul_27(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_27(t[26], t[13], m, mp);
-        sp_3072_mont_mul_27(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_27(t[28], t[14], m, mp);
-        sp_3072_mont_mul_27(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_27(t[30], t[15], m, mp);
-        sp_3072_mont_mul_27(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 56) / 57) - 1;
-        c = bits % 57;
-        if (c == 0)
-            c = 57;
-        if (i < 27)
-            n = e[i--] << (64 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (7 - c);
-            c += 57;
-        }
-        y = n >> 59;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (7 - c);
-                c += 57;
-            }
-            y = (n >> 59) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_3072_mont_sqr_27(rt, rt, m, mp);
-            sp_3072_mont_sqr_27(rt, rt, m, mp);
-            sp_3072_mont_sqr_27(rt, rt, m, mp);
-            sp_3072_mont_sqr_27(rt, rt, m, mp);
-            sp_3072_mont_sqr_27(rt, rt, m, mp);
-
-            sp_3072_mont_mul_27(rt, rt, t[y], m, mp);
-        }
-
-        sp_3072_mont_reduce_27(rt, m, mp);
-        n = sp_3072_cmp_27(rt, m);
-        sp_3072_cond_sub_27(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_54(sp_digit* r, sp_digit* m)
-{
-    /* Set r = 2^n - 1. */
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<53; i++)
-        r[i] = 0x1ffffffffffffffl;
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = 0x1ffffffffffffffl;
-        r[i + 1] = 0x1ffffffffffffffl;
-        r[i + 2] = 0x1ffffffffffffffl;
-        r[i + 3] = 0x1ffffffffffffffl;
-        r[i + 4] = 0x1ffffffffffffffl;
-        r[i + 5] = 0x1ffffffffffffffl;
-        r[i + 6] = 0x1ffffffffffffffl;
-        r[i + 7] = 0x1ffffffffffffffl;
-    }
-    r[48] = 0x1ffffffffffffffl;
-    r[49] = 0x1ffffffffffffffl;
-    r[50] = 0x1ffffffffffffffl;
-    r[51] = 0x1ffffffffffffffl;
-    r[52] = 0x1ffffffffffffffl;
-#endif
-    r[53] = 0x7ffffffffffffl;
-
-    /* r = (2^n - 1) mod n */
-    sp_3072_sub_54(r, r, m);
-
-    /* Add one so r = 2^n mod m */
-    r[0] += 1;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_3072_cmp_54(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=53; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    int i;
-
-    r |= (a[53] - b[53]) & (0 - !r);
-    r |= (a[52] - b[52]) & (0 - !r);
-    r |= (a[51] - b[51]) & (0 - !r);
-    r |= (a[50] - b[50]) & (0 - !r);
-    r |= (a[49] - b[49]) & (0 - !r);
-    r |= (a[48] - b[48]) & (0 - !r);
-    for (i = 40; i >= 0; i -= 8) {
-        r |= (a[i + 7] - b[i + 7]) & (0 - !r);
-        r |= (a[i + 6] - b[i + 6]) & (0 - !r);
-        r |= (a[i + 5] - b[i + 5]) & (0 - !r);
-        r |= (a[i + 4] - b[i + 4]) & (0 - !r);
-        r |= (a[i + 3] - b[i + 3]) & (0 - !r);
-        r |= (a[i + 2] - b[i + 2]) & (0 - !r);
-        r |= (a[i + 1] - b[i + 1]) & (0 - !r);
-        r |= (a[i + 0] - b[i + 0]) & (0 - !r);
-    }
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_sub_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 54; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = a[i + 0] - (b[i + 0] & m);
-        r[i + 1] = a[i + 1] - (b[i + 1] & m);
-        r[i + 2] = a[i + 2] - (b[i + 2] & m);
-        r[i + 3] = a[i + 3] - (b[i + 3] & m);
-        r[i + 4] = a[i + 4] - (b[i + 4] & m);
-        r[i + 5] = a[i + 5] - (b[i + 5] & m);
-        r[i + 6] = a[i + 6] - (b[i + 6] & m);
-        r[i + 7] = a[i + 7] - (b[i + 7] & m);
-    }
-    r[48] = a[48] - (b[48] & m);
-    r[49] = a[49] - (b[49] & m);
-    r[50] = a[50] - (b[50] & m);
-    r[51] = a[51] - (b[51] & m);
-    r[52] = a[52] - (b[52] & m);
-    r[53] = a[53] - (b[53] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_add_54(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 54; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[54] += t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 48; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[49]; r[49] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[50]; r[50] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    t[3] = tb * a[51]; r[51] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-    t[4] = tb * a[52]; r[52] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-    t[5] = tb * a[53]; r[53] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-    r[54] +=  t[5] >> 57;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Normalize the values in each word to 57.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_3072_norm_54(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 53; i++) {
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-#else
-    int i;
-    for (i = 0; i < 48; i += 8) {
-        a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl;
-        a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl;
-        a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl;
-        a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl;
-        a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl;
-        a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl;
-        a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl;
-        a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl;
-        a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl;
-    }
-    a[48+1] += a[48] >> 57;
-    a[48] &= 0x1ffffffffffffffl;
-    a[49+1] += a[49] >> 57;
-    a[49] &= 0x1ffffffffffffffl;
-    a[50+1] += a[50] >> 57;
-    a[50] &= 0x1ffffffffffffffl;
-    a[51+1] += a[51] >> 57;
-    a[51] &= 0x1ffffffffffffffl;
-    a[52+1] += a[52] >> 57;
-    a[52] &= 0x1ffffffffffffffl;
-#endif
-}
-
-/* Shift the result in the high 3072 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_3072_mont_shift_54(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    int128_t n = a[53] >> 51;
-    n += ((int128_t)a[54]) << 6;
-
-    for (i = 0; i < 53; i++) {
-        r[i] = n & 0x1ffffffffffffffl;
-        n >>= 57;
-        n += ((int128_t)a[55 + i]) << 6;
-    }
-    r[53] = (sp_digit)n;
-#else
-    int i;
-    int128_t n = a[53] >> 51;
-    n += ((int128_t)a[54]) << 6;
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 55]) << 6;
-        r[i + 1] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 56]) << 6;
-        r[i + 2] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 57]) << 6;
-        r[i + 3] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 58]) << 6;
-        r[i + 4] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 59]) << 6;
-        r[i + 5] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 60]) << 6;
-        r[i + 6] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 61]) << 6;
-        r[i + 7] = n & 0x1ffffffffffffffl;
-        n >>= 57; n += ((int128_t)a[i + 62]) << 6;
-    }
-    r[48] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[103]) << 6;
-    r[49] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[104]) << 6;
-    r[50] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[105]) << 6;
-    r[51] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[106]) << 6;
-    r[52] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[107]) << 6;
-    r[53] = (sp_digit)n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[54], 0, sizeof(*r) * 54);
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_3072_mont_reduce_54(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<53; i++) {
-            mu = (a[i] * mp) & 0x1ffffffffffffffl;
-            sp_3072_mul_add_54(a+i, m, mu);
-            a[i+1] += a[i] >> 57;
-        }
-        mu = (a[i] * mp) & 0x7ffffffffffffl;
-        sp_3072_mul_add_54(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-    else {
-        for (i=0; i<53; i++) {
-            mu = a[i] & 0x1ffffffffffffffl;
-            sp_3072_mul_add_54(a+i, m, mu);
-            a[i+1] += a[i] >> 57;
-        }
-        mu = a[i] & 0x7ffffffffffffl;
-        sp_3072_mul_add_54(a+i, m, mu);
-        a[i+1] += a[i] >> 57;
-        a[i] &= 0x1ffffffffffffffl;
-    }
-
-    sp_3072_mont_shift_54(a, a);
-    sp_3072_cond_sub_54(a, a, m, 0 - ((a[53] >> 51) > 0));
-    sp_3072_norm_54(a);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_54(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_54(r, a, b);
-    sp_3072_mont_reduce_54(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_54(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_54(r, a);
-    sp_3072_mont_reduce_54(r, m, mp);
-}
-
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_3072_mul_d_54(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 54; i++) {
-        t += tb * a[i];
-        r[i] = t & 0x1ffffffffffffffl;
-        t >>= 57;
-    }
-    r[54] = (sp_digit)t;
-#else
-    int128_t tb = b;
-    int128_t t[8];
-    int i;
-
-    t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl;
-    for (i = 0; i < 48; i += 8) {
-        t[1] = tb * a[i+1];
-        r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-        t[2] = tb * a[i+2];
-        r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-        t[3] = tb * a[i+3];
-        r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-        t[4] = tb * a[i+4];
-        r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-        t[5] = tb * a[i+5];
-        r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-        t[6] = tb * a[i+6];
-        r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl);
-        t[7] = tb * a[i+7];
-        r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl);
-        t[0] = tb * a[i+8];
-        r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl);
-    }
-    t[1] = tb * a[49];
-    r[49] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl);
-    t[2] = tb * a[50];
-    r[50] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl);
-    t[3] = tb * a[51];
-    r[51] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl);
-    t[4] = tb * a[52];
-    r[52] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl);
-    t[5] = tb * a[53];
-    r[53] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl);
-    r[54] =  (sp_digit)(t[5] >> 57);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_3072_cond_add_54(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 54; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i + 0] = a[i + 0] + (b[i + 0] & m);
-        r[i + 1] = a[i + 1] + (b[i + 1] & m);
-        r[i + 2] = a[i + 2] + (b[i + 2] & m);
-        r[i + 3] = a[i + 3] + (b[i + 3] & m);
-        r[i + 4] = a[i + 4] + (b[i + 4] & m);
-        r[i + 5] = a[i + 5] + (b[i + 5] & m);
-        r[i + 6] = a[i + 6] + (b[i + 6] & m);
-        r[i + 7] = a[i + 7] + (b[i + 7] & m);
-    }
-    r[48] = a[48] + (b[48] & m);
-    r[49] = a[49] + (b[49] & m);
-    r[50] = a[50] + (b[50] & m);
-    r[51] = a[51] + (b[51] & m);
-    r[52] = a[52] + (b[52] & m);
-    r[53] = a[53] + (b[53] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_div_54(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int128_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[108], t2d[54 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 54 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 54;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[53];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 54);
-        for (i=53; i>=0; i--) {
-            t1[54 + i] += t1[54 + i - 1] >> 57;
-            t1[54 + i - 1] &= 0x1ffffffffffffffl;
-            d1 = t1[54 + i];
-            d1 <<= 57;
-            d1 += t1[54 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_3072_mul_d_54(t2, d, r1);
-            sp_3072_sub_54(&t1[i], &t1[i], t2);
-            t1[54 + i] -= t2[54];
-            t1[54 + i] += t1[54 + i - 1] >> 57;
-            t1[54 + i - 1] &= 0x1ffffffffffffffl;
-            r1 = (((-t1[54 + i]) << 57) - t1[54 + i - 1]) / div;
-            r1++;
-            sp_3072_mul_d_54(t2, d, r1);
-            sp_3072_add_54(&t1[i], &t1[i], t2);
-            t1[54 + i] += t1[54 + i - 1] >> 57;
-            t1[54 + i - 1] &= 0x1ffffffffffffffl;
-        }
-        t1[54 - 1] += t1[54 - 2] >> 57;
-        t1[54 - 2] &= 0x1ffffffffffffffl;
-        d1 = t1[54 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_3072_mul_d_54(t2, d, r1);
-        sp_3072_sub_54(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 54);
-        for (i=0; i<52; i++) {
-            r[i+1] += r[i] >> 57;
-            r[i] &= 0x1ffffffffffffffl;
-        }
-        sp_3072_cond_add_54(r, r, d, 0 - (r[53] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_3072_mod_54(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_54(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_54(sp_digit* r, sp_digit* a, sp_digit* e, int bits,
-    sp_digit* m, int reduceA)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* td;
-    sp_digit* t[3];
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3 * 54 * 2);
-
-        norm = t[0] = td;
-        t[1] = &td[54 * 2];
-        t[2] = &td[2 * 54 * 2];
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_54(norm, m);
-
-        if (reduceA)
-            err = sp_3072_mod_54(t[1], a, m);
-        else
-            XMEMCPY(t[1], a, sizeof(sp_digit) * 54);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_54(t[1], t[1], norm);
-        err = sp_3072_mod_54(t[1], t[1], m);
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(*t[2]) * 54 * 2);
-            sp_3072_mont_sqr_54(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(*t[2]) * 54 * 2);
-        }
-
-        sp_3072_mont_reduce_54(t[0], m, mp);
-        n = sp_3072_cmp_54(t[0], m);
-        sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(*r) * 54 * 2);
-
-    }
-
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[3][108];
-#else
-    sp_digit* td;
-    sp_digit* t[3];
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        t[0] = td;
-        t[1] = &td[54 * 2];
-        t[2] = &td[2 * 54 * 2];
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_54(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_54(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_54(t[1], t[1], norm);
-                err = sp_3072_mod_54(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_54(t[1], a, norm);
-            err = sp_3072_mod_54(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        i = bits / 57;
-        c = bits % 57;
-        n = e[i--] << (57 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = e[i--];
-                c = 57;
-            }
-
-            y = (n >> 56) & 1;
-            n <<= 1;
-
-            sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                 ((size_t)t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_3072_mont_sqr_54(t[2], t[2], m, mp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                           ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2]));
-        }
-
-        sp_3072_mont_reduce_54(t[0], m, mp);
-        n = sp_3072_cmp_54(t[0], m);
-        sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1);
-        XMEMCPY(r, t[0], sizeof(t[0]));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][108];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit rt[108];
-    sp_digit mp = 1;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 108, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 108;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_54(norm, m);
-
-        if (reduceA) {
-            err = sp_3072_mod_54(t[1], a, m);
-            if (err == MP_OKAY) {
-                sp_3072_mul_54(t[1], t[1], norm);
-                err = sp_3072_mod_54(t[1], t[1], m);
-            }
-        }
-        else {
-            sp_3072_mul_54(t[1], a, norm);
-            err = sp_3072_mod_54(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_54(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_54(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_54(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_54(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_54(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_54(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_54(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_54(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_54(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_54(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_54(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_54(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_54(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_54(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_54(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_54(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_54(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_54(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_54(t[20], t[10], m, mp);
-        sp_3072_mont_mul_54(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_54(t[22], t[11], m, mp);
-        sp_3072_mont_mul_54(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_54(t[24], t[12], m, mp);
-        sp_3072_mont_mul_54(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_54(t[26], t[13], m, mp);
-        sp_3072_mont_mul_54(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_54(t[28], t[14], m, mp);
-        sp_3072_mont_mul_54(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_54(t[30], t[15], m, mp);
-        sp_3072_mont_mul_54(t[31], t[16], t[15], m, mp);
-
-        bits = ((bits + 4) / 5) * 5;
-        i = ((bits + 56) / 57) - 1;
-        c = bits % 57;
-        if (c == 0)
-            c = 57;
-        if (i < 54)
-            n = e[i--] << (64 - c);
-        else {
-            n = 0;
-            i--;
-        }
-        if (c < 5) {
-            n |= e[i--] << (7 - c);
-            c += 57;
-        }
-        y = n >> 59;
-        n <<= 5;
-        c -= 5;
-        XMEMCPY(rt, t[y], sizeof(rt));
-        for (; i>=0 || c>=5; ) {
-            if (c < 5) {
-                n |= e[i--] << (7 - c);
-                c += 57;
-            }
-            y = (n >> 59) & 0x1f;
-            n <<= 5;
-            c -= 5;
-
-            sp_3072_mont_sqr_54(rt, rt, m, mp);
-            sp_3072_mont_sqr_54(rt, rt, m, mp);
-            sp_3072_mont_sqr_54(rt, rt, m, mp);
-            sp_3072_mont_sqr_54(rt, rt, m, mp);
-            sp_3072_mont_sqr_54(rt, rt, m, mp);
-
-            sp_3072_mont_mul_54(rt, rt, t[y], m, mp);
-        }
-
-        sp_3072_mont_reduce_54(rt, m, mp);
-        n = sp_3072_cmp_54(rt, m);
-        sp_3072_cond_sub_54(rt, rt, m, (n < 0) - 1);
-        XMEMCPY(r, rt, sizeof(rt));
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \
-                                    !defined(RSA_LOW_MEM)
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_27(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<27; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-    r[24] = a[24] & m;
-    r[25] = a[25] & m;
-    r[26] = a[26] & m;
-#endif
-}
-
-#endif
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* d = NULL;
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit* norm;
-    sp_digit e[1];
-    sp_digit mp;
-    int i;
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 54 * 2;
-        m = r + 54 * 2;
-        norm = r;
-
-        sp_3072_from_bin(a, 54, in, inLen);
-#if DIGIT_BIT >= 57
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 54, mm);
-
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_54(norm, m);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_mul_54(a, a, norm);
-        err = sp_3072_mod_54(a, a, m);
-    }
-    if (err == MP_OKAY) {
-        for (i=56; i>=0; i--)
-            if (e[0] >> i)
-                break;
-
-        XMEMCPY(r, a, sizeof(sp_digit) * 54 * 2);
-        for (i--; i>=0; i--) {
-            sp_3072_mont_sqr_54(r, r, m, mp);
-
-            if (((e[0] >> i) & 1) == 1)
-                sp_3072_mont_mul_54(r, r, a, m, mp);
-        }
-        sp_3072_mont_reduce_54(r, m, mp);
-        mp = sp_3072_cmp_54(r, m);
-        sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return err;
-#else
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[108], md[54], rd[108];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 54 * 2;
-        m = r + 54 * 2;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 54, in, inLen);
-#if DIGIT_BIT >= 57
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 54, mm);
-
-        if (e[0] == 0x3) {
-            if (err == MP_OKAY) {
-                sp_3072_sqr_54(r, a);
-                err = sp_3072_mod_54(r, r, m);
-            }
-            if (err == MP_OKAY) {
-                sp_3072_mul_54(r, a, r);
-                err = sp_3072_mod_54(r, r, m);
-            }
-        }
-        else {
-            sp_digit* norm = r;
-            int i;
-            sp_digit mp;
-
-            sp_3072_mont_setup(m, &mp);
-            sp_3072_mont_norm_54(norm, m);
-
-            if (err == MP_OKAY) {
-                sp_3072_mul_54(a, a, norm);
-                err = sp_3072_mod_54(a, a, m);
-            }
-
-            if (err == MP_OKAY) {
-                for (i=56; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 108);
-                for (i--; i>=0; i--) {
-                    sp_3072_mont_sqr_54(r, r, m, mp);
-
-                    if (((e[0] >> i) & 1) == 1)
-                        sp_3072_mont_mul_54(r, r, a, m, mp);
-                }
-                sp_3072_mont_reduce_54(r, m, mp);
-                mp = sp_3072_cmp_54(r, m);
-                sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* a;
-    sp_digit* d = NULL;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = d + 54;
-        m = a + 54;
-        r = a;
-
-        sp_3072_from_bin(a, 54, in, inLen);
-        sp_3072_from_mp(d, 54, dm);
-        sp_3072_from_mp(m, 54, mm);
-        err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 54);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[108], d[54], m[54];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)pm;
-    (void)qm;
-    (void)dpm;
-    (void)dqm;
-    (void)qim;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 54, in, inLen);
-        sp_3072_from_mp(d, 54, dm);
-        sp_3072_from_mp(m, 54, mm);
-        err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    XMEMSET(d, 0, sizeof(sp_digit) * 54);
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#else
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* t = NULL;
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 54 * 2;
-        q = p + 27;
-        qi = dq = dp = q + 27;
-        tmpa = qi + 27;
-        tmpb = tmpa + 54;
-
-        tmp = t;
-        r = tmp + 54;
-
-        sp_3072_from_bin(a, 54, in, inLen);
-        sp_3072_from_mp(p, 27, pm);
-        sp_3072_from_mp(q, 27, qm);
-        sp_3072_from_mp(dp, 27, dpm);
-        err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(dq, 27, dqm);
-        err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_sub_27(tmpa, tmpa, tmpb);
-        sp_3072_mask_27(tmp, p, tmpa[26] >> 63);
-        sp_3072_add_27(tmpa, tmpa, tmp);
-
-        sp_3072_from_mp(qi, 27, qim);
-        sp_3072_mul_27(tmpa, tmpa, qi);
-        err = sp_3072_mod_27(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_27(tmpa, q, tmpa);
-        sp_3072_add_54(r, tmpb, tmpa);
-        sp_3072_norm_54(r);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 27 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-#else
-    sp_digit a[54 * 2];
-    sp_digit p[27], q[27], dp[27], dq[27], qi[27];
-    sp_digit tmp[54], tmpa[54], tmpb[54];
-    sp_digit* r = a;
-    int err = MP_OKAY;
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 54, in, inLen);
-        sp_3072_from_mp(p, 27, pm);
-        sp_3072_from_mp(q, 27, qm);
-        sp_3072_from_mp(dp, 27, dpm);
-        sp_3072_from_mp(dq, 27, dqm);
-        sp_3072_from_mp(qi, 27, qim);
-
-        err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY)
-        err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1);
-
-    if (err == MP_OKAY) {
-        sp_3072_sub_27(tmpa, tmpa, tmpb);
-        sp_3072_mask_27(tmp, p, tmpa[26] >> 63);
-        sp_3072_add_27(tmpa, tmpa, tmp);
-        sp_3072_mul_27(tmpa, tmpa, qi);
-        err = sp_3072_mod_27(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mul_27(tmpa, tmpa, q);
-        sp_3072_add_54(r, tmpb, tmpa);
-        sp_3072_norm_54(r);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-    XMEMSET(tmpa, 0, sizeof(tmpa));
-    XMEMSET(tmpb, 0, sizeof(tmpb));
-    XMEMSET(p, 0, sizeof(p));
-    XMEMSET(q, 0, sizeof(q));
-    XMEMSET(dp, 0, sizeof(dp));
-    XMEMSET(dq, 0, sizeof(dq));
-    XMEMSET(qi, 0, sizeof(qi));
-
-    return err;
-#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */
-#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
-}
-
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_3072_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 57
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 54);
-        r->used = 54;
-        mp_clamp(r);
-#elif DIGIT_BIT < 57
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 54; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 57) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 57 - s;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 54; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 57 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 57 - s;
-            }
-            else
-                s += 57;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 54 * 2;
-        m = e + 54;
-        r = b;
-
-        sp_3072_from_mp(b, 54, base);
-        sp_3072_from_mp(e, 54, exp);
-        sp_3072_from_mp(m, 54, mod);
-
-        err = sp_3072_mod_exp_54(r, b, e, mp_count_bits(exp), m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 54);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[108], ed[54], md[54];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    int err = MP_OKAY;
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 54 * 2;
-        m = e + 54;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 54, base);
-        sp_3072_from_mp(e, 54, exp);
-        sp_3072_from_mp(m, 54, mod);
-
-        err = sp_3072_mod_exp_54(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 54);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 384 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int err = MP_OKAY;
-    sp_digit* d = NULL;
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 54 * 2;
-        m = e + 54;
-        r = b;
-
-        sp_3072_from_mp(b, 54, base);
-        sp_3072_from_bin(e, 54, exp, expLen);
-        sp_3072_from_mp(m, 54, mod);
-
-        err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    if (d != NULL) {
-        XMEMSET(e, 0, sizeof(sp_digit) * 54);
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    return err;
-#else
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit bd[108], ed[54], md[54];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* b;
-    sp_digit* e;
-    sp_digit* m;
-    sp_digit* r;
-    word32 i;
-    int err = MP_OKAY;
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        b = d;
-        e = b + 54 * 2;
-        m = e + 54;
-        r = b;
-    }
-#else
-    r = b = bd;
-    e = ed;
-    m = md;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 54, base);
-        sp_3072_from_bin(e, 54, exp, expLen);
-        sp_3072_from_mp(m, 54, mod);
-
-        err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(sp_digit) * 54);
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-#endif
-}
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_3072 */
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-
-/* Point structure to use. */
-typedef struct sp_point {
-    sp_digit x[2 * 5];
-    sp_digit y[2 * 5];
-    sp_digit z[2 * 5];
-    int infinity;
-} sp_point;
-
-/* The modulus (prime) of the curve P256. */
-static sp_digit p256_mod[5] = {
-    0xfffffffffffffl,0x00fffffffffffl,0x0000000000000l,0x0001000000000l,
-    0x0ffffffff0000l
-};
-#ifndef WOLFSSL_SP_SMALL
-/* The Montogmery normalizer for modulus of the curve P256. */
-static sp_digit p256_norm_mod[5] = {
-    0x0000000000001l,0xff00000000000l,0xfffffffffffffl,0xfffefffffffffl,
-    0x000000000ffffl
-};
-#endif /* WOLFSSL_SP_SMALL */
-/* The Montogmery multiplier for modulus of the curve P256. */
-static sp_digit p256_mp_mod = 0x0000000000001;
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
-                                            defined(HAVE_ECC_VERIFY)
-/* The order of the curve P256. */
-static sp_digit p256_order[5] = {
-    0x9cac2fc632551l,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl,
-    0x0ffffffff0000l
-};
-#endif
-/* The order of the curve P256 minus 2. */
-static sp_digit p256_order2[5] = {
-    0x9cac2fc63254fl,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl,
-    0x0ffffffff0000l
-};
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery normalizer for order of the curve P256. */
-static sp_digit p256_norm_order[5] = {
-    0x6353d039cdaafl,0x5258e8617b0c4l,0x0000000431905l,0xffff000000000l,
-    0x000000000ffffl
-};
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery multiplier for order of the curve P256. */
-static sp_digit p256_mp_order = 0x1c8aaee00bc4fl;
-#endif
-/* The base point of curve P256. */
-static sp_point p256_base = {
-    /* X ordinate */
-    {
-        0x13945d898c296l,0x812deb33a0f4al,0x3a440f277037dl,0x4247f8bce6e56l,
-        0x06b17d1f2e12cl
-    },
-    /* Y ordinate */
-    {
-        0x6406837bf51f5l,0x576b315ececbbl,0xc0f9e162bce33l,0x7f9b8ee7eb4a7l,
-        0x04fe342e2fe1al
-    },
-    /* Z ordinate */
-    {
-        0x0000000000001l,0x0000000000000l,0x0000000000000l,0x0000000000000l,
-        0x0000000000000l
-    },
-    /* infinity */
-    0
-};
-#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
-static sp_digit p256_b[5] = {
-    0xe3c3e27d2604bl,0xb0cc53b0f63bcl,0x69886bc651d06l,0x93e7b3ebbd557l,
-    0x05ac635d8aa3al
-};
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* Allocate memory for point and return error. */
-#define sp_ecc_point_new(heap, sp, p)                                   \
-    ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \
-        MEMORY_E : MP_OKAY
-#else
-/* Set pointer to data and return no error. */
-#define sp_ecc_point_new(heap, sp, p)   ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* If valid pointer then clear point data if requested and free data. */
-#define sp_ecc_point_free(p, clear, heap)     \
-    do {                                      \
-        if (p != NULL) {                      \
-            if (clear)                        \
-                XMEMSET(p, 0, sizeof(*p));    \
-            XFREE(p, heap, DYNAMIC_TYPE_ECC); \
-        }                                     \
-    }                                         \
-    while (0)
-#else
-/* Clear point data if requested. */
-#define sp_ecc_point_free(p, clear, heap) \
-    do {                                  \
-        if (clear)                        \
-            XMEMSET(p, 0, sizeof(*p));    \
-    }                                     \
-    while (0)
-#endif
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r  The resulting Montgomery form number.
- * a  The number to convert.
- * m  The modulus (prime).
- * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mod_mul_norm_5(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    int64_t* td;
-#else
-    int64_t td[8];
-    int64_t a32d[8];
-#endif
-    int64_t* t;
-    int64_t* a32;
-    int64_t o;
-    int err = MP_OKAY;
-
-    (void)m;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
-    if (td != NULL) {
-        t = td;
-        a32 = td + 8;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t = td;
-    a32 = a32d;
-#endif
-
-    if (err == MP_OKAY) {
-        a32[0] = (sp_digit)(a[0]) & 0xffffffff;
-        a32[1] = (sp_digit)(a[0] >> 32);
-        a32[1] |= a[1] << 20;
-        a32[1] &= 0xffffffff;
-        a32[2] = (sp_digit)(a[1] >> 12) & 0xffffffff;
-        a32[3] = (sp_digit)(a[1] >> 44);
-        a32[3] |= a[2] << 8;
-        a32[3] &= 0xffffffff;
-        a32[4] = (sp_digit)(a[2] >> 24);
-        a32[4] |= a[3] << 28;
-        a32[4] &= 0xffffffff;
-        a32[5] = (sp_digit)(a[3] >> 4) & 0xffffffff;
-        a32[6] = (sp_digit)(a[3] >> 36);
-        a32[6] |= a[4] << 16;
-        a32[6] &= 0xffffffff;
-        a32[7] = (sp_digit)(a[4] >> 16) & 0xffffffff;
-
-        /*  1  1  0 -1 -1 -1 -1  0 */
-        t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
-        /*  0  1  1  0 -1 -1 -1 -1 */
-        t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
-        /*  0  0  1  1  0 -1 -1 -1 */
-        t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
-        /* -1 -1  0  2  2  1  0 -1 */
-        t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
-        /*  0 -1 -1  0  2  2  1  0 */
-        t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
-        /*  0  0 -1 -1  0  2  2  1 */
-        t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
-        /* -1 -1  0  0  0  1  3  2 */
-        t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
-        /*  1  0 -1 -1 -1 -1  0  3 */
-        t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
-        t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-        t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-        t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-        t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-        t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-        t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-        t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-        o     = t[7] >> 32; t[7] &= 0xffffffff;
-        t[0] += o;
-        t[3] -= o;
-        t[6] -= o;
-        t[7] += o;
-        t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-        t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-        t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-        t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-        t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-        t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-        t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-
-        r[0] = t[0];
-        r[0] |= t[1] << 32;
-        r[0] &= 0xfffffffffffffl;
-        r[1] = (sp_digit)(t[1] >> 20);
-        r[1] |= t[2] << 12;
-        r[1] |= t[3] << 44;
-        r[1] &= 0xfffffffffffffl;
-        r[2] = (sp_digit)(t[3] >> 8);
-        r[2] |= t[4] << 24;
-        r[2] &= 0xfffffffffffffl;
-        r[3] = (sp_digit)(t[4] >> 28);
-        r[3] |= t[5] << 4;
-        r[3] |= t[6] << 36;
-        r[3] &= 0xfffffffffffffl;
-        r[4] = (sp_digit)(t[6] >> 16);
-        r[4] |= t[7] << 16;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 52
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 52
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xfffffffffffffl;
-        s = 52 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 52 <= DIGIT_BIT) {
-            s += 52;
-            r[j] &= 0xfffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 52) {
-            r[j] &= 0xfffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 52 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point.
- *
- * p   Point of type sp_point (result).
- * pm  Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_5(sp_point* p, ecc_point* pm)
-{
-    XMEMSET(p->x, 0, sizeof(p->x));
-    XMEMSET(p->y, 0, sizeof(p->y));
-    XMEMSET(p->z, 0, sizeof(p->z));
-    sp_256_from_mp(p->x, 5, pm->x);
-    sp_256_from_mp(p->y, 5, pm->y);
-    sp_256_from_mp(p->z, 5, pm->z);
-    p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_256_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 52
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 5);
-        r->used = 5;
-        mp_clamp(r);
-#elif DIGIT_BIT < 52
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 5; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 52) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 52 - s;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 5; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 52 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 52 - s;
-            }
-            else
-                s += 52;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Convert a point of type sp_point to type ecc_point.
- *
- * p   Point of type sp_point.
- * pm  Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_5(sp_point* p, ecc_point* pm)
-{
-    int err;
-
-    err = sp_256_to_mp(p->x, pm->x);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pm->y);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pm->z);
-
-    return err;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static sp_digit sp_256_cmp_5(const sp_digit* a, const sp_digit* b)
-{
-    sp_digit r = 0;
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=4; i>=0; i--)
-        r |= (a[i] - b[i]) & (0 - !r);
-#else
-    r |= (a[ 4] - b[ 4]) & (0 - !r);
-    r |= (a[ 3] - b[ 3]) & (0 - !r);
-    r |= (a[ 2] - b[ 2]) & (0 - !r);
-    r |= (a[ 1] - b[ 1]) & (0 - !r);
-    r |= (a[ 0] - b[ 0]) & (0 - !r);
-#endif /* WOLFSSL_SP_SMALL */
-
-    return r;
-}
-
-/* Normalize the values in each word to 52.
- *
- * a  Array of sp_digit to normalize.
- */
-static void sp_256_norm_5(sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    for (i = 0; i < 4; i++) {
-        a[i+1] += a[i] >> 52;
-        a[i] &= 0xfffffffffffffl;
-    }
-#else
-    a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffl;
-    a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffl;
-    a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffl;
-    a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffl;
-#endif
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static void sp_256_cond_sub_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 5; i++)
-        r[i] = a[i] - (b[i] & m);
-#else
-    r[ 0] = a[ 0] - (b[ 0] & m);
-    r[ 1] = a[ 1] - (b[ 1] & m);
-    r[ 2] = a[ 2] - (b[ 2] & m);
-    r[ 3] = a[ 3] - (b[ 3] & m);
-    r[ 4] = a[ 4] - (b[ 4] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Mul a by scalar b and add into r. (r += a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_256_mul_add_5(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 5; i++) {
-        t += (tb * a[i]) + r[i];
-        r[i] = t & 0xfffffffffffffl;
-        t >>= 52;
-    }
-    r[5] += t;
-#else
-    int128_t tb = b;
-    int128_t t[5];
-
-    t[ 0] = tb * a[ 0];
-    t[ 1] = tb * a[ 1];
-    t[ 2] = tb * a[ 2];
-    t[ 3] = tb * a[ 3];
-    t[ 4] = tb * a[ 4];
-    r[ 0] +=                 (t[ 0] & 0xfffffffffffffl);
-    r[ 1] += (t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl);
-    r[ 2] += (t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl);
-    r[ 3] += (t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl);
-    r[ 4] += (t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl);
-    r[ 5] +=  t[ 4] >> 52;
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Shift the result in the high 256 bits down to the bottom.
- *
- * r  A single precision number.
- * a  A single precision number.
- */
-static void sp_256_mont_shift_5(sp_digit* r, const sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-    word64 n;
-
-    n = a[4] >> 48;
-    for (i = 0; i < 4; i++) {
-        n += a[5 + i] << 4;
-        r[i] = n & 0xfffffffffffffl;
-        n >>= 52;
-    }
-    n += a[9] << 4;
-    r[4] = n;
-#else
-    word64 n;
-
-    n  = a[4] >> 48;
-    n += a[ 5] << 4; r[ 0] = n & 0xfffffffffffffl; n >>= 52;
-    n += a[ 6] << 4; r[ 1] = n & 0xfffffffffffffl; n >>= 52;
-    n += a[ 7] << 4; r[ 2] = n & 0xfffffffffffffl; n >>= 52;
-    n += a[ 8] << 4; r[ 3] = n & 0xfffffffffffffl; n >>= 52;
-    n += a[ 9] << 4; r[ 4] = n;
-#endif /* WOLFSSL_SP_SMALL */
-    XMEMSET(&r[5], 0, sizeof(*r) * 5);
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-static void sp_256_mont_reduce_5(sp_digit* a, sp_digit* m, sp_digit mp)
-{
-    int i;
-    sp_digit mu;
-
-    if (mp != 1) {
-        for (i=0; i<4; i++) {
-            mu = (a[i] * mp) & 0xfffffffffffffl;
-            sp_256_mul_add_5(a+i, m, mu);
-            a[i+1] += a[i] >> 52;
-        }
-        mu = (a[i] * mp) & 0xffffffffffffl;
-        sp_256_mul_add_5(a+i, m, mu);
-        a[i+1] += a[i] >> 52;
-        a[i] &= 0xfffffffffffffl;
-    }
-    else {
-        for (i=0; i<4; i++) {
-            mu = a[i] & 0xfffffffffffffl;
-            sp_256_mul_add_5(a+i, p256_mod, mu);
-            a[i+1] += a[i] >> 52;
-        }
-        mu = a[i] & 0xffffffffffffl;
-        sp_256_mul_add_5(a+i, p256_mod, mu);
-        a[i+1] += a[i] >> 52;
-        a[i] &= 0xfffffffffffffl;
-    }
-
-    sp_256_mont_shift_5(a, a);
-    sp_256_cond_sub_5(a, a, m, 0 - ((a[4] >> 48) > 0));
-    sp_256_norm_5(a);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[4]) * b[4];
-    r[9] = (sp_digit)(c >> 52);
-    c = (c & 0xfffffffffffffl) << 52;
-    for (k = 7; k >= 0; k--) {
-        for (i = 4; i >= 0; i--) {
-            j = k - i;
-            if (j >= 5)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * b[j];
-        }
-        r[k + 2] += c >> 104;
-        r[k + 1] = (c >> 52) & 0xfffffffffffffl;
-        c = (c & 0xfffffffffffffl) << 52;
-    }
-    r[0] = (sp_digit)(c >> 52);
-}
-
-#else
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    int128_t t0   = ((int128_t)a[ 0]) * b[ 0];
-    int128_t t1   = ((int128_t)a[ 0]) * b[ 1]
-                 + ((int128_t)a[ 1]) * b[ 0];
-    int128_t t2   = ((int128_t)a[ 0]) * b[ 2]
-                 + ((int128_t)a[ 1]) * b[ 1]
-                 + ((int128_t)a[ 2]) * b[ 0];
-    int128_t t3   = ((int128_t)a[ 0]) * b[ 3]
-                 + ((int128_t)a[ 1]) * b[ 2]
-                 + ((int128_t)a[ 2]) * b[ 1]
-                 + ((int128_t)a[ 3]) * b[ 0];
-    int128_t t4   = ((int128_t)a[ 0]) * b[ 4]
-                 + ((int128_t)a[ 1]) * b[ 3]
-                 + ((int128_t)a[ 2]) * b[ 2]
-                 + ((int128_t)a[ 3]) * b[ 1]
-                 + ((int128_t)a[ 4]) * b[ 0];
-    int128_t t5   = ((int128_t)a[ 1]) * b[ 4]
-                 + ((int128_t)a[ 2]) * b[ 3]
-                 + ((int128_t)a[ 3]) * b[ 2]
-                 + ((int128_t)a[ 4]) * b[ 1];
-    int128_t t6   = ((int128_t)a[ 2]) * b[ 4]
-                 + ((int128_t)a[ 3]) * b[ 3]
-                 + ((int128_t)a[ 4]) * b[ 2];
-    int128_t t7   = ((int128_t)a[ 3]) * b[ 4]
-                 + ((int128_t)a[ 4]) * b[ 3];
-    int128_t t8   = ((int128_t)a[ 4]) * b[ 4];
-
-    t1   += t0  >> 52; r[ 0] = t0  & 0xfffffffffffffl;
-    t2   += t1  >> 52; r[ 1] = t1  & 0xfffffffffffffl;
-    t3   += t2  >> 52; r[ 2] = t2  & 0xfffffffffffffl;
-    t4   += t3  >> 52; r[ 3] = t3  & 0xfffffffffffffl;
-    t5   += t4  >> 52; r[ 4] = t4  & 0xfffffffffffffl;
-    t6   += t5  >> 52; r[ 5] = t5  & 0xfffffffffffffl;
-    t7   += t6  >> 52; r[ 6] = t6  & 0xfffffffffffffl;
-    t8   += t7  >> 52; r[ 7] = t7  & 0xfffffffffffffl;
-    r[9] = (sp_digit)(t8 >> 52);
-                       r[8] = t8 & 0xfffffffffffffl;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_mul_5(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mul_5(r, a, b);
-    sp_256_mont_reduce_5(r, m, mp);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
-{
-    int i, j, k;
-    int128_t c;
-
-    c = ((int128_t)a[4]) * a[4];
-    r[9] = (sp_digit)(c >> 52);
-    c = (c & 0xfffffffffffffl) << 52;
-    for (k = 7; k >= 0; k--) {
-        for (i = 4; i >= 0; i--) {
-            j = k - i;
-            if (j >= 5 || i <= j)
-                break;
-            if (j < 0)
-                continue;
-
-            c += ((int128_t)a[i]) * a[j] * 2;
-        }
-        if (i == j)
-           c += ((int128_t)a[i]) * a[i];
-
-        r[k + 2] += c >> 104;
-        r[k + 1] = (c >> 52) & 0xfffffffffffffl;
-        c = (c & 0xfffffffffffffl) << 52;
-    }
-    r[0] = (sp_digit)(c >> 52);
-}
-
-#else
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a)
-{
-    int128_t t0   =  ((int128_t)a[ 0]) * a[ 0];
-    int128_t t1   = (((int128_t)a[ 0]) * a[ 1]) * 2;
-    int128_t t2   = (((int128_t)a[ 0]) * a[ 2]) * 2
-                 +  ((int128_t)a[ 1]) * a[ 1];
-    int128_t t3   = (((int128_t)a[ 0]) * a[ 3]
-                 +  ((int128_t)a[ 1]) * a[ 2]) * 2;
-    int128_t t4   = (((int128_t)a[ 0]) * a[ 4]
-                 +  ((int128_t)a[ 1]) * a[ 3]) * 2
-                 +  ((int128_t)a[ 2]) * a[ 2];
-    int128_t t5   = (((int128_t)a[ 1]) * a[ 4]
-                 +  ((int128_t)a[ 2]) * a[ 3]) * 2;
-    int128_t t6   = (((int128_t)a[ 2]) * a[ 4]) * 2
-                 +  ((int128_t)a[ 3]) * a[ 3];
-    int128_t t7   = (((int128_t)a[ 3]) * a[ 4]) * 2;
-    int128_t t8   =  ((int128_t)a[ 4]) * a[ 4];
-
-    t1   += t0  >> 52; r[ 0] = t0  & 0xfffffffffffffl;
-    t2   += t1  >> 52; r[ 1] = t1  & 0xfffffffffffffl;
-    t3   += t2  >> 52; r[ 2] = t2  & 0xfffffffffffffl;
-    t4   += t3  >> 52; r[ 3] = t3  & 0xfffffffffffffl;
-    t5   += t4  >> 52; r[ 4] = t4  & 0xfffffffffffffl;
-    t6   += t5  >> 52; r[ 5] = t5  & 0xfffffffffffffl;
-    t7   += t6  >> 52; r[ 6] = t6  & 0xfffffffffffffl;
-    t8   += t7  >> 52; r[ 7] = t7  & 0xfffffffffffffl;
-    r[9] = (sp_digit)(t8 >> 52);
-                       r[8] = t8 & 0xfffffffffffffl;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_5(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_256_sqr_5(r, a);
-    sp_256_mont_reduce_5(r, m, mp);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_5(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_5(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_5(r, r, m, mp);
-}
-
-#else
-/* Mod-2 for the P256 curve. */
-static const uint64_t p256_mod_2[4] = {
-    0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000,
-    0xffffffff00000001
-};
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_5(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 5);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_5(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 5);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 5;
-    sp_digit* t3 = td + 4 * 5;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_5(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_5(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_5(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_5(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_5(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_5(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_5(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_5(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_5(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_5(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_5(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_5(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_5(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*5;
-    int64_t n;
-
-    sp_256_mont_inv_5(t1, p->z, t + 2*5);
-
-    sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_5(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 5, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_5(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_5(r->x, p256_mod);
-    sp_256_cond_sub_5(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_5(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_5(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 5, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_5(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_5(r->y, p256_mod);
-    sp_256_cond_sub_5(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_5(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 5; i++)
-        r[i] = a[i] + b[i];
-
-    return 0;
-}
-#else
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] + b[ 0];
-    r[ 1] = a[ 1] + b[ 1];
-    r[ 2] = a[ 2] + b[ 2];
-    r[ 3] = a[ 3] + b[ 3];
-    r[ 4] = a[ 4] + b[ 4];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Add two Montgomery form numbers (r = a + b % m).
- *
- * r   Result of addition.
- * a   First number to add in Montogmery form.
- * b   Second number to add in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_add_5(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    sp_256_add_5(r, a, b);
-    sp_256_norm_5(r);
-    sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0));
-    sp_256_norm_5(r);
-}
-
-/* Double a Montgomery form number (r = a + a % m).
- *
- * r   Result of doubling.
- * a   Number to double in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_dbl_5(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_add_5(r, a, a);
-    sp_256_norm_5(r);
-    sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0));
-    sp_256_norm_5(r);
-}
-
-/* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r   Result of Tripling.
- * a   Number to triple in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_tpl_5(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_add_5(r, a, a);
-    sp_256_norm_5(r);
-    sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0));
-    sp_256_norm_5(r);
-    sp_256_add_5(r, r, a);
-    sp_256_norm_5(r);
-    sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0));
-    sp_256_norm_5(r);
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    int i;
-
-    for (i = 0; i < 5; i++)
-        r[i] = a[i] - b[i];
-
-    return 0;
-}
-
-#else
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    r[ 0] = a[ 0] - b[ 0];
-    r[ 1] = a[ 1] - b[ 1];
-    r[ 2] = a[ 2] - b[ 2];
-    r[ 3] = a[ 3] - b[ 3];
-    r[ 4] = a[ 4] - b[ 4];
-
-    return 0;
-}
-
-#endif /* WOLFSSL_SP_SMALL */
-/* Conditionally add a and b using the mask m.
- * m is -1 to add and 0 when not.
- *
- * r  A single precision number representing conditional add result.
- * a  A single precision number to add with.
- * b  A single precision number to add.
- * m  Mask value to apply.
- */
-static void sp_256_cond_add_5(sp_digit* r, const sp_digit* a,
-        const sp_digit* b, const sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i = 0; i < 5; i++)
-        r[i] = a[i] + (b[i] & m);
-#else
-    r[ 0] = a[ 0] + (b[ 0] & m);
-    r[ 1] = a[ 1] + (b[ 1] & m);
-    r[ 2] = a[ 2] + (b[ 2] & m);
-    r[ 3] = a[ 3] + (b[ 3] & m);
-    r[ 4] = a[ 4] + (b[ 4] & m);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r   Result of subtration.
- * a   Number to subtract from in Montogmery form.
- * b   Number to subtract with in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_sub_5(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    sp_256_sub_5(r, a, b);
-    sp_256_cond_add_5(r, r, m, r[4] >> 48);
-    sp_256_norm_5(r);
-}
-
-/* Shift number left one bit.
- * Bottom bit is lost.
- *
- * r  Result of shift.
- * a  Number to shift.
- */
-SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, sp_digit* a)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<4; i++)
-        r[i] = ((a[i] >> 1) | (a[i + 1] << 51)) & 0xfffffffffffffl;
-#else
-    r[0] = ((a[0] >> 1) | (a[1] << 51)) & 0xfffffffffffffl;
-    r[1] = ((a[1] >> 1) | (a[2] << 51)) & 0xfffffffffffffl;
-    r[2] = ((a[2] >> 1) | (a[3] << 51)) & 0xfffffffffffffl;
-    r[3] = ((a[3] >> 1) | (a[4] << 51)) & 0xfffffffffffffl;
-#endif
-    r[4] = a[4] >> 1;
-}
-
-/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r  Result of division by 2.
- * a  Number to divide.
- * m  Modulus (prime).
- */
-static void sp_256_div2_5(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    sp_256_cond_add_5(r, a, m, 0 - (a[0] & 1));
-    sp_256_norm_5(r);
-    sp_256_rshift1_5(r, r);
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_5(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*5;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<5; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<5; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<5; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_5(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_5(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_5(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_5(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_5(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_5(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_5(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_5(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_5(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_5(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_5(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_5(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_5(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_5(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_5(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_5(y, y, t2, p256_mod);
-
-}
-
-/* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a  First number to compare.
- * b  Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
-static int sp_256_cmp_equal_5(const sp_digit* a, const sp_digit* b)
-{
-    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) |
-            (a[4] ^ b[4])) == 0;
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_5(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*5;
-    sp_digit* t3 = t + 4*5;
-    sp_digit* t4 = t + 6*5;
-    sp_digit* t5 = t + 8*5;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_5(t1, p256_mod, q->y);
-    sp_256_norm_5(t1);
-    if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) &
-        (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) {
-        sp_256_proj_point_dbl_5(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<5; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<5; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<5; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_5(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_5(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_5(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_5(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_5(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_5(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_5(x, x, t5, p256_mod);
-        sp_256_mont_dbl_5(t1, y, p256_mod);
-        sp_256_mont_sub_5(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_5(y, y, x, p256_mod);
-        sp_256_mont_mul_5(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_5(y, y, t5, p256_mod);
-    }
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-    sp_point* td;
-    sp_point* t[3];
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    (void)heap;
-
-    td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC);
-    if (td == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        XMEMSET(td, 0, sizeof(*td) * 3);
-
-        t[0] = &td[0];
-        t[1] = &td[1];
-        t[2] = &td[2];
-
-        /* t[0] = {0, 0, 1} * norm */
-        t[0]->infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_5(t[1]->x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t[1]->y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t[1]->z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        i = 4;
-        c = 48;
-        n = k[i--] << (52 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = k[i--];
-                c = 52;
-            }
-
-            y = (n >> 51) & 1;
-            n <<= 1;
-
-            sp_256_proj_point_add_5(t[y^1], t[0], t[1], tmp);
-
-            XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
-                                  ((size_t)t[1] & addr_mask[y])),
-                    sizeof(sp_point));
-            sp_256_proj_point_dbl_5(t[2], t[2], tmp);
-            XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
-                            ((size_t)t[1] & addr_mask[y])), t[2],
-                    sizeof(sp_point));
-        }
-
-        if (map)
-            sp_256_map_5(r, t[0], tmp);
-        else
-            XMEMCPY(r, t[0], sizeof(sp_point));
-    }
-
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5);
-        XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-    if (td != NULL) {
-        XMEMSET(td, 0, sizeof(sp_point) * 3);
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-
-    return err;
-}
-
-#elif defined(WOLFSSL_SP_CACHE_RESISTANT)
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[3];
-    sp_digit tmpd[2 * 5 * 5];
-#endif
-    sp_point* t;
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-    (void)heap;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_point td[3];
-    t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        t[0] = &td[0];
-        t[1] = &td[1];
-        t[2] = &td[2];
-
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        i = 4;
-        c = 48;
-        n = k[i--] << (52 - c);
-        for (; ; c--) {
-            if (c == 0) {
-                if (i == -1)
-                    break;
-
-                n = k[i--];
-                c = 52;
-            }
-
-            y = (n >> 51) & 1;
-            n <<= 1;
-
-            sp_256_proj_point_add_5(&t[y^1], &t[0], &t[1], tmp);
-
-            XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
-                                 ((size_t)&t[1] & addr_mask[y])), sizeof(t[2]));
-            sp_256_proj_point_dbl_5(&t[2], &t[2], tmp);
-            XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
-                           ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2]));
-        }
-
-        if (map)
-            sp_256_map_5(r, &t[0], tmp);
-        else
-            XMEMCPY(r, &t[0], sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 3);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-
-    return err;
-}
-
-#else
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry {
-    sp_digit x[5];
-    sp_digit y[5];
-    byte infinity;
-} sp_table_entry;
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_fast_5(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[16];
-    sp_point rtd;
-    sp_digit tmpd[2 * 5 * 5];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_digit* tmp;
-    sp_digit n;
-    int i;
-    int c, y;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod);
-        sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod);
-        sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod);
-        t[1].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[ 2], &t[ 1], tmp);
-        t[ 2].infinity = 0;
-        sp_256_proj_point_add_5(&t[ 3], &t[ 2], &t[ 1], tmp);
-        t[ 3].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[ 4], &t[ 2], tmp);
-        t[ 4].infinity = 0;
-        sp_256_proj_point_add_5(&t[ 5], &t[ 3], &t[ 2], tmp);
-        t[ 5].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[ 6], &t[ 3], tmp);
-        t[ 6].infinity = 0;
-        sp_256_proj_point_add_5(&t[ 7], &t[ 4], &t[ 3], tmp);
-        t[ 7].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[ 8], &t[ 4], tmp);
-        t[ 8].infinity = 0;
-        sp_256_proj_point_add_5(&t[ 9], &t[ 5], &t[ 4], tmp);
-        t[ 9].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[10], &t[ 5], tmp);
-        t[10].infinity = 0;
-        sp_256_proj_point_add_5(&t[11], &t[ 6], &t[ 5], tmp);
-        t[11].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[12], &t[ 6], tmp);
-        t[12].infinity = 0;
-        sp_256_proj_point_add_5(&t[13], &t[ 7], &t[ 6], tmp);
-        t[13].infinity = 0;
-        sp_256_proj_point_dbl_5(&t[14], &t[ 7], tmp);
-        t[14].infinity = 0;
-        sp_256_proj_point_add_5(&t[15], &t[ 8], &t[ 7], tmp);
-        t[15].infinity = 0;
-
-        i = 3;
-        n = k[i+1] << 12;
-        c = 44;
-        y = n >> 56;
-        XMEMCPY(rt, &t[y], sizeof(sp_point));
-        n <<= 8;
-        for (; i>=0 || c>=4; ) {
-            if (c < 4) {
-                n |= k[i--] << (12 - c);
-                c += 52;
-            }
-            y = (n >> 60) & 0xf;
-            n <<= 4;
-            c -= 4;
-
-            sp_256_proj_point_dbl_5(rt, rt, tmp);
-            sp_256_proj_point_dbl_5(rt, rt, tmp);
-            sp_256_proj_point_dbl_5(rt, rt, tmp);
-            sp_256_proj_point_dbl_5(rt, rt, tmp);
-
-            sp_256_proj_point_add_5(rt, rt, &t[y], tmp);
-        }
-
-        if (map)
-            sp_256_map_5(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 16);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(rt, 1, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_5(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*5;
-    sp_digit* b = t + 4*5;
-    sp_digit* t1 = t + 6*5;
-    sp_digit* t2 = t + 8*5;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<5; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<5; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<5; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_5(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_5(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_5(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_5(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_5(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_5(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_5(t1, b, p256_mod);
-        sp_256_mont_sub_5(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_5(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_5(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_5(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_5(y, b, x, p256_mod);
-        sp_256_mont_mul_5(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_5(y, y, p256_mod);
-        sp_256_mont_sub_5(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_5(y, y, p256_mod);
-}
-
-#endif /* FP_ECC */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_5(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*5;
-    sp_digit* t3 = t + 4*5;
-    sp_digit* t4 = t + 6*5;
-    sp_digit* t5 = t + 8*5;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_5(t1, p256_mod, q->y);
-    sp_256_norm_5(t1);
-    if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) &
-        (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) {
-        sp_256_proj_point_dbl_5(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<5; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<5; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<5; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_5(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_5(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_5(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_5(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_5(t1, t3, p256_mod);
-        sp_256_mont_sub_5(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_5(t3, t3, x, p256_mod);
-        sp_256_mont_mul_5(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_5(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_5(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 5;
-    sp_digit* tmp = t + 4 * 5;
-
-    sp_256_mont_inv_5(t1, a->z, tmp);
-
-    sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_5(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_5(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_5(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_5(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_5(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_5(t, t, 32, tmp);
-            sp_256_proj_to_affine_5(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_5(t, s1, s2, tmp);
-                sp_256_proj_to_affine_5(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_5(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 5 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 52] >> (x % 52)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 52] >> (x % 52)) & 1) << j;
-
-            sp_256_proj_point_dbl_5(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_5(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_5(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[5];
-    sp_digit y[5];
-    sp_table_entry table[256];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_5(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_5(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_fast_5(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 5 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_5(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_fast_5(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_5(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#endif
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * p     Point to multiply.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[5];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 5, km);
-        sp_256_point_from_ecc_point_5(point, gm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_5(point, point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_5(point, point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_5(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    /* No pre-computed values. */
-    return sp_256_ecc_mulmod_5(r, &p256_base, k, map, heap);
-}
-
-#else
-static sp_table_entry p256_table[256] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x730d418a9143cl,0xfc5fedb60179el,0x762251075ba95l,0x55c679fb732b7l,
-        0x018905f76a537l },
-      { 0x25357ce95560al,0xe4ba19e45cddfl,0xd21f3258b4ab8l,0x5d85d2e88688dl,
-        0x08571ff182588l },
-      0 },
-    /* 2 */
-    { { 0x886024147519al,0xac26b372f0202l,0x785ebc8d0981el,0x58e9a9d4a7caal,
-        0x0d953c50ddbdfl },
-      { 0x361ccfd590f8fl,0x6b44e6c9179d6l,0x2eb64cf72e962l,0x88f37fd961102l,
-        0x0863ebb7e9eb2l },
-      0 },
-    /* 3 */
-    { { 0x6b6235cdb6485l,0xa22f0a2f97785l,0xf7e300b808f0el,0x80a03e68d9544l,
-        0x000076055b5ffl },
-      { 0x4eb9b838d2010l,0xbb3243708a763l,0x42a660654014fl,0x3ee0e0e47d398l,
-        0x0830877613437l },
-      0 },
-    /* 4 */
-    { { 0x22fc516a0d2bbl,0x6c1a6234994f9l,0x7c62c8b0d5cc1l,0x667f9241cf3a5l,
-        0x02f5e6961fd1bl },
-      { 0x5c70bf5a01797l,0x4d609561925c1l,0x71fdb523d20b4l,0x0f7b04911b370l,
-        0x0f648f9168d6fl },
-      0 },
-    /* 5 */
-    { { 0x66847e137bbbcl,0x9e8a6a0bec9e5l,0x9d73463e43446l,0x0015b1c427617l,
-        0x05abe0285133dl },
-      { 0xa837cc04c7dabl,0x4c43260c0792al,0x8e6cc37573d9fl,0x73830c9315627l,
-        0x094bb725b6b6fl },
-      0 },
-    /* 6 */
-    { { 0x9b48f720f141cl,0xcd2df5bc74bbfl,0x11045c46199b3l,0xc4efdc3f61294l,
-        0x0cdd6bbcb2f7dl },
-      { 0x6700beaf436fdl,0x6db99326beccal,0x14f25226f647fl,0xe5f60c0fa7920l,
-        0x0a361bebd4bdal },
-      0 },
-    /* 7 */
-    { { 0xa2558597c13c7l,0x5f50b7c3e128al,0x3c09d1dc38d63l,0x292c07039aecfl,
-        0x0ba12ca09c4b5l },
-      { 0x08fa459f91dfdl,0x66ceea07fb9e4l,0xd780b293af43bl,0xef4b1eceb0899l,
-        0x053ebb99d701fl },
-      0 },
-    /* 8 */
-    { { 0x7ee31b0e63d34l,0x72a9e54fab4fel,0x5e7b5a4f46005l,0x4831c0493334dl,
-        0x08589fb9206d5l },
-      { 0x0f5cc6583553al,0x4ae25649e5aa7l,0x0044652087909l,0x1c4fcc9045071l,
-        0x0ebb0696d0254l },
-      0 },
-    /* 9 */
-    { { 0x6ca15ac1647c5l,0x47c4cf5799461l,0x64dfbacb8127dl,0x7da3dc666aa37l,
-        0x0eb2820cbd1b2l },
-      { 0x6f8d86a87e008l,0x9d922378f3940l,0x0ccecb2d87dfal,0xda1d56ed2e428l,
-        0x01f28289b55a7l },
-      0 },
-    /* 10 */
-    { { 0xaa0c03b89da99l,0x9eb8284022abbl,0x81c05e8a6f2d7l,0x4d6327847862bl,
-        0x0337a4b5905e5l },
-      { 0x7500d21f7794al,0xb77d6d7f613c6l,0x4cfd6e8207005l,0xfbd60a5a37810l,
-        0x00d65e0d5f4c2l },
-      0 },
-    /* 11 */
-    { { 0x09bbeb5275d38l,0x450be0a358d9dl,0x73eb2654268a7l,0xa232f0762ff49l,
-        0x0c23da24252f4l },
-      { 0x1b84f0b94520cl,0x63b05bd78e5dal,0x4d29ea1096667l,0xcff13a4dcb869l,
-        0x019de3b8cc790l },
-      0 },
-    /* 12 */
-    { { 0xa716c26c5fe04l,0x0b3bba1bdb183l,0x4cb712c3b28del,0xcbfd7432c586al,
-        0x0e34dcbd491fcl },
-      { 0x8d46baaa58403l,0x8682e97a53b40l,0x6aaa8af9a6974l,0x0f7f9e3901273l,
-        0x0e7641f447b4el },
-      0 },
-    /* 13 */
-    { { 0x53941df64ba59l,0xec0b0242fc7d7l,0x1581859d33f10l,0x57bf4f06dfc6al,
-        0x04a12df57052al },
-      { 0x6338f9439dbd0l,0xd4bde53e1fbfal,0x1f1b314d3c24bl,0xea46fd5e4ffa2l,
-        0x06af5aa93bb5bl },
-      0 },
-    /* 14 */
-    { { 0x0b69910c91999l,0x402a580491da1l,0x8cc20900a24b4l,0x40133e0094b4bl,
-        0x05fe3475a66a4l },
-      { 0x8cabdf93e7b4bl,0x1a7c23f91ab0fl,0xd1e6263292b50l,0xa91642e889aecl,
-        0x0b544e308ecfel },
-      0 },
-    /* 15 */
-    { { 0x8c6e916ddfdcel,0x66f89179e6647l,0xd4e67e12c3291l,0xc20b4e8d6e764l,
-        0x0e0b6b2bda6b0l },
-      { 0x12df2bb7efb57l,0xde790c40070d3l,0x79bc9441aac0dl,0x3774f90336ad6l,
-        0x071c023de25a6l },
-      0 },
-    /* 16 */
-    { { 0x8c244bfe20925l,0xc38fdce86762al,0xd38706391c19al,0x24f65a96a5d5dl,
-        0x061d587d421d3l },
-      { 0x673a2a37173eal,0x0853778b65e87l,0x5bab43e238480l,0xefbe10f8441e0l,
-        0x0fa11fe124621l },
-      0 },
-    /* 17 */
-    { { 0x91f2b2cb19ffdl,0x5bb1923c231c8l,0xac5ca8e01ba8dl,0xbedcb6d03d678l,
-        0x0586eb04c1f13l },
-      { 0x5c6e527e8ed09l,0x3c1819ede20c3l,0x6c652fa1e81a3l,0x4f11278fd6c05l,
-        0x019d5ac087086l },
-      0 },
-    /* 18 */
-    { { 0x9f581309a4e1fl,0x1be92700741e9l,0xfd28d20ab7de7l,0x563f26a5ef0bel,
-        0x0e7c0073f7f9cl },
-      { 0xd663a0ef59f76l,0x5420fcb0501f6l,0xa6602d4669b3bl,0x3c0ac08c1f7a7l,
-        0x0e08504fec65bl },
-      0 },
-    /* 19 */
-    { { 0x8f68da031b3cal,0x9ee6da6d66f09l,0x4f246e86d1cabl,0x96b45bfd81fa9l,
-        0x078f018825b09l },
-      { 0xefde43a25787fl,0x0d1dccac9bb7el,0x35bfc368016f8l,0x747a0cea4877bl,
-        0x043a773b87e94l },
-      0 },
-    /* 20 */
-    { { 0x77734d2b533d5l,0xf6a1bdddc0625l,0x79ec293673b8al,0x66b1577e7c9aal,
-        0x0bb6de651c3b2l },
-      { 0x9303ab65259b3l,0xd3d03a7480e7el,0xb3cfc27d6a0afl,0xb99bc5ac83d19l,
-        0x060b4619a5d18l },
-      0 },
-    /* 21 */
-    { { 0xa38e11ae5aa1cl,0x2b49e73658bd6l,0xe5f87edb8b765l,0xffcd0b130014el,
-        0x09d0f27b2aeebl },
-      { 0x246317a730a55l,0x2fddbbc83aca9l,0xc019a719c955bl,0xc48d07c1dfe0al,
-        0x0244a566d356el },
-      0 },
-    /* 22 */
-    { { 0x0394aeacf1f96l,0xa9024c271c6dbl,0x2cbd3b99f2122l,0xef692626ac1b8l,
-        0x045e58c873581l },
-      { 0xf479da38f9dbcl,0x46e888a040d3fl,0x6e0bed7a8aaf1l,0xb7a4945adfb24l,
-        0x0c040e21cc1e4l },
-      0 },
-    /* 23 */
-    { { 0xaf0006f8117b6l,0xff73a35433847l,0xd9475eb651969l,0x6ec7482b35761l,
-        0x01cdf5c97682cl },
-      { 0x775b411f04839l,0xf448de16987dbl,0x70b32197dbeacl,0xff3db2921dd1bl,
-        0x0046755f8a92dl },
-      0 },
-    /* 24 */
-    { { 0xac5d2bce8ffcdl,0x8b2fe61a82cc8l,0x202d6c70d53c4l,0xa5f3f6f161727l,
-        0x0046e5e113b83l },
-      { 0x8ff64d8007f01l,0x125af43183e7bl,0x5e1a03c7fb1efl,0x005b045c5ea63l,
-        0x06e0106c3303dl },
-      0 },
-    /* 25 */
-    { { 0x7358488dd73b1l,0x8f995ed0d948cl,0x56a2ab7767070l,0xcf1f38385ea8cl,
-        0x0442594ede901l },
-      { 0xaa2c912d4b65bl,0x3b96c90c37f8fl,0xe978d1f94c234l,0xe68ed326e4a15l,
-        0x0a796fa514c2el },
-      0 },
-    /* 26 */
-    { { 0xfb604823addd7l,0x83e56693b3359l,0xcbf3c809e2a61l,0x66e9f885b78e3l,
-        0x0e4ad2da9c697l },
-      { 0xf7f428e048a61l,0x8cc092d9a0357l,0x03ed8ef082d19l,0x5143fc3a1af4cl,
-        0x0c5e94046c37bl },
-      0 },
-    /* 27 */
-    { { 0xa538c2be75f9el,0xe8cb123a78476l,0x109c04b6fd1a9l,0x4747d85e4df0bl,
-        0x063283dafdb46l },
-      { 0x28cf7baf2df15l,0x550ad9a7f4ce7l,0x834bcc3e592c4l,0xa938fab226adel,
-        0x068bd19ab1981l },
-      0 },
-    /* 28 */
-    { { 0xead511887d659l,0xf4b359305ac08l,0xfe74fe33374d5l,0xdfd696986981cl,
-        0x0495292f53c6fl },
-      { 0x78c9e1acec896l,0x10ec5b44844a8l,0x64d60a7d964b2l,0x68376696f7e26l,
-        0x00ec7530d2603l },
-      0 },
-    /* 29 */
-    { { 0x13a05ad2687bbl,0x6af32e21fa2dal,0xdd4607ba1f83bl,0x3f0b390f5ef51l,
-        0x00f6207a66486l },
-      { 0x7e3bb0f138233l,0x6c272aa718bd6l,0x6ec88aedd66b9l,0x6dcf8ed004072l,
-        0x0ff0db07208edl },
-      0 },
-    /* 30 */
-    { { 0xfa1014c95d553l,0xfd5d680a8a749l,0xf3b566fa44052l,0x0ea3183b4317fl,
-        0x0313b513c8874l },
-      { 0x2e2ac08d11549l,0x0bb4dee21cb40l,0x7f2320e071ee1l,0x9f8126b987dd4l,
-        0x02d3abcf986f1l },
-      0 },
-    /* 31 */
-    { { 0x88501815581a2l,0x56632211af4c2l,0xcab2e999a0a6dl,0x8cdf19ba7a0f0l,
-        0x0c036fa10ded9l },
-      { 0xe08bac1fbd009l,0x9006d1581629al,0xb9e0d8f0b68b1l,0x0194c2eb32779l,
-        0x0a6b2a2c4b6d4l },
-      0 },
-    /* 32 */
-    { { 0x3e50f6d3549cfl,0x6ffacd665ed43l,0xe11fcb46f3369l,0x9860695bfdaccl,
-        0x0810ee252af7cl },
-      { 0x50fe17159bb2cl,0xbe758b357b654l,0x69fea72f7dfbel,0x17452b057e74dl,
-        0x0d485717a9273l },
-      0 },
-    /* 33 */
-    { { 0x41a8af0cb5a98l,0x931f3110bf117l,0xb382adfd3da8fl,0x604e1994e2cbal,
-        0x06a6045a72f9al },
-      { 0xc0d3fa2b2411dl,0x3e510e96e0170l,0x865b3ccbe0eb8l,0x57903bcc9f738l,
-        0x0d3e45cfaf9e1l },
-      0 },
-    /* 34 */
-    { { 0xf69bbe83f7669l,0x8272877d6bce1l,0x244278d09f8ael,0xc19c9548ae543l,
-        0x0207755dee3c2l },
-      { 0xd61d96fef1945l,0xefb12d28c387bl,0x2df64aa18813cl,0xb00d9fbcd1d67l,
-        0x048dc5ee57154l },
-      0 },
-    /* 35 */
-    { { 0x790bff7e5a199l,0xcf989ccbb7123l,0xa519c79e0efb8l,0xf445c27a2bfe0l,
-        0x0f2fb0aeddff6l },
-      { 0x09575f0b5025fl,0xd740fa9f2241cl,0x80bfbd0550543l,0xd5258fa3c8ad3l,
-        0x0a13e9015db28l },
-      0 },
-    /* 36 */
-    { { 0x7a350a2b65cbcl,0x722a464226f9fl,0x23f07a10b04b9l,0x526f265ce241el,
-        0x02bf0d6b01497l },
-      { 0x4dd3f4b216fb7l,0x67fbdda26ad3dl,0x708505cf7d7b8l,0xe89faeb7b83f6l,
-        0x042a94a5a162fl },
-      0 },
-    /* 37 */
-    { { 0x6ad0beaadf191l,0x9025a268d7584l,0x94dc1f60f8a48l,0xde3de86030504l,
-        0x02c2dd969c65el },
-      { 0x2171d93849c17l,0xba1da250dd6d0l,0xc3a5485460488l,0x6dbc4810c7063l,
-        0x0f437fa1f42c5l },
-      0 },
-    /* 38 */
-    { { 0x0d7144a0f7dabl,0x931776e9ac6aal,0x5f397860f0497l,0x7aa852c0a050fl,
-        0x0aaf45b335470l },
-      { 0x37c33c18d364al,0x063e49716585el,0x5ec5444d40b9bl,0x72bcf41716811l,
-        0x0cdf6310df4f2l },
-      0 },
-    /* 39 */
-    { { 0x3c6238ea8b7efl,0x1885bc2287747l,0xbda8e3408e935l,0x2ff2419567722l,
-        0x0f0d008bada9el },
-      { 0x2671d2414d3b1l,0x85b019ea76291l,0x53bcbdbb37549l,0x7b8b5c61b96d4l,
-        0x05bd5c2f5ca88l },
-      0 },
-    /* 40 */
-    { { 0xf469ef49a3154l,0x956e2b2e9aef0l,0xa924a9c3e85a5l,0x471945aaec1eal,
-        0x0aa12dfc8a09el },
-      { 0x272274df69f1dl,0x2ca2ff5e7326fl,0x7a9dd44e0e4c8l,0xa901b9d8ce73bl,
-        0x06c036e73e48cl },
-      0 },
-    /* 41 */
-    { { 0xae12a0f6e3138l,0x0025ad345a5cfl,0x5672bc56966efl,0xbe248993c64b4l,
-        0x0292ff65896afl },
-      { 0x50d445e213402l,0x274392c9fed52l,0xa1c72e8f6580el,0x7276097b397fdl,
-        0x0644e0c90311bl },
-      0 },
-    /* 42 */
-    { { 0x421e1a47153f0l,0x79920418c9e1el,0x05d7672b86c3bl,0x9a7793bdce877l,
-        0x0f25ae793cab7l },
-      { 0x194a36d869d0cl,0x824986c2641f3l,0x96e945e9d55c8l,0x0a3e49fb5ea30l,
-        0x039b8e65313dbl },
-      0 },
-    /* 43 */
-    { { 0x54200b6fd2e59l,0x669255c98f377l,0xe2a573935e2c0l,0xdb06d9dab21a0l,
-        0x039122f2f0f19l },
-      { 0xce1e003cad53cl,0x0fe65c17e3cfbl,0xaa13877225b2cl,0xff8d72baf1d29l,
-        0x08de80af8ce80l },
-      0 },
-    /* 44 */
-    { { 0xea8d9207bbb76l,0x7c21782758afbl,0xc0436b1921c7el,0x8c04dfa2b74b1l,
-        0x0871949062e36l },
-      { 0x928bba3993df5l,0xb5f3b3d26ab5fl,0x5b55050639d75l,0xfde1011aa78a8l,
-        0x0fc315e6a5b74l },
-      0 },
-    /* 45 */
-    { { 0xfd41ae8d6ecfal,0xf61aec7f86561l,0x924741d5f8c44l,0x908898452a7b4l,
-        0x0e6d4a7adee38l },
-      { 0x52ed14593c75dl,0xa4dd271162605l,0xba2c7db70a70dl,0xae57d2aede937l,
-        0x035dfaf9a9be2l },
-      0 },
-    /* 46 */
-    { { 0x56fcdaa736636l,0x97ae2cab7e6b9l,0xf34996609f51dl,0x0d2bfb10bf410l,
-        0x01da5c7d71c83l },
-      { 0x1e4833cce6825l,0x8ff9573c3b5c4l,0x23036b815ad11l,0xb9d6a28552c7fl,
-        0x07077c0fddbf4l },
-      0 },
-    /* 47 */
-    { { 0x3ff8d46b9661cl,0x6b0d2cfd71bf6l,0x847f8f7a1dfd3l,0xfe440373e140al,
-        0x053a8632ee50el },
-      { 0x6ff68696d8051l,0x95c74f468a097l,0xe4e26bddaec0cl,0xfcc162994dc35l,
-        0x0028ca76d34e1l },
-      0 },
-    /* 48 */
-    { { 0xd47dcfc9877eel,0x10801d0002d11l,0x4c260b6c8b362l,0xf046d002c1175l,
-        0x004c17cd86962l },
-      { 0xbd094b0daddf5l,0x7524ce55c06d9l,0x2da03b5bea235l,0x7474663356e67l,
-        0x0f7ba4de9fed9l },
-      0 },
-    /* 49 */
-    { { 0xbfa34ebe1263fl,0x3571ae7ce6d0dl,0x2a6f523557637l,0x1c41d24405538l,
-        0x0e31f96005213l },
-      { 0xb9216ea6b6ec6l,0x2e73c2fc44d1bl,0x9d0a29437a1d1l,0xd47bc10e7eac8l,
-        0x0aa3a6259ce34l },
-      0 },
-    /* 50 */
-    { { 0xf9df536f3dcd3l,0x50d2bf7360fbcl,0xf504f5b6cededl,0xdaee491710fadl,
-        0x02398dd627e79l },
-      { 0x705a36d09569el,0xbb5149f769cf4l,0x5f6034cea0619l,0x6210ff9c03773l,
-        0x05717f5b21c04l },
-      0 },
-    /* 51 */
-    { { 0x229c921dd895el,0x0040c284519fel,0xd637ecd8e5185l,0x28defa13d2391l,
-        0x0660a2c560e3cl },
-      { 0xa88aed67fcbd0l,0x780ea9f0969ccl,0x2e92b4dc84724l,0x245332b2f4817l,
-        0x0624ee54c4f52l },
-      0 },
-    /* 52 */
-    { { 0x49ce4d897ecccl,0xd93f9880aa095l,0x43a7c204d49d1l,0xfbc0723c24230l,
-        0x04f392afb92bdl },
-      { 0x9f8fa7de44fd9l,0xe457b32156696l,0x68ebc3cb66cfbl,0x399cdb2fa8033l,
-        0x08a3e7977ccdbl },
-      0 },
-    /* 53 */
-    { { 0x1881f06c4b125l,0x00f6e3ca8cddel,0xc7a13e9ae34e3l,0x4404ef6999de5l,
-        0x03888d02370c2l },
-      { 0x8035644f91081l,0x615f015504762l,0x32cd36e3d9fcfl,0x23361827edc86l,
-        0x0a5e62e471810l },
-      0 },
-    /* 54 */
-    { { 0x25ee32facd6c8l,0x5454bcbc661a8l,0x8df9931699c63l,0x5adc0ce3edf79l,
-        0x02c4768e6466al },
-      { 0x6ff8c90a64bc9l,0x20e4779f5cb34l,0xc05e884630a60l,0x52a0d949d064bl,
-        0x07b5e6441f9e6l },
-      0 },
-    /* 55 */
-    { { 0x9422c1d28444al,0xd8be136a39216l,0xb0c7fcee996c5l,0x744a2387afe5fl,
-        0x0b8af73cb0c8dl },
-      { 0xe83aa338b86fdl,0x58a58a5cff5fdl,0x0ac9433fee3f1l,0x0895c9ee8f6f2l,
-        0x0a036395f7f3fl },
-      0 },
-    /* 56 */
-    { { 0x3c6bba10f7770l,0x81a12a0e248c7l,0x1bc2b9fa6f16dl,0xb533100df6825l,
-        0x04be36b01875fl },
-      { 0x6086e9fb56dbbl,0x8b07e7a4f8922l,0x6d52f20306fefl,0x00c0eeaccc056l,
-        0x08cbc9a871bdcl },
-      0 },
-    /* 57 */
-    { { 0x1895cc0dac4abl,0x40712ff112e13l,0xa1cee57a874a4l,0x35f86332ae7c6l,
-        0x044e7553e0c08l },
-      { 0x03fff7734002dl,0x8b0b34425c6d5l,0xe8738b59d35cbl,0xfc1895f702760l,
-        0x0470a683a5eb8l },
-      0 },
-    /* 58 */
-    { { 0x761dc90513482l,0x2a01e9276a81bl,0xce73083028720l,0xc6efcda441ee0l,
-        0x016410690c63dl },
-      { 0x34a066d06a2edl,0x45189b100bf50l,0xb8218c9dd4d77l,0xbb4fd914ae72al,
-        0x0d73479fd7abcl },
-      0 },
-    /* 59 */
-    { { 0xefb165ad4c6e5l,0x8f5b06d04d7edl,0x575cb14262cf0l,0x666b12ed5bb18l,
-        0x0816469e30771l },
-      { 0xb9d79561e291el,0x22c1de1661d7al,0x35e0513eb9dafl,0x3f9cf49827eb1l,
-        0x00a36dd23f0ddl },
-      0 },
-    /* 60 */
-    { { 0xd32c741d5533cl,0x9e8684628f098l,0x349bd117c5f5al,0xb11839a228adel,
-        0x0e331dfd6fdbal },
-      { 0x0ab686bcc6ed8l,0xbdef7a260e510l,0xce850d77160c3l,0x33899063d9a7bl,
-        0x0d3b4782a492el },
-      0 },
-    /* 61 */
-    { { 0x9b6e8f3821f90l,0xed66eb7aada14l,0xa01311692edd9l,0xa5bd0bb669531l,
-        0x07281275a4c86l },
-      { 0x858f7d3ff47e5l,0xbc61016441503l,0xdfd9bb15e1616l,0x505962b0f11a7l,
-        0x02c062e7ece14l },
-      0 },
-    /* 62 */
-    { { 0xf996f0159ac2el,0x36cbdb2713a76l,0x8e46047281e77l,0x7ef12ad6d2880l,
-        0x0282a35f92c4el },
-      { 0x54b1ec0ce5cd2l,0xc91379c2299c3l,0xe82c11ecf99efl,0x2abd992caf383l,
-        0x0c71cd513554dl },
-      0 },
-    /* 63 */
-    { { 0x5de9c09b578f4l,0x58e3affa7a488l,0x9182f1f1884e2l,0xf3a38f76b1b75l,
-        0x0c50f6740cf47l },
-      { 0x4adf3374b68eal,0x2369965fe2a9cl,0x5a53050a406f3l,0x58dc2f86a2228l,
-        0x0b9ecb3a72129l },
-      0 },
-    /* 64 */
-    { { 0x8410ef4f8b16al,0xfec47b266a56fl,0xd9c87c197241al,0xab1b0a406b8e6l,
-        0x0803f3e02cd42l },
-      { 0x309a804dbec69l,0xf73bbad05f7f0l,0xd8e197fa83b85l,0xadc1c6097273al,
-        0x0c097440e5067l },
-      0 },
-    /* 65 */
-    { { 0xa56f2c379ab34l,0x8b841df8d1846l,0x76c68efa8ee06l,0x1f30203144591l,
-        0x0f1af32d5915fl },
-      { 0x375315d75bd50l,0xbaf72f67bc99cl,0x8d7723f837cffl,0x1c8b0613a4184l,
-        0x023d0f130e2d4l },
-      0 },
-    /* 66 */
-    { { 0xab6edf41500d9l,0xe5fcbeada8857l,0x97259510d890al,0xfadd52fe86488l,
-        0x0b0288dd6c0a3l },
-      { 0x20f30650bcb08l,0x13695d6e16853l,0x989aa7671af63l,0xc8d231f520a7bl,
-        0x0ffd3724ff408l },
-      0 },
-    /* 67 */
-    { { 0x68e64b458e6cbl,0x20317a5d28539l,0xaa75f56992dadl,0x26df3814ae0b7l,
-        0x0f5590f4ad78cl },
-      { 0x24bd3cf0ba55al,0x4a0c778bae0fcl,0x83b674a0fc472l,0x4a201ce9864f6l,
-        0x018d6da54f6f7l },
-      0 },
-    /* 68 */
-    { { 0x3e225d5be5a2bl,0x835934f3c6ed9l,0x2626ffc6fe799l,0x216a431409262l,
-        0x050bbb4d97990l },
-      { 0x191c6e57ec63el,0x40181dcdb2378l,0x236e0f665422cl,0x49c341a8099b0l,
-        0x02b10011801fel },
-      0 },
-    /* 69 */
-    { { 0x8b5c59b391593l,0xa2598270fcfc6l,0x19adcbbc385f5l,0xae0c7144f3aadl,
-        0x0dd55899983fbl },
-      { 0x88b8e74b82ff4l,0x4071e734c993bl,0x3c0322ad2e03cl,0x60419a7a9eaf4l,
-        0x0e6e4c551149dl },
-      0 },
-    /* 70 */
-    { { 0x655bb1e9af288l,0x64f7ada93155fl,0xb2820e5647e1al,0x56ff43697e4bcl,
-        0x051e00db107edl },
-      { 0x169b8771c327el,0x0b4a96c2ad43dl,0xdeb477929cdb2l,0x9177c07d51f53l,
-        0x0e22f42414982l },
-      0 },
-    /* 71 */
-    { { 0x5e8f4635f1abbl,0xb568538874cd4l,0x5a8034d7edc0cl,0x48c9c9472c1fbl,
-        0x0f709373d52dcl },
-      { 0x966bba8af30d6l,0x4af137b69c401l,0x361c47e95bf5fl,0x5b113966162a9l,
-        0x0bd52d288e727l },
-      0 },
-    /* 72 */
-    { { 0x55c7a9c5fa877l,0x727d3a3d48ab1l,0x3d189d817dad6l,0x77a643f43f9e7l,
-        0x0a0d0f8e4c8aal },
-      { 0xeafd8cc94f92dl,0xbe0c4ddb3a0bbl,0x82eba14d818c8l,0x6a0022cc65f8bl,
-        0x0a56c78c7946dl },
-      0 },
-    /* 73 */
-    { { 0x2391b0dd09529l,0xa63daddfcf296l,0xb5bf481803e0el,0x367a2c77351f5l,
-        0x0d8befdf8731al },
-      { 0x19d42fc0157f4l,0xd7fec8e650ab9l,0x2d48b0af51cael,0x6478cdf9cb400l,
-        0x0854a68a5ce9fl },
-      0 },
-    /* 74 */
-    { { 0x5f67b63506ea5l,0x89a4fe0d66dc3l,0xe95cd4d9286c4l,0x6a953f101d3bfl,
-        0x05cacea0b9884l },
-      { 0xdf60c9ceac44dl,0xf4354d1c3aa90l,0xd5dbabe3db29al,0xefa908dd3de8al,
-        0x0e4982d1235e4l },
-      0 },
-    /* 75 */
-    { { 0x04a22c34cd55el,0xb32680d132231l,0xfa1d94358695bl,0x0499fb345afa1l,
-        0x08046b7f616b2l },
-      { 0x3581e38e7d098l,0x8df46f0b70b53l,0x4cb78c4d7f61el,0xaf5530dea9ea4l,
-        0x0eb17ca7b9082l },
-      0 },
-    /* 76 */
-    { { 0x1b59876a145b9l,0x0fc1bc71ec175l,0x92715bba5cf6bl,0xe131d3e035653l,
-        0x0097b00bafab5l },
-      { 0x6c8e9565f69e1l,0x5ab5be5199aa6l,0xa4fd98477e8f7l,0xcc9e6033ba11dl,
-        0x0f95c747bafdbl },
-      0 },
-    /* 77 */
-    { { 0xf01d3bebae45el,0xf0c4bc6955558l,0xbc64fc6a8ebe9l,0xd837aeb705b1dl,
-        0x03512601e566el },
-      { 0x6f1e1fa1161cdl,0xd54c65ef87933l,0x24f21e5328ab8l,0xab6b4757eee27l,
-        0x00ef971236068l },
-      0 },
-    /* 78 */
-    { { 0x98cf754ca4226l,0x38f8642c8e025l,0x68e17905eede1l,0xbc9548963f744l,
-        0x0fc16d9333b4fl },
-      { 0x6fb31e7c800cal,0x312678adaabe9l,0xff3e8b5138063l,0x7a173d6244976l,
-        0x014ca4af1b95dl },
-      0 },
-    /* 79 */
-    { { 0x771babd2f81d5l,0x6901f7d1967a4l,0xad9c9071a5f9dl,0x231dd898bef7cl,
-        0x04057b063f59cl },
-      { 0xd82fe89c05c0al,0x6f1dc0df85bffl,0x35a16dbe4911cl,0x0b133befccaeal,
-        0x01c3b5d64f133l },
-      0 },
-    /* 80 */
-    { { 0x14bfe80ec21fel,0x6ac255be825fel,0xf4a5d67f6ce11l,0x63af98bc5a072l,
-        0x0fad27148db7el },
-      { 0x0b6ac29ab05b3l,0x3c4e251ae690cl,0x2aade7d37a9a8l,0x1a840a7dc875cl,
-        0x077387de39f0el },
-      0 },
-    /* 81 */
-    { { 0xecc49a56c0dd7l,0xd846086c741e9l,0x505aecea5cffcl,0xc47e8f7a1408fl,
-        0x0b37b85c0bef0l },
-      { 0x6b6e4cc0e6a8fl,0xbf6b388f23359l,0x39cef4efd6d4bl,0x28d5aba453facl,
-        0x09c135ac8f9f6l },
-      0 },
-    /* 82 */
-    { { 0xa320284e35743l,0xb185a3cdef32al,0xdf19819320d6al,0x851fb821b1761l,
-        0x05721361fc433l },
-      { 0xdb36a71fc9168l,0x735e5c403c1f0l,0x7bcd8f55f98bal,0x11bdf64ca87e3l,
-        0x0dcbac3c9e6bbl },
-      0 },
-    /* 83 */
-    { { 0xd99684518cbe2l,0x189c9eb04ef01l,0x47feebfd242fcl,0x6862727663c7el,
-        0x0b8c1c89e2d62l },
-      { 0x58bddc8e1d569l,0xc8b7d88cd051al,0x11f31eb563809l,0x22d426c27fd9fl,
-        0x05d23bbda2f94l },
-      0 },
-    /* 84 */
-    { { 0xc729495c8f8bel,0x803bf362bf0a1l,0xf63d4ac2961c4l,0xe9009e418403dl,
-        0x0c109f9cb91ecl },
-      { 0x095d058945705l,0x96ddeb85c0c2dl,0xa40449bb9083dl,0x1ee184692b8d7l,
-        0x09bc3344f2eeel },
-      0 },
-    /* 85 */
-    { { 0xae35642913074l,0x2748a542b10d5l,0x310732a55491bl,0x4cc1469ca665bl,
-        0x029591d525f1al },
-      { 0xf5b6bb84f983fl,0x419f5f84e1e76l,0x0baa189be7eefl,0x332c1200d4968l,
-        0x06376551f18efl },
-      0 },
-    /* 86 */
-    { { 0x5f14e562976ccl,0xe60ef12c38bdal,0xcca985222bca3l,0x987abbfa30646l,
-        0x0bdb79dc808e2l },
-      { 0xcb5c9cb06a772l,0xaafe536dcefd2l,0xc2b5db838f475l,0xc14ac2a3e0227l,
-        0x08ee86001add3l },
-      0 },
-    /* 87 */
-    { { 0x96981a4ade873l,0x4dc4fba48ccbel,0xa054ba57ee9aal,0xaa4b2cee28995l,
-        0x092e51d7a6f77l },
-      { 0xbafa87190a34dl,0x5bf6bd1ed1948l,0xcaf1144d698f7l,0xaaaad00ee6e30l,
-        0x05182f86f0a56l },
-      0 },
-    /* 88 */
-    { { 0x6212c7a4cc99cl,0x683e6d9ca1fbal,0xac98c5aff609bl,0xa6f25dbb27cb5l,
-        0x091dcab5d4073l },
-      { 0x6cc3d5f575a70l,0x396f8d87fa01bl,0x99817360cb361l,0x4f2b165d4e8c8l,
-        0x017a0cedb9797l },
-      0 },
-    /* 89 */
-    { { 0x61e2a076c8d3al,0x39210f924b388l,0x3a835d9701aadl,0xdf4194d0eae41l,
-        0x02e8ce36c7f4cl },
-      { 0x73dab037a862bl,0xb760e4c8fa912l,0x3baf2dd01ba9bl,0x68f3f96453883l,
-        0x0f4ccc6cb34f6l },
-      0 },
-    /* 90 */
-    { { 0xf525cf1f79687l,0x9592efa81544el,0x5c78d297c5954l,0xf3c9e1231741al,
-        0x0ac0db4889a0dl },
-      { 0xfc711df01747fl,0x58ef17df1386bl,0xccb6bb5592b93l,0x74a2e5880e4f5l,
-        0x095a64a6194c9l },
-      0 },
-    /* 91 */
-    { { 0x1efdac15a4c93l,0x738258514172cl,0x6cb0bad40269bl,0x06776a8dfb1c1l,
-        0x0231e54ba2921l },
-      { 0xdf9178ae6d2dcl,0x3f39112918a70l,0xe5b72234d6aa6l,0x31e1f627726b5l,
-        0x0ab0be032d8a7l },
-      0 },
-    /* 92 */
-    { { 0xad0e98d131f2dl,0xe33b04f101097l,0x5e9a748637f09l,0xa6791ac86196dl,
-        0x0f1bcc8802cf6l },
-      { 0x69140e8daacb4l,0x5560f6500925cl,0x77937a63c4e40l,0xb271591cc8fc4l,
-        0x0851694695aebl },
-      0 },
-    /* 93 */
-    { { 0x5c143f1dcf593l,0x29b018be3bde3l,0xbdd9d3d78202bl,0x55d8e9cdadc29l,
-        0x08f67d9d2daadl },
-      { 0x116567481ea5fl,0xe9e34c590c841l,0x5053fa8e7d2ddl,0x8b5dffdd43f40l,
-        0x0f84572b9c072l },
-      0 },
-    /* 94 */
-    { { 0xa7a7197af71c9l,0x447a7365655e1l,0xe1d5063a14494l,0x2c19a1b4ae070l,
-        0x0edee2710616bl },
-      { 0x034f511734121l,0x554a25e9f0b2fl,0x40c2ecf1cac6el,0xd7f48dc148f3al,
-        0x09fd27e9b44ebl },
-      0 },
-    /* 95 */
-    { { 0x7658af6e2cb16l,0x2cfe5919b63ccl,0x68d5583e3eb7dl,0xf3875a8c58161l,
-        0x0a40c2fb6958fl },
-      { 0xec560fedcc158l,0xc655f230568c9l,0xa307e127ad804l,0xdecfd93967049l,
-        0x099bc9bb87dc6l },
-      0 },
-    /* 96 */
-    { { 0x9521d927dafc6l,0x695c09cd1984al,0x9366dde52c1fbl,0x7e649d9581a0fl,
-        0x09abe210ba16dl },
-      { 0xaf84a48915220l,0x6a4dd816c6480l,0x681ca5afa7317l,0x44b0c7d539871l,
-        0x07881c25787f3l },
-      0 },
-    /* 97 */
-    { { 0x99b51e0bcf3ffl,0xc5127f74f6933l,0xd01d9680d02cbl,0x89408fb465a2dl,
-        0x015e6e319a30el },
-      { 0xd6e0d3e0e05f4l,0xdc43588404646l,0x4f850d3fad7bdl,0x72cebe61c7d1cl,
-        0x00e55facf1911l },
-      0 },
-    /* 98 */
-    { { 0xd9806f8787564l,0x2131e85ce67e9l,0x819e8d61a3317l,0x65776b0158cabl,
-        0x0d73d09766fe9l },
-      { 0x834251eb7206el,0x0fc618bb42424l,0xe30a520a51929l,0xa50b5dcbb8595l,
-        0x09250a3748f15l },
-      0 },
-    /* 99 */
-    { { 0xf08f8be577410l,0x035077a8c6cafl,0xc0a63a4fd408al,0x8c0bf1f63289el,
-        0x077414082c1ccl },
-      { 0x40fa6eb0991cdl,0x6649fdc29605al,0x324fd40c1ca08l,0x20b93a68a3c7bl,
-        0x08cb04f4d12ebl },
-      0 },
-    /* 100 */
-    { { 0x2d0556906171cl,0xcdb0240c3fb1cl,0x89068419073e9l,0x3b51db8e6b4fdl,
-        0x0e4e429ef4712l },
-      { 0xdd53c38ec36f4l,0x01ff4b6a270b8l,0x79a9a48f9d2dcl,0x65525d066e078l,
-        0x037bca2ff3c6el },
-      0 },
-    /* 101 */
-    { { 0x2e3c7df562470l,0xa2c0964ac94cdl,0x0c793be44f272l,0xb22a7c6d5df98l,
-        0x059913edc3002l },
-      { 0x39a835750592al,0x80e783de027a1l,0xa05d64f99e01dl,0xe226cf8c0375el,
-        0x043786e4ab013l },
-      0 },
-    /* 102 */
-    { { 0x2b0ed9e56b5a6l,0xa6d9fc68f9ff3l,0x97846a70750d9l,0x9e7aec15e8455l,
-        0x08638ca98b7e7l },
-      { 0xae0960afc24b2l,0xaf4dace8f22f5l,0xecba78f05398el,0xa6f03b765dd0al,
-        0x01ecdd36a7b3al },
-      0 },
-    /* 103 */
-    { { 0xacd626c5ff2f3l,0xc02873a9785d3l,0x2110d54a2d516l,0xf32dad94c9fadl,
-        0x0d85d0f85d459l },
-      { 0x00b8d10b11da3l,0x30a78318c49f7l,0x208decdd2c22cl,0x3c62556988f49l,
-        0x0a04f19c3b4edl },
-      0 },
-    /* 104 */
-    { { 0x924c8ed7f93bdl,0x5d392f51f6087l,0x21b71afcb64acl,0x50b07cae330a8l,
-        0x092b2eeea5c09l },
-      { 0xc4c9485b6e235l,0xa92936c0f085al,0x0508891ab2ca4l,0x276c80faa6b3el,
-        0x01ee782215834l },
-      0 },
-    /* 105 */
-    { { 0xa2e00e63e79f7l,0xb2f399d906a60l,0x607c09df590e7l,0xe1509021054a6l,
-        0x0f3f2ced857a6l },
-      { 0x510f3f10d9b55l,0xacd8642648200l,0x8bd0e7c9d2fcfl,0xe210e5631aa7el,
-        0x00f56a4543da3l },
-      0 },
-    /* 106 */
-    { { 0x1bffa1043e0dfl,0xcc9c007e6d5b2l,0x4a8517a6c74b6l,0xe2631a656ec0dl,
-        0x0bd8f17411969l },
-      { 0xbbb86beb7494al,0x6f45f3b8388a9l,0x4e5a79a1567d4l,0xfa09df7a12a7al,
-        0x02d1a1c3530ccl },
-      0 },
-    /* 107 */
-    { { 0xe3813506508dal,0xc4a1d795a7192l,0xa9944b3336180l,0xba46cddb59497l,
-        0x0a107a65eb91fl },
-      { 0x1d1c50f94d639l,0x758a58b7d7e6dl,0xd37ca1c8b4af3l,0x9af21a7c5584bl,
-        0x0183d760af87al },
-      0 },
-    /* 108 */
-    { { 0x697110dde59a4l,0x070e8bef8729dl,0xf2ebe78f1ad8dl,0xd754229b49634l,
-        0x01d44179dc269l },
-      { 0xdc0cf8390d30el,0x530de8110cb32l,0xbc0339a0a3b27l,0xd26231af1dc52l,
-        0x0771f9cc29606l },
-      0 },
-    /* 109 */
-    { { 0x93e7785040739l,0xb98026a939999l,0x5f8fc2644539dl,0x718ecf40f6f2fl,
-        0x064427a310362l },
-      { 0xf2d8785428aa8l,0x3febfb49a84f4l,0x23d01ac7b7adcl,0x0d6d201b2c6dfl,
-        0x049d9b7496ae9l },
-      0 },
-    /* 110 */
-    { { 0x8d8bc435d1099l,0x4e8e8d1a08cc7l,0xcb68a412adbcdl,0x544502c2e2a02l,
-        0x09037d81b3f60l },
-      { 0xbac27074c7b61l,0xab57bfd72e7cdl,0x96d5352fe2031l,0x639c61ccec965l,
-        0x008c3de6a7cc0l },
-      0 },
-    /* 111 */
-    { { 0xdd020f6d552abl,0x9805cd81f120fl,0x135129156baffl,0x6b2f06fb7c3e9l,
-        0x0c69094424579l },
-      { 0x3ae9c41231bd1l,0x875cc5820517bl,0x9d6a1221eac6el,0x3ac0208837abfl,
-        0x03fa3db02cafel },
-      0 },
-    /* 112 */
-    { { 0xa3e6505058880l,0xef643943f2d75l,0xab249257da365l,0x08ff4147861cfl,
-        0x0c5c4bdb0fdb8l },
-      { 0x13e34b272b56bl,0x9511b9043a735l,0x8844969c8327el,0xb6b5fd8ce37dfl,
-        0x02d56db9446c2l },
-      0 },
-    /* 113 */
-    { { 0x1782fff46ac6bl,0x2607a2e425246l,0x9a48de1d19f79l,0xba42fafea3c40l,
-        0x00f56bd9de503l },
-      { 0xd4ed1345cda49l,0xfc816f299d137l,0xeb43402821158l,0xb5f1e7c6a54aal,
-        0x04003bb9d1173l },
-      0 },
-    /* 114 */
-    { { 0xe8189a0803387l,0xf539cbd4043b8l,0x2877f21ece115l,0x2f9e4297208ddl,
-        0x053765522a07fl },
-      { 0x80a21a8a4182dl,0x7a3219df79a49l,0xa19a2d4a2bbd0l,0x4549674d0a2e1l,
-        0x07a056f586c5dl },
-      0 },
-    /* 115 */
-    { { 0xb25589d8a2a47l,0x48c3df2773646l,0xbf0d5395b5829l,0x267551ec000eal,
-        0x077d482f17a1al },
-      { 0x1bd9587853948l,0xbd6cfbffeeb8al,0x0681e47a6f817l,0xb0e4ab6ec0578l,
-        0x04115012b2b38l },
-      0 },
-    /* 116 */
-    { { 0x3f0f46de28cedl,0x609b13ec473c7l,0xe5c63921d5da7l,0x094661b8ce9e6l,
-        0x0cdf04572fbeal },
-      { 0x3c58b6c53c3b0l,0x10447b843c1cbl,0xcb9780e97fe3cl,0x3109fb2b8ae12l,
-        0x0ee703dda9738l },
-      0 },
-    /* 117 */
-    { { 0x15140ff57e43al,0xd3b1b811b8345l,0xf42b986d44660l,0xce212b3b5dff8l,
-        0x02a0ad89da162l },
-      { 0x4a6946bc277bal,0x54c141c27664el,0xabf6274c788c9l,0x4659141aa64ccl,
-        0x0d62d0b67ac2bl },
-      0 },
-    /* 118 */
-    { { 0x5d87b2c054ac4l,0x59f27df78839cl,0x18128d6570058l,0x2426edf7cbf3bl,
-        0x0b39a23f2991cl },
-      { 0x84a15f0b16ae5l,0xb1a136f51b952l,0x27007830c6a05l,0x4cc51d63c137fl,
-        0x004ed0092c067l },
-      0 },
-    /* 119 */
-    { { 0x185d19ae90393l,0x294a3d64e61f4l,0x854fc143047b4l,0xc387ae0001a69l,
-        0x0a0a91fc10177l },
-      { 0xa3f01ae2c831el,0x822b727e16ff0l,0xa3075b4bb76ael,0x0c418f12c8a15l,
-        0x0084cf9889ed2l },
-      0 },
-    /* 120 */
-    { { 0x509defca6becfl,0x807dffb328d98l,0x778e8b92fceael,0xf77e5d8a15c44l,
-        0x0d57955b273abl },
-      { 0xda79e31b5d4f1l,0x4b3cfa7a1c210l,0xc27c20baa52f0l,0x41f1d4d12089dl,
-        0x08e14ea4202d1l },
-      0 },
-    /* 121 */
-    { { 0x50345f2897042l,0x1f43402c4aeedl,0x8bdfb218d0533l,0xd158c8d9c194cl,
-        0x0597e1a372aa4l },
-      { 0x7ec1acf0bd68cl,0xdcab024945032l,0x9fe3e846d4be0l,0x4dea5b9c8d7acl,
-        0x0ca3f0236199bl },
-      0 },
-    /* 122 */
-    { { 0xa10b56170bd20l,0xf16d3f5de7592l,0x4b2ade20ea897l,0x07e4a3363ff14l,
-        0x0bde7fd7e309cl },
-      { 0xbb6d2b8f5432cl,0xcbe043444b516l,0x8f95b5a210dc1l,0xd1983db01e6ffl,
-        0x0b623ad0e0a7dl },
-      0 },
-    /* 123 */
-    { { 0xbd67560c7b65bl,0x9023a4a289a75l,0x7b26795ab8c55l,0x137bf8220fd0dl,
-        0x0d6aa2e4658ecl },
-      { 0xbc00b5138bb85l,0x21d833a95c10al,0x702a32e8c31d1l,0x513ab24ff00b1l,
-        0x0111662e02dccl },
-      0 },
-    /* 124 */
-    { { 0x14015efb42b87l,0x701b6c4dff781l,0x7d7c129bd9f5dl,0x50f866ecccd7al,
-        0x0db3ee1cb94b7l },
-      { 0xf3db0f34837cfl,0x8bb9578d4fb26l,0xc56657de7eed1l,0x6a595d2cdf937l,
-        0x0886a64425220l },
-      0 },
-    /* 125 */
-    { { 0x34cfb65b569eal,0x41f72119c13c2l,0x15a619e200111l,0x17bc8badc85dal,
-        0x0a70cf4eb018al },
-      { 0xf97ae8c4a6a65l,0x270134378f224l,0xf7e096036e5cfl,0x7b77be3a609e4l,
-        0x0aa4772abd174l },
-      0 },
-    /* 126 */
-    { { 0x761317aa60cc0l,0x610368115f676l,0xbc1bb5ac79163l,0xf974ded98bb4bl,
-        0x0611a6ddc30fal },
-      { 0x78cbcc15ee47al,0x824e0d96a530el,0xdd9ed882e8962l,0x9c8836f35adf3l,
-        0x05cfffaf81642l },
-      0 },
-    /* 127 */
-    { { 0x54cff9b7a99cdl,0x9d843c45a1c0dl,0x2c739e17bf3b9l,0x994c038a908f6l,
-        0x06e5a6b237dc1l },
-      { 0xb454e0ba5db77l,0x7facf60d63ef8l,0x6608378b7b880l,0xabcce591c0c67l,
-        0x0481a238d242dl },
-      0 },
-    /* 128 */
-    { { 0x17bc035d0b34al,0x6b8327c0a7e34l,0xc0362d1440b38l,0xf9438fb7262dal,
-        0x02c41114ce0cdl },
-      { 0x5cef1ad95a0b1l,0xa867d543622bal,0x1e486c9c09b37l,0x929726d6cdd20l,
-        0x020477abf42ffl },
-      0 },
-    /* 129 */
-    { { 0x5173c18d65dbfl,0x0e339edad82f7l,0xcf1001c77bf94l,0x96b67022d26bdl,
-        0x0ac66409ac773l },
-      { 0xbb36fc6261cc3l,0xc9190e7e908b0l,0x45e6c10213f7bl,0x2f856541cebaal,
-        0x0ce8e6975cc12l },
-      0 },
-    /* 130 */
-    { { 0x21b41bc0a67d2l,0x0a444d248a0f1l,0x59b473762d476l,0xb4a80e044f1d6l,
-        0x008fde365250bl },
-      { 0xec3da848bf287l,0x82d3369d6eacel,0x2449482c2a621l,0x6cd73582dfdc9l,
-        0x02f7e2fd2565dl },
-      0 },
-    /* 131 */
-    { { 0xb92dbc3770fa7l,0x5c379043f9ae4l,0x7761171095e8dl,0x02ae54f34e9d1l,
-        0x0c65be92e9077l },
-      { 0x8a303f6fd0a40l,0xe3bcce784b275l,0xf9767bfe7d822l,0x3b3a7ae4f5854l,
-        0x04bff8e47d119l },
-      0 },
-    /* 132 */
-    { { 0x1d21f00ff1480l,0x7d0754db16cd4l,0xbe0f3ea2ab8fbl,0x967dac81d2efbl,
-        0x03e4e4ae65772l },
-      { 0x8f36d3c5303e6l,0x4b922623977e1l,0x324c3c03bd999l,0x60289ed70e261l,
-        0x05388aefd58ecl },
-      0 },
-    /* 133 */
-    { { 0x317eb5e5d7713l,0xee75de49daad1l,0x74fb26109b985l,0xbe0e32f5bc4fcl,
-        0x05cf908d14f75l },
-      { 0x435108e657b12l,0xa5b96ed9e6760l,0x970ccc2bfd421l,0x0ce20e29f51f8l,
-        0x0a698ba4060f0l },
-      0 },
-    /* 134 */
-    { { 0xb1686ef748fecl,0xa27e9d2cf973dl,0xe265effe6e755l,0xad8d630b6544cl,
-        0x0b142ef8a7aebl },
-      { 0x1af9f17d5770al,0x672cb3412fad3l,0xf3359de66af3bl,0x50756bd60d1bdl,
-        0x0d1896a965851l },
-      0 },
-    /* 135 */
-    { { 0x957ab33c41c08l,0xac5468e2e1ec5l,0xc472f6c87de94l,0xda3918816b73al,
-        0x0267b0e0b7981l },
-      { 0x54e5d8e62b988l,0x55116d21e76e5l,0xd2a6f99d8ddc7l,0x93934610faf03l,
-        0x0b54e287aa111l },
-      0 },
-    /* 136 */
-    { { 0x122b5178a876bl,0xff085104b40a0l,0x4f29f7651ff96l,0xd4e6050b31ab1l,
-        0x084abb28b5f87l },
-      { 0xd439f8270790al,0x9d85e3f46bd5el,0xc1e22122d6cb5l,0x564075f55c1b6l,
-        0x0e5436f671765l },
-      0 },
-    /* 137 */
-    { { 0x9025e2286e8d5l,0xb4864453be53fl,0x408e3a0353c95l,0xe99ed832f5bdel,
-        0x00404f68b5b9cl },
-      { 0x33bdea781e8e5l,0x18163c2f5bcadl,0x119caa33cdf50l,0xc701575769600l,
-        0x03a4263df0ac1l },
-      0 },
-    /* 138 */
-    { { 0x65ecc9aeb596dl,0xe7023c92b4c29l,0xe01396101ea03l,0xa3674704b4b62l,
-        0x00ca8fd3f905el },
-      { 0x23a42551b2b61l,0x9c390fcd06925l,0x392a63e1eb7a8l,0x0c33e7f1d2be0l,
-        0x096dca2644ddbl },
-      0 },
-    /* 139 */
-    { { 0xbb43a387510afl,0xa8a9a36a01203l,0xf950378846feal,0x59dcd23a57702l,
-        0x04363e2123aadl },
-      { 0x3a1c740246a47l,0xd2e55dd24dca4l,0xd8faf96b362b8l,0x98c4f9b086045l,
-        0x0840e115cd8bbl },
-      0 },
-    /* 140 */
-    { { 0x205e21023e8a7l,0xcdd8dc7a0bf12l,0x63a5ddfc808a8l,0xd6d4e292a2721l,
-        0x05e0d6abd30del },
-      { 0x721c27cfc0f64l,0x1d0e55ed8807al,0xd1f9db242eec0l,0xa25a26a7bef91l,
-        0x07dea48f42945l },
-      0 },
-    /* 141 */
-    { { 0xf6f1ce5060a81l,0x72f8f95615abdl,0x6ac268be79f9cl,0x16d1cfd36c540l,
-        0x0abc2a2beebfdl },
-      { 0x66f91d3e2eac7l,0x63d2dd04668acl,0x282d31b6f10bal,0xefc16790e3770l,
-        0x04ea353946c7el },
-      0 },
-    /* 142 */
-    { { 0xa2f8d5266309dl,0xc081945a3eed8l,0x78c5dc10a51c6l,0xffc3cecaf45a5l,
-        0x03a76e6891c94l },
-      { 0xce8a47d7b0d0fl,0x968f584a5f9aal,0xe697fbe963acel,0x646451a30c724l,
-        0x08212a10a465el },
-      0 },
-    /* 143 */
-    { { 0xc61c3cfab8caal,0x840e142390ef7l,0xe9733ca18eb8el,0xb164cd1dff677l,
-        0x0aa7cab71599cl },
-      { 0xc9273bc837bd1l,0xd0c36af5d702fl,0x423da49c06407l,0x17c317621292fl,
-        0x040e38073fe06l },
-      0 },
-    /* 144 */
-    { { 0x80824a7bf9b7cl,0x203fbe30d0f4fl,0x7cf9ce3365d23l,0x5526bfbe53209l,
-        0x0e3604700b305l },
-      { 0xb99116cc6c2c7l,0x08ba4cbee64dcl,0x37ad9ec726837l,0xe15fdcded4346l,
-        0x06542d677a3del },
-      0 },
-    /* 145 */
-    { { 0x2b6d07b6c377al,0x47903448be3f3l,0x0da8af76cb038l,0x6f21d6fdd3a82l,
-        0x0a6534aee09bbl },
-      { 0x1780d1035facfl,0x339dcb47e630al,0x447f39335e55al,0xef226ea50fe1cl,
-        0x0f3cb672fdc9al },
-      0 },
-    /* 146 */
-    { { 0x719fe3b55fd83l,0x6c875ddd10eb3l,0x5cea784e0d7a4l,0x70e733ac9fa90l,
-        0x07cafaa2eaae8l },
-      { 0x14d041d53b338l,0xa0ef87e6c69b8l,0x1672b0fe0acc0l,0x522efb93d1081l,
-        0x00aab13c1b9bdl },
-      0 },
-    /* 147 */
-    { { 0xce278d2681297l,0xb1b509546addcl,0x661aaf2cb350el,0x12e92dc431737l,
-        0x04b91a6028470l },
-      { 0xf109572f8ddcfl,0x1e9a911af4dcfl,0x372430e08ebf6l,0x1cab48f4360acl,
-        0x049534c537232l },
-      0 },
-    /* 148 */
-    { { 0xf7d71f07b7e9dl,0xa313cd516f83dl,0xc047ee3a478efl,0xc5ee78ef264b6l,
-        0x0caf46c4fd65al },
-      { 0xd0c7792aa8266l,0x66913684bba04l,0xe4b16b0edf454l,0x770f56e65168al,
-        0x014ce9e5704c6l },
-      0 },
-    /* 149 */
-    { { 0x45e3e965e8f91l,0xbacb0f2492994l,0x0c8a0a0d3aca1l,0x9a71d31cc70f9l,
-        0x01bb708a53e4cl },
-      { 0xa9e69558bdd7al,0x08018a26b1d5cl,0xc9cf1ec734a05l,0x0102b093aa714l,
-        0x0f9d126f2da30l },
-      0 },
-    /* 150 */
-    { { 0xbca7aaff9563el,0xfeb49914a0749l,0xf5f1671dd077al,0xcc69e27a0311bl,
-        0x0807afcb9729el },
-      { 0xa9337c9b08b77l,0x85443c7e387f8l,0x76fd8ba86c3a7l,0xcd8c85fafa594l,
-        0x0751adcd16568l },
-      0 },
-    /* 151 */
-    { { 0xa38b410715c0dl,0x718f7697f78ael,0x3fbf06dd113eal,0x743f665eab149l,
-        0x029ec44682537l },
-      { 0x4719cb50bebbcl,0xbfe45054223d9l,0xd2dedb1399ee5l,0x077d90cd5b3a8l,
-        0x0ff9370e392a4l },
-      0 },
-    /* 152 */
-    { { 0x2d69bc6b75b65l,0xd5266651c559al,0xde9d7d24188f8l,0xd01a28a9f33e3l,
-        0x09776478ba2a9l },
-      { 0x2622d929af2c7l,0x6d4e690923885l,0x89a51e9334f5dl,0x82face6cc7e5al,
-        0x074a6313fac2fl },
-      0 },
-    /* 153 */
-    { { 0x4dfddb75f079cl,0x9518e36fbbb2fl,0x7cd36dd85b07cl,0x863d1b6cfcf0el,
-        0x0ab75be150ff4l },
-      { 0x367c0173fc9b7l,0x20d2594fd081bl,0x4091236b90a74l,0x59f615fdbf03cl,
-        0x04ebeac2e0b44l },
-      0 },
-    /* 154 */
-    { { 0xc5fe75c9f2c53l,0x118eae9411eb6l,0x95ac5d8d25220l,0xaffcc8887633fl,
-        0x0df99887b2c1bl },
-      { 0x8eed2850aaecbl,0x1b01d6a272bb7l,0x1cdbcac9d4918l,0x4058978dd511bl,
-        0x027b040a7779fl },
-      0 },
-    /* 155 */
-    { { 0x05db7f73b2eb2l,0x088e1b2118904l,0x962327ee0df85l,0xa3f5501b71525l,
-        0x0b393dd37e4cfl },
-      { 0x30e7b3fd75165l,0xc2bcd33554a12l,0xf7b5022d66344l,0x34196c36f1be0l,
-        0x009588c12d046l },
-      0 },
-    /* 156 */
-    { { 0x6093f02601c3bl,0xf8cf5c335fe08l,0x94aff28fb0252l,0x648b955cf2808l,
-        0x081c879a9db9fl },
-      { 0xe687cc6f56c51l,0x693f17618c040l,0x059353bfed471l,0x1bc444f88a419l,
-        0x0fa0d48f55fc1l },
-      0 },
-    /* 157 */
-    { { 0xe1c9de1608e4dl,0x113582822cbc6l,0x57ec2d7010ddal,0x67d6f6b7ddc11l,
-        0x08ea0e156b6a3l },
-      { 0x4e02f2383b3b4l,0x943f01f53ca35l,0xde03ca569966bl,0xb5ac4ff6632b2l,
-        0x03f5ab924fa00l },
-      0 },
-    /* 158 */
-    { { 0xbb0d959739efbl,0xf4e7ebec0d337l,0x11a67d1c751b0l,0x256e2da52dd64l,
-        0x08bc768872b74l },
-      { 0xe3b7282d3d253l,0xa1f58d779fa5bl,0x16767bba9f679l,0xf34fa1cac168el,
-        0x0b386f19060fcl },
-      0 },
-    /* 159 */
-    { { 0x3c1352fedcfc2l,0x6262f8af0d31fl,0x57288c25396bfl,0x9c4d9a02b4eael,
-        0x04cb460f71b06l },
-      { 0x7b4d35b8095eal,0x596fc07603ae6l,0x614a16592bbf8l,0x5223e1475f66bl,
-        0x052c0d50895efl },
-      0 },
-    /* 160 */
-    { { 0xc210e15339848l,0xe870778c8d231l,0x956e170e87a28l,0x9c0b9d1de6616l,
-        0x04ac3c9382bb0l },
-      { 0xe05516998987dl,0xc4ae09f4d619bl,0xa3f933d8b2376l,0x05f41de0b7651l,
-        0x0380d94c7e397l },
-      0 },
-    /* 161 */
-    { { 0x355aa81542e75l,0xa1ee01b9b701al,0x24d708796c724l,0x37af6b3a29776l,
-        0x02ce3e171de26l },
-      { 0xfeb49f5d5bc1al,0x7e2777e2b5cfel,0x513756ca65560l,0x4e4d4feaac2f9l,
-        0x02e6cd8520b62l },
-      0 },
-    /* 162 */
-    { { 0x5954b8c31c31dl,0x005bf21a0c368l,0x5c79ec968533dl,0x9d540bd7626e7l,
-        0x0ca17754742c6l },
-      { 0xedafff6d2dbb2l,0xbd174a9d18cc6l,0xa4578e8fd0d8cl,0x2ce6875e8793al,
-        0x0a976a7139cabl },
-      0 },
-    /* 163 */
-    { { 0x51f1b93fb353dl,0x8b57fcfa720a6l,0x1b15281d75cabl,0x4999aa88cfa73l,
-        0x08720a7170a1fl },
-      { 0xe8d37693e1b90l,0x0b16f6dfc38c3l,0x52a8742d345dcl,0x893c8ea8d00abl,
-        0x09719ef29c769l },
-      0 },
-    /* 164 */
-    { { 0xeed8d58e35909l,0xdc33ddc116820l,0xe2050269366d8l,0x04c1d7f999d06l,
-        0x0a5072976e157l },
-      { 0xa37eac4e70b2el,0x576890aa8a002l,0x45b2a5c84dcf6l,0x7725cd71bf186l,
-        0x099389c9df7b7l },
-      0 },
-    /* 165 */
-    { { 0xc08f27ada7a4bl,0x03fd389366238l,0x66f512c3abe9dl,0x82e46b672e897l,
-        0x0a88806aa202cl },
-      { 0x2044ad380184el,0xc4126a8b85660l,0xd844f17a8cb78l,0xdcfe79d670c0al,
-        0x00043bffb4738l },
-      0 },
-    /* 166 */
-    { { 0x9b5dc36d5192el,0xd34590b2af8d5l,0x1601781acf885l,0x486683566d0a1l,
-        0x052f3ef01ba6cl },
-      { 0x6732a0edcb64dl,0x238068379f398l,0x040f3090a482cl,0x7e7516cbe5fa7l,
-        0x03296bd899ef2l },
-      0 },
-    /* 167 */
-    { { 0xaba89454d81d7l,0xef51eb9b3c476l,0x1c579869eade7l,0x71e9619a21cd8l,
-        0x03b90febfaee5l },
-      { 0x3023e5496f7cbl,0xd87fb51bc4939l,0x9beb5ce55be41l,0x0b1803f1dd489l,
-        0x06e88069d9f81l },
-      0 },
-    /* 168 */
-    { { 0x7ab11b43ea1dbl,0xa95259d292ce3l,0xf84f1860a7ff1l,0xad13851b02218l,
-        0x0a7222beadefal },
-      { 0xc78ec2b0a9144l,0x51f2fa59c5a2al,0x147ce385a0240l,0xc69091d1eca56l,
-        0x0be94d523bc2al },
-      0 },
-    /* 169 */
-    { { 0x4945e0b226ce7l,0x47967e8b7072fl,0x5a6c63eb8afd7l,0xc766edea46f18l,
-        0x07782defe9be8l },
-      { 0xd2aa43db38626l,0x8776f67ad1760l,0x4499cdb460ae7l,0x2e4b341b86fc5l,
-        0x003838567a289l },
-      0 },
-    /* 170 */
-    { { 0xdaefd79ec1a0fl,0xfdceb39c972d8l,0x8f61a953bbcd6l,0xb420f5575ffc5l,
-        0x0dbd986c4adf7l },
-      { 0xa881415f39eb7l,0xf5b98d976c81al,0xf2f717d6ee2fcl,0xbbd05465475dcl,
-        0x08e24d3c46860l },
-      0 },
-    /* 171 */
-    { { 0xd8e549a587390l,0x4f0cbec588749l,0x25983c612bb19l,0xafc846e07da4bl,
-        0x0541a99c4407bl },
-      { 0x41692624c8842l,0x2ad86c05ffdb2l,0xf7fcf626044c1l,0x35d1c59d14b44l,
-        0x0c0092c49f57dl },
-      0 },
-    /* 172 */
-    { { 0xc75c3df2e61efl,0xc82e1b35cad3cl,0x09f29f47e8841l,0x944dc62d30d19l,
-        0x075e406347286l },
-      { 0x41fc5bbc237d0l,0xf0ec4f01c9e7dl,0x82bd534c9537bl,0x858691c51a162l,
-        0x05b7cb658c784l },
-      0 },
-    /* 173 */
-    { { 0xa70848a28ead1l,0x08fd3b47f6964l,0x67e5b39802dc5l,0x97a19ae4bfd17l,
-        0x07ae13eba8df0l },
-      { 0x16ef8eadd384el,0xd9b6b2ff06fd2l,0xbcdb5f30361a2l,0xe3fd204b98784l,
-        0x0787d8074e2a8l },
-      0 },
-    /* 174 */
-    { { 0x25d6b757fbb1cl,0xb2ca201debc5el,0xd2233ffe47bddl,0x84844a55e9a36l,
-        0x05c2228199ef2l },
-      { 0xd4a8588315250l,0x2b827097c1773l,0xef5d33f21b21al,0xf2b0ab7c4ea1dl,
-        0x0e45d37abbaf0l },
-      0 },
-    /* 175 */
-    { { 0xf1e3428511c8al,0xc8bdca6cd3d2dl,0x27c39a7ebb229l,0xb9d3578a71a76l,
-        0x0ed7bc12284dfl },
-      { 0x2a6df93dea561l,0x8dd48f0ed1cf2l,0xbad23e85443f1l,0x6d27d8b861405l,
-        0x0aac97cc945cal },
-      0 },
-    /* 176 */
-    { { 0x4ea74a16bd00al,0xadf5c0bcc1eb5l,0xf9bfc06d839e9l,0xdc4e092bb7f11l,
-        0x0318f97b31163l },
-      { 0x0c5bec30d7138l,0x23abc30220eccl,0x022360644e8dfl,0xff4d2bb7972fbl,
-        0x0fa41faa19a84l },
-      0 },
-    /* 177 */
-    { { 0x2d974a6642269l,0xce9bb783bd440l,0x941e60bc81814l,0xe9e2398d38e47l,
-        0x038bb6b2c1d26l },
-      { 0xe4a256a577f87l,0x53dc11fe1cc64l,0x22807288b52d2l,0x01a5ff336abf6l,
-        0x094dd0905ce76l },
-      0 },
-    /* 178 */
-    { { 0xcf7dcde93f92al,0xcb89b5f315156l,0x995e750a01333l,0x2ae902404df9cl,
-        0x092077867d25cl },
-      { 0x71e010bf39d44l,0x2096bb53d7e24l,0xc9c3d8f5f2c90l,0xeb514c44b7b35l,
-        0x081e8428bd29bl },
-      0 },
-    /* 179 */
-    { { 0x9c2bac477199fl,0xee6b5ecdd96ddl,0xe40fd0e8cb8eel,0xa4b18af7db3fel,
-        0x01b94ab62dbbfl },
-      { 0x0d8b3ce47f143l,0xfc63f4616344fl,0xc59938351e623l,0x90eef18f270fcl,
-        0x006a38e280555l },
-      0 },
-    /* 180 */
-    { { 0xb0139b3355b49l,0x60b4ebf99b2e5l,0x269f3dc20e265l,0xd4f8c08ffa6bdl,
-        0x0a7b36c2083d9l },
-      { 0x15c3a1b3e8830l,0xe1a89f9c0b64dl,0x2d16930d5fceal,0x2a20cfeee4a2el,
-        0x0be54c6b4a282l },
-      0 },
-    /* 181 */
-    { { 0xdb3df8d91167cl,0x79e7a6625ed6cl,0x46ac7f4517c3fl,0x22bb7105648f3l,
-        0x0bf30a5abeae0l },
-      { 0x785be93828a68l,0x327f3ef0368e7l,0x92146b25161c3l,0xd13ae11b5feb5l,
-        0x0d1c820de2732l },
-      0 },
-    /* 182 */
-    { { 0xe13479038b363l,0x546b05e519043l,0x026cad158c11fl,0x8da34fe57abe6l,
-        0x0b7d17bed68a1l },
-      { 0xa5891e29c2559l,0x765bfffd8444cl,0x4e469484f7a03l,0xcc64498de4af7l,
-        0x03997fd5e6412l },
-      0 },
-    /* 183 */
-    { { 0x746828bd61507l,0xd534a64d2af20l,0xa8a15e329e132l,0x13e8ffeddfb08l,
-        0x00eeb89293c6cl },
-      { 0x69a3ea7e259f8l,0xe6d13e7e67e9bl,0xd1fa685ce1db7l,0xb6ef277318f6al,
-        0x0228916f8c922l },
-      0 },
-    /* 184 */
-    { { 0xae25b0a12ab5bl,0x1f957bc136959l,0x16e2b0ccc1117l,0x097e8058429edl,
-        0x0ec05ad1d6e93l },
-      { 0xba5beac3f3708l,0x3530b59d77157l,0x18234e531baf9l,0x1b3747b552371l,
-        0x07d3141567ff1l },
-      0 },
-    /* 185 */
-    { { 0x9c05cf6dfefabl,0x68dcb377077bdl,0xa38bb95be2f22l,0xd7a3e53ead973l,
-        0x0e9ce66fc9bc1l },
-      { 0xa15766f6a02a1l,0xdf60e600ed75al,0x8cdc1b938c087l,0x0651f8947f346l,
-        0x0d9650b017228l },
-      0 },
-    /* 186 */
-    { { 0xb4c4a5a057e60l,0xbe8def25e4504l,0x7c1ccbdcbccc3l,0xb7a2a63532081l,
-        0x014d6699a804el },
-      { 0xa8415db1f411al,0x0bf80d769c2c8l,0xc2f77ad09fbafl,0x598ab4deef901l,
-        0x06f4c68410d43l },
-      0 },
-    /* 187 */
-    { { 0x6df4e96c24a96l,0x85fcbd99a3872l,0xb2ae30a534dbcl,0x9abb3c466ef28l,
-        0x04c4350fd6118l },
-      { 0x7f716f855b8dal,0x94463c38a1296l,0xae9334341a423l,0x18b5c37e1413el,
-        0x0a726d2425a31l },
-      0 },
-    /* 188 */
-    { { 0x6b3ee948c1086l,0x3dcbd3a2e1dael,0x3d022f3f1de50l,0xf3923f35ed3f0l,
-        0x013639e82cc6cl },
-      { 0x938fbcdafaa86l,0xfb2654a2589acl,0x5051329f45bc5l,0x35a31963b26e4l,
-        0x0ca9365e1c1a3l },
-      0 },
-    /* 189 */
-    { { 0x5ac754c3b2d20l,0x17904e241b361l,0xc9d071d742a54l,0x72a5b08521c4cl,
-        0x09ce29c34970bl },
-      { 0x81f736d3e0ad6l,0x9ef2f8434c8ccl,0xce862d98060dal,0xaf9835ed1d1a6l,
-        0x048c4abd7ab42l },
-      0 },
-    /* 190 */
-    { { 0x1b0cc40c7485al,0xbbe5274dbfd22l,0x263d2e8ead455l,0x33cb493c76989l,
-        0x078017c32f67bl },
-      { 0x35769930cb5eel,0x940c408ed2b9dl,0x72f1a4dc0d14el,0x1c04f8b7bf552l,
-        0x053cd0454de5cl },
-      0 },
-    /* 191 */
-    { { 0x585fa5d28ccacl,0x56005b746ebcdl,0xd0123aa5f823el,0xfa8f7c79f0a1cl,
-        0x0eea465c1d3d7l },
-      { 0x0659f0551803bl,0x9f7ce6af70781l,0x9288e706c0b59l,0x91934195a7702l,
-        0x01b6e42a47ae6l },
-      0 },
-    /* 192 */
-    { { 0x0937cf67d04c3l,0xe289eeb8112e8l,0x2594d601e312bl,0xbd3d56b5d8879l,
-        0x00224da14187fl },
-      { 0xbb8630c5fe36fl,0x604ef51f5f87al,0x3b429ec580f3cl,0xff33964fb1bfbl,
-        0x060838ef042bfl },
-      0 },
-    /* 193 */
-    { { 0xcb2f27e0bbe99l,0xf304aa39ee432l,0xfa939037bda44l,0x16435f497c7a9l,
-        0x0636eb2022d33l },
-      { 0xd0e6193ae00aal,0xfe31ae6d2ffcfl,0xf93901c875a00l,0x8bacf43658a29l,
-        0x08844eeb63921l },
-      0 },
-    /* 194 */
-    { { 0x171d26b3bae58l,0x7117e39f3e114l,0x1a8eada7db3dfl,0x789ecd37bc7f8l,
-        0x027ba83dc51fbl },
-      { 0xf439ffbf54de5l,0x0bb5fe1a71a7dl,0xb297a48727703l,0xa4ab42ee8e35dl,
-        0x0adb62d3487f3l },
-      0 },
-    /* 195 */
-    { { 0x168a2a175df2al,0x4f618c32e99b1l,0x46b0916082aa0l,0xc8b2c9e4f2e71l,
-        0x0b990fd7675e7l },
-      { 0x9d96b4df37313l,0x79d0b40789082l,0x80877111c2055l,0xd18d66c9ae4a7l,
-        0x081707ef94d10l },
-      0 },
-    /* 196 */
-    { { 0x7cab203d6ff96l,0xfc0d84336097dl,0x042db4b5b851bl,0xaa5c268823c4dl,
-        0x03792daead5a8l },
-      { 0x18865941afa0bl,0x4142d83671528l,0xbe4e0a7f3e9e7l,0x01ba17c825275l,
-        0x05abd635e94b0l },
-      0 },
-    /* 197 */
-    { { 0xfa84e0ac4927cl,0x35a7c8cf23727l,0xadca0dfe38860l,0xb610a4bcd5ea4l,
-        0x05995bf21846al },
-      { 0xf860b829dfa33l,0xae958fc18be90l,0x8630366caafe2l,0x411e9b3baf447l,
-        0x044c32ca2d483l },
-      0 },
-    /* 198 */
-    { { 0xa97f1e40ed80cl,0xb131d2ca82a74l,0xc2d6ad95f938cl,0xa54c53f2124b7l,
-        0x01f2162fb8082l },
-      { 0x67cc5720b173el,0x66085f12f97e4l,0xc9d65dc40e8a6l,0x07c98cebc20e4l,
-        0x08f1d402bc3e9l },
-      0 },
-    /* 199 */
-    { { 0x92f9cfbc4058al,0xb6292f56704f5l,0xc1d8c57b15e14l,0xdbf9c55cfe37bl,
-        0x0b1980f43926el },
-      { 0x33e0932c76b09l,0x9d33b07f7898cl,0x63bb4611df527l,0x8e456f08ead48l,
-        0x02828ad9b3744l },
-      0 },
-    /* 200 */
-    { { 0x722c4c4cf4ac5l,0x3fdde64afb696l,0x0890832f5ac1al,0xb3900551baa2el,
-        0x04973f1275a14l },
-      { 0xd8335322eac5dl,0xf50bd9b568e59l,0x25883935e07eel,0x8ac7ab36720fal,
-        0x06dac8ed0db16l },
-      0 },
-    /* 201 */
-    { { 0x545aeeda835efl,0xd21d10ed51f7bl,0x3741b094aa113l,0xde4c035a65e01l,
-        0x04b23ef5920b9l },
-      { 0xbb6803c4c7341l,0x6d3f58bc37e82l,0x51e3ee8d45770l,0x9a4e73527863al,
-        0x04dd71534ddf4l },
-      0 },
-    /* 202 */
-    { { 0x4467295476cd9l,0x2fe31a725bbf9l,0xc4b67e0648d07l,0x4dbb1441c8b8fl,
-        0x0fd3170002f4al },
-      { 0x43ff48995d0e1l,0xd10ef729aa1cbl,0x179898276e695l,0xf365e0d5f9764l,
-        0x014fac58c9569l },
-      0 },
-    /* 203 */
-    { { 0xa0065f312ae18l,0xc0fcc93fc9ad9l,0xa7d284651958dl,0xda50d9a142408l,
-        0x0ed7c765136abl },
-      { 0x70f1a25d4abbcl,0xf3f1a113ea462l,0xb51952f9b5dd8l,0x9f53c609b0755l,
-        0x0fefcb7f74d2el },
-      0 },
-    /* 204 */
-    { { 0x9497aba119185l,0x30aac45ba4bd0l,0xa521179d54e8cl,0xd80b492479deal,
-        0x01801a57e87e0l },
-      { 0xd3f8dfcafffb0l,0x0bae255240073l,0xb5fdfbc6cf33cl,0x1064781d763b5l,
-        0x09f8fc11e1eadl },
-      0 },
-    /* 205 */
-    { { 0x3a1715e69544cl,0x67f04b7813158l,0x78a4c320eaf85l,0x69a91e22a8fd2l,
-        0x0a9d3809d3d3al },
-      { 0xc2c2c59a2da3bl,0xf61895c847936l,0x3d5086938ccbcl,0x8ef75e65244e6l,
-        0x03006b9aee117l },
-      0 },
-    /* 206 */
-    { { 0x1f2b0c9eead28l,0x5d89f4dfbc0bbl,0x2ce89397eef63l,0xf761074757fdbl,
-        0x00ab85fd745f8l },
-      { 0xa7c933e5b4549l,0x5c97922f21ecdl,0x43b80404be2bbl,0x42c2261a1274bl,
-        0x0b122d67511e9l },
-      0 },
-    /* 207 */
-    { { 0x607be66a5ae7al,0xfa76adcbe33bel,0xeb6e5c501e703l,0xbaecaf9043014l,
-        0x09f599dc1097dl },
-      { 0x5b7180ff250edl,0x74349a20dc6d7l,0x0b227a38eb915l,0x4b78425605a41l,
-        0x07d5528e08a29l },
-      0 },
-    /* 208 */
-    { { 0x58f6620c26defl,0xea582b2d1ef0fl,0x1ce3881025585l,0x1730fbe7d79b0l,
-        0x028ccea01303fl },
-      { 0xabcd179644ba5l,0xe806fff0b8d1dl,0x6b3e17b1fc643l,0x13bfa60a76fc6l,
-        0x0c18baf48a1d0l },
-      0 },
-    /* 209 */
-    { { 0x638c85dc4216dl,0x67206142ac34el,0x5f5064a00c010l,0x596bd453a1719l,
-        0x09def809db7a9l },
-      { 0x8642e67ab8d2cl,0x336237a2b641el,0x4c4218bb42404l,0x8ce57d506a6d6l,
-        0x00357f8b06880l },
-      0 },
-    /* 210 */
-    { { 0xdbe644cd2cc88l,0x8df0b8f39d8e9l,0xd30a0c8cc61c2l,0x98874a309874cl,
-        0x0e4a01add1b48l },
-      { 0x1eeacf57cd8f9l,0x3ebd594c482edl,0xbd2f7871b767dl,0xcc30a7295c717l,
-        0x0466d7d79ce10l },
-      0 },
-    /* 211 */
-    { { 0x318929dada2c7l,0xc38f9aa27d47dl,0x20a59e14fa0a6l,0xad1a90e4fd288l,
-        0x0c672a522451el },
-      { 0x07cc85d86b655l,0x3bf9ad4af1306l,0x71172a6f0235dl,0x751399a086805l,
-        0x05e3d64faf2a6l },
-      0 },
-    /* 212 */
-    { { 0x410c79b3b4416l,0x85eab26d99aa6l,0xb656a74cd8fcfl,0x42fc5ebff74adl,
-        0x06c8a7a95eb8el },
-      { 0x60ba7b02a63bdl,0x038b8f004710cl,0x12d90b06b2f23l,0xca918c6c37383l,
-        0x0348ae422ad82l },
-      0 },
-    /* 213 */
-    { { 0x746635ccda2fbl,0xa18e0726d27f4l,0x92b1f2022accal,0x2d2e85adf7824l,
-        0x0c1074de0d9efl },
-      { 0x3ce44ae9a65b3l,0xac05d7151bfcfl,0xe6a9788fd71e4l,0x4ffcd4711f50cl,
-        0x0fbadfbdbc9e5l },
-      0 },
-    /* 214 */
-    { { 0x3f1cd20a99363l,0x8f6cf22775171l,0x4d359b2b91565l,0x6fcd968175cd2l,
-        0x0b7f976b48371l },
-      { 0x8e24d5d6dbf74l,0xfd71c3af36575l,0x243dfe38d23bal,0xc80548f477600l,
-        0x0f4d41b2ecafcl },
-      0 },
-    /* 215 */
-    { { 0x1cf28fdabd48dl,0x3632c078a451fl,0x17146e9ce81bel,0x0f106ace29741l,
-        0x0180824eae016l },
-      { 0x7698b66e58358l,0x52ce6ca358038l,0xe41e6c5635687l,0x6d2582380e345l,
-        0x067e5f63983cfl },
-      0 },
-    /* 216 */
-    { { 0xccb8dcf4899efl,0xf09ebb44c0f89l,0x2598ec9949015l,0x1fc6546f9276bl,
-        0x09fef789a04c1l },
-      { 0x67ecf53d2a071l,0x7fa4519b096d3l,0x11e2eefb10e1al,0x4e20ca6b3fb06l,
-        0x0bc80c181a99cl },
-      0 },
-    /* 217 */
-    { { 0x536f8e5eb82e6l,0xc7f56cb920972l,0x0b5da5e1a484fl,0xdf10c78e21715l,
-        0x049270e629f8cl },
-      { 0x9b7bbea6b50adl,0xc1a2388ffc1a3l,0x107197b9a0284l,0x2f7f5403eb178l,
-        0x0d2ee52f96137l },
-      0 },
-    /* 218 */
-    { { 0xcd28588e0362al,0xa78fa5d94dd37l,0x434a526442fa8l,0xb733aff836e5al,
-        0x0dfb478bee5abl },
-      { 0xf1ce7673eede6l,0xd42b5b2f04a91l,0x530da2fa5390al,0x473a5e66f7bf5l,
-        0x0d9a140b408dfl },
-      0 },
-    /* 219 */
-    { { 0x221b56e8ea498l,0x293563ee090e0l,0x35d2ade623478l,0x4b1ae06b83913l,
-        0x0760c058d623fl },
-      { 0x9b58cc198aa79l,0xd2f07aba7f0b8l,0xde2556af74890l,0x04094e204110fl,
-        0x07141982d8f19l },
-      0 },
-    /* 220 */
-    { { 0xa0e334d4b0f45l,0x38392a94e16f0l,0x3c61d5ed9280bl,0x4e473af324c6bl,
-        0x03af9d1ce89d5l },
-      { 0xf798120930371l,0x4c21c17097fd8l,0xc42309beda266l,0x7dd60e9545dcdl,
-        0x0b1f815c37395l },
-      0 },
-    /* 221 */
-    { { 0xaa78e89fec44al,0x473caa4caf84fl,0x1b6a624c8c2ael,0xf052691c807dcl,
-        0x0a41aed141543l },
-      { 0x353997d5ffe04l,0xdf625b6e20424l,0x78177758bacb2l,0x60ef85d660be8l,
-        0x0d6e9c1dd86fbl },
-      0 },
-    /* 222 */
-    { { 0x2e97ec6853264l,0xb7e2304a0b3aal,0x8eae9be771533l,0xf8c21b912bb7bl,
-        0x09c9c6e10ae9bl },
-      { 0x09a59e030b74cl,0x4d6a631e90a23l,0x49b79f24ed749l,0x61b689f44b23al,
-        0x0566bd59640fal },
-      0 },
-    /* 223 */
-    { { 0xc0118c18061f3l,0xd37c83fc70066l,0x7273245190b25l,0x345ef05fc8e02l,
-        0x0cf2c7390f525l },
-      { 0xbceb410eb30cfl,0xba0d77703aa09l,0x50ff255cfd2ebl,0x0979e842c43a1l,
-        0x002f517558aa2l },
-      0 },
-    /* 224 */
-    { { 0xef794addb7d07l,0x4224455500396l,0x78aa3ce0b4fc7l,0xd97dfaff8eaccl,
-        0x014e9ada5e8d4l },
-      { 0x480a12f7079e2l,0xcde4b0800edaal,0x838157d45baa3l,0x9ae801765e2d7l,
-        0x0a0ad4fab8e9dl },
-      0 },
-    /* 225 */
-    { { 0xb76214a653618l,0x3c31eaaa5f0bfl,0x4949d5e187281l,0xed1e1553e7374l,
-        0x0bcd530b86e56l },
-      { 0xbe85332e9c47bl,0xfeb50059ab169l,0x92bfbb4dc2776l,0x341dcdba97611l,
-        0x0909283cf6979l },
-      0 },
-    /* 226 */
-    { { 0x0032476e81a13l,0x996217123967bl,0x32e19d69bee1al,0x549a08ed361bdl,
-        0x035eeb7c9ace1l },
-      { 0x0ae5a7e4e5bdcl,0xd3b6ceec6e128l,0xe266bc12dcd2cl,0xe86452e4224c6l,
-        0x09a8b2cf4448al },
-      0 },
-    /* 227 */
-    { { 0x71bf209d03b59l,0xa3b65af2abf64l,0xbd5eec9c90e62l,0x1379ff7ff168el,
-        0x06bdb60f4d449l },
-      { 0xafebc8a55bc30l,0x1610097fe0dadl,0xc1e3bddc79eadl,0x08a942e197414l,
-        0x001ec3cfd94bal },
-      0 },
-    /* 228 */
-    { { 0x277ebdc9485c2l,0x7922fb10c7ba6l,0x0a28d8a48cc9al,0x64f64f61d60f7l,
-        0x0d1acb1c04754l },
-      { 0x902b126f36612l,0x4ee0618d8bd26l,0x08357ee59c3a4l,0x26c24df8a8133l,
-        0x07dcd079d4056l },
-      0 },
-    /* 229 */
-    { { 0x7d4d3f05a4b48l,0x52372307725cel,0x12a915aadcd29l,0x19b8d18f79718l,
-        0x00bf53589377dl },
-      { 0xcd95a6c68ea73l,0xca823a584d35el,0x473a723c7f3bbl,0x86fc9fb674c6fl,
-        0x0d28be4d9e166l },
-      0 },
-    /* 230 */
-    { { 0xb990638fa8e4bl,0x6e893fd8fc5d2l,0x36fb6fc559f18l,0x88ce3a6de2aa4l,
-        0x0d76007aa510fl },
-      { 0x0aab6523a4988l,0x4474dd02732d1l,0x3407278b455cfl,0xbb017f467082al,
-        0x0f2b52f68b303l },
-      0 },
-    /* 231 */
-    { { 0x7eafa9835b4cal,0xfcbb669cbc0d5l,0x66431982d2232l,0xed3a8eeeb680cl,
-        0x0d8dbe98ecc5al },
-      { 0x9be3fc5a02709l,0xe5f5ba1fa8cbal,0x10ea85230be68l,0x9705febd43cdfl,
-        0x0e01593a3ee55l },
-      0 },
-    /* 232 */
-    { { 0x5af50ea75a0a6l,0xac57858033d3el,0x0176406512226l,0xef066fe6d50fdl,
-        0x0afec07b1aeb8l },
-      { 0x9956780bb0a31l,0xcc37309aae7fbl,0x1abf3896f1af3l,0xbfdd9153a15a0l,
-        0x0a71b93546e2dl },
-      0 },
-    /* 233 */
-    { { 0xe12e018f593d2l,0x28a078122bbf8l,0xba4f2add1a904l,0x23d9150505db0l,
-        0x053a2005c6285l },
-      { 0x8b639e7f2b935l,0x5ac182961a07cl,0x518ca2c2bff97l,0x8e3d86bceea77l,
-        0x0bf47d19b3d58l },
-      0 },
-    /* 234 */
-    { { 0x967a7dd7665d5l,0x572f2f4de5672l,0x0d4903f4e3030l,0xa1b6144005ae8l,
-        0x0001c2c7f39c9l },
-      { 0xa801469efc6d6l,0xaa7bc7a724143l,0x78150a4c810bdl,0xb99b5f65670bal,
-        0x0fdadf8e786ffl },
-      0 },
-    /* 235 */
-    { { 0x8cb88ffc00785l,0x913b48eb67fd3l,0xf368fbc77fa75l,0x3c940454d055bl,
-        0x03a838e4d5aa4l },
-      { 0x663293e97bb9al,0x63441d94d9561l,0xadb2a839eb933l,0x1da3515591a60l,
-        0x03cdb8257873el },
-      0 },
-    /* 236 */
-    { { 0x140a97de77eabl,0x0d41648109137l,0xeb1d0dff7e1c5l,0x7fba762dcad2cl,
-        0x05a60cc89f1f5l },
-      { 0x3638240d45673l,0x195913c65580bl,0xd64b7411b82bel,0x8fc0057284b8dl,
-        0x0922ff56fdbfdl },
-      0 },
-    /* 237 */
-    { { 0x65deec9a129a1l,0x57cc284e041b2l,0xebfbe3ca5b1cel,0xcd6204380c46cl,
-        0x072919a7df6c5l },
-      { 0xf453a8fb90f9al,0x0b88e4031b298l,0x96f1856d719c0l,0x089ae32c0e777l,
-        0x05e7917803624l },
-      0 },
-    /* 238 */
-    { { 0x6ec557f63cdfbl,0x71f1cae4fd5c1l,0x60597ca8e6a35l,0x2fabfce26bea5l,
-        0x04e0a5371e24cl },
-      { 0xa40d3a5765357l,0x440d73a2b4276l,0x1d11a323c89afl,0x04eeb8f370ae4l,
-        0x0f5ff7818d566l },
-      0 },
-    /* 239 */
-    { { 0x3e3fe1a09df21l,0x8ee66e8e47fbfl,0x9c8901526d5d2l,0x5e642096bd0a2l,
-        0x0e41df0e9533fl },
-      { 0xfda40b3ba9e3fl,0xeb2604d895305l,0xf0367c7f2340cl,0x155f0866e1927l,
-        0x08edd7d6eac4fl },
-      0 },
-    /* 240 */
-    { { 0x1dc0e0bfc8ff3l,0x2be936f42fc9al,0xca381ef14efd8l,0xee9667016f7ccl,
-        0x01432c1caed8al },
-      { 0x8482970b23c26l,0x730735b273ec6l,0xaef0f5aa64fe8l,0xd2c6e389f6e5el,
-        0x0caef480b5ac8l },
-      0 },
-    /* 241 */
-    { { 0x5c97875315922l,0x713063cca5524l,0x64ef2cbd82951l,0xe236f3ce60d0bl,
-        0x0d0ba177e8efal },
-      { 0x9ae8fb1b3af60l,0xe53d2da20e53al,0xf9eef281a796al,0xae1601d63605dl,
-        0x0f31c957c1c54l },
-      0 },
-    /* 242 */
-    { { 0x58d5249cc4597l,0xb0bae0a028c0fl,0x34a814adc5015l,0x7c3aefc5fc557l,
-        0x0013404cb96e1l },
-      { 0xe2585c9a824bfl,0x5e001eaed7b29l,0x1ef68acd59318l,0x3e6c8d6ee6826l,
-        0x06f377c4b9193l },
-      0 },
-    /* 243 */
-    { { 0x3bad1a8333fd2l,0x025a2a95b89f9l,0xaf75acea89302l,0x9506211e5037el,
-        0x06dba3e4ed2d0l },
-      { 0xef98cd04399cdl,0x6ee6b73adea48l,0x17ecaf31811c6l,0xf4a772f60752cl,
-        0x0f13cf3423becl },
-      0 },
-    /* 244 */
-    { { 0xb9ec0a919e2ebl,0x95f62c0f68ceel,0xaba229983a9a1l,0xbad3cfba3bb67l,
-        0x0c83fa9a9274bl },
-      { 0xd1b0b62fa1ce0l,0xf53418efbf0d7l,0x2706f04e58b60l,0x2683bfa8ef9e5l,
-        0x0b49d70f45d70l },
-      0 },
-    /* 245 */
-    { { 0xc7510fad5513bl,0xecb1751e2d914l,0x9fb9d5905f32el,0xf1cf6d850418dl,
-        0x059cfadbb0c30l },
-      { 0x7ac2355cb7fd6l,0xb8820426a3e16l,0x0a78864249367l,0x4b67eaeec58c9l,
-        0x05babf362354al },
-      0 },
-    /* 246 */
-    { { 0x981d1ee424865l,0x78f2e5577f37cl,0x9e0c0588b0028l,0xc8f0702970f1bl,
-        0x06188c6a79026l },
-      { 0x9a19bd0f244dal,0x5cfb08087306fl,0xf2136371eccedl,0xb9d935470f9b9l,
-        0x0993fe475df50l },
-      0 },
-    /* 247 */
-    { { 0x31cdf9b2c3609l,0xc02c46d4ea68el,0xa77510184eb19l,0x616b7ac9ec1a9l,
-        0x081f764664c80l },
-      { 0xc2a5a75fbe978l,0xd3f183b3561d7l,0x01dd2bf6743fel,0x060d838d1f045l,
-        0x0564a812a5fe9l },
-      0 },
-    /* 248 */
-    { { 0xa64f4fa817d1dl,0x44bea82e0f7a5l,0xd57f9aa55f968l,0x1d6cb5ff5a0fcl,
-        0x0226bf3cf00e5l },
-      { 0x1a9f92f2833cfl,0x5a4f4f89a8d6dl,0xf3f7f7720a0a3l,0x783611536c498l,
-        0x068779f47ff25l },
-      0 },
-    /* 249 */
-    { { 0x0c1c173043d08l,0x741fc020fa79bl,0xa6d26d0a54467l,0x2e0bd3767e289l,
-        0x097bcb0d1eb09l },
-      { 0x6eaa8f32ed3c3l,0x51b281bc482abl,0xfa178f3c8a4f1l,0x46554d1bf4f3bl,
-        0x0a872ffe80a78l },
-      0 },
-    /* 250 */
-    { { 0xb7935a32b2086l,0x0e8160f486b1al,0xb6ae6bee1eb71l,0xa36a9bd0cd913l,
-        0x002812bfcb732l },
-      { 0xfd7cacf605318l,0x50fdfd6d1da63l,0x102d619646e5dl,0x96afa1d683982l,
-        0x007391cc9fe53l },
-      0 },
-    /* 251 */
-    { { 0x157f08b80d02bl,0xd162877f7fc50l,0x8d542ae6b8333l,0x2a087aca1af87l,
-        0x0355d2adc7e6dl },
-      { 0xf335a287386e1l,0x94f8e43275b41l,0x79989eafd272al,0x3a79286ca2cdel,
-        0x03dc2b1e37c2al },
-      0 },
-    /* 252 */
-    { { 0x9d21c04581352l,0x25376782bed68l,0xfed701f0a00c8l,0x846b203bd5909l,
-        0x0c47869103ccdl },
-      { 0xa770824c768edl,0x026841f6575dbl,0xaccce0e72feeal,0x4d3273313ed56l,
-        0x0ccc42968d5bbl },
-      0 },
-    /* 253 */
-    { { 0x50de13d7620b9l,0x8a5992a56a94el,0x75487c9d89a5cl,0x71cfdc0076406l,
-        0x0e147eb42aa48l },
-      { 0xab4eeacf3ae46l,0xfb50350fbe274l,0x8c840eafd4936l,0x96e3df2afe474l,
-        0x0239ac047080el },
-      0 },
-    /* 254 */
-    { { 0xd1f352bfee8d4l,0xcffa7b0fec481l,0xce9af3cce80b5l,0xe59d105c4c9e2l,
-        0x0c55fa1a3f5f7l },
-      { 0x6f14e8257c227l,0x3f342be00b318l,0xa904fb2c5b165l,0xb69909afc998al,
-        0x0094cd99cd4f4l },
-      0 },
-    /* 255 */
-    { { 0x81c84d703bebal,0x5032ceb2918a9l,0x3bd49ec8631d1l,0xad33a445f2c9el,
-        0x0b90a30b642abl },
-      { 0x5404fb4a5abf9l,0xc375db7603b46l,0xa35d89f004750l,0x24f76f9a42cccl,
-        0x0019f8b9a1b79l },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_5(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#endif
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[5];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 5, km);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_5(point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_5(point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_5(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN)
-/* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a  Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
-static int sp_256_iszero_5(const sp_digit* a)
-{
-    return (a[0] | a[1] | a[2] | a[3] | a[4]) == 0;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */
-/* Add 1 to a. (a = a + 1)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_add_one_5(sp_digit* a)
-{
-    a[0]++;
-    sp_256_norm_5(a);
-}
-
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 44) {
-            r[j] &= 0xfffffffffffffl;
-            s = 52 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Generates a scalar that is in the range 1..order-1.
- *
- * rng  Random number generator.
- * k    Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-static int sp_256_ecc_gen_k_5(WC_RNG* rng, sp_digit* k)
-{
-    int err;
-    byte buf[32];
-
-    do {
-        err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
-        if (err == 0) {
-            sp_256_from_bin(k, 5, buf, sizeof(buf));
-            if (sp_256_cmp_5(k, p256_order2) < 0) {
-                sp_256_add_one_5(k);
-                break;
-            }
-        }
-    }
-    while (err == 0);
-
-    return err;
-}
-
-/* Makes a random EC key pair.
- *
- * rng   Random number generator.
- * priv  Generated private value.
- * pub   Generated public point.
- * heap  Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[5];
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point inf;
-#endif
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point* infinity;
-#endif
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, inf, infinity);
-#endif
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_ecc_gen_k_5(rng, k);
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_5(point, k, 1, NULL);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL);
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            err = sp_256_ecc_mulmod_avx2_5(infinity, point, p256_order, 1,
-                                                                          NULL);
-        }
-        else
-#endif
-            err = sp_256_ecc_mulmod_5(infinity, point, p256_order, 1, NULL);
-    }
-    if (err == MP_OKAY) {
-        if (!sp_256_iszero_5(point->x) || !sp_256_iszero_5(point->y))
-            err = ECC_INF_E;
-    }
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(k, priv);
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_5(point, pub);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_ecc_point_free(infinity, 1, heap);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-
-#ifdef HAVE_ECC_DHE
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 32
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_256_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    for (i=0; i<4; i++) {
-        r[i+1] += r[i] >> 52;
-        r[i] &= 0xfffffffffffffl;
-    }
-    j = 256 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<5 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 52) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 52);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv    Scalar to multiply the point by.
- * pub     Point to multiply.
- * out     Buffer to hold X ordinate.
- * outLen  On entry, size of the buffer in bytes.
- *         On exit, length of data in buffer in bytes.
- * heap    Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outLen, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[5];
-#endif
-    sp_point* point = NULL;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 32)
-        err = BUFFER_E;
-
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 5, priv);
-        sp_256_point_from_ecc_point_5(point, pub);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_5(point, point, k, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_5(point, point, k, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        sp_256_to_bin(point->x, out);
-        *outLen = 32;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_DHE */
-
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef HAVE_INTEL_AVX2
-#endif /* HAVE_INTEL_AVX2 */
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Multiply a by scalar b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A scalar.
- */
-SP_NOINLINE static void sp_256_mul_d_5(sp_digit* r, const sp_digit* a,
-    const sp_digit b)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int128_t tb = b;
-    int128_t t = 0;
-    int i;
-
-    for (i = 0; i < 5; i++) {
-        t += tb * a[i];
-        r[i] = t & 0xfffffffffffffl;
-        t >>= 52;
-    }
-    r[5] = (sp_digit)t;
-#else
-    int128_t tb = b;
-    int128_t t[5];
-
-    t[ 0] = tb * a[ 0];
-    t[ 1] = tb * a[ 1];
-    t[ 2] = tb * a[ 2];
-    t[ 3] = tb * a[ 3];
-    t[ 4] = tb * a[ 4];
-    r[ 0] =                           (t[ 0] & 0xfffffffffffffl);
-    r[ 1] = (sp_digit)(t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl);
-    r[ 2] = (sp_digit)(t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl);
-    r[ 3] = (sp_digit)(t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl);
-    r[ 4] = (sp_digit)(t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl);
-    r[ 5] = (sp_digit)(t[ 4] >> 52);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_256_div_5(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    int i;
-    int128_t d1;
-    sp_digit div, r1;
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* td;
-#else
-    sp_digit t1d[10], t2d[5 + 1];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    td = XMALLOC(sizeof(sp_digit) * (3 * 5 + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (td != NULL) {
-        t1 = td;
-        t2 = td + 2 * 5;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    (void)m;
-
-    if (err == MP_OKAY) {
-        div = d[4];
-        XMEMCPY(t1, a, sizeof(*t1) * 2 * 5);
-        for (i=4; i>=0; i--) {
-            t1[5 + i] += t1[5 + i - 1] >> 52;
-            t1[5 + i - 1] &= 0xfffffffffffffl;
-            d1 = t1[5 + i];
-            d1 <<= 52;
-            d1 += t1[5 + i - 1];
-            r1 = (sp_digit)(d1 / div);
-
-            sp_256_mul_d_5(t2, d, r1);
-            sp_256_sub_5(&t1[i], &t1[i], t2);
-            t1[5 + i] -= t2[5];
-            t1[5 + i] += t1[5 + i - 1] >> 52;
-            t1[5 + i - 1] &= 0xfffffffffffffl;
-            r1 = (((-t1[5 + i]) << 52) - t1[5 + i - 1]) / div;
-            r1++;
-            sp_256_mul_d_5(t2, d, r1);
-            sp_256_add_5(&t1[i], &t1[i], t2);
-            t1[5 + i] += t1[5 + i - 1] >> 52;
-            t1[5 + i - 1] &= 0xfffffffffffffl;
-        }
-        t1[5 - 1] += t1[5 - 2] >> 52;
-        t1[5 - 2] &= 0xfffffffffffffl;
-        d1 = t1[5 - 1];
-        r1 = (sp_digit)(d1 / div);
-
-        sp_256_mul_d_5(t2, d, r1);
-        sp_256_sub_5(t1, t1, t2);
-        XMEMCPY(r, t1, sizeof(*r) * 2 * 5);
-        for (i=0; i<3; i++) {
-            r[i+1] += r[i] >> 52;
-            r[i] &= 0xfffffffffffffl;
-        }
-        sp_256_cond_add_5(r, r, d, 0 - (r[4] < 0));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
- */
-static int sp_256_mod_5(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_256_div_5(a, m, NULL, r);
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-#ifdef WOLFSSL_SP_SMALL
-/* Order-2 for the P256 curve. */
-static const uint64_t p256_order_2[4] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff,
-    0xffffffff00000000
-};
-#else
-/* The low half of the order-2 of the P256 curve. */
-static const uint64_t p256_order_low[2] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84
-};
-#endif /* WOLFSSL_SP_SMALL */
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_5(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_5(r, a, b);
-    sp_256_mont_reduce_5(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_5(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_5(r, a);
-    sp_256_mont_reduce_5(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_5(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_5(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_5(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_5(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 5);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_5(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_5(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 5);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 5;
-    sp_digit* t3 = td + 4 * 5;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_5(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_5(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_5(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_5(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_5(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_5(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_5(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_5(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_5(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_5(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_5(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_5(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_5(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_5(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_5(t2, t2, 4);
-    sp_256_mont_mul_order_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_5(t2, t2, 4);
-    sp_256_mont_mul_order_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_5(t2, t2, 4);
-    sp_256_mont_mul_order_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_5(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_5(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_avx2_5(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_avx2_5(r, a, b);
-    sp_256_mont_reduce_avx2_5(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_avx2_5(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_avx2_5(r, a);
-    sp_256_mont_reduce_avx2_5(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_avx2_5(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_avx2_5(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_avx2_5(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_avx2_5(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 5);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_5(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_5(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 5);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 5;
-    sp_digit* t3 = td + 4 * 5;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_avx2_5(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_avx2_5(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_avx2_5(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_avx2_5(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_avx2_5(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_5(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_5(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_5(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_avx2_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_avx2_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_avx2_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_5(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_5(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_5(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_avx2_5(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_avx2_5(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
-#ifdef HAVE_ECC_SIGN
-#ifndef SP_ECC_MAX_SIG_GEN
-#define SP_ECC_MAX_SIG_GEN  64
-#endif
-
-/* Sign the hash using the private key.
- *   e = [hash, 256 bits] from binary
- *   r = (k.G)->x mod order
- *   s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit ed[2*5];
-    sp_digit xd[2*5];
-    sp_digit kd[2*5];
-    sp_digit rd[2*5];
-    sp_digit td[3 * 2*5];
-    sp_point p;
-#endif
-    sp_digit* e = NULL;
-    sp_digit* x = NULL;
-    sp_digit* k = NULL;
-    sp_digit* r = NULL;
-    sp_digit* tmp = NULL;
-    sp_point* point = NULL;
-    sp_digit carry;
-    sp_digit* s;
-    sp_digit* kInv;
-    int err = MP_OKAY;
-    int64_t c;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            e = d + 0 * 5;
-            x = d + 2 * 5;
-            k = d + 4 * 5;
-            r = d + 6 * 5;
-            tmp = d + 8 * 5;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    e = ed;
-    x = xd;
-    k = kd;
-    r = rd;
-    tmp = td;
-#endif
-    s = e;
-    kInv = k;
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(e, 5, hash, hashLen);
-        sp_256_from_mp(x, 5, priv);
-    }
-
-    for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
-        /* New random point. */
-        err = sp_256_ecc_gen_k_5(rng, k);
-        if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                err = sp_256_ecc_mulmod_base_avx2_5(point, k, 1, heap);
-            else
-#endif
-                err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL);
-        }
-
-        if (err == MP_OKAY) {
-            /* r = point->x mod order */
-            XMEMCPY(r, point->x, sizeof(sp_digit) * 5);
-            sp_256_norm_5(r);
-            c = sp_256_cmp_5(r, p256_order);
-            sp_256_cond_sub_5(r, r, p256_order, 0 - (c >= 0));
-            sp_256_norm_5(r);
-
-            /* Conv k to Montgomery form (mod order) */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_5(k, k, p256_norm_order);
-            else
-#endif
-                sp_256_mul_5(k, k, p256_norm_order);
-            err = sp_256_mod_5(k, k, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_5(k);
-            /* kInv = 1/k mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_inv_order_avx2_5(kInv, k, tmp);
-            else
-#endif
-                sp_256_mont_inv_order_5(kInv, k, tmp);
-            sp_256_norm_5(kInv);
-
-            /* s = r * x + e */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_5(x, x, r);
-            else
-#endif
-                sp_256_mul_5(x, x, r);
-            err = sp_256_mod_5(x, x, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_5(x);
-            carry = sp_256_add_5(s, e, x);
-            sp_256_cond_sub_5(s, s, p256_order, 0 - carry);
-            sp_256_norm_5(s);
-            c = sp_256_cmp_5(s, p256_order);
-            sp_256_cond_sub_5(s, s, p256_order, 0 - (c >= 0));
-            sp_256_norm_5(s);
-
-            /* s = s * k^-1 mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_mul_order_avx2_5(s, s, kInv);
-            else
-#endif
-                sp_256_mont_mul_order_5(s, s, kInv);
-            sp_256_norm_5(s);
-
-            /* Check that signature is usable. */
-            if (!sp_256_iszero_5(s))
-                break;
-        }
-    }
-
-    if (i == 0)
-        err = RNG_FAILURE_E;
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(r, rm);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(s, sm);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5);
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    XMEMSET(e, 0, sizeof(sp_digit) * 2 * 5);
-    XMEMSET(x, 0, sizeof(sp_digit) * 2 * 5);
-    XMEMSET(k, 0, sizeof(sp_digit) * 2 * 5);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5);
-    XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*5);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-/* Verify the signature values with the hash and public key.
- *   e = Truncate(hash, 256)
- *   u1 = e/s mod order
- *   u2 = r/s mod order
- *   r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- *   (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- *   (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
-    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit u1d[2*5];
-    sp_digit u2d[2*5];
-    sp_digit sd[2*5];
-    sp_digit tmpd[2*5 * 5];
-    sp_point p1d;
-    sp_point p2d;
-#endif
-    sp_digit* u1;
-    sp_digit* u2;
-    sp_digit* s;
-    sp_digit* tmp;
-    sp_point* p1;
-    sp_point* p2 = NULL;
-    sp_digit carry;
-    int64_t c;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p1d, p1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p2d, p2);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 16 * 5, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            u1  = d + 0 * 5;
-            u2  = d + 2 * 5;
-            s   = d + 4 * 5;
-            tmp = d + 6 * 5;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    u1 = u1d;
-    u2 = u2d;
-    s  = sd;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(u1, 5, hash, hashLen);
-        sp_256_from_mp(u2, 5, r);
-        sp_256_from_mp(s, 5, sm);
-        sp_256_from_mp(p2->x, 5, pX);
-        sp_256_from_mp(p2->y, 5, pY);
-        sp_256_from_mp(p2->z, 5, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_avx2_5(s, s, p256_norm_order);
-        else
-#endif
-            sp_256_mul_5(s, s, p256_norm_order);
-        err = sp_256_mod_5(s, s, p256_order);
-    }
-    if (err == MP_OKAY) {
-        sp_256_norm_5(s);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_inv_order_avx2_5(s, s, tmp);
-            sp_256_mont_mul_order_avx2_5(u1, u1, s);
-            sp_256_mont_mul_order_avx2_5(u2, u2, s);
-        }
-        else
-#endif
-        {
-            sp_256_mont_inv_order_5(s, s, tmp);
-            sp_256_mont_mul_order_5(u1, u1, s);
-            sp_256_mont_mul_order_5(u2, u2, s);
-        }
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_5(p1, u1, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_5(p1, u1, 0, heap);
-    }
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_5(p2, p2, u2, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, heap);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_5(p1, p1, p2, tmp);
-        else
-#endif
-            sp_256_proj_point_add_5(p1, p1, p2, tmp);
-
-        /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
-        /* Reload r and convert to Montgomery form. */
-        sp_256_from_mp(u2, 5, r);
-        err = sp_256_mod_mul_norm_5(u2, u2, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* u1 = r.z'.z' mod prime */
-        sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod);
-        *res = sp_256_cmp_5(p1->x, u1) == 0;
-        if (*res == 0) {
-            /* Reload r and add order. */
-            sp_256_from_mp(u2, 5, r);
-            carry = sp_256_add_5(u2, u2, p256_order);
-            /* Carry means result is greater than mod and is not valid. */
-            if (!carry) {
-                sp_256_norm_5(u2);
-
-                /* Compare with mod and if greater or equal then not valid. */
-                c = sp_256_cmp_5(u2, p256_mod);
-                if (c < 0) {
-                    /* Convert to Montogomery form */
-                    err = sp_256_mod_mul_norm_5(u2, u2, p256_mod);
-                    if (err == MP_OKAY) {
-                        /* u1 = (r + 1*order).z'.z' mod prime */
-                        sp_256_mont_mul_5(u1, u2, p1->z, p256_mod,
-                                                                  p256_mp_mod);
-                        *res = sp_256_cmp_5(p1->x, u2) == 0;
-                    }
-                }
-            }
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p1, 0, heap);
-    sp_ecc_point_free(p2, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_CHECK_KEY
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * point  EC point.
- * heap   Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-static int sp_256_ecc_is_point_5(sp_point* point, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit t1d[2*5];
-    sp_digit t2d[2*5];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 5 * 4, heap, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 5;
-        t2 = d + 2 * 5;
-    }
-    else
-        err = MEMORY_E;
-#else
-    (void)heap;
-
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_sqr_5(t1, point->y);
-        sp_256_mod_5(t1, t1, p256_mod);
-        sp_256_sqr_5(t2, point->x);
-        sp_256_mod_5(t2, t2, p256_mod);
-        sp_256_mul_5(t2, t2, point->x);
-        sp_256_mod_5(t2, t2, p256_mod);
-	sp_256_sub_5(t2, p256_mod, t2);
-        sp_256_mont_add_5(t1, t1, t2, p256_mod);
-
-        sp_256_mont_add_5(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_5(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_5(t1, t1, point->x, p256_mod);
-
-        if (sp_256_cmp_5(t1, p256_b) != 0)
-            err = MP_VAL;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX  X ordinate of EC point.
- * pY  Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point pubd;
-#endif
-    sp_point* pub;
-    byte one[1] = { 1 };
-    int err;
-
-    err = sp_ecc_point_new(NULL, pubd, pub);
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 5, pX);
-        sp_256_from_mp(pub->y, 5, pY);
-        sp_256_from_bin(pub->z, 5, one, sizeof(one));
-
-        err = sp_256_ecc_is_point_5(pub, NULL);
-    }
-
-    sp_ecc_point_free(pub, 0, NULL);
-
-    return err;
-}
-
-/* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX     X ordinate of EC point.
- * pY     Y ordinate of EC point.
- * privm  Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit privd[5];
-    sp_point pubd;
-    sp_point pd;
-#endif
-    sp_digit* priv = NULL;
-    sp_point* pub;
-    sp_point* p = NULL;
-    byte one[1] = { 1 };
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, pubd, pub);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        priv = XMALLOC(sizeof(sp_digit) * 5, heap, DYNAMIC_TYPE_ECC);
-        if (priv == NULL)
-            err = MEMORY_E;
-    }
-#else
-    priv = privd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 5, pX);
-        sp_256_from_mp(pub->y, 5, pY);
-        sp_256_from_bin(pub->z, 5, one, sizeof(one));
-        sp_256_from_mp(priv, 5, privm);
-
-        /* Check point at infinitiy. */
-        if (sp_256_iszero_5(pub->x) &&
-            sp_256_iszero_5(pub->y))
-            err = ECC_INF_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check range of X and Y */
-        if (sp_256_cmp_5(pub->x, p256_mod) >= 0 ||
-            sp_256_cmp_5(pub->y, p256_mod) >= 0)
-            err = ECC_OUT_OF_RANGE_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check point is on curve */
-        err = sp_256_ecc_is_point_5(pub, heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* Point * order = infinity */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_5(p, pub, p256_order, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is infinity */
-        if (!sp_256_iszero_5(p->x) ||
-            !sp_256_iszero_5(p->y)) {
-            err = ECC_INF_E;
-        }
-    }
-
-    if (err == MP_OKAY) {
-        /* Base * private = point */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_5(p, priv, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_5(p, priv, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is public key */
-        if (sp_256_cmp_5(p->x, pub->x) != 0 ||
-            sp_256_cmp_5(p->y, pub->y) != 0) {
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (priv != NULL)
-        XFREE(priv, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(pub, 0, heap);
-
-    return err;
-}
-#endif
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-/* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX   First EC point's X ordinate.
- * pY   First EC point's Y ordinate.
- * pZ   First EC point's Z ordinate.
- * qX   Second EC point's X ordinate.
- * qY   Second EC point's Y ordinate.
- * qZ   Second EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 5 * 5];
-    sp_point pd;
-    sp_point qd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    sp_point* q = NULL;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(NULL, qd, q);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 5, pX);
-        sp_256_from_mp(p->y, 5, pY);
-        sp_256_from_mp(p->z, 5, pZ);
-        sp_256_from_mp(q->x, 5, qX);
-        sp_256_from_mp(q->y, 5, qY);
-        sp_256_from_mp(q->z, 5, qZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_5(p, p, q, tmp);
-        else
-#endif
-            sp_256_proj_point_add_5(p, p, q, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(q, 0, NULL);
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 5 * 2];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 2, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 5, pX);
-        sp_256_from_mp(p->y, 5, pY);
-        sp_256_from_mp(p->z, 5, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_dbl_avx2_5(p, p, tmp);
-        else
-#endif
-            sp_256_proj_point_dbl_5(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 5 * 4];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 5 * 4, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 5, pX);
-        sp_256_from_mp(p->y, 5, pY);
-        sp_256_from_mp(p->z, 5, pZ);
-
-        sp_256_map_5(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, pX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
-#ifdef HAVE_COMP_KEY
-/* Find the square root of a number mod the prime of the curve.
- *
- * y  The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mont_sqrt_5(sp_digit* y)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit t1d[2 * 5];
-    sp_digit t2d[2 * 5];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 5;
-        t2 = d + 2 * 5;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_avx2_5(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_avx2_5(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_avx2_5(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_avx2_5(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_avx2_5(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_avx2_5(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_avx2_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_avx2_5(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_avx2_5(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_avx2_5(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_avx2_5(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_avx2_5(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_5(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_5(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_5(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_5(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_5(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_5(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_5(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_5(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Uncompress the point given the X ordinate.
- *
- * xm    X ordinate.
- * odd   Whether the Y ordinate is odd.
- * ym    Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit xd[2 * 5];
-    sp_digit yd[2 * 5];
-#endif
-    sp_digit* x;
-    sp_digit* y;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        x = d + 0 * 5;
-        y = d + 2 * 5;
-    }
-    else
-        err = MEMORY_E;
-#else
-    x = xd;
-    y = yd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(x, 5, xm);
-
-        err = sp_256_mod_mul_norm_5(x, x, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* y = x^3 */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_sqr_avx2_5(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_avx2_5(y, y, x, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            sp_256_mont_sqr_5(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod);
-        }
-        /* y = x^3 - 3x */
-        sp_256_mont_sub_5(y, y, x, p256_mod);
-        sp_256_mont_sub_5(y, y, x, p256_mod);
-        sp_256_mont_sub_5(y, y, x, p256_mod);
-        /* y = x^3 - 3x + b */
-        err = sp_256_mod_mul_norm_5(x, p256_b, p256_mod);
-    }
-    if (err == MP_OKAY) {
-        sp_256_mont_add_5(y, y, x, p256_mod);
-        /* y = sqrt(x^3 - 3x + b) */
-        err = sp_256_mont_sqrt_5(y);
-    }
-    if (err == MP_OKAY) {
-        XMEMSET(y + 5, 0, 5 * sizeof(sp_digit));
-        sp_256_mont_reduce_5(y, p256_mod, p256_mp_mod);
-        if (((y[0] ^ odd) & 1) != 0)
-            sp_256_mont_sub_5(y, p256_mod, y, p256_mod);
-
-        err = sp_256_to_mp(y, ym);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-#endif /* SP_WORD_SIZE == 64 */
-#endif /* !WOLFSSL_SP_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
--- a/wolfcrypt/src/sp_int.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,665 +0,0 @@
-/* sp_int.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#ifdef WOLFSSL_SP_MATH
-
-#include <wolfssl/wolfcrypt/sp_int.h>
-
-/* Initialize the big number to be zero.
- *
- * a  SP integer.
- * returns MP_OKAY always.
- */
-int sp_init(sp_int* a)
-{
-    a->used = 0;
-    a->size = SP_INT_DIGITS;
-
-    return MP_OKAY;
-}
-
-/* Initialize up to six big numbers to be zero.
- *
- * a  SP integer.
- * b  SP integer.
- * c  SP integer.
- * d  SP integer.
- * e  SP integer.
- * f  SP integer.
- * returns MP_OKAY always.
- */
-int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, sp_int* e,
-                  sp_int* f)
-{
-    if (a != NULL) {
-        a->used = 0;
-        a->size = SP_INT_DIGITS;
-    }
-    if (b != NULL) {
-        b->used = 0;
-        b->size = SP_INT_DIGITS;
-    }
-    if (c != NULL) {
-        c->used = 0;
-        c->size = SP_INT_DIGITS;
-    }
-    if (d != NULL) {
-        d->used = 0;
-        d->size = SP_INT_DIGITS;
-    }
-    if (e != NULL) {
-        e->used = 0;
-        e->size = SP_INT_DIGITS;
-    }
-    if (f != NULL) {
-        f->used = 0;
-        f->size = SP_INT_DIGITS;
-    }
-
-    return MP_OKAY;
-}
-
-/* Clear the data from the big number and set to zero.
- *
- * a  SP integer.
- */
-void sp_clear(sp_int* a)
-{
-    int i;
-
-    for (i=0; i<a->used; i++)
-        a->dp[i] = 0;
-    a->used = 0;
-}
-
-/* Calculate the number of 8-bit values required to represent the big number.
- *
- * a  SP integer.
- * returns the count.
- */
-int sp_unsigned_bin_size(sp_int* a)
-{
-    int size = sp_count_bits(a);
-    return (size + 7) / 8;
-}
-
-/* Convert a number as an array of bytes in big-endian format to a big number.
- *
- * a     SP integer.
- * in    Array of bytes.
- * inSz  Number of data bytes in array.
- * returns MP_OKAY always.
- */
-int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz)
-{
-    int i, j = 0, s = 0;
-
-    a->dp[0] = 0;
-    for (i = inSz-1; i >= 0; i--) {
-        a->dp[j] |= ((sp_int_digit)in[i]) << s;
-        if (s == DIGIT_BIT - 8) {
-            a->dp[++j] = 0;
-            s = 0;
-        }
-        else if (s > DIGIT_BIT - 8) {
-            s = DIGIT_BIT - s;
-            if (j + 1 >= a->size)
-                break;
-            a->dp[++j] = in[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    a->used = j + 1;
-    if (a->dp[j] == 0)
-        a->used--;
-
-    for (j++; j < a->size; j++)
-        a->dp[j] = 0;
-
-    return MP_OKAY;
-}
-
-/* Convert a number as string in big-endian format to a big number.
- * Only supports base-16 (hexadecimal).
- * Negative values not supported.
- *
- * a      SP integer.
- * in     NUL terminated string.
- * radix  Number of values in a digit.
- * returns BAD_FUNC_ARG when radix not supported or value is negative, MP_VAL
- * when a character is not valid and MP_OKAY otherwise.
- */
-int sp_read_radix(sp_int* a, const char* in, int radix)
-{
-    int     i, j, k;
-    char    ch;
-
-    if (radix != 16)
-        return BAD_FUNC_ARG;
-
-    if (*in == '-') {
-        return BAD_FUNC_ARG;
-    }
-
-    j = 0;
-    k = 0;
-    a->dp[0] = 0;
-    for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) {
-        ch = in[i];
-        if (ch >= '0' && ch <= '9')
-            ch -= '0';
-        else if (ch >= 'A' && ch <= 'F')
-            ch -= 'A' - 10;
-        else if (ch >= 'a' && ch <= 'f')
-            ch -= 'a' - 10;
-        else
-            return MP_VAL;
-
-        a->dp[k] |= ((sp_int_digit)ch) << j;
-        j += 4;
-        if (j == DIGIT_BIT && k < SP_INT_DIGITS)
-            a->dp[++k] = 0;
-        j &= DIGIT_BIT - 1;
-    }
-
-    a->used = k + 1;
-    if (a->dp[k] == 0)
-        a->used--;
-
-    for (k++; k < a->size; k++)
-        a->dp[k] = 0;
-
-    return MP_OKAY;
-}
-
-/* Compare two big numbers.
- *
- * a  SP integer.
- * b  SP integer.
- * returns MP_GT if a is greater than b, MP_LT if a is less than b and MP_EQ
- * when a equals b.
- */
-int sp_cmp(sp_int* a, sp_int* b)
-{
-    int i;
-
-    if (a->used > b->used)
-        return MP_GT;
-    else if (a->used < b->used)
-        return MP_LT;
-
-    for (i = a->used - 1; i >= 0; i--) {
-        if (a->dp[i] > b->dp[i])
-            return MP_GT;
-        else if (a->dp[i] < b->dp[i])
-            return MP_LT;
-    }
-    return MP_EQ;
-}
-
-/* Count the number of bits in the big number.
- *
- * a  SP integer.
- * returns the number of bits.
- */
-int sp_count_bits(sp_int* a)
-{
-    int r = 0;
-    sp_int_digit d;
-
-    r = a->used - 1;
-    while (r >= 0 && a->dp[r] == 0)
-        r--;
-    if (r < 0)
-        r = 0;
-    else {
-        d = a->dp[r];
-        r *= DIGIT_BIT;
-        while (d != 0) {
-            r++;
-            d >>= 1;
-        }
-    }
-
-    return r;
-}
-
-/* Determine if the most significant byte of the encoded big number as the top
- * bit set.
- *
- * a  SP integer.
- * returns 1 when the top bit is set and 0 otherwise.
- */
-int sp_leading_bit(sp_int* a)
-{
-    int bit = 0;
-    sp_int_digit d;
-
-    if (a->used > 0) {
-        d = a->dp[a->used - 1];
-        while (d > (sp_int_digit)0xff)
-            d >>= 8;
-        bit = (int)(d >> 7);
-    }
-
-    return bit;
-}
-
-/* Convert the big number to an array of bytes in big-endian format.
- * The array must be large enough for encoded number - use mp_unsigned_bin_size
- * to calculate the number of bytes required.
- *
- * a  SP integer.
- * returns MP_OKAY always.
- */
-int sp_to_unsigned_bin(sp_int* a, byte* out)
-{
-    int i, j, b;
-
-    j = sp_unsigned_bin_size(a) - 1;
-    for (i=0; j>=0; i++) {
-        for (b = 0; b < SP_WORD_SIZE; b += 8) {
-            out[j--] = a->dp[i] >> b;
-            if (j < 0)
-                break;
-        }
-    }
-
-    return MP_OKAY;
-}
-
-/* Ensure the data in the big number is zeroed.
- *
- * a  SP integer.
- */
-void sp_forcezero(sp_int* a)
-{
-    ForceZero(a->dp, a->used * sizeof(sp_int_digit));
-    a->used = 0;
-}
-
-/* Copy value of big number a into b.
- *
- * a  SP integer.
- * b  SP integer.
- * returns MP_OKAY always.
- */
-int sp_copy(sp_int* a, sp_int* b)
-{
-    if (a != b) {
-        XMEMCPY(b->dp, a->dp, a->used * sizeof(sp_int_digit));
-        b->used = a->used;
-    }
-    return MP_OKAY;
-}
-
-/* Set the big number to be the value of the digit.
- *
- * a  SP integer.
- * d  Digit to be set.
- * returns MP_OKAY always.
- */
-int sp_set(sp_int* a, sp_int_digit d)
-{
-    a->dp[0] = d;
-    a->used = 1;
-    return MP_OKAY;
-}
-
-/* Checks whether the value of the big number is zero.
- *
- * a  SP integer.
- * returns 1 when value is zero and 0 otherwise.
- */
-int sp_iszero(sp_int* a)
-{
-    return a->used == 0;
-}
-
-/* Recalculate the number of digits used.
- *
- * a  SP integer.
- */
-void sp_clamp(sp_int* a)
-{
-    int i;
-
-    for (i = a->used - 1; i >= 0 && a->dp[i] == 0; i--) {
-    }
-    a->used = i + 1;
-}
-
-/* Grow big number to be able to hold l digits.
- * This function does nothing as the number of digits is fixed.
- *
- * a  SP integer.
- * l  Number of digits.
- * retuns MP_MEM if the number of digits requested is more than available and
- * MP_OKAY otherwise.
- */
-int sp_grow(sp_int* a, int l)
-{
-    if (l > a->size)
-        return MP_MEM;
-    (void)a;
-    (void)l;
-    return MP_OKAY;
-}
-
-/* Sub a one digit number from the big number.
- *
- * a  SP integer.
- * d  Digit to subtract.
- * r  SP integer - result.
- * returns MP_OKAY always.
- */
-int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r)
-{
-    int i = 0;
-
-    r->used = a->used;
-    r->dp[0] = a->dp[0] - d;
-    if (r->dp[i] > a->dp[i]) {
-        for (; i < a->used; i++) {
-            r->dp[i] = a->dp[i] - 1;
-            if (r->dp[i] != (sp_int_digit)-1)
-               break;
-        }
-    }
-    for (; i < a->used; i++)
-        r->dp[i] = a->dp[i];
-
-    return MP_OKAY;
-}
-
-/* Compare a one digit number with a big number.
- *
- * a  SP integer.
- * d  Digit to compare with.
- * returns MP_GT if a is greater than d, MP_LT if a is less than d and MP_EQ
- * when a equals d.
- */
-int sp_cmp_d(sp_int *a, sp_int_digit d)
-{
-    /* special case for zero*/
-    if (a->used == 0) {
-        if (d == 0)
-            return MP_EQ;
-        else
-            return MP_LT;
-    }
-    else if (a->used > 1)
-        return MP_GT;
-
-    /* compare the only digit of a to d */
-    if (a->dp[0] > d)
-        return MP_GT;
-    else if (a->dp[0] < d)
-        return MP_LT;
-    return MP_EQ;
-}
-
-/* Left shift the number by number of bits.
- * Bits may be larger than the word size.
- *
- * a  SP integer.
- * n  Number of bits to shift.
- * returns MP_OKAY always.
- */
-static int sp_lshb(sp_int* a, int n)
-{
-    int i;
-
-    if (n >= SP_WORD_SIZE) {
-        sp_lshd(a, n / SP_WORD_SIZE);
-        n %= SP_WORD_SIZE;
-    }
-
-    if (n == 0)
-        return MP_OKAY;
-
-    a->dp[a->used] = 0;
-    for (i = a->used - 1; i >= 0; i--) {
-        a->dp[i+1] |= a->dp[i] >> (SP_WORD_SIZE - n);
-        a->dp[i] = a->dp[i] << n;
-    }
-    if (a->dp[a->used] != 0)
-        a->used++;
-
-    return MP_OKAY;
-}
-
-/* Subtract two large numbers into result: r = a - b
- * a must be greater than b.
- *
- * a  SP integer.
- * b  SP integer.
- * r  SP integer.
- * returns MP_OKAY always.
- */
-static int sp_sub(sp_int* a, sp_int* b, sp_int* r)
-{
-    int i;
-    sp_int_digit c = 0;
-    sp_int_digit t;
-
-    for (i = 0; i < a->used && i < b->used; i++) {
-        t = a->dp[i] - b->dp[i] - c;
-        if (c == 0)
-            c = t > a->dp[i];
-        else
-            c = t >= a->dp[i];
-        r->dp[i] = t;
-    }
-    for (; i < a->used; i++) {
-        r->dp[i] = a->dp[i] - c;
-        c = r->dp[i] == (sp_int_digit)-1;
-    }
-    r->used = i;
-    sp_clamp(r);
-
-    return MP_OKAY;
-}
-
-/* Calculate the r = a mod m.
- *
- * a  SP integer.
- * m  SP integer.
- * r  SP integer.
- * returns MP_OKAY always.
- */
-int sp_mod(sp_int* a, sp_int* m, sp_int* r)
-{
-    sp_int t;
-    int mBits = sp_count_bits(m);
-    int rBits;
-
-    if (a != r)
-        sp_copy(a, r);
-    sp_init(&t);
-
-    rBits = sp_count_bits(r);
-    while (rBits > mBits) {
-        sp_copy(m, &t);
-        sp_lshb(&t, rBits - mBits);
-
-        if (sp_cmp(&t, r) == MP_GT) {
-            sp_copy(m, &t);
-            sp_lshb(&t, rBits - mBits - 1);
-        }
-        sp_sub(r, &t, r);
-
-        rBits = sp_count_bits(r);
-    }
-    if (sp_cmp(r, m) != MP_LT)
-        sp_sub(r, m, r);
-
-    return MP_OKAY;
-}
-
-#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT)
-/* Clear all data in the big number and sets value to zero.
- *
- * a  SP integer.
- */
-void sp_zero(sp_int* a)
-{
-    XMEMSET(a->dp, 0, a->size);
-    a->used = 0;
-}
-
-/* Add a one digit number to the big number.
- *
- * a  SP integer.
- * d  Digit to add.
- * r  SP integer - result.
- * returns MP_OKAY always.
- */
-int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r)
-{
-    int i = 0;
-
-    r->used = a->used;
-    r->dp[0] = a->dp[0] + d;
-    if (r->dp[i] < a->dp[i]) {
-        for (; i < a->used; i++) {
-            r->dp[i] = a->dp[i] + 1;
-            if (r->dp[i] != 0)
-               break;
-        }
-
-        if (i == a->used) {
-            r->used++;
-            r->dp[i] = 1;
-        }
-    }
-    for (; i < a->used; i++)
-        r->dp[i] = a->dp[i];
-
-    return MP_OKAY;
-}
-
-/* Left shift the big number by a number of digits.
- * WIll chop off digits overflowing maximum size.
- *
- * a  SP integer.
- * s  Number of digits to shift.
- * returns MP_OKAY always.
- */
-int sp_lshd(sp_int* a, int s)
-{
-    if (a->used + s > a->size)
-        a->used = a->size - s;
-
-    XMEMMOVE(a->dp + s, a->dp, a->used * SP_INT_DIGITS);
-    a->used += s;
-    XMEMSET(a->dp, 0, s * sizeof(sp_int_digit));
-
-    return MP_OKAY;
-}
-#endif
-
-#ifndef NO_PWDBASED
-/* Add two large numbers into result: r = a + b
- *
- * a  SP integer.
- * b  SP integer.
- * r  SP integer.
- * returns MP_OKAY always.
- */
-int sp_add(sp_int* a, sp_int* b, sp_int* r)
-{
-    int i;
-    sp_digit c = 0;
-    sp_digit t;
-
-    for (i = 0; i < a->used && i < b->used; i++) {
-        t = a->dp[i] + b->dp[i] + c;
-        if (c == 0)
-            c = t < a->dp[i];
-        else
-            c = t <= a->dp[i];
-        r->dp[i] = t;
-    }
-    for (; i < a->used; i++) {
-        r->dp[i] = a->dp[i] + c;
-        c = r->dp[i] == 0;
-    }
-    for (; i < b->used; i++) {
-        r->dp[i] = b->dp[i] + c;
-        c = r->dp[i] == 0;
-    }
-    r->dp[i] = c;
-    r->used = (int)(i + c);
-
-    return MP_OKAY;
-}
-#endif
-
-#ifndef NO_RSA
-/* Set a number into the big number.
- *
- * a  SP integer.
- * b  Value to set.
- * returns MP_OKAY always.
- */
-int sp_set_int(sp_int* a, unsigned long b)
-{
-    a->used = 1;
-    a->dp[0] = b;
-
-    return MP_OKAY;
-}
-#endif
-
-#if !defined(USE_FAST_MATH)
-/* Returns the run time settings.
- *
- * returns the settings value.
- */
-word32 CheckRunTimeSettings(void)
-{
-    return CTC_SETTINGS;
-}
-#endif
-
-#endif
-
-
--- a/wolfcrypt/src/sp_x86_64.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46726 +0,0 @@
-/* sp.c
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/* Implementation by Sean Parkinson. */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/cpuid.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#ifdef RSA_LOW_MEM
-#define SP_RSA_PRIVATE_EXP_D
-
-#ifndef WOLFSSL_SP_SMALL
-#define WOLFSSL_SP_SMALL
-#endif
-#endif
-
-#include <wolfssl/wolfcrypt/sp.h>
-
-#ifdef WOLFSSL_SP_X86_64_ASM
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
-#ifndef WOLFSSL_SP_NO_2048
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 256
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_2048_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 2048 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<32 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit tmp[16];
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 8(%[tmp])\n\t"
-        "#  A[0] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 16(%[tmp])\n\t"
-        "#  A[0] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 24(%[tmp])\n\t"
-        "#  A[0] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 32(%[tmp])\n\t"
-        "#  A[0] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 40(%[tmp])\n\t"
-        "#  A[0] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 48(%[tmp])\n\t"
-        "#  A[0] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 56(%[tmp])\n\t"
-        "#  A[0] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 64(%[tmp])\n\t"
-        "#  A[0] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 72(%[tmp])\n\t"
-        "#  A[0] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 80(%[tmp])\n\t"
-        "#  A[0] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 88(%[tmp])\n\t"
-        "#  A[0] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 96(%[tmp])\n\t"
-        "#  A[0] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 104(%[tmp])\n\t"
-        "#  A[0] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 112(%[tmp])\n\t"
-        "#  A[0] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 120(%[tmp])\n\t"
-        "#  A[1] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 128(%[r])\n\t"
-        "#  A[2] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 136(%[r])\n\t"
-        "#  A[3] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 144(%[r])\n\t"
-        "#  A[4] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "#  A[5] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "#  A[6] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 168(%[r])\n\t"
-        "#  A[7] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 176(%[r])\n\t"
-        "#  A[8] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 184(%[r])\n\t"
-        "#  A[9] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 192(%[r])\n\t"
-        "#  A[10] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "#  A[11] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "#  A[12] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 216(%[r])\n\t"
-        "#  A[13] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 224(%[r])\n\t"
-        "#  A[14] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 232(%[r])\n\t"
-        "#  A[15] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 240(%[r])\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[16];
-
-    __asm__ __volatile__ (
-        "#  A[0] * A[0]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%r8\n\t"
-        "#  A[0] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 8(%[tmp])\n\t"
-        "#  A[0] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 16(%[tmp])\n\t"
-        "#  A[0] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[1] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 24(%[tmp])\n\t"
-        "#  A[0] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 32(%[tmp])\n\t"
-        "#  A[0] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 40(%[tmp])\n\t"
-        "#  A[0] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 48(%[tmp])\n\t"
-        "#  A[0] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 56(%[tmp])\n\t"
-        "#  A[0] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 64(%[tmp])\n\t"
-        "#  A[0] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 72(%[tmp])\n\t"
-        "#  A[0] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 80(%[tmp])\n\t"
-        "#  A[0] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 88(%[tmp])\n\t"
-        "#  A[0] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 96(%[tmp])\n\t"
-        "#  A[0] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 104(%[tmp])\n\t"
-        "#  A[0] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 112(%[tmp])\n\t"
-        "#  A[0] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 120(%[tmp])\n\t"
-        "#  A[1] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[2] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 128(%[r])\n\t"
-        "#  A[2] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[3] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 136(%[r])\n\t"
-        "#  A[3] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[4] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 144(%[r])\n\t"
-        "#  A[4] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[5] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 152(%[r])\n\t"
-        "#  A[5] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[6] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 160(%[r])\n\t"
-        "#  A[6] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[7] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 168(%[r])\n\t"
-        "#  A[7] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[8] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 176(%[r])\n\t"
-        "#  A[8] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[9] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 184(%[r])\n\t"
-        "#  A[9] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[10] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 192(%[r])\n\t"
-        "#  A[10] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[11] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 200(%[r])\n\t"
-        "#  A[11] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 208(%[r])\n\t"
-        "#  A[12] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[13] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 216(%[r])\n\t"
-        "#  A[13] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 224(%[r])\n\t"
-        "#  A[14] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 232(%[r])\n\t"
-        "#  A[15] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "movq	%%rcx, 240(%[r])\n\t"
-        "movq	%%r8, 248(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply a and b into r. (r = a * b)
- *
- * r   Result of multiplication.
- * a   First number to multiply.
- * b   Second number to multiply.
- */
-SP_NOINLINE static void sp_2048_mul_avx2_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit tmp[2*16];
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "# A[0] * B[0]\n\t"
-        "mulx	0(%[b]), %%r10, %%r11\n\t"
-        "# A[0] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "# A[0] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "movq	%%r10, 0(%[t])\n\t"
-        "movq	%%r11, 8(%[t])\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "# A[0] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "# A[0] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "# A[0] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "# A[0] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "# A[0] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "# A[0] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "# A[0] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "# A[0] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adcxq	%%r15, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	8(%[t]), %%r11\n\t"
-        "movq	16(%[t]), %%r12\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "# A[1] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[1] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 8(%[t])\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "# A[1] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[1] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[1] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[1] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[1] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[1] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	16(%[t]), %%r12\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "# A[2] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[2] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "# A[2] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[2] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[2] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[2] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[2] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[2] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "# A[3] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[3] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "# A[3] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[3] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[3] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[3] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[3] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[3] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "# A[4] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[4] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "# A[4] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[4] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[4] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[4] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[4] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[4] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "# A[5] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[5] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[5] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[5] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[5] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[5] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[5] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[5] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "# A[6] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[6] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[6] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[6] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[6] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[6] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[6] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[6] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "# A[7] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[7] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[7] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[7] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[7] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[7] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[7] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[7] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "# A[8] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[8] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[8] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[8] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[8] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[8] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[8] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[8] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	72(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[9] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[9] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[9] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[9] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[9] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[9] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[9] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[9] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[10] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[10] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[10] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[10] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[10] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[10] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[10] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[10] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[11] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[11] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[11] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[11] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[11] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[11] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[11] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[11] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[12] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[12] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[12] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[12] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[12] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[12] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[12] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[12] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[13] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[13] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[13] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[13] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[13] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[13] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[13] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[13] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[14] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[14] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[14] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[14] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[14] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[14] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[14] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[14] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[15] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[15] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[15] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[15] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[15] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[15] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[15] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[15] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        :
-        : [a] "r" (a), [b] "r" (b), [t] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx",
-          "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_avx2_16(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[32];
-
-    __asm__ __volatile__ (
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 1\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "xorq	%%r13, %%r13\n\t"
-        "xorq	%%r14, %%r14\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "# A[1] x A[0]\n\t"
-        "movq	0(%[a]), %%rdx\n\t"
-        "mulxq	8(%[a]), %%r10, %%r11\n\t"
-        "# A[2] x A[0]\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[3] x A[0]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[4] x A[0]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[5] x A[0]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 8(%[tmp])\n\t"
-        "movq	%%r11, 16(%[tmp])\n\t"
-        "movq	%%r12, 24(%[tmp])\n\t"
-        "movq	%%r13, 32(%[tmp])\n\t"
-        "movq	%%r14, 40(%[tmp])\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "# A[6] x A[0]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[7] x A[0]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[0]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[9] x A[0]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[0]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 48(%[tmp])\n\t"
-        "movq	%%r10, 56(%[tmp])\n\t"
-        "movq	%%r11, 64(%[tmp])\n\t"
-        "movq	%%r12, 72(%[tmp])\n\t"
-        "movq	%%r13, 80(%[tmp])\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[11] x A[0]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[0]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[0]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[0]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[15] x A[0]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 88(%[tmp])\n\t"
-        "movq	%%r15, 96(%[tmp])\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 2\n\t"
-        "movq	24(%[tmp]), %%r13\n\t"
-        "movq	32(%[tmp]), %%r14\n\t"
-        "movq	40(%[tmp]), %%r15\n\t"
-        "movq	48(%[tmp]), %%r10\n\t"
-        "movq	56(%[tmp]), %%r11\n\t"
-        "movq	64(%[tmp]), %%r12\n\t"
-        "# A[2] x A[1]\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[3] x A[1]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[4] x A[1]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[5] x A[1]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[6] x A[1]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 24(%[tmp])\n\t"
-        "movq	%%r14, 32(%[tmp])\n\t"
-        "movq	%%r15, 40(%[tmp])\n\t"
-        "movq	%%r10, 48(%[tmp])\n\t"
-        "movq	%%r11, 56(%[tmp])\n\t"
-        "movq	72(%[tmp]), %%r13\n\t"
-        "movq	80(%[tmp]), %%r14\n\t"
-        "movq	88(%[tmp]), %%r15\n\t"
-        "movq	96(%[tmp]), %%r10\n\t"
-        "movq	104(%[tmp]), %%r11\n\t"
-        "# A[7] x A[1]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[8] x A[1]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[9] x A[1]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[10] x A[1]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[11] x A[1]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 64(%[tmp])\n\t"
-        "movq	%%r13, 72(%[tmp])\n\t"
-        "movq	%%r14, 80(%[tmp])\n\t"
-        "movq	%%r15, 88(%[tmp])\n\t"
-        "movq	%%r10, 96(%[tmp])\n\t"
-        "movq	112(%[tmp]), %%r12\n\t"
-        "movq	120(%[tmp]), %%r13\n\t"
-        "movq	128(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[12] x A[1]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[1]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[14] x A[1]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[1]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[15] x A[2]\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 104(%[tmp])\n\t"
-        "movq	%%r12, 112(%[tmp])\n\t"
-        "movq	%%r13, 120(%[tmp])\n\t"
-        "movq	%%r14, 128(%[tmp])\n\t"
-        "movq	%%r15, 136(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 144(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 3\n\t"
-        "movq	40(%[tmp]), %%r10\n\t"
-        "movq	48(%[tmp]), %%r11\n\t"
-        "movq	56(%[tmp]), %%r12\n\t"
-        "movq	64(%[tmp]), %%r13\n\t"
-        "movq	72(%[tmp]), %%r14\n\t"
-        "movq	80(%[tmp]), %%r15\n\t"
-        "# A[3] x A[2]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[4] x A[2]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[5] x A[2]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[6] x A[2]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[7] x A[2]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 40(%[tmp])\n\t"
-        "movq	%%r11, 48(%[tmp])\n\t"
-        "movq	%%r12, 56(%[tmp])\n\t"
-        "movq	%%r13, 64(%[tmp])\n\t"
-        "movq	%%r14, 72(%[tmp])\n\t"
-        "movq	88(%[tmp]), %%r10\n\t"
-        "movq	96(%[tmp]), %%r11\n\t"
-        "movq	104(%[tmp]), %%r12\n\t"
-        "movq	112(%[tmp]), %%r13\n\t"
-        "movq	120(%[tmp]), %%r14\n\t"
-        "# A[8] x A[2]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[9] x A[2]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[10] x A[2]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[11] x A[2]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[12] x A[2]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 80(%[tmp])\n\t"
-        "movq	%%r10, 88(%[tmp])\n\t"
-        "movq	%%r11, 96(%[tmp])\n\t"
-        "movq	%%r12, 104(%[tmp])\n\t"
-        "movq	%%r13, 112(%[tmp])\n\t"
-        "movq	128(%[tmp]), %%r15\n\t"
-        "movq	136(%[tmp]), %%r10\n\t"
-        "movq	144(%[tmp]), %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[13] x A[2]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[2]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[14] x A[3]\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[4]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[14] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 120(%[tmp])\n\t"
-        "movq	%%r15, 128(%[tmp])\n\t"
-        "movq	%%r10, 136(%[tmp])\n\t"
-        "movq	%%r11, 144(%[tmp])\n\t"
-        "movq	%%r12, 152(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 160(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 4\n\t"
-        "movq	56(%[tmp]), %%r13\n\t"
-        "movq	64(%[tmp]), %%r14\n\t"
-        "movq	72(%[tmp]), %%r15\n\t"
-        "movq	80(%[tmp]), %%r10\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "movq	96(%[tmp]), %%r12\n\t"
-        "# A[4] x A[3]\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[5] x A[3]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[6] x A[3]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[7] x A[3]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[3]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 56(%[tmp])\n\t"
-        "movq	%%r14, 64(%[tmp])\n\t"
-        "movq	%%r15, 72(%[tmp])\n\t"
-        "movq	%%r10, 80(%[tmp])\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	104(%[tmp]), %%r13\n\t"
-        "movq	112(%[tmp]), %%r14\n\t"
-        "movq	120(%[tmp]), %%r15\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "# A[9] x A[3]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[3]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[11] x A[3]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[3]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[3]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 96(%[tmp])\n\t"
-        "movq	%%r13, 104(%[tmp])\n\t"
-        "movq	%%r14, 112(%[tmp])\n\t"
-        "movq	%%r15, 120(%[tmp])\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	144(%[tmp]), %%r12\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[13] x A[4]\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[13] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[13] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[13] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	%%r12, 144(%[tmp])\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 5\n\t"
-        "movq	72(%[tmp]), %%r10\n\t"
-        "movq	80(%[tmp]), %%r11\n\t"
-        "movq	88(%[tmp]), %%r12\n\t"
-        "movq	96(%[tmp]), %%r13\n\t"
-        "movq	104(%[tmp]), %%r14\n\t"
-        "movq	112(%[tmp]), %%r15\n\t"
-        "# A[5] x A[4]\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[6] x A[4]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[7] x A[4]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[8] x A[4]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[9] x A[4]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 72(%[tmp])\n\t"
-        "movq	%%r11, 80(%[tmp])\n\t"
-        "movq	%%r12, 88(%[tmp])\n\t"
-        "movq	%%r13, 96(%[tmp])\n\t"
-        "movq	%%r14, 104(%[tmp])\n\t"
-        "movq	120(%[tmp]), %%r10\n\t"
-        "movq	128(%[tmp]), %%r11\n\t"
-        "movq	136(%[tmp]), %%r12\n\t"
-        "movq	144(%[tmp]), %%r13\n\t"
-        "movq	152(%[tmp]), %%r14\n\t"
-        "# A[10] x A[4]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[11] x A[4]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[12] x A[4]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[12] x A[5]\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[12] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 112(%[tmp])\n\t"
-        "movq	%%r10, 120(%[tmp])\n\t"
-        "movq	%%r11, 128(%[tmp])\n\t"
-        "movq	%%r12, 136(%[tmp])\n\t"
-        "movq	%%r13, 144(%[tmp])\n\t"
-        "movq	160(%[tmp]), %%r15\n\t"
-        "movq	168(%[tmp]), %%r10\n\t"
-        "movq	176(%[tmp]), %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[12] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[12] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[12] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[12] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 152(%[tmp])\n\t"
-        "movq	%%r15, 160(%[tmp])\n\t"
-        "movq	%%r10, 168(%[tmp])\n\t"
-        "movq	%%r11, 176(%[tmp])\n\t"
-        "movq	%%r12, 184(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 192(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 6\n\t"
-        "movq	88(%[tmp]), %%r13\n\t"
-        "movq	96(%[tmp]), %%r14\n\t"
-        "movq	104(%[tmp]), %%r15\n\t"
-        "movq	112(%[tmp]), %%r10\n\t"
-        "movq	120(%[tmp]), %%r11\n\t"
-        "movq	128(%[tmp]), %%r12\n\t"
-        "# A[6] x A[5]\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[7] x A[5]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[8] x A[5]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[9] x A[5]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[10] x A[5]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 88(%[tmp])\n\t"
-        "movq	%%r14, 96(%[tmp])\n\t"
-        "movq	%%r15, 104(%[tmp])\n\t"
-        "movq	%%r10, 112(%[tmp])\n\t"
-        "movq	%%r11, 120(%[tmp])\n\t"
-        "movq	136(%[tmp]), %%r13\n\t"
-        "movq	144(%[tmp]), %%r14\n\t"
-        "movq	152(%[tmp]), %%r15\n\t"
-        "movq	160(%[tmp]), %%r10\n\t"
-        "movq	168(%[tmp]), %%r11\n\t"
-        "# A[11] x A[5]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[11] x A[6]\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[11] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[11] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[11] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 128(%[tmp])\n\t"
-        "movq	%%r13, 136(%[tmp])\n\t"
-        "movq	%%r14, 144(%[tmp])\n\t"
-        "movq	%%r15, 152(%[tmp])\n\t"
-        "movq	%%r10, 160(%[tmp])\n\t"
-        "movq	176(%[tmp]), %%r12\n\t"
-        "movq	184(%[tmp]), %%r13\n\t"
-        "movq	192(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[11] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[9]\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[13] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[13] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[13] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 168(%[tmp])\n\t"
-        "movq	%%r12, 176(%[tmp])\n\t"
-        "movq	%%r13, 184(%[tmp])\n\t"
-        "movq	%%r14, 192(%[tmp])\n\t"
-        "movq	%%r15, 200(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 208(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 7\n\t"
-        "movq	104(%[tmp]), %%r10\n\t"
-        "movq	112(%[tmp]), %%r11\n\t"
-        "movq	120(%[tmp]), %%r12\n\t"
-        "movq	128(%[tmp]), %%r13\n\t"
-        "movq	136(%[tmp]), %%r14\n\t"
-        "movq	144(%[tmp]), %%r15\n\t"
-        "# A[7] x A[6]\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[6]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[9] x A[6]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[6]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[10] x A[7]\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	152(%[tmp]), %%r10\n\t"
-        "movq	160(%[tmp]), %%r11\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "# A[10] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[10] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[6]\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[14] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[14] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[14] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[14] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[14] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 8\n\t"
-        "movq	120(%[tmp]), %%r13\n\t"
-        "movq	128(%[tmp]), %%r14\n\t"
-        "movq	136(%[tmp]), %%r15\n\t"
-        "movq	144(%[tmp]), %%r10\n\t"
-        "movq	152(%[tmp]), %%r11\n\t"
-        "movq	160(%[tmp]), %%r12\n\t"
-        "# A[8] x A[7]\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[9] x A[7]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[9] x A[8]\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[15] x A[3]\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[15] x A[4]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 120(%[tmp])\n\t"
-        "movq	%%r14, 128(%[tmp])\n\t"
-        "movq	%%r15, 136(%[tmp])\n\t"
-        "movq	%%r10, 144(%[tmp])\n\t"
-        "movq	%%r11, 152(%[tmp])\n\t"
-        "movq	168(%[tmp]), %%r13\n\t"
-        "movq	176(%[tmp]), %%r14\n\t"
-        "movq	184(%[tmp]), %%r15\n\t"
-        "movq	192(%[tmp]), %%r10\n\t"
-        "movq	200(%[tmp]), %%r11\n\t"
-        "# A[15] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[15] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[15] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[15] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 160(%[tmp])\n\t"
-        "movq	%%r13, 168(%[tmp])\n\t"
-        "movq	%%r14, 176(%[tmp])\n\t"
-        "movq	%%r15, 184(%[tmp])\n\t"
-        "movq	%%r10, 192(%[tmp])\n\t"
-        "movq	208(%[tmp]), %%r12\n\t"
-        "movq	216(%[tmp]), %%r13\n\t"
-        "movq	224(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[15] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[15] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[15] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[15] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 200(%[tmp])\n\t"
-        "movq	%%r12, 208(%[tmp])\n\t"
-        "movq	%%r13, 216(%[tmp])\n\t"
-        "movq	%%r14, 224(%[tmp])\n\t"
-        "movq	%%r15, 232(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 240(%[tmp])\n\t"
-        "movq	%%r9, 248(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Double and Add in A[i] x A[i]\n\t"
-        "movq	8(%[tmp]), %%r11\n\t"
-        "# A[0] x A[0]\n\t"
-        "movq	0(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "movq	%%rax, 0(%[tmp])\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r11, 8(%[tmp])\n\t"
-        "movq	16(%[tmp]), %%r10\n\t"
-        "movq	24(%[tmp]), %%r11\n\t"
-        "# A[1] x A[1]\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 16(%[tmp])\n\t"
-        "movq	%%r11, 24(%[tmp])\n\t"
-        "movq	32(%[tmp]), %%r10\n\t"
-        "movq	40(%[tmp]), %%r11\n\t"
-        "# A[2] x A[2]\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 32(%[tmp])\n\t"
-        "movq	%%r11, 40(%[tmp])\n\t"
-        "movq	48(%[tmp]), %%r10\n\t"
-        "movq	56(%[tmp]), %%r11\n\t"
-        "# A[3] x A[3]\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 48(%[tmp])\n\t"
-        "movq	%%r11, 56(%[tmp])\n\t"
-        "movq	64(%[tmp]), %%r10\n\t"
-        "movq	72(%[tmp]), %%r11\n\t"
-        "# A[4] x A[4]\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 64(%[tmp])\n\t"
-        "movq	%%r11, 72(%[tmp])\n\t"
-        "movq	80(%[tmp]), %%r10\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "# A[5] x A[5]\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 80(%[tmp])\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	96(%[tmp]), %%r10\n\t"
-        "movq	104(%[tmp]), %%r11\n\t"
-        "# A[6] x A[6]\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 96(%[tmp])\n\t"
-        "movq	%%r11, 104(%[tmp])\n\t"
-        "movq	112(%[tmp]), %%r10\n\t"
-        "movq	120(%[tmp]), %%r11\n\t"
-        "# A[7] x A[7]\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 112(%[tmp])\n\t"
-        "movq	%%r11, 120(%[tmp])\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "# A[8] x A[8]\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 128(%[r])\n\t"
-        "movq	%%r11, 136(%[r])\n\t"
-        "movq	144(%[tmp]), %%r10\n\t"
-        "movq	152(%[tmp]), %%r11\n\t"
-        "# A[9] x A[9]\n\t"
-        "movq	72(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 144(%[r])\n\t"
-        "movq	%%r11, 152(%[r])\n\t"
-        "movq	160(%[tmp]), %%r10\n\t"
-        "movq	168(%[tmp]), %%r11\n\t"
-        "# A[10] x A[10]\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 160(%[r])\n\t"
-        "movq	%%r11, 168(%[r])\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "# A[11] x A[11]\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 176(%[r])\n\t"
-        "movq	%%r11, 184(%[r])\n\t"
-        "movq	192(%[tmp]), %%r10\n\t"
-        "movq	200(%[tmp]), %%r11\n\t"
-        "# A[12] x A[12]\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 192(%[r])\n\t"
-        "movq	%%r11, 200(%[r])\n\t"
-        "movq	208(%[tmp]), %%r10\n\t"
-        "movq	216(%[tmp]), %%r11\n\t"
-        "# A[13] x A[13]\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 208(%[r])\n\t"
-        "movq	%%r11, 216(%[r])\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "# A[14] x A[14]\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 224(%[r])\n\t"
-        "movq	%%r11, 232(%[r])\n\t"
-        "movq	240(%[tmp]), %%r10\n\t"
-        "movq	248(%[tmp]), %%r11\n\t"
-        "# A[15] x A[15]\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 240(%[r])\n\t"
-        "movq	%%r11, 248(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp)/2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "addq	(%[b]), %%rax\n\t"
-        "movq	%%rax, (%[r])\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "adcq	8(%[b]), %%rax\n\t"
-        "movq	%%rax, 8(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "adcq	16(%[b]), %%rax\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "adcq	24(%[b]), %%rax\n\t"
-        "movq	%%rax, 24(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "adcq	32(%[b]), %%rax\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "adcq	40(%[b]), %%rax\n\t"
-        "movq	%%rax, 40(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "adcq	48(%[b]), %%rax\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "adcq	56(%[b]), %%rax\n\t"
-        "movq	%%rax, 56(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "adcq	64(%[b]), %%rax\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "adcq	72(%[b]), %%rax\n\t"
-        "movq	%%rax, 72(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "adcq	80(%[b]), %%rax\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "adcq	88(%[b]), %%rax\n\t"
-        "movq	%%rax, 88(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "adcq	96(%[b]), %%rax\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "adcq	104(%[b]), %%rax\n\t"
-        "movq	%%rax, 104(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "adcq	112(%[b]), %%rax\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "adcq	120(%[b]), %%rax\n\t"
-        "movq	%%rax, 120(%[r])\n\t"
-        "adcq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r8\n\t"
-        "movq	8(%[a]), %%r9\n\t"
-        "movq	0(%[b]), %%rdx\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "subq	%%rdx, %%r8\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "movq	%%r8, 0(%[a])\n\t"
-        "movq	16(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "movq	%%r9, 8(%[a])\n\t"
-        "movq	24(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	32(%[b]), %%rdx\n\t"
-        "movq	%%r8, 16(%[a])\n\t"
-        "movq	32(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "movq	%%r9, 24(%[a])\n\t"
-        "movq	40(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	48(%[b]), %%rdx\n\t"
-        "movq	%%r8, 32(%[a])\n\t"
-        "movq	48(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "movq	%%r9, 40(%[a])\n\t"
-        "movq	56(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	64(%[b]), %%rdx\n\t"
-        "movq	%%r8, 48(%[a])\n\t"
-        "movq	64(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "movq	%%r9, 56(%[a])\n\t"
-        "movq	72(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	80(%[b]), %%rdx\n\t"
-        "movq	%%r8, 64(%[a])\n\t"
-        "movq	80(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "movq	%%r9, 72(%[a])\n\t"
-        "movq	88(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	96(%[b]), %%rdx\n\t"
-        "movq	%%r8, 80(%[a])\n\t"
-        "movq	96(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "movq	%%r9, 88(%[a])\n\t"
-        "movq	104(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	112(%[b]), %%rdx\n\t"
-        "movq	%%r8, 96(%[a])\n\t"
-        "movq	112(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "movq	%%r9, 104(%[a])\n\t"
-        "movq	120(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	128(%[b]), %%rdx\n\t"
-        "movq	%%r8, 112(%[a])\n\t"
-        "movq	128(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "movq	%%r9, 120(%[a])\n\t"
-        "movq	136(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	144(%[b]), %%rdx\n\t"
-        "movq	%%r8, 128(%[a])\n\t"
-        "movq	144(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "movq	%%r9, 136(%[a])\n\t"
-        "movq	152(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	160(%[b]), %%rdx\n\t"
-        "movq	%%r8, 144(%[a])\n\t"
-        "movq	160(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "movq	%%r9, 152(%[a])\n\t"
-        "movq	168(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	176(%[b]), %%rdx\n\t"
-        "movq	%%r8, 160(%[a])\n\t"
-        "movq	176(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "movq	%%r9, 168(%[a])\n\t"
-        "movq	184(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	192(%[b]), %%rdx\n\t"
-        "movq	%%r8, 176(%[a])\n\t"
-        "movq	192(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	200(%[b]), %%rcx\n\t"
-        "movq	%%r9, 184(%[a])\n\t"
-        "movq	200(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	208(%[b]), %%rdx\n\t"
-        "movq	%%r8, 192(%[a])\n\t"
-        "movq	208(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	216(%[b]), %%rcx\n\t"
-        "movq	%%r9, 200(%[a])\n\t"
-        "movq	216(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	224(%[b]), %%rdx\n\t"
-        "movq	%%r8, 208(%[a])\n\t"
-        "movq	224(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	232(%[b]), %%rcx\n\t"
-        "movq	%%r9, 216(%[a])\n\t"
-        "movq	232(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	240(%[b]), %%rdx\n\t"
-        "movq	%%r8, 224(%[a])\n\t"
-        "movq	240(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	248(%[b]), %%rcx\n\t"
-        "movq	%%r9, 232(%[a])\n\t"
-        "movq	248(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	%%r8, 240(%[a])\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	%%r9, 248(%[a])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "rdx", "rcx", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "addq	(%[b]), %%rax\n\t"
-        "movq	%%rax, (%[r])\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "adcq	8(%[b]), %%rax\n\t"
-        "movq	%%rax, 8(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "adcq	16(%[b]), %%rax\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "adcq	24(%[b]), %%rax\n\t"
-        "movq	%%rax, 24(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "adcq	32(%[b]), %%rax\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "adcq	40(%[b]), %%rax\n\t"
-        "movq	%%rax, 40(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "adcq	48(%[b]), %%rax\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "adcq	56(%[b]), %%rax\n\t"
-        "movq	%%rax, 56(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "adcq	64(%[b]), %%rax\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "adcq	72(%[b]), %%rax\n\t"
-        "movq	%%rax, 72(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "adcq	80(%[b]), %%rax\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "adcq	88(%[b]), %%rax\n\t"
-        "movq	%%rax, 88(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "adcq	96(%[b]), %%rax\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "adcq	104(%[b]), %%rax\n\t"
-        "movq	%%rax, 104(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "adcq	112(%[b]), %%rax\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "adcq	120(%[b]), %%rax\n\t"
-        "movq	%%rax, 120(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "adcq	128(%[b]), %%rax\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "adcq	136(%[b]), %%rax\n\t"
-        "movq	%%rax, 136(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "adcq	144(%[b]), %%rax\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "adcq	152(%[b]), %%rax\n\t"
-        "movq	%%rax, 152(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "adcq	160(%[b]), %%rax\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "adcq	168(%[b]), %%rax\n\t"
-        "movq	%%rax, 168(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "adcq	176(%[b]), %%rax\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "adcq	184(%[b]), %%rax\n\t"
-        "movq	%%rax, 184(%[r])\n\t"
-        "movq	192(%[a]), %%rax\n\t"
-        "adcq	192(%[b]), %%rax\n\t"
-        "movq	%%rax, 192(%[r])\n\t"
-        "movq	200(%[a]), %%rax\n\t"
-        "adcq	200(%[b]), %%rax\n\t"
-        "movq	%%rax, 200(%[r])\n\t"
-        "movq	208(%[a]), %%rax\n\t"
-        "adcq	208(%[b]), %%rax\n\t"
-        "movq	%%rax, 208(%[r])\n\t"
-        "movq	216(%[a]), %%rax\n\t"
-        "adcq	216(%[b]), %%rax\n\t"
-        "movq	%%rax, 216(%[r])\n\t"
-        "movq	224(%[a]), %%rax\n\t"
-        "adcq	224(%[b]), %%rax\n\t"
-        "movq	%%rax, 224(%[r])\n\t"
-        "movq	232(%[a]), %%rax\n\t"
-        "adcq	232(%[b]), %%rax\n\t"
-        "movq	%%rax, 232(%[r])\n\t"
-        "movq	240(%[a]), %%rax\n\t"
-        "adcq	240(%[b]), %%rax\n\t"
-        "movq	%%rax, 240(%[r])\n\t"
-        "movq	248(%[a]), %%rax\n\t"
-        "adcq	248(%[b]), %%rax\n\t"
-        "movq	%%rax, 248(%[r])\n\t"
-        "adcq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<16; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 16; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit b1[16];
-    sp_digit z2[32];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_16(a1, a, &a[16]);
-    cb = sp_2048_add_16(b1, b, &b[16]);
-    u  = ca & cb;
-    sp_2048_mul_16(z1, a1, b1);
-    sp_2048_mul_16(z2, &a[16], &b[16]);
-    sp_2048_mul_16(z0, a, b);
-    sp_2048_mask_16(r + 32, a1, 0 - cb);
-    sp_2048_mask_16(b1, b1, 0 - ca);
-    u += sp_2048_add_16(r + 32, r + 32, b1);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[32];
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit u;
-
-    u = sp_2048_add_16(a1, a, &a[16]);
-    sp_2048_sqr_16(z1, a1);
-    sp_2048_sqr_16(z2, &a[16]);
-    sp_2048_sqr_16(z0, a);
-    sp_2048_mask_16(r + 32, a1, 0 - u);
-    u += sp_2048_add_16(r + 32, r + 32, r + 32);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit b1[16];
-    sp_digit z2[32];
-    sp_digit u, ca, cb;
-
-    ca = sp_2048_add_16(a1, a, &a[16]);
-    cb = sp_2048_add_16(b1, b, &b[16]);
-    u  = ca & cb;
-    sp_2048_mul_avx2_16(z1, a1, b1);
-    sp_2048_mul_avx2_16(z2, &a[16], &b[16]);
-    sp_2048_mul_avx2_16(z0, a, b);
-    sp_2048_mask_16(r + 32, a1, 0 - cb);
-    sp_2048_mask_16(b1, b1, 0 - ca);
-    u += sp_2048_add_16(r + 32, r + 32, b1);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[32];
-    sp_digit z1[32];
-    sp_digit a1[16];
-    sp_digit u;
-
-    u = sp_2048_add_16(a1, a, &a[16]);
-    sp_2048_sqr_avx2_16(z1, a1);
-    sp_2048_sqr_avx2_16(z2, &a[16]);
-    sp_2048_sqr_avx2_16(z0, a);
-    sp_2048_mask_16(r + 32, a1, 0 - u);
-    u += sp_2048_add_16(r + 32, r + 32, r + 32);
-    u += sp_2048_sub_in_place_32(z1, z2);
-    u += sp_2048_sub_in_place_32(z1, z0);
-    u += sp_2048_add_32(r + 16, r + 16, z1);
-    r[48] = u;
-    XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1));
-    sp_2048_add_32(r + 32, r + 32, z2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r8\n\t"
-        "movq	8(%[a]), %%r9\n\t"
-        "movq	0(%[b]), %%rdx\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "subq	%%rdx, %%r8\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "movq	%%r8, 0(%[a])\n\t"
-        "movq	16(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "movq	%%r9, 8(%[a])\n\t"
-        "movq	24(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	32(%[b]), %%rdx\n\t"
-        "movq	%%r8, 16(%[a])\n\t"
-        "movq	32(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "movq	%%r9, 24(%[a])\n\t"
-        "movq	40(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	48(%[b]), %%rdx\n\t"
-        "movq	%%r8, 32(%[a])\n\t"
-        "movq	48(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "movq	%%r9, 40(%[a])\n\t"
-        "movq	56(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	64(%[b]), %%rdx\n\t"
-        "movq	%%r8, 48(%[a])\n\t"
-        "movq	64(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "movq	%%r9, 56(%[a])\n\t"
-        "movq	72(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	80(%[b]), %%rdx\n\t"
-        "movq	%%r8, 64(%[a])\n\t"
-        "movq	80(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "movq	%%r9, 72(%[a])\n\t"
-        "movq	88(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	96(%[b]), %%rdx\n\t"
-        "movq	%%r8, 80(%[a])\n\t"
-        "movq	96(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "movq	%%r9, 88(%[a])\n\t"
-        "movq	104(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	112(%[b]), %%rdx\n\t"
-        "movq	%%r8, 96(%[a])\n\t"
-        "movq	112(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "movq	%%r9, 104(%[a])\n\t"
-        "movq	120(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	%%r8, 112(%[a])\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	%%r9, 120(%[a])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "rdx", "rcx", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_16(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 16);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_16(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_16(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit t[16];
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[b]), %%rax\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 0(%[t])\n\t"
-        "movq	%%rcx, 8(%[t])\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 16(%[t])\n\t"
-        "movq	%%rcx, 24(%[t])\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 32(%[t])\n\t"
-        "movq	%%rcx, 40(%[t])\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 48(%[t])\n\t"
-        "movq	%%rcx, 56(%[t])\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 64(%[t])\n\t"
-        "movq	%%rcx, 72(%[t])\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 80(%[t])\n\t"
-        "movq	%%rcx, 88(%[t])\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 96(%[t])\n\t"
-        "movq	%%rcx, 104(%[t])\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 112(%[t])\n\t"
-        "movq	%%rcx, 120(%[t])\n\t"
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[t]), %%rdx\n\t"
-        "subq	%%rdx,%%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "movq	32(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "movq	40(%[a]), %%rcx\n\t"
-        "movq	40(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "movq	48(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 40(%[r])\n\t"
-        "movq	56(%[a]), %%rcx\n\t"
-        "movq	56(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "movq	64(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "movq	72(%[a]), %%rcx\n\t"
-        "movq	72(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "movq	80(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 72(%[r])\n\t"
-        "movq	88(%[a]), %%rcx\n\t"
-        "movq	88(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "movq	96(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 88(%[r])\n\t"
-        "movq	104(%[a]), %%rcx\n\t"
-        "movq	104(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "movq	112(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "movq	120(%[a]), %%rcx\n\t"
-        "movq	120(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	%%rcx, 120(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "movq	8(%[a]), %%r13\n\t"
-        "\nL_mont_loop_16:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "imulq	%[mp], %%r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	0(%[m])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	8(%[m])\n\t"
-        "movq	%%r13, %%r12\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r12\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	16(%[m])\n\t"
-        "movq	16(%[a]), %%r13\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r13\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[m])\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	32(%[m])\n\t"
-        "movq	32(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 32(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	40(%[m])\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	48(%[m])\n\t"
-        "movq	48(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 48(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	56(%[m])\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	64(%[m])\n\t"
-        "movq	64(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 64(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[m])\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	80(%[m])\n\t"
-        "movq	80(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 80(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	88(%[m])\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	96(%[m])\n\t"
-        "movq	96(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 96(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	104(%[m])\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	112(%[m])\n\t"
-        "movq	112(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 112(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "mulq	120(%[m])\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%[ca], %%rdx\n\t"
-        "movq	$0, %[ca]\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "addq	%%r9, %%r11\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "adcq	%%rdx, 128(%[a])\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$8, %%rcx\n\t"
-        "cmpq	$128, %%rcx\n\t"
-        "jl	L_mont_loop_16\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        "movq	%%r13, 8(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13"
-    );
-
-    sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_16(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_16(r, a, b);
-    sp_2048_mont_reduce_16(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_16(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_16(r, a);
-    sp_2048_mont_reduce_16(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	(%[a])\n\t"
-        "movq	%%rax, %%rbx\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[2] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[3] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 24(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[5] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 40(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[6] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 48(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[7] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[8] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[9] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 72(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 80(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[11] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 88(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[12] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 96(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[13] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[14] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[15] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 120(%[r])\n\t"
-        "movq	%%rcx, 128(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rdx\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "mulxq	(%[a]), %%r8, %%r9\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "mulxq	8(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[2] * B\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[3] * B\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 24(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[5] * B\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 40(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[6] * B\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 48(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[7] * B\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 56(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[8] * B\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[9] * B\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 72(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 80(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[11] * B\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 88(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[12] * B\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 96(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[13] * B\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 104(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[14] * B\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[15] * B\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "adcxq	%%r10, %%r8\n\t"
-        "movq	%%r9, 120(%[r])\n\t"
-        "movq	%%r8, 128(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "movq	%[d0], %%rax\n\t"
-        "movq	%[d1], %%rdx\n\t"
-        "divq	%[div]\n\t"
-        "movq	%%rax, %[r]\n\t"
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "rax", "rdx"
-    );
-
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_2048_cmp_16(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-    __asm__ __volatile__ (
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	$-1, %%rdx\n\t"
-        "movq	120(%[a]), %%rbx\n\t"
-        "movq	120(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	112(%[a]), %%rbx\n\t"
-        "movq	112(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	104(%[a]), %%rbx\n\t"
-        "movq	104(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	96(%[a]), %%rbx\n\t"
-        "movq	96(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	88(%[a]), %%rbx\n\t"
-        "movq	88(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	80(%[a]), %%rbx\n\t"
-        "movq	80(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	72(%[a]), %%rbx\n\t"
-        "movq	72(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	64(%[a]), %%rbx\n\t"
-        "movq	64(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	56(%[a]), %%rbx\n\t"
-        "movq	56(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	48(%[a]), %%rbx\n\t"
-        "movq	48(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	40(%[a]), %%rbx\n\t"
-        "movq	40(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	32(%[a]), %%rbx\n\t"
-        "movq	32(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	24(%[a]), %%rbx\n\t"
-        "movq	24(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	16(%[a]), %%rbx\n\t"
-        "movq	16(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	8(%[a]), %%rbx\n\t"
-        "movq	8(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	0(%[a]), %%rbx\n\t"
-        "movq	0(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "xorq	%%rdx, %[r]\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "rax", "rdx", "rcx", "rbx", "r8"
-    );
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_16(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[32], t2[17];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[15];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 16);
-    for (i=15; i>=0; i--) {
-        r1 = div_2048_word_16(t1[16 + i], t1[16 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_2048_mul_d_avx2_16(t2, d, r1);
-        else
-#endif
-            sp_2048_mul_d_16(t2, d, r1);
-        t1[16 + i] += sp_2048_sub_in_place_16(&t1[i], t2);
-        t1[16 + i] -= t2[16];
-        sp_2048_mask_16(t2, d, t1[16 + i]);
-        t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2);
-        sp_2048_mask_16(t2, d, t1[16 + i]);
-        t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_16(t1, d) >= 0;
-    sp_2048_cond_sub_16(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_16(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_16(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][32];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 32;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_16(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 16);
-        if (reduceA) {
-            err = sp_2048_mod_16(t[1] + 16, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_16(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16);
-            err = sp_2048_mod_16(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_16(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_16(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_16(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_16(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_16(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_16(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_16(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_16(t[20], t[10], m, mp);
-        sp_2048_mont_mul_16(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_16(t[22], t[11], m, mp);
-        sp_2048_mont_mul_16(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_16(t[24], t[12], m, mp);
-        sp_2048_mont_mul_16(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_16(t[26], t[13], m, mp);
-        sp_2048_mont_mul_16(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_16(t[28], t[14], m, mp);
-        sp_2048_mont_mul_16(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_16(t[30], t[15], m, mp);
-        sp_2048_mont_mul_16(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-            sp_2048_mont_sqr_16(r, r, m, mp);
-
-            sp_2048_mont_mul_16(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_2048_mont_sqr_16(r, r, m, mp);
-        sp_2048_mont_mul_16(r, r, t[y], m, mp);
-
-        XMEMSET(&r[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_mont_reduce_16(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_16(r, m) >= 0);
-        sp_2048_cond_sub_16(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_avx2_16(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "\nL_mont_loop_avx2_16:\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%r8\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "mulxq	0(%[m]), %%rax, %%r8\n\t"
-        "movq	8(%[a]), %%r12\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r12\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "mulxq	8(%[m]), %%rax, %%r8\n\t"
-        "movq	16(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "mulxq	16(%[m]), %%rax, %%r8\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 16(%[a])\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "mulxq	24(%[m]), %%rax, %%r8\n\t"
-        "movq	32(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "mulxq	32(%[m]), %%rax, %%r8\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 32(%[a])\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "mulxq	40(%[m]), %%rax, %%r8\n\t"
-        "movq	48(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "mulxq	48(%[m]), %%rax, %%r8\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 48(%[a])\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "mulxq	56(%[m]), %%rax, %%r8\n\t"
-        "movq	64(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "mulxq	64(%[m]), %%rax, %%r8\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 64(%[a])\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "mulxq	72(%[m]), %%rax, %%r8\n\t"
-        "movq	80(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "mulxq	80(%[m]), %%rax, %%r8\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 80(%[a])\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "mulxq	88(%[m]), %%rax, %%r8\n\t"
-        "movq	96(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "mulxq	96(%[m]), %%rax, %%r8\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 96(%[a])\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "mulxq	104(%[m]), %%rax, %%r8\n\t"
-        "movq	112(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "mulxq	112(%[m]), %%rax, %%r8\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 112(%[a])\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "mulxq	120(%[m]), %%rax, %%r8\n\t"
-        "movq	128(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "adcxq	%[ca], %%r10\n\t"
-        "movq	%%r9, %[ca]\n\t"
-        "adoxq	%%r9, %[ca]\n\t"
-        "adcxq	%%r9, %[ca]\n\t"
-        "movq	%%r10, 128(%[a])\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$1, %%rcx\n\t"
-        "cmpq	$16, %%rcx\n\t"
-        "jl	L_mont_loop_avx2_16\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_avx2_16(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_avx2_16(r, a, b);
-    sp_2048_mont_reduce_avx2_16(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_avx2_16(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_avx2_16(r, a);
-    sp_2048_mont_reduce_avx2_16(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_avx2_16(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][32];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 32;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_16(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 16);
-        if (reduceA) {
-            err = sp_2048_mod_16(t[1] + 16, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_16(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16);
-            err = sp_2048_mod_16(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_avx2_16(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_avx2_16(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_avx2_16(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_avx2_16(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_avx2_16(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_avx2_16(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_avx2_16(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_avx2_16(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_avx2_16(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_avx2_16(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[20], t[10], m, mp);
-        sp_2048_mont_mul_avx2_16(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[22], t[11], m, mp);
-        sp_2048_mont_mul_avx2_16(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[24], t[12], m, mp);
-        sp_2048_mont_mul_avx2_16(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[26], t[13], m, mp);
-        sp_2048_mont_mul_avx2_16(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[28], t[14], m, mp);
-        sp_2048_mont_mul_avx2_16(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_avx2_16(t[30], t[15], m, mp);
-        sp_2048_mont_mul_avx2_16(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 16);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-
-            sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_2048_mont_sqr_avx2_16(r, r, m, mp);
-        sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp);
-
-        XMEMSET(&r[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_mont_reduce_avx2_16(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_16(r, m) >= 0);
-        sp_2048_cond_sub_16(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 2048 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 32);
-
-    /* r = 2^n mod m */
-    sp_2048_sub_in_place_32(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit t[32];
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[b]), %%rax\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 0(%[t])\n\t"
-        "movq	%%rcx, 8(%[t])\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 16(%[t])\n\t"
-        "movq	%%rcx, 24(%[t])\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 32(%[t])\n\t"
-        "movq	%%rcx, 40(%[t])\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 48(%[t])\n\t"
-        "movq	%%rcx, 56(%[t])\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 64(%[t])\n\t"
-        "movq	%%rcx, 72(%[t])\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 80(%[t])\n\t"
-        "movq	%%rcx, 88(%[t])\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 96(%[t])\n\t"
-        "movq	%%rcx, 104(%[t])\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 112(%[t])\n\t"
-        "movq	%%rcx, 120(%[t])\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 128(%[t])\n\t"
-        "movq	%%rcx, 136(%[t])\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 144(%[t])\n\t"
-        "movq	%%rcx, 152(%[t])\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 160(%[t])\n\t"
-        "movq	%%rcx, 168(%[t])\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 176(%[t])\n\t"
-        "movq	%%rcx, 184(%[t])\n\t"
-        "movq	192(%[b]), %%rax\n\t"
-        "movq	200(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 192(%[t])\n\t"
-        "movq	%%rcx, 200(%[t])\n\t"
-        "movq	208(%[b]), %%rax\n\t"
-        "movq	216(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 208(%[t])\n\t"
-        "movq	%%rcx, 216(%[t])\n\t"
-        "movq	224(%[b]), %%rax\n\t"
-        "movq	232(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 224(%[t])\n\t"
-        "movq	%%rcx, 232(%[t])\n\t"
-        "movq	240(%[b]), %%rax\n\t"
-        "movq	248(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 240(%[t])\n\t"
-        "movq	%%rcx, 248(%[t])\n\t"
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[t]), %%rdx\n\t"
-        "subq	%%rdx,%%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "movq	32(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "movq	40(%[a]), %%rcx\n\t"
-        "movq	40(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "movq	48(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 40(%[r])\n\t"
-        "movq	56(%[a]), %%rcx\n\t"
-        "movq	56(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "movq	64(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "movq	72(%[a]), %%rcx\n\t"
-        "movq	72(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "movq	80(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 72(%[r])\n\t"
-        "movq	88(%[a]), %%rcx\n\t"
-        "movq	88(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "movq	96(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 88(%[r])\n\t"
-        "movq	104(%[a]), %%rcx\n\t"
-        "movq	104(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "movq	112(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "movq	120(%[a]), %%rcx\n\t"
-        "movq	120(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "movq	128(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 120(%[r])\n\t"
-        "movq	136(%[a]), %%rcx\n\t"
-        "movq	136(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "movq	144(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 136(%[r])\n\t"
-        "movq	152(%[a]), %%rcx\n\t"
-        "movq	152(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "movq	160(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "movq	168(%[a]), %%rcx\n\t"
-        "movq	168(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "movq	176(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 168(%[r])\n\t"
-        "movq	184(%[a]), %%rcx\n\t"
-        "movq	184(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	192(%[a]), %%rax\n\t"
-        "movq	192(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 184(%[r])\n\t"
-        "movq	200(%[a]), %%rcx\n\t"
-        "movq	200(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 192(%[r])\n\t"
-        "movq	208(%[a]), %%rax\n\t"
-        "movq	208(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "movq	216(%[a]), %%rcx\n\t"
-        "movq	216(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 208(%[r])\n\t"
-        "movq	224(%[a]), %%rax\n\t"
-        "movq	224(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 216(%[r])\n\t"
-        "movq	232(%[a]), %%rcx\n\t"
-        "movq	232(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 224(%[r])\n\t"
-        "movq	240(%[a]), %%rax\n\t"
-        "movq	240(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 232(%[r])\n\t"
-        "movq	248(%[a]), %%rcx\n\t"
-        "movq	248(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 240(%[r])\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "movq	8(%[a]), %%r13\n\t"
-        "\nL_mont_loop_32:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "imulq	%[mp], %%r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	0(%[m])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	8(%[m])\n\t"
-        "movq	%%r13, %%r12\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r12\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	16(%[m])\n\t"
-        "movq	16(%[a]), %%r13\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r13\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[m])\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	32(%[m])\n\t"
-        "movq	32(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 32(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	40(%[m])\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	48(%[m])\n\t"
-        "movq	48(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 48(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	56(%[m])\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	64(%[m])\n\t"
-        "movq	64(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 64(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[m])\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	80(%[m])\n\t"
-        "movq	80(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 80(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	88(%[m])\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	96(%[m])\n\t"
-        "movq	96(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 96(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	104(%[m])\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	112(%[m])\n\t"
-        "movq	112(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 112(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[m])\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	128(%[m])\n\t"
-        "movq	128(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 128(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	136(%[m])\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	144(%[m])\n\t"
-        "movq	144(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 144(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	152(%[m])\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	160(%[m])\n\t"
-        "movq	160(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 160(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[m])\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	176(%[m])\n\t"
-        "movq	176(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 176(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	184(%[m])\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	192(%[m])\n\t"
-        "movq	192(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 192(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	200(%[m])\n\t"
-        "movq	200(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 200(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	208(%[m])\n\t"
-        "movq	208(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 208(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	216(%[m])\n\t"
-        "movq	216(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 216(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	224(%[m])\n\t"
-        "movq	224(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 224(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	232(%[m])\n\t"
-        "movq	232(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 232(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	240(%[m])\n\t"
-        "movq	240(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 240(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "mulq	248(%[m])\n\t"
-        "movq	248(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%[ca], %%rdx\n\t"
-        "movq	$0, %[ca]\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "addq	%%r9, %%r11\n\t"
-        "movq	%%r11, 248(%[a])\n\t"
-        "adcq	%%rdx, 256(%[a])\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$8, %%rcx\n\t"
-        "cmpq	$256, %%rcx\n\t"
-        "jl	L_mont_loop_32\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        "movq	%%r13, 8(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13"
-    );
-
-    sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_32(r, a, b);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_32(r, a);
-    sp_2048_mont_reduce_32(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	(%[a])\n\t"
-        "movq	%%rax, %%rbx\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[2] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[3] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 24(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[5] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 40(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[6] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 48(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[7] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[8] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[9] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 72(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 80(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[11] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 88(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[12] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 96(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[13] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[14] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[15] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 120(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 128(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[17] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 136(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[18] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 144(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[19] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[20] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[21] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 168(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 176(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[23] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 184(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[24] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	192(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 192(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[25] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	200(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[26] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	208(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[27] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	216(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 216(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[28] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	224(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 224(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[29] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	232(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 232(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[30] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	240(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 240(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[31] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "mulq	248(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        "movq	%%r8, 256(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rdx\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "mulxq	(%[a]), %%r8, %%r9\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "mulxq	8(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[2] * B\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[3] * B\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 24(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[5] * B\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 40(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[6] * B\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 48(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[7] * B\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 56(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[8] * B\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[9] * B\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 72(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 80(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[11] * B\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 88(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[12] * B\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 96(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[13] * B\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 104(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[14] * B\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[15] * B\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 120(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 128(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[17] * B\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 136(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[18] * B\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 144(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[19] * B\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 152(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[20] * B\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[21] * B\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 168(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 176(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[23] * B\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 184(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[24] * B\n\t"
-        "mulxq	192(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 192(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[25] * B\n\t"
-        "mulxq	200(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 200(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[26] * B\n\t"
-        "mulxq	208(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[27] * B\n\t"
-        "mulxq	216(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 216(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[28] * B\n\t"
-        "mulxq	224(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 224(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[29] * B\n\t"
-        "mulxq	232(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 232(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[30] * B\n\t"
-        "mulxq	240(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 240(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[31] * B\n\t"
-        "mulxq	248(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "adcxq	%%r10, %%r8\n\t"
-        "movq	%%r9, 248(%[r])\n\t"
-        "movq	%%r8, 256(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "movq	%[d0], %%rax\n\t"
-        "movq	%[d1], %%rdx\n\t"
-        "divq	%[div]\n\t"
-        "movq	%%rax, %[r]\n\t"
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "rax", "rdx"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<32; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 32; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_2048_cmp_32(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-    __asm__ __volatile__ (
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	$-1, %%rdx\n\t"
-        "movq	248(%[a]), %%rbx\n\t"
-        "movq	248(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	240(%[a]), %%rbx\n\t"
-        "movq	240(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	232(%[a]), %%rbx\n\t"
-        "movq	232(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	224(%[a]), %%rbx\n\t"
-        "movq	224(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	216(%[a]), %%rbx\n\t"
-        "movq	216(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	208(%[a]), %%rbx\n\t"
-        "movq	208(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	200(%[a]), %%rbx\n\t"
-        "movq	200(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	192(%[a]), %%rbx\n\t"
-        "movq	192(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	184(%[a]), %%rbx\n\t"
-        "movq	184(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	176(%[a]), %%rbx\n\t"
-        "movq	176(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	168(%[a]), %%rbx\n\t"
-        "movq	168(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	160(%[a]), %%rbx\n\t"
-        "movq	160(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	152(%[a]), %%rbx\n\t"
-        "movq	152(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	144(%[a]), %%rbx\n\t"
-        "movq	144(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	136(%[a]), %%rbx\n\t"
-        "movq	136(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	128(%[a]), %%rbx\n\t"
-        "movq	128(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	120(%[a]), %%rbx\n\t"
-        "movq	120(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	112(%[a]), %%rbx\n\t"
-        "movq	112(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	104(%[a]), %%rbx\n\t"
-        "movq	104(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	96(%[a]), %%rbx\n\t"
-        "movq	96(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	88(%[a]), %%rbx\n\t"
-        "movq	88(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	80(%[a]), %%rbx\n\t"
-        "movq	80(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	72(%[a]), %%rbx\n\t"
-        "movq	72(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	64(%[a]), %%rbx\n\t"
-        "movq	64(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	56(%[a]), %%rbx\n\t"
-        "movq	56(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	48(%[a]), %%rbx\n\t"
-        "movq	48(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	40(%[a]), %%rbx\n\t"
-        "movq	40(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	32(%[a]), %%rbx\n\t"
-        "movq	32(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	24(%[a]), %%rbx\n\t"
-        "movq	24(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	16(%[a]), %%rbx\n\t"
-        "movq	16(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	8(%[a]), %%rbx\n\t"
-        "movq	8(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	0(%[a]), %%rbx\n\t"
-        "movq	0(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "xorq	%%rdx, %[r]\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "rax", "rdx", "rcx", "rbx", "r8"
-    );
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[64], t2[33];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[31];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
-    for (i=31; i>=0; i--) {
-        r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_2048_mul_d_avx2_32(t2, d, r1);
-        else
-#endif
-            sp_2048_mul_d_32(t2, d, r1);
-        t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
-        t1[32 + i] -= t2[32];
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-        sp_2048_mask_32(t2, d, t1[32 + i]);
-        t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_2048_cmp_32(t1, d) >= 0;
-    sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_32(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_div_32_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[64], t2[33];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[31];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 32);
-    for (i=31; i>=0; i--) {
-        r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_2048_mul_d_avx2_32(t2, d, r1);
-        else
-#endif
-            sp_2048_mul_d_32(t2, d, r1);
-        t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2);
-        t1[32 + i] -= t2[32];
-        if (t1[32 + i] != 0) {
-            t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d);
-            if (t1[32 + i] != 0)
-                t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_2048_cmp_32(t1, d) >= 0;
-    sp_2048_cond_sub_32(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_2048_div_32_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][64];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_32(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_32(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_32(t[20], t[10], m, mp);
-        sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_32(t[22], t[11], m, mp);
-        sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_32(t[24], t[12], m, mp);
-        sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_32(t[26], t[13], m, mp);
-        sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_32(t[28], t[14], m, mp);
-        sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_32(t[30], t[15], m, mp);
-        sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-            sp_2048_mont_sqr_32(r, r, m, mp);
-
-            sp_2048_mont_mul_32(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_2048_mont_sqr_32(r, r, m, mp);
-        sp_2048_mont_mul_32(r, r, t[y], m, mp);
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef HAVE_INTEL_AVX2
-/* Reduce the number back to 2048 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_2048_mont_reduce_avx2_32(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "\nL_mont_loop_avx2_32:\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%r8\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "mulxq	0(%[m]), %%rax, %%r8\n\t"
-        "movq	8(%[a]), %%r12\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r12\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "mulxq	8(%[m]), %%rax, %%r8\n\t"
-        "movq	16(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "mulxq	16(%[m]), %%rax, %%r8\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 16(%[a])\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "mulxq	24(%[m]), %%rax, %%r8\n\t"
-        "movq	32(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "mulxq	32(%[m]), %%rax, %%r8\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 32(%[a])\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "mulxq	40(%[m]), %%rax, %%r8\n\t"
-        "movq	48(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "mulxq	48(%[m]), %%rax, %%r8\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 48(%[a])\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "mulxq	56(%[m]), %%rax, %%r8\n\t"
-        "movq	64(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "mulxq	64(%[m]), %%rax, %%r8\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 64(%[a])\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "mulxq	72(%[m]), %%rax, %%r8\n\t"
-        "movq	80(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "mulxq	80(%[m]), %%rax, %%r8\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 80(%[a])\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "mulxq	88(%[m]), %%rax, %%r8\n\t"
-        "movq	96(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "mulxq	96(%[m]), %%rax, %%r8\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 96(%[a])\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "mulxq	104(%[m]), %%rax, %%r8\n\t"
-        "movq	112(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "mulxq	112(%[m]), %%rax, %%r8\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 112(%[a])\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "mulxq	120(%[m]), %%rax, %%r8\n\t"
-        "movq	128(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "mulxq	128(%[m]), %%rax, %%r8\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 128(%[a])\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "mulxq	136(%[m]), %%rax, %%r8\n\t"
-        "movq	144(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "mulxq	144(%[m]), %%rax, %%r8\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 144(%[a])\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "mulxq	152(%[m]), %%rax, %%r8\n\t"
-        "movq	160(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "mulxq	160(%[m]), %%rax, %%r8\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 160(%[a])\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "mulxq	168(%[m]), %%rax, %%r8\n\t"
-        "movq	176(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "mulxq	176(%[m]), %%rax, %%r8\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 176(%[a])\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "mulxq	184(%[m]), %%rax, %%r8\n\t"
-        "movq	192(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "mulxq	192(%[m]), %%rax, %%r8\n\t"
-        "movq	200(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 192(%[a])\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "mulxq	200(%[m]), %%rax, %%r8\n\t"
-        "movq	208(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 200(%[a])\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "mulxq	208(%[m]), %%rax, %%r8\n\t"
-        "movq	216(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 208(%[a])\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "mulxq	216(%[m]), %%rax, %%r8\n\t"
-        "movq	224(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 216(%[a])\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "mulxq	224(%[m]), %%rax, %%r8\n\t"
-        "movq	232(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 224(%[a])\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "mulxq	232(%[m]), %%rax, %%r8\n\t"
-        "movq	240(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 232(%[a])\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "mulxq	240(%[m]), %%rax, %%r8\n\t"
-        "movq	248(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 240(%[a])\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "mulxq	248(%[m]), %%rax, %%r8\n\t"
-        "movq	256(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 248(%[a])\n\t"
-        "adcxq	%[ca], %%r10\n\t"
-        "movq	%%r9, %[ca]\n\t"
-        "adoxq	%%r9, %[ca]\n\t"
-        "adcxq	%%r9, %[ca]\n\t"
-        "movq	%%r10, 256(%[a])\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$1, %%rcx\n\t"
-        "cmpq	$32, %%rcx\n\t"
-        "jl	L_mont_loop_avx2_32\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_mul_avx2_32(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_2048_mul_avx2_32(r, a, b);
-    sp_2048_mont_reduce_avx2_32(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_2048_mont_sqr_avx2_32(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_2048_sqr_avx2_32(r, a);
-    sp_2048_mont_reduce_avx2_32(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef HAVE_INTEL_AVX2
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_2048_mod_exp_avx2_32(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][64];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 64;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_setup(m, &mp);
-        sp_2048_mont_norm_32(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 32);
-        if (reduceA) {
-            err = sp_2048_mod_32(t[1] + 32, a, m);
-            if (err == MP_OKAY)
-                err = sp_2048_mod_32(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_mont_sqr_avx2_32(t[ 2], t[ 1], m, mp);
-        sp_2048_mont_mul_avx2_32(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[ 4], t[ 2], m, mp);
-        sp_2048_mont_mul_avx2_32(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[ 6], t[ 3], m, mp);
-        sp_2048_mont_mul_avx2_32(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[ 8], t[ 4], m, mp);
-        sp_2048_mont_mul_avx2_32(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[10], t[ 5], m, mp);
-        sp_2048_mont_mul_avx2_32(t[11], t[ 6], t[ 5], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[12], t[ 6], m, mp);
-        sp_2048_mont_mul_avx2_32(t[13], t[ 7], t[ 6], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[14], t[ 7], m, mp);
-        sp_2048_mont_mul_avx2_32(t[15], t[ 8], t[ 7], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[16], t[ 8], m, mp);
-        sp_2048_mont_mul_avx2_32(t[17], t[ 9], t[ 8], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[18], t[ 9], m, mp);
-        sp_2048_mont_mul_avx2_32(t[19], t[10], t[ 9], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[20], t[10], m, mp);
-        sp_2048_mont_mul_avx2_32(t[21], t[11], t[10], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[22], t[11], m, mp);
-        sp_2048_mont_mul_avx2_32(t[23], t[12], t[11], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[24], t[12], m, mp);
-        sp_2048_mont_mul_avx2_32(t[25], t[13], t[12], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[26], t[13], m, mp);
-        sp_2048_mont_mul_avx2_32(t[27], t[14], t[13], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[28], t[14], m, mp);
-        sp_2048_mont_mul_avx2_32(t[29], t[15], t[14], m, mp);
-        sp_2048_mont_sqr_avx2_32(t[30], t[15], m, mp);
-        sp_2048_mont_mul_avx2_32(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 32);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-
-            sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-        sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp);
-
-        XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-        sp_2048_mont_reduce_avx2_32(r, m, mp);
-
-        mask = 0 - (sp_2048_cmp_32(r, m) >= 0);
-        sp_2048_cond_sub_32(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[64], md[32], rd[64];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 256 ||
-                                                     mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 32 * 2;
-        m = r + 32 * 2;
-        ah = a + 32;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 32;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(ah, 32, in, inLen);
-#if DIGIT_BIT >= 64
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(m, 32, mm);
-
-        if (e[0] == 0x3) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-                if (err == MP_OKAY) {
-                    sp_2048_sqr_avx2_32(r, ah);
-                    err = sp_2048_mod_32_cond(r, r, m);
-                }
-                if (err == MP_OKAY) {
-                    sp_2048_mul_avx2_32(r, ah, r);
-                    err = sp_2048_mod_32_cond(r, r, m);
-                }
-            }
-            else
-#endif
-            {
-                if (err == MP_OKAY) {
-                    sp_2048_sqr_32(r, ah);
-                    err = sp_2048_mod_32_cond(r, r, m);
-                }
-                if (err == MP_OKAY) {
-                    sp_2048_mul_32(r, ah, r);
-                    err = sp_2048_mod_32_cond(r, r, m);
-                }
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_2048_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 32);
-            err = sp_2048_mod_32_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=63; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 32);
-#ifdef HAVE_INTEL_AVX2
-                if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-                    for (i--; i>=0; i--) {
-                        sp_2048_mont_sqr_avx2_32(r, r, m, mp);
-                        if (((e[0] >> i) & 1) == 1)
-                            sp_2048_mont_mul_avx2_32(r, r, a, m, mp);
-                    }
-                    XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-                    sp_2048_mont_reduce_avx2_32(r, m, mp);
-                }
-                else
-#endif
-                {
-                    for (i--; i>=0; i--) {
-                        sp_2048_mont_sqr_32(r, r, m, mp);
-                        if (((e[0] >> i) & 1) == 1)
-                            sp_2048_mont_mul_32(r, r, a, m, mp);
-                    }
-                    XMEMSET(&r[32], 0, sizeof(sp_digit) * 32);
-                    sp_2048_mont_reduce_32(r, m, mp);
-                }
-
-                for (i = 31; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_2048_sub_in_place_32(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 256 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[32 * 2];
-    sp_digit pd[16], qd[16], dpd[16];
-    sp_digit tmpad[32], tmpbd[32];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 256)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 32 * 2;
-        q = p + 16;
-        qi = dq = dp = q + 16;
-        tmpa = qi + 16;
-        tmpb = tmpa + 32;
-
-        tmp = t;
-        r = tmp + 32;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 32;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_2048_from_bin(a, 32, in, inLen);
-        sp_2048_from_mp(p, 16, pm);
-        sp_2048_from_mp(q, 16, qm);
-        sp_2048_from_mp(dp, 16, dpm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_2048_mod_exp_avx2_16(tmpa, a, dp, 1024, p, 1);
-        else
-#endif
-            err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(dq, 16, dqm);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_2048_mod_exp_avx2_16(tmpb, a, dq, 1024, q, 1);
-       else
-#endif
-            err = sp_2048_mod_exp_16(tmpb, a, dq, 1024, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_2048_sub_in_place_16(tmpa, tmpb);
-        sp_2048_mask_16(tmp, p, c);
-        sp_2048_add_16(tmpa, tmpa, tmp);
-
-        sp_2048_from_mp(qi, 16, qim);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_2048_mul_avx2_16(tmpa, tmpa, qi);
-        else
-#endif
-            sp_2048_mul_16(tmpa, tmpa, qi);
-        err = sp_2048_mod_16(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_2048_mul_avx2_16(tmpa, q, tmpa);
-        else
-#endif
-            sp_2048_mul_16(tmpa, q, tmpa);
-        XMEMSET(&tmpb[16], 0, sizeof(sp_digit) * 16);
-        sp_2048_add_32(r, tmpb, tmpa);
-
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_2048_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 32);
-        r->used = 32;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 32; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 32; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[64], e[32], m[32];
-    sp_digit* r = b;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 2048 || expBits > 2048 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 32, base);
-        sp_2048_from_mp(e, 32, exp);
-        sp_2048_from_mp(m, 32, mod);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_2048_mod_exp_avx2_32(r, b, e, expBits, m, 0);
-        else
-#endif
-            err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_2048_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 256 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[64], e[32], m[32];
-    sp_digit* r = b;
-    word32 i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (mp_count_bits(base) > 2048 || expLen > 256 ||
-                                                   mp_count_bits(mod) != 2048) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_from_mp(b, 32, base);
-        sp_2048_from_bin(e, 32, exp, expLen);
-        sp_2048_from_mp(m, 32, mod);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_2048_mod_exp_avx2_32(r, b, e, expLen * 8, m, 0);
-        else
-#endif
-            err = sp_2048_mod_exp_32(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_2048_to_bin(r, out);
-        *outLen = 256;
-        for (i=0; i<256 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_2048 */
-
-#ifndef WOLFSSL_SP_NO_3072
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 384
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_3072_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 3072 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<48 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit tmp[24];
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 8(%[tmp])\n\t"
-        "#  A[0] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 16(%[tmp])\n\t"
-        "#  A[0] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 24(%[tmp])\n\t"
-        "#  A[0] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 32(%[tmp])\n\t"
-        "#  A[0] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 40(%[tmp])\n\t"
-        "#  A[0] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 48(%[tmp])\n\t"
-        "#  A[0] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 56(%[tmp])\n\t"
-        "#  A[0] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 64(%[tmp])\n\t"
-        "#  A[0] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 72(%[tmp])\n\t"
-        "#  A[0] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 80(%[tmp])\n\t"
-        "#  A[0] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 88(%[tmp])\n\t"
-        "#  A[0] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 96(%[tmp])\n\t"
-        "#  A[0] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 104(%[tmp])\n\t"
-        "#  A[0] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 112(%[tmp])\n\t"
-        "#  A[0] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 120(%[tmp])\n\t"
-        "#  A[0] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 128(%[tmp])\n\t"
-        "#  A[0] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 136(%[tmp])\n\t"
-        "#  A[0] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 144(%[tmp])\n\t"
-        "#  A[0] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 152(%[tmp])\n\t"
-        "#  A[0] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 160(%[tmp])\n\t"
-        "#  A[0] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 168(%[tmp])\n\t"
-        "#  A[0] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 176(%[tmp])\n\t"
-        "#  A[0] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 184(%[tmp])\n\t"
-        "#  A[1] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[4] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 192(%[r])\n\t"
-        "#  A[2] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[4] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[5] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "#  A[3] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[4] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[5] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[6] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "#  A[4] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[5] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[6] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[7] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[4]\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 216(%[r])\n\t"
-        "#  A[5] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[6] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[7] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[8] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[5]\n\t"
-        "movq	40(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 224(%[r])\n\t"
-        "#  A[6] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[7] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[8] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[9] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[6]\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 232(%[r])\n\t"
-        "#  A[7] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[8] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[9] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[10] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[7]\n\t"
-        "movq	56(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 240(%[r])\n\t"
-        "#  A[8] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[9] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[10] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[11] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[8]\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        "#  A[9] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[10] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[11] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[12] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[9]\n\t"
-        "movq	72(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 256(%[r])\n\t"
-        "#  A[10] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[11] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[12] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[13] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[10]\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 264(%[r])\n\t"
-        "#  A[11] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[12] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[13] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[14] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[11]\n\t"
-        "movq	88(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 272(%[r])\n\t"
-        "#  A[12] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[13] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[14] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[15] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[12]\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 280(%[r])\n\t"
-        "#  A[13] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[14] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[15] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[16] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[13]\n\t"
-        "movq	104(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 288(%[r])\n\t"
-        "#  A[14] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[15] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[16] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[17] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[14]\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 296(%[r])\n\t"
-        "#  A[15] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[16] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[17] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[18] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[15]\n\t"
-        "movq	120(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 304(%[r])\n\t"
-        "#  A[16] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[17] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[18] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[19] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[16]\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 312(%[r])\n\t"
-        "#  A[17] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[18] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[19] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[20] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[17]\n\t"
-        "movq	136(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 320(%[r])\n\t"
-        "#  A[18] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[19] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[20] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[18]\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 328(%[r])\n\t"
-        "#  A[19] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[20] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[21] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[19]\n\t"
-        "movq	152(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 336(%[r])\n\t"
-        "#  A[20] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[21] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[22] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[23] * B[20]\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 344(%[r])\n\t"
-        "#  A[21] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[22] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[23] * B[21]\n\t"
-        "movq	168(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 352(%[r])\n\t"
-        "#  A[22] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[23] * B[22]\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 360(%[r])\n\t"
-        "#  A[23] * B[23]\n\t"
-        "movq	184(%[b]), %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "movq	%%rcx, 368(%[r])\n\t"
-        "movq	%%r8, 376(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[24];
-
-    __asm__ __volatile__ (
-        "#  A[0] * A[0]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%r8\n\t"
-        "#  A[0] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 8(%[tmp])\n\t"
-        "#  A[0] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 16(%[tmp])\n\t"
-        "#  A[0] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[1] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 24(%[tmp])\n\t"
-        "#  A[0] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 32(%[tmp])\n\t"
-        "#  A[0] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 40(%[tmp])\n\t"
-        "#  A[0] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 48(%[tmp])\n\t"
-        "#  A[0] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 56(%[tmp])\n\t"
-        "#  A[0] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[4]\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 64(%[tmp])\n\t"
-        "#  A[0] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 72(%[tmp])\n\t"
-        "#  A[0] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[5]\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 80(%[tmp])\n\t"
-        "#  A[0] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 88(%[tmp])\n\t"
-        "#  A[0] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[6]\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 96(%[tmp])\n\t"
-        "#  A[0] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 104(%[tmp])\n\t"
-        "#  A[0] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[7]\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 112(%[tmp])\n\t"
-        "#  A[0] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 120(%[tmp])\n\t"
-        "#  A[0] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[8]\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 128(%[tmp])\n\t"
-        "#  A[0] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 136(%[tmp])\n\t"
-        "#  A[0] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[9]\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 144(%[tmp])\n\t"
-        "#  A[0] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 152(%[tmp])\n\t"
-        "#  A[0] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[10]\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 160(%[tmp])\n\t"
-        "#  A[0] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 168(%[tmp])\n\t"
-        "#  A[0] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[11]\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 176(%[tmp])\n\t"
-        "#  A[0] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[1] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 184(%[tmp])\n\t"
-        "#  A[1] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[2] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[3] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[12]\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 192(%[r])\n\t"
-        "#  A[2] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[3] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[4] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 200(%[r])\n\t"
-        "#  A[3] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[4] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[5] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[13]\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 208(%[r])\n\t"
-        "#  A[4] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	32(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[5] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[6] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 216(%[r])\n\t"
-        "#  A[5] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	40(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[6] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[7] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[14]\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 224(%[r])\n\t"
-        "#  A[6] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	48(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[7] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[8] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 232(%[r])\n\t"
-        "#  A[7] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	56(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[8] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[9] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[15]\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 240(%[r])\n\t"
-        "#  A[8] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	64(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[9] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[10] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 248(%[r])\n\t"
-        "#  A[9] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	72(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[10] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[11] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[16]\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 256(%[r])\n\t"
-        "#  A[10] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	80(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[11] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[12] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 264(%[r])\n\t"
-        "#  A[11] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	88(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[12] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[13] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[17] * A[17]\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 272(%[r])\n\t"
-        "#  A[12] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	96(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[13] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[14] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[17] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 280(%[r])\n\t"
-        "#  A[13] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	104(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[14] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[15] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[17] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[18] * A[18]\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 288(%[r])\n\t"
-        "#  A[14] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	112(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[15] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[16] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[17] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[18] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 296(%[r])\n\t"
-        "#  A[15] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	120(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[16] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[17] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[18] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[19] * A[19]\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 304(%[r])\n\t"
-        "#  A[16] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	128(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[17] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[18] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[19] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%rcx\n\t"
-        "adcq	%%r11, %%r8\n\t"
-        "adcq	%%r12, %%r9\n\t"
-        "movq	%%rcx, 312(%[r])\n\t"
-        "#  A[17] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	136(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[18] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[19] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[20] * A[20]\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r8\n\t"
-        "adcq	%%r11, %%r9\n\t"
-        "adcq	%%r12, %%rcx\n\t"
-        "movq	%%r8, 320(%[r])\n\t"
-        "#  A[18] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	144(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r10\n\t"
-        "movq	%%rdx, %%r11\n\t"
-        "#  A[19] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[20] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "addq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "addq	%%r10, %%r9\n\t"
-        "adcq	%%r11, %%rcx\n\t"
-        "adcq	%%r12, %%r8\n\t"
-        "movq	%%r9, 328(%[r])\n\t"
-        "#  A[19] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	152(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[20] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[21] * A[21]\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 336(%[r])\n\t"
-        "#  A[20] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	160(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[21] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 344(%[r])\n\t"
-        "#  A[21] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	168(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[22] * A[22]\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 352(%[r])\n\t"
-        "#  A[22] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	176(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 360(%[r])\n\t"
-        "#  A[23] * A[23]\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "movq	%%r8, 368(%[r])\n\t"
-        "movq	%%r9, 376(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply a and b into r. (r = a * b)
- *
- * r   Result of multiplication.
- * a   First number to multiply.
- * b   Second number to multiply.
- */
-SP_NOINLINE static void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit tmp[2*24];
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "# A[0] * B[0]\n\t"
-        "mulx	0(%[b]), %%r10, %%r11\n\t"
-        "# A[0] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "# A[0] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "movq	%%r10, 0(%[t])\n\t"
-        "movq	%%r11, 8(%[t])\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "# A[0] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "# A[0] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "# A[0] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "# A[0] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "# A[0] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "# A[0] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "# A[0] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "# A[0] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "# A[0] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "# A[0] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "# A[0] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "# A[0] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "# A[0] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "# A[0] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "# A[0] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adcxq	%%r15, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	8(%[t]), %%r11\n\t"
-        "movq	16(%[t]), %%r12\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "# A[1] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[1] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 8(%[t])\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "# A[1] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[1] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[1] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[1] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[1] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[1] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[1] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[1] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[1] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[1] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[1] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[1] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[1] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	16(%[t]), %%r12\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "# A[2] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[2] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 16(%[t])\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "# A[2] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[2] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[2] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[2] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[2] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[2] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[2] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[2] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[2] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[2] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[2] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[2] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[2] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	24(%[t]), %%r13\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "# A[3] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[3] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 24(%[t])\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "# A[3] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[3] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[3] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[3] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[3] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[3] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[3] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[3] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[3] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[3] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[3] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[3] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[3] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	32(%[t]), %%r14\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "# A[4] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[4] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 32(%[t])\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "# A[4] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[4] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[4] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[4] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[4] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[4] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[4] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[4] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[4] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[4] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[4] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[4] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[4] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	40(%[t]), %%rax\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "# A[5] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[5] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 40(%[t])\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[5] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[5] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[5] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[5] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[5] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[5] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[5] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[5] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[5] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[5] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[5] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[5] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[5] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	48(%[t]), %%r10\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "# A[6] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[6] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 48(%[t])\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[6] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[6] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[6] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[6] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[6] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[6] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[6] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[6] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[6] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[6] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[6] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[6] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[6] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	56(%[t]), %%r11\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "# A[7] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[7] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 56(%[t])\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[7] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[7] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[7] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[7] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[7] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[7] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[7] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[7] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[7] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[7] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[7] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[7] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[7] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	64(%[t]), %%r12\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "# A[8] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[8] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 64(%[t])\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[8] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[8] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[8] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[8] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[8] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[8] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[8] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[8] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[8] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "# A[8] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[8] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[8] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[8] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	72(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	72(%[t]), %%r13\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "# A[9] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[9] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 72(%[t])\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[9] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[9] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[9] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[9] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[9] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[9] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[9] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[9] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[9] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "# A[9] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[9] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[9] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[9] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	80(%[t]), %%r14\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "# A[10] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[10] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 80(%[t])\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[10] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[10] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[10] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[10] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[10] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[10] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[10] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[10] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[10] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "# A[10] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[10] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[10] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[10] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	88(%[t]), %%rax\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "# A[11] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[11] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 88(%[t])\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[11] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[11] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[11] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[11] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[11] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[11] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "# A[11] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[11] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[11] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "# A[11] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[11] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[11] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[11] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	96(%[t]), %%r10\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "# A[12] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[12] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 96(%[t])\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[12] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[12] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[12] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[12] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[12] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[12] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "# A[12] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[12] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[12] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "# A[12] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[12] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[12] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[12] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	104(%[t]), %%r11\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "# A[13] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[13] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 104(%[t])\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[13] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[13] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[13] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[13] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[13] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[13] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "# A[13] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[13] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[13] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "# A[13] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[13] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[13] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[13] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	112(%[t]), %%r12\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "# A[14] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[14] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 112(%[t])\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[14] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[14] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[14] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[14] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[14] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[14] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "# A[14] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[14] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[14] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "# A[14] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[14] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[14] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[14] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	120(%[t]), %%r13\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "# A[15] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[15] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 120(%[t])\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[15] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[15] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[15] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[15] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "# A[15] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[15] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "# A[15] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[15] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[15] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "# A[15] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[15] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[15] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[15] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	128(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	128(%[t]), %%r14\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "# A[16] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[16] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[16] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[16] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 128(%[t])\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[16] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[16] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[16] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[16] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[16] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[16] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[16] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[16] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "# A[16] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[16] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[16] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[16] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "# A[16] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[16] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[16] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[16] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "# A[16] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[16] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[16] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[16] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	136(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	136(%[t]), %%rax\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "# A[17] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[17] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[17] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[17] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 136(%[t])\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[17] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[17] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[17] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[17] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[17] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[17] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[17] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[17] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "# A[17] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[17] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[17] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[17] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "# A[17] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[17] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[17] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[17] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "# A[17] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[17] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[17] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[17] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	144(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	144(%[t]), %%r10\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "# A[18] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[18] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[18] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[18] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 144(%[t])\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[18] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[18] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[18] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[18] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[18] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[18] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[18] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[18] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "# A[18] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[18] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[18] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[18] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "# A[18] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[18] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[18] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[18] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "# A[18] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[18] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[18] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[18] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r10\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "adcxq	%%rcx, %%r10\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	152(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	152(%[t]), %%r11\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "# A[19] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[19] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[19] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[19] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 152(%[t])\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[19] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[19] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[19] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[19] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "# A[19] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[19] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[19] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[19] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "# A[19] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[19] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[19] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[19] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "# A[19] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[19] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[19] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[19] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "movq	336(%[t]), %%r10\n\t"
-        "# A[19] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[19] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[19] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[19] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r11\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	%%r11, 344(%[t])\n\t"
-        "movq	160(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	160(%[t]), %%r12\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "# A[20] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[20] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[20] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[20] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 160(%[t])\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "# A[20] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[20] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[20] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[20] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "# A[20] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[20] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[20] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[20] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "# A[20] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[20] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[20] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[20] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "# A[20] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[20] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[20] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[20] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "movq	336(%[t]), %%r10\n\t"
-        "movq	344(%[t]), %%r11\n\t"
-        "# A[20] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[20] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[20] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[20] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r12\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	%%r11, 344(%[t])\n\t"
-        "movq	%%r12, 352(%[t])\n\t"
-        "movq	168(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	168(%[t]), %%r13\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "# A[21] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[21] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[21] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[21] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 168(%[t])\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "# A[21] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[21] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[21] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[21] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "# A[21] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[21] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[21] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[21] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "# A[21] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[21] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[21] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[21] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "# A[21] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[21] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[21] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[21] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	336(%[t]), %%r10\n\t"
-        "movq	344(%[t]), %%r11\n\t"
-        "movq	352(%[t]), %%r12\n\t"
-        "# A[21] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[21] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[21] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[21] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r13\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%rcx, %%r13\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	%%r11, 344(%[t])\n\t"
-        "movq	%%r12, 352(%[t])\n\t"
-        "movq	%%r13, 360(%[t])\n\t"
-        "movq	176(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	176(%[t]), %%r14\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "# A[22] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[22] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[22] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[22] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 176(%[t])\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "# A[22] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[22] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[22] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[22] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "# A[22] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[22] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[22] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[22] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "# A[22] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[22] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[22] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[22] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "movq	336(%[t]), %%r10\n\t"
-        "# A[22] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[22] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[22] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[22] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	344(%[t]), %%r11\n\t"
-        "movq	352(%[t]), %%r12\n\t"
-        "movq	360(%[t]), %%r13\n\t"
-        "# A[22] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[22] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[22] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[22] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%r14\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, %%rcx\n\t"
-        "adoxq	%%r15, %%rcx\n\t"
-        "adcxq	%%r15, %%rcx\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	%%r11, 344(%[t])\n\t"
-        "movq	%%r12, 352(%[t])\n\t"
-        "movq	%%r13, 360(%[t])\n\t"
-        "movq	%%r14, 368(%[t])\n\t"
-        "movq	184(%[a]), %%rdx\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "movq	184(%[t]), %%rax\n\t"
-        "movq	192(%[t]), %%r10\n\t"
-        "movq	200(%[t]), %%r11\n\t"
-        "movq	208(%[t]), %%r12\n\t"
-        "movq	216(%[t]), %%r13\n\t"
-        "# A[23] * B[0]\n\t"
-        "mulx	0(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[23] * B[1]\n\t"
-        "mulx	8(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[23] * B[2]\n\t"
-        "mulx	16(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[23] * B[3]\n\t"
-        "mulx	24(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 184(%[t])\n\t"
-        "movq	%%r10, 192(%[t])\n\t"
-        "movq	%%r11, 200(%[t])\n\t"
-        "movq	%%r12, 208(%[t])\n\t"
-        "movq	224(%[t]), %%r14\n\t"
-        "movq	232(%[t]), %%rax\n\t"
-        "movq	240(%[t]), %%r10\n\t"
-        "movq	248(%[t]), %%r11\n\t"
-        "# A[23] * B[4]\n\t"
-        "mulx	32(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[23] * B[5]\n\t"
-        "mulx	40(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[23] * B[6]\n\t"
-        "mulx	48(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[23] * B[7]\n\t"
-        "mulx	56(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 216(%[t])\n\t"
-        "movq	%%r14, 224(%[t])\n\t"
-        "movq	%%rax, 232(%[t])\n\t"
-        "movq	%%r10, 240(%[t])\n\t"
-        "movq	256(%[t]), %%r12\n\t"
-        "movq	264(%[t]), %%r13\n\t"
-        "movq	272(%[t]), %%r14\n\t"
-        "movq	280(%[t]), %%rax\n\t"
-        "# A[23] * B[8]\n\t"
-        "mulx	64(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[23] * B[9]\n\t"
-        "mulx	72(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[23] * B[10]\n\t"
-        "mulx	80(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[23] * B[11]\n\t"
-        "mulx	88(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "movq	%%r11, 248(%[t])\n\t"
-        "movq	%%r12, 256(%[t])\n\t"
-        "movq	%%r13, 264(%[t])\n\t"
-        "movq	%%r14, 272(%[t])\n\t"
-        "movq	288(%[t]), %%r10\n\t"
-        "movq	296(%[t]), %%r11\n\t"
-        "movq	304(%[t]), %%r12\n\t"
-        "movq	312(%[t]), %%r13\n\t"
-        "# A[23] * B[12]\n\t"
-        "mulx	96(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[23] * B[13]\n\t"
-        "mulx	104(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "# A[23] * B[14]\n\t"
-        "mulx	112(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[23] * B[15]\n\t"
-        "mulx	120(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "movq	%%rax, 280(%[t])\n\t"
-        "movq	%%r10, 288(%[t])\n\t"
-        "movq	%%r11, 296(%[t])\n\t"
-        "movq	%%r12, 304(%[t])\n\t"
-        "movq	320(%[t]), %%r14\n\t"
-        "movq	328(%[t]), %%rax\n\t"
-        "movq	336(%[t]), %%r10\n\t"
-        "movq	344(%[t]), %%r11\n\t"
-        "# A[23] * B[16]\n\t"
-        "mulx	128(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[23] * B[17]\n\t"
-        "mulx	136(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "# A[23] * B[18]\n\t"
-        "mulx	144(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%r9, %%r10\n\t"
-        "# A[23] * B[19]\n\t"
-        "mulx	152(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r10\n\t"
-        "adoxq	%%r9, %%r11\n\t"
-        "movq	%%r13, 312(%[t])\n\t"
-        "movq	%%r14, 320(%[t])\n\t"
-        "movq	%%rax, 328(%[t])\n\t"
-        "movq	%%r10, 336(%[t])\n\t"
-        "movq	352(%[t]), %%r12\n\t"
-        "movq	360(%[t]), %%r13\n\t"
-        "movq	368(%[t]), %%r14\n\t"
-        "# A[23] * B[20]\n\t"
-        "mulx	160(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r11\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "# A[23] * B[21]\n\t"
-        "mulx	168(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "# A[23] * B[22]\n\t"
-        "mulx	176(%[b]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "# A[23] * B[23]\n\t"
-        "mulx	184(%[b]), %%r8, %%r9\n\t"
-        "movq	%%r15, %%rax\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%rcx, %%rax\n\t"
-        "movq	%%r11, 344(%[t])\n\t"
-        "movq	%%r12, 352(%[t])\n\t"
-        "movq	%%r13, 360(%[t])\n\t"
-        "movq	%%r14, 368(%[t])\n\t"
-        "movq	%%rax, 376(%[t])\n\t"
-        :
-        : [a] "r" (a), [b] "r" (b), [t] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx",
-          "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[48];
-
-    __asm__ __volatile__ (
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 1\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "xorq	%%r13, %%r13\n\t"
-        "xorq	%%r14, %%r14\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "# A[1] x A[0]\n\t"
-        "movq	0(%[a]), %%rdx\n\t"
-        "mulxq	8(%[a]), %%r10, %%r11\n\t"
-        "# A[2] x A[0]\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[3] x A[0]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[4] x A[0]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[5] x A[0]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 8(%[tmp])\n\t"
-        "movq	%%r11, 16(%[tmp])\n\t"
-        "movq	%%r12, 24(%[tmp])\n\t"
-        "movq	%%r13, 32(%[tmp])\n\t"
-        "movq	%%r14, 40(%[tmp])\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "# A[6] x A[0]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[7] x A[0]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[0]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[9] x A[0]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[0]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 48(%[tmp])\n\t"
-        "movq	%%r10, 56(%[tmp])\n\t"
-        "movq	%%r11, 64(%[tmp])\n\t"
-        "movq	%%r12, 72(%[tmp])\n\t"
-        "movq	%%r13, 80(%[tmp])\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[11] x A[0]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[0]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[0]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[0]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[15] x A[0]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 88(%[tmp])\n\t"
-        "movq	%%r15, 96(%[tmp])\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "# A[16] x A[0]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[17] x A[0]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[18] x A[0]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[19] x A[0]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[20] x A[0]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "# A[21] x A[0]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[22] x A[0]\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[23] x A[0]\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 2\n\t"
-        "movq	24(%[tmp]), %%r15\n\t"
-        "movq	32(%[tmp]), %%r10\n\t"
-        "movq	40(%[tmp]), %%r11\n\t"
-        "movq	48(%[tmp]), %%r12\n\t"
-        "movq	56(%[tmp]), %%r13\n\t"
-        "movq	64(%[tmp]), %%r14\n\t"
-        "# A[2] x A[1]\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[3] x A[1]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[4] x A[1]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[5] x A[1]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[6] x A[1]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 24(%[tmp])\n\t"
-        "movq	%%r10, 32(%[tmp])\n\t"
-        "movq	%%r11, 40(%[tmp])\n\t"
-        "movq	%%r12, 48(%[tmp])\n\t"
-        "movq	%%r13, 56(%[tmp])\n\t"
-        "movq	72(%[tmp]), %%r15\n\t"
-        "movq	80(%[tmp]), %%r10\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "movq	96(%[tmp]), %%r12\n\t"
-        "movq	104(%[tmp]), %%r13\n\t"
-        "# A[7] x A[1]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[8] x A[1]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[9] x A[1]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[10] x A[1]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[11] x A[1]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 64(%[tmp])\n\t"
-        "movq	%%r15, 72(%[tmp])\n\t"
-        "movq	%%r10, 80(%[tmp])\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	%%r12, 96(%[tmp])\n\t"
-        "movq	112(%[tmp]), %%r14\n\t"
-        "movq	120(%[tmp]), %%r15\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "movq	144(%[tmp]), %%r12\n\t"
-        "# A[12] x A[1]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[13] x A[1]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[1]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[15] x A[1]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[16] x A[1]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 104(%[tmp])\n\t"
-        "movq	%%r14, 112(%[tmp])\n\t"
-        "movq	%%r15, 120(%[tmp])\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "movq	168(%[tmp]), %%r15\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "# A[17] x A[1]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[18] x A[1]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[19] x A[1]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[20] x A[1]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[21] x A[1]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 144(%[tmp])\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "# A[22] x A[1]\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[23] x A[1]\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[23] x A[2]\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r14\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 3\n\t"
-        "movq	40(%[tmp]), %%r14\n\t"
-        "movq	48(%[tmp]), %%r15\n\t"
-        "movq	56(%[tmp]), %%r10\n\t"
-        "movq	64(%[tmp]), %%r11\n\t"
-        "movq	72(%[tmp]), %%r12\n\t"
-        "movq	80(%[tmp]), %%r13\n\t"
-        "# A[3] x A[2]\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[4] x A[2]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[5] x A[2]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[6] x A[2]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[7] x A[2]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 40(%[tmp])\n\t"
-        "movq	%%r15, 48(%[tmp])\n\t"
-        "movq	%%r10, 56(%[tmp])\n\t"
-        "movq	%%r11, 64(%[tmp])\n\t"
-        "movq	%%r12, 72(%[tmp])\n\t"
-        "movq	88(%[tmp]), %%r14\n\t"
-        "movq	96(%[tmp]), %%r15\n\t"
-        "movq	104(%[tmp]), %%r10\n\t"
-        "movq	112(%[tmp]), %%r11\n\t"
-        "movq	120(%[tmp]), %%r12\n\t"
-        "# A[8] x A[2]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[9] x A[2]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[10] x A[2]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[11] x A[2]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[12] x A[2]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 80(%[tmp])\n\t"
-        "movq	%%r14, 88(%[tmp])\n\t"
-        "movq	%%r15, 96(%[tmp])\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	128(%[tmp]), %%r13\n\t"
-        "movq	136(%[tmp]), %%r14\n\t"
-        "movq	144(%[tmp]), %%r15\n\t"
-        "movq	152(%[tmp]), %%r10\n\t"
-        "movq	160(%[tmp]), %%r11\n\t"
-        "# A[13] x A[2]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[14] x A[2]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[2]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[16] x A[2]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[17] x A[2]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "# A[18] x A[2]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[19] x A[2]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[20] x A[2]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[21] x A[2]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[22] x A[2]\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[22] x A[3]\n\t"
-        "movq	176(%[a]), %%rdx\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[22] x A[4]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[22] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 4\n\t"
-        "movq	56(%[tmp]), %%r13\n\t"
-        "movq	64(%[tmp]), %%r14\n\t"
-        "movq	72(%[tmp]), %%r15\n\t"
-        "movq	80(%[tmp]), %%r10\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "movq	96(%[tmp]), %%r12\n\t"
-        "# A[4] x A[3]\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[5] x A[3]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[6] x A[3]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[7] x A[3]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[3]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 56(%[tmp])\n\t"
-        "movq	%%r14, 64(%[tmp])\n\t"
-        "movq	%%r15, 72(%[tmp])\n\t"
-        "movq	%%r10, 80(%[tmp])\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	104(%[tmp]), %%r13\n\t"
-        "movq	112(%[tmp]), %%r14\n\t"
-        "movq	120(%[tmp]), %%r15\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "# A[9] x A[3]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[3]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[11] x A[3]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[3]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[3]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 96(%[tmp])\n\t"
-        "movq	%%r13, 104(%[tmp])\n\t"
-        "movq	%%r14, 112(%[tmp])\n\t"
-        "movq	%%r15, 120(%[tmp])\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	144(%[tmp]), %%r12\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "movq	168(%[tmp]), %%r15\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "# A[14] x A[3]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[15] x A[3]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[16] x A[3]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[17] x A[3]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[18] x A[3]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	%%r12, 144(%[tmp])\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "movq	200(%[tmp]), %%r13\n\t"
-        "movq	208(%[tmp]), %%r14\n\t"
-        "movq	216(%[tmp]), %%r15\n\t"
-        "# A[19] x A[3]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[20] x A[3]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[21] x A[3]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[21] x A[4]\n\t"
-        "movq	168(%[a]), %%rdx\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[21] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "# A[21] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[21] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[21] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, 216(%[tmp])\n\t"
-        "movq	%%r10, 224(%[tmp])\n\t"
-        "movq	%%r11, 232(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r12\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r12, 240(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 5\n\t"
-        "movq	72(%[tmp]), %%r12\n\t"
-        "movq	80(%[tmp]), %%r13\n\t"
-        "movq	88(%[tmp]), %%r14\n\t"
-        "movq	96(%[tmp]), %%r15\n\t"
-        "movq	104(%[tmp]), %%r10\n\t"
-        "movq	112(%[tmp]), %%r11\n\t"
-        "# A[5] x A[4]\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[6] x A[4]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[7] x A[4]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[8] x A[4]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[9] x A[4]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 72(%[tmp])\n\t"
-        "movq	%%r13, 80(%[tmp])\n\t"
-        "movq	%%r14, 88(%[tmp])\n\t"
-        "movq	%%r15, 96(%[tmp])\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	120(%[tmp]), %%r12\n\t"
-        "movq	128(%[tmp]), %%r13\n\t"
-        "movq	136(%[tmp]), %%r14\n\t"
-        "movq	144(%[tmp]), %%r15\n\t"
-        "movq	152(%[tmp]), %%r10\n\t"
-        "# A[10] x A[4]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[11] x A[4]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[12] x A[4]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[13] x A[4]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[4]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	160(%[tmp]), %%r11\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "# A[15] x A[4]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[16] x A[4]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[17] x A[4]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[18] x A[4]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[19] x A[4]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "movq	216(%[tmp]), %%r12\n\t"
-        "movq	224(%[tmp]), %%r13\n\t"
-        "movq	232(%[tmp]), %%r14\n\t"
-        "# A[20] x A[4]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[20] x A[5]\n\t"
-        "movq	160(%[a]), %%rdx\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[20] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[20] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[20] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "movq	240(%[tmp]), %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "# A[20] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[20] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[20] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r14, 232(%[tmp])\n\t"
-        "movq	%%r15, 240(%[tmp])\n\t"
-        "movq	%%r10, 248(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r11\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r11, 256(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 6\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "movq	96(%[tmp]), %%r12\n\t"
-        "movq	104(%[tmp]), %%r13\n\t"
-        "movq	112(%[tmp]), %%r14\n\t"
-        "movq	120(%[tmp]), %%r15\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "# A[6] x A[5]\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[7] x A[5]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[8] x A[5]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[9] x A[5]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[10] x A[5]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	%%r12, 96(%[tmp])\n\t"
-        "movq	%%r13, 104(%[tmp])\n\t"
-        "movq	%%r14, 112(%[tmp])\n\t"
-        "movq	%%r15, 120(%[tmp])\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "movq	144(%[tmp]), %%r12\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "movq	168(%[tmp]), %%r15\n\t"
-        "# A[11] x A[5]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[12] x A[5]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[5]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[14] x A[5]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[5]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	%%r12, 144(%[tmp])\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "movq	200(%[tmp]), %%r13\n\t"
-        "movq	208(%[tmp]), %%r14\n\t"
-        "# A[16] x A[5]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[17] x A[5]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[18] x A[5]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[19] x A[5]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[19] x A[6]\n\t"
-        "movq	152(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "movq	216(%[tmp]), %%r15\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "movq	240(%[tmp]), %%r12\n\t"
-        "movq	248(%[tmp]), %%r13\n\t"
-        "# A[19] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[19] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[19] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[19] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[19] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "movq	%%r15, 216(%[tmp])\n\t"
-        "movq	%%r10, 224(%[tmp])\n\t"
-        "movq	%%r11, 232(%[tmp])\n\t"
-        "movq	%%r12, 240(%[tmp])\n\t"
-        "movq	256(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[19] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[19] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[19] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r13, 248(%[tmp])\n\t"
-        "movq	%%r14, 256(%[tmp])\n\t"
-        "movq	%%r15, 264(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 272(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 7\n\t"
-        "movq	104(%[tmp]), %%r10\n\t"
-        "movq	112(%[tmp]), %%r11\n\t"
-        "movq	120(%[tmp]), %%r12\n\t"
-        "movq	128(%[tmp]), %%r13\n\t"
-        "movq	136(%[tmp]), %%r14\n\t"
-        "movq	144(%[tmp]), %%r15\n\t"
-        "# A[7] x A[6]\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[8] x A[6]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[9] x A[6]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[10] x A[6]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[11] x A[6]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 104(%[tmp])\n\t"
-        "movq	%%r11, 112(%[tmp])\n\t"
-        "movq	%%r12, 120(%[tmp])\n\t"
-        "movq	%%r13, 128(%[tmp])\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	152(%[tmp]), %%r10\n\t"
-        "movq	160(%[tmp]), %%r11\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "# A[12] x A[6]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[6]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[6]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[15] x A[6]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[16] x A[6]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "movq	216(%[tmp]), %%r12\n\t"
-        "movq	224(%[tmp]), %%r13\n\t"
-        "# A[17] x A[6]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[18] x A[6]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[18] x A[7]\n\t"
-        "movq	144(%[a]), %%rdx\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[18] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[18] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "movq	232(%[tmp]), %%r14\n\t"
-        "movq	240(%[tmp]), %%r15\n\t"
-        "movq	248(%[tmp]), %%r10\n\t"
-        "movq	256(%[tmp]), %%r11\n\t"
-        "movq	264(%[tmp]), %%r12\n\t"
-        "# A[18] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[18] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[18] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[18] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[18] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "movq	%%r14, 232(%[tmp])\n\t"
-        "movq	%%r15, 240(%[tmp])\n\t"
-        "movq	%%r10, 248(%[tmp])\n\t"
-        "movq	%%r11, 256(%[tmp])\n\t"
-        "movq	272(%[tmp]), %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "# A[18] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[18] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[18] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r12, 264(%[tmp])\n\t"
-        "movq	%%r13, 272(%[tmp])\n\t"
-        "movq	%%r14, 280(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r15\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r15, 288(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 8\n\t"
-        "movq	120(%[tmp]), %%r15\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "movq	144(%[tmp]), %%r12\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "# A[8] x A[7]\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[9] x A[7]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[10] x A[7]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[11] x A[7]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[12] x A[7]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 120(%[tmp])\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	%%r12, 144(%[tmp])\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	168(%[tmp]), %%r15\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "movq	200(%[tmp]), %%r13\n\t"
-        "# A[13] x A[7]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[7]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[15] x A[7]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[16] x A[7]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[17] x A[7]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	208(%[tmp]), %%r14\n\t"
-        "movq	216(%[tmp]), %%r15\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "movq	240(%[tmp]), %%r12\n\t"
-        "# A[17] x A[8]\n\t"
-        "movq	136(%[a]), %%rdx\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[17] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[17] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[17] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[17] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "movq	%%r15, 216(%[tmp])\n\t"
-        "movq	%%r10, 224(%[tmp])\n\t"
-        "movq	%%r11, 232(%[tmp])\n\t"
-        "movq	248(%[tmp]), %%r13\n\t"
-        "movq	256(%[tmp]), %%r14\n\t"
-        "movq	264(%[tmp]), %%r15\n\t"
-        "movq	272(%[tmp]), %%r10\n\t"
-        "movq	280(%[tmp]), %%r11\n\t"
-        "# A[17] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[17] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[17] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[17] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[19] x A[15]\n\t"
-        "movq	152(%[a]), %%rdx\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 240(%[tmp])\n\t"
-        "movq	%%r13, 248(%[tmp])\n\t"
-        "movq	%%r14, 256(%[tmp])\n\t"
-        "movq	%%r15, 264(%[tmp])\n\t"
-        "movq	%%r10, 272(%[tmp])\n\t"
-        "movq	288(%[tmp]), %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "movq	%%r8, %%r14\n\t"
-        "# A[19] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[19] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[19] x A[18]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r11, 280(%[tmp])\n\t"
-        "movq	%%r12, 288(%[tmp])\n\t"
-        "movq	%%r13, 296(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r14\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r14, 304(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 9\n\t"
-        "movq	136(%[tmp]), %%r14\n\t"
-        "movq	144(%[tmp]), %%r15\n\t"
-        "movq	152(%[tmp]), %%r10\n\t"
-        "movq	160(%[tmp]), %%r11\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "# A[9] x A[8]\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[10] x A[8]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[11] x A[8]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[12] x A[8]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[8]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 136(%[tmp])\n\t"
-        "movq	%%r15, 144(%[tmp])\n\t"
-        "movq	%%r10, 152(%[tmp])\n\t"
-        "movq	%%r11, 160(%[tmp])\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "movq	216(%[tmp]), %%r12\n\t"
-        "# A[14] x A[8]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[8]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[16] x A[8]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[16] x A[9]\n\t"
-        "movq	128(%[a]), %%rdx\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[16] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	224(%[tmp]), %%r13\n\t"
-        "movq	232(%[tmp]), %%r14\n\t"
-        "movq	240(%[tmp]), %%r15\n\t"
-        "movq	248(%[tmp]), %%r10\n\t"
-        "movq	256(%[tmp]), %%r11\n\t"
-        "# A[16] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[16] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[16] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[16] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[16] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "movq	%%r14, 232(%[tmp])\n\t"
-        "movq	%%r15, 240(%[tmp])\n\t"
-        "movq	%%r10, 248(%[tmp])\n\t"
-        "movq	264(%[tmp]), %%r12\n\t"
-        "movq	272(%[tmp]), %%r13\n\t"
-        "movq	280(%[tmp]), %%r14\n\t"
-        "movq	288(%[tmp]), %%r15\n\t"
-        "movq	296(%[tmp]), %%r10\n\t"
-        "# A[20] x A[12]\n\t"
-        "movq	160(%[a]), %%rdx\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[20] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[20] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[20] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[20] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 256(%[tmp])\n\t"
-        "movq	%%r12, 264(%[tmp])\n\t"
-        "movq	%%r13, 272(%[tmp])\n\t"
-        "movq	%%r14, 280(%[tmp])\n\t"
-        "movq	%%r15, 288(%[tmp])\n\t"
-        "movq	304(%[tmp]), %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "movq	%%r8, %%r13\n\t"
-        "# A[20] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[20] x A[18]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[20] x A[19]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r10, 296(%[tmp])\n\t"
-        "movq	%%r11, 304(%[tmp])\n\t"
-        "movq	%%r12, 312(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r13\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r13, 320(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 10\n\t"
-        "movq	152(%[tmp]), %%r13\n\t"
-        "movq	160(%[tmp]), %%r14\n\t"
-        "movq	168(%[tmp]), %%r15\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "# A[10] x A[9]\n\t"
-        "movq	72(%[a]), %%rdx\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[11] x A[9]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[12] x A[9]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[13] x A[9]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[14] x A[9]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r13, 152(%[tmp])\n\t"
-        "movq	%%r14, 160(%[tmp])\n\t"
-        "movq	%%r15, 168(%[tmp])\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	200(%[tmp]), %%r13\n\t"
-        "movq	208(%[tmp]), %%r14\n\t"
-        "movq	216(%[tmp]), %%r15\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "# A[15] x A[9]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[15] x A[10]\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[15] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[15] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[15] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "movq	%%r15, 216(%[tmp])\n\t"
-        "movq	%%r10, 224(%[tmp])\n\t"
-        "movq	240(%[tmp]), %%r12\n\t"
-        "movq	248(%[tmp]), %%r13\n\t"
-        "movq	256(%[tmp]), %%r14\n\t"
-        "movq	264(%[tmp]), %%r15\n\t"
-        "movq	272(%[tmp]), %%r10\n\t"
-        "# A[15] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[21] x A[9]\n\t"
-        "movq	168(%[a]), %%rdx\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[21] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[21] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[21] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 232(%[tmp])\n\t"
-        "movq	%%r12, 240(%[tmp])\n\t"
-        "movq	%%r13, 248(%[tmp])\n\t"
-        "movq	%%r14, 256(%[tmp])\n\t"
-        "movq	%%r15, 264(%[tmp])\n\t"
-        "movq	280(%[tmp]), %%r11\n\t"
-        "movq	288(%[tmp]), %%r12\n\t"
-        "movq	296(%[tmp]), %%r13\n\t"
-        "movq	304(%[tmp]), %%r14\n\t"
-        "movq	312(%[tmp]), %%r15\n\t"
-        "# A[21] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[21] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[21] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[21] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[21] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 272(%[tmp])\n\t"
-        "movq	%%r11, 280(%[tmp])\n\t"
-        "movq	%%r12, 288(%[tmp])\n\t"
-        "movq	%%r13, 296(%[tmp])\n\t"
-        "movq	%%r14, 304(%[tmp])\n\t"
-        "movq	320(%[tmp]), %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "movq	%%r8, %%r12\n\t"
-        "# A[21] x A[18]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[21] x A[19]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[21] x A[20]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "movq	%%r15, 312(%[tmp])\n\t"
-        "movq	%%r10, 320(%[tmp])\n\t"
-        "movq	%%r11, 328(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r12\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r12, 336(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 11\n\t"
-        "movq	168(%[tmp]), %%r12\n\t"
-        "movq	176(%[tmp]), %%r13\n\t"
-        "movq	184(%[tmp]), %%r14\n\t"
-        "movq	192(%[tmp]), %%r15\n\t"
-        "movq	200(%[tmp]), %%r10\n\t"
-        "movq	208(%[tmp]), %%r11\n\t"
-        "# A[11] x A[10]\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[12] x A[10]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[13] x A[10]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[14] x A[10]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[14] x A[11]\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r12, 168(%[tmp])\n\t"
-        "movq	%%r13, 176(%[tmp])\n\t"
-        "movq	%%r14, 184(%[tmp])\n\t"
-        "movq	%%r15, 192(%[tmp])\n\t"
-        "movq	%%r10, 200(%[tmp])\n\t"
-        "movq	216(%[tmp]), %%r12\n\t"
-        "movq	224(%[tmp]), %%r13\n\t"
-        "movq	232(%[tmp]), %%r14\n\t"
-        "movq	240(%[tmp]), %%r15\n\t"
-        "movq	248(%[tmp]), %%r10\n\t"
-        "# A[14] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[14] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[22] x A[6]\n\t"
-        "movq	176(%[a]), %%rdx\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[22] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[22] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 208(%[tmp])\n\t"
-        "movq	%%r12, 216(%[tmp])\n\t"
-        "movq	%%r13, 224(%[tmp])\n\t"
-        "movq	%%r14, 232(%[tmp])\n\t"
-        "movq	%%r15, 240(%[tmp])\n\t"
-        "movq	256(%[tmp]), %%r11\n\t"
-        "movq	264(%[tmp]), %%r12\n\t"
-        "movq	272(%[tmp]), %%r13\n\t"
-        "movq	280(%[tmp]), %%r14\n\t"
-        "movq	288(%[tmp]), %%r15\n\t"
-        "# A[22] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[22] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[22] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[22] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[22] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 248(%[tmp])\n\t"
-        "movq	%%r11, 256(%[tmp])\n\t"
-        "movq	%%r12, 264(%[tmp])\n\t"
-        "movq	%%r13, 272(%[tmp])\n\t"
-        "movq	%%r14, 280(%[tmp])\n\t"
-        "movq	296(%[tmp]), %%r10\n\t"
-        "movq	304(%[tmp]), %%r11\n\t"
-        "movq	312(%[tmp]), %%r12\n\t"
-        "movq	320(%[tmp]), %%r13\n\t"
-        "movq	328(%[tmp]), %%r14\n\t"
-        "# A[22] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[22] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[22] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[22] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[22] x A[18]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 288(%[tmp])\n\t"
-        "movq	%%r10, 296(%[tmp])\n\t"
-        "movq	%%r11, 304(%[tmp])\n\t"
-        "movq	%%r12, 312(%[tmp])\n\t"
-        "movq	%%r13, 320(%[tmp])\n\t"
-        "movq	336(%[tmp]), %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "movq	%%r8, %%r11\n\t"
-        "# A[22] x A[19]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[22] x A[20]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[22] x A[21]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "movq	%%r14, 328(%[tmp])\n\t"
-        "movq	%%r15, 336(%[tmp])\n\t"
-        "movq	%%r10, 344(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r11\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r11, 352(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Diagonal 12\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "movq	192(%[tmp]), %%r12\n\t"
-        "movq	200(%[tmp]), %%r13\n\t"
-        "movq	208(%[tmp]), %%r14\n\t"
-        "movq	216(%[tmp]), %%r15\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "# A[12] x A[11]\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[13] x A[11]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[13] x A[12]\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[23] x A[3]\n\t"
-        "movq	184(%[a]), %%rdx\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[23] x A[4]\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	%%r12, 192(%[tmp])\n\t"
-        "movq	%%r13, 200(%[tmp])\n\t"
-        "movq	%%r14, 208(%[tmp])\n\t"
-        "movq	%%r15, 216(%[tmp])\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "movq	240(%[tmp]), %%r12\n\t"
-        "movq	248(%[tmp]), %%r13\n\t"
-        "movq	256(%[tmp]), %%r14\n\t"
-        "movq	264(%[tmp]), %%r15\n\t"
-        "# A[23] x A[5]\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[23] x A[6]\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[23] x A[7]\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[23] x A[8]\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[23] x A[9]\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "movq	%%r10, 224(%[tmp])\n\t"
-        "movq	%%r11, 232(%[tmp])\n\t"
-        "movq	%%r12, 240(%[tmp])\n\t"
-        "movq	%%r13, 248(%[tmp])\n\t"
-        "movq	%%r14, 256(%[tmp])\n\t"
-        "movq	272(%[tmp]), %%r10\n\t"
-        "movq	280(%[tmp]), %%r11\n\t"
-        "movq	288(%[tmp]), %%r12\n\t"
-        "movq	296(%[tmp]), %%r13\n\t"
-        "movq	304(%[tmp]), %%r14\n\t"
-        "# A[23] x A[10]\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[23] x A[11]\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[23] x A[12]\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[23] x A[13]\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "# A[23] x A[14]\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "movq	%%r15, 264(%[tmp])\n\t"
-        "movq	%%r10, 272(%[tmp])\n\t"
-        "movq	%%r11, 280(%[tmp])\n\t"
-        "movq	%%r12, 288(%[tmp])\n\t"
-        "movq	%%r13, 296(%[tmp])\n\t"
-        "movq	312(%[tmp]), %%r15\n\t"
-        "movq	320(%[tmp]), %%r10\n\t"
-        "movq	328(%[tmp]), %%r11\n\t"
-        "movq	336(%[tmp]), %%r12\n\t"
-        "movq	344(%[tmp]), %%r13\n\t"
-        "# A[23] x A[15]\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[23] x A[16]\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "# A[23] x A[17]\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%rcx, %%r11\n\t"
-        "# A[23] x A[18]\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "# A[23] x A[19]\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "movq	%%r14, 304(%[tmp])\n\t"
-        "movq	%%r15, 312(%[tmp])\n\t"
-        "movq	%%r10, 320(%[tmp])\n\t"
-        "movq	%%r11, 328(%[tmp])\n\t"
-        "movq	%%r12, 336(%[tmp])\n\t"
-        "movq	352(%[tmp]), %%r14\n\t"
-        "movq	%%r8, %%r15\n\t"
-        "movq	%%r8, %%r10\n\t"
-        "# A[23] x A[20]\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "# A[23] x A[21]\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r14\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "# A[23] x A[22]\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "adcxq	%%rax, %%r15\n\t"
-        "adoxq	%%rcx, %%r10\n\t"
-        "movq	%%r13, 344(%[tmp])\n\t"
-        "movq	%%r14, 352(%[tmp])\n\t"
-        "movq	%%r15, 360(%[tmp])\n\t"
-        "#  Carry\n\t"
-        "adcxq	%%r9, %%r10\n\t"
-        "movq	%%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r9\n\t"
-        "adoxq	%%r8, %%r9\n\t"
-        "movq	%%r10, 368(%[tmp])\n\t"
-        "movq	%%r9, 376(%[tmp])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "# Double and Add in A[i] x A[i]\n\t"
-        "movq	8(%[tmp]), %%r11\n\t"
-        "# A[0] x A[0]\n\t"
-        "movq	0(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "movq	%%rax, 0(%[tmp])\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r11, 8(%[tmp])\n\t"
-        "movq	16(%[tmp]), %%r10\n\t"
-        "movq	24(%[tmp]), %%r11\n\t"
-        "# A[1] x A[1]\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 16(%[tmp])\n\t"
-        "movq	%%r11, 24(%[tmp])\n\t"
-        "movq	32(%[tmp]), %%r10\n\t"
-        "movq	40(%[tmp]), %%r11\n\t"
-        "# A[2] x A[2]\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 32(%[tmp])\n\t"
-        "movq	%%r11, 40(%[tmp])\n\t"
-        "movq	48(%[tmp]), %%r10\n\t"
-        "movq	56(%[tmp]), %%r11\n\t"
-        "# A[3] x A[3]\n\t"
-        "movq	24(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 48(%[tmp])\n\t"
-        "movq	%%r11, 56(%[tmp])\n\t"
-        "movq	64(%[tmp]), %%r10\n\t"
-        "movq	72(%[tmp]), %%r11\n\t"
-        "# A[4] x A[4]\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 64(%[tmp])\n\t"
-        "movq	%%r11, 72(%[tmp])\n\t"
-        "movq	80(%[tmp]), %%r10\n\t"
-        "movq	88(%[tmp]), %%r11\n\t"
-        "# A[5] x A[5]\n\t"
-        "movq	40(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 80(%[tmp])\n\t"
-        "movq	%%r11, 88(%[tmp])\n\t"
-        "movq	96(%[tmp]), %%r10\n\t"
-        "movq	104(%[tmp]), %%r11\n\t"
-        "# A[6] x A[6]\n\t"
-        "movq	48(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 96(%[tmp])\n\t"
-        "movq	%%r11, 104(%[tmp])\n\t"
-        "movq	112(%[tmp]), %%r10\n\t"
-        "movq	120(%[tmp]), %%r11\n\t"
-        "# A[7] x A[7]\n\t"
-        "movq	56(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 112(%[tmp])\n\t"
-        "movq	%%r11, 120(%[tmp])\n\t"
-        "movq	128(%[tmp]), %%r10\n\t"
-        "movq	136(%[tmp]), %%r11\n\t"
-        "# A[8] x A[8]\n\t"
-        "movq	64(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 128(%[tmp])\n\t"
-        "movq	%%r11, 136(%[tmp])\n\t"
-        "movq	144(%[tmp]), %%r10\n\t"
-        "movq	152(%[tmp]), %%r11\n\t"
-        "# A[9] x A[9]\n\t"
-        "movq	72(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 144(%[tmp])\n\t"
-        "movq	%%r11, 152(%[tmp])\n\t"
-        "movq	160(%[tmp]), %%r10\n\t"
-        "movq	168(%[tmp]), %%r11\n\t"
-        "# A[10] x A[10]\n\t"
-        "movq	80(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 160(%[tmp])\n\t"
-        "movq	%%r11, 168(%[tmp])\n\t"
-        "movq	176(%[tmp]), %%r10\n\t"
-        "movq	184(%[tmp]), %%r11\n\t"
-        "# A[11] x A[11]\n\t"
-        "movq	88(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 176(%[tmp])\n\t"
-        "movq	%%r11, 184(%[tmp])\n\t"
-        "movq	192(%[tmp]), %%r10\n\t"
-        "movq	200(%[tmp]), %%r11\n\t"
-        "# A[12] x A[12]\n\t"
-        "movq	96(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 192(%[r])\n\t"
-        "movq	%%r11, 200(%[r])\n\t"
-        "movq	208(%[tmp]), %%r10\n\t"
-        "movq	216(%[tmp]), %%r11\n\t"
-        "# A[13] x A[13]\n\t"
-        "movq	104(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 208(%[r])\n\t"
-        "movq	%%r11, 216(%[r])\n\t"
-        "movq	224(%[tmp]), %%r10\n\t"
-        "movq	232(%[tmp]), %%r11\n\t"
-        "# A[14] x A[14]\n\t"
-        "movq	112(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 224(%[r])\n\t"
-        "movq	%%r11, 232(%[r])\n\t"
-        "movq	240(%[tmp]), %%r10\n\t"
-        "movq	248(%[tmp]), %%r11\n\t"
-        "# A[15] x A[15]\n\t"
-        "movq	120(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 240(%[r])\n\t"
-        "movq	%%r11, 248(%[r])\n\t"
-        "movq	256(%[tmp]), %%r10\n\t"
-        "movq	264(%[tmp]), %%r11\n\t"
-        "# A[16] x A[16]\n\t"
-        "movq	128(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 256(%[r])\n\t"
-        "movq	%%r11, 264(%[r])\n\t"
-        "movq	272(%[tmp]), %%r10\n\t"
-        "movq	280(%[tmp]), %%r11\n\t"
-        "# A[17] x A[17]\n\t"
-        "movq	136(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 272(%[r])\n\t"
-        "movq	%%r11, 280(%[r])\n\t"
-        "movq	288(%[tmp]), %%r10\n\t"
-        "movq	296(%[tmp]), %%r11\n\t"
-        "# A[18] x A[18]\n\t"
-        "movq	144(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 288(%[r])\n\t"
-        "movq	%%r11, 296(%[r])\n\t"
-        "movq	304(%[tmp]), %%r10\n\t"
-        "movq	312(%[tmp]), %%r11\n\t"
-        "# A[19] x A[19]\n\t"
-        "movq	152(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 304(%[r])\n\t"
-        "movq	%%r11, 312(%[r])\n\t"
-        "movq	320(%[tmp]), %%r10\n\t"
-        "movq	328(%[tmp]), %%r11\n\t"
-        "# A[20] x A[20]\n\t"
-        "movq	160(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 320(%[r])\n\t"
-        "movq	%%r11, 328(%[r])\n\t"
-        "movq	336(%[tmp]), %%r10\n\t"
-        "movq	344(%[tmp]), %%r11\n\t"
-        "# A[21] x A[21]\n\t"
-        "movq	168(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 336(%[r])\n\t"
-        "movq	%%r11, 344(%[r])\n\t"
-        "movq	352(%[tmp]), %%r10\n\t"
-        "movq	360(%[tmp]), %%r11\n\t"
-        "# A[22] x A[22]\n\t"
-        "movq	176(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 352(%[r])\n\t"
-        "movq	%%r11, 360(%[r])\n\t"
-        "movq	368(%[tmp]), %%r10\n\t"
-        "movq	376(%[tmp]), %%r11\n\t"
-        "# A[23] x A[23]\n\t"
-        "movq	184(%[a]), %%rdx\n\t"
-        "mulxq	%%rdx, %%rax, %%rcx\n\t"
-        "adoxq	%%r10, %%r10\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r11, %%r11\n\t"
-        "adcxq	%%rcx, %%r11\n\t"
-        "movq	%%r10, 368(%[r])\n\t"
-        "movq	%%r11, 376(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp)/2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "addq	(%[b]), %%rax\n\t"
-        "movq	%%rax, (%[r])\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "adcq	8(%[b]), %%rax\n\t"
-        "movq	%%rax, 8(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "adcq	16(%[b]), %%rax\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "adcq	24(%[b]), %%rax\n\t"
-        "movq	%%rax, 24(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "adcq	32(%[b]), %%rax\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "adcq	40(%[b]), %%rax\n\t"
-        "movq	%%rax, 40(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "adcq	48(%[b]), %%rax\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "adcq	56(%[b]), %%rax\n\t"
-        "movq	%%rax, 56(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "adcq	64(%[b]), %%rax\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "adcq	72(%[b]), %%rax\n\t"
-        "movq	%%rax, 72(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "adcq	80(%[b]), %%rax\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "adcq	88(%[b]), %%rax\n\t"
-        "movq	%%rax, 88(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "adcq	96(%[b]), %%rax\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "adcq	104(%[b]), %%rax\n\t"
-        "movq	%%rax, 104(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "adcq	112(%[b]), %%rax\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "adcq	120(%[b]), %%rax\n\t"
-        "movq	%%rax, 120(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "adcq	128(%[b]), %%rax\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "adcq	136(%[b]), %%rax\n\t"
-        "movq	%%rax, 136(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "adcq	144(%[b]), %%rax\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "adcq	152(%[b]), %%rax\n\t"
-        "movq	%%rax, 152(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "adcq	160(%[b]), %%rax\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "adcq	168(%[b]), %%rax\n\t"
-        "movq	%%rax, 168(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "adcq	176(%[b]), %%rax\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "adcq	184(%[b]), %%rax\n\t"
-        "movq	%%rax, 184(%[r])\n\t"
-        "adcq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax"
-    );
-
-    return c;
-}
-
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r8\n\t"
-        "movq	8(%[a]), %%r9\n\t"
-        "movq	0(%[b]), %%rdx\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "subq	%%rdx, %%r8\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "movq	%%r8, 0(%[a])\n\t"
-        "movq	16(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "movq	%%r9, 8(%[a])\n\t"
-        "movq	24(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	32(%[b]), %%rdx\n\t"
-        "movq	%%r8, 16(%[a])\n\t"
-        "movq	32(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "movq	%%r9, 24(%[a])\n\t"
-        "movq	40(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	48(%[b]), %%rdx\n\t"
-        "movq	%%r8, 32(%[a])\n\t"
-        "movq	48(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "movq	%%r9, 40(%[a])\n\t"
-        "movq	56(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	64(%[b]), %%rdx\n\t"
-        "movq	%%r8, 48(%[a])\n\t"
-        "movq	64(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "movq	%%r9, 56(%[a])\n\t"
-        "movq	72(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	80(%[b]), %%rdx\n\t"
-        "movq	%%r8, 64(%[a])\n\t"
-        "movq	80(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "movq	%%r9, 72(%[a])\n\t"
-        "movq	88(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	96(%[b]), %%rdx\n\t"
-        "movq	%%r8, 80(%[a])\n\t"
-        "movq	96(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "movq	%%r9, 88(%[a])\n\t"
-        "movq	104(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	112(%[b]), %%rdx\n\t"
-        "movq	%%r8, 96(%[a])\n\t"
-        "movq	112(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "movq	%%r9, 104(%[a])\n\t"
-        "movq	120(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	128(%[b]), %%rdx\n\t"
-        "movq	%%r8, 112(%[a])\n\t"
-        "movq	128(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "movq	%%r9, 120(%[a])\n\t"
-        "movq	136(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	144(%[b]), %%rdx\n\t"
-        "movq	%%r8, 128(%[a])\n\t"
-        "movq	144(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "movq	%%r9, 136(%[a])\n\t"
-        "movq	152(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	160(%[b]), %%rdx\n\t"
-        "movq	%%r8, 144(%[a])\n\t"
-        "movq	160(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "movq	%%r9, 152(%[a])\n\t"
-        "movq	168(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	176(%[b]), %%rdx\n\t"
-        "movq	%%r8, 160(%[a])\n\t"
-        "movq	176(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "movq	%%r9, 168(%[a])\n\t"
-        "movq	184(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	192(%[b]), %%rdx\n\t"
-        "movq	%%r8, 176(%[a])\n\t"
-        "movq	192(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	200(%[b]), %%rcx\n\t"
-        "movq	%%r9, 184(%[a])\n\t"
-        "movq	200(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	208(%[b]), %%rdx\n\t"
-        "movq	%%r8, 192(%[a])\n\t"
-        "movq	208(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	216(%[b]), %%rcx\n\t"
-        "movq	%%r9, 200(%[a])\n\t"
-        "movq	216(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	224(%[b]), %%rdx\n\t"
-        "movq	%%r8, 208(%[a])\n\t"
-        "movq	224(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	232(%[b]), %%rcx\n\t"
-        "movq	%%r9, 216(%[a])\n\t"
-        "movq	232(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	240(%[b]), %%rdx\n\t"
-        "movq	%%r8, 224(%[a])\n\t"
-        "movq	240(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	248(%[b]), %%rcx\n\t"
-        "movq	%%r9, 232(%[a])\n\t"
-        "movq	248(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	256(%[b]), %%rdx\n\t"
-        "movq	%%r8, 240(%[a])\n\t"
-        "movq	256(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	264(%[b]), %%rcx\n\t"
-        "movq	%%r9, 248(%[a])\n\t"
-        "movq	264(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	272(%[b]), %%rdx\n\t"
-        "movq	%%r8, 256(%[a])\n\t"
-        "movq	272(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	280(%[b]), %%rcx\n\t"
-        "movq	%%r9, 264(%[a])\n\t"
-        "movq	280(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	288(%[b]), %%rdx\n\t"
-        "movq	%%r8, 272(%[a])\n\t"
-        "movq	288(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	296(%[b]), %%rcx\n\t"
-        "movq	%%r9, 280(%[a])\n\t"
-        "movq	296(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	304(%[b]), %%rdx\n\t"
-        "movq	%%r8, 288(%[a])\n\t"
-        "movq	304(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	312(%[b]), %%rcx\n\t"
-        "movq	%%r9, 296(%[a])\n\t"
-        "movq	312(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	320(%[b]), %%rdx\n\t"
-        "movq	%%r8, 304(%[a])\n\t"
-        "movq	320(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	328(%[b]), %%rcx\n\t"
-        "movq	%%r9, 312(%[a])\n\t"
-        "movq	328(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	336(%[b]), %%rdx\n\t"
-        "movq	%%r8, 320(%[a])\n\t"
-        "movq	336(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	344(%[b]), %%rcx\n\t"
-        "movq	%%r9, 328(%[a])\n\t"
-        "movq	344(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	352(%[b]), %%rdx\n\t"
-        "movq	%%r8, 336(%[a])\n\t"
-        "movq	352(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	360(%[b]), %%rcx\n\t"
-        "movq	%%r9, 344(%[a])\n\t"
-        "movq	360(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	368(%[b]), %%rdx\n\t"
-        "movq	%%r8, 352(%[a])\n\t"
-        "movq	368(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	376(%[b]), %%rcx\n\t"
-        "movq	%%r9, 360(%[a])\n\t"
-        "movq	376(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	%%r8, 368(%[a])\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	%%r9, 376(%[a])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "rdx", "rcx", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "addq	(%[b]), %%rax\n\t"
-        "movq	%%rax, (%[r])\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "adcq	8(%[b]), %%rax\n\t"
-        "movq	%%rax, 8(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "adcq	16(%[b]), %%rax\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "adcq	24(%[b]), %%rax\n\t"
-        "movq	%%rax, 24(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "adcq	32(%[b]), %%rax\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	40(%[a]), %%rax\n\t"
-        "adcq	40(%[b]), %%rax\n\t"
-        "movq	%%rax, 40(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "adcq	48(%[b]), %%rax\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	56(%[a]), %%rax\n\t"
-        "adcq	56(%[b]), %%rax\n\t"
-        "movq	%%rax, 56(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "adcq	64(%[b]), %%rax\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	72(%[a]), %%rax\n\t"
-        "adcq	72(%[b]), %%rax\n\t"
-        "movq	%%rax, 72(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "adcq	80(%[b]), %%rax\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	88(%[a]), %%rax\n\t"
-        "adcq	88(%[b]), %%rax\n\t"
-        "movq	%%rax, 88(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "adcq	96(%[b]), %%rax\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	104(%[a]), %%rax\n\t"
-        "adcq	104(%[b]), %%rax\n\t"
-        "movq	%%rax, 104(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "adcq	112(%[b]), %%rax\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	120(%[a]), %%rax\n\t"
-        "adcq	120(%[b]), %%rax\n\t"
-        "movq	%%rax, 120(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "adcq	128(%[b]), %%rax\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	136(%[a]), %%rax\n\t"
-        "adcq	136(%[b]), %%rax\n\t"
-        "movq	%%rax, 136(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "adcq	144(%[b]), %%rax\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	152(%[a]), %%rax\n\t"
-        "adcq	152(%[b]), %%rax\n\t"
-        "movq	%%rax, 152(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "adcq	160(%[b]), %%rax\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	168(%[a]), %%rax\n\t"
-        "adcq	168(%[b]), %%rax\n\t"
-        "movq	%%rax, 168(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "adcq	176(%[b]), %%rax\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	184(%[a]), %%rax\n\t"
-        "adcq	184(%[b]), %%rax\n\t"
-        "movq	%%rax, 184(%[r])\n\t"
-        "movq	192(%[a]), %%rax\n\t"
-        "adcq	192(%[b]), %%rax\n\t"
-        "movq	%%rax, 192(%[r])\n\t"
-        "movq	200(%[a]), %%rax\n\t"
-        "adcq	200(%[b]), %%rax\n\t"
-        "movq	%%rax, 200(%[r])\n\t"
-        "movq	208(%[a]), %%rax\n\t"
-        "adcq	208(%[b]), %%rax\n\t"
-        "movq	%%rax, 208(%[r])\n\t"
-        "movq	216(%[a]), %%rax\n\t"
-        "adcq	216(%[b]), %%rax\n\t"
-        "movq	%%rax, 216(%[r])\n\t"
-        "movq	224(%[a]), %%rax\n\t"
-        "adcq	224(%[b]), %%rax\n\t"
-        "movq	%%rax, 224(%[r])\n\t"
-        "movq	232(%[a]), %%rax\n\t"
-        "adcq	232(%[b]), %%rax\n\t"
-        "movq	%%rax, 232(%[r])\n\t"
-        "movq	240(%[a]), %%rax\n\t"
-        "adcq	240(%[b]), %%rax\n\t"
-        "movq	%%rax, 240(%[r])\n\t"
-        "movq	248(%[a]), %%rax\n\t"
-        "adcq	248(%[b]), %%rax\n\t"
-        "movq	%%rax, 248(%[r])\n\t"
-        "movq	256(%[a]), %%rax\n\t"
-        "adcq	256(%[b]), %%rax\n\t"
-        "movq	%%rax, 256(%[r])\n\t"
-        "movq	264(%[a]), %%rax\n\t"
-        "adcq	264(%[b]), %%rax\n\t"
-        "movq	%%rax, 264(%[r])\n\t"
-        "movq	272(%[a]), %%rax\n\t"
-        "adcq	272(%[b]), %%rax\n\t"
-        "movq	%%rax, 272(%[r])\n\t"
-        "movq	280(%[a]), %%rax\n\t"
-        "adcq	280(%[b]), %%rax\n\t"
-        "movq	%%rax, 280(%[r])\n\t"
-        "movq	288(%[a]), %%rax\n\t"
-        "adcq	288(%[b]), %%rax\n\t"
-        "movq	%%rax, 288(%[r])\n\t"
-        "movq	296(%[a]), %%rax\n\t"
-        "adcq	296(%[b]), %%rax\n\t"
-        "movq	%%rax, 296(%[r])\n\t"
-        "movq	304(%[a]), %%rax\n\t"
-        "adcq	304(%[b]), %%rax\n\t"
-        "movq	%%rax, 304(%[r])\n\t"
-        "movq	312(%[a]), %%rax\n\t"
-        "adcq	312(%[b]), %%rax\n\t"
-        "movq	%%rax, 312(%[r])\n\t"
-        "movq	320(%[a]), %%rax\n\t"
-        "adcq	320(%[b]), %%rax\n\t"
-        "movq	%%rax, 320(%[r])\n\t"
-        "movq	328(%[a]), %%rax\n\t"
-        "adcq	328(%[b]), %%rax\n\t"
-        "movq	%%rax, 328(%[r])\n\t"
-        "movq	336(%[a]), %%rax\n\t"
-        "adcq	336(%[b]), %%rax\n\t"
-        "movq	%%rax, 336(%[r])\n\t"
-        "movq	344(%[a]), %%rax\n\t"
-        "adcq	344(%[b]), %%rax\n\t"
-        "movq	%%rax, 344(%[r])\n\t"
-        "movq	352(%[a]), %%rax\n\t"
-        "adcq	352(%[b]), %%rax\n\t"
-        "movq	%%rax, 352(%[r])\n\t"
-        "movq	360(%[a]), %%rax\n\t"
-        "adcq	360(%[b]), %%rax\n\t"
-        "movq	%%rax, 360(%[r])\n\t"
-        "movq	368(%[a]), %%rax\n\t"
-        "adcq	368(%[b]), %%rax\n\t"
-        "movq	%%rax, 368(%[r])\n\t"
-        "movq	376(%[a]), %%rax\n\t"
-        "adcq	376(%[b]), %%rax\n\t"
-        "movq	%%rax, 376(%[r])\n\t"
-        "adcq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax"
-    );
-
-    return c;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<24; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 24; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit b1[24];
-    sp_digit z2[48];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_24(a1, a, &a[24]);
-    cb = sp_3072_add_24(b1, b, &b[24]);
-    u  = ca & cb;
-    sp_3072_mul_24(z1, a1, b1);
-    sp_3072_mul_24(z2, &a[24], &b[24]);
-    sp_3072_mul_24(z0, a, b);
-    sp_3072_mask_24(r + 48, a1, 0 - cb);
-    sp_3072_mask_24(b1, b1, 0 - ca);
-    u += sp_3072_add_24(r + 48, r + 48, b1);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[48];
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit u;
-
-    u = sp_3072_add_24(a1, a, &a[24]);
-    sp_3072_sqr_24(z1, a1);
-    sp_3072_sqr_24(z2, &a[24]);
-    sp_3072_sqr_24(z0, a);
-    sp_3072_mask_24(r + 48, a1, 0 - u);
-    u += sp_3072_add_24(r + 48, r + 48, r + 48);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit* z0 = r;
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit b1[24];
-    sp_digit z2[48];
-    sp_digit u, ca, cb;
-
-    ca = sp_3072_add_24(a1, a, &a[24]);
-    cb = sp_3072_add_24(b1, b, &b[24]);
-    u  = ca & cb;
-    sp_3072_mul_avx2_24(z1, a1, b1);
-    sp_3072_mul_avx2_24(z2, &a[24], &b[24]);
-    sp_3072_mul_avx2_24(z0, a, b);
-    sp_3072_mask_24(r + 48, a1, 0 - cb);
-    sp_3072_mask_24(b1, b1, 0 - ca);
-    u += sp_3072_add_24(r + 48, r + 48, b1);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a)
-{
-    sp_digit* z0 = r;
-    sp_digit z2[48];
-    sp_digit z1[48];
-    sp_digit a1[24];
-    sp_digit u;
-
-    u = sp_3072_add_24(a1, a, &a[24]);
-    sp_3072_sqr_avx2_24(z1, a1);
-    sp_3072_sqr_avx2_24(z2, &a[24]);
-    sp_3072_sqr_avx2_24(z0, a);
-    sp_3072_mask_24(r + 48, a1, 0 - u);
-    u += sp_3072_add_24(r + 48, r + 48, r + 48);
-    u += sp_3072_sub_in_place_48(z1, z2);
-    u += sp_3072_sub_in_place_48(z1, z0);
-    u += sp_3072_add_48(r + 24, r + 24, z1);
-    r[72] = u;
-    XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1));
-    sp_3072_add_48(r + 48, r + 48, z2);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* Caclulate the bottom digit of -1/a mod 2^n.
- *
- * a    A single precision number.
- * rho  Bottom word of inverse.
- */
-static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho)
-{
-    sp_digit x, b;
-
-    b = a[0];
-    x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-    x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-
-    /* rho = -1/m mod b */
-    *rho = -x;
-}
-
-#if !defined(SP_RSA_PRIVATE_EXP_D) && defined(WOLFSSL_HAVE_SP_RSA)
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_3072_sub_in_place_24(sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r8\n\t"
-        "movq	8(%[a]), %%r9\n\t"
-        "movq	0(%[b]), %%rdx\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "subq	%%rdx, %%r8\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "movq	%%r8, 0(%[a])\n\t"
-        "movq	16(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "movq	%%r9, 8(%[a])\n\t"
-        "movq	24(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	32(%[b]), %%rdx\n\t"
-        "movq	%%r8, 16(%[a])\n\t"
-        "movq	32(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "movq	%%r9, 24(%[a])\n\t"
-        "movq	40(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	48(%[b]), %%rdx\n\t"
-        "movq	%%r8, 32(%[a])\n\t"
-        "movq	48(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "movq	%%r9, 40(%[a])\n\t"
-        "movq	56(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	64(%[b]), %%rdx\n\t"
-        "movq	%%r8, 48(%[a])\n\t"
-        "movq	64(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "movq	%%r9, 56(%[a])\n\t"
-        "movq	72(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	80(%[b]), %%rdx\n\t"
-        "movq	%%r8, 64(%[a])\n\t"
-        "movq	80(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "movq	%%r9, 72(%[a])\n\t"
-        "movq	88(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	96(%[b]), %%rdx\n\t"
-        "movq	%%r8, 80(%[a])\n\t"
-        "movq	96(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "movq	%%r9, 88(%[a])\n\t"
-        "movq	104(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	112(%[b]), %%rdx\n\t"
-        "movq	%%r8, 96(%[a])\n\t"
-        "movq	112(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "movq	%%r9, 104(%[a])\n\t"
-        "movq	120(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	128(%[b]), %%rdx\n\t"
-        "movq	%%r8, 112(%[a])\n\t"
-        "movq	128(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "movq	%%r9, 120(%[a])\n\t"
-        "movq	136(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	144(%[b]), %%rdx\n\t"
-        "movq	%%r8, 128(%[a])\n\t"
-        "movq	144(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "movq	%%r9, 136(%[a])\n\t"
-        "movq	152(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	160(%[b]), %%rdx\n\t"
-        "movq	%%r8, 144(%[a])\n\t"
-        "movq	160(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "movq	%%r9, 152(%[a])\n\t"
-        "movq	168(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	176(%[b]), %%rdx\n\t"
-        "movq	%%r8, 160(%[a])\n\t"
-        "movq	176(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "movq	%%r9, 168(%[a])\n\t"
-        "movq	184(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	%%r8, 176(%[a])\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	%%r9, 184(%[a])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "rdx", "rcx", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_24(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 24);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_24(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_24(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit t[24];
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[b]), %%rax\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 0(%[t])\n\t"
-        "movq	%%rcx, 8(%[t])\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 16(%[t])\n\t"
-        "movq	%%rcx, 24(%[t])\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 32(%[t])\n\t"
-        "movq	%%rcx, 40(%[t])\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 48(%[t])\n\t"
-        "movq	%%rcx, 56(%[t])\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 64(%[t])\n\t"
-        "movq	%%rcx, 72(%[t])\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 80(%[t])\n\t"
-        "movq	%%rcx, 88(%[t])\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 96(%[t])\n\t"
-        "movq	%%rcx, 104(%[t])\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 112(%[t])\n\t"
-        "movq	%%rcx, 120(%[t])\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 128(%[t])\n\t"
-        "movq	%%rcx, 136(%[t])\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 144(%[t])\n\t"
-        "movq	%%rcx, 152(%[t])\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 160(%[t])\n\t"
-        "movq	%%rcx, 168(%[t])\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 176(%[t])\n\t"
-        "movq	%%rcx, 184(%[t])\n\t"
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[t]), %%rdx\n\t"
-        "subq	%%rdx,%%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "movq	32(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "movq	40(%[a]), %%rcx\n\t"
-        "movq	40(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "movq	48(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 40(%[r])\n\t"
-        "movq	56(%[a]), %%rcx\n\t"
-        "movq	56(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "movq	64(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "movq	72(%[a]), %%rcx\n\t"
-        "movq	72(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "movq	80(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 72(%[r])\n\t"
-        "movq	88(%[a]), %%rcx\n\t"
-        "movq	88(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "movq	96(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 88(%[r])\n\t"
-        "movq	104(%[a]), %%rcx\n\t"
-        "movq	104(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "movq	112(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "movq	120(%[a]), %%rcx\n\t"
-        "movq	120(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "movq	128(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 120(%[r])\n\t"
-        "movq	136(%[a]), %%rcx\n\t"
-        "movq	136(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "movq	144(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 136(%[r])\n\t"
-        "movq	152(%[a]), %%rcx\n\t"
-        "movq	152(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "movq	160(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "movq	168(%[a]), %%rcx\n\t"
-        "movq	168(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "movq	176(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 168(%[r])\n\t"
-        "movq	184(%[a]), %%rcx\n\t"
-        "movq	184(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	%%rcx, 184(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "movq	8(%[a]), %%r13\n\t"
-        "\nL_mont_loop_24:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "imulq	%[mp], %%r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	0(%[m])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	8(%[m])\n\t"
-        "movq	%%r13, %%r12\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r12\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	16(%[m])\n\t"
-        "movq	16(%[a]), %%r13\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r13\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[m])\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	32(%[m])\n\t"
-        "movq	32(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 32(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	40(%[m])\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	48(%[m])\n\t"
-        "movq	48(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 48(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	56(%[m])\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	64(%[m])\n\t"
-        "movq	64(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 64(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[m])\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	80(%[m])\n\t"
-        "movq	80(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 80(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	88(%[m])\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	96(%[m])\n\t"
-        "movq	96(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 96(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	104(%[m])\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	112(%[m])\n\t"
-        "movq	112(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 112(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[m])\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	128(%[m])\n\t"
-        "movq	128(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 128(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	136(%[m])\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	144(%[m])\n\t"
-        "movq	144(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 144(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	152(%[m])\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	160(%[m])\n\t"
-        "movq	160(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 160(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[m])\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	176(%[m])\n\t"
-        "movq	176(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 176(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "mulq	184(%[m])\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%[ca], %%rdx\n\t"
-        "movq	$0, %[ca]\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "addq	%%r9, %%r11\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "adcq	%%rdx, 192(%[a])\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$8, %%rcx\n\t"
-        "cmpq	$192, %%rcx\n\t"
-        "jl	L_mont_loop_24\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        "movq	%%r13, 8(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13"
-    );
-
-    sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_24(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_24(r, a, b);
-    sp_3072_mont_reduce_24(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_24(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_24(r, a);
-    sp_3072_mont_reduce_24(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	(%[a])\n\t"
-        "movq	%%rax, %%rbx\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[2] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[3] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 24(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[5] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 40(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[6] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 48(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[7] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[8] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[9] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 72(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 80(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[11] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 88(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[12] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 96(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[13] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[14] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[15] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 120(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 128(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[17] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 136(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[18] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 144(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[19] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[20] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[21] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 168(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 176(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[23] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "movq	%%r8, 184(%[r])\n\t"
-        "movq	%%rbx, 192(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rdx\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "mulxq	(%[a]), %%r8, %%r9\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "mulxq	8(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[2] * B\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[3] * B\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 24(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[5] * B\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 40(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[6] * B\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 48(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[7] * B\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 56(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[8] * B\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[9] * B\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 72(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 80(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[11] * B\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 88(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[12] * B\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 96(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[13] * B\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 104(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[14] * B\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[15] * B\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 120(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 128(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[17] * B\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 136(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[18] * B\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 144(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[19] * B\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 152(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[20] * B\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[21] * B\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 168(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 176(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[23] * B\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "adcxq	%%r10, %%r8\n\t"
-        "movq	%%r9, 184(%[r])\n\t"
-        "movq	%%r8, 192(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "movq	%[d0], %%rax\n\t"
-        "movq	%[d1], %%rdx\n\t"
-        "divq	%[div]\n\t"
-        "movq	%%rax, %[r]\n\t"
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "rax", "rdx"
-    );
-
-    return r;
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_3072_cmp_24(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-    __asm__ __volatile__ (
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	$-1, %%rdx\n\t"
-        "movq	184(%[a]), %%rbx\n\t"
-        "movq	184(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	176(%[a]), %%rbx\n\t"
-        "movq	176(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	168(%[a]), %%rbx\n\t"
-        "movq	168(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	160(%[a]), %%rbx\n\t"
-        "movq	160(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	152(%[a]), %%rbx\n\t"
-        "movq	152(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	144(%[a]), %%rbx\n\t"
-        "movq	144(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	136(%[a]), %%rbx\n\t"
-        "movq	136(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	128(%[a]), %%rbx\n\t"
-        "movq	128(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	120(%[a]), %%rbx\n\t"
-        "movq	120(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	112(%[a]), %%rbx\n\t"
-        "movq	112(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	104(%[a]), %%rbx\n\t"
-        "movq	104(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	96(%[a]), %%rbx\n\t"
-        "movq	96(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	88(%[a]), %%rbx\n\t"
-        "movq	88(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	80(%[a]), %%rbx\n\t"
-        "movq	80(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	72(%[a]), %%rbx\n\t"
-        "movq	72(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	64(%[a]), %%rbx\n\t"
-        "movq	64(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	56(%[a]), %%rbx\n\t"
-        "movq	56(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	48(%[a]), %%rbx\n\t"
-        "movq	48(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	40(%[a]), %%rbx\n\t"
-        "movq	40(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	32(%[a]), %%rbx\n\t"
-        "movq	32(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	24(%[a]), %%rbx\n\t"
-        "movq	24(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	16(%[a]), %%rbx\n\t"
-        "movq	16(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	8(%[a]), %%rbx\n\t"
-        "movq	8(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	0(%[a]), %%rbx\n\t"
-        "movq	0(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "xorq	%%rdx, %[r]\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "rax", "rdx", "rcx", "rbx", "r8"
-    );
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_24(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[48], t2[25];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[23];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 24);
-    for (i=23; i>=0; i--) {
-        r1 = div_3072_word_24(t1[24 + i], t1[24 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_3072_mul_d_avx2_24(t2, d, r1);
-        else
-#endif
-            sp_3072_mul_d_24(t2, d, r1);
-        t1[24 + i] += sp_3072_sub_in_place_24(&t1[i], t2);
-        t1[24 + i] -= t2[24];
-        sp_3072_mask_24(t2, d, t1[24 + i]);
-        t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2);
-        sp_3072_mask_24(t2, d, t1[24 + i]);
-        t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_24(t1, d) >= 0;
-    sp_3072_cond_sub_24(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_24(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_24(a, m, NULL, r);
-}
-
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][48];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 48;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_24(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 24);
-        if (reduceA) {
-            err = sp_3072_mod_24(t[1] + 24, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_24(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24);
-            err = sp_3072_mod_24(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_24(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_24(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_24(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_24(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_24(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_24(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_24(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_24(t[20], t[10], m, mp);
-        sp_3072_mont_mul_24(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_24(t[22], t[11], m, mp);
-        sp_3072_mont_mul_24(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_24(t[24], t[12], m, mp);
-        sp_3072_mont_mul_24(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_24(t[26], t[13], m, mp);
-        sp_3072_mont_mul_24(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_24(t[28], t[14], m, mp);
-        sp_3072_mont_mul_24(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_24(t[30], t[15], m, mp);
-        sp_3072_mont_mul_24(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-            sp_3072_mont_sqr_24(r, r, m, mp);
-
-            sp_3072_mont_mul_24(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_3072_mont_sqr_24(r, r, m, mp);
-        sp_3072_mont_mul_24(r, r, t[y], m, mp);
-
-        XMEMSET(&r[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_mont_reduce_24(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_24(r, m) >= 0);
-        sp_3072_cond_sub_24(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_avx2_24(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "\nL_mont_loop_avx2_24:\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%r8\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "mulxq	0(%[m]), %%rax, %%r8\n\t"
-        "movq	8(%[a]), %%r12\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r12\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "mulxq	8(%[m]), %%rax, %%r8\n\t"
-        "movq	16(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "mulxq	16(%[m]), %%rax, %%r8\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 16(%[a])\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "mulxq	24(%[m]), %%rax, %%r8\n\t"
-        "movq	32(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "mulxq	32(%[m]), %%rax, %%r8\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 32(%[a])\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "mulxq	40(%[m]), %%rax, %%r8\n\t"
-        "movq	48(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "mulxq	48(%[m]), %%rax, %%r8\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 48(%[a])\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "mulxq	56(%[m]), %%rax, %%r8\n\t"
-        "movq	64(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "mulxq	64(%[m]), %%rax, %%r8\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 64(%[a])\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "mulxq	72(%[m]), %%rax, %%r8\n\t"
-        "movq	80(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "mulxq	80(%[m]), %%rax, %%r8\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 80(%[a])\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "mulxq	88(%[m]), %%rax, %%r8\n\t"
-        "movq	96(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "mulxq	96(%[m]), %%rax, %%r8\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 96(%[a])\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "mulxq	104(%[m]), %%rax, %%r8\n\t"
-        "movq	112(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "mulxq	112(%[m]), %%rax, %%r8\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 112(%[a])\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "mulxq	120(%[m]), %%rax, %%r8\n\t"
-        "movq	128(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "mulxq	128(%[m]), %%rax, %%r8\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 128(%[a])\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "mulxq	136(%[m]), %%rax, %%r8\n\t"
-        "movq	144(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "mulxq	144(%[m]), %%rax, %%r8\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 144(%[a])\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "mulxq	152(%[m]), %%rax, %%r8\n\t"
-        "movq	160(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "mulxq	160(%[m]), %%rax, %%r8\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 160(%[a])\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "mulxq	168(%[m]), %%rax, %%r8\n\t"
-        "movq	176(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "mulxq	176(%[m]), %%rax, %%r8\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 176(%[a])\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "mulxq	184(%[m]), %%rax, %%r8\n\t"
-        "movq	192(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "adcxq	%[ca], %%r10\n\t"
-        "movq	%%r9, %[ca]\n\t"
-        "adoxq	%%r9, %[ca]\n\t"
-        "adcxq	%%r9, %[ca]\n\t"
-        "movq	%%r10, 192(%[a])\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$1, %%rcx\n\t"
-        "cmpq	$24, %%rcx\n\t"
-        "jl	L_mont_loop_avx2_24\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_avx2_24(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_avx2_24(r, a, b);
-    sp_3072_mont_reduce_avx2_24(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_avx2_24(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_avx2_24(r, a);
-    sp_3072_mont_reduce_avx2_24(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_avx2_24(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][48];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 48;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_24(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 24);
-        if (reduceA) {
-            err = sp_3072_mod_24(t[1] + 24, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_24(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24);
-            err = sp_3072_mod_24(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_avx2_24(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_avx2_24(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_avx2_24(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_avx2_24(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_avx2_24(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_avx2_24(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_avx2_24(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_avx2_24(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_avx2_24(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_avx2_24(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[20], t[10], m, mp);
-        sp_3072_mont_mul_avx2_24(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[22], t[11], m, mp);
-        sp_3072_mont_mul_avx2_24(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[24], t[12], m, mp);
-        sp_3072_mont_mul_avx2_24(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[26], t[13], m, mp);
-        sp_3072_mont_mul_avx2_24(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[28], t[14], m, mp);
-        sp_3072_mont_mul_avx2_24(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_avx2_24(t[30], t[15], m, mp);
-        sp_3072_mont_mul_avx2_24(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 24);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-
-            sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_3072_mont_sqr_avx2_24(r, r, m, mp);
-        sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp);
-
-        XMEMSET(&r[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_mont_reduce_avx2_24(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_24(r, m) >= 0);
-        sp_3072_cond_sub_24(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#endif /* !SP_RSA_PRIVATE_EXP_D && WOLFSSL_HAVE_SP_RSA */
-
-/* r = 2^n mod m where n is the number of bits to reduce by.
- * Given m must be 3072 bits, just need to subtract.
- *
- * r  A single precision number.
- * m  A signle precision number.
- */
-static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m)
-{
-    XMEMSET(r, 0, sizeof(sp_digit) * 48);
-
-    /* r = 2^n mod m */
-    sp_3072_sub_in_place_48(r, m);
-}
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit t[48];
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[b]), %%rax\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 0(%[t])\n\t"
-        "movq	%%rcx, 8(%[t])\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 16(%[t])\n\t"
-        "movq	%%rcx, 24(%[t])\n\t"
-        "movq	32(%[b]), %%rax\n\t"
-        "movq	40(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 32(%[t])\n\t"
-        "movq	%%rcx, 40(%[t])\n\t"
-        "movq	48(%[b]), %%rax\n\t"
-        "movq	56(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 48(%[t])\n\t"
-        "movq	%%rcx, 56(%[t])\n\t"
-        "movq	64(%[b]), %%rax\n\t"
-        "movq	72(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 64(%[t])\n\t"
-        "movq	%%rcx, 72(%[t])\n\t"
-        "movq	80(%[b]), %%rax\n\t"
-        "movq	88(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 80(%[t])\n\t"
-        "movq	%%rcx, 88(%[t])\n\t"
-        "movq	96(%[b]), %%rax\n\t"
-        "movq	104(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 96(%[t])\n\t"
-        "movq	%%rcx, 104(%[t])\n\t"
-        "movq	112(%[b]), %%rax\n\t"
-        "movq	120(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 112(%[t])\n\t"
-        "movq	%%rcx, 120(%[t])\n\t"
-        "movq	128(%[b]), %%rax\n\t"
-        "movq	136(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 128(%[t])\n\t"
-        "movq	%%rcx, 136(%[t])\n\t"
-        "movq	144(%[b]), %%rax\n\t"
-        "movq	152(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 144(%[t])\n\t"
-        "movq	%%rcx, 152(%[t])\n\t"
-        "movq	160(%[b]), %%rax\n\t"
-        "movq	168(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 160(%[t])\n\t"
-        "movq	%%rcx, 168(%[t])\n\t"
-        "movq	176(%[b]), %%rax\n\t"
-        "movq	184(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 176(%[t])\n\t"
-        "movq	%%rcx, 184(%[t])\n\t"
-        "movq	192(%[b]), %%rax\n\t"
-        "movq	200(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 192(%[t])\n\t"
-        "movq	%%rcx, 200(%[t])\n\t"
-        "movq	208(%[b]), %%rax\n\t"
-        "movq	216(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 208(%[t])\n\t"
-        "movq	%%rcx, 216(%[t])\n\t"
-        "movq	224(%[b]), %%rax\n\t"
-        "movq	232(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 224(%[t])\n\t"
-        "movq	%%rcx, 232(%[t])\n\t"
-        "movq	240(%[b]), %%rax\n\t"
-        "movq	248(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 240(%[t])\n\t"
-        "movq	%%rcx, 248(%[t])\n\t"
-        "movq	256(%[b]), %%rax\n\t"
-        "movq	264(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 256(%[t])\n\t"
-        "movq	%%rcx, 264(%[t])\n\t"
-        "movq	272(%[b]), %%rax\n\t"
-        "movq	280(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 272(%[t])\n\t"
-        "movq	%%rcx, 280(%[t])\n\t"
-        "movq	288(%[b]), %%rax\n\t"
-        "movq	296(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 288(%[t])\n\t"
-        "movq	%%rcx, 296(%[t])\n\t"
-        "movq	304(%[b]), %%rax\n\t"
-        "movq	312(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 304(%[t])\n\t"
-        "movq	%%rcx, 312(%[t])\n\t"
-        "movq	320(%[b]), %%rax\n\t"
-        "movq	328(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 320(%[t])\n\t"
-        "movq	%%rcx, 328(%[t])\n\t"
-        "movq	336(%[b]), %%rax\n\t"
-        "movq	344(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 336(%[t])\n\t"
-        "movq	%%rcx, 344(%[t])\n\t"
-        "movq	352(%[b]), %%rax\n\t"
-        "movq	360(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 352(%[t])\n\t"
-        "movq	%%rcx, 360(%[t])\n\t"
-        "movq	368(%[b]), %%rax\n\t"
-        "movq	376(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 368(%[t])\n\t"
-        "movq	%%rcx, 376(%[t])\n\t"
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[t]), %%rdx\n\t"
-        "subq	%%rdx,%%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "movq	32(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "movq	40(%[a]), %%rcx\n\t"
-        "movq	40(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 32(%[r])\n\t"
-        "movq	48(%[a]), %%rax\n\t"
-        "movq	48(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 40(%[r])\n\t"
-        "movq	56(%[a]), %%rcx\n\t"
-        "movq	56(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 48(%[r])\n\t"
-        "movq	64(%[a]), %%rax\n\t"
-        "movq	64(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "movq	72(%[a]), %%rcx\n\t"
-        "movq	72(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 64(%[r])\n\t"
-        "movq	80(%[a]), %%rax\n\t"
-        "movq	80(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 72(%[r])\n\t"
-        "movq	88(%[a]), %%rcx\n\t"
-        "movq	88(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 80(%[r])\n\t"
-        "movq	96(%[a]), %%rax\n\t"
-        "movq	96(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 88(%[r])\n\t"
-        "movq	104(%[a]), %%rcx\n\t"
-        "movq	104(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 96(%[r])\n\t"
-        "movq	112(%[a]), %%rax\n\t"
-        "movq	112(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "movq	120(%[a]), %%rcx\n\t"
-        "movq	120(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 112(%[r])\n\t"
-        "movq	128(%[a]), %%rax\n\t"
-        "movq	128(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 120(%[r])\n\t"
-        "movq	136(%[a]), %%rcx\n\t"
-        "movq	136(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 128(%[r])\n\t"
-        "movq	144(%[a]), %%rax\n\t"
-        "movq	144(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 136(%[r])\n\t"
-        "movq	152(%[a]), %%rcx\n\t"
-        "movq	152(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 144(%[r])\n\t"
-        "movq	160(%[a]), %%rax\n\t"
-        "movq	160(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "movq	168(%[a]), %%rcx\n\t"
-        "movq	168(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 160(%[r])\n\t"
-        "movq	176(%[a]), %%rax\n\t"
-        "movq	176(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 168(%[r])\n\t"
-        "movq	184(%[a]), %%rcx\n\t"
-        "movq	184(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 176(%[r])\n\t"
-        "movq	192(%[a]), %%rax\n\t"
-        "movq	192(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 184(%[r])\n\t"
-        "movq	200(%[a]), %%rcx\n\t"
-        "movq	200(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 192(%[r])\n\t"
-        "movq	208(%[a]), %%rax\n\t"
-        "movq	208(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "movq	216(%[a]), %%rcx\n\t"
-        "movq	216(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 208(%[r])\n\t"
-        "movq	224(%[a]), %%rax\n\t"
-        "movq	224(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 216(%[r])\n\t"
-        "movq	232(%[a]), %%rcx\n\t"
-        "movq	232(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 224(%[r])\n\t"
-        "movq	240(%[a]), %%rax\n\t"
-        "movq	240(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 232(%[r])\n\t"
-        "movq	248(%[a]), %%rcx\n\t"
-        "movq	248(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 240(%[r])\n\t"
-        "movq	256(%[a]), %%rax\n\t"
-        "movq	256(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        "movq	264(%[a]), %%rcx\n\t"
-        "movq	264(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 256(%[r])\n\t"
-        "movq	272(%[a]), %%rax\n\t"
-        "movq	272(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 264(%[r])\n\t"
-        "movq	280(%[a]), %%rcx\n\t"
-        "movq	280(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 272(%[r])\n\t"
-        "movq	288(%[a]), %%rax\n\t"
-        "movq	288(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 280(%[r])\n\t"
-        "movq	296(%[a]), %%rcx\n\t"
-        "movq	296(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 288(%[r])\n\t"
-        "movq	304(%[a]), %%rax\n\t"
-        "movq	304(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 296(%[r])\n\t"
-        "movq	312(%[a]), %%rcx\n\t"
-        "movq	312(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 304(%[r])\n\t"
-        "movq	320(%[a]), %%rax\n\t"
-        "movq	320(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 312(%[r])\n\t"
-        "movq	328(%[a]), %%rcx\n\t"
-        "movq	328(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 320(%[r])\n\t"
-        "movq	336(%[a]), %%rax\n\t"
-        "movq	336(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 328(%[r])\n\t"
-        "movq	344(%[a]), %%rcx\n\t"
-        "movq	344(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 336(%[r])\n\t"
-        "movq	352(%[a]), %%rax\n\t"
-        "movq	352(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 344(%[r])\n\t"
-        "movq	360(%[a]), %%rcx\n\t"
-        "movq	360(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 352(%[r])\n\t"
-        "movq	368(%[a]), %%rax\n\t"
-        "movq	368(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 360(%[r])\n\t"
-        "movq	376(%[a]), %%rcx\n\t"
-        "movq	376(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 368(%[r])\n\t"
-        "movq	%%rcx, 376(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "movq	8(%[a]), %%r13\n\t"
-        "\nL_mont_loop_48:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "imulq	%[mp], %%r10\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	0(%[m])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	8(%[m])\n\t"
-        "movq	%%r13, %%r12\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r12\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	16(%[m])\n\t"
-        "movq	16(%[a]), %%r13\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r13\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[m])\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	32(%[m])\n\t"
-        "movq	32(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 32(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	40(%[m])\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	48(%[m])\n\t"
-        "movq	48(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 48(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	56(%[m])\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	64(%[m])\n\t"
-        "movq	64(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 64(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[m])\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	80(%[m])\n\t"
-        "movq	80(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 80(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	88(%[m])\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	96(%[m])\n\t"
-        "movq	96(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 96(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	104(%[m])\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	112(%[m])\n\t"
-        "movq	112(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 112(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[m])\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	128(%[m])\n\t"
-        "movq	128(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 128(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	136(%[m])\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	144(%[m])\n\t"
-        "movq	144(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 144(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	152(%[m])\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	160(%[m])\n\t"
-        "movq	160(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 160(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[m])\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	176(%[m])\n\t"
-        "movq	176(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 176(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	184(%[m])\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	192(%[m])\n\t"
-        "movq	192(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 192(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	200(%[m])\n\t"
-        "movq	200(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 200(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	208(%[m])\n\t"
-        "movq	208(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 208(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	216(%[m])\n\t"
-        "movq	216(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 216(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	224(%[m])\n\t"
-        "movq	224(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 224(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	232(%[m])\n\t"
-        "movq	232(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 232(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	240(%[m])\n\t"
-        "movq	240(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 240(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	248(%[m])\n\t"
-        "movq	248(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 248(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	256(%[m])\n\t"
-        "movq	256(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 256(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	264(%[m])\n\t"
-        "movq	264(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 264(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	272(%[m])\n\t"
-        "movq	272(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 272(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	280(%[m])\n\t"
-        "movq	280(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 280(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	288(%[m])\n\t"
-        "movq	288(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 288(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	296(%[m])\n\t"
-        "movq	296(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 296(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	304(%[m])\n\t"
-        "movq	304(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 304(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	312(%[m])\n\t"
-        "movq	312(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 312(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	320(%[m])\n\t"
-        "movq	320(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 320(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	328(%[m])\n\t"
-        "movq	328(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 328(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	336(%[m])\n\t"
-        "movq	336(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 336(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	344(%[m])\n\t"
-        "movq	344(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 344(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	352(%[m])\n\t"
-        "movq	352(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 352(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	360(%[m])\n\t"
-        "movq	360(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "addq	%%r9,  %%r11\n\t"
-        "movq	%%r11, 360(%[a])\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "mulq	368(%[m])\n\t"
-        "movq	368(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "addq	%%r8,  %%r11\n\t"
-        "movq	%%r11, 368(%[a])\n\t"
-        "adcq	$0, %%r9\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "movq	%%r10, %%rax\n\t"
-        "mulq	376(%[m])\n\t"
-        "movq	376(%[a]), %%r11\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%[ca], %%rdx\n\t"
-        "movq	$0, %[ca]\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "addq	%%r9, %%r11\n\t"
-        "movq	%%r11, 376(%[a])\n\t"
-        "adcq	%%rdx, 384(%[a])\n\t"
-        "adcq	$0, %[ca]\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$8, %%rcx\n\t"
-        "cmpq	$384, %%rcx\n\t"
-        "jl	L_mont_loop_48\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        "movq	%%r13, 8(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13"
-    );
-
-    sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_48(r, a, b);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_48(r, a);
-    sp_3072_mont_reduce_48(r, m, mp);
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	(%[a])\n\t"
-        "movq	%%rax, %%rbx\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[2] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[3] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 24(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	32(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[5] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	40(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 40(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[6] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	48(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 48(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[7] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	56(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[8] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	64(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[9] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	72(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 72(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	80(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 80(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[11] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	88(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 88(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[12] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	96(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 96(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[13] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	104(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 104(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[14] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	112(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[15] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	120(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 120(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	128(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 128(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[17] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	136(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 136(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[18] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	144(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 144(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[19] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	152(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 152(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[20] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	160(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[21] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	168(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 168(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	176(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 176(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[23] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	184(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 184(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[24] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	192(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 192(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[25] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	200(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 200(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[26] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	208(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[27] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	216(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 216(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[28] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	224(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 224(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[29] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	232(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 232(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[30] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	240(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 240(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[31] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	248(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 248(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[32] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	256(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 256(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[33] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	264(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 264(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[34] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	272(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 272(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[35] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	280(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 280(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[36] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	288(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 288(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[37] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	296(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 296(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[38] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	304(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 304(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[39] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	312(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 312(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[40] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	320(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 320(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[41] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	328(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 328(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[42] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	336(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 336(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[43] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	344(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 344(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[44] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	352(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 352(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[45] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	360(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 360(%[r])\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# A[46] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	368(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 368(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[47] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "mulq	376(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "movq	%%r8, 376(%[r])\n\t"
-        "movq	%%rbx, 384(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rdx\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "mulxq	(%[a]), %%r8, %%r9\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "mulxq	8(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[2] * B\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[3] * B\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 24(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[4] * B\n\t"
-        "mulxq	32(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[5] * B\n\t"
-        "mulxq	40(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 40(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[6] * B\n\t"
-        "mulxq	48(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 48(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[7] * B\n\t"
-        "mulxq	56(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 56(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[8] * B\n\t"
-        "mulxq	64(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 64(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[9] * B\n\t"
-        "mulxq	72(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 72(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[10] * B\n\t"
-        "mulxq	80(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 80(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[11] * B\n\t"
-        "mulxq	88(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 88(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[12] * B\n\t"
-        "mulxq	96(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 96(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[13] * B\n\t"
-        "mulxq	104(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 104(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[14] * B\n\t"
-        "mulxq	112(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 112(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[15] * B\n\t"
-        "mulxq	120(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 120(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[16] * B\n\t"
-        "mulxq	128(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 128(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[17] * B\n\t"
-        "mulxq	136(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 136(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[18] * B\n\t"
-        "mulxq	144(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 144(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[19] * B\n\t"
-        "mulxq	152(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 152(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[20] * B\n\t"
-        "mulxq	160(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 160(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[21] * B\n\t"
-        "mulxq	168(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 168(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[22] * B\n\t"
-        "mulxq	176(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 176(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[23] * B\n\t"
-        "mulxq	184(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 184(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[24] * B\n\t"
-        "mulxq	192(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 192(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[25] * B\n\t"
-        "mulxq	200(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 200(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[26] * B\n\t"
-        "mulxq	208(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 208(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[27] * B\n\t"
-        "mulxq	216(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 216(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[28] * B\n\t"
-        "mulxq	224(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 224(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[29] * B\n\t"
-        "mulxq	232(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 232(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[30] * B\n\t"
-        "mulxq	240(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 240(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[31] * B\n\t"
-        "mulxq	248(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 248(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[32] * B\n\t"
-        "mulxq	256(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 256(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[33] * B\n\t"
-        "mulxq	264(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 264(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[34] * B\n\t"
-        "mulxq	272(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 272(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[35] * B\n\t"
-        "mulxq	280(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 280(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[36] * B\n\t"
-        "mulxq	288(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 288(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[37] * B\n\t"
-        "mulxq	296(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 296(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[38] * B\n\t"
-        "mulxq	304(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 304(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[39] * B\n\t"
-        "mulxq	312(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 312(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[40] * B\n\t"
-        "mulxq	320(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 320(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[41] * B\n\t"
-        "mulxq	328(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 328(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[42] * B\n\t"
-        "mulxq	336(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 336(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[43] * B\n\t"
-        "mulxq	344(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 344(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[44] * B\n\t"
-        "mulxq	352(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 352(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[45] * B\n\t"
-        "mulxq	360(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 360(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[46] * B\n\t"
-        "mulxq	368(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 368(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[47] * B\n\t"
-        "mulxq	376(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "adcxq	%%r10, %%r8\n\t"
-        "movq	%%r9, 376(%[r])\n\t"
-        "movq	%%r8, 384(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "movq	%[d0], %%rax\n\t"
-        "movq	%[d1], %%rdx\n\t"
-        "divq	%[div]\n\t"
-        "movq	%%rax, %[r]\n\t"
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "rax", "rdx"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<48; i++)
-        r[i] = a[i] & m;
-#else
-    int i;
-
-    for (i = 0; i < 48; i += 8) {
-        r[i+0] = a[i+0] & m;
-        r[i+1] = a[i+1] & m;
-        r[i+2] = a[i+2] & m;
-        r[i+3] = a[i+3] & m;
-        r[i+4] = a[i+4] & m;
-        r[i+5] = a[i+5] & m;
-        r[i+6] = a[i+6] & m;
-        r[i+7] = a[i+7] & m;
-    }
-#endif
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_3072_cmp_48(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-    __asm__ __volatile__ (
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	$-1, %%rdx\n\t"
-        "movq	376(%[a]), %%rbx\n\t"
-        "movq	376(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	368(%[a]), %%rbx\n\t"
-        "movq	368(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	360(%[a]), %%rbx\n\t"
-        "movq	360(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	352(%[a]), %%rbx\n\t"
-        "movq	352(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	344(%[a]), %%rbx\n\t"
-        "movq	344(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	336(%[a]), %%rbx\n\t"
-        "movq	336(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	328(%[a]), %%rbx\n\t"
-        "movq	328(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	320(%[a]), %%rbx\n\t"
-        "movq	320(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	312(%[a]), %%rbx\n\t"
-        "movq	312(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	304(%[a]), %%rbx\n\t"
-        "movq	304(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	296(%[a]), %%rbx\n\t"
-        "movq	296(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	288(%[a]), %%rbx\n\t"
-        "movq	288(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	280(%[a]), %%rbx\n\t"
-        "movq	280(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	272(%[a]), %%rbx\n\t"
-        "movq	272(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	264(%[a]), %%rbx\n\t"
-        "movq	264(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	256(%[a]), %%rbx\n\t"
-        "movq	256(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	248(%[a]), %%rbx\n\t"
-        "movq	248(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	240(%[a]), %%rbx\n\t"
-        "movq	240(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	232(%[a]), %%rbx\n\t"
-        "movq	232(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	224(%[a]), %%rbx\n\t"
-        "movq	224(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	216(%[a]), %%rbx\n\t"
-        "movq	216(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	208(%[a]), %%rbx\n\t"
-        "movq	208(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	200(%[a]), %%rbx\n\t"
-        "movq	200(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	192(%[a]), %%rbx\n\t"
-        "movq	192(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	184(%[a]), %%rbx\n\t"
-        "movq	184(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	176(%[a]), %%rbx\n\t"
-        "movq	176(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	168(%[a]), %%rbx\n\t"
-        "movq	168(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	160(%[a]), %%rbx\n\t"
-        "movq	160(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	152(%[a]), %%rbx\n\t"
-        "movq	152(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	144(%[a]), %%rbx\n\t"
-        "movq	144(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	136(%[a]), %%rbx\n\t"
-        "movq	136(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	128(%[a]), %%rbx\n\t"
-        "movq	128(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	120(%[a]), %%rbx\n\t"
-        "movq	120(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	112(%[a]), %%rbx\n\t"
-        "movq	112(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	104(%[a]), %%rbx\n\t"
-        "movq	104(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	96(%[a]), %%rbx\n\t"
-        "movq	96(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	88(%[a]), %%rbx\n\t"
-        "movq	88(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	80(%[a]), %%rbx\n\t"
-        "movq	80(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	72(%[a]), %%rbx\n\t"
-        "movq	72(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	64(%[a]), %%rbx\n\t"
-        "movq	64(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	56(%[a]), %%rbx\n\t"
-        "movq	56(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	48(%[a]), %%rbx\n\t"
-        "movq	48(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	40(%[a]), %%rbx\n\t"
-        "movq	40(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	32(%[a]), %%rbx\n\t"
-        "movq	32(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	24(%[a]), %%rbx\n\t"
-        "movq	24(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	16(%[a]), %%rbx\n\t"
-        "movq	16(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	8(%[a]), %%rbx\n\t"
-        "movq	8(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	0(%[a]), %%rbx\n\t"
-        "movq	0(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "xorq	%%rdx, %[r]\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "rax", "rdx", "rcx", "rbx", "r8"
-    );
-
-    return r;
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[96], t2[49];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[47];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
-    for (i=47; i>=0; i--) {
-        r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_3072_mul_d_avx2_48(t2, d, r1);
-        else
-#endif
-            sp_3072_mul_d_48(t2, d, r1);
-        t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
-        t1[48 + i] -= t2[48];
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-        sp_3072_mask_48(t2, d, t1[48 + i]);
-        t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_3072_cmp_48(t1, d) >= 0;
-    sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_48(a, m, NULL, r);
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_div_48_cond(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[96], t2[49];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[47];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 48);
-    for (i=47; i>=0; i--) {
-        r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_3072_mul_d_avx2_48(t2, d, r1);
-        else
-#endif
-            sp_3072_mul_d_48(t2, d, r1);
-        t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2);
-        t1[48 + i] -= t2[48];
-        if (t1[48 + i] != 0) {
-            t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d);
-            if (t1[48 + i] != 0)
-                t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d);
-        }
-    }
-
-    r1 = sp_3072_cmp_48(t1, d) >= 0;
-    sp_3072_cond_sub_48(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_3072_div_48_cond(a, m, NULL, r);
-}
-
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][96];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_48(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_48(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_48(t[20], t[10], m, mp);
-        sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_48(t[22], t[11], m, mp);
-        sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_48(t[24], t[12], m, mp);
-        sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_48(t[26], t[13], m, mp);
-        sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_48(t[28], t[14], m, mp);
-        sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_48(t[30], t[15], m, mp);
-        sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-            sp_3072_mont_sqr_48(r, r, m, mp);
-
-            sp_3072_mont_mul_48(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_3072_mont_sqr_48(r, r, m, mp);
-        sp_3072_mont_mul_48(r, r, t[y], m, mp);
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef HAVE_INTEL_AVX2
-/* Reduce the number back to 3072 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_3072_mont_reduce_avx2_48(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_digit ca = 0;
-
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "movq	0(%[a]), %%r12\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "\nL_mont_loop_avx2_48:\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%r12, %%r10\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	%%r12, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%r8\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "mulxq	0(%[m]), %%rax, %%r8\n\t"
-        "movq	8(%[a]), %%r12\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r12\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "mulxq	8(%[m]), %%rax, %%r8\n\t"
-        "movq	16(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r12\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "mulxq	16(%[m]), %%rax, %%r8\n\t"
-        "movq	24(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 16(%[a])\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "mulxq	24(%[m]), %%rax, %%r8\n\t"
-        "movq	32(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 24(%[a])\n\t"
-        "# a[i+4] += m[4] * mu\n\t"
-        "mulxq	32(%[m]), %%rax, %%r8\n\t"
-        "movq	40(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 32(%[a])\n\t"
-        "# a[i+5] += m[5] * mu\n\t"
-        "mulxq	40(%[m]), %%rax, %%r8\n\t"
-        "movq	48(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 40(%[a])\n\t"
-        "# a[i+6] += m[6] * mu\n\t"
-        "mulxq	48(%[m]), %%rax, %%r8\n\t"
-        "movq	56(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 48(%[a])\n\t"
-        "# a[i+7] += m[7] * mu\n\t"
-        "mulxq	56(%[m]), %%rax, %%r8\n\t"
-        "movq	64(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 56(%[a])\n\t"
-        "# a[i+8] += m[8] * mu\n\t"
-        "mulxq	64(%[m]), %%rax, %%r8\n\t"
-        "movq	72(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 64(%[a])\n\t"
-        "# a[i+9] += m[9] * mu\n\t"
-        "mulxq	72(%[m]), %%rax, %%r8\n\t"
-        "movq	80(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 72(%[a])\n\t"
-        "# a[i+10] += m[10] * mu\n\t"
-        "mulxq	80(%[m]), %%rax, %%r8\n\t"
-        "movq	88(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 80(%[a])\n\t"
-        "# a[i+11] += m[11] * mu\n\t"
-        "mulxq	88(%[m]), %%rax, %%r8\n\t"
-        "movq	96(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 88(%[a])\n\t"
-        "# a[i+12] += m[12] * mu\n\t"
-        "mulxq	96(%[m]), %%rax, %%r8\n\t"
-        "movq	104(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 96(%[a])\n\t"
-        "# a[i+13] += m[13] * mu\n\t"
-        "mulxq	104(%[m]), %%rax, %%r8\n\t"
-        "movq	112(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 104(%[a])\n\t"
-        "# a[i+14] += m[14] * mu\n\t"
-        "mulxq	112(%[m]), %%rax, %%r8\n\t"
-        "movq	120(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 112(%[a])\n\t"
-        "# a[i+15] += m[15] * mu\n\t"
-        "mulxq	120(%[m]), %%rax, %%r8\n\t"
-        "movq	128(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 120(%[a])\n\t"
-        "# a[i+16] += m[16] * mu\n\t"
-        "mulxq	128(%[m]), %%rax, %%r8\n\t"
-        "movq	136(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 128(%[a])\n\t"
-        "# a[i+17] += m[17] * mu\n\t"
-        "mulxq	136(%[m]), %%rax, %%r8\n\t"
-        "movq	144(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 136(%[a])\n\t"
-        "# a[i+18] += m[18] * mu\n\t"
-        "mulxq	144(%[m]), %%rax, %%r8\n\t"
-        "movq	152(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 144(%[a])\n\t"
-        "# a[i+19] += m[19] * mu\n\t"
-        "mulxq	152(%[m]), %%rax, %%r8\n\t"
-        "movq	160(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 152(%[a])\n\t"
-        "# a[i+20] += m[20] * mu\n\t"
-        "mulxq	160(%[m]), %%rax, %%r8\n\t"
-        "movq	168(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 160(%[a])\n\t"
-        "# a[i+21] += m[21] * mu\n\t"
-        "mulxq	168(%[m]), %%rax, %%r8\n\t"
-        "movq	176(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 168(%[a])\n\t"
-        "# a[i+22] += m[22] * mu\n\t"
-        "mulxq	176(%[m]), %%rax, %%r8\n\t"
-        "movq	184(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 176(%[a])\n\t"
-        "# a[i+23] += m[23] * mu\n\t"
-        "mulxq	184(%[m]), %%rax, %%r8\n\t"
-        "movq	192(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 184(%[a])\n\t"
-        "# a[i+24] += m[24] * mu\n\t"
-        "mulxq	192(%[m]), %%rax, %%r8\n\t"
-        "movq	200(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 192(%[a])\n\t"
-        "# a[i+25] += m[25] * mu\n\t"
-        "mulxq	200(%[m]), %%rax, %%r8\n\t"
-        "movq	208(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 200(%[a])\n\t"
-        "# a[i+26] += m[26] * mu\n\t"
-        "mulxq	208(%[m]), %%rax, %%r8\n\t"
-        "movq	216(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 208(%[a])\n\t"
-        "# a[i+27] += m[27] * mu\n\t"
-        "mulxq	216(%[m]), %%rax, %%r8\n\t"
-        "movq	224(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 216(%[a])\n\t"
-        "# a[i+28] += m[28] * mu\n\t"
-        "mulxq	224(%[m]), %%rax, %%r8\n\t"
-        "movq	232(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 224(%[a])\n\t"
-        "# a[i+29] += m[29] * mu\n\t"
-        "mulxq	232(%[m]), %%rax, %%r8\n\t"
-        "movq	240(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 232(%[a])\n\t"
-        "# a[i+30] += m[30] * mu\n\t"
-        "mulxq	240(%[m]), %%rax, %%r8\n\t"
-        "movq	248(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 240(%[a])\n\t"
-        "# a[i+31] += m[31] * mu\n\t"
-        "mulxq	248(%[m]), %%rax, %%r8\n\t"
-        "movq	256(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 248(%[a])\n\t"
-        "# a[i+32] += m[32] * mu\n\t"
-        "mulxq	256(%[m]), %%rax, %%r8\n\t"
-        "movq	264(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 256(%[a])\n\t"
-        "# a[i+33] += m[33] * mu\n\t"
-        "mulxq	264(%[m]), %%rax, %%r8\n\t"
-        "movq	272(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 264(%[a])\n\t"
-        "# a[i+34] += m[34] * mu\n\t"
-        "mulxq	272(%[m]), %%rax, %%r8\n\t"
-        "movq	280(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 272(%[a])\n\t"
-        "# a[i+35] += m[35] * mu\n\t"
-        "mulxq	280(%[m]), %%rax, %%r8\n\t"
-        "movq	288(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 280(%[a])\n\t"
-        "# a[i+36] += m[36] * mu\n\t"
-        "mulxq	288(%[m]), %%rax, %%r8\n\t"
-        "movq	296(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 288(%[a])\n\t"
-        "# a[i+37] += m[37] * mu\n\t"
-        "mulxq	296(%[m]), %%rax, %%r8\n\t"
-        "movq	304(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 296(%[a])\n\t"
-        "# a[i+38] += m[38] * mu\n\t"
-        "mulxq	304(%[m]), %%rax, %%r8\n\t"
-        "movq	312(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 304(%[a])\n\t"
-        "# a[i+39] += m[39] * mu\n\t"
-        "mulxq	312(%[m]), %%rax, %%r8\n\t"
-        "movq	320(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 312(%[a])\n\t"
-        "# a[i+40] += m[40] * mu\n\t"
-        "mulxq	320(%[m]), %%rax, %%r8\n\t"
-        "movq	328(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 320(%[a])\n\t"
-        "# a[i+41] += m[41] * mu\n\t"
-        "mulxq	328(%[m]), %%rax, %%r8\n\t"
-        "movq	336(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 328(%[a])\n\t"
-        "# a[i+42] += m[42] * mu\n\t"
-        "mulxq	336(%[m]), %%rax, %%r8\n\t"
-        "movq	344(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 336(%[a])\n\t"
-        "# a[i+43] += m[43] * mu\n\t"
-        "mulxq	344(%[m]), %%rax, %%r8\n\t"
-        "movq	352(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 344(%[a])\n\t"
-        "# a[i+44] += m[44] * mu\n\t"
-        "mulxq	352(%[m]), %%rax, %%r8\n\t"
-        "movq	360(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 352(%[a])\n\t"
-        "# a[i+45] += m[45] * mu\n\t"
-        "mulxq	360(%[m]), %%rax, %%r8\n\t"
-        "movq	368(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 360(%[a])\n\t"
-        "# a[i+46] += m[46] * mu\n\t"
-        "mulxq	368(%[m]), %%rax, %%r8\n\t"
-        "movq	376(%[a]), %%r11\n\t"
-        "adcxq	%%rax, %%r10\n\t"
-        "adoxq	%%r8, %%r11\n\t"
-        "movq	%%r10, 368(%[a])\n\t"
-        "# a[i+47] += m[47] * mu\n\t"
-        "mulxq	376(%[m]), %%rax, %%r8\n\t"
-        "movq	384(%[a]), %%r10\n\t"
-        "adcxq	%%rax, %%r11\n\t"
-        "adoxq	%%r8, %%r10\n\t"
-        "movq	%%r11, 376(%[a])\n\t"
-        "adcxq	%[ca], %%r10\n\t"
-        "movq	%%r9, %[ca]\n\t"
-        "adoxq	%%r9, %[ca]\n\t"
-        "adcxq	%%r9, %[ca]\n\t"
-        "movq	%%r10, 384(%[a])\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %[a]\n\t"
-        "addq	$1, %%rcx\n\t"
-        "cmpq	$48, %%rcx\n\t"
-        "jl	L_mont_loop_avx2_48\n\t"
-        "movq	%%r12, 0(%[a])\n\t"
-        : [ca] "+r" (ca), [a] "+r" (a)
-        : [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca);
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_mul_avx2_48(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    sp_3072_mul_avx2_48(r, a, b);
-    sp_3072_mont_reduce_avx2_48(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#ifdef HAVE_INTEL_AVX2
-/* Square the Montgomery form number. (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_3072_mont_sqr_avx2_48(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    sp_3072_sqr_avx2_48(r, a);
-    sp_3072_mont_reduce_avx2_48(r, m, mp);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#if defined(SP_RSA_PRIVATE_EXP_D) || defined(WOLFSSL_HAVE_SP_DH)
-#ifdef HAVE_INTEL_AVX2
-/* Modular exponentiate a to the e mod m. (r = a^e mod m)
- *
- * r     A single precision number that is the result of the operation.
- * a     A single precision number being exponentiated.
- * e     A single precision number that is the exponent.
- * bits  The number of bits in the exponent.
- * m     A single precision number that is the modulus.
- * returns 0 on success and MEMORY_E on dynamic memory allocation failure.
- */
-static int sp_3072_mod_exp_avx2_48(sp_digit* r, sp_digit* a, sp_digit* e,
-        int bits, sp_digit* m, int reduceA)
-{
-#ifndef WOLFSSL_SMALL_STACK
-    sp_digit t[32][96];
-#else
-    sp_digit* t[32];
-    sp_digit* td;
-#endif
-    sp_digit* norm;
-    sp_digit mp = 1;
-    sp_digit n;
-    sp_digit mask;
-    int i;
-    int c, y;
-    int err = MP_OKAY;
-
-#ifdef WOLFSSL_SMALL_STACK
-    td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL,
-                            DYNAMIC_TYPE_TMP_BUFFER);
-    if (td == NULL)
-        err = MEMORY_E;
-
-    if (err == MP_OKAY) {
-        for (i=0; i<32; i++)
-            t[i] = td + i * 96;
-        norm = t[0];
-    }
-#else
-    norm = t[0];
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_setup(m, &mp);
-        sp_3072_mont_norm_48(norm, m);
-
-        XMEMSET(t[1], 0, sizeof(sp_digit) * 48);
-        if (reduceA) {
-            err = sp_3072_mod_48(t[1] + 48, a, m);
-            if (err == MP_OKAY)
-                err = sp_3072_mod_48(t[1], t[1], m);
-        }
-        else {
-            XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48(t[1], t[1], m);
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_mont_sqr_avx2_48(t[ 2], t[ 1], m, mp);
-        sp_3072_mont_mul_avx2_48(t[ 3], t[ 2], t[ 1], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[ 4], t[ 2], m, mp);
-        sp_3072_mont_mul_avx2_48(t[ 5], t[ 3], t[ 2], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[ 6], t[ 3], m, mp);
-        sp_3072_mont_mul_avx2_48(t[ 7], t[ 4], t[ 3], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[ 8], t[ 4], m, mp);
-        sp_3072_mont_mul_avx2_48(t[ 9], t[ 5], t[ 4], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[10], t[ 5], m, mp);
-        sp_3072_mont_mul_avx2_48(t[11], t[ 6], t[ 5], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[12], t[ 6], m, mp);
-        sp_3072_mont_mul_avx2_48(t[13], t[ 7], t[ 6], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[14], t[ 7], m, mp);
-        sp_3072_mont_mul_avx2_48(t[15], t[ 8], t[ 7], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[16], t[ 8], m, mp);
-        sp_3072_mont_mul_avx2_48(t[17], t[ 9], t[ 8], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[18], t[ 9], m, mp);
-        sp_3072_mont_mul_avx2_48(t[19], t[10], t[ 9], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[20], t[10], m, mp);
-        sp_3072_mont_mul_avx2_48(t[21], t[11], t[10], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[22], t[11], m, mp);
-        sp_3072_mont_mul_avx2_48(t[23], t[12], t[11], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[24], t[12], m, mp);
-        sp_3072_mont_mul_avx2_48(t[25], t[13], t[12], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[26], t[13], m, mp);
-        sp_3072_mont_mul_avx2_48(t[27], t[14], t[13], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[28], t[14], m, mp);
-        sp_3072_mont_mul_avx2_48(t[29], t[15], t[14], m, mp);
-        sp_3072_mont_sqr_avx2_48(t[30], t[15], m, mp);
-        sp_3072_mont_mul_avx2_48(t[31], t[16], t[15], m, mp);
-
-        i = (bits - 1) / 64;
-        n = e[i--];
-        y = n >> 59;
-        n <<= 5;
-        c = 59;
-        XMEMCPY(r, t[y], sizeof(sp_digit) * 48);
-        for (; i>=0 || c>=5; ) {
-            if (c == 0) {
-                n = e[i--];
-                y = n >> 59;
-                n <<= 5;
-                c = 59;
-            }
-            else if (c < 5) {
-                y = n >> 59;
-                n = e[i--];
-                c = 5 - c;
-                y |= n >> (64 - c);
-                n <<= c;
-                c = 64 - c;
-            }
-            else {
-                y = (n >> 59) & 0x1f;
-                n <<= 5;
-                c -= 5;
-            }
-
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-
-            sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp);
-        }
-        y = e[0] & ((1 << c) - 1);
-        for (; c > 0; c--)
-            sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-        sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp);
-
-        XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-        sp_3072_mont_reduce_avx2_48(r, m, mp);
-
-        mask = 0 - (sp_3072_cmp_48(r, m) >= 0);
-        sp_3072_cond_sub_48(r, r, m, mask);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    if (td != NULL)
-        XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-/* RSA public key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * em      Public exponent.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[96], md[48], rd[96];
-#else
-    sp_digit* d = NULL;
-#endif
-    sp_digit* a;
-    sp_digit *ah;
-    sp_digit* m;
-    sp_digit* r;
-    sp_digit e[1];
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 384 ||
-                                                     mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (d == NULL)
-            err = MEMORY_E;
-    }
-
-    if (err == MP_OKAY) {
-        a = d;
-        r = a + 48 * 2;
-        m = r + 48 * 2;
-        ah = a + 48;
-    }
-#else
-    a = ad;
-    m = md;
-    r = rd;
-    ah = a + 48;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(ah, 48, in, inLen);
-#if DIGIT_BIT >= 64
-        e[0] = em->dp[0];
-#else
-        e[0] = em->dp[0];
-        if (em->used > 1)
-            e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
-#endif
-        if (e[0] == 0)
-            err = MP_EXPTMOD_E;
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(m, 48, mm);
-
-        if (e[0] == 0x3) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-                if (err == MP_OKAY) {
-                    sp_3072_sqr_avx2_48(r, ah);
-                    err = sp_3072_mod_48_cond(r, r, m);
-                }
-                if (err == MP_OKAY) {
-                    sp_3072_mul_avx2_48(r, ah, r);
-                    err = sp_3072_mod_48_cond(r, r, m);
-                }
-            }
-            else
-#endif
-            {
-                if (err == MP_OKAY) {
-                    sp_3072_sqr_48(r, ah);
-                    err = sp_3072_mod_48_cond(r, r, m);
-                }
-                if (err == MP_OKAY) {
-                    sp_3072_mul_48(r, ah, r);
-                    err = sp_3072_mod_48_cond(r, r, m);
-                }
-            }
-        }
-        else {
-            int i;
-            sp_digit mp;
-
-            sp_3072_mont_setup(m, &mp);
-
-            /* Convert to Montgomery form. */
-            XMEMSET(a, 0, sizeof(sp_digit) * 48);
-            err = sp_3072_mod_48_cond(a, a, m);
-
-            if (err == MP_OKAY) {
-                for (i=63; i>=0; i--)
-                    if (e[0] >> i)
-                        break;
-
-                XMEMCPY(r, a, sizeof(sp_digit) * 48);
-#ifdef HAVE_INTEL_AVX2
-                if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-                    for (i--; i>=0; i--) {
-                        sp_3072_mont_sqr_avx2_48(r, r, m, mp);
-                        if (((e[0] >> i) & 1) == 1)
-                            sp_3072_mont_mul_avx2_48(r, r, a, m, mp);
-                    }
-                    XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-                    sp_3072_mont_reduce_avx2_48(r, m, mp);
-                }
-                else
-#endif
-                {
-                    for (i--; i>=0; i--) {
-                        sp_3072_mont_sqr_48(r, r, m, mp);
-                        if (((e[0] >> i) & 1) == 1)
-                            sp_3072_mont_mul_48(r, r, a, m, mp);
-                    }
-                    XMEMSET(&r[48], 0, sizeof(sp_digit) * 48);
-                    sp_3072_mont_reduce_48(r, m, mp);
-                }
-
-                for (i = 47; i > 0; i--) {
-                    if (r[i] != m[i])
-                        break;
-                }
-                if (r[i] >= m[i])
-                    sp_3072_sub_in_place_48(r, m);
-            }
-        }
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return err;
-}
-
-/* RSA private key operation.
- *
- * in      Array of bytes representing the number to exponentiate, base.
- * inLen   Number of bytes in base.
- * dm      Private exponent.
- * pm      First prime.
- * qm      Second prime.
- * dpm     First prime's CRT exponent.
- * dqm     Second prime's CRT exponent.
- * qim     Inverse of second prime mod p.
- * mm      Modulus.
- * out     Buffer to hold big-endian bytes of exponentiation result.
- *         Must be at least 384 bytes long.
- * outLen  Number of bytes in result.
- * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
- * an array is too long and MEMORY_E when dynamic memory allocation fails.
- */
-int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm,
-    mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm,
-    byte* out, word32* outLen)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit ad[48 * 2];
-    sp_digit pd[24], qd[24], dpd[24];
-    sp_digit tmpad[48], tmpbd[48];
-#else
-    sp_digit* t = NULL;
-#endif
-    sp_digit* a;
-    sp_digit* p;
-    sp_digit* q;
-    sp_digit* dp;
-    sp_digit* dq;
-    sp_digit* qi;
-    sp_digit* tmp;
-    sp_digit* tmpa;
-    sp_digit* tmpb;
-    sp_digit* r;
-    sp_digit c;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)dm;
-    (void)mm;
-
-    if (*outLen < 384)
-        err = MP_TO_E;
-    if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072))
-        err = MP_READ_E;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL,
-                               DYNAMIC_TYPE_TMP_BUFFER);
-        if (t == NULL)
-            err = MEMORY_E;
-    }
-    if (err == MP_OKAY) {
-        a = t;
-        p = a + 48 * 2;
-        q = p + 24;
-        qi = dq = dp = q + 24;
-        tmpa = qi + 24;
-        tmpb = tmpa + 48;
-
-        tmp = t;
-        r = tmp + 48;
-    }
-#else
-    r = a = ad;
-    p = pd;
-    q = qd;
-    qi = dq = dp = dpd;
-    tmpa = tmpad;
-    tmpb = tmpbd;
-    tmp = a + 48;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_3072_from_bin(a, 48, in, inLen);
-        sp_3072_from_mp(p, 24, pm);
-        sp_3072_from_mp(q, 24, qm);
-        sp_3072_from_mp(dp, 24, dpm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_3072_mod_exp_avx2_24(tmpa, a, dp, 1536, p, 1);
-        else
-#endif
-            err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1);
-    }
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(dq, 24, dqm);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_3072_mod_exp_avx2_24(tmpb, a, dq, 1536, q, 1);
-       else
-#endif
-            err = sp_3072_mod_exp_24(tmpb, a, dq, 1536, q, 1);
-    }
-
-    if (err == MP_OKAY) {
-        c = sp_3072_sub_in_place_24(tmpa, tmpb);
-        sp_3072_mask_24(tmp, p, c);
-        sp_3072_add_24(tmpa, tmpa, tmp);
-
-        sp_3072_from_mp(qi, 24, qim);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_3072_mul_avx2_24(tmpa, tmpa, qi);
-        else
-#endif
-            sp_3072_mul_24(tmpa, tmpa, qi);
-        err = sp_3072_mod_24(tmpa, tmpa, p);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_3072_mul_avx2_24(tmpa, q, tmpa);
-        else
-#endif
-            sp_3072_mul_24(tmpa, q, tmpa);
-        XMEMSET(&tmpb[24], 0, sizeof(sp_digit) * 24);
-        sp_3072_add_48(r, tmpb, tmpa);
-
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11);
-        XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    }
-#else
-    XMEMSET(tmpad, 0, sizeof(tmpad));
-    XMEMSET(tmpbd, 0, sizeof(tmpbd));
-    XMEMSET(pd, 0, sizeof(pd));
-    XMEMSET(qd, 0, sizeof(qd));
-    XMEMSET(dpd, 0, sizeof(dpd));
-#endif
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_RSA */
-#ifdef WOLFSSL_HAVE_SP_DH
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_3072_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 48);
-        r->used = 48;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 48; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 48; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base  Base. MP integer.
- * exp   Exponent. MP integer.
- * mod   Modulus. MP integer.
- * res   Result. MP integer.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res)
-{
-    int err = MP_OKAY;
-    sp_digit b[96], e[48], m[48];
-    sp_digit* r = b;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-    int expBits = mp_count_bits(exp);
-
-    if (mp_count_bits(base) > 3072 || expBits > 3072 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 48, base);
-        sp_3072_from_mp(e, 48, exp);
-        sp_3072_from_mp(m, 48, mod);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_3072_mod_exp_avx2_48(r, b, e, expBits, m, 0);
-        else
-#endif
-            err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        err = sp_3072_to_mp(r, res);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-
-/* Perform the modular exponentiation for Diffie-Hellman.
- *
- * base     Base.
- * exp      Array of bytes that is the exponent.
- * expLen   Length of data, in bytes, in exponent.
- * mod      Modulus.
- * out      Buffer to hold big-endian bytes of exponentiation result.
- *          Must be at least 384 bytes long.
- * outLen   Length, in bytes, of exponentiation result.
- * returs 0 on success, MP_READ_E if there are too many bytes in an array
- * and MEMORY_E if memory allocation fails.
- */
-int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen)
-{
-    int err = MP_OKAY;
-    sp_digit b[96], e[48], m[48];
-    sp_digit* r = b;
-    word32 i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (mp_count_bits(base) > 3072 || expLen > 384 ||
-                                                   mp_count_bits(mod) != 3072) {
-        err = MP_READ_E;
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_from_mp(b, 48, base);
-        sp_3072_from_bin(e, 48, exp, expLen);
-        sp_3072_from_mp(m, 48, mod);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_3072_mod_exp_avx2_48(r, b, e, expLen * 8, m, 0);
-        else
-#endif
-            err = sp_3072_mod_exp_48(r, b, e, expLen * 8, m, 0);
-    }
-
-    if (err == MP_OKAY) {
-        sp_3072_to_bin(r, out);
-        *outLen = 384;
-        for (i=0; i<384 && out[i] == 0; i++) {
-        }
-        *outLen -= i;
-        XMEMMOVE(out, out + i, *outLen);
-    }
-
-    XMEMSET(e, 0, sizeof(e));
-
-    return err;
-}
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#endif /* WOLFSSL_SP_NO_3072 */
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */
-#ifdef WOLFSSL_HAVE_SP_ECC
-#ifndef WOLFSSL_SP_NO_256
-
-/* Point structure to use. */
-typedef struct sp_point {
-    sp_digit x[2 * 4];
-    sp_digit y[2 * 4];
-    sp_digit z[2 * 4];
-    int infinity;
-} sp_point;
-
-/* The modulus (prime) of the curve P256. */
-static sp_digit p256_mod[4] = {
-    0xffffffffffffffffl,0x00000000ffffffffl,0x0000000000000000l,
-    0xffffffff00000001l
-};
-/* The Montogmery normalizer for modulus of the curve P256. */
-static sp_digit p256_norm_mod[4] = {
-    0x0000000000000001l,0xffffffff00000000l,0xffffffffffffffffl,
-    0x00000000fffffffel
-};
-/* The Montogmery multiplier for modulus of the curve P256. */
-static sp_digit p256_mp_mod = 0x0000000000000001;
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
-                                            defined(HAVE_ECC_VERIFY)
-/* The order of the curve P256. */
-static sp_digit p256_order[4] = {
-    0xf3b9cac2fc632551l,0xbce6faada7179e84l,0xffffffffffffffffl,
-    0xffffffff00000000l
-};
-#endif
-/* The order of the curve P256 minus 2. */
-static sp_digit p256_order2[4] = {
-    0xf3b9cac2fc63254fl,0xbce6faada7179e84l,0xffffffffffffffffl,
-    0xffffffff00000000l
-};
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery normalizer for order of the curve P256. */
-static sp_digit p256_norm_order[4] = {
-    0x0c46353d039cdaafl,0x4319055258e8617bl,0x0000000000000000l,
-    0x00000000ffffffffl
-};
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* The Montogmery multiplier for order of the curve P256. */
-static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl;
-#endif
-#ifdef WOLFSSL_SP_SMALL
-/* The base point of curve P256. */
-static sp_point p256_base = {
-    /* X ordinate */
-    {
-        0xf4a13945d898c296l,0x77037d812deb33a0l,0xf8bce6e563a440f2l,
-        0x6b17d1f2e12c4247l
-    },
-    /* Y ordinate */
-    {
-        0xcbb6406837bf51f5l,0x2bce33576b315ecel,0x8ee7eb4a7c0f9e16l,
-        0x4fe342e2fe1a7f9bl
-    },
-    /* Z ordinate */
-    {
-        0x0000000000000001l,0x0000000000000000l,0x0000000000000000l,
-        0x0000000000000000l
-    },
-    /* infinity */
-    0
-};
-#endif /* WOLFSSL_SP_SMALL */
-#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
-static sp_digit p256_b[4] = {
-    0x3bce3c3e27d2604bl,0x651d06b0cc53b0f6l,0xb3ebbd55769886bcl,
-    0x5ac635d8aa3a93e7l
-};
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* Allocate memory for point and return error. */
-#define sp_ecc_point_new(heap, sp, p)                                   \
-    ((p = XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) == NULL) ? \
-        MEMORY_E : MP_OKAY
-#else
-/* Set pointer to data and return no error. */
-#define sp_ecc_point_new(heap, sp, p)   ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-/* If valid pointer then clear point data if requested and free data. */
-#define sp_ecc_point_free(p, clear, heap)     \
-    do {                                      \
-        if (p != NULL) {                      \
-            if (clear)                        \
-                XMEMSET(p, 0, sizeof(*p));    \
-            XFREE(p, heap, DYNAMIC_TYPE_ECC); \
-        }                                     \
-    }                                         \
-    while (0)
-#else
-/* Clear point data if requested. */
-#define sp_ecc_point_free(p, clear, heap) \
-    do {                                  \
-        if (clear)                        \
-            XMEMSET(p, 0, sizeof(*p));    \
-    }                                     \
-    while (0)
-#endif
-
-/* Multiply a number by Montogmery normalizer mod modulus (prime).
- *
- * r  The resulting Montgomery form number.
- * a  The number to convert.
- * m  The modulus (prime).
- */
-static int sp_256_mod_mul_norm_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    int64_t t[8];
-    int64_t a32[8];
-    int64_t o;
-
-    (void)m;
-
-    a32[0] = a[0] & 0xffffffff;
-    a32[1] = a[0] >> 32;
-    a32[2] = a[1] & 0xffffffff;
-    a32[3] = a[1] >> 32;
-    a32[4] = a[2] & 0xffffffff;
-    a32[5] = a[2] >> 32;
-    a32[6] = a[3] & 0xffffffff;
-    a32[7] = a[3] >> 32;
-
-    /*  1  1  0 -1 -1 -1 -1  0 */
-    t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
-    /*  0  1  1  0 -1 -1 -1 -1 */
-    t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
-    /*  0  0  1  1  0 -1 -1 -1 */
-    t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
-    /* -1 -1  0  2  2  1  0 -1 */
-    t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
-    /*  0 -1 -1  0  2  2  1  0 */
-    t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
-    /*  0  0 -1 -1  0  2  2  1 */
-    t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
-    /* -1 -1  0  0  0  1  3  2 */
-    t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
-    /*  1  0 -1 -1 -1 -1  0  3 */
-    t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
-
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    o     = t[7] >> 32; t[7] &= 0xffffffff;
-    t[0] += o;
-    t[3] -= o;
-    t[6] -= o;
-    t[7] += o;
-    t[1] += t[0] >> 32; t[0] &= 0xffffffff;
-    t[2] += t[1] >> 32; t[1] &= 0xffffffff;
-    t[3] += t[2] >> 32; t[2] &= 0xffffffff;
-    t[4] += t[3] >> 32; t[3] &= 0xffffffff;
-    t[5] += t[4] >> 32; t[4] &= 0xffffffff;
-    t[6] += t[5] >> 32; t[5] &= 0xffffffff;
-    t[7] += t[6] >> 32; t[6] &= 0xffffffff;
-    r[0] = (t[1] << 32) | t[0];
-    r[1] = (t[3] << 32) | t[2];
-    r[2] = (t[5] << 32) | t[4];
-    r[3] = (t[7] << 32) | t[6];
-
-    return MP_OKAY;
-}
-
-/* Convert an mp_int to an array of sp_digit.
- *
- * r  A single precision integer.
- * a  A multi-precision integer.
- */
-static void sp_256_from_mp(sp_digit* r, int max, mp_int* a)
-{
-#if DIGIT_BIT == 64
-    int j;
-
-    XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
-
-    for (j = a->used; j < max; j++)
-        r[j] = 0;
-#elif DIGIT_BIT > 64
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= a->dp[i] << s;
-        r[j] &= 0xffffffffffffffffl;
-        s = 64 - s;
-        if (j + 1 >= max)
-            break;
-        r[++j] = a->dp[i] >> s;
-        while (s + 64 <= DIGIT_BIT) {
-            s += 64;
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            if (s < DIGIT_BIT)
-                r[++j] = a->dp[i] >> s;
-            else
-                r[++j] = 0;
-        }
-        s = DIGIT_BIT - s;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#else
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = 0; i < a->used && j < max; i++) {
-        r[j] |= ((sp_digit)a->dp[i]) << s;
-        if (s + DIGIT_BIT >= 64) {
-            r[j] &= 0xffffffffffffffffl;
-            if (j + 1 >= max)
-                break;
-            s = 64 - s;
-            if (s == DIGIT_BIT) {
-                r[++j] = 0;
-                s = 0;
-            }
-            else {
-                r[++j] = a->dp[i] >> s;
-                s = DIGIT_BIT - s;
-            }
-        }
-        else
-            s += DIGIT_BIT;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-#endif
-}
-
-/* Convert a point of type ecc_point to type sp_point.
- *
- * p   Point of type sp_point (result).
- * pm  Point of type ecc_point.
- */
-static void sp_256_point_from_ecc_point_4(sp_point* p, ecc_point* pm)
-{
-    XMEMSET(p->x, 0, sizeof(p->x));
-    XMEMSET(p->y, 0, sizeof(p->y));
-    XMEMSET(p->z, 0, sizeof(p->z));
-    sp_256_from_mp(p->x, 4, pm->x);
-    sp_256_from_mp(p->y, 4, pm->y);
-    sp_256_from_mp(p->z, 4, pm->z);
-    p->infinity = 0;
-}
-
-/* Convert an array of sp_digit to an mp_int.
- *
- * a  A single precision integer.
- * r  A multi-precision integer.
- */
-static int sp_256_to_mp(sp_digit* a, mp_int* r)
-{
-    int err;
-
-    err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
-    if (err == MP_OKAY) {
-#if DIGIT_BIT == 64
-        XMEMCPY(r->dp, a, sizeof(sp_digit) * 4);
-        r->used = 4;
-        mp_clamp(r);
-#elif DIGIT_BIT < 64
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 4; i++) {
-            r->dp[j] |= a[i] << s;
-            r->dp[j] &= (1l << DIGIT_BIT) - 1;
-            s = DIGIT_BIT - s;
-            r->dp[++j] = a[i] >> s;
-            while (s + DIGIT_BIT <= 64) {
-                s += DIGIT_BIT;
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-                r->dp[++j] = a[i] >> s;
-            }
-            s = 64 - s;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#else
-        int i, j = 0, s = 0;
-
-        r->dp[0] = 0;
-        for (i = 0; i < 4; i++) {
-            r->dp[j] |= ((mp_digit)a[i]) << s;
-            if (s + 64 >= DIGIT_BIT) {
-    #if DIGIT_BIT < 64
-                r->dp[j] &= (1l << DIGIT_BIT) - 1;
-    #endif
-                s = DIGIT_BIT - s;
-                r->dp[++j] = a[i] >> s;
-                s = 64 - s;
-            }
-            else
-                s += 64;
-        }
-        r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
-        mp_clamp(r);
-#endif
-    }
-
-    return err;
-}
-
-/* Convert a point of type sp_point to type ecc_point.
- *
- * p   Point of type sp_point.
- * pm  Point of type ecc_point (result).
- * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
- * MP_OKAY.
- */
-static int sp_256_point_to_ecc_point_4(sp_point* p, ecc_point* pm)
-{
-    int err;
-
-    err = sp_256_to_mp(p->x, pm->x);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pm->y);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pm->z);
-
-    return err;
-}
-
-/* Conditionally copy a into r using the mask m.
- * m is -1 to copy and 0 when not.
- *
- * r  A single precision number to copy over.
- * a  A single precision number to copy.
- * m  Mask value to apply.
- */
-static void sp_256_cond_copy_4(sp_digit* r, const sp_digit* a, const sp_digit m)
-{
-    sp_digit t[4];
-    __asm__ __volatile__ (
-        "movq	(%[r]), %%rax\n\t"
-        "movq	8(%[r]), %%rcx\n\t"
-        "movq	16(%[r]), %%rdx\n\t"
-        "movq	24(%[r]), %%r8\n\t"
-        "xorq	(%[a]), %%rax\n\t"
-        "xorq	8(%[a]), %%rcx\n\t"
-        "xorq	16(%[a]), %%rdx\n\t"
-        "xorq	24(%[a]), %%r8\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "andq	%[m], %%rdx\n\t"
-        "andq	%[m], %%r8\n\t"
-        "xorq	%%rax, (%[r])\n\t"
-        "xorq	%%rcx, 8(%[r])\n\t"
-        "xorq	%%rdx, 16(%[r])\n\t"
-        "xorq	%%r8, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx", "r8"
-    );
-}
-
-/* Compare a with b in constant time.
- *
- * a  A single precision integer.
- * b  A single precision integer.
- * return -ve, 0 or +ve if a is less than, equal to or greater than b
- * respectively.
- */
-static int64_t sp_256_cmp_4(sp_digit* a, sp_digit* b)
-{
-    sp_digit r = -1;
-    sp_digit one = 1;
-
-    __asm__ __volatile__ (
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	$-1, %%rdx\n\t"
-        "movq	24(%[a]), %%rbx\n\t"
-        "movq	24(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	16(%[a]), %%rbx\n\t"
-        "movq	16(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	8(%[a]), %%rbx\n\t"
-        "movq	8(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "movq	0(%[a]), %%rbx\n\t"
-        "movq	0(%[b]), %%r8\n\t"
-        "andq	%%rdx, %%rbx\n\t"
-        "andq	%%rdx, %%r8\n\t"
-        "subq	%%r8, %%rbx\n\t"
-        "cmova	%[one], %[r]\n\t"
-        "cmovc	%%rdx, %[r]\n\t"
-        "cmovnz	%%rcx, %%rdx\n\t"
-        "xorq	%%rdx, %[r]\n\t"
-        : [r] "+r" (r)
-        : [a] "r" (a), [b] "r" (b), [one] "r" (one)
-        : "rax", "rdx", "rcx", "rbx", "r8"
-    );
-
-    return r;
-}
-
-/* Normalize the values in each word to 64.
- *
- * a  Array of sp_digit to normalize.
- */
-#define sp_256_norm_4(a)
-
-/* Conditionally subtract b from a using the mask m.
- * m is -1 to subtract and 0 when not copying.
- *
- * r  A single precision number representing condition subtract result.
- * a  A single precision number to subtract from.
- * b  A single precision number to subtract.
- * m  Mask value to apply.
- */
-static sp_digit sp_256_cond_sub_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit m)
-{
-    sp_digit t[4];
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[b]), %%rax\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 0(%[t])\n\t"
-        "movq	%%rcx, 8(%[t])\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "andq	%[m], %%rax\n\t"
-        "andq	%[m], %%rcx\n\t"
-        "movq	%%rax, 16(%[t])\n\t"
-        "movq	%%rcx, 24(%[t])\n\t"
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[t]), %%rdx\n\t"
-        "subq	%%rdx,%%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[t]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m), [t] "r" (t)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Sub b from a into r. (r = a - b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "movq	(%[b]), %%rdx\n\t"
-        "subq	%%rdx, %%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	8(%[b]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rax\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	24(%[a]), %%rcx\n\t"
-        "movq	24(%[b]), %%rdx\n\t"
-        "sbbq	%%rdx, %%rcx\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	%%rcx, 24(%[r])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rcx", "rdx"
-    );
-
-    return c;
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "# i = 0\n\t"
-        "xorq	%%r13, %%r13\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "movq	%[a], %%r12\n\t"
-        "\nL_mont_loop_4:\n\t"
-        "# mu = a[i] * mp\n\t"
-        "movq	0(%%r12), %%r11\n\t"
-        "imulq	%[mp], %%r11\n\t"
-        "# a[i+0] += m[0] * mu\n\t"
-        "movq	0(%[m]), %%rax\n\t"
-        "movq	8(%[m]), %%r9\n\t"
-        "mulq	%%r11\n\t"
-        "movq	0(%%r12), %%rbx\n\t"
-        "addq	%%rax,  %%rbx\n\t"
-        "movq	%%rdx, %%r8\n\t"
-        "movq	%%rbx, 0(%%r12)\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+1] += m[1] * mu\n\t"
-        "movq	%%r9, %%rax\n\t"
-        "mulq	%%r11\n\t"
-        "movq	16(%[m]), %%r9\n\t"
-        "movq	8(%%r12), %%rbx\n\t"
-        "addq	%%r8, %%rax\n\t"
-        "movq	%%rdx, %%r10\n\t"
-        "adcq	$0, %%r10\n\t"
-        "addq	%%rax,  %%rbx\n\t"
-        "movq	%%rbx, 8(%%r12)\n\t"
-        "adcq	$0, %%r10\n\t"
-        "# a[i+2] += m[2] * mu\n\t"
-        "movq	%%r9, %%rax\n\t"
-        "mulq	%%r11\n\t"
-        "movq	24(%[m]), %%r9\n\t"
-        "movq	16(%%r12), %%rbx\n\t"
-        "addq	%%r10, %%rax\n\t"
-        "movq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax,  %%rbx\n\t"
-        "movq	%%rbx, 16(%%r12)\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# a[i+3] += m[3] * mu\n\t"
-        "movq	%%r9, %%rax\n\t"
-        "mulq	%%r11\n\t"
-        "movq	24(%%r12), %%rbx\n\t"
-        "addq	%%r8, %%rax\n\t"
-        "adcq	%%r13, %%rdx\n\t"
-        "movq	$0, %%r13\n\t"
-        "adcq	$0, %%r13\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "movq	%%rbx, 24(%%r12)\n\t"
-        "adcq	%%rdx, 32(%%r12)\n\t"
-        "adcq	$0, %%r13\n\t"
-        "# i += 1\n\t"
-        "addq	$8, %%r12\n\t"
-        "addq	$8, %%rcx\n\t"
-        "cmpq	$32, %%rcx\n\t"
-        "jl	L_mont_loop_4\n\t"
-        "xorq	%%rax, %%rax\n\t"
-        "movq	32(%[a]), %%rdx\n\t"
-        "movq	40(%[a]), %%rcx\n\t"
-        "movq	48(%[a]), %%rbx\n\t"
-        "movq	56(%[a]), %%r8\n\t"
-        "subq	%%r13, %%rax\n\t"
-        "movq	0(%[m]), %%r9\n\t"
-        "movq	8(%[m]), %%r10\n\t"
-        "movq	16(%[m]), %%r11\n\t"
-        "movq	24(%[m]), %%r12\n\t"
-        "andq	%%rax, %%r9\n\t"
-        "andq	%%rax, %%r10\n\t"
-        "andq	%%rax, %%r11\n\t"
-        "andq	%%rax, %%r12\n\t"
-        "subq	%%r9, %%rdx\n\t"
-        "sbbq	%%r10, %%rcx\n\t"
-        "sbbq	%%r11, %%rbx\n\t"
-        "sbbq	%%r12, %%r8\n\t"
-        "movq	%%rdx,   (%[a])\n\t"
-        "movq	%%rcx,  8(%[a])\n\t"
-        "movq	%%rbx, 16(%[a])\n\t"
-        "movq	%%r8, 24(%[a])\n\t"
-        :
-        : [a] "r" (a), [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rbx", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13"
-    );
-}
-
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_mul_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m, sp_digit mp)
-{
-    (void)mp;
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "movq	%%rax, %%r8\n\t"
-        "movq	%%rdx, %%r9\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%r10\n\t"
-        "#  A[1] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%r10\n\t"
-        "adcq	$0, %%r11\n\t"
-        "#  A[0] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[2] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "adcq	$0, %%r12\n\t"
-        "#  A[0] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r13, %%r13\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	$0, %%r13\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	$0, %%r13\n\t"
-        "#  A[2] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	$0, %%r13\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	$0, %%r13\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%r14, %%r14\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "# Start Reduction\n\t"
-        "movq	%%r8, %%rax\n\t"
-        "movq	%%r9, %[a]\n\t"
-        "movq	%%r10, %[b]\n\t"
-        "movq	%%r11, %%rdx\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "shlq	$32, %%r8\n\t"
-        "shldq	$32, %[a], %%r10\n\t"
-        "shldq	$32, %%rax, %%r9\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "subq	%%r8, %%rdx\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "addq	%%r8, %[a]\n\t"
-        "adcq	%%r9, %[b]\n\t"
-        "adcq	%%r10, %%rdx\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%[a], %%r13\n\t"
-        "adcq	%[b], %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a += mu << 192\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%[a], %%r12\n\t"
-        "adcq	%[b], %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "# mu <<= 32\n\t"
-        "movq	%%rdx, %[m]\n\t"
-        "shldq	$32, %[b], %%rdx\n\t"
-        "shldq	$32, %[a], %[b]\n\t"
-        "shldq	$32, %%rax, %[a]\n\t"
-        "shlq	$32, %%rax\n\t"
-        "shrq	$32, %[m]\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "addq	%[b], %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	%[m], %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subq	%%rax, %%r11\n\t"
-        "movq	$0xffffffff, %%rax\n\t"
-        "sbbq	%[a], %%r12\n\t"
-        "movq	$0xffffffff00000001, %[a]\n\t"
-        "sbbq	%[b], %%r13\n\t"
-        "sbbq	%%rdx, %%r14\n\t"
-        "sbbq	%[m], %%r15\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "andq	%%r8, %%rax\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "andq	%%r8, %[a]\n\t"
-        "subq	%%r8, %%r12\n\t"
-        "sbbq	%%rax, %%r13\n\t"
-        "sbbq	$0, %%r14\n\t"
-        "sbbq	%[a], %%r15\n\t"
-        "movq	%%r12, 0(%[r])\n\t"
-        "movq	%%r13, 8(%[r])\n\t"
-        "movq	%%r14, 16(%[r])\n\t"
-        "movq	%%r15, 24(%[r])\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b)
-        : [r] "r" (r)
-        : "memory", "rax", "rdx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_sqr_4(sp_digit* r, sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "#  A[0] * A[1]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "movq	%%rax, %%r9\n\t"
-        "movq	%%rdx, %%r10\n\t"
-        "#  A[0] * A[2]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	%%rax, %%r10\n\t"
-        "adcq	%%rdx, %%r11\n\t"
-        "#  A[0] * A[3]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "#  A[1] * A[2]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%r13, %%r13\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	$0, %%r13\n\t"
-        "#  A[1] * A[3]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%%rdx, %%r13\n\t"
-        "#  A[2] * A[3]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "xorq	%%r14, %%r14\n\t"
-        "addq	%%rax, %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "# Double\n\t"
-        "xorq	%%r15, %%r15\n\t"
-        "addq	%%r9, %%r9\n\t"
-        "adcq	%%r10, %%r10\n\t"
-        "adcq	%%r11, %%r11\n\t"
-        "adcq	%%r12, %%r12\n\t"
-        "adcq	%%r13, %%r13\n\t"
-        "adcq	%%r14, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "#  A[0] * A[0]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "movq	%%rax, %%r8\n\t"
-        "movq	%%rdx, %[mp]\n\t"
-        "#  A[1] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%[mp], %%r9\n\t"
-        "adcq	%%rax, %%r10\n\t"
-        "adcq	$0, %%rdx\n\t"
-        "movq	%%rdx, %[mp]\n\t"
-        "#  A[2] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%[mp], %%r11\n\t"
-        "adcq	%%rax, %%r12\n\t"
-        "adcq	$0, %%rdx\n\t"
-        "movq	%%rdx, %[mp]\n\t"
-        "#  A[3] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "addq	%[mp], %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "# Start Reduction\n\t"
-        "movq	%%r8, %%rax\n\t"
-        "movq	%%r9, %[a]\n\t"
-        "movq	%%r10, %[mp]\n\t"
-        "movq	%%r11, %%rdx\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "shlq	$32, %%r8\n\t"
-        "shldq	$32, %[a], %%r10\n\t"
-        "shldq	$32, %%rax, %%r9\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "subq	%%r8, %%rdx\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "addq	%%r8, %[a]\n\t"
-        "adcq	%%r9, %[mp]\n\t"
-        "adcq	%%r10, %%rdx\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%[a], %%r13\n\t"
-        "adcq	%[mp], %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a += mu << 192\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%[a], %%r12\n\t"
-        "adcq	%[mp], %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "# mu <<= 32\n\t"
-        "movq	%%rdx, %[m]\n\t"
-        "shldq	$32, %[mp], %%rdx\n\t"
-        "shldq	$32, %[a], %[mp]\n\t"
-        "shldq	$32, %%rax, %[a]\n\t"
-        "shlq	$32, %%rax\n\t"
-        "shrq	$32, %[m]\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "addq	%[mp], %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	%[m], %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subq	%%rax, %%r11\n\t"
-        "movq	$0xffffffff, %%rax\n\t"
-        "sbbq	%[a], %%r12\n\t"
-        "movq	$0xffffffff00000001, %[a]\n\t"
-        "sbbq	%[mp], %%r13\n\t"
-        "sbbq	%%rdx, %%r14\n\t"
-        "sbbq	%[m], %%r15\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "andq	%%r8, %%rax\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "andq	%%r8, %[a]\n\t"
-        "subq	%%r8, %%r12\n\t"
-        "sbbq	%%rax, %%r13\n\t"
-        "sbbq	$0, %%r14\n\t"
-        "sbbq	%[a], %%r15\n\t"
-        "movq	%%r12, 0(%[r])\n\t"
-        "movq	%%r13, 8(%[r])\n\t"
-        "movq	%%r14, 16(%[r])\n\t"
-        "movq	%%r15, 24(%[r])\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp)
-        : [r] "r" (r)
-        : "memory", "rax", "rdx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_4(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_4(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_4(r, r, m, mp);
-}
-
-#else
-/* Mod-2 for the P256 curve. */
-static const uint64_t p256_mod_2[4] = {
-    0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000,
-    0xffffffff00000001
-};
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_4(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_4(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_4(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_4(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_4(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_4(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_4(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_4(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_4(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_4(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_4(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_4(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_4(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_4(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    int64_t n;
-
-    sp_256_mont_inv_4(t1, p->z, t + 2*4);
-
-    sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_4(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 4, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_4(r->x, p256_mod);
-    sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_4(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 4, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_4(r->y, p256_mod);
-    sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-/* Add two Montgomery form numbers (r = a + b % m).
- *
- * r   Result of addition.
- * a   First number to add in Montogmery form.
- * b   Second number to add in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_add_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "movq	24(%[a]), %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	0(%[b]), %%rax\n\t"
-        "adcq	8(%[b]), %%rcx\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "adcq	16(%[b]), %%rdx\n\t"
-        "adcq	24(%[b]), %%r10\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "sbbq	$0, %%r11\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "subq	%%r11, %%rax\n\t"
-        "sbbq	%%r8, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "sbbq	$0, %%rdx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "sbbq	%%r9, %%r10\n\t"
-        "movq	%%rdx, 16(%[r])\n\t"
-        "movq	%%r10, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11"
-    );
-}
-
-/* Double a Montgomery form number (r = a + a % m).
- *
- * r   Result of doubling.
- * a   Number to double in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_dbl_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "movq	24(%[a]), %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	%%rax, %%rax\n\t"
-        "adcq	%%rcx, %%rcx\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "adcq	%%rdx, %%rdx\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "adcq	%%r10, %%r10\n\t"
-        "sbbq	$0, %%r11\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "subq	%%r11, %%rax\n\t"
-        "sbbq	%%r8, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "sbbq	$0, %%rdx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "sbbq	%%r9, %%r10\n\t"
-        "movq	%%rdx, 16(%[r])\n\t"
-        "movq	%%r10, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11"
-    );
-
-    (void)m;
-}
-
-/* Triple a Montgomery form number (r = a + a + a % m).
- *
- * r   Result of Tripling.
- * a   Number to triple in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_tpl_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "movq	24(%[a]), %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	%%rax, %%rax\n\t"
-        "adcq	%%rcx, %%rcx\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "adcq	%%rdx, %%rdx\n\t"
-        "adcq	%%r10, %%r10\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "sbbq	$0, %%r11\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "subq	%%r11, %%rax\n\t"
-        "sbbq	%%r8, %%rcx\n\t"
-        "sbbq	$0, %%rdx\n\t"
-        "sbbq	%%r9, %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	(%[a]), %%rax\n\t"
-        "adcq	8(%[a]), %%rcx\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "adcq	16(%[a]), %%rdx\n\t"
-        "adcq	24(%[a]), %%r10\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "sbbq	$0, %%r11\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "subq	%%r11, %%rax\n\t"
-        "sbbq	%%r8, %%rcx\n\t"
-        "sbbq	$0, %%rdx\n\t"
-        "sbbq	%%r9, %%r10\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "movq	%%rdx, 16(%[r])\n\t"
-        "movq	%%r10, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11"
-    );
-
-    (void)m;
-}
-
-/* Subtract two Montgomery form numbers (r = a - b % m).
- *
- * r   Result of subtration.
- * a   Number to subtract from in Montogmery form.
- * b   Number to subtract with in Montogmery form.
- * m   Modulus (prime).
- */
-static void sp_256_mont_sub_4(sp_digit* r, sp_digit* a, sp_digit* b,
-        sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%rax\n\t"
-        "movq	8(%[a]), %%rcx\n\t"
-        "movq	16(%[a]), %%rdx\n\t"
-        "movq	24(%[a]), %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "subq	0(%[b]), %%rax\n\t"
-        "sbbq	8(%[b]), %%rcx\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "sbbq	16(%[b]), %%rdx\n\t"
-        "sbbq	24(%[b]), %%r10\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "sbbq	$0, %%r11\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "addq	%%r11, %%rax\n\t"
-        "adcq	%%r8, %%rcx\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "adcq	$0, %%rdx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%r9, %%r10\n\t"
-        "movq	%%rdx, 16(%[r])\n\t"
-        "movq	%%r10, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m)
-        : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11"
-    );
-}
-
-/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
- *
- * r  Result of division by 2.
- * a  Number to divide.
- * m  Modulus (prime).
- */
-SP_NOINLINE static void sp_256_div2_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%rax\n\t"
-        "movq	8(%[a]), %%rdx\n\t"
-        "movq	16(%[a]), %%rcx\n\t"
-        "movq	24(%[a]), %%r10\n\t"
-        "movq	$0xffffffff, %%r8\n\t"
-        "movq	$0xffffffff00000001, %%r9\n\t"
-        "xorq	%%r12, %%r12\n\t"
-        "movq	%%rax, %%r11\n\t"
-        "andq	$1, %%r11\n\t"
-        "subq	%%r11, %%r12\n\t"
-        "andq	%%r12, %%r8\n\t"
-        "andq	%%r12, %%r9\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "addq	%%r12, %%rax\n\t"
-        "adcq	%%r8, %%rdx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "adcq	%%r9, %%r10\n\t"
-        "adcq	$0, %%r11\n\t"
-        "shrdq	$1, %%rdx, %%rax\n\t"
-        "shrdq	$1, %%rcx, %%rdx\n\t"
-        "shrdq	$1, %%r10, %%rcx\n\t"
-        "shrdq	$1, %%r11, %%r10\n\t"
-        "movq	%%rax, 0(%[r])\n\t"
-        "movq	%%rdx, 8(%[r])\n\t"
-        "movq	%%rcx, 16(%[r])\n\t"
-        "movq	%%r10, 24(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [m] "r" (m)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_4(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_4(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_4(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_4(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_4(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_4(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_4(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_4(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_4(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_4(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_4(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_4(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_4(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_4(y, y, p256_mod);
-}
-
-/* Compare two numbers to determine if they are equal.
- * Constant time implementation.
- *
- * a  First number to compare.
- * b  Second number to compare.
- * returns 1 when equal and 0 otherwise.
- */
-static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b)
-{
-    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0;
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_4(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, x, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, y, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, y, t5, p256_mod);
-    }
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_store_4(sp_point* r, sp_point* p,
-        int n, int m, sp_digit* t)
-{
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x = r[2*m].x;
-    sp_digit* y = r[(1<<n)*m].y;
-    sp_digit* z = r[2*m].z;
-    int i;
-
-    for (i=0; i<4; i++)
-        x[i] = p->x[i];
-    for (i=0; i<4; i++)
-        y[i] = p->y[i];
-    for (i=0; i<4; i++)
-        z[i] = p->z[i];
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod);
-    for (i=1; i<=n; i++) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod);
-        x = r[(1<<i)*m].x;
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_4(r[(1<<i)*m].z, z, y, p256_mod, p256_mp_mod);
-        z = r[(1<<i)*m].z;
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod);
-        if (i != n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-        /* Y = Y/2 */
-        sp_256_div2_4(r[(1<<i)*m].y, y, p256_mod);
-        r[(1<<i)*m].infinity = 0;
-    }
-}
-
-/* Add two Montgomery form projective points.
- *
- * ra  Result of addition.
- * rs  Result of subtraction.
- * p   Frist point to add.
- * q   Second point to add.
- * t   Temporary ordinate data.
- */
-static void sp_256_proj_point_add_sub_4(sp_point* ra, sp_point* rs,
-        sp_point* p, sp_point* q, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* t6 = t + 10*4;
-    sp_digit* x = ra->x;
-    sp_digit* y = ra->y;
-    sp_digit* z = ra->z;
-    sp_digit* xs = rs->x;
-    sp_digit* ys = rs->y;
-    sp_digit* zs = rs->z;
-
-
-    XMEMCPY(x, p->x, sizeof(p->x) / 2);
-    XMEMCPY(y, p->y, sizeof(p->y) / 2);
-    XMEMCPY(z, p->z, sizeof(p->z) / 2);
-    ra->infinity = 0;
-    rs->infinity = 0;
-
-    /* U1 = X1*Z2^2 */
-    sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod);
-    /* U2 = X2*Z1^2 */
-    sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-    /* S1 = Y1*Z2^3 */
-    sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod);
-    /* S2 = Y2*Z1^3 */
-    sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-    /* H = U2 - U1 */
-    sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-    /* RS = S2 + S1 */
-    sp_256_mont_add_4(t6, t4, t3, p256_mod);
-    /* R = S2 - S1 */
-    sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-    /* Z3 = H*Z1*Z2 */
-    /* ZS = H*Z1*Z2 */
-    sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-    XMEMCPY(zs, z, sizeof(p->z)/2);
-    /* X3 = R^2 - H^3 - 2*U1*H^2 */
-    /* XS = RS^2 - H^3 - 2*U1*H^2 */
-    sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(xs, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(x, x, t5, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t5, p256_mod);
-    sp_256_mont_dbl_4(t1, y, p256_mod);
-    sp_256_mont_sub_4(x, x, t1, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t1, p256_mod);
-    /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-    /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
-    sp_256_mont_sub_4(ys, y, xs, p256_mod);
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod);
-    sp_256_sub_4(t6, p256_mod, t6);
-    sp_256_mont_mul_4(ys, ys, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(y, y, t5, p256_mod);
-    sp_256_mont_sub_4(ys, ys, t5, p256_mod);
-}
-
-/* Structure used to describe recoding of scalar multiplication. */
-typedef struct ecc_recode {
-    /* Index into pre-computation table. */
-    uint8_t i;
-    /* Use the negative of the point. */
-    uint8_t neg;
-} ecc_recode;
-
-/* The index into pre-computation table to use. */
-static uint8_t recode_index_4_6[66] = {
-     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
-    16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,
-     0,  1,
-};
-
-/* Whether to negate y-ordinate. */
-static uint8_t recode_neg_4_6[66] = {
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     0,  0,
-};
-
-/* Recode the scalar for multiplication using pre-computed values and
- * subtraction.
- *
- * k  Scalar to multiply by.
- * v  Vector of operations to peform.
- */
-static void sp_256_ecc_recode_6_4(sp_digit* k, ecc_recode* v)
-{
-    int i, j;
-    uint8_t y;
-    int carry = 0;
-    int o;
-    sp_digit n;
-
-    j = 0;
-    n = k[j];
-    o = 0;
-    for (i=0; i<43; i++) {
-        y = n;
-        if (o + 6 < 64) {
-            y &= 0x3f;
-            n >>= 6;
-            o += 6;
-        }
-        else if (o + 6 == 64) {
-            n >>= 6;
-            if (++j < 4)
-                n = k[j];
-            o = 0;
-        }
-        else if (++j < 4) {
-            n = k[j];
-            y |= (n << (64 - o)) & 0x3f;
-            o -= 58;
-            n >>= o;
-        }
-
-        y += carry;
-        v[i].i = recode_index_4_6[y];
-        v[i].neg = recode_neg_4_6[y];
-        carry = (y >> 6) + v[i].neg;
-    }
-}
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_win_add_sub_4(sp_point* r, sp_point* g,
-        sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[33];
-    sp_point rtd, pd;
-    sp_digit tmpd[2 * 4 * 6];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode v[43];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        t[1].infinity = 0;
-        /* t[2] ... t[32]  */
-    sp_256_proj_point_dbl_n_store_4(t, &t[ 1], 5, 1, tmp);
-    sp_256_proj_point_add_4(&t[ 3], &t[ 2], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[ 6], &t[ 3], tmp);
-    sp_256_proj_point_add_sub_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[10], &t[ 5], tmp);
-    sp_256_proj_point_add_sub_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[12], &t[ 6], tmp);
-    sp_256_proj_point_dbl_4(&t[14], &t[ 7], tmp);
-    sp_256_proj_point_add_sub_4(&t[15], &t[13], &t[14], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[18], &t[ 9], tmp);
-    sp_256_proj_point_add_sub_4(&t[19], &t[17], &t[18], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[20], &t[10], tmp);
-    sp_256_proj_point_dbl_4(&t[22], &t[11], tmp);
-    sp_256_proj_point_add_sub_4(&t[23], &t[21], &t[22], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[24], &t[12], tmp);
-    sp_256_proj_point_dbl_4(&t[26], &t[13], tmp);
-    sp_256_proj_point_add_sub_4(&t[27], &t[25], &t[26], &t[ 1], tmp);
-    sp_256_proj_point_dbl_4(&t[28], &t[14], tmp);
-    sp_256_proj_point_dbl_4(&t[30], &t[15], tmp);
-    sp_256_proj_point_add_sub_4(&t[31], &t[29], &t[30], &t[ 1], tmp);
-
-        negy = t[0].y;
-
-        sp_256_ecc_recode_6_4(k, v);
-
-        i = 42;
-        XMEMCPY(rt, &t[v[i].i], sizeof(sp_point));
-        for (--i; i>=0; i--) {
-            sp_256_proj_point_dbl_n_4(rt, rt, 6, tmp);
-
-            XMEMCPY(p, &t[v[i].i], sizeof(sp_point));
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_4(rt, rt, p, tmp);
-        }
-
-        if (map)
-            sp_256_map_4(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    if (tmp != NULL)
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply two Montogmery form numbers mod the modulus (prime).
- * (r = a * b mod m)
- *
- * r   Result of multiplication.
- * a   First number to multiply in Montogmery form.
- * b   Second number to multiply in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_mul_avx2_4(sp_digit* r, sp_digit* a,
-        sp_digit* b, sp_digit* m, sp_digit mp)
-{
-    (void)mp;
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq   0(%[b]), %%rdx\n\t"
-        "mulxq  0(%[a]), %%r8, %%r9\n\t"
-        "#  A[2] * B[0]\n\t"
-        "mulxq  16(%[a]), %%r10, %%r11\n\t"
-        "#  A[1] * B[0]\n\t"
-        "mulxq  8(%[a]), %%rax, %[m]\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "adcxq  %%rax, %%r9\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%r12, %%r13\n\t"
-        "adcxq  %[m], %%r10\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "mulxq  0(%[a]), %%rax, %[m]\n\t"
-        "adoxq  %%rax, %%r9\n\t"
-        "#  A[2] * B[1]\n\t"
-        "mulxq  16(%[a]), %%rax, %%r14\n\t"
-        "adoxq  %[m], %%r10\n\t"
-        "adcxq  %%rax, %%r11\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%rax, %[m]\n\t"
-        "adcxq  %%r14, %%r12\n\t"
-        "adoxq  %%rax, %%r11\n\t"
-        "adcxq  %%r15, %%r13\n\t"
-        "adoxq  %[m], %%r12\n\t"
-        "#  A[0] * B[2]\n\t"
-        "mulxq  0(%[a]), %%rax, %[m]\n\t"
-        "adoxq  %%r15, %%r13\n\t"
-        "xorq   %%r14, %%r14\n\t"
-        "adcxq  %%rax, %%r10\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %[m], %%r11\n\t"
-        "adoxq  %%rdx, %%r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "adoxq  %%rax, %%r11\n\t"
-        "mulxq  24(%[a]), %%rax, %[m]\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "mulxq  16(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %[m], %%r13\n\t"
-        "adoxq  %%rdx, %%r12\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "adoxq  %%rax, %%r13\n\t"
-        "mulxq  24(%[a]), %%rax, %[m]\n\t"
-        "adoxq  %%r15, %%r14\n\t"
-        "adcxq  %%rax, %%r14\n\t"
-        "#  A[0] * B[3]\n\t"
-        "mulxq  0(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %[m], %%r15\n\t"
-        "xorq   %[m], %[m]\n\t"
-        "adcxq  %%rdx, %%r11\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq   0(%[b]), %%rdx\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "mulxq  24(%[a]), %%rdx, %%rax\n\t"
-        "adoxq  %%rdx, %%r11\n\t"
-        "adoxq  %%rax, %%r12\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "mulxq  16(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %%rdx, %%r13\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "adcxq  %%rax, %%r14\n\t"
-        "mulxq  24(%[a]), %%rax, %%rdx\n\t"
-        "adcxq  %[m], %%r15\n\t"
-        "adoxq  %%rax, %%r13\n\t"
-        "adoxq  %%rdx, %%r14\n\t"
-        "adoxq  %[m], %%r15\n\t"
-        "# Start Reduction\n\t"
-        "movq	%%r8, %%rax\n\t"
-        "movq	%%r9, %[a]\n\t"
-        "movq	%%r10, %[b]\n\t"
-        "movq	%%r11, %%rdx\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "shlq	$32, %%r8\n\t"
-        "shldq	$32, %[a], %%r10\n\t"
-        "shldq	$32, %%rax, %%r9\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "subq	%%r8, %%rdx\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "addq	%%r8, %[a]\n\t"
-        "adcq	%%r9, %[b]\n\t"
-        "adcq	%%r10, %%rdx\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%[a], %%r13\n\t"
-        "adcq	%[b], %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a += mu << 192\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%[a], %%r12\n\t"
-        "adcq	%[b], %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "# mu <<= 32\n\t"
-        "movq	%%rdx, %[m]\n\t"
-        "shldq	$32, %[b], %%rdx\n\t"
-        "shldq	$32, %[a], %[b]\n\t"
-        "shldq	$32, %%rax, %[a]\n\t"
-        "shlq	$32, %%rax\n\t"
-        "shrq	$32, %[m]\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "addq	%[b], %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	%[m], %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subq	%%rax, %%r11\n\t"
-        "movq	$0xffffffff, %%rax\n\t"
-        "sbbq	%[a], %%r12\n\t"
-        "movq	$0xffffffff00000001, %[a]\n\t"
-        "sbbq	%[b], %%r13\n\t"
-        "sbbq	%%rdx, %%r14\n\t"
-        "sbbq	%[m], %%r15\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "andq	%%r8, %%rax\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "andq	%%r8, %[a]\n\t"
-        "subq	%%r8, %%r12\n\t"
-        "sbbq	%%rax, %%r13\n\t"
-        "sbbq	$0, %%r14\n\t"
-        "sbbq	%[a], %%r15\n\t"
-        "movq	%%r12, 0(%[r])\n\t"
-        "movq	%%r13, 8(%[r])\n\t"
-        "movq	%%r14, 16(%[r])\n\t"
-        "movq	%%r15, 24(%[r])\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b)
-        : [r] "r" (r)
-        : "memory", "rax", "rdx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-SP_NOINLINE static void sp_256_mont_sqr_avx2_4(sp_digit* r, sp_digit* a,
-        sp_digit* m, sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "# A[0] * A[1]\n\t"
-        "movq   0(%[a]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%r9, %%r10\n\t"
-        "# A[0] * A[3]\n\t"
-        "mulxq  24(%[a]), %%r11, %%r12\n\t"
-        "# A[2] * A[1]\n\t"
-        "movq   16(%[a]), %%rdx\n\t"
-        "mulxq  8(%[a]), %[mp], %[m]\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "adoxq  %[mp], %%r11\n\t"
-        "# A[2] * A[3]\n\t"
-        "mulxq  24(%[a]), %%r13, %%r14\n\t"
-        "adoxq  %[m], %%r12\n\t"
-        "# A[2] * A[0]\n\t"
-        "mulxq  0(%[a]), %[mp], %[m]\n\t"
-        "adoxq  %%r15, %%r13\n\t"
-        "adcxq  %[mp], %%r10\n\t"
-        "adoxq  %%r15, %%r14\n\t"
-        "# A[1] * A[3]\n\t"
-        "movq   8(%[a]), %%rdx\n\t"
-        "mulxq  24(%[a]), %%rax, %%r8\n\t"
-        "adcxq  %[m], %%r11\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "adcxq  %%r8, %%r13\n\t"
-        "adcxq  %%r15, %%r14\n\t"
-        "# Double with Carry Flag\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "# A[0] * A[0]\n\t"
-        "movq   0(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%r8, %%rax\n\t"
-        "adcxq  %%r9, %%r9\n\t"
-        "# A[1] * A[1]\n\t"
-        "movq   8(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %[mp], %[m]\n\t"
-        "adcxq  %%r10, %%r10\n\t"
-        "adoxq  %%rax, %%r9\n\t"
-        "adcxq  %%r11, %%r11\n\t"
-        "adoxq  %[mp], %%r10\n\t"
-        "# A[2] * A[2]\n\t"
-        "movq   16(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%rax, %[mp]\n\t"
-        "adcxq  %%r12, %%r12\n\t"
-        "adoxq  %[m], %%r11\n\t"
-        "adcxq  %%r13, %%r13\n\t"
-        "adoxq  %%rax, %%r12\n\t"
-        "# A[3] * A[3]\n\t"
-        "movq   24(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%rax, %[m]\n\t"
-        "adcxq  %%r14, %%r14\n\t"
-        "adoxq  %[mp], %%r13\n\t"
-        "adcxq  %%r15, %%r15\n\t"
-        "adoxq  %%rax, %%r14\n\t"
-        "adoxq  %[m], %%r15\n\t"
-        "# Start Reduction\n\t"
-        "movq	%%r8, %%rax\n\t"
-        "movq	%%r9, %[a]\n\t"
-        "movq	%%r10, %[mp]\n\t"
-        "movq	%%r11, %%rdx\n\t"
-        "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t"
-        "#    - a[0] << 32 << 192\n\t"
-        "#   + (a[0] * 2) << 192\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "addq	%%r8, %%rdx\n\t"
-        "#   a[0]-a[2] << 32\n\t"
-        "shlq	$32, %%r8\n\t"
-        "shldq	$32, %[a], %%r10\n\t"
-        "shldq	$32, %%rax, %%r9\n\t"
-        "#   - a[0] << 32 << 192\n\t"
-        "subq	%%r8, %%rdx\n\t"
-        "#   + a[0]-a[2] << 32 << 64\n\t"
-        "addq	%%r8, %[a]\n\t"
-        "adcq	%%r9, %[mp]\n\t"
-        "adcq	%%r10, %%rdx\n\t"
-        "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t"
-        "#   a += mu << 256\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r12\n\t"
-        "adcq	%[a], %%r13\n\t"
-        "adcq	%[mp], %%r14\n\t"
-        "adcq	%%rdx, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a += mu << 192\n\t"
-        "addq	%%rax, %%r11\n\t"
-        "adcq	%[a], %%r12\n\t"
-        "adcq	%[mp], %%r13\n\t"
-        "adcq	%%rdx, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "# mu <<= 32\n\t"
-        "movq	%%rdx, %[m]\n\t"
-        "shldq	$32, %[mp], %%rdx\n\t"
-        "shldq	$32, %[a], %[mp]\n\t"
-        "shldq	$32, %%rax, %[a]\n\t"
-        "shlq	$32, %%rax\n\t"
-        "shrq	$32, %[m]\n\t"
-        "#   a += (mu << 32) << 64\n\t"
-        "addq	%[mp], %%r11\n\t"
-        "adcq	%%rdx, %%r12\n\t"
-        "adcq	%[m], %%r13\n\t"
-        "adcq	$0, %%r14\n\t"
-        "adcq	$0, %%r15\n\t"
-        "sbbq	$0, %%r8\n\t"
-        "#   a -= (mu << 32) << 192\n\t"
-        "subq	%%rax, %%r11\n\t"
-        "movq	$0xffffffff, %%rax\n\t"
-        "sbbq	%[a], %%r12\n\t"
-        "movq	$0xffffffff00000001, %[a]\n\t"
-        "sbbq	%[mp], %%r13\n\t"
-        "sbbq	%%rdx, %%r14\n\t"
-        "sbbq	%[m], %%r15\n\t"
-        "adcq	$0, %%r8\n\t"
-        "# mask m and sub from result if overflow\n\t"
-        "#  m[0] = -1 & mask = mask\n\t"
-        "andq	%%r8, %%rax\n\t"
-        "#  m[2] =  0 & mask = 0\n\t"
-        "andq	%%r8, %[a]\n\t"
-        "subq	%%r8, %%r12\n\t"
-        "sbbq	%%rax, %%r13\n\t"
-        "sbbq	$0, %%r14\n\t"
-        "sbbq	%[a], %%r15\n\t"
-        "movq	%%r12, 0(%[r])\n\t"
-        "movq	%%r13, 8(%[r])\n\t"
-        "movq	%%r14, 16(%[r])\n\t"
-        "movq	%%r15, 24(%[r])\n\t"
-        : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp)
-        : [r] "r" (r)
-        : "memory", "rax", "rdx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- * n   Number of times to square.
- * m   Modulus (prime).
- * mp  Montogmery mulitplier.
- */
-static void sp_256_mont_sqr_n_avx2_4(sp_digit* r, sp_digit* a, int n,
-        sp_digit* m, sp_digit mp)
-{
-    sp_256_mont_sqr_avx2_4(r, a, m, mp);
-    for (; n > 1; n--)
-        sp_256_mont_sqr_avx2_4(r, r, m, mp);
-}
-
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
- * P256 curve. (r = 1 / a mod m)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_avx2_4(sp_digit* r, sp_digit* a, sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_avx2_4(t, t, p256_mod, p256_mp_mod);
-        if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_avx2_4(t, a, p256_mod, p256_mp_mod);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_avx2_4(t2, t, 2, p256_mod, p256_mp_mod);
-    /* t3= a^d = t2 * a */
-    sp_256_mont_mul_avx2_4(t3, t2, a, p256_mod, p256_mp_mod);
-    /* t = a^f = t2 * t */
-    sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^f0 = t ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_avx2_4(t2, t, 4, p256_mod, p256_mp_mod);
-    /* t3= a^fd = t2 * t3 */
-    sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ff = t2 * t */
-    sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_avx2_4(t2, t, 8, p256_mod, p256_mp_mod);
-    /* t3= a^fffd = t2 * t3 */
-    sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_avx2_4(t2, t, 16, p256_mod, p256_mp_mod);
-    /* t3= a^fffffffd = t2 * t3 */
-    sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t = a^ffffffff00000000 = t ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_avx2_4(t2, t, 32, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001 = t2 * a */
-    sp_256_mont_mul_avx2_4(t2, t2, a, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff000000010000000000000000000000000000000000000000
-     *   = t2 ^ 2 ^ 160 */
-    sp_256_mont_sqr_n_avx2_4(t2, t2, 160, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff
-     *   = t2 * t */
-    sp_256_mont_mul_avx2_4(t2, t2, t, p256_mod, p256_mp_mod);
-    /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000
-     *   = t2 ^ 2 ^ 32 */
-    sp_256_mont_sqr_n_avx2_4(t2, t2, 32, p256_mod, p256_mp_mod);
-    /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd
-     *   = t2 * t3 */
-    sp_256_mont_mul_avx2_4(r, t2, t3, p256_mod, p256_mp_mod);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-/* Map the Montgomery form projective co-ordinate point to an affine point.
- *
- * r  Resulting affine co-ordinate point.
- * p  Montgomery form projective co-ordinate point.
- * t  Temporary ordinate data.
- */
-static void sp_256_map_avx2_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    int64_t n;
-
-    sp_256_mont_inv_avx2_4(t1, p->z, t + 2*4);
-
-    sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    /* x /= z^2 */
-    sp_256_mont_mul_avx2_4(r->x, p->x, t2, p256_mod, p256_mp_mod);
-    XMEMSET(r->x + 4, 0, sizeof(r->x) / 2);
-    sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod);
-    /* Reduce x to less than modulus */
-    n = sp_256_cmp_4(r->x, p256_mod);
-    sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->x);
-
-    /* y /= z^3 */
-    sp_256_mont_mul_avx2_4(r->y, p->y, t1, p256_mod, p256_mp_mod);
-    XMEMSET(r->y + 4, 0, sizeof(r->y) / 2);
-    sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod);
-    /* Reduce y to less than modulus */
-    n = sp_256_cmp_4(r->y, p256_mod);
-    sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0));
-    sp_256_norm_4(r->y);
-
-    XMEMSET(r->z, 0, sizeof(r->z));
-    r->z[0] = 1;
-
-}
-
-/* Double the Montgomery form projective point p.
- *
- * r  Result of doubling point.
- * p  Point to double.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_avx2_4(sp_point* r, sp_point* p, sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* When infinity don't double point passed in - constant time. */
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    /* Put point to double into result - good for infinty. */
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* T1 = Z * Z */
-    sp_256_mont_sqr_avx2_4(t1, z, p256_mod, p256_mp_mod);
-    /* Z = Y * Z */
-    sp_256_mont_mul_avx2_4(z, y, z, p256_mod, p256_mp_mod);
-    /* Z = 2Z */
-    sp_256_mont_dbl_4(z, z, p256_mod);
-    /* T2 = X - T1 */
-    sp_256_mont_sub_4(t2, x, t1, p256_mod);
-    /* T1 = X + T1 */
-    sp_256_mont_add_4(t1, x, t1, p256_mod);
-    /* T2 = T1 * T2 */
-    sp_256_mont_mul_avx2_4(t2, t1, t2, p256_mod, p256_mp_mod);
-    /* T1 = 3T2 */
-    sp_256_mont_tpl_4(t1, t2, p256_mod);
-    /* Y = 2Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* Y = Y * Y */
-    sp_256_mont_sqr_avx2_4(y, y, p256_mod, p256_mp_mod);
-    /* T2 = Y * Y */
-    sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod);
-    /* T2 = T2/2 */
-    sp_256_div2_4(t2, t2, p256_mod);
-    /* Y = Y * X */
-    sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod);
-    /* X = T1 * T1 */
-    sp_256_mont_mul_avx2_4(x, t1, t1, p256_mod, p256_mp_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* X = X - Y */
-    sp_256_mont_sub_4(x, x, y, p256_mod);
-    /* Y = Y - X */
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    /* Y = Y * T1 */
-    sp_256_mont_mul_avx2_4(y, y, t1, p256_mod, p256_mp_mod);
-    /* Y = Y - T2 */
-    sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_avx2_4(sp_point* r, sp_point* p, int n,
-        sp_digit* t)
-{
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    rp[0] = r;
-    rp[1] = &tp;
-    x = rp[p->infinity]->x;
-    y = rp[p->infinity]->y;
-    z = rp[p->infinity]->z;
-    if (r != p) {
-        for (i=0; i<4; i++)
-            r->x[i] = p->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = p->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = p->z[i];
-        r->infinity = p->infinity;
-    }
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod);
-    while (n--) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod);
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_avx2_4(z, z, y, p256_mod, p256_mp_mod);
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_avx2_4(t2, t2, p256_mod, p256_mp_mod);
-        if (n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_avx2_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-    }
-    /* Y = Y/2 */
-    sp_256_div2_4(y, y, p256_mod);
-}
-
-/* Add two Montgomery form projective points.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_avx2_4(sp_point* r, sp_point* p, sp_point* q,
-        sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Ensure only the first point is the same as the result. */
-    if (q == r) {
-        sp_point* a = p;
-        p = q;
-        q = a;
-    }
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U1 = X1*Z2^2 */
-        sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod);
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S1 = Y1*Z2^3 */
-        sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - U1 */
-        sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-        /* R = S2 - S1 */
-        sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-        /* Z3 = H*Z1*Z2 */
-        sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*U1*H^2 */
-        sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, x, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, y, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, y, t5, p256_mod);
-    }
-}
-
-/* Double the Montgomery form projective point p a number of times.
- *
- * r  Result of repeated doubling of point.
- * p  Point to double.
- * n  Number of times to double
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point* r, sp_point* p,
-        int n, int m, sp_digit* t)
-{
-    sp_digit* w = t;
-    sp_digit* a = t + 2*4;
-    sp_digit* b = t + 4*4;
-    sp_digit* t1 = t + 6*4;
-    sp_digit* t2 = t + 8*4;
-    sp_digit* x = r[2*m].x;
-    sp_digit* y = r[(1<<n)*m].y;
-    sp_digit* z = r[2*m].z;
-    int i;
-
-    for (i=0; i<4; i++)
-        x[i] = p->x[i];
-    for (i=0; i<4; i++)
-        y[i] = p->y[i];
-    for (i=0; i<4; i++)
-        z[i] = p->z[i];
-
-    /* Y = 2*Y */
-    sp_256_mont_dbl_4(y, y, p256_mod);
-    /* W = Z^4 */
-    sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod);
-    for (i=1; i<=n; i++) {
-        /* A = 3*(X^2 - W) */
-        sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(t1, t1, w, p256_mod);
-        sp_256_mont_tpl_4(a, t1, p256_mod);
-        /* B = X*Y^2 */
-        sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod);
-        x = r[(1<<i)*m].x;
-        /* X = A^2 - 2B */
-        sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(t1, b, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Z = Z*Y */
-        sp_256_mont_mul_avx2_4(r[(1<<i)*m].z, z, y, p256_mod, p256_mp_mod);
-        z = r[(1<<i)*m].z;
-        /* t2 = Y^4 */
-        sp_256_mont_sqr_avx2_4(t2, t2, p256_mod, p256_mp_mod);
-        if (i != n) {
-            /* W = W*Y^4 */
-            sp_256_mont_mul_avx2_4(w, w, t2, p256_mod, p256_mp_mod);
-        }
-        /* y = 2*A*(B - X) - Y^4 */
-        sp_256_mont_sub_4(y, b, x, p256_mod);
-        sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod);
-        sp_256_mont_dbl_4(y, y, p256_mod);
-        sp_256_mont_sub_4(y, y, t2, p256_mod);
-
-        /* Y = Y/2 */
-        sp_256_div2_4(r[(1<<i)*m].y, y, p256_mod);
-        r[(1<<i)*m].infinity = 0;
-    }
-}
-
-/* Add two Montgomery form projective points.
- *
- * ra  Result of addition.
- * rs  Result of subtraction.
- * p   Frist point to add.
- * q   Second point to add.
- * t   Temporary ordinate data.
- */
-static void sp_256_proj_point_add_sub_avx2_4(sp_point* ra, sp_point* rs,
-        sp_point* p, sp_point* q, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* t6 = t + 10*4;
-    sp_digit* x = ra->x;
-    sp_digit* y = ra->y;
-    sp_digit* z = ra->z;
-    sp_digit* xs = rs->x;
-    sp_digit* ys = rs->y;
-    sp_digit* zs = rs->z;
-
-
-    XMEMCPY(x, p->x, sizeof(p->x) / 2);
-    XMEMCPY(y, p->y, sizeof(p->y) / 2);
-    XMEMCPY(z, p->z, sizeof(p->z) / 2);
-    ra->infinity = 0;
-    rs->infinity = 0;
-
-    /* U1 = X1*Z2^2 */
-    sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod);
-    /* U2 = X2*Z1^2 */
-    sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-    /* S1 = Y1*Z2^3 */
-    sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod);
-    /* S2 = Y2*Z1^3 */
-    sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-    /* H = U2 - U1 */
-    sp_256_mont_sub_4(t2, t2, t1, p256_mod);
-    /* RS = S2 + S1 */
-    sp_256_mont_add_4(t6, t4, t3, p256_mod);
-    /* R = S2 - S1 */
-    sp_256_mont_sub_4(t4, t4, t3, p256_mod);
-    /* Z3 = H*Z1*Z2 */
-    /* ZS = H*Z1*Z2 */
-    sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod);
-    XMEMCPY(zs, z, sizeof(p->z)/2);
-    /* X3 = R^2 - H^3 - 2*U1*H^2 */
-    /* XS = RS^2 - H^3 - 2*U1*H^2 */
-    sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_avx2_4(xs, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(x, x, t5, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t5, p256_mod);
-    sp_256_mont_dbl_4(t1, y, p256_mod);
-    sp_256_mont_sub_4(x, x, t1, p256_mod);
-    sp_256_mont_sub_4(xs, xs, t1, p256_mod);
-    /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
-    /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
-    sp_256_mont_sub_4(ys, y, xs, p256_mod);
-    sp_256_mont_sub_4(y, y, x, p256_mod);
-    sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod);
-    sp_256_sub_4(t6, p256_mod, t6);
-    sp_256_mont_mul_avx2_4(ys, ys, t6, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod);
-    sp_256_mont_sub_4(y, y, t5, p256_mod);
-    sp_256_mont_sub_4(ys, ys, t5, p256_mod);
-}
-
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point* r, sp_point* g,
-        sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[33];
-    sp_point rtd, pd;
-    sp_digit tmpd[2 * 4 * 6];
-#endif
-    sp_point* t;
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode v[43];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-
-
-    if (err == MP_OKAY) {
-        /* t[0] = {0, 0, 1} * norm */
-        XMEMSET(&t[0], 0, sizeof(t[0]));
-        t[0].infinity = 1;
-        /* t[1] = {g->x, g->y, g->z} * norm */
-        err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod);
-
-    if (err == MP_OKAY) {
-        t[1].infinity = 0;
-        /* t[2] ... t[32]  */
-    sp_256_proj_point_dbl_n_store_avx2_4(t, &t[ 1], 5, 1, tmp);
-    sp_256_proj_point_add_avx2_4(&t[ 3], &t[ 2], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[ 6], &t[ 3], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[10], &t[ 5], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[12], &t[ 6], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[14], &t[ 7], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[15], &t[13], &t[14], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[18], &t[ 9], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[19], &t[17], &t[18], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[20], &t[10], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[22], &t[11], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[23], &t[21], &t[22], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[24], &t[12], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[26], &t[13], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[27], &t[25], &t[26], &t[ 1], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[28], &t[14], tmp);
-    sp_256_proj_point_dbl_avx2_4(&t[30], &t[15], tmp);
-    sp_256_proj_point_add_sub_avx2_4(&t[31], &t[29], &t[30], &t[ 1], tmp);
-
-        negy = t[0].y;
-
-        sp_256_ecc_recode_6_4(k, v);
-
-        i = 42;
-        XMEMCPY(rt, &t[v[i].i], sizeof(sp_point));
-        for (--i; i>=0; i--) {
-            sp_256_proj_point_dbl_n_avx2_4(rt, rt, 6, tmp);
-
-            XMEMCPY(p, &t[v[i].i], sizeof(sp_point));
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_avx2_4(rt, rt, p, tmp);
-        }
-
-        if (map)
-            sp_256_map_avx2_4(r, rt, tmp);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    if (tmp != NULL)
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry {
-    sp_digit x[4];
-    sp_digit y[4];
-    byte infinity;
-} sp_table_entry;
-
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_4(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_4(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_4(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_4(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, t3, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_4(t3, t3, x, p256_mod);
-        sp_256_mont_mul_4(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_4(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 4;
-    sp_digit* tmp = t + 4 * 4;
-
-    sp_256_mont_inv_4(t1, a->z, tmp);
-
-    sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_4(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_4(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_4(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_4(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_4(t, t, 32, tmp);
-            sp_256_proj_to_affine_4(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_4(t, s1, s2, tmp);
-                sp_256_proj_to_affine_4(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_4(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 4 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-
-            sp_256_proj_point_dbl_4(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_4(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_4(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-#ifdef FP_ECC
-#ifndef FP_ENTRIES
-    #define FP_ENTRIES 16
-#endif
-
-typedef struct sp_cache_t {
-    sp_digit x[4];
-    sp_digit y[4];
-    sp_table_entry table[256];
-    uint32_t cnt;
-    int set;
-} sp_cache_t;
-
-static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES];
-static THREAD_LS_T int sp_cache_last = -1;
-static THREAD_LS_T int sp_cache_inited = 0;
-
-#ifndef HAVE_THREAD_LS
-    static volatile int initCacheMutex = 0;
-    static wolfSSL_Mutex sp_cache_lock;
-#endif
-
-static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache)
-{
-    int i, j;
-    uint32_t least;
-
-    if (sp_cache_inited == 0) {
-        for (i=0; i<FP_ENTRIES; i++) {
-            sp_cache[i].set = 0;
-        }
-        sp_cache_inited = 1;
-    }
-
-    /* Compare point with those in cache. */
-    for (i=0; i<FP_ENTRIES; i++) {
-        if (!sp_cache[i].set)
-            continue;
-
-        if (sp_256_cmp_equal_4(g->x, sp_cache[i].x) & 
-                           sp_256_cmp_equal_4(g->y, sp_cache[i].y)) {
-            sp_cache[i].cnt++;
-            break;
-        }
-    }
-
-    /* No match. */
-    if (i == FP_ENTRIES) {
-        /* Find empty entry. */
-        i = (sp_cache_last + 1) % FP_ENTRIES;
-        for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) {
-            if (!sp_cache[i].set) {
-                break;
-            }
-        }
-
-        /* Evict least used. */
-        if (i == sp_cache_last) {
-            least = sp_cache[0].cnt;
-            for (j=1; j<FP_ENTRIES; j++) {
-                if (sp_cache[j].cnt < least) {
-                    i = j;
-                    least = sp_cache[i].cnt;
-                }
-            }
-        }
-
-        XMEMCPY(sp_cache[i].x, g->x, sizeof(sp_cache[i].x));
-        XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y));
-        sp_cache[i].set = 1;
-        sp_cache[i].cnt = 1;
-    }
-
-    *cache = &sp_cache[i];
-    sp_cache_last = i;
-}
-#endif /* FP_ECC */
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_4(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 4 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_4(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_4(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#ifdef HAVE_INTEL_AVX2
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-/* Add two Montgomery form projective points. The second point has a q value of
- * one.
- * Only the first point can be the same pointer as the result point.
- *
- * r  Result of addition.
- * p  Frist point to add.
- * q  Second point to add.
- * t  Temporary ordinate data.
- */
-static void sp_256_proj_point_add_qz1_avx2_4(sp_point* r, sp_point* p,
-        sp_point* q, sp_digit* t)
-{
-    sp_point *ap[2];
-    sp_point *rp[2];
-    sp_point tp;
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2*4;
-    sp_digit* t3 = t + 4*4;
-    sp_digit* t4 = t + 6*4;
-    sp_digit* t5 = t + 8*4;
-    sp_digit* x;
-    sp_digit* y;
-    sp_digit* z;
-    int i;
-
-    /* Check double */
-    sp_256_sub_4(t1, p256_mod, q->y);
-    sp_256_norm_4(t1);
-    if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) &
-        (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) {
-        sp_256_proj_point_dbl_4(r, p, t);
-    }
-    else {
-        rp[0] = r;
-        rp[1] = &tp;
-        XMEMSET(&tp, 0, sizeof(tp));
-        x = rp[p->infinity | q->infinity]->x;
-        y = rp[p->infinity | q->infinity]->y;
-        z = rp[p->infinity | q->infinity]->z;
-
-        ap[0] = p;
-        ap[1] = q;
-        for (i=0; i<4; i++)
-            r->x[i] = ap[p->infinity]->x[i];
-        for (i=0; i<4; i++)
-            r->y[i] = ap[p->infinity]->y[i];
-        for (i=0; i<4; i++)
-            r->z[i] = ap[p->infinity]->z[i];
-        r->infinity = ap[p->infinity]->infinity;
-
-        /* U2 = X2*Z1^2 */
-        sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod);
-        /* S2 = Y2*Z1^3 */
-        sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod);
-        /* H = U2 - X1 */
-        sp_256_mont_sub_4(t2, t2, x, p256_mod);
-        /* R = S2 - Y1 */
-        sp_256_mont_sub_4(t4, t4, y, p256_mod);
-        /* Z3 = H*Z1 */
-        sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod);
-        /* X3 = R^2 - H^3 - 2*X1*H^2 */
-        sp_256_mont_sqr_avx2_4(t1, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t3, x, t5, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(x, t1, t5, p256_mod);
-        sp_256_mont_dbl_4(t1, t3, p256_mod);
-        sp_256_mont_sub_4(x, x, t1, p256_mod);
-        /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
-        sp_256_mont_sub_4(t3, t3, x, p256_mod);
-        sp_256_mont_mul_avx2_4(t3, t3, t4, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_avx2_4(t5, t5, y, p256_mod, p256_mp_mod);
-        sp_256_mont_sub_4(y, t3, t5, p256_mod);
-    }
-}
-
-#ifdef FP_ECC
-/* Convert the projective point to affine.
- * Ordinates are in Montgomery form.
- *
- * a  Point to convert.
- * t  Temprorary data.
- */
-static void sp_256_proj_to_affine_avx2_4(sp_point* a, sp_digit* t)
-{
-    sp_digit* t1 = t;
-    sp_digit* t2 = t + 2 * 4;
-    sp_digit* tmp = t + 4 * 4;
-
-    sp_256_mont_inv_avx2_4(t1, a->z, tmp);
-
-    sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod);
-
-    sp_256_mont_mul_avx2_4(a->x, a->x, t2, p256_mod, p256_mp_mod);
-    sp_256_mont_mul_avx2_4(a->y, a->y, t1, p256_mod, p256_mp_mod);
-    XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
-}
-
-/* Generate the pre-computed table of points for the base point.
- *
- * a      The base point.
- * table  Place to store generated point data.
- * tmp    Temprorary data.
- * heap  Heap to use for allocation.
- */
-static int sp_256_gen_stripe_table_avx2_4(sp_point* a,
-        sp_table_entry* table, sp_digit* tmp, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td, s1d, s2d;
-#endif
-    sp_point* t;
-    sp_point* s1 = NULL;
-    sp_point* s2 = NULL;
-    int i, j;
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, td, t);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s1d, s1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, s2d, s2);
-
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod);
-    if (err == MP_OKAY)
-        err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod);
-    if (err == MP_OKAY) {
-        t->infinity = 0;
-        sp_256_proj_to_affine_avx2_4(t, tmp);
-
-        XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s1->infinity = 0;
-        XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
-        s2->infinity = 0;
-
-        /* table[0] = {0, 0, infinity} */
-        XMEMSET(&table[0], 0, sizeof(sp_table_entry));
-        table[0].infinity = 1;
-        /* table[1] = Affine version of 'a' in Montgomery form */
-        XMEMCPY(table[1].x, t->x, sizeof(table->x));
-        XMEMCPY(table[1].y, t->y, sizeof(table->y));
-        table[1].infinity = 0;
-
-        for (i=1; i<8; i++) {
-            sp_256_proj_point_dbl_n_avx2_4(t, t, 32, tmp);
-            sp_256_proj_to_affine_avx2_4(t, tmp);
-            XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
-            XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
-            table[1<<i].infinity = 0;
-        }
-
-        for (i=1; i<8; i++) {
-            XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
-            XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
-            for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
-                XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
-                XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
-                sp_256_proj_point_add_qz1_avx2_4(t, s1, s2, tmp);
-                sp_256_proj_to_affine_avx2_4(t, tmp);
-                XMEMCPY(table[j].x, t->x, sizeof(table->x));
-                XMEMCPY(table[j].y, t->y, sizeof(table->y));
-                table[j].infinity = 0;
-            }
-        }
-    }
-
-    sp_ecc_point_free(s2, 0, heap);
-    sp_ecc_point_free(s1, 0, heap);
-    sp_ecc_point_free( t, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC */
-#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL)
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point* r, sp_point* g,
-        sp_table_entry* table, sp_digit* k, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point rtd;
-    sp_point pd;
-    sp_digit td[2 * 4 * 5];
-#endif
-    sp_point* rt;
-    sp_point* p = NULL;
-    sp_digit* t;
-    int i, j;
-    int y, x;
-    int err;
-
-    (void)g;
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, rtd, rt);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                           DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-#endif
-
-    if (err == MP_OKAY) {
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
-
-        y = 0;
-        for (j=0,x=31; j<8; j++,x+=32)
-            y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-        XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
-        XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
-        rt->infinity = table[y].infinity;
-        for (i=30; i>=0; i--) {
-            y = 0;
-            for (j=0,x=i; j<8; j++,x+=32)
-                y |= ((k[x / 64] >> (x % 64)) & 1) << j;
-
-            sp_256_proj_point_dbl_avx2_4(rt, rt, t);
-            XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
-            XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
-            p->infinity = table[y].infinity;
-            sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, t);
-        }
-
-        if (map)
-            sp_256_map_avx2_4(r, rt, t);
-        else
-            XMEMCPY(r, rt, sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL)
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(rt, 0, heap);
-
-    return err;
-}
-
-#endif /* FP_ECC || WOLFSSL_SP_SMALL */
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * g     Point to multiply.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_avx2_4(sp_point* r, sp_point* g, sp_digit* k,
-        int map, void* heap)
-{
-#ifndef FP_ECC
-    return sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap);
-#else
-    sp_digit tmp[2 * 4 * 5];
-    sp_cache_t* cache;
-    int err = MP_OKAY;
-
-#ifndef HAVE_THREAD_LS
-    if (initCacheMutex == 0) {
-         wc_InitMutex(&sp_cache_lock);
-         initCacheMutex = 1;
-    }
-    if (wc_LockMutex(&sp_cache_lock) != 0)
-       err = BAD_MUTEX_E;
-#endif /* HAVE_THREAD_LS */
-
-    if (err == MP_OKAY) {
-        sp_ecc_get_cache(g, &cache);
-        if (cache->cnt == 2)
-            sp_256_gen_stripe_table_avx2_4(g, cache->table, tmp, heap);
-
-#ifndef HAVE_THREAD_LS
-        wc_UnLockMutex(&sp_cache_lock);
-#endif /* HAVE_THREAD_LS */
-
-        if (cache->cnt < 2) {
-            err = sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap);
-        }
-        else {
-            err = sp_256_ecc_mulmod_stripe_avx2_4(r, g, cache->table, k,
-                    map, heap);
-        }
-    }
-
-    return err;
-#endif
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-/* Multiply the point by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * p     Point to multiply.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, km);
-        sp_256_point_from_ecc_point_4(point, gm);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(point, point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(point, point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#ifdef WOLFSSL_SP_SMALL
-static sp_table_entry p256_table[256] = {
-    /* 0 */
-    { { 0x00, 0x00, 0x00, 0x00 },
-      { 0x00, 0x00, 0x00, 0x00 },
-      1 },
-    /* 1 */
-    { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l,
-        0x18905f76a53755c6l },
-      { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l,
-        0x8571ff1825885d85l },
-      0 },
-    /* 2 */
-    { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l,
-        0xd953c50ddbdf58e9l },
-      { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl,
-        0x863ebb7e9eb288f3l },
-      0 },
-    /* 3 */
-    { { 0x7856b6235cdb6485l,0x808f0ea22f0a2f97l,0x3e68d9544f7e300bl,
-        0x00076055b5ff80a0l },
-      { 0x7634eb9b838d2010l,0x54014fbb3243708al,0xe0e47d39842a6606l,
-        0x8308776134373ee0l },
-      0 },
-    /* 4 */
-    { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl,
-        0x2f5e6961fd1b667fl },
-      { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l,
-        0xf648f9168d6f0f7bl },
-      0 },
-    /* 5 */
-    { { 0x9e566847e137bbbcl,0xe434469e8a6a0becl,0xb1c4276179d73463l,
-        0x5abe0285133d0015l },
-      { 0x92aa837cc04c7dabl,0x573d9f4c43260c07l,0x0c93156278e6cc37l,
-        0x94bb725b6b6f7383l },
-      0 },
-    /* 6 */
-    { { 0xbbf9b48f720f141cl,0x6199b3cd2df5bc74l,0xdc3f6129411045c4l,
-        0xcdd6bbcb2f7dc4efl },
-      { 0xcca6700beaf436fdl,0x6f647f6db99326bel,0x0c0fa792014f2522l,
-        0xa361bebd4bdae5f6l },
-      0 },
-    /* 7 */
-    { { 0x28aa2558597c13c7l,0xc38d635f50b7c3e1l,0x07039aecf3c09d1dl,
-        0xba12ca09c4b5292cl },
-      { 0x9e408fa459f91dfdl,0x3af43b66ceea07fbl,0x1eceb0899d780b29l,
-        0x53ebb99d701fef4bl },
-      0 },
-    /* 8 */
-    { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l,
-        0x8589fb9206d54831l },
-      { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l,
-        0xebb0696d02541c4fl },
-      0 },
-    /* 9 */
-    { { 0x4616ca15ac1647c5l,0xb8127d47c4cf5799l,0xdc666aa3764dfbacl,
-        0xeb2820cbd1b27da3l },
-      { 0x9406f8d86a87e008l,0xd87dfa9d922378f3l,0x56ed2e4280ccecb2l,
-        0x1f28289b55a7da1dl },
-      0 },
-    /* 10 */
-    { { 0xabbaa0c03b89da99l,0xa6f2d79eb8284022l,0x27847862b81c05e8l,
-        0x337a4b5905e54d63l },
-      { 0x3c67500d21f7794al,0x207005b77d6d7f61l,0x0a5a378104cfd6e8l,
-        0x0d65e0d5f4c2fbd6l },
-      0 },
-    /* 11 */
-    { { 0xd9d09bbeb5275d38l,0x4268a7450be0a358l,0xf0762ff4973eb265l,
-        0xc23da24252f4a232l },
-      { 0x5da1b84f0b94520cl,0x09666763b05bd78el,0x3a4dcb8694d29ea1l,
-        0x19de3b8cc790cff1l },
-      0 },
-    /* 12 */
-    { { 0x183a716c26c5fe04l,0x3b28de0b3bba1bdbl,0x7432c586a4cb712cl,
-        0xe34dcbd491fccbfdl },
-      { 0xb408d46baaa58403l,0x9a69748682e97a53l,0x9e39012736aaa8afl,
-        0xe7641f447b4e0f7fl },
-      0 },
-    /* 13 */
-    { { 0x7d753941df64ba59l,0xd33f10ec0b0242fcl,0x4f06dfc6a1581859l,
-        0x4a12df57052a57bfl },
-      { 0xbfa6338f9439dbd0l,0xd3c24bd4bde53e1fl,0xfd5e4ffa21f1b314l,
-        0x6af5aa93bb5bea46l },
-      0 },
-    /* 14 */
-    { { 0xda10b69910c91999l,0x0a24b4402a580491l,0x3e0094b4b8cc2090l,
-        0x5fe3475a66a44013l },
-      { 0xb0f8cabdf93e7b4bl,0x292b501a7c23f91al,0x42e889aecd1e6263l,
-        0xb544e308ecfea916l },
-      0 },
-    /* 15 */
-    { { 0x6478c6e916ddfdcel,0x2c329166f89179e6l,0x4e8d6e764d4e67e1l,
-        0xe0b6b2bda6b0c20bl },
-      { 0x0d312df2bb7efb57l,0x1aac0dde790c4007l,0xf90336ad679bc944l,
-        0x71c023de25a63774l },
-      0 },
-    /* 16 */
-    { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l,
-        0x61d587d421d324f6l },
-      { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el,
-        0xfa11fe124621efbel },
-      0 },
-    /* 17 */
-    { { 0x1c891f2b2cb19ffdl,0x01ba8d5bb1923c23l,0xb6d03d678ac5ca8el,
-        0x586eb04c1f13bedcl },
-      { 0x0c35c6e527e8ed09l,0x1e81a33c1819ede2l,0x278fd6c056c652fal,
-        0x19d5ac0870864f11l },
-      0 },
-    /* 18 */
-    { { 0x1e99f581309a4e1fl,0xab7de71be9270074l,0x26a5ef0befd28d20l,
-        0xe7c0073f7f9c563fl },
-      { 0x1f6d663a0ef59f76l,0x669b3b5420fcb050l,0xc08c1f7a7a6602d4l,
-        0xe08504fec65b3c0al },
-      0 },
-    /* 19 */
-    { { 0xf098f68da031b3cal,0x6d1cab9ee6da6d66l,0x5bfd81fa94f246e8l,
-        0x78f018825b0996b4l },
-      { 0xb7eefde43a25787fl,0x8016f80d1dccac9bl,0x0cea4877b35bfc36l,
-        0x43a773b87e94747al },
-      0 },
-    /* 20 */
-    { { 0x62577734d2b533d5l,0x673b8af6a1bdddc0l,0x577e7c9aa79ec293l,
-        0xbb6de651c3b266b1l },
-      { 0xe7e9303ab65259b3l,0xd6a0afd3d03a7480l,0xc5ac83d19b3cfc27l,
-        0x60b4619a5d18b99bl },
-      0 },
-    /* 21 */
-    { { 0xbd6a38e11ae5aa1cl,0xb8b7652b49e73658l,0x0b130014ee5f87edl,
-        0x9d0f27b2aeebffcdl },
-      { 0xca9246317a730a55l,0x9c955b2fddbbc83al,0x07c1dfe0ac019a71l,
-        0x244a566d356ec48dl },
-      0 },
-    /* 22 */
-    { { 0x6db0394aeacf1f96l,0x9f2122a9024c271cl,0x2626ac1b82cbd3b9l,
-        0x45e58c873581ef69l },
-      { 0xd3ff479da38f9dbcl,0xa8aaf146e888a040l,0x945adfb246e0bed7l,
-        0xc040e21cc1e4b7a4l },
-      0 },
-    /* 23 */
-    { { 0x847af0006f8117b6l,0x651969ff73a35433l,0x482b35761d9475ebl,
-        0x1cdf5c97682c6ec7l },
-      { 0x7db775b411f04839l,0x7dbeacf448de1698l,0xb2921dd1b70b3219l,
-        0x046755f8a92dff3dl },
-      0 },
-    /* 24 */
-    { { 0xcc8ac5d2bce8ffcdl,0x0d53c48b2fe61a82l,0xf6f161727202d6c7l,
-        0x046e5e113b83a5f3l },
-      { 0xe7b8ff64d8007f01l,0x7fb1ef125af43183l,0x045c5ea635e1a03cl,
-        0x6e0106c3303d005bl },
-      0 },
-    /* 25 */
-    { { 0x48c7358488dd73b1l,0x7670708f995ed0d9l,0x38385ea8c56a2ab7l,
-        0x442594ede901cf1fl },
-      { 0xf8faa2c912d4b65bl,0x94c2343b96c90c37l,0xd326e4a15e978d1fl,
-        0xa796fa514c2ee68el },
-      0 },
-    /* 26 */
-    { { 0x359fb604823addd7l,0x9e2a6183e56693b3l,0xf885b78e3cbf3c80l,
-        0xe4ad2da9c69766e9l },
-      { 0x357f7f428e048a61l,0x082d198cc092d9a0l,0xfc3a1af4c03ed8efl,
-        0xc5e94046c37b5143l },
-      0 },
-    /* 27 */
-    { { 0x476a538c2be75f9el,0x6fd1a9e8cb123a78l,0xd85e4df0b109c04bl,
-        0x63283dafdb464747l },
-      { 0xce728cf7baf2df15l,0xe592c4550ad9a7f4l,0xfab226ade834bcc3l,
-        0x68bd19ab1981a938l },
-      0 },
-    /* 28 */
-    { { 0xc08ead511887d659l,0x3374d5f4b359305al,0x96986981cfe74fe3l,
-        0x495292f53c6fdfd6l },
-      { 0x4a878c9e1acec896l,0xd964b210ec5b4484l,0x6696f7e2664d60a7l,
-        0x0ec7530d26036837l },
-      0 },
-    /* 29 */
-    { { 0x2da13a05ad2687bbl,0xa1f83b6af32e21fal,0x390f5ef51dd4607bl,
-        0x0f6207a664863f0bl },
-      { 0xbd67e3bb0f138233l,0xdd66b96c272aa718l,0x8ed0040726ec88ael,
-        0xff0db07208ed6dcfl },
-      0 },
-    /* 30 */
-    { { 0x749fa1014c95d553l,0xa44052fd5d680a8al,0x183b4317ff3b566fl,
-        0x313b513c88740ea3l },
-      { 0xb402e2ac08d11549l,0x071ee10bb4dee21cl,0x26b987dd47f2320el,
-        0x2d3abcf986f19f81l },
-      0 },
-    /* 31 */
-    { { 0x4c288501815581a2l,0x9a0a6d56632211afl,0x19ba7a0f0cab2e99l,
-        0xc036fa10ded98cdfl },
-      { 0x29ae08bac1fbd009l,0x0b68b19006d15816l,0xc2eb32779b9e0d8fl,
-        0xa6b2a2c4b6d40194l },
-      0 },
-    /* 32 */
-    { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l,
-        0x810ee252af7c9860l },
-      { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l,
-        0xd485717a92731745l },
-      0 },
-    /* 33 */
-    { { 0x11741a8af0cb5a98l,0xd3da8f931f3110bfl,0x1994e2cbab382adfl,
-        0x6a6045a72f9a604el },
-      { 0x170c0d3fa2b2411dl,0xbe0eb83e510e96e0l,0x3bcc9f738865b3ccl,
-        0xd3e45cfaf9e15790l },
-      0 },
-    /* 34 */
-    { { 0xce1f69bbe83f7669l,0x09f8ae8272877d6bl,0x9548ae543244278dl,
-        0x207755dee3c2c19cl },
-      { 0x87bd61d96fef1945l,0x18813cefb12d28c3l,0x9fbcd1d672df64aal,
-        0x48dc5ee57154b00dl },
-      0 },
-    /* 35 */
-    { { 0x123790bff7e5a199l,0xe0efb8cf989ccbb7l,0xc27a2bfe0a519c79l,
-        0xf2fb0aeddff6f445l },
-      { 0x41c09575f0b5025fl,0x550543d740fa9f22l,0x8fa3c8ad380bfbd0l,
-        0xa13e9015db28d525l },
-      0 },
-    /* 36 */
-    { { 0xf9f7a350a2b65cbcl,0x0b04b9722a464226l,0x265ce241e23f07a1l,
-        0x2bf0d6b01497526fl },
-      { 0xd3d4dd3f4b216fb7l,0xf7d7b867fbdda26al,0xaeb7b83f6708505cl,
-        0x42a94a5a162fe89fl },
-      0 },
-    /* 37 */
-    { { 0x5846ad0beaadf191l,0x0f8a489025a268d7l,0xe8603050494dc1f6l,
-        0x2c2dd969c65ede3dl },
-      { 0x6d02171d93849c17l,0x460488ba1da250ddl,0x4810c7063c3a5485l,
-        0xf437fa1f42c56dbcl },
-      0 },
-    /* 38 */
-    { { 0x6aa0d7144a0f7dabl,0x0f0497931776e9acl,0x52c0a050f5f39786l,
-        0xaaf45b3354707aa8l },
-      { 0x85e37c33c18d364al,0xd40b9b063e497165l,0xf417168115ec5444l,
-        0xcdf6310df4f272bcl },
-      0 },
-    /* 39 */
-    { { 0x7473c6238ea8b7efl,0x08e9351885bc2287l,0x419567722bda8e34l,
-        0xf0d008bada9e2ff2l },
-      { 0x2912671d2414d3b1l,0xb3754985b019ea76l,0x5c61b96d453bcbdbl,
-        0x5bd5c2f5ca887b8bl },
-      0 },
-    /* 40 */
-    { { 0xef0f469ef49a3154l,0x3e85a5956e2b2e9al,0x45aaec1eaa924a9cl,
-        0xaa12dfc8a09e4719l },
-      { 0x26f272274df69f1dl,0xe0e4c82ca2ff5e73l,0xb9d8ce73b7a9dd44l,
-        0x6c036e73e48ca901l },
-      0 },
-    /* 41 */
-    { { 0x5cfae12a0f6e3138l,0x6966ef0025ad345al,0x8993c64b45672bc5l,
-        0x292ff65896afbe24l },
-      { 0xd5250d445e213402l,0xf6580e274392c9fel,0x097b397fda1c72e8l,
-        0x644e0c90311b7276l },
-      0 },
-    /* 42 */
-    { { 0xe1e421e1a47153f0l,0xb86c3b79920418c9l,0x93bdce87705d7672l,
-        0xf25ae793cab79a77l },
-      { 0x1f3194a36d869d0cl,0x9d55c8824986c264l,0x49fb5ea3096e945el,
-        0x39b8e65313db0a3el },
-      0 },
-    /* 43 */
-    { { 0x37754200b6fd2e59l,0x35e2c0669255c98fl,0xd9dab21a0e2a5739l,
-        0x39122f2f0f19db06l },
-      { 0xcfbce1e003cad53cl,0x225b2c0fe65c17e3l,0x72baf1d29aa13877l,
-        0x8de80af8ce80ff8dl },
-      0 },
-    /* 44 */
-    { { 0xafbea8d9207bbb76l,0x921c7e7c21782758l,0xdfa2b74b1c0436b1l,
-        0x871949062e368c04l },
-      { 0xb5f928bba3993df5l,0x639d75b5f3b3d26al,0x011aa78a85b55050l,
-        0xfc315e6a5b74fde1l },
-      0 },
-    /* 45 */
-    { { 0x561fd41ae8d6ecfal,0x5f8c44f61aec7f86l,0x98452a7b4924741dl,
-        0xe6d4a7adee389088l },
-      { 0x60552ed14593c75dl,0x70a70da4dd271162l,0xd2aede937ba2c7dbl,
-        0x35dfaf9a9be2ae57l },
-      0 },
-    /* 46 */
-    { { 0x6b956fcdaa736636l,0x09f51d97ae2cab7el,0xfb10bf410f349966l,
-        0x1da5c7d71c830d2bl },
-      { 0x5c41e4833cce6825l,0x15ad118ff9573c3bl,0xa28552c7f23036b8l,
-        0x7077c0fddbf4b9d6l },
-      0 },
-    /* 47 */
-    { { 0xbf63ff8d46b9661cl,0xa1dfd36b0d2cfd71l,0x0373e140a847f8f7l,
-        0x53a8632ee50efe44l },
-      { 0x0976ff68696d8051l,0xdaec0c95c74f468al,0x62994dc35e4e26bdl,
-        0x028ca76d34e1fcc1l },
-      0 },
-    /* 48 */
-    { { 0xd11d47dcfc9877eel,0xc8b36210801d0002l,0xd002c11754c260b6l,
-        0x04c17cd86962f046l },
-      { 0x6d9bd094b0daddf5l,0xbea2357524ce55c0l,0x663356e672da03b5l,
-        0xf7ba4de9fed97474l },
-      0 },
-    /* 49 */
-    { { 0xd0dbfa34ebe1263fl,0x5576373571ae7ce6l,0xd244055382a6f523l,
-        0xe31f960052131c41l },
-      { 0xd1bb9216ea6b6ec6l,0x37a1d12e73c2fc44l,0xc10e7eac89d0a294l,
-        0xaa3a6259ce34d47bl },
-      0 },
-    /* 50 */
-    { { 0xfbcf9df536f3dcd3l,0x6ceded50d2bf7360l,0x491710fadf504f5bl,
-        0x2398dd627e79daeel },
-      { 0xcf4705a36d09569el,0xea0619bb5149f769l,0xff9c037735f6034cl,
-        0x5717f5b21c046210l },
-      0 },
-    /* 51 */
-    { { 0x9fe229c921dd895el,0x8e51850040c28451l,0xfa13d2391d637ecdl,
-        0x660a2c560e3c28del },
-      { 0x9cca88aed67fcbd0l,0xc84724780ea9f096l,0x32b2f48172e92b4dl,
-        0x624ee54c4f522453l },
-      0 },
-    /* 52 */
-    { { 0x09549ce4d897ecccl,0x4d49d1d93f9880aal,0x723c2423043a7c20l,
-        0x4f392afb92bdfbc0l },
-      { 0x6969f8fa7de44fd9l,0xb66cfbe457b32156l,0xdb2fa803368ebc3cl,
-        0x8a3e7977ccdb399cl },
-      0 },
-    /* 53 */
-    { { 0xdde1881f06c4b125l,0xae34e300f6e3ca8cl,0xef6999de5c7a13e9l,
-        0x3888d02370c24404l },
-      { 0x7628035644f91081l,0x3d9fcf615f015504l,0x1827edc8632cd36el,
-        0xa5e62e4718102336l },
-      0 },
-    /* 54 */
-    { { 0x1a825ee32facd6c8l,0x699c635454bcbc66l,0x0ce3edf798df9931l,
-        0x2c4768e6466a5adcl },
-      { 0xb346ff8c90a64bc9l,0x630a6020e4779f5cl,0xd949d064bc05e884l,
-        0x7b5e6441f9e652a0l },
-      0 },
-    /* 55 */
-    { { 0x2169422c1d28444al,0xe996c5d8be136a39l,0x2387afe5fb0c7fcel,
-        0xb8af73cb0c8d744al },
-      { 0x5fde83aa338b86fdl,0xfee3f158a58a5cffl,0xc9ee8f6f20ac9433l,
-        0xa036395f7f3f0895l },
-      0 },
-    /* 56 */
-    { { 0x8c73c6bba10f7770l,0xa6f16d81a12a0e24l,0x100df68251bc2b9fl,
-        0x4be36b01875fb533l },
-      { 0x9226086e9fb56dbbl,0x306fef8b07e7a4f8l,0xeeaccc0566d52f20l,
-        0x8cbc9a871bdc00c0l },
-      0 },
-    /* 57 */
-    { { 0xe131895cc0dac4abl,0xa874a440712ff112l,0x6332ae7c6a1cee57l,
-        0x44e7553e0c0835f8l },
-      { 0x6d503fff7734002dl,0x9d35cb8b0b34425cl,0x95f702760e8738b5l,
-        0x470a683a5eb8fc18l },
-      0 },
-    /* 58 */
-    { { 0x81b761dc90513482l,0x0287202a01e9276al,0xcda441ee0ce73083l,
-        0x16410690c63dc6efl },
-      { 0xf5034a066d06a2edl,0xdd4d7745189b100bl,0xd914ae72ab8218c9l,
-        0xd73479fd7abcbb4fl },
-      0 },
-    /* 59 */
-    { { 0x7edefb165ad4c6e5l,0x262cf08f5b06d04dl,0x12ed5bb18575cb14l,
-        0x816469e30771666bl },
-      { 0xd7ab9d79561e291el,0xeb9daf22c1de1661l,0xf49827eb135e0513l,
-        0x0a36dd23f0dd3f9cl },
-      0 },
-    /* 60 */
-    { { 0x098d32c741d5533cl,0x7c5f5a9e8684628fl,0x39a228ade349bd11l,
-        0xe331dfd6fdbab118l },
-      { 0x5100ab686bcc6ed8l,0x7160c3bdef7a260el,0x9063d9a7bce850d7l,
-        0xd3b4782a492e3389l },
-      0 },
-    /* 61 */
-    { { 0xa149b6e8f3821f90l,0x92edd9ed66eb7aadl,0x0bb669531a013116l,
-        0x7281275a4c86a5bdl },
-      { 0x503858f7d3ff47e5l,0x5e1616bc61016441l,0x62b0f11a7dfd9bb1l,
-        0x2c062e7ece145059l },
-      0 },
-    /* 62 */
-    { { 0xa76f996f0159ac2el,0x281e7736cbdb2713l,0x2ad6d28808e46047l,
-        0x282a35f92c4e7ef1l },
-      { 0x9c354b1ec0ce5cd2l,0xcf99efc91379c229l,0x992caf383e82c11el,
-        0xc71cd513554d2abdl },
-      0 },
-    /* 63 */
-    { { 0x4885de9c09b578f4l,0x1884e258e3affa7al,0x8f76b1b759182f1fl,
-        0xc50f6740cf47f3a3l },
-      { 0xa9c4adf3374b68eal,0xa406f32369965fe2l,0x2f86a22285a53050l,
-        0xb9ecb3a7212958dcl },
-      0 },
-    /* 64 */
-    { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l,
-        0x803f3e02cd42ab1bl },
-      { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl,
-        0xc097440e5067adc1l },
-      0 },
-    /* 65 */
-    { { 0x846a56f2c379ab34l,0xa8ee068b841df8d1l,0x20314459176c68efl,
-        0xf1af32d5915f1f30l },
-      { 0x99c375315d75bd50l,0x837cffbaf72f67bcl,0x0613a41848d7723fl,
-        0x23d0f130e2d41c8bl },
-      0 },
-    /* 66 */
-    { { 0x857ab6edf41500d9l,0x0d890ae5fcbeada8l,0x52fe864889725951l,
-        0xb0288dd6c0a3faddl },
-      { 0x85320f30650bcb08l,0x71af6313695d6e16l,0x31f520a7b989aa76l,
-        0xffd3724ff408c8d2l },
-      0 },
-    /* 67 */
-    { { 0x53968e64b458e6cbl,0x992dad20317a5d28l,0x3814ae0b7aa75f56l,
-        0xf5590f4ad78c26dfl },
-      { 0x0fc24bd3cf0ba55al,0x0fc4724a0c778bael,0x1ce9864f683b674al,
-        0x18d6da54f6f74a20l },
-      0 },
-    /* 68 */
-    { { 0xed93e225d5be5a2bl,0x6fe799835934f3c6l,0x4314092622626ffcl,
-        0x50bbb4d97990216al },
-      { 0x378191c6e57ec63el,0x65422c40181dcdb2l,0x41a8099b0236e0f6l,
-        0x2b10011801fe49c3l },
-      0 },
-    /* 69 */
-    { { 0xfc68b5c59b391593l,0xc385f5a2598270fcl,0x7144f3aad19adcbbl,
-        0xdd55899983fbae0cl },
-      { 0x93b88b8e74b82ff4l,0xd2e03c4071e734c9l,0x9a7a9eaf43c0322al,
-        0xe6e4c551149d6041l },
-      0 },
-    /* 70 */
-    { { 0x55f655bb1e9af288l,0x647e1a64f7ada931l,0x43697e4bcb2820e5l,
-        0x51e00db107ed56ffl },
-      { 0x43d169b8771c327el,0x29cdb20b4a96c2adl,0xc07d51f53deb4779l,
-        0xe22f424149829177l },
-      0 },
-    /* 71 */
-    { { 0xcd45e8f4635f1abbl,0x7edc0cb568538874l,0xc9472c1fb5a8034dl,
-        0xf709373d52dc48c9l },
-      { 0x401966bba8af30d6l,0x95bf5f4af137b69cl,0x3966162a9361c47el,
-        0xbd52d288e7275b11l },
-      0 },
-    /* 72 */
-    { { 0xab155c7a9c5fa877l,0x17dad6727d3a3d48l,0x43f43f9e73d189d8l,
-        0xa0d0f8e4c8aa77a6l },
-      { 0x0bbeafd8cc94f92dl,0xd818c8be0c4ddb3al,0x22cc65f8b82eba14l,
-        0xa56c78c7946d6a00l },
-      0 },
-    /* 73 */
-    { { 0x2962391b0dd09529l,0x803e0ea63daddfcfl,0x2c77351f5b5bf481l,
-        0xd8befdf8731a367al },
-      { 0xab919d42fc0157f4l,0xf51caed7fec8e650l,0xcdf9cb4002d48b0al,
-        0x854a68a5ce9f6478l },
-      0 },
-    /* 74 */
-    { { 0xdc35f67b63506ea5l,0x9286c489a4fe0d66l,0x3f101d3bfe95cd4dl,
-        0x5cacea0b98846a95l },
-      { 0xa90df60c9ceac44dl,0x3db29af4354d1c3al,0x08dd3de8ad5dbabel,
-        0xe4982d1235e4efa9l },
-      0 },
-    /* 75 */
-    { { 0x23104a22c34cd55el,0x58695bb32680d132l,0xfb345afa1fa1d943l,
-        0x8046b7f616b20499l },
-      { 0xb533581e38e7d098l,0xd7f61e8df46f0b70l,0x30dea9ea44cb78c4l,
-        0xeb17ca7b9082af55l },
-      0 },
-    /* 76 */
-    { { 0x1751b59876a145b9l,0xa5cf6b0fc1bc71ecl,0xd3e03565392715bbl,
-        0x097b00bafab5e131l },
-      { 0xaa66c8e9565f69e1l,0x77e8f75ab5be5199l,0x6033ba11da4fd984l,
-        0xf95c747bafdbcc9el },
-      0 },
-    /* 77 */
-    { { 0x558f01d3bebae45el,0xa8ebe9f0c4bc6955l,0xaeb705b1dbc64fc6l,
-        0x3512601e566ed837l },
-      { 0x9336f1e1fa1161cdl,0x328ab8d54c65ef87l,0x4757eee2724f21e5l,
-        0x0ef971236068ab6bl },
-      0 },
-    /* 78 */
-    { { 0x02598cf754ca4226l,0x5eede138f8642c8el,0x48963f74468e1790l,
-        0xfc16d9333b4fbc95l },
-      { 0xbe96fb31e7c800cal,0x138063312678adaal,0x3d6244976ff3e8b5l,
-        0x14ca4af1b95d7a17l },
-      0 },
-    /* 79 */
-    { { 0x7a4771babd2f81d5l,0x1a5f9d6901f7d196l,0xd898bef7cad9c907l,
-        0x4057b063f59c231dl },
-      { 0xbffd82fe89c05c0al,0xe4911c6f1dc0df85l,0x3befccaea35a16dbl,
-        0x1c3b5d64f1330b13l },
-      0 },
-    /* 80 */
-    { { 0x5fe14bfe80ec21fel,0xf6ce116ac255be82l,0x98bc5a072f4a5d67l,
-        0xfad27148db7e63afl },
-      { 0x90c0b6ac29ab05b3l,0x37a9a83c4e251ae6l,0x0a7dc875c2aade7dl,
-        0x77387de39f0e1a84l },
-      0 },
-    /* 81 */
-    { { 0x1e9ecc49a56c0dd7l,0xa5cffcd846086c74l,0x8f7a1408f505aecel,
-        0xb37b85c0bef0c47el },
-      { 0x3596b6e4cc0e6a8fl,0xfd6d4bbf6b388f23l,0xaba453fac39cef4el,
-        0x9c135ac8f9f628d5l },
-      0 },
-    /* 82 */
-    { { 0x32aa320284e35743l,0x320d6ab185a3cdefl,0xb821b1761df19819l,
-        0x5721361fc433851fl },
-      { 0x1f0db36a71fc9168l,0x5f98ba735e5c403cl,0xf64ca87e37bcd8f5l,
-        0xdcbac3c9e6bb11bdl },
-      0 },
-    /* 83 */
-    { { 0xf01d99684518cbe2l,0xd242fc189c9eb04el,0x727663c7e47feebfl,
-        0xb8c1c89e2d626862l },
-      { 0x51a58bddc8e1d569l,0x563809c8b7d88cd0l,0x26c27fd9f11f31ebl,
-        0x5d23bbda2f9422d4l },
-      0 },
-    /* 84 */
-    { { 0x0a1c729495c8f8bel,0x2961c4803bf362bfl,0x9e418403df63d4acl,
-        0xc109f9cb91ece900l },
-      { 0xc2d095d058945705l,0xb9083d96ddeb85c0l,0x84692b8d7a40449bl,
-        0x9bc3344f2eee1ee1l },
-      0 },
-    /* 85 */
-    { { 0x0d5ae35642913074l,0x55491b2748a542b1l,0x469ca665b310732al,
-        0x29591d525f1a4cc1l },
-      { 0xe76f5b6bb84f983fl,0xbe7eef419f5f84e1l,0x1200d49680baa189l,
-        0x6376551f18ef332cl },
-      0 },
-    /* 86 */
-    { { 0xbda5f14e562976ccl,0x22bca3e60ef12c38l,0xbbfa30646cca9852l,
-        0xbdb79dc808e2987al },
-      { 0xfd2cb5c9cb06a772l,0x38f475aafe536dcel,0xc2a3e0227c2b5db8l,
-        0x8ee86001add3c14al },
-      0 },
-    /* 87 */
-    { { 0xcbe96981a4ade873l,0x7ee9aa4dc4fba48cl,0x2cee28995a054ba5l,
-        0x92e51d7a6f77aa4bl },
-      { 0x948bafa87190a34dl,0xd698f75bf6bd1ed1l,0xd00ee6e30caf1144l,
-        0x5182f86f0a56aaaal },
-      0 },
-    /* 88 */
-    { { 0xfba6212c7a4cc99cl,0xff609b683e6d9ca1l,0x5dbb27cb5ac98c5al,
-        0x91dcab5d4073a6f2l },
-      { 0x01b6cc3d5f575a70l,0x0cb361396f8d87fal,0x165d4e8c89981736l,
-        0x17a0cedb97974f2bl },
-      0 },
-    /* 89 */
-    { { 0x38861e2a076c8d3al,0x701aad39210f924bl,0x94d0eae413a835d9l,
-        0x2e8ce36c7f4cdf41l },
-      { 0x91273dab037a862bl,0x01ba9bb760e4c8fal,0xf964538833baf2ddl,
-        0xf4ccc6cb34f668f3l },
-      0 },
-    /* 90 */
-    { { 0x44ef525cf1f79687l,0x7c59549592efa815l,0xe1231741a5c78d29l,
-        0xac0db4889a0df3c9l },
-      { 0x86bfc711df01747fl,0x592b9358ef17df13l,0xe5880e4f5ccb6bb5l,
-        0x95a64a6194c974a2l },
-      0 },
-    /* 91 */
-    { { 0x72c1efdac15a4c93l,0x40269b7382585141l,0x6a8dfb1c16cb0badl,
-        0x231e54ba29210677l },
-      { 0xa70df9178ae6d2dcl,0x4d6aa63f39112918l,0xf627726b5e5b7223l,
-        0xab0be032d8a731e1l },
-      0 },
-    /* 92 */
-    { { 0x097ad0e98d131f2dl,0x637f09e33b04f101l,0x1ac86196d5e9a748l,
-        0xf1bcc8802cf6a679l },
-      { 0x25c69140e8daacb4l,0x3c4e405560f65009l,0x591cc8fc477937a6l,
-        0x851694695aebb271l },
-      0 },
-    /* 93 */
-    { { 0xde35c143f1dcf593l,0x78202b29b018be3bl,0xe9cdadc29bdd9d3dl,
-        0x8f67d9d2daad55d8l },
-      { 0x841116567481ea5fl,0xe7d2dde9e34c590cl,0xffdd43f405053fa8l,
-        0xf84572b9c0728b5dl },
-      0 },
-    /* 94 */
-    { { 0x5e1a7a7197af71c9l,0xa14494447a736565l,0xa1b4ae070e1d5063l,
-        0xedee2710616b2c19l },
-      { 0xb2f034f511734121l,0x1cac6e554a25e9f0l,0x8dc148f3a40c2ecfl,
-        0x9fd27e9b44ebd7f4l },
-      0 },
-    /* 95 */
-    { { 0x3cc7658af6e2cb16l,0xe3eb7d2cfe5919b6l,0x5a8c5816168d5583l,
-        0xa40c2fb6958ff387l },
-      { 0x8c9ec560fedcc158l,0x7ad804c655f23056l,0xd93967049a307e12l,
-        0x99bc9bb87dc6decfl },
-      0 },
-    /* 96 */
-    { { 0x84a9521d927dafc6l,0x52c1fb695c09cd19l,0x9d9581a0f9366ddel,
-        0x9abe210ba16d7e64l },
-      { 0x480af84a48915220l,0xfa73176a4dd816c6l,0xc7d539871681ca5al,
-        0x7881c25787f344b0l },
-      0 },
-    /* 97 */
-    { { 0x93399b51e0bcf3ffl,0x0d02cbc5127f74f6l,0x8fb465a2dd01d968l,
-        0x15e6e319a30e8940l },
-      { 0x646d6e0d3e0e05f4l,0xfad7bddc43588404l,0xbe61c7d1c4f850d3l,
-        0x0e55facf191172cel },
-      0 },
-    /* 98 */
-    { { 0x7e9d9806f8787564l,0x1a33172131e85ce6l,0x6b0158cab819e8d6l,
-        0xd73d09766fe96577l },
-      { 0x424834251eb7206el,0xa519290fc618bb42l,0x5dcbb8595e30a520l,
-        0x9250a3748f15a50bl },
-      0 },
-    /* 99 */
-    { { 0xcaff08f8be577410l,0xfd408a035077a8c6l,0xf1f63289ec0a63a4l,
-        0x77414082c1cc8c0bl },
-      { 0x05a40fa6eb0991cdl,0xc1ca086649fdc296l,0x3a68a3c7b324fd40l,
-        0x8cb04f4d12eb20b9l },
-      0 },
-    /* 100 */
-    { { 0xb1c2d0556906171cl,0x9073e9cdb0240c3fl,0xdb8e6b4fd8906841l,
-        0xe4e429ef47123b51l },
-      { 0x0b8dd53c38ec36f4l,0xf9d2dc01ff4b6a27l,0x5d066e07879a9a48l,
-        0x37bca2ff3c6e6552l },
-      0 },
-    /* 101 */
-    { { 0x4cd2e3c7df562470l,0x44f272a2c0964ac9l,0x7c6d5df980c793bel,
-        0x59913edc3002b22al },
-      { 0x7a139a835750592al,0x99e01d80e783de02l,0xcf8c0375ea05d64fl,
-        0x43786e4ab013e226l },
-      0 },
-    /* 102 */
-    { { 0xff32b0ed9e56b5a6l,0x0750d9a6d9fc68f9l,0xec15e845597846a7l,
-        0x8638ca98b7e79e7al },
-      { 0x2f5ae0960afc24b2l,0x05398eaf4dace8f2l,0x3b765dd0aecba78fl,
-        0x1ecdd36a7b3aa6f0l },
-      0 },
-    /* 103 */
-    { { 0x5d3acd626c5ff2f3l,0xa2d516c02873a978l,0xad94c9fad2110d54l,
-        0xd85d0f85d459f32dl },
-      { 0x9f700b8d10b11da3l,0xd2c22c30a78318c4l,0x556988f49208decdl,
-        0xa04f19c3b4ed3c62l },
-      0 },
-    /* 104 */
-    { { 0x087924c8ed7f93bdl,0xcb64ac5d392f51f6l,0x7cae330a821b71afl,
-        0x92b2eeea5c0950b0l },
-      { 0x85ac4c9485b6e235l,0xab2ca4a92936c0f0l,0x80faa6b3e0508891l,
-        0x1ee782215834276cl },
-      0 },
-    /* 105 */
-    { { 0xa60a2e00e63e79f7l,0xf590e7b2f399d906l,0x9021054a6607c09dl,
-        0xf3f2ced857a6e150l },
-      { 0x200510f3f10d9b55l,0x9d2fcfacd8642648l,0xe5631aa7e8bd0e7cl,
-        0x0f56a4543da3e210l },
-      0 },
-    /* 106 */
-    { { 0x5b21bffa1043e0dfl,0x6c74b6cc9c007e6dl,0x1a656ec0d4a8517al,
-        0xbd8f17411969e263l },
-      { 0x8a9bbb86beb7494al,0x1567d46f45f3b838l,0xdf7a12a7a4e5a79al,
-        0x2d1a1c3530ccfa09l },
-      0 },
-    /* 107 */
-    { { 0x192e3813506508dal,0x336180c4a1d795a7l,0xcddb59497a9944b3l,
-        0xa107a65eb91fba46l },
-      { 0xe6d1d1c50f94d639l,0x8b4af3758a58b7d7l,0x1a7c5584bd37ca1cl,
-        0x183d760af87a9af2l },
-      0 },
-    /* 108 */
-    { { 0x29d697110dde59a4l,0xf1ad8d070e8bef87l,0x229b49634f2ebe78l,
-        0x1d44179dc269d754l },
-      { 0xb32dc0cf8390d30el,0x0a3b27530de8110cl,0x31af1dc52bc0339al,
-        0x771f9cc29606d262l },
-      0 },
-    /* 109 */
-    { { 0x99993e7785040739l,0x44539db98026a939l,0xcf40f6f2f5f8fc26l,
-        0x64427a310362718el },
-      { 0x4f4f2d8785428aa8l,0x7b7adc3febfb49a8l,0x201b2c6df23d01acl,
-        0x49d9b7496ae90d6dl },
-      0 },
-    /* 110 */
-    { { 0xcc78d8bc435d1099l,0x2adbcd4e8e8d1a08l,0x02c2e2a02cb68a41l,
-        0x9037d81b3f605445l },
-      { 0x7cdbac27074c7b61l,0xfe2031ab57bfd72el,0x61ccec96596d5352l,
-        0x08c3de6a7cc0639cl },
-      0 },
-    /* 111 */
-    { { 0x20fdd020f6d552abl,0x56baff9805cd81f1l,0x06fb7c3e91351291l,
-        0xc690944245796b2fl },
-      { 0x17b3ae9c41231bd1l,0x1eac6e875cc58205l,0x208837abf9d6a122l,
-        0x3fa3db02cafe3ac0l },
-      0 },
-    /* 112 */
-    { { 0xd75a3e6505058880l,0x7da365ef643943f2l,0x4147861cfab24925l,
-        0xc5c4bdb0fdb808ffl },
-      { 0x73513e34b272b56bl,0xc8327e9511b9043al,0xfd8ce37df8844969l,
-        0x2d56db9446c2b6b5l },
-      0 },
-    /* 113 */
-    { { 0x2461782fff46ac6bl,0xd19f792607a2e425l,0xfafea3c409a48de1l,
-        0x0f56bd9de503ba42l },
-      { 0x137d4ed1345cda49l,0x821158fc816f299dl,0xe7c6a54aaeb43402l,
-        0x4003bb9d1173b5f1l },
-      0 },
-    /* 114 */
-    { { 0x3b8e8189a0803387l,0xece115f539cbd404l,0x4297208dd2877f21l,
-        0x53765522a07f2f9el },
-      { 0xa4980a21a8a4182dl,0xa2bbd07a3219df79l,0x674d0a2e1a19a2d4l,
-        0x7a056f586c5d4549l },
-      0 },
-    /* 115 */
-    { { 0x646b25589d8a2a47l,0x5b582948c3df2773l,0x51ec000eabf0d539l,
-        0x77d482f17a1a2675l },
-      { 0xb8a1bd9587853948l,0xa6f817bd6cfbffeel,0xab6ec05780681e47l,
-        0x4115012b2b38b0e4l },
-      0 },
-    /* 116 */
-    { { 0x3c73f0f46de28cedl,0x1d5da7609b13ec47l,0x61b8ce9e6e5c6392l,
-        0xcdf04572fbea0946l },
-      { 0x1cb3c58b6c53c3b0l,0x97fe3c10447b843cl,0xfb2b8ae12cb9780el,
-        0xee703dda97383109l },
-      0 },
-    /* 117 */
-    { { 0x34515140ff57e43al,0xd44660d3b1b811b8l,0x2b3b5dff8f42b986l,
-        0x2a0ad89da162ce21l },
-      { 0x64e4a6946bc277bal,0xc788c954c141c276l,0x141aa64ccabf6274l,
-        0xd62d0b67ac2b4659l },
-      0 },
-    /* 118 */
-    { { 0x39c5d87b2c054ac4l,0x57005859f27df788l,0xedf7cbf3b18128d6l,
-        0xb39a23f2991c2426l },
-      { 0x95284a15f0b16ae5l,0x0c6a05b1a136f51bl,0x1d63c137f2700783l,
-        0x04ed0092c0674cc5l },
-      0 },
-    /* 119 */
-    { { 0x1f4185d19ae90393l,0x3047b4294a3d64e6l,0xae0001a69854fc14l,
-        0xa0a91fc10177c387l },
-      { 0xff0a3f01ae2c831el,0xbb76ae822b727e16l,0x8f12c8a15a3075b4l,
-        0x084cf9889ed20c41l },
-      0 },
-    /* 120 */
-    { { 0xd98509defca6becfl,0x2fceae807dffb328l,0x5d8a15c44778e8b9l,
-        0xd57955b273abf77el },
-      { 0x210da79e31b5d4f1l,0xaa52f04b3cfa7a1cl,0xd4d12089dc27c20bl,
-        0x8e14ea4202d141f1l },
-      0 },
-    /* 121 */
-    { { 0xeed50345f2897042l,0x8d05331f43402c4al,0xc8d9c194c8bdfb21l,
-        0x597e1a372aa4d158l },
-      { 0x0327ec1acf0bd68cl,0x6d4be0dcab024945l,0x5b9c8d7ac9fe3e84l,
-        0xca3f0236199b4deal },
-      0 },
-    /* 122 */
-    { { 0x592a10b56170bd20l,0x0ea897f16d3f5de7l,0xa3363ff144b2ade2l,
-        0xbde7fd7e309c07e4l },
-      { 0x516bb6d2b8f5432cl,0x210dc1cbe043444bl,0x3db01e6ff8f95b5al,
-        0xb623ad0e0a7dd198l },
-      0 },
-    /* 123 */
-    { { 0xa75bd67560c7b65bl,0xab8c559023a4a289l,0xf8220fd0d7b26795l,
-        0xd6aa2e4658ec137bl },
-      { 0x10abc00b5138bb85l,0x8c31d121d833a95cl,0xb24ff00b1702a32el,
-        0x111662e02dcc513al },
-      0 },
-    /* 124 */
-    { { 0x78114015efb42b87l,0xbd9f5d701b6c4dffl,0x66ecccd7a7d7c129l,
-        0xdb3ee1cb94b750f8l },
-      { 0xb26f3db0f34837cfl,0xe7eed18bb9578d4fl,0x5d2cdf937c56657dl,
-        0x886a644252206a59l },
-      0 },
-    /* 125 */
-    { { 0x3c234cfb65b569eal,0x20011141f72119c1l,0x8badc85da15a619el,
-        0xa70cf4eb018a17bcl },
-      { 0x224f97ae8c4a6a65l,0x36e5cf270134378fl,0xbe3a609e4f7e0960l,
-        0xaa4772abd1747b77l },
-      0 },
-    /* 126 */
-    { { 0x676761317aa60cc0l,0xc79163610368115fl,0xded98bb4bbc1bb5al,
-        0x611a6ddc30faf974l },
-      { 0x30e78cbcc15ee47al,0x2e8962824e0d96a5l,0x36f35adf3dd9ed88l,
-        0x5cfffaf816429c88l },
-      0 },
-    /* 127 */
-    { { 0xc0d54cff9b7a99cdl,0x7bf3b99d843c45a1l,0x038a908f62c739e1l,
-        0x6e5a6b237dc1994cl },
-      { 0xef8b454e0ba5db77l,0xb7b8807facf60d63l,0xe591c0c676608378l,
-        0x481a238d242dabccl },
-      0 },
-    /* 128 */
-    { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l,
-        0x2c41114ce0cdf943l },
-      { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l,
-        0x20477abf42ff9297l },
-      0 },
-    /* 129 */
-    { { 0x2f75173c18d65dbfl,0x77bf940e339edad8l,0x7022d26bdcf1001cl,
-        0xac66409ac77396b6l },
-      { 0x8b0bb36fc6261cc3l,0x213f7bc9190e7e90l,0x6541cebaa45e6c10l,
-        0xce8e6975cc122f85l },
-      0 },
-    /* 130 */
-    { { 0x0f121b41bc0a67d2l,0x62d4760a444d248al,0x0e044f1d659b4737l,
-        0x08fde365250bb4a8l },
-      { 0xaceec3da848bf287l,0xc2a62182d3369d6el,0x3582dfdc92449482l,
-        0x2f7e2fd2565d6cd7l },
-      0 },
-    /* 131 */
-    { { 0xae4b92dbc3770fa7l,0x095e8d5c379043f9l,0x54f34e9d17761171l,
-        0xc65be92e907702ael },
-      { 0x2758a303f6fd0a40l,0xe7d822e3bcce784bl,0x7ae4f5854f9767bfl,
-        0x4bff8e47d1193b3al },
-      0 },
-    /* 132 */
-    { { 0xcd41d21f00ff1480l,0x2ab8fb7d0754db16l,0xac81d2efbbe0f3eal,
-        0x3e4e4ae65772967dl },
-      { 0x7e18f36d3c5303e6l,0x3bd9994b92262397l,0x9ed70e261324c3c0l,
-        0x5388aefd58ec6028l },
-      0 },
-    /* 133 */
-    { { 0xad1317eb5e5d7713l,0x09b985ee75de49dal,0x32f5bc4fc74fb261l,
-        0x5cf908d14f75be0el },
-      { 0x760435108e657b12l,0xbfd421a5b96ed9e6l,0x0e29f51f8970ccc2l,
-        0xa698ba4060f00ce2l },
-      0 },
-    /* 134 */
-    { { 0x73db1686ef748fecl,0xe6e755a27e9d2cf9l,0x630b6544ce265effl,
-        0xb142ef8a7aebad8dl },
-      { 0xad31af9f17d5770al,0x66af3b672cb3412fl,0x6bd60d1bdf3359del,
-        0xd1896a9658515075l },
-      0 },
-    /* 135 */
-    { { 0xec5957ab33c41c08l,0x87de94ac5468e2e1l,0x18816b73ac472f6cl,
-        0x267b0e0b7981da39l },
-      { 0x6e554e5d8e62b988l,0xd8ddc755116d21e7l,0x4610faf03d2a6f99l,
-        0xb54e287aa1119393l },
-      0 },
-    /* 136 */
-    { { 0x0a0122b5178a876bl,0x51ff96ff085104b4l,0x050b31ab14f29f76l,
-        0x84abb28b5f87d4e6l },
-      { 0xd5ed439f8270790al,0x2d6cb59d85e3f46bl,0x75f55c1b6c1e2212l,
-        0xe5436f6717655640l },
-      0 },
-    /* 137 */
-    { { 0x53f9025e2286e8d5l,0x353c95b4864453bel,0xd832f5bde408e3a0l,
-        0x0404f68b5b9ce99el },
-      { 0xcad33bdea781e8e5l,0x3cdf5018163c2f5bl,0x575769600119caa3l,
-        0x3a4263df0ac1c701l },
-      0 },
-    /* 138 */
-    { { 0xc2965ecc9aeb596dl,0x01ea03e7023c92b4l,0x4704b4b62e013961l,
-        0x0ca8fd3f905ea367l },
-      { 0x92523a42551b2b61l,0x1eb7a89c390fcd06l,0xe7f1d2be0392a63el,
-        0x96dca2644ddb0c33l },
-      0 },
-    /* 139 */
-    { { 0x203bb43a387510afl,0x846feaa8a9a36a01l,0xd23a57702f950378l,
-        0x4363e2123aad59dcl },
-      { 0xca43a1c740246a47l,0xb362b8d2e55dd24dl,0xf9b086045d8faf96l,
-        0x840e115cd8bb98c4l },
-      0 },
-    /* 140 */
-    { { 0xf12205e21023e8a7l,0xc808a8cdd8dc7a0bl,0xe292a272163a5ddfl,
-        0x5e0d6abd30ded6d4l },
-      { 0x07a721c27cfc0f64l,0x42eec01d0e55ed88l,0x26a7bef91d1f9db2l,
-        0x7dea48f42945a25al },
-      0 },
-    /* 141 */
-    { { 0xabdf6f1ce5060a81l,0xe79f9c72f8f95615l,0xcfd36c5406ac268bl,
-        0xabc2a2beebfd16d1l },
-      { 0x8ac66f91d3e2eac7l,0x6f10ba63d2dd0466l,0x6790e3770282d31bl,
-        0x4ea353946c7eefc1l },
-      0 },
-    /* 142 */
-    { { 0xed8a2f8d5266309dl,0x0a51c6c081945a3el,0xcecaf45a578c5dc1l,
-        0x3a76e6891c94ffc3l },
-      { 0x9aace8a47d7b0d0fl,0x963ace968f584a5fl,0x51a30c724e697fbel,
-        0x8212a10a465e6464l },
-      0 },
-    /* 143 */
-    { { 0xef7c61c3cfab8caal,0x18eb8e840e142390l,0xcd1dff677e9733cal,
-        0xaa7cab71599cb164l },
-      { 0x02fc9273bc837bd1l,0xc06407d0c36af5d7l,0x17621292f423da49l,
-        0x40e38073fe0617c3l },
-      0 },
-    /* 144 */
-    { { 0xf4f80824a7bf9b7cl,0x365d23203fbe30d0l,0xbfbe532097cf9ce3l,
-        0xe3604700b3055526l },
-      { 0x4dcb99116cc6c2c7l,0x72683708ba4cbee6l,0xdcded434637ad9ecl,
-        0x6542d677a3dee15fl },
-      0 },
-    /* 145 */
-    { { 0x3f32b6d07b6c377al,0x6cb03847903448bel,0xd6fdd3a820da8af7l,
-        0xa6534aee09bb6f21l },
-      { 0x30a1780d1035facfl,0x35e55a339dcb47e6l,0x6ea50fe1c447f393l,
-        0xf3cb672fdc9aef22l },
-      0 },
-    /* 146 */
-    { { 0xeb3719fe3b55fd83l,0xe0d7a46c875ddd10l,0x33ac9fa905cea784l,
-        0x7cafaa2eaae870e7l },
-      { 0x9b814d041d53b338l,0xe0acc0a0ef87e6c6l,0xfb93d10811672b0fl,
-        0x0aab13c1b9bd522el },
-      0 },
-    /* 147 */
-    { { 0xddcce278d2681297l,0xcb350eb1b509546al,0x2dc431737661aaf2l,
-        0x4b91a602847012e9l },
-      { 0xdcff109572f8ddcfl,0x08ebf61e9a911af4l,0x48f4360ac372430el,
-        0x49534c5372321cabl },
-      0 },
-    /* 148 */
-    { { 0x83df7d71f07b7e9dl,0xa478efa313cd516fl,0x78ef264b6c047ee3l,
-        0xcaf46c4fd65ac5eel },
-      { 0xa04d0c7792aa8266l,0xedf45466913684bbl,0x56e65168ae4b16b0l,
-        0x14ce9e5704c6770fl },
-      0 },
-    /* 149 */
-    { { 0x99445e3e965e8f91l,0xd3aca1bacb0f2492l,0xd31cc70f90c8a0a0l,
-        0x1bb708a53e4c9a71l },
-      { 0xd5ca9e69558bdd7al,0x734a0508018a26b1l,0xb093aa714c9cf1ecl,
-        0xf9d126f2da300102l },
-      0 },
-    /* 150 */
-    { { 0x749bca7aaff9563el,0xdd077afeb49914a0l,0xe27a0311bf5f1671l,
-        0x807afcb9729ecc69l },
-      { 0x7f8a9337c9b08b77l,0x86c3a785443c7e38l,0x85fafa59476fd8bal,
-        0x751adcd16568cd8cl },
-      0 },
-    /* 151 */
-    { { 0x8aea38b410715c0dl,0xd113ea718f7697f7l,0x665eab1493fbf06dl,
-        0x29ec44682537743fl },
-      { 0x3d94719cb50bebbcl,0x399ee5bfe4505422l,0x90cd5b3a8d2dedb1l,
-        0xff9370e392a4077dl },
-      0 },
-    /* 152 */
-    { { 0x59a2d69bc6b75b65l,0x4188f8d5266651c5l,0x28a9f33e3de9d7d2l,
-        0x9776478ba2a9d01al },
-      { 0x8852622d929af2c7l,0x334f5d6d4e690923l,0xce6cc7e5a89a51e9l,
-        0x74a6313fac2f82fal },
-      0 },
-    /* 153 */
-    { { 0xb2f4dfddb75f079cl,0x85b07c9518e36fbbl,0x1b6cfcf0e7cd36ddl,
-        0xab75be150ff4863dl },
-      { 0x81b367c0173fc9b7l,0xb90a7420d2594fd0l,0x15fdbf03c4091236l,
-        0x4ebeac2e0b4459f6l },
-      0 },
-    /* 154 */
-    { { 0xeb6c5fe75c9f2c53l,0xd25220118eae9411l,0xc8887633f95ac5d8l,
-        0xdf99887b2c1baffcl },
-      { 0xbb78eed2850aaecbl,0x9d49181b01d6a272l,0x978dd511b1cdbcacl,
-        0x27b040a7779f4058l },
-      0 },
-    /* 155 */
-    { { 0x90405db7f73b2eb2l,0xe0df85088e1b2118l,0x501b71525962327el,
-        0xb393dd37e4cfa3f5l },
-      { 0xa1230e7b3fd75165l,0xd66344c2bcd33554l,0x6c36f1be0f7b5022l,
-        0x09588c12d0463419l },
-      0 },
-    /* 156 */
-    { { 0xe086093f02601c3bl,0xfb0252f8cf5c335fl,0x955cf280894aff28l,
-        0x81c879a9db9f648bl },
-      { 0x040e687cc6f56c51l,0xfed471693f17618cl,0x44f88a419059353bl,
-        0xfa0d48f55fc11bc4l },
-      0 },
-    /* 157 */
-    { { 0xbc6e1c9de1608e4dl,0x010dda113582822cl,0xf6b7ddc1157ec2d7l,
-        0x8ea0e156b6a367d6l },
-      { 0xa354e02f2383b3b4l,0x69966b943f01f53cl,0x4ff6632b2de03ca5l,
-        0x3f5ab924fa00b5acl },
-      0 },
-    /* 158 */
-    { { 0x337bb0d959739efbl,0xc751b0f4e7ebec0dl,0x2da52dd6411a67d1l,
-        0x8bc768872b74256el },
-      { 0xa5be3b7282d3d253l,0xa9f679a1f58d779fl,0xa1cac168e16767bbl,
-        0xb386f19060fcf34fl },
-      0 },
-    /* 159 */
-    { { 0x31f3c1352fedcfc2l,0x5396bf6262f8af0dl,0x9a02b4eae57288c2l,
-        0x4cb460f71b069c4dl },
-      { 0xae67b4d35b8095eal,0x92bbf8596fc07603l,0xe1475f66b614a165l,
-        0x52c0d50895ef5223l },
-      0 },
-    /* 160 */
-    { { 0x231c210e15339848l,0xe87a28e870778c8dl,0x9d1de6616956e170l,
-        0x4ac3c9382bb09c0bl },
-      { 0x19be05516998987dl,0x8b2376c4ae09f4d6l,0x1de0b7651a3f933dl,
-        0x380d94c7e39705f4l },
-      0 },
-    /* 161 */
-    { { 0x01a355aa81542e75l,0x96c724a1ee01b9b7l,0x6b3a2977624d7087l,
-        0x2ce3e171de2637afl },
-      { 0xcfefeb49f5d5bc1al,0xa655607e2777e2b5l,0x4feaac2f9513756cl,
-        0x2e6cd8520b624e4dl },
-      0 },
-    /* 162 */
-    { { 0x3685954b8c31c31dl,0x68533d005bf21a0cl,0x0bd7626e75c79ec9l,
-        0xca17754742c69d54l },
-      { 0xcc6edafff6d2dbb2l,0xfd0d8cbd174a9d18l,0x875e8793aa4578e8l,
-        0xa976a7139cab2ce6l },
-      0 },
-    /* 163 */
-    { { 0x0a651f1b93fb353dl,0xd75cab8b57fcfa72l,0xaa88cfa731b15281l,
-        0x8720a7170a1f4999l },
-      { 0x8c3e8d37693e1b90l,0xd345dc0b16f6dfc3l,0x8ea8d00ab52a8742l,
-        0x9719ef29c769893cl },
-      0 },
-    /* 164 */
-    { { 0x820eed8d58e35909l,0x9366d8dc33ddc116l,0xd7f999d06e205026l,
-        0xa5072976e15704c1l },
-      { 0x002a37eac4e70b2el,0x84dcf6576890aa8al,0xcd71bf18645b2a5cl,
-        0x99389c9df7b77725l },
-      0 },
-    /* 165 */
-    { { 0x238c08f27ada7a4bl,0x3abe9d03fd389366l,0x6b672e89766f512cl,
-        0xa88806aa202c82e4l },
-      { 0x6602044ad380184el,0xa8cb78c4126a8b85l,0x79d670c0ad844f17l,
-        0x0043bffb4738dcfel },
-      0 },
-    /* 166 */
-    { { 0x8d59b5dc36d5192el,0xacf885d34590b2afl,0x83566d0a11601781l,
-        0x52f3ef01ba6c4866l },
-      { 0x3986732a0edcb64dl,0x0a482c238068379fl,0x16cbe5fa7040f309l,
-        0x3296bd899ef27e75l },
-      0 },
-    /* 167 */
-    { { 0x476aba89454d81d7l,0x9eade7ef51eb9b3cl,0x619a21cd81c57986l,
-        0x3b90febfaee571e9l },
-      { 0x9393023e5496f7cbl,0x55be41d87fb51bc4l,0x03f1dd4899beb5cel,
-        0x6e88069d9f810b18l },
-      0 },
-    /* 168 */
-    { { 0xce37ab11b43ea1dbl,0x0a7ff1a95259d292l,0x851b02218f84f186l,
-        0xa7222beadefaad13l },
-      { 0xa2ac78ec2b0a9144l,0x5a024051f2fa59c5l,0x91d1eca56147ce38l,
-        0xbe94d523bc2ac690l },
-      0 },
-    /* 169 */
-    { { 0x72f4945e0b226ce7l,0xb8afd747967e8b70l,0xedea46f185a6c63el,
-        0x7782defe9be8c766l },
-      { 0x760d2aa43db38626l,0x460ae78776f67ad1l,0x341b86fc54499cdbl,
-        0x03838567a2892e4bl },
-      0 },
-    /* 170 */
-    { { 0x2d8daefd79ec1a0fl,0x3bbcd6fdceb39c97l,0xf5575ffc58f61a95l,
-        0xdbd986c4adf7b420l },
-      { 0x81aa881415f39eb7l,0x6ee2fcf5b98d976cl,0x5465475dcf2f717dl,
-        0x8e24d3c46860bbd0l },
-      0 },
-    /* 171 */
-    { { 0x749d8e549a587390l,0x12bb194f0cbec588l,0x46e07da4b25983c6l,
-        0x541a99c4407bafc8l },
-      { 0xdb241692624c8842l,0x6044c12ad86c05ffl,0xc59d14b44f7fcf62l,
-        0xc0092c49f57d35d1l },
-      0 },
-    /* 172 */
-    { { 0xd3cc75c3df2e61efl,0x7e8841c82e1b35cal,0xc62d30d1909f29f4l,
-        0x75e406347286944dl },
-      { 0xe7d41fc5bbc237d0l,0xc9537bf0ec4f01c9l,0x91c51a16282bd534l,
-        0x5b7cb658c7848586l },
-      0 },
-    /* 173 */
-    { { 0x964a70848a28ead1l,0x802dc508fd3b47f6l,0x9ae4bfd1767e5b39l,
-        0x7ae13eba8df097a1l },
-      { 0xfd216ef8eadd384el,0x0361a2d9b6b2ff06l,0x204b98784bcdb5f3l,
-        0x787d8074e2a8e3fdl },
-      0 },
-    /* 174 */
-    { { 0xc5e25d6b757fbb1cl,0xe47bddb2ca201debl,0x4a55e9a36d2233ffl,
-        0x5c2228199ef28484l },
-      { 0x773d4a8588315250l,0x21b21a2b827097c1l,0xab7c4ea1def5d33fl,
-        0xe45d37abbaf0f2b0l },
-      0 },
-    /* 175 */
-    { { 0xd2df1e3428511c8al,0xebb229c8bdca6cd3l,0x578a71a7627c39a7l,
-        0xed7bc12284dfb9d3l },
-      { 0xcf22a6df93dea561l,0x5443f18dd48f0ed1l,0xd8b861405bad23e8l,
-        0xaac97cc945ca6d27l },
-      0 },
-    /* 176 */
-    { { 0xeb54ea74a16bd00al,0xd839e9adf5c0bcc1l,0x092bb7f11f9bfc06l,
-        0x318f97b31163dc4el },
-      { 0xecc0c5bec30d7138l,0x44e8df23abc30220l,0x2bb7972fb0223606l,
-        0xfa41faa19a84ff4dl },
-      0 },
-    /* 177 */
-    { { 0x4402d974a6642269l,0xc81814ce9bb783bdl,0x398d38e47941e60bl,
-        0x38bb6b2c1d26e9e2l },
-      { 0xc64e4a256a577f87l,0x8b52d253dc11fe1cl,0xff336abf62280728l,
-        0x94dd0905ce7601a5l },
-      0 },
-    /* 178 */
-    { { 0x156cf7dcde93f92al,0xa01333cb89b5f315l,0x02404df9c995e750l,
-        0x92077867d25c2ae9l },
-      { 0xe2471e010bf39d44l,0x5f2c902096bb53d7l,0x4c44b7b35c9c3d8fl,
-        0x81e8428bd29beb51l },
-      0 },
-    /* 179 */
-    { { 0x6dd9c2bac477199fl,0x8cb8eeee6b5ecdd9l,0x8af7db3fee40fd0el,
-        0x1b94ab62dbbfa4b1l },
-      { 0x44f0d8b3ce47f143l,0x51e623fc63f46163l,0xf18f270fcc599383l,
-        0x06a38e28055590eel },
-      0 },
-    /* 180 */
-    { { 0x2e5b0139b3355b49l,0x20e26560b4ebf99bl,0xc08ffa6bd269f3dcl,
-        0xa7b36c2083d9d4f8l },
-      { 0x64d15c3a1b3e8830l,0xd5fceae1a89f9c0bl,0xcfeee4a2e2d16930l,
-        0xbe54c6b4a2822a20l },
-      0 },
-    /* 181 */
-    { { 0xd6cdb3df8d91167cl,0x517c3f79e7a6625el,0x7105648f346ac7f4l,
-        0xbf30a5abeae022bbl },
-      { 0x8e7785be93828a68l,0x5161c3327f3ef036l,0xe11b5feb592146b2l,
-        0xd1c820de2732d13al },
-      0 },
-    /* 182 */
-    { { 0x043e13479038b363l,0x58c11f546b05e519l,0x4fe57abe6026cad1l,
-        0xb7d17bed68a18da3l },
-      { 0x44ca5891e29c2559l,0x4f7a03765bfffd84l,0x498de4af74e46948l,
-        0x3997fd5e6412cc64l },
-      0 },
-    /* 183 */
-    { { 0xf20746828bd61507l,0x29e132d534a64d2al,0xffeddfb08a8a15e3l,
-        0x0eeb89293c6c13e8l },
-      { 0xe9b69a3ea7e259f8l,0xce1db7e6d13e7e67l,0x277318f6ad1fa685l,
-        0x228916f8c922b6efl },
-      0 },
-    /* 184 */
-    { { 0x959ae25b0a12ab5bl,0xcc11171f957bc136l,0x8058429ed16e2b0cl,
-        0xec05ad1d6e93097el },
-      { 0x157ba5beac3f3708l,0x31baf93530b59d77l,0x47b55237118234e5l,
-        0x7d3141567ff11b37l },
-      0 },
-    /* 185 */
-    { { 0x7bd9c05cf6dfefabl,0xbe2f2268dcb37707l,0xe53ead973a38bb95l,
-        0xe9ce66fc9bc1d7a3l },
-      { 0x75aa15766f6a02a1l,0x38c087df60e600edl,0xf8947f3468cdc1b9l,
-        0xd9650b0172280651l },
-      0 },
-    /* 186 */
-    { { 0x504b4c4a5a057e60l,0xcbccc3be8def25e4l,0xa635320817c1ccbdl,
-        0x14d6699a804eb7a2l },
-      { 0x2c8a8415db1f411al,0x09fbaf0bf80d769cl,0xb4deef901c2f77adl,
-        0x6f4c68410d43598al },
-      0 },
-    /* 187 */
-    { { 0x8726df4e96c24a96l,0x534dbc85fcbd99a3l,0x3c466ef28b2ae30al,
-        0x4c4350fd61189abbl },
-      { 0x2967f716f855b8dal,0x41a42394463c38a1l,0xc37e1413eae93343l,
-        0xa726d2425a3118b5l },
-      0 },
-    /* 188 */
-    { { 0xdae6b3ee948c1086l,0xf1de503dcbd3a2e1l,0x3f35ed3f03d022f3l,
-        0x13639e82cc6cf392l },
-      { 0x9ac938fbcdafaa86l,0xf45bc5fb2654a258l,0x1963b26e45051329l,
-        0xca9365e1c1a335a3l },
-      0 },
-    /* 189 */
-    { { 0x3615ac754c3b2d20l,0x742a5417904e241bl,0xb08521c4cc9d071dl,
-        0x9ce29c34970b72a5l },
-      { 0x8cc81f736d3e0ad6l,0x8060da9ef2f8434cl,0x35ed1d1a6ce862d9l,
-        0x48c4abd7ab42af98l },
-      0 },
-    /* 190 */
-    { { 0xd221b0cc40c7485al,0xead455bbe5274dbfl,0x493c76989263d2e8l,
-        0x78017c32f67b33cbl },
-      { 0xb9d35769930cb5eel,0xc0d14e940c408ed2l,0xf8b7bf55272f1a4dl,
-        0x53cd0454de5c1c04l },
-      0 },
-    /* 191 */
-    { { 0xbcd585fa5d28ccacl,0x5f823e56005b746el,0x7c79f0a1cd0123aal,
-        0xeea465c1d3d7fa8fl },
-      { 0x7810659f0551803bl,0x6c0b599f7ce6af70l,0x4195a77029288e70l,
-        0x1b6e42a47ae69193l },
-      0 },
-    /* 192 */
-    { { 0x2e80937cf67d04c3l,0x1e312be289eeb811l,0x56b5d88792594d60l,
-        0x0224da14187fbd3dl },
-      { 0x87abb8630c5fe36fl,0x580f3c604ef51f5fl,0x964fb1bfb3b429ecl,
-        0x60838ef042bfff33l },
-      0 },
-    /* 193 */
-    { { 0x432cb2f27e0bbe99l,0x7bda44f304aa39eel,0x5f497c7a9fa93903l,
-        0x636eb2022d331643l },
-      { 0xfcfd0e6193ae00aal,0x875a00fe31ae6d2fl,0xf43658a29f93901cl,
-        0x8844eeb639218bacl },
-      0 },
-    /* 194 */
-    { { 0x114171d26b3bae58l,0x7db3df7117e39f3el,0xcd37bc7f81a8eadal,
-        0x27ba83dc51fb789el },
-      { 0xa7df439ffbf54de5l,0x7277030bb5fe1a71l,0x42ee8e35db297a48l,
-        0xadb62d3487f3a4abl },
-      0 },
-    /* 195 */
-    { { 0x9b1168a2a175df2al,0x082aa04f618c32e9l,0xc9e4f2e7146b0916l,
-        0xb990fd7675e7c8b2l },
-      { 0x0829d96b4df37313l,0x1c205579d0b40789l,0x66c9ae4a78087711l,
-        0x81707ef94d10d18dl },
-      0 },
-    /* 196 */
-    { { 0x97d7cab203d6ff96l,0x5b851bfc0d843360l,0x268823c4d042db4bl,
-        0x3792daead5a8aa5cl },
-      { 0x52818865941afa0bl,0xf3e9e74142d83671l,0x17c825275be4e0a7l,
-        0x5abd635e94b001bal },
-      0 },
-    /* 197 */
-    { { 0x727fa84e0ac4927cl,0xe3886035a7c8cf23l,0xa4bcd5ea4adca0dfl,
-        0x5995bf21846ab610l },
-      { 0xe90f860b829dfa33l,0xcaafe2ae958fc18bl,0x9b3baf4478630366l,
-        0x44c32ca2d483411el },
-      0 },
-    /* 198 */
-    { { 0xa74a97f1e40ed80cl,0x5f938cb131d2ca82l,0x53f2124b7c2d6ad9l,
-        0x1f2162fb8082a54cl },
-      { 0x7e467cc5720b173el,0x40e8a666085f12f9l,0x8cebc20e4c9d65dcl,
-        0x8f1d402bc3e907c9l },
-      0 },
-    /* 199 */
-    { { 0x4f592f9cfbc4058al,0xb15e14b6292f5670l,0xc55cfe37bc1d8c57l,
-        0xb1980f43926edbf9l },
-      { 0x98c33e0932c76b09l,0x1df5279d33b07f78l,0x6f08ead4863bb461l,
-        0x2828ad9b37448e45l },
-      0 },
-    /* 200 */
-    { { 0x696722c4c4cf4ac5l,0xf5ac1a3fdde64afbl,0x0551baa2e0890832l,
-        0x4973f1275a14b390l },
-      { 0xe59d8335322eac5dl,0x5e07eef50bd9b568l,0xab36720fa2588393l,
-        0x6dac8ed0db168ac7l },
-      0 },
-    /* 201 */
-    { { 0xf7b545aeeda835efl,0x4aa113d21d10ed51l,0x035a65e013741b09l,
-        0x4b23ef5920b9de4cl },
-      { 0xe82bb6803c4c7341l,0xd457706d3f58bc37l,0x73527863a51e3ee8l,
-        0x4dd71534ddf49a4el },
-      0 },
-    /* 202 */
-    { { 0xbf94467295476cd9l,0x648d072fe31a725bl,0x1441c8b8fc4b67e0l,
-        0xfd3170002f4a4dbbl },
-      { 0x1cb43ff48995d0e1l,0x76e695d10ef729aal,0xe0d5f97641798982l,
-        0x14fac58c9569f365l },
-      0 },
-    /* 203 */
-    { { 0xad9a0065f312ae18l,0x51958dc0fcc93fc9l,0xd9a142408a7d2846l,
-        0xed7c765136abda50l },
-      { 0x46270f1a25d4abbcl,0x9b5dd8f3f1a113eal,0xc609b0755b51952fl,
-        0xfefcb7f74d2e9f53l },
-      0 },
-    /* 204 */
-    { { 0xbd09497aba119185l,0xd54e8c30aac45ba4l,0x492479deaa521179l,
-        0x1801a57e87e0d80bl },
-      { 0x073d3f8dfcafffb0l,0x6cf33c0bae255240l,0x781d763b5b5fdfbcl,
-        0x9f8fc11e1ead1064l },
-      0 },
-    /* 205 */
-    { { 0x1583a1715e69544cl,0x0eaf8567f04b7813l,0x1e22a8fd278a4c32l,
-        0xa9d3809d3d3a69a9l },
-      { 0x936c2c2c59a2da3bl,0x38ccbcf61895c847l,0x5e65244e63d50869l,
-        0x3006b9aee1178ef7l },
-      0 },
-    /* 206 */
-    { { 0x0bb1f2b0c9eead28l,0x7eef635d89f4dfbcl,0x074757fdb2ce8939l,
-        0x0ab85fd745f8f761l },
-      { 0xecda7c933e5b4549l,0x4be2bb5c97922f21l,0x261a1274b43b8040l,
-        0xb122d67511e942c2l },
-      0 },
-    /* 207 */
-    { { 0x3be607be66a5ae7al,0x01e703fa76adcbe3l,0xaf9043014eb6e5c5l,
-        0x9f599dc1097dbaecl },
-      { 0x6d75b7180ff250edl,0x8eb91574349a20dcl,0x425605a410b227a3l,
-        0x7d5528e08a294b78l },
-      0 },
-    /* 208 */
-    { { 0xf0f58f6620c26defl,0x025585ea582b2d1el,0xfbe7d79b01ce3881l,
-        0x28ccea01303f1730l },
-      { 0xd1dabcd179644ba5l,0x1fc643e806fff0b8l,0xa60a76fc66b3e17bl,
-        0xc18baf48a1d013bfl },
-      0 },
-    /* 209 */
-    { { 0x34e638c85dc4216dl,0x00c01067206142acl,0xd453a17195f5064al,
-        0x9def809db7a9596bl },
-      { 0x41e8642e67ab8d2cl,0xb42404336237a2b6l,0x7d506a6d64c4218bl,
-        0x0357f8b068808ce5l },
-      0 },
-    /* 210 */
-    { { 0x8e9dbe644cd2cc88l,0xcc61c28df0b8f39dl,0x4a309874cd30a0c8l,
-        0xe4a01add1b489887l },
-      { 0x2ed1eeacf57cd8f9l,0x1b767d3ebd594c48l,0xa7295c717bd2f787l,
-        0x466d7d79ce10cc30l },
-      0 },
-    /* 211 */
-    { { 0x47d318929dada2c7l,0x4fa0a6c38f9aa27dl,0x90e4fd28820a59e1l,
-        0xc672a522451ead1al },
-      { 0x30607cc85d86b655l,0xf0235d3bf9ad4af1l,0x99a08680571172a6l,
-        0x5e3d64faf2a67513l },
-      0 },
-    /* 212 */
-    { { 0xaa6410c79b3b4416l,0xcd8fcf85eab26d99l,0x5ebff74adb656a74l,
-        0x6c8a7a95eb8e42fcl },
-      { 0x10c60ba7b02a63bdl,0x6b2f23038b8f0047l,0x8c6c3738312d90b0l,
-        0x348ae422ad82ca91l },
-      0 },
-    /* 213 */
-    { { 0x7f4746635ccda2fbl,0x22accaa18e0726d2l,0x85adf782492b1f20l,
-        0xc1074de0d9ef2d2el },
-      { 0xfcf3ce44ae9a65b3l,0xfd71e4ac05d7151bl,0xd4711f50ce6a9788l,
-        0xfbadfbdbc9e54ffcl },
-      0 },
-    /* 214 */
-    { { 0x1713f1cd20a99363l,0xb915658f6cf22775l,0x968175cd24d359b2l,
-        0xb7f976b483716fcdl },
-      { 0x5758e24d5d6dbf74l,0x8d23bafd71c3af36l,0x48f477600243dfe3l,
-        0xf4d41b2ecafcc805l },
-      0 },
-    /* 215 */
-    { { 0x51f1cf28fdabd48dl,0xce81be3632c078a4l,0x6ace2974117146e9l,
-        0x180824eae0160f10l },
-      { 0x0387698b66e58358l,0x63568752ce6ca358l,0x82380e345e41e6c5l,
-        0x67e5f63983cf6d25l },
-      0 },
-    /* 216 */
-    { { 0xf89ccb8dcf4899efl,0x949015f09ebb44c0l,0x546f9276b2598ec9l,
-        0x9fef789a04c11fc6l },
-      { 0x6d367ecf53d2a071l,0xb10e1a7fa4519b09l,0xca6b3fb0611e2eefl,
-        0xbc80c181a99c4e20l },
-      0 },
-    /* 217 */
-    { { 0x972536f8e5eb82e6l,0x1a484fc7f56cb920l,0xc78e217150b5da5el,
-        0x49270e629f8cdf10l },
-      { 0x1a39b7bbea6b50adl,0x9a0284c1a2388ffcl,0x5403eb178107197bl,
-        0xd2ee52f961372f7fl },
-      0 },
-    /* 218 */
-    { { 0xd37cd28588e0362al,0x442fa8a78fa5d94dl,0xaff836e5a434a526l,
-        0xdfb478bee5abb733l },
-      { 0xa91f1ce7673eede6l,0xa5390ad42b5b2f04l,0x5e66f7bf5530da2fl,
-        0xd9a140b408df473al },
-      0 },
-    /* 219 */
-    { { 0x0e0221b56e8ea498l,0x623478293563ee09l,0xe06b8391335d2adel,
-        0x760c058d623f4b1al },
-      { 0x0b89b58cc198aa79l,0xf74890d2f07aba7fl,0x4e204110fde2556al,
-        0x7141982d8f190409l },
-      0 },
-    /* 220 */
-    { { 0x6f0a0e334d4b0f45l,0xd9280b38392a94e1l,0x3af324c6b3c61d5el,
-        0x3af9d1ce89d54e47l },
-      { 0xfd8f798120930371l,0xeda2664c21c17097l,0x0e9545dcdc42309bl,
-        0xb1f815c373957dd6l },
-      0 },
-    /* 221 */
-    { { 0x84faa78e89fec44al,0xc8c2ae473caa4cafl,0x691c807dc1b6a624l,
-        0xa41aed141543f052l },
-      { 0x424353997d5ffe04l,0x8bacb2df625b6e20l,0x85d660be87817775l,
-        0xd6e9c1dd86fb60efl },
-      0 },
-    /* 222 */
-    { { 0x3aa2e97ec6853264l,0x771533b7e2304a0bl,0x1b912bb7b8eae9bel,
-        0x9c9c6e10ae9bf8c2l },
-      { 0xa2309a59e030b74cl,0x4ed7494d6a631e90l,0x89f44b23a49b79f2l,
-        0x566bd59640fa61b6l },
-      0 },
-    /* 223 */
-    { { 0x066c0118c18061f3l,0x190b25d37c83fc70l,0xf05fc8e027273245l,
-        0xcf2c7390f525345el },
-      { 0xa09bceb410eb30cfl,0xcfd2ebba0d77703al,0xe842c43a150ff255l,
-        0x02f517558aa20979l },
-      0 },
-    /* 224 */
-    { { 0x396ef794addb7d07l,0x0b4fc74224455500l,0xfaff8eacc78aa3cel,
-        0x14e9ada5e8d4d97dl },
-      { 0xdaa480a12f7079e2l,0x45baa3cde4b0800el,0x01765e2d7838157dl,
-        0xa0ad4fab8e9d9ae8l },
-      0 },
-    /* 225 */
-    { { 0x0bfb76214a653618l,0x1872813c31eaaa5fl,0x1553e73744949d5el,
-        0xbcd530b86e56ed1el },
-      { 0x169be85332e9c47bl,0xdc2776feb50059abl,0xcdba9761192bfbb4l,
-        0x909283cf6979341dl },
-      0 },
-    /* 226 */
-    { { 0x67b0032476e81a13l,0x9bee1a9962171239l,0x08ed361bd32e19d6l,
-        0x35eeb7c9ace1549al },
-      { 0x1280ae5a7e4e5bdcl,0x2dcd2cd3b6ceec6el,0x52e4224c6e266bc1l,
-        0x9a8b2cf4448ae864l },
-      0 },
-    /* 227 */
-    { { 0xf6471bf209d03b59l,0xc90e62a3b65af2abl,0xff7ff168ebd5eec9l,
-        0x6bdb60f4d4491379l },
-      { 0xdadafebc8a55bc30l,0xc79ead1610097fe0l,0x42e197414c1e3bddl,
-        0x01ec3cfd94ba08a9l },
-      0 },
-    /* 228 */
-    { { 0xba6277ebdc9485c2l,0x48cc9a7922fb10c7l,0x4f61d60f70a28d8al,
-        0xd1acb1c0475464f6l },
-      { 0xd26902b126f36612l,0x59c3a44ee0618d8bl,0x4df8a813308357eel,
-        0x7dcd079d405626c2l },
-      0 },
-    /* 229 */
-    { { 0x5ce7d4d3f05a4b48l,0xadcd295237230772l,0xd18f7971812a915al,
-        0x0bf53589377d19b8l },
-      { 0x35ecd95a6c68ea73l,0xc7f3bbca823a584dl,0x9fb674c6f473a723l,
-        0xd28be4d9e16686fcl },
-      0 },
-    /* 230 */
-    { { 0x5d2b990638fa8e4bl,0x559f186e893fd8fcl,0x3a6de2aa436fb6fcl,
-        0xd76007aa510f88cel },
-      { 0x2d10aab6523a4988l,0xb455cf4474dd0273l,0x7f467082a3407278l,
-        0xf2b52f68b303bb01l },
-      0 },
-    /* 231 */
-    { { 0x0d57eafa9835b4cal,0x2d2232fcbb669cbcl,0x8eeeb680c6643198l,
-        0xd8dbe98ecc5aed3al },
-      { 0xcba9be3fc5a02709l,0x30be68e5f5ba1fa8l,0xfebd43cdf10ea852l,
-        0xe01593a3ee559705l },
-      0 },
-    /* 232 */
-    { { 0xd3e5af50ea75a0a6l,0x512226ac57858033l,0x6fe6d50fd0176406l,
-        0xafec07b1aeb8ef06l },
-      { 0x7fb9956780bb0a31l,0x6f1af3cc37309aael,0x9153a15a01abf389l,
-        0xa71b93546e2dbfddl },
-      0 },
-    /* 233 */
-    { { 0xbf8e12e018f593d2l,0xd1a90428a078122bl,0x150505db0ba4f2adl,
-        0x53a2005c628523d9l },
-      { 0x07c8b639e7f2b935l,0x2bff975ac182961al,0x86bceea77518ca2cl,
-        0xbf47d19b3d588e3dl },
-      0 },
-    /* 234 */
-    { { 0x672967a7dd7665d5l,0x4e3030572f2f4de5l,0x144005ae80d4903fl,
-        0x001c2c7f39c9a1b6l },
-      { 0x143a801469efc6d6l,0xc810bdaa7bc7a724l,0x5f65670ba78150a4l,
-        0xfdadf8e786ffb99bl },
-      0 },
-    /* 235 */
-    { { 0xfd38cb88ffc00785l,0x77fa75913b48eb67l,0x0454d055bf368fbcl,
-        0x3a838e4d5aa43c94l },
-      { 0x561663293e97bb9al,0x9eb93363441d94d9l,0x515591a60adb2a83l,
-        0x3cdb8257873e1da3l },
-      0 },
-    /* 236 */
-    { { 0x137140a97de77eabl,0xf7e1c50d41648109l,0x762dcad2ceb1d0dfl,
-        0x5a60cc89f1f57fbal },
-      { 0x80b3638240d45673l,0x1b82be195913c655l,0x057284b8dd64b741l,
-        0x922ff56fdbfd8fc0l },
-      0 },
-    /* 237 */
-    { { 0x1b265deec9a129a1l,0xa5b1ce57cc284e04l,0x04380c46cebfbe3cl,
-        0x72919a7df6c5cd62l },
-      { 0x298f453a8fb90f9al,0xd719c00b88e4031bl,0xe32c0e77796f1856l,
-        0x5e7917803624089al },
-      0 },
-    /* 238 */
-    { { 0x5c16ec557f63cdfbl,0x8e6a3571f1cae4fdl,0xfce26bea560597cal,
-        0x4e0a5371e24c2fabl },
-      { 0x276a40d3a5765357l,0x3c89af440d73a2b4l,0xb8f370ae41d11a32l,
-        0xf5ff7818d56604eel },
-      0 },
-    /* 239 */
-    { { 0xfbf3e3fe1a09df21l,0x26d5d28ee66e8e47l,0x2096bd0a29c89015l,
-        0xe41df0e9533f5e64l },
-      { 0x305fda40b3ba9e3fl,0xf2340ceb2604d895l,0x0866e1927f0367c7l,
-        0x8edd7d6eac4f155fl },
-      0 },
-    /* 240 */
-    { { 0xc9a1dc0e0bfc8ff3l,0x14efd82be936f42fl,0x67016f7ccca381efl,
-        0x1432c1caed8aee96l },
-      { 0xec68482970b23c26l,0xa64fe8730735b273l,0xe389f6e5eaef0f5al,
-        0xcaef480b5ac8d2c6l },
-      0 },
-    /* 241 */
-    { { 0x5245c97875315922l,0xd82951713063cca5l,0xf3ce60d0b64ef2cbl,
-        0xd0ba177e8efae236l },
-      { 0x53a9ae8fb1b3af60l,0x1a796ae53d2da20el,0x01d63605df9eef28l,
-        0xf31c957c1c54ae16l },
-      0 },
-    /* 242 */
-    { { 0xc0f58d5249cc4597l,0xdc5015b0bae0a028l,0xefc5fc55734a814al,
-        0x013404cb96e17c3al },
-      { 0xb29e2585c9a824bfl,0xd593185e001eaed7l,0x8d6ee68261ef68acl,
-        0x6f377c4b91933e6cl },
-      0 },
-    /* 243 */
-    { { 0x9f93bad1a8333fd2l,0xa89302025a2a95b8l,0x211e5037eaf75acel,
-        0x6dba3e4ed2d09506l },
-      { 0xa48ef98cd04399cdl,0x1811c66ee6b73adel,0x72f60752c17ecaf3l,
-        0xf13cf3423becf4a7l },
-      0 },
-    /* 244 */
-    { { 0xceeb9ec0a919e2ebl,0x83a9a195f62c0f68l,0xcfba3bb67aba2299l,
-        0xc83fa9a9274bbad3l },
-      { 0x0d7d1b0b62fa1ce0l,0xe58b60f53418efbfl,0xbfa8ef9e52706f04l,
-        0xb49d70f45d702683l },
-      0 },
-    /* 245 */
-    { { 0x914c7510fad5513bl,0x05f32eecb1751e2dl,0x6d850418d9fb9d59l,
-        0x59cfadbb0c30f1cfl },
-      { 0xe167ac2355cb7fd6l,0x249367b8820426a3l,0xeaeec58c90a78864l,
-        0x5babf362354a4b67l },
-      0 },
-    /* 246 */
-    { { 0x37c981d1ee424865l,0x8b002878f2e5577fl,0x702970f1b9e0c058l,
-        0x6188c6a79026c8f0l },
-      { 0x06f9a19bd0f244dal,0x1ecced5cfb080873l,0x35470f9b9f213637l,
-        0x993fe475df50b9d9l },
-      0 },
-    /* 247 */
-    { { 0x68e31cdf9b2c3609l,0x84eb19c02c46d4eal,0x7ac9ec1a9a775101l,
-        0x81f764664c80616bl },
-      { 0x1d7c2a5a75fbe978l,0x6743fed3f183b356l,0x838d1f04501dd2bfl,
-        0x564a812a5fe9060dl },
-      0 },
-    /* 248 */
-    { { 0x7a5a64f4fa817d1dl,0x55f96844bea82e0fl,0xb5ff5a0fcd57f9aal,
-        0x226bf3cf00e51d6cl },
-      { 0xd6d1a9f92f2833cfl,0x20a0a35a4f4f89a8l,0x11536c498f3f7f77l,
-        0x68779f47ff257836l },
-      0 },
-    /* 249 */
-    { { 0x79b0c1c173043d08l,0xa54467741fc020fal,0xd3767e289a6d26d0l,
-        0x97bcb0d1eb092e0bl },
-      { 0x2ab6eaa8f32ed3c3l,0xc8a4f151b281bc48l,0x4d1bf4f3bfa178f3l,
-        0xa872ffe80a784655l },
-      0 },
-    /* 250 */
-    { { 0xb1ab7935a32b2086l,0xe1eb710e8160f486l,0x9bd0cd913b6ae6bel,
-        0x02812bfcb732a36al },
-      { 0xa63fd7cacf605318l,0x646e5d50fdfd6d1dl,0xa1d683982102d619l,
-        0x07391cc9fe5396afl },
-      0 },
-    /* 251 */
-    { { 0xc50157f08b80d02bl,0x6b8333d162877f7fl,0x7aca1af878d542ael,
-        0x355d2adc7e6d2a08l },
-      { 0xb41f335a287386e1l,0xfd272a94f8e43275l,0x286ca2cde79989eal,
-        0x3dc2b1e37c2a3a79l },
-      0 },
-    /* 252 */
-    { { 0xd689d21c04581352l,0x0a00c825376782bel,0x203bd5909fed701fl,
-        0xc47869103ccd846bl },
-      { 0x5dba770824c768edl,0x72feea026841f657l,0x73313ed56accce0el,
-        0xccc42968d5bb4d32l },
-      0 },
-    /* 253 */
-    { { 0x94e50de13d7620b9l,0xd89a5c8a5992a56al,0xdc007640675487c9l,
-        0xe147eb42aa4871cfl },
-      { 0x274ab4eeacf3ae46l,0xfd4936fb50350fbel,0xdf2afe4748c840eal,
-        0x239ac047080e96e3l },
-      0 },
-    /* 254 */
-    { { 0x481d1f352bfee8d4l,0xce80b5cffa7b0fecl,0x105c4c9e2ce9af3cl,
-        0xc55fa1a3f5f7e59dl },
-      { 0x3186f14e8257c227l,0xc5b1653f342be00bl,0x09afc998aa904fb2l,
-        0x094cd99cd4f4b699l },
-      0 },
-    /* 255 */
-    { { 0x8a981c84d703bebal,0x8631d15032ceb291l,0xa445f2c9e3bd49ecl,
-        0xb90a30b642abad33l },
-      { 0xb465404fb4a5abf9l,0x004750c375db7603l,0x6f9a42ccca35d89fl,
-        0x019f8b9a1b7924f7l },
-      0 },
-};
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_avx2_4(sp_point* r, sp_digit* k,
-        int map, void* heap)
-{
-    return sp_256_ecc_mulmod_stripe_avx2_4(r, &p256_base, p256_table,
-                                      k, map, heap);
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#else
-/* A table entry for pre-computed points. */
-typedef struct sp_table_entry_sum {
-    sp_digit x[4];
-    sp_digit y[4];
-    byte infinity;
-} sp_table_entry_sum;
-
-/* Table of pre-computed values for P256 with 3 multiples and width of 8 bits.
- */
-static sp_table_entry_sum p256_table[33][58] = {
-    {
-        /* 0 << 0 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 0 */
-        { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l,
-            0x18905f76a53755c6l },
-          { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l,
-            0x8571ff1825885d85l },
-          0 },
-        /* 3 << 0 */
-        { { 0xffac3f904eebc127l,0xb027f84a087d81fbl,0x66ad77dd87cbbc98l,
-            0x26936a3fb6ff747el },
-          { 0xb04c5c1fc983a7ebl,0x583e47ad0861fe1al,0x788208311a2ee98el,
-            0xd5f06a29e587cc07l },
-          0 },
-        /* 4 << 0 */
-        { { 0x74b0b50d46918dccl,0x4650a6edc623c173l,0x0cdaacace8100af2l,
-            0x577362f541b0176bl },
-          { 0x2d96f24ce4cbaba6l,0x17628471fad6f447l,0x6b6c36dee5ddd22el,
-            0x84b14c394c5ab863l },
-          0 },
-        /* 5 << 0 */
-        { { 0xbe1b8aaec45c61f5l,0x90ec649a94b9537dl,0x941cb5aad076c20cl,
-            0xc9079605890523c8l },
-          { 0xeb309b4ae7ba4f10l,0x73c568efe5eb882bl,0x3540a9877e7a1f68l,
-            0x73a076bb2dd1e916l },
-          0 },
-        /* 7 << 0 */
-        { { 0x0746354ea0173b4fl,0x2bd20213d23c00f7l,0xf43eaab50c23bb08l,
-            0x13ba5119c3123e03l },
-          { 0x2847d0303f5b9d4dl,0x6742f2f25da67bddl,0xef933bdc77c94195l,
-            0xeaedd9156e240867l },
-          0 },
-        /* 9 << 0 */
-        { { 0x75c96e8f264e20e8l,0xabe6bfed59a7a841l,0x2cc09c0444c8eb00l,
-            0xe05b3080f0c4e16bl },
-          { 0x1eb7777aa45f3314l,0x56af7bedce5d45e3l,0x2b6e019a88b12f1al,
-            0x086659cdfd835f9bl },
-          0 },
-        /* 10 << 0 */
-        { { 0x2c18dbd19dc21ec8l,0x98f9868a0fcf8139l,0x737d2cd648250b49l,
-            0xcc61c94724b3428fl },
-          { 0x0c2b407880dd9e76l,0xc43a8991383fbe08l,0x5f7d2d65779be5d2l,
-            0x78719a54eb3b4ab5l },
-          0 },
-        /* 11 << 0 */
-        { { 0xea7d260a6245e404l,0x9de407956e7fdfe0l,0x1ff3a4158dac1ab5l,
-            0x3e7090f1649c9073l },
-          { 0x1a7685612b944e88l,0x250f939ee57f61c8l,0x0c0daa891ead643dl,
-            0x68930023e125b88el },
-          0 },
-        /* 13 << 0 */
-        { { 0xccc425634b2ed709l,0x0e356769856fd30dl,0xbcbcd43f559e9811l,
-            0x738477ac5395b759l },
-          { 0x35752b90c00ee17fl,0x68748390742ed2e3l,0x7cd06422bd1f5bc1l,
-            0xfbc08769c9e7b797l },
-          0 },
-        /* 15 << 0 */
-        { { 0x72bcd8b7bc60055bl,0x03cc23ee56e27e4bl,0xee337424e4819370l,
-            0xe2aa0e430ad3da09l },
-          { 0x40b8524f6383c45dl,0xd766355442a41b25l,0x64efa6de778a4797l,
-            0x2042170a7079adf4l },
-          0 },
-        /* 16 << 0 */
-        { { 0x808b0b650bc6fb80l,0x5882e0753ffe2e6bl,0xd5ef2f7c2c83f549l,
-            0x54d63c809103b723l },
-          { 0xf2f11bd652a23f9bl,0x3670c3194b0b6587l,0x55c4623bb1580e9el,
-            0x64edf7b201efe220l },
-          0 },
-        /* 17 << 0 */
-        { { 0x97091dcbd53c5c9dl,0xf17624b6ac0a177bl,0xb0f139752cfe2dffl,
-            0xc1a35c0a6c7a574el },
-          { 0x227d314693e79987l,0x0575bf30e89cb80el,0x2f4e247f0d1883bbl,
-            0xebd512263274c3d0l },
-          0 },
-        /* 19 << 0 */
-        { { 0xfea912baa5659ae8l,0x68363aba25e1a16el,0xb8842277752c41acl,
-            0xfe545c282897c3fcl },
-          { 0x2d36e9e7dc4c696bl,0x5806244afba977c5l,0x85665e9be39508c1l,
-            0xf720ee256d12597bl },
-          0 },
-        /* 21 << 0 */
-        { { 0x562e4cecc135b208l,0x74e1b2654783f47dl,0x6d2a506c5a3f3b30l,
-            0xecead9f4c16762fcl },
-          { 0xf29dd4b2e286e5b9l,0x1b0fadc083bb3c61l,0x7a75023e7fac29a4l,
-            0xc086d5f1c9477fa3l },
-          0 },
-        /* 23 << 0 */
-        { { 0xf4f876532de45068l,0x37c7a7e89e2e1f6el,0xd0825fa2a3584069l,
-            0xaf2cea7c1727bf42l },
-          { 0x0360a4fb9e4785a9l,0xe5fda49c27299f4al,0x48068e1371ac2f71l,
-            0x83d0687b9077666fl },
-          0 },
-        /* 25 << 0 */
-        { { 0xa4a319acd837879fl,0x6fc1b49eed6b67b0l,0xe395993332f1f3afl,
-            0x966742eb65432a2el },
-          { 0x4b8dc9feb4966228l,0x96cc631243f43950l,0x12068859c9b731eel,
-            0x7b948dc356f79968l },
-          0 },
-        /* 27 << 0 */
-        { { 0x042c2af497e2feb4l,0xd36a42d7aebf7313l,0x49d2c9eb084ffdd7l,
-            0x9f8aa54b2ef7c76al },
-          { 0x9200b7ba09895e70l,0x3bd0c66fddb7fb58l,0x2d97d10878eb4cbbl,
-            0x2d431068d84bde31l },
-          0 },
-        /* 28 << 0 */
-        { { 0x4b523eb7172ccd1fl,0x7323cb2830a6a892l,0x97082ec0cfe153ebl,
-            0xe97f6b6af2aadb97l },
-          { 0x1d3d393ed1a83da1l,0xa6a7f9c7804b2a68l,0x4a688b482d0cb71el,
-            0xa9b4cc5f40585278l },
-          0 },
-        /* 29 << 0 */
-        { { 0x5e5db46acb66e132l,0xf1be963a0d925880l,0x944a70270317b9e2l,
-            0xe266f95948603d48l },
-          { 0x98db66735c208899l,0x90472447a2fb18a3l,0x8a966939777c619fl,
-            0x3798142a2a3be21bl },
-          0 },
-        /* 31 << 0 */
-        { { 0xe2f73c696755ff89l,0xdd3cf7e7473017e6l,0x8ef5689d3cf7600dl,
-            0x948dc4f8b1fc87b4l },
-          { 0xd9e9fe814ea53299l,0x2d921ca298eb6028l,0xfaecedfd0c9803fcl,
-            0xf38ae8914d7b4745l },
-          0 },
-        /* 33 << 0 */
-        { { 0x871514560f664534l,0x85ceae7c4b68f103l,0xac09c4ae65578ab9l,
-            0x33ec6868f044b10cl },
-          { 0x6ac4832b3a8ec1f1l,0x5509d1285847d5efl,0xf909604f763f1574l,
-            0xb16c4303c32f63c4l },
-          0 },
-        /* 34 << 0 */
-        { { 0xb6ab20147ca23cd3l,0xcaa7a5c6a391849dl,0x5b0673a375678d94l,
-            0xc982ddd4dd303e64l },
-          { 0xfd7b000b5db6f971l,0xbba2cb1f6f876f92l,0xc77332a33c569426l,
-            0xa159100c570d74f8l },
-          0 },
-        /* 35 << 0 */
-        { { 0xfd16847fdec67ef5l,0x742ee464233e76b7l,0x0b8e4134efc2b4c8l,
-            0xca640b8642a3e521l },
-          { 0x653a01908ceb6aa9l,0x313c300c547852d5l,0x24e4ab126b237af7l,
-            0x2ba901628bb47af8l },
-          0 },
-        /* 36 << 0 */
-        { { 0x3d5e58d6a8219bb7l,0xc691d0bd1b06c57fl,0x0ae4cb10d257576el,
-            0x3569656cd54a3dc3l },
-          { 0xe5ebaebd94cda03al,0x934e82d3162bfe13l,0x450ac0bae251a0c6l,
-            0x480b9e11dd6da526l },
-          0 },
-        /* 37 << 0 */
-        { { 0x00467bc58cce08b5l,0xb636458c7f178d55l,0xc5748baea677d806l,
-            0x2763a387dfa394ebl },
-          { 0xa12b448a7d3cebb6l,0xe7adda3e6f20d850l,0xf63ebce51558462cl,
-            0x58b36143620088a8l },
-          0 },
-        /* 39 << 0 */
-        { { 0xa9d89488a059c142l,0x6f5ae714ff0b9346l,0x068f237d16fb3664l,
-            0x5853e4c4363186acl },
-          { 0xe2d87d2363c52f98l,0x2ec4a76681828876l,0x47b864fae14e7b1cl,
-            0x0c0bc0e569192408l },
-          0 },
-        /* 40 << 0 */
-        { { 0xe4d7681db82e9f3el,0x83200f0bdf25e13cl,0x8909984c66f27280l,
-            0x462d7b0075f73227l },
-          { 0xd90ba188f2651798l,0x74c6e18c36ab1c34l,0xab256ea35ef54359l,
-            0x03466612d1aa702fl },
-          0 },
-        /* 41 << 0 */
-        { { 0x624d60492ed22e91l,0x6fdfe0b56f072822l,0xeeca111539ce2271l,
-            0x98100a4fdb01614fl },
-          { 0xb6b0daa2a35c628fl,0xb6f94d2ec87e9a47l,0xc67732591d57d9cel,
-            0xf70bfeec03884a7bl },
-          0 },
-        /* 43 << 0 */
-        { { 0x4ff23ffd248a7d06l,0x80c5bfb4878873fal,0xb7d9ad9005745981l,
-            0x179c85db3db01994l },
-          { 0xba41b06261a6966cl,0x4d82d052eadce5a8l,0x9e91cd3ba5e6a318l,
-            0x47795f4f95b2dda0l },
-          0 },
-        /* 44 << 0 */
-        { { 0xecfd7c1fd55a897cl,0x009194abb29110fbl,0x5f0e2046e381d3b0l,
-            0x5f3425f6a98dd291l },
-          { 0xbfa06687730d50dal,0x0423446c4b083b7fl,0x397a247dd69d3417l,
-            0xeb629f90387ba42al },
-          0 },
-        /* 45 << 0 */
-        { { 0x1ee426ccd5cd79bfl,0x0032940b946c6e18l,0x1b1e8ae057477f58l,
-            0xe94f7d346d823278l },
-          { 0xc747cb96782ba21al,0xc5254469f72b33a5l,0x772ef6dec7f80c81l,
-            0xd73acbfe2cd9e6b5l },
-          0 },
-        /* 46 << 0 */
-        { { 0x4075b5b149ee90d9l,0x785c339aa06e9ebal,0xa1030d5babf825e0l,
-            0xcec684c3a42931dcl },
-          { 0x42ab62c9c1586e63l,0x45431d665ab43f2bl,0x57c8b2c055f7835dl,
-            0x033da338c1b7f865l },
-          0 },
-        /* 47 << 0 */
-        { { 0x283c7513caa76097l,0x0a624fa936c83906l,0x6b20afec715af2c7l,
-            0x4b969974eba78bfdl },
-          { 0x220755ccd921d60el,0x9b944e107baeca13l,0x04819d515ded93d4l,
-            0x9bbff86e6dddfd27l },
-          0 },
-        /* 48 << 0 */
-        { { 0x6b34413077adc612l,0xa7496529bbd803a0l,0x1a1baaa76d8805bdl,
-            0xc8403902470343adl },
-          { 0x39f59f66175adff1l,0x0b26d7fbb7d8c5b7l,0xa875f5ce529d75e3l,
-            0x85efc7e941325cc2l },
-          0 },
-        /* 49 << 0 */
-        { { 0x21950b421ff6acd3l,0xffe7048453dc6909l,0xff4cd0b228766127l,
-            0xabdbe6084fb7db2bl },
-          { 0x837c92285e1109e8l,0x26147d27f4645b5al,0x4d78f592f7818ed8l,
-            0xd394077ef247fa36l },
-          0 },
-        /* 51 << 0 */
-        { { 0x508cec1c3b3f64c9l,0xe20bc0ba1e5edf3fl,0xda1deb852f4318d4l,
-            0xd20ebe0d5c3fa443l },
-          { 0x370b4ea773241ea3l,0x61f1511c5e1a5f65l,0x99a5e23d82681c62l,
-            0xd731e383a2f54c2dl },
-          0 },
-        /* 52 << 0 */
-        { { 0x2692f36e83445904l,0x2e0ec469af45f9c0l,0x905a3201c67528b7l,
-            0x88f77f34d0e5e542l },
-          { 0xf67a8d295864687cl,0x23b92eae22df3562l,0x5c27014b9bbec39el,
-            0x7ef2f2269c0f0f8dl },
-          0 },
-        /* 53 << 0 */
-        { { 0x97359638546c4d8dl,0x5f9c3fc492f24679l,0x912e8beda8c8acd9l,
-            0xec3a318d306634b0l },
-          { 0x80167f41c31cb264l,0x3db82f6f522113f2l,0xb155bcd2dcafe197l,
-            0xfba1da5943465283l },
-          0 },
-        /* 55 << 0 */
-        { { 0x258bbbf9e7305683l,0x31eea5bf07ef5be6l,0x0deb0e4a46c814c1l,
-            0x5cee8449a7b730ddl },
-          { 0xeab495c5a0182bdel,0xee759f879e27a6b4l,0xc2cf6a6880e518cal,
-            0x25e8013ff14cf3f4l },
-          0 },
-        /* 57 << 0 */
-        { { 0x3ec832e77acaca28l,0x1bfeea57c7385b29l,0x068212e3fd1eaf38l,
-            0xc13298306acf8cccl },
-          { 0xb909f2db2aac9e59l,0x5748060db661782al,0xc5ab2632c79b7a01l,
-            0xda44c6c600017626l },
-          0 },
-        /* 59 << 0 */
-        { { 0x69d44ed65c46aa8el,0x2100d5d3a8d063d1l,0xcb9727eaa2d17c36l,
-            0x4c2bab1b8add53b7l },
-          { 0xa084e90c15426704l,0x778afcd3a837ebeal,0x6651f7017ce477f8l,
-            0xa062499846fb7a8bl },
-          0 },
-        /* 60 << 0 */
-        { { 0xdc1e6828ed8a6e19l,0x33fc23364189d9c7l,0x026f8fe2671c39bcl,
-            0xd40c4ccdbc6f9915l },
-          { 0xafa135bbf80e75cal,0x12c651a022adff2cl,0xc40a04bd4f51ad96l,
-            0x04820109bbe4e832l },
-          0 },
-        /* 61 << 0 */
-        { { 0x3667eb1a7f4c04ccl,0x59556621a9404f84l,0x71cdf6537eceb50al,
-            0x994a44a69b8335fal },
-          { 0xd7faf819dbeb9b69l,0x473c5680eed4350dl,0xb6658466da44bba2l,
-            0x0d1bc780872bdbf3l },
-          0 },
-        /* 63 << 0 */
-        { { 0xb8d3d9319ff91fe5l,0x039c4800f0518eedl,0x95c376329182cb26l,
-            0x0763a43482fc568dl },
-          { 0x707c04d5383e76bal,0xac98b930824e8197l,0x92bf7c8f91230de0l,
-            0x90876a0140959b70l },
-          0 },
-        /* 64 << 0 */
-        { { 0xdb6d96f305968b80l,0x380a0913089f73b9l,0x7da70b83c2c61e01l,
-            0x95fb8394569b38c7l },
-          { 0x9a3c651280edfe2fl,0x8f726bb98faeaf82l,0x8010a4a078424bf8l,
-            0x296720440e844970l },
-          0 },
-        /* 65 << 0 */
-        { { 0xdc2306ebfcdbb2b2l,0x79527db7ba66f4b9l,0xbf639ed67765765el,
-            0x01628c4706b6090al },
-          { 0x66eb62f1b957b4a1l,0x33cb7691ba659f46l,0x2c90d98cf3e055d6l,
-            0x7d096ac42f174750l },
-          0 },
-        /* 71 << 0 */
-        { { 0xf19f382e92aa7864l,0x49c7cb94fc05804bl,0xf94aa89b40750d01l,
-            0xdd421b5d4a210364l },
-          { 0x56cd001e39df3672l,0x030a119fdd4af1ecl,0x11f947e696cd0572l,
-            0x574cc7b293786791l },
-          0 },
-        /* 77 << 0 */
-        { { 0x0a2193bfc266f85cl,0x719a87be5a0ec9cel,0x9c30c6422b2f9c49l,
-            0xdb15e4963d5baeb1l },
-          { 0x83c3139be0d37321l,0x4788522b2e9fdbb2l,0x2b4f0c7877eb94eal,
-            0x854dc9d595105f9el },
-          0 },
-        /* 83 << 0 */
-        { { 0x2c9ee62dc3363a22l,0x125d4714ec67199al,0xf87abebf2ab80485l,
-            0xcf3086e87a243ca4l },
-          { 0x5c52b051c64e09ddl,0x5e9b16125625aad7l,0x0536a39db19c6126l,
-            0x97f0013247b64be5l },
-          0 },
-        /* 89 << 0 */
-        { { 0xc1ee6264a7eabe67l,0x62d51e29fd54487dl,0x3ea123446310eb5al,
-            0xbd88aca74765b805l },
-          { 0xb7b284be14fb691al,0x640388f83b9fffefl,0x7ab49dd209f98f9al,
-            0x7150f87e7211e445l },
-          0 },
-        /* 95 << 0 */
-        { { 0x263e039bb308cc40l,0x6684ad762b346fd2l,0x9a127f2bcaa12d0dl,
-            0x76a8f9fea974291fl },
-          { 0xc802049b68aa19e4l,0x65499c990c5dbba0l,0xee1b1cb5344455a1l,
-            0x3f293fda2cd6f439l },
-          0 },
-        /* 101 << 0 */
-        { { 0xb7a96e0a4ea6fdf7l,0xbbe914d3b99cd026l,0x6a610374c569a602l,
-            0xe9b1c23914da499el },
-          { 0xb5f6f0feadc19a99l,0x731251826f21687cl,0x5a8a14644be77793l,
-            0x94ce9e0adba8bfc7l },
-          0 },
-        /* 107 << 0 */
-        { { 0x2ca0ba9c3796f4c7l,0x3571e4d1592ce334l,0x28f9cdebe9f6e877l,
-            0xee206023efce1a70l },
-          { 0xb2159e08b76369dcl,0x2754e4260a7f687cl,0xe008039e02de2ff1l,
-            0xccd7e9418ea700c1l },
-          0 },
-        /* 113 << 0 */
-        { { 0xa125e6c1b7ebcb88l,0x3289e86e10ec0d40l,0xcc3a5ecb98353869l,
-            0x734e0d078a2b0d3al },
-          { 0xe0d92e9a51933360l,0xfa6bcdb1786076b9l,0xd13cca90747f19ecl,
-            0x61d8209d49f3a53dl },
-          0 },
-        /* 116 << 0 */
-        { { 0x87f9793bc9826344l,0x4b3de89bb2f5f79cl,0xc9f08a5659cb1b6el,
-            0xd8f1fc5f6a92b9aal },
-          { 0x86357f9eb412595el,0x53c30bbe65b80f16l,0xf06c2c8c70549a57l,
-            0xa9c8a4b42b9157dal },
-          0 },
-        /* 119 << 0 */
-        { { 0x87af199e6cc47305l,0x062afb7c1e314ddel,0x2be22ba0f3a49fb4l,
-            0x6ed0b988157b7f56l },
-          { 0x8162cf502d653fd9l,0x17d29c64877b7497l,0xd7e814380f67b514l,
-            0xfedf1014fe6ee703l },
-          0 },
-        /* 125 << 0 */
-        { { 0xaab54cfc93740130l,0xf72dab6d225733fal,0x04b76d2d1ed32559l,
-            0xa9fe2396bb85b9cbl },
-          { 0x128b0d24bf2219f0l,0x2292393b579f3ce2l,0x51dc5fac145ff0d5l,
-            0xb16d6af8c3febbc1l },
-          0 },
-    },
-    {
-        /* 0 << 8 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 8 */
-        { { 0x486d8ffa696946fcl,0x50fbc6d8b9cba56dl,0x7e3d423e90f35a15l,
-            0x7c3da195c0dd962cl },
-          { 0xe673fdb03cfd5d8bl,0x0704b7c2889dfca5l,0xf6ce581ff52305aal,
-            0x399d49eb914d5e53l },
-          0 },
-        /* 3 << 8 */
-        { { 0x35d6a53eed4c3717l,0x9f8240cf3d0ed2a3l,0x8c0d4d05e5543aa5l,
-            0x45d5bbfbdd33b4b4l },
-          { 0xfa04cc73137fd28el,0x862ac6efc73b3ffdl,0x403ff9f531f51ef2l,
-            0x34d5e0fcbc73f5a2l },
-          0 },
-        /* 4 << 8 */
-        { { 0x4f7081e144cc3addl,0xd5ffa1d687be82cfl,0x89890b6c0edd6472l,
-            0xada26e1a3ed17863l },
-          { 0x276f271563483caal,0xe6924cd92f6077fdl,0x05a7fe980a466e3cl,
-            0xf1c794b0b1902d1fl },
-          0 },
-        /* 5 << 8 */
-        { { 0x33b2385c08369a90l,0x2990c59b190eb4f8l,0x819a6145c68eac80l,
-            0x7a786d622ec4a014l },
-          { 0x33faadbe20ac3a8dl,0x31a217815aba2d30l,0x209d2742dba4f565l,
-            0xdb2ce9e355aa0fbbl },
-          0 },
-        /* 7 << 8 */
-        { { 0x0c4a58d474a86108l,0xf8048a8fee4c5d90l,0xe3c7c924e86d4c80l,
-            0x28c889de056a1e60l },
-          { 0x57e2662eb214a040l,0xe8c48e9837e10347l,0x8774286280ac748al,
-            0xf1c24022186b06f2l },
-          0 },
-        /* 9 << 8 */
-        { { 0xe8cbf1e5d5923359l,0xdb0cea9d539b9fb0l,0x0c5b34cf49859b98l,
-            0x5e583c56a4403cc6l },
-          { 0x11fc1a2dd48185b7l,0xc93fbc7e6e521787l,0x47e7a05805105b8bl,
-            0x7b4d4d58db8260c8l },
-          0 },
-        /* 10 << 8 */
-        { { 0xb31bd6136339c083l,0x39ff8155dfb64701l,0x7c3388d2e29604abl,
-            0x1e19084ba6b10442l },
-          { 0x17cf54c0eccd47efl,0x896933854a5dfb30l,0x69d023fb47daf9f6l,
-            0x9222840b7d91d959l },
-          0 },
-        /* 11 << 8 */
-        { { 0xc510610939842194l,0xb7e2353e49d05295l,0xfc8c1d5cefb42ee0l,
-            0xe04884eb08ce811cl },
-          { 0xf1f75d817419f40el,0x5b0ac162a995c241l,0x120921bbc4c55646l,
-            0x713520c28d33cf97l },
-          0 },
-        /* 13 << 8 */
-        { { 0x41d04ee21726931al,0x0bbbb2c83660ecfdl,0xa6ef6de524818e18l,
-            0xe421cc51e7d57887l },
-          { 0xf127d208bea87be6l,0x16a475d3b1cdd682l,0x9db1b684439b63f7l,
-            0x5359b3dbf0f113b6l },
-          0 },
-        /* 15 << 8 */
-        { { 0x3a5c752edcc18770l,0x4baf1f2f8825c3a5l,0xebd63f7421b153edl,
-            0xa2383e47b2f64723l },
-          { 0xe7bf620a2646d19al,0x56cb44ec03c83ffdl,0xaf7267c94f6be9f1l,
-            0x8b2dfd7bc06bb5e9l },
-          0 },
-        /* 16 << 8 */
-        { { 0x6772b0e5ab4b35a2l,0x1d8b6001f5eeaacfl,0x728f7ce4795b9580l,
-            0x4a20ed2a41fb81dal },
-          { 0x9f685cd44fec01e6l,0x3ed7ddcca7ff50adl,0x460fd2640c2d97fdl,
-            0x3a241426eb82f4f9l },
-          0 },
-        /* 17 << 8 */
-        { { 0xc503cd33bccd9617l,0x365dede4ba7730a3l,0x798c63555ddb0786l,
-            0xa6c3200efc9cd3bcl },
-          { 0x060ffb2ce5e35efdl,0x99a4e25b5555a1c1l,0x11d95375f70b3751l,
-            0x0a57354a160e1bf6l },
-          0 },
-        /* 19 << 8 */
-        { { 0xc033bdc719803511l,0xa9f97b3b8888c3bel,0x3d68aebc85c6d05el,
-            0xc3b88a9d193919ebl },
-          { 0x2d300748c48b0ee3l,0x7506bc7c07a746c1l,0xfc48437c6e6d57f3l,
-            0x5bd71587cfeaa91al },
-          0 },
-        /* 21 << 8 */
-        { { 0xe40736d3df61bc76l,0x13a619c03f778cdbl,0x6dd921a4c56ea28fl,
-            0x76a524332fa647b4l },
-          { 0x23591891ac5bdc5dl,0xff4a1a72bac7dc01l,0x9905e26162df8453l,
-            0x3ac045dfe63b265fl },
-          0 },
-        /* 23 << 8 */
-        { { 0x8435bd6994b03ed1l,0xd9ad1de3634cc546l,0x2cf423fc00e420cal,
-            0xeed26d80a03096ddl },
-          { 0xd7f60be7a4db09d2l,0xf47f569d960622f7l,0xe5925fd77296c729l,
-            0xeff2db2626ca2715l },
-          0 },
-        /* 25 << 8 */
-        { { 0x5dfee80f83774bddl,0x6313160285734485l,0xa1b524ae914a69a9l,
-            0xebc2ffafd4e300d7l },
-          { 0x52c93db77cfa46a5l,0x71e6161f21653b50l,0x3574fc57a4bc580al,
-            0xc09015dde1bc1253l },
-          0 },
-        /* 27 << 8 */
-        { { 0x9c38ddcceb5b76c1l,0x746f528526fc0ab4l,0x52a63a50d62c269fl,
-            0x60049c5599458621l },
-          { 0xe7f48f823c2f7c9el,0x6bd99043917d5cf3l,0xeb1317a88701f469l,
-            0xbd3fe2ed9a449fe0l },
-          0 },
-        /* 28 << 8 */
-        { { 0xe652533b3cef0d7dl,0xd94f7b182bbb4381l,0x838752be0e80f500l,
-            0x8e6e24889e9c9bfbl },
-          { 0xc975169716caca6al,0x866c49d838531ad9l,0xc917e2397151ade1l,
-            0x2d016ec16037c407l },
-          0 },
-        /* 29 << 8 */
-        { { 0x202f6a9c31c71f7bl,0x01f95aa3296ffe5cl,0x5fc0601453cec3a3l,
-            0xeb9912375f498a45l },
-          { 0xae9a935e5d91ba87l,0xc6ac62810b564a19l,0x8a8fe81c3bd44e69l,
-            0x7c8b467f9dd11d45l },
-          0 },
-        /* 31 << 8 */
-        { { 0x21d3634d39eedbbal,0x35cd2e680455a46dl,0xc8cafe65f9d7eb0cl,
-            0xbda3ce9e00cefb3el },
-          { 0xddc17a602c9cf7a4l,0x01572ee47bcb8773l,0xa92b2b018c7548dfl,
-            0x732fd309a84600e3l },
-          0 },
-        /* 33 << 8 */
-        { { 0x65cf89a2e0600afal,0xcf51482f753c5ceal,0x4f2b2d25a5c2bfc5l,
-            0x9381f57187098256l },
-          { 0x89210f676e976e4bl,0xe2cf12f489f47a7bl,0xc21a1658e8484050l,
-            0xa224dbf82f0fff01l },
-          0 },
-        /* 34 << 8 */
-        { { 0xc28961087282513dl,0x9a78c4296a3f8fb8l,0xddfa56f9a31e24b7l,
-            0xb1e14f84fb72611fl },
-          { 0x1d0f70ab45078d65l,0xb247aef3819924d8l,0x8d519f9dbb9877c1l,
-            0x495c2ece8368c7c9l },
-          0 },
-        /* 35 << 8 */
-        { { 0xca9129a0bdb69d12l,0xbe3e319978f39adfl,0xa88506df5fe49438l,
-            0x17ddb7a7aafe894cl },
-          { 0x28d1456f6d1d742fl,0xeec09651917d1268l,0xdecb1c700fd5b4c0l,
-            0x32d14f6acf2861dbl },
-          0 },
-        /* 36 << 8 */
-        { { 0x903f6e3960e913afl,0xb2b58bee98bf140dl,0x9deff025354890b8l,
-            0x155810068d2e924el },
-          { 0xb5755db493c95e5bl,0x3fac42f0dae20eb8l,0x9377c8c109b6d8e0l,
-            0xa43e2b46ab47ceffl },
-          0 },
-        /* 37 << 8 */
-        { { 0x6c3f5a51cb61e7e7l,0x264aebc80d9c73b2l,0xc404b2114a0d9288l,
-            0x5178d3cf8b3a79e9l },
-          { 0x4080be5372a420d7l,0xa39396adef026429l,0x22fbb92e8dde4728l,
-            0x19e42d8874d949fcl },
-          0 },
-        /* 39 << 8 */
-        { { 0xde352d78387f5557l,0x6770149969367413l,0x255bb8c00b0cc102l,
-            0x63cad1be1f4d262el },
-          { 0xf34f9a8a3f8f4fb6l,0x32bc13aae03a969fl,0xb29d4336218371cdl,
-            0x799d76ab285bd210l },
-          0 },
-        /* 40 << 8 */
-        { { 0x5f57b2fbfacfa459l,0x874b1498c1b5aa6bl,0xb9e89acac4db2092l,
-            0x1362bf8ddf4381dal },
-          { 0x25d76830b76328a0l,0x38188b7098572ae4l,0xb43e941429132f7dl,
-            0x7895a29f22dd42c9l },
-          0 },
-        /* 41 << 8 */
-        { { 0x85bded619e808c05l,0x6e0fc2bcc7ef83bbl,0xed70e0b499bedf77l,
-            0x300e777dc1aaffc0l },
-          { 0xe2da2359c43e6d2cl,0xacf6d60a275226e0l,0x18ca38f7f82558bdl,
-            0xd7b017d475ae2591l },
-          0 },
-        /* 43 << 8 */
-        { { 0xed299e2d7cd92ee2l,0x2c08eb37ad847153l,0x7b372aa712acfd81l,
-            0x574d27f5fabda29cl },
-          { 0xbd8247f0f2ee6ebcl,0x8bf76710d06be261l,0x26e95b4bcb186d4cl,
-            0x4fa3ac1d1ebb4a46l },
-          0 },
-        /* 44 << 8 */
-        { { 0xcbde78dd5e22cbb2l,0xf449c85b76bb4391l,0x4289f357b6a4273bl,
-            0x9fce23fd48e84a19l },
-          { 0xcfc32730939eb3b4l,0x8b3d982c16c32280l,0x5ac234bad5f1346cl,
-            0x781954b470769fc9l },
-          0 },
-        /* 45 << 8 */
-        { { 0xff0d4d30062c7dbdl,0x2c483081e6f9fcf0l,0x22f96316d67e070fl,
-            0xdd9be459c0e68c44l },
-          { 0xb9c1edffce2edd4dl,0x1a54782021fc538cl,0x93849be49979aee1l,
-            0x3f313629a590949el },
-          0 },
-        /* 46 << 8 */
-        { { 0x160b836b266be332l,0x49de38215f340575l,0x782e8f6701edce66l,
-            0x83ae008b5df1a93el },
-          { 0x85d33a263ed9ffebl,0xae2f9f961e79db97l,0xf64f209b95ae9e34l,
-            0x2b6b03455e957d49l },
-          0 },
-        /* 47 << 8 */
-        { { 0x7a24a21a331d6bdal,0xfdba302f6328f742l,0x37a36dd47744dca4l,
-            0xda2832ce6fef500fl },
-          { 0x23da304a7b49d73al,0xeede2cebc6ad834fl,0xf21a81248dec3c78l,
-            0x4bc9469b19b721e3l },
-          0 },
-        /* 48 << 8 */
-        { { 0x6faf68feaae6ee70l,0x78f4cc155602b0c9l,0x7e3321a86e94052al,
-            0x2fb3a0d6734d5d80l },
-          { 0xf3b98f3bb25a43bal,0x30bf803119ee2951l,0x7ffee43321b0612al,
-            0x12f775e42eb821d0l },
-          0 },
-        /* 49 << 8 */
-        { { 0x31cc342913e5c1d6l,0x05deaa3cee54e334l,0x21ea2b61cd5087d8l,
-            0x73a1841e70d1b8bcl },
-          { 0xd44e2b41b078bf14l,0xc295732fcea2a30el,0x30cdab42954939f7l,
-            0xc1b4e43a2dba0b7cl },
-          0 },
-        /* 51 << 8 */
-        { { 0x5f33f618b6a20132l,0xc8d73e3cfbbf3022l,0xf3b9844d47ed4320l,
-            0xab5868aa927f00cal },
-          { 0x06cb1113077f6e1cl,0x1417b43a5c94faaal,0x7666cb90cf4cd1e9l,
-            0x99e009f210900566l },
-          0 },
-        /* 52 << 8 */
-        { { 0x4fdff805f57209b5l,0x9bd65ac3f952ac8dl,0x02a3abd3c7969a6fl,
-            0x1359927ef523775fl },
-          { 0xe09b463f88d2e861l,0x661d2199623287c3l,0x821e64495a70eb7al,
-            0x0afbbb1dd67dc684l },
-          0 },
-        /* 53 << 8 */
-        { { 0x2c5a2b2d55750eb2l,0x54d756c29dc28d9fl,0x798c8d113af97f71l,
-            0x54e21ee21f6d1853l },
-          { 0x34e0c8bceffc3f8al,0xed3cc4dda96f193fl,0x86436a84fad97110l,
-            0x8530ca522c97205el },
-          0 },
-        /* 55 << 8 */
-        { { 0x9b6c8452f7236867l,0x21cf260c777b44fdl,0x659fc99dceb00c52l,
-            0xda97098e2439e8dbl },
-          { 0x647efe510ed6e14fl,0x37c8ca122a6600f3l,0x53e89b0badf6f4a7l,
-            0xd9fc8c716645618al },
-          0 },
-        /* 57 << 8 */
-        { { 0x9cecfb8eee6ebd31l,0x4603994b1ff25529l,0x707bc80af4b141c4l,
-            0x3a83d56c07524d3al },
-          { 0x7035c746613a3020l,0x7aa766b286626a1cl,0x3af656095ac76c78l,
-            0x4039c655171e47d6l },
-          0 },
-        /* 59 << 8 */
-        { { 0x79cb147f0ce33b63l,0xa1328a622d160c61l,0xf99538f3cf7eb87el,
-            0x0334d4958e2241d5l },
-          { 0x3ad97e02f3e49e48l,0xdcfcc754037c3679l,0x76078ba61a8ff67cl,
-            0x8054aa55c2a64964l },
-          0 },
-        /* 60 << 8 */
-        { { 0x5852104b87453b28l,0x073e8128b387344dl,0x300e78e4817cfc08l,
-            0x3a82ed4799362088l },
-          { 0xe222304c88de46a4l,0x666c94fd57fadf4al,0x40b2d08ea0c8e108l,
-            0x4b2955b909e050fal },
-          0 },
-        /* 61 << 8 */
-        { { 0x656078565f814881l,0x0fc3d1ce58466117l,0x0ae377d3c6c1e68al,
-            0xe3dd8d5cba566c48l },
-          { 0x9404849ec4b63be6l,0x1e22b03ba5be9c92l,0x08145122a8b03e63l,
-            0x71248243771fe153l },
-          0 },
-        /* 63 << 8 */
-        { { 0xa80a0e83b41ac541l,0xa77570ea533e5f9bl,0x416a14c0216dc452l,
-            0x2a8d728a19f7ee59l },
-          { 0x58494c8cd6552eaal,0x4d635acd60145722l,0xa8e9b127327b1cbcl,
-            0xb429a62e9f8235f0l },
-          0 },
-        /* 64 << 8 */
-        { { 0xf8d112e76e6485b3l,0x4d3e24db771c52f8l,0x48e3ee41684a2f6dl,
-            0x7161957d21d95551l },
-          { 0x19631283cdb12a6cl,0xbf3fa8822e50e164l,0xf6254b633166cc73l,
-            0x3aefa7aeaee8cc38l },
-          0 },
-        /* 65 << 8 */
-        { { 0xd52d2cb746ef1c7el,0xebd4f7c4d8fb6e07l,0x16f77a48cf6dd2b4l,
-            0x6e8f0431e77e4d51l },
-          { 0x59d94cc4e9177bf2l,0xb58a578f7a7181a1l,0xeefbc4cde8f6d330l,
-            0xa66c85560fe05490l },
-          0 },
-        /* 71 << 8 */
-        { { 0x0e6db7a35d9649dal,0x4d2f25193be3d362l,0xcd891fd5a6b137b5l,
-            0xa4b7e4ddacd377a9l },
-          { 0x20ccd6f24355f258l,0x842c08673aafb413l,0xdd55db99d6873b88l,
-            0x04d15f4fea5a2a55l },
-          0 },
-        /* 77 << 8 */
-        { { 0x679cd93dfae289c2l,0x84cadd61ff92ba1bl,0x548b5a6f2cd734aal,
-            0x1827507db8267082l },
-          { 0xa903a6010c6d5b4cl,0xde0d96befdfb952bl,0x2fc9419c6a2e24f9l,
-            0x27333e3936bb3203l },
-          0 },
-        /* 83 << 8 */
-        { { 0x3eb7f062dde4aa6al,0x40effae07f354cc0l,0xe9a14bc2a066c05el,
-            0x7817b11356afc543l },
-          { 0x5f0ed1f28bdda262l,0x001e23d2e007ec13l,0x435878a59c57de6al,
-            0x84d0e20895ac263cl },
-          0 },
-        /* 89 << 8 */
-        { { 0xedf24aec97a66678l,0xd1f93cf8ccf55671l,0x4ed2ce8a9379a49dl,
-            0x64991862c39b0ac9l },
-          { 0xc15b24e31ff67e04l,0x4ee8fc76c3c084fel,0x262012b4f64bcd46l,
-            0x3b5086732425c622l },
-          0 },
-        /* 95 << 8 */
-        { { 0xaa3e451fe65002f7l,0xf5ff2617eb46d253l,0x918d146e572afca2l,
-            0x0a9333b7e56a8553l },
-          { 0x9b7e232d94127dc0l,0xcd0687d6831014e6l,0x725ce5baf08e1c71l,
-            0x56e26f48cde0e4edl },
-          0 },
-        /* 101 << 8 */
-        { { 0xae78dde8db833460l,0xaf1736fe762cb78al,0x5cd85742eae5ac60l,
-            0x7b6c52fe955e981al },
-          { 0x9f823e8555599f97l,0xb9ce70d21a4b46b3l,0xb6076175d7d09829l,
-            0x21e77d22abf390a4l },
-          0 },
-        /* 107 << 8 */
-        { { 0xf704f09da142ad7el,0xb60ec2e1bab9f5d2l,0x4180314681e54d0dl,
-            0x0de50506309335e6l },
-          { 0x4135374e05aec64fl,0xb5d31041b556808al,0x0092eb86049033a8l,
-            0x5b7a2fa0bde0d737l },
-          0 },
-        /* 113 << 8 */
-        { { 0xc0dfa6bbefb40cfal,0x86a6fe279c5037f3l,0xf153cd37f71155f4l,
-            0xf16d6029767664f9l },
-          { 0x7441aa54c635aa57l,0x547f82e9e8186b2el,0x330b464bfbf7c7fel,
-            0xb5556770a1f6fddel },
-          0 },
-        /* 116 << 8 */
-        { { 0xa0a9c5d1e8f9edf1l,0x9814c26b6946cea3l,0xcbb47a37d8e6a08dl,
-            0x517a3d9b2cba11b1l },
-          { 0x94edc73dab43c540l,0x4fd0b82a753e552cl,0x419aab8bd14ae853l,
-            0x94955f9ca68abad8l },
-          0 },
-        /* 119 << 8 */
-        { { 0x3a162e06ed169150l,0x8c9683a6ba1194a8l,0x53fead66ccc28d04l,
-            0xdbb2a85bef09809al },
-          { 0x58e677439d3ab018l,0xff9a2046b6e56bd0l,0xf4b8215eb28061e9l,
-            0xcf16d9f7b10e358fl },
-          0 },
-        /* 125 << 8 */
-        { { 0x265ceae9a55abe39l,0x9e3783f796a98f84l,0xb799628af0757d99l,
-            0xebb5f12665472fb3l },
-          { 0xd83619f52ba517d8l,0x5672105f50382bdfl,0x32c5681c4a12ee9fl,
-            0x31e6f60d834a9fedl },
-          0 },
-    },
-    {
-        /* 0 << 16 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 16 */
-        { { 0x0f0165fce3779ee3l,0xe00e7f9dbd495d9el,0x1fa4efa220284e7al,
-            0x4564bade47ac6219l },
-          { 0x90e6312ac4708e8el,0x4f5725fba71e9adfl,0xe95f55ae3d684b9fl,
-            0x47f7ccb11e94b415l },
-          0 },
-        /* 3 << 16 */
-        { { 0xbd9b8b1dbe7a2af3l,0xec51caa94fb74a72l,0xb9937a4b63879697l,
-            0x7c9a9d20ec2687d5l },
-          { 0x1773e44f6ef5f014l,0x8abcf412e90c6900l,0x387bd0228142161el,
-            0x50393755fcb6ff2al },
-          0 },
-        /* 4 << 16 */
-        { { 0xfabf770977f7195al,0x8ec86167adeb838fl,0xea1285a8bb4f012dl,
-            0xd68835039a3eab3fl },
-          { 0xee5d24f8309004c2l,0xa96e4b7613ffe95el,0x0cdffe12bd223ea4l,
-            0x8f5c2ee5b6739a53l },
-          0 },
-        /* 5 << 16 */
-        { { 0x3d61333959145a65l,0xcd9bc368fa406337l,0x82d11be32d8a52a0l,
-            0xf6877b2797a1c590l },
-          { 0x837a819bf5cbdb25l,0x2a4fd1d8de090249l,0x622a7de774990e5fl,
-            0x840fa5a07945511bl },
-          0 },
-        /* 7 << 16 */
-        { { 0x26e08c07e3533d77l,0xd7222e6a2e341c99l,0x9d60ec3d8d2dc4edl,
-            0xbdfe0d8f7c476cf8l },
-          { 0x1fe59ab61d056605l,0xa9ea9df686a8551fl,0x8489941e47fb8d8cl,
-            0xfeb874eb4a7f1b10l },
-          0 },
-        /* 9 << 16 */
-        { { 0x9164088d977eab40l,0x51f4c5b62760b390l,0xd238238f340dd553l,
-            0x358566c3db1d31c9l },
-          { 0x3a5ad69e5068f5ffl,0xf31435fcdaff6b06l,0xae549a5bd6debff0l,
-            0x59e5f0b775e01331l },
-          0 },
-        /* 10 << 16 */
-        { { 0x2cc5226138634818l,0x501814f4b44c2e0bl,0xf7e181aa54dfdba3l,
-            0xcfd58ff0e759718cl },
-          { 0xf90cdb14d3b507a8l,0x57bd478ec50bdad8l,0x29c197e250e5f9aal,
-            0x4db6eef8e40bc855l },
-          0 },
-        /* 11 << 16 */
-        { { 0xd5d5cdd35958cd79l,0x3580a1b51d373114l,0xa36e4c91fa935726l,
-            0xa38c534def20d760l },
-          { 0x7088e40a2ff5845bl,0xe5bb40bdbd78177fl,0x4f06a7a8857f9920l,
-            0xe3cc3e50e968f05dl },
-          0 },
-        /* 13 << 16 */
-        { { 0x10595b5696a71cbal,0x944938b2fdcadeb7l,0xa282da4cfccd8471l,
-            0x98ec05f30d37bfe1l },
-          { 0xe171ce1b0698304al,0x2d69144421bdf79bl,0xd0cd3b741b21dec1l,
-            0x712ecd8b16a15f71l },
-          0 },
-        /* 15 << 16 */
-        { { 0xe89f48c85963a46el,0x658ab875a99e61c7l,0x6e296f874b8517b4l,
-            0x36c4fcdcfc1bc656l },
-          { 0xde5227a1a3906defl,0x9fe95f5762418945l,0x20c91e81fdd96cdel,
-            0x5adbe47eda4480del },
-          0 },
-        /* 16 << 16 */
-        { { 0xa7a8746a584c5e20l,0x267e4ea1b9dc7035l,0x593a15cfb9548c9bl,
-            0x5e6e21354bd012f3l },
-          { 0xdf31cc6a8c8f936el,0x8af84d04b5c241dcl,0x63990a6f345efb86l,
-            0x6fef4e61b9b962cbl },
-          0 },
-        /* 17 << 16 */
-        { { 0xaa35809ddfe6e2a0l,0xebb4d7d4356a2222l,0x7d500a6a319f33b7l,
-            0x4895a47d4ac99011l },
-          { 0x300ab40bdf3812b2l,0xd0764ec88aec8b9fl,0x86b61d95e591b2a7l,
-            0xc1b2a0b72ed74603l },
-          0 },
-        /* 19 << 16 */
-        { { 0x6001bf5d3849c680l,0xd7a1a4e4c1d3faccl,0xa0f2776418c5e351l,
-            0x0849c0736c29c623l },
-          { 0x3317e143ac751c0cl,0x9bcb1f3eda06200bl,0x40a63a75541419b5l,
-            0x8fad9c983f62c513l },
-          0 },
-        /* 21 << 16 */
-        { { 0xacff0828d03b2242l,0x5a9375c43abb7389l,0x41b1a318d0192baal,
-            0x105bd3100458e97bl },
-          { 0x71582dc7ed496315l,0x8ab2884a4d4bda18l,0xb8b638b494bc5bb8l,
-            0xb42ed1309500bb04l },
-          0 },
-        /* 23 << 16 */
-        { { 0x73e04f02ad1ed952l,0x680051cadfa5bdb7l,0xbe0bef3c0c7437b9l,
-            0x45d6f3a40e65e627l },
-          { 0x5295e060c9436a75l,0xbe84ba78d289ba9el,0x350887fd69c09364l,
-            0xf27bfd17671c64a7l },
-          0 },
-        /* 25 << 16 */
-        { { 0xc8afbdc3adf6ffc5l,0x4a4fb35876385891l,0xc7fa86424d41453fl,
-            0x19490b7672eedd06l },
-          { 0xc883e45337d22d6al,0x8e6e38e4a9009f96l,0x44e2811eb1c560c6l,
-            0x8a0021bf4439cfcfl },
-          0 },
-        /* 27 << 16 */
-        { { 0xba768f8b7615a327l,0x6c8b320d7b15bbe7l,0x5d8d5bcbaaa9ca64l,
-            0x19a2b99f3d13cdfdl },
-          { 0x858288a26f172e10l,0x2412a4da37a00f94l,0xfc67fd2edaa7f6c6l,
-            0x4aea0eadafa2a5c5l },
-          0 },
-        /* 28 << 16 */
-        { { 0x5c80ccef6cd77b30l,0x49978299ec99b6d0l,0x6bf4485eb939d335l,
-            0xc53e61ab86d7c147l },
-          { 0xdd948052fb601dddl,0x34c5eb393511dd48l,0x91f5c67600e6f61cl,
-            0x33f1b525b1e71f34l },
-          0 },
-        /* 29 << 16 */
-        { { 0xb4cb4a151d2dad36l,0x709a61631e60b60dl,0x2f18f3bd932ece4fl,
-            0x70f495a8e92368bel },
-          { 0x6e88be2bb7aeaa6fl,0x4efebd9ae1bf1d6el,0x49925e6e44e94993l,
-            0x33b7aba0ef0517dcl },
-          0 },
-        /* 31 << 16 */
-        { { 0x69ce1f207afe6c37l,0xe1148ba984f68db5l,0x32668bdc2c594a8al,
-            0x2cb60d3063ac4fb3l },
-          { 0x5e6efe1dd9e036f8l,0x917cb2a27db4739fl,0x70ea601ded4e0b5el,
-            0x5928f068ae7ac8a6l },
-          0 },
-        /* 33 << 16 */
-        { { 0x9e4ad0073f2d96abl,0x51a9697f2d058c03l,0xcd5c0a7522d1e795l,
-            0xaa1a121c2ac4f019l },
-          { 0xa837c14c3e3631f4l,0x6a997381236a5576l,0xb305e7db2753782bl,
-            0xae561b0237243afbl },
-          0 },
-        /* 34 << 16 */
-        { { 0x20176baca787897bl,0x057b8b979a9f67d9l,0xe7d5c4f761e14e09l,
-            0x8e4856901e6cd6d0l },
-          { 0x3eeffbba9b925d52l,0xe651a5383046927bl,0x02326d1fe92d4352l,
-            0xad2d6493d697369fl },
-          0 },
-        /* 35 << 16 */
-        { { 0xe9de299c548c4ca5l,0x66f64ef54be3bde3l,0xcf6d39ebf2d5ebc9l,
-            0x665ca727898953e1l },
-          { 0x521ec435e33ac1b4l,0x8418fa7534ab2b82l,0x94d6c0c4771a3a87l,
-            0x21feb6054859ee22l },
-          0 },
-        /* 36 << 16 */
-        { { 0xde7153f8eed9dd1dl,0xba09ad1152ebcb2el,0xaa41b015e1843fb6l,
-            0xf933a2abdd4ce6f0l },
-          { 0x777f834313f6b83fl,0x28df7da4db113a75l,0x6d7d1b3c72a5d143l,
-            0x6f789698966c6ddfl },
-          0 },
-        /* 37 << 16 */
-        { { 0x57d11ed7a95e704el,0x7d5ac6dc380ad582l,0xb175421d5ab6e377l,
-            0x4e383b0ba760dd4dl },
-          { 0xde07b81a352b6cb3l,0x342abe825c2e1704l,0x90988de20dd48537l,
-            0x4a7fec0544821591l },
-          0 },
-        /* 39 << 16 */
-        { { 0xb0e4d17c90a94eb7l,0x27555067aceb0176l,0x587576e15c38c4e2l,
-            0xe647d9dd445f2880l },
-          { 0x00beb2f5ca502f83l,0x4e89e638c44767c7l,0xbef361da154a5757l,
-            0x2dc632a2dc0675f2l },
-          0 },
-        /* 40 << 16 */
-        { { 0xed439a33a72ba054l,0xa3170a15ead265bal,0xcf7eb903fe99a58el,
-            0xcf6db0c633d80c26l },
-          { 0xd031255ef613e71al,0x12ccbe5718ca255cl,0xdd21d0537808c40dl,
-            0xf5488ebc3af2be6bl },
-          0 },
-        /* 41 << 16 */
-        { { 0x589a125ac10f8157l,0x3c8a15bde1353e49l,0x7d9bbd0c22ce2dd0l,
-            0xdfcd019211ac7bb1l },
-          { 0x0e1d67151193c5b1l,0xd4de115ab0e8c285l,0x0b3e94c2272c29fel,
-            0xea640843c8213581l },
-          0 },
-        /* 43 << 16 */
-        { { 0x7a01aeed6aca2231l,0x8135cf2ace80abbel,0xdc1a41b2ae5fdec9l,
-            0xde34ea4da0174364l },
-          { 0xa5104e453cf8b845l,0x4b6fd986675ba557l,0x4bc750af29c8cb4al,
-            0x8bebb266583f9391l },
-          0 },
-        /* 44 << 16 */
-        { { 0x47110d7c1be3f9c5l,0x12b9e4485eadb4ddl,0x6e8c09870b713d41l,
-            0xe1e20356733d56ael },
-          { 0xe68d6bab445ea727l,0x9ef4f6eac934a1a4l,0xe0155547f8cef1c3l,
-            0xdb5c3909159bdcbfl },
-          0 },
-        /* 45 << 16 */
-        { { 0xef0449cb32fa8a37l,0x95071f5dcd246405l,0x1c56ad776c598891l,
-            0x981781de0fa9cd42l },
-          { 0x0f93d456d29c0500l,0x43aa7bc1483f52c4l,0xd7c8736666c8abadl,
-            0x47552530ea5050efl },
-          0 },
-        /* 46 << 16 */
-        { { 0x40dd9ca9fa9b8d3dl,0xf27b7bc056da41d9l,0x87967f4b66db8845l,
-            0xf6918c9444de6bc7l },
-          { 0x4d76d51135568d4dl,0x7ab18f9a40e7fa5al,0x069a44bba5bbbdc6l,
-            0x19e6c04bb4c8f808l },
-          0 },
-        /* 47 << 16 */
-        { { 0x5fd2501108b2b6c7l,0xcce85a3ec41cad21l,0x90857daffdd70387l,
-            0x7a679062c63789f4l },
-          { 0x9c462134ef8666e2l,0xcb7dba108c8505bdl,0x7c4a7e2fc610f2e7l,
-            0x22906f65d68315f9l },
-          0 },
-        /* 48 << 16 */
-        { { 0xf2efe23d442a8ad1l,0xc3816a7d06b9c164l,0xa9df2d8bdc0aa5e5l,
-            0x191ae46f120a8e65l },
-          { 0x83667f8700611c5bl,0x83171ed7ff109948l,0x33a2ecf8ca695952l,
-            0xfa4a73eef48d1a13l },
-          0 },
-        /* 49 << 16 */
-        { { 0x41dd38c1118de9a0l,0x3485cb3be2d8f6f5l,0xd4bac751b1dcc577l,
-            0x2148d93fed12ea6bl },
-          { 0xde3504729da8cb18l,0x6046daf89eb85925l,0xddbc357b942b1044l,
-            0x248e7afe815b8b7cl },
-          0 },
-        /* 51 << 16 */
-        { { 0xd4bb77b3acb21004l,0xe9f236cf83392035l,0xa9894c5c52133743l,
-            0x4d6112749a7b054al },
-          { 0xa61675ea4ba2a553l,0x59c199681da6aa78l,0x3988c36590f474del,
-            0x73e751bbd001be43l },
-          0 },
-        /* 52 << 16 */
-        { { 0x97cacf846604007dl,0x1e92b4b22d47a9f1l,0x858ae0d6374ed165l,
-            0x4c973e6f307aefb8l },
-          { 0x6f524a238a10eb72l,0x7b4a92a9eb2849d6l,0x3678bda42fe91eddl,
-            0x56092acd7c0fc35cl },
-          0 },
-        /* 53 << 16 */
-        { { 0x93bea99b1b9b43c4l,0x2f6af6f3e145fda2l,0x862f0607278adf0dl,
-            0x647be08398456ccal },
-          { 0xce79ba1487250c28l,0x1c1c4fc8efedab42l,0x966f612af90caa8dl,
-            0xb1a2cf6e72c440f8l },
-          0 },
-        /* 55 << 16 */
-        { { 0x2fca1be45b3b7dd5l,0x453c19853c211bcal,0x313cb21969a46484l,
-            0x66082837414bd5dfl },
-          { 0xab7a97bf2ac1cdf7l,0x45cd1792676d778fl,0x42fb6c4f6a5b560al,
-            0x45747fe30b8f17e9l },
-          0 },
-        /* 57 << 16 */
-        { { 0x38b6db6235db6218l,0xa10cdfe1bb54bacal,0x56fd4a1d610f7f6bl,
-            0xc4bea78b76d183d7l },
-          { 0xc0e6ca9fbf730d26l,0x1b1e271aed6cf535l,0x6fef275faadbe375l,
-            0xfa2e8da903e489bal },
-          0 },
-        /* 59 << 16 */
-        { { 0x6f79d25c7c4626ecl,0xfe27690232d55d6cl,0x3f5c5768afa19ce3l,
-            0xa1373777f8834739l },
-          { 0x761d67a8a4ce960al,0xb34de1ea459e656al,0x8725b0f09db6f269l,
-            0x75316f250dbfe22el },
-          0 },
-        /* 60 << 16 */
-        { { 0x091d5b631a093b40l,0xb85c1c075862f24al,0xc5d74eb53e8f85bfl,
-            0xf51c7746cab22456l },
-          { 0xc25cb8d9e761da89l,0x2670ec2fc0f028b5l,0x873fd30d2db9af5cl,
-            0x3d0f1ea18262565el },
-          0 },
-        /* 61 << 16 */
-        { { 0x8f9492c261c23b3cl,0xd366baeb631688a4l,0x55e759e78093bb07l,
-            0xf6d0eaf47218f765l },
-          { 0xb8a174ff54ca583bl,0x790f10e0b23d14cel,0xfebe7333be83cbbal,
-            0xfeb6dcc5eed67536l },
-          0 },
-        /* 63 << 16 */
-        { { 0x175b3bacce027e5bl,0xe0728a99c48252c4l,0x0be25d4507a39c7cl,
-            0xcb9c2d3aba8e8c72l },
-          { 0x6185a48d1abd459al,0x27207feadff9a27bl,0xfd92e8231d34393fl,
-            0x738511534351d965l },
-          0 },
-        /* 64 << 16 */
-        { { 0xfcde7cc8f43a730fl,0xe89b6f3c33ab590el,0xc823f529ad03240bl,
-            0x82b79afe98bea5dbl },
-          { 0x568f2856962fe5del,0x0c590adb60c591f3l,0x1fc74a144a28a858l,
-            0x3b662498b3203f4cl },
-          0 },
-        /* 65 << 16 */
-        { { 0x8ede0fcdc11682eel,0x41e3faa1b2ab5664l,0x58b2a7dc26a35ff5l,
-            0x939bcd6b701b89e9l },
-          { 0x55f66fd188e0838fl,0x99d1a77b4ff1f975l,0x103abbf72e060cc5l,
-            0x91c77beb6bc4bdbbl },
-          0 },
-        /* 71 << 16 */
-        { { 0xcd048abca380cc72l,0x91cab1bbd0e13662l,0x68115b18686de4cel,
-            0x484724e63deccbf5l },
-          { 0xf164ba54f176137el,0x5189793662ab2728l,0x6afdecf9b60a5458l,
-            0xca40472d0aabafd2l },
-          0 },
-        /* 77 << 16 */
-        { { 0x7a9439183b98d725l,0x1c1763e8ece1ea3cl,0x45c44ef639840476l,
-            0x689271e69c009133l },
-          { 0xa017405f56a51fe1l,0xd54cc7253e0d0970l,0x212ad075cfe09e8bl,
-            0x999f21c37af7bf30l },
-          0 },
-        /* 83 << 16 */
-        { { 0xdc2a2af12bf95f73l,0xb88b4ca76de82cbel,0xa31a21aaecb8e84el,
-            0x86d19a601b74f5bel },
-          { 0xc68bf64406008019l,0xe52ab50e9431c694l,0x6375463d627ab11cl,
-            0xdd3eeaa03c0ef241l },
-          0 },
-        /* 89 << 16 */
-        { { 0x608d9cb323f1caf8l,0x95069450b1700741l,0xe3132bd2bc2fa7aal,
-            0xc4f363e7f64e4f06l },
-          { 0xb059c4191ca888c2l,0x1004cb1f8d17bf5dl,0x6b6ba6f934ea5711l,
-            0x071d94abd79b2c8al },
-          0 },
-        /* 95 << 16 */
-        { { 0xc7ef9b42d147a39dl,0x36dd5d770a10cd5bl,0x3bf6cc77d0eea34bl,
-            0x60c84591197479c7l },
-          { 0xf95860ac50ba50edl,0xe1c94a8dc4cdc8fal,0x780818d685e24a23l,
-            0x1950e3c0c8abbd27l },
-          0 },
-        /* 101 << 16 */
-        { { 0x9908c694ae04778el,0x2e37a6790a0d36ffl,0x212a340f52b067bdl,
-            0xec89c9fad080b914l },
-          { 0x920dc2f005ab8a23l,0xecff5c78655e8984l,0x80eedd34f66211acl,
-            0xa7a56366ef58d4d8l },
-          0 },
-        /* 107 << 16 */
-        { { 0x4f95debe2bca42f0l,0xf0346307844334d2l,0x7003a60521d600aal,
-            0x1eb98c6365c5248al },
-          { 0x6757b3822fa202cal,0x32765d399fb12f36l,0xe851b476d7b44c9al,
-            0x27cd7d1b4e0bab4cl },
-          0 },
-        /* 113 << 16 */
-        { { 0xd0c1f7c9c43ea1a3l,0x73d944f49f42907dl,0xd113f34619352c92l,
-            0x86a1ad53b149cdc1l },
-          { 0x32c34e8f848d1be4l,0xba8afda7c3d9360bl,0x17e8bc32eea8bf96l,
-            0x3174cae499c87febl },
-          0 },
-        /* 116 << 16 */
-        { { 0x4b215f016671b47el,0xb67633ca4a8dae2al,0x2915120f79fd3cdbl,
-            0xc1f8a06fb064e6del },
-          { 0xf4d5368cc1d57420l,0x6ada51a8e18de475l,0xa0f0d47cc749d4b0l,
-            0xabfa2c0074526aa5l },
-          0 },
-        /* 119 << 16 */
-        { { 0xf752f6659e5ce44fl,0x7b97ebfa189d35ecl,0x9540cbb90fc609abl,
-            0x19c1dc6999632cc8l },
-          { 0x0a957700e08ca9a8l,0xb0cd0ab7a3246a4el,0xca687cfcc8d6a544l,
-            0xb6281f0035f82a77l },
-          0 },
-        /* 125 << 16 */
-        { { 0x547027012b818036l,0xf72315f729c8f14cl,0x95f1bc15230e74bel,
-            0x2e7c492f1abe20d4l },
-          { 0xe1ea8b1cd7e78ab1l,0xc3f6ba59043585adl,0xac404ea9477ac053l,
-            0xaa6872914ec6d0e3l },
-          0 },
-    },
-    {
-        /* 0 << 24 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 24 */
-        { { 0xd9d0c8c4868af75dl,0xd7325cff45c8c7eal,0xab471996cc81ecb0l,
-            0xff5d55f3611824edl },
-          { 0xbe3145411977a0eel,0x5085c4c5722038c6l,0x2d5335bff94bb495l,
-            0x894ad8a6c8e2a082l },
-          0 },
-        /* 3 << 24 */
-        { { 0xd1e059b21994ef20l,0x2a653b69638ae318l,0x70d5eb582f699010l,
-            0x279739f709f5f84al },
-          { 0x5da4663c8b799336l,0xfdfdf14d203c37ebl,0x32d8a9dca1dbfb2dl,
-            0xab40cff077d48f9bl },
-          0 },
-        /* 4 << 24 */
-        { { 0xf2369f0b879fbbedl,0x0ff0ae86da9d1869l,0x5251d75956766f45l,
-            0x4984d8c02be8d0fcl },
-          { 0x7ecc95a6d21008f0l,0x29bd54a03a1a1c49l,0xab9828c5d26c50f3l,
-            0x32c0087c51d0d251l },
-          0 },
-        /* 5 << 24 */
-        { { 0xf61790abfbaf50a5l,0xdf55e76b684e0750l,0xec516da7f176b005l,
-            0x575553bb7a2dddc7l },
-          { 0x37c87ca3553afa73l,0x315f3ffc4d55c251l,0xe846442aaf3e5d35l,
-            0x61b911496495ff28l },
-          0 },
-        /* 7 << 24 */
-        { { 0x4bdf3a4956f90823l,0xba0f5080741d777bl,0x091d71c3f38bf760l,
-            0x9633d50f9b625b02l },
-          { 0x03ecb743b8c9de61l,0xb47512545de74720l,0x9f9defc974ce1cb2l,
-            0x774a4f6a00bd32efl },
-          0 },
-        /* 9 << 24 */
-        { { 0x327bc002b0131e5bl,0x1739e6d5cb2514d9l,0xc8cbdafe55a81543l,
-            0x5bb1a36ce1137243l },
-          { 0x205da3c517325327l,0xc35c1a36515a057el,0xf00f64c942925f9bl,
-            0xbd14633cb7d59f7al },
-          0 },
-        /* 10 << 24 */
-        { { 0xae2ad171656e8c3al,0xc0e2a4631acd0705l,0x006f6a8aa0b6055cl,
-            0xaf4513d72b65a26el },
-          { 0x3f549e14d616d5bcl,0x64ee395571253b1fl,0xe8b10bc1b8ce243al,
-            0xbcbeace5913a4e77l },
-          0 },
-        /* 11 << 24 */
-        { { 0x47c1004341f37dbdl,0x96eccae36168ecf6l,0x65bde59d1ca46aa3l,
-            0x38a7027ab8698ffal },
-          { 0xa2b89dc86dc34437l,0x5a0a118d43a4153fl,0x9e330a861ce22fd8l,
-            0x28382af6b3bbd3bcl },
-          0 },
-        /* 13 << 24 */
-        { { 0x0b2e27c0d81e0271l,0xa67a7596117a317cl,0x17f08928a6723d99l,
-            0x71a75681485310a3l },
-          { 0x90465462afb66ca9l,0x185e97ccfbbe229dl,0x6a1a606addad8fc2l,
-            0x2431f316b3c797cfl },
-          0 },
-        /* 15 << 24 */
-        { { 0x4703401193529432l,0x1f106bdd30743462l,0xabfb9964cd66d8cal,
-            0x934d9d5ae9bdadd5l },
-          { 0x5976d815908e3d22l,0x344a362f28e057bdl,0xf92cdadc5443dfb3l,
-            0x001297adf089603bl },
-          0 },
-        /* 16 << 24 */
-        { { 0x7f99824f20151427l,0x206828b692430206l,0xaa9097d7e1112357l,
-            0xacf9a2f209e414ecl },
-          { 0xdbdac9da27915356l,0x7e0734b7001efee3l,0x54fab5bbd2b288e2l,
-            0x4c630fc4f62dd09cl },
-          0 },
-        /* 17 << 24 */
-        { { 0x4a2fce605044066bl,0x904a019cfa3a47f4l,0xba81ea9c0c5c0a60l,
-            0xd7e4ea0d96c098bdl },
-          { 0xefe700419cd50a02l,0xc0c839d42d7f048cl,0xe2daf264e09b561fl,
-            0x0cbc13185034b18bl },
-          0 },
-        /* 19 << 24 */
-        { { 0x11e5f2e388323f7al,0xe07a74c2927584cdl,0x1e774b3495613d2dl,
-            0x9c9b52c52c787488l },
-          { 0x3cdd3c3ebe421f08l,0x5ff7819e223e3d5fl,0xba8739b2c1da09b9l,
-            0x6b7263164e8b491bl },
-          0 },
-        /* 21 << 24 */
-        { { 0xb5afd13ca0943befl,0xd651772957abb1ccl,0x9d5a52dc9b61b5bcl,
-            0x85cefaa6806e31cdl },
-          { 0xab84257a720a1deal,0x6a60261bced70d35l,0xc023f94db9d6da61l,
-            0x947f7eec54a0ae0el },
-          0 },
-        /* 23 << 24 */
-        { { 0xc3b787569f83b787l,0xd6d249263694ddd7l,0x58d248945d70a02el,
-            0xac16670e8c278c6al },
-          { 0x71a94d58e370b6e6l,0xe4d763840253db05l,0x99b1c98814b32cfel,
-            0x4e6bd870cc78cc95l },
-          0 },
-        /* 25 << 24 */
-        { { 0xf5f7ca79c8b63614l,0xf3bfb2158af4903cl,0x2bdb9f5496d47bd3l,
-            0xd6e715300e8a63bal },
-          { 0x67e90a497a93bec4l,0x8613478b8c1e63eel,0xe36bd9c8f2dde561l,
-            0x681486518a768689l },
-          0 },
-        /* 27 << 24 */
-        { { 0xef617a9494aa531cl,0x9ac35e2fd6f4ad87l,0xbcd2a047122468fbl,
-            0xbd7a423fef7c5ca6l },
-          { 0xab58cb52064c8040l,0x93ef4ed54a644716l,0xf7d17097c32cd48dl,
-            0xb249a173d17fcf42l },
-          0 },
-        /* 28 << 24 */
-        { { 0x66fe0fffe298cdf5l,0x3f61bea47b2e51b6l,0x7d372117bad3afa4l,
-            0x6521a09cef656e2fl },
-          { 0xb3b8c966e8a58fe7l,0x25203a115a47ebc7l,0xfe81588d5c4be573l,
-            0x6132e2f31f49a03cl },
-          0 },
-        /* 29 << 24 */
-        { { 0xbbe5c108b7a7ecc4l,0x62a5a78ebfd22e4cl,0xb7974033df188bd2l,
-            0xcf11deea4df7d1ael },
-          { 0x99cc774a53ace3eal,0xe0373a71105cc1f6l,0xd751987f133d7a20l,
-            0xab86ee04ae215871l },
-          0 },
-        /* 31 << 24 */
-        { { 0x2094f9a280cd10e6l,0x045232aa7b8a0da7l,0x969a81b69c03244el,
-            0x1293b4ca7e98d955l },
-          { 0x1631421dd68f3ab0l,0xa0106422c3738c82l,0xc5f43845f82c4ff9l,
-            0xb479acbe1aa0f58fl },
-          0 },
-        /* 33 << 24 */
-        { { 0xf1db0267f67683cfl,0xa6b13c9e44ce009dl,0x04b4eed505884a69l,
-            0xf2ff9c16d9087a0bl },
-          { 0x2c53699b3e35b4a6l,0x5020c0142369afb8l,0xf83bfe0095be37f1l,
-            0xd300d8c553b29d80l },
-          0 },
-        /* 34 << 24 */
-        { { 0x16893055811cf4bbl,0x580dd1e55aeb5027l,0xcaf47fba5ae3c71cl,
-            0xde79698129ebbb07l },
-          { 0xbed1db33d262cdd3l,0x78315e3748c7313bl,0xfc9561f02fe1368dl,
-            0xe0209698ccacacc7l },
-          0 },
-        /* 35 << 24 */
-        { { 0xd61af89a781ece24l,0xf3b90626008f41e9l,0xd715dbf7c5693191l,
-            0x8d6c05de6f299edel },
-          { 0xf18d62637ca50aacl,0x7987bf5cb0dd5fdcl,0x424136bd2cfa702bl,
-            0xaa7e237ded859db2l },
-          0 },
-        /* 36 << 24 */
-        { { 0xde7169e4e5d41796l,0x6700333e33c0a380l,0xe20b95780343a994l,
-            0xa745455e1fb3a1c3l },
-          { 0x97e0ff88ce029a7fl,0x3b3481c976e384bcl,0x028b339dddad5951l,
-            0xa1fdcdbae4b95cfcl },
-          0 },
-        /* 37 << 24 */
-        { { 0xcc9221baed20c6adl,0xf2619a51fa9c73aal,0xfc2cff847d7f55a5l,
-            0xd56c23d65f01d4dal },
-          { 0x6d20f88cb3d84d5fl,0x048825f75dcc615dl,0x73634d3f85631a6el,
-            0xa57a02e3ad7b2e2dl },
-          0 },
-        /* 39 << 24 */
-        { { 0x067a8dcf08aa81ffl,0x62948258c23f3d16l,0xb61bd04316f2fe7bl,
-            0xf250f769b6a766b1l },
-          { 0x32df97246d0b241el,0xb736e4bb714e5f88l,0x50da15022c1d40d7l,
-            0x013e0edebdd285a4l },
-          0 },
-        /* 40 << 24 */
-        { { 0x1b92c3a0181a5d8fl,0x6429531d9adb77c7l,0x629152b53af710eel,
-            0x4e3f27370bd5647el },
-          { 0xfb7c392b77553c7dl,0xa930abacefe78c87l,0xf80c8cd6a05a6991l,
-            0x751469b71be5f6f5l },
-          0 },
-        /* 41 << 24 */
-        { { 0xf89f2b0b3e2f2af0l,0x52f634099eefc39al,0x505005c679906cb6l,
-            0x820c2216b2de0b1el },
-          { 0x96f0f2831f20ad7al,0xcd33125c718ffcb0l,0xf6130ef278f0c578l,
-            0x4cda2471d0b76b95l },
-          0 },
-        /* 43 << 24 */
-        { { 0x611dd83f39485581l,0x96c47051803e1b20l,0xefacc736830f44c7l,
-            0x5588d8ce688b12bal },
-          { 0x44f4edf3eee70fadl,0x1026dfd8869539f7l,0xa4c146ee8ddb0e00l,
-            0x9f4f55816efb41c8l },
-          0 },
-        /* 44 << 24 */
-        { { 0x6036ed0236cbace7l,0x5a70e4abada837ddl,0xf06918aff10b2fefl,
-            0x08a8a9f69fd31590l },
-          { 0x6c4a1ba6916af88dl,0x4868bc1466016037l,0x06d345af164228a9l,
-            0x2c1961d19b550dd9l },
-          0 },
-        /* 45 << 24 */
-        { { 0x8b72775c6851f0acl,0x7827242bd70f5975l,0x2de91f1e34db4a6fl,
-            0x586bf3d58538f5eel },
-          { 0xf0a15aed25d9a09bl,0x43018e56f74deb46l,0xc2af1ad0f50e0e67l,
-            0x49cc9528b10cff6fl },
-          0 },
-        /* 46 << 24 */
-        { { 0x05eb146c9d55c425l,0xe2b557ccbc62261fl,0x2a716301bd077089l,
-            0x83a63c81e0527d02l },
-          { 0x055ff7f8a0d9203bl,0x05d09f0525bf5a04l,0x2e44545fb3eb0b30l,
-            0xed7c57c4d279a1adl },
-          0 },
-        /* 47 << 24 */
-        { { 0x6928f6e45e0ebdd5l,0xd7e44ddf092d233bl,0xe7148066d1b7026fl,
-            0xf645a2e53d5f25c3l },
-          { 0x6eeb25ee58ff9eb4l,0x60f1fcf737f87ebfl,0x9eaaf1e5c4679c70l,
-            0x4609fb13b7b7dc7el },
-          0 },
-        /* 48 << 24 */
-        { { 0xae915f5d5fa067d1l,0x4134b57f9668960cl,0xbd3656d6a48edaacl,
-            0xdac1e3e4fc1d7436l },
-          { 0x674ff869d81fbb26l,0x449ed3ecb26c33d4l,0x85138705d94203e8l,
-            0xccde538bbeeb6f4al },
-          0 },
-        /* 49 << 24 */
-        { { 0x27f317af2b33987fl,0xd2d3cf5d51e59588l,0x333999bd031f27c9l,
-            0x6ddfa3f22e0a3306l },
-          { 0x23e0e651990041b0l,0xf028aba1585837acl,0x1c6ad72b25226f53l,
-            0xf243c991d1fca64al },
-          0 },
-        /* 51 << 24 */
-        { { 0x72b8a13272cbae1fl,0xfe0b1c4fbfdbd64al,0x98bc7876c5e76921l,
-            0x51c726bfdb1f5af7l },
-          { 0x97e88a842c186e8bl,0x9ed99516ed8eb7b4l,0x3e54a17dafc818ebl,
-            0xfcfbf25a1e8f77d8l },
-          0 },
-        /* 52 << 24 */
-        { { 0x7780d7d68f7d5c6el,0x6725b49a454101e6l,0xceddc26586b0770cl,
-            0xc26624615666f504l },
-          { 0x16b77477ce040f75l,0x13f9113c293f8b45l,0xff0cfa07e2dcc91el,
-            0x1948d8bd41c202f5l },
-          0 },
-        /* 53 << 24 */
-        { { 0x4c6ae39a1dfbe13al,0xafb1e5c46be9c200l,0x39e728d168bb08c3l,
-            0xc794b905acc9166fl },
-          { 0x1cb0dec2d9c7c3e4l,0xc4c3053289f14d65l,0x4af80801a6a9d609l,
-            0x79d7e82de0d6ab24l },
-          0 },
-        /* 55 << 24 */
-        { { 0xb905c6af8ad4cf6el,0x785590b0f6d1be13l,0x78f402c2a0ef76bel,
-            0x739b22ea5c19a40bl },
-          { 0xd4d3262553d596b6l,0x01598eb4d571666bl,0xf8dc150b8173486al,
-            0xd8aa43af15e94f09l },
-          0 },
-        /* 57 << 24 */
-        { { 0xcfa387cd984393b5l,0x1645659e21a1bf92l,0xb4ab3966dd46c7eel,
-            0xcf8c296d89482623l },
-          { 0x72e4d01cf976b4c0l,0x44ad07e8fa0fa5ebl,0xd6c82681b486fdd2l,
-            0x2d9074f89b8845b4l },
-          0 },
-        /* 59 << 24 */
-        { { 0x96e4fc08d96862dbl,0xf9e29bb6c50c14b2l,0xfedaad64f8f9be75l,
-            0xab6b2d79ae9e1274l },
-          { 0x033e3eb58d84dec0l,0xc136904ccbd113e7l,0xb82b0aed6061f289l,
-            0x3476d9247b699e25l },
-          0 },
-        /* 60 << 24 */
-        { { 0x8fb5ceeb969231dcl,0xaed13be1686ff6cdl,0x71d7c67bdd69db87l,
-            0x49613e08fb53f33al },
-          { 0x2899729ead8e802fl,0x83bfde49d1982a1dl,0x675c45ea878239d2l,
-            0xb7bf59cd0d8240d3l },
-          0 },
-        /* 61 << 24 */
-        { { 0x853d8cd1baf53b8bl,0x9c73d04cff95fc18l,0xae8a94412d1d6aacl,
-            0xd8a15ce901500b70l },
-          { 0xaef813499aacba59l,0x2cd2ba0ac493cd8dl,0x01c37ee1f398f034l,
-            0xed72d51d0f7299fcl },
-          0 },
-        /* 63 << 24 */
-        { { 0x2c204940e7592fb1l,0xcc1bb19b49366f08l,0x31855e8a7c927935l,
-            0x16f7e9a2c590b81dl },
-          { 0xa5fbb7c1ed8df240l,0x7b5204122de2d7f5l,0x7eb1eb989a637588l,
-            0x5ef4eca89540d2e8l },
-          0 },
-        /* 64 << 24 */
-        { { 0x55d5c68da61a76fal,0x598b441dca1554dcl,0xd39923b9773b279cl,
-            0x33331d3c36bf9efcl },
-          { 0x2d4c848e298de399l,0xcfdb8e77a1a27f56l,0x94c855ea57b8ab70l,
-            0xdcdb9dae6f7879bal },
-          0 },
-        /* 65 << 24 */
-        { { 0x811e14dd9594afb8l,0xaf6c1b10d349124al,0x8488021b6528a642l,
-            0xecf6834341cf1447l },
-          { 0x7a40acb756924446l,0xd9c11bbed98ec4cfl,0x0cef00bfb2bff163l,
-            0xfaaad8015432803bl },
-          0 },
-        /* 71 << 24 */
-        { { 0x5a217d5e6b075cbel,0x7ef88d1dc89b513bl,0xb6d015da0531c93bl,
-            0x477b502a6333834al },
-          { 0x4655e48b2fb458d5l,0x93f21a7cb7674ca8l,0xa0616786502d1f3al,
-            0x82d16d17f26bb6ccl },
-          0 },
-        /* 77 << 24 */
-        { { 0x3d995aa9183c1688l,0xa125906c3766d2e8l,0x23ed7871c5f10d5bl,
-            0xdfe1e1cc6df80368l },
-          { 0x8bfcb54271eaae2cl,0xe94e6f910945a7bbl,0xd543ef90862f650al,
-            0x0dc043b803eed66bl },
-          0 },
-        /* 83 << 24 */
-        { { 0x0c6a5620060d2ccdl,0xcd8200e37a8a03a4l,0x6018d304793867e6l,
-            0xad23dd61a74d054dl },
-          { 0x5a856faeebc21eb4l,0x66be16714b5cd7dbl,0xe0d0441ec75f8c9dl,
-            0xb80ca9ecf90dbc6dl },
-          0 },
-        /* 89 << 24 */
-        { { 0xbd6902ccd24692cbl,0xbcce6bbc21920408l,0x40f120ca55dec4c5l,
-            0xd9f1f5ef5361c8b3l },
-          { 0x535d368226935dffl,0x9635447b01a9998al,0x8c4ec40d99e36d12l,
-            0xbaeef8912b793369l },
-          0 },
-        /* 95 << 24 */
-        { { 0xded3a51c1cd887ebl,0xd43225568376515cl,0xdaf3a2271ca7c097l,
-            0x089156fdecd4d90cl },
-          { 0x2b354810ca0727c9l,0xb7257c1966c19d8cl,0x5e68a379432d5072l,
-            0x75c04c2443e585c7l },
-          0 },
-        /* 101 << 24 */
-        { { 0xb5ba2a8fe5e0952fl,0x2c2d086811040b4el,0x27448bd5f818e253l,
-            0x720f677987a92c85l },
-          { 0x2c9b2367b9d035fal,0xf18ad8ce16c15ab9l,0xd65a360841bd57eel,
-            0xeb4b07c9ff6ae897l },
-          0 },
-        /* 107 << 24 */
-        { { 0xcffb6d71d38589acl,0x812372920fa509d3l,0x94db5ba6e54725e8l,
-            0x1ad2b4206cfbb825l },
-          { 0x8592c1f238cfb9f2l,0xbe8e917e0eec6a27l,0x53921bfe9d93d42fl,
-            0x1aa95e6269454a35l },
-          0 },
-        /* 113 << 24 */
-        { { 0xc25e8934d898049dl,0xeeaf4e6d3bb3d459l,0xc3ac44447d29ad10l,
-            0xccdf9fcbcef8fa04l },
-          { 0x1d995a3fb9679cb9l,0x3d6c5eab46fabc14l,0xd3849ff066385d4dl,
-            0xc0eb21bacff08be2l },
-          0 },
-        /* 116 << 24 */
-        { { 0x8213c71e90d13fd6l,0x114321149bb6b733l,0xaaf8037880ac4902l,
-            0xb24e046b555f7557l },
-          { 0x5f6ed2881db79832l,0xd493a758ac760e5dl,0xbc30a2a7a1c0f570l,
-            0xa5009807161174e3l },
-          0 },
-        /* 119 << 24 */
-        { { 0x9e9b864a6889e952l,0xee908932f352f31al,0xe421f2423166b932l,
-            0x6dd4aa3b7ddbdb35l },
-          { 0x553cc5639e8b88a4l,0x05457f171f04704dl,0x1dcc3004c9554e6bl,
-            0x3a4a3a253f1b61e7l },
-          0 },
-        /* 125 << 24 */
-        { { 0x7ac0a5e7c56e303al,0x7c7bab64037b0a19l,0x11f103fcc8d29a2bl,
-            0x7d99dc46cf0b1340l },
-          { 0x0481588ceffba92el,0x8a817356b04e77bcl,0x19edf4dbce1b708dl,
-            0xa2a1f7a6e6f9d52cl },
-          0 },
-    },
-    {
-        /* 0 << 32 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 32 */
-        { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l,
-            0xd953c50ddbdf58e9l },
-          { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl,
-            0x863ebb7e9eb288f3l },
-          0 },
-        /* 3 << 32 */
-        { { 0xa18f07e0e90fb21el,0x00fd2b80bba7fca1l,0x20387f2795cd67b5l,
-            0x5b89a4e7d39707f7l },
-          { 0x8f83ad3f894407cel,0xa0025b946c226132l,0xc79563c7f906c13bl,
-            0x5f548f314e7bb025l },
-          0 },
-        /* 4 << 32 */
-        { { 0x0ee6d3a7c35d8794l,0x042e65580356bae5l,0x9f59698d643322fdl,
-            0x9379ae1550a61967l },
-          { 0x64b9ae62fcc9981el,0xaed3d6316d2934c6l,0x2454b3025e4e65ebl,
-            0xab09f647f9950428l },
-          0 },
-        /* 5 << 32 */
-        { { 0xc1b3d3d331b85f09l,0x0f45354aa88ae64al,0xa8b626d32fec50fdl,
-            0x1bdcfbd4e828834fl },
-          { 0xe45a2866cd522539l,0xfa9d4732810f7ab3l,0xd8c1d6b4c905f293l,
-            0x10ac80473461b597l },
-          0 },
-        /* 7 << 32 */
-        { { 0xbbb175146fc627e2l,0xa0569bc591573a51l,0xa7016d9e358243d5l,
-            0x0dac0c56ac1d6692l },
-          { 0x993833b5da590d5fl,0xa8067803de817491l,0x65b4f2124dbf75d0l,
-            0xcc960232ccf80cfbl },
-          0 },
-        /* 9 << 32 */
-        { { 0x35d742806cf3d65bl,0x4b7c790678b28dd9l,0xc4fcdd2f95e1f85fl,
-            0xcf6fb7ba591350b6l },
-          { 0x9f8e3287edfc26afl,0xe2dd9e73c2d0ed9al,0xeab5d67f24cbb703l,
-            0x60c293999a759a5al },
-          0 },
-        /* 10 << 32 */
-        { { 0xcf8625d7708f97cdl,0xfb6c5119ea419de4l,0xe8cb234dc03f9b06l,
-            0x5a7822c335e23972l },
-          { 0x9b876319a284ff10l,0xefcc49977093fdcel,0xdddfd62a878fe39al,
-            0x44bfbe53910aa059l },
-          0 },
-        /* 11 << 32 */
-        { { 0xfb93ca3d7ca53d5fl,0x432649f004379cbfl,0xf506113acba2ff75l,
-            0x4594ae2103718b35l },
-          { 0x1aa6cee50d044627l,0xc0e0d2b7f5c94aa2l,0x0bf33d3dee4dd3f5l,
-            0xaca96e288477c97al },
-          0 },
-        /* 13 << 32 */
-        { { 0x995c068e6861a713l,0xa9ba339463de88dcl,0xab954344689a964fl,
-            0x58195aec0f5a0d6cl },
-          { 0xc5f207d5c98f8b50l,0x6600cd280c98ccf6l,0x1a680fe339c3e6c2l,
-            0xa23f3931660e87c0l },
-          0 },
-        /* 15 << 32 */
-        { { 0x43bc1b42c78440a1l,0x9a07e22632ac6c3fl,0xaf3d7ba10f4bcd15l,
-            0x3ad43c9da36814c6l },
-          { 0xca11f742a0c9c162l,0xd3e06fc6c90b96ecl,0xeace6e766bf2d03fl,
-            0x8bcd98e8f8032795l },
-          0 },
-        /* 16 << 32 */
-        { { 0xe27a6dbe305406ddl,0x8eb7dc7fdd5d1957l,0xf54a6876387d4d8fl,
-            0x9c479409c7762de4l },
-          { 0xbe4d5b5d99b30778l,0x25380c566e793682l,0x602d37f3dac740e3l,
-            0x140deabe1566e4ael },
-          0 },
-        /* 17 << 32 */
-        { { 0x7be3ddb77099ae96l,0x83d6157306e0da6al,0x31bcac5f74bf9870l,
-            0x7f7aa3b422b256f1l },
-          { 0xff84d63caa212e20l,0x7d636556decdc8b5l,0x8fed824dbf909d62l,
-            0x62d70186e5fb1445l },
-          0 },
-        /* 19 << 32 */
-        { { 0x8796989f67d8ab8al,0xa46282253700b772l,0xa353cadf05f799abl,
-            0x7a8be2741eeb06bbl },
-          { 0xf74a367e4653b134l,0x4e43449660c70340l,0xc99b6d6b72e10b18l,
-            0xcf1adf0f1ba636e1l },
-          0 },
-        /* 21 << 32 */
-        { { 0xb0260fb57c6a0958l,0xae791b9c2fc2731el,0xb339f2bf8ce6e575l,
-            0x769214a816e2639fl },
-          { 0xbaf422e1346da10el,0xc7805fdf7a56f463l,0xf47b6b766f845428l,
-            0x8f21369e38492948l },
-          0 },
-        /* 23 << 32 */
-        { { 0x2bac716a17931a90l,0x42a5e27cc8267236l,0xfd4b367c0bafeb78l,
-            0x5856e69c6173db02l },
-          { 0xfaac7358973d73c4l,0xbfbffcc36768d285l,0x05444ff2be3eb243l,
-            0x9f8d3692f3c323fel },
-          0 },
-        /* 25 << 32 */
-        { { 0xac296863221c31a9l,0x46f3a24ef1ca99a9l,0xd927648a7535a864l,
-            0xd7e3c47d5848e497l },
-          { 0xc19595b782a98ac7l,0x9a9bf627273ff554l,0xe29aa48fb62298a1l,
-            0xed3f068ee797e9e3l },
-          0 },
-        /* 27 << 32 */
-        { { 0x8d16a1660eb9227bl,0xe04c6bc58c37c74bl,0xd1be9585cc1ef78cl,
-            0xa5cfe1962e929d9bl },
-          { 0xc9b0ea21417c1cc6l,0x316352d345b79599l,0xc1502c4dc2d54af7l,
-            0xe7f4412990f83445l },
-          0 },
-        /* 28 << 32 */
-        { { 0x0f6704abd95917e8l,0x168dafaeaec6e899l,0xd2833e8cde710027l,
-            0x34ea277e68ee3c59l },
-          { 0x3689e2350054d4e5l,0x6f3a568d11013943l,0xb5ce1ff69bc2b144l,
-            0x705bfe7e72b33a59l },
-          0 },
-        /* 29 << 32 */
-        { { 0x1baa4f02c8e93284l,0xec6b93ea3c97d3e8l,0xb656c149034f8b32l,
-            0x3cab9063cd4cc69fl },
-          { 0xd8de5989d61031ccl,0xcf85329fc1b1de1dl,0xf18b78b323d8cb9al,
-            0x6dc04bc61a6b69eal },
-          0 },
-        /* 31 << 32 */
-        { { 0x79cf86314a1d4f8fl,0xda5ba331aa47394el,0x36f9c0be8ff20527l,
-            0xccdc719bbc7097f6l },
-          { 0x2304a3ba5cb052bbl,0xab80cdea392f0ab5l,0x0ac1858bf38de03bl,
-            0xd6e2119878a8f55dl },
-          0 },
-        /* 33 << 32 */
-        { { 0x6bdebc26584bc618l,0x499f0f1894591499l,0xd35ed50bf4a573dal,
-            0x5a622e73ff2792d0l },
-          { 0x8510cbce68d41a3bl,0x6610f43c94e919afl,0x4527373dc163c8a1l,
-            0x50afb46f280a8a7dl },
-          0 },
-        /* 34 << 32 */
-        { { 0x33e779cd8de7707al,0xf94bbd94438f535bl,0x61159864be144878l,
-            0xb6623235f098ce4al },
-          { 0x6813b71ba65568d8l,0x6603dd4c2f796451l,0x9a97d88c8b9ee5b2l,
-            0xaaa4593549d5926cl },
-          0 },
-        /* 35 << 32 */
-        { { 0x2e01fc75ebe75bf2l,0x8270318d6cbdd09cl,0x534e4f21d3f1a196l,
-            0x6c9eaeca9459173el },
-          { 0xda454fe0b642a1d4l,0xe45b69bfc4664c4al,0x4724bd423e078dc8l,
-            0x39ac8fe603336b81l },
-          0 },
-        /* 36 << 32 */
-        { { 0x0a2e53dd302e9485l,0x75882a19deaa9ff4l,0xe283242eac8de4ddl,
-            0x2742105cc678dba7l },
-          { 0x9f6f0a88cdb3a8a2l,0x5c9d3338f722e894l,0xf1fa3143c38c31c1l,
-            0x22137e2db18c77acl },
-          0 },
-        /* 37 << 32 */
-        { { 0xd821665e368d7835l,0x3300c012b596c6ecl,0xb60da7353557b2ddl,
-            0x6c3d9db6fb8cf9ael },
-          { 0x092d8b0b8b4b0d34l,0x900a0bf4b3d4107dl,0x75371a245e813ec3l,
-            0x91125a17f2ad56d5l },
-          0 },
-        /* 39 << 32 */
-        { { 0x5e6594e2fe0073e6l,0x908a93778be13cb7l,0xa2c3d5c8ac26617cl,
-            0xa0bab085c317c6b9l },
-          { 0x0bdc183b83664109l,0x6bbba2b468f9dcd9l,0x697a50785814be41l,
-            0x12a59b183a5e5f98l },
-          0 },
-        /* 40 << 32 */
-        { { 0xbd9802e6c30fa92bl,0x5a70d96d9a552784l,0x9085c4ea3f83169bl,
-            0xfa9423bb06908228l },
-          { 0x2ffebe12fe97a5b9l,0x85da604971b99118l,0x9cbc2f7f63178846l,
-            0xfd96bc709153218el },
-          0 },
-        /* 41 << 32 */
-        { { 0xb5a85c61bfa70ca6l,0x4edc7f2d4c1f745fl,0x05aea9aa3ded1eb5l,
-            0x750385efb82e5918l },
-          { 0xdcbc53221fdc5164l,0x32a5721f6794184el,0x5c5b2269ff09c90bl,
-            0x96d009115323ca42l },
-          0 },
-        /* 43 << 32 */
-        { { 0x12c73403f43f1440l,0xc94813eb66cc1f50l,0x04d5957b9b035151l,
-            0x76011bca4bfaafa8l },
-          { 0x56806c13574f1f0al,0x98f63a4697652a62l,0x17c63ef4a3178de9l,
-            0xf7ce961a65009a52l },
-          0 },
-        /* 44 << 32 */
-        { { 0x58f92aebe4173516l,0xdc37d99275e42d44l,0x76dcec5b4d48e1bal,
-            0x07e0608e25676448l },
-          { 0xa1877bcd1d4af36al,0x38b62b3c5a8ccf0cl,0x60522e88aeab7f75l,
-            0xbef213ed5e03547al },
-          0 },
-        /* 45 << 32 */
-        { { 0x8acd5ba4e6ed0282l,0x792328f06a04531dl,0xe95de8aa80297e50l,
-            0x79d33ce07d60e05cl },
-          { 0xcb84646dd827d602l,0xd3421521302a608cl,0x867970a4524f9751l,
-            0x05e2f7e347a75734l },
-          0 },
-        /* 46 << 32 */
-        { { 0x64e4de4a01c66263l,0xbcfe16a4d0033d4cl,0x359e23d4817de1dcl,
-            0xb01e812ec259449cl },
-          { 0x90c9ade2df53499fl,0xabbeaa27288c6862l,0x5a655db4cd1b896fl,
-            0x416f10a5a022a3d6l },
-          0 },
-        /* 47 << 32 */
-        { { 0x0d17e1ef98601fd5l,0x9a3f85e0eab76a6fl,0x0b9eaed1510b80a1l,
-            0x3282fd747ec30422l },
-          { 0xaca5815a70a4a402l,0xfad3121cf2439cb2l,0xba251af81fccabd6l,
-            0xb382843fa5c127d5l },
-          0 },
-        /* 48 << 32 */
-        { { 0x958381db1782269bl,0xae34bf792597e550l,0xbb5c60645f385153l,
-            0x6f0e96afe3088048l },
-          { 0xbf6a021577884456l,0xb3b5688c69310ea7l,0x17c9429504fad2del,
-            0xe020f0e517896d4dl },
-          0 },
-        /* 49 << 32 */
-        { { 0x442fdfe920cd1ebel,0xa8317dfa6a250d62l,0x5214576d082d5a2dl,
-            0xc1a5d31930803c33l },
-          { 0x33eee5b25e4a2cd0l,0x7df181b3b4db8011l,0x249285145b5c6b0bl,
-            0x464c1c5828bf8837l },
-          0 },
-        /* 51 << 32 */
-        { { 0x5464da65d55babd1l,0x50eaad2a0048d80fl,0x782ca3dd2b9bce90l,
-            0x41107164ab526844l },
-          { 0xad3f0602d56e0a5fl,0xc1f0248018455114l,0xe05d8dcab1527931l,
-            0x87818cf5bb1295d7l },
-          0 },
-        /* 52 << 32 */
-        { { 0x95aeb5bd483e333al,0x003af31effeaededl,0xfc5532e87efb1e4fl,
-            0xb37e0fb52dfa24a5l },
-          { 0x485d4cecdc140b08l,0xb81a0d23983bd787l,0xd19928dae8d489fdl,
-            0x3fa0312c177b9dbdl },
-          0 },
-        /* 53 << 32 */
-        { { 0xade391470c6d7e88l,0x4fd1e8cd47072c45l,0x145760fed5a65c56l,
-            0x198960c7be4887del },
-          { 0xfe7974a82640257al,0xf838a19b774febefl,0xb2aecad11b6e988el,
-            0x643f44fa448e4a8fl },
-          0 },
-        /* 55 << 32 */
-        { { 0xc35ceffdee756e71l,0x2c1364d88ea932c4l,0xbd594d8d837d2d9fl,
-            0x5b334bdac9d74d48l },
-          { 0x72dc3e03b8fac08bl,0x38f01de006fdf70fl,0x4bde74b31d298ba4l,
-            0x2598d183ad5f42a9l },
-          0 },
-        /* 57 << 32 */
-        { { 0x02c6ba15f62befa2l,0x6399ceb55c8ccee9l,0x3638bd6e08d3473el,
-            0xb8f1f13d2f8f4a9cl },
-          { 0x50d7560655827a74l,0x8d6e65f33fb4f32cl,0x40a5d21189ee621al,
-            0x6d3f9e11c4474716l },
-          0 },
-        /* 59 << 32 */
-        { { 0xcb633a4ce9b2bb8fl,0x0475703f8c529253l,0x61e007b5a8878873l,
-            0x342d77ba14504159l },
-          { 0x2925175c313578dfl,0x4e631897b6b097f1l,0xe64d138929350e41l,
-            0x2fb20608ec7adccdl },
-          0 },
-        /* 60 << 32 */
-        { { 0xa560c234d5c0f5d1l,0x74f84bf62bdef0efl,0x61ed00005cbd3d0bl,
-            0xc74262d087fb408bl },
-          { 0xad30a6496cc64128l,0x708e3a31a4a8b154l,0xaf21ce2637f82074l,
-            0x31d33b38204c9a74l },
-          0 },
-        /* 61 << 32 */
-        { { 0x8f609fe04cc2f575l,0xe44f9784b35488c4l,0x0d464bb6180fa375l,
-            0x4f44d5d2de2247b8l },
-          { 0xf538eb38141ef077l,0x781f8f6e8fa456a4l,0x67e9a46429b4f39dl,
-            0x245d21e8b704c3e9l },
-          0 },
-        /* 63 << 32 */
-        { { 0x45a94ee858ffa7cdl,0x4d38bc6818053549l,0x0b4bc65a499d79f3l,
-            0xa81e3ab09159cab7l },
-          { 0xf13716efb47898cel,0xb7ee597c2e2d9044l,0x09396b90e6158276l,
-            0x5c644dc36a533fcel },
-          0 },
-        /* 64 << 32 */
-        { { 0xcca4428dbbe5a1a9l,0x8187fd5f3126bd67l,0x0036973a48105826l,
-            0xa39b6663b8bd61a0l },
-          { 0x6d42deef2d65a808l,0x4969044f94636b19l,0xf611ee47dd5d564cl,
-            0x7b2f3a49d2873077l },
-          0 },
-        /* 65 << 32 */
-        { { 0xbe4c16c3bf429668l,0xd32f56f0ef35db3bl,0xae8355de9ea4e3f1l,
-            0x8f66c4a2a450944el },
-          { 0xafab94c8b798fbe2l,0x18c57baff7f3d5cfl,0x692d191c5cfa5c7dl,
-            0xc0c25f69a689daebl },
-          0 },
-        /* 71 << 32 */
-        { { 0x15fb3ae398340d4cl,0xa8b9233a7de82134l,0x44971a545fc0dbc6l,
-            0xb2b4f0f3a1d3f094l },
-          { 0x8d9eaba1b6242bd4l,0xd8aad777787cc557l,0xb1ab8b7870d1a2bbl,
-            0x5d20f48cead3bfe3l },
-          0 },
-        /* 77 << 32 */
-        { { 0x4dacbf09a2bf9772l,0x969a4c4357aa8457l,0xadbe673b273ebfc5l,
-            0xb85582bb927778c9l },
-          { 0x748371855c03752cl,0xc337bc6bc2f60d11l,0x2c3838e4ad456a09l,
-            0xaf479c897e381842l },
-          0 },
-        /* 83 << 32 */
-        { { 0x8530ae751b1aea77l,0xf43b923ba8310cb9l,0x9c1a60c6bf4dd6c5l,
-            0x11885b863e3aaaa5l },
-          { 0x594a8fa90f69821el,0x1eece3d66bc37998l,0x1fd718f518df32bfl,
-            0x1c00c7d461d84082l },
-          0 },
-        /* 89 << 32 */
-        { { 0xd67ee3a4c763c3cfl,0x760b128305969234l,0x1a5ff331ec17f2d1l,
-            0x25f0392a84fecfefl },
-          { 0xb1bc004a3a80d47el,0xf450bf08182fee3bl,0xf11117681e19751el,
-            0x5b4127dae28ed23fl },
-          0 },
-        /* 95 << 32 */
-        { { 0x91e00defdaf08f09l,0x7ef41724f4738a07l,0x990fbbceaf1263fcl,
-            0x779121e3e6eeb5aal },
-          { 0x3e162c7a5a3ecf52l,0x73ae568a51be5faal,0x8bea1bfa451be8a9l,
-            0x3e8cd5db90e11097l },
-          0 },
-        /* 101 << 32 */
-        { { 0x90390f7224d27159l,0x685c139efd07e5d4l,0x4e21e44a3bc234a8l,
-            0x61b50f34eeb14dacl },
-          { 0x7beb0aa087555d58l,0x781326bcc806f0d2l,0xc289537a1eb7199fl,
-            0x44a31a037b42766el },
-          0 },
-        /* 107 << 32 */
-        { { 0x7d778206edde4b40l,0x34539fa18eb92fcdl,0x5a0bdd79bf52a552l,
-            0x066d3672fdcca75el },
-          { 0xd73fa893e28b5a5bl,0xb495135876c38698l,0x44469b0114ae16cfl,
-            0xb428c763691d6618l },
-          0 },
-        /* 113 << 32 */
-        { { 0x9022db8b69196353l,0x152ebb7dd7a4afd0l,0xea36fae57fcf1765l,
-            0xa8fc00ba0decea8al },
-          { 0x1047206a0c0b0414l,0x6607d8ade076df28l,0xf343e19966b8aba1l,
-            0x7f03c1ad311e208dl },
-          0 },
-        /* 116 << 32 */
-        { { 0xe6b4c96e888f3870l,0xa21bb618fe544042l,0x7122ee88bd817699l,
-            0xcb38ecebfa66e173l },
-          { 0x6ed5b3482c9cc05fl,0x591affc84ae0fd9el,0x7cf325ac6e7aaac0l,
-            0x2397c053d05e5be0l },
-          0 },
-        /* 119 << 32 */
-        { { 0x95363f61eaa96552l,0xe03bc6b38fb15b73l,0xa5c5808f2c389053l,
-            0xcd021e6c11b2030cl },
-          { 0x349ca9bdc038e30al,0x0a3368d4165afa2cl,0x043630debbfa1cc6l,
-            0xb8c4456ba7cdbf69l },
-          0 },
-        /* 125 << 32 */
-        { { 0x63aa3315fd7d2983l,0xaf4c96afa6a04bedl,0x3a5c0b5410814a74l,
-            0x9906f5e30f9b0770l },
-          { 0x622be6523676986fl,0x09ac5bc0173e7cb5l,0x1c40e56a502c8b3cl,
-            0xabb9a0f7253ce8f6l },
-          0 },
-    },
-    {
-        /* 0 << 40 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 40 */
-        { { 0x889f6d65533ef217l,0x7158c7e4c3ca2e87l,0xfb670dfbdc2b4167l,
-            0x75910a01844c257fl },
-          { 0xf336bf07cf88577dl,0x22245250e45e2acel,0x2ed92e8d7ca23d85l,
-            0x29f8be4c2b812f58l },
-          0 },
-        /* 3 << 40 */
-        { { 0xc51e414351facc61l,0xbaf2647de68a25bcl,0x8f5271a00ff872edl,
-            0x8f32ef993d2d9659l },
-          { 0xca12488c7593cbd4l,0xed266c5d02b82fabl,0x0a2f78ad14eb3f16l,
-            0xc34049484d47afe3l },
-          0 },
-        /* 4 << 40 */
-        { { 0xa6f3d574c005979dl,0xc2072b426a40e350l,0xfca5c1568de2ecf9l,
-            0xa8c8bf5ba515344el },
-          { 0x97aee555114df14al,0xd4374a4dfdc5ec6bl,0x754cc28f2ca85418l,
-            0x71cb9e27d3c41f78l },
-          0 },
-        /* 5 << 40 */
-        { { 0x09c1670209470496l,0xa489a5edebd23815l,0xc4dde4648edd4398l,
-            0x3ca7b94a80111696l },
-          { 0x3c385d682ad636a4l,0x6702702508dc5f1el,0x0c1965deafa21943l,
-            0x18666e16610be69el },
-          0 },
-        /* 7 << 40 */
-        { { 0x45beb4ca2a604b3bl,0x56f651843a616762l,0xf52f5a70978b806el,
-            0x7aa3978711dc4480l },
-          { 0xe13fac2a0e01fabcl,0x7c6ee8a5237d99f9l,0x251384ee05211ffel,
-            0x4ff6976d1bc9d3ebl },
-          0 },
-        /* 9 << 40 */
-        { { 0xdde0492316e043a2l,0x98a452611dd3d209l,0xeaf9f61bd431ebe8l,
-            0x00919f4dbaf56abdl },
-          { 0xe42417db6d8774b1l,0x5fc5279c58e0e309l,0x64aa40613adf81eal,
-            0xef419edabc627c7fl },
-          0 },
-        /* 10 << 40 */
-        { { 0x3919759239ef620fl,0x9d47284074fa29c4l,0x4e428fa39d416d83l,
-            0xd1a7c25129f30269l },
-          { 0x46076e1cd746218fl,0xf3ad6ee8110d967el,0xfbb5f434a00ae61fl,
-            0x3cd2c01980d4c929l },
-          0 },
-        /* 11 << 40 */
-        { { 0xfa24d0537a4af00fl,0x3f938926ca294614l,0x0d700c183982182el,
-            0x801334434cc59947l },
-          { 0xf0397106ec87c925l,0x62bd59fc0ed6665cl,0xe8414348c7cca8b5l,
-            0x574c76209f9f0a30l },
-          0 },
-        /* 13 << 40 */
-        { { 0x95be42e2bb8b6a07l,0x64be74eeca23f86al,0xa73d74fd154ce470l,
-            0x1c2d2857d8dc076al },
-          { 0xb1fa1c575a887868l,0x38df8e0b3de64818l,0xd88e52f9c34e8967l,
-            0x274b4f018b4cc76cl },
-          0 },
-        /* 15 << 40 */
-        { { 0x3f5c05b4f8b7559dl,0x0be4c7acfae29200l,0xdd6d3ef756532accl,
-            0xf6c3ed87eea7a285l },
-          { 0xe463b0a8f46ec59bl,0x531d9b14ecea6c83l,0x3d6bdbafc2dc836bl,
-            0x3ee501e92ab27f0bl },
-          0 },
-        /* 16 << 40 */
-        { { 0x8df275455922ac1cl,0xa7b3ef5ca52b3f63l,0x8e77b21471de57c4l,
-            0x31682c10834c008bl },
-          { 0xc76824f04bd55d31l,0xb6d1c08617b61c71l,0x31db0903c2a5089dl,
-            0x9c092172184e5d3fl },
-          0 },
-        /* 17 << 40 */
-        { { 0x7b1a921ea6b3340bl,0x6d7c4d7d7438a53el,0x2b9ef73c5bf71d8fl,
-            0xb5f6e0182b167a7cl },
-          { 0x5ada98ab0ce536a3l,0xee0f16f9e1fea850l,0xf6424e9d74f1c0c5l,
-            0x4d00de0cd3d10b41l },
-          0 },
-        /* 19 << 40 */
-        { { 0xd542f522a6533610l,0xfdde15a734ec439al,0x696560fedc87dd0dl,
-            0x69eab421e01fd05fl },
-          { 0xca4febdc95cc5988l,0x839be396c44d92fbl,0x7bedff6daffe543bl,
-            0xd2bb97296f6da43al },
-          0 },
-        /* 21 << 40 */
-        { { 0x5bc6dea80b8d0077l,0xb2adf5d1ea9c49efl,0x7104c20eaafe8659l,
-            0x1e3604f37866ee7el },
-          { 0x0cfc7e7b3075c8c5l,0x5281d9bb639c5a2bl,0xcbdf42494bc44ee3l,
-            0x835ab066655e9209l },
-          0 },
-        /* 23 << 40 */
-        { { 0x78fbda4b90b94ffal,0x447e52eb7beb993cl,0x920011bc92620d15l,
-            0x7bad6ecf481fd396l },
-          { 0xad3bd28ba989a09el,0x20491784a3e62b78l,0xcdcd7096b07bd9efl,
-            0x9bf5bb7337d780adl },
-          0 },
-        /* 25 << 40 */
-        { { 0xbe911a71a976c8d4l,0xba0346743fdd778el,0x2359e7434cf87ea1l,
-            0x8dccf65f07ebb691l },
-          { 0x6c2c18eb09746d87l,0x6a19945fd2ecc8fal,0xc67121ff2ffa0339l,
-            0x408c95ba9bd9fc31l },
-          0 },
-        /* 27 << 40 */
-        { { 0xa317204bcaa5da39l,0xd390df7468bf53d7l,0x56de18b2dbd71c0dl,
-            0xcb4d3bee75184779l },
-          { 0x815a219499d920a5l,0x9e10fb4ecf3d3a64l,0x7fd4901dfe92e1eel,
-            0x5d86d10d3ab87b2el },
-          0 },
-        /* 28 << 40 */
-        { { 0x24f2a692840bb336l,0x7c353bdca669fa7bl,0xda20d6fcdec9c300l,
-            0x625fbe2fa13a4f17l },
-          { 0xa2b1b61adbc17328l,0x008965bfa9515621l,0x49690939c620ff46l,
-            0x182dd27d8717e91cl },
-          0 },
-        /* 29 << 40 */
-        { { 0x98e9136c878303e4l,0x2769e74fd1e65efdl,0x6154c545809da56el,
-            0x8c5d50a04301638cl },
-          { 0x10f3d2068214b763l,0x2da9a2fc44df0644l,0xca912bab588a6fcdl,
-            0xe9e82d9b227e1932l },
-          0 },
-        /* 31 << 40 */
-        { { 0xcbdc4d66d080e55bl,0xad3f11e5b8f98d6bl,0x31bea68e18a32480l,
-            0xdf1c6fd52c1bcf6el },
-          { 0xadcda7ee118a3f39l,0xbd02f857ac060d5fl,0xd2d0265d86631997l,
-            0xb866a7d33818f2d4l },
-          0 },
-        /* 33 << 40 */
-        { { 0xfbcce2d31892d98dl,0x2e34bc9507de73dcl,0x3a48d1a94891eec1l,
-            0xe64499c24d31060bl },
-          { 0xe9674b7149745520l,0xf126ccaca6594a2cl,0x33e5c1a079945342l,
-            0x02aa0629066e061fl },
-          0 },
-        /* 34 << 40 */
-        { { 0xdfd7c0ae7af3191el,0x923ec111d68c70d9l,0xb6f1380bb675f013l,
-            0x9192a224f23d45bal },
-          { 0xbe7890f9524891e3l,0x45b24c47eba996bbl,0x59331e48320447e9l,
-            0x0e4d8753ac9afad4l },
-          0 },
-        /* 35 << 40 */
-        { { 0x49e49c38c9f5a6c3l,0x3f5eea44d8ee2a65l,0x02bf3e761c74bbb4l,
-            0x50d291cdef565571l },
-          { 0xf4edc290a36dd5fal,0x3015df9556dd6b85l,0x4494926aa5549a16l,
-            0x5de6c59390399e4al },
-          0 },
-        /* 36 << 40 */
-        { { 0x29be11c6ce800998l,0x72bb1752b90360d9l,0x2c1931975a4ad590l,
-            0x2ba2f5489fc1dbc0l },
-          { 0x7fe4eebbe490ebe0l,0x12a0a4cd7fae11c0l,0x7197cf81e903ba37l,
-            0xcf7d4aa8de1c6dd8l },
-          0 },
-        /* 37 << 40 */
-        { { 0x961fa6317e249e7bl,0x5c4f707796caed50l,0x6b176e62d7e50885l,
-            0x4dd5de72f390cbecl },
-          { 0x91fa29954b2bd762l,0x80427e6395b8dadel,0xd565bf1de2c34743l,
-            0x911da39d16e6c841l },
-          0 },
-        /* 39 << 40 */
-        { { 0x48365465802ff016l,0x6d2a561f71beece6l,0xdd299ce6f9707052l,
-            0x62a32698a23407bbl },
-          { 0x1d55bdb147004afbl,0xfadec124369b1084l,0x1ce78adf291c89f7l,
-            0x9f2eaf03278bc529l },
-          0 },
-        /* 40 << 40 */
-        { { 0x92af6bf43fd5684cl,0x2b26eecf80360aa1l,0xbd960f3000546a82l,
-            0x407b3c43f59ad8fel },
-          { 0x86cae5fe249c82bal,0x9e0faec72463744cl,0x87f551e894916272l,
-            0x033f93446ceb0615l },
-          0 },
-        /* 41 << 40 */
-        { { 0x04658ad212dba0cel,0x9e600624068822f0l,0x84661f11b26d368bl,
-            0xbca867d894ebb87al },
-          { 0x79506dc42f1bad89l,0x1a8322d3ebcbe7a1l,0xb4f1e102ac197178l,
-            0x29a950b779f7198cl },
-          0 },
-        /* 43 << 40 */
-        { { 0x19a6fb0984a3d1d5l,0x6c75c3a2ba5f5307l,0x7983485bf9698447l,
-            0x689f41b88b1cdc1el },
-          { 0x18f6fbd74c1979d0l,0x3e6be9a27a0b6708l,0x06acb615f63d5a8al,
-            0x8a817c098d0f64b1l },
-          0 },
-        /* 44 << 40 */
-        { { 0x1e5eb0d18be82e84l,0x89967f0e7a582fefl,0xbcf687d5a6e921fal,
-            0xdfee4cf3d37a09bal },
-          { 0x94f06965b493c465l,0x638b9a1c7635c030l,0x7666786466f05e9fl,
-            0xccaf6808c04da725l },
-          0 },
-        /* 45 << 40 */
-        { { 0xa9b3479b1b53a173l,0xc041eda3392eddc0l,0xdb8f804755edd7eel,
-            0xaf1f7a37ab60683cl },
-          { 0x9318603a72c0accbl,0xab1bb9fe401cbf3cl,0xc40e991e88afe245l,
-            0x9298a4580d06ac35l },
-          0 },
-        /* 46 << 40 */
-        { { 0x58e127d5036c2fe7l,0x5fe5020555b93361l,0xc1373d850f74a045l,
-            0x28cd79dbe8228e4bl },
-          { 0x0ae82320c2018d9al,0xf6d0049c78f8016al,0x381b6fe2149b31fbl,
-            0x33a0e8adec3cfbcfl },
-          0 },
-        /* 47 << 40 */
-        { { 0x23a6612e9eab5da7l,0xb645fe29d94d6431l,0xe3d74594ca1210c4l,
-            0xdc1376bceeca0674l },
-          { 0xfd40dfef657f0154l,0x7952a548d52cbac5l,0x0ee189583685ad28l,
-            0xd13639409ba9ca46l },
-          0 },
-        /* 48 << 40 */
-        { { 0xca2eb690768fccfcl,0xf402d37db835b362l,0x0efac0d0e2fdfccel,
-            0xefc9cdefb638d990l },
-          { 0x2af12b72d1669a8bl,0x33c536bc5774ccbdl,0x30b21909fb34870el,
-            0xc38fa2f77df25acal },
-          0 },
-        /* 49 << 40 */
-        { { 0x1337902f1c982cd6l,0x222e08fe14ec53eal,0x6c8abd0d330ef3e5l,
-            0xeb59e01531f6fd9dl },
-          { 0xd74ae554a8532df4l,0xbc010db1ab44c83el,0xe98016561b8f9285l,
-            0x65a9612783acc546l },
-          0 },
-        /* 51 << 40 */
-        { { 0x36a8b0a76770cfb1l,0x3338d52f9bb578fcl,0x5136c785f5ed12a4l,
-            0x652d47ed87bf129el },
-          { 0x9c6c827e6067c2d0l,0x61fc2f410345533al,0x2d7fb182130cea19l,
-            0x71a0186330b3ef85l },
-          0 },
-        /* 52 << 40 */
-        { { 0x74c5f02bbf81f3f5l,0x0525a5aeaf7e4581l,0x88d2aaba433c54ael,
-            0xed9775db806a56c5l },
-          { 0xd320738ac0edb37dl,0x25fdb6ee66cc1f51l,0xac661d1710600d76l,
-            0x931ec1f3bdd1ed76l },
-          0 },
-        /* 53 << 40 */
-        { { 0xb81e239161faa569l,0xb379f759bb40eebfl,0x9f2fd1b2a2c54549l,
-            0x0a968f4b0d6ba0ael },
-          { 0xaa869e6eedfe8c75l,0x0e36b298645ab173l,0x5a76282b0bcdefd7l,
-            0x9e949331d05293f2l },
-          0 },
-        /* 55 << 40 */
-        { { 0xc1cfa9a1c59fac6el,0x2648bffcb72747cel,0x5f8a39805f2e2637l,
-            0x8bd3a8eb73e65758l },
-          { 0xd9c43f1df14381a7l,0xecc1c3b0d6a86c10l,0xffcf4fa8a4a6dc74l,
-            0x7304fa834cea0a46l },
-          0 },
-        /* 57 << 40 */
-        { { 0x4460760c34dca952l,0xeac9cf2444c70444l,0xb879297b8493c87el,
-            0x295941a54b2dccb7l },
-          { 0x1e5cecede58721cdl,0xc8b58db74ca0d12bl,0x1927965c6da1d034l,
-            0x7220b02839ed1369l },
-          0 },
-        /* 59 << 40 */
-        { { 0xc38746c83c2e34b6l,0x9f27362e38a51042l,0x26febec02067afebl,
-            0xd9c4e15544e7371fl },
-          { 0x6035f469f92930d1l,0xe6ed7c08b4431b8bl,0xa25bf5903e16410dl,
-            0x147d83368adf4c18l },
-          0 },
-        /* 60 << 40 */
-        { { 0x7f01c9ecaa80ba59l,0x3083411a68538e51l,0x970370f1e88128afl,
-            0x625cc3db91dec14bl },
-          { 0xfef9666c01ac3107l,0xb2a8d577d5057ac3l,0xb0f2629992be5df7l,
-            0xf579c8e500353924l },
-          0 },
-        /* 61 << 40 */
-        { { 0xbd9398d6ca02669fl,0x896e053bf9ad11a1l,0xe024b699a3556f9fl,
-            0x23b4b96ad53cbca3l },
-          { 0x549d2d6c89733dd6l,0x3dae193f394f3179l,0x8bf7ec1cdfeda825l,
-            0xf6a1db7a8a4844b4l },
-          0 },
-        /* 63 << 40 */
-        { { 0x3b5403d56437a027l,0xda32bbd233ed30aal,0xd2ad3baa906de0cal,
-            0x3b6df514533f736el },
-          { 0x986f1cab5df9b9c4l,0x41cd2088970d330el,0xaae7c2238c20a923l,
-            0x52760a6e1e951dc0l },
-          0 },
-        /* 64 << 40 */
-        { { 0xb8fa3d931341ed7al,0x4223272ca7b59d49l,0x3dcb194783b8c4a4l,
-            0x4e413c01ed1302e4l },
-          { 0x6d999127e17e44cel,0xee86bf7533b3adfbl,0xf6902fe625aa96cal,
-            0xb73540e4e5aae47dl },
-          0 },
-        /* 65 << 40 */
-        { { 0x55318a525e34036cl,0xc3acafaaf9884e3fl,0xe5ba15cea042ba04l,
-            0x56a1d8960ada550el },
-          { 0xa5198cae87b76764l,0xd079d1f0b6fd84fbl,0xb22b637bcbe363edl,
-            0xbe8ab7d64499deaal },
-          0 },
-        /* 71 << 40 */
-        { { 0xbe8eba5eb4925f25l,0x00f8bf582e3159d6l,0xb1aa24fa18856070l,
-            0x22ea8b74e4c30b22l },
-          { 0x512f633e55bbe4e8l,0x82ba62318678aee9l,0xea05da90fdf72b7el,
-            0x616b9bc7a4fc65eel },
-          0 },
-        /* 77 << 40 */
-        { { 0xe31ee3b3b7c221e7l,0x10353824e353fa43l,0x9d2f3df69dd2a86fl,
-            0x8a12ab9322ccffecl },
-          { 0x25c8e326d666f9e5l,0x33ea98a0598da7fbl,0x2fc1de0917f74e17l,
-            0x0d0b6c7a35efb211l },
-          0 },
-        /* 83 << 40 */
-        { { 0x22a82c6c804e6ecel,0x824a170b1d8fce9el,0x621802becee65ed0l,
-            0x4a4e9e7895ec4285l },
-          { 0x8da0988fa8940b7al,0xaff89c5b86445aa5l,0x386fdbdad689cde9l,
-            0x3aeaae7d9f5caaccl },
-          0 },
-        /* 89 << 40 */
-        { { 0xe9cb9e68a7b62f4cl,0x515cae0ec3b7092el,0xb8abec354b491f52l,
-            0x672673fd01eeabc1l },
-          { 0x65e5739f7ad6e8a1l,0xc2da8e003d91b2f9l,0xcc43229cced84319l,
-            0x0f8cbf9574ccf2d1l },
-          0 },
-        /* 95 << 40 */
-        { { 0xb03d1cfb1b2f872al,0x88aef4670872b6f7l,0xaafe55e48ea9170cl,
-            0xd5cc4875f24aa689l },
-          { 0x7e5732908458ce84l,0xef4e143d58bfc16dl,0xc58626efaa222836l,
-            0x01c60ec0ca5e0cb8l },
-          0 },
-        /* 101 << 40 */
-        { { 0x123901aa36337c09l,0x1697acadd2f5e675l,0xc0a1ddd022fe2bael,
-            0xf68ea88cff0210ddl },
-          { 0x665d11e014168709l,0x912a575f45f25321l,0x7e7ed38070c78934l,
-            0x663d692cb0a46322l },
-          0 },
-        /* 107 << 40 */
-        { { 0x912ab8bd8642cba4l,0x97fab1a3b6b50b73l,0x76666b3cb86ef354l,
-            0x16d41330fa5ecce9l },
-          { 0x77c7c138c7da404bl,0xc6508cb78c983fb0l,0xe5881733f9004984l,
-            0x76dea7794182c7abl },
-          0 },
-        /* 113 << 40 */
-        { { 0x16db18583556b765l,0x39c18c200263755al,0x7b6691f591c15201l,
-            0x4e4c17b168514ea9l },
-          { 0xacbe449e06f5f20al,0xeb9119d2541ddfb6l,0x2f6e687bf2eac86fl,
-            0xb161471ec14ac508l },
-          0 },
-        /* 116 << 40 */
-        { { 0x58846d32c4744733l,0x40517c71379f9e34l,0x2f65655f130ef6cal,
-            0x526e4488f1f3503fl },
-          { 0x8467bd177ee4a976l,0x1d9dc913921363d1l,0xd8d24c33b069e041l,
-            0x5eb5da0a2cdf7f51l },
-          0 },
-        /* 119 << 40 */
-        { { 0x81c2cc32951ab3e7l,0xc86d9a109b0c7e87l,0x0b7a18bd606ef408l,
-            0x099b5bbfe6c2251el },
-          { 0x46d627d0bfce880fl,0xbfaddcbbe1c6865al,0xa9ab6183d2bb9a00l,
-            0x23cb9a2720ad9789l },
-          0 },
-        /* 125 << 40 */
-        { { 0x1592d0630c25fbebl,0x13869ec24995a3fal,0x6413f494861d0a73l,
-            0xa3b782342f9f1b89l },
-          { 0x113689e2b6cad351l,0x53be2014a873dcc1l,0xccf405e0c6bb1be7l,
-            0x4fff7b4ca9061ca9l },
-          0 },
-    },
-    {
-        /* 0 << 48 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 48 */
-        { { 0xcc7a64880a750c0fl,0x39bacfe34e548e83l,0x3d418c760c110f05l,
-            0x3e4daa4cb1f11588l },
-          { 0x2733e7b55ffc69ffl,0x46f147bc92053127l,0x885b2434d722df94l,
-            0x6a444f65e6fc6b7cl },
-          0 },
-        /* 3 << 48 */
-        { { 0x6d0b16f4bdaedfbdl,0x23fd326086746cedl,0x8bfb1d2fff4b3e17l,
-            0xc7f2ec2d019c14c8l },
-          { 0x3e0832f245104b0dl,0x5f00dafbadea2b7el,0x29e5cf6699fbfb0fl,
-            0x264f972361827cdal },
-          0 },
-        /* 4 << 48 */
-        { { 0x97b14f7ea90567e6l,0x513257b7b6ae5cb7l,0x85454a3c9f10903dl,
-            0xd8d2c9ad69bc3724l },
-          { 0x38da93246b29cb44l,0xb540a21d77c8cbacl,0x9bbfe43501918e42l,
-            0xfffa707a56c3614el },
-          0 },
-        /* 5 << 48 */
-        { { 0x6eb1a2f3e30bc27fl,0xe5f0c05ab0836511l,0x4d741bbf4965ab0el,
-            0xfeec41ca83464bbdl },
-          { 0x1aca705f99d0b09fl,0xc5d6cc56f42da5fal,0x49964eddcc52b931l,
-            0x8ae59615c884d8d8l },
-          0 },
-        /* 7 << 48 */
-        { { 0xf634b57b39f8868al,0xe27f4fd475cc69afl,0xa47e58cbd0d5496el,
-            0x8a26793fd323e07fl },
-          { 0xc61a9b72fa30f349l,0x94c9d9c9b696d134l,0x792beca85880a6d1l,
-            0xbdcc4645af039995l },
-          0 },
-        /* 9 << 48 */
-        { { 0xce7ef8e58c796c3cl,0x9adaae84dd66e57al,0x784ae13e45227f33l,
-            0xb046c5b82a85e757l },
-          { 0xb7aa50aeec37631fl,0xbedc4fca3b300758l,0x0f82567e0ac9700bl,
-            0x1071d9d44ff5f8d2l },
-          0 },
-        /* 10 << 48 */
-        { { 0x61360ee99e240d18l,0x057cdcacb4b94466l,0xe7667cd12fe5325cl,
-            0x1fa297b521974e3bl },
-          { 0xfa4081e7db083d76l,0x31993be6f206bd15l,0x8949269b14c19f8cl,
-            0x21468d72a9d92357l },
-          0 },
-        /* 11 << 48 */
-        { { 0xd09ef6c4e51a2811l,0x39f6862bb8fb66b9l,0x64e77f8d22dfaa99l,
-            0x7b10504461b08aacl },
-          { 0x71704e4c4a7df332l,0xd09734342ffe015bl,0xab0eaf4408d3020el,
-            0x28b1909eed63b97al },
-          0 },
-        /* 13 << 48 */
-        { { 0x2f3fa882cdadcd4fl,0xa4ef68595f631995l,0xe52ca2f9e531766fl,
-            0x20af5c3057e2c1d3l },
-          { 0x1e4828f6e51e94b8l,0xf900a1751a2f5d4fl,0xe831adb3392c58a0l,
-            0x4c5a90ca1b6e5866l },
-          0 },
-        /* 15 << 48 */
-        { { 0x5f3dcba86182827cl,0xd1a448ddbd7e7252l,0x2d8f96fcf493b815l,
-            0xba0a4c263b0aa95fl },
-          { 0x88a1514063a0007fl,0x9564c25e6a9c5846l,0x5a4d7b0fdc0fcbcal,
-            0x2275daa33f8a740el },
-          0 },
-        /* 16 << 48 */
-        { { 0x83f49167ceca9754l,0x426d2cf64b7939a0l,0x2555e355723fd0bfl,
-            0xa96e6d06c4f144e2l },
-          { 0x4768a8dd87880e61l,0x15543815e508e4d5l,0x09d7e772b1b65e15l,
-            0x63439dd6ac302fa0l },
-          0 },
-        /* 17 << 48 */
-        { { 0x159591cc0461086bl,0xb695aa9495e66e51l,0x2d4c946779ded531l,
-            0xbd2482ba89c2be79l },
-          { 0x8ee2658aa20bbf19l,0xc000528a32247917l,0xd924be4affeae845l,
-            0x51312bebed992c8bl },
-          0 },
-        /* 19 << 48 */
-        { { 0x3a01b958dc752bd9l,0x2babdbc20c215d45l,0xe689d79a131641c1l,
-            0x48e8f0da80e05ed4l },
-          { 0x4b505feb77bb70c4l,0xefbd3e2bb6057ef7l,0x7583e22dce603ca5l,
-            0xfbe3b1f22c5c70c7l },
-          0 },
-        /* 21 << 48 */
-        { { 0x8ec1ecf029e5e35al,0x2f3168e58645c2b3l,0xe9297362c7f94cb2l,
-            0x4fbf1466d1c90b39l },
-          { 0x3e4f7656920bae2al,0x805d04b9f1beb172l,0x729a7208dbdbd4b4l,
-            0x1aade45687aeca53l },
-          0 },
-        /* 23 << 48 */
-        { { 0xb0ff1f541934a508l,0x19e1397604bbf31al,0xb2a8e6033717a6b4l,
-            0xd601e45d0ef12cb9l },
-          { 0x563f0af5b515e98el,0x9b129db633984f9bl,0xe34aba2fa47e4a65l,
-            0xb56f82d19e3f9d82l },
-          0 },
-        /* 25 << 48 */
-        { { 0x0203effdb1209b86l,0x21f063edb19d6cbfl,0x59f53476980f275bl,
-            0x202456d7b7ac5e80l },
-          { 0xe5a8c05f4900edc9l,0x04c08eb470f01e86l,0xf74ac2241dcd98cel,
-            0x7e77cc0ce2e830dbl },
-          0 },
-        /* 27 << 48 */
-        { { 0x74e37234a9747edel,0x4fc9fbb1361b1013l,0xe7b533733cf357efl,
-            0x6aa2dd2c991c4193l },
-          { 0x7887e4d2a770917al,0xdd1809b4c20d24cbl,0x004cd7c38e9c2d3el,
-            0xc77c5baba9970abel },
-          0 },
-        /* 28 << 48 */
-        { { 0x20ac0351d598d710l,0x272c4166cb3a4da4l,0xdb82fe1aca71de1fl,
-            0x746e79f2d8f54b0fl },
-          { 0x6e7fc7364b573e9bl,0x75d03f46fd4b5040l,0x5c1cc36d0b98d87bl,
-            0x513ba3f11f472da1l },
-          0 },
-        /* 29 << 48 */
-        { { 0x52927eaac3af237fl,0xfaa06065d7398767l,0x042e72b497c6ce0bl,
-            0xdaed0cc40a9f2361l },
-          { 0xddc2e11c2fc1bb4al,0x631da5770c1a9ef8l,0x8a4cfe44680272bfl,
-            0xc76b9f7262fb5cc3l },
-          0 },
-        /* 31 << 48 */
-        { { 0x248f814538b3aae3l,0xb5345864bc204334l,0x66d6b5bc1d127524l,
-            0xe312080d14f572d3l },
-          { 0x13ed15a716abafebl,0x6f18ce27dba967bel,0x96c9e826ef08552dl,
-            0x2c191b06be2b63e0l },
-          0 },
-        /* 33 << 48 */
-        { { 0xde4be45dc115ca51l,0xa028cafe934dabd6l,0x7e875663d1c0f8c5l,
-            0xa8e32ab063d17473l },
-          { 0x33f55bd5543199aal,0x79d2c937a2071d6el,0xa6a6758ceff16f28l,
-            0x9c5f93ef87d85201l },
-          0 },
-        /* 34 << 48 */
-        { { 0x7f2e440381e9ede3l,0x243c3894caf6df0al,0x7c605bb11c073b11l,
-            0xcd06a541ba6a4a62l },
-          { 0x2916894949d4e2e5l,0x33649d074af66880l,0xbfc0c885e9a85035l,
-            0xb4e52113fc410f4bl },
-          0 },
-        /* 35 << 48 */
-        { { 0xe86f21bc3ad4c81el,0x53b408403a37dcebl,0xaa606087383402cdl,
-            0xc248caf185452b1dl },
-          { 0x38853772576b57cdl,0xe2798e5441b7a6edl,0x7c2f1eed95ef4a33l,
-            0xccd7e776adb1873cl },
-          0 },
-        /* 36 << 48 */
-        { { 0xdca3b70678a6513bl,0x92ea4a2a9edb1943l,0x02642216db6e2dd8l,
-            0x9b45d0b49fd57894l },
-          { 0x114e70dbc69d11ael,0x1477dd194c57595fl,0xbc2208b4ec77c272l,
-            0x95c5b4d7db68f59cl },
-          0 },
-        /* 37 << 48 */
-        { { 0xd978bb791c61030al,0xa47325d2218222f3l,0x65ad4d4832e67d97l,
-            0x31e4ed632e0d162al },
-          { 0x7308ea317f76da37l,0xcfdffe87d93f35d8l,0xf4b2d60ee6f96cc4l,
-            0x8028f3bd0117c421l },
-          0 },
-        /* 39 << 48 */
-        { { 0x7df80cbb9543edb6l,0xa07a54df40b0b3bcl,0xacbd067cc1888488l,
-            0x61ad61318a00c721l },
-          { 0x67e7599ebe2e6fe6l,0x8349d568f7270e06l,0x5630aabc307bc0c7l,
-            0x97210b3f71af442fl },
-          0 },
-        /* 40 << 48 */
-        { { 0xfe541fa47ea67c77l,0x952bd2afe3ea810cl,0x791fef568d01d374l,
-            0xa3a1c6210f11336el },
-          { 0x5ad0d5a9c7ec6d79l,0xff7038af3225c342l,0x003c6689bc69601bl,
-            0x25059bc745e8747dl },
-          0 },
-        /* 41 << 48 */
-        { { 0x58bdabb7ef701b5fl,0x64f987aee00c3a96l,0x533b391e2d585679l,
-            0x30ad79d97a862e03l },
-          { 0xd941471e8177b261l,0x33f65cb856a9018el,0x985ce9f607759fc4l,
-            0x9b085f33aefdbd9el },
-          0 },
-        /* 43 << 48 */
-        { { 0xab2fa51a9c43ee15l,0x457f338263f30575l,0xce8dcd863e75a6e0l,
-            0x67a03ab86e70421al },
-          { 0xe72c37893e174230l,0x45ffff6c066f4816l,0x3a3dd84879a2d4a7l,
-            0xefa4b7e68b76c24cl },
-          0 },
-        /* 44 << 48 */
-        { { 0x9a75c80676cb2566l,0x8f76acb1b24892d9l,0x7ae7b9cc1f08fe45l,
-            0x19ef73296a4907d8l },
-          { 0x2db4ab715f228bf0l,0xf3cdea39817032d7l,0x0b1f482edcabe3c0l,
-            0x3baf76b4bb86325cl },
-          0 },
-        /* 45 << 48 */
-        { { 0xd6be8f00e39e056al,0xb58f87a6232fa3bcl,0xd5cb09dc6b18c772l,
-            0x3177256da8e7e17bl },
-          { 0x1877fd34230bf92cl,0x6f9031175a36f632l,0x526a288728e2c9d9l,
-            0xc373fc94415ec45cl },
-          0 },
-        /* 46 << 48 */
-        { { 0xd49065e010089465l,0x3bab5d298e77c596l,0x7636c3a6193dbd95l,
-            0xdef5d294b246e499l },
-          { 0xb22c58b9286b2475l,0xa0b93939cd80862bl,0x3002c83af0992388l,
-            0x6de01f9beacbe14cl },
-          0 },
-        /* 47 << 48 */
-        { { 0x70fa6e2a2bf5e373l,0x501691739271694cl,0xd6ebb98c5d2ed9f1l,
-            0x11fd0b3f225bf92dl },
-          { 0x51ffbcea1e3d5520l,0xa7c549875513ad47l,0xe9689750b431d46dl,
-            0x6e69fecbb620cb9al },
-          0 },
-        /* 48 << 48 */
-        { { 0x6aac688eadd70482l,0x708de92a7b4a4e8al,0x75b6dd73758a6eefl,
-            0xea4bf352725b3c43l },
-          { 0x10041f2c87912868l,0xb1b1be95ef09297al,0x19ae23c5a9f3860al,
-            0xc4f0f839515dcf4bl },
-          0 },
-        /* 49 << 48 */
-        { { 0xf3c22398e04b5734l,0x4fba59b275f2579dl,0xbf95182d691901b3l,
-            0x4c139534eb599496l },
-          { 0xf3f821de33b77e8bl,0x66e580743785d42fl,0xe3ba3d5abdc89c2dl,
-            0x7ee988bdd19f37b9l },
-          0 },
-        /* 51 << 48 */
-        { { 0xe9ba62ca2ee53eb0l,0x64295ae23401d7dal,0x70ed8be24e493580l,
-            0x702caa624502732fl },
-          { 0xb1f4e21278d0cedfl,0x130b114bdc97057bl,0x9c5d0bd3c38c77b5l,
-            0xd9d641e18bad68e7l },
-          0 },
-        /* 52 << 48 */
-        { { 0xc71e27bf8538a5c6l,0x195c63dd89abff17l,0xfd3152851b71e3dal,
-            0x9cbdfda7fa680fa0l },
-          { 0x9db876ca849d7eabl,0xebe2764b3c273271l,0x663357e3f208dceal,
-            0x8c5bd833565b1b70l },
-          0 },
-        /* 53 << 48 */
-        { { 0x7c2dea1d122aebd4l,0x090bee4a138c1e4dl,0x94a9ffe59e4aca6cl,
-            0x8f3212ba5d405c7fl },
-          { 0x6618185f180b5e85l,0x76298d46f455ab9fl,0x0c804076476b2d88l,
-            0x45ea9d03d5a40b39l },
-          0 },
-        /* 55 << 48 */
-        { { 0xdf325ac76a2ed772l,0x35da47ccb0da2765l,0x94ce6f460bc9b166l,
-            0xe0fc82fb5f7f3628l },
-          { 0x2b26d588c055f576l,0xb9d37c97ec2bae98l,0xffbbead856908806l,
-            0xa8c2df87437f4c84l },
-          0 },
-        /* 57 << 48 */
-        { { 0x47d11c3528430994l,0x0183df71cf13d9d3l,0x98604c89aa138fe5l,
-            0xb1432e1c32c09aa1l },
-          { 0xf19bc45d99bd5e34l,0xb198be72108e9b89l,0xee500ae9dacde648l,
-            0x5936cf98746870a9l },
-          0 },
-        /* 59 << 48 */
-        { { 0x6d8efb98ed1d5a9bl,0x2e0b08e697f778fal,0xda728454dc5e0835l,
-            0x2c28a45f8e3651c4l },
-          { 0x667fab6f7ee77088l,0xd94429c8f29a94b4l,0xd83d594d9deea5b2l,
-            0x2dc08ccbbea58080l },
-          0 },
-        /* 60 << 48 */
-        { { 0xba5514df3fd165e8l,0x499fd6a9061f8811l,0x72cd1fe0bfef9f00l,
-            0x120a4bb979ad7e8al },
-          { 0xf2ffd0955f4a5ac5l,0xcfd174f195a7a2f0l,0xd42301ba9d17baf1l,
-            0xd2fa487a77f22089l },
-          0 },
-        /* 61 << 48 */
-        { { 0xfb5f53ba20a9a01el,0x3adb174fd20d6a9cl,0x6db8bb6d80e0f64fl,
-            0x596e428df6a26f76l },
-          { 0xbab1f846e6a4e362l,0x8bdb22af9b1becbdl,0x62b48335f31352adl,
-            0xd72c26409634f727l },
-          0 },
-        /* 63 << 48 */
-        { { 0xaaa61cb22b1ec1c3l,0x3b5156722cb6f00el,0x67d1be0a8bf83f60l,
-            0x88f1627aa4b804bcl },
-          { 0xc52b11a7cdade2abl,0xa6a8b71a606a4e9dl,0x04e0e6697b900551l,
-            0x35cfa33c8d5ad0d2l },
-          0 },
-        /* 64 << 48 */
-        { { 0xb93452381d531696l,0x57201c0088cdde69l,0xdde922519a86afc7l,
-            0xe3043895bd35cea8l },
-          { 0x7608c1e18555970dl,0x8267dfa92535935el,0xd4c60a57322ea38bl,
-            0xe0bf7977804ef8b5l },
-          0 },
-        /* 65 << 48 */
-        { { 0x375ca189b60f0d5al,0xc9458cf949a78362l,0x61c1c5024262c03al,
-            0x299353db4363d5bel },
-          { 0xe3565124dac407fel,0x16ea66cd5b93c532l,0xe5c6aec2749df8e3l,
-            0x59181317ce3ee4bfl },
-          0 },
-        /* 71 << 48 */
-        { { 0xd46ea34af41c2a3cl,0x9936184916545c98l,0xd7cb800ccf2498b4l,
-            0xe71d088d9353fe87l },
-          { 0x43443cbeae2e172cl,0x77131656ca905cb3l,0x76471fd1dce63594l,
-            0x346b1d1738f5e264l },
-          0 },
-        /* 77 << 48 */
-        { { 0x22b1e639f6d0a419l,0x8bbb1fad7cea278cl,0xf07f6c01370cc86al,
-            0x661bd027d39b837fl },
-          { 0x042c7a69de606098l,0x93433b154e44eb12l,0x20f44ada88d8bfe8l,
-            0xb44f66e64ccbfab6l },
-          0 },
-        /* 83 << 48 */
-        { { 0x1cc32158583d9745l,0x9306223cad1c2201l,0x76aa8d0995748039l,
-            0x29425391707e9b59l },
-          { 0x8501c0d4487cdf9el,0xbe08e89c205c5611l,0xa950400b04ccc48bl,
-            0xb614b69b637e966bl },
-          0 },
-        /* 89 << 48 */
-        { { 0xd9c3c1238ffa5c4bl,0xc65765f7f3593988l,0x9a7e5d2728242119l,
-            0x0ad27b5097ad7620l },
-          { 0x154cc5eb413a8b23l,0xae93d8de7afa8254l,0x9ce5116cab9907b5l,
-            0x9a163d78063103b9l },
-          0 },
-        /* 95 << 48 */
-        { { 0x5c4c299291086d2al,0x42c6ca9de8e2d951l,0xe67ecf93dd353f30l,
-            0xba54557fe7167c2el },
-          { 0x04a7eb2db734c779l,0x8f345605e300711al,0x4811c1ad67b27de6l,
-            0xb7ac8e842731d5f0l },
-          0 },
-        /* 101 << 48 */
-        { { 0xee33a1d8e449ac46l,0x2500ba0aaaebfa2dl,0x8fb914ebc424eff4l,
-            0x3a36545d3989255el },
-          { 0xd24f2484761235e6l,0x2fc5d5ddd9b2c04bl,0x73660f86070ab0dbl,
-            0x2e266d0479d20c7bl },
-          0 },
-        /* 107 << 48 */
-        { { 0x143752d5316d19a3l,0x56a55e01915497b8l,0x44ba4b2609a5fd15l,
-            0xe4fc3e7fd9bee4eel },
-          { 0x6f9d8609878a9f26l,0xdf36b5bd2ede7a20l,0x8e03e712a9a3e435l,
-            0x4ced555b56546d33l },
-          0 },
-        /* 113 << 48 */
-        { { 0x89a6aaab0882717el,0x56a9736b43fa5153l,0xdb07dcc9d0e1fb1al,
-            0xe7c986d34145e227l },
-          { 0x57be66abb10dad51l,0xa47b964e4aa01ea7l,0xd851d9f36bb837cbl,
-            0x9851ab3d652e13f7l },
-          0 },
-        /* 116 << 48 */
-        { { 0x22b88a805616ee30l,0xfb09548fe7ab1083l,0x8ad6ab0d511270cdl,
-            0x61f6c57a6924d9abl },
-          { 0xa0f7bf7290aecb08l,0x849f87c90df784a4l,0x27c79c15cfaf1d03l,
-            0xbbf9f675c463facel },
-          0 },
-        /* 119 << 48 */
-        { { 0x65512fb716dd6ce1l,0xfa76ebc960d53b35l,0x31e5322e19ada3bel,
-            0x7e259b75d0ccc3cdl },
-          { 0xd36d03f0e025fd69l,0xbefab782eea9e5f3l,0x1569969dd09ce6a7l,
-            0x2df5396178c385b0l },
-          0 },
-        /* 125 << 48 */
-        { { 0x4201652fce0ccac7l,0x12f8e93df1d29d2dl,0x6c2ac9b2220f00c1l,
-            0x4ee6a685a850baa9l },
-          { 0x2c2371f163ee8829l,0xddff16488f464433l,0xeab6cd8869a2c413l,
-            0xcae34beb85e4c2a8l },
-          0 },
-    },
-    {
-        /* 0 << 56 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 56 */
-        { { 0xc7913e91991724f3l,0x5eda799c39cbd686l,0xddb595c763d4fc1el,
-            0x6b63b80bac4fed54l },
-          { 0x6ea0fc697e5fb516l,0x737708bad0f1c964l,0x9628745f11a92ca5l,
-            0x61f379589a86967al },
-          0 },
-        /* 3 << 56 */
-        { { 0x46a8c4180d738dedl,0x6f1a5bb0e0de5729l,0xf10230b98ba81675l,
-            0x32c6f30c112b33d4l },
-          { 0x7559129dd8fffb62l,0x6a281b47b459bf05l,0x77c1bd3afa3b6776l,
-            0x0709b3807829973al },
-          0 },
-        /* 4 << 56 */
-        { { 0x8c26b232a3326505l,0x38d69272ee1d41bfl,0x0459453effe32afal,
-            0xce8143ad7cb3ea87l },
-          { 0x932ec1fa7e6ab666l,0x6cd2d23022286264l,0x459a46fe6736f8edl,
-            0x50bf0d009eca85bbl },
-          0 },
-        /* 5 << 56 */
-        { { 0x0b825852877a21ecl,0x300414a70f537a94l,0x3f1cba4021a9a6a2l,
-            0x50824eee76943c00l },
-          { 0xa0dbfcecf83cba5dl,0xf953814893b4f3c0l,0x6174416248f24dd7l,
-            0x5322d64de4fb09ddl },
-          0 },
-        /* 7 << 56 */
-        { { 0xa337c447f1f0ced1l,0x800cc7939492dd2bl,0x4b93151dbea08efal,
-            0x820cf3f8de0a741el },
-          { 0xff1982dc1c0f7d13l,0xef92196084dde6cal,0x1ad7d97245f96ee3l,
-            0x319c8dbe29dea0c7l },
-          0 },
-        /* 9 << 56 */
-        { { 0x0ae1d63b0eb919b0l,0xd74ee51da74b9620l,0x395458d0a674290cl,
-            0x324c930f4620a510l },
-          { 0x2d1f4d19fbac27d4l,0x4086e8ca9bedeeacl,0x0cdd211b9b679ab8l,
-            0x5970167d7090fec4l },
-          0 },
-        /* 10 << 56 */
-        { { 0x3420f2c9faf1fc63l,0x616d333a328c8bb4l,0x7d65364c57f1fe4al,
-            0x9343e87755e5c73al },
-          { 0x5795176be970e78cl,0xa36ccebf60533627l,0xfc7c738009cdfc1bl,
-            0xb39a2afeb3fec326l },
-          0 },
-        /* 11 << 56 */
-        { { 0xb7ff1ba16224408al,0xcc856e92247cfc5el,0x01f102e7c18bc493l,
-            0x4613ab742091c727l },
-          { 0xaa25e89cc420bf2bl,0x00a5317690337ec2l,0xd2be9f437d025fc7l,
-            0x3316fb856e6fe3dcl },
-          0 },
-        /* 13 << 56 */
-        { { 0x67332cfc2064cfd1l,0x339c31deb0651934l,0x719b28d52a3bcbeal,
-            0xee74c82b9d6ae5c6l },
-          { 0x0927d05ebaf28ee6l,0x82cecf2c9d719028l,0x0b0d353eddb30289l,
-            0xfe4bb977fddb2e29l },
-          0 },
-        /* 15 << 56 */
-        { { 0xe10b2ab817a91cael,0xb89aab6508e27f63l,0x7b3074a7dba3ddf9l,
-            0x1c20ce09330c2972l },
-          { 0x6b9917b45fcf7e33l,0xe6793743945ceb42l,0x18fc22155c633d19l,
-            0xad1adb3cc7485474l },
-          0 },
-        /* 16 << 56 */
-        { { 0x646f96796424c49bl,0xf888dfe867c241c9l,0xe12d4b9324f68b49l,
-            0x9a6b62d8a571df20l },
-          { 0x81b4b26d179483cbl,0x666f96329511fae2l,0xd281b3e4d53aa51fl,
-            0x7f96a7657f3dbd16l },
-          0 },
-        /* 17 << 56 */
-        { { 0xa7f8b5bf074a30cel,0xd7f52107005a32e6l,0x6f9e090750237ed4l,
-            0x2f21da478096fa2bl },
-          { 0xf3e19cb4eec863a0l,0xd18f77fd9527620al,0x9505c81c407c1cf8l,
-            0x9998db4e1b6ec284l },
-          0 },
-        /* 19 << 56 */
-        { { 0x794e2d5984ac066cl,0xf5954a92e68c69a0l,0x28c524584fd99dccl,
-            0x60e639fcb1012517l },
-          { 0xc2e601257de79248l,0xe9ef6404f12fc6d7l,0x4c4f28082a3b5d32l,
-            0x865ad32ec768eb8al },
-          0 },
-        /* 21 << 56 */
-        { { 0x4f4ddf91b2f1ac7al,0xf99eaabb760fee27l,0x57f4008a49c228e5l,
-            0x090be4401cf713bbl },
-          { 0xac91fbe45004f022l,0xd838c2c2569e1af6l,0xd6c7d20b0f1daaa5l,
-            0xaa063ac11bbb02c0l },
-          0 },
-        /* 23 << 56 */
-        { { 0x54935fcb81d73c9el,0x6d07e9790a5e97abl,0x4dc7b30acf3a6babl,
-            0x147ab1f3170bee11l },
-          { 0x0aaf8e3d9fafdee4l,0xfab3dbcb538a8b95l,0x405df4b36ef13871l,
-            0xf1f4e9cb088d5a49l },
-          0 },
-        /* 25 << 56 */
-        { { 0x43c01b87459afccdl,0x6bd45143b7432652l,0x8473453055b5d78el,
-            0x81088fdb1554ba7dl },
-          { 0xada0a52c1e269375l,0xf9f037c42dc5ec10l,0xc066060794bfbc11l,
-            0xc0a630bbc9c40d2fl },
-          0 },
-        /* 27 << 56 */
-        { { 0x9a730ed44763eb50l,0x24a0e221c1ab0d66l,0x643b6393648748f3l,
-            0x1982daa16d3c6291l },
-          { 0x6f00a9f78bbc5549l,0x7a1783e17f36384el,0xe8346323de977f50l,
-            0x91ab688db245502al },
-          0 },
-        /* 28 << 56 */
-        { { 0x331ab6b56d0bdd66l,0x0a6ef32e64b71229l,0x1028150efe7c352fl,
-            0x27e04350ce7b39d3l },
-          { 0x2a3c8acdc1070c82l,0xfb2034d380c9feefl,0x2d729621709f3729l,
-            0x8df290bf62cb4549l },
-          0 },
-        /* 29 << 56 */
-        { { 0x02f99f33fc2e4326l,0x3b30076d5eddf032l,0xbb21f8cf0c652fb5l,
-            0x314fb49eed91cf7bl },
-          { 0xa013eca52f700750l,0x2b9e3c23712a4575l,0xe5355557af30fbb0l,
-            0x1ada35167c77e771l },
-          0 },
-        /* 31 << 56 */
-        { { 0xdc9f46fc609e4a74l,0x2a44a143ba667f91l,0xbc3d8b95b4d83436l,
-            0xa01e4bd0c7bd2958l },
-          { 0x7b18293273483c90l,0xa79c6aa1a7c7b598l,0xbf3983c6eaaac07el,
-            0x8f18181e96e0d4e6l },
-          0 },
-        /* 33 << 56 */
-        { { 0x0bfc27eeacee5043l,0xae419e732eb10f02l,0x19c028d18943fb05l,
-            0x71f01cf7ff13aa2al },
-          { 0x7790737e8887a132l,0x6751330966318410l,0x9819e8a37ddb795el,
-            0xfecb8ef5dad100b2l },
-          0 },
-        /* 34 << 56 */
-        { { 0x59f74a223021926al,0xb7c28a496f9b4c1cl,0xed1a733f912ad0abl,
-            0x42a910af01a5659cl },
-          { 0x3842c6e07bd68cabl,0x2b57fa3876d70ac8l,0x8a6707a83c53aaebl,
-            0x62c1c51065b4db18l },
-          0 },
-        /* 35 << 56 */
-        { { 0x8de2c1fbb2d09dc7l,0xc3dfed12266bd23bl,0x927d039bd5b27db6l,
-            0x2fb2f0f1103243dal },
-          { 0xf855a07b80be7399l,0xed9327ce1f9f27a8l,0xa0bd99c7729bdef7l,
-            0x2b67125e28250d88l },
-          0 },
-        /* 36 << 56 */
-        { { 0x784b26e88670ced7l,0xe3dfe41fc31bd3b4l,0x9e353a06bcc85cbcl,
-            0x302e290960178a9dl },
-          { 0x860abf11a6eac16el,0x76447000aa2b3aacl,0x46ff9d19850afdabl,
-            0x35bdd6a5fdb2d4c1l },
-          0 },
-        /* 37 << 56 */
-        { { 0xe82594b07e5c9ce9l,0x0f379e5320af346el,0x608b31e3bc65ad4al,
-            0x710c6b12267c4826l },
-          { 0x51c966f971954cf1l,0xb1cec7930d0aa215l,0x1f15598986bd23a8l,
-            0xae2ff99cf9452e86l },
-          0 },
-        /* 39 << 56 */
-        { { 0xb5a741a76b2515cfl,0x71c416019585c749l,0x78350d4fe683de97l,
-            0x31d6152463d0b5f5l },
-          { 0x7a0cc5e1fbce090bl,0xaac927edfbcb2a5bl,0xe920de4920d84c35l,
-            0x8c06a0b622b4de26l },
-          0 },
-        /* 40 << 56 */
-        { { 0xd34dd58bafe7ddf3l,0x55851fedc1e6e55bl,0xd1395616960696e7l,
-            0x940304b25f22705fl },
-          { 0x6f43f861b0a2a860l,0xcf1212820e7cc981l,0x121862120ab64a96l,
-            0x09215b9ab789383cl },
-          0 },
-        /* 41 << 56 */
-        { { 0x311eb30537387c09l,0xc5832fcef03ee760l,0x30358f5832f7ea19l,
-            0xe01d3c3491d53551l },
-          { 0x1ca5ee41da48ea80l,0x34e71e8ecf4fa4c1l,0x312abd257af1e1c7l,
-            0xe3afcdeb2153f4a5l },
-          0 },
-        /* 43 << 56 */
-        { { 0x2a17747fa6d74081l,0x60ea4c0555a26214l,0x53514bb41f88c5fel,
-            0xedd645677e83426cl },
-          { 0xd5d6cbec96460b25l,0xa12fd0ce68dc115el,0xc5bc3ed2697840eal,
-            0x969876a8a6331e31l },
-          0 },
-        /* 44 << 56 */
-        { { 0x60c36217472ff580l,0xf42297054ad41393l,0x4bd99ef0a03b8b92l,
-            0x501c7317c144f4f6l },
-          { 0x159009b318464945l,0x6d5e594c74c5c6bel,0x2d587011321a3660l,
-            0xd1e184b13898d022l },
-          0 },
-        /* 45 << 56 */
-        { { 0x5ba047524c6a7e04l,0x47fa1e2b45550b65l,0x9419daf048c0a9a5l,
-            0x663629537c243236l },
-          { 0xcd0744b15cb12a88l,0x561b6f9a2b646188l,0x599415a566c2c0c0l,
-            0xbe3f08590f83f09al },
-          0 },
-        /* 46 << 56 */
-        { { 0x9141c5beb92041b8l,0x01ae38c726477d0dl,0xca8b71f3d12c7a94l,
-            0xfab5b31f765c70dbl },
-          { 0x76ae7492487443e9l,0x8595a310990d1349l,0xf8dbeda87d460a37l,
-            0x7f7ad0821e45a38fl },
-          0 },
-        /* 47 << 56 */
-        { { 0xed1d4db61059705al,0xa3dd492ae6b9c697l,0x4b92ee3a6eb38bd5l,
-            0xbab2609d67cc0bb7l },
-          { 0x7fc4fe896e70ee82l,0xeff2c56e13e6b7e3l,0x9b18959e34d26fcal,
-            0x2517ab66889d6b45l },
-          0 },
-        /* 48 << 56 */
-        { { 0xf167b4e0bdefdd4fl,0x69958465f366e401l,0x5aa368aba73bbec0l,
-            0x121487097b240c21l },
-          { 0x378c323318969006l,0xcb4d73cee1fe53d1l,0x5f50a80e130c4361l,
-            0xd67f59517ef5212bl },
-          0 },
-        /* 49 << 56 */
-        { { 0xf145e21e9e70c72el,0xb2e52e295566d2fbl,0x44eaba4a032397f5l,
-            0x5e56937b7e31a7del },
-          { 0x68dcf517456c61e1l,0xbc2e954aa8b0a388l,0xe3552fa760a8b755l,
-            0x03442dae73ad0cdel },
-          0 },
-        /* 51 << 56 */
-        { { 0x3fcbdbce478e2135l,0x7547b5cfbda35342l,0xa97e81f18a677af6l,
-            0xc8c2bf8328817987l },
-          { 0xdf07eaaf45580985l,0xc68d1f05c93b45cbl,0x106aa2fec77b4cacl,
-            0x4c1d8afc04a7ae86l },
-          0 },
-        /* 52 << 56 */
-        { { 0xdb41c3fd9eb45ab2l,0x5b234b5bd4b22e74l,0xda253decf215958al,
-            0x67e0606ea04edfa0l },
-          { 0xabbbf070ef751b11l,0xf352f175f6f06dcel,0xdfc4b6af6839f6b4l,
-            0x53ddf9a89959848el },
-          0 },
-        /* 53 << 56 */
-        { { 0xda49c379c21520b0l,0x90864ff0dbd5d1b6l,0x2f055d235f49c7f7l,
-            0xe51e4e6aa796b2d8l },
-          { 0xc361a67f5c9dc340l,0x5ad53c37bca7c620l,0xda1d658832c756d0l,
-            0xad60d9118bb67e13l },
-          0 },
-        /* 55 << 56 */
-        { { 0xd1183316fd6f7140l,0xf9fadb5bbd8e81f7l,0x701d5e0c5a02d962l,
-            0xfdee4dbf1b601324l },
-          { 0xbed1740735d7620el,0x04e3c2c3f48c0012l,0x9ee29da73455449al,
-            0x562cdef491a836c4l },
-          0 },
-        /* 57 << 56 */
-        { { 0x147ebf01fad097a5l,0x49883ea8610e815dl,0xe44d60ba8a11de56l,
-            0xa970de6e827a7a6dl },
-          { 0x2be414245e17fc19l,0xd833c65701214057l,0x1375813b363e723fl,
-            0x6820bb88e6a52e9bl },
-          0 },
-        /* 59 << 56 */
-        { { 0xe1b6f60c08191224l,0xc4126ebbde4ec091l,0xe1dff4dc4ae38d84l,
-            0xde3f57db4f2ef985l },
-          { 0x34964337d446a1ddl,0x7bf217a0859e77f6l,0x8ff105278e1d13f5l,
-            0xa304ef0374eeae27l },
-          0 },
-        /* 60 << 56 */
-        { { 0xfc6f5e47d19dfa5al,0xdb007de37fad982bl,0x28205ad1613715f5l,
-            0x251e67297889529el },
-          { 0x727051841ae98e78l,0xf818537d271cac32l,0xc8a15b7eb7f410f5l,
-            0xc474356f81f62393l },
-          0 },
-        /* 61 << 56 */
-        { { 0x92dbdc5ac242316bl,0xabe060acdbf4aff5l,0x6e8c38fe909a8ec6l,
-            0x43e514e56116cb94l },
-          { 0x2078fa3807d784f9l,0x1161a880f4b5b357l,0x5283ce7913adea3dl,
-            0x0756c3e6cc6a910bl },
-          0 },
-        /* 63 << 56 */
-        { { 0xa573a4966d17fbc7l,0x0cd1a70a73d2b24el,0x34e2c5cab2676937l,
-            0xe7050b06bf669f21l },
-          { 0xfbe948b61ede9046l,0xa053005197662659l,0x58cbd4edf10124c5l,
-            0xde2646e4dd6c06c8l },
-          0 },
-        /* 64 << 56 */
-        { { 0x332f81088cad38c0l,0x471b7e906bd68ae2l,0x56ac3fb20d8e27a3l,
-            0xb54660db136b4b0dl },
-          { 0x123a1e11a6fd8de4l,0x44dbffeaa37799efl,0x4540b977ce6ac17cl,
-            0x495173a8af60acefl },
-          0 },
-        /* 65 << 56 */
-        { { 0xc48b1478db447d0bl,0xe1b85f5d46104fbbl,0x4ab31e7d991c60b9l,
-            0xaa674a9258a0cfd0l },
-          { 0x179fc2cd316f4297l,0x90c18642dcccbc82l,0x65d4309e56a4c163l,
-            0xf211a9c7145a33ecl },
-          0 },
-        /* 71 << 56 */
-        { { 0x9669170cdc32717fl,0x52d69b5138133e34l,0xaed24e5fb079c3b2l,
-            0xaba44a91a21ea3d2l },
-          { 0xd6814f1938d40105l,0x38289fe463462e7al,0x1793eefa3a80cbf5l,
-            0x05816a0795f29bacl },
-          0 },
-        /* 77 << 56 */
-        { { 0xdca88ad98f850641l,0x8c1152c447999b0dl,0x509f654e654aff33l,
-            0x2228550f08a12f14l },
-          { 0x60fe99dbb6a0ccdbl,0x80d6829bfc2cddccl,0x190f454dd5617aa4l,
-            0x0aea05fe36295d2dl },
-          0 },
-        /* 83 << 56 */
-        { { 0x1de06c8af9bef9a5l,0xe24d85d3fb2d3164l,0x3dbe455e8d203d3el,
-            0x439bee4735ea47a9l },
-          { 0xcc143432784893d7l,0x9b71073bd9bebd00l,0x6c106b343aa2fe88l,
-            0x9df2a42734746f7al },
-          0 },
-        /* 89 << 56 */
-        { { 0x1ad0b3725a8c2168l,0x64e52d6d143f0402l,0xd933c783e320f31fl,
-            0x1ccf90a80ff14f52l },
-          { 0xd3a3133ee1e6d0c0l,0xfd75a2d5b4acc8cal,0x62659b8e5559d171l,
-            0x5087d6e9f13ad52al },
-          0 },
-        /* 95 << 56 */
-        { { 0xb4d647a5deef31a4l,0x95bf4ab180975ea9l,0x2f92d15adf57b03el,
-            0x5ee808ab746b26d6l },
-          { 0x4341597c1082f261l,0x027795eb40c45e95l,0xcb77744b3b690c30l,
-            0xdd87c084af3f88d1l },
-          0 },
-        /* 101 << 56 */
-        { { 0x469f177572109785l,0xf365e55123f84d6cl,0x8006a9c28a046dbbl,
-            0x1b9fbe892fa09f52l },
-          { 0xac18a88016075e9el,0x4a3069bc1e3fd628l,0x20c61eaa60c61c14l,
-            0x315b59daf61f004bl },
-          0 },
-        /* 107 << 56 */
-        { { 0x0a94387f26d04857l,0x952a4ebc43d6de95l,0xb422e15cf14abdfal,
-            0x5b7a0153324ef90cl },
-          { 0x6aefa20e9826ec5bl,0x0e529886ad2fe161l,0xb710a74ec0d416e8l,
-            0x6cf4b0a5fb6c90bcl },
-          0 },
-        /* 113 << 56 */
-        { { 0x822aea4031979d3bl,0xb504eafde215a109l,0xa8761ead84bf2377l,
-            0xb55c1e55efb3d942l },
-          { 0xd01f9b0212b7f17bl,0x41b62c2a891bfbbfl,0x50800e6b08938149l,
-            0x527b50a9b0a55d82l },
-          0 },
-        /* 116 << 56 */
-        { { 0x6bc84d8d1d9ce3c4l,0x53b465072a308df0l,0x6c3da9bfca79c88al,
-            0x9636ad9c36372acfl },
-          { 0x8840e92c425ef14cl,0x863191f96af3225bl,0xd56d82d0d369b857l,
-            0x2053a2527a4c41f9l },
-          0 },
-        /* 119 << 56 */
-        { { 0x20aecd6609ca8805l,0x945d9b31dc818ee6l,0x1424647c2119b44bl,
-            0xbe934d7e5a6641f9l },
-          { 0xe91d53184559e55el,0xc2fb8e0b4dfbc3d4l,0x9e92e20676cb937fl,
-            0x0f5582e4f2932429l },
-          0 },
-        /* 125 << 56 */
-        { { 0xb5fc22a42d31809fl,0x6d582d2b0e35b7b4l,0x5fac415158c5f576l,
-            0xdff239371e4cd7c9l },
-          { 0x0f62b329ed4d1925l,0x00994a2e6010fb16l,0xb4b91076bd754837l,
-            0xfde219463345103al },
-          0 },
-    },
-    {
-        /* 0 << 64 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 64 */
-        { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl,
-            0x2f5e6961fd1b667fl },
-          { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l,
-            0xf648f9168d6f0f7bl },
-          0 },
-        /* 3 << 64 */
-        { { 0x4090914bb5def996l,0x1cb69c83233dd1e7l,0xc1e9c1d39b3d5e76l,
-            0x1f3338edfccf6012l },
-          { 0xb1e95d0d2f5378a8l,0xacf4c2c72f00cd21l,0x6e984240eb5fe290l,
-            0xd66c038d248088ael },
-          0 },
-        /* 4 << 64 */
-        { { 0x9ad5462bb4d8bc50l,0x181c0b16a9195770l,0xebd4fe1c78412a68l,
-            0xae0341bcc0dff48cl },
-          { 0xb6bc45cf7003e866l,0xf11a6dea8a24a41bl,0x5407151ad04c24c2l,
-            0x62c9d27dda5b7b68l },
-          0 },
-        /* 5 << 64 */
-        { { 0xd4992b30614c0900l,0xda98d121bd00c24bl,0x7f534dc87ec4bfa1l,
-            0x4a5ff67437dc34bcl },
-          { 0x68c196b81d7ea1d7l,0x38cf289380a6d208l,0xfd56cd09e3cbbd6el,
-            0xec72e27e4205a5b6l },
-          0 },
-        /* 7 << 64 */
-        { { 0xe8b97932b88756ddl,0xed4e8652f17e3e61l,0xc2dd14993ee1c4a4l,
-            0xc0aaee17597f8c0el },
-          { 0x15c4edb96c168af3l,0x6563c7bfb39ae875l,0xadfadb6f20adb436l,
-            0xad55e8c99a042ac0l },
-          0 },
-        /* 9 << 64 */
-        { { 0x65c29219909523c8l,0xa62f648fa3a1c741l,0x88598d4f60c9e55al,
-            0xbce9141b0e4f347al },
-          { 0x9af97d8435f9b988l,0x0210da62320475b6l,0x3c076e229191476cl,
-            0x7520dbd944fc7834l },
-          0 },
-        /* 10 << 64 */
-        { { 0x87a7ebd1e0a1b12al,0x1e4ef88d770ba95fl,0x8c33345cdc2ae9cbl,
-            0xcecf127601cc8403l },
-          { 0x687c012e1b39b80fl,0xfd90d0ad35c33ba4l,0xa3ef5a675c9661c2l,
-            0x368fc88ee017429el },
-          0 },
-        /* 11 << 64 */
-        { { 0x664300b07850ec06l,0xac5a38b97d3a10cfl,0x9233188de34ab39dl,
-            0xe77057e45072cbb9l },
-          { 0xbcf0c042b59e78dfl,0x4cfc91e81d97de52l,0x4661a26c3ee0ca4al,
-            0x5620a4c1fb8507bcl },
-          0 },
-        /* 13 << 64 */
-        { { 0x84b9ca1504b6c5a0l,0x35216f3918f0e3a3l,0x3ec2d2bcbd986c00l,
-            0x8bf546d9d19228fel },
-          { 0xd1c655a44cd623c3l,0x366ce718502b8e5al,0x2cfc84b4eea0bfe7l,
-            0xe01d5ceecf443e8el },
-          0 },
-        /* 15 << 64 */
-        { { 0xa75feacabe063f64l,0x9b392f43bce47a09l,0xd42415091ad07acal,
-            0x4b0c591b8d26cd0fl },
-          { 0x2d42ddfd92f1169al,0x63aeb1ac4cbf2392l,0x1de9e8770691a2afl,
-            0xebe79af7d98021dal },
-          0 },
-        /* 16 << 64 */
-        { { 0x58af2010f5b343bcl,0x0f2e400af2f142fel,0x3483bfdea85f4bdfl,
-            0xf0b1d09303bfeaa9l },
-          { 0x2ea01b95c7081603l,0xe943e4c93dba1097l,0x47be92adb438f3a6l,
-            0x00bb7742e5bf6636l },
-          0 },
-        /* 17 << 64 */
-        { { 0x66917ce63b5f1cc4l,0x37ae52eace872e62l,0xbb087b722905f244l,
-            0x120770861e6af74fl },
-          { 0x4b644e491058edeal,0x827510e3b638ca1dl,0x8cf2b7046038591cl,
-            0xffc8b47afe635063l },
-          0 },
-        /* 19 << 64 */
-        { { 0x7677408d6dfafed3l,0x33a0165339661588l,0x3c9c15ec0b726fa0l,
-            0x090cfd936c9b56dal },
-          { 0xe34f4baea3c40af5l,0x3469eadbd21129f1l,0xcc51674a1e207ce8l,
-            0x1e293b24c83b1ef9l },
-          0 },
-        /* 21 << 64 */
-        { { 0x796d3a85825808bdl,0x51dc3cb73fd6e902l,0x643c768a916219d1l,
-            0x36cd7685a2ad7d32l },
-          { 0xe3db9d05b22922a4l,0x6494c87edba29660l,0xf0ac91dfbcd2ebc7l,
-            0x4deb57a045107f8dl },
-          0 },
-        /* 23 << 64 */
-        { { 0xb6c69ac82094cec3l,0x9976fb88403b770cl,0x1dea026c4859590dl,
-            0xb6acbb468562d1fdl },
-          { 0x7cd6c46144569d85l,0xc3190a3697f0891dl,0xc6f5319548d5a17dl,
-            0x7d919966d749abc8l },
-          0 },
-        /* 25 << 64 */
-        { { 0xb53b7de561906373l,0x858dbadeeb999595l,0x8cbb47b2a59e5c36l,
-            0x660318b3dcf4e842l },
-          { 0xbd161ccd12ba4b7al,0xf399daabf8c8282al,0x1587633aeeb2130dl,
-            0xa465311ada38dd7dl },
-          0 },
-        /* 27 << 64 */
-        { { 0x2dae9082be7cf3a6l,0xcc86ba92bc967274l,0xf28a2ce8aea0a8a9l,
-            0x404ca6d96ee988b3l },
-          { 0xfd7e9c5d005921b8l,0xf56297f144e79bf9l,0xa163b4600d75ddc2l,
-            0x30b23616a1f2be87l },
-          0 },
-        /* 28 << 64 */
-        { { 0x19e6125dec3f1decl,0x07b1f040911178dal,0xd93ededa904a6738l,
-            0x55187a5a0bebedcdl },
-          { 0xf7d04722eb329d41l,0xf449099ef170b391l,0xfd317a69ca99f828l,
-            0x50c3db2b34a4976dl },
-          0 },
-        /* 29 << 64 */
-        { { 0x0064d8585499fb32l,0x7b67bad977a8aeb7l,0x1d3eb9772d08eec5l,
-            0x5fc047a6cbabae1dl },
-          { 0x0577d159e54a64bbl,0x8862201bc43497e4l,0xad6b4e282ce0608dl,
-            0x8b687b7d0b167aacl },
-          0 },
-        /* 31 << 64 */
-        { { 0xe9f9669cda94951el,0x4b6af58d66b8d418l,0xfa32107417d426a4l,
-            0xc78e66a99dde6027l },
-          { 0x0516c0834a53b964l,0xfc659d38ff602330l,0x0ab55e5c58c5c897l,
-            0x985099b2838bc5dfl },
-          0 },
-        /* 33 << 64 */
-        { { 0xe7a935fa1684cb3bl,0x571650b5a7d7e69dl,0x6ba9ffa40328c168l,
-            0xac43f6bc7e46f358l },
-          { 0x54f75e567cb6a779l,0x4e4e2cc8c61320del,0xb94258bc2b8903d0l,
-            0xc7f32d57ceecabe0l },
-          0 },
-        /* 34 << 64 */
-        { { 0x34739f16cd7d9d89l,0x6daab4267ca080b5l,0x772086ff40e19f45l,
-            0x43caa56118c61b42l },
-          { 0x0ba3d4a8dbf365f1l,0xa0db435ee760ad97l,0xfd6f30d56916c59bl,
-            0xab34cb5dafe12f5dl },
-          0 },
-        /* 35 << 64 */
-        { { 0x445b86ea02a3260al,0x8c51d6428d689babl,0x183334d65588904cl,
-            0xf8a3b84d479d6422l },
-          { 0x581acfa0f0833d00l,0xc50827bc3b567d2dl,0x2c935e6daddcf73el,
-            0x2a645f7704dd19f2l },
-          0 },
-        /* 36 << 64 */
-        { { 0x78d2e8dfcb564473l,0x4349a97357d5621al,0x9d835d89218f8b24l,
-            0x01fe7bc5079b6ee2l },
-          { 0xe57f2a2b5b3b5dcel,0x5a8637b75fe55565l,0x83ff34aea41dbae7l,
-            0xfce1199c950a7a8fl },
-          0 },
-        /* 37 << 64 */
-        { { 0x0ca5d25bf8e71ce2l,0x204edc4a062685dal,0x06fe407d87678ec2l,
-            0xd16936a07defa39al },
-          { 0x3b108d84af3d16d0l,0xf2e9616d0305cad0l,0xbc9537e6f27bed97l,
-            0x71c2d699ebc9f45cl },
-          0 },
-        /* 39 << 64 */
-        { { 0x203bdd84cdcd3a85l,0x1107b901ade3ccfal,0xa7da89e95533159dl,
-            0x8d834005860e8c64l },
-          { 0x914bc0eb2a7638f7l,0xc66ce0a6620e8606l,0x11ef98c2e6c12dc0l,
-            0x25666b1d7780fc0el },
-          0 },
-        /* 40 << 64 */
-        { { 0x374f541f3e707706l,0x9a4d3638a831d0cfl,0x4ab4f4831518ca04l,
-            0x54e3ee5dfe38c318l },
-          { 0x383ae36403c8819bl,0xa9d1daa12e17864cl,0x245a97b350eeaa5bl,
-            0x5362d00999bf4e83l },
-          0 },
-        /* 41 << 64 */
-        { { 0x6667e89f4ded8a4fl,0xa59161abc36a7795l,0x1c96f6f9331ccf94l,
-            0xf2727e879a686d49l },
-          { 0x0f94894bb841295fl,0xb0fe8f744a0503d1l,0x60c581c7ef407926l,
-            0x1980c8e13edb7e1cl },
-          0 },
-        /* 43 << 64 */
-        { { 0x47948c84c5de1a41l,0xd595d14a48959688l,0x3bfca4be86ff21c9l,
-            0xb5ff59b86a4191cal },
-          { 0xced1dd1d65094c86l,0xd57b86559dc9d001l,0xbcac6fa3486e51d7l,
-            0x8e97e2637b774c1bl },
-          0 },
-        /* 44 << 64 */
-        { { 0xfc0313c29bd43980l,0x9c954b70f172db29l,0x679bdcb7f954a21al,
-            0x6b48170954e2e4fcl },
-          { 0x318af5f530baf1d0l,0x26ea8a3ccbf92060l,0xc3c69d7ccd5ae258l,
-            0xa73ba0470ead07c9l },
-          0 },
-        /* 45 << 64 */
-        { { 0xe82eb003e35dca85l,0xfd0000fa31e39180l,0xbca90f746735f378l,
-            0xe6aa783158c943edl },
-          { 0x0e94ecd5b6a438d7l,0xc02b60faf9a5f114l,0x4063568b8b1611ebl,
-            0x1398bdc1272509ecl },
-          0 },
-        /* 46 << 64 */
-        { { 0xc2ef6a01be3e92d1l,0x1bce9c27282bd5ddl,0xf7e488f3adda0568l,
-            0xd4f15fdb1af9bb8bl },
-          { 0x8c490ade4da846efl,0x76229da17f0b825el,0xc8b812082a6711c6l,
-            0x511f5e23b4c523aal },
-          0 },
-        /* 47 << 64 */
-        { { 0xbdf4e7049970f46el,0x70e220288dadbd1al,0x2b86c97fb1223d26l,
-            0x042ad22ecf62f51al },
-          { 0x72944339ba2ed2e9l,0x0ba0d10ef94fa61dl,0x3f86164194e68f15l,
-            0x1312a74acb86c545l },
-          0 },
-        /* 48 << 64 */
-        { { 0x3a63c39731815e69l,0x6df9cbd6dcdd2802l,0x4c47ed4a15b4f6afl,
-            0x62009d826ac0f978l },
-          { 0x664d80d28b898fc7l,0x72f1eeda2c17c91fl,0x9e84d3bc7aae6609l,
-            0x58c7c19528376895l },
-          0 },
-        /* 49 << 64 */
-        { { 0x640ebf5d5b8d354al,0xa5f3a8fdb396ff64l,0xd53f041d8378ed81l,
-            0x1969d61bc1234ad2l },
-          { 0x16d7acffeb68bde2l,0x63767a68f23e9368l,0x937a533c38928d95l,
-            0xee2190bbbeb0f1f2l },
-          0 },
-        /* 51 << 64 */
-        { { 0xb6860c9a73a4aafbl,0xb2f996290488870dl,0x16ef6232572d9e25l,
-            0x5b9eb1bad1383389l },
-          { 0xabf713a7ed8d77f8l,0xd2b4a2e9e2b69e64l,0xa1a22cfd6d6f17c2l,
-            0x4bfd6f992d604511l },
-          0 },
-        /* 52 << 64 */
-        { { 0xdcff7630d9294f07l,0x89b765d68dba8fd0l,0x553e55de8dbcaccdl,
-            0x9b4a009eed702bf8l },
-          { 0xf6e534dd27b8ca0dl,0xc4496b346177fd52l,0x378ce6f6c87bb7b7l,
-            0x68633d4844cc19f0l },
-          0 },
-        /* 53 << 64 */
-        { { 0xfe550021bc84c625l,0x8d7169986d45e4a3l,0xa09c6ded4c0c66b7l,
-            0xe32313aeb9e1d547l },
-          { 0x8ce775b4d1e8e0b9l,0xa899f9102654dd15l,0x7c38aa066cc8b2a9l,
-            0xe6ebb291d6ce6cc0l },
-          0 },
-        /* 55 << 64 */
-        { { 0x5963df62a6991216l,0x4c17f72246996010l,0x131dc2b840477722l,
-            0x78bf50b0d1765a75l },
-          { 0x360afd587ceaca12l,0xebc55dbb139cd470l,0x9083e27e4c05541cl,
-            0xc10057a3b873d757l },
-          0 },
-        /* 57 << 64 */
-        { { 0x440009c3deed7769l,0xde2fa58a14fd8a44l,0x509e7df35b627596l,
-            0x3d76a87cc3bb07a7l },
-          { 0x8018fee5b8ef000al,0x71ce33e9823fd4b6l,0x3a1cac37469c0bb1l,
-            0x92fe7aeaf3eec8eel },
-          0 },
-        /* 59 << 64 */
-        { { 0x37ad0eb8de64e568l,0x4ac669bca1e3e20el,0x240d0ac22ce944edl,
-            0xd532039a3c1b28fbl },
-          { 0xa2bb899a23acba6cl,0xd472af671af937e1l,0x04478f7b8851e753l,
-            0x74030eef5ea05307l },
-          0 },
-        /* 60 << 64 */
-        { { 0x3559e7b67dc17874l,0xd0caf0ef8195cc2al,0x07c067880cd24dd9l,
-            0x01a99ea002857c41l },
-          { 0xd86579e490f82f63l,0xb1e0658ae41c9237l,0x075ffafd93fd1e79l,
-            0x6e70403547f60b8fl },
-          0 },
-        /* 61 << 64 */
-        { { 0x2246ad76c1d68c31l,0x9126202b0d5c4677l,0x5f40de81638882dcl,
-            0xb131988ca3253a7fl },
-          { 0x766f1897ba9ae0a8l,0xf0e01dd41d8b5fefl,0x03e28ce3ed7b12c8l,
-            0x44b3a2be1fd20e1el },
-          0 },
-        /* 63 << 64 */
-        { { 0xd4c8e8e5f2a5f247l,0x42ffd816c2c7c979l,0x89e1485211093d1al,
-            0x98f44a4613871ebbl },
-          { 0x374849964b032e2dl,0x28a430f445995a61l,0xf2f9acbad5be16b6l,
-            0xac98a5402d8e02aal },
-          0 },
-        /* 64 << 64 */
-        { { 0x0d53f5c7a3e6fcedl,0xe8cbbdd5f45fbdebl,0xf85c01df13339a70l,
-            0x0ff71880142ceb81l },
-          { 0x4c4e8774bd70437al,0x5fb32891ba0bda6al,0x1cdbebd2f18bd26el,
-            0x2f9526f103a9d522l },
-          0 },
-        /* 65 << 64 */
-        { { 0x48334fdcc20b8d30l,0x25f887d749414fddl,0x9ccd513311a2cf0dl,
-            0x7e7799e4d08975a4l },
-          { 0xb5993a53729b951cl,0x0cf14a5a62dbc6a8l,0xb39ed36efe4d16eel,
-            0xb75f3fb681bda63al },
-          0 },
-        /* 71 << 64 */
-        { { 0xac7db8706d4f68b5l,0x819a13c7be49b3a4l,0x646ae2b1418bf1e9l,
-            0x25b53a5f69b3a5ccl },
-          { 0xd23d94d37de26578l,0x8bb581caecdd138al,0x9e053f67f857b0dal,
-            0xe679cc7a255ff474l },
-          0 },
-        /* 77 << 64 */
-        { { 0x4a4b8d990df097f9l,0x0ae1227a0b4173cal,0x0d401778adb72178l,
-            0xd29848b43f421e0cl },
-          { 0xc5eec6096eb0722dl,0x527d72877e12c028l,0xed12a9e71b5dcc0cl,
-            0x26b27344dcf4b4dal },
-          0 },
-        /* 83 << 64 */
-        { { 0x695c502565e4408al,0x2d23768fcbce94e6l,0x1505fa1e5080b88dl,
-            0x5c8fbab6855f7cc1l },
-          { 0x70d876f275fb125dl,0x456421330a252007l,0xfe99249a8ee05be1l,
-            0x0893b620f4bf5490l },
-          0 },
-        /* 89 << 64 */
-        { { 0x2a59df1ed9fe6bdfl,0x96a9c791785e057fl,0x4b0d795f86a1d751l,
-            0x196c8e0aec642886l },
-          { 0x6df67899bc0e055cl,0x4173204a63007433l,0xb5ee4efec21c9245l,
-            0x2f7d4c75c1451bael },
-          0 },
-        /* 95 << 64 */
-        { { 0x2ad7f836b1047b7fl,0x368d431a71f6bfe1l,0xfcd933b103db4667l,
-            0xfff77ed3ecb81330l },
-          { 0x3677935b44958bd4l,0xa6cfcda8a1d5a9e7l,0xb2b73bc699ff9fael,
-            0x1c2cd628f866d3c4l },
-          0 },
-        /* 101 << 64 */
-        { { 0x2756873495031ceel,0xebed373d51091c1bl,0x398fef0819aa2f27l,
-            0x2f26174e2c0a9feal },
-          { 0xedca72b6b219be3fl,0x001a8fdc80503df8l,0x9a2fadbb6b93f643l,
-            0xd48e552cd44cebc3l },
-          0 },
-        /* 107 << 64 */
-        { { 0x6c0dbb68667a7ab6l,0x00490ce757630e91l,0x04976cd57eb2f382l,
-            0x9ee486b655dda4a3l },
-          { 0x4ea5c9c9cca0d01cl,0xa6e054b639f69c6dl,0xb3b7ac992ecab239l,
-            0x80c9f6d17597512el },
-          0 },
-        /* 113 << 64 */
-        { { 0x64dfdd68b942fad9l,0xe7d8e88da5eb3d14l,0xb7281dc2382f6301l,
-            0xcfa2ee6dbfe00a7fl },
-          { 0x6e617657dc7be39fl,0x22d58dd6591c6e3al,0xd3a4003918318c13l,
-            0xcac6c830981b6b72l },
-          0 },
-        /* 116 << 64 */
-        { { 0x009690ffb4fbfaa0l,0x8bbbdab73619c6dbl,0xc6d44273728356e8l,
-            0xfd76f0d8e453ec35l },
-          { 0x775c2554aac28a29l,0x28f7af9d5c55e4f0l,0xbacf54a688e8ad4dl,
-            0x85b018e80aa76ddfl },
-          0 },
-        /* 119 << 64 */
-        { { 0x27893f7983ce88e4l,0x9556c9977785f13dl,0x83d3c38d3a35831el,
-            0x3856c829d12f0a1dl },
-          { 0xb308d84c93259c1al,0x4ef87ab4691ffd28l,0x76a18d5321a88c58l,
-            0xf13cd5d53503cb4dl },
-          0 },
-        /* 125 << 64 */
-        { { 0x669d93dba8cc0db3l,0x403cb9200dfcfcf4l,0x5def4a03e77c3979l,
-            0x2a05c9423e2e2522l },
-          { 0xd86dca52b5f48bf0l,0x174766de5828a135l,0x116290b40d3a96d0l,
-            0xe1999457aeea1193l },
-          0 },
-    },
-    {
-        /* 0 << 72 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 72 */
-        { { 0x0db2fb5ed005832al,0x5f5efd3b91042e4fl,0x8c4ffdc6ed70f8cal,
-            0xe4645d0bb52da9ccl },
-          { 0x9596f58bc9001d1fl,0x52c8f0bc4e117205l,0xfd4aa0d2e398a084l,
-            0x815bfe3a104f49del },
-          0 },
-        /* 3 << 72 */
-        { { 0x524d226ad7ab9a2dl,0x9c00090d7dfae958l,0x0ba5f5398751d8c2l,
-            0x8afcbcdd3ab8262dl },
-          { 0x57392729e99d043bl,0xef51263baebc943al,0x9feace9320862935l,
-            0x639efc03b06c817bl },
-          0 },
-        /* 4 << 72 */
-        { { 0xe839be7d341d81dcl,0xcddb688932148379l,0xda6211a1f7026eadl,
-            0xf3b2575ff4d1cc5el },
-          { 0x40cfc8f6a7a73ae6l,0x83879a5e61d5b483l,0xc5acb1ed41a50ebcl,
-            0x59a60cc83c07d8fal },
-          0 },
-        /* 5 << 72 */
-        { { 0xdec98d4ac3b81990l,0x1cb837229e0cc8fel,0xfe0b0491d2b427b9l,
-            0x0f2386ace983a66cl },
-          { 0x930c4d1eb3291213l,0xa2f82b2e59a62ae4l,0x77233853f93e89e3l,
-            0x7f8063ac11777c7fl },
-          0 },
-        /* 7 << 72 */
-        { { 0x36e607cf02ff6072l,0xa47d2ca98ad98cdcl,0xbf471d1ef5f56609l,
-            0xbcf86623f264ada0l },
-          { 0xb70c0687aa9e5cb6l,0xc98124f217401c6cl,0x8189635fd4a61435l,
-            0xd28fb8afa9d98ea6l },
-          0 },
-        /* 9 << 72 */
-        { { 0x3d4da8c3017025f3l,0xefcf628cfb9579b4l,0x5c4d00161f3716ecl,
-            0x9c27ebc46801116el },
-          { 0x5eba0ea11da1767el,0xfe15145247004c57l,0x3ace6df68c2373b7l,
-            0x75c3dffe5dbc37acl },
-          0 },
-        /* 10 << 72 */
-        { { 0xa2a147dba28a0749l,0x246c20d6ee519165l,0x5068d1b1d3810715l,
-            0xb1e7018c748160b9l },
-          { 0x03f5b1faf380ff62l,0xef7fb1ddf3cb2c1el,0xeab539a8fc91a7dal,
-            0x83ddb707f3f9b561l },
-          0 },
-        /* 11 << 72 */
-        { { 0xb57276d980101b98l,0x760883fdb82f0f66l,0x89d7de754bc3eff3l,
-            0x03b606435dc2ab40l },
-          { 0xcd6e53dfe05beeacl,0xf2f1e862bc3325cdl,0xdd0f7921774f03c3l,
-            0x97ca72214552cc1bl },
-          0 },
-        /* 13 << 72 */
-        { { 0x760cb3b5e224c5d7l,0xfa3baf8c68616919l,0x9fbca1138d142552l,
-            0x1ab18bf17669ebf5l },
-          { 0x55e6f53e9bdf25ddl,0x04cc0bf3cb6cd154l,0x595bef4995e89080l,
-            0xfe9459a8104a9ac1l },
-          0 },
-        /* 15 << 72 */
-        { { 0x694b64c5abb020e8l,0x3d18c18419c4eec7l,0x9c4673ef1c4793e5l,
-            0xc7b8aeb5056092e6l },
-          { 0x3aa1ca43f0f8c16bl,0x224ed5ecd679b2f6l,0x0d56eeaf55a205c9l,
-            0xbfe115ba4b8e028bl },
-          0 },
-        /* 16 << 72 */
-        { { 0x3e22a7b397acf4ecl,0x0426c4005ea8b640l,0x5e3295a64e969285l,
-            0x22aabc59a6a45670l },
-          { 0xb929714c5f5942bcl,0x9a6168bdfa3182edl,0x2216a665104152bal,
-            0x46908d03b6926368l },
-          0 },
-        /* 17 << 72 */
-        { { 0x9b8be0247fcba850l,0x81eb5797820a181el,0xa0f2812230a01211l,
-            0x7e9cdc3cae7b8821l },
-          { 0x202332cc72ce15e7l,0xcd3cb2bbcb8238d7l,0xe4ab63dfc6e82c43l,
-            0x58bd00283183d717l },
-          0 },
-        /* 19 << 72 */
-        { { 0x02d57b7e717ed7b5l,0xd22e5b244dbce1a2l,0x174bd7712a4cdcf5l,
-            0xa6fdb801408205bbl },
-          { 0x67b4b0695e1387e9l,0x332b19a10591a442l,0x24edd916ccacf366l,
-            0xbe34cc4534958a50l },
-          0 },
-        /* 21 << 72 */
-        { { 0xa3f46e1e3e66d391l,0xb4a732cd7d6369b2l,0x99c3b85d402c1022l,
-            0x7dccfcbe2b54932el },
-          { 0xa6ddaa7b56b1dfe2l,0x31dc78a5e34a82c9l,0x8abeb3da704f3941l,
-            0xdf11a36cca55fa98l },
-          0 },
-        /* 23 << 72 */
-        { { 0x6c01f77a16e00c1bl,0x82515490839eaaacl,0x62f3a4ef3470d334l,
-            0x5a29a6491c1dcd6cl },
-          { 0x46b6782ece997a25l,0x9978fb35d3579953l,0x98f5a9df0960e0cel,
-            0x547dc8391f527a4cl },
-          0 },
-        /* 25 << 72 */
-        { { 0x395b15835d9dc24fl,0xa4256932c73ae680l,0x0542960efaa2c8e9l,
-            0x2bb3adee71068c6al },
-          { 0xa706099b570b4554l,0x85d12bb5f4e278d6l,0xd78af6f664296843l,
-            0xc7d3b3888428c633l },
-          0 },
-        /* 27 << 72 */
-        { { 0x34d44f9343b7e597l,0xdde440a7c2530f42l,0x7270a0817856bdb9l,
-            0x86a945eb5353032fl },
-          { 0x6c2f8e9966d39810l,0x0642a31b9b8b4b6bl,0x51679e62d1509d82l,
-            0x0120001c90f8ff16l },
-          0 },
-        /* 28 << 72 */
-        { { 0x50a1c1062e36e34al,0x74e8f58ce024ed1al,0x3f0f1dfa1300d726l,
-            0x6680df267b4a2d18l },
-          { 0x12b5979d8235b3b7l,0x1d2fafcb8a611493l,0x73ebda968848ece5l,
-            0xe996c275a413e399l },
-          0 },
-        /* 29 << 72 */
-        { { 0x46b7d7c7495ff000l,0xe60ed097baed95d1l,0xaa8804ac6e38f9c0l,
-            0x92990c0645c6f9bbl },
-          { 0xcae6a439c0919851l,0x713dff151bf5e1f2l,0x5d262c302eb38cdbl,
-            0xb73d505190df31dfl },
-          0 },
-        /* 31 << 72 */
-        { { 0x921e7b1c32d9268cl,0x34db2b964276fad4l,0x0ec56d34cc44e730l,
-            0x59be3a46096545b7l },
-          { 0xe9fdbc9766cf3a6al,0x7b2f83edd04e9b53l,0x6d99b3cc8fbae3e7l,
-            0x8eb5646c7ada3a40l },
-          0 },
-        /* 33 << 72 */
-        { { 0xa69ab906fc3302bfl,0x49ae6ba7d0872e90l,0xc9e2d6d1f3a1bfc3l,
-            0x11dfe85f1a033500l },
-          { 0x45189c2998666dbdl,0xba6aab88bbfd13cel,0xcf9c8b43dbd38cd4l,
-            0xa0cb581b68009236l },
-          0 },
-        /* 34 << 72 */
-        { { 0xff18c42a16288a7al,0x6363ace430699163l,0x8546d6332a2ce353l,
-            0x5e0379ef7b6b3418l },
-          { 0x2df2bb463e941bb2l,0xae7c091888e1aacel,0x6bc0982d83f5a37al,
-            0x8521bd02676d09e0l },
-          0 },
-        /* 35 << 72 */
-        { { 0x6531dff33d361aacl,0x59b954477c8cac2el,0xcc104df6c5cb7363l,
-            0x68b571c519364acdl },
-          { 0x7521e962979c3bc0l,0xbe0544c9c4aa1f92l,0x59127fe92a31eabbl,
-            0x760ac28593d8b55bl },
-          0 },
-        /* 36 << 72 */
-        { { 0x62ed534c6115164bl,0xaebe9e4cdce84ceal,0xd81c91a1c83f64c3l,
-            0x325a8ca8ecacd09al },
-          { 0x7ea57ad968b45df1l,0xa555636fd530c5d2l,0x23aff510591cfe32l,
-            0x46ff147637bedab9l },
-          0 },
-        /* 37 << 72 */
-        { { 0xa5a7e81ecb2edb3bl,0x9b0dc5f4f8fbe238l,0xc6f258087c66dd34l,
-            0xb4a57503a3f8f38al },
-          { 0x195b433513571b5bl,0xa32840763ccbc30bl,0x64ae1ffccf99ddd5l,
-            0x0dfc8772aa844e76l },
-          0 },
-        /* 39 << 72 */
-        { { 0x8b471afbfb22341dl,0xbf448b43397afdd2l,0x4cb08409682c37edl,
-            0xc3acfae6a948f1f6l },
-          { 0xf58462549e634707l,0x50161a78bd949f52l,0xf0529e752fe73566l,
-            0xe7e3fdef6fda53e0l },
-          0 },
-        /* 40 << 72 */
-        { { 0x56dab1c8321a518cl,0xfd4439a68bce226fl,0xe0b30d194facb9fal,
-            0xb5052f307583571bl },
-          { 0x1442641012afd476l,0xd02e417203fe624al,0xfc394f65531c92e6l,
-            0x16d4bf5ad4bc0b52l },
-          0 },
-        /* 41 << 72 */
-        { { 0xa38ac25eb4ec4f0fl,0x5399c024de72b27dl,0x08318aafd81a3d65l,
-            0x1af227a70c20e5d9l },
-          { 0x6389cc9a26c54e25l,0x438298bba47dc27fl,0x75386cca1a63fa0el,
-            0xc941e84cdf7bc1b0l },
-          0 },
-        /* 43 << 72 */
-        { { 0x81cad748fdfe3faal,0x752107b453ff1988l,0x8d8bb7001a8fd829l,
-            0x69838e15ca821d8el },
-          { 0x24371ede3b9f6b34l,0x19b4bb24d91e1495l,0x90899ca1e598ded1l,
-            0xbbb78b167c14e9e3l },
-          0 },
-        /* 44 << 72 */
-        { { 0xa577e84cbef239aal,0x656d2b6f8904b4d4l,0x2f6defe6ca4007edl,
-            0xca6e517737770796l },
-          { 0x4c62fcba298b6448l,0x046849660f62e00dl,0x806c2f0390b07d82l,
-            0x730855795e8d1e60l },
-          0 },
-        /* 45 << 72 */
-        { { 0x24488802f4703b78l,0x6c9323bee9eaa1e0l,0x242990e2aa94c170l,
-            0x3292bc42a15b5886l },
-          { 0x60ccb5bc908af203l,0x8fd63583713b09bdl,0x40791ecad693fa28l,
-            0xea80abf2941af8a1l },
-          0 },
-        /* 46 << 72 */
-        { { 0xf9c0315071145fe3l,0x80a71b55d7873a7dl,0xd134244b5e10bac7l,
-            0x303f7e12ded3a4b4l },
-          { 0x58e6f17e803b7a3bl,0xcd6f64130b1ca6b4l,0x25e744ce2ce65aa2l,
-            0xf2bbc66b952efa51l },
-          0 },
-        /* 47 << 72 */
-        { { 0xc8b212e75913e1f3l,0xf018ab208d416886l,0x28249e15b617cac4l,
-            0x837fcba1693ed09al },
-          { 0x9c457e511c15a1bcl,0x9354758756c7f3f1l,0x1afd80348be18306l,
-            0xa43d56982256ab14l },
-          0 },
-        /* 48 << 72 */
-        { { 0xce06b88210395755l,0x117ce6345ec1df80l,0xfefae513eff55e96l,
-            0xcf36cba6fd7fed1el },
-          { 0x7340eca9a40ebf88l,0xe6ec1bcfb3d37e12l,0xca51b64e86bbf9ffl,
-            0x4e0dbb588b40e05el },
-          0 },
-        /* 49 << 72 */
-        { { 0xf9c063f62f2be34bl,0x9ca32fa99c20f16bl,0xe02e350d0125a01al,
-            0x62d66c54e6516c25l },
-          { 0x21b154ad5120bedbl,0xb1077f4e8d6ff9d8l,0xd01a46c300bb4941l,
-            0x9d381847d1460588l },
-          0 },
-        /* 51 << 72 */
-        { { 0xf3a9b311581cb57bl,0x65fb3fb649727d13l,0xb8496e3d35131142l,
-            0xf7642f554d0cdab9l },
-          { 0xe2f66f0e9f6d7e45l,0xbae14cedaa22fcd4l,0x1f769f0e49b2e05al,
-            0x08c4d7784ac5191el },
-          0 },
-        /* 52 << 72 */
-        { { 0x86f9108ece4aa825l,0xbe5b2f317e5a5fbfl,0x2772c1b49254bb78l,
-            0xae6cdf5f4ff8ac5cl },
-          { 0x106cd94bf6b7a12el,0xbe0915d6d1c7a1a5l,0x8bf6bc8d3b40ac5el,
-            0xbb89180423ee3acal },
-          0 },
-        /* 53 << 72 */
-        { { 0x76f15eaa618b5ea1l,0xec1ea62e6d4ad0c8l,0x301b60c8168d57fal,
-            0x454d5f771edbfb05l },
-          { 0xea888e29a936031al,0x01303d3f0174dd17l,0x8b5e06b4244254e7l,
-            0x00ebf03509724acfl },
-          0 },
-        /* 55 << 72 */
-        { { 0x66ce3ded8e66d509l,0x368e38d05a488586l,0x7b9ae220c7eedf5el,
-            0x67e9ea52bfbf9d62l },
-          { 0xe9cbf53d99b7ecb3l,0xfde3e8c0908bf072l,0x288400ab1107e21fl,
-            0x24c8856256532667l },
-          0 },
-        /* 57 << 72 */
-        { { 0x0d5f9955ca9d3ad1l,0x545feba13a1daec0l,0xd22972016cb30f23l,
-            0x9660175ccef6cf6el },
-          { 0xbf3e341a395738dcl,0x74a5efbc80f7cca4l,0xc4f9a07bbebc6a60l,
-            0x2f1e3dad4b1f915al },
-          0 },
-        /* 59 << 72 */
-        { { 0xada4423f0d5e2e34l,0x2d31f4920b372358l,0xd7f469370e2d6a8cl,
-            0xf5e7ccfe0028e4ael },
-          { 0x20fcb1f3928854b2l,0x2a8973c507271bf6l,0xe87de33e5fa88fe1l,
-            0xe9af2dce7bd3c2a6l },
-          0 },
-        /* 60 << 72 */
-        { { 0x185a19d959d097b2l,0xb1c72a3a0dea2875l,0x3b371628f9021f08l,
-            0x45f1255bfa9d6ac1l },
-          { 0x9ff36a90cfd72c0dl,0x8c7315db24fe2376l,0x9aebcde04b34d42cl,
-            0x2129ab16923025f3l },
-          0 },
-        /* 61 << 72 */
-        { { 0x341b9dd714b4cf50l,0x7c6e4634d619d00el,0x571d6e2fdf2165ael,
-            0xdedf9cd18dbe9db5l },
-          { 0x52a152777c5f3dc3l,0x7d27c97ef2901cf7l,0x5e098b54d02a85dfl,
-            0x6fce3e13088e3640l },
-          0 },
-        /* 63 << 72 */
-        { { 0xfa95be147a939904l,0xdfcf5b9bb56365ccl,0xdbb546bdd2d66922l,
-            0xf26a8b9cda03ca7fl },
-          { 0x96a8042d16821c0cl,0xe6729970e88ede60l,0xd028130d1285e303l,
-            0x1678b01688b7de75l },
-          0 },
-        /* 64 << 72 */
-        { { 0x96649933aed1d1f7l,0x566eaff350563090l,0x345057f0ad2e39cfl,
-            0x148ff65b1f832124l },
-          { 0x042e89d4cf94cf0dl,0x319bec84520c58b3l,0x2a2676265361aa0dl,
-            0xc86fa3028fbc87adl },
-          0 },
-        /* 65 << 72 */
-        { { 0x5db4884124627d04l,0xf92740766f7e3febl,0xd09eb11773496240l,
-            0xd48e51419a6b9ec9l },
-          { 0xcbb2ac97b7336e27l,0xe794fb760640bf6cl,0xc0b7f78dc7c7fa3fl,
-            0x1355d071fd2edbb9l },
-          0 },
-        /* 71 << 72 */
-        { { 0x575d9724e84e25a3l,0x068690a13d4d8708l,0x8a7b1c6c54dd62d0l,
-            0x8c45e1b37f88e231l },
-          { 0x38c665466d85afe2l,0x65231642e1d69f1bl,0xb71c53a090687ec1l,
-            0xdf8469d777fb5981l },
-          0 },
-        /* 77 << 72 */
-        { { 0xb920b503144fe6bcl,0x54b0f0593914c130l,0x63188d5a8269b650l,
-            0x8d7780962fc7064dl },
-          { 0xbf7b0eec5e50839al,0xaf8a7ddbe242cd06l,0x93df850809cecdb9l,
-            0x4db58a72410659e9l },
-          0 },
-        /* 83 << 72 */
-        { { 0x460d9b383baba3cdl,0x52386e4d2cf860b8l,0xd224fe5da3924b9al,
-            0xe4a4be7bcf14d813l },
-          { 0xb0759e82ed3774fdl,0x57c064b38d9b6c59l,0x301ab902aee183d0l,
-            0xf1c873495ba207c3l },
-          0 },
-        /* 89 << 72 */
-        { { 0xe8245b0a6dd58696l,0x0714eedb61091043l,0x7d9874459101129bl,
-            0x4a7f1f03a0b27a21l },
-          { 0x282e5cff71ee2045l,0x25c694a3da5c6b41l,0xb3d8e21f5542ca55l,
-            0x57d64170e3601af0l },
-          0 },
-        /* 95 << 72 */
-        { { 0x9c8e86c6c6c4fee6l,0x70194db5a596119bl,0xfc6271d30e06050cl,
-            0x17d94c89b15f18d2l },
-          { 0x76c9e9bd49817224l,0x42621638b989c5bcl,0x1e9c4cbeb769d70cl,
-            0x85e227c3b87f2783l },
-          0 },
-        /* 101 << 72 */
-        { { 0x146185d2117e73c5l,0xbf6214696dc38116l,0x9af9d9b5459e72cbl,
-            0x7512882fb3930b85l },
-          { 0xfe935379d36583b8l,0xb83ad35e7c7fdcdel,0x093ca0ab2658ae4bl,
-            0xc9b16d60a756681bl },
-          0 },
-        /* 107 << 72 */
-        { { 0x12c24d9195d3519bl,0x1fc6db1bdb43fd06l,0x1ae49fed25bbde51l,
-            0x27072e0b76d2827bl },
-          { 0xdcb92e05aeb8c47fl,0x601d414056145f67l,0xcb7002652a39e8f7l,
-            0x6ce9facc35620d8cl },
-          0 },
-        /* 113 << 72 */
-        { { 0x5c428a5ebd702c22l,0xcb6863291616129dl,0xe6278994eabcb9a1l,
-            0xb409a10b9327e540l },
-          { 0x6899f7cb66cf96aal,0xa9225f051c64b545l,0x00c5522ee3feec21l,
-            0x35503728e083315cl },
-          0 },
-        /* 116 << 72 */
-        { { 0x1916d88cf1600077l,0x1ac9c238e3a58b2bl,0x3080df8535f3508dl,
-            0x86cc18712744912bl },
-          { 0x56aec9d5ccd15044l,0x8dd9061a5db0ab17l,0x84d6bc4e2c84171dl,
-            0xd569c7d70989a5bdl },
-          0 },
-        /* 119 << 72 */
-        { { 0x24446b2702af35abl,0x071710478eea4565l,0xba4989db728306e6l,
-            0x2cd692a85954a558l },
-          { 0x644e02763576b32el,0x7efdb65c1f9fe65dl,0x04b2828e8796c048l,
-            0xcfd22481187b979bl },
-          0 },
-        /* 125 << 72 */
-        { { 0xa10d104084ea9701l,0x27dd0dcb415e187dl,0xf667c5e939bfe45cl,
-            0x3995e4ae55b67506l },
-          { 0xb25117d9b5a14801l,0xeee58525fe142e92l,0x100b856a6dbae9f1l,
-            0xada7057629586658l },
-          0 },
-    },
-    {
-        /* 0 << 80 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 80 */
-        { { 0xe4050f1cf1c367cal,0x9bc85a9bc90fbc7dl,0xa373c4a2e1a11032l,
-            0xb64232b7ad0393a9l },
-          { 0xf5577eb0167dad29l,0x1604f30194b78ab2l,0x0baa94afe829348bl,
-            0x77fbd8dd41654342l },
-          0 },
-        /* 3 << 80 */
-        { { 0xa2f7932c68af43eel,0x5502468e703d00bdl,0xe5dc978f2fb061f5l,
-            0xc9a1904a28c815adl },
-          { 0xd3af538d470c56a4l,0x159abc5f193d8cedl,0x2a37245f20108ef3l,
-            0xfa17081e223f7178l },
-          0 },
-        /* 4 << 80 */
-        { { 0x1fe2a9b2b4b4b67cl,0xc1d10df0e8020604l,0x9d64abfcbc8058d8l,
-            0x8943b9b2712a0fbbl },
-          { 0x90eed9143b3def04l,0x85ab3aa24ce775ffl,0x605fd4ca7bbc9040l,
-            0x8b34a564e2c75dfbl },
-          0 },
-        /* 5 << 80 */
-        { { 0x5c18acf88e2f7d90l,0xfdbf33d777be32cdl,0x0a085cd7d2eb5ee9l,
-            0x2d702cfbb3201115l },
-          { 0xb6e0ebdb85c88ce8l,0x23a3ce3c1e01d617l,0x3041618e567333acl,
-            0x9dd0fd8f157edb6bl },
-          0 },
-        /* 7 << 80 */
-        { { 0x516ff3a36fa6110cl,0x74fb1eb1fb93561fl,0x6c0c90478457522bl,
-            0xcfd321046bb8bdc6l },
-          { 0x2d6884a2cc80ad57l,0x7c27fc3586a9b637l,0x3461baedadf4e8cdl,
-            0x1d56251a617242f0l },
-          0 },
-        /* 9 << 80 */
-        { { 0x892c81a321175ec1l,0x9159a505ee018109l,0xc70130532d8be316l,
-            0x76060c21426fa2e5l },
-          { 0x074d2dfc6b6f0f22l,0x9725fc64ca01a671l,0x3f6679b92770bd8el,
-            0x8fe6604fd7c9b3fel },
-          0 },
-        /* 10 << 80 */
-        { { 0xce711154b6e00a84l,0xd9fe7e4224890e60l,0xd10bc6c34560988fl,
-            0xbdc2ef526859b004l },
-          { 0xdcf0d868d5c890eel,0x893115e6119c47dcl,0xe97966fbee714567l,
-            0x117813355c85aa53l },
-          0 },
-        /* 11 << 80 */
-        { { 0x71d530cc73204349l,0xc9df473d94a0679cl,0xc572f0014261e031l,
-            0x9786b71f22f135fel },
-          { 0xed6505fa6b64e56fl,0xe2fb48e905219c46l,0x0dbec45bedf53d71l,
-            0xd7d782f2c589f406l },
-          0 },
-        /* 13 << 80 */
-        { { 0x06513c8a446cd7f4l,0x158c423b906d52a6l,0x71503261c423866cl,
-            0x4b96f57093c148eel },
-          { 0x5daf9cc7239a8523l,0x611b597695ac4b8bl,0xde3981db724bf7f6l,
-            0x7e7d0f7867afc443l },
-          0 },
-        /* 15 << 80 */
-        { { 0x3d1ab80c8ce59954l,0x742c5a9478222ac0l,0x3ddacbf894f878ddl,
-            0xfc085117e7d54a99l },
-          { 0xfb0f1dfa21e38ec2l,0x1c7b59cb16f4ff7fl,0x988752397ea888fel,
-            0x705d270cb10dc889l },
-          0 },
-        /* 16 << 80 */
-        { { 0xe5aa692a87dec0e1l,0x010ded8df7b39d00l,0x7b1b80c854cfa0b5l,
-            0x66beb876a0f8ea28l },
-          { 0x50d7f5313476cd0el,0xa63d0e65b08d3949l,0x1a09eea953479fc6l,
-            0x82ae9891f499e742l },
-          0 },
-        /* 17 << 80 */
-        { { 0xd7c89ba1e7d1cefdl,0xcb33553a9a91e03dl,0xa01caaff59f01e54l,
-            0x4a71c141de07def7l },
-          { 0xe1616a4034d467d1l,0x6f395ab2e8ba8817l,0xf781ea64e45869abl,
-            0x8b9513bb7134f484l },
-          0 },
-        /* 19 << 80 */
-        { { 0x0b0ec9035948c135l,0xaee219539a990127l,0x9d15ba0eb185dda1l,
-            0xd87bc2fb2c7d6802l },
-          { 0x05a480307a82d7f8l,0x7b591ce4e7e11ec3l,0x14d4cc22a0e15fdbl,
-            0xf2d4213576def955l },
-          0 },
-        /* 21 << 80 */
-        { { 0xd56d69e4117a5f59l,0xcae6008a01286e97l,0x716a0a282dab13b0l,
-            0xc821da99b3a8d2d0l },
-          { 0x6898b66239c305e6l,0xe42d3394c8b61142l,0x54c1d2b253b16712l,
-            0x3cec3953a01f4be6l },
-          0 },
-        /* 23 << 80 */
-        { { 0x5bd1e3036951b85el,0x1a73f1fb164d79a4l,0x6e77abd39fb22bc3l,
-            0x8ae4c181b3d18dfdl },
-          { 0xdd4226f5a6a14ed1l,0x620e111feb4e1d92l,0xffce6e59edca4fe8l,
-            0x39f5fc053d0a717dl },
-          0 },
-        /* 25 << 80 */
-        { { 0xef8fa78cd91aff44l,0x6f3f9749bdc03be7l,0x171545f8b8596075l,
-            0xbe31a73e2af132cel },
-          { 0x5b4e174123884e1dl,0x4373357ea9fa75f0l,0x8dba2731bc06f49el,
-            0xa09aebc877fa6de8l },
-          0 },
-        /* 27 << 80 */
-        { { 0xd4974e518293e18cl,0x1e4cfc5331ec0e8fl,0x80b4258325d40b1el,
-            0x5cfb73a2a85f7588l },
-          { 0xe553efd204c0e00bl,0xdaa6750e9a48ac39l,0xf20936b00abda06al,
-            0xbfd3c7e4bf85771cl },
-          0 },
-        /* 28 << 80 */
-        { { 0x72669c3c7292495cl,0xa627e2dd82786572l,0xbdbfce5cd39c3e3dl,
-            0xba6164927feed3d6l },
-          { 0x4eb5f513e77b7318l,0x133f2e834337c2e0l,0xdea20f07f408bec6l,
-            0x848a8396e3c87655l },
-          0 },
-        /* 29 << 80 */
-        { { 0x3086643551138f2bl,0x1176d8e6108a36bal,0xd78b3b400d4d4b66l,
-            0x99ddd9bd956dbff1l },
-          { 0x91dfe72822f08e5fl,0x7fd8cfe6a081ac4el,0x8ebb278ed75285c2l,
-            0x2335fe00ef457ac0l },
-          0 },
-        /* 31 << 80 */
-        { { 0xe9d79c50f058191al,0x6749c3b05d3183f8l,0x5edc2708dbfeb1ecl,
-            0x2c18f93621275986l },
-          { 0x3a093e1f0703389fl,0xdf065e4a3ef60f44l,0x6860e4df87e7c458l,
-            0xdb22d96e8bfe4c7dl },
-          0 },
-        /* 33 << 80 */
-        { { 0xb7193811b48dad42l,0x23b9dca320ad0f0cl,0x55511ffb54efb61bl,
-            0xac8ed94626f9ce42l },
-          { 0xa42b4bc73fc4cbd9l,0x2a4670905c6f8e39l,0xb50040f87eb592del,
-            0x6633f81bdc2541f3l },
-          0 },
-        /* 34 << 80 */
-        { { 0xc104e02ed2d6d9c2l,0xa4876e870302517al,0x0263c9b2912f5005l,
-            0x902f364a3d89d268l },
-          { 0x76070565bb20a5a8l,0xa3a8977452109e98l,0x51fbffec463aa476l,
-            0xfa8519625daa1503l },
-          0 },
-        /* 35 << 80 */
-        { { 0xe449dd8f82a9a4f3l,0xa1a2f405797e6b36l,0x76913537787785e8l,
-            0x0315a3cfe064481el },
-          { 0xc02291ee83df11e2l,0x5b59a0e9bcd178f0l,0xd5e8d10ce6b4c63al,
-            0x9eee599f3fc60a82l },
-          0 },
-        /* 36 << 80 */
-        { { 0x051e589759621468l,0xb92c06327293621el,0xee17ea647762e4f2l,
-            0x412107a771abd28cl },
-          { 0xa083d87bf02d65ebl,0xbd4a3f165594395el,0x1d5694337c8882f3l,
-            0xc5eb10c55f9c63cfl },
-          0 },
-        /* 37 << 80 */
-        { { 0x4b196728c8e62c4el,0x03dbd04cb74a757cl,0xe960a65b8520f044l,
-            0x9eda0f33f7937337l },
-          { 0x06ff0b86b6dc7dfbl,0x3bd276c11fc1ac35l,0x0e67055b1b255c27l,
-            0xe43ae552eff899f8l },
-          0 },
-        /* 39 << 80 */
-        { { 0xc64c914d3b156d76l,0x784c1f61d794345dl,0xcda0c77c365d7a50l,
-            0xcc5a1e205b32dbd0l },
-          { 0x2f4e78bff90b6ac0l,0xbead62f9a2d4862dl,0xa8f67e7dcc346b53l,
-            0xa38d7ae947e59dbdl },
-          0 },
-        /* 40 << 80 */
-        { { 0x7dc1605d480aca4dl,0x08c37750ef263aabl,0xd5c6b7c93f166725l,
-            0xf99982f30ff2853bl },
-          { 0xc61b9583a8ecb64al,0x041211a91b771741l,0x50ba64154e156f97l,
-            0xb6595ea871b8954el },
-          0 },
-        /* 41 << 80 */
-        { { 0x4ae760845eb3b4eel,0xcafefdc6c62ed274l,0x4eabeacf113f790bl,
-            0x10c2cc88a5ff64c9l },
-          { 0xe7b59f8a49965d80l,0xd04884b50df07712l,0x6316ac5ba5f7bab1l,
-            0x388111d99e78a075l },
-          0 },
-        /* 43 << 80 */
-        { { 0x8d437128f24804efl,0x12a687dd7b71dd53l,0x8b8f71d96139a60el,
-            0xb047fed42a095ec7l },
-          { 0xef238041fba59ee8l,0x61b17fac64045514l,0x45b1cf4857afa184l,
-            0x8592c50a4bff5fc5l },
-          0 },
-        /* 44 << 80 */
-        { { 0x2830592394b745dcl,0x53e9ec16b09cb993l,0x59d0b57f9a134ed1l,
-            0x89d7b439c56ee0ebl },
-          { 0xc3656539991e22a2l,0xd27a89372a345043l,0x55dd5341064038eel,
-            0xc9ee3f0348cb42efl },
-          0 },
-        /* 45 << 80 */
-        { { 0x08518c631d56c1cbl,0x5650f79f31235521l,0x33fc08d648911017l,
-            0xbb8b58538a0a33c8l },
-          { 0xb54554f2f869a62al,0x67f8cf48222457e5l,0x46e13911f276cc0dl,
-            0x4b3a2ad6943b389el },
-          0 },
-        /* 46 << 80 */
-        { { 0x0e72b816b11a4c9dl,0x919b2738e9028fa4l,0xab80e1117698a5d6l,
-            0xcd7950f56cd49adal },
-          { 0x0db75c908dfb13a5l,0x2178578770f12cebl,0xfab72d5243486ff6l,
-            0x66d55d726a0673ebl },
-          0 },
-        /* 47 << 80 */
-        { { 0xe98014b922667519l,0x7fcab2b3a95da9c0l,0x9bdbccd8438d5060l,
-            0xa72fff5455a726b6l },
-          { 0x7ae032943a5e769bl,0xf7291e9b559a0734l,0x18ae4f182ce18eeel,
-            0x88e49f7328b7b4f0l },
-          0 },
-        /* 48 << 80 */
-        { { 0x90fe7a1d214aeb18l,0x1506af3c741432f7l,0xbb5565f9e591a0c4l,
-            0x10d41a77b44f1bc3l },
-          { 0xa09d65e4a84bde96l,0x42f060d8f20a6a1cl,0x652a3bfdf27f9ce7l,
-            0xb6bdb65c3b3d739fl },
-          0 },
-        /* 49 << 80 */
-        { { 0xc6a2923e60ef9d87l,0xac66cdd8c3a64f1cl,0x069292d26e0bb0ccl,
-            0x9e491414451e52a0l },
-          { 0x2e76cedf0e0d35b3l,0x311b7ae9af682b84l,0xaa1017a02f90b176l,
-            0xac0b43a794feb6e8l },
-          0 },
-        /* 51 << 80 */
-        { { 0x7ddb42f9214e82f5l,0x91c88566f67269d7l,0x1763ed8cdd0ff422l,
-            0x045dd690ad284ddfl },
-          { 0x5713bbb141e48fe7l,0xdc5bef28f8eb580fl,0x4bd0b288ed2992c2l,
-            0x436587faaf5ef2b3l },
-          0 },
-        /* 52 << 80 */
-        { { 0xbbc1a48d6e5822c4l,0x16c3135daacebd02l,0xd0c6c543b56157dfl,
-            0xae249a0ef49f44a1l },
-          { 0x1f2c23ce72c47341l,0x8f52dc2a25974313l,0x2c99bc0a958e0e6bl,
-            0xe57eab6b950cd492l },
-          0 },
-        /* 53 << 80 */
-        { { 0xea66db638934efc0l,0x7bfe479193c6f7c7l,0x78438d535ef90d99l,
-            0xe63b87c9c665736dl },
-          { 0x6de32d82db49e1bbl,0xbfa877dcd0ad1648l,0xdb2e85de1197806dl,
-            0x74e9dbd3cfee7854l },
-          0 },
-        /* 55 << 80 */
-        { { 0xd2c26e2edb6d7e0al,0x9103119a531009cdl,0xb5dc49869a8b9d54l,
-            0x4781b83bb408b427l },
-          { 0x70d98b2ccb4ba2f7l,0x112ed5d7fa8a36b8l,0x97257bc6fdde1675l,
-            0xd2a9c711db211cb7l },
-          0 },
-        /* 57 << 80 */
-        { { 0xe4aa6a06ee79fe8cl,0x06e210233dff8a54l,0x63e11ac5bf50731al,
-            0xb8b9944f544125b8l },
-          { 0xcba92c41d359aeb0l,0xd201c893249bca36l,0xfe79bd77cb501216l,
-            0x694b21488d525ba4l },
-          0 },
-        /* 59 << 80 */
-        { { 0x60c90e11ee3dde2al,0x7df08e17bb36c4a2l,0xb6c3210dcc5b3c17l,
-            0xa814180955cec91cl },
-          { 0xf4ecbc05a8193dffl,0xf43cdef8da5744fal,0x4895a6c6f12f8a2el,
-            0x44282692eb7b910al },
-          0 },
-        /* 60 << 80 */
-        { { 0x1a405e1886d6e13al,0x6a18c91827a7c67cl,0xc34877ebe127bfd7l,
-            0x3c9fab08c098e692l },
-          { 0xfe2dc65bc2066586l,0xb107603a8f68a0a9l,0x74ef0ef8127cd340l,
-            0xfe577b5b86788d87l },
-          0 },
-        /* 61 << 80 */
-        { { 0xdc7ff83c71234c81l,0xee48d9c6d868c82fl,0xb80bac5e37e4f365l,
-            0x2bfbe94efcb951c2l },
-          { 0x55829049a374d0b0l,0x2a502cada87a5fb4l,0x0742ac9d9ee840bal,
-            0x7689bf53eecd05b1l },
-          0 },
-        /* 63 << 80 */
-        { { 0x0e7f459320059c22l,0x47c273e0e49368a2l,0x5ccb960ac6946ee2l,
-            0xd8209ec48b3271b6l },
-          { 0x7fd5142cdfb9e947l,0x46a89c83ff737ab1l,0xa45f6b0282d875ecl,
-            0x19a16e0e34c296d6l },
-          0 },
-        /* 64 << 80 */
-        { { 0xeb5ddcb6ec7fae9fl,0x995f2714efb66e5al,0xdee95d8e69445d52l,
-            0x1b6c2d4609e27620l },
-          { 0x32621c318129d716l,0xb03909f10958c1aal,0x8c468ef91af4af63l,
-            0x162c429ffba5cdf6l },
-          0 },
-        /* 65 << 80 */
-        { { 0x65c93be33607927bl,0x86feaaecdae5411dl,0x4a1686c6dd2e2c3dl,
-            0xf78200068acdf51dl },
-          { 0xf82c4d0239ed3e50l,0x5ac04047b4c3a4a4l,0xbdd14d7ec34b07a7l,
-            0x9911d7027cc12db5l },
-          0 },
-        /* 71 << 80 */
-        { { 0x4ed5dbbd1751abc9l,0xaf374229a23cc54al,0x9b5fa66ea4ed3f9al,
-            0xc56dd9613d380643l },
-          { 0x7d77897144b38021l,0xdf4712d0d3584508l,0x0018e2eecd7ab168l,
-            0xc8a3a166293d29a7l },
-          0 },
-        /* 77 << 80 */
-        { { 0x34681bdb3a5a0214l,0xe188d6f1f718797el,0xaa751de7db761c5fl,
-            0x347c50324959a5cel },
-          { 0x108705fc338be49cl,0x1dc5eada95abf7a8l,0xb863808f0fc3f0b7l,
-            0x529c27c1a05c4d43l },
-          0 },
-        /* 83 << 80 */
-        { { 0xa75f90677f699f79l,0xd01cf9c866356f99l,0xf90f9b73fdfbaae7l,
-            0xe0b5f4412c304d2fl },
-          { 0x17cbfb11807f3f57l,0xe902d542af8a9eb4l,0x3335285461f89b4al,
-            0x3a51c54d3628c0ael },
-          0 },
-        /* 89 << 80 */
-        { { 0xae5fd487c704212dl,0x82dd07a565e2e32cl,0x46d4c9646c19c199l,
-            0xe7f428593778eedcl },
-          { 0x084a4e9b6dcc5ec9l,0x757e04ba2d0538b7l,0x4ec0a573a3fba4cdl,
-            0x2432a4e5c627c2fcl },
-          0 },
-        /* 95 << 80 */
-        { { 0xfde00b3094c8a424l,0x20a57d8cd224c232l,0xd6ace1a170019992l,
-            0x1a648d40697e67a3l },
-          { 0xed1fb10691338d84l,0x828004a08372bfc8l,0xb93030fefad3bfedl,
-            0x883dea23f27369ecl },
-          0 },
-        /* 101 << 80 */
-        { { 0xfbbf36a62a710d73l,0x8db834024b3cc6bbl,0xa60c47cf16d7b1fcl,
-            0xf9778fa6cd16ce8fl },
-          { 0xd77023086d14a1a6l,0x01f139cb06e8247cl,0xd89af2979770b9c1l,
-            0x94bf1ca97d9fb550l },
-          0 },
-        /* 107 << 80 */
-        { { 0xe17e2e6dc2d45f34l,0x5969d8ee26efc6cbl,0x6f175231b9219cfbl,
-            0x027f333c189f1175l },
-          { 0x5bc60fad54f6da49l,0xc52e09af8ae5c3f3l,0x6c0e3927ed07f46dl,
-            0xbfd9e598f39cf16bl },
-          0 },
-        /* 113 << 80 */
-        { { 0x9dffd95b090aefb9l,0x26db7b73637224fel,0xb78a679e92e2aa0cl,
-            0xfc7c824ffc8f895dl },
-          { 0xdc8287e8e636b3a8l,0x6b3ccc0f28b7a639l,0x38e6e2cc653de56al,
-            0x998cf6985392c3cal },
-          0 },
-        /* 116 << 80 */
-        { { 0xe68de79e57f0d6fal,0xe707b252ff9c06f7l,0x5613698a4a061697l,
-            0xd83d6453b5390352l },
-          { 0x59b007599867c708l,0xcfe24fd7b41ea7adl,0x4692abf3da5b7de6l,
-            0xd99a6f3bf0c54e8fl },
-          0 },
-        /* 119 << 80 */
-        { { 0xe8ee870dea4addc3l,0x0d1fb29559841f3el,0xdc05b5581dba2f14l,
-            0xb8bf38324e3f4600l },
-          { 0x1a909e66fd57c48al,0xb65ca4c24e2d76dfl,0x0b27755ae7c60d89l,
-            0x9fcfa75acb9003f6l },
-          0 },
-        /* 125 << 80 */
-        { { 0xbbbdf4c49e5325aal,0x6879fe11d0d1f281l,0x7a400f890633002el,
-            0xc3633c779bb79ac9l },
-          { 0x15a4cfae93ab9bc3l,0x379bbdea42594603l,0x7c61dfa257d2af3fl,
-            0x20190537b51bfb62l },
-          0 },
-    },
-    {
-        /* 0 << 88 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 88 */
-        { { 0xa80d1db6f79588c0l,0xfa52fc69b55768ccl,0x0b4df1ae7f54438al,
-            0x0cadd1a7f9b46a4fl },
-          { 0xb40ea6b31803dd6fl,0x488e4fa555eaae35l,0x9f047d55382e4e16l,
-            0xc9b5b7e02f6e0c98l },
-          0 },
-        /* 3 << 88 */
-        { { 0x4b7d0e0683a7337bl,0x1e3416d4ffecf249l,0x24840eff66a2b71fl,
-            0xd0d9a50ab37cc26dl },
-          { 0xe21981506fe28ef7l,0x3cc5ef1623324c7fl,0x220f3455769b5263l,
-            0xe2ade2f1a10bf475l },
-          0 },
-        /* 4 << 88 */
-        { { 0x9894344f3a29467al,0xde81e949c51eba6dl,0xdaea066ba5e5c2f2l,
-            0x3fc8a61408c8c7b3l },
-          { 0x7adff88f06d0de9fl,0xbbc11cf53b75ce0al,0x9fbb7accfbbc87d5l,
-            0xa1458e267badfde2l },
-          0 },
-        /* 5 << 88 */
-        { { 0x03b6c8c7dacddb7dl,0x92ed50047e1edcadl,0xa0e46c2f54080633l,
-            0xcd37663d46dec1cel },
-          { 0x396984c5f365b7ccl,0x294e3a2ae79bb95dl,0x9aa17d7727b1d3c1l,
-            0x3ffd3cfae49440f5l },
-          0 },
-        /* 7 << 88 */
-        { { 0x26679d11399f9cf3l,0x78e7a48e1e3c4394l,0x08722dea0d98daf1l,
-            0x37e7ed5880030ea3l },
-          { 0xf3731ad43c8aae72l,0x7878be95ac729695l,0x6a643affbbc28352l,
-            0xef8b801b78759b61l },
-          0 },
-        /* 9 << 88 */
-        { { 0xdcdd3709b63afe75l,0xad9d7f0b3f1af8ffl,0xdd6a8045194f4beel,
-            0x867724cc2f7d998cl },
-          { 0xd51d0aa5837751bel,0x21d6754a959a0658l,0xd2212611695f7e58l,
-            0xec4b93c2297363efl },
-          0 },
-        /* 10 << 88 */
-        { { 0x0ac1c5fab6ef26cfl,0xcd8ba0c5a39de8eel,0x11ba7537dd7796e0l,
-            0x1215933476d58d6dl },
-          { 0xf51eb76f529fda4cl,0x2fd9209ddedaa8a3l,0x555a675615efac65l,
-            0xb784c9ca7fd42fe9l },
-          0 },
-        /* 11 << 88 */
-        { { 0x8165ec11b9d1a70fl,0x01347efc384f6cael,0xe95c01a0ab7aeca9l,
-            0x459ba1c5c6c99530l },
-          { 0x38967a635cf3416bl,0x5c3761fd1e5457e2l,0x43e6077af03e9df6l,
-            0xb15d34628bd1c7f6l },
-          0 },
-        /* 13 << 88 */
-        { { 0xad87d3db35a75c49l,0xc69d800961af03c5l,0x31aef61a3a6a6c4cl,
-            0xb3292640aa10a993l },
-          { 0x959aae80aaee340fl,0xf900528e7f381a3bl,0x44ecf76e853691a3l,
-            0xa081663ce749e68el },
-          0 },
-        /* 15 << 88 */
-        { { 0x4f2782136283e34al,0x6f9fcf60fbfa315fl,0x224a2ab99b701364l,
-            0xb4b1b418f9fecadcl },
-          { 0xbf7280fe50ba1b9al,0x7e68259c33f36db9l,0x8ccb754e154c9fb0l,
-            0xf281adb1db2328f1l },
-          0 },
-        /* 16 << 88 */
-        { { 0xf92dda31be24319al,0x03f7d28be095a8e7l,0xa52fe84098782185l,
-            0x276ddafe29c24dbcl },
-          { 0x80cd54961d7a64ebl,0xe43608897f1dbe42l,0x2f81a8778438d2d5l,
-            0x7e4d52a885169036l },
-          0 },
-        /* 17 << 88 */
-        { { 0xc2a950ad2d6608bel,0xab415e2a51c3c2b6l,0xffbd2a65f5c803e7l,
-            0x3f81dc3eca908532l },
-          { 0x0ec47397c28c04f4l,0xf6c632e8153f58e8l,0xccac35f8efb4a6d8l,
-            0x22a1b677ee6d7407l },
-          0 },
-        /* 19 << 88 */
-        { { 0x276662435243c119l,0x79cb8580e707363el,0x5bf5ebf4d01682d6l,
-            0x8a980173762811e0l },
-          { 0xe2f2be1fc7547d77l,0x21a50fffb925fec6l,0x5e6cf2ef40115509l,
-            0xb69beae18faa0fc0l },
-          0 },
-        /* 21 << 88 */
-        { { 0xfa147da8cec36e75l,0xba184e5a42860484l,0xe8ec25df222fb1e6l,
-            0xce91dcb18ff8403cl },
-          { 0xf1b0e27ead7faa32l,0x097d881d42a3a205l,0xa8865dd43f8f56d4l,
-            0x624d7a451aef929dl },
-          0 },
-        /* 23 << 88 */
-        { { 0x3db0238ad01698e8l,0xbb7186dc00306082l,0x542f4377250f830el,
-            0x34b8a67dae438c50l },
-          { 0xada528a0858d8048l,0x561aa3336b57afc1l,0x8d9188e0fda35f7al,
-            0x5838d1211dcad0c5l },
-          0 },
-        /* 25 << 88 */
-        { { 0x4f97d1529f17511dl,0x8b9f012776fdb9ebl,0x53a0a72d4056e6a7l,
-            0x5ff937d64e262eeel },
-          { 0xaa64a8dc489fbe6dl,0xc19947dfea02bc69l,0x76f0bbb91492c9bel,
-            0xe53881098d89cd01l },
-          0 },
-        /* 27 << 88 */
-        { { 0x16083309456057b7l,0x2810c08040a331f6l,0x0561656c3c166929l,
-            0x16f0d8d6ed1c3999l },
-          { 0x37b6da7294697927l,0xd821c2cc23ca6c9cl,0x42ef1bdb8ca4351cl,
-            0x7ca32bad5edfa682l },
-          0 },
-        /* 28 << 88 */
-        { { 0xdc1de17d98119f10l,0x74353c5d488c36a6l,0x14aaf33a3d8e23dfl,
-            0x31e075c078baf593l },
-          { 0x0f7ca03a46d1ca3cl,0x99c5e3ac47b660c7l,0x70d0241388fe2e59l,
-            0x2e9a6be12a7ec005l },
-          0 },
-        /* 29 << 88 */
-        { { 0x4d1f087f184252b1l,0xfd3ace273f5b49c6l,0x6e874447bbb04da2l,
-            0x2347e3a1b3767ff0l },
-          { 0x990d4010f868966al,0x35320090dd658b5el,0x1105bfb974fe972al,
-            0x3961f7dc8e7ad2c6l },
-          0 },
-        /* 31 << 88 */
-        { { 0x100d8b54741e3286l,0x65d9108ef3abc7afl,0x172b450620ef8fbcl,
-            0x11bd7db2d81b8a2el },
-          { 0xf89210e1e8e41de5l,0x910613f3d98a868bl,0xbfc85241849aa909l,
-            0x68a43e21c7d3a7cal },
-          0 },
-        /* 33 << 88 */
-        { { 0x68f891479a4f8293l,0x48262328a5eb9101l,0x7eca2a178fe218b5l,
-            0xde6c22dbc733f768l },
-          { 0xde7171d108d6084dl,0xd153827a0f0f8092l,0xc7b52d8f85a9252fl,
-            0xfa29ca3a5708b31fl },
-          0 },
-        /* 34 << 88 */
-        { { 0x20518ddf9e0ad7e7l,0x33d5d079e8d28b9bl,0x1149b393d13058b0l,
-            0x708cc65586d4651dl },
-          { 0xd7fefaa694207435l,0xce882c0d96312f8fl,0x2fd5cb2059d091a7l,
-            0x4533a88a0e1ece94l },
-          0 },
-        /* 35 << 88 */
-        { { 0xceddd9b5a59c28bcl,0xaa4808f9572e2a5dl,0x38bc191999014a1el,
-            0x1aacefdaa6d85686l },
-          { 0xa59283d42a573fddl,0x84359db29c387594l,0x79994773dca3acc8l,
-            0xe4323e7654cf7653l },
-          0 },
-        /* 36 << 88 */
-        { { 0xac449695241fbd6fl,0x67c9b170081c1223l,0x16868f21b56aac6fl,
-            0x34bd8fa3f8bcb721l },
-          { 0x06b6bd33b6691c76l,0x6c924766381a7973l,0x6a12444ca54078dbl,
-            0xd02e91a96d1051ccl },
-          0 },
-        /* 37 << 88 */
-        { { 0x512f5fb35f30b344l,0xb13ade169d516885l,0x18812e9b2b468802l,
-            0xf15d730e6b28979al },
-          { 0x5015616f6889348bl,0xe0b02a0a96af0401l,0x3b02007b61204c89l,
-            0x9ece2aa7432742a4l },
-          0 },
-        /* 39 << 88 */
-        { { 0xd5f7e09c7c1cc4a1l,0x313ac04218b2d854l,0xbc4fe2a04c253b10l,
-            0x25a696a3c7080b5cl },
-          { 0x6de3cb6aef811877l,0x4d242fecd15f9644l,0xb9bfa2480ee6a136l,
-            0x8122679e9c8d181el },
-          0 },
-        /* 40 << 88 */
-        { { 0x37e5684744ddfa35l,0x9ccfc5c5dab3f747l,0x9ac1df3f1ee96cf4l,
-            0x0c0571a13b480b8fl },
-          { 0x2fbeb3d54b3a7b3cl,0x35c036695dcdbb99l,0x52a0f5dcb2415b3al,
-            0xd57759b44413ed9al },
-          0 },
-        /* 41 << 88 */
-        { { 0xc2c7daec96a8d727l,0x8a11631a17f3abf9l,0x06aba65c0ae8940al,
-            0xfca280c7873d3635l },
-          { 0x57496889ddb72b87l,0xaa9a3359320793d4l,0x11b6864d43120741l,
-            0x1877cd4e51527639l },
-          0 },
-        /* 43 << 88 */
-        { { 0x8b35ce4e6f43dfc6l,0x4114b2fe9a19f3bfl,0x8c4af8024ffa45cal,
-            0xa3ab5f869328b847l },
-          { 0x0986de3e555f30f0l,0xaae6e3eac8cb84c4l,0x2a7dcdbaa4ba01f7l,
-            0xfa32efa729f5dc6cl },
-          0 },
-        /* 44 << 88 */
-        { { 0x077379c00b33d3f8l,0x421883c67064e409l,0x2d0873d76c29c8f6l,
-            0xbfa433a3d274c0c8l },
-          { 0x56dc778f23a5891el,0xd663bf6535e2de04l,0x488fdb485db517cel,
-            0x00bba55e19b226c2l },
-          0 },
-        /* 45 << 88 */
-        { { 0x879b30ead7260d78l,0x04954ba2eac5201fl,0x3210c0e3ff2529d1l,
-            0x0743823488b470b3l },
-          { 0x8b618de48854cc0dl,0x98270d5e35b795eel,0x0e47d651aa33ca37l,
-            0x77d75fda1e87d0cfl },
-          0 },
-        /* 46 << 88 */
-        { { 0x789dbe987803fbf9l,0x940589aa17ede316l,0x032902bd85a1988cl,
-            0x43cbc0031c47f7f0l },
-          { 0xc6ff73714709148fl,0x769957122d9b8a5el,0xb4520e462597b70el,
-            0x00d19f39f67ff3b8l },
-          0 },
-        /* 47 << 88 */
-        { { 0xe2dfcef9b159f403l,0xe8e9e8d8855644afl,0x2796247163fa1068l,
-            0x400e992a968a5400l },
-          { 0xe2b9d29f56e563c1l,0xed66759c2885fabfl,0x788b6263750abdffl,
-            0x30adb00d6cbbdcacl },
-          0 },
-        /* 48 << 88 */
-        { { 0x1fe647d83d30a2c5l,0x0857f77ef78a81dcl,0x11d5a334131a4a9bl,
-            0xc0a94af929d393f5l },
-          { 0xbc3a5c0bdaa6ec1al,0xba9fe49388d2d7edl,0xbb4335b4bb614797l,
-            0x991c4d6872f83533l },
-          0 },
-        /* 49 << 88 */
-        { { 0x5548d3423fa17b28l,0x38587952823ee731l,0x8ee9b90a0a28bcd1l,
-            0xcfc029bf6676917el },
-          { 0x7e08306d2a212358l,0x66a9488dc88a66bcl,0x7a09db327d7c9e65l,
-            0x20eaf4e72cbc1790l },
-          0 },
-        /* 51 << 88 */
-        { { 0xb3095b491f2a9605l,0x7cfc4205f72691c7l,0x1544bf964d889b90l,
-            0xdc44d20ba0bbae7al },
-          { 0xee369b670b1f0b23l,0xf3ec25e818a7bdcbl,0xf614ab5df47ecf65l,
-            0x4869762f80a4a09dl },
-          0 },
-        /* 52 << 88 */
-        { { 0xedbbeee78a058fb6l,0xb9d19ddcfb09121al,0xa41bb45bd34dddcel,
-            0x2dbc80b900964bc4l },
-          { 0x4ed9137d1d6cb654l,0x1b9016db483d01c5l,0x5fc501bc6528e22el,
-            0xb2d2f8816cad646bl },
-          0 },
-        /* 53 << 88 */
-        { { 0xb57aa72a89043e56l,0x8fbca2435c5319fdl,0xe66aef43b13ce900l,
-            0x2c7c3927c3382934l },
-          { 0x434d9104a835fdf5l,0x419470b81b3b85bel,0xeaec374abeb4d448l,
-            0x26a53b51f33cda51l },
-          0 },
-        /* 55 << 88 */
-        { { 0x421f1725bb1db793l,0x20214d4f558c94a9l,0x3371233b7696092cl,
-            0x774d3fcb1902ab0el },
-          { 0x4ce223ded149aecel,0x174b260e33057bc7l,0xdf70cfa3f6effee4l,
-            0x3d8cd01f80880678l },
-          0 },
-        /* 57 << 88 */
-        { { 0x32db21862e59985cl,0x448865abaa1b39e1l,0x250ce79cd89fe98dl,
-            0x962710e763e3fb10l },
-          { 0xa8fc70561ac10e3el,0x9eed208fa3b132fbl,0xf499d638937051f5l,
-            0x27acf7ec21a9f78fl },
-          0 },
-        /* 59 << 88 */
-        { { 0x148e572a4c7b445el,0xdc10a0214dc95a4fl,0xe60e9c2e02237869l,
-            0xbfdfcb3aa393c3a4l },
-          { 0x8b799db211a64cf0l,0x1ca865ea2e16f59fl,0x865441fbd3a17e46l,
-            0x23315b9753409692l },
-          0 },
-        /* 60 << 88 */
-        { { 0x5e76fb2f286bad39l,0xbad9efe39dcad1e2l,0x60e75190edc7e904l,
-            0x6a6f063e0fecb5a5l },
-          { 0x5150ed85aed8acc3l,0xb56ccfbc6d20af6cl,0x7e0d1e982c69dbfal,
-            0xabf5628a7c7e10a9l },
-          0 },
-        /* 61 << 88 */
-        { { 0xb84af2c00df6d61fl,0x02c651c52acbaf4bl,0xfb605754afaaa0bfl,
-            0xa03f5257dff61017l },
-          { 0x9e3ffb1672762093l,0x4f9a5da0c4f40bd3l,0x37dce5220d26f8e1l,
-            0x260f736fc06a1a07l },
-          0 },
-        /* 63 << 88 */
-        { { 0xb92aba79b1077d55l,0xc52f81081a42f5f5l,0x9913f04f86e5aa99l,
-            0x6814b0b1f3c7f504l },
-          { 0xb7d61fd34d354bdal,0xf27926e39581d25el,0x97724001c2dc21adl,
-            0x835778231d5c4788l },
-          0 },
-        /* 64 << 88 */
-        { { 0x77b868cee978a1d3l,0xe3a68b337ab92d04l,0x5102979487a5b862l,
-            0x5f0606c33a61d41dl },
-          { 0x2814be276f9326f1l,0x2f521c14c6fe3c2el,0x17464d7dacdf7351l,
-            0x10f5f9d3777f7e44l },
-          0 },
-        /* 65 << 88 */
-        { { 0x53857462ff9727a2l,0xe6870e7dc68488e7l,0x276da72808c79656l,
-            0x1308eb61d86c24ebl },
-          { 0x34c43a84db0a3e56l,0x03961b5525335a59l,0xf9bc2d5805689d86l,
-            0xfa4d3c01eb29d6d6l },
-          0 },
-        /* 71 << 88 */
-        { { 0xd07dac3037d10ffal,0xb2b0a0fd8bef0a79l,0xa2e804510ec02505l,
-            0xf256c18962f55f5fl },
-          { 0x0ca3f9b10b39f4f0l,0x7bf4e1cf3bb7c8e9l,0x7a8a43f8ee11f227l,
-            0x2ad8431a3e4056ebl },
-          0 },
-        /* 77 << 88 */
-        { { 0xb8cf71ed031c1871l,0x702431806f703102l,0x9a87e1c24ec6f1b0l,
-            0xf7e6e5b4664f275dl },
-          { 0xc70a8b4e8c76b505l,0x6ba69bf2a002e9cfl,0x33ed74f7a0d8c9bfl,
-            0x17f5f4b18d9989del },
-          0 },
-        /* 83 << 88 */
-        { { 0xcd116dcb1b13a4a1l,0x591adb831c369877l,0x697be1aca6b8e80bl,
-            0xb2d4baa1b975d781l },
-          { 0xd4a9a496b16b48e7l,0x64de2d7af293997dl,0x039ae039af09a492l,
-            0x66e31a2665f3a485l },
-          0 },
-        /* 89 << 88 */
-        { { 0x110a8a42fec01a53l,0x1f5fcc1b38affab8l,0x757310ca9941a19el,
-            0x11ef95f76c29d6cbl },
-          { 0x0756bdb22dd427bal,0x8de8d44af3e16c33l,0xf9d28355e25aec52l,
-            0xeb761efc02f36465l },
-          0 },
-        /* 95 << 88 */
-        { { 0xfc83bf7454bfcd7al,0x51d861794837b6bel,0x8165b3f9801a324dl,
-            0x3a5972bc634cfd61l },
-          { 0xeecfe6d825258ed6l,0x51d968df1451ced0l,0x3010cdb8316aa0ael,
-            0xc295b8522900eaf2l },
-          0 },
-        /* 101 << 88 */
-        { { 0x5ad434a3890cc798l,0x4c17ff5e1531bce4l,0x825b5b5a5ea8e26fl,
-            0xacca9d5dd66fd7b3l },
-          { 0xb647dbde37ae6f92l,0xa5594868f3600416l,0x7b90ac53ab0c5d63l,
-            0x4b66ad7ceb43e1d0l },
-          0 },
-        /* 107 << 88 */
-        { { 0x04a211fac09ccbffl,0x9c96ad9ee873d898l,0x9eb1deb69c481f86l,
-            0xb3616ce8b2d70298l },
-          { 0x67a6fe9b9073726dl,0x5b8aa37d4c9bf744l,0xf558603ebb6aa0efl,
-            0x72767f5103d304fbl },
-          0 },
-        /* 113 << 88 */
-        { { 0x787cb8b8d6e9b7e3l,0x8bb30222e079fc68l,0x651a2ea6e3145a0bl,
-            0x0254c5da9ab18fa8l },
-          { 0x83722ffc12e1611fl,0xb0ddf1ffa7cc61bel,0x7c9c7e10ac0ac8d7l,
-            0x8241a8191da12218l },
-          0 },
-        /* 116 << 88 */
-        { { 0x70bb7719bc407e6el,0x231328efd84ceb41l,0x8bca6a1fc104bb20l,
-            0xd6f4e425280b9071l },
-          { 0xb41b95a292896a82l,0x735cf435fa34df67l,0xbc331a08d9d6d769l,
-            0x579786052682747el },
-          0 },
-        /* 119 << 88 */
-        { { 0x048ba499eb3af9a9l,0x43a8c367d50b82cel,0xedf9e2b21e0724d9l,
-            0x3098aab3d607140bl },
-          { 0xd1f18f1e5ed49eb9l,0xf9c6bb6ae0bb02a2l,0x204f96aa0cd245ddl,
-            0xdaadaf4afb011ed5l },
-          0 },
-        /* 125 << 88 */
-        { { 0xb298ce2de50404b1l,0x04dd38c45bf9b581l,0x229deabdfada51e8l,
-            0x74bd233f8788a132l },
-          { 0x951ba5ecf03e6c30l,0x9da2f5aa45bf1a41l,0x6bec7fea7e52b860l,
-            0x76e3778964b0a9ddl },
-          0 },
-    },
-    {
-        /* 0 << 96 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 96 */
-        { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l,
-            0x8589fb9206d54831l },
-          { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l,
-            0xebb0696d02541c4fl },
-          0 },
-        /* 3 << 96 */
-        { { 0xb99f0e0399375235l,0x7614c847b9917970l,0xfec93ce9524ec067l,
-            0xe40e7bf89b122520l },
-          { 0xb5670631ee4c4774l,0x6f03847a3b04914cl,0xc96e9429dc9dd226l,
-            0x43489b6c8c57c1f8l },
-          0 },
-        /* 4 << 96 */
-        { { 0x0e299d23fe67ba66l,0x9145076093cf2f34l,0xf45b5ea997fcf913l,
-            0x5be008438bd7dddal },
-          { 0x358c3e05d53ff04dl,0xbf7ccdc35de91ef7l,0xad684dbfb69ec1a0l,
-            0x367e7cf2801fd997l },
-          0 },
-        /* 5 << 96 */
-        { { 0x46ffd227cc2338fbl,0x89ff6fa990e26153l,0xbe570779331a0076l,
-            0x43d241c506e1f3afl },
-          { 0xfdcdb97dde9b62a3l,0x6a06e984a0ae30eal,0xc9bf16804fbddf7dl,
-            0x170471a2d36163c4l },
-          0 },
-        /* 7 << 96 */
-        { { 0x361619e455950cc3l,0xc71d665c56b66bb8l,0xea034b34afac6d84l,
-            0xa987f832e5e4c7e3l },
-          { 0xa07427727a79a6a7l,0x56e5d017e26d6c23l,0x7e50b97638167e10l,
-            0xaa6c81efe88aa84el },
-          0 },
-        /* 9 << 96 */
-        { { 0x473959d74d325bbfl,0x2a61beec8d6114b9l,0x25672a94924be2eel,
-            0xa48595dbf2c23d0cl },
-          { 0xe476848b6a221838l,0xe743e69a35c1b673l,0x2ab42499d8468503l,
-            0x62aa0054e9e90ba7l },
-          0 },
-        /* 10 << 96 */
-        { { 0x358d13f1bc482911l,0x685d1971b7fa7f26l,0x3e67a51d2be1aee4l,
-            0xe041850998d114a9l },
-          { 0x59639f604e052561l,0x32075c49155d0818l,0x2aa2343b67b64b1cl,
-            0x1b445e2967f53e6al },
-          0 },
-        /* 11 << 96 */
-        { { 0xbdfb271773a904e0l,0x7ce1e40b28888d73l,0x2e7e35f6eaa97d1bl,
-            0xd061772aa9afa097l },
-          { 0x434ac7c47a1f7c59l,0x6e21124ae79b7b9al,0x055acff3bb22ecc7l,
-            0x8bfd7ac984c858d3l },
-          0 },
-        /* 13 << 96 */
-        { { 0x2fd57df59f1f68adl,0x5ddcc6dbb06470c8l,0x801b6451a9b47307l,
-            0x6b51c8e376551bf4l },
-          { 0xef0bd1f7d44e1da9l,0x714bcb1d4d4e600cl,0xc57bb9e40c6540c7l,
-            0x71bd1ec2327cc644l },
-          0 },
-        /* 15 << 96 */
-        { { 0x9a52cf7e7f4dd81fl,0xa0132be15e69c05el,0x90dab7472a0f4d72l,
-            0xc142f911312d6706l },
-          { 0xe8d3631f8261998bl,0xf0f42fae615c1c94l,0x2f4e948caec3fa5dl,
-            0x242ae7a8a374101el },
-          0 },
-        /* 16 << 96 */
-        { { 0x0f893a5dc8de610bl,0xe8c515fb67e223cel,0x7774bfa64ead6dc5l,
-            0x89d20f95925c728fl },
-          { 0x7a1e0966098583cel,0xa2eedb9493f2a7d7l,0x1b2820974c304d4al,
-            0x0842e3dac077282dl },
-          0 },
-        /* 17 << 96 */
-        { { 0x1fa878cad088be52l,0x89c2cb07a9e1e656l,0x385bc5c3219d62dbl,
-            0xd82b676b5fda2752l },
-          { 0x2449dc9ee304eafcl,0x1e9e7991632f4ea2l,0x3036e061cdd5e0b9l,
-            0x75a6f6ff830825bcl },
-          0 },
-        /* 19 << 96 */
-        { { 0xb10fcddc449dedb4l,0x2c890042d1244acfl,0x9b3072cac7fc7017l,
-            0x1acda6859ce8063fl },
-          { 0xd243313c7f51e2f5l,0x52a3f1a4d73d9578l,0xda785b7a64f0ce6el,
-            0x2e766315442a4c2dl },
-          0 },
-        /* 21 << 96 */
-        { { 0x94f9b004151f111al,0xc7a5035b07dbc5fal,0x53958ea7609e49d7l,
-            0x0526b4d79013f4c0l },
-          { 0x66de5ebb593e2fbdl,0x6e7cf8b44c2e0c37l,0x6f72fc8b8c983e78l,
-            0x6fab9b632348f9d7l },
-          0 },
-        /* 23 << 96 */
-        { { 0xc748a3526a3d8468l,0x3fab479927e38032l,0x91ad3629fa430ce7l,
-            0xc5af0b2c71614c44l },
-          { 0xcede3fa50c211611l,0x6e6889ba02338083l,0xee0a195977f0fe32l,
-            0x01ea905d0f4bbc5al },
-          0 },
-        /* 25 << 96 */
-        { { 0x12cfb25e8193db48l,0xddb4ae633bea708cl,0xdaae102ef181f821l,
-            0x9d9d923024a089d9l },
-          { 0x71c4122da0876aeal,0x1a63ea3bbbe19c09l,0x3b898076016f8d0cl,
-            0xa5cccc5daea6b713l },
-          0 },
-        /* 27 << 96 */
-        { { 0xc3f22baf4a8e2f61l,0x77d29ede176da6a6l,0x40a55f211607da63l,
-            0x858b38561452e391l },
-          { 0x0dd3c267fe1b3c56l,0x66c04bdd7d55227al,0xfbd2fe55e6404e09l,
-            0x5981cf49ea9cfcbcl },
-          0 },
-        /* 28 << 96 */
-        { { 0xe549237f78890732l,0xc443bef953fcb4d9l,0x9884d8a6eb3480d6l,
-            0x8a35b6a13048b186l },
-          { 0xb4e4471665e9a90al,0x45bf380d653006c0l,0x8f3f820d4fe9ae3bl,
-            0x244a35a0979a3b71l },
-          0 },
-        /* 29 << 96 */
-        { { 0xae46a902aea870afl,0xa9b9fcf57cbedc99l,0x74f2ca3f79b7e793l,
-            0xadb8f2231dbeeb28l },
-          { 0x6302060e6764df85l,0x363320d257ebd554l,0xd9fd573e798d22e1l,
-            0x285f85f5ebb67dedl },
-          0 },
-        /* 31 << 96 */
-        { { 0xd86b329211caa2b5l,0x2a26258e39337bd1l,0x4dc5a9b579c8c291l,
-            0x16443d87741942e6l },
-          { 0x6bc9a2f8f811400cl,0x819c69359eeb4e0el,0xe1be7273ce0c214bl,
-            0x429afb8184b61581l },
-          0 },
-        /* 33 << 96 */
-        { { 0xb37e188756af5812l,0xd662bdb485aff83el,0xc89742d07bc63de7l,
-            0xea103f9d0279f487l },
-          { 0x4d26916a3a6cc639l,0x4eea3a3c7c743b94l,0x6a3e0dc7007376d9l,
-            0xdb6ef3cf573f904el },
-          0 },
-        /* 34 << 96 */
-        { { 0x9b1058ecb0b0fb53l,0x8955f5f75f8a9a9fl,0xf5f92e7f9f6f9e6dl,
-            0x03f5df6c50ec198bl },
-          { 0x6c8741f2b8aedbcel,0x8f4e60cfed8018f7l,0x6ca5297c9fa01f89l,
-            0x8591cf7a864995dbl },
-          0 },
-        /* 35 << 96 */
-        { { 0xa126147eb0a11b9bl,0xeedcc9e198900232l,0x15d94f8c2bead119l,
-            0x042423cfefc38691l },
-          { 0x6ce86fbe77165d91l,0xa07732126b3fd565l,0x8cdc409150b1f9c7l,
-            0x7f5ad1af064595acl },
-          0 },
-        /* 36 << 96 */
-        { { 0xed374a6658926dddl,0x138b2d49908015b8l,0x886c6579de1f7ab8l,
-            0x888b9aa0c3020b7al },
-          { 0xd3ec034e3a96e355l,0xba65b0b8f30fbe9al,0x064c8e50ff21367al,
-            0x1f508ea40b04b46el },
-          0 },
-        /* 37 << 96 */
-        { { 0x73644c158f8402a0l,0x0d9b5354f4730eb9l,0x78542af4e94cc278l,
-            0xf4dbede3e395f33al },
-          { 0x8fe8cbc590c70b00l,0x9c35bb2d7db197f6l,0x229b4973e6599746l,
-            0x0817d04e1a84b986l },
-          0 },
-        /* 39 << 96 */
-        { { 0x8ffe34e95ecd09b3l,0x6a7c3de4153b7cael,0xf02713e4a81044b7l,
-            0x85ca6158c70545c8l },
-          { 0xd3ff392845d88bffl,0x3a251a07f0bafe89l,0x61290e1287cea7f4l,
-            0xa360a17efa4808adl },
-          0 },
-        /* 40 << 96 */
-        { { 0x98561a49747c866cl,0xbbb1e5fe0518a062l,0x20ff4e8becdc3608l,
-            0x7f55cded20184027l },
-          { 0x8d73ec95f38c85f0l,0x5b589fdf8bc3b8c3l,0xbe95dd980f12b66fl,
-            0xf5bd1a090e338e01l },
-          0 },
-        /* 41 << 96 */
-        { { 0x2d1751083edf4e2bl,0x30e6e90fa29c10d0l,0xfee1eb14c9c6ccd2l,
-            0x244670c756a81453l },
-          { 0x90b33eefc5185c22l,0xd77ae4b63db82d28l,0xce5ee034f228f940l,
-            0x5d7660847bb47be5l },
-          0 },
-        /* 43 << 96 */
-        { { 0x88b7eec499b9a8c6l,0x56048d9e14e8ef0cl,0xa18f93215c89cf78l,
-            0xbd2087616d327e66l },
-          { 0x5b187225d9e53e27l,0xa57ca6c7bf4d0317l,0x187731d2e9557736l,
-            0xd4ce2f78a874982el },
-          0 },
-        /* 44 << 96 */
-        { { 0x65163ae55e915918l,0x6158d6d986f8a46bl,0x8466b538eeebf99cl,
-            0xca8761f6bca477efl },
-          { 0xaf3449c29ebbc601l,0xef3b0f41e0c3ae2fl,0xaa6c577d5de63752l,
-            0xe916660164682a51l },
-          0 },
-        /* 45 << 96 */
-        { { 0xf5b602bb29f47deal,0x42853c9659ddd679l,0x5c25be4041d7c001l,
-            0x8e069399d4a3b307l },
-          { 0x1782152e736ce467l,0x2e264109c9cb4f08l,0xf900cb11ab124698l,
-            0x1bbed1d02d6e05b1l },
-          0 },
-        /* 46 << 96 */
-        { { 0x9cc3fedc7da08b1fl,0x0f44949361d5ed38l,0xc8cbc4209b991b6bl,
-            0xee62a342891c42e1l },
-          { 0x11c496bb1a179139l,0x94ece2892eac4d8el,0x35f303a5a98d5570l,
-            0x69d4340514a31552l },
-          0 },
-        /* 47 << 96 */
-        { { 0x29d45e50892dfcbal,0x653e613e5c30cee3l,0x7b8c1ae61868a348l,
-            0x40ab51654f2c612al },
-          { 0x56e977f9891cdc8cl,0xee1ca12a34ca7cd1l,0xa4e283ee17b5ddf8l,
-            0x4e36f2fb6f536205l },
-          0 },
-        /* 48 << 96 */
-        { { 0x5a3097befc15aa1el,0x40d12548b54b0745l,0x5bad4706519a5f12l,
-            0xed03f717a439dee6l },
-          { 0x0794bb6c4a02c499l,0xf725083dcffe71d2l,0x2cad75190f3adcafl,
-            0x7f68ea1c43729310l },
-          0 },
-        /* 49 << 96 */
-        { { 0xa3834d85e89ea13fl,0x2ca00f942db803bbl,0x0f378681400ed3dal,
-            0x1028af6b54854da3l },
-          { 0x3928c2da06400c7fl,0x21119785d82aac92l,0x06618c17724e4af0l,
-            0x22b42b161470736bl },
-          0 },
-        /* 51 << 96 */
-        { { 0x7d0cfd48f7f2ac65l,0x46e1ac705f641b60l,0x0ab9566a0fcf0137l,
-            0xbd4380e0db460fb8l },
-          { 0x4550efbf6db99b55l,0x33846e669764b744l,0xacffa0cae34ca007l,
-            0xce642d6a077e646cl },
-          0 },
-        /* 52 << 96 */
-        { { 0xe747c8c7b7ffd977l,0xec104c3580761a22l,0x8395ebaf5a3ffb83l,
-            0xfb3261f4e4b63db7l },
-          { 0x53544960d883e544l,0x13520d708cc2eeb8l,0x08f6337bd3d65f99l,
-            0x83997db2781cf95bl },
-          0 },
-        /* 53 << 96 */
-        { { 0xd89112c47d8037a3l,0xcba48ad3464c2025l,0x3afea8399814a09dl,
-            0x69e52260269030b5l },
-          { 0x5b7067365c674805l,0x8c3fd33d87343f56l,0xc572c858b1c61edfl,
-            0x43d8f4ded06749cbl },
-          0 },
-        /* 55 << 96 */
-        { { 0x04da1f06b4066003l,0xf7d4e52f372749e8l,0x56cd667114b38747l,
-            0x1943a22a22eb6d9el },
-          { 0xc2c5391990714b0al,0xb6e3abb7d13cf3ael,0xfcd8d671676115cbl,
-            0x178ce1a0c06a0d3al },
-          0 },
-        /* 57 << 96 */
-        { { 0x94485b36913508f8l,0x92f87fe36de83b42l,0xedd476f0ed77e666l,
-            0xee90fbc68da2cf53l },
-          { 0x6f4afc53fc6cf3d9l,0x231bceb9f21f6ecfl,0x6504a11d494c6e9cl,
-            0xd3728f032c211461l },
-          0 },
-        /* 59 << 96 */
-        { { 0x09a9b93799562ca2l,0xb7d5c5cf6a5a5aa8l,0x52f5d7b9987b219dl,
-            0x33849f9ec38014d4l },
-          { 0x299adaf628f23880l,0x738ecc8874875588l,0x39d707adca2af665l,
-            0xc8c11f688f4c5f73l },
-          0 },
-        /* 60 << 96 */
-        { { 0x68e4f15e9afdfb3cl,0x49a561435bdfb6dfl,0xa9bc1bd45f823d97l,
-            0xbceb5970ea111c2al },
-          { 0x366b455fb269bbc4l,0x7cd85e1ee9bc5d62l,0xc743c41c4f18b086l,
-            0xa4b4099095294fb9l },
-          0 },
-        /* 61 << 96 */
-        { { 0x2ae046d66aa34757l,0x34db1addaa6d7e9dl,0x2b4b7e017ccf432bl,
-            0xfbe0bfa590d319c6l },
-          { 0xfb2981687ec7a7f2l,0x346cc46004f5132el,0x782b2e53b40aceddl,
-            0x402e1d64e3f0b8b9l },
-          0 },
-        /* 63 << 96 */
-        { { 0x2aa3b21d25a56088l,0xae6ee57543d08962l,0x669e42bff1e22297l,
-            0x7b4c635732e3a47al },
-          { 0x22b16260ea464a25l,0xad8ca59072d5cd7al,0x7c244266104eb96al,
-            0x1def95e28e7c11d2l },
-          0 },
-        /* 64 << 96 */
-        { { 0x9c7c581d26ee8382l,0xcf17dcc5359d638el,0xee8273abb728ae3dl,
-            0x1d112926f821f047l },
-          { 0x1149847750491a74l,0x687fa761fde0dfb9l,0x2c2580227ea435abl,
-            0x6b8bdb9491ce7e3fl },
-          0 },
-        /* 65 << 96 */
-        { { 0x1f04524cdc27e1f7l,0xa0c74f61572eab14l,0xdd5d0cfced272074l,
-            0x95533c1d5bfe4f65l },
-          { 0x3039d57ecce817cal,0x029967d73b822082l,0x9fca43866c4a10d3l,
-            0xf8b2a7f0bb4968ebl },
-          0 },
-        /* 71 << 96 */
-        { { 0x933cd6dcbfbf6407l,0xd08f21504be673f8l,0x0e1c4d0db1140a2el,
-            0x0502a092431b270al },
-          { 0x5d99f9508768c00al,0xda3ce5079b3ff3c7l,0x1c648b75031c11abl,
-            0x5e3de47bf2776305l },
-          0 },
-        /* 77 << 96 */
-        { { 0xe22af9274d2b9de4l,0xf3690f55a69609ecl,0x20260a6e453fbe18l,
-            0x8edcb46b42d0b085l },
-          { 0xd4ef250b7d9c7f58l,0x5e8578dfc83c3433l,0x9751d9b9e46e320al,
-            0xb02bd03cf3c58af6l },
-          0 },
-        /* 83 << 96 */
-        { { 0x0ab299ede1b4d1ccl,0x22e7301cec4d18d2l,0xf2380f2a7b86d4ffl,
-            0xca19ef9e40753713l },
-          { 0x52bb0d24678c38a1l,0xcc9d6fd499001c02l,0xa2dd6b00bc5876e4l,
-            0xfe04b402409fe2b3l },
-          0 },
-        /* 89 << 96 */
-        { { 0x7db986b1ff69f8d3l,0x648865e59d6266b9l,0x7ccfe96183f7dae5l,
-            0x0f59a8bd6828379bl },
-          { 0xad97e5ef0ac7c4e8l,0xa75914be784e9c18l,0x053e015bb18c1bb8l,
-            0x18f6cefcb347043el },
-          0 },
-        /* 95 << 96 */
-        { { 0xb4d641bdf257c38al,0xadcea4d0c1372574l,0x7f8d20be71c8f0d0l,
-            0x14a1d24c41dc6344l },
-          { 0xe446054e41f35526l,0x4664213823c952ddl,0xfbde483401f6b0acl,
-            0xc89eee66d75b6318l },
-          0 },
-        /* 101 << 96 */
-        { { 0x700242937a087392l,0xd42bd3aad5da04del,0xee64cb5b1f803414l,
-            0xd6341ecbbab52988l },
-          { 0x7ad522f343170a74l,0x5fba22536d61d9del,0x230304c1e845a6e5l,
-            0xd69feabfbc9e326bl },
-          0 },
-        /* 107 << 96 */
-        { { 0xef7e49412e8a11d7l,0x4cb8963662c8bae1l,0xecc741198aad5816l,
-            0x13490782c7af5175l },
-          { 0x10c701f73e91a604l,0xcb8c6c7124cc30c1l,0xce0d479c071eb382l,
-            0xa3dc71fb058087d4l },
-          0 },
-        /* 113 << 96 */
-        { { 0xec368492541eb6d1l,0x567735d6e09a94abl,0xb8039ec172350329l,
-            0x3bd83a8f4894ddafl },
-          { 0x740ef2a39c07063dl,0xba25e72277da7b59l,0xb09e248e3bf42e82l,
-            0x7ff36da0b017d037l },
-          0 },
-        /* 116 << 96 */
-        { { 0xca80416651b8d9a3l,0x42531bc90ffb0db1l,0x72ce4718aa82e7cel,
-            0x6e199913df574741l },
-          { 0xd5f1b13dd5d36946l,0x8255dc65f68f0194l,0xdc9df4cd8710d230l,
-            0x3453c20f138c1988l },
-          0 },
-        /* 119 << 96 */
-        { { 0x913f23b9ed08ac04l,0x18e336643590d098l,0xd3f72934e67536dcl,
-            0xf949a757ec7ecde9l },
-          { 0x37fc6583cf9cbd37l,0xcbe62cc043b1228el,0x777124948a743274l,
-            0x3ea3668c716ce6f1l },
-          0 },
-        /* 125 << 96 */
-        { { 0xc89ce010a90d375bl,0x39ac669340503fe3l,0x9036f782d33ecb0el,
-            0x5190656841fdc7d1l },
-          { 0xbefd136e917d94cdl,0x05fea2f22a511b24l,0x80e62d76f9076e0cl,
-            0x8c57635e418ba653l },
-          0 },
-    },
-    {
-        /* 0 << 104 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 104 */
-        { { 0x20d3c982cf7d62d2l,0x1f36e29d23ba8150l,0x48ae0bf092763f9el,
-            0x7a527e6b1d3a7007l },
-          { 0xb4a89097581a85e3l,0x1f1a520fdc158be5l,0xf98db37d167d726el,
-            0x8802786e1113e862l },
-          0 },
-        /* 3 << 104 */
-        { { 0xf6e894d1f4c6b6ecl,0x526b082718b3cd9bl,0x73f952a812117fbfl,
-            0x2be864b011945bf5l },
-          { 0x86f18ea542099b64l,0x2770b28a07548ce2l,0x97390f28295c1c9cl,
-            0x672e6a43cb5206c3l },
-          0 },
-        /* 4 << 104 */
-        { { 0xc37c7dd0c55c4496l,0xa6a9635725bbabd2l,0x5b7e63f2add7f363l,
-            0x9dce37822e73f1dfl },
-          { 0xe1e5a16ab2b91f71l,0xe44898235ba0163cl,0xf2759c32f6e515adl,
-            0xa5e2f1f88615eecfl },
-          0 },
-        /* 5 << 104 */
-        { { 0xcacce2c847c64367l,0x6a496b9f45af4ec0l,0x2a0836f36034042cl,
-            0x14a1f3900b6c62eal },
-          { 0xe7fa93633ef1f540l,0xd323b30a72a76d93l,0xffeec8b50feae451l,
-            0x4eafc172bd04ef87l },
-          0 },
-        /* 7 << 104 */
-        { { 0xe4435a51b3e59b89l,0x136139554133a1c9l,0x87f46973440bee59l,
-            0x714710f800c401e4l },
-          { 0xc0cf4bced6c446c9l,0xe0aa7fd66c4d5368l,0xde5d811afc68fc37l,
-            0x61febd72b7c2a057l },
-          0 },
-        /* 9 << 104 */
-        { { 0x27375fe665f837e2l,0x93f8c68bd882179fl,0x584feadc59b16187l,
-            0xe5b50be9483bc162l },
-          { 0x7ad9d6f1a2776625l,0xe9d1008004ff457bl,0x5b56d322677618a6l,
-            0x036694eae3e68673l },
-          0 },
-        /* 10 << 104 */
-        { { 0x6ca4f87e822e37bel,0x73f237b4253bda4el,0xf747f3a241190aebl,
-            0xf06fa36f804cf284l },
-          { 0x0a6bbb6efc621c12l,0x5d624b6440b80ec6l,0x4b0724257ba556f3l,
-            0x7fa0c3543e2d20a8l },
-          0 },
-        /* 11 << 104 */
-        { { 0x6feaffc51d8a4fd1l,0x59663b205f1ad208l,0xefc93cef24acb46al,
-            0x54929de05967118cl },
-          { 0x885708009acffb1cl,0x492bbf2b145639ecl,0x71f495a638f0018el,
-            0xe24365dbc2792847l },
-          0 },
-        /* 13 << 104 */
-        { { 0x4bedae86a6f29002l,0x7abedb56e034457al,0x8bf3eec6179bff2al,
-            0x9d626d57390f4e6bl },
-          { 0x653fe0e914dd6ea3l,0x7483715989bd6d08l,0x85fb05b4ebd9b03dl,
-            0x7dc3f2214a768bbcl },
-          0 },
-        /* 15 << 104 */
-        { { 0xaacc63f132b0ed8fl,0x041237242bafefd2l,0x0df9a7987e2d2a13l,
-            0x09bd13cf9c27591fl },
-          { 0xaa5f5e476e1afb50l,0xcd146a42b66eb646l,0x3f07561d1442ec3cl,
-            0x7e5471738ae8ec47l },
-          0 },
-        /* 16 << 104 */
-        { { 0x8de2b7bc453cadd6l,0x203900a7bc0bc1f8l,0xbcd86e47a6abd3afl,
-            0x911cac128502effbl },
-          { 0x2d550242ec965469l,0x0e9f769229e0017el,0x633f078f65979885l,
-            0xfb87d4494cf751efl },
-          0 },
-        /* 17 << 104 */
-        { { 0x2c3e61196c0c6cd5l,0x5e01a49a99f4aac8l,0xfa518fc92ef1565el,
-            0xf64ff8714f772366l },
-          { 0x52fcbc2b726420d0l,0x30fbf6eb76cfa9eel,0x0bd17139fa618268l,
-            0x23ed6e122087535dl },
-          0 },
-        /* 19 << 104 */
-        { { 0x76098e38bb4ccb2cl,0x44e88aeeafbad6d1l,0x5c4d286771928778l,
-            0xb1df868138534c94l },
-          { 0x67eb8f4d77ce9debl,0x2a86d0461a77c55dl,0xc327181e46a6a3e7l,
-            0x68fd611b8710e206l },
-          0 },
-        /* 21 << 104 */
-        { { 0xc093f3fc0c82bdf1l,0x21db25894f76c4a6l,0xf3dcb22ee410a7ael,
-            0x1db37114f3c22ffel },
-          { 0x9bd0a1fb58f6801dl,0x2cab103bd1b55cc8l,0x2ae1a7f5077ba4b2l,
-            0x82b46642ce5ab2b3l },
-          0 },
-        /* 23 << 104 */
-        { { 0xc8477ec52546684cl,0xe3f9387702ff02b5l,0xefb72133ae5d04cdl,
-            0x644905c339f10d02l },
-          { 0x1750c87c13d8d356l,0x0e9b8063b41e7640l,0xc7ece04f5647b05bl,
-            0x89a43da7ca9df9c4l },
-          0 },
-        /* 25 << 104 */
-        { { 0x02610ef1920eb7d9l,0x34bd2fc2e1ea1dc0l,0xcb89da255170b890l,
-            0xaaa2796461cff827l },
-          { 0xc308c9d37103ed6al,0xe82d63d5a467564al,0x94c897c4a0fa7732l,
-            0x75eb52fa64c7aa5fl },
-          0 },
-        /* 27 << 104 */
-        { { 0x52582f9cb985fcb6l,0xaaef8d9f8508a691l,0x494c2c346e505131l,
-            0x6d062362d55f30f6l },
-          { 0x70059e9122e1e32fl,0x1507c3fe9e51abb0l,0xd8aba31b2b7bda72l,
-            0x5acbc5f77b753f13l },
-          0 },
-        /* 28 << 104 */
-        { { 0x15bfb8bf5116f937l,0x7c64a586c1268943l,0x71e25cc38419a2c8l,
-            0x9fd6b0c48335f463l },
-          { 0x4bf0ba3ce8ee0e0el,0x6f6fba60298c21fal,0x57d57b39ae66bee0l,
-            0x292d513022672544l },
-          0 },
-        /* 29 << 104 */
-        { { 0x075dc81953952ff6l,0xd4d9eeda20b7384dl,0x8a81c1bfd2d6c6a5l,
-            0x319368a0db050f3bl },
-          { 0x91f476de31f1cee2l,0x1b38604500d0e17fl,0xed2081889a820384l,
-            0x8d00c411a0f1a637l },
-          0 },
-        /* 31 << 104 */
-        { { 0xb029b687a47fd8f0l,0xa531360696371a05l,0x7b84e88c5ab09140l,
-            0x87dad7c85eeb1d14l },
-          { 0xef0749b9d0edf6f3l,0x29fc7310e2ef198bl,0x01e05df5069ed399l,
-            0x121db4ecdf4e2fcal },
-          0 },
-        /* 33 << 104 */
-        { { 0xe730f3f62826bee0l,0xb9bdbe3fce332a8fl,0x1ecad11766ec00aal,
-            0x7503d835617a62d1l },
-          { 0x9f34e161b862b139l,0xde42194cf30f6a67l,0x5037a953c1e879fel,
-            0x62f321f89bda45dbl },
-          0 },
-        /* 34 << 104 */
-        { { 0xe87771d8033f2876l,0xb0186ec67d5cc3dbl,0x58e8bb803bc9bc1dl,
-            0x4d1395cc6f6ef60el },
-          { 0xa73c62d6186244a0l,0x918e5f23110a5b53l,0xed4878ca741b7eabl,
-            0x3038d71adbe03e51l },
-          0 },
-        /* 35 << 104 */
-        { { 0xcbdba27c40234d55l,0x24352b6cb3eb56c9l,0xae681b85a8e9295al,
-            0x2a6cfba1f1171664l },
-          { 0x49f045838ca40c3cl,0xe56da25c6eb0f8eal,0x8e62f86fc4341a4el,
-            0x7f68bdc64c3f947fl },
-          0 },
-        /* 36 << 104 */
-        { { 0x840204b7a93c3246l,0x21ab6069a0b9b4cdl,0xf5fa6e2bb1d64218l,
-            0x1de6ad0ef3d56191l },
-          { 0x570aaa88ff1929c7l,0xc6df4c6b640e87b5l,0xde8a74f2c65f0cccl,
-            0x8b972fd5e6f6cc01l },
-          0 },
-        /* 37 << 104 */
-        { { 0x862013c00bf22173l,0xfd004c834acd8e23l,0x50e422ca310b1649l,
-            0xe6d04de65bbe1854l },
-          { 0x651f646385761ef3l,0x3b17d38652cf85c9l,0xbdce284a5f54ecc7l,
-            0x72efcd3ec7c2106cl },
-          0 },
-        /* 39 << 104 */
-        { { 0x34324b182ff07e3el,0x29938f38f50bcb71l,0xd0e3d7b977e2bcc3l,
-            0x8e78f007c0a3292bl },
-          { 0xfa28c530005c2c00l,0x6f9c21d51faa0c5al,0x3df01abd7b9c78f3l,
-            0x0e5618c1ccaaeb7el },
-          0 },
-        /* 40 << 104 */
-        { { 0xaa6778fce7560b90l,0xb4073e61a7e824cel,0xff0d693cd642eba8l,
-            0x7ce2e57a5dccef38l },
-          { 0x89c2c7891df1ad46l,0x83a06922098346fdl,0x2d715d72da2fc177l,
-            0x7b6dd71d85b6cf1dl },
-          0 },
-        /* 41 << 104 */
-        { { 0x4601a6a492ad3889l,0xdc8e3364d9a0709fl,0x0c687f2b2c260327l,
-            0xe882af62e1a79573l },
-          { 0x0cfd00ab945d9017l,0xe6df7505d0e3c188l,0xb389a66dbde825a2l,
-            0x126d77b6bcd8e14fl },
-          0 },
-        /* 43 << 104 */
-        { { 0xc800acc7db18ec73l,0x0ebecc78d86e99efl,0x675796cdbd05bc5fl,
-            0x254498126afd7c7fl },
-          { 0x96293b695969b165l,0xd8514d83c162c8dal,0xe174f8b674a15a5cl,
-            0x880d687389a2f73cl },
-          0 },
-        /* 44 << 104 */
-        { { 0x53703a328300129fl,0x1f63766268c43bfdl,0xbcbd191300e54051l,
-            0x812fcc627bf5a8c5l },
-          { 0x3f969d5f29fb85dal,0x72f4e00a694759e8l,0x426b6e52790726b7l,
-            0x617bbc873bdbb209l },
-          0 },
-        /* 45 << 104 */
-        { { 0xf536f07cad1deb2el,0x2a13a11ea87a710el,0x0ce2ccab64f4dc96l,
-            0x16178694f5a55464l },
-          { 0x1496168da2cb3986l,0xb079a5b9d56a93a9l,0x97005e99092893d3l,
-            0x55df5ed6e8fcc6c3l },
-          0 },
-        /* 46 << 104 */
-        { { 0x511f8bb997aee317l,0x812a4096e81536a8l,0x137dfe593ac09b9bl,
-            0x0682238fba8c9a7al },
-          { 0x7072ead6aeccb4bdl,0x6a34e9aa692ba633l,0xc82eaec26fff9d33l,
-            0xfb7535121d4d2b62l },
-          0 },
-        /* 47 << 104 */
-        { { 0x821dca8bbf328b1cl,0x24596ddd5a3d6830l,0x061c4c15635b5b4cl,
-            0x0e2b3bef4fa3560al },
-          { 0xffced37498906c43l,0x10ebd174e26b3784l,0x7cd068c470039bb5l,
-            0xc47dda0f88404e59l },
-          0 },
-        /* 48 << 104 */
-        { { 0x1a0445ff1d7aadabl,0x65d38260d5f6a67cl,0x6e62fb0891cfb26fl,
-            0xef1e0fa55c7d91d6l },
-          { 0x47e7c7ba33db72cdl,0x017cbc09fa7c74b2l,0x3c931590f50a503cl,
-            0xcac54f60616baa42l },
-          0 },
-        /* 49 << 104 */
-        { { 0x7ad7d13569185235l,0x19771949fb69e030l,0xd4de9717bc45fb4fl,
-            0x5657b076167e5739l },
-          { 0x9503a71fdd27449el,0xfa2fabf73cc01347l,0xf8ecef24c83fb301l,
-            0x527012bd5a8d5078l },
-          0 },
-        /* 51 << 104 */
-        { { 0x70a550d7e6fc3a32l,0x8e5875841951fe57l,0x5e6d43eaaab9788bl,
-            0x1e406fed80599794l },
-          { 0xd8164ace9ed2557cl,0xf9648f30ff593e10l,0x53af2fd80c2ff879l,
-            0x6705993cc9409bf4l },
-          0 },
-        /* 52 << 104 */
-        { { 0x04b005b6c6458293l,0x36bb5276e8d10af7l,0xacf2dc138ee617b8l,
-            0x470d2d35b004b3d4l },
-          { 0x06790832feeb1b77l,0x2bb75c3985657f9cl,0xd70bd4edc0f60004l,
-            0xfe797ecc219b018bl },
-          0 },
-        /* 53 << 104 */
-        { { 0xeca02ebf0ef19ceel,0xac691fbe2de090a4l,0x1f3866641b374547l,
-            0xbd8018c6a12ee85fl },
-          { 0x3e851318ee63e0f1l,0x45b0c37a161987d3l,0x67fe36056eb567c4l,
-            0x07c291b563200c5bl },
-          0 },
-        /* 55 << 104 */
-        { { 0xc85535ac1a956a8al,0x7bf4d70bc0ade321l,0xaf2efc48237bc56fl,
-            0xf9bfe13e31ba97e7l },
-          { 0x2ca5fac4cf7c6c65l,0xc23b14ff03ec3e35l,0xc5109923217bcfd2l,
-            0xf02f96a1c58f32f3l },
-          0 },
-        /* 57 << 104 */
-        { { 0x3b1f715b0d0aeff4l,0xbe406d62f0d44536l,0xe413843d567bcb38l,
-            0x75b7fb43791e705al },
-          { 0x5b831d4b224f85e5l,0x3fea6659d9a35eael,0xd6f8bd097c85480bl,
-            0x2a9561a34a959267l },
-          0 },
-        /* 59 << 104 */
-        { { 0x4a96a3535a303c10l,0x9aa3ad71c37c8d7el,0x4e2d077fde52014fl,
-            0x4d8bec5df8e3964dl },
-          { 0xda88ab94e865e142l,0x52df506d10a88091l,0x9aebff0092fc38a2l,
-            0xdfc034395608b0a2l },
-          0 },
-        /* 60 << 104 */
-        { { 0xee23fa819966e7eel,0x64ec4aa805b7920dl,0x2d44462d2d90aad4l,
-            0xf44dd195df277ad5l },
-          { 0x8d6471f1bb46b6a1l,0x1e65d313fd885090l,0x33a800f513a977b4l,
-            0xaca9d7210797e1efl },
-          0 },
-        /* 61 << 104 */
-        { { 0xb1557be2a4ea787el,0x59324973019f667fl,0x262ceced5595367cl,
-            0x8a676897ec598640l },
-          { 0x2df6cebfc7f06f4fl,0xb255723138078f9al,0xad553c46524a0dd1l,
-            0xe20bb20a5a68d62al },
-          0 },
-        /* 63 << 104 */
-        { { 0x6f47e3779589e263l,0x7cb83e3d35106bb8l,0x2642d87bcc632fc2l,
-            0x4d18f34d8b77eb36l },
-          { 0x7de6bf6d19ca4d1cl,0x438e8f02f7e926aal,0xb539021250ac930al,
-            0xe34ddfc15b219a9fl },
-          0 },
-        /* 64 << 104 */
-        { { 0x98857ceb1bf4581cl,0xe635e186aca7b166l,0x278ddd22659722acl,
-            0xa0903c4c1db68007l },
-          { 0x366e458948f21402l,0x31b49c14b96abda2l,0x329c4b09e0403190l,
-            0x97197ca3d29f43fel },
-          0 },
-        /* 65 << 104 */
-        { { 0xfe4de13781479db4l,0x307331f012f08ea5l,0x7f59a64758c04c13l,
-            0x6b41189abdc9b3c9l },
-          { 0xb10f11e5a6f8c5edl,0x757fb7a3f5b0579el,0x456d0a873c90d027l,
-            0x7e8bb6bf32361796l },
-          0 },
-        /* 71 << 104 */
-        { { 0x6aa1dc6c9e689d8dl,0xaa5fa015479cdd09l,0x7eb4dbb582fc000al,
-            0x4a57b689eff4e701l },
-          { 0x7bfe8d2a8e15cd8cl,0xab109b1cc9074e1al,0x5716715fee1619a5l,
-            0xf29a51eccdcb40bcl },
-          0 },
-        /* 77 << 104 */
-        { { 0x14c76234ddf03c6el,0xdfb5d388baeb2eddl,0x4bd85da26d413d2dl,
-            0x5b0dd9be3ae38469l },
-          { 0xe4d8a9d89ab3ae61l,0xb9e37b880ee63951l,0x17f08e9b21a7f30fl,
-            0x173db1e8119af788l },
-          0 },
-        /* 83 << 104 */
-        { { 0x2352ad4a170d43f6l,0x098d74f65a0ae4b0l,0x290f5236c3a46c2al,
-            0xea9266102dd87e7fl },
-          { 0xd7ee90f6848e6911l,0xebe8f4cce0d8886fl,0xa2038320558ff6a0l,
-            0x1f716534f37c38cfl },
-          0 },
-        /* 89 << 104 */
-        { { 0x9754209439a4a159l,0xe6135412fed24278l,0xbba62254d70e2cabl,
-            0x4ac6a8ac85895130l },
-          { 0xc01614fee1a45363l,0x720ad3f8b67294f2l,0x724ea95cb420ea51l,
-            0x1f40ab2d712b856cl },
-          0 },
-        /* 95 << 104 */
-        { { 0x708e1c7975f3d30cl,0x423f1535e2172da3l,0x7a29be342a06a0b1l,
-            0x9de5c9eb32c68ba2l },
-          { 0x70217b0232d48793l,0x3cf3855bac1471cfl,0x6762d03f8321e179l,
-            0x06ee12ea236fa7cfl },
-          0 },
-        /* 101 << 104 */
-        { { 0x1718e7428779109bl,0x6188008d0aca350bl,0xbbe227e00594bc15l,
-            0x4a7b6423ddbdea35l },
-          { 0x06ad632dfa44e1bfl,0xaf9c163d1e97b409l,0x64dafec3c61f2b2fl,
-            0xc6759d905525c0c9l },
-          0 },
-        /* 107 << 104 */
-        { { 0x76d6294787517149l,0x2bda339baa77d325l,0x04b1bec067ad1fd1l,
-            0x49f63fcc0aec7c73l },
-          { 0x005cb459ec1bf494l,0x8fa99c1b1ec6f8bbl,0x70a4e6d78b59dd43l,
-            0xfd70bcb313d6594dl },
-          0 },
-        /* 113 << 104 */
-        { { 0x2987a7cb13966c11l,0x74ad0a26a783f283l,0xf011200ae54d27f0l,
-            0xbd8632963fb38396l },
-          { 0x7ec7fe8c9b86d059l,0xfa94ca76d0cd33a7l,0xf6ad741cdc646993l,
-            0x83054a427ebc34e9l },
-          0 },
-        /* 116 << 104 */
-        { { 0xadef8c5a192ef710l,0x88afbd4b3b7431f9l,0x7e1f740764250c9el,
-            0x6e31318db58bec07l },
-          { 0xfd4fc4b824f89b4el,0x65a5dd8848c36a2al,0x4f1eccfff024baa7l,
-            0x22a21cf2cba94650l },
-          0 },
-        /* 119 << 104 */
-        { { 0x7b45865478f39754l,0xcbb8b96c4564e003l,0xb492d2bf69b35752l,
-            0x4e6287e065ee5ad3l },
-          { 0x07906c14eb1ffe62l,0xf350390c681fcdf8l,0xc351386f6be3eec3l,
-            0x8480d00ee5df919dl },
-          0 },
-        /* 125 << 104 */
-        { { 0x399861ecf8a2d5aal,0xb179adeb046f78cbl,0x056a6cd88792f647l,
-            0xd3dfc91c3d411820l },
-          { 0x4ccf92d179693be1l,0x12ecd9a3f65cb250l,0x58e5d2102538b9e7l,
-            0x4e655882ff977ccal },
-          0 },
-    },
-    {
-        /* 0 << 112 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 112 */
-        { { 0x8ce9b6bfc360e25al,0xe6425195075a1a78l,0x9dc756a8481732f4l,
-            0x83c0440f5432b57al },
-          { 0xc670b3f1d720281fl,0x2205910ed135e051l,0xded14b0edb052be7l,
-            0x697b3d27c568ea39l },
-          0 },
-        /* 3 << 112 */
-        { { 0x0b89de9314092ebbl,0xf17256bd428e240cl,0xcf89a7f393d2f064l,
-            0x4f57841ee1ed3b14l },
-          { 0x4ee14405e708d855l,0x856aae7203f1c3d0l,0xc8e5424fbdd7eed5l,
-            0x3333e4ef73ab4270l },
-          0 },
-        /* 4 << 112 */
-        { { 0x3bc77adedda492f8l,0xc11a3aea78297205l,0x5e89a3e734931b4cl,
-            0x17512e2e9f5694bbl },
-          { 0x5dc349f3177bf8b6l,0x232ea4ba08c7ff3el,0x9c4f9d16f511145dl,
-            0xccf109a333b379c3l },
-          0 },
-        /* 5 << 112 */
-        { { 0xe75e7a88a1f25897l,0x7ac6961fa1b5d4d8l,0xe3e1077308f3ed5cl,
-            0x208a54ec0a892dfbl },
-          { 0xbe826e1978660710l,0x0cf70a97237df2c8l,0x418a7340ed704da5l,
-            0xa3eeb9a908ca33fdl },
-          0 },
-        /* 7 << 112 */
-        { { 0xb4323d588434a920l,0xc0af8e93622103c5l,0x667518ef938dbf9al,
-            0xa184307383a9cdf2l },
-          { 0x350a94aa5447ab80l,0xe5e5a325c75a3d61l,0x74ba507f68411a9el,
-            0x10581fc1594f70c5l },
-          0 },
-        /* 9 << 112 */
-        { { 0x5aaa98a7cb0c9c8cl,0x75105f3081c4375cl,0xceee50575ef1c90fl,
-            0xb31e065fc23a17bfl },
-          { 0x5364d275d4b6d45al,0xd363f3ad62ec8996l,0xb5d212394391c65bl,
-            0x84564765ebb41b47l },
-          0 },
-        /* 10 << 112 */
-        { { 0x20d18ecc37107c78l,0xacff3b6b570c2a66l,0x22f975d99bd0d845l,
-            0xef0a0c46ba178fa0l },
-          { 0x1a41965176b6028el,0xc49ec674248612d4l,0x5b6ac4f27338af55l,
-            0x06145e627bee5a36l },
-          0 },
-        /* 11 << 112 */
-        { { 0x33e95d07e75746b5l,0x1c1e1f6dc40c78bel,0x967833ef222ff8e2l,
-            0x4bedcf6ab49180adl },
-          { 0x6b37e9c13d7a4c8al,0x2748887c6ddfe760l,0xf7055123aa3a5bbcl,
-            0x954ff2257bbb8e74l },
-          0 },
-        /* 13 << 112 */
-        { { 0x4e23ca446d3fea55l,0xb4ae9c86f4810568l,0x47bfb91b2a62f27dl,
-            0x60deb4c9d9bac28cl },
-          { 0xa892d8947de6c34cl,0x4ee682594494587dl,0x914ee14e1a3f8a5bl,
-            0xbb113eaa28700385l },
-          0 },
-        /* 15 << 112 */
-        { { 0xef9dc899a7b56eafl,0x00c0e52c34ef7316l,0x5b1e4e24fe818a86l,
-            0x9d31e20dc538be47l },
-          { 0x22eb932d3ed68974l,0xe44bbc087c4e87c4l,0x4121086e0dde9aefl,
-            0x8e6b9cff134f4345l },
-          0 },
-        /* 16 << 112 */
-        { { 0x96892c1f711b0eb9l,0xb905f2c8780ab954l,0xace26309a20792dbl,
-            0xec8ac9b30684e126l },
-          { 0x486ad8b6b40a2447l,0x60121fc19fe3fb24l,0x5626fccf1a8e3b3fl,
-            0x4e5686226ad1f394l },
-          0 },
-        /* 17 << 112 */
-        { { 0xda7aae0d196aa5a1l,0xe0df8c771041b5fbl,0x451465d926b318b7l,
-            0xc29b6e557ab136e9l },
-          { 0x2c2ab48b71148463l,0xb5738de364454a76l,0x54ccf9a05a03abe4l,
-            0x377c02960427d58el },
-          0 },
-        /* 19 << 112 */
-        { { 0x90e4f7c92d7d1413l,0x67e2d6b59834f597l,0x4fd4f4f9a808c3e8l,
-            0xaf8237e0d5281ec1l },
-          { 0x25ab5fdc84687ceel,0xc5ded6b1a5b26c09l,0x8e4a5aecc8ea7650l,
-            0x23b73e5c14cc417fl },
-          0 },
-        /* 21 << 112 */
-        { { 0xb4293fdcf50225f9l,0xc52e175cb0e12b03l,0xf649c3bad0a8bf64l,
-            0x745a8fefeb8ae3c6l },
-          { 0x30d7e5a358321bc3l,0xb1732be70bc4df48l,0x1f217993e9ea5058l,
-            0xf7a71cde3e4fd745l },
-          0 },
-        /* 23 << 112 */
-        { { 0xa188b2502d0f39aal,0x622118bb15a85947l,0x2ebf520ffde0f4fal,
-            0xa40e9f294860e539l },
-          { 0x7b6a51eb22b57f0fl,0x849a33b97e80644al,0x50e5d16f1cf095fel,
-            0xd754b54eec55f002l },
-          0 },
-        /* 25 << 112 */
-        { { 0xcd821dfb988baf01l,0xe6331a7ddbb16647l,0x1eb8ad33094cb960l,
-            0x593cca38c91bbca5l },
-          { 0x384aac8d26567456l,0x40fa0309c04b6490l,0x97834cd6dab6c8f6l,
-            0x68a7318d3f91e55fl },
-          0 },
-        /* 27 << 112 */
-        { { 0xc7bfd486605daaa6l,0x46fd72b7bb9a6c9el,0xe4847fb1a124fb89l,
-            0x75959cbda2d8ffbcl },
-          { 0x42579f65c8a588eel,0x368c92e6b80b499dl,0xea4ef6cd999a5df1l,
-            0xaa73bb7f936fe604l },
-          0 },
-        /* 28 << 112 */
-        { { 0xf347a70d6457d188l,0x86eda86b8b7a388bl,0xb7cdff060ccd6013l,
-            0xbeb1b6c7d0053fb2l },
-          { 0x0b02238799240a9fl,0x1bbb384f776189b2l,0x8695e71e9066193al,
-            0x2eb5009706ffac7el },
-          0 },
-        /* 29 << 112 */
-        { { 0x0654a9c04a7d2caal,0x6f3fb3d1a5aaa290l,0x835db041ff476e8fl,
-            0x540b8b0bc42295e4l },
-          { 0xa5c73ac905e214f5l,0x9a74075a56a0b638l,0x2e4b1090ce9e680bl,
-            0x57a5b4796b8d9afal },
-          0 },
-        /* 31 << 112 */
-        { { 0x2a2bfa7f650006f0l,0xdfd7dad350c0fbb2l,0x92452495ccf9ad96l,
-            0x183bf494d95635f9l },
-          { 0x02d5df434a7bd989l,0x505385cca5431095l,0xdd98e67dfd43f53el,
-            0xd61e1a6c500c34a9l },
-          0 },
-        /* 33 << 112 */
-        { { 0x41d85ea1ef74c45bl,0x2cfbfa66ae328506l,0x98b078f53ada7da9l,
-            0xd985fe37ec752fbbl },
-          { 0xeece68fe5a0148b4l,0x6f9a55c72d78136dl,0x232dccc4d2b729cel,
-            0xa27e0dfd90aafbc4l },
-          0 },
-        /* 34 << 112 */
-        { { 0x9647445212b4603el,0xa876c5516b706d14l,0xdf145fcf69a9d412l,
-            0xe2ab75b72d479c34l },
-          { 0x12df9a761a23ff97l,0xc61389925d359d10l,0x6e51c7aefa835f22l,
-            0x69a79cb1c0fcc4d9l },
-          0 },
-        /* 35 << 112 */
-        { { 0xf57f350d594cc7e1l,0x3079ca633350ab79l,0x226fb6149aff594al,
-            0x35afec026d59a62bl },
-          { 0x9bee46f406ed2c6el,0x58da17357d939a57l,0x44c504028fd1797el,
-            0xd8853e7c5ccea6cal },
-          0 },
-        /* 36 << 112 */
-        { { 0x4065508da35fcd5fl,0x8965df8c495ccaebl,0x0f2da85012e1a962l,
-            0xee471b94c1cf1cc4l },
-          { 0xcef19bc80a08fb75l,0x704958f581de3591l,0x2867f8b23aef4f88l,
-            0x8d749384ea9f9a5fl },
-          0 },
-        /* 37 << 112 */
-        { { 0x1b3855378c9049f4l,0x5be948f37b92d8b6l,0xd96f725db6e2bd6bl,
-            0x37a222bc958c454dl },
-          { 0xe7c61abb8809bf61l,0x46f07fbc1346f18dl,0xfb567a7ae87c0d1cl,
-            0x84a461c87ef3d07al },
-          0 },
-        /* 39 << 112 */
-        { { 0x3ab3d5afbd76e195l,0x478dd1ad6938a810l,0x6ffab3936ee3d5cbl,
-            0xdfb693db22b361e4l },
-          { 0xf969449651dbf1a7l,0xcab4b4ef08a2e762l,0xe8c92f25d39bba9al,
-            0x850e61bcf1464d96l },
-          0 },
-        /* 40 << 112 */
-        { { 0xb7e830e3dc09508bl,0xfaf6d2cf74317655l,0x72606cebdf690355l,
-            0x48bb92b3d0c3ded6l },
-          { 0x65b754845c7cf892l,0xf6cd7ac9d5d5f01fl,0xc2c30a5996401d69l,
-            0x91268650ed921878l },
-          0 },
-        /* 41 << 112 */
-        { { 0x380bf913b78c558fl,0x43c0baebc8afdaa9l,0x377f61d554f169d3l,
-            0xf8da07e3ae5ff20bl },
-          { 0xb676c49da8a90ea8l,0x81c1ff2b83a29b21l,0x383297ac2ad8d276l,
-            0x3001122fba89f982l },
-          0 },
-        /* 43 << 112 */
-        { { 0xbbe1e6a6c93f72d6l,0xd5f75d12cad800eal,0xfa40a09fe7acf117l,
-            0x32c8cdd57581a355l },
-          { 0x742219927023c499l,0xa8afe5d738ec3901l,0x5691afcba90e83f0l,
-            0x41bcaa030b8f8eacl },
-          0 },
-        /* 44 << 112 */
-        { { 0xe38b5ff98d2668d5l,0x0715281a7ad81965l,0x1bc8fc7c03c6ce11l,
-            0xcbbee6e28b650436l },
-          { 0x06b00fe80cdb9808l,0x17d6e066fe3ed315l,0x2e9d38c64d0b5018l,
-            0xab8bfd56844dcaefl },
-          0 },
-        /* 45 << 112 */
-        { { 0x42894a59513aed8bl,0xf77f3b6d314bd07al,0xbbdecb8f8e42b582l,
-            0xf10e2fa8d2390fe6l },
-          { 0xefb9502262a2f201l,0x4d59ea5050ee32b0l,0xd87f77286da789a8l,
-            0xcf98a2cff79492c4l },
-          0 },
-        /* 46 << 112 */
-        { { 0xf9577239720943c2l,0xba044cf53990b9d0l,0x5aa8e82395f2884al,
-            0x834de6ed0278a0afl },
-          { 0xc8e1ee9a5f25bd12l,0x9259ceaa6f7ab271l,0x7e6d97a277d00b76l,
-            0x5c0c6eeaa437832al },
-          0 },
-        /* 47 << 112 */
-        { { 0x5232c20f5606b81dl,0xabd7b3750d991ee5l,0x4d2bfe358632d951l,
-            0x78f8514698ed9364l },
-          { 0x951873f0f30c3282l,0x0da8ac80a789230bl,0x3ac7789c5398967fl,
-            0xa69b8f7fbdda0fb5l },
-          0 },
-        /* 48 << 112 */
-        { { 0xe5db77176add8545l,0x1b71cb6672c49b66l,0xd856073968421d77l,
-            0x03840fe883e3afeal },
-          { 0xb391dad51ec69977l,0xae243fb9307f6726l,0xc88ac87be8ca160cl,
-            0x5174cced4ce355f4l },
-          0 },
-        /* 49 << 112 */
-        { { 0x98a35966e58ba37dl,0xfdcc8da27817335dl,0x5b75283083fbc7bfl,
-            0x68e419d4d9c96984l },
-          { 0x409a39f402a40380l,0x88940faf1fe977bcl,0xc640a94b8f8edea6l,
-            0x1e22cd17ed11547dl },
-          0 },
-        /* 51 << 112 */
-        { { 0x17ba93b1a20ef103l,0xad8591306ba6577bl,0x65c91cf66fa214a0l,
-            0xd7d49c6c27990da5l },
-          { 0xecd9ec8d20bb569dl,0xbd4b2502eeffbc33l,0x2056ca5a6bed0467l,
-            0x7916a1f75b63728cl },
-          0 },
-        /* 52 << 112 */
-        { { 0xd4f9497d53a4f566l,0x8973466497b56810l,0xf8e1da740494a621l,
-            0x82546a938d011c68l },
-          { 0x1f3acb19c61ac162l,0x52f8fa9cabad0d3el,0x15356523b4b7ea43l,
-            0x5a16ad61ae608125l },
-          0 },
-        /* 53 << 112 */
-        { { 0xb0bcb87f4faed184l,0x5f236b1d5029f45fl,0xd42c76070bc6b1fcl,
-            0xc644324e68aefce3l },
-          { 0x8e191d595c5d8446l,0xc020807713ae1979l,0xadcaee553ba59cc7l,
-            0x20ed6d6ba2cb81bal },
-          0 },
-        /* 55 << 112 */
-        { { 0x7392b41a530ccbbdl,0x87c82146ea823525l,0xa52f984c05d98d0cl,
-            0x2ae57d735ef6974cl },
-          { 0x9377f7bf3042a6ddl,0xb1a007c019647a64l,0xfaa9079a0cca9767l,
-            0x3d81a25bf68f72d5l },
-          0 },
-        /* 57 << 112 */
-        { { 0xc110d830b0f2ac95l,0x48d0995aab20e64el,0x0f3e00e17729cd9al,
-            0x2a570c20dd556946l },
-          { 0x912dbcfd4e86214dl,0x2d014ee2cf615498l,0x55e2b1e63530d76el,
-            0xc5135ae4fd0fd6d1l },
-          0 },
-        /* 59 << 112 */
-        { { 0x1854daa5061f1658l,0xc0016df1df0cd2b3l,0xc2a3f23e833d50del,
-            0x73b681d2bbbd3017l },
-          { 0x2f046dc43ac343c0l,0x9c847e7d85716421l,0xe1e13c910917eed4l,
-            0x3fc9eebd63a1b9c6l },
-          0 },
-        /* 60 << 112 */
-        { { 0x0f816a727fe02299l,0x6335ccc2294f3319l,0x3820179f4745c5bel,
-            0xe647b782922f066el },
-          { 0xc22e49de02cafb8al,0x299bc2fffcc2ecccl,0x9a8feea26e0e8282l,
-            0xa627278bfe893205l },
-          0 },
-        /* 61 << 112 */
-        { { 0xa7e197337933e47bl,0xf4ff6b132e766402l,0xa4d8be0a98440d9fl,
-            0x658f5c2f38938808l },
-          { 0x90b75677c95b3b3el,0xfa0442693137b6ffl,0x077b039b43c47c29l,
-            0xcca95dd38a6445b2l },
-          0 },
-        /* 63 << 112 */
-        { { 0x583f3703f9374ab6l,0x864f91956e564145l,0x33bc3f4822526d50l,
-            0x9f323c801262a496l },
-          { 0xaa97a7ae3f046a9al,0x70da183edf8a039al,0x5b68f71c52aa0ba6l,
-            0x9be0fe5121459c2dl },
-          0 },
-        /* 64 << 112 */
-        { { 0xc1e17eb6cbc613e5l,0x33131d55497ea61cl,0x2f69d39eaf7eded5l,
-            0x73c2f434de6af11bl },
-          { 0x4ca52493a4a375fal,0x5f06787cb833c5c2l,0x814e091f3e6e71cfl,
-            0x76451f578b746666l },
-          0 },
-        /* 65 << 112 */
-        { { 0xa700767eabd0cc76l,0xa14ae98015889273l,0x5acf2cc466ea6380l,
-            0xb942cc40d08d18b9l },
-          { 0x9b5daa763ae45782l,0x61a25e0fb72f0ce0l,0xf94c0e80435fefe3l,
-            0x73d552cf1620e1c9l },
-          0 },
-        /* 71 << 112 */
-        { { 0x57130582727185c1l,0x8f2b8ebc163897ecl,0x4a059cc7a04e4a6bl,
-            0x4b1de9fe0908a366l },
-          { 0xa4f7738688d0fef0l,0x55e3bb1d9ebfc138l,0x9022bbef005ae362l,
-            0xf5669edc8741d349l },
-          0 },
-        /* 77 << 112 */
-        { { 0xf192c0f7ede937a4l,0xd2e91d62810c1b1el,0xf2b40b64dcc39c69l,
-            0xe125fbd028f03b0el },
-          { 0x52966dd78da708f9l,0x92d400a3cc0e7f32l,0x4e35aae36b0842b8l,
-            0x0b4fe66ded3ad3cfl },
-          0 },
-        /* 83 << 112 */
-        { { 0x14b81d951f1ff6b5l,0x1d82f132ed9b03b8l,0x52f6f029b4fa4047l,
-            0xea653682601e5913l },
-          { 0x4e900375edeee046l,0xd22ed267f9428714l,0xb004fb3b1753e873l,
-            0xfef061ba245b2c09l },
-          0 },
-        /* 89 << 112 */
-        { { 0x5e2376eaf9deba2bl,0x1ed1e9e5269a18cfl,0x8dffd66dcb1cada8l,
-            0xb13239f068369c77l },
-          { 0x2fede3a67f25426fl,0xc885cf0c6f90a2a6l,0xd950162d4eeac543l,
-            0x53011aa09abc201bl },
-          0 },
-        /* 95 << 112 */
-        { { 0x7a63925d432b798al,0x92e762cfc9bd6da9l,0xf22fb9706a190382l,
-            0x19919b847b18a9b3l },
-          { 0x16793b803adfde86l,0xf9ce15ace8b1d44cl,0x4bf74144c0a140b8l,
-            0x680468616f853f6cl },
-          0 },
-        /* 101 << 112 */
-        { { 0xd4e0d8460db84ba2l,0x9a162a3a360b68bbl,0x7297f3939233146cl,
-            0xbc93c2f4ec77412dl },
-          { 0x13ddf0a7e07e1065l,0x000a8d45fb5e5131l,0xb4373078cf61d467l,
-            0xa4a1fd67bf3bb6f9l },
-          0 },
-        /* 107 << 112 */
-        { { 0x6f2473f9d7585098l,0x45a29448d4f23c1al,0x47fe40f1c22bdc25l,
-            0x4e46ed1f31347673l },
-          { 0x5e43a8624148898cl,0x4a02ededa993954el,0x83d830b52f8a1847l,
-            0x007e3156a7f6a378l },
-          0 },
-        /* 113 << 112 */
-        { { 0x01a39fe7e847ca18l,0xaf2722418fed2772l,0x3104ef891fbb1748l,
-            0x5b55331b2b9dd5ffl },
-          { 0xe7806e31cec6a787l,0x9f49ed881e9c0af2l,0xf5a66373a3905b36l,
-            0x77b5bca9efab75f3l },
-          0 },
-        /* 116 << 112 */
-        { { 0xd4d75f4bf0831932l,0x5e770ac477fe8cc9l,0x52b5e748862e72a2l,
-            0xe9a45482501d35fel },
-          { 0x8a93e7424a9ab187l,0x5a72506de88ca017l,0xe680dcb201eb2defl,
-            0xdc5aa4e6ba68209dl },
-          0 },
-        /* 119 << 112 */
-        { { 0x2defa3dc3d01a344l,0x11fd939b162e459al,0x928453b97313d720l,
-            0x08696dc053184a65l },
-          { 0xd9f8a69c721f7415l,0x304eb0e079539019l,0xc9b0ca6dbb0c6313l,
-            0xa10133eba93dc74el },
-          0 },
-        /* 125 << 112 */
-        { { 0xee0b164004393f1el,0x511547dfe1301979l,0xc00dfc3516d26d87l,
-            0x06227c8aab847494l },
-          { 0x178ca86748b2fdc7l,0xb51296f01a8ba1dcl,0xf252787731e1dd14l,
-            0x7ecb5456c0ba2a1fl },
-          0 },
-    },
-    {
-        /* 0 << 120 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 120 */
-        { { 0x3e0e5c9dd111f8ecl,0xbcc33f8db7c4e760l,0x702f9a91bd392a51l,
-            0x7da4a795c132e92dl },
-          { 0x1a0b0ae30bb1151bl,0x54febac802e32251l,0xea3a5082694e9e78l,
-            0xe58ffec1e4fe40b8l },
-          0 },
-        /* 3 << 120 */
-        { { 0x7b23c513516e19e4l,0x56e2e847c5c4d593l,0x9f727d735ce71ef6l,
-            0x5b6304a6f79a44c5l },
-          { 0x6638a7363ab7e433l,0x1adea470fe742f83l,0xe054b8545b7fc19fl,
-            0xf935381aba1d0698l },
-          0 },
-        /* 4 << 120 */
-        { { 0xb5504f9d918e4936l,0x65035ef6b2513982l,0x0553a0c26f4d9cb9l,
-            0x6cb10d56bea85509l },
-          { 0x48d957b7a242da11l,0x16a4d3dd672b7268l,0x3d7e637c8502a96bl,
-            0x27c7032b730d463bl },
-          0 },
-        /* 5 << 120 */
-        { { 0x55366b7d5846426fl,0xe7d09e89247d441dl,0x510b404d736fbf48l,
-            0x7fa003d0e784bd7dl },
-          { 0x25f7614f17fd9596l,0x49e0e0a135cb98dbl,0x2c65957b2e83a76al,
-            0x5d40da8dcddbe0f8l },
-          0 },
-        /* 7 << 120 */
-        { { 0x9fb3bba354530bb2l,0xbde3ef77cb0869eal,0x89bc90460b431163l,
-            0x4d03d7d2e4819a35l },
-          { 0x33ae4f9e43b6a782l,0x216db3079c88a686l,0x91dd88e000ffedd9l,
-            0xb280da9f12bd4840l },
-          0 },
-        /* 9 << 120 */
-        { { 0xa37f3573f37f5937l,0xeb0f6c7dd1e4fca5l,0x2965a554ac8ab0fcl,
-            0x17fbf56c274676acl },
-          { 0x2e2f6bd9acf7d720l,0x41fc8f8810224766l,0x517a14b385d53befl,
-            0xdae327a57d76a7d1l },
-          0 },
-        /* 10 << 120 */
-        { { 0x515d5c891f5f82dcl,0x9a7f67d76361079el,0xa8da81e311a35330l,
-            0xe44990c44b18be1bl },
-          { 0xc7d5ed95af103e59l,0xece8aba78dac9261l,0xbe82b0999394b8d3l,
-            0x6830f09a16adfe83l },
-          0 },
-        /* 11 << 120 */
-        { { 0x43c41ac194d7d9b1l,0x5bafdd82c82e7f17l,0xdf0614c15fda0fcal,
-            0x74b043a7a8ae37adl },
-          { 0x3ba6afa19e71734cl,0x15d5437e9c450f2el,0x4a5883fe67e242b1l,
-            0x5143bdc22c1953c2l },
-          0 },
-        /* 13 << 120 */
-        { { 0xc676d7f2b1f3390bl,0x9f7a1b8ca5b61272l,0x4ebebfc9c2e127a9l,
-            0x4602500c5dd997bfl },
-          { 0x7f09771c4711230fl,0x058eb37c020f09c1l,0xab693d4bfee5e38bl,
-            0x9289eb1f4653cbc0l },
-          0 },
-        /* 15 << 120 */
-        { { 0x54da9dc7ab952578l,0xb5423df226e84d0bl,0xa8b64eeb9b872042l,
-            0xac2057825990f6dfl },
-          { 0x4ff696eb21f4c77al,0x1a79c3e4aab273afl,0x29bc922e9436b3f1l,
-            0xff807ef8d6d9a27al },
-          0 },
-        /* 16 << 120 */
-        { { 0xc7f3a8f833f6746cl,0x21e46f65fea990cal,0x915fd5c5caddb0a9l,
-            0xbd41f01678614555l },
-          { 0x346f4434426ffb58l,0x8055943614dbc204l,0xf3dd20fe5a969b7fl,
-            0x9d59e956e899a39al },
-          0 },
-        /* 17 << 120 */
-        { { 0xe4ca688fd06f56c0l,0xa48af70ddf027972l,0x691f0f045e9a609dl,
-            0xa9dd82cdee61270el },
-          { 0x8903ca63a0ef18d3l,0x9fb7ee353d6ca3bdl,0xa7b4a09cabf47d03l,
-            0x4cdada011c67de8el },
-          0 },
-        /* 19 << 120 */
-        { { 0xac127dc1e038a675l,0x729deff38c5c6320l,0xb7df8fd4a90d2c53l,
-            0x9b74b0ec681e7cd3l },
-          { 0x5cb5a623dab407e5l,0xcdbd361576b340c6l,0xa184415a7d28392cl,
-            0xc184c1d8e96f7830l },
-          0 },
-        /* 21 << 120 */
-        { { 0x86a9303b2f7e85c3l,0x5fce462171988f9bl,0x5b935bf6c138acb5l,
-            0x30ea7d6725661212l },
-          { 0xef1eb5f4e51ab9a2l,0x0587c98aae067c78l,0xb3ce1b3c77ca9ca6l,
-            0x2a553d4d54b5f057l },
-          0 },
-        /* 23 << 120 */
-        { { 0x2c7156e10b1894a0l,0x92034001d81c68c0l,0xed225d00c8b115b5l,
-            0x237f9c2283b907f2l },
-          { 0x0ea2f32f4470e2c0l,0xb725f7c158be4e95l,0x0f1dcafab1ae5463l,
-            0x59ed51871ba2fc04l },
-          0 },
-        /* 25 << 120 */
-        { { 0xd1b0ccdec9520711l,0x55a9e4ed3c8b84bfl,0x9426bd39a1fef314l,
-            0x4f5f638e6eb93f2bl },
-          { 0xba2a1ed32bf9341bl,0xd63c13214d42d5a9l,0xd2964a89316dc7c5l,
-            0xd1759606ca511851l },
-          0 },
-        /* 27 << 120 */
-        { { 0xedf69feaf8c51187l,0x05bb67ec741e4da7l,0x47df0f3208114345l,
-            0x56facb07bb9792b1l },
-          { 0xf3e007e98f6229e4l,0x62d103f4526fba0fl,0x4f33bef7b0339d79l,
-            0x9841357bb59bfec1l },
-          0 },
-        /* 28 << 120 */
-        { { 0xae1e0b67e28ef5bal,0x2c9a4699cb18e169l,0x0ecd0e331e6bbd20l,
-            0x571b360eaf5e81d2l },
-          { 0xcd9fea58101c1d45l,0x6651788e18880452l,0xa99726351f8dd446l,
-            0x44bed022e37281d0l },
-          0 },
-        /* 29 << 120 */
-        { { 0x830e6eea60dbac1fl,0x23d8c484da06a2f7l,0x896714b050ca535bl,
-            0xdc8d3644ebd97a9bl },
-          { 0x106ef9fab12177b4l,0xf79bf464534d5d9cl,0x2537a349a6ab360bl,
-            0xc7c54253a00c744fl },
-          0 },
-        /* 31 << 120 */
-        { { 0x24d661d168754ab0l,0x801fce1d6f429a76l,0xc068a85fa58ce769l,
-            0xedc35c545d5eca2bl },
-          { 0xea31276fa3f660d1l,0xa0184ebeb8fc7167l,0x0f20f21a1d8db0ael,
-            0xd96d095f56c35e12l },
-          0 },
-        /* 33 << 120 */
-        { { 0x57d2046b59da06ebl,0x3c076d5fa49f6d74l,0x6b4c96e616f82ea0l,
-            0xaf7b0f1f90536c0bl },
-          { 0x7999f86d204a9b2dl,0x7e420264126c9f87l,0x4c967a1f262ac4e5l,
-            0xe8174a09900e79adl },
-          0 },
-        /* 34 << 120 */
-        { { 0xd51687f2cb82516bl,0x8a440cfc040e4670l,0xeafd2bcfe7738d32l,
-            0x7071e9162a1e911al },
-          { 0xbd3abd44cfea57bbl,0x9c3add16085b19e2l,0xb194c01d6baa5aa6l,
-            0x6f3d3faf92f85c64l },
-          0 },
-        /* 35 << 120 */
-        { { 0xe23e0769488a280el,0x8e55a728e63a5904l,0x01690716ab84cccfl,
-            0xfe796130b78b3c98l },
-          { 0x15cc475b9117f211l,0xbdc178761d1b9d56l,0x8df5594a3e37b9b9l,
-            0x97747e341e37e494l },
-          0 },
-        /* 36 << 120 */
-        { { 0xf2a6370ed2f896e1l,0x27100e63802987afl,0xb4db1cff4678ebc7l,
-            0x6e5f28d937b4b263l },
-          { 0xd29030009711ebc4l,0xf14dcb9ff8712484l,0x7a46ec3eea449146l,
-            0x200155e9c1c51179l },
-          0 },
-        /* 37 << 120 */
-        { { 0x8130f007f1968d55l,0x18823e7097ed9803l,0xdc9fec559402762dl,
-            0x9e0bd57e278f5abbl },
-          { 0xaa41b913c9ebf303l,0x1105ec43a76b9353l,0xf8e4ee4cf4e6c6b5l,
-            0x3a630972bd7be696l },
-          0 },
-        /* 39 << 120 */
-        { { 0x5c7da7e16356b3eel,0x951bfe458ccf9b48l,0x6f2c6e91d0555d0cl,
-            0x47d7f7b58efd38eel },
-          { 0x957256c8af6fd630l,0xa690c65bdc01774cl,0xad52b27c7c8dafdal,
-            0x81fbc16af44a145fl },
-          0 },
-        /* 40 << 120 */
-        { { 0x497c3a3481b0493al,0x2b3ab20d71bc8408l,0x0c60226aa03769d1l,
-            0x4ac89c7ad10708b0l },
-          { 0x62398ea5092f7e6al,0x7f408f54de96d526l,0x025bde6f85bf102cl,
-            0xcc2f85120a4aa72el },
-          0 },
-        /* 41 << 120 */
-        { { 0x8a65e0386884a9c3l,0xd2e6ac047bf8c794l,0xc9c5d3d3f7bcdfb9l,
-            0x0000ce42a33f2c12l },
-          { 0xea1c0a9a7dd13b2bl,0xbfd97d7f0c35c3b1l,0x0ba75cf3347fcefel,
-            0xc3c5f28f1333460dl },
-          0 },
-        /* 43 << 120 */
-        { { 0x7810ebf575baa708l,0xe7fa7a0dd7440549l,0x25b813baf0667e4al,
-            0x30a46740d15838a8l },
-          { 0x13207b1ad04b22f7l,0x09e601ffd1419699l,0xb1038fc77f687b27l,
-            0xa4547dc9a127f95bl },
-          0 },
-        /* 44 << 120 */
-        { { 0x83b2e3b3056ecd2cl,0xd17dcdaaf03dfd36l,0xee24a5f81dcef956l,
-            0xb6746cd0b7239f16l },
-          { 0xed6cb311c8458c48l,0xe8c0fc9805d27da4l,0x4610e9a0a1bf0970l,
-            0x1947f01d9906c19el },
-          0 },
-        /* 45 << 120 */
-        { { 0x8b979126217c7cd7l,0x65c57a378050067el,0x6a50c6383f34838cl,
-            0x3de617c29b7bc81fl },
-          { 0x58488d24253a0ac7l,0x3fe53ec75520ba0bl,0x9156dca763f0607el,
-            0xdd08c5705d1fe134l },
-          0 },
-        /* 46 << 120 */
-        { { 0xbfb1d9e1e33ba77fl,0x0985311ccaef6c01l,0xc8b59e9accca8948l,
-            0x1256280945416f25l },
-          { 0xc90edbc257f53218l,0xcaa08c05125d8fb5l,0x33ea3fd49a1aad3bl,
-            0x2aa8bd83d005e8bel },
-          0 },
-        /* 47 << 120 */
-        { { 0xcbd2f1a3c2b22963l,0x0f7bd29c0c8ac2b3l,0xddb932432d405bfdl,
-            0xeabd4805328413b5l },
-          { 0xcc79d31748ebb6b9l,0x09604f831f521aael,0xd3487fdf4c7d188cl,
-            0xd219c318d1552ea9l },
-          0 },
-        /* 48 << 120 */
-        { { 0xef4f115c775d6ecel,0x69d2e3bbe8c0e78dl,0xb0264ef1145cfc81l,
-            0x0a41e9fa1b69788bl },
-          { 0x0d9233be909a1f0bl,0x150a84520ae76b30l,0xea3375370632bb69l,
-            0x15f7b3cfaa25584al },
-          0 },
-        /* 49 << 120 */
-        { { 0xfc4c623e321f7b11l,0xd36c1066f9cbc693l,0x8165235835dc0c0al,
-            0xa3ce2e18c824e97el },
-          { 0x59ea7cbcc6ff405el,0xced5a94a1e56a1e2l,0x88d744c53ab64b39l,
-            0x8963d029073a36e7l },
-          0 },
-        /* 51 << 120 */
-        { { 0x97aa902cb19f3edbl,0x8e605ff9bbf2975bl,0x0536fa8ba6eb299bl,
-            0xfd96da4f7cd03ac0l },
-          { 0x29c5b5b578f9a265l,0x1f025a6d5fd0bc1bl,0x440486ee58e0f8e1l,
-            0x8f191f7d593e49e9l },
-          0 },
-        /* 52 << 120 */
-        { { 0xbddf656baea9c13fl,0x083c5d514c678b37l,0x975431b630878ed4l,
-            0x6de13d4608d9cf1cl },
-          { 0xfbb639cc02427c45l,0x6190ca0c5a6cd989l,0x35a6aa26c53f11b7l,
-            0x73f9e17dddfd86f6l },
-          0 },
-        /* 53 << 120 */
-        { { 0xd30478a317be7689l,0x6fc3f634e358f7a7l,0x4057ece515688d9fl,
-            0xb5397495d3d91eefl },
-          { 0x62fac49e2f49bde4l,0xeb4a3e1860125c73l,0x15f38be8dabdac55l,
-            0x18bf29f7d334d52al },
-          0 },
-        /* 55 << 120 */
-        { { 0xf684162b68777538l,0x3e2a770bbb3381f4l,0x1b7562c1b374577cl,
-            0x9eec22dc5cf21688l },
-          { 0xc35014b1d472be2cl,0xafe2317035f086fbl,0xb9c9c4c9a1491ce1l,
-            0x2df1e669b56792ddl },
-          0 },
-        /* 57 << 120 */
-        { { 0xcf7d36fe1830f624l,0x176c3c12ed0474bdl,0x25b802c8f82b493dl,
-            0x683c2a744c78147el },
-          { 0x0db99444f8f3e446l,0x437bcac6800a56c7l,0xb4e592264d08b25fl,
-            0xcaf1b4142e691ca7l },
-          0 },
-        /* 59 << 120 */
-        { { 0x378bd47b9d231cafl,0xde3aa2f01f4db832l,0xf609d16ab29bd7d5l,
-            0x13feab54bdfb54dfl },
-          { 0x274abbbc22fc1a12l,0x267febb47d30ef1bl,0xeffa996d80717cd8l,
-            0x065a86d1118d0812l },
-          0 },
-        /* 60 << 120 */
-        { { 0xc681a8656a3cb3afl,0x528f25a981751414l,0x6669f07cc7eac946l,
-            0x9fb3a53f3cc6cc6bl },
-          { 0x2919d92a11ae224al,0xa59141110b170a19l,0xdc16c611e2042f16l,
-            0x58ace12decd4180bl },
-          0 },
-        /* 61 << 120 */
-        { { 0x689bb1ec107bb59fl,0x8129702adad2b385l,0x10bd3baeb1630603l,
-            0xaadec5d15f23e7cfl },
-          { 0x572f234f4586f7fbl,0x13abdec95ec11b32l,0xa462a7ec6191c26al,
-            0x4a7d92a06685c8d3l },
-          0 },
-        /* 63 << 120 */
-        { { 0xdd4e2b63b16628eal,0xdf0c8fc8eefa5e86l,0xb0ec710205662720l,
-            0x3f4c6956fe81e9dal },
-          { 0x5732ad8f52e356f7l,0x045a103968a658f0l,0x9c40b0b6506ba33al,
-            0x0a426010cb54258dl },
-          0 },
-        /* 64 << 120 */
-        { { 0x09891641d4c5105fl,0x1ae80f8e6d7fbd65l,0x9d67225fbee6bdb0l,
-            0x3b433b597fc4d860l },
-          { 0x44e66db693e85638l,0xf7b59252e3e9862fl,0xdb785157665c32ecl,
-            0x702fefd7ae362f50l },
-          0 },
-        /* 65 << 120 */
-        { { 0x3902ab14c3254641l,0xa63cfd9fd8c001c8l,0x597d155c52d0af3cl,
-            0xc5a2cbc4a0dbe688l },
-          { 0xac8a841b249195aal,0xc98f01aaed14426fl,0xeb4a8ce8353905f1l,
-            0x4d6668171ecee1b7l },
-          0 },
-        /* 71 << 120 */
-        { { 0xbd66e7d9a94da8cdl,0x7bc04735801ef314l,0x90f3eba1c5cc2904l,
-            0x3c7dfed6f71bb36dl },
-          { 0x89a50c8da75e3086l,0x88b8b4746f8e3418l,0x26fe17f4a44a5dbdl,
-            0x98bf74c16a1e24fel },
-          0 },
-        /* 77 << 120 */
-        { { 0xca7b470679e0db85l,0x7f46c7716fc897fdl,0x9537e7918edfc0f3l,
-            0xa46d4b4405e91ddfl },
-          { 0x97d21061ee5575e7l,0x1f4f32da59650429l,0x2d1d6af878995129l,
-            0x41d6fc228a0e4260l },
-          0 },
-        /* 83 << 120 */
-        { { 0xb30a1a89107d2282l,0x5433d7673a5e1323l,0xb9eeab822abdfeafl,
-            0x9579cb46df3e0dbfl },
-          { 0x6fc3ff2c7e088e79l,0x94b32360d7314326l,0xd2e82b59e5ad82e4l,
-            0x7372dc4a55bc24e3l },
-          0 },
-        /* 89 << 120 */
-        { { 0x355697215f3c03cbl,0x4150adf2a146edcdl,0x16ec1a421a252e1cl,
-            0xdf4d0f94424984eal },
-          { 0x15142b5f5fabe961l,0xe6a73c29567ec13al,0xe6d370795d12070al,
-            0x437743d0206fd7c6l },
-          0 },
-        /* 95 << 120 */
-        { { 0x483b7a95d66bc594l,0xf6a7064e8a6113bbl,0x373ce20f4ed34f72l,
-            0x6aa876ab24f429b2l },
-          { 0x378d5c25412c3102l,0xe4219a97b493199cl,0x01c7cafaa0b37332l,
-            0x9305cc85f7633f7dl },
-          0 },
-        /* 101 << 120 */
-        { { 0x0259b43aaadf2273l,0x869c5bd3cf9dc1c2l,0x4f18a6e4068d6628l,
-            0xd110637fec2d4547l },
-          { 0x1ae88a791e94aaddl,0xe8b4be39de64f5f9l,0x85cbd9b24dc6b2bbl,
-            0xb65091fa1bc352b2l },
-          0 },
-        /* 107 << 120 */
-        { { 0x7c5cea5d20f6a354l,0xe936ff1582f3ed39l,0x54e7a775b779368el,
-            0x8ca8a46e3cb17c9el },
-          { 0x753ca1fa0138974dl,0x9ce311eba72902ffl,0xcb727e56973f72b6l,
-            0xde72538d91685710l },
-          0 },
-        /* 113 << 120 */
-        { { 0xf423569f1bec8f85l,0x23376da5ca844ac4l,0xce7b407a111523f4l,
-            0x736fb92dde7aa46dl },
-          { 0xd9139edcc7662640l,0x520fbf0656a85e24l,0x14e3b5857e5284b5l,
-            0xcbae4e8321d56ef3l },
-          0 },
-        /* 116 << 120 */
-        { { 0x69830a05564470a1l,0x1a1e26cf5b702e8el,0xe5fdf7d9d8fae645l,
-            0xe4774f74a9950c66l },
-          { 0x18bdda7cd1466825l,0xe6ab4ce6d115218al,0xfcb8c50064528629l,
-            0xd705f429e70deed9l },
-          0 },
-        /* 119 << 120 */
-        { { 0x3f992d7ba99df096l,0x08993b4125e78725l,0x79eaad13117c4cafl,
-            0x7230594c9fa87285l },
-          { 0xac23d7edf2673e27l,0xc9d76fb53b9eb111l,0x7a0a036a9e9db78al,
-            0x7c6ec39df9565cffl },
-          0 },
-        /* 125 << 120 */
-        { { 0x956ad1441fd4f7a1l,0x6c511ffecb7546cal,0x11becdaef5ae6ddbl,
-            0x67587741946168b2l },
-          { 0x99cd45edf54379a7l,0x687f8462e2748decl,0x2b2be1e1837bd066l,
-            0x3862659c0c45a5a9l },
-          0 },
-    },
-    {
-        /* 0 << 128 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 128 */
-        { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l,
-            0x61d587d421d324f6l },
-          { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el,
-            0xfa11fe124621efbel },
-          0 },
-        /* 3 << 128 */
-        { { 0xc0f734a3b2335834l,0x9526205a90ef6860l,0xcb8be71704e2bb0dl,
-            0x2418871e02f383fal },
-          { 0xd71776814082c157l,0xcc914ad029c20073l,0xf186c1ebe587e728l,
-            0x6fdb3c2261bcd5fdl },
-          0 },
-        /* 4 << 128 */
-        { { 0xb4480f0441c23fa3l,0xb4712eb0c1989a2el,0x3ccbba0f93a29ca7l,
-            0x6e205c14d619428cl },
-          { 0x90db7957b3641686l,0x0432691d45ac8b4el,0x07a759acf64e0350l,
-            0x0514d89c9c972517l },
-          0 },
-        /* 5 << 128 */
-        { { 0xcc7c4c1c2cf9d7c1l,0x1320886aee95e5abl,0xbb7b9056beae170cl,
-            0xc8a5b250dbc0d662l },
-          { 0x4ed81432c11d2303l,0x7da669121f03769fl,0x3ac7a5fd84539828l,
-            0x14dada943bccdd02l },
-          0 },
-        /* 7 << 128 */
-        { { 0x51b90651cbae2f70l,0xefc4bc0593aaa8ebl,0x8ecd8689dd1df499l,
-            0x1aee99a822f367a5l },
-          { 0x95d485b9ae8274c5l,0x6c14d4457d30b39cl,0xbafea90bbcc1ef81l,
-            0x7c5f317aa459a2edl },
-          0 },
-        /* 9 << 128 */
-        { { 0x410dc6a90deeaf52l,0xb003fb024c641c15l,0x1384978c5bc504c4l,
-            0x37640487864a6a77l },
-          { 0x05991bc6222a77dal,0x62260a575e47eb11l,0xc7af6613f21b432cl,
-            0x22f3acc9ab4953e9l },
-          0 },
-        /* 10 << 128 */
-        { { 0x27c8919240be34e8l,0xc7162b3791907f35l,0x90188ec1a956702bl,
-            0xca132f7ddf93769cl },
-          { 0x3ece44f90e2025b4l,0x67aaec690c62f14cl,0xad74141822e3cc11l,
-            0xcf9b75c37ff9a50el },
-          0 },
-        /* 11 << 128 */
-        { { 0x0d0942770c24efc8l,0x0349fd04bef737a4l,0x6d1c9dd2514cdd28l,
-            0x29c135ff30da9521l },
-          { 0xea6e4508f78b0b6fl,0x176f5dd2678c143cl,0x081484184be21e65l,
-            0x27f7525ce7df38c4l },
-          0 },
-        /* 13 << 128 */
-        { { 0x9faaccf5e4652f1dl,0xbd6fdd2ad56157b2l,0xa4f4fb1f6261ec50l,
-            0x244e55ad476bcd52l },
-          { 0x881c9305047d320bl,0x1ca983d56181263fl,0x354e9a44278fb8eel,
-            0xad2dbc0f396e4964l },
-          0 },
-        /* 15 << 128 */
-        { { 0xfce0176788a2ffe4l,0xdc506a3528e169a5l,0x0ea108617af9c93al,
-            0x1ed2436103fa0e08l },
-          { 0x96eaaa92a3d694e7l,0xc0f43b4def50bc74l,0xce6aa58c64114db4l,
-            0x8218e8ea7c000fd4l },
-          0 },
-        /* 16 << 128 */
-        { { 0x6a7091c2e48fb889l,0x26882c137b8a9d06l,0xa24986631b82a0e2l,
-            0x844ed7363518152dl },
-          { 0x282f476fd86e27c7l,0xa04edaca04afefdcl,0x8b256ebc6119e34dl,
-            0x56a413e90787d78bl },
-          0 },
-        /* 17 << 128 */
-        { { 0xd1ffd160deb58b9bl,0x78492428c007273cl,0x47c908048ef06073l,
-            0x746cd0dfe48c659el },
-          { 0xbd7e8e109d47055bl,0xe070967e39711c04l,0x3d8869c99c9444f6l,
-            0x6c67ccc834ac85fcl },
-          0 },
-        /* 19 << 128 */
-        { { 0x8a42d8b087b05be1l,0xef00df8d3e4e1456l,0x148cc8e8fbfc8cd2l,
-            0x0288ae4c4878804fl },
-          { 0x44e669a73b4f6872l,0xa4a8dbd4aab53c5bl,0x843fa963c9660052l,
-            0x128e2d2571c05dd2l },
-          0 },
-        /* 21 << 128 */
-        { { 0x3ea86174a9f1b59bl,0xc747ea076a9a8845l,0x733710b5ab242123l,
-            0x6381b546d386a60cl },
-          { 0xba0e286366a44904l,0x770f618de9db556cl,0x39e567f828fb198dl,
-            0xb5f1bef040147ee8l },
-          0 },
-        /* 23 << 128 */
-        { { 0x1adee1d516391617l,0x962d9184a3315fd9l,0x91c229750c805d59l,
-            0x4575eaf2cd9a1877l },
-          { 0x83fef163451831b9l,0x829d6bdd6f09e30fl,0x9379272dcc6b4e6al,
-            0xd7a049bd95fbee4al },
-          0 },
-        /* 25 << 128 */
-        { { 0x695f70da44ae09c6l,0x79793892bb99de1dl,0xde269352f696b429l,
-            0xe37ea97f8104c825l },
-          { 0x3166cac6b0e72e63l,0xa82e633ca03ba670l,0x1106e3843e505667l,
-            0xc2994f3dffb788b6l },
-          0 },
-        /* 27 << 128 */
-        { { 0xd36a5ab37c53073bl,0xc44a9940ebdc7e35l,0x7dd86c8bf3ded136l,
-            0x9fe9879fd5a0eb14l },
-          { 0xa210726c9b99bf9cl,0x3faf4456861036afl,0x1661f1c9615d091al,
-            0x2c63f630911551bcl },
-          0 },
-        /* 28 << 128 */
-        { { 0x1554d46da670ff1dl,0x24833d88cb97a1ccl,0x8fa6ab3cded97493l,
-            0x215e037189926498l },
-          { 0x549bd592e56d74ffl,0x58a8caf543b5e1ecl,0x3c6087a323e93cb9l,
-            0x8b0549875648b83cl },
-          0 },
-        /* 29 << 128 */
-        { { 0x232974230554f94fl,0x4f445a380f3a7618l,0xb9fb40bee4abefd6l,
-            0xfbf3eaf9c15eb07cl },
-          { 0xed469c23aca0c8b3l,0xc5209f68846e3f8fl,0x33d51d13d75da468l,
-            0x9406e10a3d5c6e29l },
-          0 },
-        /* 31 << 128 */
-        { { 0xb9a44b1f5c6cad21l,0xaa9947751ee60a83l,0xc89af3858c390401l,
-            0xef1e450b8dd51056l },
-          { 0x5f5f069879ac84d1l,0x68d82982ef57b1afl,0x31f1d90f50849555l,
-            0xff9577e57d9fc8f6l },
-          0 },
-        /* 33 << 128 */
-        { { 0xaeebc5c0b430d6a1l,0x39b87a13dc3a9c04l,0xf0c445252db4a631l,
-            0xe32d95482c66fcf6l },
-          { 0x16f11bafb17849c4l,0xdd1c76615eca71f7l,0x4389ad2e32e6c944l,
-            0x727c11a5889a06bbl },
-          0 },
-        /* 34 << 128 */
-        { { 0x38dd1ac021e5781al,0x578318dbfd019ee2l,0x096b677d5f88e574l,
-            0xdbec82b216ad9f4fl },
-          { 0x348debe23260e8d9l,0x9334126064dfcda1l,0xdc5fb34cefc8faael,
-            0x5fa048beb4a6fc25l },
-          0 },
-        /* 35 << 128 */
-        { { 0xe18806fd60b3258cl,0xb7d2926b1364df47l,0xe208300fa107ce99l,
-            0x8d2f29fe7918df0el },
-          { 0x0b012d77a1244f4cl,0xf01076f4213a11cfl,0x8e623223181c559dl,
-            0x9df196ee995a281dl },
-          0 },
-        /* 36 << 128 */
-        { { 0xc431a238013ff83bl,0x7c0018b2fad69d08l,0x99aeb52a4c9589eal,
-            0x121f41ab9b1cf19fl },
-          { 0x0cfbbcbaef0f5958l,0x8deb3aeb7be8fbdcl,0x12b954081f15aa31l,
-            0x5acc09b34c0c06fdl },
-          0 },
-        /* 37 << 128 */
-        { { 0xfaa821383a721940l,0xdd70f54dd0008b83l,0x00decb507d32a52dl,
-            0x04563529cdd87deal },
-          { 0xb0e7e2a2db81643dl,0x445f4c383a6fef50l,0x5c0ef211df694ae1l,
-            0xa5a8fead923d0f1cl },
-          0 },
-        /* 39 << 128 */
-        { { 0xbc0e08b0325b2601l,0xae9e4c6105815b7al,0x07f664faf944a4a1l,
-            0x0ad19d29288f83b3l },
-          { 0x8615cd677232c458l,0x98edff6e9038e7d1l,0x082e0c4395a4dfccl,
-            0x336267afeceee00el },
-          0 },
-        /* 40 << 128 */
-        { { 0x775cbfa86d518ffbl,0xdecee1f6930f124bl,0x9a402804f5e81d0fl,
-            0x0e8225c52a0eeb2fl },
-          { 0x884a5d39fee9e867l,0x9540428ffb505454l,0xb2bf2e20107a70d1l,
-            0xd9917c3ba010b2aal },
-          0 },
-        /* 41 << 128 */
-        { { 0xc88ad4452a29bfdel,0x3072ebfa998368b7l,0xa754cbf7f5384692l,
-            0x85f7e16906b13146l },
-          { 0x42a7095f6a549fbel,0xef44edf91f7f1f42l,0xbea2989737b0c863l,
-            0x13b096d87a1e7fc3l },
-          0 },
-        /* 43 << 128 */
-        { { 0x51add77ce2a3a251l,0x840ca1384d8476adl,0x08d01d26f6096478l,
-            0x10d501a532f1662bl },
-          { 0xc8d63f811165a955l,0x587aa2e34095046al,0x759506c617af9000l,
-            0xd6201fe4a32ab8d2l },
-          0 },
-        /* 44 << 128 */
-        { { 0xa98f42fa3d843d53l,0x33777cc613ef927al,0xc440cdbecb84ca74l,
-            0x8c22f9631dc7c5ddl },
-          { 0x4bc82b70c8d94708l,0x7e0b43fcc814364fl,0x286d4e2486f59b7el,
-            0x1abc895e4d6bf4c4l },
-          0 },
-        /* 45 << 128 */
-        { { 0x7c52500cfc8c9bbdl,0x635563381534d9f7l,0xf55f38cbfd52c990l,
-            0xc585ae85058f52e7l },
-          { 0xb710a28bf9f19a01l,0x891861bdf0273ca4l,0x38a7aa2b034b0b7cl,
-            0xa2ecead52a809fb1l },
-          0 },
-        /* 46 << 128 */
-        { { 0x3df614f1ec3ca8eal,0x6bb24e9f9505bc08l,0x23ba1afbf37ace22l,
-            0x2e51b03b3463c261l },
-          { 0x59a0fca9c39e6558l,0x819f271ca342ccd9l,0x0c913d54df7ac033l,
-            0xba0f83de573257d3l },
-          0 },
-        /* 47 << 128 */
-        { { 0xdf62817ab3b32fbcl,0x616d74b0964670d4l,0xa37bc6270e26020bl,
-            0xda46d655b7d40bdal },
-          { 0x2840f155b5773f84l,0xbb633777897774b6l,0x59ff1df79a1ed3fal,
-            0xf7011ee2bac571f9l },
-          0 },
-        /* 48 << 128 */
-        { { 0x38151e274d559d96l,0x4f18c0d3b8db6c01l,0x49a3aa836f9921afl,
-            0xdbeab27b8c046029l },
-          { 0x242b9eaa7040bf3bl,0x39c479e51614b091l,0x338ede2b0e4baf5dl,
-            0x5bb192b7f0a53945l },
-          0 },
-        /* 49 << 128 */
-        { { 0xd612951861535bb0l,0xbf14364016f6a954l,0x3e0931eedde18024l,
-            0x79d791c8139441c0l },
-          { 0xba4fe7ecb67b8269l,0x7f30d848224b96c1l,0xa7e0a6abf0341068l,
-            0x78db42c37198ea2dl },
-          0 },
-        /* 51 << 128 */
-        { { 0x13354044185ce776l,0x109a6e059ff0100cl,0xafa3b61b03144cb1l,
-            0x4e4c814585265586l },
-          { 0xa8dafd33edb35364l,0x6691781bfd2606bel,0x2e06a9786182f5ccl,
-            0x588784ebe77faeecl },
-          0 },
-        /* 52 << 128 */
-        { { 0x896d572337e440d7l,0x685c5fd9ade23f68l,0xb5b1a26dc2c64918l,
-            0xb9390e30dad6580cl },
-          { 0x87911c4e7dee5b9bl,0xb90c5053deb04f6el,0x37b942a18f065aa6l,
-            0x34acdf2a1ca0928dl },
-          0 },
-        /* 53 << 128 */
-        { { 0xc773f525606f8f04l,0x75ae4a4b41b0a5bbl,0xb2aa058eaf7df93cl,
-            0xf15bea4feafed676l },
-          { 0xd2967b236a3c4fd7l,0xa698628090e30e7fl,0xf1b5166d316418bdl,
-            0x5748682e1c13cb29l },
-          0 },
-        /* 55 << 128 */
-        { { 0xe7b11babfff3605bl,0xdbce1b74cbac080fl,0xa0be39bd6535f082l,
-            0x2b6501805f826684l },
-          { 0xf90cea2400f5244fl,0xe279f2fadd244a1cl,0xd3fca77c9421c3ael,
-            0xe66bc7ee81a5210al },
-          0 },
-        /* 57 << 128 */
-        { { 0x114085dac40c6461l,0xaf78cb47f47d41b8l,0x7a9ae851755b0adbl,
-            0x8d2e8c66a0600b6dl },
-          { 0x5fb19045389758c0l,0xfa6e2cdabe7c91b2l,0x6472a432663983a2l,
-            0xc9370829e0e19363l },
-          0 },
-        /* 59 << 128 */
-        { { 0xd335856ec50bf2ffl,0x89b42295dfa708c2l,0x5dfb42241b201b4el,
-            0x6c94d6b94eecbf9cl },
-          { 0xabe5a47a7a634097l,0xf3d53b1643febecfl,0xff18619faca9846el,
-            0x80ad8629a4066177l },
-          0 },
-        /* 60 << 128 */
-        { { 0x7872e34b3390ff23l,0x968ce4abde7d18efl,0x9b4a745e627fe7b1l,
-            0x9607b0a0caff3e2al },
-          { 0x1b05818eeb40e3a5l,0x6ac62204c0fa8d7al,0xb5b9058571ed4809l,
-            0xb2432ef0f7cb65f2l },
-          0 },
-        /* 61 << 128 */
-        { { 0xc1203418f8a144b7l,0xb3413f808378f901l,0xf6badea161857095l,
-            0xcd2816c2b2e93efel },
-          { 0x6a8303ea174a0ee6l,0x98b62f29150b28b6l,0x68071bbc9c2a05b6l,
-            0xcfcf41a39f00e36el },
-          0 },
-        /* 63 << 128 */
-        { { 0xcaf564f234d6bc29l,0x9e9a6507f3c8edb0l,0x2fb889edd4e5502el,
-            0xb70d4ceb6cc9d8edl },
-          { 0x0de25356b020f740l,0xa68d9263d11fe5e6l,0xe86400679d85dd77l,
-            0xa95dfa7dec2c8c8dl },
-          0 },
-        /* 64 << 128 */
-        { { 0x715c9f973112795fl,0xe8244437984e6ee1l,0x55cb4858ecb66bcdl,
-            0x7c136735abaffbeel },
-          { 0x546615955dbec38el,0x51c0782c388ad153l,0x9ba4c53ac6e0952fl,
-            0x27e6782a1b21dfa8l },
-          0 },
-        /* 65 << 128 */
-        { { 0x3f9bc63ece59397dl,0x3f0f98a93eaa6104l,0x2f82c37c002d9271l,
-            0x6ac0495d4985353cl },
-          { 0xbde52f629191527bl,0xa3a13fce475aa640l,0x1d71ae17ce673f89l,
-            0x2b5cc61529120ec1l },
-          0 },
-        /* 71 << 128 */
-        { { 0xa0ab0f9924318c1cl,0x0cc5ca7da80ca60bl,0x24e27598abb965bal,
-            0xc4863198b44d1351l },
-          { 0x4d913783a28f04bel,0x404e78088cce8960l,0x2973b4e46286873el,
-            0x7b6e0f3219f42b50l },
-          0 },
-        /* 77 << 128 */
-        { { 0x0091a786306a6349l,0x4640ceab2098622dl,0x9928022be8182233l,
-            0xf261bee4514d0bedl },
-          { 0x70cdcc44c5f64fedl,0x4e19fec4f9eb2dfel,0xd05bdc09058b0b69l,
-            0x16f3007ed3bc6190l },
-          0 },
-        /* 83 << 128 */
-        { { 0x8f7f16957f136df1l,0x6d7547019b4f4215l,0xfb22d55eb4cc46a6l,
-            0x0b53ef53a8563034l },
-          { 0x8b105acc42bc9353l,0xe44c0a396079d59dl,0x78441fee35ee38ddl,
-            0x87ad93e43dcc0119l },
-          0 },
-        /* 89 << 128 */
-        { { 0x98a1c55358d9f73al,0xaa0843f0540e2b91l,0x701f8831d0647459l,
-            0xc4ae9d0484673005l },
-          { 0x9c37bc9f30b3ea20l,0x24cb4e2dbcbfb2b2l,0x8513e6f313cbf070l,
-            0x0c4db4334e76c79el },
-          0 },
-        /* 95 << 128 */
-        { { 0x882a2b9cbc8320b8l,0x16e9c11e3ad9e222l,0x24399ac19b23cb1dl,
-            0x334c5496799a89c7l },
-          { 0x72b6f9b8df3d774cl,0x42955bcbb11b6704l,0x3c4d6021ad2d4eafl,
-            0x5416b309afe2b671l },
-          0 },
-        /* 101 << 128 */
-        { { 0x1bbe9e662bf7c2a6l,0x22a3a10ca4acfddbl,0x2424eaab46bae581l,
-            0xebec1bbf40d6bdadl },
-          { 0xd7e3fa1a5b012aedl,0xc0f82c23f1dc6204l,0x42787c82e319477dl,
-            0xca1ae7a14cf57573l },
-          0 },
-        /* 107 << 128 */
-        { { 0x44b7d589d51bbde9l,0x15de755fd6a4cc98l,0x9b6ea8e582fb8e2el,
-            0x9d9294f04332bc22l },
-          { 0x53c6b2b7d1fa239al,0x286bf536693ca4f1l,0xc3fa754603c00f65l,
-            0xc046713af49cdb48l },
-          0 },
-        /* 113 << 128 */
-        { { 0xe356f5f11d82d5d6l,0xa0346a73d035ca0cl,0x14c76adee1884448l,
-            0xd8369bdd1c23dde9l },
-          { 0x13017862fe025eafl,0x6b5ac5e9a76be1d7l,0x52d621a94933bb6el,
-            0xb045b53baa8c1d3fl },
-          0 },
-        /* 116 << 128 */
-        { { 0x242da39e4e40466al,0xc03cb184ac322b07l,0x776b744f9aaa10bfl,
-            0xb80d9f14fe7d4beal },
-          { 0x75cd14308f9c4908l,0xa4e59ce9087b3d7al,0x3bbdce598cdca614l,
-            0x58c57113bc1a5df1l },
-          0 },
-        /* 119 << 128 */
-        { { 0x2a70af1abd79d467l,0x68dc4f23f63e2b73l,0x4345572f1f67b23dl,
-            0xc012b08f3a340718l },
-          { 0x9458585cc963dbe2l,0x21d84032223a495cl,0x0d54a4ea0dc28159l,
-            0xd9549e2c9b927dafl },
-          0 },
-        /* 125 << 128 */
-        { { 0xcd54ebd2d43c8cd2l,0x5ff4ded6a817b9f9l,0x6f59bc31245386d3l,
-            0x65b67cb0a2077821l },
-          { 0x36407956405ffa07l,0x723e0252d589f27al,0x052004b888e1239el,
-            0x8e6d188d69fdf94dl },
-          0 },
-    },
-    {
-        /* 0 << 136 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 136 */
-        { { 0xc16c236e846e364fl,0x7f33527cdea50ca0l,0xc48107750926b86dl,
-            0x6c2a36090598e70cl },
-          { 0xa6755e52f024e924l,0xe0fa07a49db4afcal,0x15c3ce7d66831790l,
-            0x5b4ef350a6cbb0d6l },
-          0 },
-        /* 3 << 136 */
-        { { 0xe2a37598a9d82abfl,0x5f188ccbe6c170f5l,0x816822005066b087l,
-            0xda22c212c7155adal },
-          { 0x151e5d3afbddb479l,0x4b606b846d715b99l,0x4a73b54bf997cb2el,
-            0x9a1bfe433ecd8b66l },
-          0 },
-        /* 4 << 136 */
-        { { 0xe13122f3dbfb894el,0xbe9b79f6ce274b18l,0x85a49de5ca58aadfl,
-            0x2495775811487351l },
-          { 0x111def61bb939099l,0x1d6a974a26d13694l,0x4474b4ced3fc253bl,
-            0x3a1485e64c5db15el },
-          0 },
-        /* 5 << 136 */
-        { { 0x5afddab61430c9abl,0x0bdd41d32238e997l,0xf0947430418042ael,
-            0x71f9addacdddc4cbl },
-          { 0x7090c016c52dd907l,0xd9bdf44d29e2047fl,0xe6f1fe801b1011a6l,
-            0xb63accbcd9acdc78l },
-          0 },
-        /* 7 << 136 */
-        { { 0x0ad7337ac0b7eff3l,0x8552225ec5e48b3cl,0xe6f78b0c73f13a5fl,
-            0x5e70062e82349cbel },
-          { 0x6b8d5048e7073969l,0x392d2a29c33cb3d2l,0xee4f727c4ecaa20fl,
-            0xa068c99e2ccde707l },
-          0 },
-        /* 9 << 136 */
-        { { 0x5b826fcb1b3ec67bl,0xece1b4b041356616l,0x7d5ce77e56a3ab4fl,
-            0xf6087f13aa212da0l },
-          { 0xe63015054db92129l,0xb8ae4c9940407d11l,0x2b6de222dfab8385l,
-            0x9b323022b7d6c3b4l },
-          0 },
-        /* 10 << 136 */
-        { { 0x057ef17a5ae6ad84l,0x9feae00b293a6ae0l,0xd18bb6c154266408l,
-            0xd3d3e1209c8e8e48l },
-          { 0xba8d4ca80e94fc8fl,0x80262ffc8a8ea0fel,0xac5b2855f71655fdl,
-            0xa348f8fae9aced89l },
-          0 },
-        /* 11 << 136 */
-        { { 0x60684b69a5660af3l,0x69aad23b9066d14bl,0x4d9f9b49fa4d020al,
-            0xafb54ec1b5cd6a4al },
-          { 0x2b25fe1832fd864dl,0xee6945062b6b64d0l,0x954a2a515001d8aal,
-            0x5e1008557082b5b3l },
-          0 },
-        /* 13 << 136 */
-        { { 0x20ecf71cbc90eb1bl,0x4234facf651c1df4l,0xc720fce9e681f678l,
-            0x680becdda7c007f4l },
-          { 0x7c08dc063181afeal,0x75c1b050a34eca91l,0x7d3479d54b9e2333l,
-            0xed16640af3951aa3l },
-          0 },
-        /* 15 << 136 */
-        { { 0x911b596264723e54l,0x34384f8c004b327cl,0x06ca5c61b85435f2l,
-            0x12e0cd25e2c1075cl },
-          { 0xa4b84cb8ac727394l,0x50bd720492b352c1l,0xe85524a49cbd0fb4l,
-            0x10b9274be7876024l },
-          0 },
-        /* 16 << 136 */
-        { { 0xef0a3fecfa181e69l,0x9ea02f8130d69a98l,0xb2e9cf8e66eab95dl,
-            0x520f2beb24720021l },
-          { 0x621c540a1df84361l,0x1203772171fa6d5dl,0x6e3c7b510ff5f6ffl,
-            0x817a069babb2bef3l },
-          0 },
-        /* 17 << 136 */
-        { { 0xb7cf93c3aace2c6al,0x017a96e658ff1bbfl,0x3b401301624a8250l,
-            0xf5ef158529266518l },
-          { 0x3c968bef7585838dl,0x8e97d023853191abl,0x175022e4f6823389l,
-            0xb6a3bfc2f6a9b4c1l },
-          0 },
-        /* 19 << 136 */
-        { { 0x515acf174591d77el,0xb393c89e3c3b25b6l,0x291e068e9c95abd7l,
-            0x256b72c046c02544l },
-          { 0x8172af03915ea92fl,0xc1b324ae4fcd0f03l,0x8abc779215108993l,
-            0xe05fe6867ab815ael },
-          0 },
-        /* 21 << 136 */
-        { { 0xca08d4095bc42740l,0xdd2c19d3e26e2e60l,0x27afdeded7c091fal,
-            0x3b943b0faf25cb22l },
-          { 0x400af8be026047e9l,0x3149b35f772b8ff9l,0x3ddb2c06f17229d9l,
-            0xcd604aeadac152fcl },
-          0 },
-        /* 23 << 136 */
-        { { 0xea2275311c0f6803l,0x9ae82d5ea394cc08l,0xc107a2cfbe32080cl,
-            0x550f35a76429f6d7l },
-          { 0x483c94dacfb70c0cl,0xf26f8e5d90190c94l,0x8574b3cf86bf2620l,
-            0xe7258e45df9f482fl },
-          0 },
-        /* 25 << 136 */
-        { { 0x8f8dc582da46f1cfl,0x61d76cf91e1e7427l,0x8aceb48b306c84aal,
-            0xecaa142f28ebff98l },
-          { 0xac5bd940401d80fel,0x0caacb8fe800cf9el,0x99068da9b3359af5l,
-            0x92fdd5795225b8c0l },
-          0 },
-        /* 27 << 136 */
-        { { 0x5a29d1c5ab56a3fbl,0x4e46ffc0a9aab4afl,0xa210472624d83080l,
-            0xb5820998007f08b6l },
-          { 0x9ce1188e4bc07b3el,0xbf6d0dbe32a19898l,0x5d5c68ea5b2350bal,
-            0xd6c794eb3aa20b45l },
-          0 },
-        /* 28 << 136 */
-        { { 0x3de605ba9ec598cfl,0x1933d3ae4d3029ael,0x6bf2fabd9b140516l,
-            0x712dfc5559a7d01cl },
-          { 0xff3eaae0d2576366l,0x36e407f948701cf8l,0xede21d89b41f4bd4l,
-            0xc5292f5c666eefa9l },
-          0 },
-        /* 29 << 136 */
-        { { 0x30045782c3ebcd77l,0xaa0cf3c73fdbe72el,0x719ec58ef8f43b39l,
-            0x9716fb9972574d3al },
-          { 0x300afc2b0d03ccd6l,0xb60016a34f3fac41l,0x8898910ea3a439f6l,
-            0xdc00a99707ca11f5l },
-          0 },
-        /* 31 << 136 */
-        { { 0x291b15ee8ed34662l,0xb780d54b2ee422a7l,0x5b9e3788fcfe4ccbl,
-            0x4554cb8cbe8b7c3al },
-          { 0xfdaccc2209a85a7fl,0x51f4a8ec555497edl,0x07dc69037da33505l,
-            0xa3bc8bfcbc1fc1dbl },
-          0 },
-        /* 33 << 136 */
-        { { 0x661638c151e25257l,0x0a6fd99c53304974l,0x29d8ae165078eec6l,
-            0xed7512ad447b73del },
-          { 0x0e21de607a4d0e9bl,0x842abd422462be01l,0x3be82afa5cddc709l,
-            0x25bb9da99b52797dl },
-          0 },
-        /* 34 << 136 */
-        { { 0x80613af28adc986al,0x4602284935776a41l,0x17d33e0f4665d03cl,
-            0xeb12eb6c0df12b50l },
-          { 0x0f0effa0ee41527fl,0x8ca2edb680531563l,0x4c354679f28c52c3l,
-            0x67f1ba5c2f6df66dl },
-          0 },
-        /* 35 << 136 */
-        { { 0x9c27207a2479fb3fl,0xef6e0f13515fb902l,0x3f7ad9e9d0d9436el,
-            0x36eb4ea5893bbcf5l },
-          { 0x5c53a2ac02b316b7l,0x10c75ee1f54f7585l,0x29e5879c3c7a4c1bl,
-            0x77da3c82f29c67d6l },
-          0 },
-        /* 36 << 136 */
-        { { 0xf2b75d21ef78a852l,0xba38cd34dd31a900l,0x72b3a68658ffe18al,
-            0x7464190cbfd95745l },
-          { 0x406e532177ed6e81l,0x1af0975bde535eabl,0x66ba22c760c54c82l,
-            0x88e3b1ceb00a2fe0l },
-          0 },
-        /* 37 << 136 */
-        { { 0xb6099b7df7e5c69bl,0x84aa1e26ba34ee2fl,0x5952600405c338bbl,
-            0xe9a134374951a539l },
-          { 0xb12276526ec196bdl,0x26a7be264b6dce36l,0x052e10a4e2a68458l,
-            0x475fc74c1f38898bl },
-          0 },
-        /* 39 << 136 */
-        { { 0x120167fc0a3eb4e1l,0xaa94bc70c0c21204l,0x313cd835e1243b75l,
-            0x3bb63fb20bfd6a4al },
-          { 0xa615dcae21ef05cfl,0x63774c2ec23c3ee5l,0x39365b1fed0dfd65l,
-            0xb610e6ff5d2a2d7dl },
-          0 },
-        /* 40 << 136 */
-        { { 0x55b7f977f0337b15l,0x3bc872a30e94973al,0x624ad983770deea0l,
-            0xcaab336413a5efdbl },
-          { 0x391dd0027a0d4247l,0x39590d5df312aed5l,0x532802c9351365acl,
-            0xdd2e824578a2e22al },
-          0 },
-        /* 41 << 136 */
-        { { 0x81b0d7be7f774fb8l,0x62f32bb3aa412425l,0xbe7afe26bbcd2162l,
-            0xa6ce167c53c7fa7dl },
-          { 0x8deca64fc5c4fc5bl,0x70e546aba6efd2fel,0xf2d8495987ff672al,
-            0x2ca551f249c3059el },
-          0 },
-        /* 43 << 136 */
-        { { 0x40b62d528eb99155l,0xe6b048947420a7e0l,0x9ebecb2bc685e58al,
-            0x3ea642d8d3c8d2cbl },
-          { 0x5340ac6ed489d0dfl,0xf3846d08c2b7588el,0x4cecd8a0611c289bl,
-            0xdddc39c50dd71421l },
-          0 },
-        /* 44 << 136 */
-        { { 0x98c6a6a52ebee687l,0xcdf65bfa56c1c731l,0x48e8132772def210l,
-            0x4ea119418083b5a5l },
-          { 0x3fdcea4fffebb525l,0x55aaea19fb50bf72l,0x5fbedc0a2a85b40cl,
-            0x0d6fd954bf44f29fl },
-          0 },
-        /* 45 << 136 */
-        { { 0x83a8302a9db4071el,0x52f104436f8ae934l,0x96de829d175b800al,
-            0x20ff5035373e97cel },
-          { 0xf58660185f65356al,0x992c15054c8cd782l,0x0b962c8eb57d727fl,
-            0xe8a9abc92bba8bc7l },
-          0 },
-        /* 46 << 136 */
-        { { 0x81a85ddd7cf2b565l,0x5e51e6afc34a0305l,0xa8d94ccefbc89faal,
-            0x2bfd97c1e68cd288l },
-          { 0x16d79c21af2958b8l,0x5e5d989defda7df8l,0x6d2f0ca6ff734c8al,
-            0xfa5b8dd32cc9bafel },
-          0 },
-        /* 47 << 136 */
-        { { 0x5787a9934e6ed688l,0x6815f3b5aab42f46l,0x7960f45b093c6c66l,
-            0xb2b9829728be10cfl },
-          { 0x1d4c7790296568cdl,0xa279a877f048e194l,0xcf7c20f4c6a58b4el,
-            0xf0c717afa1f9c00fl },
-          0 },
-        /* 48 << 136 */
-        { { 0x8a10b53189e800cal,0x50fe0c17145208fdl,0x9e43c0d3b714ba37l,
-            0x427d200e34189accl },
-          { 0x05dee24fe616e2c0l,0x9c25f4c8ee1854c1l,0x4d3222a58f342a73l,
-            0x0807804fa027c952l },
-          0 },
-        /* 49 << 136 */
-        { { 0x79730084ba196afcl,0x17d38e98054bd539l,0xc5cfff3918583239l,
-            0x4b0db5a2d9adbee6l },
-          { 0x9bc9f1e3c2a304e8l,0xbaa61de7de406fa8l,0x8e921ca9e4bec498l,
-            0xd9f4e5ae6604ab02l },
-          0 },
-        /* 51 << 136 */
-        { { 0xdf6b97b5b37f2097l,0x7576c3f9b4a5d2b9l,0x6eb697ed3588cabbl,
-            0x4d75b38622598d8fl },
-          { 0x4e6d93b522ff55e8l,0x4620ec635b8f7edal,0xd5006209f97b7749l,
-            0x9e22e3a84da8b464l },
-          0 },
-        /* 52 << 136 */
-        { { 0xbabfb7f82e8f326fl,0xed9cac225625a519l,0xf1109c1a0edae0a9l,
-            0x45f80a9858521259l },
-          { 0x37a44b075ab71f44l,0x21699eb64a21161bl,0xb523fddf56fe67eel,
-            0x9f5c3a2120b9f72el },
-          0 },
-        /* 53 << 136 */
-        { { 0x12c1131508b75673l,0xfa20121823b096d6l,0x839f01aeeacd6537l,
-            0x0e592be787df32cal },
-          { 0xfe3f65ff8b7dd0fcl,0xed09b4875c1d9a80l,0x8c09dd97b79786d8l,
-            0x74eba2806c5bc983l },
-          0 },
-        /* 55 << 136 */
-        { { 0xf917704862987b50l,0xcc84cdc6bc4ac456l,0x8bd2c922ae08fe12l,
-            0x09d5f661fc2d06c7l },
-          { 0xd10ac6dd9457d47fl,0x65aa30a23668060cl,0x33cddac6745161fcl,
-            0xf4c18b5ea51e540fl },
-          0 },
-        /* 57 << 136 */
-        { { 0x591c064ede723c1fl,0x92e5d4e601a4adael,0x3d7ee8a3145716ecl,
-            0x0ef4c62061727816l },
-          { 0x0e17c576f1bf6d6el,0x173104015ae18045l,0xdad620aae9589b75l,
-            0xb10c7e2d0eda4905l },
-          0 },
-        /* 59 << 136 */
-        { { 0xb8020f16aa08df6fl,0x03cf58ffd67054e9l,0x302e003c11fe3d1al,
-            0x9c194bc1c638a3ecl },
-          { 0x8ed3cb3adefd3f1el,0xc4115e079bf39de4l,0x8dece48bdf46fdf6l,
-            0xebd1dbcf30eafeafl },
-          0 },
-        /* 60 << 136 */
-        { { 0x058eb276fba319c5l,0xd33a91127f7fa54al,0xf060c1b4932a2dabl,
-            0xce3a224e79c7d9bfl },
-          { 0x6fb0388c0ba92823l,0x8d31738a69787881l,0x2d86eb0203cd00b7l,
-            0x4e6e44512b69911bl },
-          0 },
-        /* 61 << 136 */
-        { { 0xff2efe1cfdcca1cfl,0x08f22c69b5bb71e3l,0xc63f4a9f7023076el,
-            0x88fb2aa0ce0c490el },
-          { 0xcc7c97f91f77783cl,0x360026d942ab36b7l,0x547c34ecefd68f70l,
-            0xebe7f99efbabfdabl },
-          0 },
-        /* 63 << 136 */
-        { { 0xe7c1c1788613e87al,0xb035d65e60b82654l,0x055a82d03583a254l,
-            0x27ce1ffc9b3b22fal },
-          { 0x0cf904917ec83cd5l,0xfc6c21805604aa40l,0x1330604099357428l,
-            0x9b0982f9ad4818b7l },
-          0 },
-        /* 64 << 136 */
-        { { 0xc222653a4f0d56f3l,0x961e4047ca28b805l,0x2c03f8b04a73434bl,
-            0x4c966787ab712a19l },
-          { 0xcc196c42864fee42l,0xc1be93da5b0ece5cl,0xa87d9f22c131c159l,
-            0x2bb6d593dce45655l },
-          0 },
-        /* 65 << 136 */
-        { { 0x3a6080d9fb56bc3al,0xf1552dcad6212d7el,0x977ac5b59420f4f6l,
-            0xef914d370e3cd97fl },
-          { 0x807bd6e69c04f768l,0x743a7b552bb803f6l,0x7f5c20804215f4b0l,
-            0x41e331288fc6ce42l },
-          0 },
-        /* 71 << 136 */
-        { { 0x5a31c9ac61e6a460l,0x55102e4093e7eeddl,0x969fe0612da6adcel,
-            0xe8cddc2f3ffea1d9l },
-          { 0xaa26c6b1f0f327c5l,0x9e5b63743544f5e1l,0x5159fa1ddbaa685bl,
-            0x9892d03aa7f44b99l },
-          0 },
-        /* 77 << 136 */
-        { { 0x4dfcbf12e2c6fc1fl,0x703f2f5b7535ac29l,0x78f8617e82f7dc0fl,
-            0x54b835ff853e792dl },
-          { 0x3cc7f000df9f7353l,0x0d7ffd68db5a157al,0x2c1c33691672b21cl,
-            0x694b4904ac970ef8l },
-          0 },
-        /* 83 << 136 */
-        { { 0xd655bc42c1d2c45cl,0x572f603cbd22b05fl,0xa7fbf09388e4531al,
-            0x8d38bbd91fdde98dl },
-          { 0x16cc2aaa73b0fa01l,0x515019a25e8ffb04l,0xb075990611e792ccl,
-            0x89df06f399112c90l },
-          0 },
-        /* 89 << 136 */
-        { { 0x26d435c2481b46dal,0x73ab7e96266e9b3al,0x22d5b1db3c613c40l,
-            0x9de4021c6727e399l },
-          { 0x451ebba56051f8c9l,0xa37f6ec52c281a58l,0x3d7a28fe0e9f4cc5l,
-            0x0f45bcd655b64df7l },
-          0 },
-        /* 95 << 136 */
-        { { 0xba2a718c66616fbel,0x4b27810b3369a9acl,0x50b8391a2b426d5fl,
-            0x420c88efa626fa05l },
-          { 0xe39cef97b9c39a30l,0xcae7cde85e67e5d0l,0x3821f8319a58e521l,
-            0xbf474d1941479509l },
-          0 },
-        /* 101 << 136 */
-        { { 0x401bbab58fb15118l,0xb0376892dbf38b39l,0x10e4b9dd3a3ca42al,
-            0xa69c2693f8063ffel },
-          { 0xe10facdde07cb761l,0x96f4dde831d7759al,0xd702fdecc2cc7f9fl,
-            0x9e87e46e1ac0162cl },
-          0 },
-        /* 107 << 136 */
-        { { 0xb6cd60518479ca8fl,0xcca345e60968f6c7l,0x7b57248a64a9afe7l,
-            0x5552e3511d0d4db9l },
-          { 0x8f749b199dc68aabl,0x0fb86f06db1f7819l,0x23b300963143ac09l,
-            0x61c166d8abfbcb9bl },
-          0 },
-        /* 113 << 136 */
-        { { 0x4c96e85a43101165l,0x393a882fcf39bd19l,0xef9e1d42c2df6f33l,
-            0xe1775c990278f088l },
-          { 0xb1581929a9250d4al,0x582b0608c4168873l,0x0b3ffba3a1e68cd8l,
-            0x3f78147ef9490897l },
-          0 },
-        /* 116 << 136 */
-        { { 0x277b5177eb18ff20l,0x48002e9828f06d62l,0xece8d6c30e506d8dl,
-            0x5cde0a58cd9ff963l },
-          { 0x3b97cdb74e3baa0el,0x50560c0b631238f9l,0xe1c31b35cf79793dl,
-            0x95d12f14355e2178l },
-          0 },
-        /* 119 << 136 */
-        { { 0x0143f695bcc31b77l,0x3627aed14c49b65al,0x6e4f7a9ce441c183l,
-            0xb708c79de1bfa0a3l },
-          { 0xdbf0fc313a0726b8l,0xe04d82a8852d78bbl,0xb859001e3be5d398l,
-            0x92dcc20c8e89bd11l },
-          0 },
-        /* 125 << 136 */
-        { { 0x5f2416a3df9026b4l,0xffc01f3afcb29a1bl,0x18d02c9f1d94b20fl,
-            0xd93b0f2f81cfdef3l },
-          { 0xe6b0fd4713adf5f2l,0xcc9067b7ba06dff3l,0xb48c0cbb2256f842l,
-            0xc2ae741dfd34df2fl },
-          0 },
-    },
-    {
-        /* 0 << 144 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 144 */
-        { { 0x80531fe1c63c4962l,0x50541e89981fdb25l,0xdc1291a1fd4c2b6bl,
-            0xc0693a17a6df4fcal },
-          { 0xb2c4604e0117f203l,0x245f19630a99b8d0l,0xaedc20aac6212c44l,
-            0xb1ed4e56520f52a8l },
-          0 },
-        /* 3 << 144 */
-        { { 0x18f37a9c6bdf22dal,0xefbc432f90dc82dfl,0xc52cef8e5d703651l,
-            0x82887ba0d99881a5l },
-          { 0x7cec9ddab920ec1dl,0xd0d7e8c3ec3e8d3bl,0x445bc3954ca88747l,
-            0xedeaa2e09fd53535l },
-          0 },
-        /* 4 << 144 */
-        { { 0xa12b384ece53c2d0l,0x779d897d5e4606dal,0xa53e47b073ec12b0l,
-            0x462dbbba5756f1adl },
-          { 0x69fe09f2cafe37b6l,0x273d1ebfecce2e17l,0x8ac1d5383cf607fdl,
-            0x8035f7ff12e10c25l },
-          0 },
-        /* 5 << 144 */
-        { { 0xb7d4cc0f296c9005l,0x4b9094fa7b0aebdbl,0xe1bf10f1c00ec8d4l,
-            0xd807b1c4d667c101l },
-          { 0xa9412cdfbe713383l,0x435e063e81142ba1l,0x984c15ecaf0a6bdcl,
-            0x592c246092a3dab9l },
-          0 },
-        /* 7 << 144 */
-        { { 0x9365690016e23e9dl,0xcb220c6ba7cc41e1l,0xb36b20c369d6245cl,
-            0x2d63c348b62e9a6al },
-          { 0xa3473e19cdc0bcb5l,0x70f18b3f8f601b98l,0x8ad7a2c7cde346e4l,
-            0xae9f6ec3bd3aaa64l },
-          0 },
-        /* 9 << 144 */
-        { { 0x030223503274c7e1l,0x61ee8c934c4b6c26l,0x3c4397e3199389cel,
-            0xe0082600488757cel },
-          { 0xaac3a2df06b4dafbl,0x45af0700ddff5b6al,0x0a5974248c1d9fa0l,
-            0x1640087d391fc68bl },
-          0 },
-        /* 10 << 144 */
-        { { 0x26a43e41d07fa53dl,0x3154a78a74e35bc5l,0x7b768924e0da2f8cl,
-            0xba964a2b23613f9al },
-          { 0x5a548d35ba1d16c4l,0x2e1bfed1fb54d057l,0xff992136bc640205l,
-            0xf39cb9148156df29l },
-          0 },
-        /* 11 << 144 */
-        { { 0xf4873fcf4e5548bdl,0x8725da3f03ce57f0l,0xd82f5c95ca953258l,
-            0xac647f127cf0747el },
-          { 0xff2038b02d570bd5l,0xb0c2a767a13ae03fl,0xebaa27cde9932d16l,
-            0xa686e3fc1234e901l },
-          0 },
-        /* 13 << 144 */
-        { { 0x9f80435e63261eccl,0x6302a62e4337d6c9l,0x91916a49ca4958a0l,
-            0x554958993149d5d3l },
-          { 0x378d020b9f91de3cl,0x47b839a34dd25170l,0x2825854138b7f258l,
-            0xea5b14f7437e7decl },
-          0 },
-        /* 15 << 144 */
-        { { 0x74f08736b0018f44l,0xf4a03417b446d0f5l,0x66a4aa2fa40ca6b2l,
-            0x215679f0badb60edl },
-          { 0x3871195a323e4eefl,0x8f0940c320952b16l,0xfe8dac62879d5f7dl,
-            0x649cb623c1a6e875l },
-          0 },
-        /* 16 << 144 */
-        { { 0xecaff541338d6e43l,0x56f7dd734541d5ccl,0xb5d426de96bc88cal,
-            0x48d94f6b9ed3a2c3l },
-          { 0x6354a3bb2ef8279cl,0xd575465b0b1867f2l,0xef99b0ff95225151l,
-            0xf3e19d88f94500d8l },
-          0 },
-        /* 17 << 144 */
-        { { 0xa26a9087133ec108l,0x5dc5699f2712bdc0l,0x96903f4dd14224a9l,
-            0x3da5992429e47b80l },
-          { 0xb717712ff9dbba5al,0x9e52004b756391c9l,0xe669a11dcc9d219cl,
-            0x3b6e6b84d1d6c07dl },
-          0 },
-        /* 19 << 144 */
-        { { 0x5feec06a676feadbl,0xfc449bc59d69f322l,0x1d8d7b5e7cda8895l,
-            0x5ed54dc11a3314a7l },
-          { 0x1a11d2ae6de889c0l,0xb2a979724ced2bd9l,0x6ecf6989306a5ef6l,
-            0x1611d57b8cc8a249l },
-          0 },
-        /* 21 << 144 */
-        { { 0x2d9942ba007cbf87l,0x4e62bce6df3fc926l,0xe7eee5b0e4560affl,
-            0xe51963bb7cb009b7l },
-          { 0xaa5118cee29b37ddl,0x5cd84a4747263903l,0x3050caa6620055d8l,
-            0x7ef576a76c4b1e3dl },
-          0 },
-        /* 23 << 144 */
-        { { 0x9026a4dde6008ff1l,0x49e995ad1c8cd96cl,0x80722e73503e589bl,
-            0x05bcbce184c2bc26l },
-          { 0x255f9abbd4682c2cl,0xc42bcfc2f084d456l,0xa0eae9b0641c0767l,
-            0x1b45632d864c9a2dl },
-          0 },
-        /* 25 << 144 */
-        { { 0xcf25793b6ae024e0l,0x1b6607b484b5c4b0l,0x9579fa903f1624c8l,
-            0x37fb65be68bd57e8l },
-          { 0xd693a55efc39c203l,0x4e267ac4c87252e9l,0xb8d78bb09f899413l,
-            0xe4c014070b3b8508l },
-          0 },
-        /* 27 << 144 */
-        { { 0x662906e5bc3f3553l,0xde38d53531459684l,0x8f46a8c634f7280dl,
-            0xaaf91b873d24198el },
-          { 0xecd5ee115f9b117el,0xce00ffbe50ae8ddal,0x263a3d4e7710a9ael,
-            0x0ff3f721f26ba74fl },
-          0 },
-        /* 28 << 144 */
-        { { 0x4a8a4f47f0cefa69l,0xdc8e4cbaa4546866l,0x359ba69b23f603c1l,
-            0xdab4d601187b7ac5l },
-          { 0xa6ca4337c1ebc8d9l,0x9fa6585452b4074bl,0x1a4b4f81902fb733l,
-            0xd2bb5d7aa525deaal },
-          0 },
-        /* 29 << 144 */
-        { { 0xcc287ac2e6b3577al,0xd7528ca7f612003bl,0x8afdb6f12c1400b8l,
-            0x103a2ed346a2dd8dl },
-          { 0xc8f8c54d2ee21339l,0x8f011b92355a2d20l,0x81c6fc9f1346f2acl,
-            0xdb6042f005a6d24bl },
-          0 },
-        /* 31 << 144 */
-        { { 0xfc90e3630da4f996l,0x8ceca49daa6d6fe4l,0x1084affdbdfc619bl,
-            0x2029f672c1140b04l },
-          { 0x606ec25f136f3e5el,0x6d24149b02224c4al,0xabb0f142cfdfcf4cl,
-            0xe40d0419fab1a0edl },
-          0 },
-        /* 33 << 144 */
-        { { 0xcfdd08265cbccb84l,0x2258a16e88ad93c4l,0xb3ac365e728c5ad3l,
-            0x0bbf97808560df1fl },
-          { 0x42d08a39bad8c7b8l,0x1e3960106d3e8b91l,0xc332b39910274f58l,
-            0xe0a84dacce2ea778l },
-          0 },
-        /* 34 << 144 */
-        { { 0x113e1189ff432945l,0x4a0d2c3d04e1106cl,0xcde487744f3597b1l,
-            0x853b029174fa26eal },
-          { 0x2149e0ff02662e26l,0xb3181eaa5e6a030fl,0x086fc2159b006340l,
-            0xa1df84a694a4e0bbl },
-          0 },
-        /* 35 << 144 */
-        { { 0xc2cbd80ac99f8d3dl,0xe24b9d8f50ecf4f4l,0xf18d34728ecb126al,
-            0x83966662e1670aael },
-          { 0x1cece80fda5f594el,0x545e94ae65f391e0l,0xf3286dff93f98bb7l,
-            0xf945e6cdf5abf176l },
-          0 },
-        /* 36 << 144 */
-        { { 0x00ba5995dd95ac33l,0xa4957a40738f3bf4l,0x073539f599438a85l,
-            0xcc9c43acc2eb1411l },
-          { 0xe27501b5be2ec3d2l,0xa88d4ed057a85458l,0x870ae236755c8777l,
-            0x0933c5af89216cbal },
-          0 },
-        /* 37 << 144 */
-        { { 0xb5feea219e40e37fl,0x8c5ccb159e20fd60l,0xaeddc502ce8209a1l,
-            0xbdf873cc11e793b3l },
-          { 0xbc938103f0de8db5l,0x619fb72fb0e9d3d5l,0x800147cb588ed2adl,
-            0x260f92bb7901ced8l },
-          0 },
-        /* 39 << 144 */
-        { { 0x72dd9b089848c699l,0xc6086381185dacc1l,0x9489f11ff7d5a4c8l,
-            0xedb41d5628dee90fl },
-          { 0x1091db6b09af693cl,0xc7587551ae4b6413l,0x806aefb0768227adl,
-            0x4214b83eafb3c88el },
-          0 },
-        /* 40 << 144 */
-        { { 0xddfb02c4c753c45fl,0x18ca81b6f9c840fel,0x846fd09ab0f8a3e6l,
-            0xb1162adde7733dbcl },
-          { 0x7070ad20236e3ab6l,0xf88cdaf5b2a56326l,0x05fc8719997cbc7al,
-            0x442cd4524b665272l },
-          0 },
-        /* 41 << 144 */
-        { { 0x748819f9aa9c0ef5l,0xd7227d8ba458ad48l,0x8d67399f27aef626l,
-            0xc6241a1859bf0a4cl },
-          { 0xed9b0bfcc31cb9bbl,0x591254f896142555l,0x80e4bab461134151l,
-            0x7c5e680243efbd83l },
-          0 },
-        /* 43 << 144 */
-        { { 0x7f3f5a1706b9b7ddl,0x392132e75faeb417l,0x508ac4788fae38a2l,
-            0x2b854ead0d3499c3l },
-          { 0x26a687d8ef18bf0fl,0x62ff0c4a8ae00b61l,0x84111011f48578f2l,
-            0xa879f383cd0fcd3al },
-          0 },
-        /* 44 << 144 */
-        { { 0xeb7615aa202992f0l,0xde0562b38361d0b3l,0x789a302862027ee0l,
-            0xe3e3e9921048f899l },
-          { 0x07945c246deadab4l,0xeb06a15ec77d894el,0xb825af36bab1416bl,
-            0x99083c4df4b4e04fl },
-          0 },
-        /* 45 << 144 */
-        { { 0x4684a8f27b3ad6c3l,0x58238dbd928d9b6bl,0x31865b998da2c495l,
-            0xc1ca784fb8e7cda1l },
-          { 0xc9605dc71e081572l,0x8f560bcdef8ed104l,0x51f73981bd3feaedl,
-            0xc778aa4e4251c88dl },
-          0 },
-        /* 46 << 144 */
-        { { 0x9c0daa63aa502800l,0x73c7959a1e15b9bdl,0xd0447bcb7ab10f6cl,
-            0x05b8fbc8b8311bdel },
-          { 0xa8a74be1915d5c4el,0x38d41c1e0b7c0351l,0x5bb2d49ff52d6568l,
-            0x6c48d8eed5e43593l },
-          0 },
-        /* 47 << 144 */
-        { { 0x387b26d554159498l,0x92e92fad1ec34eb4l,0x0f88705e7a51b635l,
-            0x66bcbf4dedca735fl },
-          { 0x0a4c6112dcb896ccl,0x148e1dfe6fc72ad9l,0x3de977fd2b4c9585l,
-            0x0cd6e65f741e62cal },
-          0 },
-        /* 48 << 144 */
-        { { 0x7807f364b71698f5l,0x6ba418d29f7b605el,0xfd20b00fa03b2cbbl,
-            0x883eca37da54386fl },
-          { 0xff0be43ff3437f24l,0xe910b432a48bb33cl,0x4963a128329df765l,
-            0xac1dd556be2fe6f7l },
-          0 },
-        /* 49 << 144 */
-        { { 0x98ae40d53ce533bal,0x10342e1931fdd9c2l,0x54a255c8abf8b2bfl,
-            0x8facc41b15f6fef7l },
-          { 0x2e195565bc65b38bl,0xb9f3abaaeaea63cbl,0xede2ab9bf2b7518bl,
-            0x5e84102ce9ea3d81l },
-          0 },
-        /* 51 << 144 */
-        { { 0x162abc35113bc262l,0x8012f06829eb3fd4l,0x0e2727eb2c1ccf9cl,
-            0x89561ff44b455b20l },
-          { 0xc48db835ee3b1fd4l,0x4075ca86095bbfa7l,0x0c498d7d98745182l,
-            0x828fb93c5dfb5205l },
-          0 },
-        /* 52 << 144 */
-        { { 0xf95c7a5f0a76333bl,0x07603929cd607927l,0xabde328591028d3el,
-            0x55765e8fa032a400l },
-          { 0x3041f2cabed17cd7l,0x018a5b7b9a9e5923l,0xca4867975bb9bae3l,
-            0x741c802ecc382cb5l },
-          0 },
-        /* 53 << 144 */
-        { { 0x182a10311e5a3d8el,0xc352b8c8986c4d10l,0x7c50a172434c02ebl,
-            0x121d728c4420c41cl },
-          { 0x0f8eca2a8a51812fl,0xdb6c4a4ea5158430l,0x67944e0b8d8f4144l,
-            0x387cc2052405c77al },
-          0 },
-        /* 55 << 144 */
-        { { 0x98b36eb47e95ad76l,0x1973fa7d5f7e5ff7l,0xc4827abc6cc8a25cl,
-            0x4263a0d3ec822ae4l },
-          { 0x49f113f35217a6f4l,0xf27cc9bb81748aa6l,0x9cb81d97d822e08el,
-            0x698d2826b5c360bcl },
-          0 },
-        /* 57 << 144 */
-        { { 0x895f81514eb6d0b8l,0x32ef71df9f786536l,0x032a449430379a79l,
-            0xa8c1076218bdb83fl },
-          { 0x7a3b0b8fe53a4064l,0x0e724a54e2ce89b7l,0x565baeba7a31f6bcl,
-            0x12b9fa6387d18a7bl },
-          0 },
-        /* 59 << 144 */
-        { { 0x027231a3585bcfbdl,0x8690e977dca24269l,0x229c021afc6f1422l,
-            0xd98050d044084cabl },
-          { 0x6add95d79d4fd09al,0x12484c68c15b24ddl,0xa79a8f4facf4f551l,
-            0xf53204e27a83cbecl },
-          0 },
-        /* 60 << 144 */
-        { { 0xbc006413a906f7aal,0x9c8cd648bbeaf464l,0xaf5c7c64fb78cdf2l,
-            0xe45839eafabc2375l },
-          { 0x1eb89bd150012172l,0x9d0d76194488518cl,0xd55a7238bd534d32l,
-            0x48f35d5e95b4fe55l },
-          0 },
-        /* 61 << 144 */
-        { { 0xa6c5574f3e70a35al,0x35c11b5a8df97d97l,0x8f629f6cda85dd27l,
-            0x94dab294c218452el },
-          { 0xa2e1882e8916c731l,0xc02ce77c8929e350l,0xa7ed351fe4eff8afl,
-            0xeb76ef0654c3e1c1l },
-          0 },
-        /* 63 << 144 */
-        { { 0xc31d7cf87e3f5be5l,0x1472af0d3ce7f3a0l,0x226414f8f962e1afl,
-            0xd318e3df16f54295l },
-          { 0x9a3f6aaf41477cd3l,0x7034172f66ec6b2el,0xbea54eb537413a62l,
-            0x79f81262dc515e73l },
-          0 },
-        /* 64 << 144 */
-        { { 0x994f523a626332d5l,0x7bc388335561bb44l,0x005ed4b03d845ea2l,
-            0xd39d3ee1c2a1f08al },
-          { 0x6561fdd3e7676b0dl,0x620e35fffb706017l,0x36ce424ff264f9a8l,
-            0xc4c3419fda2681f7l },
-          0 },
-        /* 65 << 144 */
-        { { 0xb71a52b8b6bf8719l,0x0c7701f73196db36l,0xff1b936f53141cf4l,
-            0x684d8a3c1b94a31cl },
-          { 0xe555633ab52386e1l,0x9353a2af91450578l,0xc53db6fab99b14bcl,
-            0x1f2d42adcf619d36l },
-          0 },
-        /* 71 << 144 */
-        { { 0xbeb535ef3851c573l,0x3105fff585589843l,0xbe9f62a1d47aaf06l,
-            0x6bb2ee5d107e1131l },
-          { 0x82530247a4a7699fl,0x3fb475e144872afbl,0x8ad43fd73c4c49f2l,
-            0x3f7632882e045fc4l },
-          0 },
-        /* 77 << 144 */
-        { { 0x48440beb2924d7b2l,0x234163809c88fc57l,0xdc1d23d54ab08c2bl,
-            0x576400b6e70feab0l },
-          { 0x3b8afb8ba66da779l,0x7a7e3bf445468f16l,0x1976ddf3231f79dfl,
-            0xbe61c170b8531a9el },
-          0 },
-        /* 83 << 144 */
-        { { 0xf8d2dc768bf191b2l,0x3269e68813a39eb9l,0x104bb84be755eccfl,
-            0xb8d1330f2868f807l },
-          { 0x2b29c74cb06c6059l,0x3648baa1a6440a26l,0x5dfae323f1e6b2c9l,
-            0x9d0319b79330ac0al },
-          0 },
-        /* 89 << 144 */
-        { { 0x526ba3770e708bb2l,0x95c21ba327565dd9l,0x7071f46d48a0a873l,
-            0xe4b9959efed6cc74l },
-          { 0x1b16bfd1e08a5afal,0xc87fec98d1789782l,0x200186e946cfd068l,
-            0x88ea35a7280bf3ebl },
-          0 },
-        /* 95 << 144 */
-        { { 0x9e31943d42ac0e6cl,0xe61374cf1db8e40fl,0xbe27ea35a27db609l,
-            0x7c5b91d67bf192e9l },
-          { 0xc2af846defd0a24bl,0x1b2efc37669b647al,0xbfc3c38e5e58ef8al,
-            0xb6afb167e13ab5a2l },
-          0 },
-        /* 101 << 144 */
-        { { 0x08612d29b9f2aad4l,0x43c41330ad09dd17l,0xa45cb84a9f740519l,
-            0x0a9ea9a7512ec031l },
-          { 0x6e90dccaee747f35l,0xe4388bd1f0a1479bl,0x966140c4e20a9029l,
-            0x1bb1f65d7dd956abl },
-          0 },
-        /* 107 << 144 */
-        { { 0x066d206ea8f12bb3l,0xc9023b1b4325ec13l,0x1f56c72c96ead8ddl,
-            0x454050fd8003e4c2l },
-          { 0x9ca258a58917aa9dl,0xfe24b282d94593cfl,0xea66c203752741cfl,
-            0x5714268c295a895el },
-          0 },
-        /* 113 << 144 */
-        { { 0x72a9fbecc177d694l,0x38bb9387d68454d3l,0xa3d347bf590bc7d2l,
-            0xcb6e292605ccc234l },
-          { 0x588abfcf0d393c01l,0xf053dadf539e5568l,0xad7480fef2a8b157l,
-            0xff28c8bb018cac8fl },
-          0 },
-        /* 116 << 144 */
-        { { 0x12f1a00e7f5b8821l,0x0afa44e489b4b0cel,0x2dcaad8f6006338el,
-            0x79c022cdba41242bl },
-          { 0x7f6ef7e17871d350l,0x946c2a91674253adl,0xf686d137a9cbbdd9l,
-            0xa47ce2eaf7d4f9f2l },
-          0 },
-        /* 119 << 144 */
-        { { 0x1824991b205d40d6l,0x49cca1c085046a90l,0x7e23c1acd005e3c2l,
-            0x093a9ae6d102c8ffl },
-          { 0xf4791082d2f40843l,0xe456021811645483l,0x8a59c3b0fd3a6b39l,
-            0x39130e7f820de158l },
-          0 },
-        /* 125 << 144 */
-        { { 0xf7eef88d83b90783l,0xff60762af336d581l,0xf64f2d5dd801f5a0l,
-            0x672b6ee7d6b3b8b9l },
-          { 0xa2a2dceb08034d69l,0x3eca27f635638218l,0xe7065986fa17fefdl,
-            0xf1b74445f5803af1l },
-          0 },
-    },
-    {
-        /* 0 << 152 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 152 */
-        { { 0x32670d2f7189e71fl,0xc64387485ecf91e7l,0x15758e57db757a21l,
-            0x427d09f8290a9ce5l },
-          { 0x846a308f38384a7al,0xaac3acb4b0732b99l,0x9e94100917845819l,
-            0x95cba111a7ce5e03l },
-          0 },
-        /* 3 << 152 */
-        { { 0x37a01e48a105fc8el,0x769d754a289ba48cl,0xc08c6fe1d51c2180l,
-            0xb032dd33b7bd1387l },
-          { 0x953826db020b0aa6l,0x05137e800664c73cl,0xc66302c4660cf95dl,
-            0x99004e11b2cef28al },
-          0 },
-        /* 4 << 152 */
-        { { 0x214bc9a7d298c241l,0xe3b697ba56807cfdl,0xef1c78024564eadbl,
-            0xdde8cdcfb48149c5l },
-          { 0x946bf0a75a4d2604l,0x27154d7f6c1538afl,0x95cc9230de5b1fccl,
-            0xd88519e966864f82l },
-          0 },
-        /* 5 << 152 */
-        { { 0x1013e4f796ea6ca1l,0x567cdc2a1f792871l,0xadb728705c658d45l,
-            0xf7c1ff4ace600e98l },
-          { 0xa1ba86574b6cad39l,0x3d58d634ba20b428l,0xc0011cdea2e6fdfbl,
-            0xa832367a7b18960dl },
-          0 },
-        /* 7 << 152 */
-        { { 0x1ecc032af416448dl,0x4a7e8c10ec76d971l,0x854f9805b90b6eael,
-            0xfd0b15324bed0594l },
-          { 0x89f71848d98b5ca3l,0xd01fe5fcf039b3efl,0x4481332e627bda2el,
-            0xe67cecd7a5073e41l },
-          0 },
-        /* 9 << 152 */
-        { { 0x2ab0bce94595a859l,0x4d8c2da082084ee7l,0x21ff8be5acca3d3cl,
-            0xd8b805337827f633l },
-          { 0xf74e8c026becabbfl,0x9fae4dbefede4828l,0xd3885a5b3cc46bcfl,
-            0x2d535e2b6e6ad144l },
-          0 },
-        /* 10 << 152 */
-        { { 0x63d3444507d9e240l,0x6fbadf4338cff7e6l,0x8717624a959c9461l,
-            0xd7d951c411fb775bl },
-          { 0x4049161af6fc3a2bl,0x0dfa2547a1a8e98dl,0xeca780d439c2139cl,
-            0xd8c2d8cbd73ea8efl },
-          0 },
-        /* 11 << 152 */
-        { { 0x3aa1974f07605b28l,0x4f3d82a71e296255l,0xbbe5ea03b4e23f16l,
-            0x8f5c6c6b4e654193l },
-          { 0x27181182d3e8ab01l,0xc68bb231f3ba6bc2l,0x90a244d820af1fd7l,
-            0x605abc055b713f4fl },
-          0 },
-        /* 13 << 152 */
-        { { 0xca5fe19bd221991al,0x271ff066f05f400el,0x9d46ec4c9cf09896l,
-            0xdcaa8dfdec4febc3l },
-          { 0xaa3995a0adf19d04l,0xc98634239da573a6l,0x378058b2f2465b2bl,
-            0x20d389f9b4c31612l },
-          0 },
-        /* 15 << 152 */
-        { { 0xd7d199c7b7631c9dl,0x1322c2b8bb123942l,0xe662b68fbe8b6848l,
-            0xc970faf2cde99b14l },
-          { 0x61b27134b06655e5l,0xadcef8f781365d89l,0x917b5ab521b851aal,
-            0x4f4472121cf694a7l },
-          0 },
-        /* 16 << 152 */
-        { { 0x488f1185ca8d9d1al,0xadf2c77dd987ded2l,0x5f3039f060c46124l,
-            0xe5d70b7571e095f4l },
-          { 0x82d586506260e70fl,0x39d75ea7f750d105l,0x8cf3d0b175bac364l,
-            0xf3a7564d21d01329l },
-          0 },
-        /* 17 << 152 */
-        { { 0x241e3907fe44e547l,0x42d464c36b992187l,0xeaa8fa989ba72f28l,
-            0x965a8b8f6afbb81fl },
-          { 0x69356a7a8b375ea5l,0x22501ec741bdcc83l,0xf80f4e1445fb180cl,
-            0xc0b12e95f5e1b822l },
-          0 },
-        /* 19 << 152 */
-        { { 0x977234e05483dc02l,0x0167430c13d8dcb2l,0xa9971278049912edl,
-            0xab044b18ca40fa39l },
-          { 0xac9587449ff3896cl,0x75bb32eb860d1240l,0xf807071f6b958654l,
-            0x67d2d3dc7121b4b6l },
-          0 },
-        /* 21 << 152 */
-        { { 0x3b61e67722f9f017l,0x9c593eb1a8541696l,0xbeba950050eda653l,
-            0x07b5a48f5e673f6al },
-          { 0x748dca0013257aa3l,0x6bbddf9a7372e942l,0xc012f4badde83977l,
-            0x6e59b327392ddb53l },
-          0 },
-        /* 23 << 152 */
-        { { 0xb2f3fff641356603l,0x50e63537545f042bl,0x55e5149770eb530dl,
-            0x5a7383c310860c3bl },
-          { 0x7be30382ea669a09l,0xfdf735d289cc1c7fl,0x6e51ed844e0607cfl,
-            0xdab566df4893795el },
-          0 },
-        /* 25 << 152 */
-        { { 0x20e3be0f8920690dl,0x98db80eaac279c05l,0x4cd5c60a44b8a4f8l,
-            0xeda7e91c7b0335f4l },
-          { 0x45c1302a41ee5713l,0x1f6455fe588508d0l,0x82cb7311163d2fc3l,
-            0xe866b90322f10b71l },
-          0 },
-        /* 27 << 152 */
-        { { 0xc217a2e259b4041el,0x85b96ce274526cbfl,0xcbfc4f5473f12687l,
-            0x097caa5fd40225e7l },
-          { 0x0871ad406e91293fl,0x5f2ea207033b98ecl,0x0b3b8fac1f27d37al,
-            0x7d72dd4c7f03876cl },
-          0 },
-        /* 28 << 152 */
-        { { 0xb51a40a51e6a75c1l,0x24327c760ea7d817l,0x0663018207774597l,
-            0xd6fdbec397fa7164l },
-          { 0x20c99dfb13c90f48l,0xd6ac5273686ef263l,0xc6a50bdcfef64eebl,
-            0xcd87b28186fdfc32l },
-          0 },
-        /* 29 << 152 */
-        { { 0x2f0c49ac95861439l,0xcdcb051b2e36e38al,0x459474080ae20c0cl,
-            0x374baad2dddf0aabl },
-          { 0x291abc85d5d104a4l,0x0758001958a0657cl,0xd0f428e1a905ea13l,
-            0x12599ddcf7241dbfl },
-          0 },
-        /* 31 << 152 */
-        { { 0x16222ce81bc3c403l,0xbacc1508fc13ca02l,0xfa98db4d920ee8e9l,
-            0xe5fc39c4df12a359l },
-          { 0x4e8c9b90188733e8l,0x04283dd81394936cl,0x93b3db51cd130432l,
-            0x33bfe3163c93ce31l },
-          0 },
-        /* 33 << 152 */
-        { { 0xb48591e9840b1724l,0x1009559f5885ec6fl,0x45ee51121b077620l,
-            0x848f9800f1f4cc8al },
-          { 0x6ec1e0f74e97bceal,0x953bc23a98e80642l,0x9f0d1e8194ce7181l,
-            0xeb3e6b9700eec596l },
-          0 },
-        /* 34 << 152 */
-        { { 0x6d34b39bff7514dal,0x29ffe49825be3634l,0x63e56598f28c8b82l,
-            0x78b99133aab41bcel },
-          { 0x11febd5a52563180l,0xa3be94c5c356a8c0l,0x5e9b422e0d61f864l,
-            0x2bf4ca1278fd259el },
-          0 },
-        /* 35 << 152 */
-        { { 0x8f60e40266914514l,0x6d9e280fef178167l,0x2ff7aec9e2949a48l,
-            0x422389ce72d37511l },
-          { 0xe9b156f3307ac1d2l,0x1cb581a78518e79fl,0x56d43f302185cf82l,
-            0x8d46c5aade59562cl },
-          0 },
-        /* 36 << 152 */
-        { { 0x50fc0711745edc11l,0x9dd9ad7d3dc87558l,0xce6931fbb49d1e64l,
-            0x6c77a0a2c98bd0f9l },
-          { 0x62b9a6296baf7cb1l,0xcf065f91ccf72d22l,0x7203cce979639071l,
-            0x09ae4885f9cb732fl },
-          0 },
-        /* 37 << 152 */
-        { { 0xd007d682e4b35428l,0x80c162315bcdc0d6l,0xe55a86bd36fce9b2l,
-            0x16772edb969a87cfl },
-          { 0xff323a2d3f370c94l,0x8d3c8028bf3c1afcl,0x4e1591e73b0c3fafl,
-            0xfbd6475cb981ce83l },
-          0 },
-        /* 39 << 152 */
-        { { 0xcf414ae3315b2471l,0xf54abf8033168de6l,0x6883efc5df5cdb24l,
-            0x3eca788c8efe81acl },
-          { 0xdb58c6c778eeccadl,0x3c77939082fecfb7l,0x5736cdd9c9b513f3l,
-            0xab7e6ea57b02aaf2l },
-          0 },
-        /* 40 << 152 */
-        { { 0x5e7c3becee8314f3l,0x1c068aeddbea298fl,0x08d381f17c80acecl,
-            0x03b56be8e330495bl },
-          { 0xaeffb8f29222882dl,0x95ff38f6c4af8bf7l,0x50e32d351fc57d8cl,
-            0x6635be5217b444f0l },
-          0 },
-        /* 41 << 152 */
-        { { 0x2cec7ba64805d895l,0x4c8399870ac78e7cl,0x031ad6c7f79416c5l,
-            0x1b2f2621f1838d2fl },
-          { 0x60835eac91447f90l,0x59147af1f9bab5d9l,0x7a3005d6f393f175l,
-            0x8cf3c468c4120ba2l },
-          0 },
-        /* 43 << 152 */
-        { { 0xeccffc7d8a2c1f08l,0x308916d37e384bd4l,0x6b8c2ff55e366384l,
-            0xf4b2850d03e4747cl },
-          { 0xe839c569e96c1488l,0xa46ff7f956c9cb10l,0xd968c74c362fd172l,
-            0x2aa7fe4cad6bb601l },
-          0 },
-        /* 44 << 152 */
-        { { 0x04d15276a5177900l,0x4e1dbb47f6858752l,0x5b475622c615796cl,
-            0xa6fa0387691867bfl },
-          { 0xed7f5d562844c6d0l,0xc633cf9b03a2477dl,0xf6be5c402d3721d6l,
-            0xaf312eb7e9fd68e6l },
-          0 },
-        /* 45 << 152 */
-        { { 0xf3b8164eec04c847l,0xa305ca93fe65816cl,0xa65f9963c7e2ce52l,
-            0xc448005198882cfcl },
-          { 0x46a998df05c165bbl,0xc38f4edf9dfe1e98l,0xb96ec43f8739f77al,
-            0x10a23af9313b40bfl },
-          0 },
-        /* 46 << 152 */
-        { { 0xe476c3e3ee668e0cl,0xcec6a984478197c2l,0xc9fa1d68897147c1l,
-            0x4e6aec0ea6465793l },
-          { 0xedca9db76b219c3bl,0xa2cd57942e508d3bl,0x38b384663936e02al,
-            0x0b8d3b4ca54ce90fl },
-          0 },
-        /* 47 << 152 */
-        { { 0x66e06537af08e0fcl,0x70fe0f2a907f1a93l,0x8c25245285ec1647l,
-            0x0b8b2964d5560eddl },
-          { 0xda45a326f3ef8e14l,0xf3adf9a6abc3494bl,0xbbdd93c11eda0d92l,
-            0x1b5e12c609912773l },
-          0 },
-        /* 48 << 152 */
-        { { 0x242792d2e7417ce1l,0xff42bc71970ee7f5l,0x1ff4dc6d5c67a41el,
-            0x77709b7b20882a58l },
-          { 0x3554731dbe217f2cl,0x2af2a8cd5bb72177l,0x58eee769591dd059l,
-            0xbb2930c94bba6477l },
-          0 },
-        /* 49 << 152 */
-        { { 0x5d9d507551d01848l,0x53dadb405b600d1el,0x7ba5b4dc5cb0a9a3l,
-            0xdb85b04c6795e547l },
-          { 0x480e7443f0354843l,0xc7efe6e813012322l,0x479b674a2aeee1e6l,
-            0xf5481f19704f4ea3l },
-          0 },
-        /* 51 << 152 */
-        { { 0x76a38d6978c7816el,0xe020c87df84ec554l,0x99af2f78f9818010l,
-            0x31cf103d988136eal },
-          { 0x6b095a114816a5aal,0x5a4cd2a4eff0a4afl,0x543041a5892e5e04l,
-            0x460f94c30aab9ee1l },
-          0 },
-        /* 52 << 152 */
-        { { 0x863ee0477d930cfcl,0x4c262ad1396fd1f4l,0xf4765bc8039af7e1l,
-            0x2519834b5ba104f6l },
-          { 0x7cd61b4cd105f961l,0xa5415da5d63bca54l,0x778280a088a1f17cl,
-            0xc49689492329512cl },
-          0 },
-        /* 53 << 152 */
-        { { 0x282d92b48cd3948al,0x95d219dfe168205bl,0xf6111a6f87bf3abcl,
-            0x910f8ce655fee9f2l },
-          { 0xb6c806f74f71ac89l,0xd0cc300fb7235f73l,0xfe37ccb47d0d45bbl,
-            0x5b2445f6952f0eaal },
-          0 },
-        /* 55 << 152 */
-        { { 0x03870be447141962l,0x8b79033f4a2b3f7fl,0xb6983b5ed2e5e274l,
-            0x2a2f8018501ed99cl },
-          { 0x07a92eb9feb49656l,0x063f0a9e482e2972l,0x413be27a57435832l,
-            0x56363c5f6f9d3de1l },
-          0 },
-        /* 57 << 152 */
-        { { 0xd247153163b50214l,0x32b435eeb2b897del,0xc49f0b01b05df4del,
-            0x97b6aa40b7df9b91l },
-          { 0x58ff34ec8ec39d78l,0xab0889005e0114a3l,0x6872b4de4822b7b8l,
-            0x7614c0d0ab239073l },
-          0 },
-        /* 59 << 152 */
-        { { 0x81891d378aa5d80al,0xf48ca24292e45f2cl,0xba711b6c0d04904cl,
-            0x5992cda349f16ed6l },
-          { 0x18b9a739790593eel,0x8b98e84dc4ba16d1l,0xac55701cb7b81615l,
-            0xadb4533b15822291l },
-          0 },
-        /* 60 << 152 */
-        { { 0x6210db7181236c97l,0x74f7685b3ee0781fl,0x4df7da7ba3e41372l,
-            0x2aae38b1b1a1553el },
-          { 0x1688e222f6dd9d1bl,0x576954485b8b6487l,0x478d21274b2edeaal,
-            0xb2818fa51e85956al },
-          0 },
-        /* 61 << 152 */
-        { { 0xc0677533f255ba8el,0x2bdae2a1efa2aabel,0xf7aebbd4b086c8a6l,
-            0x148455d992cb1147l },
-          { 0xa084e8d715402565l,0x33f111a8fa41bf23l,0x4bc990d627ac189bl,
-            0x48dbe6569d505f76l },
-          0 },
-        /* 63 << 152 */
-        { { 0x59df7fab596766f3l,0x4cadcbfe604f26e4l,0x0cf199338a6af592l,
-            0x3af1ace287b826c1l },
-          { 0xf09a5b38ee60684el,0xa04cbeda4ed7c711l,0xdb28c42eb1731040l,
-            0x75fcc0ec2e6e6523l },
-          0 },
-        /* 64 << 152 */
-        { { 0x1e6adddaf176f2c0l,0x01ca4604e2572658l,0x0a404ded85342ffbl,
-            0x8cf60f96441838d6l },
-          { 0x9bbc691cc9071c4al,0xfd58874434442803l,0x97101c85809c0d81l,
-            0xa7fb754c8c456f7fl },
-          0 },
-        /* 65 << 152 */
-        { { 0x4374020072196f30l,0x59ed0dc0dcd6c935l,0x17d4ed8e5034161bl,
-            0x8abe3e13009e7170l },
-          { 0xe51c41c96c791456l,0xc671807704d72bb6l,0xd4309cf56bba424al,
-            0x6122b951d0ca4ceal },
-          0 },
-        /* 71 << 152 */
-        { { 0xdfdb2e9c4278982bl,0xf3a282b32d6a2a61l,0x5611650cd2f2b03cl,
-            0xa62c177f43f7f83al },
-          { 0x372310ab4c593d32l,0x2bb6903a2b570f9cl,0x2930da3df43af904l,
-            0x2bbd04aa2c8a5a7dl },
-          0 },
-        /* 77 << 152 */
-        { { 0x10c324c007e536del,0xc456836d377be1b4l,0x9a627d75d785af3fl,
-            0xde74559118b58b31l },
-          { 0xeac83ea60c47239al,0x35da24abbc02f670l,0x2d4abde0c3af6e63l,
-            0xac53acba5a7ebf1bl },
-          0 },
-        /* 83 << 152 */
-        { { 0x2b03ec2efd9a9f3el,0xc967cd2b9d898a09l,0xb24bcba8039dc4f6l,
-            0x0ea1d297061ada1el },
-          { 0x3a7a25fbc134b8bcl,0x846282d6f61cd312l,0xfa1de0d2e0d778d9l,
-            0xf75fad4ef09be264l },
-          0 },
-        /* 89 << 152 */
-        { { 0x7d35695bcf74afb3l,0x34d43d9f15bb36fbl,0x15f0b43960b45fbel,
-            0xb15db8d84f38ec06l },
-          { 0x93ce7d50f7da1406l,0x2db97edd9f076aaal,0x27ebb9aa354429dcl,
-            0xf97eb5c446ace469l },
-          0 },
-        /* 95 << 152 */
-        { { 0x758fa2312dcf498fl,0xaa8c14d15cf3853al,0x416f5dab097d786al,
-            0xceec00ef38f242a0l },
-          { 0x2f8b10b9d8b75ef2l,0xee64912b2281be6al,0xa883481aa382a51el,
-            0x9442300f61b16b8al },
-          0 },
-        /* 101 << 152 */
-        { { 0x80e7fbc4f4b171e1l,0xdd2246f5661564a4l,0xcf08d73cd00d4e54l,
-            0xf725f5389fca9a30l },
-          { 0xd9607358af20debel,0xa97c81e16f7d1cf2l,0x72794ae70dedfb2al,
-            0xc328cb93159ff29dl },
-          0 },
-        /* 107 << 152 */
-        { { 0xaf9491d6252f6d59l,0x6744d7518feda60dl,0xa485f8aa34c5c048l,
-            0x2ed794b4b50ea53bl },
-          { 0x0da82650db26c289l,0xed3ab4c50904af55l,0x425eda1176544463l,
-            0x917be5f48939b29bl },
-          0 },
-        /* 113 << 152 */
-        { { 0xa2e72d0f8e208e5dl,0x5a5e4344234a5fedl,0x6dcc56535005bee8l,
-            0x09d0c254854e2e04l },
-          { 0xade4bcdba82f0789l,0x5a3e3cd4ec460a91l,0x6b1a867be76695b2l,
-            0xd1eb9df0a28b9331l },
-          0 },
-        /* 116 << 152 */
-        { { 0x3f5cf5f678e62ddcl,0x2267c45407fd752bl,0x5e361b6b5e437bbel,
-            0x95c595018354e075l },
-          { 0xec725f85f2b254d9l,0x844b617d2cb52b4el,0xed8554f5cf425fb5l,
-            0xab67703e2af9f312l },
-          0 },
-        /* 119 << 152 */
-        { { 0x8dcc920005fb96bbl,0x29d2442470f84705l,0x540bb6e63f09628fl,
-            0x07f8b4de2a9c2359l },
-          { 0xb8e002d1957e41dcl,0x9a0fe82b9e683a3fl,0x996b1a5250e633fdl,
-            0x748a11e500c669cal },
-          0 },
-        /* 125 << 152 */
-        { { 0x0593a788581dfd6el,0x99f1164f64e1b329l,0x1142c44b1defddbbl,
-            0xbc95c9c7660b9036l },
-          { 0xf24b5a47079179ccl,0x6175b52c21f7033bl,0x8b5d84183bc2eec0l,
-            0xc1332c8272d12670l },
-          0 },
-    },
-    {
-        /* 0 << 160 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 160 */
-        { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l,
-            0x810ee252af7c9860l },
-          { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l,
-            0xd485717a92731745l },
-          0 },
-        /* 3 << 160 */
-        { { 0x6c8d0aa9b898fd52l,0x2fb38a57be9af1a7l,0xe1f2b9a93b4f03f8l,
-            0x2b1aad44c3f0cc6fl },
-          { 0x58b5332e7cf2c084l,0x1c57d96f0367d26dl,0x2297eabdfa6e4a8dl,
-            0x65a947ee4a0e2b6al },
-          0 },
-        /* 4 << 160 */
-        { { 0xaaafafb0285b9491l,0x01a0be881e4c705el,0xff1d4f5d2ad9caabl,
-            0x6e349a4ac37a233fl },
-          { 0xcf1c12464a1c6a16l,0xd99e6b6629383260l,0xea3d43665f6d5471l,
-            0x36974d04ff8cc89bl },
-          0 },
-        /* 5 << 160 */
-        { { 0xf535b616fdd5b854l,0x592549c85728719fl,0xe231468606921cadl,
-            0x98c8ce34311b1ef8l },
-          { 0x28b937e7e9090b36l,0x67fc3ab90bf7bbb7l,0x12337097a9d87974l,
-            0x3e5adca1f970e3fel },
-          0 },
-        /* 7 << 160 */
-        { { 0xcdcc68a7b3f85ff0l,0xacd21cdd1a888044l,0xb6719b2e05dbe894l,
-            0xfae1d3d88b8260d4l },
-          { 0xedfedece8a1c5d92l,0xbca01a94dc52077el,0xc085549c16dd13edl,
-            0xdc5c3bae495ebaadl },
-          0 },
-        /* 9 << 160 */
-        { { 0xcc17063fbe7b643al,0x7872e1c846085760l,0x86b0fffbb4214c9el,
-            0xb18bbc0e72bf3638l },
-          { 0x8b17de0c722591c9l,0x1edeab1948c29e0cl,0x9fbfd98ef4304f20l,
-            0x2d1dbb6b9c77ffb6l },
-          0 },
-        /* 10 << 160 */
-        { { 0xf53f2c658ead09f7l,0x1335e1d59780d14dl,0x69cc20e0cd1b66bcl,
-            0x9b670a37bbe0bfc8l },
-          { 0xce53dc8128efbeedl,0x0c74e77c8326a6e5l,0x3604e0d2b88e9a63l,
-            0xbab38fca13dc2248l },
-          0 },
-        /* 11 << 160 */
-        { { 0x255616d3c7141771l,0xa86691ab2f226b66l,0xda19fea4b3ca63a9l,
-            0xfc05dc42ae672f2bl },
-          { 0xa9c6e786718ba28fl,0x07b7995b9c66b984l,0x0f434f551b3702f2l,
-            0xd6f6212fda84eeffl },
-          0 },
-        /* 13 << 160 */
-        { { 0x4b0e7987b5b41d78l,0xea7df9074bf0c4f8l,0xb4d03560fab80ecdl,
-            0x6cf306f6fb1db7e5l },
-          { 0x0d59fb5689fd4773l,0xab254f4000f9be33l,0x18a09a9277352da4l,
-            0xf81862f5641ea3efl },
-          0 },
-        /* 15 << 160 */
-        { { 0xb59b01579f759d01l,0xa2923d2f7eae4fdel,0x18327757690ba8c0l,
-            0x4bf7e38b44f51443l },
-          { 0xb6812563b413fc26l,0xedb7d36379e53b36l,0x4fa585c4c389f66dl,
-            0x8e1adc3154bd3416l },
-          0 },
-        /* 16 << 160 */
-        { { 0xd3b3a13f1402b9d0l,0x573441c32c7bc863l,0x4b301ec4578c3e6el,
-            0xc26fc9c40adaf57el },
-          { 0x96e71bfd7493cea3l,0xd05d4b3f1af81456l,0xdaca2a8a6a8c608fl,
-            0x53ef07f60725b276l },
-          0 },
-        /* 17 << 160 */
-        { { 0x971e9eedd5098497l,0x97692be63077d8a7l,0xb57e02ad79625a8al,
-            0x5e3d20f6a688ecd5l },
-          { 0xa4431a28188f964dl,0xd4eb23bd5a11c1dbl,0xfcda853eadc7446fl,
-            0x9e2e98b593c94046l },
-          0 },
-        /* 19 << 160 */
-        { { 0x4a649b66eddaa4f1l,0x35a04f185e690c50l,0x1639bdcff908bc53l,
-            0xce6d525c121726e8l },
-          { 0x70f34948902b402cl,0x3a40c6950e290579l,0x7b0ed90f469a0085l,
-            0xecb979c60189c501l },
-          0 },
-        /* 21 << 160 */
-        { { 0x847e2bde5cee8d07l,0x1bed198cd3340037l,0x439ffb3ce41586e3l,
-            0x594980f1856f15b0l },
-          { 0x22c3b86c6e9307c6l,0xf8b3ee08876382dbl,0x850c628e628f3f30l,
-            0x22ec0acb51ee3659l },
-          0 },
-        /* 23 << 160 */
-        { { 0xa4052591efcef5a0l,0x82692a47106d55afl,0xdac3ea88e6ead453l,
-            0xaa1368fcf3dfd875l },
-          { 0x87bc688aa0c539eal,0x905e206040b1de3el,0x072240b8f1d52452l,
-            0x3ebf0644d57b6580l },
-          0 },
-        /* 25 << 160 */
-        { { 0x12109bcc07a0b2f8l,0x336f87d2ca23f14cl,0xb39ae282452a2ea2l,
-            0x8e085f5bab59a500l },
-          { 0xf7daeb69b63f015cl,0x44c555bcacb47b38l,0x96190454b623910al,
-            0x4b666e2255b41b70l },
-          0 },
-        /* 27 << 160 */
-        { { 0xf146914eb53419fdl,0xd2109b07493e88bfl,0x30bf9cbccc54bcd5l,
-            0xcf9ea59750e34a1fl },
-          { 0x70ade8a59588591dl,0xf668be676b41c269l,0x3497c58f78df2e6bl,
-            0x0fad05cc71042b56l },
-          0 },
-        /* 28 << 160 */
-        { { 0x27f536e049ce89e7l,0x18908539cc890cb5l,0x308909abd83c2aa1l,
-            0xecd3142b1ab73bd3l },
-          { 0x6a85bf59b3f5ab84l,0x3c320a68f2bea4c6l,0xad8dc5386da4541fl,
-            0xeaf34eb0b7c41186l },
-          0 },
-        /* 29 << 160 */
-        { { 0x709da836093aa5f6l,0x567a9becb4644edel,0xae02a46044466b0cl,
-            0xc80b237a407f1b3bl },
-          { 0x451df45ab4168a98l,0xdc9b40ef24a3f7c9l,0x23593ef32671341dl,
-            0x40f4533190b90faal },
-          0 },
-        /* 31 << 160 */
-        { { 0x7f97768e922f36e3l,0x936943f8491034a2l,0x72f6c17f21483753l,
-            0x5489fa0cb2918619l },
-          { 0x55b31aa59cc21a46l,0xde4cc71a8e54ab14l,0x942cb8be9eaff8b0l,
-            0xe38f6116d1755231l },
-          0 },
-        /* 33 << 160 */
-        { { 0xf0c0606a395b39abl,0x0efcbc699b5166a5l,0x85995e6895453d85l,
-            0xadc9a2920806ee5cl },
-          { 0xc3662e804928fe09l,0x2a2ddcc6969c87e7l,0xa02d7947111d319dl,
-            0xde23bcf12d20f66dl },
-          0 },
-        /* 34 << 160 */
-        { { 0xc47cb3395f6d4a09l,0x6b4f355cee52b826l,0x3d100f5df51b930al,
-            0xf4512fac9f668f69l },
-          { 0x546781d5206c4c74l,0xd021d4d4cb4d2e48l,0x494a54c2ca085c2dl,
-            0xf1dbaca4520850a8l },
-          0 },
-        /* 35 << 160 */
-        { { 0xb2d15b14a911cc2bl,0xab2dfaf7643e28eal,0xfccc9ed1f52c4c2dl,
-            0xfb4b1d4a09d8faa3l },
-          { 0x6fd72a9b7f5ce767l,0x0233c856a287e2b5l,0xd42135e05775ebb9l,
-            0xb3c9dada7376568bl },
-          0 },
-        /* 36 << 160 */
-        { { 0x63c79326490a1acal,0xcb64dd9c41526b02l,0xbb772591a2979258l,
-            0x3f58297048d97846l },
-          { 0xd66b70d17c213ba7l,0xc28febb5e8a0ced4l,0x6b911831c10338c1l,
-            0x0d54e389bf0126f3l },
-          0 },
-        /* 37 << 160 */
-        { { 0x5952996b5306af1bl,0x99f444f4354b67bel,0x6f670181633a2928l,
-            0x289023f0e9bdc4a6l },
-          { 0xcbed12148f7455a2l,0x501ace2f659a4858l,0x83ee678d5f8e1784l,
-            0x95c984587335c5bdl },
-          0 },
-        /* 39 << 160 */
-        { { 0x2e25a1f3e0233000l,0xed0028cd44fe8ba9l,0x447501a6021d43b3l,
-            0x4ec203906b4dffccl },
-          { 0x50642f9ad0169740l,0x9360003373cc58adl,0x825f1a82fe9cf9acl,
-            0x456194c653242bd6l },
-          0 },
-        /* 40 << 160 */
-        { { 0x40242efeb483689bl,0x2575d3f6513ac262l,0xf30037c80ca6db72l,
-            0xc9fcce8298864be2l },
-          { 0x84a112ff0149362dl,0x95e575821c4ae971l,0x1fa4b1a8945cf86cl,
-            0x4525a7340b024a2fl },
-          0 },
-        /* 41 << 160 */
-        { { 0x83205e8f5db5e2b1l,0x94e7a2621e311c12l,0xe1cac7333e37068fl,
-            0xe3f43f6d39965acfl },
-          { 0xd28db9e854d905bal,0x686f372a101f2162l,0x409cfe5d3d1b46d4l,
-            0x17648f1cbd0bb63al },
-          0 },
-        /* 43 << 160 */
-        { { 0xef83315b821f4ee4l,0xb90766998ba78b4dl,0xee6a15880fce5260l,
-            0x828f4a72d754affbl },
-          { 0x4650ec7daaae54d2l,0x3174301f1057efe9l,0x174e0683eb7704cel,
-            0xb7e6aeb357eb0b14l },
-          0 },
-        /* 44 << 160 */
-        { { 0xcaead1c2c905d85fl,0xe9d7f7900733ae57l,0x24c9a65cf07cdd94l,
-            0x7389359ca4b55931l },
-          { 0xf58709b7367e45f7l,0x1f203067cb7e7adcl,0x82444bffc7b72818l,
-            0x07303b35baac8033l },
-          0 },
-        /* 45 << 160 */
-        { { 0xd59528fb38a0dc96l,0x8179dc9088d0e857l,0x55e9ba039ed4b1afl,
-            0x8a2c0dc787b74cacl },
-          { 0xe8ca91aeef1c0006l,0x67f59ab2de0e15d4l,0xba0cddf86e6634d2l,
-            0x352803657b7ba591l },
-          0 },
-        /* 46 << 160 */
-        { { 0x1e1ee4e4d13b7ea1l,0xe6489b24e0e74180l,0xa5f2c6107e70ef70l,
-            0xa1655412bdd10894l },
-          { 0x555ebefb7af4194el,0x533c1c3c8e89bd9cl,0x735b9b5789895856l,
-            0x15fb3cd2567f5c15l },
-          0 },
-        /* 47 << 160 */
-        { { 0xef07bfedfb0986c7l,0xde138afe47c1659al,0x8b79c159a555e907l,
-            0x21d572f1125518bbl },
-          { 0x2005999ad320410cl,0x4167dc469484414bl,0x0cd965c34c6aaefdl,
-            0x2a1abc9a0e1d5e9dl },
-          0 },
-        /* 48 << 160 */
-        { { 0x057fed45526f09fdl,0xe8a4f10c8128240al,0x9332efc4ff2bfd8dl,
-            0x214e77a0bd35aa31l },
-          { 0x32896d7314faa40el,0x767867ec01e5f186l,0xc9adf8f117a1813el,
-            0xcb6cda7854741795l },
-          0 },
-        /* 49 << 160 */
-        { { 0xadfaf39b888dedf1l,0x4f8b178aab1750b9l,0x26418617ffe6b0eal,
-            0x01d1be82af04a59fl },
-          { 0x41584147e652db64l,0xf7775ac5727f9ea7l,0x58052a20e72ad8bbl,
-            0x5badf0dc6021160el },
-          0 },
-        /* 51 << 160 */
-        { { 0x8490ea99183de59dl,0xc95f72146f5c6f8cl,0x89b55d15df00c334l,
-            0x84386ad8a0ec36f7l },
-          { 0x24dadaefe4dc1ed1l,0xc606ba4c1e717227l,0x7e4756c0bbfa62eal,
-            0x3916cf14afc29cf3l },
-          0 },
-        /* 52 << 160 */
-        { { 0xb7b4d00101dae185l,0x45434e0b9b7a94bcl,0xf54339affbd8cb0bl,
-            0xdcc4569ee98ef49el },
-          { 0x7789318a09a51299l,0x81b4d206b2b025d8l,0xf64aa418fae85792l,
-            0x3e50258facd7baf7l },
-          0 },
-        /* 53 << 160 */
-        { { 0x4152c508492d91f3l,0x59d6cf9c678f9db4l,0xb0a8c966404608d1l,
-            0xdced55d0e3fed558l },
-          { 0x0914a3cb33a76188l,0x79df212423d35d46l,0x2322507fca13b364l,
-            0x0aed41d60078ab93l },
-          0 },
-        /* 55 << 160 */
-        { { 0x7acdaa7f6b2ebfc2l,0xb5ab1a9a80d9f67fl,0x53ba8173ff8aa8b0l,
-            0x9cd85cf874ca56a6l },
-          { 0xabac57f49c4fad81l,0x2325bb8521078995l,0xbac5e3a1b928a054l,
-            0x7219047a2394cc2al },
-          0 },
-        /* 57 << 160 */
-        { { 0xa33410d2aa75fd37l,0x821093affc0f1192l,0xe45e85ed155e39a9l,
-            0xd0e87cd12de67188l },
-          { 0xdeca97d965d43d87l,0x8c73826f9d2c99ecl,0x1bfe111e33237ddbl,
-            0xda32e865587bfb28l },
-          0 },
-        /* 59 << 160 */
-        { { 0xde456d92c89e9e4el,0xe45688a98e47f3cdl,0x3deacfca3bacbde0l,
-            0xdf9b32efc9683a70l },
-          { 0x749bc007e1691106l,0x788a05342a5154d7l,0x1a06baecf7c7b70dl,
-            0xb5b608eeae6ffc4cl },
-          0 },
-        /* 60 << 160 */
-        { { 0x4cd296df5579bea4l,0x10e35ac85ceedaf1l,0x04c4c5fde3bcc5b1l,
-            0x95f9ee8a89412cf9l },
-          { 0x2c9459ee82b6eb0fl,0x2e84576595c2aaddl,0x774a84aed327fcfel,
-            0xd8c937220368d476l },
-          0 },
-        /* 61 << 160 */
-        { { 0x39ebf947ccd25abbl,0x74e7a868cb49ebael,0x576ea108332e6147l,
-            0xcf3ba166150c1e5dl },
-          { 0xb5411fc3515c0e93l,0x51b15761f15c8a34l,0x362a4a3a0d213f38l,
-            0xf6f63c2e24e93aeal },
-          0 },
-        /* 63 << 160 */
-        { { 0x0cb3a2dcb78528d5l,0xa1888c18d585bb41l,0x210cca40de402a6el,
-            0x10c6339d9ed7c381l },
-          { 0xcd3558d561fe2a0cl,0xc97db05dad5140b1l,0x3366b028b21f8d11l,
-            0x878b09033e38be13l },
-          0 },
-        /* 64 << 160 */
-        { { 0x211cde10296c36efl,0x7ee8967282c4da77l,0xb617d270a57836dal,
-            0xf0cd9c319cb7560bl },
-          { 0x01fdcbf7e455fe90l,0x3fb53cbb7e7334f3l,0x781e2ea44e7de4ecl,
-            0x8adab3ad0b384fd0l },
-          0 },
-        /* 65 << 160 */
-        { { 0x081e505aa353ba05l,0x244ab34a288b86b1l,0x1155f06214e3a829l,
-            0x383300daf2118a6bl },
-          { 0xe8fc17cef27032b9l,0xed7f05c9c7bd2389l,0x78f70d14202f8a88l,
-            0x8a8310c0647b3f20l },
-          0 },
-        /* 71 << 160 */
-        { { 0xc80786e1a3633369l,0x496d55de9073f5b9l,0x10deeb6a89ae93cel,
-            0x6a2dd5c8b12e00c6l },
-          { 0xc25cd2f90c68e26dl,0x29d7ad8b53f0bb64l,0x2dd0d027d7fc9b00l,
-            0xad21e1f7ca9c4d5dl },
-          0 },
-        /* 77 << 160 */
-        { { 0xd45cb932d83465f3l,0x95830c0faf22fdbdl,0x41d830e007cd2a0al,
-            0x4a08500e3616e716l },
-          { 0x5931fc9f277755a5l,0x7d11680731006764l,0xa409a0ad1b3999aal,
-            0xec70368c9939d566l },
-          0 },
-        /* 83 << 160 */
-        { { 0x3905cb59f2030370l,0x7e9bdee56dcc8fd7l,0xb1b7b04e9806e06fl,
-            0xfbdadce22c73eb57l },
-          { 0xfb1ab2e98d5b2eb3l,0x58fbf2df7699338bl,0x81b1c54a63b5a032l,
-            0xefd1a1896a5d7ff4l },
-          0 },
-        /* 89 << 160 */
-        { { 0x0265189da1f769eal,0x22fa0bbbfdb5a502l,0xf69f0d1b21027534l,
-            0x64302b81f6066b99l },
-          { 0xdef85fc98a717e80l,0xe066166386879a3bl,0xe5489b347f95b22cl,
-            0x106dca9aa054a563l },
-          0 },
-        /* 95 << 160 */
-        { { 0xd624b4f4b4be9a77l,0x21a11ed77d50acb1l,0x707181f43d406e11l,
-            0x3f324d203ef158bcl },
-          { 0xb29a2a34aa8cc8del,0x482f4a15315db969l,0x42ce4fc7d9af272el,
-            0x784665b1f8f4cdc4l },
-          0 },
-        /* 101 << 160 */
-        { { 0x66ff7f73ab43a863l,0xa90be2cba77fd07el,0x84843997f76e5288l,
-            0x288c197f3cee129bl },
-          { 0x39acc080c0a060a6l,0x4c8e574bd24e27cal,0x1dd6170ffcd3d5e9l,
-            0x9736bb51f75e5150l },
-          0 },
-        /* 107 << 160 */
-        { { 0x2133810e6ba75716l,0x4debf728712886a8l,0x351e46a1f527d1f3l,
-            0x29709ae8e9591564l },
-          { 0x696163d3a3dc1780l,0xd5b7825ae02aadf3l,0x23579d7cd565ae68l,
-            0x105380124fa42cecl },
-          0 },
-        /* 113 << 160 */
-        { { 0x04eb554d13ffa704l,0x7441a62f2ed33d20l,0xaa926fa0b5b81324l,
-            0xb981bcb829836f61l },
-          { 0x313a78d4cc9a7a15l,0xff1242d11b3921d2l,0xc0053fd36a209d4dl,
-            0x95ac85caf7e92ca9l },
-          0 },
-        /* 116 << 160 */
-        { { 0x6d2a483d6f73c51el,0xa4cb2412ea0dc2ddl,0x50663c411eb917ffl,
-            0x3d3a74cfeade299el },
-          { 0x29b3990f4a7a9202l,0xa9bccf59a7b15c3dl,0x66a3ccdca5df9208l,
-            0x48027c1443f2f929l },
-          0 },
-        /* 119 << 160 */
-        { { 0xdf8a6f9673c3f6fbl,0xe4b1f0d98cc03220l,0x5ddacd618350480cl,
-            0x485c4fababdfb016l },
-          { 0xdc840628b4d424b7l,0x07d3a99c215b2359l,0xad3dc5af56dff52el,
-            0x5a3a6754973b6825l },
-          0 },
-        /* 125 << 160 */
-        { { 0xcfe231b83539a06dl,0xb36d1f72f46770ddl,0x126049747bb900d6l,
-            0x8d0990973fc31661l },
-          { 0x03b2749c920bc39el,0xf933d510b0486e23l,0x09cc958f0e9b0bb5l,
-            0x0b254dd1aa1e23abl },
-          0 },
-    },
-    {
-        /* 0 << 168 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 168 */
-        { { 0x263a2cfb9db3b381l,0x9c3a2deed4df0a4bl,0x728d06e97d04e61fl,
-            0x8b1adfbc42449325l },
-          { 0x6ec1d9397e053a1bl,0xee2be5c766daf707l,0x80ba1e14810ac7abl,
-            0xdd2ae778f530f174l },
-          0 },
-        /* 3 << 168 */
-        { { 0xadbaeb79b6828f36l,0x9d7a025801bd5b9el,0xeda01e0d1e844b0cl,
-            0x4b625175887edfc9l },
-          { 0x14109fdd9669b621l,0x88a2ca56f6f87b98l,0xfe2eb788170df6bcl,
-            0x0cea06f4ffa473f9l },
-          0 },
-        /* 4 << 168 */
-        { { 0x43ed81b5c4e83d33l,0xd9f358795efd488bl,0x164a620f9deb4d0fl,
-            0xc6927bdbac6a7394l },
-          { 0x45c28df79f9e0f03l,0x2868661efcd7e1a9l,0x7cf4e8d0ffa348f1l,
-            0x6bd4c284398538e0l },
-          0 },
-        /* 5 << 168 */
-        { { 0x2618a091289a8619l,0xef796e606671b173l,0x664e46e59090c632l,
-            0xa38062d41e66f8fbl },
-          { 0x6c744a200573274el,0xd07b67e4a9271394l,0x391223b26bdc0e20l,
-            0xbe2d93f1eb0a05a7l },
-          0 },
-        /* 7 << 168 */
-        { { 0x7efa14b84444896bl,0x64974d2ff94027fbl,0xefdcd0e8de84487dl,
-            0x8c45b2602b48989bl },
-          { 0xa8fcbbc2d8463487l,0xd1b2b3f73fbc476cl,0x21d005b7c8f443c0l,
-            0x518f2e6740c0139cl },
-          0 },
-        /* 9 << 168 */
-        { { 0xae51dca2a91f6791l,0x2abe41909baa9efcl,0xd9d2e2f4559c7ac1l,
-            0xe82f4b51fc9f773al },
-          { 0xa77130274073e81cl,0xc0276facfbb596fcl,0x1d819fc9a684f70cl,
-            0x29b47fddc9f7b1e0l },
-          0 },
-        /* 10 << 168 */
-        { { 0x358de103459b1940l,0xec881c595b013e93l,0x51574c9349532ad3l,
-            0x2db1d445b37b46del },
-          { 0xc6445b87df239fd8l,0xc718af75151d24eel,0xaea1c4a4f43c6259l,
-            0x40c0e5d770be02f7l },
-          0 },
-        /* 11 << 168 */
-        { { 0x6a4590f4721b33f2l,0x2124f1fbfedf04eal,0xf8e53cde9745efe7l,
-            0xe7e1043265f046d9l },
-          { 0xc3fca28ee4d0c7e6l,0x847e339a87253b1bl,0x9b5953483743e643l,
-            0xcb6a0a0b4fd12fc5l },
-          0 },
-        /* 13 << 168 */
-        { { 0xec1214eda714181dl,0x609ac13b6067b341l,0xff4b4c97a545df1fl,
-            0xa124050134d2076bl },
-          { 0x6efa0c231409ca97l,0x254cc1a820638c43l,0xd4e363afdcfb46cdl,
-            0x62c2adc303942a27l },
-          0 },
-        /* 15 << 168 */
-        { { 0x27b6a8ab3fd40e09l,0xe455842e77313ea9l,0x8b51d1e21f55988bl,
-            0x5716dd73062bbbfcl },
-          { 0x633c11e54e8bf3del,0x9a0e77b61b85be3bl,0x565107290911cca6l,
-            0x27e76495efa6590fl },
-          0 },
-        /* 16 << 168 */
-        { { 0xe4ac8b33070d3aabl,0x2643672b9a2cd5e5l,0x52eff79b1cfc9173l,
-            0x665ca49b90a7c13fl },
-          { 0x5a8dda59b3efb998l,0x8a5b922d052f1341l,0xae9ebbab3cf9a530l,
-            0x35986e7bf56da4d7l },
-          0 },
-        /* 17 << 168 */
-        { { 0x3a636b5cff3513ccl,0xbb0cf8ba3198f7ddl,0xb8d4052241f16f86l,
-            0x760575d8de13a7bfl },
-          { 0x36f74e169f7aa181l,0x163a3ecff509ed1cl,0x6aead61f3c40a491l,
-            0x158c95fcdfe8fcaal },
-          0 },
-        /* 19 << 168 */
-        { { 0x6b47accdd9eee96cl,0x0ca277fbe58cec37l,0x113fe413e702c42al,
-            0xdd1764eec47cbe51l },
-          { 0x041e7cde7b3ed739l,0x50cb74595ce9e1c0l,0x355685132925b212l,
-            0x7cff95c4001b081cl },
-          0 },
-        /* 21 << 168 */
-        { { 0x726f0973da50c991l,0x48afcd5b822d6ee2l,0xe5fc718b20fd7771l,
-            0xb9e8e77dfd0807a1l },
-          { 0x7f5e0f4499a7703dl,0x6972930e618e36f3l,0x2b7c77b823807bbel,
-            0xe5b82405cb27ff50l },
-          0 },
-        /* 23 << 168 */
-        { { 0x98cb1ae9255c0980l,0x4bd863812b4a739fl,0x5a5c31e11e4a45a1l,
-            0x1e5d55fe9cb0db2fl },
-          { 0x74661b068ff5cc29l,0x026b389f0eb8a4f4l,0x536b21a458848c24l,
-            0x2e5bf8ec81dc72b0l },
-          0 },
-        /* 25 << 168 */
-        { { 0x9f0af483d309cbe6l,0x5b020d8ae0bced4fl,0x606e986db38023e3l,
-            0xad8f2c9d1abc6933l },
-          { 0x19292e1de7400e93l,0xfe3e18a952be5e4dl,0xe8e9771d2e0680bfl,
-            0x8c5bec98c54db063l },
-          0 },
-        /* 27 << 168 */
-        { { 0x4c23f62a2c160dcdl,0x34e6c5e38f90eaefl,0x35865519a9a65d5al,
-            0x07c48aae8fd38a3dl },
-          { 0xb7e7aeda50068527l,0x2c09ef231c90936al,0x31ecfeb6e879324cl,
-            0xa0871f6bfb0ec938l },
-          0 },
-        /* 28 << 168 */
-        { { 0xb1f0fb68d84d835dl,0xc90caf39861dc1e6l,0x12e5b0467594f8d7l,
-            0x26897ae265012b92l },
-          { 0xbcf68a08a4d6755dl,0x403ee41c0991fbdal,0x733e343e3bbf17e8l,
-            0xd2c7980d679b3d65l },
-          0 },
-        /* 29 << 168 */
-        { { 0x33056232d2e11305l,0x966be492f3c07a6fl,0x6a8878ffbb15509dl,
-            0xff2211010a9b59a4l },
-          { 0x6c9f564aabe30129l,0xc6f2c940336e64cfl,0x0fe752628b0c8022l,
-            0xbe0267e96ae8db87l },
-          0 },
-        /* 31 << 168 */
-        { { 0x9d031369a5e829e5l,0xcbb4c6fc1607aa41l,0x75ac59a6241d84c1l,
-            0xc043f2bf8829e0eel },
-          { 0x82a38f758ea5e185l,0x8bda40b9d87cbd9fl,0x9e65e75e2d8fc601l,
-            0x3d515f74a35690b3l },
-          0 },
-        /* 33 << 168 */
-        { { 0xf6b5b2d0bc8fa5bcl,0x8a5ead67500c277bl,0x214625e6dfa08a5dl,
-            0x51fdfedc959cf047l },
-          { 0x6bc9430b289fca32l,0xe36ff0cf9d9bdc3fl,0x2fe187cb58ea0edel,
-            0xed66af205a900b3fl },
-          0 },
-        /* 34 << 168 */
-        { { 0x00e0968b5fa9f4d6l,0x2d4066ce37a362e7l,0xa99a9748bd07e772l,
-            0x710989c006a4f1d0l },
-          { 0xd5dedf35ce40cbd8l,0xab55c5f01743293dl,0x766f11448aa24e2cl,
-            0x94d874f8605fbcb4l },
-          0 },
-        /* 35 << 168 */
-        { { 0xa365f0e8a518001bl,0xee605eb69d04ef0fl,0x5a3915cdba8d4d25l,
-            0x44c0e1b8b5113472l },
-          { 0xcbb024e88b6740dcl,0x89087a53ee1d4f0cl,0xa88fa05c1fc4e372l,
-            0x8bf395cbaf8b3af2l },
-          0 },
-        /* 36 << 168 */
-        { { 0x1e71c9a1deb8568bl,0xa35daea080fb3d32l,0xe8b6f2662cf8fb81l,
-            0x6d51afe89490696al },
-          { 0x81beac6e51803a19l,0xe3d24b7f86219080l,0x727cfd9ddf6f463cl,
-            0x8c6865ca72284ee8l },
-          0 },
-        /* 37 << 168 */
-        { { 0x32c88b7db743f4efl,0x3793909be7d11dcel,0xd398f9222ff2ebe8l,
-            0x2c70ca44e5e49796l },
-          { 0xdf4d9929cb1131b1l,0x7826f29825888e79l,0x4d3a112cf1d8740al,
-            0x00384cb6270afa8bl },
-          0 },
-        /* 39 << 168 */
-        { { 0xbe7e990ff0d796a0l,0x5fc62478df0e8b02l,0x8aae8bf4030c00adl,
-            0x3d2db93b9004ba0fl },
-          { 0xe48c8a79d85d5ddcl,0xe907caa76bb07f34l,0x58db343aa39eaed5l,
-            0x0ea6e007adaf5724l },
-          0 },
-        /* 40 << 168 */
-        { { 0xe00df169d23233f3l,0x3e32279677cb637fl,0x1f897c0e1da0cf6cl,
-            0xa651f5d831d6bbddl },
-          { 0xdd61af191a230c76l,0xbd527272cdaa5e4al,0xca753636d0abcd7el,
-            0x78bdd37c370bd8dcl },
-          0 },
-        /* 41 << 168 */
-        { { 0xc23916c217cd93fel,0x65b97a4ddadce6e2l,0xe04ed4eb174e42f8l,
-            0x1491ccaabb21480al },
-          { 0x145a828023196332l,0x3c3862d7587b479al,0x9f4a88a301dcd0edl,
-            0x4da2b7ef3ea12f1fl },
-          0 },
-        /* 43 << 168 */
-        { { 0x71965cbfc3dd9b4dl,0xce23edbffc068a87l,0xb78d4725745b029bl,
-            0x74610713cefdd9bdl },
-          { 0x7116f75f1266bf52l,0x0204672218e49bb6l,0xdf43df9f3d6f19e3l,
-            0xef1bc7d0e685cb2fl },
-          0 },
-        /* 44 << 168 */
-        { { 0xcddb27c17078c432l,0xe1961b9cb77fedb7l,0x1edc2f5cc2290570l,
-            0x2c3fefca19cbd886l },
-          { 0xcf880a36c2af389al,0x96c610fdbda71ceal,0xf03977a932aa8463l,
-            0x8eb7763f8586d90al },
-          0 },
-        /* 45 << 168 */
-        { { 0x3f3424542a296e77l,0xc871868342837a35l,0x7dc710906a09c731l,
-            0x54778ffb51b816dbl },
-          { 0x6b33bfecaf06defdl,0xfe3c105f8592b70bl,0xf937fda461da6114l,
-            0x3c13e6514c266ad7l },
-          0 },
-        /* 46 << 168 */
-        { { 0xe363a829855938e8l,0x2eeb5d9e9de54b72l,0xbeb93b0e20ccfab9l,
-            0x3dffbb5f25e61a25l },
-          { 0x7f655e431acc093dl,0x0cb6cc3d3964ce61l,0x6ab283a1e5e9b460l,
-            0x55d787c5a1c7e72dl },
-          0 },
-        /* 47 << 168 */
-        { { 0x4d2efd47deadbf02l,0x11e80219ac459068l,0x810c762671f311f0l,
-            0xfa17ef8d4ab6ef53l },
-          { 0xaf47fd2593e43bffl,0x5cb5ff3f0be40632l,0x546871068ee61da3l,
-            0x7764196eb08afd0fl },
-          0 },
-        /* 48 << 168 */
-        { { 0x831ab3edf0290a8fl,0xcae81966cb47c387l,0xaad7dece184efb4fl,
-            0xdcfc53b34749110el },
-          { 0x6698f23c4cb632f9l,0xc42a1ad6b91f8067l,0xb116a81d6284180al,
-            0xebedf5f8e901326fl },
-          0 },
-        /* 49 << 168 */
-        { { 0xf2274c9f97e3e044l,0x4201852011d09fc9l,0x56a65f17d18e6e23l,
-            0x2ea61e2a352b683cl },
-          { 0x27d291bc575eaa94l,0x9e7bc721b8ff522dl,0x5f7268bfa7f04d6fl,
-            0x5868c73faba41748l },
-          0 },
-        /* 51 << 168 */
-        { { 0x1c52e63596e78cc4l,0x5385c8b20c06b4a8l,0xd84ddfdbb0e87d03l,
-            0xc49dfb66934bafadl },
-          { 0x7071e17059f70772l,0x3a073a843a1db56bl,0x034949033b8af190l,
-            0x7d882de3d32920f0l },
-          0 },
-        /* 52 << 168 */
-        { { 0x91633f0ab2cf8940l,0x72b0b1786f948f51l,0x2d28dc30782653c8l,
-            0x88829849db903a05l },
-          { 0xb8095d0c6a19d2bbl,0x4b9e7f0c86f782cbl,0x7af739882d907064l,
-            0xd12be0fe8b32643cl },
-          0 },
-        /* 53 << 168 */
-        { { 0x358ed23d0e165dc3l,0x3d47ce624e2378cel,0x7e2bb0b9feb8a087l,
-            0x3246e8aee29e10b9l },
-          { 0x459f4ec703ce2b4dl,0xe9b4ca1bbbc077cfl,0x2613b4f20e9940c1l,
-            0xfc598bb9047d1eb1l },
-          0 },
-        /* 55 << 168 */
-        { { 0x52fb0c9d7fc63668l,0x6886c9dd0c039cdel,0x602bd59955b22351l,
-            0xb00cab02360c7c13l },
-          { 0x8cb616bc81b69442l,0x41486700b55c3ceel,0x71093281f49ba278l,
-            0xad956d9c64a50710l },
-          0 },
-        /* 57 << 168 */
-        { { 0xbaca6591d4b66947l,0xb452ce9804460a8cl,0x6830d24643768f55l,
-            0xf4197ed87dff12dfl },
-          { 0x6521b472400dd0f7l,0x59f5ca8f4b1e7093l,0x6feff11b080338ael,
-            0x0ada31f6a29ca3c6l },
-          0 },
-        /* 59 << 168 */
-        { { 0x04e5dfe0d809c7bdl,0xd7b2580c8f1050abl,0x6d91ad78d8a4176fl,
-            0x0af556ee4e2e897cl },
-          { 0x162a8b73921de0acl,0x52ac9c227ea78400l,0xee2a4eeaefce2174l,
-            0xbe61844e6d637f79l },
-          0 },
-        /* 60 << 168 */
-        { { 0x0491f1bc789a283bl,0x72d3ac3d880836f4l,0xaa1c5ea388e5402dl,
-            0x1b192421d5cc473dl },
-          { 0x5c0b99989dc84cacl,0xb0a8482d9c6e75b8l,0x639961d03a191ce2l,
-            0xda3bc8656d837930l },
-          0 },
-        /* 61 << 168 */
-        { { 0xca990653056e6f8fl,0x84861c4164d133a7l,0x8b403276746abe40l,
-            0xb7b4d51aebf8e303l },
-          { 0x05b43211220a255dl,0xc997152c02419e6el,0x76ff47b6630c2feal,
-            0x50518677281fdadel },
-          0 },
-        /* 63 << 168 */
-        { { 0x6d2d99b7ea7b979bl,0xcd78cd74e6fb3bcdl,0x11e45a9e86cffbfel,
-            0x78a61cf4637024f6l },
-          { 0xd06bc8723d502295l,0xf1376854458cb288l,0xb9db26a1342f8586l,
-            0xf33effcf4beee09el },
-          0 },
-        /* 64 << 168 */
-        { { 0xd7e0c4cdb30cfb3al,0x6d09b8c16c9db4c8l,0x40ba1a4207c8d9dfl,
-            0x6fd495f71c52c66dl },
-          { 0xfb0e169f275264dal,0x80c2b746e57d8362l,0xedd987f749ad7222l,
-            0xfdc229af4398ec7bl },
-          0 },
-        /* 65 << 168 */
-        { { 0xfe81af4609418a51l,0xdbb60b836f18e3a5l,0x5e7a86ea4566ec9cl,
-            0xb76ff40f25093925l },
-          { 0x5fe6662c429c5554l,0xfc9ec35384e478cfl,0x73dbb5f3e8cfa761l,
-            0x031e506592f82709l },
-          0 },
-        /* 71 << 168 */
-        { { 0x108c736abd49f2e0l,0xe230f2417487dcc8l,0x073fc4f8f74d939cl,
-            0x98532487e9745bbel },
-          { 0x5208eb981714b10bl,0xec35d0510458725dl,0x35dbb60bf203f4b6l,
-            0x064299b27781ab38l },
-          0 },
-        /* 77 << 168 */
-        { { 0x43cc7bbc02d26929l,0xeb00a683162d9607l,0x2af152b8ed9fa224l,
-            0xf24e8bee12257f0cl },
-          { 0xdf065dd5d004b1cbl,0x6aa20bcf9f9908c6l,0x8e5e86b6941c593dl,
-            0x0e0034b398969717l },
-          0 },
-        /* 83 << 168 */
-        { { 0x5be62e155c43b8fcl,0xd9e0adfc3c445636l,0xc5141df0e0d78f48l,
-            0xd134bbed2c277716l },
-          { 0x79033a84598fe069l,0x6c704367b081614cl,0x55c45d66bf5bf772l,
-            0xf08744c57a444730l },
-          0 },
-        /* 89 << 168 */
-        { { 0x866752091422b528l,0xdb297411c3e028eel,0x1f5575b040e1c3ccl,
-            0x85367b84d333b04fl },
-          { 0x57864c86e9804aa9l,0xf13fa8e3439156dfl,0xa3b337e0464e0aecl,
-            0x0018dfd7f2ae382bl },
-          0 },
-        /* 95 << 168 */
-        { { 0xe93cece9cea132fcl,0x985542d8f74e867al,0x2a3d18a5cc8fcf87l,
-            0xa0561055479d0039l },
-          { 0x3513c7eaac4b3f9dl,0xc095967256477606l,0xa63960f330df8ad6l,
-            0x59ca8d53cc9ddcb3l },
-          0 },
-        /* 101 << 168 */
-        { { 0x6d8e942b2f208191l,0xd49a6d9453fe5457l,0x2b55e391003010bal,
-            0x3dd1fd9fdf4605ebl },
-          { 0xdc006a3358682886l,0x60a5e86c1bd9ac88l,0xc4bd320ed0cab8f2l,
-            0x7281e7cb7751855bl },
-          0 },
-        /* 107 << 168 */
-        { { 0x7d564222e1881e7al,0x59061a89db0673c2l,0x1f9d607213f27313l,
-            0x5b3b29368ff3aeb7l },
-          { 0x6cf2304ccf969f43l,0x8eff4a25e7f69ae5l,0xbaeb6411d17da4ffl,
-            0x666af0af9eea17ecl },
-          0 },
-        /* 113 << 168 */
-        { { 0x6c0b811697f4cd0bl,0xcd7825d40e4ea852l,0x80158fb0677fef3dl,
-            0x5bb1a3aaa10ee693l },
-          { 0xc5df66678066fc9bl,0x3200dc11f404d4a6l,0x58868950a8686d8el,
-            0xbdaaffb53770fabal },
-          0 },
-        /* 116 << 168 */
-        { { 0xba6a9f84660326f5l,0x61c1e44161bc3e88l,0xfbf992a0bde85cf8l,
-            0xe704dd1e6f8c8f5fl },
-          { 0x231caa0ab1d7d486l,0xd10616d8891cd571l,0x2ddada75c008833cl,
-            0x44337d6dad514c94l },
-          0 },
-        /* 119 << 168 */
-        { { 0xd48678b8f6933cf0l,0x7b4d623e0b739471l,0x4ad620287b216238l,
-            0xb4d4918959c4fabel },
-          { 0x8c2a1bdc296d42d5l,0x9235d0ec2fd3eb96l,0xfe271972f81c135bl,
-            0x82b5181741471e16l },
-          0 },
-        /* 125 << 168 */
-        { { 0xe9aa8ce4051f8e81l,0x14484af67cd1391fl,0x53a361dcafb1656el,
-            0x6ad8ba02f4d9d0cbl },
-          { 0xfb4385466c50a722l,0x2f1c5bbc7edb37f4l,0x8dc90ccb16e4b795l,
-            0xbcb32e1508127094l },
-          0 },
-    },
-    {
-        /* 0 << 176 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 176 */
-        { { 0xb81d783e979f3925l,0x1efd130aaf4c89a7l,0x525c2144fd1bf7fal,
-            0x4b2969041b265a9el },
-          { 0xed8e9634b9db65b6l,0x35c82e3203599d8al,0xdaa7a54f403563f3l,
-            0x9df088ad022c38abl },
-          0 },
-        /* 3 << 176 */
-        { { 0x9e93ba24f111661el,0xedced484b105eb04l,0x96dc9ba1f424b578l,
-            0xbf8f66b7e83e9069l },
-          { 0x872d4df4d7ed8216l,0xbf07f3778e2cbecfl,0x4281d89998e73754l,
-            0xfec85fbb8aab8708l },
-          0 },
-        /* 4 << 176 */
-        { { 0x13b5bf22765fa7d0l,0x59805bf01d6a5370l,0x67a5e29d4280db98l,
-            0x4f53916f776b1ce3l },
-          { 0x714ff61f33ddf626l,0x4206238ea085d103l,0x1c50d4b7e5809ee3l,
-            0x999f450d85f8eb1dl },
-          0 },
-        /* 5 << 176 */
-        { { 0x82eebe731a3a93bcl,0x42bbf465a21adc1al,0xc10b6fa4ef030efdl,
-            0x247aa4c787b097bbl },
-          { 0x8b8dc632f60c77dal,0x6ffbc26ac223523el,0xa4f6ff11344579cfl,
-            0x5825653c980250f6l },
-          0 },
-        /* 7 << 176 */
-        { { 0xeda6c595d314e7bcl,0x2ee7464b467899edl,0x1cef423c0a1ed5d3l,
-            0x217e76ea69cc7613l },
-          { 0x27ccce1fe7cda917l,0x12d8016b8a893f16l,0xbcd6de849fc74f6bl,
-            0xfa5817e2f3144e61l },
-          0 },
-        /* 9 << 176 */
-        { { 0xc0b48d4e49ccd6d7l,0xff8fb02c88bd5580l,0xc75235e907d473b2l,
-            0x4fab1ac5a2188af3l },
-          { 0x030fa3bc97576ec0l,0xe8c946e80b7e7d2fl,0x40a5c9cc70305600l,
-            0x6d8260a9c8b013b4l },
-          0 },
-        /* 10 << 176 */
-        { { 0xe6c51073615cd9e4l,0x498ec047f1243c06l,0x3e5a8809b17b3d8cl,
-            0x5cd99e610cc565f1l },
-          { 0x81e312df7851dafel,0xf156f5baa79061e2l,0x80d62b71880c590el,
-            0xbec9746f0a39faa1l },
-          0 },
-        /* 11 << 176 */
-        { { 0x2b09d2c3cfdcf7ddl,0x41a9fce3723fcab4l,0x73d905f707f57ca3l,
-            0x080f9fb1ac8e1555l },
-          { 0x7c088e849ba7a531l,0x07d35586ed9a147fl,0x602846abaf48c336l,
-            0x7320fd320ccf0e79l },
-          0 },
-        /* 13 << 176 */
-        { { 0x92eb40907f8f875dl,0x9c9d754e56c26bbfl,0x158cea618110bbe7l,
-            0x62a6b802745f91eal },
-          { 0xa79c41aac6e7394bl,0x445b6a83ad57ef10l,0x0c5277eb6ea6f40cl,
-            0x319fe96b88633365l },
-          0 },
-        /* 15 << 176 */
-        { { 0x77f84203d39b8c34l,0xed8b1be63125eddbl,0x5bbf2441f6e39dc5l,
-            0xb00f6ee66a5d678al },
-          { 0xba456ecf57d0ea99l,0xdcae0f5817e06c43l,0x01643de40f5b4baal,
-            0x2c324341d161b9bel },
-          0 },
-        /* 16 << 176 */
-        { { 0x949c9976e1337c26l,0x6faadebdd73d68e5l,0x9e158614f1b768d9l,
-            0x22dfa5579cc4f069l },
-          { 0xccd6da17be93c6d6l,0x24866c61a504f5b9l,0x2121353c8d694da1l,
-            0x1c6ca5800140b8c6l },
-          0 },
-        /* 17 << 176 */
-        { { 0x4e77c5575b45afb4l,0xe9ded649efb8912dl,0x7ec9bbf542f6e557l,
-            0x2570dfff62671f00l },
-          { 0x2b3bfb7888e084bdl,0xa024b238f37fe5b4l,0x44e7dc0495649aeel,
-            0x498ca2555e7ec1d8l },
-          0 },
-        /* 19 << 176 */
-        { { 0x2e44d22526a1fc90l,0x0d6d10d24d70705dl,0xd94b6b10d70c45f4l,
-            0x0f201022b216c079l },
-          { 0xcec966c5658fde41l,0xa8d2bc7d7e27601dl,0xbfcce3e1ff230be7l,
-            0x3394ff6b0033ffb5l },
-          0 },
-        /* 21 << 176 */
-        { { 0x05d99be8b9c20cdal,0x89f7aad5d5cd0c98l,0x7ef936fe5bb94183l,
-            0x92ca0753b05cd7f2l },
-          { 0x9d65db1174a1e035l,0x02628cc813eaea92l,0xf2d9e24249e4fbf2l,
-            0x94fdfd9be384f8b7l },
-          0 },
-        /* 23 << 176 */
-        { { 0x29882d7c98379d44l,0xd000bdfb509edc8al,0xc6f95979e66fe464l,
-            0x504a6115fa61bde0l },
-          { 0x56b3b871effea31al,0x2d3de26df0c21a54l,0x21dbff31834753bfl,
-            0xe67ecf4969269d86l },
-          0 },
-        /* 25 << 176 */
-        { { 0xed29a56da16d4b34l,0x7fba9d09dca21c4fl,0x66d7ac006d8de486l,
-            0x6006198773a2a5e1l },
-          { 0x8b400f869da28ff0l,0x3133f70843c4599cl,0x9911c9b8ee28cb0dl,
-            0xcd7e28748e0af61dl },
-          0 },
-        /* 27 << 176 */
-        { { 0x6a7bb6a93b5bdb83l,0x08da65c0a4a72318l,0xc58d22aa63eb065fl,
-            0x1717596c1b15d685l },
-          { 0x112df0d0b266d88bl,0xf688ae975941945al,0x487386e37c292cacl,
-            0x42f3b50d57d6985cl },
-          0 },
-        /* 28 << 176 */
-        { { 0x69e3be0427596893l,0xb6bb02a645bf452bl,0x0875c11af4c698c8l,
-            0x6652b5c7bece3794l },
-          { 0x7b3755fd4f5c0499l,0x6ea16558b5532b38l,0xd1c69889a2e96ef7l,
-            0x9c773c3a61ed8f48l },
-          0 },
-        /* 29 << 176 */
-        { { 0x5a304ada8545d185l,0x82ae44ea738bb8cbl,0x628a35e3df87e10el,
-            0xd3624f3da15b9fe3l },
-          { 0xcc44209b14be4254l,0x7d0efcbcbdbc2ea5l,0x1f60336204c37bbel,
-            0x21f363f556a5852cl },
-          0 },
-        /* 31 << 176 */
-        { { 0x81262e4225346689l,0x716da290b07c7004l,0x35f911eab7950ee3l,
-            0x6fd72969261d21b5l },
-          { 0x5238980308b640d3l,0x5b0026ee887f12a1l,0x20e21660742e9311l,
-            0x0ef6d5415ff77ff7l },
-          0 },
-        /* 33 << 176 */
-        { { 0x64aa0874925dd0b0l,0x5ffd503851c474c6l,0x4478c72c8ebd4157l,
-            0xb98694cb8c8375e2l },
-          { 0xeda4edeecd8e208cl,0xf98a053d2c0670a6l,0x564bd3057f346b9dl,
-            0xafbbf3e94c318fddl },
-          0 },
-        /* 34 << 176 */
-        { { 0x8a03410aa96c4685l,0xef1b6b16a978a31bl,0x44738a3b629df6cfl,
-            0xa1dc65da807713e9l },
-          { 0x569cc7884c373442l,0x1f30a2464965fb52l,0x56822f1677ff5e2el,
-            0x63f18812e303748bl },
-          0 },
-        /* 35 << 176 */
-        { { 0x2abdc403dd0983ecl,0xec0c08c7f365c6f5l,0xe555083fbdb66b8bl,
-            0x593685bc4e8973ffl },
-          { 0x737df3f920e9c705l,0x00c7bcc309c31a5al,0x5f1d23e2efdcb34dl,
-            0x79d9b382470f7949l },
-          0 },
-        /* 36 << 176 */
-        { { 0x44a315645fd2eb1dl,0x4e7397263fdd1356l,0x9b96735463200efel,
-            0xcb70402e520bbb6al },
-          { 0xcbc90d7e693d2642l,0x6fb00064bc9b4002l,0x95f2eab3d96f7150l,
-            0xb1619e3fe035f47al },
-          0 },
-        /* 37 << 176 */
-        { { 0xd22d6073d1561bb7l,0x40666e4ba9928683l,0x90654dab8ab3f9b1l,
-            0x7625c507b8773421l },
-          { 0x288f28220ca88cd2l,0xbb88114ed8d005c1l,0xbeec2b0af603a11bl,
-            0x8fdda60325f7949el },
-          0 },
-        /* 39 << 176 */
-        { { 0x6503632d6ee4f1d0l,0xd5449747ea394840l,0xd696167a8abe13a1l,
-            0xc080f76e609ebaa9l },
-          { 0x181acf0c10aa70d6l,0x70614461291e5e50l,0x7ade8e84b9f0c0a3l,
-            0xef1de9f2cb11b41el },
-          0 },
-        /* 40 << 176 */
-        { { 0x2d5c3c848e592413l,0x727022961832ba2cl,0x22979b51596c6321l,
-            0x738f31cb5a04db64l },
-          { 0x0bdaa6ca98f84ee5l,0x4e9e827c15e21eeel,0x4c59dbcc3ea632e0l,
-            0xed3404db5bc6f027l },
-          0 },
-        /* 41 << 176 */
-        { { 0x2841f05cfbaf8b26l,0xac9830db5b243770l,0xde3ab1707787f324l,
-            0x1ee12efe079209bcl },
-          { 0x2d3fd62d5bcf6e3cl,0x8a680655d60b0582l,0xdafc5061bc2b64a1l,
-            0xe0d91e7526a88788l },
-          0 },
-        /* 43 << 176 */
-        { { 0x2d49c685426b1b1el,0x6c2149caeabb02f7l,0xa4697d7fde11984fl,
-            0xa0e32fb3ed3c8707l },
-          { 0xb783e825f4ca12dal,0xb2666e2448770a50l,0x82d47f478660e923l,
-            0x6e36cd71fb4a984fl },
-          0 },
-        /* 44 << 176 */
-        { { 0x3295a8ea43c66b92l,0x99387af6ac5d19d4l,0x545f9b1b8e9d2090l,
-            0x138b1c4c2660f530l },
-          { 0xbfb05fd2ff872627l,0xb6614b0f4c3bc45cl,0x13defece62ca0fb0l,
-            0x82ddae134fededd8l },
-          0 },
-        /* 45 << 176 */
-        { { 0x5a34499b871c4cbbl,0x3ab0e69a2eb6084bl,0xa8d0160025ef7755l,
-            0x5db8f611d9e70f5dl },
-          { 0x63f9eb9a7afa95d7l,0x328b97f9706d7964l,0x8bcf9a0f4b71dfcal,
-            0x53d4c3042a5c7934l },
-          0 },
-        /* 46 << 176 */
-        { { 0x0c87dd3a8768d9aal,0x201ce5a082f6a55fl,0xa3de6f3049ca4602l,
-            0x36f421422aeb5f17l },
-          { 0x5c9962399817b77al,0x2584a10ae8d165acl,0x80f683d0c726f4aal,
-            0x524307502dcdfa48l },
-          0 },
-        /* 47 << 176 */
-        { { 0x0c04399f94683df2l,0x0978e9d4e954838dl,0x01faa5e8cf4a7a7bl,
-            0x92f6e6a90dae61cfl },
-          { 0x0c0f1293373dc957l,0x8320178fd8cc6b67l,0x4af977ed4b6444f2l,
-            0xd8c9a401ad8e5f84l },
-          0 },
-        /* 48 << 176 */
-        { { 0xbd5660ed9aed9f40l,0x70ca6ad1532a8c99l,0xc4978bfb95c371eal,
-            0xe5464d0d7003109dl },
-          { 0x1af32fdfd9e535efl,0xabf57ea798c9185bl,0xed7a741712b42488l,
-            0x8e0296a7e97286fal },
-          0 },
-        /* 49 << 176 */
-        { { 0x79ee35ac16fca804l,0x8f16e6165f59782el,0x8fbef1011737694el,
-            0xb34b7625462be08bl },
-          { 0x7e63e1b016e75c91l,0xb6a18edd2d23728dl,0xcf761a1e7f299ab6l,
-            0x796dcdebf16c770el },
-          0 },
-        /* 51 << 176 */
-        { { 0x47354f22308ee4afl,0x96959a538ecd6f4bl,0xf60b5f104055cbd2l,
-            0x04b1c9599bd86095l },
-          { 0x26accd8486008564l,0x46b2fe0478f31ea7l,0x5500dbf72dd76f23l,
-            0x36bcdf584c496c6fl },
-          0 },
-        /* 52 << 176 */
-        { { 0x8836cd431527d7cel,0x1f236623187a50eal,0x6470c0ae847221f0l,
-            0xc61f86b47e449110l },
-          { 0x7cc9cc20fa9fcec1l,0xa394903019134349l,0xafe5a08ff53ab467l,
-            0x9caba02301ed2919l },
-          0 },
-        /* 53 << 176 */
-        { { 0xffecbdce406abf1el,0x0ef4bcd73ae340d4l,0x7e37bae0e19d5613l,
-            0xe191669be4c6e97al },
-          { 0x9fafe59797292db7l,0xab7ef3713172d716l,0x9f0fff330ce3b533l,
-            0xca94ff8f932dd8cfl },
-          0 },
-        /* 55 << 176 */
-        { { 0x659c8b5d78aea69el,0xdde7ab46476a8fb9l,0x26bfe303bd01b5e6l,
-            0xf3dfb08a726a937cl },
-          { 0xe7a591fa0a263670l,0xe872c3f8f97434a0l,0x4881a82e2e0f2c21l,
-            0x17624e48788ef958l },
-          0 },
-        /* 57 << 176 */
-        { { 0xd526d66da7222e5bl,0xd33bb78efeb00e25l,0x9a7d670b932c8d08l,
-            0xea31e5273cee093fl },
-          { 0x55cc091bd04b7a43l,0x12b08d6dd01a123dl,0x1d98a6467fb0e7bal,
-            0xdabb09483535fd0dl },
-          0 },
-        /* 59 << 176 */
-        { { 0x2862314d08b69b19l,0x9cf302e191effcfal,0x43bdc8462ead917al,
-            0x21b238bbf94b3d8fl },
-          { 0xa3736160e2f465d3l,0x4d7fb6818541e255l,0x46fa089a23551edcl,
-            0xf7c41d17c1fefa8cl },
-          0 },
-        /* 60 << 176 */
-        { { 0x8ed0807fed113000l,0x8e1672d04c691484l,0x33a13ab31ee86ca0l,
-            0x9df0d9573bcaee4fl },
-          { 0x0cf0c638ef0dfb71l,0x1e0fe22ac2c9510al,0x43f506716fcc6a21l,
-            0xccb58404cec03a94l },
-          0 },
-        /* 61 << 176 */
-        { { 0x59547e37fd0936c1l,0x81e0517df45140b1l,0xcc6ccd89ed49e3fcl,
-            0xc2fa23eff3b897del },
-          { 0x149511ef2050c80al,0xf66bea6b3140b833l,0xbbe1401e2786d723l,
-            0x0aeb549c887509bcl },
-          0 },
-        /* 63 << 176 */
-        { { 0xf938e85060f5867al,0x806e1fff72429adcl,0x5ff7962a45f43b52l,
-            0xd8375ab6b2bbb403l },
-          { 0x00d5819b21b287fcl,0x15c7190ebae37d58l,0x075ce5ce05fcfb07l,
-            0x76368d06dbc003cbl },
-          0 },
-        /* 64 << 176 */
-        { { 0x01079383171b445fl,0x9bcf21e38131ad4cl,0x8cdfe205c93987e8l,
-            0xe63f4152c92e8c8fl },
-          { 0x729462a930add43dl,0x62ebb143c980f05al,0x4f3954e53b06e968l,
-            0xfe1d75ad242cf6b1l },
-          0 },
-        /* 65 << 176 */
-        { { 0x1cf508197630655el,0x9b4685c408d417f5l,0x6ea942619b049259l,
-            0x31c29b54fe73b755l },
-          { 0x3d2872a1f1f2af17l,0xbcd1139956bcbc4bl,0x4d14f59890d7a85cl,
-            0xd2c46040dbcbe998l },
-          0 },
-        /* 71 << 176 */
-        { { 0x3c8a06ca9792c42al,0x92535628602460ddl,0xa95e13f2ddd4c676l,
-            0xe823841d3b20d463l },
-          { 0x0248605bbfad6051l,0x82985dd61af51233l,0x3d243a5cdef7d742l,
-            0x0a88ce55ff6aa911l },
-          0 },
-        /* 77 << 176 */
-        { { 0xcf5b5962449aec98l,0x40322a6531a41389l,0xcd15606fd72c0527l,
-            0xfe91eac7b90d65a0l },
-          { 0xcd32415487636360l,0x82f2c7bdfc653a6fl,0xd04d138ae315ce7cl,
-            0x40ebfd5e78118dbcl },
-          0 },
-        /* 83 << 176 */
-        { { 0x0f9ea6ae4144660fl,0x02345c6513279b25l,0x139497b65c7671cbl,
-            0x7259f14b2ebed1d5l },
-          { 0xa1e5d98ce9b29988l,0xaed0efcd8df73ac8l,0x88339f073b81a77cl,
-            0x28f2bbca7109c8a6l },
-          0 },
-        /* 89 << 176 */
-        { { 0xa264f99d811472ddl,0x0e7eae0afc07a80cl,0x77f264d4a683cdc6l,
-            0x0512df49d053c668l },
-          { 0x2b4dfbade61dea15l,0x83de61acfd74890al,0xd2552bab32d41182l,
-            0x1fb9411435924e6al },
-          0 },
-        /* 95 << 176 */
-        { { 0x85efe53ade23c988l,0x89d41dbbf897f91bl,0x1357f91e7873fa8dl,
-            0x7a6ec2e3718d911cl },
-          { 0xf9e4f92e8f209a01l,0x4ffb96a70fdd67f3l,0x4c81a787f83dde1cl,
-            0x0d68fce15e163b60l },
-          0 },
-        /* 101 << 176 */
-        { { 0xbc79b4b26ab6da9dl,0xb4be5c278bb005f1l,0x63624530cd3b280bl,
-            0x543142f04e880026l },
-          { 0xbf7fb14cad90ddbfl,0xfe456e8a3966732dl,0x85499fb987ce35e9l,
-            0x8af09e6b24f1305dl },
-          0 },
-        /* 107 << 176 */
-        { { 0x5fc563ec16dc2b4bl,0xfe5631b25d0e535fl,0xbf4c489f9a93e36cl,
-            0x56badff1da2a07c4l },
-          { 0x72ac6b77fb7c5595l,0x4b25b9428e6645d9l,0xeeae127251f0657el,
-            0x30779ca51abeb76bl },
-          0 },
-        /* 113 << 176 */
-        { { 0x3d602ef5d909f43dl,0x2b2951a6bb347c79l,0x44903bfaa0d88896l,
-            0xd4ab20e8684c104fl },
-          { 0x55f70b4dd9b7e626l,0x084b3ee646a5f9ecl,0x1799cbe3da4ae81al,
-            0xc7cfac937fd6b80fl },
-          0 },
-        /* 116 << 176 */
-        { { 0x45647911ca20c525l,0x78f83186004706abl,0x5596377d97510538l,
-            0x047863defe041f8cl },
-          { 0xaea784896ec82367l,0x9d4eac2601eee8fcl,0xb32728f19b57d9dbl,
-            0x60a158f5313c0f65l },
-          0 },
-        /* 119 << 176 */
-        { { 0xf78caf129754377bl,0xa7fce16b6966f0c4l,0xfea937555a54a2b7l,
-            0x52d7f79b7cdfe951l },
-          { 0x3e14b92e94b1dac0l,0x363f2e5af168b73bl,0xcc0e9dcb6436a8c2l,
-            0x2dbece4bb52cbd27l },
-          0 },
-        /* 125 << 176 */
-        { { 0x7e7907ed8df38ffel,0xa68ec827e24e8a24l,0x5093a97e5f168732l,
-            0xa9ffea2f39ebb6dbl },
-          { 0x89e02c12284276d4l,0xc1179e3b3f9502d6l,0x01becb51d8f69eb6l,
-            0x86eee2935eb1c73cl },
-          0 },
-    },
-    {
-        /* 0 << 184 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 184 */
-        { { 0xf3b7963f4c830320l,0x842c7aa0903203e3l,0xaf22ca0ae7327afbl,
-            0x38e13092967609b6l },
-          { 0x73b8fb62757558f1l,0x3cc3e831f7eca8c1l,0xe4174474f6331627l,
-            0xa77989cac3c40234l },
-          0 },
-        /* 3 << 184 */
-        { { 0xb32cb8b0b796d219l,0xc3e95f4f34741dd9l,0x8721212568edf6f5l,
-            0x7a03aee4a2b9cb8el },
-          { 0x0cd3c376f53a89aal,0x0d8af9b1948a28dcl,0xcf86a3f4902ab04fl,
-            0x8aacb62a7f42002dl },
-          0 },
-        /* 4 << 184 */
-        { { 0xfd8e139f8f5fcda8l,0xf3e558c4bdee5bfdl,0xd76cbaf4e33f9f77l,
-            0x3a4c97a471771969l },
-          { 0xda27e84bf6dce6a7l,0xff373d9613e6c2d1l,0xf115193cd759a6e9l,
-            0x3f9b702563d2262cl },
-          0 },
-        /* 5 << 184 */
-        { { 0x9cb0ae6c252bd479l,0x05e0f88a12b5848fl,0x78f6d2b2a5c97663l,
-            0x6f6e149bc162225cl },
-          { 0xe602235cde601a89l,0xd17bbe98f373be1fl,0xcaf49a5ba8471827l,
-            0x7e1a0a8518aaa116l },
-          0 },
-        /* 7 << 184 */
-        { { 0x8b1e572235e6fc06l,0x3477728f0b3e13d5l,0x150c294daa8a7372l,
-            0xc0291d433bfa528al },
-          { 0xc6c8bc67cec5a196l,0xdeeb31e45c2e8a7cl,0xba93e244fb6e1c51l,
-            0xb9f8b71b2e28e156l },
-          0 },
-        /* 9 << 184 */
-        { { 0x343ac0a3ee9523f0l,0xbb75eab2975ea978l,0x1bccf332107387f4l,
-            0x790f92599ab0062el },
-          { 0xf1a363ad1e4f6a5fl,0x06e08b8462519a50l,0x609151877265f1eel,
-            0x6a80ca3493ae985el },
-          0 },
-        /* 10 << 184 */
-        { { 0xa3f4f521e447f2c4l,0x81b8da7a604291f0l,0xd680bc467d5926del,
-            0x84f21fd534a1202fl },
-          { 0x1d1e31814e9df3d8l,0x1ca4861a39ab8d34l,0x809ddeec5b19aa4al,
-            0x59f72f7e4d329366l },
-          0 },
-        /* 11 << 184 */
-        { { 0x2dfb9e08be0f4492l,0x3ff0da03e9d5e517l,0x03dbe9a1f79466a8l,
-            0x0b87bcd015ea9932l },
-          { 0xeb64fc83ab1f58abl,0x6d9598da817edc8al,0x699cff661d3b67e5l,
-            0x645c0f2992635853l },
-          0 },
-        /* 13 << 184 */
-        { { 0xd50e57c7d7fe71f3l,0x15342190bc97ce38l,0x51bda2de4df07b63l,
-            0xba12aeae200eb87dl },
-          { 0xabe135d2a9b4f8f6l,0x04619d65fad6d99cl,0x4a6683a77994937cl,
-            0x7a778c8b6f94f09al },
-          0 },
-        /* 15 << 184 */
-        { { 0x8dd1fb83425c6559l,0x7fc00ee60af06fdal,0xe98c922533d956dfl,
-            0x0f1ef3354fbdc8a2l },
-          { 0x2abb5145b79b8ea2l,0x40fd2945bdbff288l,0x6a814ac4d7185db7l,
-            0xc4329d6fc084609al },
-          0 },
-        /* 16 << 184 */
-        { { 0x511053e453544774l,0x834d0ecc3adba2bcl,0x4215d7f7bae371f5l,
-            0xfcfd57bf6c8663bcl },
-          { 0xded2383dd6901b1dl,0x3b49fbb4b5587dc3l,0xfd44a08d07625f62l,
-            0x3ee4d65b9de9b762l },
-          0 },
-        /* 17 << 184 */
-        { { 0x55ef9d3dcc26e8b0l,0xf869c827729b707al,0xdbbf450d8c47e00cl,
-            0x73d546ea60972ed7l },
-          { 0x9563e11f0dcd6821l,0xe48e1af57d80de7fl,0xbe7139b49057838dl,
-            0xf3f0ad4d7e5ca535l },
-          0 },
-        /* 19 << 184 */
-        { { 0xac66d1d49f8f8cc2l,0x43fe5c154ef18941l,0xbae77b6ddc30fcbfl,
-            0xdb95ea7d945723b7l },
-          { 0x43298e2bda8097e2l,0x8004167baf22ea9bl,0x9cf5974196a83d57l,
-            0xb35c9aba3cf67d5el },
-          0 },
-        /* 21 << 184 */
-        { { 0x0569a48df766f793l,0x6b4c7b16706b3442l,0xcc97754416ff41e0l,
-            0x800c56e31fee2e86l },
-          { 0xce0c3d0fcdf93450l,0x6ec3703582f35916l,0x902520d5bbc11e68l,
-            0x7e2b988505078223l },
-          0 },
-        /* 23 << 184 */
-        { { 0xb30d1769101da00bl,0xb26872d5113cfdb6l,0x7b0491da44e48db5l,
-            0x810e73bb2013f8c9l },
-          { 0xc86e579a570f0b59l,0xf34107e37a918f34l,0x49286d00277473f1l,
-            0x74423f5abc85905dl },
-          0 },
-        /* 25 << 184 */
-        { { 0x90d7417879de6b48l,0xe762caf0d14fa75bl,0xa309dcf3bd91ec5dl,
-            0x7aafe1ddf526d04fl },
-          { 0x76911342d39e36ffl,0xe28994d2fabb34b8l,0xac23a92c863110cbl,
-            0x9f0f69673aabd166l },
-          0 },
-        /* 27 << 184 */
-        { { 0x7436bdf47e333f98l,0x879cf31f2455af64l,0x07933a9cf6cfde92l,
-            0xfcac38a5b6e3203fl },
-          { 0xa39b6a8098e5a6e0l,0x1d600b5da4837528l,0x54718de7c32d412bl,
-            0x02870f46317937ccl },
-          0 },
-        /* 28 << 184 */
-        { { 0x1f13756db1761ec8l,0xe53c8b98a4b97e55l,0xb2aee3f84096cc28l,
-            0x48c361a0920f1a8dl },
-          { 0xa98b672d8c31190al,0x7bc1e7d1001855d4l,0x242cfb07bf3f4b2al,
-            0x9bf44a3f32a28bc4l },
-          0 },
-        /* 29 << 184 */
-        { { 0x96d4b271e36eeccdl,0x2d8c01b859237e23l,0x24f7a6eb8adf2653l,
-            0xc08ac4ab41183d80l },
-          { 0xc35e5bb7036367c3l,0xd8c97cbc0ba59f61l,0x296b1f4c5aafe986l,
-            0xa519c7a17d179c37l },
-          0 },
-        /* 31 << 184 */
-        { { 0x4043490790ae5f49l,0x8ac8f73649556b81l,0xb57a89b0f4e77a16l,
-            0xe1a1565d071020eal },
-          { 0x4a27f34d3dda8450l,0x65af18b9bc395814l,0xaf21939f9ff49991l,
-            0x47e00639b4af7691l },
-          0 },
-        /* 33 << 184 */
-        { { 0x4b3e263246b1f9b2l,0x6457d838efde99d3l,0x77d5142325e56171l,
-            0xb45de3df7d54996cl },
-          { 0x1ee2dd3194098d98l,0x986896141f3ebdc5l,0x2704a107997efb47l,
-            0x96b502eecb11e520l },
-          0 },
-        /* 34 << 184 */
-        { { 0x58c8039ec19f866el,0xc84c053e386c2644l,0xb3708ab049435704l,
-            0x1b70c3c86fc47b24l },
-          { 0x235582a27f095649l,0x0d344b66673c9a9el,0x777c9e71e2b00efdl,
-            0x91691d6e5b877856l },
-          0 },
-        /* 35 << 184 */
-        { { 0x11c663c49cd31e22l,0x46ae0bd95fb943d7l,0x6e36bca6a392fc01l,
-            0x4f8cc3a77948716fl },
-          { 0x10ae9d6b3aa4bbb0l,0xcc9b6cb5d8001a86l,0x012c8e3aa0a4ceedl,
-            0xe462971e52274942l },
-          0 },
-        /* 36 << 184 */
-        { { 0x9982e2ac42e176a5l,0x324eba46e2782b64l,0x3d8caaafe18350f5l,
-            0xf3d82af2f5d674cal },
-          { 0xc2090fed56600d1el,0x4548e0ef5950de07l,0xb2f0023f765a4febl,
-            0xb303103339f16790l },
-          0 },
-        /* 37 << 184 */
-        { { 0xb94095dc7bdacf7al,0x0e73db39509b310al,0x76e99a6b41b5f772l,
-            0xef40e9c596f3dbd7l },
-          { 0xd0d644f980f2179el,0xe0db831d5a89807el,0xa0188493c2a2d6c6l,
-            0xf2d9a85e5ba9faa9l },
-          0 },
-        /* 39 << 184 */
-        { { 0x598b7876cdd95b93l,0x5f7cc827336966e8l,0x01887109e797f102l,
-            0x665671c446c7c296l },
-          { 0xb314793c6e019c72l,0x5a6c81580e0329acl,0x4faf2f1b44281b98l,
-            0x825884072e1fc97el },
-          0 },
-        /* 40 << 184 */
-        { { 0xa692781d61a3c8b3l,0x08bc385432876d0el,0xbecf05fb28027b03l,
-            0x636c687da4b1e12fl },
-          { 0x00e3003d07217c58l,0x613ba9375e01b2a3l,0xa58c8405881de16el,
-            0xc653c43014f8f48bl },
-          0 },
-        /* 41 << 184 */
-        { { 0x68e53c7c89c0c7c2l,0xf2e680b23c423272l,0xacd47fae60f50133l,
-            0x4c484c6534f05605l },
-          { 0x663bdcf9ebffbb7dl,0xb49cff3be42421c6l,0x0549f7b13f53f261l,
-            0xc516aeda7c374766l },
-          0 },
-        /* 43 << 184 */
-        { { 0xa515fe0f76a0ec26l,0xf727c0797b0b8b21l,0xaeed4c671993651el,
-            0x1465a7f828ac7c87l },
-          { 0x776bd5131f0ef90bl,0x57515d2cd9773e61l,0x235455e95564c50bl,
-            0xf44daef80bf06a24l },
-          0 },
-        /* 44 << 184 */
-        { { 0xbc1c6897d6a0d0f9l,0xd8e0ea0e3b0d7f55l,0xb35baa92b85b7aadl,
-            0x2becd1b7674e48f4l },
-          { 0xe2d7f78d6d7a9ac2l,0xf5074262f99c95d0l,0x4852470a89f611e9l,
-            0xf7aa911992869decl },
-          0 },
-        /* 45 << 184 */
-        { { 0x0bd1755b0ac4840fl,0x0f4c6c2aa22eef10l,0x3f72fe2d78d16dd9l,
-            0xb2d49200ff7096a4l },
-          { 0xa5dead555ffca031l,0x1d013c320b65f4cfl,0x67e498582a23f441l,
-            0x55bae166d02412c0l },
-          0 },
-        /* 46 << 184 */
-        { { 0x546dd4545739a62al,0x353dc1422a30b836l,0x1462449d99cbd704l,
-            0xda02d0772da69411l },
-          { 0xcb115fe565b1a1adl,0x395235f501230a22l,0x8ae630eed164d970l,
-            0x60b679f0074e3a7el },
-          0 },
-        /* 47 << 184 */
-        { { 0x2e64695245d231e1l,0xc96663ac00d8a0fbl,0xc1fbaa0cd07e1f41l,
-            0x4b31484488758781l },
-          { 0xd6971a835183e72el,0xd1d01f174cbe99b7l,0xe90b438c5a2f7512l,
-            0xf858fa452957c620l },
-          0 },
-        /* 48 << 184 */
-        { { 0xed7f2e774e6daae2l,0x7b3ae0e39e0a19bcl,0xd3293f8a91ae677el,
-            0xd363b0cb45c8611fl },
-          { 0xbe1d1ccf309ae93bl,0xa3f80be73920cae1l,0xaaacba74498edf01l,
-            0x1e6d2a4ab2f5ac90l },
-          0 },
-        /* 49 << 184 */
-        { { 0xb5c5bb67b972a778l,0xc2423a4a190f9b5al,0x4e693cf365247948l,
-            0xc37d129ea94a65a3l },
-          { 0xbea4736b6e9cd47bl,0xf3d1bd212338f524l,0xa2a0278e067a45dal,
-            0xc86d631b5b5dce9bl },
-          0 },
-        /* 51 << 184 */
-        { { 0xc2d75f46116952cel,0xd2b66269b75e40dal,0x024f670f921c4111l,
-            0x37ffd854c91fd490l },
-          { 0x6be44d0385b2f613l,0x040cd7d9ba11c4f9l,0x04c1cb762c0efb1fl,
-            0xd905ff4f505e4698l },
-          0 },
-        /* 52 << 184 */
-        { { 0x60c5f03f233550f1l,0xd4d09411925afd2el,0xa95b65c3d258e5a6l,
-            0x1a19cfb59f902c6al },
-          { 0xb486013af5ad5c68l,0xa2506776979638f3l,0x1232b4d0a38e0b28l,
-            0xa64784b8d36a7b4fl },
-          0 },
-        /* 53 << 184 */
-        { { 0x22c75830a13dcb47l,0xd6e81258efd7a08fl,0x6db703b6e4fc49b8l,
-            0x8a5ac636f01817e9l },
-          { 0x8d27b6e1b3f24514l,0x40edc3bc708c51d7l,0x9a1eec7765bb086dl,
-            0x812ccb42b10800f8l },
-          0 },
-        /* 55 << 184 */
-        { { 0x1a39c6acd4338453l,0x3d93822954b1295dl,0x7bf0bf45e0d81165l,
-            0x83d58ca5972804d2l },
-          { 0x105d3ddb00524b94l,0x65d516e7920378ecl,0x1d28f5f1aea33926l,
-            0xa0b354313901c906l },
-          0 },
-        /* 57 << 184 */
-        { { 0x000442a1e4f354del,0x165b44d9d1d112f5l,0x67fd9ced0d05c0a9l,
-            0xd6ce074360bd5d60l },
-          { 0x9ac80c931522af2al,0x8232d522fa07d449l,0x287b5534c3fdb652l,
-            0x9f0548b3abd2ab98l },
-          0 },
-        /* 59 << 184 */
-        { { 0xde8d7086b9aea1d4l,0x692180d98a7dc3fcl,0xd64ffb53bad3e6f3l,
-            0x84628acf36ce3f91l },
-          { 0xf76e470b6d498ac5l,0xa16945547abad602l,0x5b8fd6a5a255c1f6l,
-            0xffe24e4a8576ae2al },
-          0 },
-        /* 60 << 184 */
-        { { 0x5655179de7d70e03l,0x3e780c5c72a84570l,0xc102b4cb1d50029cl,
-            0x3e71bdd5f075e839l },
-          { 0x6460f4f0b498b822l,0x2682e06c6d4b8da5l,0x4eae53c996a740d4l,
-            0xc19d8bef6389702cl },
-          0 },
-        /* 61 << 184 */
-        { { 0x711be2081025fe1dl,0x2e562c89f0bc6a99l,0xcfd2be3a28bf4150l,
-            0x33037b4a38e5bc91l },
-          { 0x10c6da9df52fea02l,0x511f62444f0ea410l,0x19d37ca81a294c3fl,
-            0x7e40f444618e6fd3l },
-          0 },
-        /* 63 << 184 */
-        { { 0x4095f5ddbedb8734l,0x9c16027c4432f51al,0xced8179d873d0f11l,
-            0x70c2bc9f6ebe6e61l },
-          { 0x5c31035d616cf2f4l,0xf92e0fbd00a4af3dl,0xe6048a03511893c4l,
-            0x639a804b52e2f462l },
-          0 },
-        /* 64 << 184 */
-        { { 0x8735728dc2c6ff70l,0x79d6122fc5dc2235l,0x23f5d00319e277f9l,
-            0x7ee84e25dded8cc7l },
-          { 0x91a8afb063cd880al,0x3f3ea7c63574af60l,0x0cfcdc8402de7f42l,
-            0x62d0792fb31aa152l },
-          0 },
-        /* 65 << 184 */
-        { { 0x0f4bcefd9da373e4l,0x7278f44d119271a3l,0xb2dff94449e111c0l,
-            0xb0a3abf8e5d2b2d4l },
-          { 0x01baabb48ea80631l,0x27517ed3da305f85l,0x0a1ca6fc3f56aa86l,
-            0x183d9c7694c22839l },
-          0 },
-        /* 71 << 184 */
-        { { 0xe9a0dfbf22e238d7l,0x8690dfd97e8d8d31l,0xb3cb2a0d4006c59cl,
-            0xe4d297caa1850d74l },
-          { 0x066f10517842d14cl,0x68dd32737d43602bl,0x1f9f5cf931345f39l,
-            0x44f18c2b10593890l },
-          0 },
-        /* 77 << 184 */
-        { { 0x8d8c0233a7c3f60bl,0xfb59fe2d2bcbbd4cl,0xfa311680dc3e5b44l,
-            0xb3cba9f3fbea5eedl },
-          { 0xcb353b2f61e0e690l,0x06edf0c1b6e0efe0l,0xa29578cb1d0c02a2l,
-            0xaeb2d677937fec07l },
-          0 },
-        /* 83 << 184 */
-        { { 0xa19a81c5cdd0cac9l,0x5c10b942ec9cf85bl,0x0843ef4639e8c298l,
-            0xcfd45d0e6c043258l },
-          { 0x1011bcb9fb7e4b58l,0xae6362a544402bbdl,0x9ecc8c68ec15d751l,
-            0xbc05998869d1a00bl },
-          0 },
-        /* 89 << 184 */
-        { { 0xe9a43619460147e3l,0x881a6af423067448l,0x94f93ae6cee17a6bl,
-            0x469e692f10782558l },
-          { 0x01e244a1289bdb32l,0x240645779dddf970l,0x664cbd92d8f521ecl,
-            0xadaf8ffb600222d0l },
-          0 },
-        /* 95 << 184 */
-        { { 0x68314c740dbec437l,0x2095e1295ec75e2cl,0x8e88a3ddf0e6c606l,
-            0x40ac647d1230f6b2l },
-          { 0x09d124aaa2e6b991l,0xa22f9e2bcc81037cl,0xc842b64d15c3a1c2l,
-            0x4d822becce808c65l },
-          0 },
-        /* 101 << 184 */
-        { { 0xb02204d06ffb396bl,0x82eb6ecc881bead6l,0xf58432cebd6896c8l,
-            0xc243468da38f4b9dl },
-          { 0x8486402df8e628bdl,0x5dd338a1a4df2401l,0x748a41ab0daac953l,
-            0xaa121d13e51e6235l },
-          0 },
-        /* 107 << 184 */
-        { { 0x6daa0a4e50abc6aal,0x99fcc5bdeafb7cf2l,0xc705f64c4b8dbd2al,
-            0x7deff836e7b51e90l },
-          { 0xd92f42b859a8180fl,0x3bb298f8618d24acl,0x2433aa7357a56438l,
-            0xcf29895b48a6a238l },
-          0 },
-        /* 113 << 184 */
-        { { 0x74079dc59ed25aafl,0x7988245c023d5143l,0x7edfc6a6feb79c24l,
-            0x7ed03c50a6baa70fl },
-          { 0x71d3413596a753b4l,0x59efbafcef976246l,0xed050260a4a6947fl,
-            0xabbc1f8066254247l },
-          0 },
-        /* 116 << 184 */
-        { { 0x1f804e00caa4646fl,0x8643dc8870944924l,0xa37f1ca273f86de9l,
-            0xa3199f9228889898l },
-          { 0xc273ba580c1e4adfl,0x0f0d38af65bc82f0l,0xd8b28ab5f8a6cd3bl,
-            0xeea6e08575894d8el },
-          0 },
-        /* 119 << 184 */
-        { { 0x398f39132c1620f7l,0x9046d2dea921f3a3l,0x40a25a2785b50bb0l,
-            0xb9adeca0d32e95f3l },
-          { 0xa4199b1bdede5cbfl,0x9068aee084f5410bl,0x6665e4f5730f0397l,
-            0x2e9ba18c8ae20659l },
-          0 },
-        /* 125 << 184 */
-        { { 0xd76e9b2351835897l,0x72a0e000012deda6l,0x5bf08922bfec23e4l,
-            0x8c2fcf1385cf2b7bl },
-          { 0x6c42f935c63332c6l,0x8736c58395eccce9l,0x2d2abbb10721afc8l,
-            0x1f7a76cc42d4e029l },
-          0 },
-    },
-    {
-        /* 0 << 192 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 192 */
-        { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l,
-            0x803f3e02cd42ab1bl },
-          { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl,
-            0xc097440e5067adc1l },
-          0 },
-        /* 3 << 192 */
-        { { 0x266344a43794f8dcl,0xdcca923a483c5c36l,0x2d6b6bbf3f9d10a0l,
-            0xb320c5ca81d9bdf3l },
-          { 0x620e28ff47b50a95l,0x933e3b01cef03371l,0xf081bf8599100153l,
-            0x183be9a0c3a8c8d6l },
-          0 },
-        /* 4 << 192 */
-        { { 0xb6c185c341dca566l,0x7de7fedad8622aa3l,0x99e84d92901b6dfbl,
-            0x30a02b0e7c4ad288l },
-          { 0xc7c81daa2fd3cf36l,0xd1319547df89e59fl,0xb2be8184cd496733l,
-            0xd5f449eb93d3412bl },
-          0 },
-        /* 5 << 192 */
-        { { 0x25470fabe085116bl,0x04a4337587285310l,0x4e39187ee2bfd52fl,
-            0x36166b447d9ebc74l },
-          { 0x92ad433cfd4b322cl,0x726aa817ba79ab51l,0xf96eacd8c1db15ebl,
-            0xfaf71e910476be63l },
-          0 },
-        /* 7 << 192 */
-        { { 0x72cfd2e949dee168l,0x1ae052233e2af239l,0x009e75be1d94066al,
-            0x6cca31c738abf413l },
-          { 0xb50bd61d9bc49908l,0x4a9b4a8cf5e2bc1el,0xeb6cc5f7946f83acl,
-            0x27da93fcebffab28l },
-          0 },
-        /* 9 << 192 */
-        { { 0x3ce519ef76257c51l,0x6f5818d318d477e7l,0xab022e037963edc0l,
-            0xf0403a898bd1f5f3l },
-          { 0xe43b8da0496033cal,0x0994e10ea1cfdd72l,0xb1ec6d20ba73c0e2l,
-            0x0329c9ecb6bcfad1l },
-          0 },
-        /* 10 << 192 */
-        { { 0xf1ff42a12c84bd9dl,0x751f3ec4390c674al,0x27bb36f701e5e0cal,
-            0x65dfff515caf6692l },
-          { 0x5df579c4cd7bbd3fl,0xef8fb29785591205l,0x1ded7203e47ac732l,
-            0xa93dc45ccd1c331al },
-          0 },
-        /* 11 << 192 */
-        { { 0xbdec338e3318d2d4l,0x733dd7bbbe8de963l,0x61bcc3baa2c47ebdl,
-            0xa821ad1935efcbdel },
-          { 0x91ac668c024cdd5cl,0x7ba558e4c1cdfa49l,0x491d4ce0908fb4dal,
-            0x7ba869f9f685bde8l },
-          0 },
-        /* 13 << 192 */
-        { { 0xed1b5ec279f464bal,0x2d65e42c47d72e26l,0x8198e5749e67f926l,
-            0x4106673834747e44l },
-          { 0x4637acc1e37e5447l,0x02cbc9ecf3e15822l,0x58a8e98e805aa83cl,
-            0x73facd6e5595e800l },
-          0 },
-        /* 15 << 192 */
-        { { 0x468ff80338330507l,0x06f34ddf4037a53el,0x70cd1a408d6993a4l,
-            0xf85a159743e5c022l },
-          { 0x396fc9c2c125a67dl,0x03b7bebf1064bfcbl,0x7c444592a9806dcbl,
-            0x1b02614b4487cd54l },
-          0 },
-        /* 16 << 192 */
-        { { 0x8303604f692ac542l,0xf079ffe1227b91d3l,0x19f63e6315aaf9bdl,
-            0xf99ee565f1f344fbl },
-          { 0x8a1d661fd6219199l,0x8c883bc6d48ce41cl,0x1065118f3c74d904l,
-            0x713889ee0faf8b1bl },
-          0 },
-        /* 17 << 192 */
-        { { 0xb47b60f70de21bb6l,0x64acae4fdcd836cal,0x3375ea6dc744ce63l,
-            0xb764265fb047955bl },
-          { 0xc68a5d4c9841c2c3l,0x60e98fd7cf454f60l,0xc701fbe2756aea0cl,
-            0x09c8885eaab21c79l },
-          0 },
-        /* 19 << 192 */
-        { { 0x45bb810869d2d46cl,0xe47c8b3968c8365al,0xf3b87663267551bdl,
-            0x1590768f5b67547al },
-          { 0x371c1db2fb2ed3ffl,0xe316691917a59440l,0x03c0d178df242c14l,
-            0x40c93fceed862ac1l },
-          0 },
-        /* 21 << 192 */
-        { { 0x1286da692bc982d6l,0x5f6d80f27bdae7e3l,0x3d9c5647a6f064fbl,
-            0xfdc8e6a1d74c1540l },
-          { 0x97da48c6d68b135al,0xc2097979d66dbfffl,0x0296adb9ea20531dl,
-            0xa333730d4ab2c8f0l },
-          0 },
-        /* 23 << 192 */
-        { { 0x0eb3565429847fedl,0xfdc142860a673dd0l,0x721b36278b62dd0bl,
-            0x105a293e711a5771l },
-          { 0xdf001cce7f761927l,0xf7b681b011d04c7dl,0x16dff792a3ac1996l,
-            0x580c120b0fc4ae30l },
-          0 },
-        /* 25 << 192 */
-        { { 0x31ea3d4f7ee8d0bcl,0x3832f22a0f42c3dcl,0xc661061a1a87a2f4l,
-            0x0978c9f64b45576bl },
-          { 0xb7abac3c6dfb5fd2l,0x27f36a00b7e01b90l,0x68f733cde9429e36l,
-            0x953a4681dcbfe8cbl },
-          0 },
-        /* 27 << 192 */
-        { { 0xbfb7c41067fe1eafl,0xa2073c6a6929a785l,0x6f2536f4a75fdb79l,
-            0x859ad26d809bca69l },
-          { 0x06f2c0693b197e7bl,0x656ad9f48ec0a573l,0xe7c7901f9a4d0262l,
-            0xbec29443b938602bl },
-          0 },
-        /* 28 << 192 */
-        { { 0xd00397fc0f0073a4l,0x5b668fa46f8d675fl,0x14374ac91522108cl,
-            0x92efa7d10283e42el },
-          { 0x673e6df90b6d024al,0x05f914d457581f26l,0xf5c8516267df8c12l,
-            0x1197f1b4e06c2462l },
-          0 },
-        /* 29 << 192 */
-        { { 0x6e2d1cb3dd9c90c1l,0x28f82d5a7990579el,0x90e189cd06226195l,
-            0xbd2939df19b0dc74l },
-          { 0x18b18505c0917177l,0xeed5470d3117d9c4l,0x39ef92eb6c893ca0l,
-            0x4533ef8244a41940l },
-          0 },
-        /* 31 << 192 */
-        { { 0xcaee9dec34943ddal,0x8e50e98e8b4b6782l,0x24358ea591ea3a1fl,
-            0x71c4c827a9e1c194l },
-          { 0xa38baa5d09bb7a94l,0xfb4ab4c057b58f9cl,0x4a01065e24e0ee19l,
-            0xb9cf805107b877bfl },
-          0 },
-        /* 33 << 192 */
-        { { 0xd38c1ce0a2980d5el,0x8b84cca4541face7l,0x93298136dbd8d05dl,
-            0x582708d03f85c85al },
-          { 0x6545eec7282960e4l,0x92e184aebaadec07l,0x05452564fd27a20fl,
-            0x79d4668abddce6ebl },
-          0 },
-        /* 34 << 192 */
-        { { 0xf5cc5cccf5191707l,0xe800328bd5d01f67l,0x0572012ebd9b1599l,
-            0xf5be11a6863d0125l },
-          { 0x4da7ca876ea441e0l,0x47dbf83b321b134al,0x5cbadcdac1acfb4al,
-            0x19ac798a734f8e25l },
-          0 },
-        /* 35 << 192 */
-        { { 0xe312623a7002114fl,0xb888b637e047686bl,0x23b2c270cbac91bdl,
-            0xb50b31884dbfe02dl },
-          { 0x8335ce43de97eef6l,0x6a4e65502bac193al,0xf2b35aac3101f720l,
-            0x5b2c88d5379a2015l },
-          0 },
-        /* 36 << 192 */
-        { { 0xf445e77131547128l,0x22761665e27811cal,0x9b944e91a37c6681l,
-            0xc0aa06a536899860l },
-          { 0x8c2b5816cfcd557el,0xf2734a19945aa357l,0x536ca07ca55a0049l,
-            0x8328fdccc636d967l },
-          0 },
-        /* 37 << 192 */
-        { { 0x52b513616aca06bdl,0x8d19b893cdf16560l,0x06b28179c3b438cdl,
-            0xde1ef747cd1819e4l },
-          { 0xbc6cc43b5f557985l,0xa277e11f61e0142al,0x58890f1e429cc392l,
-            0x28d17dbfe5fc8f5el },
-          0 },
-        /* 39 << 192 */
-        { { 0x556df61a29a8f7cbl,0x5cf554dfd14ab27al,0x243f933ba755b886l,
-            0xa4d0b06ff2d4ce87l },
-          { 0xa745eb8d2c0f1d39l,0xc228747aea3047a5l,0xced774c41d2cecc0l,
-            0x54a55c3a774fb01al },
-          0 },
-        /* 40 << 192 */
-        { { 0xa691398a4a9eb3f0l,0x56c1dbff3b99a48fl,0x9a87e1b91b4b5b32l,
-            0xad6396145378b5fel },
-          { 0x437a243ec26b5302l,0x0275878c3ccb4c10l,0x0e81e4a21de07015l,
-            0x0c6265c9850df3c0l },
-          0 },
-        /* 41 << 192 */
-        { { 0x182c3f0e6be95db0l,0x8c5ab38cae065c62l,0xcce8294ebe23abacl,
-            0xed5b65c47d0add6dl },
-          { 0xbce57d78cc9494cal,0x76f75c717f435877l,0xb3084b2eb06560a9l,
-            0x67216bc850b55981l },
-          0 },
-        /* 43 << 192 */
-        { { 0x49c9fd92557de68bl,0x357aa44fc3151b7al,0xd36286d11e4aebd0l,
-            0x84562cd736a51203l },
-          { 0x42a57e7c3cacc002l,0x794a47751b1e25a3l,0x2c2ab68cac0d4356l,
-            0xececb6addb31afdcl },
-          0 },
-        /* 44 << 192 */
-        { { 0x47a5f010b4c21bfel,0x45c5610f0ac3dc20l,0x20e689fcea3bf4dcl,
-            0xf244ea49fb5f46e4l },
-          { 0xd918e59e8ca38e45l,0x7d6c601d96189a6fl,0x1a40f03854138471l,
-            0xfe867d7308a9d034l },
-          0 },
-        /* 45 << 192 */
-        { { 0x3b49e489100c0410l,0x8831d3992adc2b29l,0xb6726cd1247a8116l,
-            0x83a71a59d1d56d8el },
-          { 0x82ade2fe5cd333e9l,0x3b087ef83ea11f1al,0x17b96ca66ce879cel,
-            0xc2f74a971871dc43l },
-          0 },
-        /* 46 << 192 */
-        { { 0xa11a1e3680b576cel,0xf91278bbce2683e8l,0xc3bab95fbae8bc5bl,
-            0x642ca26397351715l },
-          { 0x5ffc14726fecbbc1l,0x2465e996a23f36d4l,0x06fc53bf5187d428l,
-            0x54b4014351fbce91l },
-          0 },
-        /* 47 << 192 */
-        { { 0x081ca6f0eafc7b2cl,0x1ba047a38c48703fl,0xe84865046663accfl,
-            0xde1f97568d43689cl },
-          { 0xf5373e1d5bc19f75l,0x4e48c493d64b0a54l,0x0c43f4e25807dbf6l,
-            0x73bef15167778c36l },
-          0 },
-        /* 48 << 192 */
-        { { 0xca6c0937b1b76ba6l,0x1a2eab854d2026dcl,0xb1715e1519d9ae0al,
-            0xf1ad9199bac4a026l },
-          { 0x35b3dfb807ea7b0el,0xedf5496f3ed9eb89l,0x8932e5ff2d6d08abl,
-            0xf314874e25bd2731l },
-          0 },
-        /* 49 << 192 */
-        { { 0x9d5322e89e9bba53l,0xdd7c9ceb989ff350l,0xd76147eadab0d7b3l,
-            0x8e45b1c6d7a9a9a1l },
-          { 0x8f896a91d4f10c10l,0x999a73c54068de06l,0x84a9d0839cf0a779l,
-            0x4d7cc7689f608ab2l },
-          0 },
-        /* 51 << 192 */
-        { { 0x1833ccddaee93c82l,0x6a05ef7b9f35f20fl,0xc538dac9ae413bc2l,
-            0x1e74f4658b4784bdl },
-          { 0xccb2bc4a49ffd544l,0x9b88183d2b17ae88l,0x96037a136e43824fl,
-            0xbbb61441480bf3dfl },
-          0 },
-        /* 52 << 192 */
-        { { 0x13319d20e090ad42l,0x4ff3186e12cbb719l,0xf38e504913fc0a46l,
-            0x83185a1254e60378l },
-          { 0x08c4057797ea8935l,0x7b2212a946b614f9l,0xedcdfa520634cfb3l,
-            0xdbc60eed9e7d5726l },
-          0 },
-        /* 53 << 192 */
-        { { 0x9b0785c6c7e1070fl,0xec112f53cbf561e5l,0xc93511e37fab3464l,
-            0x9e6dc4da9de8e0c2l },
-          { 0x7733c425e206b4eel,0xb8b254ef50cedf29l,0xfaee4bbbd50ad285l,
-            0x216e76d58c4eb6cfl },
-          0 },
-        /* 55 << 192 */
-        { { 0x9d6a28641d51f254l,0x26c5062a0c2822c3l,0xd74ebba8334bf4eel,
-            0x6e5446eb0b8f7305l },
-          { 0x5988ae8eb629beccl,0x71e576d0a1de7d1dl,0x15e39592a8873970l,
-            0x2b1f9a9342ecc74el },
-          0 },
-        /* 57 << 192 */
-        { { 0xcbdb70727c519bf9l,0x112986bbcaaf48e6l,0x64d4c6d1a13baf3cl,
-            0x85ccf6f7a065e77el },
-          { 0x183be337749beaedl,0xb3703096cba6c9b1l,0x1edf81f0e42b8afel,
-            0xf04ed594ccb73ad7l },
-          0 },
-        /* 59 << 192 */
-        { { 0xfa954ebc38491e9fl,0xf75a5808d32f0b03l,0x196d4a828083b9d3l,
-            0x92d5a0be5e8dc9fel },
-          { 0x4a507ae9aea628bal,0xeea5861e11a02fb5l,0xa033b84fd23ec8f7l,
-            0x1a68c36ec60f11d5l },
-          0 },
-        /* 60 << 192 */
-        { { 0x3dfb55bdab920ef2l,0xe0090971e6244484l,0xdc39fd08f7c6e1a3l,
-            0x1ca765356ee79e72l },
-          { 0x472c8985287d590cl,0x67635e35ad6daeb4l,0x06ec4e7980f9fee3l,
-            0x0aceb39921dc5fdbl },
-          0 },
-        /* 61 << 192 */
-        { { 0xdb2478fd9410a756l,0xd106aefe3a53a1e6l,0x1f4c940d14286333l,
-            0x6a98659d04950958l },
-          { 0x3232a1c6a6bbe060l,0x19ad132ca5e7ca9bl,0x3c9c13ef800fae29l,
-            0x9b0d9068b8660f49l },
-          0 },
-        /* 63 << 192 */
-        { { 0x1e7f043795c53027l,0x5221e5c0da9a3806l,0xf297d8e379d9385fl,
-            0x4d69e95f78ba697el },
-          { 0xdda936cee76d13c1l,0xd9a5790a485b12f5l,0xeab84add51efbfd0l,
-            0xc9a3ee9ca9f44aa4l },
-          0 },
-        /* 64 << 192 */
-        { { 0xefb26a753f73f449l,0x1d1c94f88d44fc79l,0x49f0fbc53bc0dc4dl,
-            0xb747ea0b3698a0d0l },
-          { 0x5218c3fe228d291el,0x35b804b543c129d6l,0xfac859b8d1acc516l,
-            0x6c10697d95d6e668l },
-          0 },
-        /* 65 << 192 */
-        { { 0x8c12e87a15454db4l,0xbc1fc546908e8fbcl,0xc35d83c7e4cf1636l,
-            0xcb2f5ac820641524l },
-          { 0x2400aae2e644ecd0l,0x9b01e2d14be37119l,0x6cffd52831b54857l,
-            0xb3fd5d864b5cbf81l },
-          0 },
-        /* 71 << 192 */
-        { { 0x2e999a4739709fb9l,0x4cb4bbdb62c2b30fl,0x4c7259ac09de0c92l,
-            0x73c1e34f8c59a0ffl },
-          { 0x0a9e5f2e48cb0a12l,0x5e07449fcf499bb0l,0x0527a8b4b02c4a54l,
-            0x7381287159da01e4l },
-          0 },
-        /* 77 << 192 */
-        { { 0xe0b876ca0548ff87l,0x74b5a9b25e03bae3l,0xd5564cc5dd0642d2l,
-            0x29ed211b668c4977l },
-          { 0xf29d3b7aa7422b11l,0x17f2d3586d29b8bal,0x2e35cdda2bb887del,
-            0x650f148078e4444bl },
-          0 },
-        /* 83 << 192 */
-        { { 0x8c75532fb47435ebl,0x2234e2c5a113f905l,0x27b75fea31508ae9l,
-            0x09733e40d489ad0bl },
-          { 0x73b38464a1b06da1l,0x0aed522dc5b7ccf2l,0xcc04783e78d7e5afl,
-            0xa81c8a8ff23eaab7l },
-          0 },
-        /* 89 << 192 */
-        { { 0x6bb5eca73c149ffal,0x4593d851c536487al,0x3675daaad85eb9edl,
-            0xbf65d0f9b8a58ffbl },
-          { 0x1dc6ddddc22e83eel,0xb673397ee10d3c17l,0x6bdc20600ca62c93l,
-            0x260389c30b821f6dl },
-          0 },
-        /* 95 << 192 */
-        { { 0x45f5cf07b417be10l,0x0acb1a44e5d561d8l,0x54b7baeafb1dfbe9l,
-            0x0e6e66219044672el },
-          { 0xa9b6db6d9a793601l,0xd70eadb8a4a0ba4al,0xaedace846098b89el,
-            0x970f2c23ac39d40fl },
-          0 },
-        /* 101 << 192 */
-        { { 0x9dff8d289c7eaaa8l,0x38bcd076db0cc361l,0x25760147cdea9db8l,
-            0x44c89dd40163f343l },
-          { 0x18815d7544db8365l,0xa186d57b37f3e4b3l,0xa71de7806e84a7fal,
-            0xf1c08989e56646b3l },
-          0 },
-        /* 107 << 192 */
-        { { 0xad73e1448fb56a43l,0x078c14fb715543c9l,0xa57770fd64b92d54l,
-            0xf0420a9277e9b919l },
-          { 0xc660d0cb588ccc1dl,0x069baa1471415c2el,0x747438dc32982740l,
-            0x4782ce08767381eel },
-          0 },
-        /* 113 << 192 */
-        { { 0xc2a1ee5fdb3b6b5dl,0x08ce544820e1339fl,0x3cb954b77073955fl,
-            0xb9ed2ee7f32d0832l },
-          { 0xc0a998b1b4aac98el,0x4912273dbca4bac7l,0xac0f5014c3f92c4al,
-            0xbf3dc27f9e916e78l },
-          0 },
-        /* 116 << 192 */
-        { { 0x222c7bae28833944l,0xbb78a867f5e3cf67l,0x590cbd96faf6cfd6l,
-            0x1c50aecb3b0d842el },
-          { 0x8f2c5df1dbade9a5l,0x60923fb7e3840cecl,0xe8f2db6b03a67512l,
-            0x90af187be0d7c628l },
-          0 },
-        /* 119 << 192 */
-        { { 0xb4162b615fee3ccbl,0xe9786e7d7327e651l,0x6c85bd938812d9c1l,
-            0xfe4905083dc9e838l },
-          { 0xe66f25178a6765dfl,0x72fd294edeee184cl,0x07608bd27b6ec227l,
-            0x9df7b664dfdaa5e6l },
-          0 },
-        /* 125 << 192 */
-        { { 0x4aea16602d53a155l,0x7285069a32ab07fdl,0xf6f3000d8b6fcd19l,
-            0x010b1f246e98953fl },
-          { 0xe180bc559f9aa221l,0x7717ee383cba4534l,0x5997f3aa36cbda06l,
-            0x54c6090064a04b05l },
-          0 },
-    },
-    {
-        /* 0 << 200 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 200 */
-        { { 0x25914f7881fdad90l,0xcf638f560d2cf6abl,0xb90bc03fcc054de5l,
-            0x932811a718b06350l },
-          { 0x2f00b3309bbd11ffl,0x76108a6fb4044974l,0x801bb9e0a851d266l,
-            0x0dd099bebf8990c1l },
-          0 },
-        /* 3 << 200 */
-        { { 0xebd6a6777b0ac93dl,0xa6e37b0d78f5e0d7l,0x2516c09676f5492bl,
-            0x1e4bf8889ac05f3al },
-          { 0xcdb42ce04df0ba2bl,0x935d5cfd5062341bl,0x8a30333382acac20l,
-            0x429438c45198b00el },
-          0 },
-        /* 4 << 200 */
-        { { 0xfb2838be67e573e0l,0x05891db94084c44bl,0x9131137396c1c2c5l,
-            0x6aebfa3fd958444bl },
-          { 0xac9cdce9e56e55c1l,0x7148ced32caa46d0l,0x2e10c7efb61fe8ebl,
-            0x9fd835daff97cf4dl },
-          0 },
-        /* 5 << 200 */
-        { { 0x6c626f56c1770616l,0x5351909e09da9a2dl,0xe58e6825a3730e45l,
-            0x9d8c8bc003ef0a79l },
-          { 0x543f78b6056becfdl,0x33f13253a090b36dl,0x82ad4997794432f9l,
-            0x1386493c4721f502l },
-          0 },
-        /* 7 << 200 */
-        { { 0xe566f400b008733al,0xcba0697d512e1f57l,0x9537c2b240509cd0l,
-            0x5f989c6957353d8cl },
-          { 0x7dbec9724c3c2b2fl,0x90e02fa8ff031fa8l,0xf4d15c53cfd5d11fl,
-            0xb3404fae48314dfcl },
-          0 },
-        /* 9 << 200 */
-        { { 0xf02cc3a9f327a07fl,0xefb27a9b4490937dl,0x81451e96b1b3afa5l,
-            0x67e24de891883be4l },
-          { 0x1ad65d4770869e54l,0xd36291a464a3856al,0x070a1abf7132e880l,
-            0x9511d0a30e28dfdfl },
-          0 },
-        /* 10 << 200 */
-        { { 0xfdeed650f8d1cac4l,0xeb99194b6d16bda5l,0xb53b19f71cabbe46l,
-            0x5f45af5039b9276cl },
-          { 0xd0784c6126ee9d77l,0xf7a1558b0c02ca5dl,0xb61d6c59f032e720l,
-            0xae3ffb95470cf3f7l },
-          0 },
-        /* 11 << 200 */
-        { { 0x9b185facc72a4be5l,0xf66de2364d848089l,0xba14d07c717afea9l,
-            0x25bfbfc02d551c1cl },
-          { 0x2cef0ecd4cdf3d88l,0x8cee2aa3647f73c4l,0xc10a7d3d722d67f7l,
-            0x090037a294564a21l },
-          0 },
-        /* 13 << 200 */
-        { { 0x6ac07bb84f3815c4l,0xddb9f6241aa9017el,0x31e30228ca85720al,
-            0xe59d63f57cb75838l },
-          { 0x69e18e777baad2d0l,0x2cfdb784d42f5d73l,0x025dd53df5774983l,
-            0x2f80e7cee042cd52l },
-          0 },
-        /* 15 << 200 */
-        { { 0x43f18d7f4d6ee4abl,0xd3ac8cde9570c3dcl,0x527e49070b8c9b2al,
-            0x716709a7c5a4c0f1l },
-          { 0x930852b0916a26b1l,0x3cc17fcf4e071177l,0x34f5e3d459694868l,
-            0xee0341aba28f655dl },
-          0 },
-        /* 16 << 200 */
-        { { 0xf431f462060b5f61l,0xa56f46b47bd057c2l,0x348dca6c47e1bf65l,
-            0x9a38783e41bcf1ffl },
-          { 0x7a5d33a9da710718l,0x5a7799872e0aeaf6l,0xca87314d2d29d187l,
-            0xfa0edc3ec687d733l },
-          0 },
-        /* 17 << 200 */
-        { { 0x4b764317aa365220l,0x7a24affe68cc0355l,0x76732ed0ceb3df5el,
-            0x2ce1332aae096ed0l },
-          { 0x89ce70a7b8adac9dl,0xfdddcf05b3fc85c8l,0xbd7b29c6f2ee8bfel,
-            0xa1effcb9457d50f3l },
-          0 },
-        /* 19 << 200 */
-        { { 0x6053972dac953207l,0xc2ca9a8408ad12f6l,0x9ed6cd386ba36190l,
-            0xa5b50a48539d18a4l },
-          { 0xd9491347dbf18c2al,0x2cdce4662e9697cfl,0x4e97db5ca9e31819l,
-            0x0fb02e2d4c044b74l },
-          0 },
-        /* 21 << 200 */
-        { { 0x66a4dd414aa5e9ddl,0x6ec7576e64f6aeb9l,0x3f08ce06c7e980b5l,
-            0x52fe9fd6c1a2aa7el },
-          { 0xfe46e6d95074326al,0xd570ed734c126c1dl,0x86c7ec257217d55al,
-            0x3cb434057c3de2b2l },
-          0 },
-        /* 23 << 200 */
-        { { 0x48e0295dcc9e79bfl,0x2419485693eb403dl,0x9386fb7709dd8194l,
-            0xb6e89bb101a242f6l },
-          { 0xc7994f3924d308d7l,0xf0fbc392de673d88l,0x43eed52ea11abb62l,
-            0xc900f9d0c83e7fbel },
-          0 },
-        /* 25 << 200 */
-        { { 0x214a10dca8152891l,0xe6787b4c64f1abb2l,0x276333d9fa1a10edl,
-            0xc0e1c88e47dbccbcl },
-          { 0x8a3c37c4849dd12el,0x2144a8c8d86e109fl,0xbb6891f7286c140cl,
-            0xb0b8c5e29cce5e6fl },
-          0 },
-        /* 27 << 200 */
-        { { 0x3f9e0e3499753288l,0x6b26f1ebe559d93al,0x647fe21d9841faf1l,
-            0x48a4b6efa786ea02l },
-          { 0x6e09cd22665a882dl,0x95390d81b63ccda6l,0x5b014db4b026a44al,
-            0x5b96efb22ad30ff1l },
-          0 },
-        /* 28 << 200 */
-        { { 0x64c50c8b4a3b99e9l,0x2489a675d0a26f4fl,0xe2aacaeed85bc6fdl,
-            0x556882038a6019bal },
-          { 0x7ceb9da645cfac07l,0xe1ad3d25652dbd09l,0x086adf348d3b5d2bl,
-            0xf9256d8aec3654a0l },
-          0 },
-        /* 29 << 200 */
-        { { 0x571c246bf009a690l,0x8fe54231ccd90d3al,0x8adde6adfe173b79l,
-            0x75d9a392b05a5e3bl },
-          { 0x607f47b0d1bb3a84l,0xe4e3b472058e691al,0xfc0f793bf3d956e3l,
-            0x6a6730b605de54dal },
-          0 },
-        /* 31 << 200 */
-        { { 0x4daf7f540d80aaa1l,0xc571d04c229c4574l,0x469e2da5fffca53dl,
-            0x9fffe29513ff7f59l },
-          { 0x2075da5a33a254f7l,0x769f33acd35e575dl,0x7b940d2c3d35001al,
-            0x2d606b57e34c95b7l },
-          0 },
-        /* 33 << 200 */
-        { { 0xc7e4f8b899365f86l,0x8f6f959faae69527l,0x749ffedffdfaeeeal,
-            0x2b91f0221b54c2a0l },
-          { 0xe75c2352addbdf83l,0xe7329922fff2694cl,0xbb65ae06badadeacl,
-            0x16cbb9d1f56be3b5l },
-          0 },
-        /* 34 << 200 */
-        { { 0xb100a4c67a07bd70l,0x222fee7634787efel,0xa4dafc14f1e79d1bl,
-            0x0d3a82dad18b8be4l },
-          { 0xe0181445fc06922fl,0x0873d99b714a90b6l,0xdf43082fa5087a0el,
-            0x195e49367399e0dbl },
-          0 },
-        /* 35 << 200 */
-        { { 0x7e83545aae6fcc9cl,0x1a24fce819e15ce2l,0x4a3465c536d8c6a8l,
-            0xd1e5f24109436ae0l },
-          { 0xed334bfc6be463d5l,0xc46a600b934fbdcfl,0xbd2fd65b920321ffl,
-            0x953fa91767fa154el },
-          0 },
-        /* 36 << 200 */
-        { { 0x5dca4995f93ddad1l,0x061efcabf72470c2l,0xad78d54d5e7e0741l,
-            0xa91f4e839c4e0ab4l },
-          { 0xdd4403af5c75aa0dl,0x4308c8ee13c69113l,0x3a3b66f51ebc36adl,
-            0xc07cc3f0f4bf777al },
-          0 },
-        /* 37 << 200 */
-        { { 0x3fd1963e37a86b32l,0x22e236d60bd0880el,0xb87467cf89f0fa5cl,
-            0x85b9c6c0310e0265l },
-          { 0x82979a96783459ael,0xd19b0919bd529ed3l,0xa21f771808434f94l,
-            0x3dd130a9195369c6l },
-          0 },
-        /* 39 << 200 */
-        { { 0xc61e62767915d157l,0xc48244279e07fb0el,0x8980c1cc8420ea49l,
-            0x10d82e4a588d4e2bl },
-          { 0xdddecd52b17eff2dl,0xe44c7b2ded8492a4l,0x96ca89ebb9bea6afl,
-            0x724166fe1b03ed03l },
-          0 },
-        /* 40 << 200 */
-        { { 0xfc87975f8fb54738l,0x3516078827c3ead3l,0x834116d2b74a085al,
-            0x53c99a73a62fe996l },
-          { 0x87585be05b81c51bl,0x925bafa8be0852b7l,0x76a4fafda84d19a7l,
-            0x39a45982585206d4l },
-          0 },
-        /* 41 << 200 */
-        { { 0x8bbc484ed551f3e1l,0x6e058a90b7eb06d2l,0xfaccd9a0e5cd281al,
-            0xe7661b78d5b44900l },
-          { 0x03afe115725fde22l,0xbe929230c7229fd1l,0x5cd0d16a0000035el,
-            0x1f6a9df0c8f5a910l },
-          0 },
-        /* 43 << 200 */
-        { { 0xe54bbcfd535dfc82l,0x89be0b89a9012196l,0xa67831ee71011beal,
-            0x2ea7a8292db43878l },
-          { 0xff7c144378ffe871l,0xa67dc3d4c63f65eal,0xbbfc7fc2a1527419l,
-            0x6440380bf6c36b8fl },
-          0 },
-        /* 44 << 200 */
-        { { 0x71ab9f69d812d7e6l,0x2847c5516e142126l,0x9e27755bb31e7753l,
-            0xb89533e2943b8c7fl },
-          { 0xbe7f0c6e14fa7dc6l,0x782a06388cee1f7al,0x7069292938e13a6bl,
-            0x1e1221f0c63f4d28l },
-          0 },
-        /* 45 << 200 */
-        { { 0x9030aa9a63a431f4l,0x0fa7b5d45039a318l,0x6a0cf40af083687dl,
-            0x46689cec659fa752l },
-          { 0x8259727a456fa97el,0x4f618a355b08d7fcl,0x2c44217b72028d15l,
-            0x8083b09935111e32l },
-          0 },
-        /* 46 << 200 */
-        { { 0xaa5976523b5b29f1l,0xb07f10ab37432a54l,0x16e3e2236e36556fl,
-            0xf1c7c9bd47cd4586l },
-          { 0xa4eef99d3f87216dl,0x4e54d3c52e1eaa79l,0x534c5901d2540d91l,
-            0x718df7c9b6f0fcfcl },
-          0 },
-        /* 47 << 200 */
-        { { 0x99497f8a2eb0ee3bl,0x87e550c1caeb3a20l,0xd23e053dfb91627cl,
-            0xb971c043873124e6l },
-          { 0x3581ab853b16e467l,0x24541c926145187bl,0x4423ec5c010c2527l,
-            0x775f13029fa82a68l },
-          0 },
-        /* 48 << 200 */
-        { { 0x499b6ab65eb03c0el,0xf19b795472bc3fdel,0xa86b5b9c6e3a80d2l,
-            0xe43775086d42819fl },
-          { 0xc1663650bb3ee8a3l,0x75eb14fcb132075fl,0xa8ccc9067ad834f6l,
-            0xea6a2474e6e92ffdl },
-          0 },
-        /* 49 << 200 */
-        { { 0xbaebdd8a0c40aec4l,0x5eccafb563e8cfd0l,0x1c204c0eb5159938l,
-            0x607109d34b996aa9l },
-          { 0x024c6c4b9cef59fel,0xbc846e216ed4b6f1l,0xf6a50ff3ff652c0al,
-            0x368af2c72d95220cl },
-          0 },
-        /* 51 << 200 */
-        { { 0xec9c2e35cbd3ccafl,0xb9eeff3ddcda8f30l,0x82012e191062d02el,
-            0xed964cc94efc6b6el },
-          { 0x8853ea0a6bf54c22l,0xea40fcc0f3cbe264l,0x21f9c01ddecf114el,
-            0x05e754c63da71e59l },
-          0 },
-        /* 52 << 200 */
-        { { 0xe6a26d38046dfc72l,0x70409579c2175175l,0x2a575ac5d44e0c1dl,
-            0xb35395e01479ab5al },
-          { 0x1550a5d4f7bfbd8el,0x01daeb680778807bl,0xe0aa940321294dbal,
-            0x84bcdc8c5b5a93b7l },
-          0 },
-        /* 53 << 200 */
-        { { 0x876cc4d2520f04abl,0x6e320f5da85ff6a8l,0x7c504720ce17bc80l,
-            0xe7907079a62089f9l },
-          { 0xa45c4ac7bca45feel,0xd8f3facd5bd54b0cl,0xc0b036277b3e4a24l,
-            0xaabe96dfe4cd4b57l },
-          0 },
-        /* 55 << 200 */
-        { { 0xdc85a54773862ce4l,0x169051a3cc6f5d85l,0x8e3d3be0355f4df7l,
-            0xa139d6fac72bac76l },
-          { 0xddc95d0dfeb0a6f0l,0xd53f70e545cd6955l,0x18eede5e47e54112l,
-            0x4a135dc9cbc6a52el },
-          0 },
-        /* 57 << 200 */
-        { { 0x705a08ba90a58fb4l,0x10eef880fb3f8a64l,0x4ced9ba2f8e585ffl,
-            0xb4f0f955fc6ebef5l },
-          { 0x152c1a338d8b739el,0xb2be701db495bee5l,0xd27141a8d3540a74l,
-            0x20c8a00247f9e9d7l },
-          0 },
-        /* 59 << 200 */
-        { { 0x6d5ae921f5adcb3fl,0xaed1047003a3b610l,0x7c75e36f22256df9l,
-            0xe664b36fb97dae99l },
-          { 0x138b5eca91e746ael,0xb3e01ef5648674a7l,0xa3f256da9e375c74l,
-            0xa00e82bc6a82d6f3l },
-          0 },
-        /* 60 << 200 */
-        { { 0xe7a01eae6e28b4a8l,0xb3bf8224782166c9l,0x0b7ba2a06a244510l,
-            0x9751a69c2abbb4dbl },
-          { 0xb611adc1b3f9fcbcl,0x1d08eb3b436c4675l,0x1c71e98a20f96a64l,
-            0x33d9b58c7ffd3f08l },
-          0 },
-        /* 61 << 200 */
-        { { 0x7c7b03c1affa2d6cl,0x5f189bb9aec6e624l,0xe77a1eedadeff5e7l,
-            0xfc58b90f4280b467l },
-          { 0x561e5d579b71cb4el,0x8ed767aa36d6a17el,0x38d8671e8aa9e188l,
-            0x7bc68f07a95350c0l },
-          0 },
-        /* 63 << 200 */
-        { { 0xe0cd38cf98c01384l,0xc6741123a4226d9fl,0xdd1d42dbf877a0b8l,
-            0xc5986ef0110b3cbal },
-          { 0xeba949f809c8cebel,0x96b47bc4bd39f1dcl,0xbad140b6e07a2a3cl,
-            0x2a8d80999ac5ca8al },
-          0 },
-        /* 64 << 200 */
-        { { 0x39d934abd3c095f1l,0x04b261bee4b76d71l,0x1d2e6970e73e6984l,
-            0x879fb23b5e5fcb11l },
-          { 0x11506c72dfd75490l,0x3a97d08561bcf1c1l,0x43201d82bf5e7007l,
-            0x7f0ac52f798232a7l },
-          0 },
-        /* 65 << 200 */
-        { { 0x8cf27618590ca850l,0x58134f6f44bb94f2l,0x0a147562b78b4eecl,
-            0x2e5986e39f1ed647l },
-          { 0x9becf893348393b0l,0xaea21b92c31c2a86l,0x3d69859e5ff1b9a6l,
-            0x6fcd19f4cd805691l },
-          0 },
-        /* 71 << 200 */
-        { { 0x81619bd4841f43c3l,0x3a3325538e5c61f0l,0x2b68921eda862151l,
-            0x97f5c8a741a491f8l },
-          { 0x8b452094d3b9afa0l,0x93b2b7b4f2124dbcl,0x53285e7d26e0e26dl,
-            0x3f003fc5c8a24edel },
-          0 },
-        /* 77 << 200 */
-        { { 0x4cdabb586c025824l,0x5935ad1586bfcd7dl,0x8ce2c3101b7c5533l,
-            0x761c9fe96cae8808l },
-          { 0x8a0723f5d9e66d70l,0xb640b323dcced11dl,0x5768528051ae548cl,
-            0x83576f75d53f3f2cl },
-          0 },
-        /* 83 << 200 */
-        { { 0xc715edc47b532ec3l,0x159765e6c4a6e14bl,0x4a74f15228cd2d45l,
-            0xbfd309edae8c753bl },
-          { 0xf56bb5315d6d5245l,0x2c89c21833b30a55l,0xe436141acd4ed5fal,
-            0x7eb7a5c707868ee6l },
-          0 },
-        /* 89 << 200 */
-        { { 0x9a3ad3ffb0c7c48cl,0x25e8d977738e3638l,0xbb6c6c9d1c024074l,
-            0xeda1ac0f8cfdf416l },
-          { 0x93059ba538de49e2l,0xdb199cfc1b9ce741l,0x49b05e9446f3b494l,
-            0x717cafc606480902l },
-          0 },
-        /* 95 << 200 */
-        { { 0x8d27421052885708l,0x9d2297fd74e5b9b5l,0xe7cb6a68dc4d7318l,
-            0x0b60b0d276357b31l },
-          { 0x57301994532c2095l,0xfbae2ba203373452l,0xe8020b20ba700583l,
-            0x1ca7772c2988919cl },
-          0 },
-        /* 101 << 200 */
-        { { 0x723296eb918f3eecl,0x358c9ff0b79901c6l,0x64a1934c8d5e814cl,
-            0x7e5a9afced165177l },
-          { 0xd783840168733e7al,0xfcf3c0b6f61ede6dl,0x94ec0bf08434e804l,
-            0xa5a70153c192c1cdl },
-          0 },
-        /* 107 << 200 */
-        { { 0x03cdf976c23e49d4l,0x51e5cfa5a2ae72d5l,0x7716faa3100f7a51l,
-            0xc53153a2c14dc015l },
-          { 0xe7c69b052b47ec18l,0xff4756907ea93b01l,0x55fde3c540a2f205l,
-            0x0263d0b12f85aed6l },
-          0 },
-        /* 113 << 200 */
-        { { 0x668c56619686fe30l,0x382a8ccd8f73a476l,0xda012cbfb40a85e7l,
-            0x55ea1e72e9e88b91l },
-          { 0x8312556088cc5afcl,0x44ae54cbc45b19c7l,0xc91fffa8f86a02cdl,
-            0xc79f573752d7e89bl },
-          0 },
-        /* 116 << 200 */
-        { { 0x652b50523e357579l,0x08ce7d3a2afe5746l,0x9dc1cca6f71a12efl,
-            0x80a221c24f6c4196l },
-          { 0xdde40eff0f49f508l,0x7995bb46913b0dc3l,0x4adbdeb385e44f6el,
-            0x6816bb3ab222e4bbl },
-          0 },
-        /* 119 << 200 */
-        { { 0xce1ee518579a1a4dl,0x5d86e8912bc3870al,0x230878d18da907c4l,
-            0xc648392777ae7ea8l },
-          { 0x64319653016c0ad7l,0x7cbfa0b0b71f20dal,0xbf087dc3395ed4d8l,
-            0x59512add307d218dl },
-          0 },
-        /* 125 << 200 */
-        { { 0x7378a969d8ae335el,0x11c69965506d3a42l,0x212539769949468al,
-            0x570cf87e64995050l },
-          { 0xf300ad2e30b94e22l,0xbc159cf8f36dad32l,0xdff3b3767ca8aa6al,
-            0xa5de93b5627fb9e7l },
-          0 },
-    },
-    {
-        /* 0 << 208 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 208 */
-        { { 0x75d9bc15adf7cccfl,0x81a3e5d6dfa1e1b0l,0x8c39e444249bc17el,
-            0xf37dccb28ea7fd43l },
-          { 0xda654873907fba12l,0x35daa6da4a372904l,0x0564cfc66283a6c5l,
-            0xd09fa4f64a9395bfl },
-          0 },
-        /* 3 << 208 */
-        { { 0xc51aa29e5cfe5c48l,0x82c020ae815ee096l,0x7848ad827549a68al,
-            0x7933d48960471355l },
-          { 0x04998d2e67c51e57l,0x0f64020ad9944afcl,0x7a299fe1a7fadac6l,
-            0x40c73ff45aefe92cl },
-          0 },
-        /* 4 << 208 */
-        { { 0xe5f649be9d8e68fdl,0xdb0f05331b044320l,0xf6fde9b3e0c33398l,
-            0x92f4209b66c8cfael },
-          { 0xe9d1afcc1a739d4bl,0x09aea75fa28ab8del,0x14375fb5eac6f1d0l,
-            0x6420b560708f7aa5l },
-          0 },
-        /* 5 << 208 */
-        { { 0xbf44ffc75488771al,0xcb76e3f17f2f2191l,0x4197bde394f86a42l,
-            0x45c25bb970641d9al },
-          { 0xd8a29e31f88ce6dcl,0xbe2becfd4bb7ac7dl,0x13094214b5670cc7l,
-            0xe90a8fd560af8433l },
-          0 },
-        /* 7 << 208 */
-        { { 0x0ecf9b8b4ebd3f02l,0xa47acd9d86b770eal,0x93b84a6a2da213cel,
-            0xd760871b53e7c8cfl },
-          { 0x7a5f58e536e530d7l,0x7abc52a51912ad51l,0x7ad43db02ea0252al,
-            0x498b00ecc176b742l },
-          0 },
-        /* 9 << 208 */
-        { { 0x9ff713ef888ae17fl,0x6007f68fb34b7bebl,0x5d2b18983b653d64l,
-            0xcbf73e91d3ca4b1bl },
-          { 0x4b050ad56cdfb3a1l,0x41bd3ec3d1f833a4l,0x78d7e2ee719d7bf5l,
-            0xea4604672a27412el },
-          0 },
-        /* 10 << 208 */
-        { { 0x7dad6d1b42cd7900l,0xb6e6b439e058f8a4l,0x8836f1e662aa3bbcl,
-            0xd45bf2c811142b0al },
-          { 0xae324bac3c045ed1l,0x372be24d270a8333l,0xeeda7a3a6b7c73b6l,
-            0xf6675402db49562al },
-          0 },
-        /* 11 << 208 */
-        { { 0xc312ba68441e760dl,0x84d0d061a50e512el,0xfe764f4e4bbdd849l,
-            0xa924adcf9dadd5c0l },
-          { 0x08685961debfe976l,0xd3d846c529fba601l,0x43bf8227dc3f4040l,
-            0x05e767b8a49e9ff5l },
-          0 },
-        /* 13 << 208 */
-        { { 0xc4689c309953e453l,0x5e355a2e1712dca5l,0x1ff83c81f1cd96f7l,
-            0xb06b89fb44cf56dbl },
-          { 0x1827705365f16e0dl,0x6403b91de5618672l,0xba3f9475be384bc6l,
-            0x7f691cbe303ce5f3l },
-          0 },
-        /* 15 << 208 */
-        { { 0x4589ba03210f4045l,0xd5e7366301e8012al,0x1c26052d74462ffal,
-            0xe78f600c4f989519l },
-          { 0xc63ca0c97cee0b2fl,0xbe588573af760b5fl,0x05906fc4593773cdl,
-            0xd5970fb0e322d5afl },
-          0 },
-        /* 16 << 208 */
-        { { 0x103c46e60ebcf726l,0x4482b8316231470el,0x6f6dfaca487c2109l,
-            0x2e0ace9762e666efl },
-          { 0x3246a9d31f8d1f42l,0x1b1e83f1574944d2l,0x13dfa63aa57f334bl,
-            0x0cf8daed9f025d81l },
-          0 },
-        /* 17 << 208 */
-        { { 0xf67c098aae0690aal,0x1a4656422b7bc62bl,0xaffc6b917220dea2l,
-            0xd97ac543d2552deel },
-          { 0x1f84514a7e816b8el,0xe9887e81a8f38552l,0x2e6358e6847ad46bl,
-            0x1f67871e6bc9895el },
-          0 },
-        /* 19 << 208 */
-        { { 0x2462b6e0d47f43fal,0x71db3610d8a245e5l,0x0c26b0e734208974l,
-            0x0cd6d49d2029bd2el },
-          { 0xf207c9f6091922b8l,0x0c476c5c7f0fbf66l,0x6de7efb2295d6da8l,
-            0xea054ee10ced6cfel },
-          0 },
-        /* 21 << 208 */
-        { { 0xd21496e3e9bd795cl,0xf293f617c6a557del,0x9d041b7239a45642l,
-            0xe8353dab4ac87f80l },
-          { 0x21e9f35620d8d019l,0x1f4adca9d2fb2668l,0xe5f68227dfecd64al,
-            0x10d71b79d7f09ec0l },
-          0 },
-        /* 23 << 208 */
-        { { 0xca3f068999f87118l,0x99a933911b2417f0l,0xa383481a3d1f70e5l,
-            0x7a31a6c833b14414l },
-          { 0x9d60f4368b2a9931l,0xd4c97ded80588534l,0x7cb29e82ab6a8bdal,
-            0x3799bdad97b4c45al },
-          0 },
-        /* 25 << 208 */
-        { { 0x51da0ff629011af3l,0xcbb03c809a4f0855l,0xea3536725555b10bl,
-            0x4bf94e025c7da97el },
-          { 0x384352f5ff713300l,0xb2c2b675192d41e6l,0x4ff66861625ca046l,
-            0xf0f5e472013dddc4l },
-          0 },
-        /* 27 << 208 */
-        { { 0x38c44cdc59987914l,0xad7f2829757fb853l,0x9aabf1c8688e3342l,
-            0xbe0f1e4ef534c850l },
-          { 0x732cac652ec24ecal,0x9328b657933bb5e4l,0xe2747ff60bb31033l,
-            0xdbaab72cfcdc36acl },
-          0 },
-        /* 28 << 208 */
-        { { 0x0e5e3049a639fc6bl,0xe75c35d986003625l,0x0cf35bd85dcc1646l,
-            0x8bcaced26c26273al },
-          { 0xe22ecf1db5536742l,0x013dd8971a9e068bl,0x17f411cb8a7909c5l,
-            0x5757ac98861dd506l },
-          0 },
-        /* 29 << 208 */
-        { { 0xaf410d5aac66a3e8l,0x39fcbffb2031f658l,0xd29e58c947ce11fbl,
-            0x7f0b874965f73e49l },
-          { 0xedc30f4b27fea6c6l,0xe03b9103d2baa340l,0xa7bb3f17ae680612l,
-            0xe06656a8197af6f0l },
-          0 },
-        /* 31 << 208 */
-        { { 0x84562095bff86165l,0x994194e916bc7589l,0xb1320c7ec14c6710l,
-            0x508a8d7f766e978fl },
-          { 0xd04adc9ec7e1f6fel,0x7bafaff68398cecfl,0x906df2fccef3b934l,
-            0xc65afe18f3008c38l },
-          0 },
-        /* 33 << 208 */
-        { { 0x477ffeeeab983130l,0x5426363a96e83d55l,0xcf0370a15204af42l,
-            0x99834414b5a6ea8fl },
-          { 0xf475ba711ab4ee8al,0x8486da5d0102d8f2l,0x55082e713839c821l,
-            0xa57e58395b65defal },
-          0 },
-        /* 34 << 208 */
-        { { 0x34b2185bbbb33a76l,0x189038b7d48158c2l,0xfa32eb90e9e90217l,
-            0x79271771730e74dfl },
-          { 0x315ed8c2a5d01ffdl,0x9799dae723e6a95el,0x40070aa016f5715al,
-            0x40e6c0ca5ea51f8cl },
-          0 },
-        /* 35 << 208 */
-        { { 0x099c0570d8132163l,0xcd5508a3023dbbf3l,0x18162ff526bfe6a6l,
-            0xf39e071144bbb455l },
-          { 0x49664996eaa3cf96l,0x1c6442d5e2649be9l,0x6199f740c01d269dl,
-            0x4be605ee37542c11l },
-          0 },
-        /* 36 << 208 */
-        { { 0xc7313e9cf36658f0l,0xc433ef1c71f8057el,0x853262461b6a835al,
-            0xc8f053987c86394cl },
-          { 0xff398cdfe983c4a1l,0xbf5e816203b7b931l,0x93193c46b7b9045bl,
-            0x1e4ebf5da4a6e46bl },
-          0 },
-        /* 37 << 208 */
-        { { 0xd032fbfd0dbf82b4l,0x707181f668e58969l,0xef434381e7be2d5el,
-            0x290669176f2c64ddl },
-          { 0xf66cffc3772769abl,0x68d8a76a17aad01cl,0xdd3991c590f6e078l,
-            0xdb74db06ea4ac7dcl },
-          0 },
-        /* 39 << 208 */
-        { { 0x9f34a7c11c78be71l,0x7bf2f2d149ca6987l,0xb528a514dcd34afcl,
-            0x4dddb3f1183a68b1l },
-          { 0x54d2626660b83883l,0x9073e4e0e0cd8dadl,0xbd2b837d9eb818b2l,
-            0x5fa5f9086ae2e32dl },
-          0 },
-        /* 40 << 208 */
-        { { 0xf9942a6043a24fe7l,0x29c1191effb3492bl,0x9f662449902fde05l,
-            0xc792a7ac6713c32dl },
-          { 0x2fd88ad8b737982cl,0x7e3a0319a21e60e3l,0x09b0de447383591al,
-            0x6df141ee8310a456l },
-          0 },
-        /* 41 << 208 */
-        { { 0xcd02ba1e0df98a64l,0x301b6bfa03f5676el,0x41e1a8d4a2fe4090l,
-            0x489c1cbf47f0e1dcl },
-          { 0x4171a98c20760847l,0xdcb21cee77af4796l,0x5fb0f0c9d0b7e981l,
-            0x4c2791dff33b9f8dl },
-          0 },
-        /* 43 << 208 */
-        { { 0x95d7ec0c50420a50l,0x5794665c2a6756d5l,0x73558c6e9101e7f5l,
-            0xa3fa0f8c1642af0el },
-          { 0xa11b309b4ee43551l,0x3939de30cb8fc712l,0x9710f2320fde8921l,
-            0x2a4db2d5cae8b41cl },
-          0 },
-        /* 44 << 208 */
-        { { 0xaec1a039e6d6f471l,0x14b2ba0f1198d12el,0xebc1a1603aeee5acl,
-            0x401f4836e0b964cel },
-          { 0x2ee437964fd03f66l,0x3fdb4e49dd8f3f12l,0x6ef267f629380f18l,
-            0x3e8e96708da64d16l },
-          0 },
-        /* 45 << 208 */
-        { { 0xdf6cdac0bc4c78adl,0xbe9e32182e97376el,0xa37f9d8b1a139274l,
-            0x7640c3982807128el },
-          { 0xe9735166c05b5f85l,0xbccd3675100e5716l,0x51376a293e5c9682l,
-            0x95efe088848f6aeal },
-          0 },
-        /* 46 << 208 */
-        { { 0xfac2d7dd23d14105l,0xdda17149a9136f52l,0xb9f3a9c672d1a99bl,
-            0x2fcf532a142c3b20l },
-          { 0xc2731f1e61190c1bl,0x26dbe810a76509e4l,0xc96cc431908bb92fl,
-            0x5661a84d80e3e694l },
-          0 },
-        /* 47 << 208 */
-        { { 0x5194d144150ba121l,0x8de57c48b6b11561l,0x803228da96c156d9l,
-            0x2112e4250a8f6376l },
-          { 0x15436294643449ffl,0xfc3880add4118cd0l,0x16ed90731e3f7413l,
-            0xa400699901d38d6dl },
-          0 },
-        /* 48 << 208 */
-        { { 0xbc19180c207674f1l,0x112e09a733ae8fdbl,0x996675546aaeb71el,
-            0x79432af1e101b1c7l },
-          { 0xd5eb558fde2ddec6l,0x81392d1f5357753fl,0xa7a76b973ae1158al,
-            0x416fbbff4a899991l },
-          0 },
-        /* 49 << 208 */
-        { { 0xf84c9147c52d7384l,0x86391accec01efa6l,0xffd68616f9c6f3f4l,
-            0xc7536461b17c2de6l },
-          { 0xa81f4ba10121abdfl,0xa068a2e26f6eae27l,0xe0ee90350eb159f0l,
-            0x4c48f761fd8c4b9cl },
-          0 },
-        /* 51 << 208 */
-        { { 0x4b6d71e87790000cl,0xced195744ce9293el,0xc25626a3747585e8l,
-            0xb8307d22d7044270l },
-          { 0xf08e7ef6117c24cbl,0xae6403162f660d04l,0xbc3ffdcff224a2fdl,
-            0x1ebc0328d0586c7el },
-          0 },
-        /* 52 << 208 */
-        { { 0x9e65fdfd0d4a9dcfl,0x7bc29e48944ddf12l,0xbc1a92d93c856866l,
-            0x273c69056e98dfe2l },
-          { 0x69fce418cdfaa6b8l,0x606bd8235061c69fl,0x42d495a06af75e27l,
-            0x8ed3d5056d873a1fl },
-          0 },
-        /* 53 << 208 */
-        { { 0x46b160e5a6022278l,0x86b1d50cc30a51fcl,0xe898ac0e684b81b7l,
-            0x04d591e277b93597l },
-          { 0xd20cac347626e18al,0xb49c941f0a968733l,0x054e6e7e21631627l,
-            0xd6d33db9d4c716b1l },
-          0 },
-        /* 55 << 208 */
-        { { 0xaa79ab4bf91e9b75l,0x7df3235bd34d961dl,0x9f3954e6534a40e1l,
-            0x80f88d2c790b4456l },
-          { 0x98f7711b21e9fb2al,0x0a04c318877d27e6l,0x499b7c2412338848l,
-            0x0b1dbe9ccd5e7ec3l },
-          0 },
-        /* 57 << 208 */
-        { { 0xb430ff44e04715ffl,0x671358d565d076d0l,0x3946d38f22c3aa06l,
-            0x80919ea363b2d627l },
-          { 0x14ffa219e8790922l,0xfe1d895ae8d89c48l,0x717e9e51748e806el,
-            0xb91e1ddf550d711dl },
-          0 },
-        /* 59 << 208 */
-        { { 0x8aac26225f540127l,0x57cd5d7cba25f742l,0x87006a6b1df7a0fcl,
-            0x88e9ab863ecbf26cl },
-          { 0xe1b8155f9143b314l,0xc00196130b679bddl,0x819e7b61a1871d07l,
-            0xc36e7892cc2c9cc9l },
-          0 },
-        /* 60 << 208 */
-        { { 0x4b03c55b8e33787fl,0xef42f975a6384673l,0xff7304f75051b9f0l,
-            0x18aca1dc741c87c2l },
-          { 0x56f120a72d4bfe80l,0xfd823b3d053e732cl,0x11bccfe47537ca16l,
-            0xdf6c9c741b5a996bl },
-          0 },
-        /* 61 << 208 */
-        { { 0x65729b05301ee370l,0x3ed09a2a24c2824cl,0x781ef66a33481977l,
-            0xf2ccdeec193506d0l },
-          { 0x92b4f70d703422d6l,0x7f004a43f80a1b99l,0x47db23607a856445l,
-            0x783a8dd1ce5b0622l },
-          0 },
-        /* 63 << 208 */
-        { { 0x7febefd34e9aac5al,0x601c89e2bdd6173el,0x79b08930c257431el,
-            0x915d601d399ee099l },
-          { 0xfa48347eca02acd2l,0xc33249baeeb7ccedl,0xd76e408755704722l,
-            0xd3709c600dcf4878l },
-          0 },
-        /* 64 << 208 */
-        { { 0xee7332c7904fc3fal,0x14a23f45c7e3636al,0xc38659c3f091d9aal,
-            0x4a995e5db12d8540l },
-          { 0x20a53becf3a5598al,0x56534b17b1eaa995l,0x9ed3dca4bf04e03cl,
-            0x716c563ad8d56268l },
-          0 },
-        /* 65 << 208 */
-        { { 0x963353201580f3adl,0x6c495304b0cd50d4l,0xd035cdc7555ff981l,
-            0xe65cd063c6b6bdfbl },
-          { 0x7deb3cbb437e749cl,0xa9de9f3db5dc24a1l,0xe2e76a2b35c29ffal,
-            0x4d35e261323ba650l },
-          0 },
-        /* 71 << 208 */
-        { { 0x52c46fc8c89e2766l,0x7330b02bb945e5f2l,0xc77ef75c2673ebbcl,
-            0x1740e72657c33783l },
-          { 0xf0312d29623565fbl,0xff9f707af0ca1ed9l,0xb98609ca5ea51a4al,
-            0xde86b9a87b5cc91fl },
-          0 },
-        /* 77 << 208 */
-        { { 0x0dece4badca158b7l,0x5e39baf6a3e9f837l,0xcf14e6dc4d57b640l,
-            0x0548aaa4b67bcbe7l },
-          { 0xb6cf5b393c90e434l,0xf8b3c5645006f3abl,0xa74e92859bf04bd9l,
-            0xf59a3a6bf99c8977l },
-          0 },
-        /* 83 << 208 */
-        { { 0x652ca66ac5b072d5l,0x2102b55993ad4928l,0x1b5f192d88210f9bl,
-            0xb18710144c6ad7e5l },
-          { 0x3979fde3bc0abf13l,0xb5cb4c7dac3fd631l,0x4aedffa6c200ec7bl,
-            0x8aed81ceaddf3610l },
-          0 },
-        /* 89 << 208 */
-        { { 0x72b48105abeefbael,0x0e9e6e41827bb22bl,0xf45ada151e52a848l,
-            0xb8e94579534867a2l },
-          { 0x3a08773b7adb0fdcl,0xe7133a28b83316dfl,0xc8b7b08c5bb41470l,
-            0x28719eb4aaf140c7l },
-          0 },
-        /* 95 << 208 */
-        { { 0x398996cd430007cel,0x20d8c0e07642d616l,0x81566639a7eb2397l,
-            0x74aa0b692e133732l },
-          { 0x326745907ba80aa7l,0x56a491c39bd69d64l,0xc8c8b040e54dcce0l,
-            0x3f991872d571d037l },
-          0 },
-        /* 101 << 208 */
-        { { 0x70e681fa4fb595c9l,0xf0635d6386b4d97bl,0xfc029284c1347081l,
-            0x5a4e9cbe4fee0303l },
-          { 0xd43da8609c31094fl,0x0412cfed6515b4aal,0x10fc06da8d53be86l,
-            0x4b7b380b4bccc94dl },
-          0 },
-        /* 107 << 208 */
-        { { 0x560d57408e7d6738l,0xa82268a8937f12a2l,0x87787b2d3d95b463l,
-            0xb36539b2030e23bfl },
-          { 0x60d16b8fd61e761dl,0x96ba2949fe8efccdl,0x8c170eda667fa7ebl,
-            0xc880d74cf800d7c3l },
-          0 },
-        /* 113 << 208 */
-        { { 0x7c05d6c1efcbfea0l,0xae7ba3291a2f6dd8l,0x521598ed5bd42ecfl,
-            0x58e07842ef0ab40cl },
-          { 0xae65105f66c752a5l,0x4910fba45f99d499l,0xbfdaf5fce9e44357l,
-            0x6aaf4053796ee5b6l },
-          0 },
-        /* 116 << 208 */
-        { { 0xf58fecb16f640f62l,0xe274b92b39f51946l,0x7f4dfc046288af44l,
-            0x0a91f32aeac329e5l },
-          { 0x43ad274bd6aaba31l,0x719a16400f6884f9l,0x685d29f6daf91e20l,
-            0x5ec1cc3327e49d52l },
-          0 },
-        /* 119 << 208 */
-        { { 0x615ac02527ba93edl,0x0d43915d3556ef47l,0x8c739fd1cb0cda89l,
-            0xa2318169625f7a16l },
-          { 0x17d486113e0479cel,0x814beb6038ee541el,0x09c9807fb98ef355l,
-            0x4ad3668752d07af6l },
-          0 },
-        /* 125 << 208 */
-        { { 0x5c1f42e444f3f568l,0xd743b7c078fb409bl,0xe09edccb6224362cl,
-            0x7f13d140c5fe872cl },
-          { 0x85e8cb88f403c0ebl,0x918a231b688d20a0l,0xc65b7ab9f246c73fl,
-            0xda743fbf76dbd6adl },
-          0 },
-    },
-    {
-        /* 0 << 216 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 216 */
-        { { 0xa0158eeae457a477l,0xd19857dbee6ddc05l,0xb326522418c41671l,
-            0x3ffdfc7e3c2c0d58l },
-          { 0x3a3a525426ee7cdal,0x341b0869df02c3a8l,0xa023bf42723bbfc8l,
-            0x3d15002a14452691l },
-          0 },
-        /* 3 << 216 */
-        { { 0xf3cae7e9262a3539l,0x78a49d1d6670d59el,0x37de0f63c1c5e1b9l,
-            0x3072c30c69cb7c1cl },
-          { 0x1d278a5277c850e6l,0x84f15f8f1f6a3de6l,0x46a8bb45592ca7adl,
-            0x1912e3eee4d424b8l },
-          0 },
-        /* 4 << 216 */
-        { { 0x6ba7a92079e5fb67l,0xe1331feb70aa725el,0x5080ccf57df5d837l,
-            0xe4cae01d7ff72e21l },
-          { 0xd9243ee60412a77dl,0x06ff7cacdf449025l,0xbe75f7cd23ef5a31l,
-            0xbc9578220ddef7a8l },
-          0 },
-        /* 5 << 216 */
-        { { 0xdc988086365e668bl,0xada8dcdaaabda5fbl,0xbc146b4c255f1fbel,
-            0x9cfcde29cf34cfc3l },
-          { 0xacbb453e7e85d1e4l,0x9ca09679f92358b5l,0x15fc2d96240823ffl,
-            0x8d65adf70c11d11el },
-          0 },
-        /* 7 << 216 */
-        { { 0x775557f10296f4fdl,0x1dca76a3ea51b436l,0xf3e98f60fb950805l,
-            0x31ff32ea831cf7f1l },
-          { 0x643e7bf18d2c714bl,0x64b5c3392e9d2acal,0xa9fd9ccc6adc2d23l,
-            0xfc2397eccc721b9bl },
-          0 },
-        /* 9 << 216 */
-        { { 0xf031182db48ec57dl,0x515d32f804b233b9l,0x06bbb1d4093aad26l,
-            0x88a142fe0d83d1ecl },
-          { 0x3b95c099245c73f8l,0xb126d4af52edcd32l,0xf8022c1e8fcb52e6l,
-            0x5a51ac4c0106d339l },
-          0 },
-        /* 10 << 216 */
-        { { 0xc589e1ce44ace150l,0xe0f8d3d94381e97cl,0x59e99b1162c5a4b8l,
-            0x90d262f7fd0ec9f9l },
-          { 0xfbc854c9283e13c9l,0x2d04fde7aedc7085l,0x057d776547dcbecbl,
-            0x8dbdf5919a76fa5fl },
-          0 },
-        /* 11 << 216 */
-        { { 0xb7f70a1a7c64a054l,0x0dc1c0df9db43e79l,0x6d0a4ae251fe63d6l,
-            0xe0d5e3327f0c8abfl },
-          { 0xff5500362b7ecee8l,0x3ea0e6f75d055008l,0x30deb62ff24ac84fl,
-            0x936969fd5d7116b7l },
-          0 },
-        /* 13 << 216 */
-        { { 0x02da76122617cf7fl,0xd6e25d4eeee35260l,0xb2fa5b0afd3533e9l,
-            0xe76bb7b0b9126f88l },
-          { 0x692e6a9988856866l,0x3fdf394f49db65cal,0x2529699122d8d606l,
-            0xe815bfbf3dd7c4cfl },
-          0 },
-        /* 15 << 216 */
-        { { 0x69c984ed4d844e7fl,0xd354b2174a2e8a82l,0x25bd4addfb2c4136l,
-            0xf72df4de144b26e1l },
-          { 0xd0aa9db0e6101afdl,0x4445efaae49bd1b8l,0x5dc54eee331593b2l,
-            0xfa35e3b9094bf10bl },
-          0 },
-        /* 16 << 216 */
-        { { 0xdb567d6ac42bd6d2l,0x6df86468bb1f96ael,0x0efe5b1a4843b28el,
-            0x961bbb056379b240l },
-          { 0xb6caf5f070a6a26bl,0x70686c0d328e6e39l,0x80da06cf895fc8d3l,
-            0x804d8810b363fdc9l },
-          0 },
-        /* 17 << 216 */
-        { { 0x660a0f893ea089c3l,0xa25823aac9009b09l,0xb2262d7ba681f5e5l,
-            0x4fc30c8c3413863al },
-          { 0x691544b7c32059f7l,0xf65cf276b21c6134l,0xe3a96b2a5104dabal,
-            0xbb08d109a43ee42fl },
-          0 },
-        /* 19 << 216 */
-        { { 0x85a52d69f9916861l,0x595469a4da4fa813l,0x1dd7786e3338502fl,
-            0x34b8ef2853963ac5l },
-          { 0xc0f019f81a891b25l,0xb619970c4f4bd775l,0x8c2a5af3be19f681l,
-            0x9463db0498ec1728l },
-          0 },
-        /* 21 << 216 */
-        { { 0xeb62c27801f39eabl,0x27de39340ab3a4aal,0xfbd17520a982ca8dl,
-            0x58817ec2e4bdc6edl },
-          { 0x312d78de31c6ac13l,0x9483bf7609202ea6l,0xf64ab8b622c6d8e1l,
-            0xdddf589ce580de74l },
-          0 },
-        /* 23 << 216 */
-        { { 0xe0fa3336ee98a92al,0x7d80eeef66a4d745l,0xb612531bba0119d3l,
-            0x86e770c1b351fe15l },
-          { 0xafbad6f882d5a397l,0x1e5f1cb80dbf0110l,0x25138ac09f79063dl,
-            0x089ed22f2746a156l },
-          0 },
-        /* 25 << 216 */
-        { { 0x198d1b5d7d8b8ddel,0xf32c11078dab37fbl,0xf15fcb6d42b93874l,
-            0x91ddb74f41f94f84l },
-          { 0x6a64540a271524b2l,0x950a0c12758b5a64l,0xf9f237933dce9580l,
-            0xc8edd0ab2cf8ce32l },
-          0 },
-        /* 27 << 216 */
-        { { 0xefc6357eae1046b7l,0xe6704929612932e4l,0xa20305d4b1355b17l,
-            0x88a9136a58b4a156l },
-          { 0xbc379985b4d275ecl,0x718b91316eaf338bl,0x61229a7ad152a509l,
-            0x1109f7c445157ae9l },
-          0 },
-        /* 28 << 216 */
-        { { 0xcf197ca7fb8088fal,0x014272474ddc96c5l,0xa2d2550a30777176l,
-            0x534698984d0cf71dl },
-          { 0x6ce937b83a2aaac6l,0xe9f91dc35af38d9bl,0x2598ad83c8bf2899l,
-            0x8e706ac9b5536c16l },
-          0 },
-        /* 29 << 216 */
-        { { 0x2bde42140df85c2cl,0x4fb839f4058a7a63l,0x7c10572a47f51231l,
-            0x878826231989824el },
-          { 0xa8293d2016e1564al,0xcb11c0f818c04576l,0x83b91e7d9740c631l,
-            0xbdcb23d0cbffcea0l },
-          0 },
-        /* 31 << 216 */
-        { { 0x64bdfd2a9094bfc8l,0x8558acc60fc54d1el,0x3992848faf27721el,
-            0x7a8fcbdaa14cd009l },
-          { 0x6de6120900a4b9c2l,0xbd192b1b20cf8f28l,0x2356b90168d9be83l,
-            0xce1e7a944a49a48al },
-          0 },
-        /* 33 << 216 */
-        { { 0x7630103b6ac189b9l,0x15d35edc6f1f5549l,0x9051799d31cb58edl,
-            0xb4f32694a7a8579el },
-          { 0x6f037435f2abe306l,0xf0595696410fb2f7l,0x2a0d347a5cc98f59l,
-            0x9c19a9a87e3bbd69l },
-          0 },
-        /* 34 << 216 */
-        { { 0x87f8df7c0e58d493l,0xb1ae5ed058b73f12l,0xc368f784dea0c34dl,
-            0x9bd0a120859a91a0l },
-          { 0xb00d88b7cc863c68l,0x3a1cc11e3d1f4d65l,0xea38e0e70aa85593l,
-            0x37f13e987dc4aee8l },
-          0 },
-        /* 35 << 216 */
-        { { 0x91dbe00e49430cd2l,0xcc67c0b17aa8ef6bl,0x769985b8a273f1a5l,
-            0x358371dc360e5dafl },
-          { 0xbf9b9127d6d8b5e8l,0x748ae12cb45588c1l,0x9c609eb556076c58l,
-            0xf287489109733e89l },
-          0 },
-        /* 36 << 216 */
-        { { 0x10d38667bc947badl,0x738e07ce2a36ee2el,0xc93470cdc577fcacl,
-            0xdee1b6162782470dl },
-          { 0x36a25e672e793d12l,0xd6aa6caee0f186dal,0x474d0fd980e07af7l,
-            0xf7cdc47dba8a5cd4l },
-          0 },
-        /* 37 << 216 */
-        { { 0xceb6aa80f8a08fddl,0xd98fc56f46fead7bl,0xe26bd3f8b07b3f1fl,
-            0x3547e9b99d361c3el },
-          { 0x1a89f802e94b8eccl,0x2210a590c0a40ef2l,0xe7e5b965afc01bf2l,
-            0xca3d57fe234b936bl },
-          0 },
-        /* 39 << 216 */
-        { { 0x9230a70db9f9e8cdl,0xa63cebfcb81ba2ecl,0x8482ca87a8f664d6l,
-            0xa8ae78e00b137064l },
-          { 0xb787bd558384c687l,0xfde1d1bdb29ae830l,0xc4a9b2e39f0b7535l,
-            0x7e6c9a15efde2d01l },
-          0 },
-        /* 40 << 216 */
-        { { 0x7d2e5c054f7269b1l,0xfcf30777e287c385l,0x10edc84ff2a46f21l,
-            0x354417574f43fa36l },
-          { 0xf1327899fd703431l,0xa438d7a616dd587al,0x65c34c57e9c8352dl,
-            0xa728edab5cc5a24el },
-          0 },
-        /* 41 << 216 */
-        { { 0xcd6e6db872896d4fl,0x324afa99896c4640l,0x37d18c3d33a292bdl,
-            0x98dba3b44143421fl },
-          { 0x2406f3c949c61b84l,0x402d974754899588l,0xc73b7fd634a485e5l,
-            0x75c9bae08587f0c3l },
-          0 },
-        /* 43 << 216 */
-        { { 0x6c32fa8cb0b4a04dl,0xeb58d0d875fda587l,0x61d8a157c4b86563l,
-            0x92191bf01006b8afl },
-          { 0xd04d3eff32d3478bl,0x3cc52eab2a684fc8l,0xb19a0f1625de54ccl,
-            0x5c5295973620db2dl },
-          0 },
-        /* 44 << 216 */
-        { { 0xa97b51265c3427b0l,0x6401405cd282c9bdl,0x3629f8d7222c5c45l,
-            0xb1c02c16e8d50aedl },
-          { 0xbea2ed75d9635bc9l,0x226790c76e24552fl,0x3c33f2a365f1d066l,
-            0x2a43463e6dfccc2el },
-          0 },
-        /* 45 << 216 */
-        { { 0x09b2e0d3b8da1e01l,0xa3a1a8fee9c0eb04l,0x59af5afe8bf653bal,
-            0xba979f8bd0a54836l },
-          { 0xa0d8194b51ee6ffbl,0x451c29e2f4b0586cl,0x7eb5fddb7471ee3dl,
-            0x84b627d4bcb3afd8l },
-          0 },
-        /* 46 << 216 */
-        { { 0x8cc3453adb483761l,0xe7cc608565d5672bl,0x277ed6cbde3efc87l,
-            0x19f2f36869234eafl },
-          { 0x9aaf43175c0b800bl,0x1f1e7c898b6da6e2l,0x6cfb4715b94ec75el,
-            0xd590dd5f453118c2l },
-          0 },
-        /* 47 << 216 */
-        { { 0xa70e9b0afb54e812l,0x092a0d7d8d86819bl,0x5421ff042e669090l,
-            0x8af770c6b133c952l },
-          { 0xc8e8dd596c8b1426l,0x1c92eb0e9523b483l,0x5a7c88f2cf3d40edl,
-            0x4cc0c04bf5dd98f8l },
-          0 },
-        /* 48 << 216 */
-        { { 0x14e49da11f17a34cl,0x5420ab39235a1456l,0xb76372412f50363bl,
-            0x7b15d623c3fabb6el },
-          { 0xa0ef40b1e274e49cl,0x5cf5074496b1860al,0xd6583fbf66afe5a4l,
-            0x44240510f47e3e9al },
-          0 },
-        /* 49 << 216 */
-        { { 0xb3939a8ffd617288l,0x3d37e5c2d68c2636l,0x4a595fac9d666c0el,
-            0xfebcad9edb3a4978l },
-          { 0x6d284a49c125016fl,0x05a7b9c80ee246a2l,0xe8b351739436c6e9l,
-            0xffb89032d4be40b7l },
-          0 },
-        /* 51 << 216 */
-        { { 0xba1387a5436ebf33l,0xc351a400e8d05267l,0x18645dde4259dbe8l,
-            0x5fc32895c10fd676l },
-          { 0x1ef7a944807f040el,0x9486b5c625738e5fl,0xc9e56cf4a7e3e96cl,
-            0x34c7dc87a20be832l },
-          0 },
-        /* 52 << 216 */
-        { { 0xe10d49996fe8393fl,0x0f809a3fe91f3a32l,0x61096d1c802f63c8l,
-            0x289e146257750d3dl },
-          { 0xed06167e9889feeal,0xd5c9c0e2e0993909l,0x46fca0d856508ac6l,
-            0x918260474f1b8e83l },
-          0 },
-        /* 53 << 216 */
-        { { 0x1d5f2ad7a9bf79cbl,0x228fb24fca9c2f98l,0x5f7c3883701c4b71l,
-            0x18cf76c4ec42d686l },
-          { 0x3680d2e94dcdec8dl,0x6d58e87ba0d60cb6l,0x72fbf086a0e513cfl,
-            0xb922d3c5346ed99al },
-          0 },
-        /* 55 << 216 */
-        { { 0x1678d658c2b9b874l,0x0e0b2c47f6360d4dl,0x01a45c02a0c9b9acl,
-            0x05e82e9d0da69afbl },
-          { 0x50be4001f28b8018l,0x503d967b667d8241l,0x6cd816534981da04l,
-            0x9b18c3117f09c35fl },
-          0 },
-        /* 57 << 216 */
-        { { 0xdfdfd5b409d22331l,0xf445126817f0c6a2l,0xe51d1aa8a5cde27bl,
-            0xb61a12a37aaf9513l },
-          { 0xe43a241d3b3ea114l,0x5c62b624366ae28dl,0x085a530db5f237eal,
-            0x7c4ed375651205afl },
-          0 },
-        /* 59 << 216 */
-        { { 0xf9de879dce842decl,0xe505320a94cedb89l,0xee55dae7f05ad888l,
-            0x44ffbfa7f028b4efl },
-          { 0xa3c1b32e63b2cd31l,0x201a058910c5ab29l,0x20f930afcd4085d6l,
-            0xda79ed169f6ff24bl },
-          0 },
-        /* 60 << 216 */
-        { { 0x7e8cfbcf704e23c6l,0xc71b7d2228aaa65bl,0xa041b2bd245e3c83l,
-            0x69b98834d21854ffl },
-          { 0x89d227a3963bfeecl,0x99947aaade7da7cbl,0x1d9ee9dbee68a9b1l,
-            0x0a08f003698ec368l },
-          0 },
-        /* 61 << 216 */
-        { { 0x04c64f33b0959be5l,0x182332ba396a7fe2l,0x4c5401e302e15b97l,
-            0x92880f9877db104bl },
-          { 0x0bf0b9cc21726a33l,0x780264741acc7b6dl,0x9721f621a26f08e3l,
-            0xe3935b434197fed1l },
-          0 },
-        /* 63 << 216 */
-        { { 0x0bffae503652be69l,0x395a9c6afb3fd5d8l,0x17f66adaa4fadfbfl,
-            0x1ee92a35f9268f8cl },
-          { 0x40ded34d6827781al,0xcd36224e34e63dccl,0xec90cf571cd1ef7al,
-            0xf6067d578f72a3bfl },
-          0 },
-        /* 64 << 216 */
-        { { 0x142b55021a93507al,0xb4cd11878d3c06cfl,0xdf70e76a91ec3f40l,
-            0x484e81ad4e7553c2l },
-          { 0x830f87b5272e9d6el,0xea1c93e5c6ff514al,0x67cc2adcc4192a8el,
-            0xc77e27e242f4535al },
-          0 },
-        /* 65 << 216 */
-        { { 0x537388d299e2f9d2l,0x15ead88612cd6d08l,0x33dfe3a769082d86l,
-            0x0ef25f4266d79d40l },
-          { 0x8035b4e546ba5cf1l,0x4e48f53711eec591l,0x40b56cda122a7aael,
-            0x78e270211dbb79a7l },
-          0 },
-        /* 71 << 216 */
-        { { 0x520b655355b4a5b1l,0xeee835cafb4f5fdel,0xb2ae86e59a823d7fl,
-            0x24325f4fc084497fl },
-          { 0x542bed4e6f0eefa4l,0x2909233b141792fdl,0x74bfc3bfc847a946l,
-            0x8ec1d009e212cb44l },
-          0 },
-        /* 77 << 216 */
-        { { 0xc2082b6d5cedd516l,0xaf148eadeafa3a10l,0x104cd5855ad63aa6l,
-            0xe3fdbf8c78c11e1el },
-          { 0x78651c493c25c24el,0x8064c4f37b7cce0el,0xa55441d4a6d8a928l,
-            0x4525c40eb0db3adcl },
-          0 },
-        /* 83 << 216 */
-        { { 0x5f69e49cfde6001el,0xc61e753aee59b47el,0xd0d4559971b0db5bl,
-            0x7f76f7b45ad4acc3l },
-          { 0xb0318a9c39830897l,0x2b15da22feef3822l,0x34049400acfb0753l,
-            0x16f4fb51a5114ed4l },
-          0 },
-        /* 89 << 216 */
-        { { 0x0b5c76928defbf10l,0xb9f1795cb79cdb6el,0xba17e7759a90317cl,
-            0x3cb69cf950cf514bl },
-          { 0x076cc4c1e5b892ffl,0x75724e8fb548b73cl,0x2ebcdb33248ff2e6l,
-            0x1f12967be109b08fl },
-          0 },
-        /* 95 << 216 */
-        { { 0x3f514c63461b7bb3l,0x3bdca5aa70afbad7l,0x368ce251eab3e38bl,
-            0xdc0fb3300d101049l },
-          { 0x7ce09abdff5013eel,0x926dd7dd7d10729dl,0xe6fe47ab6f486197l,
-            0xd23964eaa6eb6903l },
-          0 },
-        /* 101 << 216 */
-        { { 0x537ceb74eca30797l,0xf171bba557b0f338l,0x220a31fee831f1f8l,
-            0xabbc2c7c5ae6bbbcl },
-          { 0xaf7609f27eadfb60l,0x22cff1d58f28b51bl,0x63c3d76d6d1863bdl,
-            0x3a6a2fb489e8a4c8l },
-          0 },
-        /* 107 << 216 */
-        { { 0x9e74f8beb26e38f0l,0xc4c73fc4ea8bd55bl,0x086f688e1429e1fcl,
-            0x91438ff40f78159fl },
-          { 0x3571ae5f20810acbl,0x305edafe7451eb00l,0x8443c96d5704385cl,
-            0xc03b234e542605b5l },
-          0 },
-        /* 113 << 216 */
-        { { 0x2e5ff4fed85567c2l,0x136f49c7e4abd0c6l,0x5a68730cfb8a62d1l,
-            0x101ebfd030bcb848l },
-          { 0x634b0618fee950bbl,0xfa748d21c8aa65bal,0xc1d67c3e699f5560l,
-            0x6fb0546cb22889d2l },
-          0 },
-        /* 116 << 216 */
-        { { 0xa9784ebd9c95f0f9l,0x5ed9deb224640771l,0x31244af7035561c4l,
-            0x87332f3a7ee857del },
-          { 0x09e16e9e2b9e0d88l,0x52d910f456a06049l,0x507ed477a9592f48l,
-            0x85cb917b2365d678l },
-          0 },
-        /* 119 << 216 */
-        { { 0x6108f2b458a9d40dl,0xb036034838e15a52l,0xcc5610a3fd5625d6l,
-            0x79825dd083b0418el },
-          { 0xf83a95fc6324b6e5l,0x2463114deedfc4ebl,0x58b177e32250707fl,
-            0x778dcd454af8d942l },
-          0 },
-        /* 125 << 216 */
-        { { 0x1ecf2670eb816bf8l,0xa2d6e73aaa6d59c6l,0xf9a11434156852ebl,
-            0x9bc9bb70f6f82c83l },
-          { 0xd23a018d9c874836l,0xd26bf8bc6db5a8b5l,0x1d648846bec0c624l,
-            0x39f15d97ef90302fl },
-          0 },
-    },
-    {
-        /* 0 << 224 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 224 */
-        { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l,
-            0x2c41114ce0cdf943l },
-          { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l,
-            0x20477abf42ff9297l },
-          0 },
-        /* 3 << 224 */
-        { { 0x126f35b51e706ad9l,0xb99cebb4c3a9ebdfl,0xa75389afbf608d90l,
-            0x76113c4fc6c89858l },
-          { 0x80de8eb097e2b5aal,0x7e1022cc63b91304l,0x3bdab6056ccc066cl,
-            0x33cbb144b2edf900l },
-          0 },
-        /* 4 << 224 */
-        { { 0xc41764717af715d2l,0xe2f7f594d0134a96l,0x2c1873efa41ec956l,
-            0xe4e7b4f677821304l },
-          { 0xe5c8ff9788d5374al,0x2b915e6380823d5bl,0xea6bc755b2ee8fe2l,
-            0x6657624ce7112651l },
-          0 },
-        /* 5 << 224 */
-        { { 0x157af101dace5acal,0xc4fdbcf211a6a267l,0xdaddf340c49c8609l,
-            0x97e49f52e9604a65l },
-          { 0x9be8e790937e2ad5l,0x846e2508326e17f1l,0x3f38007a0bbbc0dcl,
-            0xcf03603fb11e16d6l },
-          0 },
-        /* 7 << 224 */
-        { { 0x5ed0c007f8ae7c38l,0x6db07a5c3d740192l,0xbe5e9c2a5fe36db3l,
-            0xd5b9d57a76e95046l },
-          { 0x54ac32e78eba20f2l,0xef11ca8f71b9a352l,0x305e373eff98a658l,
-            0xffe5a100823eb667l },
-          0 },
-        /* 9 << 224 */
-        { { 0x5c8ed8d5da64309dl,0x61a6de5691b30704l,0xd6b52f6a2f9b5808l,
-            0x0eee419498c958a7l },
-          { 0xcddd9aab771e4caal,0x83965dfd78bc21bel,0x02affce3b3b504f5l,
-            0x30847a21561c8291l },
-          0 },
-        /* 10 << 224 */
-        { { 0xd2eb2cf152bfda05l,0xe0e4c4e96197b98cl,0x1d35076cf8a1726fl,
-            0x6c06085b2db11e3dl },
-          { 0x15c0c4d74463ba14l,0x9d292f830030238cl,0x1311ee8b3727536dl,
-            0xfeea86efbeaedc1el },
-          0 },
-        /* 11 << 224 */
-        { { 0xb9d18cd366131e2el,0xf31d974f80fe2682l,0xb6e49e0fe4160289l,
-            0x7c48ec0b08e92799l },
-          { 0x818111d8d1989aa7l,0xb34fa0aaebf926f9l,0xdb5fe2f5a245474al,
-            0xf80a6ebb3c7ca756l },
-          0 },
-        /* 13 << 224 */
-        { { 0x8ea610593de9abe3l,0x404348819cdc03bel,0x9b261245cfedce8cl,
-            0x78c318b4cf5234a1l },
-          { 0x510bcf16fde24c99l,0x2a77cb75a2c2ff5dl,0x9c895c2b27960fb4l,
-            0xd30ce975b0eda42bl },
-          0 },
-        /* 15 << 224 */
-        { { 0x09521177ff57d051l,0x2ff38037fb6a1961l,0xfc0aba74a3d76ad4l,
-            0x7c76480325a7ec17l },
-          { 0x7532d75f48879bc8l,0xea7eacc058ce6bc1l,0xc82176b48e896c16l,
-            0x9a30e0b22c750fedl },
-          0 },
-        /* 16 << 224 */
-        { { 0xc37e2c2e421d3aa4l,0xf926407ce84fa840l,0x18abc03d1454e41cl,
-            0x26605ecd3f7af644l },
-          { 0x242341a6d6a5eabfl,0x1edb84f4216b668el,0xd836edb804010102l,
-            0x5b337ce7945e1d8cl },
-          0 },
-        /* 17 << 224 */
-        { { 0xd2075c77c055dc14l,0x2a0ffa2581d89cdfl,0x8ce815ea6ffdcbafl,
-            0xa3428878fb648867l },
-          { 0x277699cf884655fbl,0xfa5b5bd6364d3e41l,0x01f680c6441e1cb7l,
-            0x3fd61e66b70a7d67l },
-          0 },
-        /* 19 << 224 */
-        { { 0xfd5bb657b1fa70fbl,0xfa07f50fd8073a00l,0xf72e3aa7bca02500l,
-            0xf68f895d9975740dl },
-          { 0x301120605cae2a6al,0x01bd721802874842l,0x3d4238917ce47bd3l,
-            0xa66663c1789544f6l },
-          0 },
-        /* 21 << 224 */
-        { { 0xb4b9a39b36194d40l,0xe857a7c577612601l,0xf4209dd24ecf2f58l,
-            0x82b9e66d5a033487l },
-          { 0xc1e36934e4e8b9ddl,0xd2372c9da42377d7l,0x51dc94c70e3ae43bl,
-            0x4c57761e04474f6fl },
-          0 },
-        /* 23 << 224 */
-        { { 0xa39114e24415503bl,0xc08ff7c64cbb17e9l,0x1eff674dd7dec966l,
-            0x6d4690af53376f63l },
-          { 0xff6fe32eea74237bl,0xc436d17ecd57508el,0x15aa28e1edcc40fel,
-            0x0d769c04581bbb44l },
-          0 },
-        /* 25 << 224 */
-        { { 0xfe51d0296ae55043l,0x8931e98f44a87de1l,0xe57f1cc609e4fee2l,
-            0x0d063b674e072d92l },
-          { 0x70a998b9ed0e4316l,0xe74a736b306aca46l,0xecf0fbf24fda97c7l,
-            0xa40f65cb3e178d93l },
-          0 },
-        /* 27 << 224 */
-        { { 0x8667e981c27253c9l,0x05a6aefb92b36a45l,0xa62c4b369cb7bb46l,
-            0x8394f37511f7027bl },
-          { 0x747bc79c5f109d0fl,0xcad88a765b8cc60al,0x80c5a66b58f09e68l,
-            0xe753d451f6127eacl },
-          0 },
-        /* 28 << 224 */
-        { { 0xc44b74a15b0ec6f5l,0x47989fe45289b2b8l,0x745f848458d6fc73l,
-            0xec362a6ff61c70abl },
-          { 0x070c98a7b3a8ad41l,0x73a20fc07b63db51l,0xed2c2173f44c35f4l,
-            0x8a56149d9acc9dcal },
-          0 },
-        /* 29 << 224 */
-        { { 0x98f178819ac6e0f4l,0x360fdeafa413b5edl,0x0625b8f4a300b0fdl,
-            0xf1f4d76a5b3222d3l },
-          { 0x9d6f5109587f76b8l,0x8b4ee08d2317fdb5l,0x88089bb78c68b095l,
-            0x95570e9a5808d9b9l },
-          0 },
-        /* 31 << 224 */
-        { { 0x2e1284943fb42622l,0x3b2700ac500907d5l,0xf370fb091a95ec63l,
-            0xf8f30be231b6dfbdl },
-          { 0xf2b2f8d269e55f15l,0x1fead851cc1323e9l,0xfa366010d9e5eef6l,
-            0x64d487b0e316107el },
-          0 },
-        /* 33 << 224 */
-        { { 0xc9a9513929607745l,0x0ca07420a26f2b28l,0xcb2790e74bc6f9ddl,
-            0x345bbb58adcaffc0l },
-          { 0xc65ea38cbe0f27a2l,0x67c24d7c641fcb56l,0x2c25f0a7a9e2c757l,
-            0x93f5cdb016f16c49l },
-          0 },
-        /* 34 << 224 */
-        { { 0x2ca5a9d7c5ee30a1l,0xd1593635b909b729l,0x804ce9f3dadeff48l,
-            0xec464751b07c30c3l },
-          { 0x89d65ff39e49af6al,0xf2d6238a6f3d01bcl,0x1095561e0bced843l,
-            0x51789e12c8a13fd8l },
-          0 },
-        /* 35 << 224 */
-        { { 0xd633f929763231dfl,0x46df9f7de7cbddefl,0x01c889c0cb265da8l,
-            0xfce1ad10af4336d2l },
-          { 0x8d110df6fc6a0a7el,0xdd431b986da425dcl,0xcdc4aeab1834aabel,
-            0x84deb1248439b7fcl },
-          0 },
-        /* 36 << 224 */
-        { { 0x8796f1693c2a5998l,0x9b9247b47947190dl,0x55b9d9a511597014l,
-            0x7e9dd70d7b1566eel },
-          { 0x94ad78f7cbcd5e64l,0x0359ac179bd4c032l,0x3b11baaf7cc222ael,
-            0xa6a6e284ba78e812l },
-          0 },
-        /* 37 << 224 */
-        { { 0x8392053f24cea1a0l,0xc97bce4a33621491l,0x7eb1db3435399ee9l,
-            0x473f78efece81ad1l },
-          { 0x41d72fe0f63d3d0dl,0xe620b880afab62fcl,0x92096bc993158383l,
-            0x41a213578f896f6cl },
-          0 },
-        /* 39 << 224 */
-        { { 0x6fb4d4e42bad4d5fl,0xfa4c3590fef0059bl,0x6a10218af5122294l,
-            0x9a78a81aa85751d1l },
-          { 0x04f20579a98e84e7l,0xfe1242c04997e5b5l,0xe77a273bca21e1e4l,
-            0xfcc8b1ef9411939dl },
-          0 },
-        /* 40 << 224 */
-        { { 0xe20ea30292d0487al,0x1442dbec294b91fel,0x1f7a4afebb6b0e8fl,
-            0x1700ef746889c318l },
-          { 0xf5bbffc370f1fc62l,0x3b31d4b669c79ccal,0xe8bc2aaba7f6340dl,
-            0xb0b08ab4a725e10al },
-          0 },
-        /* 41 << 224 */
-        { { 0x44f05701ae340050l,0xba4b30161cf0c569l,0x5aa29f83fbe19a51l,
-            0x1b9ed428b71d752el },
-          { 0x1666e54eeb4819f5l,0x616cdfed9e18b75bl,0x112ed5be3ee27b0bl,
-            0xfbf2831944c7de4dl },
-          0 },
-        /* 43 << 224 */
-        { { 0x722eb104e2b4e075l,0x49987295437c4926l,0xb1e4c0e446a9b82dl,
-            0xd0cb319757a006f5l },
-          { 0xf3de0f7dd7808c56l,0xb5c54d8f51f89772l,0x500a114aadbd31aal,
-            0x9afaaaa6295f6cabl },
-          0 },
-        /* 44 << 224 */
-        { { 0x94705e2104cf667al,0xfc2a811b9d3935d7l,0x560b02806d09267cl,
-            0xf19ed119f780e53bl },
-          { 0xf0227c09067b6269l,0x967b85335caef599l,0x155b924368efeebcl,
-            0xcd6d34f5c497bae6l },
-          0 },
-        /* 45 << 224 */
-        { { 0x1dd8d5d36cceb370l,0x2aeac579a78d7bf9l,0x5d65017d70b67a62l,
-            0x70c8e44f17c53f67l },
-          { 0xd1fc095086a34d09l,0xe0fca256e7134907l,0xe24fa29c80fdd315l,
-            0x2c4acd03d87499adl },
-          0 },
-        /* 46 << 224 */
-        { { 0xbaaf75173b5a9ba6l,0xb9cbe1f612e51a51l,0xd88edae35e154897l,
-            0xe4309c3c77b66ca0l },
-          { 0xf5555805f67f3746l,0x85fc37baa36401ffl,0xdf86e2cad9499a53l,
-            0x6270b2a3ecbc955bl },
-          0 },
-        /* 47 << 224 */
-        { { 0xafae64f5974ad33bl,0x04d85977fe7b2df1l,0x2a3db3ff4ab03f73l,
-            0x0b87878a8702740al },
-          { 0x6d263f015a061732l,0xc25430cea32a1901l,0xf7ebab3ddb155018l,
-            0x3a86f69363a9b78el },
-          0 },
-        /* 48 << 224 */
-        { { 0x349ae368da9f3804l,0x470f07fea164349cl,0xd52f4cc98562baa5l,
-            0xc74a9e862b290df3l },
-          { 0xd3a1aa3543471a24l,0x239446beb8194511l,0xbec2dd0081dcd44dl,
-            0xca3d7f0fc42ac82dl },
-          0 },
-        /* 49 << 224 */
-        { { 0x1f3db085fdaf4520l,0xbb6d3e804549daf2l,0xf5969d8a19ad5c42l,
-            0x7052b13ddbfd1511l },
-          { 0x11890d1b682b9060l,0xa71d3883ac34452cl,0xa438055b783805b4l,
-            0x432412774725b23el },
-          0 },
-        /* 51 << 224 */
-        { { 0x40b08f7443b30ca8l,0xe10b5bbad9934583l,0xe8a546d6b51110adl,
-            0x1dd50e6628e0b6c5l },
-          { 0x292e9d54cff2b821l,0x3882555d47281760l,0x134838f83724d6e3l,
-            0xf2c679e022ddcda1l },
-          0 },
-        /* 52 << 224 */
-        { { 0x40ee88156d2a5768l,0x7f227bd21c1e7e2dl,0x487ba134d04ff443l,
-            0x76e2ff3dc614e54bl },
-          { 0x36b88d6fa3177ec7l,0xbf731d512328fff5l,0x758caea249ba158el,
-            0x5ab8ff4c02938188l },
-          0 },
-        /* 53 << 224 */
-        { { 0x33e1605635edc56dl,0x5a69d3497e940d79l,0x6c4fd00103866dcbl,
-            0x20a38f574893cdefl },
-          { 0xfbf3e790fac3a15bl,0x6ed7ea2e7a4f8e6bl,0xa663eb4fbc3aca86l,
-            0x22061ea5080d53f7l },
-          0 },
-        /* 55 << 224 */
-        { { 0x635a8e5ec3a0ee43l,0x70aaebca679898ffl,0x9ee9f5475dc63d56l,
-            0xce987966ffb34d00l },
-          { 0xf9f86b195e26310al,0x9e435484382a8ca8l,0x253bcb81c2352fe4l,
-            0xa4eac8b04474b571l },
-          0 },
-        /* 57 << 224 */
-        { { 0x2617f91c93aa96b8l,0x0fc8716b7fca2e13l,0xa7106f5e95328723l,
-            0xd1c9c40b262e6522l },
-          { 0xb9bafe8642b7c094l,0x1873439d1543c021l,0xe1baa5de5cbefd5dl,
-            0xa363fc5e521e8affl },
-          0 },
-        /* 59 << 224 */
-        { { 0xbc00fc2f2f8ba2c7l,0x0966eb2f7c67aa28l,0x13f7b5165a786972l,
-            0x3bfb75578a2fbba0l },
-          { 0x131c4f235a2b9620l,0xbff3ed276faf46bel,0x9b4473d17e172323l,
-            0x421e8878339f6246l },
-          0 },
-        /* 60 << 224 */
-        { { 0x0fa8587a25a41632l,0xc0814124a35b6c93l,0x2b18a9f559ebb8dbl,
-            0x264e335776edb29cl },
-          { 0xaf245ccdc87c51e2l,0x16b3015b501e6214l,0xbb31c5600a3882cel,
-            0x6961bb94fec11e04l },
-          0 },
-        /* 61 << 224 */
-        { { 0x3b825b8deff7a3a0l,0xbec33738b1df7326l,0x68ad747c99604a1fl,
-            0xd154c9349a3bd499l },
-          { 0xac33506f1cc7a906l,0x73bb53926c560e8fl,0x6428fcbe263e3944l,
-            0xc11828d51c387434l },
-          0 },
-        /* 63 << 224 */
-        { { 0x659b17c8d8ceb147l,0x9b649eeeb70a5554l,0x6b7fa0b5ac6bc634l,
-            0xd99fe2c71d6e732fl },
-          { 0x30e6e7628d3abba2l,0x18fee6e7a797b799l,0x5c9d360dc696464dl,
-            0xe3baeb4827bfde12l },
-          0 },
-        /* 64 << 224 */
-        { { 0x2bf5db47f23206d5l,0x2f6d34201d260152l,0x17b876533f8ff89al,
-            0x5157c30c378fa458l },
-          { 0x7517c5c52d4fb936l,0xef22f7ace6518cdcl,0xdeb483e6bf847a64l,
-            0xf508455892e0fa89l },
-          0 },
-        /* 65 << 224 */
-        { { 0xf77bb113a74ed3bel,0x89e4eb8f074f2637l,0x7fbfa84df7ce2aebl,
-            0xe7c6ecd5baaefe4cl },
-          { 0x176bba7df6319542l,0x70098120f6080799l,0x2e2118339054d9aal,
-            0x1be4c6a78295a912l },
-          0 },
-        /* 71 << 224 */
-        { { 0x6bb4d8c35df1455fl,0xb839f08f0384b033l,0x718868af11f95d50l,
-            0xae256a92e07a8801l },
-          { 0xa5bafaf24d71a273l,0x18ff04ea2a30e68fl,0x364c193287ba727el,
-            0x4bb8cf99befcaf73l },
-          0 },
-        /* 77 << 224 */
-        { { 0xc79f5b1f4e9fb3d7l,0x52854970a51cccddl,0xa4e27e97f00054a3l,
-            0x26a79792240e1232l },
-          { 0xb15579fecb5ff465l,0x6ef54c3bd1722a84l,0xee211bfa5239a4d8l,
-            0x36c7db27270b7059l },
-          0 },
-        /* 83 << 224 */
-        { { 0x5e7da0a9f9858cd3l,0x67459de5b633de49l,0x2db0d54b2e73892el,
-            0x37f50877adae399al },
-          { 0x83c28b83b65e6179l,0xae5a915ca39faf17l,0x6ab8f3fbe841b53cl,
-            0x7c30997b0df7d004l },
-          0 },
-        /* 89 << 224 */
-        { { 0x87904ca7b3b862bdl,0x7593db93cf9ea671l,0x8a2670f8739aa783l,
-            0x3921d779f5154ca6l },
-          { 0xe81ca56468f65ebbl,0x0c600603bc4e64d4l,0xdf170049cb83b2d1l,
-            0x373893b863487064l },
-          0 },
-        /* 95 << 224 */
-        { { 0x7c3c52b9c0c4e88el,0x0f0484d06f0c2446l,0xeb876827000fe87bl,
-            0xa749b3136d20f94al },
-          { 0x0876dae9d55abda6l,0xe6e4367620726911l,0xf85e8a8c4a2676b4l,
-            0x4e8c97f1b4a890ebl },
-          0 },
-        /* 101 << 224 */
-        { { 0xa992f482a3c0a4f4l,0xe1536f3f7a8d961al,0x26fc79ae000752b0l,
-            0xdbfb706b76ad8508l },
-          { 0x2642b2ed6f4cf9e4l,0xa013db54557fa7e2l,0x2ef711821d326116l,
-            0x8dc3f5bcbafc83ecl },
-          0 },
-        /* 107 << 224 */
-        { { 0x9671258578e5a201l,0xc71aca1de9125569l,0x360c45c0e2231379l,
-            0x2d71783512e82369l },
-          { 0x392432d3d84b2153l,0x502fd3f6d6939ffel,0x33c440ae6e766cacl,
-            0x99f1fbee28062416l },
-          0 },
-        /* 113 << 224 */
-        { { 0xe51ad841861604cbl,0x1ec9c54f630283a7l,0xcc42cad582a39473l,
-            0xa2eb053709929c4al },
-          { 0xe374459767f655a3l,0x9f54c2451d7f2674l,0xd85e9163fbc8aba5l,
-            0x12fd0b55866bc892l },
-          0 },
-        /* 116 << 224 */
-        { { 0x4f2c3063d7bd4661l,0xe533798d57a974ccl,0x44860d503ea02d85l,
-            0xf2a7f4e5acaa0521l },
-          { 0x05593061abb108f0l,0x56d1056044528309l,0x1f674df9c88b6d1el,
-            0x19fdc4cbd8744c4dl },
-          0 },
-        /* 119 << 224 */
-        { { 0xfd1488ec00f2f1d5l,0x24fcc67b44a825ddl,0xc7bfae2ea925a0f4l,
-            0x5e03249cad59cf48l },
-          { 0x1dc5a8e11af4844cl,0x89b2fbc58a598c20l,0xb0f56afff2078121l,
-            0x8194012d4878bb0dl },
-          0 },
-        /* 125 << 224 */
-        { { 0xc1cbe9d3a5ae1031l,0x38da74435706b987l,0x01844b55b353f188l,
-            0x390c59ca87a807c5l },
-          { 0x55ac7b1fb13b780cl,0x060970bff375c1cbl,0x8dd1f378c7ab4e5cl,
-            0xcca782e5cf726645l },
-          0 },
-    },
-    {
-        /* 0 << 232 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 232 */
-        { { 0x91213462f23f2d92l,0x6cab71bd60b94078l,0x6bdd0a63176cde20l,
-            0x54c9b20cee4d54bcl },
-          { 0x3cd2d8aa9f2ac02fl,0x03f8e617206eedb0l,0xc7f68e1693086434l,
-            0x831469c592dd3db9l },
-          0 },
-        /* 3 << 232 */
-        { { 0x4a9090cde36d0757l,0xf722d7b1d9a29382l,0xfb7fb04c04b48ddfl,
-            0x628ad2a7ebe16f43l },
-          { 0xcd3fbfb520226040l,0x6c34ecb15104b6c4l,0x30c0754ec903c188l,
-            0xec336b082d23cab0l },
-          0 },
-        /* 4 << 232 */
-        { { 0x9f51439e558df019l,0x230da4baac712b27l,0x518919e355185a24l,
-            0x4dcefcdd84b78f50l },
-          { 0xa7d90fb2a47d4c5al,0x55ac9abfb30e009el,0xfd2fc35974eed273l,
-            0xb72d824cdbea8fafl },
-          0 },
-        /* 5 << 232 */
-        { { 0xd213f923cbb13d1bl,0x98799f425bfb9bfel,0x1ae8ddc9701144a9l,
-            0x0b8b3bb64c5595eel },
-          { 0x0ea9ef2e3ecebb21l,0x17cb6c4b3671f9a7l,0x47ef464f726f1d1fl,
-            0x171b94846943a276l },
-          0 },
-        /* 7 << 232 */
-        { { 0xc9941109a607419dl,0xfaa71e62bb6bca80l,0x34158c1307c431f3l,
-            0x594abebc992bc47al },
-          { 0x6dfea691eb78399fl,0x48aafb353f42cba4l,0xedcd65af077c04f0l,
-            0x1a29a366e884491al },
-          0 },
-        /* 9 << 232 */
-        { { 0x7bf6a5c1f7ea25aal,0xd165e6bffbb07d5fl,0xe353936189e78671l,
-            0xa3fcac892bac4219l },
-          { 0xdfab6fd4f0baa8abl,0x5a4adac1e2c1c2e5l,0x6cd75e3140d85849l,
-            0xce263fea19b39181l },
-          0 },
-        /* 10 << 232 */
-        { { 0xb8d804a3315980cdl,0x693bc492fa3bebf7l,0x3578aeee2253c504l,
-            0x158de498cd2474a2l },
-          { 0x1331f5c7cfda8368l,0xd2d7bbb378d7177el,0xdf61133af3c1e46el,
-            0x5836ce7dd30e7be8l },
-          0 },
-        /* 11 << 232 */
-        { { 0xe042ece59a29a5c5l,0xb19b3c073b6c8402l,0xc97667c719d92684l,
-            0xb5624622ebc66372l },
-          { 0x0cb96e653c04fa02l,0x83a7176c8eaa39aal,0x2033561deaa1633fl,
-            0x45a9d0864533df73l },
-          0 },
-        /* 13 << 232 */
-        { { 0xa29ae9df5ece6e7cl,0x0603ac8f0facfb55l,0xcfe85b7adda233a5l,
-            0xe618919fbd75f0b8l },
-          { 0xf555a3d299bf1603l,0x1f43afc9f184255al,0xdcdaf341319a3e02l,
-            0xd3b117ef03903a39l },
-          0 },
-        /* 15 << 232 */
-        { { 0xb6b82fa74d82f4c2l,0x90725a606804efb3l,0xbc82ec46adc3425el,
-            0xb7b805812787843el },
-          { 0xdf46d91cdd1fc74cl,0xdc1c62cbe783a6c4l,0x59d1b9f31a04cbbal,
-            0xd87f6f7295e40764l },
-          0 },
-        /* 16 << 232 */
-        { { 0x196860411e84e0e5l,0xa5db84d3aea34c93l,0xf9d5bb197073a732l,
-            0xb8d2fe566bcfd7c0l },
-          { 0x45775f36f3eb82fal,0x8cb20cccfdff8b58l,0x1659b65f8374c110l,
-            0xb8b4a422330c789al },
-          0 },
-        /* 17 << 232 */
-        { { 0xa6312c9e8977d99bl,0xbe94433183f531e7l,0x8232c0c218d3b1d4l,
-            0x617aae8be1247b73l },
-          { 0x40153fc4282aec3bl,0xc6063d2ff7b8f823l,0x68f10e583304f94cl,
-            0x31efae74ee676346l },
-          0 },
-        /* 19 << 232 */
-        { { 0xd98bf2a43734e520l,0x5e3abbe3209bdcbal,0x77c76553bc945b35l,
-            0x5331c093c6ef14aal },
-          { 0x518ffe2976b60c80l,0x2285593b7ace16f8l,0xab1f64ccbe2b9784l,
-            0xe8f2c0d9ab2421b6l },
-          0 },
-        /* 21 << 232 */
-        { { 0x481dae5fd5ecfefcl,0x07084fd8c2bff8fcl,0x8040a01aea324596l,
-            0x4c646980d4de4036l },
-          { 0x9eb8ab4ed65abfc3l,0xe01cb91f13541ec7l,0x8f029adbfd695012l,
-            0x9ae284833c7569ecl },
-          0 },
-        /* 23 << 232 */
-        { { 0xc83605f6f10ff927l,0xd387145123739fc6l,0x6d163450cac1c2ccl,
-            0x6b521296a2ec1ac5l },
-          { 0x0606c4f96e3cb4a5l,0xe47d3f41778abff7l,0x425a8d5ebe8e3a45l,
-            0x53ea9e97a6102160l },
-          0 },
-        /* 25 << 232 */
-        { { 0x6b72fab526bc2797l,0x13670d1699f16771l,0x001700521e3e48d1l,
-            0x978fe401b7adf678l },
-          { 0x55ecfb92d41c5dd4l,0x5ff8e247c7b27da5l,0xe7518272013fb606l,
-            0x5768d7e52f547a3cl },
-          0 },
-        /* 27 << 232 */
-        { { 0x0e966e64c73b2383l,0x49eb3447d17d8762l,0xde1078218da05dabl,
-            0x443d8baa016b7236l },
-          { 0x163b63a5ea7610d6l,0xe47e4185ce1ca979l,0xae648b6580baa132l,
-            0xebf53de20e0d5b64l },
-          0 },
-        /* 28 << 232 */
-        { { 0x6ba535da9a85788bl,0xd21f03aebd0626d4l,0x099f8c47e873dc64l,
-            0xcda8564d018ec97el },
-          { 0x3e8d7a5cde92c68cl,0x78e035a173323cc4l,0x3ef26275f880ff7cl,
-            0xa4ee3dff273eedaal },
-          0 },
-        /* 29 << 232 */
-        { { 0x8bbaec49571d92acl,0x569e85fe4692517fl,0x8333b014a14ea4afl,
-            0x32f2a62f12e5c5adl },
-          { 0x98c2ce3a06d89b85l,0xb90741aa2ff77a08l,0x2530defc01f795a2l,
-            0xd6e5ba0b84b3c199l },
-          0 },
-        /* 31 << 232 */
-        { { 0x3d1b24cb28c682c6l,0x27f252288612575bl,0xb587c779e8e66e98l,
-            0x7b0c03e9405eb1fel },
-          { 0xfdf0d03015b548e7l,0xa8be76e038b36af7l,0x4cdab04a4f310c40l,
-            0x6287223ef47ecaecl },
-          0 },
-        /* 33 << 232 */
-        { { 0x0a4c6f3670ad54aal,0xc24cfd0d2a543909l,0xe1b0bc5b745c1a97l,
-            0xb8431cfd68f0ddbfl },
-          { 0x326357989ed8cb06l,0xa00a80ff759d2b7dl,0x81f335c190570e02l,
-            0xbfccd89849c4e4d9l },
-          0 },
-        /* 34 << 232 */
-        { { 0x4dcb646bfd16d8c4l,0x76a6b640e38ba57bl,0xd92de1f79d8ae7e2l,
-            0x126f48f13f77f23bl },
-          { 0xb7b53ca977e8abc2l,0x3faa17112c0787ffl,0xf8f9308c8e5762f8l,
-            0x600a8a7f6b83aea8l },
-          0 },
-        /* 35 << 232 */
-        { { 0xa2aed4a799aa03c0l,0x1f93b93da18b79c5l,0x7b4550b7314192c3l,
-            0x9da00676272bb08el },
-          { 0xe42f0d7e23e072edl,0x7ce76494888b5783l,0x4c7900203680b63bl,
-            0x6040c83f662a8718l },
-          0 },
-        /* 36 << 232 */
-        { { 0xba9e5c88a56d73edl,0x6c24f7712ca054d3l,0x4a37c235083beae1l,
-            0x04a883b26483e9fdl },
-          { 0x0c63f3aee27c2c5dl,0x0e1da88dae4671f1l,0xa577e8e25995e1dbl,
-            0xbfc4b1b16ed6066al },
-          0 },
-        /* 37 << 232 */
-        { { 0x8b398541f53d9e63l,0x4ab045bb019395cbl,0x69a1b90371dd70c7l,
-            0xdedf284b38aaa431l },
-          { 0xb45e245aaed3efe7l,0x49460905079f2facl,0xde4dee470845bd78l,
-            0x0540524039d02ec3l },
-          0 },
-        /* 39 << 232 */
-        { { 0x300cf051675cc986l,0x758afea99324219fl,0xf524c3fad5a93b5fl,
-            0xb73385abc3864a8al },
-          { 0xbde19289f6be9050l,0xbb9018558205a3f3l,0x99a9d14d229f6b89l,
-            0x4c3a802f4336e68fl },
-          0 },
-        /* 40 << 232 */
-        { { 0xdd4a12d8e12b31f8l,0x577e29bc177736e6l,0x2353722ba88935e8l,
-            0xca1d3729015f286dl },
-          { 0x86c7b6a239a3e035l,0x6e5250bfd3b03a9fl,0x79d98930fd0d536el,
-            0x8c4cbbabfa0c3832l },
-          0 },
-        /* 41 << 232 */
-        { { 0x92ecff374f8e6163l,0x171cc8830f35faeal,0xc5434242bcd36142l,
-            0x707049adb28b63bbl },
-          { 0xa1f4d1dbf6443da9l,0x002bb062dabc108bl,0x17287f171a272b08l,
-            0x2a3aac8c884cf6bbl },
-          0 },
-        /* 43 << 232 */
-        { { 0x55524645651c0a5al,0x14624a9703cf0d12l,0xca9315a8f884a9e2l,
-            0x9840c6e2df7c9d59l },
-          { 0xd96bd10a7438e8d5l,0x12be73d2b2f887del,0x5e47445dca2493efl,
-            0x85aef555e9fff03el },
-          0 },
-        /* 44 << 232 */
-        { { 0x169b38c9a43b2339l,0x884308d91732bfabl,0xe4b593a28ff202ddl,
-            0xaf51d11f1e65376cl },
-          { 0x6ec648de741525ffl,0xf93cbd369ff4c628l,0xc76df9efb1129c79l,
-            0x31a5f2e2b7a67294l },
-          0 },
-        /* 45 << 232 */
-        { { 0x0661bc02801d0e38l,0x4a37dc0e71fc46b7l,0x0b224cfc80c3e311l,
-            0x2dd3d2779646a957l },
-          { 0xfa45aa18ef524012l,0x5d2a2d0916185a09l,0x34d5c630b5313dcel,
-            0xd9581ed151e4cf84l },
-          0 },
-        /* 46 << 232 */
-        { { 0x5845aa4a8ebd2af8l,0x141404ecd3df43ccl,0xff3fc7681ffd48d9l,
-            0x8a096e72e0cefb65l },
-          { 0xc9c81cfdffc3a5cdl,0x7550aa3029b27cf9l,0x34dca72b65fa0380l,
-            0xe8c5f6059ddd032bl },
-          0 },
-        /* 47 << 232 */
-        { { 0xe53da8a46bfbadb3l,0x4a9dfa55afaeeb5el,0x076245ea6644b1d4l,
-            0xc19be4012307bbcbl },
-          { 0x097774c19d77318bl,0xacc8a1519cfd51c4l,0x736ef6b3ecaa7b08l,
-            0x107479132d643a80l },
-          0 },
-        /* 48 << 232 */
-        { { 0x2d500910cab91f1el,0xbedd9e444d1cd216l,0xd634b74fedd02252l,
-            0xbd60f8e11258617al },
-          { 0xd8c7537b9e05614al,0xfd26c766e7af5fc5l,0x0660b581582bd926l,
-            0x87019244acf07fc8l },
-          0 },
-        /* 49 << 232 */
-        { { 0xd4889fdf6220ae8el,0x745d67ec1abf1549l,0x957b2e3d2fb89c36l,
-            0x9768c90edc62ada9l },
-          { 0x90332fd748e6c46el,0x5aa5a4e54e90ef0dl,0x58838fd3ddcc8571l,
-            0xd12f6c6f9a721126l },
-          0 },
-        /* 51 << 232 */
-        { { 0x2f0fd0b2cec757bal,0x46a7a9c63032cd1dl,0x9af3a600547d7a77l,
-            0x828e16eca43da1bal },
-          { 0x0b303a66092a8d92l,0x78ba0389c23d08bal,0x52aed08d4616bd29l,
-            0x4c0ff1210539c9fal },
-          0 },
-        /* 52 << 232 */
-        { { 0x2c3b7322badcfe8el,0x6e0616fac5e25a04l,0x0a3c12753da6e4a2l,
-            0xe46c957e077bca01l },
-          { 0xb46ca4e3da4be64bl,0xa59bda668e75ee78l,0x41835184a4de98f2l,
-            0x6efb1f924ed6a568l },
-          0 },
-        /* 53 << 232 */
-        { { 0xbb8cdc094af1dd72l,0x93c0aa38a2460633l,0xf66f5d238a7ebc93l,
-            0x43ecda843e8e37a6l },
-          { 0x399da8265fd5139el,0x8b39930fd446f38el,0x114414135d2b68efl,
-            0x8be163b8d1637c38l },
-          0 },
-        /* 55 << 232 */
-        { { 0x488e2a35b70ddbd3l,0xb4aa5f718da50077l,0xb38b74b1d8752bbdl,
-            0x7007f328416106a3l },
-          { 0xe6a62e4fcec4ea68l,0x9fdfb79741ef920bl,0x1a19d7dfe3c337a6l,
-            0x08f643558be0f586l },
-          0 },
-        /* 57 << 232 */
-        { { 0x91a5d8ff60343a1fl,0x921e442173ef8cdfl,0x4358f27b975138cdl,
-            0x36fd8577a4992b08l },
-          { 0xc07c8ca1f8d044c6l,0xcf42903687747b6bl,0x0932ffb0867c8632l,
-            0x7e565213250e5a89l },
-          0 },
-        /* 59 << 232 */
-        { { 0xae7c3b9b06255feal,0x2eb1d9a78a6fe229l,0xf81548e77601e6f8l,
-            0x777394eb7bd96d6cl },
-          { 0x54734187000a3509l,0xaeec146492d43c04l,0xc9b7f0d7c428b4acl,
-            0x9d4bcedccd7f7018l },
-          0 },
-        /* 60 << 232 */
-        { { 0x4741b9b311370605l,0x47fa72f75d09b355l,0x391a71ac7a144c6al,
-            0x0808c0f498b6e3cal },
-          { 0x7eaed9ef7fe53900l,0xf157a2a5e5a830bal,0xd13ec09127974afcl,
-            0x78d710a70b87997dl },
-          0 },
-        /* 61 << 232 */
-        { { 0xcbb96ecb4e263f81l,0x093e0d1509084351l,0x7af3232629220a81l,
-            0xd721b415c60f36dcl },
-          { 0xe3340a87fe9387a1l,0x6088bf482ff2b126l,0xd31028f1d2bc982cl,
-            0x9794e106630d52cbl },
-          0 },
-        /* 63 << 232 */
-        { { 0x1dac76780b11e972l,0x46e814c62698dafel,0x553f7370c37640d6l,
-            0xdcf588cc51cede93l },
-          { 0x4d6b56d3c3f6215bl,0x07edc6621b8f8f03l,0xdfef9d60b9a5dfbcl,
-            0x377edf4d10af7a5bl },
-          0 },
-        /* 64 << 232 */
-        { { 0x8928e99aeeaf8c49l,0xee7aa73d6e24d728l,0x4c5007c2e72b156cl,
-            0x5fcf57c5ed408a1dl },
-          { 0x9f719e39b6057604l,0x7d343c01c2868bbfl,0x2cca254b7e103e2dl,
-            0xe6eb38a9f131bea2l },
-          0 },
-        /* 65 << 232 */
-        { { 0x26ae28bede7a4b7el,0xd2f07569d2664163l,0x798690d4ff69266al,
-            0x77093d356ef3695dl },
-          { 0xaca9903d567dd3dfl,0x259c59a3a274c67bl,0x9f34bc0bfc1198b0l,
-            0x51a7726290b1521cl },
-          0 },
-        /* 71 << 232 */
-        { { 0xa20644bc80ca5391l,0xf9cdb4f7e5b36ea3l,0xe7936c0641426e22l,
-            0x39bc23033eef8a52l },
-          { 0x31253f43e5d8f896l,0xb0e5a588dc3df499l,0x1d03519a2d7e66d5l,
-            0x923de91f6d7da5e3l },
-          0 },
-        /* 77 << 232 */
-        { { 0x17a833ffedf861e4l,0x0ee3d0af4ebec965l,0xd0fac1c1ea66870el,
-            0x325756d0ae810cf4l },
-          { 0x4ed78d2c78e9a415l,0x6cc65685192046e4l,0x03e4243d8498a91el,
-            0x56a02dd25ab97794l },
-          0 },
-        /* 83 << 232 */
-        { { 0xc2fd373748e2b156l,0x259e9a98139645bel,0xe90106fb9877b4f1l,
-            0x49e5bac5889ce002l },
-          { 0x936a7dd18cf14e0bl,0x70bf6d304e3a8a01l,0x99d3e8bfeb748b62l,
-            0xa52a27c99b31c55cl },
-          0 },
-        /* 89 << 232 */
-        { { 0x9db1d41d300637d5l,0xe38744397c2dd836l,0x36179baf0d04ceb3l,
-            0xe9ccd17b251b3f2dl },
-          { 0xd8228073442b6d1dl,0x59a038363eed2971l,0xb443732046979f5cl,
-            0x54ad4113ae63937cl },
-          0 },
-        /* 95 << 232 */
-        { { 0x092c34e6d9246e9fl,0xb4b3b63d3eeb18a7l,0x8b3778beed9d1383l,
-            0xe4cb7be9d70d5d80l },
-          { 0xcff12e9b3d059203l,0x277af117ba86699fl,0x9bd4e8e363603585l,
-            0x0750b0f28e89c8d5l },
-          0 },
-        /* 101 << 232 */
-        { { 0x38b77e5958f7187bl,0x31c7068de0cb618el,0xa0f8e0d6c11ebe62l,
-            0x07adc8010473d7ebl },
-          { 0x36161a2c5c3e9510l,0xb2ec90d64ad04815l,0x01e2dd1f917d8166l,
-            0x549bcbdd6aa0f794l },
-          0 },
-        /* 107 << 232 */
-        { { 0x4ab27c3a8e4e45e5l,0xf6bd9d82f2bb99e7l,0xcab48c735e9da59fl,
-            0xdeb09eb2b9727353l },
-          { 0xc4a7954bafb8fa3el,0x34af2a49abf6803dl,0xc1ee1416d63e13bbl,
-            0xd49bf42d7a949193l },
-          0 },
-        /* 113 << 232 */
-        { { 0x504823ea9c9c07c6l,0x9dbec902bee2288cl,0x018d7875f0ceb6bbl,
-            0x678b997304f7022cl },
-          { 0x74d658238c5fb369l,0x7d4e1f114ca89ee8l,0x148316399905abc0l,
-            0xc107324e2c4deff4l },
-          0 },
-        /* 116 << 232 */
-        { { 0x1bc4fa8bdadc4404l,0x0edb9534daa12ee3l,0x084481b6a5f7289cl,
-            0x7f42461d9d8fb3d2l },
-          { 0xf93f1d3212293c70l,0xc14706596bb73ea3l,0xf80834afde339cadl,
-            0x99dcfc0081f22953l },
-          0 },
-        /* 119 << 232 */
-        { { 0x497e544f9fca737el,0x7f6342210e91e1afl,0x638e500c78d7b20bl,
-            0xb1ffed3f7ebaa947l },
-          { 0x751aa54871086f83l,0x8100bb703cf97848l,0xc32f91ace19ad68fl,
-            0x7dffb6851fb9157el },
-          0 },
-        /* 125 << 232 */
-        { { 0x5108589778e25060l,0x33e3cb7316cfe6cbl,0x0884cb8d410c0822l,
-            0xaa806ecc0be3fc94l },
-          { 0x9f9121f5f692353el,0xb9ab0310f8ee3349l,0x390032ce2561973el,
-            0xc07b6c6c8856b766l },
-          0 },
-    },
-    {
-        /* 0 << 240 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 240 */
-        { { 0x1083e2ea1f095615l,0x0a28ad7714e68c33l,0x6bfc02523d8818bel,
-            0xb585113af35850cdl },
-          { 0x7d935f0b30df8aa1l,0xaddda07c4ab7e3acl,0x92c34299552f00cbl,
-            0xc33ed1de2909df6cl },
-          0 },
-        /* 3 << 240 */
-        { { 0xabe7905a83cdd60el,0x50602fb5a1170184l,0x689886cdb023642al,
-            0xd568d090a6e1fb00l },
-          { 0x5b1922c70259217fl,0x93831cd9c43141e4l,0xdfca35870c95f86el,
-            0xdec2057a568ae828l },
-          0 },
-        /* 4 << 240 */
-        { { 0x568f8925913cc16dl,0x18bc5b6de1a26f5al,0xdfa413bef5f499ael,
-            0xf8835decc3f0ae84l },
-          { 0xb6e60bd865a40ab0l,0x65596439194b377el,0xbcd8562592084a69l,
-            0x5ce433b94f23ede0l },
-          0 },
-        /* 5 << 240 */
-        { { 0x860d523d42e06189l,0xbf0779414e3aff13l,0x0b616dcac1b20650l,
-            0xe66dd6d12131300dl },
-          { 0xd4a0fd67ff99abdel,0xc9903550c7aac50dl,0x022ecf8b7c46b2d7l,
-            0x3333b1e83abf92afl },
-          0 },
-        /* 7 << 240 */
-        { { 0xefecdef7be42a582l,0xd3fc608065046be6l,0xc9af13c809e8dba9l,
-            0x1e6c9847641491ffl },
-          { 0x3b574925d30c31f7l,0xb7eb72baac2a2122l,0x776a0dacef0859e7l,
-            0x06fec31421900942l },
-          0 },
-        /* 9 << 240 */
-        { { 0x7ec62fbbf4737f21l,0xd8dba5ab6209f5acl,0x24b5d7a9a5f9adbel,
-            0x707d28f7a61dc768l },
-          { 0x7711460bcaa999eal,0xba7b174d1c92e4ccl,0x3c4bab6618d4bf2dl,
-            0xb8f0c980eb8bd279l },
-          0 },
-        /* 10 << 240 */
-        { { 0x9d658932790691bfl,0xed61058906b736ael,0x712c2f04c0d63b6el,
-            0x5cf06fd5c63d488fl },
-          { 0x97363facd9588e41l,0x1f9bf7622b93257el,0xa9d1ffc4667acacel,
-            0x1cf4a1aa0a061ecfl },
-          0 },
-        /* 11 << 240 */
-        { { 0x28d675b2c0519a23l,0x9ebf94fe4f6952e3l,0xf28bb767a2294a8al,
-            0x85512b4dfe0af3f5l },
-          { 0x18958ba899b16a0dl,0x95c2430cba7548a7l,0xb30d1b10a16be615l,
-            0xe3ebbb9785bfb74cl },
-          0 },
-        /* 13 << 240 */
-        { { 0x81eeb865d2fdca23l,0x5a15ee08cc8ef895l,0x768fa10a01905614l,
-            0xeff5b8ef880ee19bl },
-          { 0xf0c0cabbcb1c8a0el,0x2e1ee9cdb8c838f9l,0x0587d8b88a4a14c0l,
-            0xf6f278962ff698e5l },
-          0 },
-        /* 15 << 240 */
-        { { 0x9c4b646e9e2fce99l,0x68a210811e80857fl,0x06d54e443643b52al,
-            0xde8d6d630d8eb843l },
-          { 0x7032156342146a0al,0x8ba826f25eaa3622l,0x227a58bd86138787l,
-            0x43b6c03c10281d37l },
-          0 },
-        /* 16 << 240 */
-        { { 0x02b37a952f41deffl,0x0e44a59ae63b89b7l,0x673257dc143ff951l,
-            0x19c02205d752baf4l },
-          { 0x46c23069c4b7d692l,0x2e6392c3fd1502acl,0x6057b1a21b220846l,
-            0xe51ff9460c1b5b63l },
-          0 },
-        /* 17 << 240 */
-        { { 0x7aca2632f02fc0f0l,0xb92b337dc7f01c86l,0x624bc4bf5afbdc7dl,
-            0x812b07bc4de21a5el },
-          { 0x29d137240b2090ccl,0x0403c5095a1b2132l,0x1dca34d50e35e015l,
-            0xf085ed7d3bbbb66fl },
-          0 },
-        /* 19 << 240 */
-        { { 0xc27b98f9f781e865l,0x51e1f692994e1345l,0x0807d516e19361eel,
-            0x13885ceffb998aefl },
-          { 0xd223d5e92f0f8a17l,0x48672010e8d20280l,0x6f02fd60237eac98l,
-            0xcc51bfad9ada7ee7l },
-          0 },
-        /* 21 << 240 */
-        { { 0x2756bcdd1e09701dl,0x94e31db990d45c80l,0xb9e856a98566e584l,
-            0x4f87d9deab10e3f3l },
-          { 0x166ecb373ded9cb2l,0xfd14c7073f653d3el,0x105d049b92aec425l,
-            0x7f657e4909a42e11l },
-          0 },
-        /* 23 << 240 */
-        { { 0xea6490076a159594l,0x3e424d6b1f97ce52l,0xac6df30a185e8ccbl,
-            0xad56ec80517747bfl },
-          { 0xf0935ccf4391fe93l,0x866b260f03811d40l,0x792047b99f7b9abel,
-            0xb1600bc88ee42d84l },
-          0 },
-        /* 25 << 240 */
-        { { 0x2d97b3db7768a85fl,0x2b78f6334287e038l,0x86c947676f892bb1l,
-            0x920bfb1ac0a9c200l },
-          { 0x4292f6ec332041b2l,0xa30bb937c9989d54l,0x39f941ebc6d5879el,
-            0x76a450fcdfdbb187l },
-          0 },
-        /* 27 << 240 */
-        { { 0x31256089ee430db6l,0xaece9bd8f6836f56l,0x484cfc4bfb85a046l,
-            0xee1e3e2c1599b2b9l },
-          { 0x7e3c38903d122eafl,0xaa940ce0c770556cl,0x4802d6631b08fae8l,
-            0xb08a85807f69f8bal },
-          0 },
-        /* 28 << 240 */
-        { { 0x70ed0a0405411eael,0x60deb08f16494c66l,0x8cf20fc6133797bbl,
-            0x3e30f4f50c6bc310l },
-          { 0x1a677c29749c46c7l,0xfe1d93f4f11e981cl,0x937303d82e3e688bl,
-            0x01aef5a7a6aa9e85l },
-          0 },
-        /* 29 << 240 */
-        { { 0x4902f495b959b920l,0x13b0fdbdfca2d885l,0x41cbd9e7b6a2f0fal,
-            0xf9bdf11056430b87l },
-          { 0xd705a223954d19b9l,0x74d0fc5c972a4fdel,0xcbcbfed6912977eal,
-            0x870611fdcc59a5afl },
-          0 },
-        /* 31 << 240 */
-        { { 0xf4f19bd04089236al,0x3b206c12313d0e0bl,0x73e70df303feaeb2l,
-            0x09dba0eb9bd1efe0l },
-          { 0x4c7fd532fc4e5305l,0xd792ffede93d787al,0xc72dc4e2e4245010l,
-            0xe7e0d47d0466bbbdl },
-          0 },
-        /* 33 << 240 */
-        { { 0x549c861983e4f8bbl,0xf70133fbd8e06829l,0xc962b8e28c64e849l,
-            0xad87f5b1901e4c25l },
-          { 0xd005bde568a1cab5l,0x6a591acf0d2a95bal,0x728f14ce30ebcae4l,
-            0x303cec99a3459b0fl },
-          0 },
-        /* 34 << 240 */
-        { { 0x62e62f258350e6bcl,0x5a5ea94d96adba1fl,0x36c2a2844a23c7b3l,
-            0x32f50a72992f5c8bl },
-          { 0x55d685204136c6afl,0x1aafd32992794f20l,0x69f5d820b59aa9bfl,
-            0x218966a8570e209al },
-          0 },
-        /* 35 << 240 */
-        { { 0xf3204feb2f9a31fcl,0x77f33a360429f463l,0xfb9f3a5a59a1d6a7l,
-            0x4445a2e93b1a78e0l },
-          { 0xc77a9b6fd58e32d3l,0xa44e23c8302e6390l,0x7d8e00b4c0f7bcb0l,
-            0xd2e2237b0ffa46f4l },
-          0 },
-        /* 36 << 240 */
-        { { 0xb3046cb13c8ea6d3l,0xf0151b5efce2f445l,0xa968e60b55e5715el,
-            0x39e52662587dce61l },
-          { 0xfde176e0b7de2862l,0x298d83e68e8db497l,0x1042136773641bfbl,
-            0xd72ac78d36e0bb0dl },
-          0 },
-        /* 37 << 240 */
-        { { 0x2cabb94fff6b8340l,0xf425a35a21771acbl,0x564fec3d12c4a758l,
-            0x57a61af39ba8f281l },
-          { 0x5807e78c97e9a71dl,0x991d9be75b8314e6l,0x1cd90b16ec4133b9l,
-            0xff043efa0f1ac621l },
-          0 },
-        /* 39 << 240 */
-        { { 0xea6e5527d7e58321l,0xfb95c13c04056ff1l,0x9447361f2fc4e732l,
-            0x63cbc655786d0154l },
-          { 0x302c0d668610fb71l,0xbf692d6920d06613l,0x8465b74b4be8355al,
-            0xcc883c95c31356b7l },
-          0 },
-        /* 40 << 240 */
-        { { 0x4ab6e919b33eabcal,0xb58f0998a1acacbfl,0xa747e5782ddbc28fl,
-            0xf9dd04ca59866cbcl },
-          { 0x084c062ff7a0073fl,0x6d22acdfb577fc38l,0x0870ee08eacd907cl,
-            0x710b4b266c9fcf95l },
-          0 },
-        /* 41 << 240 */
-        { { 0xa99546faf1c835a7l,0x1514a5a30d59f933l,0x1f6ad0f81bedd730l,
-            0x24de76287b528aaal },
-          { 0x4d9e7845c02fff87l,0xba74f8a942c79e67l,0x5bf5015f476e285bl,
-            0x0b1a5d8b1b93b364l },
-          0 },
-        /* 43 << 240 */
-        { { 0x8c7c0d7ff839819fl,0xc82b819827a95965l,0xce7294d377270519l,
-            0xfb508d6cad47aff7l },
-          { 0xf6de15431035076al,0x697d60ac5dd465c6l,0x88d771b8a76dcd26l,
-            0x8c7ce11ab10c9c44l },
-          0 },
-        /* 44 << 240 */
-        { { 0x215ea44a08216060l,0xccfa18a187996cf6l,0xccfb2483f7eccdd2l,
-            0x07aa601ad453c66al },
-          { 0xd43cf263cffee9e2l,0x230bc099718f69bfl,0xc43de21300c193e8l,
-            0x94cf251799c8746fl },
-          0 },
-        /* 45 << 240 */
-        { { 0x4785d7f87d1320c5l,0x84bed8c3d0771dcbl,0xff28044d22254edbl,
-            0x2e5992a445f71504l },
-          { 0xcb92695b72bbf5cdl,0x9bcbde35c42422e5l,0x856594fd1d07ed86l,
-            0x3aaf0b717716b4ffl },
-          0 },
-        /* 46 << 240 */
-        { { 0x3edf24f9eebed405l,0x9e3141360eccb503l,0xf7704c25b85c2bc2l,
-            0x4cb7c1de9a3247eel },
-          { 0x798ac8f2f0b507c5l,0x6e6217206851bbf1l,0xc0b89398c0d9ed16l,
-            0xf7d5d2a09f20728fl },
-          0 },
-        /* 47 << 240 */
-        { { 0x7358a94a19f0ededl,0x5e08c4c3e32ccfbbl,0x84a8eeeb0089f071l,
-            0xdaf0514c41fc436el },
-          { 0x30fe216f310309afl,0xe72f77bd564e6fc9l,0xe7ef3bddfdc59fd5l,
-            0xd199b1c9a8e1169cl },
-          0 },
-        /* 48 << 240 */
-        { { 0xb9dc857c5b0f7bd4l,0x6990c2c9108ea1cdl,0x84730b83b984c7a9l,
-            0x552723d2eab18a78l },
-          { 0x9752c2e2919ba0f9l,0x075a3bd94bf40890l,0x71e52a04a6d98212l,
-            0x3fb6607a9f18a4c8l },
-          0 },
-        /* 49 << 240 */
-        { { 0xa0305d01e8c3214dl,0x025b3cae8d51cea3l,0xeeaf7ab239923274l,
-            0x51179407c876b72cl },
-          { 0xcf0241c7d4549a68l,0xffae7f4c793dab3dl,0xdfb5917b4bdf2280l,
-            0xcf25c870a652e391l },
-          0 },
-        /* 51 << 240 */
-        { { 0xb1345466b922e1c8l,0xae42f46ab5bf8a34l,0x1e1ab6053310e604l,
-            0x64093cd9b4d7a658l },
-          { 0x5d3b385ab3d9242cl,0x2225b99ae56f8ec7l,0x19a8cbfc9a916e11l,
-            0x11c5df831f957c03l },
-          0 },
-        /* 52 << 240 */
-        { { 0x09f1d04af381147bl,0x7be13628b26b345fl,0xd8371966d1c60b78l,
-            0xf1743c2c5d91808fl },
-          { 0x8a2966acafc71cc3l,0x0ba9702efdfc24c3l,0x60c80158e6fbb539l,
-            0x58eaee49812c32f4l },
-          0 },
-        /* 53 << 240 */
-        { { 0x31af7f5ee89d0b84l,0xa776dada6caa110bl,0xd67b7891df6d54ddl,
-            0x831613cab82b8a5cl },
-          { 0x7a4eb86ef020af6dl,0x2914fd11bd795a7bl,0xc038a273fcb54a17l,
-            0x6b2dc8e18219cc75l },
-          0 },
-        /* 55 << 240 */
-        { { 0x031fc875464ba9b5l,0xe268cf45bd812dd3l,0x443f57defbfb664al,
-            0xfd1a38544e28c2fal },
-          { 0xb8799782cb96515bl,0xa12d3e3f1138c95dl,0x0cc5ee117748ee57l,
-            0x6ab167cf955a7dfcl },
-          0 },
-        /* 57 << 240 */
-        { { 0x0d54aaca4dc1c74fl,0x74af1807bf2e0d61l,0x151254f87aebe0f1l,
-            0x4072f38bf6376095l },
-          { 0x31ebe17a26646abfl,0xdc8cb6b40ecc1282l,0x4f6326bbbc095a66l,
-            0x37dad65a0363636dl },
-          0 },
-        /* 59 << 240 */
-        { { 0xc851860a70f8c15al,0xb2d4555488368381l,0xbfd46e197019c7b6l,
-            0xa1a9b12f6bb6f33bl },
-          { 0xecfd5fe6f170c82bl,0x6d58bb52d601afc3l,0xb8b3de15fe6eb102l,
-            0xad07336886a47964l },
-          0 },
-        /* 60 << 240 */
-        { { 0x89f514c91911840fl,0xc9fa6b504cc106bcl,0x70a97f0dfe55b4f1l,
-            0xada6306be5888609l },
-          { 0xa9437881c6dc8d15l,0x0fc0f5368411f3dfl,0xd26162087a913dd2l,
-            0x4fe1c7c4e92848cdl },
-          0 },
-        /* 61 << 240 */
-        { { 0xaa18eb262e07383dl,0xb948c35c34e90f3dl,0x95e97f81d3653565l,
-            0x4a821a2687b5b75dl },
-          { 0x87b4d81c892db882l,0xa69e65d689f3bfadl,0xe475f532eb371cacl,
-            0xd8cc23fa17194d5dl },
-          0 },
-        /* 63 << 240 */
-        { { 0x3fc0052ad789d484l,0xe8c67aac29324323l,0x133fd07cf54c43d3l,
-            0xd4a0848fb91d4faal },
-          { 0xf683ce065ea5098fl,0xe84348f9887c8a76l,0x38f8c2cf79b224b6l,
-            0x327e4c534a818cb1l },
-          0 },
-        /* 64 << 240 */
-        { { 0xb6d92a7f3e5f9f11l,0x9afe153ad6cb3b8el,0x4d1a6dd7ddf800bdl,
-            0xf6c13cc0caf17e19l },
-          { 0x15f6c58e325fc3eel,0x71095400a31dc3b2l,0x168e7c07afa3d3e7l,
-            0x3f8417a194c7ae2dl },
-          0 },
-        /* 65 << 240 */
-        { { 0x0c9e9237d5f812bcl,0xdae5b7e9595f02e5l,0x5ec1dece42b1e9a8l,
-            0x506a6ef8e527a685l },
-          { 0xe3049290236af251l,0x6322dd1bf81970acl,0x1459d39c516d5e61l,
-            0x672f502d9455b694l },
-          0 },
-        /* 71 << 240 */
-        { { 0xf83788e06b228af2l,0xaafc823911f596fal,0x6d47fa592f0fcb13l,
-            0x0b7af65f1c99c5d4l },
-          { 0xbc4c185dca961e6fl,0xec02b09f158481a4l,0x4bbfd9f31423fdd4l,
-            0x0ff44a53b619644bl },
-          0 },
-        /* 77 << 240 */
-        { { 0x23e255a3ea3f59d8l,0x1f4a47a8261ac30bl,0x346bf409c8faf0b3l,
-            0xd13e73fbc03a226bl },
-          { 0x670ddc792fe8a79bl,0x335fa172f1aac412l,0xe2347de1a5ceff20l,
-            0x66e02c73381130f2l },
-          0 },
-        /* 83 << 240 */
-        { { 0xa6b874c51db717cdl,0x027d318ab00f160bl,0x578f89f49be791afl,
-            0x659ef2f01f3b5e9bl },
-          { 0xa0c593033835d84cl,0xb71e261fdb6f9a60l,0x65837c7f44b7813fl,
-            0xea776163ea4bcc96l },
-          0 },
-        /* 89 << 240 */
-        { { 0x208234118df3f15fl,0xe0514d4694f341acl,0xdc66282d6486d704l,
-            0xd5fb354ad2548389l },
-          { 0xf3e98d72df273295l,0x27ded7fa50cd09fcl,0x4f486af3c5c1c169l,
-            0xe51044150aa41ba3l },
-          0 },
-        /* 95 << 240 */
-        { { 0x66b14d296fce0aecl,0x35fe5e60c8915ceal,0x06a023b736c5da39l,
-            0x0977c9f0404e932fl },
-          { 0x1dd6f95db54866del,0xe5ec79359387430cl,0x98dee57b5ef42e67l,
-            0x1707f01912ed3ad0l },
-          0 },
-        /* 101 << 240 */
-        { { 0xeb3abdedeec82495l,0x587a696e764a41c7l,0x13fdcce2add1a6a3l,
-            0x299a0d43286b2162l },
-          { 0x2c4e71e18131f1b4l,0x48f0e806ada3d04fl,0x91d2de80c57491b2l,
-            0x1b1266236cc355cbl },
-          0 },
-        /* 107 << 240 */
-        { { 0xdc28afe5a6d44444l,0xb5ad8d3cfe0b947bl,0x50c6126c96ce9fb9l,
-            0x5384a998d1fc7d39l },
-          { 0xa43ff8898788f51cl,0x30359593a6bc7b87l,0x3e1691dccc0d019al,
-            0xda0ef5ad7943abcdl },
-          0 },
-        /* 113 << 240 */
-        { { 0x5bc58b6f020b5cd7l,0x9098e202e103ff4el,0xc1f1a3d9f6fce7c7l,
-            0xf9dc32a856090ccel },
-          { 0x4c7d2520a9cc3b09l,0x98d47b5dd8c4dfcel,0xdcee788297e689b4l,
-            0xe5eec71815f982b9l },
-          0 },
-        /* 116 << 240 */
-        { { 0xff154bb8a1e1538cl,0xb9883276f7dcfae9l,0x1ac0a4d2c1c8cba4l,
-            0x511a54cc76e6b284l },
-          { 0xe2da436f00011f6dl,0x4d357a190f43a8adl,0xf36899c95458655bl,
-            0xe5f75c768d613ed9l },
-          0 },
-        /* 119 << 240 */
-        { { 0x15b4af1d93f12ef8l,0x3f4c5868fd032f88l,0x39f67a08f27d86bdl,
-            0x2f551820da32db6bl },
-          { 0x72fe295ac2c16214l,0x39927c381a2cf9afl,0x8dda23d6b1dc1ae7l,
-            0x1209ff3ed32071d4l },
-          0 },
-        /* 125 << 240 */
-        { { 0x861fdceb9a3c6c6fl,0x76d7a01386778453l,0xbf8d147cd5e422cbl,
-            0xd16f532e51772d19l },
-          { 0x72025ee2570d02cdl,0xe8e7737be80c7664l,0x81b7d56c334a8d8fl,
-            0x42477a0ff1b79308l },
-          0 },
-    },
-    {
-        /* 0 << 248 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 248 */
-        { { 0xf306a3c8ee3c76cbl,0x3cf11623d32a1f6el,0xe6d5ab646863e956l,
-            0x3b8a4cbe5c005c26l },
-          { 0xdcd529a59ce6bb27l,0xc4afaa5204d4b16fl,0xb0624a267923798dl,
-            0x85e56df66b307fabl },
-          0 },
-        /* 3 << 248 */
-        { { 0x896895959884aaf7l,0xb1959be307b348a6l,0x96250e573c147c87l,
-            0xae0efb3add0c61f8l },
-          { 0xed00745eca8c325el,0x3c911696ecff3f70l,0x73acbc65319ad41dl,
-            0x7b01a020f0b1c7efl },
-          0 },
-        /* 4 << 248 */
-        { { 0x9910ba6b23a5d896l,0x1fe19e357fe4364el,0x6e1da8c39a33c677l,
-            0x15b4488b29fd9fd0l },
-          { 0x1f4392541a1f22bfl,0x920a8a70ab8163e8l,0x3fd1b24907e5658el,
-            0xf2c4f79cb6ec839bl },
-          0 },
-        /* 5 << 248 */
-        { { 0x262143b5224c08dcl,0x2bbb09b481b50c91l,0xc16ed709aca8c84fl,
-            0xa6210d9db2850ca8l },
-          { 0x6d8df67a09cb54d6l,0x91eef6e0500919a4l,0x90f613810f132857l,
-            0x9acede47f8d5028bl },
-          0 },
-        /* 7 << 248 */
-        { { 0x45e21446de673629l,0x57f7aa1e703c2d21l,0xa0e99b7f98c868c7l,
-            0x4e42f66d8b641676l },
-          { 0x602884dc91077896l,0xa0d690cfc2c9885bl,0xfeb4da333b9a5187l,
-            0x5f789598153c87eel },
-          0 },
-        /* 9 << 248 */
-        { { 0xb19b1c4fca66eca8l,0xf04a20b55663de54l,0x42a29a33c223b617l,
-            0x86c68d0d44827e11l },
-          { 0x71f90ddeadba1206l,0xeeffb4167a6ceeeal,0x9e302fbac543e8afl,
-            0xcf07f7471aa77b96l },
-          0 },
-        /* 10 << 248 */
-        { { 0xcf57fca29849e95bl,0x96e9793ed510053cl,0x89fa443d07d3e75el,
-            0xfe2bc235e52800a0l },
-          { 0x1c208b8c0ac7e740l,0xb5852a49e7222263l,0x217e4005e541e592l,
-            0xee52747dc960b0e1l },
-          0 },
-        /* 11 << 248 */
-        { { 0x5fd7cafb475952afl,0x23a6d71954a43337l,0xa83a7523b1617941l,
-            0x0b7f35d412b37dd4l },
-          { 0x81ec51292ae27eafl,0x7ca92fb3318169dfl,0xc01bfd6078d0875al,
-            0xcc6074e3c99c436el },
-          0 },
-        /* 13 << 248 */
-        { { 0x4ca6bdebf57912b8l,0x9a17577e98507b5al,0x8ed4ab7759e51dfcl,
-            0x103b7b2a470f5a36l },
-          { 0x0c8545ac12553321l,0xab5861a760482817l,0xf4b5f602b9b856cfl,
-            0x609955787adf2e5fl },
-          0 },
-        /* 15 << 248 */
-        { { 0x60ce25b1ee5cb44fl,0xddcc7d182c2d7598l,0x1765a1b301847b5cl,
-            0xf5d9c3635d0d23b7l },
-          { 0x42ff1ba7928b65d0l,0x587ac69d6148e043l,0x3099be0dd320390bl,
-            0xa7b88dfc4278329fl },
-          0 },
-        /* 16 << 248 */
-        { { 0x80802dc91ec34f9el,0xd8772d3533810603l,0x3f06d66c530cb4f3l,
-            0x7be5ed0dc475c129l },
-          { 0xcb9e3c1931e82b10l,0xc63d2857c9ff6b4cl,0xb92118c692a1b45el,
-            0x0aec44147285bbcal },
-          0 },
-        /* 17 << 248 */
-        { { 0x7685bb9e0ba4e0b7l,0x330a7ebc5e58c29bl,0xbc1d9173e8a3797al,
-            0x7c506a16ea60f86cl },
-          { 0x9defb9248c099445l,0xcf1ddcc0256df210l,0x4844ce293d07e990l,
-            0x92318e37e2628503l },
-          0 },
-        /* 19 << 248 */
-        { { 0x61acd597fdf968d7l,0x7321a8b26598c381l,0xcb86a2809f448a0cl,
-            0x38534a01855df66al },
-          { 0xc119ec141e29037fl,0xe23c20ad0b42ba67l,0xefb1c4e033fb4f22l,
-            0xf088358f445a5032l },
-          0 },
-        /* 21 << 248 */
-        { { 0x2d73f5d1b8475744l,0xcc297e0a9d399b06l,0xa8c61d4038d3df06l,
-            0xacc6e8651a2d27a0l },
-          { 0x63dd6f6230153bf2l,0x6b23ad7bd73b83b7l,0x25382bf767ff7dcdl,
-            0x7e268c8fcf7ce2d1l },
-          0 },
-        /* 23 << 248 */
-        { { 0x4b9161c3cb2ebef1l,0x6009716b669ed801l,0x97c65219aacefe44l,
-            0xde13597d71aae4b5l },
-          { 0x3a077a816141d651l,0xe1b4e80129f876eal,0x729aed6d5c00c96cl,
-            0x0c6f404374cc645el },
-          0 },
-        /* 25 << 248 */
-        { { 0x22c51812df5a66e1l,0x1c8069c9ae7dedeal,0xcff9d86f0eea5180l,
-            0x676dbd6f44235ddal },
-          { 0xa53f01383db1ad42l,0xd079e571bcf19029l,0x1e37b9ecfab0cf82l,
-            0x93ae35ed4844e9c4l },
-          0 },
-        /* 27 << 248 */
-        { { 0xdaee55a543756358l,0x0ace18d41b2d3f89l,0x3391fa36824dd7d4l,
-            0x7b9963d1770e5f3fl },
-          { 0xc1fb9a78c94f724dl,0x94ff86fe76c4da6bl,0xb5d928c64170609bl,
-            0xc9372becfb015a9fl },
-          0 },
-        /* 28 << 248 */
-        { { 0x9c34b650e16e05e9l,0x965a774094e74640l,0xa3fd22fbcea3f029l,
-            0x1eb6a9688f95277cl },
-          { 0x2520a63d7bad84f6l,0xad917201f58f2feel,0xea92c1669b840d48l,
-            0x12109c4aacef5cbdl },
-          0 },
-        /* 29 << 248 */
-        { { 0xd85850d0d407a252l,0x6fa3b14de63909d4l,0x2ff9f6593e0fba69l,
-            0x7f9fd2a2d1b2cd0bl },
-          { 0x611233d745ad896al,0xfe4211648df850f9l,0x7808832399e32983l,
-            0x4b040859dee6741dl },
-          0 },
-        /* 31 << 248 */
-        { { 0x7dd2afd456e1ed5cl,0xd48429ec41ba4992l,0x97a02188968bab27l,
-            0x09ecf813e63c4168l },
-          { 0xf4ac65e77288b10cl,0x10630ab2afac7410l,0x4e3e59c3bb049e56l,
-            0x25972fff40fea0b1l },
-          0 },
-        /* 33 << 248 */
-        { { 0xfd8363da98365c18l,0x8aa57b1a8d47bf91l,0x423dce57695f4dd6l,
-            0xfccf54d4cc17f034l },
-          { 0x8fdba27c3610ea51l,0xcc0a06d654306b06l,0xb97a121c389b9dfdl,
-            0x7dbb90eb1ed0ca42l },
-          0 },
-        /* 34 << 248 */
-        { { 0xd32d7cec0094e84cl,0x862ae25e2ece8f72l,0x8644ef1cdfceb8abl,
-            0x68a9969c8e225628l },
-          { 0xdf209e27b3117876l,0x308a6e1882ba242bl,0xcbd09a659bf0cdb6l,
-            0x79f2826cc85b9705l },
-          0 },
-        /* 35 << 248 */
-        { { 0x3b36b6bf8f011496l,0xea6acc1a9bcf6ef8l,0x6db132263b101f12l,
-            0x4fc4e35e3b7585c3l },
-          { 0x641de27556eb64c6l,0x9b2834d3f3b08519l,0xebb76a2ba1f44b40l,
-            0x1b545ccd3cd31677l },
-          0 },
-        /* 36 << 248 */
-        { { 0xab293027aad991c1l,0x598d0bf8849be4b7l,0x8c94a21ab972da90l,
-            0xada4cfdd7ecfa840l },
-          { 0x93d4b9c0fbcec63al,0x7ca617a203219a34l,0x900424eb6a652a55l,
-            0xaf9346e9eb8562e0l },
-          0 },
-        /* 37 << 248 */
-        { { 0x9681a73d2d8bc904l,0x8b5f9b317b1553bel,0xfb03b874f6bc852fl,
-            0x8e658fb8cbbec8b0l },
-          { 0x9b2ff17bb9e9f9d1l,0xf46e9bf3e8679854l,0x7fbb1323618ed3aal,
-            0x064a1c5d714ebc3dl },
-          0 },
-        /* 39 << 248 */
-        { { 0xac0bdfc39f0e69dcl,0x71957386ae12f132l,0xa263ef2e6aa90b5bl,
-            0xa94b152390d42976l },
-          { 0xfb2d17741bcdbf7bl,0xba77b77c3a04f72fl,0xa6818ed8ec3e25a1l,
-            0x2e0e01743733e251l },
-          0 },
-        /* 40 << 248 */
-        { { 0xc3e04d7902381461l,0xb1643ab5911bc478l,0xc92becfa390b3ef2l,
-            0x54476778acd2f1b6l },
-          { 0x8daa0c4d66bf3aafl,0x2bc1287b2c21c65al,0xee182910b5a13ac3l,
-            0xbb04730090b0790al },
-          0 },
-        /* 41 << 248 */
-        { { 0x8bdd6f35a8540489l,0x788c03e5ee390d4el,0x203323c18f653017l,
-            0x39953308c4bc0094l },
-          { 0x6ee0857118308d0bl,0x70e9f90b450b0002l,0x191662aa8139f145l,
-            0xd7c5415b62d71124l },
-          0 },
-        /* 43 << 248 */
-        { { 0x41b37d72b927231cl,0xca17b5429e4de13al,0x7bc03469cded2ce3l,
-            0x961b0ecb4f4560f9l },
-          { 0x7c5bd41b43d31fa1l,0x3ed047f643f44dc3l,0x5b02083efe1a4d14l,
-            0xcc2c66ac18b330bcl },
-          0 },
-        /* 44 << 248 */
-        { { 0x83766947d17d4e0bl,0xc5772beefdc3a47bl,0x765a50db1a6fd0ffl,
-            0x17f904ba45b0995el },
-          { 0xcee643832883487el,0xf56db7f3c270aaedl,0x6738d94f46cb1fd9l,
-            0xc8fa426a142fd4d5l },
-          0 },
-        /* 45 << 248 */
-        { { 0xc85bef5b5a78efcel,0xaf380c6b0580e41el,0x6c093256a43b8d9bl,
-            0xed9d07bbea670933l },
-          { 0xfdb9a295f1682c6el,0x4cc29a63532b6bb7l,0x21a918f9f8e42dd0l,
-            0x9ac935ce0edacca0l },
-          0 },
-        /* 46 << 248 */
-        { { 0xbfe48a8ff43daf9dl,0xd7799b31b313c052l,0x46d480d77119c60el,
-            0x5090d91f0b80bcb9l },
-          { 0xc94c4c1e873bd7bfl,0x16e69b4f9915aa0al,0x769be02bb1d5928cl,
-            0x3fdaf62162e1d85al },
-          0 },
-        /* 47 << 248 */
-        { { 0x03497a57371c1b5cl,0x11e4c0b3552ab6abl,0xf857061f0a169ee7l,
-            0xc21c6c43e6d1bc66l },
-          { 0x706283a82832be7al,0xd35b143299aba62cl,0x7f4da83de9aef62dl,
-            0x2b7e5fc8723fa4e5l },
-          0 },
-        /* 48 << 248 */
-        { { 0xae485bb72b724759l,0x945353e1b2d4c63al,0x82159d07de7d6f2cl,
-            0x389caef34ec5b109l },
-          { 0x4a8ebb53db65ef14l,0x2dc2cb7edd99de43l,0x816fa3ed83f2405fl,
-            0x73429bb9c14208a3l },
-          0 },
-        /* 49 << 248 */
-        { { 0xc086e737eb4cfa54l,0x9400e1ad3c44aad9l,0x210bba94336959b4l,
-            0x08621a809106f0cal },
-          { 0x2ae66096c510ee9cl,0x2ba21617fc76a895l,0xc0707f8b0c186f1el,
-            0x1fe170a3ed0bfe25l },
-          0 },
-        /* 51 << 248 */
-        { { 0x3780fe2084759c5cl,0x716ec626b7050aa7l,0x6a43fb8b84b63bd1l,
-            0xb01098a039bc449fl },
-          { 0x96b3ff8ebb7daa4dl,0x2d146882654a7f01l,0x2500f701dcae6143l,
-            0xc13d51d01626fd3bl },
-          0 },
-        /* 52 << 248 */
-        { { 0x08ed8febd56daf06l,0x8d98277b4a837f69l,0x9947c636a9b6e05al,
-            0x58c8a77ac0d58abdl },
-          { 0xf45496a45f121e4fl,0x16cd67c71076d3d3l,0xecbd1958e3fb0c5dl,
-            0xfbe185ec38e1eb47l },
-          0 },
-        /* 53 << 248 */
-        { { 0x65b067eb740216e3l,0x1e19a71479db8760l,0x8d30dca18878de5al,
-            0x627d03e8aa47c005l },
-          { 0x096d58c0d2536c96l,0x232e6a4d69b12c2al,0x850eb8c0e7044bcel,
-            0xd9cf923bef2ee9a1l },
-          0 },
-        /* 55 << 248 */
-        { { 0x8b301094c8eaee90l,0x9a96950b8330928fl,0x472ba105faccc3bal,
-            0x00f8620e9153172al },
-          { 0x019b8164303fcdf5l,0x614d5c3c41fb4c73l,0x632d98f2c5992f89l,
-            0xfbeb29d790e2dea5l },
-          0 },
-        /* 57 << 248 */
-        { { 0xefd48b577f91d6e0l,0x8575605595bcf5d4l,0x7677b4a7bb9d891bl,
-            0xdc9931e9685912c9l },
-          { 0x69bca306f31a07c8l,0x3dd729534962a7f0l,0xdcea49cc9d366c2al,
-            0xce664ba7dc79a57dl },
-          0 },
-        /* 59 << 248 */
-        { { 0x7842d547013ec3b5l,0xa2785ceb433cf990l,0x9d667e5f700ab14al,
-            0x4b46f362a0f46d55l },
-          { 0x152c0e80cc7a3487l,0x7f3a88cef86f5e68l,0x6f950a73f1b2a75fl,
-            0x9be5b1aa51d24f3bl },
-          0 },
-        /* 60 << 248 */
-        { { 0xaea68626dc4ad4f4l,0x5dc516824ddbc0b6l,0xa76697bd602e9065l,
-            0xbeeb3ea58c37888el },
-          { 0x1ec4a2f214569113l,0xe48b820ca35f4484l,0x9fb560949ae44df2l,
-            0x6ca1346292cc09fdl },
-          0 },
-        /* 61 << 248 */
-        { { 0x887e0b87bcdc3a36l,0x6b0d617d503dee65l,0x96bda1f6cebcb893l,
-            0xdc0dd17341e20b3el },
-          { 0x812fbacfa6657c11l,0x32492fcbc94a6f4bl,0x854a0bcb6a772123l,
-            0x1ed573f65d463f31l },
-          0 },
-        /* 63 << 248 */
-        { { 0x22c7ef7bd022cc4dl,0xeec383d61e63b4bcl,0x52e0aaa06502b46fl,
-            0x9224187ded5e41bfl },
-          { 0x3a01f53dd26faf1cl,0x9bc4ee2e4e591d10l,0x10b7a98eea7e4c88l,
-            0xe521c150e2c1beccl },
-          0 },
-        /* 64 << 248 */
-        { { 0xb618d590b01e6e27l,0x047e2ccde180b2dcl,0xd1b299b504aea4a9l,
-            0x412c9e1e9fa403a4l },
-          { 0x88d28a3679407552l,0x49c50136f332b8e3l,0x3a1b6fcce668de19l,
-            0x178851bc75122b97l },
-          0 },
-        /* 65 << 248 */
-        { { 0x26f9b9322ed53a71l,0x0bac7348c72ef2e0l,0x7e96001da5c6faf1l,
-            0x5d43f76dea00eb2dl },
-          { 0x1327370f44f1c478l,0x1c83a9ac6bb964c8l,0xa3a9769f76ffbd25l,
-            0xdf045fb6b04f1bddl },
-          0 },
-        /* 71 << 248 */
-        { { 0x4283898d556b975el,0x6e2301ffe3880361l,0xc6d3b2bbe9198077l,
-            0xc4799578d21cac02l },
-          { 0x11448ff8f784eb7cl,0xb775973fbb81898dl,0x4e51f061519c76b9l,
-            0xaba1f3ef3cad0393l },
-          0 },
-        /* 77 << 248 */
-        { { 0x59d60c1c9b339830l,0x5af60a44ac32746dl,0x5ac006bc9dea8d80l,
-            0x4a2a56d97f2b1180l },
-          { 0x2032845a46946fc4l,0xe25b911226a3b503l,0xfed89db9a28827d3l,
-            0xdd2d7e90c6b74593l },
-          0 },
-        /* 83 << 248 */
-        { { 0x9b047a26cda38ecfl,0x6889284f5f6cb442l,0x4d128bcb14753820l,
-            0x8f9937c160eedd78l },
-          { 0xe333bad751ab9127l,0xd31b01c67ace3b19l,0x0732de39d7c0b4bel,
-            0xad04fa4c649e2b9bl },
-          0 },
-        /* 89 << 248 */
-        { { 0x02e042689d1495bal,0x95dca5a85591b5f8l,0xb10488d856f46c71l,
-            0x97829baf3590000al },
-          { 0xaeda5cb378c9e78al,0x3615873a7ba1c71cl,0x7c9f9f4d4333aa12l,
-            0x893fab42cea8e6d3l },
-          0 },
-        /* 95 << 248 */
-        { { 0x9eb09fff69aaa09fl,0xf36678a926731322l,0x8be61ee1cafcabafl,
-            0x77a172f558ddb763l },
-          { 0x7e09dfc66471130el,0x7f8909791039771el,0x0e44071d37800b9bl,
-            0x09123d27fe762d10l },
-          0 },
-        /* 101 << 248 */
-        { { 0xffd455a7a1b7fdd6l,0xb6162cb4dabdffael,0xf859519ec89c0e56l,
-            0x07406c1b421f2846l },
-          { 0x42db24ed9e96ddbbl,0x03bcae092dc5da85l,0x75099cd217aa7493l,
-            0x8cd1aa4266b8740dl },
-          0 },
-        /* 107 << 248 */
-        { { 0xe94333d5dde7fec3l,0x894fd673745a9be3l,0xaf3d97c725683748l,
-            0xeaa469a2c9ec165fl },
-          { 0xc9a18decdc7abd3bl,0xf059008082717b02l,0x9816374a4fdf4300l,
-            0x449d3eb74fb5a6cel },
-          0 },
-        /* 113 << 248 */
-        { { 0x7fc983ebd28001a6l,0xeabf5276dae74b6bl,0x50adb67d742ed0a5l,
-            0x1d2ad363650e1446l },
-          { 0x5a564253d122f5d0l,0x7e5aefc7e30471del,0xdc64cbb3e5dc2f2cl,
-            0xe645b9fa9437be4el },
-          0 },
-        /* 116 << 248 */
-        { { 0x0f58cec54e27d357l,0x08dcf2b70004539el,0xb1ead64104f96709l,
-            0x350fed185a914c72l },
-          { 0x44f43523c5147854l,0x45f8b46f46d04ac7l,0x62c306869a449d51l,
-            0xaacc0f0d9e66d9a3l },
-          0 },
-        /* 119 << 248 */
-        { { 0x94cb62e5bdd61b63l,0xe6ce5b5104a0ec57l,0x0461cb95f0bda8a4l,
-            0xca2d6220cbadfe8fl },
-          { 0x6c19bdf03c1ad65el,0x774a49bae04239d5l,0xf78cb7404a2fd59dl,
-            0xaebf90ed66a09130l },
-          0 },
-        /* 125 << 248 */
-        { { 0x10e4074857cc8d54l,0x29985831918e3cf9l,0x3d87def9f2e344eel,
-            0x8899992c68977860l },
-          { 0xbdc8d73b210f3c50l,0x98aa042fa9857f46l,0x76a34daf6c71357fl,
-            0x086289d3200bcb6dl },
-          0 },
-    },
-    {
-        /* 0 << 256 */
-        { { 0x00, 0x00, 0x00, 0x00 },
-          { 0x00, 0x00, 0x00, 0x00 },
-          1 },
-        /* 1 << 256 */
-        { { 0xb4e370af3aeac968l,0xe4f7fee9c4b63266l,0xb4acd4c2e3ac5664l,
-            0xf8910bd2ceb38cbfl },
-          { 0x1c3ae50cc9c0726el,0x15309569d97b40bfl,0x70884b7ffd5a5a1bl,
-            0x3890896aef8314cdl },
-          0 },
-        /* 3 << 256 */
-        { { 0x996884f5903fa271l,0xe6da0fd2b9da921el,0xa6f2f2695db01e54l,
-            0x1ee3e9bd6876214el },
-          { 0xa26e181ce27a9497l,0x36d254e48e215e04l,0x42f32a6c252cabcal,
-            0x9948148780b57614l },
-          0 },
-        /* 4 << 256 */
-        { { 0xab41b43a43228d83l,0x24ae1c304ad63f99l,0x8e525f1a46a51229l,
-            0x14af860fcd26d2b4l },
-          { 0xd6baef613f714aa1l,0xf51865adeb78795el,0xd3e21fcee6a9d694l,
-            0x82ceb1dd8a37b527l },
-          0 },
-        /* 5 << 256 */
-        { { 0x4a665bfd2f9fd51al,0x7f2f1fe2481b97f7l,0xcad05d69ad36ce50l,
-            0x314fc2a4844f4dedl },
-          { 0xd5593d8cb55fc5c6l,0xe3510ce8bfb1e23dl,0xf9b7be6937453ccel,
-            0xd3541b7969fae631l },
-          0 },
-        /* 7 << 256 */
-        { { 0x711b8a4176a9f05dl,0x06ca4e4b9011d488l,0x543bc62ba248a65el,
-            0x017535ffc9290894l },
-          { 0x840b84ce406851d7l,0xafa3acdf90e960b4l,0xac3394af7128fd34l,
-            0x54eb4d5b2ac0f92cl },
-          0 },
-        /* 9 << 256 */
-        { { 0x3549a0f14df48fecl,0x6ae7b1eec239f83al,0x001dcf253eb90ff3l,
-            0x02ff0f02581e90edl },
-          { 0x72921d8ca103dcefl,0x2c513c3c5876293el,0xc07064ca6b68875el,
-            0x7198d44653b9537cl },
-          0 },
-        /* 10 << 256 */
-        { { 0x58349b77685e089bl,0x1c678441219b7b8cl,0xba8da91f61e2e20dl,
-            0xf9c50b8c309fd4e6l },
-          { 0x99b0164996d0ef64l,0xac334ded60cdb63al,0x6b9ada19fb0bce4fl,
-            0x39dc9375c7896377l },
-          0 },
-        /* 11 << 256 */
-        { { 0x068dda8b7e1bc126l,0x77c7c58176243a21l,0xcc8ba55c875f9dael,
-            0xdde7afe2ce469f95l },
-          { 0xde2a15f5e9523b85l,0x447512c6d85674ael,0x5691f89e12c6c20cl,
-            0xd64ef40e0fae4513l },
-          0 },
-        /* 13 << 256 */
-        { { 0x10db2041c4d9eb40l,0x420eccb724f03f8al,0x64470fd17d29080el,
-            0xf66c5b4416e52414l },
-          { 0xa32cc70e4ca94031l,0xa67931592c8401bal,0x34f2dc29abfcc58dl,
-            0x6f340f9a07325d7dl },
-          0 },
-        /* 15 << 256 */
-        { { 0xf55d446b060a52bbl,0x2f33cb9f02939f24l,0x0f27a01bc8953718l,
-            0x362882917fcd3932l },
-          { 0x7485613488ed4436l,0xcfe69e27195f089el,0xd6ab040a8ff10bd8l,
-            0x9741c5472e4a1623l },
-          0 },
-        /* 16 << 256 */
-        { { 0xc52d8d8b6d55d6a4l,0xc4130fb3be58e8f9l,0x5f55c345e1275627l,
-            0xb881a03c117042d3l },
-          { 0x00a970a53238d301l,0x40d7cf2412a2c4f1l,0xace4a2f5d770ea74l,
-            0x36a2e587e96940b2l },
-          0 },
-        /* 17 << 256 */
-        { { 0x84793d9fef12d4c8l,0x04b89b152d8a163cl,0x0fdb566fb4a87740l,
-            0xf7e6e5cf9e595680l },
-          { 0xbcb973e41c5cd74el,0xafcb439fe4ed49d8l,0xd5c0820aebbae8eel,
-            0x23483d836f56e2a2l },
-          0 },
-        /* 19 << 256 */
-        { { 0x91f9b8be5e8ad115l,0xf1fd6a2e225db496l,0xf362d2cf4a444085l,
-            0x033d9201eea043ebl },
-          { 0x1e50c0989951a150l,0x4814fca5cfcf1f94l,0xaf3e8ef41bf82de5l,
-            0xba0e2991038cff53l },
-          0 },
-        /* 21 << 256 */
-        { { 0x904a41ae5fc373fal,0x235556d61a6a3fc4l,0xe44eb3ea36eeb570l,
-            0xa4e1b34a26ba5ca6l },
-          { 0x210e7c9131180257l,0x2c28669622158b0cl,0xc78b69c783ddd341l,
-            0xfc05941b294e1750l },
-          0 },
-        /* 23 << 256 */
-        { { 0x70666f51fc167dedl,0x47e9e289fe75b8d1l,0x8a5f59739605a03el,
-            0x19876a58dd579094l },
-          { 0x69a5c8cca964e426l,0xed74a652ccf20306l,0x5c93ae3cf06d31d5l,
-            0x51922fa2127a8a12l },
-          0 },
-        /* 25 << 256 */
-        { { 0xa18e26f99e3d509el,0xbc296dd2c10814fal,0x5dadd6eeaa24e147l,
-            0xdba2121a8340f12el },
-          { 0xd348e7f3e245ca21l,0x1e45a42978e3eb5bl,0x252bf89c169677bbl,
-            0xfb33a2564021ac55l },
-          0 },
-        /* 27 << 256 */
-        { { 0x30dc46586e7d72b8l,0x38df46fb0d81c3d6l,0x901bab6e10e84162l,
-            0x25d7303ff7932801l },
-          { 0xe781d5f37500be42l,0x9a7104c3380ff208l,0xfa801181652121a1l,
-            0xef89f4f18d3bed43l },
-          0 },
-        /* 28 << 256 */
-        { { 0xbe4ae5683594917al,0xef7c1c47a04bf81el,0xa1dc3612046d91a0l,
-            0x3eee37affb11b338l },
-          { 0x7e90278fd03d8f51l,0x3045a6da4fa183c6l,0xb39e573391cd16a9l,
-            0xc748a504e54e9411l },
-          0 },
-        /* 29 << 256 */
-        { { 0x07804331a1c6ec56l,0x25358e795b347123l,0x1ab9b39acf9432a4l,
-            0x9628501d0a7881cel },
-          { 0x749d58988a46d98el,0x01ea43346a17c321l,0xe2b197f9b1f9160fl,
-            0x2052c7c07815f2a2l },
-          0 },
-        /* 31 << 256 */
-        { { 0xaa691bfbc57a1a6dl,0x06cae127d737d525l,0x5be04b2f963c7c98l,
-            0x936b1f5bfc00bc4al },
-          { 0x3fed4ac77eda6a34l,0xba6ca7aa2500a438l,0x1e979fa6786c2a75l,
-            0xa3db26bec13f37d4l },
-          0 },
-        /* 33 << 256 */
-        { { 0x20afae333d7006d1l,0xdcbca6fbbda467d1l,0x2714b3827df4006cl,
-            0x9abc0510c8e94549l },
-          { 0x5b30a6d464c14915l,0xba91d0c35752b44fl,0x7ad9b19bbb389f1fl,
-            0xe4c7aa04ef7c6e13l },
-          0 },
-        /* 34 << 256 */
-        { { 0x1e24a3f23d12e2b6l,0xf99df403febd6db3l,0x61e580a6b0c8e12fl,
-            0x819341b7c2bfe085l },
-          { 0xd53002d640828921l,0x31e1eb65cea010efl,0xc48d0cfe85b3279fl,
-            0xb90de69089f35fa5l },
-          0 },
-        /* 35 << 256 */
-        { { 0xa3f6fd3c88ed748fl,0x6d72613af48127b9l,0xe85ed703d1e6f7e5l,
-            0xbb563db449636f40l },
-          { 0x23bae3c9708497bal,0x89dbff163aa65cf4l,0x70861847e6c0850al,
-            0x5ef19d5d48b2e90cl },
-          0 },
-        /* 36 << 256 */
-        { { 0xab6a1e13107f7bacl,0x83a8bc57972091f5l,0x3c65b454f6dcba41l,
-            0xd7606ff96abc431dl },
-          { 0xa3af9c189bd09971l,0x6ddd3bbf276bad63l,0xd2aba9beab4f0816l,
-            0x8f13063c151581edl },
-          0 },
-        /* 37 << 256 */
-        { { 0xf9c02364f5761b15l,0x3cfa250afd478139l,0x67d51e7416e26191l,
-            0x0281bbf65eda396cl },
-          { 0xbd38d4d70d1f4510l,0x2032a930edff593el,0x0ab74a0cf2ea4ad7l,
-            0xb95aa9c3302498d6l },
-          0 },
-        /* 39 << 256 */
-        { { 0x2995495dd7da3c7cl,0x28d579d0a0bb703el,0xabec6afec8288837l,
-            0x93c34dfd05ab989bl },
-          { 0xcc94f05dde5ea3dfl,0xc3e3d4ef90f436e6l,0x32b3dee1cf59dc4el,
-            0x5eab01635447d9d9l },
-          0 },
-        /* 40 << 256 */
-        { { 0xd31c5e8e2c23464el,0x5bcc382f50cfbde7l,0x6cee3d8da93c3d9bl,
-            0xbee2948909ee62acl },
-          { 0x4848d59c10742b84l,0x2486796fe35e9c84l,0x1a1d9570cd8f391al,
-            0x839aa0913eedb743l },
-          0 },
-        /* 41 << 256 */
-        { { 0xae02a7ce0f83f369l,0x3b67c56097994835l,0x715def441ae4bbeal,
-            0x11e764ee59f6b9eel },
-          { 0x70c775051c962c3al,0x42811507d937a258l,0x06dbdceed03e6e86l,
-            0x39a3a7ed48cae79el },
-          0 },
-        /* 43 << 256 */
-        { { 0xa32e729fb220eef8l,0x12d876baf37ac5d7l,0x9376ab45105a7f34l,
-            0xb422331a4deb7275l },
-          { 0x6ea07fb7686dea5el,0xba67ed3e1d8e32c9l,0x5ae52632bbc6bb9cl,
-            0xdca55b86d1397575l },
-          0 },
-        /* 44 << 256 */
-        { { 0xd9183f74378200b1l,0xe5ea1645762f5605l,0x78b42e2f7bd6290fl,
-            0xa0bdfccc07fa0899l },
-          { 0x2f92ea52dacda629l,0x810b4e6c48de27e2l,0x013d8587d9d1250dl,
-            0xc153d519dd5141d5l },
-          0 },
-        /* 45 << 256 */
-        { { 0x8f1f6cb5b8f1d719l,0xa9abc27b04e15a4el,0xc0d944a92ad42296l,
-            0x69ecc877f3d2b0e5l },
-          { 0xec60dbea16a5581al,0x2a0ead5fb85130d6l,0x7b3d2ebb6fddac23l,
-            0x06213269ac448663l },
-          0 },
-        /* 46 << 256 */
-        { { 0xe1074008ac11e180l,0xdff3339c14b8f830l,0x136e22be636504f3l,
-            0xb07ae98aa09c5c4cl },
-          { 0x9b0a0517192168e9l,0x39e09fac86ad0865l,0x24f90705adb08d41l,
-            0x9c699cc759d3be24l },
-          0 },
-        /* 47 << 256 */
-        { { 0xd9e16551907e36b0l,0x57f24b6caf91cb5al,0xbdb7dfdb062edae4l,
-            0x99e3bffe4b85f424l },
-          { 0x250774f4b2961ba7l,0xe7c0f2386d993c51l,0xcd0aae29f559b4bdl,
-            0x3b12893a09a6859bl },
-          0 },
-        /* 48 << 256 */
-        { { 0xac177eb985ae12c3l,0x8e6cb5cc6cf76537l,0x134abb19f265f9e3l,
-            0xc37309b71ba3f55dl },
-          { 0x570833b4392d564bl,0xaa273a27d8c22f00l,0x9ba6b6276006773al,
-            0x2156c94f0a16c092l },
-          0 },
-        /* 49 << 256 */
-        { { 0x2be0436b408e1258l,0xb179a2e34f47f121l,0x140b948fa42d3cfcl,
-            0x96649c6700d2b4e6l },
-          { 0x2bf934c7d08a4b34l,0x371c770136b472ddl,0x36297876e06adc73l,
-            0x59e0d8251c3e6558l },
-          0 },
-        /* 51 << 256 */
-        { { 0x9368cfd304a8bc81l,0x145249d4c49e58c7l,0x8c7ac1891392be01l,
-            0x58cbcb5fbc7b0903l },
-          { 0x502218a1a0377b0al,0x5c17eb8afb625836l,0x845c09ef349f4d26l,
-            0x15fdeb2554ddce85l },
-          0 },
-        /* 52 << 256 */
-        { { 0xf773535a64e8344dl,0xb8486a33d0dbabe6l,0x43c2df99b578862dl,
-            0xcead29a11a39820el },
-          { 0x3e5466fe63134d63l,0xc37ea88fdf43a104l,0x3b34ac34bbaacb5al,
-            0x8281c240bc20be5al },
-          0 },
-        /* 53 << 256 */
-        { { 0x55113d5e0f8dec77l,0xdfe59f251d7e1543l,0x3b2837e0a63a849al,
-            0xdfbdb8b67a5691afl },
-          { 0x8dd6faf0bd4cf444l,0x28b2bdfaab128b6cl,0x44af3ee24b1098ebl,
-            0xbbf328ebe50b2d02l },
-          0 },
-        /* 55 << 256 */
-        { { 0xf231b1f4e4e6151al,0x6ac7130413258c6al,0x6f9cb1c1a09b9f86l,
-            0xbfc9291ee52ed880l },
-          { 0x2a7d8230bea258a2l,0xd52a0da6baf386acl,0x5166764b3af00b7el,
-            0x84792b043c985be2l },
-          0 },
-        /* 57 << 256 */
-        { { 0x914ca588a906d9e4l,0xb4e4e86abc27a876l,0x97e6ed27724324f2l,
-            0xda7e9aa5c0b87d2cl },
-          { 0xafccbe6b33a56f84l,0x69e8fd4ac892d90al,0xb47512910bb5457fl,
-            0xad65e4d05cb136fal },
-          0 },
-        /* 59 << 256 */
-        { { 0xb09974d2fd679a1bl,0x17abc2a54578faf0l,0xe7da92828c830388l,
-            0x7e455d8b0edf6146l },
-          { 0xdff3b2f0c324bdb6l,0xe7a1718769f4a4f9l,0xfb4e0b3129c500a4l,
-            0x1ed50799a09c5a07l },
-          0 },
-        /* 60 << 256 */
-        { { 0x6b669496c679d9f9l,0x3b741f36e78f0830l,0xf99d4857eb3f9e53l,
-            0x41be594276f7d4ael },
-          { 0x75f44d57c09a112bl,0xa5139fd68475eeb7l,0xa4560cd5c6bc9df6l,
-            0x8ce2c4cf50845434l },
-          0 },
-        /* 61 << 256 */
-        { { 0x96b515c32b3cb0a6l,0x65836de3930d5344l,0xfb032d5b00e6d403l,
-            0x2648301843c93bd1l },
-          { 0xfc4525dd4b572363l,0x12b7923e7b28ab5cl,0xf376b633e22ac5e6l,
-            0xd6ff6582e30b4707l },
-          0 },
-        /* 63 << 256 */
-        { { 0x8bdce75c83b09e07l,0x64228b19227717c4l,0xeae8f8a2dc6a1f02l,
-            0x1081031be72f3b6dl },
-          { 0xba0f876072c3f736l,0xde38a0c5246a28adl,0x0b116fe08596c412l,
-            0xb9e37be3fa135d11l },
-          0 },
-        /* 64 << 256 */
-        { { 0x09800dc1b48d4168l,0xa740b282bfee87a2l,0x80c6b75dc94a547al,
-            0x8cb622f0099c1985l },
-          { 0xe6c789631467e05dl,0x027b658822fd3064l,0xe14735e2c2fdb68cl,
-            0xfd2869947d853158l },
-          0 },
-        /* 65 << 256 */
-        { { 0x301916a5bbd7caf1l,0xef563fda4e2076c2l,0xccbc56088467f279l,
-            0xd7de3088b8d0f1bfl },
-          { 0x3d9adcce8586910dl,0x3fa3b8b9d775e0e9l,0x4b7a4a1d88136503l,
-            0xc748656de4994fcel },
-          0 },
-        /* 71 << 256 */
-        { { 0x18cc605c2d9f8646l,0x3764f1c29e441b64l,0xb0ea7f7fc4b64ee3l,
-            0xb5c22d0c042f8678l },
-          { 0x3761f7f89b3057fdl,0xc85b8de64a207ce4l,0x11da715bc5c04cf7l,
-            0x0cb1fa77c8e99c1fl },
-          0 },
-        /* 77 << 256 */
-        { { 0x35f9cfc8045dab4el,0x08a65c6771a7d720l,0xf076767b8eef1351l,
-            0x5351dbff8638fbe5l },
-          { 0x5aead6f7772ad54cl,0x5f6b441fafe93e69l,0xb7b83d1aeeb876b5l,
-            0xbe1ba4a7cdc094d9l },
-          0 },
-        /* 83 << 256 */
-        { { 0x005d8f04ec0377bal,0x036b8e1ace58f05dl,0xdd6ffc6f1b28cf58l,
-            0xc3d95a58e206189fl },
-          { 0xcb2873c1f52e8b8cl,0xcffdb18d80142af1l,0x7cf88eb64c77ed78l,
-            0xb3a3141981ef2c12l },
-          0 },
-        /* 89 << 256 */
-        { { 0xbb17e6f957c175b1l,0xf33abc63260a6f6dl,0x9435f2de620ddd6bl,
-            0x90bdde59ff3e99eal },
-          { 0x3d7875e0567b520fl,0xdd6954aa813b4978l,0x1af3dc24de7b631cl,
-            0x82ddcd08934d3c97l },
-          0 },
-        /* 95 << 256 */
-        { { 0x7a9d60affc5ce598l,0xc6f507597c37abfdl,0xaa1b32f3a79355d0l,
-            0xac581b94d7e4fcf3l },
-          { 0x2669cefd139f6466l,0x560a98bb26f97570l,0x32e1c1db2837b908l,
-            0x7823d7922d252781l },
-          0 },
-        /* 101 << 256 */
-        { { 0xea018b4cdedf9af0l,0x4b64c0a380c1d2f9l,0x527a0b1c36992c44l,
-            0x72a2408142b7adffl },
-          { 0x0023d10f97a502eel,0xc0f9ed067b401ac4l,0xabd1bd03d6d3b516l,
-            0xc320e3e478c5d0bel },
-          0 },
-        /* 107 << 256 */
-        { { 0x9f5d2a6a37dd009cl,0x88c0f42ac2c3cbacl,0x3155636977552a1el,
-            0xe78ec89d02f8098fl },
-          { 0x276c2ad71b6eeff9l,0xf4c49a28f7f91856l,0x698a2368dc795124l,
-            0x5502810de92a6c0fl },
-          0 },
-        /* 113 << 256 */
-        { { 0x82a5042e9f5e5192l,0x64da65fac0965a88l,0xf4c80dd56668399el,
-            0x635323757e33c233l },
-          { 0x5e5339b1a0048616l,0x4a17b1931c91741fl,0x65fdc7c213dcf3d0l,
-            0x230181426d10c410l },
-          0 },
-        /* 116 << 256 */
-        { { 0x090a04220f46c635l,0xc7eac842a04de3f5l,0x45b69d4c8990d4b2l,
-            0x032aeb50b8e0cdc6l },
-          { 0x02ce332a4ee3f307l,0x3c80c1545043980fl,0xc774838bcbd5287cl,
-            0x052661074a37d0ael },
-          0 },
-        /* 119 << 256 */
-        { { 0xc401b9c0f4d70fbfl,0xf82bbfde98ee47fel,0x94965118c84d91afl,
-            0xdd9a67c4d3b6ad1dl },
-          { 0x85c9cf1eb66a3ad4l,0x05580a0fbf5f514cl,0xf3ef0fd00218536el,
-            0x1dc2cf2bd14a7ca9l },
-          0 },
-        /* 125 << 256 */
-        { { 0x18c83e337c1e24d4l,0x30911165563657c6l,0xf9be1af679e53083l,
-            0x9b058059637753cel },
-          { 0x6a37fa24e54522b9l,0xc11d38b426dbf4c4l,0xbc6738655ebd4d9al,
-            0x2b40e9427fd4e2ecl },
-          0 },
-    },
-};
-
-/* Structure used to describe recoding of scalar multiplication. */
-typedef struct ecc_recode_sum {
-    /* Index into pre-computation table. */
-    uint8_t i;
-    /* Multiplier to add point into. */
-    uint8_t mul;
-    /* Use the negative of the point. */
-    uint8_t neg;
-} ecc_recode_sum;
-
-/* The index into pre-computation table to use. */
-static uint8_t recode_index_4_8[258] = {
-     0,  1,  1,  1,  3,  4,  2,  5,  3,  2,  4,  8,  3,  9,  5,  4,
-    11, 12,  6, 13,  7,  5,  8, 15, 55, 16,  9,  6, 18, 19,  7, 20,
-    11,  8, 12, 23, 24, 25, 13,  9, 27, 28, 14, 29, 30, 10, 15, 33,
-    11, 35, 16, 12, 37, 38, 17, 39, 18, 13, 19, 41, 42, 43, 20, 14,
-    45, 46, 21, 44, 22, 15, 23, 47, 24, 43, 25, 16, 42, 48, 26, 41,
-    27, 17, 28, 49, 18, 40, 29, 19, 30, 50, 31, 39, 32, 20, 33, 51,
-    34, 38, 35, 21, 37, 52, 22, 36, 37, 23, 38, 53, 24, 35, 39, 25,
-    34, 54, 40, 33, 55, 26, 32, 56, 27, 31, 43, 28, 30, 57, 44, 29,
-    45, 29, 44, 57, 30, 28, 43, 31, 27, 56, 32, 26, 55, 33, 40, 54,
-    34, 25, 39, 35, 24, 53, 38, 23, 37, 36, 22, 52, 37, 21, 35, 38,
-    34, 51, 33, 20, 32, 39, 31, 50, 30, 19, 29, 40, 18, 49, 28, 17,
-    27, 41, 26, 48, 42, 16, 25, 43, 24, 47, 23, 15, 22, 44, 21, 46,
-    45, 14, 20, 43, 42, 41, 19, 13, 18, 39, 17, 38, 37, 12, 16, 35,
-    11, 33, 15, 10, 30, 29, 14, 28, 27,  9, 13, 25, 24, 23, 12,  8,
-    11, 20,  7, 19, 18,  6,  9, 16, 55, 15,  8,  5,  7, 13,  6, 12,
-    11,  4,  5,  9,  3,  8,  4,  2,  3,  5,  2,  4,  3,  1,  1,  1,
-     0,  1,
-};
-
-/* Multiple to add point into. */
-static uint8_t recode_mul_4_8[258] = {
-     0,  1,  2,  3,  1,  1,  2,  1,  2,  3,  2,  1,  3,  1,  2,  3,
-     1,  1,  2,  1,  2,  3,  2,  1,  2,  1,  2,  3,  1,  1,  3,  1,
-     2,  3,  2,  1,  1,  1,  2,  3,  1,  1,  2,  1,  1,  3,  2,  1,
-     3,  1,  2,  3,  1,  1,  2,  1,  2,  3,  2,  1,  1,  1,  2,  3,
-     1,  1,  2,  3,  2,  3,  2,  1,  2,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  2,  1,  2,  3,  2,  3,  2,  1,
-     2,  3,  2,  3,  3,  1,  3,  3,  2,  3,  2,  1,  3,  3,  2,  3,
-     3,  1,  2,  3,  1,  3,  3,  1,  3,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  3,  1,  3,  3,  1,  3,  2,  1,
-     3,  3,  2,  3,  3,  1,  2,  3,  2,  3,  3,  1,  3,  3,  2,  3,
-     2,  1,  2,  3,  2,  3,  2,  1,  2,  3,  2,  3,  3,  1,  2,  3,
-     2,  3,  2,  1,  3,  3,  2,  3,  2,  1,  2,  3,  2,  3,  2,  1,
-     1,  3,  2,  1,  1,  1,  2,  3,  2,  1,  2,  1,  1,  3,  2,  1,
-     3,  1,  2,  3,  1,  1,  2,  1,  1,  3,  2,  1,  1,  1,  2,  3,
-     2,  1,  3,  1,  1,  3,  2,  1,  2,  1,  2,  3,  2,  1,  2,  1,
-     1,  3,  2,  1,  3,  1,  2,  3,  2,  1,  2,  1,  1,  3,  2,  1,
-     0,  1,
-};
-
-/* Whether to negate y-ordinate. */
-static uint8_t recode_neg_4_8[258] = {
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  1,  0,  0,  1,
-     0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-     0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,
-     1,  0,  0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  1,  0,  0,  1,
-     0,  0,  1,  1,  0,  1,  1,  0,  1,  1,  0,  1,  1,  0,  1,  1,
-     0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,  1,  1,  0,
-     1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,
-     1,  0,  1,  1,  0,  1,  1,  0,  1,  1,  1,  1,  1,  0,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,
-     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-     0,  0,
-};
-
-/* Recode the scalar for multiplication using pre-computed values, multipliers
- * and subtraction.
- *
- * k  Scalar to multiply by.
- * v  Vector of operations to peform.
- */
-static void sp_256_ecc_recode_sum_8_4(sp_digit* k, ecc_recode_sum* v)
-{
-    int i, j;
-    uint16_t y;
-    int carry = 0;
-    int o;
-    sp_digit n;
-
-    j = 0;
-    n = k[j];
-    o = 0;
-    for (i=0; i<33; i++) {
-        y = n;
-        if (o + 8 < 64) {
-            y &= 0xff;
-            n >>= 8;
-            o += 8;
-        }
-        else if (o + 8 == 64) {
-            n >>= 8;
-            if (++j < 4)
-                n = k[j];
-            o = 0;
-        }
-        else if (++j < 4) {
-            n = k[j];
-            y |= (n << (64 - o)) & 0xff;
-            o -= 56;
-            n >>= o;
-        }
-
-        y += carry;
-        v[i].i = recode_index_4_8[y];
-        v[i].mul = recode_mul_4_8[y];
-        v[i].neg = recode_neg_4_8[y];
-        carry = (y >> 8) + v[i].neg;
-    }
-}
-
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[4];
-    sp_point pd;
-    sp_digit tmpd[2 * 4 * 5];
-#endif
-    sp_point* t;
-    sp_point* p;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode_sum v[33];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-    negy = tmp;
-
-    if (err == MP_OKAY) {
-        sp_256_ecc_recode_sum_8_4(k, v);
-
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        for (i=0; i<4; i++) {
-            XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod));
-            t[i].infinity = 1;
-        }
-
-        i = 32;
-        XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-        XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-        t[v[i].mul].infinity = p256_table[i][v[i].i].infinity;
-        for (--i; i>=0; i--) {
-            XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-            XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-            p->infinity = p256_table[i][v[i].i].infinity;
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_qz1_4(&t[v[i].mul], &t[v[i].mul], p, tmp);
-        }
-        sp_256_proj_point_add_4(&t[2], &t[2], &t[3], tmp);
-        sp_256_proj_point_add_4(&t[1], &t[1], &t[3], tmp);
-        sp_256_proj_point_dbl_4(&t[2], &t[2], tmp);
-        sp_256_proj_point_add_4(&t[1], &t[1], &t[2], tmp);
-
-        if (map)
-            sp_256_map_4(r, &t[1], tmp);
-        else
-            XMEMCPY(r, &t[1], sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(p, 0, heap);
-
-    return MP_OKAY;
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * r     Resulting point.
- * k     Scalar to multiply by.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-static int sp_256_ecc_mulmod_base_avx2_4(sp_point* r, sp_digit* k, int map,
-        void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point td[4];
-    sp_point pd;
-    sp_digit tmpd[2 * 4 * 5];
-#endif
-    sp_point* t;
-    sp_point* p;
-    sp_digit* tmp;
-    sp_digit* negy;
-    int i;
-    ecc_recode_sum v[33];
-    int err;
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC);
-    if (t == NULL)
-        err = MEMORY_E;
-    tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap,
-                             DYNAMIC_TYPE_ECC);
-    if (tmp == NULL)
-        err = MEMORY_E;
-#else
-    t = td;
-    tmp = tmpd;
-#endif
-    negy = tmp;
-
-    if (err == MP_OKAY) {
-        sp_256_ecc_recode_sum_8_4(k, v);
-
-        XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        for (i=0; i<4; i++) {
-            XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod));
-            t[i].infinity = 1;
-        }
-
-        i = 32;
-        XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-        XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-        t[v[i].mul].infinity = p256_table[i][v[i].i].infinity;
-        for (--i; i>=0; i--) {
-            XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x));
-            XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y));
-            p->infinity = p256_table[i][v[i].i].infinity;
-            sp_256_sub_4(negy, p256_mod, p->y);
-            sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg);
-            sp_256_proj_point_add_qz1_avx2_4(&t[v[i].mul], &t[v[i].mul], p, tmp);
-        }
-        sp_256_proj_point_add_avx2_4(&t[2], &t[2], &t[3], tmp);
-        sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[3], tmp);
-        sp_256_proj_point_dbl_avx2_4(&t[2], &t[2], tmp);
-        sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[2], tmp);
-
-        if (map)
-            sp_256_map_avx2_4(r, &t[1], tmp);
-        else
-            XMEMCPY(r, &t[1], sizeof(sp_point));
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (t != NULL) {
-        XMEMSET(t, 0, sizeof(sp_point) * 4);
-        XFREE(t, heap, DYNAMIC_TYPE_ECC);
-    }
-    if (tmp != NULL) {
-        XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5);
-        XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    ForceZero(tmpd, sizeof(tmpd));
-    ForceZero(td, sizeof(td));
-#endif
-    sp_ecc_point_free(p, 0, heap);
-
-    return MP_OKAY;
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* WOLFSSL_SP_SMALL */
-/* Multiply the base point of P256 by the scalar and return the result.
- * If map is true then convert result to affine co-ordinates.
- *
- * km    Scalar to multiply by.
- * r     Resulting point.
- * map   Indicates whether to convert result to affine.
- * heap  Heap to use for allocation.
- * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, km);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(point, k, map, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(point, k, map, heap);
-    }
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, r);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-
-#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN)
-/* Returns 1 if the number of zero.
- * Implementation is constant time.
- *
- * a  Number to check.
- * returns 1 if the number is zero and 0 otherwise.
- */
-static int sp_256_iszero_4(const sp_digit* a)
-{
-    return (a[0] | a[1] | a[2] | a[3]) == 0;
-}
-
-#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN */
-/* Add 1 to a. (a = a + 1)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-static void sp_256_add_one_4(sp_digit* a)
-{
-    __asm__ __volatile__ (
-        "addq	$1, (%[a])\n\t"
-        "adcq	$0, 8(%[a])\n\t"
-        "adcq	$0, 16(%[a])\n\t"
-        "adcq	$0, 24(%[a])\n\t"
-        :
-        : [a] "r" (a)
-        : "memory"
-    );
-}
-
-/* Read big endian unsigned byte aray into r.
- *
- * r  A single precision integer.
- * a  Byte array.
- * n  Number of bytes in array to read.
- */
-static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n)
-{
-    int i, j = 0, s = 0;
-
-    r[0] = 0;
-    for (i = n-1; i >= 0; i--) {
-        r[j] |= ((sp_digit)a[i]) << s;
-        if (s >= 56) {
-            r[j] &= 0xffffffffffffffffl;
-            s = 64 - s;
-            if (j + 1 >= max)
-                break;
-            r[++j] = a[i] >> s;
-            s = 8 - s;
-        }
-        else
-            s += 8;
-    }
-
-    for (j++; j < max; j++)
-        r[j] = 0;
-}
-
-/* Generates a scalar that is in the range 1..order-1.
- *
- * rng  Random number generator.
- * k    Scalar value.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k)
-{
-    int err;
-    byte buf[32];
-
-    do {
-        err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
-        if (err == 0) {
-            sp_256_from_bin(k, 4, buf, sizeof(buf));
-            if (sp_256_cmp_4(k, p256_order2) < 0) {
-                sp_256_add_one_4(k);
-                break;
-            }
-        }
-    }
-    while (err == 0);
-
-    return err;
-}
-
-/* Makes a random EC key pair.
- *
- * rng   Random number generator.
- * priv  Generated private value.
- * pub   Generated public point.
- * heap  Heap to use for allocation.
- * returns ECC_INF_E when the point does not have the correct order, RNG
- * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point inf;
-#endif
-#endif
-    sp_point* point;
-    sp_digit* k = NULL;
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_point* infinity;
-#endif
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, inf, infinity);
-#endif
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_ecc_gen_k_4(rng, k);
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, NULL);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL);
-    }
-
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            err = sp_256_ecc_mulmod_avx2_4(infinity, point, p256_order, 1,
-                                                                          NULL);
-        }
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL);
-    }
-    if (err == MP_OKAY) {
-        if (!sp_256_iszero_4(point->x) || !sp_256_iszero_4(point->y))
-            err = ECC_INF_E;
-    }
-#endif
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(k, priv);
-    if (err == MP_OKAY)
-        err = sp_256_point_to_ecc_point_4(point, pub);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
-    sp_ecc_point_free(infinity, 1, heap);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-
-#ifdef HAVE_ECC_DHE
-/* Write r as big endian to byte aray.
- * Fixed length number of bytes written: 32
- *
- * r  A single precision integer.
- * a  Byte array.
- */
-static void sp_256_to_bin(sp_digit* r, byte* a)
-{
-    int i, j, s = 0, b;
-
-    j = 256 / 8 - 1;
-    a[j] = 0;
-    for (i=0; i<4 && j>=0; i++) {
-        b = 0;
-        a[j--] |= r[i] << s; b += 8 - s;
-        if (j < 0)
-            break;
-        while (b < 64) {
-            a[j--] = r[i] >> b; b += 8;
-            if (j < 0)
-                break;
-        }
-        s = 8 - (b - 64);
-        if (j >= 0)
-            a[j] = 0;
-        if (s != 0)
-            j++;
-    }
-}
-
-/* Multiply the point by the scalar and serialize the X ordinate.
- * The number is 0 padded to maximum size on output.
- *
- * priv    Scalar to multiply the point by.
- * pub     Point to multiply.
- * out     Buffer to hold X ordinate.
- * outLen  On entry, size of the buffer in bytes.
- *         On exit, length of data in buffer in bytes.
- * heap    Heap to use for allocation.
- * returns BUFFER_E if the buffer is to small for output size,
- * MEMORY_E when memory allocation fails and MP_OKAY on success.
- */
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outLen, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point p;
-    sp_digit kd[4];
-#endif
-    sp_point* point = NULL;
-    sp_digit* k = NULL;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    if (*outLen < 32)
-        err = BUFFER_E;
-
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        k = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (k == NULL)
-            err = MEMORY_E;
-    }
-#else
-    k = kd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(k, 4, priv);
-        sp_256_point_from_ecc_point_4(point, pub);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(point, point, k, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(point, point, k, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        sp_256_to_bin(point->x, out);
-        *outLen = 32;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (k != NULL)
-        XFREE(k, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(point, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_DHE */
-
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Add b to a into r. (r = a + b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	(%[a]), %%rax\n\t"
-        "addq	(%[b]), %%rax\n\t"
-        "movq	%%rax, (%[r])\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "adcq	8(%[b]), %%rax\n\t"
-        "movq	%%rax, 8(%[r])\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "adcq	16(%[b]), %%rax\n\t"
-        "movq	%%rax, 16(%[r])\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "adcq	24(%[b]), %%rax\n\t"
-        "movq	%%rax, 24(%[r])\n\t"
-        "adcq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax"
-    );
-
-    return c;
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Multiply a and b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision integer.
- */
-SP_NOINLINE static void sp_256_mul_4(sp_digit* r, const sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit tmp[4];
-
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[1] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 8(%[tmp])\n\t"
-        "#  A[0] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 16(%[tmp])\n\t"
-        "#  A[0] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[2] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq	0(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%rbx, 24(%[tmp])\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq	8(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq	16(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 40(%[r])\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq	24(%[b]), %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 48(%[r])\n\t"
-        "movq	%%rcx, 56(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Multiply a and b into r. (r = a * b)
- *
- * r   Result of multiplication.
- * a   First number to multiply.
- * b   Second number to multiply.
- */
-SP_NOINLINE static void sp_256_mul_avx2_4(sp_digit* r, const sp_digit* a,
-        const sp_digit* b)
-{
-    __asm__ __volatile__ (
-        "#  A[0] * B[0]\n\t"
-        "movq   0(%[b]), %%rdx\n\t"
-        "mulxq  0(%[a]), %%r8, %%r9\n\t"
-        "#  A[2] * B[0]\n\t"
-        "mulxq  16(%[a]), %%r10, %%r11\n\t"
-        "#  A[1] * B[0]\n\t"
-        "mulxq  8(%[a]), %%rax, %%rcx\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "adcxq  %%rax, %%r9\n\t"
-        "#  A[1] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%r12, %%r13\n\t"
-        "adcxq  %%rcx, %%r10\n\t"
-        "#  A[0] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "mulxq  0(%[a]), %%rax, %%rcx\n\t"
-        "adoxq  %%rax, %%r9\n\t"
-        "#  A[2] * B[1]\n\t"
-        "mulxq  16(%[a]), %%rax, %%r14\n\t"
-        "adoxq  %%rcx, %%r10\n\t"
-        "adcxq  %%rax, %%r11\n\t"
-        "#  A[1] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%rax, %%rcx\n\t"
-        "adcxq  %%r14, %%r12\n\t"
-        "adoxq  %%rax, %%r11\n\t"
-        "adcxq  %%r15, %%r13\n\t"
-        "adoxq  %%rcx, %%r12\n\t"
-        "#  A[0] * B[2]\n\t"
-        "mulxq  0(%[a]), %%rax, %%rcx\n\t"
-        "adoxq  %%r15, %%r13\n\t"
-        "xorq   %%r14, %%r14\n\t"
-        "adcxq  %%rax, %%r10\n\t"
-        "#  A[1] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %%rcx, %%r11\n\t"
-        "adoxq  %%rdx, %%r10\n\t"
-        "#  A[3] * B[1]\n\t"
-        "movq   8(%[b]), %%rdx\n\t"
-        "adoxq  %%rax, %%r11\n\t"
-        "mulxq  24(%[a]), %%rax, %%rcx\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "#  A[2] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "mulxq  16(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %%rcx, %%r13\n\t"
-        "adoxq  %%rdx, %%r12\n\t"
-        "#  A[3] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "adoxq  %%rax, %%r13\n\t"
-        "mulxq  24(%[a]), %%rax, %%rcx\n\t"
-        "adoxq  %%r15, %%r14\n\t"
-        "adcxq  %%rax, %%r14\n\t"
-        "#  A[0] * B[3]\n\t"
-        "mulxq  0(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %%rcx, %%r15\n\t"
-        "xorq   %%rcx, %%rcx\n\t"
-        "adcxq  %%rdx, %%r11\n\t"
-        "#  A[3] * B[0]\n\t"
-        "movq   0(%[b]), %%rdx\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "mulxq  24(%[a]), %%rdx, %%rax\n\t"
-        "adoxq  %%rdx, %%r11\n\t"
-        "adoxq  %%rax, %%r12\n\t"
-        "#  A[2] * B[3]\n\t"
-        "movq   24(%[b]), %%rdx\n\t"
-        "mulxq  16(%[a]), %%rdx, %%rax\n\t"
-        "adcxq  %%rdx, %%r13\n\t"
-        "#  A[3] * B[2]\n\t"
-        "movq   16(%[b]), %%rdx\n\t"
-        "adcxq  %%rax, %%r14\n\t"
-        "mulxq  24(%[a]), %%rax, %%rdx\n\t"
-        "adcxq  %%rcx, %%r15\n\t"
-        "adoxq  %%rax, %%r13\n\t"
-        "adoxq  %%rdx, %%r14\n\t"
-        "adoxq  %%rcx, %%r15\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "movq	%%r10, 16(%[r])\n\t"
-        "movq	%%r11, 24(%[r])\n\t"
-        "movq	%%r12, 32(%[r])\n\t"
-        "movq	%%r13, 40(%[r])\n\t"
-        "movq	%%r14, 48(%[r])\n\t"
-        "movq	%%r15, 56(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Sub b from a into a. (a -= b)
- *
- * a  A single precision integer and result.
- * b  A single precision integer.
- */
-SP_NOINLINE static sp_digit sp_256_sub_in_place_4(sp_digit* a,
-    const sp_digit* b)
-{
-    sp_digit c = 0;
-
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r8\n\t"
-        "movq	8(%[a]), %%r9\n\t"
-        "movq	0(%[b]), %%rdx\n\t"
-        "movq	8(%[b]), %%rcx\n\t"
-        "subq	%%rdx, %%r8\n\t"
-        "movq	16(%[b]), %%rdx\n\t"
-        "movq	%%r8, 0(%[a])\n\t"
-        "movq	16(%[a]), %%r8\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	24(%[b]), %%rcx\n\t"
-        "movq	%%r9, 8(%[a])\n\t"
-        "movq	24(%[a]), %%r9\n\t"
-        "sbbq	%%rdx, %%r8\n\t"
-        "movq	%%r8, 16(%[a])\n\t"
-        "sbbq	%%rcx, %%r9\n\t"
-        "movq	%%r9, 24(%[a])\n\t"
-        "sbbq	$0, %[c]\n\t"
-        : [c] "+r" (c)
-        : [a] "r" (a), [b] "r" (b)
-        : "memory", "rdx", "rcx", "r8", "r9"
-    );
-
-    return c;
-}
-
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_256_mul_d_4(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "mulq	(%[a])\n\t"
-        "movq	%%rax, %%rbx\n\t"
-        "movq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rbx, %%rbx\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "movq	%%rcx, 8(%[r])\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%rbx\n\t"
-        "# A[2] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "mulq	16(%[a])\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adcq	%%rdx, %%rbx\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "# A[3] * B\n\t"
-        "movq	%[b], %%rax\n\t"
-        "mulq	24(%[a])\n\t"
-        "addq	%%rax, %%rbx\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "movq	%%rbx, 24(%[r])\n\t"
-        "movq	%%rcx, 32(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rbx", "rcx", "r8"
-    );
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Mul a by digit b into r. (r = a * b)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * b  A single precision digit.
- */
-SP_NOINLINE static void sp_256_mul_d_avx2_4(sp_digit* r, const sp_digit* a,
-        const sp_digit b)
-{
-    __asm__ __volatile__ (
-        "# A[0] * B\n\t"
-        "movq	%[b], %%rdx\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "mulxq	(%[a]), %%r8, %%r9\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "# A[1] * B\n\t"
-        "mulxq	8(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "# A[2] * B\n\t"
-        "mulxq	16(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r9\n\t"
-        "adcxq	%%rax, %%r8\n\t"
-        "movq	%%r8, 16(%[r])\n\t"
-        "adoxq	%%rcx, %%r9\n\t"
-        "# A[3] * B\n\t"
-        "mulxq	24(%[a]), %%rax, %%rcx\n\t"
-        "movq	%%r10, %%r8\n\t"
-        "adcxq	%%rax, %%r9\n\t"
-        "adoxq	%%rcx, %%r8\n\t"
-        "adcxq	%%r10, %%r8\n\t"
-        "movq	%%r9, 24(%[r])\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [b] "r" (b)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10"
-    );
-}
-#endif /* HAVE_INTEL_AVX2 */
-
-/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div)
- *
- * d1   The high order half of the number to divide.
- * d0   The low order half of the number to divide.
- * div  The dividend.
- * returns the result of the division.
- */
-static sp_digit div_256_word_4(sp_digit d1, sp_digit d0, sp_digit div)
-{
-    sp_digit r;
-
-    __asm__ __volatile__ (
-        "movq	%[d0], %%rax\n\t"
-        "movq	%[d1], %%rdx\n\t"
-        "divq	%[div]\n\t"
-        "movq	%%rax, %[r]\n\t"
-        : [r] "=r" (r)
-        : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div)
-        : "rax", "rdx"
-    );
-
-    return r;
-}
-
-/* AND m into each word of a and store in r.
- *
- * r  A single precision integer.
- * a  A single precision integer.
- * m  Mask to AND against each digit.
- */
-static void sp_256_mask_4(sp_digit* r, sp_digit* a, sp_digit m)
-{
-#ifdef WOLFSSL_SP_SMALL
-    int i;
-
-    for (i=0; i<4; i++)
-        r[i] = a[i] & m;
-#else
-    r[0] = a[0] & m;
-    r[1] = a[1] & m;
-    r[2] = a[2] & m;
-    r[3] = a[3] & m;
-#endif
-}
-
-/* Divide d in a and put remainder into r (m*d + r = a)
- * m is not calculated as it is not needed at this time.
- *
- * a  Nmber to be divided.
- * d  Number to divide with.
- * m  Multiplier result.
- * r  Remainder from the division.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_div_4(sp_digit* a, sp_digit* d, sp_digit* m,
-        sp_digit* r)
-{
-    sp_digit t1[8], t2[5];
-    sp_digit div, r1;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)m;
-
-    div = d[3];
-    XMEMCPY(t1, a, sizeof(*t1) * 2 * 4);
-    for (i=3; i>=0; i--) {
-        r1 = div_256_word_4(t1[4 + i], t1[4 + i - 1], div);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_d_avx2_4(t2, d, r1);
-        else
-#endif
-            sp_256_mul_d_4(t2, d, r1);
-        t1[4 + i] += sp_256_sub_in_place_4(&t1[i], t2);
-        t1[4 + i] -= t2[4];
-        sp_256_mask_4(t2, d, t1[4 + i]);
-        t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2);
-        sp_256_mask_4(t2, d, t1[4 + i]);
-        t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2);
-    }
-
-    r1 = sp_256_cmp_4(t1, d) >= 0;
-    sp_256_cond_sub_4(r, t1, t2, (sp_digit)0 - r1);
-
-    return MP_OKAY;
-}
-
-/* Reduce a modulo m into r. (r = a mod m)
- *
- * r  A single precision number that is the reduced result.
- * a  A single precision number that is to be reduced.
- * m  A single precision number that is the modulus to reduce with.
- * returns MP_OKAY indicating success.
- */
-static WC_INLINE int sp_256_mod_4(sp_digit* r, sp_digit* a, sp_digit* m)
-{
-    return sp_256_div_4(a, m, NULL, r);
-}
-
-#endif
-#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
-/* Square a and put result in r. (r = a * a)
- *
- * r  A single precision integer.
- * a  A single precision integer.
- */
-SP_NOINLINE static void sp_256_sqr_4(sp_digit* r, const sp_digit* a)
-{
-    sp_digit tmp[4];
-
-    __asm__ __volatile__ (
-        "#  A[0] * A[0]\n\t"
-        "movq	0(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "movq	%%rax, (%[tmp])\n\t"
-        "movq	%%rdx, %%r8\n\t"
-        "#  A[0] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 8(%[tmp])\n\t"
-        "#  A[0] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "#  A[1] * A[1]\n\t"
-        "movq	8(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 16(%[tmp])\n\t"
-        "#  A[0] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	0(%[a])\n\t"
-        "xorq	%%r9, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "#  A[1] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "adcq	$0, %%r9\n\t"
-        "movq	%%rcx, 24(%[tmp])\n\t"
-        "#  A[1] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	8(%[a])\n\t"
-        "xorq	%%rcx, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "#  A[2] * A[2]\n\t"
-        "movq	16(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%r8\n\t"
-        "adcq	%%rdx, %%r9\n\t"
-        "adcq	$0, %%rcx\n\t"
-        "movq	%%r8, 32(%[r])\n\t"
-        "#  A[2] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	16(%[a])\n\t"
-        "xorq	%%r8, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "addq	%%rax, %%r9\n\t"
-        "adcq	%%rdx, %%rcx\n\t"
-        "adcq	$0, %%r8\n\t"
-        "movq	%%r9, 40(%[r])\n\t"
-        "#  A[3] * A[3]\n\t"
-        "movq	24(%[a]), %%rax\n\t"
-        "mulq	%%rax\n\t"
-        "addq	%%rax, %%rcx\n\t"
-        "adcq	%%rdx, %%r8\n\t"
-        "movq	%%rcx, 48(%[r])\n\t"
-        "movq	%%r8, 56(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp)
-        : "memory", "rax", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12"
-    );
-
-    XMEMCPY(r, tmp, sizeof(tmp));
-}
-
-#ifdef WOLFSSL_SP_SMALL
-/* Order-2 for the P256 curve. */
-static const uint64_t p256_order_2[4] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff,
-    0xffffffff00000000
-};
-#else
-/* The low half of the order-2 of the P256 curve. */
-static const uint64_t p256_order_low[2] = {
-    0xf3b9cac2fc63254f,0xbce6faada7179e84
-};
-#endif /* WOLFSSL_SP_SMALL */
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_4(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_4(r, a, b);
-    sp_256_mont_reduce_4(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_4(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_4(r, a);
-    sp_256_mont_reduce_4(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_4(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_4(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_4(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_4(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_4(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_4(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_4(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_4(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_4(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_4(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_4(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_4(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_4(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_4(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_4(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_4(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    sp_256_mont_mul_order_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_4(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_4(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#ifdef HAVE_INTEL_AVX2
-/* Square a and put result in r. (r = a * a)
- *
- * r   Result of squaring.
- * a   Number to square in Montogmery form.
- */
-SP_NOINLINE static void sp_256_sqr_avx2_4(sp_digit* r, const sp_digit* a)
-{
-    __asm__ __volatile__ (
-        "# A[0] * A[1]\n\t"
-        "movq   0(%[a]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%r9, %%r10\n\t"
-        "# A[0] * A[3]\n\t"
-        "mulxq  24(%[a]), %%r11, %%r12\n\t"
-        "# A[2] * A[1]\n\t"
-        "movq   16(%[a]), %%rdx\n\t"
-        "mulxq  8(%[a]), %%rcx, %%rbx\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "adoxq  %%rcx, %%r11\n\t"
-        "# A[2] * A[3]\n\t"
-        "mulxq  24(%[a]), %%r13, %%r14\n\t"
-        "adoxq  %%rbx, %%r12\n\t"
-        "# A[2] * A[0]\n\t"
-        "mulxq  0(%[a]), %%rcx, %%rbx\n\t"
-        "adoxq  %%r15, %%r13\n\t"
-        "adcxq  %%rcx, %%r10\n\t"
-        "adoxq  %%r15, %%r14\n\t"
-        "# A[1] * A[3]\n\t"
-        "movq   8(%[a]), %%rdx\n\t"
-        "mulxq  24(%[a]), %%rax, %%r8\n\t"
-        "adcxq  %%rbx, %%r11\n\t"
-        "adcxq  %%rax, %%r12\n\t"
-        "adcxq  %%r8, %%r13\n\t"
-        "adcxq  %%r15, %%r14\n\t"
-        "# Double with Carry Flag\n\t"
-        "xorq   %%r15, %%r15\n\t"
-        "# A[0] * A[0]\n\t"
-        "movq   0(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%r8, %%rax\n\t"
-        "adcxq  %%r9, %%r9\n\t"
-        "# A[1] * A[1]\n\t"
-        "movq   8(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%rcx, %%rbx\n\t"
-        "adcxq  %%r10, %%r10\n\t"
-        "adoxq  %%rax, %%r9\n\t"
-        "adcxq  %%r11, %%r11\n\t"
-        "adoxq  %%rcx, %%r10\n\t"
-        "# A[2] * A[2]\n\t"
-        "movq   16(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%rax, %%rcx\n\t"
-        "adcxq  %%r12, %%r12\n\t"
-        "adoxq  %%rbx, %%r11\n\t"
-        "adcxq  %%r13, %%r13\n\t"
-        "adoxq  %%rax, %%r12\n\t"
-        "# A[3] * A[3]\n\t"
-        "movq   24(%[a]), %%rdx\n\t"
-        "mulxq  %%rdx, %%rax, %%rbx\n\t"
-        "adcxq  %%r14, %%r14\n\t"
-        "adoxq  %%rcx, %%r13\n\t"
-        "adcxq  %%r15, %%r15\n\t"
-        "adoxq  %%rax, %%r14\n\t"
-        "adoxq  %%rbx, %%r15\n\t"
-        "movq	%%r8, 0(%[r])\n\t"
-        "movq	%%r9, 8(%[r])\n\t"
-        "movq	%%r10, 16(%[r])\n\t"
-        "movq	%%r11, 24(%[r])\n\t"
-        "movq	%%r12, 32(%[r])\n\t"
-        "movq	%%r13, 40(%[r])\n\t"
-        "movq	%%r14, 48(%[r])\n\t"
-        "movq	%%r15, 56(%[r])\n\t"
-        :
-        : [r] "r" (r), [a] "r" (a)
-        : "memory", "rax", "rdx", "rcx", "rbx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-/* Reduce the number back to 256 bits using Montgomery reduction.
- *
- * a   A single precision number to reduce in place.
- * m   The single precision number representing the modulus.
- * mp  The digit representing the negative inverse of m mod 2^n.
- */
-SP_NOINLINE static void sp_256_mont_reduce_avx2_4(sp_digit* a, sp_digit* m,
-        sp_digit mp)
-{
-    __asm__ __volatile__ (
-        "movq	0(%[a]), %%r12\n\t"
-        "movq	8(%[a]), %%r13\n\t"
-        "movq	16(%[a]), %%r14\n\t"
-        "movq	24(%[a]), %%r15\n\t"
-        "xorq	%%r10, %%r10\n\t"
-        "xorq	%%r11, %%r11\n\t"
-        "# a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp)\n\t"
-        "movq	32(%[a]), %%rax\n\t"
-        "#   mu = a[0] * mp\n\t"
-        "movq	%%r12, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%rcx\n\t"
-        "#   a[0] += m[0] * mu\n\t"
-        "mulx	0(%[m]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "#   a[1] += m[1] * mu\n\t"
-        "mulx	8(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "#   a[2] += m[2] * mu\n\t"
-        "mulx	16(%[m]), %%r8, %%r9\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "#   a[3] += m[3] * mu\n\t"
-        "mulx	24(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r15\n\t"
-        "adcxq	%%r8, %%r15\n\t"
-        "adoxq	%%rcx, %%rax\n\t"
-        "adcxq	%%r11, %%rax\n\t"
-        "adoxq	%%r11, %%r10\n\t"
-        "adcxq	%%r11, %%r10\n\t"
-        "# a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp)\n\t"
-        "movq	40(%[a]), %%r12\n\t"
-        "#   mu = a[1] * mp\n\t"
-        "movq	%%r13, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%rcx\n\t"
-        "#   a[1] += m[0] * mu\n\t"
-        "mulx	0(%[m]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "#   a[2] += m[1] * mu\n\t"
-        "mulx	8(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r14\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "#   a[3] += m[2] * mu\n\t"
-        "mulx	16(%[m]), %%r8, %%r9\n\t"
-        "adoxq	%%rcx, %%r15\n\t"
-        "adcxq	%%r8, %%r15\n\t"
-        "#   a[4] += m[3] * mu\n\t"
-        "mulx	24(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "adcxq	%%r10, %%r12\n\t"
-        "movq	%%r11, %%r10\n\t"
-        "adoxq	%%r11, %%r10\n\t"
-        "adcxq	%%r11, %%r10\n\t"
-        "# a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp)\n\t"
-        "movq	48(%[a]), %%r13\n\t"
-        "#   mu = a[2] * mp\n\t"
-        "movq	%%r14, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%rcx\n\t"
-        "#   a[2] += m[0] * mu\n\t"
-        "mulx	0(%[m]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r14\n\t"
-        "#   a[3] += m[1] * mu\n\t"
-        "mulx	8(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r15\n\t"
-        "adcxq	%%r8, %%r15\n\t"
-        "#   a[4] += m[2] * mu\n\t"
-        "mulx	16(%[m]), %%r8, %%r9\n\t"
-        "adoxq	%%rcx, %%rax\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "#   a[5] += m[3] * mu\n\t"
-        "mulx	24(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r12\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "adoxq	%%rcx, %%r13\n\t"
-        "adcxq	%%r10, %%r13\n\t"
-        "movq	%%r11, %%r10\n\t"
-        "adoxq	%%r11, %%r10\n\t"
-        "adcxq	%%r11, %%r10\n\t"
-        "# a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp)\n\t"
-        "movq	56(%[a]), %%r14\n\t"
-        "#   mu = a[3] * mp\n\t"
-        "movq	%%r15, %%rdx\n\t"
-        "mulxq	%[mp], %%rdx, %%rcx\n\t"
-        "#   a[3] += m[0] * mu\n\t"
-        "mulx	0(%[m]), %%r8, %%r9\n\t"
-        "adcxq	%%r8, %%r15\n\t"
-        "#   a[4] += m[1] * mu\n\t"
-        "mulx	8(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%rax\n\t"
-        "adcxq	%%r8, %%rax\n\t"
-        "#   a[5] += m[2] * mu\n\t"
-        "mulx	16(%[m]), %%r8, %%r9\n\t"
-        "adoxq	%%rcx, %%r12\n\t"
-        "adcxq	%%r8, %%r12\n\t"
-        "#   a[6] += m[3] * mu\n\t"
-        "mulx	24(%[m]), %%r8, %%rcx\n\t"
-        "adoxq	%%r9, %%r13\n\t"
-        "adcxq	%%r8, %%r13\n\t"
-        "adoxq	%%rcx, %%r14\n\t"
-        "adcxq	%%r10, %%r14\n\t"
-        "movq	%%r11, %%r10\n\t"
-        "adoxq	%%r11, %%r10\n\t"
-        "adcxq	%%r11, %%r10\n\t"
-        "# Subtract mod if carry\n\t"
-        "subq	%%r10, %%r11\n\t"
-        "movq	0(%[m]), %%r8\n\t"
-        "movq	8(%[m]), %%r9\n\t"
-        "movq	16(%[m]), %%r10\n\t"
-        "movq	24(%[m]), %%rdx\n\t"
-        "andq	%%r11, %%r8\n\t"
-        "andq	%%r11, %%r9\n\t"
-        "andq	%%r11, %%r10\n\t"
-        "andq	%%r11, %%rdx\n\t"
-        "subq	%%r8, %%rax\n\t"
-        "sbbq	%%r9, %%r12\n\t"
-        "sbbq	%%r10, %%r13\n\t"
-        "sbbq	%%rdx, %%r14\n\t"
-        "movq	%%rax,   (%[a])\n\t"
-        "movq	%%r12,  8(%[a])\n\t"
-        "movq	%%r13, 16(%[a])\n\t"
-        "movq	%%r14, 24(%[a])\n\t"
-        :
-        : [a] "r" (a), [m] "r" (m), [mp] "r" (mp)
-        : "memory", "rax", "rcx", "rdx", "r8", "r9", "r10", "r11",
-          "r12", "r13", "r14", "r15"
-    );
-}
-
-/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
- *
- * r  Result of the multiplication.
- * a  First operand of the multiplication.
- * b  Second operand of the multiplication.
- */
-static void sp_256_mont_mul_order_avx2_4(sp_digit* r, sp_digit* a, sp_digit* b)
-{
-    sp_256_mul_avx2_4(r, a, b);
-    sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order);
-}
-
-/* Square number mod the order of P256 curve. (r = a * a mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_order_avx2_4(sp_digit* r, sp_digit* a)
-{
-    sp_256_sqr_avx2_4(r, a);
-    sp_256_mont_reduce_avx2_4(r, p256_order, p256_mp_order);
-}
-
-#ifndef WOLFSSL_SP_SMALL
-/* Square number mod the order of P256 curve a number of times.
- * (r = a ^ n mod order)
- *
- * r  Result of the squaring.
- * a  Number to square.
- */
-static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, sp_digit* a, int n)
-{
-    int i;
-
-    sp_256_mont_sqr_order_avx2_4(r, a);
-    for (i=1; i<n; i++)
-        sp_256_mont_sqr_order_avx2_4(r, r);
-}
-#endif /* !WOLFSSL_SP_SMALL */
-
-/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
- * (r = 1 / a mod order)
- *
- * r   Inverse result.
- * a   Number to invert.
- * td  Temporary data.
- */
-static void sp_256_mont_inv_order_avx2_4(sp_digit* r, sp_digit* a,
-        sp_digit* td)
-{
-#ifdef WOLFSSL_SP_SMALL
-    sp_digit* t = td;
-    int i;
-
-    XMEMCPY(t, a, sizeof(sp_digit) * 4);
-    for (i=254; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_4(t, t);
-        if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t, t, a);
-    }
-    XMEMCPY(r, t, sizeof(sp_digit) * 4);
-#else
-    sp_digit* t = td;
-    sp_digit* t2 = td + 2 * 4;
-    sp_digit* t3 = td + 4 * 4;
-    int i;
-
-    /* t = a^2 */
-    sp_256_mont_sqr_order_avx2_4(t, a);
-    /* t = a^3 = t * a */
-    sp_256_mont_mul_order_avx2_4(t, t, a);
-    /* t2= a^c = t ^ 2 ^ 2 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 2);
-    /* t3= a^f = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t3, t2, t);
-    /* t2= a^f0 = t3 ^ 2 ^ 4 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t3, 4);
-    /* t = a^ff = t2 * t3 */
-    sp_256_mont_mul_order_avx2_4(t, t2, t3);
-    /* t3= a^ff00 = t ^ 2 ^ 8 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 8);
-    /* t = a^ffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t, t2, t);
-    /* t2= a^ffff0000 = t ^ 2 ^ 16 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 16);
-    /* t = a^ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t, t2, t);
-    /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64  */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t, 64);
-    /* t2= a^ffffffff00000000ffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32  */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 32);
-    /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
-    sp_256_mont_mul_order_avx2_4(t2, t2, t);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
-    for (i=127; i>=112; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
-    for (i=107; i>=64; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
-    for (i=59; i>=32; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    sp_256_mont_mul_order_avx2_4(t2, t2, t3);
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
-    for (i=27; i>=0; i--) {
-        sp_256_mont_sqr_order_avx2_4(t2, t2);
-        if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64)))
-            sp_256_mont_mul_order_avx2_4(t2, t2, a);
-    }
-    /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
-    sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4);
-    /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
-    sp_256_mont_mul_order_avx2_4(r, t2, t3);
-#endif /* WOLFSSL_SP_SMALL */
-}
-
-#endif /* HAVE_INTEL_AVX2 */
-#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */
-#ifdef HAVE_ECC_SIGN
-#ifndef SP_ECC_MAX_SIG_GEN
-#define SP_ECC_MAX_SIG_GEN  64
-#endif
-
-/* Sign the hash using the private key.
- *   e = [hash, 256 bits] from binary
- *   r = (k.G)->x mod order
- *   s = (r * x + e) / k mod order
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit ed[2*4];
-    sp_digit xd[2*4];
-    sp_digit kd[2*4];
-    sp_digit rd[2*4];
-    sp_digit td[3 * 2*4];
-    sp_point p;
-#endif
-    sp_digit* e = NULL;
-    sp_digit* x = NULL;
-    sp_digit* k = NULL;
-    sp_digit* r = NULL;
-    sp_digit* tmp = NULL;
-    sp_point* point = NULL;
-    sp_digit carry;
-    sp_digit* s;
-    sp_digit* kInv;
-    int err = MP_OKAY;
-    int64_t c;
-    int i;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    (void)heap;
-
-    err = sp_ecc_point_new(heap, p, point);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            e = d + 0 * 4;
-            x = d + 2 * 4;
-            k = d + 4 * 4;
-            r = d + 6 * 4;
-            tmp = d + 8 * 4;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    e = ed;
-    x = xd;
-    k = kd;
-    r = rd;
-    tmp = td;
-#endif
-    s = e;
-    kInv = k;
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(e, 4, hash, hashLen);
-        sp_256_from_mp(x, 4, priv);
-    }
-
-    for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
-        /* New random point. */
-        err = sp_256_ecc_gen_k_4(rng, k);
-        if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, heap);
-            else
-#endif
-                err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL);
-        }
-
-        if (err == MP_OKAY) {
-            /* r = point->x mod order */
-            XMEMCPY(r, point->x, sizeof(sp_digit) * 4);
-            sp_256_norm_4(r);
-            c = sp_256_cmp_4(r, p256_order);
-            sp_256_cond_sub_4(r, r, p256_order, 0 - (c >= 0));
-            sp_256_norm_4(r);
-
-            /* Conv k to Montgomery form (mod order) */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_4(k, k, p256_norm_order);
-            else
-#endif
-                sp_256_mul_4(k, k, p256_norm_order);
-            err = sp_256_mod_4(k, k, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_4(k);
-            /* kInv = 1/k mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_inv_order_avx2_4(kInv, k, tmp);
-            else
-#endif
-                sp_256_mont_inv_order_4(kInv, k, tmp);
-            sp_256_norm_4(kInv);
-
-            /* s = r * x + e */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mul_avx2_4(x, x, r);
-            else
-#endif
-                sp_256_mul_4(x, x, r);
-            err = sp_256_mod_4(x, x, p256_order);
-        }
-        if (err == MP_OKAY) {
-            sp_256_norm_4(x);
-            carry = sp_256_add_4(s, e, x);
-            sp_256_cond_sub_4(s, s, p256_order, 0 - carry);
-            sp_256_norm_4(s);
-            c = sp_256_cmp_4(s, p256_order);
-            sp_256_cond_sub_4(s, s, p256_order, 0 - (c >= 0));
-            sp_256_norm_4(s);
-
-            /* s = s * k^-1 mod order */
-#ifdef HAVE_INTEL_AVX2
-            if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-                sp_256_mont_mul_order_avx2_4(s, s, kInv);
-            else
-#endif
-                sp_256_mont_mul_order_4(s, s, kInv);
-            sp_256_norm_4(s);
-
-            /* Check that signature is usable. */
-            if (!sp_256_iszero_4(s))
-                break;
-        }
-    }
-
-    if (i == 0)
-        err = RNG_FAILURE_E;
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(r, rm);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(s, sm);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL) {
-        XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4);
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-    }
-#else
-    XMEMSET(e, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(x, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(k, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4);
-    XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*4);
-#endif
-    sp_ecc_point_free(point, 1, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-/* Verify the signature values with the hash and public key.
- *   e = Truncate(hash, 256)
- *   u1 = e/s mod order
- *   u2 = r/s mod order
- *   r == (u1.G + u2.Q)->x mod order
- * Optimization: Leave point in projective form.
- *   (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
- *   (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
- * The hash is truncated to the first 256 bits.
- *
- * hash     Hash to sign.
- * hashLen  Length of the hash data.
- * rng      Random number generator.
- * priv     Private part of key - scalar.
- * rm       First part of result as an mp_int.
- * sm       Sirst part of result as an mp_int.
- * heap     Heap to use for allocation.
- * returns RNG failures, MEMORY_E when memory allocation fails and
- * MP_OKAY on success.
- */
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
-    mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit u1d[2*4];
-    sp_digit u2d[2*4];
-    sp_digit sd[2*4];
-    sp_digit tmpd[2*4 * 5];
-    sp_point p1d;
-    sp_point p2d;
-#endif
-    sp_digit* u1;
-    sp_digit* u2;
-    sp_digit* s;
-    sp_digit* tmp;
-    sp_point* p1;
-    sp_point* p2 = NULL;
-    sp_digit carry;
-    int64_t c;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, p1d, p1);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, p2d, p2);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        d = XMALLOC(sizeof(sp_digit) * 16 * 4, heap, DYNAMIC_TYPE_ECC);
-        if (d != NULL) {
-            u1  = d + 0 * 4;
-            u2  = d + 2 * 4;
-            s   = d + 4 * 4;
-            tmp = d + 6 * 4;
-        }
-        else
-            err = MEMORY_E;
-    }
-#else
-    u1 = u1d;
-    u2 = u2d;
-    s  = sd;
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        if (hashLen > 32)
-            hashLen = 32;
-
-        sp_256_from_bin(u1, 4, hash, hashLen);
-        sp_256_from_mp(u2, 4, r);
-        sp_256_from_mp(s, 4, sm);
-        sp_256_from_mp(p2->x, 4, pX);
-        sp_256_from_mp(p2->y, 4, pY);
-        sp_256_from_mp(p2->z, 4, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_mul_avx2_4(s, s, p256_norm_order);
-        else
-#endif
-            sp_256_mul_4(s, s, p256_norm_order);
-        err = sp_256_mod_4(s, s, p256_order);
-    }
-    if (err == MP_OKAY) {
-        sp_256_norm_4(s);
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_inv_order_avx2_4(s, s, tmp);
-            sp_256_mont_mul_order_avx2_4(u1, u1, s);
-            sp_256_mont_mul_order_avx2_4(u2, u2, s);
-        }
-        else
-#endif
-        {
-            sp_256_mont_inv_order_4(s, s, tmp);
-            sp_256_mont_mul_order_4(u1, u1, s);
-            sp_256_mont_mul_order_4(u2, u2, s);
-        }
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap);
-    }
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap);
-    }
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp);
-        else
-#endif
-            sp_256_proj_point_add_4(p1, p1, p2, tmp);
-
-        /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
-        /* Reload r and convert to Montgomery form. */
-        sp_256_from_mp(u2, 4, r);
-        err = sp_256_mod_mul_norm_4(u2, u2, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* u1 = r.z'.z' mod prime */
-        sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod);
-        sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod);
-        *res = sp_256_cmp_4(p1->x, u1) == 0;
-        if (*res == 0) {
-            /* Reload r and add order. */
-            sp_256_from_mp(u2, 4, r);
-            carry = sp_256_add_4(u2, u2, p256_order);
-            /* Carry means result is greater than mod and is not valid. */
-            if (!carry) {
-                sp_256_norm_4(u2);
-
-                /* Compare with mod and if greater or equal then not valid. */
-                c = sp_256_cmp_4(u2, p256_mod);
-                if (c < 0) {
-                    /* Convert to Montogomery form */
-                    err = sp_256_mod_mul_norm_4(u2, u2, p256_mod);
-                    if (err == MP_OKAY) {
-                        /* u1 = (r + 1*order).z'.z' mod prime */
-                        sp_256_mont_mul_4(u1, u2, p1->z, p256_mod,
-                                                                  p256_mp_mod);
-                        *res = sp_256_cmp_4(p1->x, u2) == 0;
-                    }
-                }
-            }
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p1, 0, heap);
-    sp_ecc_point_free(p2, 0, heap);
-
-    return err;
-}
-#endif /* HAVE_ECC_VERIFY */
-
-#ifdef HAVE_ECC_CHECK_KEY
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * point  EC point.
- * heap   Heap to use if dynamically allocating.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-static int sp_256_ecc_is_point_4(sp_point* point, void* heap)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d = NULL;
-#else
-    sp_digit t1d[2*4];
-    sp_digit t2d[2*4];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 4;
-        t2 = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    (void)heap;
-
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_sqr_4(t1, point->y);
-        sp_256_mod_4(t1, t1, p256_mod);
-        sp_256_sqr_4(t2, point->x);
-        sp_256_mod_4(t2, t2, p256_mod);
-        sp_256_mul_4(t2, t2, point->x);
-        sp_256_mod_4(t2, t2, p256_mod);
-	sp_256_sub_4(t2, p256_mod, t2);
-        sp_256_mont_add_4(t1, t1, t2, p256_mod);
-
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-        sp_256_mont_add_4(t1, t1, point->x, p256_mod);
-
-        if (sp_256_cmp_4(t1, p256_b) != 0)
-            err = MP_VAL;
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, heap, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Check that the x and y oridinates are a valid point on the curve.
- *
- * pX  X ordinate of EC point.
- * pY  Y ordinate of EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve and MP_OKAY otherwise.
- */
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_point pubd;
-#endif
-    sp_point* pub;
-    byte one[1] = { 1 };
-    int err;
-
-    err = sp_ecc_point_new(NULL, pubd, pub);
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 4, pX);
-        sp_256_from_mp(pub->y, 4, pY);
-        sp_256_from_bin(pub->z, 4, one, sizeof(one));
-
-        err = sp_256_ecc_is_point_4(pub, NULL);
-    }
-
-    sp_ecc_point_free(pub, 0, NULL);
-
-    return err;
-}
-
-/* Check that the private scalar generates the EC point (px, py), the point is
- * on the curve and the point has the correct order.
- *
- * pX     X ordinate of EC point.
- * pY     Y ordinate of EC point.
- * privm  Private scalar that generates EC point.
- * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
- * not on the curve, ECC_INF_E if the point does not have the correct order,
- * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
- * MP_OKAY otherwise.
- */
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit privd[4];
-    sp_point pubd;
-    sp_point pd;
-#endif
-    sp_digit* priv = NULL;
-    sp_point* pub;
-    sp_point* p = NULL;
-    byte one[1] = { 1 };
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(heap, pubd, pub);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(heap, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        priv = XMALLOC(sizeof(sp_digit) * 4, heap, DYNAMIC_TYPE_ECC);
-        if (priv == NULL)
-            err = MEMORY_E;
-    }
-#else
-    priv = privd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(pub->x, 4, pX);
-        sp_256_from_mp(pub->y, 4, pY);
-        sp_256_from_bin(pub->z, 4, one, sizeof(one));
-        sp_256_from_mp(priv, 4, privm);
-
-        /* Check point at infinitiy. */
-        if (sp_256_iszero_4(pub->x) &&
-            sp_256_iszero_4(pub->y))
-            err = ECC_INF_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check range of X and Y */
-        if (sp_256_cmp_4(pub->x, p256_mod) >= 0 ||
-            sp_256_cmp_4(pub->y, p256_mod) >= 0)
-            err = ECC_OUT_OF_RANGE_E;
-    }
-
-    if (err == MP_OKAY) {
-        /* Check point is on curve */
-        err = sp_256_ecc_is_point_4(pub, heap);
-    }
-
-    if (err == MP_OKAY) {
-        /* Point * order = infinity */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_avx2_4(p, pub, p256_order, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is infinity */
-        if (!sp_256_iszero_4(p->x) ||
-            !sp_256_iszero_4(p->y)) {
-            err = ECC_INF_E;
-        }
-    }
-
-    if (err == MP_OKAY) {
-        /* Base * private = point */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            err = sp_256_ecc_mulmod_base_avx2_4(p, priv, 1, heap);
-        else
-#endif
-            err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap);
-    }
-    if (err == MP_OKAY) {
-        /* Check result is public key */
-        if (sp_256_cmp_4(p->x, pub->x) != 0 ||
-            sp_256_cmp_4(p->y, pub->y) != 0) {
-            err = ECC_PRIV_KEY_E;
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (priv != NULL)
-        XFREE(priv, heap, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, heap);
-    sp_ecc_point_free(pub, 0, heap);
-
-    return err;
-}
-#endif
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-/* Add two projective EC points together.
- * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
- *
- * pX   First EC point's X ordinate.
- * pY   First EC point's Y ordinate.
- * pZ   First EC point's Z ordinate.
- * qX   Second EC point's X ordinate.
- * qY   Second EC point's Y ordinate.
- * qZ   Second EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 5];
-    sp_point pd;
-    sp_point qd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    sp_point* q = NULL;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-    if (err == MP_OKAY)
-        err = sp_ecc_point_new(NULL, qd, q);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-        sp_256_from_mp(q->x, 4, qX);
-        sp_256_from_mp(q->y, 4, qY);
-        sp_256_from_mp(q->z, 4, qZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_add_avx2_4(p, p, q, tmp);
-        else
-#endif
-            sp_256_proj_point_add_4(p, p, q, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(q, 0, NULL);
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Double a projective EC point.
- * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * rX   Resultant EC point's X ordinate.
- * rY   Resultant EC point's Y ordinate.
- * rZ   Resultant EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 2];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
-            sp_256_proj_point_dbl_avx2_4(p, p, tmp);
-        else
-#endif
-            sp_256_proj_point_dbl_4(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, rX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, rY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, rZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-
-/* Map a projective EC point to affine in place.
- * pZ will be one.
- *
- * pX   EC point's X ordinate.
- * pY   EC point's Y ordinate.
- * pZ   EC point's Z ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
-{
-#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)
-    sp_digit tmpd[2 * 4 * 4];
-    sp_point pd;
-#endif
-    sp_digit* tmp;
-    sp_point* p;
-    int err;
-
-    err = sp_ecc_point_new(NULL, pd, p);
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (err == MP_OKAY) {
-        tmp = XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-        if (tmp == NULL)
-            err = MEMORY_E;
-    }
-#else
-    tmp = tmpd;
-#endif
-    if (err == MP_OKAY) {
-        sp_256_from_mp(p->x, 4, pX);
-        sp_256_from_mp(p->y, 4, pY);
-        sp_256_from_mp(p->z, 4, pZ);
-
-        sp_256_map_4(p, p, tmp);
-    }
-
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->x, pX);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->y, pY);
-    if (err == MP_OKAY)
-        err = sp_256_to_mp(p->z, pZ);
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (tmp != NULL)
-        XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
-#endif
-    sp_ecc_point_free(p, 0, NULL);
-
-    return err;
-}
-#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
-#ifdef HAVE_COMP_KEY
-/* Find the square root of a number mod the prime of the curve.
- *
- * y  The number to operate on and the result.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-static int sp_256_mont_sqrt_4(sp_digit* y)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit t1d[2 * 4];
-    sp_digit t2d[2 * 4];
-#endif
-    sp_digit* t1;
-    sp_digit* t2;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        t1 = d + 0 * 4;
-        t2 = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    t1 = t1d;
-    t2 = t2d;
-#endif
-
-    if (err == MP_OKAY) {
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_avx2_4(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_avx2_4(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_avx2_4(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_avx2_4(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_avx2_4(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            /* t2 = y ^ 0x2 */
-            sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0x3 */
-            sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xc */
-            sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xf */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xf0 */
-            sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xff00 */
-            sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t2 = y ^ 0xffff0000 */
-            sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff */
-            sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000000 */
-            sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001 */
-            sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
-            sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod);
-            /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
-            sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod);
-            sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod);
-        }
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-
-/* Uncompress the point given the X ordinate.
- *
- * xm    X ordinate.
- * odd   Whether the Y ordinate is odd.
- * ym    Calculated Y ordinate.
- * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
- */
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
-{
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    sp_digit* d;
-#else
-    sp_digit xd[2 * 4];
-    sp_digit yd[2 * 4];
-#endif
-    sp_digit* x;
-    sp_digit* y;
-    int err = MP_OKAY;
-#ifdef HAVE_INTEL_AVX2
-    word32 cpuid_flags = cpuid_get_flags();
-#endif
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    d = XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC);
-    if (d != NULL) {
-        x = d + 0 * 4;
-        y = d + 2 * 4;
-    }
-    else
-        err = MEMORY_E;
-#else
-    x = xd;
-    y = yd;
-#endif
-
-    if (err == MP_OKAY) {
-        sp_256_from_mp(x, 4, xm);
-
-        err = sp_256_mod_mul_norm_4(x, x, p256_mod);
-    }
-
-    if (err == MP_OKAY) {
-        /* y = x^3 */
-#ifdef HAVE_INTEL_AVX2
-        if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
-            sp_256_mont_sqr_avx2_4(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod);
-        }
-        else
-#endif
-        {
-            sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod);
-            sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod);
-        }
-        /* y = x^3 - 3x */
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        sp_256_mont_sub_4(y, y, x, p256_mod);
-        /* y = x^3 - 3x + b */
-        err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod);
-    }
-    if (err == MP_OKAY) {
-        sp_256_mont_add_4(y, y, x, p256_mod);
-        /* y = sqrt(x^3 - 3x + b) */
-        err = sp_256_mont_sqrt_4(y);
-    }
-    if (err == MP_OKAY) {
-        XMEMSET(y + 4, 0, 4 * sizeof(sp_digit));
-        sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod);
-        if (((y[0] ^ odd) & 1) != 0)
-            sp_256_mont_sub_4(y, p256_mod, y, p256_mod);
-
-        err = sp_256_to_mp(y, ym);
-    }
-
-#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
-    if (d != NULL)
-        XFREE(d, NULL, DYNAMIC_TYPE_ECC);
-#endif
-
-    return err;
-}
-#endif
-#endif /* WOLFSSL_SP_NO_256 */
-#endif /* WOLFSSL_HAVE_SP_ECC */
-#endif /* WOLFSSL_SP_X86_64_ASM */
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
--- a/wolfcrypt/src/srp.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,757 +0,0 @@
-/* srp.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef WOLFCRYPT_HAVE_SRP
-
-#include <wolfssl/wolfcrypt/srp.h>
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-/** Computes the session key using the Mask Generation Function 1. */
-static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size);
-
-static int SrpHashInit(SrpHash* hash, SrpType type)
-{
-    hash->type = type;
-
-    switch (type) {
-        case SRP_TYPE_SHA:
-            #ifndef NO_SHA
-                return wc_InitSha(&hash->data.sha);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA256:
-            #ifndef NO_SHA256
-                return wc_InitSha256(&hash->data.sha256);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA384:
-            #ifdef WOLFSSL_SHA384
-                return wc_InitSha384(&hash->data.sha384);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA512:
-            #ifdef WOLFSSL_SHA512
-                return wc_InitSha512(&hash->data.sha512);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-}
-
-static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size)
-{
-    switch (hash->type) {
-        case SRP_TYPE_SHA:
-            #ifndef NO_SHA
-                return wc_ShaUpdate(&hash->data.sha, data, size);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA256:
-            #ifndef NO_SHA256
-                return wc_Sha256Update(&hash->data.sha256, data, size);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA384:
-            #ifdef WOLFSSL_SHA384
-                return wc_Sha384Update(&hash->data.sha384, data, size);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA512:
-            #ifdef WOLFSSL_SHA512
-                return wc_Sha512Update(&hash->data.sha512, data, size);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-}
-
-static int SrpHashFinal(SrpHash* hash, byte* digest)
-{
-    switch (hash->type) {
-        case SRP_TYPE_SHA:
-            #ifndef NO_SHA
-                return wc_ShaFinal(&hash->data.sha, digest);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA256:
-            #ifndef NO_SHA256
-                return wc_Sha256Final(&hash->data.sha256, digest);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA384:
-            #ifdef WOLFSSL_SHA384
-                return wc_Sha384Final(&hash->data.sha384, digest);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        case SRP_TYPE_SHA512:
-            #ifdef WOLFSSL_SHA512
-                return wc_Sha512Final(&hash->data.sha512, digest);
-            #else
-                return BAD_FUNC_ARG;
-            #endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-}
-
-static word32 SrpHashSize(SrpType type)
-{
-    switch (type) {
-        case SRP_TYPE_SHA:
-            #ifndef NO_SHA
-                return WC_SHA_DIGEST_SIZE;
-            #else
-                return 0;
-            #endif
-
-        case SRP_TYPE_SHA256:
-            #ifndef NO_SHA256
-                return WC_SHA256_DIGEST_SIZE;
-            #else
-                return 0;
-            #endif
-
-        case SRP_TYPE_SHA384:
-            #ifdef WOLFSSL_SHA384
-                return WC_SHA384_DIGEST_SIZE;
-            #else
-                return 0;
-            #endif
-
-        case SRP_TYPE_SHA512:
-            #ifdef WOLFSSL_SHA512
-                return WC_SHA512_DIGEST_SIZE;
-            #else
-                return 0;
-            #endif
-
-        default:
-            return 0;
-    }
-}
-
-int wc_SrpInit(Srp* srp, SrpType type, SrpSide side)
-{
-    int r;
-
-    /* validating params */
-
-    if (!srp)
-        return BAD_FUNC_ARG;
-
-    if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE)
-        return BAD_FUNC_ARG;
-
-    switch (type) {
-        case SRP_TYPE_SHA:
-            #ifdef NO_SHA
-                return NOT_COMPILED_IN;
-            #else
-                break; /* OK */
-            #endif
-
-        case SRP_TYPE_SHA256:
-            #ifdef NO_SHA256
-                return NOT_COMPILED_IN;
-            #else
-                break; /* OK */
-            #endif
-
-        case SRP_TYPE_SHA384:
-            #ifndef WOLFSSL_SHA384
-                return NOT_COMPILED_IN;
-            #else
-                break; /* OK */
-            #endif
-
-        case SRP_TYPE_SHA512:
-            #ifndef WOLFSSL_SHA512
-                return NOT_COMPILED_IN;
-            #else
-                break; /* OK */
-            #endif
-
-        default:
-            return BAD_FUNC_ARG;
-    }
-
-    /* initializing variables */
-
-    XMEMSET(srp, 0, sizeof(Srp));
-
-    if ((r = SrpHashInit(&srp->client_proof, type)) != 0)
-        return r;
-
-    if ((r = SrpHashInit(&srp->server_proof, type)) != 0)
-        return r;
-
-    if ((r = mp_init_multi(&srp->N,    &srp->g, &srp->auth,
-                           &srp->priv, 0, 0)) != 0)
-        return r;
-
-    srp->side = side;    srp->type   = type;
-    srp->salt = NULL;    srp->saltSz = 0;
-    srp->user = NULL;    srp->userSz = 0;
-    srp->key  = NULL;    srp->keySz  = 0;
-
-    srp->keyGenFunc_cb = wc_SrpSetKey;
-
-    /* default heap hint to NULL or test value */
-#ifdef WOLFSSL_HEAP_TEST
-    srp->heap = (void*)WOLFSSL_HEAP_TEST;
-#else
-    srp->heap = NULL;
-#endif
-
-    return 0;
-}
-
-void wc_SrpTerm(Srp* srp)
-{
-    if (srp) {
-        mp_clear(&srp->N);    mp_clear(&srp->g);
-        mp_clear(&srp->auth); mp_clear(&srp->priv);
-        if (srp->salt) {
-            ForceZero(srp->salt, srp->saltSz);
-            XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP);
-        }
-        if (srp->user) {
-            ForceZero(srp->user, srp->userSz);
-            XFREE(srp->user, srp->heap, DYNAMIC_TYPE_SRP);
-        }
-        if (srp->key) {
-            ForceZero(srp->key, srp->keySz);
-            XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP);
-        }
-
-        ForceZero(srp, sizeof(Srp));
-    }
-}
-
-int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size)
-{
-    if (!srp || !username)
-        return BAD_FUNC_ARG;
-
-    srp->user = (byte*)XMALLOC(size, srp->heap, DYNAMIC_TYPE_SRP);
-    if (srp->user == NULL)
-        return MEMORY_E;
-
-    srp->userSz = size;
-    XMEMCPY(srp->user, username, srp->userSz);
-
-    return 0;
-}
-
-int wc_SrpSetParams(Srp* srp, const byte* N,    word32 nSz,
-                              const byte* g,    word32 gSz,
-                              const byte* salt, word32 saltSz)
-{
-    SrpHash hash;
-    byte digest1[SRP_MAX_DIGEST_SIZE];
-    byte digest2[SRP_MAX_DIGEST_SIZE];
-    byte pad = 0;
-    int i, r;
-    int j = 0;
-
-    if (!srp || !N || !g || !salt || nSz < gSz)
-        return BAD_FUNC_ARG;
-
-    if (!srp->user)
-        return SRP_CALL_ORDER_E;
-
-    /* Set N */
-    if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY)
-        return MP_READ_E;
-
-    if (mp_count_bits(&srp->N) < SRP_MODULUS_MIN_BITS)
-        return BAD_FUNC_ARG;
-
-    /* Set g */
-    if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY)
-        return MP_READ_E;
-
-    if (mp_cmp(&srp->N, &srp->g) != MP_GT)
-        return BAD_FUNC_ARG;
-
-    /* Set salt */
-    if (srp->salt) {
-        ForceZero(srp->salt, srp->saltSz);
-        XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP);
-    }
-
-    srp->salt = (byte*)XMALLOC(saltSz, srp->heap, DYNAMIC_TYPE_SRP);
-    if (srp->salt == NULL)
-        return MEMORY_E;
-
-    XMEMCPY(srp->salt, salt, saltSz);
-    srp->saltSz = saltSz;
-
-    /* Set k = H(N, g) */
-            r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz);
-    for (i = 0; (word32)i < nSz - gSz; i++) {
-        if (!r) r = SrpHashUpdate(&hash, &pad, 1);
-    }
-    if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
-    if (!r) r = SrpHashFinal(&hash, srp->k);
-
-    /* update client proof */
-
-    /* digest1 = H(N) */
-    if (!r) r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz);
-    if (!r) r = SrpHashFinal(&hash, digest1);
-
-    /* digest2 = H(g) */
-    if (!r) r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
-    if (!r) r = SrpHashFinal(&hash, digest2);
-
-    /* digest1 = H(N) ^ H(g) */
-    if (r == 0) {
-        for (i = 0, j = SrpHashSize(srp->type); i < j; i++)
-            digest1[i] ^= digest2[i];
-    }
-
-    /* digest2 = H(user) */
-    if (!r) r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
-    if (!r) r = SrpHashFinal(&hash, digest2);
-
-    /* client proof = H( H(N) ^ H(g) | H(user) | salt) */
-    if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j);
-    if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j);
-    if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz);
-
-    return r;
-}
-
-int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
-{
-    SrpHash hash;
-    byte digest[SRP_MAX_DIGEST_SIZE];
-    word32 digestSz;
-    int r;
-
-    if (!srp || !password || srp->side != SRP_CLIENT_SIDE)
-        return BAD_FUNC_ARG;
-
-    if (!srp->salt)
-        return SRP_CALL_ORDER_E;
-
-    digestSz = SrpHashSize(srp->type);
-
-    /* digest = H(username | ':' | password) */
-            r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
-    if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1);
-    if (!r) r = SrpHashUpdate(&hash, password, size);
-    if (!r) r = SrpHashFinal(&hash, digest);
-
-    /* digest = H(salt | H(username | ':' | password)) */
-    if (!r) r = SrpHashInit(&hash, srp->type);
-    if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz);
-    if (!r) r = SrpHashUpdate(&hash, digest, digestSz);
-    if (!r) r = SrpHashFinal(&hash, digest);
-
-    /* Set x (private key) */
-    if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz);
-
-    ForceZero(digest, SRP_MAX_DIGEST_SIZE);
-
-    return r;
-}
-
-int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size)
-{
-    mp_int v;
-    int r;
-
-    if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE)
-        return BAD_FUNC_ARG;
-
-    if (mp_iszero(&srp->auth) == MP_YES)
-        return SRP_CALL_ORDER_E;
-
-    r = mp_init(&v);
-    if (r != MP_OKAY)
-        return MP_INIT_E;
-
-    /* v = g ^ x % N */
-    if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v);
-    if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY;
-    if (!r) r = mp_to_unsigned_bin(&v, verifier);
-    if (!r) *size = mp_unsigned_bin_size(&v);
-
-    mp_clear(&v);
-
-    return r;
-}
-
-int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size)
-{
-    if (!srp || !verifier || srp->side != SRP_SERVER_SIDE)
-        return BAD_FUNC_ARG;
-
-    return mp_read_unsigned_bin(&srp->auth, verifier, size);
-}
-
-int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size)
-{
-    mp_int p;
-    int r;
-
-    if (!srp || !priv || !size)
-        return BAD_FUNC_ARG;
-
-    if (mp_iszero(&srp->auth) == MP_YES)
-        return SRP_CALL_ORDER_E;
-
-    r = mp_init(&p);
-    if (r != MP_OKAY)
-        return MP_INIT_E;
-    if (!r) r = mp_read_unsigned_bin(&p, priv, size);
-    if (!r) r = mp_mod(&p, &srp->N, &srp->priv);
-    if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0;
-
-    mp_clear(&p);
-
-    return r;
-}
-
-/** Generates random data using wolfcrypt RNG. */
-static int wc_SrpGenPrivate(Srp* srp, byte* priv, word32 size)
-{
-    WC_RNG rng;
-    int r = wc_InitRng(&rng);
-
-    if (!r) r = wc_RNG_GenerateBlock(&rng, priv, size);
-    if (!r) r = wc_SrpSetPrivate(srp, priv, size);
-    if (!r) wc_FreeRng(&rng);
-
-    return r;
-}
-
-int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size)
-{
-    mp_int pubkey;
-    word32 modulusSz;
-    int r;
-
-    if (!srp || !pub || !size)
-        return BAD_FUNC_ARG;
-
-    if (mp_iszero(&srp->auth) == MP_YES)
-        return SRP_CALL_ORDER_E;
-
-    modulusSz = mp_unsigned_bin_size(&srp->N);
-    if (*size < modulusSz)
-        return BUFFER_E;
-
-    r = mp_init(&pubkey);
-    if (r != MP_OKAY)
-        return MP_INIT_E;
-
-    /* priv = random() */
-    if (mp_iszero(&srp->priv) == MP_YES)
-        r = wc_SrpGenPrivate(srp, pub, SRP_PRIVATE_KEY_MIN_BITS / 8);
-
-    /* client side: A = g ^ a % N */
-    if (srp->side == SRP_CLIENT_SIDE) {
-        if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey);
-
-    /* server side: B = (k * v + (g ^ b % N)) % N */
-    } else {
-        mp_int i, j;
-
-        if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) {
-            if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type));
-            if (!r) r = mp_iszero(&i) == MP_YES ? SRP_BAD_KEY_E : 0;
-            if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey);
-            if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j);
-            if (!r) r = mp_add(&j, &pubkey, &i);
-            if (!r) r = mp_mod(&i, &srp->N, &pubkey);
-
-            mp_clear(&i); mp_clear(&j);
-        }
-    }
-
-    /* extract public key to buffer */
-    XMEMSET(pub, 0, modulusSz);
-    if (!r) r = mp_to_unsigned_bin(&pubkey, pub);
-    if (!r) *size = mp_unsigned_bin_size(&pubkey);
-    mp_clear(&pubkey);
-
-    return r;
-}
-
-static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size)
-{
-    SrpHash hash;
-    byte digest[SRP_MAX_DIGEST_SIZE];
-    word32 i, j, digestSz = SrpHashSize(srp->type);
-    byte counter[4];
-    int r = BAD_FUNC_ARG;
-
-    XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE);
-
-    srp->key = (byte*)XMALLOC(2 * digestSz, srp->heap, DYNAMIC_TYPE_SRP);
-    if (srp->key == NULL)
-        return MEMORY_E;
-
-    srp->keySz = 2 * digestSz;
-
-    for (i = j = 0; j < srp->keySz; i++) {
-        counter[0] = (i >> 24) & 0xFF;
-        counter[1] = (i >> 16) & 0xFF;
-        counter[2] = (i >>  8) & 0xFF;
-        counter[3] =  i        & 0xFF;
-
-        r = SrpHashInit(&hash, srp->type);
-        if (!r) r = SrpHashUpdate(&hash, secret, size);
-        if (!r) r = SrpHashUpdate(&hash, counter, 4);
-
-        if (j + digestSz > srp->keySz) {
-            if (!r) r = SrpHashFinal(&hash, digest);
-            XMEMCPY(srp->key + j, digest, srp->keySz - j);
-            j = srp->keySz;
-        }
-        else {
-            if (!r) r = SrpHashFinal(&hash, srp->key + j);
-            j += digestSz;
-        }
-    }
-
-    ForceZero(digest, sizeof(digest));
-    ForceZero(&hash, sizeof(SrpHash));
-
-    return r;
-}
-
-int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz,
-                               byte* serverPubKey, word32 serverPubKeySz)
-{
-    SrpHash hash;
-    byte *secret;
-    byte digest[SRP_MAX_DIGEST_SIZE];
-    word32 i, secretSz, digestSz;
-    mp_int u, s, temp1, temp2;
-    byte pad = 0;
-    int r;
-
-    /* validating params */
-
-    if (!srp || !clientPubKey || clientPubKeySz == 0
-             || !serverPubKey || serverPubKeySz == 0)
-        return BAD_FUNC_ARG;
-
-    if (mp_iszero(&srp->priv) == MP_YES)
-        return SRP_CALL_ORDER_E;
-
-    /* initializing variables */
-
-    if ((r = SrpHashInit(&hash, srp->type)) != 0)
-        return r;
-
-    digestSz = SrpHashSize(srp->type);
-    secretSz = mp_unsigned_bin_size(&srp->N);
-
-    if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) ==NULL)
-        return MEMORY_E;
-
-    if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) {
-        XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP);
-        return r;
-    }
-
-    /* building u (random scrambling parameter) */
-
-    /* H(A) */
-    for (i = 0; !r && i < secretSz - clientPubKeySz; i++)
-        r = SrpHashUpdate(&hash, &pad, 1);
-    if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz);
-
-    /* H(A | B) */
-    for (i = 0; !r && i < secretSz - serverPubKeySz; i++)
-        r = SrpHashUpdate(&hash, &pad, 1);
-    if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz);
-
-    /* set u */
-    if (!r) r = SrpHashFinal(&hash, digest);
-    if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type));
-
-    /* building s (secret) */
-
-    if (!r && srp->side == SRP_CLIENT_SIDE) {
-
-        /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */
-        r = mp_read_unsigned_bin(&temp1, srp->k, digestSz);
-        if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2);
-        if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s);
-        if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz);
-        if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_sub(&temp2, &s, &temp1);
-
-        /* temp2 = a + u * x */
-        if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s);
-        if (!r) r = mp_add(&srp->priv, &s, &temp2);
-
-        /* secret = temp1 ^ temp2 % N */
-        if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s);
-
-    } else if (!r && srp->side == SRP_SERVER_SIDE) {
-        /* temp1 = v ^ u % N */
-        r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1);
-
-        /* temp2 = A * temp1 % N; rejects A == 0, A >= N */
-        if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz);
-        if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2);
-
-        /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */
-        if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1);
-        if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0;
-        if (!r) r = mp_sub(&srp->N, &temp1, &s);
-        if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0;
-
-        /* secret = temp2 * b % N */
-        if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s);
-    }
-
-    /* building session key from secret */
-
-    if (!r) r = mp_to_unsigned_bin(&s, secret);
-    if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s));
-
-    /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */
-
-    if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz);
-    if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz);
-    if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key,     srp->keySz);
-
-    /* updating server proof = H(A) */
-
-    if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz);
-
-    XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP);
-    mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2);
-
-    return r;
-}
-
-int wc_SrpGetProof(Srp* srp, byte* proof, word32* size)
-{
-    int r;
-
-    if (!srp || !proof || !size)
-        return BAD_FUNC_ARG;
-
-    if (*size < SrpHashSize(srp->type))
-        return BUFFER_E;
-
-    if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE
-                          ? &srp->client_proof
-                          : &srp->server_proof, proof)) != 0)
-        return r;
-
-    *size = SrpHashSize(srp->type);
-
-    if (srp->side == SRP_CLIENT_SIDE) {
-        /* server proof = H( A | client proof | K) */
-        if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size);
-        if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz);
-    }
-
-    return r;
-}
-
-int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size)
-{
-    byte digest[SRP_MAX_DIGEST_SIZE];
-    int r;
-
-    if (!srp || !proof)
-        return BAD_FUNC_ARG;
-
-    if (size != SrpHashSize(srp->type))
-        return BUFFER_E;
-
-    r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof
-                                                  : &srp->client_proof, digest);
-
-    if (srp->side == SRP_SERVER_SIDE) {
-        /* server proof = H( A | client proof | K) */
-        if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size);
-        if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz);
-    }
-
-    if (!r && XMEMCMP(proof, digest, size) != 0)
-        r = SRP_VERIFY_E;
-
-    return r;
-}
-
-#endif /* WOLFCRYPT_HAVE_SRP */
-
--- a/wolfcrypt/src/tfm.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3419 +0,0 @@
-/* tfm.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-/*
- * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca,
- * http://math.libtomcrypt.com
- */
-
-/**
- *  Edited by Moises Guimaraes (moises@wolfssl.com)
- *  to fit wolfSSL's needs.
- */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-/* in case user set USE_FAST_MATH there */
-#include <wolfssl/wolfcrypt/settings.h>
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#ifdef USE_FAST_MATH
-
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/tfm.h>
-#include <wolfcrypt/src/asm.c>  /* will define asm MACROS or C ones */
-#include <wolfssl/wolfcrypt/wolfmath.h> /* common functions */
-
-#if defined(FREESCALE_LTC_TFM)
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-#ifdef WOLFSSL_DEBUG_MATH
-    #include <stdio.h>
-#endif
-
-
-/* math settings check */
-word32 CheckRunTimeSettings(void)
-{
-    return CTC_SETTINGS;
-}
-
-
-/* math settings size check */
-word32 CheckRunTimeFastMath(void)
-{
-    return FP_SIZE;
-}
-
-
-/* Functions */
-
-void fp_add(fp_int *a, fp_int *b, fp_int *c)
-{
-  int     sa, sb;
-
-  /* get sign of both inputs */
-  sa = a->sign;
-  sb = b->sign;
-
-  /* handle two cases, not four */
-  if (sa == sb) {
-    /* both positive or both negative */
-    /* add their magnitudes, copy the sign */
-    c->sign = sa;
-    s_fp_add (a, b, c);
-  } else {
-    /* one positive, the other negative */
-    /* subtract the one with the greater magnitude from */
-    /* the one of the lesser magnitude.  The result gets */
-    /* the sign of the one with the greater magnitude. */
-    if (fp_cmp_mag (a, b) == FP_LT) {
-      c->sign = sb;
-      s_fp_sub (b, a, c);
-    } else {
-      c->sign = sa;
-      s_fp_sub (a, b, c);
-    }
-  }
-}
-
-/* unsigned addition */
-void s_fp_add(fp_int *a, fp_int *b, fp_int *c)
-{
-  int      x, y, oldused;
-  fp_word  t;
-
-  y       = MAX(a->used, b->used);
-  oldused = MIN(c->used, FP_SIZE);   /* help static analysis w/ largest size */
-  c->used = y;
-
-  t = 0;
-  for (x = 0; x < y; x++) {
-      t         += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]);
-      c->dp[x]   = (fp_digit)t;
-      t        >>= DIGIT_BIT;
-  }
-  if (t != 0 && x < FP_SIZE) {
-     c->dp[c->used++] = (fp_digit)t;
-     ++x;
-  }
-
-  c->used = x;
-
-  /* zero any excess digits on the destination that we didn't write to */
-  for (; x < oldused; x++) {
-     c->dp[x] = 0;
-  }
-  fp_clamp(c);
-}
-
-/* c = a - b */
-void fp_sub(fp_int *a, fp_int *b, fp_int *c)
-{
-  int     sa, sb;
-
-  sa = a->sign;
-  sb = b->sign;
-
-  if (sa != sb) {
-    /* subtract a negative from a positive, OR */
-    /* subtract a positive from a negative. */
-    /* In either case, ADD their magnitudes, */
-    /* and use the sign of the first number. */
-    c->sign = sa;
-    s_fp_add (a, b, c);
-  } else {
-    /* subtract a positive from a positive, OR */
-    /* subtract a negative from a negative. */
-    /* First, take the difference between their */
-    /* magnitudes, then... */
-    if (fp_cmp_mag (a, b) != FP_LT) {
-      /* Copy the sign from the first */
-      c->sign = sa;
-      /* The first has a larger or equal magnitude */
-      s_fp_sub (a, b, c);
-    } else {
-      /* The result has the *opposite* sign from */
-      /* the first number. */
-      c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS;
-      /* The second has a larger magnitude */
-      s_fp_sub (b, a, c);
-    }
-  }
-}
-
-/* unsigned subtraction ||a|| >= ||b|| ALWAYS! */
-void s_fp_sub(fp_int *a, fp_int *b, fp_int *c)
-{
-  int      x, oldbused, oldused;
-  fp_word  t;
-
-  oldused  = c->used;
-  oldbused = b->used;
-  c->used  = a->used;
-  t       = 0;
-  for (x = 0; x < oldbused; x++) {
-     t         = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t);
-     c->dp[x]  = (fp_digit)t;
-     t         = (t >> DIGIT_BIT)&1;
-  }
-  for (; x < a->used; x++) {
-     t         = ((fp_word)a->dp[x]) - t;
-     c->dp[x]  = (fp_digit)t;
-     t         = (t >> DIGIT_BIT)&1;
-   }
-
-  /* zero any excess digits on the destination that we didn't write to */
-  for (; x < oldused; x++) {
-     c->dp[x] = 0;
-  }
-  fp_clamp(c);
-}
-
-/* c = a * b */
-void fp_mul(fp_int *A, fp_int *B, fp_int *C)
-{
-    int   y, yy, oldused;
-
-    oldused = C->used;
-
-    y  = MAX(A->used, B->used);
-    yy = MIN(A->used, B->used);
-
-    /* call generic if we're out of range */
-    if (y + yy > FP_SIZE) {
-       fp_mul_comba(A, B, C);
-       goto clean;
-    }
-
-    /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size
-       of the largest input.  We also want to avoid doing excess mults if the
-       inputs are not close to the next power of two.  That is, for example,
-       if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications
-    */
-
-#if defined(TFM_MUL3) && FP_SIZE >= 6
-        if (y <= 3) {
-           fp_mul_comba3(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL4) && FP_SIZE >= 8
-        if (y == 4) {
-           fp_mul_comba4(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL6) && FP_SIZE >= 12
-        if (y <= 6) {
-           fp_mul_comba6(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL7) && FP_SIZE >= 14
-        if (y == 7) {
-           fp_mul_comba7(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL8) && FP_SIZE >= 16
-        if (y == 8) {
-           fp_mul_comba8(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL9) && FP_SIZE >= 18
-        if (y == 9) {
-           fp_mul_comba9(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL12) && FP_SIZE >= 24
-        if (y <= 12) {
-           fp_mul_comba12(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL17) && FP_SIZE >= 34
-        if (y <= 17) {
-           fp_mul_comba17(A,B,C);
-           goto clean;
-        }
-#endif
-
-#if defined(TFM_SMALL_SET) && FP_SIZE >= 32
-        if (y <= 16) {
-           fp_mul_comba_small(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL20) && FP_SIZE >= 40
-        if (y <= 20) {
-           fp_mul_comba20(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL24) && FP_SIZE >= 48
-        if (yy >= 16 && y <= 24) {
-           fp_mul_comba24(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL28) && FP_SIZE >= 56
-        if (yy >= 20 && y <= 28) {
-           fp_mul_comba28(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL32) && FP_SIZE >= 64
-        if (yy >= 24 && y <= 32) {
-           fp_mul_comba32(A,B,C);
-           goto clean;
-        }
-#endif
-#if defined(TFM_MUL48) && FP_SIZE >= 96
-        if (yy >= 40 && y <= 48) {
-          fp_mul_comba48(A,B,C);
-          goto clean;
-        }
-#endif
-#if defined(TFM_MUL64) && FP_SIZE >= 128
-        if (yy >= 56 && y <= 64) {
-           fp_mul_comba64(A,B,C);
-           goto clean;
-        }
-#endif
-        fp_mul_comba(A,B,C);
-
-clean:
-    /* zero any excess digits on the destination that we didn't write to */
-    for (y = C->used; y >= 0 && y < oldused; y++) {
-        C->dp[y] = 0;
-    }
-}
-
-void fp_mul_2(fp_int * a, fp_int * b)
-{
-  int     x, oldused;
-
-  oldused = b->used;
-  b->used = a->used;
-
-  {
-    fp_digit r, rr, *tmpa, *tmpb;
-
-    /* alias for source */
-    tmpa = a->dp;
-
-    /* alias for dest */
-    tmpb = b->dp;
-
-    /* carry */
-    r = 0;
-    for (x = 0; x < a->used; x++) {
-
-      /* get what will be the *next* carry bit from the
-       * MSB of the current digit
-       */
-      rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1));
-
-      /* now shift up this digit, add in the carry [from the previous] */
-      *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r);
-
-      /* copy the carry that would be from the source
-       * digit into the next iteration
-       */
-      r = rr;
-    }
-
-    /* new leading digit? */
-    if (r != 0 && b->used != (FP_SIZE-1)) {
-      /* add a MSB which is always 1 at this point */
-      *tmpb = 1;
-      ++(b->used);
-    }
-
-    /* zero any excess digits on the destination that we didn't write to */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-}
-
-/* c = a * b */
-void fp_mul_d(fp_int *a, fp_digit b, fp_int *c)
-{
-   fp_word  w;
-   int      x, oldused;
-
-   oldused = c->used;
-   c->used = a->used;
-   c->sign = a->sign;
-   w       = 0;
-   for (x = 0; x < a->used; x++) {
-       w         = ((fp_word)a->dp[x]) * ((fp_word)b) + w;
-       c->dp[x]  = (fp_digit)w;
-       w         = w >> DIGIT_BIT;
-   }
-   if (w != 0 && (a->used != FP_SIZE)) {
-      c->dp[c->used++] = (fp_digit) w;
-      ++x;
-   }
-
-   /* zero any excess digits on the destination that we didn't write to */
-   for (; x < oldused; x++) {
-      c->dp[x] = 0;
-   }
-   fp_clamp(c);
-}
-
-/* c = a * 2**d */
-void fp_mul_2d(fp_int *a, int b, fp_int *c)
-{
-   fp_digit carry, carrytmp, shift;
-   int x;
-
-   /* copy it */
-   fp_copy(a, c);
-
-   /* handle whole digits */
-   if (b >= DIGIT_BIT) {
-      fp_lshd(c, b/DIGIT_BIT);
-   }
-   b %= DIGIT_BIT;
-
-   /* shift the digits */
-   if (b != 0) {
-      carry = 0;
-      shift = DIGIT_BIT - b;
-      for (x = 0; x < c->used; x++) {
-          carrytmp = c->dp[x] >> shift;
-          c->dp[x] = (c->dp[x] << b) + carry;
-          carry = carrytmp;
-      }
-      /* store last carry if room */
-      if (carry && x < FP_SIZE) {
-         c->dp[c->used++] = carry;
-      }
-   }
-   fp_clamp(c);
-}
-
-/* generic PxQ multiplier */
-#if defined(HAVE_INTEL_MULX)
-
-WC_INLINE static void fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C)
-
-{
-   int       ix, iy, iz, pa;
-   fp_int    tmp, *dst;
-
-   /* get size of output and trim */
-   pa = A->used + B->used;
-   if (pa >= FP_SIZE) {
-      pa = FP_SIZE-1;
-   }
-
-   /* Always take branch to use tmp variable. This avoids a cache attack for
-    * determining if C equals A */
-   if (1) {
-      fp_init(&tmp);
-      dst = &tmp;
-   }
-
-   TFM_INTEL_MUL_COMBA(A, B, dst) ;
-
-  dst->used = pa;
-  dst->sign = A->sign ^ B->sign;
-  fp_clamp(dst);
-  fp_copy(dst, C);
-}
-#endif
-
-void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C)
-{
-   int       ix, iy, iz, tx, ty, pa;
-   fp_digit  c0, c1, c2, *tmpx, *tmpy;
-   fp_int    tmp, *dst;
-
-   IF_HAVE_INTEL_MULX(fp_mul_comba_mulx(A, B, C), return) ;
-
-   COMBA_START;
-   COMBA_CLEAR;
-
-   /* get size of output and trim */
-   pa = A->used + B->used;
-   if (pa >= FP_SIZE) {
-      pa = FP_SIZE-1;
-   }
-
-   /* Always take branch to use tmp variable. This avoids a cache attack for
-    * determining if C equals A */
-   if (1) {
-      fp_init(&tmp);
-      dst = &tmp;
-   }
-
-   for (ix = 0; ix < pa; ix++) {
-      /* get offsets into the two bignums */
-      ty = MIN(ix, (B->used > 0 ? B->used - 1 : 0));
-      tx = ix - ty;
-
-      /* setup temp aliases */
-      tmpx = A->dp + tx;
-      tmpy = B->dp + ty;
-
-      /* this is the number of times the loop will iterate, essentially its
-         while (tx++ < a->used && ty-- >= 0) { ... }
-       */
-      iy = MIN(A->used-tx, ty+1);
-
-      /* execute loop */
-      COMBA_FORWARD;
-      for (iz = 0; iz < iy; ++iz) {
-          fp_digit _tmpx = *tmpx++;
-          fp_digit _tmpy = *tmpy--;
-          MULADD(_tmpx, _tmpy);
-      }
-
-      /* store term */
-      COMBA_STORE(dst->dp[ix]);
-  }
-  COMBA_FINI;
-
-  dst->used = pa;
-  dst->sign = A->sign ^ B->sign;
-  fp_clamp(dst);
-  fp_copy(dst, C);
-}
-
-/* a/b => cb + d == a */
-int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
-{
-  fp_int  q, x, y, t1, t2;
-  int     n, t, i, norm, neg;
-
-  /* is divisor zero ? */
-  if (fp_iszero (b) == FP_YES) {
-    return FP_VAL;
-  }
-
-  /* if a < b then q=0, r = a */
-  if (fp_cmp_mag (a, b) == FP_LT) {
-    if (d != NULL) {
-      fp_copy (a, d);
-    }
-    if (c != NULL) {
-      fp_zero (c);
-    }
-    return FP_OKAY;
-  }
-
-  fp_init(&q);
-  q.used = a->used + 2;
-
-  fp_init(&t1);
-  fp_init(&t2);
-  fp_init_copy(&x, a);
-  fp_init_copy(&y, b);
-
-  /* fix the sign */
-  neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG;
-  x.sign = y.sign = FP_ZPOS;
-
-  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
-  norm = fp_count_bits(&y) % DIGIT_BIT;
-  if (norm < (int)(DIGIT_BIT-1)) {
-     norm = (DIGIT_BIT-1) - norm;
-     fp_mul_2d (&x, norm, &x);
-     fp_mul_2d (&y, norm, &y);
-  } else {
-     norm = 0;
-  }
-
-  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
-  n = x.used - 1;
-  t = y.used - 1;
-
-  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
-  fp_lshd (&y, n - t); /* y = y*b**{n-t} */
-
-  while (fp_cmp (&x, &y) != FP_LT) {
-    ++(q.dp[n - t]);
-    fp_sub (&x, &y, &x);
-  }
-
-  /* reset y by shifting it back down */
-  fp_rshd (&y, n - t);
-
-  /* step 3. for i from n down to (t + 1) */
-  for (i = n; i >= (t + 1); i--) {
-    if (i > x.used) {
-      continue;
-    }
-
-    /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
-     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
-    if (x.dp[i] == y.dp[t]) {
-      q.dp[i - t - 1] = (fp_digit) ((((fp_word)1) << DIGIT_BIT) - 1);
-    } else {
-      fp_word tmp;
-      tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT);
-      tmp |= ((fp_word) x.dp[i - 1]);
-      tmp /= ((fp_word)y.dp[t]);
-      q.dp[i - t - 1] = (fp_digit) (tmp);
-    }
-
-    /* while (q{i-t-1} * (yt * b + y{t-1})) >
-             xi * b**2 + xi-1 * b + xi-2
-
-       do q{i-t-1} -= 1;
-    */
-    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
-    do {
-      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
-
-      /* find left hand */
-      fp_zero (&t1);
-      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
-      t1.dp[1] = y.dp[t];
-      t1.used = 2;
-      fp_mul_d (&t1, q.dp[i - t - 1], &t1);
-
-      /* find right hand */
-      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
-      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
-      t2.dp[2] = x.dp[i];
-      t2.used = 3;
-    } while (fp_cmp_mag(&t1, &t2) == FP_GT);
-
-    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
-    fp_mul_d (&y, q.dp[i - t - 1], &t1);
-    fp_lshd  (&t1, i - t - 1);
-    fp_sub   (&x, &t1, &x);
-
-    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
-    if (x.sign == FP_NEG) {
-      fp_copy (&y, &t1);
-      fp_lshd (&t1, i - t - 1);
-      fp_add (&x, &t1, &x);
-      q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
-    }
-  }
-
-  /* now q is the quotient and x is the remainder
-   * [which we have to normalize]
-   */
-
-  /* get sign before writing to c */
-  x.sign = x.used == 0 ? FP_ZPOS : a->sign;
-
-  if (c != NULL) {
-    fp_clamp (&q);
-    fp_copy (&q, c);
-    c->sign = neg;
-  }
-
-  if (d != NULL) {
-    fp_div_2d (&x, norm, &x, NULL);
-
-    /* zero any excess digits on the destination that we didn't write to */
-    for (i = b->used; i < x.used; i++) {
-        x.dp[i] = 0;
-    }
-    fp_clamp(&x);
-    fp_copy (&x, d);
-  }
-
-  return FP_OKAY;
-}
-
-/* b = a/2 */
-void fp_div_2(fp_int * a, fp_int * b)
-{
-  int     x, oldused;
-
-  oldused = b->used;
-  b->used = a->used;
-  {
-    fp_digit r, rr, *tmpa, *tmpb;
-
-    /* source alias */
-    tmpa = a->dp + b->used - 1;
-
-    /* dest alias */
-    tmpb = b->dp + b->used - 1;
-
-    /* carry */
-    r = 0;
-    for (x = b->used - 1; x >= 0; x--) {
-      /* get the carry for the next iteration */
-      rr = *tmpa & 1;
-
-      /* shift the current digit, add in carry and store */
-      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
-
-      /* forward carry to next iteration */
-      r = rr;
-    }
-
-    /* zero any excess digits on the destination that we didn't write to */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-  fp_clamp (b);
-}
-
-/* c = a / 2**b */
-void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d)
-{
-  int      D;
-  fp_int   t;
-
-  /* if the shift count is <= 0 then we do no work */
-  if (b <= 0) {
-    fp_copy (a, c);
-    if (d != NULL) {
-      fp_zero (d);
-    }
-    return;
-  }
-
-  fp_init(&t);
-
-  /* get the remainder */
-  if (d != NULL) {
-    fp_mod_2d (a, b, &t);
-  }
-
-  /* copy */
-  fp_copy(a, c);
-
-  /* shift by as many digits in the bit count */
-  if (b >= (int)DIGIT_BIT) {
-    fp_rshd (c, b / DIGIT_BIT);
-  }
-
-  /* shift any bit count < DIGIT_BIT */
-  D = (b % DIGIT_BIT);
-  if (D != 0) {
-    fp_rshb(c, D);
-  }
-  fp_clamp (c);
-  if (d != NULL) {
-    fp_copy (&t, d);
-  }
-}
-
-/* c = a mod b, 0 <= c < b  */
-int fp_mod(fp_int *a, fp_int *b, fp_int *c)
-{
-   fp_int t;
-   int    err;
-
-   fp_init(&t);
-   if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) {
-      return err;
-   }
-   if (t.sign != b->sign) {
-      fp_add(&t, b, c);
-   } else {
-      fp_copy(&t, c);
-  }
-  return FP_OKAY;
-}
-
-/* c = a mod 2**d */
-void fp_mod_2d(fp_int *a, int b, fp_int *c)
-{
-   int x;
-
-   /* zero if count less than or equal to zero */
-   if (b <= 0) {
-      fp_zero(c);
-      return;
-   }
-
-   /* get copy of input */
-   fp_copy(a, c);
-
-   /* if 2**d is larger than we just return */
-   if (b >= (DIGIT_BIT * a->used)) {
-      return;
-   }
-
-  /* zero digits above the last digit of the modulus */
-  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
-    c->dp[x] = 0;
-  }
-  /* clear the digit that is not completely outside/inside the modulus */
-  c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b);
-  fp_clamp (c);
-}
-
-static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c)
-{
-  fp_int  x, y, u, v, A, B, C, D;
-  int     res;
-
-  /* b cannot be negative */
-  if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) {
-    return FP_VAL;
-  }
-
-  /* init temps */
-  fp_init(&x);    fp_init(&y);
-  fp_init(&u);    fp_init(&v);
-  fp_init(&A);    fp_init(&B);
-  fp_init(&C);    fp_init(&D);
-
-  /* x = a, y = b */
-  if ((res = fp_mod(a, b, &x)) != FP_OKAY) {
-      return res;
-  }
-  fp_copy(b, &y);
-
-  /* 2. [modified] if x,y are both even then return an error! */
-  if (fp_iseven (&x) == FP_YES && fp_iseven (&y) == FP_YES) {
-    return FP_VAL;
-  }
-
-  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
-  fp_copy (&x, &u);
-  fp_copy (&y, &v);
-  fp_set (&A, 1);
-  fp_set (&D, 1);
-
-top:
-  /* 4.  while u is even do */
-  while (fp_iseven (&u) == FP_YES) {
-    /* 4.1 u = u/2 */
-    fp_div_2 (&u, &u);
-
-    /* 4.2 if A or B is odd then */
-    if (fp_isodd (&A) == FP_YES || fp_isodd (&B) == FP_YES) {
-      /* A = (A+y)/2, B = (B-x)/2 */
-      fp_add (&A, &y, &A);
-      fp_sub (&B, &x, &B);
-    }
-    /* A = A/2, B = B/2 */
-    fp_div_2 (&A, &A);
-    fp_div_2 (&B, &B);
-  }
-
-  /* 5.  while v is even do */
-  while (fp_iseven (&v) == FP_YES) {
-    /* 5.1 v = v/2 */
-    fp_div_2 (&v, &v);
-
-    /* 5.2 if C or D is odd then */
-    if (fp_isodd (&C) == FP_YES || fp_isodd (&D) == FP_YES) {
-      /* C = (C+y)/2, D = (D-x)/2 */
-      fp_add (&C, &y, &C);
-      fp_sub (&D, &x, &D);
-    }
-    /* C = C/2, D = D/2 */
-    fp_div_2 (&C, &C);
-    fp_div_2 (&D, &D);
-  }
-
-  /* 6.  if u >= v then */
-  if (fp_cmp (&u, &v) != FP_LT) {
-    /* u = u - v, A = A - C, B = B - D */
-    fp_sub (&u, &v, &u);
-    fp_sub (&A, &C, &A);
-    fp_sub (&B, &D, &B);
-  } else {
-    /* v - v - u, C = C - A, D = D - B */
-    fp_sub (&v, &u, &v);
-    fp_sub (&C, &A, &C);
-    fp_sub (&D, &B, &D);
-  }
-
-  /* if not zero goto step 4 */
-  if (fp_iszero (&u) == FP_NO)
-    goto top;
-
-  /* now a = C, b = D, gcd == g*v */
-
-  /* if v != 1 then there is no inverse */
-  if (fp_cmp_d (&v, 1) != FP_EQ) {
-    return FP_VAL;
-  }
-
-  /* if its too low */
-  while (fp_cmp_d(&C, 0) == FP_LT) {
-      fp_add(&C, b, &C);
-  }
-
-  /* too big */
-  while (fp_cmp_mag(&C, b) != FP_LT) {
-      fp_sub(&C, b, &C);
-  }
-
-  /* C is now the inverse */
-  fp_copy(&C, c);
-  return FP_OKAY;
-}
-
-/* c = 1/a (mod b) for odd b only */
-int fp_invmod(fp_int *a, fp_int *b, fp_int *c)
-{
-  fp_int  x, y, u, v, B, D;
-  int     neg;
-
-  /* 2. [modified] b must be odd   */
-  if (fp_iseven (b) == FP_YES) {
-    return fp_invmod_slow(a,b,c);
-  }
-
-  /* init all our temps */
-  fp_init(&x);  fp_init(&y);
-  fp_init(&u);  fp_init(&v);
-  fp_init(&B);  fp_init(&D);
-
-  /* x == modulus, y == value to invert */
-  fp_copy(b, &x);
-
-  /* we need y = |a| */
-  fp_abs(a, &y);
-
-  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
-  fp_copy(&x, &u);
-  fp_copy(&y, &v);
-  fp_set (&D, 1);
-
-top:
-  /* 4.  while u is even do */
-  while (fp_iseven (&u) == FP_YES) {
-    /* 4.1 u = u/2 */
-    fp_div_2 (&u, &u);
-
-    /* 4.2 if B is odd then */
-    if (fp_isodd (&B) == FP_YES) {
-      fp_sub (&B, &x, &B);
-    }
-    /* B = B/2 */
-    fp_div_2 (&B, &B);
-  }
-
-  /* 5.  while v is even do */
-  while (fp_iseven (&v) == FP_YES) {
-    /* 5.1 v = v/2 */
-    fp_div_2 (&v, &v);
-
-    /* 5.2 if D is odd then */
-    if (fp_isodd (&D) == FP_YES) {
-      /* D = (D-x)/2 */
-      fp_sub (&D, &x, &D);
-    }
-    /* D = D/2 */
-    fp_div_2 (&D, &D);
-  }
-
-  /* 6.  if u >= v then */
-  if (fp_cmp (&u, &v) != FP_LT) {
-    /* u = u - v, B = B - D */
-    fp_sub (&u, &v, &u);
-    fp_sub (&B, &D, &B);
-  } else {
-    /* v - v - u, D = D - B */
-    fp_sub (&v, &u, &v);
-    fp_sub (&D, &B, &D);
-  }
-
-  /* if not zero goto step 4 */
-  if (fp_iszero (&u) == FP_NO) {
-    goto top;
-  }
-
-  /* now a = C, b = D, gcd == g*v */
-
-  /* if v != 1 then there is no inverse */
-  if (fp_cmp_d (&v, 1) != FP_EQ) {
-    return FP_VAL;
-  }
-
-  /* b is now the inverse */
-  neg = a->sign;
-  while (D.sign == FP_NEG) {
-    fp_add (&D, b, &D);
-  }
-  /* too big */
-  while (fp_cmp_mag(&D, b) != FP_LT) {
-    fp_sub(&D, b, &D);
-  }
-  fp_copy (&D, c);
-  c->sign = neg;
-  return FP_OKAY;
-}
-
-/* d = a * b (mod c) */
-int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
-{
-  int err;
-  fp_int t;
-
-  fp_init(&t);
-  fp_mul(a, b, &t);
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  if (d->size < FP_SIZE) {
-    err = fp_mod(&t, c, &t);
-    fp_copy(&t, d);
-  } else
-#endif
-  {
-    err = fp_mod(&t, c, d);
-  }
-
-  return err;
-}
-
-/* d = a - b (mod c) */
-int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
-{
-  int err;
-  fp_int t;
-
-  fp_init(&t);
-  fp_sub(a, b, &t);
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  if (d->size < FP_SIZE) {
-    err = fp_mod(&t, c, &t);
-    fp_copy(&t, d);
-  } else
-#endif
-  {
-    err = fp_mod(&t, c, d);
-  }
-
-  return err;
-}
-
-/* d = a + b (mod c) */
-int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
-{
-  int err;
-  fp_int t;
-
-  fp_init(&t);
-  fp_add(a, b, &t);
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  if (d->size < FP_SIZE) {
-    err = fp_mod(&t, c, &t);
-    fp_copy(&t, d);
-  } else
-#endif
-  {
-    err = fp_mod(&t, c, d);
-  }
-
-  return err;
-}
-
-#ifdef TFM_TIMING_RESISTANT
-
-/* timing resistant montgomery ladder based exptmod
-   Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder",
-   Cryptographic Hardware and Embedded Systems, CHES 2002
-*/
-static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
-{
-#ifdef WC_NO_CACHE_RESISTANT
-  fp_int   R[2];
-#else
-  fp_int   R[3];   /* need a temp for cache resistance */
-#endif
-  fp_digit buf, mp;
-  int      err, bitcnt, digidx, y;
-
-  /* now setup montgomery  */
-  if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
-     return err;
-  }
-
-  fp_init(&R[0]);
-  fp_init(&R[1]);
-#ifndef WC_NO_CACHE_RESISTANT
-  fp_init(&R[2]);
-#endif
-
-  /* now we need R mod m */
-  fp_montgomery_calc_normalization (&R[0], P);
-
-  /* now set R[0][1] to G * R mod m */
-  if (fp_cmp_mag(P, G) != FP_GT) {
-     /* G > P so we reduce it first */
-     fp_mod(G, P, &R[1]);
-  } else {
-     fp_copy(G, &R[1]);
-  }
-  fp_mulmod (&R[1], &R[0], P, &R[1]);
-
-  /* for j = t-1 downto 0 do
-        r_!k = R0*R1; r_k = r_k^2
-  */
-
-  /* set initial mode and bit cnt */
-  bitcnt = 1;
-  buf    = 0;
-  digidx = X->used - 1;
-
-  for (;;) {
-    /* grab next digit as required */
-    if (--bitcnt == 0) {
-      /* if digidx == -1 we are out of digits so break */
-      if (digidx == -1) {
-        break;
-      }
-      /* read next digit and reset bitcnt */
-      buf    = X->dp[digidx--];
-      bitcnt = (int)DIGIT_BIT;
-    }
-
-    /* grab the next msb from the exponent */
-    y     = (int)(buf >> (DIGIT_BIT - 1)) & 1;
-    buf <<= (fp_digit)1;
-
-    /* do ops */
-    fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp);
-
-#ifdef WC_NO_CACHE_RESISTANT
-    fp_sqr(&R[y], &R[y]);          fp_montgomery_reduce(&R[y], P, mp);
-#else
-    /* instead of using R[y] for sqr, which leaks key bit to cache monitor,
-     * use R[2] as temp, make sure address calc is constant, keep
-     * &R[0] and &R[1] in cache */
-    fp_copy((fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) +
-                        ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ),
-            &R[2]);
-    fp_sqr(&R[2], &R[2]);          fp_montgomery_reduce(&R[2], P, mp);
-    fp_copy(&R[2],
-            (fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) +
-                        ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ) );
-#endif /* WC_NO_CACHE_RESISTANT */
-  }
-
-   fp_montgomery_reduce(&R[0], P, mp);
-   fp_copy(&R[0], Y);
-   return FP_OKAY;
-}
-
-#else /* TFM_TIMING_RESISTANT */
-
-/* y = g**x (mod b)
- * Some restrictions... x must be positive and < b
- */
-static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
-{
-  fp_int   res;
-  fp_digit buf, mp;
-  int      err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
-#ifdef WOLFSSL_SMALL_STACK
-  fp_int  *M;
-#else
-  fp_int   M[64];
-#endif
-
-  /* find window size */
-  x = fp_count_bits (X);
-  if (x <= 21) {
-    winsize = 1;
-  } else if (x <= 36) {
-    winsize = 3;
-  } else if (x <= 140) {
-    winsize = 4;
-  } else if (x <= 450) {
-    winsize = 5;
-  } else {
-    winsize = 6;
-  }
-
-  /* now setup montgomery  */
-  if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
-     return err;
-  }
-
-#ifdef WOLFSSL_SMALL_STACK
-  /* only allocate space for what's needed */
-  M = (fp_int*)XMALLOC(sizeof(fp_int)*(1 << winsize), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-  if (M == NULL) {
-     return FP_MEM;
-  }
-#endif
-
-  /* init M array */
-  for(x = 0; x < (1 << winsize); x++)
-    fp_init(&M[x]);
-
-  /* setup result */
-  fp_init(&res);
-
-  /* create M table
-   *
-   * The M table contains powers of the input base, e.g. M[x] = G^x mod P
-   *
-   * The first half of the table is not computed though except for M[0] and M[1]
-   */
-
-   /* now we need R mod m */
-   fp_montgomery_calc_normalization (&res, P);
-
-   /* now set M[1] to G * R mod m */
-   if (fp_cmp_mag(P, G) != FP_GT) {
-      /* G > P so we reduce it first */
-      fp_mod(G, P, &M[1]);
-   } else {
-      fp_copy(G, &M[1]);
-   }
-   fp_mulmod (&M[1], &res, P, &M[1]);
-
-  /* compute the value at M[1<<(winsize-1)] by
-   * squaring M[1] (winsize-1) times */
-  fp_copy (&M[1], &M[1 << (winsize - 1)]);
-  for (x = 0; x < (winsize - 1); x++) {
-    fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]);
-    fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp);
-  }
-
-  /* create upper table */
-  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
-    fp_mul(&M[x - 1], &M[1], &M[x]);
-    fp_montgomery_reduce(&M[x], P, mp);
-  }
-
-  /* set initial mode and bit cnt */
-  mode   = 0;
-  bitcnt = 1;
-  buf    = 0;
-  digidx = X->used - 1;
-  bitcpy = 0;
-  bitbuf = 0;
-
-  for (;;) {
-    /* grab next digit as required */
-    if (--bitcnt == 0) {
-      /* if digidx == -1 we are out of digits so break */
-      if (digidx == -1) {
-        break;
-      }
-      /* read next digit and reset bitcnt */
-      buf    = X->dp[digidx--];
-      bitcnt = (int)DIGIT_BIT;
-    }
-
-    /* grab the next msb from the exponent */
-    y     = (int)(buf >> (DIGIT_BIT - 1)) & 1;
-    buf <<= (fp_digit)1;
-
-    /* if the bit is zero and mode == 0 then we ignore it
-     * These represent the leading zero bits before the first 1 bit
-     * in the exponent.  Technically this opt is not required but it
-     * does lower the # of trivial squaring/reductions used
-     */
-    if (mode == 0 && y == 0) {
-      continue;
-    }
-
-    /* if the bit is zero and mode == 1 then we square */
-    if (mode == 1 && y == 0) {
-      fp_sqr(&res, &res);
-      fp_montgomery_reduce(&res, P, mp);
-      continue;
-    }
-
-    /* else we add it to the window */
-    bitbuf |= (y << (winsize - ++bitcpy));
-    mode    = 2;
-
-    if (bitcpy == winsize) {
-      /* ok window is filled so square as required and multiply  */
-      /* square first */
-      for (x = 0; x < winsize; x++) {
-        fp_sqr(&res, &res);
-        fp_montgomery_reduce(&res, P, mp);
-      }
-
-      /* then multiply */
-      fp_mul(&res, &M[bitbuf], &res);
-      fp_montgomery_reduce(&res, P, mp);
-
-      /* empty window and reset */
-      bitcpy = 0;
-      bitbuf = 0;
-      mode   = 1;
-    }
-  }
-
-  /* if bits remain then square/multiply */
-  if (mode == 2 && bitcpy > 0) {
-    /* square then multiply if the bit is set */
-    for (x = 0; x < bitcpy; x++) {
-      fp_sqr(&res, &res);
-      fp_montgomery_reduce(&res, P, mp);
-
-      /* get next bit of the window */
-      bitbuf <<= 1;
-      if ((bitbuf & (1 << winsize)) != 0) {
-        /* then multiply */
-        fp_mul(&res, &M[1], &res);
-        fp_montgomery_reduce(&res, P, mp);
-      }
-    }
-  }
-
-  /* fixup result if Montgomery reduction is used
-   * recall that any value in a Montgomery system is
-   * actually multiplied by R mod n.  So we have
-   * to reduce one more time to cancel out the factor
-   * of R.
-   */
-  fp_montgomery_reduce(&res, P, mp);
-
-  /* swap res with Y */
-  fp_copy (&res, Y);
-
-#ifdef WOLFSSL_SMALL_STACK
-  XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-  return FP_OKAY;
-}
-
-#endif /* TFM_TIMING_RESISTANT */
-
-int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
-{
-   /* prevent overflows */
-   if (P->used > (FP_SIZE/2)) {
-      return FP_VAL;
-   }
-
-   if (X->sign == FP_NEG) {
-#ifndef POSITIVE_EXP_ONLY  /* reduce stack if assume no negatives */
-      int    err;
-      fp_int tmp;
-
-      /* yes, copy G and invmod it */
-      fp_init_copy(&tmp, G);
-      if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) {
-         return err;
-      }
-      X->sign = FP_ZPOS;
-      err =  _fp_exptmod(&tmp, X, P, Y);
-      if (X != Y) {
-         X->sign = FP_NEG;
-      }
-      return err;
-#else
-      return FP_VAL;
-#endif
-   }
-   else {
-      /* Positive exponent so just exptmod */
-      return _fp_exptmod(G, X, P, Y);
-   }
-}
-
-/* computes a = 2**b */
-void fp_2expt(fp_int *a, int b)
-{
-   int     z;
-
-   /* zero a as per default */
-   fp_zero (a);
-
-   if (b < 0) {
-      return;
-   }
-
-   z = b / DIGIT_BIT;
-   if (z >= FP_SIZE) {
-      return;
-   }
-
-  /* set the used count of where the bit will go */
-  a->used = z + 1;
-
-  /* put the single bit in its place */
-  a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT);
-}
-
-/* b = a*a  */
-void fp_sqr(fp_int *A, fp_int *B)
-{
-    int y, oldused;
-
-    oldused = B->used;
-    y = A->used;
-
-    /* call generic if we're out of range */
-    if (y + y > FP_SIZE) {
-       fp_sqr_comba(A, B);
-       goto clean;
-    }
-
-#if defined(TFM_SQR3) && FP_SIZE >= 6
-        if (y <= 3) {
-           fp_sqr_comba3(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR4) && FP_SIZE >= 8
-        if (y == 4) {
-           fp_sqr_comba4(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR6) && FP_SIZE >= 12
-        if (y <= 6) {
-           fp_sqr_comba6(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR7) && FP_SIZE >= 14
-        if (y == 7) {
-           fp_sqr_comba7(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR8) && FP_SIZE >= 16
-        if (y == 8) {
-           fp_sqr_comba8(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR9) && FP_SIZE >= 18
-        if (y == 9) {
-           fp_sqr_comba9(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR12) && FP_SIZE >= 24
-        if (y <= 12) {
-           fp_sqr_comba12(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR17) && FP_SIZE >= 34
-        if (y <= 17) {
-           fp_sqr_comba17(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SMALL_SET)
-        if (y <= 16) {
-           fp_sqr_comba_small(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR20) && FP_SIZE >= 40
-        if (y <= 20) {
-           fp_sqr_comba20(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR24) && FP_SIZE >= 48
-        if (y <= 24) {
-           fp_sqr_comba24(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR28) && FP_SIZE >= 56
-        if (y <= 28) {
-           fp_sqr_comba28(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR32) && FP_SIZE >= 64
-        if (y <= 32) {
-           fp_sqr_comba32(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR48) && FP_SIZE >= 96
-        if (y <= 48) {
-           fp_sqr_comba48(A,B);
-           goto clean;
-        }
-#endif
-#if defined(TFM_SQR64) && FP_SIZE >= 128
-        if (y <= 64) {
-           fp_sqr_comba64(A,B);
-           goto clean;
-        }
-#endif
-       fp_sqr_comba(A, B);
-
-clean:
-  /* zero any excess digits on the destination that we didn't write to */
-  for (y = B->used; y >= 0 && y < oldused; y++) {
-    B->dp[y] = 0;
-  }
-}
-
-/* generic comba squarer */
-void fp_sqr_comba(fp_int *A, fp_int *B)
-{
-  int       pa, ix, iz;
-  fp_digit  c0, c1, c2;
-  fp_int    tmp, *dst;
-#ifdef TFM_ISO
-  fp_word   tt;
-#endif
-
-  /* get size of output and trim */
-  pa = A->used + A->used;
-  if (pa >= FP_SIZE) {
-     pa = FP_SIZE-1;
-  }
-
-  /* number of output digits to produce */
-  COMBA_START;
-  COMBA_CLEAR;
-
-  if (A == B) {
-     fp_init(&tmp);
-     dst = &tmp;
-  } else {
-     fp_zero(B);
-     dst = B;
-  }
-
-  for (ix = 0; ix < pa; ix++) {
-      int      tx, ty, iy;
-      fp_digit *tmpy, *tmpx;
-
-      /* get offsets into the two bignums */
-      ty = MIN(A->used-1, ix);
-      tx = ix - ty;
-
-      /* setup temp aliases */
-      tmpx = A->dp + tx;
-      tmpy = A->dp + ty;
-
-      /* this is the number of times the loop will iterate,
-         while (tx++ < a->used && ty-- >= 0) { ... }
-       */
-      iy = MIN(A->used-tx, ty+1);
-
-      /* now for squaring tx can never equal ty
-       * we halve the distance since they approach
-       * at a rate of 2x and we have to round because
-       * odd cases need to be executed
-       */
-      iy = MIN(iy, (ty-tx+1)>>1);
-
-      /* forward carries */
-      COMBA_FORWARD;
-
-      /* execute loop */
-      for (iz = 0; iz < iy; iz++) {
-          SQRADD2(*tmpx++, *tmpy--);
-      }
-
-      /* even columns have the square term in them */
-      if ((ix&1) == 0) {
-          /* TAO change COMBA_ADD back to SQRADD */
-          SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
-      }
-
-      /* store it */
-      COMBA_STORE(dst->dp[ix]);
-  }
-
-  COMBA_FINI;
-
-  /* setup dest */
-  dst->used = pa;
-  fp_clamp (dst);
-  if (dst != B) {
-     fp_copy(dst, B);
-  }
-}
-
-int fp_cmp(fp_int *a, fp_int *b)
-{
-   if (a->sign == FP_NEG && b->sign == FP_ZPOS) {
-      return FP_LT;
-   } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) {
-      return FP_GT;
-   } else {
-      /* compare digits */
-      if (a->sign == FP_NEG) {
-         /* if negative compare opposite direction */
-         return fp_cmp_mag(b, a);
-      } else {
-         return fp_cmp_mag(a, b);
-      }
-   }
-}
-
-/* compare against a single digit */
-int fp_cmp_d(fp_int *a, fp_digit b)
-{
-  /* special case for zero*/
-  if (a->used == 0 && b == 0)
-    return FP_EQ;
-
-  /* compare based on sign */
-  if ((b && a->used == 0) || a->sign == FP_NEG) {
-    return FP_LT;
-  }
-
-  /* compare based on magnitude */
-  if (a->used > 1) {
-    return FP_GT;
-  }
-
-  /* compare the only digit of a to b */
-  if (a->dp[0] > b) {
-    return FP_GT;
-  } else if (a->dp[0] < b) {
-    return FP_LT;
-  } else {
-    return FP_EQ;
-  }
-
-}
-
-int fp_cmp_mag(fp_int *a, fp_int *b)
-{
-   int x;
-
-   if (a->used > b->used) {
-      return FP_GT;
-   } else if (a->used < b->used) {
-      return FP_LT;
-   } else {
-      for (x = a->used - 1; x >= 0; x--) {
-          if (a->dp[x] > b->dp[x]) {
-             return FP_GT;
-          } else if (a->dp[x] < b->dp[x]) {
-             return FP_LT;
-          }
-      }
-   }
-   return FP_EQ;
-}
-
-/* sets up the montgomery reduction */
-int fp_montgomery_setup(fp_int *a, fp_digit *rho)
-{
-  fp_digit x, b;
-
-/* fast inversion mod 2**k
- *
- * Based on the fact that
- *
- * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
- *                    =>  2*X*A - X*X*A*A = 1
- *                    =>  2*(1) - (1)     = 1
- */
-  b = a->dp[0];
-
-  if ((b & 1) == 0) {
-    return FP_VAL;
-  }
-
-  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
-  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
-  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
-  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
-#ifdef FP_64BIT
-  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
-#endif
-
-  /* rho = -1/m mod b */
-  *rho = (fp_digit) (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x));
-
-  return FP_OKAY;
-}
-
-/* computes a = B**n mod b without division or multiplication useful for
- * normalizing numbers in a Montgomery system.
- */
-void fp_montgomery_calc_normalization(fp_int *a, fp_int *b)
-{
-  int     x, bits;
-
-  /* how many bits of last digit does b use */
-  bits = fp_count_bits (b) % DIGIT_BIT;
-  if (!bits) bits = DIGIT_BIT;
-
-  /* compute A = B^(n-1) * 2^(bits-1) */
-  if (b->used > 1) {
-     fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1);
-  } else {
-     fp_set(a, 1);
-     bits = 1;
-  }
-
-  /* now compute C = A * B mod b */
-  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
-    fp_mul_2 (a, a);
-    if (fp_cmp_mag (a, b) != FP_LT) {
-      s_fp_sub (a, b, a);
-    }
-  }
-}
-
-
-#ifdef TFM_SMALL_MONT_SET
-    #include "fp_mont_small.i"
-#endif
-
-#ifdef HAVE_INTEL_MULX
-static WC_INLINE void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu)
-{
-    fp_digit cy = *cy_mulx ;
-    INNERMUL8_MULX ;
-    *cy_mulx = cy ;
-}
-
-/* computes x/R == x (mod N) via Montgomery Reduction */
-static void fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp)
-{
-   fp_digit c[FP_SIZE+1], *_c, *tmpm, mu = 0;
-   int      oldused, x, y, pa;
-
-   /* bail if too large */
-   if (m->used > (FP_SIZE/2)) {
-      (void)mu;                     /* shut up compiler */
-      return;
-   }
-
-#ifdef TFM_SMALL_MONT_SET
-   if (m->used <= 16) {
-      fp_montgomery_reduce_small(a, m, mp);
-      return;
-   }
-#endif
-
-
-   /* now zero the buff */
-   XMEMSET(c, 0, sizeof(c));
-   pa = m->used;
-
-   /* copy the input */
-   oldused = a->used;
-   for (x = 0; x < oldused; x++) {
-       c[x] = a->dp[x];
-   }
-   MONT_START;
-
-   for (x = 0; x < pa; x++) {
-       fp_digit cy = 0;
-       /* get Mu for this round */
-       LOOP_START;
-       _c   = c + x;
-       tmpm = m->dp;
-       y = 0;
-        for (; y < (pa & ~7); y += 8) {
-              innermul8_mulx(_c, &cy, tmpm, mu) ;
-              _c   += 8;
-              tmpm += 8;
-           }
-       for (; y < pa; y++) {
-          INNERMUL;
-          ++_c;
-       }
-       LOOP_END;
-       while (cy) {
-           PROPCARRY;
-           ++_c;
-       }
-  }
-
-  /* now copy out */
-  _c   = c + pa;
-  tmpm = a->dp;
-  for (x = 0; x < pa+1; x++) {
-     *tmpm++ = *_c++;
-  }
-
-  /* zero any excess digits on the destination that we didn't write to */
-  for (; x < oldused; x++) {
-     *tmpm++ = 0;
-  }
-
-  MONT_FINI;
-
-  a->used = pa+1;
-  fp_clamp(a);
-
-  /* if A >= m then A = A - m */
-  if (fp_cmp_mag (a, m) != FP_LT) {
-    s_fp_sub (a, m, a);
-  }
-}
-#endif
-
-/* computes x/R == x (mod N) via Montgomery Reduction */
-void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
-{
-   fp_digit c[FP_SIZE+1], *_c, *tmpm, mu = 0;
-   int      oldused, x, y, pa;
-
-   IF_HAVE_INTEL_MULX(fp_montgomery_reduce_mulx(a, m, mp), return) ;
-
-   /* bail if too large */
-   if (m->used > (FP_SIZE/2)) {
-      (void)mu;                     /* shut up compiler */
-      return;
-   }
-
-#ifdef TFM_SMALL_MONT_SET
-   if (m->used <= 16) {
-      fp_montgomery_reduce_small(a, m, mp);
-      return;
-   }
-#endif
-
-
-   /* now zero the buff */
-   XMEMSET(c, 0, sizeof(c));
-   pa = m->used;
-
-   /* copy the input */
-   oldused = a->used;
-   for (x = 0; x < oldused; x++) {
-       c[x] = a->dp[x];
-   }
-   MONT_START;
-
-   for (x = 0; x < pa; x++) {
-       fp_digit cy = 0;
-       /* get Mu for this round */
-       LOOP_START;
-       _c   = c + x;
-       tmpm = m->dp;
-       y = 0;
-#if defined(INNERMUL8)
-        for (; y < (pa & ~7); y += 8) {
-              INNERMUL8 ;
-              _c   += 8;
-              tmpm += 8;
-           }
-#endif
-       for (; y < pa; y++) {
-          INNERMUL;
-          ++_c;
-       }
-       LOOP_END;
-       while (cy) {
-           PROPCARRY;
-           ++_c;
-       }
-  }
-
-  /* now copy out */
-  _c   = c + pa;
-  tmpm = a->dp;
-  for (x = 0; x < pa+1; x++) {
-     *tmpm++ = *_c++;
-  }
-
-  /* zero any excess digits on the destination that we didn't write to */
-  for (; x < oldused; x++) {
-     *tmpm++ = 0;
-  }
-
-  MONT_FINI;
-
-  a->used = pa+1;
-  fp_clamp(a);
-
-  /* if A >= m then A = A - m */
-  if (fp_cmp_mag (a, m) != FP_LT) {
-    s_fp_sub (a, m, a);
-  }
-}
-
-void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c)
-{
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  const word32 maxC = (a->size * sizeof(fp_digit));
-#else
-  const word32 maxC = (FP_SIZE * sizeof(fp_digit));
-#endif
-
-  /* zero the int */
-  fp_zero (a);
-
-  /* if input b excess max, then truncate */
-  if (c > 0 && (word32)c > maxC) {
-     int excess = (c - maxC);
-     c -= excess;
-     b += excess;
-  }
-
-  /* If we know the endianness of this architecture, and we're using
-     32-bit fp_digits, we can optimize this */
-#if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \
-    defined(FP_32BIT)
-  /* But not for both simultaneously */
-#if defined(LITTLE_ENDIAN_ORDER) && defined(BIG_ENDIAN_ORDER)
-#error Both LITTLE_ENDIAN_ORDER and BIG_ENDIAN_ORDER defined.
-#endif
-  {
-     unsigned char *pd = (unsigned char *)a->dp;
-
-     a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit);
-     /* read the bytes in */
-#ifdef BIG_ENDIAN_ORDER
-     {
-       /* Use Duff's device to unroll the loop. */
-       int idx = (c - 1) & ~3;
-       switch (c % 4) {
-       case 0:    do { pd[idx+0] = *b++;
-       case 3:         pd[idx+1] = *b++;
-       case 2:         pd[idx+2] = *b++;
-       case 1:         pd[idx+3] = *b++;
-                     idx -= 4;
-                 } while ((c -= 4) > 0);
-       }
-     }
-#else
-     for (c -= 1; c >= 0; c -= 1) {
-       pd[c] = *b++;
-     }
-#endif
-  }
-#else
-  /* read the bytes in */
-  for (; c > 0; c--) {
-     fp_mul_2d (a, 8, a);
-     a->dp[0] |= *b++;
-
-     if (a->used == 0) {
-         a->used = 1;
-     }
-  }
-#endif
-  fp_clamp (a);
-}
-
-int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b)
-{
-#if DIGIT_BIT == 64 || DIGIT_BIT == 32
-   int i, j;
-   fp_digit n;
-
-   for (j=0,i=0; i<t->used-1; ) {
-       b[x++] = (unsigned char)(t->dp[i] >> j);
-       j += 8;
-       i += j == DIGIT_BIT;
-       j &= DIGIT_BIT - 1;
-   }
-   n = t->dp[i];
-   while (n != 0) {
-       b[x++] = (unsigned char)n;
-       n >>= 8;
-   }
-   return x;
-#else
-   while (fp_iszero (t) == FP_NO) {
-      b[x++] = (unsigned char) (t->dp[0] & 255);
-      fp_div_2d (t, 8, t, NULL);
-  }
-  return x;
-#endif
-}
-
-void fp_to_unsigned_bin(fp_int *a, unsigned char *b)
-{
-  int     x;
-  fp_int  t;
-
-  fp_init_copy(&t, a);
-
-  x = fp_to_unsigned_bin_at_pos(0, &t, b);
-  fp_reverse (b, x);
-}
-
-int fp_unsigned_bin_size(fp_int *a)
-{
-  int     size = fp_count_bits (a);
-  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
-}
-
-void fp_set(fp_int *a, fp_digit b)
-{
-   fp_zero(a);
-   a->dp[0] = b;
-   a->used  = a->dp[0] ? 1 : 0;
-}
-
-
-#ifndef MP_SET_CHUNK_BITS
-    #define MP_SET_CHUNK_BITS 4
-#endif
-void fp_set_int(fp_int *a, unsigned long b)
-{
-  int x;
-
-  /* use direct fp_set if b is less than fp_digit max */
-  if (b < FP_DIGIT_MAX) {
-    fp_set (a, (fp_digit)b);
-    return;
-  }
-
-  fp_zero (a);
-
-  /* set chunk bits at a time */
-  for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) {
-    fp_mul_2d (a, MP_SET_CHUNK_BITS, a);
-
-    /* OR in the top bits of the source */
-    a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) &
-                                  ((1 << MP_SET_CHUNK_BITS) - 1);
-
-    /* shift the source up to the next chunk bits */
-    b <<= MP_SET_CHUNK_BITS;
-
-    /* ensure that digits are not clamped off */
-    a->used += 1;
-  }
-
-  /* clamp digits */
-  fp_clamp(a);
-}
-
-/* check if a bit is set */
-int fp_is_bit_set (fp_int *a, fp_digit b)
-{
-    fp_digit i;
-
-    if (b > FP_MAX_BITS)
-        return 0;
-    else
-        i = b/DIGIT_BIT;
-
-    if ((fp_digit)a->used < i)
-        return 0;
-
-    return (int)((a->dp[i] >> b%DIGIT_BIT) & (fp_digit)1);
-}
-
-/* set the b bit of a */
-int fp_set_bit (fp_int * a, fp_digit b)
-{
-    fp_digit i;
-
-    if (b > FP_MAX_BITS)
-        return 0;
-    else
-        i = b/DIGIT_BIT;
-
-    /* set the used count of where the bit will go if required */
-    if (a->used < (int)(i+1))
-        a->used = (int)(i+1);
-
-    /* put the single bit in its place */
-    a->dp[i] |= ((fp_digit)1) << (b % DIGIT_BIT);
-
-    return MP_OKAY;
-}
-
-int fp_count_bits (fp_int * a)
-{
-  int     r;
-  fp_digit q;
-
-  /* shortcut */
-  if (a->used == 0) {
-    return 0;
-  }
-
-  /* get number of digits and add that */
-  r = (a->used - 1) * DIGIT_BIT;
-
-  /* take the last digit and count the bits in it */
-  q = a->dp[a->used - 1];
-  while (q > ((fp_digit) 0)) {
-    ++r;
-    q >>= ((fp_digit) 1);
-  }
-
-  return r;
-}
-
-int fp_leading_bit(fp_int *a)
-{
-    int bit = 0;
-
-    if (a->used != 0) {
-        fp_digit q = a->dp[a->used - 1];
-        int qSz = sizeof(fp_digit);
-
-        while (qSz > 0) {
-            if ((unsigned char)q != 0)
-                bit = (q & 0x80) != 0;
-            q >>= 8;
-            qSz--;
-        }
-    }
-
-    return bit;
-}
-
-void fp_lshd(fp_int *a, int x)
-{
-    int y;
-
-    /* move up and truncate as required */
-    y = MIN(a->used + x - 1, (int)(FP_SIZE-1));
-
-    /* store new size */
-    a->used = y + 1;
-
-    /* move digits */
-    for (; y >= x; y--) {
-        a->dp[y] = a->dp[y-x];
-    }
-
-    /* zero lower digits */
-    for (; y >= 0; y--) {
-        a->dp[y] = 0;
-    }
-
-    /* clamp digits */
-    fp_clamp(a);
-}
-
-
-/* right shift by bit count */
-void fp_rshb(fp_int *c, int x)
-{
-    fp_digit *tmpc, mask, shift;
-    fp_digit r, rr;
-    fp_digit D = x;
-
-    /* mask */
-    mask = (((fp_digit)1) << D) - 1;
-
-    /* shift for lsb */
-    shift = DIGIT_BIT - D;
-
-    /* alias */
-    tmpc = c->dp + (c->used - 1);
-
-    /* carry */
-    r = 0;
-    for (x = c->used - 1; x >= 0; x--) {
-      /* get the lower  bits of this word in a temp */
-      rr = *tmpc & mask;
-
-      /* shift the current word and mix in the carry bits from previous word */
-      *tmpc = (*tmpc >> D) | (r << shift);
-      --tmpc;
-
-      /* set the carry to the carry bits of the current word found above */
-      r = rr;
-    }
-
-    /* clamp digits */
-    fp_clamp(c);
-}
-
-
-void fp_rshd(fp_int *a, int x)
-{
-  int y;
-
-  /* too many digits just zero and return */
-  if (x >= a->used) {
-     fp_zero(a);
-     return;
-  }
-
-   /* shift */
-   for (y = 0; y < a->used - x; y++) {
-      a->dp[y] = a->dp[y+x];
-   }
-
-   /* zero rest */
-   for (; y < a->used; y++) {
-      a->dp[y] = 0;
-   }
-
-   /* decrement count */
-   a->used -= x;
-   fp_clamp(a);
-}
-
-/* reverse an array, used for radix code */
-void fp_reverse (unsigned char *s, int len)
-{
-  int     ix, iy;
-  unsigned char t;
-
-  ix = 0;
-  iy = len - 1;
-  while (ix < iy) {
-    t     = s[ix];
-    s[ix] = s[iy];
-    s[iy] = t;
-    ++ix;
-    --iy;
-  }
-}
-
-
-/* c = a - b */
-void fp_sub_d(fp_int *a, fp_digit b, fp_int *c)
-{
-   fp_int tmp;
-   fp_init(&tmp);
-   fp_set(&tmp, b);
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-   if (c->size < FP_SIZE) {
-     fp_sub(a, &tmp, &tmp);
-     fp_copy(&tmp, c);
-   } else
-#endif
-   {
-     fp_sub(a, &tmp, c);
-   }
-}
-
-
-/* wolfSSL callers from normal lib */
-
-/* init a new mp_int */
-int mp_init (mp_int * a)
-{
-  if (a)
-    fp_init(a);
-  return MP_OKAY;
-}
-
-void fp_init(fp_int *a)
-{
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-    a->size = FP_SIZE;
-#endif
-#ifdef HAVE_WOLF_BIGINT
-    wc_bigint_init(&a->raw);
-#endif
-    fp_zero(a);
-}
-
-void fp_zero(fp_int *a)
-{
-    int size = FP_SIZE;
-    a->used = 0;
-    a->sign = FP_ZPOS;
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-    size = a->size;
-#endif
-    XMEMSET(a->dp, 0, size * sizeof(fp_digit));
-}
-
-void fp_clear(fp_int *a)
-{
-    int size = FP_SIZE;
-    a->used = 0;
-    a->sign = FP_ZPOS;
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-    size = a->size;
-#endif
-    XMEMSET(a->dp, 0, size * sizeof(fp_digit));
-    fp_free(a);
-}
-
-void fp_forcezero (mp_int * a)
-{
-    int size = FP_SIZE;
-    a->used = 0;
-    a->sign = FP_ZPOS;
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-    size = a->size;
-#endif
-    ForceZero(a->dp, size * sizeof(fp_digit));
-#ifdef HAVE_WOLF_BIGINT
-    wc_bigint_zero(&a->raw);
-#endif
-    fp_free(a);
-}
-
-void mp_forcezero (mp_int * a)
-{
-    fp_forcezero(a);
-}
-
-void fp_free(fp_int* a)
-{
-#ifdef HAVE_WOLF_BIGINT
-    wc_bigint_free(&a->raw);
-#else
-    (void)a;
-#endif
-}
-
-
-/* clear one (frees)  */
-void mp_clear (mp_int * a)
-{
-    if (a == NULL)
-        return;
-    fp_clear(a);
-}
-
-void mp_free(mp_int* a)
-{
-    fp_free(a);
-}
-
-/* handle up to 6 inits */
-int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d,
-                  mp_int* e, mp_int* f)
-{
-    if (a)
-        fp_init(a);
-    if (b)
-        fp_init(b);
-    if (c)
-        fp_init(c);
-    if (d)
-        fp_init(d);
-    if (e)
-        fp_init(e);
-    if (f)
-        fp_init(f);
-
-    return MP_OKAY;
-}
-
-/* high level addition (handles signs) */
-int mp_add (mp_int * a, mp_int * b, mp_int * c)
-{
-  fp_add(a, b, c);
-  return MP_OKAY;
-}
-
-/* high level subtraction (handles signs) */
-int mp_sub (mp_int * a, mp_int * b, mp_int * c)
-{
-  fp_sub(a, b, c);
-  return MP_OKAY;
-}
-
-/* high level multiplication (handles sign) */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mul(mp_int * a, mp_int * b, mp_int * c)
-#else
-int mp_mul (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  fp_mul(a, b, c);
-  return MP_OKAY;
-}
-
-int mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
-{
-  fp_mul_d(a, b, c);
-  return MP_OKAY;
-}
-
-/* d = a * b (mod c) */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
-#else
-int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
-#endif
-{
-  return fp_mulmod(a, b, c, d);
-}
-
-/* d = a - b (mod c) */
-int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
-{
-  return fp_submod(a, b, c, d);
-}
-
-/* d = a + b (mod c) */
-int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
-{
-  return fp_addmod(a, b, c, d);
-}
-
-/* c = a mod b, 0 <= c < b */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_mod (mp_int * a, mp_int * b, mp_int * c)
-#else
-int mp_mod (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  return fp_mod (a, b, c);
-}
-
-/* hac 14.61, pp608 */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
-#else
-int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
-#endif
-{
-  return fp_invmod(a, b, c);
-}
-
-/* this is a shell function that calls either the normal or Montgomery
- * exptmod functions.  Originally the call to the montgomery code was
- * embedded in the normal function but that wasted alot of stack space
- * for nothing (since 99% of the time the Montgomery code would be called)
- */
-#if defined(FREESCALE_LTC_TFM)
-int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
-#else
-int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
-#endif
-{
-  return fp_exptmod(G, X, P, Y);
-}
-
-/* compare two ints (signed)*/
-int mp_cmp (mp_int * a, mp_int * b)
-{
-  return fp_cmp(a, b);
-}
-
-/* compare a digit */
-int mp_cmp_d(mp_int * a, mp_digit b)
-{
-  return fp_cmp_d(a, b);
-}
-
-/* get the size for an unsigned equivalent */
-int mp_unsigned_bin_size (mp_int * a)
-{
-  return fp_unsigned_bin_size(a);
-}
-
-int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b)
-{
-    return fp_to_unsigned_bin_at_pos(x, t, b);
-}
-
-/* store in unsigned [big endian] format */
-int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
-{
-  fp_to_unsigned_bin(a,b);
-  return MP_OKAY;
-}
-
-/* reads a unsigned char array, assumes the msb is stored first [big endian] */
-int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
-{
-  fp_read_unsigned_bin(a, b, c);
-  return MP_OKAY;
-}
-
-
-int mp_sub_d(fp_int *a, fp_digit b, fp_int *c)
-{
-    fp_sub_d(a, b, c);
-    return MP_OKAY;
-}
-
-int mp_mul_2d(fp_int *a, int b, fp_int *c)
-{
-    fp_mul_2d(a, b, c);
-	return MP_OKAY;
-}
-
-int mp_2expt(fp_int* a, int b)
-{
-    fp_2expt(a, b);
-    return MP_OKAY;
-}
-
-int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d)
-{
-    return fp_div(a, b, c, d);
-}
-
-int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d)
-{
-    fp_div_2d(a, b, c, d);
-    return MP_OKAY;
-}
-
-void fp_copy(fp_int *a, fp_int *b)
-{
-    /* if source and destination are different */
-    if (a != b) {
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-        /* verify a will fit in b */
-        if (b->size >= a->used) {
-            int x, oldused;
-            oldused = b->used;
-            b->used = a->used;
-            b->sign = a->sign;
-
-            XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit));
-
-            /* zero any excess digits on the destination that we didn't write to */
-            for (x = b->used; x >= 0 && x < oldused; x++) {
-                b->dp[x] = 0;
-            }
-        }
-        else {
-            /* TODO: Handle error case */
-        }
-#else
-        /* all dp's are same size, so do straight copy */
-        b->used = a->used;
-        b->sign = a->sign;
-        XMEMCPY(b->dp, a->dp, FP_SIZE * sizeof(fp_digit));
-#endif
-    }
-}
-
-void fp_init_copy(fp_int *a, fp_int* b)
-{
-    if (a != b) {
-        fp_init(a);
-        fp_copy(b, a);
-    }
-}
-
-/* fast math wrappers */
-int mp_copy(fp_int* a, fp_int* b)
-{
-    fp_copy(a, b);
-    return MP_OKAY;
-}
-
-int mp_isodd(mp_int* a)
-{
-    return fp_isodd(a);
-}
-
-int mp_iszero(mp_int* a)
-{
-    return fp_iszero(a);
-}
-
-int mp_count_bits (mp_int* a)
-{
-    return fp_count_bits(a);
-}
-
-int mp_leading_bit (mp_int* a)
-{
-    return fp_leading_bit(a);
-}
-
-void mp_rshb (mp_int* a, int x)
-{
-    fp_rshb(a, x);
-}
-
-void mp_rshd (mp_int* a, int x)
-{
-    fp_rshd(a, x);
-}
-
-int mp_set_int(mp_int *a, unsigned long b)
-{
-    fp_set_int(a, b);
-    return MP_OKAY;
-}
-
-int mp_is_bit_set (mp_int *a, mp_digit b)
-{
-    return fp_is_bit_set(a, b);
-}
-
-int mp_set_bit(mp_int *a, mp_digit b)
-{
-    return fp_set_bit(a, b);
-}
-
-#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC)
-
-/* c = a * a (mod b) */
-int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c)
-{
-  int err;
-  fp_int t;
-
-  fp_init(&t);
-  fp_sqr(a, &t);
-
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  if (c->size < FP_SIZE) {
-    err = fp_mod(&t, b, &t);
-    fp_copy(&t, c);
-  }
-  else
-#endif
-  {
-    err = fp_mod(&t, b, c);
-  }
-
-  return err;
-}
-
-/* fast math conversion */
-int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c)
-{
-    return fp_sqrmod(a, b, c);
-}
-
-/* fast math conversion */
-int mp_montgomery_calc_normalization(mp_int *a, mp_int *b)
-{
-    fp_montgomery_calc_normalization(a, b);
-    return MP_OKAY;
-}
-
-#endif /* WOLFSSL_KEYGEN || HAVE_ECC */
-
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
-    defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
-    defined(WOLFSSL_PUBLIC_MP)
-
-#ifdef WOLFSSL_KEY_GEN
-/* swap the elements of two integers, for cases where you can't simply swap the
- * mp_int pointers around
- */
-static void fp_exch (fp_int * a, fp_int * b)
-{
-    fp_int  t;
-
-    t  = *a;
-    *a = *b;
-    *b = t;
-}
-#endif
-
-static const int lnz[16] = {
-   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
-};
-
-/* Counts the number of lsbs which are zero before the first zero bit */
-int fp_cnt_lsb(fp_int *a)
-{
-   int x;
-   fp_digit q, qq;
-
-   /* easy out */
-   if (fp_iszero(a) == FP_YES) {
-      return 0;
-   }
-
-   /* scan lower digits until non-zero */
-   for (x = 0; x < a->used && a->dp[x] == 0; x++) {}
-   q = a->dp[x];
-   x *= DIGIT_BIT;
-
-   /* now scan this digit until a 1 is found */
-   if ((q & 1) == 0) {
-      do {
-         qq  = q & 15;
-         x  += lnz[qq];
-         q >>= 4;
-      } while (qq == 0);
-   }
-   return x;
-}
-
-
-static int s_is_power_of_two(fp_digit b, int *p)
-{
-   int x;
-
-   /* fast return if no power of two */
-   if ((b==0) || (b & (b-1))) {
-      return FP_NO;
-   }
-
-   for (x = 0; x < DIGIT_BIT; x++) {
-      if (b == (((fp_digit)1)<<x)) {
-         *p = x;
-         return FP_YES;
-      }
-   }
-   return FP_NO;
-}
-
-/* a/b => cb + d == a */
-static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d)
-{
-  fp_int   q;
-  fp_word  w;
-  fp_digit t;
-  int      ix;
-
-  fp_init(&q);
-
-  /* cannot divide by zero */
-  if (b == 0) {
-     return FP_VAL;
-  }
-
-  /* quick outs */
-  if (b == 1 || fp_iszero(a) == FP_YES) {
-     if (d != NULL) {
-        *d = 0;
-     }
-     if (c != NULL) {
-        fp_copy(a, c);
-     }
-     return FP_OKAY;
-  }
-
-  /* power of two ? */
-  if (s_is_power_of_two(b, &ix) == FP_YES) {
-     if (d != NULL) {
-        *d = a->dp[0] & ((((fp_digit)1)<<ix) - 1);
-     }
-     if (c != NULL) {
-        fp_div_2d(a, ix, c, NULL);
-     }
-     return FP_OKAY;
-  }
-
-  if (c != NULL) {
-    q.used = a->used;
-    q.sign = a->sign;
-  }
-
-  w = 0;
-  for (ix = a->used - 1; ix >= 0; ix--) {
-     w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]);
-
-     if (w >= b) {
-        t = (fp_digit)(w / b);
-        w -= ((fp_word)t) * ((fp_word)b);
-      } else {
-        t = 0;
-      }
-      if (c != NULL)
-        q.dp[ix] = (fp_digit)t;
-  }
-
-  if (d != NULL) {
-     *d = (fp_digit)w;
-  }
-
-  if (c != NULL) {
-     fp_clamp(&q);
-     fp_copy(&q, c);
-  }
-
-  return FP_OKAY;
-}
-
-
-/* c = a mod b, 0 <= c < b  */
-static int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
-{
-   return fp_div_d(a, b, NULL, c);
-}
-
-int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
-{
-   return fp_mod_d(a, b, c);
-}
-
-#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */
-
-#ifdef WOLFSSL_KEY_GEN
-
-static void fp_gcd(fp_int *a, fp_int *b, fp_int *c);
-static void fp_lcm(fp_int *a, fp_int *b, fp_int *c);
-static int  fp_isprime_ex(fp_int *a, int t);
-static int  fp_isprime(fp_int *a);
-static int  fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap);
-
-int mp_gcd(fp_int *a, fp_int *b, fp_int *c)
-{
-    fp_gcd(a, b, c);
-    return MP_OKAY;
-}
-
-
-int mp_lcm(fp_int *a, fp_int *b, fp_int *c)
-{
-    fp_lcm(a, b, c);
-    return MP_OKAY;
-}
-
-
-int mp_prime_is_prime(mp_int* a, int t, int* result)
-{
-    (void)t;
-    *result = fp_isprime(a);
-    return MP_OKAY;
-}
-
-int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap)
-{
-    int err;
-
-    err = fp_randprime(N, len, rng, heap);
-    switch(err) {
-        case FP_VAL:
-            return MP_VAL;
-        case FP_MEM:
-            return MP_MEM;
-        default:
-            break;
-    }
-
-    return MP_OKAY;
-}
-
-int mp_exch (mp_int * a, mp_int * b)
-{
-    fp_exch(a, b);
-    return MP_OKAY;
-}
-
-/* Miller-Rabin test of "a" to the base of "b" as described in
- * HAC pp. 139 Algorithm 4.24
- *
- * Sets result to 0 if definitely composite or 1 if probably prime.
- * Randomly the chance of error is no more than 1/4 and often
- * very much lower.
- */
-static void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
-{
-  fp_int  n1, y, r;
-  int     s, j;
-
-  /* default */
-  *result = FP_NO;
-
-  /* ensure b > 1 */
-  if (fp_cmp_d(b, 1) != FP_GT) {
-     return;
-  }
-
-  /* get n1 = a - 1 */
-  fp_init_copy(&n1, a);
-  fp_sub_d(&n1, 1, &n1);
-
-  /* set 2**s * r = n1 */
-  fp_init_copy(&r, &n1);
-
-  /* count the number of least significant bits
-   * which are zero
-   */
-  s = fp_cnt_lsb(&r);
-
-  /* now divide n - 1 by 2**s */
-  fp_div_2d (&r, s, &r, NULL);
-
-  /* compute y = b**r mod a */
-  fp_init(&y);
-  fp_exptmod(b, &r, a, &y);
-
-  /* if y != 1 and y != n1 do */
-  if (fp_cmp_d (&y, 1) != FP_EQ && fp_cmp (&y, &n1) != FP_EQ) {
-    j = 1;
-    /* while j <= s-1 and y != n1 */
-    while ((j <= (s - 1)) && fp_cmp (&y, &n1) != FP_EQ) {
-      fp_sqrmod (&y, a, &y);
-
-      /* if y == 1 then composite */
-      if (fp_cmp_d (&y, 1) == FP_EQ) {
-         return;
-      }
-      ++j;
-    }
-
-    /* if y != n1 then composite */
-    if (fp_cmp (&y, &n1) != FP_EQ) {
-       return;
-    }
-  }
-
-  /* probably prime now */
-  *result = FP_YES;
-}
-
-
-/* a few primes */
-static const fp_digit primes[FP_PRIME_SIZE] = {
-  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
-  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
-  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
-  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
-  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
-  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
-  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
-  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
-
-  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
-  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
-  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
-  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
-  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
-  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
-  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
-  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
-
-  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
-  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
-  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
-  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
-  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
-  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
-  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
-  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
-
-  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
-  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
-  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
-  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
-  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
-  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
-  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
-  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
-};
-
-int fp_isprime_ex(fp_int *a, int t)
-{
-   fp_int   b;
-   fp_digit d;
-   int      r, res;
-
-   if (t <= 0 || t > FP_PRIME_SIZE) {
-     return FP_NO;
-   }
-
-   /* do trial division */
-   for (r = 0; r < FP_PRIME_SIZE; r++) {
-       res = fp_mod_d(a, primes[r], &d);
-       if (res != MP_OKAY || d == 0) {
-           return FP_NO;
-       }
-   }
-
-   /* now do 't' miller rabins */
-   fp_init(&b);
-   for (r = 0; r < t; r++) {
-       fp_set(&b, primes[r]);
-       fp_prime_miller_rabin(a, &b, &res);
-       if (res == FP_NO) {
-          return FP_NO;
-       }
-   }
-   return FP_YES;
-}
-
-int fp_isprime(fp_int *a)
-{
-  return fp_isprime_ex(a, 8);
-}
-
-int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap)
-{
-    static const int USE_BBS = 1;
-    int   err, type;
-    byte* buf;
-
-    /* get type */
-    if (len < 0) {
-        type = USE_BBS;
-        len = -len;
-    } else {
-        type = 0;
-    }
-
-    /* allow sizes between 2 and 512 bytes for a prime size */
-    if (len < 2 || len > 512) {
-        return FP_VAL;
-    }
-
-    /* allocate buffer to work with */
-    buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (buf == NULL) {
-        return FP_MEM;
-    }
-    XMEMSET(buf, 0, len);
-
-    do {
-#ifdef SHOW_GEN
-        printf(".");
-        fflush(stdout);
-#endif
-        /* generate value */
-        err = wc_RNG_GenerateBlock(rng, buf, len);
-        if (err != 0) {
-            XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-            return FP_VAL;
-        }
-
-        /* munge bits */
-        buf[0]     |= 0x80 | 0x40;
-        buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
-
-        /* load value */
-        fp_read_unsigned_bin(N, buf, len);
-
-        /* test */
-    } while (fp_isprime(N) == FP_NO);
-
-    XMEMSET(buf, 0, len);
-    XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
-
-    return FP_OKAY;
-}
-
-/* c = [a, b] */
-void fp_lcm(fp_int *a, fp_int *b, fp_int *c)
-{
-   fp_int  t1, t2;
-
-   fp_init(&t1);
-   fp_init(&t2);
-   fp_gcd(a, b, &t1);
-   if (fp_cmp_mag(a, b) == FP_GT) {
-      fp_div(a, &t1, &t2, NULL);
-      fp_mul(b, &t2, c);
-   } else {
-      fp_div(b, &t1, &t2, NULL);
-      fp_mul(a, &t2, c);
-   }
-}
-
-
-
-/* c = (a, b) */
-void fp_gcd(fp_int *a, fp_int *b, fp_int *c)
-{
-   fp_int u, v, r;
-
-   /* either zero than gcd is the largest */
-   if (fp_iszero (a) == FP_YES && fp_iszero (b) == FP_NO) {
-     fp_abs (b, c);
-     return;
-   }
-   if (fp_iszero (a) == FP_NO && fp_iszero (b) == FP_YES) {
-     fp_abs (a, c);
-     return;
-   }
-
-   /* optimized.  At this point if a == 0 then
-    * b must equal zero too
-    */
-   if (fp_iszero (a) == FP_YES) {
-     fp_zero(c);
-     return;
-   }
-
-   /* sort inputs */
-   if (fp_cmp_mag(a, b) != FP_LT) {
-      fp_init_copy(&u, a);
-      fp_init_copy(&v, b);
-   } else {
-      fp_init_copy(&u, b);
-      fp_init_copy(&v, a);
-   }
-
-   fp_init(&r);
-   while (fp_iszero(&v) == FP_NO) {
-      fp_mod(&u, &v, &r);
-      fp_copy(&v, &u);
-      fp_copy(&r, &v);
-   }
-   fp_copy(&u, c);
-}
-
-#endif /* WOLFSSL_KEY_GEN */
-
-
-#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(OPENSSL_EXTRA) || \
-    defined(WC_RSA_BLINDING)
-/* c = a + b */
-void fp_add_d(fp_int *a, fp_digit b, fp_int *c)
-{
-   fp_int tmp;
-   fp_init(&tmp);
-   fp_set(&tmp, b);
-   fp_add(a, &tmp, c);
-}
-
-/* external compatibility */
-int mp_add_d(fp_int *a, fp_digit b, fp_int *c)
-{
-    fp_add_d(a, b, c);
-    return MP_OKAY;
-}
-
-#endif  /* HAVE_ECC || !NO_PWDBASED */
-
-
-#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \
-    defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \
-    defined(DEBUG_WOLFSSL)
-
-/* chars used in radix conversions */
-static const char* const fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                     "abcdefghijklmnopqrstuvwxyz+/";
-#endif
-
-#if !defined(NO_DSA) || defined(HAVE_ECC)
-#if DIGIT_BIT == 64 || DIGIT_BIT == 32
-static int fp_read_radix_16(fp_int *a, const char *str)
-{
-  int     i, j, k, neg;
-  char    ch;
-
-  /* if the leading digit is a
-   * minus set the sign to negative.
-   */
-  if (*str == '-') {
-    ++str;
-    neg = FP_NEG;
-  } else {
-    neg = FP_ZPOS;
-  }
-
-  j = 0;
-  k = 0;
-  for (i = (int)(XSTRLEN(str) - 1); i >= 0; i--) {
-      ch = str[i];
-      if (ch >= '0' && ch <= '9')
-          ch -= '0';
-      else if (ch >= 'A' && ch <= 'F')
-          ch -= 'A' - 10;
-      else if (ch >= 'a' && ch <= 'f')
-          ch -= 'a' - 10;
-      else
-          return FP_VAL;
-
-      a->dp[k] |= ((fp_digit)ch) << j;
-      j += 4;
-      k += j == DIGIT_BIT;
-      j &= DIGIT_BIT - 1;
-  }
-
-  a->used = k + 1;
-  fp_clamp(a);
-  /* set the sign only if a != 0 */
-  if (fp_iszero(a) != FP_YES) {
-     a->sign = neg;
-  }
-  return FP_OKAY;
-}
-#endif
-
-static int fp_read_radix(fp_int *a, const char *str, int radix)
-{
-  int     y, neg;
-  char    ch;
-
-  /* set the integer to the default of zero */
-  fp_zero (a);
-
-#if DIGIT_BIT == 64 || DIGIT_BIT == 32
-  if (radix == 16)
-      return fp_read_radix_16(a, str);
-#endif
-
-  /* make sure the radix is ok */
-  if (radix < 2 || radix > 64) {
-    return FP_VAL;
-  }
-
-  /* if the leading digit is a
-   * minus set the sign to negative.
-   */
-  if (*str == '-') {
-    ++str;
-    neg = FP_NEG;
-  } else {
-    neg = FP_ZPOS;
-  }
-
-  /* process each digit of the string */
-  while (*str) {
-    /* if the radix <= 36 the conversion is case insensitive
-     * this allows numbers like 1AB and 1ab to represent the same  value
-     * [e.g. in hex]
-     */
-    ch = (char)((radix <= 36) ? XTOUPPER((unsigned char)*str) : *str);
-    for (y = 0; y < 64; y++) {
-      if (ch == fp_s_rmap[y]) {
-         break;
-      }
-    }
-
-    /* if the char was found in the map
-     * and is less than the given radix add it
-     * to the number, otherwise exit the loop.
-     */
-    if (y < radix) {
-      fp_mul_d (a, (fp_digit) radix, a);
-      fp_add_d (a, (fp_digit) y, a);
-    } else {
-      break;
-    }
-    ++str;
-  }
-
-  /* set the sign only if a != 0 */
-  if (fp_iszero(a) != FP_YES) {
-     a->sign = neg;
-  }
-  return FP_OKAY;
-}
-
-/* fast math conversion */
-int mp_read_radix(mp_int *a, const char *str, int radix)
-{
-    return fp_read_radix(a, str, radix);
-}
-
-#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */
-
-#ifdef HAVE_ECC
-
-/* fast math conversion */
-int mp_sqr(fp_int *A, fp_int *B)
-{
-    fp_sqr(A, B);
-    return MP_OKAY;
-}
-
-/* fast math conversion */
-int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
-{
-    fp_montgomery_reduce(a, m, mp);
-    return MP_OKAY;
-}
-
-
-/* fast math conversion */
-int mp_montgomery_setup(fp_int *a, fp_digit *rho)
-{
-    return fp_montgomery_setup(a, rho);
-}
-
-int mp_div_2(fp_int * a, fp_int * b)
-{
-    fp_div_2(a, b);
-    return MP_OKAY;
-}
-
-
-int mp_init_copy(fp_int * a, fp_int * b)
-{
-    fp_init_copy(a, b);
-    return MP_OKAY;
-}
-
-#ifdef HAVE_COMP_KEY
-
-int mp_cnt_lsb(fp_int* a)
-{
-    return fp_cnt_lsb(a);
-}
-
-#endif /* HAVE_COMP_KEY */
-
-#endif /* HAVE_ECC */
-
-#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA)
-/* fast math conversion */
-int mp_set(fp_int *a, fp_digit b)
-{
-    fp_set(a,b);
-    return MP_OKAY;
-}
-#endif
-
-#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
-    defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
-    defined(WOLFSSL_PUBLIC_MP)
-
-/* returns size of ASCII representation */
-int mp_radix_size (mp_int *a, int radix, int *size)
-{
-    int     res, digs;
-    fp_int  t;
-    fp_digit d;
-
-    *size = 0;
-
-    /* special case for binary */
-    if (radix == 2) {
-        *size = fp_count_bits (a) + (a->sign == FP_NEG ? 1 : 0) + 1;
-        return FP_YES;
-    }
-
-    /* make sure the radix is in range */
-    if (radix < 2 || radix > 64) {
-        return FP_VAL;
-    }
-
-    if (fp_iszero(a) == MP_YES) {
-        *size = 2;
-        return FP_OKAY;
-    }
-
-    /* digs is the digit count */
-    digs = 0;
-
-    /* if it's negative add one for the sign */
-    if (a->sign == FP_NEG) {
-        ++digs;
-    }
-
-    /* init a copy of the input */
-    fp_init_copy (&t, a);
-
-    /* force temp to positive */
-    t.sign = FP_ZPOS;
-
-    /* fetch out all of the digits */
-    while (fp_iszero (&t) == FP_NO) {
-        if ((res = fp_div_d (&t, (mp_digit) radix, &t, &d)) != FP_OKAY) {
-            fp_zero (&t);
-            return res;
-        }
-        ++digs;
-    }
-    fp_zero (&t);
-
-    /* return digs + 1, the 1 is for the NULL byte that would be required. */
-    *size = digs + 1;
-    return FP_OKAY;
-}
-
-/* stores a bignum as a ASCII string in a given radix (2..64) */
-int mp_toradix (mp_int *a, char *str, int radix)
-{
-    int     res, digs;
-    fp_int  t;
-    fp_digit d;
-    char   *_s = str;
-
-    /* check range of the radix */
-    if (radix < 2 || radix > 64) {
-        return FP_VAL;
-    }
-
-    /* quick out if its zero */
-    if (fp_iszero(a) == FP_YES) {
-        *str++ = '0';
-        *str = '\0';
-        return FP_YES;
-    }
-
-    /* init a copy of the input */
-    fp_init_copy (&t, a);
-
-    /* if it is negative output a - */
-    if (t.sign == FP_NEG) {
-        ++_s;
-        *str++ = '-';
-        t.sign = FP_ZPOS;
-    }
-
-    digs = 0;
-    while (fp_iszero (&t) == FP_NO) {
-        if ((res = fp_div_d (&t, (fp_digit) radix, &t, &d)) != FP_OKAY) {
-            fp_zero (&t);
-            return res;
-        }
-        *str++ = fp_s_rmap[d];
-        ++digs;
-    }
-
-    /* reverse the digits of the string.  In this case _s points
-     * to the first digit [excluding the sign] of the number]
-     */
-    fp_reverse ((unsigned char *)_s, digs);
-
-    /* append a NULL so the string is properly terminated */
-    *str = '\0';
-
-    fp_zero (&t);
-    return FP_OKAY;
-}
-
-#ifdef WOLFSSL_DEBUG_MATH
-void mp_dump(const char* desc, mp_int* a, byte verbose)
-{
-  char buffer[FP_SIZE * sizeof(fp_digit) * 2];
-  int size = FP_SIZE;
-
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-  size = a->size;
-#endif
-
-  printf("%s: ptr=%p, used=%d, sign=%d, size=%d, fpd=%d\n",
-    desc, a, a->used, a->sign, size, (int)sizeof(fp_digit));
-
-  mp_tohex(a, buffer);
-  printf("  %s\n  ", buffer);
-
-  if (verbose) {
-    int i;
-    for(i=0; i<size * (int)sizeof(fp_digit); i++) {
-      printf("%x ", *(((byte*)a->dp) + i));
-    }
-    printf("\n");
-  }
-}
-#endif /* WOLFSSL_DEBUG_MATH */
-
-#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */
-
-
-int mp_abs(mp_int* a, mp_int* b)
-{
-    fp_abs(a, b);
-    return FP_OKAY;
-}
-
-
-int mp_lshd (mp_int * a, int b)
-{
-    fp_lshd(a, b);
-    return FP_OKAY;
-}
-
-#endif /* USE_FAST_MATH */
-
--- a/wolfcrypt/src/wc_encrypt.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,606 +0,0 @@
-/* wc_encrypt.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/aes.h>
-#include <wolfssl/wolfcrypt/des3.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#include <wolfssl/wolfcrypt/arc4.h>
-#include <wolfssl/wolfcrypt/wc_encrypt.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/asn.h>
-#include <wolfssl/wolfcrypt/coding.h>
-#include <wolfssl/wolfcrypt/pwdbased.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-#if !defined(NO_AES) && defined(HAVE_AES_CBC)
-#ifdef HAVE_AES_DECRYPT
-int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz,
-                                  const byte* key, word32 keySz, const byte* iv)
-{
-    int  ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Aes* aes = NULL;
-#else
-    Aes  aes[1];
-#endif
-
-    if (out == NULL || in == NULL || key == NULL || iv == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (aes == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_AesInit(aes, NULL, INVALID_DEVID);
-    if (ret == 0) {
-        ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION);
-        if (ret == 0)
-            ret = wc_AesCbcDecrypt(aes, out, in, inSz);
-
-        wc_AesFree(aes);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-#endif /* HAVE_AES_DECRYPT */
-
-int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz,
-                            const byte* key, word32 keySz, const byte* iv)
-{
-    int  ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Aes* aes = NULL;
-#else
-    Aes  aes[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (aes == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_AesInit(aes, NULL, INVALID_DEVID);
-    if (ret == 0) {
-        ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
-        if (ret == 0)
-            ret = wc_AesCbcEncrypt(aes, out, in, inSz);
-
-        wc_AesFree(aes);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-#endif /* !NO_AES && HAVE_AES_CBC */
-
-
-#ifndef NO_DES3
-int wc_Des_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
-                             const byte* key, const byte* iv)
-{
-    int ret  = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Des* des = NULL;
-#else
-    Des  des[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (des == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_Des_SetKey(des, key, iv, DES_ENCRYPTION);
-    if (ret == 0)
-        ret = wc_Des_CbcEncrypt(des, out, in, sz);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
-                             const byte* key, const byte* iv)
-{
-    int ret  = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Des* des = NULL;
-#else
-    Des  des[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (des == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION);
-    if (ret == 0)
-        ret = wc_Des_CbcDecrypt(des, out, in, sz);
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz,
-                              const byte* key, const byte* iv)
-{
-    int ret    = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Des3* des3 = NULL;
-#else
-    Des3  des3[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (des3 == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
-    if (ret == 0) {
-        ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION);
-        if (ret == 0)
-            ret = wc_Des3_CbcEncrypt(des3, out, in, sz);
-        wc_Des3Free(des3);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-
-int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz,
-                              const byte* key, const byte* iv)
-{
-    int ret    = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    Des3* des3 = NULL;
-#else
-    Des3  des3[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-    des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (des3 == NULL)
-        return MEMORY_E;
-#endif
-
-    ret = wc_Des3Init(des3, NULL, INVALID_DEVID);
-    if (ret == 0) {
-        ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION);
-        if (ret == 0)
-            ret = wc_Des3_CbcDecrypt(des3, out, in, sz);
-        wc_Des3Free(des3);
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* !NO_DES3 */
-
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-
-int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz,
-    const byte* password, int passwordSz, int hashType)
-{
-    int ret = NOT_COMPILED_IN;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* key      = NULL;
-#else
-    byte  key[WC_MAX_SYM_KEY_SIZE];
-#endif
-
-    (void)derSz;
-    (void)passwordSz;
-    (void)hashType;
-
-    if (der == NULL || password == NULL || info == NULL || info->keySz == 0) {
-        return BAD_FUNC_ARG;
-    }
-
-    /* use file's salt for key derivation, hex decode first */
-    if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) {
-        return BUFFER_E;
-    }
-    if (info->ivSz < PKCS5_SALT_SZ)
-        return BUFFER_E;
-
-#ifdef WOLFSSL_SMALL_STACK
-    key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-    if (key == NULL) {
-        return MEMORY_E;
-    }
-#endif
-
-#ifndef NO_PWDBASED
-    if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
-                                        info->keySz, hashType)) != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-#endif
-        return ret;
-    }
-#endif
-
-#ifndef NO_DES3
-    if (info->cipherType == WC_CIPHER_DES)
-        ret = wc_Des_CbcDecryptWithKey(der, der, derSz, key, info->iv);
-    if (info->cipherType == WC_CIPHER_DES3)
-        ret = wc_Des3_CbcDecryptWithKey(der, der, derSz, key, info->iv);
-#endif /* NO_DES3 */
-#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT)
-    if (info->cipherType == WC_CIPHER_AES_CBC)
-        ret = wc_AesCbcDecryptWithKey(der, der, derSz, key, info->keySz,
-            info->iv);
-#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-#endif
-
-    return ret;
-}
-
-int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz,
-    const byte* password, int passwordSz, int hashType)
-{
-    int ret = NOT_COMPILED_IN;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* key      = NULL;
-#else
-    byte  key[WC_MAX_SYM_KEY_SIZE];
-#endif
-
-    (void)derSz;
-    (void)passwordSz;
-    (void)hashType;
-
-    if (der == NULL || password == NULL || info == NULL || info->keySz == 0 ||
-            info->ivSz < PKCS5_SALT_SZ) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-    if (key == NULL) {
-        return MEMORY_E;
-    }
-#endif /* WOLFSSL_SMALL_STACK */
-
-#ifndef NO_PWDBASED
-    if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1,
-                                        info->keySz, hashType)) != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-#endif
-        return ret;
-    }
-#endif
-
-#ifndef NO_DES3
-    if (info->cipherType == WC_CIPHER_DES)
-        ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv);
-    if (info->cipherType == WC_CIPHER_DES3)
-        ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv);
-#endif /* NO_DES3 */
-#ifndef NO_AES
-    if (info->cipherType == WC_CIPHER_AES_CBC)
-        ret = wc_AesCbcEncryptWithKey(der, der, derSz, key, info->keySz,
-            info->iv);
-#endif /* NO_AES */
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(key, NULL, DYNAMIC_TYPE_SYMETRIC_KEY);
-#endif
-
-    return ret;
-}
-
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-
-#ifndef NO_PWDBASED
-
-/* Decrypt/Encrypt input in place from parameters based on id
- *
- * returns a negative value on fail case
- */
-int wc_CryptKey(const char* password, int passwordSz, byte* salt,
-                      int saltSz, int iterations, int id, byte* input,
-                      int length, int version, byte* cbcIv, int enc)
-{
-    int typeH;
-    int derivedLen;
-    int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
-    byte* key;
-#else
-    byte key[MAX_KEY_SIZE];
-#endif
-
-    (void)input;
-    (void)length;
-    (void)enc;
-
-    WOLFSSL_ENTER("wc_CryptKey");
-
-    switch (id) {
-    #ifndef NO_DES3
-        #ifndef NO_MD5
-        case PBE_MD5_DES:
-            typeH = WC_MD5;
-            derivedLen = 16;           /* may need iv for v1.5 */
-            break;
-        #endif
-        #ifndef NO_SHA
-        case PBE_SHA1_DES:
-            typeH = WC_SHA;
-            derivedLen = 16;           /* may need iv for v1.5 */
-            break;
-
-        case PBE_SHA1_DES3:
-            typeH = WC_SHA;
-            derivedLen = 32;           /* may need iv for v1.5 */
-            break;
-        #endif /* !NO_SHA */
-    #endif /* !NO_DES3 */
-    #if !defined(NO_SHA) && !defined(NO_RC4)
-        case PBE_SHA1_RC4_128:
-            typeH = WC_SHA;
-            derivedLen = 16;
-            break;
-    #endif
-    #ifdef WOLFSSL_AES_256
-        case PBE_AES256_CBC:
-            typeH = WC_SHA256;
-            derivedLen = 32;
-            break;
-    #endif
-        default:
-            WOLFSSL_MSG("Unknown/Unsupported encrypt/decrypt id");
-            return ALGO_ID_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (key == NULL)
-        return MEMORY_E;
-#endif
-
-    if (version == PKCS5v2)
-        ret = wc_PBKDF2(key, (byte*)password, passwordSz,
-                        salt, saltSz, iterations, derivedLen, typeH);
-#ifndef NO_SHA
-    else if (version == PKCS5)
-        ret = wc_PBKDF1(key, (byte*)password, passwordSz,
-                        salt, saltSz, iterations, derivedLen, typeH);
-#endif
-    else if (version == PKCS12v1) {
-        int  i, idx = 0;
-        byte unicodePasswd[MAX_UNICODE_SZ];
-
-        if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            return UNICODE_SIZE_E;
-        }
-
-        for (i = 0; i < passwordSz; i++) {
-            unicodePasswd[idx++] = 0x00;
-            unicodePasswd[idx++] = (byte)password[i];
-        }
-        /* add trailing NULL */
-        unicodePasswd[idx++] = 0x00;
-        unicodePasswd[idx++] = 0x00;
-
-        ret =  wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
-                            iterations, derivedLen, typeH, 1);
-        if (id != PBE_SHA1_RC4_128)
-            ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
-                                iterations, 8, typeH, 2);
-    }
-    else {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        WOLFSSL_MSG("Unknown/Unsupported PKCS version");
-        return ALGO_ID_E;
-    }
-
-    if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-        XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-        return ret;
-    }
-
-    switch (id) {
-#ifndef NO_DES3
-    #if !defined(NO_SHA) || !defined(NO_MD5)
-        case PBE_MD5_DES:
-        case PBE_SHA1_DES:
-        {
-            Des    des;
-            byte*  desIv = key + 8;
-
-            if (version == PKCS5v2 || version == PKCS12v1)
-                desIv = cbcIv;
-
-            if (enc) {
-                ret = wc_Des_SetKey(&des, key, desIv, DES_ENCRYPTION);
-            }
-            else {
-                ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION);
-            }
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return ret;
-            }
-
-            if (enc) {
-                wc_Des_CbcEncrypt(&des, input, input, length);
-            }
-            else {
-                wc_Des_CbcDecrypt(&des, input, input, length);
-            }
-            break;
-        }
-    #endif /* !NO_SHA || !NO_MD5 */
-
-    #ifndef NO_SHA
-        case PBE_SHA1_DES3:
-        {
-            Des3   des;
-            byte*  desIv = key + 24;
-
-            if (version == PKCS5v2 || version == PKCS12v1)
-                desIv = cbcIv;
-
-            ret = wc_Des3Init(&des, NULL, INVALID_DEVID);
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return ret;
-            }
-            if (enc) {
-                ret = wc_Des3_SetKey(&des, key, desIv, DES_ENCRYPTION);
-            }
-            else {
-                ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION);
-            }
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return ret;
-            }
-            if (enc) {
-                ret = wc_Des3_CbcEncrypt(&des, input, input, length);
-            }
-            else {
-                ret = wc_Des3_CbcDecrypt(&des, input, input, length);
-            }
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return ret;
-            }
-            break;
-        }
-    #endif /* !NO_SHA */
-#endif
-#if !defined(NO_RC4) && !defined(NO_SHA)
-        case PBE_SHA1_RC4_128:
-        {
-            Arc4    dec;
-
-            wc_Arc4SetKey(&dec, key, derivedLen);
-            wc_Arc4Process(&dec, input, input, length);
-            break;
-        }
-#endif
-#ifndef NO_AES
-    #ifdef WOLFSSL_AES_256
-        case PBE_AES256_CBC:
-        {
-            Aes dec;
-            ret = wc_AesInit(&dec, NULL, INVALID_DEVID);
-            if (ret == 0)
-                ret = wc_AesSetKey(&dec, key, derivedLen,
-                                   cbcIv, AES_DECRYPTION);
-            if (ret == 0)
-                ret = wc_AesCbcDecrypt(&dec, input, input, length);
-            if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
-                XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-                return ret;
-            }
-            ForceZero(&dec, sizeof(Aes));
-            break;
-        }
-    #endif /* WOLFSSL_AES_256 */
-#endif
-
-        default:
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-            WOLFSSL_MSG("Unknown/Unsupported encrypt/decryption algorithm");
-            return ALGO_ID_E;
-    }
-
-#ifdef WOLFSSL_SMALL_STACK
-    XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
-    return ret;
-}
-
-#endif /* !NO_PWDBASED */
-
--- a/wolfcrypt/src/wc_port.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1592 +0,0 @@
-/* port.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/wc_port.h>
-#ifdef HAVE_ECC
-    #include <wolfssl/wolfcrypt/ecc.h>
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-/* IPP header files for library initialization */
-#ifdef HAVE_FAST_RSA
-    #include <ipp.h>
-    #include <ippcp.h>
-#endif
-
-#ifdef FREESCALE_LTC_TFM
-    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
-#endif
-
-#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A)
-    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-    #include <wolfssl/openssl/evp.h>
-#endif
-
-#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY)
-    #include <wolfssl/wolfcrypt/memory.h>
-    #include <wolfssl/wolfcrypt/mem_track.h>
-#endif
-
-#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-    defined(WOLFSSL_IMX6_CAAM_BLOB)
-    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
-#endif
-
-#ifdef WOLF_CRYPTO_DEV
-    #include <wolfssl/wolfcrypt/cryptodev.h>
-#endif
-
-#ifdef _MSC_VER
-    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
-    #pragma warning(disable: 4996)
-#endif
-
-/* prevent multiple mutex initializations */
-static volatile int initRefCount = 0;
-
-/* Used to initialize state for wolfcrypt
-   return 0 on success
- */
-int wolfCrypt_Init(void)
-{
-    int ret = 0;
-
-    if (initRefCount == 0) {
-        WOLFSSL_ENTER("wolfCrypt_Init");
-
-    #ifdef WOLF_CRYPTO_DEV
-        wc_CryptoDev_Init();
-    #endif
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        ret = wolfAsync_HardwareStart();
-        if (ret != 0) {
-            WOLFSSL_MSG("Async hardware start failed");
-            /* don't return failure, allow operation to continue */
-        }
-    #endif
-
-    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
-        ret = InitMemoryTracker();
-        if (ret != 0) {
-            WOLFSSL_MSG("InitMemoryTracker failed");
-            return ret;
-        }
-    #endif
-
-    #if WOLFSSL_CRYPT_HW_MUTEX
-        /* If crypto hardware mutex protection is enabled, then initialize it */
-        ret = wolfSSL_CryptHwMutexInit();
-        if (ret != 0) {
-            WOLFSSL_MSG("Hw crypt mutex init failed");
-            return ret;
-        }
-    #endif
-
-    /* if defined have fast RSA then initialize Intel IPP */
-    #ifdef HAVE_FAST_RSA
-        WOLFSSL_MSG("Attempting to use optimized IPP Library");
-        if ((ret = ippInit()) != ippStsNoErr) {
-            /* possible to get a CPU feature support status on optimized IPP
-              library but still use default library and see competitive speeds */
-            WOLFSSL_MSG("Warning when trying to set up optimization");
-            WOLFSSL_MSG(ippGetStatusString(ret));
-            WOLFSSL_MSG("Using default fast IPP library");
-            ret = 0;
-            (void)ret; /* suppress not read warning */
-        }
-    #endif
-
-    #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC)
-        ret = ksdk_port_init();
-        if (ret != 0) {
-            WOLFSSL_MSG("KSDK port init failed");
-            return ret;
-        }
-    #endif
-
-    #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A)
-        atmel_init();
-    #endif
-
-    #ifdef WOLFSSL_ARMASM
-        WOLFSSL_MSG("Using ARM hardware acceleration");
-    #endif
-
-    #if !defined(WOLFCRYPT_ONLY) && \
-        ( defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) )
-        wolfSSL_EVP_init();
-    #endif
-
-    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-        if ((ret = wc_LoggingInit()) != 0) {
-            WOLFSSL_MSG("Error creating logging mutex");
-            return ret;
-        }
-    #endif
-
-#ifdef HAVE_ECC
-    #ifdef ECC_CACHE_CURVE
-        if ((ret = wc_ecc_curve_cache_init()) != 0) {
-            WOLFSSL_MSG("Error creating curve cache");
-            return ret;
-        }
-    #endif
-#endif
-
-#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-    defined(WOLFSSL_IMX6_CAAM_BLOB)
-        if ((ret = wc_caamInit()) != 0) {
-            return ret;
-        }
-#endif
-
-        initRefCount = 1;
-    }
-
-    return ret;
-}
-
-
-/* return success value is the same as wolfCrypt_Init */
-int wolfCrypt_Cleanup(void)
-{
-    int ret = 0;
-
-    if (initRefCount == 1) {
-        WOLFSSL_ENTER("wolfCrypt_Cleanup");
-
-#ifdef HAVE_ECC
-    #ifdef FP_ECC
-        wc_ecc_fp_free();
-    #endif
-    #ifdef ECC_CACHE_CURVE
-        wc_ecc_curve_cache_free();
-    #endif
-#endif /* HAVE_ECC */
-
-    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-        ret = wc_LoggingCleanup();
-    #endif
-
-    #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
-        ShowMemoryTracker();
-    #endif
-
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        wolfAsync_HardwareStop();
-    #endif
-
-    #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
-        defined(WOLFSSL_IMX6_CAAM_BLOB)
-        wc_caamFree();
-    #endif
-
-        initRefCount = 0; /* allow re-init */
-    }
-
-    return ret;
-}
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \
-	!defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
-
-/* File Handling Helpers */
-/* returns 0 if file found, -1 if no files or negative error */
-int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name)
-{
-    int ret = -1; /* default to no files found */
-
-    if (name)
-        *name = NULL;
-
-    if (ctx == NULL || path == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(ctx->name, 0, MAX_FILENAME_SZ);
-
-#ifdef USE_WINDOWS_API
-    XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 4);
-    XSTRNCAT(ctx->name, "\\*", 3);
-
-    ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData);
-    if (ctx->hFind == INVALID_HANDLE_VALUE) {
-        WOLFSSL_MSG("FindFirstFile for path verify locations failed");
-        return BAD_PATH_ERROR;
-    }
-
-    do {
-        if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
-            XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3);
-            XSTRNCAT(ctx->name, "\\", 2);
-            XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2);
-            if (name)
-                *name = ctx->name;
-            return 0;
-        }
-    } while (FindNextFileA(ctx->hFind, &ctx->FindFileData));
-#else
-    ctx->dir = opendir(path);
-    if (ctx->dir == NULL) {
-        WOLFSSL_MSG("opendir path verify locations failed");
-        return BAD_PATH_ERROR;
-    }
-
-    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
-        XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2);
-        XSTRNCAT(ctx->name, "/", 1);
-        XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2);
-
-        if (stat(ctx->name, &ctx->s) != 0) {
-            WOLFSSL_MSG("stat on name failed");
-            ret = BAD_PATH_ERROR;
-            break;
-        } else if (S_ISREG(ctx->s.st_mode)) {
-            if (name)
-                *name = ctx->name;
-            return 0;
-        }
-    }
-#endif
-    wc_ReadDirClose(ctx);
-
-    return ret;
-}
-
-/* returns 0 if file found, -1 if no more files */
-int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name)
-{
-    int ret = -1; /* default to no file found */
-
-    if (name)
-        *name = NULL;
-
-    if (ctx == NULL || path == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(ctx->name, 0, MAX_FILENAME_SZ);
-
-#ifdef USE_WINDOWS_API
-    while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) {
-        if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
-            XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3);
-            XSTRNCAT(ctx->name, "\\", 2);
-            XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2);
-            if (name)
-                *name = ctx->name;
-            return 0;
-        }
-    }
-#else
-    while ((ctx->entry = readdir(ctx->dir)) != NULL) {
-        XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2);
-        XSTRNCAT(ctx->name, "/", 1);
-        XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2);
-
-        if (stat(ctx->name, &ctx->s) != 0) {
-            WOLFSSL_MSG("stat on name failed");
-            ret = BAD_PATH_ERROR;
-            break;
-        } else if (S_ISREG(ctx->s.st_mode)) {
-            if (name)
-                *name = ctx->name;
-            return 0;
-        }
-    }
-#endif
-
-    wc_ReadDirClose(ctx);
-
-    return ret;
-}
-
-void wc_ReadDirClose(ReadDirCtx* ctx)
-{
-    if (ctx == NULL) {
-        return;
-    }
-
-#ifdef USE_WINDOWS_API
-    if (ctx->hFind != INVALID_HANDLE_VALUE) {
-        FindClose(ctx->hFind);
-        ctx->hFind = INVALID_HANDLE_VALUE;
-    }
-#else
-    if (ctx->dir) {
-        closedir(ctx->dir);
-        ctx->dir = NULL;
-    }
-#endif
-}
-
-#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
-
-
-wolfSSL_Mutex* wc_InitAndAllocMutex(void)
-{
-    wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL,
-            DYNAMIC_TYPE_MUTEX);
-    if (m != NULL) {
-        if (wc_InitMutex(m) != 0) {
-            WOLFSSL_MSG("Init Mutex failed");
-            XFREE(m, NULL, DYNAMIC_TYPE_MUTEX);
-            m = NULL;
-        }
-    }
-    else {
-        WOLFSSL_MSG("Memory error with Mutex allocation");
-    }
-
-    return m;
-}
-
-#ifdef USE_WOLF_STRTOK
-/* String token (delim) search. If str is null use nextp. */
-char* wc_strtok(char *str, const char *delim, char **nextp)
-{
-    char* ret;
-    int i, j;
-
-    /* Use next if str is NULL */
-    if (str == NULL && nextp)
-        str = *nextp;
-
-    /* verify str input */
-    if (str == NULL || *str == '\0')
-        return NULL;
-
-    /* match on entire delim */
-    for (i = 0; str[i]; i++) {
-        for (j = 0; delim[j]; j++) {
-            if (delim[j] == str[i])
-                break;
-        }
-        if (!delim[j])
-            break;
-    }
-    str += i;
-    /* if end of string, not found so return NULL */
-    if (*str == '\0')
-        return NULL;
-
-    ret = str;
-
-    /* match on first delim */
-    for (i = 0; str[i]; i++) {
-        for (j = 0; delim[j]; j++) {
-            if (delim[j] == str[i])
-                break;
-        }
-        if (delim[j] == str[i])
-            break;
-    }
-    str += i;
-
-    /* null terminate found string */
-    if (*str)
-        *str++ = '\0';
-
-    /* return pointer to next */
-    if (nextp)
-        *nextp = str;
-
-    return ret;
-}
-#endif /* USE_WOLF_STRTOK */
-
-#ifdef USE_WOLF_STRSEP
-char* wc_strsep(char **stringp, const char *delim)
-{
-    char *s, *tok;
-    const char *spanp;
-
-    /* null check */
-    if (stringp == NULL || *stringp == NULL)
-        return NULL;
-
-    s = *stringp;
-    for (tok = s; *tok; ++tok) {
-        for (spanp = delim; *spanp; ++spanp) {
-            /* found delimiter */
-            if (*tok == *spanp) {
-                *tok = '\0'; /* replace delim with null term */
-                *stringp = tok + 1; /* return past delim */
-                return s;
-            }
-        }
-    }
-
-    *stringp = NULL;
-    return s;
-}
-#endif /* USE_WOLF_STRSEP */
-
-#if WOLFSSL_CRYPT_HW_MUTEX
-/* Mutex for protection of cryptography hardware */
-static wolfSSL_Mutex wcCryptHwMutex;
-static int wcCryptHwMutexInit = 0;
-
-int wolfSSL_CryptHwMutexInit(void) {
-    int ret = 0;
-    if(wcCryptHwMutexInit == 0) {
-        ret = wc_InitMutex(&wcCryptHwMutex);
-        if(ret == 0) {
-            wcCryptHwMutexInit = 1;
-        }
-    }
-    return ret;
-}
-
-int wolfSSL_CryptHwMutexLock(void) {
-    int ret = BAD_MUTEX_E;
-
-    /* Make sure HW Mutex has been initialized */
-    wolfSSL_CryptHwMutexInit();
-
-    if(wcCryptHwMutexInit) {
-        ret = wc_LockMutex(&wcCryptHwMutex);
-    }
-    return ret;
-}
-
-int wolfSSL_CryptHwMutexUnLock(void) {
-    int ret = BAD_MUTEX_E;
-
-    if(wcCryptHwMutexInit) {
-        ret = wc_UnLockMutex(&wcCryptHwMutex);
-    }
-    return ret;
-}
-#endif /* WOLFSSL_CRYPT_HW_MUTEX */
-
-
-/* ---------------------------------------------------------------------------*/
-/* Mutex Ports */
-/* ---------------------------------------------------------------------------*/
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-    static mutex_cb*     compat_mutex_cb = NULL;
-
-    /* Function that locks or unlocks a mutex based on the flag passed in.
-     *
-     * flag lock or unlock i.e. CRYPTO_LOCK
-     * type the type of lock to unlock or lock
-     * file name of the file calling
-     * line the line number from file calling
-     */
-    int wc_LockMutex_ex(int flag, int type, const char* file, int line)
-    {
-        if (compat_mutex_cb != NULL) {
-            compat_mutex_cb(flag, type, file, line);
-            return 0;
-        }
-        else {
-            WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb");
-            return BAD_STATE_E;
-        }
-    }
-
-
-    /* Set the callback function to use for locking/unlocking mutex
-     *
-     * cb callback function to use
-     */
-    int wc_SetMutexCb(mutex_cb* cb)
-    {
-        compat_mutex_cb = cb;
-        return 0;
-    }
-#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */
-#ifdef SINGLE_THREADED
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        (void)m;
-        return 0;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex *m)
-    {
-        (void)m;
-        return 0;
-    }
-
-
-    int wc_LockMutex(wolfSSL_Mutex *m)
-    {
-        (void)m;
-        return 0;
-    }
-
-
-    int wc_UnLockMutex(wolfSSL_Mutex *m)
-    {
-        (void)m;
-        return 0;
-    }
-
-#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \
-  defined(FREESCALE_FREE_RTOS)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        int iReturn;
-
-        *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex();
-        if( *m != NULL )
-            iReturn = 0;
-        else
-            iReturn = BAD_MUTEX_E;
-
-        return iReturn;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        vSemaphoreDelete( *m );
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        /* Assume an infinite block, or should there be zero block? */
-        xSemaphoreTake( *m, portMAX_DELAY );
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        xSemaphoreGive( *m );
-        return 0;
-    }
-
-#elif defined(WOLFSSL_SAFERTOS)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        vSemaphoreCreateBinary(m->mutexBuffer, m->mutex);
-        if (m->mutex == NULL)
-            return BAD_MUTEX_E;
-
-        return 0;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        (void)m;
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        /* Assume an infinite block */
-        xSemaphoreTake(m->mutex, portMAX_DELAY);
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        xSemaphoreGive(m->mutex);
-        return 0;
-    }
-
-#elif defined(USE_WINDOWS_API)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        InitializeCriticalSection(m);
-        return 0;
-    }
-
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        DeleteCriticalSection(m);
-        return 0;
-    }
-
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        EnterCriticalSection(m);
-        return 0;
-    }
-
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        LeaveCriticalSection(m);
-        return 0;
-    }
-
-#elif defined(WOLFSSL_PTHREADS)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        if (pthread_mutex_init(m, 0) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        if (pthread_mutex_destroy(m) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        if (pthread_mutex_lock(m) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        if (pthread_mutex_unlock(m) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-#elif defined(THREADX)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        if (tx_mutex_delete(m) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        if (tx_mutex_put(m) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-#elif defined(MICRIUM)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        OS_ERR err;
-
-        OSMutexCreate(m, "wolfSSL Mutex", &err);
-
-        if (err == OS_ERR_NONE)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED)
-            OS_ERR err;
-
-            OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err);
-
-            if (err == OS_ERR_NONE)
-                return 0;
-            else
-                return BAD_MUTEX_E;
-        #else
-            return 0;
-        #endif
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        OS_ERR err;
-
-        OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
-
-        if (err == OS_ERR_NONE)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        OS_ERR err;
-
-        OSMutexPost(m, OS_OPT_POST_NONE, &err);
-
-        if (err == OS_ERR_NONE)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-#elif defined(EBSNET)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1)
-            return BAD_MUTEX_E;
-        else
-            return 0;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        rtp_sig_mutex_free(*m);
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        rtp_sig_mutex_release(*m);
-        return 0;
-    }
-
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        if (_mutex_init(m, NULL) == MQX_EOK)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        if (_mutex_destroy(m) == MQX_EOK)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        if (_mutex_lock(m) == MQX_EOK)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        if (_mutex_unlock(m) == MQX_EOK)
-            return 0;
-        else
-            return BAD_MUTEX_E;
-    }
-
-#elif defined(WOLFSSL_TIRTOS)
-    #include <xdc/runtime/Error.h>
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        Semaphore_Params params;
-        Error_Block eb;
-
-        Error_init(&eb);
-        Semaphore_Params_init(&params);
-        params.mode = Semaphore_Mode_BINARY;
-
-        *m = Semaphore_create(1, &params, &eb);
-        if (Error_check(&eb)) {
-            Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.",
-                NULL);
-            return BAD_MUTEX_E;
-        }
-        else
-            return 0;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        Semaphore_delete(m);
-
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        Semaphore_pend(*m, BIOS_WAIT_FOREVER);
-
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        Semaphore_post(*m);
-
-        return 0;
-    }
-
-#elif defined(WOLFSSL_uITRON4)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        int iReturn;
-        m->sem.sematr  = TA_TFIFO;
-        m->sem.isemcnt = 1;
-        m->sem.maxsem  = 1;
-        m->sem.name    = NULL;
-
-        m->id = acre_sem(&m->sem);
-        if( m->id != E_OK )
-            iReturn = 0;
-        else
-            iReturn = BAD_MUTEX_E;
-
-        return iReturn;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        del_sem( m->id );
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        wai_sem(m->id);
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        sig_sem(m->id);
-        return 0;
-    }
-
-    /****  uITRON malloc/free ***/
-    static ID ID_wolfssl_MPOOL = 0;
-    static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"};
-
-    int uITRON4_minit(size_t poolsz) {
-        ER ercd;
-        wolfssl_MPOOL.mplsz = poolsz;
-        ercd = acre_mpl(&wolfssl_MPOOL);
-        if (ercd > 0) {
-            ID_wolfssl_MPOOL = ercd;
-            return 0;
-        } else {
-            return -1;
-        }
-    }
-
-    void *uITRON4_malloc(size_t sz) {
-        ER ercd;
-        void *p;
-        ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p);
-        if (ercd == E_OK) {
-            return p;
-        } else {
-            return 0;
-        }
-    }
-
-    void *uITRON4_realloc(void *p, size_t sz) {
-      ER ercd;
-      void *newp;
-      if(p) {
-          ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp);
-          if (ercd == E_OK) {
-              XMEMCPY(newp, p, sz);
-              ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
-              if (ercd == E_OK) {
-                  return newp;
-              }
-          }
-      }
-      return 0;
-    }
-
-    void uITRON4_free(void *p) {
-        ER ercd;
-        ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p);
-        if (ercd == E_OK) {
-            return;
-        } else {
-            return;
-        }
-    }
-
-#elif defined(WOLFSSL_uTKERNEL2)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        int iReturn;
-        m->sem.sematr  = TA_TFIFO;
-        m->sem.isemcnt = 1;
-        m->sem.maxsem  = 1;
-
-        m->id = tk_cre_sem(&m->sem);
-        if( m->id != NULL )
-            iReturn = 0;
-        else
-            iReturn = BAD_MUTEX_E;
-
-        return iReturn;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        tk_del_sem(m->id);
-        return 0;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        tk_wai_sem(m->id, 1, TMO_FEVR);
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        tk_sig_sem(m->id, 1);
-        return 0;
-    }
-
-    /****  uT-Kernel malloc/free ***/
-    static ID ID_wolfssl_MPOOL = 0;
-    static T_CMPL wolfssl_MPOOL = {
-        NULL,       /* Extended information */
-        TA_TFIFO,   /* Memory pool attribute */
-        0,          /* Size of whole memory pool (byte) */
-        "wolfSSL"   /* Object name (max 8-char) */
-    };
-
-    int uTKernel_init_mpool(unsigned int sz) {
-        ER ercd;
-        wolfssl_MPOOL.mplsz = sz;
-        ercd = tk_cre_mpl(&wolfssl_MPOOL);
-        if (ercd > 0) {
-            ID_wolfssl_MPOOL = ercd;
-            return 0;
-        } else {
-            return (int)ercd;
-        }
-    }
-
-    void *uTKernel_malloc(unsigned int sz) {
-        ER ercd;
-        void *p;
-        ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR);
-        if (ercd == E_OK) {
-            return p;
-        } else {
-            return 0;
-        }
-    }
-
-    void *uTKernel_realloc(void *p, unsigned int sz) {
-      ER ercd;
-      void *newp;
-      if (p) {
-          ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR);
-          if (ercd == E_OK) {
-              XMEMCPY(newp, p, sz);
-              ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
-              if (ercd == E_OK) {
-                  return newp;
-              }
-          }
-      }
-      return 0;
-    }
-
-    void uTKernel_free(void *p) {
-        ER ercd;
-        ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p);
-        if (ercd == E_OK) {
-            return;
-        } else {
-            return;
-        }
-    }
-
-#elif defined (WOLFSSL_FROSTED)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        *m = mutex_init();
-        if (*m)
-            return 0;
-        else
-            return -1;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        mutex_destroy(*m);
-        return(0);
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        mutex_lock(*m);
-        return 0;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        mutex_unlock(*m);
-        return 0;
-    }
-
-#elif defined(WOLFSSL_CMSIS_RTOS)
-
-    #define CMSIS_NMUTEX 10
-    osMutexDef(wolfSSL_mt0);  osMutexDef(wolfSSL_mt1);  osMutexDef(wolfSSL_mt2);
-    osMutexDef(wolfSSL_mt3);  osMutexDef(wolfSSL_mt4);  osMutexDef(wolfSSL_mt5);
-    osMutexDef(wolfSSL_mt6);  osMutexDef(wolfSSL_mt7);  osMutexDef(wolfSSL_mt8);
-    osMutexDef(wolfSSL_mt9);
-
-    static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0),
-        osMutex(wolfSSL_mt1),    osMutex(wolfSSL_mt2),   osMutex(wolfSSL_mt3),
-        osMutex(wolfSSL_mt4),    osMutex(wolfSSL_mt5),   osMutex(wolfSSL_mt6),
-        osMutex(wolfSSL_mt7),    osMutex(wolfSSL_mt8),   osMutex(wolfSSL_mt9) };
-
-    static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0};
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        int i;
-        for (i=0; i<CMSIS_NMUTEX; i++) {
-            if(CMSIS_mutexID[i] == 0) {
-                CMSIS_mutexID[i] = osMutexCreate(CMSIS_mutex[i]);
-                (*m) = CMSIS_mutexID[i];
-            return 0;
-            }
-        }
-        return -1;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        int i;
-        osMutexDelete   (*m);
-        for (i=0; i<CMSIS_NMUTEX; i++) {
-            if(CMSIS_mutexID[i] == (*m)) {
-                CMSIS_mutexID[i] = 0;
-                return(0);
-            }
-        }
-        return(-1);
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        osMutexWait(*m, osWaitForever);
-        return(0);
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        osMutexRelease (*m);
-        return 0;
-    }
-
-#elif defined(WOLFSSL_MDK_ARM)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        os_mut_init (m);
-        return 0;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        return(0);
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        os_mut_wait (m, 0xffff);
-        return(0);
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        os_mut_release (m);
-        return 0;
-    }
-
-#elif defined(INTIME_RTOS)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        int ret = 0;
-
-        if (m == NULL)
-            return BAD_FUNC_ARG;
-
-        *m = CreateRtSemaphore(
-            1,                      /* initial unit count */
-            1,                      /* maximum unit count */
-            PRIORITY_QUEUING        /* creation flags: FIFO_QUEUING or PRIORITY_QUEUING */
-        );
-        if (*m == BAD_RTHANDLE) {
-            ret = GetLastRtError();
-            if (ret != E_OK)
-                ret = BAD_MUTEX_E;
-        }
-        return ret;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        int ret = 0;
-        BOOLEAN del;
-
-        if (m == NULL)
-            return BAD_FUNC_ARG;
-
-        del = DeleteRtSemaphore(
-            *m                      /* handle for RT semaphore */
-        );
-    	if (del != TRUE)
-    		ret = BAD_MUTEX_E;
-
-        return ret;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        int ret = 0;
-        DWORD lck;
-
-        if (m == NULL)
-            return BAD_FUNC_ARG;
-
-        lck = WaitForRtSemaphore(
-            *m,                     /* handle for RT semaphore */
-            1,                      /* number of units to wait for */
-            WAIT_FOREVER            /* number of milliseconds to wait for units */
-        );
-        if (lck == WAIT_FAILED) {
-            ret = GetLastRtError();
-            if (ret != E_OK)
-                ret = BAD_MUTEX_E;
-        }
-        return ret;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        int ret = 0;
-        BOOLEAN rel;
-
-        if (m == NULL)
-            return BAD_FUNC_ARG;
-
-        rel = ReleaseRtSemaphore(
-            *m,                     /* handle for RT semaphore */
-            1                       /* number of units to release to semaphore */
-        );
-    	if (rel != TRUE)
-    		ret = BAD_MUTEX_E;
-
-        return ret;
-    }
-
-#elif defined(WOLFSSL_NUCLEUS_1_2)
-
-    int wc_InitMutex(wolfSSL_Mutex* m)
-    {
-        /* Call the Nucleus function to create the semaphore */
-        if (NU_Create_Semaphore(m, "WOLFSSL_MTX", 1,
-                                NU_PRIORITY) == NU_SUCCESS) {
-            return 0;
-        }
-
-        return BAD_MUTEX_E;
-    }
-
-    int wc_FreeMutex(wolfSSL_Mutex* m)
-    {
-        if (NU_Delete_Semaphore(m) == NU_SUCCESS)
-            return 0;
-
-        return BAD_MUTEX_E;
-    }
-
-    int wc_LockMutex(wolfSSL_Mutex* m)
-    {
-        /* passing suspend task option */
-        if (NU_Obtain_Semaphore(m, NU_SUSPEND) == NU_SUCCESS)
-            return 0;
-
-        return BAD_MUTEX_E;
-    }
-
-    int wc_UnLockMutex(wolfSSL_Mutex* m)
-    {
-        if (NU_Release_Semaphore(m) == NU_SUCCESS)
-            return 0;
-
-        return BAD_MUTEX_E;
-    }
-
-#else
-    #warning No mutex handling defined
-
-#endif
-
-#ifndef NO_ASN_TIME
-#if defined(_WIN32_WCE)
-time_t windows_time(time_t* timer)
-{
-    SYSTEMTIME     sysTime;
-    FILETIME       fTime;
-    ULARGE_INTEGER intTime;
-    time_t         localTime;
-
-    if (timer == NULL)
-        timer = &localTime;
-
-    GetSystemTime(&sysTime);
-    SystemTimeToFileTime(&sysTime, &fTime);
-
-    XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
-    /* subtract EPOCH */
-    intTime.QuadPart -= 0x19db1ded53e8000;
-    /* to secs */
-    intTime.QuadPart /= 10000000;
-    *timer = (time_t)intTime.QuadPart;
-
-    return *timer;
-}
-#endif /*  _WIN32_WCE */
-
-#if defined(WOLFSSL_GMTIME)
-struct tm* gmtime(const time_t* timer)
-{
-    #define YEAR0          1900
-    #define EPOCH_YEAR     1970
-    #define SECS_DAY       (24L * 60L * 60L)
-    #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
-    #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
-
-    static const int _ytab[2][12] =
-    {
-        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
-        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
-    };
-
-    static struct tm st_time;
-    struct tm* ret = &st_time;
-    time_t secs = *timer;
-    unsigned long dayclock, dayno;
-    int year = EPOCH_YEAR;
-
-    dayclock = (unsigned long)secs % SECS_DAY;
-    dayno    = (unsigned long)secs / SECS_DAY;
-
-    ret->tm_sec  = (int) dayclock % 60;
-    ret->tm_min  = (int)(dayclock % 3600) / 60;
-    ret->tm_hour = (int) dayclock / 3600;
-    ret->tm_wday = (int) (dayno + 4) % 7;        /* day 0 a Thursday */
-
-    while(dayno >= (unsigned long)YEARSIZE(year)) {
-        dayno -= YEARSIZE(year);
-        year++;
-    }
-
-    ret->tm_year = year - YEAR0;
-    ret->tm_yday = (int)dayno;
-    ret->tm_mon  = 0;
-
-    while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
-        dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
-        ret->tm_mon++;
-    }
-
-    ret->tm_mday  = (int)++dayno;
-    ret->tm_isdst = 0;
-
-    return ret;
-}
-#endif /* WOLFSSL_GMTIME */
-
-
-#if defined(HAVE_RTP_SYS)
-#define YEAR0          1900
-
-struct tm* rtpsys_gmtime(const time_t* timer)       /* has a gmtime() but hangs */
-{
-    static struct tm st_time;
-    struct tm* ret = &st_time;
-
-    DC_RTC_CALENDAR cal;
-    dc_rtc_time_get(&cal, TRUE);
-
-    ret->tm_year  = cal.year - YEAR0;       /* gm starts at 1900 */
-    ret->tm_mon   = cal.month - 1;          /* gm starts at 0 */
-    ret->tm_mday  = cal.day;
-    ret->tm_hour  = cal.hour;
-    ret->tm_min   = cal.minute;
-    ret->tm_sec   = cal.second;
-
-    return ret;
-}
-
-#endif /* HAVE_RTP_SYS */
-
-
-#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
-
-/*
- * time() is just a stub in Microchip libraries. We need our own
- * implementation. Use SNTP client to get seconds since epoch.
- */
-time_t pic32_time(time_t* timer)
-{
-#ifdef MICROCHIP_TCPIP_V5
-    DWORD sec = 0;
-#else
-    uint32_t sec = 0;
-#endif
-    time_t localTime;
-
-    if (timer == NULL)
-        timer = &localTime;
-
-#ifdef MICROCHIP_MPLAB_HARMONY
-    sec = TCPIP_SNTP_UTCSecondsGet();
-#else
-    sec = SNTPGetUTCSeconds();
-#endif
-    *timer = (time_t) sec;
-
-    return *timer;
-}
-
-#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */
-
-#if defined(MICRIUM)
-
-time_t micrium_time(time_t* timer)
-{
-    CLK_TS_SEC sec;
-
-    Clk_GetTS_Unix(&sec);
-
-    return (time_t) sec;
-}
-
-#endif /* MICRIUM */
-
-#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-
-time_t mqx_time(time_t* timer)
-{
-    time_t localTime;
-    TIME_STRUCT time_s;
-
-    if (timer == NULL)
-        timer = &localTime;
-
-    _time_get(&time_s);
-    *timer = (time_t) time_s.SECONDS;
-
-    return *timer;
-}
-
-#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */
-
-
-#if defined(WOLFSSL_TIRTOS)
-
-time_t XTIME(time_t * timer)
-{
-    time_t sec = 0;
-
-    sec = (time_t) Seconds_get();
-
-    if (timer != NULL)
-        *timer = sec;
-
-    return sec;
-}
-
-#endif /* WOLFSSL_TIRTOS */
-
-#if defined(WOLFSSL_XILINX)
-#include "xrtcpsu.h"
-
-time_t XTIME(time_t * timer)
-{
-    time_t sec = 0;
-    XRtcPsu_Config* con;
-    XRtcPsu         rtc;
-
-    con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID);
-    if (con != NULL) {
-        if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) {
-            sec = (time_t)XRtcPsu_GetCurrentTime(&rtc);
-        }
-        else {
-            WOLFSSL_MSG("Unable to initialize RTC");
-        }
-    }
-
-    if (timer != NULL)
-        *timer = sec;
-
-    return sec;
-}
-
-#endif /* WOLFSSL_XILINX */
-#endif /* !NO_ASN_TIME */
-
-#ifndef WOLFSSL_LEANPSK
-char* mystrnstr(const char* s1, const char* s2, unsigned int n)
-{
-    unsigned int s2_len = (unsigned int)XSTRLEN(s2);
-
-    if (s2_len == 0)
-        return (char*)s1;
-
-    while (n >= s2_len && s1[0]) {
-        if (s1[0] == s2[0])
-            if (XMEMCMP(s1, s2, s2_len) == 0)
-                return (char*)s1;
-        s1++;
-        n--;
-    }
-
-    return NULL;
-}
-#endif
-
-/* custom memory wrappers */
-#ifdef WOLFSSL_NUCLEUS_1_2
-
-    /* system memory pool */
-    extern NU_MEMORY_POOL System_Memory;
-
-    void* nucleus_malloc(unsigned long size, void* heap, int type)
-    {
-        STATUS status;
-        void*  stack_ptr;
-
-        status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size,
-                                    NU_NO_SUSPEND);
-        if (status == NU_SUCCESS) {
-            return 0;
-        } else {
-            return stack_ptr;
-        }
-    }
-
-    void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type)
-    {
-        STATUS     status;
-        DM_HEADER* old_header;
-        word32     old_size, copy_size;
-        void*      new_mem;
-
-        /* if ptr is NULL, behave like malloc */
-        new_mem = nucleus_malloc(size, NULL, 0);
-        if (new_mem == 0 || ptr == 0) {
-            return new_mem;
-        }
-
-        /* calculate old memory block size */
-        /* mem pointers stored in block headers (ref dm_defs.h) */
-        old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD);
-        old_size   = (byte*)old_header->dm_next_memory - (byte*)ptr;
-
-        /* copy old to new */
-        if (old_size < size) {
-            copy_size = old_size;
-        } else {
-            copy_size = size;
-        }
-        XMEMCPY(new_mem, ptr, copy_size);
-
-        /* free old */
-        nucleus_free(ptr, NULL, 0);
-
-        return new_mem;
-    }
-
-    void nucleus_free(void* ptr, void* heap, int type)
-    {
-        if (ptr != NULL)
-            NU_Deallocate_Memory(ptr);
-    }
-
-#endif /* WOLFSSL_NUCLEUS_1_2 */
-
-#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH)
-    #include <wolfcrypt/src/port/ti/ti-ccm.c>  /* initialize and Mutex for TI Crypt Engine */
-    #include <wolfcrypt/src/port/ti/ti-hash.c> /* md5, sha1, sha224, sha256 */
-#endif
-
--- a/wolfcrypt/src/wolfcrypt_first.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfcrypt/src/wolfcrypt_last.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfcrypt/src/wolfevent.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/* wolfevent.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-
-#ifdef HAVE_WOLF_EVENT
-
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/error-crypt.h>
-
-#include <wolfssl/wolfcrypt/wolfevent.h>
-
-
-int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context)
-{
-    if (event == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (event->state == WOLF_EVENT_STATE_PENDING) {
-        WOLFSSL_MSG("Event already pending!");
-        return BAD_COND_E;
-    }
-
-    XMEMSET(event, 0, sizeof(WOLF_EVENT));
-    event->type = type;
-    event->context = context;
-
-    return 0;
-}
-
-int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags)
-{
-    int ret = BAD_COND_E;
-
-    /* Check hardware */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST &&
-        event->type <= WOLF_EVENT_TYPE_ASYNC_LAST)
-    {
-        ret = wolfAsync_EventPoll(event, flags);
-    }
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-    return ret;
-}
-
-int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue)
-{
-    int ret = 0;
-
-    if (queue == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    XMEMSET(queue, 0, sizeof(WOLF_EVENT_QUEUE));
-#ifndef SINGLE_THREADED
-    ret = wc_InitMutex(&queue->lock);
-#endif
-    return ret;
-}
-
-
-int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event)
-{
-    int ret;
-
-    if (queue == NULL || event == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef SINGLE_THREADED
-    if ((ret = wc_LockMutex(&queue->lock)) != 0) {
-        return ret;
-    }
-#endif
-
-    ret = wolfEventQueue_Add(queue, event);
-
-#ifndef SINGLE_THREADED
-    wc_UnLockMutex(&queue->lock);
-#endif
-
-    return ret;
-}
-
-int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event)
-{
-    int ret = 0;
-
-    if (queue == NULL || event == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef SINGLE_THREADED
-    /* In single threaded mode "event_queue.lock" doesn't exist */
-    if ((ret = wc_LockMutex(&queue->lock)) != 0) {
-        return ret;
-    }
-#endif
-
-    /* Pop first item off queue */
-    *event = queue->head;
-    ret = wolfEventQueue_Remove(queue, *event);
-
-#ifndef SINGLE_THREADED
-    wc_UnLockMutex(&queue->lock);
-#endif
-
-    return ret;
-}
-
-/* assumes queue is locked by caller */
-int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event)
-{
-    if (queue == NULL || event == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    event->next = NULL; /* added to end */
-    event->prev = NULL;
-    if (queue->tail == NULL)  {
-        queue->head = event;
-    }
-    else {
-        queue->tail->next = event;
-        event->prev = queue->tail;
-    }
-    queue->tail = event;      /* add to the end either way */
-    queue->count++;
-
-    return 0;
-}
-
-/* assumes queue is locked by caller */
-int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event)
-{
-    int ret = 0;
-
-    if (queue == NULL || event == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (event == queue->head && event == queue->tail) {
-        queue->head = NULL;
-        queue->tail = NULL;
-    }
-    else if (event == queue->head) {
-        queue->head = event->next;
-        queue->head->prev = NULL;
-    }
-    else if (event == queue->tail) {
-        queue->tail = event->prev;
-        queue->tail->next = NULL;
-    }
-    else {
-        WOLF_EVENT* next = event->next;
-        WOLF_EVENT* prev = event->prev;
-        next->prev = prev;
-        prev->next = next;
-    }
-    queue->count--;
-
-    return ret;
-}
-
-int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter,
-    WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount)
-{
-    WOLF_EVENT* event;
-    int ret = 0, count = 0;
-
-    if (queue == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef SINGLE_THREADED
-    /* In single threaded mode "event_queue.lock" doesn't exist */
-    if ((ret = wc_LockMutex(&queue->lock)) != 0) {
-        return ret;
-    }
-#endif
-
-    /* itterate event queue */
-    for (event = queue->head; event != NULL; event = event->next)
-    {
-        /* optional filter based on context */
-        if (context_filter == NULL || event->context == context_filter) {
-
-            /* poll event */
-            ret = wolfEvent_Poll(event, flags);
-            if (ret < 0) break; /* exit for */
-
-            /* If event is done then process */
-            if (event->state == WOLF_EVENT_STATE_DONE) {
-                /* remove from queue */
-                ret = wolfEventQueue_Remove(queue, event);
-                if (ret < 0) break; /* exit for */
-
-                /* return pointer in 'events' arg */
-                if (events) {
-                    events[count] = event; /* return pointer */
-                }
-                count++;
-
-                /* check to make sure our event list isn't full */
-                if (events && count >= maxEvents) {
-                    break; /* exit for */
-                }
-            }
-        }
-    }
-
-#ifndef SINGLE_THREADED
-    wc_UnLockMutex(&queue->lock);
-#endif
-
-    /* return number of properly populated events */
-    if (eventCount) {
-        *eventCount = count;
-    }
-
-    return ret;
-}
-
-int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue)
-{
-    int ret;
-
-    if (queue == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-#ifndef SINGLE_THREADED
-    /* In single threaded mode "event_queue.lock" doesn't exist */
-    if ((ret = wc_LockMutex(&queue->lock)) != 0) {
-        return ret;
-    }
-#endif
-
-    ret = queue->count;
-
-#ifndef SINGLE_THREADED
-    wc_UnLockMutex(&queue->lock);
-#endif
-
-    return ret;
-}
-
-void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue)
-{
-    if (queue) {
-    #ifndef SINGLE_THREADED
-        wc_FreeMutex(&queue->lock);
-    #endif
-    }
-}
-
-#endif /* HAVE_WOLF_EVENT */
-
--- a/wolfcrypt/src/wolfmath.c	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/* wolfmath.c
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* common functions for either math library */
-
-#ifdef HAVE_CONFIG_H
-    #include <config.h>
-#endif
-
-/* in case user set USE_FAST_MATH there */
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef USE_FAST_MATH
-    #include <wolfssl/wolfcrypt/tfm.h>
-#else
-    #include <wolfssl/wolfcrypt/integer.h>
-#endif
-
-#include <wolfssl/wolfcrypt/error-crypt.h>
-#include <wolfssl/wolfcrypt/logging.h>
-
-#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT)
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifdef NO_INLINE
-    #include <wolfssl/wolfcrypt/misc.h>
-#else
-    #define WOLFSSL_MISC_INCLUDED
-    #include <wolfcrypt/src/misc.c>
-#endif
-
-
-#if !defined(WC_NO_CACHE_RESISTANT) && \
-    ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \
-     (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT)))
-
-    /* all off / all on pointer addresses for constant calculations */
-    /* ecc.c uses same table */
-    const wolfssl_word wc_off_on_addr[2] =
-    {
-    #if defined(WC_64BIT_CPU)
-        W64LIT(0x0000000000000000),
-        W64LIT(0xffffffffffffffff)
-    #elif defined(WC_16BIT_CPU)
-        0x0000U,
-        0xffffU
-    #else
-        /* 32 bit */
-        0x00000000U,
-        0xffffffffU
-    #endif
-    };
-#endif
-
-
-int get_digit_count(mp_int* a)
-{
-    if (a == NULL)
-        return 0;
-
-    return a->used;
-}
-
-mp_digit get_digit(mp_int* a, int n)
-{
-    if (a == NULL)
-        return 0;
-
-    return (n >= a->used || n < 0) ? 0 : a->dp[n];
-}
-
-int get_rand_digit(WC_RNG* rng, mp_digit* d)
-{
-    return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit));
-}
-
-#ifdef WC_RSA_BLINDING
-int mp_rand(mp_int* a, int digits, WC_RNG* rng)
-{
-    int ret = 0;
-    DECLARE_VAR(d, mp_digit, 1, rng->heap);
-
-    if (rng == NULL) {
-        ret = MISSING_RNG_E; goto exit;
-    }
-
-    if (a == NULL
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        || d == NULL
-    #endif
-    ) {
-        ret = BAD_FUNC_ARG; goto exit;
-    }
-
-    mp_zero(a);
-    if (digits <= 0) {
-        ret = MP_OKAY; goto exit;
-    }
-
-    /* first place a random non-zero digit */
-    do {
-        ret = get_rand_digit(rng, d);
-        if (ret != 0) {
-            goto exit;
-        }
-    } while (*d == 0);
-
-    if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) {
-        goto exit;
-    }
-
-    while (--digits > 0) {
-        if ((ret = mp_lshd(a, 1)) != MP_OKAY) {
-            goto exit;
-        }
-        if ((ret = get_rand_digit(rng, d)) != 0) {
-            goto exit;
-        }
-        if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) {
-            goto exit;
-        }
-    }
-
-exit:
-    FREE_VAR(d, rng->heap);
-
-    return ret;
-}
-#endif /* WC_RSA_BLINDING */
-
-
-#ifdef HAVE_WOLF_BIGINT
-void wc_bigint_init(WC_BIGINT* a)
-{
-    if (a != NULL) {
-        a->buf = NULL;
-        a->len = 0;
-        a->heap = NULL;
-    }
-}
-
-int wc_bigint_alloc(WC_BIGINT* a, word32 sz)
-{
-    int err = MP_OKAY;
-
-    if (a == NULL)
-        return BAD_FUNC_ARG;
-
-    if (sz > 0) {
-        if (a->buf && sz > a->len) {
-            wc_bigint_free(a);
-        }
-        if (a->buf == NULL) {
-            a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
-        }
-        if (a->buf == NULL) {
-            err = MP_MEM;
-        }
-        else {
-            XMEMSET(a->buf, 0, sz);
-        }
-    }
-    a->len = sz;
-
-    return err;
-}
-
-/* assumes input is big endian format */
-int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen)
-{
-    int err;
-
-    if (a == NULL || in == NULL || inlen == 0)
-        return BAD_FUNC_ARG;
-
-    err = wc_bigint_alloc(a, inlen);
-    if (err == 0) {
-        XMEMCPY(a->buf, in, inlen);
-    }
-
-    return err;
-}
-
-int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen)
-{
-    word32 sz;
-
-    if (a == NULL || out == NULL || outlen == NULL || *outlen == 0)
-        return BAD_FUNC_ARG;
-
-    /* trim to fit into output buffer */
-    sz = a->len;
-    if (a->len > *outlen) {
-        WOLFSSL_MSG("wc_bigint_export: Truncating output");
-        sz = *outlen;
-    }
-
-    if (a->buf) {
-        XMEMCPY(out, a->buf, sz);
-    }
-
-    *outlen = sz;
-
-    return MP_OKAY;
-}
-
-void wc_bigint_zero(WC_BIGINT* a)
-{
-    if (a && a->buf) {
-        ForceZero(a->buf, a->len);
-    }
-}
-
-void wc_bigint_free(WC_BIGINT* a)
-{
-    if (a) {
-        if (a->buf) {
-          XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
-        }
-        a->buf = NULL;
-        a->len = 0;
-    }
-}
-
-/* sz: make sure the buffer is at least that size and zero padded.
- *     A `sz == 0` will use the size of `src`.
- *     The calulcates sz is stored into dst->len in `wc_bigint_alloc`.
- */
-int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz)
-{
-    int err;
-    word32 x, y;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    /* get size of source */
-    x = mp_unsigned_bin_size(src);
-    if (sz < x)
-        sz = x;
-
-    /* make sure destination is allocated and large enough */
-    err = wc_bigint_alloc(dst, sz);
-    if (err == MP_OKAY) {
-
-        /* leading zero pad */
-        y = sz - x;
-        XMEMSET(dst->buf, 0, y);
-
-        /* export src as unsigned bin to destination buf */
-        err = mp_to_unsigned_bin(src, dst->buf + y);
-    }
-
-    return err;
-}
-
-int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst)
-{
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    return wc_mp_to_bigint_sz(src, dst, 0);
-}
-
-int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst)
-{
-    int err;
-
-    if (src == NULL || dst == NULL)
-        return BAD_FUNC_ARG;
-
-    if (src->buf == NULL)
-        return BAD_FUNC_ARG;
-
-    err = mp_read_unsigned_bin(dst, src->buf, src->len);
-    wc_bigint_free(src);
-
-    return err;
-}
-
-#endif /* HAVE_WOLF_BIGINT */
-
-#endif /* USE_FAST_MATH || !NO_BIG_INT */
-
--- a/wolfssl/error-ssl.h	Tue Nov 19 14:32:16 2019 +0000
+++ b/wolfssl/error-ssl.h	Wed Nov 20 13:27:48 2019 +0000
@@ -1,202 +1,202 @@
-/* error-ssl.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLFSSL_ERROR_H
-#define WOLFSSL_ERROR_H
-
-#include <wolfssl/wolfcrypt/error-crypt.h>   /* pull in wolfCrypt errors */
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum wolfSSL_ErrorCodes {
-    INPUT_CASE_ERROR             = -301,   /* process input state error */
-    PREFIX_ERROR                 = -302,   /* bad index to key rounds  */
-    MEMORY_ERROR                 = -303,   /* out of memory            */
-    VERIFY_FINISHED_ERROR        = -304,   /* verify problem on finished */
-    VERIFY_MAC_ERROR             = -305,   /* verify mac problem       */
-    PARSE_ERROR                  = -306,   /* parse error on header    */
-    UNKNOWN_HANDSHAKE_TYPE       = -307,   /* weird handshake type     */
-    SOCKET_ERROR_E               = -308,   /* error state on socket    */
-    SOCKET_NODATA                = -309,   /* expected data, not there */
-    INCOMPLETE_DATA              = -310,   /* don't have enough data to
-                                              complete task            */
-    UNKNOWN_RECORD_TYPE          = -311,   /* unknown type in record hdr */
-    DECRYPT_ERROR                = -312,   /* error during decryption  */
-    FATAL_ERROR                  = -313,   /* recvd alert fatal error  */
-    ENCRYPT_ERROR                = -314,   /* error during encryption  */
-    FREAD_ERROR                  = -315,   /* fread problem            */
-    NO_PEER_KEY                  = -316,   /* need peer's key          */
-    NO_PRIVATE_KEY               = -317,   /* need the private key     */
-    RSA_PRIVATE_ERROR            = -318,   /* error during rsa priv op */
-    NO_DH_PARAMS                 = -319,   /* server missing DH params */
-    BUILD_MSG_ERROR              = -320,   /* build message failure    */
-
-    BAD_HELLO                    = -321,   /* client hello malformed   */
-    DOMAIN_NAME_MISMATCH         = -322,   /* peer subject name mismatch */
-    WANT_READ                    = -323,   /* want read, call again    */
-    NOT_READY_ERROR              = -324,   /* handshake layer not ready */
-
-    VERSION_ERROR                = -326,   /* record layer version error */
-    WANT_WRITE                   = -327,   /* want write, call again   */
-    BUFFER_ERROR                 = -328,   /* malformed buffer input   */
-    VERIFY_CERT_ERROR            = -329,   /* verify cert error        */
-    VERIFY_SIGN_ERROR            = -330,   /* verify sign error        */
-    CLIENT_ID_ERROR              = -331,   /* psk client identity error  */
-    SERVER_HINT_ERROR            = -332,   /* psk server hint error  */
-    PSK_KEY_ERROR                = -333,   /* psk key error  */
-    ZLIB_INIT_ERROR              = -334,   /* zlib init error  */
-    ZLIB_COMPRESS_ERROR          = -335,   /* zlib compression error  */
-    ZLIB_DECOMPRESS_ERROR        = -336,   /* zlib decompression error  */
-
-    GETTIME_ERROR                = -337,   /* gettimeofday failed ??? */
-    GETITIMER_ERROR              = -338,   /* getitimer failed ??? */
-    SIGACT_ERROR                 = -339,   /* sigaction failed ??? */
-    SETITIMER_ERROR              = -340,   /* setitimer failed ??? */
-    LENGTH_ERROR                 = -341,   /* record layer length error */
-    PEER_KEY_ERROR               = -342,   /* can't decode peer key */
-    ZERO_RETURN                  = -343,   /* peer sent close notify */
-    SIDE_ERROR                   = -344,   /* wrong client/server type */
-    NO_PEER_CERT                 = -345,   /* peer didn't send key */
-    NTRU_KEY_ERROR               = -346,   /* NTRU key error  */
-    NTRU_DRBG_ERROR              = -347,   /* NTRU drbg error  */
-    NTRU_ENCRYPT_ERROR           = -348,   /* NTRU encrypt error  */
-    NTRU_DECRYPT_ERROR           = -349,   /* NTRU decrypt error  */
-    ECC_CURVETYPE_ERROR          = -350,   /* Bad ECC Curve Type */
-    ECC_CURVE_ERROR              = -351,   /* Bad ECC Curve */
-    ECC_PEERKEY_ERROR            = -352,   /* Bad Peer ECC Key */
-    ECC_MAKEKEY_ERROR            = -353,   /* Bad Make ECC Key */
-    ECC_EXPORT_ERROR             = -354,   /* Bad ECC Export Key */
-    ECC_SHARED_ERROR             = -355,   /* Bad ECC Shared Secret */
-    NOT_CA_ERROR                 = -357,   /* Not a CA cert error */
-
-    BAD_CERT_MANAGER_ERROR       = -359,   /* Bad Cert Manager */
-    OCSP_CERT_REVOKED            = -360,   /* OCSP Certificate revoked */
-    CRL_CERT_REVOKED             = -361,   /* CRL Certificate revoked */
-    CRL_MISSING                  = -362,   /* CRL Not loaded */
-    MONITOR_SETUP_E              = -363,   /* CRL Monitor setup error */
-    THREAD_CREATE_E              = -364,   /* Thread Create Error */
-    OCSP_NEED_URL                = -365,   /* OCSP need an URL for lookup */
-    OCSP_CERT_UNKNOWN            = -366,   /* OCSP responder doesn't know */
-    OCSP_LOOKUP_FAIL             = -367,   /* OCSP lookup not successful */
-    MAX_CHAIN_ERROR              = -368,   /* max chain depth exceeded */
-    COOKIE_ERROR                 = -369,   /* dtls cookie error */
-    SEQUENCE_ERROR               = -370,   /* dtls sequence error */
-    SUITES_ERROR                 = -371,   /* suites pointer error */
-
-    OUT_OF_ORDER_E               = -373,   /* out of order message */
-    BAD_KEA_TYPE_E               = -374,   /* bad KEA type found */
-    SANITY_CIPHER_E              = -375,   /* sanity check on cipher error */
-    RECV_OVERFLOW_E              = -376,   /* RXCB returned more than rqed */
-    GEN_COOKIE_E                 = -377,   /* Generate Cookie Error */
-    NO_PEER_VERIFY               = -378,   /* Need peer cert verify Error */
-    FWRITE_ERROR                 = -379,   /* fwrite problem */
-    CACHE_MATCH_ERROR            = -380,   /* chache hdr match error */
-    UNKNOWN_SNI_HOST_NAME_E      = -381,   /* Unrecognized host name Error */
-    UNKNOWN_MAX_FRAG_LEN_E       = -382,   /* Unrecognized max frag len Error */
-    KEYUSE_SIGNATURE_E           = -383,   /* KeyUse digSignature error */
-    KEYUSE_ENCIPHER_E            = -385,   /* KeyUse keyEncipher error */
-    EXTKEYUSE_AUTH_E             = -386,   /* ExtKeyUse server|client_auth */
-    SEND_OOB_READ_E              = -387,   /* Send Cb out of bounds read */
-    SECURE_RENEGOTIATION_E       = -388,   /* Invalid Renegotiation Info */
-    SESSION_TICKET_LEN_E         = -389,   /* Session Ticket too large */
-    SESSION_TICKET_EXPECT_E      = -390,   /* Session Ticket missing   */
-    SCR_DIFFERENT_CERT_E         = -391,   /* SCR Different cert error  */
-    SESSION_SECRET_CB_E          = -392,   /* Session secret Cb fcn failure */
-    NO_CHANGE_CIPHER_E           = -393,   /* Finished before change cipher */
-    SANITY_MSG_E                 = -394,   /* Sanity check on msg order error */
-    DUPLICATE_MSG_E              = -395,   /* Duplicate message error */
-    SNI_UNSUPPORTED              = -396,   /* SSL 3.0 does not support SNI */
-    SOCKET_PEER_CLOSED_E         = -397,   /* Underlying transport closed */
-
-    BAD_TICKET_KEY_CB_SZ         = -398,   /* Bad session ticket key cb size */
-    BAD_TICKET_MSG_SZ            = -399,   /* Bad session ticket msg size    */
-    BAD_TICKET_ENCRYPT           = -400,   /* Bad user ticket encrypt        */
-
-    DH_KEY_SIZE_E                = -401,   /* DH Key too small */
-    SNI_ABSENT_ERROR             = -402,   /* No SNI request. */
-    RSA_SIGN_FAULT               = -403,   /* RSA Sign fault */
-    HANDSHAKE_SIZE_ERROR         = -404,   /* Handshake message too large */
-
-    UNKNOWN_ALPN_PROTOCOL_NAME_E = -405,   /* Unrecognized protocol name Error*/
-    BAD_CERTIFICATE_STATUS_ERROR = -406,   /* Bad certificate status message */
-    OCSP_INVALID_STATUS          = -407,   /* Invalid OCSP Status */
-    OCSP_WANT_READ               = -408,   /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */
-    RSA_KEY_SIZE_E               = -409,   /* RSA key too small */
-    ECC_KEY_SIZE_E               = -410,   /* ECC key too small */
-
-    DTLS_EXPORT_VER_E            = -411,   /* export version error */
-    INPUT_SIZE_E                 = -412,   /* input size too big error */
-    CTX_INIT_MUTEX_E             = -413,   /* initialize ctx mutex error */
-    EXT_MASTER_SECRET_NEEDED_E   = -414,   /* need EMS enabled to resume */
-    DTLS_POOL_SZ_E               = -415,   /* exceeded DTLS pool size */
-    DECODE_E                     = -416,   /* decode handshake message error */
-    HTTP_TIMEOUT                 = -417,   /* HTTP timeout for OCSP or CRL req */
-    WRITE_DUP_READ_E             = -418,   /* Write dup write side can't read */
-    WRITE_DUP_WRITE_E            = -419,   /* Write dup read side can't write */
-    INVALID_CERT_CTX_E           = -420,   /* TLS cert ctx not matching */
-    BAD_KEY_SHARE_DATA           = -421,   /* Key Share data invalid */
-    MISSING_HANDSHAKE_DATA       = -422,   /* Handshake message missing data */
-    BAD_BINDER                   = -423,   /* Binder does not match */
-    EXT_NOT_ALLOWED              = -424,   /* Extension not allowed in msg */
-    INVALID_PARAMETER            = -425,   /* Security parameter invalid */
-    MCAST_HIGHWATER_CB_E         = -426,   /* Multicast highwater cb err */
-    ALERT_COUNT_E                = -427,   /* Alert Count exceeded err */
-    EXT_MISSING                  = -428,   /* Required extension not found */
-    UNSUPPORTED_EXTENSION        = -429,   /* TLSX not requested by client */
-    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
-
-    /* begin negotiation parameter errors */
-    UNSUPPORTED_SUITE            = -500,   /* unsupported cipher suite */
-    MATCH_SUITE_ERROR            = -501,   /* can't match cipher suite */
-    COMPRESSION_ERROR            = -502,   /* compression mismatch */
-    KEY_SHARE_ERROR              = -503,   /* key share mismatch */
-    POST_HAND_AUTH_ERROR         = -504,   /* client won't do post-hand auth */
-    HRR_COOKIE_ERROR             = -505    /* HRR msg cookie mismatch */
-    /* end negotiation parameter errors only 10 for now */
-    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
-
-    /* no error stings go down here, add above negotiation errors !!!! */
-};
-
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-    enum {
-        MIN_PARAM_ERR = UNSUPPORTED_SUITE,
-        MAX_PARAM_ERR = MIN_PARAM_ERR - 10
-    };
-#endif
-
-
-WOLFSSL_LOCAL
-void SetErrorString(int err, char* buff);
-
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-
-#endif /* wolfSSL_ERROR_H */
+/* error-ssl.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLFSSL_ERROR_H
+#define WOLFSSL_ERROR_H
+
+#include <wolfcrypt/error-crypt.h>   /* pull in wolfCrypt errors */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+enum wolfSSL_ErrorCodes {
+    INPUT_CASE_ERROR             = -301,   /* process input state error */
+    PREFIX_ERROR                 = -302,   /* bad index to key rounds  */
+    MEMORY_ERROR                 = -303,   /* out of memory            */
+    VERIFY_FINISHED_ERROR        = -304,   /* verify problem on finished */
+    VERIFY_MAC_ERROR             = -305,   /* verify mac problem       */
+    PARSE_ERROR                  = -306,   /* parse error on header    */
+    UNKNOWN_HANDSHAKE_TYPE       = -307,   /* weird handshake type     */
+    SOCKET_ERROR_E               = -308,   /* error state on socket    */
+    SOCKET_NODATA                = -309,   /* expected data, not there */
+    INCOMPLETE_DATA              = -310,   /* don't have enough data to
+                                              complete task            */
+    UNKNOWN_RECORD_TYPE          = -311,   /* unknown type in record hdr */
+    DECRYPT_ERROR                = -312,   /* error during decryption  */
+    FATAL_ERROR                  = -313,   /* recvd alert fatal error  */
+    ENCRYPT_ERROR                = -314,   /* error during encryption  */
+    FREAD_ERROR                  = -315,   /* fread problem            */
+    NO_PEER_KEY                  = -316,   /* need peer's key          */
+    NO_PRIVATE_KEY               = -317,   /* need the private key     */
+    RSA_PRIVATE_ERROR            = -318,   /* error during rsa priv op */
+    NO_DH_PARAMS                 = -319,   /* server missing DH params */
+    BUILD_MSG_ERROR              = -320,   /* build message failure    */
+
+    BAD_HELLO                    = -321,   /* client hello malformed   */
+    DOMAIN_NAME_MISMATCH         = -322,   /* peer subject name mismatch */
+    WANT_READ                    = -323,   /* want read, call again    */
+    NOT_READY_ERROR              = -324,   /* handshake layer not ready */
+
+    VERSION_ERROR                = -326,   /* record layer version error */
+    WANT_WRITE                   = -327,   /* want write, call again   */
+    BUFFER_ERROR                 = -328,   /* malformed buffer input   */
+    VERIFY_CERT_ERROR            = -329,   /* verify cert error        */
+    VERIFY_SIGN_ERROR            = -330,   /* verify sign error        */
+    CLIENT_ID_ERROR              = -331,   /* psk client identity error  */
+    SERVER_HINT_ERROR            = -332,   /* psk server hint error  */
+    PSK_KEY_ERROR                = -333,   /* psk key error  */
+    ZLIB_INIT_ERROR              = -334,   /* zlib init error  */
+    ZLIB_COMPRESS_ERROR          = -335,   /* zlib compression error  */
+    ZLIB_DECOMPRESS_ERROR        = -336,   /* zlib decompression error  */
+
+    GETTIME_ERROR                = -337,   /* gettimeofday failed ??? */
+    GETITIMER_ERROR              = -338,   /* getitimer failed ??? */
+    SIGACT_ERROR                 = -339,   /* sigaction failed ??? */
+    SETITIMER_ERROR              = -340,   /* setitimer failed ??? */
+    LENGTH_ERROR                 = -341,   /* record layer length error */
+    PEER_KEY_ERROR               = -342,   /* can't decode peer key */
+    ZERO_RETURN                  = -343,   /* peer sent close notify */
+    SIDE_ERROR                   = -344,   /* wrong client/server type */
+    NO_PEER_CERT                 = -345,   /* peer didn't send key */
+    NTRU_KEY_ERROR               = -346,   /* NTRU key error  */
+    NTRU_DRBG_ERROR              = -347,   /* NTRU drbg error  */
+    NTRU_ENCRYPT_ERROR           = -348,   /* NTRU encrypt error  */
+    NTRU_DECRYPT_ERROR           = -349,   /* NTRU decrypt error  */
+    ECC_CURVETYPE_ERROR          = -350,   /* Bad ECC Curve Type */
+    ECC_CURVE_ERROR              = -351,   /* Bad ECC Curve */
+    ECC_PEERKEY_ERROR            = -352,   /* Bad Peer ECC Key */
+    ECC_MAKEKEY_ERROR            = -353,   /* Bad Make ECC Key */
+    ECC_EXPORT_ERROR             = -354,   /* Bad ECC Export Key */
+    ECC_SHARED_ERROR             = -355,   /* Bad ECC Shared Secret */
+    NOT_CA_ERROR                 = -357,   /* Not a CA cert error */
 
+    BAD_CERT_MANAGER_ERROR       = -359,   /* Bad Cert Manager */
+    OCSP_CERT_REVOKED            = -360,   /* OCSP Certificate revoked */
+    CRL_CERT_REVOKED             = -361,   /* CRL Certificate revoked */
+    CRL_MISSING                  = -362,   /* CRL Not loaded */
+    MONITOR_SETUP_E              = -363,   /* CRL Monitor setup error */
+    THREAD_CREATE_E              = -364,   /* Thread Create Error */
+    OCSP_NEED_URL                = -365,   /* OCSP need an URL for lookup */
+    OCSP_CERT_UNKNOWN            = -366,   /* OCSP responder doesn't know */
+    OCSP_LOOKUP_FAIL             = -367,   /* OCSP lookup not successful */
+    MAX_CHAIN_ERROR              = -368,   /* max chain depth exceeded */
+    COOKIE_ERROR                 = -369,   /* dtls cookie error */
+    SEQUENCE_ERROR               = -370,   /* dtls sequence error */
+    SUITES_ERROR                 = -371,   /* suites pointer error */
+
+    OUT_OF_ORDER_E               = -373,   /* out of order message */
+    BAD_KEA_TYPE_E               = -374,   /* bad KEA type found */
+    SANITY_CIPHER_E              = -375,   /* sanity check on cipher error */
+    RECV_OVERFLOW_E              = -376,   /* RXCB returned more than rqed */
+    GEN_COOKIE_E                 = -377,   /* Generate Cookie Error */
+    NO_PEER_VERIFY               = -378,   /* Need peer cert verify Error */
+    FWRITE_ERROR                 = -379,   /* fwrite problem */
+    CACHE_MATCH_ERROR            = -380,   /* chache hdr match error */
+    UNKNOWN_SNI_HOST_NAME_E      = -381,   /* Unrecognized host name Error */
+    UNKNOWN_MAX_FRAG_LEN_E       = -382,   /* Unrecognized max frag len Error */
+    KEYUSE_SIGNATURE_E           = -383,   /* KeyUse digSignature error */
+    KEYUSE_ENCIPHER_E            = -385,   /* KeyUse keyEncipher error */
+    EXTKEYUSE_AUTH_E             = -386,   /* ExtKeyUse server|client_auth */
+    SEND_OOB_READ_E              = -387,   /* Send Cb out of bounds read */
+    SECURE_RENEGOTIATION_E       = -388,   /* Invalid Renegotiation Info */
+    SESSION_TICKET_LEN_E         = -389,   /* Session Ticket too large */
+    SESSION_TICKET_EXPECT_E      = -390,   /* Session Ticket missing   */
+    SCR_DIFFERENT_CERT_E         = -391,   /* SCR Different cert error  */
+    SESSION_SECRET_CB_E          = -392,   /* Session secret Cb fcn failure */
+    NO_CHANGE_CIPHER_E           = -393,   /* Finished before change cipher */
+    SANITY_MSG_E                 = -394,   /* Sanity check on msg order error */
+    DUPLICATE_MSG_E              = -395,   /* Duplicate message error */
+    SNI_UNSUPPORTED              = -396,   /* SSL 3.0 does not support SNI */
+    SOCKET_PEER_CLOSED_E         = -397,   /* Underlying transport closed */
+
+    BAD_TICKET_KEY_CB_SZ         = -398,   /* Bad session ticket key cb size */
+    BAD_TICKET_MSG_SZ            = -399,   /* Bad session ticket msg size    */
+    BAD_TICKET_ENCRYPT           = -400,   /* Bad user ticket encrypt        */
+
+    DH_KEY_SIZE_E                = -401,   /* DH Key too small */
+    SNI_ABSENT_ERROR             = -402,   /* No SNI request. */
+    RSA_SIGN_FAULT               = -403,   /* RSA Sign fault */
+    HANDSHAKE_SIZE_ERROR         = -404,   /* Handshake message too large */
+
+    UNKNOWN_ALPN_PROTOCOL_NAME_E = -405,   /* Unrecognized protocol name Error*/
+    BAD_CERTIFICATE_STATUS_ERROR = -406,   /* Bad certificate status message */
+    OCSP_INVALID_STATUS          = -407,   /* Invalid OCSP Status */
+    OCSP_WANT_READ               = -408,   /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */
+    RSA_KEY_SIZE_E               = -409,   /* RSA key too small */
+    ECC_KEY_SIZE_E               = -410,   /* ECC key too small */
+
+    DTLS_EXPORT_VER_E            = -411,   /* export version error */
+    INPUT_SIZE_E                 = -412,   /* input size too big error */
+    CTX_INIT_MUTEX_E             = -413,   /* initialize ctx mutex error */
+    EXT_MASTER_SECRET_NEEDED_E   = -414,   /* need EMS enabled to resume */
+    DTLS_POOL_SZ_E               = -415,   /* exceeded DTLS pool size */
+    DECODE_E                     = -416,   /* decode handshake message error */
+    HTTP_TIMEOUT                 = -417,   /* HTTP timeout for OCSP or CRL req */
+    WRITE_DUP_READ_E             = -418,   /* Write dup write side can't read */
+    WRITE_DUP_WRITE_E            = -419,   /* Write dup read side can't write */
+    INVALID_CERT_CTX_E           = -420,   /* TLS cert ctx not matching */
+    BAD_KEY_SHARE_DATA           = -421,   /* Key Share data invalid */
+    MISSING_HANDSHAKE_DATA       = -422,   /* Handshake message missing data */
+    BAD_BINDER                   = -423,   /* Binder does not match */
+    EXT_NOT_ALLOWED              = -424,   /* Extension not allowed in msg */
+    INVALID_PARAMETER            = -425,   /* Security parameter invalid */
+    MCAST_HIGHWATER_CB_E         = -426,   /* Multicast highwater cb err */
+    ALERT_COUNT_E                = -427,   /* Alert Count exceeded err */
+    EXT_MISSING                  = -428,   /* Required extension not found */
+    UNSUPPORTED_EXTENSION        = -429,   /* TLSX not requested by client */
+    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
+
+    /* begin negotiation parameter errors */
+    UNSUPPORTED_SUITE            = -500,   /* unsupported cipher suite */
+    MATCH_SUITE_ERROR            = -501,   /* can't match cipher suite */
+    COMPRESSION_ERROR            = -502,   /* compression mismatch */
+    KEY_SHARE_ERROR              = -503,   /* key share mismatch */
+    POST_HAND_AUTH_ERROR         = -504,   /* client won't do post-hand auth */
+    HRR_COOKIE_ERROR             = -505    /* HRR msg cookie mismatch */
+    /* end negotiation parameter errors only 10 for now */
+    /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
+
+    /* no error stings go down here, add above negotiation errors !!!! */
+};
+
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    enum {
+        MIN_PARAM_ERR = UNSUPPORTED_SUITE,
+        MAX_PARAM_ERR = MIN_PARAM_ERR - 10
+    };
+#endif
+
+
+WOLFSSL_LOCAL
+void SetErrorString(int err, char* buff);
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* wolfSSL_ERROR_H */
+
--- a/wolfssl/internal.h	Tue Nov 19 14:32:16 2019 +0000
+++ b/wolfssl/internal.h	Wed Nov 20 13:27:48 2019 +0000
@@ -1,4174 +1,4174 @@
-/* internal.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLFSSL_INT_H
-#define WOLFSSL_INT_H
-
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/ssl.h>
-#ifdef HAVE_CRL
-    #include <wolfssl/crl.h>
-#endif
-#include <wolfssl/wolfcrypt/random.h>
-#ifndef NO_DES3
-    #include <wolfssl/wolfcrypt/des3.h>
-#endif
-#ifndef NO_HC128
-    #include <wolfssl/wolfcrypt/hc128.h>
-#endif
-#ifndef NO_RABBIT
-    #include <wolfssl/wolfcrypt/rabbit.h>
-#endif
-#ifdef HAVE_CHACHA
-    #include <wolfssl/wolfcrypt/chacha.h>
-#endif
-#ifndef NO_ASN
-    #include <wolfssl/wolfcrypt/asn.h>
-    #include <wolfssl/wolfcrypt/pkcs12.h>
-#endif
-#ifndef NO_MD5
-    #include <wolfssl/wolfcrypt/md5.h>
-#endif
-#ifndef NO_SHA
-    #include <wolfssl/wolfcrypt/sha.h>
-#endif
-#ifndef NO_AES
-    #include <wolfssl/wolfcrypt/aes.h>
-#endif
-#ifdef HAVE_POLY1305
-    #include <wolfssl/wolfcrypt/poly1305.h>
-#endif
-#ifdef HAVE_CAMELLIA
-    #include <wolfssl/wolfcrypt/camellia.h>
-#endif
-#include <wolfssl/wolfcrypt/logging.h>
-#ifndef NO_HMAC
-    #include <wolfssl/wolfcrypt/hmac.h>
-#endif
-#ifndef NO_RC4
-    #include <wolfssl/wolfcrypt/arc4.h>
-#endif
-#ifndef NO_SHA256
-    #include <wolfssl/wolfcrypt/sha256.h>
-#endif
-#ifdef HAVE_OCSP
-    #include <wolfssl/ocsp.h>
-#endif
-#ifdef WOLFSSL_SHA384
-    #include <wolfssl/wolfcrypt/sha512.h>
-#endif
-#ifdef WOLFSSL_SHA512
-    #include <wolfssl/wolfcrypt/sha512.h>
-#endif
-#ifdef HAVE_AESGCM
-    #include <wolfssl/wolfcrypt/sha512.h>
-#endif
-#ifdef WOLFSSL_RIPEMD
-    #include <wolfssl/wolfcrypt/ripemd.h>
-#endif
-#ifdef HAVE_IDEA
-    #include <wolfssl/wolfcrypt/idea.h>
-#endif
-#ifndef NO_RSA
-    #include <wolfssl/wolfcrypt/rsa.h>
-#endif
-#ifdef HAVE_ECC
-    #include <wolfssl/wolfcrypt/ecc.h>
-#endif
-#ifndef NO_DH
-    #include <wolfssl/wolfcrypt/dh.h>
-#endif
-#ifdef HAVE_ED25519
-    #include <wolfssl/wolfcrypt/ed25519.h>
-#endif
-#ifdef HAVE_CURVE25519
-    #include <wolfssl/wolfcrypt/curve25519.h>
-#endif
-
-#include <wolfssl/wolfcrypt/wc_encrypt.h>
-#include <wolfssl/wolfcrypt/hash.h>
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-    #include <wolfssl/callbacks.h>
-#endif
-#ifdef WOLFSSL_CALLBACKS
-    #include <signal.h>
-#endif
-
-#ifdef USE_WINDOWS_API
-    #ifdef WOLFSSL_GAME_BUILD
-        #include "system/xtl.h"
-    #else
-        #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN)
-            /* On WinCE winsock2.h must be included before windows.h */
-            #include <winsock2.h>
-        #endif
-        #include <windows.h>
-    #endif
-#elif defined(THREADX)
-    #ifndef SINGLE_THREADED
-        #include "tx_api.h"
-    #endif
-#elif defined(MICRIUM)
-    /* do nothing, just don't pick Unix */
-#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS)
-    /* do nothing */
-#elif defined(EBSNET)
-    /* do nothing */
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    /* do nothing */
-#elif defined(FREESCALE_FREE_RTOS)
-    #include "fsl_os_abstraction.h"
-#elif defined(WOLFSSL_uITRON4)
-        /* do nothing */
-#elif defined(WOLFSSL_uTKERNEL2)
-        /* do nothing */
-#elif defined(WOLFSSL_CMSIS_RTOS)
-    #include "cmsis_os.h"
-#elif defined(WOLFSSL_MDK_ARM)
-    #if defined(WOLFSSL_MDK5)
-         #include "cmsis_os.h"
-    #else
-        #include <rtl.h>
-    #endif
-#elif defined(WOLFSSL_CMSIS_RTOS)
-    #include "cmsis_os.h"
-#elif defined(MBED)
-#elif defined(WOLFSSL_TIRTOS)
-    /* do nothing */
-#elif defined(INTIME_RTOS)
-    #include <rt.h>
-#elif defined(WOLFSSL_NUCLEUS_1_2)
-    /* do nothing */
-#else
-    #ifndef SINGLE_THREADED
-        #define WOLFSSL_PTHREADS
-        #include <pthread.h>
-    #endif
-    #ifdef OPENSSL_EXTRA
-        #include <unistd.h>      /* for close of BIO */
-    #endif
-#endif
-
-#ifndef CHAR_BIT
-    /* Needed for DTLS without big math */
-    #include <limits.h>
-#endif
-
-
-#ifdef HAVE_LIBZ
-    #include "zlib.h"
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifdef OPENSSL_EXTRA
-    #ifdef WOLFCRYPT_HAVE_SRP
-        #include <wolfssl/wolfcrypt/srp.h>
-    #endif
-#endif
-
-#ifdef _MSC_VER
-    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
-    #pragma warning(disable: 4996)
-#endif
-
-#ifdef NO_SHA
-    #define WC_SHA_DIGEST_SIZE 20
-#endif
-
-#ifdef NO_SHA256
-    #define WC_SHA256_DIGEST_SIZE 32
-#endif
-
-#ifdef NO_MD5
-    #define WC_MD5_DIGEST_SIZE 16
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Define or comment out the cipher suites you'd like to be compiled in
-   make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined
-
-   When adding cipher suites, add name to cipher_names, idx to cipher_name_idx
-
-   Now that there is a maximum strength crypto build, the following BUILD_XXX
-   flags need to be divided into two groups selected by WOLFSSL_MAX_STRENGTH.
-   Those that do not use Perfect Forward Security and do not use AEAD ciphers
-   need to be switched off. Allowed suites use (EC)DHE, AES-GCM|CCM, or
-   CHACHA-POLY.
-*/
-
-/* Check that if WOLFSSL_MAX_STRENGTH is set that all the required options are
- * not turned off. */
-#if defined(WOLFSSL_MAX_STRENGTH) && \
-    ((!defined(HAVE_ECC) && (defined(NO_DH) || defined(NO_RSA))) || \
-     (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM) && \
-      (!defined(HAVE_POLY1305) || !defined(HAVE_CHACHA))) || \
-     (defined(NO_SHA256) && !defined(WOLFSSL_SHA384)) || \
-     !defined(NO_OLD_TLS))
-
-    #error "You are trying to build max strength with requirements disabled."
-#endif
-
-/* Have QSH : Quantum-safe Handshake */
-#if defined(HAVE_QSH)
-    #define BUILD_TLS_QSH
-#endif
-
-#ifndef WOLFSSL_MAX_STRENGTH
-
-    #if !defined(NO_RSA) && !defined(NO_RC4)
-        #if defined(WOLFSSL_STATIC_RSA)
-            #if !defined(NO_SHA)
-                #define BUILD_SSL_RSA_WITH_RC4_128_SHA
-            #endif
-            #if !defined(NO_MD5)
-                #define BUILD_SSL_RSA_WITH_RC4_128_MD5
-            #endif
-        #endif
-        #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) \
-            && defined(WOLFSSL_STATIC_RSA)
-            #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
-        #endif
-    #endif
-
-    #if !defined(NO_RSA) && !defined(NO_DES3)
-        #if !defined(NO_SHA)
-            #if defined(WOLFSSL_STATIC_RSA)
-                #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
-            #endif
-            #if !defined(NO_TLS) && defined(HAVE_NTRU) \
-                && defined(WOLFSSL_STATIC_RSA)
-                    #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
-            #endif
-        #endif
-    #endif
-
-    #if !defined(NO_RSA) && defined(HAVE_IDEA)
-        #if !defined(NO_SHA) && defined(WOLFSSL_STATIC_RSA)
-            #define BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
-        #endif
-    #endif
-
-    #if !defined(NO_RSA) && !defined(NO_AES) && !defined(NO_TLS)
-        #if !defined(NO_SHA)
-            #if defined(WOLFSSL_STATIC_RSA)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
-                #endif
-            #endif
-            #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
-                #endif
-            #endif
-        #endif
-        #if defined(WOLFSSL_STATIC_RSA)
-            #if !defined (NO_SHA256)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
-                #endif
-            #endif
-            #if defined (HAVE_AESGCM)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
-                #endif
-                #if defined (WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-                    #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
-                #endif
-            #endif
-            #if defined (HAVE_AESCCM)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_RSA_WITH_AES_128_CCM_8
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_RSA_WITH_AES_256_CCM_8
-                #endif
-            #endif
-            #if defined(HAVE_BLAKE2)
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
-                #endif
-            #endif
-        #endif
-    #endif
-
-    #if defined(HAVE_CAMELLIA) && !defined(NO_TLS)
-        #ifndef NO_RSA
-          #if defined(WOLFSSL_STATIC_RSA)
-            #if !defined(NO_SHA)
-                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
-                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
-            #endif
-            #ifndef NO_SHA256
-                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
-                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
-            #endif
-          #endif
-            #if !defined(NO_DH)
-              #if !defined(NO_SHA)
-                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
-                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
-              #endif
-                #ifndef NO_SHA256
-                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
-                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
-                #endif
-            #endif
-        #endif
-    #endif
-
-#if defined(WOLFSSL_STATIC_PSK)
-    #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS)
-        #if !defined(NO_SHA)
-            #ifdef WOLFSSL_AES_128
-                #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
-            #endif
-            #ifdef WOLFSSL_AES_256
-                #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
-            #endif
-        #endif
-        #ifndef NO_SHA256
-            #ifdef WOLFSSL_AES_128
-            #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
-            #ifdef HAVE_AESGCM
-                #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
-            #endif
-            #endif /* WOLFSSL_AES_128 */
-            #ifdef HAVE_AESCCM
-                #ifdef WOLFSSL_AES_128
-                    #define BUILD_TLS_PSK_WITH_AES_128_CCM_8
-                    #define BUILD_TLS_PSK_WITH_AES_128_CCM
-                #endif
-                #ifdef WOLFSSL_AES_256
-                    #define BUILD_TLS_PSK_WITH_AES_256_CCM_8
-                    #define BUILD_TLS_PSK_WITH_AES_256_CCM
-                #endif
-            #endif
-        #endif
-        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-            #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
-            #ifdef HAVE_AESGCM
-                #define BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
-            #endif
-        #endif
-    #endif
-#endif
-
-    #if !defined(NO_TLS) && defined(HAVE_NULL_CIPHER)
-        #if !defined(NO_RSA)
-            #if defined(WOLFSSL_STATIC_RSA)
-                #if !defined(NO_SHA)
-                    #define BUILD_TLS_RSA_WITH_NULL_SHA
-                #endif
-                #ifndef NO_SHA256
-                    #define BUILD_TLS_RSA_WITH_NULL_SHA256
-                #endif
-            #endif
-        #endif
-        #if !defined(NO_PSK) && defined(WOLFSSL_STATIC_PSK)
-            #if !defined(NO_SHA)
-                #define BUILD_TLS_PSK_WITH_NULL_SHA
-            #endif
-            #ifndef NO_SHA256
-                #define BUILD_TLS_PSK_WITH_NULL_SHA256
-            #endif
-            #ifdef WOLFSSL_SHA384
-                #define BUILD_TLS_PSK_WITH_NULL_SHA384
-            #endif
-        #endif
-    #endif
-
-#if defined(WOLFSSL_STATIC_RSA)
-    #if !defined(NO_HC128) && !defined(NO_RSA) && !defined(NO_TLS)
-        #ifndef NO_MD5
-            #define BUILD_TLS_RSA_WITH_HC_128_MD5
-        #endif
-        #if !defined(NO_SHA)
-            #define BUILD_TLS_RSA_WITH_HC_128_SHA
-        #endif
-        #if defined(HAVE_BLAKE2)
-            #define BUILD_TLS_RSA_WITH_HC_128_B2B256
-        #endif
-    #endif
-
-    #if !defined(NO_RABBIT) && !defined(NO_TLS) && !defined(NO_RSA)
-        #if !defined(NO_SHA)
-            #define BUILD_TLS_RSA_WITH_RABBIT_SHA
-        #endif
-    #endif
-#endif
-
-    #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
-        !defined(NO_RSA)
-
-        #if !defined(NO_SHA)
-            #ifdef WOLFSSL_AES_128
-                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-            #endif
-            #ifdef WOLFSSL_AES_256
-                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-            #endif
-            #if !defined(NO_DES3)
-                #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-            #endif
-        #endif
-        #if !defined(NO_SHA256) && defined(HAVE_AES_CBC)
-            #ifdef WOLFSSL_AES_128
-                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-            #endif
-            #ifdef WOLFSSL_AES_256
-                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
-            #endif
-        #endif
-    #endif
-
-    #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \
-        !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128)
-        #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
-
-        #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM)
-            #define BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
-        #endif
-    #endif
-
-    #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
-        #ifndef NO_SHA256
-            #if !defined(NO_AES) && defined(WOLFSSL_AES_128)
-                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
-            #endif
-            #ifdef HAVE_NULL_CIPHER
-                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
-            #endif
-        #endif
-        #ifdef WOLFSSL_SHA384
-            #if !defined(NO_AES) && defined(WOLFSSL_AES_256)
-                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
-            #endif
-            #ifdef HAVE_NULL_CIPHER
-                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
-            #endif
-        #endif
-    #endif
-
-    #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS)
-        #if !defined(NO_AES)
-            #if !defined(NO_SHA)
-                #if !defined(NO_RSA)
-                    #ifdef WOLFSSL_AES_128
-                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
-                    #endif
-                    #ifdef WOLFSSL_AES_256
-                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
-                    #endif
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #ifdef WOLFSSL_AES_128
-                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
-                        #endif
-                        #ifdef WOLFSSL_AES_256
-                            #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
-                        #endif
-                    #endif
-                #endif
-
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #ifdef WOLFSSL_AES_128
-                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
-                    #endif
-                    #ifdef WOLFSSL_AES_256
-                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
-                    #endif
-                #endif
-
-                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                    #ifdef WOLFSSL_AES_128
-                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
-                    #endif
-                    #ifdef WOLFSSL_AES_256
-                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
-                    #endif
-                #endif
-            #endif /* NO_SHA */
-            #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
-                #if !defined(NO_RSA)
-                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
-                    #endif
-                #endif
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
-                #endif
-                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
-                #endif
-            #endif
-
-            #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-                #if !defined(NO_RSA)
-                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
-                    #endif
-                #endif
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
-                #endif
-                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
-                #endif
-            #endif
-
-            #if defined (HAVE_AESGCM)
-                #if !defined(NO_RSA)
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #ifdef WOLFSSL_AES_128
-                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
-                        #endif
-                    #endif
-                    #if defined(WOLFSSL_SHA384)
-                        #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                            #ifdef WOLFSSL_AES_256
-                                #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
-                            #endif
-                        #endif
-                    #endif
-                #endif
-
-                #if defined(WOLFSSL_STATIC_DH) && defined(WOLFSSL_AES_128) && \
-                                                               defined(HAVE_ECC)
-                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
-                #endif
-
-                #if defined(WOLFSSL_SHA384)
-                    #if defined(WOLFSSL_STATIC_DH) && \
-                                   defined(WOLFSSL_AES_256) && defined(HAVE_ECC)
-                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
-                    #endif
-                #endif
-            #endif
-        #endif /* NO_AES */
-        #if !defined(NO_RC4)
-            #if !defined(NO_SHA)
-                #if !defined(NO_RSA)
-                    #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
-                    #endif
-                #endif
-
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
-                #endif
-                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                    #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
-                #endif
-            #endif
-        #endif
-        #if !defined(NO_DES3)
-            #ifndef NO_SHA
-                #if !defined(NO_RSA)
-                    #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
-                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                        #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
-                    #endif
-                #endif
-
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
-                #endif
-                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
-                    #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
-                #endif
-            #endif /* NO_SHA */
-        #endif
-        #if defined(HAVE_NULL_CIPHER)
-            #if !defined(NO_SHA)
-                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                    #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
-                #endif
-            #endif
-            #if !defined(NO_PSK) && !defined(NO_SHA256)
-                #define BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
-            #endif
-        #endif
-        #if !defined(NO_PSK) && !defined(NO_SHA256) && !defined(NO_AES) && \
-            defined(WOLFSSL_AES_128)
-            #define BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
-        #endif
-    #endif
-    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
-        #if !defined(NO_OLD_POLY1305)
-        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-        #endif
-        #ifndef NO_RSA
-            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-        #endif
-        #if !defined(NO_DH) && !defined(NO_RSA)
-            #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
-        #endif
-        #endif /* NO_OLD_POLY1305 */
-        #if !defined(NO_PSK)
-            #define BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
-            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
-                #define BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-            #endif
-            #ifndef NO_DH
-                #define BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
-            #endif
-        #endif /* !NO_PSK */
-    #endif
-
-#endif /* !WOLFSSL_MAX_STRENGTH */
-
-#if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
-    !defined(NO_RSA) && defined(HAVE_AESGCM)
-
-    #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
-        #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
-    #endif
-
-    #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-        #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
-    #endif
-#endif
-
-#if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
-    #ifndef NO_SHA256
-        #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128)
-            #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
-        #endif
-        #ifdef HAVE_AESCCM
-            #ifdef WOLFSSL_AES_128
-                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
-            #endif
-            #ifdef WOLFSSL_AES_256
-                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
-            #endif
-        #endif
-    #endif
-    #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) && \
-        defined(WOLFSSL_AES_256)
-        #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
-    #endif
-#endif
-
-#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS) && \
-                                                                !defined(NO_AES)
-    #ifdef HAVE_AESGCM
-        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
-            #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-            #endif
-            #ifndef NO_RSA
-                #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-            #endif
-        #endif
-        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-            #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
-            #endif
-            #ifndef NO_RSA
-                #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-            #endif
-        #endif
-    #endif
-    #if defined(HAVE_AESCCM) && !defined(NO_SHA256)
-        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-            #ifdef WOLFSSL_AES_128
-                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
-                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
-            #endif
-            #ifdef WOLFSSL_AES_256
-                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
-            #endif
-        #endif
-    #endif
-#endif
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
-    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
-                                                          defined(HAVE_ED25519))
-            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-        #endif
-        #ifndef NO_RSA
-            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-        #endif
-    #endif
-    #if !defined(NO_DH) && !defined(NO_RSA)
-        #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-    #endif
-#endif
-
-#if defined(WOLFSSL_TLS13)
-    #ifdef HAVE_AESGCM
-        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
-            #define BUILD_TLS_AES_128_GCM_SHA256
-        #endif
-        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
-            #define BUILD_TLS_AES_256_GCM_SHA384
-        #endif
-    #endif
-
-    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-        #ifndef NO_SHA256
-            #define BUILD_TLS_CHACHA20_POLY1305_SHA256
-        #endif
-    #endif
-
-    #ifdef HAVE_AESCCM
-        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
-            #define BUILD_TLS_AES_128_CCM_SHA256
-            #define BUILD_TLS_AES_128_CCM_8_SHA256
-        #endif
-    #endif
-#endif
-
-#ifdef WOLFSSL_MULTICAST
-    #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256)
-        #define BUILD_WDM_WITH_NULL_SHA256
-    #endif
-#endif
-
-#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \
-    defined(BUILD_SSL_RSA_WITH_RC4_128_MD5)
-    #define BUILD_ARC4
-#endif
-
-#if defined(BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA)
-    #define BUILD_DES3
-#endif
-
-#if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \
-    defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA) || \
-    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) || \
-    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256)
-    #undef  BUILD_AES
-    #define BUILD_AES
-#endif
-
-#if defined(BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256) || \
-    defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \
-    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) || \
-    defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) || \
-    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) || \
-    defined(BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384) || \
-    defined(BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) || \
-    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) || \
-    defined(BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384) || \
-    defined(BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384)
-    #define BUILD_AESGCM
-#else
-    /* No AES-GCM cipher suites available with build */
-    #define NO_AESGCM_AEAD
-#endif
-
-#if defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
-    defined(BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
-    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
-    defined(BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
-    defined(BUILD_TLS_CHACHA20_POLY1305_SHA256)
-    /* Have an available ChaCha Poly cipher suite */
-#else
-    /* No ChaCha Poly cipher suites available with build */
-    #define NO_CHAPOL_AEAD
-#endif
-
-#if defined(BUILD_TLS_RSA_WITH_HC_128_SHA) || \
-    defined(BUILD_TLS_RSA_WITH_HC_128_MD5) || \
-    defined(BUILD_TLS_RSA_WITH_HC_128_B2B256)
-    #define BUILD_HC128
-#endif
-
-#if defined(BUILD_TLS_RSA_WITH_RABBIT_SHA)
-    #define BUILD_RABBIT
-#endif
-
-#ifdef NO_DES3
-    #define DES_BLOCK_SIZE 8
-#else
-    #undef  BUILD_DES3
-    #define BUILD_DES3
-#endif
-
-#if defined(NO_AES) || defined(NO_AES_DECRYPT)
-    #define AES_BLOCK_SIZE 16
-    #undef  BUILD_AES
-#else
-    #undef  BUILD_AES
-    #define BUILD_AES
-#endif
-
-#ifndef NO_RC4
-    #undef  BUILD_ARC4
-    #define BUILD_ARC4
-#endif
-
-#ifdef HAVE_CHACHA
-    #define CHACHA20_BLOCK_SIZE 16
-#endif
-
-#if defined(WOLFSSL_MAX_STRENGTH) || \
-    (defined(HAVE_AESGCM) && !defined(NO_AESGCM_AEAD)) || \
-     defined(HAVE_AESCCM) || \
-    (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_CHAPOL_AEAD))
-
-    #define HAVE_AEAD
-#endif
-
-#if defined(WOLFSSL_MAX_STRENGTH) || \
-    defined(HAVE_ECC) || !defined(NO_DH)
-
-    #define HAVE_PFS
-#endif
-
-#if defined(BUILD_SSL_RSA_WITH_IDEA_CBC_SHA)
-    #define BUILD_IDEA
-#endif
-
-/* actual cipher values, 2nd byte */
-enum {
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16,
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA  = 0x39,
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA  = 0x33,
-    TLS_DH_anon_WITH_AES_128_CBC_SHA  = 0x34,
-    TLS_RSA_WITH_AES_256_CBC_SHA      = 0x35,
-    TLS_RSA_WITH_AES_128_CBC_SHA      = 0x2F,
-    TLS_RSA_WITH_NULL_SHA             = 0x02,
-    TLS_PSK_WITH_AES_256_CBC_SHA      = 0x8d,
-    TLS_PSK_WITH_AES_128_CBC_SHA256   = 0xae,
-    TLS_PSK_WITH_AES_256_CBC_SHA384   = 0xaf,
-    TLS_PSK_WITH_AES_128_CBC_SHA      = 0x8c,
-    TLS_PSK_WITH_NULL_SHA256          = 0xb0,
-    TLS_PSK_WITH_NULL_SHA384          = 0xb1,
-    TLS_PSK_WITH_NULL_SHA             = 0x2c,
-    SSL_RSA_WITH_RC4_128_SHA          = 0x05,
-    SSL_RSA_WITH_RC4_128_MD5          = 0x04,
-    SSL_RSA_WITH_3DES_EDE_CBC_SHA     = 0x0A,
-    SSL_RSA_WITH_IDEA_CBC_SHA         = 0x07,
-
-    /* ECC suites, first byte is 0xC0 (ECC_BYTE) */
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA    = 0x14,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA    = 0x13,
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA  = 0x0A,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA  = 0x09,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA        = 0x11,
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA      = 0x07,
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA   = 0x12,
-    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08,
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256   = 0x27,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x23,
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384   = 0x28,
-    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0x24,
-    TLS_ECDHE_ECDSA_WITH_NULL_SHA           = 0x06,
-    TLS_ECDHE_PSK_WITH_NULL_SHA256          = 0x3a,
-    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256   = 0x37,
-
-    /* static ECDH, first byte is 0xC0 (ECC_BYTE) */
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA    = 0x0F,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA    = 0x0E,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA  = 0x05,
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA  = 0x04,
-    TLS_ECDH_RSA_WITH_RC4_128_SHA        = 0x0C,
-    TLS_ECDH_ECDSA_WITH_RC4_128_SHA      = 0x02,
-    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA   = 0x0D,
-    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x03,
-    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256   = 0x29,
-    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0x25,
-    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384   = 0x2A,
-    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0x26,
-
-    /* wolfSSL extension - eSTREAM */
-    TLS_RSA_WITH_HC_128_MD5       = 0xFB,
-    TLS_RSA_WITH_HC_128_SHA       = 0xFC,
-    TLS_RSA_WITH_RABBIT_SHA       = 0xFD,
-    WDM_WITH_NULL_SHA256          = 0xFE, /* wolfSSL DTLS Multicast */
-
-    /* wolfSSL extension - Blake2b 256 */
-    TLS_RSA_WITH_AES_128_CBC_B2B256   = 0xF8,
-    TLS_RSA_WITH_AES_256_CBC_B2B256   = 0xF9,
-    TLS_RSA_WITH_HC_128_B2B256        = 0xFA,   /* eSTREAM too */
-
-    /* wolfSSL extension - NTRU */
-    TLS_NTRU_RSA_WITH_RC4_128_SHA      = 0xe5,
-    TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0xe6,
-    TLS_NTRU_RSA_WITH_AES_128_CBC_SHA  = 0xe7,  /* clashes w/official SHA-256 */
-    TLS_NTRU_RSA_WITH_AES_256_CBC_SHA  = 0xe8,
-
-    /* wolfSSL extension - NTRU , Quantum-safe Handshake
-       first byte is 0xD0 (QSH_BYTE) */
-    TLS_QSH      = 0x01,
-
-    /* SHA256 */
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b,
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67,
-    TLS_RSA_WITH_AES_256_CBC_SHA256     = 0x3d,
-    TLS_RSA_WITH_AES_128_CBC_SHA256     = 0x3c,
-    TLS_RSA_WITH_NULL_SHA256            = 0x3b,
-    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0xb2,
-    TLS_DHE_PSK_WITH_NULL_SHA256        = 0xb4,
-
-    /* SHA384 */
-    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0xb3,
-    TLS_DHE_PSK_WITH_NULL_SHA384        = 0xb5,
-
-    /* AES-GCM */
-    TLS_RSA_WITH_AES_128_GCM_SHA256          = 0x9c,
-    TLS_RSA_WITH_AES_256_GCM_SHA384          = 0x9d,
-    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      = 0x9e,
-    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      = 0x9f,
-    TLS_DH_anon_WITH_AES_256_GCM_SHA384      = 0xa7,
-    TLS_PSK_WITH_AES_128_GCM_SHA256          = 0xa8,
-    TLS_PSK_WITH_AES_256_GCM_SHA384          = 0xa9,
-    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      = 0xaa,
-    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      = 0xab,
-
-    /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */
-    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  = 0x2b,
-    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  = 0x2c,
-    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   = 0x2d,
-    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   = 0x2e,
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    = 0x2f,
-    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    = 0x30,
-    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     = 0x31,
-    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     = 0x32,
-
-    /* AES-CCM, first byte is 0xC0 but isn't ECC,
-     * also, in some of the other AES-CCM suites
-     * there will be second byte number conflicts
-     * with non-ECC AES-GCM */
-    TLS_RSA_WITH_AES_128_CCM_8         = 0xa0,
-    TLS_RSA_WITH_AES_256_CCM_8         = 0xa1,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CCM   = 0xac,
-    TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xae,
-    TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xaf,
-    TLS_PSK_WITH_AES_128_CCM           = 0xa4,
-    TLS_PSK_WITH_AES_256_CCM           = 0xa5,
-    TLS_PSK_WITH_AES_128_CCM_8         = 0xa8,
-    TLS_PSK_WITH_AES_256_CCM_8         = 0xa9,
-    TLS_DHE_PSK_WITH_AES_128_CCM       = 0xa6,
-    TLS_DHE_PSK_WITH_AES_256_CCM       = 0xa7,
-
-    /* Camellia */
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA        = 0x41,
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        = 0x84,
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     = 0xba,
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     = 0xc0,
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA    = 0x45,
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    = 0x88,
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe,
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4,
-
-    /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */
-    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   = 0xa8,
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9,
-    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     = 0xaa,
-    TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   = 0xac,
-    TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         = 0xab,
-    TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     = 0xad,
-
-    /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */
-    TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256   = 0x13,
-    TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14,
-    TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256     = 0x15,
-
-    /* TLS v1.3 cipher suites */
-    TLS_AES_128_GCM_SHA256       = 0x01,
-    TLS_AES_256_GCM_SHA384       = 0x02,
-    TLS_CHACHA20_POLY1305_SHA256 = 0x03,
-    TLS_AES_128_CCM_SHA256       = 0x04,
-    TLS_AES_128_CCM_8_SHA256     = 0x05,
-
-    /* Renegotiation Indication Extension Special Suite */
-    TLS_EMPTY_RENEGOTIATION_INFO_SCSV        = 0xff
-};
-
-
-#ifndef WOLFSSL_SESSION_TIMEOUT
-    #define WOLFSSL_SESSION_TIMEOUT 500
-    /* default session resumption cache timeout in seconds */
-#endif
-
-
-#ifndef WOLFSSL_DTLS_WINDOW_WORDS
-    #define WOLFSSL_DTLS_WINDOW_WORDS 2
-#endif /* WOLFSSL_DTLS_WINDOW_WORDS */
-#define DTLS_WORD_BITS (sizeof(word32) * CHAR_BIT)
-#define DTLS_SEQ_BITS  (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS)
-#define DTLS_SEQ_SZ    (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS)
-
-#ifndef WOLFSSL_MULTICAST
-    #define WOLFSSL_DTLS_PEERSEQ_SZ 1
-#else
-    #ifndef WOLFSSL_MULTICAST_PEERS
-        /* max allowed multicast group peers */
-        #define WOLFSSL_MULTICAST_PEERS 100
-    #endif
-    #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS
-#endif /* WOLFSSL_MULTICAST */
-
-#ifndef WOLFSSL_MAX_MTU
-    #define WOLFSSL_MAX_MTU 1500
-#endif /* WOLFSSL_MAX_MTU */
-
-
-/* set minimum DH key size allowed */
-#ifndef WOLFSSL_MIN_DHKEY_BITS
-    #ifdef WOLFSSL_MAX_STRENGTH
-        #define WOLFSSL_MIN_DHKEY_BITS 2048
-    #else
-        #define WOLFSSL_MIN_DHKEY_BITS 1024
-    #endif
-#endif
-#if (WOLFSSL_MIN_DHKEY_BITS % 8)
-    #error DH minimum bit size must be multiple of 8
-#endif
-#if (WOLFSSL_MIN_DHKEY_BITS > 16000)
-    #error DH minimum bit size must not be greater than 16000
-#endif
-#define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8)
-/* set maximum DH key size allowed */
-#ifndef WOLFSSL_MAX_DHKEY_BITS
-    #define WOLFSSL_MAX_DHKEY_BITS 4096
-#endif
-#if (WOLFSSL_MAX_DHKEY_BITS % 8)
-    #error DH maximum bit size must be multiple of 8
-#endif
-#if (WOLFSSL_MAX_DHKEY_BITS > 16000)
-    #error DH maximum bit size must not be greater than 16000
-#endif
-#define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8)
-
-
-
-enum Misc {
-    CIPHER_BYTE = 0x00,            /* Default ciphers */
-    ECC_BYTE    = 0xC0,            /* ECC first cipher suite byte */
-    QSH_BYTE    = 0xD0,            /* Quantum-safe Handshake cipher suite */
-    CHACHA_BYTE = 0xCC,            /* ChaCha first cipher suite */
-    TLS13_BYTE  = 0x13,            /* TLS v1.3 first byte of cipher suite */
-
-    SEND_CERT       = 1,
-    SEND_BLANK_CERT = 2,
-
-    DTLS_MAJOR      = 0xfe,     /* DTLS major version number */
-    DTLS_MINOR      = 0xff,     /* DTLS minor version number */
-    DTLSv1_2_MINOR  = 0xfd,     /* DTLS minor version number */
-    SSLv3_MAJOR     = 3,        /* SSLv3 and TLSv1+  major version number */
-    SSLv3_MINOR     = 0,        /* TLSv1   minor version number */
-    TLSv1_MINOR     = 1,        /* TLSv1   minor version number */
-    TLSv1_1_MINOR   = 2,        /* TLSv1_1 minor version number */
-    TLSv1_2_MINOR   = 3,        /* TLSv1_2 minor version number */
-    TLSv1_3_MINOR   = 4,        /* TLSv1_3 minor version number */
-#ifndef WOLFSSL_TLS13_FINAL
-    TLS_DRAFT_MAJOR = 0x7f,     /* Draft TLS major version number */
-#ifdef WOLFSSL_TLS13_DRAFT_18
-    TLS_DRAFT_MINOR = 0x12,     /* Minor version number of TLS draft */
-#elif defined(WOLFSSL_TLS13_DRAFT_22)
-    TLS_DRAFT_MINOR = 0x16,     /* Minor version number of TLS draft */
-#elif defined(WOLFSSL_TLS13_DRAFT_23)
-    TLS_DRAFT_MINOR = 0x17,     /* Minor version number of TLS draft */
-#elif defined(WOLFSSL_TLS13_DRAFT_26)
-    TLS_DRAFT_MINOR = 0x1a,     /* Minor version number of TLS draft */
-#else
-    TLS_DRAFT_MINOR = 0x1c,     /* Minor version number of TLS draft */
-#endif
-#endif
-    OLD_HELLO_ID    = 0x01,     /* SSLv2 Client Hello Indicator */
-    INVALID_BYTE    = 0xff,     /* Used to initialize cipher specs values */
-    NO_COMPRESSION  =  0,
-    ZLIB_COMPRESSION = 221,     /* wolfSSL zlib compression */
-    HELLO_EXT_SIG_ALGO = 13,    /* ID for the sig_algo hello extension */
-    HELLO_EXT_EXTMS = 0x0017,   /* ID for the extended master secret ext */
-    SECRET_LEN      = WOLFSSL_MAX_MASTER_KEY_LENGTH,
-                                /* pre RSA and all master */
-#if defined(WOLFSSL_MYSQL_COMPATIBLE)
-    ENCRYPT_LEN     = 1024,     /* allow larger static buffer with mysql */
-#else
-    ENCRYPT_LEN     = 512,      /* allow 4096 bit static buffer */
-#endif
-    SIZEOF_SENDER   =  4,       /* clnt or srvr           */
-    FINISHED_SZ     = 36,       /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */
-    MAX_RECORD_SIZE = 16384,    /* 2^14, max size by standard */
-    MAX_MSG_EXTRA   = 38 + WC_MAX_DIGEST_SIZE,
-                                /* max added to msg, mac + pad  from */
-                                /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max
-                                   digest sz + BLOC_SZ (iv) + pad byte (1) */
-    MAX_COMP_EXTRA  = 1024,     /* max compression extra */
-    MAX_MTU         = WOLFSSL_MAX_MTU,     /* max expected MTU */
-    MAX_UDP_SIZE    = 8192 - 100, /* was MAX_MTU - 100 */
-    MAX_DH_SZ       = (MAX_DHKEY_SZ * 2) + 12,
-                                /* 4096 p, pub, g + 2 byte size for each */
-    MAX_STR_VERSION = 8,        /* string rep of protocol version */
-
-    PAD_MD5        = 48,       /* pad length for finished */
-    PAD_SHA        = 40,       /* pad length for finished */
-    MAX_PAD_SIZE   = 256,      /* maximum length of padding */
-
-    LENGTH_SZ      =  2,       /* length field for HMAC, data only */
-    VERSION_SZ     =  2,       /* length of proctocol version */
-    SEQ_SZ         =  8,       /* 64 bit sequence number  */
-    ALERT_SIZE     =  2,       /* level + description     */
-    VERIFY_HEADER  =  2,       /* always use 2 bytes      */
-    EXTS_SZ        =  2,       /* always use 2 bytes      */
-    EXT_ID_SZ      =  2,       /* always use 2 bytes      */
-    MAX_DH_SIZE    = MAX_DHKEY_SZ+1,
-                               /* Max size plus possible leading 0 */
-    NAMED_DH_MASK  = 0x100,    /* Named group mask for DH parameters  */
-    SESSION_HINT_SZ = 4,       /* session timeout hint */
-    SESSION_ADD_SZ = 4,        /* session age add */
-    TICKET_NONCE_LEN_SZ = 1,   /* Ticket nonce length size */
-    DEF_TICKET_NONCE_SZ = 1,   /* Default ticket nonce size */
-    MAX_TICKET_NONCE_SZ = 4,   /* maximum ticket nonce size */
-    MAX_LIFETIME   = 604800,   /* maximum ticket lifetime */
-    MAX_EARLY_DATA_SZ = 4096,  /* maximum early data size */
-
-    RAN_LEN      = 32,         /* random length           */
-    SEED_LEN     = RAN_LEN * 2, /* tls prf seed length    */
-    ID_LEN       = 32,         /* session id length       */
-    COOKIE_SECRET_SZ = 14,     /* dtls cookie secret size */
-    MAX_COOKIE_LEN = 32,       /* max dtls cookie size    */
-    COOKIE_SZ    = 20,         /* use a 20 byte cookie    */
-    SUITE_LEN    =  2,         /* cipher suite sz length  */
-    ENUM_LEN     =  1,         /* always a byte           */
-    OPAQUE8_LEN  =  1,         /* 1 byte                  */
-    OPAQUE16_LEN =  2,         /* 2 bytes                 */
-    OPAQUE24_LEN =  3,         /* 3 bytes                 */
-    OPAQUE32_LEN =  4,         /* 4 bytes                 */
-    OPAQUE64_LEN =  8,         /* 8 bytes                 */
-    COMP_LEN     =  1,         /* compression length      */
-    CURVE_LEN    =  2,         /* ecc named curve length  */
-    KE_GROUP_LEN =  2,         /* key exchange group length */
-    SERVER_ID_LEN = 20,        /* server session id length  */
-
-    HANDSHAKE_HEADER_SZ   = 4,  /* type + length(3)        */
-    RECORD_HEADER_SZ      = 5,  /* type + version + len(2) */
-    CERT_HEADER_SZ        = 3,  /* always 3 bytes          */
-    REQ_HEADER_SZ         = 2,  /* cert request header sz  */
-    HINT_LEN_SZ           = 2,  /* length of hint size field */
-    TRUNCATED_HMAC_SZ     = 10, /* length of hmac w/ truncated hmac extension */
-    HELLO_EXT_SZ          = 4,  /* base length of a hello extension */
-    HELLO_EXT_TYPE_SZ     = 2,  /* length of a hello extension type */
-    HELLO_EXT_SZ_SZ       = 2,  /* length of a hello extension size */
-    HELLO_EXT_SIGALGO_SZ  = 2,  /* length of number of items in sigalgo list */
-
-    DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
-    DTLS_RECORD_HEADER_SZ    = 13, /* normal + epoch(2) + seq_num(6) */
-    DTLS_HANDSHAKE_EXTRA     = 8,  /* diff from normal */
-    DTLS_RECORD_EXTRA        = 8,  /* diff from normal */
-    DTLS_HANDSHAKE_SEQ_SZ    = 2,  /* handshake header sequence number */
-    DTLS_HANDSHAKE_FRAG_SZ   = 3,  /* fragment offset and length are 24 bit */
-    DTLS_POOL_SZ             = 255,/* allowed number of list items in TX pool */
-    DTLS_EXPORT_PRO          = 165,/* wolfSSL protocol for serialized session */
-    DTLS_EXPORT_VERSION      = 4,  /* wolfSSL version for serialized session */
-    DTLS_EXPORT_OPT_SZ       = 60, /* amount of bytes used from Options */
-    DTLS_EXPORT_VERSION_3    = 3,  /* wolfSSL version before TLS 1.3 addition */
-    DTLS_EXPORT_OPT_SZ_3     = 59, /* amount of bytes used from Options */
-    DTLS_EXPORT_KEY_SZ       = 325 + (DTLS_SEQ_SZ * 2),
-                                   /* max amount of bytes used from Keys */
-    DTLS_EXPORT_MIN_KEY_SZ   = 78 + (DTLS_SEQ_SZ * 2),
-                                   /* min amount of bytes used from Keys */
-    DTLS_EXPORT_SPC_SZ       = 16, /* amount of bytes used from CipherSpecs */
-    DTLS_EXPORT_LEN          = 2,  /* 2 bytes for length and protocol */
-    DTLS_EXPORT_IP           = 46, /* max ip size IPv4 mapped IPv6 */
-    MAX_EXPORT_BUFFER        = 514, /* max size of buffer for exporting */
-    FINISHED_LABEL_SZ   = 15,  /* TLS finished label size */
-    TLS_FINISHED_SZ     = 12,  /* TLS has a shorter size  */
-    EXT_MASTER_LABEL_SZ = 22,  /* TLS extended master secret label sz */
-    MASTER_LABEL_SZ     = 13,  /* TLS master secret label sz */
-    KEY_LABEL_SZ        = 13,  /* TLS key block expansion sz */
-    MAX_PRF_HALF        = 256, /* Maximum half secret len */
-    MAX_PRF_LABSEED     = 128, /* Maximum label + seed len */
-    MAX_PRF_DIG         = 224, /* Maximum digest len      */
-    PROTOCOL_LABEL_SZ   = 9,   /* Length of the protocol label */
-    MAX_LABEL_SZ        = 34,  /* Maximum length of a label */
-    MAX_HKDF_LABEL_SZ   = OPAQUE16_LEN +
-                          OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
-                          OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
-    MAX_REQUEST_SZ      = 256, /* Maximum cert req len (no auth yet */
-    SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
-    TLS_MAX_PAD_SZ      = 255, /* Max padding in TLS */
-
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-    MAX_SYM_KEY_SIZE    = AES_256_KEY_SIZE,
-#else
-    MAX_SYM_KEY_SIZE    = WC_MAX_SYM_KEY_SIZE,
-#endif
-
-#ifdef HAVE_SELFTEST
-    AES_256_KEY_SIZE    = 32,
-    AES_IV_SIZE         = 16,
-    AES_128_KEY_SIZE    = 16,
-#endif
-
-    MAX_IV_SZ           = AES_BLOCK_SIZE,
-
-    AEAD_SEQ_OFFSET     = 4,   /* Auth Data: Sequence number */
-    AEAD_TYPE_OFFSET    = 8,   /* Auth Data: Type            */
-    AEAD_VMAJ_OFFSET    = 9,   /* Auth Data: Major Version   */
-    AEAD_VMIN_OFFSET    = 10,  /* Auth Data: Minor Version   */
-    AEAD_LEN_OFFSET     = 11,  /* Auth Data: Length          */
-    AEAD_AUTH_DATA_SZ   = 13,  /* Size of the data to authenticate */
-    AEAD_NONCE_SZ       = 12,
-    AESGCM_IMP_IV_SZ    = 4,   /* Size of GCM/CCM AEAD implicit IV */
-    AESGCM_EXP_IV_SZ    = 8,   /* Size of GCM/CCM AEAD explicit IV */
-    AESGCM_NONCE_SZ     = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ,
-
-    CHACHA20_IMP_IV_SZ  = 12,  /* Size of ChaCha20 AEAD implicit IV */
-    CHACHA20_NONCE_SZ   = 12,  /* Size of ChacCha20 nonce           */
-    CHACHA20_OLD_OFFSET = 4,   /* Offset for seq # in old poly1305  */
-
-    /* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */
-
-    AES_GCM_AUTH_SZ     = 16, /* AES-GCM Auth Tag length    */
-    AES_CCM_16_AUTH_SZ  = 16, /* AES-CCM-16 Auth Tag length */
-    AES_CCM_8_AUTH_SZ   = 8,  /* AES-CCM-8 Auth Tag Length  */
-    AESCCM_NONCE_SZ     = 12,
-
-    CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */
-    CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */
-    CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */
-    CAMELLIA_IV_SIZE      = 16, /* always block size */
-
-    CHACHA20_256_KEY_SIZE = 32,  /* for 256 bit             */
-    CHACHA20_128_KEY_SIZE = 16,  /* for 128 bit             */
-    CHACHA20_IV_SIZE      = 12,  /* 96 bits for iv          */
-
-    POLY1305_AUTH_SZ    = 16,  /* 128 bits                */
-
-    HC_128_KEY_SIZE     = 16,  /* 128 bits                */
-    HC_128_IV_SIZE      = 16,  /* also 128 bits           */
-
-    RABBIT_KEY_SIZE     = 16,  /* 128 bits                */
-    RABBIT_IV_SIZE      =  8,  /* 64 bits for iv          */
-
-    EVP_SALT_SIZE       =  8,  /* evp salt size 64 bits   */
-
-    ECDHE_SIZE          = 32,  /* ECHDE server size defaults to 256 bit */
-    MAX_EXPORT_ECC_SZ   = 256, /* Export ANS X9.62 max future size */
-    MAX_CURVE_NAME_SZ   = 16,  /* Maximum size of curve name string */
-
-    NEW_SA_MAJOR        = 8,   /* Most signicant byte used with new sig algos */
-    ED25519_SA_MAJOR    = 8,   /* Most significant byte for ED25519 */
-    ED25519_SA_MINOR    = 7,   /* Least significant byte for ED25519 */
-    ED448_SA_MAJOR      = 8,   /* Most significant byte for ED448 */
-    ED448_SA_MINOR      = 8,   /* Least significant byte for ED448 */
-
-    MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */
-    MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */
-
-    MAX_CERT_VERIFY_SZ = 1024, /* max   */
-    CLIENT_HELLO_FIRST =  35,  /* Protocol + RAN_LEN + sizeof(id_len) */
-    MAX_SUITE_NAME     =  48,  /* maximum length of cipher suite string */
-
-    DTLS_TIMEOUT_INIT       =  1, /* default timeout init for DTLS receive  */
-    DTLS_TIMEOUT_MAX        = 64, /* default max timeout for DTLS receive */
-    DTLS_TIMEOUT_MULTIPLIER =  2, /* default timeout multiplier for DTLS recv */
-
-    MAX_PSK_ID_LEN     = 128,  /* max psk identity/hint supported */
-    NULL_TERM_LEN      =   1,  /* length of null '\0' termination character */
-    MAX_PSK_KEY_LEN    =  64,  /* max psk key supported */
-    MIN_PSK_ID_LEN     =   6,  /* min length of identities */
-    MIN_PSK_BINDERS_LEN=  33,  /* min length of binders */
-    MAX_TICKET_AGE_SECS=  10,  /* maximum ticket age in seconds */
-
-    MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4,  /* 4 mb file size alloc limit */
-
-#if defined(HAVE_EX_DATA) || defined(FORTRESS)
-    MAX_EX_DATA        =   5,  /* allow for five items of ex_data */
-#endif
-
-    MAX_X509_SIZE      = 2048, /* max static x509 buffer size */
-    CERT_MIN_SIZE      =  256, /* min PEM cert size with header/footer */
-
-    MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */
-    MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */
-    MAX_NTRU_BITS       =  256, /* max symmetric bit strength */
-    NO_SNIFF           =   0,  /* not sniffing */
-    SNIFF              =   1,  /* currently sniffing */
-
-    HASH_SIG_SIZE      =   2,  /* default SHA1 RSA */
-
-    NO_COPY            =   0,  /* should we copy static buffer for write */
-    COPY               =   1,  /* should we copy static buffer for write */
-
-    INVALID_PEER_ID    = 0xFFFF, /* Initialize value for peer ID. */
-
-    PREV_ORDER         = -1,   /* Sequence number is in previous epoch. */
-    PEER_ORDER         = 1,    /* Peer sequence number for verify. */
-    CUR_ORDER          = 0,    /* Current sequence number. */
-    WRITE_PROTO        = 1,    /* writing a protocol message */
-    READ_PROTO         = 0     /* reading a protocol message */
-};
-
-/* minimum Downgrade Minor version */
-#ifndef WOLFSSL_MIN_DOWNGRADE
-    #ifndef NO_OLD_TLS
-        #define WOLFSSL_MIN_DOWNGRADE TLSv1_MINOR
-    #else
-        #define WOLFSSL_MIN_DOWNGRADE TLSv1_2_MINOR
-    #endif
-#endif
-
-/* Set max implicit IV size for AEAD cipher suites */
-#define AEAD_MAX_IMP_SZ 12
-
-/* Set max explicit IV size for AEAD cipher suites */
-#define AEAD_MAX_EXP_SZ 8
-
-
-#ifndef WOLFSSL_MAX_SUITE_SZ
-    #define WOLFSSL_MAX_SUITE_SZ 300
-    /* 150 suites for now! */
-#endif
-
-/* number of items in the signature algo list */
-#ifndef WOLFSSL_MAX_SIGALGO
-    #define WOLFSSL_MAX_SIGALGO 32
-#endif
-
-
-/* set minimum ECC key size allowed */
-#ifndef WOLFSSL_MIN_ECC_BITS
-    #ifdef WOLFSSL_MAX_STRENGTH
-        #define WOLFSSL_MIN_ECC_BITS  256
-    #else
-        #define WOLFSSL_MIN_ECC_BITS 224
-    #endif
-#endif /* WOLFSSL_MIN_ECC_BITS */
-#if (WOLFSSL_MIN_ECC_BITS % 8)
-    /* Some ECC keys are not divisable by 8 such as prime239v1 or sect131r1.
-       In these cases round down to the nearest value divisable by 8. The
-       restriction of being divisable by 8 is in place to match wc_ecc_size
-       function from wolfSSL.
-     */
-    #error ECC minimum bit size must be a multiple of 8
-#endif
-#define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8)
-
-/* set minimum RSA key size allowed */
-#ifndef WOLFSSL_MIN_RSA_BITS
-    #ifdef WOLFSSL_MAX_STRENGTH
-        #define WOLFSSL_MIN_RSA_BITS 2048
-    #else
-        #define WOLFSSL_MIN_RSA_BITS 1024
-    #endif
-#endif /* WOLFSSL_MIN_RSA_BITS */
-#if (WOLFSSL_MIN_RSA_BITS % 8)
-    /* This is to account for the example case of a min size of 2050 bits but
-       still allows 2049 bit key. So we need the measurment to be in bytes. */
-    #error RSA minimum bit size must be a multiple of 8
-#endif
-#define MIN_RSAKEY_SZ (WOLFSSL_MIN_RSA_BITS / 8)
-
-#ifdef SESSION_INDEX
-/* Shift values for making a session index */
-#define SESSIDX_ROW_SHIFT 4
-#define SESSIDX_IDX_MASK  0x0F
-#endif
-
-
-/* max cert chain peer depth */
-#ifndef MAX_CHAIN_DEPTH
-    #define MAX_CHAIN_DEPTH 9
-#endif
-
-/* max size of a certificate message payload */
-/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */
-#ifndef MAX_CERTIFICATE_SZ
-    #define MAX_CERTIFICATE_SZ \
-                CERT_HEADER_SZ + \
-                (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH
-#endif
-
-/* max size of a handshake message, currently set to the certificate */
-#ifndef MAX_HANDSHAKE_SZ
-    #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ
-#endif
-
-#ifndef SESSION_TICKET_LEN
-    #define SESSION_TICKET_LEN 256
-#endif
-
-#ifndef SESSION_TICKET_HINT_DEFAULT
-    #define SESSION_TICKET_HINT_DEFAULT 300
-#endif
-
-
-/* don't use extra 3/4k stack space unless need to */
-#ifdef HAVE_NTRU
-    #define MAX_ENCRYPT_SZ MAX_NTRU_ENCRYPT_SZ
-#else
-    #define MAX_ENCRYPT_SZ ENCRYPT_LEN
-#endif
-
-
-/* states */
-enum states {
-    NULL_STATE = 0,
-
-    SERVER_HELLOVERIFYREQUEST_COMPLETE,
-    SERVER_HELLO_RETRY_REQUEST_COMPLETE,
-    SERVER_HELLO_COMPLETE,
-    SERVER_ENCRYPTED_EXTENSIONS_COMPLETE,
-    SERVER_CERT_COMPLETE,
-    SERVER_KEYEXCHANGE_COMPLETE,
-    SERVER_HELLODONE_COMPLETE,
-	SERVER_CHANGECIPHERSPEC_COMPLETE,
-    SERVER_FINISHED_COMPLETE,
-
-    CLIENT_HELLO_COMPLETE,
-    CLIENT_KEYEXCHANGE_COMPLETE,
-	CLIENT_CHANGECIPHERSPEC_COMPLETE,
-    CLIENT_FINISHED_COMPLETE,
-
-    HANDSHAKE_DONE
-};
-
-/* SSL Version */
-typedef struct ProtocolVersion {
-    byte major;
-    byte minor;
-} WOLFSSL_PACK ProtocolVersion;
-
-
-WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
-WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
-WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
-WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
-WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
-
-#ifdef WOLFSSL_DTLS
-    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void);
-    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
-
-    #ifdef WOLFSSL_SESSION_EXPORT
-    WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf,
-                                                                     word32 sz);
-    WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
-                                                                     word32 sz);
-    WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
-    #endif
-#endif
-
-
-/* wolfSSL BIO_METHOD type */
-struct WOLFSSL_BIO_METHOD {
-    byte type;               /* method type */
-};
-
-
-/* wolfSSL BIO type */
-struct WOLFSSL_BIO {
-    WOLFSSL_BUF_MEM* mem_buf;
-    WOLFSSL*     ssl;           /* possible associated ssl */
-#ifndef NO_FILESYSTEM
-    XFILE        file;
-#endif
-    WOLFSSL_BIO* prev;          /* previous in chain */
-    WOLFSSL_BIO* next;          /* next in chain */
-    WOLFSSL_BIO* pair;          /* BIO paired with */
-    void*        heap;          /* user heap hint */
-    byte*        mem;           /* memory buffer */
-    int         wrSz;          /* write buffer size (mem) */
-    int         wrIdx;         /* current index for write buffer */
-    int         rdIdx;         /* current read index */
-    int         readRq;        /* read request */
-    int         memLen;        /* memory buffer length */
-    int         fd;            /* possible file descriptor */
-    int         eof;           /* eof flag */
-    int         flags;
-    byte        type;          /* method type */
-    byte        close;         /* close flag */
-};
-
-
-/* wolfSSL method type */
-struct WOLFSSL_METHOD {
-    ProtocolVersion version;
-    byte            side;         /* connection side, server or client */
-    byte            downgrade;    /* whether to downgrade version, default no */
-};
-
-/* wolfSSL buffer type - internal uses "buffer" type */
-typedef WOLFSSL_BUFFER_INFO buffer;
-
-typedef struct Suites Suites;
-
-
-/* defaults to client */
-WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion);
-
-/* for sniffer */
-WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                            word32 size, word32 totalSz, int sniff);
-WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx);
-/* TLS v1.3 needs these */
-WOLFSSL_LOCAL int  HandleTlsResumption(WOLFSSL* ssl, int bogusID,
-                                       Suites* clSuites);
-WOLFSSL_LOCAL int  DoClientHello(WOLFSSL* ssl, const byte* input, word32*,
-                                 word32);
-#ifdef WOLFSSL_TLS13
-WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input,
-                                     word32* inOutIdx, word32 helloSz);
-#endif
-WOLFSSL_LOCAL int  DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
-                                 word32);
-WOLFSSL_LOCAL int  CompleteServerHello(WOLFSSL *ssl);
-WOLFSSL_LOCAL int  CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
-WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
-                                   word32 hashSigAlgoSz);
-WOLFSSL_LOCAL int  DecodePrivateKey(WOLFSSL *ssl, word16* length);
-#ifdef HAVE_PK_CALLBACKS
-WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl);
-#ifndef NO_ASN
-    WOLFSSL_LOCAL int  InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx);
-#endif
-#endif
-WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl);
-WOLFSSL_LOCAL int  ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size);
-WOLFSSL_LOCAL int  MatchDomainName(const char* pattern, int len, const char* str);
-#ifndef NO_CERTS
-WOLFSSL_LOCAL int  CheckAltNames(DecodedCert* dCert, char* domain);
-#endif
-WOLFSSL_LOCAL int  CreateTicket(WOLFSSL* ssl);
-WOLFSSL_LOCAL int  HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz);
-WOLFSSL_LOCAL int  HashOutput(WOLFSSL* ssl, const byte* output, int sz,
-                              int ivSz);
-WOLFSSL_LOCAL int  HashInput(WOLFSSL* ssl, const byte* input, int sz);
-#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl);
-#endif
-#ifdef WOLFSSL_TLS13
-WOLFSSL_LOCAL int  DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
-                                word16 sz, const byte* aad, word16 aadSz);
-WOLFSSL_LOCAL int  DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
-                                           word32* inOutIdx, byte type,
-                                           word32 size, word32 totalSz);
-WOLFSSL_LOCAL int  DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input,
-                                       word32* inOutIdx, word32 totalSz);
-WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
-                                     word32* inOutIdx, word32 helloSz,
-                                     byte* extMsgType);
-#endif
-int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
-                    int pLen, int content);
-
-
-enum {
-    FORCED_FREE = 1,
-    NO_FORCED_FREE = 0
-};
-
-
-/* only use compression extra if using compression */
-#ifdef HAVE_LIBZ
-    #define COMP_EXTRA MAX_COMP_EXTRA
-#else
-    #define COMP_EXTRA 0
-#endif
-
-/* only the sniffer needs space in the buffer for extra MTU record(s) */
-#ifdef WOLFSSL_SNIFFER
-    #define MTU_EXTRA MAX_MTU * 3
-#else
-    #define MTU_EXTRA 0
-#endif
-
-
-/* embedded callbacks require large static buffers, make sure on */
-#ifdef WOLFSSL_CALLBACKS
-    #undef  LARGE_STATIC_BUFFERS
-    #define LARGE_STATIC_BUFFERS
-#endif
-
-
-/* give user option to use 16K static buffers */
-#if defined(LARGE_STATIC_BUFFERS)
-    #define RECORD_SIZE MAX_RECORD_SIZE
-#else
-    #ifdef WOLFSSL_DTLS
-        #define RECORD_SIZE MAX_MTU
-    #else
-        #define RECORD_SIZE 128
-    #endif
-#endif
-
-
-/* user option to turn off 16K output option */
-/* if using small static buffers (default) and SSL_write tries to write data
-   larger than the record we have, dynamically get it, unless user says only
-   write in static buffer chunks  */
-#ifndef STATIC_CHUNKS_ONLY
-    #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE
-#else
-    #define OUTPUT_RECORD_SIZE RECORD_SIZE
-#endif
-
-/* wolfSSL input buffer
-
-   RFC 2246:
-
-   length
-       The length (in bytes) of the following TLSPlaintext.fragment.
-       The length should not exceed 2^14.
-*/
-#if defined(LARGE_STATIC_BUFFERS)
-    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \
-             MTU_EXTRA + MAX_MSG_EXTRA
-#else
-    /* don't fragment memory from the record header */
-    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ
-#endif
-
-typedef struct {
-    ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN];
-    byte*  buffer;       /* place holder for static or dynamic buffer */
-    word32 length;       /* total buffer length used */
-    word32 idx;          /* idx to part of length already consumed */
-    word32 bufferSize;   /* current buffer size */
-    byte   dynamicFlag;  /* dynamic memory currently in use */
-    byte   offset;       /* alignment offset attempt */
-} bufferStatic;
-
-/* Cipher Suites holder */
-struct Suites {
-    word16 suiteSz;                 /* suite length in bytes        */
-    word16 hashSigAlgoSz;           /* SigAlgo extension length in bytes */
-    byte   suites[WOLFSSL_MAX_SUITE_SZ];
-    byte   hashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* sig/algo to offer */
-    byte   setSuites;               /* user set suites from default */
-    byte   hashAlgo;                /* selected hash algorithm */
-    byte   sigAlgo;                 /* selected sig algorithm */
-};
-
-
-WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
-                                         int haveRSAsig, int haveAnon,
-                                         int tls1_2, int keySz);
-WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16,
-                              word16, word16, word16, word16, word16, int);
-WOLFSSL_LOCAL int  MatchSuite(WOLFSSL* ssl, Suites* peerSuites);
-WOLFSSL_LOCAL int  SetCipherList(WOLFSSL_CTX*, Suites*, const char* list);
-
-#ifndef PSK_TYPES_DEFINED
-    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
-                          unsigned int, unsigned char*, unsigned int);
-    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
-                          unsigned char*, unsigned int);
-#endif /* PSK_TYPES_DEFINED */
-#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \
-   !defined(WOLFSSL_DTLS_EXPORT_TYPES)
-    typedef int (*wc_dtls_export)(WOLFSSL* ssl,
-                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
-#define WOLFSSL_DTLS_EXPORT_TYPES
-#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
-
-
-/* wolfSSL Cipher type just points back to SSL */
-struct WOLFSSL_CIPHER {
-    WOLFSSL* ssl;
-};
-
-
-typedef struct OcspEntry OcspEntry;
-
-#ifdef NO_SHA
-    #define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-#else
-    #define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-#endif
-
-#ifdef NO_ASN
-    /* no_asn won't have */
-    typedef struct CertStatus CertStatus;
-#endif
-
-struct OcspEntry {
-    OcspEntry*  next;                            /* next entry             */
-    byte        issuerHash[OCSP_DIGEST_SIZE];    /* issuer hash            */
-    byte        issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
-    CertStatus* status;                          /* OCSP response list     */
-    int         totalStatus;                     /* number on list         */
-};
-
-
-#ifndef HAVE_OCSP
-    typedef struct WOLFSSL_OCSP WOLFSSL_OCSP;
-#endif
-
-/* wolfSSL OCSP controller */
-struct WOLFSSL_OCSP {
-    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
-    OcspEntry*            ocspList;      /* OCSP response list */
-    wolfSSL_Mutex         ocspLock;      /* OCSP list lock */
-#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
-    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    int(*statusCb)(WOLFSSL*, void*);
-#endif
-};
-
-#ifndef MAX_DATE_SIZE
-#define MAX_DATE_SIZE 32
-#endif
-
-typedef struct CRL_Entry CRL_Entry;
-
-#ifdef NO_SHA
-    #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-#else
-    #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-#endif
-
-#ifdef NO_ASN
-    typedef struct RevokedCert RevokedCert;
-#endif
-
-/* Complete CRL */
-struct CRL_Entry {
-    CRL_Entry* next;                      /* next entry */
-    byte    issuerHash[CRL_DIGEST_SIZE];  /* issuer hash                 */
-    /* byte    crlHash[CRL_DIGEST_SIZE];      raw crl data hash           */
-    /* restore the hash here if needed for optimized comparisons */
-    byte    lastDate[MAX_DATE_SIZE]; /* last date updated  */
-    byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
-    byte    lastDateFormat;          /* last date format */
-    byte    nextDateFormat;          /* next date format */
-    RevokedCert* certs;              /* revoked cert list  */
-    int          totalCerts;         /* number on list     */
-    int     verified;
-    byte*   toBeSigned;
-    word32  tbsSz;
-    byte*   signature;
-    word32  signatureSz;
-    word32  signatureOID;
-#if !defined(NO_SKID) && defined(CRL_SKID_READY)
-    byte    extAuthKeyIdSet;
-    byte    extAuthKeyId[KEYID_SIZE];
-#endif
-};
-
-
-typedef struct CRL_Monitor CRL_Monitor;
-
-/* CRL directory monitor */
-struct CRL_Monitor {
-    char* path;      /* full dir path, if valid pointer we're using */
-    int   type;      /* PEM or ASN1 type */
-};
-
-
-#if defined(HAVE_CRL) && defined(NO_FILESYSTEM)
-    #undef HAVE_CRL_MONITOR
-#endif
-
-/* wolfSSL CRL controller */
-struct WOLFSSL_CRL {
-    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
-    CRL_Entry*            crlList;       /* our CRL list */
-#ifdef HAVE_CRL_IO
-    CbCrlIO               crlIOCb;
-#endif
-    wolfSSL_Mutex         crlLock;       /* CRL list lock */
-    CRL_Monitor           monitors[2];   /* PEM and DER possible */
-#ifdef HAVE_CRL_MONITOR
-    pthread_cond_t        cond;          /* condition to signal setup */
-    pthread_t             tid;           /* monitoring thread */
-    int                   mfd;           /* monitor fd, -1 if no init yet */
-    int                   setup;         /* thread is setup predicate */
-#endif
-    void*                 heap;          /* heap hint for dynamic memory */
-};
-
-
-#ifdef NO_ASN
-    typedef struct Signer Signer;
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    typedef struct TrustedPeerCert TrustedPeerCert;
-#endif
-#endif
-
-
-#ifndef CA_TABLE_SIZE
-    #define CA_TABLE_SIZE 11
-#endif
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    #define TP_TABLE_SIZE 11
-#endif
-
-/* wolfSSL Certificate Manager */
-struct WOLFSSL_CERT_MANAGER {
-    Signer*         caTable[CA_TABLE_SIZE]; /* the CA signer table */
-    void*           heap;                /* heap helper */
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */
-    wolfSSL_Mutex   tpLock;                  /* trusted peer list lock */
-#endif
-    WOLFSSL_CRL*    crl;                 /* CRL checker */
-    WOLFSSL_OCSP*   ocsp;                /* OCSP checker */
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
-                               ||  defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
-    WOLFSSL_OCSP*   ocsp_stapling;       /* OCSP checker for OCSP stapling */
-#endif
-    char*           ocspOverrideURL;     /* use this responder */
-    void*           ocspIOCtx;           /* I/O callback CTX */
-    CallbackCACache caCacheCallback;     /* CA cache addition callback */
-    CbMissingCRL    cbMissingCRL;        /* notify through cb of missing crl */
-    CbOCSPIO        ocspIOCb;            /* I/O callback for OCSP lookup */
-    CbOCSPRespFree  ocspRespFreeCb;      /* Frees OCSP Response from IO Cb */
-    wolfSSL_Mutex   caLock;              /* CA list lock */
-    byte            crlEnabled;          /* is CRL on ? */
-    byte            crlCheckAll;         /* always leaf, but all ? */
-    byte            ocspEnabled;         /* is OCSP on ? */
-    byte            ocspCheckAll;        /* always leaf, but all ? */
-    byte            ocspSendNonce;       /* send the OCSP nonce ? */
-    byte            ocspUseOverrideURL;  /* ignore cert's responder, override */
-    byte            ocspStaplingEnabled; /* is OCSP Stapling on ? */
-
-#ifndef NO_RSA
-    short           minRsaKeySz;         /* minimum allowed RSA key size */
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    short           minEccKeySz;         /* minimum allowed ECC key size */
-#endif
-};
-
-WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*);
-WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*);
-WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*);
-WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int);
-WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*);
-
-/* wolfSSL Sock Addr */
-struct WOLFSSL_SOCKADDR {
-    unsigned int sz; /* sockaddr size */
-    void*        sa; /* pointer to the sockaddr_in or sockaddr_in6 */
-};
-
-typedef struct WOLFSSL_DTLS_CTX {
-    WOLFSSL_SOCKADDR peer;
-    int rfd;
-    int wfd;
-} WOLFSSL_DTLS_CTX;
-
-
-typedef struct WOLFSSL_DTLS_PEERSEQ {
-    word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
-                        /* Sliding window for current epoch    */
-    word16 nextEpoch;   /* Expected epoch in next record       */
-    word16 nextSeq_hi;  /* Expected sequence in next record    */
-    word32 nextSeq_lo;
-
-    word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS];
-                        /* Sliding window for old epoch        */
-    word32 prevSeq_lo;
-    word16 prevSeq_hi;  /* Next sequence in allowed old epoch  */
-
-#ifdef WOLFSSL_MULTICAST
-    word16 peerId;
-    word32 highwaterMark;
-#endif
-} WOLFSSL_DTLS_PEERSEQ;
-
-
-#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
-
-/* keys and secrets
- * keep as a constant size (no additional ifdefs) for session export */
-typedef struct Keys {
-    byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE];   /* max sizes */
-    byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE];
-    byte client_write_key[MAX_SYM_KEY_SIZE];         /* max sizes */
-    byte server_write_key[MAX_SYM_KEY_SIZE];
-    byte client_write_IV[MAX_WRITE_IV_SZ];               /* max sizes */
-    byte server_write_IV[MAX_WRITE_IV_SZ];
-#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT)
-    byte aead_exp_IV[AEAD_MAX_EXP_SZ];
-    byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ];
-    byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
-#endif
-
-    word32 peer_sequence_number_hi;
-    word32 peer_sequence_number_lo;
-    word32 sequence_number_hi;
-    word32 sequence_number_lo;
-
-#ifdef WOLFSSL_DTLS
-    word16 curEpoch;    /* Received epoch in current record    */
-    word16 curSeq_hi;   /* Received sequence in current record */
-    word32 curSeq_lo;
-#ifdef WOLFSSL_MULTICAST
-    byte   curPeerId;   /* Received peer group ID in current record */
-#endif
-    WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ];
-
-    word16 dtls_peer_handshake_number;
-    word16 dtls_expected_peer_handshake_number;
-
-    word16 dtls_epoch;                          /* Current epoch    */
-    word16 dtls_sequence_number_hi;             /* Current epoch */
-    word32 dtls_sequence_number_lo;
-    word16 dtls_prev_sequence_number_hi;        /* Previous epoch */
-    word32 dtls_prev_sequence_number_lo;
-    word16 dtls_handshake_number;               /* Current tx handshake seq */
-#endif
-
-    word32 encryptSz;             /* last size of encrypted data   */
-    word32 padSz;                 /* how much to advance after decrypt part */
-    byte   encryptionOn;          /* true after change cipher spec */
-    byte   decryptedCur;          /* only decrypt current record once */
-#ifdef WOLFSSL_TLS13
-    byte   updateResponseReq:1;   /* KeyUpdate response from peer required. */
-    byte   keyUpdateRespond:1;    /* KeyUpdate is to be responded to. */
-#endif
-} Keys;
-
-
-
-/** TLS Extensions - RFC 6066 */
-#ifdef HAVE_TLS_EXTENSIONS
-
-typedef enum {
-    TLSX_SERVER_NAME                = 0x0000, /* a.k.a. SNI  */
-    TLSX_MAX_FRAGMENT_LENGTH        = 0x0001,
-    TLSX_TRUNCATED_HMAC             = 0x0004,
-    TLSX_STATUS_REQUEST             = 0x0005, /* a.k.a. OCSP stapling   */
-    TLSX_SUPPORTED_GROUPS           = 0x000a, /* a.k.a. Supported Curves */
-    TLSX_EC_POINT_FORMATS           = 0x000b,
-    TLSX_SIGNATURE_ALGORITHMS       = 0x000d,
-    TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
-    TLSX_STATUS_REQUEST_V2          = 0x0011, /* a.k.a. OCSP stapling v2 */
-    TLSX_QUANTUM_SAFE_HYBRID        = 0x0018, /* a.k.a. QSH  */
-    TLSX_SESSION_TICKET             = 0x0023,
-#ifdef WOLFSSL_TLS13
-    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    TLSX_PRE_SHARED_KEY             = 0x0029,
-    #endif
-    #ifdef WOLFSSL_EARLY_DATA
-    TLSX_EARLY_DATA                 = 0x002a,
-    #endif
-    TLSX_SUPPORTED_VERSIONS         = 0x002b,
-    TLSX_COOKIE                     = 0x002c,
-    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    TLSX_PSK_KEY_EXCHANGE_MODES     = 0x002d,
-    #endif
-    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
-    TLSX_POST_HANDSHAKE_AUTH        = 0x0031,
-    #endif
-    #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22)
-    TLSX_KEY_SHARE                  = 0x0028,
-    #else
-    TLSX_SIGNATURE_ALGORITHMS_CERT  = 0x0032,
-    TLSX_KEY_SHARE                  = 0x0033,
-    #endif
-#endif
-    TLSX_RENEGOTIATION_INFO         = 0xff01
-} TLSX_Type;
-
-typedef struct TLSX {
-    TLSX_Type    type; /* Extension Type  */
-    void*        data; /* Extension Data  */
-    word32       val;  /* Extension Value */
-    byte         resp; /* IsResponse Flag */
-    struct TLSX* next; /* List Behavior   */
-} TLSX;
-
-WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
-WOLFSSL_LOCAL void  TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
-WOLFSSL_LOCAL void  TLSX_FreeAll(TLSX* list, void* heap);
-WOLFSSL_LOCAL int   TLSX_SupportExtensions(WOLFSSL* ssl);
-WOLFSSL_LOCAL int   TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest);
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
-WOLFSSL_LOCAL int   TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, 
-                                         word16* pLength);
-WOLFSSL_LOCAL int   TLSX_WriteRequest(WOLFSSL* ssl, byte* output,
-                                       byte msgType, word16* pOffset);
-#endif
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
-/* TLS 1.3 Certificate messages have extensions. */
-WOLFSSL_LOCAL int   TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, 
-                                          word16* pLength);
-WOLFSSL_LOCAL int   TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, 
-                                        word16* pOffset);
-#endif
-
-WOLFSSL_LOCAL int   TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length,
-                               byte msgType, Suites *suites);
-
-#elif defined(HAVE_SNI)                           \
-   || defined(HAVE_MAX_FRAGMENT)                  \
-   || defined(HAVE_TRUNCATED_HMAC)                \
-   || defined(HAVE_CERTIFICATE_STATUS_REQUEST)    \
-   || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
-   || defined(HAVE_SUPPORTED_CURVES)              \
-   || defined(HAVE_ALPN)                          \
-   || defined(HAVE_QSH)                           \
-   || defined(HAVE_SESSION_TICKET)                \
-   || defined(HAVE_SECURE_RENEGOTIATION)          \
-   || defined(HAVE_SERVER_RENEGOTIATION_INFO)
-
-#error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined.
-
-#endif /* HAVE_TLS_EXTENSIONS */
-
-/** Server Name Indication - RFC 6066 (session 3) */
-#ifdef HAVE_SNI
-
-typedef struct SNI {
-    byte                       type;    /* SNI Type         */
-    union { char* host_name; } data;    /* SNI Data         */
-    struct SNI*                next;    /* List Behavior    */
-    byte                       status;  /* Matching result  */
-#ifndef NO_WOLFSSL_SERVER
-    byte                       options; /* Behavior options */
-#endif
-} SNI;
-
-WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
-                                                       word16 size, void* heap);
-WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
-WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
-                                                                   void** data);
-
-#ifndef NO_WOLFSSL_SERVER
-WOLFSSL_LOCAL void   TLSX_SNI_SetOptions(TLSX* extensions, byte type,
-                                                                  byte options);
-WOLFSSL_LOCAL int    TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
-                                         byte type, byte* sni, word32* inOutSz);
-#endif
-
-#endif /* HAVE_SNI */
-
-/* Application-Layer Protocol Negotiation - RFC 7301 */
-#ifdef HAVE_ALPN
-typedef struct ALPN {
-    char*        protocol_name; /* ALPN protocol name */
-    struct ALPN* next;          /* List Behavior      */
-    byte         options;       /* Behavior options */
-    byte         negotiated;    /* ALPN protocol negotiated or not */
-} ALPN;
-
-WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
-                                       void** data, word16 *dataSz);
-
-WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
-                               word16 size, byte options, void* heap);
-
-WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option);
-
-#endif /* HAVE_ALPN */
-
-/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */
-#ifdef HAVE_MAX_FRAGMENT
-
-WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap);
-
-#endif /* HAVE_MAX_FRAGMENT */
-
-/** Truncated HMAC - RFC 6066 (session 7) */
-#ifdef HAVE_TRUNCATED_HMAC
-
-WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap);
-
-#endif /* HAVE_TRUNCATED_HMAC */
-
-/** Certificate Status Request - RFC 6066 (session 8) */
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-
-typedef struct {
-    byte status_type;
-    byte options;
-    WOLFSSL* ssl;
-    union {
-        OcspRequest ocsp;
-    } request;
-#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
-    buffer response;
-#endif
-} CertificateStatusRequest;
-
-WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequest(TLSX** extensions,
-           byte status_type, byte options, WOLFSSL* ssl, void* heap, int devId);
-#ifndef NO_CERTS
-WOLFSSL_LOCAL int   TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert,
-                                                                    void* heap);
-#endif
-WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
-WOLFSSL_LOCAL int   TLSX_CSR_ForceRequest(WOLFSSL* ssl);
-
-#endif
-
-/** Certificate Status Request v2 - RFC 6961 */
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-
-typedef struct CSRIv2 {
-    byte status_type;
-    byte options;
-    word16 requests;
-    union {
-        OcspRequest ocsp[1 + MAX_CHAIN_DEPTH];
-    } request;
-    struct CSRIv2* next;
-} CertificateStatusRequestItemV2;
-
-WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequestV2(TLSX** extensions,
-                         byte status_type, byte options, void* heap, int devId);
-#ifndef NO_CERTS
-WOLFSSL_LOCAL int   TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert,
-                                                       byte isPeer, void* heap);
-#endif
-WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type,
-                                                                    byte index);
-WOLFSSL_LOCAL int   TLSX_CSR2_ForceRequest(WOLFSSL* ssl);
-
-#endif
-
-/** Supported Elliptic Curves - RFC 4492 (session 4) */
-#ifdef HAVE_SUPPORTED_CURVES
-
-typedef struct SupportedCurve {
-    word16 name;                 /* Curve Names */
-    struct SupportedCurve* next; /* List Behavior */
-} SupportedCurve;
-
-typedef struct PointFormat {
-    byte format;                /* PointFormat */
-    struct PointFormat* next;   /* List Behavior */
-} PointFormat;
-
-WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name,
-                                                                    void* heap);
-
-WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point,
-                                                                    void* heap);
-
-#ifndef NO_WOLFSSL_SERVER
-WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first,
-                                                                   byte second);
-WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl);
-#endif
-WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl,
-                                                            int checkSupported);
-
-#endif /* HAVE_SUPPORTED_CURVES */
-
-/** Renegotiation Indication - RFC 5746 */
-#if defined(HAVE_SECURE_RENEGOTIATION) \
- || defined(HAVE_SERVER_RENEGOTIATION_INFO)
-
-enum key_cache_state {
-    SCR_CACHE_NULL   = 0,       /* empty / begin state */
-    SCR_CACHE_NEEDED,           /* need to cache keys */
-    SCR_CACHE_COPY,             /* we have a cached copy */
-    SCR_CACHE_PARTIAL,          /* partial restore to real keys */
-    SCR_CACHE_COMPLETE          /* complete restore to real keys */
-};
-
-/* Additional Connection State according to rfc5746 section 3.1 */
-typedef struct SecureRenegotiation {
-   byte                 enabled;  /* secure_renegotiation flag in rfc */
-   byte                 startScr; /* server requested client to start scr */
-   enum key_cache_state cache_status;  /* track key cache state */
-   byte                 client_verify_data[TLS_FINISHED_SZ];  /* cached */
-   byte                 server_verify_data[TLS_FINISHED_SZ];  /* cached */
-   byte                 subject_hash[WC_SHA_DIGEST_SIZE];  /* peer cert hash */
-   Keys                 tmp_keys;  /* can't overwrite real keys yet */
-} SecureRenegotiation;
-
-WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap);
-
-#ifdef HAVE_SERVER_RENEGOTIATION_INFO
-WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap);
-#endif
-
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-/** Session Ticket - RFC 5077 (session 3.2) */
-#ifdef HAVE_SESSION_TICKET
-
-typedef struct SessionTicket {
-    word32 lifetime;
-#ifdef WOLFSSL_TLS13
-    word64 seen;
-    word32 ageAdd;
-#endif
-    byte*  data;
-    word16 size;
-} SessionTicket;
-
-WOLFSSL_LOCAL int  TLSX_UseSessionTicket(TLSX** extensions,
-                                             SessionTicket* ticket, void* heap);
-WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
-                                           byte* data, word16 size, void* heap);
-WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap);
-
-#endif /* HAVE_SESSION_TICKET */
-
-/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */
-#ifdef HAVE_QSH
-
-typedef struct QSHScheme {
-    struct QSHScheme* next; /* List Behavior   */
-    byte*             PK;
-    word16            name; /* QSHScheme Names */
-    word16            PKLen;
-} QSHScheme;
-
-typedef struct QSHkey {
-    struct QSHKey* next;
-    word16 name;
-    buffer pub;
-    buffer pri;
-} QSHKey;
-
-typedef struct QSHSecret {
-    QSHScheme* list;
-    buffer* SerSi;
-    buffer* CliSi;
-} QSHSecret;
-
-/* used in key exchange during handshake */
-WOLFSSL_LOCAL int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input,
-                                                  word16 length, byte isServer);
-WOLFSSL_LOCAL word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output);
-WOLFSSL_LOCAL word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest);
-
-/* used by api for setting a specific QSH scheme */
-WOLFSSL_LOCAL int TLSX_UseQSHScheme(TLSX** extensions, word16 name,
-                                         byte* pKey, word16 pKeySz, void* heap);
-
-/* used when parsing in QSHCipher structs */
-WOLFSSL_LOCAL int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn,
-                                                      byte* out, word16* szOut);
-#ifndef NO_WOLFSSL_SERVER
-WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name);
-#endif
-
-#endif /* HAVE_QSH */
-
-#ifdef WOLFSSL_TLS13
-/* Cookie extension information - cookie data. */
-typedef struct Cookie {
-    word16 len;
-    byte   data;
-} Cookie;
-
-WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len,
-                                  byte* mac, byte macSz, int resp);
-
-
-/* Key Share - TLS v1.3 Specification */
-
-/* The KeyShare extension information - entry in a linked list. */
-typedef struct KeyShareEntry {
-    word16                group;     /* NamedGroup               */
-    byte*                 ke;        /* Key exchange data        */
-    word32                keLen;     /* Key exchange data length */
-    void*                 key;       /* Private key              */
-    word32                keyLen;    /* Private key length       */
-    byte*                 pubKey;    /* Public key               */
-    word32                pubKeyLen; /* Public key length        */
-    struct KeyShareEntry* next;      /* List pointer             */
-} KeyShareEntry;
-
-WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len,
-                                    byte* data, KeyShareEntry **kse);
-WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
-WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl);
-WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl);
-
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-#ifndef WOLFSSL_TLS13_DRAFT_18
-/* Ticket nonce - for deriving PSK.
- * Length allowed to be: 1..255. Only support 4 bytes.
- */
-typedef struct TicketNonce {
-    byte len;
-    byte data[MAX_TICKET_NONCE_SZ];
-} TicketNonce;
-#endif
-
-/* The PreSharedKey extension information - entry in a linked list. */
-typedef struct PreSharedKey {
-    word16               identityLen;             /* Length of identity */
-    byte*                identity;                /* PSK identity       */
-    word32               ticketAge;               /* Age of the ticket  */
-    byte                 cipherSuite0;            /* Cipher Suite       */
-    byte                 cipherSuite;             /* Cipher Suite       */
-    word32               binderLen;               /* Length of HMAC     */
-    byte                 binder[WC_MAX_DIGEST_SIZE]; /* HMAC of hanshake   */
-    byte                 hmac;                    /* HMAC algorithm     */
-    byte                 resumption:1;            /* Resumption PSK     */
-    byte                 chosen:1;                /* Server's choice    */
-    struct PreSharedKey* next;                    /* List pointer       */
-} PreSharedKey;
-
-WOLFSSL_LOCAL word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list,
-                                                    byte* output, byte msgType);
-WOLFSSL_LOCAL word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list,
-                                                      byte msgType);
-WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity,
-                                        word16 len, word32 age, byte hmac,
-                                        byte cipherSuite0, byte cipherSuite,
-                                        byte resumption,
-                                        PreSharedKey **preSharedKey);
-
-/* The possible Pre-Shared Key key exchange modes. */
-enum PskKeyExchangeMode {
-    PSK_KE,
-    PSK_DHE_KE
-};
-
-/* User can define this. */
-#ifndef WOLFSSL_DEF_PSK_CIPHER
-#define WOLFSSL_DEF_PSK_CIPHER    TLS_AES_128_GCM_SHA256
-#endif
-
-WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes);
-
-#ifdef WOLFSSL_EARLY_DATA
-WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max);
-#endif
-#endif /* HAVE_SESSION_TICKET || !NO_PSK */
-
-
-/* The types of keys to derive for. */
-enum DeriveKeyType {
-    no_key,
-    early_data_key,
-    handshake_key,
-    traffic_key,
-    update_traffic_key
-};
-
-/* The key update request values for KeyUpdate message. */
-enum KeyUpdateRequest {
-    update_not_requested,
-    update_requested
-};
-#endif /* WOLFSSL_TLS13 */
-
-
-#ifdef OPENSSL_EXTRA
-enum SetCBIO {
-    WOLFSSL_CBIO_NONE = 0,
-    WOLFSSL_CBIO_RECV = 0x1,
-    WOLFSSL_CBIO_SEND = 0x2, 
-};
-#endif
-
-/* wolfSSL context type */
-struct WOLFSSL_CTX {
-    WOLFSSL_METHOD* method;
-#ifdef SINGLE_THREADED
-    WC_RNG*         rng;          /* to be shared with WOLFSSL w/o locking */
-#endif
-    wolfSSL_Mutex   countMutex;   /* reference count mutex */
-    int         refCount;         /* reference count */
-    int         err;              /* error code in case of mutex not created */
-#ifndef NO_DH
-    buffer      serverDH_P;
-    buffer      serverDH_G;
-#endif
-#ifndef NO_CERTS
-    DerBuffer*  certificate;
-    DerBuffer*  certChain;
-                 /* chain after self, in DER, with leading size for each cert */
-    #ifdef OPENSSL_EXTRA
-    WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;
-    #endif
-    #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
-        defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY)
-    WOLF_STACK_OF(WOLFSSL_X509)* x509Chain;
-    #endif
-#ifdef WOLFSSL_TLS13
-    int         certChainCnt;
-#endif
-    DerBuffer*  privateKey;
-    byte        privateKeyType;
-    int         privateKeySz;
-    WOLFSSL_CERT_MANAGER* cm;      /* our cert manager, ctx owns SSL will use */
-#endif
-#ifdef KEEP_OUR_CERT
-    WOLFSSL_X509*    ourCert;     /* keep alive a X509 struct of cert */
-    int              ownOurCert;  /* Dispose of certificate if we own */
-#endif
-    Suites*     suites;           /* make dynamic, user may not need/set */
-    void*       heap;             /* for user memory overrides */
-    byte        verifyDepth;
-    byte        verifyPeer:1;
-    byte        verifyNone:1;
-    byte        failNoCert:1;
-    byte        failNoCertxPSK:1; /* fail if no cert with the exception of PSK*/
-    byte        sessionCacheOff:1;
-    byte        sessionCacheFlushOff:1;
-#ifdef HAVE_EXT_CACHE
-    byte        internalCacheOff:1;
-#endif
-    byte        sendVerify;       /* for client side (can not be single bit) */
-    byte        haveRSA:1;        /* RSA available */
-    byte        haveECC:1;        /* ECC available */
-    byte        haveDH:1;         /* server DH parms set by user */
-    byte        haveNTRU:1;       /* server private NTRU  key loaded */
-    byte        haveECDSAsig:1;   /* server cert signed w/ ECDSA */
-    byte        haveStaticECC:1;  /* static server ECC private key */
-    byte        partialWrite:1;   /* only one msg per write call */
-    byte        quietShutdown:1;  /* don't send close notify */
-    byte        groupMessages:1;  /* group handshake messages before sending */
-    byte        minDowngrade;     /* minimum downgrade version */
-    byte        haveEMS:1;        /* have extended master secret extension */
-    byte        useClientOrder:1; /* Use client's cipher preference order */
-#ifdef WOLFSSL_TLS13
-    byte        noTicketTls13:1;  /* Server won't create new Ticket */
-    byte        noPskDheKe:1;     /* Don't use (EC)DHE with PSK */
-#endif
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-    byte        postHandshakeAuth:1;  /* Post-handshake auth supported. */
-#endif
-#ifdef WOLFSSL_MULTICAST
-    byte        haveMcast;        /* multicast requested */
-    byte        mcastID;          /* multicast group ID */
-#endif
-#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
-    byte        dtlsSctp;         /* DTLS-over-SCTP mode */
-    word16      dtlsMtuSz;        /* DTLS MTU size */
-#endif
-#ifndef NO_DH
-    word16      minDhKeySz;       /* minimum DH key size */
-    word16      maxDhKeySz;       /* maximum DH key size */
-#endif
-#ifndef NO_RSA
-    short       minRsaKeySz;      /* minimum RSA key size */
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    short       minEccKeySz;      /* minimum ECC key size */
-#endif
-#ifdef OPENSSL_EXTRA
-    byte              sessionCtx[ID_LEN]; /* app session context ID */
-    word32            disabledCurves;   /* curves disabled by user */
-    unsigned long     mask;             /* store SSL_OP_ flags */
-    const unsigned char *alpn_cli_protos;/* ALPN client protocol list */
-    unsigned int         alpn_cli_protos_len;
-    byte              sessionCtxSz;
-    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
-    CallbackInfoState* CBIS;      /* used to get info about SSL state */
-#endif
-    CallbackIORecv CBIORecv;
-    CallbackIOSend CBIOSend;
-#ifdef WOLFSSL_DTLS
-    CallbackGenCookie CBIOCookie;       /* gen cookie callback */
-#ifdef WOLFSSL_SESSION_EXPORT
-    wc_dtls_export  dtls_export;        /* export function for DTLS session */
-    CallbackGetPeer CBGetPeer;
-    CallbackSetPeer CBSetPeer;
-#endif
-#endif /* WOLFSSL_DTLS */
-    VerifyCallback  verifyCallback;     /* cert verification callback */
-    word32          timeout;            /* session timeout */
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-    word32          ecdhCurveOID;       /* curve Ecc_Sum */
-#endif
-#ifdef HAVE_ECC
-    word16          eccTempKeySz;       /* in octets 20 - 66 */
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    word32          pkCurveOID;         /* curve Ecc_Sum */
-#endif
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    byte        havePSK;                /* psk key set by user */
-    wc_psk_client_callback client_psk_cb;  /* client callback */
-    wc_psk_server_callback server_psk_cb;  /* server callback */
-    char        server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
-#endif /* HAVE_SESSION_TICKET || !NO_PSK */
-#ifdef WOLFSSL_TLS13
-    word16          group[WOLFSSL_MAX_GROUP_COUNT];
-    byte            numGroups;
-#endif
-#ifdef WOLFSSL_EARLY_DATA
-    word32          maxEarlyDataSz;
-#endif
-#ifdef HAVE_ANON
-    byte        haveAnon;               /* User wants to allow Anon suites */
-#endif /* HAVE_ANON */
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    pem_password_cb* passwd_cb;
-    void*            passwd_userdata;
-#endif
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-    WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */
-    WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */
-    byte            readAhead;
-    void*           userPRFArg; /* passed to prf callback */
-#endif
-#ifdef HAVE_EX_DATA
-    void*           ex_data[MAX_EX_DATA];
-#endif
-#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
-    CallbackALPNSelect alpnSelect;
-    void*              alpnSelectArg;
-#endif
-#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)))
-    CallbackSniRecv sniRecvCb;
-    void*           sniRecvCbArg;
-#endif
-#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS)
-    CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */
-    word32      mcastFirstSeq;    /* first trigger level */
-    word32      mcastSecondSeq;   /* second tigger level */
-    word32      mcastMaxSeq;      /* max level */
-#endif
-#ifdef HAVE_OCSP
-    WOLFSSL_OCSP      ocsp;
-#endif
-    int             devId;              /* async device id to use */
-#ifdef HAVE_TLS_EXTENSIONS
-    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
-    #ifndef NO_WOLFSSL_SERVER
-        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
-         || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-            OcspRequest* certOcspRequest;
-        #endif
-        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-            OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH];
-        #endif
-    #endif
-    #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
-        SessionTicketEncCb ticketEncCb;   /* enc/dec session ticket Cb */
-        void*              ticketEncCtx;  /* session encrypt context */
-        int                ticketHint;    /* ticket hint in seconds */
-    #endif
-    #ifdef HAVE_SUPPORTED_CURVES
-        byte userCurves;                  /* indicates user called wolfSSL_CTX_UseSupportedCurve */
-    #endif
-#endif
-#ifdef ATOMIC_USER
-    CallbackMacEncrypt    MacEncryptCb;    /* Atomic User Mac/Encrypt Cb */
-    CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    #ifdef HAVE_ECC
-        CallbackEccKeyGen EccKeyGenCb;  /* User EccKeyGen Callback Handler */
-        CallbackEccSign   EccSignCb;    /* User EccSign   Callback handler */
-        CallbackEccVerify EccVerifyCb;  /* User EccVerify Callback handler */
-        CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */
-        #ifdef HAVE_ED25519
-            /* User Ed25519Sign   Callback handler */
-            CallbackEd25519Sign   Ed25519SignCb;
-            /* User Ed25519Verify Callback handler */
-            CallbackEd25519Verify Ed25519VerifyCb;
-        #endif
-        #ifdef HAVE_CURVE25519
-            /* User X25519 KeyGen Callback Handler */
-            CallbackX25519KeyGen X25519KeyGenCb;
-            /* User X25519 SharedSecret Callback handler */
-            CallbackX25519SharedSecret X25519SharedSecretCb;
-        #endif
-    #endif /* HAVE_ECC */
-    #ifndef NO_DH
-        CallbackDhAgree DhAgreeCb;      /* User DH Agree Callback handler */
-    #endif
-    #ifndef NO_RSA
-        CallbackRsaSign   RsaSignCb;      /* User RsaSign Callback handler (priv key) */
-        CallbackRsaVerify RsaVerifyCb;    /* User RsaVerify Callback handler (pub key) */
-        CallbackRsaVerify RsaSignCheckCb; /* User VerifyRsaSign Callback handler (priv key) */
-        #ifdef WC_RSA_PSS
-            CallbackRsaPssSign   RsaPssSignCb;       /* User RsaSign (priv key) */
-            CallbackRsaPssVerify RsaPssVerifyCb;     /* User RsaVerify (pub key) */
-            CallbackRsaPssVerify RsaPssSignCheckCb; /* User VerifyRsaSign (priv key) */
-        #endif
-        CallbackRsaEnc    RsaEncCb;     /* User Rsa Public Encrypt  handler */
-        CallbackRsaDec    RsaDecCb;     /* User Rsa Private Decrypt handler */
-    #endif /* NO_RSA */
-#endif /* HAVE_PK_CALLBACKS */
-#ifdef HAVE_WOLF_EVENT
-        WOLF_EVENT_QUEUE event_queue;
-#endif /* HAVE_WOLF_EVENT */
-#ifdef HAVE_EXT_CACHE
-        WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*);
-        int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*);
-        void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*);
-#endif
-#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256)
-        Srp*  srp;  /* TLS Secure Remote Password Protocol*/
-        byte* srp_password;
-#endif
-};
-
-WOLFSSL_LOCAL
-WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap);
-WOLFSSL_LOCAL
-int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*, void* heap);
-WOLFSSL_LOCAL
-void FreeSSL_Ctx(WOLFSSL_CTX*);
-WOLFSSL_LOCAL
-void SSL_CtxResourceFree(WOLFSSL_CTX*);
-
-WOLFSSL_LOCAL
-int DeriveTlsKeys(WOLFSSL* ssl);
-WOLFSSL_LOCAL
-int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
-                          word32 inSz, word16 sz);
-
-#ifndef NO_CERTS
-    WOLFSSL_LOCAL
-    int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify);
-    WOLFSSL_LOCAL
-    int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash);
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    WOLFSSL_LOCAL
-    int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify);
-    WOLFSSL_LOCAL
-    int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash);
-#endif
-#endif
-
-/* All cipher suite related info
- * Keep as a constant size (no ifdefs) for session export */
-typedef struct CipherSpecs {
-    word16 key_size;
-    word16 iv_size;
-    word16 block_size;
-    word16 aead_mac_size;
-    byte bulk_cipher_algorithm;
-    byte cipher_type;               /* block, stream, or aead */
-    byte mac_algorithm;
-    byte kea;                       /* key exchange algo */
-    byte sig_algo;
-    byte hash_size;
-    byte pad_size;
-    byte static_ecdh;
-} CipherSpecs;
-
-
-void InitCipherSpecs(CipherSpecs* cs);
-
-
-/* Supported Message Authentication Codes from page 43 */
-enum MACAlgorithm {
-    no_mac,
-    md5_mac,
-    sha_mac,
-    sha224_mac,
-    sha256_mac,     /* needs to match external KDF_MacAlgorithm */
-    sha384_mac,
-    sha512_mac,
-    rmd_mac,
-    blake2b_mac
-};
-
-
-/* Supported Key Exchange Protocols */
-enum KeyExchangeAlgorithm {
-    no_kea,
-    rsa_kea,
-    diffie_hellman_kea,
-    fortezza_kea,
-    psk_kea,
-    dhe_psk_kea,
-    ecdhe_psk_kea,
-    ntru_kea,
-    ecc_diffie_hellman_kea,
-    ecc_static_diffie_hellman_kea       /* for verify suite only */
-};
-
-
-/* Supported Authentication Schemes */
-enum SignatureAlgorithm {
-    anonymous_sa_algo = 0,
-    rsa_sa_algo       = 1,
-    dsa_sa_algo       = 2,
-    ecc_dsa_sa_algo   = 3,
-    rsa_pss_sa_algo   = 8,
-    ed25519_sa_algo   = 9
-};
-
-
-/* Supprted ECC Curve Types */
-enum EccCurves {
-    named_curve = 3
-};
-
-
-/* Valid client certificate request types from page 27 */
-enum ClientCertificateType {
-    rsa_sign            = 1,
-    dss_sign            = 2,
-    rsa_fixed_dh        = 3,
-    dss_fixed_dh        = 4,
-    rsa_ephemeral_dh    = 5,
-    dss_ephemeral_dh    = 6,
-    fortezza_kea_cert   = 20,
-    ecdsa_sign          = 64,
-    rsa_fixed_ecdh      = 65,
-    ecdsa_fixed_ecdh    = 66
-};
-
-
-enum CipherType { stream, block, aead };
-
-
-
-
-
-
-/* cipher for now */
-typedef struct Ciphers {
-#ifdef BUILD_ARC4
-    Arc4*   arc4;
-#endif
-#ifdef BUILD_DES3
-    Des3*   des3;
-#endif
-#if defined(BUILD_AES) || defined(BUILD_AESGCM)
-    Aes*    aes;
-    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) || defined(WOLFSSL_TLS13)
-        byte* additional;
-        byte* nonce;
-    #endif
-#endif
-#ifdef HAVE_CAMELLIA
-    Camellia* cam;
-#endif
-#ifdef HAVE_CHACHA
-    ChaCha*   chacha;
-#endif
-#ifdef HAVE_HC128
-    HC128*  hc128;
-#endif
-#ifdef BUILD_RABBIT
-    Rabbit* rabbit;
-#endif
-#ifdef HAVE_IDEA
-    Idea* idea;
-#endif
-    byte    state;
-    byte    setup;       /* have we set it up flag for detection */
-} Ciphers;
-
-
-#ifdef HAVE_ONE_TIME_AUTH
-/* Ciphers for one time authentication such as poly1305 */
-typedef struct OneTimeAuth {
-#ifdef HAVE_POLY1305
-    Poly1305* poly1305;
-#endif
-    byte    setup;      /* flag for if a cipher has been set */
-
-} OneTimeAuth;
-#endif
-
-
-WOLFSSL_LOCAL void InitCiphers(WOLFSSL* ssl);
-WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl);
-
-
-/* hashes type */
-typedef struct Hashes {
-    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
-        byte md5[WC_MD5_DIGEST_SIZE];
-    #endif
-    #if !defined(NO_SHA)
-        byte sha[WC_SHA_DIGEST_SIZE];
-    #endif
-    #ifndef NO_SHA256
-        byte sha256[WC_SHA256_DIGEST_SIZE];
-    #endif
-    #ifdef WOLFSSL_SHA384
-        byte sha384[WC_SHA384_DIGEST_SIZE];
-    #endif
-    #ifdef WOLFSSL_SHA512
-        byte sha512[WC_SHA512_DIGEST_SIZE];
-    #endif
-} Hashes;
-
-WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
-
-#ifdef WOLFSSL_TLS13
-typedef union Digest {
-#ifndef NO_WOLFSSL_SHA256
-    wc_Sha256 sha256;
-#endif
-#ifdef WOLFSSL_SHA384
-    wc_Sha384 sha384;
-#endif
-#ifdef WOLFSSL_SHA512
-    wc_Sha512 sha512;
-#endif
-} Digest;
-#endif
-
-/* Static x509 buffer */
-typedef struct x509_buffer {
-    int  length;                  /* actual size */
-    byte buffer[MAX_X509_SIZE];   /* max static cert size */
-} x509_buffer;
-
-
-/* wolfSSL X509_CHAIN, for no dynamic memory SESSION_CACHE */
-struct WOLFSSL_X509_CHAIN {
-    int         count;                    /* total number in chain */
-    x509_buffer certs[MAX_CHAIN_DEPTH];   /* only allow max depth 4 for now */
-};
-
-
-/* wolfSSL session type */
-struct WOLFSSL_SESSION {
-    word32             bornOn;                    /* create time in seconds   */
-    word32             timeout;                   /* timeout in seconds       */
-    byte               sessionID[ID_LEN];         /* id for protocol          */
-    byte               sessionIDSz;
-    byte               masterSecret[SECRET_LEN];  /* stored secret            */
-    word16             haveEMS;                   /* ext master secret flag   */
-#ifdef SESSION_CERTS
-    WOLFSSL_X509_CHAIN chain;                     /* peer cert chain, static  */
-    #ifdef WOLFSSL_ALT_CERT_CHAINS
-    WOLFSSL_X509_CHAIN altChain;                  /* peer alt cert chain, static */
-    #endif
-#endif
-#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
-                               defined(HAVE_SESSION_TICKET))
-    ProtocolVersion    version;                   /* which version was used   */
-    byte               cipherSuite0;              /* first byte, normally 0   */
-    byte               cipherSuite;               /* 2nd byte, actual suite   */
-#endif
-#ifndef NO_CLIENT_CACHE
-    word16             idLen;                     /* serverID length          */
-    byte               serverID[SERVER_ID_LEN];   /* for easier client lookup */
-#endif
-#ifdef OPENSSL_EXTRA
-    byte               sessionCtxSz;              /* sessionCtx length        */
-    byte               sessionCtx[ID_LEN];        /* app specific context id  */
-#endif
-#ifdef WOLFSSL_TLS13
-    word16             namedGroup;
-#endif
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    #ifdef WOLFSSL_TLS13
-    word32             ticketSeen;                /* Time ticket seen (ms) */
-    word32             ticketAdd;                 /* Added by client */
-        #ifndef WOLFSSL_TLS13_DRAFT_18
-    TicketNonce        ticketNonce;               /* Nonce used to derive PSK */
-        #endif
-    #endif
-    #ifdef WOLFSSL_EARLY_DATA
-    word32             maxEarlyDataSz;
-    #endif
-#endif
-#ifdef HAVE_SESSION_TICKET
-    byte*              ticket;
-    word16             ticketLen;
-    byte               staticTicket[SESSION_TICKET_LEN];
-    byte               isDynamic;
-#endif
-#ifdef HAVE_EXT_CACHE
-    byte               isAlloced;
-#endif
-#ifdef HAVE_EX_DATA
-    void*              ex_data[MAX_EX_DATA];
-#endif
-};
-
-
-WOLFSSL_LOCAL
-WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte);
-WOLFSSL_LOCAL
-int          SetSession(WOLFSSL*, WOLFSSL_SESSION*);
-
-typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int);
-
-#ifndef NO_CLIENT_CACHE
-    WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int);
-#endif
-
-/* client connect state for nonblocking restart */
-enum ConnectState {
-    CONNECT_BEGIN = 0,
-    CLIENT_HELLO_SENT,
-    HELLO_AGAIN,               /* HELLO_AGAIN s for DTLS case */
-    HELLO_AGAIN_REPLY,
-    FIRST_REPLY_DONE,
-    FIRST_REPLY_FIRST,
-    FIRST_REPLY_SECOND,
-    FIRST_REPLY_THIRD,
-    FIRST_REPLY_FOURTH,
-    FINISHED_DONE,
-    SECOND_REPLY_DONE
-};
-
-
-/* server accept state for nonblocking restart */
-enum AcceptState {
-    ACCEPT_BEGIN = 0,
-    ACCEPT_CLIENT_HELLO_DONE,
-    ACCEPT_HELLO_RETRY_REQUEST_DONE,
-    ACCEPT_FIRST_REPLY_DONE,
-    SERVER_HELLO_SENT,
-    SERVER_EXTENSIONS_SENT,
-    CERT_SENT,
-    CERT_VERIFY_SENT,
-    CERT_STATUS_SENT,
-    KEY_EXCHANGE_SENT,
-    CERT_REQ_SENT,
-    SERVER_HELLO_DONE,
-    ACCEPT_SECOND_REPLY_DONE,
-    TICKET_SENT,
-    CHANGE_CIPHER_SENT,
-    ACCEPT_FINISHED_DONE,
-    ACCEPT_THIRD_REPLY_DONE
-};
-
-/* TLS 1.3 server accept state for nonblocking restart */
-enum AcceptStateTls13 {
-    TLS13_ACCEPT_BEGIN = 0,
-    TLS13_ACCEPT_CLIENT_HELLO_DONE,
-    TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE,
-    TLS13_ACCEPT_FIRST_REPLY_DONE,
-    TLS13_ACCEPT_SECOND_REPLY_DONE,
-    TLS13_SERVER_HELLO_SENT,
-    TLS13_ACCEPT_THIRD_REPLY_DONE,
-    TLS13_SERVER_EXTENSIONS_SENT,
-    TLS13_CERT_REQ_SENT,
-    TLS13_CERT_SENT,
-    TLS13_CERT_VERIFY_SENT,
-    TLS13_ACCEPT_FINISHED_SENT,
-    TLS13_PRE_TICKET_SENT,
-    TLS13_ACCEPT_FINISHED_DONE,
-    TLS13_TICKET_SENT
-};
-
-/* buffers for struct WOLFSSL */
-typedef struct Buffers {
-    bufferStatic    inputBuffer;
-    bufferStatic    outputBuffer;
-    buffer          domainName;            /* for client check */
-    buffer          clearOutputBuffer;
-    buffer          sig;                   /* signature data */
-    buffer          digest;                /* digest data */
-    int             prevSent;              /* previous plain text bytes sent
-                                              when got WANT_WRITE            */
-    int             plainSz;               /* plain text bytes in buffer to send
-                                              when got WANT_WRITE            */
-    byte            weOwnCert;             /* SSL own cert flag */
-    byte            weOwnCertChain;        /* SSL own cert chain flag */
-    byte            weOwnKey;              /* SSL own key  flag */
-    byte            weOwnDH;               /* SSL own dh (p,g)  flag */
-#ifndef NO_DH
-    buffer          serverDH_P;            /* WOLFSSL_CTX owns, unless we own */
-    buffer          serverDH_G;            /* WOLFSSL_CTX owns, unless we own */
-    buffer          serverDH_Pub;
-    buffer          serverDH_Priv;
-    DhKey*          serverDH_Key;
-#endif
-#ifndef NO_CERTS
-    DerBuffer*      certificate;           /* WOLFSSL_CTX owns, unless we own */
-    DerBuffer*      key;                   /* WOLFSSL_CTX owns, unless we own */
-    byte            keyType;               /* Type of key: RSA, ECC, Ed25519 */
-    int             keySz;                 /* Size of RSA key */
-    DerBuffer*      certChain;             /* WOLFSSL_CTX owns, unless we own */
-                 /* chain after self, in DER, with leading size for each cert */
-#ifdef WOLFSSL_TLS13
-    int             certChainCnt;
-    DerBuffer*      certExts;
-#endif
-#endif
-#ifdef WOLFSSL_SEND_HRR_COOKIE
-    buffer          tls13CookieSecret;     /* HRR cookie secret */
-#endif
-#ifdef WOLFSSL_DTLS
-    WOLFSSL_DTLS_CTX dtlsCtx;              /* DTLS connection context */
-    #ifndef NO_WOLFSSL_SERVER
-        buffer       dtlsCookieSecret;     /* DTLS cookie secret */
-    #endif /* NO_WOLFSSL_SERVER */
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    #ifdef HAVE_ECC
-        buffer peerEccDsaKey;              /* we own for Ecc Verify Callbacks */
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        buffer peerEd25519Key;             /* for Ed25519 Verify Callbacks */
-    #endif /* HAVE_ED25519 */
-    #ifndef NO_RSA
-        buffer peerRsaKey;                 /* we own for Rsa Verify Callbacks */
-    #endif /* NO_RSA */
-#endif /* HAVE_PK_CALLBACKS */
-} Buffers;
-
-/* sub-states for send/do key share (key exchange) */
-enum asyncState {
-    TLS_ASYNC_BEGIN = 0,
-    TLS_ASYNC_BUILD,
-    TLS_ASYNC_DO,
-    TLS_ASYNC_VERIFY,
-    TLS_ASYNC_FINALIZE,
-    TLS_ASYNC_END
-};
-
-/* sub-states for build message */
-enum buildMsgState {
-    BUILD_MSG_BEGIN = 0,
-    BUILD_MSG_SIZE,
-    BUILD_MSG_HASH,
-    BUILD_MSG_VERIFY_MAC,
-    BUILD_MSG_ENCRYPT,
-};
-
-/* sub-states for cipher operations */
-enum cipherState {
-    CIPHER_STATE_BEGIN = 0,
-    CIPHER_STATE_DO,
-    CIPHER_STATE_END,
-};
-
-typedef struct Options {
-#ifndef NO_PSK
-    wc_psk_client_callback client_psk_cb;
-    wc_psk_server_callback server_psk_cb;
-#endif /* NO_PSK */
-#ifdef OPENSSL_EXTRA
-    unsigned long     mask; /* store SSL_OP_ flags */
-#endif
-
-    /* on/off or small bit flags, optimize layout */
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    word16            havePSK:1;            /* psk key set by user */
-#endif /* HAVE_SESSION_TICKET || !NO_PSK */
-    word16            sendVerify:2;     /* false = 0, true = 1, sendBlank = 2 */
-    word16            sessionCacheOff:1;
-    word16            sessionCacheFlushOff:1;
-#ifdef HAVE_EXT_CACHE
-    word16            internalCacheOff:1;
-#endif
-    word16            side:1;             /* client or server end */
-    word16            verifyPeer:1;
-    word16            verifyNone:1;
-    word16            failNoCert:1;
-    word16            failNoCertxPSK:1;   /* fail for no cert except with PSK */
-    word16            downgrade:1;        /* allow downgrade of versions */
-    word16            resuming:1;
-    word16            haveSessionId:1;    /* server may not send */
-    word16            tls:1;              /* using TLS ? */
-    word16            tls1_1:1;           /* using TLSv1.1+ ? */
-    word16            tls1_3:1;           /* using TLSv1.3+ ? */
-    word16            dtls:1;             /* using datagrams ? */
-    word16            connReset:1;        /* has the peer reset */
-    word16            isClosed:1;         /* if we consider conn closed */
-    word16            closeNotify:1;      /* we've received a close notify */
-    word16            sentNotify:1;       /* we've sent a close notify */
-    word16            usingCompression:1; /* are we using compression */
-    word16            haveRSA:1;          /* RSA available */
-    word16            haveECC:1;          /* ECC available */
-    word16            haveDH:1;           /* server DH parms set by user */
-    word16            haveNTRU:1;         /* server NTRU  private key loaded */
-    word16            haveQSH:1;          /* have QSH ability */
-    word16            haveECDSAsig:1;     /* server ECDSA signed cert */
-    word16            haveStaticECC:1;    /* static server ECC private key */
-    word16            havePeerCert:1;     /* do we have peer's cert */
-    word16            havePeerVerify:1;   /* and peer's cert verify */
-    word16            usingPSK_cipher:1;  /* are using psk as cipher */
-    word16            usingAnon_cipher:1; /* are we using an anon cipher */
-    word16            noPskDheKe:1;       /* Don't use (EC)DHE with PSK */
-    word16            sendAlertState:1;   /* nonblocking resume */
-    word16            partialWrite:1;     /* only one msg per write call */
-    word16            quietShutdown:1;    /* don't send close notify */
-    word16            certOnly:1;         /* stop once we get cert */
-    word16            groupMessages:1;    /* group handshake messages */
-    word16            saveArrays:1;       /* save array Memory for user get keys
-                                           or psk */
-    word16            weOwnRng:1;         /* will be true unless CTX owns */
-    word16            haveEMS:1;          /* using extended master secret */
-#ifdef HAVE_POLY1305
-    word16            oldPoly:1;        /* set when to use old rfc way of poly*/
-#endif
-#ifdef HAVE_ANON
-    word16            haveAnon:1;       /* User wants to allow Anon suites */
-#endif
-#ifdef HAVE_SESSION_TICKET
-    word16            createTicket:1;     /* Server to create new Ticket */
-    word16            useTicket:1;        /* Use Ticket not session cache */
-    word16            rejectTicket:1;     /* Callback rejected ticket */
-#ifdef WOLFSSL_TLS13
-    word16            noTicketTls13:1;    /* Server won't create new Ticket */
-#endif
-#endif
-#ifdef WOLFSSL_DTLS
-    word16            dtlsUseNonblock:1;  /* are we using nonblocking socket */
-    word16            dtlsHsRetain:1;     /* DTLS retaining HS data */
-    word16            haveMcast:1;        /* using multicast ? */
-#ifdef WOLFSSL_SCTP
-    word16            dtlsSctp:1;         /* DTLS-over-SCTP mode */
-#endif
-#endif
-#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES)
-    word16            userCurves:1;       /* indicates user called wolfSSL_UseSupportedCurve */
-#endif
-    word16            keepResources:1;    /* Keep resources after handshake */
-    word16            useClientOrder:1;   /* Use client's cipher order */
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-    word16            postHandshakeAuth:1;/* Client send post_handshake_auth
-                                           * extendion. */
-#endif
-#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
-    word16            sendCookie:1;       /* Server creates a Cookie in HRR */
-#endif
-#ifdef WOLFSSL_ALT_CERT_CHAINS
-    word16            usingAltCertChain:1;/* Alternate cert chain was used */
-#endif
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
-    word16            sentChangeCipher:1; /* Change Cipher Spec sent */
-#endif
-#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
-                                                !defined(NO_ED25519_CLIENT_AUTH)
-    word16            cacheMessages:1;    /* Cache messages for sign/verify */
-#endif
-
-    /* need full byte values for this section */
-    byte            processReply;           /* nonblocking resume */
-    byte            cipherSuite0;           /* first byte, normally 0 */
-    byte            cipherSuite;            /* second byte, actual suite */
-    byte            serverState;
-    byte            clientState;
-    byte            handShakeState;
-    byte            handShakeDone;      /* at least one handshake complete */
-    byte            minDowngrade;       /* minimum downgrade version */
-    byte            connectState;       /* nonblocking resume */
-    byte            acceptState;        /* nonblocking resume */
-    byte            asyncState;         /* sub-state for enum asyncState */
-    byte            buildMsgState;      /* sub-state for enum buildMsgState */
-    byte            alertCount;         /* detect warning dos attempt */
-#ifdef WOLFSSL_MULTICAST
-    word16          mcastID;            /* Multicast group ID */
-#endif
-#ifndef NO_DH
-    word16          minDhKeySz;         /* minimum DH key size */
-    word16          maxDhKeySz;         /* minimum DH key size */
-    word16          dhKeySz;            /* actual DH key size */
-#endif
-#ifndef NO_RSA
-    short           minRsaKeySz;      /* minimum RSA key size */
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    short           minEccKeySz;      /* minimum ECC key size */
-#endif
-#ifdef OPENSSL_EXTRA
-    byte            verifyDepth;      /* maximum verification depth */
-#endif
-#ifdef WOLFSSL_EARLY_DATA
-    word16          pskIdIndex;
-    word32          maxEarlyDataSz;
-#endif
-#ifdef WOLFSSL_TLS13
-    byte            oldMinor;          /* client preferred version < TLS 1.3 */
-#endif
-} Options;
-
-typedef struct Arrays {
-    byte*           pendingMsg;         /* defrag buffer */
-    byte*           preMasterSecret;
-    word32          preMasterSz;        /* differs for DH, actual size */
-    word32          pendingMsgSz;       /* defrag buffer size */
-    word32          pendingMsgOffset;   /* current offset into defrag buffer */
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
-    word32          psk_keySz;          /* actual size */
-    char            client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN];
-    char            server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
-    byte            psk_key[MAX_PSK_KEY_LEN];
-#endif
-    byte            clientRandom[RAN_LEN];
-    byte            serverRandom[RAN_LEN];
-    byte            sessionID[ID_LEN];
-    byte            sessionIDSz;
-#ifdef WOLFSSL_TLS13
-    byte            clientSecret[SECRET_LEN];
-    byte            serverSecret[SECRET_LEN];
-    byte            secret[SECRET_LEN];
-#endif
-    byte            masterSecret[SECRET_LEN];
-#ifdef WOLFSSL_DTLS
-    byte            cookie[MAX_COOKIE_LEN];
-    byte            cookieSz;
-#endif
-    byte            pendingMsgType;    /* defrag buffer message type */
-} Arrays;
-
-#ifndef ASN_NAME_MAX
-#define ASN_NAME_MAX 256
-#endif
-
-#ifndef MAX_DATE_SZ
-#define MAX_DATE_SZ 32
-#endif
-
-struct WOLFSSL_STACK {
-    unsigned long num; /* number of nodes in stack
-                        * (saftey measure for freeing and shortcut for count) */
-    union {
-        WOLFSSL_X509*        x509;
-        WOLFSSL_X509_NAME*   name;
-        WOLFSSL_BIO*         bio;
-        WOLFSSL_ASN1_OBJECT* obj;
-        char*                string;
-    } data;
-    WOLFSSL_STACK* next;
-};
-
-
-struct WOLFSSL_X509_NAME {
-    char  *name;
-    int   dynamicName;
-    int   sz;
-    char  staticName[ASN_NAME_MAX];
-#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
-    !defined(NO_ASN)
-    DecodedName fullName;
-    WOLFSSL_X509_NAME_ENTRY cnEntry;
-    WOLFSSL_X509_NAME_ENTRY extra[MAX_NAME_ENTRIES]; /* extra entries added */
-    WOLFSSL_X509*           x509;   /* x509 that struct belongs to */
-#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
-    byte  raw[ASN_NAME_MAX];
-    int   rawLen;
-#endif
-};
-
-#ifndef EXTERNAL_SERIAL_SIZE
-    #define EXTERNAL_SERIAL_SIZE 32
-#endif
-
-#ifdef NO_ASN
-    typedef struct DNS_entry DNS_entry;
-#endif
-
-struct WOLFSSL_X509 {
-    int              version;
-    int              serialSz;
-#ifdef WOLFSSL_SEP
-    int              deviceTypeSz;
-    int              hwTypeSz;
-    byte             deviceType[EXTERNAL_SERIAL_SIZE];
-    byte             hwType[EXTERNAL_SERIAL_SIZE];
-    int              hwSerialNumSz;
-    byte             hwSerialNum[EXTERNAL_SERIAL_SIZE];
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        byte             certPolicySet;
-        byte             certPolicyCrit;
-    #endif /* OPENSSL_EXTRA */
-#endif
-    int              notBeforeSz;
-    int              notAfterSz;
-    byte             notBefore[MAX_DATE_SZ];
-    byte             notAfter[MAX_DATE_SZ];
-    buffer           sig;
-    int              sigOID;
-    DNS_entry*       altNames;                       /* alt names list */
-    buffer           pubKey;
-    int              pubKeyOID;
-    DNS_entry*       altNamesNext;                   /* hint for retrieval */
-    #if defined(HAVE_ECC) || defined(HAVE_ED25519)
-        word32       pkCurveOID;
-    #endif /* HAVE_ECC */
-    #ifndef NO_CERTS
-        DerBuffer*   derCert;                        /* may need  */
-    #endif
-    void*            heap;                           /* heap hint */
-    byte             dynamicMemory;                  /* dynamic memory flag */
-    byte             isCa:1;
-#ifdef WOLFSSL_CERT_EXT
-    char             certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
-    int              certPoliciesNb;
-#endif /* WOLFSSL_CERT_EXT */
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-#ifdef HAVE_EX_DATA
-    void*            ex_data[MAX_EX_DATA];
-#endif
-    byte*            authKeyId;
-    byte*            subjKeyId;
-    byte*            extKeyUsageSrc;
-    byte*            CRLInfo;
-    byte*            authInfo;
-    word32           pathLength;
-    word16           keyUsage;
-    int              CRLInfoSz;
-    int              authInfoSz;
-    word32           authKeyIdSz;
-    word32           subjKeyIdSz;
-    word32           extKeyUsageSz;
-    word32           extKeyUsageCount;
-
-    byte             CRLdistSet:1;
-    byte             CRLdistCrit:1;
-    byte             authInfoSet:1;
-    byte             authInfoCrit:1;
-    byte             keyUsageSet:1;
-    byte             keyUsageCrit:1;
-    byte             extKeyUsageCrit:1;
-    byte             subjKeyIdSet:1;
-
-    byte             subjKeyIdCrit:1;
-    byte             basicConstSet:1;
-    byte             basicConstCrit:1;
-    byte             basicConstPlSet:1;
-    byte             subjAltNameSet:1;
-    byte             subjAltNameCrit:1;
-    byte             authKeyIdSet:1;
-    byte             authKeyIdCrit:1;
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-    byte             serial[EXTERNAL_SERIAL_SIZE];
-    char             subjectCN[ASN_NAME_MAX];        /* common name short cut */
-#ifdef WOLFSSL_CERT_REQ
-    char             challengePw[CTC_NAME_SIZE]; /* for REQ certs */
-#endif
-    WOLFSSL_X509_NAME issuer;
-    WOLFSSL_X509_NAME subject;
-};
-
-
-/* record layer header for PlainText, Compressed, and CipherText */
-typedef struct RecordLayerHeader {
-    byte            type;
-    byte            pvMajor;
-    byte            pvMinor;
-    byte            length[2];
-} RecordLayerHeader;
-
-
-/* record layer header for DTLS PlainText, Compressed, and CipherText */
-typedef struct DtlsRecordLayerHeader {
-    byte            type;
-    byte            pvMajor;
-    byte            pvMinor;
-    byte            sequence_number[8];   /* per record */
-    byte            length[2];
-} DtlsRecordLayerHeader;
-
-
-typedef struct DtlsFrag {
-    word32 begin;
-    word32 end;
-    struct DtlsFrag* next;
-} DtlsFrag;
-
-
-typedef struct DtlsMsg {
-    struct DtlsMsg* next;
-    byte*           buf;
-    byte*           msg;
-    DtlsFrag*       fragList;
-    word32          fragSz;    /* Length of fragments received */
-    word32          seq;       /* Handshake sequence number    */
-    word32          sz;        /* Length of whole mesage       */
-    byte            type;
-} DtlsMsg;
-
-
-#ifdef HAVE_NETX
-
-    /* NETX I/O Callback default */
-    typedef struct NetX_Ctx {
-        NX_TCP_SOCKET* nxSocket;    /* send/recv socket handle */
-        NX_PACKET*     nxPacket;    /* incoming packet handle for short reads */
-        ULONG          nxOffset;    /* offset already read from nxPacket */
-        ULONG          nxWait;      /* wait option flag */
-    } NetX_Ctx;
-
-#endif
-
-
-/* Handshake messages received from peer (plus change cipher */
-typedef struct MsgsReceived {
-    word16 got_hello_request:1;
-    word16 got_client_hello:2;
-    word16 got_server_hello:2;
-    word16 got_hello_verify_request:1;
-    word16 got_session_ticket:1;
-    word16 got_end_of_early_data:1;
-    word16 got_hello_retry_request:1;
-    word16 got_encrypted_extensions:1;
-    word16 got_certificate:1;
-    word16 got_certificate_status:1;
-    word16 got_server_key_exchange:1;
-    word16 got_certificate_request:1;
-    word16 got_server_hello_done:1;
-    word16 got_certificate_verify:1;
-    word16 got_client_key_exchange:1;
-    word16 got_finished:1;
-    word16 got_key_update:1;
-    word16 got_change_cipher:1;
-} MsgsReceived;
-
-
-/* Handshake hashes */
-typedef struct HS_Hashes {
-    Hashes          verifyHashes;
-    Hashes          certHashes;         /* for cert verify */
-#ifndef NO_SHA
-    wc_Sha          hashSha;            /* sha hash of handshake msgs */
-#endif
-#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
-    wc_Md5          hashMd5;            /* md5 hash of handshake msgs */
-#endif
-#ifndef NO_SHA256
-    wc_Sha256       hashSha256;         /* sha256 hash of handshake msgs */
-#endif
-#ifdef WOLFSSL_SHA384
-    wc_Sha384       hashSha384;         /* sha384 hash of handshake msgs */
-#endif
-#ifdef WOLFSSL_SHA512
-    wc_Sha512       hashSha512;         /* sha512 hash of handshake msgs */
-#endif
-#if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
-    byte*           messages;           /* handshake messages */
-    int             length;             /* length of handhsake messages' data */
-    int             prevLen;            /* length of messages but last */
-#endif
-} HS_Hashes;
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #define MAX_ASYNC_ARGS 18
-    typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs);
-
-    struct WOLFSSL_ASYNC {
-        WC_ASYNC_DEV* dev;
-        FreeArgsCb    freeArgs; /* function pointer to cleanup args */
-        word32        args[MAX_ASYNC_ARGS]; /* holder for current args */
-    };
-#endif
-
-#ifdef HAVE_WRITE_DUP
-
-    #define WRITE_DUP_SIDE 1
-    #define READ_DUP_SIDE 2
-
-    typedef struct WriteDup {
-        wolfSSL_Mutex   dupMutex;       /* reference count mutex */
-        int             dupCount;       /* reference count */
-        int             dupErr;         /* under dupMutex, pass to other side */
-    } WriteDup;
-
-    WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl);
-    WOLFSSL_LOCAL int  NotifyWriteSide(WOLFSSL* ssl, int err);
-#endif /* HAVE_WRITE_DUP */
-
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-typedef struct CertReqCtx CertReqCtx;
-
-struct CertReqCtx {
-    CertReqCtx* next;
-    byte        len;
-    byte        ctx;
-};
-#endif
-
-#ifdef WOLFSSL_EARLY_DATA
-typedef enum EarlyDataState {
-    no_early_data,
-    expecting_early_data,
-    process_early_data,
-    done_early_data
-} EarlyDataState;
-#endif
-
-/* wolfSSL ssl type */
-struct WOLFSSL {
-    WOLFSSL_CTX*    ctx;
-    Suites*         suites;             /* only need during handshake */
-    Arrays*         arrays;
-    HS_Hashes*      hsHashes;
-    void*           IOCB_ReadCtx;
-    void*           IOCB_WriteCtx;
-    WC_RNG*         rng;
-    void*           verifyCbCtx;        /* cert verify callback user ctx*/
-    VerifyCallback  verifyCallback;     /* cert verification callback */
-    void*           heap;               /* for user overrides */
-#ifdef HAVE_WRITE_DUP
-    WriteDup*       dupWrite;           /* valid pointer indicates ON */
-             /* side that decrements dupCount to zero frees overall structure */
-    byte            dupSide;            /* write side or read side */
-#endif
-#ifdef OPENSSL_EXTRA
-    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
-#endif
-    CallbackIORecv  CBIORecv;
-    CallbackIOSend  CBIOSend;
-#ifdef WOLFSSL_STATIC_MEMORY
-    WOLFSSL_HEAP_HINT heap_hint;
-#endif
-#ifndef NO_HANDSHAKE_DONE_CB
-    HandShakeDoneCb hsDoneCb;          /*  notify user handshake done */
-    void*           hsDoneCtx;         /*  user handshake cb context  */
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    struct WOLFSSL_ASYNC async;
-#elif defined(WOLFSSL_NONBLOCK_OCSP)
-    void*           nonblockarg;        /* dynamic arg for handling non-block resume */
-#endif
-    void*           hsKey;              /* Handshake key (RsaKey or ecc_key) allocated from heap */
-    word32          hsType;             /* Type of Handshake key (hsKey) */
-    WOLFSSL_CIPHER  cipher;
-    hmacfp          hmac;
-    Ciphers         encrypt;
-    Ciphers         decrypt;
-    Buffers         buffers;
-    WOLFSSL_SESSION session;
-#ifdef HAVE_EXT_CACHE
-    WOLFSSL_SESSION* extSession;
-#endif
-    WOLFSSL_ALERT_HISTORY alert_history;
-    int             error;
-    int             rfd;                /* read  file descriptor */
-    int             wfd;                /* write file descriptor */
-    int             rflags;             /* user read  flags */
-    int             wflags;             /* user write flags */
-    word32          timeout;            /* session timeout */
-    word32          fragOffset;         /* fragment offset */
-    word16          curSize;
-    byte            verifyDepth;
-    RecordLayerHeader curRL;
-    MsgsReceived    msgsReceived;       /* peer messages received */
-    ProtocolVersion version;            /* negotiated version */
-    ProtocolVersion chVersion;          /* client hello version */
-    CipherSpecs     specs;
-    Keys            keys;
-    Options         options;
-#ifdef OPENSSL_EXTRA
-    CallbackInfoState* CBIS;             /* used to get info about SSL state */
-    int              cbmode;             /* read or write on info callback */
-    int              cbtype;             /* event type in info callback */
-    WOLFSSL_BIO*     biord;              /* socket bio read  to free/close */
-    WOLFSSL_BIO*     biowr;              /* socket bio write to free/close */
-    byte             sessionCtx[ID_LEN]; /* app session context ID */
-    unsigned long    peerVerifyRet;
-    byte             readAhead;
-    byte             sessionCtxSz;       /* size of sessionCtx stored */
-#ifdef HAVE_PK_CALLBACKS
-    void*            loggingCtx;         /* logging callback argument */
-#endif
-#endif /* OPENSSL_EXTRA */
-#ifndef NO_RSA
-    RsaKey*         peerRsaKey;
-    byte            peerRsaKeyPresent;
-#endif
-#ifdef HAVE_QSH
-    QSHKey*         QSH_Key;
-    QSHKey*         peerQSHKey;
-    QSHSecret*      QSH_secret;
-    byte            isQSH;             /* is the handshake a QSH? */
-    byte            sendQSHKeys;       /* flag for if the client should sen
-                                          public keys */
-    byte            peerQSHKeyPresent;
-    byte            minRequest;
-    byte            maxRequest;
-    byte            user_set_QSHSchemes;
-#endif
-#ifdef WOLFSSL_TLS13
-    word16          namedGroup;
-    word16          group[WOLFSSL_MAX_GROUP_COUNT];
-    byte            numGroups;
-#endif
-    byte            pssAlgo;
-#ifdef WOLFSSL_TLS13
-    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
-    word16          certHashSigAlgoSz;  /* SigAlgoCert ext length in bytes */
-    byte            certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to
-                                                           * offer */
-    #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
-#endif
-#ifdef HAVE_NTRU
-    word16          peerNtruKeyLen;
-    byte            peerNtruKey[MAX_NTRU_PUB_KEY_SZ];
-    byte            peerNtruKeyPresent;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    int             eccVerifyRes;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
-    word32          ecdhCurveOID;            /* curve Ecc_Sum     */
-    ecc_key*        eccTempKey;              /* private ECDHE key */
-    byte            eccTempKeyPresent;       /* also holds type */
-    byte            peerEccKeyPresent;
-#endif
-#ifdef HAVE_ECC
-    ecc_key*        peerEccKey;              /* peer's  ECDHE key */
-    ecc_key*        peerEccDsaKey;           /* peer's  ECDSA key */
-    word16          eccTempKeySz;            /* in octets 20 - 66 */
-    byte            peerEccDsaKeyPresent;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    word32          pkCurveOID;              /* curve Ecc_Sum     */
-#endif
-#ifdef HAVE_ED25519
-    ed25519_key*    peerEd25519Key;
-    byte            peerEd25519KeyPresent;
-#endif
-#ifdef HAVE_CURVE25519
-    curve25519_key* peerX25519Key;
-    byte            peerX25519KeyPresent;
-#endif
-#ifdef HAVE_LIBZ
-    z_stream        c_stream;           /* compression   stream */
-    z_stream        d_stream;           /* decompression stream */
-    byte            didStreamInit;      /* for stream init and end */
-#endif
-#ifdef WOLFSSL_DTLS
-    int             dtls_timeout_init;  /* starting timeout value */
-    int             dtls_timeout_max;   /* maximum timeout value */
-    int             dtls_timeout;       /* current timeout value, changes */
-    word32          dtls_tx_msg_list_sz;
-    word32          dtls_rx_msg_list_sz;
-    DtlsMsg*        dtls_tx_msg_list;
-    DtlsMsg*        dtls_rx_msg_list;
-    void*           IOCB_CookieCtx;     /* gen cookie ctx */
-    word32          dtls_expected_rx;
-#ifdef WOLFSSL_SESSION_EXPORT
-    wc_dtls_export  dtls_export;        /* export function for session */
-#endif
-#ifdef WOLFSSL_SCTP
-    word16          dtlsMtuSz;
-#endif /* WOLFSSL_SCTP */
-#ifdef WOLFSSL_MULTICAST
-    void*           mcastHwCbCtx;       /* Multicast highwater callback ctx */
-#endif /* WOLFSSL_MULTICAST */
-#ifdef WOLFSSL_DTLS_DROP_STATS
-    word32 macDropCount;
-    word32 replayDropCount;
-#endif /* WOLFSSL_DTLS_DROP_STATS */
-#endif /* WOLFSSL_DTLS */
-#ifdef WOLFSSL_CALLBACKS
-    TimeoutInfo     timeoutInfo;        /* info saved during handshake */
-    HandShakeInfo   handShakeInfo;      /* info saved during handshake */
-#endif
-#ifdef OPENSSL_EXTRA
-    SSL_Msg_Cb      protoMsgCb;         /* inspect protocol message callback */
-    void*           protoMsgCtx;        /* user set context with msg callback */
-#endif
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-    byte            hsInfoOn;           /* track handshake info        */
-    byte            toInfoOn;           /* track timeout   info        */
-#endif
-#ifdef HAVE_FUZZER
-    CallbackFuzzer  fuzzerCb;           /* for testing with using fuzzer */
-    void*           fuzzerCtx;          /* user defined pointer */
-#endif
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-    CertReqCtx*     certReqCtx;
-#endif
-#ifdef KEEP_PEER_CERT
-    WOLFSSL_X509     peerCert;           /* X509 peer cert */
-#endif
-#ifdef KEEP_OUR_CERT
-    WOLFSSL_X509*    ourCert;            /* keep alive a X509 struct of cert.
-                                            points to ctx if not owned (owned
-                                            flag found in buffers.weOwnCert) */
-#endif
-    byte             keepCert;           /* keep certificate after handshake */
-#if defined(HAVE_EX_DATA) || defined(FORTRESS)
-    void*            ex_data[MAX_EX_DATA]; /* external data, for Fortress */
-#endif
-    int              devId;             /* async device id to use */
-#ifdef HAVE_ONE_TIME_AUTH
-    OneTimeAuth     auth;
-#endif
-#ifdef HAVE_TLS_EXTENSIONS
-    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
-    #ifdef HAVE_MAX_FRAGMENT
-        word16 max_fragment;
-    #endif
-    #ifdef HAVE_TRUNCATED_HMAC
-        byte truncated_hmac;
-    #endif
-    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-        byte status_request;
-    #endif
-    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-        byte status_request_v2;
-    #endif
-    #if defined(HAVE_SECURE_RENEGOTIATION) \
-        || defined(HAVE_SERVER_RENEGOTIATION_INFO)
-        SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
-    #endif                                         /* user turned on */
-    #ifdef HAVE_ALPN
-        char*   alpn_client_list;  /* keep the client's list */
-        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)  || defined(WOLFSSL_HAPROXY)
-            CallbackALPNSelect alpnSelect;
-            void*              alpnSelectArg;
-        #endif
-    #endif                         /* of accepted protocols */
-    #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
-        CallbackSessionTicket session_ticket_cb;
-        void*                 session_ticket_ctx;
-        byte                  expect_session_ticket;
-    #endif
-#endif /* HAVE_TLS_EXTENSIONS */
-#ifdef HAVE_OCSP
-        void*       ocspIOCtx;
-    #ifdef OPENSSL_EXTRA
-        byte*       ocspResp;
-        int         ocspRespSz;
-        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-            char*   url;
-        #endif
-    #endif
-#endif
-#ifdef HAVE_NETX
-    NetX_Ctx        nxCtx;             /* NetX IO Context */
-#endif
-#ifdef SESSION_INDEX
-    int sessionIndex;                  /* Session's location in the cache. */
-#endif
-#ifdef ATOMIC_USER
-    void*    MacEncryptCtx;    /* Atomic User Mac/Encrypt Callback Context */
-    void*    DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
-#endif
-#ifdef HAVE_PK_CALLBACKS
-    #ifdef HAVE_ECC
-        void* EccKeyGenCtx;              /* EccKeyGen  Callback Context */
-        void* EccSignCtx;                /* Ecc Sign   Callback Context */
-        void* EccVerifyCtx;              /* Ecc Verify Callback Context */
-        void* EccSharedSecretCtx;        /* Ecc Pms    Callback Context */
-        #ifdef HAVE_ED25519
-            void* Ed25519SignCtx;        /* ED25519 Sign   Callback Context */
-            void* Ed25519VerifyCtx;      /* ED25519 Verify Callback Context */
-        #endif
-        #ifdef HAVE_CURVE25519
-            void* X25519KeyGenCtx;       /* X25519 KeyGen Callback Context */
-            void* X25519SharedSecretCtx; /* X25519 Pms    Callback Context */
-        #endif
-    #endif /* HAVE_ECC */
-    #ifndef NO_DH
-        void* DhAgreeCtx; /* DH Pms Callback Context */
-    #endif /* !NO_DH */
-    #ifndef NO_RSA
-        void* RsaSignCtx;     /* Rsa Sign   Callback Context */
-        void* RsaVerifyCtx;   /* Rsa Verify Callback Context */
-        #ifdef WC_RSA_PSS
-            void* RsaPssSignCtx;     /* Rsa PSS Sign   Callback Context */
-            void* RsaPssVerifyCtx;   /* Rsa PSS Verify Callback Context */
-        #endif
-        void* RsaEncCtx;      /* Rsa Public  Encrypt   Callback Context */
-        void* RsaDecCtx;      /* Rsa Private Decrypt   Callback Context */
-    #endif /* NO_RSA */
-#endif /* HAVE_PK_CALLBACKS */
-#ifdef HAVE_SECRET_CALLBACK
-        SessionSecretCb sessionSecretCb;
-        void*           sessionSecretCtx;
-#endif /* HAVE_SECRET_CALLBACK */
-#ifdef WOLFSSL_JNI
-        void* jObjectRef;     /* reference to WolfSSLSession in JNI wrapper */
-#endif /* WOLFSSL_JNI */
-#ifdef WOLFSSL_EARLY_DATA
-    EarlyDataState earlyData;
-    word32 earlyDataSz;
-#endif
-};
-
-
-WOLFSSL_LOCAL
-int  SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int);
-WOLFSSL_LOCAL
-int  InitSSL(WOLFSSL*, WOLFSSL_CTX*, int);
-WOLFSSL_LOCAL
-void FreeSSL(WOLFSSL*, void* heap);
-WOLFSSL_API void SSL_ResourceFree(WOLFSSL*);   /* Micrium uses */
-
-
-
-#ifndef NO_CERTS
-
-    WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
-                                    long sz, int format, int type, WOLFSSL* ssl,
-                                    long* used, int userChain);
-    WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format,
-                                 int type, WOLFSSL* ssl, int userChain,
-                                WOLFSSL_CRL* crl);
-
-    #ifdef OPENSSL_EXTRA
-    WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName,
-                                    size_t domainNameLen);
-    #endif
-#endif
-
-
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
-    WOLFSSL_LOCAL
-    void InitHandShakeInfo(HandShakeInfo*, WOLFSSL*);
-    WOLFSSL_LOCAL
-    void FinishHandShakeInfo(HandShakeInfo*);
-    WOLFSSL_LOCAL
-    void AddPacketName(WOLFSSL* ssl, const char* name);
-
-    WOLFSSL_LOCAL
-    void InitTimeoutInfo(TimeoutInfo*);
-    WOLFSSL_LOCAL
-    void FreeTimeoutInfo(TimeoutInfo*, void*);
-    WOLFSSL_LOCAL
-    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
-                               const byte* data, int sz, int write, void* heap);
-    WOLFSSL_LOCAL
-    void AddLateName(const char*, TimeoutInfo*);
-    WOLFSSL_LOCAL
-    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info);
-#endif
-
-
-/* Record Layer Header identifier from page 12 */
-enum ContentType {
-    no_type            = 0,
-    change_cipher_spec = 20,
-    alert              = 21,
-    handshake          = 22,
-    application_data   = 23
-};
-
-
-/* handshake header, same for each message type, pgs 20/21 */
-typedef struct HandShakeHeader {
-    byte            type;
-    word24          length;
-} HandShakeHeader;
-
-
-/* DTLS handshake header, same for each message type */
-typedef struct DtlsHandShakeHeader {
-    byte            type;
-    word24          length;
-    byte            message_seq[2];    /* start at 0, retransmit gets same # */
-    word24          fragment_offset;   /* bytes in previous fragments */
-    word24          fragment_length;   /* length of this fragment */
-} DtlsHandShakeHeader;
-
-
-enum HandShakeType {
-    hello_request        =   0,
-    client_hello         =   1,
-    server_hello         =   2,
-    hello_verify_request =   3,    /* DTLS addition */
-    session_ticket       =   4,
-    end_of_early_data    =   5,
-    hello_retry_request  =   6,
-    encrypted_extensions =   8,
-    certificate          =  11,
-    server_key_exchange  =  12,
-    certificate_request  =  13,
-    server_hello_done    =  14,
-    certificate_verify   =  15,
-    client_key_exchange  =  16,
-    finished             =  20,
-    certificate_status   =  22,
-    key_update           =  24,
-    change_cipher_hs     =  55,    /* simulate unique handshake type for sanity
-                                      checks.  record layer change_cipher
-                                      conflicts with handshake finished */
-    message_hash         = 254,    /* synthetic message type for TLS v1.3 */
-    no_shake             = 255     /* used to initialize the DtlsMsg record */
-};
-
-enum ProvisionSide {
-    PROVISION_CLIENT = 1,
-    PROVISION_SERVER = 2,
-    PROVISION_CLIENT_SERVER = 3
-};
-
-
-static const byte client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
-static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
-
-static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
-static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
-
-
-/* internal functions */
-WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);
-WOLFSSL_LOCAL int SendTicket(WOLFSSL*);
-WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32);
-WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int);
-#ifdef WOLFSSL_TLS13
-#ifdef WOLFSSL_TLS13_DRAFT_18
-WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*);
-#else
-WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte);
-#endif
-#endif
-WOLFSSL_LOCAL int SendCertificate(WOLFSSL*);
-WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*);
-#endif
-WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*);
-WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*);
-WOLFSSL_LOCAL int SendBuffered(WOLFSSL*);
-WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int);
-WOLFSSL_LOCAL int SendFinished(WOLFSSL*);
-WOLFSSL_LOCAL int SendAlert(WOLFSSL*, int, int);
-WOLFSSL_LOCAL int ProcessReply(WOLFSSL*);
-
-WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL*);
-WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL*);
-
-WOLFSSL_LOCAL int AddSession(WOLFSSL*);
-WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl);
-WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side);
-
-WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl);
-WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl);
-WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv);
-
-WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl);
-WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree);
-WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
-
-WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
-
-WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32);
-WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment);
-
-#ifndef NO_CERTS
-    #ifndef NO_RSA
-        #ifdef WC_RSA_PSS
-            WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz,
-                byte* out, word32 sigSz, enum wc_HashType hashType);
-            WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, 
-                enum wc_HashType* hashType, int* mgf);
-        #endif
-        WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig,
-            word32 sigSz, const byte* plain, word32 plainSz, int sigAlgo,
-            int hashAlgo, RsaKey* key, DerBuffer* keyBufInfo);
-        WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
-            byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
-            DerBuffer* keyBufInfo);
-        WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
-            byte** out, int sigAlgo, int hashAlgo, RsaKey* key,
-            buffer* keyBufInfo);
-        WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out,
-            word32* outSz, RsaKey* key, DerBuffer* keyBufInfo);
-        WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
-            word32* outSz, RsaKey* key, buffer* keyBufInfo);
-    #endif /* !NO_RSA */
-
-    #ifdef HAVE_ECC
-        WOLFSSL_LOCAL int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
-            byte* out, word32* outSz, ecc_key* key, DerBuffer* keyBufInfo);
-        WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz,
-            const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo);
-        WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key,
-            ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out,
-            word32* outlen, int side);
-    #endif /* HAVE_ECC */
-    #ifdef HAVE_ED25519
-        WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl);
-        WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
-            byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo);
-        WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in,
-            word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key,
-            buffer* keyBufInfo);
-    #endif /* HAVE_ED25519 */
-
-
-    #ifdef WOLFSSL_TRUST_PEER_CERT
-
-        /* options for searching hash table for a matching trusted peer cert */
-        #define WC_MATCH_SKID 0
-        #define WC_MATCH_NAME 1
-
-        WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash,
-                                                                      int type);
-        WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp,
-                                                             DecodedCert* cert);
-    #endif
-
-    WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash);
-    #ifndef NO_SKID
-        WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash);
-    #endif
-#endif /* !NO_CERTS */
-WOLFSSL_LOCAL int  BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash,
-                                   word32* hashLen);
-WOLFSSL_LOCAL int  BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes,
-                                   const byte* sender);
-WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
-WOLFSSL_LOCAL  int CheckAvailableSize(WOLFSSL *ssl, int size);
-WOLFSSL_LOCAL  int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
-
-#ifndef NO_TLS
-    WOLFSSL_LOCAL int  MakeTlsMasterSecret(WOLFSSL*);
-    WOLFSSL_LOCAL int  TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in,
-                                word32 sz, int padSz, int content, int verify);
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
-    WOLFSSL_LOCAL int SendClientHello(WOLFSSL*);
-    #ifdef WOLFSSL_TLS13
-    WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*);
-    #endif
-    WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*);
-    WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*);
-#endif /* NO_WOLFSSL_CLIENT */
-
-#ifndef NO_WOLFSSL_SERVER
-    WOLFSSL_LOCAL int SendServerHello(WOLFSSL*);
-    WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*);
-#endif /* NO_WOLFSSL_SERVER */
-
-#ifdef WOLFSSL_DTLS
-    WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*);
-    WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*);
-    WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*);
-    WOLFSSL_LOCAL int  DtlsMsgSet(DtlsMsg*, word32, const byte*, byte,
-                                                       word32, word32, void*);
-    WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32);
-    WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32,
-                                                byte, word32, word32, void*);
-    WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*);
-
-    WOLFSSL_LOCAL int  DtlsMsgPoolSave(WOLFSSL*, const byte*, word32);
-    WOLFSSL_LOCAL int  DtlsMsgPoolTimeout(WOLFSSL*);
-    WOLFSSL_LOCAL int  VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32);
-    WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*);
-    WOLFSSL_LOCAL int  DtlsMsgPoolSend(WOLFSSL*, int);
-#endif /* WOLFSSL_DTLS */
-
-#ifndef NO_TLS
-
-
-#endif /* NO_TLS */
-
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
-    WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void);
-#endif
-WOLFSSL_LOCAL word32  LowResTimer(void);
-
-#ifndef NO_CERTS
-    WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int);
-    WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap);
-    WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int, void* heap);
-    WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*);
-    WOLFSSL_LOCAL int  CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*);
-#endif
-
-typedef struct CipherSuiteInfo {
-    const char* name;
-#ifndef NO_ERROR_STRINGS
-    const char* name_iana;
-#endif
-    byte cipherSuite0;
-    byte cipherSuite;
-} CipherSuiteInfo;
-
-WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void);
-WOLFSSL_LOCAL int GetCipherNamesSize(void);
-WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite);
-WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite);
-WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl);
-WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl);
-
-enum encrypt_side {
-    ENCRYPT_SIDE_ONLY = 1,
-    DECRYPT_SIDE_ONLY,
-    ENCRYPT_AND_DECRYPT_SIDE
-};
-
-WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side);
-
-
-#ifndef NO_DH
-    WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
-        byte* priv, word32* privSz,
-        byte* pub, word32* pubSz);
-    WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
-        const byte* priv, word32 privSz,
-        const byte* otherPub, word32 otherPubSz,
-        byte* agree, word32* agreeSz);
-#endif /* !NO_DH */
-
-#ifdef HAVE_ECC
-    WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer);
-#endif
-
-WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl);
-WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl);
-
-WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
-                        const byte* input, int inSz, int type, int hashOutput,
-                        int sizeOnly, int asyncOkay);
-
-#ifdef WOLFSSL_TLS13
-int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
-               int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay);
-#endif
-
-WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey);
-WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey);
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WOLFSSL_LOCAL int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags);
-    WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state);
-    WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev);
-#endif
-
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-#endif /* wolfSSL_INT_H */
-
+/* internal.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+
+#ifndef WOLFSSL_INT_H
+#define WOLFSSL_INT_H
+
+
+#include <wolfcrypt/types.h>
+#include <wolfssl/ssl.h>
+#ifdef HAVE_CRL
+    #include <wolfssl/crl.h>
+#endif
+#include <wolfcrypt/random.h>
+#ifndef NO_DES3
+    #include <wolfcrypt/des3.h>
+#endif
+#ifndef NO_HC128
+    #include <wolfcrypt/hc128.h>
+#endif
+#ifndef NO_RABBIT
+    #include <wolfcrypt/rabbit.h>
+#endif
+#ifdef HAVE_CHACHA
+    #include <wolfcrypt/chacha.h>
+#endif
+#ifndef NO_ASN
+    #include <wolfcrypt/asn.h>
+    #include <wolfcrypt/pkcs12.h>
+#endif
+#ifndef NO_MD5
+    #include <wolfcrypt/md5.h>
+#endif
+#ifndef NO_SHA
+    #include <wolfcrypt/sha.h>
+#endif
+#ifndef NO_AES
+    #include <wolfcrypt/aes.h>
+#endif
+#ifdef HAVE_POLY1305
+    #include <wolfcrypt/poly1305.h>
+#endif
+#ifdef HAVE_CAMELLIA
+    #include <wolfcrypt/camellia.h>
+#endif
+#include <wolfcrypt/logging.h>
+#ifndef NO_HMAC
+    #include <wolfcrypt/hmac.h>
+#endif
+#ifndef NO_RC4
+    #include <wolfcrypt/arc4.h>
+#endif
+#ifndef NO_SHA256
+    #include <wolfcrypt/sha256.h>
+#endif
+#ifdef HAVE_OCSP
+    #include <wolfssl/ocsp.h>
+#endif
+#ifdef WOLFSSL_SHA384
+    #include <wolfcrypt/sha512.h>
+#endif
+#ifdef WOLFSSL_SHA512
+    #include <wolfcrypt/sha512.h>
+#endif
+#ifdef HAVE_AESGCM
+    #include <wolfcrypt/sha512.h>
+#endif
+#ifdef WOLFSSL_RIPEMD
+    #include <wolfcrypt/ripemd.h>
+#endif
+#ifdef HAVE_IDEA
+    #include <wolfcrypt/idea.h>
+#endif
+#ifndef NO_RSA
+    #include <wolfcrypt/rsa.h>
+#endif
+#ifdef HAVE_ECC
+    #include <wolfcrypt/ecc.h>
+#endif
+#ifndef NO_DH
+    #include <wolfcrypt/dh.h>
+#endif
+#ifdef HAVE_ED25519
+    #include <wolfcrypt/ed25519.h>
+#endif
+#ifdef HAVE_CURVE25519
+    #include <wolfcrypt/curve25519.h>
+#endif
+
+#include <wolfcrypt/wc_encrypt.h>
+#include <wolfcrypt/hash.h>
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    #include <wolfssl/callbacks.h>
+#endif
+#ifdef WOLFSSL_CALLBACKS
+    #include <signal.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+    #ifdef WOLFSSL_GAME_BUILD
+        #include "system/xtl.h"
+    #else
+        #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN)
+            /* On WinCE winsock2.h must be included before windows.h */
+            #include <winsock2.h>
+        #endif
+        #include <windows.h>
+    #endif
+#elif defined(THREADX)
+    #ifndef SINGLE_THREADED
+        #include "tx_api.h"
+    #endif
+#elif defined(MICRIUM)
+    /* do nothing, just don't pick Unix */
+#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS)
+    /* do nothing */
+#elif defined(EBSNET)
+    /* do nothing */
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+    /* do nothing */
+#elif defined(FREESCALE_FREE_RTOS)
+    #include "fsl_os_abstraction.h"
+#elif defined(WOLFSSL_uITRON4)
+        /* do nothing */
+#elif defined(WOLFSSL_uTKERNEL2)
+        /* do nothing */
+#elif defined(WOLFSSL_CMSIS_RTOS)
+    #include "cmsis_os.h"
+#elif defined(WOLFSSL_MDK_ARM)
+    #if defined(WOLFSSL_MDK5)
+         #include "cmsis_os.h"
+    #else
+        #include <rtl.h>
+    #endif
+#elif defined(WOLFSSL_CMSIS_RTOS)
+    #include "cmsis_os.h"
+#elif defined(MBED)
+#elif defined(WOLFSSL_TIRTOS)
+    /* do nothing */
+#elif defined(INTIME_RTOS)
+    #include <rt.h>
+#elif defined(WOLFSSL_NUCLEUS_1_2)
+    /* do nothing */
+#else
+    #ifndef SINGLE_THREADED
+        #define WOLFSSL_PTHREADS
+        #include <pthread.h>
+    #endif
+    #ifdef OPENSSL_EXTRA
+        #include <unistd.h>      /* for close of BIO */
+    #endif
+#endif
+
+#ifndef CHAR_BIT
+    /* Needed for DTLS without big math */
+    #include <limits.h>
+#endif
+
+
+#ifdef HAVE_LIBZ
+    #include "zlib.h"
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #include <wolfssl/wolfcrypt/async.h>
+#endif
+
+#ifdef OPENSSL_EXTRA
+    #ifdef WOLFCRYPT_HAVE_SRP
+        #include <wolfssl/wolfcrypt/srp.h>
+    #endif
+#endif
+
+#ifdef _MSC_VER
+    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
+    #pragma warning(disable: 4996)
+#endif
+
+#ifdef NO_SHA
+    #define WC_SHA_DIGEST_SIZE 20
+#endif
+
+#ifdef NO_SHA256
+    #define WC_SHA256_DIGEST_SIZE 32
+#endif
+
+#ifdef NO_MD5
+    #define WC_MD5_DIGEST_SIZE 16
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/* Define or comment out the cipher suites you'd like to be compiled in
+   make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined
+
+   When adding cipher suites, add name to cipher_names, idx to cipher_name_idx
+
+   Now that there is a maximum strength crypto build, the following BUILD_XXX
+   flags need to be divided into two groups selected by WOLFSSL_MAX_STRENGTH.
+   Those that do not use Perfect Forward Security and do not use AEAD ciphers
+   need to be switched off. Allowed suites use (EC)DHE, AES-GCM|CCM, or
+   CHACHA-POLY.
+*/
+
+/* Check that if WOLFSSL_MAX_STRENGTH is set that all the required options are
+ * not turned off. */
+#if defined(WOLFSSL_MAX_STRENGTH) && \
+    ((!defined(HAVE_ECC) && (defined(NO_DH) || defined(NO_RSA))) || \
+     (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM) && \
+      (!defined(HAVE_POLY1305) || !defined(HAVE_CHACHA))) || \
+     (defined(NO_SHA256) && !defined(WOLFSSL_SHA384)) || \
+     !defined(NO_OLD_TLS))
+
+    #error "You are trying to build max strength with requirements disabled."
+#endif
+
+/* Have QSH : Quantum-safe Handshake */
+#if defined(HAVE_QSH)
+    #define BUILD_TLS_QSH
+#endif
+
+#ifndef WOLFSSL_MAX_STRENGTH
+
+    #if !defined(NO_RSA) && !defined(NO_RC4)
+        #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined(NO_SHA)
+                #define BUILD_SSL_RSA_WITH_RC4_128_SHA
+            #endif
+            #if !defined(NO_MD5)
+                #define BUILD_SSL_RSA_WITH_RC4_128_MD5
+            #endif
+        #endif
+        #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) \
+            && defined(WOLFSSL_STATIC_RSA)
+            #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+        #endif
+    #endif
+
+    #if !defined(NO_RSA) && !defined(NO_DES3)
+        #if !defined(NO_SHA)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+            #if !defined(NO_TLS) && defined(HAVE_NTRU) \
+                && defined(WOLFSSL_STATIC_RSA)
+                    #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+        #endif
+    #endif
+
+    #if !defined(NO_RSA) && defined(HAVE_IDEA)
+        #if !defined(NO_SHA) && defined(WOLFSSL_STATIC_RSA)
+            #define BUILD_SSL_RSA_WITH_IDEA_CBC_SHA
+        #endif
+    #endif
+
+    #if !defined(NO_RSA) && !defined(NO_AES) && !defined(NO_TLS)
+        #if !defined(NO_SHA)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+                #endif
+            #endif
+            #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+                #endif
+            #endif
+        #endif
+        #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined (NO_SHA256)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256
+                #endif
+            #endif
+            #if defined (HAVE_AESGCM)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
+                #endif
+                #if defined (WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+                    #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384
+                #endif
+            #endif
+            #if defined (HAVE_AESCCM)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CCM_8
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CCM_8
+                #endif
+            #endif
+            #if defined(HAVE_BLAKE2)
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256
+                #endif
+            #endif
+        #endif
+    #endif
+
+    #if defined(HAVE_CAMELLIA) && !defined(NO_TLS)
+        #ifndef NO_RSA
+          #if defined(WOLFSSL_STATIC_RSA)
+            #if !defined(NO_SHA)
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+            #endif
+            #ifndef NO_SHA256
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+                #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+            #endif
+          #endif
+            #if !defined(NO_DH)
+              #if !defined(NO_SHA)
+                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+                #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+              #endif
+                #ifndef NO_SHA256
+                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+                    #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+                #endif
+            #endif
+        #endif
+    #endif
+
+#if defined(WOLFSSL_STATIC_PSK)
+    #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS)
+        #if !defined(NO_SHA)
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+            #endif
+        #endif
+        #ifndef NO_SHA256
+            #ifdef WOLFSSL_AES_128
+            #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
+            #ifdef HAVE_AESGCM
+                #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
+            #endif
+            #endif /* WOLFSSL_AES_128 */
+            #ifdef HAVE_AESCCM
+                #ifdef WOLFSSL_AES_128
+                    #define BUILD_TLS_PSK_WITH_AES_128_CCM_8
+                    #define BUILD_TLS_PSK_WITH_AES_128_CCM
+                #endif
+                #ifdef WOLFSSL_AES_256
+                    #define BUILD_TLS_PSK_WITH_AES_256_CCM_8
+                    #define BUILD_TLS_PSK_WITH_AES_256_CCM
+                #endif
+            #endif
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
+            #ifdef HAVE_AESGCM
+                #define BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384
+            #endif
+        #endif
+    #endif
+#endif
+
+    #if !defined(NO_TLS) && defined(HAVE_NULL_CIPHER)
+        #if !defined(NO_RSA)
+            #if defined(WOLFSSL_STATIC_RSA)
+                #if !defined(NO_SHA)
+                    #define BUILD_TLS_RSA_WITH_NULL_SHA
+                #endif
+                #ifndef NO_SHA256
+                    #define BUILD_TLS_RSA_WITH_NULL_SHA256
+                #endif
+            #endif
+        #endif
+        #if !defined(NO_PSK) && defined(WOLFSSL_STATIC_PSK)
+            #if !defined(NO_SHA)
+                #define BUILD_TLS_PSK_WITH_NULL_SHA
+            #endif
+            #ifndef NO_SHA256
+                #define BUILD_TLS_PSK_WITH_NULL_SHA256
+            #endif
+            #ifdef WOLFSSL_SHA384
+                #define BUILD_TLS_PSK_WITH_NULL_SHA384
+            #endif
+        #endif
+    #endif
+
+#if defined(WOLFSSL_STATIC_RSA)
+    #if !defined(NO_HC128) && !defined(NO_RSA) && !defined(NO_TLS)
+        #ifndef NO_MD5
+            #define BUILD_TLS_RSA_WITH_HC_128_MD5
+        #endif
+        #if !defined(NO_SHA)
+            #define BUILD_TLS_RSA_WITH_HC_128_SHA
+        #endif
+        #if defined(HAVE_BLAKE2)
+            #define BUILD_TLS_RSA_WITH_HC_128_B2B256
+        #endif
+    #endif
+
+    #if !defined(NO_RABBIT) && !defined(NO_TLS) && !defined(NO_RSA)
+        #if !defined(NO_SHA)
+            #define BUILD_TLS_RSA_WITH_RABBIT_SHA
+        #endif
+    #endif
+#endif
+
+    #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
+        !defined(NO_RSA)
+
+        #if !defined(NO_SHA)
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+            #endif
+            #if !defined(NO_DES3)
+                #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+            #endif
+        #endif
+        #if !defined(NO_SHA256) && defined(HAVE_AES_CBC)
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+            #endif
+        #endif
+    #endif
+
+    #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \
+        !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128)
+        #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
+
+        #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM)
+            #define BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384
+        #endif
+    #endif
+
+    #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
+        #ifndef NO_SHA256
+            #if !defined(NO_AES) && defined(WOLFSSL_AES_128)
+                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+            #endif
+            #ifdef HAVE_NULL_CIPHER
+                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
+            #endif
+        #endif
+        #ifdef WOLFSSL_SHA384
+            #if !defined(NO_AES) && defined(WOLFSSL_AES_256)
+                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+            #endif
+            #ifdef HAVE_NULL_CIPHER
+                #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA384
+            #endif
+        #endif
+    #endif
+
+    #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS)
+        #if !defined(NO_AES)
+            #if !defined(NO_SHA)
+                #if !defined(NO_RSA)
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+                    #endif
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #ifdef WOLFSSL_AES_128
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+                        #endif
+                        #ifdef WOLFSSL_AES_256
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+                        #endif
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+                    #endif
+                #endif
+
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #ifdef WOLFSSL_AES_128
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+                    #endif
+                    #ifdef WOLFSSL_AES_256
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+                    #endif
+                #endif
+            #endif /* NO_SHA */
+            #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+                    #endif
+                #endif
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+                #endif
+            #endif
+
+            #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+                    #endif
+                #endif
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+                #endif
+            #endif
+
+            #if defined (HAVE_AESGCM)
+                #if !defined(NO_RSA)
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #ifdef WOLFSSL_AES_128
+                            #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+                        #endif
+                    #endif
+                    #if defined(WOLFSSL_SHA384)
+                        #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                            #ifdef WOLFSSL_AES_256
+                                #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+                            #endif
+                        #endif
+                    #endif
+                #endif
+
+                #if defined(WOLFSSL_STATIC_DH) && defined(WOLFSSL_AES_128) && \
+                                                               defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+                #endif
+
+                #if defined(WOLFSSL_SHA384)
+                    #if defined(WOLFSSL_STATIC_DH) && \
+                                   defined(WOLFSSL_AES_256) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+                    #endif
+                #endif
+            #endif
+        #endif /* NO_AES */
+        #if !defined(NO_RC4)
+            #if !defined(NO_SHA)
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+                #endif
+            #endif
+        #endif
+        #if !defined(NO_DES3)
+            #ifndef NO_SHA
+                #if !defined(NO_RSA)
+                    #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+                    #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                        #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+                    #endif
+                #endif
+
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+                #endif
+                #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC)
+                    #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+                #endif
+            #endif /* NO_SHA */
+        #endif
+        #if defined(HAVE_NULL_CIPHER)
+            #if !defined(NO_SHA)
+                #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                    #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+                #endif
+            #endif
+            #if !defined(NO_PSK) && !defined(NO_SHA256)
+                #define BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
+            #endif
+        #endif
+        #if !defined(NO_PSK) && !defined(NO_SHA256) && !defined(NO_AES) && \
+            defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+        #endif
+    #endif
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
+        #if !defined(NO_OLD_POLY1305)
+        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #ifndef NO_RSA
+            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #if !defined(NO_DH) && !defined(NO_RSA)
+            #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
+        #endif
+        #endif /* NO_OLD_POLY1305 */
+        #if !defined(NO_PSK)
+            #define BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+                #define BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #endif
+            #ifndef NO_DH
+                #define BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+            #endif
+        #endif /* !NO_PSK */
+    #endif
+
+#endif /* !WOLFSSL_MAX_STRENGTH */
+
+#if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \
+    !defined(NO_RSA) && defined(HAVE_AESGCM)
+
+    #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+        #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+    #endif
+
+    #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+        #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+    #endif
+#endif
+
+#if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS)
+    #ifndef NO_SHA256
+        #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+        #endif
+        #ifdef HAVE_AESCCM
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM
+            #endif
+        #endif
+    #endif
+    #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) && \
+        defined(WOLFSSL_AES_256)
+        #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+    #endif
+#endif
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS) && \
+                                                                !defined(NO_AES)
+    #ifdef HAVE_AESGCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+            #endif
+            #ifndef NO_RSA
+                #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+            #endif
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+            #endif
+            #ifndef NO_RSA
+                #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+            #endif
+        #endif
+    #endif
+    #if defined(HAVE_AESCCM) && !defined(NO_SHA256)
+        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+            #ifdef WOLFSSL_AES_128
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+            #endif
+            #ifdef WOLFSSL_AES_256
+                #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+            #endif
+        #endif
+    #endif
+#endif
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256)
+    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+        #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \
+                                                          defined(HAVE_ED25519))
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+        #endif
+        #ifndef NO_RSA
+            #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+        #endif
+    #endif
+    #if !defined(NO_DH) && !defined(NO_RSA)
+        #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    #endif
+#endif
+
+#if defined(WOLFSSL_TLS13)
+    #ifdef HAVE_AESGCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_AES_128_GCM_SHA256
+        #endif
+        #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
+            #define BUILD_TLS_AES_256_GCM_SHA384
+        #endif
+    #endif
+
+    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+        #ifndef NO_SHA256
+            #define BUILD_TLS_CHACHA20_POLY1305_SHA256
+        #endif
+    #endif
+
+    #ifdef HAVE_AESCCM
+        #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128)
+            #define BUILD_TLS_AES_128_CCM_SHA256
+            #define BUILD_TLS_AES_128_CCM_8_SHA256
+        #endif
+    #endif
+#endif
+
+#ifdef WOLFSSL_MULTICAST
+    #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256)
+        #define BUILD_WDM_WITH_NULL_SHA256
+    #endif
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \
+    defined(BUILD_SSL_RSA_WITH_RC4_128_MD5)
+    #define BUILD_ARC4
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA)
+    #define BUILD_DES3
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \
+    defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256)
+    #undef  BUILD_AES
+    #define BUILD_AES
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) || \
+    defined(BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384)
+    #define BUILD_AESGCM
+#else
+    /* No AES-GCM cipher suites available with build */
+    #define NO_AESGCM_AEAD
+#endif
+
+#if defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \
+    defined(BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256) || \
+    defined(BUILD_TLS_CHACHA20_POLY1305_SHA256)
+    /* Have an available ChaCha Poly cipher suite */
+#else
+    /* No ChaCha Poly cipher suites available with build */
+    #define NO_CHAPOL_AEAD
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_HC_128_SHA) || \
+    defined(BUILD_TLS_RSA_WITH_HC_128_MD5) || \
+    defined(BUILD_TLS_RSA_WITH_HC_128_B2B256)
+    #define BUILD_HC128
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_RABBIT_SHA)
+    #define BUILD_RABBIT
+#endif
+
+#ifdef NO_DES3
+    #define DES_BLOCK_SIZE 8
+#else
+    #undef  BUILD_DES3
+    #define BUILD_DES3
+#endif
+
+#if defined(NO_AES) || defined(NO_AES_DECRYPT)
+    #define AES_BLOCK_SIZE 16
+    #undef  BUILD_AES
+#else
+    #undef  BUILD_AES
+    #define BUILD_AES
+#endif
+
+#ifndef NO_RC4
+    #undef  BUILD_ARC4
+    #define BUILD_ARC4
+#endif
+
+#ifdef HAVE_CHACHA
+    #define CHACHA20_BLOCK_SIZE 16
+#endif
+
+#if defined(WOLFSSL_MAX_STRENGTH) || \
+    (defined(HAVE_AESGCM) && !defined(NO_AESGCM_AEAD)) || \
+     defined(HAVE_AESCCM) || \
+    (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_CHAPOL_AEAD))
+
+    #define HAVE_AEAD
+#endif
+
+#if defined(WOLFSSL_MAX_STRENGTH) || \
+    defined(HAVE_ECC) || !defined(NO_DH)
+
+    #define HAVE_PFS
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_IDEA_CBC_SHA)
+    #define BUILD_IDEA
+#endif
+
+/* actual cipher values, 2nd byte */
+enum {
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16,
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA  = 0x39,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA  = 0x33,
+    TLS_DH_anon_WITH_AES_128_CBC_SHA  = 0x34,
+    TLS_RSA_WITH_AES_256_CBC_SHA      = 0x35,
+    TLS_RSA_WITH_AES_128_CBC_SHA      = 0x2F,
+    TLS_RSA_WITH_NULL_SHA             = 0x02,
+    TLS_PSK_WITH_AES_256_CBC_SHA      = 0x8d,
+    TLS_PSK_WITH_AES_128_CBC_SHA256   = 0xae,
+    TLS_PSK_WITH_AES_256_CBC_SHA384   = 0xaf,
+    TLS_PSK_WITH_AES_128_CBC_SHA      = 0x8c,
+    TLS_PSK_WITH_NULL_SHA256          = 0xb0,
+    TLS_PSK_WITH_NULL_SHA384          = 0xb1,
+    TLS_PSK_WITH_NULL_SHA             = 0x2c,
+    SSL_RSA_WITH_RC4_128_SHA          = 0x05,
+    SSL_RSA_WITH_RC4_128_MD5          = 0x04,
+    SSL_RSA_WITH_3DES_EDE_CBC_SHA     = 0x0A,
+    SSL_RSA_WITH_IDEA_CBC_SHA         = 0x07,
+
+    /* ECC suites, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA    = 0x14,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA    = 0x13,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA  = 0x0A,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA  = 0x09,
+    TLS_ECDHE_RSA_WITH_RC4_128_SHA        = 0x11,
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA      = 0x07,
+    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA   = 0x12,
+    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256   = 0x27,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x23,
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384   = 0x28,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0x24,
+    TLS_ECDHE_ECDSA_WITH_NULL_SHA           = 0x06,
+    TLS_ECDHE_PSK_WITH_NULL_SHA256          = 0x3a,
+    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256   = 0x37,
+
+    /* static ECDH, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA    = 0x0F,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA    = 0x0E,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA  = 0x05,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA  = 0x04,
+    TLS_ECDH_RSA_WITH_RC4_128_SHA        = 0x0C,
+    TLS_ECDH_ECDSA_WITH_RC4_128_SHA      = 0x02,
+    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA   = 0x0D,
+    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x03,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256   = 0x29,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0x25,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384   = 0x2A,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0x26,
+
+    /* wolfSSL extension - eSTREAM */
+    TLS_RSA_WITH_HC_128_MD5       = 0xFB,
+    TLS_RSA_WITH_HC_128_SHA       = 0xFC,
+    TLS_RSA_WITH_RABBIT_SHA       = 0xFD,
+    WDM_WITH_NULL_SHA256          = 0xFE, /* wolfSSL DTLS Multicast */
+
+    /* wolfSSL extension - Blake2b 256 */
+    TLS_RSA_WITH_AES_128_CBC_B2B256   = 0xF8,
+    TLS_RSA_WITH_AES_256_CBC_B2B256   = 0xF9,
+    TLS_RSA_WITH_HC_128_B2B256        = 0xFA,   /* eSTREAM too */
+
+    /* wolfSSL extension - NTRU */
+    TLS_NTRU_RSA_WITH_RC4_128_SHA      = 0xe5,
+    TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0xe6,
+    TLS_NTRU_RSA_WITH_AES_128_CBC_SHA  = 0xe7,  /* clashes w/official SHA-256 */
+    TLS_NTRU_RSA_WITH_AES_256_CBC_SHA  = 0xe8,
+
+    /* wolfSSL extension - NTRU , Quantum-safe Handshake
+       first byte is 0xD0 (QSH_BYTE) */
+    TLS_QSH      = 0x01,
+
+    /* SHA256 */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b,
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67,
+    TLS_RSA_WITH_AES_256_CBC_SHA256     = 0x3d,
+    TLS_RSA_WITH_AES_128_CBC_SHA256     = 0x3c,
+    TLS_RSA_WITH_NULL_SHA256            = 0x3b,
+    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0xb2,
+    TLS_DHE_PSK_WITH_NULL_SHA256        = 0xb4,
+
+    /* SHA384 */
+    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0xb3,
+    TLS_DHE_PSK_WITH_NULL_SHA384        = 0xb5,
+
+    /* AES-GCM */
+    TLS_RSA_WITH_AES_128_GCM_SHA256          = 0x9c,
+    TLS_RSA_WITH_AES_256_GCM_SHA384          = 0x9d,
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      = 0x9e,
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      = 0x9f,
+    TLS_DH_anon_WITH_AES_256_GCM_SHA384      = 0xa7,
+    TLS_PSK_WITH_AES_128_GCM_SHA256          = 0xa8,
+    TLS_PSK_WITH_AES_256_GCM_SHA384          = 0xa9,
+    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      = 0xaa,
+    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      = 0xab,
+
+    /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  = 0x2b,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  = 0x2c,
+    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   = 0x2d,
+    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   = 0x2e,
+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    = 0x2f,
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    = 0x30,
+    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     = 0x31,
+    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     = 0x32,
+
+    /* AES-CCM, first byte is 0xC0 but isn't ECC,
+     * also, in some of the other AES-CCM suites
+     * there will be second byte number conflicts
+     * with non-ECC AES-GCM */
+    TLS_RSA_WITH_AES_128_CCM_8         = 0xa0,
+    TLS_RSA_WITH_AES_256_CCM_8         = 0xa1,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM   = 0xac,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xae,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xaf,
+    TLS_PSK_WITH_AES_128_CCM           = 0xa4,
+    TLS_PSK_WITH_AES_256_CCM           = 0xa5,
+    TLS_PSK_WITH_AES_128_CCM_8         = 0xa8,
+    TLS_PSK_WITH_AES_256_CCM_8         = 0xa9,
+    TLS_DHE_PSK_WITH_AES_128_CCM       = 0xa6,
+    TLS_DHE_PSK_WITH_AES_256_CCM       = 0xa7,
+
+    /* Camellia */
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA        = 0x41,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        = 0x84,
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     = 0xba,
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     = 0xc0,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA    = 0x45,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    = 0x88,
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe,
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4,
+
+    /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */
+    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   = 0xa8,
+    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9,
+    TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     = 0xaa,
+    TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   = 0xac,
+    TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         = 0xab,
+    TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     = 0xad,
+
+    /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */
+    TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256   = 0x13,
+    TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14,
+    TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256     = 0x15,
+
+    /* TLS v1.3 cipher suites */
+    TLS_AES_128_GCM_SHA256       = 0x01,
+    TLS_AES_256_GCM_SHA384       = 0x02,
+    TLS_CHACHA20_POLY1305_SHA256 = 0x03,
+    TLS_AES_128_CCM_SHA256       = 0x04,
+    TLS_AES_128_CCM_8_SHA256     = 0x05,
+
+    /* Renegotiation Indication Extension Special Suite */
+    TLS_EMPTY_RENEGOTIATION_INFO_SCSV        = 0xff
+};
+
+
+#ifndef WOLFSSL_SESSION_TIMEOUT
+    #define WOLFSSL_SESSION_TIMEOUT 500
+    /* default session resumption cache timeout in seconds */
+#endif
+
+
+#ifndef WOLFSSL_DTLS_WINDOW_WORDS
+    #define WOLFSSL_DTLS_WINDOW_WORDS 2
+#endif /* WOLFSSL_DTLS_WINDOW_WORDS */
+#define DTLS_WORD_BITS (sizeof(word32) * CHAR_BIT)
+#define DTLS_SEQ_BITS  (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS)
+#define DTLS_SEQ_SZ    (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS)
+
+#ifndef WOLFSSL_MULTICAST
+    #define WOLFSSL_DTLS_PEERSEQ_SZ 1
+#else
+    #ifndef WOLFSSL_MULTICAST_PEERS
+        /* max allowed multicast group peers */
+        #define WOLFSSL_MULTICAST_PEERS 100
+    #endif
+    #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS
+#endif /* WOLFSSL_MULTICAST */
+
+#ifndef WOLFSSL_MAX_MTU
+    #define WOLFSSL_MAX_MTU 1500
+#endif /* WOLFSSL_MAX_MTU */
+
+
+/* set minimum DH key size allowed */
+#ifndef WOLFSSL_MIN_DHKEY_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_DHKEY_BITS 2048
+    #else
+        #define WOLFSSL_MIN_DHKEY_BITS 1024
+    #endif
+#endif
+#if (WOLFSSL_MIN_DHKEY_BITS % 8)
+    #error DH minimum bit size must be multiple of 8
+#endif
+#if (WOLFSSL_MIN_DHKEY_BITS > 16000)
+    #error DH minimum bit size must not be greater than 16000
+#endif
+#define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8)
+/* set maximum DH key size allowed */
+#ifndef WOLFSSL_MAX_DHKEY_BITS
+    #define WOLFSSL_MAX_DHKEY_BITS 4096
+#endif
+#if (WOLFSSL_MAX_DHKEY_BITS % 8)
+    #error DH maximum bit size must be multiple of 8
+#endif
+#if (WOLFSSL_MAX_DHKEY_BITS > 16000)
+    #error DH maximum bit size must not be greater than 16000
+#endif
+#define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8)
+
+
+
+enum Misc {
+    CIPHER_BYTE = 0x00,            /* Default ciphers */
+    ECC_BYTE    = 0xC0,            /* ECC first cipher suite byte */
+    QSH_BYTE    = 0xD0,            /* Quantum-safe Handshake cipher suite */
+    CHACHA_BYTE = 0xCC,            /* ChaCha first cipher suite */
+    TLS13_BYTE  = 0x13,            /* TLS v1.3 first byte of cipher suite */
+
+    SEND_CERT       = 1,
+    SEND_BLANK_CERT = 2,
+
+    DTLS_MAJOR      = 0xfe,     /* DTLS major version number */
+    DTLS_MINOR      = 0xff,     /* DTLS minor version number */
+    DTLSv1_2_MINOR  = 0xfd,     /* DTLS minor version number */
+    SSLv3_MAJOR     = 3,        /* SSLv3 and TLSv1+  major version number */
+    SSLv3_MINOR     = 0,        /* TLSv1   minor version number */
+    TLSv1_MINOR     = 1,        /* TLSv1   minor version number */
+    TLSv1_1_MINOR   = 2,        /* TLSv1_1 minor version number */
+    TLSv1_2_MINOR   = 3,        /* TLSv1_2 minor version number */
+    TLSv1_3_MINOR   = 4,        /* TLSv1_3 minor version number */
+#ifndef WOLFSSL_TLS13_FINAL
+    TLS_DRAFT_MAJOR = 0x7f,     /* Draft TLS major version number */
+#ifdef WOLFSSL_TLS13_DRAFT_18
+    TLS_DRAFT_MINOR = 0x12,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_22)
+    TLS_DRAFT_MINOR = 0x16,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_23)
+    TLS_DRAFT_MINOR = 0x17,     /* Minor version number of TLS draft */
+#elif defined(WOLFSSL_TLS13_DRAFT_26)
+    TLS_DRAFT_MINOR = 0x1a,     /* Minor version number of TLS draft */
+#else
+    TLS_DRAFT_MINOR = 0x1c,     /* Minor version number of TLS draft */
+#endif
+#endif
+    OLD_HELLO_ID    = 0x01,     /* SSLv2 Client Hello Indicator */
+    INVALID_BYTE    = 0xff,     /* Used to initialize cipher specs values */
+    NO_COMPRESSION  =  0,
+    ZLIB_COMPRESSION = 221,     /* wolfSSL zlib compression */
+    HELLO_EXT_SIG_ALGO = 13,    /* ID for the sig_algo hello extension */
+    HELLO_EXT_EXTMS = 0x0017,   /* ID for the extended master secret ext */
+    SECRET_LEN      = WOLFSSL_MAX_MASTER_KEY_LENGTH,
+                                /* pre RSA and all master */
+#if defined(WOLFSSL_MYSQL_COMPATIBLE)
+    ENCRYPT_LEN     = 1024,     /* allow larger static buffer with mysql */
+#else
+    ENCRYPT_LEN     = 512,      /* allow 4096 bit static buffer */
+#endif
+    SIZEOF_SENDER   =  4,       /* clnt or srvr           */
+    FINISHED_SZ     = 36,       /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */
+    MAX_RECORD_SIZE = 16384,    /* 2^14, max size by standard */
+    MAX_MSG_EXTRA   = 38 + WC_MAX_DIGEST_SIZE,
+                                /* max added to msg, mac + pad  from */
+                                /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max
+                                   digest sz + BLOC_SZ (iv) + pad byte (1) */
+    MAX_COMP_EXTRA  = 1024,     /* max compression extra */
+    MAX_MTU         = WOLFSSL_MAX_MTU,     /* max expected MTU */
+    MAX_UDP_SIZE    = 8192 - 100, /* was MAX_MTU - 100 */
+    MAX_DH_SZ       = (MAX_DHKEY_SZ * 2) + 12,
+                                /* 4096 p, pub, g + 2 byte size for each */
+    MAX_STR_VERSION = 8,        /* string rep of protocol version */
+
+    PAD_MD5        = 48,       /* pad length for finished */
+    PAD_SHA        = 40,       /* pad length for finished */
+    MAX_PAD_SIZE   = 256,      /* maximum length of padding */
+
+    LENGTH_SZ      =  2,       /* length field for HMAC, data only */
+    VERSION_SZ     =  2,       /* length of proctocol version */
+    SEQ_SZ         =  8,       /* 64 bit sequence number  */
+    ALERT_SIZE     =  2,       /* level + description     */
+    VERIFY_HEADER  =  2,       /* always use 2 bytes      */
+    EXTS_SZ        =  2,       /* always use 2 bytes      */
+    EXT_ID_SZ      =  2,       /* always use 2 bytes      */
+    MAX_DH_SIZE    = MAX_DHKEY_SZ+1,
+                               /* Max size plus possible leading 0 */
+    NAMED_DH_MASK  = 0x100,    /* Named group mask for DH parameters  */
+    SESSION_HINT_SZ = 4,       /* session timeout hint */
+    SESSION_ADD_SZ = 4,        /* session age add */
+    TICKET_NONCE_LEN_SZ = 1,   /* Ticket nonce length size */
+    DEF_TICKET_NONCE_SZ = 1,   /* Default ticket nonce size */
+    MAX_TICKET_NONCE_SZ = 4,   /* maximum ticket nonce size */
+    MAX_LIFETIME   = 604800,   /* maximum ticket lifetime */
+    MAX_EARLY_DATA_SZ = 4096,  /* maximum early data size */
+
+    RAN_LEN      = 32,         /* random length           */
+    SEED_LEN     = RAN_LEN * 2, /* tls prf seed length    */
+    ID_LEN       = 32,         /* session id length       */
+    COOKIE_SECRET_SZ = 14,     /* dtls cookie secret size */
+    MAX_COOKIE_LEN = 32,       /* max dtls cookie size    */
+    COOKIE_SZ    = 20,         /* use a 20 byte cookie    */
+    SUITE_LEN    =  2,         /* cipher suite sz length  */
+    ENUM_LEN     =  1,         /* always a byte           */
+    OPAQUE8_LEN  =  1,         /* 1 byte                  */
+    OPAQUE16_LEN =  2,         /* 2 bytes                 */
+    OPAQUE24_LEN =  3,         /* 3 bytes                 */
+    OPAQUE32_LEN =  4,         /* 4 bytes                 */
+    OPAQUE64_LEN =  8,         /* 8 bytes                 */
+    COMP_LEN     =  1,         /* compression length      */
+    CURVE_LEN    =  2,         /* ecc named curve length  */
+    KE_GROUP_LEN =  2,         /* key exchange group length */
+    SERVER_ID_LEN = 20,        /* server session id length  */
+
+    HANDSHAKE_HEADER_SZ   = 4,  /* type + length(3)        */
+    RECORD_HEADER_SZ      = 5,  /* type + version + len(2) */
+    CERT_HEADER_SZ        = 3,  /* always 3 bytes          */
+    REQ_HEADER_SZ         = 2,  /* cert request header sz  */
+    HINT_LEN_SZ           = 2,  /* length of hint size field */
+    TRUNCATED_HMAC_SZ     = 10, /* length of hmac w/ truncated hmac extension */
+    HELLO_EXT_SZ          = 4,  /* base length of a hello extension */
+    HELLO_EXT_TYPE_SZ     = 2,  /* length of a hello extension type */
+    HELLO_EXT_SZ_SZ       = 2,  /* length of a hello extension size */
+    HELLO_EXT_SIGALGO_SZ  = 2,  /* length of number of items in sigalgo list */
+
+    DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
+    DTLS_RECORD_HEADER_SZ    = 13, /* normal + epoch(2) + seq_num(6) */
+    DTLS_HANDSHAKE_EXTRA     = 8,  /* diff from normal */
+    DTLS_RECORD_EXTRA        = 8,  /* diff from normal */
+    DTLS_HANDSHAKE_SEQ_SZ    = 2,  /* handshake header sequence number */
+    DTLS_HANDSHAKE_FRAG_SZ   = 3,  /* fragment offset and length are 24 bit */
+    DTLS_POOL_SZ             = 255,/* allowed number of list items in TX pool */
+    DTLS_EXPORT_PRO          = 165,/* wolfSSL protocol for serialized session */
+    DTLS_EXPORT_VERSION      = 4,  /* wolfSSL version for serialized session */
+    DTLS_EXPORT_OPT_SZ       = 60, /* amount of bytes used from Options */
+    DTLS_EXPORT_VERSION_3    = 3,  /* wolfSSL version before TLS 1.3 addition */
+    DTLS_EXPORT_OPT_SZ_3     = 59, /* amount of bytes used from Options */
+    DTLS_EXPORT_KEY_SZ       = 325 + (DTLS_SEQ_SZ * 2),
+                                   /* max amount of bytes used from Keys */
+    DTLS_EXPORT_MIN_KEY_SZ   = 78 + (DTLS_SEQ_SZ * 2),
+                                   /* min amount of bytes used from Keys */
+    DTLS_EXPORT_SPC_SZ       = 16, /* amount of bytes used from CipherSpecs */
+    DTLS_EXPORT_LEN          = 2,  /* 2 bytes for length and protocol */
+    DTLS_EXPORT_IP           = 46, /* max ip size IPv4 mapped IPv6 */
+    MAX_EXPORT_BUFFER        = 514, /* max size of buffer for exporting */
+    FINISHED_LABEL_SZ   = 15,  /* TLS finished label size */
+    TLS_FINISHED_SZ     = 12,  /* TLS has a shorter size  */
+    EXT_MASTER_LABEL_SZ = 22,  /* TLS extended master secret label sz */
+    MASTER_LABEL_SZ     = 13,  /* TLS master secret label sz */
+    KEY_LABEL_SZ        = 13,  /* TLS key block expansion sz */
+    MAX_PRF_HALF        = 256, /* Maximum half secret len */
+    MAX_PRF_LABSEED     = 128, /* Maximum label + seed len */
+    MAX_PRF_DIG         = 224, /* Maximum digest len      */
+    PROTOCOL_LABEL_SZ   = 9,   /* Length of the protocol label */
+    MAX_LABEL_SZ        = 34,  /* Maximum length of a label */
+    MAX_HKDF_LABEL_SZ   = OPAQUE16_LEN +
+                          OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
+                          OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
+    MAX_REQUEST_SZ      = 256, /* Maximum cert req len (no auth yet */
+    SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
+    TLS_MAX_PAD_SZ      = 255, /* Max padding in TLS */
+
+#if defined(HAVE_FIPS) && \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    MAX_SYM_KEY_SIZE    = AES_256_KEY_SIZE,
+#else
+    MAX_SYM_KEY_SIZE    = WC_MAX_SYM_KEY_SIZE,
+#endif
+
+#ifdef HAVE_SELFTEST
+    AES_256_KEY_SIZE    = 32,
+    AES_IV_SIZE         = 16,
+    AES_128_KEY_SIZE    = 16,
+#endif
+
+    MAX_IV_SZ           = AES_BLOCK_SIZE,
+
+    AEAD_SEQ_OFFSET     = 4,   /* Auth Data: Sequence number */
+    AEAD_TYPE_OFFSET    = 8,   /* Auth Data: Type            */
+    AEAD_VMAJ_OFFSET    = 9,   /* Auth Data: Major Version   */
+    AEAD_VMIN_OFFSET    = 10,  /* Auth Data: Minor Version   */
+    AEAD_LEN_OFFSET     = 11,  /* Auth Data: Length          */
+    AEAD_AUTH_DATA_SZ   = 13,  /* Size of the data to authenticate */
+    AEAD_NONCE_SZ       = 12,
+    AESGCM_IMP_IV_SZ    = 4,   /* Size of GCM/CCM AEAD implicit IV */
+    AESGCM_EXP_IV_SZ    = 8,   /* Size of GCM/CCM AEAD explicit IV */
+    AESGCM_NONCE_SZ     = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ,
+
+    CHACHA20_IMP_IV_SZ  = 12,  /* Size of ChaCha20 AEAD implicit IV */
+    CHACHA20_NONCE_SZ   = 12,  /* Size of ChacCha20 nonce           */
+    CHACHA20_OLD_OFFSET = 4,   /* Offset for seq # in old poly1305  */
+
+    /* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */
+
+    AES_GCM_AUTH_SZ     = 16, /* AES-GCM Auth Tag length    */
+    AES_CCM_16_AUTH_SZ  = 16, /* AES-CCM-16 Auth Tag length */
+    AES_CCM_8_AUTH_SZ   = 8,  /* AES-CCM-8 Auth Tag Length  */
+    AESCCM_NONCE_SZ     = 12,
+
+    CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */
+    CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */
+    CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */
+    CAMELLIA_IV_SIZE      = 16, /* always block size */
+
+    CHACHA20_256_KEY_SIZE = 32,  /* for 256 bit             */
+    CHACHA20_128_KEY_SIZE = 16,  /* for 128 bit             */
+    CHACHA20_IV_SIZE      = 12,  /* 96 bits for iv          */
+
+    POLY1305_AUTH_SZ    = 16,  /* 128 bits                */
+
+    HC_128_KEY_SIZE     = 16,  /* 128 bits                */
+    HC_128_IV_SIZE      = 16,  /* also 128 bits           */
+
+    RABBIT_KEY_SIZE     = 16,  /* 128 bits                */
+    RABBIT_IV_SIZE      =  8,  /* 64 bits for iv          */
+
+    EVP_SALT_SIZE       =  8,  /* evp salt size 64 bits   */
+
+    ECDHE_SIZE          = 32,  /* ECHDE server size defaults to 256 bit */
+    MAX_EXPORT_ECC_SZ   = 256, /* Export ANS X9.62 max future size */
+    MAX_CURVE_NAME_SZ   = 16,  /* Maximum size of curve name string */
+
+    NEW_SA_MAJOR        = 8,   /* Most signicant byte used with new sig algos */
+    ED25519_SA_MAJOR    = 8,   /* Most significant byte for ED25519 */
+    ED25519_SA_MINOR    = 7,   /* Least significant byte for ED25519 */
+    ED448_SA_MAJOR      = 8,   /* Most significant byte for ED448 */
+    ED448_SA_MINOR      = 8,   /* Least significant byte for ED448 */
+
+    MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */
+    MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */
+
+    MAX_CERT_VERIFY_SZ = 1024, /* max   */
+    CLIENT_HELLO_FIRST =  35,  /* Protocol + RAN_LEN + sizeof(id_len) */
+    MAX_SUITE_NAME     =  48,  /* maximum length of cipher suite string */
+
+    DTLS_TIMEOUT_INIT       =  1, /* default timeout init for DTLS receive  */
+    DTLS_TIMEOUT_MAX        = 64, /* default max timeout for DTLS receive */
+    DTLS_TIMEOUT_MULTIPLIER =  2, /* default timeout multiplier for DTLS recv */
+
+    MAX_PSK_ID_LEN     = 128,  /* max psk identity/hint supported */
+    NULL_TERM_LEN      =   1,  /* length of null '\0' termination character */
+    MAX_PSK_KEY_LEN    =  64,  /* max psk key supported */
+    MIN_PSK_ID_LEN     =   6,  /* min length of identities */
+    MIN_PSK_BINDERS_LEN=  33,  /* min length of binders */
+    MAX_TICKET_AGE_SECS=  10,  /* maximum ticket age in seconds */
+
+    MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4,  /* 4 mb file size alloc limit */
+
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    MAX_EX_DATA        =   5,  /* allow for five items of ex_data */
+#endif
+
+    MAX_X509_SIZE      = 2048, /* max static x509 buffer size */
+    CERT_MIN_SIZE      =  256, /* min PEM cert size with header/footer */
+
+    MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */
+    MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */
+    MAX_NTRU_BITS       =  256, /* max symmetric bit strength */
+    NO_SNIFF           =   0,  /* not sniffing */
+    SNIFF              =   1,  /* currently sniffing */
+
+    HASH_SIG_SIZE      =   2,  /* default SHA1 RSA */
+
+    NO_COPY            =   0,  /* should we copy static buffer for write */
+    COPY               =   1,  /* should we copy static buffer for write */
+
+    INVALID_PEER_ID    = 0xFFFF, /* Initialize value for peer ID. */
+
+    PREV_ORDER         = -1,   /* Sequence number is in previous epoch. */
+    PEER_ORDER         = 1,    /* Peer sequence number for verify. */
+    CUR_ORDER          = 0,    /* Current sequence number. */
+    WRITE_PROTO        = 1,    /* writing a protocol message */
+    READ_PROTO         = 0     /* reading a protocol message */
+};
+
+/* minimum Downgrade Minor version */
+#ifndef WOLFSSL_MIN_DOWNGRADE
+    #ifndef NO_OLD_TLS
+        #define WOLFSSL_MIN_DOWNGRADE TLSv1_MINOR
+    #else
+        #define WOLFSSL_MIN_DOWNGRADE TLSv1_2_MINOR
+    #endif
+#endif
+
+/* Set max implicit IV size for AEAD cipher suites */
+#define AEAD_MAX_IMP_SZ 12
+
+/* Set max explicit IV size for AEAD cipher suites */
+#define AEAD_MAX_EXP_SZ 8
+
+
+#ifndef WOLFSSL_MAX_SUITE_SZ
+    #define WOLFSSL_MAX_SUITE_SZ 300
+    /* 150 suites for now! */
+#endif
+
+/* number of items in the signature algo list */
+#ifndef WOLFSSL_MAX_SIGALGO
+    #define WOLFSSL_MAX_SIGALGO 32
+#endif
+
+
+/* set minimum ECC key size allowed */
+#ifndef WOLFSSL_MIN_ECC_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_ECC_BITS  256
+    #else
+        #define WOLFSSL_MIN_ECC_BITS 224
+    #endif
+#endif /* WOLFSSL_MIN_ECC_BITS */
+#if (WOLFSSL_MIN_ECC_BITS % 8)
+    /* Some ECC keys are not divisable by 8 such as prime239v1 or sect131r1.
+       In these cases round down to the nearest value divisable by 8. The
+       restriction of being divisable by 8 is in place to match wc_ecc_size
+       function from wolfSSL.
+     */
+    #error ECC minimum bit size must be a multiple of 8
+#endif
+#define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8)
+
+/* set minimum RSA key size allowed */
+#ifndef WOLFSSL_MIN_RSA_BITS
+    #ifdef WOLFSSL_MAX_STRENGTH
+        #define WOLFSSL_MIN_RSA_BITS 2048
+    #else
+        #define WOLFSSL_MIN_RSA_BITS 1024
+    #endif
+#endif /* WOLFSSL_MIN_RSA_BITS */
+#if (WOLFSSL_MIN_RSA_BITS % 8)
+    /* This is to account for the example case of a min size of 2050 bits but
+       still allows 2049 bit key. So we need the measurment to be in bytes. */
+    #error RSA minimum bit size must be a multiple of 8
+#endif
+#define MIN_RSAKEY_SZ (WOLFSSL_MIN_RSA_BITS / 8)
+
+#ifdef SESSION_INDEX
+/* Shift values for making a session index */
+#define SESSIDX_ROW_SHIFT 4
+#define SESSIDX_IDX_MASK  0x0F
+#endif
+
+
+/* max cert chain peer depth */
+#ifndef MAX_CHAIN_DEPTH
+    #define MAX_CHAIN_DEPTH 9
+#endif
+
+/* max size of a certificate message payload */
+/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */
+#ifndef MAX_CERTIFICATE_SZ
+    #define MAX_CERTIFICATE_SZ \
+                CERT_HEADER_SZ + \
+                (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH
+#endif
+
+/* max size of a handshake message, currently set to the certificate */
+#ifndef MAX_HANDSHAKE_SZ
+    #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ
+#endif
+
+#ifndef SESSION_TICKET_LEN
+    #define SESSION_TICKET_LEN 256
+#endif
+
+#ifndef SESSION_TICKET_HINT_DEFAULT
+    #define SESSION_TICKET_HINT_DEFAULT 300
+#endif
+
+
+/* don't use extra 3/4k stack space unless need to */
+#ifdef HAVE_NTRU
+    #define MAX_ENCRYPT_SZ MAX_NTRU_ENCRYPT_SZ
+#else
+    #define MAX_ENCRYPT_SZ ENCRYPT_LEN
+#endif
+
+
+/* states */
+enum states {
+    NULL_STATE = 0,
+
+    SERVER_HELLOVERIFYREQUEST_COMPLETE,
+    SERVER_HELLO_RETRY_REQUEST_COMPLETE,
+    SERVER_HELLO_COMPLETE,
+    SERVER_ENCRYPTED_EXTENSIONS_COMPLETE,
+    SERVER_CERT_COMPLETE,
+    SERVER_KEYEXCHANGE_COMPLETE,
+    SERVER_HELLODONE_COMPLETE,
+	SERVER_CHANGECIPHERSPEC_COMPLETE,
+    SERVER_FINISHED_COMPLETE,
+
+    CLIENT_HELLO_COMPLETE,
+    CLIENT_KEYEXCHANGE_COMPLETE,
+	CLIENT_CHANGECIPHERSPEC_COMPLETE,
+    CLIENT_FINISHED_COMPLETE,
+
+    HANDSHAKE_DONE
+};
+
+/* SSL Version */
+typedef struct ProtocolVersion {
+    byte major;
+    byte minor;
+} WOLFSSL_PACK ProtocolVersion;
+
+
+WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
+WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void);
+    WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
+
+    #ifdef WOLFSSL_SESSION_EXPORT
+    WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf,
+                                                                     word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
+                                                                     word32 sz);
+    WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
+    #endif
+#endif
+
+
+/* wolfSSL BIO_METHOD type */
+struct WOLFSSL_BIO_METHOD {
+    byte type;               /* method type */
+};
+
+
+/* wolfSSL BIO type */
+struct WOLFSSL_BIO {
+    WOLFSSL_BUF_MEM* mem_buf;
+    WOLFSSL*     ssl;           /* possible associated ssl */
+#ifndef NO_FILESYSTEM
+    XFILE        file;
+#endif
+    WOLFSSL_BIO* prev;          /* previous in chain */
+    WOLFSSL_BIO* next;          /* next in chain */
+    WOLFSSL_BIO* pair;          /* BIO paired with */
+    void*        heap;          /* user heap hint */
+    byte*        mem;           /* memory buffer */
+    int         wrSz;          /* write buffer size (mem) */
+    int         wrIdx;         /* current index for write buffer */
+    int         rdIdx;         /* current read index */
+    int         readRq;        /* read request */
+    int         memLen;        /* memory buffer length */
+    int         fd;            /* possible file descriptor */
+    int         eof;           /* eof flag */
+    int         flags;
+    byte        type;          /* method type */
+    byte        close;         /* close flag */
+};
+
+
+/* wolfSSL method type */
+struct WOLFSSL_METHOD {
+    ProtocolVersion version;
+    byte            side;         /* connection side, server or client */
+    byte            downgrade;    /* whether to downgrade version, default no */
+};
+
+/* wolfSSL buffer type - internal uses "buffer" type */
+typedef WOLFSSL_BUFFER_INFO buffer;
+
+typedef struct Suites Suites;
+
+
+/* defaults to client */
+WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion);
+
+/* for sniffer */
+WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                            word32 size, word32 totalSz, int sniff);
+WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx);
+/* TLS v1.3 needs these */
+WOLFSSL_LOCAL int  HandleTlsResumption(WOLFSSL* ssl, int bogusID,
+                                       Suites* clSuites);
+WOLFSSL_LOCAL int  DoClientHello(WOLFSSL* ssl, const byte* input, word32*,
+                                 word32);
+#ifdef WOLFSSL_TLS13
+WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 helloSz);
+#endif
+WOLFSSL_LOCAL int  DoServerHello(WOLFSSL* ssl, const byte* input, word32*,
+                                 word32);
+WOLFSSL_LOCAL int  CompleteServerHello(WOLFSSL *ssl);
+WOLFSSL_LOCAL int  CheckVersion(WOLFSSL *ssl, ProtocolVersion pv);
+WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
+                                   word32 hashSigAlgoSz);
+WOLFSSL_LOCAL int  DecodePrivateKey(WOLFSSL *ssl, word16* length);
+#ifdef HAVE_PK_CALLBACKS
+WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl);
+#ifndef NO_ASN
+    WOLFSSL_LOCAL int  InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx);
+#endif
+#endif
+WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl);
+WOLFSSL_LOCAL int  ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size);
+WOLFSSL_LOCAL int  MatchDomainName(const char* pattern, int len, const char* str);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int  CheckAltNames(DecodedCert* dCert, char* domain);
+#endif
+WOLFSSL_LOCAL int  CreateTicket(WOLFSSL* ssl);
+WOLFSSL_LOCAL int  HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz);
+WOLFSSL_LOCAL int  HashOutput(WOLFSSL* ssl, const byte* output, int sz,
+                              int ivSz);
+WOLFSSL_LOCAL int  HashInput(WOLFSSL* ssl, const byte* input, int sz);
+#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl);
+#endif
+#ifdef WOLFSSL_TLS13
+WOLFSSL_LOCAL int  DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
+                                word16 sz, const byte* aad, word16 aadSz);
+WOLFSSL_LOCAL int  DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
+                                           word32* inOutIdx, byte type,
+                                           word32 size, word32 totalSz);
+WOLFSSL_LOCAL int  DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input,
+                                       word32* inOutIdx, word32 totalSz);
+WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
+                                     word32* inOutIdx, word32 helloSz,
+                                     byte* extMsgType);
+#endif
+int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
+                    int pLen, int content);
+
+
+enum {
+    FORCED_FREE = 1,
+    NO_FORCED_FREE = 0
+};
+
+
+/* only use compression extra if using compression */
+#ifdef HAVE_LIBZ
+    #define COMP_EXTRA MAX_COMP_EXTRA
+#else
+    #define COMP_EXTRA 0
+#endif
+
+/* only the sniffer needs space in the buffer for extra MTU record(s) */
+#ifdef WOLFSSL_SNIFFER
+    #define MTU_EXTRA MAX_MTU * 3
+#else
+    #define MTU_EXTRA 0
+#endif
+
+
+/* embedded callbacks require large static buffers, make sure on */
+#ifdef WOLFSSL_CALLBACKS
+    #undef  LARGE_STATIC_BUFFERS
+    #define LARGE_STATIC_BUFFERS
+#endif
+
+
+/* give user option to use 16K static buffers */
+#if defined(LARGE_STATIC_BUFFERS)
+    #define RECORD_SIZE MAX_RECORD_SIZE
+#else
+    #ifdef WOLFSSL_DTLS
+        #define RECORD_SIZE MAX_MTU
+    #else
+        #define RECORD_SIZE 128
+    #endif
+#endif
+
+
+/* user option to turn off 16K output option */
+/* if using small static buffers (default) and SSL_write tries to write data
+   larger than the record we have, dynamically get it, unless user says only
+   write in static buffer chunks  */
+#ifndef STATIC_CHUNKS_ONLY
+    #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE
+#else
+    #define OUTPUT_RECORD_SIZE RECORD_SIZE
+#endif
+
+/* wolfSSL input buffer
+
+   RFC 2246:
+
+   length
+       The length (in bytes) of the following TLSPlaintext.fragment.
+       The length should not exceed 2^14.
+*/
+#if defined(LARGE_STATIC_BUFFERS)
+    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \
+             MTU_EXTRA + MAX_MSG_EXTRA
+#else
+    /* don't fragment memory from the record header */
+    #define STATIC_BUFFER_LEN RECORD_HEADER_SZ
+#endif
+
+typedef struct {
+    ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN];
+    byte*  buffer;       /* place holder for static or dynamic buffer */
+    word32 length;       /* total buffer length used */
+    word32 idx;          /* idx to part of length already consumed */
+    word32 bufferSize;   /* current buffer size */
+    byte   dynamicFlag;  /* dynamic memory currently in use */
+    byte   offset;       /* alignment offset attempt */
+} bufferStatic;
+
+/* Cipher Suites holder */
+struct Suites {
+    word16 suiteSz;                 /* suite length in bytes        */
+    word16 hashSigAlgoSz;           /* SigAlgo extension length in bytes */
+    byte   suites[WOLFSSL_MAX_SUITE_SZ];
+    byte   hashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* sig/algo to offer */
+    byte   setSuites;               /* user set suites from default */
+    byte   hashAlgo;                /* selected hash algorithm */
+    byte   sigAlgo;                 /* selected sig algorithm */
+};
+
+
+WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
+                                         int haveRSAsig, int haveAnon,
+                                         int tls1_2, int keySz);
+WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16,
+                              word16, word16, word16, word16, word16, int);
+WOLFSSL_LOCAL int  MatchSuite(WOLFSSL* ssl, Suites* peerSuites);
+WOLFSSL_LOCAL int  SetCipherList(WOLFSSL_CTX*, Suites*, const char* list);
+
+#ifndef PSK_TYPES_DEFINED
+    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
+                          unsigned int, unsigned char*, unsigned int);
+    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int);
+#endif /* PSK_TYPES_DEFINED */
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \
+   !defined(WOLFSSL_DTLS_EXPORT_TYPES)
+    typedef int (*wc_dtls_export)(WOLFSSL* ssl,
+                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
+#define WOLFSSL_DTLS_EXPORT_TYPES
+#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
+
+
+/* wolfSSL Cipher type just points back to SSL */
+struct WOLFSSL_CIPHER {
+    WOLFSSL* ssl;
+};
+
+
+typedef struct OcspEntry OcspEntry;
+
+#ifdef NO_SHA
+    #define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+#else
+    #define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+#endif
+
+#ifdef NO_ASN
+    /* no_asn won't have */
+    typedef struct CertStatus CertStatus;
+#endif
+
+struct OcspEntry {
+    OcspEntry*  next;                            /* next entry             */
+    byte        issuerHash[OCSP_DIGEST_SIZE];    /* issuer hash            */
+    byte        issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */
+    CertStatus* status;                          /* OCSP response list     */
+    int         totalStatus;                     /* number on list         */
+};
+
+
+#ifndef HAVE_OCSP
+    typedef struct WOLFSSL_OCSP WOLFSSL_OCSP;
+#endif
+
+/* wolfSSL OCSP controller */
+struct WOLFSSL_OCSP {
+    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
+    OcspEntry*            ocspList;      /* OCSP response list */
+    wolfSSL_Mutex         ocspLock;      /* OCSP list lock */
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+    int(*statusCb)(WOLFSSL*, void*);
+#endif
+};
+
+#ifndef MAX_DATE_SIZE
+#define MAX_DATE_SIZE 32
+#endif
+
+typedef struct CRL_Entry CRL_Entry;
+
+#ifdef NO_SHA
+    #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
+#else
+    #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE
+#endif
+
+#ifdef NO_ASN
+    typedef struct RevokedCert RevokedCert;
+#endif
+
+/* Complete CRL */
+struct CRL_Entry {
+    CRL_Entry* next;                      /* next entry */
+    byte    issuerHash[CRL_DIGEST_SIZE];  /* issuer hash                 */
+    /* byte    crlHash[CRL_DIGEST_SIZE];      raw crl data hash           */
+    /* restore the hash here if needed for optimized comparisons */
+    byte    lastDate[MAX_DATE_SIZE]; /* last date updated  */
+    byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
+    byte    lastDateFormat;          /* last date format */
+    byte    nextDateFormat;          /* next date format */
+    RevokedCert* certs;              /* revoked cert list  */
+    int          totalCerts;         /* number on list     */
+    int     verified;
+    byte*   toBeSigned;
+    word32  tbsSz;
+    byte*   signature;
+    word32  signatureSz;
+    word32  signatureOID;
+#if !defined(NO_SKID) && defined(CRL_SKID_READY)
+    byte    extAuthKeyIdSet;
+    byte    extAuthKeyId[KEYID_SIZE];
+#endif
+};
+
+
+typedef struct CRL_Monitor CRL_Monitor;
+
+/* CRL directory monitor */
+struct CRL_Monitor {
+    char* path;      /* full dir path, if valid pointer we're using */
+    int   type;      /* PEM or ASN1 type */
+};
+
+
+#if defined(HAVE_CRL) && defined(NO_FILESYSTEM)
+    #undef HAVE_CRL_MONITOR
+#endif
+
+/* wolfSSL CRL controller */
+struct WOLFSSL_CRL {
+    WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
+    CRL_Entry*            crlList;       /* our CRL list */
+#ifdef HAVE_CRL_IO
+    CbCrlIO               crlIOCb;
+#endif
+    wolfSSL_Mutex         crlLock;       /* CRL list lock */
+    CRL_Monitor           monitors[2];   /* PEM and DER possible */
+#ifdef HAVE_CRL_MONITOR
+    pthread_cond_t        cond;          /* condition to signal setup */
+    pthread_t             tid;           /* monitoring thread */
+    int                   mfd;           /* monitor fd, -1 if no init yet */
+    int                   setup;         /* thread is setup predicate */
+#endif
+    void*                 heap;          /* heap hint for dynamic memory */
+};
+
+
+#ifdef NO_ASN
+    typedef struct Signer Signer;
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    typedef struct TrustedPeerCert TrustedPeerCert;
+#endif
+#endif
+
+
+#ifndef CA_TABLE_SIZE
+    #define CA_TABLE_SIZE 11
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    #define TP_TABLE_SIZE 11
+#endif
+
+/* wolfSSL Certificate Manager */
+struct WOLFSSL_CERT_MANAGER {
+    Signer*         caTable[CA_TABLE_SIZE]; /* the CA signer table */
+    void*           heap;                /* heap helper */
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */
+    wolfSSL_Mutex   tpLock;                  /* trusted peer list lock */
+#endif
+    WOLFSSL_CRL*    crl;                 /* CRL checker */
+    WOLFSSL_OCSP*   ocsp;                /* OCSP checker */
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+                               ||  defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+    WOLFSSL_OCSP*   ocsp_stapling;       /* OCSP checker for OCSP stapling */
+#endif
+    char*           ocspOverrideURL;     /* use this responder */
+    void*           ocspIOCtx;           /* I/O callback CTX */
+    CallbackCACache caCacheCallback;     /* CA cache addition callback */
+    CbMissingCRL    cbMissingCRL;        /* notify through cb of missing crl */
+    CbOCSPIO        ocspIOCb;            /* I/O callback for OCSP lookup */
+    CbOCSPRespFree  ocspRespFreeCb;      /* Frees OCSP Response from IO Cb */
+    wolfSSL_Mutex   caLock;              /* CA list lock */
+    byte            crlEnabled;          /* is CRL on ? */
+    byte            crlCheckAll;         /* always leaf, but all ? */
+    byte            ocspEnabled;         /* is OCSP on ? */
+    byte            ocspCheckAll;        /* always leaf, but all ? */
+    byte            ocspSendNonce;       /* send the OCSP nonce ? */
+    byte            ocspUseOverrideURL;  /* ignore cert's responder, override */
+    byte            ocspStaplingEnabled; /* is OCSP Stapling on ? */
+
+#ifndef NO_RSA
+    short           minRsaKeySz;         /* minimum allowed RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    short           minEccKeySz;         /* minimum allowed ECC key size */
+#endif
+};
+
+WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*);
+WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*);
+WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*);
+WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int);
+WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*);
+
+/* wolfSSL Sock Addr */
+struct WOLFSSL_SOCKADDR {
+    unsigned int sz; /* sockaddr size */
+    void*        sa; /* pointer to the sockaddr_in or sockaddr_in6 */
+};
+
+typedef struct WOLFSSL_DTLS_CTX {
+    WOLFSSL_SOCKADDR peer;
+    int rfd;
+    int wfd;
+} WOLFSSL_DTLS_CTX;
+
+
+typedef struct WOLFSSL_DTLS_PEERSEQ {
+    word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
+                        /* Sliding window for current epoch    */
+    word16 nextEpoch;   /* Expected epoch in next record       */
+    word16 nextSeq_hi;  /* Expected sequence in next record    */
+    word32 nextSeq_lo;
+
+    word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS];
+                        /* Sliding window for old epoch        */
+    word32 prevSeq_lo;
+    word16 prevSeq_hi;  /* Next sequence in allowed old epoch  */
+
+#ifdef WOLFSSL_MULTICAST
+    word16 peerId;
+    word32 highwaterMark;
+#endif
+} WOLFSSL_DTLS_PEERSEQ;
+
+
+#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */
+
+/* keys and secrets
+ * keep as a constant size (no additional ifdefs) for session export */
+typedef struct Keys {
+    byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE];   /* max sizes */
+    byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE];
+    byte client_write_key[MAX_SYM_KEY_SIZE];         /* max sizes */
+    byte server_write_key[MAX_SYM_KEY_SIZE];
+    byte client_write_IV[MAX_WRITE_IV_SZ];               /* max sizes */
+    byte server_write_IV[MAX_WRITE_IV_SZ];
+#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT)
+    byte aead_exp_IV[AEAD_MAX_EXP_SZ];
+    byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ];
+    byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
+#endif
+
+    word32 peer_sequence_number_hi;
+    word32 peer_sequence_number_lo;
+    word32 sequence_number_hi;
+    word32 sequence_number_lo;
+
+#ifdef WOLFSSL_DTLS
+    word16 curEpoch;    /* Received epoch in current record    */
+    word16 curSeq_hi;   /* Received sequence in current record */
+    word32 curSeq_lo;
+#ifdef WOLFSSL_MULTICAST
+    byte   curPeerId;   /* Received peer group ID in current record */
+#endif
+    WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ];
+
+    word16 dtls_peer_handshake_number;
+    word16 dtls_expected_peer_handshake_number;
+
+    word16 dtls_epoch;                          /* Current epoch    */
+    word16 dtls_sequence_number_hi;             /* Current epoch */
+    word32 dtls_sequence_number_lo;
+    word16 dtls_prev_sequence_number_hi;        /* Previous epoch */
+    word32 dtls_prev_sequence_number_lo;
+    word16 dtls_handshake_number;               /* Current tx handshake seq */
+#endif
+
+    word32 encryptSz;             /* last size of encrypted data   */
+    word32 padSz;                 /* how much to advance after decrypt part */
+    byte   encryptionOn;          /* true after change cipher spec */
+    byte   decryptedCur;          /* only decrypt current record once */
+#ifdef WOLFSSL_TLS13
+    byte   updateResponseReq:1;   /* KeyUpdate response from peer required. */
+    byte   keyUpdateRespond:1;    /* KeyUpdate is to be responded to. */
+#endif
+} Keys;
+
+
+
+/** TLS Extensions - RFC 6066 */
+#ifdef HAVE_TLS_EXTENSIONS
+
+typedef enum {
+    TLSX_SERVER_NAME                = 0x0000, /* a.k.a. SNI  */
+    TLSX_MAX_FRAGMENT_LENGTH        = 0x0001,
+    TLSX_TRUNCATED_HMAC             = 0x0004,
+    TLSX_STATUS_REQUEST             = 0x0005, /* a.k.a. OCSP stapling   */
+    TLSX_SUPPORTED_GROUPS           = 0x000a, /* a.k.a. Supported Curves */
+    TLSX_EC_POINT_FORMATS           = 0x000b,
+    TLSX_SIGNATURE_ALGORITHMS       = 0x000d,
+    TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
+    TLSX_STATUS_REQUEST_V2          = 0x0011, /* a.k.a. OCSP stapling v2 */
+    TLSX_QUANTUM_SAFE_HYBRID        = 0x0018, /* a.k.a. QSH  */
+    TLSX_SESSION_TICKET             = 0x0023,
+#ifdef WOLFSSL_TLS13
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX_PRE_SHARED_KEY             = 0x0029,
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+    TLSX_EARLY_DATA                 = 0x002a,
+    #endif
+    TLSX_SUPPORTED_VERSIONS         = 0x002b,
+    TLSX_COOKIE                     = 0x002c,
+    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    TLSX_PSK_KEY_EXCHANGE_MODES     = 0x002d,
+    #endif
+    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    TLSX_POST_HANDSHAKE_AUTH        = 0x0031,
+    #endif
+    #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22)
+    TLSX_KEY_SHARE                  = 0x0028,
+    #else
+    TLSX_SIGNATURE_ALGORITHMS_CERT  = 0x0032,
+    TLSX_KEY_SHARE                  = 0x0033,
+    #endif
+#endif
+    TLSX_RENEGOTIATION_INFO         = 0xff01
+} TLSX_Type;
+
+typedef struct TLSX {
+    TLSX_Type    type; /* Extension Type  */
+    void*        data; /* Extension Data  */
+    word32       val;  /* Extension Value */
+    byte         resp; /* IsResponse Flag */
+    struct TLSX* next; /* List Behavior   */
+} TLSX;
+
+WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
+WOLFSSL_LOCAL void  TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
+WOLFSSL_LOCAL void  TLSX_FreeAll(TLSX* list, void* heap);
+WOLFSSL_LOCAL int   TLSX_SupportExtensions(WOLFSSL* ssl);
+WOLFSSL_LOCAL int   TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest);
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
+WOLFSSL_LOCAL int   TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, 
+                                         word16* pLength);
+WOLFSSL_LOCAL int   TLSX_WriteRequest(WOLFSSL* ssl, byte* output,
+                                       byte msgType, word16* pOffset);
+#endif
+
+#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
+/* TLS 1.3 Certificate messages have extensions. */
+WOLFSSL_LOCAL int   TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, 
+                                          word16* pLength);
+WOLFSSL_LOCAL int   TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, 
+                                        word16* pOffset);
+#endif
+
+WOLFSSL_LOCAL int   TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length,
+                               byte msgType, Suites *suites);
+
+#elif defined(HAVE_SNI)                           \
+   || defined(HAVE_MAX_FRAGMENT)                  \
+   || defined(HAVE_TRUNCATED_HMAC)                \
+   || defined(HAVE_CERTIFICATE_STATUS_REQUEST)    \
+   || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
+   || defined(HAVE_SUPPORTED_CURVES)              \
+   || defined(HAVE_ALPN)                          \
+   || defined(HAVE_QSH)                           \
+   || defined(HAVE_SESSION_TICKET)                \
+   || defined(HAVE_SECURE_RENEGOTIATION)          \
+   || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+
+#error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined.
+
+#endif /* HAVE_TLS_EXTENSIONS */
+
+/** Server Name Indication - RFC 6066 (session 3) */
+#ifdef HAVE_SNI
+
+typedef struct SNI {
+    byte                       type;    /* SNI Type         */
+    union { char* host_name; } data;    /* SNI Data         */
+    struct SNI*                next;    /* List Behavior    */
+    byte                       status;  /* Matching result  */
+#ifndef NO_WOLFSSL_SERVER
+    byte                       options; /* Behavior options */
+#endif
+} SNI;
+
+WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
+                                                       word16 size, void* heap);
+WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
+WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
+                                                                   void** data);
+
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL void   TLSX_SNI_SetOptions(TLSX* extensions, byte type,
+                                                                  byte options);
+WOLFSSL_LOCAL int    TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
+                                         byte type, byte* sni, word32* inOutSz);
+#endif
+
+#endif /* HAVE_SNI */
+
+/* Application-Layer Protocol Negotiation - RFC 7301 */
+#ifdef HAVE_ALPN
+typedef struct ALPN {
+    char*        protocol_name; /* ALPN protocol name */
+    struct ALPN* next;          /* List Behavior      */
+    byte         options;       /* Behavior options */
+    byte         negotiated;    /* ALPN protocol negotiated or not */
+} ALPN;
+
+WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
+                                       void** data, word16 *dataSz);
+
+WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
+                               word16 size, byte options, void* heap);
+
+WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option);
+
+#endif /* HAVE_ALPN */
+
+/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */
+#ifdef HAVE_MAX_FRAGMENT
+
+WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap);
+
+#endif /* HAVE_MAX_FRAGMENT */
+
+/** Truncated HMAC - RFC 6066 (session 7) */
+#ifdef HAVE_TRUNCATED_HMAC
+
+WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap);
+
+#endif /* HAVE_TRUNCATED_HMAC */
+
+/** Certificate Status Request - RFC 6066 (session 8) */
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+typedef struct {
+    byte status_type;
+    byte options;
+    WOLFSSL* ssl;
+    union {
+        OcspRequest ocsp;
+    } request;
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    buffer response;
+#endif
+} CertificateStatusRequest;
+
+WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequest(TLSX** extensions,
+           byte status_type, byte options, WOLFSSL* ssl, void* heap, int devId);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int   TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert,
+                                                                    void* heap);
+#endif
+WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions);
+WOLFSSL_LOCAL int   TLSX_CSR_ForceRequest(WOLFSSL* ssl);
+
+#endif
+
+/** Certificate Status Request v2 - RFC 6961 */
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+typedef struct CSRIv2 {
+    byte status_type;
+    byte options;
+    word16 requests;
+    union {
+        OcspRequest ocsp[1 + MAX_CHAIN_DEPTH];
+    } request;
+    struct CSRIv2* next;
+} CertificateStatusRequestItemV2;
+
+WOLFSSL_LOCAL int   TLSX_UseCertificateStatusRequestV2(TLSX** extensions,
+                         byte status_type, byte options, void* heap, int devId);
+#ifndef NO_CERTS
+WOLFSSL_LOCAL int   TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert,
+                                                       byte isPeer, void* heap);
+#endif
+WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type,
+                                                                    byte index);
+WOLFSSL_LOCAL int   TLSX_CSR2_ForceRequest(WOLFSSL* ssl);
+
+#endif
+
+/** Supported Elliptic Curves - RFC 4492 (session 4) */
+#ifdef HAVE_SUPPORTED_CURVES
+
+typedef struct SupportedCurve {
+    word16 name;                 /* Curve Names */
+    struct SupportedCurve* next; /* List Behavior */
+} SupportedCurve;
+
+typedef struct PointFormat {
+    byte format;                /* PointFormat */
+    struct PointFormat* next;   /* List Behavior */
+} PointFormat;
+
+WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name,
+                                                                    void* heap);
+
+WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point,
+                                                                    void* heap);
+
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first,
+                                                                   byte second);
+WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl);
+#endif
+WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl,
+                                                            int checkSupported);
+
+#endif /* HAVE_SUPPORTED_CURVES */
+
+/** Renegotiation Indication - RFC 5746 */
+#if defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+
+enum key_cache_state {
+    SCR_CACHE_NULL   = 0,       /* empty / begin state */
+    SCR_CACHE_NEEDED,           /* need to cache keys */
+    SCR_CACHE_COPY,             /* we have a cached copy */
+    SCR_CACHE_PARTIAL,          /* partial restore to real keys */
+    SCR_CACHE_COMPLETE          /* complete restore to real keys */
+};
+
+/* Additional Connection State according to rfc5746 section 3.1 */
+typedef struct SecureRenegotiation {
+   byte                 enabled;  /* secure_renegotiation flag in rfc */
+   byte                 startScr; /* server requested client to start scr */
+   enum key_cache_state cache_status;  /* track key cache state */
+   byte                 client_verify_data[TLS_FINISHED_SZ];  /* cached */
+   byte                 server_verify_data[TLS_FINISHED_SZ];  /* cached */
+   byte                 subject_hash[WC_SHA_DIGEST_SIZE];  /* peer cert hash */
+   Keys                 tmp_keys;  /* can't overwrite real keys yet */
+} SecureRenegotiation;
+
+WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap);
+
+#ifdef HAVE_SERVER_RENEGOTIATION_INFO
+WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap);
+#endif
+
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+/** Session Ticket - RFC 5077 (session 3.2) */
+#ifdef HAVE_SESSION_TICKET
+
+typedef struct SessionTicket {
+    word32 lifetime;
+#ifdef WOLFSSL_TLS13
+    word64 seen;
+    word32 ageAdd;
+#endif
+    byte*  data;
+    word16 size;
+} SessionTicket;
+
+WOLFSSL_LOCAL int  TLSX_UseSessionTicket(TLSX** extensions,
+                                             SessionTicket* ticket, void* heap);
+WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
+                                           byte* data, word16 size, void* heap);
+WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap);
+
+#endif /* HAVE_SESSION_TICKET */
+
+/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */
+#ifdef HAVE_QSH
+
+typedef struct QSHScheme {
+    struct QSHScheme* next; /* List Behavior   */
+    byte*             PK;
+    word16            name; /* QSHScheme Names */
+    word16            PKLen;
+} QSHScheme;
+
+typedef struct QSHkey {
+    struct QSHKey* next;
+    word16 name;
+    buffer pub;
+    buffer pri;
+} QSHKey;
+
+typedef struct QSHSecret {
+    QSHScheme* list;
+    buffer* SerSi;
+    buffer* CliSi;
+} QSHSecret;
+
+/* used in key exchange during handshake */
+WOLFSSL_LOCAL int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input,
+                                                  word16 length, byte isServer);
+WOLFSSL_LOCAL word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output);
+WOLFSSL_LOCAL word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest);
+
+/* used by api for setting a specific QSH scheme */
+WOLFSSL_LOCAL int TLSX_UseQSHScheme(TLSX** extensions, word16 name,
+                                         byte* pKey, word16 pKeySz, void* heap);
+
+/* used when parsing in QSHCipher structs */
+WOLFSSL_LOCAL int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn,
+                                                      byte* out, word16* szOut);
+#ifndef NO_WOLFSSL_SERVER
+WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name);
+#endif
+
+#endif /* HAVE_QSH */
+
+#ifdef WOLFSSL_TLS13
+/* Cookie extension information - cookie data. */
+typedef struct Cookie {
+    word16 len;
+    byte   data;
+} Cookie;
+
+WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len,
+                                  byte* mac, byte macSz, int resp);
+
+
+/* Key Share - TLS v1.3 Specification */
+
+/* The KeyShare extension information - entry in a linked list. */
+typedef struct KeyShareEntry {
+    word16                group;     /* NamedGroup               */
+    byte*                 ke;        /* Key exchange data        */
+    word32                keLen;     /* Key exchange data length */
+    void*                 key;       /* Private key              */
+    word32                keyLen;    /* Private key length       */
+    byte*                 pubKey;    /* Public key               */
+    word32                pubKeyLen; /* Public key length        */
+    struct KeyShareEntry* next;      /* List pointer             */
+} KeyShareEntry;
+
+WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len,
+                                    byte* data, KeyShareEntry **kse);
+WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
+WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl);
+WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl);
+
+
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+#ifndef WOLFSSL_TLS13_DRAFT_18
+/* Ticket nonce - for deriving PSK.
+ * Length allowed to be: 1..255. Only support 4 bytes.
+ */
+typedef struct TicketNonce {
+    byte len;
+    byte data[MAX_TICKET_NONCE_SZ];
+} TicketNonce;
+#endif
+
+/* The PreSharedKey extension information - entry in a linked list. */
+typedef struct PreSharedKey {
+    word16               identityLen;             /* Length of identity */
+    byte*                identity;                /* PSK identity       */
+    word32               ticketAge;               /* Age of the ticket  */
+    byte                 cipherSuite0;            /* Cipher Suite       */
+    byte                 cipherSuite;             /* Cipher Suite       */
+    word32               binderLen;               /* Length of HMAC     */
+    byte                 binder[WC_MAX_DIGEST_SIZE]; /* HMAC of hanshake   */
+    byte                 hmac;                    /* HMAC algorithm     */
+    byte                 resumption:1;            /* Resumption PSK     */
+    byte                 chosen:1;                /* Server's choice    */
+    struct PreSharedKey* next;                    /* List pointer       */
+} PreSharedKey;
+
+WOLFSSL_LOCAL word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list,
+                                                    byte* output, byte msgType);
+WOLFSSL_LOCAL word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list,
+                                                      byte msgType);
+WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity,
+                                        word16 len, word32 age, byte hmac,
+                                        byte cipherSuite0, byte cipherSuite,
+                                        byte resumption,
+                                        PreSharedKey **preSharedKey);
+
+/* The possible Pre-Shared Key key exchange modes. */
+enum PskKeyExchangeMode {
+    PSK_KE,
+    PSK_DHE_KE
+};
+
+/* User can define this. */
+#ifndef WOLFSSL_DEF_PSK_CIPHER
+#define WOLFSSL_DEF_PSK_CIPHER    TLS_AES_128_GCM_SHA256
+#endif
+
+WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes);
+
+#ifdef WOLFSSL_EARLY_DATA
+WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max);
+#endif
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+
+
+/* The types of keys to derive for. */
+enum DeriveKeyType {
+    no_key,
+    early_data_key,
+    handshake_key,
+    traffic_key,
+    update_traffic_key
+};
+
+/* The key update request values for KeyUpdate message. */
+enum KeyUpdateRequest {
+    update_not_requested,
+    update_requested
+};
+#endif /* WOLFSSL_TLS13 */
+
+
+#ifdef OPENSSL_EXTRA
+enum SetCBIO {
+    WOLFSSL_CBIO_NONE = 0,
+    WOLFSSL_CBIO_RECV = 0x1,
+    WOLFSSL_CBIO_SEND = 0x2, 
+};
+#endif
+
+/* wolfSSL context type */
+struct WOLFSSL_CTX {
+    WOLFSSL_METHOD* method;
+#ifdef SINGLE_THREADED
+    WC_RNG*         rng;          /* to be shared with WOLFSSL w/o locking */
+#endif
+    wolfSSL_Mutex   countMutex;   /* reference count mutex */
+    int         refCount;         /* reference count */
+    int         err;              /* error code in case of mutex not created */
+#ifndef NO_DH
+    buffer      serverDH_P;
+    buffer      serverDH_G;
+#endif
+#ifndef NO_CERTS
+    DerBuffer*  certificate;
+    DerBuffer*  certChain;
+                 /* chain after self, in DER, with leading size for each cert */
+    #ifdef OPENSSL_EXTRA
+    WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;
+    #endif
+    #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
+        defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY)
+    WOLF_STACK_OF(WOLFSSL_X509)* x509Chain;
+    #endif
+#ifdef WOLFSSL_TLS13
+    int         certChainCnt;
+#endif
+    DerBuffer*  privateKey;
+    byte        privateKeyType;
+    int         privateKeySz;
+    WOLFSSL_CERT_MANAGER* cm;      /* our cert manager, ctx owns SSL will use */
+#endif
+#ifdef KEEP_OUR_CERT
+    WOLFSSL_X509*    ourCert;     /* keep alive a X509 struct of cert */
+    int              ownOurCert;  /* Dispose of certificate if we own */
+#endif
+    Suites*     suites;           /* make dynamic, user may not need/set */
+    void*       heap;             /* for user memory overrides */
+    byte        verifyDepth;
+    byte        verifyPeer:1;
+    byte        verifyNone:1;
+    byte        failNoCert:1;
+    byte        failNoCertxPSK:1; /* fail if no cert with the exception of PSK*/
+    byte        sessionCacheOff:1;
+    byte        sessionCacheFlushOff:1;
+#ifdef HAVE_EXT_CACHE
+    byte        internalCacheOff:1;
+#endif
+    byte        sendVerify;       /* for client side (can not be single bit) */
+    byte        haveRSA:1;        /* RSA available */
+    byte        haveECC:1;        /* ECC available */
+    byte        haveDH:1;         /* server DH parms set by user */
+    byte        haveNTRU:1;       /* server private NTRU  key loaded */
+    byte        haveECDSAsig:1;   /* server cert signed w/ ECDSA */
+    byte        haveStaticECC:1;  /* static server ECC private key */
+    byte        partialWrite:1;   /* only one msg per write call */
+    byte        quietShutdown:1;  /* don't send close notify */
+    byte        groupMessages:1;  /* group handshake messages before sending */
+    byte        minDowngrade;     /* minimum downgrade version */
+    byte        haveEMS:1;        /* have extended master secret extension */
+    byte        useClientOrder:1; /* Use client's cipher preference order */
+#ifdef WOLFSSL_TLS13
+    byte        noTicketTls13:1;  /* Server won't create new Ticket */
+    byte        noPskDheKe:1;     /* Don't use (EC)DHE with PSK */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    byte        postHandshakeAuth:1;  /* Post-handshake auth supported. */
+#endif
+#ifdef WOLFSSL_MULTICAST
+    byte        haveMcast;        /* multicast requested */
+    byte        mcastID;          /* multicast group ID */
+#endif
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+    byte        dtlsSctp;         /* DTLS-over-SCTP mode */
+    word16      dtlsMtuSz;        /* DTLS MTU size */
+#endif
+#ifndef NO_DH
+    word16      minDhKeySz;       /* minimum DH key size */
+    word16      maxDhKeySz;       /* maximum DH key size */
+#endif
+#ifndef NO_RSA
+    short       minRsaKeySz;      /* minimum RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    short       minEccKeySz;      /* minimum ECC key size */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte              sessionCtx[ID_LEN]; /* app session context ID */
+    word32            disabledCurves;   /* curves disabled by user */
+    unsigned long     mask;             /* store SSL_OP_ flags */
+    const unsigned char *alpn_cli_protos;/* ALPN client protocol list */
+    unsigned int         alpn_cli_protos_len;
+    byte              sessionCtxSz;
+    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
+    CallbackInfoState* CBIS;      /* used to get info about SSL state */
+#endif
+    CallbackIORecv CBIORecv;
+    CallbackIOSend CBIOSend;
+#ifdef WOLFSSL_DTLS
+    CallbackGenCookie CBIOCookie;       /* gen cookie callback */
+#ifdef WOLFSSL_SESSION_EXPORT
+    wc_dtls_export  dtls_export;        /* export function for DTLS session */
+    CallbackGetPeer CBGetPeer;
+    CallbackSetPeer CBSetPeer;
+#endif
+#endif /* WOLFSSL_DTLS */
+    VerifyCallback  verifyCallback;     /* cert verification callback */
+    word32          timeout;            /* session timeout */
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    word32          ecdhCurveOID;       /* curve Ecc_Sum */
+#endif
+#ifdef HAVE_ECC
+    word16          eccTempKeySz;       /* in octets 20 - 66 */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    word32          pkCurveOID;         /* curve Ecc_Sum */
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    byte        havePSK;                /* psk key set by user */
+    wc_psk_client_callback client_psk_cb;  /* client callback */
+    wc_psk_server_callback server_psk_cb;  /* server callback */
+    char        server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+#ifdef WOLFSSL_TLS13
+    word16          group[WOLFSSL_MAX_GROUP_COUNT];
+    byte            numGroups;
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    word32          maxEarlyDataSz;
+#endif
+#ifdef HAVE_ANON
+    byte        haveAnon;               /* User wants to allow Anon suites */
+#endif /* HAVE_ANON */
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    pem_password_cb* passwd_cb;
+    void*            passwd_userdata;
+#endif
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+    WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */
+    WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */
+    byte            readAhead;
+    void*           userPRFArg; /* passed to prf callback */
+#endif
+#ifdef HAVE_EX_DATA
+    void*           ex_data[MAX_EX_DATA];
+#endif
+#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
+    CallbackALPNSelect alpnSelect;
+    void*              alpnSelectArg;
+#endif
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)))
+    CallbackSniRecv sniRecvCb;
+    void*           sniRecvCbArg;
+#endif
+#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS)
+    CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */
+    word32      mcastFirstSeq;    /* first trigger level */
+    word32      mcastSecondSeq;   /* second tigger level */
+    word32      mcastMaxSeq;      /* max level */
+#endif
+#ifdef HAVE_OCSP
+    WOLFSSL_OCSP      ocsp;
+#endif
+    int             devId;              /* async device id to use */
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
+    #ifndef NO_WOLFSSL_SERVER
+        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+         || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+            OcspRequest* certOcspRequest;
+        #endif
+        #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+            OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH];
+        #endif
+    #endif
+    #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
+        SessionTicketEncCb ticketEncCb;   /* enc/dec session ticket Cb */
+        void*              ticketEncCtx;  /* session encrypt context */
+        int                ticketHint;    /* ticket hint in seconds */
+    #endif
+    #ifdef HAVE_SUPPORTED_CURVES
+        byte userCurves;                  /* indicates user called wolfSSL_CTX_UseSupportedCurve */
+    #endif
+#endif
+#ifdef ATOMIC_USER
+    CallbackMacEncrypt    MacEncryptCb;    /* Atomic User Mac/Encrypt Cb */
+    CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        CallbackEccKeyGen EccKeyGenCb;  /* User EccKeyGen Callback Handler */
+        CallbackEccSign   EccSignCb;    /* User EccSign   Callback handler */
+        CallbackEccVerify EccVerifyCb;  /* User EccVerify Callback handler */
+        CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */
+        #ifdef HAVE_ED25519
+            /* User Ed25519Sign   Callback handler */
+            CallbackEd25519Sign   Ed25519SignCb;
+            /* User Ed25519Verify Callback handler */
+            CallbackEd25519Verify Ed25519VerifyCb;
+        #endif
+        #ifdef HAVE_CURVE25519
+            /* User X25519 KeyGen Callback Handler */
+            CallbackX25519KeyGen X25519KeyGenCb;
+            /* User X25519 SharedSecret Callback handler */
+            CallbackX25519SharedSecret X25519SharedSecretCb;
+        #endif
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        CallbackDhAgree DhAgreeCb;      /* User DH Agree Callback handler */
+    #endif
+    #ifndef NO_RSA
+        CallbackRsaSign   RsaSignCb;      /* User RsaSign Callback handler (priv key) */
+        CallbackRsaVerify RsaVerifyCb;    /* User RsaVerify Callback handler (pub key) */
+        CallbackRsaVerify RsaSignCheckCb; /* User VerifyRsaSign Callback handler (priv key) */
+        #ifdef WC_RSA_PSS
+            CallbackRsaPssSign   RsaPssSignCb;       /* User RsaSign (priv key) */
+            CallbackRsaPssVerify RsaPssVerifyCb;     /* User RsaVerify (pub key) */
+            CallbackRsaPssVerify RsaPssSignCheckCb; /* User VerifyRsaSign (priv key) */
+        #endif
+        CallbackRsaEnc    RsaEncCb;     /* User Rsa Public Encrypt  handler */
+        CallbackRsaDec    RsaDecCb;     /* User Rsa Private Decrypt handler */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_WOLF_EVENT
+        WOLF_EVENT_QUEUE event_queue;
+#endif /* HAVE_WOLF_EVENT */
+#ifdef HAVE_EXT_CACHE
+        WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*);
+        int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*);
+        void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*);
+#endif
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256)
+        Srp*  srp;  /* TLS Secure Remote Password Protocol*/
+        byte* srp_password;
+#endif
+};
+
+WOLFSSL_LOCAL
+WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap);
+WOLFSSL_LOCAL
+int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*, void* heap);
+WOLFSSL_LOCAL
+void FreeSSL_Ctx(WOLFSSL_CTX*);
+WOLFSSL_LOCAL
+void SSL_CtxResourceFree(WOLFSSL_CTX*);
+
+WOLFSSL_LOCAL
+int DeriveTlsKeys(WOLFSSL* ssl);
+WOLFSSL_LOCAL
+int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+                          word32 inSz, word16 sz);
+
+#ifndef NO_CERTS
+    WOLFSSL_LOCAL
+    int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify);
+    WOLFSSL_LOCAL
+    int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_LOCAL
+    int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify);
+    WOLFSSL_LOCAL
+    int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash);
+#endif
+#endif
+
+/* All cipher suite related info
+ * Keep as a constant size (no ifdefs) for session export */
+typedef struct CipherSpecs {
+    word16 key_size;
+    word16 iv_size;
+    word16 block_size;
+    word16 aead_mac_size;
+    byte bulk_cipher_algorithm;
+    byte cipher_type;               /* block, stream, or aead */
+    byte mac_algorithm;
+    byte kea;                       /* key exchange algo */
+    byte sig_algo;
+    byte hash_size;
+    byte pad_size;
+    byte static_ecdh;
+} CipherSpecs;
+
+
+void InitCipherSpecs(CipherSpecs* cs);
+
+
+/* Supported Message Authentication Codes from page 43 */
+enum MACAlgorithm {
+    no_mac,
+    md5_mac,
+    sha_mac,
+    sha224_mac,
+    sha256_mac,     /* needs to match external KDF_MacAlgorithm */
+    sha384_mac,
+    sha512_mac,
+    rmd_mac,
+    blake2b_mac
+};
+
+
+/* Supported Key Exchange Protocols */
+enum KeyExchangeAlgorithm {
+    no_kea,
+    rsa_kea,
+    diffie_hellman_kea,
+    fortezza_kea,
+    psk_kea,
+    dhe_psk_kea,
+    ecdhe_psk_kea,
+    ntru_kea,
+    ecc_diffie_hellman_kea,
+    ecc_static_diffie_hellman_kea       /* for verify suite only */
+};
+
+
+/* Supported Authentication Schemes */
+enum SignatureAlgorithm {
+    anonymous_sa_algo = 0,
+    rsa_sa_algo       = 1,
+    dsa_sa_algo       = 2,
+    ecc_dsa_sa_algo   = 3,
+    rsa_pss_sa_algo   = 8,
+    ed25519_sa_algo   = 9
+};
+
+
+/* Supprted ECC Curve Types */
+enum EccCurves {
+    named_curve = 3
+};
+
+
+/* Valid client certificate request types from page 27 */
+enum ClientCertificateType {
+    rsa_sign            = 1,
+    dss_sign            = 2,
+    rsa_fixed_dh        = 3,
+    dss_fixed_dh        = 4,
+    rsa_ephemeral_dh    = 5,
+    dss_ephemeral_dh    = 6,
+    fortezza_kea_cert   = 20,
+    ecdsa_sign          = 64,
+    rsa_fixed_ecdh      = 65,
+    ecdsa_fixed_ecdh    = 66
+};
+
+
+enum CipherType { stream, block, aead };
+
+
+
+
+
+
+/* cipher for now */
+typedef struct Ciphers {
+#ifdef BUILD_ARC4
+    Arc4*   arc4;
+#endif
+#ifdef BUILD_DES3
+    Des3*   des3;
+#endif
+#if defined(BUILD_AES) || defined(BUILD_AESGCM)
+    Aes*    aes;
+    #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) || defined(WOLFSSL_TLS13)
+        byte* additional;
+        byte* nonce;
+    #endif
+#endif
+#ifdef HAVE_CAMELLIA
+    Camellia* cam;
+#endif
+#ifdef HAVE_CHACHA
+    ChaCha*   chacha;
+#endif
+#ifdef HAVE_HC128
+    HC128*  hc128;
+#endif
+#ifdef BUILD_RABBIT
+    Rabbit* rabbit;
+#endif
+#ifdef HAVE_IDEA
+    Idea* idea;
+#endif
+    byte    state;
+    byte    setup;       /* have we set it up flag for detection */
+} Ciphers;
+
+
+#ifdef HAVE_ONE_TIME_AUTH
+/* Ciphers for one time authentication such as poly1305 */
+typedef struct OneTimeAuth {
+#ifdef HAVE_POLY1305
+    Poly1305* poly1305;
+#endif
+    byte    setup;      /* flag for if a cipher has been set */
+
+} OneTimeAuth;
+#endif
+
+
+WOLFSSL_LOCAL void InitCiphers(WOLFSSL* ssl);
+WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl);
+
+
+/* hashes type */
+typedef struct Hashes {
+    #if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+        byte md5[WC_MD5_DIGEST_SIZE];
+    #endif
+    #if !defined(NO_SHA)
+        byte sha[WC_SHA_DIGEST_SIZE];
+    #endif
+    #ifndef NO_SHA256
+        byte sha256[WC_SHA256_DIGEST_SIZE];
+    #endif
+    #ifdef WOLFSSL_SHA384
+        byte sha384[WC_SHA384_DIGEST_SIZE];
+    #endif
+    #ifdef WOLFSSL_SHA512
+        byte sha512[WC_SHA512_DIGEST_SIZE];
+    #endif
+} Hashes;
+
+WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes);
+
+#ifdef WOLFSSL_TLS13
+typedef union Digest {
+#ifndef NO_WOLFSSL_SHA256
+    wc_Sha256 sha256;
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384 sha384;
+#endif
+#ifdef WOLFSSL_SHA512
+    wc_Sha512 sha512;
+#endif
+} Digest;
+#endif
+
+/* Static x509 buffer */
+typedef struct x509_buffer {
+    int  length;                  /* actual size */
+    byte buffer[MAX_X509_SIZE];   /* max static cert size */
+} x509_buffer;
+
+
+/* wolfSSL X509_CHAIN, for no dynamic memory SESSION_CACHE */
+struct WOLFSSL_X509_CHAIN {
+    int         count;                    /* total number in chain */
+    x509_buffer certs[MAX_CHAIN_DEPTH];   /* only allow max depth 4 for now */
+};
+
+
+/* wolfSSL session type */
+struct WOLFSSL_SESSION {
+    word32             bornOn;                    /* create time in seconds   */
+    word32             timeout;                   /* timeout in seconds       */
+    byte               sessionID[ID_LEN];         /* id for protocol          */
+    byte               sessionIDSz;
+    byte               masterSecret[SECRET_LEN];  /* stored secret            */
+    word16             haveEMS;                   /* ext master secret flag   */
+#ifdef SESSION_CERTS
+    WOLFSSL_X509_CHAIN chain;                     /* peer cert chain, static  */
+    #ifdef WOLFSSL_ALT_CERT_CHAINS
+    WOLFSSL_X509_CHAIN altChain;                  /* peer alt cert chain, static */
+    #endif
+#endif
+#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SESSION_TICKET))
+    ProtocolVersion    version;                   /* which version was used   */
+    byte               cipherSuite0;              /* first byte, normally 0   */
+    byte               cipherSuite;               /* 2nd byte, actual suite   */
+#endif
+#ifndef NO_CLIENT_CACHE
+    word16             idLen;                     /* serverID length          */
+    byte               serverID[SERVER_ID_LEN];   /* for easier client lookup */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte               sessionCtxSz;              /* sessionCtx length        */
+    byte               sessionCtx[ID_LEN];        /* app specific context id  */
+#endif
+#ifdef WOLFSSL_TLS13
+    word16             namedGroup;
+#endif
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    #ifdef WOLFSSL_TLS13
+    word32             ticketSeen;                /* Time ticket seen (ms) */
+    word32             ticketAdd;                 /* Added by client */
+        #ifndef WOLFSSL_TLS13_DRAFT_18
+    TicketNonce        ticketNonce;               /* Nonce used to derive PSK */
+        #endif
+    #endif
+    #ifdef WOLFSSL_EARLY_DATA
+    word32             maxEarlyDataSz;
+    #endif
+#endif
+#ifdef HAVE_SESSION_TICKET
+    byte*              ticket;
+    word16             ticketLen;
+    byte               staticTicket[SESSION_TICKET_LEN];
+    byte               isDynamic;
+#endif
+#ifdef HAVE_EXT_CACHE
+    byte               isAlloced;
+#endif
+#ifdef HAVE_EX_DATA
+    void*              ex_data[MAX_EX_DATA];
+#endif
+};
+
+
+WOLFSSL_LOCAL
+WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte);
+WOLFSSL_LOCAL
+int          SetSession(WOLFSSL*, WOLFSSL_SESSION*);
+
+typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int);
+
+#ifndef NO_CLIENT_CACHE
+    WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int);
+#endif
+
+/* client connect state for nonblocking restart */
+enum ConnectState {
+    CONNECT_BEGIN = 0,
+    CLIENT_HELLO_SENT,
+    HELLO_AGAIN,               /* HELLO_AGAIN s for DTLS case */
+    HELLO_AGAIN_REPLY,
+    FIRST_REPLY_DONE,
+    FIRST_REPLY_FIRST,
+    FIRST_REPLY_SECOND,
+    FIRST_REPLY_THIRD,
+    FIRST_REPLY_FOURTH,
+    FINISHED_DONE,
+    SECOND_REPLY_DONE
+};
+
+
+/* server accept state for nonblocking restart */
+enum AcceptState {
+    ACCEPT_BEGIN = 0,
+    ACCEPT_CLIENT_HELLO_DONE,
+    ACCEPT_HELLO_RETRY_REQUEST_DONE,
+    ACCEPT_FIRST_REPLY_DONE,
+    SERVER_HELLO_SENT,
+    SERVER_EXTENSIONS_SENT,
+    CERT_SENT,
+    CERT_VERIFY_SENT,
+    CERT_STATUS_SENT,
+    KEY_EXCHANGE_SENT,
+    CERT_REQ_SENT,
+    SERVER_HELLO_DONE,
+    ACCEPT_SECOND_REPLY_DONE,
+    TICKET_SENT,
+    CHANGE_CIPHER_SENT,
+    ACCEPT_FINISHED_DONE,
+    ACCEPT_THIRD_REPLY_DONE
+};
+
+/* TLS 1.3 server accept state for nonblocking restart */
+enum AcceptStateTls13 {
+    TLS13_ACCEPT_BEGIN = 0,
+    TLS13_ACCEPT_CLIENT_HELLO_DONE,
+    TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE,
+    TLS13_ACCEPT_FIRST_REPLY_DONE,
+    TLS13_ACCEPT_SECOND_REPLY_DONE,
+    TLS13_SERVER_HELLO_SENT,
+    TLS13_ACCEPT_THIRD_REPLY_DONE,
+    TLS13_SERVER_EXTENSIONS_SENT,
+    TLS13_CERT_REQ_SENT,
+    TLS13_CERT_SENT,
+    TLS13_CERT_VERIFY_SENT,
+    TLS13_ACCEPT_FINISHED_SENT,
+    TLS13_PRE_TICKET_SENT,
+    TLS13_ACCEPT_FINISHED_DONE,
+    TLS13_TICKET_SENT
+};
+
+/* buffers for struct WOLFSSL */
+typedef struct Buffers {
+    bufferStatic    inputBuffer;
+    bufferStatic    outputBuffer;
+    buffer          domainName;            /* for client check */
+    buffer          clearOutputBuffer;
+    buffer          sig;                   /* signature data */
+    buffer          digest;                /* digest data */
+    int             prevSent;              /* previous plain text bytes sent
+                                              when got WANT_WRITE            */
+    int             plainSz;               /* plain text bytes in buffer to send
+                                              when got WANT_WRITE            */
+    byte            weOwnCert;             /* SSL own cert flag */
+    byte            weOwnCertChain;        /* SSL own cert chain flag */
+    byte            weOwnKey;              /* SSL own key  flag */
+    byte            weOwnDH;               /* SSL own dh (p,g)  flag */
+#ifndef NO_DH
+    buffer          serverDH_P;            /* WOLFSSL_CTX owns, unless we own */
+    buffer          serverDH_G;            /* WOLFSSL_CTX owns, unless we own */
+    buffer          serverDH_Pub;
+    buffer          serverDH_Priv;
+    DhKey*          serverDH_Key;
+#endif
+#ifndef NO_CERTS
+    DerBuffer*      certificate;           /* WOLFSSL_CTX owns, unless we own */
+    DerBuffer*      key;                   /* WOLFSSL_CTX owns, unless we own */
+    byte            keyType;               /* Type of key: RSA, ECC, Ed25519 */
+    int             keySz;                 /* Size of RSA key */
+    DerBuffer*      certChain;             /* WOLFSSL_CTX owns, unless we own */
+                 /* chain after self, in DER, with leading size for each cert */
+#ifdef WOLFSSL_TLS13
+    int             certChainCnt;
+    DerBuffer*      certExts;
+#endif
+#endif
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+    buffer          tls13CookieSecret;     /* HRR cookie secret */
+#endif
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_DTLS_CTX dtlsCtx;              /* DTLS connection context */
+    #ifndef NO_WOLFSSL_SERVER
+        buffer       dtlsCookieSecret;     /* DTLS cookie secret */
+    #endif /* NO_WOLFSSL_SERVER */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        buffer peerEccDsaKey;              /* we own for Ecc Verify Callbacks */
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        buffer peerEd25519Key;             /* for Ed25519 Verify Callbacks */
+    #endif /* HAVE_ED25519 */
+    #ifndef NO_RSA
+        buffer peerRsaKey;                 /* we own for Rsa Verify Callbacks */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+} Buffers;
+
+/* sub-states for send/do key share (key exchange) */
+enum asyncState {
+    TLS_ASYNC_BEGIN = 0,
+    TLS_ASYNC_BUILD,
+    TLS_ASYNC_DO,
+    TLS_ASYNC_VERIFY,
+    TLS_ASYNC_FINALIZE,
+    TLS_ASYNC_END
+};
+
+/* sub-states for build message */
+enum buildMsgState {
+    BUILD_MSG_BEGIN = 0,
+    BUILD_MSG_SIZE,
+    BUILD_MSG_HASH,
+    BUILD_MSG_VERIFY_MAC,
+    BUILD_MSG_ENCRYPT,
+};
+
+/* sub-states for cipher operations */
+enum cipherState {
+    CIPHER_STATE_BEGIN = 0,
+    CIPHER_STATE_DO,
+    CIPHER_STATE_END,
+};
+
+typedef struct Options {
+#ifndef NO_PSK
+    wc_psk_client_callback client_psk_cb;
+    wc_psk_server_callback server_psk_cb;
+#endif /* NO_PSK */
+#ifdef OPENSSL_EXTRA
+    unsigned long     mask; /* store SSL_OP_ flags */
+#endif
+
+    /* on/off or small bit flags, optimize layout */
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    word16            havePSK:1;            /* psk key set by user */
+#endif /* HAVE_SESSION_TICKET || !NO_PSK */
+    word16            sendVerify:2;     /* false = 0, true = 1, sendBlank = 2 */
+    word16            sessionCacheOff:1;
+    word16            sessionCacheFlushOff:1;
+#ifdef HAVE_EXT_CACHE
+    word16            internalCacheOff:1;
+#endif
+    word16            side:1;             /* client or server end */
+    word16            verifyPeer:1;
+    word16            verifyNone:1;
+    word16            failNoCert:1;
+    word16            failNoCertxPSK:1;   /* fail for no cert except with PSK */
+    word16            downgrade:1;        /* allow downgrade of versions */
+    word16            resuming:1;
+    word16            haveSessionId:1;    /* server may not send */
+    word16            tls:1;              /* using TLS ? */
+    word16            tls1_1:1;           /* using TLSv1.1+ ? */
+    word16            tls1_3:1;           /* using TLSv1.3+ ? */
+    word16            dtls:1;             /* using datagrams ? */
+    word16            connReset:1;        /* has the peer reset */
+    word16            isClosed:1;         /* if we consider conn closed */
+    word16            closeNotify:1;      /* we've received a close notify */
+    word16            sentNotify:1;       /* we've sent a close notify */
+    word16            usingCompression:1; /* are we using compression */
+    word16            haveRSA:1;          /* RSA available */
+    word16            haveECC:1;          /* ECC available */
+    word16            haveDH:1;           /* server DH parms set by user */
+    word16            haveNTRU:1;         /* server NTRU  private key loaded */
+    word16            haveQSH:1;          /* have QSH ability */
+    word16            haveECDSAsig:1;     /* server ECDSA signed cert */
+    word16            haveStaticECC:1;    /* static server ECC private key */
+    word16            havePeerCert:1;     /* do we have peer's cert */
+    word16            havePeerVerify:1;   /* and peer's cert verify */
+    word16            usingPSK_cipher:1;  /* are using psk as cipher */
+    word16            usingAnon_cipher:1; /* are we using an anon cipher */
+    word16            noPskDheKe:1;       /* Don't use (EC)DHE with PSK */
+    word16            sendAlertState:1;   /* nonblocking resume */
+    word16            partialWrite:1;     /* only one msg per write call */
+    word16            quietShutdown:1;    /* don't send close notify */
+    word16            certOnly:1;         /* stop once we get cert */
+    word16            groupMessages:1;    /* group handshake messages */
+    word16            saveArrays:1;       /* save array Memory for user get keys
+                                           or psk */
+    word16            weOwnRng:1;         /* will be true unless CTX owns */
+    word16            haveEMS:1;          /* using extended master secret */
+#ifdef HAVE_POLY1305
+    word16            oldPoly:1;        /* set when to use old rfc way of poly*/
+#endif
+#ifdef HAVE_ANON
+    word16            haveAnon:1;       /* User wants to allow Anon suites */
+#endif
+#ifdef HAVE_SESSION_TICKET
+    word16            createTicket:1;     /* Server to create new Ticket */
+    word16            useTicket:1;        /* Use Ticket not session cache */
+    word16            rejectTicket:1;     /* Callback rejected ticket */
+#ifdef WOLFSSL_TLS13
+    word16            noTicketTls13:1;    /* Server won't create new Ticket */
+#endif
+#endif
+#ifdef WOLFSSL_DTLS
+    word16            dtlsUseNonblock:1;  /* are we using nonblocking socket */
+    word16            dtlsHsRetain:1;     /* DTLS retaining HS data */
+    word16            haveMcast:1;        /* using multicast ? */
+#ifdef WOLFSSL_SCTP
+    word16            dtlsSctp:1;         /* DTLS-over-SCTP mode */
+#endif
+#endif
+#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES)
+    word16            userCurves:1;       /* indicates user called wolfSSL_UseSupportedCurve */
+#endif
+    word16            keepResources:1;    /* Keep resources after handshake */
+    word16            useClientOrder:1;   /* Use client's cipher order */
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    word16            postHandshakeAuth:1;/* Client send post_handshake_auth
+                                           * extendion. */
+#endif
+#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
+    word16            sendCookie:1;       /* Server creates a Cookie in HRR */
+#endif
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+    word16            usingAltCertChain:1;/* Alternate cert chain was used */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
+    word16            sentChangeCipher:1; /* Change Cipher Spec sent */
+#endif
+#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \
+                                                !defined(NO_ED25519_CLIENT_AUTH)
+    word16            cacheMessages:1;    /* Cache messages for sign/verify */
+#endif
+
+    /* need full byte values for this section */
+    byte            processReply;           /* nonblocking resume */
+    byte            cipherSuite0;           /* first byte, normally 0 */
+    byte            cipherSuite;            /* second byte, actual suite */
+    byte            serverState;
+    byte            clientState;
+    byte            handShakeState;
+    byte            handShakeDone;      /* at least one handshake complete */
+    byte            minDowngrade;       /* minimum downgrade version */
+    byte            connectState;       /* nonblocking resume */
+    byte            acceptState;        /* nonblocking resume */
+    byte            asyncState;         /* sub-state for enum asyncState */
+    byte            buildMsgState;      /* sub-state for enum buildMsgState */
+    byte            alertCount;         /* detect warning dos attempt */
+#ifdef WOLFSSL_MULTICAST
+    word16          mcastID;            /* Multicast group ID */
+#endif
+#ifndef NO_DH
+    word16          minDhKeySz;         /* minimum DH key size */
+    word16          maxDhKeySz;         /* minimum DH key size */
+    word16          dhKeySz;            /* actual DH key size */
+#endif
+#ifndef NO_RSA
+    short           minRsaKeySz;      /* minimum RSA key size */
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    short           minEccKeySz;      /* minimum ECC key size */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte            verifyDepth;      /* maximum verification depth */
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    word16          pskIdIndex;
+    word32          maxEarlyDataSz;
+#endif
+#ifdef WOLFSSL_TLS13
+    byte            oldMinor;          /* client preferred version < TLS 1.3 */
+#endif
+} Options;
+
+typedef struct Arrays {
+    byte*           pendingMsg;         /* defrag buffer */
+    byte*           preMasterSecret;
+    word32          preMasterSz;        /* differs for DH, actual size */
+    word32          pendingMsgSz;       /* defrag buffer size */
+    word32          pendingMsgOffset;   /* current offset into defrag buffer */
+#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
+    word32          psk_keySz;          /* actual size */
+    char            client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+    char            server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
+    byte            psk_key[MAX_PSK_KEY_LEN];
+#endif
+    byte            clientRandom[RAN_LEN];
+    byte            serverRandom[RAN_LEN];
+    byte            sessionID[ID_LEN];
+    byte            sessionIDSz;
+#ifdef WOLFSSL_TLS13
+    byte            clientSecret[SECRET_LEN];
+    byte            serverSecret[SECRET_LEN];
+    byte            secret[SECRET_LEN];
+#endif
+    byte            masterSecret[SECRET_LEN];
+#ifdef WOLFSSL_DTLS
+    byte            cookie[MAX_COOKIE_LEN];
+    byte            cookieSz;
+#endif
+    byte            pendingMsgType;    /* defrag buffer message type */
+} Arrays;
+
+#ifndef ASN_NAME_MAX
+#define ASN_NAME_MAX 256
+#endif
+
+#ifndef MAX_DATE_SZ
+#define MAX_DATE_SZ 32
+#endif
+
+struct WOLFSSL_STACK {
+    unsigned long num; /* number of nodes in stack
+                        * (saftey measure for freeing and shortcut for count) */
+    union {
+        WOLFSSL_X509*        x509;
+        WOLFSSL_X509_NAME*   name;
+        WOLFSSL_BIO*         bio;
+        WOLFSSL_ASN1_OBJECT* obj;
+        char*                string;
+    } data;
+    WOLFSSL_STACK* next;
+};
+
+
+struct WOLFSSL_X509_NAME {
+    char  *name;
+    int   dynamicName;
+    int   sz;
+    char  staticName[ASN_NAME_MAX];
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(NO_ASN)
+    DecodedName fullName;
+    WOLFSSL_X509_NAME_ENTRY cnEntry;
+    WOLFSSL_X509_NAME_ENTRY extra[MAX_NAME_ENTRIES]; /* extra entries added */
+    WOLFSSL_X509*           x509;   /* x509 that struct belongs to */
+#endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
+    byte  raw[ASN_NAME_MAX];
+    int   rawLen;
+#endif
+};
+
+#ifndef EXTERNAL_SERIAL_SIZE
+    #define EXTERNAL_SERIAL_SIZE 32
+#endif
+
+#ifdef NO_ASN
+    typedef struct DNS_entry DNS_entry;
+#endif
+
+struct WOLFSSL_X509 {
+    int              version;
+    int              serialSz;
+#ifdef WOLFSSL_SEP
+    int              deviceTypeSz;
+    int              hwTypeSz;
+    byte             deviceType[EXTERNAL_SERIAL_SIZE];
+    byte             hwType[EXTERNAL_SERIAL_SIZE];
+    int              hwSerialNumSz;
+    byte             hwSerialNum[EXTERNAL_SERIAL_SIZE];
+    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+        byte             certPolicySet;
+        byte             certPolicyCrit;
+    #endif /* OPENSSL_EXTRA */
+#endif
+    int              notBeforeSz;
+    int              notAfterSz;
+    byte             notBefore[MAX_DATE_SZ];
+    byte             notAfter[MAX_DATE_SZ];
+    buffer           sig;
+    int              sigOID;
+    DNS_entry*       altNames;                       /* alt names list */
+    buffer           pubKey;
+    int              pubKeyOID;
+    DNS_entry*       altNamesNext;                   /* hint for retrieval */
+    #if defined(HAVE_ECC) || defined(HAVE_ED25519)
+        word32       pkCurveOID;
+    #endif /* HAVE_ECC */
+    #ifndef NO_CERTS
+        DerBuffer*   derCert;                        /* may need  */
+    #endif
+    void*            heap;                           /* heap hint */
+    byte             dynamicMemory;                  /* dynamic memory flag */
+    byte             isCa:1;
+#ifdef WOLFSSL_CERT_EXT
+    char             certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
+    int              certPoliciesNb;
+#endif /* WOLFSSL_CERT_EXT */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#ifdef HAVE_EX_DATA
+    void*            ex_data[MAX_EX_DATA];
+#endif
+    byte*            authKeyId;
+    byte*            subjKeyId;
+    byte*            extKeyUsageSrc;
+    byte*            CRLInfo;
+    byte*            authInfo;
+    word32           pathLength;
+    word16           keyUsage;
+    int              CRLInfoSz;
+    int              authInfoSz;
+    word32           authKeyIdSz;
+    word32           subjKeyIdSz;
+    word32           extKeyUsageSz;
+    word32           extKeyUsageCount;
+
+    byte             CRLdistSet:1;
+    byte             CRLdistCrit:1;
+    byte             authInfoSet:1;
+    byte             authInfoCrit:1;
+    byte             keyUsageSet:1;
+    byte             keyUsageCrit:1;
+    byte             extKeyUsageCrit:1;
+    byte             subjKeyIdSet:1;
+
+    byte             subjKeyIdCrit:1;
+    byte             basicConstSet:1;
+    byte             basicConstCrit:1;
+    byte             basicConstPlSet:1;
+    byte             subjAltNameSet:1;
+    byte             subjAltNameCrit:1;
+    byte             authKeyIdSet:1;
+    byte             authKeyIdCrit:1;
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    byte             serial[EXTERNAL_SERIAL_SIZE];
+    char             subjectCN[ASN_NAME_MAX];        /* common name short cut */
+#ifdef WOLFSSL_CERT_REQ
+    char             challengePw[CTC_NAME_SIZE]; /* for REQ certs */
+#endif
+    WOLFSSL_X509_NAME issuer;
+    WOLFSSL_X509_NAME subject;
+};
+
+
+/* record layer header for PlainText, Compressed, and CipherText */
+typedef struct RecordLayerHeader {
+    byte            type;
+    byte            pvMajor;
+    byte            pvMinor;
+    byte            length[2];
+} RecordLayerHeader;
+
+
+/* record layer header for DTLS PlainText, Compressed, and CipherText */
+typedef struct DtlsRecordLayerHeader {
+    byte            type;
+    byte            pvMajor;
+    byte            pvMinor;
+    byte            sequence_number[8];   /* per record */
+    byte            length[2];
+} DtlsRecordLayerHeader;
+
+
+typedef struct DtlsFrag {
+    word32 begin;
+    word32 end;
+    struct DtlsFrag* next;
+} DtlsFrag;
+
+
+typedef struct DtlsMsg {
+    struct DtlsMsg* next;
+    byte*           buf;
+    byte*           msg;
+    DtlsFrag*       fragList;
+    word32          fragSz;    /* Length of fragments received */
+    word32          seq;       /* Handshake sequence number    */
+    word32          sz;        /* Length of whole mesage       */
+    byte            type;
+} DtlsMsg;
+
+
+#ifdef HAVE_NETX
+
+    /* NETX I/O Callback default */
+    typedef struct NetX_Ctx {
+        NX_TCP_SOCKET* nxSocket;    /* send/recv socket handle */
+        NX_PACKET*     nxPacket;    /* incoming packet handle for short reads */
+        ULONG          nxOffset;    /* offset already read from nxPacket */
+        ULONG          nxWait;      /* wait option flag */
+    } NetX_Ctx;
+
+#endif
+
+
+/* Handshake messages received from peer (plus change cipher */
+typedef struct MsgsReceived {
+    word16 got_hello_request:1;
+    word16 got_client_hello:2;
+    word16 got_server_hello:2;
+    word16 got_hello_verify_request:1;
+    word16 got_session_ticket:1;
+    word16 got_end_of_early_data:1;
+    word16 got_hello_retry_request:1;
+    word16 got_encrypted_extensions:1;
+    word16 got_certificate:1;
+    word16 got_certificate_status:1;
+    word16 got_server_key_exchange:1;
+    word16 got_certificate_request:1;
+    word16 got_server_hello_done:1;
+    word16 got_certificate_verify:1;
+    word16 got_client_key_exchange:1;
+    word16 got_finished:1;
+    word16 got_key_update:1;
+    word16 got_change_cipher:1;
+} MsgsReceived;
+
+
+/* Handshake hashes */
+typedef struct HS_Hashes {
+    Hashes          verifyHashes;
+    Hashes          certHashes;         /* for cert verify */
+#ifndef NO_SHA
+    wc_Sha          hashSha;            /* sha hash of handshake msgs */
+#endif
+#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
+    wc_Md5          hashMd5;            /* md5 hash of handshake msgs */
+#endif
+#ifndef NO_SHA256
+    wc_Sha256       hashSha256;         /* sha256 hash of handshake msgs */
+#endif
+#ifdef WOLFSSL_SHA384
+    wc_Sha384       hashSha384;         /* sha384 hash of handshake msgs */
+#endif
+#ifdef WOLFSSL_SHA512
+    wc_Sha512       hashSha512;         /* sha512 hash of handshake msgs */
+#endif
+#if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+    byte*           messages;           /* handshake messages */
+    int             length;             /* length of handhsake messages' data */
+    int             prevLen;            /* length of messages but last */
+#endif
+} HS_Hashes;
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    #define MAX_ASYNC_ARGS 18
+    typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs);
+
+    struct WOLFSSL_ASYNC {
+        WC_ASYNC_DEV* dev;
+        FreeArgsCb    freeArgs; /* function pointer to cleanup args */
+        word32        args[MAX_ASYNC_ARGS]; /* holder for current args */
+    };
+#endif
+
+#ifdef HAVE_WRITE_DUP
+
+    #define WRITE_DUP_SIDE 1
+    #define READ_DUP_SIDE 2
+
+    typedef struct WriteDup {
+        wolfSSL_Mutex   dupMutex;       /* reference count mutex */
+        int             dupCount;       /* reference count */
+        int             dupErr;         /* under dupMutex, pass to other side */
+    } WriteDup;
+
+    WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl);
+    WOLFSSL_LOCAL int  NotifyWriteSide(WOLFSSL* ssl, int err);
+#endif /* HAVE_WRITE_DUP */
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+typedef struct CertReqCtx CertReqCtx;
+
+struct CertReqCtx {
+    CertReqCtx* next;
+    byte        len;
+    byte        ctx;
+};
+#endif
+
+#ifdef WOLFSSL_EARLY_DATA
+typedef enum EarlyDataState {
+    no_early_data,
+    expecting_early_data,
+    process_early_data,
+    done_early_data
+} EarlyDataState;
+#endif
+
+/* wolfSSL ssl type */
+struct WOLFSSL {
+    WOLFSSL_CTX*    ctx;
+    Suites*         suites;             /* only need during handshake */
+    Arrays*         arrays;
+    HS_Hashes*      hsHashes;
+    void*           IOCB_ReadCtx;
+    void*           IOCB_WriteCtx;
+    WC_RNG*         rng;
+    void*           verifyCbCtx;        /* cert verify callback user ctx*/
+    VerifyCallback  verifyCallback;     /* cert verification callback */
+    void*           heap;               /* for user overrides */
+#ifdef HAVE_WRITE_DUP
+    WriteDup*       dupWrite;           /* valid pointer indicates ON */
+             /* side that decrements dupCount to zero frees overall structure */
+    byte            dupSide;            /* write side or read side */
+#endif
+#ifdef OPENSSL_EXTRA
+    byte              cbioFlag;  /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */
+#endif
+    CallbackIORecv  CBIORecv;
+    CallbackIOSend  CBIOSend;
+#ifdef WOLFSSL_STATIC_MEMORY
+    WOLFSSL_HEAP_HINT heap_hint;
+#endif
+#ifndef NO_HANDSHAKE_DONE_CB
+    HandShakeDoneCb hsDoneCb;          /*  notify user handshake done */
+    void*           hsDoneCtx;         /*  user handshake cb context  */
+#endif
+#ifdef WOLFSSL_ASYNC_CRYPT
+    struct WOLFSSL_ASYNC async;
+#elif defined(WOLFSSL_NONBLOCK_OCSP)
+    void*           nonblockarg;        /* dynamic arg for handling non-block resume */
+#endif
+    void*           hsKey;              /* Handshake key (RsaKey or ecc_key) allocated from heap */
+    word32          hsType;             /* Type of Handshake key (hsKey) */
+    WOLFSSL_CIPHER  cipher;
+    hmacfp          hmac;
+    Ciphers         encrypt;
+    Ciphers         decrypt;
+    Buffers         buffers;
+    WOLFSSL_SESSION session;
+#ifdef HAVE_EXT_CACHE
+    WOLFSSL_SESSION* extSession;
+#endif
+    WOLFSSL_ALERT_HISTORY alert_history;
+    int             error;
+    int             rfd;                /* read  file descriptor */
+    int             wfd;                /* write file descriptor */
+    int             rflags;             /* user read  flags */
+    int             wflags;             /* user write flags */
+    word32          timeout;            /* session timeout */
+    word32          fragOffset;         /* fragment offset */
+    word16          curSize;
+    byte            verifyDepth;
+    RecordLayerHeader curRL;
+    MsgsReceived    msgsReceived;       /* peer messages received */
+    ProtocolVersion version;            /* negotiated version */
+    ProtocolVersion chVersion;          /* client hello version */
+    CipherSpecs     specs;
+    Keys            keys;
+    Options         options;
+#ifdef OPENSSL_EXTRA
+    CallbackInfoState* CBIS;             /* used to get info about SSL state */
+    int              cbmode;             /* read or write on info callback */
+    int              cbtype;             /* event type in info callback */
+    WOLFSSL_BIO*     biord;              /* socket bio read  to free/close */
+    WOLFSSL_BIO*     biowr;              /* socket bio write to free/close */
+    byte             sessionCtx[ID_LEN]; /* app session context ID */
+    unsigned long    peerVerifyRet;
+    byte             readAhead;
+    byte             sessionCtxSz;       /* size of sessionCtx stored */
+#ifdef HAVE_PK_CALLBACKS
+    void*            loggingCtx;         /* logging callback argument */
+#endif
+#endif /* OPENSSL_EXTRA */
+#ifndef NO_RSA
+    RsaKey*         peerRsaKey;
+    byte            peerRsaKeyPresent;
+#endif
+#ifdef HAVE_QSH
+    QSHKey*         QSH_Key;
+    QSHKey*         peerQSHKey;
+    QSHSecret*      QSH_secret;
+    byte            isQSH;             /* is the handshake a QSH? */
+    byte            sendQSHKeys;       /* flag for if the client should sen
+                                          public keys */
+    byte            peerQSHKeyPresent;
+    byte            minRequest;
+    byte            maxRequest;
+    byte            user_set_QSHSchemes;
+#endif
+#ifdef WOLFSSL_TLS13
+    word16          namedGroup;
+    word16          group[WOLFSSL_MAX_GROUP_COUNT];
+    byte            numGroups;
+#endif
+    byte            pssAlgo;
+#ifdef WOLFSSL_TLS13
+    #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
+    word16          certHashSigAlgoSz;  /* SigAlgoCert ext length in bytes */
+    byte            certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to
+                                                           * offer */
+    #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
+#endif
+#ifdef HAVE_NTRU
+    word16          peerNtruKeyLen;
+    byte            peerNtruKey[MAX_NTRU_PUB_KEY_SZ];
+    byte            peerNtruKeyPresent;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    int             eccVerifyRes;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    word32          ecdhCurveOID;            /* curve Ecc_Sum     */
+    ecc_key*        eccTempKey;              /* private ECDHE key */
+    byte            eccTempKeyPresent;       /* also holds type */
+    byte            peerEccKeyPresent;
+#endif
+#ifdef HAVE_ECC
+    ecc_key*        peerEccKey;              /* peer's  ECDHE key */
+    ecc_key*        peerEccDsaKey;           /* peer's  ECDSA key */
+    word16          eccTempKeySz;            /* in octets 20 - 66 */
+    byte            peerEccDsaKeyPresent;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519)
+    word32          pkCurveOID;              /* curve Ecc_Sum     */
+#endif
+#ifdef HAVE_ED25519
+    ed25519_key*    peerEd25519Key;
+    byte            peerEd25519KeyPresent;
+#endif
+#ifdef HAVE_CURVE25519
+    curve25519_key* peerX25519Key;
+    byte            peerX25519KeyPresent;
+#endif
+#ifdef HAVE_LIBZ
+    z_stream        c_stream;           /* compression   stream */
+    z_stream        d_stream;           /* decompression stream */
+    byte            didStreamInit;      /* for stream init and end */
+#endif
+#ifdef WOLFSSL_DTLS
+    int             dtls_timeout_init;  /* starting timeout value */
+    int             dtls_timeout_max;   /* maximum timeout value */
+    int             dtls_timeout;       /* current timeout value, changes */
+    word32          dtls_tx_msg_list_sz;
+    word32          dtls_rx_msg_list_sz;
+    DtlsMsg*        dtls_tx_msg_list;
+    DtlsMsg*        dtls_rx_msg_list;
+    void*           IOCB_CookieCtx;     /* gen cookie ctx */
+    word32          dtls_expected_rx;
+#ifdef WOLFSSL_SESSION_EXPORT
+    wc_dtls_export  dtls_export;        /* export function for session */
+#endif
+#ifdef WOLFSSL_SCTP
+    word16          dtlsMtuSz;
+#endif /* WOLFSSL_SCTP */
+#ifdef WOLFSSL_MULTICAST
+    void*           mcastHwCbCtx;       /* Multicast highwater callback ctx */
+#endif /* WOLFSSL_MULTICAST */
+#ifdef WOLFSSL_DTLS_DROP_STATS
+    word32 macDropCount;
+    word32 replayDropCount;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+#endif /* WOLFSSL_DTLS */
+#ifdef WOLFSSL_CALLBACKS
+    TimeoutInfo     timeoutInfo;        /* info saved during handshake */
+    HandShakeInfo   handShakeInfo;      /* info saved during handshake */
+#endif
+#ifdef OPENSSL_EXTRA
+    SSL_Msg_Cb      protoMsgCb;         /* inspect protocol message callback */
+    void*           protoMsgCtx;        /* user set context with msg callback */
+#endif
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    byte            hsInfoOn;           /* track handshake info        */
+    byte            toInfoOn;           /* track timeout   info        */
+#endif
+#ifdef HAVE_FUZZER
+    CallbackFuzzer  fuzzerCb;           /* for testing with using fuzzer */
+    void*           fuzzerCtx;          /* user defined pointer */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    CertReqCtx*     certReqCtx;
+#endif
+#ifdef KEEP_PEER_CERT
+    WOLFSSL_X509     peerCert;           /* X509 peer cert */
+#endif
+#ifdef KEEP_OUR_CERT
+    WOLFSSL_X509*    ourCert;            /* keep alive a X509 struct of cert.
+                                            points to ctx if not owned (owned
+                                            flag found in buffers.weOwnCert) */
+#endif
+    byte             keepCert;           /* keep certificate after handshake */
+#if defined(HAVE_EX_DATA) || defined(FORTRESS)
+    void*            ex_data[MAX_EX_DATA]; /* external data, for Fortress */
+#endif
+    int              devId;             /* async device id to use */
+#ifdef HAVE_ONE_TIME_AUTH
+    OneTimeAuth     auth;
+#endif
+#ifdef HAVE_TLS_EXTENSIONS
+    TLSX* extensions;                  /* RFC 6066 TLS Extensions data */
+    #ifdef HAVE_MAX_FRAGMENT
+        word16 max_fragment;
+    #endif
+    #ifdef HAVE_TRUNCATED_HMAC
+        byte truncated_hmac;
+    #endif
+    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+        byte status_request;
+    #endif
+    #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+        byte status_request_v2;
+    #endif
+    #if defined(HAVE_SECURE_RENEGOTIATION) \
+        || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+        SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
+    #endif                                         /* user turned on */
+    #ifdef HAVE_ALPN
+        char*   alpn_client_list;  /* keep the client's list */
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)  || defined(WOLFSSL_HAPROXY)
+            CallbackALPNSelect alpnSelect;
+            void*              alpnSelectArg;
+        #endif
+    #endif                         /* of accepted protocols */
+    #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
+        CallbackSessionTicket session_ticket_cb;
+        void*                 session_ticket_ctx;
+        byte                  expect_session_ticket;
+    #endif
+#endif /* HAVE_TLS_EXTENSIONS */
+#ifdef HAVE_OCSP
+        void*       ocspIOCtx;
+    #ifdef OPENSSL_EXTRA
+        byte*       ocspResp;
+        int         ocspRespSz;
+        #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+            char*   url;
+        #endif
+    #endif
+#endif
+#ifdef HAVE_NETX
+    NetX_Ctx        nxCtx;             /* NetX IO Context */
+#endif
+#ifdef SESSION_INDEX
+    int sessionIndex;                  /* Session's location in the cache. */
+#endif
+#ifdef ATOMIC_USER
+    void*    MacEncryptCtx;    /* Atomic User Mac/Encrypt Callback Context */
+    void*    DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    #ifdef HAVE_ECC
+        void* EccKeyGenCtx;              /* EccKeyGen  Callback Context */
+        void* EccSignCtx;                /* Ecc Sign   Callback Context */
+        void* EccVerifyCtx;              /* Ecc Verify Callback Context */
+        void* EccSharedSecretCtx;        /* Ecc Pms    Callback Context */
+        #ifdef HAVE_ED25519
+            void* Ed25519SignCtx;        /* ED25519 Sign   Callback Context */
+            void* Ed25519VerifyCtx;      /* ED25519 Verify Callback Context */
+        #endif
+        #ifdef HAVE_CURVE25519
+            void* X25519KeyGenCtx;       /* X25519 KeyGen Callback Context */
+            void* X25519SharedSecretCtx; /* X25519 Pms    Callback Context */
+        #endif
+    #endif /* HAVE_ECC */
+    #ifndef NO_DH
+        void* DhAgreeCtx; /* DH Pms Callback Context */
+    #endif /* !NO_DH */
+    #ifndef NO_RSA
+        void* RsaSignCtx;     /* Rsa Sign   Callback Context */
+        void* RsaVerifyCtx;   /* Rsa Verify Callback Context */
+        #ifdef WC_RSA_PSS
+            void* RsaPssSignCtx;     /* Rsa PSS Sign   Callback Context */
+            void* RsaPssVerifyCtx;   /* Rsa PSS Verify Callback Context */
+        #endif
+        void* RsaEncCtx;      /* Rsa Public  Encrypt   Callback Context */
+        void* RsaDecCtx;      /* Rsa Private Decrypt   Callback Context */
+    #endif /* NO_RSA */
+#endif /* HAVE_PK_CALLBACKS */
+#ifdef HAVE_SECRET_CALLBACK
+        SessionSecretCb sessionSecretCb;
+        void*           sessionSecretCtx;
+#endif /* HAVE_SECRET_CALLBACK */
+#ifdef WOLFSSL_JNI
+        void* jObjectRef;     /* reference to WolfSSLSession in JNI wrapper */
+#endif /* WOLFSSL_JNI */
+#ifdef WOLFSSL_EARLY_DATA
+    EarlyDataState earlyData;
+    word32 earlyDataSz;
+#endif
+};
+
+
+WOLFSSL_LOCAL
+int  SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int);
+WOLFSSL_LOCAL
+int  InitSSL(WOLFSSL*, WOLFSSL_CTX*, int);
+WOLFSSL_LOCAL
+void FreeSSL(WOLFSSL*, void* heap);
+WOLFSSL_API void SSL_ResourceFree(WOLFSSL*);   /* Micrium uses */
+
+
+
+#ifndef NO_CERTS
+
+    WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+                                    long sz, int format, int type, WOLFSSL* ssl,
+                                    long* used, int userChain);
+    WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format,
+                                 int type, WOLFSSL* ssl, int userChain,
+                                WOLFSSL_CRL* crl);
+
+    #ifdef OPENSSL_EXTRA
+    WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName,
+                                    size_t domainNameLen);
+    #endif
+#endif
+
+
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+    WOLFSSL_LOCAL
+    void InitHandShakeInfo(HandShakeInfo*, WOLFSSL*);
+    WOLFSSL_LOCAL
+    void FinishHandShakeInfo(HandShakeInfo*);
+    WOLFSSL_LOCAL
+    void AddPacketName(WOLFSSL* ssl, const char* name);
+
+    WOLFSSL_LOCAL
+    void InitTimeoutInfo(TimeoutInfo*);
+    WOLFSSL_LOCAL
+    void FreeTimeoutInfo(TimeoutInfo*, void*);
+    WOLFSSL_LOCAL
+    void AddPacketInfo(WOLFSSL* ssl, const char* name, int type,
+                               const byte* data, int sz, int write, void* heap);
+    WOLFSSL_LOCAL
+    void AddLateName(const char*, TimeoutInfo*);
+    WOLFSSL_LOCAL
+    void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info);
+#endif
+
+
+/* Record Layer Header identifier from page 12 */
+enum ContentType {
+    no_type            = 0,
+    change_cipher_spec = 20,
+    alert              = 21,
+    handshake          = 22,
+    application_data   = 23
+};
+
+
+/* handshake header, same for each message type, pgs 20/21 */
+typedef struct HandShakeHeader {
+    byte            type;
+    word24          length;
+} HandShakeHeader;
+
+
+/* DTLS handshake header, same for each message type */
+typedef struct DtlsHandShakeHeader {
+    byte            type;
+    word24          length;
+    byte            message_seq[2];    /* start at 0, retransmit gets same # */
+    word24          fragment_offset;   /* bytes in previous fragments */
+    word24          fragment_length;   /* length of this fragment */
+} DtlsHandShakeHeader;
+
+
+enum HandShakeType {
+    hello_request        =   0,
+    client_hello         =   1,
+    server_hello         =   2,
+    hello_verify_request =   3,    /* DTLS addition */
+    session_ticket       =   4,
+    end_of_early_data    =   5,
+    hello_retry_request  =   6,
+    encrypted_extensions =   8,
+    certificate          =  11,
+    server_key_exchange  =  12,
+    certificate_request  =  13,
+    server_hello_done    =  14,
+    certificate_verify   =  15,
+    client_key_exchange  =  16,
+    finished             =  20,
+    certificate_status   =  22,
+    key_update           =  24,
+    change_cipher_hs     =  55,    /* simulate unique handshake type for sanity
+                                      checks.  record layer change_cipher
+                                      conflicts with handshake finished */
+    message_hash         = 254,    /* synthetic message type for TLS v1.3 */
+    no_shake             = 255     /* used to initialize the DtlsMsg record */
+};
+
+enum ProvisionSide {
+    PROVISION_CLIENT = 1,
+    PROVISION_SERVER = 2,
+    PROVISION_CLIENT_SERVER = 3
+};
+
+
+static const byte client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+
+/* internal functions */
+WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);
+WOLFSSL_LOCAL int SendTicket(WOLFSSL*);
+WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32);
+WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int);
+#ifdef WOLFSSL_TLS13
+#ifdef WOLFSSL_TLS13_DRAFT_18
+WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*);
+#else
+WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte);
+#endif
+#endif
+WOLFSSL_LOCAL int SendCertificate(WOLFSSL*);
+WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*);
+#endif
+WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*);
+WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*);
+WOLFSSL_LOCAL int SendBuffered(WOLFSSL*);
+WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int);
+WOLFSSL_LOCAL int SendFinished(WOLFSSL*);
+WOLFSSL_LOCAL int SendAlert(WOLFSSL*, int, int);
+WOLFSSL_LOCAL int ProcessReply(WOLFSSL*);
+
+WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL*);
+WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL*);
+
+WOLFSSL_LOCAL int AddSession(WOLFSSL*);
+WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl);
+WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side);
+
+WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl);
+WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl);
+WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv);
+
+WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl);
+WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree);
+WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32);
+WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment);
+
+#ifndef NO_CERTS
+    #ifndef NO_RSA
+        #ifdef WC_RSA_PSS
+            WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz,
+                byte* out, word32 sigSz, enum wc_HashType hashType);
+            WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, 
+                enum wc_HashType* hashType, int* mgf);
+        #endif
+        WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig,
+            word32 sigSz, const byte* plain, word32 plainSz, int sigAlgo,
+            int hashAlgo, RsaKey* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
+            DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz,
+            byte** out, int sigAlgo, int hashAlgo, RsaKey* key,
+            buffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out,
+            word32* outSz, RsaKey* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
+            word32* outSz, RsaKey* key, buffer* keyBufInfo);
+    #endif /* !NO_RSA */
+
+    #ifdef HAVE_ECC
+        WOLFSSL_LOCAL int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, ecc_key* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz,
+            const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo);
+        WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key,
+            ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out,
+            word32* outlen, int side);
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_ED25519
+        WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl);
+        WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,
+            byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in,
+            word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key,
+            buffer* keyBufInfo);
+    #endif /* HAVE_ED25519 */
+
+
+    #ifdef WOLFSSL_TRUST_PEER_CERT
+
+        /* options for searching hash table for a matching trusted peer cert */
+        #define WC_MATCH_SKID 0
+        #define WC_MATCH_NAME 1
+
+        WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash,
+                                                                      int type);
+        WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp,
+                                                             DecodedCert* cert);
+    #endif
+
+    WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash);
+    #ifndef NO_SKID
+        WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash);
+    #endif
+#endif /* !NO_CERTS */
+WOLFSSL_LOCAL int  BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash,
+                                   word32* hashLen);
+WOLFSSL_LOCAL int  BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes,
+                                   const byte* sender);
+WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
+WOLFSSL_LOCAL  int CheckAvailableSize(WOLFSSL *ssl, int size);
+WOLFSSL_LOCAL  int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
+
+#ifndef NO_TLS
+    WOLFSSL_LOCAL int  MakeTlsMasterSecret(WOLFSSL*);
+    WOLFSSL_LOCAL int  TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in,
+                                word32 sz, int padSz, int content, int verify);
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+    WOLFSSL_LOCAL int SendClientHello(WOLFSSL*);
+    #ifdef WOLFSSL_TLS13
+    WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*);
+    #endif
+    WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*);
+    WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*);
+#endif /* NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+    WOLFSSL_LOCAL int SendServerHello(WOLFSSL*);
+    WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*);
+#endif /* NO_WOLFSSL_SERVER */
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*);
+    WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*);
+    WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*);
+    WOLFSSL_LOCAL int  DtlsMsgSet(DtlsMsg*, word32, const byte*, byte,
+                                                       word32, word32, void*);
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32);
+    WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32,
+                                                byte, word32, word32, void*);
+    WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*);
+
+    WOLFSSL_LOCAL int  DtlsMsgPoolSave(WOLFSSL*, const byte*, word32);
+    WOLFSSL_LOCAL int  DtlsMsgPoolTimeout(WOLFSSL*);
+    WOLFSSL_LOCAL int  VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32);
+    WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*);
+    WOLFSSL_LOCAL int  DtlsMsgPoolSend(WOLFSSL*, int);
+#endif /* WOLFSSL_DTLS */
+
+#ifndef NO_TLS
+
+
+#endif /* NO_TLS */
+
+#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
+    WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void);
+#endif
+WOLFSSL_LOCAL word32  LowResTimer(void);
+
+#ifndef NO_CERTS
+    WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int);
+    WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap);
+    WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int, void* heap);
+    WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*);
+    WOLFSSL_LOCAL int  CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*);
+#endif
+
+typedef struct CipherSuiteInfo {
+    const char* name;
+#ifndef NO_ERROR_STRINGS
+    const char* name_iana;
+#endif
+    byte cipherSuite0;
+    byte cipherSuite;
+} CipherSuiteInfo;
+
+WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void);
+WOLFSSL_LOCAL int GetCipherNamesSize(void);
+WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite);
+WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite);
+WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl);
+WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl);
+
+enum encrypt_side {
+    ENCRYPT_SIDE_ONLY = 1,
+    DECRYPT_SIDE_ONLY,
+    ENCRYPT_AND_DECRYPT_SIDE
+};
+
+WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side);
+
+
+#ifndef NO_DH
+    WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
+        byte* priv, word32* privSz,
+        byte* pub, word32* pubSz);
+    WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
+        const byte* priv, word32 privSz,
+        const byte* otherPub, word32 otherPubSz,
+        byte* agree, word32* agreeSz);
+#endif /* !NO_DH */
+
+#ifdef HAVE_ECC
+    WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer);
+#endif
+
+WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl);
+WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl);
+
+WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
+                        const byte* input, int inSz, int type, int hashOutput,
+                        int sizeOnly, int asyncOkay);
+
+#ifdef WOLFSSL_TLS13
+int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
+               int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay);
+#endif
+
+WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey);
+WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    WOLFSSL_LOCAL int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags);
+    WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state);
+    WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev);
+#endif
+
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+#endif /* wolfSSL_INT_H */
+
--- a/wolfssl/ssl.h	Tue Nov 19 14:32:16 2019 +0000
+++ b/wolfssl/ssl.h	Wed Nov 20 13:27:48 2019 +0000
@@ -1,2980 +1,2980 @@
-/* ssl.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-/*!
-    \file ../wolfssl/ssl.h
-    \brief Header file containing key wolfSSL API
-*/
-
-/* wolfSSL API */
-
-#ifndef WOLFSSL_SSL_H
-#define WOLFSSL_SSL_H
-
-
-/* for users not using preprocessor flags*/
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/version.h>
-#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/asn_public.h>
-
-#ifdef HAVE_WOLF_EVENT
-    #include <wolfssl/wolfcrypt/wolfevent.h>
-#endif
-
-#ifndef NO_FILESYSTEM
-    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <nio.h>
-        #endif
-    #endif
-#endif
-
-#ifdef WOLFSSL_PREFIX
-    #include "prefix_ssl.h"
-#endif
-
-#ifdef LIBWOLFSSL_VERSION_STRING
-    #define WOLFSSL_VERSION LIBWOLFSSL_VERSION_STRING
-#endif
-
-#ifdef _WIN32
-    /* wincrypt.h clashes */
-    #undef OCSP_REQUEST
-    #undef OCSP_RESPONSE
-#endif
-
-#ifdef OPENSSL_COEXIST
-    /* mode to allow wolfSSL and OpenSSL to exist together */
-    #ifdef TEST_OPENSSL_COEXIST
-        /*
-        ./configure --enable-opensslcoexist \
-            CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \
-            LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto"
-        */
-        #include <openssl/ssl.h>
-        #include <openssl/rand.h>
-        #include <openssl/err.h>
-        #include <openssl/ec.h>
-        #include <openssl/hmac.h>
-        #include <openssl/bn.h>
-    #endif
-
-    /* make sure old names are disabled */
-    #ifndef NO_OLD_SSL_NAMES
-        #define NO_OLD_SSL_NAMES
-    #endif
-    #ifndef NO_OLD_WC_NAMES
-        #define NO_OLD_WC_NAMES
-    #endif
-
-#elif (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-    #include <wolfssl/openssl/bn.h>
-    #include <wolfssl/openssl/hmac.h>
-
-    /* We need the old SSL names */
-    #ifdef NO_OLD_SSL_NAMES
-        #undef NO_OLD_SSL_NAMES
-    #endif
-    #ifdef NO_OLD_WC_NAMES
-        #undef NO_OLD_WC_NAMES
-    #endif
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED
-#define WOLFSSL_WOLFSSL_TYPE_DEFINED
-typedef struct WOLFSSL          WOLFSSL;
-#endif
-typedef struct WOLFSSL_SESSION  WOLFSSL_SESSION;
-typedef struct WOLFSSL_METHOD   WOLFSSL_METHOD;
-#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
-#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
-typedef struct WOLFSSL_CTX      WOLFSSL_CTX;
-#endif
-
-typedef struct WOLFSSL_STACK      WOLFSSL_STACK;
-typedef struct WOLFSSL_X509       WOLFSSL_X509;
-typedef struct WOLFSSL_X509_NAME  WOLFSSL_X509_NAME;
-typedef struct WOLFSSL_X509_NAME_ENTRY  WOLFSSL_X509_NAME_ENTRY;
-typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN;
-typedef struct WC_PKCS12          WOLFSSL_X509_PKCS12;
-
-typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER;
-typedef struct WOLFSSL_SOCKADDR     WOLFSSL_SOCKADDR;
-typedef struct WOLFSSL_CRL          WOLFSSL_CRL;
-
-typedef void  *WOLFSSL_X509_STORE_CTX_verify_cb; /* verify callback */
-
-/* redeclare guard */
-#define WOLFSSL_TYPES_DEFINED
-
-#include <wolfssl/wolfio.h>
-
-
-#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */
-typedef struct WOLFSSL_RSA            WOLFSSL_RSA;
-#define WOLFSSL_RSA_TYPE_DEFINED
-#endif
-
-#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */
-    typedef struct WC_RNG WC_RNG;
-    #define WC_RNG_TYPE_DEFINED
-#endif
-
-#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */
-typedef struct WOLFSSL_DSA            WOLFSSL_DSA;
-#define WOLFSSL_DSA_TYPE_DEFINED
-#endif
-
-#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */
-typedef struct WOLFSSL_EC_KEY         WOLFSSL_EC_KEY;
-typedef struct WOLFSSL_EC_POINT       WOLFSSL_EC_POINT;
-typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_GROUP;
-#define WOLFSSL_EC_TYPE_DEFINED
-#endif
-
-#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */
-typedef struct WOLFSSL_ECDSA_SIG      WOLFSSL_ECDSA_SIG;
-#define WOLFSSL_ECDSA_TYPE_DEFINED
-#endif
-
-typedef struct WOLFSSL_CIPHER         WOLFSSL_CIPHER;
-typedef struct WOLFSSL_X509_LOOKUP    WOLFSSL_X509_LOOKUP;
-typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD;
-typedef struct WOLFSSL_CRL            WOLFSSL_X509_CRL;
-typedef struct WOLFSSL_X509_STORE     WOLFSSL_X509_STORE;
-typedef struct WOLFSSL_X509_VERIFY_PARAM  WOLFSSL_X509_VERIFY_PARAM;
-typedef struct WOLFSSL_BIO            WOLFSSL_BIO;
-typedef struct WOLFSSL_BIO_METHOD     WOLFSSL_BIO_METHOD;
-typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION;
-typedef struct WOLFSSL_ASN1_TIME      WOLFSSL_ASN1_TIME;
-typedef struct WOLFSSL_ASN1_INTEGER   WOLFSSL_ASN1_INTEGER;
-typedef struct WOLFSSL_ASN1_OBJECT    WOLFSSL_ASN1_OBJECT;
-
-typedef struct WOLFSSL_ASN1_STRING      WOLFSSL_ASN1_STRING;
-typedef struct WOLFSSL_dynlock_value    WOLFSSL_dynlock_value;
-typedef struct WOLFSSL_DH               WOLFSSL_DH;
-typedef struct WOLFSSL_ASN1_BIT_STRING  WOLFSSL_ASN1_BIT_STRING;
-
-#define WOLFSSL_ASN1_UTCTIME          WOLFSSL_ASN1_TIME
-#define WOLFSSL_ASN1_GENERALIZEDTIME  WOLFSSL_ASN1_TIME
-
-#define WOLFSSL_ASN1_INTEGER_MAX 20
-struct WOLFSSL_ASN1_INTEGER {
-    /* size can be increased set at 20 for tag, length then to hold at least 16
-     * byte type */
-    unsigned char  intData[WOLFSSL_ASN1_INTEGER_MAX];
-    /* ASN_INTEGER | LENGTH | hex of number */
-    unsigned char  negative;   /* negative number flag */
-
-    unsigned char* data;
-    unsigned int   dataMax;   /* max size of data buffer */
-    unsigned int   isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */
-};
-
-struct WOLFSSL_ASN1_TIME {
-    /* MAX_DATA_SIZE is 32 */
-    unsigned char data[32 + 2];
-    /* ASN_TIME | LENGTH | date bytes */
-};
-
-struct WOLFSSL_ASN1_STRING {
-    int length;
-    int type; /* type of string i.e. CTC_UTF8 */
-    char* data;
-    long flags;
-};
-
-#define WOLFSSL_MAX_SNAME 40
-struct WOLFSSL_ASN1_OBJECT {
-    void*  heap;
-    unsigned char* obj;
-    /* sName is short name i.e sha256 rather than oid (null terminated) */
-    char   sName[WOLFSSL_MAX_SNAME];
-    int    type; /* oid */
-    int    grp;  /* type of OID, i.e. oidCertPolicyType */
-    unsigned int  objSz;
-    unsigned char dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */
-    struct d { /* derefrenced */
-        WOLFSSL_ASN1_STRING  ia5_internal;
-        WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */
-        WOLFSSL_ASN1_STRING* dNSName;
-        WOLFSSL_ASN1_STRING* iPAddress;
-    } d;
-};
-
-struct WOLFSSL_EVP_PKEY {
-    void* heap;
-    int type;         /* openssh dereference */
-    int save_type;    /* openssh dereference */
-    int pkey_sz;
-    union {
-        char* ptr; /* der format of key / or raw for NTRU */
-    } pkey;
-    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
-    #ifndef NO_RSA
-        WOLFSSL_RSA* rsa;
-        byte      ownRsa; /* if struct owns RSA and should free it */
-    #endif
-    #ifdef HAVE_ECC
-        WOLFSSL_EC_KEY* ecc;
-        byte      ownEcc; /* if struct owns ECC and should free it */
-    #endif
-    WC_RNG rng;
-    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-    #ifdef HAVE_ECC
-        int pkey_curve;
-    #endif
-};
-typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO;
-
-#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */
-typedef struct WOLFSSL_EVP_PKEY     WOLFSSL_EVP_PKEY;
-typedef char   WOLFSSL_EVP_MD;
-#define WOLFSSL_EVP_TYPE_DEFINED
-#endif
-
-#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */
-
-
-enum BIO_TYPE {
-    WOLFSSL_BIO_BUFFER = 1,
-    WOLFSSL_BIO_SOCKET = 2,
-    WOLFSSL_BIO_SSL    = 3,
-    WOLFSSL_BIO_MEMORY = 4,
-    WOLFSSL_BIO_BIO    = 5,
-    WOLFSSL_BIO_FILE   = 6,
-    WOLFSSL_BIO_BASE64 = 7
-};
-
-enum BIO_FLAGS {
-    WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01,
-    WOLFSSL_BIO_FLAG_READ         = 0x02,
-    WOLFSSL_BIO_FLAG_WRITE        = 0x04,
-    WOLFSSL_BIO_FLAG_IO_SPECIAL   = 0x08,
-    WOLFSSL_BIO_FLAG_RETRY        = 0x10
-};
-
-typedef struct WOLFSSL_BUF_MEM {
-    char*  data;   /* dereferenced */
-    size_t length; /* current length */
-    size_t max;    /* maximum length */
-} WOLFSSL_BUF_MEM;
-
-typedef struct WOLFSSL_COMP_METHOD {
-    int type;            /* stunnel dereference */
-} WOLFSSL_COMP_METHOD;
-
-struct WOLFSSL_X509_LOOKUP_METHOD {
-    int type;
-};
-
-struct WOLFSSL_X509_LOOKUP {
-    WOLFSSL_X509_STORE *store;
-};
-
-struct WOLFSSL_X509_STORE {
-    int                   cache;          /* stunnel dereference */
-    WOLFSSL_CERT_MANAGER* cm;
-    WOLFSSL_X509_LOOKUP   lookup;
-#ifdef OPENSSL_EXTRA
-    int                   isDynamic;
-#endif
-#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
-    WOLFSSL_X509_CRL *crl;
-#endif
-};
-
-#ifdef OPENSSL_EXTRA
-#define WOLFSSL_USE_CHECK_TIME 0x2
-#define WOLFSSL_NO_CHECK_TIME  0x200000
-#define WOLFSSL_NO_WILDCARDS   0x4
-struct WOLFSSL_X509_VERIFY_PARAM {
-    time_t  check_time;
-    unsigned long flags;
-};
-#endif
-
-typedef struct WOLFSSL_ALERT {
-    int code;
-    int level;
-} WOLFSSL_ALERT;
-
-typedef struct WOLFSSL_ALERT_HISTORY {
-    WOLFSSL_ALERT last_rx;
-    WOLFSSL_ALERT last_tx;
-} WOLFSSL_ALERT_HISTORY;
-
-typedef struct WOLFSSL_X509_REVOKED {
-    WOLFSSL_ASN1_INTEGER* serialNumber;          /* stunnel dereference */
-} WOLFSSL_X509_REVOKED;
-
-
-typedef struct WOLFSSL_X509_OBJECT {
-    union {
-        char* ptr;
-        WOLFSSL_X509 *x509;
-        WOLFSSL_X509_CRL* crl;           /* stunnel dereference */
-    } data;
-} WOLFSSL_X509_OBJECT;
-
-typedef struct WOLFSSL_BUFFER_INFO {
-    unsigned char* buffer;
-    unsigned int length;
-} WOLFSSL_BUFFER_INFO;
-
-typedef struct WOLFSSL_X509_STORE_CTX {
-    WOLFSSL_X509_STORE* store;    /* Store full of a CA cert chain */
-    WOLFSSL_X509* current_cert;   /* stunnel dereference */
-    WOLFSSL_X509* current_issuer; /* asio dereference */
-    WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */
-    WOLFSSL_STACK* chain;
-#ifdef OPENSSL_EXTRA
-    WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */
-#endif
-    char* domain;                /* subject CN domain name */
-    void* ex_data;               /* external data, for fortress build */
-    void* userCtx;               /* user ctx */
-    int   error;                 /* current error */
-    int   error_depth;           /* index of cert depth for this error */
-    int   discardSessionCerts;   /* so verify callback can flag for discard */
-    int   totalCerts;            /* number of peer cert buffers */
-    WOLFSSL_BUFFER_INFO* certs;  /* peer certs */
-    WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */
-} WOLFSSL_X509_STORE_CTX;
-
-typedef char* WOLFSSL_STRING;
-
-/* Valid Alert types from page 16/17
- * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c
- */
-enum AlertDescription {
-    close_notify                    =   0,
-    unexpected_message              =  10,
-    bad_record_mac                  =  20,
-    record_overflow                 =  22,
-    decompression_failure           =  30,
-    handshake_failure               =  40,
-    no_certificate                  =  41,
-    bad_certificate                 =  42,
-    unsupported_certificate         =  43,
-    certificate_revoked             =  44,
-    certificate_expired             =  45,
-    certificate_unknown             =  46,
-    illegal_parameter               =  47,
-    decode_error                    =  50,
-    decrypt_error                   =  51,
-    #ifdef WOLFSSL_MYSQL_COMPATIBLE
-    /* catch name conflict for enum protocol with MYSQL build */
-    wc_protocol_version             =  70,
-    #else
-    protocol_version                =  70,
-    #endif
-    no_renegotiation                = 100,
-    unsupported_extension           = 110, /**< RFC 5246, section 7.2.2 */
-    unrecognized_name               = 112, /**< RFC 6066, section 3 */
-    bad_certificate_status_response = 113, /**< RFC 6066, section 8 */
-    unknown_psk_identity            = 115, /**< RFC 4279, section 2 */
-    no_application_protocol         = 120
-};
-
-
-enum AlertLevel {
-    alert_warning = 1,
-    alert_fatal   = 2
-};
-
-/* Maximum master key length (SECRET_LEN) */
-#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48
-/* Maximum number of groups that can be set */
-#define WOLFSSL_MAX_GROUP_COUNT       10
-
-typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap);
-#ifdef WOLFSSL_TLS13
-    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap);
-    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap);
-#endif
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap);
-
-#ifdef WOLFSSL_DTLS
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap);
-#endif
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void);
-WOLFSSL_API WOLFSSL_METHOD* wolfTLSv1_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void);
-WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
-#ifdef WOLFSSL_TLS13
-    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void);
-    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void);
-#endif
-
-#ifdef WOLFSSL_DTLS
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void);
-    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void);
-#endif
-
-#ifdef HAVE_POLY1305
-    WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
-#endif
-
-#ifdef WOLFSSL_SESSION_EXPORT
-#ifdef WOLFSSL_DTLS
-
-#ifndef WOLFSSL_DTLS_EXPORT_TYPES
-typedef int (*wc_dtls_export)(WOLFSSL* ssl,
-                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
-#define WOLFSSL_DTLS_EXPORT_TYPES
-#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
-
-WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf,
-                                                               unsigned int sz);
-WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
-                                                           wc_dtls_export func);
-WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
-WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf,
-                                                              unsigned int* sz);
-#endif /* WOLFSSL_DTLS */
-#endif /* WOLFSSL_SESSION_EXPORT */
-
-#ifdef WOLFSSL_STATIC_MEMORY
-#ifndef WOLFSSL_MEM_GUARD
-#define WOLFSSL_MEM_GUARD
-    typedef struct WOLFSSL_MEM_STATS      WOLFSSL_MEM_STATS;
-    typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS;
-#endif
-WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx,
-                                            wolfSSL_method_func method,
-                                            unsigned char* buf, unsigned int sz,
-                                            int flag, int max);
-WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx,
-                                                 WOLFSSL_MEM_STATS* mem_stats);
-WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl,
-                                            WOLFSSL_MEM_CONN_STATS* mem_stats);
-#endif
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
-
-WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);
-WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int);
-WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*,
-                                                const char*);
-#ifdef WOLFSSL_TRUST_PEER_CERT
-WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int);
-#endif
-WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *,
-                                                     const char *file);
-WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *,
-                                                  const char *file, int format);
-WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int);
-
-WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl);
-WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx);
-WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth);
-WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
-WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int);
-WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, const char *file);
-WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*,
-                                                  const char *file, int format);
-WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
-
-#ifdef WOLFSSL_DER_LOAD
-    WOLFSSL_API int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX*,
-                                                    const char*, int);
-#endif
-
-#ifdef HAVE_NTRU
-    WOLFSSL_API int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX*, const char*);
-    /* load NTRU private key blob */
-#endif
-
-#endif /* !NO_FILESYSTEM && !NO_CERTS */
-
-WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
-WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
-WOLFSSL_API int  wolfSSL_is_server(WOLFSSL*);
-WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_set_fd (WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_set_write_fd (WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_set_read_fd (WOLFSSL*, int);
-WOLFSSL_API char* wolfSSL_get_cipher_list(int priority);
-WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority);
-WOLFSSL_API int  wolfSSL_get_ciphers(char*, int);
-WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
-WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, 
-    const unsigned char);
-WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
-    int len);
-WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_get_fd(const WOLFSSL*);
-/* please see note at top of README if you get an error from connect */
-WOLFSSL_API int  wolfSSL_connect(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_write(WOLFSSL*, const void*, int);
-WOLFSSL_API int  wolfSSL_read(WOLFSSL*, void*, int);
-WOLFSSL_API int  wolfSSL_peek(WOLFSSL*, void*, int);
-WOLFSSL_API int  wolfSSL_accept(WOLFSSL*);
-#ifdef WOLFSSL_TLS13
-WOLFSSL_API int  wolfSSL_send_hrr_cookie(WOLFSSL* ssl,
-    const unsigned char* secret, unsigned int secretSz);
-WOLFSSL_API int  wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx);
-WOLFSSL_API int  wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx);
-WOLFSSL_API int  wolfSSL_no_dhe_psk(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_update_keys(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);
-WOLFSSL_API int  wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_request_certificate(WOLFSSL* ssl);
-
-WOLFSSL_API int  wolfSSL_preferred_group(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups,
-                                        int count);
-WOLFSSL_API int  wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count);
-
-WOLFSSL_API int  wolfSSL_connect_TLSv13(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_accept_TLSv13(WOLFSSL*);
-
-#ifdef WOLFSSL_EARLY_DATA
-WOLFSSL_API int  wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx,
-                                                unsigned int sz);
-WOLFSSL_API int  wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz);
-WOLFSSL_API int  wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*);
-WOLFSSL_API int  wolfSSL_read_early_data(WOLFSSL*, void*, int, int*);
-#endif
-#endif
-WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*);
-WOLFSSL_API void wolfSSL_free(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_shutdown(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_send(WOLFSSL*, const void*, int sz, int flags);
-WOLFSSL_API int  wolfSSL_recv(WOLFSSL*, void*, int sz, int flags);
-
-WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int);
-WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int);
-
-WOLFSSL_API int  wolfSSL_get_error(WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *);
-
-WOLFSSL_API int  wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*);
-WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long);
-WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*);
-WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long);
-WOLFSSL_API int  wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int);
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)
-WOLFSSL_API int  wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t,
-                     WOLFSSL_BIO**, size_t);
-
-WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**);
-WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*, 
-                                           int, const unsigned char*);
-WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**);
-#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
-
-#ifdef SESSION_INDEX
-WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session);
-#endif /* SESSION_INDEX */
-
-#if defined(SESSION_INDEX) && defined(SESSION_CERTS)
-WOLFSSL_API
-    WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session);
-#endif /* SESSION_INDEX && SESSION_CERTS */
-
-typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*);
-#ifdef OPENSSL_EXTRA
-typedef void (CallbackInfoState)(const WOLFSSL*, int, int);
-
-typedef struct WOLFSSL_CRYPTO_EX_DATA {
-    WOLFSSL_STACK* data;
-} WOLFSSL_CRYPTO_EX_DATA;
-
-typedef int  (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr,
-        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
-typedef int  (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out,
-        WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg);
-typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr,
-        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
-
-WOLFSSL_API int  wolfSSL_get_ex_new_index(long argValue, void* arg,
-        WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b,
-        WOLFSSL_CRYPTO_EX_free* c);
-#endif
-
-WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int,
-                                      VerifyCallback verify_callback);
-WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback);
-WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*);
-
-WOLFSSL_API int  wolfSSL_pending(WOLFSSL*);
-
-WOLFSSL_API void wolfSSL_load_error_strings(void);
-WOLFSSL_API int  wolfSSL_library_init(void);
-WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, long);
-
-#ifdef HAVE_SECRET_CALLBACK
-typedef int (*SessionSecretCb)(WOLFSSL* ssl,
-                                        void* secret, int* secretSz, void* ctx);
-WOLFSSL_API int  wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, void*);
-#endif /* HAVE_SECRET_CALLBACK */
-
-/* session cache persistence */
-WOLFSSL_API int  wolfSSL_save_session_cache(const char*);
-WOLFSSL_API int  wolfSSL_restore_session_cache(const char*);
-WOLFSSL_API int  wolfSSL_memsave_session_cache(void*, int);
-WOLFSSL_API int  wolfSSL_memrestore_session_cache(const void*, int);
-WOLFSSL_API int  wolfSSL_get_session_cache_memsize(void);
-
-/* certificate cache persistence, uses ctx since certs are per ctx */
-WOLFSSL_API int  wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX*, const char*);
-WOLFSSL_API int  wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX*, const char*);
-WOLFSSL_API int  wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX*, void*, int, int*);
-WOLFSSL_API int  wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX*, const void*, int);
-WOLFSSL_API int  wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX*);
-
-/* only supports full name from cipher_name[] delimited by : */
-WOLFSSL_API int  wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*);
-WOLFSSL_API int  wolfSSL_set_cipher_list(WOLFSSL*, const char*);
-
-/* Nonblocking DTLS helper functions */
-WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_dtls_get_using_nonblock(WOLFSSL*);
-#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock
-#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock
-    /* The old names are deprecated. */
-WOLFSSL_API int  wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int);
-WOLFSSL_API int  wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int);
-WOLFSSL_API int  wolfSSL_dtls_got_timeout(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_dtls(WOLFSSL* ssl);
-
-WOLFSSL_API int  wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int);
-WOLFSSL_API int  wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*);
-
-WOLFSSL_API int  wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*);
-WOLFSSL_API int  wolfSSL_dtls_set_sctp(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short);
-WOLFSSL_API int  wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short);
-
-WOLFSSL_API int  wolfSSL_dtls_get_drop_stats(WOLFSSL*,
-                                             unsigned int*, unsigned int*);
-WOLFSSL_API int  wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short);
-WOLFSSL_API int  wolfSSL_set_secret(WOLFSSL*, unsigned short,
-                     const unsigned char*, unsigned int,
-                     const unsigned char*, const unsigned char*,
-                     const unsigned char*);
-WOLFSSL_API int  wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int);
-WOLFSSL_API int  wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int);
-WOLFSSL_API int  wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short);
-WOLFSSL_API int  wolfSSL_mcast_get_max_peers(void);
-typedef int (*CallbackMcastHighwater)(unsigned short peerId,
-                                      unsigned int maxSeq,
-                                      unsigned int curSeq, void* ctx);
-WOLFSSL_API int  wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*,
-                                                    unsigned int,
-                                                    unsigned int,
-                                                    unsigned int,
-                                                    CallbackMcastHighwater);
-WOLFSSL_API int  wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*);
-
-WOLFSSL_API int   wolfSSL_ERR_GET_REASON(unsigned long err);
-WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*);
-WOLFSSL_API void  wolfSSL_ERR_error_string_n(unsigned long e, char* buf,
-                                           unsigned long sz);
-WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long);
-
-/* extras */
-
-#ifndef WOLF_STACK_OF
-    #define WOLF_STACK_OF(x) WOLFSSL_STACK
-#endif
-#ifndef DECLARE_STACK_OF
-    #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x);
-#endif
-
-WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
-                                                            WOLFSSL_X509* x509);
-WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
-WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
-WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value(
-        WOLFSSL_STACK* sk, int i);
-WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk);
-WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
-        void f (WOLFSSL_ASN1_OBJECT*));
-WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void);
-WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj);
-WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk,
-                                                      WOLFSSL_ASN1_OBJECT* obj);
-WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop(
-                                            WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
-WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
-WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in);
-
-WOLFSSL_API int  wolfSSL_set_ex_data(WOLFSSL*, int, void*);
-WOLFSSL_API int  wolfSSL_get_shutdown(const WOLFSSL*);
-WOLFSSL_API int  wolfSSL_set_rfd(WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_set_wfd(WOLFSSL*, int);
-WOLFSSL_API void wolfSSL_set_shutdown(WOLFSSL*, int);
-WOLFSSL_API int  wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*,
-                                           unsigned int);
-WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*);
-WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_session_reused(WOLFSSL*);
-WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session);
-WOLFSSL_API int  wolfSSL_is_init_finished(WOLFSSL*);
-
-WOLFSSL_API const char*  wolfSSL_get_version(WOLFSSL*);
-WOLFSSL_API int  wolfSSL_get_current_cipher_suite(WOLFSSL* ssl);
-WOLFSSL_API WOLFSSL_CIPHER*  wolfSSL_get_current_cipher(WOLFSSL*);
-WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int);
-WOLFSSL_API const char*  wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher);
-WOLFSSL_API const char*  wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session);
-WOLFSSL_API const char*  wolfSSL_get_cipher(WOLFSSL*);
-WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl);
-                           /* what's ref count */
-
-WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void);
-
-WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port,
-                                     char** path, int* ssl);
-
-WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void);
-WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void);
-WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void);
-
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
-WOLFSSL_API int  wolfSSL_BIO_free(WOLFSSL_BIO*);
-WOLFSSL_API int  wolfSSL_BIO_free_all(WOLFSSL_BIO*);
-WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz);
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio);
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type);
-WOLFSSL_API int  wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int);
-WOLFSSL_API int  wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int);
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append);
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*);
-WOLFSSL_API int  wolfSSL_BIO_flush(WOLFSSL_BIO*);
-WOLFSSL_API int  wolfSSL_BIO_pending(WOLFSSL_BIO*);
-
-WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void);
-WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size);
-WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void);
-WOLFSSL_API WOLFSSL_BIO*        wolfSSL_BIO_new_socket(int sfd, int flag);
-WOLFSSL_API int         wolfSSL_BIO_eof(WOLFSSL_BIO*);
-
-WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void);
-WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void);
-WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int);
-
-WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p);
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len);
-
-
-WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag);
-WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag);
-WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr);
-
-#ifndef NO_FILESYSTEM
-WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void);
-#endif
-
-WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void);
-WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void);
-
-WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg);
-WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg);
-
-WOLFSSL_API int  wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size);
-WOLFSSL_API int  wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2);
-WOLFSSL_API int  wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b);
-WOLFSSL_API int  wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf);
-WOLFSSL_API int  wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num);
-WOLFSSL_API int  wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num);
-WOLFSSL_API int  wolfSSL_BIO_reset(WOLFSSL_BIO *bio);
-
-WOLFSSL_API int  wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs);
-WOLFSSL_API int  wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name);
-WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v);
-WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m);
-
-WOLFSSL_API void        wolfSSL_RAND_screen(void);
-WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long);
-WOLFSSL_API int         wolfSSL_RAND_write_file(const char*);
-WOLFSSL_API int         wolfSSL_RAND_load_file(const char*, long);
-WOLFSSL_API int         wolfSSL_RAND_egd(const char*);
-WOLFSSL_API int         wolfSSL_RAND_seed(const void*, int);
-WOLFSSL_API void        wolfSSL_RAND_Cleanup(void);
-WOLFSSL_API void        wolfSSL_RAND_add(const void*, int, double);
-WOLFSSL_API int         wolfSSL_RAND_poll(void);
-
-WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void);
-WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void);
-WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*);
-
-WOLFSSL_API unsigned long wolfSSL_thread_id(void);
-WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void));
-WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*,
-                                                      int));
-WOLFSSL_API void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)
-                                                   (const char*, int));
-WOLFSSL_API void wolfSSL_set_dynlock_lock_callback(void (*f)(int,
-                                      WOLFSSL_dynlock_value*, const char*, int));
-WOLFSSL_API void wolfSSL_set_dynlock_destroy_callback(void (*f)
-                                     (WOLFSSL_dynlock_value*, const char*, int));
-WOLFSSL_API int  wolfSSL_num_locks(void);
-
-WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
-                                                        WOLFSSL_X509_STORE_CTX*);
-WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*);
-WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*);
-
-WOLFSSL_API void  wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
-                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb);
-WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n,
-                                                           unsigned char** out);
-WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
-WOLFSSL_API char*       wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int);
-WOLFSSL_API WOLFSSL_X509_NAME*  wolfSSL_X509_get_issuer_name(WOLFSSL_X509*);
-WOLFSSL_API WOLFSSL_X509_NAME*  wolfSSL_X509_get_subject_name(WOLFSSL_X509*);
-WOLFSSL_API int  wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int);
-WOLFSSL_API int  wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int);
-WOLFSSL_API int  wolfSSL_X509_get_isCA(WOLFSSL_X509*);
-WOLFSSL_API int  wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509*);
-WOLFSSL_API unsigned int wolfSSL_X509_get_pathLength(WOLFSSL_X509*);
-WOLFSSL_API unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509*);
-WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID(
-                                            WOLFSSL_X509*, unsigned char*, int*);
-WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID(
-                                            WOLFSSL_X509*, unsigned char*, int*);
-WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*);
-WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID(
-                                            WOLFSSL_X509_NAME*, int, char*, int);
-WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID(
-                                           WOLFSSL_X509_NAME*, int, int);
-WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*);
-WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void);
-WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type);
-WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1);
-WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1,
-                                                  const void* data, int dataSz);
-WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*);
-WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*);
-WOLFSSL_API int         wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*);
-WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long);
-WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*);
-WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*);
-
-WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long);
-WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*,
-                                            long);
-WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void);
-WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void);
-
-WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE*,
-                                                    WOLFSSL_X509_LOOKUP_METHOD*);
-WOLFSSL_API WOLFSSL_X509_STORE*  wolfSSL_X509_STORE_new(void);
-WOLFSSL_API void         wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*);
-WOLFSSL_API int          wolfSSL_X509_STORE_add_cert(
-                                              WOLFSSL_X509_STORE*, WOLFSSL_X509*);
-WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(
-                                                   WOLFSSL_X509_STORE_CTX* ctx);
-WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store,
-                                                            unsigned long flag);
-WOLFSSL_API int          wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*);
-WOLFSSL_API int          wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*,
-                                   int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*);
-WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void);
-WOLFSSL_API int  wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*,
-                      WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*);
-WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*);
-WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*);
-
-WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*);
-WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*);
-
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*);
-WOLFSSL_API int       wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*);
-WOLFSSL_API void      wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*);
-WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(
-        WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
-                                         WOLFSSL_EVP_PKEY** out);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key,
-        unsigned char** in, long inSz);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type,
-        WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key,
-        unsigned char** in, long inSz);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap);
-WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void);
-WOLFSSL_API int       wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*);
-WOLFSSL_API int       wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*);
-#ifdef OPENSSL_EXTRA
-WOLFSSL_API void      wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*,
-                                                      unsigned long flags,
-                                                      time_t t);
-#endif
-WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*);
-WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
-                                                      WOLFSSL_X509_REVOKED*,int);
-WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*);
-WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*);
-WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void);
-
-WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*);
-
-WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t,
-                                                            char* buf, int len);
-WOLFSSL_API int  wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*,
-                                       const WOLFSSL_ASN1_INTEGER*);
-WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*);
-
-#ifdef OPENSSL_EXTRA
-WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
-                                       WOLFSSL_BIGNUM *bn);
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*);
-WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t,
-                                                     int, long);
-#endif
-
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list(
-        const WOLFSSL_CTX *s);
-WOLFSSL_API void  wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*,
-                                               WOLF_STACK_OF(WOLFSSL_X509_NAME)*);
-WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int);
-WOLFSSL_API int   wolfSSL_get_ex_data_X509_STORE_CTX_idx(void);
-WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(
-                                           WOLFSSL_X509_STORE_CTX* ctx, int er);
-WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int);
-
-WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*,
-                                                          void* userdata);
-WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*,
-                                                   pem_password_cb*);
-WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx);
-WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx);
-
-WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*,
-                          void (*)(const WOLFSSL* ssl, int type, int val));
-
-WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void);
-WOLFSSL_API int           wolfSSL_GET_REASON(int);
-
-WOLFSSL_API const char* wolfSSL_alert_type_string_long(int);
-WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int);
-WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*);
-
-WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long,
-                                               void(*)(int, int, void*), void*);
-WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, 
-                                            const unsigned char **pp, long len);
-WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**, 
-                                            const unsigned char**, long);
-WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp);
-WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp);
-WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *,
-                                           WOLFSSL_RSA *(*)(WOLFSSL *, int, int));
-
-WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key);
-
-WOLFSSL_API long wolfSSL_CTX_sess_accept(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_connect(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_hits(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*);
-WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*);
-
-WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*);
-WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long);
-WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*);
-
-WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*);
-WOLFSSL_API int  wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*);
-WOLFSSL_API int  wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v);
-WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg);
-WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(
-        WOLFSSL_CTX*, void* arg);
-WOLFSSL_API int  wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*);
-WOLFSSL_API int  wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*);
-WOLFSSL_API int  wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*);
-
-WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op);
-WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s);
-WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s,  long op);
-WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s);
-WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s);
-WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh);
-WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg);
-WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type);
-WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg);
-WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg);
-WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg);
-WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp);
-WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len);
-
-WOLFSSL_API void wolfSSL_CONF_modules_unload(int all);
-WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg);
-WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl);
-
-#define WOLFSSL_DEFAULT_CIPHER_LIST ""   /* default all */
-
-enum {
-    WOLFSSL_OCSP_URL_OVERRIDE = 1,
-    WOLFSSL_OCSP_NO_NONCE     = 2,
-    WOLFSSL_OCSP_CHECKALL     = 4,
-
-    WOLFSSL_CRL_CHECKALL = 1,
-    WOLFSSL_CRL_CHECK    = 27,
-};
-
-#ifdef OPENSSL_EXTRA
-/* seperated out from other enums because of size */
-enum {
-    SSL_OP_MICROSOFT_SESS_ID_BUG                  = 0x00000001,
-    SSL_OP_NETSCAPE_CHALLENGE_BUG                 = 0x00000002,
-    SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG       = 0x00000004,
-    SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG            = 0x00000008,
-    SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER             = 0x00000010,
-    SSL_OP_MSIE_SSLV2_RSA_PADDING                 = 0x00000020,
-    SSL_OP_SSLEAY_080_CLIENT_DH_BUG               = 0x00000040,
-    SSL_OP_TLS_D5_BUG                             = 0x00000080,
-    SSL_OP_TLS_BLOCK_PADDING_BUG                  = 0x00000100,
-    SSL_OP_TLS_ROLLBACK_BUG                       = 0x00000200,
-    SSL_OP_ALL                                    = 0x00000400,
-    SSL_OP_EPHEMERAL_RSA                          = 0x00000800,
-    SSL_OP_NO_SSLv3                               = 0x00001000,
-    SSL_OP_NO_TLSv1                               = 0x00002000,
-    SSL_OP_PKCS1_CHECK_1                          = 0x00004000,
-    SSL_OP_PKCS1_CHECK_2                          = 0x00008000,
-    SSL_OP_NETSCAPE_CA_DN_BUG                     = 0x00010000,
-    SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG        = 0x00020000,
-    SSL_OP_SINGLE_DH_USE                          = 0x00040000,
-    SSL_OP_NO_TICKET                              = 0x00080000,
-    SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS            = 0x00100000,
-    SSL_OP_NO_QUERY_MTU                           = 0x00200000,
-    SSL_OP_COOKIE_EXCHANGE                        = 0x00400000,
-    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000,
-    SSL_OP_SINGLE_ECDH_USE                        = 0x01000000,
-    SSL_OP_CIPHER_SERVER_PREFERENCE               = 0x02000000,
-    SSL_OP_NO_TLSv1_1                             = 0x04000000,
-    SSL_OP_NO_TLSv1_2                             = 0x08000000,
-    SSL_OP_NO_COMPRESSION                         = 0x10000000,
-    SSL_OP_NO_TLSv1_3                             = 0x20000000,
-};
-
-enum {
-#ifdef HAVE_OCSP
-    /* OCSP Flags */
-    OCSP_NOCERTS     = 1,
-    OCSP_NOINTERN    = 2,
-    OCSP_NOSIGS      = 4,
-    OCSP_NOCHAIN     = 8,
-    OCSP_NOVERIFY    = 16,
-    OCSP_NOEXPLICIT  = 32,
-    OCSP_NOCASIGN    = 64,
-    OCSP_NODELEGATED = 128,
-    OCSP_NOCHECKS    = 256,
-    OCSP_TRUSTOTHER  = 512,
-    OCSP_RESPID_KEY  = 1024,
-    OCSP_NOTIME      = 2048,
-
-    /* OCSP Types */
-    OCSP_CERTID   = 2,
-    OCSP_REQUEST  = 4,
-    OCSP_RESPONSE = 8,
-    OCSP_BASICRESP = 16,
-#endif
-
-    ASN1_GENERALIZEDTIME = 4,
-    SSL_MAX_SSL_SESSION_ID_LENGTH = 32,
-
-    EVP_R_BAD_DECRYPT = 2,
-
-    SSL_ST_CONNECT = 0x1000,
-    SSL_ST_ACCEPT  = 0x2000,
-    SSL_ST_MASK    = 0x0FFF,
-
-    SSL_CB_LOOP = 0x01,
-    SSL_CB_EXIT = 0x02,
-    SSL_CB_READ = 0x04,
-    SSL_CB_WRITE = 0x08,
-    SSL_CB_HANDSHAKE_START = 0x10,
-    SSL_CB_HANDSHAKE_DONE = 0x20,
-    SSL_CB_ALERT = 0x4000,
-    SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ),
-    SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE),
-    SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP),
-    SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT),
-    SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP),
-    SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT),
-	SSL_CB_MODE_READ = 1,
-	SSL_CB_MODE_WRITE = 2,
-
-    SSL_MODE_ENABLE_PARTIAL_WRITE = 2,
-
-    BIO_FLAGS_BASE64_NO_NL = 1,
-    BIO_CLOSE   = 1,
-    BIO_NOCLOSE = 0,
-
-    NID_undef = 0,
-
-    X509_FILETYPE_PEM = 8,
-    X509_LU_X509      = 9,
-    X509_LU_CRL       = 12,
-
-    X509_V_OK                                    = 0,
-    X509_V_ERR_CRL_SIGNATURE_FAILURE             = 13,
-    X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD    = 14,
-    X509_V_ERR_CRL_HAS_EXPIRED                   = 15,
-    X509_V_ERR_CERT_REVOKED                      = 16,
-    X509_V_ERR_CERT_CHAIN_TOO_LONG               = 17,
-    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT         = 18,
-    X509_V_ERR_CERT_NOT_YET_VALID                = 19,
-    X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD    = 20,
-    X509_V_ERR_CERT_HAS_EXPIRED                  = 21,
-    X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD     = 22,
-    X509_V_ERR_CERT_REJECTED                     = 23,
-    /* Required for Nginx  */
-    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT       = 24,
-    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN         = 25,
-    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26,
-    X509_V_ERR_CERT_UNTRUSTED                    = 27,
-    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE   = 28,
-    X509_V_ERR_SUBJECT_ISSUER_MISMATCH           = 29,
-    /* additional X509_V_ERR_* enums not used in wolfSSL */
-    X509_V_ERR_UNABLE_TO_GET_CRL,
-    X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
-    X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
-    X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
-    X509_V_ERR_CERT_SIGNATURE_FAILURE,
-    X509_V_ERR_CRL_NOT_YET_VALID,
-    X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
-    X509_V_ERR_OUT_OF_MEM,
-    X509_V_ERR_INVALID_CA,
-    X509_V_ERR_PATH_LENGTH_EXCEEDED,
-    X509_V_ERR_INVALID_PURPOSE,
-    X509_V_ERR_AKID_SKID_MISMATCH,
-    X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
-    X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
-    X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
-    X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
-    X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
-    X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
-    X509_V_ERR_INVALID_NON_CA,
-    X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
-    X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
-    X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
-    X509_V_ERR_INVALID_EXTENSION,
-    X509_V_ERR_INVALID_POLICY_EXTENSION,
-    X509_V_ERR_NO_EXPLICIT_POLICY,
-    X509_V_ERR_UNNESTED_RESOURCE,
-
-    X509_R_CERT_ALREADY_IN_HASH_TABLE,
-
-    XN_FLAG_SPC_EQ  = (1 << 23),
-    XN_FLAG_ONELINE = 0,
-    XN_FLAG_RFC2253 = 1,
-
-    CRYPTO_LOCK = 1,
-    CRYPTO_NUM_LOCKS = 10,
-
-    ASN1_STRFLGS_ESC_MSB = 4
-};
-#endif
-
-/* extras end */
-
-#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
-/* wolfSSL extension, provide last error from SSL_get_error
-   since not using thread storage error queue */
-#include <stdio.h>
-WOLFSSL_API void  wolfSSL_ERR_print_errors_fp(XFILE, int err);
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp);
-#endif
-#endif
-
-
-#ifndef NO_OLD_SSL_NAMES
-    #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE
-    #define SSL_FAILURE WOLFSSL_FAILURE
-    #define SSL_SUCCESS WOLFSSL_SUCCESS
-    #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE
-
-    #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND
-    #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE
-    #define SSL_BAD_STAT WOLFSSL_BAD_STAT
-    #define SSL_BAD_PATH WOLFSSL_BAD_PATH
-    #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE
-    #define SSL_BAD_FILE WOLFSSL_BAD_FILE
-    #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED
-    #define SSL_UNKNOWN WOLFSSL_UNKNOWN
-    #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR
-
-    #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1
-    #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM
-    #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT
-    #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW
-
-    #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE
-    #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER
-    #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT
-    #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE
-    #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK
-
-    #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF
-    #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT
-    #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER
-    #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH
-    #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR
-    #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP
-    #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE
-    #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL
-
-    #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ
-    #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE
-    #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT
-    #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT
-    #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL
-    #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP
-    #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN
-    #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL
-
-    #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN
-    #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN
-    #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
-    #define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2
-
-    #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE
-    #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA
-    #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
-    #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE
-
-    #define PEM_BUFSIZE WOLF_PEM_BUFSIZE
-#endif
-
-enum { /* ssl Constants */
-    WOLFSSL_ERROR_NONE      =  0,   /* for most functions */
-    WOLFSSL_FAILURE         =  0,   /* for some functions */
-    WOLFSSL_SUCCESS         =  1,
-    WOLFSSL_SHUTDOWN_NOT_DONE =  2,  /* call wolfSSL_shutdown again to complete */
-
-    WOLFSSL_ALPN_NOT_FOUND  = -9,
-    WOLFSSL_BAD_CERTTYPE    = -8,
-    WOLFSSL_BAD_STAT        = -7,
-    WOLFSSL_BAD_PATH        = -6,
-    WOLFSSL_BAD_FILETYPE    = -5,
-    WOLFSSL_BAD_FILE        = -4,
-    WOLFSSL_NOT_IMPLEMENTED = -3,
-    WOLFSSL_UNKNOWN         = -2,
-    WOLFSSL_FATAL_ERROR     = -1,
-
-    WOLFSSL_FILETYPE_ASN1    = 2,
-    WOLFSSL_FILETYPE_PEM     = 1,
-    WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */
-    WOLFSSL_FILETYPE_RAW     = 3, /* NTRU raw key blob */
-
-    WOLFSSL_VERIFY_NONE                 = 0,
-    WOLFSSL_VERIFY_PEER                 = 1,
-    WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
-    WOLFSSL_VERIFY_CLIENT_ONCE          = 4,
-    WOLFSSL_VERIFY_FAIL_EXCEPT_PSK      = 8,
-
-    WOLFSSL_SESS_CACHE_OFF                = 0x0000,
-    WOLFSSL_SESS_CACHE_CLIENT             = 0x0001,
-    WOLFSSL_SESS_CACHE_SERVER             = 0x0002,
-    WOLFSSL_SESS_CACHE_BOTH               = 0x0003,
-    WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR      = 0x0008,
-    WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100,
-    WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE  = 0x0200,
-    WOLFSSL_SESS_CACHE_NO_INTERNAL        = 0x0300,
-
-    WOLFSSL_ERROR_WANT_READ        =  2,
-    WOLFSSL_ERROR_WANT_WRITE       =  3,
-    WOLFSSL_ERROR_WANT_CONNECT     =  7,
-    WOLFSSL_ERROR_WANT_ACCEPT      =  8,
-    WOLFSSL_ERROR_SYSCALL          =  5,
-    WOLFSSL_ERROR_WANT_X509_LOOKUP = 83,
-    WOLFSSL_ERROR_ZERO_RETURN      =  6,
-    WOLFSSL_ERROR_SSL              = 85,
-
-    WOLFSSL_SENT_SHUTDOWN     = 1,
-    WOLFSSL_RECEIVED_SHUTDOWN = 2,
-    WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4,
-    WOLFSSL_OP_NO_SSLv2       = 8,
-
-    WOLFSSL_R_SSL_HANDSHAKE_FAILURE           = 101,
-    WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA          = 102,
-    WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103,
-    WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE     = 104,
-
-    WOLF_PEM_BUFSIZE = 1024
-};
-
-#ifndef NO_PSK
-    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
-                                    unsigned int, unsigned char*, unsigned int);
-    WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*,
-                                                    wc_psk_client_callback);
-    WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*,
-                                                    wc_psk_client_callback);
-
-    WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*);
-    WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*);
-
-    WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*);
-    WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*);
-
-    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
-                          unsigned char*, unsigned int);
-    WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*,
-                                                    wc_psk_server_callback);
-    WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*,
-                                                    wc_psk_server_callback);
-
-    #define PSK_TYPES_DEFINED
-#endif /* NO_PSK */
-
-
-#ifdef HAVE_ANON
-    WOLFSSL_API int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX*);
-#endif /* HAVE_ANON */
-
-
-/* extra begins */
-#ifdef OPENSSL_EXTRA
-enum {  /* ERR Constants */
-    ERR_TXT_STRING = 1
-};
-
-/* bio misc */
-enum {
-    WOLFSSL_BIO_ERROR = -1,
-    WOLFSSL_BIO_UNSET = -2,
-    WOLFSSL_BIO_SIZE  = 17000 /* default BIO write size if not set */
-};
-#endif
-
-WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err,
-                                       const char* file, int line);
-WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*);
-WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*,
-                                                 const char**, int *);
-
-WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void);
-WOLFSSL_API void          wolfSSL_ERR_clear_error(void);
-
-
-WOLFSSL_API int  wolfSSL_RAND_status(void);
-WOLFSSL_API int  wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num);
-WOLFSSL_API int  wolfSSL_RAND_bytes(unsigned char* buf, int num);
-WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void);
-WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long);
-WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx);
-WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long);
-
-#ifndef NO_CERTS
-  WOLFSSL_API int  wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*);
-#endif /* !NO_CERTS */
-
-WOLFSSL_API void wolfSSL_ERR_free_strings(void);
-WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long);
-WOLFSSL_API int  wolfSSL_clear(WOLFSSL* ssl);
-WOLFSSL_API int  wolfSSL_state(WOLFSSL* ssl);
-
-WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void);
-WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode);
-WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx);
-WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m);
-WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl);
-
-
-WOLFSSL_API int  wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*);
-WOLFSSL_API int  wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*,
-                                            const unsigned char*, unsigned int);
-WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl);
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*);
-
-WOLFSSL_API int wolfSSL_want_read(WOLFSSL*);
-WOLFSSL_API int wolfSSL_want_write(WOLFSSL*);
-
-WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...);
-WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*,
-                                         const WOLFSSL_ASN1_UTCTIME*);
-WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*,
-                                         const WOLFSSL_ASN1_GENERALIZEDTIME*);
-WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*);
-WOLFSSL_API int   wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*);
-WOLFSSL_API void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*, int);
-
-/* stunnel 4.28 needs */
-WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int);
-WOLFSSL_API int   wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*);
-WOLFSSL_API void  wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*,
-                       WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*));
-WOLFSSL_API void  wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*,
-                                            int (*f)(WOLFSSL*, WOLFSSL_SESSION*));
-WOLFSSL_API void  wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX*,
-                                       void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*));
-
-WOLFSSL_API int          wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION*,unsigned char**);
-WOLFSSL_API WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION**,
-                                                   const unsigned char**, long);
-
-WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*);
-WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*);
-WOLFSSL_API int  wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*);
-
-/* extra ends */
-
-
-/* wolfSSL extensions */
-
-/* call before SSL_connect, if verifying will add name check to
-   date check and signature check */
-WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
-
-/* need to call once to load library (session cache) */
-WOLFSSL_API int wolfSSL_Init(void);
-/* call when done to cleanup/free session cache mutex / resources  */
-WOLFSSL_API int wolfSSL_Cleanup(void);
-
-/* which library version do we have */
-WOLFSSL_API const char* wolfSSL_lib_version(void);
-/* which library version do we have in hex */
-WOLFSSL_API unsigned int wolfSSL_lib_version_hex(void);
-
-/* do accept or connect depedning on side */
-WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl);
-/* turn on wolfSSL data compression */
-WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl);
-
-WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int);
-WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int);
-
-/* get wolfSSL peer X509_CHAIN */
-WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl);
-#ifdef WOLFSSL_ALT_CERT_CHAINS
-WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl);
-/* get wolfSSL alternate peer X509_CHAIN */
-WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl);
-#endif
-/* peer chain count */
-WOLFSSL_API int  wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain);
-/* index cert length */
-WOLFSSL_API int  wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN*, int idx);
-/* index cert */
-WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx);
-/* index cert in X509 */
-WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx);
-/* free X509 */
-#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509))
-WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*);
-/* get index cert in PEM */
-WOLFSSL_API int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx,
-                                unsigned char* buf, int inLen, int* outLen);
-WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(const WOLFSSL_SESSION* s);
-WOLFSSL_API int  wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*);
-WOLFSSL_API char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509*);
-WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*);
-WOLFSSL_API const unsigned char* wolfSSL_X509_notBefore(WOLFSSL_X509*);
-WOLFSSL_API const unsigned char* wolfSSL_X509_notAfter(WOLFSSL_X509*);
-WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*);
-
-WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*);
-
-WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*);
-
-WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509,
-        const unsigned char** in, int len);
-WOLFSSL_API WOLFSSL_X509*
-    wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len);
-WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out);
-WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl,
-                                                   const unsigned char *in, int len);
-#ifndef NO_FILESYSTEM
-WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl);
-#endif
-WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl);
-
-#ifndef NO_FILESYSTEM
-    #ifndef NO_STDIO_FILESYSTEM
-    WOLFSSL_API WOLFSSL_X509*
-        wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file);
-    #endif
-WOLFSSL_API WOLFSSL_X509*
-    wolfSSL_X509_load_certificate_file(const char* fname, int format);
-#endif
-WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
-    const unsigned char* buf, int sz, int format);
-
-#ifdef WOLFSSL_SEP
-    WOLFSSL_API unsigned char*
-           wolfSSL_X509_get_device_type(WOLFSSL_X509*, unsigned char*, int*);
-    WOLFSSL_API unsigned char*
-           wolfSSL_X509_get_hw_type(WOLFSSL_X509*, unsigned char*, int*);
-    WOLFSSL_API unsigned char*
-           wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509*, unsigned char*, int*);
-#endif
-
-/* connect enough to get peer cert */
-WOLFSSL_API int  wolfSSL_connect_cert(WOLFSSL* ssl);
-
-
-
-/* PKCS12 compatibility */
-typedef struct WC_PKCS12 WC_PKCS12;
-WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio,
-                                       WC_PKCS12** pkcs12);
-#ifndef NO_FILESYSTEM
-WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp,
-                                       WOLFSSL_X509_PKCS12** pkcs12);
-#endif
-WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
-     WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
-     WOLF_STACK_OF(WOLFSSL_X509)** ca);
-WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
-        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
-        WOLF_STACK_OF(WOLFSSL_X509)* ca,
-        int keyNID, int certNID, int itt, int macItt, int keytype);
-WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void);
-
-
-
-#ifndef NO_DH
-/* server Diffie-Hellman parameters */
-WOLFSSL_API int  wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz,
-                                const unsigned char* g, int gSz);
-WOLFSSL_API int  wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz,
-                                       int format);
-#ifndef NO_FILESYSTEM
-    WOLFSSL_API int  wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format);
-#endif
-
-/* server ctx Diffie-Hellman parameters */
-WOLFSSL_API int  wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX*, const unsigned char* p,
-                                    int pSz, const unsigned char* g, int gSz);
-WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* b,
-                                           long sz, int format);
-
-#ifndef NO_FILESYSTEM
-    WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f,
-                                             int format);
-#endif
-
-WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, unsigned short);
-WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, unsigned short);
-WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, unsigned short);
-WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, unsigned short);
-WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*);
-#endif /* NO_DH */
-
-#ifndef NO_RSA
-WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short);
-WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short);
-#endif /* NO_RSA */
-
-#ifdef HAVE_ECC
-WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short);
-WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
-#endif /* NO_RSA */
-
-WOLFSSL_API int  wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short);
-WOLFSSL_API int  wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, unsigned short);
-
-/* keyblock size in bytes or -1 */
-/* need to call wolfSSL_KeepArrays before handshake to save keys */
-WOLFSSL_API int wolfSSL_get_keyblock_size(WOLFSSL*);
-WOLFSSL_API int wolfSSL_get_keys(WOLFSSL*,unsigned char** ms, unsigned int* msLen,
-                                       unsigned char** sr, unsigned int* srLen,
-                                       unsigned char** cr, unsigned int* crLen);
-
-/* Computes EAP-TLS and EAP-TTLS keying material from the master_secret. */
-WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len,
-                                                             const char* label);
-
-
-#ifndef _WIN32
-    #ifndef NO_WRITEV
-        #ifdef __PPU
-            #include <sys/types.h>
-            #include <sys/socket.h>
-        #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \
-              !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \
-              !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \
-              !defined(WOLFSSL_CHIBIOS)
-            #include <sys/uio.h>
-        #endif
-        /* allow writev style writing */
-        WOLFSSL_API int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov,
-                                     int iovcnt);
-    #endif
-#endif
-
-
-#ifndef NO_CERTS
-    /* SSL_CTX versions */
-    WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*);
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*);
-    WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*,
-                                               const unsigned char*, long, int);
-#endif
-    WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*,
-                                               const unsigned char*, long, int);
-    WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*,
-                                               const unsigned char*, long, int);
-    WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*,
-                                               const unsigned char*, long, int);
-    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*,
-                                               const unsigned char*, long, int);
-    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*,
-                                                    const unsigned char*, long);
-
-    /* SSL versions */
-    WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*,
-                                               long, int);
-    WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*,
-                                               long, int);
-    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*,
-                                               const unsigned char*, long, int);
-    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*,
-                                               const unsigned char*, long);
-    WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*);
-
-    #if defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT)
-        WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl);
-    #endif
-#endif
-
-WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*);
-WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*);
-
-
-#ifdef HAVE_FUZZER
-enum fuzzer_type {
-    FUZZ_HMAC      = 0,
-    FUZZ_ENCRYPT   = 1,
-    FUZZ_SIGNATURE = 2,
-    FUZZ_HASH      = 3,
-    FUZZ_HEAD      = 4
-};
-
-typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz,
-        int type, void* fuzzCtx);
-
-WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx);
-#endif
-
-
-WOLFSSL_API int   wolfSSL_DTLS_SetCookieSecret(WOLFSSL*,
-                                               const unsigned char*,
-                                               unsigned int);
-
-
-/* I/O Callback default errors */
-enum IOerrors {
-    WOLFSSL_CBIO_ERR_GENERAL    = -1,     /* general unexpected err */
-    WOLFSSL_CBIO_ERR_WANT_READ  = -2,     /* need to call read  again */
-    WOLFSSL_CBIO_ERR_WANT_WRITE = -2,     /* need to call write again */
-    WOLFSSL_CBIO_ERR_CONN_RST   = -3,     /* connection reset */
-    WOLFSSL_CBIO_ERR_ISR        = -4,     /* interrupt */
-    WOLFSSL_CBIO_ERR_CONN_CLOSE = -5,     /* connection closed or epipe */
-    WOLFSSL_CBIO_ERR_TIMEOUT    = -6      /* socket timeout */
-};
-
-
-/* CA cache callbacks */
-enum {
-    WOLFSSL_SSLV3    = 0,
-    WOLFSSL_TLSV1    = 1,
-    WOLFSSL_TLSV1_1  = 2,
-    WOLFSSL_TLSV1_2  = 3,
-    WOLFSSL_TLSV1_3  = 4,
-    WOLFSSL_USER_CA  = 1,          /* user added as trusted */
-    WOLFSSL_CHAIN_CA = 2           /* added to cache from trusted chain */
-};
-
-WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*);
-
-WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version);
-WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version);
-WOLFSSL_API int wolfSSL_GetObjectSize(void);  /* object size based on build */
-WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void);
-WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void);
-WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int);
-WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*);
-WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version);
-
-/* moved to asn.c, old names kept for backwards compatability */
-#define wolfSSL_KeyPemToDer    wc_KeyPemToDer
-#define wolfSSL_CertPemToDer   wc_CertPemToDer
-#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer
-#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer
-#define wolfSSL_PemCertToDer   wc_PemCertToDer
-
-
-typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
-typedef void (*CbMissingCRL)(const char* url);
-typedef int  (*CbOCSPIO)(void*, const char*, int,
-                                         unsigned char*, int, unsigned char**);
-typedef void (*CbOCSPRespFree)(void*,unsigned char*);
-
-#ifdef HAVE_CRL_IO
-typedef int  (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz);
-#endif
-
-/* User Atomic Record Layer CallBacks */
-typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut,
-       const unsigned char* macIn, unsigned int macInSz, int macContent,
-       int macVerify, unsigned char* encOut, const unsigned char* encIn,
-       unsigned int encSz, void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX*, CallbackMacEncrypt);
-WOLFSSL_API void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl,
-       unsigned char* decOut, const unsigned char* decIn,
-       unsigned int decSz, int content, int verify, unsigned int* padSz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*,
-                                               CallbackDecryptVerify);
-WOLFSSL_API void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl);
-
-WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int);
-WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*);
-WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*);
-WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*);
-WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteIV(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetKeySize(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetIVSize(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetSide(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_IsTLSv1_1(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetBulkCipher(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetCipherBlockSize(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetAeadMacSize(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetHmacSize(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetHmacType(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_GetCipherType(WOLFSSL*);
-WOLFSSL_API int                  wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*,
-                                                       unsigned int, int, int);
-
-/* Atomic User Needs */
-enum {
-    WOLFSSL_SERVER_END = 0,
-    WOLFSSL_CLIENT_END = 1,
-    WOLFSSL_NEITHER_END = 3,
-    WOLFSSL_BLOCK_TYPE = 2,
-    WOLFSSL_STREAM_TYPE = 3,
-    WOLFSSL_AEAD_TYPE = 4,
-    WOLFSSL_TLS_HMAC_INNER_SZ = 13      /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */
-};
-
-/* for GetBulkCipher and internal use */
-enum BulkCipherAlgorithm {
-    wolfssl_cipher_null,
-    wolfssl_rc4,
-    wolfssl_rc2,
-    wolfssl_des,
-    wolfssl_triple_des,             /* leading 3 (3des) not valid identifier */
-    wolfssl_des40,
-#ifdef HAVE_IDEA
-    wolfssl_idea,
-#endif
-    wolfssl_aes,
-    wolfssl_aes_gcm,
-    wolfssl_aes_ccm,
-    wolfssl_chacha,
-    wolfssl_camellia,
-    wolfssl_hc128,                  /* wolfSSL extensions */
-    wolfssl_rabbit
-};
-
-
-/* for KDF TLS 1.2 mac types */
-enum KDF_MacAlgorithm {
-    wolfssl_sha256 = 4,     /* needs to match internal MACAlgorithm */
-    wolfssl_sha384,
-    wolfssl_sha512
-};
-
-
-/* Public Key Callback support */
-#ifdef HAVE_PK_CALLBACKS
-#ifdef HAVE_ECC
-
-struct ecc_key;
-
-typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key, 
-    unsigned int keySz, int ecc_curve, void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen);
-WOLFSSL_API void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackEccSign)(WOLFSSL* ssl,
-       const unsigned char* in, unsigned int inSz,
-       unsigned char* out, unsigned int* outSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, CallbackEccSign);
-WOLFSSL_API void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackEccVerify)(WOLFSSL* ssl,
-       const unsigned char* sig, unsigned int sigSz,
-       const unsigned char* hash, unsigned int hashSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       int* result, void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify);
-WOLFSSL_API void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey,
-        unsigned char* pubKeyDer, unsigned int* pubKeySz,
-        unsigned char* out, unsigned int* outlen,
-        int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
-WOLFSSL_API void  wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret);
-WOLFSSL_API void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl);
-#endif
-
-#ifndef NO_DH
-/* Public DH Key Callback support */
-struct DhKey;
-typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key,
-        const unsigned char* priv, unsigned int privSz,
-        const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz,
-        unsigned char* out, unsigned int* outlen,
-        void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree);
-WOLFSSL_API void  wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl);
-#endif /* !NO_DH */
-
-#ifdef HAVE_ED25519
-struct ed25519_key;
-typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl,
-       const unsigned char* in, unsigned int inSz,
-       unsigned char* out, unsigned int* outSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*,
-                                               CallbackEd25519Sign);
-WOLFSSL_API void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl,
-       const unsigned char* sig, unsigned int sigSz,
-       const unsigned char* msg, unsigned int msgSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       int* result, void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*,
-                                                 CallbackEd25519Verify);
-WOLFSSL_API void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl);
-#endif
-
-#ifdef HAVE_CURVE25519
-struct curve25519_key;
-
-typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key, 
-    unsigned int keySz, void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen);
-WOLFSSL_API void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl,
-        struct curve25519_key* otherKey,
-        unsigned char* pubKeyDer, unsigned int* pubKeySz,
-        unsigned char* out, unsigned int* outlen,
-        int side, void* ctx);
-        /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
-WOLFSSL_API void  wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*,
-        CallbackX25519SharedSecret);
-WOLFSSL_API void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl);
-#endif
-
-#ifndef NO_RSA
-typedef int (*CallbackRsaSign)(WOLFSSL* ssl,
-       const unsigned char* in, unsigned int inSz,
-       unsigned char* out, unsigned int* outSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign);
-WOLFSSL_API void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackRsaVerify)(WOLFSSL* ssl,
-       unsigned char* sig, unsigned int sigSz,
-       unsigned char** out,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX*, CallbackRsaVerify);
-WOLFSSL_API void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl);
-
-#ifdef WC_RSA_PSS
-typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl,
-       const unsigned char* in, unsigned int inSz,
-       unsigned char* out, unsigned int* outSz,
-       int hash, int mgf,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign);
-WOLFSSL_API void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl);
-
-typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl,
-       unsigned char* sig, unsigned int sigSz,
-       unsigned char** out,
-       int hash, int mgf,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*,
-                                                CallbackRsaPssVerify);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX*,
-                                                    CallbackRsaPssVerify);
-WOLFSSL_API void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl);
-#endif
-
-/* RSA Public Encrypt cb */
-typedef int (*CallbackRsaEnc)(WOLFSSL* ssl,
-       const unsigned char* in, unsigned int inSz,
-       unsigned char* out, unsigned int* outSz,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc);
-WOLFSSL_API void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl);
-
-/* RSA Private Decrypt cb */
-typedef int (*CallbackRsaDec)(WOLFSSL* ssl,
-       unsigned char* in, unsigned int inSz,
-       unsigned char** out,
-       const unsigned char* keyDer, unsigned int keySz,
-       void* ctx);
-WOLFSSL_API void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec);
-WOLFSSL_API void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx);
-WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl);
-#endif
-#endif /* HAVE_PK_CALLBACKS */
-
-#ifndef NO_CERTS
-    WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache);
-
-    WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*);
-
-    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_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f,
-                                                                 const char* d);
-    WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*,
-                                  const unsigned char* in, long sz, int format);
-    WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm);
-#ifdef WOLFSSL_TRUST_PEER_CERT
-    WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm);
-#endif
-    WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f,
-                                                                    int format);
-    WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
-                                const unsigned char* buff, long sz, int format);
-    WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER*,
-                                                        unsigned char*, int sz);
-    WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*,
-                                                                   int options);
-    WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*);
-    WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*,
-                                                         const char*, int, int);
-    WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*,
-                                            const unsigned char*, long sz, int);
-    WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*,
-                                                                  CbMissingCRL);
-#ifdef HAVE_CRL_IO
-    WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*,
-                                                                       CbCrlIO);
-#endif
-    WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*,
-                                                        unsigned char*, int sz);
-    WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*,
-                                                                   int options);
-    WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*);
-    WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*,
-                                                                   const char*);
-    WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*,
-                                               CbOCSPIO, CbOCSPRespFree, void*);
-
-    WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling(
-                                                      WOLFSSL_CERT_MANAGER* cm);
-    WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling(
-                                                      WOLFSSL_CERT_MANAGER* cm);
-
-    WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options);
-    WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl);
-    WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int);
-    WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*,
-                                          const unsigned char*, long sz, int);
-    WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL);
-#ifdef HAVE_CRL_IO
-    WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb);
-#endif
-    WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options);
-    WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*);
-    WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*);
-    WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*);
-    WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*);
-    WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*);
-
-    WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options);
-    WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx);
-    WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int);
-    WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*,
-                                            const unsigned char*, long sz, int);
-    WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL);
-#ifdef HAVE_CRL_IO
-    WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO);
-#endif
-
-    WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options);
-    WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*);
-    WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*);
-    WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*,
-                                               CbOCSPIO, CbOCSPRespFree, void*);
-    WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*);
-    WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*);
-#endif /* !NO_CERTS */
-
-
-#ifdef SINGLE_THREADED
-    WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*);
-#endif
-
-/* end of handshake frees temporary arrays, if user needs for get_keys or
-   psk hints, call KeepArrays before handshake and then FreeArrays when done
-   if don't want to wait for object free */
-WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*);
-WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*);
-
-WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl);
-
-WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx);
-WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl);
-
-/* async additions */
-#define wolfSSL_UseAsync wolfSSL_SetDevId
-#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId
-WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId);
-WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId);
-
-/* helpers to get device id and heap */
-WOLFSSL_API int   wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
-WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
-
-/* TLS Extensions */
-
-/* Server Name Indication */
-#ifdef HAVE_SNI
-
-/* SNI types */
-enum {
-    WOLFSSL_SNI_HOST_NAME = 0
-};
-
-WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
-                                         const void* data, unsigned short size);
-WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type,
-                                         const void* data, unsigned short size);
-
-#ifndef NO_WOLFSSL_SERVER
-
-/* SNI options */
-enum {
-    /* Do not abort the handshake if the requested SNI didn't match. */
-    WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01,
-
-    /* Behave as if the requested SNI matched in a case of mismatch.  */
-    /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */
-    WOLFSSL_SNI_ANSWER_ON_MISMATCH   = 0x02,
-
-    /* Abort the handshake if the client didn't send a SNI request. */
-    WOLFSSL_SNI_ABORT_ON_ABSENCE     = 0x04,
-};
-
-WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type,
-                                                         unsigned char options);
-WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx,
-                                     unsigned char type, unsigned char options);
-WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
-                 const unsigned char* clientHello, unsigned int helloSz,
-                 unsigned char type, unsigned char* sni, unsigned int* inOutSz);
-
-#endif /* NO_WOLFSSL_SERVER */
-
-/* SNI status */
-enum {
-    WOLFSSL_SNI_NO_MATCH   = 0,
-    WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */
-    WOLFSSL_SNI_REAL_MATCH = 2,
-    WOLFSSL_SNI_FORCE_KEEP = 3  /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */
-};
-
-WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type);
-
-WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl,
-                                               unsigned char type, void** data);
-
-#endif /* HAVE_SNI */
-
-/* Application-Layer Protocol Negotiation */
-#ifdef HAVE_ALPN
-
-/* ALPN status code */
-enum {
-    WOLFSSL_ALPN_NO_MATCH = 0,
-    WOLFSSL_ALPN_MATCH    = 1,
-    WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2,
-    WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4,
-};
-
-enum {
-    WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255,
-    WOLFSSL_MAX_ALPN_NUMBER = 257
-};
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out,
-    unsigned char* outLen, const unsigned char* in, unsigned int inLen,
-    void *arg);
-#endif
-
-WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
-                                unsigned int protocol_name_listSz,
-                                unsigned char options);
-
-WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
-                                         unsigned short *size);
-
-WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list,
-                                             unsigned short *listSz);
-WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list);
-#endif /* HAVE_ALPN */
-
-/* Maximum Fragment Length */
-#ifdef HAVE_MAX_FRAGMENT
-
-/* Fragment lengths */
-enum {
-    WOLFSSL_MFL_2_9  = 1, /*  512 bytes */
-    WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */
-    WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */
-    WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */
-    WOLFSSL_MFL_2_13 = 5  /* 8192 bytes *//* wolfSSL ONLY!!! */
-};
-
-#ifndef NO_WOLFSSL_CLIENT
-
-WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl);
-WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl);
-
-#endif
-#endif
-
-/* Truncated HMAC */
-#ifdef HAVE_TRUNCATED_HMAC
-#ifndef NO_WOLFSSL_CLIENT
-
-WOLFSSL_API int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx);
-
-#endif
-#endif
-
-/* Certificate Status Request */
-/* Certificate Status Type */
-enum {
-    WOLFSSL_CSR_OCSP = 1
-};
-
-/* Certificate Status Options (flags) */
-enum {
-    WOLFSSL_CSR_OCSP_USE_NONCE = 0x01
-};
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-#ifndef NO_WOLFSSL_CLIENT
-
-WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl,
-                              unsigned char status_type, unsigned char options);
-
-WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx,
-                              unsigned char status_type, unsigned char options);
-
-#endif
-#endif
-
-/* Certificate Status Request v2 */
-/* Certificate Status Type */
-enum {
-    WOLFSSL_CSR2_OCSP = 1,
-    WOLFSSL_CSR2_OCSP_MULTI = 2
-};
-
-/* Certificate Status v2 Options (flags) */
-enum {
-    WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01
-};
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-#ifndef NO_WOLFSSL_CLIENT
-
-WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl,
-                              unsigned char status_type, unsigned char options);
-
-WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx,
-                              unsigned char status_type, unsigned char options);
-
-#endif
-#endif
-
-/* Named Groups */
-enum {
-#if 0 /* Not Supported */
-    WOLFSSL_ECC_SECT163K1 = 1,
-    WOLFSSL_ECC_SECT163R1 = 2,
-    WOLFSSL_ECC_SECT163R2 = 3,
-    WOLFSSL_ECC_SECT193R1 = 4,
-    WOLFSSL_ECC_SECT193R2 = 5,
-    WOLFSSL_ECC_SECT233K1 = 6,
-    WOLFSSL_ECC_SECT233R1 = 7,
-    WOLFSSL_ECC_SECT239K1 = 8,
-    WOLFSSL_ECC_SECT283K1 = 9,
-    WOLFSSL_ECC_SECT283R1 = 10,
-    WOLFSSL_ECC_SECT409K1 = 11,
-    WOLFSSL_ECC_SECT409R1 = 12,
-    WOLFSSL_ECC_SECT571K1 = 13,
-    WOLFSSL_ECC_SECT571R1 = 14,
-#endif
-    WOLFSSL_ECC_SECP160K1 = 15,
-    WOLFSSL_ECC_SECP160R1 = 16,
-    WOLFSSL_ECC_SECP160R2 = 17,
-    WOLFSSL_ECC_SECP192K1 = 18,
-    WOLFSSL_ECC_SECP192R1 = 19,
-    WOLFSSL_ECC_SECP224K1 = 20,
-    WOLFSSL_ECC_SECP224R1 = 21,
-    WOLFSSL_ECC_SECP256K1 = 22,
-    WOLFSSL_ECC_SECP256R1 = 23,
-    WOLFSSL_ECC_SECP384R1 = 24,
-    WOLFSSL_ECC_SECP521R1 = 25,
-    WOLFSSL_ECC_BRAINPOOLP256R1 = 26,
-    WOLFSSL_ECC_BRAINPOOLP384R1 = 27,
-    WOLFSSL_ECC_BRAINPOOLP512R1 = 28,
-    WOLFSSL_ECC_X25519    = 29,
-#ifdef WOLFSSL_TLS13
-    /* Not implemented. */
-    WOLFSSL_ECC_X448      = 30,
-
-    WOLFSSL_FFDHE_2048    = 256,
-    WOLFSSL_FFDHE_3072    = 257,
-    WOLFSSL_FFDHE_4096    = 258,
-    WOLFSSL_FFDHE_6144    = 259,
-    WOLFSSL_FFDHE_8192    = 260,
-#endif
-};
-
-enum {
-    WOLFSSL_EC_PF_UNCOMPRESSED = 0,
-#if 0 /* Not Supported */
-    WOLFSSL_EC_PF_X962_COMP_PRIME = 1,
-    WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2,
-#endif
-};
-
-#ifdef HAVE_SUPPORTED_CURVES
-#ifndef NO_WOLFSSL_CLIENT
-
-WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, unsigned short name);
-WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx,
-                                                           unsigned short name);
-
-#endif
-#endif
-
-#ifdef WOLFSSL_TLS13
-WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, unsigned short group);
-WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl);
-#endif
-
-
-/* Secure Renegotiation */
-#ifdef HAVE_SECURE_RENEGOTIATION
-
-WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl);
-
-#endif
-
-/* Session Ticket */
-#ifdef HAVE_SESSION_TICKET
-
-#ifndef NO_WOLFSSL_CLIENT
-WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
-WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*);
-WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, unsigned int);
-typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*);
-WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
-                                                  CallbackSessionTicket, void*);
-#endif /* NO_WOLFSSL_CLIENT */
-
-
-#define WOLFSSL_TICKET_NAME_SZ 16
-#define WOLFSSL_TICKET_IV_SZ   16
-#define WOLFSSL_TICKET_MAC_SZ  32
-
-enum TicketEncRet {
-    WOLFSSL_TICKET_RET_FATAL  = -1,  /* fatal error, don't use ticket */
-    WOLFSSL_TICKET_RET_OK     =  0,  /* ok, use ticket */
-    WOLFSSL_TICKET_RET_REJECT,       /* don't use ticket, but not fatal */
-    WOLFSSL_TICKET_RET_CREATE        /* existing ticket ok and create new one */
-};
-
-#ifndef NO_WOLFSSL_SERVER
-
-typedef int (*SessionTicketEncCb)(WOLFSSL*,
-                                 unsigned char key_name[WOLFSSL_TICKET_NAME_SZ],
-                                 unsigned char iv[WOLFSSL_TICKET_IV_SZ],
-                                 unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
-                                 int enc, unsigned char*, int, int*, void*);
-WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx,
-                                            SessionTicketEncCb);
-WOLFSSL_API int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int);
-WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*);
-
-#endif /* NO_WOLFSSL_SERVER */
-
-#endif /* HAVE_SESSION_TICKET */
-
-#ifdef HAVE_QSH
-/* Quantum-safe Crypto Schemes */
-enum {
-    WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65  */
-    WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86  */
-    WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */
-    WOLFSSL_LWE_XXX  = 0x0201,     /* Learning With Error encryption scheme */
-    WOLFSSL_HFE_XXX  = 0x0301,     /* Hidden Field Equation scheme */
-    WOLFSSL_NULL_QSH = 0xFFFF      /* QSHScheme is not used */
-};
-
-
-/* test if the connection is using a QSH secure connection return 1 if so */
-WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name);
-#ifndef NO_WOLFSSL_CLIENT
-    /* user control over sending client public key in hello
-       when flag = 1 will send keys if flag is 0 or function is not called
-       then will not send keys in the hello extension */
-    WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag);
-#endif
-
-#endif /* QSH */
-
-/* TLS Extended Master Secret Extension */
-WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl);
-WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
-
-
-#define WOLFSSL_CRL_MONITOR   0x01   /* monitor this dir flag */
-#define WOLFSSL_CRL_START_MON 0x02   /* start monitoring flag */
-
-
-/* notify user the handshake is done */
-typedef int (*HandShakeDoneCb)(WOLFSSL*, void*);
-WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*);
-
-
-WOLFSSL_API int wolfSSL_PrintSessionStats(void);
-WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
-                                          unsigned int* total,
-                                          unsigned int* peak,
-                                          unsigned int* maxSessions);
-/* External facing KDF */
-WOLFSSL_API
-int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
-                               const unsigned char* pms, unsigned int pmsLen,
-                               const unsigned char* cr, const unsigned char* sr,
-                               int tls1_2, int hash_type);
-
-WOLFSSL_API
-int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, unsigned int msLen,
-                              const unsigned char* pms, unsigned int pmsLen,
-                              const unsigned char* sHash, unsigned int sHashLen,
-                              int tls1_2, int hash_type);
-
-WOLFSSL_API
-int wolfSSL_DeriveTlsKeys(unsigned char* key_data, unsigned int keyLen,
-                               const unsigned char* ms, unsigned int msLen,
-                               const unsigned char* sr, const unsigned char* cr,
-                               int tls1_2, int hash_type);
-
-#ifdef WOLFSSL_CALLBACKS
-
-/* used internally by wolfSSL while OpenSSL types aren't */
-#include <wolfssl/callbacks.h>
-
-typedef int (*HandShakeCallBack)(HandShakeInfo*);
-typedef int (*TimeoutCallBack)(TimeoutInfo*);
-
-/* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack
-   for diagnostics */
-WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
-                                 Timeval);
-WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
-                                Timeval);
-
-#endif /* WOLFSSL_CALLBACKS */
-
-
-#ifdef WOLFSSL_HAVE_WOLFSCEP
-    WOLFSSL_API void wolfSSL_wolfSCEP(void);
-#endif /* WOLFSSL_HAVE_WOLFSCEP */
-
-#ifdef WOLFSSL_HAVE_CERT_SERVICE
-    WOLFSSL_API void wolfSSL_cert_service(void);
-#endif
-
-#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
- * this subset and its memory usage */
-
-#include <wolfssl/openssl/asn1.h>
-struct WOLFSSL_X509_NAME_ENTRY {
-    WOLFSSL_ASN1_OBJECT* object; /* not defined yet */
-    WOLFSSL_ASN1_STRING  data;
-    WOLFSSL_ASN1_STRING* value;  /* points to data, for lighttpd port */
-    int nid; /* i.e. ASN_COMMON_NAME */
-    int set;
-    int size;
-};
-#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
-
-enum {
-    WOLFSSL_SYS_ACCEPT = 0,
-    WOLFSSL_SYS_BIND,
-    WOLFSSL_SYS_CONNECT,
-    WOLFSSL_SYS_FOPEN,
-    WOLFSSL_SYS_FREAD,
-    WOLFSSL_SYS_GETADDRINFO,
-    WOLFSSL_SYS_GETSOCKOPT,
-    WOLFSSL_SYS_GETSOCKNAME,
-    WOLFSSL_SYS_GETHOSTBYNAME,
-    WOLFSSL_SYS_GETNAMEINFO,
-    WOLFSSL_SYS_GETSERVBYNAME,
-    WOLFSSL_SYS_IOCTLSOCKET,
-    WOLFSSL_SYS_LISTEN,
-    WOLFSSL_SYS_OPENDIR,
-    WOLFSSL_SYS_SETSOCKOPT,
-    WOLFSSL_SYS_SOCKET
-};
-
-/* Object functions */
-WOLFSSL_API const char *  wolfSSL_OBJ_nid2sn(int n);
-WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
-WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn);
-
-WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n);
-WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn);
-
-WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n);
-WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name);
-
-WOLFSSL_API void wolfSSL_OBJ_cleanup(void);
-/* end of object functions */
-
-WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line);
-WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt);
-WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt);
-
-#ifndef NO_CERTS
-WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
-            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
-            unsigned char* data, int dataSz);
-WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
-                              WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set);
-WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
-            const WOLFSSL_X509_NAME* y);
-WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void);
-WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl);
-WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509,
-                                                     int nid, int* c, int* idx);
-WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509,
-        const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len);
-WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509);
-WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der,
-                                                                     int derSz);
-WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey);
-WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl,
-                                            unsigned char* der, long derSz);
-WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl);
-#ifndef NO_RSA
-WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der,
-                                                                long derSz);
-#endif
-#endif /* NO_CERTS */
-
-WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r);
-
-WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
-        unsigned char* out, int outSz);
-WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses);
-
-WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx,
-                                                       WOLFSSL_X509_STORE* str);
-WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
-#if !defined(NO_FILESYSTEM)
-WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp,
-                                               WOLFSSL_X509** x509);
-#endif
-WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio,
-                                               WOLFSSL_X509** x509);
-WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx);
-
-WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b);
-WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl,
-                                             unsigned char *out, size_t outlen);
-WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl,
-                                              unsigned char* out, size_t outSz);
-WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey);
-WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
-WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX
-        (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
-#ifndef NO_FILESYSTEM
-WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **x,
-                                                    pem_password_cb *cb, void *u);
-#endif
-
-/*lighttp compatibility */
-
-struct WOLFSSL_ASN1_BIT_STRING {
-    int length;
-    int type;
-    char* data;
-    long flags;
-};
-
-
-#if    defined(OPENSSL_EXTRA) \
-    || defined(OPENSSL_ALL) \
-    || defined(HAVE_LIGHTY) \
-    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
-    || defined(HAVE_STUNNEL) \
-    || defined(WOLFSSL_NGINX) \
-    || defined(WOLFSSL_HAPROXY)
-WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne);
-WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void);
-WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name);
-WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x);
-WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name);
-/* These are to be merged shortly */
-WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth);
-WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl);
-WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg);
-WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne);
-WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc);
-WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*));
-WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md);
-WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md);
-WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md);
-WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md);
-WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*);
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk );
-WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509);
-
-#ifndef NO_FILESYSTEM
-WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c);
-WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp);
-#endif
-
-#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-
-#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
-
-
-#if defined(OPENSSL_ALL) \
-    || defined(HAVE_STUNNEL) \
-    || defined(HAVE_LIGHTY) \
-    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
-    || defined(WOLFSSL_HAPROXY) \
-    || defined(OPENSSL_EXTRA)
-
-WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode);
-WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*);
-WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp,
-    WOLFSSL_DH **x, pem_password_cb *cb, void *u);
-WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp,
-    WOLFSSL_DSA **x, pem_password_cb *cb, void *u);
-WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
-WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
-WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x);
-
-#endif /* HAVE_STUNNEL || HAVE_LIGHTY */
-
-
-#if defined(OPENSSL_ALL) \
-    || defined(HAVE_STUNNEL) \
-    || defined(WOLFSSL_NGINX) \
-    || defined(WOLFSSL_HAPROXY) \
-    || defined(OPENSSL_EXTRA) \
-    || defined(HAVE_LIGHTY)
-
-#include <wolfssl/openssl/crypto.h>
-
-/* SNI received callback type */
-typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg);
-
-WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
-    void *(*r) (void *, size_t, const char *, int), void (*f) (void *));
-
-WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void);
-
-WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn);
-WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
-    void (*callback) (int, int, void *), void *cb_arg);
-
-WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int,
-                           void (*callback) (int, int, void *));
-
-WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void);
-
-WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void);
-
-WOLFSSL_API int wolfSSL_FIPS_mode(void);
-
-WOLFSSL_API int wolfSSL_FIPS_mode_set(int r);
-
-WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth);
-
-WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits);
-
-WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s);
-
-WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s);
-
-WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int,
-        unsigned long);
-
-WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(
-                            const WOLFSSL_X509*);
-
-WOLFSSL_API int        wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*);
-
-WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl);
-
-WOLFSSL_API int  wolfSSL_version(WOLFSSL*);
-
-WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*);
-
-WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int);
-
-WOLFSSL_API void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int);
-
-WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int);
-
-WOLFSSL_API int   wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*);
-
-WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*,
-        CRYPTO_free_func*);
-
-WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*);
-
-
-WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*,
-        unsigned int*);
-
-WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *);
-
-WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char);
-
-WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*);
-
-WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*);
-
-WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*);
-
-WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *,
-        CallbackSniRecv);
-WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *,
-        CallbackSniRecv);
-
-WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*);
-
-WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*);
-
-/* support for depricated old name */
-#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state
-
-#ifndef NO_FILESYSTEM
-WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE *fp);
-#endif
-
-WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*));
-
-WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val);
-
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
-                               WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*);
-
-WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*));
-#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */
-
-#if defined(OPENSSL_ALL) || \
-    defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
-    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-
-WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx);
-
-#endif
-
-#ifdef WOLFSSL_JNI
-WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr);
-WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl);
-#endif /* WOLFSSL_JNI */
-
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags);
-WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
-    WOLF_EVENT_FLAG flags, int* eventCount);
-#endif /* WOLFSSL_ASYNC_CRYPT */
-
-#ifdef OPENSSL_EXTRA
-WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names);
-
-typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type,
-    const void *buf, size_t len, WOLFSSL *ssl, void *arg);
-
-WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb);
-WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb);
-WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg);
-WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg);
-WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file,
-    int *line, const char **data, int *flags);
-WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx,
-    const unsigned char *protos, unsigned int protos_len);
-WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data,
-    size_t siz, const char* file, int line);
-WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void);
-#endif
-
-#if defined(OPENSSL_ALL) \
-    || defined(WOLFSSL_NGINX) \
-    || defined(WOLFSSL_HAPROXY) \
-    || defined(OPENSSL_EXTRA)
-WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name);
-#endif
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-/* Not an OpenSSL API. */
-WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response);
-/* Not an OpenSSL API. */
-WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl);
-/* Not an OpenSSL API. */
-WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url);
-#endif
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
-    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl);
-WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a,
-    void *b, void *c);
-WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx);
-WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx,
-    void *data);
-
-WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data,
-    const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len);
-
-WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx);
-WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx,
-    WOLFSSL_EC_KEY *ecdh);
-WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *,
-    WOLFSSL_SESSION *c);
-
-WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s);
-WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s);
-WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s);
-WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */
-#ifndef NO_SESSION_CACHE
-    WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s);
-#endif
-WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk,
-    size_t chklen, unsigned int flags, char **peername);
-
-WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp,
-    const WOLFSSL_ASN1_INTEGER *a);
-
-#ifdef HAVE_SESSION_TICKET
-WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)(
-    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
-    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc));
-#endif
-
-#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
-    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx,
-    WOLF_STACK_OF(X509)** chain);
-WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
-    int(*)(WOLFSSL*, void*));
-
-WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
-    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x);
-
-WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk);
-WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x);
-
-WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer,
-    WOLFSSL_X509 *subject);
-
-WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x);
-
-WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value(
-    WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx);
-#endif /* HAVE_OCSP */
-
-WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio,
-    WOLFSSL_X509 *cert);
-
-#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || 
-    OPENSSL_EXTRA || HAVE_LIGHTY*/
-
-WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl,
-        const unsigned char **data, unsigned int *len);
-WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out,
-        unsigned char *outlen,
-        const unsigned char *in, unsigned int inlen,
-        const unsigned char *client,
-        unsigned int client_len);
-WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
-        int (*cb) (WOLFSSL *ssl,
-            const unsigned char **out,
-            unsigned char *outlen,
-            const unsigned char *in,
-            unsigned int inlen,
-            void *arg), void *arg);
-WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
-        int (*cb) (WOLFSSL *ssl,
-            const unsigned char **out,
-            unsigned int *outlen,
-            void *arg), void *arg);
-WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
-        int (*cb) (WOLFSSL *ssl,
-            unsigned char **out,
-            unsigned char *outlen,
-            const unsigned char *in,
-            unsigned int inlen,
-            void *arg), void *arg);
-WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
-        unsigned *len);
-
-
-#ifdef OPENSSL_EXTRA
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context(
-        const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length);
-WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count);
-WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count);
-#endif
-
-WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len);
-WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len);
-WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x);
-WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor);
-WOLFSSL_API void *X509_get_X509_PUBKEY(void * x);
-WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub);
-WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a);
-WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength));
-WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
-WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir);
-WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x);
-WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p);
-WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st);
-WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx);
-WOLFSSL_API void ERR_load_SSL_strings(void);
-WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p);
-
-WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag);
-WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags);
-WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
-                                                                WOLFSSL_ASN1_TIME **out);
-WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp);
-#endif /* OPENSSL_EXTRA */
-
-#ifdef HAVE_PK_CALLBACKS
-WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx);
-#endif
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-
-#endif /* WOLFSSL_SSL_H */
-
+/* ssl.h
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+/*!
+    \file ../wolfssl/ssl.h
+    \brief Header file containing key wolfSSL API
+*/
+
+/* wolfSSL API */
+
+#ifndef WOLFSSL_SSL_H
+#define WOLFSSL_SSL_H
+
+
+/* for users not using preprocessor flags*/
+#include <wolfcrypt/settings.h>
+#include <wolfssl/version.h>
+#include <wolfcrypt/logging.h>
+#include <wolfcrypt/asn_public.h>
+
+#ifdef HAVE_WOLF_EVENT
+    #include <wolfcrypt/wolfevent.h>
+#endif
+
+#ifndef NO_FILESYSTEM
+    #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+        #if MQX_USE_IO_OLD
+            #include <fio.h>
+        #else
+            #include <nio.h>
+        #endif
+    #endif
+#endif
+
+#ifdef WOLFSSL_PREFIX
+    #include "prefix_ssl.h"
+#endif
+
+#ifdef LIBWOLFSSL_VERSION_STRING
+    #define WOLFSSL_VERSION LIBWOLFSSL_VERSION_STRING
+#endif
+
+#ifdef _WIN32
+    /* wincrypt.h clashes */
+    #undef OCSP_REQUEST
+    #undef OCSP_RESPONSE
+#endif
+
+#ifdef OPENSSL_COEXIST
+    /* mode to allow wolfSSL and OpenSSL to exist together */
+    #ifdef TEST_OPENSSL_COEXIST
+        /*
+        ./configure --enable-opensslcoexist \
+            CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \
+            LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto"
+        */
+        #include <openssl/ssl.h>
+        #include <openssl/rand.h>
+        #include <openssl/err.h>
+        #include <openssl/ec.h>
+        #include <openssl/hmac.h>
+        #include <openssl/bn.h>
+    #endif
+
+    /* make sure old names are disabled */
+    #ifndef NO_OLD_SSL_NAMES
+        #define NO_OLD_SSL_NAMES
+    #endif
+    #ifndef NO_OLD_WC_NAMES
+        #define NO_OLD_WC_NAMES
+    #endif
+
+#elif (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    #include <wolfssl/openssl/bn.h>
+    #include <wolfssl/openssl/hmac.h>
+
+    /* We need the old SSL names */
+    #ifdef NO_OLD_SSL_NAMES
+        #undef NO_OLD_SSL_NAMES
+    #endif
+    #ifdef NO_OLD_WC_NAMES
+        #undef NO_OLD_WC_NAMES
+    #endif
+#endif
+
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED
+#define WOLFSSL_WOLFSSL_TYPE_DEFINED
+typedef struct WOLFSSL          WOLFSSL;
+#endif
+typedef struct WOLFSSL_SESSION  WOLFSSL_SESSION;
+typedef struct WOLFSSL_METHOD   WOLFSSL_METHOD;
+#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
+#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED
+typedef struct WOLFSSL_CTX      WOLFSSL_CTX;
+#endif
+
+typedef struct WOLFSSL_STACK      WOLFSSL_STACK;
+typedef struct WOLFSSL_X509       WOLFSSL_X509;
+typedef struct WOLFSSL_X509_NAME  WOLFSSL_X509_NAME;
+typedef struct WOLFSSL_X509_NAME_ENTRY  WOLFSSL_X509_NAME_ENTRY;
+typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN;
+typedef struct WC_PKCS12          WOLFSSL_X509_PKCS12;
+
+typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER;
+typedef struct WOLFSSL_SOCKADDR     WOLFSSL_SOCKADDR;
+typedef struct WOLFSSL_CRL          WOLFSSL_CRL;
+
+typedef void  *WOLFSSL_X509_STORE_CTX_verify_cb; /* verify callback */
+
+/* redeclare guard */
+#define WOLFSSL_TYPES_DEFINED
+
+#include <wolfssl/wolfio.h>
+
+
+#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_RSA            WOLFSSL_RSA;
+#define WOLFSSL_RSA_TYPE_DEFINED
+#endif
+
+#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */
+    typedef struct WC_RNG WC_RNG;
+    #define WC_RNG_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_DSA            WOLFSSL_DSA;
+#define WOLFSSL_DSA_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_EC_KEY         WOLFSSL_EC_KEY;
+typedef struct WOLFSSL_EC_POINT       WOLFSSL_EC_POINT;
+typedef struct WOLFSSL_EC_GROUP       WOLFSSL_EC_GROUP;
+#define WOLFSSL_EC_TYPE_DEFINED
+#endif
+
+#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_ECDSA_SIG      WOLFSSL_ECDSA_SIG;
+#define WOLFSSL_ECDSA_TYPE_DEFINED
+#endif
+
+typedef struct WOLFSSL_CIPHER         WOLFSSL_CIPHER;
+typedef struct WOLFSSL_X509_LOOKUP    WOLFSSL_X509_LOOKUP;
+typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD;
+typedef struct WOLFSSL_CRL            WOLFSSL_X509_CRL;
+typedef struct WOLFSSL_X509_STORE     WOLFSSL_X509_STORE;
+typedef struct WOLFSSL_X509_VERIFY_PARAM  WOLFSSL_X509_VERIFY_PARAM;
+typedef struct WOLFSSL_BIO            WOLFSSL_BIO;
+typedef struct WOLFSSL_BIO_METHOD     WOLFSSL_BIO_METHOD;
+typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION;
+typedef struct WOLFSSL_ASN1_TIME      WOLFSSL_ASN1_TIME;
+typedef struct WOLFSSL_ASN1_INTEGER   WOLFSSL_ASN1_INTEGER;
+typedef struct WOLFSSL_ASN1_OBJECT    WOLFSSL_ASN1_OBJECT;
+
+typedef struct WOLFSSL_ASN1_STRING      WOLFSSL_ASN1_STRING;
+typedef struct WOLFSSL_dynlock_value    WOLFSSL_dynlock_value;
+typedef struct WOLFSSL_DH               WOLFSSL_DH;
+typedef struct WOLFSSL_ASN1_BIT_STRING  WOLFSSL_ASN1_BIT_STRING;
+
+#define WOLFSSL_ASN1_UTCTIME          WOLFSSL_ASN1_TIME
+#define WOLFSSL_ASN1_GENERALIZEDTIME  WOLFSSL_ASN1_TIME
+
+#define WOLFSSL_ASN1_INTEGER_MAX 20
+struct WOLFSSL_ASN1_INTEGER {
+    /* size can be increased set at 20 for tag, length then to hold at least 16
+     * byte type */
+    unsigned char  intData[WOLFSSL_ASN1_INTEGER_MAX];
+    /* ASN_INTEGER | LENGTH | hex of number */
+    unsigned char  negative;   /* negative number flag */
+
+    unsigned char* data;
+    unsigned int   dataMax;   /* max size of data buffer */
+    unsigned int   isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */
+};
+
+struct WOLFSSL_ASN1_TIME {
+    /* MAX_DATA_SIZE is 32 */
+    unsigned char data[32 + 2];
+    /* ASN_TIME | LENGTH | date bytes */
+};
+
+struct WOLFSSL_ASN1_STRING {
+    int length;
+    int type; /* type of string i.e. CTC_UTF8 */
+    char* data;
+    long flags;
+};
+
+#define WOLFSSL_MAX_SNAME 40
+struct WOLFSSL_ASN1_OBJECT {
+    void*  heap;
+    unsigned char* obj;
+    /* sName is short name i.e sha256 rather than oid (null terminated) */
+    char   sName[WOLFSSL_MAX_SNAME];
+    int    type; /* oid */
+    int    grp;  /* type of OID, i.e. oidCertPolicyType */
+    unsigned int  objSz;
+    unsigned char dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */
+    struct d { /* derefrenced */
+        WOLFSSL_ASN1_STRING  ia5_internal;
+        WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */
+        WOLFSSL_ASN1_STRING* dNSName;
+        WOLFSSL_ASN1_STRING* iPAddress;
+    } d;
+};
+
+struct WOLFSSL_EVP_PKEY {
+    void* heap;
+    int type;         /* openssh dereference */
+    int save_type;    /* openssh dereference */
+    int pkey_sz;
+    union {
+        char* ptr; /* der format of key / or raw for NTRU */
+    } pkey;
+    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
+    #ifndef NO_RSA
+        WOLFSSL_RSA* rsa;
+        byte      ownRsa; /* if struct owns RSA and should free it */
+    #endif
+    #ifdef HAVE_ECC
+        WOLFSSL_EC_KEY* ecc;
+        byte      ownEcc; /* if struct owns ECC and should free it */
+    #endif
+    WC_RNG rng;
+    #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+    #ifdef HAVE_ECC
+        int pkey_curve;
+    #endif
+};
+typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO;
+
+#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */
+typedef struct WOLFSSL_EVP_PKEY     WOLFSSL_EVP_PKEY;
+typedef char   WOLFSSL_EVP_MD;
+#define WOLFSSL_EVP_TYPE_DEFINED
+#endif
+
+#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */
+
+
+enum BIO_TYPE {
+    WOLFSSL_BIO_BUFFER = 1,
+    WOLFSSL_BIO_SOCKET = 2,
+    WOLFSSL_BIO_SSL    = 3,
+    WOLFSSL_BIO_MEMORY = 4,
+    WOLFSSL_BIO_BIO    = 5,
+    WOLFSSL_BIO_FILE   = 6,
+    WOLFSSL_BIO_BASE64 = 7
+};
+
+enum BIO_FLAGS {
+    WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01,
+    WOLFSSL_BIO_FLAG_READ         = 0x02,
+    WOLFSSL_BIO_FLAG_WRITE        = 0x04,
+    WOLFSSL_BIO_FLAG_IO_SPECIAL   = 0x08,
+    WOLFSSL_BIO_FLAG_RETRY        = 0x10
+};
+
+typedef struct WOLFSSL_BUF_MEM {
+    char*  data;   /* dereferenced */
+    size_t length; /* current length */
+    size_t max;    /* maximum length */
+} WOLFSSL_BUF_MEM;
+
+typedef struct WOLFSSL_COMP_METHOD {
+    int type;            /* stunnel dereference */
+} WOLFSSL_COMP_METHOD;
+
+struct WOLFSSL_X509_LOOKUP_METHOD {
+    int type;
+};
+
+struct WOLFSSL_X509_LOOKUP {
+    WOLFSSL_X509_STORE *store;
+};
+
+struct WOLFSSL_X509_STORE {
+    int                   cache;          /* stunnel dereference */
+    WOLFSSL_CERT_MANAGER* cm;
+    WOLFSSL_X509_LOOKUP   lookup;
+#ifdef OPENSSL_EXTRA
+    int                   isDynamic;
+#endif
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
+    WOLFSSL_X509_CRL *crl;
+#endif
+};
+
+#ifdef OPENSSL_EXTRA
+#define WOLFSSL_USE_CHECK_TIME 0x2
+#define WOLFSSL_NO_CHECK_TIME  0x200000
+#define WOLFSSL_NO_WILDCARDS   0x4
+struct WOLFSSL_X509_VERIFY_PARAM {
+    time_t  check_time;
+    unsigned long flags;
+};
+#endif
+
+typedef struct WOLFSSL_ALERT {
+    int code;
+    int level;
+} WOLFSSL_ALERT;
+
+typedef struct WOLFSSL_ALERT_HISTORY {
+    WOLFSSL_ALERT last_rx;
+    WOLFSSL_ALERT last_tx;
+} WOLFSSL_ALERT_HISTORY;
+
+typedef struct WOLFSSL_X509_REVOKED {
+    WOLFSSL_ASN1_INTEGER* serialNumber;          /* stunnel dereference */
+} WOLFSSL_X509_REVOKED;
+
+
+typedef struct WOLFSSL_X509_OBJECT {
+    union {
+        char* ptr;
+        WOLFSSL_X509 *x509;
+        WOLFSSL_X509_CRL* crl;           /* stunnel dereference */
+    } data;
+} WOLFSSL_X509_OBJECT;
+
+typedef struct WOLFSSL_BUFFER_INFO {
+    unsigned char* buffer;
+    unsigned int length;
+} WOLFSSL_BUFFER_INFO;
+
+typedef struct WOLFSSL_X509_STORE_CTX {
+    WOLFSSL_X509_STORE* store;    /* Store full of a CA cert chain */
+    WOLFSSL_X509* current_cert;   /* stunnel dereference */
+    WOLFSSL_X509* current_issuer; /* asio dereference */
+    WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */
+    WOLFSSL_STACK* chain;
+#ifdef OPENSSL_EXTRA
+    WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */
+#endif
+    char* domain;                /* subject CN domain name */
+    void* ex_data;               /* external data, for fortress build */
+    void* userCtx;               /* user ctx */
+    int   error;                 /* current error */
+    int   error_depth;           /* index of cert depth for this error */
+    int   discardSessionCerts;   /* so verify callback can flag for discard */
+    int   totalCerts;            /* number of peer cert buffers */
+    WOLFSSL_BUFFER_INFO* certs;  /* peer certs */
+    WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */
+} WOLFSSL_X509_STORE_CTX;
+
+typedef char* WOLFSSL_STRING;
+
+/* Valid Alert types from page 16/17
+ * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c
+ */
+enum AlertDescription {
+    close_notify                    =   0,
+    unexpected_message              =  10,
+    bad_record_mac                  =  20,
+    record_overflow                 =  22,
+    decompression_failure           =  30,
+    handshake_failure               =  40,
+    no_certificate                  =  41,
+    bad_certificate                 =  42,
+    unsupported_certificate         =  43,
+    certificate_revoked             =  44,
+    certificate_expired             =  45,
+    certificate_unknown             =  46,
+    illegal_parameter               =  47,
+    decode_error                    =  50,
+    decrypt_error                   =  51,
+    #ifdef WOLFSSL_MYSQL_COMPATIBLE
+    /* catch name conflict for enum protocol with MYSQL build */
+    wc_protocol_version             =  70,
+    #else
+    protocol_version                =  70,
+    #endif
+    no_renegotiation                = 100,
+    unsupported_extension           = 110, /**< RFC 5246, section 7.2.2 */
+    unrecognized_name               = 112, /**< RFC 6066, section 3 */
+    bad_certificate_status_response = 113, /**< RFC 6066, section 8 */
+    unknown_psk_identity            = 115, /**< RFC 4279, section 2 */
+    no_application_protocol         = 120
+};
+
+
+enum AlertLevel {
+    alert_warning = 1,
+    alert_fatal   = 2
+};
+
+/* Maximum master key length (SECRET_LEN) */
+#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48
+/* Maximum number of groups that can be set */
+#define WOLFSSL_MAX_GROUP_COUNT       10
+
+typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap);
+#ifdef WOLFSSL_TLS13
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap);
+#endif
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap);
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap);
+#endif
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD* wolfTLSv1_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void);
+WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
+#ifdef WOLFSSL_TLS13
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void);
+#endif
+
+#ifdef WOLFSSL_DTLS
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void);
+    WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void);
+#endif
+
+#ifdef HAVE_POLY1305
+    WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int);
+#endif
+
+#ifdef WOLFSSL_SESSION_EXPORT
+#ifdef WOLFSSL_DTLS
+
+#ifndef WOLFSSL_DTLS_EXPORT_TYPES
+typedef int (*wc_dtls_export)(WOLFSSL* ssl,
+                   unsigned char* exportBuffer, unsigned int sz, void* userCtx);
+#define WOLFSSL_DTLS_EXPORT_TYPES
+#endif /* WOLFSSL_DTLS_EXPORT_TYPES */
+
+WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf,
+                                                               unsigned int sz);
+WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
+                                                           wc_dtls_export func);
+WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
+WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf,
+                                                              unsigned int* sz);
+#endif /* WOLFSSL_DTLS */
+#endif /* WOLFSSL_SESSION_EXPORT */
+
+#ifdef WOLFSSL_STATIC_MEMORY
+#ifndef WOLFSSL_MEM_GUARD
+#define WOLFSSL_MEM_GUARD
+    typedef struct WOLFSSL_MEM_STATS      WOLFSSL_MEM_STATS;
+    typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS;
+#endif
+WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx,
+                                            wolfSSL_method_func method,
+                                            unsigned char* buf, unsigned int sz,
+                                            int flag, int max);
+WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx,
+                                                 WOLFSSL_MEM_STATS* mem_stats);
+WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl,
+                                            WOLFSSL_MEM_CONN_STATS* mem_stats);
+#endif
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+
+WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);
+WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int);
+WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*,
+                                                const char*);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int);
+#endif
+WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *,
+                                                     const char *file);
+WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *,
+                                                  const char *file, int format);
+WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int);
+
+WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl);
+WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx);
+WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth);
+WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
+WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int);
+WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, const char *file);
+WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*,
+                                                  const char *file, int format);
+WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
+
+#ifdef WOLFSSL_DER_LOAD
+    WOLFSSL_API int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX*,
+                                                    const char*, int);
+#endif
+
+#ifdef HAVE_NTRU
+    WOLFSSL_API int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX*, const char*);
+    /* load NTRU private key blob */
+#endif
+
+#endif /* !NO_FILESYSTEM && !NO_CERTS */
+
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
+WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_is_server(WOLFSSL*);
+WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_set_fd (WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_write_fd (WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_read_fd (WOLFSSL*, int);
+WOLFSSL_API char* wolfSSL_get_cipher_list(int priority);
+WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority);
+WOLFSSL_API int  wolfSSL_get_ciphers(char*, int);
+WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
+WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, 
+    const unsigned char);
+WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
+    int len);
+WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_get_fd(const WOLFSSL*);
+/* please see note at top of README if you get an error from connect */
+WOLFSSL_API int  wolfSSL_connect(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_write(WOLFSSL*, const void*, int);
+WOLFSSL_API int  wolfSSL_read(WOLFSSL*, void*, int);
+WOLFSSL_API int  wolfSSL_peek(WOLFSSL*, void*, int);
+WOLFSSL_API int  wolfSSL_accept(WOLFSSL*);
+#ifdef WOLFSSL_TLS13
+WOLFSSL_API int  wolfSSL_send_hrr_cookie(WOLFSSL* ssl,
+    const unsigned char* secret, unsigned int secretSz);
+WOLFSSL_API int  wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_no_dhe_psk(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_update_keys(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);
+WOLFSSL_API int  wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_request_certificate(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_preferred_group(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups,
+                                        int count);
+WOLFSSL_API int  wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count);
+
+WOLFSSL_API int  wolfSSL_connect_TLSv13(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_accept_TLSv13(WOLFSSL*);
+
+#ifdef WOLFSSL_EARLY_DATA
+WOLFSSL_API int  wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx,
+                                                unsigned int sz);
+WOLFSSL_API int  wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz);
+WOLFSSL_API int  wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*);
+WOLFSSL_API int  wolfSSL_read_early_data(WOLFSSL*, void*, int, int*);
+#endif
+#endif
+WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*);
+WOLFSSL_API void wolfSSL_free(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_shutdown(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_send(WOLFSSL*, const void*, int sz, int flags);
+WOLFSSL_API int  wolfSSL_recv(WOLFSSL*, void*, int sz, int flags);
+
+WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int);
+WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int);
+
+WOLFSSL_API int  wolfSSL_get_error(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *);
+
+WOLFSSL_API int  wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*);
+WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*);
+WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long);
+WOLFSSL_API int  wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int);
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)
+WOLFSSL_API int  wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t,
+                     WOLFSSL_BIO**, size_t);
+
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**);
+WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*, 
+                                           int, const unsigned char*);
+WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**);
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO */
+
+#ifdef SESSION_INDEX
+WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session);
+#endif /* SESSION_INDEX */
+
+#if defined(SESSION_INDEX) && defined(SESSION_CERTS)
+WOLFSSL_API
+    WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session);
+#endif /* SESSION_INDEX && SESSION_CERTS */
+
+typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*);
+#ifdef OPENSSL_EXTRA
+typedef void (CallbackInfoState)(const WOLFSSL*, int, int);
+
+typedef struct WOLFSSL_CRYPTO_EX_DATA {
+    WOLFSSL_STACK* data;
+} WOLFSSL_CRYPTO_EX_DATA;
+
+typedef int  (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr,
+        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
+typedef int  (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out,
+        WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg);
+typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr,
+        WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg);
+
+WOLFSSL_API int  wolfSSL_get_ex_new_index(long argValue, void* arg,
+        WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b,
+        WOLFSSL_CRYPTO_EX_free* c);
+#endif
+
+WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int,
+                                      VerifyCallback verify_callback);
+WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback);
+WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*);
+
+WOLFSSL_API int  wolfSSL_pending(WOLFSSL*);
+
+WOLFSSL_API void wolfSSL_load_error_strings(void);
+WOLFSSL_API int  wolfSSL_library_init(void);
+WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, long);
+
+#ifdef HAVE_SECRET_CALLBACK
+typedef int (*SessionSecretCb)(WOLFSSL* ssl,
+                                        void* secret, int* secretSz, void* ctx);
+WOLFSSL_API int  wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, void*);
+#endif /* HAVE_SECRET_CALLBACK */
+
+/* session cache persistence */
+WOLFSSL_API int  wolfSSL_save_session_cache(const char*);
+WOLFSSL_API int  wolfSSL_restore_session_cache(const char*);
+WOLFSSL_API int  wolfSSL_memsave_session_cache(void*, int);
+WOLFSSL_API int  wolfSSL_memrestore_session_cache(const void*, int);
+WOLFSSL_API int  wolfSSL_get_session_cache_memsize(void);
+
+/* certificate cache persistence, uses ctx since certs are per ctx */
+WOLFSSL_API int  wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX*, void*, int, int*);
+WOLFSSL_API int  wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX*, const void*, int);
+WOLFSSL_API int  wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX*);
+
+/* only supports full name from cipher_name[] delimited by : */
+WOLFSSL_API int  wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*);
+WOLFSSL_API int  wolfSSL_set_cipher_list(WOLFSSL*, const char*);
+
+/* Nonblocking DTLS helper functions */
+WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_dtls_get_using_nonblock(WOLFSSL*);
+#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock
+#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock
+    /* The old names are deprecated. */
+WOLFSSL_API int  wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int);
+WOLFSSL_API int  wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int);
+WOLFSSL_API int  wolfSSL_dtls_got_timeout(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_dtls(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int);
+WOLFSSL_API int  wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*);
+
+WOLFSSL_API int  wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_dtls_set_sctp(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int  wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short);
+
+WOLFSSL_API int  wolfSSL_dtls_get_drop_stats(WOLFSSL*,
+                                             unsigned int*, unsigned int*);
+WOLFSSL_API int  wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int  wolfSSL_set_secret(WOLFSSL*, unsigned short,
+                     const unsigned char*, unsigned int,
+                     const unsigned char*, const unsigned char*,
+                     const unsigned char*);
+WOLFSSL_API int  wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int);
+WOLFSSL_API int  wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int);
+WOLFSSL_API int  wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short);
+WOLFSSL_API int  wolfSSL_mcast_get_max_peers(void);
+typedef int (*CallbackMcastHighwater)(unsigned short peerId,
+                                      unsigned int maxSeq,
+                                      unsigned int curSeq, void* ctx);
+WOLFSSL_API int  wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*,
+                                                    unsigned int,
+                                                    unsigned int,
+                                                    unsigned int,
+                                                    CallbackMcastHighwater);
+WOLFSSL_API int  wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*);
+
+WOLFSSL_API int   wolfSSL_ERR_GET_REASON(unsigned long err);
+WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*);
+WOLFSSL_API void  wolfSSL_ERR_error_string_n(unsigned long e, char* buf,
+                                           unsigned long sz);
+WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long);
+
+/* extras */
+
+#ifndef WOLF_STACK_OF
+    #define WOLF_STACK_OF(x) WOLFSSL_STACK
+#endif
+#ifndef DECLARE_STACK_OF
+    #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x);
+#endif
+
+WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
+                                                            WOLFSSL_X509* x509);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
+WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value(
+        WOLFSSL_STACK* sk, int i);
+WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk);
+WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
+        void f (WOLFSSL_ASN1_OBJECT*));
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void);
+WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj);
+WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk,
+                                                      WOLFSSL_ASN1_OBJECT* obj);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop(
+                                            WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
+WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk);
+WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in);
+
+WOLFSSL_API int  wolfSSL_set_ex_data(WOLFSSL*, int, void*);
+WOLFSSL_API int  wolfSSL_get_shutdown(const WOLFSSL*);
+WOLFSSL_API int  wolfSSL_set_rfd(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_wfd(WOLFSSL*, int);
+WOLFSSL_API void wolfSSL_set_shutdown(WOLFSSL*, int);
+WOLFSSL_API int  wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*,
+                                           unsigned int);
+WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*);
+WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_session_reused(WOLFSSL*);
+WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session);
+WOLFSSL_API int  wolfSSL_is_init_finished(WOLFSSL*);
+
+WOLFSSL_API const char*  wolfSSL_get_version(WOLFSSL*);
+WOLFSSL_API int  wolfSSL_get_current_cipher_suite(WOLFSSL* ssl);
+WOLFSSL_API WOLFSSL_CIPHER*  wolfSSL_get_current_cipher(WOLFSSL*);
+WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int);
+WOLFSSL_API const char*  wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher);
+WOLFSSL_API const char*  wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session);
+WOLFSSL_API const char*  wolfSSL_get_cipher(WOLFSSL*);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl);
+                           /* what's ref count */
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void);
+
+WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port,
+                                     char** path, int* ssl);
+
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void);
+WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void);
+
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
+WOLFSSL_API int  wolfSSL_BIO_free(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_free_all(WOLFSSL_BIO*);
+WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type);
+WOLFSSL_API int  wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int);
+WOLFSSL_API int  wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_flush(WOLFSSL_BIO*);
+WOLFSSL_API int  wolfSSL_BIO_pending(WOLFSSL_BIO*);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void);
+WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size);
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void);
+WOLFSSL_API WOLFSSL_BIO*        wolfSSL_BIO_new_socket(int sfd, int flag);
+WOLFSSL_API int         wolfSSL_BIO_eof(WOLFSSL_BIO*);
+
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void);
+WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void);
+WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int);
+
+WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p);
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len);
+
+
+WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag);
+WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag);
+WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr);
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void);
+#endif
+
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void);
+WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void);
+
+WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg);
+WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg);
+
+WOLFSSL_API int  wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size);
+WOLFSSL_API int  wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2);
+WOLFSSL_API int  wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b);
+WOLFSSL_API int  wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf);
+WOLFSSL_API int  wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num);
+WOLFSSL_API int  wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num);
+WOLFSSL_API int  wolfSSL_BIO_reset(WOLFSSL_BIO *bio);
+
+WOLFSSL_API int  wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs);
+WOLFSSL_API int  wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name);
+WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v);
+WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m);
+
+WOLFSSL_API void        wolfSSL_RAND_screen(void);
+WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long);
+WOLFSSL_API int         wolfSSL_RAND_write_file(const char*);
+WOLFSSL_API int         wolfSSL_RAND_load_file(const char*, long);
+WOLFSSL_API int         wolfSSL_RAND_egd(const char*);
+WOLFSSL_API int         wolfSSL_RAND_seed(const void*, int);
+WOLFSSL_API void        wolfSSL_RAND_Cleanup(void);
+WOLFSSL_API void        wolfSSL_RAND_add(const void*, int, double);
+WOLFSSL_API int         wolfSSL_RAND_poll(void);
+
+WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void);
+WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void);
+WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*);
+
+WOLFSSL_API unsigned long wolfSSL_thread_id(void);
+WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void));
+WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*,
+                                                      int));
+WOLFSSL_API void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)
+                                                   (const char*, int));
+WOLFSSL_API void wolfSSL_set_dynlock_lock_callback(void (*f)(int,
+                                      WOLFSSL_dynlock_value*, const char*, int));
+WOLFSSL_API void wolfSSL_set_dynlock_destroy_callback(void (*f)
+                                     (WOLFSSL_dynlock_value*, const char*, int));
+WOLFSSL_API int  wolfSSL_num_locks(void);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
+                                                        WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API int   wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*);
+
+WOLFSSL_API void  wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
+                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb);
+WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n,
+                                                           unsigned char** out);
+WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
+WOLFSSL_API char*       wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int);
+WOLFSSL_API WOLFSSL_X509_NAME*  wolfSSL_X509_get_issuer_name(WOLFSSL_X509*);
+WOLFSSL_API WOLFSSL_X509_NAME*  wolfSSL_X509_get_subject_name(WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int);
+WOLFSSL_API int  wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int);
+WOLFSSL_API int  wolfSSL_X509_get_isCA(WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509*);
+WOLFSSL_API unsigned int wolfSSL_X509_get_pathLength(WOLFSSL_X509*);
+WOLFSSL_API unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509*);
+WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID(
+                                            WOLFSSL_X509*, unsigned char*, int*);
+WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID(
+                                            WOLFSSL_X509*, unsigned char*, int*);
+WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*);
+WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID(
+                                            WOLFSSL_X509_NAME*, int, char*, int);
+WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID(
+                                           WOLFSSL_X509_NAME*, int, int);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void);
+WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type);
+WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1);
+WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1,
+                                                  const void* data, int dataSz);
+WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*);
+WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*);
+WOLFSSL_API int         wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long);
+WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*);
+
+WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long);
+WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*,
+                                            long);
+WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void);
+WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void);
+
+WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE*,
+                                                    WOLFSSL_X509_LOOKUP_METHOD*);
+WOLFSSL_API WOLFSSL_X509_STORE*  wolfSSL_X509_STORE_new(void);
+WOLFSSL_API void         wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*);
+WOLFSSL_API int          wolfSSL_X509_STORE_add_cert(
+                                              WOLFSSL_X509_STORE*, WOLFSSL_X509*);
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(
+                                                   WOLFSSL_X509_STORE_CTX* ctx);
+WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store,
+                                                            unsigned long flag);
+WOLFSSL_API int          wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*);
+WOLFSSL_API int          wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*,
+                                   int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*);
+WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void);
+WOLFSSL_API int  wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*,
+                      WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*);
+
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*);
+
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*);
+WOLFSSL_API int       wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*);
+WOLFSSL_API void      wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*);
+WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(
+        WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+                                         WOLFSSL_EVP_PKEY** out);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key,
+        unsigned char** in, long inSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type,
+        WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key,
+        unsigned char** in, long inSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap);
+WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void);
+WOLFSSL_API int       wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*);
+WOLFSSL_API int       wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*);
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API void      wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*,
+                                                      unsigned long flags,
+                                                      time_t t);
+#endif
+WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*);
+WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
+                                                      WOLFSSL_X509_REVOKED*,int);
+WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*);
+WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*);
+WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void);
+
+WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*);
+
+WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t,
+                                                            char* buf, int len);
+WOLFSSL_API int  wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*,
+                                       const WOLFSSL_ASN1_INTEGER*);
+WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*);
+
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai,
+                                       WOLFSSL_BIGNUM *bn);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*);
+WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t,
+                                                     int, long);
+#endif
+
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list(
+        const WOLFSSL_CTX *s);
+WOLFSSL_API void  wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*,
+                                               WOLF_STACK_OF(WOLFSSL_X509_NAME)*);
+WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int);
+WOLFSSL_API int   wolfSSL_get_ex_data_X509_STORE_CTX_idx(void);
+WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(
+                                           WOLFSSL_X509_STORE_CTX* ctx, int er);
+WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int);
+
+WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*,
+                                                          void* userdata);
+WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*,
+                                                   pem_password_cb*);
+WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx);
+WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx);
+
+WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*,
+                          void (*)(const WOLFSSL* ssl, int type, int val));
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void);
+WOLFSSL_API int           wolfSSL_GET_REASON(int);
+
+WOLFSSL_API const char* wolfSSL_alert_type_string_long(int);
+WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int);
+WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*);
+
+WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long,
+                                               void(*)(int, int, void*), void*);
+WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, 
+                                            const unsigned char **pp, long len);
+WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**, 
+                                            const unsigned char**, long);
+WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp);
+WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp);
+WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *,
+                                           WOLFSSL_RSA *(*)(WOLFSSL *, int, int));
+
+WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key);
+
+WOLFSSL_API long wolfSSL_CTX_sess_accept(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_hits(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*);
+WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*);
+
+WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long);
+WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*);
+
+WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v);
+WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg);
+WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(
+        WOLFSSL_CTX*, void* arg);
+WOLFSSL_API int  wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*);
+WOLFSSL_API int  wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*);
+WOLFSSL_API int  wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*);
+
+WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op);
+WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s);
+WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s,  long op);
+WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s);
+WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s);
+WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh);
+WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type);
+WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp);
+WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len);
+
+WOLFSSL_API void wolfSSL_CONF_modules_unload(int all);
+WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg);
+WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl);
+
+#define WOLFSSL_DEFAULT_CIPHER_LIST ""   /* default all */
+
+enum {
+    WOLFSSL_OCSP_URL_OVERRIDE = 1,
+    WOLFSSL_OCSP_NO_NONCE     = 2,
+    WOLFSSL_OCSP_CHECKALL     = 4,
+
+    WOLFSSL_CRL_CHECKALL = 1,
+    WOLFSSL_CRL_CHECK    = 27,
+};
+
+#ifdef OPENSSL_EXTRA
+/* seperated out from other enums because of size */
+enum {
+    SSL_OP_MICROSOFT_SESS_ID_BUG                  = 0x00000001,
+    SSL_OP_NETSCAPE_CHALLENGE_BUG                 = 0x00000002,
+    SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG       = 0x00000004,
+    SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG            = 0x00000008,
+    SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER             = 0x00000010,
+    SSL_OP_MSIE_SSLV2_RSA_PADDING                 = 0x00000020,
+    SSL_OP_SSLEAY_080_CLIENT_DH_BUG               = 0x00000040,
+    SSL_OP_TLS_D5_BUG                             = 0x00000080,
+    SSL_OP_TLS_BLOCK_PADDING_BUG                  = 0x00000100,
+    SSL_OP_TLS_ROLLBACK_BUG                       = 0x00000200,
+    SSL_OP_ALL                                    = 0x00000400,
+    SSL_OP_EPHEMERAL_RSA                          = 0x00000800,
+    SSL_OP_NO_SSLv3                               = 0x00001000,
+    SSL_OP_NO_TLSv1                               = 0x00002000,
+    SSL_OP_PKCS1_CHECK_1                          = 0x00004000,
+    SSL_OP_PKCS1_CHECK_2                          = 0x00008000,
+    SSL_OP_NETSCAPE_CA_DN_BUG                     = 0x00010000,
+    SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG        = 0x00020000,
+    SSL_OP_SINGLE_DH_USE                          = 0x00040000,
+    SSL_OP_NO_TICKET                              = 0x00080000,
+    SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS            = 0x00100000,
+    SSL_OP_NO_QUERY_MTU                           = 0x00200000,
+    SSL_OP_COOKIE_EXCHANGE                        = 0x00400000,
+    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000,
+    SSL_OP_SINGLE_ECDH_USE                        = 0x01000000,
+    SSL_OP_CIPHER_SERVER_PREFERENCE               = 0x02000000,
+    SSL_OP_NO_TLSv1_1                             = 0x04000000,
+    SSL_OP_NO_TLSv1_2                             = 0x08000000,
+    SSL_OP_NO_COMPRESSION                         = 0x10000000,
+    SSL_OP_NO_TLSv1_3                             = 0x20000000,
+};
+
+enum {
+#ifdef HAVE_OCSP
+    /* OCSP Flags */
+    OCSP_NOCERTS     = 1,
+    OCSP_NOINTERN    = 2,
+    OCSP_NOSIGS      = 4,
+    OCSP_NOCHAIN     = 8,
+    OCSP_NOVERIFY    = 16,
+    OCSP_NOEXPLICIT  = 32,
+    OCSP_NOCASIGN    = 64,
+    OCSP_NODELEGATED = 128,
+    OCSP_NOCHECKS    = 256,
+    OCSP_TRUSTOTHER  = 512,
+    OCSP_RESPID_KEY  = 1024,
+    OCSP_NOTIME      = 2048,
+
+    /* OCSP Types */
+    OCSP_CERTID   = 2,
+    OCSP_REQUEST  = 4,
+    OCSP_RESPONSE = 8,
+    OCSP_BASICRESP = 16,
+#endif
+
+    ASN1_GENERALIZEDTIME = 4,
+    SSL_MAX_SSL_SESSION_ID_LENGTH = 32,
+
+    EVP_R_BAD_DECRYPT = 2,
+
+    SSL_ST_CONNECT = 0x1000,
+    SSL_ST_ACCEPT  = 0x2000,
+    SSL_ST_MASK    = 0x0FFF,
+
+    SSL_CB_LOOP = 0x01,
+    SSL_CB_EXIT = 0x02,
+    SSL_CB_READ = 0x04,
+    SSL_CB_WRITE = 0x08,
+    SSL_CB_HANDSHAKE_START = 0x10,
+    SSL_CB_HANDSHAKE_DONE = 0x20,
+    SSL_CB_ALERT = 0x4000,
+    SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ),
+    SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE),
+    SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP),
+    SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT),
+    SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP),
+    SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT),
+	SSL_CB_MODE_READ = 1,
+	SSL_CB_MODE_WRITE = 2,
+
+    SSL_MODE_ENABLE_PARTIAL_WRITE = 2,
+
+    BIO_FLAGS_BASE64_NO_NL = 1,
+    BIO_CLOSE   = 1,
+    BIO_NOCLOSE = 0,
+
+    NID_undef = 0,
+
+    X509_FILETYPE_PEM = 8,
+    X509_LU_X509      = 9,
+    X509_LU_CRL       = 12,
+
+    X509_V_OK                                    = 0,
+    X509_V_ERR_CRL_SIGNATURE_FAILURE             = 13,
+    X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD    = 14,
+    X509_V_ERR_CRL_HAS_EXPIRED                   = 15,
+    X509_V_ERR_CERT_REVOKED                      = 16,
+    X509_V_ERR_CERT_CHAIN_TOO_LONG               = 17,
+    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT         = 18,
+    X509_V_ERR_CERT_NOT_YET_VALID                = 19,
+    X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD    = 20,
+    X509_V_ERR_CERT_HAS_EXPIRED                  = 21,
+    X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD     = 22,
+    X509_V_ERR_CERT_REJECTED                     = 23,
+    /* Required for Nginx  */
+    X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT       = 24,
+    X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN         = 25,
+    X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26,
+    X509_V_ERR_CERT_UNTRUSTED                    = 27,
+    X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE   = 28,
+    X509_V_ERR_SUBJECT_ISSUER_MISMATCH           = 29,
+    /* additional X509_V_ERR_* enums not used in wolfSSL */
+    X509_V_ERR_UNABLE_TO_GET_CRL,
+    X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
+    X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
+    X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
+    X509_V_ERR_CERT_SIGNATURE_FAILURE,
+    X509_V_ERR_CRL_NOT_YET_VALID,
+    X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
+    X509_V_ERR_OUT_OF_MEM,
+    X509_V_ERR_INVALID_CA,
+    X509_V_ERR_PATH_LENGTH_EXCEEDED,
+    X509_V_ERR_INVALID_PURPOSE,
+    X509_V_ERR_AKID_SKID_MISMATCH,
+    X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
+    X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
+    X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
+    X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
+    X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
+    X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
+    X509_V_ERR_INVALID_NON_CA,
+    X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
+    X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
+    X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
+    X509_V_ERR_INVALID_EXTENSION,
+    X509_V_ERR_INVALID_POLICY_EXTENSION,
+    X509_V_ERR_NO_EXPLICIT_POLICY,
+    X509_V_ERR_UNNESTED_RESOURCE,
+
+    X509_R_CERT_ALREADY_IN_HASH_TABLE,
+
+    XN_FLAG_SPC_EQ  = (1 << 23),
+    XN_FLAG_ONELINE = 0,
+    XN_FLAG_RFC2253 = 1,
+
+    CRYPTO_LOCK = 1,
+    CRYPTO_NUM_LOCKS = 10,
+
+    ASN1_STRFLGS_ESC_MSB = 4
+};
+#endif
+
+/* extras end */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+/* wolfSSL extension, provide last error from SSL_get_error
+   since not using thread storage error queue */
+#include <stdio.h>
+WOLFSSL_API void  wolfSSL_ERR_print_errors_fp(XFILE, int err);
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp);
+#endif
+#endif
+
+
+#ifndef NO_OLD_SSL_NAMES
+    #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE
+    #define SSL_FAILURE WOLFSSL_FAILURE
+    #define SSL_SUCCESS WOLFSSL_SUCCESS
+    #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE
+
+    #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND
+    #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE
+    #define SSL_BAD_STAT WOLFSSL_BAD_STAT
+    #define SSL_BAD_PATH WOLFSSL_BAD_PATH
+    #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE
+    #define SSL_BAD_FILE WOLFSSL_BAD_FILE
+    #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED
+    #define SSL_UNKNOWN WOLFSSL_UNKNOWN
+    #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR
+
+    #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1
+    #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM
+    #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT
+    #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW
+
+    #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE
+    #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER
+    #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT
+    #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE
+    #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK
+
+    #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF
+    #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT
+    #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER
+    #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH
+    #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR
+    #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP
+    #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE
+    #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL
+
+    #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ
+    #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE
+    #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT
+    #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT
+    #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL
+    #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP
+    #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN
+    #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL
+
+    #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN
+    #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN
+    #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
+    #define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2
+
+    #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE
+    #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA
+    #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
+    #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE
+
+    #define PEM_BUFSIZE WOLF_PEM_BUFSIZE
+#endif
+
+enum { /* ssl Constants */
+    WOLFSSL_ERROR_NONE      =  0,   /* for most functions */
+    WOLFSSL_FAILURE         =  0,   /* for some functions */
+    WOLFSSL_SUCCESS         =  1,
+    WOLFSSL_SHUTDOWN_NOT_DONE =  2,  /* call wolfSSL_shutdown again to complete */
+
+    WOLFSSL_ALPN_NOT_FOUND  = -9,
+    WOLFSSL_BAD_CERTTYPE    = -8,
+    WOLFSSL_BAD_STAT        = -7,
+    WOLFSSL_BAD_PATH        = -6,
+    WOLFSSL_BAD_FILETYPE    = -5,
+    WOLFSSL_BAD_FILE        = -4,
+    WOLFSSL_NOT_IMPLEMENTED = -3,
+    WOLFSSL_UNKNOWN         = -2,
+    WOLFSSL_FATAL_ERROR     = -1,
+
+    WOLFSSL_FILETYPE_ASN1    = 2,
+    WOLFSSL_FILETYPE_PEM     = 1,
+    WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */
+    WOLFSSL_FILETYPE_RAW     = 3, /* NTRU raw key blob */
+
+    WOLFSSL_VERIFY_NONE                 = 0,
+    WOLFSSL_VERIFY_PEER                 = 1,
+    WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+    WOLFSSL_VERIFY_CLIENT_ONCE          = 4,
+    WOLFSSL_VERIFY_FAIL_EXCEPT_PSK      = 8,
+
+    WOLFSSL_SESS_CACHE_OFF                = 0x0000,
+    WOLFSSL_SESS_CACHE_CLIENT             = 0x0001,
+    WOLFSSL_SESS_CACHE_SERVER             = 0x0002,
+    WOLFSSL_SESS_CACHE_BOTH               = 0x0003,
+    WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR      = 0x0008,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE  = 0x0200,
+    WOLFSSL_SESS_CACHE_NO_INTERNAL        = 0x0300,
+
+    WOLFSSL_ERROR_WANT_READ        =  2,
+    WOLFSSL_ERROR_WANT_WRITE       =  3,
+    WOLFSSL_ERROR_WANT_CONNECT     =  7,
+    WOLFSSL_ERROR_WANT_ACCEPT      =  8,
+    WOLFSSL_ERROR_SYSCALL          =  5,
+    WOLFSSL_ERROR_WANT_X509_LOOKUP = 83,
+    WOLFSSL_ERROR_ZERO_RETURN      =  6,
+    WOLFSSL_ERROR_SSL              = 85,
+
+    WOLFSSL_SENT_SHUTDOWN     = 1,
+    WOLFSSL_RECEIVED_SHUTDOWN = 2,
+    WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4,
+    WOLFSSL_OP_NO_SSLv2       = 8,
+
+    WOLFSSL_R_SSL_HANDSHAKE_FAILURE           = 101,
+    WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA          = 102,
+    WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103,
+    WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE     = 104,
+
+    WOLF_PEM_BUFSIZE = 1024
+};
+
+#ifndef NO_PSK
+    typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*,
+                                    unsigned int, unsigned char*, unsigned int);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*,
+                                                    wc_psk_client_callback);
+    WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*,
+                                                    wc_psk_client_callback);
+
+    WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*);
+    WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*);
+
+    WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*);
+    WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*);
+
+    typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*,
+                          unsigned char*, unsigned int);
+    WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*,
+                                                    wc_psk_server_callback);
+    WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*,
+                                                    wc_psk_server_callback);
+
+    #define PSK_TYPES_DEFINED
+#endif /* NO_PSK */
+
+
+#ifdef HAVE_ANON
+    WOLFSSL_API int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX*);
+#endif /* HAVE_ANON */
+
+
+/* extra begins */
+#ifdef OPENSSL_EXTRA
+enum {  /* ERR Constants */
+    ERR_TXT_STRING = 1
+};
+
+/* bio misc */
+enum {
+    WOLFSSL_BIO_ERROR = -1,
+    WOLFSSL_BIO_UNSET = -2,
+    WOLFSSL_BIO_SIZE  = 17000 /* default BIO write size if not set */
+};
+#endif
+
+WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err,
+                                       const char* file, int line);
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*);
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*,
+                                                 const char**, int *);
+
+WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void);
+WOLFSSL_API void          wolfSSL_ERR_clear_error(void);
+
+
+WOLFSSL_API int  wolfSSL_RAND_status(void);
+WOLFSSL_API int  wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num);
+WOLFSSL_API int  wolfSSL_RAND_bytes(unsigned char* buf, int num);
+WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void);
+WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long);
+WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx);
+WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long);
+
+#ifndef NO_CERTS
+  WOLFSSL_API int  wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*);
+#endif /* !NO_CERTS */
+
+WOLFSSL_API void wolfSSL_ERR_free_strings(void);
+WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long);
+WOLFSSL_API int  wolfSSL_clear(WOLFSSL* ssl);
+WOLFSSL_API int  wolfSSL_state(WOLFSSL* ssl);
+
+WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void);
+WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode);
+WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx);
+WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m);
+WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl);
+
+
+WOLFSSL_API int  wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*);
+WOLFSSL_API int  wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*,
+                                            const unsigned char*, unsigned int);
+WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_want_read(WOLFSSL*);
+WOLFSSL_API int wolfSSL_want_write(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...);
+WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*,
+                                         const WOLFSSL_ASN1_UTCTIME*);
+WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*,
+                                         const WOLFSSL_ASN1_GENERALIZEDTIME*);
+WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*);
+WOLFSSL_API int   wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*);
+WOLFSSL_API void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*, int);
+
+/* stunnel 4.28 needs */
+WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int);
+WOLFSSL_API int   wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*);
+WOLFSSL_API void  wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*,
+                       WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*));
+WOLFSSL_API void  wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*,
+                                            int (*f)(WOLFSSL*, WOLFSSL_SESSION*));
+WOLFSSL_API void  wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX*,
+                                       void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*));
+
+WOLFSSL_API int          wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION*,unsigned char**);
+WOLFSSL_API WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION**,
+                                                   const unsigned char**, long);
+
+WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*);
+WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*);
+WOLFSSL_API int  wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*);
+
+/* extra ends */
+
+
+/* wolfSSL extensions */
+
+/* call before SSL_connect, if verifying will add name check to
+   date check and signature check */
+WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
+
+/* need to call once to load library (session cache) */
+WOLFSSL_API int wolfSSL_Init(void);
+/* call when done to cleanup/free session cache mutex / resources  */
+WOLFSSL_API int wolfSSL_Cleanup(void);
+
+/* which library version do we have */
+WOLFSSL_API const char* wolfSSL_lib_version(void);
+/* which library version do we have in hex */
+WOLFSSL_API unsigned int wolfSSL_lib_version_hex(void);
+
+/* do accept or connect depedning on side */
+WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl);
+/* turn on wolfSSL data compression */
+WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl);
+
+WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int);
+WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int);
+
+/* get wolfSSL peer X509_CHAIN */
+WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl);
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl);
+/* get wolfSSL alternate peer X509_CHAIN */
+WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl);
+#endif
+/* peer chain count */
+WOLFSSL_API int  wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain);
+/* index cert length */
+WOLFSSL_API int  wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN*, int idx);
+/* index cert */
+WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx);
+/* index cert in X509 */
+WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx);
+/* free X509 */
+#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509))
+WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*);
+/* get index cert in PEM */
+WOLFSSL_API int  wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx,
+                                unsigned char* buf, int inLen, int* outLen);
+WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(const WOLFSSL_SESSION* s);
+WOLFSSL_API int  wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*);
+WOLFSSL_API char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509*);
+WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*);
+WOLFSSL_API const unsigned char* wolfSSL_X509_notBefore(WOLFSSL_X509*);
+WOLFSSL_API const unsigned char* wolfSSL_X509_notAfter(WOLFSSL_X509*);
+WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*);
+
+WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*);
+
+WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509,
+        const unsigned char** in, int len);
+WOLFSSL_API WOLFSSL_X509*
+    wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len);
+WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out);
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl,
+                                                   const unsigned char *in, int len);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl);
+#endif
+WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl);
+
+#ifndef NO_FILESYSTEM
+    #ifndef NO_STDIO_FILESYSTEM
+    WOLFSSL_API WOLFSSL_X509*
+        wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file);
+    #endif
+WOLFSSL_API WOLFSSL_X509*
+    wolfSSL_X509_load_certificate_file(const char* fname, int format);
+#endif
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
+    const unsigned char* buf, int sz, int format);
+
+#ifdef WOLFSSL_SEP
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_device_type(WOLFSSL_X509*, unsigned char*, int*);
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_hw_type(WOLFSSL_X509*, unsigned char*, int*);
+    WOLFSSL_API unsigned char*
+           wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509*, unsigned char*, int*);
+#endif
+
+/* connect enough to get peer cert */
+WOLFSSL_API int  wolfSSL_connect_cert(WOLFSSL* ssl);
+
+
+
+/* PKCS12 compatibility */
+typedef struct WC_PKCS12 WC_PKCS12;
+WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio,
+                                       WC_PKCS12** pkcs12);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp,
+                                       WOLFSSL_X509_PKCS12** pkcs12);
+#endif
+WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
+     WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert,
+     WOLF_STACK_OF(WOLFSSL_X509)** ca);
+WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name,
+        WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert,
+        WOLF_STACK_OF(WOLFSSL_X509)* ca,
+        int keyNID, int certNID, int itt, int macItt, int keytype);
+WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void);
+
+
+
+#ifndef NO_DH
+/* server Diffie-Hellman parameters */
+WOLFSSL_API int  wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz,
+                                const unsigned char* g, int gSz);
+WOLFSSL_API int  wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz,
+                                       int format);
+#ifndef NO_FILESYSTEM
+    WOLFSSL_API int  wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format);
+#endif
+
+/* server ctx Diffie-Hellman parameters */
+WOLFSSL_API int  wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX*, const unsigned char* p,
+                                    int pSz, const unsigned char* g, int gSz);
+WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* b,
+                                           long sz, int format);
+
+#ifndef NO_FILESYSTEM
+    WOLFSSL_API int  wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f,
+                                             int format);
+#endif
+
+WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, unsigned short);
+WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, unsigned short);
+WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, unsigned short);
+WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*);
+#endif /* NO_DH */
+
+#ifndef NO_RSA
+WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short);
+WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short);
+#endif /* NO_RSA */
+
+#ifdef HAVE_ECC
+WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short);
+WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
+#endif /* NO_RSA */
+
+WOLFSSL_API int  wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short);
+WOLFSSL_API int  wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, unsigned short);
+
+/* keyblock size in bytes or -1 */
+/* need to call wolfSSL_KeepArrays before handshake to save keys */
+WOLFSSL_API int wolfSSL_get_keyblock_size(WOLFSSL*);
+WOLFSSL_API int wolfSSL_get_keys(WOLFSSL*,unsigned char** ms, unsigned int* msLen,
+                                       unsigned char** sr, unsigned int* srLen,
+                                       unsigned char** cr, unsigned int* crLen);
+
+/* Computes EAP-TLS and EAP-TTLS keying material from the master_secret. */
+WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len,
+                                                             const char* label);
+
+
+#ifndef _WIN32
+    #ifndef NO_WRITEV
+        #ifdef __PPU
+            #include <sys/types.h>
+            #include <sys/socket.h>
+        #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \
+              !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \
+              !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \
+              !defined(WOLFSSL_CHIBIOS)
+            #include <sys/uio.h>
+        #endif
+        /* allow writev style writing */
+        WOLFSSL_API int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov,
+                                     int iovcnt);
+    #endif
+#endif
+
+
+#ifndef NO_CERTS
+    /* SSL_CTX versions */
+    WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+#endif
+    WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*,
+                                                    const unsigned char*, long);
+
+    /* SSL versions */
+    WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*,
+                                               long, int);
+    WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*,
+                                               long, int);
+    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*,
+                                               const unsigned char*, long, int);
+    WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*,
+                                               const unsigned char*, long);
+    WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*);
+
+    #if defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT)
+        WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl);
+    #endif
+#endif
+
+WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*);
+WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*);
+
+
+#ifdef HAVE_FUZZER
+enum fuzzer_type {
+    FUZZ_HMAC      = 0,
+    FUZZ_ENCRYPT   = 1,
+    FUZZ_SIGNATURE = 2,
+    FUZZ_HASH      = 3,
+    FUZZ_HEAD      = 4
+};
+
+typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz,
+        int type, void* fuzzCtx);
+
+WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx);
+#endif
+
+
+WOLFSSL_API int   wolfSSL_DTLS_SetCookieSecret(WOLFSSL*,
+                                               const unsigned char*,
+                                               unsigned int);
+
+
+/* I/O Callback default errors */
+enum IOerrors {
+    WOLFSSL_CBIO_ERR_GENERAL    = -1,     /* general unexpected err */
+    WOLFSSL_CBIO_ERR_WANT_READ  = -2,     /* need to call read  again */
+    WOLFSSL_CBIO_ERR_WANT_WRITE = -2,     /* need to call write again */
+    WOLFSSL_CBIO_ERR_CONN_RST   = -3,     /* connection reset */
+    WOLFSSL_CBIO_ERR_ISR        = -4,     /* interrupt */
+    WOLFSSL_CBIO_ERR_CONN_CLOSE = -5,     /* connection closed or epipe */
+    WOLFSSL_CBIO_ERR_TIMEOUT    = -6      /* socket timeout */
+};
+
+
+/* CA cache callbacks */
+enum {
+    WOLFSSL_SSLV3    = 0,
+    WOLFSSL_TLSV1    = 1,
+    WOLFSSL_TLSV1_1  = 2,
+    WOLFSSL_TLSV1_2  = 3,
+    WOLFSSL_TLSV1_3  = 4,
+    WOLFSSL_USER_CA  = 1,          /* user added as trusted */
+    WOLFSSL_CHAIN_CA = 2           /* added to cache from trusted chain */
+};
+
+WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version);
+WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version);
+WOLFSSL_API int wolfSSL_GetObjectSize(void);  /* object size based on build */
+WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void);
+WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void);
+WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int);
+WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*);
+WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version);
+
+/* moved to asn.c, old names kept for backwards compatability */
+#define wolfSSL_KeyPemToDer    wc_KeyPemToDer
+#define wolfSSL_CertPemToDer   wc_CertPemToDer
+#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer
+#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer
+#define wolfSSL_PemCertToDer   wc_PemCertToDer
+
+
+typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
+typedef void (*CbMissingCRL)(const char* url);
+typedef int  (*CbOCSPIO)(void*, const char*, int,
+                                         unsigned char*, int, unsigned char**);
+typedef void (*CbOCSPRespFree)(void*,unsigned char*);
+
+#ifdef HAVE_CRL_IO
+typedef int  (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz);
+#endif
+
+/* User Atomic Record Layer CallBacks */
+typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut,
+       const unsigned char* macIn, unsigned int macInSz, int macContent,
+       int macVerify, unsigned char* encOut, const unsigned char* encIn,
+       unsigned int encSz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX*, CallbackMacEncrypt);
+WOLFSSL_API void  wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl,
+       unsigned char* decOut, const unsigned char* decIn,
+       unsigned int decSz, int content, int verify, unsigned int* padSz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*,
+                                               CallbackDecryptVerify);
+WOLFSSL_API void  wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl);
+
+WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int);
+WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*);
+WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteIV(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetKeySize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetIVSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetSide(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_IsTLSv1_1(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetBulkCipher(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetCipherBlockSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetAeadMacSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetHmacSize(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetHmacType(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_GetCipherType(WOLFSSL*);
+WOLFSSL_API int                  wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*,
+                                                       unsigned int, int, int);
+
+/* Atomic User Needs */
+enum {
+    WOLFSSL_SERVER_END = 0,
+    WOLFSSL_CLIENT_END = 1,
+    WOLFSSL_NEITHER_END = 3,
+    WOLFSSL_BLOCK_TYPE = 2,
+    WOLFSSL_STREAM_TYPE = 3,
+    WOLFSSL_AEAD_TYPE = 4,
+    WOLFSSL_TLS_HMAC_INNER_SZ = 13      /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */
+};
+
+/* for GetBulkCipher and internal use */
+enum BulkCipherAlgorithm {
+    wolfssl_cipher_null,
+    wolfssl_rc4,
+    wolfssl_rc2,
+    wolfssl_des,
+    wolfssl_triple_des,             /* leading 3 (3des) not valid identifier */
+    wolfssl_des40,
+#ifdef HAVE_IDEA
+    wolfssl_idea,
+#endif
+    wolfssl_aes,
+    wolfssl_aes_gcm,
+    wolfssl_aes_ccm,
+    wolfssl_chacha,
+    wolfssl_camellia,
+    wolfssl_hc128,                  /* wolfSSL extensions */
+    wolfssl_rabbit
+};
+
+
+/* for KDF TLS 1.2 mac types */
+enum KDF_MacAlgorithm {
+    wolfssl_sha256 = 4,     /* needs to match internal MACAlgorithm */
+    wolfssl_sha384,
+    wolfssl_sha512
+};
+
+
+/* Public Key Callback support */
+#ifdef HAVE_PK_CALLBACKS
+#ifdef HAVE_ECC
+
+struct ecc_key;
+
+typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key, 
+    unsigned int keySz, int ecc_curve, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen);
+WOLFSSL_API void  wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, CallbackEccSign);
+WOLFSSL_API void  wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccVerify)(WOLFSSL* ssl,
+       const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* hash, unsigned int hashSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify);
+WOLFSSL_API void  wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
+WOLFSSL_API void  wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret);
+WOLFSSL_API void  wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl);
+#endif
+
+#ifndef NO_DH
+/* Public DH Key Callback support */
+struct DhKey;
+typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key,
+        const unsigned char* priv, unsigned int privSz,
+        const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree);
+WOLFSSL_API void  wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl);
+#endif /* !NO_DH */
+
+#ifdef HAVE_ED25519
+struct ed25519_key;
+typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*,
+                                               CallbackEd25519Sign);
+WOLFSSL_API void  wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl,
+       const unsigned char* sig, unsigned int sigSz,
+       const unsigned char* msg, unsigned int msgSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       int* result, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*,
+                                                 CallbackEd25519Verify);
+WOLFSSL_API void  wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl);
+#endif
+
+#ifdef HAVE_CURVE25519
+struct curve25519_key;
+
+typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key, 
+    unsigned int keySz, void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen);
+WOLFSSL_API void  wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl,
+        struct curve25519_key* otherKey,
+        unsigned char* pubKeyDer, unsigned int* pubKeySz,
+        unsigned char* out, unsigned int* outlen,
+        int side, void* ctx);
+        /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */
+WOLFSSL_API void  wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*,
+        CallbackX25519SharedSecret);
+WOLFSSL_API void  wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl);
+#endif
+
+#ifndef NO_RSA
+typedef int (*CallbackRsaSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign);
+WOLFSSL_API void  wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackRsaVerify)(WOLFSSL* ssl,
+       unsigned char* sig, unsigned int sigSz,
+       unsigned char** out,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX*, CallbackRsaVerify);
+WOLFSSL_API void  wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl);
+
+#ifdef WC_RSA_PSS
+typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       int hash, int mgf,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign);
+WOLFSSL_API void  wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl);
+
+typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl,
+       unsigned char* sig, unsigned int sigSz,
+       unsigned char** out,
+       int hash, int mgf,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*,
+                                                CallbackRsaPssVerify);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX*,
+                                                    CallbackRsaPssVerify);
+WOLFSSL_API void  wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl);
+#endif
+
+/* RSA Public Encrypt cb */
+typedef int (*CallbackRsaEnc)(WOLFSSL* ssl,
+       const unsigned char* in, unsigned int inSz,
+       unsigned char* out, unsigned int* outSz,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc);
+WOLFSSL_API void  wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl);
+
+/* RSA Private Decrypt cb */
+typedef int (*CallbackRsaDec)(WOLFSSL* ssl,
+       unsigned char* in, unsigned int inSz,
+       unsigned char** out,
+       const unsigned char* keyDer, unsigned int keySz,
+       void* ctx);
+WOLFSSL_API void  wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec);
+WOLFSSL_API void  wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx);
+WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl);
+#endif
+#endif /* HAVE_PK_CALLBACKS */
+
+#ifndef NO_CERTS
+    WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache);
+
+    WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*);
+
+    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_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f,
+                                                                 const char* d);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*,
+                                  const unsigned char* in, long sz, int format);
+    WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm);
+#endif
+    WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f,
+                                                                    int format);
+    WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
+                                const unsigned char* buff, long sz, int format);
+    WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER*,
+                                                        unsigned char*, int sz);
+    WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*,
+                                                                   int options);
+    WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*,
+                                                         const char*, int, int);
+    WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*,
+                                            const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*,
+                                                                  CbMissingCRL);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*,
+                                                                       CbCrlIO);
+#endif
+    WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*,
+                                                        unsigned char*, int sz);
+    WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*,
+                                                                   int options);
+    WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*);
+    WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*,
+                                                                   const char*);
+    WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*,
+                                               CbOCSPIO, CbOCSPRespFree, void*);
+
+    WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling(
+                                                      WOLFSSL_CERT_MANAGER* cm);
+    WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling(
+                                                      WOLFSSL_CERT_MANAGER* cm);
+
+    WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options);
+    WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl);
+    WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int);
+    WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*,
+                                          const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb);
+#endif
+    WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options);
+    WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*);
+    WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*);
+    WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*);
+    WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*);
+    WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*);
+
+    WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options);
+    WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx);
+    WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int);
+    WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*,
+                                            const unsigned char*, long sz, int);
+    WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL);
+#ifdef HAVE_CRL_IO
+    WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO);
+#endif
+
+    WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options);
+    WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*);
+    WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*,
+                                               CbOCSPIO, CbOCSPRespFree, void*);
+    WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*);
+    WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*);
+#endif /* !NO_CERTS */
+
+
+#ifdef SINGLE_THREADED
+    WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*);
+#endif
+
+/* end of handshake frees temporary arrays, if user needs for get_keys or
+   psk hints, call KeepArrays before handshake and then FreeArrays when done
+   if don't want to wait for object free */
+WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*);
+WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl);
+
+WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx);
+WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl);
+
+/* async additions */
+#define wolfSSL_UseAsync wolfSSL_SetDevId
+#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId
+WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId);
+WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId);
+
+/* helpers to get device id and heap */
+WOLFSSL_API int   wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
+WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
+
+/* TLS Extensions */
+
+/* Server Name Indication */
+#ifdef HAVE_SNI
+
+/* SNI types */
+enum {
+    WOLFSSL_SNI_HOST_NAME = 0
+};
+
+WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
+                                         const void* data, unsigned short size);
+WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type,
+                                         const void* data, unsigned short size);
+
+#ifndef NO_WOLFSSL_SERVER
+
+/* SNI options */
+enum {
+    /* Do not abort the handshake if the requested SNI didn't match. */
+    WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01,
+
+    /* Behave as if the requested SNI matched in a case of mismatch.  */
+    /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */
+    WOLFSSL_SNI_ANSWER_ON_MISMATCH   = 0x02,
+
+    /* Abort the handshake if the client didn't send a SNI request. */
+    WOLFSSL_SNI_ABORT_ON_ABSENCE     = 0x04,
+};
+
+WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type,
+                                                         unsigned char options);
+WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx,
+                                     unsigned char type, unsigned char options);
+WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
+                 const unsigned char* clientHello, unsigned int helloSz,
+                 unsigned char type, unsigned char* sni, unsigned int* inOutSz);
+
+#endif /* NO_WOLFSSL_SERVER */
+
+/* SNI status */
+enum {
+    WOLFSSL_SNI_NO_MATCH   = 0,
+    WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */
+    WOLFSSL_SNI_REAL_MATCH = 2,
+    WOLFSSL_SNI_FORCE_KEEP = 3  /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */
+};
+
+WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type);
+
+WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl,
+                                               unsigned char type, void** data);
+
+#endif /* HAVE_SNI */
+
+/* Application-Layer Protocol Negotiation */
+#ifdef HAVE_ALPN
+
+/* ALPN status code */
+enum {
+    WOLFSSL_ALPN_NO_MATCH = 0,
+    WOLFSSL_ALPN_MATCH    = 1,
+    WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2,
+    WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4,
+};
+
+enum {
+    WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255,
+    WOLFSSL_MAX_ALPN_NUMBER = 257
+};
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out,
+    unsigned char* outLen, const unsigned char* in, unsigned int inLen,
+    void *arg);
+#endif
+
+WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
+                                unsigned int protocol_name_listSz,
+                                unsigned char options);
+
+WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
+                                         unsigned short *size);
+
+WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list,
+                                             unsigned short *listSz);
+WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list);
+#endif /* HAVE_ALPN */
+
+/* Maximum Fragment Length */
+#ifdef HAVE_MAX_FRAGMENT
+
+/* Fragment lengths */
+enum {
+    WOLFSSL_MFL_2_9  = 1, /*  512 bytes */
+    WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */
+    WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */
+    WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */
+    WOLFSSL_MFL_2_13 = 5  /* 8192 bytes *//* wolfSSL ONLY!!! */
+};
+
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl);
+WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl);
+
+#endif
+#endif
+
+/* Truncated HMAC */
+#ifdef HAVE_TRUNCATED_HMAC
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx);
+
+#endif
+#endif
+
+/* Certificate Status Request */
+/* Certificate Status Type */
+enum {
+    WOLFSSL_CSR_OCSP = 1
+};
+
+/* Certificate Status Options (flags) */
+enum {
+    WOLFSSL_CSR_OCSP_USE_NONCE = 0x01
+};
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl,
+                              unsigned char status_type, unsigned char options);
+
+WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx,
+                              unsigned char status_type, unsigned char options);
+
+#endif
+#endif
+
+/* Certificate Status Request v2 */
+/* Certificate Status Type */
+enum {
+    WOLFSSL_CSR2_OCSP = 1,
+    WOLFSSL_CSR2_OCSP_MULTI = 2
+};
+
+/* Certificate Status v2 Options (flags) */
+enum {
+    WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01
+};
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl,
+                              unsigned char status_type, unsigned char options);
+
+WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx,
+                              unsigned char status_type, unsigned char options);
+
+#endif
+#endif
+
+/* Named Groups */
+enum {
+#if 0 /* Not Supported */
+    WOLFSSL_ECC_SECT163K1 = 1,
+    WOLFSSL_ECC_SECT163R1 = 2,
+    WOLFSSL_ECC_SECT163R2 = 3,
+    WOLFSSL_ECC_SECT193R1 = 4,
+    WOLFSSL_ECC_SECT193R2 = 5,
+    WOLFSSL_ECC_SECT233K1 = 6,
+    WOLFSSL_ECC_SECT233R1 = 7,
+    WOLFSSL_ECC_SECT239K1 = 8,
+    WOLFSSL_ECC_SECT283K1 = 9,
+    WOLFSSL_ECC_SECT283R1 = 10,
+    WOLFSSL_ECC_SECT409K1 = 11,
+    WOLFSSL_ECC_SECT409R1 = 12,
+    WOLFSSL_ECC_SECT571K1 = 13,
+    WOLFSSL_ECC_SECT571R1 = 14,
+#endif
+    WOLFSSL_ECC_SECP160K1 = 15,
+    WOLFSSL_ECC_SECP160R1 = 16,
+    WOLFSSL_ECC_SECP160R2 = 17,
+    WOLFSSL_ECC_SECP192K1 = 18,
+    WOLFSSL_ECC_SECP192R1 = 19,
+    WOLFSSL_ECC_SECP224K1 = 20,
+    WOLFSSL_ECC_SECP224R1 = 21,
+    WOLFSSL_ECC_SECP256K1 = 22,
+    WOLFSSL_ECC_SECP256R1 = 23,
+    WOLFSSL_ECC_SECP384R1 = 24,
+    WOLFSSL_ECC_SECP521R1 = 25,
+    WOLFSSL_ECC_BRAINPOOLP256R1 = 26,
+    WOLFSSL_ECC_BRAINPOOLP384R1 = 27,
+    WOLFSSL_ECC_BRAINPOOLP512R1 = 28,
+    WOLFSSL_ECC_X25519    = 29,
+#ifdef WOLFSSL_TLS13
+    /* Not implemented. */
+    WOLFSSL_ECC_X448      = 30,
+
+    WOLFSSL_FFDHE_2048    = 256,
+    WOLFSSL_FFDHE_3072    = 257,
+    WOLFSSL_FFDHE_4096    = 258,
+    WOLFSSL_FFDHE_6144    = 259,
+    WOLFSSL_FFDHE_8192    = 260,
+#endif
+};
+
+enum {
+    WOLFSSL_EC_PF_UNCOMPRESSED = 0,
+#if 0 /* Not Supported */
+    WOLFSSL_EC_PF_X962_COMP_PRIME = 1,
+    WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2,
+#endif
+};
+
+#ifdef HAVE_SUPPORTED_CURVES
+#ifndef NO_WOLFSSL_CLIENT
+
+WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, unsigned short name);
+WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx,
+                                                           unsigned short name);
+
+#endif
+#endif
+
+#ifdef WOLFSSL_TLS13
+WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, unsigned short group);
+WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl);
+#endif
+
+
+/* Secure Renegotiation */
+#ifdef HAVE_SECURE_RENEGOTIATION
+
+WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl);
+
+#endif
+
+/* Session Ticket */
+#ifdef HAVE_SESSION_TICKET
+
+#ifndef NO_WOLFSSL_CLIENT
+WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
+WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*);
+WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, unsigned int);
+typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*);
+WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
+                                                  CallbackSessionTicket, void*);
+#endif /* NO_WOLFSSL_CLIENT */
+
+
+#define WOLFSSL_TICKET_NAME_SZ 16
+#define WOLFSSL_TICKET_IV_SZ   16
+#define WOLFSSL_TICKET_MAC_SZ  32
+
+enum TicketEncRet {
+    WOLFSSL_TICKET_RET_FATAL  = -1,  /* fatal error, don't use ticket */
+    WOLFSSL_TICKET_RET_OK     =  0,  /* ok, use ticket */
+    WOLFSSL_TICKET_RET_REJECT,       /* don't use ticket, but not fatal */
+    WOLFSSL_TICKET_RET_CREATE        /* existing ticket ok and create new one */
+};
+
+#ifndef NO_WOLFSSL_SERVER
+
+typedef int (*SessionTicketEncCb)(WOLFSSL*,
+                                 unsigned char key_name[WOLFSSL_TICKET_NAME_SZ],
+                                 unsigned char iv[WOLFSSL_TICKET_IV_SZ],
+                                 unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
+                                 int enc, unsigned char*, int, int*, void*);
+WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx,
+                                            SessionTicketEncCb);
+WOLFSSL_API int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int);
+WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*);
+
+#endif /* NO_WOLFSSL_SERVER */
+
+#endif /* HAVE_SESSION_TICKET */
+
+#ifdef HAVE_QSH
+/* Quantum-safe Crypto Schemes */
+enum {
+    WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65  */
+    WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86  */
+    WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */
+    WOLFSSL_LWE_XXX  = 0x0201,     /* Learning With Error encryption scheme */
+    WOLFSSL_HFE_XXX  = 0x0301,     /* Hidden Field Equation scheme */
+    WOLFSSL_NULL_QSH = 0xFFFF      /* QSHScheme is not used */
+};
+
+
+/* test if the connection is using a QSH secure connection return 1 if so */
+WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name);
+#ifndef NO_WOLFSSL_CLIENT
+    /* user control over sending client public key in hello
+       when flag = 1 will send keys if flag is 0 or function is not called
+       then will not send keys in the hello extension */
+    WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag);
+#endif
+
+#endif /* QSH */
+
+/* TLS Extended Master Secret Extension */
+WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl);
+WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
+
+
+#define WOLFSSL_CRL_MONITOR   0x01   /* monitor this dir flag */
+#define WOLFSSL_CRL_START_MON 0x02   /* start monitoring flag */
+
+
+/* notify user the handshake is done */
+typedef int (*HandShakeDoneCb)(WOLFSSL*, void*);
+WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*);
+
+
+WOLFSSL_API int wolfSSL_PrintSessionStats(void);
+WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
+                                          unsigned int* total,
+                                          unsigned int* peak,
+                                          unsigned int* maxSessions);
+/* External facing KDF */
+WOLFSSL_API
+int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
+                               const unsigned char* pms, unsigned int pmsLen,
+                               const unsigned char* cr, const unsigned char* sr,
+                               int tls1_2, int hash_type);
+
+WOLFSSL_API
+int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, unsigned int msLen,
+                              const unsigned char* pms, unsigned int pmsLen,
+                              const unsigned char* sHash, unsigned int sHashLen,
+                              int tls1_2, int hash_type);
+
+WOLFSSL_API
+int wolfSSL_DeriveTlsKeys(unsigned char* key_data, unsigned int keyLen,
+                               const unsigned char* ms, unsigned int msLen,
+                               const unsigned char* sr, const unsigned char* cr,
+                               int tls1_2, int hash_type);
+
+#ifdef WOLFSSL_CALLBACKS
+
+/* used internally by wolfSSL while OpenSSL types aren't */
+#include <wolfssl/callbacks.h>
+
+typedef int (*HandShakeCallBack)(HandShakeInfo*);
+typedef int (*TimeoutCallBack)(TimeoutInfo*);
+
+/* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack
+   for diagnostics */
+WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
+                                 Timeval);
+WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack,
+                                Timeval);
+
+#endif /* WOLFSSL_CALLBACKS */
+
+
+#ifdef WOLFSSL_HAVE_WOLFSCEP
+    WOLFSSL_API void wolfSSL_wolfSCEP(void);
+#endif /* WOLFSSL_HAVE_WOLFSCEP */
+
+#ifdef WOLFSSL_HAVE_CERT_SERVICE
+    WOLFSSL_API void wolfSSL_cert_service(void);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
+ * this subset and its memory usage */
+
+#include <wolfssl/openssl/asn1.h>
+struct WOLFSSL_X509_NAME_ENTRY {
+    WOLFSSL_ASN1_OBJECT* object; /* not defined yet */
+    WOLFSSL_ASN1_STRING  data;
+    WOLFSSL_ASN1_STRING* value;  /* points to data, for lighttpd port */
+    int nid; /* i.e. ASN_COMMON_NAME */
+    int set;
+    int size;
+};
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+
+enum {
+    WOLFSSL_SYS_ACCEPT = 0,
+    WOLFSSL_SYS_BIND,
+    WOLFSSL_SYS_CONNECT,
+    WOLFSSL_SYS_FOPEN,
+    WOLFSSL_SYS_FREAD,
+    WOLFSSL_SYS_GETADDRINFO,
+    WOLFSSL_SYS_GETSOCKOPT,
+    WOLFSSL_SYS_GETSOCKNAME,
+    WOLFSSL_SYS_GETHOSTBYNAME,
+    WOLFSSL_SYS_GETNAMEINFO,
+    WOLFSSL_SYS_GETSERVBYNAME,
+    WOLFSSL_SYS_IOCTLSOCKET,
+    WOLFSSL_SYS_LISTEN,
+    WOLFSSL_SYS_OPENDIR,
+    WOLFSSL_SYS_SETSOCKOPT,
+    WOLFSSL_SYS_SOCKET
+};
+
+/* Object functions */
+WOLFSSL_API const char *  wolfSSL_OBJ_nid2sn(int n);
+WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
+WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn);
+
+WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n);
+WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn);
+
+WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n);
+WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name);
+
+WOLFSSL_API void wolfSSL_OBJ_cleanup(void);
+/* end of object functions */
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line);
+WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt);
+WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt);
+
+#ifndef NO_CERTS
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
+            WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
+            unsigned char* data, int dataSz);
+WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
+                              WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set);
+WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
+            const WOLFSSL_X509_NAME* y);
+WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void);
+WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl);
+WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509,
+                                                     int nid, int* c, int* idx);
+WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509,
+        const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len);
+WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509);
+WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der,
+                                                                     int derSz);
+WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey);
+WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl,
+                                            unsigned char* der, long derSz);
+WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl);
+#ifndef NO_RSA
+WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der,
+                                                                long derSz);
+#endif
+#endif /* NO_CERTS */
+
+WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r);
+
+WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses,
+        unsigned char* out, int outSz);
+WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses);
+
+WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx,
+                                                       WOLFSSL_X509_STORE* str);
+WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp,
+                                               WOLFSSL_X509** x509);
+#endif
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio,
+                                               WOLFSSL_X509** x509);
+WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx);
+
+WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b);
+WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl,
+                                             unsigned char *out, size_t outlen);
+WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl,
+                                              unsigned char* out, size_t outSz);
+WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey);
+WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX
+        (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u);
+#ifndef NO_FILESYSTEM
+WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **x,
+                                                    pem_password_cb *cb, void *u);
+#endif
+
+/*lighttp compatibility */
+
+struct WOLFSSL_ASN1_BIT_STRING {
+    int length;
+    int type;
+    char* data;
+    long flags;
+};
+
+
+#if    defined(OPENSSL_EXTRA) \
+    || defined(OPENSSL_ALL) \
+    || defined(HAVE_LIGHTY) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
+    || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne);
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void);
+WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name);
+WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name);
+/* These are to be merged shortly */
+WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth);
+WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl);
+WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg);
+WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne);
+WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc);
+WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*));
+WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md);
+WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk );
+WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509);
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c);
+WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp);
+#endif
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
+
+
+#if defined(OPENSSL_ALL) \
+    || defined(HAVE_STUNNEL) \
+    || defined(HAVE_LIGHTY) \
+    || defined(WOLFSSL_MYSQL_COMPATIBLE) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA)
+
+WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode);
+WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*);
+WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp,
+    WOLFSSL_DH **x, pem_password_cb *cb, void *u);
+WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp,
+    WOLFSSL_DSA **x, pem_password_cb *cb, void *u);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x);
+
+#endif /* HAVE_STUNNEL || HAVE_LIGHTY */
+
+
+#if defined(OPENSSL_ALL) \
+    || defined(HAVE_STUNNEL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) \
+    || defined(HAVE_LIGHTY)
+
+#include <wolfssl/openssl/crypto.h>
+
+/* SNI received callback type */
+typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg);
+
+WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
+    void *(*r) (void *, size_t, const char *, int), void (*f) (void *));
+
+WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void);
+
+WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn);
+WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator,
+    void (*callback) (int, int, void *), void *cb_arg);
+
+WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int,
+                           void (*callback) (int, int, void *));
+
+WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void);
+
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void);
+
+WOLFSSL_API int wolfSSL_FIPS_mode(void);
+
+WOLFSSL_API int wolfSSL_FIPS_mode_set(int r);
+
+WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth);
+
+WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits);
+
+WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s);
+
+WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s);
+
+WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int,
+        unsigned long);
+
+WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(
+                            const WOLFSSL_X509*);
+
+WOLFSSL_API int        wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*);
+
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl);
+
+WOLFSSL_API int  wolfSSL_version(WOLFSSL*);
+
+WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*);
+
+WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int);
+
+WOLFSSL_API void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int);
+
+WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int);
+
+WOLFSSL_API int   wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*);
+
+WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*,
+        CRYPTO_free_func*);
+
+WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*);
+
+
+WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*,
+        unsigned int*);
+
+WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *);
+
+WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char);
+
+WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*);
+
+WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*);
+
+WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*);
+
+WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *,
+        CallbackSniRecv);
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *,
+        CallbackSniRecv);
+
+WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*);
+
+WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*);
+
+/* support for depricated old name */
+#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state
+
+#ifndef NO_FILESYSTEM
+WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE *fp);
+#endif
+
+WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*));
+
+WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val);
+
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
+                               WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*);
+
+WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*));
+#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */
+
+#if defined(OPENSSL_ALL) || \
+    defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+
+WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx);
+
+#endif
+
+#ifdef WOLFSSL_JNI
+WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr);
+WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl);
+#endif /* WOLFSSL_JNI */
+
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags);
+WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents,
+    WOLF_EVENT_FLAG flags, int* eventCount);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef OPENSSL_EXTRA
+WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names);
+
+typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type,
+    const void *buf, size_t len, WOLFSSL *ssl, void *arg);
+
+WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb);
+WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb);
+WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg);
+WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg);
+WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file,
+    int *line, const char **data, int *flags);
+WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx,
+    const unsigned char *protos, unsigned int protos_len);
+WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data,
+    size_t siz, const char* file, int line);
+WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void);
+#endif
+
+#if defined(OPENSSL_ALL) \
+    || defined(WOLFSSL_NGINX) \
+    || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA)
+WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+/* Not an OpenSSL API. */
+WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response);
+/* Not an OpenSSL API. */
+WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl);
+/* Not an OpenSSL API. */
+WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url);
+#endif
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
+    || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl);
+WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a,
+    void *b, void *c);
+WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx);
+WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx,
+    void *data);
+
+WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data,
+    const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len);
+
+WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx);
+WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx,
+    WOLFSSL_EC_KEY *ecdh);
+WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *,
+    WOLFSSL_SESSION *c);
+
+WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s);
+WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s);
+WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s);
+WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */
+#ifndef NO_SESSION_CACHE
+    WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s);
+#endif
+WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk,
+    size_t chklen, unsigned int flags, char **peername);
+
+WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp,
+    const WOLFSSL_ASN1_INTEGER *a);
+
+#ifdef HAVE_SESSION_TICKET
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)(
+    WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
+    WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc));
+#endif
+
+#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx,
+    WOLF_STACK_OF(X509)** chain);
+WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx,
+    int(*)(WOLFSSL*, void*));
+
+WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
+    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x);
+
+WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk);
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x);
+
+WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer,
+    WOLFSSL_X509 *subject);
+
+WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x);
+
+WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value(
+    WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx);
+#endif /* HAVE_OCSP */
+
+WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio,
+    WOLFSSL_X509 *cert);
+
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || 
+    OPENSSL_EXTRA || HAVE_LIGHTY*/
+
+WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl,
+        const unsigned char **data, unsigned int *len);
+WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out,
+        unsigned char *outlen,
+        const unsigned char *in, unsigned int inlen,
+        const unsigned char *client,
+        unsigned int client_len);
+WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx,
+        int (*cb) (WOLFSSL *ssl,
+            const unsigned char **out,
+            unsigned char *outlen,
+            const unsigned char *in,
+            unsigned int inlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s,
+        int (*cb) (WOLFSSL *ssl,
+            const unsigned char **out,
+            unsigned int *outlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s,
+        int (*cb) (WOLFSSL *ssl,
+            unsigned char **out,
+            unsigned char *outlen,
+            const unsigned char *in,
+            unsigned int inlen,
+            void *arg), void *arg);
+WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data,
+        unsigned *len);
+
+
+#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context(
+        const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length);
+WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count);
+WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count);
+#endif
+
+WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len);
+WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len);
+WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x);
+WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor);
+WOLFSSL_API void *X509_get_X509_PUBKEY(void * x);
+WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub);
+WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a);
+WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength));
+WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir);
+WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x);
+WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p);
+WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st);
+WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx);
+WOLFSSL_API void ERR_load_SSL_strings(void);
+WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p);
+
+WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag);
+WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags);
+WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t,
+                                                                WOLFSSL_ASN1_TIME **out);
+WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp);
+#endif /* OPENSSL_EXTRA */
+
+#ifdef HAVE_PK_CALLBACKS
+WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx);
+#endif
+
+#ifdef __cplusplus
+    }  /* extern "C" */
+#endif
+
+
+#endif /* WOLFSSL_SSL_H */
+
--- a/wolfssl/wolfcrypt/aes.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/* aes.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/aes.h
-*/
-
-
-#ifndef WOLF_CRYPT_AES_H
-#define WOLF_CRYPT_AES_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_AES
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-/* included for fips @wc_fips */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-#include <cyassl/ctaocrypt/aes.h>
-#if defined(CYASSL_AES_COUNTER) && !defined(WOLFSSL_AES_COUNTER)
-    #define WOLFSSL_AES_COUNTER
-#endif
-#if !defined(WOLFSSL_AES_DIRECT) && defined(CYASSL_AES_DIRECT)
-    #define WOLFSSL_AES_DIRECT
-#endif
-#endif
-
-
-#ifdef WOLFSSL_AESNI
-
-#include <wmmintrin.h>
-#include <emmintrin.h>
-#include <smmintrin.h>
-
-#endif /* WOLFSSL_AESNI */
-
-
-#ifdef WOLFSSL_XILINX_CRYPT
-#include "xsecure_aes.h"
-#endif
-
-#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG)
-    #include <wolfssl/wolfcrypt/random.h>
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* these are required for FIPS and non-FIPS */
-enum {
-    AES_128_KEY_SIZE    = 16,  /* for 128 bit             */
-    AES_192_KEY_SIZE    = 24,  /* for 192 bit             */
-    AES_256_KEY_SIZE    = 32,  /* for 256 bit             */
-
-    AES_IV_SIZE         = 16,  /* always block size       */
-};
-
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-enum {
-    AES_ENC_TYPE   = WC_CIPHER_AES,   /* cipher unique type */
-    AES_ENCRYPTION = 0,
-    AES_DECRYPTION = 1,
-
-    AES_BLOCK_SIZE      = 16,
-
-    KEYWRAP_BLOCK_SIZE  = 8,
-
-    GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */
-    GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */
-    GCM_NONCE_MIN_SZ = 8,  /* wolfCrypt's minimum nonce size allowed. */
-    CCM_NONCE_MIN_SZ = 7,
-    CCM_NONCE_MAX_SZ = 13,
-    CTR_SZ   = 4,
-    AES_IV_FIXED_SZ = 4
-};
-
-
-typedef struct Aes {
-    /* AESNI needs key first, rounds 2nd, not sure why yet */
-    ALIGN16 word32 key[60];
-    word32  rounds;
-    int     keylen;
-
-    ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
-    ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)];      /* same         */
-
-#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
-    word32 invokeCtr[2];
-    word32 nonceSz;
-#endif
-#ifdef HAVE_AESGCM
-    ALIGN16 byte H[AES_BLOCK_SIZE];
-#ifdef GCM_TABLE
-    /* key-based fast multiplication table. */
-    ALIGN16 byte M0[256][AES_BLOCK_SIZE];
-#endif /* GCM_TABLE */
-#endif /* HAVE_AESGCM */
-#ifdef WOLFSSL_AESNI
-    byte use_aesni;
-#endif /* WOLFSSL_AESNI */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    word32 asyncKey[AES_MAX_KEY_SIZE/8/sizeof(word32)]; /* raw key */
-    word32 asyncIv[AES_BLOCK_SIZE/sizeof(word32)]; /* raw IV */
-    WC_ASYNC_DEV asyncDev;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB)
-    word32  left;            /* unused bytes left from last call */
-#endif
-#ifdef WOLFSSL_XILINX_CRYPT
-    XSecure_Aes xilAes;
-    XCsuDma     dma;
-    word32      key_init[8];
-    word32      kup;
-#endif
-    void*  heap; /* memory hint to use */
-} Aes;
-
-#ifdef WOLFSSL_AES_XTS
-typedef struct XtsAes {
-    Aes aes;
-    Aes tweak;
-} XtsAes;
-#endif
-
-#ifdef HAVE_AESGCM
-typedef struct Gmac {
-    Aes aes;
-} Gmac;
-#endif /* HAVE_AESGCM */
-#endif /* HAVE_FIPS */
-
-
-/* Authenticate cipher function prototypes */
-typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   const byte* iv, word32 ivSz,
-                                   byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
-typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   const byte* iv, word32 ivSz,
-                                   const byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
-
-/* AES-CBC */
-WOLFSSL_API int  wc_AesSetKey(Aes* aes, const byte* key, word32 len,
-                              const byte* iv, int dir);
-WOLFSSL_API int  wc_AesSetIV(Aes* aes, const byte* iv);
-WOLFSSL_API int  wc_AesCbcEncrypt(Aes* aes, byte* out,
-                                  const byte* in, word32 sz);
-WOLFSSL_API int  wc_AesCbcDecrypt(Aes* aes, byte* out,
-                                  const byte* in, word32 sz);
-
-#ifdef WOLFSSL_AES_CFB
-WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out,
-                                    const byte* in, word32 sz);
-#ifdef HAVE_AES_DECRYPT
-WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out,
-                                    const byte* in, word32 sz);
-#endif /* HAVE_AES_DECRYPT */
-#endif /* WOLFSSL_AES_CFB */
-
-#ifdef HAVE_AES_ECB
-WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out,
-                                  const byte* in, word32 sz);
-WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
-                                  const byte* in, word32 sz);
-#endif
-
-/* AES-CTR */
-#ifdef WOLFSSL_AES_COUNTER
- WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out,
-                                   const byte* in, word32 sz);
-#endif
-/* AES-DIRECT */
-#if defined(WOLFSSL_AES_DIRECT)
- WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in);
- WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in);
- WOLFSSL_API int  wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
-                                const byte* iv, int dir);
-#endif
-
-#ifdef HAVE_AESGCM
-#ifdef WOLFSSL_XILINX_CRYPT
- WOLFSSL_API int  wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len,
-         word32 kup);
-#endif
- WOLFSSL_API int  wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len);
- WOLFSSL_API int  wc_AesGcmEncrypt(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   const byte* iv, word32 ivSz,
-                                   byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
- WOLFSSL_API int  wc_AesGcmDecrypt(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   const byte* iv, word32 ivSz,
-                                   const byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
-
-#ifndef WC_NO_RNG
- WOLFSSL_API int  wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz);
- WOLFSSL_API int  wc_AesGcmSetIV(Aes* aes, word32 ivSz,
-                                   const byte* ivFixed, word32 ivFixedSz,
-                                   WC_RNG* rng);
- WOLFSSL_API int  wc_AesGcmEncrypt_ex(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   byte* ivOut, word32 ivOutSz,
-                                   byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
-#endif /* WC_NO_RNG */
-
- WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len);
- WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
-                               const byte* authIn, word32 authInSz,
-                               byte* authTag, word32 authTagSz);
-#ifndef WC_NO_RNG
- WOLFSSL_API int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
-                               const byte* authIn, word32 authInSz,
-                               byte* authTag, word32 authTagSz, WC_RNG* rng);
- WOLFSSL_API int wc_GmacVerify(const byte* key, word32 keySz,
-                               const byte* iv, word32 ivSz,
-                               const byte* authIn, word32 authInSz,
-                               const byte* authTag, word32 authTagSz);
-#endif /* WC_NO_RNG */
- WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-                               word32 cSz, byte* s, word32 sSz);
-#endif /* HAVE_AESGCM */
-#ifdef HAVE_AESCCM
- WOLFSSL_API int  wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz);
- WOLFSSL_API int  wc_AesCcmEncrypt(Aes* aes, byte* out,
-                                   const byte* in, word32 inSz,
-                                   const byte* nonce, word32 nonceSz,
-                                   byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
- WOLFSSL_API int  wc_AesCcmDecrypt(Aes* aes, byte* out,
-                                   const byte* in, word32 inSz,
-                                   const byte* nonce, word32 nonceSz,
-                                   const byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
- WOLFSSL_API int  wc_AesCcmSetNonce(Aes* aes,
-                                   const byte* nonce, word32 nonceSz);
- WOLFSSL_API int  wc_AesCcmEncrypt_ex(Aes* aes, byte* out,
-                                   const byte* in, word32 sz,
-                                   byte* ivOut, word32 ivOutSz,
-                                   byte* authTag, word32 authTagSz,
-                                   const byte* authIn, word32 authInSz);
-#endif /* HAVE_AESCCM */
-#ifdef HAVE_AES_KEYWRAP
- WOLFSSL_API int  wc_AesKeyWrap(const byte* key, word32 keySz,
-                                const byte* in, word32 inSz,
-                                byte* out, word32 outSz,
-                                const byte* iv);
- WOLFSSL_API int  wc_AesKeyUnWrap(const byte* key, word32 keySz,
-                                const byte* in, word32 inSz,
-                                byte* out, word32 outSz,
-                                const byte* iv);
-#endif /* HAVE_AES_KEYWRAP */
-
-#ifdef WOLFSSL_AES_XTS
-
-WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key,
-         word32 len, int dir, void* heap, int devId);
-
-WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out,
-         const byte* in, word32 sz, word64 sector);
-
-WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out,
-         const byte* in, word32 sz, word64 sector);
-
-WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out,
-         const byte* in, word32 sz, const byte* i, word32 iSz);
-
-WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out,
-        const byte* in, word32 sz, const byte* i, word32 iSz);
-
-WOLFSSL_API int wc_AesXtsFree(XtsAes* aes);
-#endif
-
-WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize);
-
-WOLFSSL_API int  wc_AesInit(Aes*, void*, int);
-WOLFSSL_API void wc_AesFree(Aes*);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-
-#endif /* NO_AES */
-#endif /* WOLF_CRYPT_AES_H */
-
--- a/wolfssl/wolfcrypt/arc4.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/* arc4.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/arc4.h
-*/
-
-#ifndef WOLF_CRYPT_ARC4_H
-#define WOLF_CRYPT_ARC4_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-enum {
-	ARC4_ENC_TYPE   = 4,    /* cipher unique type */
-    ARC4_STATE_SIZE = 256,
-    RC4_KEY_SIZE    = 16,   /* always 128bit           */
-};
-
-/* ARC4 encryption and decryption */
-typedef struct Arc4 {
-    byte x;
-    byte y;
-    byte state[ARC4_STATE_SIZE];
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif
-    void* heap;
-} Arc4;
-
-WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32);
-WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32);
-
-WOLFSSL_API int  wc_Arc4Init(Arc4*, void*, int);
-WOLFSSL_API void wc_Arc4Free(Arc4*);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-
-#endif /* WOLF_CRYPT_ARC4_H */
-
-
--- a/wolfssl/wolfcrypt/asn.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1140 +0,0 @@
-/* asn.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/asn.h
-*/
-
-#ifndef WOLF_CRYPT_ASN_H
-#define WOLF_CRYPT_ASN_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_ASN
-
-
-#if !defined(NO_ASN_TIME) && defined(NO_TIME_H)
-    #define NO_ASN_TIME /* backwards compatibility with NO_TIME_H */
-#endif
-
-#include <wolfssl/wolfcrypt/integer.h>
-
-/* fips declare of RsaPrivateKeyDecode @wc_fips */
-#if defined(HAVE_FIPS) && !defined(NO_RSA) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-    #include <cyassl/ctaocrypt/rsa.h>
-#endif
-
-#ifndef NO_DH
-    #include <wolfssl/wolfcrypt/dh.h>
-#endif
-#ifndef NO_DSA
-    #include <wolfssl/wolfcrypt/dsa.h>
-#endif
-#ifndef NO_SHA
-    #include <wolfssl/wolfcrypt/sha.h>
-#endif
-#ifndef NO_MD5
-    #include <wolfssl/wolfcrypt/md5.h>
-#endif
-#include <wolfssl/wolfcrypt/sha256.h>
-#include <wolfssl/wolfcrypt/asn_public.h>   /* public interface */
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum {
-    ISSUER  = 0,
-    SUBJECT = 1,
-
-    EXTERNAL_SERIAL_SIZE = 32,
-
-    BEFORE  = 0,
-    AFTER   = 1
-};
-
-/* ASN Tags   */
-enum ASN_Tags {
-    ASN_BOOLEAN           = 0x01,
-    ASN_INTEGER           = 0x02,
-    ASN_BIT_STRING        = 0x03,
-    ASN_OCTET_STRING      = 0x04,
-    ASN_TAG_NULL          = 0x05,
-    ASN_OBJECT_ID         = 0x06,
-    ASN_ENUMERATED        = 0x0a,
-    ASN_UTF8STRING        = 0x0c,
-    ASN_SEQUENCE          = 0x10,
-    ASN_SET               = 0x11,
-    ASN_UTC_TIME          = 0x17,
-    ASN_OTHER_TYPE        = 0x00,
-    ASN_RFC822_TYPE       = 0x01,
-    ASN_DNS_TYPE          = 0x02,
-    ASN_DIR_TYPE          = 0x04,
-    ASN_URI_TYPE          = 0x06, /* the value 6 is from GeneralName OID */
-    ASN_GENERALIZED_TIME  = 0x18,
-    CRL_EXTENSIONS        = 0xa0,
-    ASN_EXTENSIONS        = 0xa3,
-    ASN_LONG_LENGTH       = 0x80,
-    ASN_INDEF_LENGTH      = 0x80,
-
-    /* ASN_Flags - Bitmask */
-    ASN_CONSTRUCTED       = 0x20,
-    ASN_CONTEXT_SPECIFIC  = 0x80,
-};
-
-#define ASN_UTC_TIME_SIZE 14
-#define ASN_GENERALIZED_TIME_SIZE 16
-
-enum DN_Tags {
-    ASN_COMMON_NAME   = 0x03,   /* CN */
-    ASN_SUR_NAME      = 0x04,   /* SN */
-    ASN_SERIAL_NUMBER = 0x05,   /* serialNumber */
-    ASN_COUNTRY_NAME  = 0x06,   /* C  */
-    ASN_LOCALITY_NAME = 0x07,   /* L  */
-    ASN_STATE_NAME    = 0x08,   /* ST */
-    ASN_ORG_NAME      = 0x0a,   /* O  */
-    ASN_ORGUNIT_NAME  = 0x0b,    /* OU */
-    ASN_EMAIL_NAME    = 0x98,    /* not oid number there is 97 in 2.5.4.0-97 */
-
-    /* pilot attribute types
-     * OID values of 0.9.2342.19200300.100.1.* */
-    ASN_USER_ID          = 0x01, /* UID */
-    ASN_DOMAIN_COMPONENT = 0x19  /* DC */
-};
-
-/* DN Tag Strings */
-#define WOLFSSL_COMMON_NAME      "/CN="
-#define WOLFSSL_SUR_NAME         "/SN="
-#define WOLFSSL_SERIAL_NUMBER    "/serialNumber="
-#define WOLFSSL_COUNTRY_NAME     "/C="
-#define WOLFSSL_LOCALITY_NAME    "/L="
-#define WOLFSSL_STATE_NAME       "/ST="
-#define WOLFSSL_ORG_NAME         "/O="
-#define WOLFSSL_ORGUNIT_NAME     "/OU="
-#define WOLFSSL_DOMAIN_COMPONENT "/DC="
-
-enum ECC_TYPES {
-    ECC_PREFIX_0 = 160,
-    ECC_PREFIX_1 = 161
-};
-
-enum Misc_ASN {
-    ASN_NAME_MAX        = 256,
-    MAX_SALT_SIZE       =  64,     /* MAX PKCS Salt length */
-    MAX_IV_SIZE         =  64,     /* MAX PKCS Iv length */
-    ASN_BOOL_SIZE       =   2,     /* including type */
-    ASN_ECC_HEADER_SZ   =   2,     /* String type + 1 byte len */
-    ASN_ECC_CONTEXT_SZ  =   2,     /* Content specific type + 1 byte len */
-#ifdef NO_SHA
-    KEYID_SIZE          = WC_SHA256_DIGEST_SIZE,
-#else
-    KEYID_SIZE          = WC_SHA_DIGEST_SIZE,
-#endif
-    RSA_INTS            =   8,     /* RSA ints in private key */
-    DSA_INTS            =   5,     /* DSA ints in private key */
-    MIN_DATE_SIZE       =  13,
-    MAX_DATE_SIZE       =  32,
-    ASN_GEN_TIME_SZ     =  15,     /* 7 numbers * 2 + Zulu tag */
-    MAX_ENCODED_SIG_SZ  = 512,
-    MAX_SIG_SZ          = 256,
-    MAX_ALGO_SZ         =  20,
-    MAX_SHORT_SZ        =   6,     /* asn int + byte len + 4 byte length */
-    MAX_SEQ_SZ          =   5,     /* enum(seq | con) + length(4) */
-    MAX_SET_SZ          =   5,     /* enum(set | con) + length(4) */
-    MAX_OCTET_STR_SZ    =   5,     /* enum(set | con) + length(4) */
-    MAX_EXP_SZ          =   5,     /* enum(contextspec|con|exp) + length(4) */
-    MAX_PRSTR_SZ        =   5,     /* enum(prstr) + length(4) */
-    MAX_VERSION_SZ      =   5,     /* enum + id + version(byte) + (header(2))*/
-    MAX_ENCODED_DIG_SZ  =  73,     /* sha512 + enum(bit or octet) + length(4) */
-    MAX_RSA_INT_SZ      = 517,     /* RSA raw sz 4096 for bits + tag + len(4) */
-    MAX_NTRU_KEY_SZ     = 610,     /* NTRU 112 bit public key */
-    MAX_NTRU_ENC_SZ     = 628,     /* NTRU 112 bit DER public encoding */
-    MAX_LENGTH_SZ       =   4,     /* Max length size for DER encoding */
-    MAX_RSA_E_SZ        =  16,     /* Max RSA public e size */
-    MAX_CA_SZ           =  32,     /* Max encoded CA basic constraint length */
-    MAX_SN_SZ           =  35,     /* Max encoded serial number (INT) length */
-    MAX_DER_DIGEST_SZ   = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, /* Maximum DER digest size */
-#ifdef WOLFSSL_CERT_GEN
-    #ifdef WOLFSSL_CERT_REQ
-                          /* Max encoded cert req attributes length */
-        MAX_ATTRIB_SZ   = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 +
-                          MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */
-    #endif
-    #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT)
-        MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE,
-    #else
-        MAX_EXTENSIONS_SZ   = 1 + MAX_LENGTH_SZ + MAX_CA_SZ,
-    #endif
-                                   /* Max total extensions, id + len + others */
-#endif
-#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA)
-    MAX_OID_SZ          = 32,      /* Max DER length of OID*/
-    MAX_OID_STRING_SZ   = 64,      /* Max string length representation of OID*/
-#endif
-#ifdef WOLFSSL_CERT_EXT
-    MAX_KID_SZ			= 45,	   /* Max encoded KID length (SHA-256 case) */
-    MAX_KEYUSAGE_SZ     = 18,      /* Max encoded Key Usage length */
-    MAX_EXTKEYUSAGE_SZ  = 12 + (6 * (8 + 2)) +
-                          CTC_MAX_EKU_OID_SZ, /* Max encoded ExtKeyUsage
-                        (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + (6 * (SEQ + OID))) */
-    MAX_CERTPOL_NB      = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */
-    MAX_CERTPOL_SZ      = CTC_MAX_CERTPOL_SZ,
-#endif
-    MAX_NAME_ENTRIES    = 5,       /* extra entries added to x509 name struct */
-    OCSP_NONCE_EXT_SZ   = 35,      /* OCSP Nonce Extension size */
-    MAX_OCSP_EXT_SZ     = 58,      /* Max OCSP Extension length */
-    MAX_OCSP_NONCE_SZ   = 16,      /* OCSP Nonce size           */
-    EIGHTK_BUF          = 8192,    /* Tmp buffer size           */
-    MAX_PUBLIC_KEY_SZ   = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
-                                   /* use bigger NTRU size */
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */
-#else
-    HEADER_ENCRYPTED_KEY_SIZE = 0,
-#endif
-    TRAILING_ZERO       = 1,       /* Used for size of zero pad */
-    MIN_VERSION_SZ      = 3,       /* Min bytes needed for GetMyVersion */
-#if defined(OPENSSL_ALL)  || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \
-    defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
-    MAX_TIME_STRING_SZ  = 25,      /* Max length of formatted time string */
-#endif
-
-    PKCS5_SALT_SZ       = 8,
-
-    PEM_LINE_LEN       = 80,       /* PEM line max + fudge */
-};
-
-
-enum Oid_Types {
-    oidHashType         = 0,
-    oidSigType          = 1,
-    oidKeyType          = 2,
-    oidCurveType        = 3,
-    oidBlkType          = 4,
-    oidOcspType         = 5,
-    oidCertExtType      = 6,
-    oidCertAuthInfoType = 7,
-    oidCertPolicyType   = 8,
-    oidCertAltNameType  = 9,
-    oidCertKeyUseType   = 10,
-    oidKdfType          = 11,
-    oidKeyWrapType      = 12,
-    oidCmsKeyAgreeType  = 13,
-    oidPBEType          = 14,
-    oidHmacType         = 15,
-    oidIgnoreType
-};
-
-
-enum Hash_Sum  {
-    MD2h    = 646,
-    MD5h    = 649,
-    SHAh    =  88,
-    SHA224h = 417,
-    SHA256h = 414,
-    SHA384h = 415,
-    SHA512h = 416
-};
-
-
-#if !defined(NO_DES3) || !defined(NO_AES)
-enum Block_Sum {
-#ifdef WOLFSSL_AES_128
-    AES128CBCb = 414,
-#endif
-#ifdef WOLFSSL_AES_192
-    AES192CBCb = 434,
-#endif
-#ifdef WOLFSSL_AES_256
-    AES256CBCb = 454,
-#endif
-#ifndef NO_DES3
-    DESb       = 69,
-    DES3b      = 652
-#endif
-};
-#endif /* !NO_DES3 || !NO_AES */
-
-
-enum Key_Sum {
-    DSAk     = 515,
-    RSAk     = 645,
-    NTRUk    = 274,
-    ECDSAk   = 518,
-    ED25519k = 256
-};
-
-
-#ifndef NO_AES
-enum KeyWrap_Sum {
-#ifdef WOLFSSL_AES_128
-    AES128_WRAP = 417,
-#endif
-#ifdef WOLFSSL_AES_192
-    AES192_WRAP = 437,
-#endif
-#ifdef WOLFSSL_AES_256
-    AES256_WRAP = 457
-#endif
-};
-#endif /* !NO_AES */
-
-enum Key_Agree {
-    dhSinglePass_stdDH_sha1kdf_scheme   = 464,
-    dhSinglePass_stdDH_sha224kdf_scheme = 188,
-    dhSinglePass_stdDH_sha256kdf_scheme = 189,
-    dhSinglePass_stdDH_sha384kdf_scheme = 190,
-    dhSinglePass_stdDH_sha512kdf_scheme = 191,
-};
-
-
-enum Ecc_Sum {
-    ECC_SECP112R1_OID = 182,
-    ECC_SECP112R2_OID = 183,
-    ECC_SECP128R1_OID = 204,
-    ECC_SECP128R2_OID = 205,
-    ECC_SECP160R1_OID = 184,
-    ECC_SECP160R2_OID = 206,
-    ECC_SECP160K1_OID = 185,
-    ECC_BRAINPOOLP160R1_OID = 98,
-    ECC_SECP192R1_OID = 520,
-    ECC_PRIME192V2_OID = 521,
-    ECC_PRIME192V3_OID = 522,
-    ECC_SECP192K1_OID = 207,
-    ECC_BRAINPOOLP192R1_OID = 100,
-    ECC_SECP224R1_OID = 209,
-    ECC_SECP224K1_OID = 208,
-    ECC_BRAINPOOLP224R1_OID = 102,
-    ECC_PRIME239V1_OID = 523,
-    ECC_PRIME239V2_OID = 524,
-    ECC_PRIME239V3_OID = 525,
-    ECC_SECP256R1_OID = 526,
-    ECC_SECP256K1_OID = 186,
-    ECC_BRAINPOOLP256R1_OID = 104,
-    ECC_X25519_OID = 365,
-    ECC_ED25519_OID = 256,
-    ECC_BRAINPOOLP320R1_OID = 106,
-    ECC_SECP384R1_OID = 210,
-    ECC_BRAINPOOLP384R1_OID = 108,
-    ECC_BRAINPOOLP512R1_OID = 110,
-    ECC_SECP521R1_OID = 211,
-};
-
-
-enum KDF_Sum {
-    PBKDF2_OID = 660
-};
-
-
-enum HMAC_Sum {
-    HMAC_SHA224_OID = 652,
-    HMAC_SHA256_OID = 653,
-    HMAC_SHA384_OID = 654,
-    HMAC_SHA512_OID = 655
-};
-
-
-enum Extensions_Sum {
-    BASIC_CA_OID    = 133,
-    ALT_NAMES_OID   = 131,
-    CRL_DIST_OID    = 145,
-    AUTH_INFO_OID   = 69, /* id-pe 1 */
-    AUTH_KEY_OID    = 149,
-    SUBJ_KEY_OID    = 128,
-    CERT_POLICY_OID = 146,
-    KEY_USAGE_OID   = 129,  /* 2.5.29.15 */
-    INHIBIT_ANY_OID = 168,  /* 2.5.29.54 */
-    EXT_KEY_USAGE_OID         = 151, /* 2.5.29.37 */
-    NAME_CONS_OID             = 144, /* 2.5.29.30 */
-    PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */
-    SUBJECT_INFO_ACCESS       = 79,  /* id-pe 11 */
-    POLICY_MAP_OID            = 147,
-    POLICY_CONST_OID          = 150,
-    ISSUE_ALT_NAMES_OID       = 132,
-    TLS_FEATURE_OID           = 92   /* id-pe 24 */
-};
-
-enum CertificatePolicy_Sum {
-    CP_ANY_OID      = 146  /* id-ce 32 0 */
-};
-
-enum SepHardwareName_Sum {
-    HW_NAME_OID     = 79   /* 1.3.6.1.5.5.7.8.4 from RFC 4108*/
-};
-
-enum AuthInfo_Sum {
-    AIA_OCSP_OID      = 116, /* 1.3.6.1.5.5.7.48.1 */
-    AIA_CA_ISSUER_OID = 117  /* 1.3.6.1.5.5.7.48.2 */
-};
-
-enum ExtKeyUsage_Sum { /* From RFC 5280 */
-    EKU_ANY_OID         = 151, /* 2.5.29.37.0, anyExtendedKeyUsage         */
-    EKU_SERVER_AUTH_OID = 71,  /* 1.3.6.1.5.5.7.3.1, id-kp-serverAuth      */
-    EKU_CLIENT_AUTH_OID = 72,  /* 1.3.6.1.5.5.7.3.2, id-kp-clientAuth      */
-    EKU_CODESIGNING_OID = 73,  /* 1.3.6.1.5.5.7.3.3, id-kp-codeSigning     */
-    EKU_EMAILPROTECT_OID = 74, /* 1.3.6.1.5.5.7.3.4, id-kp-emailProtection */
-    EKU_TIMESTAMP_OID   = 78,  /* 1.3.6.1.5.5.7.3.8, id-kp-timeStamping    */
-    EKU_OCSP_SIGN_OID   = 79   /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning     */
-};
-
-
-enum VerifyType {
-    NO_VERIFY   = 0,
-    VERIFY      = 1,
-    VERIFY_CRL  = 2,
-    VERIFY_OCSP = 3
-};
-
-#ifdef WOLFSSL_CERT_EXT
-enum KeyIdType {
-    SKID_TYPE = 0,
-    AKID_TYPE = 1
-};
-#endif
-
-/* Key usage extension bits (based on RFC 5280) */
-#define KEYUSE_DIGITAL_SIG    0x0080
-#define KEYUSE_CONTENT_COMMIT 0x0040
-#define KEYUSE_KEY_ENCIPHER   0x0020
-#define KEYUSE_DATA_ENCIPHER  0x0010
-#define KEYUSE_KEY_AGREE      0x0008
-#define KEYUSE_KEY_CERT_SIGN  0x0004
-#define KEYUSE_CRL_SIGN       0x0002
-#define KEYUSE_ENCIPHER_ONLY  0x0001
-#define KEYUSE_DECIPHER_ONLY  0x8000
-
-/* Extended Key Usage bits (internal mapping only) */
-#define EXTKEYUSE_USER        0x80
-#define EXTKEYUSE_OCSP_SIGN   0x40
-#define EXTKEYUSE_TIMESTAMP   0x20
-#define EXTKEYUSE_EMAILPROT   0x10
-#define EXTKEYUSE_CODESIGN    0x08
-#define EXTKEYUSE_CLIENT_AUTH 0x04
-#define EXTKEYUSE_SERVER_AUTH 0x02
-#define EXTKEYUSE_ANY         0x01
-
-typedef struct DNS_entry   DNS_entry;
-
-struct DNS_entry {
-    DNS_entry* next;   /* next on DNS list */
-    int        type;   /* i.e. ASN_DNS_TYPE */
-    int        len;    /* actual DNS len */
-    char*      name;   /* actual DNS name */
-};
-
-
-typedef struct Base_entry  Base_entry;
-
-struct Base_entry {
-    Base_entry* next;   /* next on name base list */
-    char*       name;   /* actual name base */
-    int         nameSz; /* name length */
-    byte        type;   /* Name base type (DNS or RFC822) */
-};
-
-#define DOMAIN_COMPONENT_MAX 10
-
-struct DecodedName {
-    char*   fullName;
-    int     fullNameLen;
-    int     entryCount;
-    int     cnIdx;
-    int     cnLen;
-    int     snIdx;
-    int     snLen;
-    int     cIdx;
-    int     cLen;
-    int     lIdx;
-    int     lLen;
-    int     stIdx;
-    int     stLen;
-    int     oIdx;
-    int     oLen;
-    int     ouIdx;
-    int     ouLen;
-    int     emailIdx;
-    int     emailLen;
-    int     uidIdx;
-    int     uidLen;
-    int     serialIdx;
-    int     serialLen;
-    int     dcIdx[DOMAIN_COMPONENT_MAX];
-    int     dcLen[DOMAIN_COMPONENT_MAX];
-    int     dcNum;
-    int     dcMode;
-};
-
-enum SignatureState {
-    SIG_STATE_BEGIN,
-    SIG_STATE_HASH,
-    SIG_STATE_KEY,
-    SIG_STATE_DO,
-    SIG_STATE_CHECK,
-};
-
-
-#ifdef HAVE_PK_CALLBACKS
-#ifdef HAVE_ECC
-    typedef int (*wc_CallbackEccVerify)(
-           const unsigned char* sig, unsigned int sigSz,
-           const unsigned char* hash, unsigned int hashSz,
-           const unsigned char* keyDer, unsigned int keySz,
-           int* result, void* ctx);
-#endif
-#ifndef NO_RSA
-    typedef int (*wc_CallbackRsaVerify)(
-           unsigned char* sig, unsigned int sigSz,
-           unsigned char** out,
-           const unsigned char* keyDer, unsigned int keySz,
-           void* ctx);
-#endif
-#endif /* HAVE_PK_CALLBACKS */
-
-struct SignatureCtx {
-    void* heap;
-    byte* digest;
-#ifndef NO_RSA
-    byte* out;
-    byte* plain;
-#endif
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    int verify;
-#endif
-    union {
-    #ifndef NO_RSA
-        struct RsaKey*      rsa;
-    #endif
-    #ifdef HAVE_ECC
-        struct ecc_key*     ecc;
-    #endif
-    #ifdef HAVE_ED25519
-        struct ed25519_key* ed25519;
-    #endif
-        void* ptr;
-    } key;
-    int devId;
-    int state;
-    int typeH;
-    int digestSz;
-    word32 keyOID;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV* asyncDev;
-    void* asyncCtx;
-#endif
-
-#ifdef HAVE_PK_CALLBACKS
-#ifdef HAVE_ECC
-    wc_CallbackEccVerify pkCbEcc;
-    void* pkCtxEcc;
-#endif
-#ifndef NO_RSA
-    wc_CallbackRsaVerify pkCbRsa;
-    void* pkCtxRsa;
-#endif
-#endif /* HAVE_PK_CALLBACKS */
-};
-
-enum CertSignState {
-    CERTSIGN_STATE_BEGIN,
-    CERTSIGN_STATE_DIGEST,
-    CERTSIGN_STATE_ENCODE,
-    CERTSIGN_STATE_DO,
-};
-
-struct CertSignCtx {
-    byte* sig;
-    byte* digest;
-    #ifndef NO_RSA
-        byte* encSig;
-        int encSigSz;
-    #endif
-    int state; /* enum CertSignState */
-};
-
-
-typedef struct DecodedCert DecodedCert;
-typedef struct DecodedName DecodedName;
-typedef struct Signer      Signer;
-#ifdef WOLFSSL_TRUST_PEER_CERT
-typedef struct TrustedPeerCert TrustedPeerCert;
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-typedef struct SignatureCtx SignatureCtx;
-typedef struct CertSignCtx  CertSignCtx;
-
-
-struct DecodedCert {
-    byte*   publicKey;
-    word32  pubKeySize;
-    int     pubKeyStored;
-    word32  certBegin;               /* offset to start of cert          */
-    word32  sigIndex;                /* offset to start of signature     */
-    word32  sigLength;               /* length of signature              */
-    word32  signatureOID;            /* sum of algorithm object id       */
-    word32  keyOID;                  /* sum of key algo  object id       */
-    int     version;                 /* cert version, 1 or 3             */
-    DNS_entry* altNames;             /* alt names list of dns entries    */
-#ifndef IGNORE_NAME_CONSTRAINTS
-    DNS_entry* altEmailNames;        /* alt names list of RFC822 entries */
-    Base_entry* permittedNames;      /* Permitted name bases             */
-    Base_entry* excludedNames;       /* Excluded name bases              */
-#endif /* IGNORE_NAME_CONSTRAINTS */
-    byte    subjectHash[KEYID_SIZE]; /* hash of all Names                */
-    byte    issuerHash[KEYID_SIZE];  /* hash of all Names                */
-#ifdef HAVE_OCSP
-    byte    issuerKeyHash[KEYID_SIZE]; /* hash of the public Key         */
-#endif /* HAVE_OCSP */
-    byte*   signature;               /* not owned, points into raw cert  */
-    char*   subjectCN;               /* CommonName                       */
-    int     subjectCNLen;            /* CommonName Length                */
-    char    subjectCNEnc;            /* CommonName Encoding              */
-    char    issuer[ASN_NAME_MAX];    /* full name including common name  */
-    char    subject[ASN_NAME_MAX];   /* full name including common name  */
-    int     verify;                  /* Default to yes, but could be off */
-    byte*   source;                  /* byte buffer holder cert, NOT owner */
-    word32  srcIdx;                  /* current offset into buffer       */
-    word32  maxIdx;                  /* max offset based on init size    */
-    void*   heap;                    /* for user memory overrides        */
-    byte    serial[EXTERNAL_SERIAL_SIZE];  /* raw serial number          */
-    int     serialSz;                /* raw serial bytes stored */
-    byte*   extensions;              /* not owned, points into raw cert  */
-    int     extensionsSz;            /* length of cert extensions */
-    word32  extensionsIdx;           /* if want to go back and parse later */
-    byte*   extAuthInfo;             /* Authority Information Access URI */
-    int     extAuthInfoSz;           /* length of the URI                */
-    byte*   extCrlInfo;              /* CRL Distribution Points          */
-    int     extCrlInfoSz;            /* length of the URI                */
-    byte    extSubjKeyId[KEYID_SIZE]; /* Subject Key ID                  */
-    byte    extAuthKeyId[KEYID_SIZE]; /* Authority Key ID                */
-    byte    pathLength;              /* CA basic constraint path length  */
-    word16  extKeyUsage;             /* Key usage bitfield               */
-    byte    extExtKeyUsage;          /* Extended Key usage bitfield      */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    byte*   extExtKeyUsageSrc;
-    word32  extExtKeyUsageSz;
-    word32  extExtKeyUsageCount;
-    byte*   extAuthKeyIdSrc;
-    word32  extAuthKeyIdSz;
-    byte*   extSubjKeyIdSrc;
-    word32  extSubjKeyIdSz;
-#endif
-
-#if defined(HAVE_ECC) || defined(HAVE_ED25519)
-    word32  pkCurveOID;           /* Public Key's curve OID */
-#endif /* HAVE_ECC */
-    byte*   beforeDate;
-    int     beforeDateLen;
-    byte*   afterDate;
-    int     afterDateLen;
-#ifdef HAVE_PKCS7
-    byte*   issuerRaw;               /* pointer to issuer inside source */
-    int     issuerRawLen;
-#endif
-#ifndef IGNORE_NAME_CONSTRAINT
-    byte*   subjectRaw;               /* pointer to subject inside source */
-    int     subjectRawLen;
-#endif
-#ifdef WOLFSSL_CERT_GEN
-    /* easy access to subject info for other sign */
-    char*   subjectSN;
-    int     subjectSNLen;
-    char    subjectSNEnc;
-    char*   subjectC;
-    int     subjectCLen;
-    char    subjectCEnc;
-    char*   subjectL;
-    int     subjectLLen;
-    char    subjectLEnc;
-    char*   subjectST;
-    int     subjectSTLen;
-    char    subjectSTEnc;
-    char*   subjectO;
-    int     subjectOLen;
-    char    subjectOEnc;
-    char*   subjectOU;
-    int     subjectOULen;
-    char    subjectOUEnc;
-    char*   subjectEmail;
-    int     subjectEmailLen;
-#endif /* WOLFSSL_CERT_GEN */
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    DecodedName issuerName;
-    DecodedName subjectName;
-#endif /* OPENSSL_EXTRA */
-#ifdef WOLFSSL_SEP
-    int     deviceTypeSz;
-    byte*   deviceType;
-    int     hwTypeSz;
-    byte*   hwType;
-    int     hwSerialNumSz;
-    byte*   hwSerialNum;
-#endif /* WOLFSSL_SEP */
-#ifdef WOLFSSL_CERT_EXT
-    char    extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ];
-    int     extCertPoliciesNb;
-#endif /* WOLFSSL_CERT_EXT */
-
-    Signer* ca;
-    SignatureCtx sigCtx;
-
-    /* Option Bits */
-    byte subjectCNStored : 1;      /* have we saved a copy we own */
-    byte extSubjKeyIdSet : 1;      /* Set when the SKID was read from cert */
-    byte extAuthKeyIdSet : 1;      /* Set when the AKID was read from cert */
-#ifndef IGNORE_NAME_CONSTRAINTS
-    byte extNameConstraintSet : 1;
-#endif
-    byte isCA : 1;                 /* CA basic constraint true */
-    byte pathLengthSet : 1;        /* CA basic const path length set */
-    byte weOwnAltNames : 1;        /* altNames haven't been given to copy */
-    byte extKeyUsageSet : 1;
-    byte extExtKeyUsageSet : 1;    /* Extended Key Usage set */
-    byte extCRLdistSet : 1;
-    byte extAuthInfoSet : 1;
-    byte extBasicConstSet : 1;
-    byte extSubjAltNameSet : 1;
-    byte inhibitAnyOidSet : 1;
-#ifdef WOLFSSL_SEP
-    byte extCertPolicySet : 1;
-#endif
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    byte extCRLdistCrit : 1;
-    byte extAuthInfoCrit : 1;
-    byte extBasicConstCrit : 1;
-    byte extSubjAltNameCrit : 1;
-    byte extAuthKeyIdCrit : 1;
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        byte extNameConstraintCrit : 1;
-    #endif
-    byte extSubjKeyIdCrit : 1;
-    byte extKeyUsageCrit : 1;
-    byte extExtKeyUsageCrit : 1;
-#endif /* OPENSSL_EXTRA */
-#ifdef WOLFSSL_SEP
-    byte extCertPolicyCrit : 1;
-#endif
-
-};
-
-
-#ifdef NO_SHA
-    #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-#else
-    #define SIGNER_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-#endif
-
-/* CA Signers */
-/* if change layout change PERSIST_CERT_CACHE functions too */
-struct Signer {
-    word32  pubKeySize;
-    word32  keyOID;                  /* key type */
-    word16  keyUsage;
-    byte    pathLength;
-    byte    pathLengthSet;
-    byte*   publicKey;
-    int     nameLen;
-    char*   name;                    /* common name */
-#ifndef IGNORE_NAME_CONSTRAINTS
-        Base_entry* permittedNames;
-        Base_entry* excludedNames;
-#endif /* IGNORE_NAME_CONSTRAINTS */
-    byte    subjectNameHash[SIGNER_DIGEST_SIZE];
-                                     /* sha hash of names in certificate */
-    #ifndef NO_SKID
-        byte    subjectKeyIdHash[SIGNER_DIGEST_SIZE];
-                                     /* sha hash of names in certificate */
-    #endif
-#ifdef WOLFSSL_SIGNER_DER_CERT
-    DerBuffer* derCert;
-#endif
-    Signer* next;
-};
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* used for having trusted peer certs rather then CA */
-struct TrustedPeerCert {
-    int     nameLen;
-    char*   name;                    /* common name */
-    #ifndef IGNORE_NAME_CONSTRAINTS
-        Base_entry* permittedNames;
-        Base_entry* excludedNames;
-    #endif /* IGNORE_NAME_CONSTRAINTS */
-    byte    subjectNameHash[SIGNER_DIGEST_SIZE];
-                                     /* sha hash of names in certificate */
-    #ifndef NO_SKID
-        byte    subjectKeyIdHash[SIGNER_DIGEST_SIZE];
-                                     /* sha hash of names in certificate */
-    #endif
-    word32 sigLen;
-    byte*  sig;
-    struct TrustedPeerCert* next;
-};
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-/* for testing or custom openssl wrappers */
-#if defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \
-    defined(OPENSSL_EXTRA_X509_SMALL)
-    #define WOLFSSL_ASN_API WOLFSSL_API
-#else
-    #define WOLFSSL_ASN_API WOLFSSL_LOCAL
-#endif
-
-WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der,
-                                word32* derSz);
-
-WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*);
-#ifndef IGNORE_NAME_CONSTRAINTS
-    WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*);
-#endif /* IGNORE_NAME_CONSTRAINTS */
-WOLFSSL_ASN_API void InitDecodedCert(DecodedCert*, byte*, word32, void*);
-WOLFSSL_ASN_API void FreeDecodedCert(DecodedCert*);
-WOLFSSL_ASN_API int  ParseCert(DecodedCert*, int type, int verify, void* cm);
-
-WOLFSSL_LOCAL int DecodePolicyOID(char *o, word32 oSz, byte *in, word32 inSz);
-WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm);
-WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify);
-
-WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);
-WOLFSSL_LOCAL Signer* MakeSigner(void*);
-WOLFSSL_LOCAL void    FreeSigner(Signer*, void*);
-WOLFSSL_LOCAL void    FreeSignerTable(Signer**, int, void*);
-#ifdef WOLFSSL_TRUST_PEER_CERT
-WOLFSSL_LOCAL void    FreeTrustedPeer(TrustedPeerCert*, void*);
-WOLFSSL_LOCAL void    FreeTrustedPeerTable(TrustedPeerCert**, int, void*);
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length);
-WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx,
-                                      word32 length);
-WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int);
-WOLFSSL_ASN_API int UnTraditionalEnc(byte* key, word32 keySz, byte* out,
-        word32* outSz, const char* password, int passwordSz, int vPKCS,
-        int vAlgo, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap);
-WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz);
-WOLFSSL_LOCAL int EncryptContent(byte* input, word32 sz, byte* out, word32* outSz,
-        const char* password,int passwordSz, int vPKCS, int vAlgo,
-        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap);
-WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID,
-        word32* oidSz, int* algoID, void* heap);
-
-typedef struct tm wolfssl_tm;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || \
-    defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len);
-#endif
-WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
-                                                 wolfssl_tm* certTime, int* idx);
-WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);
-
-/* ASN.1 helper functions */
-#ifdef WOLFSSL_CERT_GEN
-WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name);
-#endif
-WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number,
-                              word32 maxIdx);
-WOLFSSL_LOCAL char* GetSigName(int oid);
-WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
-                           word32 maxIdx);
-WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
-                             word32 maxIdx);
-WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
-                        word32 maxIdx);
-WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
-                              int* version, word32 maxIdx);
-WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
-                        word32 maxIdx);
-#ifdef HAVE_OID_ENCODING
-    WOLFSSL_LOCAL int EncodeObjectId(const word16* in, word32 inSz,
-        byte* out, word32* outSz);
-#endif
-#ifdef HAVE_OID_DECODING
-    WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz,
-        word16* out, word32* outSz);
-#endif
-WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
-                              word32 oidType, word32 maxIdx);
-WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
-                           word32 oidType, word32 maxIdx);
-WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output);
-WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output);
-WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output);
-WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output);
-WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output);
-WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output);
-WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz);
-WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
-WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
-    int maxSnSz);
-WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx,
-    byte* serial, int* serialSz, word32 maxIdx);
-WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
-                             int maxIdx);
-WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der);
-WOLFSSL_LOCAL int RsaPublicKeyDerSize(RsaKey* key, int with_header);
-
-#ifdef HAVE_ECC
-    /* ASN sig helpers */
-    WOLFSSL_LOCAL int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r,
-                                      mp_int* s);
-    WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen,
-                                       mp_int* r, mp_int* s);
-#endif
-
-WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId);
-WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx);
-
-#ifndef NO_CERTS
-
-WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type,
-                          DerBuffer** pDer, void* heap, EncryptedInfo* info,
-                          int* eccKey);
-WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap);
-WOLFSSL_LOCAL void FreeDer(DerBuffer** der);
-
-#endif /* !NO_CERTS */
-
-#ifdef WOLFSSL_CERT_GEN
-
-enum cert_enums {
-    NAME_ENTRIES    =  8,
-    JOINT_LEN       =  2,
-    EMAIL_JOINT_LEN =  9,
-    PILOT_JOINT_LEN =  10,
-    RSA_KEY         = 10,
-    NTRU_KEY        = 11,
-    ECC_KEY         = 12,
-    ED25519_KEY     = 13
-};
-
-#endif /* WOLFSSL_CERT_GEN */
-
-
-
-/* for pointer use */
-typedef struct CertStatus CertStatus;
-
-#ifdef HAVE_OCSP
-
-enum Ocsp_Response_Status {
-    OCSP_SUCCESSFUL        = 0, /* Response has valid confirmations */
-    OCSP_MALFORMED_REQUEST = 1, /* Illegal confirmation request */
-    OCSP_INTERNAL_ERROR    = 2, /* Internal error in issuer */
-    OCSP_TRY_LATER         = 3, /* Try again later */
-    OCSP_SIG_REQUIRED      = 5, /* Must sign the request (4 is skipped) */
-    OCSP_UNAUTHROIZED      = 6  /* Request unauthorized */
-};
-
-
-enum Ocsp_Cert_Status {
-    CERT_GOOD    = 0,
-    CERT_REVOKED = 1,
-    CERT_UNKNOWN = 2
-};
-
-
-enum Ocsp_Sums {
-    OCSP_BASIC_OID = 117,
-    OCSP_NONCE_OID = 118
-};
-
-#ifdef OPENSSL_EXTRA
-enum Ocsp_Verify_Error {
-    OCSP_VERIFY_ERROR_NONE = 0,
-    OCSP_BAD_ISSUER = 1
-};
-#endif
-
-
-typedef struct OcspRequest  OcspRequest;
-typedef struct OcspResponse OcspResponse;
-
-
-struct CertStatus {
-    CertStatus* next;
-
-    byte serial[EXTERNAL_SERIAL_SIZE];
-    int serialSz;
-
-    int status;
-
-    byte thisDate[MAX_DATE_SIZE];
-    byte nextDate[MAX_DATE_SIZE];
-    byte thisDateFormat;
-    byte nextDateFormat;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    byte* thisDateAsn;
-    byte* nextDateAsn;
-#endif
-
-    byte*  rawOcspResponse;
-    word32 rawOcspResponseSz;
-};
-
-
-struct OcspResponse {
-    int     responseStatus;  /* return code from Responder */
-
-    byte*   response;        /* Pointer to beginning of OCSP Response */
-    word32  responseSz;      /* length of the OCSP Response */
-
-    byte    producedDate[MAX_DATE_SIZE];
-                             /* Date at which this response was signed */
-    byte    producedDateFormat; /* format of the producedDate */
-    byte*   issuerHash;
-    byte*   issuerKeyHash;
-
-    byte*   cert;
-    word32  certSz;
-
-    byte*   sig;             /* Pointer to sig in source */
-    word32  sigSz;           /* Length in octets for the sig */
-    word32  sigOID;          /* OID for hash used for sig */
-
-    CertStatus* status;      /* certificate status to fill out */
-
-    byte*   nonce;           /* pointer to nonce inside ASN.1 response */
-    int     nonceSz;         /* length of the nonce string */
-
-    byte*   source;          /* pointer to source buffer, not owned */
-    word32  maxIdx;          /* max offset based on init size */
-
-#ifdef OPENSSL_EXTRA
-    int     verifyError;
-#endif
-};
-
-
-struct OcspRequest {
-    byte   issuerHash[KEYID_SIZE];
-    byte   issuerKeyHash[KEYID_SIZE];
-    byte*  serial;   /* copy of the serial number in source cert */
-    int    serialSz;
-    byte*  url;      /* copy of the extAuthInfo in source cert */
-    int    urlSz;
-
-    byte   nonce[MAX_OCSP_NONCE_SZ];
-    int    nonceSz;
-    void*  heap;
-    void*  ssl;
-};
-
-
-WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
-WOLFSSL_LOCAL int  OcspResponseDecode(OcspResponse*, void*, void* heap, int);
-
-WOLFSSL_LOCAL int    InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*);
-WOLFSSL_LOCAL void   FreeOcspRequest(OcspRequest*);
-WOLFSSL_LOCAL int    EncodeOcspRequest(OcspRequest*, byte*, word32);
-WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32);
-
-
-WOLFSSL_LOCAL int  CompareOcspReqResp(OcspRequest*, OcspResponse*);
-
-
-#endif /* HAVE_OCSP */
-
-
-/* for pointer use */
-typedef struct RevokedCert RevokedCert;
-
-#ifdef HAVE_CRL
-
-struct RevokedCert {
-    byte         serialNumber[EXTERNAL_SERIAL_SIZE];
-    int          serialSz;
-    RevokedCert* next;
-};
-
-typedef struct DecodedCRL DecodedCRL;
-
-struct DecodedCRL {
-    word32  certBegin;               /* offset to start of cert          */
-    word32  sigIndex;                /* offset to start of signature     */
-    word32  sigLength;               /* length of signature              */
-    word32  signatureOID;            /* sum of algorithm object id       */
-    byte*   signature;               /* pointer into raw source, not owned */
-    byte    issuerHash[SIGNER_DIGEST_SIZE]; /* issuer hash               */
-    byte    crlHash[SIGNER_DIGEST_SIZE]; /* raw crl data hash            */
-    byte    lastDate[MAX_DATE_SIZE]; /* last date updated  */
-    byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
-    byte    lastDateFormat;          /* format of last date */
-    byte    nextDateFormat;          /* format of next date */
-    RevokedCert* certs;              /* revoked cert list  */
-    int          totalCerts;         /* number on list     */
-    void*   heap;
-};
-
-WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap);
-WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx,
-                                      const byte* toBeSigned, word32 tbsSz,
-                                      const byte* signature, word32 sigSz,
-                                      word32 signatureOID, Signer *ca,
-                                      void* heap);
-WOLFSSL_LOCAL int  ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm);
-WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*);
-
-
-#endif /* HAVE_CRL */
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* !NO_ASN */
-
-
-#if !defined(NO_ASN) || !defined(NO_PWDBASED)
-
-#ifndef MAX_KEY_SIZE
-    #define MAX_KEY_SIZE    64  /* MAX PKCS Key length */
-#endif
-#ifndef MAX_UNICODE_SZ
-    #define MAX_UNICODE_SZ  256
-#endif
-
-enum PBESTypes {
-    PBE_MD5_DES      = 0,
-    PBE_SHA1_RC4_128 = 1,
-    PBE_SHA1_DES     = 2,
-    PBE_SHA1_DES3    = 3,
-    PBE_AES256_CBC   = 4,
-
-    PBE_SHA1_RC4_128_SUM = 657,
-    PBE_SHA1_DES3_SUM    = 659,
-    PBES2            = 13       /* algo ID */
-};
-
-enum PKCSTypes {
-    PKCS5v2             =   6,     /* PKCS #5 v2.0 */
-    PKCS12v1            =  12,     /* PKCS #12 */
-    PKCS5               =   5,     /* PKCS oid tag */
-    PKCS8v0             =   0,     /* default PKCS#8 version */
-};
-
-#endif /* !NO_ASN || !NO_PWDBASED */
-
-#endif /* WOLF_CRYPT_ASN_H */
-
--- a/wolfssl/wolfcrypt/asn_public.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,466 +0,0 @@
-/* asn_public.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/asn_public.h
-*/
-
-#ifndef WOLF_CRYPT_ASN_PUBLIC_H
-#define WOLF_CRYPT_ASN_PUBLIC_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* guard on redeclaration */
-#ifndef WC_ECCKEY_TYPE_DEFINED
-    typedef struct ecc_key ecc_key;
-    #define WC_ECCKEY_TYPE_DEFINED
-#endif
-#ifndef WC_ED25519KEY_TYPE_DEFINED
-    typedef struct ed25519_key ed25519_key;
-    #define WC_ED25519KEY_TYPE_DEFINED
-#endif
-#ifndef WC_RSAKEY_TYPE_DEFINED
-    typedef struct RsaKey RsaKey;
-    #define WC_RSAKEY_TYPE_DEFINED
-#endif
-#ifndef WC_RNG_TYPE_DEFINED
-    typedef struct WC_RNG WC_RNG;
-    #define WC_RNG_TYPE_DEFINED
-#endif
-
-
-/* Certificate file Type */
-enum CertType {
-    CERT_TYPE       = 0,
-    PRIVATEKEY_TYPE,
-    DH_PARAM_TYPE,
-    DSA_PARAM_TYPE,
-    CRL_TYPE,
-    CA_TYPE,
-    ECC_PRIVATEKEY_TYPE,
-    DSA_PRIVATEKEY_TYPE,
-    CERTREQ_TYPE,
-    DSA_TYPE,
-    ECC_TYPE,
-    RSA_TYPE,
-    PUBLICKEY_TYPE,
-    RSA_PUBLICKEY_TYPE,
-    ECC_PUBLICKEY_TYPE,
-    TRUSTED_PEER_TYPE,
-    EDDSA_PRIVATEKEY_TYPE,
-    ED25519_TYPE,
-    PKCS12_TYPE
-};
-
-
-/* Signature type, by OID sum */
-enum Ctc_SigType {
-    CTC_SHAwDSA      = 517,
-    CTC_MD2wRSA      = 646,
-    CTC_MD5wRSA      = 648,
-    CTC_SHAwRSA      = 649,
-    CTC_SHAwECDSA    = 520,
-    CTC_SHA224wRSA   = 658,
-    CTC_SHA224wECDSA = 523,
-    CTC_SHA256wRSA   = 655,
-    CTC_SHA256wECDSA = 524,
-    CTC_SHA384wRSA   = 656,
-    CTC_SHA384wECDSA = 525,
-    CTC_SHA512wRSA   = 657,
-    CTC_SHA512wECDSA = 526,
-    CTC_ED25519      = 256
-};
-
-enum Ctc_Encoding {
-    CTC_UTF8       = 0x0c, /* utf8      */
-    CTC_PRINTABLE  = 0x13  /* printable */
-};
-
-#ifndef WC_CTC_MAX_ALT_SIZE
-    #define WC_CTC_MAX_ALT_SIZE 16384
-#endif
-
-enum Ctc_Misc {
-    CTC_COUNTRY_SIZE  =     2,
-    CTC_NAME_SIZE     =    64,
-    CTC_DATE_SIZE     =    32,
-    CTC_MAX_ALT_SIZE  = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */
-    CTC_SERIAL_SIZE   =    16,
-#ifdef WOLFSSL_CERT_EXT
-    /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum
-     * We support only hash */
-    CTC_MAX_SKID_SIZE = 32, /* SHA256_DIGEST_SIZE */
-    CTC_MAX_AKID_SIZE = 32, /* SHA256_DIGEST_SIZE */
-    CTC_MAX_CERTPOL_SZ = 64,
-    CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */
-#endif /* WOLFSSL_CERT_EXT */
-};
-
-/* DER buffer */
-typedef struct DerBuffer {
-    byte*  buffer;
-    void*  heap;
-    word32 length;
-    int    type;    /* enum CertType */
-    int    dynType; /* DYNAMIC_TYPE_* */
-} DerBuffer;
-
-enum {
-    IV_SZ   = 32,                   /* max iv sz */
-    NAME_SZ = 80,                   /* max one line */
-
-    PEM_PASS_READ  = 0,
-    PEM_PASS_WRITE = 1,
-};
-
-
-typedef int (pem_password_cb)(char* passwd, int sz, int rw, void* userdata);
-
-typedef struct EncryptedInfo {
-    pem_password_cb* passwd_cb;
-    void*            passwd_userdata;
-
-    long     consumed;         /* tracks PEM bytes consumed */
-
-    int      cipherType;
-    word32   keySz;
-    word32   ivSz;             /* salt or encrypted IV size */
-
-    char     name[NAME_SZ];    /* cipher name, such as "DES-CBC" */
-    byte     iv[IV_SZ];        /* salt or encrypted IV */
-
-    int      set:1;            /* if encryption set */
-} EncryptedInfo;
-
-
-#ifdef WOLFSSL_CERT_GEN
-
-#ifdef WOLFSSL_EKU_OID
-    #ifndef CTC_MAX_EKU_NB
-        #define CTC_MAX_EKU_NB 1
-    #endif
-    #ifndef CTC_MAX_EKU_OID_SZ
-        #define CTC_MAX_EKU_OID_SZ 30
-    #endif
-#else
-    #undef CTC_MAX_EKU_OID_SZ
-    #define CTC_MAX_EKU_OID_SZ 0
-#endif
-
-
-#ifdef WOLFSSL_MULTI_ATTRIB
-#ifndef CTC_MAX_ATTRIB
-    #define CTC_MAX_ATTRIB 4
-#endif
-
-/* ASN Encoded Name field */
-typedef struct NameAttrib {
-    int  sz;                     /* actual string value length */
-    int  id;                     /* id of name */
-    int  type;                   /* enc of name */
-    char value[CTC_NAME_SIZE];   /* name */
-} NameAttrib;
-#endif /* WOLFSSL_MULTI_ATTRIB */
-
-
-typedef struct CertName {
-    char country[CTC_NAME_SIZE];
-    char countryEnc;
-    char state[CTC_NAME_SIZE];
-    char stateEnc;
-    char locality[CTC_NAME_SIZE];
-    char localityEnc;
-    char sur[CTC_NAME_SIZE];
-    char surEnc;
-    char org[CTC_NAME_SIZE];
-    char orgEnc;
-    char unit[CTC_NAME_SIZE];
-    char unitEnc;
-    char commonName[CTC_NAME_SIZE];
-    char commonNameEnc;
-    char email[CTC_NAME_SIZE];  /* !!!! email has to be last !!!! */
-#ifdef WOLFSSL_MULTI_ATTRIB
-    NameAttrib name[CTC_MAX_ATTRIB];
-#endif
-} CertName;
-
-
-/* for user to fill for certificate generation */
-typedef struct Cert {
-    int      version;                   /* x509 version  */
-    byte     serial[CTC_SERIAL_SIZE];   /* serial number */
-    int      serialSz;                  /* serial size */
-    int      sigType;                   /* signature algo type */
-    CertName issuer;                    /* issuer info */
-    int      daysValid;                 /* validity days */
-    int      selfSigned;                /* self signed flag */
-    CertName subject;                   /* subject info */
-    int      isCA;                      /* is this going to be a CA */
-    /* internal use only */
-    int      bodySz;                    /* pre sign total size */
-    int      keyType;                   /* public key type of subject */
-#ifdef WOLFSSL_ALT_NAMES
-    byte     altNames[CTC_MAX_ALT_SIZE]; /* altNames copy */
-    int      altNamesSz;                 /* altNames size in bytes */
-    byte     beforeDate[CTC_DATE_SIZE];  /* before date copy */
-    int      beforeDateSz;               /* size of copy */
-    byte     afterDate[CTC_DATE_SIZE];   /* after date copy */
-    int      afterDateSz;                /* size of copy */
-#endif
-#ifdef WOLFSSL_CERT_EXT
-    byte    skid[CTC_MAX_SKID_SIZE];     /* Subject Key Identifier */
-    int     skidSz;                      /* SKID size in bytes */
-    byte    akid[CTC_MAX_AKID_SIZE];     /* Authority Key Identifier */
-    int     akidSz;                      /* AKID size in bytes */
-    word16  keyUsage;                    /* Key Usage */
-    byte    extKeyUsage;                 /* Extended Key Usage */
-#ifdef WOLFSSL_EKU_OID
-    /* Extended Key Usage OIDs */
-    byte    extKeyUsageOID[CTC_MAX_EKU_NB][CTC_MAX_EKU_OID_SZ];
-    byte    extKeyUsageOIDSz[CTC_MAX_EKU_NB];
-#endif
-    char    certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ];
-    word16  certPoliciesNb;              /* Number of Cert Policy */
-#endif
-#ifdef WOLFSSL_CERT_REQ
-    char     challengePw[CTC_NAME_SIZE];
-#endif
-    void*   heap; /* heap hint */
-} Cert;
-
-
-
-/* Initialize and Set Certificate defaults:
-   version    = 3 (0x2)
-   serial     = 0 (Will be randomly generated)
-   sigType    = SHA_WITH_RSA
-   issuer     = blank
-   daysValid  = 500
-   selfSigned = 1 (true) use subject as issuer
-   subject    = blank
-   isCA       = 0 (false)
-   keyType    = RSA_KEY (default)
-*/
-WOLFSSL_API int wc_InitCert(Cert*);
-WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz,
-                                int keyType, void* key, WC_RNG* rng);
-WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
-                             ecc_key*, WC_RNG*);
-#ifdef WOLFSSL_CERT_REQ
-    WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz,
-                                       int, void*);
-    WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz,
-                                    RsaKey*, ecc_key*);
-#endif
-WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer,
-                                word32 buffSz, int keyType, void* key,
-                                WC_RNG* rng);
-WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer,
-                             word32 derSz, RsaKey*, ecc_key*, WC_RNG*);
-WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*,
-                             WC_RNG*);
-WOLFSSL_API int wc_SetIssuer(Cert*, const char*);
-WOLFSSL_API int wc_SetSubject(Cert*, const char*);
-#ifdef WOLFSSL_ALT_NAMES
-    WOLFSSL_API int wc_SetAltNames(Cert*, const char*);
-#endif
-WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int);
-WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int);
-WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int);
-WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int);
-
-#ifndef NO_ASN_TIME
-WOLFSSL_API int wc_GetCertDates(Cert* cert, struct tm* before, 
-    struct tm* after);
-#endif
-
-#ifdef WOLFSSL_CERT_EXT
-WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType,
-                                                void* key);
-WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
-                                             ecc_key *eckey);
-WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz);
-WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file);
-WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType,
-                                                   void* key);
-WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey,
-                                                ecc_key *eckey);
-WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file);
-
-#ifdef HAVE_NTRU
-WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey,
-                                                    word16 ntruKeySz);
-#endif
-
-/* Set the KeyUsage.
- * Value is a string separated tokens with ','. Accepted tokens are :
- * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign,
- * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly.
- *
- * nonRepudiation and contentCommitment are for the same usage.
- */
-WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value);
-
-/* Set ExtendedKeyUsage
- * Value is a string separated tokens with ','. Accepted tokens are :
- * any,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning
- */
-WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value);
-
-
-#ifdef WOLFSSL_EKU_OID
-/* Set ExtendedKeyUsage with unique OID
- * oid is expected to be in byte representation
- */
-WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz,
-                                     byte idx, void* heap);
-#endif /* WOLFSSL_EKU_OID */
-#endif /* WOLFSSL_CERT_EXT */
-
-    #ifdef HAVE_NTRU
-        WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz,
-                                     const byte* ntruKey, word16 keySz,
-                                     WC_RNG*);
-    #endif
-
-#endif /* WOLFSSL_CERT_GEN */
-
-WOLFSSL_API int wc_GetDateInfo(const byte* certDate, int certDateSz, 
-    const byte** date, byte* format, int* length);
-#ifndef NO_ASN_TIME
-WOLFSSL_API int wc_GetDateAsCalendarTime(const byte* date, int length,
-    byte format, struct tm* time);
-#endif
-
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
-
-    WOLFSSL_API int wc_PemGetHeaderFooter(int type, const char** header, 
-        const char** footer);
-
-#endif
-
-#ifdef WOLFSSL_PEM_TO_DER
-    WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type,
-              DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey);
-
-    WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int,
-                                   unsigned char*, int, const char*);
-    WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int,
-                                    unsigned char*, int, int);
-#endif /* WOLFSSL_PEM_TO_DER */
-
-#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
-    #ifndef NO_FILESYSTEM
-        WOLFSSL_API int wc_PemPubKeyToDer(const char* fileName,
-                                          unsigned char* derBuf, int derSz);
-    #endif
-
-    WOLFSSL_API int wc_PubKeyPemToDer(const unsigned char*, int,
-                                      unsigned char*, int);
-#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
-
-#ifdef WOLFSSL_CERT_GEN
-    #ifndef NO_FILESYSTEM
-        WOLFSSL_API int wc_PemCertToDer(const char* fileName,
-                                        unsigned char* derBuf, int derSz);
-    #endif
-#endif /* WOLFSSL_CERT_GEN */
-
-#ifdef WOLFSSL_DER_TO_PEM
-    WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output,
-                                word32 outputSz, int type);
-    WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output,
-                                word32 outputSz, byte *cipherIno, int type);
-#endif
-
-#ifdef HAVE_ECC
-    /* private key helpers */
-    WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,
-                                           ecc_key*, word32);
-    WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen);
-    WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output,
-                                          word32 inLen);
-    WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output,
-                                            word32* outLen);
-
-    /* public key helper */
-    WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,
-                                              ecc_key*, word32);
-    WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output,
-                                         word32 inLen, int with_AlgCurve);
-#endif
-
-#ifdef HAVE_ED25519
-    /* private key helpers */
-    WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*,
-                                               ed25519_key*, word32);
-    WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output,
-                                       word32 inLen);
-    WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output,
-                                              word32 inLen);
-
-    /* public key helper */
-    WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*,
-                                              ed25519_key*, word32);
-    #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
-        WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output,
-                                               word32 inLen, int with_AlgCurve);
-    #endif
-#endif
-
-/* DER encode signature */
-WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest,
-                                      word32 digSz, int hashOID);
-WOLFSSL_API int wc_GetCTC_HashOID(int type);
-
-WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input,
-                                             word32* inOutIdx, word32 sz);
-WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz,
-       byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz);
-
-#ifndef NO_ASN_TIME
-/* Time */
-/* Returns seconds (Epoch/UTC)
- * timePtr: is "time_t", which is typically "long"
- * Example:
-    long lTime;
-    rc = wc_GetTime(&lTime, (word32)sizeof(lTime));
-*/
-WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize);
-#endif
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    WOLFSSL_API int wc_EncryptedInfoGet(EncryptedInfo* info,
-        const char* cipherInfo);
-#endif
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_ASN_PUBLIC_H */
-
-
--- a/wolfssl/wolfcrypt/async.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfssl/wolfcrypt/blake2-impl.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
-
-   To the extent possible under law, the author(s) have dedicated all copyright
-   and related and neighboring rights to this software to the public domain
-   worldwide. This software is distributed without any warranty.
-
-   You should have received a copy of the CC0 Public Domain Dedication along with
-   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-*/
-/* blake2-impl.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLFCRYPT_BLAKE2_IMPL_H
-#define WOLFCRYPT_BLAKE2_IMPL_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-static WC_INLINE word32 load32( const void *src )
-{
-#if defined(LITTLE_ENDIAN_ORDER)
-  return *( word32 * )( src );
-#else
-  const byte *p = ( byte * )src;
-  word32 w = *p++;
-  w |= ( word32 )( *p++ ) <<  8;
-  w |= ( word32 )( *p++ ) << 16;
-  w |= ( word32 )( *p++ ) << 24;
-  return w;
-#endif
-}
-
-static WC_INLINE word64 load64( const void *src )
-{
-#if defined(LITTLE_ENDIAN_ORDER)
-  return *( word64 * )( src );
-#else
-  const byte *p = ( byte * )src;
-  word64 w = *p++;
-  w |= ( word64 )( *p++ ) <<  8;
-  w |= ( word64 )( *p++ ) << 16;
-  w |= ( word64 )( *p++ ) << 24;
-  w |= ( word64 )( *p++ ) << 32;
-  w |= ( word64 )( *p++ ) << 40;
-  w |= ( word64 )( *p++ ) << 48;
-  w |= ( word64 )( *p++ ) << 56;
-  return w;
-#endif
-}
-
-static WC_INLINE void store32( void *dst, word32 w )
-{
-#if defined(LITTLE_ENDIAN_ORDER)
-  *( word32 * )( dst ) = w;
-#else
-  byte *p = ( byte * )dst;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w;
-#endif
-}
-
-static WC_INLINE void store64( void *dst, word64 w )
-{
-#if defined(LITTLE_ENDIAN_ORDER)
-  *( word64 * )( dst ) = w;
-#else
-  byte *p = ( byte * )dst;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w;
-#endif
-}
-
-static WC_INLINE word64 load48( const void *src )
-{
-  const byte *p = ( const byte * )src;
-  word64 w = *p++;
-  w |= ( word64 )( *p++ ) <<  8;
-  w |= ( word64 )( *p++ ) << 16;
-  w |= ( word64 )( *p++ ) << 24;
-  w |= ( word64 )( *p++ ) << 32;
-  w |= ( word64 )( *p++ ) << 40;
-  return w;
-}
-
-static WC_INLINE void store48( void *dst, word64 w )
-{
-  byte *p = ( byte * )dst;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w; w >>= 8;
-  *p++ = ( byte )w;
-}
-
-static WC_INLINE word32 rotl32( const word32 w, const unsigned c )
-{
-  return ( w << c ) | ( w >> ( 32 - c ) );
-}
-
-static WC_INLINE word64 rotl64( const word64 w, const unsigned c )
-{
-  return ( w << c ) | ( w >> ( 64 - c ) );
-}
-
-static WC_INLINE word32 rotr32( const word32 w, const unsigned c )
-{
-  return ( w >> c ) | ( w << ( 32 - c ) );
-}
-
-static WC_INLINE word64 rotr64( const word64 w, const unsigned c )
-{
-  return ( w >> c ) | ( w << ( 64 - c ) );
-}
-
-/* prevents compiler optimizing out memset() */
-static WC_INLINE void secure_zero_memory( void *v, word64 n )
-{
-  volatile byte *p = ( volatile byte * )v;
-
-  while( n-- ) *p++ = 0;
-}
-
-#endif  /* WOLFCRYPT_BLAKE2_IMPL_H */
-
-
--- a/wolfssl/wolfcrypt/blake2-int.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
-   BLAKE2 reference source code package - reference C implementations
-
-   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
-
-   To the extent possible under law, the author(s) have dedicated all copyright
-   and related and neighboring rights to this software to the public domain
-   worldwide. This software is distributed without any warranty.
-
-   You should have received a copy of the CC0 Public Domain Dedication along with
-   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-*/
-/* blake2-int.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-
-#ifndef WOLFCRYPT_BLAKE2_INT_H
-#define WOLFCRYPT_BLAKE2_INT_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-
-#if defined(_MSC_VER)
-    #define ALIGN(x) __declspec(align(x))
-#elif defined(__GNUC__)
-    #define ALIGN(x) __attribute__((aligned(x)))
-#else
-    #define ALIGN(x)
-#endif
-
-
-#if defined(__cplusplus)
-    extern "C" {
-#endif
-
-  enum blake2s_constant
-  {
-    BLAKE2S_BLOCKBYTES = 64,
-    BLAKE2S_OUTBYTES   = 32,
-    BLAKE2S_KEYBYTES   = 32,
-    BLAKE2S_SALTBYTES  = 8,
-    BLAKE2S_PERSONALBYTES = 8
-  };
-
-  enum blake2b_constant
-  {
-    BLAKE2B_BLOCKBYTES = 128,
-    BLAKE2B_OUTBYTES   = 64,
-    BLAKE2B_KEYBYTES   = 64,
-    BLAKE2B_SALTBYTES  = 16,
-    BLAKE2B_PERSONALBYTES = 16
-  };
-
-#pragma pack(push, 1)
-  typedef struct __blake2s_param
-  {
-    byte  digest_length; /* 1 */
-    byte  key_length;    /* 2 */
-    byte  fanout;        /* 3 */
-    byte  depth;         /* 4 */
-    word32 leaf_length;   /* 8 */
-    byte  node_offset[6];/* 14 */
-    byte  node_depth;    /* 15 */
-    byte  inner_length;  /* 16 */
-    /* byte  reserved[0]; */
-    byte  salt[BLAKE2B_SALTBYTES]; /* 24 */
-    byte  personal[BLAKE2S_PERSONALBYTES];  /* 32 */
-  } blake2s_param;
-
-  ALIGN( 64 ) typedef struct __blake2s_state
-  {
-    word32 h[8];
-    word32 t[2];
-    word32 f[2];
-    byte  buf[2 * BLAKE2S_BLOCKBYTES];
-    word64 buflen;
-    byte  last_node;
-  } blake2s_state ;
-
-  typedef struct __blake2b_param
-  {
-    byte  digest_length; /* 1 */
-    byte  key_length;    /* 2 */
-    byte  fanout;        /* 3 */
-    byte  depth;         /* 4 */
-    word32 leaf_length;   /* 8 */
-    word64 node_offset;   /* 16 */
-    byte  node_depth;    /* 17 */
-    byte  inner_length;  /* 18 */
-    byte  reserved[14];  /* 32 */
-    byte  salt[BLAKE2B_SALTBYTES]; /* 48 */
-    byte  personal[BLAKE2B_PERSONALBYTES];  /* 64 */
-  } blake2b_param;
-
-  ALIGN( 64 ) typedef struct __blake2b_state
-  {
-    word64 h[8];
-    word64 t[2];
-    word64 f[2];
-    byte  buf[2 * BLAKE2B_BLOCKBYTES];
-    word64 buflen;
-    byte  last_node;
-  } blake2b_state;
-
-  typedef struct __blake2sp_state
-  {
-    blake2s_state S[8][1];
-    blake2s_state R[1];
-    byte buf[8 * BLAKE2S_BLOCKBYTES];
-    word64 buflen;
-  } blake2sp_state;
-
-  typedef struct __blake2bp_state
-  {
-    blake2b_state S[4][1];
-    blake2b_state R[1];
-    byte buf[4 * BLAKE2B_BLOCKBYTES];
-    word64 buflen;
-  } blake2bp_state;
-#pragma pack(pop)
-
-  /* Streaming API */
-  int blake2s_init( blake2s_state *S, const byte outlen );
-  int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, const byte keylen );
-  int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
-  int blake2s_update( blake2s_state *S, const byte *in, word64 inlen );
-  int blake2s_final( blake2s_state *S, byte *out, byte outlen );
-
-  int blake2b_init( blake2b_state *S, const byte outlen );
-  int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, const byte keylen );
-  int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
-  int blake2b_update( blake2b_state *S, const byte *in, word64 inlen );
-  int blake2b_final( blake2b_state *S, byte *out, byte outlen );
-
-  int blake2sp_init( blake2sp_state *S, const byte outlen );
-  int blake2sp_init_key( blake2sp_state *S, const byte outlen, const void *key, const byte keylen );
-  int blake2sp_update( blake2sp_state *S, const byte *in, word64 inlen );
-  int blake2sp_final( blake2sp_state *S, byte *out, byte outlen );
-
-  int blake2bp_init( blake2bp_state *S, const byte outlen );
-  int blake2bp_init_key( blake2bp_state *S, const byte outlen, const void *key, const byte keylen );
-  int blake2bp_update( blake2bp_state *S, const byte *in, word64 inlen );
-  int blake2bp_final( blake2bp_state *S, byte *out, byte outlen );
-
-  /* Simple API */
-  int blake2s( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen );
-  int blake2b( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen );
-
-  int blake2sp( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen );
-  int blake2bp( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen );
-
-  static WC_INLINE int blake2( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen )
-  {
-    return blake2b( out, in, key, outlen, inlen, keylen );
-  }
-
-
-
-#if defined(__cplusplus)
-    }
-#endif
-
-#endif  /* WOLFCRYPT_BLAKE2_INT_H */
-
-
--- a/wolfssl/wolfcrypt/blake2.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* blake2.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/blake2.h
-*/
-
-#ifndef WOLF_CRYPT_BLAKE2_H
-#define WOLF_CRYPT_BLAKE2_H
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_BLAKE2
-
-#include <wolfssl/wolfcrypt/blake2-int.h>
-
-/* call old functions if using fips for the sake of hmac @wc_fips */
-#ifdef HAVE_FIPS
-    /* Since hmac can call blake functions provide original calls */
-    #define wc_InitBlake2b   InitBlake2b
-    #define wc_Blake2bUpdate Blake2bUpdate
-    #define wc_Blake2bFinal  Blake2bFinal
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* in bytes, variable digest size up to 512 bits (64 bytes) */
-enum {
-    BLAKE2B_ID  = WC_HASH_TYPE_BLAKE2B,
-    BLAKE2B_256 = 32   /* 256 bit type, SSL default */
-};
-
-
-/* BLAKE2b digest */
-typedef struct Blake2b {
-    blake2b_state S[1];         /* our state */
-    word32        digestSz;     /* digest size used on init */
-} Blake2b;
-
-
-WOLFSSL_API int wc_InitBlake2b(Blake2b*, word32);
-WOLFSSL_API int wc_Blake2bUpdate(Blake2b*, const byte*, word32);
-WOLFSSL_API int wc_Blake2bFinal(Blake2b*, byte*, word32);
-
-
-
-#ifdef __cplusplus
-    }
-#endif
-
-#endif  /* HAVE_BLAKE2 */
-#endif  /* WOLF_CRYPT_BLAKE2_H */
-
-
--- a/wolfssl/wolfcrypt/camellia.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/* camellia.h ver 1.2.0
- *
- * Copyright (c) 2006,2007
- * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer as
- *   the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* camellia.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/camellia.h
-*/
-
-
-#ifndef WOLF_CRYPT_CAMELLIA_H
-#define WOLF_CRYPT_CAMELLIA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_CAMELLIA
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum {
-    CAMELLIA_BLOCK_SIZE = 16
-};
-
-#define CAMELLIA_TABLE_BYTE_LEN 272
-#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / sizeof(word32))
-
-typedef word32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
-
-typedef struct Camellia {
-    word32 keySz;
-    KEY_TABLE_TYPE key;
-    word32 reg[CAMELLIA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
-    word32 tmp[CAMELLIA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
-} Camellia;
-
-
-WOLFSSL_API int  wc_CamelliaSetKey(Camellia* cam,
-                                   const byte* key, word32 len, const byte* iv);
-WOLFSSL_API int  wc_CamelliaSetIV(Camellia* cam, const byte* iv);
-WOLFSSL_API int  wc_CamelliaEncryptDirect(Camellia* cam, byte* out,
-                                                                const byte* in);
-WOLFSSL_API int  wc_CamelliaDecryptDirect(Camellia* cam, byte* out,
-                                                                const byte* in);
-WOLFSSL_API int wc_CamelliaCbcEncrypt(Camellia* cam,
-                                          byte* out, const byte* in, word32 sz);
-WOLFSSL_API int wc_CamelliaCbcDecrypt(Camellia* cam,
-                                          byte* out, const byte* in, word32 sz);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_CAMELLIA */
-#endif /* WOLF_CRYPT_CAMELLIA_H */
-
-
--- a/wolfssl/wolfcrypt/chacha.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/* chacha.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/chacha.h
-*/
-
-
-#ifndef WOLF_CRYPT_CHACHA_H
-#define WOLF_CRYPT_CHACHA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_CHACHA
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Size of the IV */
-#define CHACHA_IV_WORDS    3
-#define CHACHA_IV_BYTES    (CHACHA_IV_WORDS * sizeof(word32))
-
-/* Size of ChaCha chunks */
-#define CHACHA_CHUNK_WORDS 16
-#define CHACHA_CHUNK_BYTES (CHACHA_CHUNK_WORDS * sizeof(word32))
-
-#ifdef WOLFSSL_X86_64_BUILD
-#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CHACHA_ASM)
-    #define USE_INTEL_CHACHA_SPEEDUP
-    #define HAVE_INTEL_AVX1
-#endif
-#endif
-
-enum {
-	CHACHA_ENC_TYPE = WC_CIPHER_CHACHA,    /* cipher unique type */
-    CHACHA_MAX_KEY_SZ = 32,
-};
-
-typedef struct ChaCha {
-    word32 X[CHACHA_CHUNK_WORDS];           /* state of cipher */
-#ifdef HAVE_INTEL_AVX1
-    /* vpshufd reads 16 bytes but we only use bottom 4. */
-    byte extra[12];
-#endif
-} ChaCha;
-
-/**
-  * IV(nonce) changes with each record
-  * counter is for what value the block counter should start ... usually 0
-  */
-WOLFSSL_API int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter);
-
-WOLFSSL_API int wc_Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain,
-                              word32 msglen);
-WOLFSSL_API int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_CHACHA */
-#endif /* WOLF_CRYPT_CHACHA_H */
-
-
--- a/wolfssl/wolfcrypt/chacha20_poly1305.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/* chacha20_poly1305.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* This implementation of the ChaCha20-Poly1305 AEAD is based on "ChaCha20
- * and Poly1305 for IETF protocols" (draft-irtf-cfrg-chacha20-poly1305-10):
- * https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10
- */
-
-/*!
-    \file wolfssl/wolfcrypt/chacha20_poly1305.h
-*/
-
-#ifndef WOLF_CRYPT_CHACHA20_POLY1305_H
-#define WOLF_CRYPT_CHACHA20_POLY1305_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#define CHACHA20_POLY1305_AEAD_KEYSIZE      32
-#define CHACHA20_POLY1305_AEAD_IV_SIZE      12
-#define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16
-
-enum {
-    CHACHA20_POLY_1305_ENC_TYPE = 8    /* cipher unique type */
-};
-
-    /*
-     * The IV for this implementation is 96 bits to give the most flexibility.
-     *
-     * Some protocols may have unique per-invocation inputs that are not
-     * 96-bit in length. For example, IPsec may specify a 64-bit nonce. In
-     * such a case, it is up to the protocol document to define how to
-     * transform the protocol nonce into a 96-bit nonce, for example by
-     * concatenating a constant value.
-     */
-
-WOLFSSL_API
-int wc_ChaCha20Poly1305_Encrypt(
-                const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
-                const byte* inAAD, const word32 inAADLen,
-                const byte* inPlaintext, const word32 inPlaintextLen,
-                byte* outCiphertext,
-                byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
-
-WOLFSSL_API
-int wc_ChaCha20Poly1305_Decrypt(
-                const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
-                const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
-                const byte* inAAD, const word32 inAADLen,
-                const byte* inCiphertext, const word32 inCiphertextLen,
-                const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
-                byte* outPlaintext);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_CHACHA && HAVE_POLY1305 */
-#endif /* WOLF_CRYPT_CHACHA20_POLY1305_H */
-
--- a/wolfssl/wolfcrypt/cmac.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/* cmac.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_CMAC_H
-#define WOLF_CRYPT_CMAC_H
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/wolfcrypt/aes.h>
-
-#if !defined(NO_AES) && defined(WOLFSSL_CMAC)
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-typedef struct Cmac {
-    Aes aes;
-    byte buffer[AES_BLOCK_SIZE]; /* partially stored block */
-    byte digest[AES_BLOCK_SIZE]; /* running digest */
-    byte k1[AES_BLOCK_SIZE];
-    byte k2[AES_BLOCK_SIZE];
-    word32 bufferSz;
-    word32 totalSz;
-} Cmac;
-
-
-typedef enum CmacType {
-    WC_CMAC_AES = 1
-} CmacType;
-
-#define WC_CMAC_TAG_MAX_SZ AES_BLOCK_SIZE
-#define WC_CMAC_TAG_MIN_SZ (AES_BLOCK_SIZE/4)
-
-#endif /* HAVE_FIPS */
-
-WOLFSSL_API
-int wc_InitCmac(Cmac* cmac,
-                const byte* key, word32 keySz,
-                int type, void* unused);
-WOLFSSL_API
-int wc_CmacUpdate(Cmac* cmac,
-                  const byte* in, word32 inSz);
-WOLFSSL_API
-int wc_CmacFinal(Cmac* cmac,
-                 byte* out, word32* outSz);
-
-WOLFSSL_API
-int wc_AesCmacGenerate(byte* out, word32* outSz,
-                       const byte* in, word32 inSz,
-                       const byte* key, word32 keySz);
-
-WOLFSSL_API
-int wc_AesCmacVerify(const byte* check, word32 checkSz,
-                     const byte* in, word32 inSz,
-                     const byte* key, word32 keySz);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-
-#endif /* NO_AES && WOLFSSL_CMAC */
-#endif /* WOLF_CRYPT_CMAC_H */
-
-
--- a/wolfssl/wolfcrypt/coding.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/* coding.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/coding.h
-*/
-
-#ifndef WOLF_CRYPT_CODING_H
-#define WOLF_CRYPT_CODING_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out,
-                               word32* outLen);
-
-#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(WOLFSSL_KEY_GEN) \
-   || defined(WOLFSSL_CERT_GEN) || defined(HAVE_WEBSERVER) || !defined(NO_DSA)
-    #ifndef WOLFSSL_BASE64_ENCODE
-        #define WOLFSSL_BASE64_ENCODE
-    #endif
-#endif
-
-
-#ifdef WOLFSSL_BASE64_ENCODE
-    enum Escaped {
-        WC_STD_ENC = 0,       /* normal \n line ending encoding */
-        WC_ESC_NL_ENC,        /* use escape sequence encoding   */
-        WC_NO_NL_ENC          /* no encoding at all             */
-    }; /* Encoding types */
-
-    /* encode isn't */
-    WOLFSSL_API
-    int Base64_Encode(const byte* in, word32 inLen, byte* out,
-                                  word32* outLen);
-    WOLFSSL_API
-    int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out,
-                                  word32* outLen);
-    WOLFSSL_API
-    int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out,
-                                  word32* outLen);
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
-    defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) || \
-    defined(HAVE_ECC_CDH) || defined(HAVE_SELFTEST) || \
-    defined(WOLFSSL_ENCRYPTED_KEYS)
-    #ifndef WOLFSSL_BASE16
-        #define WOLFSSL_BASE16
-    #endif
-#endif
-
-#ifdef WOLFSSL_BASE16
-    WOLFSSL_API
-    int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen);
-    WOLFSSL_API
-    int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen);
-#endif
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_CODING_H */
-
-
--- a/wolfssl/wolfcrypt/compress.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* compress.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/compress.h
-*/
-
-
-#ifndef WOLF_CRYPT_COMPRESS_H
-#define WOLF_CRYPT_COMPRESS_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_LIBZ
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-#define COMPRESS_FIXED 1
-
-
-WOLFSSL_API int wc_Compress(byte*, word32, const byte*, word32, word32);
-WOLFSSL_API int wc_DeCompress(byte*, word32, const byte*, word32);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-
-#endif /* HAVE_LIBZ */
-#endif /* WOLF_CRYPT_COMPRESS_H */
-
-
--- a/wolfssl/wolfcrypt/cpuid.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* cpuid.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLF_CRYPT_CPUID_H
-#define WOLF_CRYPT_CPUID_H
-
-
-#include <wolfssl/wolfcrypt/types.h>
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \
-    defined(WOLFSSL_AESNI)
-    #define CPUID_AVX1   0x0001
-    #define CPUID_AVX2   0x0002
-    #define CPUID_RDRAND 0x0004
-    #define CPUID_RDSEED 0x0008
-    #define CPUID_BMI2   0x0010   /* MULX, RORX */
-    #define CPUID_AESNI  0x0020
-    #define CPUID_ADX    0x0040   /* ADCX, ADOX */
-
-    #define IS_INTEL_AVX1(f)    ((f) & CPUID_AVX1)
-    #define IS_INTEL_AVX2(f)    ((f) & CPUID_AVX2)
-    #define IS_INTEL_RDRAND(f)  ((f) & CPUID_RDRAND)
-    #define IS_INTEL_RDSEED(f)  ((f) & CPUID_RDSEED)
-    #define IS_INTEL_BMI2(f)    ((f) & CPUID_BMI2)
-    #define IS_INTEL_AESNI(f)   ((f) & CPUID_AESNI)
-    #define IS_INTEL_ADX(f)     ((f) & CPUID_ADX)
-
-    void cpuid_set_flags(void);
-    word32 cpuid_get_flags(void);
-#endif
-
-#ifdef __cplusplus
-    }   /* extern "C" */
-#endif
-
-
-#endif /* WOLF_CRYPT_CPUID_H */
-
--- a/wolfssl/wolfcrypt/cryptodev.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* cryptodev.h
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _WOLF_CRYPTO_DEV_H_
-#define _WOLF_CRYPTO_DEV_H_
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLF_CRYPTO_DEV
-
-#ifndef NO_RSA
-    #include <wolfssl/wolfcrypt/rsa.h>
-#endif
-#ifdef HAVE_ECC
-    #include <wolfssl/wolfcrypt/ecc.h>
-#endif
-
-/* Crypto Information Structure for callbacks */
-typedef struct wc_CryptoInfo {
-    int algo_type; /* enum wc_AlgoType */
-    struct {
-        int type; /* enum wc_PkType */
-        union {
-        #ifndef NO_RSA
-            struct {
-                const byte* in;
-                word32 inLen;
-                byte* out;
-                word32* outLen;
-                int type;
-                RsaKey* key;
-                WC_RNG* rng;
-            } rsa;
-        #endif
-        #ifdef HAVE_ECC
-            struct {
-                ecc_key* private_key;
-                ecc_key* public_key;
-                byte* out;
-                word32* outlen;
-            } ecdh;
-            struct {
-                const byte* in;
-                word32 inlen;
-                byte* out;
-                word32 *outlen;
-                WC_RNG* rng;
-                ecc_key* key;
-            } eccsign;
-            struct {
-                const byte* sig;
-                word32 siglen;
-                const byte* hash;
-                word32 hashlen;
-                int* res;
-                ecc_key* key;
-            } eccverify;
-        #endif
-        };
-    } pk;
-} wc_CryptoInfo;
-
-typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx);
-
-WOLFSSL_LOCAL void wc_CryptoDev_Init(void);
-
-WOLFSSL_API int  wc_CryptoDev_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx);
-WOLFSSL_API void wc_CryptoDev_UnRegisterDevice(int devId);
-
-
-#ifndef NO_RSA
-WOLFSSL_LOCAL int wc_CryptoDev_Rsa(const byte* in, word32 inLen, byte* out,
-    word32* outLen, int type, RsaKey* key, WC_RNG* rng);
-#endif /* !NO_RSA */
-
-#ifdef HAVE_ECC
-WOLFSSL_LOCAL int wc_CryptoDev_Ecdh(ecc_key* private_key, ecc_key* public_key,
-    byte* out, word32* outlen);
-
-WOLFSSL_LOCAL int wc_CryptoDev_EccSign(const byte* in, word32 inlen, byte* out,
-    word32 *outlen, WC_RNG* rng, ecc_key* key);
-
-WOLFSSL_LOCAL int wc_CryptoDev_EccVerify(const byte* sig, word32 siglen,
-    const byte* hash, word32 hashlen, int* res, ecc_key* key);
-#endif /* HAVE_ECC */
-
-#endif /* WOLF_CRYPTO_DEV */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* _WOLF_CRYPTO_DEV_H_ */
-
--- a/wolfssl/wolfcrypt/curve25519.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/* curve25519.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/curve25519.h
-*/
-
-
-#ifndef WOLF_CRYPT_CURVE25519_H
-#define WOLF_CRYPT_CURVE25519_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_CURVE25519
-
-#include <wolfssl/wolfcrypt/fe_operations.h>
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#define CURVE25519_KEYSIZE 32
-
-/* curve25519 set type */
-typedef struct {
-    int size;       /* The size of the curve in octets */
-    const char* name;     /* name of this curve */
-} curve25519_set_type;
-
-
-/* ECC point, the internal structure is Little endian
- * the mathematical functions used the endianess */
-typedef struct {
-    byte point[CURVE25519_KEYSIZE];
-    #ifdef FREESCALE_LTC_ECC
-        byte pointY[CURVE25519_KEYSIZE];
-    #endif
-} ECPoint;
-
-/* A CURVE25519 Key */
-typedef struct curve25519_key {
-    int idx;            /* Index into the ecc_sets[] for the parameters of
-                           this curve if -1, this key is using user supplied
-                           curve in dp */
-    const curve25519_set_type* dp;   /* domain parameters, either points to
-                                   curves (idx >= 0) or user supplied */
-    ECPoint   p;        /* public key  */
-    ECPoint   k;        /* private key */
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif
-} curve25519_key;
-
-enum {
-    EC25519_LITTLE_ENDIAN=0,
-    EC25519_BIG_ENDIAN=1
-};
-
-WOLFSSL_API
-int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key);
-
-WOLFSSL_API
-int wc_curve25519_shared_secret(curve25519_key* private_key,
-                                curve25519_key* public_key,
-                                byte* out, word32* outlen);
-
-WOLFSSL_API
-int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
-                                   curve25519_key* public_key,
-                                   byte* out, word32* outlen, int endian);
-
-WOLFSSL_API
-int wc_curve25519_init(curve25519_key* key);
-
-WOLFSSL_API
-void wc_curve25519_free(curve25519_key* key);
-
-
-/* raw key helpers */
-WOLFSSL_API
-int wc_curve25519_import_private(const byte* priv, word32 privSz,
-                                 curve25519_key* key);
-WOLFSSL_API
-int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
-                                    curve25519_key* key, int endian);
-
-WOLFSSL_API
-int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
-                            const byte* pub, word32 pubSz, curve25519_key* key);
-WOLFSSL_API
-int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
-                                        const byte* pub, word32 pubSz,
-                                        curve25519_key* key, int endian);
-WOLFSSL_API
-int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
-                                     word32* outLen);
-WOLFSSL_API
-int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
-                                        word32* outLen, int endian);
-
-WOLFSSL_API
-int wc_curve25519_import_public(const byte* in, word32 inLen,
-                                curve25519_key* key);
-WOLFSSL_API
-int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
-                                   curve25519_key* key, int endian);
-
-WOLFSSL_API
-int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
-                                   word32* outLen, int endian);
-
-WOLFSSL_API
-int wc_curve25519_export_key_raw(curve25519_key* key,
-                                 byte* priv, word32 *privSz,
-                                 byte* pub, word32 *pubSz);
-WOLFSSL_API
-int wc_curve25519_export_key_raw_ex(curve25519_key* key,
-                                    byte* priv, word32 *privSz,
-                                    byte* pub, word32 *pubSz,
-                                    int endian);
-/* size helper */
-WOLFSSL_API
-int wc_curve25519_size(curve25519_key* key);
-
-#ifdef __cplusplus
-    }    /* extern "C" */
-#endif
-
-#endif /* HAVE_CURVE25519 */
-#endif /* WOLF_CRYPT_CURVE25519_H */
-
-
--- a/wolfssl/wolfcrypt/des3.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/* des3.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/des3.h
-*/
-
-#ifndef WOLF_CRYPT_DES3_H
-#define WOLF_CRYPT_DES3_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_DES3
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-/* included for fips @wc_fips */
-#include <cyassl/ctaocrypt/des3.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* these are required for FIPS and non-FIPS */
-enum {
-    DES_KEY_SIZE        =  8,  /* des                     */
-    DES3_KEY_SIZE       = 24,  /* 3 des ede               */
-    DES_IV_SIZE         = 16,
-};
-
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-enum {
-    DES_ENC_TYPE    = WC_CIPHER_DES,     /* cipher unique type */
-    DES3_ENC_TYPE   = WC_CIPHER_DES3,    /* cipher unique type */
-
-    DES_BLOCK_SIZE  = 8,
-    DES_KS_SIZE     = 32,    /* internal DES key buffer size */
-
-    DES_ENCRYPTION  = 0,
-    DES_DECRYPTION  = 1
-};
-
-#define DES_IVLEN 8
-#define DES_KEYLEN 8
-#define DES3_IVLEN 8
-#define DES3_KEYLEN 24
-
-
-#if defined(STM32_CRYPTO)
-enum {
-    DES_CBC = 0,
-    DES_ECB = 1
-};
-#endif
-
-
-/* DES encryption and decryption */
-typedef struct Des {
-    word32 reg[DES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
-    word32 tmp[DES_BLOCK_SIZE / sizeof(word32)];      /* same         */
-    word32 key[DES_KS_SIZE];
-} Des;
-
-
-/* DES3 encryption and decryption */
-typedef struct Des3 {
-    word32 key[3][DES_KS_SIZE];
-    word32 reg[DES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */
-    word32 tmp[DES_BLOCK_SIZE / sizeof(word32)];      /* same         */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    const byte* key_raw;
-    const byte* iv_raw;
-    WC_ASYNC_DEV asyncDev;
-#endif
-    void* heap;
-} Des3;
-#endif /* HAVE_FIPS */
-
-
-WOLFSSL_API int  wc_Des_SetKey(Des* des, const byte* key,
-                               const byte* iv, int dir);
-WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv);
-WOLFSSL_API int  wc_Des_CbcEncrypt(Des* des, byte* out,
-                                   const byte* in, word32 sz);
-WOLFSSL_API int  wc_Des_CbcDecrypt(Des* des, byte* out,
-                                   const byte* in, word32 sz);
-WOLFSSL_API int  wc_Des_EcbEncrypt(Des* des, byte* out,
-                                   const byte* in, word32 sz);
-WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out,
-                                   const byte* in, word32 sz);
-
-/* ECB decrypt same process as encrypt but with decrypt key */
-#define wc_Des_EcbDecrypt  wc_Des_EcbEncrypt
-#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt
-
-WOLFSSL_API int  wc_Des3_SetKey(Des3* des, const byte* key,
-                                const byte* iv,int dir);
-WOLFSSL_API int  wc_Des3_SetIV(Des3* des, const byte* iv);
-WOLFSSL_API int  wc_Des3_CbcEncrypt(Des3* des, byte* out,
-                                    const byte* in,word32 sz);
-WOLFSSL_API int  wc_Des3_CbcDecrypt(Des3* des, byte* out,
-                                    const byte* in,word32 sz);
-
-/* These are only required when using either:
-  static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */
-WOLFSSL_API int  wc_Des3Init(Des3*, void*, int);
-WOLFSSL_API void wc_Des3Free(Des3*);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_DES3 */
-#endif /* WOLF_CRYPT_DES3_H */
-
-
--- a/wolfssl/wolfcrypt/dh.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/* dh.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/dh.h
-*/
-
-#ifndef WOLF_CRYPT_DH_H
-#define WOLF_CRYPT_DH_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_DH
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-typedef struct DhParams {
-    #ifdef HAVE_FFDHE_Q
-    const byte* q;
-    word32      q_len;
-    #endif /* HAVE_FFDHE_Q */
-    const byte* p;
-    word32      p_len;
-    const byte* g;
-    word32      g_len;
-} DhParams;
-
-/* Diffie-Hellman Key */
-typedef struct DhKey {
-    mp_int p, g, q;                         /* group parameters  */
-    void* heap;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif
-} DhKey;
-
-
-#ifdef HAVE_FFDHE_2048
-WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void);
-#endif
-#ifdef HAVE_FFDHE_3072
-WOLFSSL_API const DhParams* wc_Dh_ffdhe3072_Get(void);
-#endif
-#ifdef HAVE_FFDHE_4096
-WOLFSSL_API const DhParams* wc_Dh_ffdhe4096_Get(void);
-#endif
-#ifdef HAVE_FFDHE_6144
-WOLFSSL_API const DhParams* wc_Dh_ffdhe6144_Get(void);
-#endif
-#ifdef HAVE_FFDHE_8192
-WOLFSSL_API const DhParams* wc_Dh_ffdhe8192_Get(void);
-#endif
-
-WOLFSSL_API int wc_InitDhKey(DhKey* key);
-WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId);
-WOLFSSL_API int wc_FreeDhKey(DhKey* key);
-
-WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv,
-                                 word32* privSz, byte* pub, word32* pubSz);
-WOLFSSL_API int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz,
-                       const byte* priv, word32 privSz, const byte* otherPub,
-                       word32 pubSz);
-
-WOLFSSL_API int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key,
-                           word32);
-WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g,
-                        word32 gSz);
-WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz,
-                        const byte* g, word32 gSz, const byte* q, word32 qSz);
-WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p,
-                            word32* pInOutSz, byte* g, word32* gInOutSz);
-WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz);
-WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz,
-                            const byte* prime, word32 primeSz);
-WOLFSSL_API int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 pubSz);
-WOLFSSL_API int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 pubSz,
-                            const byte* prime, word32 primeSz);
-WOLFSSL_API int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz,
-                        const byte* priv, word32 privSz);
-WOLFSSL_API int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh);
-WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz,
-                       byte* q, word32* qSz, byte* g, word32* gSz);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_DH */
-#endif /* WOLF_CRYPT_DH_H */
-
-
--- a/wolfssl/wolfcrypt/dsa.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/* dsa.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/dsa.h
-*/
-
-#ifndef WOLF_CRYPT_DSA_H
-#define WOLF_CRYPT_DSA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_DSA
-
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/random.h>
-
-/* for DSA reverse compatibility */
-#define InitDsaKey wc_InitDsaKey
-#define FreeDsaKey wc_FreeDsaKey
-#define DsaSign wc_DsaSign
-#define DsaVerify wc_DsaVerify
-#define DsaPublicKeyDecode wc_DsaPublicKeyDecode
-#define DsaPrivateKeyDecode wc_DsaPrivateKeyDecode
-#define DsaKeyToDer wc_DsaKeyToDer
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-enum {
-    DSA_PUBLIC   = 0,
-    DSA_PRIVATE  = 1
-};
-
-/* DSA */
-typedef struct DsaKey {
-    mp_int p, q, g, y, x;
-    int   type;                               /* public or private */
-    void* heap;                               /* memory hint */
-} DsaKey;
-
-WOLFSSL_API int wc_InitDsaKey(DsaKey* key);
-WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h);
-WOLFSSL_API void wc_FreeDsaKey(DsaKey* key);
-WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out,
-                           DsaKey* key, WC_RNG* rng);
-WOLFSSL_API int wc_DsaVerify(const byte* digest, const byte* sig,
-                             DsaKey* key, int* answer);
-WOLFSSL_API int wc_DsaPublicKeyDecode(const byte* input, word32* inOutIdx,
-                                      DsaKey*, word32);
-WOLFSSL_API int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
-                                       DsaKey*, word32);
-WOLFSSL_API int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen);
-
-#ifdef WOLFSSL_KEY_GEN
-WOLFSSL_API int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa);
-WOLFSSL_API int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa);
-#endif
-
-/* raw export functions */
-WOLFSSL_API int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p,
-                                      const char* q, const char* g);
-WOLFSSL_API int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz,
-                                      byte* q, word32* qSz, byte* g,
-                                      word32* gSz);
-WOLFSSL_API int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y,
-                                   word32* ySz);
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_DSA */
-#endif /* WOLF_CRYPT_DSA_H */
-
-
--- a/wolfssl/wolfcrypt/ecc.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,680 +0,0 @@
-/* ecc.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/ecc.h
-*/
-
-
-#ifndef WOLF_CRYPT_ECC_H
-#define WOLF_CRYPT_ECC_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_ECC
-
-#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifdef HAVE_X963_KDF
-    #include <wolfssl/wolfcrypt/hash.h>
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-    #ifdef WOLFSSL_CERT_GEN
-        #include <wolfssl/wolfcrypt/asn.h>
-    #endif
-#endif
-
-#ifdef WOLFSSL_ATECC508A
-    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
-#endif /* WOLFSSL_ATECC508A */
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-/* Enable curve B parameter if needed */
-#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE)
-    #ifndef USE_ECC_B_PARAM /* Allow someone to force enable */
-        #define USE_ECC_B_PARAM
-    #endif
-#endif
-
-
-/* Use this as the key->idx if a custom ecc_set is used for key->dp */
-#define ECC_CUSTOM_IDX    (-1)
-
-
-/* Determine max ECC bits based on enabled curves */
-#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
-    #define MAX_ECC_BITS    521
-#elif defined(HAVE_ECC512)
-    #define MAX_ECC_BITS    512
-#elif defined(HAVE_ECC384)
-    #define MAX_ECC_BITS    384
-#elif defined(HAVE_ECC320)
-    #define MAX_ECC_BITS    320
-#elif !defined(NO_ECC256)
-    #define MAX_ECC_BITS    256
-#elif defined(HAVE_ECC239)
-    #define MAX_ECC_BITS    239
-#elif defined(HAVE_ECC224)
-    #define MAX_ECC_BITS    224
-#elif defined(HAVE_ECC192)
-    #define MAX_ECC_BITS    192
-#elif defined(HAVE_ECC160)
-    #define MAX_ECC_BITS    160
-#elif defined(HAVE_ECC128)
-    #define MAX_ECC_BITS    128
-#elif defined(HAVE_ECC112)
-    #define MAX_ECC_BITS    112
-#endif
-
-/* calculate max ECC bytes */
-#if ((MAX_ECC_BITS * 2) % 8) == 0
-    #define MAX_ECC_BYTES     (MAX_ECC_BITS / 8)
-#else
-    /* add byte if not aligned */
-    #define MAX_ECC_BYTES     ((MAX_ECC_BITS / 8) + 1)
-#endif
-
-
-enum {
-    ECC_PUBLICKEY       = 1,
-    ECC_PRIVATEKEY      = 2,
-    ECC_PRIVATEKEY_ONLY = 3,
-    ECC_MAXNAME     = 16,   /* MAX CURVE NAME LENGTH */
-    SIG_HEADER_SZ   =  6,   /* ECC signature header size */
-    ECC_BUFSIZE     = 256,  /* for exported keys temp buffer */
-    ECC_MINSIZE     = 20,   /* MIN Private Key size */
-    ECC_MAXSIZE     = 66,   /* MAX Private Key size */
-    ECC_MAXSIZE_GEN = 74,   /* MAX Buffer size required when generating ECC keys*/
-    ECC_MAX_PAD_SZ  = 4,    /* ECC maximum padding size */
-    ECC_MAX_OID_LEN = 16,
-    ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ),
-
-    /* max crypto hardware size */
-#ifdef WOLFSSL_ATECC508A
-    ECC_MAX_CRYPTO_HW_SIZE = ATECC_KEY_SIZE, /* from port/atmel/atmel.h */
-    ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2),
-#elif defined(PLUTON_CRYPTO_ECC)
-    ECC_MAX_CRYPTO_HW_SIZE = 32,
-#endif
-
-    /* point encoding type */
-    ECC_TYPE_HEX_STR = 1,
-    ECC_TYPE_UNSIGNED_BIN = 2,
-
-    /* point compression type */
-    ECC_POINT_COMP_EVEN = 0x02,
-    ECC_POINT_COMP_ODD = 0x03,
-    ECC_POINT_UNCOMP = 0x04,
-
-    /* Shamir's dual add constants */
-    SHAMIR_PRECOMP_SZ = 16,
-};
-
-/* Curve Types */
-typedef enum ecc_curve_id {
-    ECC_CURVE_INVALID = -1,
-    ECC_CURVE_DEF = 0, /* NIST or SECP */
-
-    /* NIST Prime Curves */
-    ECC_SECP192R1,
-    ECC_PRIME192V2,
-    ECC_PRIME192V3,
-    ECC_PRIME239V1,
-    ECC_PRIME239V2,
-    ECC_PRIME239V3,
-    ECC_SECP256R1,
-
-    /* SECP Curves */
-    ECC_SECP112R1,
-    ECC_SECP112R2,
-    ECC_SECP128R1,
-    ECC_SECP128R2,
-    ECC_SECP160R1,
-    ECC_SECP160R2,
-    ECC_SECP224R1,
-    ECC_SECP384R1,
-    ECC_SECP521R1,
-
-    /* Koblitz */
-    ECC_SECP160K1,
-    ECC_SECP192K1,
-    ECC_SECP224K1,
-    ECC_SECP256K1,
-
-    /* Brainpool Curves */
-    ECC_BRAINPOOLP160R1,
-    ECC_BRAINPOOLP192R1,
-    ECC_BRAINPOOLP224R1,
-    ECC_BRAINPOOLP256R1,
-    ECC_BRAINPOOLP320R1,
-    ECC_BRAINPOOLP384R1,
-    ECC_BRAINPOOLP512R1,
-
-    /* Twisted Edwards Curves */
-#ifdef HAVE_CURVE25519
-    ECC_X25519,
-#endif
-#ifdef HAVE_X448
-    ECC_X448,
-#endif
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-    ECC_CURVE_CUSTOM,
-#endif
-} ecc_curve_id;
-
-#ifdef HAVE_OID_ENCODING
-typedef word16 ecc_oid_t;
-#else
-typedef byte   ecc_oid_t;
-    /* OID encoded with ASN scheme:
-        first element = (oid[0] * 40) + oid[1]
-        if any element > 127 then MSB 0x80 indicates additional byte */
-#endif
-
-/* ECC set type defined a GF(p) curve */
-#ifndef USE_WINDOWS_API
-typedef struct ecc_set_type {
-    int size;             /* The size of the curve in octets */
-    int id;               /* id of this curve */
-    const char* name;     /* name of this curve */
-    const char* prime;    /* prime that defines the field, curve is in (hex) */
-    const char* Af;       /* fields A param (hex) */
-    const char* Bf;       /* fields B param (hex) */
-    const char* order;    /* order of the curve (hex) */
-    const char* Gx;       /* x coordinate of the base point on curve (hex) */
-    const char* Gy;       /* y coordinate of the base point on curve (hex) */
-    const ecc_oid_t* oid;
-    word32      oidSz;
-    word32      oidSum;    /* sum of encoded OID bytes */
-    int         cofactor;
-} ecc_set_type;
-#else
-/* MSC does something different with the pointers to the arrays than GCC,
- * and it causes the FIPS checksum to fail. In the case of windows builds,
- * store everything as arrays instead of pointers to strings. */
-
-#define MAX_ECC_NAME 16
-#define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 1)
-    /* The values are stored as text strings. */
-
-typedef struct ecc_set_type {
-    int size;             /* The size of the curve in octets */
-    int id;               /* id of this curve */
-    const char name[MAX_ECC_NAME];     /* name of this curve */
-    const char prime[MAX_ECC_STRING];    /* prime that defines the field, curve is in (hex) */
-    const char Af[MAX_ECC_STRING];       /* fields A param (hex) */
-    const char Bf[MAX_ECC_STRING];       /* fields B param (hex) */
-    const char order[MAX_ECC_STRING];    /* order of the curve (hex) */
-    const char Gx[MAX_ECC_STRING];       /* x coordinate of the base point on curve (hex) */
-    const char Gy[MAX_ECC_STRING];       /* y coordinate of the base point on curve (hex) */
-    const ecc_oid_t oid[10];
-    word32      oidSz;
-    word32      oidSum;    /* sum of encoded OID bytes */
-    int         cofactor;
-} ecc_set_type;
-#endif
-
-
-#ifdef ALT_ECC_SIZE
-
-/* Note on ALT_ECC_SIZE:
- * The fast math code uses an array of a fixed size to store the big integers.
- * By default, the array is big enough for RSA keys. There is a size,
- * FP_MAX_BITS which can be used to make the array smaller when one wants ECC
- * but not RSA. Some people want fast math sized for both RSA and ECC, where
- * ECC won't use as much as RSA. The flag ALT_ECC_SIZE switches in an alternate
- * ecc_point structure that uses an alternate fp_int that has a shorter array
- * of fp_digits.
- *
- * Now, without ALT_ECC_SIZE, the ecc_point has three single item arrays of
- * mp_ints for the components of the point. With ALT_ECC_SIZE, the components
- * of the point are pointers that are set to each of a three item array of
- * alt_fp_ints. While an mp_int will have 4096 bits of digit inside the
- * structure, the alt_fp_int will only have 528 bits. A size value was added
- * in the ALT case, as well, and is set by mp_init() and alt_fp_init(). The
- * functions fp_zero() and fp_copy() use the size parameter. An int needs to
- * be initialized before using it instead of just fp_zeroing it, the init will
- * call zero. FP_MAX_BITS_ECC defaults to 528, but can be set to change the
- * number of bits used in the alternate FP_INT.
- *
- * Do not enable ALT_ECC_SIZE and disable fast math in the configuration.
- */
-
-#ifndef USE_FAST_MATH
-    #error USE_FAST_MATH must be defined to use ALT_ECC_SIZE
-#endif
-
-/* determine max bits required for ECC math */
-#ifndef FP_MAX_BITS_ECC
-    /* check alignment */
-    #if ((MAX_ECC_BITS * 2) % DIGIT_BIT) == 0
-        /* max bits is double */
-        #define FP_MAX_BITS_ECC     (MAX_ECC_BITS * 2)
-    #else
-        /* max bits is doubled, plus one digit of fudge */
-        #define FP_MAX_BITS_ECC     ((MAX_ECC_BITS * 2) + DIGIT_BIT)
-    #endif
-#else
-    /* verify alignment */
-    #if FP_MAX_BITS_ECC % CHAR_BIT
-       #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT
-    #endif
-#endif
-
-/* determine buffer size */
-#define FP_SIZE_ECC    (FP_MAX_BITS_ECC/DIGIT_BIT)
-
-
-/* This needs to match the size of the fp_int struct, except the
- * fp_digit array will be shorter. */
-typedef struct alt_fp_int {
-    int used, sign, size;
-    fp_digit dp[FP_SIZE_ECC];
-} alt_fp_int;
-#endif /* ALT_ECC_SIZE */
-
-#ifndef WC_ECCKEY_TYPE_DEFINED
-    typedef struct ecc_key ecc_key;
-    #define WC_ECCKEY_TYPE_DEFINED
-#endif
-
-
-/* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) =>
-   (x/z^2, y/z^3, 1) when interpreted as affine */
-typedef struct {
-#ifndef ALT_ECC_SIZE
-    mp_int x[1];        /* The x coordinate */
-    mp_int y[1];        /* The y coordinate */
-    mp_int z[1];        /* The z coordinate */
-#else
-    mp_int* x;        /* The x coordinate */
-    mp_int* y;        /* The y coordinate */
-    mp_int* z;        /* The z coordinate */
-    alt_fp_int xyz[3];
-#endif
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    ecc_key* key;
-#endif
-} ecc_point;
-
-/* ECC Flags */
-enum {
-    WC_ECC_FLAG_NONE = 0x00,
-#ifdef HAVE_ECC_CDH
-    WC_ECC_FLAG_COFACTOR = 0x01,
-#endif
-};
-
-/* An ECC Key */
-struct ecc_key {
-    int type;           /* Public or Private */
-    int idx;            /* Index into the ecc_sets[] for the parameters of
-                           this curve if -1, this key is using user supplied
-                           curve in dp */
-    int    state;
-    word32 flags;
-    const ecc_set_type* dp;     /* domain parameters, either points to NIST
-                                   curves (idx >= 0) or user supplied */
-#ifdef WOLFSSL_CUSTOM_CURVES
-    int deallocSet;
-#endif
-    void* heap;         /* heap hint */
-    ecc_point pubkey;   /* public key */
-    mp_int    k;        /* private key */
-#ifdef WOLFSSL_ATECC508A
-    int  slot;        /* Key Slot Number (-1 unknown) */
-    byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE];
-#endif
-#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV)
-    int devId;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    mp_int* r;          /* sign/verify temps */
-    mp_int* s;
-    WC_ASYNC_DEV asyncDev;
-    #ifdef HAVE_CAVIUM_V
-        mp_int* e;      /* Sign, Verify and Shared Secret */
-        mp_int* signK;
-    #endif
-    #ifdef WOLFSSL_CERT_GEN
-        CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */
-    #endif
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    mp_int* t1;
-    mp_int* t2;
-#ifdef ALT_ECC_SIZE
-    mp_int* x;
-    mp_int* y;
-    mp_int* z;
-#endif
-#endif
-};
-
-
-/* ECC predefined curve sets  */
-extern const ecc_set_type ecc_sets[];
-
-WOLFSSL_API
-const char* wc_ecc_get_name(int curve_id);
-
-#ifndef WOLFSSL_ATECC508A
-
-#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
-    #define ECC_API    WOLFSSL_API
-#else
-    #define ECC_API    WOLFSSL_LOCAL
-#endif
-
-ECC_API int ecc_mul2add(ecc_point* A, mp_int* kA,
-                ecc_point* B, mp_int* kB,
-                ecc_point* C, mp_int* a, mp_int* modulus, void* heap);
-
-ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit);
-ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
-                                     mp_int* a, mp_int* modulus, mp_digit mp);
-ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a,
-                                     mp_int* modulus, mp_digit mp);
-
-#endif
-
-WOLFSSL_API
-int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key);
-WOLFSSL_API
-int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
-    int curve_id);
-WOLFSSL_API
-int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut);
-WOLFSSL_API
-int wc_ecc_check_key(ecc_key* key);
-WOLFSSL_API
-int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime);
-
-#ifdef HAVE_ECC_DHE
-WOLFSSL_API
-int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
-                      word32* outlen);
-WOLFSSL_LOCAL
-int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point,
-                             byte* out, word32 *outlen);
-WOLFSSL_API
-int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point,
-                             byte* out, word32 *outlen);
-#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */
-#endif /* HAVE_ECC_DHE */
-
-#ifdef HAVE_ECC_SIGN
-WOLFSSL_API
-int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
-                     WC_RNG* rng, ecc_key* key);
-WOLFSSL_API
-int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
-                        ecc_key* key, mp_int *r, mp_int *s);
-#endif /* HAVE_ECC_SIGN */
-
-#ifdef HAVE_ECC_VERIFY
-WOLFSSL_API
-int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
-                    word32 hashlen, int* stat, ecc_key* key);
-WOLFSSL_API
-int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
-                          word32 hashlen, int* stat, ecc_key* key);
-#endif /* HAVE_ECC_VERIFY */
-
-WOLFSSL_API
-int wc_ecc_init(ecc_key* key);
-WOLFSSL_API
-int wc_ecc_init_ex(ecc_key* key, void* heap, int devId);
-#ifdef WOLFSSL_CUSTOM_CURVES
-WOLFSSL_LOCAL
-void wc_ecc_free_curve(const ecc_set_type* curve, void* heap);
-#endif
-WOLFSSL_API
-int wc_ecc_free(ecc_key* key);
-WOLFSSL_API
-int wc_ecc_set_flags(ecc_key* key, word32 flags);
-WOLFSSL_API
-void wc_ecc_fp_free(void);
-
-WOLFSSL_API
-int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id);
-
-WOLFSSL_API
-int wc_ecc_is_valid_idx(int n);
-WOLFSSL_API
-int wc_ecc_get_curve_idx(int curve_id);
-WOLFSSL_API
-int wc_ecc_get_curve_id(int curve_idx);
-#define wc_ecc_get_curve_name_from_id wc_ecc_get_name
-WOLFSSL_API
-int wc_ecc_get_curve_size_from_id(int curve_id);
-
-WOLFSSL_API
-int wc_ecc_get_curve_idx_from_name(const char* curveName);
-WOLFSSL_API
-int wc_ecc_get_curve_size_from_name(const char* curveName);
-WOLFSSL_API
-int wc_ecc_get_curve_id_from_name(const char* curveName);
-WOLFSSL_API
-int wc_ecc_get_curve_id_from_params(int fieldSize,
-        const byte* prime, word32 primeSz, const byte* Af, word32 AfSz,
-        const byte* Bf, word32 BfSz, const byte* order, word32 orderSz,
-        const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor);
-
-
-WOLFSSL_API
-ecc_point* wc_ecc_new_point(void);
-WOLFSSL_API
-ecc_point* wc_ecc_new_point_h(void* h);
-WOLFSSL_API
-void wc_ecc_del_point(ecc_point* p);
-WOLFSSL_API
-void wc_ecc_del_point_h(ecc_point* p, void* h);
-WOLFSSL_API
-int wc_ecc_copy_point(ecc_point* p, ecc_point *r);
-WOLFSSL_API
-int wc_ecc_cmp_point(ecc_point* a, ecc_point *b);
-WOLFSSL_API
-int wc_ecc_point_is_at_infinity(ecc_point *p);
-
-#ifndef WOLFSSL_ATECC508A
-WOLFSSL_API
-int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
-                  mp_int* a, mp_int* modulus, int map);
-WOLFSSL_LOCAL
-int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
-                  mp_int* a, mp_int* modulus, int map, void* heap);
-#endif /* !WOLFSSL_ATECC508A */
-
-
-#ifdef HAVE_ECC_KEY_EXPORT
-/* ASN key helpers */
-WOLFSSL_API
-int wc_ecc_export_x963(ecc_key*, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_ecc_export_x963_ex(ecc_key*, byte* out, word32* outLen, int compressed);
-    /* extended functionality with compressed option */
-#endif /* HAVE_ECC_KEY_EXPORT */
-
-#ifdef HAVE_ECC_KEY_IMPORT
-WOLFSSL_API
-int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key);
-WOLFSSL_API
-int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
-                          int curve_id);
-WOLFSSL_API
-int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
-                           word32 pubSz, ecc_key* key);
-WOLFSSL_API
-int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
-                const byte* pub, word32 pubSz, ecc_key* key, int curve_id);
-WOLFSSL_API
-int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen);
-WOLFSSL_API
-int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
-    byte* out, word32* outlen);
-WOLFSSL_API
-int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen,
-                   byte* s, word32* sLen);
-WOLFSSL_API
-int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
-                   const char* d, const char* curveName);
-WOLFSSL_API
-int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
-                   const char* d, int curve_id);
-WOLFSSL_API
-int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy,
-                   byte* d, int curve_id);
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-#ifdef HAVE_ECC_KEY_EXPORT
-WOLFSSL_API
-int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
-                             byte* qy, word32* qyLen);
-WOLFSSL_API
-int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen,
-                            byte* qy, word32* qyLen, byte* d, word32* dLen);
-#endif /* HAVE_ECC_KEY_EXPORT */
-
-#ifdef HAVE_ECC_KEY_EXPORT
-
-WOLFSSL_API
-int wc_ecc_export_point_der(const int curve_idx, ecc_point* point,
-                            byte* out, word32* outLen);
-#endif /* HAVE_ECC_KEY_EXPORT */
-
-
-#ifdef HAVE_ECC_KEY_IMPORT
-WOLFSSL_API
-int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
-                            ecc_point* point);
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-/* size helper */
-WOLFSSL_API
-int wc_ecc_size(ecc_key* key);
-WOLFSSL_API
-int wc_ecc_sig_size_calc(int sz);
-WOLFSSL_API
-int wc_ecc_sig_size(ecc_key* key);
-
-WOLFSSL_API
-int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz);
-
-#ifdef WOLFSSL_CUSTOM_CURVES
-    WOLFSSL_API
-    int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp);
-#endif
-
-#ifdef HAVE_ECC_ENCRYPT
-/* ecc encrypt */
-
-enum ecEncAlgo {
-    ecAES_128_CBC = 1,  /* default */
-    ecAES_256_CBC = 2
-};
-
-enum ecKdfAlgo {
-    ecHKDF_SHA256 = 1,  /* default */
-    ecHKDF_SHA1   = 2
-};
-
-enum ecMacAlgo {
-    ecHMAC_SHA256 = 1,  /* default */
-    ecHMAC_SHA1   = 2
-};
-
-enum {
-    KEY_SIZE_128     = 16,
-    KEY_SIZE_256     = 32,
-    IV_SIZE_64       =  8,
-    IV_SIZE_128      = 16,
-    EXCHANGE_SALT_SZ = 16,
-    EXCHANGE_INFO_SZ = 23
-};
-
-enum ecFlags {
-    REQ_RESP_CLIENT = 1,
-    REQ_RESP_SERVER = 2
-};
-
-
-typedef struct ecEncCtx ecEncCtx;
-
-WOLFSSL_API
-ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng);
-WOLFSSL_API
-ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap);
-WOLFSSL_API
-void wc_ecc_ctx_free(ecEncCtx*);
-WOLFSSL_API
-int wc_ecc_ctx_reset(ecEncCtx*, WC_RNG*);  /* reset for use again w/o alloc/free */
-
-WOLFSSL_API
-const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*);
-WOLFSSL_API
-int wc_ecc_ctx_set_peer_salt(ecEncCtx*, const byte* salt);
-WOLFSSL_API
-int wc_ecc_ctx_set_info(ecEncCtx*, const byte* info, int sz);
-
-WOLFSSL_API
-int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
-                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
-WOLFSSL_API
-int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
-                word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
-
-#endif /* HAVE_ECC_ENCRYPT */
-
-#ifdef HAVE_X963_KDF
-WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret,
-                word32 secretSz, const byte* sinfo, word32 sinfoSz,
-                byte* out, word32 outSz);
-#endif
-
-#ifdef ECC_CACHE_CURVE
-WOLFSSL_API int wc_ecc_curve_cache_init(void);
-WOLFSSL_API void wc_ecc_curve_cache_free(void);
-#endif
-
-
-#ifdef __cplusplus
-    }    /* extern "C" */
-#endif
-
-#endif /* HAVE_ECC */
-#endif /* WOLF_CRYPT_ECC_H */
-
--- a/wolfssl/wolfcrypt/ed25519.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/* ed25519.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/ed25519.h
-*/
-
-
-#ifndef WOLF_CRYPT_ED25519_H
-#define WOLF_CRYPT_ED25519_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_ED25519
-
-#include <wolfssl/wolfcrypt/fe_operations.h>
-#include <wolfssl/wolfcrypt/ge_operations.h>
-#include <wolfssl/wolfcrypt/random.h>
-#include <wolfssl/wolfcrypt/sha512.h>
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-/* info about EdDSA curve specifically ed25519, defined as an elliptic curve
-   over GF(p) */
-/*
-    32,                key size
-    "ED25519",         curve name
-    "2^255-19",        prime number
-    "SHA512",          hash function
-    "-121665/121666",  value of d
-*/
-
-#define ED25519_KEY_SIZE     32 /* private key only */
-#define ED25519_SIG_SIZE     64
-
-#define ED25519_PUB_KEY_SIZE 32 /* compressed */
-/* both private and public key */
-#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE)
-
-
-#ifndef WC_ED25519KEY_TYPE_DEFINED
-    typedef struct ed25519_key ed25519_key;
-    #define WC_ED25519KEY_TYPE_DEFINED
-#endif
-
-/* An ED25519 Key */
-struct ed25519_key {
-    byte    p[ED25519_PUB_KEY_SIZE]; /* compressed public key */
-    byte    k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */
-#ifdef FREESCALE_LTC_ECC
-    /* uncompressed point coordinates */
-    byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */
-    byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */
-#endif
-    int pubKeySet:1;
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif
-};
-
-
-WOLFSSL_API
-int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
-                        word32 *outlen, ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
-                          word32 msglen, int* stat, ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_init(ed25519_key* key);
-WOLFSSL_API
-void wc_ed25519_free(ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
-                                                              ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
-                               const byte* pub, word32 pubSz, ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen);
-WOLFSSL_API
-int wc_ed25519_export_key(ed25519_key* key,
-                          byte* priv, word32 *privSz,
-                          byte* pub, word32 *pubSz);
-
-int wc_ed25519_check_key(ed25519_key* key);
-
-/* size helper */
-WOLFSSL_API
-int wc_ed25519_size(ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_priv_size(ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_pub_size(ed25519_key* key);
-WOLFSSL_API
-int wc_ed25519_sig_size(ed25519_key* key);
-
-#ifdef __cplusplus
-    }    /* extern "C" */
-#endif
-
-#endif /* HAVE_ED25519 */
-#endif /* WOLF_CRYPT_ED25519_H */
-
-
--- a/wolfssl/wolfcrypt/error-crypt.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/* error-crypt.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/error-crypt.h
-*/
-
-#ifndef WOLF_CRYPT_ERROR_H
-#define WOLF_CRYPT_ERROR_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_FIPS
-	#include <cyassl/ctaocrypt/error-crypt.h>
-#endif /* HAVE_FIPS */
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-/* error codes, add string for new errors !!! */
-enum {
-    MAX_CODE_E         = -100,  /* errors -101 - -299 */
-    OPEN_RAN_E         = -101,  /* opening random device error */
-    READ_RAN_E         = -102,  /* reading random device error */
-    WINCRYPT_E         = -103,  /* windows crypt init error */
-    CRYPTGEN_E         = -104,  /* windows crypt generation error */
-    RAN_BLOCK_E        = -105,  /* reading random device would block */
-    BAD_MUTEX_E        = -106,  /* Bad mutex operation */
-    WC_TIMEOUT_E       = -107,  /* timeout error */
-    WC_PENDING_E       = -108,  /* wolfCrypt operation pending (would block) */
-    WC_NOT_PENDING_E   = -109,  /* wolfCrypt operation not pending */
-
-    MP_INIT_E          = -110,  /* mp_init error state */
-    MP_READ_E          = -111,  /* mp_read error state */
-    MP_EXPTMOD_E       = -112,  /* mp_exptmod error state */
-    MP_TO_E            = -113,  /* mp_to_xxx error state, can't convert */
-    MP_SUB_E           = -114,  /* mp_sub error state, can't subtract */
-    MP_ADD_E           = -115,  /* mp_add error state, can't add */
-    MP_MUL_E           = -116,  /* mp_mul error state, can't multiply */
-    MP_MULMOD_E        = -117,  /* mp_mulmod error state, can't multiply mod */
-    MP_MOD_E           = -118,  /* mp_mod error state, can't mod */
-    MP_INVMOD_E        = -119,  /* mp_invmod error state, can't inv mod */
-    MP_CMP_E           = -120,  /* mp_cmp error state */
-    MP_ZERO_E          = -121,  /* got a mp zero result, not expected */
-
-    MEMORY_E           = -125,  /* out of memory error */
-    VAR_STATE_CHANGE_E = -126,  /* var state modified by different thread */
-
-    RSA_WRONG_TYPE_E   = -130,  /* RSA wrong block type for RSA function */
-    RSA_BUFFER_E       = -131,  /* RSA buffer error, output too small or
-                                   input too large */
-    BUFFER_E           = -132,  /* output buffer too small or input too large */
-    ALGO_ID_E          = -133,  /* setting algo id error */
-    PUBLIC_KEY_E       = -134,  /* setting public key error */
-    DATE_E             = -135,  /* setting date validity error */
-    SUBJECT_E          = -136,  /* setting subject name error */
-    ISSUER_E           = -137,  /* setting issuer  name error */
-    CA_TRUE_E          = -138,  /* setting CA basic constraint true error */
-    EXTENSIONS_E       = -139,  /* setting extensions error */
-
-    ASN_PARSE_E        = -140,  /* ASN parsing error, invalid input */
-    ASN_VERSION_E      = -141,  /* ASN version error, invalid number */
-    ASN_GETINT_E       = -142,  /* ASN get big int error, invalid data */
-    ASN_RSA_KEY_E      = -143,  /* ASN key init error, invalid input */
-    ASN_OBJECT_ID_E    = -144,  /* ASN object id error, invalid id */
-    ASN_TAG_NULL_E     = -145,  /* ASN tag error, not null */
-    ASN_EXPECT_0_E     = -146,  /* ASN expect error, not zero */
-    ASN_BITSTR_E       = -147,  /* ASN bit string error, wrong id */
-    ASN_UNKNOWN_OID_E  = -148,  /* ASN oid error, unknown sum id */
-    ASN_DATE_SZ_E      = -149,  /* ASN date error, bad size */
-    ASN_BEFORE_DATE_E  = -150,  /* ASN date error, current date before */
-    ASN_AFTER_DATE_E   = -151,  /* ASN date error, current date after */
-    ASN_SIG_OID_E      = -152,  /* ASN signature error, mismatched oid */
-    ASN_TIME_E         = -153,  /* ASN time error, unknown time type */
-    ASN_INPUT_E        = -154,  /* ASN input error, not enough data */
-    ASN_SIG_CONFIRM_E  = -155,  /* ASN sig error, confirm failure */
-    ASN_SIG_HASH_E     = -156,  /* ASN sig error, unsupported hash type */
-    ASN_SIG_KEY_E      = -157,  /* ASN sig error, unsupported key type */
-    ASN_DH_KEY_E       = -158,  /* ASN key init error, invalid input */
-    ASN_NTRU_KEY_E     = -159,  /* ASN ntru key decode error, invalid input */
-    ASN_CRIT_EXT_E     = -160,  /* ASN unsupported critical extension */
-    ASN_ALT_NAME_E     = -161,  /* ASN alternate name error */
-    ASN_NO_PEM_HEADER  = -162,  /* ASN no PEM header found */
-
-    ECC_BAD_ARG_E      = -170,  /* ECC input argument of wrong type */
-    ASN_ECC_KEY_E      = -171,  /* ASN ECC bad input */
-    ECC_CURVE_OID_E    = -172,  /* Unsupported ECC OID curve type */
-    BAD_FUNC_ARG       = -173,  /* Bad function argument provided */
-    NOT_COMPILED_IN    = -174,  /* Feature not compiled in */
-    UNICODE_SIZE_E     = -175,  /* Unicode password too big */
-    NO_PASSWORD        = -176,  /* no password provided by user */
-    ALT_NAME_E         = -177,  /* alt name size problem, too big */
-    BAD_OCSP_RESPONDER = -178,  /* missing key usage extensions */
-
-    AES_GCM_AUTH_E     = -180,  /* AES-GCM Authentication check failure */
-    AES_CCM_AUTH_E     = -181,  /* AES-CCM Authentication check failure */
-
-    ASYNC_INIT_E       = -182,  /* Async Init type error */
-
-    COMPRESS_INIT_E    = -183,  /* Compress init error */
-    COMPRESS_E         = -184,  /* Compress error */
-    DECOMPRESS_INIT_E  = -185,  /* DeCompress init error */
-    DECOMPRESS_E       = -186,  /* DeCompress error */
-
-    BAD_ALIGN_E         = -187,  /* Bad alignment for operation, no alloc */
-    ASN_NO_SIGNER_E     = -188,  /* ASN no signer to confirm failure */
-    ASN_CRL_CONFIRM_E   = -189,  /* ASN CRL signature confirm failure */
-    ASN_CRL_NO_SIGNER_E = -190,  /* ASN CRL no signer to confirm failure */
-    ASN_OCSP_CONFIRM_E  = -191,  /* ASN OCSP signature confirm failure */
-
-    BAD_STATE_E         = -192,  /* Bad state operation */
-    BAD_PADDING_E       = -193,  /* Bad padding, msg not correct length  */
-
-    REQ_ATTRIBUTE_E     = -194,  /* setting cert request attributes error */
-
-    PKCS7_OID_E         = -195,  /* PKCS#7, mismatched OID error */
-    PKCS7_RECIP_E       = -196,  /* PKCS#7, recipient error */
-    FIPS_NOT_ALLOWED_E  = -197,  /* FIPS not allowed error */
-    ASN_NAME_INVALID_E  = -198,  /* ASN name constraint error */
-
-    RNG_FAILURE_E       = -199,  /* RNG Failed, Reinitialize */
-    HMAC_MIN_KEYLEN_E   = -200,  /* FIPS Mode HMAC Minimum Key Length error */
-    RSA_PAD_E           = -201,  /* RSA Padding Error */
-    LENGTH_ONLY_E       = -202,  /* Returning output length only */
-
-    IN_CORE_FIPS_E      = -203,  /* In Core Integrity check failure */
-    AES_KAT_FIPS_E      = -204,  /* AES KAT failure */
-    DES3_KAT_FIPS_E     = -205,  /* DES3 KAT failure */
-    HMAC_KAT_FIPS_E     = -206,  /* HMAC KAT failure */
-    RSA_KAT_FIPS_E      = -207,  /* RSA KAT failure */
-    DRBG_KAT_FIPS_E     = -208,  /* HASH DRBG KAT failure */
-    DRBG_CONT_FIPS_E    = -209,  /* HASH DRBG Continuous test failure */
-    AESGCM_KAT_FIPS_E   = -210,  /* AESGCM KAT failure */
-    THREAD_STORE_KEY_E  = -211,  /* Thread local storage key create failure */
-    THREAD_STORE_SET_E  = -212,  /* Thread local storage key set failure */
-
-    MAC_CMP_FAILED_E    = -213,  /* MAC comparison failed */
-    IS_POINT_E          = -214,  /* ECC is point on curve failed */
-    ECC_INF_E           = -215,  /* ECC point infinity error */
-    ECC_PRIV_KEY_E      = -216,  /* ECC private key not valid error */
-    ECC_OUT_OF_RANGE_E  = -217,  /* ECC key component out of range */
-
-    SRP_CALL_ORDER_E    = -218,  /* SRP function called in the wrong order. */
-    SRP_VERIFY_E        = -219,  /* SRP proof verification failed. */
-    SRP_BAD_KEY_E       = -220,  /* SRP bad ephemeral values. */
-
-    ASN_NO_SKID         = -221,  /* ASN no Subject Key Identifier found */
-    ASN_NO_AKID         = -222,  /* ASN no Authority Key Identifier found */
-    ASN_NO_KEYUSAGE     = -223,  /* ASN no Key Usage found */
-    SKID_E              = -224,  /* setting Subject Key Identifier error */
-    AKID_E              = -225,  /* setting Authority Key Identifier error */
-    KEYUSAGE_E          = -226,  /* Bad Key Usage value */
-    CERTPOLICIES_E      = -227,  /* setting Certificate Policies error */
-
-    WC_INIT_E           = -228,  /* wolfcrypt failed to initialize */
-    SIG_VERIFY_E        = -229,  /* wolfcrypt signature verify error */
-    BAD_COND_E          = -230,  /* Bad condition variable operation */
-    SIG_TYPE_E          = -231,  /* Signature Type not enabled/available */
-    HASH_TYPE_E         = -232,  /* Hash Type not enabled/available */
-
-    WC_KEY_SIZE_E       = -234,  /* Key size error, either too small or large */
-    ASN_COUNTRY_SIZE_E  = -235,  /* ASN Cert Gen, invalid country code size */
-    MISSING_RNG_E       = -236,  /* RNG required but not provided */
-    ASN_PATHLEN_SIZE_E  = -237,  /* ASN CA path length too large error */
-    ASN_PATHLEN_INV_E   = -238,  /* ASN CA path length inversion error */
-
-    BAD_KEYWRAP_ALG_E   = -239,
-    BAD_KEYWRAP_IV_E    = -240,  /* Decrypted AES key wrap IV incorrect */
-    WC_CLEANUP_E        = -241,  /* wolfcrypt cleanup failed */
-    ECC_CDH_KAT_FIPS_E  = -242,  /* ECC CDH Known Answer Test failure */
-    DH_CHECK_PUB_E      = -243,  /* DH Check Pub Key error */
-    BAD_PATH_ERROR      = -244,  /* Bad path for opendir */
-
-    ASYNC_OP_E          = -245,  /* Async operation error */
-
-    ECC_PRIVATEONLY_E   = -246,  /* Invalid use of private only ECC key*/
-    EXTKEYUSAGE_E       = -247,  /* Bad Extended Key Usage value */
-    WC_HW_E             = -248,  /* Error with hardware crypto use */
-    WC_HW_WAIT_E        = -249,  /* Hardware waiting on resource */
-
-    PSS_SALTLEN_E       = -250,  /* PSS length of salt is to long for hash */
-    PRIME_GEN_E         = -251,  /* Failure finding a prime. */
-    BER_INDEF_E         = -252,  /* Cannot decode indefinite length BER. */
-    RSA_OUT_OF_RANGE_E  = -253,  /* Ciphertext to decrypt out of range. */
-    RSAPSS_PAT_FIPS_E   = -254,  /* RSA-PSS PAT failure */
-    ECDSA_PAT_FIPS_E    = -255,  /* ECDSA PAT failure */
-    DH_KAT_FIPS_E       = -256,  /* DH KAT failure */
-    AESCCM_KAT_FIPS_E   = -257,  /* AESCCM KAT failure */
-    SHA3_KAT_FIPS_E     = -258,  /* SHA-3 KAT failure */
-    ECDHE_KAT_FIPS_E    = -259,  /* ECDHE KAT failure */
-    AES_GCM_OVERFLOW_E  = -260,  /* AES-GCM invocation counter overflow. */
-    AES_CCM_OVERFLOW_E  = -261,  /* AES-CCM invocation counter overflow. */
-    RSA_KEY_PAIR_E      = -262,  /* RSA Key Pair-Wise Consistency check fail. */
-    DH_CHECK_PRIV_E     = -263,  /* DH Check Priv Key error */
-
-    WC_LAST_E           = -263,  /* Update this to indicate last error */
-    MIN_CODE_E          = -300   /* errors -101 - -299 */
-
-    /* add new companion error id strings for any new error codes
-       wolfcrypt/src/error.c !!! */
-};
-
-
-#ifdef NO_ERROR_STRINGS
-    #define wc_GetErrorString(error) "no support for error strings built in"
-    #define wc_ErrorString(err, buf) \
-        (void)err; XSTRNCPY((buf), wc_GetErrorString((err)), \
-        WOLFSSL_MAX_ERROR_SZ);
-
-#else
-WOLFSSL_API void wc_ErrorString(int err, char* buff);
-WOLFSSL_API const char* wc_GetErrorString(int error);
-#endif
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-#endif /* WOLF_CRYPT_ERROR_H */
-
--- a/wolfssl/wolfcrypt/fe_operations.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/* fe_operations.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_FE_OPERATIONS_H
-#define WOLF_CRYPT_FE_OPERATIONS_H
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519)
-
-#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL)
-    #include <stdint.h>
-#endif
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CURVED25519_X64)
-    #define CURVED25519_X64
-#elif defined(HAVE___UINT128_T) && !defined(NO_CURVED25519_128BIT)
-    #define CURVED25519_128BIT
-#endif
-
-/*
-fe means field element.
-Here the field is \Z/(2^255-19).
-An element t, entries t[0]...t[9], represents the integer
-t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
-Bounds on each t[i] vary depending on context.
-*/
-
-#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL)
-    #define F25519_SIZE 32
-
-    WOLFSSL_LOCAL void lm_copy(byte*, const byte*);
-    WOLFSSL_LOCAL void lm_add(byte*, const byte*, const byte*);
-    WOLFSSL_LOCAL void lm_sub(byte*, const byte*, const byte*);
-    WOLFSSL_LOCAL void lm_neg(byte*,const byte*);
-    WOLFSSL_LOCAL void lm_invert(byte*, const byte*);
-    WOLFSSL_LOCAL void lm_mul(byte*,const byte*,const byte*);
-#endif
-
-
-#if !defined(FREESCALE_LTC_ECC)
-WOLFSSL_LOCAL void fe_init(void);
-
-WOLFSSL_LOCAL int  curve25519(byte * q, byte * n, byte * p);
-#endif
-
-/* default to be faster but take more memory */
-#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL)
-
-#ifdef CURVED25519_X64
-    typedef int64_t  fe[4];
-#elif defined(CURVED25519_128BIT)
-    typedef int64_t  fe[5];
-#else
-    typedef int32_t  fe[10];
-#endif
-
-WOLFSSL_LOCAL void fe_copy(fe, const fe);
-WOLFSSL_LOCAL void fe_add(fe, const fe, const fe);
-WOLFSSL_LOCAL void fe_neg(fe,const fe);
-WOLFSSL_LOCAL void fe_sub(fe, const fe, const fe);
-WOLFSSL_LOCAL void fe_invert(fe, const fe);
-WOLFSSL_LOCAL void fe_mul(fe,const fe,const fe);
-
-
-/* Based On Daniel J Bernstein's curve25519 and ed25519 Public Domain ref10
-   work. */
-
-WOLFSSL_LOCAL void fe_0(fe);
-WOLFSSL_LOCAL void fe_1(fe);
-WOLFSSL_LOCAL int  fe_isnonzero(const fe);
-WOLFSSL_LOCAL int  fe_isnegative(const fe);
-WOLFSSL_LOCAL void fe_tobytes(unsigned char *, const fe);
-WOLFSSL_LOCAL void fe_sq(fe, const fe);
-WOLFSSL_LOCAL void fe_sq2(fe,const fe);
-WOLFSSL_LOCAL void fe_frombytes(fe,const unsigned char *);
-WOLFSSL_LOCAL void fe_cswap(fe, fe, int);
-WOLFSSL_LOCAL void fe_mul121666(fe,fe);
-WOLFSSL_LOCAL void fe_cmov(fe,const fe, int);
-WOLFSSL_LOCAL void fe_pow22523(fe,const fe);
-
-/* 64 type needed for SHA512 */
-WOLFSSL_LOCAL uint64_t load_3(const unsigned char *in);
-WOLFSSL_LOCAL uint64_t load_4(const unsigned char *in);
-
-#ifdef CURVED25519_X64
-WOLFSSL_LOCAL void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py,
-                               const fe pz, const fe pt);
-WOLFSSL_LOCAL void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px,
-                               const fe py, const fe pz, const fe pt);
-WOLFSSL_LOCAL void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px,
-                             const fe py, const fe pz);
-WOLFSSL_LOCAL void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px,
-                              const fe py, const fe pz, const fe pt,
-                              const fe qxy2d, const fe qyplusx,
-                              const fe qyminusx);
-WOLFSSL_LOCAL void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px,
-                              const fe py, const fe pz, const fe pt,
-                              const fe qxy2d, const fe qyplusx,
-                              const fe qyminusx);
-WOLFSSL_LOCAL void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px,
-                             const fe py, const fe pz, const fe pt, const fe qz,
-                             const fe qt2d, const fe qyplusx,
-                             const fe qyminusx);
-WOLFSSL_LOCAL void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px,
-                             const fe py, const fe pz, const fe pt, const fe qz,
-                             const fe qt2d, const fe qyplusx,
-                             const fe qyminusx);
-WOLFSSL_LOCAL void fe_cmov_table(fe* r, fe* base, signed char b);
-#endif /* CURVED25519_X64 */
-#endif /* !CURVE25519_SMALL || !ED25519_SMALL */
-
-/* Use less memory and only 32bit types or less, but is slower
-   Based on Daniel Beer's public domain work. */
-#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL)
-static const byte c25519_base_x[F25519_SIZE] = {9};
-static const byte f25519_zero[F25519_SIZE]   = {0};
-static const byte f25519_one[F25519_SIZE]    = {1};
-static const byte fprime_zero[F25519_SIZE]   = {0};
-static const byte fprime_one[F25519_SIZE]    = {1};
-
-WOLFSSL_LOCAL void fe_load(byte *x, word32 c);
-WOLFSSL_LOCAL void fe_normalize(byte *x);
-WOLFSSL_LOCAL void fe_inv__distinct(byte *r, const byte *x);
-
-/* Conditional copy. If condition == 0, then zero is copied to dst. If
- * condition == 1, then one is copied to dst. Any other value results in
- * undefined behavior.
- */
-WOLFSSL_LOCAL void fe_select(byte *dst, const byte *zero, const byte *one,
-		   byte condition);
-
-/* Multiply a point by a small constant. The two pointers are not
- * required to be distinct.
- *
- * The constant must be less than 2^24.
- */
-WOLFSSL_LOCAL void fe_mul_c(byte *r, const byte *a, word32 b);
-WOLFSSL_LOCAL void fe_mul__distinct(byte *r, const byte *a, const byte *b);
-
-/* Compute one of the square roots of the field element, if the element
- * is square. The other square is -r.
- *
- * If the input is not square, the returned value is a valid field
- * element, but not the correct answer. If you don't already know that
- * your element is square, you should square the return value and test.
- */
-WOLFSSL_LOCAL void fe_sqrt(byte *r, const byte *x);
-
-/* Conditional copy. If condition == 0, then zero is copied to dst. If
- * condition == 1, then one is copied to dst. Any other value results in
- * undefined behavior.
- */
-WOLFSSL_LOCAL void fprime_select(byte *dst, const byte *zero, const byte *one,
-		                         byte condition);
-WOLFSSL_LOCAL void fprime_add(byte *r, const byte *a, const byte *modulus);
-WOLFSSL_LOCAL void fprime_sub(byte *r, const byte *a, const byte *modulus);
-WOLFSSL_LOCAL void fprime_mul(byte *r, const byte *a, const byte *b,
-		                      const byte *modulus);
-WOLFSSL_LOCAL void fprime_copy(byte *x, const byte *a);
-
-#endif /* CURVE25519_SMALL || ED25519_SMALL */
-#endif /* HAVE_CURVE25519 || HAVE_ED25519 */
-
-#endif /* WOLF_CRYPT_FE_OPERATIONS_H */
-
--- a/wolfssl/wolfcrypt/fips.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/wolfssl/wolfcrypt/fips_test.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/* fips_test.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLF_CRYPT_FIPS_TEST_H
-#define WOLF_CRYPT_FIPS_TEST_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Known Answer Test string inputs are hex, internal */
-WOLFSSL_LOCAL int DoKnownAnswerTests(char*, int);
-
-
-/* FIPS failure callback */
-typedef void(*wolfCrypt_fips_cb)(int ok, int err, const char* hash);
-
-/* Public set function */
-WOLFSSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf);
-
-/* Public get status functions */
-WOLFSSL_API int wolfCrypt_GetStatus_fips(void);
-WOLFSSL_API const char* wolfCrypt_GetCoreHash_fips(void);
-
-#ifdef HAVE_FORCE_FIPS_FAILURE
-    /* Public function to force failure mode for operational testing */
-    WOLFSSL_API int wolfCrypt_SetStatus_fips(int);
-#endif
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_FIPS_TEST_H */
-
-
--- a/wolfssl/wolfcrypt/ge_operations.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/* ge_operations.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
- /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */
-
-#ifndef WOLF_CRYPT_GE_OPERATIONS_H
-#define WOLF_CRYPT_GE_OPERATIONS_H
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifdef HAVE_ED25519
-
-#include <wolfssl/wolfcrypt/fe_operations.h>
-
-/*
-ge means group element.
-
-Here the group is the set of pairs (x,y) of field elements (see fe.h)
-satisfying -x^2 + y^2 = 1 + d x^2y^2
-where d = -121665/121666.
-
-Representations:
-  ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
-  ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
-  ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
-  ge_precomp (Duif): (y+x,y-x,2dxy)
-*/
-
-#ifdef ED25519_SMALL
-  typedef byte     ge[F25519_SIZE];
-#elif defined(CURVED25519_X64)
-  typedef int64_t  ge[4];
-#elif defined(CURVED25519_128BIT)
-  typedef int64_t  ge[5];
-#else
-  typedef int32_t  ge[10];
-#endif
-
-typedef struct {
-  ge X;
-  ge Y;
-  ge Z;
-} ge_p2;
-
-typedef struct {
-  ge X;
-  ge Y;
-  ge Z;
-  ge T;
-} ge_p3;
-
-
-WOLFSSL_LOCAL int  ge_compress_key(byte* out, const byte* xIn, const byte* yIn,
-                                                                word32 keySz);
-WOLFSSL_LOCAL int  ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *);
-
-WOLFSSL_LOCAL int  ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,
-                                         const ge_p3 *,const unsigned char *);
-WOLFSSL_LOCAL void ge_scalarmult_base(ge_p3 *,const unsigned char *);
-WOLFSSL_LOCAL void sc_reduce(byte* s);
-WOLFSSL_LOCAL void sc_muladd(byte* s, const byte* a, const byte* b,
-                             const byte* c);
-WOLFSSL_LOCAL void ge_tobytes(unsigned char *,const ge_p2 *);
-WOLFSSL_LOCAL void ge_p3_tobytes(unsigned char *,const ge_p3 *);
-
-
-#ifndef ED25519_SMALL
-typedef struct {
-  ge X;
-  ge Y;
-  ge Z;
-  ge T;
-} ge_p1p1;
-
-typedef struct {
-  ge yplusx;
-  ge yminusx;
-  ge xy2d;
-} ge_precomp;
-
-typedef struct {
-  ge YplusX;
-  ge YminusX;
-  ge Z;
-  ge T2d;
-} ge_cached;
-
-#endif /* !ED25519_SMALL */
-
-#endif /* HAVE_ED25519 */
-
-#endif /* WOLF_CRYPT_GE_OPERATIONS_H */
-
--- a/wolfssl/wolfcrypt/hash.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/* hash.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/hash.h
-*/
-
-#ifndef WOLF_CRYPT_HASH_H
-#define WOLF_CRYPT_HASH_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_MD5
-    #include <wolfssl/wolfcrypt/md5.h>
-#endif
-#ifndef NO_SHA
-    #include <wolfssl/wolfcrypt/sha.h>
-#endif
-#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
-    #include <wolfssl/wolfcrypt/sha256.h>
-#endif
-#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
-    #include <wolfssl/wolfcrypt/sha512.h>
-#endif
-#ifdef HAVE_BLAKE2
-    #include <wolfssl/wolfcrypt/blake2.h>
-#endif
-#ifdef WOLFSSL_SHA3
-    #include <wolfssl/wolfcrypt/sha3.h>
-#endif
-#ifndef NO_MD4
-    #include <wolfssl/wolfcrypt/md4.h>
-#endif
-#ifdef WOLFSSL_MD2
-    #include <wolfssl/wolfcrypt/md2.h>
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#if !defined(HAVE_FIPS) && !defined(NO_OLD_WC_NAMES)
-    #define MAX_DIGEST_SIZE WC_MAX_DIGEST_SIZE
-#endif
-
-
-typedef union {
-    #ifndef NO_MD5
-        wc_Md5 md5;
-    #endif
-    #ifndef NO_SHA
-        wc_Sha sha;
-    #endif
-    #ifdef WOLFSSL_SHA224
-        wc_Sha224 sha224;
-    #endif
-    #ifndef NO_SHA256
-        wc_Sha256 sha256;
-    #endif
-    #ifdef WOLFSSL_SHA384
-        wc_Sha384 sha384;
-    #endif
-    #ifdef WOLFSSL_SHA512
-        wc_Sha512 sha512;
-    #endif
-} wc_HashAlg;
-
-/* Find largest possible digest size
-   Note if this gets up to the size of 80 or over check smallstack build */
-#if defined(WOLFSSL_SHA3)
-    #define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA3_224_BLOCK_SIZE /* 224 is the largest block size */
-#elif defined(WOLFSSL_SHA512)
-    #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA512_BLOCK_SIZE
-#elif defined(HAVE_BLAKE2)
-    #define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES
-    #define WC_MAX_BLOCK_SIZE  BLAKE2B_BLOCKBYTES
-#elif defined(WOLFSSL_SHA384)
-    #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA384_BLOCK_SIZE
-#elif !defined(NO_SHA256)
-    #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA256_BLOCK_SIZE
-#elif defined(WOLFSSL_SHA224)
-    #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA224_BLOCK_SIZE
-#elif !defined(NO_SHA)
-    #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_SHA_BLOCK_SIZE
-#elif !defined(NO_MD5)
-    #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE
-    #define WC_MAX_BLOCK_SIZE  WC_MD5_BLOCK_SIZE
-#else
-    #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */
-    #define WC_MAX_BLOCK_SIZE  128
-#endif
-
-#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
-WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type);
-WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid);
-#endif
-
-WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType);
-
-WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type);
-WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type);
-WOLFSSL_API int wc_Hash(enum wc_HashType hash_type,
-    const byte* data, word32 data_len,
-    byte* hash, word32 hash_len);
-
-/* generic hash operation wrappers */
-WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type);
-WOLFSSL_API int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type,
-    const byte* data, word32 dataSz);
-WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type,
-    byte* out);
-
-
-#ifndef NO_MD5
-#include <wolfssl/wolfcrypt/md5.h>
-WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash);
-#endif
-
-#ifndef NO_SHA
-#include <wolfssl/wolfcrypt/sha.h>
-WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*);
-#endif
-
-#ifdef WOLFSSL_SHA224
-#include <wolfssl/wolfcrypt/sha256.h>
-WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*);
-#endif /* defined(WOLFSSL_SHA224) */
-
-#ifndef NO_SHA256
-#include <wolfssl/wolfcrypt/sha256.h>
-WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*);
-#endif
-
-#ifdef WOLFSSL_SHA384
-#include <wolfssl/wolfcrypt/sha512.h>
-WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*);
-#endif /* defined(WOLFSSL_SHA384) */
-
-#ifdef WOLFSSL_SHA512
-#include <wolfssl/wolfcrypt/sha512.h>
-WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*);
-#endif /* WOLFSSL_SHA512 */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_HASH_H */
-
--- a/wolfssl/wolfcrypt/hc128.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* hc128.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/hc128.h
-*/
-
-
-#ifndef WOLF_CRYPT_HC128_H
-#define WOLF_CRYPT_HC128_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_HC128
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum {
-	HC128_ENC_TYPE =  WC_CIPHER_HC128,     /* cipher unique type */
-};
-
-/* HC-128 stream cipher */
-typedef struct HC128 {
-    word32 T[1024];             /* P[i] = T[i];  Q[i] = T[1024 + i ]; */
-    word32 X[16];
-    word32 Y[16];
-    word32 counter1024;         /* counter1024 = i mod 1024 at the ith step */
-    word32 key[8];
-    word32 iv[8];
-#ifdef XSTREAM_ALIGN
-    void*  heap;  /* heap hint, currently XMALLOC only used with aligning */
-#endif
-} HC128;
-
-
-WOLFSSL_API int wc_Hc128_Process(HC128*, byte*, const byte*, word32);
-WOLFSSL_API int wc_Hc128_SetKey(HC128*, const byte* key, const byte* iv);
-
-WOLFSSL_LOCAL int wc_Hc128_SetHeap(HC128* ctx, void* heap);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_HC128 */
-#endif /* WOLF_CRYPT_HC128_H */
-
-
--- a/wolfssl/wolfcrypt/hmac.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/* hmac.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/hmac.h
-*/
-
-#ifndef NO_HMAC
-
-#ifndef WOLF_CRYPT_HMAC_H
-#define WOLF_CRYPT_HMAC_H
-
-#include <wolfssl/wolfcrypt/hash.h>
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-/* for fips @wc_fips */
-    #include <cyassl/ctaocrypt/hmac.h>
-    #define WC_HMAC_BLOCK_SIZE HMAC_BLOCK_SIZE
-#endif
-
-
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-	#include <wolfssl/wolfcrypt/fips.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifndef NO_OLD_WC_NAMES
-    #define HMAC_BLOCK_SIZE WC_HMAC_BLOCK_SIZE
-#endif
-
-enum {
-    HMAC_FIPS_MIN_KEY = 14,   /* 112 bit key length minimum */
-
-    IPAD    = 0x36,
-    OPAD    = 0x5C,
-
-/* If any hash is not enabled, add the ID here. */
-#ifdef NO_MD5
-    WC_MD5     = WC_HASH_TYPE_MD5,
-#endif
-#ifdef NO_SHA
-    WC_SHA     = WC_HASH_TYPE_SHA,
-#endif
-#ifdef NO_SHA256
-    WC_SHA256  = WC_HASH_TYPE_SHA256,
-#endif
-#ifndef WOLFSSL_SHA512
-    WC_SHA512  = WC_HASH_TYPE_SHA512,
-#endif
-#ifndef WOLFSSL_SHA384
-    WC_SHA384  = WC_HASH_TYPE_SHA384,
-#endif
-#ifndef HAVE_BLAKE2
-    BLAKE2B_ID = WC_HASH_TYPE_BLAKE2B,
-#endif
-#ifndef WOLFSSL_SHA224
-    WC_SHA224  = WC_HASH_TYPE_SHA224,
-#endif
-#ifndef WOLFSSL_SHA3
-    WC_SHA3_224 = WC_HASH_TYPE_SHA3_224,
-    WC_SHA3_256 = WC_HASH_TYPE_SHA3_256,
-    WC_SHA3_384 = WC_HASH_TYPE_SHA3_384,
-    WC_SHA3_512 = WC_HASH_TYPE_SHA3_512,
-#endif
-};
-
-/* Select the largest available hash for the buffer size. */
-#define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE
-
-#if !defined(WOLFSSL_SHA3) && !defined(WOLFSSL_SHA512) && !defined(HAVE_BLAKE2) && \
-    !defined(WOLFSSL_SHA384) && defined(NO_SHA256) && defined(WOLFSSL_SHA224) && \
-     defined(NO_SHA) && defined(NO_MD5)
-    #error "You have to have some kind of hash if you want to use HMAC."
-#endif
-
-
-/* hash union */
-typedef union {
-#ifndef NO_MD5
-    wc_Md5 md5;
-#endif
-#ifndef NO_SHA
-    wc_Sha sha;
-#endif
-#ifdef WOLFSSL_SHA224
-    wc_Sha224 sha224;
-#endif
-#ifndef NO_SHA256
-    wc_Sha256 sha256;
-#endif
-#ifdef WOLFSSL_SHA384
-    wc_Sha384 sha384;
-#endif
-#ifdef WOLFSSL_SHA512
-    wc_Sha512 sha512;
-#endif
-#ifdef HAVE_BLAKE2
-    Blake2b blake2b;
-#endif
-#ifdef WOLFSSL_SHA3
-    wc_Sha3 sha3;
-#endif
-} Hash;
-
-/* Hmac digest */
-typedef struct Hmac {
-    Hash    hash;
-    word32  ipad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];  /* same block size all*/
-    word32  opad[WC_HMAC_BLOCK_SIZE  / sizeof(word32)];
-    word32  innerHash[WC_MAX_DIGEST_SIZE / sizeof(word32)];
-    void*   heap;                 /* heap hint */
-    byte    macType;              /* md5 sha or sha256 */
-    byte    innerHashKeyed;       /* keyed flag */
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-    word16       keyLen;          /* hmac key length (key in ipad) */
-#endif /* WOLFSSL_ASYNC_CRYPT */
-} Hmac;
-
-#endif /* HAVE_FIPS */
-
-/* does init */
-WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz);
-WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32);
-WOLFSSL_API int wc_HmacFinal(Hmac*, byte*);
-WOLFSSL_API int wc_HmacSizeByType(int type);
-
-WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId);
-WOLFSSL_API void wc_HmacFree(Hmac*);
-
-WOLFSSL_API int wolfSSL_GetHmacMaxSize(void);
-
-WOLFSSL_LOCAL int _InitHmac(Hmac* hmac, int type, void* heap);
-
-#ifdef HAVE_HKDF
-
-WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz,
-                                const byte* inKey, word32 inKeySz, byte* out);
-WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz,
-                               const byte* info, word32 infoSz,
-                               byte* out,        word32 outSz);
-
-WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
-                    const byte* salt, word32 saltSz,
-                    const byte* info, word32 infoSz,
-                    byte* out, word32 outSz);
-
-#endif /* HAVE_HKDF */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_HMAC_H */
-
-#endif /* NO_HMAC */
-
-
--- a/wolfssl/wolfcrypt/idea.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* idea.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/idea.h
-*/
-
-#ifndef WOLF_CRYPT_IDEA_H
-#define WOLF_CRYPT_IDEA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_IDEA
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum {
-    IDEA_MODULO     = 0x10001,             /* 2^16+1 */
-    IDEA_2EXP16     = 0x10000,             /* 2^16 */
-    IDEA_MASK       = 0xFFFF,              /* 16 bits set to one */
-    IDEA_ROUNDS     = 8,                   /* number of rounds for IDEA */
-    IDEA_SK_NUM     = (6*IDEA_ROUNDS + 4), /* number of subkeys */
-    IDEA_KEY_SIZE   = 16,                  /* size of key in bytes */
-    IDEA_BLOCK_SIZE = 8,                   /* size of IDEA blocks in bytes */
-    IDEA_IV_SIZE    = 8,                   /* size of IDEA IV in bytes */
-    IDEA_ENCRYPTION = 0,
-    IDEA_DECRYPTION = 1
-};
-
-/* IDEA encryption and decryption */
-typedef struct Idea {
-    word32  reg[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
-    word32  tmp[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
-    word16  skey[IDEA_SK_NUM]; /* 832 bits expanded key */
-} Idea;
-
-WOLFSSL_API int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz,
-                              const byte *iv, int dir);
-WOLFSSL_API int wc_IdeaSetIV(Idea *idea, const byte* iv);
-WOLFSSL_API int wc_IdeaCipher(Idea *idea, byte* out, const byte* in);
-WOLFSSL_API int wc_IdeaCbcEncrypt(Idea *idea, byte* out,
-                                  const byte* in, word32 len);
-WOLFSSL_API int wc_IdeaCbcDecrypt(Idea *idea, byte* out,
-                                  const byte* in, word32 len);
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_IDEA */
-#endif /* WOLF_CRYPT_IDEA_H */
-
--- a/wolfssl/wolfcrypt/integer.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,402 +0,0 @@
-/* integer.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/*
- * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
- * http://math.libtomcrypt.com
- */
-
-
-#ifndef WOLF_CRYPT_INTEGER_H
-#define WOLF_CRYPT_INTEGER_H
-
-/* may optionally use fast math instead, not yet supported on all platforms and
-   may not be faster on all
-*/
-#include <wolfssl/wolfcrypt/types.h>       /* will set MP_xxBIT if not default */
-#ifdef WOLFSSL_SP_MATH
-    #include <wolfssl/wolfcrypt/sp_int.h>
-#elif defined(USE_FAST_MATH)
-    #include <wolfssl/wolfcrypt/tfm.h>
-#else
-
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifndef CHAR_BIT
-    #include <limits.h>
-#endif
-
-#include <wolfssl/wolfcrypt/mpi_class.h>
-
-/* wolf big int and common functions */
-#include <wolfssl/wolfcrypt/wolfmath.h>
-
-
-#ifdef WOLFSSL_PUBLIC_MP
-    #define MP_API   WOLFSSL_API
-#else
-    #define MP_API
-#endif
-
-#ifndef MIN
-   #define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-#ifndef MAX
-   #define MAX(x,y) ((x)>(y)?(x):(y))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-
-/* C++ compilers don't like assigning void * to mp_digit * */
-#define  OPT_CAST(x)  (x *)
-
-#elif defined(_SH3)
-
-/* SuperH SH3 compiler doesn't like assigning voi* to mp_digit* */
-#define  OPT_CAST(x)  (x *)
-
-#else
-
-/* C on the other hand doesn't care */
-#define  OPT_CAST(x)
-
-#endif /* __cplusplus */
-
-
-/* detect 64-bit mode if possible */
-#if defined(__x86_64__)
-   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
-      #define MP_64BIT
-   #endif
-#endif
-/* if intel compiler doesn't provide 128 bit type don't turn on 64bit */
-#if defined(MP_64BIT) && defined(__INTEL_COMPILER) && !defined(HAVE___UINT128_T)
-    #undef MP_64BIT
-#endif
-
-
-/* allow user to define on mp_digit, mp_word, DIGIT_BIT types */
-#ifndef WOLFSSL_BIGINT_TYPES
-
-/* some default configurations.
- *
- * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
- * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
- *
- * At the very least a mp_digit must be able to hold 7 bits
- * [any size beyond that is ok provided it doesn't overflow the data type]
- */
-#ifdef MP_8BIT
-   typedef unsigned char      mp_digit;
-   typedef unsigned short     mp_word;
-#elif defined(MP_16BIT) || defined(NO_64BIT)
-   typedef unsigned short     mp_digit;
-   typedef unsigned int       mp_word;
-   #define DIGIT_BIT          12
-#elif defined(MP_64BIT)
-   /* for GCC only on supported platforms */
-   typedef unsigned long long mp_digit;  /* 64 bit type, 128 uses mode(TI) */
-   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
-
-   #define DIGIT_BIT          60
-#else
-   /* this is the default case, 28-bit digits */
-
-   #if defined(_MSC_VER) || defined(__BORLANDC__)
-      typedef unsigned __int64   ulong64;
-   #else
-      typedef unsigned long long ulong64;
-   #endif
-
-   typedef unsigned int       mp_digit;  /* long could be 64 now, changed TAO */
-   typedef ulong64            mp_word;
-
-#ifdef MP_31BIT
-   /* this is an extension that uses 31-bit digits */
-   #define DIGIT_BIT          31
-#else
-   /* default case is 28-bit digits, defines MP_28BIT as a handy test macro */
-   #define DIGIT_BIT          28
-   #define MP_28BIT
-#endif
-#endif
-
-#endif /* WOLFSSL_BIGINT_TYPES */
-
-/* otherwise the bits per digit is calculated automatically from the size of
-   a mp_digit */
-#ifndef DIGIT_BIT
-   #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))
-      /* bits per digit */
-#endif
-
-#define MP_DIGIT_BIT     DIGIT_BIT
-#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
-#define MP_DIGIT_MAX     MP_MASK
-
-/* equalities */
-#define MP_LT        -1   /* less than */
-#define MP_EQ         0   /* equal to */
-#define MP_GT         1   /* greater than */
-
-#define MP_ZPOS       0   /* positive integer */
-#define MP_NEG        1   /* negative */
-
-#define MP_OKAY       0   /* ok result */
-#define MP_MEM        -2  /* out of mem */
-#define MP_VAL        -3  /* invalid input */
-#define MP_NOT_INF	  -4  /* point not at infinity */
-#define MP_RANGE      MP_NOT_INF
-
-#define MP_YES        1   /* yes response */
-#define MP_NO         0   /* no response */
-
-/* Primality generation flags */
-#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
-#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
-#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
-
-typedef int           mp_err;
-
-/* define this to use lower memory usage routines (exptmods mostly) */
-#define MP_LOW_MEM
-
-/* default precision */
-#ifndef MP_PREC
-   #ifndef MP_LOW_MEM
-      #define MP_PREC                 32     /* default digits of precision */
-   #else
-      #define MP_PREC                 1      /* default digits of precision */
-   #endif
-#endif
-
-/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD -
-   BITS_PER_DIGIT*2) */
-#define MP_WARRAY  (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
-
-#ifdef HAVE_WOLF_BIGINT
-    struct WC_BIGINT;
-#endif
-
-/* the mp_int structure */
-typedef struct mp_int {
-    int used, alloc, sign;
-    mp_digit *dp;
-
-#ifdef HAVE_WOLF_BIGINT
-    struct WC_BIGINT raw; /* unsigned binary (big endian) */
-#endif
-} mp_int;
-#define MP_INT_DEFINED
-
-/* callback for mp_prime_random, should fill dst with random bytes and return
-   how many read [up to len] */
-typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
-
-
-#define USED(m)    ((m)->used)
-#define DIGIT(m,k) ((m)->dp[(k)])
-#define SIGN(m)    ((m)->sign)
-
-
-/* ---> Basic Manipulations <--- */
-#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
-#define mp_isone(a) \
-    (((((a)->used == 1)) && ((a)->dp[0] == 1u)) ? MP_YES : MP_NO)
-#define mp_iseven(a) \
-    (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO)
-#define mp_isodd(a) \
-    (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO)
-#define mp_isneg(a)  (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO)
-
-/* number of primes */
-#ifdef MP_8BIT
-   #define PRIME_SIZE      31
-#else
-   #define PRIME_SIZE      256
-#endif
-
-#ifndef MAX_INVMOD_SZ
-    #if defined(WOLFSSL_MYSQL_COMPATIBLE)
-        #define MAX_INVMOD_SZ 8192
-    #else
-        #define MAX_INVMOD_SZ 4096
-    #endif
-#endif
-
-#define mp_prime_random(a, t, size, bbs, cb, dat) \
-   mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
-
-#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
-#define mp_raw_size(mp)           mp_signed_bin_size(mp)
-#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
-#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
-#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
-#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
-
-#define MP_RADIX_BIN  2
-#define MP_RADIX_OCT  8
-#define MP_RADIX_DEC  10
-#define MP_RADIX_HEX  16
-#define MP_RADIX_MAX  64
-
-#define mp_tobinary(M, S)  mp_toradix((M), (S), MP_RADIX_BIN)
-#define mp_tooctal(M, S)   mp_toradix((M), (S), MP_RADIX_OCT)
-#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC)
-#define mp_tohex(M, S)     mp_toradix((M), (S), MP_RADIX_HEX)
-
-#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
-
-#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
-    defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL)
-extern const char *mp_s_rmap;
-#endif
-
-/* 6 functions needed by Rsa */
-MP_API int  mp_init (mp_int * a);
-MP_API void mp_clear (mp_int * a);
-MP_API void mp_free (mp_int * a);
-MP_API void mp_forcezero(mp_int * a);
-MP_API int  mp_unsigned_bin_size(mp_int * a);
-MP_API int  mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
-MP_API int  mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b);
-MP_API int  mp_to_unsigned_bin (mp_int * a, unsigned char *b);
-MP_API int  mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
-/* end functions needed by Rsa */
-
-/* functions added to support above needed, removed TOOM and KARATSUBA */
-MP_API int  mp_count_bits (mp_int * a);
-MP_API int  mp_leading_bit (mp_int * a);
-MP_API int  mp_init_copy (mp_int * a, mp_int * b);
-MP_API int  mp_copy (mp_int * a, mp_int * b);
-MP_API int  mp_grow (mp_int * a, int size);
-MP_API int  mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
-MP_API void mp_zero (mp_int * a);
-MP_API void mp_clamp (mp_int * a);
-MP_API void mp_exch (mp_int * a, mp_int * b);
-MP_API void mp_rshd (mp_int * a, int b);
-MP_API void mp_rshb (mp_int * a, int b);
-MP_API int  mp_mod_2d (mp_int * a, int b, mp_int * c);
-MP_API int  mp_mul_2d (mp_int * a, int b, mp_int * c);
-MP_API int  mp_lshd (mp_int * a, int b);
-MP_API int  mp_abs (mp_int * a, mp_int * b);
-MP_API int  mp_invmod (mp_int * a, mp_int * b, mp_int * c);
-int  fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_cmp_mag (mp_int * a, mp_int * b);
-MP_API int  mp_cmp (mp_int * a, mp_int * b);
-MP_API int  mp_cmp_d(mp_int * a, mp_digit b);
-MP_API int  mp_set (mp_int * a, mp_digit b);
-MP_API int  mp_is_bit_set (mp_int * a, mp_digit b);
-MP_API int  mp_mod (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
-MP_API int  mp_div_2(mp_int * a, mp_int * b);
-MP_API int  mp_add (mp_int * a, mp_int * b, mp_int * c);
-int  s_mp_add (mp_int * a, mp_int * b, mp_int * c);
-int  s_mp_sub (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_sub (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_reduce_is_2k_l(mp_int *a);
-MP_API int  mp_reduce_is_2k(mp_int *a);
-MP_API int  mp_dr_is_modulus(mp_int *a);
-MP_API int  mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y,
-                             int);
-MP_API int  mp_montgomery_setup (mp_int * n, mp_digit * rho);
-int  fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
-MP_API int  mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
-MP_API void mp_dr_setup(mp_int *a, mp_digit *d);
-MP_API int  mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k);
-MP_API int  mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
-int  fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
-int  s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
-MP_API int  mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
-MP_API int  mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
-MP_API int  mp_reduce (mp_int * x, mp_int * m, mp_int * mu);
-MP_API int  mp_reduce_setup (mp_int * a, mp_int * b);
-int  s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
-MP_API int  mp_montgomery_calc_normalization (mp_int * a, mp_int * b);
-int  s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
-int  s_mp_sqr (mp_int * a, mp_int * b);
-int  fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
-int  fast_s_mp_sqr (mp_int * a, mp_int * b);
-MP_API int  mp_init_size (mp_int * a, int size);
-MP_API int  mp_div_3 (mp_int * a, mp_int *c, mp_digit * d);
-MP_API int  mp_mul_2(mp_int * a, mp_int * b);
-MP_API int  mp_mul (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_sqr (mp_int * a, mp_int * b);
-MP_API int  mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
-MP_API int  mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
-MP_API int  mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
-MP_API int  mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
-MP_API int  mp_2expt (mp_int * a, int b);
-MP_API int  mp_set_bit (mp_int * a, int b);
-MP_API int  mp_reduce_2k_setup(mp_int *a, mp_digit *d);
-MP_API int  mp_add_d (mp_int* a, mp_digit b, mp_int* c);
-MP_API int  mp_set_int (mp_int * a, unsigned long b);
-MP_API int  mp_sub_d (mp_int * a, mp_digit b, mp_int * c);
-/* end support added functions */
-
-/* added */
-MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
-                         mp_int* f);
-MP_API int mp_toradix (mp_int *a, char *str, int radix);
-MP_API int mp_radix_size (mp_int * a, int radix, int *size);
-
-#ifdef WOLFSSL_DEBUG_MATH
-    MP_API void mp_dump(const char* desc, mp_int* a, byte verbose);
-#else
-    #define mp_dump(desc, a, verbose)
-#endif
-
-#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN)
-    MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c);
-#endif
-#if !defined(NO_DSA) || defined(HAVE_ECC)
-    MP_API int mp_read_radix(mp_int* a, const char* str, int radix);
-#endif
-
-#ifdef WOLFSSL_KEY_GEN
-    MP_API int mp_prime_is_prime (mp_int * a, int t, int *result);
-    MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c);
-    MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c);
-    MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
-#endif
-
-MP_API int mp_cnt_lsb(mp_int *a);
-MP_API int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c);
-
-
-/* wolf big int and common functions */
-#include <wolfssl/wolfcrypt/wolfmath.h>
-
-
-#ifdef __cplusplus
-   }
-#endif
-
-
-#endif /* USE_FAST_MATH */
-
-#endif  /* WOLF_CRYPT_INTEGER_H */
-
-
--- a/wolfssl/wolfcrypt/logging.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/* logging.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/logging.h
-*/
-
-
-/* submitted by eof */
-
-
-#ifndef WOLFSSL_LOGGING_H
-#define WOLFSSL_LOGGING_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-enum wc_LogLevels {
-    ERROR_LOG = 0,
-    INFO_LOG,
-    ENTER_LOG,
-    LEAVE_LOG,
-    OTHER_LOG
-};
-
-#ifdef WOLFSSL_FUNC_TIME
-/* WARNING: This code is only to be used for debugging performance.
- *          The code is not thread-safe.
- *          Do not use WOLFSSL_FUNC_TIME in production code.
- */
-enum wc_FuncNum {
-    WC_FUNC_CLIENT_HELLO_SEND = 0,
-    WC_FUNC_CLIENT_HELLO_DO,
-    WC_FUNC_SERVER_HELLO_SEND,
-    WC_FUNC_SERVER_HELLO_DO,
-    WC_FUNC_ENCRYPTED_EXTENSIONS_SEND,
-    WC_FUNC_ENCRYPTED_EXTENSIONS_DO,
-    WC_FUNC_CERTIFICATE_REQUEST_SEND,
-    WC_FUNC_CERTIFICATE_REQUEST_DO,
-    WC_FUNC_CERTIFICATE_SEND,
-    WC_FUNC_CERTIFICATE_DO,
-    WC_FUNC_CERTIFICATE_VERIFY_SEND,
-    WC_FUNC_CERTIFICATE_VERIFY_DO,
-    WC_FUNC_FINISHED_SEND,
-    WC_FUNC_FINISHED_DO,
-    WC_FUNC_KEY_UPDATE_SEND,
-    WC_FUNC_KEY_UPDATE_DO,
-    WC_FUNC_EARLY_DATA_SEND,
-    WC_FUNC_EARLY_DATA_DO,
-    WC_FUNC_NEW_SESSION_TICKET_SEND,
-    WC_FUNC_NEW_SESSION_TICKET_DO,
-    WC_FUNC_SERVER_HELLO_DONE_SEND,
-    WC_FUNC_SERVER_HELLO_DONE_DO,
-    WC_FUNC_TICKET_SEND,
-    WC_FUNC_TICKET_DO,
-    WC_FUNC_CLIENT_KEY_EXCHANGE_SEND,
-    WC_FUNC_CLIENT_KEY_EXCHANGE_DO,
-    WC_FUNC_CERTIFICATE_STATUS_SEND,
-    WC_FUNC_CERTIFICATE_STATUS_DO,
-    WC_FUNC_SERVER_KEY_EXCHANGE_SEND,
-    WC_FUNC_SERVER_KEY_EXCHANGE_DO,
-    WC_FUNC_END_OF_EARLY_DATA_SEND,
-    WC_FUNC_END_OF_EARLY_DATA_DO,
-    WC_FUNC_COUNT
-};
-#endif
-
-typedef void (*wolfSSL_Logging_cb)(const int logLevel,
-                                   const char *const logMessage);
-
-WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function);
-
-/* turn logging on, only if compiled in */
-WOLFSSL_API int  wolfSSL_Debugging_ON(void);
-/* turn logging off */
-WOLFSSL_API void wolfSSL_Debugging_OFF(void);
-
-
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-    WOLFSSL_LOCAL int wc_LoggingInit(void);
-    WOLFSSL_LOCAL int wc_LoggingCleanup(void);
-    WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf,
-            char* file);
-    WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file,
-            const char **reason, int *line);
-    WOLFSSL_LOCAL void wc_RemoveErrorNode(int index);
-    WOLFSSL_LOCAL void wc_ClearErrorNodes(void);
-    WOLFSSL_LOCAL int wc_PullErrorNode(const char **file, const char **reason,
-                            int *line);
-    WOLFSSL_API   int wc_SetLoggingHeap(void* h);
-    WOLFSSL_API   int wc_ERR_remove_state(void);
-    #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
-        WOLFSSL_API   void wc_ERR_print_errors_fp(XFILE fp);
-    #endif
-#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
-
-#ifdef WOLFSSL_FUNC_TIME
-    /* WARNING: This code is only to be used for debugging performance.
-     *          The code is not thread-safe.
-     *          Do not use WOLFSSL_FUNC_TIME in production code.
-     */
-    WOLFSSL_API void WOLFSSL_START(int funcNum);
-    WOLFSSL_API void WOLFSSL_END(int funcNum);
-    WOLFSSL_API void WOLFSSL_TIME(int count);
-#else
-    #define WOLFSSL_START(n)
-    #define WOLFSSL_END(n)
-    #define WOLFSSL_TIME(n)
-#endif
-
-#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_DEBUG_ERRORS_ONLY)
-    #if defined(_WIN32)
-        #if defined(INTIME_RTOS)
-            #define __func__ NULL
-        #else
-            #define __func__ __FUNCTION__
-        #endif
-    #endif
-
-    /* a is prepended to m and b is appended, creating a log msg a + m + b */
-    #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " "  #b
-
-    WOLFSSL_API void WOLFSSL_ENTER(const char* msg);
-    WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret);
-    #define WOLFSSL_STUB(m) \
-        WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented))
-
-    WOLFSSL_API void WOLFSSL_MSG(const char* msg);
-    WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length);
-
-#else
-
-    #define WOLFSSL_ENTER(m)
-    #define WOLFSSL_LEAVE(m, r)
-    #define WOLFSSL_STUB(m)
-
-    #define WOLFSSL_MSG(m)
-    #define WOLFSSL_BUFFER(b, l)
-
-#endif /* DEBUG_WOLFSSL && !WOLFSSL_DEBUG_ERRORS_ONLY */
-
-#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-
-    #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
-        WOLFSSL_API void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line,
-            const char* file, void* ctx);
-        #define WOLFSSL_ERROR(x) \
-            WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__, NULL)
-    #else
-        WOLFSSL_API void WOLFSSL_ERROR(int err);
-    #endif
-    WOLFSSL_API void WOLFSSL_ERROR_MSG(const char* msg);
-
-#else
-    #define WOLFSSL_ERROR(e)
-    #define WOLFSSL_ERROR_MSG(m)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* WOLFSSL_LOGGING_H */
-
-
--- a/wolfssl/wolfcrypt/md2.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* md2.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/md2.h
-*/
-
-
-#ifndef WOLF_CRYPT_MD2_H
-#define WOLF_CRYPT_MD2_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef WOLFSSL_MD2
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* in bytes */
-enum {
-    MD2             =  WC_HASH_TYPE_MD2,
-    MD2_BLOCK_SIZE  = 16,
-    MD2_DIGEST_SIZE = 16,
-    MD2_PAD_SIZE    = 16,
-    MD2_X_SIZE      = 48
-};
-
-
-/* Md2 digest */
-typedef struct Md2 {
-    word32  count;   /* bytes % PAD_SIZE  */
-    byte    X[MD2_X_SIZE];
-    byte    C[MD2_BLOCK_SIZE];
-    byte    buffer[MD2_BLOCK_SIZE];
-} Md2;
-
-
-WOLFSSL_API void wc_InitMd2(Md2*);
-WOLFSSL_API void wc_Md2Update(Md2*, const byte*, word32);
-WOLFSSL_API void wc_Md2Final(Md2*, byte*);
-WOLFSSL_API int  wc_Md2Hash(const byte*, word32, byte*);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_MD2 */
-#endif /* WOLF_CRYPT_MD2_H */
-
-
--- a/wolfssl/wolfcrypt/md4.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* md4.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/md4.h
-*/
-
-#ifndef WOLF_CRYPT_MD4_H
-#define WOLF_CRYPT_MD4_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_MD4
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* in bytes */
-enum {
-    MD4             =  WC_HASH_TYPE_MD4,
-    MD4_BLOCK_SIZE  = 64,
-    MD4_DIGEST_SIZE = 16,
-    MD4_PAD_SIZE    = 56
-};
-
-
-/* MD4 digest */
-typedef struct Md4 {
-    word32  buffLen;   /* in bytes          */
-    word32  loLen;     /* length in bytes   */
-    word32  hiLen;     /* length in bytes   */
-    word32  digest[MD4_DIGEST_SIZE / sizeof(word32)];
-    word32  buffer[MD4_BLOCK_SIZE  / sizeof(word32)];
-} Md4;
-
-
-WOLFSSL_API void wc_InitMd4(Md4*);
-WOLFSSL_API void wc_Md4Update(Md4*, const byte*, word32);
-WOLFSSL_API void wc_Md4Final(Md4*, byte*);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_MD4 */
-#endif /* WOLF_CRYPT_MD4_H */
-
-
--- a/wolfssl/wolfcrypt/md5.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/* md5.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/md5.h
-*/
-
-
-#ifndef WOLF_CRYPT_MD5_H
-#define WOLF_CRYPT_MD5_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_MD5
-
-#ifdef HAVE_FIPS
-    #define wc_InitMd5   InitMd5
-    #define wc_Md5Update Md5Update
-    #define wc_Md5Final  Md5Final
-    #define wc_Md5Hash   Md5Hash
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifndef NO_OLD_WC_NAMES
-    #define Md5             wc_Md5
-    #define MD5             WC_MD5
-    #define MD5_BLOCK_SIZE  WC_MD5_BLOCK_SIZE
-    #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE
-    #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE
-#endif
-
-/* in bytes */
-enum {
-    WC_MD5             =  WC_HASH_TYPE_MD5,
-    WC_MD5_BLOCK_SIZE  = 64,
-    WC_MD5_DIGEST_SIZE = 16,
-    WC_MD5_PAD_SIZE    = 56
-};
-
-
-#ifdef WOLFSSL_MICROCHIP_PIC32MZ
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-#endif
-#ifdef STM32_HASH
-    #include <wolfssl/wolfcrypt/port/st/stm32.h>
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#ifdef WOLFSSL_TI_HASH
-    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
-#elif defined(WOLFSSL_IMX6_CAAM)
-    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
-#else
-
-/* MD5 digest */
-typedef struct wc_Md5 {
-#ifdef STM32_HASH
-    STM32_HASH_Context stmCtx;
-#else
-    word32  buffLen;   /* in bytes          */
-    word32  loLen;     /* length in bytes   */
-    word32  hiLen;     /* length in bytes   */
-    word32  buffer[WC_MD5_BLOCK_SIZE  / sizeof(word32)];
-#ifdef WOLFSSL_PIC32MZ_HASH
-    word32  digest[PIC32_DIGEST_SIZE / sizeof(word32)];
-#else
-    word32  digest[WC_MD5_DIGEST_SIZE / sizeof(word32)];
-#endif
-    void*   heap;
-#ifdef WOLFSSL_PIC32MZ_HASH
-    hashUpdCache cache; /* cache for updates */
-#endif
-#endif /* STM32_HASH */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-} wc_Md5;
-
-#endif /* WOLFSSL_TI_HASH */
-
-WOLFSSL_API int wc_InitMd5(wc_Md5*);
-WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int);
-WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32);
-WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*);
-WOLFSSL_API void wc_Md5Free(wc_Md5*);
-
-WOLFSSL_API int  wc_Md5GetHash(wc_Md5*, byte*);
-WOLFSSL_API int  wc_Md5Copy(wc_Md5*, wc_Md5*);
-
-#ifdef WOLFSSL_PIC32MZ_HASH
-WOLFSSL_API void wc_Md5SizeSet(wc_Md5* md5, word32 len);
-#endif
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_MD5 */
-#endif /* WOLF_CRYPT_MD5_H */
-
--- a/wolfssl/wolfcrypt/mem_track.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/* mem_track.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* The memory tracker overrides the wolfSSL memory callback system and uses a
- * static to track the total, peak and currently allocated bytes.
- *
- * If you are already using the memory callbacks then enabling this will
- * override the memory callbacks and prevent your memory callbacks from
- * working. This assumes malloc() and free() are available. Feel free to
- * customize this for your needs.
-
- * The enable this feature define the following:
- * #define USE_WOLFSSL_MEMORY
- * #define WOLFSSL_TRACK_MEMORY
- *
- * On startup call:
- * InitMemoryTracker();
- *
- * When ready to dump the memory report call:
- * ShowMemoryTracker();
- *
- * Report example:
- * total   Allocs =       228
- * total   Bytes  =     93442
- * peak    Bytes  =      8840
- * current Bytes  =         0
- *
- *
- * You can also:
- * #define WOLFSSL_DEBUG_MEMORY
- *
- * To print every alloc/free along with the function and line number.
- * Example output:
- * Alloc: 0x7fa14a500010 -> 120 at wc_InitRng:496
- * Free: 0x7fa14a500010 -> 120 at wc_FreeRng:606
- */
-
-
-#ifndef WOLFSSL_MEM_TRACK_H
-#define WOLFSSL_MEM_TRACK_H
-
-#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY)
-
-    #include "wolfssl/wolfcrypt/logging.h"
-
-    typedef struct memoryStats {
-        size_t totalAllocs;     /* number of allocations */
-        size_t totalDeallocs;   /* number of deallocations */
-        size_t totalBytes;      /* total number of bytes allocated */
-        size_t peakBytes;       /* concurrent max bytes */
-        size_t currentBytes;    /* total current bytes in use */
-    } memoryStats;
-
-    typedef struct memHint {
-        size_t thisSize;      /* size of this memory */
-        void*  thisMemory;    /* actual memory for user */
-    } memHint;
-
-    typedef struct memoryTrack {
-        union {
-            memHint hint;
-            byte    alignit[16];   /* make sure we have strong alignment */
-        } u;
-    } memoryTrack;
-
-    #if defined(WOLFSSL_TRACK_MEMORY)
-        #define DO_MEM_STATS
-        static memoryStats ourMemStats;
-    #endif
-
-    /* if defined to not using inline then declare function prototypes */
-    #ifdef NO_INLINE
-        #define STATIC
-		#ifdef WOLFSSL_DEBUG_MEMORY
-			WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line);
-			WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line);
-			WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line);
-		#else
-			WOLFSSL_LOCAL void* TrackMalloc(size_t sz);
-			WOLFSSL_LOCAL void TrackFree(void* ptr);
-			WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz);
-		#endif
-        WOLFSSL_LOCAL int InitMemoryTracker(void);
-        WOLFSSL_LOCAL void ShowMemoryTracker(void);
-    #else
-        #define STATIC static
-    #endif
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-    STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line)
-#else
-    STATIC WC_INLINE void* TrackMalloc(size_t sz)
-#endif
-    {
-        memoryTrack* mt;
-
-        if (sz == 0)
-            return NULL;
-
-        mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz);
-        if (mt == NULL)
-            return NULL;
-
-        mt->u.hint.thisSize   = sz;
-        mt->u.hint.thisMemory = (byte*)mt + sizeof(memoryTrack);
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-        printf("Alloc: %p -> %u at %s:%d\n", mt->u.hint.thisMemory, (word32)sz, func, line);
-#endif
-
-#ifdef DO_MEM_STATS
-        ourMemStats.totalAllocs++;
-        ourMemStats.totalBytes   += sz;
-        ourMemStats.currentBytes += sz;
-        if (ourMemStats.currentBytes > ourMemStats.peakBytes)
-            ourMemStats.peakBytes = ourMemStats.currentBytes;
-#endif
-
-        return mt->u.hint.thisMemory;
-    }
-
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-    STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line)
-#else
-    STATIC WC_INLINE void TrackFree(void* ptr)
-#endif
-    {
-        memoryTrack* mt;
-
-        if (ptr == NULL) {
-            return;
-        }
-
-        mt = (memoryTrack*)ptr;
-        --mt;   /* same as minus sizeof(memoryTrack), removes header */
-
-#ifdef DO_MEM_STATS
-        ourMemStats.currentBytes -= mt->u.hint.thisSize;
-        ourMemStats.totalDeallocs++;
-#endif
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-        printf("Free: %p -> %u at %s:%d\n", ptr, (word32)mt->u.hint.thisSize, func, line);
-#endif
-
-        free(mt);
-    }
-
-
-#ifdef WOLFSSL_DEBUG_MEMORY
-    STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line)
-#else
-    STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz)
-#endif
-    {
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        void* ret = TrackMalloc(sz, func, line);
-    #else
-        void* ret = TrackMalloc(sz);
-    #endif
-
-        if (ptr) {
-            /* if realloc is bigger, don't overread old ptr */
-            memoryTrack* mt = (memoryTrack*)ptr;
-            --mt;  /* same as minus sizeof(memoryTrack), removes header */
-
-            if (mt->u.hint.thisSize < sz)
-                sz = mt->u.hint.thisSize;
-        }
-
-        if (ret && ptr)
-            XMEMCPY(ret, ptr, sz);
-
-        if (ret) {
-        #ifdef WOLFSSL_DEBUG_MEMORY
-            TrackFree(ptr, func, line);
-        #else
-            TrackFree(ptr);
-        #endif
-        }
-
-        return ret;
-    }
-
-#ifdef WOLFSSL_TRACK_MEMORY
-    STATIC WC_INLINE int InitMemoryTracker(void)
-    {
-        int ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc);
-        if (ret < 0) {
-            printf("wolfSSL SetAllocators failed for track memory\n");
-            return ret;
-        }
-
-    #ifdef DO_MEM_STATS
-        ourMemStats.totalAllocs  = 0;
-        ourMemStats.totalDeallocs = 0;
-        ourMemStats.totalBytes   = 0;
-        ourMemStats.peakBytes    = 0;
-        ourMemStats.currentBytes = 0;
-    #endif
-
-        return ret;
-    }
-
-    STATIC WC_INLINE void ShowMemoryTracker(void)
-    {
-    #ifdef DO_MEM_STATS
-        printf("total   Allocs   = %9lu\n",
-                                       (unsigned long)ourMemStats.totalAllocs);
-        printf("total   Deallocs = %9lu\n",
-                                       (unsigned long)ourMemStats.totalDeallocs);
-        printf("total   Bytes    = %9lu\n",
-                                       (unsigned long)ourMemStats.totalBytes);
-        printf("peak    Bytes    = %9lu\n",
-                                       (unsigned long)ourMemStats.peakBytes);
-        printf("current Bytes    = %9lu\n",
-                                       (unsigned long)ourMemStats.currentBytes);
-    #endif
-    }
-
-    STATIC WC_INLINE int CleanupMemoryTracker(void)
-    {
-        /* restore default allocators */
-        return wolfSSL_ResetAllocators();
-    }
-#endif
-
-#endif /* USE_WOLFSSL_MEMORY */
-
-#endif /* WOLFSSL_MEM_TRACK_H */
-
-
--- a/wolfssl/wolfcrypt/memory.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/* memory.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* submitted by eof */
-
-/*!
-    \file wolfssl/wolfcrypt/memory.h
-*/
-
-#ifndef WOLFSSL_MEMORY_H
-#define WOLFSSL_MEMORY_H
-
-#include <stdlib.h>
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_STATIC_MEMORY
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line);
-        typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type, const char* func, unsigned int line);
-        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line);
-        WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line);
-        WOLFSSL_API void  wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line);
-        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line);
-    #else
-        typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type);
-        typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type);
-        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type);
-        WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type);
-        WOLFSSL_API void  wolfSSL_Free(void *ptr, void* heap, int type);
-        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type);
-    #endif /* WOLFSSL_DEBUG_MEMORY */
-#else
-    #ifdef WOLFSSL_DEBUG_MEMORY
-        typedef void *(*wolfSSL_Malloc_cb)(size_t size, const char* func, unsigned int line);
-        typedef void (*wolfSSL_Free_cb)(void *ptr, const char* func, unsigned int line);
-        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, const char* func, unsigned int line);
-
-        /* Public in case user app wants to use XMALLOC/XFREE */
-        WOLFSSL_API void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line);
-        WOLFSSL_API void  wolfSSL_Free(void *ptr, const char* func, unsigned int line);
-        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line);
-    #else
-        typedef void *(*wolfSSL_Malloc_cb)(size_t size);
-        typedef void (*wolfSSL_Free_cb)(void *ptr);
-        typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size);
-        /* Public in case user app wants to use XMALLOC/XFREE */
-        WOLFSSL_API void* wolfSSL_Malloc(size_t size);
-        WOLFSSL_API void  wolfSSL_Free(void *ptr);
-        WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size);
-    #endif /* WOLFSSL_DEBUG_MEMORY */
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-/* Public get/set functions */
-WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb,
-                                      wolfSSL_Free_cb,
-                                      wolfSSL_Realloc_cb);
-WOLFSSL_API int wolfSSL_ResetAllocators(void);
-WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*,
-                                      wolfSSL_Free_cb*,
-                                      wolfSSL_Realloc_cb*);
-
-#ifdef WOLFSSL_STATIC_MEMORY
-    #define WOLFSSL_STATIC_TIMEOUT 1
-    #ifndef WOLFSSL_STATIC_ALIGN
-        #define WOLFSSL_STATIC_ALIGN 16
-    #endif
-    #ifndef WOLFMEM_MAX_BUCKETS
-        #define WOLFMEM_MAX_BUCKETS  9
-    #endif
-    #define WOLFMEM_DEF_BUCKETS  9     /* number of default memory blocks */
-    #ifndef WOLFMEM_IO_SZ
-        #define WOLFMEM_IO_SZ        16992 /* 16 byte aligned */
-    #endif
-    #ifndef WOLFMEM_BUCKETS
-        /* default size of chunks of memory to seperate into
-         * having session certs enabled makes a 21k SSL struct */
-        #ifndef SESSION_CERTS
-            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,16128
-        #else
-            #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,21920
-        #endif
-    #endif
-    #ifndef WOLFMEM_DIST
-        #define WOLFMEM_DIST    8,4,4,12,4,5,8,1,1
-    #endif
-
-    /* flags for loading static memory (one hot bit) */
-    #define WOLFMEM_GENERAL       0x01
-    #define WOLFMEM_IO_POOL       0x02
-    #define WOLFMEM_IO_POOL_FIXED 0x04
-    #define WOLFMEM_TRACK_STATS   0x08
-
-    #ifndef WOLFSSL_MEM_GUARD
-    #define WOLFSSL_MEM_GUARD
-        typedef struct WOLFSSL_MEM_STATS      WOLFSSL_MEM_STATS;
-        typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS;
-    #endif
-
-    struct WOLFSSL_MEM_CONN_STATS {
-        word32 peakMem;   /* peak memory usage    */
-        word32 curMem;    /* current memory usage */
-        word32 peakAlloc; /* peak memory allocations */
-        word32 curAlloc;  /* current memory allocations */
-        word32 totalAlloc;/* total memory allocations for lifetime */
-        word32 totalFr;   /* total frees for lifetime */
-    };
-
-    struct WOLFSSL_MEM_STATS {
-        word32 curAlloc;  /* current memory allocations */
-        word32 totalAlloc;/* total memory allocations for lifetime */
-        word32 totalFr;   /* total frees for lifetime */
-        word32 totalUse;  /* total amount of memory used in blocks */
-        word32 avaIO;     /* available IO specific pools */
-        word32 maxHa;     /* max number of concurent handshakes allowed */
-        word32 maxIO;     /* max number of concurent IO connections allowed */
-        word32 blockSz[WOLFMEM_MAX_BUCKETS]; /* block sizes in stacks */
-        word32 avaBlock[WOLFMEM_MAX_BUCKETS];/* ava block sizes */
-        word32 usedBlock[WOLFMEM_MAX_BUCKETS];
-        int    flag; /* flag used */
-    };
-
-    typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */
-    typedef struct WOLFSSL_HEAP {
-        wc_Memory* ava[WOLFMEM_MAX_BUCKETS];
-        wc_Memory* io;                  /* list of buffers to use for IO */
-        word32     maxHa;               /* max concurent handshakes */
-        word32     curHa;
-        word32     maxIO;               /* max concurrent IO connections */
-        word32     curIO;
-        word32     sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */
-        word32     distList[WOLFMEM_MAX_BUCKETS];/* general distribution */
-        word32     inUse; /* amount of memory currently in use */
-        word32     ioUse;
-        word32     alloc; /* total number of allocs */
-        word32     frAlc; /* total number of frees  */
-        int        flag;
-        wolfSSL_Mutex memory_mutex;
-    } WOLFSSL_HEAP;
-
-    /* structure passed into XMALLOC as heap hint
-     * having this abstraction allows tracking statistics of individual ssl's
-     */
-    typedef struct WOLFSSL_HEAP_HINT {
-        WOLFSSL_HEAP*           memory;
-        WOLFSSL_MEM_CONN_STATS* stats;  /* hold individual connection stats */
-        wc_Memory*  outBuf; /* set if using fixed io buffers */
-        wc_Memory*  inBuf;
-        byte        haFlag; /* flag used for checking handshake count */
-    } WOLFSSL_HEAP_HINT;
-
-    WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint,
-            unsigned char* buf, unsigned int sz, int flag, int max);
-
-    WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap);
-    WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz,
-                                                  int flag, WOLFSSL_HEAP* heap);
-    WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap,
-                                                      WOLFSSL_MEM_STATS* stats);
-    WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io);
-    WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io);
-
-    WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag);
-    WOLFSSL_API int wolfSSL_MemoryPaddingSz(void);
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_MEMORY_H */
-
-
--- a/wolfssl/wolfcrypt/misc.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* misc.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLF_CRYPT_MISC_H
-#define WOLF_CRYPT_MISC_H
-
-
-#include <wolfssl/wolfcrypt/types.h>
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-#ifdef NO_INLINE
-WOLFSSL_LOCAL
-word32 rotlFixed(word32, word32);
-WOLFSSL_LOCAL
-word32 rotrFixed(word32, word32);
-
-WOLFSSL_LOCAL
-word32 ByteReverseWord32(word32);
-WOLFSSL_LOCAL
-void   ByteReverseWords(word32*, const word32*, word32);
-
-WOLFSSL_LOCAL
-void XorWords(wolfssl_word*, const wolfssl_word*, word32);
-WOLFSSL_LOCAL
-void xorbuf(void*, const void*, word32);
-
-WOLFSSL_LOCAL
-void ForceZero(const void*, word32);
-
-WOLFSSL_LOCAL
-int ConstantCompare(const byte*, const byte*, int);
-
-#ifdef WORD64_AVAILABLE
-WOLFSSL_LOCAL
-word64 rotlFixed64(word64, word64);
-WOLFSSL_LOCAL
-word64 rotrFixed64(word64, word64);
-
-WOLFSSL_LOCAL
-word64 ByteReverseWord64(word64);
-WOLFSSL_LOCAL
-void   ByteReverseWords64(word64*, const word64*, word32);
-#endif /* WORD64_AVAILABLE */
-
-#ifndef WOLFSSL_HAVE_MIN
-    #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */
-        #define min min
-    #endif
-    WOLFSSL_LOCAL word32 min(word32 a, word32 b);
-#endif
-
-#ifndef WOLFSSL_HAVE_MAX
-    #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */
-        #define max max
-    #endif
-    WOLFSSL_LOCAL word32 max(word32 a, word32 b);
-#endif /* WOLFSSL_HAVE_MAX */
-
-
-void c32to24(word32 in, word24 out);
-void c16toa(word16 u16, byte* c);
-void c32toa(word32 u32, byte* c);
-void c24to32(const word24 u24, word32* u32);
-void ato16(const byte* c, word16* u16);
-void ato24(const byte* c, word32* u24);
-void ato32(const byte* c, word32* u32);
-word32 btoi(byte b);
-
-
-WOLFSSL_LOCAL byte ctMaskGT(int a, int b);
-WOLFSSL_LOCAL byte ctMaskGTE(int a, int b);
-WOLFSSL_LOCAL byte ctMaskLT(int a, int b);
-WOLFSSL_LOCAL byte ctMaskLTE(int a, int b);
-WOLFSSL_LOCAL byte ctMaskEq(int a, int b);
-WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b);
-WOLFSSL_LOCAL byte ctSetLTE(int a, int b);
-
-#endif /* NO_INLINE */
-
-
-#ifdef __cplusplus
-    }   /* extern "C" */
-#endif
-
-
-#endif /* WOLF_CRYPT_MISC_H */
-
-
--- a/wolfssl/wolfcrypt/mpi_class.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1020 +0,0 @@
-/* mpi_class.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
-#if defined(LTM2)
-#define LTM3
-#endif
-#if defined(LTM1)
-#define LTM2
-#endif
-#define LTM1
-
-#if defined(LTM_ALL)
-#define BN_ERROR_C
-#define BN_FAST_MP_INVMOD_C
-#define BN_FAST_MP_MONTGOMERY_REDUCE_C
-#define BN_FAST_S_MP_MUL_DIGS_C
-#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
-#define BN_FAST_S_MP_SQR_C
-#define BN_MP_2EXPT_C
-#define BN_MP_ABS_C
-#define BN_MP_ADD_C
-#define BN_MP_ADD_D_C
-#define BN_MP_ADDMOD_C
-#define BN_MP_AND_C
-#define BN_MP_CLAMP_C
-#define BN_MP_CLEAR_C
-#define BN_MP_CLEAR_MULTI_C
-#define BN_MP_CMP_C
-#define BN_MP_CMP_D_C
-#define BN_MP_CMP_MAG_C
-#define BN_MP_CNT_LSB_C
-#define BN_MP_COPY_C
-#define BN_MP_COUNT_BITS_C
-#define BN_MP_DIV_C
-#define BN_MP_DIV_2_C
-#define BN_MP_DIV_2D_C
-#define BN_MP_DIV_3_C
-#define BN_MP_DIV_D_C
-#define BN_MP_DR_IS_MODULUS_C
-#define BN_MP_DR_REDUCE_C
-#define BN_MP_DR_SETUP_C
-#define BN_MP_EXCH_C
-#define BN_MP_EXPT_D_C
-#define BN_MP_EXPTMOD_C
-#define BN_MP_EXPTMOD_FAST_C
-#define BN_MP_EXTEUCLID_C
-#define BN_MP_FREAD_C
-#define BN_MP_FWRITE_C
-#define BN_MP_GCD_C
-#define BN_MP_GET_INT_C
-#define BN_MP_GROW_C
-#define BN_MP_INIT_C
-#define BN_MP_INIT_COPY_C
-#define BN_MP_INIT_MULTI_C
-#define BN_MP_INIT_SET_C
-#define BN_MP_INIT_SET_INT_C
-#define BN_MP_INIT_SIZE_C
-#define BN_MP_INVMOD_C
-#define BN_MP_INVMOD_SLOW_C
-#define BN_MP_IS_SQUARE_C
-#define BN_MP_JACOBI_C
-#define BN_MP_KARATSUBA_MUL_C
-#define BN_MP_KARATSUBA_SQR_C
-#define BN_MP_LCM_C
-#define BN_MP_LSHD_C
-#define BN_MP_MOD_C
-#define BN_MP_MOD_2D_C
-#define BN_MP_MOD_D_C
-#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
-#define BN_MP_MONTGOMERY_REDUCE_C
-#define BN_MP_MONTGOMERY_SETUP_C
-#define BN_MP_MUL_C
-#define BN_MP_MUL_2_C
-#define BN_MP_MUL_2D_C
-#define BN_MP_MUL_D_C
-#define BN_MP_MULMOD_C
-#define BN_MP_N_ROOT_C
-#define BN_MP_NEG_C
-#define BN_MP_OR_C
-#define BN_MP_PRIME_FERMAT_C
-#define BN_MP_PRIME_IS_DIVISIBLE_C
-#define BN_MP_PRIME_IS_PRIME_C
-#define BN_MP_PRIME_MILLER_RABIN_C
-#define BN_MP_PRIME_NEXT_PRIME_C
-#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
-#define BN_MP_PRIME_RANDOM_EX_C
-#define BN_MP_RADIX_SIZE_C
-#define BN_MP_RADIX_SMAP_C
-#define BN_MP_RAND_C
-#define BN_MP_READ_RADIX_C
-#define BN_MP_READ_SIGNED_BIN_C
-#define BN_MP_READ_UNSIGNED_BIN_C
-#define BN_MP_REDUCE_C
-#define BN_MP_REDUCE_2K_C
-#define BN_MP_REDUCE_2K_L_C
-#define BN_MP_REDUCE_2K_SETUP_C
-#define BN_MP_REDUCE_2K_SETUP_L_C
-#define BN_MP_REDUCE_IS_2K_C
-#define BN_MP_REDUCE_IS_2K_L_C
-#define BN_MP_REDUCE_SETUP_C
-#define BN_MP_RSHD_C
-#define BN_MP_SET_C
-#define BN_MP_SET_INT_C
-#define BN_MP_SHRINK_C
-#define BN_MP_SIGNED_BIN_SIZE_C
-#define BN_MP_SQR_C
-#define BN_MP_SQRMOD_C
-#define BN_MP_SQRT_C
-#define BN_MP_SUB_C
-#define BN_MP_SUB_D_C
-#define BN_MP_SUBMOD_C
-#define BN_MP_TO_SIGNED_BIN_C
-#define BN_MP_TO_SIGNED_BIN_N_C
-#define BN_MP_TO_UNSIGNED_BIN_C
-#define BN_MP_TO_UNSIGNED_BIN_N_C
-#define BN_MP_TOOM_MUL_C
-#define BN_MP_TOOM_SQR_C
-#define BN_MP_TORADIX_C
-#define BN_MP_TORADIX_N_C
-#define BN_MP_UNSIGNED_BIN_SIZE_C
-#define BN_MP_XOR_C
-#define BN_MP_ZERO_C
-#define BN_PRIME_TAB_C
-#define BN_REVERSE_C
-#define BN_S_MP_ADD_C
-#define BN_S_MP_EXPTMOD_C
-#define BN_S_MP_MUL_DIGS_C
-#define BN_S_MP_MUL_HIGH_DIGS_C
-#define BN_S_MP_SQR_C
-#define BN_S_MP_SUB_C
-#define BNCORE_C
-#endif
-
-#if defined(BN_ERROR_C)
-   #define BN_MP_ERROR_TO_STRING_C
-#endif
-
-#if defined(BN_FAST_MP_INVMOD_C)
-   #define BN_MP_ISEVEN_C
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_COPY_C
-   #define BN_MP_MOD_C
-   #define BN_MP_SET_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_ISODD_C
-   #define BN_MP_SUB_C
-   #define BN_MP_CMP_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_CMP_D_C
-   #define BN_MP_ADD_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_FAST_S_MP_MUL_DIGS_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_FAST_S_MP_SQR_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_2EXPT_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_GROW_C
-#endif
-
-#if defined(BN_MP_ABS_C)
-   #define BN_MP_COPY_C
-#endif
-
-#if defined(BN_MP_ADD_C)
-   #define BN_S_MP_ADD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_ADD_D_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_SUB_D_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_ADDMOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_ADD_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MOD_C
-#endif
-
-#if defined(BN_MP_AND_C)
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_CLAMP_C)
-#endif
-
-#if defined(BN_MP_CLEAR_C)
-#endif
-
-#if defined(BN_MP_CLEAR_MULTI_C)
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_CMP_C)
-   #define BN_MP_CMP_MAG_C
-#endif
-
-#if defined(BN_MP_CMP_D_C)
-#endif
-
-#if defined(BN_MP_CMP_MAG_C)
-#endif
-
-#if defined(BN_MP_CNT_LSB_C)
-   #define BN_MP_ISZERO_C
-#endif
-
-#if defined(BN_MP_COPY_C)
-   #define BN_MP_GROW_C
-#endif
-
-#if defined(BN_MP_COUNT_BITS_C)
-#endif
-
-#if defined(BN_MP_DIV_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_COPY_C
-   #define BN_MP_ZERO_C
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_SET_C
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_ABS_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_CMP_C
-   #define BN_MP_SUB_C
-   #define BN_MP_ADD_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_MULTI_C
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_INIT_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_DIV_2_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_DIV_2D_C)
-   #define BN_MP_COPY_C
-   #define BN_MP_ZERO_C
-   #define BN_MP_INIT_C
-   #define BN_MP_MOD_2D_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-#endif
-
-#if defined(BN_MP_DIV_3_C)
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_DIV_D_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_COPY_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_DIV_3_C
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_DR_IS_MODULUS_C)
-#endif
-
-#if defined(BN_MP_DR_REDUCE_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_DR_SETUP_C)
-#endif
-
-#if defined(BN_MP_EXCH_C)
-#endif
-
-#if defined(BN_MP_EXPT_D_C)
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_SET_C
-   #define BN_MP_SQR_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MUL_C
-#endif
-
-#if defined(BN_MP_EXPTMOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_INVMOD_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_ABS_C
-   #define BN_MP_CLEAR_MULTI_C
-   #define BN_MP_REDUCE_IS_2K_L_C
-   #define BN_S_MP_EXPTMOD_C
-   #define BN_MP_DR_IS_MODULUS_C
-   #define BN_MP_REDUCE_IS_2K_C
-   #define BN_MP_ISODD_C
-   #define BN_MP_EXPTMOD_FAST_C
-#endif
-
-#if defined(BN_MP_EXPTMOD_FAST_C)
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_INIT_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MONTGOMERY_SETUP_C
-   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
-   #define BN_MP_MONTGOMERY_REDUCE_C
-   #define BN_MP_DR_SETUP_C
-   #define BN_MP_DR_REDUCE_C
-   #define BN_MP_REDUCE_2K_SETUP_C
-   #define BN_MP_REDUCE_2K_C
-   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
-   #define BN_MP_MULMOD_C
-   #define BN_MP_SET_C
-   #define BN_MP_MOD_C
-   #define BN_MP_COPY_C
-   #define BN_MP_SQR_C
-   #define BN_MP_MUL_C
-   #define BN_MP_EXCH_C
-#endif
-
-#if defined(BN_MP_EXTEUCLID_C)
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_SET_C
-   #define BN_MP_COPY_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_DIV_C
-   #define BN_MP_MUL_C
-   #define BN_MP_SUB_C
-   #define BN_MP_NEG_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_MP_FREAD_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_S_RMAP_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_ADD_D_C
-   #define BN_MP_CMP_D_C
-#endif
-
-#if defined(BN_MP_FWRITE_C)
-   #define BN_MP_RADIX_SIZE_C
-   #define BN_MP_TORADIX_C
-#endif
-
-#if defined(BN_MP_GCD_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_ABS_C
-   #define BN_MP_ZERO_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_CNT_LSB_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_EXCH_C
-   #define BN_S_MP_SUB_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_GET_INT_C)
-#endif
-
-#if defined(BN_MP_GROW_C)
-#endif
-
-#if defined(BN_MP_INIT_C)
-#endif
-
-#if defined(BN_MP_INIT_COPY_C)
-   #define BN_MP_COPY_C
-#endif
-
-#if defined(BN_MP_INIT_MULTI_C)
-   #define BN_MP_ERR_C
-   #define BN_MP_INIT_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_INIT_SET_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_SET_C
-#endif
-
-#if defined(BN_MP_INIT_SET_INT_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_SET_INT_C
-#endif
-
-#if defined(BN_MP_INIT_SIZE_C)
-   #define BN_MP_INIT_C
-#endif
-
-#if defined(BN_MP_INVMOD_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_ISODD_C
-   #define BN_FAST_MP_INVMOD_C
-   #define BN_MP_INVMOD_SLOW_C
-#endif
-
-#if defined(BN_MP_INVMOD_SLOW_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_MOD_C
-   #define BN_MP_COPY_C
-   #define BN_MP_ISEVEN_C
-   #define BN_MP_SET_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_ISODD_C
-   #define BN_MP_ADD_C
-   #define BN_MP_SUB_C
-   #define BN_MP_CMP_C
-   #define BN_MP_CMP_D_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_MP_IS_SQUARE_C)
-   #define BN_MP_MOD_D_C
-   #define BN_MP_INIT_SET_INT_C
-   #define BN_MP_MOD_C
-   #define BN_MP_GET_INT_C
-   #define BN_MP_SQRT_C
-   #define BN_MP_SQR_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_JACOBI_C)
-   #define BN_MP_CMP_D_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_CNT_LSB_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_MOD_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_KARATSUBA_MUL_C)
-   #define BN_MP_MUL_C
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_SUB_C
-   #define BN_MP_ADD_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_KARATSUBA_SQR_C)
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_SQR_C
-   #define BN_MP_SUB_C
-   #define BN_S_MP_ADD_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_ADD_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_LCM_C)
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_GCD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_DIV_C
-   #define BN_MP_MUL_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_MP_LSHD_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_RSHD_C
-#endif
-
-#if defined(BN_MP_MOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_DIV_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_ADD_C
-   #define BN_MP_EXCH_C
-#endif
-
-#if defined(BN_MP_MOD_2D_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_COPY_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_MOD_D_C)
-   #define BN_MP_DIV_D_C
-#endif
-
-#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_2EXPT_C
-   #define BN_MP_SET_C
-   #define BN_MP_MUL_2_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_MONTGOMERY_REDUCE_C)
-   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_MONTGOMERY_SETUP_C)
-#endif
-
-#if defined(BN_MP_MUL_C)
-   #define BN_MP_TOOM_MUL_C
-   #define BN_MP_KARATSUBA_MUL_C
-   #define BN_FAST_S_MP_MUL_DIGS_C
-   #define BN_S_MP_MUL_C
-   #define BN_S_MP_MUL_DIGS_C
-#endif
-
-#if defined(BN_MP_MUL_2_C)
-   #define BN_MP_GROW_C
-#endif
-
-#if defined(BN_MP_MUL_2D_C)
-   #define BN_MP_COPY_C
-   #define BN_MP_GROW_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_MUL_D_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_MULMOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_MUL_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MOD_C
-#endif
-
-#if defined(BN_MP_N_ROOT_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_SET_C
-   #define BN_MP_COPY_C
-   #define BN_MP_EXPT_D_C
-   #define BN_MP_MUL_C
-   #define BN_MP_SUB_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_DIV_C
-   #define BN_MP_CMP_C
-   #define BN_MP_SUB_D_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_NEG_C)
-   #define BN_MP_COPY_C
-   #define BN_MP_ISZERO_C
-#endif
-
-#if defined(BN_MP_OR_C)
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_PRIME_FERMAT_C)
-   #define BN_MP_CMP_D_C
-   #define BN_MP_INIT_C
-   #define BN_MP_EXPTMOD_C
-   #define BN_MP_CMP_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
-   #define BN_MP_MOD_D_C
-#endif
-
-#if defined(BN_MP_PRIME_IS_PRIME_C)
-   #define BN_MP_CMP_D_C
-   #define BN_MP_PRIME_IS_DIVISIBLE_C
-   #define BN_MP_INIT_C
-   #define BN_MP_SET_C
-   #define BN_MP_PRIME_MILLER_RABIN_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_PRIME_MILLER_RABIN_C)
-   #define BN_MP_CMP_D_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_SUB_D_C
-   #define BN_MP_CNT_LSB_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_EXPTMOD_C
-   #define BN_MP_CMP_C
-   #define BN_MP_SQRMOD_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_PRIME_NEXT_PRIME_C)
-   #define BN_MP_CMP_D_C
-   #define BN_MP_SET_C
-   #define BN_MP_SUB_D_C
-   #define BN_MP_ISEVEN_C
-   #define BN_MP_MOD_D_C
-   #define BN_MP_INIT_C
-   #define BN_MP_ADD_D_C
-   #define BN_MP_PRIME_MILLER_RABIN_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
-#endif
-
-#if defined(BN_MP_PRIME_RANDOM_EX_C)
-   #define BN_MP_READ_UNSIGNED_BIN_C
-   #define BN_MP_PRIME_IS_PRIME_C
-   #define BN_MP_SUB_D_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_MUL_2_C
-   #define BN_MP_ADD_D_C
-#endif
-
-#if defined(BN_MP_RADIX_SIZE_C)
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_DIV_D_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_RADIX_SMAP_C)
-   #define BN_MP_S_RMAP_C
-#endif
-
-#if defined(BN_MP_RAND_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_ADD_D_C
-   #define BN_MP_LSHD_C
-#endif
-
-#if defined(BN_MP_READ_RADIX_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_S_RMAP_C
-   #define BN_MP_RADIX_SMAP_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_ADD_D_C
-   #define BN_MP_ISZERO_C
-#endif
-
-#if defined(BN_MP_READ_SIGNED_BIN_C)
-   #define BN_MP_READ_UNSIGNED_BIN_C
-#endif
-
-#if defined(BN_MP_READ_UNSIGNED_BIN_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_ZERO_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_REDUCE_C)
-   #define BN_MP_REDUCE_SETUP_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_MUL_C
-   #define BN_S_MP_MUL_HIGH_DIGS_C
-   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
-   #define BN_MP_MOD_2D_C
-   #define BN_S_MP_MUL_DIGS_C
-   #define BN_MP_SUB_C
-   #define BN_MP_CMP_D_C
-   #define BN_MP_SET_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_ADD_C
-   #define BN_MP_CMP_C
-   #define BN_S_MP_SUB_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_REDUCE_2K_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_MUL_D_C
-   #define BN_S_MP_ADD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_REDUCE_2K_L_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_MUL_C
-   #define BN_S_MP_ADD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_REDUCE_2K_SETUP_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_2EXPT_C
-   #define BN_MP_CLEAR_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_2EXPT_C
-   #define BN_MP_COUNT_BITS_C
-   #define BN_S_MP_SUB_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_REDUCE_IS_2K_C)
-   #define BN_MP_REDUCE_2K_C
-   #define BN_MP_COUNT_BITS_C
-#endif
-
-#if defined(BN_MP_REDUCE_IS_2K_L_C)
-#endif
-
-#if defined(BN_MP_REDUCE_SETUP_C)
-   #define BN_MP_2EXPT_C
-   #define BN_MP_DIV_C
-#endif
-
-#if defined(BN_MP_RSHD_C)
-   #define BN_MP_ZERO_C
-#endif
-
-#if defined(BN_MP_SET_C)
-   #define BN_MP_ZERO_C
-#endif
-
-#if defined(BN_MP_SET_INT_C)
-   #define BN_MP_ZERO_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_SHRINK_C)
-#endif
-
-#if defined(BN_MP_SIGNED_BIN_SIZE_C)
-   #define BN_MP_UNSIGNED_BIN_SIZE_C
-#endif
-
-#if defined(BN_MP_SQR_C)
-   #define BN_MP_TOOM_SQR_C
-   #define BN_MP_KARATSUBA_SQR_C
-   #define BN_FAST_S_MP_SQR_C
-   #define BN_S_MP_SQR_C
-#endif
-
-#if defined(BN_MP_SQRMOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_SQR_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MOD_C
-#endif
-
-#if defined(BN_MP_SQRT_C)
-   #define BN_MP_N_ROOT_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_ZERO_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_DIV_C
-   #define BN_MP_ADD_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_SUB_C)
-   #define BN_S_MP_ADD_C
-   #define BN_MP_CMP_MAG_C
-   #define BN_S_MP_SUB_C
-#endif
-
-#if defined(BN_MP_SUB_D_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_ADD_D_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_MP_SUBMOD_C)
-   #define BN_MP_INIT_C
-   #define BN_MP_SUB_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_MOD_C
-#endif
-
-#if defined(BN_MP_TO_SIGNED_BIN_C)
-   #define BN_MP_TO_UNSIGNED_BIN_C
-#endif
-
-#if defined(BN_MP_TO_SIGNED_BIN_N_C)
-   #define BN_MP_SIGNED_BIN_SIZE_C
-   #define BN_MP_TO_SIGNED_BIN_C
-#endif
-
-#if defined(BN_MP_TO_UNSIGNED_BIN_C)
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_ISZERO_C
-   #define BN_MP_DIV_2D_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
-   #define BN_MP_UNSIGNED_BIN_SIZE_C
-   #define BN_MP_TO_UNSIGNED_BIN_C
-#endif
-
-#if defined(BN_MP_TOOM_MUL_C)
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_MOD_2D_C
-   #define BN_MP_COPY_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_MUL_C
-   #define BN_MP_MUL_2_C
-   #define BN_MP_ADD_C
-   #define BN_MP_SUB_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_DIV_3_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_MP_TOOM_SQR_C)
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_MOD_2D_C
-   #define BN_MP_COPY_C
-   #define BN_MP_RSHD_C
-   #define BN_MP_SQR_C
-   #define BN_MP_MUL_2_C
-   #define BN_MP_ADD_C
-   #define BN_MP_SUB_C
-   #define BN_MP_DIV_2_C
-   #define BN_MP_MUL_2D_C
-   #define BN_MP_MUL_D_C
-   #define BN_MP_DIV_3_C
-   #define BN_MP_LSHD_C
-   #define BN_MP_CLEAR_MULTI_C
-#endif
-
-#if defined(BN_MP_TORADIX_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_DIV_D_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_S_RMAP_C
-#endif
-
-#if defined(BN_MP_TORADIX_N_C)
-   #define BN_MP_ISZERO_C
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_DIV_D_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_S_RMAP_C
-#endif
-
-#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
-   #define BN_MP_COUNT_BITS_C
-#endif
-
-#if defined(BN_MP_XOR_C)
-   #define BN_MP_INIT_COPY_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_MP_ZERO_C)
-#endif
-
-#if defined(BN_PRIME_TAB_C)
-#endif
-
-#if defined(BN_REVERSE_C)
-#endif
-
-#if defined(BN_S_MP_ADD_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BN_S_MP_EXPTMOD_C)
-   #define BN_MP_COUNT_BITS_C
-   #define BN_MP_INIT_C
-   #define BN_MP_CLEAR_C
-   #define BN_MP_REDUCE_SETUP_C
-   #define BN_MP_REDUCE_C
-   #define BN_MP_REDUCE_2K_SETUP_L_C
-   #define BN_MP_REDUCE_2K_L_C
-   #define BN_MP_MOD_C
-   #define BN_MP_COPY_C
-   #define BN_MP_SQR_C
-   #define BN_MP_MUL_C
-   #define BN_MP_SET_C
-   #define BN_MP_EXCH_C
-#endif
-
-#if defined(BN_S_MP_MUL_DIGS_C)
-   #define BN_FAST_S_MP_MUL_DIGS_C
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
-   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_S_MP_SQR_C)
-   #define BN_MP_INIT_SIZE_C
-   #define BN_MP_CLAMP_C
-   #define BN_MP_EXCH_C
-   #define BN_MP_CLEAR_C
-#endif
-
-#if defined(BN_S_MP_SUB_C)
-   #define BN_MP_GROW_C
-   #define BN_MP_CLAMP_C
-#endif
-
-#if defined(BNCORE_C)
-#endif
-
-#ifdef LTM3
-#define LTM_LAST
-#endif
-#include "mpi_superclass.h"
-#include "mpi_class.h"
-#else
-#define LTM_LAST
-#endif
-
-
--- a/wolfssl/wolfcrypt/mpi_superclass.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* mpi_superclass.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-/* super class file for PK algos */
-
-/* default ... include all MPI */
-#define LTM_ALL
-
-/* RSA only (does not support DH/DSA/ECC) */
-/* #define SC_RSA_1 */
-
-/* For reference.... On an Athlon64 optimizing for speed...
-
-   LTM's mpi.o with all functions [striped] is 142KiB in size.
-
-*/
-
-/* Works for RSA only, mpi.o is 68KiB */
-#ifdef SC_RSA_1
-   #define BN_MP_SHRINK_C
-   #define BN_MP_LCM_C
-   #define BN_MP_PRIME_RANDOM_EX_C
-   #define BN_MP_INVMOD_C
-   #define BN_MP_GCD_C
-   #define BN_MP_MOD_C
-   #define BN_MP_MULMOD_C
-   #define BN_MP_ADDMOD_C
-   #define BN_MP_EXPTMOD_C
-   #define BN_MP_SET_INT_C
-   #define BN_MP_INIT_MULTI_C
-   #define BN_MP_CLEAR_MULTI_C
-   #define BN_MP_UNSIGNED_BIN_SIZE_C
-   #define BN_MP_TO_UNSIGNED_BIN_C
-   #define BN_MP_MOD_D_C
-   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
-   #define BN_REVERSE_C
-   #define BN_PRIME_TAB_C
-
-   /* other modifiers */
-   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */
-
-   /* here we are on the last pass so we turn things off.  The functions classes are still there
-    * but we remove them specifically from the build.  This also invokes tweaks in functions
-    * like removing support for even moduli, etc...
-    */
-#ifdef LTM_LAST
-   #undef  BN_MP_TOOM_MUL_C
-   #undef  BN_MP_TOOM_SQR_C
-   #undef  BN_MP_KARATSUBA_MUL_C
-   #undef  BN_MP_KARATSUBA_SQR_C
-   #undef  BN_MP_REDUCE_C
-   #undef  BN_MP_REDUCE_SETUP_C
-   #undef  BN_MP_DR_IS_MODULUS_C
-   #undef  BN_MP_DR_SETUP_C
-   #undef  BN_MP_DR_REDUCE_C
-   #undef  BN_MP_REDUCE_IS_2K_C
-   #undef  BN_MP_REDUCE_2K_SETUP_C
-   #undef  BN_MP_REDUCE_2K_C
-   #undef  BN_S_MP_EXPTMOD_C
-   #undef  BN_MP_DIV_3_C
-   #undef  BN_S_MP_MUL_HIGH_DIGS_C
-   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
-   #undef  BN_FAST_MP_INVMOD_C
-
-   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
-    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
-    * which means roughly speaking you can handle up to 2536-bit RSA keys with these defined without
-    * trouble.
-    */
-   #undef  BN_S_MP_MUL_DIGS_C
-   #undef  BN_S_MP_SQR_C
-   #undef  BN_MP_MONTGOMERY_REDUCE_C
-#endif
-
-#endif
-
-
--- a/wolfssl/wolfcrypt/pkcs12.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* pkcs12.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_PKCS12_H
-#define WOLF_CRYPT_PKCS12_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifndef WOLFSSL_TYPES_DEFINED /* do not redeclare from ssl.h */
-    typedef struct WC_PKCS12 WC_PKCS12;
-#endif
-
-typedef struct WC_DerCertList { /* dereferenced in ssl.c */
-    byte* buffer;
-    word32 bufferSz;
-    struct WC_DerCertList* next;
-} WC_DerCertList;
-
-/* default values for creating PKCS12 */
-enum {
-    WC_PKCS12_ITT_DEFAULT = 2048,
-    WC_PKCS12_MAC_DEFAULT = 1,
-};
-
-WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void);
-WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12);
-WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12);
-WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
-        byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
-        WC_DerCertList** ca);
-WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz,
-        char* name, byte* key, word32 keySz, byte* cert, word32 certSz,
-        WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter,
-        int keyType, void* heap);
-
-
-WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap);
-WOLFSSL_LOCAL void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12);
-
-WOLFSSL_LOCAL void wc_FreeCertList(WC_DerCertList* list, void* heap);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_PKCS12_H */
-
-
--- a/wolfssl/wolfcrypt/pkcs7.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/* pkcs7.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/pkcs7.h
-*/
-
-#ifndef WOLF_CRYPT_PKCS7_H
-#define WOLF_CRYPT_PKCS7_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_PKCS7
-
-#ifndef NO_ASN
-    #include <wolfssl/wolfcrypt/asn.h>
-#endif
-#include <wolfssl/wolfcrypt/asn_public.h>
-#include <wolfssl/wolfcrypt/random.h>
-#ifndef NO_AES
-    #include <wolfssl/wolfcrypt/aes.h>
-#endif
-#ifndef NO_DES3
-    #include <wolfssl/wolfcrypt/des3.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Max number of certificates that PKCS7 structure can parse */
-#ifndef MAX_PKCS7_CERTS
-#define MAX_PKCS7_CERTS 4
-#endif
-
-/* PKCS#7 content types, ref RFC 2315 (Section 14) */
-enum PKCS7_TYPES {
-    PKCS7_MSG                 = 650,   /* 1.2.840.113549.1.7   */
-    DATA                      = 651,   /* 1.2.840.113549.1.7.1 */
-    SIGNED_DATA               = 652,   /* 1.2.840.113549.1.7.2 */
-    ENVELOPED_DATA            = 653,   /* 1.2.840.113549.1.7.3 */
-    SIGNED_AND_ENVELOPED_DATA = 654,   /* 1.2.840.113549.1.7.4 */
-    DIGESTED_DATA             = 655,   /* 1.2.840.113549.1.7.5 */
-    ENCRYPTED_DATA            = 656    /* 1.2.840.113549.1.7.6 */
-};
-
-enum Pkcs7_Misc {
-    PKCS7_NONCE_SZ        = 16,
-    MAX_ENCRYPTED_KEY_SZ  = 512,    /* max enc. key size, RSA <= 4096 */
-    MAX_CONTENT_KEY_LEN   = 32,     /* highest current cipher is AES-256-CBC */
-    MAX_CONTENT_IV_SIZE   = 16,     /* highest current is AES128 */
-#ifndef NO_AES
-    MAX_CONTENT_BLOCK_LEN = AES_BLOCK_SIZE,
-#else
-    MAX_CONTENT_BLOCK_LEN = DES_BLOCK_SIZE,
-#endif
-    MAX_RECIP_SZ          = MAX_VERSION_SZ +
-                            MAX_SEQ_SZ + ASN_NAME_MAX + MAX_SN_SZ +
-                            MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ
-};
-
-
-typedef struct PKCS7Attrib {
-    byte* oid;
-    word32 oidSz;
-    byte* value;
-    word32 valueSz;
-} PKCS7Attrib;
-
-
-typedef struct PKCS7DecodedAttrib {
-    struct PKCS7DecodedAttrib* next;
-    byte* oid;
-    word32 oidSz;
-    byte* value;
-    word32 valueSz;
-} PKCS7DecodedAttrib;
-
-
-/* Public Structure Warning:
- * Existing members must not be changed to maintain backwards compatibility! 
- */
-typedef struct PKCS7 {
-    WC_RNG* rng;
-    PKCS7Attrib* signedAttribs;
-    byte*  content;               /* inner content, not owner             */
-    byte*  singleCert;            /* recipient cert, DER, not owner       */
-    byte*  issuer;                /* issuer name of singleCert            */
-    byte*  privateKey;            /* private key, DER, not owner          */
-    void*  heap;                  /* heap hint for dynamic memory         */
-#ifdef ASN_BER_TO_DER
-    byte*  der;                   /* DER encoded version of message       */
-#endif
-    byte*  cert[MAX_PKCS7_CERTS];
-
-    /* Encrypted-data Content Type */
-    byte*        encryptionKey;         /* block cipher encryption key */
-    PKCS7Attrib* unprotectedAttribs;    /* optional */
-    PKCS7DecodedAttrib* decodedAttrib;  /* linked list of decoded attribs */
-
-    /* Enveloped-data optional ukm, not owner */
-    byte*  ukm;
-    word32 ukmSz;
-
-    word32 encryptionKeySz;       /* size of key buffer, bytes */
-    word32 unprotectedAttribsSz;
-    word32 contentSz;             /* content size                         */
-    word32 singleCertSz;          /* size of recipient cert buffer, bytes */
-    word32 issuerSz;              /* length of issuer name                */
-    word32 issuerSnSz;            /* length of serial number              */
-
-    word32 publicKeySz;
-    word32 publicKeyOID;          /* key OID (RSAk, ECDSAk, etc) */
-    word32 privateKeySz;          /* size of private key buffer, bytes    */
-    word32 signedAttribsSz;
-    int contentOID;               /* PKCS#7 content type OID sum          */
-    int hashOID;
-    int encryptOID;               /* key encryption algorithm OID         */
-    int keyWrapOID;               /* key wrap algorithm OID               */
-    int keyAgreeOID;              /* key agreement algorithm OID          */
-    int devId;                    /* device ID for HW based private key   */
-    byte issuerHash[KEYID_SIZE];  /* hash of all alt Names                */
-    byte issuerSn[MAX_SN_SZ];     /* singleCert's serial number           */
-    byte publicKey[MAX_RSA_INT_SZ + MAX_RSA_E_SZ]; /* MAX RSA key size (m + e)*/
-    word32 certSz[MAX_PKCS7_CERTS];
-    
-     /* flags - up to 16-bits */
-    word16 isDynamic:1;
-
-    /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
-} PKCS7;
-
-
-WOLFSSL_API PKCS7* wc_PKCS7_New(void* heap, int devId);
-WOLFSSL_API int  wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId);
-WOLFSSL_API int  wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz);
-WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7);
-
-WOLFSSL_API int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid,
-        word32 oidSz, byte* out, word32* outSz);
-WOLFSSL_API int  wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output,
-                                       word32 outputSz);
-WOLFSSL_API int  wc_PKCS7_EncodeSignedData(PKCS7* pkcs7,
-                                       byte* output, word32 outputSz);
-WOLFSSL_API int  wc_PKCS7_VerifySignedData(PKCS7* pkcs7,
-                                       byte* pkiMsg, word32 pkiMsgSz);
-WOLFSSL_API int  wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7,
-                                          byte* output, word32 outputSz);
-WOLFSSL_API int  wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
-                                          word32 pkiMsgSz, byte* output,
-                                          word32 outputSz);
-
-WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz);
-WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
-                                 word32 blockSz);
-
-#ifndef NO_PKCS7_ENCRYPTED_DATA
-WOLFSSL_API int  wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7,
-                                          byte* output, word32 outputSz);
-WOLFSSL_API int  wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg,
-                                          word32 pkiMsgSz, byte* output,
-                                          word32 outputSz);
-#endif /* NO_PKCS7_ENCRYPTED_DATA */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_PKCS7 */
-#endif /* WOLF_CRYPT_PKCS7_H */
-
-
--- a/wolfssl/wolfcrypt/poly1305.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* poly1305.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/poly1305.h
-*/
-
-#ifndef WOLF_CRYPT_POLY1305_H
-#define WOLF_CRYPT_POLY1305_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef HAVE_POLY1305
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* auto detect between 32bit / 64bit */
-#if defined(__SIZEOF_INT128__) && defined(__LP64__)
-#define WC_HAS_SIZEOF_INT128_64BIT
-#endif
-
-#if defined(_MSC_VER) && defined(_M_X64)
-#define WC_HAS_MSVC_64BIT
-#endif
-
-#if (defined(__GNUC__) && defined(__LP64__) && \
-        ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))))
-#define WC_HAS_GCC_4_4_64BIT
-#endif
-
-#ifdef USE_INTEL_SPEEDUP
-#elif (defined(WC_HAS_SIZEOF_INT128_64BIT) || defined(WC_HAS_MSVC_64BIT) ||  \
-       defined(WC_HAS_GCC_4_4_64BIT))
-#define POLY130564
-#else
-#define POLY130532
-#endif
-
-enum {
-    POLY1305 = 7,
-    POLY1305_BLOCK_SIZE = 16,
-    POLY1305_DIGEST_SIZE = 16,
-};
-
-#define WC_POLY1305_PAD_SZ 16
-#define WC_POLY1305_MAC_SZ 16
-
-/* Poly1305 state */
-typedef struct Poly1305 {
-#ifdef USE_INTEL_SPEEDUP
-    word64 r[3];
-    word64 h[3];
-    word64 pad[2];
-    word64 hh[20];
-    word32 r1[8];
-    word32 r2[8];
-    word32 r3[8];
-    word32 r4[8];
-    word64 hm[16];
-    unsigned char buffer[8*POLY1305_BLOCK_SIZE];
-    size_t leftover;
-    unsigned char finished;
-    unsigned char started;
-#else
-#if defined(POLY130564)
-    word64 r[3];
-    word64 h[3];
-    word64 pad[2];
-#else
-    word32 r[5];
-    word32 h[5];
-    word32 pad[4];
-#endif
-    size_t leftover;
-    unsigned char buffer[POLY1305_BLOCK_SIZE];
-    unsigned char finished;
-#endif
-} Poly1305;
-
-/* does init */
-
-WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key,
-                                  word32 kySz);
-WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32);
-WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag);
-WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
-                               byte* input, word32 sz, byte* tag, word32 tagSz);
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* HAVE_POLY1305 */
-#endif /* WOLF_CRYPT_POLY1305_H */
-
-
--- a/wolfssl/wolfcrypt/pwdbased.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/* pwdbased.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/pwdbased.h
-*/
-
-#ifndef WOLF_CRYPT_PWDBASED_H
-#define WOLF_CRYPT_PWDBASED_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_PWDBASED
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/*
- * hashType renamed to typeH to avoid shadowing global declaration here:
- * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types
- */
-WOLFSSL_API int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
-                      const byte* passwd, int passwdLen, 
-                      const byte* salt, int saltLen, int iterations, 
-                      int hashType, void* heap);
-WOLFSSL_API int wc_PBKDF1(byte* output, const byte* passwd, int pLen,
-                      const byte* salt, int sLen, int iterations, int kLen,
-                      int typeH);
-WOLFSSL_API int wc_PBKDF2(byte* output, const byte* passwd, int pLen,
-                      const byte* salt, int sLen, int iterations, int kLen,
-                      int typeH);
-WOLFSSL_API int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int pLen,
-                            const byte* salt, int sLen, int iterations,
-                            int kLen, int typeH, int purpose);
-WOLFSSL_API int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen,
-                       const byte* salt, int saltLen, int iterations, int kLen,
-                       int hashType, int id, void* heap);
-
-#ifdef HAVE_SCRYPT
-WOLFSSL_API int wc_scrypt(byte* output, const byte* passwd, int passLen,
-                          const byte* salt, int saltLen, int cost,
-                          int blockSize, int parallel, int dkLen);
-#endif
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_PWDBASED */
-#endif /* WOLF_CRYPT_PWDBASED_H */
-
--- a/wolfssl/wolfcrypt/rabbit.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* rabbit.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/rabbit.h
-*/
-
-
-#ifndef WOLF_CRYPT_RABBIT_H
-#define WOLF_CRYPT_RABBIT_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_RABBIT
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-enum {
-	RABBIT_ENC_TYPE  = 5     /* cipher unique type */
-};
-
-
-/* Rabbit Context */
-typedef struct RabbitCtx {
-    word32 x[8];
-    word32 c[8];
-    word32 carry;
-} RabbitCtx;
-
-
-/* Rabbit stream cipher */
-typedef struct Rabbit {
-    RabbitCtx masterCtx;
-    RabbitCtx workCtx;
-#ifdef XSTREAM_ALIGN
-    void*  heap;  /* heap hint, currently XMALLOC only used with aligning */
-#endif
-} Rabbit;
-
-
-WOLFSSL_API int wc_RabbitProcess(Rabbit*, byte*, const byte*, word32);
-WOLFSSL_API int wc_RabbitSetKey(Rabbit*, const byte* key, const byte* iv);
-
-WOLFSSL_LOCAL int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_RABBIT */
-#endif /* WOLF_CRYPT_RABBIT_H */
-
-
--- a/wolfssl/wolfcrypt/random.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/* random.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/random.h
-*/
-
-
-
-#ifndef WOLF_CRYPT_RANDOM_H
-#define WOLF_CRYPT_RANDOM_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-/* included for fips @wc_fips */
-#if defined(HAVE_FIPS) && \
-        (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-#include <cyassl/ctaocrypt/random.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
- /* Maximum generate block length */
-#ifndef RNG_MAX_BLOCK_LEN
-    #ifdef HAVE_INTEL_QA
-        #define RNG_MAX_BLOCK_LEN (0xFFFF)
-    #else
-        #define RNG_MAX_BLOCK_LEN (0x10000)
-    #endif
-#endif
-
-/* Size of the BRBG seed */
-#ifndef DRBG_SEED_LEN
-    #define DRBG_SEED_LEN (440/8)
-#endif
-
-
-#if !defined(CUSTOM_RAND_TYPE)
-    /* To maintain compatibility the default is byte */
-    #define CUSTOM_RAND_TYPE    byte
-#endif
-
-/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined
-    or CUSTOM_RAND_GENERATE_BLOCK is defined*/
-#if !defined(WC_NO_HASHDRBG) || !defined(CUSTOM_RAND_GENERATE_BLOCK)
-    #undef  HAVE_HASHDRBG
-    #define HAVE_HASHDRBG
-    #ifndef WC_RESEED_INTERVAL
-        #define WC_RESEED_INTERVAL (1000000)
-    #endif
-#endif
-
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-/* RNG supports the following sources (in order):
- * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and
- *     bypasses the options below.
- * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU.
- * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG
- *     seeded via wc_GenerateSeed. This is the default source.
- */
-
- /* Seed source can be overriden by defining one of these:
-      CUSTOM_RAND_GENERATE_SEED
-      CUSTOM_RAND_GENERATE_SEED_OS
-      CUSTOM_RAND_GENERATE */
-
-
-#if defined(CUSTOM_RAND_GENERATE_BLOCK)
-    /* To use define the following:
-     * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
-     * extern int myRngFunc(byte* output, word32 sz);
-     */
-#elif defined(HAVE_HASHDRBG)
-    #ifdef NO_SHA256
-        #error "Hash DRBG requires SHA-256."
-    #endif /* NO_SHA256 */
-    #include <wolfssl/wolfcrypt/sha256.h>
-#elif defined(HAVE_WNR)
-     /* allow whitewood as direct RNG source using wc_GenerateSeed directly */
-#else
-    #error No RNG source defined!
-#endif
-
-#ifdef HAVE_WNR
-    #include <wnr.h>
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-
-#if defined(USE_WINDOWS_API)
-    #if defined(_WIN64)
-        typedef unsigned __int64 ProviderHandle;
-        /* type HCRYPTPROV, avoid #include <windows.h> */
-    #else
-        typedef unsigned long ProviderHandle;
-    #endif
-#endif
-
-
-/* OS specific seeder */
-typedef struct OS_Seed {
-    #if defined(USE_WINDOWS_API)
-        ProviderHandle handle;
-    #else
-        int fd;
-    #endif
-} OS_Seed;
-
-
-#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */
-    typedef struct WC_RNG WC_RNG;
-    #define WC_RNG_TYPE_DEFINED
-#endif
-
-/* RNG context */
-struct WC_RNG {
-    OS_Seed seed;
-    void* heap;
-#ifdef HAVE_HASHDRBG
-    /* Hash-based Deterministic Random Bit Generator */
-    struct DRBG* drbg;
-    byte status;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-    int devId;
-#endif
-};
-
-#endif /* NO FIPS or have FIPS v2*/
-
-/* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts,
- * can't be used with CTaoCrypt FIPS */
-#if !defined(NO_OLD_RNGNAME) && !defined(HAVE_FIPS)
-    #define RNG WC_RNG
-#endif
-
-
-WOLFSSL_LOCAL
-int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz);
-
-
-#ifdef HAVE_WNR
-    /* Whitewood netRandom client library */
-    WOLFSSL_API int  wc_InitNetRandom(const char*, wnr_hmac_key, int);
-    WOLFSSL_API int  wc_FreeNetRandom(void);
-#endif /* HAVE_WNR */
-
-
-WOLFSSL_API int  wc_InitRng(WC_RNG*);
-WOLFSSL_API int  wc_InitRng_ex(WC_RNG* rng, void* heap, int devId);
-WOLFSSL_API int  wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz);
-WOLFSSL_API int  wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
-                                    void* heap, int devId);
-WOLFSSL_API int  wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz);
-WOLFSSL_API int  wc_RNG_GenerateByte(WC_RNG*, byte*);
-WOLFSSL_API int  wc_FreeRng(WC_RNG*);
-
-
-#ifdef HAVE_HASHDRBG
-    WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy,
-                                        word32 entropySz);
-    WOLFSSL_API int wc_RNG_HealthTest(int reseed,
-                                        const byte* entropyA, word32 entropyASz,
-                                        const byte* entropyB, word32 entropyBSz,
-                                        byte* output, word32 outputSz);
-    WOLFSSL_API int wc_RNG_HealthTest_ex(int reseed,
-                                        const byte* nonce, word32 nonceSz,
-                                        const byte* entropyA, word32 entropyASz,
-                                        const byte* entropyB, word32 entropyBSz,
-                                        byte* output, word32 outputSz,
-                                        void* heap, int devId);
-#endif /* HAVE_HASHDRBG */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_RANDOM_H */
-
-
--- a/wolfssl/wolfcrypt/ripemd.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* ripemd.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/ripemd.h
-*/
-
-#ifndef WOLF_CRYPT_RIPEMD_H
-#define WOLF_CRYPT_RIPEMD_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef WOLFSSL_RIPEMD
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-
-/* in bytes */
-enum {
-    RIPEMD             =  3,    /* hash type unique */
-    RIPEMD_BLOCK_SIZE  = 64,
-    RIPEMD_DIGEST_SIZE = 20,
-    RIPEMD_PAD_SIZE    = 56
-};
-
-
-/* RipeMd 160 digest */
-typedef struct RipeMd {
-    word32  buffLen;   /* in bytes          */
-    word32  loLen;     /* length in bytes   */
-    word32  hiLen;     /* length in bytes   */
-    word32  digest[RIPEMD_DIGEST_SIZE / sizeof(word32)];
-    word32  buffer[RIPEMD_BLOCK_SIZE  / sizeof(word32)];
-} RipeMd;
-
-
-WOLFSSL_API int wc_InitRipeMd(RipeMd*);
-WOLFSSL_API int wc_RipeMdUpdate(RipeMd*, const byte*, word32);
-WOLFSSL_API int wc_RipeMdFinal(RipeMd*, byte*);
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_RIPEMD */
-#endif /* WOLF_CRYPT_RIPEMD_H */
-
--- a/wolfssl/wolfcrypt/rsa.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/* rsa.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/rsa.h
-*/
-
-
-#ifndef WOLF_CRYPT_RSA_H
-#define WOLF_CRYPT_RSA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_RSA
-
-
-/* RSA default exponent */
-#ifndef WC_RSA_EXPONENT
-    #define WC_RSA_EXPONENT 65537L
-#endif
-
-
-/* allow for user to plug in own crypto */
-#if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA))
-    #include "user_rsa.h"
-#else
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-/* for fips @wc_fips */
-#include <cyassl/ctaocrypt/rsa.h>
-#if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN)
-    #define WOLFSSL_KEY_GEN
-#endif
-#else
-    #include <wolfssl/wolfcrypt/integer.h>
-    #include <wolfssl/wolfcrypt/random.h>
-#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */
-#if defined(HAVE_FIPS) && \
-	defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-#include <wolfssl/wolfcrypt/fips.h>
-#endif
-
-/* header file needed for OAEP padding */
-#include <wolfssl/wolfcrypt/hash.h>
-
-#ifdef WOLFSSL_XILINX_CRYPT
-#include "xsecure_rsa.h"
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-    #ifdef WOLFSSL_CERT_GEN
-        #include <wolfssl/wolfcrypt/asn.h>
-    #endif
-#endif
-
-enum {
-    RSA_PUBLIC   = 0,
-    RSA_PRIVATE  = 1,
-
-    RSA_TYPE_UNKNOWN    = -1,
-    RSA_PUBLIC_ENCRYPT  = 0,
-    RSA_PUBLIC_DECRYPT  = 1,
-    RSA_PRIVATE_ENCRYPT = 2,
-    RSA_PRIVATE_DECRYPT = 3,
-
-    RSA_BLOCK_TYPE_1 = 1,
-    RSA_BLOCK_TYPE_2 = 2,
-
-    RSA_MIN_SIZE = 512,
-    RSA_MAX_SIZE = 4096,
-
-    RSA_MIN_PAD_SZ   = 11,     /* separator + 0 + pad value + 8 pads */
-
-    RSA_PSS_PAD_SZ = 8,
-    RSA_PSS_SALT_MAX_SZ = 62,
-
-#ifdef OPENSSL_EXTRA
-    RSA_PKCS1_PADDING_SIZE = 11,
-    RSA_PKCS1_OAEP_PADDING_SIZE = 42, /* (2 * hashlen(SHA-1)) + 2 */
-#endif
-#ifdef WC_RSA_PSS
-    RSA_PSS_PAD_TERM = 0xBC,
-#endif
-};
-
-/* RSA */
-struct RsaKey {
-    mp_int n, e, d, p, q;
-#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
-    mp_int dP, dQ, u;
-#endif
-    void* heap;                               /* for user memory overrides */
-    byte* data;                               /* temp buffer for async RSA */
-    int   type;                               /* public or private */
-    int   state;
-    word32 dataLen;
-#ifdef WC_RSA_BLINDING
-    WC_RNG* rng;                              /* for PrivateDecrypt blinding */
-#endif
-#ifdef WOLF_CRYPTO_DEV
-    int   devId;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-    #ifdef WOLFSSL_CERT_GEN
-        CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */
-    #endif
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#ifdef WOLFSSL_XILINX_CRYPT
-    word32 pubExp; /* to keep values in scope they are here in struct */
-    byte*  mod;
-    XSecure_Rsa xRsa;
-#endif
-    byte   dataIsAlloc;
-};
-
-#ifndef WC_RSAKEY_TYPE_DEFINED
-    typedef struct RsaKey RsaKey;
-    #define WC_RSAKEY_TYPE_DEFINED
-#endif
-
-#endif /*HAVE_FIPS */
-
-WOLFSSL_API int  wc_InitRsaKey(RsaKey* key, void* heap);
-WOLFSSL_API int  wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId);
-WOLFSSL_API int  wc_FreeRsaKey(RsaKey* key);
-WOLFSSL_API int  wc_CheckRsaKey(RsaKey* key);
-#ifdef WOLFSSL_XILINX_CRYPT
-WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key);
-#endif /* WOLFSSL_XILINX_CRYPT */
-
-WOLFSSL_API int  wc_RsaFunction(const byte* in, word32 inLen, byte* out,
-                           word32* outLen, int type, RsaKey* key, WC_RNG* rng);
-
-WOLFSSL_API int  wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
-                                 word32 outLen, RsaKey* key, WC_RNG* rng);
-WOLFSSL_API int  wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
-                                        RsaKey* key);
-WOLFSSL_API int  wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
-                                  word32 outLen, RsaKey* key);
-WOLFSSL_API int  wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
-                            word32 outLen, RsaKey* key, WC_RNG* rng);
-WOLFSSL_API int  wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out,
-                                word32 outLen, enum wc_HashType hash, int mgf,
-                                RsaKey* key, WC_RNG* rng);
-WOLFSSL_API int  wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out,
-                                   word32 outLen, enum wc_HashType hash,
-                                   int mgf, int saltLen, RsaKey* key,
-                                   WC_RNG* rng);
-WOLFSSL_API int  wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out,
-                                    RsaKey* key);
-WOLFSSL_API int  wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
-                              word32 outLen, RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
-                                        enum wc_HashType hash, int mgf,
-                                        RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out,
-                                           enum wc_HashType hash, int mgf,
-                                           int saltLen, RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out,
-                                  word32 outLen, enum wc_HashType hash, int mgf,
-                                  RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out,
-                                     word32 outLen, enum wc_HashType hash,
-                                     int mgf, int saltLen, RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_CheckPadding(const byte* in, word32 inLen, byte* sig,
-                                        word32 sigSz,
-                                        enum wc_HashType hashType);
-WOLFSSL_API int  wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inLen,
-                                           byte* sig, word32 sigSz,
-                                           enum wc_HashType hashType,
-                                           int saltLen, int bits);
-WOLFSSL_API int  wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
-                               const byte* digest, word32 digentLen,
-                               enum wc_HashType hash, int mgf,
-                               RsaKey* key);
-WOLFSSL_API int  wc_RsaPSS_VerifyCheck(byte* in, word32 inLen,
-                               byte* out, word32 outLen,
-                               const byte* digest, word32 digestLen,
-                               enum wc_HashType hash, int mgf,
-                               RsaKey* key);
-
-WOLFSSL_API int  wc_RsaEncryptSize(RsaKey* key);
-
-#if !defined(HAVE_FIPS) || \
-	(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-/* to avoid asn duplicate symbols @wc_fips */
-WOLFSSL_API int  wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
-                                                               RsaKey*, word32);
-WOLFSSL_API int  wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx,
-                                                               RsaKey*, word32);
-WOLFSSL_API int  wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
-                                        const byte* e, word32 eSz, RsaKey* key);
-#ifdef WOLFSSL_KEY_GEN
-    WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen);
-#endif
-
-WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
-
-/*
-   choice of padding added after fips, so not available when using fips RSA
- */
-
-/* Mask Generation Function Identifiers */
-#define WC_MGF1NONE   0
-#define WC_MGF1SHA1   26
-#define WC_MGF1SHA224 4
-#define WC_MGF1SHA256 1
-#define WC_MGF1SHA384 2
-#define WC_MGF1SHA512 3
-
-/* Padding types */
-#define WC_RSA_PKCSV15_PAD 0
-#define WC_RSA_OAEP_PAD    1
-#define WC_RSA_PSS_PAD     2
-#define WC_RSA_NO_PAD      3
-
-WOLFSSL_API int  wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
-                   word32 outLen, RsaKey* key, WC_RNG* rng, int type,
-                   enum wc_HashType hash, int mgf, byte* label, word32 lableSz);
-WOLFSSL_API int  wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
-                   byte* out, word32 outLen, RsaKey* key, int type,
-                   enum wc_HashType hash, int mgf, byte* label, word32 lableSz);
-WOLFSSL_API int  wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen,
-                      byte** out, RsaKey* key, int type, enum wc_HashType hash,
-                      int mgf, byte* label, word32 lableSz);
-#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING)
-WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
-                   RsaKey* key, int type, WC_RNG* rng);
-#endif
-
-#endif /* HAVE_FIPS*/
-
-WOLFSSL_API int  wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
-                                                                       word32*);
-WOLFSSL_API int wc_RsaExportKey(RsaKey* key,
-                                byte* e, word32* eSz,
-                                byte* n, word32* nSz,
-                                byte* d, word32* dSz,
-                                byte* p, word32* pSz,
-                                byte* q, word32* qSz);
-
-WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen);
-
-#ifdef WOLFSSL_KEY_GEN
-    WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng);
-    WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz,
-                                          const byte* q, word32 qSz,
-                                          const byte* e, word32 eSz,
-                                          int nlen, int* isPrime);
-#endif
-
-#endif /* HAVE_USER_RSA */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_RSA */
-#endif /* WOLF_CRYPT_RSA_H */
-
-
--- a/wolfssl/wolfcrypt/selftest.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* selftest.h
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifndef WOLFCRYPT_SELF_TEST_H
-#define WOLFCRYPT_SELF_TEST_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef HAVE_SELFTEST
-    /* wolfCrypt self test, runs CAVP KATs */
-    WOLFSSL_API int wolfCrypt_SelfTest(void);
-#endif
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFCRYPT_SELF_TEST_H */
-
-
-
--- a/wolfssl/wolfcrypt/settings.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1746 +0,0 @@
-/* settings.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* Place OS specific preprocessor flags, defines, includes here, will be
-   included into every file because types.h includes it */
-
-
-#ifndef WOLF_CRYPT_SETTINGS_H
-#define WOLF_CRYPT_SETTINGS_H
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Uncomment next line if using IPHONE */
-/* #define IPHONE */
-
-/* Uncomment next line if using ThreadX */
-/* #define THREADX */
-
-/* Uncomment next line if using Micrium uC/OS-III */
-/* #define MICRIUM */
-
-/* Uncomment next line if using Mbed */
-/* #define MBED */
-
-/* Uncomment next line if using Microchip PIC32 ethernet starter kit */
-/* #define MICROCHIP_PIC32 */
-
-/* Uncomment next line if using Microchip TCP/IP stack, version 5 */
-/* #define MICROCHIP_TCPIP_V5 */
-
-/* Uncomment next line if using Microchip TCP/IP stack, version 6 or later */
-/* #define MICROCHIP_TCPIP */
-
-/* Uncomment next line if using PIC32MZ Crypto Engine */
-/* #define WOLFSSL_MICROCHIP_PIC32MZ */
-
-/* Uncomment next line if using FreeRTOS */
-/* #define FREERTOS */
-
-/* Uncomment next line if using FreeRTOS+ TCP */
-/* #define FREERTOS_TCP */
-
-/* Uncomment next line if using FreeRTOS Windows Simulator */
-/* #define FREERTOS_WINSIM */
-
-/* Uncomment next line if using RTIP */
-/* #define EBSNET */
-
-/* Uncomment next line if using lwip */
-/* #define WOLFSSL_LWIP */
-
-/* Uncomment next line if building wolfSSL for a game console */
-/* #define WOLFSSL_GAME_BUILD */
-
-/* Uncomment next line if building wolfSSL for LSR */
-/* #define WOLFSSL_LSR */
-
-/* Uncomment next line if building for Freescale Classic MQX version 4.0 */
-/* #define FREESCALE_MQX_4_0 */
-
-/* Uncomment next line if building for Freescale Classic MQX/RTCS/MFS */
-/* #define FREESCALE_MQX */
-
-/* Uncomment next line if building for Freescale KSDK MQX/RTCS/MFS */
-/* #define FREESCALE_KSDK_MQX */
-
-/* Uncomment next line if building for Freescale KSDK Bare Metal */
-/* #define FREESCALE_KSDK_BM */
-
-/* Uncomment next line if building for Freescale KSDK FreeRTOS, */
-/* (old name FREESCALE_FREE_RTOS) */
-/* #define FREESCALE_KSDK_FREERTOS */
-
-/* Uncomment next line if using STM32F2 */
-/* #define WOLFSSL_STM32F2 */
-
-/* Uncomment next line if using STM32F4 */
-/* #define WOLFSSL_STM32F4 */
-
-/* Uncomment next line if using STM32F7 */
-/* #define WOLFSSL_STM32F7 */
-
-/* Uncomment next line if using QL SEP settings */
-/* #define WOLFSSL_QL */
-
-/* Uncomment next line if building for EROAD */
-/* #define WOLFSSL_EROAD */
-
-/* Uncomment next line if building for IAR EWARM */
-/* #define WOLFSSL_IAR_ARM */
-
-/* Uncomment next line if building for Rowley CrossWorks ARM */
-/* #define WOLFSSL_ROWLEY_ARM */
-
-/* Uncomment next line if using TI-RTOS settings */
-/* #define WOLFSSL_TIRTOS */
-
-/* Uncomment next line if building with PicoTCP */
-/* #define WOLFSSL_PICOTCP */
-
-/* Uncomment next line if building for PicoTCP demo bundle */
-/* #define WOLFSSL_PICOTCP_DEMO */
-
-/* Uncomment next line if building for uITRON4  */
-/* #define WOLFSSL_uITRON4 */
-
-/* Uncomment next line if building for uT-Kernel */
-/* #define WOLFSSL_uTKERNEL2 */
-
-/* Uncomment next line if using Max Strength build */
-/* #define WOLFSSL_MAX_STRENGTH */
-
-/* Uncomment next line if building for VxWorks */
-/* #define WOLFSSL_VXWORKS */
-
-/* Uncomment next line if building for Nordic nRF5x platofrm */
-/* #define WOLFSSL_NRF5x */
-
-/* Uncomment next line to enable deprecated less secure static DH suites */
-/* #define WOLFSSL_STATIC_DH */
-
-/* Uncomment next line to enable deprecated less secure static RSA suites */
-/* #define WOLFSSL_STATIC_RSA */
-
-/* Uncomment next line if building for ARDUINO */
-/* Uncomment both lines if building for ARDUINO on INTEL_GALILEO */
-/* #define WOLFSSL_ARDUINO */
-/* #define INTEL_GALILEO */
-
-/* Uncomment next line to enable asynchronous crypto WC_PENDING_E */
-/* #define WOLFSSL_ASYNC_CRYPT */
-
-/* Uncomment next line if building for uTasker */
-/* #define WOLFSSL_UTASKER */
-
-/* Uncomment next line if building for embOS */
-/* #define WOLFSSL_EMBOS */
-
-/* Uncomment next line if building for RIOT-OS */
-/* #define WOLFSSL_RIOT_OS */
-
-/* Uncomment next line if building for using XILINX hardened crypto */
-/* #define WOLFSSL_XILINX_CRYPT */
-
-/* Uncomment next line if building for using XILINX */
-/* #define WOLFSSL_XILINX */
-
-/* Uncomment next line if building for Nucleus 1.2 */
-/* #define WOLFSSL_NUCLEUS_1_2 */
-
-#include <wolfssl/wolfcrypt/visibility.h>
-#define WOLFSSL_USER_SETTINGS
-#ifdef WOLFSSL_USER_SETTINGS
-    #include "user_settings.h"
-#endif
-
-
-/* make sure old RNG name is used with CTaoCrypt FIPS */
-#ifdef HAVE_FIPS
-    #define WC_RNG RNG
-    /* blinding adds API not available yet in FIPS mode */
-    #undef WC_RSA_BLINDING
-#endif
-
-
-#if defined(_WIN32) && !defined(_M_X64) && \
-    defined(HAVE_AESGCM) && defined(WOLFSSL_AESNI)
-
-/* The _M_X64 macro is what's used in the headers for MSC to tell if it
- * has the 64-bit versions of the 128-bit integers available. If one is
- * building on 32-bit Windows with AES-NI, turn off the AES-GCMloop
- * unrolling. */
-
-    #define AES_GCM_AESNI_NO_UNROLL
-#endif
-
-#ifdef IPHONE
-    #define SIZEOF_LONG_LONG 8
-#endif
-
-#ifdef THREADX
-    #define SIZEOF_LONG_LONG 8
-#endif
-
-#ifdef HAVE_NETX
-    #ifdef NEED_THREADX_TYPES
-        #include <types.h>
-    #endif
-    #include <nx_api.h>
-#endif
-
-#if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */
-    #define WOLFSSL_LWIP
-    #define NO_WRITEV
-    #define SINGLE_THREADED
-    #define WOLFSSL_USER_IO
-    #define NO_FILESYSTEM
-#endif
-
-#if defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_ROWLEY_ARM)
-    #define NO_MAIN_DRIVER
-    #define SINGLE_THREADED
-    #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096)
-        #define USE_CERT_BUFFERS_1024
-    #endif
-    #define BENCH_EMBEDDED
-    #define NO_FILESYSTEM
-    #define NO_WRITEV
-    #define WOLFSSL_USER_IO
-    #define BENCH_EMBEDDED
-#endif
-
-#ifdef MICROCHIP_PIC32
-    /* #define WOLFSSL_MICROCHIP_PIC32MZ */
-    #define SIZEOF_LONG_LONG 8
-    #define SINGLE_THREADED
-    #define WOLFSSL_USER_IO
-    #define NO_WRITEV
-    #define NO_DEV_RANDOM
-    #define NO_FILESYSTEM
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define WOLFSSL_HAVE_MIN
-    #define WOLFSSL_HAVE_MAX
-    #define NO_BIG_INT
-#endif
-
-#ifdef WOLFSSL_MICROCHIP_PIC32MZ
-    #define WOLFSSL_PIC32MZ_CRYPT
-    #define WOLFSSL_PIC32MZ_RNG
-    #define WOLFSSL_PIC32MZ_HASH
-#endif
-
-#ifdef MICROCHIP_TCPIP_V5
-    /* include timer functions */
-    #include "TCPIP Stack/TCPIP.h"
-#endif
-
-#ifdef MICROCHIP_TCPIP
-    /* include timer, NTP functions */
-    #ifdef MICROCHIP_MPLAB_HARMONY
-        #include "tcpip/tcpip.h"
-    #else
-        #include "system/system_services.h"
-        #include "tcpip/sntp.h"
-    #endif
-#endif
-
-#ifdef MBED
-    #define WOLFSSL_USER_IO
-    #define NO_FILESYSTEM
-    #define NO_CERT
-    #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096)
-        #define USE_CERT_BUFFERS_1024
-    #endif
-    #define NO_WRITEV
-    #define NO_DEV_RANDOM
-    #define NO_SHA512
-    #define NO_DH
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    #define NO_DSA
-    #define NO_HC128
-    #define HAVE_ECC
-    #define NO_SESSION_CACHE
-    #define WOLFSSL_CMSIS_RTOS
-#endif
-
-
-#ifdef WOLFSSL_EROAD
-    #define FREESCALE_MQX
-    #define FREESCALE_MMCAU
-    #define SINGLE_THREADED
-    #define NO_STDIO_FILESYSTEM
-    #define WOLFSSL_LEANPSK
-    #define HAVE_NULL_CIPHER
-    #define NO_OLD_TLS
-    #define NO_ASN
-    #define NO_BIG_INT
-    #define NO_RSA
-    #define NO_DSA
-    #define NO_DH
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    #define NO_CERTS
-    #define NO_PWDBASED
-    #define NO_DES3
-    #define NO_MD4
-    #define NO_RC4
-    #define NO_MD5
-    #define NO_SESSION_CACHE
-    #define NO_MAIN_DRIVER
-#endif
-
-#ifdef WOLFSSL_PICOTCP
-    #ifndef errno
-        #define errno pico_err
-    #endif
-    #include "pico_defines.h"
-    #include "pico_stack.h"
-    #include "pico_constants.h"
-    #include "pico_protocol.h"
-    #define CUSTOM_RAND_GENERATE pico_rand
-#endif
-
-#ifdef WOLFSSL_PICOTCP_DEMO
-    #define WOLFSSL_STM32
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define XMALLOC(s, h, type)  PICO_ZALLOC((s))
-    #define XFREE(p, h, type)    PICO_FREE((p))
-    #define SINGLE_THREADED
-    #define NO_WRITEV
-    #define WOLFSSL_USER_IO
-    #define NO_DEV_RANDOM
-    #define NO_FILESYSTEM
-#endif
-
-#ifdef FREERTOS_WINSIM
-    #define FREERTOS
-    #define USE_WINDOWS_API
-#endif
-
-
-#ifdef WOLFSSL_VXWORKS
-    /* VxWorks simulator incorrectly detects building for i386 */
-    #ifdef VXWORKS_SIM
-        #define TFM_NO_ASM
-    #endif
-    #define WOLFSSL_PTHREADS
-    #define WOLFSSL_HAVE_MIN
-    #define WOLFSSL_HAVE_MAX
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define NO_MAIN_DRIVER
-    #define NO_DEV_RANDOM
-    #define NO_WRITEV
-#endif
-
-
-#ifdef WOLFSSL_ARDUINO
-    #define NO_WRITEV
-    #define NO_WOLFSSL_DIR
-    #define SINGLE_THREADED
-    #define NO_DEV_RANDOM
-    #ifndef INTEL_GALILEO /* Galileo has time.h compatibility */
-        #define TIME_OVERRIDES /* must define XTIME and XGMTIME externally */
-    #endif
-    #define WOLFSSL_USER_IO
-    #define HAVE_ECC
-    #define NO_DH
-    #define NO_SESSION_CACHE
-    #define USE_SLOW_SHA
-    #define NO_WOLFSSL_SERVER
-    #define NO_ERROR_STRINGS
-#endif
-
-
-#ifdef WOLFSSL_UTASKER
-    /* uTasker configuration - used for fnRandom() */
-    #include "config.h"
-
-    #define SINGLE_THREADED
-    #define NO_WOLFSSL_DIR
-    #define WOLFSSL_HAVE_MIN
-    #define NO_WRITEV
-
-    #define HAVE_ECC
-    #define ALT_ECC_SIZE
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define ECC_TIMING_RESISTANT
-
-    /* used in wolfCrypt test */
-    #define NO_MAIN_DRIVER
-    #define USE_CERT_BUFFERS_2048
-
-    /* uTasker port uses RAW sockets, use I/O callbacks
-     * See wolfSSL uTasker example for sample callbacks */
-    #define WOLFSSL_USER_IO
-
-    /* uTasker filesystem not ported  */
-    #define NO_FILESYSTEM
-
-    /* uTasker RNG is abstracted, calls HW RNG when available */
-    #define CUSTOM_RAND_GENERATE    fnRandom
-    #define CUSTOM_RAND_TYPE        unsigned short
-
-    /* user needs to define XTIME to function that provides
-     * seconds since Unix epoch */
-    #ifndef XTIME
-        #error XTIME must be defined in wolfSSL settings.h
-        /* #define XTIME fnSecondsSinceEpoch */
-    #endif
-
-    /* use uTasker std library replacements where available */
-    #define STRING_USER
-    #define XMEMCPY(d,s,l)         uMemcpy((d),(s),(l))
-    #define XMEMSET(b,c,l)         uMemset((b),(c),(l))
-    #define XMEMCMP(s1,s2,n)       uMemcmp((s1),(s2),(n))
-    #define XMEMMOVE(d,s,l)        memmove((d),(s),(l))
-
-    #define XSTRLEN(s1)            uStrlen((s1))
-    #define XSTRNCPY(s1,s2,n)      strncpy((s1),(s2),(n))
-    #define XSTRSTR(s1,s2)         strstr((s1),(s2))
-    #define XSTRNSTR(s1,s2,n)      mystrnstr((s1),(s2),(n))
-    #define XSTRNCMP(s1,s2,n)      strncmp((s1),(s2),(n))
-    #define XSTRNCAT(s1,s2,n)      strncat((s1),(s2),(n))
-    #define XSTRNCASECMP(s1,s2,n)  _strnicmp((s1),(s2),(n))
-    #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN)
-        #define XSTRTOK            strtok_r
-    #endif
-#endif
-
-#ifdef WOLFSSL_EMBOS
-    #define NO_FILESYSTEM           /* Not ported at this time */
-    #define USE_CERT_BUFFERS_2048   /* use when NO_FILESYSTEM */
-    #define NO_MAIN_DRIVER
-    #define NO_RC4
-    #define SINGLE_THREADED         /* Not ported at this time */
-#endif
-
-#ifdef WOLFSSL_RIOT_OS
-    #define NO_WRITEV
-    #define TFM_NO_ASM
-    #define USE_FAST_MATH
-    #define NO_FILESYSTEM
-    #define USE_CERT_BUFFERS_2048
-#endif
-
-#ifdef WOLFSSL_CHIBIOS
-    /* ChibiOS definitions. This file is distributed with chibiOS. */
-    #include "wolfssl_chibios.h"
-#endif
-
-#ifdef WOLFSSL_PB
-    /* PB is using older 1.2 version of Nucleus */
-    #undef WOLFSSL_NUCLEUS
-    #define WOLFSSL_NUCLEUS_1_2
-#endif
-
-#ifdef WOLFSSL_NUCLEUS_1_2
-    #define NO_WRITEV
-    #define NO_WOLFSSL_DIR
-
-    #if !defined(NO_ASN_TIME) && !defined(USER_TIME)
-        #error User must define XTIME, see manual
-    #endif
-
-    #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER)
-        extern void* nucleus_malloc(unsigned long size, void* heap, int type);
-        extern void* nucleus_realloc(void* ptr, unsigned long size, void* heap,
-                                     int type);
-        extern void  nucleus_free(void* ptr, void* heap, int type);
-
-        #define XMALLOC(s, h, type)  nucleus_malloc
-        #define XREALLOC(p, n, h, t) nucleus_realloc
-        #define XFREE(p, h, type)    nucleus_free
-    #endif
-#endif
-
-#ifdef WOLFSSL_NRF5x
-        #define SIZEOF_LONG 4
-        #define SIZEOF_LONG_LONG 8
-        #define NO_ASN_TIME
-        #define NO_DEV_RANDOM
-        #define NO_FILESYSTEM
-        #define NO_MAIN_DRIVER
-        #define NO_WRITEV
-        #define SINGLE_THREADED
-        #define USE_FAST_MATH
-        #define TFM_TIMING_RESISTANT
-        #define USE_WOLFSSL_MEMORY
-        #define WOLFSSL_NRF51
-        #define WOLFSSL_USER_IO
-        #define NO_SESSION_CACHE
-#endif
-
-/* Micrium will use Visual Studio for compilation but not the Win32 API */
-#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \
-    !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \
-    !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS)
-    #define USE_WINDOWS_API
-#endif
-
-#if defined(WOLFSSL_uITRON4)
-
-#define XMALLOC_USER
-#include <stddef.h>
-#define ITRON_POOL_SIZE 1024*20
-extern int uITRON4_minit(size_t poolsz) ;
-extern void *uITRON4_malloc(size_t sz) ;
-extern void *uITRON4_realloc(void *p, size_t sz) ;
-extern void uITRON4_free(void *p) ;
-
-#define XMALLOC(sz, heap, type)     uITRON4_malloc(sz)
-#define XREALLOC(p, sz, heap, type) uITRON4_realloc(p, sz)
-#define XFREE(p, heap, type)        uITRON4_free(p)
-#endif
-
-#if defined(WOLFSSL_uTKERNEL2)
-  #ifndef NO_TKERNEL_MEM_POOL
-    #define XMALLOC_OVERRIDE
-    int   uTKernel_init_mpool(unsigned int sz); /* initializing malloc pool */
-    void* uTKernel_malloc(unsigned int sz);
-    void* uTKernel_realloc(void *p, unsigned int sz);
-    void  uTKernel_free(void *p);
-    #define XMALLOC(s, h, type)  uTKernel_malloc((s))
-    #define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n))
-    #define XFREE(p, h, type)    uTKernel_free((p))
-  #endif
-
-  #ifndef NO_STDIO_FGETS_REMAP
-    #include <stdio.h>
-    #include "tm/tmonitor.h"
-
-    /* static char* gets(char *buff); */
-    static char* fgets(char *buff, int sz, FILE *fp) {
-        char * p = buff;
-        *p = '\0';
-        while (1) {
-            *p = tm_getchar(-1);
-            tm_putchar(*p);
-            if (*p == '\r') {
-                tm_putchar('\n');
-                *p = '\0';
-                break;
-            }
-            p++;
-        }
-        return buff;
-    }
-  #endif /* !NO_STDIO_FGETS_REMAP */
-#endif
-
-
-#if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER)
-    #include <stdlib.h>
-    #define XMALLOC(s, h, type)  malloc((s))
-    #define XFREE(p, h, type)    free((p))
-    #define XREALLOC(p, n, h, t) realloc((p), (n))
-#endif
-
-#if defined(XMALLOC_USER) && defined(SSN_BUILDING_LIBYASSL)
-    #undef  XMALLOC
-    #define XMALLOC     yaXMALLOC
-    #undef  XFREE
-    #define XFREE       yaXFREE
-    #undef  XREALLOC
-    #define XREALLOC    yaXREALLOC
-#endif
-
-
-#ifdef FREERTOS
-    #include "FreeRTOS.h"
-
-    /* FreeRTOS pvPortRealloc() only in AVR32_UC3 port */
-    #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \
-        !defined(WOLFSSL_STATIC_MEMORY)
-        #define XMALLOC(s, h, type)  pvPortMalloc((s))
-        #define XFREE(p, h, type)    vPortFree((p))
-    #endif
-
-    #ifndef NO_WRITEV
-        #define NO_WRITEV
-    #endif
-    #ifndef HAVE_SHA512
-        #ifndef NO_SHA512
-            #define NO_SHA512
-        #endif
-    #endif
-    #ifndef HAVE_DH
-        #ifndef NO_DH
-            #define NO_DH
-        #endif
-    #endif
-    #ifndef NO_DSA
-        #define NO_DSA
-    #endif
-    #ifndef NO_HC128
-        #define NO_HC128
-    #endif
-
-    #ifndef SINGLE_THREADED
-        #include "semphr.h"
-    #endif
-#endif
-
-#ifdef FREERTOS_TCP
-    #if !defined(NO_WOLFSSL_MEMORY) && !defined(XMALLOC_USER) && \
-        !defined(WOLFSSL_STATIC_MEMORY)
-        #define XMALLOC(s, h, type)  pvPortMalloc((s))
-        #define XFREE(p, h, type)    vPortFree((p))
-    #endif
-
-    #define WOLFSSL_GENSEED_FORTEST
-
-    #define NO_WOLFSSL_DIR
-    #define NO_WRITEV
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define NO_MAIN_DRIVER
-#endif
-
-#ifdef WOLFSSL_TIRTOS
-    #define SIZEOF_LONG_LONG 8
-    #define NO_WRITEV
-    #define NO_WOLFSSL_DIR
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define ECC_TIMING_RESISTANT
-    #define WC_RSA_BLINDING
-    #define NO_DEV_RANDOM
-    #define NO_FILESYSTEM
-    #define USE_CERT_BUFFERS_2048
-    #define NO_ERROR_STRINGS
-    #define USER_TIME
-    #define HAVE_ECC
-    #define HAVE_ALPN
-    #define USE_WOLF_STRTOK /* use with HAVE_ALPN */
-    #define HAVE_TLS_EXTENSIONS
-    #define HAVE_AESGCM
-    #define HAVE_SUPPORTED_CURVES
-    #define ALT_ECC_SIZE
-
-    #ifdef __IAR_SYSTEMS_ICC__
-        #pragma diag_suppress=Pa089
-    #elif !defined(__GNUC__)
-        /* Suppress the sslpro warning */
-        #pragma diag_suppress=11
-    #endif
-
-    #include <ti/sysbios/hal/Seconds.h>
-#endif
-
-#ifdef EBSNET
-    #include "rtip.h"
-
-    /* #define DEBUG_WOLFSSL */
-    #define NO_WOLFSSL_DIR  /* tbd */
-
-    #if (POLLOS)
-        #define SINGLE_THREADED
-    #endif
-
-    #if (RTPLATFORM)
-        #if (!RTP_LITTLE_ENDIAN)
-            #define BIG_ENDIAN_ORDER
-        #endif
-    #else
-        #if (!KS_LITTLE_ENDIAN)
-            #define BIG_ENDIAN_ORDER
-        #endif
-    #endif
-
-    #if (WINMSP3)
-        #undef SIZEOF_LONG
-        #define SIZEOF_LONG_LONG 8
-    #else
-        #sslpro: settings.h - please implement SIZEOF_LONG and SIZEOF_LONG_LONG
-    #endif
-
-    #define XMALLOC(s, h, type) ((void *)rtp_malloc((s), SSL_PRO_MALLOC))
-    #define XFREE(p, h, type) (rtp_free(p))
-    #define XREALLOC(p, n, h, t) realloc((p), (n))
-
-#endif /* EBSNET */
-
-#ifdef WOLFSSL_GAME_BUILD
-    #define SIZEOF_LONG_LONG 8
-    #if defined(__PPU) || defined(__XENON)
-        #define BIG_ENDIAN_ORDER
-    #endif
-#endif
-
-#ifdef WOLFSSL_LSR
-    #define HAVE_WEBSERVER
-    #define SIZEOF_LONG_LONG 8
-    #define WOLFSSL_LOW_MEMORY
-    #define NO_WRITEV
-    #define NO_SHA512
-    #define NO_DH
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    #define NO_DSA
-    #define NO_HC128
-    #define NO_DEV_RANDOM
-    #define NO_WOLFSSL_DIR
-    #define NO_RABBIT
-    #ifndef NO_FILESYSTEM
-        #define LSR_FS
-        #include "inc/hw_types.h"
-        #include "fs.h"
-    #endif
-    #define WOLFSSL_LWIP
-    #include <errno.h>  /* for tcp errno */
-    #define WOLFSSL_SAFERTOS
-    #if defined(__IAR_SYSTEMS_ICC__)
-        /* enum uses enum */
-        #pragma diag_suppress=Pa089
-    #endif
-#endif
-
-#ifdef WOLFSSL_SAFERTOS
-    #ifndef SINGLE_THREADED
-        #include "SafeRTOS/semphr.h"
-    #endif
-
-    #include "SafeRTOS/heap.h"
-    #define XMALLOC(s, h, type)  pvPortMalloc((s))
-    #define XFREE(p, h, type)    vPortFree((p))
-    #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n))
-#endif
-
-#ifdef WOLFSSL_LOW_MEMORY
-    #undef  RSA_LOW_MEM
-    #define RSA_LOW_MEM
-    #undef  WOLFSSL_SMALL_STACK
-    #define WOLFSSL_SMALL_STACK
-    #undef  TFM_TIMING_RESISTANT
-    #define TFM_TIMING_RESISTANT
-#endif
-
-#ifdef FREESCALE_MQX_4_0
-    /* use normal Freescale MQX port, but with minor changes for 4.0 */
-    #define FREESCALE_MQX
-#endif
-
-#ifdef FREESCALE_MQX
-    #define FREESCALE_COMMON
-    #include "mqx.h"
-    #ifndef NO_FILESYSTEM
-        #include "mfs.h"
-        #if MQX_USE_IO_OLD
-            #include "fio.h"
-            #define NO_STDIO_FILESYSTEM
-        #else
-            #include "nio.h"
-        #endif
-    #endif
-    #ifndef SINGLE_THREADED
-        #include "mutex.h"
-    #endif
-
-    #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER)
-        #define XMALLOC_OVERRIDE
-        #define XMALLOC(s, h, t)    (void *)_mem_alloc_system((s))
-        #define XFREE(p, h, t)      {void* xp = (p); if ((xp)) _mem_free((xp));}
-        /* Note: MQX has no realloc, using fastmath above */
-    #endif
-#endif
-
-#ifdef FREESCALE_KSDK_MQX
-    #define FREESCALE_COMMON
-    #include <mqx.h>
-    #ifndef NO_FILESYSTEM
-        #if MQX_USE_IO_OLD
-            #include <fio.h>
-        #else
-            #include <stdio.h>
-            #include <nio.h>
-        #endif
-    #endif
-    #ifndef SINGLE_THREADED
-        #include <mutex.h>
-    #endif
-
-    #define XMALLOC(s, h, t)    (void *)_mem_alloc_system((s))
-    #define XFREE(p, h, t)      {void* xp = (p); if ((xp)) _mem_free((xp));}
-    #define XREALLOC(p, n, h, t) _mem_realloc((p), (n)) /* since MQX 4.1.2 */
-
-    #define MQX_FILE_PTR FILE *
-    #define IO_SEEK_SET  SEEK_SET
-    #define IO_SEEK_END  SEEK_END
-#endif /* FREESCALE_KSDK_MQX */
-
-#if defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    #define NO_FILESYSTEM
-    #define WOLFSSL_CRYPT_HW_MUTEX 1
-
-    #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY)
-        #define XMALLOC(s, h, type)  pvPortMalloc((s))
-        #define XFREE(p, h, type)    vPortFree((p))
-    #endif
-
-    //#define USER_TICKS
-    /* Allows use of DH with fixed points if uncommented and NO_DH is removed */
-    /* WOLFSSL_DH_CONST */
-    #define WOLFSSL_LWIP
-    #define FREERTOS_TCP
-
-    #define FREESCALE_FREE_RTOS
-    #define FREERTOS_SOCKET_ERROR ( -1 )
-    #define FREERTOS_EWOULDBLOCK ( -2 )
-    #define FREERTOS_EINVAL ( -4 )
-    #define FREERTOS_EADDRNOTAVAIL ( -5 )
-    #define FREERTOS_EADDRINUSE ( -6 )
-    #define FREERTOS_ENOBUFS ( -7 )
-    #define FREERTOS_ENOPROTOOPT ( -8 )
-#endif /* FREESCALE_FREE_RTOS || FREESCALE_KSDK_FREERTOS */
-
-#ifdef FREESCALE_KSDK_BM
-    #define FREESCALE_COMMON
-    #define WOLFSSL_USER_IO
-    #define SINGLE_THREADED
-    #define NO_FILESYSTEM
-    #ifndef TIME_OVERRIDES
-        #define USER_TICKS
-    #endif
-#endif /* FREESCALE_KSDK_BM */
-
-#ifdef FREESCALE_COMMON
-    #define SIZEOF_LONG_LONG 8
-
-    /* disable features */
-    #undef  NO_WRITEV
-    #define NO_WRITEV
-    #undef  NO_DEV_RANDOM
-    #define NO_DEV_RANDOM
-    #undef  NO_RABBIT
-    #define NO_RABBIT
-    #undef  NO_WOLFSSL_DIR
-    #define NO_WOLFSSL_DIR
-    #undef  NO_RC4
-    #define NO_RC4
-
-    /* enable features */
-    #undef  USE_FAST_MATH
-    #define USE_FAST_MATH
-
-    #define USE_CERT_BUFFERS_2048
-    #define BENCH_EMBEDDED
-
-    #define TFM_TIMING_RESISTANT
-    #define ECC_TIMING_RESISTANT
-
-    #undef  HAVE_ECC
-    #define HAVE_ECC
-    #ifndef NO_AES
-        #undef  HAVE_AESCCM
-        #define HAVE_AESCCM
-        #undef  HAVE_AESGCM
-        #define HAVE_AESGCM
-        #undef  WOLFSSL_AES_COUNTER
-        #define WOLFSSL_AES_COUNTER
-        #undef  WOLFSSL_AES_DIRECT
-        #define WOLFSSL_AES_DIRECT
-    #endif
-
-    #ifdef FREESCALE_KSDK_1_3
-        #include "fsl_device_registers.h"
-    #elif !defined(FREESCALE_MQX)
-        /* Classic MQX does not have fsl_common.h */
-        #include "fsl_common.h"
-    #endif
-
-    /* random seed */
-    #define NO_OLD_RNGNAME
-    #if defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0)
-        #define FREESCALE_KSDK_2_0_TRNG
-    #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0)
-        #ifdef FREESCALE_KSDK_1_3
-            #include "fsl_rnga_driver.h"
-            #define FREESCALE_RNGA
-            #define RNGA_INSTANCE (0)
-        #else
-            #define FREESCALE_KSDK_2_0_RNGA
-        #endif
-    #elif !defined(FREESCALE_KSDK_BM) && !defined(FREESCALE_FREE_RTOS) && !defined(FREESCALE_KSDK_FREERTOS)
-        #define FREESCALE_RNGA
-        #define RNGA_INSTANCE (0)
-        /* defaulting to K70 RNGA, user should change if different */
-        /* #define FREESCALE_K53_RNGB */
-        #define FREESCALE_K70_RNGA
-    #endif
-
-    /* HW crypto */
-    /* automatic enable based on Kinetis feature */
-    /* if case manual selection is required, for example for benchmarking purposes,
-     * just define FREESCALE_USE_MMCAU or FREESCALE_USE_LTC or none of these two macros (for software only)
-     * both can be enabled simultaneously as LTC has priority over MMCAU in source code.
-     */
-    /* #define FSL_HW_CRYPTO_MANUAL_SELECTION */
-    #ifndef FSL_HW_CRYPTO_MANUAL_SELECTION
-        #if defined(FSL_FEATURE_SOC_MMCAU_COUNT) && FSL_FEATURE_SOC_MMCAU_COUNT
-            #define FREESCALE_USE_MMCAU
-        #endif
-
-        #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT
-            #define FREESCALE_USE_LTC
-        #endif
-    #else
-        /* #define FREESCALE_USE_MMCAU */
-        /* #define FREESCALE_USE_LTC */
-    #endif
-#endif /* FREESCALE_COMMON */
-
-/* Classic pre-KSDK mmCAU library */
-#ifdef FREESCALE_USE_MMCAU_CLASSIC
-    #define FREESCALE_USE_MMCAU
-    #define FREESCALE_MMCAU_CLASSIC
-    #define FREESCALE_MMCAU_CLASSIC_SHA
-#endif
-
-/* KSDK mmCAU library */
-#ifdef FREESCALE_USE_MMCAU
-    /* AES and DES */
-    #define FREESCALE_MMCAU
-    /* MD5, SHA-1 and SHA-256 */
-    #define FREESCALE_MMCAU_SHA
-#endif /* FREESCALE_USE_MMCAU */
-
-#ifdef FREESCALE_USE_LTC
-    #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT
-        #define FREESCALE_LTC
-        #define LTC_BASE LTC0
-
-        #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
-            #define FREESCALE_LTC_DES
-        #endif
-
-        #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
-            #define FREESCALE_LTC_AES_GCM
-        #endif
-
-        #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
-            #define FREESCALE_LTC_SHA
-        #endif
-
-        #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
-            #define FREESCALE_LTC_ECC
-            #define FREESCALE_LTC_TFM
-
-            /* the LTC PKHA hardware limit is 2048 bits (256 bytes) for integer arithmetic.
-               the LTC_MAX_INT_BYTES defines the size of local variables that hold big integers. */
-            #ifndef LTC_MAX_INT_BYTES
-                #define LTC_MAX_INT_BYTES (256)
-            #endif
-
-            /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined.
-             * In such a case both software and hardware algorithm
-             * for TFM is linked in. The decision for which algorithm is used is determined at runtime
-             * from size of inputs. If inputs and result can fit into LTC (see LTC_MAX_INT_BYTES)
-             * then we call hardware algorithm, otherwise we call software algorithm.
-             *
-             * Chinese reminder theorem is used to break RSA 4096 exponentiations (both public and private key)
-             * into several computations with 2048-bit modulus and exponents.
-             */
-            /* #define FREESCALE_LTC_TFM_RSA_4096_ENABLE */
-
-            /* ECC-384, ECC-256, ECC-224 and ECC-192 have been enabled with LTC PKHA acceleration */
-            #ifdef HAVE_ECC
-                #undef  ECC_TIMING_RESISTANT
-                #define ECC_TIMING_RESISTANT
-
-                /* the LTC PKHA hardware limit is 512 bits (64 bytes) for ECC.
-                   the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters
-                   and point coordinates */
-                #ifndef LTC_MAX_ECC_BITS
-                    #define LTC_MAX_ECC_BITS (384)
-                #endif
-
-                /* Enable curves up to 384 bits */
-                #if !defined(ECC_USER_CURVES) && !defined(HAVE_ALL_CURVES)
-                    #define ECC_USER_CURVES
-                    #define HAVE_ECC192
-                    #define HAVE_ECC224
-                    #undef  NO_ECC256
-                    #define HAVE_ECC384
-                #endif
-
-                /* enable features */
-                #undef  HAVE_CURVE25519
-                #define HAVE_CURVE25519
-                #undef  HAVE_ED25519
-                #define HAVE_ED25519
-                #undef  WOLFSSL_SHA512
-                #define WOLFSSL_SHA512
-            #endif
-        #endif
-    #endif
-#endif /* FREESCALE_USE_LTC */
-
-#ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE
-    #undef  USE_CERT_BUFFERS_4096
-    #define USE_CERT_BUFFERS_4096
-    #undef  FP_MAX_BITS
-    #define FP_MAX_BITS (8192)
-
-    #undef  NO_DH
-    #define NO_DH
-    #undef  NO_DSA
-    #define NO_DSA
-#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */
-
-/* if LTC has AES engine but doesn't have GCM, use software with LTC AES ECB mode */
-#if defined(FREESCALE_USE_LTC) && !defined(FREESCALE_LTC_AES_GCM)
-    #define GCM_TABLE
-#endif
-
-#if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \
-    defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32F1) || \
-    defined(WOLFSSL_STM32L4)
-
-    #define SIZEOF_LONG_LONG 8
-    #define NO_DEV_RANDOM
-    #define NO_WOLFSSL_DIR
-    #undef  NO_RABBIT
-    #define NO_RABBIT
-    #ifndef NO_STM32_RNG
-        #undef  STM32_RNG
-        #define STM32_RNG
-        #ifdef WOLFSSL_STM32F427_RNG
-            #include "stm32f427xx.h"
-        #endif
-    #endif
-    #ifndef NO_STM32_CRYPTO
-        #undef  STM32_CRYPTO
-        #define STM32_CRYPTO
-    #endif
-    #ifndef NO_STM32_HASH
-        #undef  STM32_HASH
-        #define STM32_HASH
-    #endif
-    #if !defined(__GNUC__) && !defined(__ICCARM__)
-        #define KEIL_INTRINSICS
-    #endif
-    #define NO_OLD_RNGNAME
-    #ifdef WOLFSSL_STM32_CUBEMX
-        #if defined(WOLFSSL_STM32F2)
-            #include "stm32f2xx_hal.h"
-        #elif defined(WOLFSSL_STM32L4)
-            #include "stm32l4xx_hal.h"
-        #elif defined(WOLFSSL_STM32F4)
-            #include "stm32f4xx_hal.h"
-        #elif defined(WOLFSSL_STM32F7)
-            #include "stm32f7xx_hal.h"
-        #elif defined(WOLFSSL_STM32F1)
-            #include "stm32f1xx_hal.h"
-        #endif
-
-        #ifndef STM32_HAL_TIMEOUT
-            #define STM32_HAL_TIMEOUT   0xFF
-        #endif
-    #else
-        #if defined(WOLFSSL_STM32F2)
-            #include "stm32f2xx.h"
-            #ifdef STM32_CRYPTO
-                #include "stm32f2xx_cryp.h"
-            #endif
-            #ifdef STM32_HASH
-                #include "stm32f2xx_hash.h"
-            #endif
-        #elif defined(WOLFSSL_STM32F4)
-            #include "stm32f4xx.h"
-            #ifdef STM32_CRYPTO
-                #include "stm32f4xx_cryp.h"
-            #endif
-            #ifdef STM32_HASH
-                #include "stm32f4xx_hash.h"
-            #endif
-        #elif defined(WOLFSSL_STM32L4)
-            #include "stm32l4xx.h"
-            #ifdef STM32_CRYPTO
-                #include "stm32l4xx_cryp.h"
-            #endif
-            #ifdef STM32_HASH
-                #include "stm32l4xx_hash.h"
-            #endif
-        #elif defined(WOLFSSL_STM32F7)
-            #include "stm32f7xx.h"
-        #elif defined(WOLFSSL_STM32F1)
-            #include "stm32f1xx.h"
-        #endif
-    #endif /* WOLFSSL_STM32_CUBEMX */
-#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32F7 */
-
-#ifdef MICRIUM
-    #include <stdlib.h>
-    #include <os.h>
-    #include <net_cfg.h>
-    #include <net_sock.h>
-    #include <net_err.h>
-    #include <lib_mem.h>
-    #include <lib_math.h>
-
-    #define USE_FAST_MATH
-    #define TFM_TIMING_RESISTANT
-    #define ECC_TIMING_RESISTANT
-    #define WC_RSA_BLINDING
-    #define HAVE_HASHDRBG
-
-    #define HAVE_ECC
-    #define ALT_ECC_SIZE
-    #define TFM_ECC192
-    #define TFM_ECC224
-    #define TFM_ECC256
-    #define TFM_ECC384
-    #define TFM_ECC521
-
-    #define NO_RC4
-    #define HAVE_TLS_EXTENSIONS
-    #define HAVE_SUPPORTED_CURVES
-    #define HAVE_EXTENDED_MASTER
-
-    #define NO_WOLFSSL_DIR
-    #define NO_WRITEV
-
-    #ifndef CUSTOM_RAND_GENERATE
-        #define CUSTOM_RAND_TYPE     RAND_NBR
-        #define CUSTOM_RAND_GENERATE Math_Rand
-    #endif
-
-    #define WOLFSSL_TYPES
-    typedef CPU_INT08U byte;
-    typedef CPU_INT16U word16;
-    typedef CPU_INT32U word32;
-
-    #define STRING_USER
-    #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr)))
-    #define XSTRNCPY(pstr_dest, pstr_src, len_max) \
-                    ((CPU_CHAR *)Str_Copy_N((CPU_CHAR *)(pstr_dest), \
-                     (CPU_CHAR *)(pstr_src), (CPU_SIZE_T)(len_max)))
-    #define XSTRNCMP(pstr_1, pstr_2, len_max) \
-                    ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \
-                     (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
-    #define XSTRNCASECMP(pstr_1, pstr_2, len_max) \
-                    ((CPU_INT16S)Str_CmpIgnoreCase_N((CPU_CHAR *)(pstr_1), \
-                     (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
-    #define XSTRSTR(pstr, pstr_srch) \
-                    ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \
-                     (CPU_CHAR *)(pstr_srch)))
-    #define XSTRNSTR(pstr, pstr_srch, len_max) \
-                    ((CPU_CHAR *)Str_Str_N((CPU_CHAR *)(pstr), \
-                     (CPU_CHAR *)(pstr_srch),(CPU_SIZE_T)(len_max)))
-    #define XSTRNCAT(pstr_dest, pstr_cat, len_max) \
-                    ((CPU_CHAR *)Str_Cat_N((CPU_CHAR *)(pstr_dest), \
-                     (const CPU_CHAR *)(pstr_cat),(CPU_SIZE_T)(len_max)))
-    #define XMEMSET(pmem, data_val, size) \
-                    ((void)Mem_Set((void *)(pmem), (CPU_INT08U) (data_val), \
-                    (CPU_SIZE_T)(size)))
-    #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \
-                     (void *)(psrc), (CPU_SIZE_T)(size)))
-    #define XMEMCMP(pmem_1, pmem_2, size) \
-                   (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), (void *)(pmem_2), \
-                     (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES)
-    #define XMEMMOVE XMEMCPY
-
-    #if (OS_CFG_MUTEX_EN == DEF_DISABLED)
-        #define SINGLE_THREADED
-    #endif
-
-    #if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
-        #define BIG_ENDIAN_ORDER
-    #else
-        #undef  BIG_ENDIAN_ORDER
-        #define LITTLE_ENDIAN_ORDER
-    #endif
-#endif /* MICRIUM */
-
-
-#ifdef WOLFSSL_QL
-    #ifndef WOLFSSL_SEP
-        #define WOLFSSL_SEP
-    #endif
-    #ifndef OPENSSL_EXTRA
-        #define OPENSSL_EXTRA
-    #endif
-    #ifndef SESSION_CERTS
-        #define SESSION_CERTS
-    #endif
-    #ifndef HAVE_AESCCM
-        #define HAVE_AESCCM
-    #endif
-    #ifndef ATOMIC_USER
-        #define ATOMIC_USER
-    #endif
-    #ifndef WOLFSSL_DER_LOAD
-        #define WOLFSSL_DER_LOAD
-    #endif
-    #ifndef KEEP_PEER_CERT
-        #define KEEP_PEER_CERT
-    #endif
-    #ifndef HAVE_ECC
-        #define HAVE_ECC
-    #endif
-    #ifndef SESSION_INDEX
-        #define SESSION_INDEX
-    #endif
-#endif /* WOLFSSL_QL */
-
-
-#if defined(WOLFSSL_XILINX)
-    #define USER_TIME /* XTIME in asn.c */
-    #define NO_WOLFSSL_DIR
-    #define NO_DEV_RANDOM
-    #define HAVE_AESGCM
-#endif
-
-#if defined(WOLFSSL_XILINX_CRYPT)
-    #if defined(WOLFSSL_ARMASM)
-        #error can not use both ARMv8 instructions and XILINX hardened crypto
-    #endif
-    #if defined(WOLFSSL_SHA3)
-        /* only SHA3-384 is supported */
-        #undef WOLFSSL_NOSHA3_224
-        #undef WOLFSSL_NOSHA3_256
-        #undef WOLFSSL_NOSHA3_512
-        #define WOLFSSL_NOSHA3_224
-        #define WOLFSSL_NOSHA3_256
-        #define WOLFSSL_NOSHA3_512
-    #endif
-#endif /*(WOLFSSL_XILINX_CRYPT)*/
-
-#ifdef WOLFSSL_IMX6
-    #ifndef SIZEOF_LONG_LONG
-        #define SIZEOF_LONG_LONG 8
-    #endif
-#endif
-
-/* if defined turn on all CAAM support */
-#ifdef WOLFSSL_IMX6_CAAM
-    #undef  WOLFSSL_IMX6_CAAM_RNG
-    #define WOLFSSL_IMX6_CAAM_RNG
-
-    #undef  WOLFSSL_IMX6_CAAM_BLOB
-    #define WOLFSSL_IMX6_CAAM_BLOB
-
-#if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_XTS)
-    /* large performance gain with HAVE_AES_ECB defined */
-    #undef HAVE_AES_ECB
-    #define HAVE_AES_ECB
-#endif
-#endif
-
-#if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \
-    !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \
-    !defined(XMALLOC_OVERRIDE)
-    #define USE_WOLFSSL_MEMORY
-#endif
-
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS)
-    #undef  KEEP_PEER_CERT
-    #define KEEP_PEER_CERT
-#endif
-
-
-/* stream ciphers except arc4 need 32bit alignment, intel ok without */
-#ifndef XSTREAM_ALIGN
-    #if defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
-        #define NO_XSTREAM_ALIGN
-    #else
-        #define XSTREAM_ALIGN
-    #endif
-#endif
-
-/* write dup cannot be used with secure renegotiation because write dup
- * make write side write only and read side read only */
-#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION)
-    #error "WRITE DUP and SECURE RENEGOTIATION cannot both be on"
-#endif
-
-#ifdef WOLFSSL_SGX
-    #ifdef _MSC_VER
-        #define NO_RC4
-        #ifndef HAVE_FIPS
-            #define WOLFCRYPT_ONLY
-            #define NO_DES3
-            #define NO_SHA
-            #define NO_MD5
-        #else
-            #define TFM_TIMING_RESISTANT
-            #define NO_WOLFSSL_DIR
-            #define NO_WRITEV
-            #define NO_MAIN_DRIVER
-            #define WOLFSSL_LOG_PRINTF
-            #define WOLFSSL_DH_CONST
-        #endif
-    #else
-        #define HAVE_ECC
-        #define NO_WRITEV
-        #define NO_MAIN_DRIVER
-        #define USER_TICKS
-        #define WOLFSSL_LOG_PRINTF
-        #define WOLFSSL_DH_CONST
-    #endif /* _MSC_VER */
-    #if !defined(HAVE_FIPS) && !defined(NO_RSA)
-        #define WC_RSA_BLINDING
-    #endif
-	
-    #define NO_FILESYSTEM
-    #define ECC_TIMING_RESISTANT
-    #define TFM_TIMING_RESISTANT
-    #define SINGLE_THREADED
-    #define NO_ASN_TIME /* can not use headers such as windows.h */
-    #define HAVE_AESGCM
-    #define USE_CERT_BUFFERS_2048
-    #define USE_FAST_MATH
-#endif /* WOLFSSL_SGX */
-
-/* FreeScale MMCAU hardware crypto has 4 byte alignment.
-   However, KSDK fsl_mmcau.h gives API with no alignment
-   requirements (4 byte alignment is managed internally by fsl_mmcau.c) */
-#ifdef FREESCALE_MMCAU
-    #ifdef FREESCALE_MMCAU_CLASSIC
-        #define WOLFSSL_MMCAU_ALIGNMENT 4
-    #else
-        #define WOLFSSL_MMCAU_ALIGNMENT 0
-    #endif
-#endif
-
-/* if using hardware crypto and have alignment requirements, specify the
-   requirement here.  The record header of SSL/TLS will prevent easy alignment.
-   This hint tries to help as much as possible.  */
-#ifndef WOLFSSL_GENERAL_ALIGNMENT
-    #ifdef WOLFSSL_AESNI
-        #define WOLFSSL_GENERAL_ALIGNMENT 16
-    #elif defined(XSTREAM_ALIGN)
-        #define WOLFSSL_GENERAL_ALIGNMENT  4
-    #elif defined(FREESCALE_MMCAU) || defined(FREESCALE_MMCAU_CLASSIC)
-        #define WOLFSSL_GENERAL_ALIGNMENT  WOLFSSL_MMCAU_ALIGNMENT
-    #else
-        #define WOLFSSL_GENERAL_ALIGNMENT  0
-    #endif
-#endif
-
-#if defined(WOLFSSL_GENERAL_ALIGNMENT) && (WOLFSSL_GENERAL_ALIGNMENT > 0)
-    #if defined(_MSC_VER)
-        #define XGEN_ALIGN __declspec(align(WOLFSSL_GENERAL_ALIGNMENT))
-    #elif defined(__GNUC__)
-        #define XGEN_ALIGN __attribute__((aligned(WOLFSSL_GENERAL_ALIGNMENT)))
-    #else
-        #define XGEN_ALIGN
-    #endif
-#else
-    #define XGEN_ALIGN
-#endif
-
-#ifdef HAVE_CRL
-    /* not widely supported yet */
-    #undef NO_SKID
-    #define NO_SKID
-#endif
-
-
-#ifdef __INTEL_COMPILER
-    #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */
-#endif
-
-/* user can specify what curves they want with ECC_USER_CURVES otherwise
- * all curves are on by default for now */
-#ifndef ECC_USER_CURVES
-    #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_ALL_CURVES)
-        #define HAVE_ALL_CURVES
-    #endif
-#endif
-
-/* ECC Configs */
-#ifdef HAVE_ECC
-    /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */
-    #ifndef NO_ECC_SIGN
-        #undef HAVE_ECC_SIGN
-        #define HAVE_ECC_SIGN
-    #endif
-    #ifndef NO_ECC_VERIFY
-        #undef HAVE_ECC_VERIFY
-        #define HAVE_ECC_VERIFY
-    #endif
-    #ifndef NO_ECC_CHECK_KEY
-        #undef HAVE_ECC_CHECK_KEY
-        #define HAVE_ECC_CHECK_KEY
-    #endif
-    #ifndef NO_ECC_DHE
-        #undef HAVE_ECC_DHE
-        #define HAVE_ECC_DHE
-    #endif
-    #ifndef NO_ECC_KEY_IMPORT
-        #undef HAVE_ECC_KEY_IMPORT
-        #define HAVE_ECC_KEY_IMPORT
-    #endif
-    #ifndef NO_ECC_KEY_EXPORT
-        #undef HAVE_ECC_KEY_EXPORT
-        #define HAVE_ECC_KEY_EXPORT
-    #endif
-#endif /* HAVE_ECC */
-
-/* Curve255519 Configs */
-#ifdef HAVE_CURVE25519
-    /* By default enable shared secret, key export and import */
-    #ifndef NO_CURVE25519_SHARED_SECRET
-        #undef HAVE_CURVE25519_SHARED_SECRET
-        #define HAVE_CURVE25519_SHARED_SECRET
-    #endif
-    #ifndef NO_CURVE25519_KEY_EXPORT
-        #undef HAVE_CURVE25519_KEY_EXPORT
-        #define HAVE_CURVE25519_KEY_EXPORT
-    #endif
-    #ifndef NO_CURVE25519_KEY_IMPORT
-        #undef HAVE_CURVE25519_KEY_IMPORT
-        #define HAVE_CURVE25519_KEY_IMPORT
-    #endif
-#endif /* HAVE_CURVE25519 */
-
-/* Ed255519 Configs */
-#ifdef HAVE_ED25519
-    /* By default enable sign, verify, key export and import */
-    #ifndef NO_ED25519_SIGN
-        #undef HAVE_ED25519_SIGN
-        #define HAVE_ED25519_SIGN
-    #endif
-    #ifndef NO_ED25519_VERIFY
-        #undef HAVE_ED25519_VERIFY
-        #define HAVE_ED25519_VERIFY
-    #endif
-    #ifndef NO_ED25519_KEY_EXPORT
-        #undef HAVE_ED25519_KEY_EXPORT
-        #define HAVE_ED25519_KEY_EXPORT
-    #endif
-    #ifndef NO_ED25519_KEY_IMPORT
-        #undef HAVE_ED25519_KEY_IMPORT
-        #define HAVE_ED25519_KEY_IMPORT
-    #endif
-#endif /* HAVE_ED25519 */
-
-/* AES Config */
-#ifndef NO_AES
-    /* By default enable all AES key sizes, decryption and CBC */
-    #ifndef AES_MAX_KEY_SIZE
-        #undef  AES_MAX_KEY_SIZE
-        #define AES_MAX_KEY_SIZE    256
-    #endif
-
-    #ifndef NO_AES_128
-        #undef  WOLFSSL_AES_128
-        #define WOLFSSL_AES_128
-    #endif
-    #if !defined(NO_AES_192) && AES_MAX_KEY_SIZE >= 192
-        #undef  WOLFSSL_AES_192
-        #define WOLFSSL_AES_192
-    #endif
-    #if !defined(NO_AES_256) && AES_MAX_KEY_SIZE >= 256
-        #undef  WOLFSSL_AES_256
-        #define WOLFSSL_AES_256
-    #endif
-    #if !defined(WOLFSSL_AES_128) && defined(HAVE_ECC_ENCRYPT)
-        #warning HAVE_ECC_ENCRYPT uses AES 128 bit keys
-     #endif
-
-    #ifndef NO_AES_DECRYPT
-        #undef  HAVE_AES_DECRYPT
-        #define HAVE_AES_DECRYPT
-    #endif
-    #ifndef NO_AES_CBC
-        #undef  HAVE_AES_CBC
-        #define HAVE_AES_CBC
-    #else
-        #ifndef WOLFCRYPT_ONLY
-            #error "AES CBC is required for TLS and can only be disabled for WOLFCRYPT_ONLY builds"
-        #endif
-    #endif
-    #ifdef WOLFSSL_AES_XTS
-        /* AES-XTS makes calls to AES direct functions */
-        #ifndef WOLFSSL_AES_DIRECT
-        #define WOLFSSL_AES_DIRECT
-        #endif
-    #endif
-    #ifdef WOLFSSL_AES_CFB
-        /* AES-CFB makes calls to AES direct functions */
-        #ifndef WOLFSSL_AES_DIRECT
-        #define WOLFSSL_AES_DIRECT
-        #endif
-    #endif
-#endif
-
-/* if desktop type system and fastmath increase default max bits */
-#ifdef WOLFSSL_X86_64_BUILD
-    #ifdef USE_FAST_MATH
-        #ifndef FP_MAX_BITS
-            #define FP_MAX_BITS 8192
-        #endif
-    #endif
-#endif
-
-/* If using the max strength build, ensure OLD TLS is disabled. */
-#ifdef WOLFSSL_MAX_STRENGTH
-    #undef NO_OLD_TLS
-    #define NO_OLD_TLS
-#endif
-
-
-/* Default AES minimum auth tag sz, allow user to override */
-#ifndef WOLFSSL_MIN_AUTH_TAG_SZ
-    #define WOLFSSL_MIN_AUTH_TAG_SZ 12
-#endif
-
-
-/* sniffer requires:
- * static RSA cipher suites
- * session stats and peak stats
- */
-#ifdef WOLFSSL_SNIFFER
-    #ifndef WOLFSSL_STATIC_RSA
-        #define WOLFSSL_STATIC_RSA
-    #endif
-    #ifndef WOLFSSL_SESSION_STATS
-        #define WOLFSSL_SESSION_STATS
-    #endif
-    #ifndef WOLFSSL_PEAK_SESSIONS
-        #define WOLFSSL_PEAK_SESSIONS
-    #endif
-#endif
-
-/* Decode Public Key extras on by default, user can turn off with
- * WOLFSSL_NO_DECODE_EXTRA */
-#ifndef WOLFSSL_NO_DECODE_EXTRA
-    #ifndef RSA_DECODE_EXTRA
-        #define RSA_DECODE_EXTRA
-    #endif
-    #ifndef ECC_DECODE_EXTRA
-        #define ECC_DECODE_EXTRA
-    #endif
-#endif
-
-/* C Sharp wrapper defines */
-#ifdef HAVE_CSHARP
-    #ifndef WOLFSSL_DTLS
-        #define WOLFSSL_DTLS
-    #endif
-    #undef NO_PSK
-    #undef NO_SHA256
-    #undef NO_DH
-#endif
-
-/* Asynchronous Crypto */
-#ifdef WOLFSSL_ASYNC_CRYPT
-    /* Make sure wolf events are enabled */
-    #undef HAVE_WOLF_EVENT
-    #define HAVE_WOLF_EVENT
-
-    #ifdef WOLFSSL_ASYNC_CRYPT_TEST
-        #define WC_ASYNC_DEV_SIZE 320+24
-    #else
-        #define WC_ASYNC_DEV_SIZE 320
-    #endif
-
-    #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \
-        !defined(WOLFSSL_ASYNC_CRYPT_TEST)
-        #error No async hardware defined with WOLFSSL_ASYNC_CRYPT!
-    #endif
-
-    /* Enable ECC_CACHE_CURVE for ASYNC */
-    #if !defined(ECC_CACHE_CURVE)
-        #define ECC_CACHE_CURVE
-    #endif
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#ifndef WC_ASYNC_DEV_SIZE
-    #define WC_ASYNC_DEV_SIZE 0
-#endif
-
-/* leantls checks */
-#ifdef WOLFSSL_LEANTLS
-    #ifndef HAVE_ECC
-        #error leantls build needs ECC
-    #endif
-#endif /* WOLFSSL_LEANTLS*/
-
-/* restriction with static memory */
-#ifdef WOLFSSL_STATIC_MEMORY
-    #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY)
-         #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY
-    #endif
-    #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT)
-        #error static memory requires fast math please define USE_FAST_MATH
-    #endif
-    #ifdef WOLFSSL_SMALL_STACK
-        #error static memory does not support small stack please undefine
-    #endif
-#endif /* WOLFSSL_STATIC_MEMORY */
-
-#ifdef HAVE_AES_KEYWRAP
-    #ifndef WOLFSSL_AES_DIRECT
-        #error AES key wrap requires AES direct please define WOLFSSL_AES_DIRECT
-    #endif
-#endif
-
-#ifdef HAVE_PKCS7
-    #if defined(NO_AES) && defined(NO_DES3)
-        #error PKCS7 needs either AES or 3DES enabled, please enable one
-    #endif
-    #ifndef HAVE_AES_KEYWRAP
-        #error PKCS7 requires AES key wrap please define HAVE_AES_KEYWRAP
-    #endif
-    #if defined(HAVE_ECC) && !defined(HAVE_X963_KDF)
-        #error PKCS7 requires X963 KDF please define HAVE_X963_KDF
-    #endif
-#endif
-
-#if !defined(WOLFCRYPT_ONLY) && !defined(NO_OLD_TLS) && \
-        (defined(NO_SHA) || defined(NO_MD5))
-    #error old TLS requires MD5 and SHA
-#endif
-
-/* for backwards compatibility */
-#if defined(TEST_IPV6) && !defined(WOLFSSL_IPV6)
-    #define WOLFSSL_IPV6
-#endif
-
-
-/* Place any other flags or defines here */
-
-#if defined(WOLFSSL_MYSQL_COMPATIBLE) && defined(_WIN32) \
-                                      && defined(HAVE_GMTIME_R)
-    #undef HAVE_GMTIME_R /* don't trust macro with windows */
-#endif /* WOLFSSL_MYSQL_COMPATIBLE */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    #define SSL_OP_NO_COMPRESSION    SSL_OP_NO_COMPRESSION
-    #define OPENSSL_NO_ENGINE
-    #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
-    #ifndef OPENSSL_EXTRA
-        #define OPENSSL_EXTRA
-    #endif
-    #ifndef HAVE_SESSION_TICKET
-        #define HAVE_SESSION_TICKET
-    #endif
-    #ifndef HAVE_OCSP
-        #define HAVE_OCSP
-    #endif
-    #ifndef KEEP_OUR_CERT
-        #define KEEP_OUR_CERT
-    #endif
-    #ifndef HAVE_SNI
-        #define HAVE_SNI
-    #endif
-#endif
-
-#if defined(WOLFSSL_NGINX)
-    #define SSL_CTRL_SET_TLSEXT_HOSTNAME
-#endif
-
-/* both CURVE and ED small math should be enabled */
-#ifdef CURVED25519_SMALL
-        #define CURVE25519_SMALL
-        #define ED25519_SMALL
-#endif
-
-
-#ifndef WOLFSSL_ALERT_COUNT_MAX
-    #define WOLFSSL_ALERT_COUNT_MAX 5
-#endif
-
-/* warning for not using harden build options (default with ./configure) */
-#ifndef WC_NO_HARDEN
-    #if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \
-        (defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \
-        (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS))
-
-        #ifndef _MSC_VER
-            #warning "For timing resistance / side-channel attack prevention consider using harden options"
-        #else
-            #pragma message("Warning: For timing resistance / side-channel attack prevention consider using harden options")
-        #endif
-    #endif
-#endif
-
-#if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA)
-    /* added to have compatibility with SHA256() */
-    #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS)
-        #define NO_OLD_SHA_NAMES
-    #endif
-#endif
-
-/* switch for compatibility layer functionality. Has subparts i.e. BIO/X509
- * When opensslextra is enabled all subparts should be turned on. */
-#ifdef OPENSSL_EXTRA
-    #undef  OPENSSL_EXTRA_X509_SMALL
-    #define OPENSSL_EXTRA_X509_SMALL
-#endif /* OPENSSL_EXTRA */
-
-/* support for converting DER to PEM */
-#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || \
-        defined(OPENSSL_EXTRA)
-    #undef  WOLFSSL_DER_TO_PEM
-    #define WOLFSSL_DER_TO_PEM
-#endif
-
-/* keep backwards compatibility enabling encrypted private key */
-#ifndef WOLFSSL_ENCRYPTED_KEYS
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
-        defined(HAVE_WEBSERVER)
-        #define WOLFSSL_ENCRYPTED_KEYS
-    #endif
-#endif
-
-/* support for disabling PEM to DER */
-#if !defined(WOLFSSL_NO_PEM)
-    #undef  WOLFSSL_PEM_TO_DER
-    #define WOLFSSL_PEM_TO_DER
-#endif
-
-/* Parts of the openssl compatibility layer require peer certs */
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    #undef  KEEP_PEER_CERT
-    #define KEEP_PEER_CERT
-#endif
-
-/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/
-#ifdef WOLFSSL_ARMASM
-    #undef  WOLFSSL_NO_HASH_RAW
-    #define WOLFSSL_NO_HASH_RAW
-#endif
-
-#ifdef __cplusplus
-    }   /* extern "C" */
-#endif
-
-#endif
-
--- a/wolfssl/wolfcrypt/sha.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/* sha.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/sha.h
-*/
-
-
-#ifndef WOLF_CRYPT_SHA_H
-#define WOLF_CRYPT_SHA_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_SHA
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-#define wc_Sha             Sha
-#define WC_SHA             SHA
-#define WC_SHA_BLOCK_SIZE  SHA_BLOCK_SIZE
-#define WC_SHA_DIGEST_SIZE SHA_DIGEST_SIZE
-#define WC_SHA_PAD_SIZE    SHA_PAD_SIZE
-
-/* for fips @wc_fips */
-#include <cyassl/ctaocrypt/sha.h>
-#endif
-
-#ifdef FREESCALE_LTC_SHA
-    #include "fsl_ltc.h"
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_MICROCHIP_PIC32MZ
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-#endif
-#ifdef STM32_HASH
-    #include <wolfssl/wolfcrypt/port/st/stm32.h>
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#if !defined(NO_OLD_SHA_NAMES)
-    #define SHA             WC_SHA
-#endif
-
-#ifndef NO_OLD_WC_NAMES
-    #define Sha             wc_Sha
-    #define SHA_BLOCK_SIZE  WC_SHA_BLOCK_SIZE
-    #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-    #define SHA_PAD_SIZE    WC_SHA_PAD_SIZE
-#endif
-
-/* in bytes */
-enum {
-    WC_SHA              =  WC_HASH_TYPE_SHA,
-    WC_SHA_BLOCK_SIZE   = 64,
-    WC_SHA_DIGEST_SIZE  = 20,
-    WC_SHA_PAD_SIZE     = 56
-};
-
-
-#if defined(WOLFSSL_TI_HASH)
-    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
-
-#elif defined(WOLFSSL_IMX6_CAAM)
-    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
-
-#else
-/* Sha digest */
-typedef struct wc_Sha {
-#ifdef FREESCALE_LTC_SHA
-        ltc_hash_ctx_t ctx;
-#elif defined(STM32_HASH)
-        STM32_HASH_Context stmCtx;
-#else
-        word32  buffLen;   /* in bytes          */
-        word32  loLen;     /* length in bytes   */
-        word32  hiLen;     /* length in bytes   */
-        word32  buffer[WC_SHA_BLOCK_SIZE  / sizeof(word32)];
-    #ifdef WOLFSSL_PIC32MZ_HASH
-        word32  digest[PIC32_DIGEST_SIZE / sizeof(word32)];
-    #else
-        word32  digest[WC_SHA_DIGEST_SIZE / sizeof(word32)];
-    #endif
-        void*   heap;
-    #ifdef WOLFSSL_PIC32MZ_HASH
-        hashUpdCache cache; /* cache for updates */
-    #endif
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        WC_ASYNC_DEV asyncDev;
-    #endif /* WOLFSSL_ASYNC_CRYPT */
-#endif
-} wc_Sha;
-
-#endif /* WOLFSSL_TI_HASH */
-
-
-#endif /* HAVE_FIPS */
-
-WOLFSSL_API int wc_InitSha(wc_Sha*);
-WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId);
-WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32);
-WOLFSSL_API int wc_ShaFinalRaw(wc_Sha*, byte*);
-WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*);
-WOLFSSL_API void wc_ShaFree(wc_Sha*);
-
-WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*);
-WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*);
-
-#ifdef WOLFSSL_PIC32MZ_HASH
-WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len);
-#endif
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_SHA */
-#endif /* WOLF_CRYPT_SHA_H */
-
-
--- a/wolfssl/wolfcrypt/sha256.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/* sha256.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/sha256.h
-*/
-
-
-/* code submitted by raphael.huck@efixo.com */
-
-#ifndef WOLF_CRYPT_SHA256_H
-#define WOLF_CRYPT_SHA256_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifndef NO_SHA256
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-    #define wc_Sha256             Sha256
-    #define WC_SHA256             SHA256
-    #define WC_SHA256_BLOCK_SIZE  SHA256_BLOCK_SIZE
-    #define WC_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE
-    #define WC_SHA256_PAD_SIZE    SHA256_PAD_SIZE
-
-    #ifdef WOLFSSL_SHA224
-        #define wc_Sha224             Sha224
-        #define WC_SHA224             SHA224
-        #define WC_SHA224_BLOCK_SIZE  SHA224_BLOCK_SIZE
-        #define WC_SHA224_DIGEST_SIZE SHA224_DIGEST_SIZE
-        #define WC_SHA224_PAD_SIZE    SHA224_PAD_SIZE
-    #endif
-
-    /* for fips @wc_fips */
-    #include <cyassl/ctaocrypt/sha256.h>
-#endif
-
-#ifdef FREESCALE_LTC_SHA
-    #include "fsl_ltc.h"
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_MICROCHIP_PIC32MZ
-    #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
-#endif
-#ifdef STM32_HASH
-    #include <wolfssl/wolfcrypt/port/st/stm32.h>
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#if defined(_MSC_VER)
-    #define SHA256_NOINLINE __declspec(noinline)
-#elif defined(__GNUC__)
-    #define SHA256_NOINLINE __attribute__((noinline))
-#else
-    #define SHA256_NOINLINE
-#endif
-
-#if !defined(NO_OLD_SHA_NAMES)
-    #define SHA256             WC_SHA256
-#endif
-
-#ifndef NO_OLD_WC_NAMES
-    #define Sha256             wc_Sha256
-    #define SHA256_BLOCK_SIZE  WC_SHA256_BLOCK_SIZE
-    #define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-    #define SHA256_PAD_SIZE    WC_SHA256_PAD_SIZE
-#endif
-
-/* in bytes */
-enum {
-    WC_SHA256              =  WC_HASH_TYPE_SHA256,
-    WC_SHA256_BLOCK_SIZE   = 64,
-    WC_SHA256_DIGEST_SIZE  = 32,
-    WC_SHA256_PAD_SIZE     = 56
-};
-
-
-#ifdef WOLFSSL_TI_HASH
-    #include "wolfssl/wolfcrypt/port/ti/ti-hash.h"
-#elif defined(WOLFSSL_IMX6_CAAM)
-    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
-#else
-/* wc_Sha256 digest */
-typedef struct wc_Sha256 {
-#ifdef FREESCALE_LTC_SHA
-    ltc_hash_ctx_t ctx;
-#elif defined(STM32_HASH)
-    STM32_HASH_Context stmCtx;
-#else
-    /* alignment on digest and buffer speeds up ARMv8 crypto operations */
-    ALIGN16 word32  digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
-    ALIGN16 word32  buffer[WC_SHA256_BLOCK_SIZE  / sizeof(word32)];
-    word32  buffLen;   /* in bytes          */
-    word32  loLen;     /* length in bytes   */
-    word32  hiLen;     /* length in bytes   */
-    void*   heap;
-#ifdef USE_INTEL_SPEEDUP
-    const byte* data;
-#endif
-#ifdef WOLFSSL_PIC32MZ_HASH
-    hashUpdCache cache; /* cache for updates */
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    word32* W;
-#endif
-#endif
-} wc_Sha256;
-
-#endif
-
-#endif /* HAVE_FIPS */
-
-WOLFSSL_API int wc_InitSha256(wc_Sha256*);
-WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int);
-WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32);
-WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*);
-WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*);
-WOLFSSL_API void wc_Sha256Free(wc_Sha256*);
-
-WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*);
-WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst);
-
-#ifdef WOLFSSL_PIC32MZ_HASH
-WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32);
-#endif
-
-#ifdef WOLFSSL_SHA224
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifndef NO_OLD_WC_NAMES
-    #define Sha224             wc_Sha224
-    #define SHA224             WC_SHA224
-    #define SHA224_BLOCK_SIZE  WC_SHA224_BLOCK_SIZE
-    #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
-    #define SHA224_PAD_SIZE    WC_SHA224_PAD_SIZE
-#endif
-
-/* in bytes */
-enum {
-    WC_SHA224              =   WC_HASH_TYPE_SHA224,
-    WC_SHA224_BLOCK_SIZE   =   WC_SHA256_BLOCK_SIZE,
-    WC_SHA224_DIGEST_SIZE  =   28,
-    WC_SHA224_PAD_SIZE     =   WC_SHA256_PAD_SIZE
-};
-
-
-typedef wc_Sha256 wc_Sha224;
-#endif /* HAVE_FIPS */
-
-WOLFSSL_API int wc_InitSha224(wc_Sha224*);
-WOLFSSL_API int wc_InitSha224_ex(wc_Sha224*, void*, int);
-WOLFSSL_API int wc_Sha224Update(wc_Sha224*, const byte*, word32);
-WOLFSSL_API int wc_Sha224Final(wc_Sha224*, byte*);
-WOLFSSL_API void wc_Sha224Free(wc_Sha224*);
-
-WOLFSSL_API int wc_Sha224GetHash(wc_Sha224*, byte*);
-WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst);
-
-#endif /* WOLFSSL_SHA224 */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* NO_SHA256 */
-#endif /* WOLF_CRYPT_SHA256_H */
-
-
--- a/wolfssl/wolfcrypt/sha3.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/* sha3.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_SHA3_H
-#define WOLF_CRYPT_SHA3_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#ifdef WOLFSSL_SHA3
-
-#ifdef HAVE_FIPS
-    /* for fips @wc_fips */
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-/* in bytes */
-enum {
-    WC_SHA3_224              = WC_HASH_TYPE_SHA3_224,
-    WC_SHA3_224_DIGEST_SIZE  = 28,
-    WC_SHA3_224_COUNT        = 18,
-
-    WC_SHA3_256              = WC_HASH_TYPE_SHA3_256,
-    WC_SHA3_256_DIGEST_SIZE  = 32,
-    WC_SHA3_256_COUNT        = 17,
-
-    WC_SHA3_384              = WC_HASH_TYPE_SHA3_384,
-    WC_SHA3_384_DIGEST_SIZE  = 48,
-    WC_SHA3_384_COUNT        = 13,
-
-    WC_SHA3_512              = WC_HASH_TYPE_SHA3_512,
-    WC_SHA3_512_DIGEST_SIZE  = 64,
-    WC_SHA3_512_COUNT        =  9,
-
-#ifndef HAVE_SELFTEST
-    /* These values are used for HMAC, not SHA-3 directly.
-     * They come from from FIPS PUB 202. */
-    WC_SHA3_224_BLOCK_SIZE = 144,
-    WC_SHA3_256_BLOCK_SIZE = 136,
-    WC_SHA3_384_BLOCK_SIZE = 104,
-    WC_SHA3_512_BLOCK_SIZE = 72,
-#endif
-};
-
-#ifndef NO_OLD_WC_NAMES
-    #define SHA3_224             WC_SHA3_224
-    #define SHA3_224_DIGEST_SIZE WC_SHA3_224_DIGEST_SIZE
-    #define SHA3_256             WC_SHA3_256
-    #define SHA3_256_DIGEST_SIZE WC_SHA3_256_DIGEST_SIZE
-    #define SHA3_384             WC_SHA3_384
-    #define SHA3_384_DIGEST_SIZE WC_SHA3_384_DIGEST_SIZE
-    #define SHA3_512             WC_SHA3_512
-    #define SHA3_512_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE
-    #define Sha3 wc_Sha3
-#endif
-
-
-#ifdef WOLFSSL_XILINX_CRYPT
-    #include "wolfssl/wolfcrypt/port/xilinx/xil-sha3.h"
-#else
-/* Sha3 digest */
-typedef struct Sha3 {
-    /* State data that is processed for each block. */
-    word64 s[25];
-    /* Unprocessed message data. */
-    byte   t[200];
-    /* Index into unprocessed data to place next message byte. */
-    byte   i;
-
-    void*  heap;
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-} wc_Sha3;
-#endif
-
-
-WOLFSSL_API int wc_InitSha3_224(wc_Sha3*, void*, int);
-WOLFSSL_API int wc_Sha3_224_Update(wc_Sha3*, const byte*, word32);
-WOLFSSL_API int wc_Sha3_224_Final(wc_Sha3*, byte*);
-WOLFSSL_API void wc_Sha3_224_Free(wc_Sha3*);
-WOLFSSL_API int wc_Sha3_224_GetHash(wc_Sha3*, byte*);
-WOLFSSL_API int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst);
-
-WOLFSSL_API int wc_InitSha3_256(wc_Sha3*, void*, int);
-WOLFSSL_API int wc_Sha3_256_Update(wc_Sha3*, const byte*, word32);
-WOLFSSL_API int wc_Sha3_256_Final(wc_Sha3*, byte*);
-WOLFSSL_API void wc_Sha3_256_Free(wc_Sha3*);
-WOLFSSL_API int wc_Sha3_256_GetHash(wc_Sha3*, byte*);
-WOLFSSL_API int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst);
-
-WOLFSSL_API int wc_InitSha3_384(wc_Sha3*, void*, int);
-WOLFSSL_API int wc_Sha3_384_Update(wc_Sha3*, const byte*, word32);
-WOLFSSL_API int wc_Sha3_384_Final(wc_Sha3*, byte*);
-WOLFSSL_API void wc_Sha3_384_Free(wc_Sha3*);
-WOLFSSL_API int wc_Sha3_384_GetHash(wc_Sha3*, byte*);
-WOLFSSL_API int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst);
-
-WOLFSSL_API int wc_InitSha3_512(wc_Sha3*, void*, int);
-WOLFSSL_API int wc_Sha3_512_Update(wc_Sha3*, const byte*, word32);
-WOLFSSL_API int wc_Sha3_512_Final(wc_Sha3*, byte*);
-WOLFSSL_API void wc_Sha3_512_Free(wc_Sha3*);
-WOLFSSL_API int wc_Sha3_512_GetHash(wc_Sha3*, byte*);
-WOLFSSL_API int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_SHA3 */
-#endif /* WOLF_CRYPT_SHA3_H */
-
-
--- a/wolfssl/wolfcrypt/sha512.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/* sha512.h
- *
- * Copyright (C) 2006-2018 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/sha512.h
-*/
-
-
-#ifndef WOLF_CRYPT_SHA512_H
-#define WOLF_CRYPT_SHA512_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
-
-#if defined(HAVE_FIPS) && \
-    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
-    #include <wolfssl/wolfcrypt/fips.h>
-#endif /* HAVE_FIPS_VERSION >= 2 */
-
-#if defined(HAVE_FIPS) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-    #ifdef WOLFSSL_SHA512
-        #define wc_Sha512             Sha512
-        #define WC_SHA512             SHA512
-        #define WC_SHA512_BLOCK_SIZE  SHA512_BLOCK_SIZE
-        #define WC_SHA512_DIGEST_SIZE SHA512_DIGEST_SIZE
-        #define WC_SHA512_PAD_SIZE    SHA512_PAD_SIZE
-    #endif /* WOLFSSL_SHA512 */
-    #ifdef WOLFSSL_SHA384
-        #define wc_Sha384             Sha384
-        #define WC_SHA384             SHA384
-        #define WC_SHA384_BLOCK_SIZE  SHA384_BLOCK_SIZE
-        #define WC_SHA384_DIGEST_SIZE SHA384_DIGEST_SIZE
-        #define WC_SHA384_PAD_SIZE    SHA384_PAD_SIZE
-    #endif /* WOLFSSL_SHA384 */
-
-    #define CYASSL_SHA512
-    #if defined(WOLFSSL_SHA384)
-        #define CYASSL_SHA384
-    #endif
-	/* for fips @wc_fips */
-    #include <cyassl/ctaocrypt/sha512.h>
-#endif
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#ifdef WOLFSSL_ASYNC_CRYPT
-    #include <wolfssl/wolfcrypt/async.h>
-#endif
-
-#if defined(_MSC_VER)
-    #define SHA512_NOINLINE __declspec(noinline)
-#elif defined(__GNUC__)
-    #define SHA512_NOINLINE __attribute__((noinline))
-#else
-    #define SHA512_NOINLINE
-#endif
-
-#ifdef WOLFSSL_SHA512
-
-#if !defined(NO_OLD_SHA_NAMES)
-    #define SHA512             WC_SHA512
-#endif
-
-#if !defined(NO_OLD_WC_NAMES)
-    #define Sha512             wc_Sha512
-    #define SHA512_BLOCK_SIZE  WC_SHA512_BLOCK_SIZE
-    #define SHA512_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
-    #define SHA512_PAD_SIZE    WC_SHA512_PAD_SIZE
-#endif
-
-#endif /* WOLFSSL_SHA512 */
-
-/* in bytes */
-enum {
-#ifdef WOLFSSL_SHA512
-    WC_SHA512              =   WC_HASH_TYPE_SHA512,
-#endif
-    WC_SHA512_BLOCK_SIZE   = 128,
-    WC_SHA512_DIGEST_SIZE  =  64,
-    WC_SHA512_PAD_SIZE     = 112
-};
-
-
-#ifdef WOLFSSL_IMX6_CAAM
-    #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h"
-#else
-/* wc_Sha512 digest */
-typedef struct wc_Sha512 {
-    word64  digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
-    word64  buffer[WC_SHA512_BLOCK_SIZE  / sizeof(word64)];
-    word32  buffLen;   /* in bytes          */
-    word64  loLen;     /* length in bytes   */
-    word64  hiLen;     /* length in bytes   */
-    void*   heap;
-#ifdef USE_INTEL_SPEEDUP
-    const byte* data;
-#endif
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WC_ASYNC_DEV asyncDev;
-#endif /* WOLFSSL_ASYNC_CRYPT */
-#ifdef WOLFSSL_SMALL_STACK_CACHE
-    word64* W;
-#endif
-} wc_Sha512;
-#endif
-
-#endif /* HAVE_FIPS */
-
-#ifdef WOLFSSL_SHA512
-
-WOLFSSL_API int wc_InitSha512(wc_Sha512*);
-WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int);
-WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32);
-WOLFSSL_API int wc_Sha512FinalRaw(wc_Sha512*, byte*);
-WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*);
-WOLFSSL_API void wc_Sha512Free(wc_Sha512*);
-
-WOLFSSL_API int wc_Sha512GetHash(wc_Sha512*, byte*);
-WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst);
-
-#endif /* WOLFSSL_SHA512 */
-
-#if defined(WOLFSSL_SHA384)
-
-/* avoid redefinition of structs */
-#if !defined(HAVE_FIPS) || \
-    (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
-
-#if !defined(NO_OLD_SHA_NAMES)
-    #define SHA384             WC_SHA384
-#endif
-
-#if !defined(NO_OLD_WC_NAMES)
-    #define Sha384             wc_Sha384
-    #define SHA384_BLOCK_SIZE  WC_SHA384_BLOCK_SIZE
-    #define SHA384_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
-    #define SHA384_PAD_SIZE    WC_SHA384_PAD_SIZE
-#endif
-
-/* in bytes */
-enum {
-    WC_SHA384              =   WC_HASH_TYPE_SHA384,
-    WC_SHA384_BLOCK_SIZE   =   WC_SHA512_BLOCK_SIZE,
-    WC_SHA384_DIGEST_SIZE  =   48,
-    WC_SHA384_PAD_SIZE     =   WC_SHA512_PAD_SIZE
-};
-
-
-typedef wc_Sha512 wc_Sha384;
-#endif /* HAVE_FIPS */
-
-WOLFSSL_API int wc_InitSha384(wc_Sha384*);
-WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int);
-WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32);
-WOLFSSL_API int wc_Sha384FinalRaw(wc_Sha384*, byte*);
-WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*);
-WOLFSSL_API void wc_Sha384Free(wc_Sha384*);
-
-WOLFSSL_API int wc_Sha384GetHash(wc_Sha384*, byte*);
-WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst);
-
-#endif /* WOLFSSL_SHA384 */
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
-#endif /* WOLF_CRYPT_SHA512_H */
-
-
--- a/wolfssl/wolfcrypt/signature.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/* signature.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/signature.h
-*/
-
-
-#ifndef WOLF_CRYPT_SIGNATURE_H
-#define WOLF_CRYPT_SIGNATURE_H
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/wolfcrypt/hash.h>
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-enum wc_SignatureType {
-    WC_SIGNATURE_TYPE_NONE = 0,
-    WC_SIGNATURE_TYPE_ECC = 1,
-    WC_SIGNATURE_TYPE_RSA = 2,
-    WC_SIGNATURE_TYPE_RSA_W_ENC = 3, /* Adds DER header via wc_EncodeSignature */
-};
-
-WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type,
-    const void* key, word32 key_len);
-
-WOLFSSL_API int wc_SignatureVerifyHash(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* hash_data, word32 hash_len,
-    const byte* sig, word32 sig_len,
-    const void* key, word32 key_len);
-
-WOLFSSL_API int wc_SignatureVerify(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* data, word32 data_len,
-    const byte* sig, word32 sig_len,
-    const void* key, word32 key_len);
-
-WOLFSSL_API int wc_SignatureGenerateHash(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* hash_data, word32 hash_len,
-    byte* sig, word32 *sig_len,
-    const void* key, word32 key_len, WC_RNG* rng);
-WOLFSSL_API int wc_SignatureGenerate(
-    enum wc_HashType hash_type, enum wc_SignatureType sig_type,
-    const byte* data, word32 data_len,
-    byte* sig, word32 *sig_len,
-    const void* key, word32 key_len,
-    WC_RNG* rng);
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_SIGNATURE_H */
-
--- a/wolfssl/wolfcrypt/sp.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* sp.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_SP_H
-#define WOLF_CRYPT_SP_H
-
-#include <wolfssl/wolfcrypt/types.h>
-
-#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
-                                    defined(WOLFSSL_HAVE_SP_ECC)
-
-#include <stdint.h>
-
-#include <wolfssl/wolfcrypt/integer.h>
-#include <wolfssl/wolfcrypt/sp_int.h>
-
-#include <wolfssl/wolfcrypt/ecc.h>
-
-#if defined(_MSC_VER)
-    #define SP_NOINLINE __declspec(noinline)
-#elif defined(__GNUC__)
-    #define SP_NOINLINE __attribute__((noinline))
-#else
-    #define 5P_NOINLINE
-#endif
-
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_HAVE_SP_RSA
-
-WOLFSSL_LOCAL int sp_RsaPublic_2048(const byte* in, word32 inLen,
-    mp_int* em, mp_int* mm, byte* out, word32* outLen);
-WOLFSSL_LOCAL int sp_RsaPrivate_2048(const byte* in, word32 inLen,
-    mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim,
-    mp_int* mm, byte* out, word32* outLen);
-
-WOLFSSL_LOCAL int sp_RsaPublic_3072(const byte* in, word32 inLen,
-    mp_int* em, mp_int* mm, byte* out, word32* outLen);
-WOLFSSL_LOCAL int sp_RsaPrivate_3072(const byte* in, word32 inLen,
-    mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim,
-    mp_int* mm, byte* out, word32* outLen);
-
-#endif /* WOLFSSL_HAVE_SP_RSA */
-
-#ifdef WOLFSSL_HAVE_SP_DH
-
-WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod,
-    mp_int* res);
-WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod,
-    mp_int* res);
-
-WOLFSSL_LOCAL int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen);
-WOLFSSL_LOCAL int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen,
-    mp_int* mod, byte* out, word32* outLen);
-
-#endif /* WOLFSSL_HAVE_SP_DH */
-
-#ifdef WOLFSSL_HAVE_SP_ECC
-
-int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* rm, int map,
-                      void* heap);
-int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* rm, int map, void* heap);
-
-int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap);
-int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
-                          word32* outlen, void* heap);
-int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
-                    mp_int* rm, mp_int* sm, void* heap);
-int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY,
-                      mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap);
-int sp_ecc_is_point_256(mp_int* pX, mp_int* pY);
-int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap);
-int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* qX, mp_int* qY, mp_int* qZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ);
-int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
-                              mp_int* rX, mp_int* rY, mp_int* rZ);
-int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ);
-int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym);
-
-#endif /*ifdef WOLFSSL_HAVE_SP_ECC */
-
-
-#ifdef __cplusplus
-    } /* extern "C" */
-#endif
-
-#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */
-
-#endif /* WOLF_CRYPT_SP_H */
-
-
--- a/wolfssl/wolfcrypt/sp_int.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/* sp_int.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-#ifndef WOLF_CRYPT_SP_INT_H
-#define WOLF_CRYPT_SP_INT_H
-
-#include <stdint.h>
-#include <limits.h>
-
-#ifdef WOLFSSL_SP_X86_64_ASM
-    #define SP_WORD_SIZE 64
-
-    #define HAVE_INTEL_AVX1
-    #define HAVE_INTEL_AVX2
-#elif defined(WOLFSSL_SP_ARM64_ASM)
-    #define SP_WORD_SIZE 64
-#elif defined(WOLFSSL_SP_ARM32_ASM)
-    #define SP_WORD_SIZE 32
-#endif
-
-#ifndef SP_WORD_SIZE
-    #if defined(NO_64BIT) || !defined(HAVE___UINT128_T)
-        #define SP_WORD_SIZE 32
-    #else
-        #define SP_WORD_SIZE 64
-    #endif
-#endif
-
-#ifndef WOLFSSL_SP_ASM
-  #if SP_WORD_SIZE == 32
-    typedef int32_t sp_digit;
-    typedef uint32_t sp_int_digit;
-  #elif SP_WORD_SIZE == 64
-    typedef int64_t sp_digit;
-    typedef uint64_t sp_int_digit;
-    typedef unsigned long uint128_t __attribute__ ((mode(TI)));
-    typedef long int128_t __attribute__ ((mode(TI)));
-  #else
-    #error Word size not defined
-  #endif
-#else
-  #if SP_WORD_SIZE == 32
-    typedef uint32_t sp_digit;
-    typedef uint32_t sp_int_digit;
-  #elif SP_WORD_SIZE == 64
-    typedef uint64_t sp_digit;
-    typedef uint64_t sp_int_digit;
-    typedef unsigned long uint128_t __attribute__ ((mode(TI)));
-    typedef long int128_t __attribute__ ((mode(TI)));
-  #else
-    #error Word size not defined
-  #endif
-#endif
-
-#ifdef WOLFSSL_SP_MATH
-#include <wolfssl/wolfcrypt/random.h>
-
-#ifndef MIN
-   #define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-#ifndef MAX
-   #define MAX(x,y) ((x)>(y)?(x):(y))
-#endif
-
-#ifdef WOLFSSL_PUBLIC_MP
-    #define MP_API   WOLFSSL_API
-#else
-    #define MP_API   WOLFSSL_LOCAL
-#endif
-
-#if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH)
-    #if !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512)
-        #define SP_INT_DIGITS        ((512 + SP_WORD_SIZE) / SP_WORD_SIZE)
-    #else
-        #define SP_INT_DIGITS        ((256 + SP_WORD_SIZE) / SP_WORD_SIZE)
-    #endif
-#elif !defined(WOLFSSL_SP_NO_3072)
-    #define SP_INT_DIGITS        ((2048 + SP_WORD_SIZE) / SP_WORD_SIZE)
-#else
-    #define SP_INT_DIGITS        ((3072 + SP_WORD_SIZE) / SP_WORD_SIZE)
-#endif
-
-#define sp_isodd(a) (a->used != 0 && (a->dp[0] & 1))
-
-typedef struct sp_int {
-    sp_int_digit dp[SP_INT_DIGITS];
-    int size;
-    int used;
-} sp_int;
-
-
-MP_API int sp_init(sp_int* a);
-MP_API int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d,
-                         sp_int* e, sp_int* f);
-MP_API void sp_clear(sp_int* a);
-MP_API int sp_unsigned_bin_size(sp_int* a);
-MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz);
-MP_API int sp_read_radix(sp_int* a, const char* in, int radix);
-MP_API int sp_cmp(sp_int* a, sp_int* b);
-MP_API int sp_count_bits(sp_int* a);
-MP_API int sp_leading_bit(sp_int* a);
-MP_API int sp_to_unsigned_bin(sp_int* a, byte* in);
-MP_API void sp_forcezero(sp_int* a);
-MP_API int sp_copy(sp_int* a, sp_int* b);
-MP_API int sp_set(sp_int* a, sp_int_digit d);
-MP_API int sp_iszero(sp_int* a);
-MP_API void sp_clamp(sp_int* a);
-MP_API int sp_grow(sp_int* a, int l);
-MP_API int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r);
-MP_API int sp_cmp_d(sp_int* a, sp_int_digit d);
-MP_API int sp_mod(sp_int* a, sp_int* m, sp_int* r);
-MP_API void sp_zero(sp_int* a);
-MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r);
-MP_API int sp_lshd(sp_int* a, int s);
-MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r);
-MP_API int sp_set_int(sp_int* a, unsigned long b);
-
-typedef sp_int mp_int;
-typedef sp_digit mp_digit;
-
-#define MP_OKAY    0
-#define MP_NO      0
-#define MP_YES     1
-
-#define MP_RADIX_HEX     16
-
-#define MP_GT    1
-#define MP_EQ    0
-#define MP_LT    -1
-
-#define MP_MEM   -2
-#define MP_VAL   -3
-
-#define DIGIT_BIT  SP_WORD_SIZE
-
-#define CheckFastMathSettings() 1
-
-#define mp_free(a)
-
-#define mp_init                 sp_init
-#define mp_init_multi           sp_init_multi
-#define mp_clear                sp_clear
-#define mp_read_unsigned_bin    sp_read_unsigned_bin
-#define mp_unsigned_bin_size    sp_unsigned_bin_size
-#define mp_read_radix           sp_read_radix
-#define mp_cmp                  sp_cmp
-#define mp_count_bits           sp_count_bits
-#define mp_leading_bit          sp_leading_bit
-#define mp_to_unsigned_bin      sp_to_unsigned_bin
-#define mp_forcezero            sp_forcezero
-#define mp_copy                 sp_copy
-#define mp_set                  sp_set
-#define mp_iszero               sp_iszero
-#define mp_clamp                sp_clamp
-#define mp_grow                 sp_grow
-#define mp_sub_d                sp_sub_d
-#define mp_cmp_d                sp_cmp_d
-#define mp_mod                  sp_mod
-#define mp_zero                 sp_zero
-#define mp_add_d                sp_add_d
-#define mp_lshd                 sp_lshd
-#define mp_add                  sp_add
-#define mp_isodd                sp_isodd
-#define mp_set_int              sp_set_int
-
-#define MP_INT_DEFINED
-
-#include <wolfssl/wolfcrypt/wolfmath.h>
-#endif
-
-#endif /* WOLF_CRYPT_SP_H */
-
-
--- a/wolfssl/wolfcrypt/srp.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/* srp.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/srp.h
-*/
-
-#ifdef WOLFCRYPT_HAVE_SRP
-
-#ifndef WOLFCRYPT_SRP_H
-#define WOLFCRYPT_SRP_H
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/wolfcrypt/sha.h>
-#include <wolfssl/wolfcrypt/sha256.h>
-#include <wolfssl/wolfcrypt/sha512.h>
-#include <wolfssl/wolfcrypt/integer.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Select the largest available hash for the buffer size. */
-#if defined(WOLFSSL_SHA512)
-    #define SRP_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
-#elif defined(WOLFSSL_SHA384)
-    #define SRP_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
-#elif !defined(NO_SHA256)
-    #define SRP_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
-#elif !defined(NO_SHA)
-    #define SRP_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE
-#else
-    #error "You have to have some kind of SHA hash if you want to use SRP."
-#endif
-
-/* Set the minimum number of bits acceptable in an SRP modulus */
-#define SRP_MODULUS_MIN_BITS 512
-
-/* Set the minimum number of bits acceptable for private keys (RFC 5054) */
-#define SRP_PRIVATE_KEY_MIN_BITS 256
-
-/* salt size for SRP password */
-#define SRP_SALT_SIZE  16
-
-/**
- * SRP side, client or server.
- */
-typedef enum {
-    SRP_CLIENT_SIDE  = 0,
-    SRP_SERVER_SIDE  = 1,
-} SrpSide;
-
-/**
- * SRP hash type, SHA[1|256|384|512].
- */
-typedef enum {
-        SRP_TYPE_SHA    = 1,
-        SRP_TYPE_SHA256 = 2,
-        SRP_TYPE_SHA384 = 3,
-        SRP_TYPE_SHA512 = 4,
-} SrpType;
-
-
-/**
- * SRP hash struct.
- */
-typedef struct {
-    byte type;
-    union {
-        #ifndef NO_SHA
-            wc_Sha sha;
-        #endif
-        #ifndef NO_SHA256
-            wc_Sha256 sha256;
-        #endif
-        #ifdef WOLFSSL_SHA384
-            wc_Sha384 sha384;
-        #endif
-        #ifdef WOLFSSL_SHA512
-            wc_Sha512 sha512;
-        #endif
-    } data;
-} SrpHash;
-
-typedef struct Srp {
-    SrpSide side;                   /**< Client or Server, @see SrpSide.      */
-    SrpType type;                   /**< Hash type, @see SrpType.             */
-    byte*   user;                   /**< Username, login.                     */
-    word32  userSz;                 /**< Username length.                     */
-    byte*   salt;                   /**< Small salt.                          */
-    word32  saltSz;                 /**< Salt length.                         */
-    mp_int  N;                      /**< Modulus. N = 2q+1, [q, N] are primes.*/
-    mp_int  g;                      /**< Generator. A generator modulo N.     */
-    byte    k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameter. k = H(N, g)   */
-    mp_int  auth;                   /**< Client: x = H(salt + H(user:pswd))   */
-                                    /**< Server: v = g ^ x % N                */
-    mp_int  priv;                   /**< Private ephemeral value.             */
-    SrpHash client_proof;           /**< Client proof. Sent to the Server.    */
-    SrpHash server_proof;           /**< Server proof. Sent to the Client.    */
-    byte*   key;                    /**< Session key.                         */
-    word32  keySz;                  /**< Session key length.                  */
-    int (*keyGenFunc_cb) (struct Srp* srp, byte* secret, word32 size);
-        /**< Function responsible for generating the session key.             */
-        /**< It MUST use XMALLOC with type DYNAMIC_TYPE_SRP to allocate the   */
-        /**< key buffer for this structure and set keySz to the buffer size.  */
-        /**< The default function used by this implementation is a modified   */
-        /**< version of t_mgf1 that uses the proper hash function according   */
-        /**< to srp->type.                                                    */
-    void*   heap;                   /**< heap hint pointer                    */
-} Srp;
-
-/**
- * Initializes the Srp struct for usage.
- *
- * @param[out] srp   the Srp structure to be initialized.
- * @param[in]  type  the hash type to be used.
- * @param[in]  side  the side of the communication.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpInit(Srp* srp, SrpType type, SrpSide side);
-
-/**
- * Releases the Srp struct resources after usage.
- *
- * @param[in,out] srp    the Srp structure to be terminated.
- */
-WOLFSSL_API void wc_SrpTerm(Srp* srp);
-
-/**
- * Sets the username.
- *
- * This function MUST be called after wc_SrpInit.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[in]     username  the buffer containing the username.
- * @param[in]     size      the username size in bytes
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size);
-
-
-/**
- * Sets the srp parameters based on the username.
- *
- * This function MUST be called after wc_SrpSetUsername.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[in]     N         the Modulus. N = 2q+1, [q, N] are primes.
- * @param[in]     nSz       the N size in bytes.
- * @param[in]     g         the Generator modulo N.
- * @param[in]     gSz       the g size in bytes
- * @param[in]     salt      a small random salt. Specific for each username.
- * @param[in]     saltSz    the salt size in bytes
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N,    word32 nSz,
-                                          const byte* g,    word32 gSz,
-                                          const byte* salt, word32 saltSz);
-
-/**
- * Sets the password.
- *
- * Setting the password does not persists the clear password data in the
- * srp structure. The client calculates x = H(salt + H(user:pswd)) and stores
- * it in the auth field.
- *
- * This function MUST be called after wc_SrpSetParams and is CLIENT SIDE ONLY.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[in]     password  the buffer containing the password.
- * @param[in]     size      the password size in bytes.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size);
-
-/**
- * Sets the verifier.
- *
- * This function MUST be called after wc_SrpSetParams and is SERVER SIDE ONLY.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[in]     verifier  the buffer containing the verifier.
- * @param[in]     size      the verifier size in bytes.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size);
-
-/**
- * Gets the verifier.
- *
- * The client calculates the verifier with v = g ^ x % N.
- * This function MAY be called after wc_SrpSetPassword and is CLIENT SIDE ONLY.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[out]    verifier  the buffer to write the verifier.
- * @param[in,out] size      the buffer size in bytes. Will be updated with the
- *                          verifier size.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size);
-
-/**
- * Sets the private ephemeral value.
- *
- * The private ephemeral value is known as:
- *   a at the client side. a = random()
- *   b at the server side. b = random()
- * This function is handy for unit test cases or if the developer wants to use
- * an external random source to set the ephemeral value.
- * This function MAY be called before wc_SrpGetPublic.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[in]     priv      the ephemeral value.
- * @param[in]     size      the private size in bytes.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size);
-
-/**
- * Gets the public ephemeral value.
- *
- * The public ephemeral value is known as:
- *   A at the client side. A = g ^ a % N
- *   B at the server side. B = (k * v + (g ˆ b % N)) % N
- * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier.
- *
- * @param[in,out] srp       the Srp structure.
- * @param[out]    pub       the buffer to write the public ephemeral value.
- * @param[in,out] size      the the buffer size in bytes. Will be updated with
- *                          the ephemeral value size.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size);
-
-
-/**
- * Computes the session key.
- *
- * The key can be accessed at srp->key after success.
- *
- * @param[in,out] srp               the Srp structure.
- * @param[in]     clientPubKey      the client's public ephemeral value.
- * @param[in]     clientPubKeySz    the client's public ephemeral value size.
- * @param[in]     serverPubKey      the server's public ephemeral value.
- * @param[in]     serverPubKeySz    the server's public ephemeral value size.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpComputeKey(Srp* srp,
-                                 byte* clientPubKey, word32 clientPubKeySz,
-                                 byte* serverPubKey, word32 serverPubKeySz);
-
-/**
- * Gets the proof.
- *
- * This function MUST be called after wc_SrpComputeKey.
- *
- * @param[in,out] srp   the Srp structure.
- * @param[out]    proof the buffer to write the proof.
- * @param[in,out] size  the buffer size in bytes. Will be updated with the
- *                          proof size.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size);
-
-/**
- * Verifies the peers proof.
- *
- * This function MUST be called before wc_SrpGetSessionKey.
- *
- * @param[in,out] srp   the Srp structure.
- * @param[in]     proof the peers proof.
- * @param[in]     size  the proof size in bytes.
- *
- * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
- */
-WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size);
-
-#ifdef __cplusplus
-   } /* extern "C" */
-#endif
-
-#endif /* WOLFCRYPT_SRP_H */
-#endif /* WOLFCRYPT_HAVE_SRP */
-
--- a/wolfssl/wolfcrypt/tfm.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,762 +0,0 @@
-/* tfm.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-/*
- * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca,
- * http://math.libtomcrypt.com
- */
-
-
-/**
- *  Edited by Moises Guimaraes (moises.guimaraes@phoebus.com.br)
- *  to fit CyaSSL's needs.
- */
-
-/*!
-    \file wolfssl/wolfcrypt/tfm.h
-*/
-
-#ifndef WOLF_CRYPT_TFM_H
-#define WOLF_CRYPT_TFM_H
-
-#include <wolfssl/wolfcrypt/types.h>
-#ifndef CHAR_BIT
-    #include <limits.h>
-#endif
-
-#include <wolfssl/wolfcrypt/random.h>
-
-/* wolf big int and common functions */
-#include <wolfssl/wolfcrypt/wolfmath.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifdef WOLFSSL_PUBLIC_MP
-    #define MP_API   WOLFSSL_API
-#else
-    #define MP_API
-#endif
-
-#ifndef MIN
-   #define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-#ifndef MAX
-   #define MAX(x,y) ((x)>(y)?(x):(y))
-#endif
-
-#ifdef WOLFSSL_NO_ASM
-   #undef  TFM_NO_ASM
-   #define TFM_NO_ASM
-#endif
-
-#ifndef NO_64BIT
-/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
-#if defined(__x86_64__)
-   #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
-       #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
-   #endif
-   #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
-      #define TFM_X86_64
-   #endif
-#endif
-#if defined(TFM_X86_64)
-    #if !defined(FP_64BIT)
-       #define FP_64BIT
-    #endif
-#endif
-/* use 64-bit digit even if not using asm on x86_64 */
-#if defined(__x86_64__) && !defined(FP_64BIT)
-    #define FP_64BIT
-#endif
-/* if intel compiler doesn't provide 128 bit type don't turn on 64bit */
-#if defined(FP_64BIT) && defined(__INTEL_COMPILER) && !defined(HAVE___UINT128_T)
-    #undef FP_64BIT
-    #undef TFM_X86_64
-#endif
-#endif /* NO_64BIT */
-
-/* try to detect x86-32 */
-#if defined(__i386__) && !defined(TFM_SSE2)
-   #if defined(TFM_X86_64) || defined(TFM_ARM)
-       #error x86-32 detected, x86-64/ARM optimizations are not valid!
-   #endif
-   #if !defined(TFM_X86) && !defined(TFM_NO_ASM)
-      #define TFM_X86
-   #endif
-#endif
-
-/* make sure we're 32-bit for x86-32/sse/arm/ppc32 */
-#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT)
-   #warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining)
-   #undef FP_64BIT
-#endif
-
-/* multi asms? */
-#ifdef TFM_X86
-   #define TFM_ASM
-#endif
-#ifdef TFM_X86_64
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-#ifdef TFM_SSE2
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-#ifdef TFM_ARM
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-#ifdef TFM_PPC32
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-#ifdef TFM_PPC64
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-#ifdef TFM_AVR32
-   #ifdef TFM_ASM
-      #error TFM_ASM already defined!
-   #endif
-   #define TFM_ASM
-#endif
-
-/* we want no asm? */
-#ifdef TFM_NO_ASM
-   #undef TFM_X86
-   #undef TFM_X86_64
-   #undef TFM_SSE2
-   #undef TFM_ARM
-   #undef TFM_PPC32
-   #undef TFM_PPC64
-   #undef TFM_AVR32
-   #undef TFM_ASM
-#endif
-
-/* ECC helpers */
-#ifdef TFM_ECC192
-   #ifdef FP_64BIT
-       #define TFM_MUL3
-       #define TFM_SQR3
-   #else
-       #define TFM_MUL6
-       #define TFM_SQR6
-   #endif
-#endif
-
-#ifdef TFM_ECC224
-   #ifdef FP_64BIT
-       #define TFM_MUL4
-       #define TFM_SQR4
-   #else
-       #define TFM_MUL7
-       #define TFM_SQR7
-   #endif
-#endif
-
-#ifdef TFM_ECC256
-   #ifdef FP_64BIT
-       #define TFM_MUL4
-       #define TFM_SQR4
-   #else
-       #define TFM_MUL8
-       #define TFM_SQR8
-   #endif
-#endif
-
-#ifdef TFM_ECC384
-   #ifdef FP_64BIT
-       #define TFM_MUL6
-       #define TFM_SQR6
-   #else
-       #define TFM_MUL12
-       #define TFM_SQR12
-   #endif
-#endif
-
-#ifdef TFM_ECC521
-   #ifdef FP_64BIT
-       #define TFM_MUL9
-       #define TFM_SQR9
-   #else
-       #define TFM_MUL17
-       #define TFM_SQR17
-   #endif
-#endif
-
-
-/* allow user to define on fp_digit, fp_word types */
-#ifndef WOLFSSL_BIGINT_TYPES
-
-/* some default configurations.
- */
-#if defined(FP_64BIT)
-   /* for GCC only on supported platforms */
-   typedef unsigned long long fp_digit;   /* 64bit, 128 uses mode(TI) below */
-   #define SIZEOF_FP_DIGIT 8
-   typedef unsigned long      fp_word __attribute__ ((mode(TI)));
-#else
-
-   #ifndef NO_64BIT
-      #if defined(_MSC_VER) || defined(__BORLANDC__)
-         typedef unsigned __int64   ulong64;
-      #else
-         typedef unsigned long long ulong64;
-      #endif
-      typedef unsigned int       fp_digit;
-      #define SIZEOF_FP_DIGIT 4
-      typedef ulong64            fp_word;
-      #define FP_32BIT
-   #else
-      /* some procs like coldfire prefer not to place multiply into 64bit type
-         even though it exists */
-      typedef unsigned short     fp_digit;
-      #define SIZEOF_FP_DIGIT 2
-      typedef unsigned int       fp_word;
-   #endif
-#endif
-
-#endif /* WOLFSSL_BIGINT_TYPES */
-
-/* # of digits this is */
-#define DIGIT_BIT   ((CHAR_BIT) * SIZEOF_FP_DIGIT)
-
-/* Max size of any number in bits.  Basically the largest size you will be
- * multiplying should be half [or smaller] of FP_MAX_SIZE-four_digit
- *
- * It defaults to 4096-bits [allowing multiplications up to 2048x2048 bits ]
- */
-
-
-#ifndef FP_MAX_BITS
-    #define FP_MAX_BITS           4096
-#endif
-#define FP_MAX_SIZE           (FP_MAX_BITS+(8*DIGIT_BIT))
-
-/* will this lib work? */
-#if (CHAR_BIT & 7)
-   #error CHAR_BIT must be a multiple of eight.
-#endif
-#if FP_MAX_BITS % CHAR_BIT
-   #error FP_MAX_BITS must be a multiple of CHAR_BIT
-#endif
-
-#define FP_MASK    (fp_digit)(-1)
-#define FP_DIGIT_MAX FP_MASK
-#define FP_SIZE    (FP_MAX_SIZE/DIGIT_BIT)
-
-/* signs */
-#define FP_ZPOS     0
-#define FP_NEG      1
-
-/* return codes */
-#define FP_OKAY      0
-#define FP_VAL      -1
-#define FP_MEM      -2
-#define FP_NOT_INF	-3
-
-/* equalities */
-#define FP_LT        -1   /* less than */
-#define FP_EQ         0   /* equal to */
-#define FP_GT         1   /* greater than */
-
-/* replies */
-#define FP_YES        1   /* yes response */
-#define FP_NO         0   /* no response */
-
-#ifdef HAVE_WOLF_BIGINT
-    struct WC_BIGINT;
-#endif
-
-/* a FP type */
-typedef struct fp_int {
-    int      used;
-    int      sign;
-#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT)
-    int      size;
-#endif
-    fp_digit dp[FP_SIZE];
-
-#ifdef HAVE_WOLF_BIGINT
-    struct WC_BIGINT raw; /* unsigned binary (big endian) */
-#endif
-} fp_int;
-
-/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */
-#ifndef TFM_ALREADY_SET
-
-/* do we want the large set of small multiplications ?
-   Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC
-   Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-)
- */
-/* need to refactor the function */
-/*#define TFM_SMALL_SET */
-
-/* do we want huge code
-   Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA)
-   Less important on 64-bit machines as 32 digits == 2048 bits
- */
-#if 0
-#define TFM_MUL3
-#define TFM_MUL4
-#define TFM_MUL6
-#define TFM_MUL7
-#define TFM_MUL8
-#define TFM_MUL9
-#define TFM_MUL12
-#define TFM_MUL17
-#endif
-#ifdef TFM_HUGE_SET
-#define TFM_MUL20
-#define TFM_MUL24
-#define TFM_MUL28
-#define TFM_MUL32
-#if (FP_MAX_BITS >= 6144) && defined(FP_64BIT)
-    #define TFM_MUL48
-#endif
-#if (FP_MAX_BITS >= 8192) && defined(FP_64BIT)
-    #define TFM_MUL64
-#endif
-#endif
-
-#if 0
-#define TFM_SQR3
-#define TFM_SQR4
-#define TFM_SQR6
-#define TFM_SQR7
-#define TFM_SQR8
-#define TFM_SQR9
-#define TFM_SQR12
-#define TFM_SQR17
-#endif
-#ifdef TFM_HUGE_SET
-#define TFM_SQR20
-#define TFM_SQR24
-#define TFM_SQR28
-#define TFM_SQR32
-#define TFM_SQR48
-#define TFM_SQR64
-#endif
-
-/* Optional math checks (enable WOLFSSL_DEBUG_MATH to print info) */
-/* #define TFM_CHECK */
-
-/* Is the target a P4 Prescott
- */
-/* #define TFM_PRESCOTT */
-
-/* Do we want timing resistant fp_exptmod() ?
- * This makes it slower but also timing invariant with respect to the exponent
- */
-/* #define TFM_TIMING_RESISTANT */
-
-#endif /* TFM_ALREADY_SET */
-
-/* functions */
-
-/* returns a TFM ident string useful for debugging... */
-/*const char *fp_ident(void);*/
-
-/* initialize [or zero] an fp int */
-void fp_init(fp_int *a);
-MP_API void fp_zero(fp_int *a);
-MP_API void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */
-MP_API void fp_forcezero (fp_int * a);
-MP_API void fp_free(fp_int* a);
-
-/* zero/even/odd ? */
-#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO)
-#define fp_isone(a) \
-    ((((a)->used == 1) && ((a)->dp[0] == 1)) ? FP_YES : FP_NO)
-#define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO)
-#define fp_isodd(a)  (((a)->used > 0  && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
-#define fp_isneg(a)  (((a)->sign != 0) ? FP_YES : FP_NO)
-
-/* set to a small digit */
-void fp_set(fp_int *a, fp_digit b);
-void fp_set_int(fp_int *a, unsigned long b);
-
-/* check if a bit is set */
-int fp_is_bit_set(fp_int *a, fp_digit b);
-/* set the b bit to 1 */
-int fp_set_bit (fp_int * a, fp_digit b);
-
-/* copy from a to b */
-void fp_copy(fp_int *a, fp_int *b);
-void fp_init_copy(fp_int *a, fp_int *b);
-
-/* clamp digits */
-#define fp_clamp(a)   { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; }
-#define mp_clamp(a)   fp_clamp(a)
-#define mp_grow(a,s)  MP_OKAY
-
-/* negate and absolute */
-#define fp_neg(a, b)  { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); }
-#define fp_abs(a, b)  { fp_copy(a, b); (b)->sign  = 0; }
-
-/* right shift x digits */
-void fp_rshd(fp_int *a, int x);
-
-/* right shift x bits */
-void fp_rshb(fp_int *a, int x);
-
-/* left shift x digits */
-void fp_lshd(fp_int *a, int x);
-
-/* signed comparison */
-int fp_cmp(fp_int *a, fp_int *b);
-
-/* unsigned comparison */
-int fp_cmp_mag(fp_int *a, fp_int *b);
-
-/* power of 2 operations */
-void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
-void fp_mod_2d(fp_int *a, int b, fp_int *c);
-void fp_mul_2d(fp_int *a, int b, fp_int *c);
-void fp_2expt (fp_int *a, int b);
-void fp_mul_2(fp_int *a, fp_int *c);
-void fp_div_2(fp_int *a, fp_int *c);
-
-/* Counts the number of lsbs which are zero before the first zero bit */
-int fp_cnt_lsb(fp_int *a);
-
-/* c = a + b */
-void fp_add(fp_int *a, fp_int *b, fp_int *c);
-
-/* c = a - b */
-void fp_sub(fp_int *a, fp_int *b, fp_int *c);
-
-/* c = a * b */
-void fp_mul(fp_int *a, fp_int *b, fp_int *c);
-
-/* b = a*a  */
-void fp_sqr(fp_int *a, fp_int *b);
-
-/* a/b => cb + d == a */
-int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
-
-/* c = a mod b, 0 <= c < b  */
-int fp_mod(fp_int *a, fp_int *b, fp_int *c);
-
-/* compare against a single digit */
-int fp_cmp_d(fp_int *a, fp_digit b);
-
-/* c = a + b */
-void fp_add_d(fp_int *a, fp_digit b, fp_int *c);
-
-/* c = a - b */
-void fp_sub_d(fp_int *a, fp_digit b, fp_int *c);
-
-/* c = a * b */
-void fp_mul_d(fp_int *a, fp_digit b, fp_int *c);
-
-/* a/b => cb + d == a */
-/*int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);*/
-
-/* c = a mod b, 0 <= c < b  */
-/*int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c);*/
-
-/* ---> number theory <--- */
-/* d = a + b (mod c) */
-/*int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/
-
-/* d = a - b (mod c) */
-/*int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/
-
-/* d = a * b (mod c) */
-int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
-
-/* d = a - b (mod c) */
-int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
-
-/* d = a + b (mod c) */
-int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
-
-/* c = a * a (mod b) */
-int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c);
-
-/* c = 1/a (mod b) */
-int fp_invmod(fp_int *a, fp_int *b, fp_int *c);
-
-/* c = (a, b) */
-/*void fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/
-
-/* c = [a, b] */
-/*void fp_lcm(fp_int *a, fp_int *b, fp_int *c);*/
-
-/* setups the montgomery reduction */
-int fp_montgomery_setup(fp_int *a, fp_digit *mp);
-
-/* computes a = B**n mod b without division or multiplication useful for
- * normalizing numbers in a Montgomery system.
- */
-void fp_montgomery_calc_normalization(fp_int *a, fp_int *b);
-
-/* computes x/R == x (mod N) via Montgomery Reduction */
-void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
-
-/* d = a**b (mod c) */
-int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
-
-/* primality stuff */
-
-/* perform a Miller-Rabin test of a to the base b and store result in "result" */
-/*void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);*/
-
-#define FP_PRIME_SIZE      256
-/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime  */
-/*int fp_isprime(fp_int *a);*/
-/* extended version of fp_isprime, do 't' Miller-Rabins instead of only 8 */
-/*int fp_isprime_ex(fp_int *a, int t);*/
-
-/* Primality generation flags */
-/*#define TFM_PRIME_BBS      0x0001 */ /* BBS style prime */
-/*#define TFM_PRIME_SAFE     0x0002 */ /* Safe prime (p-1)/2 == prime */
-/*#define TFM_PRIME_2MSB_OFF 0x0004 */ /* force 2nd MSB to 0 */
-/*#define TFM_PRIME_2MSB_ON  0x0008 */ /* force 2nd MSB to 1 */
-
-/* callback for fp_prime_random, should fill dst with random bytes and return how many read [up to len] */
-/*typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);*/
-
-/*#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)*/
-
-/*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/
-
-/* radix conversions */
-int fp_count_bits(fp_int *a);
-int fp_leading_bit(fp_int *a);
-
-int fp_unsigned_bin_size(fp_int *a);
-void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c);
-void fp_to_unsigned_bin(fp_int *a, unsigned char *b);
-int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b);
-
-/*int fp_signed_bin_size(fp_int *a);*/
-/*void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);*/
-/*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/
-
-/*int fp_read_radix(fp_int *a, char *str, int radix);*/
-/*int fp_toradix(fp_int *a, char *str, int radix);*/
-/*int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);*/
-
-
-/* VARIOUS LOW LEVEL STUFFS */
-void s_fp_add(fp_int *a, fp_int *b, fp_int *c);
-void s_fp_sub(fp_int *a, fp_int *b, fp_int *c);
-void fp_reverse(unsigned char *s, int len);
-
-void fp_mul_comba(fp_int *a, fp_int *b, fp_int *c);
-
-void fp_mul_comba_small(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba3(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba4(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba6(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba7(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba8(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba9(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba12(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba17(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba20(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba24(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba28(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba32(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba48(fp_int *a, fp_int *b, fp_int *c);
-void fp_mul_comba64(fp_int *a, fp_int *b, fp_int *c);
-void fp_sqr_comba(fp_int *a, fp_int *b);
-void fp_sqr_comba_small(fp_int *a, fp_int *b);
-void fp_sqr_comba3(fp_int *a, fp_int *b);
-void fp_sqr_comba4(fp_int *a, fp_int *b);
-void fp_sqr_comba6(fp_int *a, fp_int *b);
-void fp_sqr_comba7(fp_int *a, fp_int *b);
-void fp_sqr_comba8(fp_int *a, fp_int *b);
-void fp_sqr_comba9(fp_int *a, fp_int *b);
-void fp_sqr_comba12(fp_int *a, fp_int *b);
-void fp_sqr_comba17(fp_int *a, fp_int *b);
-void fp_sqr_comba20(fp_int *a, fp_int *b);
-void fp_sqr_comba24(fp_int *a, fp_int *b);
-void fp_sqr_comba28(fp_int *a, fp_int *b);
-void fp_sqr_comba32(fp_int *a, fp_int *b);
-void fp_sqr_comba48(fp_int *a, fp_int *b);
-void fp_sqr_comba64(fp_int *a, fp_int *b);
-
-
-/**
- * Used by wolfSSL
- */
-
-/* Types */
-typedef fp_digit mp_digit;
-typedef fp_word  mp_word;
-typedef fp_int mp_int;
-#define MP_INT_DEFINED
-
-/* Constants */
-#define MP_LT   FP_LT   /* less than    */
-#define MP_EQ   FP_EQ   /* equal to     */
-#define MP_GT   FP_GT   /* greater than */
-#define MP_VAL  FP_VAL  /* invalid */
-#define MP_MEM  FP_MEM  /* memory error */
-#define MP_NOT_INF FP_NOT_INF /* point not at infinity */
-#define MP_OKAY FP_OKAY /* ok result    */
-#define MP_NO   FP_NO   /* yes/no result */
-#define MP_YES  FP_YES  /* yes/no result */
-#define MP_ZPOS FP_ZPOS
-#define MP_NEG  FP_NEG
-#define MP_MASK FP_MASK
-
-/* Prototypes */
-#define mp_zero(a)   fp_zero(a)
-#define mp_isone(a)  fp_isone(a)
-#define mp_iseven(a) fp_iseven(a)
-#define mp_isneg(a)  fp_isneg(a)
-
-#define MP_RADIX_BIN  2
-#define MP_RADIX_OCT  8
-#define MP_RADIX_DEC  10
-#define MP_RADIX_HEX  16
-#define MP_RADIX_MAX  64
-
-#define mp_tobinary(M, S)  mp_toradix((M), (S), MP_RADIX_BIN)
-#define mp_tooctal(M, S)   mp_toradix((M), (S), MP_RADIX_OCT)
-#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC)
-#define mp_tohex(M, S)     mp_toradix((M), (S), MP_RADIX_HEX)
-
-MP_API int  mp_init (mp_int * a);
-MP_API void mp_clear (mp_int * a);
-MP_API void mp_free (mp_int * a);
-MP_API void mp_forcezero (mp_int * a);
-MP_API int  mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
-                         mp_int* f);
-
-MP_API int  mp_add (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_sub (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_add_d (mp_int * a, mp_digit b, mp_int * c);
-
-MP_API int  mp_mul (mp_int * a, mp_int * b, mp_int * c);
-MP_API int  mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
-MP_API int  mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
-MP_API int  mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
-MP_API int  mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d);
-MP_API int  mp_mod(mp_int *a, mp_int *b, mp_int *c);
-MP_API int  mp_invmod(mp_int *a, mp_int *b, mp_int *c);
-MP_API int  mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y);
-MP_API int  mp_mul_2d(mp_int *a, int b, mp_int *c);
-MP_API int  mp_2expt(mp_int* a, int b);
-
-MP_API int  mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
-
-MP_API int  mp_cmp(mp_int *a, mp_int *b);
-MP_API int  mp_cmp_d(mp_int *a, mp_digit b);
-
-MP_API int  mp_unsigned_bin_size(mp_int * a);
-MP_API int  mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
-MP_API int  mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b);
-MP_API int  mp_to_unsigned_bin (mp_int * a, unsigned char *b);
-
-MP_API int  mp_sub_d(fp_int *a, fp_digit b, fp_int *c);
-MP_API int  mp_copy(fp_int* a, fp_int* b);
-MP_API int  mp_isodd(mp_int* a);
-MP_API int  mp_iszero(mp_int* a);
-MP_API int  mp_count_bits(mp_int *a);
-MP_API int  mp_leading_bit(mp_int *a);
-MP_API int  mp_set_int(mp_int *a, unsigned long b);
-MP_API int  mp_is_bit_set (mp_int * a, mp_digit b);
-MP_API int  mp_set_bit (mp_int * a, mp_digit b);
-MP_API void mp_rshb(mp_int *a, int x);
-MP_API void mp_rshd(mp_int *a, int x);
-MP_API int mp_toradix (mp_int *a, char *str, int radix);
-MP_API int mp_radix_size (mp_int * a, int radix, int *size);
-
-#ifdef WOLFSSL_DEBUG_MATH
-    MP_API void mp_dump(const char* desc, mp_int* a, byte verbose);
-#else
-    #define mp_dump(desc, a, verbose)
-#endif
-
-#if !defined(NO_DSA) || defined(HAVE_ECC)
-    MP_API int mp_read_radix(mp_int* a, const char* str, int radix);
-#endif
-
-#ifdef HAVE_ECC
-    MP_API int mp_sqr(fp_int *a, fp_int *b);
-    MP_API int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
-    MP_API int mp_montgomery_setup(fp_int *a, fp_digit *rho);
-    MP_API int mp_div_2(fp_int * a, fp_int * b);
-    MP_API int mp_init_copy(fp_int * a, fp_int * b);
-#endif
-
-#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA)
-    MP_API int mp_set(fp_int *a, fp_digit b);
-#endif
-
-#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN)
-    MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c);
-    MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
-#endif
-
-#ifdef WOLFSSL_KEY_GEN
-MP_API int  mp_gcd(fp_int *a, fp_int *b, fp_int *c);
-MP_API int  mp_lcm(fp_int *a, fp_int *b, fp_int *c);
-MP_API int  mp_prime_is_prime(mp_int* a, int t, int* result);
-MP_API int  mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap);
-MP_API int  mp_exch(mp_int *a, mp_int *b);
-#endif /* WOLFSSL_KEY_GEN */
-
-MP_API int  mp_cnt_lsb(fp_int *a);
-MP_API int  mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
-MP_API int  mp_mod_d(fp_int* a, fp_digit b, fp_digit* c);
-MP_API int  mp_lshd (mp_int * a, int b);
-MP_API int  mp_abs(mp_int* a, mp_int* b);
-
-WOLFSSL_API word32 CheckRunTimeFastMath(void);
-
-/* If user uses RSA, DH, DSA, or ECC math lib directly then fast math FP_SIZE
-   must match, return 1 if a match otherwise 0 */
-#define CheckFastMathSettings() (FP_SIZE == CheckRunTimeFastMath())
-
-
-/* wolf big int and common functions */
-#include <wolfssl/wolfcrypt/wolfmath.h>
-
-
-#ifdef __cplusplus
-   }
-#endif
-
-#endif  /* WOLF_CRYPT_TFM_H */
-
-
--- a/wolfssl/wolfcrypt/types.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,721 +0,0 @@
-/* types.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/types.h
-*/
-
-#ifndef WOLF_CRYPT_TYPES_H
-#define WOLF_CRYPT_TYPES_H
-
-	#include <wolfssl/wolfcrypt/settings.h>
-	#include <wolfssl/wolfcrypt/wc_port.h>
-
-	#ifdef __cplusplus
-	    extern "C" {
-	#endif
-
-
-	#if defined(WORDS_BIGENDIAN)
-	    #define BIG_ENDIAN_ORDER
-	#endif
-
-	#ifndef BIG_ENDIAN_ORDER
-	    #define LITTLE_ENDIAN_ORDER
-	#endif
-
-	#ifndef WOLFSSL_TYPES
-	    #ifndef byte
-	        typedef unsigned char  byte;
-	    #endif
-	    typedef unsigned short word16;
-	    typedef unsigned int   word32;
-	    typedef byte           word24[3];
-	#endif
-
-
-	/* try to set SIZEOF_LONG or LONG_LONG if user didn't */
-	#if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) && !defined(__EMSCRIPTEN__)
-	    #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG)
-	        #if (defined(__alpha__) || defined(__ia64__) || \
-	            defined(_ARCH_PPC64) || defined(__mips64) || \
-	            defined(__x86_64__) || \
-	            ((defined(sun) || defined(__sun)) && \
-	             (defined(LP64) || defined(_LP64))))
-	            /* long should be 64bit */
-	            #define SIZEOF_LONG 8
-	        #elif defined(__i386__) || defined(__CORTEX_M3__)
-	            /* long long should be 64bit */
-	            #define SIZEOF_LONG_LONG 8
-	        #endif
- 	    #endif
-	#endif
-
-	#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
-	    #define WORD64_AVAILABLE
-	    #define W64LIT(x) x##ui64
-	    typedef unsigned __int64 word64;
-	#elif defined(__EMSCRIPTEN__)
-	    #define WORD64_AVAILABLE
-	    #define W64LIT(x) x##ull
-	    typedef unsigned long long word64;
-	#elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8
-	    #define WORD64_AVAILABLE
-	    #define W64LIT(x) x##LL
-	    typedef unsigned long word64;
-	#elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8
-	    #define WORD64_AVAILABLE
-	    #define W64LIT(x) x##LL
-	    typedef unsigned long long word64;
-	#elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8
-	    #define WORD64_AVAILABLE
-	    #define W64LIT(x) x##LL
-	    typedef unsigned long long word64;
-	#endif
-
-#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE)
-	/* These platforms have 64-bit CPU registers.  */
-	#if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \
-	     defined(__mips64)  || defined(__x86_64__) || defined(_M_X64)) || \
-         defined(__aarch64__) || defined(__sparc64__)
-	    typedef word64 wolfssl_word;
-        #define WC_64BIT_CPU
-	#elif (defined(sun) || defined(__sun)) && \
-          (defined(LP64) || defined(_LP64))
-        /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits
-         * and int uses 32 bits. When using Solaris Studio sparc and __sparc are
-         * available for 32 bit detection but __sparc64__ could be missed. This
-         * uses LP64 for checking 64 bit CPU arch. */
-	    typedef word64 wolfssl_word;
-        #define WC_64BIT_CPU
-    #else
-	    typedef word32 wolfssl_word;
-	    #ifdef WORD64_AVAILABLE
-	        #define WOLFCRYPT_SLOW_WORD64
-	    #endif
-	#endif
-#else
-        #undef WORD64_AVAILABLE
-        typedef word32 wolfssl_word;
-        #define MP_16BIT  /* for mp_int, mp_word needs to be twice as big as
-                             mp_digit, no 64 bit type so make mp_digit 16 bit */
-#endif
-
-	enum {
-	    WOLFSSL_WORD_SIZE  = sizeof(wolfssl_word),
-	    WOLFSSL_BIT_SIZE   = 8,
-	    WOLFSSL_WORD_BITS  = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE
-	};
-
-	#define WOLFSSL_MAX_16BIT 0xffffU
-
-	/* use inlining if compiler allows */
-	#ifndef WC_INLINE
-	#ifndef NO_INLINE
-	    #ifdef _MSC_VER
-	        #define WC_INLINE __inline
-	    #elif defined(__GNUC__)
-               #ifdef WOLFSSL_VXWORKS
-                   #define WC_INLINE __inline__
-               #else
-                   #define WC_INLINE inline
-               #endif
-	    #elif defined(__IAR_SYSTEMS_ICC__)
-	        #define WC_INLINE inline
-	    #elif defined(THREADX)
-	        #define WC_INLINE _Inline
-	    #else
-	        #define WC_INLINE
-	    #endif
-	#else
-	    #define WC_INLINE
-	#endif
-	#endif
-
-    #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST)
-        #define INLINE WC_INLINE
-    #endif
-
-
-    /* set up rotate style */
-    #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \
-        !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS)
-        #define INTEL_INTRINSICS
-        #define FAST_ROTATE
-    #elif defined(__MWERKS__) && TARGET_CPU_PPC
-        #define PPC_INTRINSICS
-        #define FAST_ROTATE
-    #elif defined(__GNUC__)  && (defined(__i386__) || defined(__x86_64__))
-        /* GCC does peephole optimizations which should result in using rotate
-           instructions  */
-        #define FAST_ROTATE
-    #endif
-
-
-	/* set up thread local storage if available */
-	#ifdef HAVE_THREAD_LS
-	    #if defined(_MSC_VER)
-	        #define THREAD_LS_T __declspec(thread)
-	    /* Thread local storage only in FreeRTOS v8.2.1 and higher */
-	    #elif defined(FREERTOS) || defined(FREERTOS_TCP)
-	        #define THREAD_LS_T
-	    #else
-	        #define THREAD_LS_T __thread
-	    #endif
-	#else
-	    #define THREAD_LS_T
-	#endif
-
-    /* GCC 7 has new switch() fall-through detection */
-    #if defined(__GNUC__)
-        #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1)))
-            #define FALL_THROUGH __attribute__ ((fallthrough));
-        #endif
-    #endif
-    #ifndef FALL_THROUGH
-        #define FALL_THROUGH
-    #endif
-
-	/* Micrium will use Visual Studio for compilation but not the Win32 API */
-	#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \
-		!defined(FREERTOS_TCP) && !defined(EBSNET) && \
-        !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS)
-	    #define USE_WINDOWS_API
-	#endif
-
-
-	/* idea to add global alloc override by Moises Guimaraes  */
-	/* default to libc stuff */
-	/* XREALLOC is used once in normal math lib, not in fast math lib */
-	/* XFREE on some embedded systems doesn't like free(0) so test  */
-	#if defined(HAVE_IO_POOL)
-		WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type);
-		WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type);
-		WOLFSSL_API void XFREE(void *p, void* heap, int type);
-	#elif defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA)
-        #include <wolfssl/wolfcrypt/port/intel/quickassist_mem.h>
-        #undef USE_WOLFSSL_MEMORY
-        #ifdef WOLFSSL_DEBUG_MEMORY
-            #define XMALLOC(s, h, t)     IntelQaMalloc((s), (h), (t), __func__, __LINE__)
-            #define XFREE(p, h, t)       IntelQaFree((p), (h), (t), __func__, __LINE__)
-            #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__)
-        #else
-            #define XMALLOC(s, h, t)     IntelQaMalloc((s), (h), (t))
-            #define XFREE(p, h, t)       IntelQaFree((p), (h), (t))
-            #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t))
-        #endif /* WOLFSSL_DEBUG_MEMORY */
-    #elif defined(XMALLOC_USER)
-	    /* prototypes for user heap override functions */
-	    #include <stddef.h>  /* for size_t */
-	    extern void *XMALLOC(size_t n, void* heap, int type);
-	    extern void *XREALLOC(void *p, size_t n, void* heap, int type);
-	    extern void XFREE(void *p, void* heap, int type);
-    #elif defined(XMALLOC_OVERRIDE)
-        /* override the XMALLOC, XFREE and XREALLOC macros */
-	#elif defined(NO_WOLFSSL_MEMORY)
-	    /* just use plain C stdlib stuff if desired */
-	    #include <stdlib.h>
-	    #define XMALLOC(s, h, t)     ((void)h, (void)t, malloc((s)))
-	    #define XFREE(p, h, t)       {void* xp = (p); if((xp)) free((xp));}
-	    #define XREALLOC(p, n, h, t) realloc((p), (n))
-	#elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \
-	        && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \
-	        && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \
-            && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4)
-	    /* default C runtime, can install different routines at runtime via cbs */
-	    #include <wolfssl/wolfcrypt/memory.h>
-        #ifdef WOLFSSL_STATIC_MEMORY
-            #ifdef WOLFSSL_DEBUG_MEMORY
-				#define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t), __func__, __LINE__)
-				#define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);}
-				#define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__)
-            #else
-	            #define XMALLOC(s, h, t)     wolfSSL_Malloc((s), (h), (t))
-				#define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));}
-				#define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t))
-            #endif /* WOLFSSL_DEBUG_MEMORY */
-        #elif !defined(FREERTOS) && !defined(FREERTOS_TCP)
-            #ifdef WOLFSSL_DEBUG_MEMORY
-				#define XMALLOC(s, h, t)     ((void)h, (void)t, wolfSSL_Malloc((s), __func__, __LINE__))
-				#define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);}
-				#define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__)
-            #else
-	            #define XMALLOC(s, h, t)     ((void)h, (void)t, wolfSSL_Malloc((s)))
-	            #define XFREE(p, h, t)       {void* xp = (p); if((xp)) wolfSSL_Free((xp));}
-	            #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n))
-            #endif /* WOLFSSL_DEBUG_MEMORY */
-        #endif /* WOLFSSL_STATIC_MEMORY */
-	#endif
-
-    /* declare/free variable handling for async */
-    #ifdef WOLFSSL_ASYNC_CRYPT
-        #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \
-            VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT);
-        #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \
-            VAR_TYPE* VAR_NAME = ({ \
-                VAR_TYPE* ptr = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); \
-                if (ptr && INIT_VALUE) { \
-                    XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \
-                } \
-                ptr; \
-            })
-        #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
-            VAR_TYPE* VAR_NAME[VAR_ITEMS]; \
-            int idx##VAR_NAME; \
-            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
-                VAR_NAME[idx##VAR_NAME] = (VAR_TYPE*)XMALLOC(VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); \
-            }
-        #define FREE_VAR(VAR_NAME, HEAP) \
-            XFREE(VAR_NAME, HEAP, DYNAMIC_TYPE_WOLF_BIGINT);
-        #define FREE_ARRAY(VAR_NAME, VAR_ITEMS, HEAP) \
-            for (idx##VAR_NAME=0; idx##VAR_NAME<VAR_ITEMS; idx##VAR_NAME++) { \
-                XFREE(VAR_NAME[idx##VAR_NAME], HEAP, DYNAMIC_TYPE_WOLF_BIGINT); \
-            }
-    #else
-        #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \
-            VAR_TYPE VAR_NAME[VAR_SIZE]
-        #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \
-            VAR_TYPE* VAR_NAME = (VAR_TYPE*)INIT_VALUE
-        #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \
-            VAR_TYPE VAR_NAME[VAR_ITEMS][VAR_SIZE]
-        #define FREE_VAR(VAR_NAME, HEAP) /* nothing to free, its stack */
-        #define FREE_ARRAY(VAR_NAME, VAR_ITEMS, HEAP)  /* nothing to free, its stack */
-    #endif
-
-    #if !defined(USE_WOLF_STRTOK) && \
-            (defined(__MINGW32__) || defined(WOLFSSL_TIRTOS) || defined(WOLF_C99))
-        #define USE_WOLF_STRTOK
-    #endif
-    #if !defined(USE_WOLF_STRSEP) && (defined(WOLF_C99))
-        #define USE_WOLF_STRSEP
-    #endif
-
-	#ifndef STRING_USER
-	    #include <string.h>
-	    #define XMEMCPY(d,s,l)    memcpy((d),(s),(l))
-	    #define XMEMSET(b,c,l)    memset((b),(c),(l))
-	    #define XMEMCMP(s1,s2,n)  memcmp((s1),(s2),(n))
-	    #define XMEMMOVE(d,s,l)   memmove((d),(s),(l))
-
-	    #define XSTRLEN(s1)       strlen((s1))
-	    #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
-	    /* strstr, strncmp, and strncat only used by wolfSSL proper,
-         * not required for wolfCrypt only */
-	    #define XSTRSTR(s1,s2)    strstr((s1),(s2))
-	    #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n))
-	    #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
-	    #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))
-
-        #ifdef USE_WOLF_STRSEP
-            #define XSTRSEP(s1,d) wc_strsep((s1),(d))
-        #else
-            #define XSTRSEP(s1,d) strsep((s1),(d))
-        #endif
-
-        #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS)
-            /* XC32 does not support strncasecmp, so use case sensitive one */
-            #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n))
-        #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM)
-	        #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
-        #else
-            #if defined(HAVE_STRINGS_H) && defined(WOLF_C99) && \
-                !defined(WOLFSSL_SGX)
-                #include <strings.h>
-            #endif
-	        #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
-	    #endif
-
-        /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when
-           debugging is turned on */
-        #ifndef USE_WINDOWS_API
-            #if defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
-               !defined(NO_STDIO_FILESYSTEM)
-                /* case where stdio is not included else where but is needed for
-                 * snprintf */
-                #include <stdio.h>
-            #endif
-            #define XSNPRINTF snprintf
-        #else
-            #define XSNPRINTF _snprintf
-        #endif
-
-        #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN)
-            /* use only Thread Safe version of strtok */
-            #if defined(USE_WOLF_STRTOK)
-                #define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr))
-            #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS)
-                #define XSTRTOK(s1,d,ptr) strtok_s((s1),(d),(ptr))
-            #else
-                #define XSTRTOK(s1,d,ptr) strtok_r((s1),(d),(ptr))
-            #endif
-        #endif
-	#endif
-
-    #ifdef USE_WOLF_STRTOK
-        WOLFSSL_API char* wc_strtok(char *str, const char *delim, char **nextp);
-    #endif
-    #ifdef USE_WOLF_STRSEP
-        WOLFSSL_API char* wc_strsep(char **stringp, const char *delim);
-    #endif
-
-    #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
-        !defined(NO_STDIO_FILESYSTEM)
-        #ifndef XGETENV
-            #include <stdlib.h>
-            #define XGETENV getenv
-        #endif
-    #endif /* OPENSSL_EXTRA */
-
-	#ifndef CTYPE_USER
-	    #include <ctype.h>
-	    #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \
-            defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA)
-	        #define XTOUPPER(c)     toupper((c))
-	        #define XISALPHA(c)     isalpha((c))
-	    #endif
-	    /* needed by wolfSSL_check_domain_name() */
-	    #define XTOLOWER(c)      tolower((c))
-	#endif
-
-
-	/* memory allocation types for user hints */
-	enum {
-        DYNAMIC_TYPE_CA           = 1,
-        DYNAMIC_TYPE_CERT         = 2,
-        DYNAMIC_TYPE_KEY          = 3,
-        DYNAMIC_TYPE_FILE         = 4,
-        DYNAMIC_TYPE_SUBJECT_CN   = 5,
-        DYNAMIC_TYPE_PUBLIC_KEY   = 6,
-        DYNAMIC_TYPE_SIGNER       = 7,
-        DYNAMIC_TYPE_NONE         = 8,
-        DYNAMIC_TYPE_BIGINT       = 9,
-        DYNAMIC_TYPE_RSA          = 10,
-        DYNAMIC_TYPE_METHOD       = 11,
-        DYNAMIC_TYPE_OUT_BUFFER   = 12,
-        DYNAMIC_TYPE_IN_BUFFER    = 13,
-        DYNAMIC_TYPE_INFO         = 14,
-        DYNAMIC_TYPE_DH           = 15,
-        DYNAMIC_TYPE_DOMAIN       = 16,
-        DYNAMIC_TYPE_SSL          = 17,
-        DYNAMIC_TYPE_CTX          = 18,
-        DYNAMIC_TYPE_WRITEV       = 19,
-        DYNAMIC_TYPE_OPENSSL      = 20,
-        DYNAMIC_TYPE_DSA          = 21,
-        DYNAMIC_TYPE_CRL          = 22,
-        DYNAMIC_TYPE_REVOKED      = 23,
-        DYNAMIC_TYPE_CRL_ENTRY    = 24,
-        DYNAMIC_TYPE_CERT_MANAGER = 25,
-        DYNAMIC_TYPE_CRL_MONITOR  = 26,
-        DYNAMIC_TYPE_OCSP_STATUS  = 27,
-        DYNAMIC_TYPE_OCSP_ENTRY   = 28,
-        DYNAMIC_TYPE_ALTNAME      = 29,
-        DYNAMIC_TYPE_SUITES       = 30,
-        DYNAMIC_TYPE_CIPHER       = 31,
-        DYNAMIC_TYPE_RNG          = 32,
-        DYNAMIC_TYPE_ARRAYS       = 33,
-        DYNAMIC_TYPE_DTLS_POOL    = 34,
-        DYNAMIC_TYPE_SOCKADDR     = 35,
-        DYNAMIC_TYPE_LIBZ         = 36,
-        DYNAMIC_TYPE_ECC          = 37,
-        DYNAMIC_TYPE_TMP_BUFFER   = 38,
-        DYNAMIC_TYPE_DTLS_MSG     = 39,
-        DYNAMIC_TYPE_X509         = 40,
-        DYNAMIC_TYPE_TLSX         = 41,
-        DYNAMIC_TYPE_OCSP         = 42,
-        DYNAMIC_TYPE_SIGNATURE    = 43,
-        DYNAMIC_TYPE_HASHES       = 44,
-        DYNAMIC_TYPE_SRP          = 45,
-        DYNAMIC_TYPE_COOKIE_PWD   = 46,
-        DYNAMIC_TYPE_USER_CRYPTO  = 47,
-        DYNAMIC_TYPE_OCSP_REQUEST = 48,
-        DYNAMIC_TYPE_X509_EXT     = 49,
-        DYNAMIC_TYPE_X509_STORE   = 50,
-        DYNAMIC_TYPE_X509_CTX     = 51,
-        DYNAMIC_TYPE_URL          = 52,
-        DYNAMIC_TYPE_DTLS_FRAG    = 53,
-        DYNAMIC_TYPE_DTLS_BUFFER  = 54,
-        DYNAMIC_TYPE_SESSION_TICK = 55,
-        DYNAMIC_TYPE_PKCS         = 56,
-        DYNAMIC_TYPE_MUTEX        = 57,
-        DYNAMIC_TYPE_PKCS7        = 58,
-        DYNAMIC_TYPE_AES_BUFFER   = 59,
-        DYNAMIC_TYPE_WOLF_BIGINT  = 60,
-        DYNAMIC_TYPE_ASN1         = 61,
-        DYNAMIC_TYPE_LOG          = 62,
-        DYNAMIC_TYPE_WRITEDUP     = 63,
-        DYNAMIC_TYPE_PRIVATE_KEY  = 64,
-        DYNAMIC_TYPE_HMAC         = 65,
-        DYNAMIC_TYPE_ASYNC        = 66,
-        DYNAMIC_TYPE_ASYNC_NUMA   = 67,
-        DYNAMIC_TYPE_ASYNC_NUMA64 = 68,
-        DYNAMIC_TYPE_CURVE25519   = 69,
-        DYNAMIC_TYPE_ED25519      = 70,
-        DYNAMIC_TYPE_SECRET       = 71,
-        DYNAMIC_TYPE_DIGEST       = 72,
-        DYNAMIC_TYPE_RSA_BUFFER   = 73,
-        DYNAMIC_TYPE_DCERT        = 74,
-        DYNAMIC_TYPE_STRING       = 75,
-        DYNAMIC_TYPE_PEM          = 76,
-        DYNAMIC_TYPE_DER          = 77,
-        DYNAMIC_TYPE_CERT_EXT     = 78,
-        DYNAMIC_TYPE_ALPN         = 79,
-        DYNAMIC_TYPE_ENCRYPTEDINFO= 80,
-        DYNAMIC_TYPE_DIRCTX       = 81,
-        DYNAMIC_TYPE_HASHCTX      = 82,
-        DYNAMIC_TYPE_SEED         = 83,
-        DYNAMIC_TYPE_SYMETRIC_KEY = 84,
-        DYNAMIC_TYPE_ECC_BUFFER   = 85,
-        DYNAMIC_TYPE_QSH          = 86,
-        DYNAMIC_TYPE_SALT         = 87,
-        DYNAMIC_TYPE_HASH_TMP     = 88,
-        DYNAMIC_TYPE_BLOB         = 89,
-        DYNAMIC_TYPE_NAME_ENTRY   = 90,
-	};
-
-	/* max error buffer string size */
-    #ifndef WOLFSSL_MAX_ERROR_SZ
-	    #define WOLFSSL_MAX_ERROR_SZ 80
-    #endif
-
-	/* stack protection */
-	enum {
-	    MIN_STACK_BUFFER = 8
-	};
-
-
-    /* Algorithm Types */
-    enum wc_AlgoType {
-        WC_ALGO_TYPE_NONE = 0,
-        WC_ALGO_TYPE_HASH = 1,
-        WC_ALGO_TYPE_CIPHER = 2,
-        WC_ALGO_TYPE_PK = 3,
-
-        WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_PK
-    };
-
-    /* hash types */
-    enum wc_HashType {
-        WC_HASH_TYPE_NONE = 0,
-        WC_HASH_TYPE_MD2 = 1,
-        WC_HASH_TYPE_MD4 = 2,
-        WC_HASH_TYPE_MD5 = 3,
-        WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */
-        WC_HASH_TYPE_SHA224 = 5,
-        WC_HASH_TYPE_SHA256 = 6,
-        WC_HASH_TYPE_SHA384 = 7,
-        WC_HASH_TYPE_SHA512 = 8,
-        WC_HASH_TYPE_MD5_SHA = 9,
-        WC_HASH_TYPE_SHA3_224 = 10,
-        WC_HASH_TYPE_SHA3_256 = 11,
-        WC_HASH_TYPE_SHA3_384 = 12,
-        WC_HASH_TYPE_SHA3_512 = 13,
-        WC_HASH_TYPE_BLAKE2B = 14,
-
-        WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2B
-    };
-
-    /* cipher types */
-    enum wc_CipherType {
-        WC_CIPHER_NONE = 0,
-        WC_CIPHER_AES = 1,
-        WC_CIPHER_AES_CBC = 2,
-        WC_CIPHER_AES_GCM = 3,
-        WC_CIPHER_AES_CTR = 4,
-        WC_CIPHER_AES_XTS = 5,
-        WC_CIPHER_AES_CFB = 6,
-        WC_CIPHER_DES3 = 7,
-        WC_CIPHER_DES = 8,
-        WC_CIPHER_CHACHA = 9,
-        WC_CIPHER_HC128 = 10,
-        WC_CIPHER_IDEA = 11,
-
-        WC_CIPHER_MAX = WC_CIPHER_HC128
-    };
-
-    /* PK=public key (asymmetric) based algorithms */
-    enum wc_PkType {
-        WC_PK_TYPE_NONE = 0,
-        WC_PK_TYPE_RSA = 1,
-        WC_PK_TYPE_DH = 2,
-        WC_PK_TYPE_ECDH = 3,
-        WC_PK_TYPE_ECDSA_SIGN = 4,
-        WC_PK_TYPE_ECDSA_VERIFY = 5,
-        WC_PK_TYPE_ED25519 = 6,
-        WC_PK_TYPE_CURVE25519 = 7,
-
-        WC_PK_TYPE_MAX = WC_PK_TYPE_CURVE25519
-    };
-
-
-	/* settings detection for compile vs runtime math incompatibilities */
-	enum {
-	#if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG)
-	    CTC_SETTINGS = 0x0
-	#elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8)
-	    CTC_SETTINGS = 0x1
-	#elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
-	    CTC_SETTINGS = 0x2
-	#elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4)
-	    CTC_SETTINGS = 0x4
-	#elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG)
-	    CTC_SETTINGS = 0x8
-	#elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8)
-	    CTC_SETTINGS = 0x10
-	#elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
-	    CTC_SETTINGS = 0x20
-	#elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4)
-	    CTC_SETTINGS = 0x40
-	#else
-	    #error "bad math long / long long settings"
-	#endif
-	};
-
-
-	WOLFSSL_API word32 CheckRunTimeSettings(void);
-
-	/* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long
-	   types need to match at compile time and run time, CheckCtcSettings will
-	   return 1 if a match otherwise 0 */
-	#define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings())
-
-	/* invalid device id */
-	#define INVALID_DEVID    -2
-
-
-    /* AESNI requires alignment and ARMASM gains some performance from it */
-    #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || defined(USE_INTEL_SPEEDUP)
-        #if !defined(ALIGN16)
-            #if defined(__GNUC__)
-                #define ALIGN16 __attribute__ ( (aligned (16)))
-            #elif defined(_MSC_VER)
-                /* disable align warning, we want alignment ! */
-                #pragma warning(disable: 4324)
-                #define ALIGN16 __declspec (align (16))
-            #else
-                #define ALIGN16
-            #endif
-        #endif /* !ALIGN16 */
-
-        #if !defined (ALIGN32)
-            #if defined (__GNUC__)
-                #define ALIGN32 __attribute__ ( (aligned (32)))
-            #elif defined(_MSC_VER)
-                /* disable align warning, we want alignment ! */
-                #pragma warning(disable: 4324)
-                #define ALIGN32 __declspec (align (32))
-            #else
-                #define ALIGN32
-            #endif
-        #endif
-
-        #if !defined(ALIGN32)
-            #if defined(__GNUC__)
-                #define ALIGN32 __attribute__ ( (aligned (32)))
-            #elif defined(_MSC_VER)
-                /* disable align warning, we want alignment ! */
-                #pragma warning(disable: 4324)
-                #define ALIGN32 __declspec (align (32))
-            #else
-                #define ALIGN32
-            #endif
-        #endif /* !ALIGN32 */
-
-        #if defined(__GNUC__)
-            #define ALIGN128 __attribute__ ( (aligned (128)))
-        #elif defined(_MSC_VER)
-            /* disable align warning, we want alignment ! */
-            #pragma warning(disable: 4324)
-            #define ALIGN128 __declspec (align (128))
-        #else
-            #define ALIGN128
-        #endif
-
-        #if defined(__GNUC__)
-            #define ALIGN256 __attribute__ ( (aligned (256)))
-        #elif defined(_MSC_VER)
-            /* disable align warning, we want alignment ! */
-            #pragma warning(disable: 4324)
-            #define ALIGN256 __declspec (align (256))
-        #else
-            #define ALIGN256
-        #endif
-
-    #else
-        #ifndef ALIGN16
-            #define ALIGN16
-        #endif
-        #ifndef ALIGN32
-            #define ALIGN32
-        #endif
-        #ifndef ALIGN128
-            #define ALIGN128
-        #endif
-        #ifndef ALIGN256
-            #define ALIGN256
-        #endif
-    #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */
-
-
-    #ifndef TRUE
-        #define TRUE  1
-    #endif
-    #ifndef FALSE
-        #define FALSE 0
-    #endif
-
-
-    #ifdef WOLFSSL_RIOT_OS
-        #define EXIT_TEST(ret) exit(ret)
-    #elif defined(HAVE_STACK_SIZE)
-        #define EXIT_TEST(ret) return (void*)((size_t)(ret))
-    #else
-        #define EXIT_TEST(ret) return ret
-    #endif
-
-
-    #if defined(__GNUC__)
-        #define WOLFSSL_PACK __attribute__ ((packed))
-    #else
-        #define WOLFSSL_PACK
-    #endif
-
-    #ifndef __GNUC_PREREQ
-        #if defined(__GNUC__) && defined(__GNUC_MINOR__)
-            #define __GNUC_PREREQ(maj, min) \
-                ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-        #else
-            #define __GNUC_PREREQ(maj, min) (0) /* not GNUC */
-        #endif
-    #endif
-
-    #if defined(__GNUC__)
-        #define WC_NORETURN __attribute__((noreturn))
-    #else
-        #define WC_NORETURN
-    #endif
-
-
-	#ifdef __cplusplus
-	    }   /* extern "C" */
-	#endif
-
-#endif /* WOLF_CRYPT_TYPES_H */
-
--- a/wolfssl/wolfcrypt/visibility.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/* visibility.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-/* Visibility control macros */
-
-#ifndef WOLF_CRYPT_VISIBILITY_H
-#define WOLF_CRYPT_VISIBILITY_H
-
-
-/* for compatibility and so that fips is using same name of macro @wc_fips */
-/* The following visibility wrappers are for old FIPS. New FIPS should use
- * the same as a non-FIPS build. */
-#if defined(HAVE_FIPS) && \
-    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
-    #include <cyassl/ctaocrypt/visibility.h>
-    #define WOLFSSL_API   CYASSL_API
-	#define WOLFSSL_LOCAL CYASSL_LOCAL
-#else
-
-/* WOLFSSL_API is used for the public API symbols.
-        It either imports or exports (or does nothing for static builds)
-
-   WOLFSSL_LOCAL is used for non-API symbols (private).
-*/
-
-#if defined(BUILDING_WOLFSSL)
-    #if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-        #define WOLFSSL_API   __attribute__ ((visibility("default")))
-        #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden")))
-    #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-        #define WOLFSSL_API   __global
-        #define WOLFSSL_LOCAL __hidden
-    #elif defined(_MSC_VER) || defined(__MINGW32__)
-        #if defined(WOLFSSL_DLL)
-            #define WOLFSSL_API __declspec(dllexport)
-        #else
-            #define WOLFSSL_API
-        #endif
-        #define WOLFSSL_LOCAL
-    #else
-        #define WOLFSSL_API
-        #define WOLFSSL_LOCAL
-    #endif /* HAVE_VISIBILITY */
-#else /* BUILDING_WOLFSSL */
-    #if defined(_MSC_VER) || defined(__MINGW32__)
-        #if defined(WOLFSSL_DLL)
-            #define WOLFSSL_API __declspec(dllimport)
-        #else
-            #define WOLFSSL_API
-        #endif
-        #define WOLFSSL_LOCAL
-    #else
-        #define WOLFSSL_API
-        #define WOLFSSL_LOCAL
-    #endif
-#endif /* BUILDING_WOLFSSL */
-
-#endif /* HAVE_FIPS */
-#endif /* WOLF_CRYPT_VISIBILITY_H */
-
-
--- a/wolfssl/wolfcrypt/wc_encrypt.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/* wc_encrypt.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/wc_encrypt.h
-*/
-
-
-#ifndef WOLF_CRYPT_ENCRYPT_H
-#define WOLF_CRYPT_ENCRYPT_H
-
-#include <wolfssl/wolfcrypt/types.h>
-#include <wolfssl/wolfcrypt/aes.h>
-#include <wolfssl/wolfcrypt/chacha.h>
-#include <wolfssl/wolfcrypt/des3.h>
-#include <wolfssl/wolfcrypt/arc4.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* determine max cipher key size */
-#ifndef NO_AES
-    #define WC_MAX_SYM_KEY_SIZE     (AES_MAX_KEY_SIZE/8)
-#elif defined(HAVE_CHACHA)
-    #define WC_MAX_SYM_KEY_SIZE     CHACHA_MAX_KEY_SZ
-#elif !defined(NO_DES3)
-    #define WC_MAX_SYM_KEY_SIZE     DES3_KEY_SIZE
-#elif !defined(NO_RC4)
-    #define WC_MAX_SYM_KEY_SIZE     RC4_KEY_SIZE
-#else
-    #define WC_MAX_SYM_KEY_SIZE     32
-#endif
-
-
-#ifndef NO_AES
-WOLFSSL_API int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz,
-                                        const byte* key, word32 keySz,
-                                        const byte* iv);
-WOLFSSL_API int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz,
-                                        const byte* key, word32 keySz,
-                                        const byte* iv);
-#endif /* !NO_AES */
-
-
-#ifndef NO_DES3
-WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out,
-                                         const byte* in, word32 sz,
-                                         const byte* key, const byte* iv);
-WOLFSSL_API int wc_Des_CbcEncryptWithKey(byte* out,
-                                         const byte* in, word32 sz,
-                                         const byte* key, const byte* iv);
-WOLFSSL_API int wc_Des3_CbcEncryptWithKey(byte* out,
-                                          const byte* in, word32 sz,
-                                          const byte* key, const byte* iv);
-WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out,
-                                          const byte* in, word32 sz,
-                                          const byte* key, const byte* iv);
-#endif /* !NO_DES3 */
-
-
-
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
-    struct EncryptedInfo;
-    WOLFSSL_API int wc_BufferKeyDecrypt(struct EncryptedInfo* info, byte* der, word32 derSz,
-        const byte* password, int passwordSz, int hashType);
-    WOLFSSL_API int wc_BufferKeyEncrypt(struct EncryptedInfo* info, byte* der, word32 derSz,
-        const byte* password, int passwordSz, int hashType);
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-#ifndef NO_PWDBASED
-    WOLFSSL_LOCAL int wc_CryptKey(const char* password, int passwordSz, 
-        byte* salt, int saltSz, int iterations, int id, byte* input, int length,
-        int version, byte* cbcIv, int enc);
-#endif
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_ENCRYPT_H */
-
-
--- a/wolfssl/wolfcrypt/wc_port.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,538 +0,0 @@
-/* wc_port.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-/*!
-    \file wolfssl/wolfcrypt/wc_port.h
-*/
-
-#ifndef WOLF_CRYPT_PORT_H
-#define WOLF_CRYPT_PORT_H
-
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/wolfcrypt/visibility.h>
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-/* Detect if compiler supports C99. "NO_WOLF_C99" can be defined in
- * user_settings.h to disable checking for C99 support. */
-#if !defined(WOLF_C99) && defined(__STDC_VERSION__) && \
-    !defined(WOLFSSL_ARDUINO) && !defined(NO_WOLF_C99)
-    #if __STDC_VERSION__ >= 199901L
-        #define WOLF_C99
-    #endif
-#endif
-
-#ifdef USE_WINDOWS_API
-    #ifdef WOLFSSL_GAME_BUILD
-        #include "system/xtl.h"
-    #else
-        #ifndef WIN32_LEAN_AND_MEAN
-            #define WIN32_LEAN_AND_MEAN
-        #endif
-        #ifndef WOLFSSL_SGX
-            #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN)
-                /* On WinCE winsock2.h must be included before windows.h */
-                #include <winsock2.h>
-            #endif
-            #include <windows.h>
-        #endif /* WOLFSSL_SGX */
-    #endif
-#elif defined(THREADX)
-    #ifndef SINGLE_THREADED
-        #ifdef NEED_THREADX_TYPES
-            #include <types.h>
-        #endif
-        #include <tx_api.h>
-    #endif
-#elif defined(MICRIUM)
-    /* do nothing, just don't pick Unix */
-#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS)
-    /* do nothing */
-#elif defined(EBSNET)
-    /* do nothing */
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    /* do nothing */
-#elif defined(FREESCALE_FREE_RTOS)
-    #include "fsl_os_abstraction.h"
-#elif defined(WOLFSSL_uITRON4)
-    #include "stddef.h"
-    #include "kernel.h"
-#elif  defined(WOLFSSL_uTKERNEL2)
-    #include "tk/tkernel.h"
-#elif defined(WOLFSSL_CMSIS_RTOS)
-    #include "cmsis_os.h"
-#elif defined(WOLFSSL_MDK_ARM)
-    #if defined(WOLFSSL_MDK5)
-        #include "cmsis_os.h"
-    #else
-        #include <rtl.h>
-    #endif
-#elif defined(WOLFSSL_CMSIS_RTOS)
-    #include "cmsis_os.h"
-#elif defined(WOLFSSL_TIRTOS)
-    #include <ti/sysbios/BIOS.h>
-    #include <ti/sysbios/knl/Semaphore.h>
-#elif defined(WOLFSSL_FROSTED)
-    #include <semaphore.h>
-#elif defined(INTIME_RTOS)
-    #include <rt.h>
-    #include <io.h>
-#elif defined(WOLFSSL_NUCLEUS_1_2)
-    /* NU_DEBUG needed struct access in nucleus_realloc */
-    #define NU_DEBUG
-    #include "plus/nucleus.h"
-    #include "nucleus.h"
-#else
-    #ifndef SINGLE_THREADED
-        #define WOLFSSL_PTHREADS
-        #include <pthread.h>
-    #endif
-    #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
-        #include <unistd.h>      /* for close of BIO */
-    #endif
-#endif
-
-/* For FIPS keep the function names the same */
-#ifdef HAVE_FIPS
-#define wc_InitMutex   InitMutex
-#define wc_FreeMutex   FreeMutex
-#define wc_LockMutex   LockMutex
-#define wc_UnLockMutex UnLockMutex
-#endif /* HAVE_FIPS */
-
-#ifdef SINGLE_THREADED
-    typedef int wolfSSL_Mutex;
-#else /* MULTI_THREADED */
-    /* FREERTOS comes first to enable use of FreeRTOS Windows simulator only */
-    #if defined(FREERTOS)
-        typedef xSemaphoreHandle wolfSSL_Mutex;
-    #elif defined(FREERTOS_TCP)
-        #include "FreeRTOS.h"
-        #include "semphr.h"
-		typedef SemaphoreHandle_t  wolfSSL_Mutex;
-    #elif defined(WOLFSSL_SAFERTOS)
-        typedef struct wolfSSL_Mutex {
-            signed char mutexBuffer[portQUEUE_OVERHEAD_BYTES];
-            xSemaphoreHandle mutex;
-        } wolfSSL_Mutex;
-    #elif defined(USE_WINDOWS_API)
-        typedef CRITICAL_SECTION wolfSSL_Mutex;
-    #elif defined(WOLFSSL_PTHREADS)
-        typedef pthread_mutex_t wolfSSL_Mutex;
-    #elif defined(THREADX)
-        typedef TX_MUTEX wolfSSL_Mutex;
-    #elif defined(MICRIUM)
-        typedef OS_MUTEX wolfSSL_Mutex;
-    #elif defined(EBSNET)
-        typedef RTP_MUTEX wolfSSL_Mutex;
-    #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-        typedef MUTEX_STRUCT wolfSSL_Mutex;
-    #elif defined(FREESCALE_FREE_RTOS)
-        typedef mutex_t wolfSSL_Mutex;
-    #elif defined(WOLFSSL_uITRON4)
-        typedef struct wolfSSL_Mutex {
-            T_CSEM sem ;
-            ID     id ;
-        } wolfSSL_Mutex;
-    #elif defined(WOLFSSL_uTKERNEL2)
-        typedef struct wolfSSL_Mutex {
-            T_CSEM sem ;
-            ID     id ;
-        } wolfSSL_Mutex;
-    #elif defined(WOLFSSL_MDK_ARM)
-        #if defined(WOLFSSL_CMSIS_RTOS)
-            typedef osMutexId wolfSSL_Mutex;
-        #else
-            typedef OS_MUT wolfSSL_Mutex;
-        #endif
-    #elif defined(WOLFSSL_CMSIS_RTOS)
-        typedef osMutexId wolfSSL_Mutex;
-    #elif defined(WOLFSSL_TIRTOS)
-        typedef ti_sysbios_knl_Semaphore_Handle wolfSSL_Mutex;
-    #elif defined(WOLFSSL_FROSTED)
-        typedef mutex_t * wolfSSL_Mutex;
-    #elif defined(INTIME_RTOS)
-        typedef RTHANDLE wolfSSL_Mutex;
-    #elif defined(WOLFSSL_NUCLEUS_1_2)
-        typedef NU_SEMAPHORE wolfSSL_Mutex;
-    #else
-        #error Need a mutex type in multithreaded mode
-    #endif /* USE_WINDOWS_API */
-#endif /* SINGLE_THREADED */
-
-/* Enable crypt HW mutex for Freescale MMCAU or PIC32MZ */
-#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ)
-    #ifndef WOLFSSL_CRYPT_HW_MUTEX
-        #define WOLFSSL_CRYPT_HW_MUTEX  1
-    #endif
-#endif /* FREESCALE_MMCAU */
-
-#ifndef WOLFSSL_CRYPT_HW_MUTEX
-    #define WOLFSSL_CRYPT_HW_MUTEX  0
-#endif
-
-#if WOLFSSL_CRYPT_HW_MUTEX
-    /* wolfSSL_CryptHwMutexInit is called on first wolfSSL_CryptHwMutexLock,
-       however it's recommended to call this directly on Hw init to avoid possible
-       race condition where two calls to wolfSSL_CryptHwMutexLock are made at
-       the same time. */
-    int wolfSSL_CryptHwMutexInit(void);
-    int wolfSSL_CryptHwMutexLock(void);
-    int wolfSSL_CryptHwMutexUnLock(void);
-#else
-    /* Define stubs, since HW mutex is disabled */
-    #define wolfSSL_CryptHwMutexInit()      0 /* Success */
-    #define wolfSSL_CryptHwMutexLock()      0 /* Success */
-    #define wolfSSL_CryptHwMutexUnLock()    (void)0 /* Success */
-#endif /* WOLFSSL_CRYPT_HW_MUTEX */
-
-/* Mutex functions */
-WOLFSSL_API int wc_InitMutex(wolfSSL_Mutex*);
-WOLFSSL_API wolfSSL_Mutex* wc_InitAndAllocMutex(void);
-WOLFSSL_API int wc_FreeMutex(wolfSSL_Mutex*);
-WOLFSSL_API int wc_LockMutex(wolfSSL_Mutex*);
-WOLFSSL_API int wc_UnLockMutex(wolfSSL_Mutex*);
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-/* dynamiclly set which mutex to use. unlock / lock is controlled by flag */
-typedef void (mutex_cb)(int flag, int type, const char* file, int line);
-
-WOLFSSL_API int wc_LockMutex_ex(int flag, int type, const char* file, int line);
-WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb);
-#endif
-
-/* main crypto initialization function */
-WOLFSSL_API int wolfCrypt_Init(void);
-WOLFSSL_API int wolfCrypt_Cleanup(void);
-
-/* filesystem abstraction layer, used by ssl.c */
-#ifndef NO_FILESYSTEM
-
-#if defined(EBSNET)
-    #include "vfapi.h"
-    #include "vfile.h"
-
-    #define XFILE                    int
-    #define XFOPEN(NAME, MODE)       vf_open((const char *)NAME, VO_RDONLY, 0);
-    #define XFSEEK                   vf_lseek
-    #define XFTELL                   vf_tell
-    #define XREWIND                  vf_rewind
-    #define XFREAD(BUF, SZ, AMT, FD) vf_read(FD, BUF, SZ*AMT)
-    #define XFWRITE(BUF, SZ, AMT, FD) vf_write(FD, BUF, SZ*AMT)
-    #define XFCLOSE                  vf_close
-    #define XSEEK_END                VSEEK_END
-    #define XBADFILE                 -1
-    #define XFGETS(b,s,f)            -2 /* Not ported yet */
-#elif defined(LSR_FS)
-    #include <fs.h>
-    #define XFILE                   struct fs_file*
-    #define XFOPEN(NAME, MODE)      fs_open((char*)NAME);
-    #define XFSEEK(F, O, W)         (void)F
-    #define XFTELL(F)               (F)->len
-    #define XREWIND(F)              (void)F
-    #define XFREAD(BUF, SZ, AMT, F) fs_read(F, (char*)BUF, SZ*AMT)
-    #define XFWRITE(BUF, SZ, AMT, F) fs_write(F, (char*)BUF, SZ*AMT)
-    #define XFCLOSE                 fs_close
-    #define XSEEK_END               0
-    #define XBADFILE                NULL
-    #define XFGETS(b,s,f)            -2 /* Not ported yet */
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    #define XFILE                   MQX_FILE_PTR
-    #define XFOPEN                  fopen
-    #define XFSEEK                  fseek
-    #define XFTELL                  ftell
-    #define XREWIND(F)              fseek(F, 0, IO_SEEK_SET)
-    #define XFREAD                  fread
-    #define XFWRITE                 fwrite
-    #define XFCLOSE                 fclose
-    #define XSEEK_END               IO_SEEK_END
-    #define XBADFILE                NULL
-    #define XFGETS                  fgets
-#elif defined(MICRIUM)
-    #include <fs_api.h>
-    #define XFILE      FS_FILE*
-    #define XFOPEN     fs_fopen
-    #define XFSEEK     fs_fseek
-    #define XFTELL     fs_ftell
-    #define XREWIND    fs_rewind
-    #define XFREAD     fs_fread
-    #define XFWRITE    fs_fwrite
-    #define XFCLOSE    fs_fclose
-    #define XSEEK_END  FS_SEEK_END
-    #define XBADFILE   NULL
-    #define XFGETS(b,s,f) -2 /* Not ported yet */
-#elif defined(WOLFSSL_NUCLEUS_1_2)
-    #include "fal/inc/fal.h"
-    #define XFILE      FILE*
-    #define XFOPEN     fopen
-    #define XFSEEK     fseek
-    #define XFTELL     ftell
-    #define XREWIND    rewind
-    #define XFREAD     fread
-    #define XFWRITE    fwrite
-    #define XFCLOSE    fclose
-    #define XSEEK_END  PSEEK_END
-    #define XBADFILE   NULL
-#else
-    /* stdio, default case */
-    #include <stdio.h>
-    #define XFILE      FILE*
-    #if defined(WOLFSSL_MDK_ARM)
-        extern FILE * wolfSSL_fopen(const char *name, const char *mode) ;
-        #define XFOPEN     wolfSSL_fopen
-    #else
-        #define XFOPEN     fopen
-    #endif
-    #define XFSEEK     fseek
-    #define XFTELL     ftell
-    #define XREWIND    rewind
-    #define XFREAD     fread
-    #define XFWRITE    fwrite
-    #define XFCLOSE    fclose
-    #define XSEEK_END  SEEK_END
-    #define XBADFILE   NULL
-    #define XFGETS     fgets
-
-    #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\
-        && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
-        #include <dirent.h>
-        #include <unistd.h>
-        #include <sys/stat.h>
-    #endif
-#endif
-
-    #ifndef MAX_FILENAME_SZ
-        #define MAX_FILENAME_SZ  256 /* max file name length */
-    #endif
-    #ifndef MAX_PATH
-        #define MAX_PATH 256
-    #endif
-
-#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS) && \
-    !defined(WOLFSSL_NUCLEUS_1_2)
-    typedef struct ReadDirCtx {
-    #ifdef USE_WINDOWS_API
-        WIN32_FIND_DATAA FindFileData;
-        HANDLE hFind;
-    #else
-        struct dirent* entry;
-        DIR*   dir;
-        struct stat s;
-    #endif
-        char name[MAX_FILENAME_SZ];
-    } ReadDirCtx;
-
-    WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name);
-    WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name);
-    WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx);
-#endif /* !NO_WOLFSSL_DIR */
-
-#endif /* !NO_FILESYSTEM */
-
-/* Windows API defines its own min() macro. */
-#if defined(USE_WINDOWS_API)
-    #if defined(min) || defined(WOLFSSL_MYSQL_COMPATIBLE)
-        #define WOLFSSL_HAVE_MIN
-    #endif /* min */
-    #if defined(max) || defined(WOLFSSL_MYSQL_COMPATIBLE)
-        #define WOLFSSL_HAVE_MAX
-    #endif /* max */
-#endif /* USE_WINDOWS_API */
-
-/* Time functions */
-#ifndef NO_ASN_TIME
-#if defined(USER_TIME)
-    /* Use our gmtime and time_t/struct tm types.
-       Only needs seconds since EPOCH using XTIME function.
-       time_t XTIME(time_t * timer) {}
-    */
-    #define WOLFSSL_GMTIME
-    #define USE_WOLF_TM
-    #define USE_WOLF_TIME_T
-
-#elif defined(TIME_OVERRIDES)
-    /* Override XTIME() and XGMTIME() functionality.
-       Requires user to provide these functions:
-        time_t XTIME(time_t * timer) {}
-        struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {}
-    */
-    #ifndef HAVE_TIME_T_TYPE
-        #define USE_WOLF_TIME_T
-    #endif
-    #ifndef HAVE_TM_TYPE
-        #define USE_WOLF_TM
-    #endif
-    #define NEED_TMP_TIME
-
-#elif defined(HAVE_RTP_SYS)
-    #include "os.h"           /* dc_rtc_api needs    */
-    #include "dc_rtc_api.h"   /* to get current time */
-
-    /* uses parital <time.h> structures */
-    #define XTIME(tl)       (0)
-    #define XGMTIME(c, t)   rtpsys_gmtime((c))
-
-#elif defined(MICRIUM)
-    #include <clk.h>
-    #include <time.h>
-    #define XTIME(t1)       micrium_time((t1))
-    #define WOLFSSL_GMTIME
-
-#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
-    #include <time.h>
-    #define XTIME(t1)       pic32_time((t1))
-    #define XGMTIME(c, t)   gmtime((c))
-
-#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
-    #ifdef FREESCALE_MQX_4_0
-        #include <time.h>
-        extern time_t mqx_time(time_t* timer);
-    #else
-        #define HAVE_GMTIME_R
-    #endif
-    #define XTIME(t1)       mqx_time((t1))
-
-#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS)
-    #include <time.h>
-    #ifndef XTIME
-        /*extern time_t ksdk_time(time_t* timer);*/
-        #define XTIME(t1)   ksdk_time((t1))
-    #endif
-    #define XGMTIME(c, t)   gmtime((c))
-
-#elif defined(WOLFSSL_ATMEL)
-    #define XTIME(t1)       atmel_get_curr_time_and_date((t1))
-    #define WOLFSSL_GMTIME
-    #define USE_WOLF_TM
-    #define USE_WOLF_TIME_T
-
-#elif defined(IDIRECT_DEV_TIME)
-    /*Gets the timestamp from cloak software owned by VT iDirect
-    in place of time() from <time.h> */
-    #include <time.h>
-    #define XTIME(t1)       idirect_time((t1))
-    #define XGMTIME(c, t)   gmtime((c))
-
-#elif defined(_WIN32_WCE)
-    #include <windows.h>
-    #define XTIME(t1)       windows_time((t1))
-    #define WOLFSSL_GMTIME
-
-#else
-    /* default */
-    /* uses complete <time.h> facility */
-    #include <time.h>
-    #if defined(HAVE_SYS_TIME_H)
-        #include <sys/time.h>
-    #endif
-
-    /* PowerPC time_t is int */
-    #ifdef __PPC__
-        #define TIME_T_NOT_LONG
-    #endif
-#endif
-
-
-/* Map default time functions */
-#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME)
-    #define XTIME(tl)       time((tl))
-#endif
-#if !defined(XGMTIME) && !defined(TIME_OVERRIDES)
-    #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99)
-        #define XGMTIME(c, t)   gmtime((c))
-    #else
-        #define XGMTIME(c, t)   gmtime_r((c), (t))
-        #define NEED_TMP_TIME
-    #endif
-#endif
-#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE)
-    #define USE_WOLF_VALIDDATE
-    #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#endif
-
-/* wolf struct tm and time_t */
-#if defined(USE_WOLF_TM)
-    struct tm {
-        int  tm_sec;     /* seconds after the minute [0-60] */
-        int  tm_min;     /* minutes after the hour [0-59] */
-        int  tm_hour;    /* hours since midnight [0-23] */
-        int  tm_mday;    /* day of the month [1-31] */
-        int  tm_mon;     /* months since January [0-11] */
-        int  tm_year;    /* years since 1900 */
-        int  tm_wday;    /* days since Sunday [0-6] */
-        int  tm_yday;    /* days since January 1 [0-365] */
-        int  tm_isdst;   /* Daylight Savings Time flag */
-        long tm_gmtoff;  /* offset from CUT in seconds */
-        char *tm_zone;   /* timezone abbreviation */
-    };
-#endif /* USE_WOLF_TM */
-#if defined(USE_WOLF_TIME_T)
-    typedef long time_t;
-#endif
-#if defined(USE_WOLF_SUSECONDS_T)
-    typedef long suseconds_t;
-#endif
-#if defined(USE_WOLF_TIMEVAL_T)
-    struct timeval
-    {
-        time_t tv_sec;
-        suseconds_t tv_usec;
-    };
-#endif
-
-    /* forward declarations */
-#if defined(USER_TIME)
-    struct tm* gmtime(const time_t* timer);
-    extern time_t XTIME(time_t * timer);
-
-    #ifdef STACK_TRAP
-        /* for stack trap tracking, don't call os gmtime on OS X/linux,
-           uses a lot of stack spce */
-        extern time_t time(time_t * timer);
-        #define XTIME(tl)  time((tl))
-    #endif /* STACK_TRAP */
-
-#elif defined(TIME_OVERRIDES)
-    extern time_t XTIME(time_t * timer);
-    extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp);
-#elif defined(WOLFSSL_GMTIME)
-    struct tm* gmtime(const time_t* timer);
-#endif
-#endif /* NO_ASN_TIME */
-
-#ifndef WOLFSSL_LEANPSK
-    char* mystrnstr(const char* s1, const char* s2, unsigned int n);
-#endif
-
-#ifndef FILE_BUFFER_SIZE
-    #define FILE_BUFFER_SIZE 1024     /* default static file buffer size for input,
-                                    will use dynamic buffer if not big enough */
-#endif
-
-
-#ifdef __cplusplus
-    }  /* extern "C" */
-#endif
-
-#endif /* WOLF_CRYPT_PORT_H */
-
-
--- a/wolfssl/wolfcrypt/wolfevent.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/* wolfevent.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-#ifndef _WOLF_EVENT_H_
-#define _WOLF_EVENT_H_
-
-#ifdef __cplusplus
-    extern "C" {
-#endif
-
-#ifndef SINGLE_THREADED
-    #include <wolfssl/wolfcrypt/wc_port.h>
-#endif
-
-typedef struct WOLF_EVENT WOLF_EVENT;
-typedef unsigned short WOLF_EVENT_FLAG;
-
-typedef enum WOLF_EVENT_TYPE {
-    WOLF_EVENT_TYPE_NONE,
-#ifdef WOLFSSL_ASYNC_CRYPT
-    WOLF_EVENT_TYPE_ASYNC_WOLFSSL,    /* context is WOLFSSL* */
-    WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT,  /* context is WC_ASYNC_DEV */
-    WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
-    WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT,
-#endif /* WOLFSSL_ASYNC_CRYPT */
-} WOLF_EVENT_TYPE;
-
-typedef enum WOLF_EVENT_STATE {
-    WOLF_EVENT_STATE_READY,
-    WOLF_EVENT_STATE_PENDING,
-    WOLF_EVENT_STATE_DONE,
-} WOLF_EVENT_STATE;
-
-struct WOLF_EVENT {
-    /* double linked list */
-    WOLF_EVENT*         next;
-    WOLF_EVENT*         prev;
-
-    void*               context;
-    union {
-        void* ptr;
-#ifdef WOLFSSL_ASYNC_CRYPT
-        struct WC_ASYNC_DEV* async;
-#endif
-    } dev;
-#ifdef HAVE_CAVIUM
-    word64              reqId;
-    #ifdef WOLFSSL_NITROX_DEBUG
-    word32              pendCount;
-    #endif
-#endif
-#ifndef WC_NO_ASYNC_THREADING
-    pthread_t           threadId;
-#endif
-    int                 ret;    /* Async return code */
-    unsigned int        flags;
-    WOLF_EVENT_TYPE     type;
-    WOLF_EVENT_STATE    state;
-};
-
-enum WOLF_POLL_FLAGS {
-    WOLF_POLL_FLAG_CHECK_HW = 0x01,
-};
-
-typedef struct {
-    WOLF_EVENT*         head;     /* head of queue */
-    WOLF_EVENT*         tail;     /* tail of queue */
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex       lock;     /* queue lock */
-#endif
-    int                 count;
-} WOLF_EVENT_QUEUE;
-
-
-#ifdef HAVE_WOLF_EVENT
-
-/* Event */
-WOLFSSL_API int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context);
-WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags);
-
-/* Event Queue */
-WOLFSSL_API int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue);
-WOLFSSL_API int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event);
-WOLFSSL_API int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event);
-WOLFSSL_API int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter,
-    WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount);
-WOLFSSL_API int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue);
-WOLFSSL_API void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue);
-
-/* the queue mutex must be locked prior to calling these */
-WOLFSSL_API int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event);
-WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event);
-
-
-#endif /* HAVE_WOLF_EVENT */
-
-
-#ifdef __cplusplus
-    }   /* extern "C" */
-#endif
-
-#endif /* _WOLF_EVENT_H_ */
-
--- a/wolfssl/wolfcrypt/wolfmath.h	Tue Nov 19 14:32:16 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* wolfmath.h
- *
- * Copyright (C) 2006-2017 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-#if defined(HAVE_WOLF_BIGINT) && !defined(WOLF_BIGINT_DEFINED)
-    /* raw big integer */
-    typedef struct WC_BIGINT {
-        byte*   buf;
-        word32  len;
-        void*   heap;
-    } WC_BIGINT;
-
-    #define WOLF_BIGINT_DEFINED
-#endif
-
-
-/* only define functions if mp_int has been declared */
-#ifdef MP_INT_DEFINED
-
-#ifndef __WOLFMATH_H__
-#define __WOLFMATH_H__
-
-    /* timing resistance array */
-    #if !defined(WC_NO_CACHE_RESISTANT) && \
-        ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \
-         (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT)))
-
-        extern const wolfssl_word wc_off_on_addr[2];
-    #endif
-
-    /* common math functions */
-    int get_digit_count(mp_int* a);
-    mp_digit get_digit(mp_int* a, int n);
-    int get_rand_digit(WC_RNG* rng, mp_digit* d);
-    int mp_rand(mp_int* a, int digits, WC_RNG* rng);
-
-
-    #ifdef HAVE_WOLF_BIGINT
-        void wc_bigint_init(WC_BIGINT* a);
-        int wc_bigint_alloc(WC_BIGINT* a, word32 sz);
-        int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen);
-        int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen);
-        void wc_bigint_zero(WC_BIGINT* a);
-        void wc_bigint_free(WC_BIGINT* a);
-
-        int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst);
-        int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz);
-        int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst);
-    #endif /* HAVE_WOLF_BIGINT */
-
-#endif /* __WOLFMATH_H__ */
-
-#endif /* MP_INT_DEFINED */
-